From 2c5b8ec6d95cf68650265941530e5ce38c8dd6d9 Mon Sep 17 00:00:00 2001 From: Chris Larson Date: Thu, 9 Dec 2004 09:47:41 +0000 Subject: Merge oe-devel@oe-devel.bkbits.net:openembedded into hyperion.kergoth.com:/home/kergoth/code/openembedded 2004/12/09 03:39:39-06:00 kergoth.com!kergoth Break people's builds again.. this time moving the packages into a packages/ subdir to clean things up a bit. BKrev: 41b81f3dvlp3rU7_8MUXLcI8LDdDoA --- ...kernel-24-8_2.4.18-rmk7-pxa3-embedix20030509.bb | 10 - ...kernel-32-0_2.4.18-rmk7-pxa3-embedix20030509.bb | 10 - ...ernel-32-32_2.4.18-rmk7-pxa3-embedix20030509.bb | 10 - ...ernel-40-24_2.4.18-rmk7-pxa3-embedix20030509.bb | 10 - ...ernel-48-16_2.4.18-rmk7-pxa3-embedix20030509.bb | 10 - ...kernel-58-6_2.4.18-rmk7-pxa3-embedix20030509.bb | 10 - ...kernel-64-0_2.4.18-rmk7-pxa3-embedix20030509.bb | 10 - ...-kernel-all_2.4.18-rmk7-pxa3-embedix20030509.bb | 0 linux/files/ipaq-hal.init | 14 - linux/files/linux-2.4-cpufreq.patch | 20 - linux/files/linux-2.4-no-short-loads.patch | 18 - linux/files/linux-2.4.18-list_move.patch | 32 - linux/files/mipv6-1.1-v2.4.25.patch | 19832 ----- linux/gumstix-2.6.5-gnalm1-gum0/defconfig | 777 - .../linux-2.6.5-gnalm1.patch | 20991 ----- linux/gumstix_2.6.5-gnalm1-gum0.bb | 0 .../defconfig-ipaqpxa | 1575 - .../ipsec.patch | 1446 - .../defconfig-ipaqpxa | 1577 - .../defconfig-ipaqpxa | 1578 - .../defconfig-ipaqpxa | 1578 - .../defconfig-ipaqpxa | 0 .../mmc_h5400.patch | 0 linux/handhelds-pxa-2.6/defconfig | 1328 - linux/handhelds-pxa-2.6/defconfig-ipaq-pxa-2.6 | 1304 - .../defconfig-ipaq-pxa-2.6_2.6.8.1-hh0 | 1382 - linux/handhelds-pxa-2.6_2.6.6-hh0.bb | 0 linux/handhelds-pxa-2.6_2.6.8.1-hh0.bb | 0 linux/handhelds-pxa-2.6_cvs.bb | 0 linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh36.12.bb | 0 linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh36.13.bb | 0 linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh36.14.bb | 0 linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh37.1.bb | 0 linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh37.4.bb | 0 .../defconfig-ipaqsa | 1505 - .../disable-pcmcia-probe.patch | 17 - .../ipsec.patch | 1446 - .../mkdep.patch | 16 - .../defconfig-ipaqsa | 1508 - .../defconfig-ipaqsa | 0 linux/handhelds-sa-2.6/defconfig-jornada56x | 877 - linux/handhelds-sa-2.6_cvs.bb | 0 linux/handhelds-sa_2.4.19-rmk6-pxa1-hh36.12.bb | 0 linux/handhelds-sa_2.4.19-rmk6-pxa1-hh37.1.bb | 0 linux/handhelds-sa_2.4.19-rmk6-pxa1-hh37.4.bb | 0 linux/ipod_2.4.24-ipod0.bb | 0 linux/linux-bast-2.4.25-vrs1-bast1/defconfig | 1115 - linux/linux-bast-2.4.25-vrs1-bast1/mkdep.patch | 16 - linux/linux-bast_2.4.25-vrs1-bast1.bb | 0 linux/linux-colinux-2.4.28/colinux-0.6.1.patch | 0 linux/linux-colinux-2.4.28/defconfig | 0 .../gcc-registerparanoia.patch | 0 .../gcc340-fixes-v2.4.26-try3.patch | 0 .../linux-2.4.24-attribute-used.patch | 0 linux/linux-colinux-2.4.28/nofpu.patch | 0 linux/linux-colinux-2.4.28/shortloadbytes.patch | 0 linux/linux-colinux_2.4.28.bb | 0 linux/linux-epia-2.6.8.1/epia_defconfig | 1480 - linux/linux-epia_2.6.8.1.bb | 0 linux/linux-mtx-1-2.4.24/01-mtd-2004-01-27.diff | 51462 ----------- linux/linux-mtx-1-2.4.24/02-mtd-mtx-1-map.diff | 248 - .../03-mtd-erase-compiler-bug.diff | 21 - linux/linux-mtx-1-2.4.24/04-zboot-2.4.24.patch | 5286 -- linux/linux-mtx-1-2.4.24/05-zboot-cflags.diff | 15 - linux/linux-mtx-1-2.4.24/06-zboot-mtx.diff | 27 - linux/linux-mtx-1-2.4.24/07-zimage-flash-bin.patch | 11 - .../linux-mtx-1-2.4.24/08-usb-nonpci-2.4.24.patch | 173 - linux/linux-mtx-1-2.4.24/09-iw-max-spy-32.diff | 11 - linux/linux-mtx-1-2.4.24/10-mtx-pci-slots.diff | 23 - linux/linux-mtx-1-2.4.24/11-mtx-extraversion.diff | 11 - .../12-openswan-2.2.0-nat-t.diff | 143 - linux/linux-mtx-1-2.4.24/13-openswan-2.2.0.patch | 61573 ------------- linux/linux-mtx-1-2.4.24/14-au1000-eth-vlan.diff | 10 - .../15-mtd-proc-partition-rw.diff | 173 - linux/linux-mtx-1-2.4.24/defconfig-mtx-1 | 1176 - linux/linux-mtx-1-2.4.27/01-mtd-2004-01-27.diff | 51503 ----------- linux/linux-mtx-1-2.4.27/02-mtd-mtx-1-map.diff | 248 - .../03-mtd-erase-compiler-bug.diff | 21 - linux/linux-mtx-1-2.4.27/04-mtx-1-board-reset.diff | 15 - linux/linux-mtx-1-2.4.27/05-mtx-1-pci-irq.diff | 18 - linux/linux-mtx-1-2.4.27/06-zboot-2.4.26.patch | 5308 -- .../07-zboot-zimage-flash-bin.diff | 11 - .../linux-mtx-1-2.4.27/08-usb-nonpci-2.4.24.patch | 3185 - linux/linux-mtx-1-2.4.27/09-au1000-eth-vlan.diff | 10 - linux/linux-mtx-1-2.4.27/10-iw-max-spy-32.diff | 11 - .../11-mtd-proc-partition-rw.diff | 173 - .../12-openswan-2.2.0-nat-t.diff | 143 - linux/linux-mtx-1-2.4.27/13-openswan-2.2.0.patch | 61573 ------------- .../14-au1000-eth-link-beat.diff | 64 - .../15-au1000-pci-fixup-non-coherent-pre-ac.diff | 0 linux/linux-mtx-1-2.4.27/defconfig-mtx-1 | 1200 - linux/linux-mtx-1-2.4.27/mtx-1-board-reset.diff | 15 - linux/linux-mtx-1-2.4.27/zimage-flash-bin.patch | 11 - linux/linux-mtx-1_2.4.24.bb | 0 linux/linux-mtx-1_2.4.27.bb | 0 linux/linux-netvista-2.4.27/netvista_defconfig | 0 linux/linux-netvista_2.4.27.bb | 0 .../omap1610h2/defconfig | 840 - .../schedstats-arm.patch | 26 - linux/linux-omap-2.6_2.6.9-omap1.bb | 0 linux/linux-sun4cdm-2.4.26/defconfig | 473 - linux/linux-sun4cdm-2.6.8.1/sun4c_defconfig | 689 - linux/linux-sun4cdm_2.4.26.bb | 0 linux/linux-sun4cdm_2.6.8.1.bb | 0 linux/linux-xxs1500-2.4.21/Makefile | 756 - linux/linux-xxs1500-2.4.21/defconfig-xxs1500 | 1199 - .../linux-xxs1500-2.4.21/zboot-Makefile-flags.diff | 11 - linux/linux-xxs1500_2.4.21.bb | 0 linux/mnci-ramses-2.4.21-rmk2-pxa1.bb | 0 .../diff-2.4.21-rmk2-pxa1.gz | 0 .../mnci-combined.patch | 19914 ----- linux/mnci-ramses_2.4.21-rmk2-pxa1.bb | 0 .../montavista-sa-2.4.17-mvl21/apm-hh-merge.patch | 561 - .../montavista-sa-2.4.17-mvl21/beagle-sound.patch | 57 - linux/montavista-sa-2.4.17-mvl21/defconfig-beagle | 1152 - .../disable-pcmcia-probe.patch | 17 - .../flash-for-beagle-iii.patch | 21 - linux/montavista-sa-2.4.17-mvl21/iw240_we15-6.diff | 399 - .../iw_handlers.w13-5.diff | 1513 - .../iw_handlers.w14-5.diff | 838 - .../montavista-sa-2.4.17-mvl21/machine_name.patch | 19 - linux/montavista-sa-2.4.17-mvl21/mkdep.patch | 16 - linux/montavista-sa-2.4.17-mvl21/opie-logo.patch | 10936 --- .../pcmcia_preempt.patch | 180 - .../remove-montavista-init-stupidity.patch | 23 - .../ucb1x_kill-zombie.patch | 15 - linux/montavista-sa_2.4.17-mvl21.bb | 0 .../nslu2-linksys-kernel-2.4.22/config-fixes.patch | 0 .../gcc-registerparanoia.patch | 0 .../gcc3-userfuncs.patch | 0 .../linux-2.4.24-attribute-used.patch | 0 linux/nslu2-linksys-kernel-2.4.22/nofpu.patch | 0 linux/nslu2-linksys-kernel-2.4.22/nslu2/defconfig | 0 .../short_loadbytes.patch | 0 linux/nslu2-linksys-kernel_2.4.22.bb | 50 - .../2.4.25-vrs2-pxa1-jpm1.patch | 8760 -- .../2.4.25-vrs2-pxa1.patch | 39937 --------- .../2.4.25-vrs2.patch | 86979 ------------------- .../defconfig-simpad | 1285 - .../disable-pcmcia-probe.patch | 17 - .../opensimpad-2.4.25-vrs2-pxa1-jpm1/keymap.patch | 0 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/mkdep.patch | 16 - .../mppe-20040216.patch | 1225 - .../scrolling-area.patch | 18 - .../simpad-apm.diff | 799 - .../simpad-backlight-if.diff | 97 - .../simpad-pm-updates.patch | 47 - .../simpad-switches-input.diff | 126 - .../simpad-switches-input2.diff | 52 - .../simpad-ts-noninput.diff | 11 - .../sound-volume-reversed.patch | 16 - linux/opensimpad-64+0_2.4.25-vrs2-pxa1-jpm1.bb | 5 - linux/opensimpad_2.4.25-vrs2-pxa1-jpm1.bb | 70 - linux/openslug-kernel-2.6.7/arm-Makefile.patch | 0 linux/openslug-kernel-2.6.7/arm-timer.patch | 0 linux/openslug-kernel-2.6.7/defconfig | 0 linux/openslug-kernel-2.6.7/ipx4xx-pci.patch | 0 linux/openslug-kernel-2.6.7/x1205-rtc.patch | 0 linux/openslug-kernel-2.6.9/defconfig | 1112 - linux/openslug-kernel-2.6.9/nslu2-io.c | 748 - linux/openslug-kernel-2.6.9/nslu2-part.c | 120 - linux/openslug-kernel-2.6.9/nslu2-pci.c | 87 - linux/openslug-kernel-2.6.9/nslu2-setup.c | 132 - linux/openslug-kernel-2.6.9/nslu2.h | 43 - linux/openslug-kernel-2.6.9/nslu2_2.6.9.patch | 312 - linux/openslug-kernel-2.6.9/x1205-rtc.c | 548 - linux/openslug-kernel_2.6.7.bb | 0 linux/openslug-kernel_2.6.9.bb | 58 - linux/openzaurus-2.6.10-rc2/defconfig-collie | 0 linux/openzaurus-2.6.10-rc2/defconfig-husky | 893 - linux/openzaurus-2.6.10-rc2/defconfig-poodle | 0 .../1764-1.patch | 16 - .../bluecard_cs.patch | 11 - .../bluetooth-2.4.18-mh11.patch | 31393 ------- .../bluetooth-2.4.18-mh15.patch | 32759 ------- .../bt950_cs.patch | 1174 - .../buffered-fbmem.patch | 19 - .../compile.patch | 14 - .../corgi-fbcon-logo.patch | 281 - .../defconfig-corgi | 1304 - .../defconfig-husky | 1304 - .../defconfig-poodle | 1110 - .../defconfig-shepherd | 1303 - .../defconfig-tosa | 1377 - .../deviceinfo.patch | 26 - .../disable-pcmcia-probe.patch | 17 - .../enable-sysrq.patch | 61 - .../idecs.patch | 77 - .../initsh.patch | 14 - .../irda-qos.patch | 108 - .../iw240_we15-6.diff | 399 - .../iw_handlers.w13-5.diff | 1513 - .../iw_handlers.w14-5.diff | 838 - .../keyboard-ctrl+alt.patch | 79 - .../keymap-more-sane.patch | 23 - .../logo.patch | 2598 - .../mkdep.patch | 16 - .../module_licence.patch | 96 - .../piro.patch | 75444 ---------------- .../sharpsl_battery.patch | 346 - .../smallfonts.diff | 2453 - .../swap-performance.patch | 19 - .../tosa-power-key-off.patch | 127 - .../tosa_map.patch | 889 - .../tosa_ts.patch | 207 - .../usb-storage.patch | 3433 - ...nzaurus-pxa_2.4.18-rmk7-pxa3-embedix20031107.bb | 104 - .../1764-1.patch | 16 - .../battery.patch | 326 - .../bluetooth-2.4.18-mh15.patch | 32759 ------- .../bluetooth-patch-2.4.18-mh9.diff | 30831 ------- .../cacko.patch | 0 .../defconfig-collie | 1283 - .../disable-pcmcia-probe.patch | 17 - .../idecs.patch | 77 - .../initsh.patch | 14 - .../iw240_we15-6.diff | 399 - .../iw_handlers.w13-5.diff | 1513 - .../iw_handlers.w14-5.diff | 838 - .../keymap-more-sane.patch | 19 - .../logo.patch | 2598 - .../mkdep.patch | 16 - .../module_licence.patch | 81 - .../sound-2.4.18r2.patch | 5602 -- ...enzaurus-sa_2.4.18-rmk7-pxa3-embedix20030509.bb | 95 - linux/openzaurus_2.6.10-rc2.bb | 0 linux/unslung-able-kernel_2.3r25.bb | 8 - linux/unslung-kernel-2.3r25/able/defconfig | 976 - linux/unslung-kernel-2.3r25/defconfig | 973 - .../unslung-kernel-2.3r25/ext3flash-on-disk1.patch | 41 - linux/unslung-kernel-2.3r25/ext3flash.patch | 0 linux/unslung-kernel-2.3r25/gl811e.patch | 0 linux/unslung-kernel-2.3r25/limit1gb.patch | 0 .../unslung-kernel-2.3r25/missing-usb-ioctls.patch | 0 linux/unslung-kernel-2.3r25/usbnet.patch | 0 linux/unslung-standard-kernel_2.3r25.bb | 29 - 236 files changed, 728055 deletions(-) delete mode 100644 linux/collie-kernel-24-8_2.4.18-rmk7-pxa3-embedix20030509.bb delete mode 100644 linux/collie-kernel-32-0_2.4.18-rmk7-pxa3-embedix20030509.bb delete mode 100644 linux/collie-kernel-32-32_2.4.18-rmk7-pxa3-embedix20030509.bb delete mode 100644 linux/collie-kernel-40-24_2.4.18-rmk7-pxa3-embedix20030509.bb delete mode 100644 linux/collie-kernel-48-16_2.4.18-rmk7-pxa3-embedix20030509.bb delete mode 100644 linux/collie-kernel-58-6_2.4.18-rmk7-pxa3-embedix20030509.bb delete mode 100644 linux/collie-kernel-64-0_2.4.18-rmk7-pxa3-embedix20030509.bb delete mode 100644 linux/collie-kernel-all_2.4.18-rmk7-pxa3-embedix20030509.bb delete mode 100644 linux/files/ipaq-hal.init delete mode 100644 linux/files/linux-2.4-cpufreq.patch delete mode 100644 linux/files/linux-2.4-no-short-loads.patch delete mode 100644 linux/files/linux-2.4.18-list_move.patch delete mode 100644 linux/files/mipv6-1.1-v2.4.25.patch delete mode 100644 linux/gumstix-2.6.5-gnalm1-gum0/defconfig delete mode 100644 linux/gumstix-2.6.5-gnalm1-gum0/linux-2.6.5-gnalm1.patch delete mode 100644 linux/gumstix_2.6.5-gnalm1-gum0.bb delete mode 100644 linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.12/defconfig-ipaqpxa delete mode 100644 linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.12/ipsec.patch delete mode 100644 linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.13/defconfig-ipaqpxa delete mode 100644 linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.14/defconfig-ipaqpxa delete mode 100644 linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh37.1/defconfig-ipaqpxa delete mode 100644 linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh37.4/defconfig-ipaqpxa delete mode 100644 linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh37.4/mmc_h5400.patch delete mode 100644 linux/handhelds-pxa-2.6/defconfig delete mode 100644 linux/handhelds-pxa-2.6/defconfig-ipaq-pxa-2.6 delete mode 100644 linux/handhelds-pxa-2.6/defconfig-ipaq-pxa-2.6_2.6.8.1-hh0 delete mode 100644 linux/handhelds-pxa-2.6_2.6.6-hh0.bb delete mode 100644 linux/handhelds-pxa-2.6_2.6.8.1-hh0.bb delete mode 100644 linux/handhelds-pxa-2.6_cvs.bb delete mode 100644 linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh36.12.bb delete mode 100644 linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh36.13.bb delete mode 100644 linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh36.14.bb delete mode 100644 linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh37.1.bb delete mode 100644 linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh37.4.bb delete mode 100644 linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/defconfig-ipaqsa delete mode 100644 linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/disable-pcmcia-probe.patch delete mode 100644 linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/ipsec.patch delete mode 100644 linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/mkdep.patch delete mode 100644 linux/handhelds-sa-2.4.19-rmk6-pxa1-hh37.1/defconfig-ipaqsa delete mode 100644 linux/handhelds-sa-2.4.19-rmk6-pxa1-hh37.4/defconfig-ipaqsa delete mode 100644 linux/handhelds-sa-2.6/defconfig-jornada56x delete mode 100644 linux/handhelds-sa-2.6_cvs.bb delete mode 100644 linux/handhelds-sa_2.4.19-rmk6-pxa1-hh36.12.bb delete mode 100644 linux/handhelds-sa_2.4.19-rmk6-pxa1-hh37.1.bb delete mode 100644 linux/handhelds-sa_2.4.19-rmk6-pxa1-hh37.4.bb delete mode 100644 linux/ipod_2.4.24-ipod0.bb delete mode 100644 linux/linux-bast-2.4.25-vrs1-bast1/defconfig delete mode 100644 linux/linux-bast-2.4.25-vrs1-bast1/mkdep.patch delete mode 100644 linux/linux-bast_2.4.25-vrs1-bast1.bb delete mode 100644 linux/linux-colinux-2.4.28/colinux-0.6.1.patch delete mode 100644 linux/linux-colinux-2.4.28/defconfig delete mode 100644 linux/linux-colinux-2.4.28/gcc-registerparanoia.patch delete mode 100644 linux/linux-colinux-2.4.28/gcc340-fixes-v2.4.26-try3.patch delete mode 100644 linux/linux-colinux-2.4.28/linux-2.4.24-attribute-used.patch delete mode 100644 linux/linux-colinux-2.4.28/nofpu.patch delete mode 100644 linux/linux-colinux-2.4.28/shortloadbytes.patch delete mode 100644 linux/linux-colinux_2.4.28.bb delete mode 100644 linux/linux-epia-2.6.8.1/epia_defconfig delete mode 100644 linux/linux-epia_2.6.8.1.bb delete mode 100644 linux/linux-mtx-1-2.4.24/01-mtd-2004-01-27.diff delete mode 100644 linux/linux-mtx-1-2.4.24/02-mtd-mtx-1-map.diff delete mode 100644 linux/linux-mtx-1-2.4.24/03-mtd-erase-compiler-bug.diff delete mode 100644 linux/linux-mtx-1-2.4.24/04-zboot-2.4.24.patch delete mode 100644 linux/linux-mtx-1-2.4.24/05-zboot-cflags.diff delete mode 100644 linux/linux-mtx-1-2.4.24/06-zboot-mtx.diff delete mode 100644 linux/linux-mtx-1-2.4.24/07-zimage-flash-bin.patch delete mode 100644 linux/linux-mtx-1-2.4.24/08-usb-nonpci-2.4.24.patch delete mode 100644 linux/linux-mtx-1-2.4.24/09-iw-max-spy-32.diff delete mode 100644 linux/linux-mtx-1-2.4.24/10-mtx-pci-slots.diff delete mode 100644 linux/linux-mtx-1-2.4.24/11-mtx-extraversion.diff delete mode 100644 linux/linux-mtx-1-2.4.24/12-openswan-2.2.0-nat-t.diff delete mode 100644 linux/linux-mtx-1-2.4.24/13-openswan-2.2.0.patch delete mode 100644 linux/linux-mtx-1-2.4.24/14-au1000-eth-vlan.diff delete mode 100644 linux/linux-mtx-1-2.4.24/15-mtd-proc-partition-rw.diff delete mode 100644 linux/linux-mtx-1-2.4.24/defconfig-mtx-1 delete mode 100644 linux/linux-mtx-1-2.4.27/01-mtd-2004-01-27.diff delete mode 100644 linux/linux-mtx-1-2.4.27/02-mtd-mtx-1-map.diff delete mode 100644 linux/linux-mtx-1-2.4.27/03-mtd-erase-compiler-bug.diff delete mode 100644 linux/linux-mtx-1-2.4.27/04-mtx-1-board-reset.diff delete mode 100644 linux/linux-mtx-1-2.4.27/05-mtx-1-pci-irq.diff delete mode 100644 linux/linux-mtx-1-2.4.27/06-zboot-2.4.26.patch delete mode 100644 linux/linux-mtx-1-2.4.27/07-zboot-zimage-flash-bin.diff delete mode 100644 linux/linux-mtx-1-2.4.27/08-usb-nonpci-2.4.24.patch delete mode 100644 linux/linux-mtx-1-2.4.27/09-au1000-eth-vlan.diff delete mode 100644 linux/linux-mtx-1-2.4.27/10-iw-max-spy-32.diff delete mode 100644 linux/linux-mtx-1-2.4.27/11-mtd-proc-partition-rw.diff delete mode 100644 linux/linux-mtx-1-2.4.27/12-openswan-2.2.0-nat-t.diff delete mode 100644 linux/linux-mtx-1-2.4.27/13-openswan-2.2.0.patch delete mode 100644 linux/linux-mtx-1-2.4.27/14-au1000-eth-link-beat.diff delete mode 100644 linux/linux-mtx-1-2.4.27/15-au1000-pci-fixup-non-coherent-pre-ac.diff delete mode 100644 linux/linux-mtx-1-2.4.27/defconfig-mtx-1 delete mode 100644 linux/linux-mtx-1-2.4.27/mtx-1-board-reset.diff delete mode 100644 linux/linux-mtx-1-2.4.27/zimage-flash-bin.patch delete mode 100644 linux/linux-mtx-1_2.4.24.bb delete mode 100644 linux/linux-mtx-1_2.4.27.bb delete mode 100644 linux/linux-netvista-2.4.27/netvista_defconfig delete mode 100644 linux/linux-netvista_2.4.27.bb delete mode 100644 linux/linux-omap-2.6-2.6.9-omap1/omap1610h2/defconfig delete mode 100644 linux/linux-omap-2.6-2.6.9-omap1/schedstats-arm.patch delete mode 100644 linux/linux-omap-2.6_2.6.9-omap1.bb delete mode 100644 linux/linux-sun4cdm-2.4.26/defconfig delete mode 100644 linux/linux-sun4cdm-2.6.8.1/sun4c_defconfig delete mode 100644 linux/linux-sun4cdm_2.4.26.bb delete mode 100644 linux/linux-sun4cdm_2.6.8.1.bb delete mode 100644 linux/linux-xxs1500-2.4.21/Makefile delete mode 100644 linux/linux-xxs1500-2.4.21/defconfig-xxs1500 delete mode 100644 linux/linux-xxs1500-2.4.21/zboot-Makefile-flags.diff delete mode 100644 linux/linux-xxs1500_2.4.21.bb delete mode 100644 linux/mnci-ramses-2.4.21-rmk2-pxa1.bb delete mode 100644 linux/mnci-ramses-2.4.21-rmk2-pxa1/diff-2.4.21-rmk2-pxa1.gz delete mode 100644 linux/mnci-ramses-2.4.21-rmk2-pxa1/mnci-combined.patch delete mode 100644 linux/mnci-ramses_2.4.21-rmk2-pxa1.bb delete mode 100644 linux/montavista-sa-2.4.17-mvl21/apm-hh-merge.patch delete mode 100644 linux/montavista-sa-2.4.17-mvl21/beagle-sound.patch delete mode 100644 linux/montavista-sa-2.4.17-mvl21/defconfig-beagle delete mode 100644 linux/montavista-sa-2.4.17-mvl21/disable-pcmcia-probe.patch delete mode 100644 linux/montavista-sa-2.4.17-mvl21/flash-for-beagle-iii.patch delete mode 100644 linux/montavista-sa-2.4.17-mvl21/iw240_we15-6.diff delete mode 100644 linux/montavista-sa-2.4.17-mvl21/iw_handlers.w13-5.diff delete mode 100644 linux/montavista-sa-2.4.17-mvl21/iw_handlers.w14-5.diff delete mode 100644 linux/montavista-sa-2.4.17-mvl21/machine_name.patch delete mode 100644 linux/montavista-sa-2.4.17-mvl21/mkdep.patch delete mode 100644 linux/montavista-sa-2.4.17-mvl21/opie-logo.patch delete mode 100644 linux/montavista-sa-2.4.17-mvl21/pcmcia_preempt.patch delete mode 100644 linux/montavista-sa-2.4.17-mvl21/remove-montavista-init-stupidity.patch delete mode 100644 linux/montavista-sa-2.4.17-mvl21/ucb1x_kill-zombie.patch delete mode 100644 linux/montavista-sa_2.4.17-mvl21.bb delete mode 100644 linux/nslu2-linksys-kernel-2.4.22/config-fixes.patch delete mode 100644 linux/nslu2-linksys-kernel-2.4.22/gcc-registerparanoia.patch delete mode 100644 linux/nslu2-linksys-kernel-2.4.22/gcc3-userfuncs.patch delete mode 100644 linux/nslu2-linksys-kernel-2.4.22/linux-2.4.24-attribute-used.patch delete mode 100644 linux/nslu2-linksys-kernel-2.4.22/nofpu.patch delete mode 100644 linux/nslu2-linksys-kernel-2.4.22/nslu2/defconfig delete mode 100644 linux/nslu2-linksys-kernel-2.4.22/short_loadbytes.patch delete mode 100644 linux/nslu2-linksys-kernel_2.4.22.bb delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/2.4.25-vrs2-pxa1-jpm1.patch delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/2.4.25-vrs2-pxa1.patch delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/2.4.25-vrs2.patch delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/defconfig-simpad delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/disable-pcmcia-probe.patch delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/keymap.patch delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/mkdep.patch delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/mppe-20040216.patch delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/scrolling-area.patch delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-apm.diff delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-backlight-if.diff delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-pm-updates.patch delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-switches-input.diff delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-switches-input2.diff delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-ts-noninput.diff delete mode 100644 linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/sound-volume-reversed.patch delete mode 100644 linux/opensimpad-64+0_2.4.25-vrs2-pxa1-jpm1.bb delete mode 100644 linux/opensimpad_2.4.25-vrs2-pxa1-jpm1.bb delete mode 100644 linux/openslug-kernel-2.6.7/arm-Makefile.patch delete mode 100644 linux/openslug-kernel-2.6.7/arm-timer.patch delete mode 100644 linux/openslug-kernel-2.6.7/defconfig delete mode 100644 linux/openslug-kernel-2.6.7/ipx4xx-pci.patch delete mode 100644 linux/openslug-kernel-2.6.7/x1205-rtc.patch delete mode 100644 linux/openslug-kernel-2.6.9/defconfig delete mode 100644 linux/openslug-kernel-2.6.9/nslu2-io.c delete mode 100644 linux/openslug-kernel-2.6.9/nslu2-part.c delete mode 100644 linux/openslug-kernel-2.6.9/nslu2-pci.c delete mode 100644 linux/openslug-kernel-2.6.9/nslu2-setup.c delete mode 100644 linux/openslug-kernel-2.6.9/nslu2.h delete mode 100644 linux/openslug-kernel-2.6.9/nslu2_2.6.9.patch delete mode 100644 linux/openslug-kernel-2.6.9/x1205-rtc.c delete mode 100644 linux/openslug-kernel_2.6.7.bb delete mode 100644 linux/openslug-kernel_2.6.9.bb delete mode 100644 linux/openzaurus-2.6.10-rc2/defconfig-collie delete mode 100644 linux/openzaurus-2.6.10-rc2/defconfig-husky delete mode 100644 linux/openzaurus-2.6.10-rc2/defconfig-poodle delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/1764-1.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/bluecard_cs.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/bluetooth-2.4.18-mh11.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/bluetooth-2.4.18-mh15.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/bt950_cs.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/buffered-fbmem.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/compile.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/corgi-fbcon-logo.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/defconfig-corgi delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/defconfig-husky delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/defconfig-poodle delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/defconfig-shepherd delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/defconfig-tosa delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/deviceinfo.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/disable-pcmcia-probe.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/enable-sysrq.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/idecs.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/initsh.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/irda-qos.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/iw240_we15-6.diff delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/iw_handlers.w13-5.diff delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/iw_handlers.w14-5.diff delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/keyboard-ctrl+alt.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/keymap-more-sane.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/logo.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/mkdep.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/module_licence.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/piro.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/sharpsl_battery.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/smallfonts.diff delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/swap-performance.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/tosa-power-key-off.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/tosa_map.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/tosa_ts.patch delete mode 100644 linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/usb-storage.patch delete mode 100644 linux/openzaurus-pxa_2.4.18-rmk7-pxa3-embedix20031107.bb delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/1764-1.patch delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/battery.patch delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/bluetooth-2.4.18-mh15.patch delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/bluetooth-patch-2.4.18-mh9.diff delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/cacko.patch delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/defconfig-collie delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/disable-pcmcia-probe.patch delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/idecs.patch delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/initsh.patch delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/iw240_we15-6.diff delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/iw_handlers.w13-5.diff delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/iw_handlers.w14-5.diff delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/keymap-more-sane.patch delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/logo.patch delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/mkdep.patch delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/module_licence.patch delete mode 100644 linux/openzaurus-sa-2.4.18-rmk7-pxa3-embedix20030509/sound-2.4.18r2.patch delete mode 100644 linux/openzaurus-sa_2.4.18-rmk7-pxa3-embedix20030509.bb delete mode 100644 linux/openzaurus_2.6.10-rc2.bb delete mode 100644 linux/unslung-able-kernel_2.3r25.bb delete mode 100644 linux/unslung-kernel-2.3r25/able/defconfig delete mode 100644 linux/unslung-kernel-2.3r25/defconfig delete mode 100644 linux/unslung-kernel-2.3r25/ext3flash-on-disk1.patch delete mode 100644 linux/unslung-kernel-2.3r25/ext3flash.patch delete mode 100644 linux/unslung-kernel-2.3r25/gl811e.patch delete mode 100644 linux/unslung-kernel-2.3r25/limit1gb.patch delete mode 100644 linux/unslung-kernel-2.3r25/missing-usb-ioctls.patch delete mode 100644 linux/unslung-kernel-2.3r25/usbnet.patch delete mode 100644 linux/unslung-standard-kernel_2.3r25.bb (limited to 'linux') diff --git a/linux/collie-kernel-24-8_2.4.18-rmk7-pxa3-embedix20030509.bb b/linux/collie-kernel-24-8_2.4.18-rmk7-pxa3-embedix20030509.bb deleted file mode 100644 index 02b68a038f..0000000000 --- a/linux/collie-kernel-24-8_2.4.18-rmk7-pxa3-embedix20030509.bb +++ /dev/null @@ -1,10 +0,0 @@ -SECTION = "kernel" -COLLIE_MEMORY_SIZE=24 -COLLIE_RAMDISK_SIZE=8 - -include ../linux/openzaurus-sa_2.4.18-rmk7-pxa3-embedix20030509.bb - -do_deploy_append() { - ! test -d ${DEPLOY_DIR}/images/collie/kernel && mkdir -p ${DEPLOY_DIR}/images/collie/kernel - mv ${DEPLOY_DIR}/images/${KERNEL_IMAGETYPE}-${DATETIME} ${DEPLOY_DIR}/images/collie/kernel/${KERNEL_IMAGETYPE}_collie-${COLLIE_MEMORY_SIZE}-${COLLIE_RAMDISK_SIZE} -} diff --git a/linux/collie-kernel-32-0_2.4.18-rmk7-pxa3-embedix20030509.bb b/linux/collie-kernel-32-0_2.4.18-rmk7-pxa3-embedix20030509.bb deleted file mode 100644 index 1bd0519ce0..0000000000 --- a/linux/collie-kernel-32-0_2.4.18-rmk7-pxa3-embedix20030509.bb +++ /dev/null @@ -1,10 +0,0 @@ -SECTION = "kernel" -COLLIE_MEMORY_SIZE=32 -COLLIE_RAMDISK_SIZE=0 - -include ../linux/openzaurus-sa_2.4.18-rmk7-pxa3-embedix20030509.bb - -do_deploy_append() { - ! test -d ${DEPLOY_DIR}/images/collie/kernel && mkdir -p ${DEPLOY_DIR}/images/collie/kernel - mv ${DEPLOY_DIR}/images/${KERNEL_IMAGETYPE}-${DATETIME} ${DEPLOY_DIR}/images/collie/kernel/${KERNEL_IMAGETYPE}_collie-${COLLIE_MEMORY_SIZE}-${COLLIE_RAMDISK_SIZE} -} diff --git a/linux/collie-kernel-32-32_2.4.18-rmk7-pxa3-embedix20030509.bb b/linux/collie-kernel-32-32_2.4.18-rmk7-pxa3-embedix20030509.bb deleted file mode 100644 index a254eb4a6e..0000000000 --- a/linux/collie-kernel-32-32_2.4.18-rmk7-pxa3-embedix20030509.bb +++ /dev/null @@ -1,10 +0,0 @@ -SECTION = "kernel" -COLLIE_MEMORY_SIZE=32 -COLLIE_RAMDISK_SIZE=32 - -include ../linux/openzaurus-sa_2.4.18-rmk7-pxa3-embedix20030509.bb - -do_deploy_append() { - ! test -d ${DEPLOY_DIR}/images/collie/kernel && mkdir -p ${DEPLOY_DIR}/images/collie/kernel - mv ${DEPLOY_DIR}/images/${KERNEL_IMAGETYPE}-${DATETIME} ${DEPLOY_DIR}/images/collie/kernel/${KERNEL_IMAGETYPE}_collie-${COLLIE_MEMORY_SIZE}-${COLLIE_RAMDISK_SIZE} -} diff --git a/linux/collie-kernel-40-24_2.4.18-rmk7-pxa3-embedix20030509.bb b/linux/collie-kernel-40-24_2.4.18-rmk7-pxa3-embedix20030509.bb deleted file mode 100644 index 2e3a9676be..0000000000 --- a/linux/collie-kernel-40-24_2.4.18-rmk7-pxa3-embedix20030509.bb +++ /dev/null @@ -1,10 +0,0 @@ -SECTION = "kernel" -COLLIE_MEMORY_SIZE=40 -COLLIE_RAMDISK_SIZE=24 - -include ../linux/openzaurus-sa_2.4.18-rmk7-pxa3-embedix20030509.bb - -do_deploy_append() { - ! test -d ${DEPLOY_DIR}/images/collie/kernel && mkdir -p ${DEPLOY_DIR}/images/collie/kernel - mv ${DEPLOY_DIR}/images/${KERNEL_IMAGETYPE}-${DATETIME} ${DEPLOY_DIR}/images/collie/kernel/${KERNEL_IMAGETYPE}_collie-${COLLIE_MEMORY_SIZE}-${COLLIE_RAMDISK_SIZE} -} diff --git a/linux/collie-kernel-48-16_2.4.18-rmk7-pxa3-embedix20030509.bb b/linux/collie-kernel-48-16_2.4.18-rmk7-pxa3-embedix20030509.bb deleted file mode 100644 index ea6981f4af..0000000000 --- a/linux/collie-kernel-48-16_2.4.18-rmk7-pxa3-embedix20030509.bb +++ /dev/null @@ -1,10 +0,0 @@ -SECTION = "kernel" -COLLIE_MEMORY_SIZE=48 -COLLIE_RAMDISK_SIZE=16 - -include ../linux/openzaurus-sa_2.4.18-rmk7-pxa3-embedix20030509.bb - -do_deploy_append() { - ! test -d ${DEPLOY_DIR}/images/collie/kernel && mkdir -p ${DEPLOY_DIR}/images/collie/kernel - mv ${DEPLOY_DIR}/images/${KERNEL_IMAGETYPE}-${DATETIME} ${DEPLOY_DIR}/images/collie/kernel/${KERNEL_IMAGETYPE}_collie-${COLLIE_MEMORY_SIZE}-${COLLIE_RAMDISK_SIZE} -} diff --git a/linux/collie-kernel-58-6_2.4.18-rmk7-pxa3-embedix20030509.bb b/linux/collie-kernel-58-6_2.4.18-rmk7-pxa3-embedix20030509.bb deleted file mode 100644 index c25f61bf42..0000000000 --- a/linux/collie-kernel-58-6_2.4.18-rmk7-pxa3-embedix20030509.bb +++ /dev/null @@ -1,10 +0,0 @@ -SECTION = "kernel" -COLLIE_MEMORY_SIZE=58 -COLLIE_RAMDISK_SIZE=6 - -include ../linux/openzaurus-sa_2.4.18-rmk7-pxa3-embedix20030509.bb - -do_deploy_append() { - ! test -d ${DEPLOY_DIR}/images/collie/kernel && mkdir -p ${DEPLOY_DIR}/images/collie/kernel - mv ${DEPLOY_DIR}/images/${KERNEL_IMAGETYPE}-${DATETIME} ${DEPLOY_DIR}/images/collie/kernel/${KERNEL_IMAGETYPE}_collie-${COLLIE_MEMORY_SIZE}-${COLLIE_RAMDISK_SIZE} -} diff --git a/linux/collie-kernel-64-0_2.4.18-rmk7-pxa3-embedix20030509.bb b/linux/collie-kernel-64-0_2.4.18-rmk7-pxa3-embedix20030509.bb deleted file mode 100644 index a91a145d47..0000000000 --- a/linux/collie-kernel-64-0_2.4.18-rmk7-pxa3-embedix20030509.bb +++ /dev/null @@ -1,10 +0,0 @@ -SECTION = "kernel" -COLLIE_MEMORY_SIZE=64 -COLLIE_RAMDISK_SIZE=0 - -include ../linux/openzaurus-sa_2.4.18-rmk7-pxa3-embedix20030509.bb - -do_deploy_append() { - ! test -d ${DEPLOY_DIR}/images/collie/kernel && mkdir -p ${DEPLOY_DIR}/images/collie/kernel - mv ${DEPLOY_DIR}/images/${KERNEL_IMAGETYPE}-${DATETIME} ${DEPLOY_DIR}/images/collie/kernel/${KERNEL_IMAGETYPE}_collie-${COLLIE_MEMORY_SIZE}-${COLLIE_RAMDISK_SIZE} -} diff --git a/linux/collie-kernel-all_2.4.18-rmk7-pxa3-embedix20030509.bb b/linux/collie-kernel-all_2.4.18-rmk7-pxa3-embedix20030509.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/files/ipaq-hal.init b/linux/files/ipaq-hal.init deleted file mode 100644 index 4efb52ec97..0000000000 --- a/linux/files/ipaq-hal.init +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -# make sure update-modules has been run -# since the calls below depend on aliases... -if [ ! -f /etc/modules.conf ]; then - update-modules || true -fi - -modprobe ipaq_hal || exit 0 - -if [ -d /proc/hal ]; then - model=`cat /proc/hal/model` - modprobe ipaq_hal_$model -fi diff --git a/linux/files/linux-2.4-cpufreq.patch b/linux/files/linux-2.4-cpufreq.patch deleted file mode 100644 index c3526bb30d..0000000000 --- a/linux/files/linux-2.4-cpufreq.patch +++ /dev/null @@ -1,20 +0,0 @@ -Index: include/linux/cpufreq.h -=================================================================== -RCS file: /cvs/linux/kernel/include/linux/cpufreq.h,v -retrieving revision 1.4 -diff -u -r1.4 cpufreq.h ---- linux/include/linux/cpufreq.h 23 Aug 2002 22:18:47 -0000 1.4 -+++ linux/include/linux/cpufreq.h 29 Apr 2004 08:44:18 -0000 -@@ -16,9 +16,9 @@ - #include - - #ifndef CONFIG_SMP --#define cpufreq_current(cpu) ((void)(cpu), __cpufreq_cur) --#define cpufreq_max(cpu) ((void)(cpu), __cpufreq_max) --#define cpufreq_min(cpu) ((void)(cpu), __cpufreq_min) -+#define cpufreq_current(cpu) (__cpufreq_cur) -+#define cpufreq_max(cpu) (__cpufreq_max) -+#define cpufreq_min(cpu) (__cpufreq_min) - #else - /* - * Should be something like: diff --git a/linux/files/linux-2.4-no-short-loads.patch b/linux/files/linux-2.4-no-short-loads.patch deleted file mode 100644 index f2d6c74224..0000000000 --- a/linux/files/linux-2.4-no-short-loads.patch +++ /dev/null @@ -1,18 +0,0 @@ -Index: arch/arm/Makefile -=================================================================== -RCS file: /cvs/linux/kernel/arch/arm/Makefile,v -retrieving revision 1.47 -diff -u -r1.47 Makefile ---- linux/arch/arm/Makefile 9 Jul 2003 14:10:56 -0000 1.47 -+++ linux/arch/arm/Makefile 28 Apr 2004 21:11:04 -0000 -@@ -60,8 +60,8 @@ - tune-$(CONFIG_CPU_XSCALE) :=-mtune=xscale - #tune-$(CONFIG_CPU_XSCALE) :=-mtune=strongarm - --CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm --CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm -+CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -msoft-float -Uarm -+CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -msoft-float -Uarm - AFLAGS +=$(apcs-y) $(arch-y) -msoft-float - - ifeq ($(CONFIG_CPU_26),y) diff --git a/linux/files/linux-2.4.18-list_move.patch b/linux/files/linux-2.4.18-list_move.patch deleted file mode 100644 index faec56330b..0000000000 --- a/linux/files/linux-2.4.18-list_move.patch +++ /dev/null @@ -1,32 +0,0 @@ ---- linux/include/linux/list.h~ 2001-12-21 17:42:03.000000000 +0000 -+++ linux/include/linux/list.h 2004-06-14 23:41:33.000000000 +0100 -@@ -105,6 +105,29 @@ - } - - /** -+ * list_move - delete from one list and add as another's head -+ * @list: the entry to move -+ * @head: the head that will precede our entry -+ */ -+static inline void list_move(struct list_head *list, struct list_head *head) -+{ -+ __list_del(list->prev, list->next); -+ list_add(list, head); -+} -+ -+/** -+ * list_move_tail - delete from one list and add as another's tail -+ * @list: the entry to move -+ * @head: the head that will follow our entry -+ */ -+static inline void list_move_tail(struct list_head *list, -+ struct list_head *head) -+{ -+ __list_del(list->prev, list->next); -+ list_add_tail(list, head); -+} -+ -+/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ diff --git a/linux/files/mipv6-1.1-v2.4.25.patch b/linux/files/mipv6-1.1-v2.4.25.patch deleted file mode 100644 index c5f32b6416..0000000000 --- a/linux/files/mipv6-1.1-v2.4.25.patch +++ /dev/null @@ -1,19832 +0,0 @@ -diff -uprN linux-2.4.25.old/Documentation/Configure.help linux-2.4.25/Documentation/Configure.help ---- linux-2.4.25.old/Documentation/Configure.help 2004-06-26 11:22:00.000000000 +0100 -+++ linux-2.4.25/Documentation/Configure.help 2004-06-26 11:29:29.000000000 +0100 -@@ -6204,6 +6204,57 @@ CONFIG_IPV6 - - It is safe to say N here for now. - -+IPv6: IPv6 over IPv6 Tunneling (EXPERIMENTAL) -+CONFIG_IPV6_TUNNEL -+ Experimental IP6-IP6 tunneling. You must select this, if you want -+ to use CONFIG_IPV6_MOBILITY. More information in MIPL Mobile IPv6 -+ instructions. -+ -+ If you don't want IP6-IP6 tunnels and Mobile IPv6, say N. -+ -+IPv6: Mobility Support (EXPERIMENTAL) -+CONFIG_IPV6_MOBILITY -+ This is experimental support for the upcoming specification of -+ Mobile IPv6. Mobile IPv6 allows nodes to seamlessly move between -+ networks without changing their IP addresses, thus allowing them to -+ maintain upper layer connections (e.g. TCP). Selecting this option -+ allows your computer to act as a Correspondent Node (CN). A MIPv6 -+ Mobile Node will be able to communicate with the CN and use route -+ optimization. -+ -+ For more information and configuration details, see -+ http://www.mipl.mediapoli.com/. -+ -+ If unsure, say N. -+ -+MIPv6: Mobile Node Support -+CONFIG_IPV6_MOBILITY_MN -+ If you want your computer to be a MIPv6 Mobile Node (MN), select -+ this option. You must configure MN using the userspace tools -+ available at http://www.mipl.mediapoli.com/download/mipv6-tools/. -+ -+ If your computer is stationary, or you are unsure if you need this, -+ say N. Note that you will need a properly configured MIPv6 Home -+ Agent to use any Mobile Nodes. -+ -+MIPv6: Home Agent Support -+CONFIG_IPV6_MOBILITY_HA -+ If you want your router to serve as a MIPv6 Home Agent (HA), select -+ this option. You must configure HA using the userspace tools -+ available at http://www.mipl.mediapoli.com/download/mipv6-tools/. -+ -+ If your computer is not a router, or you are unsure if you need -+ this, say N. -+ -+MIPv6: Debug messages -+CONFIG_IPV6_MOBILITY_DEBUG -+ MIPL Mobile IPv6 can produce a lot of debugging messages. There are -+ eight debug levels (0 through 7) and the level is controlled via -+ /proc/sys/net/ipv6/mobility/debuglevel. Since MIPL is still -+ experimental, you might want to say Y here. -+ -+ Be sure to say Y and record debug messages when submitting a bug -+ report. - The SCTP Protocol (EXPERIMENTAL) - CONFIG_IP_SCTP - Stream Control Transmission Protocol -diff -uprN linux-2.4.25.old/Documentation/DocBook/Makefile linux-2.4.25/Documentation/DocBook/Makefile ---- linux-2.4.25.old/Documentation/DocBook/Makefile 2002-11-28 23:53:08.000000000 +0000 -+++ linux-2.4.25/Documentation/DocBook/Makefile 2004-06-26 11:29:29.000000000 +0100 -@@ -2,7 +2,7 @@ BOOKS := wanbook.sgml z8530book.sgml mca - kernel-api.sgml parportbook.sgml kernel-hacking.sgml \ - kernel-locking.sgml via-audio.sgml mousedrivers.sgml sis900.sgml \ - deviceiobook.sgml procfs-guide.sgml tulip-user.sgml \ -- journal-api.sgml -+ journal-api.sgml mip6-func.sgml - - PS := $(patsubst %.sgml, %.ps, $(BOOKS)) - PDF := $(patsubst %.sgml, %.pdf, $(BOOKS)) -@@ -86,6 +86,9 @@ videobook.sgml: videobook.tmpl $(TOPDIR) - procfs-guide.sgml: procfs-guide.tmpl procfs_example.sgml - $(TOPDIR)/scripts/docgen < procfs-guide.tmpl >$@ - -+mip6-func.sgml: mip6-func.tmpl -+ $(TOPDIR)/scripts/docgen <$< >$@ -+ - APISOURCES := $(TOPDIR)/drivers/media/video/videodev.c \ - $(TOPDIR)/arch/i386/kernel/irq.c \ - $(TOPDIR)/arch/i386/kernel/mca.c \ -diff -uprN linux-2.4.25.old/Documentation/DocBook/mip6-func.tmpl linux-2.4.25/Documentation/DocBook/mip6-func.tmpl ---- linux-2.4.25.old/Documentation/DocBook/mip6-func.tmpl 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/Documentation/DocBook/mip6-func.tmpl 2004-06-26 11:29:29.000000000 +0100 -@@ -0,0 +1,756 @@ -+ -+ -+ -+ MIPL Mobile IPv6 Function Reference Guide -+ -+ -+ -+ MIPL Mobile IPv6 for Linux Team -+ -+ Helsinki University of Technology -+ Telecommunications Software and Multimedia Lab -+
-+ PO BOX 9201 -+ FIN-02015 HUT -+ Finland -+ mipl@list.mipl.mediapoli.com -+
-+
-+
-+
-+ -+ -+ 2000-2001 -+ Helsinki University of Technology -+ -+ -+ -+ -+ Copyright (c) 2001, 2002 MIPL Mobile IPv6 for Linux Team. -+ -+ -+ Permission is granted to copy, distribute and/or modify this -+ document under the terms of the GNU Free Documentation License, -+ Version 1.1 published by the Free Software Foundation; with the -+ Invariant Sections being "Introduction", with the Front-Cover -+ Texts being "MIPL Mobile IPv6 Function Reference Guide", "MIPL -+ Mobile IPv6 for Linux Team" and "Helsinki University of -+ Technology". A copy of the license is included in . -+ -+ -+ -+
-+ -+ -+ -+ -+ Introduction -+ -+ -+ MIPL Mobile IPv6 for Linux is an implementation of Mobility -+ Support in IPv6 IETF mobile-ip working groups Internet-Draft -+ (draft-ietf-mobileip-ipv6). This implementation has been -+ developed in the Telecommunications Software and Multimedia -+ Laboratory at Helsinki University of Technology. -+ -+ -+ -+ MIPL is fully open source, licensed under the GNU General -+ Public License. Latest source for MIPL can be downloaded from -+ the MIPL website at: -+ -+ -+ http://www.mipl.mediapoli.com/. -+ -+ -+ Developers and users interested in MIPL can subscribe to the -+ MIPL mailing list by sending e-mail to -+ majordomo@list.mipl.mediapoli.com with -+ -+ -+ subscribe mipl -+ -+ -+ in the body of the message. -+ -+ -+ -+ This document is a reference guide to MIPL functions. Intended -+ audience is developers wishing to contribute to the project. -+ Hopefully this document will make it easier and quicker to -+ understand and adopt the inner workings of MIPL Mobile IPv6. -+ -+ -+ -+ MIPL Mobile IPv6 for Linux Team members (past and present): -+ -+ -+ -+
-+ Sami Kivisaari Sami.Kivisaari@hut.fi -+
-+
-+ -+
-+ Niklas Kampe Niklas.Kampe@hut.fi -+
-+
-+ -+
-+ Juha Mynttinen Juha.Mynttinen@hut.fi -+
-+
-+ -+
-+ Toni Nykanen Toni.Nykanen@iki.fi -+
-+
-+ -+
-+ Henrik Petander Henrik.Petander@hut.fi -+
-+
-+ -+
-+ Antti Tuominen ajtuomin@tml.hut.fi -+
-+
-+
-+ -+ -+ -+
-+ Marko Myllynen -+
-+
-+ -+
-+ Ville Nuorvala vnuorval@tcs.hut.fi -+
-+
-+ -+
-+ Jaakko Laine Jaakko.Laine@hut.fi -+
-+
-+
-+
-+ -+
-+ -+ -+ Common functions for all entities -+ -+ Low-level functions -+ -+ These functions implement memory allocation used by others. -+ Hashlist functions implement a linked list with hash lookup, -+ which is used with Binding Update List, Binding Cache, Home -+ Agents List etc. -+ -+!Inet/ipv6/mobile_ip6/mempool.h -+!Inet/ipv6/mobile_ip6/hashlist.h -+ -+ -+ Debug functions -+ -+ Debug and utility functions. These functions are available if -+ CONFIG_IPV6_MOBILITY_DEBUG is set. -+ Otherwise macros expand to no operation. -+ -+!Inet/ipv6/mobile_ip6/debug.h -+!Inet/ipv6/mobile_ip6/mipv6.c -+ -+ -+ Extension Header functions -+ -+ These functions create and handle extension headers that are -+ specific to MIPv6. -+ -+!Inet/ipv6/mobile_ip6/exthdrs.c -+ -+ -+ Mobility Header functions -+ -+ MIPv6 specifies a new protocol called Mobility Header. -+ Mobility Header has several message types. Messages may also -+ carry Mobility Options. These functions are used to create and -+ handle Mobility Headers and Mobility Options. -+ -+!Inet/ipv6/mobile_ip6/sendopts.c -+!Inet/ipv6/mobile_ip6/mh_recv.c -+!Inet/ipv6/mobile_ip6/auth_subopt.c -+ -+ -+ Binding Cache -+ -+ All Mobile IPv6 entities have a binding cache. These functions -+ provide easy manipulation of the binding cache. -+ -+!Inet/ipv6/mobile_ip6/bcache.c -+ -+ -+ Security -+ -+ -+ These functions are common authentication functions and -+ implement Draft 13 style IPSec AH support for Binding Updates. -+ -+!Inet/ipv6/mobile_ip6/ah_algo.c -+!Inet/ipv6/mobile_ip6/sadb.c -+!Inet/ipv6/mobile_ip6/ah.c -+ -+ -+ Utility functions -+ -+ -+ These functions are general utility functions commonly used by -+ all entities. -+ -+!Inet/ipv6/mobile_ip6/util.c -+ -+ -+ -+ -+ -+ Mobile Node functions -+ General functions -+ -+ -+!Inet/ipv6/mobile_ip6/mn.c -+ -+ -+ Binding Update List -+ -+ Mobile Node keeps track of sent binding updates in Binding -+ Update List. -+ -+!Inet/ipv6/mobile_ip6/bul.c -+ -+ -+ Movement detection -+ -+ -+ These functions are used by the mobile node for movement -+ detection. -+ -+!Inet/ipv6/mobile_ip6/mdetect.c -+ -+ -+ -+ -+ Home Agent functions -+ General functions -+ -+ -+!Inet/ipv6/mobile_ip6/ha.c -+ -+ -+ Duplicate Address Detection functions -+ -+ Home Agent does Duplicate Address Detection for Mobile Nodes' -+ addresses. These functions implement MIPv6 specific DAD -+ functionality. -+ -+!Inet/ipv6/mobile_ip6/dad.c -+ -+ -+ -+ -+ GNU Free Documentation License -+ -+ -+ Version 1.1, March 2000 -+ -+ -+ -+ Copyright (C) 2000 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. -+ -+ -+ 0. PREAMBLE -+ -+ -+ The purpose of this License is to make a manual, textbook, or -+ other written document "free" in the sense of freedom: to -+ assure everyone the effective freedom to copy and redistribute -+ it, with or without modifying it, either commercially or -+ noncommercially. Secondarily, this License preserves for the -+ author and publisher a way to get credit for their work, while -+ not being considered responsible for modifications made by -+ others. -+ -+ -+ -+ This License is a kind of "copyleft", which means that -+ derivative works of the document must themselves be free in the -+ same sense. It complements the GNU General Public License, -+ which is a copyleft license designed for free software. -+ -+ -+ -+ We have designed this License in order to use it for manuals -+ for free software, because free software needs free -+ documentation: a free program should come with manuals -+ providing the same freedoms that the software does. But this -+ License is not limited to software manuals; it can be used for -+ any textual work, regardless of subject matter or whether it is -+ published as a printed book. We recommend this License -+ principally for works whose purpose is instruction or -+ reference. -+ -+ -+ -+ 1. APPLICABILITY AND DEFINITIONS -+ -+ -+ This License applies to any manual or other work that contains -+ a notice placed by the copyright holder saying it can be -+ distributed under the terms of this License. The "Document", -+ below, refers to any such manual or work. Any member of the -+ public is a licensee, and is addressed as "you". -+ -+ -+ -+ A "Modified Version" of the Document means any work containing -+ the Document or a portion of it, either copied verbatim, or -+ with modifications and/or translated into another language. -+ -+ -+ -+ A "Secondary Section" is a named appendix or a front-matter -+ section of the Document that deals exclusively with the -+ relationship of the publishers or authors of the Document to -+ the Document's overall subject (or to related matters) and -+ contains nothing that could fall directly within that overall -+ subject. (For example, if the Document is in part a textbook of -+ mathematics, a Secondary Section may not explain any -+ mathematics.) The relationship could be a matter of historical -+ connection with the subject or with related matters, or of -+ legal, commercial, philosophical, ethical or political position -+ regarding them. -+ -+ -+ -+ The "Invariant Sections" are certain Secondary Sections whose -+ titles are designated, as being those of Invariant Sections, in -+ the notice that says that the Document is released under this -+ License. -+ -+ -+ -+ The "Cover Texts" are certain short passages of text that are -+ listed, as Front-Cover Texts or Back-Cover Texts, in the notice -+ that says that the Document is released under this License. -+ -+ -+ -+ A "Transparent" copy of the Document means a machine-readable -+ copy, represented in a format whose specification is available -+ to the general public, whose contents can be viewed and edited -+ directly and straightforwardly with generic text editors or -+ (for images composed of pixels) generic paint programs or (for -+ drawings) some widely available drawing editor, and that is -+ suitable for input to text formatters or for automatic -+ translation to a variety of formats suitable for input to text -+ formatters. A copy made in an otherwise Transparent file format -+ whose markup has been designed to thwart or discourage -+ subsequent modification by readers is not Transparent. A copy -+ that is not "Transparent" is called "Opaque". -+ -+ -+ -+ Examples of suitable formats for Transparent copies include -+ plain ASCII without markup, Texinfo input format, LaTeX input -+ format, SGML or XML using a publicly available DTD, and -+ standard-conforming simple HTML designed for human -+ modification. Opaque formats include PostScript, PDF, -+ proprietary formats that can be read and edited only by -+ proprietary word processors, SGML or XML for which the DTD -+ and/or processing tools are not generally available, and the -+ machine-generated HTML produced by some word processors for -+ output purposes only. -+ -+ -+ -+ The "Title Page" means, for a printed book, the title page -+ itself, plus such following pages as are needed to hold, -+ legibly, the material this License requires to appear in the -+ title page. For works in formats which do not have any title -+ page as such, "Title Page" means the text near the most -+ prominent appearance of the work's title, preceding the -+ beginning of the body of the text. -+ -+ -+ -+ 2. VERBATIM COPYING -+ -+ -+ You may copy and distribute the Document in any medium, either -+ commercially or noncommercially, provided that this License, -+ the copyright notices, and the license notice saying this -+ License applies to the Document are reproduced in all copies, -+ and that you add no other conditions whatsoever to those of -+ this License. You may not use technical measures to obstruct or -+ control the reading or further copying of the copies you make -+ or distribute. However, you may accept compensation in exchange -+ for copies. If you distribute a large enough number of copies -+ you must also follow the conditions in section 3. -+ -+ -+ -+ You may also lend copies, under the same conditions stated -+ above, and you may publicly display copies. -+ -+ -+ -+ 3. COPYING IN QUANTITY -+ -+ -+ If you publish printed copies of the Document numbering more -+ than 100, and the Document's license notice requires Cover -+ Texts, you must enclose the copies in covers that carry, -+ clearly and legibly, all these Cover Texts: Front-Cover Texts -+ on the front cover, and Back-Cover Texts on the back -+ cover. Both covers must also clearly and legibly identify you -+ as the publisher of these copies. The front cover must present -+ the full title with all words of the title equally prominent -+ and visible. You may add other material on the covers in -+ addition. Copying with changes limited to the covers, as long -+ as they preserve the title of the Document and satisfy these -+ conditions, can be treated as verbatim copying in other -+ respects. -+ -+ -+ -+ If the required texts for either cover are too voluminous to -+ fit legibly, you should put the first ones listed (as many as -+ fit reasonably) on the actual cover, and continue the rest onto -+ adjacent pages. -+ -+ -+ -+ If you publish or distribute Opaque copies of the Document -+ numbering more than 100, you must either include a -+ machine-readable Transparent copy along with each Opaque copy, -+ or state in or with each Opaque copy a publicly-accessible -+ computer-network location containing a complete Transparent -+ copy of the Document, free of added material, which the general -+ network-using public has access to download anonymously at no -+ charge using public-standard network protocols. If you use the -+ latter option, you must take reasonably prudent steps, when you -+ begin distribution of Opaque copies in quantity, to ensure that -+ this Transparent copy will remain thus accessible at the stated -+ location until at least one year after the last time you -+ distribute an Opaque copy (directly or through your agents or -+ retailers) of that edition to the public. -+ -+ -+ -+ It is requested, but not required, that you contact the authors -+ of the Document well before redistributing any large number of -+ copies, to give them a chance to provide you with an updated -+ version of the Document. -+ -+ -+ -+ 4. MODIFICATIONS -+ -+ -+ You may copy and distribute a Modified Version of the Document -+ under the conditions of sections 2 and 3 above, provided that -+ you release the Modified Version under precisely this License, -+ with the Modified Version filling the role of the Document, -+ thus licensing distribution and modification of the Modified -+ Version to whoever possesses a copy of it. In addition, you -+ must do these things in the Modified Version: -+ -+ -+ -+ -+ -+ -+ A. Use in the Title Page (and on the covers, if any) a title -+ distinct from that of the Document, and from those of previous -+ versions (which should, if there were any, be listed in the -+ History section of the Document). You may use the same title -+ as a previous version if the original publisher of that -+ version gives permission. -+ -+ -+ -+ -+ B. List on the Title Page, as authors, one or more persons -+ or entities responsible for authorship of the modifications in -+ the Modified Version, together with at least five of the -+ principal authors of the Document (all of its principal -+ authors, if it has less than five). -+ -+ -+ -+ -+ C. State on the Title page the name of the publisher of the -+ Modified Version, as the publisher. -+ -+ -+ -+ -+ D. Preserve all the copyright notices of the Document. -+ -+ -+ -+ -+ E. Add an appropriate copyright notice for your -+ modifications adjacent to the other copyright notices. -+ -+ -+ -+ -+ F. Include, immediately after the copyright notices, a -+ license notice giving the public permission to use the -+ Modified Version under the terms of this License, in the form -+ shown in the Addendum below. -+ -+ -+ -+ -+ G. Preserve in that license notice the full lists of -+ Invariant Sections and required Cover Texts given in the -+ Document's license notice. -+ -+ -+ -+ -+ H. Include an unaltered copy of this License. -+ -+ -+ -+ -+ I. Preserve the section entitled "History", and its title, -+ and add to it an item stating at least the title, year, new -+ authors, and publisher of the Modified Version as given on the -+ Title Page. If there is no section entitled "History" in the -+ Document, create one stating the title, year, authors, and -+ publisher of the Document as given on its Title Page, then add -+ an item describing the Modified Version as stated in the -+ previous sentence. -+ -+ -+ -+ -+ J. Preserve the network location, if any, given in the -+ Document for public access to a Transparent copy of the -+ Document, and likewise the network locations given in the -+ Document for previous versions it was based on. These may be -+ placed in the "History" section. You may omit a network -+ location for a work that was published at least four years -+ before the Document itself, or if the original publisher of -+ the version it refers to gives permission. -+ -+ -+ -+ -+ K. In any section entitled "Acknowledgements" or -+ "Dedications", preserve the section's title, and preserve in -+ the section all the substance and tone of each of the -+ contributor acknowledgements and/or dedications given therein. -+ -+ -+ -+ -+ L. Preserve all the Invariant Sections of the Document, -+ unaltered in their text and in their titles. Section numbers -+ or the equivalent are not considered part of the section -+ titles. -+ -+ -+ -+ -+ M. Delete any section entitled "Endorsements". Such a -+ section may not be included in the Modified Version. -+ -+ -+ -+ -+ N. Do not retitle any existing section as "Endorsements" or -+ to conflict in title with any Invariant Section. -+ -+ -+ -+ -+ -+ -+ If the Modified Version includes new front-matter sections or -+ appendices that qualify as Secondary Sections and contain no -+ material copied from the Document, you may at your option -+ designate some or all of these sections as invariant. To do -+ this, add their titles to the list of Invariant Sections in the -+ Modified Version's license notice. These titles must be -+ distinct from any other section titles. -+ -+ -+ -+ You may add a section entitled "Endorsements", provided it -+ contains nothing but endorsements of your Modified Version by -+ various parties--for example, statements of peer review or that -+ the text has been approved by an organization as the -+ authoritative definition of a standard. -+ -+ -+ -+ You may add a passage of up to five words as a Front-Cover -+ Text, and a passage of up to 25 words as a Back-Cover Text, to -+ the end of the list of Cover Texts in the Modified -+ Version. Only one passage of Front-Cover Text and one of -+ Back-Cover Text may be added by (or through arrangements made -+ by) any one entity. If the Document already includes a cover -+ text for the same cover, previously added by you or by -+ arrangement made by the same entity you are acting on behalf -+ of, you may not add another; but you may replace the old one, -+ on explicit permission from the previous publisher that added -+ the old one. -+ -+ -+ -+ The author(s) and publisher(s) of the Document do not by this -+ License give permission to use their names for publicity for or -+ to assert or imply endorsement of any Modified Version. -+ -+ -+ -+ 5. COMBINING DOCUMENTS -+ -+ -+ You may combine the Document with other documents released -+ under this License, under the terms defined in section 4 above -+ for modified versions, provided that you include in the -+ combination all of the Invariant Sections of all of the -+ original documents, unmodified, and list them all as Invariant -+ Sections of your combined work in its license notice. -+ -+ -+ -+ The combined work need only contain one copy of this License, -+ and multiple identical Invariant Sections may be replaced with -+ a single copy. If there are multiple Invariant Sections with -+ the same name but different contents, make the title of each -+ such section unique by adding at the end of it, in parentheses, -+ the name of the original author or publisher of that section if -+ known, or else a unique number. Make the same adjustment to the -+ section titles in the list of Invariant Sections in the license -+ notice of the combined work. -+ -+ -+ -+ In the combination, you must combine any sections entitled -+ "History" in the various original documents, forming one -+ section entitled "History"; likewise combine any sections -+ entitled "Acknowledgements", and any sections entitled -+ "Dedications". You must delete all sections entitled -+ "Endorsements." -+ -+ -+ -+ 6. COLLECTIONS OF DOCUMENTS -+ -+ -+ You may make a collection consisting of the Document and other -+ documents released under this License, and replace the -+ individual copies of this License in the various documents with -+ a single copy that is included in the collection, provided that -+ you follow the rules of this License for verbatim copying of -+ each of the documents in all other respects. -+ -+ -+ -+ You may extract a single document from such a collection, and -+ distribute it individually under this License, provided you -+ insert a copy of this License into the extracted document, and -+ follow this License in all other respects regarding verbatim -+ copying of that document. -+ -+ -+ -+ 7. AGGREGATION WITH INDEPENDENT WORKS -+ -+ -+ A compilation of the Document or its derivatives with other -+ separate and independent documents or works, in or on a volume -+ of a storage or distribution medium, does not as a whole count -+ as a Modified Version of the Document, provided no compilation -+ copyright is claimed for the compilation. Such a compilation is -+ called an "aggregate", and this License does not apply to the -+ other self-contained works thus compiled with the Document, on -+ account of their being thus compiled, if they are not -+ themselves derivative works of the Document. -+ -+ -+ -+ If the Cover Text requirement of section 3 is applicable to -+ these copies of the Document, then if the Document is less than -+ one quarter of the entire aggregate, the Document's Cover Texts -+ may be placed on covers that surround only the Document within -+ the aggregate. Otherwise they must appear on covers around the -+ whole aggregate. -+ -+ -+ -+ 8. TRANSLATION -+ -+ -+ Translation is considered a kind of modification, so you may -+ distribute translations of the Document under the terms of -+ section 4. Replacing Invariant Sections with translations -+ requires special permission from their copyright holders, but -+ you may include translations of some or all Invariant Sections -+ in addition to the original versions of these Invariant -+ Sections. You may include a translation of this License -+ provided that you also include the original English version of -+ this License. In case of a disagreement between the translation -+ and the original English version of this License, the original -+ English version will prevail. -+ -+ -+ -+ 9. TERMINATION -+ -+ -+ You may not copy, modify, sublicense, or distribute the -+ Document except as expressly provided for under this -+ License. Any other attempt to copy, modify, sublicense or -+ distribute the Document 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. -+ -+ -+ -+ 10. FUTURE REVISIONS OF THIS LICENSE -+ -+ -+ The Free Software Foundation may publish new, revised versions -+ of the GNU Free Documentation 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. See http://www.gnu.org/copyleft/. -+ -+ -+ -+ Each version of the License is given a distinguishing version -+ number. If the Document specifies that a particular numbered -+ version of this License "or any later version" applies to it, -+ you have the option of following the terms and conditions -+ either of that specified version or of any later version that -+ has been published (not as a draft) by the Free Software -+ Foundation. If the Document does not specify a version number -+ of this License, you may choose any version ever published (not -+ as a draft) by the Free Software Foundation. -+ -+ -+ -+ -+
-diff -uprN linux-2.4.25.old/include/linux/icmpv6.h linux-2.4.25/include/linux/icmpv6.h ---- linux-2.4.25.old/include/linux/icmpv6.h 2003-08-25 12:44:44.000000000 +0100 -+++ linux-2.4.25/include/linux/icmpv6.h 2004-06-26 11:29:29.000000000 +0100 -@@ -40,14 +40,16 @@ struct icmp6hdr { - struct icmpv6_nd_ra { - __u8 hop_limit; - #if defined(__LITTLE_ENDIAN_BITFIELD) -- __u8 reserved:6, -+ __u8 reserved:5, -+ home_agent:1, - other:1, - managed:1; - - #elif defined(__BIG_ENDIAN_BITFIELD) - __u8 managed:1, - other:1, -- reserved:6; -+ home_agent:1, -+ reserved:5; - #else - #error "Please fix " - #endif -@@ -70,6 +72,7 @@ struct icmp6hdr { - #define icmp6_addrconf_managed icmp6_dataun.u_nd_ra.managed - #define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other - #define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime -+#define icmp6_home_agent icmp6_dataun.u_nd_ra.home_agent - }; - - -diff -uprN linux-2.4.25.old/include/linux/if_arp.h linux-2.4.25/include/linux/if_arp.h ---- linux-2.4.25.old/include/linux/if_arp.h 2002-02-25 19:38:13.000000000 +0000 -+++ linux-2.4.25/include/linux/if_arp.h 2004-06-26 11:29:29.000000000 +0100 -@@ -59,7 +59,7 @@ - #define ARPHRD_RAWHDLC 518 /* Raw HDLC */ - - #define ARPHRD_TUNNEL 768 /* IPIP tunnel */ --#define ARPHRD_TUNNEL6 769 /* IPIP6 tunnel */ -+#define ARPHRD_TUNNEL6 769 /* IP6IP6 tunnel */ - #define ARPHRD_FRAD 770 /* Frame Relay Access Device */ - #define ARPHRD_SKIP 771 /* SKIP vif */ - #define ARPHRD_LOOPBACK 772 /* Loopback device */ -diff -uprN linux-2.4.25.old/include/linux/in6.h linux-2.4.25/include/linux/in6.h ---- linux-2.4.25.old/include/linux/in6.h 2003-06-13 15:51:38.000000000 +0100 -+++ linux-2.4.25/include/linux/in6.h 2004-06-26 11:29:29.000000000 +0100 -@@ -142,6 +142,11 @@ struct in6_flowlabel_req - #define IPV6_TLV_JUMBO 194 - - /* -+ * Mobile IPv6 TLV options. -+ */ -+#define MIPV6_TLV_HOMEADDR 201 -+ -+/* - * IPV6 socket options - */ - -diff -uprN linux-2.4.25.old/include/linux/ipv6.h linux-2.4.25/include/linux/ipv6.h ---- linux-2.4.25.old/include/linux/ipv6.h 2003-11-28 18:26:21.000000000 +0000 -+++ linux-2.4.25/include/linux/ipv6.h 2004-06-26 11:29:29.000000000 +0100 -@@ -29,6 +29,7 @@ struct in6_ifreq { - - #define IPV6_SRCRT_STRICT 0x01 /* this hop must be a neighbor */ - #define IPV6_SRCRT_TYPE_0 0 /* IPv6 type 0 Routing Header */ -+#define IPV6_SRCRT_TYPE_2 2 /* type 2 for Mobile IPv6 */ - - /* - * routing header -@@ -71,6 +72,19 @@ struct rt0_hdr { - struct in6_addr addr[0]; - - #define rt0_type rt_hdr.type -+ -+}; -+ -+/* -+ * routing header type 2 -+ */ -+ -+struct rt2_hdr { -+ struct ipv6_rt_hdr rt_hdr; -+ __u32 reserved; -+ struct in6_addr addr; -+ -+#define rt2_type rt_hdr.type; - }; - - /* -@@ -156,12 +170,16 @@ enum { - struct inet6_skb_parm - { - int iif; -+ __u8 mipv6_flags; - __u16 ra; - __u16 hop; - __u16 auth; - __u16 dst0; - __u16 srcrt; -+ __u16 srcrt2; -+ __u16 hao; - __u16 dst1; -+ struct in6_addr hoa; - }; - - #endif -diff -uprN linux-2.4.25.old/include/linux/ipv6_route.h linux-2.4.25/include/linux/ipv6_route.h ---- linux-2.4.25.old/include/linux/ipv6_route.h 2003-11-28 18:26:21.000000000 +0000 -+++ linux-2.4.25/include/linux/ipv6_route.h 2004-06-26 11:29:29.000000000 +0100 -@@ -33,6 +33,7 @@ enum - #define RTF_CACHE 0x01000000 /* cache entry */ - #define RTF_FLOW 0x02000000 /* flow significant route */ - #define RTF_POLICY 0x04000000 /* policy route */ -+#define RTF_MOBILENODE 0x10000000 /* for routing to Mobile Node */ - - #define RTF_LOCAL 0x80000000 - -diff -uprN linux-2.4.25.old/include/linux/ipv6_tunnel.h linux-2.4.25/include/linux/ipv6_tunnel.h ---- linux-2.4.25.old/include/linux/ipv6_tunnel.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/include/linux/ipv6_tunnel.h 2004-06-26 11:29:29.000000000 +0100 -@@ -0,0 +1,34 @@ -+/* -+ * $Id$ -+ */ -+ -+#ifndef _IPV6_TUNNEL_H -+#define _IPV6_TUNNEL_H -+ -+#define IPV6_TLV_TNL_ENCAP_LIMIT 4 -+#define IPV6_DEFAULT_TNL_ENCAP_LIMIT 4 -+ -+/* don't add encapsulation limit if one isn't present in inner packet */ -+#define IP6_TNL_F_IGN_ENCAP_LIMIT 0x1 -+/* copy the traffic class field from the inner packet */ -+#define IP6_TNL_F_USE_ORIG_TCLASS 0x2 -+/* copy the flowlabel from the inner packet */ -+#define IP6_TNL_F_USE_ORIG_FLOWLABEL 0x4 -+/* created and maintained from within the kernel */ -+#define IP6_TNL_F_KERNEL_DEV 0x8 -+/* being used for Mobile IPv6 */ -+#define IP6_TNL_F_MIP6_DEV 0x10 -+ -+struct ip6_tnl_parm { -+ char name[IFNAMSIZ]; /* name of tunnel device */ -+ int link; /* ifindex of underlying L2 interface */ -+ __u8 proto; /* tunnel protocol */ -+ __u8 encap_limit; /* encapsulation limit for tunnel */ -+ __u8 hop_limit; /* hop limit for tunnel */ -+ __u32 flowinfo; /* traffic class and flowlabel for tunnel */ -+ __u32 flags; /* tunnel flags */ -+ struct in6_addr laddr; /* local tunnel end-point address */ -+ struct in6_addr raddr; /* remote tunnel end-point address */ -+}; -+ -+#endif -diff -uprN linux-2.4.25.old/include/linux/rtnetlink.h linux-2.4.25/include/linux/rtnetlink.h ---- linux-2.4.25.old/include/linux/rtnetlink.h 2004-02-18 13:36:32.000000000 +0000 -+++ linux-2.4.25/include/linux/rtnetlink.h 2004-06-26 11:29:29.000000000 +0100 -@@ -309,15 +309,17 @@ enum - IFA_LABEL, - IFA_BROADCAST, - IFA_ANYCAST, -- IFA_CACHEINFO -+ IFA_CACHEINFO, -+ IFA_HOMEAGENT - }; - --#define IFA_MAX IFA_CACHEINFO -+#define IFA_MAX IFA_HOMEAGENT - - /* ifa_flags */ - - #define IFA_F_SECONDARY 0x01 - -+#define IFA_F_HOMEADDR 0x10 - #define IFA_F_DEPRECATED 0x20 - #define IFA_F_TENTATIVE 0x40 - #define IFA_F_PERMANENT 0x80 -diff -uprN linux-2.4.25.old/include/linux/skbuff.h linux-2.4.25/include/linux/skbuff.h ---- linux-2.4.25.old/include/linux/skbuff.h 2003-08-25 12:44:44.000000000 +0100 -+++ linux-2.4.25/include/linux/skbuff.h 2004-06-26 11:29:29.000000000 +0100 -@@ -177,7 +177,7 @@ struct sk_buff { - * want to keep them across layers you have to do a skb_clone() - * first. This is owned by whoever has the skb queued ATM. - */ -- char cb[48]; -+ char cb[64]; - - unsigned int len; /* Length of actual data */ - unsigned int data_len; -diff -uprN linux-2.4.25.old/include/linux/sysctl.h linux-2.4.25/include/linux/sysctl.h ---- linux-2.4.25.old/include/linux/sysctl.h 2004-02-18 13:36:32.000000000 +0000 -+++ linux-2.4.25/include/linux/sysctl.h 2004-06-26 11:29:29.000000000 +0100 -@@ -387,7 +387,24 @@ enum { - NET_IPV6_NEIGH=17, - NET_IPV6_ROUTE=18, - NET_IPV6_ICMP=19, -- NET_IPV6_BINDV6ONLY=20 -+ NET_IPV6_BINDV6ONLY=20, -+ NET_IPV6_MOBILITY=26 -+}; -+ -+/* /proc/sys/net/ipv6/mobility */ -+enum { -+ NET_IPV6_MOBILITY_DEBUG=1, -+ NET_IPV6_MOBILITY_TUNNEL_SITELOCAL=2, -+ NET_IPV6_MOBILITY_ROUTER_SOLICITATION_MAX_SENDTIME=3, -+ NET_IPV6_MOBILITY_ROUTER_REACH=4, -+ NET_IPV6_MOBILITY_MDETECT_MECHANISM=5, -+ NET_IPV6_MOBILITY_RETROUT=6, -+ NET_IPV6_MOBILITY_MAX_TNLS=7, -+ NET_IPV6_MOBILITY_MIN_TNLS=8, -+ NET_IPV6_MOBILITY_BINDING_REFRESH=9, -+ NET_IPV6_MOBILITY_BU_F_LLADDR=10, -+ NET_IPV6_MOBILITY_BU_F_KEYMGM=11, -+ NET_IPV6_MOBILITY_BU_F_CN_ACK=12 - }; - - enum { -diff -uprN linux-2.4.25.old/include/net/addrconf.h linux-2.4.25/include/net/addrconf.h ---- linux-2.4.25.old/include/net/addrconf.h 2003-08-25 12:44:44.000000000 +0100 -+++ linux-2.4.25/include/net/addrconf.h 2004-06-26 11:29:29.000000000 +0100 -@@ -16,9 +16,11 @@ struct prefix_info { - #if defined(__BIG_ENDIAN_BITFIELD) - __u8 onlink : 1, - autoconf : 1, -- reserved : 6; -+ router_address : 1, -+ reserved : 5; - #elif defined(__LITTLE_ENDIAN_BITFIELD) -- __u8 reserved : 6, -+ __u8 reserved : 5, -+ router_address : 1, - autoconf : 1, - onlink : 1; - #else -@@ -55,6 +57,7 @@ extern int ipv6_chk_addr(struct in6_ad - struct net_device *dev); - extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, - struct net_device *dev); -+extern void ipv6_del_addr(struct inet6_ifaddr *ifp); - extern int ipv6_get_saddr(struct dst_entry *dst, - struct in6_addr *daddr, - struct in6_addr *saddr); -@@ -85,7 +88,9 @@ extern void ipv6_mc_up(struct inet6_dev - extern void ipv6_mc_down(struct inet6_dev *idev); - extern void ipv6_mc_init_dev(struct inet6_dev *idev); - extern void ipv6_mc_destroy_dev(struct inet6_dev *idev); -+extern void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags); - extern void addrconf_dad_failure(struct inet6_ifaddr *ifp); -+extern void addrconf_dad_completed(struct inet6_ifaddr *ifp); - - extern int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group, - struct in6_addr *src_addr); -@@ -116,6 +121,9 @@ extern int ipv6_chk_acast_addr(struct - extern int register_inet6addr_notifier(struct notifier_block *nb); - extern int unregister_inet6addr_notifier(struct notifier_block *nb); - -+extern int ipv6_generate_eui64(u8 *eui, struct net_device *dev); -+extern int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev); -+ - static inline struct inet6_dev * - __in6_dev_get(struct net_device *dev) - { -diff -uprN linux-2.4.25.old/include/net/ip6_route.h linux-2.4.25/include/net/ip6_route.h ---- linux-2.4.25.old/include/net/ip6_route.h 2003-06-13 15:51:39.000000000 +0100 -+++ linux-2.4.25/include/net/ip6_route.h 2004-06-26 11:29:29.000000000 +0100 -@@ -2,6 +2,7 @@ - #define _NET_IP6_ROUTE_H - - #define IP6_RT_PRIO_FW 16 -+#define IP6_RT_PRIO_MIPV6 64 - #define IP6_RT_PRIO_USER 1024 - #define IP6_RT_PRIO_ADDRCONF 256 - #define IP6_RT_PRIO_KERN 512 -@@ -40,6 +41,9 @@ extern int ipv6_route_ioctl(unsigned i - - extern int ip6_route_add(struct in6_rtmsg *rtmsg, - struct nlmsghdr *); -+ -+extern int ip6_route_del(struct in6_rtmsg *rtmsg, -+ struct nlmsghdr *); - extern int ip6_del_rt(struct rt6_info *, - struct nlmsghdr *); - -@@ -99,7 +103,8 @@ extern rwlock_t rt6_lock; - */ - - static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, -- struct in6_addr *daddr) -+ struct in6_addr *daddr, -+ struct in6_addr *saddr) - { - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; - struct rt6_info *rt = (struct rt6_info *) dst; -@@ -107,6 +112,9 @@ static inline void ip6_dst_store(struct - write_lock(&sk->dst_lock); - __sk_dst_set(sk, dst); - np->daddr_cache = daddr; -+#ifdef CONFIG_IPV6_SUBTREES -+ np->saddr_cache = saddr; -+#endif - np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; - write_unlock(&sk->dst_lock); - } -diff -uprN linux-2.4.25.old/include/net/ipv6.h linux-2.4.25/include/net/ipv6.h ---- linux-2.4.25.old/include/net/ipv6.h 2003-11-28 18:26:21.000000000 +0000 -+++ linux-2.4.25/include/net/ipv6.h 2004-06-26 11:29:29.000000000 +0100 -@@ -37,6 +37,7 @@ - #define NEXTHDR_ICMP 58 /* ICMP for IPv6. */ - #define NEXTHDR_NONE 59 /* No next header */ - #define NEXTHDR_DEST 60 /* Destination options header. */ -+#define NEXTHDR_MH 135 /* Mobility header, RFC 3775 */ - - #define NEXTHDR_MAX 255 - -@@ -145,9 +146,12 @@ struct ipv6_txoptions - __u16 opt_flen; /* after fragment hdr */ - __u16 opt_nflen; /* before fragment hdr */ - -+ __u8 mipv6_flags; /* flags set by MIPv6 */ -+ - struct ipv6_opt_hdr *hopopt; - struct ipv6_opt_hdr *dst0opt; -- struct ipv6_rt_hdr *srcrt; /* Routing Header */ -+ struct ipv6_rt_hdr *srcrt; /* Routing Header Type 0 */ -+ struct ipv6_rt_hdr *srcrt2; /* Routing Header Type 2 */ - struct ipv6_opt_hdr *auth; - struct ipv6_opt_hdr *dst1opt; - -@@ -256,6 +260,38 @@ static inline int ipv6_addr_any(const st - a->s6_addr32[2] | a->s6_addr32[3] ) == 0); - } - -+static inline void ipv6_addr_prefix(struct in6_addr *pfx, -+ const struct in6_addr *addr, int plen) -+{ -+ /* caller must guarantee 0 <= plen <= 128 */ -+ int o = plen >> 3, -+ b = plen & 0x7; -+ -+ memcpy(pfx->s6_addr, addr, o); -+ if (b != 0) { -+ pfx->s6_addr[o] = addr->s6_addr[o] & (0xff00 >> b); -+ o++; -+ } -+ if (o < 16) -+ memset(pfx->s6_addr + o, 0, 16 - o); -+} -+ -+static inline int ipv6_prefix_cmp(const struct in6_addr *p1, -+ const struct in6_addr *p2, int plen) -+{ -+ int b = plen&0x7; -+ int o = plen>>3; -+ int res = 0; -+ -+ if (o > 0) -+ res = memcmp(&p1->s6_addr[0], &p2->s6_addr[0], o); -+ if (res == 0 && b > 0) { -+ __u8 m = (0xff00 >> b) & 0xff; -+ res = (p1->s6_addr[o] & m) - (p2->s6_addr[o] & m); -+ } -+ return res; -+} -+ - /* - * Prototypes exported by ipv6 - */ -diff -uprN linux-2.4.25.old/include/net/ipv6_tunnel.h linux-2.4.25/include/net/ipv6_tunnel.h ---- linux-2.4.25.old/include/net/ipv6_tunnel.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/include/net/ipv6_tunnel.h 2004-06-26 11:29:29.000000000 +0100 -@@ -0,0 +1,92 @@ -+/* -+ * $Id$ -+ */ -+ -+#ifndef _NET_IPV6_TUNNEL_H -+#define _NET_IPV6_TUNNEL_H -+ -+#include -+#include -+#include -+#include -+#include -+ -+/* capable of sending packets */ -+#define IP6_TNL_F_CAP_XMIT 0x10000 -+/* capable of receiving packets */ -+#define IP6_TNL_F_CAP_RCV 0x20000 -+ -+#define IP6_TNL_MAX 128 -+ -+/* IPv6 tunnel */ -+ -+struct ip6_tnl { -+ struct ip6_tnl *next; /* next tunnel in list */ -+ struct net_device *dev; /* virtual device associated with tunnel */ -+ struct net_device_stats stat; /* statistics for tunnel device */ -+ int recursion; /* depth of hard_start_xmit recursion */ -+ struct ip6_tnl_parm parms; /* tunnel configuration paramters */ -+ struct flowi fl; /* flowi template for xmit */ -+ atomic_t refcnt; /* nr of identical tunnels used by kernel */ -+ struct socket *sock; -+}; -+ -+#define IP6_TNL_PRE_ENCAP 0 -+#define IP6_TNL_PRE_DECAP 1 -+#define IP6_TNL_MAXHOOKS 2 -+ -+#define IP6_TNL_DROP 0 -+#define IP6_TNL_ACCEPT 1 -+ -+typedef int ip6_tnl_hookfn(struct ip6_tnl *t, struct sk_buff *skb); -+ -+struct ip6_tnl_hook_ops { -+ struct list_head list; -+ unsigned int hooknum; -+ int priority; -+ ip6_tnl_hookfn *hook; -+}; -+ -+enum ip6_tnl_hook_priorities { -+ IP6_TNL_PRI_FIRST = INT_MIN, -+ IP6_TNL_PRI_LAST = INT_MAX -+}; -+ -+/* Tunnel encapsulation limit destination sub-option */ -+ -+struct ipv6_tlv_tnl_enc_lim { -+ __u8 type; /* type-code for option */ -+ __u8 length; /* option length */ -+ __u8 encap_limit; /* tunnel encapsulation limit */ -+} __attribute__ ((packed)); -+ -+#ifdef __KERNEL__ -+extern int ip6ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt); -+ -+extern struct ip6_tnl *ip6ip6_tnl_lookup(struct in6_addr *remote, -+ struct in6_addr *local); -+ -+void ip6ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p); -+ -+extern int ip6ip6_kernel_tnl_add(struct ip6_tnl_parm *p); -+ -+extern int ip6ip6_kernel_tnl_del(struct ip6_tnl *t); -+ -+extern unsigned int ip6ip6_tnl_inc_max_kdev_count(unsigned int n); -+ -+extern unsigned int ip6ip6_tnl_dec_max_kdev_count(unsigned int n); -+ -+extern unsigned int ip6ip6_tnl_inc_min_kdev_count(unsigned int n); -+ -+extern unsigned int ip6ip6_tnl_dec_min_kdev_count(unsigned int n); -+ -+extern void ip6ip6_tnl_register_hook(struct ip6_tnl_hook_ops *reg); -+ -+extern void ip6ip6_tnl_unregister_hook(struct ip6_tnl_hook_ops *reg); -+ -+#ifdef CONFIG_IPV6_TUNNEL -+extern int __init ip6_tunnel_init(void); -+extern void ip6_tunnel_cleanup(void); -+#endif -+#endif -+#endif -diff -uprN linux-2.4.25.old/include/net/mipglue.h linux-2.4.25/include/net/mipglue.h ---- linux-2.4.25.old/include/net/mipglue.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/include/net/mipglue.h 2004-06-26 11:29:29.000000000 +0100 -@@ -0,0 +1,266 @@ -+/* -+ * Glue for Mobility support integration to IPv6 -+ * -+ * Authors: -+ * Antti Tuominen -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _NET_MIPGLUE_H -+#define _NET_MIPGLUE_H -+ -+#ifndef USE_IPV6_MOBILITY -+#if defined(CONFIG_IPV6_MOBILITY) || defined(CONFIG_IPV6_MOBILITY_MODULE) -+#define USE_IPV6_MOBILITY -+#endif -+#endif -+ -+/* symbols to indicate whether destination options received should take -+ * effect or not (see exthdrs.c, procrcv.c) -+ */ -+#define MIPV6_DSTOPTS_ACCEPT 1 -+#define MIPV6_DSTOPTS_DISCARD 0 -+ -+#define MIPV6_IGN_RTR 0 -+#define MIPV6_ADD_RTR 1 -+#define MIPV6_CHG_RTR 2 -+ -+/* MIPV6: Approximate maximum for mobile IPv6 options and headers */ -+#define MIPV6_HEADERS 48 -+ -+#ifdef __KERNEL__ -+#include -+#include -+#include -+ -+struct sk_buff; -+struct ndisc_options; -+struct sock; -+struct ipv6_txoptions; -+struct flowi; -+struct dst_entry; -+struct in6_addr; -+struct inet6_ifaddr; -+ -+#ifdef USE_IPV6_MOBILITY -+ -+/* calls a procedure from mipv6-module */ -+#define MIPV6_CALLPROC(X) if(mipv6_functions.X) mipv6_functions.X -+ -+/* calls a function from mipv6-module, default-value if function not defined -+ */ -+#define MIPV6_CALLFUNC(X,Y) (!mipv6_functions.X)?(Y):mipv6_functions.X -+ -+/* sets a handler-function to process a call */ -+#define MIPV6_SETCALL(X,Y) if(mipv6_functions.X) printk("mipv6: Warning, function assigned twice!\n"); \ -+ mipv6_functions.X = Y -+#define MIPV6_RESETCALL(X) mipv6_functions.X = NULL -+ -+/* pointers to mipv6 callable functions */ -+struct mipv6_callable_functions { -+ void (*mipv6_initialize_dstopt_rcv) (struct sk_buff *skb); -+ int (*mipv6_finalize_dstopt_rcv) (int process); -+ int (*mipv6_handle_homeaddr) (struct sk_buff *skb, int optoff); -+ int (*mipv6_ra_rcv) (struct sk_buff *skb, -+ struct ndisc_options *ndopts); -+ void (*mipv6_icmp_rcv) (struct sk_buff *skb); -+ struct ipv6_txoptions * (*mipv6_modify_txoptions) ( -+ struct sock *sk, -+ struct sk_buff *skb, -+ struct ipv6_txoptions *opt, -+ struct flowi *fl, -+ struct dst_entry **dst); -+ void (*mipv6_set_home) (int ifindex, struct in6_addr *homeaddr, -+ int plen, struct in6_addr *homeagent, -+ int plen2); -+ void (*mipv6_get_home_address) (struct in6_addr *home_addr); -+ void (*mipv6_get_care_of_address)(struct in6_addr *homeaddr, -+ struct in6_addr *coa); -+ int (*mipv6_is_home_addr)(struct in6_addr *addr); -+ void (*mipv6_change_router)(void); -+ void (*mipv6_check_dad)(struct in6_addr *home_addr); -+ void (*mipv6_icmp_swap_addrs)(struct sk_buff *skb); -+ int (*mipv6_forward)(struct sk_buff *skb); -+ int (*mipv6_mn_ha_probe)(struct inet6_ifaddr *ifp, u8 *lladdr); -+}; -+ -+extern struct mipv6_callable_functions mipv6_functions; -+ -+extern void mipv6_invalidate_calls(void); -+ -+extern int mipv6_handle_dstopt(struct sk_buff *skb, int optoff); -+ -+static inline int -+ndisc_mip_mn_ha_probe(struct inet6_ifaddr *ifp, u8 *lladdr) -+{ -+ return MIPV6_CALLFUNC(mipv6_mn_ha_probe, 0)(ifp, lladdr); -+} -+ -+/* Must only be called for HA, no checks here */ -+static inline int ip6_mipv6_forward(struct sk_buff *skb) -+{ -+ return MIPV6_CALLFUNC(mipv6_forward, 0)(skb); -+} -+ -+/* -+ * Avoid adding new default routers if the old one is still in use -+ */ -+ -+static inline int ndisc_mipv6_ra_rcv(struct sk_buff *skb, -+ struct ndisc_options *ndopts) -+{ -+ return MIPV6_CALLFUNC(mipv6_ra_rcv, MIPV6_ADD_RTR)(skb, ndopts); -+} -+ -+static inline int ipv6_chk_mip_home_addr(struct in6_addr *addr) -+{ -+ return MIPV6_CALLFUNC(mipv6_is_home_addr, 0)(addr); -+} -+ -+static inline void ndisc_mipv6_change_router(int change_rtr) -+{ -+ if (change_rtr == MIPV6_CHG_RTR) -+ MIPV6_CALLPROC(mipv6_change_router)(); -+} -+ -+static inline void ndisc_check_mipv6_dad(struct in6_addr *target) -+{ -+ MIPV6_CALLPROC(mipv6_check_dad)(target); -+} -+ -+static inline void icmpv6_swap_mipv6_addrs(struct sk_buff *skb) -+{ -+ MIPV6_CALLPROC(mipv6_icmp_swap_addrs)(skb); -+} -+ -+static inline void mipv6_icmp_rcv(struct sk_buff *skb) -+{ -+ MIPV6_CALLPROC(mipv6_icmp_rcv)(skb); -+} -+ -+static inline int tcp_v6_get_mipv6_header_len(void) -+{ -+ return MIPV6_HEADERS; -+} -+ -+static inline struct in6_addr * -+mipv6_get_fake_hdr_daddr(struct in6_addr *hdaddr, struct in6_addr *daddr) -+{ -+ return daddr; -+} -+ -+static inline void -+addrconf_set_mipv6_mn_home(int ifindex, struct in6_addr *homeaddr, int plen, -+ struct in6_addr *homeagent, int plen2) -+{ -+ MIPV6_CALLPROC(mipv6_set_home)(ifindex, homeaddr, plen, homeagent, plen2); -+} -+ -+static inline void addrconf_get_mipv6_home_address(struct in6_addr *saddr) -+{ -+ MIPV6_CALLPROC(mipv6_get_home_address)(saddr); -+} -+ -+static inline struct ipv6_txoptions * -+ip6_add_mipv6_txoptions(struct sock *sk, struct sk_buff *skb, -+ struct ipv6_txoptions *opt, struct flowi *fl, -+ struct dst_entry **dst) -+{ -+ return MIPV6_CALLFUNC(mipv6_modify_txoptions, opt)(sk, skb, opt, fl, dst); -+ -+} -+ -+static inline void -+ip6_mark_mipv6_packet(struct ipv6_txoptions *txopt, struct sk_buff *skb) -+{ -+ struct inet6_skb_parm *opt; -+ if (txopt) { -+ opt = (struct inet6_skb_parm *)skb->cb; -+ opt->mipv6_flags = txopt->mipv6_flags; -+ } -+} -+ -+static inline void -+ip6_free_mipv6_txoptions(struct ipv6_txoptions *opt, -+ struct ipv6_txoptions *orig_opt) -+{ -+ if (opt && opt != orig_opt) -+ kfree(opt); -+} -+ -+#else /* USE_IPV6_MOBILITY */ -+ -+#define mipv6_handle_dstopt ip6_tlvopt_unknown -+ -+static inline int -+ndisc_mip_mn_ha_probe(struct inet6_ifaddr *ifp, u8 *lladdr) -+{ -+ return 0; -+} -+ -+static inline int ip6_mipv6_forward(struct sk_buff *skb) -+{ -+ return 0; -+} -+ -+static inline int ndisc_mipv6_ra_rcv(struct sk_buff *skb, -+ struct ndisc_options *ndopts) -+{ -+ return MIPV6_ADD_RTR; -+} -+ -+static inline int ipv6_chk_mip_home_addr(struct in6_addr *addr) -+{ -+ return 0; -+} -+ -+static inline void ndisc_mipv6_change_router(int change_rtr) {} -+ -+static inline void ndisc_check_mipv6_dad(struct in6_addr *target) {} -+ -+static inline void icmpv6_swap_mipv6_addrs(struct sk_buff *skb) {} -+ -+static inline void mipv6_icmp_rcv(struct sk_buff *skb) {} -+ -+static inline int tcp_v6_get_mipv6_header_len(void) -+{ -+ return 0; -+} -+ -+static inline struct in6_addr * -+mipv6_get_fake_hdr_daddr(struct in6_addr *hdaddr, struct in6_addr *daddr) -+{ -+ return hdaddr; -+} -+ -+static inline void -+addrconf_set_mipv6_mn_home(int ifindex, struct in6_addr *homeaddr, int plen, -+ struct in6_addr *homeagent, int plen2) {} -+ -+static inline void addrconf_get_mipv6_home_address(struct in6_addr *saddr) {} -+ -+static inline struct ipv6_txoptions * -+ip6_add_mipv6_txoptions(struct sock *sk, struct sk_buff *skb, -+ struct ipv6_txoptions *opt, struct flowi *fl, -+ struct dst_entry **dst) -+{ -+ return opt; -+} -+ -+static inline void -+ip6_mark_mipv6_packet(struct ipv6_txoptions *txopt, struct sk_buff *skb) {} -+ -+static inline void -+ip6_free_mipv6_txoptions(struct ipv6_txoptions *opt, -+ struct ipv6_txoptions *orig_opt) {} -+ -+#endif /* USE_IPV6_MOBILITY */ -+#endif /* __KERNEL__ */ -+#endif /* _NET_MIPGLUE_H */ -diff -uprN linux-2.4.25.old/include/net/mipv6.h linux-2.4.25/include/net/mipv6.h ---- linux-2.4.25.old/include/net/mipv6.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/include/net/mipv6.h 2004-06-26 11:29:29.000000000 +0100 -@@ -0,0 +1,258 @@ -+/* -+ * Mobile IPv6 header-file -+ * -+ * Authors: -+ * Sami Kivisaari -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _NET_MIPV6_H -+#define _NET_MIPV6_H -+ -+#include -+#include -+#include -+ -+/* -+ * -+ * Mobile IPv6 Protocol constants -+ * -+ */ -+#define DHAAD_RETRIES 4 /* transmissions */ -+#define INITIAL_BINDACK_TIMEOUT 1 /* seconds */ -+#define INITIAL_DHAAD_TIMEOUT 3 /* seconds */ -+#define INITIAL_SOLICIT_TIMER 3 /* seconds */ -+#define MAX_BINDACK_TIMEOUT 32 /* seconds */ -+#define MAX_NONCE_LIFE 240 /* seconds */ -+#define MAX_TOKEN_LIFE 210 /* seconds */ -+#define MAX_RR_BINDING_LIFE 420 /* seconds */ -+#define MAX_UPDATE_RATE 3 /* 1/s (min delay=1s) */ -+#define PREFIX_ADV_RETRIES 3 /* transmissions */ -+#define PREFIX_ADV_TIMEOUT 3 /* seconds */ -+ -+#define MAX_FAST_UPDATES 5 /* transmissions */ -+#define MAX_PFX_ADV_DELAY 1000 /* seconds */ -+#define SLOW_UPDATE_RATE 10 /* 1/10s (max delay=10s)*/ -+#define INITIAL_BINDACK_DAD_TIMEOUT 2 /* seconds */ -+ -+/* -+ * -+ * Mobile IPv6 (RFC 3775) Protocol configuration variable defaults -+ * -+ */ -+#define DefHomeRtrAdvInterval 1000 /* seconds */ -+#define DefMaxMobPfxAdvInterval 86400 /* seconds */ -+#define DefMinDelayBetweenRAs 3 /* seconds (min 0.03) */ -+#define DefMinMobPfxAdvInterval 600 /* seconds */ -+#define DefInitialBindackTimeoutFirstReg 1.5 /* seconds */ -+ -+/* This is not actually specified in the draft, but is needed to avoid -+ * prefix solicitation storm when valid lifetime of a prefix is smaller -+ * than MAX_PFX_ADV_DELAY -+ */ -+#define MIN_PFX_SOL_DELAY 5 /* seconds */ -+ -+/* Mobile IPv6 ICMP types */ -+/* -+ * Official numbers from RFC 3775 -+ */ -+#define MIPV6_DHAAD_REQUEST 144 -+#define MIPV6_DHAAD_REPLY 145 -+#define MIPV6_PREFIX_SOLICIT 146 -+#define MIPV6_PREFIX_ADV 147 -+ -+/* Binding update flag codes */ -+#define MIPV6_BU_F_ACK 0x80 -+#define MIPV6_BU_F_HOME 0x40 -+#define MIPV6_BU_F_LLADDR 0x20 -+#define MIPV6_BU_F_KEYMGM 0x10 -+ -+/* Binding ackknowledgment flag codes */ -+#define MIPV6_BA_F_KEYMGM 0x80 -+ -+/* Binding error status */ -+#define MIPV6_BE_HAO_WO_BINDING 1 -+#define MIPV6_BE_UNKNOWN_MH_TYPE 2 -+ -+/* Mobility Header */ -+struct mipv6_mh -+{ -+ __u8 payload; /* Payload Protocol */ -+ __u8 length; /* MH Length */ -+ __u8 type; /* MH Type */ -+ __u8 reserved; /* Reserved */ -+ __u16 checksum; /* Checksum */ -+ __u8 data[0]; /* Message specific data */ -+} __attribute__ ((packed)); -+ -+/* Mobility Header type */ -+#define IPPROTO_MOBILITY 135 /* RFC 3775*/ -+/* Mobility Header Message Types */ -+ -+#define MIPV6_MH_BRR 0 -+#define MIPV6_MH_HOTI 1 -+#define MIPV6_MH_COTI 2 -+#define MIPV6_MH_HOT 3 -+#define MIPV6_MH_COT 4 -+#define MIPV6_MH_BU 5 -+#define MIPV6_MH_BA 6 -+#define MIPV6_MH_BE 7 -+ -+/* -+ * Status codes for Binding Acknowledgements -+ */ -+#define SUCCESS 0 -+#define REASON_UNSPECIFIED 128 -+#define ADMINISTRATIVELY_PROHIBITED 129 -+#define INSUFFICIENT_RESOURCES 130 -+#define HOME_REGISTRATION_NOT_SUPPORTED 131 -+#define NOT_HOME_SUBNET 132 -+#define NOT_HA_FOR_MN 133 -+#define DUPLICATE_ADDR_DETECT_FAIL 134 -+#define SEQUENCE_NUMBER_OUT_OF_WINDOW 135 -+#define EXPIRED_HOME_NONCE_INDEX 136 -+#define EXPIRED_CAREOF_NONCE_INDEX 137 -+#define EXPIRED_NONCES 138 -+#define REG_TYPE_CHANGE_FORBIDDEN 139 -+/* -+ * Values for mipv6_flags in struct inet6_skb_parm -+ */ -+ -+#define MIPV6_RCV_TUNNEL 0x1 -+#define MIPV6_SND_HAO 0x2 -+#define MIPV6_SND_BU 0x4 -+ -+/* -+ * Mobility Header Message structures -+ */ -+ -+struct mipv6_mh_brr -+{ -+ __u16 reserved; -+ /* Mobility options */ -+} __attribute__ ((packed)); -+ -+struct mipv6_mh_bu -+{ -+ __u16 sequence; /* sequence number of BU */ -+ __u8 flags; /* flags */ -+ __u8 reserved; /* reserved bits */ -+ __u16 lifetime; /* lifetime of BU */ -+ /* Mobility options */ -+} __attribute__ ((packed)); -+ -+struct mipv6_mh_ba -+{ -+ __u8 status; /* statuscode */ -+ __u8 reserved; /* reserved bits */ -+ __u16 sequence; /* sequence number of BA */ -+ __u16 lifetime; /* lifetime in CN's bcache */ -+ /* Mobility options */ -+} __attribute__ ((packed)); -+ -+struct mipv6_mh_be -+{ -+ __u8 status; -+ __u8 reserved; -+ struct in6_addr home_addr; -+ /* Mobility options */ -+} __attribute__ ((packed)); -+ -+struct mipv6_mh_addr_ti -+{ -+ __u16 reserved; /* Reserved */ -+ u_int8_t init_cookie[8]; /* HoT/CoT Init Cookie */ -+ /* Mobility options */ -+} __attribute__ ((packed)); -+ -+struct mipv6_mh_addr_test -+{ -+ __u16 nonce_index; /* Home/Care-of Nonce Index */ -+ u_int8_t init_cookie[8]; /* HoT/CoT Init Cookie */ -+ u_int8_t kgen_token[8]; /* Home/Care-of key generation token */ -+ /* Mobility options */ -+} __attribute__ ((packed)); -+ -+/* -+ * Mobility Options for various MH types. -+ */ -+#define MIPV6_OPT_PAD1 0x00 -+#define MIPV6_OPT_PADN 0x01 -+#define MIPV6_OPT_BIND_REFRESH_ADVICE 0x02 -+#define MIPV6_OPT_ALTERNATE_COA 0x03 -+#define MIPV6_OPT_NONCE_INDICES 0x04 -+#define MIPV6_OPT_AUTH_DATA 0x05 -+ -+#define MIPV6_SEQ_GT(x,y) \ -+ ((short int)(((__u16)(x)) - ((__u16)(y))) > 0) -+ -+/* -+ * Mobility Option structures -+ */ -+ -+struct mipv6_mo -+{ -+ __u8 type; -+ __u8 length; -+ __u8 value[0]; /* type specific data */ -+} __attribute__ ((packed)); -+ -+struct mipv6_mo_pad1 -+{ -+ __u8 type; -+} __attribute__ ((packed)); -+ -+struct mipv6_mo_padn -+{ -+ __u8 type; -+ __u8 length; -+ __u8 data[0]; -+} __attribute__ ((packed)); -+ -+struct mipv6_mo_alt_coa -+{ -+ __u8 type; -+ __u8 length; -+ struct in6_addr addr; /* alternate care-of-address */ -+} __attribute__ ((packed)); -+ -+struct mipv6_mo_nonce_indices -+{ -+ __u8 type; -+ __u8 length; -+ __u16 home_nonce_i; /* Home Nonce Index */ -+ __u16 careof_nonce_i; /* Careof Nonce Index */ -+} __attribute__ ((packed)); -+ -+struct mipv6_mo_bauth_data -+{ -+ __u8 type; -+ __u8 length; -+ __u8 data[0]; -+} __attribute__ ((packed)); -+ -+struct mipv6_mo_br_advice -+{ -+ __u8 type; -+ __u8 length; -+ __u16 refresh_interval; /* Refresh Interval */ -+} __attribute__ ((packed)); -+ -+/* -+ * Home Address Destination Option structure -+ */ -+struct mipv6_dstopt_homeaddr -+{ -+ __u8 type; /* type-code for option */ -+ __u8 length; /* option length */ -+ struct in6_addr addr; /* home address */ -+} __attribute__ ((packed)); -+ -+#endif /* _NET_MIPV6_H */ -diff -uprN linux-2.4.25.old/include/net/ndisc.h linux-2.4.25/include/net/ndisc.h ---- linux-2.4.25.old/include/net/ndisc.h 2002-11-28 23:53:15.000000000 +0000 -+++ linux-2.4.25/include/net/ndisc.h 2004-06-26 11:29:29.000000000 +0100 -@@ -21,6 +21,10 @@ - #define ND_OPT_REDIRECT_HDR 4 - #define ND_OPT_MTU 5 - -+/* Mobile IPv6 specific ndisc options */ -+#define ND_OPT_RTR_ADV_INTERVAL 7 -+#define ND_OPT_HOME_AGENT_INFO 8 -+ - #define MAX_RTR_SOLICITATION_DELAY HZ - - #define ND_REACHABLE_TIME (30*HZ) -@@ -57,7 +61,7 @@ struct nd_opt_hdr { - } __attribute__((__packed__)); - - struct ndisc_options { -- struct nd_opt_hdr *nd_opt_array[7]; -+ struct nd_opt_hdr *nd_opt_array[10]; - struct nd_opt_hdr *nd_opt_piend; - }; - -@@ -67,6 +71,8 @@ struct ndisc_options { - #define nd_opts_pi_end nd_opt_piend - #define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR] - #define nd_opts_mtu nd_opt_array[ND_OPT_MTU] -+#define nd_opts_rai nd_opt_array[ND_OPT_RTR_ADV_INTERVAL] -+#define nd_opts_hai nd_opt_array[ND_OPT_HOME_AGENT_INFO] - - extern struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur, struct nd_opt_hdr *end); - extern struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, struct ndisc_options *ndopts); -@@ -83,6 +89,15 @@ extern void ndisc_send_ns(struct net_d - struct in6_addr *daddr, - struct in6_addr *saddr); - -+extern void ndisc_send_na(struct net_device *dev, -+ struct neighbour *neigh, -+ struct in6_addr *daddr, -+ struct in6_addr *solicited_addr, -+ int router, -+ int solicited, -+ int override, -+ int inc_opt); -+ - extern void ndisc_send_rs(struct net_device *dev, - struct in6_addr *saddr, - struct in6_addr *daddr); -diff -uprN linux-2.4.25.old/include/net/sock.h linux-2.4.25/include/net/sock.h ---- linux-2.4.25.old/include/net/sock.h 2004-02-18 13:36:32.000000000 +0000 -+++ linux-2.4.25/include/net/sock.h 2004-06-26 11:29:30.000000000 +0100 -@@ -149,7 +149,9 @@ struct ipv6_pinfo { - struct in6_addr rcv_saddr; - struct in6_addr daddr; - struct in6_addr *daddr_cache; -- -+#if defined(CONFIG_IPV6_SUBTREES) -+ struct in6_addr *saddr_cache; -+#endif - __u32 flow_label; - __u32 frag_size; - int hop_limit; -diff -uprN linux-2.4.25.old/net/Makefile linux-2.4.25/net/Makefile ---- linux-2.4.25.old/net/Makefile 2004-06-26 11:22:00.000000000 +0100 -+++ linux-2.4.25/net/Makefile 2004-06-26 11:29:30.000000000 +0100 -@@ -7,7 +7,7 @@ - - O_TARGET := network.o - --mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink sched core sctp -+mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink sched core sctp ipv6 - export-objs := netsyms.o - - subdir-y := core ethernet -@@ -25,6 +25,7 @@ subdir-$(CONFIG_IP_SCTP) += sctp - ifneq ($(CONFIG_IPV6),n) - ifneq ($(CONFIG_IPV6),) - subdir-$(CONFIG_NETFILTER) += ipv6/netfilter -+subdir-$(CONFIG_IPV6_MOBILITY) += ipv6/mobile_ip6 - endif - endif - -diff -uprN linux-2.4.25.old/net/core/neighbour.c linux-2.4.25/net/core/neighbour.c ---- linux-2.4.25.old/net/core/neighbour.c 2004-02-18 13:36:32.000000000 +0000 -+++ linux-2.4.25/net/core/neighbour.c 2004-06-26 11:29:30.000000000 +0100 -@@ -386,7 +386,7 @@ struct pneigh_entry * pneigh_lookup(stru - if (!creat) - return NULL; - -- n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL); -+ n = kmalloc(sizeof(*n) + key_len, GFP_ATOMIC); - if (n == NULL) - return NULL; - -diff -uprN linux-2.4.25.old/net/ipv6/Config.in linux-2.4.25/net/ipv6/Config.in ---- linux-2.4.25.old/net/ipv6/Config.in 2001-12-21 17:42:05.000000000 +0000 -+++ linux-2.4.25/net/ipv6/Config.in 2004-06-26 11:29:30.000000000 +0100 -@@ -1,10 +1,16 @@ - # - # IPv6 configuration - # -- -+bool ' IPv6: routing by source address (EXPERIMENTAL)' CONFIG_IPV6_SUBTREES - #bool ' IPv6: flow policy support' CONFIG_RT6_POLICY - #bool ' IPv6: firewall support' CONFIG_IPV6_FIREWALL - -+if [ "$CONFIG_IPV6" != "n" ]; then -+ dep_tristate ' IPv6: IPv6 over IPv6 Tunneling (EXPERIMENTAL)' CONFIG_IPV6_TUNNEL $CONFIG_IPV6 -+fi -+ -+source net/ipv6/mobile_ip6/Config.in -+ - if [ "$CONFIG_NETFILTER" != "n" ]; then - source net/ipv6/netfilter/Config.in - fi -diff -uprN linux-2.4.25.old/net/ipv6/Makefile linux-2.4.25/net/ipv6/Makefile ---- linux-2.4.25.old/net/ipv6/Makefile 2003-11-28 18:26:21.000000000 +0000 -+++ linux-2.4.25/net/ipv6/Makefile 2004-06-26 11:29:30.000000000 +0100 -@@ -6,18 +6,28 @@ - # unless it's something special (ie not a .c file). - # - -+export-objs := ipv6_syms.o ipv6_tunnel.o - --O_TARGET := ipv6.o -+#list-multi := ipv6.o ipv6_tunnel.o - --obj-y := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \ -- route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \ -- protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ -- exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ -- ip6_flowlabel.o ipv6_syms.o -+ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ -+ sit.o route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o \ -+ raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ -+ exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ -+ ip6_flowlabel.o ipv6_syms.o -+ -+ifneq ($(CONFIG_IPV6_MOBILITY),n) -+ifneq ($(CONFIG_IPV6_MOBILITY),) -+ipv6-objs += mipglue.o -+endif -+endif - --export-objs := ipv6_syms.o -+obj-$(CONFIG_IPV6) += ipv6.o -+obj-$(CONFIG_IPV6_TUNNEL) += ipv6_tunnel.o -+ -+ipv6.o: $(ipv6-objs) -+ $(LD) -r -o $@ $(ipv6-objs) - --obj-m := $(O_TARGET) - - #obj-$(CONFIG_IPV6_FIREWALL) += ip6_fw.o - -diff -uprN linux-2.4.25.old/net/ipv6/addrconf.c linux-2.4.25/net/ipv6/addrconf.c ---- linux-2.4.25.old/net/ipv6/addrconf.c 2003-11-28 18:26:21.000000000 +0000 -+++ linux-2.4.25/net/ipv6/addrconf.c 2004-06-26 11:29:30.000000000 +0100 -@@ -68,6 +68,8 @@ - - #include - -+#include -+ - #define IPV6_MAX_ADDRESSES 16 - - /* Set to 3 to get tracing... */ -@@ -103,9 +105,9 @@ static spinlock_t addrconf_verify_lock = - - static int addrconf_ifdown(struct net_device *dev, int how); - --static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags); -+void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags); - static void addrconf_dad_timer(unsigned long data); --static void addrconf_dad_completed(struct inet6_ifaddr *ifp); -+void addrconf_dad_completed(struct inet6_ifaddr *ifp); - static void addrconf_rs_timer(unsigned long data); - static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); - -@@ -330,38 +332,6 @@ static struct inet6_dev * ipv6_find_idev - return idev; - } - --void ipv6_addr_prefix(struct in6_addr *prefix, -- struct in6_addr *addr, int prefix_len) --{ -- unsigned long mask; -- int ncopy, nbits; -- -- memset(prefix, 0, sizeof(*prefix)); -- -- if (prefix_len <= 0) -- return; -- if (prefix_len > 128) -- prefix_len = 128; -- -- ncopy = prefix_len / 32; -- switch (ncopy) { -- case 4: prefix->s6_addr32[3] = addr->s6_addr32[3]; -- case 3: prefix->s6_addr32[2] = addr->s6_addr32[2]; -- case 2: prefix->s6_addr32[1] = addr->s6_addr32[1]; -- case 1: prefix->s6_addr32[0] = addr->s6_addr32[0]; -- case 0: break; -- } -- nbits = prefix_len % 32; -- if (nbits == 0) -- return; -- -- mask = ~((1 << (32 - nbits)) - 1); -- mask = htonl(mask); -- -- prefix->s6_addr32[ncopy] = addr->s6_addr32[ncopy] & mask; --} -- -- - static void dev_forward_change(struct inet6_dev *idev) - { - struct net_device *dev; -@@ -513,7 +483,7 @@ ipv6_add_addr(struct inet6_dev *idev, co - - /* This function wants to get referenced ifp and releases it before return */ - --static void ipv6_del_addr(struct inet6_ifaddr *ifp) -+void ipv6_del_addr(struct inet6_ifaddr *ifp) - { - struct inet6_ifaddr *ifa, **ifap; - struct inet6_dev *idev = ifp->idev; -@@ -662,6 +632,12 @@ out: - if (match) - in6_ifa_put(match); - -+ /* The home address is always used as source address in -+ * MIPL mobile IPv6 -+ */ -+ if (scope != IFA_HOST && scope != IFA_LINK) -+ addrconf_get_mipv6_home_address(saddr); -+ - return err; - } - -@@ -815,7 +791,7 @@ void addrconf_leave_solict(struct net_de - } - - --static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) -+int ipv6_generate_eui64(u8 *eui, struct net_device *dev) - { - switch (dev->type) { - case ARPHRD_ETHER: -@@ -840,7 +816,7 @@ static int ipv6_generate_eui64(u8 *eui, - return -1; - } - --static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev) -+int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev) - { - int err = -1; - struct inet6_ifaddr *ifp; -@@ -1407,6 +1383,24 @@ static void addrconf_sit_config(struct n - sit_route_add(dev); - } - -+/** -+ * addrconf_ipv6_tunnel_config - configure IPv6 tunnel device -+ * @dev: tunnel device -+ **/ -+ -+static void addrconf_ipv6_tunnel_config(struct net_device *dev) -+{ -+ struct inet6_dev *idev; -+ -+ ASSERT_RTNL(); -+ -+ /* Assign inet6_dev structure to tunnel device */ -+ if ((idev = ipv6_find_idev(dev)) == NULL) { -+ printk(KERN_DEBUG "init ipv6 tunnel: add_dev failed\n"); -+ return; -+ } -+} -+ - - int addrconf_notify(struct notifier_block *this, unsigned long event, - void * data) -@@ -1421,6 +1415,10 @@ int addrconf_notify(struct notifier_bloc - addrconf_sit_config(dev); - break; - -+ case ARPHRD_TUNNEL6: -+ addrconf_ipv6_tunnel_config(dev); -+ break; -+ - case ARPHRD_LOOPBACK: - init_loopback(dev); - break; -@@ -1602,7 +1600,7 @@ out: - /* - * Duplicate Address Detection - */ --static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags) -+void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags) - { - struct net_device *dev; - unsigned long rand_num; -@@ -1667,7 +1665,7 @@ static void addrconf_dad_timer(unsigned - in6_ifa_put(ifp); - } - --static void addrconf_dad_completed(struct inet6_ifaddr *ifp) -+void addrconf_dad_completed(struct inet6_ifaddr *ifp) - { - struct net_device * dev = ifp->idev->dev; - -@@ -1676,7 +1674,7 @@ static void addrconf_dad_completed(struc - */ - - ipv6_ifa_notify(RTM_NEWADDR, ifp); -- -+ notifier_call_chain(&inet6addr_chain,NETDEV_UP,ifp); - /* If added prefix is link local and forwarding is off, - start sending router solicitations. - */ -@@ -1877,8 +1875,20 @@ inet6_rtm_newaddr(struct sk_buff *skb, s - if (rta[IFA_LOCAL-1]) { - if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))) - return -EINVAL; -+ if (ifm->ifa_flags & IFA_F_HOMEADDR && !rta[IFA_HOMEAGENT-1]) -+ return -EINVAL; - pfx = RTA_DATA(rta[IFA_LOCAL-1]); - } -+ if (rta[IFA_HOMEAGENT-1]) { -+ struct in6_addr *ha; -+ if (pfx == NULL || !(ifm->ifa_flags & IFA_F_HOMEADDR)) -+ return -EINVAL; -+ if (RTA_PAYLOAD(rta[IFA_HOMEAGENT-1]) < sizeof(*ha)) -+ return -EINVAL; -+ ha = RTA_DATA(rta[IFA_HOMEAGENT-1]); -+ addrconf_set_mipv6_mn_home(ifm->ifa_index, pfx, ifm->ifa_prefixlen, -+ ha, ifm->ifa_prefixlen); -+ } - if (pfx == NULL) - return -EINVAL; - -diff -uprN linux-2.4.25.old/net/ipv6/af_inet6.c linux-2.4.25/net/ipv6/af_inet6.c ---- linux-2.4.25.old/net/ipv6/af_inet6.c 2003-11-28 18:26:21.000000000 +0000 -+++ linux-2.4.25/net/ipv6/af_inet6.c 2004-06-26 11:29:30.000000000 +0100 -@@ -58,6 +58,9 @@ - #include - #include - #include -+#ifdef CONFIG_IPV6_TUNNEL -+#include -+#endif - - #include - #include -@@ -646,6 +649,11 @@ static int __init inet6_init(void) - err = ndisc_init(&inet6_family_ops); - if (err) - goto ndisc_fail; -+#ifdef CONFIG_IPV6_TUNNEL -+ err = ip6_tunnel_init(); -+ if (err) -+ goto ip6_tunnel_fail; -+#endif - err = igmp6_init(&inet6_family_ops); - if (err) - goto igmp_fail; -@@ -698,6 +706,10 @@ proc_raw6_fail: - #endif - igmp_fail: - ndisc_cleanup(); -+#ifdef CONFIG_IPV6_TUNNEL -+ ip6_tunnel_cleanup(); -+ip6_tunnel_fail: -+#endif - ndisc_fail: - icmpv6_cleanup(); - icmp_fail: -@@ -730,6 +742,9 @@ static void inet6_exit(void) - ip6_route_cleanup(); - ipv6_packet_cleanup(); - igmp6_cleanup(); -+#ifdef CONFIG_IPV6_TUNNEL -+ ip6_tunnel_cleanup(); -+#endif - ndisc_cleanup(); - icmpv6_cleanup(); - #ifdef CONFIG_SYSCTL -diff -uprN linux-2.4.25.old/net/ipv6/exthdrs.c linux-2.4.25/net/ipv6/exthdrs.c ---- linux-2.4.25.old/net/ipv6/exthdrs.c 2003-08-25 12:44:44.000000000 +0100 -+++ linux-2.4.25/net/ipv6/exthdrs.c 2004-06-26 11:29:30.000000000 +0100 -@@ -41,6 +41,9 @@ - #include - #include - -+#include -+#include -+ - #include - - /* -@@ -160,7 +163,8 @@ bad: - *****************************/ - - struct tlvtype_proc tlvprocdestopt_lst[] = { -- /* No destination options are defined now */ -+ /* Mobility Support destination options */ -+ {MIPV6_TLV_HOMEADDR, mipv6_handle_dstopt}, - {-1, NULL} - }; - -@@ -210,6 +214,7 @@ static int ipv6_routing_header(struct sk - - struct ipv6_rt_hdr *hdr; - struct rt0_hdr *rthdr; -+ struct rt2_hdr *rt2hdr; - - if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || - !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { -@@ -225,17 +230,25 @@ static int ipv6_routing_header(struct sk - kfree_skb(skb); - return -1; - } -- -+ /* Silently discard invalid packets containing RTH type 2 */ -+ if (hdr->type == IPV6_SRCRT_TYPE_2 && -+ (hdr->hdrlen != 2 || hdr->segments_left != 1)) { -+ kfree_skb(skb); -+ return -1; -+ } - looped_back: - if (hdr->segments_left == 0) { -- opt->srcrt = skb->h.raw - skb->nh.raw; -+ if (hdr->type == IPV6_SRCRT_TYPE_0) -+ opt->srcrt = skb->h.raw - skb->nh.raw; -+ else if (hdr->type == IPV6_SRCRT_TYPE_2) -+ opt->srcrt2 = skb->h.raw - skb->nh.raw; - skb->h.raw += (hdr->hdrlen + 1) << 3; - opt->dst0 = opt->dst1; - opt->dst1 = 0; - return (&hdr->nexthdr) - skb->nh.raw; - } - -- if (hdr->type != IPV6_SRCRT_TYPE_0) { -+ if (hdr->type != IPV6_SRCRT_TYPE_0 && hdr->type != IPV6_SRCRT_TYPE_2) { - icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); - return -1; - } -@@ -275,9 +288,20 @@ looped_back: - - i = n - --hdr->segments_left; - -- rthdr = (struct rt0_hdr *) hdr; -- addr = rthdr->addr; -- addr += i - 1; -+ if (hdr->type == IPV6_SRCRT_TYPE_0) { -+ rthdr = (struct rt0_hdr *) hdr; -+ addr = rthdr->addr; -+ addr += i - 1; -+ } else { -+ /* check that address is this node's home address */ -+ rt2hdr = (struct rt2_hdr *) hdr; -+ addr = &rt2hdr->addr; -+ if (!ipv6_chk_addr(addr, NULL) || -+ !ipv6_chk_mip_home_addr(addr)) { -+ kfree_skb(skb); -+ return -1; -+ } -+ } - - addr_type = ipv6_addr_type(addr); - -@@ -330,6 +354,10 @@ looped_back: - temporary (or permanent) backdoor. - If listening socket set IPV6_RTHDR to 2, then we invert header. - --ANK (980729) -+ -+ By the Mobile IPv6 specification Type 2 routing header MUST NOT be -+ inverted. -+ --AJT (20020917) - */ - - struct ipv6_txoptions * -@@ -352,6 +380,18 @@ ipv6_invert_rthdr(struct sock *sk, struc - struct ipv6_txoptions *opt; - int hdrlen = ipv6_optlen(hdr); - -+ if (hdr->type == IPV6_SRCRT_TYPE_2) { -+ opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC); -+ if (opt == NULL) -+ return NULL; -+ memset(opt, 0, sizeof(*opt)); -+ opt->tot_len = sizeof(*opt) + hdrlen; -+ opt->srcrt = (void*)(opt+1); -+ opt->opt_nflen = hdrlen; -+ memcpy(opt->srcrt, hdr, sizeof(struct rt2_hdr)); -+ return opt; -+ } -+ - if (hdr->segments_left || - hdr->type != IPV6_SRCRT_TYPE_0 || - hdr->hdrlen & 0x01) -@@ -622,8 +662,18 @@ u8 *ipv6_build_nfrag_opts(struct sk_buff - if (opt) { - if (opt->dst0opt) - prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst0opt); -- if (opt->srcrt) -- prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, daddr); -+ if (opt->srcrt) { -+ if (opt->srcrt2) { -+ struct in6_addr *rt2_hop = &((struct rt2_hdr *)opt->srcrt2)->addr; -+ prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, rt2_hop); -+ } else -+ prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, daddr); -+ } -+ if (opt->srcrt2) { -+ struct inet6_skb_parm *parm = (struct inet6_skb_parm *)skb->cb; -+ ipv6_addr_copy(&parm->hoa, daddr); -+ prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt2, daddr); -+ } - } - return prev_hdr; - } -@@ -684,6 +734,11 @@ void ipv6_push_nfrag_opts(struct sk_buff - u8 *proto, - struct in6_addr **daddr) - { -+ if (opt->srcrt2) { -+ struct inet6_skb_parm *parm = (struct inet6_skb_parm *)skb->cb; -+ ipv6_addr_copy(&parm->hoa, *daddr); -+ ipv6_push_rthdr(skb, proto, opt->srcrt2, daddr); -+ } - if (opt->srcrt) - ipv6_push_rthdr(skb, proto, opt->srcrt, daddr); - if (opt->dst0opt) -@@ -719,6 +774,8 @@ ipv6_dup_options(struct sock *sk, struct - *((char**)&opt2->auth) += dif; - if (opt2->srcrt) - *((char**)&opt2->srcrt) += dif; -+ if (opt2->srcrt2) -+ *((char**)&opt2->srcrt2) += dif; - } - return opt2; - } -diff -uprN linux-2.4.25.old/net/ipv6/icmp.c linux-2.4.25/net/ipv6/icmp.c ---- linux-2.4.25.old/net/ipv6/icmp.c 2003-11-28 18:26:21.000000000 +0000 -+++ linux-2.4.25/net/ipv6/icmp.c 2004-06-26 11:29:30.000000000 +0100 -@@ -61,6 +61,8 @@ - #include - #include - -+#include -+ - #include - #include - -@@ -364,6 +366,8 @@ void icmpv6_send(struct sk_buff *skb, in - - msg.len = len; - -+ icmpv6_swap_mipv6_addrs(skb); -+ - ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1, - MSG_DONTWAIT); - if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB) -@@ -562,13 +566,13 @@ int icmpv6_rcv(struct sk_buff *skb) - rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev, - ntohl(hdr->icmp6_mtu)); - -- /* -- * Drop through to notify -- */ -+ icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu); -+ break; - - case ICMPV6_DEST_UNREACH: -- case ICMPV6_TIME_EXCEED: - case ICMPV6_PARAMPROB: -+ mipv6_icmp_rcv(skb); -+ case ICMPV6_TIME_EXCEED: - icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu); - break; - -@@ -597,6 +601,13 @@ int icmpv6_rcv(struct sk_buff *skb) - case ICMPV6_MGM_REDUCTION: - break; - -+ case MIPV6_DHAAD_REQUEST: -+ case MIPV6_DHAAD_REPLY: -+ case MIPV6_PREFIX_SOLICIT: -+ case MIPV6_PREFIX_ADV: -+ mipv6_icmp_rcv(skb); -+ break; -+ - default: - if (net_ratelimit()) - printk(KERN_DEBUG "icmpv6: msg of unkown type\n"); -diff -uprN linux-2.4.25.old/net/ipv6/ip6_fib.c linux-2.4.25/net/ipv6/ip6_fib.c ---- linux-2.4.25.old/net/ipv6/ip6_fib.c 2003-08-25 12:44:44.000000000 +0100 -+++ linux-2.4.25/net/ipv6/ip6_fib.c 2004-06-26 11:29:30.000000000 +0100 -@@ -18,6 +18,7 @@ - * Yuji SEKIYA @USAGI: Support default route on router node; - * remove ip6_null_entry from the top of - * routing table. -+ * Ville Nuorvala: Fixes to source address based routing - */ - #include - #include -@@ -40,7 +41,6 @@ - #include - - #define RT6_DEBUG 2 --#undef CONFIG_IPV6_SUBTREES - - #if RT6_DEBUG >= 3 - #define RT6_TRACE(x...) printk(KERN_DEBUG x) -@@ -500,6 +500,8 @@ static __inline__ void fib6_start_gc(str - mod_timer(&ip6_fib_timer, jiffies + ip6_rt_gc_interval); - } - -+static struct rt6_info * fib6_find_prefix(struct fib6_node *fn); -+ - /* - * Add routing information to the routing tree. - * / -@@ -508,17 +510,19 @@ static __inline__ void fib6_start_gc(str - - int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh) - { -- struct fib6_node *fn; -+ struct fib6_node *fn = root; - int err = -ENOMEM; - -- fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr), -- rt->rt6i_dst.plen, (u8*) &rt->rt6i_dst - (u8*) rt); -+#ifdef CONFIG_IPV6_SUBTREES -+ struct fib6_node *pn = NULL; - -+ fn = fib6_add_1(root, &rt->rt6i_src.addr, sizeof(struct in6_addr), -+ rt->rt6i_src.plen, (u8*) &rt->rt6i_src - (u8*) rt); -+ - if (fn == NULL) - goto out; - --#ifdef CONFIG_IPV6_SUBTREES -- if (rt->rt6i_src.plen) { -+ if (rt->rt6i_dst.plen) { - struct fib6_node *sn; - - if (fn->subtree == NULL) { -@@ -546,9 +550,9 @@ int fib6_add(struct fib6_node *root, str - - /* Now add the first leaf node to new subtree */ - -- sn = fib6_add_1(sfn, &rt->rt6i_src.addr, -- sizeof(struct in6_addr), rt->rt6i_src.plen, -- (u8*) &rt->rt6i_src - (u8*) rt); -+ sn = fib6_add_1(sfn, &rt->rt6i_dst.addr, -+ sizeof(struct in6_addr), rt->rt6i_dst.plen, -+ (u8*) &rt->rt6i_dst - (u8*) rt); - - if (sn == NULL) { - /* If it is failed, discard just allocated -@@ -562,21 +566,30 @@ int fib6_add(struct fib6_node *root, str - /* Now link new subtree to main tree */ - sfn->parent = fn; - fn->subtree = sfn; -- if (fn->leaf == NULL) { -- fn->leaf = rt; -- atomic_inc(&rt->rt6i_ref); -- } - } else { -- sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr, -- sizeof(struct in6_addr), rt->rt6i_src.plen, -- (u8*) &rt->rt6i_src - (u8*) rt); -+ sn = fib6_add_1(fn->subtree, &rt->rt6i_dst.addr, -+ sizeof(struct in6_addr), rt->rt6i_dst.plen, -+ (u8*) &rt->rt6i_dst - (u8*) rt); - - if (sn == NULL) - goto st_failure; - } - -+ /* fib6_add_1 might have cleared the old leaf pointer */ -+ if (fn->leaf == NULL) { -+ fn->leaf = rt; -+ atomic_inc(&rt->rt6i_ref); -+ } -+ -+ pn = fn; - fn = sn; - } -+#else -+ fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr), -+ rt->rt6i_dst.plen, (u8*) &rt->rt6i_dst - (u8*) rt); -+ -+ if (fn == NULL) -+ goto out; - #endif - - err = fib6_add_rt2node(fn, rt, nlh); -@@ -588,8 +601,30 @@ int fib6_add(struct fib6_node *root, str - } - - out: -- if (err) -+ if (err) { -+#ifdef CONFIG_IPV6_SUBTREES -+ -+ /* If fib6_add_1 has cleared the old leaf pointer in the -+ super-tree leaf node, we have to find a new one for it. -+ -+ This situation will never arise in the sub-tree since -+ the node will at least have the route that caused -+ fib6_add_rt2node to fail. -+ */ -+ -+ if (pn && !(pn->fn_flags & RTN_RTINFO)) { -+ pn->leaf = fib6_find_prefix(pn); -+#if RT6_DEBUG >= 2 -+ if (!pn->leaf) { -+ BUG_TRAP(pn->leaf); -+ pn->leaf = &ip6_null_entry; -+ } -+#endif -+ atomic_inc(&pn->leaf->rt6i_ref); -+ } -+#endif - dst_free(&rt->u.dst); -+ } - return err; - - #ifdef CONFIG_IPV6_SUBTREES -@@ -597,8 +632,8 @@ out: - is orphan. If it is, shoot it. - */ - st_failure: -- if (fn && !(fn->fn_flags&RTN_RTINFO|RTN_ROOT)) -- fib_repair_tree(fn); -+ if (fn && !(fn->fn_flags & (RTN_RTINFO | RTN_ROOT))) -+ fib6_repair_tree(fn); - dst_free(&rt->u.dst); - return err; - #endif -@@ -641,22 +676,28 @@ static struct fib6_node * fib6_lookup_1( - break; - } - -- while ((fn->fn_flags & RTN_ROOT) == 0) { -+ for (;;) { - #ifdef CONFIG_IPV6_SUBTREES - if (fn->subtree) { -- struct fib6_node *st; -- struct lookup_args *narg; -- -- narg = args + 1; -- -- if (narg->addr) { -- st = fib6_lookup_1(fn->subtree, narg); -+ struct rt6key *key; - -- if (st && !(st->fn_flags & RTN_ROOT)) -- return st; -+ key = (struct rt6key *) ((u8 *) fn->leaf + -+ args->offset); -+ -+ if (addr_match(&key->addr, args->addr, key->plen)) { -+ struct fib6_node *st; -+ struct lookup_args *narg = args + 1; -+ if (!ipv6_addr_any(narg->addr)) { -+ st = fib6_lookup_1(fn->subtree, narg); -+ -+ if (st && !(st->fn_flags & RTN_ROOT)) -+ return st; -+ } - } - } - #endif -+ if (fn->fn_flags & RTN_ROOT) -+ break; - - if (fn->fn_flags & RTN_RTINFO) { - struct rt6key *key; -@@ -680,13 +721,22 @@ struct fib6_node * fib6_lookup(struct fi - struct lookup_args args[2]; - struct rt6_info *rt = NULL; - struct fib6_node *fn; -+#ifdef CONFIG_IPV6_SUBTREES -+ struct in6_addr saddr_buf; -+#endif - -+#ifdef CONFIG_IPV6_SUBTREES -+ if (saddr == NULL) { -+ memset(&saddr_buf, 0, sizeof(struct in6_addr)); -+ saddr = &saddr_buf; -+ } -+ args[0].offset = (u8*) &rt->rt6i_src - (u8*) rt; -+ args[0].addr = saddr; -+ args[1].offset = (u8*) &rt->rt6i_dst - (u8*) rt; -+ args[1].addr = daddr; -+#else - args[0].offset = (u8*) &rt->rt6i_dst - (u8*) rt; - args[0].addr = daddr; -- --#ifdef CONFIG_IPV6_SUBTREES -- args[1].offset = (u8*) &rt->rt6i_src - (u8*) rt; -- args[1].addr = saddr; - #endif - - fn = fib6_lookup_1(root, args); -@@ -739,19 +789,25 @@ struct fib6_node * fib6_locate(struct fi - { - struct rt6_info *rt = NULL; - struct fib6_node *fn; -- -- fn = fib6_locate_1(root, daddr, dst_len, -- (u8*) &rt->rt6i_dst - (u8*) rt); -- - #ifdef CONFIG_IPV6_SUBTREES -- if (src_len) { -- BUG_TRAP(saddr!=NULL); -- if (fn == NULL) -- fn = fn->subtree; -+ struct in6_addr saddr_buf; -+ -+ if (saddr == NULL) { -+ memset(&saddr_buf, 0, sizeof(struct in6_addr)); -+ saddr = &saddr_buf; -+ } -+ fn = fib6_locate_1(root, saddr, src_len, -+ (u8*) &rt->rt6i_src - (u8*) rt); -+ if (dst_len) { - if (fn) -- fn = fib6_locate_1(fn, saddr, src_len, -- (u8*) &rt->rt6i_src - (u8*) rt); -+ fn = fib6_locate_1(fn->subtree, daddr, dst_len, -+ (u8*) &rt->rt6i_dst - (u8*) rt); -+ else -+ return NULL; - } -+#else -+ fn = fib6_locate_1(root, daddr, dst_len, -+ (u8*) &rt->rt6i_dst - (u8*) rt); - #endif - - if (fn && fn->fn_flags&RTN_RTINFO) -@@ -939,7 +995,7 @@ static void fib6_del_route(struct fib6_n - } - fn = fn->parent; - } -- /* No more references are possiible at this point. */ -+ /* No more references are possible at this point. */ - if (atomic_read(&rt->rt6i_ref) != 1) BUG(); - } - -diff -uprN linux-2.4.25.old/net/ipv6/ip6_input.c linux-2.4.25/net/ipv6/ip6_input.c ---- linux-2.4.25.old/net/ipv6/ip6_input.c 2003-08-25 12:44:44.000000000 +0100 -+++ linux-2.4.25/net/ipv6/ip6_input.c 2004-06-26 11:29:30.000000000 +0100 -@@ -40,13 +40,42 @@ - #include - #include - -+static inline int ip6_proxy_chk(struct sk_buff *skb) -+{ -+ struct ipv6hdr *hdr = skb->nh.ipv6h; - -- -+ if (ipv6_addr_type(&hdr->daddr)&IPV6_ADDR_UNICAST && -+ pneigh_lookup(&nd_tbl, &hdr->daddr, skb->dev, 0)) { -+ u8 nexthdr = hdr->nexthdr; -+ int offset; -+ struct icmp6hdr msg; -+ -+ if (ipv6_ext_hdr(nexthdr)) { -+ offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr, -+ skb->len - sizeof(*hdr)); -+ if (offset < 0) -+ return 0; -+ } else -+ offset = sizeof(*hdr); -+ -+ /* capture unicast NUD probes on behalf of the proxied node */ -+ -+ if (nexthdr == IPPROTO_ICMPV6 && -+ !skb_copy_bits(skb, offset, &msg, sizeof(msg)) && -+ msg.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) { -+ return 1; -+ } -+ } -+ return 0; -+} -+ - static inline int ip6_rcv_finish( struct sk_buff *skb) - { -- if (skb->dst == NULL) -- ip6_route_input(skb); -- -+ if (skb->dst == NULL) { -+ if (ip6_proxy_chk(skb)) -+ return ip6_input(skb); -+ ip6_route_input(skb); -+ } - return skb->dst->input(skb); - } - -diff -uprN linux-2.4.25.old/net/ipv6/ip6_output.c linux-2.4.25/net/ipv6/ip6_output.c ---- linux-2.4.25.old/net/ipv6/ip6_output.c 2003-08-25 12:44:44.000000000 +0100 -+++ linux-2.4.25/net/ipv6/ip6_output.c 2004-06-26 11:29:30.000000000 +0100 -@@ -50,6 +50,8 @@ - #include - #include - -+#include -+ - static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *fhdr) - { - static u32 ipv6_fragmentation_id = 1; -@@ -194,7 +196,14 @@ int ip6_xmit(struct sock *sk, struct sk_ - u8 proto = fl->proto; - int seg_len = skb->len; - int hlimit; -+ int retval; -+ struct ipv6_txoptions *orig_opt = opt; -+ -+ opt = ip6_add_mipv6_txoptions(sk, skb, orig_opt, fl, &dst); - -+ if(orig_opt && !opt) -+ return -ENOMEM; -+ - if (opt) { - int head_room; - -@@ -209,8 +218,11 @@ int ip6_xmit(struct sock *sk, struct sk_ - struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room); - kfree_skb(skb); - skb = skb2; -- if (skb == NULL) -+ if (skb == NULL) { -+ ip6_free_mipv6_txoptions(opt, orig_opt); -+ - return -ENOBUFS; -+ } - if (sk) - skb_set_owner_w(skb, sk); - } -@@ -242,7 +254,10 @@ int ip6_xmit(struct sock *sk, struct sk_ - - if (skb->len <= dst->pmtu) { - IP6_INC_STATS(Ip6OutRequests); -- return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute); -+ ip6_mark_mipv6_packet(opt, skb); -+ retval = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute); -+ ip6_free_mipv6_txoptions(opt, orig_opt); -+ return retval; - } - - if (net_ratelimit()) -@@ -250,6 +265,9 @@ int ip6_xmit(struct sock *sk, struct sk_ - skb->dev = dst->dev; - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst->pmtu, skb->dev); - kfree_skb(skb); -+ -+ ip6_free_mipv6_txoptions(opt, orig_opt); -+ - return -EMSGSIZE; - } - -@@ -473,6 +491,7 @@ static int ip6_frag_xmit(struct sock *sk - - IP6_INC_STATS(Ip6FragCreates); - IP6_INC_STATS(Ip6OutRequests); -+ ip6_mark_mipv6_packet(opt, skb); - err = NF_HOOK(PF_INET6,NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute); - if (err) { - kfree_skb(last_skb); -@@ -499,6 +518,7 @@ static int ip6_frag_xmit(struct sock *sk - IP6_INC_STATS(Ip6FragCreates); - IP6_INC_STATS(Ip6FragOKs); - IP6_INC_STATS(Ip6OutRequests); -+ ip6_mark_mipv6_packet(opt, last_skb); - return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, last_skb, NULL,dst->dev, ip6_maybe_reroute); - } - -@@ -509,26 +529,43 @@ int ip6_build_xmit(struct sock *sk, inet - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; - struct in6_addr *final_dst = NULL; - struct dst_entry *dst; -+ struct rt6_info *rt; - int err = 0; - unsigned int pktlength, jumbolen, mtu; - struct in6_addr saddr; -+ struct ipv6_txoptions *orig_opt = opt; -+#ifdef CONFIG_IPV6_SUBTREES -+ struct dst_entry *org_dst; -+#endif -+ -+ opt = ip6_add_mipv6_txoptions(sk, NULL, orig_opt, fl, NULL); -+ -+ if(orig_opt && !opt) -+ return -ENOMEM; - - if (opt && opt->srcrt) { - struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; - final_dst = fl->fl6_dst; - fl->fl6_dst = rt0->addr; -- } -+ } else if (opt && opt->srcrt2) { -+ struct rt2_hdr *rt2 = (struct rt2_hdr *) opt->srcrt2; -+ final_dst = fl->fl6_dst; -+ fl->fl6_dst = &rt2->addr; -+ } - - if (!fl->oif && ipv6_addr_is_multicast(fl->nl_u.ip6_u.daddr)) - fl->oif = np->mcast_oif; - - dst = __sk_dst_check(sk, np->dst_cookie); -+#ifdef CONFIG_IPV6_SUBTREES -+ org_dst = dst; -+#endif - if (dst) { -- struct rt6_info *rt = (struct rt6_info*)dst; -+ rt = (struct rt6_info*)dst; - - /* Yes, checking route validity in not connected - case is not very simple. Take into account, -- that we do not support routing by source, TOS, -+ that we do not support routing by TOS, - and MSG_DONTROUTE --ANK (980726) - - 1. If route was host route, check that -@@ -548,6 +585,13 @@ int ip6_build_xmit(struct sock *sk, inet - ipv6_addr_cmp(fl->fl6_dst, &rt->rt6i_dst.addr)) - && (np->daddr_cache == NULL || - ipv6_addr_cmp(fl->fl6_dst, np->daddr_cache))) -+#ifdef CONFIG_IPV6_SUBTREES -+ || (fl->fl6_src != NULL -+ && (rt->rt6i_src.plen != 128 || -+ ipv6_addr_cmp(fl->fl6_src, &rt->rt6i_src.addr)) -+ && (np->saddr_cache == NULL || -+ ipv6_addr_cmp(fl->fl6_src, np->saddr_cache))) -+#endif - || (fl->oif && fl->oif != dst->dev->ifindex)) { - dst = NULL; - } else -@@ -560,21 +604,42 @@ int ip6_build_xmit(struct sock *sk, inet - if (dst->error) { - IP6_INC_STATS(Ip6OutNoRoutes); - dst_release(dst); -+ ip6_free_mipv6_txoptions(opt, orig_opt); - return -ENETUNREACH; - } - - if (fl->fl6_src == NULL) { - err = ipv6_get_saddr(dst, fl->fl6_dst, &saddr); -- - if (err) { - #if IP6_DEBUG >= 2 - printk(KERN_DEBUG "ip6_build_xmit: " - "no available source address\n"); - #endif -+ -+#ifdef CONFIG_IPV6_SUBTREES -+ if (dst != org_dst) { -+ dst_release(dst); -+ dst = org_dst; -+ } -+#endif - goto out; - } - fl->fl6_src = &saddr; - } -+#ifdef CONFIG_IPV6_SUBTREES -+ rt = (struct rt6_info*)dst; -+ if (dst != org_dst || rt->rt6i_src.plen != 128 || -+ ipv6_addr_cmp(fl->fl6_src, &rt->rt6i_src.addr)) { -+ dst_release(dst); -+ dst = ip6_route_output(sk, fl); -+ if (dst->error) { -+ IP6_INC_STATS(Ip6OutNoRoutes); -+ dst_release(dst); -+ ip6_free_mipv6_txoptions(opt, orig_opt); -+ return -ENETUNREACH; -+ } -+ } -+#endif - pktlength = length; - - if (hlimit < 0) { -@@ -667,6 +732,7 @@ int ip6_build_xmit(struct sock *sk, inet - - if (!err) { - IP6_INC_STATS(Ip6OutRequests); -+ ip6_mark_mipv6_packet(opt, skb); - err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute); - } else { - err = -EFAULT; -@@ -688,9 +754,14 @@ int ip6_build_xmit(struct sock *sk, inet - * cleanup - */ - out: -- ip6_dst_store(sk, dst, fl->nl_u.ip6_u.daddr == &np->daddr ? &np->daddr : NULL); -+ ip6_dst_store(sk, dst, -+ fl->nl_u.ip6_u.daddr == &np->daddr ? &np->daddr : NULL, -+ fl->nl_u.ip6_u.saddr == &np->saddr ? &np->saddr : NULL); - if (err > 0) - err = np->recverr ? net_xmit_errno(err) : 0; -+ -+ ip6_free_mipv6_txoptions(opt, orig_opt); -+ - return err; - } - -@@ -769,6 +840,15 @@ int ip6_forward(struct sk_buff *skb) - return -ETIMEDOUT; - } - -+ /* The proxying router can't forward traffic sent to a link-local -+ address, so signal the sender and discard the packet. This -+ behavior is required by the MIPv6 specification. */ -+ -+ if (ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL && -+ skb->dev && pneigh_lookup(&nd_tbl, &hdr->daddr, skb->dev, 0)) { -+ dst_link_failure(skb); -+ goto drop; -+ } - /* IPv6 specs say nothing about it, but it is clear that we cannot - send redirects to source routed frames. - */ -diff -uprN linux-2.4.25.old/net/ipv6/ipv6_syms.c linux-2.4.25/net/ipv6/ipv6_syms.c ---- linux-2.4.25.old/net/ipv6/ipv6_syms.c 2003-11-28 18:26:21.000000000 +0000 -+++ linux-2.4.25/net/ipv6/ipv6_syms.c 2004-06-26 11:29:30.000000000 +0100 -@@ -6,6 +6,8 @@ - #include - #include - #include -+#include -+#include - - EXPORT_SYMBOL(ipv6_addr_type); - EXPORT_SYMBOL(icmpv6_send); -@@ -33,3 +35,48 @@ EXPORT_SYMBOL(inet6_ioctl); - EXPORT_SYMBOL(ipv6_get_saddr); - EXPORT_SYMBOL(ipv6_chk_addr); - EXPORT_SYMBOL(in6_dev_finish_destroy); -+ -+#if defined(CONFIG_IPV6_TUNNEL_MODULE) || defined(CONFIG_IPV6_MOBILITY_MODULE) -+EXPORT_SYMBOL(ip6_build_xmit); -+EXPORT_SYMBOL(rt6_lookup); -+EXPORT_SYMBOL(ipv6_ext_hdr); -+#endif -+#ifdef CONFIG_IPV6_MOBILITY_MODULE -+EXPORT_SYMBOL(mipv6_functions); -+EXPORT_SYMBOL(mipv6_invalidate_calls); -+#if defined(CONFIG_IPV6_MOBILITY_HA_MODULE) || defined(CONFIG_IPV6_MOBILITY_MN_MODULE) -+EXPORT_SYMBOL(ip6_route_add); -+EXPORT_SYMBOL(ip6_route_del); -+EXPORT_SYMBOL(ipv6_get_lladdr); -+EXPORT_SYMBOL(ipv6_get_ifaddr); -+EXPORT_SYMBOL(nd_tbl); -+EXPORT_SYMBOL(ndisc_send_ns); -+EXPORT_SYMBOL(ndisc_send_na); -+EXPORT_SYMBOL(ndisc_next_option); -+EXPORT_SYMBOL(inet6_ifa_finish_destroy); -+#endif -+#ifdef CONFIG_IPV6_MOBILITY_HA_MODULE -+EXPORT_SYMBOL(ipv6_dev_ac_dec); -+EXPORT_SYMBOL(ipv6_dev_ac_inc); -+EXPORT_SYMBOL(ipv6_dev_mc_dec); -+EXPORT_SYMBOL(ipv6_dev_mc_inc); -+EXPORT_SYMBOL(ip6_forward); -+EXPORT_SYMBOL(ip6_input); -+EXPORT_SYMBOL(ipv6_chk_acast_addr); -+#endif -+#ifdef CONFIG_IPV6_MOBILITY_MN_MODULE -+#endif -+EXPORT_SYMBOL(addrconf_add_ifaddr); -+EXPORT_SYMBOL(addrconf_del_ifaddr); -+EXPORT_SYMBOL(addrconf_dad_start); -+EXPORT_SYMBOL(ip6_del_rt); -+EXPORT_SYMBOL(ip6_routing_table); -+EXPORT_SYMBOL(rt6_get_dflt_router); -+EXPORT_SYMBOL(rt6_purge_dflt_routers); -+EXPORT_SYMBOL(rt6_lock); -+EXPORT_SYMBOL(ndisc_send_rs); -+EXPORT_SYMBOL(fib6_clean_tree); -+EXPORT_SYMBOL(ipv6_del_addr); -+EXPORT_SYMBOL(ipv6_generate_eui64); -+EXPORT_SYMBOL(ipv6_inherit_eui64); -+#endif -diff -uprN linux-2.4.25.old/net/ipv6/ipv6_tunnel.c linux-2.4.25/net/ipv6/ipv6_tunnel.c ---- linux-2.4.25.old/net/ipv6/ipv6_tunnel.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/ipv6_tunnel.c 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,1604 @@ -+/* -+ * IPv6 over IPv6 tunnel device -+ * Linux INET6 implementation -+ * -+ * Authors: -+ * Ville Nuorvala -+ * -+ * $Id$ -+ * -+ * Based on: -+ * linux/net/ipv6/sit.c -+ * -+ * RFC 2473 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+MODULE_AUTHOR("Ville Nuorvala"); -+MODULE_DESCRIPTION("IPv6-in-IPv6 tunnel"); -+MODULE_LICENSE("GPL"); -+ -+#define IPV6_TLV_TEL_DST_SIZE 8 -+ -+#ifdef IP6_TNL_DEBUG -+#define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __FUNCTION__) -+#else -+#define IP6_TNL_TRACE(x...) do {;} while(0) -+#endif -+ -+#define IPV6_TCLASS_MASK (IPV6_FLOWINFO_MASK & ~IPV6_FLOWLABEL_MASK) -+ -+#define HASH_SIZE 32 -+ -+#define HASH(addr) (((addr)->s6_addr32[0] ^ (addr)->s6_addr32[1] ^ \ -+ (addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \ -+ (HASH_SIZE - 1)) -+ -+static int ip6ip6_fb_tnl_dev_init(struct net_device *dev); -+static int ip6ip6_tnl_dev_init(struct net_device *dev); -+ -+/* the IPv6 IPv6 tunnel fallback device */ -+static struct net_device ip6ip6_fb_tnl_dev = { -+ name: "ip6tnl0", -+ init: ip6ip6_fb_tnl_dev_init -+}; -+ -+/* the IPv6 IPv6 fallback tunnel */ -+static struct ip6_tnl ip6ip6_fb_tnl = { -+ dev: &ip6ip6_fb_tnl_dev, -+ parms:{name: "ip6tnl0", proto: IPPROTO_IPV6} -+}; -+ -+/* lists for storing tunnels in use */ -+static struct ip6_tnl *tnls_r_l[HASH_SIZE]; -+static struct ip6_tnl *tnls_wc[1]; -+static struct ip6_tnl **tnls[2] = { tnls_wc, tnls_r_l }; -+ -+/* list for unused cached kernel tunnels */ -+static struct ip6_tnl *tnls_kernel[1]; -+/* maximum number of cached kernel tunnels */ -+static unsigned int max_kdev_count = 0; -+/* minimum number of cached kernel tunnels */ -+static unsigned int min_kdev_count = 0; -+/* current number of cached kernel tunnels */ -+static unsigned int kdev_count = 0; -+ -+/* lists for tunnel hook functions */ -+static struct list_head hooks[IP6_TNL_MAXHOOKS]; -+ -+/* locks for the different lists */ -+static rwlock_t ip6ip6_lock = RW_LOCK_UNLOCKED; -+static rwlock_t ip6ip6_kernel_lock = RW_LOCK_UNLOCKED; -+static rwlock_t ip6ip6_hook_lock = RW_LOCK_UNLOCKED; -+ -+/* flag indicating if the module is being removed */ -+static int shutdown = 0; -+ -+/** -+ * ip6ip6_tnl_lookup - fetch tunnel matching the end-point addresses -+ * @remote: the address of the tunnel exit-point -+ * @local: the address of the tunnel entry-point -+ * -+ * Return: -+ * tunnel matching given end-points if found, -+ * else fallback tunnel if its device is up, -+ * else %NULL -+ **/ -+ -+struct ip6_tnl * -+ip6ip6_tnl_lookup(struct in6_addr *remote, struct in6_addr *local) -+{ -+ unsigned h0 = HASH(remote); -+ unsigned h1 = HASH(local); -+ struct ip6_tnl *t; -+ -+ for (t = tnls_r_l[h0 ^ h1]; t; t = t->next) { -+ if (!ipv6_addr_cmp(local, &t->parms.laddr) && -+ !ipv6_addr_cmp(remote, &t->parms.raddr) && -+ (t->dev->flags & IFF_UP)) -+ return t; -+ } -+ if ((t = tnls_wc[0]) != NULL && (t->dev->flags & IFF_UP)) -+ return t; -+ -+ return NULL; -+} -+ -+/** -+ * ip6ip6_bucket - get head of list matching given tunnel parameters -+ * @p: parameters containing tunnel end-points -+ * -+ * Description: -+ * ip6ip6_bucket() returns the head of the list matching the -+ * &struct in6_addr entries laddr and raddr in @p. -+ * -+ * Return: head of IPv6 tunnel list -+ **/ -+ -+static struct ip6_tnl ** -+ip6ip6_bucket(struct ip6_tnl_parm *p) -+{ -+ struct in6_addr *remote = &p->raddr; -+ struct in6_addr *local = &p->laddr; -+ unsigned h = 0; -+ int prio = 0; -+ -+ if (!ipv6_addr_any(remote) || !ipv6_addr_any(local)) { -+ prio = 1; -+ h = HASH(remote) ^ HASH(local); -+ } -+ return &tnls[prio][h]; -+} -+ -+/** -+ * ip6ip6_kernel_tnl_link - add new kernel tunnel to cache -+ * @t: kernel tunnel -+ * -+ * Note: -+ * %IP6_TNL_F_KERNEL_DEV is assumed to be raised in t->parms.flags. -+ * See the comments on ip6ip6_kernel_tnl_add() for more information. -+ **/ -+ -+static inline void -+ip6ip6_kernel_tnl_link(struct ip6_tnl *t) -+{ -+ write_lock_bh(&ip6ip6_kernel_lock); -+ t->next = tnls_kernel[0]; -+ tnls_kernel[0] = t; -+ kdev_count++; -+ write_unlock_bh(&ip6ip6_kernel_lock); -+} -+ -+/** -+ * ip6ip6_kernel_tnl_unlink - remove first kernel tunnel from cache -+ * -+ * Return: first free kernel tunnel -+ * -+ * Note: -+ * See the comments on ip6ip6_kernel_tnl_add() for more information. -+ **/ -+ -+static inline struct ip6_tnl * -+ip6ip6_kernel_tnl_unlink(void) -+{ -+ struct ip6_tnl *t; -+ -+ write_lock_bh(&ip6ip6_kernel_lock); -+ if ((t = tnls_kernel[0]) != NULL) { -+ tnls_kernel[0] = t->next; -+ kdev_count--; -+ } -+ write_unlock_bh(&ip6ip6_kernel_lock); -+ return t; -+} -+ -+/** -+ * ip6ip6_tnl_link - add tunnel to hash table -+ * @t: tunnel to be added -+ **/ -+ -+static void -+ip6ip6_tnl_link(struct ip6_tnl *t) -+{ -+ struct ip6_tnl **tp = ip6ip6_bucket(&t->parms); -+ -+ write_lock_bh(&ip6ip6_lock); -+ t->next = *tp; -+ *tp = t; -+ write_unlock_bh(&ip6ip6_lock); -+} -+ -+/** -+ * ip6ip6_tnl_unlink - remove tunnel from hash table -+ * @t: tunnel to be removed -+ **/ -+ -+static void -+ip6ip6_tnl_unlink(struct ip6_tnl *t) -+{ -+ struct ip6_tnl **tp; -+ -+ write_lock_bh(&ip6ip6_lock); -+ for (tp = ip6ip6_bucket(&t->parms); *tp; tp = &(*tp)->next) { -+ if (t == *tp) { -+ *tp = t->next; -+ break; -+ } -+ } -+ write_unlock_bh(&ip6ip6_lock); -+} -+ -+/** -+ * ip6ip6_tnl_create() - create a new tunnel -+ * @p: tunnel parameters -+ * @pt: pointer to new tunnel -+ * -+ * Description: -+ * Create tunnel matching given parameters. New kernel managed devices are -+ * not put in the normal hash structure, but are instead cached for later -+ * use. -+ * -+ * Return: -+ * 0 on success -+ **/ -+ -+ -+static int __ip6ip6_tnl_create(struct ip6_tnl_parm *p, -+ struct ip6_tnl **pt, -+ int kernel_list) -+{ -+ struct net_device *dev; -+ int err = -ENOBUFS; -+ struct ip6_tnl *t; -+ -+ MOD_INC_USE_COUNT; -+ dev = kmalloc(sizeof (*dev) + sizeof (*t), GFP_KERNEL); -+ if (!dev) { -+ MOD_DEC_USE_COUNT; -+ return err; -+ } -+ memset(dev, 0, sizeof (*dev) + sizeof (*t)); -+ dev->priv = (void *) (dev + 1); -+ t = (struct ip6_tnl *) dev->priv; -+ t->dev = dev; -+ dev->init = ip6ip6_tnl_dev_init; -+ dev->features |= NETIF_F_DYNALLOC; -+ if (kernel_list) { -+ memcpy(t->parms.name, p->name, IFNAMSIZ - 1); -+ t->parms.proto = IPPROTO_IPV6; -+ t->parms.flags = IP6_TNL_F_KERNEL_DEV; -+ } else { -+ memcpy(&t->parms, p, sizeof (*p)); -+ } -+ t->parms.name[IFNAMSIZ - 1] = '\0'; -+ strcpy(dev->name, t->parms.name); -+ if (!dev->name[0]) { -+ int i; -+ for (i = 0; i < IP6_TNL_MAX; i++) { -+ sprintf(dev->name, "ip6tnl%d", i); -+ if (__dev_get_by_name(dev->name) == NULL) -+ break; -+ } -+ -+ if (i == IP6_TNL_MAX) { -+ goto failed; -+ } -+ memcpy(t->parms.name, dev->name, IFNAMSIZ); -+ } -+ if ((err = register_netdevice(dev)) < 0) { -+ goto failed; -+ } -+ dev_hold(dev); -+ if (kernel_list) { -+ ip6ip6_kernel_tnl_link(t); -+ } else { -+ ip6ip6_tnl_link(t); -+ } -+ *pt = t; -+ return 0; -+failed: -+ kfree(dev); -+ MOD_DEC_USE_COUNT; -+ return err; -+} -+ -+ -+int ip6ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt) -+{ -+ return __ip6ip6_tnl_create(p, pt, 0); -+} -+ -+ -+static void manage_kernel_tnls(void *foo); -+ -+static struct tq_struct manager_task = { -+ routine:manage_kernel_tnls, -+ data:NULL -+}; -+ -+/** -+ * manage_kernel_tnls() - create and destroy kernel tunnels -+ * -+ * Description: -+ * manage_kernel_tnls() creates new kernel devices if there -+ * are less than $min_kdev_count of them and deletes old ones if -+ * there are less than $max_kdev_count of them in the cache -+ * -+ * Note: -+ * Schedules itself to be run later in process context if called from -+ * interrupt. Therefore only works synchronously when called from process -+ * context. -+ **/ -+ -+static void -+manage_kernel_tnls(void *foo) -+{ -+ struct ip6_tnl *t = NULL; -+ struct ip6_tnl_parm parm; -+ -+ /* We can't do this processing in interrupt -+ context so schedule it for later */ -+ if (in_interrupt()) { -+ read_lock(&ip6ip6_kernel_lock); -+ if (!shutdown && -+ (kdev_count < min_kdev_count || -+ kdev_count > max_kdev_count)) { -+ schedule_task(&manager_task); -+ } -+ read_unlock(&ip6ip6_kernel_lock); -+ return; -+ } -+ -+ rtnl_lock(); -+ read_lock_bh(&ip6ip6_kernel_lock); -+ memset(&parm, 0, sizeof (parm)); -+ parm.flags = IP6_TNL_F_KERNEL_DEV; -+ /* Create tunnels until there are at least min_kdev_count */ -+ while (kdev_count < min_kdev_count) { -+ read_unlock_bh(&ip6ip6_kernel_lock); -+ if (!__ip6ip6_tnl_create(&parm, &t, 1)) { -+ dev_open(t->dev); -+ } else { -+ goto err; -+ } -+ read_lock_bh(&ip6ip6_kernel_lock); -+ } -+ -+ /* Destroy tunnels until there are at most max_kdev_count */ -+ while (kdev_count > max_kdev_count) { -+ read_unlock_bh(&ip6ip6_kernel_lock); -+ if ((t = ip6ip6_kernel_tnl_unlink()) != NULL) { -+ unregister_netdevice(t->dev); -+ } else { -+ goto err; -+ } -+ read_lock_bh(&ip6ip6_kernel_lock); -+ } -+ read_unlock_bh(&ip6ip6_kernel_lock); -+err: -+ rtnl_unlock(); -+} -+ -+/** -+ * ip6ip6_tnl_inc_max_kdev_count() - increase max kernel dev cache size -+ * @n: size increase -+ * Description: -+ * Increase the upper limit for the number of kernel devices allowed in the -+ * cache at any on time. -+ **/ -+ -+unsigned int -+ip6ip6_tnl_inc_max_kdev_count(unsigned int n) -+{ -+ write_lock_bh(&ip6ip6_kernel_lock); -+ max_kdev_count += n; -+ write_unlock_bh(&ip6ip6_kernel_lock); -+ manage_kernel_tnls(NULL); -+ return max_kdev_count; -+} -+ -+/** -+ * ip6ip6_tnl_dec_max_kdev_count() - decrease max kernel dev cache size -+ * @n: size decrement -+ * Description: -+ * Decrease the upper limit for the number of kernel devices allowed in the -+ * cache at any on time. -+ **/ -+ -+unsigned int -+ip6ip6_tnl_dec_max_kdev_count(unsigned int n) -+{ -+ write_lock_bh(&ip6ip6_kernel_lock); -+ max_kdev_count -= min(max_kdev_count, n); -+ if (max_kdev_count < min_kdev_count) -+ min_kdev_count = max_kdev_count; -+ write_unlock_bh(&ip6ip6_kernel_lock); -+ manage_kernel_tnls(NULL); -+ return max_kdev_count; -+} -+ -+/** -+ * ip6ip6_tnl_inc_min_kdev_count() - increase min kernel dev cache size -+ * @n: size increase -+ * Description: -+ * Increase the lower limit for the number of kernel devices allowed in the -+ * cache at any on time. -+ **/ -+ -+unsigned int -+ip6ip6_tnl_inc_min_kdev_count(unsigned int n) -+{ -+ write_lock_bh(&ip6ip6_kernel_lock); -+ min_kdev_count += n; -+ if (min_kdev_count > max_kdev_count) -+ max_kdev_count = min_kdev_count; -+ write_unlock_bh(&ip6ip6_kernel_lock); -+ manage_kernel_tnls(NULL); -+ return min_kdev_count; -+} -+ -+/** -+ * ip6ip6_tnl_dec_min_kdev_count() - decrease min kernel dev cache size -+ * @n: size decrement -+ * Description: -+ * Decrease the lower limit for the number of kernel devices allowed in the -+ * cache at any on time. -+ **/ -+ -+unsigned int -+ip6ip6_tnl_dec_min_kdev_count(unsigned int n) -+{ -+ write_lock_bh(&ip6ip6_kernel_lock); -+ min_kdev_count -= min(min_kdev_count, n); -+ write_unlock_bh(&ip6ip6_kernel_lock); -+ manage_kernel_tnls(NULL); -+ return min_kdev_count; -+} -+ -+/** -+ * ip6ip6_tnl_locate - find or create tunnel matching given parameters -+ * @p: tunnel parameters -+ * @create: != 0 if allowed to create new tunnel if no match found -+ * -+ * Description: -+ * ip6ip6_tnl_locate() first tries to locate an existing tunnel -+ * based on @parms. If this is unsuccessful, but @create is set a new -+ * tunnel device is created and registered for use. -+ * -+ * Return: -+ * 0 if tunnel located or created, -+ * -EINVAL if parameters incorrect, -+ * -ENODEV if no matching tunnel available -+ **/ -+ -+int ip6ip6_tnl_locate(struct ip6_tnl_parm *p, struct ip6_tnl **pt, int create) -+{ -+ struct in6_addr *remote = &p->raddr; -+ struct in6_addr *local = &p->laddr; -+ struct ip6_tnl *t; -+ -+ if (p->proto != IPPROTO_IPV6) -+ return -EINVAL; -+ -+ for (t = *ip6ip6_bucket(p); t; t = t->next) { -+ if (!ipv6_addr_cmp(local, &t->parms.laddr) && -+ !ipv6_addr_cmp(remote, &t->parms.raddr)) { -+ *pt = t; -+ return (create ? -EEXIST : 0); -+ } -+ } -+ return ip6ip6_tnl_create(p, pt); -+} -+ -+/** -+ * ip6ip6_tnl_dev_destructor - tunnel device destructor -+ * @dev: the device to be destroyed -+ **/ -+ -+static void -+ip6ip6_tnl_dev_destructor(struct net_device *dev) -+{ -+ if (dev != &ip6ip6_fb_tnl_dev) { -+ MOD_DEC_USE_COUNT; -+ } -+} -+ -+/** -+ * ip6ip6_tnl_dev_uninit - tunnel device uninitializer -+ * @dev: the device to be destroyed -+ * -+ * Description: -+ * ip6ip6_tnl_dev_uninit() removes tunnel from its list -+ **/ -+ -+static void -+ip6ip6_tnl_dev_uninit(struct net_device *dev) -+{ -+ struct ip6_tnl *t = (struct ip6_tnl *) dev->priv; -+ -+ if (dev == &ip6ip6_fb_tnl_dev) { -+ write_lock_bh(&ip6ip6_lock); -+ tnls_wc[0] = NULL; -+ write_unlock_bh(&ip6ip6_lock); -+ } else { -+ ip6ip6_tnl_unlink(t); -+ } -+ sock_release(t->sock); -+ dev_put(dev); -+} -+ -+/** -+ * parse_tvl_tnl_enc_lim - handle encapsulation limit option -+ * @skb: received socket buffer -+ * -+ * Return: -+ * 0 if none was found, -+ * else index to encapsulation limit -+ **/ -+ -+static __u16 -+parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) -+{ -+ struct ipv6hdr *ipv6h = (struct ipv6hdr *) raw; -+ __u8 nexthdr = ipv6h->nexthdr; -+ __u16 off = sizeof (*ipv6h); -+ -+ while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) { -+ __u16 optlen = 0; -+ struct ipv6_opt_hdr *hdr; -+ if (raw + off + sizeof (*hdr) > skb->data && -+ !pskb_may_pull(skb, raw - skb->data + off + sizeof (*hdr))) -+ break; -+ -+ hdr = (struct ipv6_opt_hdr *) (raw + off); -+ if (nexthdr == NEXTHDR_FRAGMENT) { -+ struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr; -+ if (frag_hdr->frag_off) -+ break; -+ optlen = 8; -+ } else if (nexthdr == NEXTHDR_AUTH) { -+ optlen = (hdr->hdrlen + 2) << 2; -+ } else { -+ optlen = ipv6_optlen(hdr); -+ } -+ if (nexthdr == NEXTHDR_DEST) { -+ __u16 i = off + 2; -+ while (1) { -+ struct ipv6_tlv_tnl_enc_lim *tel; -+ -+ /* No more room for encapsulation limit */ -+ if (i + sizeof (*tel) > off + optlen) -+ break; -+ -+ tel = (struct ipv6_tlv_tnl_enc_lim *) &raw[i]; -+ /* return index of option if found and valid */ -+ if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT && -+ tel->length == 1) -+ return i; -+ /* else jump to next option */ -+ if (tel->type) -+ i += tel->length + 2; -+ else -+ i++; -+ } -+ } -+ nexthdr = hdr->nexthdr; -+ off += optlen; -+ } -+ return 0; -+} -+ -+/** -+ * ip6ip6_err - tunnel error handler -+ * -+ * Description: -+ * ip6ip6_err() should handle errors in the tunnel according -+ * to the specifications in RFC 2473. -+ **/ -+ -+void ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, -+ int type, int code, int offset, __u32 info) -+{ -+ struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; -+ struct ip6_tnl *t; -+ int rel_msg = 0; -+ int rel_type = ICMPV6_DEST_UNREACH; -+ int rel_code = ICMPV6_ADDR_UNREACH; -+ __u32 rel_info = 0; -+ __u16 len; -+ -+ /* If the packet doesn't contain the original IPv6 header we are -+ in trouble since we might need the source address for furter -+ processing of the error. */ -+ -+ read_lock(&ip6ip6_lock); -+ if ((t = ip6ip6_tnl_lookup(&ipv6h->daddr, &ipv6h->saddr)) == NULL) -+ goto out; -+ -+ switch (type) { -+ __u32 teli; -+ struct ipv6_tlv_tnl_enc_lim *tel; -+ __u32 mtu; -+ case ICMPV6_DEST_UNREACH: -+ if (net_ratelimit()) -+ printk(KERN_WARNING -+ "%s: Path to destination invalid " -+ "or inactive!\n", t->parms.name); -+ rel_msg = 1; -+ break; -+ case ICMPV6_TIME_EXCEED: -+ if (code == ICMPV6_EXC_HOPLIMIT) { -+ if (net_ratelimit()) -+ printk(KERN_WARNING -+ "%s: Too small hop limit or " -+ "routing loop in tunnel!\n", -+ t->parms.name); -+ rel_msg = 1; -+ } -+ break; -+ case ICMPV6_PARAMPROB: -+ /* ignore if parameter problem not caused by a tunnel -+ encapsulation limit sub-option */ -+ if (code != ICMPV6_HDR_FIELD) { -+ break; -+ } -+ teli = parse_tlv_tnl_enc_lim(skb, skb->data); -+ -+ if (teli && teli == ntohl(info) - 2) { -+ tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; -+ if (tel->encap_limit == 0) { -+ if (net_ratelimit()) -+ printk(KERN_WARNING -+ "%s: Too small encapsulation " -+ "limit or routing loop in " -+ "tunnel!\n", t->parms.name); -+ rel_msg = 1; -+ } -+ } -+ break; -+ case ICMPV6_PKT_TOOBIG: -+ mtu = ntohl(info) - offset; -+ if (mtu < IPV6_MIN_MTU) -+ mtu = IPV6_MIN_MTU; -+ t->dev->mtu = mtu; -+ -+ if ((len = sizeof (*ipv6h) + ipv6h->payload_len) > mtu) { -+ rel_type = ICMPV6_PKT_TOOBIG; -+ rel_code = 0; -+ rel_info = mtu; -+ rel_msg = 1; -+ } -+ break; -+ } -+ if (rel_msg && pskb_may_pull(skb, offset + sizeof (*ipv6h))) { -+ struct rt6_info *rt; -+ struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); -+ if (!skb2) -+ goto out; -+ -+ dst_release(skb2->dst); -+ skb2->dst = NULL; -+ skb_pull(skb2, offset); -+ skb2->nh.raw = skb2->data; -+ -+ /* Try to guess incoming interface */ -+ rt = rt6_lookup(&skb2->nh.ipv6h->saddr, NULL, 0, 0); -+ -+ if (rt && rt->rt6i_dev) -+ skb2->dev = rt->rt6i_dev; -+ -+ icmpv6_send(skb2, rel_type, rel_code, rel_info, skb2->dev); -+ -+ if (rt) -+ dst_release(&rt->u.dst); -+ -+ kfree_skb(skb2); -+ } -+out: -+ read_unlock(&ip6ip6_lock); -+} -+ -+/** -+ * call_hooks - call ipv6 tunnel hooks -+ * @hooknum: hook number, either %IP6_TNL_PRE_ENCAP, or -+ * %IP6_TNL_PRE_DECAP -+ * @t: the current tunnel -+ * @skb: the tunneled packet -+ * -+ * Description: -+ * Pass packet to all the hook functions until %IP6_TNL_DROP -+ * -+ * Return: -+ * %IP6_TNL_ACCEPT or %IP6_TNL_DROP -+ **/ -+ -+static inline int -+call_hooks(unsigned int hooknum, struct ip6_tnl *t, struct sk_buff *skb) -+{ -+ struct ip6_tnl_hook_ops *h; -+ int accept = IP6_TNL_ACCEPT; -+ -+ if (hooknum < IP6_TNL_MAXHOOKS) { -+ struct list_head *i; -+ read_lock(&ip6ip6_hook_lock); -+ for (i = hooks[hooknum].next; i != &hooks[hooknum]; i = i->next) { -+ h = (struct ip6_tnl_hook_ops *) i; -+ -+ if (h->hook) { -+ accept = h->hook(t, skb); -+ -+ if (accept != IP6_TNL_ACCEPT) -+ break; -+ } -+ } -+ read_unlock(&ip6ip6_hook_lock); -+ } -+ return accept; -+} -+ -+/** -+ * ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally -+ * @skb: received socket buffer -+ * -+ * Return: 0 -+ **/ -+ -+int ip6ip6_rcv(struct sk_buff *skb) -+{ -+ struct ipv6hdr *ipv6h; -+ struct ip6_tnl *t; -+ -+ if (!pskb_may_pull(skb, sizeof (*ipv6h))) -+ goto discard; -+ -+ ipv6h = skb->nh.ipv6h; -+ -+ read_lock(&ip6ip6_lock); -+ -+ if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) { -+ if (!(t->parms.flags & IP6_TNL_F_CAP_RCV) || -+ call_hooks(IP6_TNL_PRE_DECAP, t, skb) != IP6_TNL_ACCEPT) { -+ t->stat.rx_dropped++; -+ read_unlock(&ip6ip6_lock); -+ goto discard; -+ } -+ skb->mac.raw = skb->nh.raw; -+ skb->nh.raw = skb->data; -+ skb->protocol = htons(ETH_P_IPV6); -+ skb->pkt_type = PACKET_HOST; -+ memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); -+ skb->dev = t->dev; -+ dst_release(skb->dst); -+ skb->dst = NULL; -+ t->stat.rx_packets++; -+ t->stat.rx_bytes += skb->len; -+ netif_rx(skb); -+ read_unlock(&ip6ip6_lock); -+ return 0; -+ } -+ read_unlock(&ip6ip6_lock); -+ icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev); -+discard: -+ kfree_skb(skb); -+ return 0; -+} -+ -+static inline struct ipv6_txoptions *create_tel(__u8 encap_limit) -+{ -+ struct ipv6_tlv_tnl_enc_lim *tel; -+ struct ipv6_txoptions *opt; -+ __u8 *raw; -+ -+ int opt_len = sizeof(*opt) + IPV6_TLV_TEL_DST_SIZE; -+ -+ if (!(opt = kmalloc(opt_len, GFP_ATOMIC))) { -+ return NULL; -+ } -+ memset(opt, 0, opt_len); -+ opt->tot_len = opt_len; -+ opt->dst0opt = (struct ipv6_opt_hdr *) (opt + 1); -+ opt->opt_nflen = 8; -+ -+ tel = (struct ipv6_tlv_tnl_enc_lim *) (opt->dst0opt + 1); -+ tel->type = IPV6_TLV_TNL_ENCAP_LIMIT; -+ tel->length = 1; -+ tel->encap_limit = encap_limit; -+ -+ raw = (__u8 *) opt->dst0opt; -+ raw[5] = IPV6_TLV_PADN; -+ raw[6] = 1; -+ -+ return opt; -+} -+ -+static int -+ip6ip6_getfrag(const void *data, struct in6_addr *addr, -+ char *buff, unsigned int offset, unsigned int len) -+{ -+ memcpy(buff, data + offset, len); -+ return 0; -+} -+ -+/** -+ * ip6ip6_tnl_addr_conflict - compare packet addresses to tunnel's own -+ * @t: the outgoing tunnel device -+ * @hdr: IPv6 header from the incoming packet -+ * -+ * Description: -+ * Avoid trivial tunneling loop by checking that tunnel exit-point -+ * doesn't match source of incoming packet. -+ * -+ * Return: -+ * 1 if conflict, -+ * 0 else -+ **/ -+ -+static inline int -+ip6ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr) -+{ -+ return !ipv6_addr_cmp(&t->parms.raddr, &hdr->saddr); -+} -+ -+/** -+ * ip6ip6_tnl_xmit - encapsulate packet and send -+ * @skb: the outgoing socket buffer -+ * @dev: the outgoing tunnel device -+ * -+ * Description: -+ * Build new header and do some sanity checks on the packet before sending -+ * it to ip6_build_xmit(). -+ * -+ * Return: -+ * 0 -+ **/ -+ -+int ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) -+{ -+ struct ip6_tnl *t = (struct ip6_tnl *) dev->priv; -+ struct net_device_stats *stats = &t->stat; -+ struct ipv6hdr *ipv6h = skb->nh.ipv6h; -+ struct ipv6_txoptions *opt = NULL; -+ int encap_limit = -1; -+ __u16 offset; -+ struct flowi fl; -+ int err = 0; -+ struct dst_entry *dst; -+ struct sock *sk = t->sock->sk; -+ struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; -+ int mtu; -+ -+ if (t->recursion++) { -+ stats->collisions++; -+ goto tx_err; -+ } -+ if (skb->protocol != htons(ETH_P_IPV6) || -+ !(t->parms.flags & IP6_TNL_F_CAP_XMIT) || -+ ip6ip6_tnl_addr_conflict(t, ipv6h)) { -+ goto tx_err; -+ } -+ if ((offset = parse_tlv_tnl_enc_lim(skb, skb->nh.raw)) > 0) { -+ struct ipv6_tlv_tnl_enc_lim *tel; -+ tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->nh.raw[offset]; -+ if (tel->encap_limit == 0) { -+ icmpv6_send(skb, ICMPV6_PARAMPROB, -+ ICMPV6_HDR_FIELD, offset + 2, skb->dev); -+ goto tx_err; -+ } -+ encap_limit = tel->encap_limit - 1; -+ } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) { -+ encap_limit = t->parms.encap_limit; -+ } -+ if (call_hooks(IP6_TNL_PRE_ENCAP, t, skb) != IP6_TNL_ACCEPT) -+ goto discard; -+ memcpy(&fl, &t->fl, sizeof (fl)); -+ -+ if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) -+ fl.fl6_flowlabel |= (*(__u32 *) ipv6h & IPV6_TCLASS_MASK); -+ if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)) -+ fl.fl6_flowlabel |= (*(__u32 *) ipv6h & IPV6_FLOWLABEL_MASK); -+ -+ if (encap_limit >= 0 && (opt = create_tel(encap_limit)) == NULL) -+ goto tx_err; -+ -+ dst = __sk_dst_check(sk, np->dst_cookie); -+ -+ if (dst) { -+ if (np->daddr_cache == NULL || -+ ipv6_addr_cmp(fl.fl6_dst, np->daddr_cache) || -+#ifdef CONFIG_IPV6_SUBTREES -+ np->saddr_cache == NULL || -+ ipv6_addr_cmp(fl.fl6_src, np->saddr_cache) || -+#endif -+ (fl.oif && fl.oif != dst->dev->ifindex)) { -+ dst = NULL; -+ } else { -+ dst_hold(dst); -+ } -+ } -+ if (dst == NULL) { -+ dst = ip6_route_output(sk, &fl); -+ if (dst->error) { -+ stats->tx_carrier_errors++; -+ dst_link_failure(skb); -+ goto tx_err_dst_release; -+ } -+ /* local routing loop */ -+ if (dst->dev == dev) { -+ stats->collisions++; -+ if (net_ratelimit()) -+ printk(KERN_WARNING -+ "%s: Local routing loop detected!\n", -+ t->parms.name); -+ goto tx_err_dst_release; -+ } -+ } -+ mtu = dst->pmtu - sizeof (*ipv6h); -+ if (opt) { -+ mtu -= (opt->opt_nflen + opt->opt_flen); -+ } -+ if (mtu < IPV6_MIN_MTU) -+ mtu = IPV6_MIN_MTU; -+ if (skb->dst && mtu < skb->dst->pmtu) { -+ struct rt6_info *rt = (struct rt6_info *) skb->dst; -+ rt->rt6i_flags |= RTF_MODIFIED; -+ rt->u.dst.pmtu = mtu; -+ } -+ if (skb->len > mtu) { -+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); -+ goto tx_err_dst_release; -+ } -+ ip6_dst_store(sk, dst, &np->daddr, &np->saddr); -+ err = ip6_build_xmit(sk, ip6ip6_getfrag, (void *) skb->nh.raw, -+ &fl, skb->len, opt, t->parms.hop_limit, -+ MSG_DONTWAIT); -+ -+ if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) { -+ stats->tx_bytes += skb->len; -+ stats->tx_packets++; -+ } else { -+ stats->tx_errors++; -+ stats->tx_aborted_errors++; -+ } -+ if (opt) -+ kfree(opt); -+ kfree_skb(skb); -+ t->recursion--; -+ return 0; -+tx_err_dst_release: -+ dst_release(dst); -+ if (opt) -+ kfree(opt); -+tx_err: -+ stats->tx_errors++; -+discard: -+ stats->tx_dropped++; -+ kfree_skb(skb); -+ t->recursion--; -+ return 0; -+} -+ -+static void ip6_tnl_set_cap(struct ip6_tnl *t) -+{ -+ struct ip6_tnl_parm *p = &t->parms; -+ struct in6_addr *laddr = &p->laddr; -+ struct in6_addr *raddr = &p->raddr; -+ int ltype = ipv6_addr_type(laddr); -+ int rtype = ipv6_addr_type(raddr); -+ -+ p->flags &= ~(IP6_TNL_F_CAP_XMIT|IP6_TNL_F_CAP_RCV); -+ -+ if (ltype != IPV6_ADDR_ANY && rtype != IPV6_ADDR_ANY && -+ ((ltype|rtype) & -+ (IPV6_ADDR_UNICAST| -+ IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL| -+ IPV6_ADDR_MAPPED|IPV6_ADDR_RESERVED)) == IPV6_ADDR_UNICAST) { -+ struct net_device *ldev = NULL; -+ int l_ok = 1; -+ int r_ok = 1; -+ -+ if (p->link) -+ ldev = dev_get_by_index(p->link); -+ -+ if ((ltype&IPV6_ADDR_UNICAST) && !ipv6_chk_addr(laddr, ldev)) -+ l_ok = 0; -+ -+ if ((rtype&IPV6_ADDR_UNICAST) && ipv6_chk_addr(raddr, NULL)) -+ r_ok = 0; -+ -+ if (l_ok && r_ok) { -+ if (ltype&IPV6_ADDR_UNICAST) -+ p->flags |= IP6_TNL_F_CAP_XMIT; -+ if (rtype&IPV6_ADDR_UNICAST) -+ p->flags |= IP6_TNL_F_CAP_RCV; -+ } -+ if (ldev) -+ dev_put(ldev); -+ } -+} -+ -+static void ip6ip6_tnl_link_config(struct ip6_tnl *t) -+{ -+ struct net_device *dev = t->dev; -+ struct ip6_tnl_parm *p = &t->parms; -+ struct flowi *fl = &t->fl; -+ -+ /* Set up flowi template */ -+ fl->fl6_src = &p->laddr; -+ fl->fl6_dst = &p->raddr; -+ fl->oif = p->link; -+ fl->fl6_flowlabel = 0; -+ -+ if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS)) -+ fl->fl6_flowlabel |= IPV6_TCLASS_MASK & htonl(p->flowinfo); -+ if (!(p->flags&IP6_TNL_F_USE_ORIG_FLOWLABEL)) -+ fl->fl6_flowlabel |= IPV6_FLOWLABEL_MASK & htonl(p->flowinfo); -+ -+ ip6_tnl_set_cap(t); -+ -+ if (p->flags&IP6_TNL_F_CAP_XMIT && p->flags&IP6_TNL_F_CAP_RCV) -+ dev->flags |= IFF_POINTOPOINT; -+ else -+ dev->flags &= ~IFF_POINTOPOINT; -+ -+ if (p->flags & IP6_TNL_F_CAP_XMIT) { -+ struct rt6_info *rt = rt6_lookup(&p->raddr, &p->laddr, -+ p->link, 0); -+ -+ if (rt == NULL) -+ return; -+ -+ if (rt->rt6i_dev) { -+ dev->iflink = rt->rt6i_dev->ifindex; -+ -+ dev->hard_header_len = rt->rt6i_dev->hard_header_len + -+ sizeof (struct ipv6hdr); -+ -+ dev->mtu = rt->rt6i_dev->mtu - sizeof (struct ipv6hdr); -+ -+ if (dev->mtu < IPV6_MIN_MTU) -+ dev->mtu = IPV6_MIN_MTU; -+ } -+ dst_release(&rt->u.dst); -+ } -+} -+ -+/** -+ * __ip6ip6_tnl_change - update the tunnel parameters -+ * @t: tunnel to be changed -+ * @p: tunnel configuration parameters -+ * -+ * Description: -+ * __ip6ip6_tnl_change() updates the tunnel parameters -+ **/ -+ -+static void -+__ip6ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p) -+{ -+ ipv6_addr_copy(&t->parms.laddr, &p->laddr); -+ ipv6_addr_copy(&t->parms.raddr, &p->raddr); -+ t->parms.flags = p->flags; -+ t->parms.hop_limit = p->hop_limit; -+ t->parms.encap_limit = p->encap_limit; -+ t->parms.flowinfo = p->flowinfo; -+ ip6ip6_tnl_link_config(t); -+} -+ -+void ip6ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p) -+{ -+ ip6ip6_tnl_unlink(t); -+ __ip6ip6_tnl_change(t, p); -+ ip6ip6_tnl_link(t); -+} -+ -+/** -+ * ip6ip6_kernel_tnl_add - configure and add kernel tunnel to hash -+ * @p: kernel tunnel configuration parameters -+ * -+ * Description: -+ * ip6ip6_kernel_tnl_add() fetches an unused kernel tunnel configures -+ * it according to @p and places it among the active tunnels. -+ * -+ * Return: -+ * number of references to tunnel on success, -+ * %-EEXIST if there is already a device matching description -+ * %-EINVAL if p->flags doesn't have %IP6_TNL_F_KERNEL_DEV raised, -+ * %-ENODEV if there are no unused kernel tunnels available -+ * -+ * Note: -+ * The code for creating, opening, closing and destroying network devices -+ * must be called from process context, while the Mobile IP code, which -+ * needs the tunnel devices, unfortunately runs in interrupt context. -+ * -+ * The devices must be created and opened in advance, then placed in a -+ * list where the kernel can fetch and ready them for use at a later time. -+ * -+ **/ -+ -+int -+ip6ip6_kernel_tnl_add(struct ip6_tnl_parm *p) -+{ -+ struct ip6_tnl *t; -+ -+ if (!(p->flags & IP6_TNL_F_KERNEL_DEV)) -+ return -EINVAL; -+ if ((t = ip6ip6_tnl_lookup(&p->raddr, &p->laddr)) != NULL && -+ t != &ip6ip6_fb_tnl) { -+ /* Handle duplicate tunnels by incrementing -+ reference count */ -+ atomic_inc(&t->refcnt); -+ goto out; -+ } -+ if ((t = ip6ip6_kernel_tnl_unlink()) == NULL) -+ return -ENODEV; -+ __ip6ip6_tnl_change(t, p); -+ -+ atomic_inc(&t->refcnt); -+ -+ ip6ip6_tnl_link(t); -+ -+ manage_kernel_tnls(NULL); -+out: -+ return atomic_read(&t->refcnt); -+} -+ -+/** -+ * ip6ip6_kernel_tnl_del - delete no longer needed kernel tunnel -+ * @t: kernel tunnel to be removed from hash -+ * -+ * Description: -+ * ip6ip6_kernel_tnl_del() removes and deconfigures the tunnel @t -+ * and places it among the unused kernel devices. -+ * -+ * Return: -+ * number of references on success, -+ * %-EINVAL if p->flags doesn't have %IP6_TNL_F_KERNEL_DEV raised, -+ * -+ * Note: -+ * See the comments on ip6ip6_kernel_tnl_add() for more information. -+ **/ -+ -+int -+ip6ip6_kernel_tnl_del(struct ip6_tnl *t) -+{ -+ if (!t) -+ return -ENODEV; -+ -+ if (!(t->parms.flags & IP6_TNL_F_KERNEL_DEV)) -+ return -EINVAL; -+ -+ if (atomic_dec_and_test(&t->refcnt)) { -+ struct ip6_tnl_parm p; -+ ip6ip6_tnl_unlink(t); -+ memset(&p, 0, sizeof (p)); -+ p.flags = IP6_TNL_F_KERNEL_DEV; -+ -+ __ip6ip6_tnl_change(t, &p); -+ -+ ip6ip6_kernel_tnl_link(t); -+ -+ manage_kernel_tnls(NULL); -+ } -+ return atomic_read(&t->refcnt); -+} -+ -+/** -+ * ip6ip6_tnl_ioctl - configure ipv6 tunnels from userspace -+ * @dev: virtual device associated with tunnel -+ * @ifr: parameters passed from userspace -+ * @cmd: command to be performed -+ * -+ * Description: -+ * ip6ip6_tnl_ioctl() is used for managing IPv6 tunnels -+ * from userspace. -+ * -+ * The possible commands are the following: -+ * %SIOCGETTUNNEL: get tunnel parameters for device -+ * %SIOCADDTUNNEL: add tunnel matching given tunnel parameters -+ * %SIOCCHGTUNNEL: change tunnel parameters to those given -+ * %SIOCDELTUNNEL: delete tunnel -+ * -+ * The fallback device "ip6tnl0", created during module -+ * initialization, can be used for creating other tunnel devices. -+ * -+ * Return: -+ * 0 on success, -+ * %-EFAULT if unable to copy data to or from userspace, -+ * %-EPERM if current process hasn't %CAP_NET_ADMIN set or attempting -+ * to configure kernel devices from userspace, -+ * %-EINVAL if passed tunnel parameters are invalid, -+ * %-EEXIST if changing a tunnel's parameters would cause a conflict -+ * %-ENODEV if attempting to change or delete a nonexisting device -+ * -+ * Note: -+ * See the comments on ip6ip6_kernel_tnl_add() for more information -+ * about kernel tunnels. -+ * **/ -+ -+static int -+ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -+{ -+ int err = 0; -+ int create; -+ struct ip6_tnl_parm p; -+ struct ip6_tnl *t = NULL; -+ -+ MOD_INC_USE_COUNT; -+ -+ switch (cmd) { -+ case SIOCGETTUNNEL: -+ if (dev == &ip6ip6_fb_tnl_dev) { -+ if (copy_from_user(&p, -+ ifr->ifr_ifru.ifru_data, -+ sizeof (p))) { -+ err = -EFAULT; -+ break; -+ } -+ if ((err = ip6ip6_tnl_locate(&p, &t, 0)) == -ENODEV) -+ t = (struct ip6_tnl *) dev->priv; -+ else if (err) -+ break; -+ } else -+ t = (struct ip6_tnl *) dev->priv; -+ -+ memcpy(&p, &t->parms, sizeof (p)); -+ if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) { -+ err = -EFAULT; -+ } -+ break; -+ case SIOCADDTUNNEL: -+ case SIOCCHGTUNNEL: -+ err = -EPERM; -+ create = (cmd == SIOCADDTUNNEL); -+ if (!capable(CAP_NET_ADMIN)) -+ break; -+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) { -+ err = -EFAULT; -+ break; -+ } -+ if (p.flags & IP6_TNL_F_KERNEL_DEV) { -+ break; -+ } -+ if (!create && dev != &ip6ip6_fb_tnl_dev) { -+ t = (struct ip6_tnl *) dev->priv; -+ } -+ if (!t && (err = ip6ip6_tnl_locate(&p, &t, create))) { -+ break; -+ } -+ if (cmd == SIOCCHGTUNNEL) { -+ if (t->dev != dev) { -+ err = -EEXIST; -+ break; -+ } -+ if (t->parms.flags & IP6_TNL_F_KERNEL_DEV) { -+ err = -EPERM; -+ break; -+ } -+ ip6ip6_tnl_change(t, &p); -+ netdev_state_change(dev); -+ } -+ if (copy_to_user(ifr->ifr_ifru.ifru_data, -+ &t->parms, sizeof (p))) { -+ err = -EFAULT; -+ } else { -+ err = 0; -+ } -+ break; -+ case SIOCDELTUNNEL: -+ err = -EPERM; -+ if (!capable(CAP_NET_ADMIN)) -+ break; -+ -+ if (dev == &ip6ip6_fb_tnl_dev) { -+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, -+ sizeof (p))) { -+ err = -EFAULT; -+ break; -+ } -+ err = ip6ip6_tnl_locate(&p, &t, 0); -+ if (err) -+ break; -+ if (t == &ip6ip6_fb_tnl) { -+ err = -EPERM; -+ break; -+ } -+ } else { -+ t = (struct ip6_tnl *) dev->priv; -+ } -+ if (t->parms.flags & IP6_TNL_F_KERNEL_DEV) -+ err = -EPERM; -+ else -+ err = unregister_netdevice(t->dev); -+ break; -+ default: -+ err = -EINVAL; -+ } -+ MOD_DEC_USE_COUNT; -+ return err; -+} -+ -+/** -+ * ip6ip6_tnl_get_stats - return the stats for tunnel device -+ * @dev: virtual device associated with tunnel -+ * -+ * Return: stats for device -+ **/ -+ -+static struct net_device_stats * -+ip6ip6_tnl_get_stats(struct net_device *dev) -+{ -+ return &(((struct ip6_tnl *) dev->priv)->stat); -+} -+ -+/** -+ * ip6ip6_tnl_change_mtu - change mtu manually for tunnel device -+ * @dev: virtual device associated with tunnel -+ * @new_mtu: the new mtu -+ * -+ * Return: -+ * 0 on success, -+ * %-EINVAL if mtu too small -+ **/ -+ -+static int -+ip6ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) -+{ -+ if (new_mtu < IPV6_MIN_MTU) { -+ return -EINVAL; -+ } -+ dev->mtu = new_mtu; -+ return 0; -+} -+ -+/** -+ * ip6ip6_tnl_dev_init_gen - general initializer for all tunnel devices -+ * @dev: virtual device associated with tunnel -+ * -+ * Description: -+ * Set function pointers and initialize the &struct flowi template used -+ * by the tunnel. -+ **/ -+ -+static int -+ip6ip6_tnl_dev_init_gen(struct net_device *dev) -+{ -+ struct ip6_tnl *t = (struct ip6_tnl *) dev->priv; -+ struct flowi *fl = &t->fl; -+ int err; -+ struct sock *sk; -+ -+ if ((err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_IPV6, &t->sock))) { -+ printk(KERN_ERR -+ "Failed to create IPv6 tunnel socket (err %d).\n", err); -+ return err; -+ } -+ t->sock->inode->i_uid = 0; -+ t->sock->inode->i_gid = 0; -+ -+ sk = t->sock->sk; -+ sk->allocation = GFP_ATOMIC; -+ sk->net_pinfo.af_inet6.hop_limit = 254; -+ sk->net_pinfo.af_inet6.mc_loop = 0; -+ sk->prot->unhash(sk); -+ -+ memset(fl, 0, sizeof (*fl)); -+ fl->proto = IPPROTO_IPV6; -+ -+ dev->destructor = ip6ip6_tnl_dev_destructor; -+ dev->uninit = ip6ip6_tnl_dev_uninit; -+ dev->hard_start_xmit = ip6ip6_tnl_xmit; -+ dev->get_stats = ip6ip6_tnl_get_stats; -+ dev->do_ioctl = ip6ip6_tnl_ioctl; -+ dev->change_mtu = ip6ip6_tnl_change_mtu; -+ -+ dev->type = ARPHRD_TUNNEL6; -+ dev->hard_header_len = LL_MAX_HEADER + sizeof (struct ipv6hdr); -+ dev->mtu = ETH_DATA_LEN - sizeof (struct ipv6hdr); -+ dev->flags |= IFF_NOARP; -+ dev->iflink = 0; -+ /* Hmm... MAX_ADDR_LEN is 8, so the ipv6 addresses can't be -+ copied to dev->dev_addr and dev->broadcast, like the ipv4 -+ addresses were in ipip.c, ip_gre.c and sit.c. */ -+ dev->addr_len = 0; -+ return 0; -+} -+ -+/** -+ * ip6ip6_tnl_dev_init - initializer for all non fallback tunnel devices -+ * @dev: virtual device associated with tunnel -+ **/ -+ -+static int -+ip6ip6_tnl_dev_init(struct net_device *dev) -+{ -+ struct ip6_tnl *t = (struct ip6_tnl *) dev->priv; -+ ip6ip6_tnl_dev_init_gen(dev); -+ ip6ip6_tnl_link_config(t); -+ return 0; -+} -+ -+#ifdef MODULE -+ -+/** -+ * ip6ip6_fb_tnl_open - function called when fallback device opened -+ * @dev: fallback device -+ * -+ * Return: 0 -+ **/ -+ -+static int -+ip6ip6_fb_tnl_open(struct net_device *dev) -+{ -+ MOD_INC_USE_COUNT; -+ return 0; -+} -+ -+/** -+ * ip6ip6_fb_tnl_close - function called when fallback device closed -+ * @dev: fallback device -+ * -+ * Return: 0 -+ **/ -+ -+static int -+ip6ip6_fb_tnl_close(struct net_device *dev) -+{ -+ MOD_DEC_USE_COUNT; -+ return 0; -+} -+#endif -+ -+/** -+ * ip6ip6_fb_tnl_dev_init - initializer for fallback tunnel device -+ * @dev: fallback device -+ * -+ * Return: 0 -+ **/ -+ -+int __init -+ip6ip6_fb_tnl_dev_init(struct net_device *dev) -+{ -+ ip6ip6_tnl_dev_init_gen(dev); -+#ifdef MODULE -+ dev->open = ip6ip6_fb_tnl_open; -+ dev->stop = ip6ip6_fb_tnl_close; -+#endif -+ dev_hold(dev); -+ tnls_wc[0] = &ip6ip6_fb_tnl; -+ return 0; -+} -+ -+/** -+ * ip6ip6_tnl_register_hook - add hook for processing of tunneled packets -+ * @reg: hook function and its parameters -+ * -+ * Description: -+ * Add a netfilter like hook function for special handling of tunneled -+ * packets. The hook functions are called before encapsulation -+ * (%IP6_TNL_PRE_ENCAP) and before decapsulation -+ * (%IP6_TNL_PRE_DECAP). The possible return values by the hook -+ * functions are %IP6_TNL_DROP, %IP6_TNL_ACCEPT and -+ * %IP6_TNL_STOLEN (in case the hook function took care of the packet -+ * and it doesn't have to be processed any further). -+ **/ -+ -+void -+ip6ip6_tnl_register_hook(struct ip6_tnl_hook_ops *reg) -+{ -+ if (reg->hooknum < IP6_TNL_MAXHOOKS) { -+ struct list_head *i; -+ -+ write_lock_bh(&ip6ip6_hook_lock); -+ for (i = hooks[reg->hooknum].next; -+ i != &hooks[reg->hooknum]; i = i->next) { -+ if (reg->priority < -+ ((struct ip6_tnl_hook_ops *) i)->priority) { -+ break; -+ } -+ } -+ list_add(®->list, i->prev); -+ write_unlock_bh(&ip6ip6_hook_lock); -+ } -+} -+ -+/** -+ * ip6ip6_tnl_unregister_hook - remove tunnel hook -+ * @reg: hook function and its parameters -+ **/ -+ -+void -+ip6ip6_tnl_unregister_hook(struct ip6_tnl_hook_ops *reg) -+{ -+ if (reg->hooknum < IP6_TNL_MAXHOOKS) { -+ write_lock_bh(&ip6ip6_hook_lock); -+ list_del(®->list); -+ write_unlock_bh(&ip6ip6_hook_lock); -+ } -+} -+ -+ -+/* the IPv6 over IPv6 protocol structure */ -+static struct inet6_protocol ip6ip6_protocol = { -+ ip6ip6_rcv, /* IPv6 handler */ -+ ip6ip6_err, /* IPv6 error control */ -+ NULL, /* next */ -+ IPPROTO_IPV6, /* protocol ID */ -+ 0, /* copy */ -+ NULL, /* data */ -+ "IPv6 over IPv6" /* name */ -+}; -+ -+/** -+ * ip6_tunnel_init - register protocol and reserve needed resources -+ * -+ * Return: 0 on success -+ **/ -+ -+int __init ip6_tunnel_init(void) -+{ -+ int i, err; -+ -+ ip6ip6_fb_tnl_dev.priv = (void *) &ip6ip6_fb_tnl; -+ -+ for (i = 0; i < IP6_TNL_MAXHOOKS; i++) { -+ INIT_LIST_HEAD(&hooks[i]); -+ } -+ if ((err = register_netdev(&ip6ip6_fb_tnl_dev))) -+ return err; -+ -+ inet6_add_protocol(&ip6ip6_protocol); -+ return 0; -+} -+ -+/** -+ * ip6_tunnel_cleanup - free resources and unregister protocol -+ **/ -+ -+void ip6_tunnel_cleanup(void) -+{ -+ write_lock_bh(&ip6ip6_kernel_lock); -+ shutdown = 1; -+ write_unlock_bh(&ip6ip6_kernel_lock); -+ flush_scheduled_tasks(); -+ manage_kernel_tnls(NULL); -+ inet6_del_protocol(&ip6ip6_protocol); -+ unregister_netdev(&ip6ip6_fb_tnl_dev); -+} -+ -+#ifdef MODULE -+module_init(ip6_tunnel_init); -+module_exit(ip6_tunnel_cleanup); -+#endif -+ -+#if defined(CONFIG_IPV6_MOBILITY_HA_MODULE) || defined(CONFIG_IPV6_MOBILITY_MN_MODULE) -+EXPORT_SYMBOL(ip6ip6_tnl_register_hook); -+EXPORT_SYMBOL(ip6ip6_tnl_unregister_hook); -+#endif -+#ifdef CONFIG_IPV6_MOBILITY_HA_MODULE -+EXPORT_SYMBOL(ip6ip6_tnl_dec_max_kdev_count); -+EXPORT_SYMBOL(ip6ip6_tnl_inc_max_kdev_count); -+EXPORT_SYMBOL(ip6ip6_tnl_dec_min_kdev_count); -+EXPORT_SYMBOL(ip6ip6_tnl_inc_min_kdev_count); -+EXPORT_SYMBOL(ip6ip6_kernel_tnl_add); -+EXPORT_SYMBOL(ip6ip6_kernel_tnl_del); -+EXPORT_SYMBOL(ip6ip6_tnl_lookup); -+#endif -+#ifdef CONFIG_IPV6_MOBILITY_MN_MODULE -+EXPORT_SYMBOL(ip6ip6_tnl_create); -+EXPORT_SYMBOL(ip6ip6_tnl_change); -+#endif -+ -diff -uprN linux-2.4.25.old/net/ipv6/mipglue.c linux-2.4.25/net/ipv6/mipglue.c ---- linux-2.4.25.old/net/ipv6/mipglue.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mipglue.c 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,63 @@ -+/* -+ * Glue for Mobility support integration to IPv6 -+ * -+ * Authors: -+ * Antti Tuominen -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 -+ -+extern int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff); -+ -+/* Initialize all zero */ -+struct mipv6_callable_functions mipv6_functions = { NULL }; -+ -+/* Sets mipv6_functions struct to zero to invalidate all successive -+ * calls to mipv6 functions. Used on module unload. */ -+ -+void mipv6_invalidate_calls(void) -+{ -+ memset(&mipv6_functions, 0, sizeof(mipv6_functions)); -+} -+ -+ -+/* Selects correct handler for tlv encoded destination option. Called -+ * by ip6_parse_tlv. Checks if mipv6 calls are valid before calling. */ -+ -+int mipv6_handle_dstopt(struct sk_buff *skb, int optoff) -+{ -+ int ret; -+ -+ switch (skb->nh.raw[optoff]) { -+ case MIPV6_TLV_HOMEADDR: -+ ret = MIPV6_CALLFUNC(mipv6_handle_homeaddr, 0)(skb, optoff); -+ break; -+ default: -+ /* Should never happen */ -+ printk(KERN_ERR __FILE__ ": Invalid destination option code (%d)\n", -+ skb->nh.raw[optoff]); -+ ret = 1; -+ break; -+ } -+ -+ /* If mipv6 handlers are not valid, pass the packet to -+ * ip6_tlvopt_unknown() for correct handling. */ -+ if (!ret) -+ return ip6_tlvopt_unknown(skb, optoff); -+ -+ return ret; -+} -+ -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/Config.in linux-2.4.25/net/ipv6/mobile_ip6/Config.in ---- linux-2.4.25.old/net/ipv6/mobile_ip6/Config.in 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/Config.in 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,12 @@ -+# -+# Mobile IPv6 Configuration -+# -+dep_tristate ' IPv6: Mobility Support (Correspondent Node)' CONFIG_IPV6_MOBILITY $CONFIG_IPV6 -+if [ "$CONFIG_IPV6_IPV6_TUNNEL" != "n" ]; then -+ dep_tristate ' MIPv6: Mobile Node Support' CONFIG_IPV6_MOBILITY_MN $CONFIG_IPV6_MOBILITY -+ -+ dep_tristate ' MIPv6: Home Agent Support' CONFIG_IPV6_MOBILITY_HA $CONFIG_IPV6_MOBILITY -+fi -+if [ "$CONFIG_IPV6_MOBILITY" != "n" ]; then -+ bool ' MIPv6: Debug messages' CONFIG_IPV6_MOBILITY_DEBUG -+fi -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/Makefile linux-2.4.25/net/ipv6/mobile_ip6/Makefile ---- linux-2.4.25.old/net/ipv6/mobile_ip6/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/Makefile 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,35 @@ -+# -+# Makefile for the MIPL Mobile IPv6 for Linux. -+# -+# Note! Dependencies are done automagically by 'make dep', which also -+# removes any old dependencies. DON'T put your own dependencies here -+# unless it's something special (ie not a .c file). -+# -+ -+ -+O_TARGET := mip6_base.o -+ -+list-multi := mip6_ha.o mip6_mn.o -+ -+obj-y := hashlist.o bcache.o mobhdr_common.o stats.o exthdrs.o \ -+ rr_crypto.o hmac.o auth_opt.o mipv6_icmp.o module_cn.o -+ -+obj-m := $(O_TARGET) -+ -+mip6_ha-objs := halist.o mipv6_icmp_ha.o tunnel_ha.o \ -+ ndisc_ha.o ha.o module_ha.o -+ -+mip6_mn-objs := mipv6_icmp_mn.o ioctl_mn.o tunnel_mn.o \ -+ mdetect.o bul.o multiaccess_ctl.o mobhdr_mn.o mn.o \ -+ module_mn.o -+ -+obj-$(CONFIG_IPV6_MOBILITY_HA) += mip6_ha.o -+obj-$(CONFIG_IPV6_MOBILITY_MN) += mip6_mn.o -+ -+include $(TOPDIR)/Rules.make -+ -+mip6_ha.o: $(mip6_ha-objs) -+ $(LD) -r -o $@ $(mip6_ha-objs) -+ -+mip6_mn.o: $(mip6_mn-objs) -+ $(LD) -r -o $@ $(mip6_mn-objs) -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/README linux-2.4.25/net/ipv6/mobile_ip6/README ---- linux-2.4.25.old/net/ipv6/mobile_ip6/README 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/README 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,15 @@ -+MIPL Mobile IPv6 for Linux -+ -+More information at http://www.mipl.mediapoli.com/. -+ -+To join MIPL Mobile IPv6 for Linux mailing lists go to: -+ -+ http://www.mipl.mediapoli.com/cgi-bin/mailman/listinfo -+ -+Or send mail with subject "subscribe" for the general list to: -+ -+ mipl-request@list.mipl.mediapoli.com -+ -+or for the developer list to: -+ -+ mipl-devel-request@list.mail.mediapoli.com -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/auth_opt.c linux-2.4.25/net/ipv6/mobile_ip6/auth_opt.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/auth_opt.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/auth_opt.c 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,121 @@ -+/* -+ * MIPv6 Binding Authentication Data Option functions -+ * -+ * Authors: -+ * Henrik Petander -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 "debug.h" -+#include "hmac.h" -+#include "mobhdr.h" -+ -+#define DBG_KEY 5 -+ -+int mipv6_auth_build(struct in6_addr *cn_addr, struct in6_addr *coa, -+ __u8 *mh, __u8 *aud_data, __u8 *k_bu) -+{ -+ /* First look up the peer from sadb based on his address */ -+ struct ah_processing ahp; -+ -+ /* Don't add any other options or this system is screwed */ -+ -+ __u8 buf[MAX_HASH_LENGTH]; -+ -+ -+ if (!k_bu) { -+ DEBUG(DBG_ERROR, "k_bu missing, aborting"); -+ return -1; -+ } -+ DEBUG(DBG_KEY, "Key for building authenticator:"); -+ debug_print_buffer(DBG_KEY, k_bu, HMAC_SHA1_KEY_SIZE); -+ -+ if (ah_hmac_sha1_init(&ahp, k_bu, HMAC_SHA1_KEY_SIZE) < 0) { -+ DEBUG(DBG_ERROR, "Failed to initialize hmac sha1"); -+ return -1; -+ } -+ -+ DEBUG(DBG_KEY, "coa: "); -+ debug_print_buffer(DBG_KEY, coa, 16); -+ DEBUG(DBG_KEY, "cn_addr: "); -+ debug_print_buffer(DBG_KEY, cn_addr, 16); -+ DEBUG(DBG_KEY, "MH contents: "); -+ debug_print_buffer(DBG_KEY, mh, aud_data - mh); -+ -+ /* First the common part */ -+ ah_hmac_sha1_loop(&ahp, coa, sizeof(struct in6_addr)); -+ ah_hmac_sha1_loop(&ahp, cn_addr, sizeof(struct in6_addr)); -+ ah_hmac_sha1_loop(&ahp, mh, aud_data - mh); -+ ah_hmac_sha1_result(&ahp, buf); -+ -+ memcpy(aud_data, buf, MIPV6_RR_MAC_LENGTH); -+ -+ return 0; -+} -+ -+int mipv6_auth_check(struct in6_addr *cn_addr, struct in6_addr *coa, -+ __u8 *opt, __u8 optlen, -+ struct mipv6_mo_bauth_data *aud, __u8 *k_bu) -+{ -+ int ret = -1; -+ struct ah_processing ahp; -+ __u8 htarget[MAX_HASH_LENGTH]; -+ -+ /* Look up peer by home address */ -+ if (!k_bu) { -+ DEBUG(DBG_ERROR, "k_bu missing, aborting"); -+ return -1; -+ } -+ -+ DEBUG(DBG_KEY, "Key for checking authenticator:"); -+ debug_print_buffer(DBG_KEY, k_bu, HMAC_SHA1_KEY_SIZE); -+ -+ if (!aud || !coa) { -+ DEBUG(DBG_INFO, "%s is NULL", aud ? "coa" : "aud"); -+ goto out; -+ } -+ -+ if (aud->length != MIPV6_RR_MAC_LENGTH) { -+ DEBUG(DBG_ERROR, -+ ": Incorrect authentication option length %d", aud->length); -+ goto out; -+ } -+ -+ if (ah_hmac_sha1_init(&ahp, k_bu, HMAC_SHA1_KEY_SIZE) < 0) { -+ DEBUG(DBG_ERROR, -+ "internal error in initialization of authentication algorithm"); -+ goto out; -+ } -+ DEBUG(DBG_KEY, "coa: "); -+ debug_print_buffer(DBG_KEY, coa, 16); -+ DEBUG(DBG_KEY, "cn_addr: "); -+ debug_print_buffer(DBG_KEY, cn_addr, 16); -+ DEBUG(DBG_KEY, "MH contents: "); -+ debug_print_buffer(DBG_KEY, opt, (u8*) aud->data - opt); -+ -+ ah_hmac_sha1_loop(&ahp, coa, sizeof(struct in6_addr)); -+ ah_hmac_sha1_loop(&ahp, cn_addr, sizeof(struct in6_addr)); -+ -+ /* -+ * Process MH + options till the start of the authenticator in -+ * Auth. data option -+ */ -+ ah_hmac_sha1_loop(&ahp, opt, (u8 *)aud->data - opt); -+ ah_hmac_sha1_result(&ahp, htarget); -+ if (memcmp(htarget, aud->data, MIPV6_RR_MAC_LENGTH) == 0) -+ ret = 0; -+ -+ DEBUG(DBG_ERROR, "returning %d", ret); -+out: -+ return ret; -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/bcache.c linux-2.4.25/net/ipv6/mobile_ip6/bcache.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/bcache.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/bcache.c 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,746 @@ -+/* -+ * Binding Cache -+ * -+ * Authors: -+ * Juha Mynttinen -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+ -+/* -+ * Changes: -+ * -+ * Nanno Langstraat : Timer code cleaned up, active socket -+ * test rewritten -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "bcache.h" -+#include "hashlist.h" -+#include "debug.h" -+#include "mobhdr.h" -+#include "tunnel.h" -+#include "config.h" -+ -+#define TIMERDELAY HZ/10 -+ -+struct mipv6_bcache { -+ struct hashlist *entries; -+ __u32 size; -+ struct timer_list callback_timer; -+}; -+ -+struct in6_addr_pair { -+ struct in6_addr *a1; -+ struct in6_addr *a2; -+}; -+ -+static rwlock_t bcache_lock = RW_LOCK_UNLOCKED; -+ -+static struct mipv6_bcache bcache; -+ -+static int bcache_proc_info(char *buffer, char **start, off_t offset, -+ int length); -+ -+#define MIPV6_BCACHE_HASHSIZE 32 -+ -+/* Moment of transmission of a BR, in seconds before bcache entry expiry */ -+#define BCACHE_BR_SEND_LEAD 3 -+ -+#define MIPV6_MAX_BRR 3 /* Send 3 BRRs before deleting BC entry */ -+#define MIPV6_BRR_RATE HZ /* Send BRRs once per second */ -+ -+/* -+ * Internal functions. -+ */ -+ -+struct cache_entry_iterator_args { -+ struct mipv6_bce **entry; -+}; -+ -+static int find_first_cache_entry_iterator(void *data, void *args, -+ unsigned long *lifetime) -+{ -+ struct mipv6_bce *entry = -+ (struct mipv6_bce *) data; -+ struct cache_entry_iterator_args *state = -+ (struct cache_entry_iterator_args *) args; -+ -+ ASSERT(entry != NULL); -+ -+ if (entry->type == CACHE_ENTRY) { -+ *(state->entry) = entry; -+ return ITERATOR_STOP; /* stop iteration */ -+ } else { -+ return ITERATOR_CONT; /* continue iteration */ -+ } -+} -+ -+ -+/* -+ * Get memory for a new bcache entry. If bcache is full, a cache -+ * entry may be deleted to get space for a home registration, but not -+ * vice versa. -+ */ -+static struct mipv6_bce *mipv6_bce_alloc(__u8 type) -+{ -+ struct mipv6_bce *entry; -+ struct cache_entry_iterator_args args; -+ -+ DEBUG_FUNC(); -+ -+ entry = (struct mipv6_bce *) -+ hashlist_alloc(bcache.entries, SLAB_ATOMIC); -+ -+ /* Cache replacement policy: always replace the CACHE_ENTRY -+ closest to expiration. Type HOME_REGISTRATION entry may -+ never be deleted before expiration. */ -+ if (entry == NULL) { -+ /* cache full, try to delete a CACHE_ENTRY */ -+ args.entry = &entry; -+ hashlist_iterate(bcache.entries, &args, -+ find_first_cache_entry_iterator); -+ if (entry == NULL) -+ return NULL; -+ hashlist_delete(bcache.entries, -+ (struct hashlist_entry *)entry); -+ entry = (struct mipv6_bce *) -+ hashlist_alloc(bcache.entries, SLAB_ATOMIC); -+ } -+ return entry; -+} -+ -+/* -+ * Frees entry's memory allocated with mipv6_bce_alloc -+ */ -+static void mipv6_bce_free(struct mipv6_bce *entry) -+{ -+ hashlist_free(bcache.entries, (void *) entry); -+} -+ -+/* -+ * Removes all expired entries -+ */ -+static void expire(void) -+{ -+ struct mipv6_bce *entry; -+ struct br_addrs { -+ struct in6_addr daddr; -+ struct in6_addr saddr; -+ struct br_addrs *next; -+ }; -+ struct br_addrs *br_info = NULL; -+ -+ DEBUG_FUNC(); -+ -+ write_lock(&bcache_lock); -+ -+ while ((entry = (struct mipv6_bce *) -+ hashlist_get_first(bcache.entries)) != NULL) { -+ struct rt6_info *rt; -+ if (time_after_eq(jiffies, entry->callback_time)) { -+ -+ DEBUG(DBG_INFO, "an entry expired"); -+ -+ if (entry->type & HOME_REGISTRATION) { -+ mip6_fn.proxy_del(&entry->home_addr, entry); -+ } -+ hashlist_delete(bcache.entries, (void *)entry); -+ mipv6_bce_free(entry); -+ entry = NULL; -+ } else if (entry->br_callback_time != 0 && -+ time_after_eq(jiffies, entry->br_callback_time) && -+ entry->br_count < MIPV6_MAX_BRR && -+ (rt = rt6_lookup(&entry->home_addr, &entry->our_addr, 0, 0)) != NULL){ -+ /* Do we have a destination cache entry for the home address */ -+ if (rt->rt6i_flags & RTF_CACHE) { -+ struct br_addrs *tmp; -+ tmp = br_info; -+ DEBUG(DBG_INFO, -+ "bcache entry recently used. Sending BR."); -+ /* queue for sending */ -+ br_info = kmalloc(sizeof(struct br_addrs), -+ GFP_ATOMIC); -+ if (br_info) { -+ ipv6_addr_copy(&br_info->saddr, -+ &entry->our_addr); -+ ipv6_addr_copy(&br_info->daddr, -+ &entry->home_addr); -+ br_info->next = tmp; -+ entry->last_br = jiffies; -+ entry->br_callback_time = jiffies + MIPV6_BRR_RATE; -+ entry->br_count++; -+ } else { -+ br_info = tmp; -+ DEBUG(DBG_ERROR, "Out of memory"); -+ } -+ -+ } else -+ entry->br_callback_time = 0; -+ dst_release(&rt->u.dst); -+ } else { -+ entry->br_callback_time = 0; -+ break; -+ } -+ } -+ write_unlock(&bcache_lock); -+ -+ while (br_info) { -+ struct br_addrs *tmp = br_info->next; -+ if (mipv6_send_brr(&br_info->saddr, &br_info->daddr, NULL) < 0) -+ DEBUG(DBG_WARNING, -+ "BR send for %x:%x:%x:%x:%x:%x:%x:%x failed", -+ NIPV6ADDR(&br_info->daddr)); -+ kfree(br_info); -+ br_info = tmp; -+ } -+} -+ -+static void set_timer(void) -+{ -+ struct mipv6_bce *entry; -+ unsigned long callback_time; -+ -+ DEBUG_FUNC(); -+ -+ entry = (struct mipv6_bce *) -+ hashlist_get_first(bcache.entries); -+ if (entry != NULL) { -+ if (entry->br_callback_time > 0 && -+ time_after(entry->br_callback_time, jiffies)) -+ callback_time = entry->br_callback_time; -+ else if (time_after(entry->callback_time, jiffies)) -+ callback_time = entry->callback_time; -+ else { -+ DEBUG(DBG_WARNING, -+ "bcache timer attempted to schedule" -+ " for a historical jiffies count!"); -+ callback_time = jiffies + TIMERDELAY; -+ } -+ -+ DEBUG(DBG_INFO, "setting timer to now"); -+ mod_timer(&bcache.callback_timer, callback_time); -+ } else { -+ del_timer(&bcache.callback_timer); -+ DEBUG(DBG_INFO, "BC empty, not setting a new timer"); -+ } -+} -+ -+/* -+ * The function that is scheduled to do the callback functions. May be -+ * modified e.g to allow Binding Requests, now only calls expire() and -+ * schedules a new timer. -+ */ -+static void timer_handler(unsigned long dummy) -+{ -+ expire(); -+ write_lock(&bcache_lock); -+ set_timer(); -+ write_unlock(&bcache_lock); -+} -+ -+/* -+ * Interface functions visible to other modules -+ */ -+ -+/** -+ * mipv6_bcache_add - add Binding Cache entry -+ * @ifindex: interface index -+ * @our_addr: own address -+ * @home_addr_org: MN's home address -+ * @coa: MN's care-of address -+ * @lifetime: lifetime for this binding -+ * @prefix: prefix length -+ * @seq: sequence number -+ * @flags: flags received in BU -+ * @type: type of entry -+ * -+ * Adds an entry for this @home_addr_org in the Binding Cache. If entry -+ * already exists, old entry is updated. @type may be %CACHE_ENTRY or -+ * %HOME_REGISTRATION. -+ **/ -+int mipv6_bcache_add(int ifindex, -+ struct in6_addr *our_addr, -+ struct in6_addr *home_addr, -+ struct in6_addr *coa, -+ __u32 lifetime, __u16 seq, __u8 flags, __u8 type) -+{ -+ struct mipv6_bce *entry; -+ int update = 0; -+ int create_tunnel = 0; -+ unsigned long now = jiffies; -+ struct in6_addr_pair hashkey; -+ int ret = -1; -+ -+ DEBUG_FUNC(); -+ -+ hashkey.a1 = home_addr; -+ hashkey.a2 = our_addr; -+ -+ write_lock(&bcache_lock); -+ -+ if (type == HOME_REGISTRATION && !(mip6node_cnf.capabilities&CAP_HA)) -+ return 0; -+ -+ if (unlikely(bcache.entries == NULL)) { -+ ret = -ENOMEM; -+ goto err; -+ } -+ -+ if ((entry = (struct mipv6_bce *) -+ hashlist_get(bcache.entries, &hashkey)) != NULL) { -+ /* if an entry for this home_addr exists (with smaller -+ * seq than the new seq), update it by removing it -+ * first -+ */ -+ if (!MIPV6_SEQ_GT(seq, entry->seq)) { -+ DEBUG(DBG_INFO, "smaller seq than existing, not updating"); -+ goto out; -+ } -+ DEBUG(DBG_INFO, "updating an existing entry"); -+ update = 1; -+ -+ /* H-flag is already checked in BU handler. */ -+ /* XXX: Should we care about the other flags?*/ -+ if (flags != entry->flags) { -+ DEBUG(DBG_INFO, "entry/BU flag mismatch"); -+ } -+ -+ if (type == HOME_REGISTRATION) { -+ create_tunnel = (ipv6_addr_cmp(&entry->coa, coa) || -+ entry->ifindex != ifindex); -+ } -+ } else { -+ /* no entry for this home_addr, try to create a new entry */ -+ DEBUG(DBG_INFO, "creating a new entry"); -+ update = 0; -+ -+ entry = mipv6_bce_alloc(type); -+ if (entry == NULL) { -+ DEBUG(DBG_INFO, "cache full, entry not added"); -+ goto err; -+ } -+ -+ create_tunnel = (type == HOME_REGISTRATION); -+ } -+ -+ if (create_tunnel) { -+ if (update) -+ mip6_fn.proxy_del(&entry->home_addr, entry); -+ if (mip6_fn.proxy_create(flags, ifindex, coa, our_addr, home_addr) < 0) { -+ goto err_proxy; -+ } -+ } -+ -+ ipv6_addr_copy(&(entry->our_addr), our_addr); -+ ipv6_addr_copy(&(entry->home_addr), home_addr); -+ ipv6_addr_copy(&(entry->coa), coa); -+ entry->ifindex = ifindex; -+ entry->seq = seq; -+ entry->type = type; -+ entry->flags = flags; -+ -+ entry->last_br = 0; -+ entry->destunr_count = 0; -+ entry->callback_time = now + lifetime * HZ; -+ if (entry->type & HOME_REGISTRATION) -+ entry->br_callback_time = 0; -+ else -+ entry->br_callback_time = now + -+ (lifetime - BCACHE_BR_SEND_LEAD) * HZ; -+ -+ if (update) { -+ DEBUG(DBG_INFO, "updating entry : %x", entry); -+ hashlist_reposition(bcache.entries, (void *)entry, -+ entry->callback_time); -+ } else { -+ DEBUG(DBG_INFO, "adding entry: %x", entry); -+ if ((hashlist_add(bcache.entries, -+ &hashkey, -+ entry->callback_time, entry)) < 0) { -+ -+ DEBUG(DBG_ERROR, "Hash add failed"); -+ goto err_hashlist; -+ } -+ } -+ -+ set_timer(); -+ -+out: -+ write_unlock(&bcache_lock); -+ return 0; -+ -+err_hashlist: -+ if (create_tunnel) { -+ mip6_fn.proxy_del(home_addr, entry); -+ } -+err_proxy: -+ if (update) { -+ hashlist_delete(bcache.entries, (void *)entry); -+ } -+ mipv6_bce_free(entry); -+err: -+ write_unlock(&bcache_lock); -+ return ret; -+} -+ -+int mipv6_bcache_icmp_err(struct in6_addr *home_addr, -+ struct in6_addr *our_addr, -+ int destunr_count) -+{ -+ struct mipv6_bce *entry; -+ struct in6_addr_pair hashkey; -+ -+ int ret = -ENOENT; -+ -+ DEBUG_FUNC(); -+ -+ hashkey.a1 = home_addr; -+ hashkey.a2 = our_addr; -+ -+ write_lock(&bcache_lock); -+ if (unlikely(bcache.entries == NULL)) { -+ ret = -ENOMEM; -+ goto err; -+ } -+ -+ if ((entry = (struct mipv6_bce *) -+ hashlist_get(bcache.entries, &hashkey)) != NULL) { -+ entry->last_destunr = jiffies; -+ entry->destunr_count = destunr_count; -+ ret = 0; -+ } -+err: -+ write_unlock(&bcache_lock); -+ return ret; -+} -+ -+ -+/** -+ * mipv6_bcache_delete - delete Binding Cache entry -+ * @home_addr: MN's home address -+ * @our_addr: our address -+ * @type: type of entry -+ * -+ * Deletes an entry associated with @home_addr from Binding Cache. -+ * Valid values for @type are %CACHE_ENTRY, %HOME_REGISTRATION and -+ * %ANY_ENTRY. %ANY_ENTRY deletes any type of entry. -+ **/ -+int mipv6_bcache_delete(struct in6_addr *home_addr, -+ struct in6_addr *our_addr, __u8 type) -+{ -+ struct mipv6_bce *entry; -+ struct in6_addr_pair hashkey; -+ int err = 0; -+ -+ DEBUG_FUNC(); -+ -+ if (home_addr == NULL || our_addr == NULL) { -+ DEBUG(DBG_INFO, "error in arguments"); -+ return -EINVAL; -+ } -+ -+ hashkey.a1 = home_addr; -+ hashkey.a2 = our_addr; -+ -+ write_lock(&bcache_lock); -+ -+ if (unlikely(bcache.entries == NULL) || -+ (entry = (struct mipv6_bce *) -+ hashlist_get(bcache.entries, &hashkey)) == NULL || -+ !(entry->type & type)) { -+ DEBUG(DBG_INFO, "No matching entry found"); -+ err = -ENOENT; -+ goto out; -+ } -+ -+ hashlist_delete(bcache.entries, (void *) entry); -+ mipv6_bce_free(entry); -+ -+ set_timer(); -+out: -+ write_unlock(&bcache_lock); -+ return err; -+} -+ -+/** -+ * mipv6_bcache_exists - check if entry exists -+ * @home_addr: home address to check -+ * @our_addr: our address -+ * -+ * Determines if a binding exists for @home_addr. Returns type of the -+ * entry or negative if entry does not exist. -+ **/ -+int mipv6_bcache_exists(struct in6_addr *home_addr, -+ struct in6_addr *our_addr) -+{ -+ struct mipv6_bce *entry; -+ struct in6_addr_pair hashkey; -+ int type = -ENOENT; -+ -+ DEBUG_FUNC(); -+ -+ if (home_addr == NULL || our_addr == NULL) -+ return -EINVAL; -+ -+ hashkey.a1 = home_addr; -+ hashkey.a2 = our_addr; -+ -+ read_lock(&bcache_lock); -+ if (likely(bcache.entries != NULL) && -+ (entry = (struct mipv6_bce *) -+ hashlist_get(bcache.entries, &hashkey)) != NULL) { -+ type = entry->type; -+ } -+ read_unlock(&bcache_lock); -+ -+ return type; -+} -+ -+/** -+ * mipv6_bcache_get - get entry from Binding Cache -+ * @home_addr: home address to search -+ * @our_addr: our address -+ * @entry: pointer to buffer -+ * -+ * Gets a copy of Binding Cache entry for @home_addr. If entry -+ * exists entry is copied to @entry and zero is returned. -+ * Otherwise returns negative. -+ **/ -+int mipv6_bcache_get(struct in6_addr *home_addr, -+ struct in6_addr *our_addr, -+ struct mipv6_bce *entry) -+{ -+ struct mipv6_bce *entry2; -+ struct in6_addr_pair hashkey; -+ int ret = -ENOENT; -+ -+ DEBUG_FUNC(); -+ -+ if (home_addr == NULL || our_addr == NULL || entry == NULL) -+ return -EINVAL; -+ -+ hashkey.a1 = home_addr; -+ hashkey.a2 = our_addr; -+ -+ read_lock_bh(&bcache_lock); -+ -+ entry2 = (struct mipv6_bce *) -+ hashlist_get(bcache.entries, &hashkey); -+ if (entry2 != NULL) { -+ memcpy(entry, entry2, sizeof(struct mipv6_bce)); -+ ret = 0; -+ } -+ read_unlock_bh(&bcache_lock); -+ return ret; -+} -+ -+int mipv6_bcache_iterate(hashlist_iterator_t func, void *args) -+{ -+ int ret; -+ -+ read_lock_bh(&bcache_lock); -+ ret = hashlist_iterate(bcache.entries, args, func); -+ read_unlock_bh(&bcache_lock); -+ -+ return ret; -+} -+ -+/* -+ * Proc-filesystem functions -+ */ -+ -+#define BC_INFO_LEN 80 -+ -+struct procinfo_iterator_args { -+ char *buffer; -+ int offset; -+ int length; -+ int skip; -+ int len; -+}; -+ -+static int procinfo_iterator(void *data, void *args, unsigned long *pref) -+{ -+ struct procinfo_iterator_args *arg = -+ (struct procinfo_iterator_args *) args; -+ struct mipv6_bce *entry = -+ (struct mipv6_bce *) data; -+ -+ ASSERT(entry != NULL); -+ -+ if (arg->skip < arg->offset / BC_INFO_LEN) { -+ arg->skip++; -+ return ITERATOR_CONT; -+ } -+ -+ if (arg->len >= arg->length) -+ return ITERATOR_CONT; -+ -+ /* HoA CoA CallbackInSecs Type */ -+ arg->len += sprintf(arg->buffer + arg->len, -+ "%08x%08x%08x%08x %08x%08x%08x%08x %010lu %02d\n", -+ ntohl(entry->home_addr.s6_addr32[0]), -+ ntohl(entry->home_addr.s6_addr32[1]), -+ ntohl(entry->home_addr.s6_addr32[2]), -+ ntohl(entry->home_addr.s6_addr32[3]), -+ ntohl(entry->coa.s6_addr32[0]), -+ ntohl(entry->coa.s6_addr32[1]), -+ ntohl(entry->coa.s6_addr32[2]), -+ ntohl(entry->coa.s6_addr32[3]), -+ ((entry->callback_time) - jiffies) / HZ, -+ (int) entry->type); -+ -+ return ITERATOR_CONT; -+} -+ -+ /* -+ * Callback function for proc filesystem. -+ */ -+static int bcache_proc_info(char *buffer, char **start, off_t offset, -+ int length) -+{ -+ struct procinfo_iterator_args args; -+ -+ DEBUG_FUNC(); -+ -+ args.buffer = buffer; -+ args.offset = offset; -+ args.length = length; -+ args.skip = 0; -+ args.len = 0; -+ -+ read_lock_bh(&bcache_lock); -+ hashlist_iterate(bcache.entries, &args, procinfo_iterator); -+ read_unlock_bh(&bcache_lock); -+ -+ *start = buffer; -+ if (offset) -+ *start += offset % BC_INFO_LEN; -+ -+ args.len -= offset % BC_INFO_LEN; -+ -+ if (args.len > length) -+ args.len = length; -+ if (args.len < 0) -+ args.len = 0; -+ -+ return args.len; -+} -+ -+static int bcache_compare(void *data, void *hashkey) -+{ -+ struct in6_addr_pair *p = (struct in6_addr_pair *) hashkey; -+ struct mipv6_bce *e = (struct mipv6_bce *) data; -+ -+ if (ipv6_addr_cmp(&e->home_addr, p->a1) == 0 -+ && ipv6_addr_cmp(&e->our_addr, p->a2) == 0) -+ return 0; -+ else -+ return -1; -+} -+ -+static __u32 bcache_hash(void *hashkey) -+{ -+ struct in6_addr_pair *p = (struct in6_addr_pair *) hashkey; -+ -+ return p->a1->s6_addr32[0] ^ p->a1->s6_addr32[1] ^ -+ p->a2->s6_addr32[2] ^ p->a2->s6_addr32[3]; -+} -+ -+/* -+ * Initialization and shutdown functions -+ */ -+ -+int __init mipv6_bcache_init(__u32 size) -+{ -+ if (size < 1) { -+ DEBUG(DBG_ERROR, "Binding cache size must be at least 1"); -+ return -EINVAL; -+ } -+ bcache.entries = hashlist_create(MIPV6_BCACHE_HASHSIZE, size, -+ sizeof(struct mipv6_bce), -+ "mip6_bcache", NULL, NULL, -+ bcache_compare, bcache_hash); -+ -+ if (bcache.entries == NULL) { -+ DEBUG(DBG_ERROR, "Failed to initialize hashlist"); -+ return -ENOMEM; -+ } -+ -+ init_timer(&bcache.callback_timer); -+ bcache.callback_timer.data = 0; -+ bcache.callback_timer.function = timer_handler; -+ bcache.size = size; -+ -+ proc_net_create("mip6_bcache", 0, bcache_proc_info); -+ -+ DEBUG(DBG_INFO, "Binding cache initialized"); -+ return 0; -+} -+ -+static int -+bce_cleanup_iterator(void *rawentry, void *args, unsigned long *sortkey) -+{ -+ int type = (int) args; -+ struct mipv6_bce *entry = (struct mipv6_bce *) rawentry; -+ if (entry->type == type) { -+ if (entry->type & HOME_REGISTRATION) { -+ if (unlikely(mip6_fn.proxy_del == NULL)) -+ DEBUG(DBG_ERROR, "proxy_del unitialized"); -+ else -+ mip6_fn.proxy_del(&entry->home_addr, entry); -+ } -+ return ITERATOR_DELETE_ENTRY; -+ } -+ return ITERATOR_CONT; -+ -+} -+ -+void mipv6_bcache_cleanup(int type) -+{ -+ write_lock_bh(&bcache_lock); -+ hashlist_iterate(bcache.entries,(void *) type, bce_cleanup_iterator); -+ write_unlock_bh(&bcache_lock); -+} -+ -+int __exit mipv6_bcache_exit(void) -+{ -+ struct hashlist *entries; -+ -+ DEBUG_FUNC(); -+ -+ proc_net_remove("mip6_bcache"); -+ -+ write_lock_bh(&bcache_lock); -+ DEBUG(DBG_INFO, "Stopping the bcache timer"); -+ del_timer(&bcache.callback_timer); -+ hashlist_iterate(bcache.entries,(void *)CACHE_ENTRY, -+ bce_cleanup_iterator); -+ -+ entries = bcache.entries; -+ bcache.entries = NULL; -+ write_unlock_bh(&bcache_lock); -+ -+ hashlist_destroy(entries); -+ return 0; -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/bcache.h linux-2.4.25/net/ipv6/mobile_ip6/bcache.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/bcache.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/bcache.h 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,72 @@ -+/* -+ * MIPL Mobile IPv6 Binding Cache header file -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _BCACHE_H -+#define _BCACHE_H -+ -+#include -+#include -+#include "hashlist.h" -+ -+#define CACHE_ENTRY 1 /* this and HOME_REGISTRATION are the entry types */ -+#define HOME_REGISTRATION 2 -+#define ANY_ENTRY 3 -+ -+#define MIPV6_MAX_DESTUNREACH 5 /* Delete CN BCEs after 5 destination unreachables */ -+#define MIPV6_DEST_UNR_IVAL 10 /* What is the max interval of destination -+ unreacahable error messages for them to be persistent*/ -+ -+struct mipv6_bce { -+ struct hashlist_entry e; -+ int ifindex; /* Interface identifier */ -+ struct in6_addr our_addr; /* our address (as seen by the MN) */ -+ struct in6_addr home_addr; /* MN home address */ -+ struct in6_addr coa; /* MN care-of address */ -+ unsigned long callback_time; /* time of expiration (in jiffies) */ -+ unsigned long br_callback_time; /* time for sending a BR (in jiffies) */ -+ int (*callback_function)(struct mipv6_bce *entry); -+ __u8 type; /* home registration */ -+ __u8 router; /* mn is router */ -+ __u8 flags; /* flags received in BU */ -+ __u16 seq; /* sequence number */ -+ unsigned long last_br; /* time when last BR sent */ -+ unsigned long last_destunr; /* time when last ICMP destination unreachable received */ -+ int br_count; /* How many BRRs have sent */ -+ int destunr_count; /* Number of destination unreachables received */ -+}; -+ -+int mipv6_bcache_add(int ifindex, struct in6_addr *our_addr, -+ struct in6_addr *home_addr, struct in6_addr *coa, -+ __u32 lifetime, __u16 seq, __u8 flags, __u8 type); -+ -+int mipv6_bcache_icmp_err(struct in6_addr *home_addr, -+ struct in6_addr *our_addr, -+ int destunr_count); -+ -+int mipv6_bcache_delete(struct in6_addr *home_addr, struct in6_addr *our_addr, -+ __u8 type); -+ -+int mipv6_bcache_exists(struct in6_addr *home_addr, -+ struct in6_addr *our_addr); -+ -+int mipv6_bcache_get(struct in6_addr *home_addr, -+ struct in6_addr *our_addr, -+ struct mipv6_bce *entry); -+ -+int mipv6_bcache_iterate(int (*func)(void *, void *, unsigned long *), void *args); -+ -+void mipv6_bcache_cleanup(int type); -+ -+int mipv6_bcache_init(__u32 size); -+ -+int mipv6_bcache_exit(void); -+ -+#endif /* _BCACHE_H */ -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/bul.c linux-2.4.25/net/ipv6/mobile_ip6/bul.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/bul.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/bul.c 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,634 @@ -+/* -+ * Binding update list -+ * -+ * Authors: -+ * Juha Mynttinen -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+ -+/* -+ * Changes: -+ * -+ * Nanno Langstraat : Timer code cleaned up -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "bul.h" -+#include "debug.h" -+#include "hashlist.h" -+#include "tunnel_mn.h" -+#include "mobhdr.h" -+ -+#define MIPV6_BUL_HASHSIZE 32 -+ -+rwlock_t bul_lock = RW_LOCK_UNLOCKED; -+ -+struct mipv6_bul { -+ struct hashlist *entries; -+ struct timer_list callback_timer; -+}; -+ -+static struct mipv6_bul bul; -+ -+struct in6_addr_pair { -+ struct in6_addr *a1; -+ struct in6_addr *a2; -+}; -+ -+/********************************************************************** -+ * -+ * Private functions -+ * -+ **********************************************************************/ -+ -+static int bul_compare(void *data, void *hashkey) -+{ -+ struct in6_addr_pair *p = (struct in6_addr_pair *)hashkey; -+ struct mipv6_bul_entry *e = (struct mipv6_bul_entry *)data; -+ -+ if (ipv6_addr_cmp(&e->cn_addr, p->a1) == 0 -+ && ipv6_addr_cmp(&e->home_addr, p->a2) == 0) -+ return 0; -+ else -+ return -1; -+} -+ -+struct test_keys { -+ struct in6_addr *addr; -+ u8 *cookie; -+}; -+ -+static int bul_compare_cookie(void *data, void *keys) -+{ -+ struct test_keys *p = (struct test_keys *)keys; -+ struct mipv6_bul_entry *e = (struct mipv6_bul_entry *)data; -+ -+ if (ipv6_addr_cmp(&e->cn_addr, p->addr) == 0 && e->rr -+ && memcmp(&e->rr->cot_cookie, p->cookie, 8) == 0) -+ return 0; -+ else -+ return -1; -+} -+ -+static u32 bul_hash(void *hashkey) -+{ -+ struct in6_addr_pair *p = (struct in6_addr_pair *)hashkey; -+ -+ return p->a1->s6_addr32[0] ^ -+ p->a1->s6_addr32[1] ^ -+ p->a1->s6_addr32[2] ^ -+ p->a1->s6_addr32[3]; -+} -+ -+static int bul_proc_info(char *buffer, char **start, off_t offset, -+ int length); -+ -+static struct mipv6_bul_entry *mipv6_bul_get_entry(void) -+{ -+ DEBUG_FUNC(); -+ return ((struct mipv6_bul_entry *) -+ hashlist_alloc(bul.entries, SLAB_ATOMIC)); -+} -+ -+static void mipv6_bul_entry_free(struct mipv6_bul_entry *entry) -+{ -+ DEBUG_FUNC(); -+ -+ if (entry->rr) { -+ if (entry->rr->kbu) -+ kfree(entry->rr->kbu); -+ kfree(entry->rr); -+ } -+ if (entry->ops) -+ kfree(entry->ops); -+ hashlist_free(bul.entries, (void *)entry); -+} -+ -+static __inline__ int del_bul_entry_tnl(struct mipv6_bul_entry *entry) -+{ -+ if (entry->flags & MIPV6_BU_F_HOME) { -+ return mipv6_mv_tnl_to_ha(&entry->cn_addr, -+ &entry->coa, -+ &entry->home_addr); -+ } -+ return 0; -+} -+ -+static void timer_update(void) -+{ -+ struct mipv6_bul_entry *entry; -+ -+ DEBUG_FUNC(); -+ -+ entry = hashlist_get_first(bul.entries); -+ -+ while (entry && time_after_eq(jiffies, entry->callback_time)) { -+ if (time_after_eq(jiffies, entry->expire) || -+ entry->callback(entry) != 0) { -+ /* -+ * Either the entry has expired, or the callback -+ * indicated that it should be deleted. -+ */ -+ hashlist_delete(bul.entries, (void *)entry); -+ -+ del_bul_entry_tnl(entry); -+ mipv6_bul_entry_free(entry); -+ DEBUG(DBG_INFO, "Entry deleted (was expired) from " -+ "binding update list"); -+ } else { -+ /* move entry to its right place in the hashlist */ -+ DEBUG(DBG_INFO, "Rescheduling"); -+ hashlist_reposition(bul.entries, (void *)entry, -+ entry->callback_time); -+ } -+ entry = (struct mipv6_bul_entry *) -+ hashlist_get_first(bul.entries); -+ } -+ -+ if (entry == NULL) { -+ DEBUG(DBG_INFO, "bul empty, not setting a new timer"); -+ del_timer(&bul.callback_timer); -+ } else { -+ mod_timer(&bul.callback_timer, entry->callback_time); -+ } -+} -+ -+static void timer_handler(unsigned long dummy) -+{ -+ DEBUG_FUNC(); -+ -+ write_lock(&bul_lock); -+ timer_update(); -+ write_unlock(&bul_lock); -+} -+ -+/********************************************************************** -+ * -+ * Public interface functions -+ * -+ **********************************************************************/ -+ -+/** -+ * mipv6_bul_iterate - apply interator function to all entries -+ * @func: function to apply -+ * @args: extra arguments for iterator -+ * -+ * Applies @func for each entry in Binding Update List. Extra -+ * arguments given in @args are also passed to the iterator function. -+ * Caller must hold @bul_lock. -+ **/ -+int mipv6_bul_iterate(hashlist_iterator_t func, void *args) -+{ -+ DEBUG_FUNC(); -+ -+ return hashlist_iterate(bul.entries, args, func); -+} -+ -+/** -+ * mipv6_bul_exists - check if Binding Update List entry exists -+ * @cn: address to check -+ * -+ * Checks if Binding Update List has an entry for @cn. Returns true -+ * if entry exists, false otherwise. Caller may not hold @bul_lock. -+ **/ -+int mipv6_bul_exists(struct in6_addr *cn, struct in6_addr *haddr) -+{ -+ int exists; -+ struct in6_addr_pair hashkey; -+ -+ DEBUG_FUNC(); -+ -+ hashkey.a1 = cn; -+ hashkey.a2 = haddr; -+ -+ read_lock_bh(&bul_lock); -+ -+ if (unlikely(bul.entries == NULL)) -+ exists = 0; -+ else -+ exists = (hashlist_get(bul.entries, &hashkey) != NULL); -+ -+ read_unlock_bh(&bul_lock); -+ return exists; -+} -+ -+/** -+ * mipv6_bul_get - get Binding Update List entry -+ * @cn_addr: CN address to search -+ * @home_addr: home address to search -+ * -+ * Returns Binding Update List entry for @cn_addr if it exists. -+ * Otherwise returns %NULL. Caller must hold @bul_lock. -+ **/ -+struct mipv6_bul_entry *mipv6_bul_get(struct in6_addr *cn_addr, -+ struct in6_addr *home_addr) -+{ -+ struct mipv6_bul_entry *entry; -+ struct in6_addr_pair hashkey; -+ -+ DEBUG_FUNC(); -+ -+ if (unlikely(bul.entries == NULL)) { -+ return NULL; -+ } -+ hashkey.a1 = cn_addr; -+ hashkey.a2 = home_addr; -+ -+ entry = (struct mipv6_bul_entry *) -+ hashlist_get(bul.entries, &hashkey); -+ -+ return entry; -+} -+ -+struct mipv6_bul_entry *mipv6_bul_get_by_ccookie( -+ struct in6_addr *cn_addr, u8 *cookie) -+{ -+ struct test_keys key; -+ -+ DEBUG_FUNC(); -+ -+ if (unlikely(bul.entries == NULL)) -+ return NULL; -+ key.addr = cn_addr; -+ key.cookie = cookie; -+ -+ return (struct mipv6_bul_entry *) -+ hashlist_get_ex(bul.entries, &key, -+ bul_compare_cookie); -+} -+ -+/** -+ * mipv6_bul_reschedule - reschedule Binding Update List entry -+ * @entry: entry to reschedule -+ * -+ * Reschedules a Binding Update List entry. Must be called after -+ * modifying entry lifetime. Caller must hold @bul_lock (write). -+ **/ -+void mipv6_bul_reschedule(struct mipv6_bul_entry *entry) -+{ -+ DEBUG_FUNC(); -+ -+ hashlist_reposition(bul.entries, -+ (void *)entry, -+ entry->callback_time); -+ timer_update(); -+} -+ -+/** -+ * mipv6_bul_add - add binding update to Binding Update List -+ * @cn_addr: IPv6 address where BU was sent -+ * @home_addr: Home address for this binding -+ * @coa: Care-of address for this binding -+ * @lifetime: expiration time of the binding in seconds -+ * @seq: sequence number of the BU -+ * @flags: %MIPV6_BU_F_* flags -+ * @callback: callback function called on expiration -+ * @callback_time: expiration time for callback -+ * @state: binding send state -+ * @delay: retransmission delay -+ * @maxdelay: retransmission maximum delay -+ * @ops: Mobility header options for BU -+ * @rr: Return routability information -+ * -+ * Adds a binding update sent to @cn_addr for @home_addr to the -+ * Binding Update List. If entry already exists, it is updated. -+ * Entry is set to expire in @lifetime seconds. Entry has a callback -+ * function @callback that is called at @callback_time. Entry @state -+ * controls resending of this binding update and it can be set to -+ * %ACK_OK, %RESEND_EXP or %ACK_ERROR. Returns a pointer to the newly -+ * created or updated entry. Caller must hold @bul_lock (write). -+ **/ -+struct mipv6_bul_entry *mipv6_bul_add( -+ struct in6_addr *cn_addr, struct in6_addr *home_addr, -+ struct in6_addr *coa, -+ __u32 lifetime, __u16 seq, __u8 flags, -+ int (*callback)(struct mipv6_bul_entry *entry), -+ __u32 callback_time, -+ __u8 state, __u32 delay, __u32 maxdelay, -+ struct mipv6_mh_opt *ops, -+ struct mipv6_rr_info *rr) -+{ -+ struct mipv6_bul_entry *entry; -+ int update = 0; -+ struct in6_addr_pair hashkey; -+ -+ DEBUG_FUNC(); -+ -+ if (unlikely(bul.entries == NULL)) -+ return NULL; -+ -+ if (cn_addr == NULL || home_addr == NULL || coa == NULL || -+ lifetime < 0 || callback == NULL || callback_time < 0 || -+ (state != ACK_OK && state != RESEND_EXP && state != ACK_ERROR) || -+ delay < 0 || maxdelay < 0) { -+ DEBUG(DBG_ERROR, "invalid arguments"); -+ return NULL; -+ } -+ DEBUG(DBG_INFO, "cn_addr: %x:%x:%x:%x:%x:%x:%x:%x, " -+ "home_addr: %x:%x:%x:%x:%x:%x:%x:%x" -+ "coaddr: %x:%x:%x:%x:%x:%x:%x:%x", NIPV6ADDR(cn_addr), -+ NIPV6ADDR(home_addr), NIPV6ADDR(coa)); -+ hashkey.a1 = cn_addr; -+ hashkey.a2 = home_addr; -+ -+ /* -+ * decide whether to add a new entry or update existing, also -+ * check if there's room for a new entry when adding a new -+ * entry (latter is handled by mipv6_bul_get_entry() -+ */ -+ if ((entry = (struct mipv6_bul_entry *) -+ hashlist_get(bul.entries, &hashkey)) != NULL) { -+ /* if an entry for this cn_addr exists (with smaller -+ * seq than the new entry's seq), update it */ -+ -+ if (MIPV6_SEQ_GT(seq, entry->seq)) { -+ DEBUG(DBG_INFO, "updating an existing entry"); -+ update = 1; -+ } else { -+ DEBUG(DBG_INFO, "smaller seq than existing, not updating"); -+ return NULL; -+ } -+ } else { -+ entry = mipv6_bul_get_entry(); -+ if (entry == NULL) { -+ DEBUG(DBG_WARNING, "binding update list full, can't add!!!"); -+ return NULL; -+ } -+ memset(entry, 0, sizeof(*entry)); -+ /* First BU send happens here, save count in the entry */ -+ entry->consecutive_sends = 1; -+ } -+ -+ if (!update) { -+ ipv6_addr_copy(&(entry->cn_addr), cn_addr); -+ ipv6_addr_copy(&(entry->home_addr), home_addr); -+ entry->ops = ops; -+ } -+ /* Add Return Routability info to bul entry */ -+ if (rr) { -+ if(entry->rr) -+ kfree(entry->rr); -+ entry->rr = rr; -+ } -+ -+ ipv6_addr_copy(&(entry->coa), coa); -+ entry->lifetime = lifetime; -+ if (lifetime) -+ entry->expire = jiffies + lifetime * HZ; -+ else if (flags & MIPV6_BU_F_ACK) -+ entry->expire = jiffies + HOME_RESEND_EXPIRE * HZ; -+ entry->seq = seq; -+ entry->flags = flags; -+ entry->lastsend = jiffies; /* current time = last use of the entry */ -+ entry->state = state; -+ entry->delay = delay; -+ entry->maxdelay = maxdelay; -+ entry->callback_time = jiffies + callback_time * HZ; -+ entry->callback = callback; -+ -+ if (flags & MIPV6_BU_F_HOME && -+ mipv6_mv_tnl_to_ha(cn_addr, coa, home_addr)) { -+ DEBUG(DBG_ERROR, "reconfiguration of the tunnel failed"); -+ } -+ if (update) { -+ DEBUG(DBG_INFO, "updating entry: %x", entry); -+ hashlist_reposition(bul.entries, (void *)entry, -+ entry->callback_time); -+ } else { -+ DEBUG(DBG_INFO, "adding entry: %x", entry); -+ -+ hashkey.a1 = &entry->cn_addr; -+ hashkey.a2 = &entry->home_addr; -+ -+ if ((hashlist_add(bul.entries, &hashkey, -+ entry->callback_time, -+ entry)) < 0) { -+ DEBUG(DBG_ERROR, "Hash add failed"); -+ mipv6_bul_entry_free(entry); -+ return NULL; -+ } -+ } -+ timer_update(); -+ -+ return entry; -+} -+ -+/** -+ * mipv6_bul_delete - delete Binding Update List entry -+ * @cn_addr: address for entry to delete -+ * -+ * Deletes the entry for @cn_addr from the Binding Update List. -+ * Returns zero if entry was deleted succesfully, otherwise returns -+ * negative. Caller may not hold @bul_lock. -+ **/ -+int mipv6_bul_delete(struct in6_addr *cn_addr, struct in6_addr *home_addr) -+{ -+ struct mipv6_bul_entry *entry; -+ struct in6_addr_pair hashkey; -+ -+ DEBUG_FUNC(); -+ -+ hashkey.a1 = cn_addr; -+ hashkey.a2 = home_addr; -+ -+ write_lock(&bul_lock); -+ -+ if (unlikely(bul.entries == NULL) || -+ (entry = (struct mipv6_bul_entry *) -+ hashlist_get(bul.entries, &hashkey)) == NULL) { -+ write_unlock(&bul_lock); -+ DEBUG(DBG_INFO, "No such entry"); -+ return -ENOENT; -+ } -+ -+ hashlist_delete(bul.entries, (void *)entry); -+ -+ del_bul_entry_tnl(entry); -+ -+ mipv6_bul_entry_free(entry); -+ timer_update(); -+ write_unlock(&bul_lock); -+ -+ DEBUG(DBG_INFO, "Binding update list entry deleted"); -+ -+ return 0; -+} -+ -+/********************************************************************** -+ * -+ * Proc interface functions -+ * -+ **********************************************************************/ -+ -+#define BUL_INFO_LEN 152 -+ -+struct procinfo_iterator_args { -+ char *buffer; -+ int offset; -+ int length; -+ int skip; -+ int len; -+}; -+ -+static int procinfo_iterator(void *data, void *args, -+ unsigned long *sortkey) -+{ -+ struct procinfo_iterator_args *arg = -+ (struct procinfo_iterator_args *)args; -+ struct mipv6_bul_entry *entry = -+ (struct mipv6_bul_entry *)data; -+ unsigned long callback_seconds; -+ -+ DEBUG_FUNC(); -+ -+ if (entry == NULL) return ITERATOR_ERR; -+ -+ if (time_after(jiffies, entry->callback_time)) -+ callback_seconds = 0; -+ else -+ callback_seconds = (entry->callback_time - jiffies) / HZ; -+ -+ if (arg->skip < arg->offset / BUL_INFO_LEN) { -+ arg->skip++; -+ return ITERATOR_CONT; -+ } -+ -+ if (arg->len >= arg->length) -+ return ITERATOR_CONT; -+ -+ /* CN HoA CoA ExpInSecs SeqNum State Delay MaxDelay CallbackInSecs */ -+ arg->len += sprintf(arg->buffer + arg->len, -+ "%08x%08x%08x%08x %08x%08x%08x%08x %08x%08x%08x%08x\n" -+ "%010lu %05d %02d %010d %010d %010lu\n", -+ ntohl(entry->cn_addr.s6_addr32[0]), -+ ntohl(entry->cn_addr.s6_addr32[1]), -+ ntohl(entry->cn_addr.s6_addr32[2]), -+ ntohl(entry->cn_addr.s6_addr32[3]), -+ ntohl(entry->home_addr.s6_addr32[0]), -+ ntohl(entry->home_addr.s6_addr32[1]), -+ ntohl(entry->home_addr.s6_addr32[2]), -+ ntohl(entry->home_addr.s6_addr32[3]), -+ ntohl(entry->coa.s6_addr32[0]), -+ ntohl(entry->coa.s6_addr32[1]), -+ ntohl(entry->coa.s6_addr32[2]), -+ ntohl(entry->coa.s6_addr32[3]), -+ (entry->expire - jiffies) / HZ, -+ entry->seq, entry->state, entry->delay, -+ entry->maxdelay, callback_seconds); -+ -+ return ITERATOR_CONT; -+} -+ -+ -+/* -+ * Callback function for proc filesystem. -+ */ -+static int bul_proc_info(char *buffer, char **start, off_t offset, -+ int length) -+{ -+ struct procinfo_iterator_args args; -+ -+ DEBUG_FUNC(); -+ -+ args.buffer = buffer; -+ args.offset = offset; -+ args.length = length; -+ args.skip = 0; -+ args.len = 0; -+ -+ read_lock_bh(&bul_lock); -+ hashlist_iterate(bul.entries, &args, procinfo_iterator); -+ read_unlock_bh(&bul_lock); -+ -+ *start = buffer; -+ if (offset) -+ *start += offset % BUL_INFO_LEN; -+ -+ args.len -= offset % BUL_INFO_LEN; -+ -+ if (args.len > length) -+ args.len = length; -+ if (args.len < 0) -+ args.len = 0; -+ -+ return args.len; -+} -+ -+/********************************************************************** -+ * -+ * Code module init/fini functions -+ * -+ **********************************************************************/ -+ -+int __init mipv6_bul_init(__u32 size) -+{ -+ DEBUG_FUNC(); -+ -+ if (size < 1) { -+ DEBUG(DBG_CRITICAL, -+ "Binding update list size must be at least 1"); -+ return -EINVAL; -+ } -+ bul.entries = hashlist_create(MIPV6_BUL_HASHSIZE, size, -+ sizeof(struct mipv6_bul_entry), -+ "mip6_bul", NULL, NULL, -+ bul_compare, bul_hash); -+ -+ if (bul.entries == NULL) { -+ DEBUG(DBG_CRITICAL, "Couldn't allocate memory for " -+ "hashlist when creating a binding update list"); -+ return -ENOMEM; -+ } -+ init_timer(&bul.callback_timer); -+ bul.callback_timer.data = 0; -+ bul.callback_timer.function = timer_handler; -+ proc_net_create("mip6_bul", 0, bul_proc_info); -+ DEBUG(DBG_INFO, "Binding update list initialized"); -+ return 0; -+} -+ -+void __exit mipv6_bul_exit() -+{ -+ struct mipv6_bul_entry *entry; -+ struct hashlist *entries; -+ -+ DEBUG_FUNC(); -+ -+ proc_net_remove("mip6_bul"); -+ -+ write_lock_bh(&bul_lock); -+ -+ DEBUG(DBG_INFO, "Stopping the bul timer"); -+ del_timer(&bul.callback_timer); -+ -+ while ((entry = (struct mipv6_bul_entry *) -+ hashlist_get_first(bul.entries)) != NULL) { -+ hashlist_delete(bul.entries, (void *)entry); -+ -+ del_bul_entry_tnl(entry); -+ -+ mipv6_bul_entry_free(entry); -+ } -+ entries = bul.entries; -+ bul.entries = NULL; -+ write_unlock_bh(&bul_lock); -+ -+ hashlist_destroy(entries); -+ -+ DEBUG(DBG_INFO, "binding update list destroyed"); -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/bul.h linux-2.4.25/net/ipv6/mobile_ip6/bul.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/bul.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/bul.h 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,91 @@ -+/* -+ * MIPL Mobile IPv6 Binding Update List header file -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _BUL_H -+#define _BUL_H -+ -+#include "hashlist.h" -+ -+#define ACK_OK 0x01 -+#define RESEND_EXP 0x02 -+#define ACK_ERROR 0x04 -+ -+#define HOME_RESEND_EXPIRE 3600 -+#define MIPV6_COOKIE_LEN 8 -+struct mipv6_rr_info { -+ /* RR information */ -+ u16 rr_state; /* State of the RR */ -+ u16 rr_flags; /* Flags for the RR */ -+ u8 hot_cookie[MIPV6_COOKIE_LEN]; /* HoT Cookie */ -+ u8 cot_cookie[MIPV6_COOKIE_LEN]; /* CoT Cookie */ -+ u8 home_cookie[MIPV6_COOKIE_LEN]; /* Home Cookie */ -+ u8 careof_cookie[MIPV6_COOKIE_LEN]; /* Careof Cookie */ -+ u32 lastsend_hoti; /* When HoTI was last sent (jiffies) */ -+ u32 lastsend_coti; /* When CoTI was last sent (jiffies) */ -+ u32 home_time; /* when Care-of cookie was received */ -+ u32 careof_time; /* when Home cookie was received */ -+ int home_nonce_index; /* Home cookie nonce index */ -+ int careof_nonce_index; /* Care-of cookie nonce index */ -+ u8 *kbu; /* Binding authentication key */ -+}; -+struct mipv6_bul_entry { -+ struct hashlist_entry e; -+ struct in6_addr cn_addr; /* CN to which BU was sent */ -+ struct in6_addr home_addr; /* home address of this binding */ -+ struct in6_addr coa; /* care-of address of the sent BU */ -+ -+ unsigned long expire; /* entry's expiration time (jiffies) */ -+ __u32 lifetime; /* lifetime sent in this BU */ -+ __u32 lastsend; /* last time when BU sent (jiffies) */ -+ __u32 consecutive_sends; /* Number of consecutive BU's sent */ -+ __u16 seq; /* sequence number of the latest BU */ -+ __u8 flags; /* BU send flags */ -+ __u8 state; /* resend state */ -+ __u32 initdelay; /* initial ack wait */ -+ __u32 delay; /* current ack wait */ -+ __u32 maxdelay; /* maximum ack wait */ -+ -+ struct mipv6_rr_info *rr; -+ struct mipv6_mh_opt *ops; /* saved option values */ -+ -+ unsigned long callback_time; -+ int (*callback)(struct mipv6_bul_entry *entry); -+}; -+ -+extern rwlock_t bul_lock; -+ -+int mipv6_bul_init(__u32 size); -+ -+void mipv6_bul_exit(void); -+ -+struct mipv6_bul_entry *mipv6_bul_add( -+ struct in6_addr *cn_addr, struct in6_addr *home_addr, -+ struct in6_addr *coa, __u32 lifetime, __u16 seq, __u8 flags, -+ int (*callback)(struct mipv6_bul_entry *entry), __u32 callback_time, -+ __u8 state, __u32 delay, __u32 maxdelay, struct mipv6_mh_opt *ops, -+ struct mipv6_rr_info *rr); -+ -+int mipv6_bul_delete(struct in6_addr *cn_addr, struct in6_addr *home_addr); -+ -+int mipv6_bul_exists(struct in6_addr *cnaddr, struct in6_addr *home_addr); -+ -+struct mipv6_bul_entry *mipv6_bul_get(struct in6_addr *cnaddr, -+ struct in6_addr *home_addr); -+struct mipv6_bul_entry *mipv6_bul_get_by_ccookie(struct in6_addr *cn_addr, -+ u8 *cookie); -+ -+int bul_entry_expired(struct mipv6_bul_entry *bulentry); -+ -+void mipv6_bul_reschedule(struct mipv6_bul_entry *entry); -+ -+int mipv6_bul_iterate(int (*func)(void *, void *, unsigned long *), void *args); -+ -+#endif /* BUL_H */ -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/config.h linux-2.4.25/net/ipv6/mobile_ip6/config.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/config.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/config.h 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,72 @@ -+/* -+ * Configuration parameters -+ * -+ * $Id$ -+ */ -+ -+#define MIPV6VERSION "D24" -+#define MIPLVERSION "v1.0" -+ -+#define CAP_CN 0x01 -+#define CAP_HA 0x02 -+#define CAP_MN 0x04 -+ -+struct mip6_conf { -+ int capabilities; -+ int debug_level; -+ int accept_ret_rout; -+ int max_rtr_reachable_time; -+ int eager_cell_switching; -+ int max_num_tunnels; -+ int min_num_tunnels; -+ int binding_refresh_advice; -+ int bu_lladdr; -+ int bu_keymgm; -+ int bu_cn_ack; -+}; -+ -+extern struct mip6_conf mip6node_cnf; -+ -+struct mipv6_bce; -+ -+struct mip6_func { -+ void (*bce_home_add) (int ifindex, struct in6_addr *daddr, -+ struct in6_addr *haddr, struct in6_addr *coa, -+ struct in6_addr *rep_coa, __u32 lifetime, -+ __u16 sequence, __u8 flags, __u8 *k_bu); -+ void (*bce_cache_add) (int ifindex, struct in6_addr *daddr, -+ struct in6_addr *haddr, struct in6_addr *coa, -+ struct in6_addr *rep_coa, __u32 lifetime, -+ __u16 sequence, __u8 flags, __u8 *k_bu); -+ void (*bce_home_del) (struct in6_addr *daddr, struct in6_addr *haddr, -+ struct in6_addr *coa, struct in6_addr *rep_coa, -+ __u16 sequence, __u8 flags, -+ __u8 *k_bu); -+ void (*bce_cache_del) (struct in6_addr *daddr, struct in6_addr *haddr, -+ struct in6_addr *coa, struct in6_addr *rep_coa, -+ __u16 sequence, __u8 flags, -+ __u8 *k_bu); -+ -+ int (*bce_tnl_rt_add) (struct in6_addr *coa, -+ struct in6_addr *ha_addr, -+ struct in6_addr *home_addr); -+ -+ void (*bce_tnl_rt_del) (struct in6_addr *coa, -+ struct in6_addr *ha_addr, -+ struct in6_addr *home_addr); -+ -+ void (*proxy_del) (struct in6_addr *home_addr, struct mipv6_bce *entry); -+ int (*proxy_create) (int flags, int ifindex, struct in6_addr *coa, -+ struct in6_addr *our_addr, struct in6_addr *home_addr); -+ -+ int (*icmpv6_dhaad_rep_rcv) (struct sk_buff *skb); -+ int (*icmpv6_dhaad_req_rcv) (struct sk_buff *skb); -+ int (*icmpv6_pfxadv_rcv) (struct sk_buff *skb); -+ int (*icmpv6_pfxsol_rcv) (struct sk_buff *skb); -+ int (*icmpv6_paramprob_rcv) (struct sk_buff *skb); -+ -+ int (*mn_use_hao) (struct in6_addr *daddr, struct in6_addr *saddr); -+ void (*mn_check_tunneled_packet) (struct sk_buff *skb); -+}; -+ -+extern struct mip6_func mip6_fn; -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/debug.h linux-2.4.25/net/ipv6/mobile_ip6/debug.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/debug.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/debug.h 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,112 @@ -+/* -+ * MIPL Mobile IPv6 Debugging macros and functions -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _DEBUG_H -+#define _DEBUG_H -+ -+#include -+ -+/* priorities for different debug conditions */ -+ -+#define DBG_CRITICAL 0 /* unrecoverable error */ -+#define DBG_ERROR 1 /* error (recoverable) */ -+#define DBG_WARNING 2 /* unusual situation but not a real error */ -+#define DBG_INFO 3 /* generally useful information */ -+#define DBG_EXTRA 4 /* extra information */ -+#define DBG_FUNC_ENTRY 6 /* use to indicate function entry and exit */ -+#define DBG_DATADUMP 7 /* packet dumps, etc. lots of flood */ -+ -+/** -+ * NIPV6ADDR - macro for IPv6 addresses -+ * @addr: Network byte order IPv6 address -+ * -+ * Macro for printing IPv6 addresses. Used in conjunction with -+ * printk() or derivatives (such as DEBUG macro). -+ **/ -+#define NIPV6ADDR(addr) \ -+ ntohs(((u16 *)addr)[0]), \ -+ ntohs(((u16 *)addr)[1]), \ -+ ntohs(((u16 *)addr)[2]), \ -+ ntohs(((u16 *)addr)[3]), \ -+ ntohs(((u16 *)addr)[4]), \ -+ ntohs(((u16 *)addr)[5]), \ -+ ntohs(((u16 *)addr)[6]), \ -+ ntohs(((u16 *)addr)[7]) -+ -+#ifdef CONFIG_IPV6_MOBILITY_DEBUG -+extern int mipv6_debug; -+ -+/** -+ * debug_print - print debug message -+ * @debug_level: message priority -+ * @fname: calling function's name -+ * @fmt: printf-style formatting string -+ * -+ * Prints a debug message to system log if @debug_level is less or -+ * equal to @mipv6_debug. Should always be called using DEBUG() -+ * macro, not directly. -+ **/ -+static void debug_print(int debug_level, const char *fname, const char* fmt, ...) -+{ -+ char s[1024]; -+ va_list args; -+ -+ if (mipv6_debug < debug_level) -+ return; -+ -+ va_start(args, fmt); -+ vsprintf(s, fmt, args); -+ printk("mip6[%s]: %s\n", fname, s); -+ va_end(args); -+} -+ -+/** -+ * debug_print_buffer - print arbitrary buffer to system log -+ * @debug_level: message priority -+ * @data: pointer to buffer -+ * @len: number of bytes to print -+ * -+ * Prints @len bytes from buffer @data to system log. @debug_level -+ * tells on which debug level message gets printed. For -+ * debug_print_buffer() priority %DBG_DATADUMP should be used. -+ **/ -+#define debug_print_buffer(debug_level,data,len) { \ -+ if (mipv6_debug >= debug_level) { \ -+ int i; \ -+ for (i=0; i -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 "debug.h" -+#include "stats.h" -+#include "mobhdr.h" -+#include "bcache.h" -+#include "config.h" -+ -+/** -+ * mipv6_append_home_addr - Add Home Address Option -+ * @opt: buffer for Home Address Option -+ * @offset: offset from beginning of @opt -+ * @addr: address for HAO -+ * -+ * Adds a Home Address Option to a packet. Option is stored in -+ * @offset from beginning of @opt. The option is created but the -+ * original source address in IPv6 header is left intact. The source -+ * address will be changed from home address to CoA after the checksum -+ * has been calculated in getfrag. Padding is done automatically, and -+ * @opt must have allocated space for both actual option and pad. -+ * Returns offset from @opt to end of options. -+ **/ -+int mipv6_append_home_addr(__u8 *opt, int offset, struct in6_addr *addr) -+{ -+ int pad; -+ struct mipv6_dstopt_homeaddr *ho; -+ -+ DEBUG(DBG_DATADUMP, "HAO: %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(addr)); -+ -+ pad = (6 - offset) & 7; -+ mipv6_add_pad(opt + offset, pad); -+ -+ ho = (struct mipv6_dstopt_homeaddr *)(opt + offset + pad); -+ ho->type = MIPV6_TLV_HOMEADDR; -+ ho->length = sizeof(*ho) - 2; -+ ipv6_addr_copy(&ho->addr, addr); -+ -+ return offset + pad + sizeof(*ho); -+} -+static inline int check_hao_validity(struct mipv6_dstopt_homeaddr *haopt, -+ u8 *dst1, -+ struct in6_addr *saddr, -+ struct in6_addr *daddr) -+{ -+ int addr_type = ipv6_addr_type(&haopt->addr); -+ struct mipv6_bce bc_entry; -+ -+ if (addr_type & IPV6_ADDR_LINKLOCAL || -+ !(addr_type & IPV6_ADDR_UNICAST)) { -+ DEBUG(DBG_INFO, "HAO with link local or non-unicast HoA, " -+ "not sending BE to " -+ "home address " -+ "%x:%x:%x:%x:%x:%x:%x:%x ", -+ "care-of address %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(&haopt->addr), -+ NIPV6ADDR(saddr)); -+ return -EINVAL; -+ } else if (dst1[0] != IPPROTO_MOBILITY && -+ (mipv6_bcache_get(&haopt->addr, -+ daddr, &bc_entry) != 0 || -+ ipv6_addr_cmp(saddr, &bc_entry.coa))) { -+ DEBUG(DBG_INFO, "HAO without binding or incorrect CoA, " -+ "sending BE code 1: " -+ "home address %x:%x:%x:%x:%x:%x:%x:%x", -+ "to care-of address %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(&haopt->addr), -+ NIPV6ADDR(saddr)); -+ return -ENOENT; -+ } -+ return 0; -+} -+/** -+ * mipv6_handle_homeaddr - Home Address Destination Option handler -+ * @skb: packet buffer -+ * @optoff: offset to where option begins -+ * -+ * Handles Home Address Option in IPv6 Destination Option header. -+ * Packet and offset to option are passed. If HAO is used without -+ * binding, sends a Binding Error code 1. When sending BE, notify bit -+ * is cleared to prevent IPv6 error handling from sending ICMP -+ * Parameter Problem. Returns 1 on success, otherwise zero. -+ **/ -+int mipv6_handle_homeaddr(struct sk_buff *skb, int optoff) -+{ -+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr; -+ struct in6_addr coaddr; -+ struct inet6_skb_parm *opt = (struct inet6_skb_parm *) skb->cb; -+ struct mipv6_dstopt_homeaddr *haopt = -+ (struct mipv6_dstopt_homeaddr *) &skb->nh.raw[optoff]; -+ u8 *dst1; -+ int err; -+ -+ DEBUG_FUNC(); -+ -+ if (haopt->length != sizeof(*haopt) - 2) { -+ DEBUG(DBG_WARNING, "HAO has invalid length"); -+ MIPV6_INC_STATS(n_ha_drop.invalid); -+ return 0; -+ } -+ dst1 = (u8 *)skb->h.raw; -+ err = check_hao_validity(haopt, dst1, saddr, &skb->nh.ipv6h->daddr); -+ -+ if (err) { -+ haopt->type &= ~(0x80); /* clear notify bit */ -+ if (err == -ENOENT) -+ mipv6_send_be(&skb->nh.ipv6h->daddr, saddr, -+ &haopt->addr, MIPV6_BE_HAO_WO_BINDING); -+ MIPV6_INC_STATS(n_ha_drop.misc); -+ return 0; -+ } -+ ipv6_addr_copy(&coaddr, saddr); -+ ipv6_addr_copy(saddr, &haopt->addr); -+ ipv6_addr_copy(&haopt->addr, &coaddr); -+ opt->hao = optoff; -+ if (mip6_fn.mn_check_tunneled_packet != NULL) -+ mip6_fn.mn_check_tunneled_packet(skb); -+ -+ MIPV6_INC_STATS(n_ha_rcvd); -+ return 1; -+} -+ -+/** -+ * mipv6_icmp_swap_addrs - Switch HAO and src and RT2 and dest for ICMP errors -+ * @skb: packet buffer -+ * -+ * Reset the source address and the Home Address option in skb before -+ * appending it to an ICMP error message, so original packet appears -+ * in the error message rather than mangled. -+ **/ -+void mipv6_icmp_swap_addrs(struct sk_buff *skb) -+{ -+ struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; -+ struct in6_addr tmp; -+ struct in6_addr *hoa; -+ DEBUG_FUNC(); -+ if (opt->srcrt2) { -+ struct rt2_hdr *rt2; -+ rt2 = (struct rt2_hdr *)(skb->nh.raw + opt->srcrt2); -+ hoa = &rt2->addr; -+ -+ ipv6_addr_copy(&tmp, hoa); -+ ipv6_addr_copy(hoa, &skb->nh.ipv6h->daddr); -+ ipv6_addr_copy(&skb->nh.ipv6h->daddr, &tmp); -+ rt2->rt_hdr.segments_left++; -+ skb->nh.ipv6h->hop_limit++; -+ } -+ if (opt->hao) { -+ struct mipv6_dstopt_homeaddr *hao; -+ hao = (struct mipv6_dstopt_homeaddr *)(skb->nh.raw + opt->hao); -+ hoa = &hao->addr; -+ -+ ipv6_addr_copy(&tmp, hoa); -+ ipv6_addr_copy(hoa, &skb->nh.ipv6h->saddr); -+ ipv6_addr_copy(&skb->nh.ipv6h->saddr, &tmp); -+ } -+} -+ -+/** -+ * mipv6_append_rt2hdr - Add Type 2 Routing Header -+ * @rt: buffer for new routing header -+ * @addr: intermediate hop address -+ * -+ * Adds a Routing Header Type 2 in a packet. Stores newly created -+ * routing header in buffer @rt. Type 2 RT only carries one address, -+ * so there is no need to process old routing header. @rt must have -+ * allocated space for 24 bytes. -+ **/ -+void mipv6_append_rt2hdr(struct ipv6_rt_hdr *rt, struct in6_addr *addr) -+{ -+ struct rt2_hdr *rt2 = (struct rt2_hdr *)rt; -+ -+ DEBUG(DBG_DATADUMP, "RT2: %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(addr)); -+ -+ if (ipv6_addr_type(addr) == IPV6_ADDR_MULTICAST) { -+ DEBUG(DBG_ERROR, "destination address not unicast"); -+ return; -+ } -+ -+ memset(rt2, 0, sizeof(*rt2)); -+ rt2->rt_hdr.type = 2; -+ rt2->rt_hdr.hdrlen = 2; -+ rt2->rt_hdr.segments_left = 1; -+ ipv6_addr_copy(&rt2->addr, addr); -+} -+ -+/** -+ * mipv6_append_dst1opts - Add Destination Option (1) Headers -+ * @dst1opt: buffer for new destination options -+ * @saddr: address for Home Address Option -+ * @old_dst1opt: old destination options -+ * @len: length of options -+ * -+ * Adds Destination Option (1) Header to a packet. New options are -+ * stored in @dst1opt. If old destination options exist, they are -+ * copied from @old_dst1opt. Only Home Address Option is destination -+ * option. @dstopt must have allocated space for @len bytes. @len -+ * includes Destination Option Header (2 bytes), Home Address Option -+ * (18 bytes) and possible HAO pad (8n+6). -+ **/ -+/* -+ * ISSUE: Home Address Destination Option should really be added to a -+ * new destination option header specified in Mobile IPv6 spec which -+ * should be placed after routing header(s), but before fragmentation -+ * header. Putting HAO in DO1 works for now, but support for the new -+ * placement should be added to the IPv6 stack. -+ */ -+void -+mipv6_append_dst1opts(struct ipv6_opt_hdr *dst1opt, struct in6_addr *saddr, -+ struct ipv6_opt_hdr *old_dst1opt, int len) -+{ -+ int offset; -+ -+ if (old_dst1opt) { -+ memcpy(dst1opt, old_dst1opt, ipv6_optlen(old_dst1opt)); -+ offset = ipv6_optlen(old_dst1opt); -+ } else { -+ offset = sizeof (*dst1opt); -+ } -+ dst1opt->hdrlen = (len >> 3) - 1; -+ mipv6_append_home_addr((__u8 *) dst1opt, offset, saddr); -+} -+ -+/** -+ * mipv6_modify_txoptions - Modify outgoing packets -+ * @sk: socket -+ * @skb: packet buffer for outgoing packet -+ * @old_opt: transmit options -+ * @fl: packet flow structure -+ * @dst: pointer to destination cache entry -+ * -+ * Adds Home Address Option (for MN packets, when not at home) and -+ * Routing Header Type 2 (for CN packets when sending to an MN) to -+ * data packets. Old extension headers are copied from @old_opt (if -+ * any). Extension headers are _explicitly_ added for packets with -+ * Mobility Header. Returns the new header structure, or old if no -+ * changes. -+ **/ -+struct ipv6_txoptions * -+mipv6_modify_txoptions(struct sock *sk, struct sk_buff *skb, -+ struct ipv6_txoptions *old_opt, struct flowi *fl, -+ struct dst_entry **dst) -+{ -+ struct ipv6_opt_hdr *old_hopopt = NULL; -+ struct ipv6_opt_hdr *old_dst1opt = NULL; -+ struct ipv6_rt_hdr *old_srcrt = NULL; -+ -+ int srcrtlen = 0, dst1len = 0; -+ int tot_len, use_hao = 0; -+ struct ipv6_txoptions *opt; -+ struct mipv6_bce bc_entry; -+ struct in6_addr tmpaddr, *saddr, *daddr, coaddr; -+ __u8 *opt_ptr; -+ -+ DEBUG_FUNC(); -+ -+ if (fl->proto == IPPROTO_MOBILITY) return old_opt; -+ /* -+ * we have to be prepared to the fact that saddr might not be present, -+ * if that is the case, we acquire saddr just as kernel does. -+ */ -+ saddr = fl ? fl->fl6_src : NULL; -+ daddr = fl ? fl->fl6_dst : NULL; -+ -+ if (daddr == NULL) -+ return old_opt; -+ if (saddr == NULL) { -+ int err = ipv6_get_saddr(NULL, daddr, &tmpaddr); -+ if (err) -+ return old_opt; -+ else -+ saddr = &tmpaddr; -+ } -+ -+ DEBUG(DBG_DATADUMP, -+ "dest. address of packet: %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(daddr)); -+ DEBUG(DBG_DATADUMP, " and src. address: %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(saddr)); -+ -+ if (old_opt) { -+ old_hopopt = old_opt->hopopt; -+ old_dst1opt = old_opt->dst1opt; -+ old_srcrt = old_opt->srcrt; -+ } -+ -+ if (mip6_fn.mn_use_hao != NULL) -+ use_hao = mip6_fn.mn_use_hao(daddr, saddr); -+ -+ if (use_hao) { -+ if (old_dst1opt) -+ dst1len = ipv6_optlen(old_dst1opt); -+ dst1len += sizeof(struct mipv6_dstopt_homeaddr) + -+ ((6 - dst1len) & 7); /* padding */ -+ } -+ -+ if (mipv6_bcache_get(daddr, saddr, &bc_entry) == 0) -+ srcrtlen = sizeof(struct rt2_hdr); -+ -+ if ((tot_len = srcrtlen + dst1len) == 0) { -+ return old_opt; -+ } -+ -+ tot_len += sizeof(*opt); -+ -+ if (!(opt = kmalloc(tot_len, GFP_ATOMIC))) { -+ return NULL; -+ } -+ memset(opt, 0, tot_len); -+ opt->tot_len = tot_len; -+ opt_ptr = (__u8 *) (opt + 1); -+ -+ if (old_srcrt) { -+ opt->srcrt = old_srcrt; -+ opt->opt_nflen += ipv6_optlen(old_srcrt); -+ } -+ -+ if (srcrtlen) { -+ DEBUG(DBG_DATADUMP, "Binding exists. Adding routing header"); -+ -+ opt->srcrt2 = (struct ipv6_rt_hdr *) opt_ptr; -+ opt->opt_nflen += srcrtlen; -+ opt_ptr += srcrtlen; -+ -+ /* -+ * Append care-of-address to routing header (original -+ * destination address is home address, the first -+ * source route segment gets put to the destination -+ * address and the home address gets to the last -+ * segment of source route (just as it should)) -+ */ -+ -+ ipv6_addr_copy(&coaddr, &bc_entry.coa); -+ -+ mipv6_append_rt2hdr(opt->srcrt2, &coaddr); -+ -+ /* -+ * reroute output (we have to do this in case of TCP -+ * segment) unless a routing header of type 0 is also added -+ */ -+ if (dst && !opt->srcrt) { -+ struct in6_addr *tmp = fl->fl6_dst; -+ fl->fl6_dst = &coaddr; -+ -+ dst_release(*dst); -+ *dst = ip6_route_output(sk, fl); -+ if (skb) -+ skb->dst = *dst; -+ fl->fl6_dst = tmp; -+ -+ DEBUG(DBG_DATADUMP, "Rerouted outgoing packet"); -+ } -+ } -+ -+ /* Only home address option is inserted to first dst opt header */ -+ if (dst1len) { -+ opt->dst1opt = (struct ipv6_opt_hdr *) opt_ptr; -+ opt->opt_flen += dst1len; -+ opt_ptr += dst1len; -+ mipv6_append_dst1opts(opt->dst1opt, saddr, -+ old_dst1opt, dst1len); -+ opt->mipv6_flags = MIPV6_SND_HAO; -+ } else if (old_dst1opt) { -+ opt->dst1opt = old_dst1opt; -+ opt->opt_flen += ipv6_optlen(old_dst1opt); -+ } -+ if (old_hopopt) { -+ opt->hopopt = old_hopopt; -+ opt->opt_nflen += ipv6_optlen(old_hopopt); -+ } -+ -+ return opt; -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/exthdrs.h linux-2.4.25/net/ipv6/mobile_ip6/exthdrs.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/exthdrs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/exthdrs.h 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,47 @@ -+/* -+ * MIPL Mobile IPv6 Extension Headers header file -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _MIPV6_EXTHDRS_H -+#define _MIPV6_EXTHDRS_H -+ -+struct in6_addr; -+struct sk_buff; -+struct ipv6_rt_hdr; -+struct ipv6_opt_hdr; -+struct ipv6_txoptions; -+struct flowi; -+struct dst_entry; -+/* -+ * Home Address Destination Option function prototypes -+ */ -+int mipv6_append_home_addr(__u8 *opt, int offset, struct in6_addr *addr); -+ -+int mipv6_handle_homeaddr(struct sk_buff *skb, int optoff); -+ -+void mipv6_icmp_swap_addrs(struct sk_buff *skb); -+ -+/* -+ * Creates a routing header of type 2. -+ */ -+void mipv6_append_rt2hdr(struct ipv6_rt_hdr *srcrt, struct in6_addr *addr); -+ -+/* Function to add the first destination option header, which may -+ * include a home address option. -+ */ -+void mipv6_append_dst1opts(struct ipv6_opt_hdr *dst1opt, struct in6_addr *saddr, -+ struct ipv6_opt_hdr *old_dst1opt, int len); -+ -+struct ipv6_txoptions *mipv6_modify_txoptions( -+ struct sock *sk, struct sk_buff *skb, -+ struct ipv6_txoptions *old_opt, struct flowi *fl, -+ struct dst_entry **dst); -+ -+#endif /* _MIPV6_EXTHDRS_H */ -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/ha.c linux-2.4.25/net/ipv6/mobile_ip6/ha.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/ha.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/ha.c 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,553 @@ -+/* -+ * Home-agent functionality -+ * -+ * Authors: -+ * Sami Kivisaari -+ * Henrik Petander -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * Changes: Venkata Jagana, -+ * Krishna Kumar : Statistics fix -+ * Masahide Nakamura : Use of mipv6_forward -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef CONFIG_SYSCTL -+#include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "tunnel_ha.h" -+#include "bcache.h" -+#include "stats.h" -+#include "debug.h" -+#include "util.h" -+#include "ha.h" -+#include "config.h" -+#include "mobhdr.h" -+ -+static int mipv6_ha_tunnel_sitelocal = 0; -+ -+#ifdef CONFIG_SYSCTL -+ -+static struct ctl_table_header *mipv6_ha_sysctl_header; -+ -+static struct mipv6_ha_sysctl_table -+{ -+ struct ctl_table_header *sysctl_header; -+ ctl_table mipv6_vars[3]; -+ ctl_table mipv6_mobility_table[2]; -+ ctl_table mipv6_proto_table[2]; -+ ctl_table mipv6_root_table[2]; -+} mipv6_ha_sysctl = { -+ NULL, -+ -+ {{NET_IPV6_MOBILITY_TUNNEL_SITELOCAL, "tunnel_sitelocal", -+ &mipv6_ha_tunnel_sitelocal, sizeof(int), 0644, NULL, -+ &proc_dointvec}, -+ {0}}, -+ -+ {{NET_IPV6_MOBILITY, "mobility", NULL, 0, 0555, -+ mipv6_ha_sysctl.mipv6_vars}, {0}}, -+ {{NET_IPV6, "ipv6", NULL, 0, 0555, -+ mipv6_ha_sysctl.mipv6_mobility_table}, {0}}, -+ {{CTL_NET, "net", NULL, 0, 0555, -+ mipv6_ha_sysctl.mipv6_proto_table}, {0}} -+}; -+ -+#endif /* CONFIG_SYSCTL */ -+ -+ -+/* this is defined in kernel IPv6 module (sockglue.c) */ -+extern struct packet_type ipv6_packet_type; -+ -+/* mipv6_forward: Intercept NS packets destined to home address of MN */ -+int mipv6_forward(struct sk_buff *skb) -+{ -+ struct ipv6hdr *ipv6h; -+ struct in6_addr *daddr, *saddr; -+ __u8 nexthdr; -+ int nhoff; -+ -+ if (skb == NULL) return 0; -+ -+ ipv6h = skb->nh.ipv6h; -+ daddr = &ipv6h->daddr; -+ saddr = &ipv6h->saddr; -+ -+ nexthdr = ipv6h->nexthdr; -+ nhoff = sizeof(*ipv6h); -+ -+ if (ipv6_ext_hdr(nexthdr)) -+ nhoff = ipv6_skip_exthdr(skb, nhoff, &nexthdr, -+ skb->len - sizeof(*ipv6h)); -+ -+ /* Do not to forward Neighbor Solicitation to Home Address of MN */ -+ if (nexthdr == IPPROTO_ICMPV6) { -+ struct icmp6hdr *icmp6h; -+ int dest_type; -+ -+ if (nhoff < 0 || !pskb_may_pull(skb, nhoff + -+ sizeof(struct icmp6hdr))) { -+ kfree_skb(skb); -+ return 0; -+ } -+ -+ dest_type = ipv6_addr_type(daddr); -+ icmp6h = (struct icmp6hdr *)&skb->nh.raw[nhoff]; -+ -+ /* Intercepts NS to HoA of MN */ -+ -+ if ((icmp6h->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) || -+ ((dest_type & IPV6_ADDR_MULTICAST) && -+ (icmp6h->icmp6_type == NDISC_ROUTER_ADVERTISEMENT))) { -+ ip6_input(skb); -+ } else { -+ ip6_forward(skb); -+ } -+ } else { -+ ip6_forward(skb); -+ } -+ return 0; -+} -+ -+ -+/** -+ * mipv6_proxy_nd_rem - stop acting as a proxy for @home_address -+ * @home_addr: address to remove -+ * @ha_addr: home agent's address on home link -+ * @linklocal: link-local compatibility bit -+ * -+ * When Home Agent acts as a proxy for an address it must leave the -+ * solicited node multicast group for that address and stop responding -+ * to neighbour solicitations. -+ **/ -+static int mipv6_proxy_nd_rem(struct in6_addr *home_addr, -+ int ifindex, int linklocal) -+{ -+ /* When MN returns home HA leaves the solicited mcast groups -+ * for MNs home addresses -+ */ -+ int err; -+ struct net_device *dev; -+ -+ DEBUG_FUNC(); -+ -+ if ((dev = dev_get_by_index(ifindex)) == NULL) { -+ DEBUG(DBG_ERROR, "couldn't get dev"); -+ return -ENODEV; -+ } -+#if 1 /* TEST */ -+ /* Remove link-local entry */ -+ if (linklocal) { -+ struct in6_addr ll_addr; -+ mipv6_generate_ll_addr(&ll_addr, home_addr); -+ if ((err = pneigh_delete(&nd_tbl, &ll_addr, dev)) < 0) { -+ DEBUG(DBG_INFO, -+ "peigh_delete failed for " -+ "%x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(&ll_addr)); -+ } -+ } -+#endif -+ /* Remove global (or site-local) entry */ -+ if ((err = pneigh_delete(&nd_tbl, home_addr, dev)) < 0) { -+ DEBUG(DBG_INFO, -+ "peigh_delete failed for " -+ "%x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(home_addr)); -+ } -+ dev_put(dev); -+ return err; -+} -+ -+/** -+ * mipv6_proxy_nd - join multicast group for this address -+ * @home_addr: address to defend -+ * @ha_addr: home agent's address on home link -+ * @linklocal: link-local compatibility bit -+ * -+ * While Mobile Node is away from home, Home Agent acts as a proxy for -+ * @home_address. HA responds to neighbour solicitations for @home_address -+ * thus getting all packets destined to home address of MN. -+ **/ -+static int mipv6_proxy_nd(struct in6_addr *home_addr, -+ int ifindex, int linklocal) -+{ -+ /* The HA sends a proxy ndisc_na message to all hosts on MN's -+ * home subnet by sending a neighbor advertisement with the -+ * home address or all addresses of the mobile node if the -+ * prefix is not 0. The addresses are formed by combining the -+ * suffix or the host part of the address with each subnet -+ * prefix that exists in the home subnet -+ */ -+ -+ /* Since no previous entry for MN exists a proxy_nd advertisement -+ * is sent to all nodes link local multicast address -+ */ -+ int err = -1; -+ -+ struct net_device *dev; -+ struct in6_addr na_saddr; -+ struct in6_addr ll_addr; -+ struct pneigh_entry *ll_pneigh; -+ struct in6_addr mcdest; -+ int send_ll_na = 0; -+ int inc_opt = 1; -+ int solicited = 0; -+ int override = 1; -+ -+ DEBUG_FUNC(); -+ -+ if ((dev = dev_get_by_index(ifindex)) == NULL) { -+ DEBUG(DBG_ERROR, "couldn't get dev"); -+ return -ENODEV; -+ } -+ -+ if (!pneigh_lookup(&nd_tbl, home_addr, dev, 1)) { -+ DEBUG(DBG_INFO, -+ "peigh_lookup failed for " -+ "%x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(home_addr)); -+ goto free_dev; -+ } -+#if 1 /* TEST */ -+ if (linklocal) { -+ mipv6_generate_ll_addr(&ll_addr, home_addr); -+ -+ if ((ll_pneigh = pneigh_lookup(&nd_tbl, &ll_addr, -+ dev, 1)) == NULL) { -+ DEBUG(DBG_INFO, -+ "peigh_lookup failed for " -+ "%x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(&ll_addr)); -+ pneigh_delete(&nd_tbl, home_addr, dev); -+ goto free_dev; -+ } else { -+ send_ll_na = 1; -+ } -+ } else { -+ ll_pneigh = NULL; -+ } -+#endif -+ /* Proxy neighbor advertisement of MN's home address -+ * to all nodes solicited multicast address -+ */ -+ if (!ipv6_get_lladdr(dev, &na_saddr)) { -+ ipv6_addr_all_nodes(&mcdest); -+ ndisc_send_na(dev, NULL, &mcdest, home_addr, 0, -+ solicited, override, inc_opt); -+#if 1 /* TEST */ -+ if (send_ll_na) { -+ ndisc_send_na(dev, NULL, &mcdest, &ll_addr, -+ 0, solicited, override, inc_opt); -+ } -+#endif -+ err = 0; -+ } else { -+ DEBUG(DBG_ERROR, "failed to get link local address for sending proxy NA"); -+ } -+free_dev: -+ dev_put(dev); -+ return err; -+ -+} -+ -+struct inet6_ifaddr *is_on_link_ipv6_address(struct in6_addr *mn_haddr, -+ struct in6_addr *ha_addr) -+{ -+ struct inet6_ifaddr *ifp; -+ struct inet6_dev *in6_dev; -+ struct inet6_ifaddr *oifp = NULL; -+ -+ if ((ifp = ipv6_get_ifaddr(ha_addr, 0)) == NULL) -+ return NULL; -+ -+ if ((in6_dev = ifp->idev) != NULL) { -+ in6_dev_hold(in6_dev); -+ oifp = in6_dev->addr_list; -+ while (oifp != NULL) { -+ spin_lock(&oifp->lock); -+ if (mipv6_prefix_compare(&oifp->addr, mn_haddr, -+ oifp->prefix_len) && -+ !(oifp->flags & IFA_F_TENTATIVE)) { -+ spin_unlock(&oifp->lock); -+ DEBUG(DBG_INFO, "Home Addr Opt: on-link"); -+ in6_ifa_hold(oifp); -+ break; -+ } -+ spin_unlock(&oifp->lock); -+ oifp = oifp->if_next; -+ } -+ in6_dev_put(in6_dev); -+ } -+ in6_ifa_put(ifp); -+/* DEBUG(DBG_WARNING, "Home Addr Opt NOT on-link"); */ -+ return oifp; -+ -+} -+ -+/* -+ * Lifetime checks. ifp->valid_lft >= ifp->prefered_lft always (see addrconf.c) -+ * Returned value is in seconds. -+ */ -+ -+static __u32 get_min_lifetime(struct inet6_ifaddr *ifp, __u32 lifetime) -+{ -+ __u32 rem_lifetime = 0; -+ unsigned long now = jiffies; -+ -+ if (ifp->valid_lft == 0) { -+ rem_lifetime = lifetime; -+ } else { -+ __u32 valid_lft_left = -+ ifp->valid_lft - ((now - ifp->tstamp) / HZ); -+ rem_lifetime = -+ min_t(unsigned long, valid_lft_left, lifetime); -+ } -+ -+ return rem_lifetime; -+} -+ -+#define MAX_LIFETIME 1000 -+ -+/** -+ * mipv6_lifetime_check - check maximum lifetime is not exceeded -+ * @lifetime: lifetime to check -+ * -+ * Checks @lifetime does not exceed %MAX_LIFETIME. Returns @lifetime -+ * if not exceeded, otherwise returns %MAX_LIFETIME. -+ **/ -+static int mipv6_lifetime_check(int lifetime) -+{ -+ return (lifetime > MAX_LIFETIME) ? MAX_LIFETIME : lifetime; -+} -+ -+/* Generic routine handling finish of BU processing */ -+void mipv6_bu_finish(struct inet6_ifaddr *ifp, int ifindex, __u8 ba_status, -+ struct in6_addr *daddr, struct in6_addr *haddr, -+ struct in6_addr *coa, struct in6_addr *rep_coa, -+ __u32 ba_lifetime, __u16 sequence, __u8 flags, __u8 *k_bu) -+{ -+ int err; -+ -+ if (ba_status >= REASON_UNSPECIFIED) { -+ /* DAD failed */ -+ goto out; -+ } -+ -+ ba_lifetime = get_min_lifetime(ifp, ba_lifetime); -+ ba_lifetime = mipv6_lifetime_check(ba_lifetime); -+ -+ if ((err = mipv6_bcache_add(ifindex, daddr, haddr, coa, -+ ba_lifetime, sequence, flags, -+ HOME_REGISTRATION)) != 0 ) { -+ DEBUG(DBG_WARNING, "home reg failed."); -+ -+ if (err == -ENOMEDIUM) -+ return; -+ -+ ba_status = INSUFFICIENT_RESOURCES; -+ } else { -+ DEBUG(DBG_INFO, "home reg succeeded."); -+ } -+ -+ DEBUG(DBG_DATADUMP, "home_addr: %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(haddr)); -+ DEBUG(DBG_DATADUMP, "coa: %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(coa)); -+ DEBUG(DBG_DATADUMP, "lifet:%d, seq:%d", ba_lifetime, sequence); -+out: -+ mipv6_send_ba(daddr, haddr, coa, rep_coa, ba_status, sequence, -+ ba_lifetime, k_bu); -+} -+ -+static int ha_proxy_create(int flags, int ifindex, struct in6_addr *coa, -+ struct in6_addr *our_addr, struct in6_addr *home_addr) -+{ -+ int ret; -+ -+ if ((ret = mipv6_add_tnl_to_mn(coa, our_addr, home_addr)) <= 0) { -+ if (ret != -ENOMEDIUM) { -+ DEBUG(DBG_ERROR, "unable to configure tunnel to MN!"); -+ } -+ return -1; -+ } -+ if (mipv6_proxy_nd(home_addr, ifindex, -+ flags & MIPV6_BU_F_LLADDR) != 0) { -+ DEBUG(DBG_ERROR, "mipv6_proxy_nd failed!"); -+ mipv6_del_tnl_to_mn(coa, our_addr, home_addr); -+ return -2; -+ } -+ return 0; -+} -+ -+static void ha_proxy_del(struct in6_addr *home_addr, struct mipv6_bce *entry) -+{ -+ if (mipv6_proxy_nd_rem(&entry->home_addr, entry->ifindex, -+ entry->flags & MIPV6_BU_F_LLADDR) == 0) { -+ DEBUG(DBG_INFO, "proxy_nd succ"); -+ } else { -+ DEBUG(DBG_INFO, "proxy_nd fail"); -+ } -+ mipv6_del_tnl_to_mn(&entry->coa, &entry->our_addr, home_addr); -+} -+ -+static void bc_home_add(int ifindex, -+ struct in6_addr *daddr, struct in6_addr *haddr, -+ struct in6_addr *coa, struct in6_addr *rep_coa, -+ __u32 lifetime, __u16 sequence, __u8 flags, -+ __u8 *k_bu) -+{ -+ struct inet6_ifaddr *ifp = NULL; -+ __u8 ba_status = SUCCESS; -+ -+ DEBUG_FUNC(); -+ -+ ifp = is_on_link_ipv6_address(haddr, daddr); -+ -+ if (ifp == NULL) { -+ ba_status = NOT_HOME_SUBNET; -+ } else if (((ipv6_addr_type(haddr) & IPV6_ADDR_SITELOCAL) || -+ (ipv6_addr_type(coa) & IPV6_ADDR_SITELOCAL)) -+ && !mipv6_ha_tunnel_sitelocal) { -+ /* Site-local home or care-of addresses are not -+ accepted by default */ -+ ba_status = ADMINISTRATIVELY_PROHIBITED; -+ } else { -+ int ret; -+ -+ ifindex = ifp->idev->dev->ifindex; -+ -+ if ((ret = mipv6_dad_start(ifp, ifindex, daddr, -+ haddr, coa, rep_coa, lifetime, -+ sequence, flags)) < 0) { -+ /* An error occurred */ -+ ba_status = -ret; -+ } else if (ret) { -+ /* DAD is needed to be performed. */ -+ in6_ifa_put(ifp); -+ return; -+ } -+ } -+ -+ mipv6_bu_finish(ifp, ifindex, ba_status, daddr, haddr, coa, -+ rep_coa, lifetime, sequence, flags, k_bu); -+ if (ifp) -+ in6_ifa_put(ifp); -+} -+ -+static void bc_home_delete(struct in6_addr *daddr, struct in6_addr *haddr, -+ struct in6_addr *coa, struct in6_addr *rep_coa, -+ __u16 sequence, __u8 flags, __u8 *k_bu) -+{ -+ __u8 status = SUCCESS; -+ struct mipv6_bce bce; -+ -+ /* Primary Care-of Address Deregistration */ -+ if (mipv6_bcache_get(haddr, daddr, &bce) < 0) { -+ DEBUG(DBG_INFO, "entry is not in cache"); -+ status = NOT_HA_FOR_MN; -+ } else { -+ ha_proxy_del(&bce.home_addr, &bce); -+ mipv6_bcache_delete(haddr, daddr, HOME_REGISTRATION); -+ } -+ mipv6_send_ba(daddr, haddr, coa, rep_coa, status, sequence, 0, k_bu); -+} -+ -+extern int mipv6_ra_rcv_ptr(struct sk_buff *skb, struct icmp6hdr *msg); -+ -+ -+static int -+mipv6_ha_tnl_xmit_stats_hook(struct ip6_tnl *t, struct sk_buff *skb) -+{ -+ DEBUG_FUNC(); -+ if (is_mip6_tnl(t)) -+ MIPV6_INC_STATS(n_encapsulations); -+ return IP6_TNL_ACCEPT; -+} -+ -+static struct ip6_tnl_hook_ops mipv6_ha_tnl_xmit_stats_ops = { -+ {NULL, NULL}, -+ IP6_TNL_PRE_ENCAP, -+ IP6_TNL_PRI_LAST, -+ mipv6_ha_tnl_xmit_stats_hook -+}; -+ -+static int -+mipv6_ha_tnl_rcv_stats_hook(struct ip6_tnl *t, struct sk_buff *skb) -+{ -+ DEBUG_FUNC(); -+ if (is_mip6_tnl(t)) -+ MIPV6_INC_STATS(n_decapsulations); -+ return IP6_TNL_ACCEPT; -+} -+ -+static struct ip6_tnl_hook_ops mipv6_ha_tnl_rcv_stats_ops = { -+ {NULL, NULL}, -+ IP6_TNL_PRE_DECAP, -+ IP6_TNL_PRI_LAST, -+ mipv6_ha_tnl_rcv_stats_hook -+}; -+ -+static struct mip6_func old; -+ -+int __init mipv6_ha_init(void) -+{ -+ DEBUG_FUNC(); -+ -+#ifdef CONFIG_SYSCTL -+ if (!(mipv6_ha_sysctl_header = -+ register_sysctl_table(mipv6_ha_sysctl.mipv6_root_table, 0))) -+ printk(KERN_ERR "Failed to register sysctl handlers!"); -+#endif -+ memcpy(&old, &mip6_fn, sizeof(struct mip6_func)); -+ mip6_fn.bce_home_add = bc_home_add; -+ mip6_fn.bce_home_del = bc_home_delete; -+ mip6_fn.proxy_del = ha_proxy_del; -+ mip6_fn.proxy_create = ha_proxy_create; -+ /* register packet interception hooks */ -+ ip6ip6_tnl_register_hook(&mipv6_ha_tnl_xmit_stats_ops); -+ ip6ip6_tnl_register_hook(&mipv6_ha_tnl_rcv_stats_ops); -+ return 0; -+} -+ -+void __exit mipv6_ha_exit(void) -+{ -+ DEBUG_FUNC(); -+ -+#ifdef CONFIG_SYSCTL -+ unregister_sysctl_table(mipv6_ha_sysctl_header); -+#endif -+ -+ /* remove packet interception hooks */ -+ ip6ip6_tnl_unregister_hook(&mipv6_ha_tnl_rcv_stats_ops); -+ ip6ip6_tnl_unregister_hook(&mipv6_ha_tnl_xmit_stats_ops); -+ -+ mip6_fn.bce_home_add = old.bce_home_add; -+ mip6_fn.bce_home_del = old.bce_home_del; -+ mip6_fn.proxy_del = old.proxy_del; -+ mip6_fn.proxy_create = old.proxy_create; -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/ha.h linux-2.4.25/net/ipv6/mobile_ip6/ha.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/ha.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/ha.h 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,39 @@ -+/* -+ * MIPL Mobile IPv6 Home Agent header file -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _HA_H -+#define _HA_H -+ -+int mipv6_ha_init(void); -+void mipv6_ha_exit(void); -+ -+int mipv6_dad_start(struct inet6_ifaddr *ifp, int ifindex, -+ struct in6_addr *daddr, struct in6_addr *haddr, -+ struct in6_addr *coa, struct in6_addr *rep_coa, -+ __u32 ba_lifetime, __u16 sequence, __u8 flags); -+ -+void mipv6_bu_finish(struct inet6_ifaddr *ifp, int ifindex, -+ __u8 ba_status, struct in6_addr *daddr, -+ struct in6_addr *haddr, struct in6_addr *coa, -+ struct in6_addr *rep_coa, __u32 ba_lifetime, -+ __u16 sequence, __u8 flags, __u8 *k_bu); -+ -+ -+static __inline__ void mipv6_generate_ll_addr(struct in6_addr *ll_addr, -+ struct in6_addr *addr) -+{ -+ ll_addr->s6_addr32[0] = htonl(0xfe800000); -+ ll_addr->s6_addr32[1] = 0; -+ ll_addr->s6_addr32[2] = addr->s6_addr32[2]; -+ ll_addr->s6_addr32[3] = addr->s6_addr32[3]; -+} -+ -+#endif -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/halist.c linux-2.4.25/net/ipv6/mobile_ip6/halist.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/halist.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/halist.c 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,507 @@ -+/* -+ * Home Agents List -+ * -+ * Authors: -+ * Antti Tuominen -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ */ -+ -+#define PREF_BASE 0xffff /* MAX value for u16 field in RA */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "hashlist.h" -+#include "util.h" -+#include "debug.h" -+ -+struct mipv6_halist { -+ struct hashlist *entries; -+ struct timer_list expire_timer; -+}; -+ -+static rwlock_t home_agents_lock = RW_LOCK_UNLOCKED; -+ -+static struct mipv6_halist home_agents; -+ -+struct mipv6_halist_entry { -+ struct hashlist_entry e; -+ int ifindex; /* Link identifier */ -+ struct in6_addr link_local_addr; /* HA's link-local address */ -+ struct in6_addr global_addr; /* HA's Global address */ -+ int plen; -+ long preference; /* The preference for this HA */ -+ unsigned long expire; /* expiration time (jiffies) */ -+}; -+ -+static inline void mipv6_ha_ac_add(struct in6_addr *ll_addr, int ifindex, -+ struct in6_addr *glob_addr, int plen) -+{ -+ struct net_device *dev; -+ -+ if ((dev = __dev_get_by_index(ifindex)) && ipv6_chk_addr(ll_addr, dev)) { -+ struct in6_addr addr; -+ mipv6_ha_anycast(&addr, glob_addr, plen); -+ ipv6_dev_ac_inc(dev, &addr); -+ } -+} -+ -+static inline void mipv6_ha_ac_del(struct in6_addr *ll_addr, int ifindex, -+ struct in6_addr *glob_addr, int plen) -+{ -+ struct net_device *dev; -+ -+ if ((dev = __dev_get_by_index(ifindex)) && ipv6_chk_addr(ll_addr, dev)) { -+ struct in6_addr addr; -+ mipv6_ha_anycast(&addr, glob_addr, plen); -+ ipv6_dev_ac_dec(dev, &addr); -+ } -+} -+ -+struct preflist_iterator_args { -+ int count; -+ int requested; -+ int ifindex; -+ struct in6_addr *list; -+}; -+ -+static int preflist_iterator(void *data, void *args, -+ unsigned long *pref) -+{ -+ struct preflist_iterator_args *state = -+ (struct preflist_iterator_args *)args; -+ struct mipv6_halist_entry *entry = -+ (struct mipv6_halist_entry *)data; -+ struct in6_addr *newaddr = -+ (struct in6_addr *)state->list + state->count; -+ -+ if (state->count >= state->requested) -+ return ITERATOR_STOP; -+ -+ if (time_after(jiffies, entry->expire)) { -+ if (!ipv6_addr_any(&entry->link_local_addr)) { -+ mipv6_ha_ac_del(&entry->link_local_addr, -+ entry->ifindex, -+ &entry->global_addr, entry->plen); -+ } -+ DEBUG(DBG_INFO, "preflist_iterator: Deleting entry with address %x:%x:%x:%x:%x:%x:%x:%x to list", NIPV6ADDR(&entry->global_addr)); -+ return ITERATOR_DELETE_ENTRY; -+ } -+ if (state->ifindex != entry->ifindex) -+ return ITERATOR_CONT; -+ -+ ipv6_addr_copy(newaddr, &entry->global_addr); -+ DEBUG(DBG_INFO, "preflist_iterator: adding new entry with address %x:%x:%x:%x:%x:%x:%x:%x to list", NIPV6ADDR(&entry->global_addr)); -+ state->count++; -+ -+ return ITERATOR_CONT; -+} -+ -+static int gc_iterator(void *data, void *args, -+ unsigned long *pref) -+{ -+ struct mipv6_halist_entry *entry = -+ (struct mipv6_halist_entry *)data; -+ -+ int *type = (int *)args; -+ -+ if (*type == 1 || time_after(jiffies, entry->expire)) { -+ if (!ipv6_addr_any(&entry->link_local_addr)) { -+ mipv6_ha_ac_del(&entry->link_local_addr, -+ entry->ifindex, -+ &entry->global_addr, entry->plen); -+ } -+ return ITERATOR_DELETE_ENTRY; -+ } -+ -+ return ITERATOR_CONT; -+} -+ -+static int mipv6_halist_gc(int type) -+{ -+ DEBUG_FUNC(); -+ hashlist_iterate(home_agents.entries, &type, gc_iterator); -+ return 0; -+} -+ -+static void mipv6_halist_expire(unsigned long dummy) -+{ -+ DEBUG_FUNC(); -+ -+ write_lock(&home_agents_lock); -+ mipv6_halist_gc(0); -+ write_unlock(&home_agents_lock); -+} -+ -+ -+static struct mipv6_halist_entry *mipv6_halist_new_entry(void) -+{ -+ struct mipv6_halist_entry *entry; -+ -+ DEBUG_FUNC(); -+ -+ entry = hashlist_alloc(home_agents.entries, SLAB_ATOMIC); -+ -+ return entry; -+} -+ -+ -+ -+/** -+ * mipv6_halist_add - Add new home agent to the Home Agents List -+ * @ifindex: interface identifier -+ * @glob_addr: home agent's global address -+ * @ll_addr: home agent's link-local address -+ * @pref: relative preference for this home agent -+ * @lifetime: lifetime for the entry -+ * -+ * Adds new home agent to the Home Agents List. The list is interface -+ * specific and @ifindex tells through which interface the home agent -+ * was heard. Returns zero on success and negative on failure. -+ **/ -+ -+int mipv6_halist_add(int ifindex, struct in6_addr *glob_addr, int plen, -+ struct in6_addr *ll_addr, unsigned int pref, __u32 lifetime) -+{ -+ int update = 0, ret = 0; -+ unsigned int mpref; -+ struct mipv6_halist_entry *entry = NULL; -+ -+ DEBUG_FUNC(); -+ -+ write_lock(&home_agents_lock); -+ -+ if (glob_addr == NULL || lifetime <= 0) { -+ DEBUG(DBG_WARNING, "invalid arguments"); -+ ret = -EINVAL; -+ goto out; -+ } -+ mpref = PREF_BASE - pref; -+ if ((entry = (struct mipv6_halist_entry *) -+ hashlist_get(home_agents.entries, glob_addr)) != NULL) { -+ if (entry->ifindex == ifindex) { -+ DEBUG(DBG_DATADUMP, "updating old entry with address %x:%x:%x:%x:%x:%x:%x:%x", NIPV6ADDR(glob_addr)); -+ update = 1; -+ } else { -+ DEBUG(DBG_INFO, "halist_add : adding new entry with address %x:%x:%x:%x:%x:%x:%x:%x", NIPV6ADDR(glob_addr)); -+ update = 0; -+ } -+ } -+ if (update) { -+ entry->expire = jiffies + lifetime * HZ; -+ if (entry->preference != mpref) { -+ entry->preference = mpref; -+ ret = hashlist_reposition(home_agents.entries, -+ (void *)entry, mpref); -+ } -+ } else { -+ entry = mipv6_halist_new_entry(); -+ if (entry == NULL) { -+ DEBUG(DBG_INFO, "list full"); -+ ret = -ENOMEM; -+ goto out; -+ } -+ entry->ifindex = ifindex; -+ if (ll_addr) { -+ ipv6_addr_copy(&entry->link_local_addr, ll_addr); -+ mipv6_ha_ac_add(ll_addr, ifindex, glob_addr, plen); -+ } else -+ ipv6_addr_set(&entry->link_local_addr, 0, 0, 0, 0); -+ -+ ipv6_addr_copy(&entry->global_addr, glob_addr); -+ entry->plen = plen; -+ entry->preference = mpref; -+ entry->expire = jiffies + lifetime * HZ; -+ ret = hashlist_add(home_agents.entries, glob_addr, mpref, -+ entry); -+ } -+out: -+ write_unlock(&home_agents_lock); -+ return ret; -+} -+ -+/** -+ * mipv6_halist_delete - delete home agent from Home Agents List -+ * @glob_addr: home agent's global address -+ * -+ * Deletes entry for home agent @glob_addr from the Home Agent List. -+ **/ -+int mipv6_halist_delete(struct in6_addr *glob_addr) -+{ -+ struct hashlist_entry *e; -+ struct mipv6_halist_entry *entry; -+ DEBUG_FUNC(); -+ -+ if (glob_addr == NULL) { -+ DEBUG(DBG_WARNING, "invalid glob addr"); -+ return -EINVAL; -+ } -+ write_lock(&home_agents_lock); -+ if ((e = hashlist_get(home_agents.entries, glob_addr)) == NULL) { -+ write_unlock(&home_agents_lock); -+ return -ENOENT; -+ } -+ hashlist_delete(home_agents.entries, e); -+ entry = (struct mipv6_halist_entry *)e; -+ if (!ipv6_addr_any(&entry->link_local_addr)) { -+ mipv6_ha_ac_del(&entry->link_local_addr, entry->ifindex, -+ &entry->global_addr, entry->plen); -+ } -+ hashlist_free(home_agents.entries, e); -+ write_unlock(&home_agents_lock); -+ return 0; -+} -+ -+/** -+ * mipv6_ha_get_pref_list - Get list of preferred home agents -+ * @ifindex: interface identifier -+ * @addrs: pointer to a buffer to store the list -+ * @max: maximum number of home agents to return -+ * -+ * Creates a list of @max preferred (or all known if less than @max) -+ * home agents. Home Agents List is interface specific so you must -+ * supply @ifindex. Stores list in addrs and returns number of home -+ * agents stored. On failure, returns a negative value. -+ **/ -+int mipv6_ha_get_pref_list(int ifindex, struct in6_addr **addrs, int max) -+{ -+ struct preflist_iterator_args args; -+ -+ DEBUG_FUNC(); -+ if (max <= 0) { -+ *addrs = NULL; -+ return 0; -+ } -+ -+ args.count = 0; -+ args.requested = max; -+ args.ifindex = ifindex; -+ args.list = kmalloc(max * sizeof(struct in6_addr), GFP_ATOMIC); -+ -+ if (args.list == NULL) return -ENOMEM; -+ -+ read_lock(&home_agents_lock); -+ hashlist_iterate(home_agents.entries, &args, preflist_iterator); -+ read_unlock(&home_agents_lock); -+ -+ if (args.count >= 0) { -+ *addrs = args.list; -+ } else { -+ kfree(args.list); -+ *addrs = NULL; -+ } -+ -+ return args.count; -+} -+ -+struct getaddr_iterator_args { -+ struct net_device *dev; -+ struct in6_addr *addr; -+}; -+ -+static int getaddr_iterator(void *data, void *args, -+ unsigned long *pref) -+{ -+ struct mipv6_halist_entry *entry = -+ (struct mipv6_halist_entry *)data; -+ struct getaddr_iterator_args *state = -+ (struct getaddr_iterator_args *)args; -+ -+ if (entry->ifindex != state->dev->ifindex) -+ return ITERATOR_CONT; -+ -+ if (ipv6_chk_addr(&entry->global_addr, state->dev)) { -+ ipv6_addr_copy(state->addr, &entry->global_addr); -+ return ITERATOR_STOP; -+ } -+ return ITERATOR_CONT; -+} -+ -+/* -+ * Get Home Agent Address for given interface. If node is not serving -+ * as a HA for this interface returns negative error value. -+ */ -+int mipv6_ha_get_addr(int ifindex, struct in6_addr *addr) -+{ -+ struct getaddr_iterator_args args; -+ struct net_device *dev; -+ -+ if (ifindex <= 0) -+ return -EINVAL; -+ -+ if ((dev = dev_get_by_index(ifindex)) == NULL) -+ return -ENODEV; -+ -+ memset(addr, 0, sizeof(struct in6_addr)); -+ args.dev = dev; -+ args.addr = addr; -+ read_lock(&home_agents_lock); -+ hashlist_iterate(home_agents.entries, &args, getaddr_iterator); -+ read_unlock(&home_agents_lock); -+ dev_put(dev); -+ -+ if (ipv6_addr_any(addr)) -+ return -ENOENT; -+ -+ return 0; -+} -+ -+#define HALIST_INFO_LEN 81 -+ -+struct procinfo_iterator_args { -+ char *buffer; -+ int offset; -+ int length; -+ int skip; -+ int len; -+}; -+ -+static int procinfo_iterator(void *data, void *args, -+ unsigned long *pref) -+{ -+ struct procinfo_iterator_args *arg = -+ (struct procinfo_iterator_args *)args; -+ struct mipv6_halist_entry *entry = -+ (struct mipv6_halist_entry *)data; -+ unsigned long int expire; -+ -+ DEBUG_FUNC(); -+ -+ if (entry == NULL) return ITERATOR_ERR; -+ -+ if (time_after(jiffies, entry->expire)) { -+ if (!ipv6_addr_any(&entry->link_local_addr)) { -+ mipv6_ha_ac_del(&entry->link_local_addr, -+ entry->ifindex, -+ &entry->global_addr, entry->plen); -+ } -+ return ITERATOR_DELETE_ENTRY; -+ } -+ if (arg->skip < arg->offset / HALIST_INFO_LEN) { -+ arg->skip++; -+ return ITERATOR_CONT; -+ } -+ -+ if (arg->len >= arg->length) -+ return ITERATOR_CONT; -+ -+ expire = (entry->expire - jiffies) / HZ; -+ -+ arg->len += sprintf(arg->buffer + arg->len, -+ "%02d %08x%08x%08x%08x %08x%08x%08x%08x %05ld %05ld\n", -+ entry->ifindex, -+ ntohl(entry->global_addr.s6_addr32[0]), -+ ntohl(entry->global_addr.s6_addr32[1]), -+ ntohl(entry->global_addr.s6_addr32[2]), -+ ntohl(entry->global_addr.s6_addr32[3]), -+ ntohl(entry->link_local_addr.s6_addr32[0]), -+ ntohl(entry->link_local_addr.s6_addr32[1]), -+ ntohl(entry->link_local_addr.s6_addr32[2]), -+ ntohl(entry->link_local_addr.s6_addr32[3]), -+ -(entry->preference - PREF_BASE), expire); -+ -+ return ITERATOR_CONT; -+} -+ -+static int halist_proc_info(char *buffer, char **start, off_t offset, -+ int length) -+{ -+ struct procinfo_iterator_args args; -+ -+ DEBUG_FUNC(); -+ -+ args.buffer = buffer; -+ args.offset = offset; -+ args.length = length; -+ args.skip = 0; -+ args.len = 0; -+ -+ read_lock_bh(&home_agents_lock); -+ hashlist_iterate(home_agents.entries, &args, procinfo_iterator); -+ read_unlock_bh(&home_agents_lock); -+ -+ *start = buffer; -+ if (offset) -+ *start += offset % HALIST_INFO_LEN; -+ -+ args.len -= offset % HALIST_INFO_LEN; -+ -+ if (args.len > length) -+ args.len = length; -+ if (args.len < 0) -+ args.len = 0; -+ -+ return args.len; -+} -+ -+static int halist_compare(void *data, void *hashkey) -+{ -+ struct mipv6_halist_entry *e = (struct mipv6_halist_entry *)data; -+ struct in6_addr *key = (struct in6_addr *)hashkey; -+ -+ return ipv6_addr_cmp(&e->global_addr, key); -+} -+ -+static __u32 halist_hash(void *hashkey) -+{ -+ struct in6_addr *key = (struct in6_addr *)hashkey; -+ __u32 hash; -+ -+ hash = key->s6_addr32[0] ^ -+ key->s6_addr32[1] ^ -+ key->s6_addr32[2] ^ -+ key->s6_addr32[3]; -+ -+ return hash; -+} -+ -+int __init mipv6_halist_init(__u32 size) -+{ -+ DEBUG_FUNC(); -+ -+ if (size <= 0) { -+ DEBUG(DBG_ERROR, "size must be at least 1"); -+ return -EINVAL; -+ } -+ init_timer(&home_agents.expire_timer); -+ home_agents.expire_timer.data = 0; -+ home_agents.expire_timer.function = mipv6_halist_expire; -+ home_agents_lock = RW_LOCK_UNLOCKED; -+ -+ home_agents.entries = hashlist_create(16, size, sizeof(struct mipv6_halist_entry), -+ "mip6_halist", NULL, NULL, -+ halist_compare, halist_hash); -+ -+ if (home_agents.entries == NULL) { -+ DEBUG(DBG_ERROR, "Failed to initialize hashlist"); -+ return -ENOMEM; -+ } -+ -+ proc_net_create("mip6_home_agents", 0, halist_proc_info); -+ DEBUG(DBG_INFO, "Home Agents List initialized"); -+ return 0; -+} -+ -+void __exit mipv6_halist_exit(void) -+{ -+ DEBUG_FUNC(); -+ proc_net_remove("mip6_home_agents"); -+ write_lock_bh(&home_agents_lock); -+ DEBUG(DBG_INFO, "Stopping the halist timer"); -+ del_timer(&home_agents.expire_timer); -+ mipv6_halist_gc(1); -+ write_unlock_bh(&home_agents_lock); -+ hashlist_destroy(home_agents.entries); -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/halist.h linux-2.4.25/net/ipv6/mobile_ip6/halist.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/halist.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/halist.h 2004-06-26 11:29:30.000000000 +0100 -@@ -0,0 +1,28 @@ -+/* -+ * MIPL Mobile IPv6 Home Agents List header file -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _HALIST_H -+#define _HALIST_H -+ -+int mipv6_halist_init(__u32 size); -+ -+void mipv6_halist_exit(void); -+ -+int mipv6_halist_add(int ifindex, struct in6_addr *glob_addr, int plen, -+ struct in6_addr *ll_addr, unsigned int pref, __u32 lifetime); -+ -+int mipv6_halist_delete(struct in6_addr *glob_addr); -+ -+int mipv6_ha_get_pref_list(int ifindex, struct in6_addr **addrs, int max); -+ -+int mipv6_ha_get_addr(int ifindex, struct in6_addr *addr); -+ -+#endif /* _HALIST_H */ -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/hashlist.c linux-2.4.25/net/ipv6/mobile_ip6/hashlist.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/hashlist.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/hashlist.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,351 @@ -+/* -+ * Generic hashtable with chaining. Supports secodary sort order -+ * with doubly linked-list. -+ * -+ * Authors: -+ * Sami Kivisaari -+ * Antti Tuominen -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 "hashlist.h" -+#include "debug.h" -+ -+struct hashlist { -+ int count; /* entry count */ -+ int maxcount; /* max entries */ -+ __u32 bucketnum; /* hash buckets */ -+ -+ kmem_cache_t *kmem; -+ -+ struct list_head *hashtable; -+ struct list_head sortedlist; -+ -+ int (*compare)(void *data, void *hashkey); -+ __u32 (*hash_function)(void *hashkey); -+}; -+ -+/** -+ * hashlist_create - Create new hashlist -+ * @bucketnum: number of hash buckets -+ * @maxentries: maximum number of entries (0 = no limit) -+ * @size: entry size in bytes -+ * @name: name for kmem_cache_t -+ * @ctor: kmem_cache_t constructor -+ * @dtor: kmem_cache_t destructor -+ * @compare: compare function for key -+ * @hash_function: hash function -+ * -+ * Creates a hashlist structure with @max_entries entries of @size -+ * bytes. User must supply @hash_function and @compare function for -+ * the hashlist. User can also supply @ctor and @dtor for kmem_cache. -+ **/ -+struct hashlist *hashlist_create(int bucketnum, int max_entries, size_t size, -+ char *name, -+ void (*ctor)(void *, kmem_cache_t *, unsigned long), -+ void (*dtor)(void *, kmem_cache_t *, unsigned long), -+ int (*compare)(void *data, void *hashkey), -+ __u32 (*hash_function)(void *hashkey)) -+{ -+ int i; -+ struct hashlist *hl; -+ -+ if (!compare || !hash_function) -+ goto hlfailed; -+ -+ hl = kmalloc(sizeof(struct hashlist), GFP_ATOMIC); -+ if (!hl) goto hlfailed; -+ -+ hl->kmem = kmem_cache_create(name, size, 0, 0, ctor, dtor); -+ if (!hl->kmem) goto poolfailed; -+ -+ hl->hashtable = kmalloc( -+ sizeof(struct list_head) * bucketnum, GFP_ATOMIC); -+ if (!hl->hashtable) goto hashfailed; -+ -+ for (i = 0; i < bucketnum; i++) -+ INIT_LIST_HEAD(&hl->hashtable[i]); -+ -+ INIT_LIST_HEAD(&hl->sortedlist); -+ -+ hl->maxcount = max_entries; -+ hl->count = 0; -+ hl->bucketnum = bucketnum; -+ hl->compare = compare; -+ hl->hash_function = hash_function; -+ -+ return hl; -+ -+hashfailed: -+ kmem_cache_destroy(hl->kmem); -+ hl->kmem = NULL; -+ -+poolfailed: -+ kfree(hl); -+ -+hlfailed: -+ DEBUG(DBG_ERROR, "could not create hashlist"); -+ -+ return NULL; -+} -+ -+/** -+ * hashlist_destroy - Destroy hashlist -+ * @hashlist: hashlist to destroy -+ * -+ * Frees all memory allocated for a hashlist. -+ **/ -+void hashlist_destroy(struct hashlist *hashlist) -+{ -+ DEBUG_FUNC(); -+ -+ if (hashlist == NULL) return; -+ -+ if (hashlist->hashtable) { -+ kfree(hashlist->hashtable); -+ hashlist->hashtable = NULL; -+ } -+ -+ if (hashlist->kmem) { -+ kmem_cache_destroy(hashlist->kmem); -+ hashlist->kmem = NULL; -+ } -+ -+ kfree(hashlist); -+ -+ return; -+} -+ -+/* -+ * Insert a chain of entries to hashlist into correct order. The -+ * entries are assumed to have valid hashkeys. We use time_after_eq -+ * for comparing, since it handles wrap-around correctly, and the -+ * sortkey is usually jiffies. -+ */ -+static void sorted_insert(struct list_head *lh, struct hashlist_entry *he) -+{ -+ struct list_head *p; -+ struct hashlist_entry *hlp = NULL; -+ unsigned long sortkey = he->sortkey; -+ -+ if (list_empty(lh)) { -+ list_add(&he->sorted, lh); -+ return; -+ } -+ -+ list_for_each(p, lh) { -+ hlp = list_entry(p, typeof(*hlp), sorted); -+ if (time_after_eq(hlp->sortkey, sortkey)) { -+ list_add(&he->sorted, hlp->sorted.prev); -+ return; -+ } -+ } -+ list_add(&he->sorted, &hlp->sorted); -+} -+ -+/** -+ * hashlist_iterate - Apply function for all elements in a hash list -+ * @hashlist: pointer to hashlist -+ * @args: data to pass to the function -+ * @func: pointer to a function -+ * -+ * Apply arbitrary function @func to all elements in a hash list. -+ * @func must be a pointer to a function with the following prototype: -+ * int func(void *entry, void *arg, struct in6_addr *hashkey, unsigned -+ * long *sortkey). Function must return %ITERATOR_STOP, -+ * %ITERATOR_CONT or %ITERATOR_DELETE_ENTRY. %ITERATOR_STOP stops -+ * iterator and returns last return value from the function. -+ * %ITERATOR_CONT continues with iteration. %ITERATOR_DELETE_ENTRY -+ * deletes current entry from the hashlist. If function changes -+ * hashlist element's sortkey, iterator automatically schedules -+ * element to be reinserted after all elements have been processed. -+ */ -+int hashlist_iterate( -+ struct hashlist *hashlist, void *args, -+ hashlist_iterator_t func) -+{ -+ int res = ITERATOR_CONT; -+ unsigned long skey; -+ struct list_head *p, *n, repos; -+ struct hashlist_entry *he; -+ -+ DEBUG_FUNC(); -+ INIT_LIST_HEAD(&repos); -+ -+ list_for_each_safe(p, n, &hashlist->sortedlist) { -+ he = list_entry(p, typeof(*he), sorted); -+ if (res == ITERATOR_STOP) -+ break; -+ skey = he->sortkey; -+ res = func(he, args, &he->sortkey); -+ if (res == ITERATOR_DELETE_ENTRY) { -+ hashlist_delete(hashlist, he); -+ hashlist_free(hashlist, he); -+ } else if (skey != he->sortkey) { -+ /* iterator changed the sortkey, schedule for -+ * repositioning */ -+ list_move(&he->sorted, &repos); -+ } -+ } -+ list_for_each_safe(p, n, &repos) { -+ he = list_entry(p, typeof(*he), sorted); -+ sorted_insert(&hashlist->sortedlist, he); -+ } -+ return res; -+} -+ -+/** -+ * hashlist_alloc - Allocate memory for a hashlist entry -+ * @hashlist: hashlist for allocated entry -+ * @size: size of entry in bytes -+ * -+ * Allocates @size bytes memory from @hashlist->kmem. -+ **/ -+void *hashlist_alloc(struct hashlist *hashlist, int type) -+{ -+ if (hashlist == NULL) return NULL; -+ return kmem_cache_alloc(hashlist->kmem, type); -+} -+ -+/** -+ * hashlist_free - Free hashlist entry -+ * @hashlist: hashlist where @he is -+ * @he: entry to free -+ * -+ * Frees an allocated hashlist entry. -+ **/ -+void hashlist_free(struct hashlist *hashlist, struct hashlist_entry *he) -+{ -+ kmem_cache_free(hashlist->kmem, he); -+} -+ -+/** -+ * hashlist_add - Add element to hashlist -+ * @hashlist: pointer to hashlist -+ * @hashkey: hashkey for the element -+ * @sortkey: key for sorting -+ * @data: element data -+ * -+ * Add element to hashlist. Hashlist is also sorted in a linked list -+ * by @sortkey. -+ */ -+int hashlist_add(struct hashlist *hashlist, void *hashkey, -+ unsigned long sortkey, void *entry) -+{ -+ struct hashlist_entry *he = (struct hashlist_entry *)entry; -+ unsigned int hash; -+ -+ if (hashlist->count >= hashlist->maxcount) -+ return -1; -+ -+ hashlist->count++; -+ -+ /* link the entry to sorted order */ -+ he->sortkey = sortkey; -+ sorted_insert(&hashlist->sortedlist, he); -+ -+ /* hash the entry */ -+ hash = hashlist->hash_function(hashkey) % hashlist->bucketnum; -+ list_add(&he->hashlist, &hashlist->hashtable[hash]); -+ -+ return 0; -+} -+ -+/** -+ * hashlist_get_ex - Get element from hashlist -+ * @hashlist: hashlist -+ * @hashkey: hashkey of the desired entry -+ * -+ * Lookup entry with @hashkey from the hash table using @compare -+ * function for entry comparison. Returns entry on success, otherwise -+ * %NULL. -+ **/ -+struct hashlist_entry *hashlist_get_ex( -+ struct hashlist *hashlist, void *hashkey, -+ int (*compare)(void *data, void *hashkey)) -+{ -+ struct list_head *p, *bkt; -+ __u32 hash; -+ -+ hash = hashlist->hash_function(hashkey) % hashlist->bucketnum; -+ bkt = &hashlist->hashtable[hash]; -+ -+ /* scan the entries within the same hashbucket */ -+ list_for_each(p, bkt) { -+ struct hashlist_entry *he = list_entry(p, typeof(*he), -+ hashlist); -+ if (compare(he, hashkey) == 0) -+ return he; -+ } -+ -+ return NULL; -+} -+ -+/** -+ * hashlist_get - Get element from hashlist -+ * @hashlist: hashlist -+ * @hashkey: hashkey of the desired entry -+ * -+ * Lookup entry with @hashkey from the hash table. Returns entry on -+ * success, otherwise %NULL. -+ **/ -+struct hashlist_entry *hashlist_get(struct hashlist *hashlist, void *hashkey) -+{ -+ return hashlist_get_ex(hashlist, hashkey, hashlist->compare); -+} -+ -+/** -+ * hashlist_reposition - set entry to new position in the list -+ * @hashlist: hashlist -+ * @he: entry to reposition -+ * @sortkey: new sortkey of the entry -+ * -+ * If secondary order sortkey changes, entry must be repositioned in -+ * the sorted list. -+ **/ -+int hashlist_reposition(struct hashlist *hashlist, struct hashlist_entry *he, -+ unsigned long sortkey) -+{ -+ list_del(&he->sorted); -+ he->sortkey = sortkey; -+ sorted_insert(&hashlist->sortedlist, he); -+ -+ return 0; -+} -+ -+/** -+ * hashlist_delete - Delete entry from hashlist -+ * @hashlist: hashlist where entry is -+ * @he: entry to delete -+ * -+ * Deletes an entry from the hashlist and sorted list. -+ **/ -+void hashlist_delete(struct hashlist *hashlist, -+ struct hashlist_entry *he) -+{ -+ list_del_init(&he->hashlist); -+ list_del_init(&he->sorted); -+ -+ hashlist->count--; -+} -+ -+/** -+ * hashlist_get_first - Get first item from sorted list -+ * @hashlist: pointer to hashlist -+ * -+ * Returns first item in the secondary sort order. -+ **/ -+void * hashlist_get_first(struct hashlist *hashlist) -+{ -+ if (list_empty(&hashlist->sortedlist)) -+ return NULL; -+ -+ return list_entry(hashlist->sortedlist.next, struct hashlist_entry, sorted); -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/hashlist.h linux-2.4.25/net/ipv6/mobile_ip6/hashlist.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/hashlist.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/hashlist.h 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,63 @@ -+/* -+ * MIPL Mobile IPv6 Hashlist header file -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _HASHLIST_H -+#define _HASHLIST_H -+ -+#define ITERATOR_ERR -1 -+#define ITERATOR_CONT 0 -+#define ITERATOR_STOP 1 -+#define ITERATOR_DELETE_ENTRY 2 -+ -+struct kmem_cache_t; -+ -+struct hashlist_entry { -+ unsigned long sortkey; -+ struct list_head sorted; -+ struct list_head hashlist; -+}; -+ -+struct hashlist * hashlist_create( -+ int bucketnum, int max_entries, size_t size, char *name, -+ void (*ctor)(void *, kmem_cache_t *, unsigned long), -+ void (*dtor)(void *, kmem_cache_t *, unsigned long), -+ int (*compare)(void *data, void *hashkey), -+ __u32 (*hash_function)(void *hashkey)); -+ -+void hashlist_destroy(struct hashlist *hashlist); -+ -+void *hashlist_alloc(struct hashlist *hashlist, int type); -+ -+void hashlist_free(struct hashlist *hashlist, struct hashlist_entry *he); -+ -+struct hashlist_entry *hashlist_get(struct hashlist *hashlist, void *hashkey); -+ -+struct hashlist_entry *hashlist_get_ex( -+ struct hashlist *hashlist, void *hashkey, -+ int (*compare)(void *data, void *hashkey)); -+ -+int hashlist_add(struct hashlist *hashlist, void *hashkey, -+ unsigned long sortkey, void *data); -+ -+void hashlist_delete(struct hashlist *hashlist, struct hashlist_entry *he); -+ -+/* iterator function */ -+typedef int (*hashlist_iterator_t)(void *, void *, unsigned long *); -+ -+int hashlist_iterate(struct hashlist *hashlist, void *args, -+ hashlist_iterator_t func); -+ -+void * hashlist_get_first(struct hashlist *hashlist); -+ -+int hashlist_reposition(struct hashlist *hashlist, struct hashlist_entry *he, -+ unsigned long sortkey); -+ -+#endif -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/hmac.c linux-2.4.25/net/ipv6/mobile_ip6/hmac.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/hmac.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/hmac.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,658 @@ -+/* Authentication algorithms -+ * -+ * Authors: -+ * Alexis Olivereau -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * Changes: -+ * Henrik Petander : Cleaned up unused parts -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "hmac.h" -+#define LROLL(x, s) (((x) << (s)) | ((x) >> (32 - (s)))) -+ -+/* MD5 */ -+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) -+#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) -+#define H(x, y, z) ((x) ^ (y) ^ (z)) -+#define I(x, y, z) ((y) ^ ((x) | ~(z))) -+ -+#define FF(a, b, c, d, m, s, t) { \ -+ (a) += F ((b), (c), (d)) + (m) + (t); \ -+ (a) = LROLL((a), (s)); \ -+ (a) += (b); \ -+ } -+#define GG(a, b, c, d, m, s, t) { \ -+ (a) += G ((b), (c), (d)) + (m) + (t); \ -+ (a) = LROLL((a), (s)); \ -+ (a) += (b); \ -+ } -+#define HH(a, b, c, d, m, s, t) { \ -+ (a) += H ((b), (c), (d)) + (m) + (t); \ -+ (a) = LROLL((a), (s)); \ -+ (a) += (b); \ -+ } -+#define II(a, b, c, d, m, s, t) { \ -+ (a) += I ((b), (c), (d)) + (m) + (t); \ -+ (a) = LROLL((a), (s)); \ -+ (a) += (b); \ -+ } -+ -+#define s11 7 -+#define s12 12 -+#define s13 17 -+#define s14 22 -+#define s21 5 -+#define s22 9 -+#define s23 14 -+#define s24 20 -+#define s31 4 -+#define s32 11 -+#define s33 16 -+#define s34 23 -+#define s41 6 -+#define s42 10 -+#define s43 15 -+#define s44 21 -+ -+/* SHA-1 */ -+#define f(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) -+#define g(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) -+#define h(x, y, z) ((x) ^ (y) ^ (z)) -+ -+#define K1 0x5a827999 -+#define K2 0x6ed9eba1 -+#define K3 0x8f1bbcdc -+#define K4 0xca62c1d6 -+ -+int ah_hmac_md5_init(struct ah_processing *ahp, u_int8_t *key, u_int32_t key_len) -+{ -+ int i; -+ int key_up4; -+ uint32_t ipad = 0x36363636; -+ uint8_t extkey[64]; -+ -+ ahp->key_auth = key; -+ ahp->key_auth_len = key_len; -+ ahp->context = (void *) kmalloc(sizeof(MD5_CTX), GFP_ATOMIC); -+ if (ahp->context == NULL) -+ return -1; -+ md5_init((MD5_CTX *) ahp->context); -+ if ((64 * sizeof(uint8_t)) < ahp->key_auth_len) { -+ printk("buffer overflow!"); -+ return -1; -+ } -+ memcpy(extkey, ahp->key_auth, ahp->key_auth_len); -+ if (ahp->key_auth_len % 4) { -+ memset(extkey + ahp->key_auth_len, 0, -+ 4 - (ahp->key_auth_len % 4)); -+ } -+ key_up4 = ((ahp->key_auth_len + 0x3) & 0xFFFFFFFC) / 4; -+ -+ for (i = 0; i < key_up4; i++) -+ ((uint32_t *) extkey)[i] = ((uint32_t *) extkey)[i] ^ ipad; -+ for (i = key_up4; i < 16; i++) -+ ((uint32_t *) extkey)[i] = ipad; -+ -+ md5_compute((MD5_CTX *) ahp->context, extkey, 64); -+ return 0; -+} -+ -+void ah_hmac_md5_loop(struct ah_processing *ahp, void *str, uint32_t len) -+{ -+ md5_compute((MD5_CTX *) ahp->context, str, len); -+} -+ -+void ah_hmac_md5_result(struct ah_processing *ahp, char *digest) -+{ -+ uint8_t inner[HMAC_MD5_HASH_LEN]; -+ int i; -+ int key_up4; -+ uint32_t opad = 0x5c5c5c5c; -+ uint8_t extkey[64]; -+ -+ md5_final((MD5_CTX *) ahp->context, inner); -+ md5_init((MD5_CTX *) ahp->context); -+ -+ memcpy(extkey, ahp->key_auth, ahp->key_auth_len); -+ if (ahp->key_auth_len % 4) { -+ memset(extkey + ahp->key_auth_len, 0, -+ 4 - (ahp->key_auth_len % 4)); -+ } -+ key_up4 = ((ahp->key_auth_len + 0x3) & 0xFFFFFFFC) / 4; -+ -+ for (i = 0; i < key_up4; i++) -+ ((uint32_t *) extkey)[i] = ((uint32_t *) extkey)[i] ^ opad; -+ for (i = key_up4; i < 16; i++) -+ ((uint32_t *) extkey)[i] = opad; -+ -+ md5_compute((MD5_CTX *) ahp->context, extkey, 64); -+ md5_compute((MD5_CTX *) ahp->context, inner, HMAC_MD5_HASH_LEN); -+ -+ md5_final((MD5_CTX *) ahp->context, digest); -+ -+ kfree(ahp->context); -+} -+ -+int ah_hmac_sha1_init(struct ah_processing *ahp, u_int8_t *key, u_int32_t key_len) -+{ -+ int i; -+ int key_up4; -+ uint32_t ipad = 0x36363636; -+ uint8_t extkey[64]; -+ -+ ahp->key_auth = key; -+ ahp->key_auth_len = key_len; -+ -+ ahp->context = (void *) kmalloc(sizeof(SHA1_CTX), GFP_ATOMIC); -+ //if (ahp->context == NULL) -+ // return -1; -+ -+ sha1_init((SHA1_CTX *) ahp->context); -+ -+ memcpy(extkey, ahp->key_auth, ahp->key_auth_len); -+ if (ahp->key_auth_len % 4) { -+ memset(extkey + ahp->key_auth_len, 0, -+ 4 - (ahp->key_auth_len % 4)); -+ } -+ key_up4 = ((ahp->key_auth_len + 0x3) & 0xFFFFFFFC) / 4; -+ -+ for (i = 0; i < key_up4; i++) -+ ((uint32_t *) extkey)[i] = ((uint32_t *) extkey)[i] ^ ipad; -+ for (i = key_up4; i < 16; i++) -+ ((uint32_t *) extkey)[i] = ipad; -+ -+ sha1_compute((SHA1_CTX *) ahp->context, extkey, 64); -+ return 0; -+} -+ -+void ah_hmac_sha1_loop(struct ah_processing *ahp, void *str, uint32_t len) -+{ -+ if (!ahp) -+ return; -+ sha1_compute((SHA1_CTX *) ahp->context, str, len); -+} -+ -+void ah_hmac_sha1_result(struct ah_processing *ahp, char *digest) -+{ -+ uint8_t inner[HMAC_SHA1_HASH_LEN]; -+ int i; -+ int key_up4; -+ uint32_t opad = 0x5c5c5c5c; -+ uint8_t extkey[64]; -+ -+ if (!ahp) -+ return; -+ sha1_final((SHA1_CTX *) ahp->context, inner); -+ sha1_init((SHA1_CTX *) ahp->context); -+ -+ memcpy(extkey, ahp->key_auth, ahp->key_auth_len); -+ if (ahp->key_auth_len % 4) { -+ memset(extkey + ahp->key_auth_len, 0, -+ 4 - (ahp->key_auth_len % 4)); -+ } -+ key_up4 = ((ahp->key_auth_len + 0x3) & 0xFFFFFFFC) / 4; -+ -+ for (i = 0; i < key_up4; i++) -+ ((uint32_t *) extkey)[i] = ((uint32_t *) extkey)[i] ^ opad; -+ for (i = key_up4; i < 16; i++) -+ ((uint32_t *) extkey)[i] = opad; -+ -+ sha1_compute((SHA1_CTX *) ahp->context, extkey, 64); -+ sha1_compute((SHA1_CTX *) ahp->context, inner, -+ HMAC_SHA1_HASH_LEN); -+ -+ sha1_final((SHA1_CTX *) ahp->context, digest); -+ -+ kfree(ahp->context); -+} -+ -+void md5_init(MD5_CTX * ctx) -+{ -+ ctx->A = 0x67452301; -+ ctx->B = 0xefcdab89; -+ ctx->C = 0x98badcfe; -+ ctx->D = 0x10325476; -+ ctx->buf_cur = ctx->buf; -+ ctx->bitlen[0] = ctx->bitlen[1] = 0; -+ memset(ctx->buf, 0, 64); -+} -+ -+void md5_over_block(MD5_CTX * ctx, uint8_t * data) -+{ -+ uint32_t M[16]; -+ uint32_t a = ctx->A; -+ uint32_t b = ctx->B; -+ uint32_t c = ctx->C; -+ uint32_t d = ctx->D; -+ -+ create_M_blocks(M, data); -+ -+ /* Round 1 */ -+ FF(a, b, c, d, M[0], s11, 0xd76aa478); /* 1 */ -+ FF(d, a, b, c, M[1], s12, 0xe8c7b756); /* 2 */ -+ FF(c, d, a, b, M[2], s13, 0x242070db); /* 3 */ -+ FF(b, c, d, a, M[3], s14, 0xc1bdceee); /* 4 */ -+ FF(a, b, c, d, M[4], s11, 0xf57c0faf); /* 5 */ -+ FF(d, a, b, c, M[5], s12, 0x4787c62a); /* 6 */ -+ FF(c, d, a, b, M[6], s13, 0xa8304613); /* 7 */ -+ FF(b, c, d, a, M[7], s14, 0xfd469501); /* 8 */ -+ FF(a, b, c, d, M[8], s11, 0x698098d8); /* 9 */ -+ FF(d, a, b, c, M[9], s12, 0x8b44f7af); /* 10 */ -+ FF(c, d, a, b, M[10], s13, 0xffff5bb1); /* 11 */ -+ FF(b, c, d, a, M[11], s14, 0x895cd7be); /* 12 */ -+ FF(a, b, c, d, M[12], s11, 0x6b901122); /* 13 */ -+ FF(d, a, b, c, M[13], s12, 0xfd987193); /* 14 */ -+ FF(c, d, a, b, M[14], s13, 0xa679438e); /* 15 */ -+ FF(b, c, d, a, M[15], s14, 0x49b40821); /* 16 */ -+ -+ /* Round 2 */ -+ GG(a, b, c, d, M[1], s21, 0xf61e2562); /* 17 */ -+ GG(d, a, b, c, M[6], s22, 0xc040b340); /* 18 */ -+ GG(c, d, a, b, M[11], s23, 0x265e5a51); /* 19 */ -+ GG(b, c, d, a, M[0], s24, 0xe9b6c7aa); /* 20 */ -+ GG(a, b, c, d, M[5], s21, 0xd62f105d); /* 21 */ -+ GG(d, a, b, c, M[10], s22, 0x02441453); /* 22 */ -+ GG(c, d, a, b, M[15], s23, 0xd8a1e681); /* 23 */ -+ GG(b, c, d, a, M[4], s24, 0xe7d3fbc8); /* 24 */ -+ GG(a, b, c, d, M[9], s21, 0x21e1cde6); /* 25 */ -+ GG(d, a, b, c, M[14], s22, 0xc33707d6); /* 26 */ -+ GG(c, d, a, b, M[3], s23, 0xf4d50d87); /* 27 */ -+ GG(b, c, d, a, M[8], s24, 0x455a14ed); /* 28 */ -+ GG(a, b, c, d, M[13], s21, 0xa9e3e905); /* 29 */ -+ GG(d, a, b, c, M[2], s22, 0xfcefa3f8); /* 30 */ -+ GG(c, d, a, b, M[7], s23, 0x676f02d9); /* 31 */ -+ GG(b, c, d, a, M[12], s24, 0x8d2a4c8a); /* 32 */ -+ -+ /* Round 3 */ -+ HH(a, b, c, d, M[5], s31, 0xfffa3942); /* 33 */ -+ HH(d, a, b, c, M[8], s32, 0x8771f681); /* 34 */ -+ HH(c, d, a, b, M[11], s33, 0x6d9d6122); /* 35 */ -+ HH(b, c, d, a, M[14], s34, 0xfde5380c); /* 36 */ -+ HH(a, b, c, d, M[1], s31, 0xa4beea44); /* 37 */ -+ HH(d, a, b, c, M[4], s32, 0x4bdecfa9); /* 38 */ -+ HH(c, d, a, b, M[7], s33, 0xf6bb4b60); /* 39 */ -+ HH(b, c, d, a, M[10], s34, 0xbebfbc70); /* 40 */ -+ HH(a, b, c, d, M[13], s31, 0x289b7ec6); /* 41 */ -+ HH(d, a, b, c, M[0], s32, 0xeaa127fa); /* 42 */ -+ HH(c, d, a, b, M[3], s33, 0xd4ef3085); /* 43 */ -+ HH(b, c, d, a, M[6], s34, 0x4881d05); /* 44 */ -+ HH(a, b, c, d, M[9], s31, 0xd9d4d039); /* 45 */ -+ HH(d, a, b, c, M[12], s32, 0xe6db99e5); /* 46 */ -+ HH(c, d, a, b, M[15], s33, 0x1fa27cf8); /* 47 */ -+ HH(b, c, d, a, M[2], s34, 0xc4ac5665); /* 48 */ -+ -+ /* Round 4 */ -+ II(a, b, c, d, M[0], s41, 0xf4292244); /* 49 */ -+ II(d, a, b, c, M[7], s42, 0x432aff97); /* 50 */ -+ II(c, d, a, b, M[14], s43, 0xab9423a7); /* 51 */ -+ II(b, c, d, a, M[5], s44, 0xfc93a039); /* 52 */ -+ II(a, b, c, d, M[12], s41, 0x655b59c3); /* 53 */ -+ II(d, a, b, c, M[3], s42, 0x8f0ccc92); /* 54 */ -+ II(c, d, a, b, M[10], s43, 0xffeff47d); /* 55 */ -+ II(b, c, d, a, M[1], s44, 0x85845dd1); /* 56 */ -+ II(a, b, c, d, M[8], s41, 0x6fa87e4f); /* 57 */ -+ II(d, a, b, c, M[15], s42, 0xfe2ce6e0); /* 58 */ -+ II(c, d, a, b, M[6], s43, 0xa3014314); /* 59 */ -+ II(b, c, d, a, M[13], s44, 0x4e0811a1); /* 60 */ -+ II(a, b, c, d, M[4], s41, 0xf7537e82); /* 61 */ -+ II(d, a, b, c, M[11], s42, 0xbd3af235); /* 62 */ -+ II(c, d, a, b, M[2], s43, 0x2ad7d2bb); /* 63 */ -+ II(b, c, d, a, M[9], s44, 0xeb86d391); /* 64 */ -+ -+ ctx->A += a; -+ ctx->B += b; -+ ctx->C += c; -+ ctx->D += d; -+} -+ -+void create_M_blocks(uint32_t * M, uint8_t * data) -+{ -+#ifdef HAVE_LITTLE_ENDIAN -+ memcpy((uint8_t *) M, data, 64); -+#endif /* HAVE_LITTLE_ENDIAN */ -+ -+#ifdef HAVE_BIG_ENDIAN -+ int i; -+ for (i = 0; i < 16; i++, data += 4) { -+ ((uint8_t *) (&M[i]))[0] = data[3]; -+ ((uint8_t *) (&M[i]))[1] = data[2]; -+ ((uint8_t *) (&M[i]))[2] = data[1]; -+ ((uint8_t *) (&M[i]))[3] = data[0]; -+ } -+#endif /* HAVE_BIG_ENDIAN */ -+} -+ -+void md5_compute(MD5_CTX * ctx, uint8_t * data, uint32_t len) -+{ -+ uint8_t pos = ((ctx->bitlen[0] >> 3) & 0x3f); -+ -+ /* First we update the bit length */ -+ if ((ctx->bitlen[0] += (len << 3)) < (len << 3)) -+ ctx->bitlen[1]++; -+ ctx->bitlen[1] += (len >> 29); /* len is expressed in bytes */ -+ -+ if (pos) { -+ /* Buffer is not empty */ -+ if (64 - pos >= len) { -+ memcpy(ctx->buf_cur, data, len); -+ ctx->buf_cur += len; -+ pos += len; -+ if (pos == 64) { -+ /* The current block is over */ -+ md5_over_block(ctx, ctx->buf); -+ ctx->buf_cur = ctx->buf; -+ } -+ return; -+ } else { -+ memcpy(ctx->buf_cur, data, 64 - pos); -+ md5_over_block(ctx, ctx->buf); -+ len -= (64 - pos); -+ data += (64 - pos); -+ ctx->buf_cur = ctx->buf; -+ } -+ } -+ while (len >= 64) { -+ md5_over_block(ctx, data); -+ len -= 64; -+ data += 64; -+ } -+ if (len) { -+ memcpy(ctx->buf_cur, data, len); -+ ctx->buf_cur += len; -+ } -+} -+ -+void md5_final(MD5_CTX * ctx, uint8_t * digest) -+{ -+ uint32_t rem_size; -+ uint8_t *buf_cur = ctx->buf_cur; -+ int i; -+ -+ rem_size = 64 - ((ctx->bitlen[0] >> 3) & 0x3f); -+ *(buf_cur++) = 0x80; -+ -+ if (rem_size > 8 + 1) { -+ /* We have enough room in the current block */ -+ for (i = 0; i < rem_size - 8 - 1; i++) { -+ *(buf_cur++) = 0; -+ } -+ } else { -+ /* We do not have enough room and need therefore to add a new -+ 64-byte block */ -+ for (i = 0; i < rem_size - 1; i++) { -+ *(buf_cur++) = 0; -+ } -+ md5_over_block(ctx, ctx->buf); -+ -+ buf_cur = ctx->buf; -+ for (i = 0; i < 64 - 8; i++) { -+ *(buf_cur++) = 0; -+ } -+ } -+#ifdef HAVE_LITTLE_ENDIAN -+ memcpy(buf_cur, (uint8_t *) ctx->bitlen, 8); -+#endif /* HAVE_LITTLE_ENDIAN */ -+ -+#ifdef HAVE_BIG_ENDIAN -+ *(buf_cur++) = (ctx->bitlen[0] >> 24) & 0xff; -+ *(buf_cur++) = (ctx->bitlen[0] >> 16) & 0xff; -+ *(buf_cur++) = (ctx->bitlen[0] >> 8) & 0xff; -+ *(buf_cur++) = (ctx->bitlen[0] >> 0) & 0xff; -+ *(buf_cur++) = (ctx->bitlen[1] >> 24) & 0xff; -+ *(buf_cur++) = (ctx->bitlen[1] >> 16) & 0xff; -+ *(buf_cur++) = (ctx->bitlen[1] >> 8) & 0xff; -+ *(buf_cur++) = (ctx->bitlen[1] >> 0) & 0xff; -+#endif /* HAVE_BIG_ENDIAN */ -+ -+ md5_over_block(ctx, ctx->buf); -+ -+#ifdef HAVE_LITTLE_ENDIAN -+ memcpy(digest + 0, (uint8_t *) (&(ctx->A)), sizeof(uint32_t)); -+ memcpy(digest + 4, (uint8_t *) (&(ctx->B)), sizeof(uint32_t)); -+ memcpy(digest + 8, (uint8_t *) (&(ctx->C)), sizeof(uint32_t)); -+ memcpy(digest + 12, (uint8_t *) (&(ctx->D)), sizeof(uint32_t)); -+#endif /* HAVE_LITTLE_ENDIAN */ -+ -+#ifdef HAVE_BIG_ENDIAN -+ digest[0] = ((ctx->A) >> 24) & 0xff; -+ digest[1] = ((ctx->A) >> 16) & 0xff; -+ digest[2] = ((ctx->A) >> 8) & 0xff; -+ digest[3] = ((ctx->A) >> 0) & 0xff; -+ digest[4] = ((ctx->B) >> 24) & 0xff; -+ digest[5] = ((ctx->B) >> 16) & 0xff; -+ digest[6] = ((ctx->B) >> 8) & 0xff; -+ digest[7] = ((ctx->B) >> 0) & 0xff; -+ digest[8] = ((ctx->C) >> 24) & 0xff; -+ digest[9] = ((ctx->C) >> 16) & 0xff; -+ digest[10] = ((ctx->C) >> 8) & 0xff; -+ digest[11] = ((ctx->C) >> 0) & 0xff; -+ digest[12] = ((ctx->D) >> 24) & 0xff; -+ digest[13] = ((ctx->D) >> 16) & 0xff; -+ digest[14] = ((ctx->D) >> 8) & 0xff; -+ digest[15] = ((ctx->D) >> 0) & 0xff; -+#endif /* HAVE_BIG_ENDIAN */ -+} -+ -+void sha1_init(SHA1_CTX * ctx) -+{ -+ ctx->A = 0x67452301; -+ ctx->B = 0xefcdab89; -+ ctx->C = 0x98badcfe; -+ ctx->D = 0x10325476; -+ ctx->E = 0xc3d2e1f0; -+ ctx->buf_cur = ctx->buf; -+ ctx->bitlen[0] = ctx->bitlen[1] = 0; -+ memset(ctx->buf, 0, 64); -+} -+ -+void sha1_over_block(SHA1_CTX * ctx, uint8_t * data) -+{ -+ int i; -+ uint32_t W[80]; -+ uint32_t a = ctx->A; -+ uint32_t b = ctx->B; -+ uint32_t c = ctx->C; -+ uint32_t d = ctx->D; -+ uint32_t e = ctx->E; -+ uint32_t temp; -+ -+ create_W_blocks(W, data); -+ -+ /* Round 1 */ -+ for (i = 0; i < 20; i++) { -+ temp = LROLL(a, 5) + f(b, c, d) + e + W[i] + K1; -+ e = d; -+ d = c; -+ c = LROLL(b, 30); -+ b = a; -+ a = temp; -+ } -+ -+ /* Round 2 */ -+ for (i = 20; i < 40; i++) { -+ temp = LROLL(a, 5) + h(b, c, d) + e + W[i] + K2; -+ e = d; -+ d = c; -+ c = LROLL(b, 30); -+ b = a; -+ a = temp; -+ } -+ -+ /* Round 3 */ -+ for (i = 40; i < 60; i++) { -+ temp = LROLL(a, 5) + g(b, c, d) + e + W[i] + K3; -+ e = d; -+ d = c; -+ c = LROLL(b, 30); -+ b = a; -+ a = temp; -+ } -+ -+ /* Round 4 */ -+ for (i = 60; i < 80; i++) { -+ temp = LROLL(a, 5) + h(b, c, d) + e + W[i] + K4; -+ e = d; -+ d = c; -+ c = LROLL(b, 30); -+ b = a; -+ a = temp; -+ } -+ -+ ctx->A += a; -+ ctx->B += b; -+ ctx->C += c; -+ ctx->D += d; -+ ctx->E += e; -+} -+ -+void create_W_blocks(uint32_t * W, uint8_t * data) -+{ -+ int i; -+ -+#ifdef HAVE_BIG_ENDIAN -+ memcpy((uint8_t *) W, data, 64); -+#endif /* HAVE_BIG_ENDIAN */ -+ -+#ifdef HAVE_LITTLE_ENDIAN -+ for (i = 0; i < 16; i++, data += 4) { -+ ((uint8_t *) (&W[i]))[0] = data[3]; -+ ((uint8_t *) (&W[i]))[1] = data[2]; -+ ((uint8_t *) (&W[i]))[2] = data[1]; -+ ((uint8_t *) (&W[i]))[3] = data[0]; -+ } -+#endif /* HAVE_LITTLE_ENDIAN */ -+ for (i = 16; i < 80; i++) { -+ W[i] = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; -+ W[i] = LROLL(W[i], 1); -+ } -+} -+ -+void sha1_compute(SHA1_CTX * ctx, uint8_t * data, uint32_t len) -+{ -+ uint8_t pos = ((ctx->bitlen[0] >> 3) & 0x3f); -+ -+ /* First we update the bit length */ -+ if ((ctx->bitlen[0] += (len << 3)) < (len << 3)) -+ ctx->bitlen[1]++; -+ ctx->bitlen[1] += (len >> 29); /* len is expressed in bytes */ -+ -+ if (pos) { -+ /* Buffer is not empty */ -+ if (64 - pos >= len) { -+ memcpy(ctx->buf_cur, data, len); -+ ctx->buf_cur += len; -+ pos += len; -+ if (pos == 64) { -+ /* The current block is over */ -+ sha1_over_block(ctx, ctx->buf); -+ ctx->buf_cur = ctx->buf; -+ } -+ return; -+ } else { -+ memcpy(ctx->buf_cur, data, 64 - pos); -+ sha1_over_block(ctx, ctx->buf); -+ len -= (64 - pos); -+ data += (64 - pos); -+ ctx->buf_cur = ctx->buf; -+ } -+ } -+ while (len >= 64) { -+ sha1_over_block(ctx, data); -+ len -= 64; -+ data += 64; -+ } -+ if (len) { -+ memcpy(ctx->buf_cur, data, len); -+ ctx->buf_cur += len; -+ } -+} -+ -+void sha1_final(SHA1_CTX * ctx, uint8_t * digest) -+{ -+ uint32_t rem_size; -+ uint8_t *buf_cur = ctx->buf_cur; -+ int i; -+ -+ rem_size = 64 - ((ctx->bitlen[0] >> 3) & 0x3f); -+ *(buf_cur++) = 0x80; -+ -+ if (rem_size > 8 + 1) { -+ /* We have enough room in the current block */ -+ for (i = 0; i < rem_size - 8 - 1; i++) { -+ *(buf_cur++) = 0; -+ } -+ } else { -+ /* We do not have enough room and need therefore to add a new -+ 64-byte block */ -+ for (i = 0; i < rem_size - 1; i++) { -+ *(buf_cur++) = 0; -+ } -+ sha1_over_block(ctx, ctx->buf); -+ -+ buf_cur = ctx->buf; -+ for (i = 0; i < 64 - 8; i++) { -+ *(buf_cur++) = 0; -+ } -+ } -+#ifdef HAVE_BIG_ENDIAN -+ memcpy(buf_cur, (uint8_t *) ctx->bitlen, 8); -+#endif /* HAVE_BIG_ENDIAN */ -+ -+#ifdef HAVE_LITTLE_ENDIAN -+ *(buf_cur++) = (ctx->bitlen[1] >> 24) & 0xff; -+ *(buf_cur++) = (ctx->bitlen[1] >> 16) & 0xff; -+ *(buf_cur++) = (ctx->bitlen[1] >> 8) & 0xff; -+ *(buf_cur++) = (ctx->bitlen[1] >> 0) & 0xff; -+ *(buf_cur++) = (ctx->bitlen[0] >> 24) & 0xff; -+ *(buf_cur++) = (ctx->bitlen[0] >> 16) & 0xff; -+ *(buf_cur++) = (ctx->bitlen[0] >> 8) & 0xff; -+ *(buf_cur++) = (ctx->bitlen[0] >> 0) & 0xff; -+#endif /* HAVE_LITTLE_ENDIAN */ -+ -+ sha1_over_block(ctx, ctx->buf); -+ -+#ifdef HAVE_BIG_ENDIAN -+ memcpy(digest + 0, (uint8_t *) (&(ctx->A)), sizeof(uint32_t)); -+ memcpy(digest + 4, (uint8_t *) (&(ctx->B)), sizeof(uint32_t)); -+ memcpy(digest + 8, (uint8_t *) (&(ctx->C)), sizeof(uint32_t)); -+ memcpy(digest + 12, (uint8_t *) (&(ctx->D)), sizeof(uint32_t)); -+ memcpy(digest + 16, (uint8_t *) (&(ctx->E)), sizeof(uint32_t)); -+#endif /* HAVE_BIG_ENDIAN */ -+ -+#ifdef HAVE_LITTLE_ENDIAN -+ digest[0] = ((ctx->A) >> 24) & 0xff; -+ digest[1] = ((ctx->A) >> 16) & 0xff; -+ digest[2] = ((ctx->A) >> 8) & 0xff; -+ digest[3] = ((ctx->A) >> 0) & 0xff; -+ digest[4] = ((ctx->B) >> 24) & 0xff; -+ digest[5] = ((ctx->B) >> 16) & 0xff; -+ digest[6] = ((ctx->B) >> 8) & 0xff; -+ digest[7] = ((ctx->B) >> 0) & 0xff; -+ digest[8] = ((ctx->C) >> 24) & 0xff; -+ digest[9] = ((ctx->C) >> 16) & 0xff; -+ digest[10] = ((ctx->C) >> 8) & 0xff; -+ digest[11] = ((ctx->C) >> 0) & 0xff; -+ digest[12] = ((ctx->D) >> 24) & 0xff; -+ digest[13] = ((ctx->D) >> 16) & 0xff; -+ digest[14] = ((ctx->D) >> 8) & 0xff; -+ digest[15] = ((ctx->D) >> 0) & 0xff; -+ digest[16] = ((ctx->E) >> 24) & 0xff; -+ digest[17] = ((ctx->E) >> 16) & 0xff; -+ digest[18] = ((ctx->E) >> 8) & 0xff; -+ digest[19] = ((ctx->E) >> 0) & 0xff; -+#endif /* HAVE_LITTLE_ENDIAN */ -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/hmac.h linux-2.4.25/net/ipv6/mobile_ip6/hmac.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/hmac.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/hmac.h 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,94 @@ -+/* -+ * MIPL Mobile IPv6 Message authentication algorithms -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _HMAC_H -+#define _HMAC_H -+ -+#include -+#include -+ -+#define HAVE_LITTLE_ENDIAN -+ -+#define NO_EXPIRY 1 /* For sec_as */ -+ -+#define ALG_AUTH_NONE 0 -+#define ALG_AUTH_HMAC_MD5 1 -+#define ALG_AUTH_HMAC_SHA1 2 -+ -+struct sec_as; -+struct ah_processing { -+ void *context; -+ struct sec_as *sas; -+ u_int8_t *key_auth; -+ u_int32_t key_auth_len; -+}; -+ -+struct antireplay { -+ u_int32_t count; -+ u_int32_t bitmap; -+}; -+ -+typedef struct { -+ u_int32_t A, B, C, D; -+ u_int32_t bitlen[2]; -+ u_int8_t* buf_cur; -+ u_int8_t buf[64]; -+} MD5_CTX; -+ -+typedef struct { -+ u_int32_t A, B, C, D, E; -+ u_int32_t bitlen[2]; -+ u_int8_t* buf_cur; -+ u_int8_t buf[64]; -+} SHA1_CTX; -+ -+ -+ -+int ah_hmac_md5_init (struct ah_processing *ahp, u_int8_t *key, u_int32_t key_len); -+void ah_hmac_md5_loop(struct ah_processing*, void*, u_int32_t); -+void ah_hmac_md5_result(struct ah_processing*, char*); -+int ah_hmac_sha1_init(struct ah_processing*, u_int8_t *key, u_int32_t key_len); -+void ah_hmac_sha1_loop(struct ah_processing*, void*, u_int32_t); -+void ah_hmac_sha1_result(struct ah_processing*, char*); -+ -+ -+#define AH_HDR_LEN 12 /* # of bytes for Next Header, Payload Length, -+ RESERVED, Security Parameters Index and -+ -+ Sequence Number Field */ -+ -+void md5_init(MD5_CTX *ctx); -+void md5_over_block(MD5_CTX *ctx, u_int8_t* data); -+void create_M_blocks(u_int32_t* M, u_int8_t* data); -+void md5_compute(MD5_CTX *ctx, u_int8_t* data, u_int32_t len); -+void md5_final(MD5_CTX *ctx, u_int8_t* digest); -+ -+void sha1_init(SHA1_CTX *ctx); -+void sha1_over_block(SHA1_CTX *ctx, u_int8_t* data); -+void create_W_blocks(u_int32_t* W, u_int8_t* data); -+void sha1_compute(SHA1_CTX *ctx, u_int8_t* data, u_int32_t len); -+void sha1_final(SHA1_CTX *ctx, u_int8_t* digest); -+ -+struct mipv6_acq { -+ struct in6_addr coa; -+ struct in6_addr haddr; -+ struct in6_addr peer; -+ u_int32_t spi; -+}; -+#define MIPV6_MAX_AUTH_DATA 20 -+ -+#define HMAC_MD5_HASH_LEN 16 -+#define HMAC_SHA1_HASH_LEN 20 -+#define HMAC_SHA1_KEY_SIZE 20 -+#define HMAC_MD5_ICV_LEN 12 /* RFC 2403 */ -+#define HMAC_SHA1_ICV_LEN 12 /* RFC 2404 */ -+ -+#endif /* _HMAC_H */ -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/ioctl_mn.c linux-2.4.25/net/ipv6/mobile_ip6/ioctl_mn.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/ioctl_mn.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/ioctl_mn.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,142 @@ -+/* -+ * Mobile Node IOCTL Control device -+ * -+ * Authors: -+ * Henrik Petander -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 "debug.h" -+#include "mdetect.h" -+#include "multiaccess_ctl.h" -+ -+/* Reserved for local / experimental use */ -+#define MAJOR_NUM 0xf9 -+ -+/* Get Care-of address information for Mobile Node */ -+#define IOCTL_GET_CAREOFADDR _IOWR(MAJOR_NUM, 9, void *) -+ -+#define MA_IOCTL_SET_IFACE_PREFERENCE _IOR (MAJOR_NUM, 13, void *) -+ -+/* The name of the device file */ -+#define CTLFILE "mipv6_dev" -+ -+static int inuse = 0; -+ -+static int mipv6_open(struct inode *inode, struct file *file) -+{ -+ DEBUG(DBG_INFO, "(%p)\n", file); -+ -+ if (inuse) -+ return -EBUSY; -+ -+ inuse++; -+ -+ MOD_INC_USE_COUNT; -+ -+ return 0; -+} -+ -+static int mipv6_close(struct inode *inode, struct file *file) -+{ -+ DEBUG(DBG_INFO, "(%p,%p)\n", inode, file); -+ inuse--; -+ -+ MOD_DEC_USE_COUNT; -+ -+ return 0; -+} -+ -+int mipv6_ioctl(struct inode *inode, struct file *file, -+ unsigned int ioctl_num, /* The number of the ioctl */ -+ unsigned long arg) /* The parameter to it */ -+{ -+ struct in6_addr careofaddr; -+ -+ /* Switch according to the ioctl called */ -+ switch (ioctl_num) { -+ case IOCTL_GET_CAREOFADDR: -+ DEBUG(DBG_DATADUMP, "IOCTL_GET_CAREOFADDR"); -+ /* First get home address from user and then look up -+ * the care-of address and return it -+ */ -+ if (copy_from_user(&careofaddr, (struct in6_addr *)arg, -+ sizeof(struct in6_addr)) < 0) { -+ DEBUG(DBG_WARNING, "Copy from user failed"); -+ return -EFAULT; -+ } -+ mipv6_get_care_of_address(&careofaddr, &careofaddr); -+ if (copy_to_user((struct in6_addr *)arg, &careofaddr, -+ sizeof(struct in6_addr)) < 0) { -+ DEBUG(DBG_WARNING, "copy_to_user failed"); -+ return -EFAULT; -+ } -+ break; -+ case MA_IOCTL_SET_IFACE_PREFERENCE: -+ DEBUG(DBG_INFO, "MA_IOCTL_SET_IFACE_PREFERENCE"); -+ ma_ctl_set_preference(arg); -+ break; -+ -+ default: -+ DEBUG(DBG_WARNING, "Unknown ioctl cmd (%d)", ioctl_num); -+ return -ENOENT; -+ } -+ return 0; -+} -+ -+struct file_operations Fops = { -+ owner: THIS_MODULE, -+ read: NULL, -+ write: NULL, -+ poll: NULL, -+ ioctl: mipv6_ioctl, -+ open: mipv6_open, -+ release: mipv6_close -+}; -+ -+ -+/* Initialize the module - Register the character device */ -+int mipv6_ioctl_mn_init(void) -+{ -+ int ret_val; -+ -+ /* Register the character device (atleast try) */ -+ ret_val = register_chrdev(MAJOR_NUM, CTLFILE, &Fops); -+ -+ /* Negative values signify an error */ -+ if (ret_val < 0) { -+ DEBUG(DBG_ERROR, "failed registering char device (err=%d)", -+ ret_val); -+ return ret_val; -+ } -+ -+ DEBUG(DBG_INFO, "Device number %x, success", MAJOR_NUM); -+ return 0; -+} -+ -+ -+/* Cleanup - unregister the appropriate file from /proc */ -+void mipv6_ioctl_mn_exit(void) -+{ -+ int ret; -+ /* Unregister the device */ -+ ret = unregister_chrdev(MAJOR_NUM, CTLFILE); -+ -+ /* If there's an error, report it */ -+ if (ret < 0) -+ DEBUG(DBG_ERROR, "errorcode: %d\n", ret); -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mdetect.c linux-2.4.25/net/ipv6/mobile_ip6/mdetect.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/mdetect.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/mdetect.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,1153 @@ -+/* -+ * Movement Detection Module -+ * -+ * Authors: -+ * Henrik Petander -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * Handles the L3 movement detection of mobile node and also -+ * changing of its routes. -+ * -+ */ -+ -+/* -+ * Changes: -+ * -+ * Nanno Langstraat : Locking fixes -+ * Venkata Jagana : Locking fix -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef CONFIG_SYSCTL -+#include -+#endif /* CONFIG_SYSCTL */ -+ -+#include "util.h" -+#include "mdetect.h" -+#include "mn.h" -+#include "debug.h" -+#include "multiaccess_ctl.h" -+ -+#define START 0 -+#define CONTINUE 1 -+#define OK 2 -+#define DEBUG_MDETECT 7 -+ -+#define DEF_RTR_POLL_IVAL 5 /* In seconds */ -+ -+#define NO_RTR 0 -+#define RTR_SUSPECT 1 -+#define CURR_RTR_OK 2 -+ -+#define RA_RCVD 0 -+#define NA_RCVD 1 -+#define TIMEOUT 2 -+ -+#define MIPV6_MDF_NONE 0x0 -+#define MIPV6_MDF_HAS_RTR_PREV 0x1 -+ -+#define ROUTER_REACHABLE 1 -+#define RADV_MISSED 2 -+#define NOT_REACHABLE 3 -+ -+/* R_TIME_OUT paramater is used to make the decision when to change the -+ * default router, if the current one is unreachable. 2s is pretty aggressive -+ * and may result in hopping between two routers. OTOH a small value enhances -+ * the performance -+ */ -+#define R_TIME_OUT 30*HZ -+ -+/* maximum RA interval for router unreachability detection */ -+#define MAX_RADV_INTERVAL 6*HZ /* 6000 ms... */ -+ -+/* Threshold for exponential resending of router solicitations */ -+#define RS_RESEND_LINEAR 10*HZ -+ -+#define EAGER_CELL_SWITCHING 1 -+#define LAZY_CELL_SWITCHING 0 -+#define RESPECT_DAD 1 -+ -+#define ROUTER_ADDRESS 0x20 -+ -+/* RA flags */ -+#define ND_RA_FLAG_MANAGED 0x80 -+#define ND_RA_FLAG_OTHER 0x40 -+#define ND_RA_FLAG_HA 0x20 -+ -+/* DAD flags for global and link local addresses */ -+ -+#define COA_TENTATIVE 0x10 -+#define LLADDR_TENTATIVE 0x01 -+ -+struct router { -+ struct list_head list; -+ struct in6_addr ll_addr; -+ struct in6_addr raddr; /* Also contains prefix */ -+ __u8 link_addr[MAX_ADDR_LEN]; /* link layer address */ -+ __u8 link_addr_len; -+ __u8 state; -+ __u8 is_current; -+ __u8 reachable; -+ int ifindex; -+ int pfix_len; /* Length of the network prefix */ -+ unsigned long lifetime; /* from ra */ -+ __u32 last_ns_sent; -+ __u32 last_ra_rcvd; -+ __u32 interval; /* ra interval in milliseconds, 0 if not set */ -+ int glob_addr; /*Whether raddr contains also routers global address*/ -+ __u8 flags; /* RA flags, for example ha */ -+ struct in6_addr CoA; /* care-off address used with this router */ -+ int extra_addr_route; -+}; -+ -+/* dad could also be RESPECT_DAD for duplicate address detection of -+ new care-of addresses */ -+static int dad = 0; -+ -+/* Only one choice, nothing else implemented */ -+int max_rtr_reach_time = DEF_RTR_POLL_IVAL; -+ -+ -+int eager_cell_switching = EAGER_CELL_SWITCHING; /* Can be set to 0 via proc */ -+static spinlock_t router_lock; -+static spinlock_t ho_lock; -+ -+static void coa_timer_handler(unsigned long arg); -+static void timer_handler(unsigned long foo); -+static struct router *curr_router = NULL, *next_router = NULL; -+static struct timer_list r_timer = { function: timer_handler }; -+static struct timer_list coa_timer = { function: coa_timer_handler }; -+#define MAX_ROUTERS 1000 -+static LIST_HEAD(rtr_list); -+static int num_routers = 0; -+static struct handoff *_ho = NULL; -+/* -+ * Functions for handling the default router list, which movement -+ * detection uses for avoiding loops etc. -+ */ -+ -+/* TODO: Send NS to router after MAX interval has passed from last RA */ -+static int mipv6_router_state(struct router *rtr) { -+ if (rtr->interval) { -+ if (time_before(jiffies, (rtr->last_ra_rcvd + (rtr->interval * HZ) / 1000))) -+ return ROUTER_REACHABLE; -+ else -+ return NOT_REACHABLE; -+ } -+ else -+ if (time_after(jiffies, rtr->last_ra_rcvd + (rtr->lifetime * HZ))) -+ return NOT_REACHABLE; -+ return ROUTER_REACHABLE; -+} -+ -+/* searches for a specific router or any router that is reachable, -+ * if address is NULL. Also deletes obsolete routers. -+ */ -+static void mipv6_router_gc(void) -+{ -+ struct router *curr = NULL; -+ struct list_head *lh, *lh_tmp; -+ -+ DEBUG_FUNC(); -+ -+ list_for_each_safe(lh, lh_tmp, &rtr_list) { -+ curr = list_entry(lh, struct router, list); -+ if (mipv6_router_state(curr) == NOT_REACHABLE && !curr->is_current) { -+ num_routers--; -+ list_del_init(&curr->list); -+ DEBUG(DBG_DATADUMP, "Deleting unreachable router %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(&curr->raddr)); -+ kfree(curr); -+ } -+ else { -+ DEBUG(DBG_DATADUMP, "NOT Deleting router %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(&curr->raddr)); -+ } -+ } -+} -+ -+static struct router *mipv6_rtr_get(struct in6_addr *search_addr) -+{ -+ struct router *rtr = NULL; -+ struct list_head *lh; -+ -+ DEBUG_FUNC(); -+ -+ if (search_addr == NULL) -+ return NULL; -+ list_for_each(lh, &rtr_list) { -+ rtr = list_entry(lh, struct router, list); -+ if(!ipv6_addr_cmp(search_addr, &rtr->raddr)) { -+ return rtr; -+ } -+ } -+ return NULL; -+} -+ -+/* -+ * Adds router to list -+ */ -+static struct router *mipv6_rtr_add(struct router *nrt) -+{ -+ -+ struct router *rptr; -+ -+ DEBUG_FUNC(); -+ -+ /* check if someone is trying DoS attack, or we just have some -+ memory leaks... */ -+ if (num_routers > MAX_ROUTERS) { -+ DEBUG(DBG_CRITICAL, -+ "failed to add new router, MAX_ROUTERS exceeded"); -+ return NULL; -+ } -+ -+ rptr = kmalloc(sizeof(struct router), GFP_ATOMIC); -+ if (rptr) { -+ memcpy(rptr, nrt, sizeof(struct router)); -+ list_add(&rptr->list, &rtr_list); -+ num_routers++; -+ } -+ DEBUG(DBG_INFO, "Adding router: %x:%x:%x:%x:%x:%x:%x:%x, " -+ "lifetime : %d sec, adv.interval: %d millisec", -+ NIPV6ADDR(&rptr->raddr), rptr->lifetime, rptr->interval); -+ -+ DEBUG(DBG_INFO, "num_routers after addition: %d", num_routers); -+ return rptr; -+} -+ -+/* Cleans up the list */ -+static void list_free(struct router **curr_router_p) -+{ -+ struct router *tmp; -+ struct list_head *lh, *lh_tmp; -+ -+ DEBUG_FUNC(); -+ -+ DEBUG(DBG_INFO, "Freeing the router list"); -+ /* set curr_router->prev_router and curr_router NULL */ -+ *curr_router_p = NULL; -+ list_for_each_safe(lh, lh_tmp, &rtr_list) { -+ tmp = list_entry(lh, struct router, list); -+ DEBUG(DBG_INFO, "%x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(&tmp->ll_addr)); -+ list_del(&tmp->list); -+ kfree(tmp); -+ num_routers--; -+ } -+} -+ -+int rs_state = START; -+ -+/* Sends router solicitations to all valid devices -+ * source = link local address (of sending interface) -+ * dstaddr = all routers multicast address -+ * Solicitations are sent at an exponentially decreasing rate -+ * -+ * TODO: send solicitation first at a normal rate (from ipv6) and -+ * after that use the exponentially increasing intervals -+ */ -+static int rs_send(void) -+{ -+ struct net_device *dev; -+ struct in6_addr raddr, lladdr; -+ struct inet6_dev *in6_dev = NULL; -+ static int num_rs; -+ -+ if (rs_state == START) { -+ num_rs = 0; -+ rs_state = CONTINUE; -+ } else if (num_rs++ > MAX_RTR_SOLICITATIONS) -+ return HZ; -+ -+ ipv6_addr_all_routers(&raddr); -+ read_lock(&dev_base_lock); -+ -+ /* Send router solicitations to all interfaces */ -+ for (dev = dev_base; dev; dev = dev->next) { -+ if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ETHER) { -+ DEBUG(DBG_DATADUMP, "Sending RS to device %s", -+ dev->name); -+ if (!ipv6_get_lladdr(dev, &lladdr)) { -+ ndisc_send_rs(dev, &lladdr, &raddr); -+ in6_dev = in6_dev_get(dev); -+ in6_dev->if_flags |= IF_RS_SENT; -+ in6_dev_put(in6_dev); -+ } else { -+ DEBUG(DBG_DATADUMP, "%s: device doesn't have link-local address!\n", dev->name); -+ continue; -+ } -+ } -+ -+ } -+ read_unlock(&dev_base_lock); -+ return RTR_SOLICITATION_INTERVAL; -+} -+ -+/* Create a new CoA for MN and also add a route to it if it is still tentative -+ to allow MN to get packets to the address immediately -+ */ -+static int form_coa(struct in6_addr *coa, struct in6_addr *pfix, -+ int plen, int ifindex) -+{ -+ struct net_device *dev; -+ struct inet6_dev *in6_dev; -+ int ret = 0; -+ -+ if ((dev = dev_get_by_index(ifindex)) == NULL) { -+ DEBUG(DBG_WARNING, "Device is not present"); -+ return -1; -+ } -+ if ((in6_dev = in6_dev_get(dev)) == NULL) { -+ DEBUG(DBG_WARNING, "inet6_dev is not present"); -+ dev_put(dev); -+ return -1; -+ } -+ coa->s6_addr32[0] = pfix->s6_addr32[0]; -+ coa->s6_addr32[1] = pfix->s6_addr32[1]; -+ -+ if (ipv6_generate_eui64(coa->s6_addr + 8, dev) && -+ ipv6_inherit_eui64(coa->s6_addr + 8, in6_dev)) { -+ in6_dev_put(in6_dev); -+ dev_put(dev); -+ return -1; -+ } -+ if (ipv6_chk_addr(coa, dev) == 0) { -+ DEBUG(DBG_WARNING, "care-of address still tentative"); -+ ret = 1; -+ } -+ DEBUG(DBG_INFO, "Formed new CoA: %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(coa)); -+ -+ in6_dev_put(in6_dev); -+ dev_put(dev); -+ return ret; -+} -+ -+static inline int rtr_is_gw(struct router *rtr, struct rt6_info *rt) -+{ -+ return ((rt->rt6i_flags & RTF_GATEWAY) && -+ !ipv6_addr_cmp(&rt->rt6i_gateway, &rtr->ll_addr)); -+} -+ -+static inline int is_prefix_route(struct router *rtr, struct rt6_info *rt) -+{ -+ return (!(rt->rt6i_flags & RTF_GATEWAY) && -+ mipv6_prefix_compare(&rt->rt6i_dst.addr, &rtr->raddr, -+ rtr->pfix_len)); -+} -+ -+/* -+ * Function that determines whether given rt6_info should be destroyed -+ * (negative => destroy rt6_info, zero or positive => do nothing) -+ */ -+static int mn_route_cleaner(struct rt6_info *rt, void *arg) -+{ -+ int type; -+ -+ struct router *rtr = (struct router *)arg; -+ -+ int ret = -1; -+ -+ DEBUG_FUNC(); -+ -+ if (!rt || !rtr) { -+ DEBUG(DBG_ERROR, "mn_route_cleaner: rt or rtr NULL"); -+ return 0; -+ } -+ -+ /* Do not delete routes to local addresses or to multicast -+ * addresses, since we need them to get router advertisements -+ * etc. Multicast addresses are more tricky, but we don't -+ * delete them in any case. The routing mechanism is not optimal for -+ * multihoming. -+ * -+ * Also keep all new prefix routes, gateway routes through rtr and -+ * all remaining default routes (including those used for reverse -+ * tunneling) -+ */ -+ type = ipv6_addr_type(&rt->rt6i_dst.addr); -+ -+ if ((type & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)) || -+ rt->rt6i_dev == &loopback_dev || rtr_is_gw(rtr, rt) || -+ is_prefix_route(rtr, rt) || (rt->rt6i_flags & RTF_DEFAULT)) -+ ret = 0; -+ -+ /* delete all others */ -+ -+ if (rt->rt6i_dev != &loopback_dev) { -+ DEBUG(DEBUG_MDETECT, -+ "%s route:\n" -+ "dev: %s,\n" -+ "gw: %x:%x:%x:%x:%x:%x:%x:%x,\n" -+ "flags: %x,\n" -+ "metric: %d,\n" -+ "src: %x:%x:%x:%x:%x:%x:%x:%x,\n" -+ "dst: %x:%x:%x:%x:%x:%x:%x:%x,\n" -+ "plen: %d\n", -+ (ret ? "Deleting" : "Keeping"), -+ rt->rt6i_dev->name, -+ NIPV6ADDR(&rt->rt6i_gateway), -+ rt->rt6i_flags, -+ rt->rt6i_metric, -+ NIPV6ADDR(&rt->rt6i_src.addr), -+ NIPV6ADDR(&rt->rt6i_dst.addr), -+ rt->rt6i_dst.plen); -+ } -+ return ret; -+} -+ -+/* -+ * Deletes old routes -+ */ -+static __inline__ void delete_routes(struct router *rtr) -+{ -+ DEBUG_FUNC(); -+ -+ /* Routing table is locked to ensure that nobody uses its */ -+ write_lock_bh(&rt6_lock); -+ DEBUG(DBG_INFO, "mipv6: Purging routes"); -+ /* TODO: Does not prune, should it? */ -+ fib6_clean_tree(&ip6_routing_table, -+ mn_route_cleaner, 0, rtr); -+ write_unlock_bh(&rt6_lock); -+ -+} -+ -+ -+static __inline__ void delete_coas(struct router *rtr) -+{ -+ struct net_device *dev; -+ struct inet6_dev *idev; -+ struct inet6_ifaddr *ifa; -+ -+ dev = dev_get_by_index(rtr->ifindex); -+ if (!dev) -+ return; -+ -+ idev = in6_dev_get(dev); -+ -+ if (idev) { -+ read_lock_bh(&idev->lock); -+ ifa = idev->addr_list; -+ while (ifa) { -+ int keep; -+ spin_lock(&ifa->lock); -+ -+ keep = (ifa->flags&(IFA_F_PERMANENT|IFA_F_HOMEADDR) || -+ !ipv6_addr_cmp(&ifa->addr, &rtr->CoA)); -+ -+ spin_unlock(&ifa->lock); -+ -+ if (keep) -+ ifa = ifa->if_next; -+ else { -+ in6_ifa_hold(ifa); -+ read_unlock_bh(&idev->lock); -+ -+ ipv6_del_addr(ifa); -+ -+ read_lock_bh(&idev->lock); -+ ifa = idev->addr_list; -+ } -+ } -+ read_unlock_bh(&idev->lock); -+ in6_dev_put(idev); -+ } -+ dev_put(dev); -+} -+ -+int next_mdet_state[3][3] = {{CURR_RTR_OK, NO_RTR, NO_RTR}, -+ {CURR_RTR_OK, CURR_RTR_OK, NO_RTR}, -+ {CURR_RTR_OK, CURR_RTR_OK, RTR_SUSPECT}}; -+ -+char *states[3] = {"NO_RTR", "RTR_SUSPECT", "CURR_RTR_OK"}; -+char *events[3] = {"RA_RCVD", "NA_RCVD", "TIMEOUT"}; -+ -+/* State transitions -+ * NO_RTR, RA_RCVD -> CURR_RTR_OK -+ * NO_RTR, NA_RCVD -> NO_RTR -+ * NO_RTR, TIMEOUT -> NO_RTR -+ -+ * RTR_SUSPECT, RA_RCVD -> CURR_RTR_OK -+ * RTR_SUSPECT, NA_RCVD -> CURR_RTR_OK -+ * RTR_SUSPECT, TIMEOUT -> NO_RTR -+ -+ * CURR_RTR_OK, RA_RCVD -> CURR_RTR_OK -+ * CURR_RTR_OK, NA_RCVD -> CURR_RTR_OK -+ * CURR_RTR_OK, TIMEOUT -> RTR_SUSPECT -+ */ -+static int _curr_state = NO_RTR; -+ -+#if 0 -+static int get_mdet_state(void){ -+ int state; -+ spin_lock_bh(&router_lock); -+ state = _curr_state; -+ spin_unlock_bh(&router_lock); -+ return state; -+} -+#endif -+ -+/* Needs to be called with router_lock locked */ -+static int mdet_statemachine(int event) -+{ -+ -+ if (event > 2 || _curr_state > 2) { -+ DEBUG(DBG_ERROR, "Got illegal event or curr_state"); -+ return -1; -+ } -+ -+ DEBUG(DBG_DATADUMP, "Got event %s and curr_state is %s", -+ events[event], states[_curr_state]); -+ -+ _curr_state = next_mdet_state[_curr_state][event]; -+ DEBUG(DBG_DATADUMP, "Next state is %s", states[_curr_state]); -+ return _curr_state; -+} -+ -+static void mipv6_do_ll_dad(int ifindex) -+{ -+ struct net_device *dev = dev_get_by_index(ifindex); -+ if (dev) { -+ struct in6_addr lladdr; -+ struct inet6_ifaddr *ifa; -+ if (!ipv6_get_lladdr(dev, &lladdr) && -+ (ifa = ipv6_get_ifaddr(&lladdr, dev)) != NULL) { -+ spin_lock_bh(&ifa->lock); -+ if (!(ifa->flags & IFA_F_TENTATIVE)) { -+ ifa->flags |= IFA_F_TENTATIVE; -+ spin_unlock_bh(&ifa->lock); -+ addrconf_dad_start(ifa, 0); -+ } else -+ spin_unlock_bh(&ifa->lock); -+ -+ } -+ dev_put(dev); -+ } -+} -+/* -+ * Changes the router, called from ndisc.c if mipv6_router_event -+ * returns true. -+ */ -+ -+static void mipv6_change_router(void) -+{ -+ struct in6_addr coa; -+ int ret, ifindex; -+ -+ DEBUG_FUNC(); -+ -+ -+ if (next_router == NULL) -+ return; -+ -+ spin_lock(&router_lock); -+ -+ -+ if (curr_router != NULL && -+ !ipv6_addr_cmp(&curr_router->ll_addr, &next_router->ll_addr)) { -+ DEBUG(DBG_INFO,"Trying to handoff from: " -+ "%x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(&curr_router->ll_addr)); -+ DEBUG(DBG_INFO,"Trying to handoff to: " -+ "%x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(&next_router->ll_addr)); -+ next_router = NULL; /* Let's not leave dangling pointers */ -+ spin_unlock(&router_lock); -+ return; -+ } -+ ret = form_coa(&next_router->CoA, &next_router->raddr, -+ next_router->pfix_len, next_router->ifindex); -+ if (ret < 0) { -+ DEBUG(DBG_ERROR, "handoff: Creation of coa failed"); -+ spin_unlock(&router_lock); -+ return; -+ } else if (ret > 0) -+ next_router->flags |= COA_TENTATIVE; -+ -+ mdet_statemachine(RA_RCVD); /* TODO: What if DAD fails... */ -+ if (next_router->interval) -+ mod_timer(&r_timer, jiffies + -+ (next_router->interval * HZ)/1000); -+ else -+ mod_timer(&r_timer, jiffies + max_rtr_reach_time * HZ); -+ -+ -+ if (ret == 0) { -+ ipv6_addr_copy(&coa, &next_router->CoA); -+ ifindex = next_router->ifindex; -+ spin_unlock(&router_lock); -+ mipv6_mdet_finalize_ho(&coa, ifindex); -+ return; -+ } -+ spin_unlock(&router_lock); -+ -+} -+static unsigned long ns_send(void) -+{ -+ struct neighbour *neigh; -+ struct net_device *dev; -+ struct in6_addr *raddr; -+ -+ DEBUG(DBG_DATADUMP, "Sending Neighbour solicitation to default router to verify its reachability"); -+ if (!curr_router) -+ return HZ; -+ if ((dev = dev_get_by_index(curr_router->ifindex)) == NULL) -+ return HZ; -+ if ((neigh = ndisc_get_neigh(dev, &curr_router->ll_addr)) == NULL) { -+ dev_put(dev); -+ return HZ; -+ } -+ if (curr_router->glob_addr) -+ raddr = &curr_router->raddr; -+ else -+ raddr = &curr_router->ll_addr; -+ -+ curr_router->last_ns_sent = jiffies; -+ ndisc_send_ns(dev, neigh, raddr, raddr, NULL); -+ -+ neigh_release(neigh); -+ dev_put(dev); -+ return HZ/5; /* Wait 200ms for a reply */ -+} -+ -+static int na_rcvd(void) -+{ -+ int neigh_ok = 0; -+ struct neighbour *neigh; -+ struct net_device *dev; -+ -+ if (!curr_router) -+ return 0; -+ if ((dev = dev_get_by_index(curr_router->ifindex)) == NULL) -+ return 0; -+ if ((neigh = ndisc_get_neigh(dev, &curr_router->ll_addr)) == NULL) { -+ dev_put(dev); -+ return 0; -+ } -+ if (neigh->flags & NTF_ROUTER && -+ (time_after(neigh->confirmed, curr_router->last_ns_sent) || -+ neigh->confirmed == curr_router->last_ns_sent)) { -+ neigh_ok = 1; -+ DEBUG(DBG_DATADUMP, "Mdetect event: NA rcvd from curr rtr"); -+ } else -+ DEBUG(DBG_DATADUMP, "Mdetect event: NA NOT rcvd from curr rtr within time limit"); -+ neigh_release(neigh); -+ dev_put(dev); -+ return neigh_ok; -+} -+ -+static void coa_timer_handler(unsigned long dummy) -+{ -+ -+ spin_lock_bh(&ho_lock); -+ if (_ho) { -+ DEBUG(DBG_INFO, "Starting handoff after DAD"); -+ mipv6_mobile_node_moved(_ho); -+ kfree(_ho); -+ _ho = NULL; -+ } -+ spin_unlock_bh(&ho_lock); -+} -+static void timer_handler(unsigned long foo) -+{ -+ unsigned long timeout; -+ int state; -+ spin_lock_bh(&router_lock); -+ -+ if (_curr_state != NO_RTR) -+ rs_state = START; -+ -+ if (_curr_state == RTR_SUSPECT && na_rcvd()) { -+ state = mdet_statemachine(NA_RCVD); -+ timeout = curr_router->interval ? curr_router->interval : max_rtr_reach_time * HZ; -+ } else { -+ state = mdet_statemachine(TIMEOUT); -+ if (state == NO_RTR) -+ timeout = rs_send(); -+ else /* RTR_SUSPECT */ -+ timeout = ns_send(); -+ } -+ if (!timeout) -+ timeout = HZ; -+ -+ mipv6_router_gc(); -+ mod_timer(&r_timer, jiffies + timeout); -+ spin_unlock_bh(&router_lock); -+} -+ -+/** -+ * mipv6_get_care_of_address - get node's care-of primary address -+ * @homeaddr: one of node's home addresses -+ * @coaddr: buffer to store care-of address -+ * -+ * Stores the current care-of address in the @coaddr, assumes -+ * addresses in EUI-64 format. Since node might have several home -+ * addresses caller MUST supply @homeaddr. If node is at home -+ * @homeaddr is stored in @coaddr. Returns 0 on success, otherwise a -+ * negative value. -+ **/ -+int mipv6_get_care_of_address( -+ struct in6_addr *homeaddr, struct in6_addr *coaddr) -+{ -+ -+ DEBUG_FUNC(); -+ -+ if (homeaddr == NULL) -+ return -1; -+ spin_lock_bh(&router_lock); -+ if (curr_router == NULL || mipv6_mn_is_at_home(homeaddr) || -+ mipv6_prefix_compare(homeaddr, &curr_router->raddr, 64) || -+ curr_router->flags&COA_TENTATIVE) { -+ DEBUG(DBG_INFO, -+ "mipv6_get_care_of_address: returning home address"); -+ ipv6_addr_copy(coaddr, homeaddr); -+ spin_unlock_bh(&router_lock); -+ return 0; -+ -+ } -+ -+ /* At home or address check failure probably due to dad wait */ -+ if (mipv6_prefix_compare(&curr_router->raddr, homeaddr, -+ curr_router->pfix_len) -+ || (dad == RESPECT_DAD && -+ (ipv6_chk_addr(coaddr, NULL) == 0))) { -+ ipv6_addr_copy(coaddr, homeaddr); -+ } else { -+ ipv6_addr_copy(coaddr, &curr_router->CoA); -+ } -+ -+ spin_unlock_bh(&router_lock); -+ return 0; -+} -+ -+int mipv6_mdet_del_if(int ifindex) -+{ -+ struct router *curr = NULL; -+ struct list_head *lh, *lh_tmp; -+ -+ spin_lock_bh(&router_lock); -+ list_for_each_safe(lh, lh_tmp, &rtr_list) { -+ curr = list_entry(lh, struct router, list); -+ if (curr->ifindex == ifindex) { -+ num_routers--; -+ list_del_init(&curr->list); -+ DEBUG(DBG_DATADUMP, "Deleting router %x:%x:%x:%x:%x:%x:%x:%x on interface %d", -+ NIPV6ADDR(&curr->raddr), ifindex); -+ if (curr_router == curr) -+ curr_router = NULL; -+ kfree(curr); -+ } -+ } -+ spin_unlock_bh(&router_lock); -+ return 0; -+} -+ -+void mipv6_mdet_retrigger_ho(void) -+{ -+ struct handoff ho; -+ -+ spin_lock_bh(&router_lock); -+ if (curr_router != NULL) { -+ ho.coa = &curr_router->CoA; -+ ho.plen = curr_router->pfix_len; -+ ho.ifindex = curr_router->ifindex; -+ ipv6_addr_copy(&ho.rtr_addr, &curr_router->raddr); -+ ho.home_address = (curr_router->glob_addr && -+ curr_router->flags&ND_RA_FLAG_HA); -+ } -+ spin_unlock_bh(&router_lock); -+ mipv6_mobile_node_moved(&ho); -+} -+ -+void mipv6_mdet_set_curr_rtr_reachable(int reachable) -+{ -+ spin_lock_bh(&router_lock); -+ if (curr_router != NULL) { -+ curr_router->reachable = reachable; -+ } -+ spin_unlock_bh(&router_lock); -+ -+} -+ -+int mipv6_mdet_finalize_ho(const struct in6_addr *coa, const int ifindex) -+{ -+ int dummy; -+ struct handoff ho; -+ struct router *tmp; -+ struct net_device *dev; -+ struct in6_addr ll_addr; -+ -+ spin_lock_bh(&router_lock); -+ -+ if (!next_router) { -+ spin_unlock_bh(&router_lock); -+ return 0; -+ } -+ -+ dev = dev_get_by_index(next_router->ifindex); -+ -+ if (ipv6_get_lladdr(dev, &ll_addr) == 0) { -+ if (ipv6_addr_cmp(&ll_addr, coa) == 0) -+ DEBUG(DBG_INFO, "DAD for link local address completed"); -+ next_router->flags &= ~LLADDR_TENTATIVE; -+ } -+ -+ dev_put(dev); -+ -+ if (mipv6_prefix_compare(coa, &next_router->CoA, -+ next_router->pfix_len)) { -+ DEBUG(DBG_INFO, "DAD for Care-of address completed"); -+ next_router->flags &= ~COA_TENTATIVE; -+ } -+ if (!(next_router->flags&LLADDR_TENTATIVE) && !(next_router->flags&COA_TENTATIVE)) { -+ DEBUG(DBG_INFO, "%s: Proceeding with handoff after DAD\n", __FUNCTION__); -+ tmp = curr_router; -+ curr_router = next_router; -+ curr_router->is_current = 1; -+ next_router = NULL; -+ curr_router->flags &= ~COA_TENTATIVE; -+ delete_routes(curr_router); -+ delete_coas(curr_router); -+ if (tmp) { -+ struct net_device *dev_old = dev_get_by_index(tmp->ifindex); -+ struct rt6_info *rt = NULL; -+ if (dev_old) { -+ rt = rt6_get_dflt_router(&tmp->ll_addr, dev_old); -+ dev_put(dev_old); -+ } -+ if (rt) -+ ip6_del_rt(rt, NULL); -+ tmp->is_current = 0; -+ } -+ -+ ma_ctl_upd_iface(curr_router->ifindex, MA_IFACE_CURRENT, &dummy); -+ ma_ctl_upd_iface(curr_router->ifindex, MA_IFACE_CURRENT, &dummy); -+ -+ -+ ho.coa = &curr_router->CoA; -+ ho.plen = curr_router->pfix_len; -+ ho.ifindex = curr_router->ifindex; -+ ipv6_addr_copy(&ho.rtr_addr, &curr_router->raddr); -+ ho.home_address = (curr_router->glob_addr && -+ curr_router->flags&ND_RA_FLAG_HA); -+ -+ spin_unlock_bh(&router_lock); -+ mipv6_mobile_node_moved(&ho); -+ } else -+ spin_unlock_bh(&router_lock); -+ return 0; -+} -+/* Decides whether router candidate is the same router as current rtr -+ * based on prefix / global addresses of the routers and their link local -+ * addresses -+ */ -+static int is_current_rtr(struct router *nrt, struct router *crt) -+{ -+ DEBUG_FUNC(); -+ -+ DEBUG(DEBUG_MDETECT, "Current router: " -+ "%x:%x:%x:%x:%x:%x:%x:%x and", NIPV6ADDR(&crt->raddr)); -+ DEBUG(DEBUG_MDETECT, "Candidate router: " -+ "%x:%x:%x:%x:%x:%x:%x:%x", NIPV6ADDR(&nrt->raddr)); -+ -+ return (!ipv6_addr_cmp(&nrt->raddr,&crt->raddr) && -+ !ipv6_addr_cmp(&nrt->ll_addr, &crt->ll_addr)); -+} -+ -+/* -+ * Change next router to nrtr -+ * Returns 1, if router has been changed. -+ */ -+ -+static int change_next_rtr(struct router *nrtr, struct router *ortr) -+{ -+ int changed = 0; -+ DEBUG_FUNC(); -+ -+ if (!next_router || ipv6_addr_cmp(&nrtr->raddr, &next_router->raddr)) { -+ changed = 1; -+ } -+ next_router = nrtr; -+ return changed; -+} -+static int clean_ncache(struct router *nrt, struct router *ort, int same_if) -+{ -+ struct net_device *ortdev; -+ DEBUG_FUNC(); -+ -+ /* Always call ifdown after a handoff to ensure proper routing */ -+ -+ if (!ort) -+ return 0; -+ if ((ortdev = dev_get_by_index(ort->ifindex)) == NULL) { -+ DEBUG(DBG_WARNING, "Device is not present"); -+ return -1; -+ } -+ neigh_ifdown(&nd_tbl, ortdev); -+ dev_put(ortdev); -+ return 0; -+} -+ -+static int mdet_get_if_preference(int ifi) -+{ -+ int pref = 0; -+ -+ DEBUG_FUNC(); -+ -+ pref = ma_ctl_get_preference(ifi); -+ -+ DEBUG(DEBUG_MDETECT, "ifi: %d preference %d", ifi, pref); -+ -+ return pref; -+} -+ -+/* -+ * Called from mipv6_mn_ra_rcv to determine whether to do a handoff. -+ */ -+static int mipv6_router_event(struct router *rptr) -+{ -+ struct router *nrt = NULL; -+ int new_router = 0, same_if = 1; -+ int oldstate = _curr_state; -+ int addrtype = ipv6_addr_type(&rptr->raddr); -+ -+ DEBUG_FUNC(); -+ -+ if (rptr->lifetime == 0) -+ return MIPV6_IGN_RTR; -+ DEBUG(DEBUG_MDETECT, "Received a RA from router: " -+ "%x:%x:%x:%x:%x:%x:%x:%x", NIPV6ADDR(&rptr->raddr)); -+ spin_lock(&router_lock); -+ -+ /* Add or update router entry */ -+ if ((nrt = mipv6_rtr_get(&rptr->raddr)) == NULL) { -+ if (addrtype == IPV6_ADDR_ANY || (nrt = mipv6_rtr_add(rptr)) == NULL) { -+ spin_unlock(&router_lock); -+ return MIPV6_IGN_RTR; -+ } -+ DEBUG(DBG_INFO, "Router not on list,adding it to the list"); -+ new_router = 1; -+ } -+ nrt->last_ra_rcvd = jiffies; -+ nrt->state = ROUTER_REACHABLE; -+ nrt->interval = rptr->interval; -+ nrt->lifetime = rptr->lifetime; -+ nrt->ifindex = rptr->ifindex; -+ nrt->flags = rptr->flags; -+ nrt->glob_addr = rptr->glob_addr; -+ -+ /* Whether from current router */ -+ if (curr_router && curr_router->reachable && -+ is_current_rtr(nrt, curr_router)) { -+ if (nrt->interval) -+ mod_timer(&r_timer, jiffies + (nrt->interval * HZ)/1000); -+ else -+ mod_timer(&r_timer, jiffies + max_rtr_reach_time * HZ); -+ mdet_statemachine(RA_RCVD); -+ spin_unlock(&router_lock); -+ return MIPV6_ADD_RTR; -+ } else if (oldstate == NO_RTR) { -+ rt6_purge_dflt_routers(0); /* For multiple interface case */ -+ DEBUG(DBG_INFO, "No router or router not reachable, switching to new one"); -+ goto handoff; -+ } -+ if (!curr_router) { -+ /* Startup */ -+ goto handoff; -+ } -+ /* Router behind same interface as current one ?*/ -+ same_if = (nrt->ifindex == curr_router->ifindex); -+ /* Switch to new router behind same interface if eager cell -+ * switching is used or if the interface is preferred -+ */ -+ if ((new_router && eager_cell_switching && same_if) || -+ (mdet_get_if_preference(nrt->ifindex) > -+ mdet_get_if_preference(curr_router->ifindex))) { -+ DEBUG(DBG_INFO, "Switching to new router."); -+ goto handoff; -+ } -+ -+ /* No handoff, don't add default route */ -+ DEBUG(DEBUG_MDETECT, "Ignoring RA"); -+ spin_unlock(&router_lock); -+ return MIPV6_IGN_RTR; -+handoff: -+ clean_ncache(nrt, curr_router, same_if); -+ nrt->reachable = 1; -+ if (same_if && change_next_rtr(nrt, curr_router)) { -+ mipv6_do_ll_dad(nrt->ifindex); -+ nrt->flags |= LLADDR_TENTATIVE; -+ } -+ spin_unlock(&router_lock); -+ -+ return MIPV6_CHG_RTR; -+} -+ -+/* -+ * Called from ndisc.c's router_discovery. -+ */ -+ -+static inline int ret_to_ha(struct in6_addr *addr) -+{ -+ int res = 0; -+ struct mn_info *minfo; -+ read_lock(&mn_info_lock); -+ minfo = mipv6_mninfo_get_by_ha(addr); -+ if (minfo != NULL) { -+ spin_lock(&minfo->lock); -+ if (minfo->has_home_reg) { -+ res = 1; -+ } -+ spin_unlock(&minfo->lock); -+ } -+ read_unlock(&mn_info_lock); -+ return res; -+} -+ -+static int mipv6_mn_ra_rcv(struct sk_buff *skb, struct ndisc_options *ndopts) -+{ -+ int ifi = ((struct inet6_skb_parm *)skb->cb)->iif; -+ struct ra_msg *ra = (struct ra_msg *) skb->h.raw; -+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr; -+ struct router nrt; -+ struct in6_addr *ha = NULL; -+ u8 *lladdr = NULL; -+ int res; -+ DEBUG_FUNC(); -+ -+ memset(&nrt, 0, sizeof(struct router)); -+ -+ if (ra->icmph.icmp6_home_agent) { -+ nrt.flags |= ND_RA_FLAG_HA; -+ DEBUG(DBG_DATADUMP, "RA has ND_RA_FLAG_HA up"); -+ } -+ -+ if (ra->icmph.icmp6_addrconf_managed) { -+ nrt.flags |= ND_RA_FLAG_MANAGED; -+ DEBUG(DBG_DATADUMP, "RA has ND_RA_FLAG_MANAGED up"); -+ } -+ -+ if (ra->icmph.icmp6_addrconf_other) { -+ nrt.flags |= ND_RA_FLAG_OTHER; -+ DEBUG(DBG_DATADUMP, "RA has ND_RA_FLAG_OTHER up"); -+ } -+ -+ ipv6_addr_copy(&nrt.ll_addr, saddr); -+ nrt.ifindex = ifi; -+ nrt.lifetime = ntohs(ra->icmph.icmp6_rt_lifetime); -+ -+ if (ndopts->nd_opts_src_lladdr) { -+ lladdr = (u8 *) ndopts->nd_opts_src_lladdr+2; -+ nrt.link_addr_len = skb->dev->addr_len; -+ memcpy(nrt.link_addr, lladdr, nrt.link_addr_len); -+ } -+ if (ndopts->nd_opts_pi) { -+ struct nd_opt_hdr *p; -+ for (p = ndopts->nd_opts_pi; -+ p; -+ p = ndisc_next_option(p, ndopts->nd_opts_pi_end)) { -+ struct prefix_info *pinfo; -+ int update = 0; -+ -+ pinfo = (struct prefix_info *) p; -+ -+ if (!pinfo->autoconf) -+ continue; -+ -+ if ((pinfo->router_address && -+ (update = ret_to_ha(&pinfo->prefix))) || -+ ipv6_addr_type(&nrt.raddr) != IPV6_ADDR_UNICAST) { -+ ipv6_addr_copy(&nrt.raddr, &pinfo->prefix); -+ nrt.pfix_len = pinfo->prefix_len; -+ if (pinfo->router_address) -+ nrt.glob_addr = 1; -+ else -+ nrt.glob_addr = 0; -+ if (update) -+ ha = &pinfo->prefix; -+ DEBUG(DBG_DATADUMP, "Address of the received " -+ "prefix info option: %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(&nrt.raddr)); -+ DEBUG(DBG_DATADUMP, "the length of the prefix is %d", -+ nrt.pfix_len); -+ } -+ } -+ } -+ if (ndopts->nd_opts_rai) { -+ nrt.interval = ntohl(*(__u32 *)(ndopts->nd_opts_rai+4)); -+ DEBUG(DBG_DATADUMP, -+ "received router interval option with interval : %d ", -+ nrt.interval / HZ); -+ -+ if (nrt.interval > MAX_RADV_INTERVAL) { -+ nrt.interval = 0; -+ DEBUG(DBG_DATADUMP, "but we are using: %d, " -+ "because interval>MAX_RADV_INTERVAL", -+ nrt.interval / HZ); -+ } -+ } -+ -+ res = mipv6_router_event(&nrt); -+ -+ if (ha && lladdr) { -+ mipv6_mn_ha_nd_update(__dev_get_by_index(ifi), ha, lladdr); -+ } -+ return res; -+} -+ -+int __init mipv6_initialize_mdetect(void) -+{ -+ -+ DEBUG_FUNC(); -+ -+ spin_lock_init(&router_lock); -+ spin_lock_init(&ho_lock); -+ init_timer(&coa_timer); -+ init_timer(&r_timer); -+ r_timer.expires = jiffies + HZ; -+ add_timer(&r_timer); -+ -+ /* Actual HO, also deletes old routes after the addition of new ones -+ in ndisc */ -+ MIPV6_SETCALL(mipv6_change_router, mipv6_change_router); -+ -+ MIPV6_SETCALL(mipv6_ra_rcv, mipv6_mn_ra_rcv); -+ -+ return 0; -+} -+ -+int __exit mipv6_shutdown_mdetect() -+{ -+ -+ DEBUG_FUNC(); -+ -+ MIPV6_RESETCALL(mipv6_ra_rcv); -+ MIPV6_RESETCALL(mipv6_change_router); -+ spin_lock_bh(&router_lock); -+ spin_lock(&ho_lock); -+ del_timer(&coa_timer); -+ del_timer(&r_timer); -+ /* Free the memory allocated by router list */ -+ list_free(&curr_router); -+ if (_ho) -+ kfree(_ho); -+ spin_unlock(&ho_lock); -+ spin_unlock_bh(&router_lock); -+ return 0; -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mdetect.h linux-2.4.25/net/ipv6/mobile_ip6/mdetect.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/mdetect.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/mdetect.h 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,37 @@ -+/* -+ * MIPL Mobile IPv6 Movement detection module header file -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _MDETECT_H -+#define _MDETECT_H -+ -+struct handoff { -+ int home_address; /* Is the coa a home address */ -+ int ifindex; -+ int plen; -+ struct in6_addr *coa; -+ struct in6_addr rtr_addr; /* Prefix or rtr address if coa is home address */ -+}; -+ -+int mipv6_initialize_mdetect(void); -+ -+int mipv6_shutdown_mdetect(void); -+ -+int mipv6_get_care_of_address(struct in6_addr *homeaddr, struct in6_addr *coa); -+ -+int mipv6_mdet_del_if(int ifindex); -+ -+int mipv6_mdet_finalize_ho(const struct in6_addr *coa, const int ifindex); -+ -+void mipv6_mdet_retrigger_ho(void); -+ -+void mipv6_mdet_set_curr_rtr_reachable(int reachable); -+ -+#endif /* _MDETECT_H */ -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp.c linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,342 @@ -+/** -+ * Generic icmp routines -+ * -+ * Authors: -+ * Jaakko Laine , -+ * Ville Nuorvala -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 "debug.h" -+#include "bcache.h" -+#include "mipv6_icmp.h" -+#include "config.h" -+ -+struct mipv6_icmpv6_msg { -+ struct icmp6hdr icmph; -+ __u8 *data; -+ struct in6_addr *daddr; -+ int len; -+ __u32 csum; -+}; -+ -+#define MIPV6_ICMP_HOP_LIMIT 64 -+ -+static struct socket *mipv6_icmpv6_socket = NULL; -+static __u16 identifier = 0; -+ -+int mipv6_icmpv6_no_rcv(struct sk_buff *skb) -+{ -+ return 0; -+} -+ -+static int mipv6_icmpv6_xmit_holder = -1; -+ -+static int mipv6_icmpv6_xmit_lock_bh(void) -+{ -+ if (!spin_trylock(&mipv6_icmpv6_socket->sk->lock.slock)) { -+ if (mipv6_icmpv6_xmit_holder == smp_processor_id()) -+ return -EAGAIN; -+ spin_lock(&mipv6_icmpv6_socket->sk->lock.slock); -+ } -+ mipv6_icmpv6_xmit_holder = smp_processor_id(); -+ return 0; -+} -+ -+static __inline__ int mipv6_icmpv6_xmit_lock(void) -+{ -+ int ret; -+ local_bh_disable(); -+ ret = mipv6_icmpv6_xmit_lock_bh(); -+ if (ret) -+ local_bh_enable(); -+ return ret; -+} -+ -+static void mipv6_icmpv6_xmit_unlock_bh(void) -+{ -+ mipv6_icmpv6_xmit_holder = -1; -+ spin_unlock(&mipv6_icmpv6_socket->sk->lock.slock); -+} -+ -+static __inline__ void mipv6_icmpv6_xmit_unlock(void) -+{ -+ mipv6_icmpv6_xmit_unlock_bh(); -+ local_bh_enable(); -+} -+ -+ -+/** -+ * mipv6_icmpv6_dest_unreach - Destination Unreachable ICMP error message handler -+ * @skb: buffer containing ICMP error message -+ * -+ * Special Mobile IPv6 ICMP handling. If Correspondent Node receives -+ * persistent ICMP Destination Unreachable messages for a destination -+ * in its Binding Cache, the binding should be deleted. See draft -+ * section 8.8. -+ **/ -+static int mipv6_icmpv6_rcv_dest_unreach(struct sk_buff *skb) -+{ -+ struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw; -+ struct ipv6hdr *ipv6h = (struct ipv6hdr *) (icmph + 1); -+ int left = (skb->tail - skb->h.raw) - sizeof(*icmph)- sizeof(ipv6h); -+ struct ipv6_opt_hdr *eh; -+ struct rt2_hdr *rt2h = NULL; -+ struct in6_addr *daddr = &ipv6h->daddr; -+ struct in6_addr *saddr = &ipv6h->saddr; -+ int hdrlen, nexthdr = ipv6h->nexthdr; -+ struct mipv6_bce bce; -+ DEBUG_FUNC(); -+ -+ eh = (struct ipv6_opt_hdr *) (ipv6h + 1); -+ -+ while (left > 0) { -+ if (nexthdr != NEXTHDR_HOP && nexthdr != NEXTHDR_DEST && -+ nexthdr != NEXTHDR_ROUTING) -+ return 0; -+ -+ hdrlen = ipv6_optlen(eh); -+ if (hdrlen > left) -+ return 0; -+ -+ if (nexthdr == NEXTHDR_ROUTING) { -+ struct ipv6_rt_hdr *rth = (struct ipv6_rt_hdr *) eh; -+ -+ if (rth->type == IPV6_SRCRT_TYPE_2) { -+ if (hdrlen != sizeof(struct rt2_hdr)) -+ return 0; -+ -+ rt2h = (struct rt2_hdr *) rth; -+ -+ if (rt2h->rt_hdr.segments_left > 0) -+ daddr = &rt2h->addr; -+ break; -+ } -+ } -+ /* check for home address option in case this node is a MN */ -+ if (nexthdr == NEXTHDR_DEST) { -+ __u8 *raw = (__u8 *) eh; -+ __u16 i = 2; -+ while (1) { -+ struct mipv6_dstopt_homeaddr *hao; -+ -+ if (i + sizeof (*hao) > hdrlen) -+ break; -+ -+ hao = (struct mipv6_dstopt_homeaddr *) &raw[i]; -+ -+ if (hao->type == MIPV6_TLV_HOMEADDR && -+ hao->length == sizeof(struct in6_addr)) { -+ saddr = &hao->addr; -+ break; -+ } -+ if (hao->type) -+ i += hao->length + 2; -+ else -+ i++; -+ } -+ -+ } -+ nexthdr = eh->nexthdr; -+ eh = (struct ipv6_opt_hdr *) ((u8 *) eh + hdrlen); -+ left -= hdrlen; -+ } -+ if (rt2h == NULL) return 0; -+ -+ if (mipv6_bcache_get(daddr, saddr, &bce) == 0 && !(bce.flags&HOME_REGISTRATION)) { -+ /* A primitive algorithm for detecting persistent ICMP destination unreachable messages */ -+ if (bce.destunr_count && -+ time_after(jiffies, -+ bce.last_destunr + MIPV6_DEST_UNR_IVAL*HZ)) -+ bce.destunr_count = 0; -+ -+ bce.destunr_count++; -+ -+ mipv6_bcache_icmp_err(daddr, saddr, bce.destunr_count); -+ -+ if (bce.destunr_count > MIPV6_MAX_DESTUNREACH && mipv6_bcache_delete(daddr, saddr, CACHE_ENTRY) == 0) { -+ DEBUG(DBG_INFO, "Deleted bcache entry " -+ "%x:%x:%x:%x:%x:%x:%x:%x " -+ "%x:%x:%x:%x:%x:%x:%x:%x (reason: " -+ "%d dest unreachables) ", -+ NIPV6ADDR(daddr), NIPV6ADDR(saddr), bce.destunr_count); -+ } -+ } -+ return 0; -+} -+ -+static int mipv6_icmpv6_getfrag(const void *data, struct in6_addr *saddr, -+ char *buff, unsigned int offset, -+ unsigned int len) -+{ -+ struct mipv6_icmpv6_msg *msg = (struct mipv6_icmpv6_msg *) data; -+ struct icmp6hdr *icmph; -+ __u32 csum; -+ -+ if (offset) { -+ msg->csum = csum_partial_copy_nocheck(msg->data + offset - -+ sizeof(*icmph), buff, -+ len, msg->csum); -+ return 0; -+ } -+ -+ csum = csum_partial_copy_nocheck((__u8 *) &msg->icmph, buff, -+ sizeof(*icmph), msg->csum); -+ -+ csum = csum_partial_copy_nocheck(msg->data, buff + sizeof(*icmph), -+ len - sizeof(*icmph), csum); -+ -+ icmph = (struct icmp6hdr *) buff; -+ -+ icmph->icmp6_cksum = csum_ipv6_magic(saddr, msg->daddr, msg->len, -+ IPPROTO_ICMPV6, csum); -+ return 0; -+} -+ -+/** -+ * mipv6_icmpv6_send - generic icmpv6 message send -+ * @daddr: destination address -+ * @saddr: source address -+ * @type: icmp type -+ * @code: icmp code -+ * @id: packet identifier. If null, uses internal counter to get new id -+ * @data: packet data -+ * @datalen: length of data in bytes -+ */ -+void mipv6_icmpv6_send(struct in6_addr *daddr, struct in6_addr *saddr, int type, -+ int code, __u16 *id, __u16 flags, void *data, int datalen) -+{ -+ struct sock *sk = mipv6_icmpv6_socket->sk; -+ struct flowi fl; -+ struct mipv6_icmpv6_msg msg; -+ -+ DEBUG_FUNC(); -+ -+ fl.proto = IPPROTO_ICMPV6; -+ fl.fl6_dst = daddr; -+ fl.fl6_src = saddr; -+ fl.fl6_flowlabel = 0; -+ fl.uli_u.icmpt.type = type; -+ fl.uli_u.icmpt.code = code; -+ -+ msg.icmph.icmp6_type = type; -+ msg.icmph.icmp6_code = code; -+ msg.icmph.icmp6_cksum = 0; -+ -+ if (id) -+ msg.icmph.icmp6_identifier = htons(*id); -+ else -+ msg.icmph.icmp6_identifier = htons(identifier++); -+ -+ msg.icmph.icmp6_sequence = htons(flags); -+ msg.data = data; -+ msg.csum = 0; -+ msg.len = datalen + sizeof(struct icmp6hdr); -+ msg.daddr = daddr; -+ -+ if (mipv6_icmpv6_xmit_lock()) -+ return; -+ -+ ip6_build_xmit(sk, mipv6_icmpv6_getfrag, &msg, &fl, msg.len, NULL, -1, -+ MSG_DONTWAIT); -+ -+ ICMP6_INC_STATS_BH(Icmp6OutMsgs); -+ mipv6_icmpv6_xmit_unlock(); -+} -+ -+/** -+ * icmp6_rcv - ICMPv6 receive and multiplex -+ * @skb: buffer containing ICMP message -+ * -+ * Generic ICMPv6 receive function to multiplex messages to approriate -+ * handlers. Only used for ICMP messages with special handling in -+ * Mobile IPv6. -+ **/ -+static void icmp6_rcv(struct sk_buff *skb) -+{ -+ struct icmp6hdr *hdr; -+ -+ if (skb_is_nonlinear(skb) && -+ skb_linearize(skb, GFP_ATOMIC) != 0) { -+ kfree_skb(skb); -+ return; -+ } -+ __skb_push(skb, skb->data-skb->h.raw); -+ -+ hdr = (struct icmp6hdr *) skb->h.raw; -+ -+ switch (hdr->icmp6_type) { -+ case ICMPV6_DEST_UNREACH: -+ mipv6_icmpv6_rcv_dest_unreach(skb); -+ break; -+ -+ case ICMPV6_PARAMPROB: -+ mip6_fn.icmpv6_paramprob_rcv(skb); -+ break; -+ -+ case MIPV6_DHAAD_REPLY: -+ mip6_fn.icmpv6_dhaad_rep_rcv(skb); -+ break; -+ -+ case MIPV6_PREFIX_ADV: -+ mip6_fn.icmpv6_pfxadv_rcv(skb); -+ break; -+ -+ case MIPV6_DHAAD_REQUEST: -+ mip6_fn.icmpv6_dhaad_req_rcv(skb); -+ break; -+ -+ case MIPV6_PREFIX_SOLICIT: -+ mip6_fn.icmpv6_pfxsol_rcv(skb); -+ break; -+ } -+} -+ -+int mipv6_icmpv6_init(void) -+{ -+ struct sock *sk; -+ int err; -+ -+ if ((mipv6_icmpv6_socket = sock_alloc()) == NULL) { -+ DEBUG(DBG_ERROR, "Cannot allocate mipv6_icmpv6_socket"); -+ return -1; -+ } -+ mipv6_icmpv6_socket->type = SOCK_RAW; -+ -+ if ((err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMP, -+ &mipv6_icmpv6_socket)) < 0) { -+ DEBUG(DBG_ERROR, "Cannot initialize mipv6_icmpv6_socket"); -+ sock_release(mipv6_icmpv6_socket); -+ mipv6_icmpv6_socket = NULL; /* For safety */ -+ return err; -+ } -+ sk = mipv6_icmpv6_socket->sk; -+ sk->allocation = GFP_ATOMIC; -+ sk->prot->unhash(sk); -+ -+ /* Register our ICMP handler */ -+ MIPV6_SETCALL(mipv6_icmp_rcv, icmp6_rcv); -+ return 0; -+} -+ -+void mipv6_icmpv6_exit(void) -+{ -+ MIPV6_RESETCALL(mipv6_icmp_rcv); -+ if (mipv6_icmpv6_socket) -+ sock_release(mipv6_icmpv6_socket); -+ mipv6_icmpv6_socket = NULL; /* For safety */ -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp.h linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp.h 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,43 @@ -+/* -+ * MIPL Mobile IPv6 ICMP send and receive prototypes -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _MIPV6_ICMP -+#define _MIPV6_ICMP -+ -+#include -+#include -+ -+void mipv6_icmpv6_send(struct in6_addr *daddr, struct in6_addr *saddr, -+ int type, int code, __u16 *id, __u16 flags, -+ void *data, int datalen); -+ -+void mipv6_icmpv6_send_dhaad_req(struct in6_addr *home_addr, int plen, __u16 dhaad_id); -+ -+void mipv6_icmpv6_send_dhaad_rep(int ifindex, __u16 id, struct in6_addr *daddr); -+/* No handling */ -+int mipv6_icmpv6_no_rcv(struct sk_buff *skb); -+ -+/* Receive DHAAD Reply message */ -+int mipv6_icmpv6_rcv_dhaad_rep(struct sk_buff *skb); -+/* Receive Parameter Problem message */ -+int mipv6_icmpv6_rcv_paramprob(struct sk_buff *skb); -+/* Receive prefix advertisements */ -+int mipv6_icmpv6_rcv_pfx_adv(struct sk_buff *skb); -+ -+/* Receive DHAAD Request message */ -+int mipv6_icmpv6_rcv_dhaad_req(struct sk_buff *skb); -+/* Receive prefix solicitations */ -+int mipv6_icmpv6_rcv_pfx_sol(struct sk_buff *skb); -+ -+int mipv6_icmpv6_init(void); -+void mipv6_icmpv6_exit(void); -+ -+#endif -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp_ha.c linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp_ha.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp_ha.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp_ha.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,158 @@ -+/* -+ * Home Agent specific ICMP routines -+ * -+ * Authors: -+ * Antti Tuominen -+ * Jaakko Laine -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 "halist.h" -+#include "debug.h" -+#include "mipv6_icmp.h" -+//#include "prefix.h" -+ -+/* Is this the easiest way of checking on -+ * which interface an anycast address is ? -+ */ -+static int find_ac_dev(struct in6_addr *addr) -+{ -+ int ifindex = 0; -+ struct net_device *dev; -+ read_lock(&dev_base_lock); -+ for (dev=dev_base; dev; dev=dev->next) { -+ if (ipv6_chk_acast_addr(dev, addr)) { -+ ifindex = dev->ifindex; -+ break; -+ } -+ } -+ read_unlock(&dev_base_lock); -+ return ifindex; -+} -+ -+/** -+ * mipv6_icmpv6_send_dhaad_rep - Reply to DHAAD Request -+ * @ifindex: index of interface request was received from -+ * @id: request's identification number -+ * @daddr: requester's IPv6 address -+ * -+ * When Home Agent receives Dynamic Home Agent Address Discovery -+ * request, it replies with a list of home agents available on the -+ * home link. -+ */ -+void mipv6_icmpv6_send_dhaad_rep(int ifindex, __u16 id, struct in6_addr *daddr) -+{ -+ __u8 *data = NULL; -+ struct in6_addr home, *ha_addrs = NULL; -+ int addr_count, max_addrs, size = 0; -+ -+ if (daddr == NULL) -+ return; -+ -+ if (mipv6_ha_get_addr(ifindex, &home) < 0) { -+ DEBUG(DBG_INFO, "Not Home Agent in this interface"); -+ return; -+ } -+ -+ /* We send all available HA addresses, not exceeding a maximum -+ * number we can fit in a packet with minimum IPv6 MTU (to -+ * avoid fragmentation). -+ */ -+ max_addrs = 76; -+ addr_count = mipv6_ha_get_pref_list(ifindex, &ha_addrs, max_addrs); -+ -+ if (addr_count < 0) return; -+ -+ if (addr_count != 0 && ha_addrs == NULL) { -+ DEBUG(DBG_ERROR, "addr_count = %d but return no addresses", -+ addr_count); -+ return; -+ } -+ data = (u8 *)ha_addrs; -+ -+ size = addr_count * sizeof(struct in6_addr); -+ -+ mipv6_icmpv6_send(daddr, &home, MIPV6_DHAAD_REPLY, -+ 0, &id, 0, data, size); -+ if (ha_addrs) { -+ data = NULL; -+ kfree(ha_addrs); -+ } -+} -+ -+/** -+ * mipv6_icmpv6_dhaad_req - Home Agent Address Discovery Request ICMP handler -+ * @skb: buffer containing ICMP information message -+ * -+ * Special Mobile IPv6 ICMP message. Handles Dynamic Home Agent -+ * Address Discovery Request messages. -+ **/ -+int mipv6_icmpv6_rcv_dhaad_req(struct sk_buff *skb) -+{ -+ struct icmp6hdr *phdr = (struct icmp6hdr *) skb->h.raw; -+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr; -+ struct in6_addr *daddr = &skb->nh.ipv6h->daddr; -+ __u16 identifier; -+ int ifindex = 0; -+ -+ DEBUG_FUNC(); -+ -+ /* Invalid packet checks. */ -+ if (phdr->icmp6_code != 0) -+ return 0; -+ -+ identifier = ntohs(phdr->icmp6_identifier); -+ -+ /* -+ * Make sure we have the right ifindex (if the -+ * req came through another interface. -+ */ -+ ifindex = find_ac_dev(daddr); -+ if (ifindex == 0) { -+ DEBUG(DBG_WARNING, "received dhaad request to anycast address %x:%x:%x:%x:%x:%x:%x:%x" -+ " on which prefix we are not HA", -+ NIPV6ADDR(daddr)); -+ return 0; -+ } -+ -+ /* -+ * send reply with list -+ */ -+ mipv6_icmpv6_send_dhaad_rep(ifindex, identifier, saddr); -+ return 1; -+} -+#if 0 -+/** -+ * mipv6_icmpv6_handle_pfx_sol - handle prefix solicitations -+ * @skb: sk_buff including the icmp6 message -+ */ -+int mipv6_icmpv6_rcv_pfx_sol(struct sk_buff *skb) -+{ -+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr; -+ struct in6_addr *daddr = &skb->nh.ipv6h->daddr; -+ struct inet6_ifaddr *ifp; -+ -+ DEBUG_FUNC(); -+ -+ if (!(ifp = ipv6_get_ifaddr(daddr, NULL))) -+ return -1; -+ -+ in6_ifa_put(ifp); -+ mipv6_pfx_cancel_send(saddr, -1); -+ -+ return 0; -+} -+#endif -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp_mn.c linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp_mn.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp_mn.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp_mn.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,273 @@ -+/* -+ * Mobile Node specific ICMP routines -+ * -+ * Authors: -+ * Antti Tuominen -+ * Jaakko Laine -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 "mn.h" -+#include "bul.h" -+#include "mdetect.h" -+#include "debug.h" -+#include "mipv6_icmp.h" -+#include "util.h" -+//#include "prefix.h" -+ -+#define INFINITY 0xffffffff -+ -+/** -+ * mipv6_icmpv6_paramprob - Parameter Problem ICMP error message handler -+ * @skb: buffer containing ICMP error message -+ * -+ * Special Mobile IPv6 ICMP handling. If Mobile Node receives ICMP -+ * Parameter Problem message when using a Home Address Option, -+ * offending node should be logged and error message dropped. If -+ * error is received because of a Binding Update, offending node -+ * should be recorded in Binding Update List and no more Binding -+ * Updates should be sent to this destination. See RFC 3775 section -+ * 10.15. -+ **/ -+int mipv6_icmpv6_rcv_paramprob(struct sk_buff *skb) -+{ -+ struct icmp6hdr *phdr = (struct icmp6hdr *) skb->h.raw; -+ struct in6_addr *saddr = skb ? &skb->nh.ipv6h->saddr : NULL; -+ struct in6_addr *daddr = skb ? &skb->nh.ipv6h->daddr : NULL; -+ struct ipv6hdr *hdr = (struct ipv6hdr *) (phdr + 1); -+ int ulen = (skb->tail - (unsigned char *) (phdr + 1)); -+ -+ int errptr; -+ __u8 *off_octet; -+ -+ DEBUG_FUNC(); -+ -+ /* We only handle code 1 & 2 messages. */ -+ if (phdr->icmp6_code != ICMPV6_UNK_NEXTHDR && -+ phdr->icmp6_code != ICMPV6_UNK_OPTION) -+ return 0; -+ -+ /* Find offending octet in the original packet. */ -+ errptr = ntohl(phdr->icmp6_pointer); -+ -+ /* There is not enough of the original packet left to figure -+ * out what went wrong. Bail out. */ -+ if (ulen <= errptr) -+ return 0; -+ -+ off_octet = ((__u8 *) hdr + errptr); -+ DEBUG(DBG_INFO, "Parameter problem: offending octet %d [0x%2x]", -+ errptr, *off_octet); -+ -+ /* If CN did not understand Mobility Header, set BUL entry to -+ * ACK_ERROR so no further BUs are sumbitted to this CN. */ -+ if (phdr->icmp6_code == ICMPV6_UNK_NEXTHDR && -+ *off_octet == IPPROTO_MOBILITY) { -+ struct bul_inval_args args; -+ args.all_rr_states = 1; -+ args.cn = saddr; -+ args.mn = daddr; -+ write_lock(&bul_lock); -+ mipv6_bul_iterate(mn_bul_invalidate, &args); -+ write_unlock(&bul_lock); -+ } -+ -+ /* If CN did not understand Home Address Option, we log an -+ * error and discard the error message. */ -+ if (phdr->icmp6_code == ICMPV6_UNK_OPTION && -+ *off_octet == MIPV6_TLV_HOMEADDR) { -+ DEBUG(DBG_WARNING, "Correspondent node does not " -+ "implement Home Address Option receipt."); -+ return 1; -+ } -+ return 0; -+} -+ -+/** -+ * mipv6_mn_dhaad_send_req - Send DHAAD Request to home network -+ * @home_addr: address to do DHAAD for -+ * @plen: prefix length for @home_addr -+ * -+ * Send Dynamic Home Agent Address Discovery Request to the Home -+ * Agents anycast address in the nodes home network. -+ **/ -+void -+mipv6_icmpv6_send_dhaad_req(struct in6_addr *home_addr, int plen, __u16 dhaad_id) -+{ -+ struct in6_addr ha_anycast; -+ struct in6_addr careofaddr; -+ -+ if (mipv6_get_care_of_address(home_addr, &careofaddr) < 0) { -+ DEBUG(DBG_WARNING, "Could not get node's Care-of Address"); -+ return; -+ } -+ -+ if (mipv6_ha_anycast(&ha_anycast, home_addr, plen) < 0) { -+ DEBUG(DBG_WARNING, -+ "Could not get Home Agent Anycast address for home address %x:%x.%x:%x:%x:%x:%x:%x/%d", -+ NIPV6ADDR(home_addr), plen); -+ return; -+ } -+ -+ mipv6_icmpv6_send(&ha_anycast, &careofaddr, MIPV6_DHAAD_REQUEST, 0, -+ &dhaad_id, 0, NULL, 0); -+ -+} -+ -+/** -+ * mipv6_icmpv6_dhaad_rep - Home Agent Address Discovery Reply ICMP handler -+ * @skb: buffer containing ICMP information message -+ * -+ * Special Mobile IPv6 ICMP message. Handles Dynamic Home Agent -+ * Address Discovery Reply messages. -+ **/ -+int mipv6_icmpv6_rcv_dhaad_rep(struct sk_buff *skb) -+{ -+ struct icmp6hdr *phdr = (struct icmp6hdr *) skb->h.raw; -+ struct in6_addr *address; -+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr; -+ __u16 identifier; -+ int ulen = (skb->tail - (unsigned char *) ((__u32 *) phdr + 2)); -+ int i; -+ struct in6_addr home_addr, coa; -+ struct in6_addr *first_ha = NULL; -+ struct mn_info *minfo; -+ int n_addr = ulen / sizeof(struct in6_addr); -+ -+ DEBUG_FUNC(); -+ -+ /* Invalid packet checks. */ -+ if (ulen % sizeof(struct in6_addr) != 0) -+ return 0; -+ -+ if (phdr->icmp6_code != 0) -+ return 0; -+ -+ identifier = ntohs(phdr->icmp6_identifier); -+ if (ulen > 0) { -+ address = (struct in6_addr *) ((__u32 *) phdr + 2); -+ } else { -+ address = saddr; -+ n_addr = 1; -+ } -+ -+ /* receive list of home agent addresses -+ * add to home agents list -+ */ -+ DEBUG(DBG_INFO, "DHAAD: got %d home agents", n_addr); -+ -+ first_ha = address; -+ -+ /* lookup H@ with identifier */ -+ read_lock(&mn_info_lock); -+ minfo = mipv6_mninfo_get_by_id(identifier); -+ if (!minfo) { -+ read_unlock(&mn_info_lock); -+ DEBUG(DBG_INFO, "no mninfo with id %d", -+ identifier); -+ return 0; -+ } -+ spin_lock(&minfo->lock); -+ -+ /* Logic: -+ * 1. if old HA on list, prefer it -+ * 2. otherwise first HA on list prefered -+ */ -+ for (i = 0; i < n_addr; i++) { -+ DEBUG(DBG_INFO, "HA[%d] %x:%x:%x:%x:%x:%x:%x:%x", -+ i, NIPV6ADDR(address)); -+ if (ipv6_addr_cmp(&minfo->ha, address) == 0) { -+ spin_unlock(&minfo->lock); -+ read_unlock(&mn_info_lock); -+ return 0; -+ } -+ address++; -+ } -+ ipv6_addr_copy(&minfo->ha, first_ha); -+ spin_unlock(&minfo->lock); -+ ipv6_addr_copy(&home_addr, &minfo->home_addr); -+ read_unlock(&mn_info_lock); -+ -+ mipv6_get_care_of_address(&home_addr, &coa); -+ init_home_registration(&home_addr, &coa); -+ -+ return 1; -+} -+#if 0 -+/** -+ * mipv6_icmpv6_handle_pfx_adv - handle prefix advertisements -+ * @skb: sk_buff including the icmp6 message -+ */ -+int mipv6_icmpv6_rcv_pfx_adv(struct sk_buff *skb) -+{ -+ struct icmp6hdr *hdr = (struct icmp6hdr *) skb->h.raw; -+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr; -+ struct in6_addr *daddr = &skb->nh.ipv6h->daddr; -+ __u8 *opt = (__u8 *) (hdr + 1); -+ int optlen = (skb->tail - opt); -+ unsigned long min_expire = INFINITY; -+ struct inet6_skb_parm *parm = (struct inet6_skb_parm *) skb->cb; -+ -+ DEBUG_FUNC(); -+ -+ while (optlen > 0) { -+ int len = opt[1] << 3; -+ if (len == 0) -+ goto set_timer; -+ -+ if (opt[0] == ND_OPT_PREFIX_INFO) { -+ int ifindex; -+ unsigned long expire; -+ struct prefix_info *pinfo = -+ (struct prefix_info *) opt; -+ struct net_device *dev; -+ struct mn_info *mninfo; -+ -+ read_lock(&mn_info_lock); -+ mninfo = mipv6_mninfo_get_by_ha(saddr); -+ if (mninfo == NULL) { -+ ifindex = 0; -+ } else { -+ spin_lock(&mninfo->lock); -+ ifindex = mninfo->ifindex; -+ spin_unlock(&mninfo->lock); -+ mninfo = NULL; -+ } -+ read_unlock(&mn_info_lock); -+ -+ if (!(dev = dev_get_by_index(ifindex))) { -+ DEBUG(DBG_WARNING, "Cannot find device by index %d", parm->iif); -+ goto nextopt; -+ } -+ -+ expire = ntohl(pinfo->valid); -+ expire = expire == 0 ? INFINITY : expire; -+ -+ min_expire = expire < min_expire ? expire : min_expire; -+ -+ dev_put(dev); -+ } -+ -+nextopt: -+ optlen -= len; -+ opt += len; -+ } -+ -+set_timer: -+ -+ mipv6_pfx_add_home(parm->iif, saddr, daddr, min_expire); -+ return 0; -+} -+#endif -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mn.c linux-2.4.25/net/ipv6/mobile_ip6/mn.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/mn.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/mn.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,1521 @@ -+/* -+ * Mobile-node functionality -+ * -+ * Authors: -+ * Sami Kivisaari -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "util.h" -+#include "mdetect.h" -+#include "bul.h" -+#include "mobhdr.h" -+#include "debug.h" -+#include "mn.h" -+#include "mipv6_icmp.h" -+#include "multiaccess_ctl.h" -+//#include "prefix.h" -+#include "tunnel_mn.h" -+#include "stats.h" -+#include "config.h" -+ -+#define MIPV6_BUL_SIZE 128 -+ -+static LIST_HEAD(mn_info_list); -+ -+/* Lock for list of MN infos */ -+rwlock_t mn_info_lock = RW_LOCK_UNLOCKED; -+ -+static spinlock_t ifrh_lock = SPIN_LOCK_UNLOCKED; -+ -+struct ifr_holder { -+ struct list_head list; -+ struct in6_ifreq ifr; -+ int old_ifi; -+ struct handoff *ho; -+}; -+ -+LIST_HEAD(ifrh_list); -+ -+static struct tq_struct mv_home_addr_task; -+ -+/* Determines whether manually configured home addresses are preferred as -+ * source addresses over dynamically configured ones -+ */ -+int mipv6_use_preconfigured_hoaddr = 1; -+ -+/* Determines whether home addresses, which are at home are preferred as -+ * source addresses over other home addresses -+ */ -+int mipv6_use_topol_corr_hoaddr = 0; -+ -+static spinlock_t icmpv6_id_lock = SPIN_LOCK_UNLOCKED; -+static __u16 icmpv6_id = 0; -+ -+static inline __u16 mipv6_get_dhaad_id(void) -+{ -+ __u16 ret; -+ spin_lock_bh(&icmpv6_id_lock); -+ ret = ++icmpv6_id; -+ spin_unlock_bh(&icmpv6_id_lock); -+ return ret; -+} -+ -+/** -+ * mipv6_mninfo_get_by_home - Returns mn_info for a home address -+ * @haddr: home address of MN -+ * -+ * Returns mn_info on success %NULL otherwise. Caller MUST hold -+ * @mn_info_lock (read or write). -+ **/ -+struct mn_info *mipv6_mninfo_get_by_home(struct in6_addr *haddr) -+{ -+ struct list_head *lh; -+ struct mn_info *minfo; -+ -+ DEBUG_FUNC(); -+ -+ if (!haddr) -+ return NULL; -+ -+ list_for_each(lh, &mn_info_list) { -+ minfo = list_entry(lh, struct mn_info, list); -+ spin_lock(&minfo->lock); -+ if (!ipv6_addr_cmp(&minfo->home_addr, haddr)) { -+ spin_unlock(&minfo->lock); -+ return minfo; -+ } -+ spin_unlock(&minfo->lock); -+ } -+ return NULL; -+} -+ -+/** -+ * mipv6_mninfo_get_by_ha - Lookup mn_info with Home Agent address -+ * @home_agent: Home Agent address -+ * -+ * Searches for a mn_info entry with @ha set to @home_agent. You MUST -+ * hold @mn_info_lock when calling this function. Returns pointer to -+ * mn_info entry or %NULL on failure. -+ **/ -+struct mn_info *mipv6_mninfo_get_by_ha(struct in6_addr *home_agent) -+{ -+ struct list_head *lh; -+ struct mn_info *minfo; -+ -+ if (!home_agent) -+ return NULL; -+ -+ list_for_each(lh, &mn_info_list) { -+ minfo = list_entry(lh, struct mn_info, list); -+ spin_lock(&minfo->lock); -+ if (!ipv6_addr_cmp(&minfo->ha, home_agent)) { -+ spin_unlock(&minfo->lock); -+ return minfo; -+ } -+ spin_unlock(&minfo->lock); -+ } -+ return NULL; -+} -+ -+/** -+ * mipv6_mninfo_get_by_id - Lookup mn_info with id -+ * @id: DHAAD identifier -+ * -+ * Searches for a mn_info entry with @dhaad_id set to @id. You MUST -+ * hold @mn_info_lock when calling this function. Returns pointer to -+ * mn_info entry or %NULL on failure. -+ **/ -+struct mn_info *mipv6_mninfo_get_by_id(unsigned short id) -+{ -+ struct list_head *lh; -+ struct mn_info *minfo = 0; -+ -+ list_for_each(lh, &mn_info_list) { -+ minfo = list_entry(lh, struct mn_info, list); -+ spin_lock(&minfo->lock); -+ if (minfo->dhaad_id == id) { -+ spin_unlock(&minfo->lock); -+ return minfo; -+ } -+ spin_unlock(&minfo->lock); -+ } -+ return NULL; -+} -+ -+/** -+ * mipv6_mninfo_add - Adds a new home info for MN -+ * @ifindex: Interface for home address -+ * @home_addr: Home address of MN, must be set -+ * @plen: prefix length of the home address, must be set -+ * @isathome : home address at home -+ * @lifetime: lifetime of the home address, 0 is infinite -+ * @ha: home agent for the home address -+ * @ha_plen: prefix length of home agent's address, can be zero -+ * @ha_lifetime: Lifetime of the home address, 0 is infinite -+ * -+ * The function adds a new home info entry for MN, allowing it to -+ * register the home address with the home agent. Starts home -+ * registration process. If @ha is %ADDRANY, DHAAD is performed to -+ * find a home agent. Returns 0 on success, a negative value -+ * otherwise. Caller MUST NOT hold @mn_info_lock or -+ * @addrconf_hash_lock. -+ **/ -+void mipv6_mninfo_add(int ifindex, struct in6_addr *home_addr, int plen, -+ int isathome, unsigned long lifetime, struct in6_addr *ha, -+ int ha_plen, unsigned long ha_lifetime, int man_conf) -+{ -+ struct mn_info *minfo; -+ struct in6_addr coa; -+ -+ DEBUG_FUNC(); -+ -+ write_lock_bh(&mn_info_lock); -+ if ((minfo = mipv6_mninfo_get_by_home(home_addr)) != NULL){ -+ DEBUG(1, "MN info already exists"); -+ write_unlock_bh(&mn_info_lock); -+ return; -+ } -+ minfo = kmalloc(sizeof(struct mn_info), GFP_ATOMIC); -+ if (!minfo) { -+ write_unlock_bh(&mn_info_lock); -+ return; -+ } -+ memset(minfo, 0, sizeof(struct mn_info)); -+ spin_lock_init(&minfo->lock); -+ -+ -+ ipv6_addr_copy(&minfo->home_addr, home_addr); -+ -+ if (ha) -+ ipv6_addr_copy(&minfo->ha, ha); -+ if (ha_plen < 128 && ha_plen > 0) -+ minfo->home_plen = ha_plen; -+ else minfo->home_plen = 64; -+ -+ minfo->ifindex_user = ifindex; /* Ifindex for tunnel interface */ -+ minfo->ifindex = ifindex; /* Interface on which home address is currently conf'd */ -+ /* TODO: we should get home address lifetime from somewhere */ -+ /* minfo->home_addr_expires = jiffies + lifetime * HZ; */ -+ -+ /* manual configuration flag cannot be unset by dynamic updates -+ * from prefix advertisements -+ */ -+ if (!minfo->man_conf) minfo->man_conf = man_conf; -+ minfo->is_at_home = isathome; -+ -+ list_add(&minfo->list, &mn_info_list); -+ write_unlock_bh(&mn_info_lock); -+ -+ if (mipv6_get_care_of_address(home_addr, &coa) == 0) -+ init_home_registration(home_addr, &coa); -+} -+ -+/** -+ * mipv6_mninfo_del - Delete home info for MN -+ * @home_addr : Home address or prefix -+ * @del_dyn_only : Delete only dynamically created home entries -+ * -+ * Deletes every mn_info entry that matches the first plen bits of -+ * @home_addr. Returns number of deleted entries on success and a -+ * negative value otherwise. Caller MUST NOT hold @mn_info_lock. -+ **/ -+int mipv6_mninfo_del(struct in6_addr *home_addr, int del_dyn_only) -+{ -+ struct list_head *lh, *next; -+ struct mn_info *minfo; -+ int ret = -1; -+ if (!home_addr) -+ return -1; -+ -+ write_lock(&mn_info_lock); -+ -+ list_for_each_safe(lh, next, &mn_info_list) { -+ minfo = list_entry(lh, struct mn_info, list); -+ if (ipv6_addr_cmp(&minfo->home_addr, home_addr) == 0 -+ && ((!minfo->man_conf && del_dyn_only) || !del_dyn_only)){ -+ list_del(&minfo->list); -+ kfree(minfo); -+ ret++; -+ } -+ } -+ write_unlock(&mn_info_lock); -+ return ret; -+} -+ -+void mipv6_mn_set_home(int ifindex, struct in6_addr *homeaddr, int plen, -+ struct in6_addr *homeagent, int ha_plen) -+{ -+ mipv6_mninfo_add(ifindex, homeaddr, plen, 0, 0, -+ homeagent, ha_plen, 0, 1); -+} -+ -+static int skip_dad(struct in6_addr *addr) -+{ -+ struct mn_info *minfo; -+ int ret = 0; -+ -+ if (addr == NULL) { -+ DEBUG(DBG_CRITICAL, "Null argument"); -+ return 0; -+ } -+ read_lock_bh(&mn_info_lock); -+ if ((minfo = mipv6_mninfo_get_by_home(addr)) != NULL) { -+ if ((minfo->is_at_home != MN_NOT_AT_HOME) && (minfo->has_home_reg)) -+ ret = 1; -+ DEBUG(DBG_INFO, "minfo->is_at_home = %d, minfo->has_home_reg = %d", -+ minfo->is_at_home, minfo->has_home_reg); -+ } -+ read_unlock_bh(&mn_info_lock); -+ -+ return ret; -+} -+/** -+ * mipv6_mn_is_home_addr - Determines if addr is node's home address -+ * @addr: IPv6 address -+ * -+ * Returns 1 if addr is node's home address. Otherwise returns zero. -+ **/ -+int mipv6_mn_is_home_addr(struct in6_addr *addr) -+{ -+ int ret = 0; -+ -+ if (addr == NULL) { -+ DEBUG(DBG_CRITICAL, "Null argument"); -+ return -1; -+ } -+ read_lock_bh(&mn_info_lock); -+ if (mipv6_mninfo_get_by_home(addr)) -+ ret = 1; -+ read_unlock_bh(&mn_info_lock); -+ -+ return (ret); -+} -+ -+/** -+ * mipv6_mn_is_at_home - determine if node is home for a home address -+ * @home_addr : home address of MN -+ * -+ * Returns 1 if home address in question is in the home network, 0 -+ * otherwise. Caller MUST NOT not hold @mn_info_lock. -+ **/ -+int mipv6_mn_is_at_home(struct in6_addr *home_addr) -+{ -+ struct mn_info *minfo; -+ int ret = 0; -+ read_lock_bh(&mn_info_lock); -+ if ((minfo = mipv6_mninfo_get_by_home(home_addr)) != NULL) { -+ spin_lock(&minfo->lock); -+ ret = (minfo->is_at_home == MN_AT_HOME); -+ spin_unlock(&minfo->lock); -+ } -+ read_unlock_bh(&mn_info_lock); -+ return ret; -+} -+void mipv6_mn_set_home_reg(struct in6_addr *home_addr, int has_home_reg) -+{ -+ struct mn_info *minfo; -+ read_lock_bh(&mn_info_lock); -+ -+ if ((minfo = mipv6_mninfo_get_by_home(home_addr)) != NULL) { -+ spin_lock(&minfo->lock); -+ minfo->has_home_reg = has_home_reg; -+ spin_unlock(&minfo->lock); -+ } -+ read_unlock_bh(&mn_info_lock); -+} -+ -+static int mn_inet6addr_event( -+ struct notifier_block *nb, unsigned long event, void *ptr) -+{ -+ struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)ptr; -+ -+ switch (event) { -+ case NETDEV_UP: -+ /* Is address a valid coa ?*/ -+ if (!(ifp->flags & IFA_F_TENTATIVE)) -+ mipv6_mdet_finalize_ho(&ifp->addr, -+ ifp->idev->dev->ifindex); -+ else if(skip_dad(&ifp->addr)) -+ ifp->flags &= ~IFA_F_TENTATIVE; -+ break; -+ case NETDEV_DOWN: -+#if 0 -+ /* This is useless with manually configured home -+ addresses, which will not expire -+ */ -+ mipv6_mninfo_del(&ifp->addr, 0); -+#endif -+ break; -+ -+ } -+ -+ return NOTIFY_DONE; -+} -+ -+struct notifier_block mipv6_mn_inet6addr_notifier = { -+ mn_inet6addr_event, -+ NULL, -+ 0 /* check if using zero is ok */ -+}; -+ -+static void mipv6_get_saddr_hook(struct in6_addr *homeaddr) -+{ -+ int found = 0, reiter = 0; -+ struct list_head *lh; -+ struct mn_info *minfo = NULL; -+ struct in6_addr coa; -+ -+ read_lock_bh(&mn_info_lock); -+restart: -+ list_for_each(lh, &mn_info_list) { -+ minfo = list_entry(lh, struct mn_info, list); -+ if ((ipv6_addr_scope(homeaddr) != ipv6_addr_scope(&minfo->home_addr)) -+ || ipv6_chk_addr(&minfo->home_addr, NULL) == 0) -+ continue; -+ -+ spin_lock(&minfo->lock); -+ if (minfo->is_at_home == MN_AT_HOME || minfo->has_home_reg) { -+ if ((mipv6_use_topol_corr_hoaddr && -+ minfo->is_at_home == MN_AT_HOME) || -+ (mipv6_use_preconfigured_hoaddr && -+ minfo->man_conf) || -+ (!(mipv6_use_preconfigured_hoaddr || -+ mipv6_use_topol_corr_hoaddr) || reiter)) { -+ spin_unlock(&minfo->lock); -+ ipv6_addr_copy(homeaddr, &minfo->home_addr); -+ found = 1; -+ break; -+ } -+ } -+ spin_unlock(&minfo->lock); -+ } -+ if (!found && !reiter) { -+ reiter = 1; -+ goto restart; -+ } -+ -+ if (!found && minfo && -+ !mipv6_get_care_of_address(&minfo->home_addr, &coa)) { -+ ipv6_addr_copy(homeaddr, &coa); -+ } -+ read_unlock_bh(&mn_info_lock); -+ -+ DEBUG(DBG_DATADUMP, "Source address selection: %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(homeaddr)); -+ return; -+} -+ -+static void mv_home_addr(void *arg) -+{ -+ mm_segment_t oldfs; -+ int err = 0, new_if = 0; -+ struct list_head *lh, *next; -+ struct ifr_holder *ifrh; -+ LIST_HEAD(list); -+ -+ DEBUG(DBG_INFO, "mipv6 move home address task"); -+ -+ spin_lock_bh(&ifrh_lock); -+ list_splice_init(&ifrh_list, &list); -+ spin_unlock_bh(&ifrh_lock); -+ -+ oldfs = get_fs(); set_fs(KERNEL_DS); -+ list_for_each_safe(lh, next, &list) { -+ ifrh = list_entry(lh, struct ifr_holder, list); -+ if (ifrh->old_ifi) { -+ new_if = ifrh->ifr.ifr6_ifindex; -+ ifrh->ifr.ifr6_ifindex = ifrh->old_ifi; -+ err = addrconf_del_ifaddr(&ifrh->ifr); -+ ifrh->ifr.ifr6_ifindex = new_if; -+ if (err < 0) -+ DEBUG(DBG_WARNING, "removal of home address %x:%x:%x:%x:%x:%x:%x:%x from" -+ " old interface %d failed with status %d", -+ NIPV6ADDR(&ifrh->ifr.ifr6_addr), ifrh->old_ifi, err); -+ } -+ if(!err) { -+ err = addrconf_add_ifaddr(&ifrh->ifr); -+ } -+ if (ifrh->ho) { -+ DEBUG(DBG_INFO, "Calling mobile_node moved after moving home address to new if"); -+ mipv6_mobile_node_moved(ifrh->ho); -+ } -+ list_del(&ifrh->list); -+ kfree(ifrh); -+ } -+ set_fs(oldfs); -+ -+ if (err < 0) -+ DEBUG(DBG_WARNING, "adding of home address to a new interface %d failed %d", new_if, err); -+ else { -+ DEBUG(DBG_WARNING, "adding of home address to a new interface OK"); -+ } -+} -+ -+struct dhaad_halist { -+ struct list_head list; -+ struct in6_addr addr; -+ int retry; -+}; -+ -+/* clear all has from candidate list. do this when a new dhaad reply -+ * is received. */ -+int mipv6_mn_flush_ha_candidate(struct list_head *ha) -+{ -+ struct list_head *p, *tmp; -+ struct dhaad_halist *e; -+ -+ list_for_each_safe(p, tmp, ha) { -+ e = list_entry(p, struct dhaad_halist, list); -+ list_del(p); -+ kfree(e); -+ e = NULL; -+ } -+ return 0; -+} -+ -+/* add new ha to candidates. only done when dhaad reply is received. */ -+int mipv6_mn_add_ha_candidate(struct list_head *ha, struct in6_addr *addr) -+{ -+ struct dhaad_halist *e; -+ -+ e = kmalloc(sizeof(*e), GFP_ATOMIC); -+ memset(e, 0, sizeof(*e)); -+ ipv6_addr_copy(&e->addr, addr); -+ -+ list_add_tail(&e->list, ha); -+ return 0; -+} -+ -+#define MAX_RETRIES_PER_HA 3 -+ -+/* get next ha candidate. this is done when dhaad reply has been -+ * received and we want to register with the best available ha. */ -+int mipv6_mn_get_ha_candidate(struct list_head *ha, struct in6_addr *addr) -+{ -+ struct list_head *p; -+ -+ list_for_each(p, ha) { -+ struct dhaad_halist *e; -+ e = list_entry(p, typeof(*e), list); -+ if (e->retry >= 0 && e->retry < MAX_RETRIES_PER_HA) { -+ ipv6_addr_copy(addr, &e->addr); -+ return 0; -+ } -+ } -+ return -1; -+} -+ -+/* change candidate status. if registration with ha fails, we -+ * increase retry for ha candidate. if retry is >= 3 we set it to -1 -+ * (failed), do get_ha_candidate() again */ -+int mipv6_mn_try_ha_candidate(struct list_head *ha, struct in6_addr *addr) -+{ -+ struct list_head *p; -+ -+ list_for_each(p, ha) { -+ struct dhaad_halist *e; -+ e = list_entry(p, typeof(*e), list); -+ if (ipv6_addr_cmp(addr, &e->addr) == 0) { -+ if (e->retry >= MAX_RETRIES_PER_HA) e->retry = -1; -+ else if (e->retry >= 0) e->retry++; -+ return 0; -+ } -+ } -+ return -1; -+} -+ -+/** -+ * mipv6_mn_get_bulifetime - Get lifetime for a binding update -+ * @home_addr: home address for BU -+ * @coa: care-of address for BU -+ * @flags: flags used for BU -+ * -+ * Returns maximum lifetime for BUs determined by the lifetime of -+ * care-of address and the lifetime of home address. -+ **/ -+__u32 mipv6_mn_get_bulifetime(struct in6_addr *home_addr, struct in6_addr *coa, -+ __u8 flags) -+{ -+ struct inet6_ifaddr *ifp_hoa, *ifp_coa; -+ __u32 lifetime = (flags & MIPV6_BU_F_HOME ? -+ HA_BU_DEF_LIFETIME : CN_BU_DEF_LIFETIME); -+ -+ ifp_hoa = ipv6_get_ifaddr(home_addr, NULL); -+ if(!ifp_hoa) { -+ DEBUG(DBG_INFO, "home address missing"); -+ return 0; -+ } -+ if (!(ifp_hoa->flags & IFA_F_PERMANENT)){ -+ if (ifp_hoa->valid_lft) -+ lifetime = min_t(__u32, lifetime, ifp_hoa->valid_lft); -+ else -+ DEBUG(DBG_ERROR, "Zero lifetime for home address"); -+ } -+ in6_ifa_put(ifp_hoa); -+ -+ ifp_coa = ipv6_get_ifaddr(coa, NULL); -+ if (!ifp_coa) { -+ DEBUG(DBG_INFO, "care-of address missing"); -+ return 0; -+ } -+ if (!(ifp_coa->flags & IFA_F_PERMANENT)) { -+ if(ifp_coa->valid_lft) -+ lifetime = min_t(__u32, lifetime, ifp_coa->valid_lft); -+ else -+ DEBUG(DBG_ERROR, -+ "Zero lifetime for care-of address"); -+ } -+ in6_ifa_put(ifp_coa); -+ -+ DEBUG(DBG_INFO, "Lifetime for binding is %ld", lifetime); -+ return lifetime; -+} -+ -+static int -+mipv6_mn_tnl_rcv_send_bu_hook(struct ip6_tnl *t, struct sk_buff *skb) -+{ -+ struct ipv6hdr *inner; -+ struct ipv6hdr *outer = skb->nh.ipv6h; -+ struct mn_info *minfo = NULL; -+ __u32 lifetime; -+ __u8 user_flags = 0; -+ -+ DEBUG_FUNC(); -+ -+ if (!is_mip6_tnl(t)) -+ return IP6_TNL_ACCEPT; -+ -+ if (!mip6node_cnf.accept_ret_rout) { -+ DEBUG(DBG_INFO, "Return routability administratively disabled" -+ " not doing route optimization"); -+ return IP6_TNL_ACCEPT; -+ } -+ if (!pskb_may_pull(skb, skb->h.raw-skb->data+sizeof(*inner))) -+ return IP6_TNL_DROP; -+ -+ inner = (struct ipv6hdr *)skb->h.raw; -+ -+ read_lock(&mn_info_lock); -+ minfo = mipv6_mninfo_get_by_home(&inner->daddr); -+ -+ if (!minfo) { -+ DEBUG(DBG_WARNING, "MN info missing"); -+ read_unlock(&mn_info_lock); -+ return IP6_TNL_ACCEPT; -+ } -+ DEBUG(DBG_DATADUMP, "MIPV6 MN: Received a tunneled IPv6 packet" -+ " to %x:%x:%x:%x:%x:%x:%x:%x," -+ " from %x:%x:%x:%x:%x:%x:%x:%x with\n tunnel header" -+ "daddr: %x:%x:%x:%x:%x:%x:%x:%x," -+ "saddr: %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(&inner->daddr), NIPV6ADDR(&inner->saddr), -+ NIPV6ADDR(&outer->daddr), NIPV6ADDR(&outer->saddr)); -+ -+ spin_lock(&minfo->lock); -+ -+ /* We don't send bus in response to all tunneled packets */ -+ -+ if (!ipv6_addr_cmp(&minfo->ha, &inner->saddr)) { -+ spin_unlock(&minfo->lock); -+ read_unlock(&mn_info_lock); -+ DEBUG(DBG_ERROR, "HA BUG: Received a tunneled packet " -+ "originally sent by home agent, not sending BU"); -+ return IP6_TNL_ACCEPT; -+ } -+ spin_unlock(&minfo->lock); -+ read_unlock(&mn_info_lock); -+ -+ DEBUG(DBG_DATADUMP, "Sending BU to correspondent node"); -+ -+ user_flags |= mip6node_cnf.bu_cn_ack ? MIPV6_BU_F_ACK : 0; -+ -+ if (inner->nexthdr != IPPROTO_DSTOPTS && -+ inner->nexthdr != IPPROTO_MOBILITY) { -+ struct in6_addr coa; -+ /* Don't start RR when receiving ICMP error messages */ -+ if (inner->nexthdr == IPPROTO_ICMPV6) { -+ int ptr = (u8*)(inner+1) - skb->data; -+ u8 type; -+ -+ if (skb_copy_bits(skb, -+ ptr+offsetof(struct icmp6hdr, -+ icmp6_type), -+ &type, 1) -+ || !(type & ICMPV6_INFOMSG_MASK)) { -+ return IP6_TNL_ACCEPT; -+ } -+ } -+ lifetime = mipv6_mn_get_bulifetime(&inner->daddr, -+ &outer->daddr, 0); -+ if (lifetime && -+ !mipv6_get_care_of_address(&inner->daddr, &coa)) { -+ write_lock(&bul_lock); -+ mipv6_send_bu(&inner->daddr, &inner->saddr, &coa, -+ INITIAL_BINDACK_TIMEOUT, -+ MAX_BINDACK_TIMEOUT, 1, -+ user_flags, -+ lifetime, NULL); -+ write_unlock(&bul_lock); -+ } -+ } -+ DEBUG(DBG_DATADUMP, "setting rcv_tunnel flag in skb"); -+ skb->security |= MIPV6_RCV_TUNNEL; -+ return IP6_TNL_ACCEPT; -+} -+ -+static struct ip6_tnl_hook_ops mipv6_mn_tnl_rcv_send_bu_ops = { -+ {NULL, NULL}, -+ IP6_TNL_PRE_DECAP, -+ IP6_TNL_PRI_FIRST, -+ mipv6_mn_tnl_rcv_send_bu_hook -+}; -+ -+static int -+mipv6_mn_tnl_xmit_stats_hook(struct ip6_tnl *t, struct sk_buff *skb) -+{ -+ DEBUG_FUNC(); -+ if (is_mip6_tnl(t)) -+ MIPV6_INC_STATS(n_encapsulations); -+ return IP6_TNL_ACCEPT; -+} -+ -+static struct ip6_tnl_hook_ops mipv6_mn_tnl_xmit_stats_ops = { -+ {NULL, NULL}, -+ IP6_TNL_PRE_ENCAP, -+ IP6_TNL_PRI_LAST, -+ mipv6_mn_tnl_xmit_stats_hook -+}; -+ -+static int -+mipv6_mn_tnl_rcv_stats_hook(struct ip6_tnl *t, struct sk_buff *skb) -+{ -+ DEBUG_FUNC(); -+ if (is_mip6_tnl(t)) -+ MIPV6_INC_STATS(n_decapsulations); -+ return IP6_TNL_ACCEPT; -+} -+ -+static struct ip6_tnl_hook_ops mipv6_mn_tnl_rcv_stats_ops = { -+ {NULL, NULL}, -+ IP6_TNL_PRE_DECAP, -+ IP6_TNL_PRI_LAST, -+ mipv6_mn_tnl_rcv_stats_hook -+}; -+ -+static void mn_check_tunneled_packet(struct sk_buff *skb) -+{ -+ DEBUG_FUNC(); -+ /* If tunnel flag was set */ -+ if (skb->security & MIPV6_RCV_TUNNEL) { -+ struct in6_addr coa; -+ __u32 lifetime; -+ __u8 user_flags = 0; -+ int ptr = (u8*)(skb->nh.ipv6h+1) - skb->data; -+ int len = skb->len - ptr; -+ __u8 nexthdr = skb->nh.ipv6h->nexthdr; -+ -+ if (len < 0) -+ return; -+ -+ ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, len); -+ if (ptr < 0) -+ return; -+ -+ if (!mip6node_cnf.accept_ret_rout) { -+ DEBUG(DBG_INFO, "Return routability administratively disabled"); -+ return; -+ } -+ if (nexthdr == IPPROTO_MOBILITY) -+ return; -+ -+ /* Don't start RR when receiving ICMP error messages */ -+ if (nexthdr == IPPROTO_ICMPV6) { -+ u8 type; -+ -+ if (skb_copy_bits(skb, -+ ptr+offsetof(struct icmp6hdr, -+ icmp6_type), -+ &type, 1) -+ || !(type & ICMPV6_INFOMSG_MASK)) { -+ return; -+ } -+ } -+ user_flags |= mip6node_cnf.bu_cn_ack ? MIPV6_BU_F_ACK : 0; -+ mipv6_get_care_of_address(&skb->nh.ipv6h->daddr, &coa); -+ lifetime = mipv6_mn_get_bulifetime(&skb->nh.ipv6h->daddr, -+ &coa, 0); -+ -+ DEBUG(DBG_WARNING, "packet to address %x:%x:%x:%x:%x:%x:%x:%x" -+ "was tunneled. Sending BU to CN" -+ "%x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(&skb->nh.ipv6h->daddr), -+ NIPV6ADDR(&skb->nh.ipv6h->saddr)); -+ /* This should work also with home address option */ -+ -+ write_lock(&bul_lock); -+ mipv6_send_bu(&skb->nh.ipv6h->daddr, &skb->nh.ipv6h->saddr, -+ &coa, INITIAL_BINDACK_TIMEOUT, -+ MAX_BINDACK_TIMEOUT, 1, user_flags, -+ lifetime, NULL); -+ write_unlock(&bul_lock); -+ } -+} -+ -+static int sched_mv_home_addr_task(struct in6_addr *haddr, int plen_new, -+ int newif, int oldif, struct handoff *ho) -+{ -+ int alloc_size; -+ struct ifr_holder *ifrh; -+ -+ alloc_size = sizeof(*ifrh) + (ho ? sizeof(*ho): 0); -+ if ((ifrh = kmalloc(alloc_size, GFP_ATOMIC)) == NULL) { -+ DEBUG(DBG_ERROR, "Out of memory"); -+ return -1; -+ } -+ if (ho) { -+ ifrh->ho = (struct handoff *)((struct ifr_holder *)(ifrh + 1)); -+ memcpy(ifrh->ho, ho, sizeof(*ho)); -+ } else -+ ifrh->ho = NULL; -+ -+ /* must queue task to avoid deadlock with rtnl */ -+ ifrh->ifr.ifr6_ifindex = newif; -+ ifrh->ifr.ifr6_prefixlen = plen_new; -+ ipv6_addr_copy(&ifrh->ifr.ifr6_addr, haddr); -+ ifrh->old_ifi = oldif; -+ -+ spin_lock_bh(&ifrh_lock); -+ list_add_tail(&ifrh->list, &ifrh_list); -+ spin_unlock_bh(&ifrh_lock); -+ -+ schedule_task(&mv_home_addr_task); -+ -+ return 0; -+} -+ -+static void send_ret_home_ns(struct in6_addr *ha_addr, -+ struct in6_addr *home_addr, -+ int ifindex) -+{ -+ struct in6_addr nil; -+ struct in6_addr mcaddr; -+ struct net_device *dev = dev_get_by_index(ifindex); -+ if (!dev) -+ return; -+ memset(&nil, 0, sizeof(nil)); -+ addrconf_addr_solict_mult(home_addr, &mcaddr); -+ ndisc_send_ns(dev, NULL, home_addr, &mcaddr, &nil); -+ dev_put(dev); -+} -+ -+static inline int ha_is_reachable(int ifindex, struct in6_addr *ha) -+{ -+ struct net_device *dev; -+ int reachable = 0; -+ -+ dev = dev_get_by_index(ifindex); -+ if (dev) { -+ struct neighbour *neigh; -+ if ((neigh = ndisc_get_neigh(dev, ha)) != NULL) { -+ read_lock_bh(&neigh->lock); -+ if (neigh->nud_state&NUD_VALID) -+ reachable = 1; -+ read_unlock_bh(&neigh->lock); -+ neigh_release(neigh); -+ } -+ dev_put(dev); -+ } -+ return reachable; -+} -+ -+static int mn_ha_handoff(struct handoff *ho) -+{ -+ struct list_head *lh; -+ struct mn_info *minfo; -+ struct in6_addr *coa= ho->coa; -+ int wait_mv_home = 0; -+ -+ read_lock_bh(&mn_info_lock); -+ list_for_each(lh, &mn_info_list) { -+ __u8 has_home_reg; -+ int ifindex; -+ struct in6_addr ha; -+ __u8 athome; -+ __u32 lifetime; -+ struct mipv6_bul_entry *entry = NULL; -+ -+ minfo = list_entry(lh, struct mn_info, list); -+ spin_lock(&minfo->lock); -+ has_home_reg = minfo->has_home_reg; -+ ifindex = minfo->ifindex; -+ ipv6_addr_copy(&ha, &minfo->ha); -+ -+ if (mipv6_prefix_compare(&ho->rtr_addr, &minfo->home_addr, -+ ho->plen)) { -+ if (minfo->has_home_reg) -+ athome = minfo->is_at_home = MN_RETURNING_HOME; -+ else -+ athome = minfo->is_at_home = MN_AT_HOME; -+ coa = &minfo->home_addr; -+ -+ spin_unlock(&minfo->lock); -+#if 0 -+ /* Cancel prefix solicitation, rtr is our HA */ -+ mipv6_pfx_cancel_send(&ho->rtr_addr, ifindex); -+#endif -+ minfo->ifindex = ho->ifindex; -+ -+ if (minfo->has_home_reg && -+ !ha_is_reachable(ho->ifindex, &minfo->ha)) { -+ send_ret_home_ns(&minfo->ha, -+ &minfo->home_addr, -+ ho->ifindex); -+ mipv6_mdet_set_curr_rtr_reachable(0); -+ wait_mv_home++; -+ } -+ if (ifindex != ho->ifindex){ -+ wait_mv_home++; -+ DEBUG(DBG_INFO, -+ "Moving home address back to " -+ "the home interface"); -+ sched_mv_home_addr_task(&minfo->home_addr, -+ 128, -+ ho->ifindex, -+ ifindex, ho); -+ } -+ if (!has_home_reg || wait_mv_home) -+ continue; -+ -+ lifetime = 0; -+ -+ } else { -+ athome = minfo->is_at_home = MN_NOT_AT_HOME; -+ if (minfo->ifindex_user != minfo->ifindex) { -+ DEBUG(DBG_INFO, "Scheduling home address move to virtual interface"); -+ sched_mv_home_addr_task(&minfo->home_addr, -+ 128, -+ minfo->ifindex_user, -+ minfo->ifindex, ho); /* Is minfo->ifindex correct */ -+ -+ wait_mv_home++; -+ } -+ minfo->ifindex = minfo->ifindex_user; -+ spin_unlock(&minfo->lock); -+ if (wait_mv_home) -+ continue; -+ if (!has_home_reg && -+ init_home_registration(&minfo->home_addr, -+ ho->coa)) { -+ continue; -+ } -+ lifetime = mipv6_mn_get_bulifetime(&minfo->home_addr, -+ ho->coa, -+ MIPV6_BU_F_HOME); -+ -+ } -+ write_lock(&bul_lock); -+ if (!(entry = mipv6_bul_get(&ha, &minfo->home_addr)) || -+ !(entry->flags & MIPV6_BU_F_HOME)) { -+ DEBUG(DBG_ERROR, -+ "Unable to find home registration for " -+ "home address: %x:%x:%x:%x:%x:%x:%x:%x!\n", -+ NIPV6ADDR(&minfo->home_addr)); -+ write_unlock(&bul_lock); -+ continue; -+ } -+ DEBUG(DBG_INFO, "Sending home de ? %d registration for " -+ "home address: %x:%x:%x:%x:%x:%x:%x:%x\n" -+ "to home agent %x:%x:%x:%x:%x:%x:%x:%x, " -+ "with lifetime %ld", -+ (athome != MN_NOT_AT_HOME), -+ NIPV6ADDR(&entry->home_addr), -+ NIPV6ADDR(&entry->cn_addr), lifetime); -+ mipv6_send_bu(&entry->home_addr, &entry->cn_addr, -+ coa, INITIAL_BINDACK_TIMEOUT, -+ MAX_BINDACK_TIMEOUT, 1, entry->flags, -+ lifetime, NULL); -+ write_unlock(&bul_lock); -+ -+ } -+ read_unlock_bh(&mn_info_lock); -+ return wait_mv_home; -+} -+/** -+ * mn_cn_handoff - called for every bul entry to send BU to CN -+ * @rawentry: bul entry -+ * @args: handoff event -+ * @sortkey: -+ * -+ * Since MN can have many home addresses and home networks, every BUL -+ * entry needs to be checked -+ **/ -+int mn_cn_handoff(void *rawentry, void *args, unsigned long *sortkey) -+{ -+ struct mipv6_bul_entry *entry = (struct mipv6_bul_entry *)rawentry; -+ struct in6_addr *coa = (struct in6_addr *)args; -+ -+ DEBUG_FUNC(); -+ -+ /* Home registrations already handled by mn_ha_handoff */ -+ if (entry->flags & MIPV6_BU_F_HOME) -+ return ITERATOR_CONT; -+ -+ /* BUL is locked by mipv6_mobile_node_moved which calls us -+ through mipv6_bul_iterate */ -+ -+ if (mipv6_prefix_compare(coa, -+ &entry->home_addr, -+ 64)) { -+ mipv6_send_bu(&entry->home_addr, &entry->cn_addr, -+ &entry->home_addr, INITIAL_BINDACK_TIMEOUT, -+ MAX_BINDACK_TIMEOUT, 1, entry->flags, 0, -+ NULL); -+ } else { -+ u32 lifetime = mipv6_mn_get_bulifetime(&entry->home_addr, -+ coa, -+ entry->flags); -+ mipv6_send_bu(&entry->home_addr, &entry->cn_addr, -+ coa, INITIAL_BINDACK_TIMEOUT, -+ MAX_BINDACK_TIMEOUT, 1, entry->flags, -+ lifetime, NULL); -+ } -+ return ITERATOR_CONT; -+} -+ -+ -+int mn_bul_invalidate(void *rawentry, void *args, unsigned long *sortkey) -+{ -+ struct mipv6_bul_entry *bul = (struct mipv6_bul_entry *)rawentry; -+ struct bul_inval_args *arg = (struct bul_inval_args *)args; -+ -+ DEBUG_FUNC(); -+ -+ if (!ipv6_addr_cmp(arg->cn, &bul->cn_addr) && -+ (!ipv6_addr_cmp(arg->mn, &bul->home_addr) || -+ !ipv6_addr_cmp(arg->mn, &bul->coa))) { -+ if (arg->all_rr_states || !bul->rr || -+ (bul->rr->rr_state != RR_INIT && -+ bul->rr->rr_state != RR_DONE)) { -+ bul->state = ACK_ERROR; -+ bul->callback = bul_entry_expired; -+ bul->callback_time = jiffies + -+ DUMB_CN_BU_LIFETIME * HZ; -+ bul->expire = bul->callback_time; -+ DEBUG(DBG_INFO, "BUL entry set to ACK_ERROR"); -+ mipv6_bul_reschedule(bul); -+ } -+ } -+ return ITERATOR_CONT; -+} -+/** -+ * init_home_registration - start Home Registration process -+ * @home_addr: home address -+ * @coa: care-of address -+ * -+ * Checks whether we have a Home Agent address for this home address. -+ * If not starts Dynamic Home Agent Address Discovery. Otherwise -+ * tries to register with home agent if not already registered. -+ * Returns 1, if home registration process is started and 0 otherwise -+ **/ -+int init_home_registration(struct in6_addr *home_addr, struct in6_addr *coa) -+{ -+ struct mn_info *hinfo; -+ struct in6_addr ha; -+ __u8 man_conf; -+ int ifindex; -+ __u32 lifetime; -+ __u8 user_flags = 0, flags; -+ -+ DEBUG_FUNC(); -+ -+ read_lock_bh(&mn_info_lock); -+ if ((hinfo = mipv6_mninfo_get_by_home(home_addr)) == NULL) { -+ DEBUG(DBG_ERROR, "No mn_info found for address: " -+ "%x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(home_addr)); -+ read_unlock_bh(&mn_info_lock); -+ return -ENOENT; -+ } -+ spin_lock(&hinfo->lock); -+ if (mipv6_prefix_compare(&hinfo->home_addr, coa, hinfo->home_plen)) { -+ spin_unlock(&hinfo->lock); -+ read_unlock_bh(&mn_info_lock); -+ DEBUG(DBG_INFO, "Adding home address, MN at home"); -+ return 1; -+ } -+ if (ipv6_addr_any(&hinfo->ha)) { -+ int dhaad_id = mipv6_get_dhaad_id(); -+ hinfo->dhaad_id = dhaad_id; -+ spin_unlock(&hinfo->lock); -+ mipv6_icmpv6_send_dhaad_req(home_addr, hinfo->home_plen, dhaad_id); -+ read_unlock_bh(&mn_info_lock); -+ DEBUG(DBG_INFO, -+ "Home Agent address not set, initiating DHAAD"); -+ return 1; -+ } -+ ipv6_addr_copy(&ha, &hinfo->ha); -+ man_conf = hinfo->man_conf; -+ ifindex = hinfo->ifindex; -+ spin_unlock(&hinfo->lock); -+ read_unlock_bh(&mn_info_lock); -+#if 0 -+ if (man_conf) -+ mipv6_pfx_add_ha(&ha, coa, ifindex); -+#endif -+ if (mipv6_bul_exists(&ha, home_addr)) { -+ DEBUG(DBG_INFO, "BU already sent to HA"); -+ return 0; -+ } -+ /* user flags received through sysctl */ -+ user_flags |= mip6node_cnf.bu_lladdr ? MIPV6_BU_F_LLADDR : 0; -+ user_flags |= mip6node_cnf.bu_keymgm ? MIPV6_BU_F_KEYMGM : 0; -+ -+ flags = MIPV6_BU_F_HOME | MIPV6_BU_F_ACK | user_flags; -+ -+ lifetime = mipv6_mn_get_bulifetime(home_addr, coa, flags); -+ -+ DEBUG(DBG_INFO, "Sending initial home registration for " -+ "home address: %x:%x:%x:%x:%x:%x:%x:%x\n" -+ "to home agent %x:%x:%x:%x:%x:%x:%x:%x, " -+ "with lifetime %ld, prefixlength %d", -+ NIPV6ADDR(home_addr), NIPV6ADDR(&ha), lifetime, 0); -+ -+ write_lock_bh(&bul_lock); -+ mipv6_send_bu(home_addr, &ha, coa, INITIAL_BINDACK_DAD_TIMEOUT, -+ MAX_BINDACK_TIMEOUT, 1, flags, lifetime, NULL); -+ write_unlock_bh(&bul_lock); -+ -+ return 1; -+} -+ -+/** -+ * mipv6_mobile_node_moved - Send BUs to all HAs and CNs -+ * @ho: handoff structure contains the new and previous routers -+ * -+ * Event for handoff. Sends BUs everyone on Binding Update List. -+ **/ -+int mipv6_mobile_node_moved(struct handoff *ho) -+{ -+#if 0 -+ int bu_to_prev_router = 1; -+#endif -+ int dummy; -+ -+ DEBUG_FUNC(); -+ -+ ma_ctl_upd_iface(ho->ifindex, -+ MA_IFACE_CURRENT | MA_IFACE_HAS_ROUTER, &dummy); -+ -+ /* First send BU to HA, then to all other nodes that are on BU list */ -+ if (mn_ha_handoff(ho) != 0) -+ return 0; /* Wait for move home address task */ -+#if 0 -+ /* Add current care-of address to mn_info list, if current router acts -+ as a HA.*/ -+ -+ if (ho->home_address && bu_to_prev_router) -+ mipv6_mninfo_add(ho->coa, ho->plen, -+ MN_AT_HOME, 0, &ho->rtr_addr, -+ ho->plen, ROUTER_BU_DEF_LIFETIME, -+ 0); -+ -+#endif -+ return 0; -+} -+ -+/** -+ * mipv6_mn_send_home_na - send NA when returning home -+ * @haddr: home address to advertise -+ * -+ * After returning home, MN must advertise all its valid addresses in -+ * home link to all nodes. -+ **/ -+void mipv6_mn_send_home_na(struct in6_addr *haddr) -+{ -+ struct net_device *dev = NULL; -+ struct in6_addr mc_allnodes; -+ struct mn_info *hinfo = NULL; -+ -+ read_lock(&mn_info_lock); -+ hinfo = mipv6_mninfo_get_by_home(haddr); -+ if (!hinfo) { -+ read_unlock(&mn_info_lock); -+ return; -+ } -+ spin_lock(&hinfo->lock); -+ hinfo->is_at_home = MN_AT_HOME; -+ dev = dev_get_by_index(hinfo->ifindex); -+ spin_unlock(&hinfo->lock); -+ read_unlock(&mn_info_lock); -+ if (dev == NULL) { -+ DEBUG(DBG_ERROR, "Send home_na: device not found."); -+ return; -+ } -+ -+ ipv6_addr_all_nodes(&mc_allnodes); -+ ndisc_send_na(dev, NULL, &mc_allnodes, haddr, 0, 0, 1, 1); -+ dev_put(dev); -+} -+ -+static int mn_use_hao(struct in6_addr *daddr, struct in6_addr *saddr) -+{ -+ struct mipv6_bul_entry *entry; -+ struct mn_info *minfo = NULL; -+ int add_ha = 0; -+ -+ read_lock_bh(&mn_info_lock); -+ minfo = mipv6_mninfo_get_by_home(saddr); -+ if (minfo && minfo->is_at_home != MN_AT_HOME) { -+ read_lock_bh(&bul_lock); -+ if ((entry = mipv6_bul_get(daddr, saddr)) == NULL) { -+ read_unlock_bh(&bul_lock); -+ read_unlock_bh(&mn_info_lock); -+ return add_ha; -+ } -+ add_ha = (entry->state != ACK_ERROR && -+ (!entry->rr || entry->rr->rr_state == RR_DONE || -+ entry->flags & MIPV6_BU_F_HOME)); -+ read_unlock_bh(&bul_lock); -+ } -+ read_unlock_bh(&mn_info_lock); -+ return add_ha; -+} -+ -+static int -+mn_dev_event(struct notifier_block *nb, unsigned long event, void *ptr) -+{ -+ struct net_device *dev = ptr; -+ struct list_head *lh; -+ struct mn_info *minfo; -+ int newif = 0; -+ -+ /* here are probably the events we need to worry about */ -+ switch (event) { -+ case NETDEV_UP: -+ DEBUG(DBG_DATADUMP, "New netdevice %s registered.", dev->name); -+ if (dev->type != ARPHRD_LOOPBACK && !dev_is_mip6_tnl(dev)) -+ ma_ctl_add_iface(dev->ifindex); -+ -+ break; -+ case NETDEV_GOING_DOWN: -+ DEBUG(DBG_DATADUMP, "Netdevice %s disappeared.", dev->name); -+ /* -+ * Go through mn_info list and move all home addresses on the -+ * netdev going down to a new device. This will make it -+ * practically impossible for the home address to return home, -+ * but allow MN to retain its connections using the address. -+ */ -+ -+ read_lock_bh(&mn_info_lock); -+ list_for_each(lh, &mn_info_list) { -+ minfo = list_entry(lh, struct mn_info, list); -+ spin_lock(&minfo->lock); -+ if (minfo->ifindex == dev->ifindex) { -+ if (sched_mv_home_addr_task(&minfo->home_addr, 128, -+ minfo->ifindex_user, -+ 0, NULL) < 0) { -+ minfo->ifindex = 0; -+ spin_unlock(&minfo->lock); -+ read_unlock_bh(&mn_info_lock); -+ return NOTIFY_DONE; -+ } else { -+ minfo->ifindex = minfo->ifindex_user; -+ if (minfo->is_at_home) { -+ minfo->is_at_home = 0; -+ -+ } -+ newif = minfo->ifindex_user; -+ } -+ } -+ spin_unlock(&minfo->lock); -+ } -+ -+ read_unlock_bh(&mn_info_lock); -+ } -+ ma_ctl_upd_iface(dev->ifindex, MA_IFACE_NOT_PRESENT, &newif); -+ mipv6_mdet_del_if(dev->ifindex); -+ -+ return NOTIFY_DONE; -+} -+ -+struct notifier_block mipv6_mn_dev_notifier = { -+ mn_dev_event, -+ NULL, -+ 0 /* check if using zero is ok */ -+}; -+ -+static void deprecate_addr(struct mn_info *minfo) -+{ -+ /* -+ * Lookup address from IPv6 address list and set deprecated flag -+ */ -+ -+} -+ -+/* -+ * Required because we can only modify addresses after the packet is -+ * constructed. We otherwise mess with higher level protocol -+ * pseudoheaders. With strict protocol layering life would be SO much -+ * easier! -+ */ -+static unsigned int modify_xmit_addrs(unsigned int hooknum, -+ struct sk_buff **pskb, -+ const struct net_device *in, -+ const struct net_device *out, -+ int (*okfn) (struct sk_buff *)) -+{ -+ struct sk_buff *skb = *pskb; -+ -+ DEBUG_FUNC(); -+ -+ if (skb) { -+ struct ipv6hdr *hdr = skb->nh.ipv6h; -+ struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; -+ struct mipv6_bul_entry *bule; -+ struct in6_addr *daddr; -+ -+ if (!ipv6_addr_any(&opt->hoa)) -+ daddr = &opt->hoa; -+ else -+ daddr = &hdr->daddr; -+ -+ /* We don't consult bul when sending a BU to avoid deadlock, since -+ * BUL is already locked. -+ */ -+ -+ -+ if (opt->mipv6_flags & MIPV6_SND_HAO && -+ !(opt->mipv6_flags & MIPV6_SND_BU)) { -+ write_lock(&bul_lock); -+ bule = mipv6_bul_get(daddr, &hdr->saddr); -+ if (!bule) { -+ write_unlock(&bul_lock); -+ return NF_ACCEPT; -+ } -+ if (!bule->rr || bule->rr->rr_state == RR_DONE || -+ bule->flags & MIPV6_BU_F_HOME) { -+ DEBUG(DBG_DATADUMP, -+ "Replace source address with CoA and reroute"); -+ ipv6_addr_copy(&hdr->saddr, &bule->coa); -+ skb->nfcache |= NFC_ALTERED; -+ } -+ write_unlock(&bul_lock); -+ } else if (opt->mipv6_flags & MIPV6_SND_HAO) { -+ mipv6_get_care_of_address(&hdr->saddr, &hdr->saddr); -+ skb->nfcache |= NFC_ALTERED; -+ } -+ } -+ return NF_ACCEPT; -+} -+ -+/* We set a netfilter hook so that we can modify outgoing packet's -+ * source addresses -+ */ -+struct nf_hook_ops addr_modify_hook_ops = { -+ {NULL, NULL}, /* List head, no predecessor, no successor */ -+ modify_xmit_addrs, -+ PF_INET6, -+ NF_IP6_LOCAL_OUT, -+ NF_IP6_PRI_FIRST /* Should be of EXTREMELY high priority since we -+ * do not want to mess with IPSec (possibly -+ * implemented as packet filter) -+ */ -+}; -+ -+#define MN_INFO_LEN 77 -+ -+static int mn_proc_info(char *buffer, char **start, off_t offset, -+ int length) -+{ -+ struct list_head *p; -+ struct mn_info *minfo; -+ int len = 0, skip = 0; -+ -+ DEBUG_FUNC(); -+ -+ read_lock_bh(&mn_info_lock); -+ list_for_each(p, &mn_info_list) { -+ if (len < offset / MN_INFO_LEN) { -+ skip++; -+ continue; -+ } -+ if (len >= length) -+ break; -+ minfo = list_entry(p, struct mn_info, list); -+ spin_lock(&minfo->lock); -+ len += sprintf(buffer + len, "%02d %08x%08x%08x%08x %02x " -+ "%08x%08x%08x%08x %d %d\n", -+ minfo->ifindex, -+ ntohl(minfo->home_addr.s6_addr32[0]), -+ ntohl(minfo->home_addr.s6_addr32[1]), -+ ntohl(minfo->home_addr.s6_addr32[2]), -+ ntohl(minfo->home_addr.s6_addr32[3]), -+ minfo->home_plen, -+ ntohl(minfo->ha.s6_addr32[0]), -+ ntohl(minfo->ha.s6_addr32[1]), -+ ntohl(minfo->ha.s6_addr32[2]), -+ ntohl(minfo->ha.s6_addr32[3]), -+ minfo->is_at_home, minfo->has_home_reg); -+ spin_unlock(&minfo->lock); -+ } -+ read_unlock_bh(&mn_info_lock); -+ -+ *start = buffer; -+ if (offset) -+ *start += offset % MN_INFO_LEN; -+ -+ len -= offset % MN_INFO_LEN; -+ -+ if (len > length) -+ len = length; -+ if (len < 0) -+ len = 0; -+ -+ return len; -+} -+ -+int mipv6_mn_ha_nd_update(struct net_device *dev, -+ struct in6_addr *ha, u8 *lladdr) -+{ -+ int valid = 0; -+ struct neighbour *neigh; -+ if ((neigh = ndisc_get_neigh(dev, ha))) { -+ read_lock(&neigh->lock); -+ valid = neigh->nud_state & NUD_VALID; -+ read_unlock(&neigh->lock); -+ if (!valid && lladdr) -+ neigh_update(neigh, lladdr, NUD_REACHABLE, 0, 1); -+ neigh_release(neigh); -+ } -+ return valid; -+} -+ -+int mipv6_mn_ha_probe(struct inet6_ifaddr *ifp, u8 *lladdr) -+{ -+ struct mn_info *minfo; -+ -+ if (!(minfo = mipv6_mninfo_get_by_home(&ifp->addr)) || -+ ipv6_addr_any(&minfo->ha)) -+ return 0; -+ -+ if (mipv6_mn_ha_nd_update(ifp->idev->dev, &minfo->ha, lladdr)) -+ mipv6_mdet_retrigger_ho(); -+ return 1; -+} -+ -+int __init mipv6_mn_init(void) -+{ -+ struct net_device *dev; -+ -+ DEBUG_FUNC(); -+ -+ if (mipv6_add_tnl_to_ha()) -+ return -ENODEV; -+ -+ mipv6_bul_init(MIPV6_BUL_SIZE); -+ mip6_fn.mn_use_hao = mn_use_hao; -+ mip6_fn.mn_check_tunneled_packet = mn_check_tunneled_packet; -+ INIT_TQUEUE(&mv_home_addr_task, mv_home_addr, NULL); -+ -+ ma_ctl_init(); -+ for (dev = dev_base; dev; dev = dev->next) { -+ if (dev->flags & IFF_UP && -+ dev->type != ARPHRD_LOOPBACK && !dev_is_mip6_tnl(dev)) { -+ ma_ctl_add_iface(dev->ifindex); -+ } -+ } -+ DEBUG(DBG_INFO, "Multiaccess support initialized"); -+ -+ register_netdevice_notifier(&mipv6_mn_dev_notifier); -+ register_inet6addr_notifier(&mipv6_mn_inet6addr_notifier); -+ -+ ip6ip6_tnl_register_hook(&mipv6_mn_tnl_rcv_send_bu_ops); -+ ip6ip6_tnl_register_hook(&mipv6_mn_tnl_xmit_stats_ops); -+ ip6ip6_tnl_register_hook(&mipv6_mn_tnl_rcv_stats_ops); -+ -+ MIPV6_SETCALL(mipv6_set_home, mipv6_mn_set_home); -+ -+ mipv6_initialize_mdetect(); -+ -+ /* COA to home transformation hook */ -+ MIPV6_SETCALL(mipv6_get_home_address, mipv6_get_saddr_hook); -+ MIPV6_SETCALL(mipv6_mn_ha_probe, mipv6_mn_ha_probe); -+ MIPV6_SETCALL(mipv6_is_home_addr, mipv6_mn_is_home_addr); -+ proc_net_create("mip6_mninfo", 0, mn_proc_info); -+ /* Set packet modification hook (source addresses) */ -+ nf_register_hook(&addr_modify_hook_ops); -+ -+ return 0; -+} -+ -+void __exit mipv6_mn_exit(void) -+{ -+ struct list_head *lh, *tmp; -+ struct mn_info *minfo; -+ DEBUG_FUNC(); -+ -+ mip6_fn.mn_use_hao = NULL; -+ mip6_fn.mn_check_tunneled_packet = NULL; -+ -+ MIPV6_RESETCALL(mipv6_set_home); -+ MIPV6_RESETCALL(mipv6_get_home_address); -+ MIPV6_RESETCALL(mipv6_mn_ha_probe); -+ MIPV6_RESETCALL(mipv6_is_home_addr); -+ nf_unregister_hook(&addr_modify_hook_ops); -+ proc_net_remove("mip6_mninfo"); -+ mipv6_shutdown_mdetect(); -+ ip6ip6_tnl_unregister_hook(&mipv6_mn_tnl_rcv_stats_ops); -+ ip6ip6_tnl_unregister_hook(&mipv6_mn_tnl_xmit_stats_ops); -+ ip6ip6_tnl_unregister_hook(&mipv6_mn_tnl_rcv_send_bu_ops); -+ ma_ctl_clean(); -+ -+ unregister_inet6addr_notifier(&mipv6_mn_inet6addr_notifier); -+ unregister_netdevice_notifier(&mipv6_mn_dev_notifier); -+ write_lock_bh(&mn_info_lock); -+ -+ list_for_each_safe(lh, tmp, &mn_info_list) { -+ minfo = list_entry(lh, struct mn_info, list); -+ if (minfo->is_at_home == MN_NOT_AT_HOME) -+ deprecate_addr(minfo); -+ list_del(&minfo->list); -+ kfree(minfo); -+ } -+ write_unlock_bh(&mn_info_lock); -+ mipv6_bul_exit(); -+ flush_scheduled_tasks(); -+ mipv6_del_tnl_to_ha(); -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mn.h linux-2.4.25/net/ipv6/mobile_ip6/mn.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/mn.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/mn.h 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,96 @@ -+/* -+ * MIPL Mobile IPv6 Mobile Node header file -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _MN_H -+#define _MN_H -+ -+#include -+ -+/* constants for sending of BUs*/ -+#define HA_BU_DEF_LIFETIME 10000 -+#define CN_BU_DEF_LIFETIME 420 /* Max lifetime for RR bindings from RFC 3775 */ -+#define DUMB_CN_BU_LIFETIME 600 /* BUL entry lifetime in case of dumb CN */ -+#define ROUTER_BU_DEF_LIFETIME 30 /* For packet forwarding from previous coa */ -+#define ERROR_DEF_LIFETIME DUMB_CN_BU_LIFETIME -+ -+extern rwlock_t mn_info_lock; -+ -+#define MN_NOT_AT_HOME 0 -+#define MN_RETURNING_HOME 1 -+#define MN_AT_HOME 2 -+ -+/* -+ * Mobile Node information record -+ */ -+struct mn_info { -+ struct in6_addr home_addr; -+ struct in6_addr ha; -+ __u8 home_plen; -+ __u8 is_at_home; -+ __u8 has_home_reg; -+ __u8 man_conf; -+ int ifindex; -+ int ifindex_user; -+ unsigned long home_addr_expires; -+ unsigned short dhaad_id; -+ struct list_head list; -+ spinlock_t lock; -+}; -+ -+/* prototypes for interface functions */ -+int mipv6_mn_init(void); -+void mipv6_mn_exit(void); -+ -+struct handoff; -+ -+/* Interface to movement detection */ -+int mipv6_mobile_node_moved(struct handoff *ho); -+ -+void mipv6_mn_send_home_na(struct in6_addr *haddr); -+/* Init home reg. with coa */ -+int init_home_registration(struct in6_addr *home_addr, struct in6_addr *coa); -+ -+/* mn_info functions that require locking by caller */ -+struct mn_info *mipv6_mninfo_get_by_home(struct in6_addr *haddr); -+ -+struct mn_info *mipv6_mninfo_get_by_ha(struct in6_addr *home_agent); -+ -+struct mn_info *mipv6_mninfo_get_by_id(unsigned short id); -+ -+/* "safe" mn_info functions */ -+void mipv6_mninfo_add(int ifindex, struct in6_addr *home_addr, int plen, -+ int isathome, unsigned long lifetime, struct in6_addr *ha, -+ int ha_plen, unsigned long ha_lifetime, int man_conf); -+ -+int mipv6_mninfo_del(struct in6_addr *home_addr, int del_dyn_only); -+ -+void mipv6_mn_set_home_reg(struct in6_addr *home_addr, int has_home_reg); -+ -+int mipv6_mn_is_at_home(struct in6_addr *addr); -+ -+int mipv6_mn_is_home_addr(struct in6_addr *addr); -+ -+__u32 mipv6_mn_get_bulifetime(struct in6_addr *home_addr, -+ struct in6_addr *coa, __u8 flags); -+int mn_cn_handoff(void *rawentry, void *args, unsigned long *sortkey); -+ -+int mipv6_mn_ha_nd_update(struct net_device *dev, -+ struct in6_addr *ha, u8 *lladdr); -+ -+struct bul_inval_args { -+ int all_rr_states; -+ struct in6_addr *cn; -+ struct in6_addr *mn; -+}; -+ -+int mn_bul_invalidate(void *rawentry, void *args, unsigned long *sortkey); -+ -+#endif /* _MN_H */ -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mobhdr.h linux-2.4.25/net/ipv6/mobile_ip6/mobhdr.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/mobhdr.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/mobhdr.h 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,101 @@ -+/* -+ * MIPL Mobile IPv6 Mobility Header send and receive -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _MOBHDR_H -+#define _MOBHDR_H -+ -+#include -+ -+/* RR states for mipv6_send_bu() */ -+#define RR_INIT 0x00 -+#define RR_WAITH 0x01 -+#define RR_WAITC 0x02 -+#define RR_WAITHC 0x13 -+#define RR_DONE 0x10 -+ -+#define MH_UNKNOWN_CN 1 -+#define MH_AUTH_FAILED 2 -+#define MH_SEQUENCE_MISMATCH 3 -+ -+struct mipv6_bul_entry; -+struct sk_buff; -+ -+int mipv6_mh_common_init(void); -+void mipv6_mh_common_exit(void); -+int mipv6_mh_mn_init(void); -+void mipv6_mh_mn_exit(void); -+ -+struct mipv6_mh_opt { -+ struct mipv6_mo_alt_coa *alt_coa; -+ struct mipv6_mo_nonce_indices *nonce_indices; -+ struct mipv6_mo_bauth_data *auth_data; -+ struct mipv6_mo_br_advice *br_advice; -+ int freelen; -+ int totlen; -+ u8 *next_free; -+ u8 data[0]; -+}; -+ -+struct mobopt { -+ struct mipv6_mo_alt_coa *alt_coa; -+ struct mipv6_mo_nonce_indices *nonce_indices; -+ struct mipv6_mo_bauth_data *auth_data; -+ struct mipv6_mo_br_advice *br_advice; -+}; -+ -+struct mipv6_mh_opt *alloc_mh_opts(int totlen); -+int append_mh_opt(struct mipv6_mh_opt *ops, u8 type, u8 len, void *data); -+int parse_mo_tlv(void *mos, int len, struct mobopt *opts); -+int mipv6_add_pad(u8 *data, int n); -+ -+struct mipv6_auth_parm { -+ struct in6_addr *coa; -+ struct in6_addr *cn_addr; -+ __u8 *k_bu; -+}; -+ -+int send_mh(struct in6_addr *daddr, struct in6_addr *saddr, -+ u8 msg_type, u8 msg_len, u8 *msg, -+ struct in6_addr *hao_addr, struct in6_addr *rth_addr, -+ struct mipv6_mh_opt *ops, struct mipv6_auth_parm *parm); -+ -+int mipv6_mh_register(int type, int (*func)(struct sk_buff *, -+ struct in6_addr *, struct in6_addr *, -+ struct in6_addr *, struct in6_addr *, struct mipv6_mh *)); -+ -+void mipv6_mh_unregister(int type); -+ -+int mipv6_send_brr(struct in6_addr *saddr, struct in6_addr *daddr, -+ struct mipv6_mh_opt *ops); -+ -+int mipv6_send_bu(struct in6_addr *saddr, struct in6_addr *daddr, -+ struct in6_addr *coa, __u32 initdelay, -+ __u32 maxackdelay, __u8 exp, __u8 flags, -+ __u32 lifetime, struct mipv6_mh_opt *ops); -+ -+int mipv6_send_be(struct in6_addr *saddr, struct in6_addr *daddr, -+ struct in6_addr *home, __u8 status); -+ -+int mipv6_send_ba(struct in6_addr *saddr, struct in6_addr *daddr, -+ struct in6_addr *auth_coa, struct in6_addr *rep_coa, -+ u8 status, u16 sequence, u32 lifetime, u8 *k_bu); -+ -+/* Binding Authentication Data Option routines */ -+#define MAX_HASH_LENGTH 20 -+#define MIPV6_RR_MAC_LENGTH 12 -+ -+int mipv6_auth_build(struct in6_addr *cn_addr, struct in6_addr *coa, -+ __u8 *opt, __u8 *aud_data, __u8 *k_bu); -+ -+int mipv6_auth_check(struct in6_addr *cn_addr, struct in6_addr *coa, -+ __u8 *opt, __u8 optlen, struct mipv6_mo_bauth_data *aud, -+ __u8 *k_bu); -+#endif /* _MOBHDR_H */ -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mobhdr_common.c linux-2.4.25/net/ipv6/mobile_ip6/mobhdr_common.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/mobhdr_common.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/mobhdr_common.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,1210 @@ -+/* -+ * Mobile IPv6 Mobility Header Common Functions -+ * -+ * Authors: -+ * Antti Tuominen -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 "stats.h" -+#include "debug.h" -+#include "mobhdr.h" -+#include "bcache.h" -+ -+#include "rr_crypto.h" -+#include "exthdrs.h" -+#include "config.h" -+ -+#define MIPV6_MH_MAX MIPV6_MH_BE -+struct mh_proto { -+ int (*func) (struct sk_buff *, -+ struct in6_addr *, struct in6_addr *, -+ struct in6_addr *, struct in6_addr *, -+ struct mipv6_mh *); -+}; -+ -+static struct mh_proto mh_rcv[MIPV6_MH_MAX]; -+ -+int mipv6_mh_register(int type, int (*func)(struct sk_buff *, -+ struct in6_addr *, struct in6_addr *, -+ struct in6_addr *, struct in6_addr *, struct mipv6_mh *)) -+{ -+ if (mh_rcv[type].func != NULL) -+ return -1; -+ -+ mh_rcv[type].func = func; -+ -+ return 0; -+} -+ -+void mipv6_mh_unregister(int type) -+{ -+ if (type < 0 || type > MIPV6_MH_MAX) -+ return; -+ -+ mh_rcv[type].func = NULL; -+} -+ -+struct socket *mipv6_mh_socket = NULL; -+ -+/* TODO: Fix fragmentation */ -+static int dstopts_getfrag( -+ const void *data, struct in6_addr *addr, -+ char *buff, unsigned int offset, unsigned int len) -+{ -+ memcpy(buff, data + offset, len); -+ return 0; -+} -+ -+struct mipv6_mh_opt *alloc_mh_opts(int totlen) -+{ -+ struct mipv6_mh_opt *ops; -+ -+ ops = kmalloc(sizeof(*ops) + totlen, GFP_ATOMIC); -+ if (ops == NULL) -+ return NULL; -+ -+ memset(ops, 0, sizeof(*ops)); -+ ops->next_free = ops->data; -+ ops->freelen = totlen; -+ -+ return ops; -+} -+ -+int append_mh_opt(struct mipv6_mh_opt *ops, u8 type, u8 len, void *data) -+{ -+ struct mipv6_mo *mo; -+ -+ if (ops->next_free == NULL) { -+ DEBUG(DBG_ERROR, "No free room for option"); -+ return -ENOMEM; -+ } -+ if (ops->freelen < len + 2) { -+ DEBUG(DBG_ERROR, "No free room for option"); -+ return -ENOMEM; -+ } -+ else { -+ ops->freelen -= (len + 2); -+ ops->totlen += (len + 2); -+ } -+ -+ mo = (struct mipv6_mo *)ops->next_free; -+ mo->type = type; -+ mo->length = len; -+ -+ switch (type) { -+ case MIPV6_OPT_ALTERNATE_COA: -+ ops->alt_coa = (struct mipv6_mo_alt_coa *)mo; -+ ipv6_addr_copy(&ops->alt_coa->addr, (struct in6_addr *)data); -+ break; -+ case MIPV6_OPT_NONCE_INDICES: -+ DEBUG(DBG_INFO, "Added nonce indices pointer"); -+ ops->nonce_indices = (struct mipv6_mo_nonce_indices *)mo; -+ ops->nonce_indices->home_nonce_i = *(__u16 *)data; -+ ops->nonce_indices->careof_nonce_i = *((__u16 *)data + 1); -+ break; -+ case MIPV6_OPT_AUTH_DATA: -+ DEBUG(DBG_INFO, "Added opt auth_data pointer"); -+ ops->auth_data = (struct mipv6_mo_bauth_data *)mo; -+ break; -+ case MIPV6_OPT_BIND_REFRESH_ADVICE: -+ ops->br_advice = (struct mipv6_mo_br_advice *)mo; -+ ops->br_advice->refresh_interval = htons(*(u16 *)data); -+ break; -+ default: -+ DEBUG(DBG_ERROR, "Unknow option type"); -+ break; -+ } -+ -+ if (ops->freelen == 0) -+ ops->next_free = NULL; -+ else -+ ops->next_free += (len + 2); -+ -+ return 0; -+} -+ -+/* -+ * Calculates required padding with xn + y requirement with offset -+ */ -+static inline int optpad(int xn, int y, int offset) -+{ -+ return ((y - offset) & (xn - 1)); -+} -+ -+static int option_pad(int type, int offset) -+{ -+ if (type == MIPV6_OPT_ALTERNATE_COA) -+ return optpad(8, 6, offset); /* 8n + 6 */ -+ if (type == MIPV6_OPT_BIND_REFRESH_ADVICE || -+ type == MIPV6_OPT_NONCE_INDICES) -+ return optpad(2, 0, offset); /* 2n */ -+ return 0; -+} -+ -+/* -+ * Add Pad1 or PadN option to data -+ */ -+int mipv6_add_pad(u8 *data, int n) -+{ -+ struct mipv6_mo_padn *padn; -+ -+ if (n <= 0) return 0; -+ if (n == 1) { -+ *data = MIPV6_OPT_PAD1; -+ return 1; -+ } -+ padn = (struct mipv6_mo_padn *)data; -+ padn->type = MIPV6_OPT_PADN; -+ padn->length = n - 2; -+ memset(padn->data, 0, n - 2); -+ return n; -+} -+ -+/* -+ * Write options to mobility header buffer -+ */ -+static int prepare_mh_opts(u8 *optdata, int off, struct mipv6_mh_opt *ops) -+{ -+ u8 *nextopt = optdata; -+ int offset = off, pad = 0; -+ -+ if (ops == NULL) { -+ nextopt = NULL; -+ return -1; -+ } -+ -+ if (ops->alt_coa) { -+ pad = option_pad(MIPV6_OPT_ALTERNATE_COA, offset); -+ nextopt += mipv6_add_pad(nextopt, pad); -+ memcpy(nextopt, ops->alt_coa, sizeof(struct mipv6_mo_alt_coa)); -+ nextopt += sizeof(struct mipv6_mo_alt_coa); -+ offset += pad + sizeof(struct mipv6_mo_alt_coa); -+ } -+ -+ if (ops->br_advice) { -+ pad = option_pad(MIPV6_OPT_BIND_REFRESH_ADVICE, offset); -+ nextopt += mipv6_add_pad(nextopt, pad); -+ memcpy(nextopt, ops->br_advice, sizeof(struct mipv6_mo_br_advice)); -+ nextopt += sizeof(struct mipv6_mo_br_advice); -+ offset += pad + sizeof(struct mipv6_mo_br_advice); -+ } -+ -+ if (ops->nonce_indices) { -+ pad = option_pad(MIPV6_OPT_NONCE_INDICES, offset); -+ nextopt += mipv6_add_pad(nextopt, pad); -+ memcpy(nextopt, ops->nonce_indices, sizeof(struct mipv6_mo_nonce_indices)); -+ nextopt += sizeof(struct mipv6_mo_nonce_indices); -+ offset += pad + sizeof(struct mipv6_mo_nonce_indices); -+ } -+ -+ if (ops->auth_data) { -+ /* This option should always be the last. Header -+ * length must be a multiple of 8 octects, so we pad -+ * if necessary. */ -+ pad = optpad(8, 0, offset + ops->auth_data->length + 2); -+ nextopt += mipv6_add_pad(nextopt, pad); -+ memcpy(nextopt, ops->auth_data, ops->auth_data->length + 2); -+ nextopt += ops->auth_data->length + 2; -+ } -+ nextopt = NULL; -+ -+ return 0; -+} -+ -+static int calculate_mh_opts(struct mipv6_mh_opt *ops, int mh_len) -+{ -+ int offset = mh_len; -+ -+ if (ops == NULL) -+ return 0; -+ -+ if (ops->alt_coa) -+ offset += sizeof(struct mipv6_mo_alt_coa) -+ + option_pad(MIPV6_OPT_ALTERNATE_COA, offset); -+ -+ if (ops->br_advice) -+ offset += sizeof(struct mipv6_mo_br_advice) -+ + option_pad(MIPV6_OPT_BIND_REFRESH_ADVICE, offset); -+ -+ if (ops->nonce_indices) -+ offset += sizeof(struct mipv6_mo_nonce_indices) -+ + option_pad(MIPV6_OPT_NONCE_INDICES, offset); -+ -+ if (ops->auth_data) /* no alignment */ -+ offset += ops->auth_data->length + 2; -+ -+ return offset - mh_len; -+} -+ -+/* -+ * -+ * Mobility Header Message send functions -+ * -+ */ -+ -+/** -+ * send_mh - builds and sends a MH msg -+ * -+ * @daddr: destination address for packet -+ * @saddr: source address for packet -+ * @msg_type: type of MH -+ * @msg_len: message length -+ * @msg: MH type specific data -+ * @hao_addr: home address for home address option -+ * @rth_addr: routing header address -+ * @ops: mobility options -+ * @parm: auth data -+ * -+ * Builds MH, appends the type specific msg data to the header and -+ * sends the packet with a home address option, if a home address was -+ * given. Returns 0, if everything succeeded and a negative error code -+ * otherwise. -+ **/ -+int send_mh(struct in6_addr *daddr, -+ struct in6_addr *saddr, -+ u8 msg_type, u8 msg_len, u8 *msg, -+ struct in6_addr *hao_addr, -+ struct in6_addr *rth_addr, -+ struct mipv6_mh_opt *ops, -+ struct mipv6_auth_parm *parm) -+{ -+ struct flowi fl; -+ struct mipv6_mh *mh; -+ struct sock *sk = mipv6_mh_socket->sk; -+ struct ipv6_txoptions *txopt = NULL; -+ int tot_len = sizeof(struct mipv6_mh) + msg_len; -+ int padded_len = 0, txopt_len = 0; -+ -+ DEBUG_FUNC(); -+ /* Add length of options */ -+ tot_len += calculate_mh_opts(ops, tot_len); -+ /* Needs to be a multiple of 8 octets */ -+ padded_len = tot_len + optpad(8, 0, tot_len); -+ -+ mh = sock_kmalloc(sk, padded_len, GFP_ATOMIC); -+ if (!mh) { -+ DEBUG(DBG_ERROR, "memory allocation failed"); -+ return -ENOMEM; -+ } -+ -+ memset(&fl, 0, sizeof(fl)); -+ fl.proto = IPPROTO_MOBILITY; -+ fl.fl6_dst = daddr; -+ fl.fl6_src = saddr; -+ fl.fl6_flowlabel = 0; -+ fl.oif = sk->bound_dev_if; -+ -+ if (hao_addr || rth_addr) { -+ __u8 *opt_ptr; -+ -+ if (hao_addr) -+ txopt_len += sizeof(struct mipv6_dstopt_homeaddr) + 6; -+ if (rth_addr) -+ txopt_len += sizeof(struct rt2_hdr); -+ -+ txopt_len += sizeof(*txopt); -+ txopt = sock_kmalloc(sk, txopt_len, GFP_ATOMIC); -+ if (txopt == NULL) { -+ DEBUG(DBG_ERROR, "No socket space left"); -+ sock_kfree_s(sk, mh, padded_len); -+ return -ENOMEM; -+ } -+ memset(txopt, 0, txopt_len); -+ txopt->tot_len = txopt_len; -+ opt_ptr = (__u8 *) (txopt + 1); -+ if (hao_addr) { -+ int holen = sizeof(struct mipv6_dstopt_homeaddr) + 6; -+ txopt->dst1opt = (struct ipv6_opt_hdr *) opt_ptr; -+ txopt->opt_flen += holen; -+ opt_ptr += holen; -+ mipv6_append_dst1opts(txopt->dst1opt, saddr, -+ NULL, holen); -+ txopt->mipv6_flags = MIPV6_SND_HAO | MIPV6_SND_BU; -+ } -+ if (rth_addr) { -+ int rtlen = sizeof(struct rt2_hdr); -+ txopt->srcrt2 = (struct ipv6_rt_hdr *) opt_ptr; -+ txopt->opt_nflen += rtlen; -+ opt_ptr += rtlen; -+ mipv6_append_rt2hdr(txopt->srcrt2, rth_addr); -+ } -+ } -+ -+ /* Fill in the fields of MH */ -+ mh->payload = NEXTHDR_NONE; -+ mh->length = (padded_len >> 3) - 1; /* Units of 8 octets - 1 */ -+ mh->type = msg_type; -+ mh->reserved = 0; -+ mh->checksum = 0; -+ -+ memcpy(mh->data, msg, msg_len); -+ prepare_mh_opts(mh->data + msg_len, msg_len + sizeof(*mh), ops); -+ /* If BAD is present, this is already done. */ -+ mipv6_add_pad((u8 *)mh + tot_len, padded_len - tot_len); -+ -+ if (parm && parm->k_bu && ops && ops->auth_data) { -+ /* Calculate the position of the authorization data before adding checksum*/ -+ mipv6_auth_build(parm->cn_addr, parm->coa, (__u8 *)mh, -+ (__u8 *)mh + padded_len - MIPV6_RR_MAC_LENGTH, parm->k_bu); -+ } -+ /* Calculate the MH checksum */ -+ mh->checksum = csum_ipv6_magic(fl.fl6_src, fl.fl6_dst, -+ padded_len, IPPROTO_MOBILITY, -+ csum_partial((char *)mh, padded_len, 0)); -+ ip6_build_xmit(sk, dstopts_getfrag, mh, &fl, padded_len, txopt, 255, -+ MSG_DONTWAIT); -+ /* dst cache must be cleared so RR messages can be routed through -+ different interfaces */ -+ sk_dst_reset(sk); -+ -+ if (txopt_len) -+ sock_kfree_s(sk, txopt, txopt_len); -+ sock_kfree_s(sk, mh, padded_len); -+ return 0; -+} -+ -+/** -+ * mipv6_send_brr - send a Binding Refresh Request -+ * @saddr: source address for BRR -+ * @daddr: destination address for BRR -+ * @ops: mobility options -+ * -+ * Sends a binding request. On a mobile node, use the mobile node's -+ * home address for @saddr. Returns 0 on success, negative on -+ * failure. -+ **/ -+int mipv6_send_brr(struct in6_addr *saddr, struct in6_addr *daddr, -+ struct mipv6_mh_opt *ops) -+{ -+ struct mipv6_mh_brr br; -+ -+ memset(&br, 0, sizeof(br)); -+ /* We don't need to explicitly add a RH to brr, since it will be -+ * included automatically, if a BCE exists -+ */ -+ MIPV6_INC_STATS(n_brr_sent); -+ return send_mh(daddr, saddr, MIPV6_MH_BRR, sizeof(br), (u8 *)&br, -+ NULL, NULL, ops, NULL); -+} -+ -+/** -+ * mipv6_send_ba - send a Binding Acknowledgement -+ * @saddr: source address for BA -+ * @daddr: destination address for BA -+ * @reply_coa: destination care-of address of MN -+ * @auth_coa: care-of address of MN used for authentication -+ * @status: status field value -+ * @sequence: sequence number from BU -+ * @lifetime: granted lifetime for binding in seconds -+ * @ops: mobility options -+ * -+ * Send a binding acknowledgement. On a mobile node, use the mobile -+ * node's home address for saddr. Returns 0 on success, non-zero on -+ * failure. -+ **/ -+int mipv6_send_ba(struct in6_addr *saddr, struct in6_addr *daddr, -+ struct in6_addr *auth_coa, struct in6_addr *rep_coa, -+ u8 status, u16 sequence, u32 lifetime, u8 *k_bu) -+{ -+ struct mipv6_mh_ba ba; -+ struct mipv6_auth_parm parm; -+ struct mipv6_mh_opt *ops = NULL; -+ int ops_len = 0, ret = 0; -+ struct mipv6_bce bc_entry; -+ int coming_home = 0; -+ int bypass_tnl = 0; -+ -+ memset(&ba, 0, sizeof(ba)); -+ -+ ba.status = status; -+ ba.sequence = htons(sequence); -+ ba.lifetime = htons(lifetime >> 2); -+ -+ DEBUG(DBG_INFO, "sending a status %d BA %s authenticator to MN \n" -+ "%x:%x:%x:%x:%x:%x:%x:%x at care of address \n" -+ "%x:%x:%x:%x:%x:%x:%x:%x : with lifetime %d and \n" -+ " sequence number %d", -+ status, k_bu ? "with" : "without", -+ NIPV6ADDR(daddr), NIPV6ADDR(auth_coa), lifetime, sequence); -+ -+ memset(&parm, 0, sizeof(parm)); -+ parm.coa = auth_coa; -+ parm.cn_addr = saddr; -+ -+ if (k_bu) { -+ ops_len += sizeof(struct mipv6_mo_bauth_data) + -+ MIPV6_RR_MAC_LENGTH; -+ parm.k_bu = k_bu; -+ } -+ -+ if (mip6node_cnf.binding_refresh_advice) { -+ ops_len += sizeof(struct mipv6_mo_br_advice); -+ } -+ if (ops_len) { -+ ops = alloc_mh_opts(ops_len); -+ if (ops == NULL) { -+ DEBUG(DBG_WARNING, "Out of memory"); -+ return -ENOMEM; -+ } -+ if (mip6node_cnf.binding_refresh_advice > 0) { -+ if (append_mh_opt(ops, MIPV6_OPT_BIND_REFRESH_ADVICE, 2, -+ &mip6node_cnf.binding_refresh_advice) < 0) { -+ DEBUG(DBG_WARNING, "Adding BRA failed"); -+ if (ops) -+ kfree(ops); -+ return -ENOMEM; -+ } -+ } -+ if (k_bu) { -+ if (append_mh_opt(ops, MIPV6_OPT_AUTH_DATA, -+ MIPV6_RR_MAC_LENGTH, NULL) < 0) { -+ DEBUG(DBG_WARNING, "Adding BAD failed"); -+ if (ops) -+ kfree(ops); -+ return -ENOMEM; -+ } -+ } -+ } -+ coming_home = !ipv6_addr_cmp(rep_coa, daddr); -+ -+ bypass_tnl = (coming_home && -+ !mipv6_bcache_get(daddr, saddr, &bc_entry) && -+ bc_entry.flags&MIPV6_BU_F_HOME && -+ status >= 128); -+ -+ if (bypass_tnl && mip6_fn.bce_tnl_rt_del) -+ mip6_fn.bce_tnl_rt_del(&bc_entry.coa, -+ &bc_entry.our_addr, -+ &bc_entry.home_addr); -+ -+ if (coming_home) -+ ret = send_mh(daddr, saddr, MIPV6_MH_BA, sizeof(ba), (u8 *)&ba, -+ NULL, NULL, ops, &parm); -+ else -+ ret = send_mh(daddr, saddr, MIPV6_MH_BA, sizeof(ba), (u8 *)&ba, -+ NULL, rep_coa, ops, &parm); -+ -+ if (bypass_tnl && mip6_fn.bce_tnl_rt_add) -+ mip6_fn.bce_tnl_rt_add(&bc_entry.coa, -+ &bc_entry.our_addr, -+ &bc_entry.home_addr); -+ -+ if (ret == 0) { -+ if (status < 128) { -+ MIPV6_INC_STATS(n_ba_sent); -+ } else { -+ MIPV6_INC_STATS(n_ban_sent); -+ } -+ } -+ -+ if (ops) -+ kfree(ops); -+ -+ return 0; -+} -+ -+/** -+ * mipv6_send_be - send a Binding Error message -+ * @saddr: source address for BE -+ * @daddr: destination address for BE -+ * @home: Home Address in offending packet (if any) -+ * -+ * Sends a binding error. On a mobile node, use the mobile node's -+ * home address for @saddr. Returns 0 on success, negative on -+ * failure. -+ **/ -+int mipv6_send_be(struct in6_addr *saddr, struct in6_addr *daddr, -+ struct in6_addr *home, __u8 status) -+{ -+ struct mipv6_mh_be be; -+ int ret = 0; -+ struct mipv6_bce bc_entry; -+ int bypass_tnl = 0; -+ -+ if (ipv6_addr_is_multicast(daddr)) -+ return -EINVAL; -+ -+ memset(&be, 0, sizeof(be)); -+ be.status = status; -+ if (home) -+ ipv6_addr_copy(&be.home_addr, home); -+ -+ if (mipv6_bcache_get(daddr, saddr, &bc_entry) == 0 && -+ bc_entry.flags&MIPV6_BU_F_HOME) -+ bypass_tnl = 1; -+ -+ if (bypass_tnl && mip6_fn.bce_tnl_rt_del) -+ mip6_fn.bce_tnl_rt_del(&bc_entry.coa, -+ &bc_entry.our_addr, -+ &bc_entry.home_addr); -+ -+ ret = send_mh(daddr, saddr, MIPV6_MH_BE, sizeof(be), (u8 *)&be, -+ NULL, NULL, NULL, NULL); -+ -+ if (bypass_tnl && mip6_fn.bce_tnl_rt_add) -+ mip6_fn.bce_tnl_rt_add(&bc_entry.coa, -+ &bc_entry.our_addr, -+ &bc_entry.home_addr); -+ -+ if (ret == 0) -+ MIPV6_INC_STATS(n_be_sent); -+ -+ return ret; -+} -+ -+/** -+ * mipv6_send_addr_test - send a HoT or CoT message -+ * @saddr: source address -+ * @daddr: destination address -+ * @msg_type: HoT or CoT message -+ * @init: HoTI or CoTI message -+ * -+ * Send a reply to HoTI or CoTI message. -+ **/ -+static int mipv6_send_addr_test(struct in6_addr *saddr, -+ struct in6_addr *daddr, -+ int msg_type, -+ struct mipv6_mh_addr_ti *init) -+{ -+ u_int8_t *kgen_token = NULL; -+ struct mipv6_mh_addr_test addr_test; -+ struct mipv6_rr_nonce *nonce; -+ struct mipv6_mh_opt *ops = NULL; -+ int ret = 0; -+ -+ DEBUG_FUNC(); -+ -+ if ((nonce = mipv6_rr_get_new_nonce())== NULL) { -+ DEBUG(DBG_WARNING, "Nonce creation failed"); -+ return 0; -+ } -+ if (mipv6_rr_cookie_create(daddr, &kgen_token, nonce->index)) { -+ DEBUG(DBG_WARNING, "No cookie"); -+ return 0; -+ } -+ -+ addr_test.nonce_index = nonce->index; -+ memcpy(addr_test.init_cookie, init->init_cookie, -+ MIPV6_RR_COOKIE_LENGTH); -+ memcpy(addr_test.kgen_token, kgen_token, -+ MIPV6_RR_COOKIE_LENGTH); -+ -+ /* No options defined */ -+ ret = send_mh(daddr, saddr, msg_type, sizeof(addr_test), -+ (u8 *)&addr_test, NULL, NULL, ops, NULL); -+ -+ if (ret == 0) { -+ if (msg_type == MIPV6_MH_HOT) { -+ MIPV6_INC_STATS(n_hot_sent); -+ } else { -+ MIPV6_INC_STATS(n_cot_sent); -+ } -+ } -+ -+ return 0; -+} -+ -+static void bc_cache_add(int ifindex, struct in6_addr *daddr, -+ struct in6_addr *haddr, struct in6_addr *coa, -+ struct in6_addr *rep_coa, __u32 lifetime, -+ __u16 sequence, __u8 flags, __u8 *k_bu) -+{ -+ __u8 ba_status = SUCCESS; -+ -+ if (lifetime > MAX_RR_BINDING_LIFE) -+ lifetime = MAX_RR_BINDING_LIFE; -+ -+ if (mipv6_bcache_add(ifindex, daddr, haddr, coa, lifetime, -+ sequence, flags, CACHE_ENTRY) != 0) { -+ DEBUG(DBG_ERROR, "binding failed."); -+ ba_status = INSUFFICIENT_RESOURCES; -+ } -+ -+ if (flags & MIPV6_BU_F_ACK) { -+ DEBUG(DBG_INFO, "sending ack (code=%d)", ba_status); -+ mipv6_send_ba(daddr, haddr, coa, rep_coa, ba_status, sequence, -+ lifetime, k_bu); -+ } -+} -+ -+static void bc_cn_home_add(int ifindex, struct in6_addr *daddr, -+ struct in6_addr *haddr, struct in6_addr *coa, -+ struct in6_addr *rep_coa, __u32 lifetime, -+ __u16 sequence, __u8 flags, __u8 *k_bu) -+{ -+ mipv6_send_ba(daddr, haddr, coa, rep_coa, -+ HOME_REGISTRATION_NOT_SUPPORTED, -+ sequence, lifetime, k_bu); -+} -+ -+static void bc_cache_delete(struct in6_addr *daddr, struct in6_addr *haddr, -+ struct in6_addr *coa, struct in6_addr *rep_coa, -+ __u16 sequence, __u8 flags, -+ __u8 *k_bu) -+{ -+ __u8 status = SUCCESS; -+ -+ /* Cached Care-of Address Deregistration */ -+ if (mipv6_bcache_exists(haddr, daddr) == CACHE_ENTRY) { -+ mipv6_bcache_delete(haddr, daddr, CACHE_ENTRY); -+ } else { -+ DEBUG(DBG_INFO, "entry is not in cache"); -+ status = REASON_UNSPECIFIED; -+ } -+ if (flags & MIPV6_BU_F_ACK) { -+ mipv6_send_ba(daddr, haddr, coa, rep_coa, status, sequence, -+ 0, k_bu); -+ } -+} -+ -+static void bc_cn_home_delete(struct in6_addr *daddr, struct in6_addr *haddr, -+ struct in6_addr *coa, struct in6_addr *rep_coa, -+ __u16 sequence, __u8 flags, -+ __u8 *k_bu) -+{ -+} -+ -+/** -+ * parse_mo_tlv - Parse TLV-encoded Mobility Options -+ * @mos: pointer to Mobility Options -+ * @len: total length of options -+ * @opts: structure to store option pointers -+ * -+ * Parses Mobility Options passed in @mos. Stores pointers in @opts -+ * to all valid mobility options found in @mos. Unknown options and -+ * padding (%MIPV6_OPT_PAD1 and %MIPV6_OPT_PADN) is ignored and -+ * skipped. -+ **/ -+int parse_mo_tlv(void *mos, int len, struct mobopt *opts) -+{ -+ struct mipv6_mo *curr = (struct mipv6_mo *)mos; -+ int left = len; -+ -+ while (left > 0) { -+ int optlen = 0; -+ if (curr->type == MIPV6_OPT_PAD1) -+ optlen = 1; -+ else -+ optlen = 2 + curr->length; -+ -+ if (optlen > left) -+ goto bad; -+ -+ switch (curr->type) { -+ case MIPV6_OPT_PAD1: -+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_PAD1 at %x", curr); -+ break; -+ case MIPV6_OPT_PADN: -+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_PADN at %x", curr); -+ break; -+ case MIPV6_OPT_ALTERNATE_COA: -+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_ACOA at %x", curr); -+ opts->alt_coa = (struct mipv6_mo_alt_coa *)curr; -+ break; -+ case MIPV6_OPT_NONCE_INDICES: -+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_NONCE_INDICES at %x", curr); -+ opts->nonce_indices = -+ (struct mipv6_mo_nonce_indices *)curr; -+ break; -+ case MIPV6_OPT_AUTH_DATA: -+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_AUTH_DATA at %x", curr); -+ opts->auth_data = (struct mipv6_mo_bauth_data *)curr; -+ break; -+ case MIPV6_OPT_BIND_REFRESH_ADVICE: -+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_BIND_REFRESH_ADVICE at %x", curr); -+ opts->br_advice = (struct mipv6_mo_br_advice *)curr; -+ break; -+ default: -+ DEBUG(DBG_INFO, "MO Unknown option type %d at %x, ignoring.", -+ curr->type, curr); -+ /* unknown mobility option, ignore and skip */ -+ } -+ -+ (u8 *)curr += optlen; -+ left -= optlen; -+ } -+ -+ if (left == 0) -+ return 0; -+ bad: -+ return -1; -+} -+ -+/* -+ * -+ * Mobility Header Message handlers -+ * -+ */ -+ -+static int mipv6_handle_mh_testinit(struct sk_buff *skb, -+ struct in6_addr *cn, -+ struct in6_addr *lcoa, -+ struct in6_addr *saddr, -+ struct in6_addr *fcoa, -+ struct mipv6_mh *mh) -+{ -+ struct mipv6_mh_addr_ti *ti = (struct mipv6_mh_addr_ti *)mh->data; -+ int msg_len = (mh->length+1) << 3; -+ int opt_len; -+ DEBUG_FUNC(); -+ -+ if (msg_len > skb->len) -+ return -1; -+ -+ opt_len = msg_len - sizeof(*mh) - sizeof(*ti); -+ -+ if (opt_len < 0) { -+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw; -+ icmpv6_send(skb, ICMPV6_PARAMPROB, -+ ICMPV6_HDR_FIELD, pos, skb->dev); -+ -+ DEBUG(DBG_INFO, "Mobility Header length less than H/C TestInit"); -+ return -1; -+ } -+ if (!mip6node_cnf.accept_ret_rout) { -+ DEBUG(DBG_INFO, "Return routability administratively disabled"); -+ return -1; -+ } -+ if (lcoa || fcoa) { -+ DEBUG(DBG_INFO, "H/C TestInit has HAO or RTH2, dropped."); -+ return -1; -+ } -+ -+ if (mh->type == MIPV6_MH_HOTI) { -+ MIPV6_INC_STATS(n_hoti_rcvd); -+ return mipv6_send_addr_test(cn, saddr, MIPV6_MH_HOT, ti); -+ } else if (mh->type == MIPV6_MH_COTI) { -+ MIPV6_INC_STATS(n_coti_rcvd); -+ return mipv6_send_addr_test(cn, saddr, MIPV6_MH_COT, ti); -+ } else -+ return -1; /* Impossible to get here */ -+} -+ -+/** -+ * mipv6_handle_mh_bu - Binding Update handler -+ * @src: care-of address of sender -+ * @dst: our address -+ * @haddr: home address of sender -+ * @mh: pointer to the beginning of the Mobility Header -+ * -+ * Handles Binding Update. Packet and offset to option are passed. -+ * Returns 0 on success, otherwise negative. -+ **/ -+static int mipv6_handle_mh_bu(struct sk_buff *skb, -+ struct in6_addr *dst, -+ struct in6_addr *unused, -+ struct in6_addr *haddr, -+ struct in6_addr *coaddr, -+ struct mipv6_mh *mh) -+{ -+ struct mipv6_mh_bu *bu = (struct mipv6_mh_bu *)mh->data; -+ int msg_len = (mh->length+1) << 3; -+ int opt_len; -+ int auth = 0; -+ int dereg; /* Is this deregistration? */ -+ int addr_type; -+ -+ struct mipv6_bce bc_entry; -+ struct in6_addr *coa, *reply_coa; -+ __u8 *key_bu = NULL; /* RR BU authentication key */ -+ __u8 flags = bu->flags; -+ __u16 sequence; -+ __u32 lifetime; -+ __u16 nonce_ind = (__u16) -1; -+ -+ if (msg_len > skb->len) -+ return -1; -+ -+ opt_len = msg_len - sizeof(*mh) - sizeof(*bu); -+ -+ if (opt_len < 0) { -+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw; -+ icmpv6_send(skb, ICMPV6_PARAMPROB, -+ ICMPV6_HDR_FIELD, pos, skb->dev); -+ -+ DEBUG(DBG_INFO, "Mobility Header length less than BU"); -+ MIPV6_INC_STATS(n_bu_drop.invalid); -+ return -1; -+ } -+ -+ addr_type = ipv6_addr_type(haddr); -+ if (addr_type&IPV6_ADDR_LINKLOCAL || !(addr_type&IPV6_ADDR_UNICAST)) -+ return -EINVAL; -+ -+ /* If HAO not present, CoA == HAddr */ -+ if (coaddr == NULL) -+ coa = haddr; -+ else { -+ coa = coaddr; -+ addr_type = ipv6_addr_type(coa); -+ if (addr_type&IPV6_ADDR_LINKLOCAL || -+ !(addr_type&IPV6_ADDR_UNICAST)) -+ return -EINVAL; -+ } -+ reply_coa = coa; -+ -+ sequence = ntohs(bu->sequence); -+ if (bu->lifetime == 0xffff) -+ lifetime = 0xffffffff; -+ else -+ lifetime = ntohs(bu->lifetime) << 2; -+ -+ dereg = (ipv6_addr_cmp(haddr, coa) == 0 || lifetime == 0); -+ -+ if (opt_len > 0) { -+ struct mobopt opts; -+ memset(&opts, 0, sizeof(opts)); -+ if (parse_mo_tlv(bu + 1, opt_len, &opts) < 0) { -+ MIPV6_INC_STATS(n_bu_drop.invalid); -+ return -1; -+ } -+ /* -+ * MIPV6_OPT_AUTH_DATA, MIPV6_OPT_NONCE_INDICES, -+ * MIPV6_OPT_ALT_COA -+ */ -+ if (opts.alt_coa) { -+ coa = &opts.alt_coa->addr; -+ dereg = (ipv6_addr_cmp(haddr, coa) == 0 || lifetime == 0); -+ } -+ addr_type = ipv6_addr_type(coa); -+ if (addr_type&IPV6_ADDR_LINKLOCAL || -+ !(addr_type&IPV6_ADDR_UNICAST)) -+ return -EINVAL; -+ -+ if (flags & MIPV6_BU_F_HOME) { -+ if (opts.nonce_indices) -+ return -1; -+ } else { -+ u8 ba_status = 0; -+ u8 *h_ckie = NULL, *c_ckie = NULL; /* Home and care-of cookies */ -+ -+ /* BUs to CN MUST include authorization data and nonce indices options */ -+ if (!opts.auth_data || !opts.nonce_indices) { -+ DEBUG(DBG_WARNING, -+ "Route optimization BU without authorization material, aborting processing"); -+ return MH_AUTH_FAILED; -+ } -+ if (mipv6_rr_cookie_create( -+ haddr, &h_ckie, opts.nonce_indices->home_nonce_i) < 0) { -+ DEBUG(DBG_WARNING, -+ "mipv6_rr_cookie_create failed for home cookie"); -+ ba_status = EXPIRED_HOME_NONCE_INDEX; -+ } -+ nonce_ind = opts.nonce_indices->home_nonce_i; -+ /* Don't create the care-of cookie, if MN deregisters */ -+ if (!dereg && mipv6_rr_cookie_create( -+ coa, &c_ckie, -+ opts.nonce_indices->careof_nonce_i) < 0) { -+ DEBUG(DBG_WARNING, -+ "mipv6_rr_cookie_create failed for coa cookie"); -+ if (ba_status == 0) -+ ba_status = EXPIRED_CAREOF_NONCE_INDEX; -+ else -+ ba_status = EXPIRED_NONCES; -+ } -+ if (ba_status == 0) { -+ if (dereg) -+ key_bu = mipv6_rr_key_calc(h_ckie, NULL); -+ else -+ key_bu = mipv6_rr_key_calc(h_ckie, c_ckie); -+ mh->checksum = 0;/* TODO: Don't mangle the packet */ -+ if (key_bu && mipv6_auth_check( -+ dst, coa, (__u8 *)mh, msg_len + sizeof(*mh), opts.auth_data, key_bu) == 0) { -+ DEBUG(DBG_INFO, "mipv6_auth_check OK for BU"); -+ auth = 1; -+ } else { -+ DEBUG(DBG_WARNING, -+ "BU Authentication failed"); -+ } -+ } -+ if (h_ckie) -+ kfree(h_ckie); -+ if (c_ckie) -+ kfree(c_ckie); -+ if (ba_status != 0) { -+ MIPV6_INC_STATS(n_bu_drop.auth); -+ mipv6_send_ba(dst, haddr, coa, -+ reply_coa, ba_status, -+ sequence, 0, NULL); -+ goto out; -+ } -+ } -+ -+ } -+ /* Require authorization option for RO, home reg is protected by IPsec */ -+ if (!(flags & MIPV6_BU_F_HOME) && !auth) { -+ MIPV6_INC_STATS(n_bu_drop.auth); -+ if (key_bu) -+ kfree(key_bu); -+ return MH_AUTH_FAILED; -+ } -+ -+ if (mipv6_bcache_get(haddr, dst, &bc_entry) == 0) { -+ if ((bc_entry.flags&MIPV6_BU_F_HOME) != -+ (flags&MIPV6_BU_F_HOME)) { -+ DEBUG(DBG_INFO, -+ "Registration type change. Sending BA REG_TYPE_CHANGE_FORBIDDEN"); -+ mipv6_send_ba(dst, haddr, coa, reply_coa, -+ REG_TYPE_CHANGE_FORBIDDEN, -+ sequence, lifetime, key_bu); -+ goto out; -+ } -+ if (!MIPV6_SEQ_GT(sequence, bc_entry.seq)) { -+ DEBUG(DBG_INFO, -+ "Sequence number mismatch. Sending BA SEQUENCE_NUMBER_OUT_OF_WINDOW"); -+ mipv6_send_ba(dst, haddr, coa, reply_coa, -+ SEQUENCE_NUMBER_OUT_OF_WINDOW, -+ bc_entry.seq, lifetime, key_bu); -+ goto out; -+ } -+ } -+ -+ if (!dereg) { -+ int ifindex; -+ struct rt6_info *rt; -+ -+ /* Avoid looping binding cache entries */ -+ if (mipv6_bcache_get(coa, dst, &bc_entry) == 0) { -+ DEBUG(DBG_WARNING, "Looped BU, dropping the packet"); -+ goto out; -+ } -+ DEBUG(DBG_INFO, "calling bu_add."); -+ if ((rt = rt6_lookup(haddr, dst, 0, 0)) != NULL) { -+ ifindex = rt->rt6i_dev->ifindex; -+ dst_release(&rt->u.dst); -+ } else { -+ /* -+ * Can't process the BU since the right interface is -+ * not found. -+ */ -+ DEBUG(DBG_WARNING, "No route entry found for handling " -+ "a BU request, (using 0 as index)"); -+ ifindex = 0; -+ } -+ if (flags & MIPV6_BU_F_HOME) -+ mip6_fn.bce_home_add(ifindex, dst, haddr, coa, -+ reply_coa, lifetime, sequence, -+ flags, key_bu); -+ else -+ mip6_fn.bce_cache_add(ifindex, dst, haddr, coa, -+ reply_coa, lifetime, sequence, -+ flags, key_bu); -+ } else { -+ DEBUG(DBG_INFO, "calling BCE delete."); -+ -+ if (flags & MIPV6_BU_F_HOME) -+ mip6_fn.bce_home_del(dst, haddr, coa, reply_coa, -+ sequence, flags, key_bu); -+ else { -+ mipv6_rr_invalidate_nonce(nonce_ind); -+ mip6_fn.bce_cache_del(dst, haddr, coa, reply_coa, -+ sequence, flags, key_bu); -+ } -+ } -+ out: -+ MIPV6_INC_STATS(n_bu_rcvd); -+ if (key_bu) -+ kfree(key_bu); -+ return 0; -+} -+ -+static int mipv6_mh_rcv(struct sk_buff *skb) -+{ -+ struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; -+ struct mipv6_mh *mh; -+ struct in6_addr *lhome, *fhome, *lcoa = NULL, *fcoa = NULL; -+ int ret = 0; -+ -+ fhome = &skb->nh.ipv6h->saddr; -+ lhome = &skb->nh.ipv6h->daddr; -+ -+ if (opt->hao != 0) { -+ struct mipv6_dstopt_homeaddr *hao; -+ hao = (struct mipv6_dstopt_homeaddr *)(skb->nh.raw + opt->hao); -+ fcoa = &hao->addr; -+ } -+ -+ if (opt->srcrt2 != 0) { -+ struct rt2_hdr *rt2; -+ rt2 = (struct rt2_hdr *)((u8 *)skb->nh.raw + opt->srcrt2); -+ lcoa = &rt2->addr; -+ } -+ -+ /* Verify checksum is correct */ -+ if (skb->ip_summed == CHECKSUM_HW) { -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ if (csum_ipv6_magic(fhome, lhome, skb->len, IPPROTO_MOBILITY, -+ skb->csum)) { -+ if (net_ratelimit()) -+ printk(KERN_WARNING "MIPv6 MH hw checksum failed\n"); -+ skb->ip_summed = CHECKSUM_NONE; -+ } -+ } -+ if (skb->ip_summed == CHECKSUM_NONE) { -+ if (csum_ipv6_magic(fhome, lhome, skb->len, IPPROTO_MOBILITY, -+ skb_checksum(skb, 0, skb->len, 0))) { -+ if (net_ratelimit()) -+ printk(KERN_WARNING "MIPv6 MH checksum failed\n"); -+ goto bad; -+ } -+ } -+ -+ if (!pskb_may_pull(skb, skb->h.raw-skb->data+sizeof(*mh)) || -+ !pskb_may_pull(skb, -+ skb->h.raw-skb->data+((skb->h.raw[1]+1)<<3))) { -+ DEBUG(DBG_INFO, "MIPv6 MH invalid length"); -+ kfree_skb(skb); -+ return 0; -+ } -+ -+ mh = (struct mipv6_mh *) skb->h.raw; -+ -+ /* Verify there are no more headers after the MH */ -+ if (mh->payload != NEXTHDR_NONE) { -+ __u32 pos = (__u32)&mh->payload - (__u32)skb->nh.raw; -+ icmpv6_send(skb, ICMPV6_PARAMPROB, -+ ICMPV6_HDR_FIELD, pos, skb->dev); -+ -+ DEBUG(DBG_INFO, "MIPv6 MH error"); -+ goto bad; -+ } -+ -+ if (mh->type > MIPV6_MH_MAX) { -+ /* send binding error */ -+ printk("Invalid mobility header type (%d)\n", mh->type); -+ mipv6_send_be(lhome, fcoa ? fcoa : fhome, -+ fcoa ? fhome : NULL, -+ MIPV6_BE_UNKNOWN_MH_TYPE); -+ goto bad; -+ } -+ if (mh_rcv[mh->type].func != NULL) { -+ ret = mh_rcv[mh->type].func(skb, lhome, lcoa, fhome, fcoa, mh); -+ } else { -+ DEBUG(DBG_INFO, "No handler for MH Type %d", mh->type); -+ goto bad; -+ } -+ -+ kfree_skb(skb); -+ return 0; -+ -+bad: -+ MIPV6_INC_STATS(n_mh_in_error); -+ kfree_skb(skb); -+ return 0; -+ -+} -+ -+#if LINUX_VERSION_CODE >= 0x2052a -+struct inet6_protocol mipv6_mh_protocol = -+{ -+ mipv6_mh_rcv, /* handler */ -+ NULL /* error control */ -+}; -+#else -+struct inet6_protocol mipv6_mh_protocol = -+{ -+ mipv6_mh_rcv, /* handler */ -+ NULL, /* error control */ -+ NULL, /* next */ -+ IPPROTO_MOBILITY, /* protocol ID */ -+ 0, /* copy */ -+ NULL, /* data */ -+ "MIPv6 MH" /* name */ -+}; -+#endif -+ -+/* -+ * -+ * Code module init/exit functions -+ * -+ */ -+ -+int __init mipv6_mh_common_init(void) -+{ -+ struct sock *sk; -+ int err; -+ -+ mip6_fn.bce_home_add = bc_cn_home_add; -+ mip6_fn.bce_cache_add = bc_cache_add; -+ mip6_fn.bce_home_del = bc_cn_home_delete; -+ mip6_fn.bce_cache_del = bc_cache_delete; -+ -+ mipv6_mh_socket = sock_alloc(); -+ if (mipv6_mh_socket == NULL) { -+ printk(KERN_ERR -+ "Failed to create the MIP6 MH control socket.\n"); -+ return -1; -+ } -+ mipv6_mh_socket->type = SOCK_RAW; -+ -+ if ((err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_MOBILITY, -+ &mipv6_mh_socket)) < 0) { -+ printk(KERN_ERR -+ "Failed to initialize the MIP6 MH control socket (err %d).\n", -+ err); -+ sock_release(mipv6_mh_socket); -+ mipv6_mh_socket = NULL; /* for safety */ -+ return err; -+ } -+ -+ sk = mipv6_mh_socket->sk; -+ sk->allocation = GFP_ATOMIC; -+ sk->sndbuf = 64 * 1024 + sizeof(struct sk_buff); -+ sk->prot->unhash(sk); -+ -+ memset(&mh_rcv, 0, sizeof(mh_rcv)); -+ mh_rcv[MIPV6_MH_HOTI].func = mipv6_handle_mh_testinit; -+ mh_rcv[MIPV6_MH_COTI].func = mipv6_handle_mh_testinit; -+ mh_rcv[MIPV6_MH_BU].func = mipv6_handle_mh_bu; -+ -+#if LINUX_VERSION_CODE >= 0x2052a -+ if (inet6_add_protocol(&mipv6_mh_protocol, IPPROTO_MOBILITY) < 0) { -+ printk(KERN_ERR "Failed to register MOBILITY protocol\n"); -+ sock_release(mipv6_mh_socket); -+ mipv6_mh_socket = NULL; -+ return -EAGAIN; -+ } -+#else -+ inet6_add_protocol(&mipv6_mh_protocol); -+#endif -+ /* To disable the use of dst_cache, -+ * which slows down the sending of BUs ?? -+ */ -+ sk->dst_cache=NULL; -+ -+ return 0; -+} -+ -+void __exit mipv6_mh_common_exit(void) -+{ -+ if (mipv6_mh_socket) sock_release(mipv6_mh_socket); -+ mipv6_mh_socket = NULL; /* For safety. */ -+ -+#if LINUX_VERSION_CODE >= 0x2052a -+ inet6_del_protocol(&mipv6_mh_protocol, IPPROTO_MOBILITY); -+#else -+ inet6_del_protocol(&mipv6_mh_protocol); -+#endif -+ memset(&mh_rcv, 0, sizeof(mh_rcv)); -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mobhdr_mn.c linux-2.4.25/net/ipv6/mobile_ip6/mobhdr_mn.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/mobhdr_mn.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/mobhdr_mn.c 2004-06-26 11:29:32.000000000 +0100 -@@ -0,0 +1,1155 @@ -+/* -+ * Mobile IPv6 Mobility Header Functions for Mobile Node -+ * -+ * Authors: -+ * Antti Tuominen -+ * Niklas Kämpe -+ * Henrik Petander -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 "mobhdr.h" -+#include "mn.h" -+#include "bul.h" -+#include "rr_crypto.h" -+#include "debug.h" -+#include "util.h" -+#include "stats.h" -+ -+int rr_configured = 1; -+ -+/* Return value of mipv6_rr_state() */ -+#define NO_RR 0 -+#define DO_RR 1 -+#define RR_FOR_COA 2 -+#define INPROGRESS_RR 3 -+ -+/** -+ * send_bu_msg - sends a Binding Update -+ * @bulentry : BUL entry with the information for building a BU -+ * -+ * Function builds a BU msg based on the contents of a bul entry. -+ * Does not change the bul entry. -+ **/ -+static int send_bu_msg(struct mipv6_bul_entry *binding) -+{ -+ int auth = 0; /* Use auth */ -+ int ret = 0; -+ struct mipv6_auth_parm parm; -+ struct mipv6_mh_bu bu; -+ -+ if (!binding) { -+ DEBUG(DBG_ERROR, "called with a null bul entry"); -+ return -1; -+ } -+ -+ memset(&parm, 0, sizeof(parm)); -+ if (mipv6_prefix_compare(&binding->coa, &binding->home_addr, 64)) -+ parm.coa = &binding->home_addr; -+ else -+ parm.coa = &binding->coa; -+ parm.cn_addr = &binding->cn_addr; -+ -+ if (binding->rr && binding->rr->kbu) { -+ DEBUG(DBG_INFO, "Binding with key"); -+ auth = 1; -+ parm.k_bu = binding->rr->kbu; -+ } -+ memset(&bu, 0, sizeof(bu)); -+ bu.flags = binding->flags; -+ bu.sequence = htons(binding->seq); -+ bu.lifetime = htons(binding->lifetime >> 2); -+ bu.reserved = 0; -+ -+ ret = send_mh(&binding->cn_addr, &binding->home_addr, -+ MIPV6_MH_BU, sizeof(bu), (u8 *)&bu, -+ &binding->home_addr, NULL, -+ binding->ops, &parm); -+ -+ if (ret == 0) -+ MIPV6_INC_STATS(n_bu_sent); -+ -+ return ret; -+} -+ -+/** -+ * mipv6_send_addr_test_init - send a HoTI or CoTI message -+ * @saddr: source address for H/CoTI -+ * @daddr: destination address for H/CoTI -+ * @msg_type: Identifies whether HoTI or CoTI -+ * @init_cookie: the HoTi or CoTi init cookie -+ * -+ * The message will be retransmitted till we get a HoT or CoT message, since -+ * our caller (mipv6_RR_start) has entered this message in the BUL with -+ * exponential backoff retramission set. -+ */ -+static int mipv6_send_addr_test_init(struct in6_addr *saddr, -+ struct in6_addr *daddr, -+ u8 msg_type, -+ u8 *init_cookie) -+{ -+ struct mipv6_mh_addr_ti ti; -+ struct mipv6_mh_opt *ops = NULL; -+ int ret = 0; -+ -+ /* Set reserved and copy the cookie from address test init msg */ -+ ti.reserved = 0; -+ mipv6_rr_mn_cookie_create(init_cookie); -+ memcpy(ti.init_cookie, init_cookie, MIPV6_RR_COOKIE_LENGTH); -+ -+ ret = send_mh(daddr, saddr, msg_type, sizeof(ti), (u8 *)&ti, -+ NULL, NULL, ops, NULL); -+ if (ret == 0) { -+ if (msg_type == MIPV6_MH_HOTI) { -+ MIPV6_INC_STATS(n_hoti_sent); -+ } else { -+ MIPV6_INC_STATS(n_coti_sent); -+ } -+ } -+ -+ return ret; -+} -+ -+/* -+ * -+ * Callback handlers for binding update list -+ * -+ */ -+ -+/* Return value 0 means keep entry, non-zero means discard entry. */ -+ -+/* Callback for BUs not requiring acknowledgement -+ */ -+int bul_entry_expired(struct mipv6_bul_entry *bulentry) -+{ -+ /* Lifetime expired, delete entry. */ -+ DEBUG(DBG_INFO, "bul entry 0x%p lifetime expired, deleting entry", -+ bulentry); -+ return 1; -+} -+ -+/* Callback for BUs requiring acknowledgement with exponential resending -+ * scheme */ -+static int bul_resend_exp(struct mipv6_bul_entry *bulentry) -+{ -+ unsigned long now = jiffies; -+ -+ DEBUG(DBG_INFO, "(0x%x) resending bu", (int) bulentry); -+ -+ -+ /* If sending a de-registration, do not care about the -+ * lifetime value, as de-registrations are normally sent with -+ * a zero lifetime value. If the entry is a home entry get the -+ * current lifetime. -+ */ -+ -+ if (bulentry->lifetime != 0) { -+ bulentry->lifetime = mipv6_mn_get_bulifetime( -+ &bulentry->home_addr, &bulentry->coa, bulentry->flags); -+ -+ bulentry->expire = now + bulentry->lifetime * HZ; -+ } else { -+ bulentry->expire = now + HOME_RESEND_EXPIRE * HZ; -+ } -+ if (bulentry->rr) { -+ /* Redo RR, if cookies have expired */ -+ if (time_after(jiffies, bulentry->rr->home_time + MAX_TOKEN_LIFE * HZ)) -+ bulentry->rr->rr_state |= RR_WAITH; -+ if (time_after(jiffies, bulentry->rr->careof_time + MAX_NONCE_LIFE * HZ)) -+ bulentry->rr->rr_state |= RR_WAITC; -+ -+ if (bulentry->rr->rr_state & RR_WAITH) { -+ /* Resend HoTI directly */ -+ mipv6_send_addr_test_init(&bulentry->home_addr, -+ &bulentry->cn_addr, MIPV6_MH_HOTI, -+ bulentry->rr->hot_cookie); -+ } -+ if (bulentry->rr->rr_state & RR_WAITC) { -+ /* Resend CoTI directly */ -+ mipv6_send_addr_test_init(&bulentry->coa, -+ &bulentry->cn_addr, MIPV6_MH_COTI, -+ bulentry->rr->cot_cookie); -+ } -+ goto out; -+ } -+ -+ bulentry->seq++; -+ -+ if (send_bu_msg(bulentry) < 0) -+ DEBUG(DBG_ERROR, "Resending of BU failed"); -+ -+out: -+ /* Schedule next retransmission */ -+ if (bulentry->delay < bulentry->maxdelay) { -+ bulentry->delay = 2 * bulentry->delay; -+ if (bulentry->delay > bulentry->maxdelay) { -+ /* can happen if maxdelay is not power(mindelay, 2) */ -+ bulentry->delay = bulentry->maxdelay; -+ } -+ } else if (bulentry->flags & MIPV6_BU_F_HOME) { -+ /* Home registration - continue sending BU at maxdelay rate */ -+ DEBUG(DBG_INFO, "Sending BU to HA after max ack wait time " -+ "reached(0x%x)", (int) bulentry); -+ bulentry->delay = bulentry->maxdelay; -+ } else if (!(bulentry->flags & MIPV6_BU_F_HOME)) { -+ /* Failed to get BA from a CN */ -+ bulentry->callback_time = now; -+ return -1; -+ } -+ -+ bulentry->callback_time = now + bulentry->delay * HZ; -+ return 0; -+} -+ -+ -+ -+/* Callback for sending a registration refresh BU -+ */ -+static int bul_refresh(struct mipv6_bul_entry *bulentry) -+{ -+ unsigned long now = jiffies; -+ -+ /* Refresh interval passed, send new BU */ -+ DEBUG(DBG_INFO, "bul entry 0x%x refresh interval passed, sending new BU", (int) bulentry); -+ if (bulentry->lifetime == 0) -+ return 0; -+ -+ /* Set new maximum lifetime and expiration time */ -+ bulentry->lifetime = mipv6_mn_get_bulifetime(&bulentry->home_addr, -+ &bulentry->coa, -+ bulentry->flags); -+ bulentry->expire = now + bulentry->lifetime * HZ; -+ bulentry->seq++; -+ /* Send update */ -+ if (send_bu_msg(bulentry) < 0) -+ DEBUG(DBG_ERROR, "Resending of BU failed"); -+ -+ if (time_after_eq(now, bulentry->expire)) { -+ /* Sanity check */ -+ DEBUG(DBG_ERROR, "bul entry expire time in history - setting expire to %u secs", ERROR_DEF_LIFETIME); -+ bulentry->lifetime = ERROR_DEF_LIFETIME; -+ bulentry->expire = now + ERROR_DEF_LIFETIME*HZ; -+ } -+ -+ /* Set up retransmission */ -+ bulentry->state = RESEND_EXP; -+ bulentry->callback = bul_resend_exp; -+ bulentry->callback_time = now + INITIAL_BINDACK_TIMEOUT*HZ; -+ bulentry->delay = INITIAL_BINDACK_TIMEOUT; -+ bulentry->maxdelay = MAX_BINDACK_TIMEOUT; -+ -+ return 0; -+} -+ -+static int mipv6_send_RR_bu(struct mipv6_bul_entry *bulentry) -+{ -+ int ret; -+ int ops_len = 0; -+ u16 nonces[2]; -+ -+ DEBUG(DBG_INFO, "Sending BU to CN %x:%x:%x:%x:%x:%x:%x:%x " -+ "for home address %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(&bulentry->cn_addr), NIPV6ADDR(&bulentry->home_addr)); -+ nonces[0] = bulentry->rr->home_nonce_index; -+ nonces[1] = bulentry->rr->careof_nonce_index; -+ ops_len = sizeof(struct mipv6_mo_bauth_data) + MIPV6_RR_MAC_LENGTH + -+ sizeof(struct mipv6_mo_nonce_indices); -+ if (bulentry->ops) { -+ DEBUG(DBG_WARNING, "Bul entry had existing mobility options, freeing them"); -+ kfree(bulentry->ops); -+ } -+ bulentry->ops = alloc_mh_opts(ops_len); -+ -+ if (!bulentry->ops) -+ return -ENOMEM; -+ if (append_mh_opt(bulentry->ops, MIPV6_OPT_NONCE_INDICES, -+ sizeof(struct mipv6_mo_nonce_indices) - 2, nonces) < 0) -+ return -ENOMEM; -+ -+ if (append_mh_opt(bulentry->ops, MIPV6_OPT_AUTH_DATA, -+ MIPV6_RR_MAC_LENGTH, NULL) < 0) -+ return -ENOMEM; -+ /* RR procedure is over, send a BU */ -+ if (!(bulentry->flags & MIPV6_BU_F_ACK)) { -+ DEBUG(DBG_INFO, "Setting bul callback to bul_entry_expired"); -+ bulentry->state = ACK_OK; -+ bulentry->callback = bul_entry_expired; -+ bulentry->callback_time = jiffies + HZ * bulentry->lifetime; -+ bulentry->expire = jiffies + HZ * bulentry->lifetime; -+ } -+ else { -+ bulentry->callback_time = jiffies + HZ; -+ bulentry->expire = jiffies + HZ * bulentry->lifetime; -+ } -+ -+ ret = send_bu_msg(bulentry); -+ mipv6_bul_reschedule(bulentry); -+ return ret; -+} -+ -+static int mipv6_rr_state(struct mipv6_bul_entry *bul, struct in6_addr *saddr, -+ struct in6_addr *coa, __u8 flags) -+{ -+ if (!rr_configured) -+ return NO_RR; -+ if (flags & MIPV6_BU_F_HOME) { -+ /* We don't need RR, this is a Home Registration */ -+ return NO_RR; -+ } -+ if (!bul || !bul->rr) { -+ /* First time BU to CN, need RR */ -+ return DO_RR; -+ } -+ -+ switch (bul->rr->rr_state) { -+ case RR_INIT: -+ /* Need RR if first BU to CN */ -+ return DO_RR; -+ case RR_DONE: -+ /* If MN moves to a new coa, do RR for it */ -+ if (!ipv6_addr_cmp(&bul->coa, coa)) -+ return NO_RR; -+ else -+ return DO_RR; -+ default: -+ /* -+ * We are in the middle of RR, the HoTI and CoTI have been -+ * sent. But we haven't got HoT and CoT from the CN, so -+ * don't do anything more at this time. -+ */ -+ return INPROGRESS_RR; -+ } -+} -+ -+/** -+ * mipv6_RR_start - Start Return Routability procedure -+ * @home_addr: home address -+ * @cn_addr: correspondent address -+ * @coa: care-of address -+ * @entry: binding update list entry (if any) -+ * @initdelay: initial ack timeout -+ * @maxackdelay: maximum ack timeout -+ * @flags: flags -+ * @lifetime: lifetime of binding -+ * @ops: mobility options -+ * -+ * Caller must hold @bul_lock (write). -+ **/ -+static int mipv6_RR_start(struct in6_addr *home_addr, struct in6_addr *cn_addr, -+ struct in6_addr *coa, struct mipv6_bul_entry *entry, -+ __u32 initdelay, __u32 maxackdelay, __u8 flags, -+ __u32 lifetime, struct mipv6_mh_opt *ops) -+{ -+ int ret = -1; -+ struct mipv6_bul_entry *bulentry = entry; -+ struct mipv6_rr_info *rr = NULL; -+ int seq = 0; -+ DEBUG_FUNC(); -+ -+ /* Do RR procedure only for care-of address after handoff, -+ if home cookie is still valid */ -+ if (bulentry && bulentry->rr) { -+ if (time_before(jiffies, bulentry->rr->home_time + MAX_NONCE_LIFE * HZ) && -+ lifetime && !(ipv6_addr_cmp(home_addr, coa) == 0)) { -+ mipv6_rr_mn_cookie_create(bulentry->rr->cot_cookie); -+ DEBUG(DBG_INFO, "Bul entry and rr info exist, only doing RR for CoA"); -+ ipv6_addr_copy(&bulentry->coa, coa); -+ bulentry->rr->rr_state |= RR_WAITC; -+ } else if (!lifetime) { /* Send only HoTi when returning home */ -+ mipv6_rr_mn_cookie_create(bulentry->rr->hot_cookie); -+ DEBUG(DBG_INFO, "Bul entry and rr info exist, only doing RR for HoA"); -+ ipv6_addr_copy(&bulentry->coa, coa); /* Home address as CoA */ -+ bulentry->rr->rr_state |= RR_WAITH; -+ } -+ } else { -+ DEBUG(DBG_INFO, "Doing RR for both HoA and CoA"); -+ rr = kmalloc(sizeof(*rr), GFP_ATOMIC); -+ memset(rr, 0, sizeof(*rr)); -+ rr->rr_state = RR_WAITHC; -+ } -+ if (bulentry) { -+ if (bulentry->state == ACK_ERROR) -+ goto out; -+ seq = bulentry->seq + 1; -+ } else -+ seq = 0; -+ /* Save the info in the BUL to retransmit the BU after RR is done */ -+ /* Caller must hold bul_lock (write) since we don't */ -+ -+ if ((bulentry = mipv6_bul_add(cn_addr, home_addr, coa, -+ min_t(__u32, lifetime, MAX_RR_BINDING_LIFE), -+ seq, flags, bul_resend_exp, initdelay, -+ RESEND_EXP, initdelay, -+ maxackdelay, ops, -+ rr)) == NULL) { -+ DEBUG(DBG_INFO, "couldn't update BUL for HoTi"); -+ goto out; -+ } -+ -+ rr = bulentry->rr; -+ if (rr->rr_state&RR_WAITH) -+ mipv6_send_addr_test_init(home_addr, cn_addr, MIPV6_MH_HOTI, -+ rr->hot_cookie); -+ if (ipv6_addr_cmp(home_addr, coa) && lifetime) -+ mipv6_send_addr_test_init(coa, cn_addr, MIPV6_MH_COTI, rr->cot_cookie); -+ else { -+ bulentry->rr->rr_state &= ~RR_WAITC; -+ } -+ ret = 0; -+out: -+ return ret; -+} -+ -+/* -+ * Status codes for mipv6_ba_rcvd() -+ */ -+#define STATUS_UPDATE 0 -+#define STATUS_REMOVE 1 -+ -+/** -+ * mipv6_ba_rcvd - Update BUL for this Binding Acknowledgement -+ * @ifindex: interface BA came from -+ * @cnaddr: sender IPv6 address -+ * @home_addr: home address -+ * @sequence: sequence number -+ * @lifetime: lifetime granted by Home Agent in seconds -+ * @refresh: recommended resend interval -+ * @status: %STATUS_UPDATE (ack) or %STATUS_REMOVE (nack) -+ * -+ * This function must be called to notify the module of the receipt of -+ * a binding acknowledgement so that it can cease retransmitting the -+ * option. The caller must have validated the acknowledgement before calling -+ * this function. 'status' can be either STATUS_UPDATE in which case the -+ * binding acknowledgement is assumed to be valid and the corresponding -+ * binding update list entry is updated, or STATUS_REMOVE in which case -+ * the corresponding binding update list entry is removed (this can be -+ * used upon receiving a negative acknowledgement). -+ * Returns 0 if a matching binding update has been sent or non-zero if -+ * not. -+ */ -+static int mipv6_ba_rcvd(int ifindex, struct in6_addr *cnaddr, -+ struct in6_addr *home_addr, -+ u16 sequence, u32 lifetime, -+ u32 refresh, int status) -+{ -+ struct mipv6_bul_entry *bulentry; -+ unsigned long now = jiffies; -+ struct in6_addr coa; -+ -+ DEBUG(DBG_INFO, "BA received with sequence number 0x%x, status: %d", -+ (int) sequence, status); -+ -+ /* Find corresponding entry in binding update list. */ -+ write_lock(&bul_lock); -+ if ((bulentry = mipv6_bul_get(cnaddr, home_addr)) == NULL) { -+ DEBUG(DBG_INFO, "- discarded, no entry in bul matches BA source address"); -+ write_unlock(&bul_lock); -+ return -1; -+ } -+ -+ ipv6_addr_copy(&coa, &bulentry->coa); -+ if (status == SEQUENCE_NUMBER_OUT_OF_WINDOW) { -+ __u32 lifetime = mipv6_mn_get_bulifetime(&bulentry->home_addr, -+ &bulentry->coa, -+ bulentry->flags); -+ bulentry->seq = sequence; -+ -+ mipv6_send_bu(&bulentry->home_addr, &bulentry->cn_addr, -+ &bulentry->coa, INITIAL_BINDACK_TIMEOUT, -+ MAX_BINDACK_TIMEOUT, 1, bulentry->flags, -+ lifetime, NULL); -+ write_unlock(&bul_lock); -+ return 0; -+ } else if (status >= REASON_UNSPECIFIED) { -+ int err; -+ int at_home = MN_NOT_AT_HOME; -+ DEBUG(DBG_WARNING, "- NACK - BA status: %d, deleting bul entry", status); -+ if (bulentry->flags & MIPV6_BU_F_HOME) { -+ struct mn_info *minfo; -+ read_lock(&mn_info_lock); -+ minfo = mipv6_mninfo_get_by_home(home_addr); -+ if (minfo) { -+ spin_lock(&minfo->lock); -+ if (minfo->is_at_home != MN_NOT_AT_HOME) -+ minfo->is_at_home = MN_AT_HOME; -+ at_home = minfo->is_at_home; -+ minfo->has_home_reg = 0; -+ spin_unlock(&minfo->lock); -+ } -+ read_unlock(&mn_info_lock); -+ DEBUG(DBG_ERROR, "Home registration failed: BA status: %d, deleting bul entry", status); -+ } -+ write_unlock(&bul_lock); -+ err = mipv6_bul_delete(cnaddr, home_addr); -+ if (at_home == MN_AT_HOME) { -+ mipv6_mn_send_home_na(home_addr); -+ write_lock_bh(&bul_lock); -+ mipv6_bul_iterate(mn_cn_handoff, &coa); -+ write_unlock_bh(&bul_lock); -+ } -+ return err; -+ } -+ bulentry->state = ACK_OK; -+ -+ if (bulentry->flags & MIPV6_BU_F_HOME && lifetime > 0) { -+ /* For home registrations: schedule a refresh binding update. -+ * Use the refresh interval given by home agent or 80% -+ * of lifetime, whichever is less. -+ * -+ * Adjust binding lifetime if 'granted' lifetime -+ * (lifetime value in received binding acknowledgement) -+ * is shorter than 'requested' lifetime (lifetime -+ * value sent in corresponding binding update). -+ * max((L_remain - (L_update - L_ack)), 0) -+ */ -+ if (lifetime * HZ < (bulentry->expire - bulentry->lastsend)) { -+ bulentry->expire = -+ max_t(__u32, bulentry->expire - -+ ((bulentry->expire - bulentry->lastsend) - -+ lifetime * HZ), jiffies + -+ ERROR_DEF_LIFETIME * HZ); -+ } -+ if (refresh > lifetime || refresh == 0) -+ refresh = 4 * lifetime / 5; -+ DEBUG(DBG_INFO, "setting callback for expiration of" -+ " a Home Registration: lifetime:%d, refresh:%d", -+ lifetime, refresh); -+ bulentry->callback = bul_refresh; -+ bulentry->callback_time = now + refresh * HZ; -+ bulentry->expire = now + lifetime * HZ; -+ bulentry->lifetime = lifetime; -+ if (time_after_eq(jiffies, bulentry->expire)) { -+ /* Sanity check */ -+ DEBUG(DBG_ERROR, "bul entry expire time in history - setting expire to %u secs", -+ ERROR_DEF_LIFETIME); -+ bulentry->expire = jiffies + ERROR_DEF_LIFETIME * HZ; -+ } -+ mipv6_mn_set_home_reg(home_addr, 1); -+ mipv6_bul_iterate(mn_cn_handoff, &coa); -+ } else if ((bulentry->flags & MIPV6_BU_F_HOME) && bulentry->lifetime == 0) { -+ write_unlock(&bul_lock); -+ DEBUG(DBG_INFO, "Got BA for deregistration BU"); -+ mipv6_mn_set_home_reg(home_addr, 0); -+ mipv6_bul_delete(cnaddr, home_addr); -+ mipv6_mn_send_home_na(home_addr); -+ -+ write_lock_bh(&bul_lock); -+ mipv6_bul_iterate(mn_cn_handoff, &coa); -+ write_unlock_bh(&bul_lock); -+ return 0; -+ } -+ -+ mipv6_bul_reschedule(bulentry); -+ write_unlock(&bul_lock); -+ -+ return 0; -+} -+ -+static int mipv6_handle_mh_HC_test(struct sk_buff *skb, -+ struct in6_addr *saddr, -+ struct in6_addr *fcoa, -+ struct in6_addr *cn, -+ struct in6_addr *lcoa, -+ struct mipv6_mh *mh) -+{ -+ int ret = 0; -+ int msg_len = (mh->length+1) << 3; -+ int opt_len; -+ -+ struct mipv6_mh_addr_test *tm = (struct mipv6_mh_addr_test *)mh->data; -+ struct mipv6_bul_entry *bulentry; -+ -+ DEBUG_FUNC(); -+ -+ if (msg_len > skb->len) -+ return -1; -+ -+ opt_len = msg_len - sizeof(*mh) - sizeof(*tm); -+ -+ if (opt_len < 0) { -+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw; -+ icmpv6_send(skb, ICMPV6_PARAMPROB, -+ ICMPV6_HDR_FIELD, pos, skb->dev); -+ -+ DEBUG(DBG_INFO, "Mobility Header length less than H/C Test"); -+ return -1; -+ } -+ if (fcoa || lcoa) { -+ DEBUG(DBG_INFO, "H/C Test has HAO or RTH2, dropped."); -+ return -1; -+ } -+ write_lock(&bul_lock); -+ -+ /* We need to get the home address, since CoT only has the CoA*/ -+ if (mh->type == MIPV6_MH_COT) { -+ if ((bulentry = mipv6_bul_get_by_ccookie(cn, tm->init_cookie)) == NULL) { -+ DEBUG(DBG_ERROR, "has no BUL or RR state for " -+ "source:%x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(cn)); -+ write_unlock(&bul_lock); -+ return -1; -+ } -+ } else { /* HoT has the home address */ -+ if (((bulentry = mipv6_bul_get(cn, saddr)) == NULL) || !bulentry->rr) { -+ DEBUG(DBG_ERROR, "has no BUL or RR state for " -+ "source:%x:%x:%x:%x:%x:%x:%x:%x " -+ "dest:%x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(cn), NIPV6ADDR(saddr)); -+ write_unlock(&bul_lock); -+ return -1; -+ } -+ } -+ -+ switch (mh->type) { -+ case MIPV6_MH_HOT: -+ if ((bulentry->rr->rr_state & RR_WAITH) == 0) { -+ DEBUG(DBG_ERROR, "Not waiting for a Home Test message"); -+ goto out; -+ } -+ /* -+ * Make sure no home cookies have been received yet. -+ * TODO: Check not being put in at this time since subsequent -+ * BU's after this time will have home cookie stored. -+ */ -+ -+ /* Check if the cookie received is the right one */ -+ if (!mipv6_equal_cookies(tm->init_cookie, -+ bulentry->rr->hot_cookie)) { -+ /* Invalid cookie, might be an old cookie */ -+ DEBUG(DBG_WARNING, "Received HoT cookie does not match stored cookie"); -+ goto out; -+ } -+ DEBUG(DBG_INFO, "Got Care-of Test message"); -+ bulentry->rr->rr_state &= ~RR_WAITH; -+ memcpy(bulentry->rr->home_cookie, tm->kgen_token, MIPV6_COOKIE_LEN); -+ bulentry->rr->home_nonce_index = tm->nonce_index; -+ bulentry->rr->home_time = jiffies; -+ ret = 1; -+ break; -+ -+ case MIPV6_MH_COT: -+ if ((bulentry->rr->rr_state & RR_WAITC) == 0) { -+ DEBUG(DBG_ERROR, "Not waiting for a Home Test message"); -+ goto out; -+ } -+ /* -+ * Make sure no home cookies have been received yet. -+ * TODO: Check not being put in at this time since subsequent -+ * BU's at this time will have careof cookie stored. -+ */ -+ -+ /* Check if the cookie received is the right one */ -+ if (!mipv6_equal_cookies(tm->init_cookie, -+ bulentry->rr->cot_cookie)) { -+ DEBUG(DBG_INFO, "Received CoT cookie does not match stored cookie"); -+ goto out; -+ } -+ bulentry->rr->rr_state &= ~RR_WAITC; -+ memcpy(bulentry->rr->careof_cookie, tm->kgen_token, MIPV6_COOKIE_LEN); -+ bulentry->rr->careof_nonce_index = tm->nonce_index; -+ bulentry->rr->careof_time = jiffies; -+ ret = 1; -+ break; -+ default: -+ /* Impossible to get here */ -+ break; -+ } -+out: -+ if (bulentry->rr->rr_state == RR_DONE) { -+ if (bulentry->rr->kbu) /* First free any old keys */ -+ kfree(bulentry->rr->kbu); -+ /* Store the session key to be used in BU's */ -+ if (ipv6_addr_cmp(&bulentry->coa, &bulentry->home_addr) && bulentry->lifetime) -+ bulentry->rr->kbu = mipv6_rr_key_calc(bulentry->rr->home_cookie, -+ bulentry->rr->careof_cookie); -+ else -+ bulentry->rr->kbu = mipv6_rr_key_calc(bulentry->rr->home_cookie, -+ NULL); -+ /* RR procedure is over, send a BU */ -+ mipv6_send_RR_bu(bulentry); -+ } -+ write_unlock(&bul_lock); -+ return ret; -+} -+ -+/** -+ * mipv6_handle_mh_brr - Binding Refresh Request handler -+ * @home: home address -+ * @coa: care-of address -+ * @cn: source of this packet -+ * @mh: pointer to the beginning of the Mobility Header -+ * -+ * Handles Binding Refresh Request. Packet and offset to option are -+ * passed. Returns 0 on success, otherwise negative. -+ **/ -+static int mipv6_handle_mh_brr(struct sk_buff *skb, -+ struct in6_addr *home, -+ struct in6_addr *unused1, -+ struct in6_addr *cn, -+ struct in6_addr *unused2, -+ struct mipv6_mh *mh) -+{ -+ struct mipv6_mh_brr *brr = (struct mipv6_mh_brr *)mh->data; -+ struct mipv6_bul_entry *binding; -+ int msg_len = (mh->length+1) << 3; -+ int opt_len; -+ -+ if (msg_len > skb->len) -+ return -1; -+ -+ opt_len = msg_len - sizeof(*mh) - sizeof(*brr); -+ -+ if (opt_len < 0) { -+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw; -+ icmpv6_send(skb, ICMPV6_PARAMPROB, -+ ICMPV6_HDR_FIELD, pos, skb->dev); -+ -+ DEBUG(DBG_WARNING, "Mobility Header length less than BRR"); -+ MIPV6_INC_STATS(n_brr_drop.invalid); -+ return -1; -+ } -+ -+ /* check we know src, else drop */ -+ write_lock(&bul_lock); -+ if ((binding = mipv6_bul_get(cn, home)) == NULL) { -+ MIPV6_INC_STATS(n_brr_drop.misc); -+ write_unlock(&bul_lock); -+ return MH_UNKNOWN_CN; -+ } -+ -+ MIPV6_INC_STATS(n_brr_rcvd); -+ -+ if (opt_len > 0) { -+ struct mobopt opts; -+ memset(&opts, 0, sizeof(opts)); -+ if (parse_mo_tlv(brr + 1, opt_len, &opts) < 0) { -+ write_unlock(&bul_lock); -+ return -1; -+ } -+ /* -+ * MIPV6_OPT_AUTH_DATA -+ */ -+ } -+ -+ /* must hold bul_lock (write) */ -+ mipv6_RR_start(home, cn, &binding->coa, binding, binding->delay, -+ binding->maxdelay, binding->flags, -+ binding->lifetime, binding->ops); -+ -+ write_unlock(&bul_lock); -+ /* MAY also decide to delete binding and send zero lifetime BU -+ with alt-coa set to home address */ -+ -+ return 0; -+} -+ -+/** -+ * mipv6_handle_mh_ba - Binding Acknowledgement handler -+ * @src: source of this packet -+ * @coa: care-of address -+ * @home: home address -+ * @mh: pointer to the beginning of the Mobility Header -+ * -+ **/ -+static int mipv6_handle_mh_ba(struct sk_buff *skb, -+ struct in6_addr *home, -+ struct in6_addr *coa, -+ struct in6_addr *src, -+ struct in6_addr *unused, -+ struct mipv6_mh *mh) -+{ -+ struct mipv6_mh_ba *ba = (struct mipv6_mh_ba *)mh->data; -+ struct mipv6_bul_entry *binding = NULL; -+ struct mobopt opts; -+ int msg_len = (mh->length+1) << 3; -+ int opt_len; -+ -+ int auth = 1, req_auth = 1, refresh = -1, ifindex = 0; -+ u32 lifetime, sequence; -+ -+ if (msg_len > skb->len) -+ return -1; -+ -+ opt_len = msg_len - sizeof(*mh) - sizeof(*ba); -+ -+ if (opt_len < 0) { -+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw; -+ icmpv6_send(skb, ICMPV6_PARAMPROB, -+ ICMPV6_HDR_FIELD, pos, skb->dev); -+ -+ DEBUG(DBG_WARNING, "Mobility Header length less than BA"); -+ MIPV6_INC_STATS(n_ba_drop.invalid); -+ return -1; -+ } -+ -+ lifetime = ntohs(ba->lifetime) << 2; -+ sequence = ntohs(ba->sequence); -+ -+ if (opt_len > 0) { -+ memset(&opts, 0, sizeof(opts)); -+ if (parse_mo_tlv(ba + 1, opt_len, &opts) < 0) -+ return -1; -+ /* -+ * MIPV6_OPT_AUTH_DATA, MIPV6_OPT_BR_ADVICE -+ */ -+ if (opts.br_advice) -+ refresh = ntohs(opts.br_advice->refresh_interval); -+ } -+ -+ if (ba->status >= EXPIRED_HOME_NONCE_INDEX && -+ ba->status <= EXPIRED_NONCES) -+ req_auth = 0; -+ -+ write_lock(&bul_lock); -+ binding = mipv6_bul_get(src, home); -+ if (!binding) { -+ DEBUG(DBG_INFO, "No binding, BA dropped."); -+ write_unlock(&bul_lock); -+ return -1; -+ } -+ -+ if (opts.auth_data && binding->rr && -+ (mipv6_auth_check(src, coa, (__u8 *)mh, msg_len, -+ opts.auth_data, binding->rr->kbu) == 0)) -+ auth = 1; -+ -+ if (req_auth && binding->rr && !auth) { -+ DEBUG(DBG_INFO, "BA Authentication failed."); -+ MIPV6_INC_STATS(n_ba_drop.auth); -+ write_unlock(&bul_lock); -+ return MH_AUTH_FAILED; -+ } -+ -+ if (ba->status == SEQUENCE_NUMBER_OUT_OF_WINDOW) { -+ DEBUG(DBG_INFO, -+ "Sequence number out of window, setting seq to %d", -+ sequence); -+ } else if (binding->seq != sequence) { -+ DEBUG(DBG_INFO, "BU/BA Sequence Number mismatch %d != %d", -+ binding->seq, sequence); -+ MIPV6_INC_STATS(n_ba_drop.invalid); -+ write_unlock(&bul_lock); -+ return MH_SEQUENCE_MISMATCH; -+ } -+ if (ba->status == EXPIRED_HOME_NONCE_INDEX || ba->status == EXPIRED_NONCES) { -+ if (binding->rr) { -+ /* Need to resend home test init to CN */ -+ binding->rr->rr_state |= RR_WAITH; -+ mipv6_send_addr_test_init(&binding->home_addr, -+ &binding->cn_addr, -+ MIPV6_MH_HOTI, -+ binding->rr->hot_cookie); -+ MIPV6_INC_STATS(n_ban_rcvd); -+ } else { -+ DEBUG(DBG_WARNING, "Got BA with status EXPIRED_HOME_NONCE_INDEX" -+ "for non-RR BU"); -+ MIPV6_INC_STATS(n_ba_drop.invalid); -+ } -+ write_unlock(&bul_lock); -+ return 0; -+ } -+ if (ba->status == EXPIRED_CAREOF_NONCE_INDEX || ba->status == EXPIRED_NONCES) { -+ if (binding->rr) { -+ /* Need to resend care-of test init to CN */ -+ binding->rr->rr_state |= RR_WAITC; -+ mipv6_send_addr_test_init(&binding->coa, -+ &binding->cn_addr, -+ MIPV6_MH_COTI, -+ binding->rr->cot_cookie); -+ MIPV6_INC_STATS(n_ban_rcvd); -+ } else { -+ DEBUG(DBG_WARNING, "Got BA with status EXPIRED_HOME_CAREOF_INDEX" -+ "for non-RR BU"); -+ MIPV6_INC_STATS(n_ba_drop.invalid); -+ } -+ write_unlock(&bul_lock); -+ return 0; -+ } -+ write_unlock(&bul_lock); -+ -+ if (ba->status >= REASON_UNSPECIFIED) { -+ DEBUG(DBG_INFO, "Binding Ack status : %d indicates error", ba->status); -+ mipv6_ba_rcvd(ifindex, src, home, sequence, lifetime, -+ refresh, ba->status); -+ MIPV6_INC_STATS(n_ban_rcvd); -+ return 0; -+ } -+ MIPV6_INC_STATS(n_ba_rcvd); -+ if (mipv6_ba_rcvd(ifindex, src, home, ntohs(ba->sequence), lifetime, -+ refresh, ba->status)) { -+ DEBUG(DBG_WARNING, "mipv6_ba_rcvd failed"); -+ } -+ -+ return 0; -+} -+ -+/** -+ * mipv6_handle_mh_be - Binding Error handler -+ * @cn: source of this packet -+ * @coa: care-of address -+ * @home: home address -+ * @mh: pointer to the beginning of the Mobility Header -+ * -+ **/ -+ -+static int mipv6_handle_mh_be(struct sk_buff *skb, -+ struct in6_addr *home, -+ struct in6_addr *coa, -+ struct in6_addr *cn, -+ struct in6_addr *unused, -+ struct mipv6_mh *mh) -+{ -+ struct mipv6_mh_be *be = (struct mipv6_mh_be *)mh->data; -+ int msg_len = (mh->length+1) << 3; -+ int opt_len; -+ struct in6_addr *hoa; -+ struct bul_inval_args args; -+ -+ DEBUG_FUNC(); -+ -+ if (msg_len > skb->len) -+ return -1; -+ -+ opt_len = msg_len - sizeof(*mh) - sizeof(*be); -+ -+ if (opt_len < 0) { -+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw; -+ icmpv6_send(skb, ICMPV6_PARAMPROB, -+ ICMPV6_HDR_FIELD, pos, skb->dev); -+ -+ DEBUG(DBG_WARNING, "Mobility Header length less than BE"); -+ MIPV6_INC_STATS(n_be_drop.invalid); -+ return -1; -+ } -+ -+ -+ if (!ipv6_addr_any(&be->home_addr)) -+ hoa = &be->home_addr; -+ else -+ hoa = home; -+ -+ MIPV6_INC_STATS(n_be_rcvd); -+ -+ args.all_rr_states = 0; -+ args.cn = cn; -+ args.mn = hoa; -+ -+ switch (be->status) { -+ case 1: /* Home Address Option used without a binding */ -+ /* Get ULP information about CN-MN communication. If -+ nothing in progress, MUST delete. Otherwise MAY -+ ignore. */ -+ args.all_rr_states = 1; -+ case 2: /* Received unknown MH type */ -+ /* If not expecting ack, SHOULD ignore. If MH -+ extension in use, stop it. If not, stop RO for -+ this CN. */ -+ write_lock(&bul_lock); -+ mipv6_bul_iterate(mn_bul_invalidate, &args); -+ write_unlock(&bul_lock); -+ break; -+ } -+ -+ return 0; -+} -+ -+/* -+ * mipv6_bu_rate_limit() : Takes a bulentry, a COA and 'flags' to check -+ * whether BU being sent is for Home Registration or not. -+ * -+ * If the number of BU's sent is fewer than MAX_FAST_UPDATES, this BU -+ * is allowed to be sent at the MAX_UPDATE_RATE. -+ * If the number of BU's sent is greater than or equal to MAX_FAST_UPDATES, -+ * this BU is allowed to be sent at the SLOW_UPDATE_RATE. -+ * -+ * Assumption : This function is not re-entrant. and the caller holds the -+ * bulentry lock (by calling mipv6_bul_get()) to stop races with other -+ * CPU's executing this same function. -+ * -+ * Side-Effects. Either of the following could on success : -+ * 1. Sets consecutive_sends to 1 if the entry is a Home agent -+ * registration or the COA has changed. -+ * 2. Increments consecutive_sends if the number of BU's sent so -+ * far is less than MAX_FAST_UPDATES, and this BU is being sent -+ * atleast MAX_UPDATE_RATE after previous one. -+ * -+ * Return Value : 0 on Success, -1 on Failure -+ */ -+static int mipv6_bu_rate_limit(struct mipv6_bul_entry *bulentry, -+ struct in6_addr *coa, __u8 flags) -+{ -+ if ((flags & MIPV6_BU_F_HOME) || ipv6_addr_cmp(&bulentry->coa, coa)) { -+ /* Home Agent Registration or different COA - restart from 1 */ -+ bulentry->consecutive_sends = 1; -+ return 0; -+ } -+ -+ if (bulentry->consecutive_sends < MAX_FAST_UPDATES) { -+ /* First MAX_FAST_UPDATES can be sent at MAX_UPDATE_RATE */ -+ if (jiffies - bulentry->lastsend < MAX_UPDATE_RATE * HZ) { -+ return -1; -+ } -+ bulentry->consecutive_sends ++; -+ } else { -+ /* Remaining updates SHOULD be sent at SLOW_UPDATE_RATE */ -+ if (jiffies - bulentry->lastsend < SLOW_UPDATE_RATE * HZ) { -+ return -1; -+ } -+ /* Don't inc 'consecutive_sends' to avoid overflow to zero */ -+ } -+ /* OK to send a BU */ -+ return 0; -+} -+ -+/** -+ * mipv6_send_bu - send a Binding Update -+ * @saddr: source address for BU -+ * @daddr: destination address for BU -+ * @coa: care-of address for MN -+ * @initdelay: initial BA wait timeout -+ * @maxackdelay: maximum BA wait timeout -+ * @exp: exponention back off -+ * @flags: flags for BU -+ * @lifetime: granted lifetime for binding -+ * @ops: mobility options -+ * -+ * Send a binding update. 'flags' may contain any of %MIPV6_BU_F_ACK, -+ * %MIPV6_BU_F_HOME, %MIPV6_BU_F_ROUTER bitwise ORed. If -+ * %MIPV6_BU_F_ACK is included retransmission will be attempted until -+ * the update has been acknowledged. Retransmission is done if no -+ * acknowledgement is received within @initdelay seconds. @exp -+ * specifies whether to use exponential backoff (@exp != 0) or linear -+ * backoff (@exp == 0). For exponential backoff the time to wait for -+ * an acknowledgement is doubled on each retransmission until a delay -+ * of @maxackdelay, after which retransmission is no longer attempted. -+ * For linear backoff the delay is kept constant and @maxackdelay -+ * specifies the maximum number of retransmissions instead. If -+ * sub-options are present ops must contain all sub-options to be -+ * added. On a mobile node, use the mobile node's home address for -+ * @saddr. Returns 0 on success, non-zero on failure. -+ * -+ * Caller may not hold @bul_lock. -+ **/ -+int mipv6_send_bu(struct in6_addr *saddr, struct in6_addr *daddr, -+ struct in6_addr *coa, u32 initdelay, -+ u32 maxackdelay, u8 exp, u8 flags, u32 lifetime, -+ struct mipv6_mh_opt *ops) -+{ -+ int ret; -+ __u8 state; -+ __u16 seq = 0; -+ int (*callback)(struct mipv6_bul_entry *); -+ __u32 callback_time; -+ struct mipv6_bul_entry *bulentry; -+ -+ /* First a sanity check: don't send BU to local addresses */ -+ if(ipv6_chk_addr(daddr, NULL)) { -+ DEBUG(DBG_ERROR, "BUG: Trying to send BU to local address"); -+ return -1; -+ } -+ DEBUG(DBG_INFO, "Sending BU to CN %x:%x:%x:%x:%x:%x:%x:%x " -+ "for home address %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(daddr), NIPV6ADDR(saddr)); -+ -+ if ((bulentry = mipv6_bul_get(daddr, saddr)) != NULL) { -+ if (bulentry->state == ACK_ERROR) { -+ /* -+ * Don't send any more BU's to nodes which don't -+ * understanding one. -+ */ -+ DEBUG(DBG_INFO, "Not sending BU to node which doesn't" -+ " understand one"); -+ return -1; -+ } -+ if (mipv6_bu_rate_limit(bulentry, coa, flags) < 0) { -+ DEBUG(DBG_DATADUMP, "Limiting BU sent."); -+ return 0; -+ } -+ } -+ -+ switch (mipv6_rr_state(bulentry, saddr, coa, flags)) { -+ case INPROGRESS_RR: -+ /* We are already doing RR, don't do BU at this time, it is -+ * done automatically later */ -+ DEBUG(DBG_INFO, "RR in progress not sending BU"); -+ return 0; -+ -+ case DO_RR: -+ /* Just do RR and return, BU is done automatically later */ -+ DEBUG(DBG_INFO, "starting RR" ); -+ mipv6_RR_start(saddr, daddr, coa, bulentry, initdelay, -+ maxackdelay, flags, lifetime, ops); -+ return 0; -+ -+ case NO_RR: -+ DEBUG(DBG_DATADUMP, "No RR necessary" ); -+ default: -+ break; -+ } -+ -+ if (bulentry) -+ seq = bulentry->seq + 1; -+ -+ /* Add to binding update list */ -+ -+ if (flags & MIPV6_BU_F_ACK) { -+ DEBUG(DBG_INFO, "Setting bul callback to bul_resend_exp"); -+ /* Send using exponential backoff */ -+ state = RESEND_EXP; -+ callback = bul_resend_exp; -+ callback_time = initdelay; -+ } else { -+ DEBUG(DBG_INFO, "Setting bul callback to bul_entry_expired"); -+ /* No acknowledgement/resending required */ -+ state = ACK_OK; /* pretend we got an ack */ -+ callback = bul_entry_expired; -+ callback_time = lifetime; -+ } -+ -+ /* BU only for the home address */ -+ /* We must hold bul_lock (write) while calling add */ -+ if ((bulentry = mipv6_bul_add(daddr, saddr, coa, lifetime, seq, -+ flags, callback, callback_time, -+ state, initdelay, maxackdelay, ops, -+ NULL)) == NULL) { -+ DEBUG(DBG_INFO, "couldn't update BUL"); -+ return 0; -+ } -+ ret = send_bu_msg(bulentry); -+ -+ return ret; -+} -+ -+int __init mipv6_mh_mn_init(void) -+{ -+ mipv6_mh_register(MIPV6_MH_HOT, mipv6_handle_mh_HC_test); -+ mipv6_mh_register(MIPV6_MH_COT, mipv6_handle_mh_HC_test); -+ mipv6_mh_register(MIPV6_MH_BA, mipv6_handle_mh_ba); -+ mipv6_mh_register(MIPV6_MH_BRR, mipv6_handle_mh_brr); -+ mipv6_mh_register(MIPV6_MH_BE, mipv6_handle_mh_be); -+ -+ return 0; -+} -+ -+void __exit mipv6_mh_mn_exit(void) -+{ -+ mipv6_mh_unregister(MIPV6_MH_HOT); -+ mipv6_mh_unregister(MIPV6_MH_COT); -+ mipv6_mh_unregister(MIPV6_MH_BA); -+ mipv6_mh_unregister(MIPV6_MH_BRR); -+ mipv6_mh_unregister(MIPV6_MH_BE); -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/module_cn.c linux-2.4.25/net/ipv6/mobile_ip6/module_cn.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/module_cn.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/module_cn.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,167 @@ -+/* -+ * Mobile IPv6 Common Module -+ * -+ * Authors: -+ * Sami Kivisaari -+ * Antti Tuominen -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 -+ -+#ifdef CONFIG_SYSCTL -+#include -+#endif /* CONFIG_SYSCTL */ -+ -+#include -+ -+#include "bcache.h" -+#include "mipv6_icmp.h" -+#include "stats.h" -+#include "mobhdr.h" -+#include "exthdrs.h" -+ -+int mipv6_debug = 1; -+ -+#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115 -+MODULE_AUTHOR("MIPL Team"); -+MODULE_DESCRIPTION("Mobile IPv6"); -+MODULE_LICENSE("GPL"); -+MODULE_PARM(mipv6_debug, "i"); -+#endif -+ -+#include "config.h" -+ -+struct mip6_func mip6_fn; -+struct mip6_conf mip6node_cnf = { -+ capabilities: CAP_CN, -+ accept_ret_rout: 1, -+ max_rtr_reachable_time: 0, -+ eager_cell_switching: 0, -+ max_num_tunnels: 0, -+ min_num_tunnels: 0, -+ binding_refresh_advice: 0, -+ bu_lladdr: 0, -+ bu_keymgm: 0, -+ bu_cn_ack: 0 -+}; -+ -+#define MIPV6_BCACHE_SIZE 128 -+ -+/********************************************************************** -+ * -+ * MIPv6 CN Module Init / Cleanup -+ * -+ **********************************************************************/ -+ -+#ifdef CONFIG_SYSCTL -+/* Sysctl table */ -+ctl_table mipv6_mobility_table[] = { -+ {NET_IPV6_MOBILITY_DEBUG, "debuglevel", -+ &mipv6_debug, sizeof(int), 0644, NULL, -+ &proc_dointvec}, -+ {NET_IPV6_MOBILITY_RETROUT, "accept_return_routability", -+ &mip6node_cnf.accept_ret_rout, sizeof(int), 0644, NULL, -+ &proc_dointvec}, -+ {0} -+}; -+ctl_table mipv6_table[] = { -+ {NET_IPV6_MOBILITY, "mobility", NULL, 0, 0555, mipv6_mobility_table}, -+ {0} -+}; -+ -+static struct ctl_table_header *mipv6_sysctl_header; -+static struct ctl_table mipv6_net_table[]; -+static struct ctl_table mipv6_root_table[]; -+ -+ctl_table mipv6_net_table[] = { -+ {NET_IPV6, "ipv6", NULL, 0, 0555, mipv6_table}, -+ {0} -+}; -+ -+ctl_table mipv6_root_table[] = { -+ {CTL_NET, "net", NULL, 0, 0555, mipv6_net_table}, -+ {0} -+}; -+#endif /* CONFIG_SYSCTL */ -+ -+extern void mipv6_rr_init(void); -+ -+/* Initialize the module */ -+static int __init mip6_init(void) -+{ -+ int err = 0; -+ -+ printk(KERN_INFO "MIPL Mobile IPv6 for Linux Correspondent Node %s (%s)\n", -+ MIPLVERSION, MIPV6VERSION); -+ -+#ifdef CONFIG_IPV6_MOBILITY_DEBUG -+ printk(KERN_INFO "Debug-level: %d\n", mipv6_debug); -+#endif -+ -+ if ((err = mipv6_bcache_init(MIPV6_BCACHE_SIZE)) < 0) -+ goto bcache_fail; -+ -+ if ((err = mipv6_icmpv6_init()) < 0) -+ goto icmp_fail; -+ -+ if ((err = mipv6_stats_init()) < 0) -+ goto stats_fail; -+ mipv6_rr_init(); -+ -+#ifdef CONFIG_SYSCTL -+ mipv6_sysctl_header = register_sysctl_table(mipv6_root_table, 0); -+#endif -+ -+ if ((err = mipv6_mh_common_init()) < 0) -+ goto mh_fail; -+ -+ MIPV6_SETCALL(mipv6_modify_txoptions, mipv6_modify_txoptions); -+ -+ MIPV6_SETCALL(mipv6_handle_homeaddr, mipv6_handle_homeaddr); -+ MIPV6_SETCALL(mipv6_icmp_swap_addrs, mipv6_icmp_swap_addrs); -+ -+ return 0; -+ -+mh_fail: -+#ifdef CONFIG_SYSCTL -+ unregister_sysctl_table(mipv6_sysctl_header); -+#endif -+ mipv6_stats_exit(); -+stats_fail: -+ mipv6_icmpv6_exit(); -+icmp_fail: -+ mipv6_bcache_exit(); -+bcache_fail: -+ return err; -+} -+module_init(mip6_init); -+ -+#ifdef MODULE -+/* Cleanup module */ -+static void __exit mip6_exit(void) -+{ -+ printk(KERN_INFO "mip6_base.o exiting.\n"); -+#ifdef CONFIG_SYSCTL -+ unregister_sysctl_table(mipv6_sysctl_header); -+#endif -+ -+ /* Invalidate all custom kernel hooks. No need to do this -+ separately for all hooks. */ -+ mipv6_invalidate_calls(); -+ -+ mipv6_mh_common_exit(); -+ mipv6_stats_exit(); -+ mipv6_icmpv6_exit(); -+ mipv6_bcache_exit(); -+} -+module_exit(mip6_exit); -+#endif /* MODULE */ -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/module_ha.c linux-2.4.25/net/ipv6/mobile_ip6/module_ha.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/module_ha.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/module_ha.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,264 @@ -+/* -+ * Mobile IPv6 Home Agent Module -+ * -+ * Authors: -+ * Sami Kivisaari -+ * Antti Tuominen -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 -+ -+#ifdef CONFIG_SYSCTL -+#include -+#endif /* CONFIG_SYSCTL */ -+ -+#include -+#include -+ -+#include "mobhdr.h" -+#include "tunnel_ha.h" -+#include "ha.h" -+#include "halist.h" -+#include "mipv6_icmp.h" -+//#include "prefix.h" -+#include "bcache.h" -+#include "debug.h" -+ -+int mipv6_use_auth = 0; -+ -+#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115 -+MODULE_AUTHOR("MIPL Team"); -+MODULE_DESCRIPTION("Mobile IPv6 Home Agent"); -+MODULE_LICENSE("GPL"); -+#endif -+ -+#include "config.h" -+ -+#define MIPV6_HALIST_SIZE 128 -+struct ha_info_opt { -+ u8 type; -+ u8 len; -+ u16 res; -+ u16 pref; -+ u16 ltime; -+}; -+/* -+ * Called from ndisc.c's router_discovery. -+ */ -+static int mipv6_ha_ra_rcv(struct sk_buff *skb, struct ndisc_options *ndopts) -+{ -+ unsigned int ha_info_pref = 0, ha_info_lifetime; -+ int ifi = ((struct inet6_skb_parm *)skb->cb)->iif; -+ struct ra_msg *ra = (struct ra_msg *) skb->h.raw; -+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr; -+ struct in6_addr ll_addr; -+ struct hal { -+ struct in6_addr prefix; -+ int plen; -+ struct hal *next; -+ }; -+ -+ DEBUG_FUNC(); -+ -+ ha_info_lifetime = ntohs(ra->icmph.icmp6_rt_lifetime); -+ ipv6_addr_copy(&ll_addr, saddr); -+ -+ if (ndopts->nd_opts_hai) { -+ struct ha_info_opt *hai = (struct ha_info_opt *)ndopts->nd_opts_hai; -+ ha_info_pref = ntohs(hai->pref); -+ ha_info_lifetime = ntohs(hai->ltime); -+ DEBUG(DBG_DATADUMP, -+ "received home agent info with preference : %d and lifetime : %d", -+ ha_info_pref, ha_info_lifetime); -+ } -+ if (ndopts->nd_opts_pi) { -+ struct nd_opt_hdr *p; -+ for (p = ndopts->nd_opts_pi; -+ p; -+ p = ndisc_next_option(p, ndopts->nd_opts_pi_end)) { -+ struct prefix_info *pinfo; -+ -+ pinfo = (struct prefix_info *) p; -+ -+ if (pinfo->router_address) { -+ DEBUG(DBG_DATADUMP, "Adding router address to " -+ "ha queue \n"); -+ /* If RA has H bit set and Prefix Info -+ * Option R bit set, queue this -+ * address to be added to Home Agents -+ * List. -+ */ -+ if (ipv6_addr_type(&pinfo->prefix) & -+ IPV6_ADDR_LINKLOCAL) -+ continue; -+ if (!ra->icmph.icmp6_home_agent || !ha_info_lifetime) { -+ mipv6_halist_delete(&pinfo->prefix); -+ continue; -+ } else { -+ -+ mipv6_halist_add(ifi, &pinfo->prefix, -+ pinfo->prefix_len, &ll_addr, -+ ha_info_pref, ha_info_lifetime); -+ } -+ -+ } -+ -+ } -+ } -+ return MIPV6_ADD_RTR; -+} -+ -+/********************************************************************** -+ * -+ * MIPv6 Module Init / Cleanup -+ * -+ **********************************************************************/ -+ -+#ifdef CONFIG_SYSCTL -+/* Sysctl table */ -+extern int -+mipv6_max_tnls_sysctl(ctl_table *, int, struct file *, void *, size_t *); -+ -+extern int -+mipv6_min_tnls_sysctl(ctl_table *, int, struct file *, void *, size_t *); -+ -+int max_adv = ~(u16)0; -+int min_zero = 0; -+ctl_table mipv6_mobility_table[] = { -+ {NET_IPV6_MOBILITY_BINDING_REFRESH, "binding_refresh_advice", -+ &mip6node_cnf.binding_refresh_advice, sizeof(int), 0644, NULL, -+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_zero, &max_adv}, -+ -+ {NET_IPV6_MOBILITY_MAX_TNLS, "max_tnls", &mipv6_max_tnls, sizeof(int), -+ 0644, NULL, &mipv6_max_tnls_sysctl}, -+ {NET_IPV6_MOBILITY_MIN_TNLS, "min_tnls", &mipv6_min_tnls, sizeof(int), -+ 0644, NULL, &mipv6_min_tnls_sysctl}, -+ {0} -+}; -+ctl_table mipv6_table[] = { -+ {NET_IPV6_MOBILITY, "mobility", NULL, 0, 0555, mipv6_mobility_table}, -+ {0} -+}; -+ -+static struct ctl_table_header *mipv6_sysctl_header; -+static struct ctl_table mipv6_net_table[]; -+static struct ctl_table mipv6_root_table[]; -+ -+ctl_table mipv6_net_table[] = { -+ {NET_IPV6, "ipv6", NULL, 0, 0555, mipv6_table}, -+ {0} -+}; -+ -+ctl_table mipv6_root_table[] = { -+ {CTL_NET, "net", NULL, 0, 0555, mipv6_net_table}, -+ {0} -+}; -+#endif /* CONFIG_SYSCTL */ -+ -+extern void mipv6_check_dad(struct in6_addr *haddr); -+extern void mipv6_dad_init(void); -+extern void mipv6_dad_exit(void); -+extern int mipv6_forward(struct sk_buff *); -+ -+/* Initialize the module */ -+static int __init mip6_ha_init(void) -+{ -+ int err = 0; -+ -+ printk(KERN_INFO "MIPL Mobile IPv6 for Linux Home Agent %s (%s)\n", -+ MIPLVERSION, MIPV6VERSION); -+ mip6node_cnf.capabilities = CAP_CN | CAP_HA; -+ -+ mip6_fn.icmpv6_dhaad_rep_rcv = mipv6_icmpv6_no_rcv; -+ mip6_fn.icmpv6_dhaad_req_rcv = mipv6_icmpv6_rcv_dhaad_req; -+ mip6_fn.icmpv6_pfxadv_rcv = mipv6_icmpv6_no_rcv; -+ mip6_fn.icmpv6_pfxsol_rcv = mipv6_icmpv6_no_rcv; -+ mip6_fn.icmpv6_paramprob_rcv = mipv6_icmpv6_no_rcv; -+ -+#ifdef CONFIG_IPV6_MOBILITY_DEBUG -+ printk(KERN_INFO "Debug-level: %d\n", mipv6_debug); -+#endif -+ -+#ifdef CONFIG_SYSCTL -+ mipv6_sysctl_header = register_sysctl_table(mipv6_root_table, 0); -+#endif -+ mipv6_initialize_tunnel(); -+ -+ if ((err = mipv6_ha_init()) < 0) -+ goto ha_fail; -+ -+ MIPV6_SETCALL(mipv6_ra_rcv, mipv6_ha_ra_rcv); -+ MIPV6_SETCALL(mipv6_forward, mipv6_forward); -+ mipv6_dad_init(); -+ MIPV6_SETCALL(mipv6_check_dad, mipv6_check_dad); -+ -+ if ((err = mipv6_halist_init(MIPV6_HALIST_SIZE)) < 0) -+ goto halist_fail; -+ -+// mipv6_initialize_pfx_icmpv6(); -+ -+ return 0; -+ -+halist_fail: -+ mipv6_dad_exit(); -+ mipv6_ha_exit(); -+ha_fail: -+ mipv6_shutdown_tunnel(); -+ -+ mip6_fn.icmpv6_dhaad_rep_rcv = NULL; -+ mip6_fn.icmpv6_dhaad_req_rcv = NULL; -+ mip6_fn.icmpv6_pfxadv_rcv = NULL; -+ mip6_fn.icmpv6_pfxsol_rcv = NULL; -+ mip6_fn.icmpv6_paramprob_rcv = NULL; -+ -+ MIPV6_RESETCALL(mipv6_ra_rcv); -+ MIPV6_RESETCALL(mipv6_forward); -+ MIPV6_RESETCALL(mipv6_check_dad); -+ -+#ifdef CONFIG_SYSCTL -+ unregister_sysctl_table(mipv6_sysctl_header); -+#endif -+ return err; -+} -+module_init(mip6_ha_init); -+ -+#ifdef MODULE -+/* Cleanup module */ -+static void __exit mip6_ha_exit(void) -+{ -+ printk(KERN_INFO "mip6_ha.o exiting.\n"); -+ mip6node_cnf.capabilities &= ~(int)CAP_HA; -+ -+ mipv6_bcache_cleanup(HOME_REGISTRATION); -+ -+ MIPV6_RESETCALL(mipv6_ra_rcv); -+ MIPV6_RESETCALL(mipv6_forward); -+ MIPV6_RESETCALL(mipv6_check_dad); -+ -+ mipv6_halist_exit(); -+// mipv6_shutdown_pfx_icmpv6(); -+ -+ mip6_fn.icmpv6_dhaad_rep_rcv = NULL; -+ mip6_fn.icmpv6_dhaad_req_rcv = NULL; -+ mip6_fn.icmpv6_pfxadv_rcv = NULL; -+ mip6_fn.icmpv6_pfxsol_rcv = NULL; -+ mip6_fn.icmpv6_paramprob_rcv = NULL; -+ -+ mipv6_dad_exit(); -+ mipv6_ha_exit(); -+ mipv6_shutdown_tunnel(); -+#ifdef CONFIG_SYSCTL -+ unregister_sysctl_table(mipv6_sysctl_header); -+#endif -+} -+module_exit(mip6_ha_exit); -+#endif /* MODULE */ -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/module_mn.c linux-2.4.25/net/ipv6/mobile_ip6/module_mn.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/module_mn.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/module_mn.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,188 @@ -+/* -+ * Mobile IPv6 Mobile Node Module -+ * -+ * Authors: -+ * Sami Kivisaari -+ * Antti Tuominen -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 -+ -+#ifdef CONFIG_SYSCTL -+#include -+#endif /* CONFIG_SYSCTL */ -+ -+#include -+ -+extern int mipv6_debug; -+int mipv6_use_auth = 0; -+ -+#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115 -+MODULE_AUTHOR("MIPL Team"); -+MODULE_DESCRIPTION("Mobile IPv6 Mobile Node"); -+MODULE_LICENSE("GPL"); -+MODULE_PARM(mipv6_debug, "i"); -+#endif -+ -+#include "config.h" -+ -+#include "mobhdr.h" -+#include "mn.h" -+#include "mipv6_icmp.h" -+//#include "prefix.h" -+ -+/* TODO: These will go as soon as we get rid of the last two ioctls */ -+extern int mipv6_ioctl_mn_init(void); -+extern void mipv6_ioctl_mn_exit(void); -+ -+/********************************************************************** -+ * -+ * MIPv6 Module Init / Cleanup -+ * -+ **********************************************************************/ -+ -+#ifdef CONFIG_SYSCTL -+/* Sysctl table */ -+ -+extern int max_rtr_reach_time; -+extern int eager_cell_switching; -+ -+static int max_reach = 1000; -+static int min_reach = 1; -+static int max_one = 1; -+static int min_zero = 0; -+ -+extern int -+mipv6_mdetect_mech_sysctl(ctl_table *, int, struct file *, void *, size_t *); -+ -+extern int -+mipv6_router_reach_sysctl(ctl_table *, int, struct file *, void *, size_t *); -+ -+ctl_table mipv6_mobility_table[] = { -+ {NET_IPV6_MOBILITY_BU_F_LLADDR, "bu_flag_lladdr", -+ &mip6node_cnf.bu_lladdr, sizeof(int), 0644, NULL, -+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_zero, &max_one}, -+ {NET_IPV6_MOBILITY_BU_F_KEYMGM, "bu_flag_keymgm", -+ &mip6node_cnf.bu_keymgm, sizeof(int), 0644, NULL, -+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_zero, &max_one}, -+ {NET_IPV6_MOBILITY_BU_F_CN_ACK, "bu_flag_cn_ack", -+ &mip6node_cnf.bu_cn_ack, sizeof(int), 0644, NULL, -+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_zero, &max_one}, -+ -+ {NET_IPV6_MOBILITY_ROUTER_REACH, "max_router_reachable_time", -+ &max_rtr_reach_time, sizeof(int), 0644, NULL, -+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_reach, &max_reach}, -+ -+ {NET_IPV6_MOBILITY_MDETECT_MECHANISM, "eager_cell_switching", -+ &eager_cell_switching, sizeof(int), 0644, NULL, -+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_zero, &max_one}, -+ -+ {0} -+}; -+ctl_table mipv6_table[] = { -+ {NET_IPV6_MOBILITY, "mobility", NULL, 0, 0555, mipv6_mobility_table}, -+ {0} -+}; -+ -+static struct ctl_table_header *mipv6_sysctl_header; -+static struct ctl_table mipv6_net_table[]; -+static struct ctl_table mipv6_root_table[]; -+ -+ctl_table mipv6_net_table[] = { -+ {NET_IPV6, "ipv6", NULL, 0, 0555, mipv6_table}, -+ {0} -+}; -+ -+ctl_table mipv6_root_table[] = { -+ {CTL_NET, "net", NULL, 0, 0555, mipv6_net_table}, -+ {0} -+}; -+#endif /* CONFIG_SYSCTL */ -+ -+/* Initialize the module */ -+static int __init mip6_mn_init(void) -+{ -+ int err = 0; -+ -+ printk(KERN_INFO "MIPL Mobile IPv6 for Linux Mobile Node %s (%s)\n", -+ MIPLVERSION, MIPV6VERSION); -+ mip6node_cnf.capabilities = CAP_CN | CAP_MN; -+ -+#ifdef CONFIG_IPV6_MOBILITY_DEBUG -+ printk(KERN_INFO "Debug-level: %d\n", mipv6_debug); -+#endif -+ -+#ifdef CONFIG_SYSCTL -+ mipv6_sysctl_header = register_sysctl_table(mipv6_root_table, 0); -+#endif -+ if ((err = mipv6_mn_init()) < 0) -+ goto mn_fail; -+ -+ mipv6_mh_mn_init(); -+ -+ mip6_fn.icmpv6_dhaad_rep_rcv = mipv6_icmpv6_rcv_dhaad_rep; -+ mip6_fn.icmpv6_dhaad_req_rcv = mipv6_icmpv6_no_rcv; -+ mip6_fn.icmpv6_pfxadv_rcv = mipv6_icmpv6_no_rcv; -+ mip6_fn.icmpv6_pfxsol_rcv = mipv6_icmpv6_no_rcv; -+ mip6_fn.icmpv6_paramprob_rcv = mipv6_icmpv6_rcv_paramprob; -+ -+// mipv6_initialize_pfx_icmpv6(); -+ -+ if ((err = mipv6_ioctl_mn_init()) < 0) -+ goto ioctl_fail; -+ -+ return 0; -+ -+ioctl_fail: -+// mipv6_shutdown_pfx_icmpv6(); -+ -+ mip6_fn.icmpv6_dhaad_rep_rcv = NULL; -+ mip6_fn.icmpv6_dhaad_req_rcv = NULL; -+ mip6_fn.icmpv6_pfxadv_rcv = NULL; -+ mip6_fn.icmpv6_pfxsol_rcv = NULL; -+ mip6_fn.icmpv6_paramprob_rcv = NULL; -+ -+ mipv6_mh_mn_exit(); -+ mipv6_mn_exit(); -+mn_fail: -+#ifdef CONFIG_SYSCTL -+ unregister_sysctl_table(mipv6_sysctl_header); -+#endif -+ return err; -+} -+module_init(mip6_mn_init); -+ -+#ifdef MODULE -+/* Cleanup module */ -+static void __exit mip6_mn_exit(void) -+{ -+ printk(KERN_INFO "mip6_mn.o exiting.\n"); -+ mip6node_cnf.capabilities &= ~(int)CAP_MN; -+ -+ mipv6_ioctl_mn_exit(); -+// mipv6_shutdown_pfx_icmpv6(); -+ -+ mip6_fn.icmpv6_dhaad_rep_rcv = NULL; -+ mip6_fn.icmpv6_dhaad_req_rcv = NULL; -+ mip6_fn.icmpv6_pfxadv_rcv = NULL; -+ mip6_fn.icmpv6_pfxsol_rcv = NULL; -+ mip6_fn.icmpv6_paramprob_rcv = NULL; -+ -+ mipv6_mn_exit(); -+ -+/* common cleanup */ -+#ifdef CONFIG_SYSCTL -+ unregister_sysctl_table(mipv6_sysctl_header); -+#endif -+} -+module_exit(mip6_mn_exit); -+#endif /* MODULE */ -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/multiaccess_ctl.c linux-2.4.25/net/ipv6/mobile_ip6/multiaccess_ctl.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/multiaccess_ctl.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/multiaccess_ctl.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,287 @@ -+/* -+ * 2001 (c) Oy L M Ericsson Ab -+ * -+ * Author: NomadicLab / Ericsson Research -+ * -+ * $Id$ -+ * -+ */ -+ -+/* -+ * Vertical hand-off information manager -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "multiaccess_ctl.h" -+#include "debug.h" -+ -+/* -+ * Local variables -+ */ -+static LIST_HEAD(if_list); -+ -+/* Internal interface information list */ -+struct ma_if_info { -+ struct list_head list; -+ int interface_id; -+ int preference; -+ __u8 status; -+}; -+ -+/** -+ * ma_ctl_get_preference - get preference value for interface -+ * @ifi: interface index -+ * -+ * Returns integer value preference for given interface. -+ **/ -+int ma_ctl_get_preference(int ifi) -+{ -+ struct list_head *lh; -+ struct ma_if_info *info; -+ int pref = 0; -+ -+ list_for_each(lh, &if_list) { -+ info = list_entry(lh, struct ma_if_info, list); -+ if (info->interface_id == ifi) { -+ pref = info->preference; -+ return pref; -+ } -+ } -+ return -1; -+} -+/** -+ * ma_ctl_get_preference - get preference value for interface -+ * @ifi: interface index -+ * -+ * Returns integer value interface index for interface with highest preference. -+ **/ -+int ma_ctl_get_preferred_if(void) -+{ -+ struct list_head *lh; -+ struct ma_if_info *info, *pref_if = NULL; -+ -+ list_for_each(lh, &if_list) { -+ info = list_entry(lh, struct ma_if_info, list); -+ if (!pref_if || (info->preference > pref_if->preference)) { -+ pref_if = info; -+ } -+ } -+ if (pref_if) return pref_if->interface_id; -+ return 0; -+} -+/** -+ * ma_ctl_set_preference - set preference for interface -+ * @arg: ioctl args -+ * -+ * Sets preference of an existing interface (called by ioctl). -+ **/ -+void ma_ctl_set_preference(unsigned long arg) -+{ -+ struct list_head *lh; -+ struct ma_if_info *info; -+ struct ma_if_uinfo uinfo; -+ -+ memset(&uinfo, 0, sizeof(struct ma_if_uinfo)); -+ if (copy_from_user(&uinfo, (struct ma_if_uinfo *)arg, -+ sizeof(struct ma_if_uinfo)) < 0) { -+ DEBUG(DBG_WARNING, "copy_from_user failed"); -+ return; -+ } -+ -+ /* check if the interface exists */ -+ list_for_each(lh, &if_list) { -+ info = list_entry(lh, struct ma_if_info, list); -+ if (info->interface_id == uinfo.interface_id) { -+ info->preference = uinfo.preference; -+ return; -+ } -+ } -+} -+ -+/** -+ * ma_ctl_add_iface - add new interface to list -+ * @if_index: interface index -+ * -+ * Adds new interface entry to preference list. Preference is set to -+ * the same value as @if_index. Entry @status is set to -+ * %MA_IFACE_NOT_USED. -+ **/ -+void ma_ctl_add_iface(int if_index) -+{ -+ struct list_head *lh; -+ struct ma_if_info *info; -+ -+ DEBUG_FUNC(); -+ -+ /* check if the interface already exists */ -+ list_for_each(lh, &if_list) { -+ info = list_entry(lh, struct ma_if_info, list); -+ if (info->interface_id == if_index) { -+ info->status = MA_IFACE_NOT_USED; -+ info->preference = if_index; -+ return; -+ } -+ } -+ -+ info = kmalloc(sizeof(struct ma_if_info), GFP_ATOMIC); -+ if (info == NULL) { -+ DEBUG(DBG_ERROR, "Out of memory"); -+ return; -+ } -+ memset(info, 0, sizeof(struct ma_if_info)); -+ info->interface_id = if_index; -+ info->preference = if_index; -+ info->status = MA_IFACE_NOT_USED; -+ list_add(&info->list, &if_list); -+} -+ -+/** -+ * ma_ctl_del_iface - remove entry from the list -+ * @if_index: interface index -+ * -+ * Removes entry for interface @if_index from preference list. -+ **/ -+int ma_ctl_del_iface(int if_index) -+{ -+ struct list_head *lh, *next; -+ struct ma_if_info *info; -+ -+ DEBUG_FUNC(); -+ -+ /* if the iface exists, change availability to 0 */ -+ list_for_each_safe(lh, next, &if_list) { -+ info = list_entry(lh, struct ma_if_info, list); -+ if (info->interface_id == if_index) { -+ list_del(&info->list); -+ kfree(info); -+ return 0; -+ } -+ } -+ -+ return -1; -+} -+ -+/** -+ * ma_ctl_upd_iface - update entry (and list) -+ * @if_index: interface to update -+ * @status: new status for interface -+ * @change_if_index: new interface -+ * -+ * Updates @if_index entry on preference list. Entry status is set to -+ * @status. If new @status is %MA_IFACE_CURRENT, updates list to have -+ * only one current device. If @status is %MA_IFACE_NOT_PRESENT, -+ * entry is deleted and further if entry had %MA_IFACE_CURRENT set, -+ * new current device is looked up and returned in @change_if_index. -+ * New preferred interface is also returned if current device changes -+ * to %MA_IFACE_NOT_USED. Returns 0 on success, otherwise negative. -+ **/ -+int ma_ctl_upd_iface(int if_index, int status, int *change_if_index) -+{ -+ struct list_head *lh, *tmp; -+ struct ma_if_info *info, *pref = NULL; -+ int found = 0; -+ -+ DEBUG_FUNC(); -+ -+ *change_if_index = 0; -+ -+ /* check if the interface exists */ -+ list_for_each_safe(lh, tmp, &if_list) { -+ info = list_entry(lh, struct ma_if_info, list); -+ if (status == MA_IFACE_NOT_PRESENT) { -+ if (info->interface_id == if_index) { -+ list_del_init(&info->list); -+ kfree(info); -+ found = 1; -+ break; -+ } -+ } else if (status == MA_IFACE_CURRENT) { -+ if (info->interface_id == if_index) { -+ info->status |= MA_IFACE_CURRENT; -+ found = 1; -+ } else { -+ info->status |= MA_IFACE_NOT_USED; -+ } -+ } else if (status == MA_IFACE_NOT_USED) { -+ if (info->interface_id == if_index) { -+ if (info->status | MA_IFACE_CURRENT) { -+ found = 1; -+ } -+ info->status &= !MA_IFACE_CURRENT; -+ info->status |= MA_IFACE_NOT_USED; -+ info->status &= !MA_IFACE_HAS_ROUTER; -+ } -+ break; -+ } else if (status == MA_IFACE_HAS_ROUTER) { -+ if (info->interface_id == if_index) { -+ info->status |= MA_IFACE_HAS_ROUTER; -+ } -+ return 0; -+ } -+ } -+ -+ if (status & (MA_IFACE_NOT_USED|MA_IFACE_NOT_PRESENT) && found) { -+ /* select new interface */ -+ list_for_each(lh, &if_list) { -+ info = list_entry(lh, struct ma_if_info, list); -+ if (pref == NULL || ((info->preference > pref->preference) && -+ info->status & MA_IFACE_HAS_ROUTER)) -+ pref = info; -+ } -+ if (pref) { -+ *change_if_index = pref->interface_id; -+ pref->status |= MA_IFACE_CURRENT; -+ } else { -+ *change_if_index = -1; -+ } -+ return 0; -+ } -+ -+ if (found) return 0; -+ -+ return -1; -+} -+ -+static int if_proc_info(char *buffer, char **start, off_t offset, -+ int length) -+{ -+ struct list_head *lh; -+ struct ma_if_info *info; -+ int len = 0; -+ -+ list_for_each(lh, &if_list) { -+ info = list_entry(lh, struct ma_if_info, list); -+ len += sprintf(buffer + len, "%02d %010d %1d %1d\n", -+ info->interface_id, info->preference, -+ !!(info->status & MA_IFACE_HAS_ROUTER), -+ !!(info->status & MA_IFACE_CURRENT)); -+ } -+ -+ *start = buffer + offset; -+ -+ len -= offset; -+ -+ if (len > length) len = length; -+ -+ return len; -+ -+} -+ -+void ma_ctl_init(void) -+{ -+ proc_net_create("mip6_iface", 0, if_proc_info); -+} -+ -+void ma_ctl_clean(void) -+{ -+ proc_net_remove("mip6_iface"); -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/multiaccess_ctl.h linux-2.4.25/net/ipv6/mobile_ip6/multiaccess_ctl.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/multiaccess_ctl.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/multiaccess_ctl.h 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,77 @@ -+/* -+ * 2001 (c) Oy L M Ericsson Ab -+ * -+ * Author: NomadicLab / Ericsson Research -+ * -+ * $Id$ -+ * -+ */ -+ -+#ifndef _MULTIACCESS_CTL_H -+#define _MULTIACCESS_CTL_H -+ -+/* status */ -+#define MA_IFACE_NOT_PRESENT 0x01 -+#define MA_IFACE_NOT_USED 0x02 -+#define MA_IFACE_HAS_ROUTER 0x04 -+#define MA_IFACE_CURRENT 0x10 -+ -+struct ma_if_uinfo { -+ int interface_id; -+ int preference; -+ __u8 status; -+}; -+/* -+ * @ma_ctl_get_preferred_id: returns most preferred interface id -+ */ -+int ma_ctl_get_preferred_if(void); -+ -+/* @ma_ctl_get_preference: returns preference for an interface -+ * @name: name of the interface (dev->name) -+ */ -+int ma_ctl_get_preference(int ifi); -+ -+/* -+ * Public function: ma_ctl_set_preference -+ * Description: Set preference of an existing interface (called by ioctl) -+ * Returns: -+ */ -+void ma_ctl_set_preference(unsigned long); -+ -+/* -+ * Public function: ma_ctl_add_iface -+ * Description: Inform control module to insert a new interface -+ * Returns: 0 if success, any other number means an error -+ */ -+void ma_ctl_add_iface(int); -+ -+/* -+ * Public function: ma_ctl_del_iface -+ * Description: Inform control module to remove an obsolete interface -+ * Returns: 0 if success, any other number means an error -+ */ -+int ma_ctl_del_iface(int); -+ -+/* -+ * Public function: ma_ctl_upd_iface -+ * Description: Inform control module of status change. -+ * Returns: 0 if success, any other number means an error -+ */ -+int ma_ctl_upd_iface(int, int, int *); -+ -+/* -+ * Public function: ma_ctl_init -+ * Description: XXX -+ * Returns: XXX -+ */ -+void ma_ctl_init(void); -+ -+/* -+ * Public function: ma_ctl_clean -+ * Description: XXX -+ * Returns: - -+ */ -+void ma_ctl_clean(void); -+ -+ -+#endif -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/ndisc_ha.c linux-2.4.25/net/ipv6/mobile_ip6/ndisc_ha.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/ndisc_ha.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/ndisc_ha.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,596 @@ -+/* -+ * Mobile IPv6 Duplicate Address Detection Functions -+ * -+ * Authors: -+ * Krishna Kumar -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 "debug.h" -+#include "bcache.h" -+#include "ha.h" /* mipv6_generate_ll_addr */ -+ -+/* -+ * Binding Updates from MN are cached in this structure till DAD is performed. -+ * This structure is used to retrieve a pending Binding Update for the HA to -+ * reply to after performing DAD. The first cell is different from the rest as -+ * follows : -+ * 1. The first cell is used to chain the remaining cells. -+ * 2. The timeout of the first cell is used to delete expired entries -+ * in the list of cells, while the timeout of the other cells are -+ * used for timing out a NS request so as to reply to a BU. -+ * 3. The only elements of the first cell that are used are : -+ * next, prev, and callback_timer. -+ * -+ * TODO : Don't we need to do pneigh_lookup on the Link Local address ? -+ */ -+struct mipv6_dad_cell { -+ /* Information needed for DAD management */ -+ struct mipv6_dad_cell *next; /* Next element on the DAD list */ -+ struct mipv6_dad_cell *prev; /* Prev element on the DAD list */ -+ __u16 probes; /* Number of times to probe for addr */ -+ __u16 flags; /* Entry flags - see below */ -+ struct timer_list callback_timer; /* timeout for entry */ -+ -+ /* Information needed for performing DAD */ -+ struct inet6_ifaddr *ifp; -+ int ifindex; -+ struct in6_addr daddr; -+ struct in6_addr haddr; /* home address */ -+ struct in6_addr ll_haddr; /* Link Local value of haddr */ -+ struct in6_addr coa; -+ struct in6_addr rep_coa; -+ __u32 ba_lifetime; -+ __u16 sequence; -+ __u8 bu_flags; -+}; -+ -+/* Values for the 'flags' field in the mipv6_dad_cell */ -+#define DAD_INIT_ENTRY 0 -+#define DAD_DUPLICATE_ADDRESS 1 -+#define DAD_UNIQUE_ADDRESS 2 -+ -+/* Head of the pending DAD list */ -+static struct mipv6_dad_cell dad_cell_head; -+ -+/* Lock to access the pending DAD list */ -+static rwlock_t dad_lock = RW_LOCK_UNLOCKED; -+ -+/* Timer routine which deletes 'expired' entries in the DAD list */ -+static void mipv6_dad_delete_old_entries(unsigned long unused) -+{ -+ struct mipv6_dad_cell *curr, *next; -+ unsigned long next_time = 0; -+ -+ write_lock(&dad_lock); -+ curr = dad_cell_head.next; -+ while (curr != &dad_cell_head) { -+ next = curr->next; -+ if (curr->flags != DAD_INIT_ENTRY) { -+ if (curr->callback_timer.expires <= jiffies) { -+ /* Entry has expired, free it up. */ -+ curr->next->prev = curr->prev; -+ curr->prev->next = curr->next; -+ in6_ifa_put(curr->ifp); -+ kfree(curr); -+ } else if (next_time < -+ curr->callback_timer.expires) { -+ next_time = curr->callback_timer.expires; -+ } -+ } -+ curr = next; -+ } -+ write_unlock(&dad_lock); -+ if (next_time) { -+ /* -+ * Start another timer if more cells need to be removed at -+ * a later stage. -+ */ -+ dad_cell_head.callback_timer.expires = next_time; -+ add_timer(&dad_cell_head.callback_timer); -+ } -+} -+ -+/* -+ * Queue a timeout routine to clean up 'expired' DAD entries. -+ */ -+static void mipv6_start_dad_head_timer(struct mipv6_dad_cell *cell) -+{ -+ unsigned long expire = jiffies + -+ cell->ifp->idev->nd_parms->retrans_time * 10; -+ -+ if (!timer_pending(&dad_cell_head.callback_timer) || -+ expire < dad_cell_head.callback_timer.expires) { -+ /* -+ * Add timer if none pending, or mod the timer if new -+ * cell needs to be expired before existing timer runs. -+ * -+ * We let the cell remain as long as possible, so that -+ * new BU's as part of retransmissions don't have to go -+ * through DAD before replying. -+ */ -+ dad_cell_head.callback_timer.expires = expire; -+ -+ /* -+ * Keep the cell around for atleast some time to handle -+ * retransmissions or BU's due to fast MN movement. This -+ * is needed otherwise a previous timeout can delete all -+ * expired entries including this new one. -+ */ -+ cell->callback_timer.expires = jiffies + -+ cell->ifp->idev->nd_parms->retrans_time * 5; -+ if (!timer_pending(&dad_cell_head.callback_timer)) { -+ add_timer(&dad_cell_head.callback_timer); -+ } else { -+ mod_timer(&dad_cell_head.callback_timer, expire); -+ } -+ } -+} -+ -+ -+/* Join solicited node MC address */ -+static inline void mipv6_join_sol_mc_addr(struct in6_addr *addr, -+ struct net_device *dev) -+{ -+ struct in6_addr maddr; -+ -+ /* Join solicited node MC address */ -+ addrconf_addr_solict_mult(addr, &maddr); -+ ipv6_dev_mc_inc(dev, &maddr); -+} -+ -+/* Leave solicited node MC address */ -+static inline void mipv6_leave_sol_mc_addr(struct in6_addr *addr, -+ struct net_device *dev) -+{ -+ struct in6_addr maddr; -+ -+ addrconf_addr_solict_mult(addr, &maddr); -+ ipv6_dev_mc_dec(dev, &maddr); -+} -+ -+/* Send a NS */ -+static inline void mipv6_dad_send_ns(struct inet6_ifaddr *ifp, -+ struct in6_addr *haddr) -+{ -+ struct in6_addr unspec; -+ struct in6_addr mcaddr; -+ -+ ipv6_addr_set(&unspec, 0, 0, 0, 0); -+ addrconf_addr_solict_mult(haddr, &mcaddr); -+ -+ /* addr is 'unspec' since we treat this address as transient */ -+ ndisc_send_ns(ifp->idev->dev, NULL, haddr, &mcaddr, &unspec); -+} -+ -+/* -+ * Search for a home address in the list of pending DAD's. Called from -+ * Neighbor Advertisement -+ * Return values : -+ * -1 : No DAD entry found for this advertisement, or entry already -+ * finished processing. -+ * 0 : Entry found waiting for DAD to finish. -+ */ -+static int dad_search_haddr(struct in6_addr *ll_haddr, -+ struct in6_addr *daddr, struct in6_addr *haddr, -+ struct in6_addr *coa, struct in6_addr *rep_coa, -+ __u16 * seq, struct inet6_ifaddr **ifp) -+{ -+ struct mipv6_dad_cell *cell; -+ -+ read_lock(&dad_lock); -+ cell = dad_cell_head.next; -+ while (cell != &dad_cell_head && -+ ipv6_addr_cmp(&cell->ll_haddr, ll_haddr) && -+ ipv6_addr_cmp(&cell->haddr, ll_haddr)) { -+ cell = cell->next; -+ } -+ if (cell == &dad_cell_head || cell->flags != DAD_INIT_ENTRY) { -+ /* Not found element, or element already finished processing */ -+ if (cell != &dad_cell_head) { -+ /* -+ * Set the state to DUPLICATE, even if it was UNIQUE -+ * earlier. It is not needed to setup timer via -+ * mipv6_start_dad_head_timer since this must have -+ * already been done. -+ */ -+ cell->flags = DAD_DUPLICATE_ADDRESS; -+ } -+ read_unlock(&dad_lock); -+ return -1; -+ } -+ -+ /* -+ * The NA found an unprocessed entry in the DAD list. Expire this -+ * entry since another node advertised this address. Caller should -+ * reject BU (DAD failed). -+ */ -+ ipv6_addr_copy(daddr, &cell->daddr); -+ ipv6_addr_copy(haddr, &cell->haddr); -+ ipv6_addr_copy(coa, &cell->coa); -+ ipv6_addr_copy(rep_coa, &cell->rep_coa); -+ *seq = cell->sequence; -+ *ifp = cell->ifp; -+ -+ if (del_timer(&cell->callback_timer) == 0) { -+ /* Timer already deleted, race with Timeout Handler */ -+ /* No action needed */ -+ } -+ -+ cell->flags = DAD_DUPLICATE_ADDRESS; -+ -+ /* Now leave this address to avoid future processing of NA's */ -+ mipv6_leave_sol_mc_addr(&cell->ll_haddr, cell->ifp->idev->dev); -+ /* Leave also global address, if link local address was in use */ -+ if (ipv6_addr_cmp(&cell->ll_haddr, &cell->haddr)) -+ mipv6_leave_sol_mc_addr(&cell->haddr, cell->ifp->idev->dev); -+ /* Start dad_head timer to remove this entry */ -+ mipv6_start_dad_head_timer(cell); -+ -+ read_unlock(&dad_lock); -+ -+ return 0; -+} -+ -+/* ENTRY routine called via Neighbor Advertisement */ -+void mipv6_check_dad(struct in6_addr *ll_haddr) -+{ -+ struct in6_addr daddr, haddr, coa, rep_coa; -+ struct inet6_ifaddr *ifp; -+ __u16 seq; -+ -+ if (dad_search_haddr(ll_haddr, &daddr, &haddr, &coa, &rep_coa, &seq, -+ &ifp) < 0) { -+ /* -+ * Didn't find entry, or no action needed (the action has -+ * already been performed). -+ */ -+ return; -+ } -+ -+ /* -+ * A DAD cell was present, meaning that there is a pending BU -+ * request for 'haddr' - reject the BU. -+ */ -+ mipv6_bu_finish(ifp, 0, DUPLICATE_ADDR_DETECT_FAIL, -+ &daddr, &haddr, &coa, &rep_coa, 0, seq, 0, NULL); -+ return; -+} -+ -+/* -+ * Check if the passed 'cell' is in the list of pending DAD's. Called from -+ * the Timeout Handler. -+ * -+ * Assumes that the caller is holding the dad_lock in reader mode. -+ */ -+static int dad_search_cell(struct mipv6_dad_cell *cell) -+{ -+ struct mipv6_dad_cell *tmp; -+ -+ tmp = dad_cell_head.next; -+ while (tmp != &dad_cell_head && tmp != cell) { -+ tmp = tmp->next; -+ } -+ if (tmp == cell) { -+ if (cell->flags == DAD_INIT_ENTRY) { -+ /* Found valid entry */ -+ if (--cell->probes == 0) { -+ /* -+ * Retransmission's are over - return success. -+ */ -+ cell->flags = DAD_UNIQUE_ADDRESS; -+ -+ /* -+ * Leave this address to avoid future -+ * processing of NA's. -+ */ -+ mipv6_leave_sol_mc_addr(&cell->ll_haddr, -+ cell->ifp->idev-> -+ dev); -+ if (ipv6_addr_cmp(&cell->ll_haddr, &cell->haddr)) -+ mipv6_leave_sol_mc_addr(&cell->haddr, -+ cell->ifp->idev->dev); -+ /* start timeout to delete this cell. */ -+ mipv6_start_dad_head_timer(cell); -+ return 0; -+ } -+ /* -+ * Retransmission not finished, send another NS and -+ * return failure. -+ */ -+ mipv6_dad_send_ns(cell->ifp, &cell->ll_haddr); -+ if (ipv6_addr_cmp(&cell->ll_haddr, &cell->haddr)) -+ mipv6_leave_sol_mc_addr(&cell->haddr, -+ cell->ifp->idev->dev); -+ cell->callback_timer.expires = jiffies + -+ cell->ifp->idev->nd_parms->retrans_time; -+ add_timer(&cell->callback_timer); -+ } else { -+ /* -+ * This means that an NA was received before the -+ * timeout and when the state changed from -+ * DAD_INIT_ENTRY, the BU got failed as a result. -+ * There is nothing to be done. -+ */ -+ } -+ } -+ return -1; -+} -+ -+/* ENTRY routine called via Timeout */ -+static void mipv6_dad_timeout(unsigned long arg) -+{ -+ __u8 ba_status = SUCCESS; -+ struct in6_addr daddr; -+ struct in6_addr haddr; -+ struct in6_addr coa; -+ struct in6_addr rep_coa; -+ struct inet6_ifaddr *ifp; -+ int ifindex; -+ __u32 ba_lifetime; -+ __u16 sequence; -+ __u8 flags; -+ struct mipv6_dad_cell *cell = (struct mipv6_dad_cell *) arg; -+ -+ /* -+ * If entry is not in the list, we have already sent BU Failure -+ * after getting a NA. -+ */ -+ read_lock(&dad_lock); -+ if (dad_search_cell(cell) < 0) { -+ /* -+ * 'cell' is no longer valid (may not be in the list or -+ * is already processed, due to NA processing), or NS -+ * retransmissions are not yet over. -+ */ -+ read_unlock(&dad_lock); -+ return; -+ } -+ -+ /* This is the final Timeout. Send Bind Ack Success */ -+ -+ ifp = cell->ifp; -+ ifindex = cell->ifindex; -+ ba_lifetime = cell->ba_lifetime; -+ sequence = cell->sequence; -+ flags = cell->bu_flags; -+ -+ ipv6_addr_copy(&daddr, &cell->daddr); -+ ipv6_addr_copy(&haddr, &cell->haddr); -+ ipv6_addr_copy(&coa, &cell->coa); -+ ipv6_addr_copy(&rep_coa, &cell->rep_coa); -+ read_unlock(&dad_lock); -+ -+ /* Send BU Acknowledgement Success */ -+ mipv6_bu_finish(ifp, ifindex, ba_status, -+ &daddr, &haddr, &coa, &rep_coa, -+ ba_lifetime, sequence, flags, NULL); -+ return; -+} -+ -+/* -+ * Check if original home address exists in our DAD pending list, if so return -+ * the cell. -+ * -+ * Assumes that the caller is holding the dad_lock in writer mode. -+ */ -+static struct mipv6_dad_cell *mipv6_dad_get_cell(struct in6_addr *haddr) -+{ -+ struct mipv6_dad_cell *cell; -+ -+ cell = dad_cell_head.next; -+ while (cell != &dad_cell_head -+ && ipv6_addr_cmp(&cell->haddr, haddr)) { -+ cell = cell->next; -+ } -+ if (cell == &dad_cell_head) { -+ /* Not found element */ -+ return NULL; -+ } -+ return cell; -+} -+ -+/* -+ * Save all parameters needed for doing a Bind Ack in the mipv6_dad_cell -+ * structure. -+ */ -+static void mipv6_dad_save_cell(struct mipv6_dad_cell *cell, -+ struct inet6_ifaddr *ifp, int ifindex, -+ struct in6_addr *daddr, -+ struct in6_addr *haddr, -+ struct in6_addr *coa, -+ struct in6_addr *rep_coa, -+ __u32 ba_lifetime, -+ __u16 sequence, __u8 flags) -+{ -+ in6_ifa_hold(ifp); -+ cell->ifp = ifp; -+ cell->ifindex = ifindex; -+ -+ ipv6_addr_copy(&cell->daddr, daddr); -+ ipv6_addr_copy(&cell->haddr, haddr); -+ ipv6_addr_copy(&cell->coa, coa); -+ ipv6_addr_copy(&cell->rep_coa, rep_coa); -+ -+ /* Convert cell->ll_haddr to Link Local address */ -+ if (flags & MIPV6_BU_F_LLADDR) -+ mipv6_generate_ll_addr(&cell->ll_haddr, haddr); -+ else -+ ipv6_addr_copy(&cell->ll_haddr, haddr); -+ -+ cell->ba_lifetime = ba_lifetime; -+ cell->sequence = sequence; -+ cell->bu_flags = flags; -+} -+ -+/* -+ * Top level DAD routine for performing DAD. -+ * -+ * Return values -+ * 0 : Don't need to do DAD. -+ * 1 : Need to do DAD. -+ * -n : Error, where 'n' is the reason for the error. -+ * -+ * Assumption : DAD process has been optimized by using cached values upto -+ * some time. However sometimes this can cause problems. Eg. when the first -+ * BU was received, DAD might have failed. Before the second BU arrived, -+ * the node using MN's home address might have stopped using it, but still -+ * we will return DAD_DUPLICATE_ADDRESS based on the first DAD's result. Or -+ * this can go the other way around. However, it is a very small possibility -+ * and thus optimization is turned on by default. It is possible to change -+ * this feature (needs a little code-rewriting in this routine), but -+ * currently DAD result is being cached for performance reasons. -+ */ -+int mipv6_dad_start(struct inet6_ifaddr *ifp, int ifindex, -+ struct in6_addr *daddr, struct in6_addr *haddr, -+ struct in6_addr *coa, struct in6_addr *rep_coa, -+ __u32 ba_lifetime, __u16 sequence, __u8 flags) -+{ -+ int found; -+ struct mipv6_dad_cell *cell; -+ struct mipv6_bce bc_entry; -+ -+ if (ifp->idev->cnf.dad_transmits == 0) { -+ /* DAD is not configured on the HA, return SUCCESS */ -+ return 0; -+ } -+ -+ if (mipv6_bcache_get(haddr, daddr, &bc_entry) == 0) { -+ /* -+ * We already have an entry in our cache - don't need to -+ * do DAD as we are already defending this home address. -+ */ -+ return 0; -+ } -+ -+ write_lock(&dad_lock); -+ if ((cell = mipv6_dad_get_cell(haddr)) != NULL) { -+ /* -+ * An existing entry for BU was found in our cache due -+ * to retransmission of the BU or a new COA registration. -+ */ -+ switch (cell->flags) { -+ case DAD_INIT_ENTRY: -+ /* Old entry is waiting for DAD to complete */ -+ break; -+ case DAD_UNIQUE_ADDRESS: -+ /* DAD is finished successfully - return success. */ -+ write_unlock(&dad_lock); -+ return 0; -+ case DAD_DUPLICATE_ADDRESS: -+ /* -+ * DAD is finished and we got a NA while doing BU - -+ * return failure. -+ */ -+ write_unlock(&dad_lock); -+ return -DUPLICATE_ADDR_DETECT_FAIL; -+ default: -+ /* Unknown state - should never happen */ -+ DEBUG(DBG_WARNING, -+ "cell entry in unknown state : %d", -+ cell->flags); -+ write_unlock(&dad_lock); -+ return -REASON_UNSPECIFIED; -+ } -+ found = 1; -+ } else { -+ if ((cell = (struct mipv6_dad_cell *) -+ kmalloc(sizeof(struct mipv6_dad_cell), GFP_ATOMIC)) -+ == NULL) { -+ return -INSUFFICIENT_RESOURCES; -+ } -+ found = 0; -+ } -+ -+ mipv6_dad_save_cell(cell, ifp, ifindex, daddr, haddr, coa, rep_coa, -+ ba_lifetime, sequence, flags); -+ -+ if (!found) { -+ cell->flags = DAD_INIT_ENTRY; -+ cell->probes = ifp->idev->cnf.dad_transmits; -+ -+ /* Insert element on dad_cell_head list */ -+ dad_cell_head.prev->next = cell; -+ cell->next = &dad_cell_head; -+ cell->prev = dad_cell_head.prev; -+ dad_cell_head.prev = cell; -+ write_unlock(&dad_lock); -+ if (flags & MIPV6_BU_F_LLADDR) { -+ /* join the solicited node MC of the global homeaddr.*/ -+ mipv6_join_sol_mc_addr(&cell->haddr, ifp->idev->dev); -+ /* Send a NS */ -+ mipv6_dad_send_ns(ifp, &cell->haddr); -+ } -+ /* join the solicited node MC of the homeaddr. */ -+ mipv6_join_sol_mc_addr(&cell->ll_haddr, ifp->idev->dev); -+ -+ /* Send a NS */ -+ mipv6_dad_send_ns(ifp, &cell->ll_haddr); -+ -+ /* Initialize timer for this cell to timeout the NS. */ -+ init_timer(&cell->callback_timer); -+ cell->callback_timer.data = (unsigned long) cell; -+ cell->callback_timer.function = mipv6_dad_timeout; -+ cell->callback_timer.expires = jiffies + -+ ifp->idev->nd_parms->retrans_time; -+ add_timer(&cell->callback_timer); -+ } else { -+ write_unlock(&dad_lock); -+ } -+ return 1; -+} -+ -+void __init mipv6_dad_init(void) -+{ -+ dad_cell_head.next = dad_cell_head.prev = &dad_cell_head; -+ init_timer(&dad_cell_head.callback_timer); -+ dad_cell_head.callback_timer.data = 0; -+ dad_cell_head.callback_timer.function = -+ mipv6_dad_delete_old_entries; -+} -+ -+void __exit mipv6_dad_exit(void) -+{ -+ struct mipv6_dad_cell *curr, *next; -+ -+ write_lock_bh(&dad_lock); -+ del_timer(&dad_cell_head.callback_timer); -+ -+ curr = dad_cell_head.next; -+ while (curr != &dad_cell_head) { -+ next = curr->next; -+ del_timer(&curr->callback_timer); -+ if (curr->flags == DAD_INIT_ENTRY) { -+ /* -+ * We were in DAD_INIT state and listening to the -+ * solicited node MC address - need to stop that. -+ */ -+ mipv6_leave_sol_mc_addr(&curr->ll_haddr, -+ curr->ifp->idev->dev); -+ if (ipv6_addr_cmp(&curr->ll_haddr, &curr->haddr)) -+ mipv6_leave_sol_mc_addr(&curr->haddr, -+ curr->ifp->idev->dev); -+ } -+ in6_ifa_put(curr->ifp); -+ kfree(curr); -+ curr = next; -+ } -+ dad_cell_head.next = dad_cell_head.prev = &dad_cell_head; -+ write_unlock_bh(&dad_lock); -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/prefix.c linux-2.4.25/net/ipv6/mobile_ip6/prefix.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/prefix.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/prefix.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,217 @@ -+/** -+ * Prefix solicitation and advertisement -+ * -+ * Authors: -+ * Jaakko Laine -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 "mipv6_icmp.h" -+#include "debug.h" -+#include "sortedlist.h" -+#include "prefix.h" -+#include "config.h" -+ -+#define INFINITY 0xffffffff -+ -+struct timer_list pfx_timer; -+ -+struct list_head pfx_list; -+rwlock_t pfx_list_lock = RW_LOCK_UNLOCKED; -+ -+int compare_pfx_list_entry(const void *data1, const void *data2, -+ int datalen) -+{ -+ struct pfx_list_entry *e1 = (struct pfx_list_entry *) data1; -+ struct pfx_list_entry *e2 = (struct pfx_list_entry *) data2; -+ -+ return ((ipv6_addr_cmp(&e1->daddr, &e2->daddr) == 0) -+ && (e2->ifindex == -1 || e1->ifindex == e2->ifindex)); -+} -+ -+/** -+ * mipv6_pfx_cancel_send - cancel pending items to daddr from saddr -+ * @daddr: Destination address -+ * @ifindex: pending items on this interface will be canceled -+ * -+ * if ifindex == -1, all items to daddr will be removed -+ */ -+void mipv6_pfx_cancel_send(struct in6_addr *daddr, int ifindex) -+{ -+ unsigned long tmp; -+ struct pfx_list_entry entry; -+ -+ DEBUG_FUNC(); -+ -+ /* We'll just be comparing these parts... */ -+ memcpy(&entry.daddr, daddr, sizeof(struct in6_addr)); -+ entry.ifindex = ifindex; -+ -+ write_lock_bh(&pfx_list_lock); -+ -+ while (mipv6_slist_del_item(&pfx_list, &entry, -+ compare_pfx_list_entry) == 0) -+ ; -+ -+ if ((tmp = mipv6_slist_get_first_key(&pfx_list))) -+ mod_timer(&pfx_timer, tmp); -+ -+ write_unlock_bh(&pfx_list_lock); -+} -+ -+/** -+ * mipv6_pfx_add_ha - add a new HA to send prefix solicitations to -+ * @daddr: address of HA -+ * @saddr: our address to use as source address -+ * @ifindex: interface index -+ */ -+void mipv6_pfx_add_ha(struct in6_addr *daddr, struct in6_addr *saddr, -+ int ifindex) -+{ -+ unsigned long tmp; -+ struct pfx_list_entry entry; -+ -+ DEBUG_FUNC(); -+ -+ memcpy(&entry.daddr, daddr, sizeof(struct in6_addr)); -+ memcpy(&entry.saddr, saddr, sizeof(struct in6_addr)); -+ entry.retries = 0; -+ entry.ifindex = ifindex; -+ -+ write_lock_bh(&pfx_list_lock); -+ if (mipv6_slist_modify(&pfx_list, &entry, sizeof(struct pfx_list_entry), -+ jiffies + INITIAL_SOLICIT_TIMER * HZ, -+ compare_pfx_list_entry)) -+ DEBUG(DBG_WARNING, "Cannot add new HA to pfx list"); -+ -+ if ((tmp = mipv6_slist_get_first_key(&pfx_list))) -+ mod_timer(&pfx_timer, tmp); -+ write_unlock_bh(&pfx_list_lock); -+} -+ -+int mipv6_pfx_add_home(int ifindex, struct in6_addr *saddr, -+ struct in6_addr *daddr, unsigned long min_expire) -+{ -+ unsigned long tmp; -+ -+ write_lock(&pfx_list_lock); -+ -+ if (min_expire != INFINITY) { -+ unsigned long expire; -+ struct pfx_list_entry entry; -+ -+ memcpy(&entry.daddr, saddr, sizeof(struct in6_addr)); -+ memcpy(&entry.saddr, daddr, sizeof(struct in6_addr)); -+ entry.retries = 0; -+ entry.ifindex = ifindex; -+ -+ /* This is against the RFC 3775, but we need to set -+ * a minimum interval for a prefix solicitation. -+ * Otherwise a prefix solicitation storm will -+ * result if valid lifetime of the prefix is -+ * smaller than MAX_PFX_ADV_DELAY -+ */ -+ min_expire -= MAX_PFX_ADV_DELAY; -+ min_expire = min_expire < MIN_PFX_SOL_DELAY ? MIN_PFX_SOL_DELAY : min_expire; -+ -+ expire = jiffies + min_expire * HZ; -+ -+ if (mipv6_slist_modify(&pfx_list, &entry, -+ sizeof(struct pfx_list_entry), -+ expire, -+ compare_pfx_list_entry) != 0) -+ DEBUG(DBG_WARNING, "Cannot add new entry to pfx_list"); -+ } -+ -+ if ((tmp = mipv6_slist_get_first_key(&pfx_list))) -+ mod_timer(&pfx_timer, tmp); -+ -+ write_unlock(&pfx_list_lock); -+ -+ return 0; -+} -+ -+/** -+ * set_ha_pfx_list - manipulate pfx_list for HA when timer goes off -+ * @entry: pfx_list_entry that is due -+ */ -+static void set_ha_pfx_list(struct pfx_list_entry *entry) -+{ -+} -+ -+/** -+ * set_mn_pfx_list - manipulate pfx_list for MN when timer goes off -+ * @entry: pfx_list_entry that is due -+ */ -+static void set_mn_pfx_list(struct pfx_list_entry *entry) -+{ -+} -+ -+/** -+ * pfx_timer_handler - general timer handler -+ * @dummy: dummy -+ * -+ * calls set_ha_pfx_list and set_mn_pfx_list to do the thing when -+ * a timer goes off -+ */ -+static void pfx_timer_handler(unsigned long dummy) -+{ -+ unsigned long tmp; -+ struct pfx_list_entry *entry; -+ -+ DEBUG_FUNC(); -+ -+ write_lock(&pfx_list_lock); -+ if (!(entry = mipv6_slist_get_first(&pfx_list))) -+ goto out; -+ -+ if (mip6node_cnf.capabilities & CAP_HA) -+ set_ha_pfx_list(entry); -+ if (mip6node_cnf.capabilities & CAP_MN) -+ set_mn_pfx_list(entry); -+ if ((tmp = mipv6_slist_get_first_key(&pfx_list))) -+ mod_timer(&pfx_timer, tmp); -+ -+ out: -+ write_unlock(&pfx_list_lock); -+} -+ -+int mipv6_initialize_pfx_icmpv6(void) -+{ -+ INIT_LIST_HEAD(&pfx_list); -+ -+ init_timer(&pfx_timer); -+ pfx_timer.function = pfx_timer_handler; -+ -+ return 0; -+} -+ -+void mipv6_shutdown_pfx_icmpv6(void) -+{ -+ struct prefix_info *tmp; -+ -+ if (timer_pending(&pfx_timer)) -+ del_timer(&pfx_timer); -+ -+ write_lock_bh(&pfx_list_lock); -+ while ((tmp = mipv6_slist_del_first(&pfx_list))) -+ kfree(tmp); -+ write_unlock_bh(&pfx_list_lock); -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/prefix.h linux-2.4.25/net/ipv6/mobile_ip6/prefix.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/prefix.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/prefix.h 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,57 @@ -+/* -+ * MIPL Mobile IPv6 Prefix solicitation and advertisement -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _PREFIX_H -+#define _PREFIX_H -+ -+#include -+ -+struct pfx_list_entry { -+ struct in6_addr daddr; -+ struct in6_addr saddr; -+ int retries; -+ int ifindex; -+}; -+ -+extern struct list_head pfx_list; -+extern rwlock_t pfx_list_lock; -+extern struct timer_list pfx_timer; -+ -+int compare_pfx_list_entry(const void *data1, const void *data2, -+ int datalen); -+ -+/** -+ * mipv6_pfx_cancel_send - cancel pending pfx_advs/sols to daddr -+ * @daddr: destination address -+ * @ifindex: pending items on this interface will be canceled -+ * -+ * if ifindex == -1, all items to daddr will be removed -+ */ -+void mipv6_pfx_cancel_send(struct in6_addr *daddr, int ifindex); -+ -+/** -+ * mipv6_pfx_add_ha - add a new HA to send prefix solicitations to -+ * @daddr: address of HA -+ * @saddr: our address to use as source address -+ * @ifindex: interface index -+ */ -+void mipv6_pfx_add_ha(struct in6_addr *daddr, struct in6_addr *saddr, -+ int ifindex); -+ -+void mipv6_pfxs_modified(struct prefix_info *pinfo, int ifindex); -+ -+int mipv6_pfx_add_home(int ifindex, struct in6_addr *daddr, -+ struct in6_addr *saddr, unsigned long min_expire); -+ -+int mipv6_initialize_pfx_icmpv6(void); -+void mipv6_shutdown_pfx_icmpv6(void); -+ -+#endif -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/prefix_ha.c linux-2.4.25/net/ipv6/mobile_ip6/prefix_ha.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/prefix_ha.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/prefix_ha.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,122 @@ -+/** -+ * Prefix advertisement for Home Agent -+ * -+ * Authors: -+ * Jaakko Laine -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 "mipv6_icmp.h" -+#include "debug.h" -+#include "sortedlist.h" -+#include "util.h" -+#include "bcache.h" -+#include "config.h" -+#include "prefix.h" -+ -+/** -+ * pfx_adv_iterator - modify pfx_list entries according to new prefix info -+ * @data: MN's home registration bcache_entry -+ * @args: new prefix info -+ * @sortkey: ignored -+ */ -+static int pfx_adv_iterator(void *data, void *args, unsigned long sortkey) -+{ -+ struct mipv6_bce *bc_entry = (struct mipv6_bce *) data; -+ struct prefix_info *pinfo = (struct prefix_info *) args; -+ -+ if (mipv6_prefix_compare(&bc_entry->coa, &pinfo->prefix, -+ pinfo->prefix_len) == 0) { -+ struct pfx_list_entry pfx_entry; -+ -+ memcpy(&pfx_entry.daddr, &bc_entry->coa, -+ sizeof(struct in6_addr)); -+ memcpy(&pfx_entry.daddr, &bc_entry->our_addr, -+ sizeof(struct in6_addr)); -+ pfx_entry.retries = 0; -+ pfx_entry.ifindex = bc_entry->ifindex; -+ -+ mipv6_slist_modify(&pfx_list, &pfx_entry, -+ sizeof(struct pfx_list_entry), -+ jiffies + -+ net_random() % (MAX_PFX_ADV_DELAY * HZ), -+ compare_pfx_list_entry); -+ } -+ -+ return 0; -+} -+ -+struct homereg_iterator_args { -+ struct list_head *head; -+ int count; -+}; -+ -+static int homereg_iterator(void *data, void *args, unsigned long *sortkey) -+{ -+ struct mipv6_bce *entry = (struct mipv6_bce *) data; -+ struct homereg_iterator_args *state = -+ (struct homereg_iterator_args *) args; -+ -+ if (entry->type == HOME_REGISTRATION) { -+ mipv6_slist_add(state->head, entry, -+ sizeof(struct mipv6_bce), -+ state->count); -+ state->count++; -+ } -+ return 0; -+} -+ -+static int mipv6_bcache_get_homeregs(struct list_head *head) -+{ -+ struct homereg_iterator_args args; -+ -+ DEBUG_FUNC(); -+ -+ args.count = 0; -+ args.head = head; -+ -+ mipv6_bcache_iterate(homereg_iterator, &args); -+ return args.count; -+} -+ -+/** -+ * mipv6_prefix_added - prefix was added to interface, act accordingly -+ * @pinfo: prefix_info that was added -+ * @ifindex: interface index -+ */ -+void mipv6_pfxs_modified(struct prefix_info *pinfo, int ifindex) -+{ -+ int count; -+ unsigned long tmp; -+ struct list_head home_regs; -+ -+ DEBUG_FUNC(); -+ -+ INIT_LIST_HEAD(&home_regs); -+ -+ if (!(count = mipv6_bcache_get_homeregs(&home_regs))) -+ return; -+ -+ write_lock_bh(&pfx_list_lock); -+ mipv6_slist_for_each(&home_regs, pinfo, pfx_adv_iterator); -+ if ((tmp = mipv6_slist_get_first_key(&pfx_list))) -+ mod_timer(&pfx_timer, tmp); -+ write_unlock_bh(&pfx_list_lock); -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/rr_crypto.c linux-2.4.25/net/ipv6/mobile_ip6/rr_crypto.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/rr_crypto.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/rr_crypto.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,255 @@ -+/* -+ * rr_cookie.c - Mobile IPv6 return routability crypto -+ * Author : Henrik Petander -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 "debug.h" -+#include "hmac.h" -+#include "rr_crypto.h" -+ -+#define DBG_RR 5 -+ -+u8 k_CN[HMAC_SHA1_KEY_SIZE]; // secret key of CN -+ -+u16 curr_index = 0; -+ -+struct nonce_timestamp nonce_table[MAX_NONCES]; -+spinlock_t nonce_lock = SPIN_LOCK_UNLOCKED; -+void update_nonces(void); -+ -+/** nonce_is_fresh - whether the nonce was generated recently -+ * -+ * @non_ts : table entry containing the nonce and a timestamp -+ * @interval : if nonce was generated within interval seconds it is fresh -+ * -+ * Returns 1 if the nonce is fresh, 0 otherwise. -+ */ -+static int nonce_is_fresh(struct nonce_timestamp *non_ts, unsigned long interval) -+{ -+ if (time_before(jiffies, non_ts->timestamp + interval * HZ) && !non_ts->invalid) -+ return 1; -+ return 0; -+} -+void mipv6_rr_invalidate_nonce(u16 nonce_ind) -+{ -+ spin_lock_bh(&nonce_lock); -+ if (nonce_ind > MAX_NONCES) { -+ spin_unlock_bh(&nonce_lock); -+ return; -+ } -+ nonce_table[nonce_ind].invalid = 1; -+ spin_unlock_bh(&nonce_lock); -+} -+/* Returns a pointer to a new nonce */ -+struct mipv6_rr_nonce * mipv6_rr_get_new_nonce(void) -+{ -+ struct mipv6_rr_nonce *nce = kmalloc(sizeof(*nce), GFP_ATOMIC); -+ -+ if (!nce) -+ return NULL; -+ // Lock nonces here -+ spin_lock_bh(&nonce_lock); -+ // If nonce is not fresh create new one -+ if (!nonce_is_fresh(&nonce_table[curr_index], MIPV6_RR_NONCE_LIFETIME)) { -+ // increment the last nonce pointer and create new nonce -+ curr_index++; -+ // Wrap around -+ if (curr_index == MAX_NONCES) -+ curr_index = 0; -+ // Get random data to fill the nonce data -+ get_random_bytes(nonce_table[curr_index].nonce.data, MIPV6_RR_NONCE_DATA_LENGTH); -+ // Fill the index field -+ nonce_table[curr_index].nonce.index = curr_index; -+ nonce_table[curr_index].invalid = 0; -+ nonce_table[curr_index].timestamp = jiffies; -+ } -+ spin_unlock_bh(&nonce_lock); -+ memcpy(nce, &nonce_table[curr_index].nonce, sizeof(*nce)); -+ // Unlock nonces -+ return nce; -+} -+/** mipv6_rr_nonce_get_by_index - returns a nonce for index -+ * @nonce_ind : index of the nonce -+ * -+ * Returns a nonce or NULL if the nonce index was invalid or the nonce -+ * for the index was not fresh. -+ */ -+struct mipv6_rr_nonce * mipv6_rr_nonce_get_by_index(u16 nonce_ind) -+{ -+ struct mipv6_rr_nonce *nce = NULL; -+ -+ spin_lock_bh(&nonce_lock); -+ if (nonce_ind >= MAX_NONCES) { -+ DEBUG(DBG_WARNING, "Nonce index field from BU invalid"); -+ -+ /* Here a double of the nonce_lifetime is used for freshness -+ * verification, since the nonces -+ * are not created in response to every initiator packet -+ */ -+ } else if (nonce_is_fresh(&nonce_table[nonce_ind], 2 * MIPV6_RR_NONCE_LIFETIME)) { -+ nce = kmalloc(sizeof(*nce), GFP_ATOMIC); -+ memcpy(nce, &nonce_table[nonce_ind].nonce, sizeof(*nce)); -+ } -+ spin_unlock_bh(&nonce_lock); -+ -+ return nce; -+} -+ -+/* Fills rr test init cookies with random bytes */ -+void mipv6_rr_mn_cookie_create(u8 *cookie) -+{ -+ get_random_bytes(cookie, MIPV6_RR_COOKIE_LENGTH); -+} -+ -+/** mipv6_rr_cookie_create - builds a home or care-of cookie -+ * -+ * @addr : the home or care-of address from HoTI or CoTI -+ * @ckie : memory where the cookie is copied to -+ * @nce : pointer to a nonce used for the calculation, nce is freed during the function -+ * -+ */ -+int mipv6_rr_cookie_create(struct in6_addr *addr, u8 **ckie, -+ u16 nonce_index) -+{ -+ struct ah_processing ah_proc; -+ u8 digest[HMAC_SHA1_HASH_LEN]; -+ struct mipv6_rr_nonce *nce; -+ -+ if ((nce = mipv6_rr_nonce_get_by_index(nonce_index))== NULL) -+ return -1; -+ -+ if (*ckie == NULL && (*ckie = kmalloc(MIPV6_RR_COOKIE_LENGTH, -+ GFP_ATOMIC)) == NULL) { -+ kfree(nce); -+ return -1; -+ } -+ /* Calculate the full hmac-sha1 digest from address and nonce using the secret key of cn */ -+ -+ if (ah_hmac_sha1_init(&ah_proc, k_CN, HMAC_SHA1_KEY_SIZE) < 0) { -+ DEBUG(DBG_ERROR, "Hmac sha1 initialization failed"); -+ kfree(nce); -+ return -1; -+ } -+ -+ ah_hmac_sha1_loop(&ah_proc, addr, sizeof(*addr)); -+ ah_hmac_sha1_loop(&ah_proc, nce->data, MIPV6_RR_NONCE_DATA_LENGTH); -+ ah_hmac_sha1_result(&ah_proc, digest); -+ -+ -+ /* clean up nonce */ -+ kfree(nce); -+ -+ /* Copy first 64 bits of hash target to the cookie */ -+ memcpy(*ckie, digest, MIPV6_RR_COOKIE_LENGTH); -+ return 0; -+} -+ -+/** mipv6_rr_key_calc - creates BU authentication key -+ * -+ * @hoc : Home Cookie -+ * @coc : Care-of Cookie -+ * -+ * Returns BU authentication key of length HMAC_SHA1_KEY_SIZE or NULL in error cases, -+ * caller needs to free the key. -+ */ -+u8 *mipv6_rr_key_calc(u8 *hoc, u8 *coc) -+{ -+ -+ u8 *key_bu = kmalloc(HMAC_SHA1_KEY_SIZE, GFP_ATOMIC); -+ SHA1_CTX c; -+ -+ if (!key_bu) { -+ DEBUG(DBG_CRITICAL, "Memory allocation failed, could nort create BU authentication key"); -+ return NULL; -+ } -+ -+ /* Calculate the key from home and care-of cookies -+ * Kbu = sha1(home_cookie | care-of cookie) -+ * or KBu = sha1(home_cookie), if MN deregisters -+ */ -+ sha1_init(&c); -+ sha1_compute(&c, hoc, MIPV6_RR_COOKIE_LENGTH); -+ if (coc) -+ sha1_compute(&c, coc, MIPV6_RR_COOKIE_LENGTH); -+ sha1_final(&c, key_bu); -+ DEBUG(DBG_RR, "Home and Care-of cookies used for calculating key "); -+ debug_print_buffer(DBG_RR, hoc, MIPV6_RR_COOKIE_LENGTH); -+ if (coc) -+ debug_print_buffer(DBG_RR, coc, MIPV6_RR_COOKIE_LENGTH); -+ -+ return key_bu; -+} -+ -+void mipv6_rr_init(void) -+{ -+ get_random_bytes(k_CN, HMAC_SHA1_KEY_SIZE); -+ memset(nonce_table, 0, MAX_NONCES * sizeof(struct nonce_timestamp)); -+} -+ -+#ifdef TEST_MIPV6_RR_CRYPTO -+void mipv6_test_rr(void) -+{ -+ struct mipv6_rr_nonce *nonce; -+ struct in6_addr a1, a2; -+ int ind1, ind2; -+ u8 *ckie1 = NULL, *ckie2 = NULL; -+ u8 *key_mn = NULL, *key_cn = NULL; -+ mipv6_init_rr(); -+ -+ nonce = mipv6_rr_get_new_nonce(); -+ if (!nonce) { -+ printk("mipv6_rr_get_new_nonce() failed, at 1! \n"); -+ return; -+ } -+ mipv6_rr_cookie_create(&a1, &ckie1, nonce->index); -+ ind1 = nonce->index; -+ kfree(nonce); -+ -+ nonce = mipv6_rr_get_new_nonce(); -+ if (!nonce) { -+ printk("mipv6_rr_get_new_nonce() failed, at 2! \n"); -+ return; -+ } -+ -+ mipv6_rr_cookie_create(&a2, &ckie2, nonce->index); -+ ind2 = nonce->index; -+ key_mn = mipv6_rr_key_calc(ckie1, ckie2); -+ -+ /* Create home and coa cookies based on indices */ -+ mipv6_rr_cookie_create(&a1, &ckie1, ind1); -+ mipv6_rr_cookie_create(&a2, &ckie2, ind2); -+ key_cn = mipv6_rr_key_calc(ckie1, ckie2); -+ if (!key_cn || !key_mn) { -+ printk("creation of secret key failed!\n"); -+ return; -+ } -+ if(memcmp(key_cn, key_mn, HMAC_SHA1_KEY_SIZE)) -+ printk("mipv6_rr_key_calc produced different keys for MN and CN \n"); -+ else -+ printk("mipv6_rr_crypto test OK\n"); -+ kfree(nonce); -+ kfree(key_cn); -+ kfree(key_mn); -+} -+#endif -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/rr_crypto.h linux-2.4.25/net/ipv6/mobile_ip6/rr_crypto.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/rr_crypto.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/rr_crypto.h 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,72 @@ -+/* -+ * MIPL Mobile IPv6 Return routability crypto prototypes -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _RR_CRYPTO -+#define _RR_CRYPTO -+ -+#include -+ -+/* Macros and data structures */ -+ -+#define MIPV6_RR_NONCE_LIFETIME 60 -+#define MIPV6_RR_NONCE_DATA_LENGTH 8 -+#define MIPV6_RR_COOKIE_LENGTH 8 -+#define COOKIE_SIZE 8 -+#define MAX_NONCES 4 -+#define HMAC_SHA1_KEY_SIZE 20 -+ -+struct mipv6_rr_nonce { -+ u_int16_t index; -+ u_int8_t data[MIPV6_RR_NONCE_DATA_LENGTH]; -+}; -+ -+struct nonce_timestamp { -+ struct mipv6_rr_nonce nonce; -+ unsigned long timestamp; -+ u_int8_t invalid; -+}; -+ -+/* Function definitions */ -+ -+/* Return 1 if equal, 0 if not */ -+static __inline__ int mipv6_equal_cookies(u8 *c1, u8 *c2) -+{ -+ return (memcmp(c1, c2, MIPV6_RR_COOKIE_LENGTH) == 0); -+} -+ -+/* Function declarations */ -+ -+/* Create cookie for HoTi and CoTi */ -+extern void mipv6_rr_mn_cookie_create(u8 *cookie); -+ -+/* Create cookie for HoT and CoT */ -+extern int mipv6_rr_cookie_create(struct in6_addr *addr, u8 **ckie, u16 nonce_index); -+ -+/* Calculate return routability key from home and care-of cookies, key length is -+ * HMAC_SHA1_KEY_SIZE -+ */ -+extern u_int8_t *mipv6_rr_key_calc(u8 *hoc, u8 *coc); -+ -+extern struct mipv6_rr_nonce *mipv6_rr_get_new_nonce(void); -+ -+/* For avoiding replay attacks when MN deregisters */ -+extern void mipv6_rr_invalidate_nonce(u16 nonce_index); -+/* -+ * initializes the return routability crypto -+ */ -+ -+void mipv6_rr_init(void); -+ -+#ifdef TEST_MIPV6_RR_CRYPTO -+void mipv6_test_rr(void); -+#endif /* TEST_MIPV6_RR_CRYPTO */ -+ -+#endif /* RR_CRYPTO */ -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/sortedlist.c linux-2.4.25/net/ipv6/mobile_ip6/sortedlist.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/sortedlist.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/sortedlist.c 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,349 @@ -+/** -+ * Sorted list - linked list with sortkey. -+ * -+ * Authors: -+ * Jaakko Laine -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 -+ -+struct mipv6_sorted_list_entry { -+ struct list_head list; -+ void *data; -+ int datalen; -+ unsigned long sortkey; -+}; -+ -+/** -+ * compare - compares two arbitrary data items -+ * @data1: first data item -+ * @data2: second data item -+ * @datalen: length of data items in bits -+ * -+ * datalen is in bits! -+ */ -+int mipv6_bitwise_compare(const void *data1, const void *data2, int datalen) -+{ -+ int n = datalen; -+ __u8 * ptr1 = (__u8 *)data1; -+ __u8 * ptr2 = (__u8 *)data2; -+ -+ for (; n>=0; n-=8, ptr1++, ptr2++) { -+ if (n >= 8) { -+ if (*ptr1 != *ptr2) -+ return 0; -+ } else { -+ if ((*ptr1 ^ *ptr2) & ((~0) << (8 - n))) -+ return 0; -+ } -+ } -+ -+ return 1; -+} -+ -+/** -+ * mipv6_slist_add - add an entry to sorted list -+ * @head: list_head of the sorted list -+ * @data: item to store -+ * @datalen: length of data (in bytes) -+ * @key: sortkey of item -+ * -+ * Allocates memory for entry and data -+ */ -+int mipv6_slist_add(struct list_head *head, void *data, int datalen, -+ unsigned long sortkey) -+{ -+ struct list_head *pos; -+ struct mipv6_sorted_list_entry *entry, *tmp, *next; -+ -+ entry = kmalloc(sizeof(struct mipv6_sorted_list_entry), GFP_ATOMIC); -+ -+ if (!entry) -+ return -1; -+ -+ entry->data = kmalloc(datalen, GFP_ATOMIC); -+ -+ if (!entry->data) { -+ kfree(entry); -+ return -1; -+ } -+ -+ memcpy(entry->data, data, datalen); -+ entry->datalen = datalen; -+ entry->sortkey = sortkey; -+ -+ if ((pos = head->next) == head) { -+ list_add(&entry->list, head); -+ return 0; -+ } -+ -+ tmp = list_entry(pos, struct mipv6_sorted_list_entry, list); -+ if (entry->sortkey < tmp->sortkey) { -+ list_add(&entry->list, head); -+ return 0; -+ } -+ -+ for (; pos != head; pos = pos->next) { -+ tmp = list_entry(pos, struct mipv6_sorted_list_entry, list); -+ if (pos->next == head) { -+ list_add(&entry->list, &tmp->list); -+ return 0; -+ } -+ next = list_entry(pos->next, struct mipv6_sorted_list_entry, list); -+ if (entry->sortkey >= tmp->sortkey && entry->sortkey < next->sortkey) { -+ list_add(&entry->list, &tmp->list); -+ return 0; -+ } -+ } -+ -+ /* never reached */ -+ return -1; -+} -+ -+/** -+ * mipv6_slist_get_first - get the first data item in the list -+ * @head: list_head of the sorted list -+ * -+ * Returns the actual data item, not copy, so don't kfree it -+ */ -+void *mipv6_slist_get_first(struct list_head *head) -+{ -+ struct mipv6_sorted_list_entry *entry; -+ -+ if (list_empty(head)) -+ return NULL; -+ -+ entry = list_entry(head->next, struct mipv6_sorted_list_entry, list); -+ return entry->data; -+} -+ -+/** -+ * mipv6_slist_del_first - delete (and get) the first item in list -+ * @head: list_head of the sorted list -+ * -+ * Remember to kfree the item -+ */ -+void *mipv6_slist_del_first(struct list_head *head) -+{ -+ void *tmp; -+ struct mipv6_sorted_list_entry *entry; -+ -+ if (list_empty(head)) -+ return NULL; -+ -+ entry = list_entry(head->next, struct mipv6_sorted_list_entry, list); -+ tmp = entry->data; -+ -+ list_del(head->next); -+ kfree(entry); -+ -+ return tmp; -+} -+ -+/** -+ * mipv6_slist_del_item - delete entry -+ * @head: list_head of the sorted list -+ * @data: item to delete -+ * @compare: function used for comparing the data items -+ * -+ * compare function needs to have prototype -+ * int (*compare)(const void *data1, const void *data2, int datalen) -+ */ -+int mipv6_slist_del_item(struct list_head *head, void *data, -+ int (*compare)(const void *data1, const void *data2, -+ int datalen)) -+{ -+ struct list_head *pos; -+ struct mipv6_sorted_list_entry *entry; -+ -+ for(pos = head->next; pos != head; pos = pos->next) { -+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list); -+ if (compare(data, entry->data, entry->datalen)) { -+ list_del(pos); -+ kfree(entry->data); -+ kfree(entry); -+ return 0; -+ } -+ } -+ -+ return -1; -+} -+ -+/** -+ * mipv6_slist_get_first_key - get sortkey of the first item -+ * @head: list_head of the sorted list -+ */ -+unsigned long mipv6_slist_get_first_key(struct list_head *head) -+{ -+ struct mipv6_sorted_list_entry *entry; -+ -+ if (list_empty(head)) -+ return 0; -+ -+ entry = list_entry(head->next, struct mipv6_sorted_list_entry, list); -+ return entry->sortkey; -+} -+ -+/** -+ * mipv6_slist_get_key - get sortkey of the data item -+ * @head: list_head of the sorted list -+ * @data: the item to search for -+ * @compare: function used for comparing the data items -+ * -+ * compare function needs to have prototype -+ * int (*compare)(const void *data1, const void *data2, int datalen) -+ */ -+unsigned long mipv6_slist_get_key(struct list_head *head, void *data, -+ int (*compare)(const void *data1, -+ const void *data2, -+ int datalen)) -+{ -+ struct list_head *pos; -+ struct mipv6_sorted_list_entry *entry; -+ -+ for(pos = head->next; pos != head; pos = pos->next) { -+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list); -+ if (compare(data, entry->data, entry->datalen)) -+ return entry->sortkey; -+ } -+ -+ return 0; -+} -+ -+/** -+ * mipv6_slist_get_data - get the data item identified by sortkey -+ * @head: list_head of the sorted list -+ * @key: sortkey of the item -+ * -+ * Returns the actual data item, not copy, so don't kfree it -+ */ -+void *mipv6_slist_get_data(struct list_head *head, unsigned long sortkey) -+{ -+ struct list_head *pos; -+ struct mipv6_sorted_list_entry *entry; -+ -+ list_for_each(pos, head) { -+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list); -+ if (entry->sortkey == sortkey) -+ return entry->data; -+ } -+ -+ return NULL; -+} -+ -+/** -+ * reorder_entry - move an entry to a new position according to sortkey -+ * @head: list_head of the sorted list -+ * @entry_pos: current place of the entry -+ * @key: new sortkey -+ */ -+static void reorder_entry(struct list_head *head, struct list_head *entry_pos, -+ unsigned long sortkey) -+{ -+ struct list_head *pos; -+ struct mipv6_sorted_list_entry *entry; -+ -+ list_del(entry_pos); -+ -+ for (pos = head->next; pos != head; pos = pos->next) { -+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list); -+ if (sortkey >= entry->sortkey) { -+ list_add(entry_pos, &entry->list); -+ return; -+ } -+ } -+ -+ list_add(entry_pos, head); -+} -+ -+/** -+ * mipv6_slist_modify - modify data item -+ * @head: list_head of the sorted list -+ * @data: item, whose sortkey is to be modified -+ * @datalen: datalen in bytes -+ * @new_key: new sortkey -+ * @compare: function used for comparing the data items -+ * -+ * Compies the new data on top of the old one, if compare function returns -+ * true. If there's no matching entry, new one will be created. -+ * Compare function needs to have prototype -+ * int (*compare)(const void *data1, const void *data2, int datalen) -+ */ -+int mipv6_slist_modify(struct list_head *head, void *data, int datalen, -+ unsigned long new_key, -+ int (*compare)(const void *data1, const void *data2, -+ int datalen)) -+{ -+ struct list_head *pos; -+ struct mipv6_sorted_list_entry *entry; -+ -+ for (pos = head->next; pos != head; pos = pos->next) { -+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list); -+ if (compare(data, entry->data, datalen)) { -+ memcpy(entry->data, data, datalen); -+ entry->sortkey = new_key; -+ reorder_entry(head, &entry->list, new_key); -+ return 0; -+ } -+ } -+ -+ return mipv6_slist_add(head, data, datalen, new_key); -+} -+ -+/** -+ * mipv6_slist_push_first - move the first entry to place indicated by new_key -+ * @head: list_head of the sorted list -+ * @new_key: new sortkey -+ */ -+int mipv6_slist_push_first(struct list_head *head, unsigned long new_key) -+{ -+ struct mipv6_sorted_list_entry *entry; -+ -+ if (list_empty(head)) -+ return -1; -+ -+ entry = list_entry(head->next, struct mipv6_sorted_list_entry, list); -+ entry->sortkey = new_key; -+ -+ reorder_entry(head, head->next, new_key); -+ return 0; -+} -+ -+/** -+ * mipv6_slist_for_each - apply func to every item in list -+ * @head: list_head of the sorted list -+ * @args: args to pass to func -+ * @func: function to use -+ * -+ * function must be of type -+ * int (*func)(void *data, void *args, unsigned long sortkey) -+ * List iteration will stop once func has been applied to every item -+ * or when func returns true -+ */ -+int mipv6_slist_for_each(struct list_head *head, void *args, -+ int (*func)(void *data, void *args, -+ unsigned long sortkey)) -+{ -+ struct list_head *pos; -+ struct mipv6_sorted_list_entry *entry; -+ -+ list_for_each(pos, head) { -+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list); -+ if (func(entry->data, args, entry->sortkey)) -+ break; -+ } -+ -+ return 0; -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/sortedlist.h linux-2.4.25/net/ipv6/mobile_ip6/sortedlist.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/sortedlist.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/sortedlist.h 2004-06-26 11:29:31.000000000 +0100 -@@ -0,0 +1,133 @@ -+/* -+ * Sorted list - linked list with sortkey -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+ -+/** -+ * compare - compares two arbitrary data items -+ * @data1: first data item -+ * @data2: second data item -+ * @datalen: length of data items in bits -+ * -+ * datalen is in bits! -+ */ -+int mipv6_bitwise_compare(const void *data1, const void *data2, int datalen); -+ -+/** -+ * mipv6_slist_add - add an entry to sorted list -+ * @head: list_head of the sorted list -+ * @data: item to store -+ * @datalen: length of data (in bytes) -+ * @key: sortkey of item -+ * -+ * Allocates memory for entry and data -+ */ -+int mipv6_slist_add(struct list_head *head, void *data, int datalen, -+ unsigned long sortkey); -+ -+/** -+ * mipv6_slist_get_first - get the first data item in the list -+ * @head: list_head of the sorted list -+ * -+ * Returns the actual data item, not copy, so don't kfree it -+ */ -+void *mipv6_slist_get_first(struct list_head *head); -+ -+/** -+ * mipv6_slist_del_first - delete (and get) the first item in list -+ * @head: list_head of the sorted list -+ * -+ * Remember to kfree the item -+ */ -+void *mipv6_slist_del_first(struct list_head *head); -+ -+/** -+ * mipv6_slist_del_item - delete entry -+ * @head: list_head of the sorted list -+ * @data: item to delete -+ * @compare: function used for comparing the data items -+ * -+ * compare function needs to have prototype -+ * int (*compare)(const void *data1, const void *data2, int datalen) where -+ * datalen is in bits -+ */ -+int mipv6_slist_del_item(struct list_head *head, void *data, -+ int (*compare)(const void *data1, const void *data2, -+ int datalen)); -+ -+/** -+ * mipv6_slist_get_first_key - get sortkey of the first item -+ * @head: list_head of the sorted list -+ */ -+unsigned long mipv6_slist_get_first_key(struct list_head *head); -+ -+/** -+ * mipv6_slist_get_key - get sortkey of the data item -+ * @head: list_head of the sorted list -+ * @data: the item to search for -+ * @compare: function used for comparing the data items -+ * -+ * compare function needs to have prototype -+ * int (*compare)(const void *data1, const void *data2, int datalen) where -+ * datalen is in bits -+ */ -+unsigned long mipv6_slist_get_key(struct list_head *head, void *data, -+ int (*compare)(const void *data1, -+ const void *data2, -+ int datalen)); -+ -+/** -+ * mipv6_slist_get_data - get the data item identified by sortkey -+ * @head: list_head of the sorted list -+ * @key: sortkey of the item -+ * -+ * Returns the actual data item, not copy, so don't kfree it -+ */ -+void *mipv6_slist_get_data(struct list_head *head, unsigned long sortkey); -+ -+/** -+ * mipv6_slist_modify - modify data item -+ * @head: list_head of the sorted list -+ * @data: item, whose sortkey is to be modified -+ * @datalen: datalen in bytes -+ * @new_key: new sortkey -+ * @compare: function used for comparing the data items -+ * -+ * Compies the new data on top of the old one, if compare function returns -+ * non-negative. If there's no matching entry, new one will be created. -+ * Compare function needs to have prototype -+ * int (*compare)(const void *data1, const void *data2, int datalen) where -+ * datalen is in bits. -+ */ -+int mipv6_slist_modify(struct list_head *head, void *data, int datalen, -+ unsigned long new_key, -+ int (*compare)(const void *data1, const void *data2, -+ int datalen)); -+ -+/** -+ * mipv6_slist_push_first - move the first entry to place indicated by new_key -+ * @head: list_head of the sorted list -+ * @new_key: new sortkey -+ */ -+int mipv6_slist_push_first(struct list_head *head, unsigned long new_key); -+ -+/** -+ * mipv6_slist_for_each - apply func to every item in list -+ * @head: list_head of the sorted list -+ * @args: args to pass to func -+ * @func: function to use -+ * -+ * function must be of type -+ * int (*func)(void *data, void *args, unsigned long sortkey) -+ * List iteration will stop once func has been applied to every item -+ * or when func returns true -+ */ -+int mipv6_slist_for_each(struct list_head *head, void *args, -+ int (*func)(void *data, void *args, -+ unsigned long sortkey)); -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/stats.c linux-2.4.25/net/ipv6/mobile_ip6/stats.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/stats.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/stats.c 2004-06-26 11:29:32.000000000 +0100 -@@ -0,0 +1,90 @@ -+/* -+ * Statistics module -+ * -+ * Authors: -+ * Sami Kivisaari -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * Changes: -+ * Krishna Kumar, -+ * Venkata Jagana : SMP locking fix -+ */ -+ -+#include -+#include -+#include "stats.h" -+ -+struct mipv6_statistics mipv6_stats; -+ -+static int proc_info_dump( -+ char *buffer, char **start, -+ off_t offset, int length) -+{ -+ struct inf { -+ char *name; -+ int *value; -+ } int_stats[] = { -+ {"NEncapsulations", &mipv6_stats.n_encapsulations}, -+ {"NDecapsulations", &mipv6_stats.n_decapsulations}, -+ {"NBindRefreshRqsRcvd", &mipv6_stats.n_brr_rcvd}, -+ {"NHomeTestInitsRcvd", &mipv6_stats.n_hoti_rcvd}, -+ {"NCareofTestInitsRcvd", &mipv6_stats.n_coti_rcvd}, -+ {"NHomeTestRcvd", &mipv6_stats.n_hot_rcvd}, -+ {"NCareofTestRcvd", &mipv6_stats.n_cot_rcvd}, -+ {"NBindUpdatesRcvd", &mipv6_stats.n_bu_rcvd}, -+ {"NBindAcksRcvd", &mipv6_stats.n_ba_rcvd}, -+ {"NBindNAcksRcvd", &mipv6_stats.n_ban_rcvd}, -+ {"NBindErrorsRcvd", &mipv6_stats.n_be_rcvd}, -+ {"NBindRefreshRqsSent", &mipv6_stats.n_brr_sent}, -+ {"NHomeTestInitsSent", &mipv6_stats.n_hoti_sent}, -+ {"NCareofTestInitsSent", &mipv6_stats.n_coti_sent}, -+ {"NHomeTestSent", &mipv6_stats.n_hot_sent}, -+ {"NCareofTestSent", &mipv6_stats.n_cot_sent}, -+ {"NBindUpdatesSent", &mipv6_stats.n_bu_sent}, -+ {"NBindAcksSent", &mipv6_stats.n_ba_sent}, -+ {"NBindNAcksSent", &mipv6_stats.n_ban_sent}, -+ {"NBindErrorsSent", &mipv6_stats.n_be_sent}, -+ {"NBindUpdatesDropAuth", &mipv6_stats.n_bu_drop.auth}, -+ {"NBindUpdatesDropInvalid", &mipv6_stats.n_bu_drop.invalid}, -+ {"NBindUpdatesDropMisc", &mipv6_stats.n_bu_drop.misc}, -+ {"NBindAcksDropAuth", &mipv6_stats.n_bu_drop.auth}, -+ {"NBindAcksDropInvalid", &mipv6_stats.n_bu_drop.invalid}, -+ {"NBindAcksDropMisc", &mipv6_stats.n_bu_drop.misc}, -+ {"NBindRqsDropAuth", &mipv6_stats.n_bu_drop.auth}, -+ {"NBindRqsDropInvalid", &mipv6_stats.n_bu_drop.invalid}, -+ {"NBindRqsDropMisc", &mipv6_stats.n_bu_drop.misc} -+ }; -+ -+ int i; -+ int len = 0; -+ for(i=0; i length) len = length; -+ -+ return len; -+} -+ -+int mipv6_stats_init(void) -+{ -+ memset(&mipv6_stats, 0, sizeof(struct mipv6_statistics)); -+ proc_net_create("mip6_stat", 0, proc_info_dump); -+ return 0; -+} -+ -+void mipv6_stats_exit(void) -+{ -+ proc_net_remove("mip6_stat"); -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/stats.h linux-2.4.25/net/ipv6/mobile_ip6/stats.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/stats.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/stats.h 2004-06-26 11:29:32.000000000 +0100 -@@ -0,0 +1,71 @@ -+/* -+ * MIPL Mobile IPv6 Statistics header file -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _STATS_H -+#define _STATS_H -+ -+struct mipv6_drop { -+ __u32 auth; -+ __u32 invalid; -+ __u32 misc; -+}; -+ -+struct mipv6_statistics { -+ int n_encapsulations; -+ int n_decapsulations; -+ int n_mh_in_msg; -+ int n_mh_in_error; -+ int n_mh_out_msg; -+ int n_mh_out_error; -+ -+ int n_brr_rcvd; -+ int n_hoti_rcvd; -+ int n_coti_rcvd; -+ int n_hot_rcvd; -+ int n_cot_rcvd; -+ int n_bu_rcvd; -+ int n_ba_rcvd; -+ int n_ban_rcvd; -+ int n_be_rcvd; -+ -+ int n_brr_sent; -+ int n_hoti_sent; -+ int n_coti_sent; -+ int n_hot_sent; -+ int n_cot_sent; -+ int n_bu_sent; -+ int n_ba_sent; -+ int n_ban_sent; -+ int n_be_sent; -+ -+ int n_ha_rcvd; -+ int n_ha_sent; -+ -+ struct mipv6_drop n_bu_drop; -+ struct mipv6_drop n_ba_drop; -+ struct mipv6_drop n_brr_drop; -+ struct mipv6_drop n_be_drop; -+ struct mipv6_drop n_ha_drop; -+}; -+ -+extern struct mipv6_statistics mipv6_stats; -+ -+#ifdef CONFIG_SMP -+/* atomic_t is max 24 bits long */ -+#define MIPV6_INC_STATS(X) atomic_inc((atomic_t *)&mipv6_stats.X); -+#else -+#define MIPV6_INC_STATS(X) mipv6_stats.X++; -+#endif -+ -+int mipv6_stats_init(void); -+void mipv6_stats_exit(void); -+ -+#endif -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel.h linux-2.4.25/net/ipv6/mobile_ip6/tunnel.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/tunnel.h 2004-06-26 11:29:32.000000000 +0100 -@@ -0,0 +1,35 @@ -+/* -+ * MIPL Mobile IPv6 IP6-IP6 tunneling header file -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _TUNNEL_H -+#define _TUNNEL_H -+ -+#include -+#include -+#include -+ -+static __inline__ int is_mip6_tnl(struct ip6_tnl *t) -+{ -+ return (t != NULL && -+ t->parms.flags & IP6_TNL_F_KERNEL_DEV && -+ t->parms.flags & IP6_TNL_F_MIP6_DEV); -+ -+} -+ -+static __inline__ int dev_is_mip6_tnl(struct net_device *dev) -+{ -+ struct ip6_tnl *t = (struct ip6_tnl *)dev->priv; -+ return (dev->type == ARPHRD_TUNNEL6 && is_mip6_tnl(t)); -+} -+ -+ -+#endif -+ -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_ha.c linux-2.4.25/net/ipv6/mobile_ip6/tunnel_ha.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_ha.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/tunnel_ha.c 2004-06-26 11:29:32.000000000 +0100 -@@ -0,0 +1,264 @@ -+/* -+ * IPv6-IPv6 tunneling module -+ * -+ * Authors: -+ * Sami Kivisaari -+ * Ville Nuorvala -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 -+ -+#ifdef CONFIG_SYSCTL -+#include -+#endif /* CONFIG_SYSCTL */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "tunnel.h" -+#include "debug.h" -+#include "stats.h" -+#include "config.h" -+ -+#define MIPV6_TNL_MAX IP6_TNL_MAX -+#define MIPV6_TNL_MIN 1 -+ -+int mipv6_max_tnls = 3; -+int mipv6_min_tnls = 1; -+ -+DECLARE_MUTEX(tnl_sem); -+ -+int mipv6_max_tnls_sysctl(ctl_table *ctl, int write, struct file *filp, -+ void *buffer, size_t *lenp) -+{ -+ int err; -+ -+ DEBUG_FUNC(); -+ -+ down(&tnl_sem); -+ if (write) { -+ int diff; -+ int old_max_tnls = mipv6_max_tnls; -+ err = proc_dointvec(ctl, write, filp, buffer, lenp); -+ if (err < 0) -+ goto out; -+ if (mipv6_max_tnls < mipv6_min_tnls || -+ mipv6_max_tnls > MIPV6_TNL_MAX) { -+ mipv6_max_tnls = old_max_tnls; -+ goto out; -+ } -+ if (mipv6_max_tnls < old_max_tnls) { -+ diff = old_max_tnls - mipv6_max_tnls; -+ ip6ip6_tnl_dec_max_kdev_count(diff); -+ } else if (mipv6_max_tnls > old_max_tnls) { -+ diff = mipv6_max_tnls - old_max_tnls; -+ ip6ip6_tnl_inc_max_kdev_count(diff); -+ } -+ } else { -+ err = proc_dointvec(ctl, write, filp, buffer, lenp); -+ } -+out: -+ up(&tnl_sem); -+ return err; -+} -+ -+int mipv6_min_tnls_sysctl(ctl_table *ctl, int write, struct file *filp, -+ void *buffer, size_t *lenp) -+{ -+ int err; -+ -+ DEBUG_FUNC(); -+ -+ down(&tnl_sem); -+ if (write) { -+ int diff; -+ int old_min_tnls = mipv6_min_tnls; -+ err = proc_dointvec(ctl, write, filp, buffer, lenp); -+ if (err < 0) -+ goto out; -+ if (mipv6_min_tnls > mipv6_max_tnls || -+ mipv6_min_tnls < MIPV6_TNL_MIN) { -+ mipv6_min_tnls = old_min_tnls; -+ goto out; -+ } -+ if (mipv6_min_tnls < old_min_tnls) { -+ diff = old_min_tnls - mipv6_min_tnls; -+ ip6ip6_tnl_dec_min_kdev_count(diff); -+ } else if (mipv6_min_tnls > old_min_tnls) { -+ diff = mipv6_min_tnls - old_min_tnls; -+ ip6ip6_tnl_inc_min_kdev_count(diff); -+ } -+ } else { -+ err = proc_dointvec(ctl, write, filp, buffer, lenp); -+ } -+out: -+ up(&tnl_sem); -+ return err; -+} -+ -+static __inline__ int mipv6_tnl_add(struct in6_addr *remote, -+ struct in6_addr *local) -+{ -+ struct ip6_tnl_parm p; -+ int ret; -+ -+ DEBUG_FUNC(); -+ -+ memset(&p, 0, sizeof(p)); -+ p.proto = IPPROTO_IPV6; -+ ipv6_addr_copy(&p.laddr, local); -+ ipv6_addr_copy(&p.raddr, remote); -+ p.hop_limit = 255; -+ p.flags = (IP6_TNL_F_KERNEL_DEV | IP6_TNL_F_MIP6_DEV | -+ IP6_TNL_F_IGN_ENCAP_LIMIT); -+ -+ ret = ip6ip6_kernel_tnl_add(&p); -+ if (ret > 0) { -+ DEBUG(DBG_INFO, "added tunnel from: " -+ "%x:%x:%x:%x:%x:%x:%x:%x to: %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(local), NIPV6ADDR(remote)); -+ } else { -+ DEBUG(DBG_WARNING, "unable to add tunnel from: " -+ "%x:%x:%x:%x:%x:%x:%x:%x to: %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(local), NIPV6ADDR(remote)); -+ } -+ return ret; -+} -+ -+static __inline__ int mipv6_tnl_del(struct in6_addr *remote, -+ struct in6_addr *local) -+{ -+ struct ip6_tnl *t = ip6ip6_tnl_lookup(remote, local); -+ -+ DEBUG_FUNC(); -+ -+ if (t != NULL && (t->parms.flags & IP6_TNL_F_MIP6_DEV)) { -+ DEBUG(DBG_INFO, "deleting tunnel from: " -+ "%x:%x:%x:%x:%x:%x:%x:%x to: %x:%x:%x:%x:%x:%x:%x:%x", -+ NIPV6ADDR(local), NIPV6ADDR(remote)); -+ -+ return ip6ip6_kernel_tnl_del(t); -+ } -+ return 0; -+} -+ -+static int add_route_to_mn(struct in6_addr *coa, struct in6_addr *ha_addr, -+ struct in6_addr *home_addr) -+{ -+ struct in6_rtmsg rtmsg; -+ int err; -+ struct ip6_tnl *t = ip6ip6_tnl_lookup(coa, ha_addr); -+ -+ if (!is_mip6_tnl(t)) { -+ DEBUG(DBG_CRITICAL,"Tunnel missing"); -+ return -ENODEV; -+ } -+ -+ DEBUG(DBG_INFO, "adding route to: %x:%x:%x:%x:%x:%x:%x:%x via " -+ "tunnel device", NIPV6ADDR(home_addr)); -+ -+ memset(&rtmsg, 0, sizeof(rtmsg)); -+ ipv6_addr_copy(&rtmsg.rtmsg_dst, home_addr); -+ rtmsg.rtmsg_dst_len = 128; -+ rtmsg.rtmsg_type = RTMSG_NEWROUTE; -+ rtmsg.rtmsg_flags = RTF_UP | RTF_NONEXTHOP | RTF_HOST | RTF_MOBILENODE; -+ rtmsg.rtmsg_ifindex = t->dev->ifindex; -+ rtmsg.rtmsg_metric = IP6_RT_PRIO_MIPV6; -+ if ((err = ip6_route_add(&rtmsg, NULL)) == -EEXIST) { -+ err = 0; -+ } -+ return err; -+} -+ -+static void del_route_to_mn(struct in6_addr *coa, struct in6_addr *ha_addr, -+ struct in6_addr *home_addr) -+{ -+ struct ip6_tnl *t = ip6ip6_tnl_lookup(coa, ha_addr); -+ -+ DEBUG_FUNC(); -+ -+ if (is_mip6_tnl(t)) { -+ struct in6_rtmsg rtmsg; -+ -+ DEBUG(DBG_INFO, "deleting route to: %x:%x:%x:%x:%x:%x:%x:%x " -+ " via tunnel device", NIPV6ADDR(home_addr)); -+ -+ memset(&rtmsg, 0, sizeof(rtmsg)); -+ ipv6_addr_copy(&rtmsg.rtmsg_dst, home_addr); -+ rtmsg.rtmsg_dst_len = 128; -+ rtmsg.rtmsg_ifindex = t->dev->ifindex; -+ rtmsg.rtmsg_metric = IP6_RT_PRIO_MIPV6; -+ ip6_route_del(&rtmsg, NULL); -+ } -+} -+ -+ -+int mipv6_add_tnl_to_mn(struct in6_addr *coa, -+ struct in6_addr *ha_addr, -+ struct in6_addr *home_addr) -+{ -+ int ret; -+ -+ DEBUG_FUNC(); -+ -+ ret = mipv6_tnl_add(coa, ha_addr); -+ -+ if (ret > 0) { -+ int err = add_route_to_mn(coa, ha_addr, home_addr); -+ if (err) { -+ if (err != -ENODEV) { -+ mipv6_tnl_del(coa, ha_addr); -+ } -+ return err; -+ } -+ } -+ return ret; -+} -+ -+int mipv6_del_tnl_to_mn(struct in6_addr *coa, -+ struct in6_addr *ha_addr, -+ struct in6_addr *home_addr) -+{ -+ DEBUG_FUNC(); -+ del_route_to_mn(coa, ha_addr, home_addr); -+ return mipv6_tnl_del(coa, ha_addr); -+} -+ -+__init void mipv6_initialize_tunnel(void) -+{ -+ down(&tnl_sem); -+ ip6ip6_tnl_inc_max_kdev_count(mipv6_max_tnls); -+ ip6ip6_tnl_inc_min_kdev_count(mipv6_min_tnls); -+ up(&tnl_sem); -+ mip6_fn.bce_tnl_rt_add = add_route_to_mn; -+ mip6_fn.bce_tnl_rt_del = del_route_to_mn; -+} -+ -+__exit void mipv6_shutdown_tunnel(void) -+{ -+ mip6_fn.bce_tnl_rt_del = NULL; -+ mip6_fn.bce_tnl_rt_add = NULL; -+ down(&tnl_sem); -+ ip6ip6_tnl_dec_min_kdev_count(mipv6_min_tnls); -+ ip6ip6_tnl_dec_max_kdev_count(mipv6_max_tnls); -+ up(&tnl_sem); -+} -+ -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_ha.h linux-2.4.25/net/ipv6/mobile_ip6/tunnel_ha.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_ha.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/tunnel_ha.h 2004-06-26 11:29:32.000000000 +0100 -@@ -0,0 +1,20 @@ -+#ifndef _TUNNEL_HA_H -+#define _TUNNEL_HA_H -+ -+#include "tunnel.h" -+ -+extern int mipv6_max_tnls; -+extern int mipv6_min_tnls; -+ -+extern void mipv6_initialize_tunnel(void); -+extern void mipv6_shutdown_tunnel(void); -+ -+extern int mipv6_add_tnl_to_mn(struct in6_addr *coa, -+ struct in6_addr *ha_addr, -+ struct in6_addr *home_addr); -+ -+extern int mipv6_del_tnl_to_mn(struct in6_addr *coa, -+ struct in6_addr *ha_addr, -+ struct in6_addr *home_addr); -+ -+#endif -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_mn.c linux-2.4.25/net/ipv6/mobile_ip6/tunnel_mn.c ---- linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_mn.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/tunnel_mn.c 2004-06-26 11:29:32.000000000 +0100 -@@ -0,0 +1,160 @@ -+/* -+ * IPv6-IPv6 tunneling module -+ * -+ * Authors: -+ * Sami Kivisaari -+ * Ville Nuorvala -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 -+ -+#ifdef CONFIG_SYSCTL -+#include -+#endif /* CONFIG_SYSCTL */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "tunnel.h" -+#include "debug.h" -+#include "stats.h" -+ -+static struct net_device *mn_ha_tdev; -+ -+static spinlock_t mn_ha_lock = SPIN_LOCK_UNLOCKED; -+ -+static __inline__ int add_reverse_route(struct in6_addr *ha_addr, -+ struct in6_addr *home_addr, -+ struct net_device *tdev) -+{ -+ struct in6_rtmsg rtmsg; -+ int err; -+ -+ DEBUG_FUNC(); -+ -+ memset(&rtmsg, 0, sizeof(rtmsg)); -+ rtmsg.rtmsg_type = RTMSG_NEWROUTE; -+ ipv6_addr_copy(&rtmsg.rtmsg_src, home_addr); -+ rtmsg.rtmsg_src_len = 128; -+ rtmsg.rtmsg_flags = RTF_UP | RTF_DEFAULT; -+ rtmsg.rtmsg_ifindex = tdev->ifindex; -+ rtmsg.rtmsg_metric = IP6_RT_PRIO_MIPV6; -+ if ((err = ip6_route_add(&rtmsg, NULL)) == -EEXIST) { -+ return 0; -+ } -+ return err; -+} -+ -+static __inline__ void del_reverse_route(struct in6_addr *ha_addr, -+ struct in6_addr *home_addr, -+ struct net_device *tdev) -+{ -+ struct in6_rtmsg rtmsg; -+ -+ DEBUG(DBG_INFO, "removing reverse route via tunnel device"); -+ -+ memset(&rtmsg, 0, sizeof(rtmsg)); -+ ipv6_addr_copy(&rtmsg.rtmsg_src, home_addr); -+ rtmsg.rtmsg_src_len = 128; -+ rtmsg.rtmsg_ifindex = tdev->ifindex; -+ rtmsg.rtmsg_metric = IP6_RT_PRIO_MIPV6; -+ ip6_route_del(&rtmsg, NULL); -+} -+ -+int mipv6_add_tnl_to_ha(void) -+{ -+ struct ip6_tnl_parm p; -+ struct ip6_tnl *t; -+ int err; -+ -+ DEBUG_FUNC(); -+ -+ memset(&p, 0, sizeof(p)); -+ p.proto = IPPROTO_IPV6; -+ p.hop_limit = 255; -+ p.flags = (IP6_TNL_F_KERNEL_DEV | IP6_TNL_F_MIP6_DEV | -+ IP6_TNL_F_IGN_ENCAP_LIMIT); -+ strcpy(p.name, "mip6mnha1"); -+ -+ rtnl_lock(); -+ if ((err = ip6ip6_tnl_create(&p, &t))) { -+ rtnl_unlock(); -+ return err; -+ } -+ spin_lock_bh(&mn_ha_lock); -+ -+ if (!mn_ha_tdev) { -+ mn_ha_tdev = t->dev; -+ dev_hold(mn_ha_tdev); -+ } -+ spin_unlock_bh(&mn_ha_lock); -+ dev_open(t->dev); -+ rtnl_unlock(); -+ return 0; -+} -+ -+int mipv6_mv_tnl_to_ha(struct in6_addr *ha_addr, -+ struct in6_addr *coa, -+ struct in6_addr *home_addr) -+{ -+ int err = -ENODEV; -+ -+ DEBUG_FUNC(); -+ -+ spin_lock_bh(&mn_ha_lock); -+ if (mn_ha_tdev) { -+ struct ip6_tnl_parm p; -+ memset(&p, 0, sizeof(p)); -+ p.proto = IPPROTO_IPV6; -+ ipv6_addr_copy(&p.laddr, coa); -+ ipv6_addr_copy(&p.raddr, ha_addr); -+ p.hop_limit = 255; -+ p.flags = (IP6_TNL_F_KERNEL_DEV | IP6_TNL_F_MIP6_DEV | -+ IP6_TNL_F_IGN_ENCAP_LIMIT); -+ -+ ip6ip6_tnl_change((struct ip6_tnl *) mn_ha_tdev->priv, &p); -+ if (ipv6_addr_cmp(coa, home_addr)) { -+ err = add_reverse_route(ha_addr, home_addr, -+ mn_ha_tdev); -+ } else { -+ del_reverse_route(ha_addr, home_addr, mn_ha_tdev); -+ err = 0; -+ } -+ } -+ spin_unlock_bh(&mn_ha_lock); -+ return err; -+} -+ -+void mipv6_del_tnl_to_ha(void) -+{ -+ struct net_device *dev; -+ -+ DEBUG_FUNC(); -+ -+ rtnl_lock(); -+ spin_lock_bh(&mn_ha_lock); -+ dev = mn_ha_tdev; -+ mn_ha_tdev = NULL; -+ spin_unlock_bh(&mn_ha_lock); -+ dev_put(dev); -+ unregister_netdevice(dev); -+ rtnl_unlock(); -+} -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_mn.h linux-2.4.25/net/ipv6/mobile_ip6/tunnel_mn.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_mn.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/tunnel_mn.h 2004-06-26 11:29:32.000000000 +0100 -@@ -0,0 +1,14 @@ -+#ifndef _TUNNEL_MN_H -+#define _TUNNEL_MN_H -+ -+#include "tunnel.h" -+ -+extern int mipv6_add_tnl_to_ha(void); -+ -+extern int mipv6_mv_tnl_to_ha(struct in6_addr *ha_addr, -+ struct in6_addr *coa, -+ struct in6_addr *home_addr); -+ -+extern int mipv6_del_tnl_to_ha(void); -+ -+#endif -diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/util.h linux-2.4.25/net/ipv6/mobile_ip6/util.h ---- linux-2.4.25.old/net/ipv6/mobile_ip6/util.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.25/net/ipv6/mobile_ip6/util.h 2004-06-26 11:29:32.000000000 +0100 -@@ -0,0 +1,91 @@ -+/* -+ * MIPL Mobile IPv6 Utility functions -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the 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 _UTIL_H -+#define _UTIL_H -+ -+#include -+#include -+ -+/** -+ * mipv6_prefix_compare - Compare two IPv6 prefixes -+ * @addr: IPv6 address -+ * @prefix: IPv6 address -+ * @nprefix: number of bits to compare -+ * -+ * Perform prefix comparison bitwise for the @nprefix first bits -+ * Returns 1, if the prefixes are the same, 0 otherwise -+ **/ -+static inline int mipv6_prefix_compare(const struct in6_addr *addr, -+ const struct in6_addr *prefix, -+ const unsigned int pfix_len) -+{ -+ int i; -+ unsigned int nprefix = pfix_len; -+ -+ if (nprefix > 128) -+ return 0; -+ -+ for (i = 0; nprefix > 0; nprefix -= 32, i++) { -+ if (nprefix >= 32) { -+ if (addr->s6_addr32[i] != prefix->s6_addr32[i]) -+ return 0; -+ } else { -+ if (((addr->s6_addr32[i] ^ prefix->s6_addr32[i]) & -+ ((~0) << (32 - nprefix))) != 0) -+ return 0; -+ return 1; -+ } -+ } -+ -+ return 1; -+} -+ -+/** -+ * homeagent_anycast - Compute Home Agent anycast address -+ * @ac_addr: append home agent anycast suffix to passed prefix -+ * @prefix: prefix ha anycast address is generated from -+ * @plen: length of prefix in bits -+ * -+ * Calculate corresponding Home Agent Anycast Address (RFC2526) in a -+ * given subnet. -+ */ -+static inline int -+mipv6_ha_anycast(struct in6_addr *ac_addr, struct in6_addr *prefix, int plen) -+{ -+ if (plen <= 0 || plen > 120) { -+ /* error, interface id should be minimum 8 bits */ -+ return -1; -+ } -+ ipv6_addr_copy(ac_addr, prefix); -+ -+ if (plen < 32) -+ ac_addr->s6_addr32[0] |= htonl((u32)(~0) >> plen); -+ if (plen < 64) -+ ac_addr->s6_addr32[1] |= htonl((u32)(~0) >> (plen > 32 ? plen % 32 : 0)); -+ if (plen < 92) -+ ac_addr->s6_addr32[2] |= htonl((u32)(~0) >> (plen > 64 ? plen % 32 : 0)); -+ if (plen <= 120) -+ ac_addr->s6_addr32[3] |= htonl((u32)(~0) >> (plen > 92 ? plen % 32 : 0)); -+ -+ /* RFC2526: for interface identifiers in EUI-64 -+ * format, the universal/local bit in the interface -+ * identifier MUST be set to 0. */ -+ if (plen == 64) { -+ ac_addr->s6_addr32[2] &= (int)htonl(0xfdffffff); -+ } -+ /* Mobile IPv6 Home-Agents anycast id (0x7e) */ -+ ac_addr->s6_addr32[3] &= (int)htonl(0xfffffffe); -+ -+ return 0; -+} -+ -+#endif /* _UTIL_H */ -diff -uprN linux-2.4.25.old/net/ipv6/ndisc.c linux-2.4.25/net/ipv6/ndisc.c ---- linux-2.4.25.old/net/ipv6/ndisc.c 2003-11-28 18:26:21.000000000 +0000 -+++ linux-2.4.25/net/ipv6/ndisc.c 2004-06-26 11:29:32.000000000 +0100 -@@ -23,6 +23,7 @@ - * and moved to net/core. - * Pekka Savola : RFC2461 validation - * YOSHIFUJI Hideaki @USAGI : Verify ND options properly -+ * Ville Nuorvala : RFC2461 fixes to proxy ND - */ - - /* Set to 3 to get tracing... */ -@@ -70,6 +71,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -187,6 +189,8 @@ struct ndisc_options *ndisc_parse_option - case ND_OPT_TARGET_LL_ADDR: - case ND_OPT_MTU: - case ND_OPT_REDIRECT_HDR: -+ case ND_OPT_RTR_ADV_INTERVAL: -+ case ND_OPT_HOME_AGENT_INFO: - if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) { - ND_PRINTK2((KERN_WARNING - "ndisc_parse_options(): duplicated ND6 option found: type=%d\n", -@@ -372,8 +376,8 @@ ndisc_build_ll_hdr(struct sk_buff *skb, - */ - - void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, -- struct in6_addr *daddr, struct in6_addr *solicited_addr, -- int router, int solicited, int override, int inc_opt) -+ struct in6_addr *daddr, struct in6_addr *solicited_addr, -+ int router, int solicited, int override, int inc_opt) - { - static struct in6_addr tmpaddr; - struct inet6_ifaddr *ifp; -@@ -766,7 +770,8 @@ void ndisc_recv_ns(struct sk_buff *skb) - int addr_type = ipv6_addr_type(saddr); - - if (in6_dev && in6_dev->cnf.forwarding && -- (addr_type & IPV6_ADDR_UNICAST) && -+ (addr_type & IPV6_ADDR_UNICAST || -+ addr_type == IPV6_ADDR_ANY) && - pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) { - int inc = ipv6_addr_type(daddr)&IPV6_ADDR_MULTICAST; - -@@ -778,13 +783,21 @@ void ndisc_recv_ns(struct sk_buff *skb) - nd_tbl.stats.rcv_probes_mcast++; - else - nd_tbl.stats.rcv_probes_ucast++; -- -- neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev); - -- if (neigh) { -- ndisc_send_na(dev, neigh, saddr, &msg->target, -- 0, 1, 0, 1); -- neigh_release(neigh); -+ if (addr_type & IPV6_ADDR_UNICAST) { -+ neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev); -+ -+ if (neigh) { -+ ndisc_send_na(dev, neigh, saddr, &msg->target, -+ 0, 1, 0, 1); -+ neigh_release(neigh); -+ } -+ } else { -+ /* the proxy should also protect against DAD */ -+ struct in6_addr maddr; -+ ipv6_addr_all_nodes(&maddr); -+ ndisc_send_na(dev, NULL, &maddr, &msg->target, -+ 0, 0, 0, 1); - } - } else { - struct sk_buff *n = skb_clone(skb, GFP_ATOMIC); -@@ -849,6 +862,9 @@ void ndisc_recv_na(struct sk_buff *skb) - if (ifp->flags & IFA_F_TENTATIVE) { - addrconf_dad_failure(ifp); - return; -+ } else if (ndisc_mip_mn_ha_probe(ifp, lladdr)) { -+ in6_ifa_put(ifp); -+ return; - } - /* What should we make now? The advertisement - is invalid, but ndisc specs say nothing -@@ -887,6 +903,7 @@ void ndisc_recv_na(struct sk_buff *skb) - msg->icmph.icmp6_override, 1); - neigh_release(neigh); - } -+ ndisc_check_mipv6_dad(&msg->target); - } - - static void ndisc_router_discovery(struct sk_buff *skb) -@@ -894,6 +911,7 @@ static void ndisc_router_discovery(struc - struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw; - struct neighbour *neigh; - struct inet6_dev *in6_dev; -+ int change_rtr; - struct rt6_info *rt; - int lifetime; - struct ndisc_options ndopts; -@@ -923,10 +941,6 @@ static void ndisc_router_discovery(struc - ND_PRINTK1("RA: can't find in6 device\n"); - return; - } -- if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) { -- in6_dev_put(in6_dev); -- return; -- } - - if (!ndisc_parse_options(opt, optlen, &ndopts)) { - in6_dev_put(in6_dev); -@@ -935,7 +949,12 @@ static void ndisc_router_discovery(struc - "ICMP6 RA: invalid ND option, ignored.\n"); - return; - } -+ change_rtr = ndisc_mipv6_ra_rcv(skb, &ndopts); - -+ if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) { -+ in6_dev_put(in6_dev); -+ return; -+ } - if (in6_dev->if_flags & IF_RS_SENT) { - /* - * flag that an RA was received after an RS was sent -@@ -963,8 +982,7 @@ static void ndisc_router_discovery(struc - ip6_del_rt(rt, NULL); - rt = NULL; - } -- -- if (rt == NULL && lifetime) { -+ if (rt == NULL && lifetime && change_rtr) { - ND_PRINTK2("ndisc_rdisc: adding default router\n"); - - rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev); -@@ -1087,6 +1105,8 @@ out: - if (rt) - dst_release(&rt->u.dst); - in6_dev_put(in6_dev); -+ -+ ndisc_mipv6_change_router(change_rtr); - } - - static void ndisc_redirect_rcv(struct sk_buff *skb) -diff -uprN linux-2.4.25.old/net/ipv6/raw.c linux-2.4.25/net/ipv6/raw.c ---- linux-2.4.25.old/net/ipv6/raw.c 2003-11-28 18:26:21.000000000 +0000 -+++ linux-2.4.25/net/ipv6/raw.c 2004-06-26 11:29:32.000000000 +0100 -@@ -43,6 +43,7 @@ - #include - #include - #include -+#include - - #include - -@@ -636,6 +637,7 @@ static int rawv6_sendmsg(struct sock *sk - hdr.daddr = daddr; - else - hdr.daddr = NULL; -+ hdr.daddr = mipv6_get_fake_hdr_daddr(hdr.daddr, daddr); - - err = ip6_build_xmit(sk, rawv6_frag_cksum, &hdr, &fl, len, - opt, hlimit, msg->msg_flags); -diff -uprN linux-2.4.25.old/net/ipv6/route.c linux-2.4.25/net/ipv6/route.c ---- linux-2.4.25.old/net/ipv6/route.c 2004-02-18 13:36:32.000000000 +0000 -+++ linux-2.4.25/net/ipv6/route.c 2004-06-26 11:29:32.000000000 +0100 -@@ -49,6 +49,7 @@ - #include - #include - #include -+#include - - #include - -@@ -363,12 +364,8 @@ static struct rt6_info *rt6_cow(struct r - rt->u.dst.flags |= DST_HOST; - - #ifdef CONFIG_IPV6_SUBTREES -- if (rt->rt6i_src.plen && saddr) { -- ipv6_addr_copy(&rt->rt6i_src.addr, saddr); -- rt->rt6i_src.plen = 128; -- } -+ rt->rt6i_src.plen = ort->rt6i_src.plen; - #endif -- - rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); - - dst_hold(&rt->u.dst); -@@ -511,14 +508,19 @@ struct dst_entry * ip6_route_output(stru - struct rt6_info *rt; - int strict; - int attempts = 3; -+ struct in6_addr *saddr; - -+ if (ipv6_chk_addr(fl->nl_u.ip6_u.daddr, NULL)) -+ saddr = NULL; -+ else -+ saddr = fl->nl_u.ip6_u.saddr; -+ - strict = ipv6_addr_type(fl->nl_u.ip6_u.daddr) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL); - - relookup: - read_lock_bh(&rt6_lock); - -- fn = fib6_lookup(&ip6_routing_table, fl->nl_u.ip6_u.daddr, -- fl->nl_u.ip6_u.saddr); -+ fn = fib6_lookup(&ip6_routing_table, fl->nl_u.ip6_u.daddr, saddr); - - restart: - rt = fn->leaf; -@@ -663,25 +665,6 @@ out: - return (atomic_read(&ip6_dst_ops.entries) > ip6_rt_max_size); - } - --/* Clean host part of a prefix. Not necessary in radix tree, -- but results in cleaner routing tables. -- -- Remove it only when all the things will work! -- */ -- --static void ipv6_addr_prefix(struct in6_addr *pfx, -- const struct in6_addr *addr, int plen) --{ -- int b = plen&0x7; -- int o = plen>>3; -- -- memcpy(pfx->s6_addr, addr, o); -- if (o < 16) -- memset(pfx->s6_addr + o, 0, 16 - o); -- if (b != 0) -- pfx->s6_addr[o] = addr->s6_addr[o]&(0xff00 >> b); --} -- - static int ipv6_get_mtu(struct net_device *dev) - { - int mtu = IPV6_MIN_MTU; -@@ -810,7 +793,7 @@ int ip6_route_add(struct in6_rtmsg *rtms - if (!(gwa_type&IPV6_ADDR_UNICAST)) - goto out; - -- grt = rt6_lookup(gw_addr, NULL, rtmsg->rtmsg_ifindex, 1); -+ grt = rt6_lookup(gw_addr, &rtmsg->rtmsg_src, rtmsg->rtmsg_ifindex, 1); - - err = -EHOSTUNREACH; - if (grt == NULL) -@@ -848,7 +831,15 @@ int ip6_route_add(struct in6_rtmsg *rtms - goto out; - } - } -- -+#ifdef USE_IPV6_MOBILITY -+ /* If destination is mobile node, add special skb->dst->input -+ * function for proxy ND. -+ */ -+ if (rtmsg->rtmsg_flags & RTF_MOBILENODE) { -+ rt->u.dst.input = ip6_mipv6_forward; -+ } -+#endif /* CONFIG_IPV6_MOBILITY */ -+ - if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) - rt->rt6i_hoplimit = IPV6_DEFAULT_MCASTHOPS; - else -@@ -936,7 +927,7 @@ void rt6_redirect(struct in6_addr *dest, - struct rt6_info *rt, *nrt; - - /* Locate old route to this destination. */ -- rt = rt6_lookup(dest, NULL, neigh->dev->ifindex, 1); -+ rt = rt6_lookup(dest, saddr, neigh->dev->ifindex, 1); - - if (rt == NULL) - return; -@@ -1003,6 +994,9 @@ source_ok: - nrt = ip6_rt_copy(rt); - if (nrt == NULL) - goto out; -+#ifdef CONFIG_IPV6_SUBTREES -+ nrt->rt6i_src.plen = rt->rt6i_src.plen; -+#endif - - nrt->rt6i_flags = RTF_GATEWAY|RTF_UP|RTF_DYNAMIC|RTF_CACHE; - if (on_link) -@@ -1104,6 +1098,9 @@ void rt6_pmtu_discovery(struct in6_addr - nrt = ip6_rt_copy(rt); - if (nrt == NULL) - goto out; -+#ifdef CONFIG_IPV6_SUBTREES -+ nrt->rt6i_src.plen = rt->rt6i_src.plen; -+#endif - ipv6_addr_copy(&nrt->rt6i_dst.addr, daddr); - nrt->rt6i_dst.plen = 128; - nrt->u.dst.flags |= DST_HOST; -diff -uprN linux-2.4.25.old/net/ipv6/tcp_ipv6.c linux-2.4.25/net/ipv6/tcp_ipv6.c ---- linux-2.4.25.old/net/ipv6/tcp_ipv6.c 2003-11-28 18:26:21.000000000 +0000 -+++ linux-2.4.25/net/ipv6/tcp_ipv6.c 2004-06-26 11:29:32.000000000 +0100 -@@ -50,6 +50,7 @@ - #include - #include - #include -+#include - - #include - -@@ -557,6 +558,7 @@ static int tcp_v6_connect(struct sock *s - struct flowi fl; - struct dst_entry *dst; - int addr_type; -+ int reroute = 0; - int err; - - if (addr_len < SIN6_LEN_RFC2133) -@@ -660,7 +662,7 @@ static int tcp_v6_connect(struct sock *s - - fl.proto = IPPROTO_TCP; - fl.fl6_dst = &np->daddr; -- fl.fl6_src = saddr; -+ fl.fl6_src = saddr; - fl.oif = sk->bound_dev_if; - fl.uli_u.ports.dport = usin->sin6_port; - fl.uli_u.ports.sport = sk->sport; -@@ -669,31 +671,46 @@ static int tcp_v6_connect(struct sock *s - struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; - fl.nl_u.ip6_u.daddr = rt0->addr; - } -- - dst = ip6_route_output(sk, &fl); -- -+#ifdef CONFIG_IPV6_SUBTREES -+ reroute = (saddr == NULL); -+#endif - if ((err = dst->error) != 0) { - dst_release(dst); - goto failure; - } -- -- ip6_dst_store(sk, dst, NULL); -- sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM; -- -+ if (!reroute) { -+ ip6_dst_store(sk, dst, NULL, NULL); -+ sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM; -+ } - if (saddr == NULL) { - err = ipv6_get_saddr(dst, &np->daddr, &saddr_buf); -+ -+ if (reroute) -+ dst_release(dst); - if (err) - goto failure; - - saddr = &saddr_buf; -+ ipv6_addr_copy(&np->rcv_saddr, saddr); -+#ifdef CONFIG_IPV6_SUBTREES -+ fl.fl6_src = saddr; -+ dst = ip6_route_output(sk, &fl); -+ -+ if ((err = dst->error) != 0) { -+ dst_release(dst); -+ goto failure; -+ } -+ ip6_dst_store(sk, dst, NULL, NULL); -+ sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM; -+#endif - } - - /* set the source address */ -- ipv6_addr_copy(&np->rcv_saddr, saddr); - ipv6_addr_copy(&np->saddr, saddr); - sk->rcv_saddr= LOOPBACK4_IPV6; - -- tp->ext_header_len = 0; -+ tp->ext_header_len = tcp_v6_get_mipv6_header_len(); - if (np->opt) - tp->ext_header_len = np->opt->opt_flen+np->opt->opt_nflen; - tp->mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); -@@ -1338,7 +1355,7 @@ static struct sock * tcp_v6_syn_recv_soc - #endif - MOD_INC_USE_COUNT; - -- ip6_dst_store(newsk, dst, NULL); -+ ip6_dst_store(newsk, dst, NULL, NULL); - sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM; - - newtp = &(newsk->tp_pinfo.af_tcp); -@@ -1383,7 +1400,7 @@ static struct sock * tcp_v6_syn_recv_soc - sock_kfree_s(sk, opt, opt->tot_len); - } - -- newtp->ext_header_len = 0; -+ newtp->ext_header_len = tcp_v6_get_mipv6_header_len(); - if (np->opt) - newtp->ext_header_len = np->opt->opt_nflen + np->opt->opt_flen; - -@@ -1710,7 +1727,7 @@ static int tcp_v6_rebuild_header(struct - return err; - } - -- ip6_dst_store(sk, dst, NULL); -+ ip6_dst_store(sk, dst, NULL, NULL); - sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM; - } - -@@ -1749,7 +1766,7 @@ static int tcp_v6_xmit(struct sk_buff *s - return -sk->err_soft; - } - -- ip6_dst_store(sk, dst, NULL); -+ ip6_dst_store(sk, dst, NULL, NULL); - } - - skb->dst = dst_clone(dst); -diff -uprN linux-2.4.25.old/net/ipv6/udp.c linux-2.4.25/net/ipv6/udp.c ---- linux-2.4.25.old/net/ipv6/udp.c 2004-02-18 13:36:32.000000000 +0000 -+++ linux-2.4.25/net/ipv6/udp.c 2004-06-26 11:29:32.000000000 +0100 -@@ -48,6 +48,7 @@ - #include - #include - #include -+#include - - #include - -@@ -232,6 +233,7 @@ int udpv6_connect(struct sock *sk, struc - struct ip6_flowlabel *flowlabel = NULL; - int addr_type; - int err; -+ int reroute = 0; - - if (usin->sin6_family == AF_INET) { - if (__ipv6_only_sock(sk)) -@@ -331,7 +333,7 @@ ipv4_connected: - - fl.proto = IPPROTO_UDP; - fl.fl6_dst = &np->daddr; -- fl.fl6_src = &saddr; -+ fl.fl6_src = NULL; - fl.oif = sk->bound_dev_if; - fl.uli_u.ports.dport = sk->dport; - fl.uli_u.ports.sport = sk->sport; -@@ -348,29 +350,44 @@ ipv4_connected: - struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; - fl.fl6_dst = rt0->addr; - } -- - dst = ip6_route_output(sk, &fl); -- - if ((err = dst->error) != 0) { - dst_release(dst); - fl6_sock_release(flowlabel); -- return err; -- } -- -- ip6_dst_store(sk, dst, fl.fl6_dst); -- -+ return err; -+ } -+#ifdef CONFIG_IPV6_SUBTREES -+ reroute = (fl.fl6_src == NULL); -+#endif - /* get the source adddress used in the apropriate device */ - - err = ipv6_get_saddr(dst, daddr, &saddr); - -+ if (reroute) -+ dst_release(dst); -+ - if (err == 0) { -- if(ipv6_addr_any(&np->saddr)) -+#ifdef CONFIG_IPV6_SUBTREES -+ if (reroute) { -+ fl.fl6_src = &saddr; -+ dst = ip6_route_output(sk, &fl); -+ if ((err = dst->error) != 0) { -+ dst_release(dst); -+ fl6_sock_release(flowlabel); -+ return err; -+ } -+ } -+#endif -+ if(ipv6_addr_any(&np->saddr)) { - ipv6_addr_copy(&np->saddr, &saddr); -- -+ fl.fl6_src = &np->saddr; -+ } - if(ipv6_addr_any(&np->rcv_saddr)) { - ipv6_addr_copy(&np->rcv_saddr, &saddr); - sk->rcv_saddr = LOOPBACK4_IPV6; - } -+ ip6_dst_store(sk, dst, fl.fl6_dst, -+ fl.fl6_src == &np->saddr ? fl.fl6_src : NULL); - sk->state = TCP_ESTABLISHED; - } - fl6_sock_release(flowlabel); -@@ -894,6 +911,7 @@ static int udpv6_sendmsg(struct sock *sk - opt = fl6_merge_options(&opt_space, flowlabel, opt); - if (opt && opt->srcrt) - udh.daddr = daddr; -+ udh.daddr = mipv6_get_fake_hdr_daddr(udh.daddr, daddr); - - udh.uh.source = sk->sport; - udh.uh.len = len < 0x10000 ? htons(len) : 0; -diff -uprN linux-2.4.25.old/net/netsyms.c linux-2.4.25/net/netsyms.c ---- linux-2.4.25.old/net/netsyms.c 2003-11-28 18:26:21.000000000 +0000 -+++ linux-2.4.25/net/netsyms.c 2004-06-26 11:29:32.000000000 +0100 -@@ -190,6 +190,7 @@ EXPORT_SYMBOL(neigh_sysctl_register); - #endif - EXPORT_SYMBOL(pneigh_lookup); - EXPORT_SYMBOL(pneigh_enqueue); -+EXPORT_SYMBOL(pneigh_delete); - EXPORT_SYMBOL(neigh_destroy); - EXPORT_SYMBOL(neigh_parms_alloc); - EXPORT_SYMBOL(neigh_parms_release); diff --git a/linux/gumstix-2.6.5-gnalm1-gum0/defconfig b/linux/gumstix-2.6.5-gnalm1-gum0/defconfig deleted file mode 100644 index 64020e2cbe..0000000000 --- a/linux/gumstix-2.6.5-gnalm1-gum0/defconfig +++ /dev/null @@ -1,777 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_ARM=y -CONFIG_MMU=y -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y -CONFIG_BROKEN_ON_SMP=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_HOTPLUG is not set -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# System Type -# -# CONFIG_ARCH_ADIFCC is not set -# CONFIG_ARCH_ANAKIN is not set -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -CONFIG_ARCH_PXA=y -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP3XX is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_SHARK is not set - -# -# CLPS711X/EP721X Implementations -# - -# -# Epxa10db -# - -# -# Footbridge Implementations -# - -# -# IOP3xx Implementation Options -# -# CONFIG_ARCH_IOP310 is not set -# CONFIG_ARCH_IOP321 is not set - -# -# IOP3xx Chipset Features -# - -# -# Intel PXA250/210 Implementations -# -CONFIG_ARCH_GUMSTIK=y -# CONFIG_ARCH_LUBBOCK is not set -# CONFIG_ARCH_PXA_IDP is not set - -# -# SA11x0 Implementations -# - -# -# Processor Type -# -CONFIG_CPU_32=y -CONFIG_CPU_XSCALE=y -CONFIG_CPU_32v5=y -CONFIG_CPU_ABRT_EV5T=y -CONFIG_CPU_TLB_V4WBI=y -CONFIG_CPU_MINICACHE=y - -# -# Processor Features -# -# CONFIG_ARM_THUMB is not set -CONFIG_XSCALE_PMU=y - -# -# General setup -# -# CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CPU_FREQ=y - -# -# At least one math emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set -CONFIG_FPE_FASTFPE=y -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_AOUT=y -# CONFIG_BINFMT_MISC is not set - -# -# Generic Driver Options -# -CONFIG_PM=y -# CONFIG_PREEMPT is not set -# CONFIG_APM is not set -# CONFIG_ARTHUR is not set -CONFIG_CMDLINE="root=/dev/ram0 console=tty0,115200n8" -CONFIG_ALIGNMENT_TRAP=y - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_CONCAT=y -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set - -# -# Mapping drivers for chip access -# -CONFIG_MTD_COMPLEX_MAPPINGS=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x00180000 -CONFIG_MTD_PHYSMAP_LEN=0x00280000 -CONFIG_MTD_PHYSMAP_BUSWIDTH=2 -CONFIG_MTD_GUMSTIK=y -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_EDB7312 is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -CONFIG_MTD_BLKMTD=y - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=36000 -CONFIG_BLK_DEV_INITRD=y - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_PACKET is not set -# CONFIG_NETLINK_DEV is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -CONFIG_MII=y - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# -CONFIG_PPP=y -# CONFIG_PPP_MULTILINK is not set -# CONFIG_PPP_FILTER is not set -# CONFIG_PPP_ASYNC is not set -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPPOE is not set -CONFIG_SLIP=y -# CONFIG_SLIP_COMPRESSED is not set -# CONFIG_SLIP_SMART is not set -# CONFIG_SLIP_MODE_SLIP6 is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -CONFIG_BT=y -CONFIG_BT_L2CAP=y -CONFIG_BT_SCO=y -CONFIG_BT_RFCOMM=y -CONFIG_BT_RFCOMM_TTY=y -CONFIG_BT_BNEP=y -# CONFIG_BT_BNEP_MC_FILTER is not set -# CONFIG_BT_BNEP_PROTO_FILTER is not set - -# -# Bluetooth device drivers -# -CONFIG_BT_HCIUART=y -CONFIG_BT_HCIUART_H4=y -# CONFIG_BT_HCIUART_BCSP is not set -# CONFIG_BT_HCIVHCI is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_TSLIBDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set -# CONFIG_SERIO_I8042 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_PXA=y -CONFIG_SERIAL_PXA_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set -CONFIG_SA1100_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set - -# -# I2C support -# -CONFIG_I2C=y -CONFIG_I2C_CHARDEV=y - -# -# I2C Algorithms -# -CONFIG_I2C_ALGOBIT=y -# CONFIG_I2C_ALGOPCF is not set -CONFIG_I2C_ALGOPXA=y - -# -# I2C Hardware Bus support -# -# CONFIG_I2C_AMD756 is not set -# CONFIG_I2C_AMD8111 is not set -# CONFIG_I2C_ISA is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -CONFIG_I2C_PXA2XX=y -# CONFIG_SCx200_ACB is not set - -# -# Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ASB100 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_FSCHER is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_VIA686A is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83627HF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_EEPROM is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# MMC/SD Card support -# -CONFIG_MMC=y -# CONFIG_MMC_DEBUG is not set -CONFIG_MMC_BLOCK=y -CONFIG_MMC_PXA=y - -# -# File systems -# -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -# CONFIG_EXT2_FS_POSIX_ACL is not set -# CONFIG_EXT2_FS_SECURITY is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS_XATTR=y -# CONFIG_DEVPTS_FS_SECURITY is not set -CONFIG_TMPFS=y -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -CONFIG_CRAMFS=y -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set -CONFIG_LOCKD=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -CONFIG_LDM_PARTITION=y -# CONFIG_LDM_DEBUG is not set -# CONFIG_NEC98_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_EFI_PARTITION is not set - -# -# Native Language Support -# -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -CONFIG_NLS_ISO8859_1=y -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Profiling support -# -# CONFIG_PROFILING is not set - -# -# Graphics support -# -# CONFIG_FB is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Misc devices -# - -# -# Multimedia Capabilities Port drivers -# -# CONFIG_MCP is not set - -# -# Console Switches -# -# CONFIG_SWITCHES is not set - -# -# USB support -# - -# -# USB Gadget Support -# -CONFIG_USB_GADGET=y -# CONFIG_USB_GADGET_NET2280 is not set -CONFIG_USB_GADGET_PXA2XX=y -CONFIG_USB_PXA2XX=y -CONFIG_USB_PXA2XX_SMALL=y -# CONFIG_USB_GADGET_GOKU is not set -# CONFIG_USB_GADGET_SA1100 is not set -# CONFIG_USB_GADGET_DUALSPEED is not set -# CONFIG_USB_ZERO is not set -CONFIG_USB_ETH=y -# CONFIG_USB_GADGETFS is not set -# CONFIG_USB_FILE_STORAGE is not set -# CONFIG_USB_G_SERIAL is not set - -# -# Kernel hacking -# -CONFIG_FRAME_POINTER=y -# CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -CONFIG_CRC32=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/linux/gumstix-2.6.5-gnalm1-gum0/linux-2.6.5-gnalm1.patch b/linux/gumstix-2.6.5-gnalm1-gum0/linux-2.6.5-gnalm1.patch deleted file mode 100644 index e8ed5c9d44..0000000000 --- a/linux/gumstix-2.6.5-gnalm1-gum0/linux-2.6.5-gnalm1.patch +++ /dev/null @@ -1,20991 +0,0 @@ ---- linux-2.6.5/kernel/printk.c~heh 2004-04-03 22:38:24.000000000 -0500 -+++ linux-2.6.5/kernel/printk.c 2004-04-30 20:57:36.000000000 -0400 -@@ -832,3 +832,25 @@ - printk_ratelimit_burst); - } - EXPORT_SYMBOL(printk_ratelimit); -+ -+#include -+ -+static void -+show_msg_info(int key, struct pt_regs *regs, struct tty_struct *tty) -+{ -+ call_console_drivers(log_end - logged_chars, log_end); -+} -+ -+static struct sysrq_key_op msg_info_op = { -+ .handler = show_msg_info, -+ .help_msg = "Dumpmsgs", -+ .action_msg = "Kernel Messages", -+}; -+ -+static int __init dbg_init(void) -+{ -+ register_sysrq_key('d', &msg_info_op); -+ return 0; -+} -+ -+__initcall(dbg_init); ---- linux-2.6.5/kernel/resource.c~heh 2004-04-03 22:37:36.000000000 -0500 -+++ linux-2.6.5/kernel/resource.c 2004-04-30 20:57:36.000000000 -0400 -@@ -179,6 +179,8 @@ - { - struct resource *tmp, **p; - -+ BUG_ON(old->child); -+ - p = &old->parent->child; - for (;;) { - tmp = *p; -@@ -409,6 +411,47 @@ - EXPORT_SYMBOL(adjust_resource); - - /* -+ * Given an existing resource, change its start and size to match the -+ * arguments. Returns -EBUSY if it can't fit. Existing children of -+ * the resource are assumed to be immutable. -+ */ -+int reallocate_resource(struct resource *res, unsigned long start, unsigned long size) -+{ -+ struct resource *tmp, *parent = res->parent; -+ unsigned long end = start + size - 1; -+ int result = -EBUSY; -+ -+ write_lock(&resource_lock); -+ -+ if ((start < parent->start) || (end > parent->end)) -+ goto out; -+ -+ for (tmp = res->child; tmp; tmp = tmp->sibling) { -+ if ((tmp->start < start) || (tmp->end > end)) -+ goto out; -+ } -+ -+ if (res->sibling && (res->sibling->start <= end)) -+ goto out; -+ -+ tmp = parent->child; -+ if (tmp != res) { -+ while (tmp->sibling != res) -+ tmp = tmp->sibling; -+ if (start <= tmp->end) -+ goto out; -+ } -+ -+ res->start = start; -+ res->end = end; -+ result = 0; -+ -+ out: -+ write_unlock(&resource_lock); -+ return result; -+} -+ -+/* - * This is compatibility stuff for IO resources. - * - * Note how this, unlike the above, knows about ---- linux-2.6.5/include/asm-arm/mach/irq.h~heh 2004-04-03 22:36:54.000000000 -0500 -+++ linux-2.6.5/include/asm-arm/mach/irq.h 2004-04-30 20:57:36.000000000 -0400 -@@ -14,6 +14,19 @@ - struct pt_regs; - struct seq_file; - -+/* -+ * Architectures are expected to define NR_IRQ_DEVICES and -+ * NR_IRQ_DEVICE_SHIFT if they wish to use dynamic IRQs. -+ */ -+#ifndef NR_IRQ_DEVICES -+#define NR_IRQ_DEVICES 1 -+#endif -+#define NR_IRQ_PER_DEVICE (1 << (NR_IRQ_DEVICE_SHIFT - 1)) -+ -+#define IRQ_DEVICE(i) ((i) >> NR_IRQ_DEVICE_SHIFT) -+#define IRQ_INDEX(i) ((i) & (NR_IRQ_PER_GROUP - 1)) -+#define TO_IRQ(g,i) (((g) << NR_IRQ_DEVICE_SHIFT) + (i)) -+ - typedef void (*irq_handler_t)(unsigned int, struct irqdesc *, struct pt_regs *); - typedef void (*irq_control_t)(unsigned int); - ---- linux-2.6.5/include/asm-arm/arch-pxa/uncompress.h~heh 2004-04-03 22:36:17.000000000 -0500 -+++ linux-2.6.5/include/asm-arm/arch-pxa/uncompress.h 2004-04-30 20:57:36.000000000 -0400 -@@ -12,6 +12,7 @@ - #define FFUART ((volatile unsigned long *)0x40100000) - #define BTUART ((volatile unsigned long *)0x40200000) - #define STUART ((volatile unsigned long *)0x40700000) -+#define HWUART ((volatile unsigned long *)0x41600000) - - #define UART FFUART - ---- linux-2.6.5/include/asm-arm/arch-pxa/dma.h~heh 2004-04-03 22:38:18.000000000 -0500 -+++ linux-2.6.5/include/asm-arm/arch-pxa/dma.h 2004-04-30 20:57:36.000000000 -0400 -@@ -22,11 +22,11 @@ - * Note: this structure must always be aligned to a 16-byte boundary. - */ - --typedef struct { -- volatile u32 ddadr; /* Points to the next descriptor + flags */ -- volatile u32 dsadr; /* DSADR value for the current transfer */ -- volatile u32 dtadr; /* DTADR value for the current transfer */ -- volatile u32 dcmd; /* DCMD value for the current transfer */ -+typedef struct pxa_dma_desc { -+ u32 ddadr; /* Points to the next descriptor + flags */ -+ u32 dsadr; /* DSADR value for the current transfer */ -+ u32 dtadr; /* DTADR value for the current transfer */ -+ u32 dcmd; /* DCMD value for the current transfer */ - } pxa_dma_desc; - - /* ---- linux-2.6.5/include/asm-arm/arch-pxa/serial.h~heh 2004-04-03 22:37:06.000000000 -0500 -+++ linux-2.6.5/include/asm-arm/arch-pxa/serial.h 2004-04-30 20:57:36.000000000 -0400 -@@ -43,6 +43,15 @@ - io_type: SERIAL_IO_MEM, \ - irq: IRQ_BTUART, \ - flags: STD_COM_FLAGS, \ -+ }, { \ -+ type: PORT_PXA, \ -+ xmit_fifo_size: 64, \ -+ baud_base: BAUD_BASE, \ -+ iomem_base: &HWUART, \ -+ iomem_reg_shift: 2, \ -+ io_type: SERIAL_IO_MEM, \ -+ irq: IRQ_HWUART, \ -+ flags: STD_COM_FLAGS, \ - } - - #define EXTRA_SERIAL_PORT_DEFNS ---- linux-2.6.5/include/asm-arm/arch-pxa/pxa-regs.h~heh 2004-04-03 22:37:36.000000000 -0500 -+++ linux-2.6.5/include/asm-arm/arch-pxa/pxa-regs.h 2004-04-30 20:57:36.000000000 -0400 -@@ -124,26 +124,26 @@ - #define DRCMR12 __REG(0x40000130) /* Request to Channel Map Register for AC97 audio transmit Request */ - #define DRCMR13 __REG(0x40000134) /* Request to Channel Map Register for SSP receive Request */ - #define DRCMR14 __REG(0x40000138) /* Request to Channel Map Register for SSP transmit Request */ --#define DRCMR15 __REG(0x4000013c) /* Reserved */ --#define DRCMR16 __REG(0x40000140) /* Reserved */ -+#define DRCMR15 __REG(0x4000013c) /* Request to Channel Map Register for NSSP receive Request */ -+#define DRCMR16 __REG(0x40000140) /* Request to Channel Map Register for NSSP transmit Request */ - #define DRCMR17 __REG(0x40000144) /* Request to Channel Map Register for ICP receive Request */ - #define DRCMR18 __REG(0x40000148) /* Request to Channel Map Register for ICP transmit Request */ - #define DRCMR19 __REG(0x4000014c) /* Request to Channel Map Register for STUART receive Request */ - #define DRCMR20 __REG(0x40000150) /* Request to Channel Map Register for STUART transmit Request */ - #define DRCMR21 __REG(0x40000154) /* Request to Channel Map Register for MMC receive Request */ - #define DRCMR22 __REG(0x40000158) /* Request to Channel Map Register for MMC transmit Request */ --#define DRCMR23 __REG(0x4000015c) /* Reserved */ --#define DRCMR24 __REG(0x40000160) /* Reserved */ -+#define DRCMR23 __REG(0x4000015c) /* Request to Channel Map Register for ASSP receive Request */ -+#define DRCMR24 __REG(0x40000160) /* Request to Channel Map Register for ASSP transmit Request */ - #define DRCMR25 __REG(0x40000164) /* Request to Channel Map Register for USB endpoint 1 Request */ - #define DRCMR26 __REG(0x40000168) /* Request to Channel Map Register for USB endpoint 2 Request */ - #define DRCMR27 __REG(0x4000016C) /* Request to Channel Map Register for USB endpoint 3 Request */ - #define DRCMR28 __REG(0x40000170) /* Request to Channel Map Register for USB endpoint 4 Request */ --#define DRCMR29 __REG(0x40000174) /* Reserved */ -+#define DRCMR29 __REG(0x40000174) /* Request to Channel Map Register for HWUART receive Request */ - #define DRCMR30 __REG(0x40000178) /* Request to Channel Map Register for USB endpoint 6 Request */ - #define DRCMR31 __REG(0x4000017C) /* Request to Channel Map Register for USB endpoint 7 Request */ - #define DRCMR32 __REG(0x40000180) /* Request to Channel Map Register for USB endpoint 8 Request */ - #define DRCMR33 __REG(0x40000184) /* Request to Channel Map Register for USB endpoint 9 Request */ --#define DRCMR34 __REG(0x40000188) /* Reserved */ -+#define DRCMR34 __REG(0x40000188) /* Request to Channel Map Register for HWUART transmit Request */ - #define DRCMR35 __REG(0x4000018C) /* Request to Channel Map Register for USB endpoint 11 Request */ - #define DRCMR36 __REG(0x40000190) /* Request to Channel Map Register for USB endpoint 12 Request */ - #define DRCMR37 __REG(0x40000194) /* Request to Channel Map Register for USB endpoint 13 Request */ -@@ -163,12 +163,16 @@ - #define DRCMRTXPCDR DRCMR12 - #define DRCMRRXSSDR DRCMR13 - #define DRCMRTXSSDR DRCMR14 -+#define DRCMRRXNSSPDR DRCMR15 -+#define DRCMRTXNSSPDR DRCMR16 - #define DRCMRRXICDR DRCMR17 - #define DRCMRTXICDR DRCMR18 - #define DRCMRRXSTRBR DRCMR19 - #define DRCMRTXSTTHR DRCMR20 - #define DRCMRRXMMC DRCMR21 - #define DRCMRTXMMC DRCMR22 -+#define DRCMRRXASSPDR DRCMR23 -+#define DRCMRTXASSPDR DRCMR24 - - #define DRCMR_MAPVLD (1 << 7) /* Map Valid (read / write) */ - #define DRCMR_CHLNUM 0x0f /* mask for Channel Number (read / write) */ -@@ -303,6 +307,22 @@ - #define BTDLL __REG(0x40200000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */ - #define BTDLH __REG(0x40200004) /* Divisor Latch High Register (DLAB = 1) (read/write) */ - -+/* Hardware UART (HWUART) */ -+#define HWUART HWRBR -+#define HWRBR __REG(0x41600000) /* Receive Buffer Register (read only) */ -+#define HWTHR __REG(0x41600000) /* Transmit Holding Register (write only) */ -+#define HWIER __REG(0x41600004) /* Interrupt Enable Register (read/write) */ -+#define HWIIR __REG(0x41600008) /* Interrupt ID Register (read only) */ -+#define HWFCR __REG(0x41600008) /* FIFO Control Register (write only) */ -+#define HWLCR __REG(0x4160000C) /* Line Control Register (read/write) */ -+#define HWMCR __REG(0x41600010) /* Modem Control Register (read/write) */ -+#define HWLSR __REG(0x41600014) /* Line Status Register (read only) */ -+#define HWMSR __REG(0x41600018) /* Reserved */ -+#define HWSPR __REG(0x4160001C) /* Scratch Pad Register (read/write) */ -+#define HWISR __REG(0x41600020) /* Infrared Selection Register (read/write) */ -+#define HWDLL __REG(0x41600000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */ -+#define HWDLH __REG(0x41600004) /* Divisor Latch High Register (DLAB = 1) (read/write) */ -+ - /* Standard UART (STUART) */ - #define STUART STRBR - #define STRBR __REG(0x40700000) /* Receive Buffer Register (read only) */ -@@ -1078,6 +1098,111 @@ - - - /* -+ * NSSP Serial Port Registers (Network SSP) -+ */ -+ -+#define NSSCR0 __REG(0x41400000) /* NSSP Control Register 0 */ -+#define NSSCR1 __REG(0x41400004) /* NSSP Control Register 1 */ -+#define NSSSR __REG(0x41400008) /* NSSP Status Register */ -+#define NSSITR __REG(0x4140000C) /* NSSP Interrupt Test Register */ -+#define NSSDR __REG(0x41400010) /* (Write / Read) NSSP Data Write Register/NSSP Data Read Register */ -+#define NSSTO __REG(0x41400028) /* NSSP Time Out Register */ -+#define NSSPSP __REG(0x4140002C) /* NSSP Programable Serial Port Register*/ -+ -+ -+/* -+ * ASSP Serial Port Registers (Audio SSP) -+ */ -+ -+#define ASSCR0 __REG(0x41500000) /* ASSP Control Register 0 */ -+#define ASSCR1 __REG(0x41500004) /* ASSP Control Register 1 */ -+#define ASSSR __REG(0x41500008) /* ASSP Status Register */ -+#define ASSITR __REG(0x4150000C) /* ASSP Interrupt Test Register */ -+#define ASSDR __REG(0x41500010) /* (Write / Read) ASSP Data Write Register/ASSP Data Read Register */ -+#define ASSTO __REG(0x41500028) /* ASSP Time Out Register */ -+#define ASSPSP __REG(0x4150002C) /* ASSP Programable Serial Port Register*/ -+ -+ -+/* -+ * Bit definitions for SSP, NSSP and ASSP registers -+ * - note that some bits are only available on the NSSP and ASSP -+ */ -+ -+#define SSCR0_EDSS (1 << 20) /* ext. data size select */ -+#define SSCR0_SCR_MASK 0x000fff00 /* [19:8] secrial clock rate */ -+#define SSCR0_SCR(x) (((x)<<8) & XSSCR0_SCR_MASK) -+#define SSCR0_SSE (1 << 7) /* sync ser port enable */ -+#define SSCR0_FRF_MASK 0x00000030 /* [5:4] frame format */ -+#define SSCR0_FRF(x) (((x)<<4) & XSSCR0_FRF_MASK) -+#define SSCR0_FRF_SPI 0x00000000 /* ser peripheral i/f */ -+#define SSCR0_FRF_TISSP 0x00000010 /* TI sync ser port */ -+#define SSCR0_FRF_MICROWAVE 0x00000020 /* microwire */ -+#define SSCR0_FRF_PSP 0x00000030 /* prog ser protocol */ -+#define SSCR0_DSS_MASK 0x0000000f /* data size select */ -+#define SSCR0_DSS(x) ((x) & XSSCR0_DSS_MASK) -+ -+#define SSCR1_TTELP (1 << 31) /* tx hi-z later phase */ -+#define SSCR1_TTE (1 << 30) /* tx hi-z enable */ -+#define SSCR1_EBCEI (1 << 29) /* bit count error int mask */ -+#define SSCR1_SCFR (1 << 28) /* slave clock free running */ -+#define SSCR1_SCLKDIR (1 << 25) /* ssp clock direction */ -+#define SSCR1_SFRMDIR (1 << 24) /* ssp frame direction */ -+#define SSCR1_RWOT (1 << 23) /* rx without transmit */ -+#define SSCR1_TSRE (1 << 21) /* tx req enable */ -+#define SSCR1_RSRE (1 << 20) /* rx req enable */ -+#define SSCR1_TINTE (1 << 19) /* timeout int enable */ -+#define SSCR1_STRF (1 << 15) /* select fifo for efwr */ -+#define SSCR1_EFWR (1 << 14) /* fifo write/read enable */ -+#define SSCR1_RFT_MASK 0x00003c00 /* [13:10] rx fifo threshold */ -+#define SSCR1_RFT(x) (((x)<<10) & XSSCR1_RFT_MASK) -+#define SSCR1_TFT_MASK 0x000003c0 /* [9:6] tx fifo threshold */ -+#define SSCR1_TFT(x) (((x)<<6) & XSSCR1_TFT_MASK) -+#define SSCR1_MWDS (1 << 5) /* microwire tx data size */ -+#define SSCR1_SPH (1 << 4) /* SPI SSPSCLK phase */ -+#define SSCR1_SPO (1 << 3) /* motorolla SPI polarity */ -+#define SSCR1_LBM (1 << 2) /* loop-back mode */ -+#define SSCR1_TIE (1 << 1) /* tx fifo int enable */ -+#define SSCR1_RIE (1 << 0) /* rx fifo int enable */ -+ -+#define SSPSP_DMYSTOP_MASK 0x01800000 /* [24:23] dummy stop */ -+#define SSPSP_DMYSTOP(x) (((x)<<23) & XSSPSP_DMYSTOP_MASK) -+#define SSPSP_SFRMWDTH_MASK 0x007f0000 /* [22:16] serial frame width */ -+#define SSPSP_SFRMWDTH(x) (((x)<<16) & XSSPSP_SFRMWDTH_MASK) -+#define SSPSP_SFRMDLY_MASK 0x0000fe00 /* [15:9] serial frame delay */ -+#define SSPSP_SFRMDLY(x) (((x)<<9) & XSSPSP_SFRMDLY_MASK) -+#define SSPSP_DMYSTRT_MASK 0x00000180 /* [8:7] dummy start */ -+#define SSPSP_DMYSTRT(x) (((x)<<7) & XSSPSP_DMYSTRT_MASK) -+#define SSPSP_STRTDLY_MASK 0x00000070 /* [6:4] three-bit start delay */ -+#define SSPSP_STRTDLY(x) (((x)<<4) & XSSPSP_STRTDLY_MASK) -+#define SSPSP_ETDS (1 << 3) /* end of tx data state */ -+#define SSPSP_SFRMP (1 << 2) /* serial frame polarity */ -+#define SSPSP_SCMODE_MASK 0x00000003 /* bit-rate clock mode */ -+#define SSPSP_SCMODE(x) ((x) & XSSPSP_SCMODE_MASK) -+ -+#define SSTO_TIMEOUT_MASK 0x00ffffff /* [23:0] timeout */ -+#define SSTO_TIMEOUT(x) ((x) & XSSTO_TIMEOUT_MASK) -+ -+#define SSITR_TROR (1 << 7) /* test rx fifo overrun */ -+#define SSITR_TRFS (1 << 6) /* test rx fifo serv req */ -+#define SSITR_TTFS (1 << 5) /* test tx fifo serv req */ -+ -+#define SSSR_BCE (1 << 23) /* bit count error */ -+#define SSSR_CSS (1 << 22) /* clock sync stat */ -+#define SSSR_TUR (1 << 21) /* tx fifo underrun */ -+#define SSSR_TINT (1 << 19) /* rx timeout int */ -+#define SSSR_RFL_MASK 0x0000f000 /* rx fifo level */ -+#define SSSR_RFL(x) (((x)<<16) & XSSSR_RFL_MASK) -+#define SSSR_TFL_MASK 0x00000f00 /* tx fifo level */ -+#define SSSR_TFL(x) (((x)<<8) & XSSSR_TFL_MASK) -+#define SSSR_ROR (1 << 7) /* rx fifo overrun */ -+#define SSSR_RFS (1 << 6) /* rx fifo serv request */ -+#define SSSR_TFS (1 << 5) /* tx fifo serv req */ -+#define SSSR_BSY (1 << 4) /* SSP busy */ -+#define SSSR_RNE (1 << 3) /* rx fifo not empty */ -+#define SSSR_TNF (1 << 2) /* tx fifo not full */ -+ -+ -+/* - * MultiMediaCard (MMC) controller - */ - -@@ -1122,6 +1247,7 @@ - #define CKEN7_BTUART (1 << 7) /* BTUART Unit Clock Enable */ - #define CKEN6_FFUART (1 << 6) /* FFUART Unit Clock Enable */ - #define CKEN5_STUART (1 << 5) /* STUART Unit Clock Enable */ -+#define CKEN4_HWUART (1 << 4) /* HWUART Unit Clock Enable */ - #define CKEN3_SSP (1 << 3) /* SSP Unit Clock Enable */ - #define CKEN2_AC97 (1 << 2) /* AC97 Unit Clock Enable */ - #define CKEN1_PWM1 (1 << 1) /* PWM1 Clock Enable */ ---- linux-2.6.5/include/asm-arm/page.h~heh 2004-04-03 22:36:25.000000000 -0500 -+++ linux-2.6.5/include/asm-arm/page.h 2004-04-30 20:57:36.000000000 -0400 -@@ -92,6 +92,14 @@ - # endif - #endif - -+#ifdef CONFIG_CPU_COPY_V6 -+# ifdef _USER -+# define MULTI_USER 1 -+# else -+# define _USER v6 -+# endif -+#endif -+ - #ifndef _USER - #error Unknown user operations model - #endif ---- linux-2.6.5/include/asm-arm/thread_info.h~heh 2004-04-03 22:37:06.000000000 -0500 -+++ linux-2.6.5/include/asm-arm/thread_info.h 2004-04-30 20:57:36.000000000 -0400 -@@ -108,8 +108,8 @@ - #define TI_CPU 20 - #define TI_CPU_DOMAIN 24 - #define TI_CPU_SAVE 28 --#define TI_USED_MATH 76 --#define TI_FPSTATE (TI_USED_MATH+16) -+#define TI_USED_CP 76 -+#define TI_FPSTATE (TI_USED_CP+16) - - #endif - ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/include/asm-arm/rtc.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,45 @@ -+/* -+ * linux/include/asm-arm/rtc.h -+ * -+ * Copyright (C) 2003 Deep Blue Solutions Ltd. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#ifndef ASMARM_RTC_H -+#define ASMARM_RTC_H -+ -+struct module; -+ -+struct rtc_ops { -+ struct module *owner; -+ int (*open)(void); -+ void (*release)(void); -+ int (*ioctl)(unsigned int, unsigned long); -+ -+ void (*read_time)(struct rtc_time *); -+ int (*set_time)(struct rtc_time *); -+ void (*read_alarm)(struct rtc_wkalrm *); -+ int (*set_alarm)(struct rtc_wkalrm *); -+ int (*proc)(char *buf); -+}; -+ -+void rtc_time_to_tm(unsigned long, struct rtc_time *); -+int rtc_tm_to_time(struct rtc_time *, unsigned long *); -+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 *); -+void unregister_rtc(struct rtc_ops *); -+ -+static inline int rtc_periodic_alarm(struct rtc_time *tm) -+{ -+ return (tm->tm_year == -1) || -+ ((unsigned)tm->tm_mon >= 12) || -+ ((unsigned)(tm->tm_mday - 1) >= 31) || -+ ((unsigned)tm->tm_hour > 23) || -+ ((unsigned)tm->tm_min > 59) || -+ ((unsigned)tm->tm_sec > 59); -+} -+ -+#endif ---- linux-2.6.5/include/linux/serial.h~heh 2004-04-03 22:36:26.000000000 -0500 -+++ linux-2.6.5/include/linux/serial.h 2004-04-30 20:57:36.000000000 -0400 -@@ -81,17 +81,6 @@ - #define SERIAL_IO_HUB6 1 - #define SERIAL_IO_MEM 2 - --struct serial_uart_config { -- char *name; -- int dfl_xmit_fifo_size; -- int flags; --}; -- --#define UART_CLEAR_FIFO 0x01 --#define UART_USE_FIFO 0x02 --#define UART_STARTECH 0x04 --#define UART_NATSEMI 0x08 -- - /* - * Definitions for async_struct (and serial_struct) flags field - */ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/include/linux/i2c-pxa.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,76 @@ -+/* -+ * i2c_pxa.h -+ * -+ * Copyright (C) 2002 Intrinsyc Software Inc. -+ * -+ * 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 _I2C_PXA_H_ -+#define _I2C_PXA_H_ -+ -+struct i2c_algo_pxa_data -+{ -+ void (*write_byte) (u8 value); -+ u8 (*read_byte) (void); -+ void (*start) (void); -+ void (*repeat_start) (void); -+ void (*stop) (void); -+ void (*abort) (void); -+ int (*wait_bus_not_busy) (void); -+ int (*wait_for_interrupt) (int wait_type); -+ void (*transfer) (int lastbyte, int receive, int midbyte); -+ void (*reset) (void); -+ -+ int udelay; -+ int timeout; -+}; -+ -+#define DEF_TIMEOUT 3 -+#define BUS_ERROR (-EREMOTEIO) -+#define ACK_DELAY 0 /* time to delay before checking bus error */ -+#define MAX_MESSAGES 65536 /* maximum number of messages to send */ -+ -+#define I2C_SLEEP_TIMEOUT 2 /* time to sleep for on i2c transactions */ -+#define I2C_RETRY (-2000) /* an error has occurred retry transmit */ -+#define I2C_TRANSMIT 1 -+#define I2C_RECEIVE 0 -+#define I2C_PXA_SLAVE_ADDR 0x1 /* slave pxa unit address */ -+#define I2C_ICR_INIT (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE) /* ICR initialization value */ -+/* ICR initialize bit values -+* -+* 15. FM 0 (100 Khz operation) -+* 14. UR 0 (No unit reset) -+* 13. SADIE 0 (Disables the unit from interrupting on slave addresses -+* matching its slave address) -+* 12. ALDIE 0 (Disables the unit from interrupt when it loses arbitration -+* in master mode) -+* 11. SSDIE 0 (Disables interrupts from a slave stop detected, in slave mode) -+* 10. BEIE 1 (Enable interrupts from detected bus errors, no ACK sent) -+* 9. IRFIE 1 (Enable interrupts from full buffer received) -+* 8. ITEIE 1 (Enables the I2C unit to interrupt when transmit buffer empty) -+* 7. GCD 1 (Disables i2c unit response to general call messages as a slave) -+* 6. IUE 0 (Disable unit until we change settings) -+* 5. SCLE 1 (Enables the i2c clock output for master mode (drives SCL) -+* 4. MA 0 (Only send stop with the ICR stop bit) -+* 3. TB 0 (We are not transmitting a byte initially) -+* 2. ACKNAK 0 (Send an ACK after the unit receives a byte) -+* 1. STOP 0 (Do not send a STOP) -+* 0. START 0 (Do not send a START) -+* -+*/ -+ -+#define I2C_ISR_INIT 0x7FF /* status register init */ -+/* I2C status register init values -+ * -+ * 10. BED 1 (Clear bus error detected) -+ * 9. SAD 1 (Clear slave address detected) -+ * 7. IRF 1 (Clear IDBR Receive Full) -+ * 6. ITE 1 (Clear IDBR Transmit Empty) -+ * 5. ALD 1 (Clear Arbitration Loss Detected) -+ * 4. SSD 1 (Clear Slave Stop Detected) -+ */ -+ -+#endif ---- linux-2.6.5/include/linux/ioport.h~heh 2004-04-03 22:36:26.000000000 -0500 -+++ linux-2.6.5/include/linux/ioport.h 2004-04-30 20:57:36.000000000 -0400 -@@ -99,6 +99,7 @@ - void (*alignf)(void *, struct resource *, - unsigned long, unsigned long), - void *alignf_data); -+extern int reallocate_resource(struct resource *res, unsigned long start, unsigned long size); - int adjust_resource(struct resource *res, unsigned long start, - unsigned long size); - ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/include/linux/switches.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,74 @@ -+/* -+ * linux/include/linux/switches.h -+ * -+ * Copyright (C) 2000 John Dorsey -+ * -+ * 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. -+ * -+ * 23 October 2000 - created. -+ */ -+ -+#if !defined(_LINUX_SWITCHES_H) -+#define _LINUX_SWITCHES_H -+ -+#define SWITCHES_MASK_SIZE (128) -+ -+typedef unsigned long switches_bitfield; -+ -+#define SWITCHES_BITS (sizeof(switches_bitfield) * 8) -+#define SWITCHES_NUM_FIELDS (SWITCHES_MASK_SIZE / SWITCHES_BITS) -+#define SWITCHES_FIELD_SELECT(i) ((i) / SWITCHES_BITS) -+#define SWITCHES_FIELD_MASK(i) ((switches_bitfield)(1 << (i) % \ -+ SWITCHES_BITS)) -+ -+typedef struct switches_mask_t { -+ unsigned int count; -+ switches_bitfield events[SWITCHES_NUM_FIELDS]; -+ switches_bitfield states[SWITCHES_NUM_FIELDS]; -+} switches_mask_t; -+ -+#define SWITCHES_ZERO(m) \ -+do { \ -+ unsigned int sz_i; \ -+ (m)->count = 0; \ -+ for(sz_i = 0; sz_i < SWITCHES_NUM_FIELDS; ++sz_i) \ -+ (m)->events[sz_i] = (m)->states[sz_i] = 0; \ -+} while (0) -+ -+/* `s' is the state of the switch, either 0 or non-zero: */ -+#define SWITCHES_SET(m, i, s) \ -+do { \ -+ ((m)->events[SWITCHES_FIELD_SELECT((i))] |= \ -+ SWITCHES_FIELD_MASK((i))); \ -+ if(s) \ -+ ((m)->states[SWITCHES_FIELD_SELECT((i))] |= \ -+ SWITCHES_FIELD_MASK((i))); \ -+ else \ -+ ((m)->states[SWITCHES_FIELD_SELECT((i))] &= \ -+ ~SWITCHES_FIELD_MASK((i))); \ -+ ++((m)->count); \ -+} while (0) -+ -+/* Should only use to clear an event set by SWITCHES_SET(): */ -+#define SWITCHES_CLEAR(m, i) \ -+do { \ -+ ((m)->events[SWITCHES_FIELD_SELECT((i))] &= \ -+ ~SWITCHES_FIELD_MASK((i))); \ -+ ((m)->states[SWITCHES_FIELD_SELECT((i))] &= \ -+ ~SWITCHES_FIELD_MASK((i))); \ -+ --((m)->count); \ -+} -+ -+#define SWITCHES_COUNT(m) ((m)->count) -+ -+/* Returns 0 or non-zero: */ -+#define SWITCHES_EVENT(m, i) \ -+((m)->events[SWITCHES_FIELD_SELECT((i))] & SWITCHES_FIELD_MASK((i))) -+ -+/* Returns 0 or non-zero: */ -+#define SWITCHES_STATE(m, i) \ -+((m)->states[SWITCHES_FIELD_SELECT((i))] & SWITCHES_FIELD_MASK((i))) -+ -+#endif /* !defined(_LINUX_SWITCHES_H) */ ---- linux-2.6.5/include/linux/serial_reg.h~heh 2004-04-03 22:37:38.000000000 -0500 -+++ linux-2.6.5/include/linux/serial_reg.h 2004-04-30 20:57:36.000000000 -0400 -@@ -121,6 +121,7 @@ - /* - * These are the definitions for the Modem Control Register - */ -+#define UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS (TI16C750) */ - #define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ - #define UART_MCR_OUT2 0x08 /* Out2 complement */ - #define UART_MCR_OUT1 0x04 /* Out1 complement */ -@@ -156,6 +157,21 @@ - #define UART_FCR_PXAR32 0xc0 /* receive FIFO treshold = 32 */ - - /* -+ * The Intel PXA2xx chip defines those bits -+ */ -+#define UART_IER_DMAE 0x80 /* DMA Requests Enable */ -+#define UART_IER_UUE 0x40 /* UART Unit Enable */ -+#define UART_IER_NRZE 0x20 /* NRZ coding Enable */ -+#define UART_IER_RTOIE 0x10 /* Receiver Time Out Interrupt Enable */ -+ -+#define UART_IIR_TOD 0x08 /* Character Timeout Indication Detected */ -+ -+#define UART_FCR_PXAR1 0x00 /* receive FIFO treshold = 1 */ -+#define UART_FCR_PXAR8 0x40 /* receive FIFO treshold = 8 */ -+#define UART_FCR_PXAR16 0x80 /* receive FIFO treshold = 16 */ -+#define UART_FCR_PXAR32 0xc0 /* receive FIFO treshold = 32 */ -+ -+/* - * These are the definitions for the Extended Features Register - * (StarTech 16C660 only, when DLAB=1) - */ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/include/linux/mmc/card.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,83 @@ -+/* -+ * linux/include/linux/mmc/card.h -+ * -+ * 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. -+ * -+ * Card driver specific definitions. -+ */ -+#ifndef LINUX_MMC_CARD_H -+#define LINUX_MMC_CARD_H -+ -+#include -+ -+struct mmc_cid { -+ unsigned int manfid; -+ unsigned int serial; -+ char prod_name[8]; -+ unsigned char hwrev; -+ unsigned char fwrev; -+ unsigned char month; -+ unsigned char year; -+}; -+ -+struct mmc_csd { -+ unsigned char mmc_prot; -+ unsigned short cmdclass; -+ unsigned short tacc_clks; -+ unsigned int tacc_ns; -+ unsigned int max_dtr; -+ unsigned int read_blkbits; -+ unsigned int capacity; -+}; -+ -+struct mmc_host; -+ -+/* -+ * MMC device -+ */ -+struct mmc_card { -+ struct list_head node; /* node in hosts devices list */ -+ struct mmc_host *host; /* the host this device belongs to */ -+ struct device dev; /* the device */ -+ unsigned int rca; /* relative card address of device */ -+ unsigned int state; /* (our) card state */ -+#define MMC_STATE_PRESENT (1<<0) -+#define MMC_STATE_DEAD (1<<1) -+ struct mmc_cid cid; /* card identification */ -+ struct mmc_csd csd; /* card specific */ -+}; -+ -+#define mmc_card_dead(c) ((c)->state & MMC_STATE_DEAD) -+#define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT) -+ -+#define mmc_card_name(c) ((c)->cid.prod_name) -+#define mmc_card_id(c) ((c)->dev.bus_id) -+ -+#define mmc_list_to_card(l) container_of(l, struct mmc_card, node) -+#define mmc_get_drvdata(c) dev_get_drvdata(&(c)->dev) -+#define mmc_set_drvdata(c,d) dev_set_drvdata(&(c)->dev, d) -+ -+/* -+ * MMC device driver (e.g., Flash card, I/O card...) -+ */ -+struct mmc_driver { -+ struct device_driver drv; -+ int (*probe)(struct mmc_card *); -+ void (*remove)(struct mmc_card *); -+ int (*suspend)(struct mmc_card *, u32); -+ int (*resume)(struct mmc_card *); -+}; -+ -+extern int mmc_register_driver(struct mmc_driver *); -+extern void mmc_unregister_driver(struct mmc_driver *); -+ -+static inline int mmc_card_claim_host(struct mmc_card *card) -+{ -+ return __mmc_claim_host(card->host, card); -+} -+ -+#define mmc_card_release_host(c) mmc_release_host((c)->host) -+ -+#endif ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/include/linux/mmc/mmc.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,88 @@ -+/* -+ * linux/include/linux/mmc/mmc.h -+ * -+ * 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 MMC_H -+#define MMC_H -+ -+#include -+#include -+#include -+ -+struct request; -+struct mmc_data; -+struct mmc_request; -+ -+struct mmc_command { -+ u32 opcode; -+ u32 arg; -+ u32 resp[4]; -+ unsigned int flags; /* expected response type */ -+#define MMC_RSP_NONE (0 << 0) -+#define MMC_RSP_SHORT (1 << 0) -+#define MMC_RSP_LONG (2 << 0) -+#define MMC_RSP_MASK (3 << 0) -+#define MMC_RSP_CRC (1 << 3) /* expect valid crc */ -+#define MMC_RSP_BUSY (1 << 4) /* card may send busy */ -+ -+ unsigned int retries; /* max number of retries */ -+ unsigned int error; /* command error */ -+ -+#define MMC_ERR_NONE 0 -+#define MMC_ERR_TIMEOUT 1 -+#define MMC_ERR_BADCRC 2 -+#define MMC_ERR_FIFO 3 -+#define MMC_ERR_FAILED 4 -+#define MMC_ERR_INVALID 5 -+ -+ struct mmc_data *data; /* data segment associated with cmd */ -+ struct mmc_request *req; /* assoicated request */ -+}; -+ -+struct mmc_data { -+ unsigned int timeout_ns; /* data timeout (in ns, max 80ms) */ -+ unsigned int timeout_clks; /* data timeout (in clocks) */ -+ unsigned int blksz_bits; /* data block size */ -+ unsigned int blocks; /* number of blocks */ -+ struct request *rq; /* request structure */ -+ unsigned int error; /* data error */ -+ unsigned int flags; -+ -+#define MMC_DATA_WRITE (1 << 8) -+#define MMC_DATA_READ (1 << 9) -+#define MMC_DATA_STREAM (1 << 10) -+ -+ unsigned int bytes_xfered; -+ -+ struct mmc_command *stop; /* stop command */ -+ struct mmc_request *req; /* assoicated request */ -+}; -+ -+struct mmc_request { -+ struct mmc_command *cmd; -+ struct mmc_data *data; -+ struct mmc_command *stop; -+ -+ void *done_data; /* completion data */ -+ void (*done)(struct mmc_request *);/* completion function */ -+}; -+ -+struct mmc_host; -+struct mmc_card; -+ -+extern int mmc_wait_for_req(struct mmc_host *, struct mmc_request *); -+extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int); -+ -+extern int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card); -+ -+static inline void mmc_claim_host(struct mmc_host *host) -+{ -+ __mmc_claim_host(host, (struct mmc_card *)-1); -+} -+ -+extern void mmc_release_host(struct mmc_host *host); -+ -+#endif ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/include/linux/mmc/host.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,67 @@ -+/* -+ * linux/include/linux/mmc/host.h -+ * -+ * 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. -+ * -+ * Host driver specific definitions. -+ */ -+#ifndef LINUX_MMC_HOST_H -+#define LINUX_MMC_HOST_H -+ -+#include -+ -+struct mmc_ios { -+ unsigned int clock; /* clock rate */ -+ unsigned short vdd; /* supply (units of 10mV) */ -+ unsigned char bus_mode; /* command output mode */ -+ -+#define MMC_BUSMODE_OPENDRAIN 1 -+#define MMC_BUSMODE_PUSHPULL 2 -+ -+ unsigned char power_mode; /* power supply mode */ -+ -+#define MMC_POWER_OFF 0 -+#define MMC_POWER_UP 1 -+#define MMC_POWER_ON 2 -+}; -+ -+struct mmc_host_ops { -+ void (*request)(struct mmc_host *host, struct mmc_request *req); -+ void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios); -+}; -+ -+struct mmc_card; -+ -+struct mmc_host { -+ struct device *dev; -+ struct mmc_host_ops *ops; -+ unsigned int f_min; -+ unsigned int f_max; -+ u32 ocr_avail; -+ -+ /* private data */ -+ unsigned int host_num; /* host number */ -+ struct mmc_ios ios; /* current io bus settings */ -+ u32 ocr; /* the current OCR setting */ -+ -+ struct list_head cards; /* devices attached to this host */ -+ -+ wait_queue_head_t wq; -+ spinlock_t lock; /* card_busy lock */ -+ struct mmc_card *card_busy; /* the MMC card claiming host */ -+ struct mmc_card *card_selected; /* the selected MMC card */ -+}; -+ -+extern int mmc_init_host(struct mmc_host *); -+extern int mmc_add_host(struct mmc_host *); -+extern void mmc_remove_host(struct mmc_host *); -+extern int mmc_suspend_host(struct mmc_host *, u32); -+extern int mmc_resume_host(struct mmc_host *); -+ -+extern void mmc_detect_change(struct mmc_host *); -+extern void mmc_request_done(struct mmc_host *, struct mmc_request *); -+ -+#endif -+ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/include/linux/mmc/protocol.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,203 @@ -+/* -+ * Header for MultiMediaCard (MMC) -+ * -+ * Copyright 2002 Hewlett-Packard Company -+ * -+ * Use consistent with the GNU GPL is permitted, -+ * provided that this copyright notice is -+ * preserved in its entirety in all copies and derived works. -+ * -+ * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, -+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS -+ * FITNESS FOR ANY PARTICULAR PURPOSE. -+ * -+ * Many thanks to Alessandro Rubini and Jonathan Corbet! -+ * -+ * Based strongly on code by: -+ * -+ * Author: Yong-iL Joh -+ * Date : $Date$ -+ * -+ * Author: Andrew Christian -+ * 15 May 2002 -+ */ -+ -+#ifndef MMC_MMC_PROTOCOL_H -+#define MMC_MMC_PROTOCOL_H -+ -+/* Standard MMC commands (3.1) type argument response */ -+ /* class 1 */ -+#define MMC_GO_IDLE_STATE 0 /* bc */ -+#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */ -+#define MMC_ALL_SEND_CID 2 /* bcr R2 */ -+#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */ -+#define MMC_SET_DSR 4 /* bc [31:16] RCA */ -+#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */ -+#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */ -+#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */ -+#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */ -+#define MMC_STOP_TRANSMISSION 12 /* ac R1b */ -+#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */ -+#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */ -+ -+ /* class 2 */ -+#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */ -+#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */ -+#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */ -+ -+ /* class 3 */ -+#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */ -+ -+ /* class 4 */ -+#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */ -+#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */ -+#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */ -+#define MMC_PROGRAM_CID 26 /* adtc R1 */ -+#define MMC_PROGRAM_CSD 27 /* adtc R1 */ -+ -+ /* class 6 */ -+#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */ -+#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */ -+#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */ -+ -+ /* class 5 */ -+#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */ -+#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */ -+#define MMC_ERASE 37 /* ac R1b */ -+ -+ /* class 9 */ -+#define MMC_FAST_IO 39 /* ac R4 */ -+#define MMC_GO_IRQ_STATE 40 /* bcr R5 */ -+ -+ /* class 7 */ -+#define MMC_LOCK_UNLOCK 42 /* adtc R1b */ -+ -+ /* class 8 */ -+#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ -+#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1b */ -+ -+/* -+ MMC status in R1 -+ Type -+ e : error bit -+ s : status bit -+ r : detected and set for the actual command response -+ x : detected and set during command execution. the host must poll -+ the card by sending status command in order to read these bits. -+ Clear condition -+ a : according to the card state -+ b : always related to the previous command. Reception of -+ a valid command will clear it (with a delay of one command) -+ c : clear by read -+ */ -+ -+#define R1_OUT_OF_RANGE (1 << 31) /* er, c */ -+#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */ -+#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */ -+#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */ -+#define R1_ERASE_PARAM (1 << 27) /* ex, c */ -+#define R1_WP_VIOLATION (1 << 26) /* erx, c */ -+#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */ -+#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */ -+#define R1_COM_CRC_ERROR (1 << 23) /* er, b */ -+#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */ -+#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */ -+#define R1_CC_ERROR (1 << 20) /* erx, c */ -+#define R1_ERROR (1 << 19) /* erx, c */ -+#define R1_UNDERRUN (1 << 18) /* ex, c */ -+#define R1_OVERRUN (1 << 17) /* ex, c */ -+#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */ -+#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */ -+#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */ -+#define R1_ERASE_RESET (1 << 13) /* sr, c */ -+#define R1_STATUS(x) (x & 0xFFFFE000) -+#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ -+#define R1_READY_FOR_DATA (1 << 8) /* sx, a */ -+#define R1_APP_CMD (1 << 7) /* sr, c */ -+ -+/* These are unpacked versions of the actual responses */ -+ -+struct _mmc_csd { -+ u8 csd_structure; -+ u8 spec_vers; -+ u8 taac; -+ u8 nsac; -+ u8 tran_speed; -+ u16 ccc; -+ u8 read_bl_len; -+ u8 read_bl_partial; -+ u8 write_blk_misalign; -+ u8 read_blk_misalign; -+ u8 dsr_imp; -+ u16 c_size; -+ u8 vdd_r_curr_min; -+ u8 vdd_r_curr_max; -+ u8 vdd_w_curr_min; -+ u8 vdd_w_curr_max; -+ u8 c_size_mult; -+ union { -+ struct { /* MMC system specification version 3.1 */ -+ u8 erase_grp_size; -+ u8 erase_grp_mult; -+ } v31; -+ struct { /* MMC system specification version 2.2 */ -+ u8 sector_size; -+ u8 erase_grp_size; -+ } v22; -+ } erase; -+ u8 wp_grp_size; -+ u8 wp_grp_enable; -+ u8 default_ecc; -+ u8 r2w_factor; -+ u8 write_bl_len; -+ u8 write_bl_partial; -+ u8 file_format_grp; -+ u8 copy; -+ u8 perm_write_protect; -+ u8 tmp_write_protect; -+ u8 file_format; -+ u8 ecc; -+}; -+ -+#define MMC_VDD_145_150 0x00000001 /* VDD voltage 1.45 - 1.50 */ -+#define MMC_VDD_150_155 0x00000002 /* VDD voltage 1.50 - 1.55 */ -+#define MMC_VDD_155_160 0x00000004 /* VDD voltage 1.55 - 1.60 */ -+#define MMC_VDD_160_165 0x00000008 /* VDD voltage 1.60 - 1.65 */ -+#define MMC_VDD_165_170 0x00000010 /* VDD voltage 1.65 - 1.70 */ -+#define MMC_VDD_17_18 0x00000020 /* VDD voltage 1.7 - 1.8 */ -+#define MMC_VDD_18_19 0x00000040 /* VDD voltage 1.8 - 1.9 */ -+#define MMC_VDD_19_20 0x00000080 /* VDD voltage 1.9 - 2.0 */ -+#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */ -+#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */ -+#define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */ -+#define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */ -+#define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */ -+#define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */ -+#define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */ -+#define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */ -+#define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */ -+#define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */ -+#define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */ -+#define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */ -+#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */ -+#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */ -+#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */ -+#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */ -+#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */ -+ -+ -+/* -+ * CSD field definitions -+ */ -+ -+#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */ -+#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */ -+#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 */ -+ -+#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */ -+#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */ -+#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */ -+#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 */ -+ -+#endif /* MMC_MMC_PROTOCOL_H */ -+ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/include/linux/l3/algo-bit.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,39 @@ -+/* -+ * linux/include/linux/l3/algo-bit.h -+ * -+ * Copyright (C) 2001 Russell King, 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. -+ * -+ * L3 Bus bit-banging algorithm. Derived from i2c-algo-bit.h by -+ * Simon G. Vogl. -+ */ -+#ifndef L3_ALGO_BIT_H -+#define L3_ALGO_BIT_H 1 -+ -+#include -+ -+struct l3_algo_bit_data { -+ void (*setdat) (void *data, int state); -+ void (*setclk) (void *data, int state); -+ void (*setmode)(void *data, int state); -+ void (*setdir) (void *data, int in); /* set data direction */ -+ int (*getdat) (void *data); -+ -+ void *data; -+ -+ /* bus timings (us) */ -+ int data_hold; -+ int data_setup; -+ int clock_high; -+ int mode_hold; -+ int mode_setup; -+ int mode; -+}; -+ -+int l3_bit_add_bus(struct l3_adapter *); -+int l3_bit_del_bus(struct l3_adapter *); -+ -+#endif ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/include/linux/l3/l3.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,95 @@ -+/* -+ * linux/include/linux/l3/l3.h -+ * -+ * Copyright (C) 2001 Russell King, 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. -+ * -+ * Derived from i2c.h by Simon G. Vogl -+ */ -+#ifndef L3_H -+#define L3_H -+ -+struct l3_msg { -+ unsigned char addr; /* slave address */ -+ unsigned char flags; -+#define L3_M_RD 0x01 -+#define L3_M_NOADDR 0x02 -+ unsigned short len; /* msg length */ -+ unsigned char *buf; /* pointer to msg data */ -+}; -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+ -+struct l3_adapter; -+ -+struct l3_algorithm { -+ /* textual description */ -+ char name[32]; -+ -+ /* perform bus transactions */ -+ int (*xfer)(struct l3_adapter *, struct l3_msg msgs[], int num); -+}; -+ -+struct semaphore; -+ -+/* -+ * l3_adapter is the structure used to identify a physical L3 bus along -+ * with the access algorithms necessary to access it. -+ */ -+struct l3_adapter { -+ /* -+ * This name is used to uniquely identify the adapter. -+ * It should be the same as the module name. -+ */ -+ char name[32]; -+ -+ /* -+ * the algorithm to access the bus -+ */ -+ struct l3_algorithm *algo; -+ -+ /* -+ * Algorithm specific data -+ */ -+ void *algo_data; -+ -+ /* -+ * This may be NULL, or should point to the module struct -+ */ -+ struct module *owner; -+ -+ /* -+ * private data for the adapter -+ */ -+ void *data; -+ -+ /* -+ * Our lock. Unlike the i2c layer, we allow this to be used for -+ * other stuff, like the i2c layer lock. Some people implement -+ * i2c stuff using the same signals as the l3 bus. -+ */ -+ struct semaphore *lock; -+ -+ /* -+ * List of all adapters. -+ */ -+ struct list_head adapters; -+}; -+ -+extern int l3_add_adapter(struct l3_adapter *); -+extern int l3_del_adapter(struct l3_adapter *); -+extern void l3_put_adapter(struct l3_adapter *); -+extern struct l3_adapter *l3_get_adapter(const char *name); -+ -+extern int l3_write(struct l3_adapter *, int, const char *, int); -+extern int l3_read(struct l3_adapter *, int, char *, int); -+ -+#endif -+ -+#endif /* L3_H */ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/include/linux/l3/uda1341.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,61 @@ -+/* -+ * linux/include/linux/l3/uda1341.h -+ * -+ * Philips UDA1341 mixer device driver -+ * -+ * Copyright (c) 2000 Nicolas Pitre -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License. -+ */ -+ -+#define UDA1341_NAME "uda1341" -+ -+struct uda1341_cfg { -+ unsigned int fs:16; -+ unsigned int format:3; -+}; -+ -+#define FMT_I2S 0 -+#define FMT_LSB16 1 -+#define FMT_LSB18 2 -+#define FMT_LSB20 3 -+#define FMT_MSB 4 -+#define FMT_LSB16MSB 5 -+#define FMT_LSB18MSB 6 -+#define FMT_LSB20MSB 7 -+ -+#define L3_UDA1341_CONFIGURE 0x13410001 -+ -+struct l3_gain { -+ unsigned int left:8; -+ unsigned int right:8; -+ unsigned int unused:8; -+ unsigned int channel:8; -+}; -+ -+#define L3_SET_VOLUME 0x13410002 -+#define L3_SET_TREBLE 0x13410003 -+#define L3_SET_BASS 0x13410004 -+#define L3_SET_GAIN 0x13410005 -+ -+struct l3_agc { -+ unsigned int level:8; -+ unsigned int enable:1; -+ unsigned int attack:7; -+ unsigned int decay:8; -+ unsigned int channel:8; -+}; -+ -+#define L3_INPUT_AGC 0x13410006 -+ -+struct uda1341; -+ -+int uda1341_configure(struct uda1341 *uda, struct uda1341_cfg *conf); -+int uda1341_mixer_ctl(struct uda1341 *uda, int cmd, void *arg); -+int uda1341_open(struct uda1341 *uda); -+void uda1341_close(struct uda1341 *uda); -+ -+struct uda1341 *uda1341_attach(const char *adapter); -+void uda1341_detach(struct uda1341 *uda); -+ ---- linux-2.6.5/include/linux/i2c-id.h~heh 2004-04-03 22:36:16.000000000 -0500 -+++ linux-2.6.5/include/linux/i2c-id.h 2004-04-30 20:57:36.000000000 -0400 -@@ -187,6 +187,7 @@ - #define I2C_ALGO_BITHS 0x130000 /* enhanced bit style adapters */ - #define I2C_ALGO_OCP_IOP3XX 0x140000 /* XSCALE IOP3XX On-chip I2C alg */ - -+#define I2C_ALGO_PXA 0x200000 /* Intel PXA I2C algorithm */ - #define I2C_ALGO_EXP 0x800000 /* experimental */ - - #define I2C_ALGO_MASK 0xff0000 /* Mask for algorithms */ ---- linux-2.6.5/include/linux/serial_core.h~heh 2004-04-03 22:36:18.000000000 -0500 -+++ linux-2.6.5/include/linux/serial_core.h 2004-04-30 20:57:36.000000000 -0400 -@@ -17,7 +17,7 @@ - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -- * $Id$ -+ * $Id$ - */ - - /* -@@ -159,8 +159,6 @@ - spinlock_t lock; /* port lock */ - unsigned int iobase; /* in/out[bwl] */ - char *membase; /* read/write[bwl] */ -- unsigned int irq; /* irq number */ -- unsigned int uartclk; /* base uart clock */ - unsigned char fifosize; /* tx fifo size */ - unsigned char x_char; /* xon/xoff char */ - unsigned char regshift; /* reg offset shift */ -@@ -172,6 +170,7 @@ - - unsigned int read_status_mask; /* driver specific */ - unsigned int ignore_status_mask; /* driver specific */ -+ - struct uart_info *info; /* pointer to parent info */ - struct uart_icount icount; /* statistics */ - -@@ -182,7 +181,6 @@ - - unsigned int flags; - --#define UPF_HUP_NOTIFY (1 << 0) - #define UPF_FOURPORT (1 << 1) - #define UPF_SAK (1 << 2) - #define UPF_SPD_MASK (0x1030) -@@ -212,9 +210,12 @@ - unsigned int timeout; /* character-based timeout */ - unsigned int type; /* port type */ - struct uart_ops *ops; -+ unsigned int uartclk; /* base uart clock */ - unsigned int custom_divisor; -+ unsigned int irq; /* irq number */ - unsigned int line; /* port index */ - unsigned long mapbase; /* for ioremap */ -+ struct device *dev; /* parent device */ - unsigned char hub6; /* this should be in the 8250 driver */ - unsigned char unused[3]; - }; ---- linux-2.6.5/include/linux/vmalloc.h~heh 2004-04-03 22:38:23.000000000 -0500 -+++ linux-2.6.5/include/linux/vmalloc.h 2004-04-30 20:57:36.000000000 -0400 -@@ -35,6 +35,8 @@ - * Lowlevel-APIs (not for driver use!) - */ - extern struct vm_struct *get_vm_area(unsigned long size, unsigned long flags); -+extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags, -+ unsigned long start, unsigned long end); - extern struct vm_struct *remove_vm_area(void *addr); - extern int map_vm_area(struct vm_struct *area, pgprot_t prot, - struct page ***pages); ---- linux-2.6.5/include/linux/mm.h~heh 2004-04-03 22:36:15.000000000 -0500 -+++ linux-2.6.5/include/linux/mm.h 2004-04-30 20:57:36.000000000 -0400 -@@ -655,5 +655,12 @@ - int in_gate_area(struct task_struct *task, unsigned long addr); - #endif - -+#ifndef __arm__ -+#define memc_update_addr(x,y,z) -+#define memc_update_mm(x) -+#define memc_clear(x,y) -+#endif -+ - #endif /* __KERNEL__ */ - #endif /* _LINUX_MM_H */ -+ ---- linux-2.6.5/init/do_mounts.c~heh 2004-04-03 22:36:56.000000000 -0500 -+++ linux-2.6.5/init/do_mounts.c 2004-04-30 20:57:36.000000000 -0400 -@@ -391,7 +391,7 @@ - root_device_name += 5; - } - -- is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; -+ is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR || MAJOR(ROOT_DEV) == 31; - - if (initrd_load()) - goto out; ---- linux-2.6.5/fs/binfmt_aout.c~heh 2004-04-03 22:36:26.000000000 -0500 -+++ linux-2.6.5/fs/binfmt_aout.c 2004-04-30 20:57:36.000000000 -0400 -@@ -432,7 +432,11 @@ - else - send_sig(SIGTRAP, current, 0); - } -+#ifndef __arm__ - return 0; -+#else -+ return regs->ARM_r0; -+#endif - } - - static int load_aout_library(struct file *file) -@@ -462,8 +466,11 @@ - - /* For QMAGIC, the starting address is 0x20 into the page. We mask - this off to get the starting address for the page */ -- -- start_addr = ex.a_entry & 0xfffff000; -+#ifndef __arm__ -+ start_addr = ex.a_entry & 0xfffff000; -+#else -+ start_addr = ex.a_entry & 0xffff8000; -+#endif - - if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) { - static unsigned long error_time; ---- linux-2.6.5/mm/slab.c~heh 2004-04-03 22:37:41.000000000 -0500 -+++ linux-2.6.5/mm/slab.c 2004-04-30 20:57:36.000000000 -0400 -@@ -2115,12 +2115,12 @@ - * - * Called with disabled ints. - */ --static inline void __cache_free (kmem_cache_t *cachep, void* objp) -+static inline void __cache_free (kmem_cache_t *cachep, void* objp, void *caller) - { - struct array_cache *ac = ac_data(cachep); - - check_irq_off(); -- objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0)); -+ objp = cache_free_debugcheck(cachep, objp, caller /*__builtin_return_address(0)*/); - - if (likely(ac->avail < ac->limit)) { - STATS_INC_FREEHIT(cachep); -@@ -2289,7 +2289,7 @@ - unsigned long flags; - - local_irq_save(flags); -- __cache_free(cachep, objp); -+ __cache_free(cachep, objp, __builtin_return_address(0)); - local_irq_restore(flags); - } - -@@ -2312,7 +2312,7 @@ - local_irq_save(flags); - kfree_debugcheck(objp); - c = GET_PAGE_CACHE(virt_to_page(objp)); -- __cache_free(c, (void*)objp); -+ __cache_free(c, (void*)objp, __builtin_return_address(0)); - local_irq_restore(flags); - } - ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/Documentation/l3/structure 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,36 @@ -+L3 Bus Driver -+------------- -+ -+The structure of the driver is as follows: -+ -+ +----------+ +----------+ +----------+ -+ | client 1 | | client 2 | | client 3 | -+ +-----^----+ +----^-----+ +----^-----+ -+ | | | -+ +-----v--------------v---------------v-----+ -+ | | -+ +-----^-------+ +-------^-----+ -+ | | core | | -+ +-----v----+ | | +----v-----+ -+ | device | | | | device | -+ | driver 1 | | | | driver 2 | -+ +-----^----+ | | +----^-----+ -+ | | services | | -+ +-----v-------+ +-------v-----+ -+ | | -+ +-----------------^----^-------------------+ -+ | | -+ | +-v---------+ -+ | | algorithm | -+ | | driver | -+ | +-v---------+ -+ | | -+ +-v----v-+ -+ | bus | -+ | driver | -+ +--------+ -+ -+Clients talk to the core to attach device drivers and bus adapters, and -+to instruct device drivers to perform actions. Device drivers then talk -+to the core to perform L3 bus transactions via the algorithm driver and -+ultimately bus driver. ---- linux-2.6.5/arch/arm/kernel/debug.S~heh 2004-04-03 22:36:55.000000000 -0500 -+++ linux-2.6.5/arch/arm/kernel/debug.S 2004-04-30 20:57:36.000000000 -0400 -@@ -192,6 +192,20 @@ - - @ if all ports are inactive, then there is nothing we can do - moveq pc, lr -+ ldr r1, [\rx, #UTCR2] -+ teq r1, #5 -+ movne r1, #0 -+ strne r1, [\rx, #UTCR3] -+ movne r1, #8 -+ strne r1, [\rx, #UTCR0] -+ movne r1, #5 -+ strne r1, [\rx, #UTCR2] -+ movne r1, #0 -+ strne r1, [\rx, #UTCR1] -+ movne r1, #3 -+ strne r1, [\rx, #UTCR3] -+ movne r1, #255 -+ strne r1, [\rx, #UTSR0] - .endm - - .macro senduart,rd,rx -@@ -287,7 +301,7 @@ - - #elif defined(CONFIG_ARCH_INTEGRATOR) - --#include -+#include - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 -@@ -298,7 +312,7 @@ - .endm - - .macro senduart,rd,rx -- strb \rd, [\rx, #AMBA_UARTDR] -+ strb \rd, [\rx, #UART01x_DR] - .endm - - .macro waituart,rd,rx ---- linux-2.6.5/arch/arm/kernel/entry-armv.S~heh 2004-04-03 22:36:54.000000000 -0500 -+++ linux-2.6.5/arch/arm/kernel/entry-armv.S 2004-04-30 20:57:36.000000000 -0400 -@@ -1181,6 +1181,9 @@ - * get out of that mode without clobbering one register. - */ - vector_FIQ: disable_fiq -+ mrs r13, spsr -+ orr r13, r13, #PSR_F_BIT -+ msr spsr, r13 - subs pc, lr, #4 - - /*============================================================================= ---- linux-2.6.5/arch/arm/kernel/irq.c~heh 2004-04-03 22:36:12.000000000 -0500 -+++ linux-2.6.5/arch/arm/kernel/irq.c 2004-04-30 20:57:36.000000000 -0400 -@@ -47,12 +47,36 @@ - #define MAX_IRQ_CNT 100000 - - static volatile unsigned long irq_err_count; --static spinlock_t irq_controller_lock; - static LIST_HEAD(irq_pending); - - struct irqdesc irq_desc[NR_IRQS]; - void (*init_arch_irq)(void) __initdata = NULL; - -+#if NR_IRQ_DEVICES > 1 -+struct irq_device { -+ spinlock_t lock; -+ int nr_irqs; -+ struct irq_desc *irqs; -+}; -+ -+static struct irq_device irq_devices[NR_IRQ_DEVICES] = { -+ [0] = { -+ .lock = SPIN_LOCK_UNLOCKED, -+ .nr_irqs = NR_IRQS, -+ .irqs = irq_desc, -+ }, -+}; -+#define IRQ_LOCK(irq) (&irq_devices[IRQ_DEVICE(irq)].lock) -+#define IRQ_DESC(irq) (&irq_devices[IRQ_DEVICE(irq)].irqs[IRQ_INDEX(irq)]) -+#define IRQ_VALID(irq) (IRQ_DEVICE(irq) < NR_IRQ_DEVICES && \ -+ IRQ_INDEX(irq) < irq_devices[IRQ_DEVICE(irq)].nr_irqs) -+#else -+static spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED; -+#define IRQ_LOCK(irq) (&irq_controller_lock) -+#define IRQ_DESC(irq) (&irq_desc[irq]) -+#define IRQ_VALID(irq) ((irq) < NR_IRQS) -+#endif -+ - /* - * Dummy mask/unmask handler - */ -@@ -95,13 +119,13 @@ - */ - void disable_irq(unsigned int irq) - { -- struct irqdesc *desc = irq_desc + irq; -+ struct irqdesc *desc = IRQ_DESC(irq); - unsigned long flags; - -- spin_lock_irqsave(&irq_controller_lock, flags); -+ spin_lock_irqsave(IRQ_LOCK(irq), flags); - desc->disable_depth++; - list_del_init(&desc->pend); -- spin_unlock_irqrestore(&irq_controller_lock, flags); -+ spin_unlock_irqrestore(IRQ_LOCK(irq), flags); - } - - /** -@@ -116,10 +140,10 @@ - */ - void enable_irq(unsigned int irq) - { -- struct irqdesc *desc = irq_desc + irq; -+ struct irqdesc *desc = IRQ_DESC(irq); - unsigned long flags; - -- spin_lock_irqsave(&irq_controller_lock, flags); -+ spin_lock_irqsave(IRQ_LOCK(irq), flags); - if (unlikely(!desc->disable_depth)) { - printk("enable_irq(%u) unbalanced from %p\n", irq, - __builtin_return_address(0)); -@@ -140,7 +164,7 @@ - list_add(&desc->pend, &irq_pending); - } - } -- spin_unlock_irqrestore(&irq_controller_lock, flags); -+ spin_unlock_irqrestore(IRQ_LOCK(irq), flags); - } - - /* -@@ -148,24 +172,24 @@ - */ - void enable_irq_wake(unsigned int irq) - { -- struct irqdesc *desc = irq_desc + irq; -+ struct irqdesc *desc = IRQ_DESC(irq); - unsigned long flags; - -- spin_lock_irqsave(&irq_controller_lock, flags); -+ spin_lock_irqsave(IRQ_LOCK(irq), flags); - if (desc->chip->wake) - desc->chip->wake(irq, 1); -- spin_unlock_irqrestore(&irq_controller_lock, flags); -+ spin_unlock_irqrestore(IRQ_LOCK(irq), flags); - } - - void disable_irq_wake(unsigned int irq) - { -- struct irqdesc *desc = irq_desc + irq; -+ struct irqdesc *desc = IRQ_DESC(irq); - unsigned long flags; - -- spin_lock_irqsave(&irq_controller_lock, flags); -+ spin_lock_irqsave(IRQ_LOCK(irq), flags); - if (desc->chip->wake) - desc->chip->wake(irq, 0); -- spin_unlock_irqrestore(&irq_controller_lock, flags); -+ spin_unlock_irqrestore(IRQ_LOCK(irq), flags); - } - - int show_interrupts(struct seq_file *p, void *v) -@@ -175,8 +199,8 @@ - unsigned long flags; - - if (i < NR_IRQS) { -- spin_lock_irqsave(&irq_controller_lock, flags); -- action = irq_desc[i].action; -+ spin_lock_irqsave(IRQ_LOCK(irq), flags); -+ action = IRQ_DESC(i)->action; - if (!action) - goto unlock; - -@@ -187,7 +211,7 @@ - - seq_putc(p, '\n'); - unlock: -- spin_unlock_irqrestore(&irq_controller_lock, flags); -+ spin_unlock_irqrestore(IRQ_LOCK(irq), flags); - } else if (i == NR_IRQS) { - #ifdef CONFIG_ARCH_ACORN - show_fiq_list(p, v); -@@ -259,7 +283,7 @@ - unsigned int status; - int retval = 0; - -- spin_unlock(&irq_controller_lock); -+ spin_unlock(IRQ_LOCK(irq)); - - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); -@@ -274,7 +298,7 @@ - if (status & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - -- spin_lock_irq(&irq_controller_lock); -+ spin_lock_irq(IRQ_LOCK(irq)); - - return retval; - } -@@ -455,7 +479,7 @@ - desc = &bad_irq_desc; - - irq_enter(); -- spin_lock(&irq_controller_lock); -+ spin_lock(IRQ_LOCK(irq)); - desc->handle(irq, desc, regs); - - /* -@@ -464,7 +488,7 @@ - if (!list_empty(&irq_pending)) - do_pending_irqs(regs); - -- spin_unlock(&irq_controller_lock); -+ spin_unlock(IRQ_LOCK(irq)); - irq_exit(); - } - -@@ -473,7 +497,7 @@ - struct irqdesc *desc; - unsigned long flags; - -- if (irq >= NR_IRQS) { -+ if (!IRQ_VALID(irq)) { - printk(KERN_ERR "Trying to install handler for IRQ%d\n", irq); - return; - } -@@ -481,12 +505,12 @@ - if (handle == NULL) - handle = do_bad_IRQ; - -- desc = irq_desc + irq; -+ desc = IRQ_DESC(irq); - - if (is_chained && desc->chip == &bad_chip) - printk(KERN_WARNING "Trying to install chained handler for IRQ%d\n", irq); - -- spin_lock_irqsave(&irq_controller_lock, flags); -+ spin_lock_irqsave(IRQ_LOCK(irq), flags); - if (handle == do_bad_IRQ) { - desc->chip->mask(irq); - desc->chip->ack(irq); -@@ -499,7 +523,7 @@ - desc->disable_depth = 0; - desc->chip->unmask(irq); - } -- spin_unlock_irqrestore(&irq_controller_lock, flags); -+ spin_unlock_irqrestore(IRQ_LOCK(irq), flags); - } - - void set_irq_chip(unsigned int irq, struct irqchip *chip) -@@ -507,7 +531,7 @@ - struct irqdesc *desc; - unsigned long flags; - -- if (irq >= NR_IRQS) { -+ if (!IRQ_VALID(irq)) { - printk(KERN_ERR "Trying to install chip for IRQ%d\n", irq); - return; - } -@@ -515,10 +539,10 @@ - if (chip == NULL) - chip = &bad_chip; - -- desc = irq_desc + irq; -- spin_lock_irqsave(&irq_controller_lock, flags); -+ desc = IRQ_DESC(irq); -+ spin_lock_irqsave(IRQ_LOCK(irq), flags); - desc->chip = chip; -- spin_unlock_irqrestore(&irq_controller_lock, flags); -+ spin_unlock_irqrestore(IRQ_LOCK(irq), flags); - } - - int set_irq_type(unsigned int irq, unsigned int type) -@@ -527,16 +551,21 @@ - unsigned long flags; - int ret = -ENXIO; - -- if (irq >= NR_IRQS) { -+ if (!IRQ_VALID(irq)) { - printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq); - return -ENODEV; - } - -- desc = irq_desc + irq; -+ desc = IRQ_DESC(irq); -+ if (!desc->action && desc->handle != do_bad_IRQ) { -+ printk(KERN_ERR "Setting type of unclaimed IRQ%d from ", irq); -+ print_symbol("%s\n", (unsigned long)__builtin_return_address(0)); -+ } -+ - if (desc->chip->type) { -- spin_lock_irqsave(&irq_controller_lock, flags); -+ spin_lock_irqsave(IRQ_LOCK(irq), flags); - ret = desc->chip->type(irq, type); -- spin_unlock_irqrestore(&irq_controller_lock, flags); -+ spin_unlock_irqrestore(IRQ_LOCK(irq), flags); - } - - return ret; -@@ -547,17 +576,17 @@ - struct irqdesc *desc; - unsigned long flags; - -- if (irq >= NR_IRQS) { -+ if (!IRQ_VALID(irq)) { - printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq); - return; - } - -- desc = irq_desc + irq; -- spin_lock_irqsave(&irq_controller_lock, flags); -+ desc = IRQ_DESC(irq); -+ spin_lock_irqsave(IRQ_LOCK(irq), flags); - desc->valid = (iflags & IRQF_VALID) != 0; - desc->probe_ok = (iflags & IRQF_PROBE) != 0; - desc->noautoenable = (iflags & IRQF_NOAUTOEN) != 0; -- spin_unlock_irqrestore(&irq_controller_lock, flags); -+ spin_unlock_irqrestore(IRQ_LOCK(irq), flags); - } - - int setup_irq(unsigned int irq, struct irqaction *new) -@@ -587,13 +616,13 @@ - /* - * The following block of code has to be executed atomically - */ -- desc = irq_desc + irq; -- spin_lock_irqsave(&irq_controller_lock, flags); -+ desc = IRQ_DESC(irq); -+ spin_lock_irqsave(IRQ_LOCK(irq), flags); - p = &desc->action; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) { -- spin_unlock_irqrestore(&irq_controller_lock, flags); -+ spin_unlock_irqrestore(IRQ_LOCK(irq), flags); - return -EBUSY; - } - -@@ -618,7 +647,7 @@ - } - } - -- spin_unlock_irqrestore(&irq_controller_lock, flags); -+ spin_unlock_irqrestore(IRQ_LOCK(irq), flags); - return 0; - } - -@@ -659,7 +688,7 @@ - unsigned long retval; - struct irqaction *action; - -- if (irq >= NR_IRQS || !irq_desc[irq].valid || !handler || -+ if (!IRQ_VALID(irq) || !IRQ_DESC(irq)->valid || !handler || - (irq_flags & SA_SHIRQ && !dev_id)) - return -EINVAL; - -@@ -700,14 +729,14 @@ - struct irqaction * action, **p; - unsigned long flags; - -- if (irq >= NR_IRQS || !irq_desc[irq].valid) { -+ if (!IRQ_VALID(irq) || !IRQ_DESC(irq)->valid) { - printk(KERN_ERR "Trying to free IRQ%d\n",irq); - dump_stack(); - return; - } - -- spin_lock_irqsave(&irq_controller_lock, flags); -- for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) { -+ spin_lock_irqsave(IRQ_LOCK(irq), flags); -+ for (p = &IRQ_DESC(irq)->action; (action = *p) != NULL; p = &action->next) { - if (action->dev_id != dev_id) - continue; - -@@ -715,7 +744,7 @@ - *p = action->next; - break; - } -- spin_unlock_irqrestore(&irq_controller_lock, flags); -+ spin_unlock_irqrestore(IRQ_LOCK(irq), flags); - - if (!action) { - printk(KERN_ERR "Trying to free free IRQ%d\n",irq); -@@ -747,19 +776,18 @@ - * first snaffle up any unassigned but - * probe-able interrupts - */ -- spin_lock_irq(&irq_controller_lock); - for (i = 0; i < NR_IRQS; i++) { -- if (!irq_desc[i].probe_ok || irq_desc[i].action) -- continue; -- -- irq_desc[i].probing = 1; -- irq_desc[i].triggered = 0; -- if (irq_desc[i].chip->type) -- irq_desc[i].chip->type(i, IRQT_PROBE); -- irq_desc[i].chip->unmask(i); -- irqs += 1; -+ spin_lock_irq(IRQ_LOCK(i)); -+ if (irq_desc[i].probe_ok && !irq_desc[i].action) { -+ irq_desc[i].probing = 1; -+ irq_desc[i].triggered = 0; -+ if (irq_desc[i].chip->type) -+ irq_desc[i].chip->type(i, IRQT_PROBE); -+ irq_desc[i].chip->unmask(i); -+ irqs += 1; -+ } -+ spin_unlock_irq(IRQ_LOCK(i)); - } -- spin_unlock_irq(&irq_controller_lock); - - /* - * wait for spurious interrupts to mask themselves out again -@@ -770,14 +798,14 @@ - /* - * now filter out any obviously spurious interrupts - */ -- spin_lock_irq(&irq_controller_lock); - for (i = 0; i < NR_IRQS; i++) { -+ spin_lock_irq(IRQ_LOCK(i)); - if (irq_desc[i].probing && irq_desc[i].triggered) { - irq_desc[i].probing = 0; - irqs -= 1; - } -+ spin_unlock_irq(IRQ_LOCK(i)); - } -- spin_unlock_irq(&irq_controller_lock); - - return irqs; - } -@@ -788,11 +816,13 @@ - { - unsigned int mask = 0, i; - -- spin_lock_irq(&irq_controller_lock); -- for (i = 0; i < 16 && i < NR_IRQS; i++) -- if (irq_desc[i].probing && irq_desc[i].triggered) -+ for (i = 0; i < 16 && i < NR_IRQS; i++) { -+ struct irqdesc *desc = IRQ_DESC(i); -+ spin_lock_irq(IRQ_LOCK(i)); -+ if (desc->probing && desc->triggered) - mask |= 1 << i; -- spin_unlock_irq(&irq_controller_lock); -+ spin_unlock_irq(IRQ_LOCK(i)); -+ } - - up(&probe_sem); - -@@ -813,23 +843,21 @@ - * look at the interrupts, and find exactly one - * that we were probing has been triggered - */ -- spin_lock_irq(&irq_controller_lock); - for (i = 0; i < NR_IRQS; i++) { -- if (irq_desc[i].probing && -- irq_desc[i].triggered) { -+ struct irqdesc *desc = IRQ_DESC(i); -+ -+ spin_lock_irq(IRQ_LOCK(i)); -+ if (desc->probing && desc->triggered) { - if (irq_found != NO_IRQ) { -+ spin_unlock_irq(IRQ_LOCK(i)); - irq_found = NO_IRQ; -- goto out; -+ break; - } - irq_found = i; - } -+ spin_unlock_irq(IRQ_LOCK(i)); - } - -- if (irq_found == -1) -- irq_found = NO_IRQ; --out: -- spin_unlock_irq(&irq_controller_lock); -- - up(&probe_sem); - - return irq_found; ---- linux-2.6.5/arch/arm/kernel/bios32.c~heh 2004-04-03 22:36:56.000000000 -0500 -+++ linux-2.6.5/arch/arm/kernel/bios32.c 2004-04-30 20:57:36.000000000 -0400 -@@ -565,8 +565,6 @@ - if (hw->postinit) - hw->postinit(); - -- pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq); -- - list_for_each_entry(sys, &hw->buses, node) { - struct pci_bus *bus = sys->bus; - -@@ -581,6 +579,11 @@ - pci_bus_assign_resources(bus); - - /* -+ * Fixup IRQs. -+ */ -+ pci_bus_fixup_irqs(bus, pcibios_swizzle, pcibios_map_irq); -+ -+ /* - * Tell drivers about devices found. - */ - pci_bus_add_devices(bus); ---- linux-2.6.5/arch/arm/kernel/traps.c~heh 2004-04-03 22:36:57.000000000 -0500 -+++ linux-2.6.5/arch/arm/kernel/traps.c 2004-04-30 20:57:36.000000000 -0400 -@@ -206,33 +206,43 @@ - c_backtrace(fp, 0x10); - } - --spinlock_t die_lock = SPIN_LOCK_UNLOCKED; -- --/* -- * This function is protected against re-entrancy. -- */ --NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) -+static void __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs) - { -- struct task_struct *tsk = current; -+ struct task_struct *tsk = thread->task; - static int die_counter; - -- console_verbose(); -- spin_lock_irq(&die_lock); -- bust_spinlocks(1); -- - printk("Internal error: %s: %x [#%d]\n", str, err, ++die_counter); - print_modules(); - printk("CPU: %d\n", smp_processor_id()); - show_regs(regs); - printk("Process %s (pid: %d, stack limit = 0x%p)\n", -- tsk->comm, tsk->pid, tsk->thread_info + 1); -+ tsk->comm, tsk->pid, thread + 1); - - if (!user_mode(regs) || in_interrupt()) { - dump_mem("Stack: ", regs->ARM_sp, 8192+(unsigned long)tsk->thread_info); - dump_backtrace(regs, tsk); - dump_instr(regs); - } -+} -+ -+void nmi_watchdog(struct thread_info *thread, struct pt_regs *regs) -+{ -+ __die("NMI watchdog", 0, thread, regs); -+} - -+spinlock_t die_lock = SPIN_LOCK_UNLOCKED; -+ -+/* -+ * This function is protected against re-entrancy. -+ */ -+NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) -+{ -+ struct thread_info *thread = current_thread_info(); -+ -+ console_verbose(); -+ spin_lock_irq(&die_lock); -+ bust_spinlocks(1); -+ __die(str, err, thread, regs); - bust_spinlocks(0); - spin_unlock_irq(&die_lock); - do_exit(SIGSEGV); ---- linux-2.6.5/arch/arm/Kconfig~heh 2004-04-03 22:37:07.000000000 -0500 -+++ linux-2.6.5/arch/arm/Kconfig 2004-04-30 20:57:36.000000000 -0400 -@@ -297,7 +297,7 @@ - - config CPU_FREQ - bool "Support CPU clock change (EXPERIMENTAL)" -- depends on (ARCH_SA1100 || ARCH_INTEGRATOR) && EXPERIMENTAL -+ depends on (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_PXA) && EXPERIMENTAL - help - CPU clock scaling allows you to change the clock speed of the - running CPU on the fly. This is a nice method to save battery power, ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/fastfpe/entry.S 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,294 @@ -+/* -+At entry the registers contain the following information: -+ -+r14 return address for undefined exception return -+r9 return address for return from exception -+r13 user registers on stack, offset 0 up to offset 4*15 contains -+ registers r0..15, then the psr -+r10 FP workspace 35 words (init, reg[8][4], fpsr, fpcr) -+ -+*/ -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .data -+fp_const: -+ .word 0, 0x00000000, 0, 0x80000000 @ 0 -+ .word 0, 0x80000000, 0, 0 @ 1 -+ .word 0, 0x80000000, 0, 1 @ 2 -+ .word 0, 0xc0000000, 0, 1 @ 3 -+ .word 0, 0x80000000, 0, 2 @ 4 -+ .word 0, 0xa0000000, 0, 2 @ 5 -+ .word 0, 0x80000000, 0, -1 @ 0.5 -+ .word 0, 0xa0000000, 0, 3 @ 10 -+fp_undef: -+ .word 0 -+fp_cond: -+ .word 0xf0f0 @ eq -+ .word 0x0f0f @ ne -+ .word 0xcccc @ cs -+ .word 0x3333 @ cc -+ .word 0xff00 @ mi -+ .word 0x00ff @ pl -+ .word 0xaaaa @ vs -+ .word 0x5555 @ vc -+ .word 0x0c0c @ hi -+ .word 0xf3f3 @ ls -+ .word 0xaa55 @ ge -+ .word 0x55aa @ lt -+ .word 0x0a05 @ gt -+ .word 0xf5fa @ le -+ .word 0xffff @ al -+ .word 0x0000 @ nv -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .text -+ .globl fastfpe_enter -+fastfpe_enter: -+ ldr r4,=fp_undef -+ str r14,[r4] @ to free one register -+ add r10,r10,#4 @ to make the code simpler -+ mov r4, r0 @ r4=trapped instruction -+ and r1,r4,#0x00000f00 @ r1=coprocessor << 8 -+next_enter: -+ cmp r1,#1<<8 @ copro 1 ? -+ beq copro_1 -+ cmp r1,#2<<8 -+ movne pc,r14 -+ -+copro_2: -+ and r1,r4,#0x0f000000 -+ cmp r1,#0x0c000000 @ CPDT with post indexing -+ cmpne r1,#0x0d000000 @ CPDT with pre indexing -+ beq CPDT_M_enter -+ mov pc,r14 -+ -+copro_1: -+ and r1,r4,#0x0f000000 -+ cmp r1,#0x0e000000 @ CPDO -+ beq CPDO_CPRT_enter -+ cmp r1,#0x0c000000 @ CPDT with post indexing -+ cmpne r1,#0x0d000000 @ CPDT with pre indexing -+ beq CPDT_1_enter -+ mov pc,r14 -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl fastfpe_next -+fastfpe_next: -+ ldr r5,[r13,#60] -+next_after_cond: -+__x1: -+ ldrt r4,[r5],#4 -+ -+ ldr r0,=fp_cond @ check condition of next instruction -+ ldr r1,[r13,#64] @ psr containing flags -+ mov r2,r4,lsr#28 -+ mov r1,r1,lsr#28 -+ ldr r0,[r0,r2,lsl#2] -+ mov r0,r0,lsr r1 -+ tst r0,#1 -+ beq next_after_cond @ must not necessarily have been an -+ @ FP instruction ! -+ and r1,r4,#0x0f000000 @ Test for copro instruction -+ cmp r1,#0x0c000000 -+ rsbgts r0,r1,#0x0e000000 @ cmpgt #0x0e000000,r1 -+ movlt pc,r9 @ next is no copro instruction, return -+ -+ ands r1,r4,#0x00000f00 @ r1 = coprocessor << 8 -+ cmpne r1,#3<<8 -+ movge pc,r9 @ copro = 0 or >=3, return -+ -+ str r5,[r13,#60] @ save updated pc -+ b next_enter -+ -+/*---------------------------------------------------------------------------*/ -+ -+undefined: -+ ldr r4,=fp_undef -+ ldr pc,[r4] -+ -+/*---------------------------------------------------------------------------*/ -+ -+CPDT_1_enter: -+ and r5,r4,#0x000f0000 @ r5=base register number << 16 -+ ldr r6,[r13,r5,lsr#14] @ r6=base address -+ cmp r5,#0x000f0000 @ base register = pc ? -+ addeq r6,r6,#4 -+ and r7,r4,#0x000000ff @ r7=offset value -+ -+ tst r4,#0x00800000 @ up or down? -+ addne r7,r6,r7,lsl#2 -+ subeq r7,r6,r7,lsl#2 @ r6=base address +/- offset -+ tst r4,#0x01000000 @ preindexing ? -+ movne r6,r7 -+ tst r4,#0x00200000 @ write back ? -+ cmpne r5,#0x000f0000 @ base register = pc ? -+ strne r7,[r13,r5,lsr#14] -+ -+ and r0,r4,#0x00007000 @ r0=fp register number << 12 -+ add r0,r10,r0,lsr#8 @ r0=address of fp register -+ mov r1,#0 -+ tst r4,#0x00008000 -+ orrne r1,r1,#1 @ T0 -+ tst r4,#0x00400000 -+ orrne r1,r1,#2 @ T1 -+ tst r4,#0x00100000 -+ orrne r1,r1,#4 @ L/S -+ -+ add pc,pc,r1,lsl#2 -+ mov r0,r0 -+ b CPDT_store_single @ these functions get -+ b CPDT_store_double @ r0=address of fp register -+ b CPDT_store_extended @ r6=address of data -+ b undefined @ CPDT_store_decimal -+ b CPDT_load_single -+ b CPDT_load_double -+ b CPDT_load_extended -+ b undefined @ CPDT_load_decimal -+ -+/*---------------------------------------------------------------------------*/ -+ -+CPDT_M_enter: -+ and r5,r4,#0x000f0000 @ r5=base register number << 16 -+ ldr r6,[r13,r5,lsr#14] @ r6=base address -+ cmp r5,#0x000f0000 @ base register = pc ? -+ addeq r6,r6,#4 -+ and r7,r4,#0x000000ff @ r7=offset value -+ -+ tst r4,#0x00800000 @ up or down? -+ addne r7,r6,r7,lsl#2 -+ subeq r7,r6,r7,lsl#2 @ r7=base address +/- offset -+ tst r4,#0x01000000 @ preindexing ? -+ movne r6,r7 -+ tst r4,#0x00200000 @ write back ? -+ cmpne r5,#0x000f0000 @ base register = pc ? -+ strne r7,[r13,r5,lsr#14] -+ -+ and r0,r4,#0x00007000 @ r0=fp register number << 12 -+ and r1,r4,#0x00008000 -+ mov r1,r1,lsr#15 @ N0 -+ and r2,r4,#0x00400000 -+ orrs r1,r1,r2,lsr#21 @ N1 -+ addeq r1,r1,#4 @ r1=register count -+ -+ tst r4,#0x00100000 @ load/store -+ beq CPDT_sfm -+ b CPDT_lfm -+ -+/*---------------------------------------------------------------------------*/ -+ -+CPDO_CPRT_enter: -+ tst r4,#0x00000010 -+ bne CPRT_enter -+ -+ and r0,r4,#0x00007000 -+ add r0,r10,r0,lsr#8 @ r0=address of Fd -+ and r1,r4,#0x00070000 -+ add r1,r10,r1,lsr#12 @ r1=address of Fn -+ tst r4,#0x00000008 -+ bne CPDO_const -+ and r2,r4,#0x00000007 -+ add r2,r10,r2,lsl#4 @ r2=address of Fm -+ -+CPDO_constback: -+ and r3,r4,#0x00f00000 -+ tst r4,#0x00008000 -+ orrne r3,r3,#0x01000000 -+ -+ add pc,pc,r3,lsr#18 -+ mov r0,r0 -+ b CPDO_adf -+ b CPDO_muf -+ b CPDO_suf -+ b CPDO_rsf -+ b CPDO_dvf -+ b CPDO_rdf -+ b undefined -+ b undefined -+ b undefined @ CPDO_rmf -+ b CPDO_muf -+ b CPDO_dvf -+ b CPDO_rdf -+ b undefined -+ b undefined -+ b undefined -+ b undefined -+ b CPDO_mvf -+ b CPDO_mnf -+ b CPDO_abs -+ b CPDO_rnd -+ b CPDO_sqt -+ b undefined -+ b undefined -+ b undefined -+ b undefined -+ b undefined -+ b undefined -+ b undefined -+ b undefined -+ b undefined -+ b CPDO_rnd -+ b fastfpe_next -+ -+CPDO_const: -+ ldr r2,=fp_const -+ and r3,r4,#0x00000007 -+ add r2,r2,r3,lsl#4 -+ b CPDO_constback -+ -+/*---------------------------------------------------------------------------*/ -+ -+CPRT_enter: -+ and r0,r4,#0x0000f000 @ r0=Rd<<12 -+ and r1,r4,#0x00070000 -+ add r1,r10,r1,lsr#12 @ r1=address of Fn -+ tst r4,#0x00000008 -+ bne CPRT_const -+ and r2,r4,#0x00000007 -+ add r2,r10,r2,lsl#4 @ r2=address of Fm -+ -+CPRT_constback: -+ and r3,r4,#0x00f00000 -+ -+ add pc,pc,r3,lsr#18 -+ mov r0,r0 -+ b CPRT_flt -+ b CPRT_fix -+ b CPRT_wfs -+ b CPRT_rfs -+ b undefined -+ b undefined -+ b undefined -+ b undefined -+ b undefined -+ b CPRT_cmf -+ b undefined -+ b CPRT_cnf -+ b undefined -+ b CPRT_cmf -+ b undefined -+ b CPRT_cnf -+ -+CPRT_const: -+ ldr r2,=fp_const -+ and r3,r4,#0x00000007 -+ add r2,r2,r3,lsl#4 -+ b CPRT_constback -+ -+/*---------------------------------------------------------------------------*/ -+ -+ @ The fetch of the next instruction to emulate could fault -+ -+ .section .fixup,"ax" -+ .align -+__f1: -+ mov pc,r9 -+ .previous -+ .section __ex_table,"a" -+ .align 3 -+ .long __x1,__f1 -+ .previous -+ -+/*---------------------------------------------------------------------------*/ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/fastfpe/module.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,62 @@ -+/* -+ Fast Floating Point Emulator -+ (c) Peter Teichmann -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the 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 -+ -+#ifndef MODULE -+#define kern_fp_enter fp_enter -+ -+extern char fpe_type[]; -+#endif -+ -+static void (*orig_fp_enter)(void); /* old kern_fp_enter value */ -+extern void (*kern_fp_enter)(void); /* current FP handler */ -+extern void fastfpe_enter(void); /* forward declarations */ -+ -+static int __init fpe_init(void) -+{ -+ if (fpe_type[0] && strcmp(fpe_type, "fastfpe")) -+ return 0; -+ -+ printk("Fast Floating Point Emulator V0.9 (c) Peter Teichmann.\n"); -+ -+ /* Save pointer to the old FP handler and then patch ourselves in */ -+ orig_fp_enter = kern_fp_enter; -+ kern_fp_enter = fastfpe_enter; -+ -+ return 0; -+} -+ -+static void __exit fpe_exit(void) -+{ -+ /* Restore the values we saved earlier. */ -+ kern_fp_enter = orig_fp_enter; -+} -+ -+module_init(fpe_init); -+module_exit(fpe_exit); -+ -+MODULE_AUTHOR("Peter Teichmann "); -+MODULE_DESCRIPTION("Fast floating point emulator with full precision"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/fastfpe/CPDO.S 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,682 @@ -+/* -+The FP structure has 4 words reserved for each register, the first is used just -+for the sign in bit 31, the second and third are for the mantissa (unsigned -+integer, high 32 bit first) and the fourth is the exponent (signed integer). -+The mantissa is always normalized. -+ -+If the exponent is 0x80000000, that is the most negative value, the number -+represented is 0 and both mantissa words are also 0. -+ -+If the exponent is 0x7fffffff, that is the biggest positive value, the number -+represented is infinity if the high 32 mantissa bit are also 0, otherwise it is -+a NaN. The low 32 mantissa bit are 0 if the number represented is infinity. -+ -+Decimal and packed decimal numbers are not supported yet. -+ -+The parameters to these functions are r0=destination pointer, r1 and r2 -+source pointers. r4 is the instruction. They may use r0-r8 and r14. They return -+to fastfpe_next, except CPDO_rnf_core which expects the return address in r14. -+*/ -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDO_adf -+CPDO_adf: -+ ldmia r1,{r1,r3,r5,r7} -+ ldmia r2,{r2,r4,r6,r8} -+ -+ cmp r7,#0x7fffffff -+ cmpne r8,#0x7fffffff -+ beq CPDO_adf_extra -+ -+ cmp r1,r2 -+ bne CPDO_suf_s -+ -+CPDO_adf_s: -+ subs r2,r7,r8 -+ bge CPDO_adf_2nd -+ -+ mov r7,r8 -+ rsb r2,r2,#0 -+ cmp r2,#32 -+ ble CPDO_adf_1st2 -+ -+ sub r2,r2,#32 -+ cmp r2,#32 -+ movgt r2,#32 -+ mov r5,r3,lsr r2 -+ mov r3,#0 -+ b CPDO_adf_add -+ -+CPDO_adf_1st2: -+ rsb r8,r2,#32 -+ mov r5,r5,lsr r2 -+ orr r5,r5,r3,lsl r8 -+ mov r3,r3,lsr r2 @ 1. op normalized -+ b CPDO_adf_add -+ -+CPDO_adf_2nd: -+ cmp r2,#32 -+ ble CPDO_adf_2nd2 -+ -+ sub r2,r2,#32 -+ cmp r2,#32 -+ movgt r2,#32 -+ mov r6,r4,lsr r2 -+ mov r4,#0 -+ b CPDO_adf_add -+ -+CPDO_adf_2nd2: -+ rsb r8,r2,#32 -+ mov r6,r6,lsr r2 -+ orr r6,r6,r4,lsl r8 -+ mov r4,r4,lsr r2 @ 2. op normalized -+ -+CPDO_adf_add: -+ adds r5,r5,r6 -+ adcs r3,r3,r4 @ do addition -+ bcc CPDO_adf_end -+ -+ add r7,r7,#1 -+ movs r3,r3,rrx -+ mov r5,r5,rrx @ correct for overflow -+ -+CPDO_adf_end: -+ cmp r7,#0x20000000 -+ bge CPDO_inf -+ -+ stmia r0,{r1,r3,r5,r7} -+ b fastfpe_next -+ -+CPDO_adf_extra: -+ cmp r7,#0x7fffffff @ was it the 1st ? -+ bne CPDO_infnan_2 @ no it was the 2nd -+ cmp r8,#0x7fffffff @ if 1st, 2nd too ? -+ bne CPDO_infnan_1 @ no only 1st -+ cmp r3,#0 -+ cmpeq r4,#0 -+ bne CPDO_nan_12 -+ b CPDO_inf -+ -+/*---------------------------------------------------------------------------*/ -+ -+CPDO_infnan_1: -+ stmia r0,{r1,r3,r5,r7} -+ b fastfpe_next -+ -+CPDO_infnan_2: -+ stmia r0,{r2,r4,r6,r8} -+ b fastfpe_next -+ -+CPDO_nan_12: -+ orr r2,r3,r4 -+ b CPDO_inf_1 -+ -+CPDO_nan: -+ mov r2,#0x40000000 @ create non signalling NaN -+ b CPDO_inf_1 -+ -+CPDO_inf: -+ mov r2,#0 -+CPDO_inf_1: -+ mov r3,#0 -+ mov r4,#0x7fffffff -+CPDO_store_1234: -+ stmia r0,{r1,r2,r3,r4} -+ b fastfpe_next -+ -+CPDO_zero: -+ mov r1,#0 -+CPDO_zero_1: -+ mov r2,#0 -+ mov r3,#0 -+ mov r4,#0x80000000 -+ stmia r0,{r1,r2,r3,r4} -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDO_suf -+CPDO_suf: -+ ldmia r1,{r1,r3,r5,r7} -+ ldmia r2,{r2,r4,r6,r8} -+ -+CPDO_suf_l: -+ cmp r7,#0x7fffffff -+ cmpne r8,#0x7fffffff -+ beq CPDO_suf_extra -+ -+ cmp r1,r2 -+ bne CPDO_adf_s -+ -+CPDO_suf_s: -+ subs r2,r7,r8 @ determine greater number -+ bgt CPDO_suf_2nd @ first number is greater -+ blt CPDO_suf_1st @ second number is greater -+ cmp r3,r4 @ also mantissa is important -+ cmpeq r5,r6 -+ bhi CPDO_suf_2nd @ first number is greater -+ beq CPDO_zero -+ -+CPDO_suf_1st: -+ eor r1,r1,#0x80000000 @ second number is greater, invert sign -+ mov r7,r8 -+ rsb r2,r2,#0 -+ cmp r2,#32 -+ ble CPDO_suf_1st2 -+ -+ sub r2,r2,#32 -+ cmp r2,#32 -+ movgt r2,#32 -+ mov r5,r3,lsr r2 -+ mov r3,#0 -+ b CPDO_suf_1st_sub -+ -+CPDO_suf_1st2: -+ rsb r8,r2,#32 -+ mov r5,r5,lsr r2 -+ orr r5,r5,r3,lsl r8 -+ mov r3,r3,lsr r2 @ 1. op normalized -+ -+CPDO_suf_1st_sub: -+ subs r5,r6,r5 @ do subtraction -+ sbc r3,r4,r3 -+ b CPDO_suf_norm -+ -+CPDO_suf_2nd: -+ cmp r2,#32 -+ ble CPDO_suf_2nd2 -+ -+ sub r2,r2,#32 -+ cmp r2,#32 -+ movgt r2,#32 -+ mov r6,r4,lsr r2 -+ mov r4,#0 -+ b CPDO_suf_2nd_sub -+ -+CPDO_suf_2nd2: -+ rsb r8,r2,#32 -+ mov r6,r6,lsr r2 -+ orr r6,r6,r4,lsl r8 -+ mov r4,r4,lsr r2 @ 2. op normalized -+ -+CPDO_suf_2nd_sub: -+ subs r5,r5,r6 -+ sbc r3,r3,r4 @ do subtraction -+ -+CPDO_suf_norm: -+ teq r3,#0 @ normalize 32bit -+ moveq r3,r5 -+ moveq r5,#0 -+ subeq r7,r7,#32 -+ -+ cmp r3,#0x00010000 @ 16bit -+ movcc r3,r3,lsl#16 -+ orrcc r3,r3,r5,lsr#16 -+ movcc r5,r5,lsl#16 -+ subcc r7,r7,#16 -+ -+ cmp r3,#0x01000000 @ 8bit -+ movcc r3,r3,lsl#8 -+ orrcc r3,r3,r5,lsr#24 -+ movcc r5,r5,lsl#8 -+ subcc r7,r7,#8 -+ -+ cmp r3,#0x10000000 @ 4bit -+ movcc r3,r3,lsl#4 -+ orrcc r3,r3,r5,lsr#28 -+ movcc r5,r5,lsl#4 -+ subcc r7,r7,#4 -+ -+ cmp r3,#0x40000000 @ 2bit -+ movcc r3,r3,lsl#2 -+ orrcc r3,r3,r5,lsr#30 -+ movcc r5,r5,lsl#2 -+ subcc r7,r7,#2 -+ -+ cmp r3,#0x80000000 @ 1bit -+ movcc r3,r3,lsl#1 -+ orrcc r3,r3,r5,lsr#31 -+ movcc r5,r5,lsl#1 -+ subcc r7,r7,#1 -+ -+ cmp r7,#0xe0000000 -+ ble CPDO_zero_1 -+ -+ stmia r0,{r1,r3,r5,r7} -+ b fastfpe_next -+ -+CPDO_suf_extra: -+ cmp r7,#0x7fffffff @ was it the 1st ? -+ eorne r2,r2,#0x80000000 @ change sign, might have been INF -+ bne CPDO_infnan_2 @ no it was the 2nd -+ cmp r8,#0x7fffffff @ if 1st, 2nd too ? -+ bne CPDO_infnan_1 @ no only 1st -+ cmp r3,#0 -+ cmpeq r4,#0 -+ bne CPDO_nan_12 -+ b CPDO_nan @ here is difference with adf ! -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDO_rsf -+CPDO_rsf: -+ mov r3,r2 -+ ldmia r1,{r2,r4,r6,r8} -+ ldmia r3,{r1,r3,r5,r7} -+ b CPDO_suf_l -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDO_muf -+CPDO_muf: -+ ldmia r1,{r1,r3,r5,r7} -+ ldmia r2,{r2,r4,r6,r8} -+ -+ cmp r7,#0x7fffffff -+ cmpne r8,#0x7fffffff -+ beq CPDO_muf_extra -+ -+ eor r1,r1,r2 -+ adds r8,r7,r8 -+ bvs CPDO_zero_1 -+ -+ umull r7,r2,r3,r4 -+ umull r14,r3,r6,r3 -+ adds r7,r7,r3 @ r2|r7|r14 = r2|r7|#0 + #0|r3|r14 -+ adc r2,r2,#0 -+ umull r4,r3,r5,r4 -+ adds r14,r14,r4 @ r2|r7|r14 += #0|r3|r4 -+ adcs r7,r7,r3 -+ adc r2,r2,#0 -+ umull r4,r3,r5,r6 -+ adds r14,r14,r3 @ r2|r7|r14 += #0|#0|r3 -+ adcs r7,r7,#0 -+ adcs r2,r2,#0 -+ -+ bpl CPDO_muf_norm -+ -+ add r8,r8,#1 -+ b CPDO_muf_end -+ -+CPDO_muf_norm: -+ adds r14,r14,r14 -+ adcs r7,r7,r7 -+ adcs r2,r2,r2 -+ -+CPDO_muf_end: -+ cmp r8,#0x20000000 -+ bge CPDO_inf -+ cmp r8,#0xe0000000 -+ ble CPDO_zero_1 -+ stmia r0,{r1,r2,r7,r8} -+ b fastfpe_next -+ -+CPDO_muf_extra: -+ cmp r7,#0x7fffffff @ was it the first? -+ bne CPDO_muf_extra_2nd @ no, so it was the second -+ cmp r8,#0x7fffffff @ yes, second too? -+ bne CPDO_muf_extra_1st @ no, only first -+ orr r3,r3,r4 @ if both inf -> inf, otherwise nan -+ eor r1,r1,r2 @ sign for the inf case -+ b CPDO_infnan_1 -+ -+CPDO_muf_extra_1st: -+ cmp r3,#0 @ is it a nan? -+ bne CPDO_infnan_1 -+ cmp r8,#0x80000000 @ is the second 0? -+ beq CPDO_nan -+ eor r1,r1,r2 @ correct sign for inf -+ b CPDO_inf -+ -+CPDO_muf_extra_2nd: -+ cmp r4,#0 @ is it a nan? -+ bne CPDO_infnan_2 -+ cmp r7,#0x80000000 @ is the first 0? -+ beq CPDO_nan -+ eor r1,r1,r2 @ correct sign for inf -+ b CPDO_inf -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDO_dvf -+CPDO_dvf: -+ ldmia r1,{r1,r3,r5,r7} -+ ldmia r2,{r2,r4,r6,r8} -+ -+CPDO_dvf_l: -+ cmp r7,#0x7fffffff -+ cmpne r8,#0x7fffffff -+ beq CPDO_dvf_extra -+ cmp r8,#0x80000000 -+ beq CPDO_dvf_by0 -+ -+ eor r1,r1,r2 -+ cmp r7,#0x80000000 -+ beq CPDO_zero_1 -+ -+ sub r8,r7,r8 -+ -+ mov r2,#0 -+ mov r7,#1 -+ -+ cmp r3,r4 -+ cmpeq r5,r6 -+ bcs CPDO_dvf_loop_ -+ -+ sub r8,r8,#1 -+ -+CPDO_dvf_loop: -+ adds r5,r5,r5 -+ adcs r3,r3,r3 -+ bcs CPDO_dvf_anyway -+CPDO_dvf_loop_: -+ subs r5,r5,r6 -+ sbcs r3,r3,r4 -+ bcs CPDO_dvf_okay -+ -+ adds r5,r5,r6 -+ adc r3,r3,r4 -+ adds r7,r7,r7 -+ adcs r2,r2,r2 -+ bcc CPDO_dvf_loop -+ b CPDO_dvf_end -+ -+CPDO_dvf_anyway: -+ adcs r7,r7,r7 -+ adcs r2,r2,r2 -+ bcs CPDO_dvf_end -+ subs r5,r5,r6 -+ sbc r3,r3,r4 -+ b CPDO_dvf_loop -+ -+CPDO_dvf_okay: -+ adcs r7,r7,r7 -+ adcs r2,r2,r2 -+ bcc CPDO_dvf_loop -+ -+CPDO_dvf_end: -+ b CPDO_muf_end -+ -+CPDO_dvf_by0: -+ cmp R7,#0x80000000 -+ beq CPDO_nan @ first also 0 -> nan -+ eor r1,r1,r2 @ otherwise calculatesign for inf -+ b CPDO_inf -+ -+CPDO_dvf_extra: -+ cmp r7,#0x7fffffff @ was it the first? -+ bne CPDO_dvf_extra_2nd @ no, so it was the second -+ cmp r8,#0x7fffffff @ yes, second too? -+ bne CPDO_dvf_extra_1st @ no, only first -+ orrs r3,r3,r4 -+ beq CPDO_nan @ if both inf -> create nan -+ b CPDO_nan_12 @ otherwise keep nan -+ -+CPDO_dvf_extra_1st: -+ eor r1,r1,r2 @ correct sign for inf -+ b CPDO_infnan_1 -+ -+CPDO_dvf_extra_2nd: -+ cmp r4,#0 @ is it a nan? -+ bne CPDO_infnan_2 -+ eor r1,r1,r2 @ correct sign for zero -+ b CPDO_zero_1 -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDO_rdf -+CPDO_rdf: -+ mov r3,r2 -+ ldmia r1,{r2,r4,r6,r8} -+ ldmia r3,{r1,r3,r5,r7} -+ b CPDO_dvf_l -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDO_rmf -+CPDO_rmf: -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDO_mvf -+CPDO_mvf: -+ ldmia r2,{r1,r2,r3,r4} -+ stmia r0,{r1,r2,r3,r4} -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDO_mnf -+CPDO_mnf: -+ ldmia r2,{r1,r2,r3,r4} -+ eor r1,r1,#0x80000000 -+ stmia r0,{r1,r2,r3,r4} -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDO_abs -+CPDO_abs: -+ ldmia r2,{r1,r2,r3,r4} -+ bic r1,r1,#0x80000000 -+ stmia r0,{r1,r2,r3,r4} -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDO_sqt -+CPDO_sqt: -+ ldmia r2,{r1,r2,r3,r4} -+ cmp r1,#0 -+ bne CPDO_nan -+ cmp r4,#0x7fffffff -+ beq CPDO_store_1234 -+ -+ tst r4,r4,lsr#1 @carry=exponent bit 0 -+ bcc CPDO_sqt_exponenteven -+ adds r3,r3,r3 -+ adcs r2,r2,r2 @carry is needed in loop! -+CPDO_sqt_exponenteven: -+ mov r4,r4,asr #1 -+ str r4,[r0,#12] -+ -+ mov r4,#0x80000000 -+ mov r5,#0 -+ sub r2,r2,#0x80000000 -+ -+ mov r8,#0x40000000 -+ mov r14,#0x80000000 -+ -+ mov r1,#1 -+ b CPDO_sqt_loop1_first -+CPDO_sqt_loop1: -+ adds r3,r3,r3 -+ adcs r2,r2,r2 -+CPDO_sqt_loop1_first: -+ add r6,r4,r8,lsr r1 @r7 const = r5 -+ bcs CPDO_sqt_loop1_1 -+ cmp r2,r6 -+ cmpeq r3,r5 @r5 for r7 -+ bcc CPDO_sqt_loop1_0 -+CPDO_sqt_loop1_1: -+ orr r4,r4,r14,lsr r1 -+ subs r3,r3,r5 @r5 for r7 -+ sbc r2,r2,r6 -+CPDO_sqt_loop1_0: -+ add r1,r1,#1 -+ cmp r1,#30 -+ ble CPDO_sqt_loop1 -+ -+ adds r3,r3,r3 -+ adcs r2,r2,r2 -+ bcs CPDO_sqt_between_1 -+ adds r7,r5,#0x80000000 -+ adc r6,r4,#0 -+ cmp r2,r6 -+ cmpeq r3,r7 -+ bcc CPDO_sqt_between_0 -+CPDO_sqt_between_1: -+ orr r4,r4,#0x00000001 -+ subs r3,r3,r5 -+ sbc r2,r2,r4 -+ subs r3,r3,#0x80000000 -+ sbc r2,r2,#0 -+CPDO_sqt_between_0: -+ mov r1,#0 -+ -+CPDO_sqt_loop2: -+ adds r3,r3,r3 -+ adcs r2,r2,r2 -+ bcs CPDO_sqt_loop2_1 -+ adds r7,r5,r8,lsr r1 -+ adc r6,r4,#0 -+ cmp r2,r6 -+ cmpeq r3,r7 -+ bcc CPDO_sqt_loop2_0 -+CPDO_sqt_loop2_1: -+ orr r5,r5,r14,lsr r1 -+ subs r3,r3,r5 -+ sbc r2,r2,r4 -+ subs r3,r3,r8,lsr r1 -+ sbc r2,r2,#0 -+CPDO_sqt_loop2_0: -+ add r1,r1,#1 -+ cmp r1,#30 -+ ble CPDO_sqt_loop2 -+ -+ adds r3,r3,r3 -+ adcs r2,r2,r2 -+ bcs CPDO_sqt_after_1 -+ cmp r2,r6 -+ cmpeq r3,r7 -+ bcc CPDO_sqt_after_0 -+CPDO_sqt_after_1: -+ orr r5,r5,#0x00000001 -+CPDO_sqt_after_0: -+ -+ mov r1,#0 -+ stmia r0,{r1,r4,r5} -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDO_rnd -+CPDO_rnd: -+ ldmia r2,{r1,r2,r3,r5} -+ bl CPDO_rnd_core -+ -+CPDO_rnd_store: -+ stmia r0,{r1,r2,r3,r5} -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDO_rnd_core -+CPDO_rnd_core: -+ and r4,r4,#0x00000060 -+ add pc,pc,r4,lsr#3 -+ mov r0,r0 -+ b CPDO_rnd_N -+ b CPDO_rnd_P -+ b CPDO_rnd_M -+ b CPDO_rnd_Z -+ -+CPDO_rnd_N: -+ cmp r5,#-1 -+ blt CPDO_rnd_zero -+ cmp r5,#63 -+ movge pc,r14 -+ mov r4,#0x40000000 -+ cmp r5,#31 -+ bge CPDO_rnd_N_2 -+ -+ adds r2,r2,r4,lsr r5 -+ bcc CPDO_rnd_end -+ b CPDO_rnd_end_norm -+ -+CPDO_rnd_N_2: -+CPDO_rnd_P_2: -+ sub r6,r5,#32 -+ adds r3,r3,r4,ror r6 @ror ist needed to handle a -1 correctly -+ adcs r2,r2,#0 -+ bcc CPDO_rnd_end -+ b CPDO_rnd_end_norm -+ -+CPDO_rnd_P: -+ tst r1,#0x80000000 -+ bne CPDO_rnd_M_entry -+CPDO_rnd_P_entry: -+ cmp r5,#0 -+ blt CPDO_rnd_P_small -+ cmp r5,#63 -+ movge pc,r14 -+ mov r4,#0x7fffffff -+ cmp r5,#32 -+ bge CPDO_rnd_P_2 -+ -+ adds r3,r3,#0xffffffff -+ adcs r2,r2,r4,lsr r5 -+ bcc CPDO_rnd_end -+ b CPDO_rnd_end_norm -+ -+CPDO_rnd_P_small: -+ cmp r5,#0x80000000 -+ moveq pc,r14 -+ b CPDO_rnd_one -+ -+CPDO_rnd_M: -+ tst r1,#0x80000000 -+ bne CPDO_rnd_P_entry -+CPDO_rnd_M_entry: -+ cmp r5,#0 -+ blt CPDO_rnd_zero -+ cmp r5,#63 -+ movge pc,r14 -+ -+ b CPDO_rnd_end -+ -+CPDO_rnd_Z: -+ cmp r5,#0 -+ blt CPDO_rnd_zero -+ cmp r5,#63 -+ movge pc,r14 -+ b CPDO_rnd_end -+ -+CPDO_rnd_end_norm: -+ add r5,r5,#1 -+ movs r2,r2,rrx -+ mov r3,r3,rrx -+CPDO_rnd_end: -+ rsbs r4,r5,#31 -+ bmi CPDO_rnd_end_2 -+ mov r3,#0 -+ mov r2,r2,lsr r4 -+ mov r2,r2,lsl r4 -+ mov pc,r14 -+ -+CPDO_rnd_end_2: -+ rsb r4,r5,#63 -+ mov r3,r3,lsr r4 -+ mov r3,r3,lsl r4 -+ mov pc,r14 -+ -+CPDO_rnd_one: -+ mov r2,#0x80000000 -+ mov r3,#0 -+ mov r5,#0 -+ mov pc,r14 -+ -+CPDO_rnd_zero: -+ mov r1,#0 -+ mov r2,#0 -+ mov r3,#0 -+ mov r5,#0x80000000 -+ mov pc,r14 -+ -+/*---------------------------------------------------------------------------*/ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/fastfpe/CPRT.S 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,185 @@ -+/* -+The FP structure has 4 words reserved for each register, the first is used -+just -+for the sign in bit 31, the second and third are for the mantissa (unsigned -+integer, high 32 bit first) and the fourth is the exponent (signed integer). -+The mantissa is always normalized. -+ -+If the exponent is 0x80000000, that is the most negative value, the number -+represented is 0 and both mantissa words are also 0. -+ -+If the exponent is 0x7fffffff, that is the biggest positive value, the -+number -+represented is infinity if the high 32 mantissa bit are also 0, otherwise it -+is -+a NaN. The low 32 mantissa bit are 0 if the number represented is infinity. -+ -+Decimal and packed decimal numbers are not supported yet. -+*/ -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .text -+ .globl CPRT_flt -+CPRT_flt: -+ add r0,r13,r0,lsr#10 -+ ldr r2,[r0] -+ mov r3,#0 -+ cmp r2,#0 -+ beq CPRT_flt_zero -+ -+ ands r0,r2,#0x80000000 -+ rsbne r2,r2,#0 -+ mov r4,#31 -+ -+ cmp r2,#0x00010000 -+ movcc r2,r2,lsl#16 -+ subcc r4,r4,#16 -+ -+ cmp r2,#0x01000000 -+ movcc r2,r2,lsl#8 -+ subcc r4,r4,#8 -+ -+ cmp r2,#0x10000000 -+ movcc r2,r2,lsl#4 -+ subcc r4,r4,#4 -+ -+ cmp r2,#0x40000000 -+ movcc r2,r2,lsl#2 -+ subcc r4,r4,#2 -+ -+ cmp r2,#0x80000000 -+ movcc r2,r2,lsl#1 -+ subcc r4,r4,#1 -+ -+ stmia r1,{r0,r2,r3,r4} -+ b fastfpe_next -+ -+CPRT_flt_zero: -+ mov r0,#0 -+ mov r4,#0x80000000 -+ stmia r1,{r0,r2,r3,r4} -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPRT_fix -+CPRT_fix: -+ ldmia r2,{r1,r2,r3,r5} -+ bl CPDO_rnd_core -+ -+CPRT_back: -+ add r0,r13,r0,lsr#10 -+ cmp r5,#0 -+ blt CPRT_int_zero -+ cmp r5,#30 -+ bgt CPRT_overflow -+ -+ rsb r5,r5,#31 -+ mov r2,r2,lsr r5 -+ tst r1,#0x80000000 -+ rsbne r2,r2,#0 -+ -+ str r2,[r0] -+ b fastfpe_next -+ -+CPRT_int_zero: -+ mov r2,#0 -+ str r2,[r0] -+ b fastfpe_next -+ -+CPRT_overflow: -+ mov r2,#0x80000000 -+ tst r1,#0x80000000 -+ subeq r2,r2,#1 -+ str r2,[r0] -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPRT_wfs -+CPRT_wfs: -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPRT_rfs -+CPRT_rfs: -+ add r0,r13,r0,lsr#10 -+ mov r1,#0x02000000 @ Software Emulation, not Acorn FPE -+ str r1,[r0] -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPRT_cmf -+CPRT_cmf: -+ ldmia r1,{r1,r3,r5,r7} -+ ldmia r2,{r2,r4,r6,r8} -+ -+CPRT_cmf_e: -+ ldr r0,[r13,#16*4] -+ -+ cmp r7,#0x7fffffff -+ bic r0,r0,#0xf0000000 -+ -+ cmpeq r3,#0xffffffff -+ beq CPRT_cmf_unordered -+ cmp r8,#0x7fffffff -+ cmpeq r4,#0xffffffff -+ beq CPRT_cmf_unordered -+ -+ cmp r1,r2 -+ beq CPRT_cmf_equalsign -+ b CPRT_cmf_sign -+ -+CPRT_cmf_equalsign: -+ cmp r7,r8 -+ beq CPRT_cmf_equalexponent -+ bgt CPRT_cmf_sign -+ b CPRT_cmf_signb -+ -+CPRT_cmf_equalexponent: -+ cmp r3,r4 -+ cmpeq r5,r6 -+ beq CPRT_cmf_equal -+ bhi CPRT_cmf_sign -+ b CPRT_cmf_signb -+ -+CPRT_cmf_sign: -+ cmp r7,#0x80000000 @ (0.0 == -0.0)? -+ cmpeq r7,r8 -+ beq CPRT_cmf_equal -+ tst r1,#0x80000000 -+ orreq r0,r0,#0x20000000 -+ orrne r0,r0,#0x80000000 -+ str r0,[r13,#16*4] -+ b fastfpe_next -+ -+CPRT_cmf_signb: -+ tst r1,#0x80000000 -+ orrne r0,r0,#0x20000000 -+ orreq r0,r0,#0x80000000 -+ str r0,[r13,#16*4] -+ b fastfpe_next -+ -+CPRT_cmf_equal: -+ orr r0,r0,#0x60000000 -+ str r0,[r13,#16*4] -+ b fastfpe_next -+ -+CPRT_cmf_unordered: -+ orr r0,r0,#0x10000000 -+ str r0,[r13,#16*4] -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPRT_cnf -+CPRT_cnf: -+ ldmia r1,{r1,r3,r5,r7} -+ ldmia r2,{r2,r4,r6,r8} -+ eor r2,r2,#0x80000000 -+ b CPRT_cmf_e -+ -+/*---------------------------------------------------------------------------*/ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/fastfpe/CPDT.S 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,430 @@ -+/* -+The FP structure has 4 words reserved for each register, the first is used just -+for the sign in bit 31, the second and third are for the mantissa (unsigned -+integer, high 32 bit first) and the fourth is the exponent (signed integer). -+The mantissa is always normalized. -+ -+If the exponent is 0x80000000, that is the most negative value, the number -+represented is 0 and both mantissa words are also 0. -+ -+If the exponent is 0x7fffffff, that is the biggest positive value, the number -+represented is infinity if the high 32 mantissa bit are also 0, otherwise it is -+a NaN. The low 32 mantissa bit are 0 if the number represented is infinity. -+ -+Decimal and packed decimal numbers are not supported yet. -+*/ -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDT_load_single -+CPDT_load_single: -+ ldr r1,[r6] -+ -+ and r2,r1,#0x80000000 @ r2 = sign -+ -+ mov r5,r1,lsr#23 -+ bics r5,r5,#0x100 -+ beq CPDT_ls_e0 @ exponent = 0; zero/denormalized -+ teq r5,#255 -+ beq CPDT_ls_e255 @ exponent = 255; infinity/NaN -+ -+ sub r5,r5,#127 @ r5 = exponent, remove normalized bias -+ -+ mov r3,r1,lsl#8 -+ orr r3,r3,#0x80000000 -+ mov r4,#0 @ r3,r4 = mantissa -+ -+ stmia r0,{r2-r5} -+ b fastfpe_next -+ -+CPDT_ls_e0: -+ movs r3,r1,lsl#9 -+ beq CPDT_load_zero -+ -+ mov r5,#-127 -+ -+CPDT_ls_e0_norm: -+ tst r3,#0x80000000 -+ subeq r5,r5,#1 -+ moveq r3,r3,lsl#1 -+ beq CPDT_ls_e0_norm -+ -+ mov r4,#0 -+ stmia r0,{r2-r5} -+ b fastfpe_next -+ -+CPDT_ls_e255: -+ mov r3,r1,lsl#9 -+ mov r4,#0 -+ mov r5,#0x7fffffff -+ stmia r0,{r2-r5} -+ b fastfpe_next -+ -+CPDT_load_zero: -+ mov r3,#0 -+ mov r4,#0 -+ mov r5,#0x80000000 -+ stmia r0,{r2-r5} -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDT_load_double -+CPDT_load_double: -+ ldr r1,[r6] -+ ldr r6,[r6,#4] -+ -+ and r2,r1,#0x80000000 @ r2 = sign -+ -+ mov r5,r1,lsr#20 -+ bics r5,r5,#0x800 -+ beq CPDT_ld_e0 @ exponent = 0; zero/denormalized -+ add r4,r5,#1 -+ teq r4,#2048 -+ beq CPDT_ld_e2047 @ exponent = 2047; infinity/NaN -+ -+ add r5,r5,#1 -+ sub r5,r5,#1024 @ r5 = exponent, remove normalized bias -+ -+ mov r3,r1,lsl#11 -+ orr r3,r3,#0x80000000 -+ orr r3,r3,r6,lsr #21 -+ mov r4,r6,lsl#11 @ r3,r4 = mantissa -+ -+ stmia r0,{r2-r5} -+ b fastfpe_next -+ -+CPDT_ld_e0: -+ mov r3,r1,lsl#12 -+ orr r3,r3,r6,lsr#20 -+ movs r4,r6,lsl#12 -+ teqeq r3,#0 -+ beq CPDT_load_zero -+ -+ mov r5,#1 -+ sub r5,r5,#1024 -+ -+CPDT_ld_e0_norm: -+ tst r3,#0x80000000 -+ subeq r5,r5,#1 -+ moveqs r4,r4,lsl#1 -+ adceq r3,r3,r3 -+ beq CPDT_ld_e0_norm -+ -+ stmia r0,{r2-r5} -+ b fastfpe_next -+ -+CPDT_ld_e2047: -+ mov r3,r1,lsl#12 -+ orr r3,r3,r6,lsr#1 -+ bic r6,r6,#0x80000000 -+ orr r3,r3,r6 @ to get all fraction bits ! -+ mov r4,#0 -+ mov r5,#0x7fffffff -+ stmia r0,{r2-r5} -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDT_load_extended -+CPDT_load_extended: -+ ldr r1,[r6] -+ ldr r3,[r6,#4] -+ ldr r4,[r6,#8] -+ -+ and r2,r1,#0x80000000 -+ bics r5,r1,#0x80000000 -+ beq CPDT_le_e0 -+ add r1,r5,#1 -+ teq r4,#32768 -+ beq CPDT_le_e32767 -+ -+ add r5,r5,#1 -+ sub r5,r5,#16384 -+ -+ stmia r0,{r2-r5} -+ b fastfpe_next -+ -+CPDT_le_e0: -+ teq r3,#0 -+ teqeq r4,#0 -+ beq CPDT_load_zero -+ -+ mov r5,#2 -+ sub r5,r5,#16384 -+ b CPDT_ld_e0_norm -+ -+CPDT_le_e32767: -+ mov r3,r3,lsl#1 -+ orr r3,r3,r4,lsr#1 -+ bic r4,r4,#0x80000000 -+ orr r3,r3,r4 -+ mov r5,#0x7fffffff -+ stmia r0,{r2-r5} -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDT_load_decimal -+CPDT_load_decimal: -+ -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDT_store_single -+CPDT_store_single: -+ ldmia r0,{r1-r4} -+ -+ cmp r4,#-127 -+ ble CPDT_ss_e0 -+ cmp r4,#128 -+ bge CPDT_ss_e255 -+ -+ adds r2,r2,#1<<7 @ round to nearest -+ bcs CPDT_ss_rnd_ovfl @ very very seldom taken -+ -+CPDT_ss_store: -+ add r4,r4,#127 -+ orr r1,r1,r4,lsl#23 -+ -+ bic r2,r2,#0x80000000 -+ orr r1,r1,r2,lsr#8 -+ -+ str r1,[r6] -+ b fastfpe_next -+ -+CPDT_ss_rnd_ovfl: -+ add r4,r4,#1 -+ cmp r4,#128 -+ bge CPDT_ss_e255 -+ -+ mov r2,#0x80000000 -+ mov r3,#0 -+ b CPDT_ss_store -+ -+CPDT_ss_e0: -+ cmp r4,#-150 -+ ble CPDT_ss_zero -+ -+ add r4,r4,#126 -+CPDT_ss_unnormalize: -+ mov r2,r2,lsr#1 -+ adds r4,r4,#1 -+ bne CPDT_ss_unnormalize -+ -+ orr r1,r1,r2,lsr#8 -+ -+CPDT_ss_zero: -+ str r1,[r6] -+ b fastfpe_next -+ -+CPDT_ss_e255: -+ cmp r4,#0x7fffffff -+ bne CPDT_ss_inf -+ cmp r2,#0 -+ beq CPDT_ss_inf -+ -+ orr r1,r1,#0x00200000 @ for safety so that it is not INF -+ orr r1,r1,r2,lsr#9 @ get highest bit of mantissa -+ -+CPDT_ss_inf: -+ orr r1,r1,#0x7f000000 -+ orr r1,r1,#0x00800000 -+ str r1,[r6] -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDT_store_double -+CPDT_store_double: -+ ldmia r0,{r1-r4} -+ -+ cmp r4,#1024 @ this check has to be first, or -+ bge CPDT_sd_e2047 @ overflow can occur on second ! -+ add r0,r4,#3 -+ cmp r0,#-1023+3 @ cmp with -1023 -+ ble CPDT_sd_e0 -+ -+ adds r3,r3,#1<<10 @ round to nearest -+ adcs r2,r2,#0 -+ bcs CPDT_sd_rnd_ovfl @ very very seldom taken -+ -+CPDT_sd_store: -+ sub r4,r4,#1 -+ add r4,r4,#1024 -+ orr r1,r1,r4,lsl#20 -+ -+ bic r2,r2,#0x80000000 -+ orr r1,r1,r2,lsr#11 -+ -+ mov r2,r2,lsl#21 -+ orr r2,r2,r3,lsr#11 -+ -+ stmia r6,{r1,r2} -+ b fastfpe_next -+ -+CPDT_sd_rnd_ovfl: -+ add r4,r4,#1 -+ cmp r4,#1024 -+ bge CPDT_sd_e2047 -+ -+ mov r2,#0x80000000 -+ mov r3,#0 -+ b CPDT_sd_store -+ -+CPDT_sd_e0: -+ add r0,r4,#1075-1024 -+ cmp r0,#-1024 -+ ble CPDT_sd_zero -+ -+ add r4,r4,#1024 -+ sub r4,r4,#2 -+CPDT_sd_unnormalize: -+ movs r2,r2,lsr#1 -+ mov r3,r3,rrx -+ adds r4,r4,#1 -+ bne CPDT_sd_unnormalize -+ -+ orr r1,r1,r2,lsr#11 -+ mov r2,r2,lsl#21 -+ orr r2,r2,r3,lsr#11 -+ -+ stmia r6,{r1,r2} -+ b fastfpe_next -+ -+CPDT_sd_zero: -+ mov r2,#0 -+ stmia r6,{r1,r2} -+ b fastfpe_next -+ -+CPDT_sd_e2047: -+ cmp r4,#0x7fffffff -+ bne CPDT_sd_inf -+ cmp r2,#0 -+ beq CPDT_sd_inf -+ -+ orr r1,r1,#0x00040000 @ for safety so that it is not INF -+ orr r1,r1,r2,lsr#12 @ get highest bit of mantissa -+ -+CPDT_sd_inf: -+ orr r1,r1,#0x7f000000 -+ orr r1,r1,#0x00f00000 -+ stmia r6,{r1,r2} -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDT_store_extended -+CPDT_store_extended: -+ ldmia r0,{r1-r4} -+ -+ cmp r4,#16384 @ this check has to be first, or -+ bge CPDT_se_e32767 @ overflow can occur with second ! -+ add r0,r4,#63 -+ cmp r0,#-16383+63 -+ ble CPDT_se_e0 -+ -+ sub r4,r4,#1 -+ add r4,r4,#16384 -+ orr r1,r1,r4 -+ -+ stmia r6,{r1-r3} -+ b fastfpe_next -+ -+CPDT_se_e0: -+ add r0,r4,#16446-16384 -+ cmp r0,#-16384 -+ ble CPDT_se_zero -+ -+ add r4,r4,#16384 -+ sub r4,r4,#2 -+CPDT_se_unnormalize: -+ movs r2,r2,lsr#1 -+ mov r3,r3,rrx -+ adds r4,r4,#1 -+ bne CPDT_se_unnormalize -+ -+ stmia r6,{r1-r3} -+ b fastfpe_next -+ -+CPDT_se_zero: -+ mov r2,#0 -+ mov r3,#0 -+ stmia r6,{r1-r3} -+ b fastfpe_next -+ -+CPDT_se_e32767: -+ cmp r4,#0x7fffffff -+ bne CPDT_se_inf -+ cmp r2,#0 -+ beq CPDT_se_inf -+ -+ mov r2,r2,lsl#1 -+ orr r2,r2,#0x20000000 -+ -+CPDT_se_inf: -+ orr r1,r1,#0x00007f00 -+ orr r1,r1,#0x000000ff -+ stmia r6,{r1-r3} -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDT_store_decimal -+CPDT_store_decimal: -+ -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDT_sfm -+CPDT_sfm: -+ add r2,r10,r0,lsr#8 -+ ldr r4,[r2,#0] -+ ldr r3,[r2,#4] -+ bic r3,r3,#0x80000000 -+ orr r3,r3,r4 -+ str r3,[r6],#4 -+ ldr r3,[r2,#8] -+ str r3,[r6],#4 -+ ldr r3,[r2,#12] -+ str r3,[r6],#4 -+ -+ add r0,r0,#1<<12 -+ and r0,r0,#7<<12 -+ subs r1,r1,#1 -+ bne CPDT_sfm -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ -+ -+ .globl CPDT_lfm -+CPDT_lfm: -+ add r2,r10,r0,lsr#8 -+ ldr r4,[r6],#4 -+ and r3,r4,#0x80000000 -+ str r3,[r2,#0] -+ ldr r3,[r6],#4 -+ str r3,[r2,#8] -+ ldr r3,[r6],#4 -+ str r3,[r2,#12] -+ -+ cmp r3,#0x80000000 @ does the exp indicate zero? -+ biceq r4,r4,#0x80000000 @ if so, indicate 'denormalized' -+ beq CPDT_lfm_storer4 -+ cmp r3,#0x7fffffff @ does the exp indicate inf or NaN? -+ biceq r4,r4,#0x80000000 @ if so, indicate 'denormalized' -+ beq CPDT_lfm_storer4 -+ orrne r4,r4,#0x80000000 @ otherwise, set normalized bit -+ -+CPDT_lfm_storer4: -+ str r4,[r2,#4] -+ -+ add r0,r0,#1<<12 -+ and r0,r0,#7<<12 -+ subs r1,r1,#1 -+ bne CPDT_lfm -+ b fastfpe_next -+ -+/*---------------------------------------------------------------------------*/ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/fastfpe/Makefile 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,14 @@ -+# -+# linux/arch/arm/fastfpe/Makefile -+# -+# Copyright (C) Peter Teichmann -+# -+ -+obj-y := -+obj-m := -+obj-n := -+obj- := -+ -+fastfpe-objs := module.o entry.o CPDO.o CPRT.o CPDT.o -+ -+obj-$(CONFIG_FPE_FASTFPE) += fastfpe.o ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/common/rtctime.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,482 @@ -+/* -+ * linux/arch/arm/common/rtctime.c -+ * -+ * Copyright (C) 2003 Deep Blue Solutions Ltd. -+ * Based on sa1100-rtc.c, Nils Faerber, CIH, Nicolas Pitre. -+ * Based on rtc.c by Paul Gortmaker -+ * -+ * 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 -+ -+static DECLARE_WAIT_QUEUE_HEAD(rtc_wait); -+static struct fasync_struct *rtc_async_queue; -+ -+/* -+ * rtc_lock protects rtc_irq_data -+ */ -+static spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; -+static unsigned long rtc_irq_data; -+ -+/* -+ * rtc_sem protects rtc_inuse and rtc_ops -+ */ -+static DECLARE_MUTEX(rtc_sem); -+static unsigned long rtc_inuse; -+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; -+} -+ -+/* -+ * Convert Gregorian date to seconds since 01-01-1970 00:00:00. -+ */ -+int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) -+{ -+ unsigned int yrs = tm->tm_year + 1900; -+ -+ *time = 0; -+ -+ if (yrs < 1970 || -+ tm->tm_mon >= 12 || -+ tm->tm_mday < 1 || -+ tm->tm_mday > month_days(tm->tm_mon, yrs) || -+ tm->tm_hour >= 24 || -+ tm->tm_min >= 60 || -+ tm->tm_sec >= 60) -+ return -EINVAL; -+ -+ *time = mktime(yrs, tm->tm_mon + 1, tm->tm_mday, -+ tm->tm_hour, tm->tm_min, tm->tm_sec); -+ -+ return 0; -+} -+ -+/* -+ * Calculate the next alarm time given the requested alarm time mask -+ * and the current time. -+ * -+ * FIXME: for now, we just copy the alarm time because we're lazy (and -+ * is therefore buggy - setting a 10am alarm at 8pm will not result in -+ * the alarm triggering.) -+ */ -+void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc_time *alrm) -+{ -+ next->tm_year = now->tm_year; -+ next->tm_mon = now->tm_mon; -+ next->tm_mday = now->tm_mday; -+ next->tm_hour = alrm->tm_hour; -+ next->tm_min = alrm->tm_min; -+ next->tm_sec = alrm->tm_sec; -+} -+ -+static inline void rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm) -+{ -+ memset(tm, 0, sizeof(struct rtc_time)); -+ ops->read_time(tm); -+} -+ -+static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm) -+{ -+ return ops->set_time(tm); -+} -+ -+static inline void rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) -+{ -+ memset(alrm, 0, sizeof(struct rtc_wkalrm)); -+ ops->read_alarm(alrm); -+} -+ -+static inline int rtc_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) -+{ -+ return ops->set_alarm(alrm); -+} -+ -+void rtc_update(unsigned long num, unsigned long events) -+{ -+ spin_lock(&rtc_lock); -+ rtc_irq_data = (rtc_irq_data + (num << 8)) | events; -+ spin_unlock(&rtc_lock); -+ -+ wake_up_interruptible(&rtc_wait); -+ kill_fasync(&rtc_async_queue, SIGIO, POLL_IN); -+} -+ -+ -+static ssize_t -+rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ unsigned long data; -+ ssize_t ret; -+ -+ if (count < sizeof(unsigned long)) -+ return -EINVAL; -+ -+ add_wait_queue(&rtc_wait, &wait); -+ do { -+ __set_current_state(TASK_INTERRUPTIBLE); -+ -+ spin_lock_irq(&rtc_lock); -+ data = rtc_irq_data; -+ rtc_irq_data = 0; -+ spin_unlock_irq(&rtc_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_wait, &wait); -+ -+ if (ret == 0) { -+ ret = put_user(data, (unsigned long *)buf); -+ if (ret == 0) -+ ret = sizeof(unsigned long); -+ } -+ return ret; -+} -+ -+static unsigned int rtc_poll(struct file *file, poll_table *wait) -+{ -+ unsigned long data; -+ -+ poll_wait(file, &rtc_wait, wait); -+ -+ spin_lock_irq(&rtc_lock); -+ data = rtc_irq_data; -+ spin_unlock_irq(&rtc_lock); -+ -+ return data != 0 ? POLLIN | POLLRDNORM : 0; -+} -+ -+static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ struct rtc_ops *ops = file->private_data; -+ struct rtc_time tm; -+ struct rtc_wkalrm alrm; -+ int ret; -+ -+ switch (cmd) { -+ case RTC_ALM_READ: -+ rtc_read_alarm(ops, &alrm); -+ ret = copy_to_user((void *)arg, &alrm.time, sizeof(tm)); -+ if (ret) -+ ret = -EFAULT; -+ break; -+ -+ case RTC_ALM_SET: -+ ret = copy_from_user(&alrm.time, (void *)arg, sizeof(tm)); -+ alrm.enabled = 0; -+ alrm.pending = 0; -+ alrm.time.tm_mday = -1; -+ alrm.time.tm_mon = -1; -+ alrm.time.tm_year = -1; -+ alrm.time.tm_wday = -1; -+ alrm.time.tm_yday = -1; -+ alrm.time.tm_isdst = -1; -+ if (ret == 0) -+ ret = rtc_set_alarm(ops, &alrm); -+ else -+ ret = -EFAULT; -+ break; -+ -+ case RTC_RD_TIME: -+ rtc_read_time(ops, &tm); -+ ret = copy_to_user((void *)arg, &tm, sizeof(tm)); -+ if (ret) -+ ret = -EFAULT; -+ break; -+ -+ case RTC_SET_TIME: -+ if (!capable(CAP_SYS_TIME)) { -+ ret = -EACCES; -+ break; -+ } -+ ret = copy_from_user(&tm, (void *)arg, sizeof(tm)); -+ if (ret == 0) -+ ret = rtc_set_time(ops, &tm); -+ else -+ ret = -EFAULT; -+ break; -+ -+#ifndef rtc_epoch -+ case RTC_EPOCH_SET: -+ /* -+ * There were no RTC clocks before 1900. -+ */ -+ if (arg < 1900) { -+ ret = -EINVAL; -+ break; -+ } -+ if (!capable(CAP_SYS_TIME)) { -+ ret = -EACCES; -+ break; -+ } -+ rtc_epoch = arg; -+ ret = 0; -+ break; -+#endif -+ -+ case RTC_EPOCH_READ: -+ ret = put_user(rtc_epoch, (unsigned long *)arg); -+ break; -+ -+ case RTC_WKALM_SET: -+ ret = copy_from_user(&alrm, (void *)arg, sizeof(alrm)); -+ if (ret == 0) -+ ret = rtc_set_alarm(ops, &alrm); -+ else -+ ret = -EFAULT; -+ break; -+ -+ case RTC_WKALM_RD: -+ rtc_read_alarm(ops, &alrm); -+ ret = copy_to_user((void *)arg, &alrm, sizeof(alrm)); -+ if (ret) -+ ret = -EFAULT; -+ break; -+ -+ default: -+ ret = ops->ioctl(cmd, arg); -+ } -+ return ret; -+} -+ -+static int rtc_open(struct inode *inode, struct file *file) -+{ -+ int ret; -+ -+ down(&rtc_sem); -+ -+ if (rtc_inuse) { -+ ret = -EBUSY; -+ } else if (!rtc_ops || !try_module_get(rtc_ops->owner)) { -+ ret = -ENODEV; -+ } else { -+ file->private_data = rtc_ops; -+ -+ ret = rtc_ops->open ? rtc_ops->open() : 0; -+ if (ret == 0) { -+ spin_lock_irq(&rtc_lock); -+ rtc_irq_data = 0; -+ spin_unlock_irq(&rtc_lock); -+ -+ rtc_inuse = 1; -+ } -+ } -+ up(&rtc_sem); -+ -+ return ret; -+} -+ -+static int rtc_release(struct inode *inode, struct file *file) -+{ -+ struct rtc_ops *ops = file->private_data; -+ -+ if (ops->release) -+ ops->release(); -+ -+ spin_lock_irq(&rtc_lock); -+ rtc_irq_data = 0; -+ spin_unlock_irq(&rtc_lock); -+ -+ module_put(rtc_ops->owner); -+ rtc_inuse = 0; -+ -+ return 0; -+} -+ -+static int rtc_fasync(int fd, struct file *file, int on) -+{ -+ return fasync_helper(fd, file, on, &rtc_async_queue); -+} -+ -+static struct file_operations rtc_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .read = rtc_read, -+ .poll = rtc_poll, -+ .ioctl = rtc_ioctl, -+ .open = rtc_open, -+ .release = rtc_release, -+ .fasync = rtc_fasync, -+}; -+ -+static struct miscdevice rtc_miscdev = { -+ .minor = RTC_MINOR, -+ .name = "rtc", -+ .fops = &rtc_fops, -+}; -+ -+ -+static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ struct rtc_ops *ops = data; -+ struct rtc_wkalrm alrm; -+ struct rtc_time tm; -+ char *p = page; -+ int len; -+ -+ rtc_read_time(ops, &tm); -+ -+ p += sprintf(p, -+ "rtc_time\t: %02d:%02d:%02d\n" -+ "rtc_date\t: %04d-%02d-%02d\n" -+ "rtc_epoch\t: %04lu\n", -+ tm.tm_hour, tm.tm_min, tm.tm_sec, -+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, -+ rtc_epoch); -+ -+ rtc_read_alarm(ops, &alrm); -+ p += sprintf(p, "alrm_time\t: "); -+ if ((unsigned int)alrm.time.tm_hour <= 24) -+ p += sprintf(p, "%02d:", alrm.time.tm_hour); -+ else -+ p += sprintf(p, "**:"); -+ if ((unsigned int)alrm.time.tm_min <= 59) -+ p += sprintf(p, "%02d:", alrm.time.tm_min); -+ else -+ p += sprintf(p, "**:"); -+ if ((unsigned int)alrm.time.tm_sec <= 59) -+ p += sprintf(p, "%02d\n", alrm.time.tm_sec); -+ else -+ p += sprintf(p, "**\n"); -+ -+ p += sprintf(p, "alrm_date\t: "); -+ if ((unsigned int)alrm.time.tm_year <= 200) -+ p += sprintf(p, "%04d-", alrm.time.tm_year + 1900); -+ else -+ p += sprintf(p, "****-"); -+ if ((unsigned int)alrm.time.tm_mon <= 11) -+ p += sprintf(p, "%02d-", alrm.time.tm_mon + 1); -+ else -+ p += sprintf(p, "**-"); -+ if ((unsigned int)alrm.time.tm_mday <= 31) -+ p += sprintf(p, "%02d\n", alrm.time.tm_mday); -+ else -+ p += sprintf(p, "**\n"); -+ p += sprintf(p, "alrm_wakeup\t: %s\n", alrm.enabled ? "yes" : "no"); -+ p += sprintf(p, "alrm_pending\t: %s\n", alrm.pending ? "yes" : "no"); -+ -+ if (ops->proc) -+ p += ops->proc(p); -+ -+ len = (p - page) - off; -+ if (len < 0) -+ len = 0; -+ *eof = len <= count; -+ *start = page + off; -+ -+ return len; -+} -+ -+int register_rtc(struct rtc_ops *ops) -+{ -+ int ret = -EBUSY; -+ -+ down(&rtc_sem); -+ if (rtc_ops == NULL) { -+ rtc_ops = ops; -+ -+ ret = misc_register(&rtc_miscdev); -+ if (ret == 0) -+ create_proc_read_entry("driver/rtc", 0, 0, -+ rtc_read_proc, ops); -+ } -+ up(&rtc_sem); -+ -+ return ret; -+} -+ -+void unregister_rtc(struct rtc_ops *rtc) -+{ -+ down(&rtc_sem); -+ if (rtc == rtc_ops) { -+ remove_proc_entry("driver/rtc", NULL); -+ misc_deregister(&rtc_miscdev); -+ rtc_ops = NULL; -+ } -+ up(&rtc_sem); -+} -+ -+EXPORT_SYMBOL(rtc_time_to_tm); -+EXPORT_SYMBOL(rtc_tm_to_time); -+EXPORT_SYMBOL(rtc_update); -+EXPORT_SYMBOL(register_rtc); -+EXPORT_SYMBOL(unregister_rtc); ---- linux-2.6.5/arch/arm/common/Makefile~heh 2004-04-03 22:36:57.000000000 -0500 -+++ linux-2.6.5/arch/arm/common/Makefile 2004-04-30 20:57:36.000000000 -0400 -@@ -2,7 +2,7 @@ - # Makefile for the linux kernel. - # - --obj-y += platform.o -+obj-y += platform.o rtctime.o - obj-$(CONFIG_ARM_AMBA) += amba.o - obj-$(CONFIG_ICST525) += icst525.o - obj-$(CONFIG_SA1111) += sa1111.o sa1111-pcibuf.o ---- linux-2.6.5/arch/arm/mach-pxa/generic.c~heh 2004-04-03 22:36:53.000000000 -0500 -+++ linux-2.6.5/arch/arm/mach-pxa/generic.c 2004-04-30 20:57:36.000000000 -0400 -@@ -132,7 +132,7 @@ - /* virtual physical length type */ - { 0xf6000000, 0x20000000, 0x01000000, MT_DEVICE }, /* PCMCIA0 IO */ - { 0xf7000000, 0x30000000, 0x01000000, MT_DEVICE }, /* PCMCIA1 IO */ -- { 0xf8000000, 0x40000000, 0x01400000, MT_DEVICE }, /* Devs */ -+ { 0xf8000000, 0x40000000, 0x01800000, MT_DEVICE }, /* Devs */ - { 0xfa000000, 0x44000000, 0x00100000, MT_DEVICE }, /* LCD */ - { 0xfc000000, 0x48000000, 0x00100000, MT_DEVICE }, /* Mem Ctl */ - { 0xff000000, 0x00000000, 0x00100000, MT_DEVICE } /* UNCACHED_PHYS_0 */ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-pxa/cpu-pxa.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,322 @@ -+/* -+ * linux/arch/arm/mach-pxa/cpu-pxa.c -+ * -+ * Copyright (C) 2002,2003 Intrinsyc 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * History: -+ * 31-Jul-2002 : Initial version [FB] -+ * 29-Jan-2003 : added PXA255 support [FB] -+ * 20-Apr-2003 : ported to v2.5 (Dustin McIntire, Sensoria Corp.) -+ * -+ * Note: -+ * This driver may change the memory bus clock rate, but will not do any -+ * platform specific access timing changes... for example if you have flash -+ * memory connected to CS0, you will need to register a platform specific -+ * notifier which will adjust the memory access strobes to maintain a -+ * minimum strobe width. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define DEBUG 0 -+ -+#ifdef DEBUG -+ static unsigned int freq_debug = DEBUG; -+ MODULE_PARM(freq_debug, "i"); -+ MODULE_PARM_DESC(freq_debug, "Set the debug messages to on=1/off=0"); -+#else -+ #define freq_debug 0 -+#endif -+ -+typedef struct -+{ -+ unsigned int khz; -+ unsigned int membus; -+ unsigned int cccr; -+ unsigned int div2; -+} pxa_freqs_t; -+ -+/* Define the refresh period in mSec for the SDRAM and the number of rows */ -+#define SDRAM_TREF 64 /* standard 64ms SDRAM */ -+#define SDRAM_ROWS 4096 /* 64MB=8192 32MB=4096 */ -+#define MDREFR_DRI(x) ((x*SDRAM_TREF)/(SDRAM_ROWS*32)) -+ -+#define CCLKCFG_TURBO 0x1 -+#define CCLKCFG_FCS 0x2 -+#define PXA25x_MIN_FREQ 99500 -+#define PXA25x_MAX_FREQ 398100 -+#define MDREFR_DB2_MASK (MDREFR_K2DB2 | MDREFR_K1DB2) -+#define MDREFR_DRI_MASK 0xFFF -+ -+ -+/* Use the run mode frequencies for the CPUFREQ_POLICY_PERFORMANCE policy */ -+static pxa_freqs_t pxa255_run_freqs[] = -+{ -+ /* CPU MEMBUS CCCR DIV2*/ -+ { 99500, 99500, 0x121, 1}, /* run= 99, turbo= 99, PXbus=50, SDRAM=50 */ -+ {132700, 132700, 0x123, 1}, /* run=133, turbo=133, PXbus=66, SDRAM=66 */ -+ {199100, 99500, 0x141, 0}, /* run=199, turbo=199, PXbus=99, SDRAM=99 */ -+ {265400, 132700, 0x143, 1}, /* run=265, turbo=265, PXbus=133, SDRAM=66 */ -+ {331800, 165900, 0x145, 1}, /* run=331, turbo=331, PXbus=166, SDRAM=83 */ -+ {398100, 99500, 0x161, 0}, /* run=398, turbo=398, PXbus=196, SDRAM=99 */ -+ {0,} -+}; -+#define NUM_RUN_FREQS (sizeof(pxa255_run_freqs)/sizeof(pxa_freqs_t)) -+ -+static struct cpufreq_frequency_table pxa255_run_freq_table[NUM_RUN_FREQS+1]; -+ -+/* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */ -+static pxa_freqs_t pxa255_turbo_freqs[] = -+{ -+ /* CPU MEMBUS CCCR DIV2*/ -+ { 99500, 99500, 0x121, 1}, /* run=99, turbo= 99, PXbus=50, SDRAM=50 */ -+ {199100, 99500, 0x221, 0}, /* run=99, turbo=199, PXbus=50, SDRAM=99 */ -+ {298500, 99500, 0x321, 0}, /* run=99, turbo=287, PXbus=50, SDRAM=99 */ -+ {298600, 99500, 0x1c1, 0}, /* run=199, turbo=287, PXbus=99, SDRAM=99 */ -+ {398100, 99500, 0x241, 0}, /* run=199, turbo=398, PXbus=99, SDRAM=99 */ -+ {0,} -+}; -+#define NUM_TURBO_FREQS (sizeof(pxa255_turbo_freqs)/sizeof(pxa_freqs_t)) -+ -+static struct cpufreq_frequency_table pxa255_turbo_freq_table[NUM_TURBO_FREQS+1]; -+ -+/* find a valid frequency point */ -+static int pxa_verify_policy(struct cpufreq_policy *policy) -+{ -+ int ret; -+ struct cpufreq_frequency_table *pxa_freqs_table; -+ -+ if(policy->policy == CPUFREQ_POLICY_PERFORMANCE) { -+ pxa_freqs_table = pxa255_run_freq_table; -+ } else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) { -+ pxa_freqs_table = pxa255_turbo_freq_table; -+ } else if (policy->policy == CPUFREQ_POLICY_GOVERNOR) { -+ pxa_freqs_table = pxa255_run_freq_table; -+ } else { -+ printk("CPU PXA: Unknown policy found. " -+ "Using CPUFREQ_POLICY_PERFORMANCE\n"); -+ pxa_freqs_table = pxa255_run_freq_table; -+ } -+ ret=cpufreq_frequency_table_verify(policy, pxa_freqs_table); -+ -+ if(freq_debug) { -+ printk("Verified CPU policy: %dKhz min to %dKhz max\n", -+ policy->min, policy->max); -+ } -+ -+ return ret; -+} -+ -+static int pxa_set_target(struct cpufreq_policy *policy, -+ unsigned int target_freq, -+ unsigned int relation) -+{ -+ int idx; -+ unsigned long cpus_allowed; -+ int cpu = policy->cpu; -+ struct cpufreq_freqs freqs; -+ pxa_freqs_t *pxa_freq_settings; -+ struct cpufreq_frequency_table *pxa_freqs_table; -+ unsigned long flags; -+ unsigned int unused; -+ unsigned int preset_mdrefr, postset_mdrefr; -+ -+ /* -+ * Save this threads cpus_allowed mask. -+ */ -+ cpus_allowed = current->cpus_allowed; -+ -+ /* -+ * Bind to the specified CPU. When this call returns, -+ * we should be running on the right CPU. -+ */ -+ set_cpus_allowed(current, 1 << cpu); -+ BUG_ON(cpu != smp_processor_id()); -+ -+ /* Get the current policy */ -+ if(policy->policy == CPUFREQ_POLICY_PERFORMANCE) { -+ pxa_freq_settings = pxa255_run_freqs; -+ pxa_freqs_table = pxa255_run_freq_table; -+ }else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) { -+ pxa_freq_settings = pxa255_turbo_freqs; -+ pxa_freqs_table = pxa255_turbo_freq_table; -+ }else if (policy->policy == CPUFREQ_POLICY_GOVERNOR) { -+ pxa_freq_settings = pxa255_run_freqs; -+ pxa_freqs_table = pxa255_run_freq_table; -+ }else { -+ printk("CPU PXA: Unknown policy found. " -+ "Using CPUFREQ_POLICY_PERFORMANCE\n"); -+ pxa_freq_settings = pxa255_run_freqs; -+ pxa_freqs_table = pxa255_run_freq_table; -+ } -+ -+ /* Lookup the next frequency */ -+ if (cpufreq_frequency_table_target(policy, pxa_freqs_table, -+ target_freq, relation, &idx)) { -+ return -EINVAL; -+ } -+ -+ freqs.old = policy->cur; -+ freqs.new = pxa_freq_settings[idx].khz; -+ freqs.cpu = policy->cpu; -+ if(freq_debug) { -+ printk(KERN_INFO "Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n", -+ freqs.new/1000, (pxa_freq_settings[idx].div2) ? -+ (pxa_freq_settings[idx].membus/2000) : -+ (pxa_freq_settings[idx].membus/1000)); -+ } -+ -+ void *ramstart = phys_to_virt(0xa0000000); -+ -+ /* -+ * Tell everyone what we're about to do... -+ * you should add a notify client with any platform specific -+ * Vcc changing capability -+ */ -+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); -+ -+ /* Calculate the next MDREFR. If we're slowing down the SDRAM clock -+ * we need to preset the smaller DRI before the change. If we're speeding -+ * up we need to set the larger DRI value after the change. -+ */ -+ preset_mdrefr = postset_mdrefr = MDREFR; -+ if((MDREFR & MDREFR_DRI_MASK) > MDREFR_DRI(pxa_freq_settings[idx].membus)) { -+ preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK) | -+ MDREFR_DRI(pxa_freq_settings[idx].membus); -+ } -+ postset_mdrefr = (postset_mdrefr & ~MDREFR_DRI_MASK) | -+ MDREFR_DRI(pxa_freq_settings[idx].membus); -+ -+ /* If we're dividing the memory clock by two for the SDRAM clock, this -+ * must be set prior to the change. Clearing the divide must be done -+ * after the change. -+ */ -+ if(pxa_freq_settings[idx].div2) { -+ preset_mdrefr |= MDREFR_DB2_MASK; -+ postset_mdrefr |= MDREFR_DB2_MASK; -+ } else { -+ postset_mdrefr &= ~MDREFR_DB2_MASK; -+ } -+ -+ local_irq_save(flags); -+ -+ /* Set new the CCCR */ -+ CCCR = pxa_freq_settings[idx].cccr; -+ -+ __asm__ __volatile__(" \ -+ ldr r4, [%1] ; /* load MDREFR */ \ -+ b 2f ; \ -+ .align 5 ; \ -+1: \ -+ str %4, [%1] ; /* preset the MDREFR */ \ -+ mcr p14, 0, %2, c6, c0, 0 ; /* set CCLKCFG[FCS] */ \ -+ str %5, [%1] ; /* postset the MDREFR */ \ -+ \ -+ b 3f ; \ -+2: b 1b ; \ -+3: nop ; \ -+ " -+ : "=&r" (unused) -+ : "r" (&MDREFR), "r" (CCLKCFG_TURBO|CCLKCFG_FCS), "r" (ramstart), \ -+ "r" (preset_mdrefr), "r" (postset_mdrefr) -+ : "r4", "r5"); -+ local_irq_restore(flags); -+ -+ /* -+ * Restore the CPUs allowed mask. -+ */ -+ set_cpus_allowed(current, cpus_allowed); -+ -+ /* -+ * Tell everyone what we've just done... -+ * you should add a notify client with any platform specific -+ * SDRAM refresh timer adjustments -+ */ -+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); -+ -+ return 0; -+} -+ -+static int pxa_cpufreq_init(struct cpufreq_policy *policy) -+{ -+ unsigned long cpus_allowed; -+ unsigned int cpu = policy->cpu; -+ int i; -+ -+ cpus_allowed = current->cpus_allowed; -+ -+ set_cpus_allowed(current, 1 << cpu); -+ BUG_ON(cpu != smp_processor_id()); -+ -+ /* set default policy and cpuinfo */ -+ policy->policy = CPUFREQ_POLICY_PERFORMANCE; -+ policy->cpuinfo.max_freq = PXA25x_MAX_FREQ; -+ policy->cpuinfo.min_freq = PXA25x_MIN_FREQ; -+ policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */ -+ policy->cur = get_clk_frequency_khz(0); /* current freq */ -+ policy->min = policy->max = policy->cur; -+ -+ /* Generate the run cpufreq_frequency_table struct */ -+ for(i=0;i - #include -+#include - #include - - #include -@@ -29,31 +32,162 @@ - #include - #include - --static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, -- unsigned long phys_addr, pgprot_t pgprot) -+extern rwlock_t vmlist_lock; -+extern struct vm_struct *vmlist; -+ -+static struct vm_struct * -+get_io_vm_area(unsigned long size, unsigned long align, unsigned long flags) - { -+ struct vm_struct **p, *tmp, *area; -+ unsigned long addr; -+ -+ area = (struct vm_struct *)kmalloc(sizeof(*area), GFP_KERNEL); -+ if (!area) -+ return NULL; -+ -+ align -= 1; -+ -+ size += PAGE_SIZE; -+ addr = VMALLOC_START; -+ write_lock(&vmlist_lock); -+ for (p = &vmlist; (tmp = *p); p = &tmp->next) { -+ if ((unsigned long)tmp->addr < addr) -+ continue; -+ if ((size + addr) < addr) -+ goto out; -+ if (size + addr <= (unsigned long) tmp->addr) -+ break; -+ addr = tmp->size + (unsigned long) tmp->addr; -+ if ((addr + align) < addr) -+ goto out; -+ addr = (addr + align) & ~align; -+ if (addr > VMALLOC_END - size) -+ goto out; -+ } -+ area->flags = flags; -+ area->addr = (void *)addr; -+ area->size = size; -+ area->next = *p; -+ *p = area; -+ write_unlock(&vmlist_lock); -+ return area; -+ -+out: -+ write_unlock(&vmlist_lock); -+ kfree(area); -+ return NULL; -+} -+ -+static inline void unmap_area_pte(pmd_t *pmd, unsigned long address, unsigned long size) -+{ -+ pte_t *ptep; - unsigned long end; - -+ if (pmd_none(*pmd)) -+ return; -+ if (pmd_bad(*pmd)) { -+ pmd_ERROR(*pmd); -+ pmd_clear(pmd); -+ return; -+ } -+ ptep = pte_offset_kernel(pmd, address); - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; -- if (address >= end) -- BUG(); - do { -- if (!pte_none(*pte)) { -- printk("remap_area_pte: page already exists\n"); -- BUG(); -+ pte_t pte; -+ pte = ptep_get_and_clear(ptep); -+ address += PAGE_SIZE; -+ ptep++; -+ if (pte_none(pte)) -+ continue; -+ if (pte_present(pte)) { -+ unsigned long pfn = pte_pfn(pte); -+ struct page *page; -+ -+ if (!pfn_valid(pfn)) -+ continue; -+ page = pfn_to_page(pfn); -+ if (!PageReserved(page)) -+ __free_page(page); -+ continue; - } -- set_pte(pte, pfn_pte(phys_addr >> PAGE_SHIFT, pgprot)); -+ printk(KERN_CRIT "Whee.. Swapped out page in kernel page table\n"); -+ } while (address < end); -+} -+ -+static inline void unmap_area_pmd(pgd_t *dir, unsigned long address, unsigned long size) -+{ -+ pmd_t *pmd; -+ unsigned long end; -+ -+ if (pgd_none(*dir)) -+ return; -+ if (pgd_bad(*dir)) { -+ pgd_ERROR(*dir); -+ pgd_clear(dir); -+ return; -+ } -+ pmd = pmd_offset(dir, address); -+ address &= ~PGDIR_MASK; -+ end = address + size; -+ if (end > PGDIR_SIZE) -+ end = PGDIR_SIZE; -+ do { -+ unmap_area_pte(pmd, address, end - address); -+ address = (address + PMD_SIZE) & PMD_MASK; -+ pmd++; -+ } while (address < end); -+} -+ -+static void -+unmap_area_pages(unsigned long address, unsigned long size) -+{ -+ unsigned long start = address; -+ unsigned long end = address + size; -+ pgd_t *dir; -+ -+ dir = pgd_offset_k(address); -+ flush_cache_vunmap(start, end); -+ do { -+ unmap_area_pmd(dir, address, end - address); -+ address = (address + PGDIR_SIZE) & PGDIR_MASK; -+ dir++; -+ } while (address && (address < end)); -+ flush_tlb_kernel_range(start, end); -+} -+ -+static inline void -+remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, -+ unsigned long pfn, pgprot_t pgprot) -+{ -+ unsigned long end; -+ -+ address &= ~PMD_MASK; -+ end = address + size; -+ if (end > PMD_SIZE) -+ end = PMD_SIZE; -+ BUG_ON(address >= end); -+ do { -+ if (!pte_none(*pte)) -+ goto bad; -+ -+ set_pte(pte, pfn_pte(pfn, pgprot)); - address += PAGE_SIZE; -- phys_addr += PAGE_SIZE; -+ pfn++; - pte++; - } while (address && (address < end)); -+ return; -+ -+ bad: -+ printk("remap_area_pte: page already exists\n"); -+ BUG(); - } - --static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, -- unsigned long phys_addr, unsigned long flags) -+static inline int -+remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, -+ unsigned long pfn, unsigned long flags) - { - unsigned long end; - pgprot_t pgprot; -@@ -64,51 +198,53 @@ - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - -- phys_addr -= address; -- if (address >= end) -- BUG(); -+ pfn -= address >> PAGE_SHIFT; -+ BUG_ON(address >= end); - - pgprot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE | flags); - do { - pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address); - if (!pte) - return -ENOMEM; -- remap_area_pte(pte, address, end - address, address + phys_addr, pgprot); -+ remap_area_pte(pte, address, end - address, pfn + (address >> PAGE_SHIFT), pgprot); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); - return 0; - } - --static int remap_area_pages(unsigned long address, unsigned long phys_addr, -- unsigned long size, unsigned long flags) -+static int -+remap_area_pages(unsigned long start, unsigned long pfn, -+ unsigned long size, unsigned long flags) - { -- int error; -+ unsigned long address = start; -+ unsigned long end = start + size; -+ int err = 0; - pgd_t * dir; -- unsigned long end = address + size; - -- phys_addr -= address; -+ pfn -= address >> PAGE_SHIFT; - dir = pgd_offset(&init_mm, address); -- flush_cache_all(); -- if (address >= end) -- BUG(); -+ BUG_ON(address >= end); - spin_lock(&init_mm.page_table_lock); - do { -- pmd_t *pmd; -- pmd = pmd_alloc(&init_mm, dir, address); -- error = -ENOMEM; -- if (!pmd) -+ pmd_t *pmd = pmd_alloc(&init_mm, dir, address); -+ if (!pmd) { -+ err = -ENOMEM; - break; -+ } - if (remap_area_pmd(pmd, address, end - address, -- phys_addr + address, flags)) -+ pfn + (address >> PAGE_SHIFT), flags)) { -+ err = -ENOMEM; - break; -- error = 0; -+ } -+ - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); -+ - spin_unlock(&init_mm.page_table_lock); -- flush_tlb_all(); -- return error; -+ flush_cache_vmap(start, end); -+ return err; - } - - /* -@@ -146,11 +282,11 @@ - /* - * Ok, go for it.. - */ -- area = get_vm_area(size, VM_IOREMAP); -+ area = get_io_vm_area(size, align, VM_IOREMAP); - if (!area) - return NULL; - addr = area->addr; -- if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { -+ if (remap_area_pages((unsigned long) addr, phys_addr >> PAGE_SHIFT, size, flags)) { - vfree(addr); - return NULL; - } -@@ -159,5 +295,26 @@ - - void __iounmap(void *addr) - { -- vfree((void *) (PAGE_MASK & (unsigned long) addr)); -+ struct vm_struct **p, *tmp; -+ -+ if (!addr) -+ return; -+ -+ if ((PAGE_SIZE - 1) & (unsigned long)addr) { -+ printk(KERN_ERR "Trying to iounmap() bad address (%p)\n", addr); -+ return; -+ } -+ -+ write_lock(&vmlist_lock); -+ for (p = &vmlist; (tmp = *p); p = &tmp->next) { -+ if (tmp->addr == addr) { -+ *p = tmp->next; -+ unmap_area_pages((unsigned long) tmp->addr, tmp->size); -+ write_unlock(&vmlist_lock); -+ kfree(tmp); -+ return; -+ } -+ } -+ write_unlock(&vmlist_lock); -+ printk(KERN_ERR "Trying to iounmap nonexistent area (%p)\n", addr); - } ---- linux-2.6.5/arch/arm/mm/proc-xscale.S~heh 2004-04-03 22:38:05.000000000 -0500 -+++ linux-2.6.5/arch/arm/mm/proc-xscale.S 2004-04-30 20:57:36.000000000 -0400 -@@ -563,11 +563,62 @@ - movne r2, #0 @ no -> fault - - str r2, [r0] @ hardware version -+ -+ @ We try to map 64K page entries when possible. -+ @ We do that for kernel space only since the usage pattern from -+ @ the setting of VM area is quite simple. User space is not worth -+ @ the implied complexity because of ever randomly changing PTEs -+ @ (page aging, swapout, etc) requiring constant coherency checks. -+ @ Since PTEs are usually set in increasing order, we test the -+ @ possibility for a large page only when given the last PTE of a -+ @ 64K boundary. -+ tsteq r1, #L_PTE_USER -+ andeq r1, r0, #(15 << 2) -+ teqeq r1, #(15 << 2) -+ beq 1f -+ - mov ip, #0 - mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line - mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer - mov pc, lr - -+ @ See if we have 16 identical PTEs but with consecutive base addresses -+1: bic r3, r2, #0x0000f000 -+ mov r1, #0x0000f000 -+2: eor r2, r2, r3 -+ teq r2, r1 -+ bne 4f -+ subs r1, r1, #0x00001000 -+ ldr r2, [r0, #-4]! -+ bne 2b -+ eors r2, r2, r3 -+ bne 4f -+ -+ @ Now create our LARGE PTE from the current EXT one. -+ bic r3, r3, #PTE_TYPE_MASK -+ orr r3, r3, #PTE_TYPE_LARGE -+ and r2, r3, #0x30 @ EXT_AP --> LARGE_AP0 -+ orr r2, r2, r2, lsl #2 @ add LARGE_AP1 -+ orr r2, r2, r2, lsl #4 @ add LARGE_AP3 + LARGE_AP2 -+ and r1, r3, #0x3c0 @ EXT_TEX -+ bic r3, r3, #0x3c0 -+ orr r2, r2, r1, lsl #(12 - 6) @ --> LARGE_TEX -+ orr r2, r2, r3 @ add remaining bits -+ -+ @ then put it in the pagetable -+ mov r3, r2 -+3: strd r2, [r0], #8 -+ tst r0, #(15 << 2) -+ bne 3b -+ -+ @ Then sync the 2 corresponding cache lines -+ sub r0, r0, #(16 << 2) -+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line -+4: orr r0, r0, #(15 << 2) -+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line -+ mov ip, #0 -+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer -+ mov pc, lr - - .ltorg - ---- linux-2.6.5/arch/arm/mach-sa1100/Makefile~heh 2004-04-03 22:38:26.000000000 -0500 -+++ linux-2.6.5/arch/arm/mach-sa1100/Makefile 2004-04-30 20:57:36.000000000 -0400 -@@ -3,7 +3,7 @@ - # - - # Common support --obj-y := generic.o irq.o dma.o -+obj-y := generic.o irq.o dma.o nmi-oopser.o - obj-m := - obj-n := - obj- := -@@ -88,7 +88,7 @@ - obj-$(CONFIG_LEDS) += $(led-y) - - # SA1110 USB client support --#obj-$(CONFIG_SA1100_USB) += usb/ -+obj-$(CONFIG_SA1100_USB) += usb/ - - # Miscelaneous functions - obj-$(CONFIG_PM) += pm.o sleep.o ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/strings.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,43 @@ -+/* -+ * usb/strings.h -+ * -+ * Copyright (C) 2002 Russell King. -+ * -+ * USB device string handling, built upon usb buffers. -+ */ -+#ifndef USBDEV_STRINGS_H -+#define USBDEV_STRINGS_H -+ -+#include -+ -+struct usb_buf; -+ -+#define NR_STRINGS 8 -+ -+struct usb_string_descriptor; -+ -+struct usbc_strs { -+ spinlock_t lock; -+ struct usb_buf *buf[NR_STRINGS]; -+}; -+ -+#define usbc_string_desc(buf) ((struct usb_string_descriptor *)(buf)->data) -+ -+void usbc_string_from_cstr(struct usb_buf *buf, const char *str); -+struct usb_buf *usbc_string_alloc(int len); -+void usbc_string_free(struct usb_buf *buf); -+ -+int usbc_string_add(struct usbc_strs *table, struct usb_buf *buf); -+void usbc_string_del(struct usbc_strs *table, int nr); -+ -+/* -+ * Note: usbc_string_find() increments the buffer use count. -+ * You must call usbb_put() after use. -+ */ -+struct usb_buf * -+usbc_string_find(struct usbc_strs *table, unsigned int lang, unsigned int idx); -+ -+void usbc_string_free_all(struct usbc_strs *table); -+void usbc_string_init(struct usbc_strs *table); -+ -+#endif ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/usb_ctl.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,114 @@ -+/* -+ * Copyright (C) Compaq Computer Corporation, 1998, 1999 -+ * Copyright (C) Extenex Corporation 2001 -+ * -+ * usb_ctl.h -+ * -+ * PRIVATE interface used to share info among components of the SA-1100 USB -+ * core: usb_ctl, usb_ep0, usb_recv and usb_send. Clients of the USB core -+ * should use sa1100_usb.h. -+ * -+ */ -+ -+#ifndef _USB_CTL_H -+#define _USB_CTL_H -+ -+#include /* dmach_t */ -+ -+struct usb_client; -+ -+struct usb_stats_t { -+ unsigned long ep0_fifo_write_failures; -+ unsigned long ep0_bytes_written; -+ unsigned long ep0_fifo_read_failures; -+ unsigned long ep0_bytes_read; -+}; -+ -+struct usb_info_t -+{ -+ struct usb_client *client; -+ dma_regs_t *dmach_tx, *dmach_rx; -+ int state; -+ unsigned char address; -+ struct usb_stats_t stats; -+}; -+ -+/* in usb_ctl.c */ -+extern struct usb_info_t usbd_info; -+ -+/* -+ * Function Prototypes -+ */ -+enum { kError=-1, kEvSuspend=0, kEvReset=1, -+ kEvResume=2, kEvAddress=3, kEvConfig=4, kEvDeConfig=5 }; -+int usbctl_next_state_on_event( int event ); -+ -+/* endpoint zero */ -+void ep0_reset(void); -+void ep0_int_hndlr(void); -+ -+/* receiver */ -+int ep1_recv(void); -+int ep1_init(dma_regs_t *dma); -+void ep1_int_hndlr(int status); -+void ep1_reset(void); -+void ep1_stall(void); -+ -+/* xmitter */ -+void ep2_reset(void); -+int ep2_init(dma_regs_t *dma); -+void ep2_int_hndlr(int status); -+void ep2_stall(void); -+ -+#define UDC_write(reg, val) { \ -+ int i = 10000; \ -+ do { \ -+ (reg) = (val); \ -+ if (i-- <= 0) { \ -+ printk( "%s [%d]: write %#x to %p (%#x) failed\n", \ -+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \ -+ break; \ -+ } \ -+ } while((reg) != (val)); \ -+} -+ -+#define UDC_set(reg, val) { \ -+ int i = 10000; \ -+ do { \ -+ (reg) |= (val); \ -+ if (i-- <= 0) { \ -+ printk( "%s [%d]: set %#x of %p (%#x) failed\n", \ -+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \ -+ break; \ -+ } \ -+ } while(!((reg) & (val))); \ -+} -+ -+#define UDC_clear(reg, val) { \ -+ int i = 10000; \ -+ do { \ -+ (reg) &= ~(val); \ -+ if (i-- <= 0) { \ -+ printk( "%s [%d]: clear %#x of %p (%#x) failed\n", \ -+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \ -+ break; \ -+ } \ -+ } while((reg) & (val)); \ -+} -+ -+#define UDC_flip(reg, val) { \ -+ int i = 10000; \ -+ (reg) = (val); \ -+ do { \ -+ (reg) = (val); \ -+ if (i-- <= 0) { \ -+ printk( "%s [%d]: flip %#x of %p (%#x) failed\n", \ -+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \ -+ break; \ -+ } \ -+ } while(((reg) & (val))); \ -+} -+ -+ -+#define CHECK_ADDRESS { if ( Ser0UDCAR == 1 ) { printk("%s:%d I lost my address!!!\n",__FUNCTION__, __LINE__);}} -+#endif /* _USB_CTL_H */ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/usb_send.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,302 @@ -+/* -+ * Generic xmit layer for the SA1100 USB client function -+ * Copyright (c) 2001 by Nicolas Pitre -+ * -+ * This code was loosely inspired by the original version which was -+ * Copyright (c) Compaq Computer Corporation, 1998-1999 -+ * -+ * 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 is still work in progress... -+ * -+ * Please see linux/Documentation/arm/SA1100/SA1100_USB for details. -+ * 15/03/2001 - ep2_start now sets UDCAR to overcome something that is hardware -+ * bug, I think. green@iXcelerator.com -+ */ -+ -+#include -+#include -+#include -+#include // for the massive_attack hack 28Feb01ww -+#include -+ -+#include -+ -+#include "usbdev.h" -+#include "sa1100_usb.h" -+#include "sa1100usb.h" -+ -+static unsigned int ep2_curdmalen; -+static unsigned int ep2_remain; -+ -+static struct sausb_dev *ep2_dev; -+ -+static void udc_set_cs2(u32 val, u32 mask, u32 check) -+{ -+ int i = 0; -+ -+ do { -+ Ser0UDCCS2 = val; -+ udelay(1); -+ if ((Ser0UDCCS2 & mask) == check) -+ return; -+ } while (i++ < 10000); -+ -+ printk("UDC: UDCCS2 write timed out: val=0x%08x\n", val); -+} -+ -+/* set feature stall executing, async */ -+static void ep2_start(struct sausb_dev *usb) -+{ -+ ep2_curdmalen = min(ep2_remain, usb->ep[1].maxpktsize); -+ if (ep2_curdmalen == 0) -+ return; -+ -+ /* -+ * must do this _before_ queue buffer.. -+ * stop NAKing IN tokens -+ */ -+ udc_set_cs2(usb->ep[1].udccs | UDCCS2_TPC, UDCCS2_TPC, 0); -+ -+ UDC_write(Ser0UDCIMP, ep2_curdmalen - 1); -+ -+ /* Remove if never seen...8Mar01ww */ -+ { -+ int massive_attack = 20; -+ while (Ser0UDCIMP != ep2_curdmalen - 1 && massive_attack--) { -+ printk("usbsnd: Oh no you don't! Let me spin..."); -+ udelay(500); -+ printk("and try again...\n"); -+ UDC_write(Ser0UDCIMP, ep2_curdmalen - 1); -+ } -+ if (massive_attack != 20) { -+ if (Ser0UDCIMP != ep2_curdmalen - 1) -+ printk("usbsnd: Massive attack FAILED. %d\n", -+ 20 - massive_attack); -+ else -+ printk("usbsnd: Massive attack WORKED. %d\n", -+ 20 - massive_attack); -+ } -+ } -+ /* End remove if never seen... 8Mar01ww */ -+ -+ /* -+ * fight stupid silicon bug -+ */ -+ Ser0UDCAR = usb->ctl->address; -+ -+ sa1100_start_dma(usb->ep[1].dmach, usb->ep[1].pktdma, ep2_curdmalen); -+} -+ -+static void udc_ep2_done(struct sausb_dev *usb, int flag) -+{ -+ int size = usb->ep[1].buflen - ep2_remain; -+ -+ if (!usb->ep[1].buflen) -+ return; -+ -+ dma_unmap_single(usb->dev, usb->ep[1].bufdma, usb->ep[1].buflen, -+ DMA_TO_DEVICE); -+ -+ usb->ep[1].bufdma = 0; -+ usb->ep[1].buflen = 0; -+ usb->ep[1].pktdma = 0; -+ -+ if (usb->ep[1].cb_func) -+ usb->ep[1].cb_func(usb->ep[1].cb_data, flag, size); -+} -+ -+/* -+ * Initialisation. Clear out the status. -+ */ -+void udc_ep2_init(struct sausb_dev *usb) -+{ -+ ep2_dev = usb; -+ -+ usb->ep[1].udccs = UDCCS2_FST; -+ -+ BUG_ON(usb->ep[1].buflen); -+ BUG_ON(usb->ep[1].pktlen); -+ -+ sa1100_reset_dma(usb->ep[1].dmach); -+} -+ -+/* -+ * Note: rev A0-B2 chips don't like FST -+ */ -+void udc_ep2_halt(struct sausb_dev *usb, int halt) -+{ -+ usb->ep[1].host_halt = halt; -+ -+ if (halt) { -+ usb->ep[1].udccs |= UDCCS2_FST; -+ udc_set_cs2(UDCCS2_FST, UDCCS2_FST, UDCCS2_FST); -+ } else { -+ sa1100_clear_dma(usb->ep[1].dmach); -+ -+ udc_set_cs2(UDCCS2_FST, UDCCS2_FST, UDCCS2_FST); -+ udc_set_cs2(0, UDCCS2_FST, 0); -+ udc_set_cs2(UDCCS2_SST, UDCCS2_SST, 0); -+ -+ usb->ep[1].udccs &= ~UDCCS2_FST; -+ -+ udc_ep2_done(usb, -EINTR); -+ } -+} -+ -+/* -+ * This gets called when we receive a SET_CONFIGURATION packet to EP0. -+ * We were configured. We can now send packets to the host. -+ */ -+void udc_ep2_config(struct sausb_dev *usb, unsigned int maxpktsize) -+{ -+ /* -+ * We shouldn't be transmitting anything... -+ */ -+ BUG_ON(usb->ep[1].buflen); -+ BUG_ON(usb->ep[1].pktlen); -+ -+ /* -+ * Set our configuration. -+ */ -+ usb->ep[1].maxpktsize = maxpktsize; -+ usb->ep[1].configured = 1; -+ -+ /* -+ * Clear any pending TPC status. -+ */ -+ udc_set_cs2(UDCCS2_TPC, UDCCS2_TPC, 0); -+ -+ /* -+ * Enable EP2 interrupts. -+ */ -+ usb->udccr &= ~UDCCR_TIM; -+ UDC_write(Ser0UDCCR, usb->udccr); -+ -+ usb->ep[1].udccs = 0; -+} -+ -+/* -+ * We saw a reset from the attached hub, or were deconfigured. -+ * This means we are no longer configured. -+ */ -+void udc_ep2_reset(struct sausb_dev *usb) -+{ -+ /* -+ * Disable EP2 interrupts. -+ */ -+ usb->udccr |= UDCCR_TIM; -+ UDC_write(Ser0UDCCR, usb->udccr); -+ -+ usb->ep[1].configured = 0; -+ usb->ep[1].maxpktsize = 0; -+ -+ sa1100_reset_dma(usb->ep[1].dmach); -+ udc_ep2_done(usb, -EINTR); -+} -+ -+void udc_ep2_int_hndlr(struct sausb_dev *usb) -+{ -+ u32 status = Ser0UDCCS2; -+ -+ // check for stupid silicon bug. -+ if (Ser0UDCAR != usb->ctl->address) -+ Ser0UDCAR = usb->ctl->address; -+ -+ udc_set_cs2(usb->ep[1].udccs | UDCCS2_SST, UDCCS2_SST, 0); -+ -+ if (!(status & UDCCS2_TPC)) { -+ printk("usb_send: Not TPC: UDCCS2 = %x\n", status); -+ return; -+ } -+ -+ sa1100_stop_dma(usb->ep[1].dmach); -+ -+ if (status & (UDCCS2_TPE | UDCCS2_TUR)) { -+ printk("usb_send: transmit error %x\n", status); -+ usb->ep[1].fifo_errs ++; -+ udc_ep2_done(usb, -EIO); -+ } else { -+ unsigned int imp; -+#if 1 // 22Feb01ww/Oleg -+ imp = ep2_curdmalen; -+#else -+ // this is workaround for case when setting -+ // of Ser0UDCIMP was failed -+ imp = Ser0UDCIMP + 1; -+#endif -+ usb->ep[1].pktdma += imp; -+ ep2_remain -= imp; -+ -+ usb->ep[1].bytes += imp; -+ usb->ep[1].packets++; -+ -+ sa1100_clear_dma(usb->ep[1].dmach); -+ -+ if (ep2_remain != 0) { -+ ep2_start(usb); -+ } else { -+ udc_ep2_done(usb, 0); -+ } -+ } -+} -+ -+int udc_ep2_send(struct sausb_dev *usb, char *buf, int len) -+{ -+ unsigned long flags; -+ dma_addr_t dma; -+ int ret; -+ -+ if (!buf || len == 0) -+ return -EINVAL; -+ -+ dma = dma_map_single(usb->dev, buf, len, DMA_TO_DEVICE); -+ -+ spin_lock_irqsave(&usb->lock, flags); -+ do { -+ if (!usb->ep[1].configured) { -+ ret = -ENODEV; -+ break; -+ } -+ -+ if (usb->ep[1].buflen) { -+ ret = -EBUSY; -+ break; -+ } -+ -+ usb->ep[1].bufdma = dma; -+ usb->ep[1].buflen = len; -+ usb->ep[1].pktdma = dma; -+ ep2_remain = len; -+ -+ sa1100_clear_dma(usb->ep[1].dmach); -+ -+ ep2_start(usb); -+ ret = 0; -+ } while (0); -+ spin_unlock_irqrestore(&usb->lock, flags); -+ -+ if (ret) -+ dma_unmap_single(usb->dev, dma, len, DMA_TO_DEVICE); -+ -+ return ret; -+} -+ -+void udc_ep2_send_reset(struct sausb_dev *usb) -+{ -+ sa1100_reset_dma(usb->ep[1].dmach); -+ udc_ep2_done(usb, -EINTR); -+} -+ -+int udc_ep2_idle(struct sausb_dev *usb) -+{ -+ if (!usb->ep[1].configured) -+ return -ENODEV; -+ -+ if (usb->ep[1].buflen) -+ return -EBUSY; -+ -+ return 0; -+} ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/usb-char.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,709 @@ -+/* -+ * (C) Copyright 2000-2001 Extenex Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ * usb-char.c -+ * -+ * Miscellaneous character device interface for SA1100 USB function -+ * driver. -+ * -+ * Background: -+ * The SA1100 function driver ported from the Compaq Itsy project -+ * has an interface, usb-eth.c, to feed network packets over the -+ * usb wire and into the Linux TCP/IP stack. -+ * -+ * This file replaces that one with a simple character device -+ * interface that allows unstructured "byte pipe" style reads and -+ * writes over the USB bulk endpoints by userspace programs. -+ * -+ * A new define, CONFIG_SA1100_USB_NETLINK, has been created that, -+ * when set, (the default) causes the ethernet interface to be used. -+ * When not set, this more pedestrian character interface is linked -+ * in instead. -+ * -+ * Please see linux/Documentation/arm/SA1100/SA1100_USB for details. -+ * -+ * ward.willats@extenex.com -+ * -+ * To do: -+ * - Can't dma into ring buffer directly with dma_map/unmap usb_recv -+ * uses and get bytes out at the same time DMA is going on. Investigate: -+ * a) changing usb_recv to use alloc_consistent() at client request; or -+ * b) non-ring-buffer based data structures. In the meantime, I am using -+ * a bounce buffer. Simple, but wasteful. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "usb-char.h" -+#include "client.h" -+ -+ -+ -+////////////////////////////////////////////////////////////////////////////// -+// Driver Options -+////////////////////////////////////////////////////////////////////////////// -+ -+#define VERSION "0.4" -+ -+ -+#define VERBOSITY 1 -+ -+#if VERBOSITY -+# define PRINTK(x, a...) printk (x, ## a) -+#else -+# define PRINTK(x, a...) /**/ -+#endif -+ -+////////////////////////////////////////////////////////////////////////////// -+// Globals - Macros - Enums - Structures -+////////////////////////////////////////////////////////////////////////////// -+#ifndef MIN -+#define MIN( a, b ) ((a)<(b)?(a):(b)) -+#endif -+ -+typedef int bool; enum { false = 0, true = 1 }; -+ -+static const char pszMe[] = "usbchr: "; -+ -+static wait_queue_head_t wq_read; -+static wait_queue_head_t wq_write; -+static wait_queue_head_t wq_poll; -+ -+/* Serialze multiple writers onto the transmit hardware -+.. since we sleep the writer during transmit to stay in -+.. sync. (Multiple writers don't make much sense, but..) */ -+static DECLARE_MUTEX( xmit_sem ); -+ -+// size of usb DATA0/1 packets. 64 is standard maximum -+// for bulk transport, though most hosts seem to be able -+// to handle larger. -+#define TX_PACKET_SIZE 64 -+#define RX_PACKET_SIZE 64 -+#define RBUF_SIZE (4*PAGE_SIZE) -+ -+static struct wcirc_buf { -+ char *buf; -+ int in; -+ int out; -+} rx_ring = { NULL, 0, 0 }; -+ -+static struct { -+ unsigned long cnt_rx_complete; -+ unsigned long cnt_rx_errors; -+ unsigned long bytes_rx; -+ unsigned long cnt_tx_timeouts; -+ unsigned long cnt_tx_errors; -+ unsigned long bytes_tx; -+} charstats; -+ -+ -+static char * tx_buf = NULL; -+static char * packet_buffer = NULL; -+static int sending = 0; -+static int usb_ref_count = 0; -+static int last_tx_result = 0; -+static int last_rx_result = 0; -+static int last_tx_size = 0; -+static struct timer_list tx_timer; -+ -+////////////////////////////////////////////////////////////////////////////// -+// Prototypes -+////////////////////////////////////////////////////////////////////////////// -+static char * what_the_f( int e ); -+static void free_txrx_buffers( void ); -+static void twiddle_descriptors(struct usb_client *client); -+static int usbc_open( struct inode *pInode, struct file *pFile ); -+static void rx_done_callback_packet_buffer(void *data, int flag, int size ); -+ -+static void tx_timeout( unsigned long ); -+static void tx_done_callback(void *data, int flag, int size ); -+ -+static ssize_t usbc_read( struct file *, char *, size_t, loff_t * ); -+static ssize_t usbc_write( struct file *, const char *, size_t, loff_t * ); -+static unsigned int usbc_poll( struct file *pFile, poll_table * pWait ); -+static int usbc_ioctl( struct inode *pInode, struct file *pFile, -+ unsigned int nCmd, unsigned long argument ); -+static int usbc_close( struct inode *pInode, struct file *pFile ); -+ -+#ifdef CONFIG_SA1100_EXTENEX1 -+static void extenex_configured_notify_proc( void ); -+#endif -+////////////////////////////////////////////////////////////////////////////// -+// Private Helpers -+////////////////////////////////////////////////////////////////////////////// -+ -+static char * what_the_f( int e ) -+{ -+ char * p; -+ switch( e ) { -+ case 0: -+ p = "noErr"; -+ break; -+ case -ENODEV: -+ p = "ENODEV - usb not in config state"; -+ break; -+ case -EBUSY: -+ p = "EBUSY - another request on the hardware"; -+ break; -+ case -EAGAIN: -+ p = "EAGAIN"; -+ break; -+ case -EINTR: -+ p = "EINTR - interrupted\n"; -+ break; -+ case -EPIPE: -+ p = "EPIPE - zero length xfer\n"; -+ break; -+ default: -+ p = "????"; -+ break; -+ } -+ return p; -+} -+ -+static void free_txrx_buffers( void ) -+{ -+ if ( rx_ring.buf != NULL ) { -+ kfree( rx_ring.buf ); -+ rx_ring.buf = NULL; -+ } -+ if ( packet_buffer != NULL ) { -+ kfree( packet_buffer ); -+ packet_buffer = NULL; -+ } -+ if ( tx_buf != NULL ) { -+ kfree( tx_buf ); -+ tx_buf = NULL; -+ } -+} -+ -+/* twiddle_descriptors() -+ * It is between open() and start(). Setup descriptors. -+ */ -+static void twiddle_descriptors(struct usb_client *client) -+{ -+ struct cdb *cdb = sa1100_usb_get_descriptor_ptr(); -+ -+ cdb->ep1.wMaxPacketSize = cpu_to_le16(RX_PACKET_SIZE); -+ cdb->ep2.wMaxPacketSize = cpu_to_le16(TX_PACKET_SIZE); -+ -+#ifdef CONFIG_SA1100_EXTENEX1 -+ if (machine_is_extenex1()) { -+ int nr; -+ -+ cdb->cfg.bmAttributes = USB_CONFIG_SELFPOWERED; -+ cdb->cfg.MaxPower = 0; -+ -+ nr = sa1100_usb_add_string(client->ctl, "HHT Bulk Transfer"); -+ -+ if (nr > 0) -+ cdb->intf.iInterface = nr; -+ } -+#endif -+} -+ -+////////////////////////////////////////////////////////////////////////////// -+// ASYNCHRONOUS -+////////////////////////////////////////////////////////////////////////////// -+static void kick_start_rx( void ) -+{ -+ if ( usb_ref_count ) { -+ int total_space = CIRC_SPACE( rx_ring.in, rx_ring.out, RBUF_SIZE ); -+ if ( total_space >= RX_PACKET_SIZE ) { -+ sa1100_usb_recv_set_callback(rx_done_callback_packet_buffer, NULL); -+ sa1100_usb_recv( packet_buffer, RX_PACKET_SIZE); -+ } -+ } -+} -+/* -+ * rx_done_callback_packet_buffer() -+ * We have completed a DMA xfer into the temp packet buffer. -+ * Move to ring. -+ * -+ * flag values: -+ * on init, -EAGAIN -+ * on reset, -EINTR -+ * on RPE, -EIO -+ * on short packet -EPIPE -+ */ -+static void -+rx_done_callback_packet_buffer(void *data, int flag, int size ) -+{ -+ charstats.cnt_rx_complete++; -+ -+ if ( flag == 0 || flag == -EPIPE ) { -+ size_t n; -+ -+ charstats.bytes_rx += size; -+ -+ n = CIRC_SPACE_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE ); -+ n = MIN( n, size ); -+ size -= n; -+ -+ memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer, n ); -+ rx_ring.in = (rx_ring.in + n) & (RBUF_SIZE-1); -+ memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer + n, size ); -+ rx_ring.in = (rx_ring.in + size) & (RBUF_SIZE-1); -+ -+ wake_up_interruptible( &wq_read ); -+ wake_up_interruptible( &wq_poll ); -+ -+ last_rx_result = 0; -+ -+ kick_start_rx(); -+ -+ } else if ( flag != -EAGAIN ) { -+ charstats.cnt_rx_errors++; -+ last_rx_result = flag; -+ wake_up_interruptible( &wq_read ); -+ wake_up_interruptible( &wq_poll ); -+ } -+ else /* init, start a read */ -+ kick_start_rx(); -+} -+ -+ -+static void tx_timeout( unsigned long unused ) -+{ -+ printk( "%stx timeout\n", pszMe ); -+ sa1100_usb_send_reset(); -+ charstats.cnt_tx_timeouts++; -+} -+ -+ -+// on init, -EAGAIN -+// on reset, -EINTR -+// on TPE, -EIO -+static void tx_done_callback(void *data, int flags, int size ) -+{ -+ if ( flags == 0 ) -+ charstats.bytes_tx += size; -+ else -+ charstats.cnt_tx_errors++; -+ last_tx_size = size; -+ last_tx_result = flags; -+ sending = 0; -+ wake_up_interruptible( &wq_write ); -+ wake_up_interruptible( &wq_poll ); -+} -+ -+ -+static struct usb_client usbc_client = { -+ .name = "usb-char", -+ -+ /* -+ * USB client identification for host use in CPU endian. -+ */ -+ .vendor = 0, -+ .product = 0, -+ .version = 0, -+ .class = 0xff, -+ .subclass = 0, -+ .protocol = 0, -+}; -+ -+#ifdef CONFIG_SA1100_EXTENEX1 -+#include "../../../drivers/char/ex_gpio.h" -+static void extenex_state_change(void *data, int state, int oldstate) -+{ -+ if (exgpio_play_string( "440,1:698,1") == -EAGAIN) -+ printk( "%sWanted to BEEP but ex_gpio not open\n", pszMe ); -+} -+#endif -+ -+////////////////////////////////////////////////////////////////////////////// -+// Workers -+////////////////////////////////////////////////////////////////////////////// -+ -+static int usbc_open(struct inode *pInode, struct file *pFile) -+{ -+ int retval = 0; -+ -+ PRINTK( KERN_DEBUG "%sopen()\n", pszMe ); -+ -+#ifdef CONFIG_SA1100_EXTENEX1 -+ if (machine_is_extenex1()) { -+ usbc_client.vendor = 0x0c9f; -+ usbc_client.product = 0x0100; -+ usbc_client.version = 0x0001; -+ usbc_client.manufacturer_str = "Extenex"; -+ usbc_client.product_str = "Handheld Theater"; -+ usbc_client.serial_str = "00000000"; -+ usbc_client.state_change = extenex_state_change; -+ } -+#endif -+ -+ /* start usb core */ -+ retval = usbctl_open(&usbc_client); -+ if (retval) -+ return retval; -+ -+ /* allocate memory */ -+ if ( usb_ref_count == 0 ) { -+ tx_buf = (char*) kmalloc( TX_PACKET_SIZE, GFP_KERNEL | GFP_DMA ); -+ if ( tx_buf == NULL ) { -+ printk( "%sARGHH! COULD NOT ALLOCATE TX BUFFER\n", pszMe ); -+ goto malloc_fail; -+ } -+ rx_ring.buf = -+ (char*) kmalloc( RBUF_SIZE, GFP_KERNEL ); -+ -+ if ( rx_ring.buf == NULL ) { -+ printk( "%sARGHH! COULD NOT ALLOCATE RX BUFFER\n", pszMe ); -+ goto malloc_fail; -+ } -+ -+ packet_buffer = -+ (char*) kmalloc( RX_PACKET_SIZE, GFP_KERNEL | GFP_DMA ); -+ -+ if ( packet_buffer == NULL ) { -+ printk( "%sARGHH! COULD NOT ALLOCATE RX PACKET BUFFER\n", pszMe ); -+ goto malloc_fail; -+ } -+ rx_ring.in = rx_ring.out = 0; -+ memset( &charstats, 0, sizeof( charstats ) ); -+ sending = 0; -+ last_tx_result = 0; -+ last_tx_size = 0; -+ } -+ -+ /* modify default descriptors */ -+ twiddle_descriptors(&usbc_client); -+ -+ retval = usbctl_start(&usbc_client); -+ if ( retval ) { -+ printk( "%sAGHH! Could not USB core\n", pszMe ); -+ free_txrx_buffers(); -+ return retval; -+ } -+ usb_ref_count++; /* must do _before_ kick_start() */ -+ MOD_INC_USE_COUNT; -+ kick_start_rx(); -+ return 0; -+ -+ malloc_fail: -+ free_txrx_buffers(); -+ return -ENOMEM; -+} -+ -+/* -+ * Read endpoint. Note that you can issue a read to an -+ * unconfigured endpoint. Eventually, the host may come along -+ * and configure underneath this module and data will appear. -+ */ -+static ssize_t usbc_read( struct file *pFile, char *pUserBuffer, -+ size_t stCount, loff_t *pPos ) -+{ -+ ssize_t retval; -+ unsigned long flags; -+ DECLARE_WAITQUEUE( wait, current ); -+ -+ PRINTK( KERN_DEBUG "%sread()\n", pszMe ); -+ -+ local_irq_save(flags); -+ if ( last_rx_result == 0 ) { -+ local_irq_restore( flags ); -+ } else { /* an error happended and receiver is paused */ -+ local_irq_restore( flags ); -+ last_rx_result = 0; -+ kick_start_rx(); -+ } -+ -+ add_wait_queue( &wq_read, &wait ); -+ while( 1 ) { -+ ssize_t bytes_avail; -+ ssize_t bytes_to_end; -+ -+ set_current_state( TASK_INTERRUPTIBLE ); -+ -+ /* snap ring buf state */ -+ local_irq_save( flags ); -+ bytes_avail = CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ); -+ bytes_to_end = CIRC_CNT_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE ); -+ local_irq_restore( flags ); -+ -+ if ( bytes_avail != 0 ) { -+ ssize_t bytes_to_move = MIN( stCount, bytes_avail ); -+ retval = 0; // will be bytes transfered -+ if ( bytes_to_move != 0 ) { -+ size_t n = MIN( bytes_to_end, bytes_to_move ); -+ if ( copy_to_user( pUserBuffer, -+ &rx_ring.buf[ rx_ring.out ], -+ n ) ) { -+ retval = -EFAULT; -+ break; -+ } -+ bytes_to_move -= n; -+ retval += n; -+ // might go 1 char off end, so wrap -+ rx_ring.out = ( rx_ring.out + n ) & (RBUF_SIZE-1); -+ if ( copy_to_user( pUserBuffer + n, -+ &rx_ring.buf[ rx_ring.out ], -+ bytes_to_move ) -+ ) { -+ retval = -EFAULT; -+ break; -+ } -+ rx_ring.out += bytes_to_move; // cannot wrap -+ retval += bytes_to_move; -+ kick_start_rx(); -+ } -+ break; -+ } -+ else if ( last_rx_result ) { -+ retval = last_rx_result; -+ break; -+ } -+ else if ( pFile->f_flags & O_NONBLOCK ) { // no data, can't sleep -+ retval = -EAGAIN; -+ break; -+ } -+ else if ( signal_pending( current ) ) { // no data, can sleep, but signal -+ retval = -ERESTARTSYS; -+ break; -+ } -+ schedule(); // no data, can sleep -+ } -+ set_current_state( TASK_RUNNING ); -+ remove_wait_queue( &wq_read, &wait ); -+ -+ if ( retval < 0 ) -+ printk( "%sread error %d - %s\n", pszMe, retval, what_the_f( retval ) ); -+ return retval; -+} -+ -+/* -+ * Write endpoint. This routine attempts to break the passed in buffer -+ * into usb DATA0/1 packet size chunks and send them to the host. -+ * (The lower-level driver tries to do this too, but easier for us -+ * to manage things here.) -+ * -+ * We are at the mercy of the host here, in that it must send an IN -+ * token to us to pull this data back, so hopefully some higher level -+ * protocol is expecting traffic to flow in that direction so the host -+ * is actually polling us. To guard against hangs, a 5 second timeout -+ * is used. -+ * -+ * This routine takes some care to only report bytes sent that have -+ * actually made it across the wire. Thus we try to stay in lockstep -+ * with the completion routine and only have one packet on the xmit -+ * hardware at a time. Multiple simultaneous writers will get -+ * "undefined" results. -+ * -+ */ -+static ssize_t usbc_write( struct file *pFile, const char * pUserBuffer, -+ size_t stCount, loff_t *pPos ) -+{ -+ ssize_t retval = 0; -+ ssize_t stSent = 0; -+ -+ DECLARE_WAITQUEUE( wait, current ); -+ -+ PRINTK( KERN_DEBUG "%swrite() %d bytes\n", pszMe, stCount ); -+ -+ down( &xmit_sem ); // only one thread onto the hardware at a time -+ -+ while( stCount != 0 && retval == 0 ) { -+ int nThisTime = MIN( TX_PACKET_SIZE, stCount ); -+ copy_from_user( tx_buf, pUserBuffer, nThisTime ); -+ sending = nThisTime; -+ sa1100_usb_send_set_callback(tx_done_callback, NULL); -+ retval = sa1100_usb_send( tx_buf, nThisTime); -+ if ( retval < 0 ) { -+ char * p = what_the_f( retval ); -+ printk( "%sCould not queue xmission. rc=%d - %s\n", -+ pszMe, retval, p ); -+ sending = 0; -+ break; -+ } -+ /* now have something on the diving board */ -+ add_wait_queue( &wq_write, &wait ); -+ tx_timer.expires = jiffies + ( HZ * 5 ); -+ add_timer( &tx_timer ); -+ while( 1 ) { -+ set_current_state( TASK_INTERRUPTIBLE ); -+ if ( sending == 0 ) { /* it jumped into the pool */ -+ del_timer( &tx_timer ); -+ retval = last_tx_result; -+ if ( retval == 0 ) { -+ stSent += last_tx_size; -+ pUserBuffer += last_tx_size; -+ stCount -= last_tx_size; -+ } -+ else -+ printk( "%sxmission error rc=%d - %s\n", -+ pszMe, retval, what_the_f(retval) ); -+ break; -+ } -+ else if ( signal_pending( current ) ) { -+ del_timer( &tx_timer ); -+ printk( "%ssignal\n", pszMe ); -+ retval = -ERESTARTSYS; -+ break; -+ } -+ schedule(); -+ } -+ set_current_state( TASK_RUNNING ); -+ remove_wait_queue( &wq_write, &wait ); -+ } -+ -+ up( &xmit_sem ); -+ -+ if ( 0 == retval ) -+ retval = stSent; -+ return retval; -+} -+ -+static unsigned int usbc_poll( struct file *pFile, poll_table * pWait ) -+{ -+ unsigned int retval = 0; -+ -+ PRINTK( KERN_DEBUG "%poll()\n", pszMe ); -+ -+ poll_wait( pFile, &wq_poll, pWait ); -+ -+ if ( CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ) ) -+ retval |= POLLIN | POLLRDNORM; -+ if ( sa1100_usb_xmitter_avail() ) -+ retval |= POLLOUT | POLLWRNORM; -+ return retval; -+} -+ -+static int usbc_ioctl( struct inode *pInode, struct file *pFile, -+ unsigned int nCmd, unsigned long argument ) -+{ -+ int retval = 0; -+ -+ switch( nCmd ) { -+ -+ case USBC_IOC_FLUSH_RECEIVER: -+ sa1100_usb_recv_reset(); -+ rx_ring.in = rx_ring.out = 0; -+ break; -+ -+ case USBC_IOC_FLUSH_TRANSMITTER: -+ sa1100_usb_send_reset(); -+ break; -+ -+ case USBC_IOC_FLUSH_ALL: -+ sa1100_usb_recv_reset(); -+ rx_ring.in = rx_ring.out = 0; -+ sa1100_usb_send_reset(); -+ break; -+ -+ default: -+ retval = -ENOIOCTLCMD; -+ break; -+ -+ } -+ return retval; -+} -+ -+ -+static int usbc_close( struct inode *pInode, struct file * pFile ) -+{ -+ PRINTK( KERN_DEBUG "%sclose()\n", pszMe ); -+ if ( --usb_ref_count == 0 ) { -+ down( &xmit_sem ); -+ usbctl_stop(&usbc_client); -+ free_txrx_buffers(); -+ del_timer( &tx_timer ); -+ usbctl_close(&usbc_client); -+ up(&xmit_sem); -+ } -+ MOD_DEC_USE_COUNT; -+ return 0; -+} -+ -+////////////////////////////////////////////////////////////////////////////// -+// Initialization -+////////////////////////////////////////////////////////////////////////////// -+ -+static struct file_operations usbc_fops = { -+ owner: THIS_MODULE, -+ open: usbc_open, -+ read: usbc_read, -+ write: usbc_write, -+ poll: usbc_poll, -+ ioctl: usbc_ioctl, -+ release: usbc_close, -+}; -+ -+static struct miscdevice usbc_misc_device = { -+ USBC_MINOR, -+ "usb_char", -+ &usbc_fops -+}; -+ -+/* -+ * usbc_init() -+ */ -+ -+static int __init usbc_init( void ) -+{ -+ int rc; -+ -+#if !defined( CONFIG_ARCH_SA1100 ) -+ return -ENODEV; -+#endif -+ -+ if ( (rc = misc_register( &usbc_misc_device )) != 0 ) { -+ printk( KERN_WARNING "%sCould not register device 10, " -+ "%d. (%d)\n", pszMe, USBC_MINOR, rc ); -+ return -EBUSY; -+ } -+ -+ // initialize wait queues -+ init_waitqueue_head( &wq_read ); -+ init_waitqueue_head( &wq_write ); -+ init_waitqueue_head( &wq_poll ); -+ -+ // initialize tx timeout timer -+ init_timer( &tx_timer ); -+ tx_timer.function = tx_timeout; -+ -+ printk( KERN_INFO "USB Function Character Driver Interface" -+ " - %s, (C) 2001, Extenex Corp.\n", VERSION -+ ); -+ -+ return rc; -+} -+ -+static void __exit usbc_exit( void ) -+{ -+} -+ -+module_init(usbc_init); -+module_exit(usbc_exit); -+ -+// end: usb-char.c -+ -+MODULE_LICENSE("GPL"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/usb-eth.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,535 @@ -+/* -+ * Network driver for the SA1100 USB client function -+ * Copyright (c) 2001 by Nicolas Pitre -+ * -+ * This code was loosely inspired by the original initial ethernet test driver -+ * Copyright (c) Compaq Computer Corporation, 1999 -+ * -+ * 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. -+ * -+ * Issues: -+ * - DMA needs 8 byte aligned buffer, but causes inefficiencies -+ * in the IP code. -+ * - stall endpoint operations appeared to be very unstable. -+ */ -+ -+/* -+ * Define RX_NO_COPY if you want data to arrive directly into the -+ * receive network buffers, instead of arriving into bounce buffer -+ * and then get copied to network buffer. -+ * -+ * Since the SA1100 DMA engine is unable to cope with unaligned -+ * buffer addresses, we need to use bounce buffers or suffer the -+ * alignment trap performance hit. -+ */ -+#undef RX_NO_COPY -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "client.h" -+ -+ -+#define ETHERNET_VENDOR_ID 0x049f -+#define ETHERNET_PRODUCT_ID 0x505A -+#define MAX_PACKET 32768 -+ -+/* -+ * This is our usb "packet size", and must match the host "packet size". -+ */ -+static int usb_rsize = 64; -+static int usb_wsize = 64; -+ -+struct usbe_info { -+ struct net_device dev; -+ struct usb_client client; -+ struct sk_buff *cur_tx_skb; -+ struct sk_buff *next_tx_skb; -+ struct sk_buff *cur_rx_skb; -+ struct sk_buff *next_rx_skb; -+#ifndef RX_NO_COPY -+ char *dmabuf; // dma expects it's buffers to be aligned on 8 bytes boundary -+#endif -+ struct net_device_stats stats; -+}; -+ -+ -+static int usbeth_change_mtu(struct net_device *dev, int new_mtu) -+{ -+ if (new_mtu <= sizeof(struct ethhdr) || new_mtu > MAX_PACKET) -+ return -EINVAL; -+ -+ // no second zero-length packet read wanted after mtu-sized packets -+ if (((new_mtu + sizeof(struct ethhdr)) % usb_rsize) == 0) -+ return -EDOM; -+ -+ dev->mtu = new_mtu; -+ return 0; -+} -+ -+static struct sk_buff *usb_new_recv_skb(struct usbe_info *usbe) -+{ -+ struct sk_buff *skb; -+ -+ skb = alloc_skb(2 + sizeof(struct ethhdr) + usbe->dev.mtu, -+ GFP_ATOMIC); -+ -+ if (skb) -+ skb_reserve(skb, 2); -+ -+ return skb; -+} -+ -+static void usbeth_recv_callback(void *data, int flag, int len) -+{ -+ struct usbe_info *usbe = data; -+ struct sk_buff *skb; -+ unsigned int size; -+ char *buf; -+ -+ skb = usbe->cur_rx_skb; -+ -+ /* flag validation */ -+ if (flag != 0) -+ goto error; -+ -+ /* -+ * Make sure we have enough room left in the buffer. -+ */ -+ if (len > skb_tailroom(skb)) { -+ usbe->stats.rx_over_errors++; -+ usbe->stats.rx_errors++; -+ goto oversize; -+ } -+ -+ /* -+ * If the packet is smaller than usb_rsize bytes, the packet -+ * is complete, and we need to use the next receive buffer. -+ */ -+ if (len != usb_rsize) -+ usbe->cur_rx_skb = usbe->next_rx_skb; -+ -+ /* -+ * Put the data onto the socket buffer and resume USB receive. -+ */ -+#ifndef RX_NO_COPY -+ memcpy(skb_put(skb, len), usbe->dmabuf, len); -+ buf = usbe->dmabuf; -+ size = usb_rsize; -+#else -+ skb_put(skb, len); -+ buf = usbe->cur_rx_skb->tail; -+ size = skb_tailroom(usbe->cur_rx_skb); -+#endif -+ usbctl_ep_queue_buffer(usbe->client.ctl, 1, buf, size); -+ -+ if (len == usb_rsize) -+ return; -+ -+ /* -+ * A frame must contain at least an ethernet header. -+ */ -+ if (skb->len < sizeof(struct ethhdr)) { -+ usbe->stats.rx_length_errors++; -+ usbe->stats.rx_errors++; -+ goto recycle; -+ } -+ -+ /* -+ * MAC must match our address or the broadcast address. -+ * Really, we should let any packet through, otherwise -+ * things that rely on multicast won't work. -+ */ -+ if (memcmp(skb->data, usbe->dev.dev_addr, ETH_ALEN) && -+ memcmp(skb->data, usbe->dev.broadcast, ETH_ALEN)) { -+ usbe->stats.rx_frame_errors++; -+ usbe->stats.rx_errors++; -+ goto recycle; -+ } -+ -+ /* -+ * We're going to consume this SKB. Get a new skb to -+ * replace it with. IF this fails, we'd better recycle -+ * the one we have. -+ */ -+ usbe->next_rx_skb = usb_new_recv_skb(usbe); -+ if (!usbe->next_rx_skb) { -+ if (net_ratelimit()) -+ printk(KERN_ERR "%s: can't allocate new rx skb\n", -+ usbe->dev.name); -+ usbe->stats.rx_dropped++; -+ goto recycle; -+ } -+ -+// FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ? -+ -+ usbe->stats.rx_packets++; -+ usbe->stats.rx_bytes += skb->len; -+ usbe->dev.last_rx = jiffies; -+ -+ skb->dev = &usbe->dev; -+ skb->protocol = eth_type_trans(skb, &usbe->dev); -+ skb->ip_summed = CHECKSUM_NONE; -+ -+ if (netif_rx(skb) == NET_RX_DROP) -+ usbe->stats.rx_dropped++; -+ return; -+ -+ error: -+ /* -+ * Oops, IO error, or stalled. -+ */ -+ switch (flag) { -+ case -EIO: /* aborted transfer */ -+ usbe->stats.rx_errors++; -+ break; -+ -+ case -EPIPE: /* fifo screwed/no data */ -+ usbe->stats.rx_fifo_errors++; -+ usbe->stats.rx_errors++; -+ break; -+ -+ case -EINTR: /* reset */ -+ break; -+ -+ case -EAGAIN: /* initialisation */ -+ break; -+ } -+ -+ oversize: -+ skb_trim(skb, 0); -+ -+#ifndef RX_NO_COPY -+ buf = usbe->dmabuf; -+ size = usb_rsize; -+#else -+ buf = skb->tail; -+ size = skb_tailroom(skb); -+#endif -+ usbctl_ep_queue_buffer(usbe->client.ctl, 1, buf, size); -+ return; -+ -+ recycle: -+ skb_trim(skb, 0); -+ usbe->next_rx_skb = skb; -+ return; -+} -+ -+/* -+ * Send a skb. -+ * -+ * Note that the receiver expects the last packet to be a non-multiple -+ * of its rsize. If the packet length is a muliple of wsize (and -+ * therefore the remote rsize) tweak the length. -+ */ -+static void usbeth_send(struct sk_buff *skb, struct usbe_info *usbe) -+{ -+ unsigned int len = skb->len; -+ int ret; -+ -+ if ((len % usb_wsize) == 0) -+ len++; -+ -+ ret = usbctl_ep_queue_buffer(usbe->client.ctl, 2, skb->data, len); -+ if (ret) { -+ printk(KERN_ERR "%s: tx dropping packet: %d\n", -+ usbe->dev.name, ret); -+ -+ /* -+ * If the USB core can't accept the packet, we drop it. -+ */ -+ dev_kfree_skb_irq(skb); -+ -+ usbe->cur_tx_skb = NULL; -+ usbe->stats.tx_carrier_errors++; -+ } else { -+ usbe->dev.trans_start = jiffies; -+ } -+} -+ -+static void usbeth_send_callback(void *data, int flag, int size) -+{ -+ struct usbe_info *usbe = data; -+ struct sk_buff *skb = usbe->cur_tx_skb; -+ -+ switch (flag) { -+ case 0: -+ usbe->stats.tx_packets++; -+ usbe->stats.tx_bytes += skb->len; -+ break; -+ case -EIO: -+ usbe->stats.tx_errors++; -+ break; -+ default: -+ usbe->stats.tx_dropped++; -+ break; -+ } -+ -+ dev_kfree_skb_irq(skb); -+ -+ skb = usbe->cur_tx_skb = usbe->next_tx_skb; -+ usbe->next_tx_skb = NULL; -+ -+ if (skb) -+ usbeth_send(skb, usbe); -+ -+ netif_wake_queue(&usbe->dev); -+} -+ -+static int usbeth_xmit(struct sk_buff *skb, struct net_device *dev) -+{ -+ struct usbe_info *usbe = dev->priv; -+ unsigned long flags; -+ -+ if (usbe->next_tx_skb) { -+ printk(KERN_ERR "%s: called with next_tx_skb != NULL\n", -+ usbe->dev.name); -+ return 1; -+ } -+ -+ local_irq_save(flags); -+ if (usbe->cur_tx_skb) { -+ usbe->next_tx_skb = skb; -+ netif_stop_queue(dev); -+ } else { -+ usbe->cur_tx_skb = skb; -+ -+ usbeth_send(skb, usbe); -+ } -+ local_irq_restore(flags); -+ return 0; -+} -+ -+/* -+ * Transmit timed out. Reset the endpoint, and re-queue the pending -+ * packet. If we have a free transmit slot, wake the transmit queue. -+ */ -+static void usbeth_xmit_timeout(struct net_device *dev) -+{ -+ struct usbe_info *usbe = dev->priv; -+ unsigned long flags; -+ -+ usbctl_ep_reset(usbe->client.ctl, 2); -+ -+ local_irq_save(flags); -+ if (usbe->cur_tx_skb) -+ usbeth_send(usbe->cur_tx_skb, usbe); -+ -+ if (usbe->next_tx_skb == NULL) -+ netif_wake_queue(dev); -+ -+ usbe->stats.tx_errors++; -+ local_irq_restore(flags); -+} -+ -+static int usbeth_open(struct net_device *dev) -+{ -+ struct usbe_info *usbe = dev->priv; -+ unsigned char *buf; -+ unsigned int size; -+ -+ usbctl_ep_set_callback(usbe->client.ctl, 2, usbeth_send_callback, usbe); -+ usbctl_ep_set_callback(usbe->client.ctl, 1, usbeth_recv_callback, usbe); -+ -+ usbe->cur_tx_skb = usbe->next_tx_skb = NULL; -+ usbe->cur_rx_skb = usb_new_recv_skb(usbe); -+ usbe->next_rx_skb = usb_new_recv_skb(usbe); -+ if (!usbe->cur_rx_skb || !usbe->next_rx_skb) { -+ printk(KERN_ERR "%s: can't allocate new skb\n", -+ usbe->dev.name); -+ if (usbe->cur_rx_skb) -+ kfree_skb(usbe->cur_rx_skb); -+ if (usbe->next_rx_skb) -+ kfree_skb(usbe->next_rx_skb); -+ return -ENOMEM;; -+ } -+#ifndef RX_NO_COPY -+ buf = usbe->dmabuf; -+ size = usb_rsize; -+#else -+ buf = usbe->cur_rx_skb->tail; -+ size = skb_tailroom(usbe->cur_rx_skb); -+#endif -+ usbctl_ep_queue_buffer(usbe->client.ctl, 1, buf, size); -+ -+ if (netif_carrier_ok(dev)) -+ netif_start_queue(dev); -+ -+ return 0; -+} -+ -+static int usbeth_close(struct net_device *dev) -+{ -+ struct usbe_info *usbe = dev->priv; -+ -+ netif_stop_queue(dev); -+ -+ usbctl_ep_set_callback(usbe->client.ctl, 2, NULL, NULL); -+ usbctl_ep_set_callback(usbe->client.ctl, 1, NULL, NULL); -+ usbctl_ep_reset(usbe->client.ctl, 2); -+ usbctl_ep_reset(usbe->client.ctl, 1); -+ -+ if (usbe->cur_tx_skb) -+ kfree_skb(usbe->cur_tx_skb); -+ if (usbe->next_tx_skb) -+ kfree_skb(usbe->next_tx_skb); -+ if (usbe->cur_rx_skb) -+ kfree_skb(usbe->cur_rx_skb); -+ if (usbe->next_rx_skb) -+ kfree_skb(usbe->next_rx_skb); -+ -+ return 0; -+} -+ -+static struct net_device_stats *usbeth_stats(struct net_device *dev) -+{ -+ struct usbe_info *usbe = dev->priv; -+ -+ return &usbe->stats; -+} -+ -+static int __init usbeth_probe(struct net_device *dev) -+{ -+ u8 node_id[ETH_ALEN]; -+ -+ SET_MODULE_OWNER(dev); -+ -+ /* -+ * Assign the hardware address of the board: -+ * generate it randomly, as there can be many such -+ * devices on the bus. -+ */ -+ get_random_bytes(node_id, sizeof node_id); -+ node_id[0] &= 0xfe; // clear multicast bit -+ memcpy(dev->dev_addr, node_id, sizeof node_id); -+ -+ ether_setup(dev); -+ dev->flags &= ~IFF_MULTICAST; -+ dev->flags &= ~IFF_BROADCAST; -+ //dev->flags |= IFF_NOARP; -+ -+ return 0; -+} -+ -+/* -+ * This is called when something in the upper usb client layers -+ * changes that affects the endpoint connectivity state (eg, -+ * connection or disconnection from the host.) We probably want -+ * to do some more handling here, like kicking off a pending -+ * transmission if we're running? -+ */ -+static void usbeth_state_change(void *data, int state, int oldstate) -+{ -+ struct usbe_info *usbe = data; -+ -+ if (state == USB_STATE_CONFIGURED) { -+ netif_carrier_on(&usbe->dev); -+ if (netif_running(&usbe->dev)) -+ netif_wake_queue(&usbe->dev); -+ } else { -+ if (netif_running(&usbe->dev)) -+ netif_stop_queue(&usbe->dev); -+ netif_carrier_off(&usbe->dev); -+ } -+} -+ -+static struct usbe_info usbe_info = { -+ .dev = { -+ .name = "usbf", -+ .init = usbeth_probe, -+ .get_stats = usbeth_stats, -+ .watchdog_timeo = 1 * HZ, -+ .open = usbeth_open, -+ .stop = usbeth_close, -+ .hard_start_xmit = usbeth_xmit, -+ .change_mtu = usbeth_change_mtu, -+ .tx_timeout = usbeth_xmit_timeout, -+ .priv = &usbe_info, -+ }, -+ .client = { -+ .name = "usbeth", -+ .priv = &usbe_info, -+ .state_change = usbeth_state_change, -+ -+ /* -+ * USB client identification for host use in CPU endian. -+ */ -+ .vendor = ETHERNET_VENDOR_ID, -+ .product = ETHERNET_PRODUCT_ID, -+ .version = 0, -+ .class = 0xff, /* vendor specific */ -+ .subclass = 0, -+ .protocol = 0, -+ -+ .product_str = "SA1100 USB NIC", -+ }, -+}; -+ -+static int __init usbeth_init(void) -+{ -+ int rc; -+ -+#ifndef RX_NO_COPY -+ usbe_info.dmabuf = kmalloc(usb_rsize, GFP_KERNEL | GFP_DMA); -+ if (!usbe_info.dmabuf) -+ return -ENOMEM; -+#endif -+ -+ if (register_netdev(&usbe_info.dev) != 0) { -+#ifndef RX_NO_COPY -+ kfree(usbe_info.dmabuf); -+#endif -+ return -EIO; -+ } -+ -+ rc = usbctl_open(&usbe_info.client); -+ if (rc == 0) { -+ struct cdb *cdb = sa1100_usb_get_descriptor_ptr(); -+ -+ cdb->ep1.wMaxPacketSize = cpu_to_le16(usb_rsize); -+ cdb->ep2.wMaxPacketSize = cpu_to_le16(usb_wsize); -+ -+ rc = usbctl_start(&usbe_info.client); -+ if (rc) -+ usbctl_close(&usbe_info.client); -+ } -+ -+ if (rc) { -+ unregister_netdev(&usbe_info.dev); -+#ifndef RX_NO_COPY -+ kfree(usbe_info.dmabuf); -+#endif -+ } -+ -+ return rc; -+} -+ -+static void __exit usbeth_cleanup(void) -+{ -+ usbctl_stop(&usbe_info.client); -+ usbctl_close(&usbe_info.client); -+ -+ unregister_netdev(&usbe_info.dev); -+#ifndef RX_NO_COPY -+ kfree(usbe_info.dmabuf); -+#endif -+} -+ -+module_init(usbeth_init); -+module_exit(usbeth_cleanup); -+ -+MODULE_DESCRIPTION("USB client ethernet driver"); -+MODULE_PARM(usb_rsize, "1i"); -+MODULE_PARM_DESC(usb_rsize, "number of bytes in packets from host to sa11x0"); -+MODULE_PARM(usb_wsize, "1i"); -+MODULE_PARM_DESC(usb_wsize, "number of bytes in packets from sa11x0 to host"); -+MODULE_LICENSE("GPL"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/usb_recv.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,318 @@ -+/* -+ * Generic receive layer for the SA1100 USB client function -+ * Copyright (c) 2001 by Nicolas Pitre -+ * -+ * This code was loosely inspired by the original version which was -+ * Copyright (c) Compaq Computer Corporation, 1998-1999 -+ * -+ * 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 is still work in progress... -+ * -+ * Please see linux/Documentation/arm/SA1100/SA1100_USB for details. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "sa1100_usb.h" -+#include "sa1100usb.h" -+ -+static int naking; -+ -+#if 1 -+static void dump_buf(struct sausb_dev *usb, const char *prefix) -+{ -+ printk("%s: buf [dma=%08x len=%3d] pkt [cpu=%08x dma=%08x len=%3d rem=%3d]\n", -+ prefix, -+ usb->ep[0].bufdma, -+ usb->ep[0].buflen, -+ (unsigned int)usb->ep[0].pktcpu, -+ usb->ep[0].pktdma, -+ usb->ep[0].pktlen, -+ usb->ep[0].pktrem); -+} -+#endif -+ -+static void udc_ep1_done(struct sausb_dev *usb, int flag, int size) -+{ -+// printk("UDC: rxd: %3d %3d\n", flag, size); -+ dump_buf(usb, "UDC: rxd"); -+ -+ if (!usb->ep[0].buflen) -+ return; -+ -+ dma_unmap_single(usb->dev, usb->ep[0].bufdma, usb->ep[0].buflen, -+ DMA_FROM_DEVICE); -+ -+ usb->ep[0].bufdma = 0; -+ usb->ep[0].buflen = 0; -+ usb->ep[0].pktcpu = NULL; -+ usb->ep[0].pktdma = 0; -+ usb->ep[0].pktlen = 0; -+ usb->ep[0].pktrem = 0; -+ -+ if (usb->ep[0].cb_func) -+ usb->ep[0].cb_func(usb->ep[0].cb_data, flag, size); -+} -+ -+/* -+ * Initialisation. Clear out the status, and set FST. -+ */ -+void udc_ep1_init(struct sausb_dev *usb) -+{ -+ sa1100_reset_dma(usb->ep[0].dmach); -+ -+ UDC_clear(Ser0UDCCS1, UDCCS1_FST | UDCCS1_RPE | UDCCS1_RPC); -+ -+ BUG_ON(usb->ep[0].buflen); -+ BUG_ON(usb->ep[0].pktlen); -+} -+ -+void udc_ep1_halt(struct sausb_dev *usb, int halt) -+{ -+ if (halt) { -+ /* force stall at UDC */ -+ UDC_set(Ser0UDCCS1, UDCCS1_FST); -+ } else { -+ sa1100_reset_dma(usb->ep[0].dmach); -+ -+ UDC_clear(Ser0UDCCS1, UDCCS1_FST); -+ -+ udc_ep1_done(usb, -EINTR, 0); -+ } -+} -+ -+/* -+ * This gets called when we receive a SET_CONFIGURATION packet to EP0. -+ * We were configured. We can now accept packets from the host. -+ */ -+void udc_ep1_config(struct sausb_dev *usb, unsigned int maxpktsize) -+{ -+ usb->ep[0].maxpktsize = maxpktsize; -+ usb->ep[0].configured = 1; -+ -+ Ser0UDCOMP = maxpktsize - 1; -+ -+ sa1100_reset_dma(usb->ep[0].dmach); -+ udc_ep1_done(usb, -EINTR, 0); -+ -+ /* -+ * Enable EP1 interrupts. -+ */ -+ usb->udccr &= ~UDCCR_RIM; -+ UDC_write(Ser0UDCCR, usb->udccr); -+} -+ -+/* -+ * We saw a reset from the attached hub. This means we are no -+ * longer configured, and as far as the rest of the world is -+ * concerned, we don't exist. -+ */ -+void udc_ep1_reset(struct sausb_dev *usb) -+{ -+ /* -+ * Disable EP1 interrupts. -+ */ -+ usb->udccr |= UDCCR_RIM; -+ UDC_write(Ser0UDCCR, usb->udccr); -+ -+ usb->ep[0].configured = 0; -+ usb->ep[0].maxpktsize = 0; -+ -+ sa1100_reset_dma(usb->ep[0].dmach); -+ udc_ep1_done(usb, -EINTR, 0); -+} -+ -+void udc_ep1_int_hndlr(struct sausb_dev *usb) -+{ -+ dma_addr_t dma_addr; -+ unsigned int len; -+ u32 status = Ser0UDCCS1; -+ -+ dump_buf(usb, "UDC: int"); -+ -+ if (naking) { -+ printk("UDC: usbrx: in ISR but naking [0x%02x]\n", status); -+ return; -+ } -+ -+ if (!(status & UDCCS1_RPC)) -+ /* you can get here if we are holding NAK */ -+ return; -+ -+ if (!usb->ep[0].buflen) { -+ printk("UDC: usb_recv: RPC for non-existent buffer [0x%02x]\n", status); -+ naking = 1; -+ return; -+ } -+ -+ sa1100_stop_dma(usb->ep[0].dmach); -+ -+ dma_addr = sa1100_get_dma_pos(usb->ep[0].dmach); -+ -+ /* -+ * We've finished with the DMA for this packet. -+ */ -+ sa1100_clear_dma(usb->ep[0].dmach); -+ -+ if (status & UDCCS1_SST) { -+ printk("UDC: usb_recv: stall sent\n"); -+ UDC_flip(Ser0UDCCS1, UDCCS1_SST); -+ -+ /* -+ * UDC aborted current transfer, so we do. -+ * -+ * It would be better to re-queue this buffer IMHO. It -+ * hasn't gone anywhere yet. --rmk -+ */ -+ UDC_flip(Ser0UDCCS1, UDCCS1_RPC); -+ udc_ep1_done(usb, -EIO, 0); -+ return; -+ } -+ -+ if (status & UDCCS1_RPE) { -+ printk("UDC: usb_recv: RPError %x\n", status); -+ UDC_flip(Ser0UDCCS1, UDCCS1_RPC); -+ udc_ep1_done(usb, -EIO, 0); -+ return; -+ } -+ -+ len = dma_addr - usb->ep[0].pktdma; -+ if (len < 0) { -+ printk("UDC: usb_recv: dma_addr (%x) < pktdma (%x)\n", -+ dma_addr, usb->ep[0].pktdma); -+ len = 0; -+ } -+ -+ if (len > usb->ep[0].pktlen) -+ len = usb->ep[0].pktlen; -+ -+ /* -+ * If our transfer was smaller, and we have bytes left in -+ * the FIFO, we need to read them out manually. -+ */ -+ if (len < usb->ep[0].pktlen && (Ser0UDCCS1 & UDCCS1_RNE)) { -+ char *buf; -+ -+ dma_sync_single(usb->dev, usb->ep[0].pktdma + len, -+ usb->ep[0].pktlen - len, DMA_FROM_DEVICE); -+ -+ buf = (char *)usb->ep[0].pktcpu + len; -+ -+ do { -+ *buf++ = Ser0UDCDR; -+ len++; -+ } while (len < usb->ep[0].pktlen && (Ser0UDCCS1 & UDCCS1_RNE)); -+ -+ /* -+ * Note: knowing the internals of this macro is BAD, but we -+ * need this to cause the data to be written back to memory. -+ */ -+ dma_sync_single(usb->dev, usb->ep[0].pktdma + len, -+ usb->ep[0].pktlen - len, DMA_TO_DEVICE); -+ } -+ -+ /* -+ * If the FIFO still contains data, something's definitely wrong. -+ */ -+ if (Ser0UDCCS1 & UDCCS1_RNE) { -+ printk("UDC: usb_recv: fifo screwed, shouldn't contain data\n"); -+ usb->ep[0].fifo_errs++; -+ naking = 1; -+ udc_ep1_done(usb, -EPIPE, 0); -+ return; -+ } -+ -+ /* -+ * Do statistics. -+ */ -+ if (len) { -+ usb->ep[0].bytes += len; -+ usb->ep[0].packets ++; -+ } -+ -+ /* -+ * Update remaining byte count for this buffer. -+ */ -+ usb->ep[0].pktrem -= len; -+ -+ /* -+ * If we received a full-sized packet, and there's more -+ * data remaining, th, queue up another receive. -+ */ -+ if (len == usb->ep[0].pktlen && usb->ep[0].pktrem != 0) { -+ usb->ep[0].pktcpu += len; -+ usb->ep[0].pktdma += len; -+ usb->ep[0].pktlen = min(usb->ep[0].pktrem, usb->ep[0].maxpktsize); -+ sa1100_start_dma(usb->ep[0].dmach, usb->ep[0].pktdma, usb->ep[0].pktlen); -+ /* -+ * Clear RPC to receive next packet. -+ */ -+ UDC_flip(Ser0UDCCS1, UDCCS1_RPC); -+ dump_buf(usb, "UDC: req"); -+ return; -+ } -+ -+ naking = 1; -+ udc_ep1_done(usb, 0, usb->ep[0].buflen - usb->ep[0].pktrem); -+} -+ -+int udc_ep1_queue_buffer(struct sausb_dev *usb, char *buf, unsigned int len) -+{ -+ unsigned long flags; -+ dma_addr_t dma; -+ int ret; -+ -+ if (!buf || len == 0) -+ return -EINVAL; -+ -+ dma = dma_map_single(usb->dev, buf, len, DMA_FROM_DEVICE); -+ -+ spin_lock_irqsave(&usb->lock, flags); -+ do { -+ if (usb->ep[0].buflen) { -+ ret = -EBUSY; -+ break; -+ } -+ -+ sa1100_clear_dma(usb->ep[0].dmach); -+ -+ usb->ep[0].bufdma = dma; -+ usb->ep[0].buflen = len; -+ usb->ep[0].pktcpu = buf; -+ usb->ep[0].pktdma = dma; -+ usb->ep[0].pktlen = min(len, usb->ep[0].maxpktsize); -+ usb->ep[0].pktrem = len; -+ -+ sa1100_start_dma(usb->ep[0].dmach, usb->ep[0].bufdma, usb->ep[0].buflen); -+ dump_buf(usb, "UDC: que"); -+ -+ if (naking) { -+ /* turn off NAK of OUT packets, if set */ -+ UDC_flip(Ser0UDCCS1, UDCCS1_RPC); -+ naking = 0; -+ } -+ -+ ret = 0; -+ } while (0); -+ spin_unlock_irqrestore(&usb->lock, flags); -+ -+ if (ret) -+ dma_unmap_single(usb->dev, dma, len, DMA_FROM_DEVICE); -+ -+ return 0; -+} -+ -+void udc_ep1_recv_reset(struct sausb_dev *usb) -+{ -+ sa1100_reset_dma(usb->ep[0].dmach); -+ udc_ep1_done(usb, -EINTR, 0); -+} ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/buffer.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,63 @@ -+/* -+ * usb/buffer.c -+ * -+ * Copyright (C) 2002 Russell King. -+ */ -+#include -+#include -+#include -+ -+#include "buffer.h" -+ -+static LIST_HEAD(buffers); -+ -+struct usb_buf *usbb_alloc(int size, int gfp) -+{ -+ unsigned long flags; -+ struct usb_buf *buf; -+ -+ buf = kmalloc(sizeof(struct usb_buf) + size, gfp); -+ if (buf) { -+ atomic_set(&buf->users, 1); -+ local_irq_save(flags); -+ list_add(&buf->list, &buffers); -+ local_irq_restore(flags); -+ buf->len = 0; -+ buf->data = (unsigned char *) (buf + 1); -+ buf->head = (unsigned char *) (buf + 1); -+ } -+ -+ return buf; -+} -+ -+void __usbb_free(struct usb_buf *buf) -+{ -+ unsigned long flags; -+ local_irq_save(flags); -+ list_del(&buf->list); -+ local_irq_restore(flags); -+ kfree(buf); -+} -+ -+EXPORT_SYMBOL(usbb_alloc); -+EXPORT_SYMBOL(__usbb_free); -+ -+static void __exit usbb_exit(void) -+{ -+ if (!list_empty(&buffers)) { -+ struct list_head *l, *n; -+ printk("usbb: buffers not freed:\n"); -+ -+ list_for_each_safe(l, n, &buffers) { -+ struct usb_buf *b = list_entry(l, struct usb_buf, list); -+ -+ printk(" %p: alloced from %p count %d\n", -+ b, b->alloced_by, atomic_read(&b->users)); -+ -+ __usbb_free(b); -+ } -+ } -+} -+ -+module_exit(usbb_exit); -+ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/usb-char.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (C) 2001 Extenex Corporation -+ * -+ * usb-char.h -+ * -+ * Character device emulation client for SA-1100 client usb core. -+ * -+ * -+ * -+ */ -+#ifndef _USB_CHAR_H -+#define _USB_CHAR_H -+ -+#define USBC_MAJOR 10 /* miscellaneous character device */ -+#define USBC_MINOR 240 /* in the "reserved for local use" range */ -+ -+#define USBC_MAGIC 0x8E -+ -+/* zap everything in receive ring buffer */ -+#define USBC_IOC_FLUSH_RECEIVER _IO( USBC_MAGIC, 0x01 ) -+ -+/* reset transmitter */ -+#define USBC_IOC_FLUSH_TRANSMITTER _IO( USBC_MAGIC, 0x02 ) -+ -+/* do both of above */ -+#define USBC_IOC_FLUSH_ALL _IO( USBC_MAGIC, 0x03 ) -+ -+ -+ -+ -+ -+ -+#endif /* _USB_CHAR_H */ -+ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/buffer.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,45 @@ -+/* -+ * usb/buffer.h: USB client buffers -+ * -+ * Copyright (C) 2002 Russell King. -+ * -+ * Loosely based on linux/skbuff.h -+ */ -+#ifndef USBDEV_BUFFER_H -+#define USBDEV_BUFFER_H -+ -+#include -+ -+struct usb_buf { -+ atomic_t users; -+ struct list_head list; -+ void *alloced_by; -+ unsigned char *data; -+ unsigned char *head; -+ unsigned int len; -+}; -+ -+extern struct usb_buf *usbb_alloc(int size, int gfp); -+extern void __usbb_free(struct usb_buf *); -+ -+static inline struct usb_buf *usbb_get(struct usb_buf *buf) -+{ -+ atomic_inc(&buf->users); -+ return buf; -+} -+ -+static inline void usbb_put(struct usb_buf *buf) -+{ -+ if (atomic_dec_and_test(&buf->users)) -+ __usbb_free(buf); -+} -+ -+static inline void *usbb_push(struct usb_buf *buf, int len) -+{ -+ unsigned char *b = buf->head; -+ buf->head += len; -+ buf->len += len; -+ return b; -+} -+ -+#endif ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/sa1100usb.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,1160 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "buffer.h" -+#include "usbdev.h" -+#include "sa1100_usb.h" -+#include "sa1100usb.h" -+ -+#ifdef DEBUG -+#define DPRINTK(fmt, args...) printk( fmt , ## args) -+#else -+#define DPRINTK(fmt, args...) -+#endif -+ -+static inline void pcs(const char *prefix) -+{ -+#ifdef DEBUG -+ __u32 foo = Ser0UDCCS0; -+ -+ DPRINTK("%s UDCAR: %d\n", prefix, Ser0UDCAR); -+ -+ printk("UDC: %s: %08x [ %s%s%s%s%s%s]\n", prefix, -+ foo, -+ foo & UDCCS0_SE ? "SE " : "", -+ foo & UDCCS0_DE ? "DE " : "", -+ foo & UDCCS0_FST ? "FST " : "", -+ foo & UDCCS0_SST ? "SST " : "", -+ foo & UDCCS0_IPR ? "IPR " : "", -+ foo & UDCCS0_OPR ? "OPR " : ""); -+#endif -+} -+ -+/* -+ * soft_connect_hook() -+ * -+ * Some devices have platform-specific circuitry to make USB -+ * not seem to be plugged in, even when it is. This allows -+ * software to control when a device 'appears' on the USB bus -+ * (after Linux has booted and this driver has loaded, for -+ * example). If you have such a circuit, control it here. -+ */ -+static inline void soft_connect_hook(int enable) -+{ -+#ifdef CONFIG_SA1100_EXTENEX1 -+ if (machine_is_extenex1()) { -+ if (enable) { -+ PPDR |= PPC_USB_SOFT_CON; -+ PPSR |= PPC_USB_SOFT_CON; -+ } else { -+ PPSR &= ~PPC_USB_SOFT_CON; -+ PPDR &= ~PPC_USB_SOFT_CON; -+ } -+ } -+#endif -+} -+ -+/* -+ * disable the UDC at the source -+ */ -+static inline void udc_disable(struct sausb_dev *usb) -+{ -+ soft_connect_hook(0); -+ -+ usb->udccr = UDCCR_UDD | UDCCR_SUSIM; -+ -+ UDC_write(Ser0UDCCR, usb->udccr); -+} -+ -+/* -+ * Clear any pending write from the EP0 write buffer. -+ */ -+static void ep0_clear_write(struct sausb_dev *usb) -+{ -+ struct usb_buf *buf; -+ -+ buf = usb->wrbuf; -+ usb->wrint = NULL; -+ usb->wrbuf = NULL; -+ usb->wrptr = NULL; -+ usb->wrlen = 0; -+ -+ if (buf) -+ usbb_put(buf); -+} -+ -+static int udc_start(void *priv) -+{ -+ struct sausb_dev *usb = priv; -+ -+ usb->ep[0].maxpktsize = 0; -+ usb->ep[1].maxpktsize = 0; -+ -+ /* -+ * start UDC internal machinery running, but mask interrupts. -+ */ -+ usb->udccr = UDCCR_SUSIM | UDCCR_TIM | UDCCR_RIM | UDCCR_EIM | -+ UDCCR_RESIM; -+ UDC_write(Ser0UDCCR, usb->udccr); -+ -+ udelay(100); -+ -+ /* -+ * clear all interrupt sources -+ */ -+ Ser0UDCSR = UDCSR_RSTIR | UDCSR_RESIR | UDCSR_EIR | -+ UDCSR_RIR | UDCSR_TIR | UDCSR_SUSIR; -+ -+ /* -+ * flush DMA and fire through some -EAGAINs -+ */ -+ udc_ep1_init(usb); -+ udc_ep2_init(usb); -+ -+ /* -+ * enable any platform specific hardware -+ */ -+ soft_connect_hook(1); -+ -+ /* -+ * Enable resume, suspend and endpoint 0 interrupts. Leave -+ * endpoint 1 and 2 interrupts masked. -+ * -+ * If you are unplugged you will immediately get a suspend -+ * interrupt. If you are plugged and have a soft connect-circuit, -+ * you will get a reset. If you are plugged without a soft-connect, -+ * I think you also get suspend. -+ */ -+ usb->udccr &= ~(UDCCR_SUSIM | UDCCR_EIM | UDCCR_RESIM); -+ UDC_write(Ser0UDCCR, usb->udccr); -+ -+ return 0; -+} -+ -+static int udc_stop(void *priv) -+{ -+ struct sausb_dev *usb = priv; -+ -+ ep0_clear_write(usb); -+ -+ /* mask everything */ -+ Ser0UDCCR = 0xFC; -+ -+ udc_ep1_reset(usb); -+ udc_ep2_reset(usb); -+ -+ udc_disable(usb); -+ -+ return 0; -+} -+ -+ -+ -+ -+ -+/* -+ * some voodo I am adding, since the vanilla macros just aren't doing it -+ * 1Mar01ww -+ */ -+ -+#define ABORT_BITS (UDCCS0_SST | UDCCS0_SE) -+#define OK_TO_WRITE (!(Ser0UDCCS0 & ABORT_BITS)) -+#define BOTH_BITS (UDCCS0_IPR | UDCCS0_DE) -+ -+static void set_de(void) -+{ -+ int i = 1; -+ -+ while (1) { -+ if (OK_TO_WRITE) { -+ Ser0UDCCS0 |= UDCCS0_DE; -+ } else { -+ DPRINTK("UDC: quitting set DE because SST or SE set\n"); -+ break; -+ } -+ if (Ser0UDCCS0 & UDCCS0_DE) -+ break; -+ udelay(i); -+ if (++i == 50) { -+ printk("UDC: Dangnabbbit! Cannot set DE! (DE=%8.8X CCS0=%8.8X)\n", -+ UDCCS0_DE, Ser0UDCCS0); -+ break; -+ } -+ } -+} -+ -+static void set_ipr(void) -+{ -+ int i = 1; -+ -+ while (1) { -+ if (OK_TO_WRITE) { -+ Ser0UDCCS0 |= UDCCS0_IPR; -+ } else { -+ DPRINTK("UDC: Quitting set IPR because SST or SE set\n"); -+ break; -+ } -+ if (Ser0UDCCS0 & UDCCS0_IPR) -+ break; -+ udelay(i); -+ if (++i == 50) { -+ printk("UDC: Dangnabbbit! Cannot set IPR! (IPR=%8.8X CCS0=%8.8X)\n", -+ UDCCS0_IPR, Ser0UDCCS0); -+ break; -+ } -+ } -+} -+ -+static void set_ipr_and_de(void) -+{ -+ int i = 1; -+ -+ while (1) { -+ if (OK_TO_WRITE) { -+ Ser0UDCCS0 |= BOTH_BITS; -+ } else { -+ DPRINTK("UDC: Quitting set IPR/DE because SST or SE set\n"); -+ break; -+ } -+ if ((Ser0UDCCS0 & BOTH_BITS) == BOTH_BITS) -+ break; -+ udelay(i); -+ if (++i == 50) { -+ printk("UDC: Dangnabbbit! Cannot set DE/IPR! (DE=%8.8X IPR=%8.8X CCS0=%8.8X)\n", -+ UDCCS0_DE, UDCCS0_IPR, Ser0UDCCS0); -+ break; -+ } -+ } -+} -+ -+static inline void set_cs_bits(__u32 bits) -+{ -+ if (bits & (UDCCS0_SO | UDCCS0_SSE | UDCCS0_FST | UDCCS0_SST)) -+ Ser0UDCCS0 = bits; -+ else if ((bits & BOTH_BITS) == BOTH_BITS) -+ set_ipr_and_de(); -+ else if (bits & UDCCS0_IPR) -+ set_ipr(); -+ else if (bits & UDCCS0_DE) -+ set_de(); -+} -+ -+/* -+ * udc_ep0_write_fifo() -+ * -+ * Stick bytes in the 8 bytes endpoint zero FIFO. This version uses a -+ * variety of tricks to make sure the bytes are written correctly: -+ * 1. The count register is checked to see if the byte went in, -+ * and the write is attempted again if not. -+ * 2. An overall counter is used to break out so we don't hang in -+ * those (rare) cases where the UDC reverses direction of the -+ * FIFO underneath us without notification (in response to host -+ * aborting a setup transaction early). -+ */ -+static void udc_ep0_write_fifo(struct sausb_dev *usb) -+{ -+ unsigned int bytes_this_time = min(usb->wrlen, 8U); -+ int bytes_written = 0; -+ -+ DPRINTK("WF=%d: ", bytes_this_time); -+ -+ while (bytes_this_time--) { -+ unsigned int cwc; -+ int i; -+ -+ DPRINTK("%2.2X ", *usb->wrptr); -+ -+ cwc = Ser0UDCWC & 15; -+ -+ i = 10; -+ do { -+ Ser0UDCD0 = *usb->wrptr; -+ udelay(20); /* voodo 28Feb01ww */ -+ } while ((Ser0UDCWC & 15) == cwc && --i); -+ -+ if (i == 0) { -+ printk("UDC: udc_ep0_write_fifo: write failure\n"); -+ usb->ep0_wr_fifo_errs++; -+ } -+ -+ usb->wrptr++; -+ bytes_written++; -+ } -+ usb->wrlen -= bytes_written; -+ -+ /* following propagation voodo so maybe caller writing IPR in -+ ..a moment might actually get it to stick 28Feb01ww */ -+ udelay(300); -+ -+ usb->ep0_wr_bytes += bytes_written; -+ DPRINTK("L=%d WCR=%8.8X\n", usb->wrlen, Ser0UDCWC); -+} -+ -+/* -+ * read_fifo() -+ * -+ * Read 1-8 bytes out of FIFO and put in request. Called to do the -+ * initial read of setup requests from the host. Return number of -+ * bytes read. -+ * -+ * Like write fifo above, this driver uses multiple reads checked -+ * against the count register with an overall timeout. -+ */ -+static int -+udc_ep0_read_fifo(struct sausb_dev *usb, struct usb_ctrlrequest *request, int sz) -+{ -+ unsigned char *pOut = (unsigned char *) request; -+ unsigned int fifo_count, bytes_read = 0; -+ -+ fifo_count = Ser0UDCWC & 15; -+ -+ DPRINTK("RF=%d ", fifo_count); -+ BUG_ON(fifo_count > sz); -+ -+ while (fifo_count--) { -+ unsigned int cwc; -+ int i; -+ -+ cwc = Ser0UDCWC & 15; -+ -+ i = 10; -+ do { -+ *pOut = (unsigned char) Ser0UDCD0; -+ udelay(20); -+ } while ((Ser0UDCWC & 15) == cwc && --i); -+ -+ if (i == 0) { -+ printk(KERN_ERR "UDC: udc_ep0_read_fifo: read failure\n"); -+ usb->ep0_rd_fifo_errs++; -+ break; -+ } -+ pOut++; -+ bytes_read++; -+ } -+ -+ DPRINTK("fc=%d\n", bytes_read); -+ usb->ep0_rd_bytes += bytes_read; -+ usb->ep0_rd_packets ++; -+ return bytes_read; -+} -+ -+static void ep0_sh_write_data(struct sausb_dev *usb) -+{ -+ /* -+ * If bytes left is zero, we are coming in on the -+ * interrupt after the last packet went out. And -+ * we know we don't have to empty packet this -+ * transfer so just set DE and we are done -+ */ -+ set_cs_bits(UDCCS0_DE); -+} -+ -+static void ep0_sh_write_with_empty_packet(struct sausb_dev *usb) -+{ -+ /* -+ * If bytes left is zero, we are coming in on the -+ * interrupt after the last packet went out. -+ * We must do short packet suff, so set DE and IPR -+ */ -+ set_cs_bits(UDCCS0_IPR | UDCCS0_DE); -+ DPRINTK("UDC: sh_write_empty: Sent empty packet\n"); -+} -+ -+static int udc_clear_opr(void) -+{ -+ int i = 10000; -+ int is_clear; -+ -+ /*FIXME*/ -+ do { -+ Ser0UDCCS0 = UDCCS0_SO; -+ is_clear = !(Ser0UDCCS0 & UDCCS0_OPR); -+ if (i-- <= 0) -+ break; -+ } while (!is_clear); -+ -+ return is_clear; -+} -+ -+static int udc_ep0_queue(void *priv, struct usb_buf *buf, -+ unsigned int req_len) -+{ -+ struct sausb_dev *usb = priv; -+ __u32 cs_reg_bits = UDCCS0_IPR; -+ -+ DPRINTK("a=%d r=%d\n", buf->len, req_len); -+ -+ /* -+ * thou shalt not enter data phase until -+ * Out Packet Ready is clear -+ */ -+ if (!udc_clear_opr()) { -+ printk("UDC: SO did not clear OPR\n"); -+ set_cs_bits(UDCCS0_DE | UDCCS0_SO); -+ usbb_put(buf); -+ return 1; -+ } -+ -+ usb->ep0_wr_packets++; -+ -+ usb->wrbuf = buf; -+ usb->wrptr = buf->data; -+ usb->wrlen = min(buf->len, req_len); -+ -+ udc_ep0_write_fifo(usb); -+ -+ if (usb->wrlen == 0) { -+ /* -+ * out in one, so data end -+ */ -+ cs_reg_bits |= UDCCS0_DE; -+ ep0_clear_write(usb); -+ } else if (buf->len < req_len) { -+ /* -+ * we are going to short-change host -+ * so need nul to not stall -+ */ -+ usb->wrint = ep0_sh_write_with_empty_packet; -+ } else { -+ /* -+ * we have as much or more than requested -+ */ -+ usb->wrint = ep0_sh_write_data; -+ } -+ -+ /* -+ * note: IPR was set uncondtionally at start of routine -+ */ -+ set_cs_bits(cs_reg_bits); -+ return 0; -+} -+ -+/* -+ * When SO and DE sent, UDC will enter status phase and ack, propagating -+ * new address to udc core. Next control transfer will be on the new -+ * address. -+ * -+ * You can't see the change in a read back of CAR until then (about 250us -+ * later, on my box). The original Intel driver sets S0 and DE and code -+ * to check that address has propagated here. I tried this, but it would -+ * only sometimes work! The rest of the time it would never propagate and -+ * we'd spin forever. So now I just set it and pray... -+ */ -+static void udc_set_address(void *priv, unsigned int addr) -+{ -+ Ser0UDCAR = addr; -+} -+ -+static void udc_set_config(void *priv, struct cdb *cdb) -+{ -+ struct sausb_dev *usb = priv; -+ -+ if (cdb) { -+ udc_ep1_config(usb, le16_to_cpu(cdb->ep1.wMaxPacketSize)); -+ udc_ep2_config(usb, le16_to_cpu(cdb->ep2.wMaxPacketSize)); -+ } else { -+ udc_ep1_reset(usb); -+ udc_ep2_reset(usb); -+ } -+} -+ -+static unsigned int udc_ep_get_status(void *priv, unsigned int ep) -+{ -+ unsigned int status; -+ -+ switch (ep) { -+ case 0: -+ status = (Ser0UDCCS0 & UDCCS0_FST) ? 1 : 0; -+ break; -+ -+ case 1: -+ status = (Ser0UDCCS1 & UDCCS1_FST) ? 1 : 0; -+ break; -+ -+ case 2: -+ status = (Ser0UDCCS2 & UDCCS2_FST) ? 1 : 0; -+ break; -+ -+ default: -+ printk(KERN_ERR "UDC: get_status: bad end point %d\n", ep); -+ status = 0; -+ break; -+ } -+ -+ return status; -+} -+ -+static void udc_ep_halt(void *priv, unsigned int ep, int halt) -+{ -+ struct sausb_dev *usb = priv; -+ -+ printk("UDC: ep%d %s halt\n", ep, halt ? "set" : "clear"); -+ -+ switch (ep) { -+ case 1: -+ udc_ep1_halt(usb, halt); -+ break; -+ -+ case 2: -+ udc_ep2_halt(usb, halt); -+ break; -+ } -+} -+ -+static int udc_ep_queue(void *priv, unsigned int ep, char *buf, unsigned int len) -+{ -+ struct sausb_dev *usb = priv; -+ int ret = -EINVAL; -+ -+ switch (ep) { -+ case 1: -+ ret = udc_ep1_queue_buffer(usb, buf, len); -+ break; -+ case 2: -+ ret = udc_ep2_send(usb, buf, len); -+ break; -+ } -+ -+ return ret; -+} -+ -+static void udc_ep_reset(void *priv, unsigned int ep) -+{ -+ struct sausb_dev *usb = priv; -+ -+ switch (ep) { -+ case 1: -+ udc_ep1_recv_reset(usb); -+ break; -+ case 2: -+ udc_ep2_send_reset(usb); -+ break; -+ } -+} -+ -+static void udc_ep_callback(void *priv, unsigned int ep, usb_callback_t cb, void *data) -+{ -+ struct sausb_dev *usb = priv; -+ unsigned long flags; -+ -+ if (ep == 1 || ep == 2) { -+ ep -= 1; -+ -+ spin_lock_irqsave(&usb->lock, flags); -+ usb->ep[ep].cb_func = cb; -+ usb->ep[ep].cb_data = data; -+ spin_unlock_irqrestore(&usb->lock, flags); -+ } -+} -+ -+static int udc_ep_idle(void *priv, unsigned int ep) -+{ -+ struct sausb_dev *usb = priv; -+ int ret = -EINVAL; -+ -+ switch (ep) { -+ case 1: -+ break; -+ case 2: -+ ret = udc_ep2_idle(usb); -+ break; -+ } -+ -+ return ret; -+} -+ -+static struct usbc_driver usb_sa1100_drv = { -+ .owner = THIS_MODULE, -+ .name = "SA1100", -+ .start = udc_start, -+ .stop = udc_stop, -+ .ep0_queue = udc_ep0_queue, -+ .set_address = udc_set_address, -+ .set_config = udc_set_config, -+ .ep_get_status = udc_ep_get_status, -+ .ep_halt = udc_ep_halt, -+ .ep_queue = udc_ep_queue, -+ .ep_reset = udc_ep_reset, -+ .ep_callback = udc_ep_callback, -+ .ep_idle = udc_ep_idle, -+}; -+ -+ -+/* -+ * udc_ep0_read_packet() -+ * -+ * This setup handler is the "idle" state of endpoint zero. It looks for -+ * OPR (OUT packet ready) to see if a setup request has been been received -+ * from the host. Requests without a return data phase are immediately -+ * handled. Otherwise, the handler may be set to one of the sh_write_xxxx -+ * data pumpers if more than 8 bytes need to get back to the host. -+ */ -+static void udc_ep0_read_packet(struct sausb_dev *usb, u32 cs_reg_in) -+{ -+ struct usb_ctrlrequest req; -+ int n, ret = RET_NOACTION; -+ -+ /* -+ * A control request has been received by EP0. -+ * Read the request. -+ */ -+ n = udc_ep0_read_fifo(usb, &req, sizeof(req)); -+ -+ if (n == sizeof(req)) { -+ ret = usbctl_parse_request(usb->ctl, &req); -+ } else { -+ /* -+ * The request wasn't fully received. Force a -+ * stall. -+ */ -+ set_cs_bits(UDCCS0_FST | UDCCS0_SO); -+ printk("UDC: fifo read error: wanted %d bytes got %d\n", -+ sizeof(req), n); -+ } -+ -+ switch (ret) { -+ case RET_ERROR: -+ case RET_NOACTION: -+ break; -+ -+ case RET_ACK: -+ set_cs_bits(UDCCS0_DE | UDCCS0_SO); -+ break; -+ -+ case RET_REQERROR: -+ /* -+ * Send stall PID to host. -+ */ -+ set_cs_bits(UDCCS0_DE | UDCCS0_SO | UDCCS0_FST); -+ break; -+ } -+} -+ -+/* -+ * HACK DEBUG 3Mar01ww -+ * Well, maybe not, it really seems to help! 08Mar01ww -+ */ -+static void core_kicker(struct sausb_dev *usb) -+{ -+ __u32 car = Ser0UDCAR; -+ __u32 imp = Ser0UDCIMP; -+ __u32 omp = Ser0UDCOMP; -+ -+ UDC_set(Ser0UDCCR, UDCCR_UDD); -+ udelay(300); -+ UDC_clear(Ser0UDCCR, UDCCR_UDD); -+ -+ Ser0UDCAR = car; -+ Ser0UDCIMP = imp; -+ Ser0UDCOMP = omp; -+} -+ -+static void enable_resume_mask_suspend(struct sausb_dev *usb) -+{ -+ int i; -+ -+ usb->udccr |= UDCCR_SUSIM; -+ -+ i = 1; -+ do { -+ Ser0UDCCR = usb->udccr; -+ udelay(i); -+ if (Ser0UDCCR == usb->udccr) -+ break; -+ if (Ser0UDCSR & UDCSR_RSTIR) -+ break; -+ } while (i++ < 50); -+ -+ if (i == 50) -+ printk("UDC: enable_resume: could not set SUSIM 0x%08x\n", -+ Ser0UDCCR); -+ -+ usb->udccr &= ~UDCCR_RESIM; -+ -+ i = 1; -+ do { -+ Ser0UDCCR = usb->udccr; -+ udelay(i); -+ if (Ser0UDCCR == usb->udccr) -+ break; -+ if (Ser0UDCSR & UDCSR_RSTIR) -+ break; -+ } while (i++ < 50); -+ -+ if (i == 50) -+ printk("UDC: enable_resume: could not clear RESIM 0x%08x\n", -+ Ser0UDCCR); -+} -+ -+static void enable_suspend_mask_resume(struct sausb_dev *usb) -+{ -+ int i; -+ -+ usb->udccr |= UDCCR_RESIM; -+ -+ i = 1; -+ do { -+ Ser0UDCCR = usb->udccr; -+ udelay(i); -+ if (Ser0UDCCR == usb->udccr) -+ break; -+ if (Ser0UDCSR & UDCSR_RSTIR) -+ break; -+ } while (i++ < 50); -+ -+ if (i == 50) -+ printk("UDC: enable_resume: could not set RESIM 0x%08x\n", -+ Ser0UDCCR); -+ -+ usb->udccr &= ~UDCCR_SUSIM; -+ -+ i = 1; -+ do { -+ Ser0UDCCR = usb->udccr; -+ udelay(i); -+ if (Ser0UDCCR == usb->udccr) -+ break; -+ if (Ser0UDCSR & UDCSR_RSTIR) -+ break; -+ } while (i++ < 50); -+ -+ if (i == 50) -+ printk("UDC: enable_resume: could not clear SUSIM 0x%08x\n", -+ Ser0UDCCR); -+} -+ -+/* -+ * Reset received from HUB (or controller just went nuts and reset by -+ * itself!) so UDC core has been reset, track this state here -+ */ -+static void udc_reset(struct sausb_dev *usb) -+{ -+ if (usbctl_reset(usb->ctl)) { -+ ep0_clear_write(usb); -+ -+ /* -+ * Clean up endpoints. -+ */ -+ udc_ep1_reset(usb); -+ udc_ep2_reset(usb); -+ } -+ -+ /* -+ * mask reset ints, they flood during sequence, enable -+ * suspend and resume -+ */ -+ usb->udccr = (usb->udccr & ~(UDCCR_SUSIM | UDCCR_RESIM)) | UDCCR_REM; -+ Ser0UDCCR = usb->udccr; -+} -+ -+/* -+ * handle interrupt for endpoint zero -+ */ -+static void udc_ep0_int_hndlr(struct sausb_dev *usb) -+{ -+ u32 cs_reg_in; -+ -+ pcs("-->"); -+ -+ cs_reg_in = Ser0UDCCS0; -+ -+ /* -+ * If "setup end" has been set, the usb controller has terminated -+ * a setup transaction before we set DE. This happens during -+ * enumeration with some hosts. For example, the host will ask for -+ * our device descriptor and specify a return of 64 bytes. When we -+ * hand back the first 8, the host will know our max packet size -+ * and turn around and issue a new setup immediately. This causes -+ * the UDC to auto-ack the new setup and set SE. We must then -+ * "unload" (process) the new setup, which is what will happen -+ * after this preamble is finished executing. -+ */ -+ if (cs_reg_in & UDCCS0_SE) { -+ DPRINTK("UDC: early termination of setup\n"); -+ -+ /* -+ * Clear setup end -+ */ -+ set_cs_bits(UDCCS0_SSE); -+ -+ /* -+ * Clear any pending write. -+ */ -+ ep0_clear_write(usb); -+ } -+ -+ /* -+ * UDC sent a stall due to a protocol violation. -+ */ -+ if (cs_reg_in & UDCCS0_SST) { -+ usb->ep0_stall_sent++; -+ -+ DPRINTK("UDC: write_preamble: UDC sent stall\n"); -+ -+ /* -+ * Clear sent stall -+ */ -+ set_cs_bits(UDCCS0_SST); -+ -+ /* -+ * Clear any pending write. -+ */ -+ ep0_clear_write(usb); -+ } -+ -+ switch (cs_reg_in & (UDCCS0_OPR | UDCCS0_IPR)) { -+ case UDCCS0_OPR | UDCCS0_IPR: -+ DPRINTK("UDC: write_preamble: see OPR. Stopping write to " -+ "handle new SETUP\n"); -+ -+ /* -+ * very rarely, you can get OPR and -+ * leftover IPR. Try to clear -+ */ -+ UDC_clear(Ser0UDCCS0, UDCCS0_IPR); -+ -+ /* -+ * Clear any pending write. -+ */ -+ ep0_clear_write(usb); -+ -+ /*FALLTHROUGH*/ -+ case UDCCS0_OPR: -+ /* -+ * A new setup request is pending. Handle -+ * it. Note that we don't try to read a -+ * packet if SE was set and OPR is clear. -+ */ -+ udc_ep0_read_packet(usb, cs_reg_in); -+ break; -+ -+ case 0: -+ if (usb->wrint) { -+ if (usb->wrlen != 0) { -+ /* -+ * More data to go -+ */ -+ udc_ep0_write_fifo(usb); -+ set_ipr(); -+ } -+ -+ if (usb->wrlen == 0) { -+ /* -+ * All data sent. -+ */ -+ usb->wrint(usb); -+ -+ ep0_clear_write(usb); -+ } -+ } -+ break; -+ -+ case UDCCS0_IPR: -+ DPRINTK("UDC: IPR set, not writing\n"); -+ usb->ep0_early_irqs++; -+ break; -+ } -+ -+ pcs("<--"); -+} -+ -+static irqreturn_t udc_interrupt(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ struct sausb_dev *usb = dev_id; -+ u32 status = Ser0UDCSR; -+ -+ /* -+ * ReSeT Interrupt Request - UDC has been reset -+ */ -+ if (status & UDCSR_RSTIR) { -+ udc_reset(usb); -+ -+ /* -+ * clear all pending sources -+ */ -+ UDC_flip(Ser0UDCSR, status); -+ return IRQ_HANDLED; -+ } -+ -+ /* -+ * else we have done something other than reset, -+ * so be sure reset enabled -+ */ -+ usb->udccr &= ~UDCCR_REM; -+ UDC_write(Ser0UDCCR, usb->udccr); -+ -+ /* -+ * RESume Interrupt Request -+ */ -+ if (status & UDCSR_RESIR) { -+ usbctl_resume(usb->ctl); -+ core_kicker(usb); -+ enable_suspend_mask_resume(usb); -+ } -+ -+ /* -+ * SUSpend Interrupt Request -+ */ -+ if (status & UDCSR_SUSIR) { -+ usbctl_suspend(usb->ctl); -+ enable_resume_mask_suspend(usb); -+ } -+ -+ /* -+ * clear all pending sources -+ */ -+ UDC_flip(Ser0UDCSR, status); -+ -+ if (status & UDCSR_EIR) -+ udc_ep0_int_hndlr(usb); -+ -+ if (status & UDCSR_RIR) -+ udc_ep1_int_hndlr(usb); -+ -+ if (status & UDCSR_TIR) -+ udc_ep2_int_hndlr(usb); -+ -+ return IRQ_HANDLED; -+} -+ -+#ifdef CONFIG_PROC_FS -+ -+#define SAY( fmt, args... ) p += sprintf(p, fmt, ## args ) -+#define SAYV( num ) p += sprintf(p, num_fmt, "Value", num ) -+#define SAYC( label, yn ) p += sprintf(p, yn_fmt, label, yn ) -+#define SAYS( label, v ) p += sprintf(p, cnt_fmt, label, v ) -+ -+static int -+udc_read_proc(char *page, char **start, off_t off, int cnt, int *eof, -+ void *data) -+{ -+ struct sausb_dev *usb = data; -+ char *p = page; -+ u32 v; -+ int len, i; -+ -+ p += usbctl_proc_info(usb->ctl, p); -+ p += sprintf(p, "\nUDC:\n"); -+ v = Ser0UDCAR; -+ p += sprintf(p, "Address\t: %d (0x%02x)\n", v, v); -+ v = Ser0UDCIMP; -+ p += sprintf(p, "IN max\t: %d (0x%02x)\n", v + 1, v); -+ v = Ser0UDCOMP; -+ p += sprintf(p, "OUT max\t: %d (0x%02x)\n", v + 1, v); -+ v = Ser0UDCCR; -+ p += sprintf(p, "UDCCR\t: 0x%02x " -+ "[ %cSUSIM %cTIM %cRIM %cEIM %cRESIM %cUDA %cUDD ] " -+ "(0x%02x)\n", -+ v, -+ v & UDCCR_SUSIM ? '+' : '-', v & UDCCR_TIM ? '+' : '-', -+ v & UDCCR_RIM ? '+' : '-', v & UDCCR_EIM ? '+' : '-', -+ v & UDCCR_RESIM ? '+' : '-', v & UDCCR_UDA ? '+' : '-', -+ v & UDCCR_UDD ? '+' : '-', usb->udccr); -+ v = Ser0UDCCS0; -+ p += sprintf(p, "UDCCS0\t: 0x%02x " -+ "[ %cSO %cSE %cDE %cFST %cSST %cIPR %cOPR ]\n", -+ v, -+ v & UDCCS0_SO ? '+' : '-', v & UDCCS0_SE ? '+' : '-', -+ v & UDCCS0_DE ? '+' : '-', v & UDCCS0_FST ? '+' : '-', -+ v & UDCCS0_SST ? '+' : '-', v & UDCCS0_IPR ? '+' : '-', -+ v & UDCCS0_OPR ? '+' : '-'); -+ v = Ser0UDCCS1; -+ p += sprintf(p, "UDCCS1\t: 0x%02x " -+ "[ %cRNE %cFST %cSST %cRPE %cRPC %cRFS ]\n", -+ v, -+ v & UDCCS1_RNE ? '+' : '-', v & UDCCS1_FST ? '+' : '-', -+ v & UDCCS1_SST ? '+' : '-', v & UDCCS1_RPE ? '+' : '-', -+ v & UDCCS1_RPC ? '+' : '-', v & UDCCS1_RFS ? '+' : '-'); -+ v = Ser0UDCCS2; -+ p += sprintf(p, "UDCCS2\t: 0x%02x " -+ "[ %cFST %cSST %cTUR %cTPE %cTPC %cTFS ]\n", -+ v, -+ v & UDCCS2_FST ? '+' : '-', v & UDCCS2_SST ? '+' : '-', -+ v & UDCCS2_TUR ? '+' : '-', v & UDCCS2_TPE ? '+' : '-', -+ v & UDCCS2_TPC ? '+' : '-', v & UDCCS2_TFS ? '+' : '-'); -+ -+ p += sprintf(p, "\n"); -+ p += sprintf(p, " Bytes Packets FIFO errs Max Sz\n"); -+ p += sprintf(p, "EP0 Rd: %10ld %10ld %10ld -\n", -+ usb->ep0_rd_bytes, -+ usb->ep0_rd_packets, -+ usb->ep0_rd_fifo_errs); -+ p += sprintf(p, "EP0 Wr: %10ld %10ld %10ld -\n", -+ usb->ep0_wr_bytes, -+ usb->ep0_wr_packets, -+ usb->ep0_wr_fifo_errs); -+ -+ for (i = 0; i < 2; i++) -+ p += sprintf(p, "EP%d : %10ld %10ld %10ld %6d\n", -+ i + 1, -+ usb->ep[i].bytes, -+ usb->ep[i].packets, -+ usb->ep[i].fifo_errs, -+ usb->ep[i].maxpktsize); -+ -+ p += sprintf(p, "Stalls sent\t: %ld\n", usb->ep0_stall_sent); -+ p += sprintf(p, "Early ints\t: %ld\n", usb->ep0_early_irqs); -+ -+#if 0 -+ v = Ser0UDCSR; -+ SAY("\nUDC Interrupt Request Register\n"); -+ SAYV(v); -+ SAYC("Reset pending", (v & UDCSR_RSTIR) ? yes : no); -+ SAYC("Suspend pending", (v & UDCSR_SUSIR) ? yes : no); -+ SAYC("Resume pending", (v & UDCSR_RESIR) ? yes : no); -+ SAYC("ep0 pending", (v & UDCSR_EIR) ? yes : no); -+ SAYC("receiver pending", (v & UDCSR_RIR) ? yes : no); -+ SAYC("tramsitter pending", (v & UDCSR_TIR) ? yes : no); -+ -+#ifdef CONFIG_SA1100_EXTENEX1 -+ SAYC("\nSoft connect", -+ (PPSR & PPC_USB_SOFT_CON) ? "Visible" : "Hidden"); -+#endif -+#endif -+ -+ len = (p - page) - off; -+ if (len < 0) -+ len = 0; -+ *eof = (len <= cnt) ? 1 : 0; -+ *start = page + off; -+ -+ return len; -+} -+ -+#endif -+ -+extern struct usbctl usbctl; -+ -+static int __devinit udc_probe(struct device *dev) -+{ -+ struct sausb_dev *usb; -+ int retval; -+ -+ if (!request_mem_region(0x80000000, 0x10000, "sa11x0-udc")) -+ return -EBUSY; -+ -+ usb = kmalloc(sizeof(struct sausb_dev), GFP_KERNEL); -+ if (!usb) -+ return -ENOMEM; -+ -+ memset(usb, 0, sizeof(struct sausb_dev)); -+ dev_set_drvdata(dev, usb); -+ -+ usb_sa1100_drv.priv = usb; -+ -+ usb->dev = dev; -+ usb->ctl = &usbctl; -+ -+ spin_lock_init(&usb->lock); -+ -+ udc_disable(usb); -+ -+ usbctl_init(usb->ctl, &usb_sa1100_drv); -+ -+#ifdef CONFIG_PROC_FS -+ create_proc_read_entry("sausb", 0, NULL, udc_read_proc, usb); -+#endif -+ -+ /* setup rx dma */ -+ retval = sa1100_request_dma(DMA_Ser0UDCRd, "USB receive", -+ NULL, NULL, &usb->ep[0].dmach); -+ if (retval) { -+ printk("UDC: unable to register for rx dma rc=%d\n", -+ retval); -+ goto err; -+ } -+ -+ /* setup tx dma */ -+ retval = sa1100_request_dma(DMA_Ser0UDCWr, "USB transmit", -+ NULL, NULL, &usb->ep[1].dmach); -+ if (retval) { -+ printk("UDC: unable to register for tx dma rc=%d\n", -+ retval); -+ goto err; -+ } -+ -+ /* now allocate the IRQ. */ -+ retval = request_irq(IRQ_Ser0UDC, udc_interrupt, SA_INTERRUPT, -+ "SA USB core", usb); -+ if (retval) { -+ printk("UDC: couldn't request USB irq rc=%d\n", retval); -+ goto err; -+ } -+ -+ return retval; -+ -+ err: -+ if (usb->ep[2].dmach) { -+ sa1100_free_dma(usb->ep[2].dmach); -+ usb->ep[2].dmach = NULL; -+ } -+ if (usb->ep[1].dmach) { -+ sa1100_free_dma(usb->ep[1].dmach); -+ usb->ep[1].dmach = NULL; -+ } -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("sausb", NULL); -+#endif -+ release_mem_region(0x80000000, 0x10000); -+ return retval; -+} -+ -+/* -+ * Release DMA and interrupt resources -+ */ -+static int __devexit udc_remove(struct device *dev) -+{ -+ struct sausb_dev *usb = dev_get_drvdata(dev); -+ -+ dev_set_drvdata(dev, NULL); -+ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("sausb", NULL); -+#endif -+ -+ udc_disable(usb); -+ -+ free_irq(IRQ_Ser0UDC, usb); -+ sa1100_free_dma(usb->ep[1].dmach); -+ sa1100_free_dma(usb->ep[0].dmach); -+ -+ usbctl_exit(usb->ctl); -+ -+ release_mem_region(0x80000000, 0x10000); -+ -+ return 0; -+} -+ -+static struct device_driver sa11x0usb_driver = { -+ .name = "sa11x0-udc", -+ .bus = &platform_bus_type, -+ .probe = udc_probe, -+ .remove = __devexit_p(udc_remove), -+}; -+ -+static int __init udc_init(void) -+{ -+ return driver_register(&sa11x0usb_driver); -+} -+ -+static void __exit udc_exit(void) -+{ -+ driver_unregister(&sa11x0usb_driver); -+} -+ -+module_init(udc_init); -+module_exit(udc_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("SA1100 USB Gadget driver"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/control.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,933 @@ -+/* -+ * usb/control.c -+ * -+ * This parses and handles all the control messages to/from endpoint 0. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "buffer.h" -+#include "client.h" -+#include "usbdev.h" -+ -+#include "sa1100_usb.h" -+ -+#define USB_ENDPOINT_HALT 0 -+#define USB_DEVICE_REMOTE_WAKEUP 1 -+ -+#undef DEBUG -+ -+#ifdef DEBUG -+#define DPRINTK(fmt, args...) printk(KERN_DEBUG fmt , ## args) -+#else -+#define DPRINTK(fmt, args...) -+#endif -+ -+/* -+ * print string descriptor -+ */ -+static char * __attribute__((unused)) -+psdesc(char *str, int len, struct usb_string_descriptor *desc) -+{ -+ char *start = str; -+ int nchars = (desc->bLength - 2) / sizeof(__u16) + 2; -+ int i; -+ -+ if (nchars >= len) -+ nchars = len - 1; -+ -+ nchars -= 2; -+ -+ *str++ = '"'; -+ for(i = 0; i < nchars; i++) -+ *str++ = le16_to_cpu(desc->wData[i]); -+ *str++ = '"'; -+ *str = '\0'; -+ -+ return start; -+} -+ -+enum { -+ kError = -1, -+ kEvSuspend = 0, -+ kEvReset = 1, -+ kEvResume = 2, -+ kEvAddress = 3, -+ kEvConfig = 4, -+ kEvDeConfig = 5 -+}; -+ -+enum { -+ kStateZombie = 0, -+ kStateZombieSuspend = 1, -+ kStateDefault = 2, -+ kStateDefaultSuspend = 3, -+ kStateAddr = 4, -+ kStateAddrSuspend = 5, -+ kStateConfig = 6, -+ kStateConfigSuspend = 7 -+}; -+ -+#define kE kError -+#define kSZ kStateZombie -+#define kSZS kStateZombieSuspend -+#define kSD kStateDefault -+#define kSDS kStateDefaultSuspend -+#define kSA kStateAddr -+#define kSAS kStateAddrSuspend -+#define kSC kStateConfig -+#define kSCS kStateConfigSuspend -+ -+/* -+ * Fig 9-1 P192 -+ * Zombie == Attached | Powered -+ */ -+static int device_state_machine[8][6] = { -+// suspend reset resume addr config deconfig -+{ kSZS, kSD, kE, kE, kE, kE }, /* zombie */ -+{ kE, kSD, kSZ, kE, kE, kE }, /* zom sus */ -+{ kSDS, kError, kSD, kSA, kE, kE }, /* default */ -+{ kE, kSD, kSD, kE, kE, kE }, /* def sus */ -+{ kSAS, kSD, kE, kE, kSC, kE }, /* addr */ -+{ kE, kSD, kSA, kE, kE, kE }, /* addr sus */ -+{ kSCS, kSD, kE, kE, kE, kSA }, /* config */ -+{ kE, kSD, kSC, kE, kE, kE } /* cfg sus */ -+}; -+ -+/* -+ * "device state" is the usb device framework state, as opposed to the -+ * "state machine state" which is whatever the driver needs and is much -+ * more fine grained -+ */ -+static int sm_state_to_device_state[8] = { -+ USB_STATE_POWERED, /* zombie */ -+ USB_STATE_SUSPENDED, /* zombie suspended */ -+ USB_STATE_DEFAULT, /* default */ -+ USB_STATE_SUSPENDED, /* default suspended */ -+ USB_STATE_ADDRESS, /* address */ -+ USB_STATE_SUSPENDED, /* address suspended */ -+ USB_STATE_CONFIGURED, /* config */ -+ USB_STATE_SUSPENDED /* config suspended */ -+}; -+ -+static char * state_names[8] = { -+ "zombie", -+ "zombie suspended", -+ "default", -+ "default suspended", -+ "address", -+ "address suspended", -+ "configured", -+ "config suspended" -+}; -+ -+static char * event_names[6] = { -+ "suspend", -+ "reset", -+ "resume", -+ "address assigned", -+ "configure", -+ "de-configure" -+}; -+ -+static char * device_state_names[] = { -+ "not attached", -+ "attached", -+ "powered", -+ "default", -+ "address", -+ "configured", -+ "suspended" -+}; -+ -+static void usbctl_callbacks(struct usbctl *ctl, int state, int oldstate) -+{ -+ struct usb_client *clnt = ctl->clnt; -+ -+ /* -+ * Inform any clients currently attached -+ * that the connectivity state changed. -+ */ -+ if (clnt && clnt->state_change) -+ clnt->state_change(clnt->priv, state, oldstate); -+} -+ -+/* -+ * called by the interrupt handler here and the two endpoint -+ * files when interesting .."events" happen -+ */ -+static int usbctl_next_state_on_event(struct usbctl *ctl, int event) -+{ -+ int next_state, next_dev_state, old_dev_state; -+ -+ printk(KERN_DEBUG "usbctl: %s --[%s]--> ", state_names[ctl->sm_state], -+ event_names[event]); -+ -+ next_state = device_state_machine[ctl->sm_state][event]; -+ if (next_state != kError) { -+ next_dev_state = sm_state_to_device_state[next_state]; -+ -+ printk("%s. Device in %s state.\n", -+ state_names[next_state], -+ device_state_names[next_dev_state]); -+ -+ old_dev_state = ctl->state; -+ ctl->sm_state = next_state; -+ ctl->state = next_dev_state; -+ -+ if (old_dev_state != next_dev_state) -+ usbctl_callbacks(ctl, next_dev_state, old_dev_state); -+ } else -+ printk("(error)\n"); -+ -+ return next_state; -+} -+ -+/* -+ * Driver detected USB HUB reset. -+ */ -+int usbctl_reset(struct usbctl *ctl) -+{ -+ int ret; -+ -+ ret = usbctl_next_state_on_event(ctl, kEvReset) == kError; -+ -+ if (!ret) { -+ ctl->address = 0; -+ } -+ return ret; -+} -+ -+EXPORT_SYMBOL(usbctl_reset); -+ -+void usbctl_suspend(struct usbctl *ctl) -+{ -+ usbctl_next_state_on_event(ctl, kEvSuspend); -+} -+ -+EXPORT_SYMBOL(usbctl_suspend); -+ -+void usbctl_resume(struct usbctl *ctl) -+{ -+ usbctl_next_state_on_event(ctl, kEvResume); -+} -+ -+EXPORT_SYMBOL(usbctl_resume); -+ -+static struct usb_interface_descriptor * -+usbctl_get_interface_descriptor(struct usbctl *ctl, unsigned int interface) -+{ -+ /*FIXME*/ -+ struct cdb *cdb = sa1100_usb_get_descriptor_ptr(); -+ -+ return (struct usb_interface_descriptor *)&cdb->intf; -+} -+ -+static inline int -+__usbctl_queue(struct usbctl *ctl, struct usb_ctrlrequest *req, -+ struct usb_buf *buf) -+{ -+ unsigned int reqlen = le16_to_cpu(req->wLength); -+ -+ return ctl->driver->ep0_queue(ctl->driver->priv, buf, reqlen) ? -+ RET_ERROR : RET_QUEUED; -+} -+ -+static int -+usbctl_queue(struct usbctl *ctl, struct usb_ctrlrequest *req, -+ void *data, unsigned int len) -+{ -+ struct usb_buf *buf; -+ -+ buf = usbb_alloc(len, GFP_ATOMIC); -+ if (!buf) { -+ printk(KERN_ERR "usb: out of memory\n"); -+ return RET_ERROR; -+ } -+ -+ if (data) -+ memcpy(usbb_push(buf, len), data, len); -+ -+ return __usbctl_queue(ctl, req, buf); -+} -+ -+/* -+ * 9.4.5: Get Status (device) -+ */ -+static int -+usbctl_parse_dev_get_status(struct usbctl *ctl, struct usb_ctrlrequest *req) -+{ -+ u16 status; -+ -+ status = /* self_powered_hook() ? 1 : 0 */1; -+ -+ status = cpu_to_le16(status); -+ -+ return usbctl_queue(ctl, req, &status, 2); -+} -+ -+/* -+ * Send USB device description to the host. -+ */ -+static int -+usbctl_desc_device(struct usbctl *ctl, struct usb_ctrlrequest *req) -+{ -+ return __usbctl_queue(ctl, req, usbb_get(ctl->dev_desc_buf)); -+} -+ -+/* -+ * Send USB configuration information to the host. -+ */ -+static int -+usbctl_desc_config(struct usbctl *ctl, struct usb_ctrlrequest *req) -+{ -+ /*FIXME*/ -+ struct cdb *cdb = sa1100_usb_get_descriptor_ptr(); -+ -+ return usbctl_queue(ctl, req, cdb, sizeof(struct cdb)); -+} -+ -+/* -+ * Send a string to the host from the string table. -+ */ -+static int -+usbctl_desc_string(struct usbctl *ctl, struct usb_ctrlrequest *req, -+ unsigned int idx) -+{ -+ struct usb_buf *buf; -+ unsigned int lang = le16_to_cpu(req->wIndex); -+ char string[32] __attribute__((unused)); -+ int ret; -+ -+ DPRINTK("usbctl: desc_string (index %u, lang 0x%04x): ", idx, lang); -+ -+ buf = usbc_string_find(&ctl->strings, lang, idx); -+ if (buf) { -+ DPRINTK("%s\n", idx == 0 ? "language" : -+ psdesc(string, sizeof(string), usbc_string_desc(buf))); -+ -+ ret = __usbctl_queue(ctl, req, buf); -+ } else { -+ DPRINTK("not found -> stall\n"); -+ ret = RET_REQERROR; -+ } -+ return ret; -+} -+ -+/* -+ * Send an interface description (and endpoints) to the host. -+ */ -+static int -+usbctl_desc_interface(struct usbctl *ctl, struct usb_ctrlrequest *req, -+ unsigned int idx) -+{ -+ struct usb_interface_descriptor *desc; -+ int ret; -+ -+ DPRINTK("usbctl: desc_interface (index %d)\n", idx); -+ -+ desc = usbctl_get_interface_descriptor(ctl, idx); -+ -+ if (desc) { -+ ret = usbctl_queue(ctl, req, desc, desc->bLength); -+ } else { -+ printk("usbctl: unknown interface %d\n", idx); -+ ret = RET_REQERROR; -+ } -+ -+ return ret; -+} -+ -+/* -+ * Send an endpoint (1 .. n) to the host. -+ */ -+static int -+usbctl_desc_endpoint(struct usbctl *ctl, struct usb_ctrlrequest *req, -+ unsigned int idx) -+{ -+ int ret; -+ -+ DPRINTK("usbctl: desc_endpoint (index %d)\n", idx); -+ -+ if (idx >= 1 && idx <= ctl->nr_ep) { -+ struct usb_endpoint_descriptor *ep = ctl->ep_desc[idx - 1]; -+ -+ ret = usbctl_queue(ctl, req, ep, ep->bLength); -+ } else { -+ printk("usbctl: unknown endpoint %d\n", idx); -+ ret = RET_REQERROR; -+ } -+ -+ return ret; -+} -+ -+/* -+ * 9.4.3: Parse a request for a descriptor. -+ * Unspecified conditions: -+ * None -+ * Valid states: default, address, configured. -+ */ -+static int -+usbctl_parse_dev_descriptor(struct usbctl *ctl, struct usb_ctrlrequest *req) -+{ -+ unsigned int idx = le16_to_cpu(req->wValue) & 255; -+ unsigned int type = le16_to_cpu(req->wValue) >> 8; -+ int ret; -+ -+ switch (type) { -+ case USB_DT_DEVICE: /* check if idx matters */ -+ ret = usbctl_desc_device(ctl, req); -+ break; -+ -+ case USB_DT_CONFIG: /* check if idx matters */ -+ ret = usbctl_desc_config(ctl, req); -+ break; -+ -+ case USB_DT_STRING: -+ ret = usbctl_desc_string(ctl, req, idx); -+ break; -+ -+ case USB_DT_INTERFACE: -+ ret = usbctl_desc_interface(ctl, req, idx); -+ break; -+ -+ case USB_DT_ENDPOINT: -+ ret = usbctl_desc_endpoint(ctl, req, idx); -+ break; -+ -+ case USB_DT_DEVICE_QUALIFIER: -+ case USB_DT_OTHER_SPEED_CONFIG: -+ case USB_DT_INTERFACE_POWER: -+ default: -+ printk(KERN_ERR "usbctl: unknown descriptor: " -+ "wValue = 0x%04x wIndex = 0x%04x\n", -+ le16_to_cpu(req->wValue), le16_to_cpu(req->wIndex)); -+ ret = RET_REQERROR; -+ break; -+ } -+ -+ return ret; -+} -+ -+/* -+ * 9.4.6: Set Address -+ * The USB1.1 spec says the response to SetAddress() with value 0 -+ * is undefined. It then goes on to define the response. We -+ * acknowledge addresses of zero, but take no further action. -+ */ -+static int -+usbctl_parse_dev_set_address(struct usbctl *ctl, struct usb_ctrlrequest *req) -+{ -+ unsigned int address = le16_to_cpu(req->wValue) & 0x7f; -+ -+ if (ctl->state == USB_STATE_CONFIGURED) -+ return RET_REQERROR; -+ -+ if (address != 0) { -+ ctl->address = address; -+ -+ usbctl_next_state_on_event(ctl, kEvAddress); -+ -+ ctl->driver->set_address(ctl->driver->priv, address); -+ } -+ -+ return RET_ACK; -+} -+ -+/* -+ * 9.4.2: Get Configuration. -+ * Unspecified conditions: -+ * - non-zero wIndex, wValue or wLength (ignored) -+ * - default state (request error) -+ * Valid states: address, configured. -+ */ -+static int -+usbctl_parse_dev_get_config(struct usbctl *ctl, struct usb_ctrlrequest *req) -+{ -+ u8 status = 0; -+ -+ if (ctl->state == USB_STATE_CONFIGURED) -+ status = 1; -+ -+ return usbctl_queue(ctl, req, &status, 1); -+} -+ -+/* -+ * 9.4.7: Set Configuration. -+ * Unspecified conditions: -+ * - default state (request error) -+ */ -+static int -+usbctl_parse_dev_set_config(struct usbctl *ctl, struct usb_ctrlrequest *req) -+{ -+ unsigned int cfg = le16_to_cpu(req->wValue); -+ int ret = RET_REQERROR; -+ -+ if (ctl->state == USB_STATE_DEFAULT) -+ return ret; -+ -+ if (cfg == 0) { -+ /* enter address state, or remain in address state */ -+ usbctl_next_state_on_event(ctl, kEvDeConfig); -+ -+ ctl->driver->set_config(ctl->driver->priv, NULL); -+ -+ ret = RET_ACK; -+ } else if (cfg == 1) { -+ /* enter configured state, and set configuration */ -+ /*FIXME*/ -+ struct cdb *cdb = sa1100_usb_get_descriptor_ptr(); -+ -+ usbctl_next_state_on_event(ctl, kEvConfig); -+ -+ ctl->driver->set_config(ctl->driver->priv, cdb); -+ ret = RET_ACK; -+ } -+ -+ return ret; -+} -+ -+/* -+ * Interface handling -+ */ -+ -+/* -+ * 9.4.5: Get Status (interface) -+ */ -+static int -+usbctl_parse_int_get_status(struct usbctl *ctl, struct usb_ctrlrequest *req) -+{ -+ unsigned int interface = le16_to_cpu(req->wIndex) & 255; -+ u16 status; -+ -+ switch (ctl->state) { -+ case USB_STATE_DEFAULT: -+ return RET_REQERROR; -+ -+ case USB_STATE_ADDRESS: -+ if (interface != 0) -+ return RET_REQERROR; -+ break; -+ -+ case USB_STATE_CONFIGURED: -+ if (interface != 1) -+ return RET_REQERROR; -+ break; -+ } -+ -+ status = cpu_to_le16(0); -+ -+ return usbctl_queue(ctl, req, &status, 2); -+} -+ -+/* -+ * 9.4.4: Get Interface -+ * Unspecified conditions: -+ * - -+ * States: Default (unspecified), Address (Request Error), Configured (ok) -+ */ -+static int -+usbctl_parse_int_get_interface(struct usbctl *ctl, struct usb_ctrlrequest *req) -+{ -+ unsigned int interface = le16_to_cpu(req->wIndex) & 255; -+ u8 null = 0; -+ -+ if (ctl->state != USB_STATE_CONFIGURED) -+ return RET_REQERROR; -+ -+ /* -+ * If the interface doesn't exist, respond with request error -+ */ -+ if (interface != 1) -+ return RET_REQERROR; -+ -+ printk("usbctl: get interface %d not supported\n", interface); -+ -+ return usbctl_queue(ctl, req, &null, 1); -+} -+ -+static int -+usbctl_parse_int_set_interface(struct usbctl *ctl, struct usb_ctrlrequest *req) -+{ -+ unsigned int interface = le16_to_cpu(req->wIndex) & 255; -+ -+ if (interface != 0) -+ printk("usbctl: set interface %d not supported (ignored)\n", -+ interface); -+ -+ return RET_ACK; -+} -+ -+/* -+ * Endpoint handling -+ */ -+ -+/* -+ * 9.4.5: Get Status (endpoint) -+ */ -+static int -+usbctl_parse_ep_get_status(struct usbctl *ctl, struct usb_ctrlrequest *req) -+{ -+ unsigned int ep = le16_to_cpu(req->wIndex) & 15; -+ u16 status; -+ -+ if ((ep != 0 && ctl->state != USB_STATE_CONFIGURED) || -+ ep <= ctl->nr_ep) -+ return RET_REQERROR; -+ -+ status = ctl->driver->ep_get_status(ctl->driver->priv, ep); -+ status = cpu_to_le16(status); -+ -+ return usbctl_queue(ctl, req, &status, 2); -+} -+ -+/* -+ * 9.4.1: Clear an endpoint feature. We only support ENDPOINT_HALT. -+ * Unspecified conditions: -+ * - non-zero wLength is not specified (ignored) -+ * Valid states: Address, Configured. -+ */ -+static int -+usbctl_parse_ep_clear_feature(struct usbctl *ctl, struct usb_ctrlrequest *req) -+{ -+ unsigned int feature = le16_to_cpu(req->wValue); -+ unsigned int ep = le16_to_cpu(req->wIndex) & 15; -+ int ret; -+ -+ if ((ep != 0 && ctl->state != USB_STATE_CONFIGURED) || -+ ep <= ctl->nr_ep) -+ return RET_REQERROR; -+ -+ if (feature == USB_ENDPOINT_HALT) { -+ ctl->driver->ep_halt(ctl->driver->priv, ep, 0); -+ ret = RET_ACK; -+ } else { -+ printk(KERN_ERR "usbctl: unsupported clear feature: " -+ "wValue = 0x%04x wIndex = 0x%04x\n", -+ feature, ep); -+ -+ ret = RET_REQERROR; -+ } -+ return ret; -+} -+ -+/* -+ * 9.4.9: Set Feature (endpoint) -+ */ -+static int -+usbctl_parse_ep_set_feature(struct usbctl *ctl, struct usb_ctrlrequest *req) -+{ -+ unsigned int feature = le16_to_cpu(req->wValue); -+ unsigned int ep = le16_to_cpu(req->wIndex) & 15; -+ int ret; -+ -+ if ((ep != 0 && ctl->state != USB_STATE_CONFIGURED) || -+ ep <= ctl->nr_ep) -+ return RET_REQERROR; -+ -+ if (feature == USB_ENDPOINT_HALT) { -+ ctl->driver->ep_halt(ctl->driver->priv, ep, 1); -+ ret = RET_ACK; -+ } else { -+ printk(KERN_ERR "usbctl: unsupported set feature " -+ "wValue = 0x%04x wIndex = 0x%04x\n", -+ feature, ep); -+ -+ ret = RET_REQERROR; -+ } -+ return ret; -+} -+ -+/* -+ * This reflects Table 9.3 (p186) in the USB1.1 spec. -+ * -+ * Some notes: -+ * - USB1.1 specifies remote wakeup feature, so we don't implement -+ * USB_RECIP_DEVICE USB_REQ_{SET,CLEAR}_FEATURE -+ * - USB1.1 doesn't actually specify any interface features, so we -+ * don't implement USB_RECIP_INTERFACE USB_REQ_{SET,CLEAR}_FEATURE -+ */ -+static int (*request_fns[4][16])(struct usbctl *, struct usb_ctrlrequest *) = { -+ [USB_RECIP_DEVICE] = { -+ [USB_REQ_GET_STATUS] = usbctl_parse_dev_get_status, -+ [USB_REQ_CLEAR_FEATURE] = NULL, -+ [USB_REQ_SET_FEATURE] = NULL, -+ [USB_REQ_SET_ADDRESS] = usbctl_parse_dev_set_address, -+ [USB_REQ_GET_DESCRIPTOR] = usbctl_parse_dev_descriptor, -+ [USB_REQ_SET_DESCRIPTOR] = NULL, -+ [USB_REQ_GET_CONFIGURATION] = usbctl_parse_dev_get_config, -+ [USB_REQ_SET_CONFIGURATION] = usbctl_parse_dev_set_config, -+ }, -+ -+ [USB_RECIP_INTERFACE] = { -+ [USB_REQ_GET_STATUS] = usbctl_parse_int_get_status, -+ [USB_REQ_CLEAR_FEATURE] = NULL, -+ [USB_REQ_SET_FEATURE] = NULL, -+ [USB_REQ_GET_INTERFACE] = usbctl_parse_int_get_interface, -+ [USB_REQ_SET_INTERFACE] = usbctl_parse_int_set_interface, -+ }, -+ -+ [USB_RECIP_ENDPOINT] = { -+ [USB_REQ_GET_STATUS] = usbctl_parse_ep_get_status, -+ [USB_REQ_CLEAR_FEATURE] = usbctl_parse_ep_clear_feature, -+ [USB_REQ_SET_FEATURE] = usbctl_parse_ep_set_feature, -+ }, -+}; -+ -+static void __attribute__((unused)) -+usbctl_dump_request(const char *prefix, const struct usb_ctrlrequest *req) -+{ -+ printk("%sbRequestType=0x%02x bRequest=0x%02x " -+ "wValue=0x%04x wIndex=0x%04x wLength=0x%04x\n", -+ prefix, req->bRequestType, req->bRequest, -+ le16_to_cpu(req->wValue), le16_to_cpu(req->wIndex), -+ le16_to_cpu(req->wLength)); -+} -+ -+int usbctl_parse_request(struct usbctl *ctl, struct usb_ctrlrequest *req) -+{ -+ unsigned int type; -+ int (*fn)(struct usbctl *, struct usb_ctrlrequest *) = NULL; -+ int ret = RET_REQERROR; -+ -+ //usbctl_dump_request("usbctl: ", req); -+ -+ type = req->bRequestType & USB_TYPE_MASK; -+ if (type == USB_TYPE_STANDARD) { -+ unsigned int recip; -+ -+ recip = req->bRequestType & USB_RECIP_MASK; -+ if (recip < ARRAY_SIZE(request_fns) && -+ req->bRequest < ARRAY_SIZE(request_fns[0])) -+ fn = request_fns[recip][req->bRequest]; -+ } -+ -+ if (fn) -+ ret = fn(ctl, req); -+ else -+ usbctl_dump_request(KERN_ERR "usbctl: unknown request: ", -+ req); -+ -+ /* -+ * Make sure we're doing the right thing. -+ */ -+ if (req->bRequestType & USB_DIR_IN) { -+ if (ret != RET_QUEUED && ret != RET_REQERROR) -+ printk("Error: device to host transfer expected\n"); -+ } else { -+ if (ret == RET_QUEUED) -+ printk("Error: no device to host transfer expected\n"); -+ } -+ -+ return ret; -+} -+ -+EXPORT_SYMBOL(usbctl_parse_request); -+ -+/* Start running. Must have called usb_open (above) first */ -+int usbctl_start(struct usb_client *client) -+{ -+ struct usbctl *ctl = client->ctl; -+ -+ if (ctl == NULL || ctl->clnt != client) { -+ printk("usbctl: start: no client registered\n"); -+ return -EPERM; -+ } -+ -+ ctl->sm_state = kStateZombie; -+ ctl->state = USB_STATE_POWERED; -+ -+ /* -+ * Notify the client as to our state. -+ */ -+ usbctl_callbacks(ctl, USB_STATE_POWERED, USB_STATE_SUSPENDED); -+ -+ return ctl->driver->start(ctl->driver->priv); -+} -+ -+EXPORT_SYMBOL(usbctl_start); -+ -+/* -+ * Stop USB core from running -+ */ -+void usbctl_stop(struct usb_client *client) -+{ -+ struct usbctl *ctl = client->ctl; -+ -+ if (ctl == NULL || ctl->clnt != client) { -+ printk("USBDEV: stop: no client/driver registered\n"); -+ return; -+ } -+ -+ ctl->driver->stop(ctl->driver->priv); -+} -+ -+EXPORT_SYMBOL(usbctl_stop); -+ -+struct usbctl usbctl; -+ -+EXPORT_SYMBOL(usbctl); -+ -+/* Open SA usb core on behalf of a client, but don't start running */ -+ -+int usbctl_open(struct usb_client *client) -+{ -+ struct usbctl *ctl = &usbctl; -+ int ret; -+printk("usbctl_open: ctl %p driver %p\n", ctl, ctl->driver); -+ if (!ctl->driver || !try_module_get(ctl->driver->owner)) -+ return -ENODEV; -+ -+ if (ctl->clnt != NULL) { -+ ret = -EBUSY; -+ goto err; -+ } -+ -+ ctl->clnt = client; -+ ctl->state = USB_STATE_SUSPENDED; -+ ctl->nr_ep = 2; -+ /* start in zombie suspended state */ -+ ctl->sm_state = kStateZombieSuspend; -+ ctl->state = USB_STATE_SUSPENDED; -+ client->ctl = ctl; -+ -+ ctl->dev_desc_buf = usbb_alloc(sizeof(struct usb_device_descriptor), -+ GFP_KERNEL); -+ if (!ctl->dev_desc_buf) { -+ ret = -ENOMEM; -+ goto err; -+ } -+ -+ ctl->dev_desc = usbb_push(ctl->dev_desc_buf, -+ sizeof(struct usb_device_descriptor)); -+ -+ /* create descriptors for enumeration */ -+ initialize_descriptors(ctl); -+ -+ return 0; -+ -+ err: -+ module_put(ctl->driver->owner); -+ return ret; -+} -+ -+EXPORT_SYMBOL(usbctl_open); -+ -+/* Tell SA core client is through using it */ -+void usbctl_close(struct usb_client *client) -+{ -+ struct usbctl *ctl = client->ctl; -+ -+ if (ctl == NULL || ctl->clnt != client) { -+ printk("usbctl: close: no client registered\n"); -+ return; -+ } -+ -+ usbb_put(ctl->dev_desc_buf); -+ -+ client->ctl = NULL; -+ ctl->clnt = NULL; -+ ctl->dev_desc = NULL; -+ ctl->dev_desc_buf = NULL; -+ /* reset to zombie suspended state */ -+ ctl->sm_state = kStateZombieSuspend; -+ ctl->state = USB_STATE_SUSPENDED; -+ -+ usbc_string_free_all(&ctl->strings); -+ -+ if (ctl->driver->owner) -+ module_put(ctl->driver->owner); -+} -+ -+EXPORT_SYMBOL(usbctl_close); -+ -+int usbctl_proc_info(struct usbctl *ctl, char *buf) -+{ -+ char *p = buf; -+ -+ p += sprintf(p, "USB Gadget Core:\n"); -+ p += sprintf(p, "Driver\t: %s\n", -+ ctl->driver ? ctl->driver->name : "none"); -+ p += sprintf(p, "Client\t: %s\n", -+ ctl->clnt ? ctl->clnt->name : "none"); -+ p += sprintf(p, "State\t: %s (%s) %d\n", -+ device_state_names[sm_state_to_device_state[ctl->sm_state]], -+ state_names[ctl->sm_state], -+ ctl->sm_state); -+ p += sprintf(p, "Address\t: %d\n", ctl->address); -+ -+ return p - buf; -+} -+ -+EXPORT_SYMBOL(usbctl_proc_info); -+ -+int -+usbctl_ep_queue_buffer(struct usbctl *ctl, unsigned int ep, -+ char *buf, unsigned int len) -+{ -+ return ctl->driver->ep_queue(ctl->driver->priv, ep, buf, len); -+} -+ -+EXPORT_SYMBOL(usbctl_ep_queue_buffer); -+ -+void usbctl_ep_reset(struct usbctl *ctl, unsigned int ep) -+{ -+ return ctl->driver->ep_reset(ctl->driver->priv, ep); -+} -+ -+EXPORT_SYMBOL(usbctl_ep_reset); -+ -+void -+usbctl_ep_set_callback(struct usbctl *ctl, unsigned int ep, -+ usb_callback_t callback, void *data) -+{ -+ ctl->driver->ep_callback(ctl->driver->priv, ep, callback, data); -+} -+ -+EXPORT_SYMBOL(usbctl_ep_set_callback); -+ -+int usbctl_ep_idle(struct usbctl *ctl, unsigned int ep) -+{ -+ return ctl->driver->ep_idle(ctl->driver->priv, ep); -+} -+ -+EXPORT_SYMBOL(usbctl_ep_idle); -+ -+/* -+ * usbctl_init() -+ * Module load time. Allocate dma and interrupt resources. Setup /proc fs -+ * entry. Leave UDC disabled. -+ */ -+int usbctl_init(struct usbctl *ctl, struct usbc_driver *drv) -+{ -+ usbc_string_init(&ctl->strings); -+printk("usbctl_init: %p %p\n", ctl, drv); -+ /* -+ * start in zombie suspended state -+ */ -+ ctl->sm_state = kStateZombieSuspend; -+ ctl->state = USB_STATE_SUSPENDED; -+ ctl->driver = drv; -+ -+ return 0; -+} -+ -+/* -+ * usbctl_exit() -+ */ -+void usbctl_exit(struct usbctl *ctl) -+{ -+ usbc_string_free_all(&ctl->strings); -+ -+ ctl->driver = NULL; -+} -+ -+EXPORT_SYMBOL(usbctl_init); -+EXPORT_SYMBOL(usbctl_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("USB gadget core"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/client.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,40 @@ -+#ifndef USBDEV_CLIENT_H -+#define USBDEV_CLIENT_H -+ -+#include "sa1100_usb.h" /* grr */ -+ -+struct usbctl; -+ -+struct usb_client { -+ struct usbctl *ctl; -+ const char *name; /* Client name */ -+ void *priv; /* Client-private data */ -+ void (*state_change)(void *priv, int state, int oldstate); -+ __u16 vendor; /* USB vendor ID */ -+ __u16 product; /* USB product ID */ -+ __u16 version; /* USB version ID */ -+ __u8 class; /* USB class */ -+ __u8 subclass; /* USB subclass */ -+ __u8 protocol; /* USB protocol */ -+ __u8 unused1; -+ __u16 unused2; -+ const char *manufacturer_str; -+ const char *product_str; -+ const char *serial_str; -+}; -+ -+int usbctl_start(struct usb_client *client); -+void usbctl_stop(struct usb_client *client); -+int usbctl_open(struct usb_client *client); -+void usbctl_close(struct usb_client *client); -+ -+int -+usbctl_ep_queue_buffer(struct usbctl *ctl, unsigned int ep, -+ char *buf, unsigned int len); -+void usbctl_ep_reset(struct usbctl *ctl, unsigned int ep); -+void -+usbctl_ep_set_callback(struct usbctl *ctl, unsigned int ep, -+ usb_callback_t callback, void *data); -+int usbctl_ep_idle(struct usbctl *ctl, unsigned int ep); -+ -+#endif ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/sa1100_usb.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,50 @@ -+/* -+ * sa1100_usb.h -+ * -+ * Public interface to the sa1100 USB core. For use by client modules -+ * like usb-eth and usb-char. -+ * -+ */ -+#ifndef _SA1100_USB_H -+#define _SA1100_USB_H -+ -+typedef void (*usb_callback_t)(void *data, int flag, int size); -+ -+/* in usb_send.c */ -+int sa1100_usb_xmitter_avail( void ); -+int sa1100_usb_send(char *buf, int len); -+void sa1100_usb_send_set_callback(usb_callback_t callback, void *data); -+void sa1100_usb_send_reset(void); -+ -+/* in usb_recev.c */ -+int sa1100_usb_recv(char *buf, int len); -+void sa1100_usb_recv_set_callback(usb_callback_t callback, void *data); -+void sa1100_usb_recv_reset(void); -+ -+////////////////////////////////////////////////////////////////////////////// -+// Descriptor Management -+////////////////////////////////////////////////////////////////////////////// -+ -+// MaxPower: -+#define USB_POWER(x) ((x)>>1) /* convert mA to descriptor units of A for MaxPower */ -+ -+/* "config descriptor buffer" - that is, one config, -+ ..one interface and 2 endpoints */ -+struct cdb { -+ struct usb_config_descriptor cfg; -+ struct usb_interface_descriptor intf; -+ struct usb_endpoint_descriptor ep1, ep2; -+} __attribute__ ((packed)); -+ -+ -+/*======================================================= -+ * Descriptor API -+ */ -+ -+/* Get the address of the statically allocated desc_t structure -+ in the usb core driver. Clients can modify this between -+ the time they call sa1100_usb_open() and sa1100_usb_start() -+*/ -+struct cdb *sa1100_usb_get_descriptor_ptr(void); -+ -+#endif /* _SA1100_USB_H */ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/sa1100usb.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,136 @@ -+/* -+ * Copyright (C) Compaq Computer Corporation, 1998, 1999 -+ * Copyright (C) Extenex Corporation 2001 -+ * -+ * usb_ctl.h -+ * -+ * PRIVATE interface used to share info among components of the SA-1100 USB -+ * core: usb_ctl, usb_ep0, usb_recv and usb_send. Clients of the USB core -+ * should use sa1100_usb.h. -+ * -+ */ -+#ifndef SA1100USB_H -+#define SA1100USB_H -+ -+struct usbctl; -+ -+struct sausb_dev { -+ struct device *dev; -+ struct usbctl *ctl; -+ spinlock_t lock; -+ -+ u32 udccr; -+ -+ /* -+ * EP0 write thread. -+ */ -+ void (*wrint)(struct sausb_dev *); -+ struct usb_buf *wrbuf; -+ unsigned char *wrptr; -+ unsigned int wrlen; -+ -+ /* -+ * EP0 statistics. -+ */ -+ unsigned long ep0_wr_fifo_errs; -+ unsigned long ep0_wr_bytes; -+ unsigned long ep0_wr_packets; -+ unsigned long ep0_rd_fifo_errs; -+ unsigned long ep0_rd_bytes; -+ unsigned long ep0_rd_packets; -+ unsigned long ep0_stall_sent; -+ unsigned long ep0_early_irqs; -+ -+ /* -+ * EP1 .. n -+ */ -+ struct { -+ dma_regs_t *dmach; -+ -+ dma_addr_t bufdma; -+ unsigned int buflen; -+ void *pktcpu; -+ dma_addr_t pktdma; -+ unsigned int pktlen; -+ unsigned int pktrem; -+ -+ void *cb_data; -+ void (*cb_func)(void *data, int flag, int size); -+ -+ u32 udccs; -+ unsigned int maxpktsize; -+ unsigned int configured; -+ unsigned int host_halt; -+ unsigned long fifo_errs; -+ unsigned long bytes; -+ unsigned long packets; -+ } ep[2]; -+}; -+ -+/* receiver */ -+int ep1_recv(void); -+void udc_ep1_init(struct sausb_dev *); -+void udc_ep1_halt(struct sausb_dev *, int); -+void udc_ep1_reset(struct sausb_dev *); -+void udc_ep1_config(struct sausb_dev *, unsigned int); -+void udc_ep1_int_hndlr(struct sausb_dev *); -+ -+/* xmitter */ -+void udc_ep2_init(struct sausb_dev *); -+void udc_ep2_halt(struct sausb_dev *, int); -+void udc_ep2_reset(struct sausb_dev *); -+void udc_ep2_config(struct sausb_dev *, unsigned int); -+void udc_ep2_int_hndlr(struct sausb_dev *); -+ -+#define UDC_write(reg, val) do { \ -+ int i = 10000; \ -+ do { \ -+ (reg) = (val); \ -+ if (i-- <= 0) { \ -+ printk( "%s [%d]: write %#x to %p (%#x) failed\n", \ -+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \ -+ break; \ -+ } \ -+ } while((reg) != (val)); \ -+} while (0) -+ -+#define UDC_set(reg, val) do { \ -+ int i = 10000; \ -+ do { \ -+ (reg) |= (val); \ -+ if (i-- <= 0) { \ -+ printk( "%s [%d]: set %#x of %p (%#x) failed\n", \ -+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \ -+ break; \ -+ } \ -+ } while(!((reg) & (val))); \ -+} while (0) -+ -+#define UDC_clear(reg, val) do { \ -+ int i = 10000; \ -+ do { \ -+ (reg) &= ~(val); \ -+ if (i-- <= 0) { \ -+ printk( "%s [%d]: clear %#x of %p (%#x) failed\n", \ -+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \ -+ break; \ -+ } \ -+ } while((reg) & (val)); \ -+} while (0) -+ -+#define UDC_flip(reg, val) do { \ -+ int i = 10000; \ -+ (reg) = (val); \ -+ do { \ -+ (reg) = (val); \ -+ if (i-- <= 0) { \ -+ printk( "%s [%d]: flip %#x of %p (%#x) failed\n", \ -+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \ -+ break; \ -+ } \ -+ } while(((reg) & (val))); \ -+} while (0) -+ -+#define CHECK_ADDRESS { if ( Ser0UDCAR == 1 ) { printk("%s:%d I lost my address!!!\n",__FUNCTION__, __LINE__);}} -+ -+#endif ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/strings.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,117 @@ -+/* -+ * usb/strings.c -+ * -+ * Copyright (C) 2002 Russell King. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "buffer.h" -+#include "strings.h" -+ -+struct usb_buf *usbc_string_alloc(int len) -+{ -+ struct usb_buf *buf; -+ int tot_len; -+ -+ tot_len = sizeof(struct usb_descriptor_header) + sizeof(u16) * len; -+ -+ buf = usbb_alloc(tot_len, GFP_KERNEL); -+ -+ if (buf) { -+ struct usb_string_descriptor *desc = usbb_push(buf, tot_len); -+ -+ desc->bLength = tot_len; -+ desc->bDescriptorType = USB_DT_STRING; -+ } -+ return buf; -+} -+ -+void usbc_string_free(struct usb_buf *buf) -+{ -+ if (buf) -+ usbb_put(buf); -+} -+ -+void usbc_string_from_cstr(struct usb_buf *buf, const char *str) -+{ -+ struct usb_string_descriptor *desc = usbc_string_desc(buf); -+ int i, len; -+ -+ len = strlen(str); -+ BUG_ON((sizeof(__u16) * len) > desc->bLength - sizeof(struct usb_descriptor_header)); -+ -+ for (i = 0; i < len; i++) -+ desc->wData[i] = cpu_to_le16(str[i]); -+} -+ -+int usbc_string_add(struct usbc_strs *table, struct usb_buf *buf) -+{ -+ int nr, i; -+ -+ nr = -ENOSPC; -+ spin_lock_irq(&table->lock); -+ for (i = 0; i < NR_STRINGS; i++) -+ if (table->buf[i] == NULL) { -+ table->buf[i] = buf; -+ nr = i; -+ break; -+ } -+ spin_unlock_irq(&table->lock); -+ -+ return nr; -+} -+ -+void usbc_string_del(struct usbc_strs *table, int nr) -+{ -+ if (nr < NR_STRINGS) { -+ spin_lock_irq(&table->lock); -+ table->buf[nr] = NULL; -+ spin_unlock_irq(&table->lock); -+ } -+} -+ -+struct usb_buf * -+usbc_string_find(struct usbc_strs *table, unsigned int lang, unsigned int idx) -+{ -+ struct usb_buf *buf = NULL; -+ -+ if (idx < NR_STRINGS) { -+ spin_lock_irq(&table->lock); -+ buf = usbb_get(table->buf[idx]); -+ spin_unlock_irq(&table->lock); -+ } -+ -+ return buf; -+} -+ -+void usbc_string_free_all(struct usbc_strs *table) -+{ -+ int i; -+ -+ spin_lock_irq(&table->lock); -+ for (i = 0; i < NR_STRINGS; i++) { -+ usbc_string_free(table->buf[i]); -+ table->buf[i] = NULL; -+ } -+ spin_unlock_irq(&table->lock); -+} -+ -+void usbc_string_init(struct usbc_strs *table) -+{ -+ memset(table, 0, sizeof(struct usbc_strs)); -+ spin_lock_init(&table->lock); -+} -+ -+EXPORT_SYMBOL(usbc_string_from_cstr); -+EXPORT_SYMBOL(usbc_string_alloc); -+EXPORT_SYMBOL(usbc_string_free); -+EXPORT_SYMBOL(usbc_string_add); -+EXPORT_SYMBOL(usbc_string_del); -+EXPORT_SYMBOL(usbc_string_find); -+EXPORT_SYMBOL(usbc_string_free_all); -+EXPORT_SYMBOL(usbc_string_init); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/usb_ctl.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,171 @@ -+ /* -+ * Copyright (C) Compaq Computer Corporation, 1998, 1999 -+ * Copyright (C) Extenex Corporation, 2001 -+ * -+ * usb_ctl.c -+ * -+ * SA1100 USB controller core driver. -+ * -+ * This file provides interrupt routing and overall coordination -+ * of the three endpoints in usb_ep0, usb_receive (1), and usb_send (2). -+ * -+ * Please see linux/Documentation/arm/SA1100/SA1100_USB for details. -+ * -+ */ -+#include -+#include -+#include -+ -+#include "buffer.h" -+#include "client.h" -+#include "usbdev.h" -+#include "sa1100_usb.h" -+ -+////////////////////////////////////////////////////////////////////////////// -+// Globals -+////////////////////////////////////////////////////////////////////////////// -+ -+/* device descriptors */ -+static struct cdb cdb; -+ -+////////////////////////////////////////////////////////////////////////////// -+// Private Helpers -+////////////////////////////////////////////////////////////////////////////// -+ -+int sa1100_usb_add_string(struct usbctl *ctl, const char *str) -+{ -+ int nr = 0; -+ -+ if (str) { -+ struct usb_buf *buf; -+ int len; -+ -+ len = strlen(str); -+ -+ nr = -ENOMEM; -+ buf = usbc_string_alloc(len); -+ if (buf) { -+ usbc_string_from_cstr(buf, str); -+ nr = usbc_string_add(&ctl->strings, buf); -+ -+ if (nr < 0) -+ usbc_string_free(buf); -+ } -+ } -+ -+ return nr; -+} -+ -+EXPORT_SYMBOL(sa1100_usb_add_string); -+ -+static int sa1100_usb_add_language(struct usbctl *ctl, unsigned int lang) -+{ -+ struct usb_buf *buf; -+ int nr = -ENOMEM; -+ -+ buf = usbc_string_alloc(1); -+ if (buf) { -+ usbc_string_desc(buf)->wData[0] = cpu_to_le16(lang); /* American English */ -+ nr = usbc_string_add(&ctl->strings, buf); -+ -+ if (nr < 0) -+ usbc_string_free(buf); -+ } -+ -+ return nr; -+} -+ -+/* setup default descriptors */ -+ -+void initialize_descriptors(struct usbctl *ctl) -+{ -+ struct usb_client *clnt = ctl->clnt; -+ int r; -+ -+ ctl->ep_desc[0] = (struct usb_endpoint_descriptor *)&cdb.ep1; -+ ctl->ep_desc[1] = (struct usb_endpoint_descriptor *)&cdb.ep2; -+ -+ cdb.cfg.bLength = USB_DT_CONFIG_SIZE; -+ cdb.cfg.bDescriptorType = USB_DT_CONFIG; -+ cdb.cfg.wTotalLength = cpu_to_le16(sizeof(struct cdb)); -+ cdb.cfg.bNumInterfaces = 1; -+ cdb.cfg.bConfigurationValue = 1; -+ cdb.cfg.iConfiguration = 0; -+ cdb.cfg.bmAttributes = USB_CONFIG_ATT_ONE; -+ cdb.cfg.bMaxPower = USB_POWER( 500 ); -+ -+ cdb.intf.bLength = USB_DT_INTERFACE_SIZE; -+ cdb.intf.bDescriptorType = USB_DT_INTERFACE; -+ cdb.intf.bInterfaceNumber = 0; /* unique intf index*/ -+ cdb.intf.bAlternateSetting = 0; -+ cdb.intf.bNumEndpoints = 2; -+ cdb.intf.bInterfaceClass = 0xff; /* vendor specific */ -+ cdb.intf.bInterfaceSubClass = 0; -+ cdb.intf.bInterfaceProtocol = 0; -+ cdb.intf.iInterface = 0; -+ -+ cdb.ep1.bLength = USB_DT_INTERFACE_SIZE; -+ cdb.ep1.bDescriptorType = USB_DT_ENDPOINT; -+ cdb.ep1.bEndpointAddress = USB_DIR_OUT | 1; -+ cdb.ep1.bmAttributes = USB_ENDPOINT_XFER_BULK; -+ cdb.ep1.wMaxPacketSize = cpu_to_le16(64); -+ cdb.ep1.bInterval = 0; -+ -+ cdb.ep2.bLength = USB_DT_INTERFACE_SIZE; -+ cdb.ep2.bDescriptorType = USB_DT_ENDPOINT; -+ cdb.ep2.bEndpointAddress = USB_DIR_IN | 2; -+ cdb.ep2.bmAttributes = USB_ENDPOINT_XFER_BULK; -+ cdb.ep2.wMaxPacketSize = cpu_to_le16(64); -+ cdb.ep2.bInterval = 0; -+ -+ ctl->dev_desc->bLength = USB_DT_DEVICE_SIZE; -+ ctl->dev_desc->bDescriptorType = USB_DT_DEVICE; -+ ctl->dev_desc->bcdUSB = cpu_to_le16(0x100); /* 1.0 */ -+ ctl->dev_desc->bDeviceClass = clnt->class; -+ ctl->dev_desc->bDeviceSubClass = clnt->subclass; -+ ctl->dev_desc->bDeviceProtocol = clnt->protocol; -+ ctl->dev_desc->bMaxPacketSize0 = 8; /* ep0 max fifo size */ -+ ctl->dev_desc->idVendor = cpu_to_le16(clnt->vendor); -+ ctl->dev_desc->idProduct = cpu_to_le16(clnt->product); -+ ctl->dev_desc->bcdDevice = cpu_to_le16(clnt->version); -+ ctl->dev_desc->bNumConfigurations = 1; -+ -+ /* set language */ -+ /* See: http://www.usb.org/developers/data/USB_LANGIDs.pdf */ -+ r = sa1100_usb_add_language(ctl, 0x409); -+ if (r < 0) -+ printk(KERN_ERR "usbc: couldn't add language\n"); -+ -+ r = sa1100_usb_add_string(ctl, clnt->manufacturer_str); -+ if (r < 0) -+ printk(KERN_ERR "usbc: couldn't add manufacturer string\n"); -+ -+ ctl->dev_desc->iManufacturer = r > 0 ? r : 0; -+ -+ r = sa1100_usb_add_string(ctl, clnt->product_str); -+ if (r < 0) -+ printk(KERN_ERR "usbc: couldn't add product string\n"); -+ -+ ctl->dev_desc->iProduct = r > 0 ? r : 0; -+ -+ r = sa1100_usb_add_string(ctl, clnt->serial_str); -+ if (r < 0) -+ printk(KERN_ERR "usbc: couldn't add serial string\n"); -+ -+ ctl->dev_desc->iSerialNumber = r > 0 ? r : 0; -+} -+ -+ -+/*==================================================== -+ * Descriptor Manipulation. -+ * Use these between open() and start() above to setup -+ * the descriptors for your device. -+ */ -+ -+/* get pointer to static default descriptor */ -+struct cdb *sa1100_usb_get_descriptor_ptr(void) -+{ -+ return &cdb; -+} -+ -+EXPORT_SYMBOL(sa1100_usb_get_descriptor_ptr); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/Makefile 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,12 @@ -+# -+# Makefile for the USB client -+# -+ -+usbdevcore-objs := buffer.o control.o strings.o usb_ctl.o -+ -+sa1100-objs := sa1100usb.o usb_recv.o usb_send.o -+ -+obj-$(CONFIG_SA1100_USB) += usbdevcore.o sa1100.o -+obj-$(CONFIG_SA1100_USB_NETLINK) += usb-eth.o -+obj-$(CONFIG_SA1100_USB_CHAR) += usb-char.o -+ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/usb/usbdev.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,91 @@ -+#ifndef USBDEV_H -+#define USBDEV_H -+ -+#include "strings.h" -+ -+struct usb_buf; -+struct module; -+struct cdb; -+struct usb_client; -+ -+struct usbc_driver { -+ struct module *owner; -+ const char *name; -+ void *priv; -+ int (*start)(void *); -+ int (*stop)(void *); -+ -+ int (*ep0_queue)(void *, struct usb_buf *buf, unsigned int req_len); -+ void (*set_address)(void *, unsigned int addr); -+ void (*set_config)(void *, struct cdb *config); -+ -+ /* -+ * Get specified endpoint status, as defined in 9.4.5. -+ */ -+ unsigned int (*ep_get_status)(void *, unsigned int ep); -+ void (*ep_halt)(void *, unsigned int ep, int halt); -+ -+ /* -+ * Client -+ */ -+ int (*ep_queue)(void *, unsigned int, char *, unsigned int); -+ void (*ep_reset)(void *, unsigned int); -+ void (*ep_callback)(void *, unsigned int, void (*)(void *, int, int), void *); -+ int (*ep_idle)(void *, unsigned int); -+}; -+ -+struct usbc_endpoint { -+ struct usb_endpoint_descriptor *desc; -+}; -+ -+struct usbc_interface { -+ struct usb_interface_descriptor *desc; -+ unsigned int nr_ep; -+ struct usbc_endpoint *ep[0]; -+}; -+ -+struct usbc_config { -+ struct usb_config_descriptor *desc; -+ unsigned int nr_interface; -+ struct usbc_interface *interface[0]; -+}; -+ -+struct usbctl { -+ struct usb_client *clnt; -+ const struct usbc_driver *driver; -+ -+ /* Internal state */ -+ unsigned int address; /* host assigned address */ -+ unsigned int state; /* our device state */ -+ unsigned int sm_state; /* state machine state */ -+ -+ struct usbc_config *config; /* active configuration */ -+ struct usbc_strs strings; -+ -+ /* Descriptors */ -+ struct usb_device_descriptor *dev_desc; /* device descriptor */ -+ struct usb_buf *dev_desc_buf; /* device descriptor buffer */ -+ -+ -+ int nr_ep; -+ struct usb_endpoint_descriptor *ep_desc[2]; -+}; -+ -+/* -+ * Function Prototypes -+ */ -+ -+#define RET_ERROR (-1) -+#define RET_NOACTION (0) -+#define RET_QUEUED (1) -+#define RET_ACK (2) -+#define RET_REQERROR (3) -+ -+int usbctl_parse_request(struct usbctl *ctl, struct usb_ctrlrequest *req); -+ -+int usbctl_reset(struct usbctl *ctl); -+void usbctl_suspend(struct usbctl *ctl); -+void usbctl_resume(struct usbctl *ctl); -+ -+#endif -+ ---- linux-2.6.5/arch/arm/mach-sa1100/pm.c~heh 2004-04-03 22:36:27.000000000 -0500 -+++ linux-2.6.5/arch/arm/mach-sa1100/pm.c 2004-04-30 20:57:36.000000000 -0400 -@@ -150,6 +150,7 @@ - */ - static int sa11x0_pm_prepare(u32 state) - { -+ nmi_watchdog_disable(); - return 0; - } - -@@ -158,6 +159,7 @@ - */ - static int sa11x0_pm_finish(u32 state) - { -+ nmi_watchdog_enable(); - return 0; - } - ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/arch/arm/mach-sa1100/nmi-oopser.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,104 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+static void *nmi_stack; -+ -+asm(" \n\ -+nmi_start: \n\ -+ mrs r8, spsr \n\ -+ ldr r9, .Lstack \n\ -+ ldr sp, [r9] \n\ -+ sub sp, sp, #18 * 4 \n\ -+ str r8, [sp, #16 * 4] \n\ -+ str lr, [sp, #15 * 4] \n\ -+ stmia sp, {r0 - r7} \n\ -+ add r0, sp, #8 * 4 \n\ -+ mrs r2, cpsr \n\ -+ bic r1, r2, #0x1f \n\ -+ orr r1, r1, #0x13 \n\ -+ msr cpsr_c, r1 \n\ -+ mov r0, r0 \n\ -+ stmia r0, {r8 - lr} \n\ -+ mov r0, r0 \n\ -+ msr cpsr_c, r2 \n\ -+ mov r0, r0 \n\ -+ mov r0, sp \n\ -+ mov lr, pc \n\ -+ ldr pc, .Lfn \n\ -+ ldmia sp, {r0 - r7} \n\ -+ ldr r8, [sp, #16 * 4] \n\ -+ ldr lr, [sp, #15 * 4] \n\ -+ add sp, sp, #18 * 4 \n\ -+ msr spsr, r8 \n\ -+ movs pc, lr \n\ -+ \n\ -+.Lstack: .long nmi_stack \n\ -+.Lfn: .long nmi_fn \n\ -+nmi_end:"); -+ -+extern unsigned char nmi_start, nmi_end; -+ -+static void __attribute__((unused)) nmi_fn(struct pt_regs *regs) -+{ -+ struct thread_info *thread; -+ unsigned long osmr0, osmr1, oscr, ossr, icmr, icip; -+ -+ oscr = OSCR; -+ osmr0 = OSMR0; -+ osmr1 = OSMR1; -+ ossr = OSSR; -+ icmr = ICMR; -+ icip = ICIP; -+ -+ OSSR = OSSR_M1; -+ ICMR &= ~IC_OST1; -+ -+ thread = (struct thread_info *)(regs->ARM_sp & ~8191); -+ -+ bust_spinlocks(1); -+ printk("OSMR0:%08lx OSMR1:%08lx OSCR:%08lx OSSR:%08lx ICMR:%08lx ICIP:%08lx\n", -+ osmr0, osmr1, oscr, ossr, icmr, icip); -+ nmi_watchdog(thread, regs); -+ bust_spinlocks(0); -+ -+ OSSR = OSSR_M1; -+ OSMR1 = OSSR + 36864000; -+ ICMR |= IC_OST1; -+} -+ -+static int nmi_init(void) -+{ -+ unsigned char *vec_base = (unsigned char *)vectors_base(); -+return 0; -+ nmi_stack = (void *)__get_free_page(GFP_KERNEL); -+ if (!nmi_stack) -+ return -ENOMEM; -+ -+ nmi_stack += PAGE_SIZE; -+ -+ modify_domain(DOMAIN_USER, DOMAIN_MANAGER); -+ memcpy(vec_base + 0x1c, &nmi_start, &nmi_end - &nmi_start); -+ modify_domain(DOMAIN_USER, DOMAIN_CLIENT); -+ -+ /* -+ * Ensure timer 1 is set to FIQ, and enabled. -+ */ -+ OSMR1 = OSCR - 1; -+ OSSR = OSSR_M1; -+ OIER |= OIER_E1; -+ ICLR |= IC_OST1; -+ ICMR |= IC_OST1; -+ -+ return 0; -+} -+ -+__initcall(nmi_init); ---- linux-2.6.5/drivers/media/Kconfig~heh 2004-04-03 22:36:51.000000000 -0500 -+++ linux-2.6.5/drivers/media/Kconfig 2004-04-30 20:57:36.000000000 -0400 -@@ -32,6 +32,8 @@ - - source "drivers/media/common/Kconfig" - -+source "drivers/media/mmc/Kconfig" -+ - config VIDEO_TUNER - tristate - default y if VIDEO_BT848=y || VIDEO_SAA7134=y || VIDEO_MXB=y || VIDEO_CX88=y ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/media/mmc/Kconfig 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,52 @@ -+# -+# MMC subsystem configuration -+# -+ -+menu "MMC/SD Card support" -+ -+config MMC -+ tristate "MMC support" -+ help -+ MMC is the "multi-media card" bus protocol. -+ -+ If you want MMC support, you should say Y here and also -+ to the specific driver for your MMC interface. -+ -+config MMC_DEBUG -+ bool "MMC debugging" -+ depends on MMC != n -+ help -+ This is an option for use by developers; most people should -+ say N here. This enables MMC core and driver debugging. -+ -+config MMC_BLOCK -+ tristate "MMC block device driver" -+ depends on MMC -+ default y -+ help -+ Say Y here to enable the MMC block device driver support. -+ This provides a block device driver, which you can use to -+ mount the filesystem. Almost everyone wishing MMC support -+ should say Y or M here. -+ -+config MMC_ARMMMCI -+ tristate "ARM AMBA Multimedia Card Interface support" -+ depends on ARM_AMBA && MMC -+ help -+ This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card -+ Interface (PL180 and PL181) support. If you have an ARM(R) -+ platform with a Multimedia Card slot, say Y or M here. -+ -+ If unsure, say N. -+ -+config MMC_PXA -+ tristate "Intel PXA255 Multimedia Card Interface support" -+ depends on ARCH_PXA && MMC -+ help -+ This selects the Intel(R) PXA(R) Multimedia card Interface. -+ If you have a PXA(R) platform with a Multimedia Card slot, -+ say Y or M here. -+ -+ If unsure, say N. -+ -+endmenu ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/media/mmc/mmc_queue.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,171 @@ -+/* -+ * linux/drivers/media/mmc/mmc_queue.c -+ * -+ * Copyright (C) 2003 Russell King, 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. -+ * -+ */ -+#include -+#include -+ -+#include -+#include -+#include "mmc_queue.h" -+ -+/* -+ * Prepare a MMC request. Essentially, this means passing the -+ * preparation off to the media driver. The media driver will -+ * create a mmc_io_request in req->special. -+ */ -+static int mmc_prep_request(struct request_queue *q, struct request *req) -+{ -+ struct mmc_queue *mq = q->queuedata; -+ int ret = BLKPREP_KILL; -+ -+ if (req->flags & REQ_SPECIAL) { -+ /* -+ * Special commands already have the command -+ * blocks already setup in req->special. -+ */ -+ BUG_ON(!req->special); -+ -+ ret = BLKPREP_OK; -+ } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { -+ /* -+ * Block I/O requests need translating according -+ * to the protocol. -+ */ -+ ret = mq->prep_fn(mq, req); -+ } else { -+ /* -+ * Everything else is invalid. -+ */ -+ blk_dump_rq_flags(req, "MMC bad request"); -+ } -+ -+ if (ret == BLKPREP_OK) -+ req->flags |= REQ_DONTPREP; -+ -+ return ret; -+} -+ -+static int mmc_queue_thread(void *d) -+{ -+ struct mmc_queue *mq = d; -+ struct request_queue *q = mq->queue; -+ DECLARE_WAITQUEUE(wait, current); -+ int ret; -+ -+ /* -+ * Set iothread to ensure that we aren't put to sleep by -+ * the process freezing. We handle suspension ourselves. -+ */ -+ current->flags |= PF_MEMALLOC|PF_IOTHREAD; -+ -+ daemonize("mmcqd"); -+ -+ spin_lock_irq(¤t->sighand->siglock); -+ sigfillset(¤t->blocked); -+ recalc_sigpending(); -+ spin_unlock_irq(¤t->sighand->siglock); -+ -+ mq->thread = current; -+ complete(&mq->thread_complete); -+ -+ add_wait_queue(&mq->thread_wq, &wait); -+ spin_lock_irq(q->queue_lock); -+ do { -+ struct request *req = NULL; -+ -+ set_current_state(TASK_INTERRUPTIBLE); -+ if (!blk_queue_plugged(q)) -+ mq->req = req = elv_next_request(q); -+ spin_unlock(q->queue_lock); -+ -+ if (!req) { -+ if (!mq->thread) -+ break; -+ schedule(); -+ continue; -+ } -+ set_current_state(TASK_RUNNING); -+ -+ ret = mq->issue_fn(mq, req); -+ -+ spin_lock_irq(q->queue_lock); -+ end_request(req, ret); -+ } while (1); -+ remove_wait_queue(&mq->thread_wq, &wait); -+ -+ complete_and_exit(&mq->thread_complete, 0); -+ return 0; -+} -+ -+/* -+ * Generic MMC request handler. This is called for any queue on a -+ * particular host. When the host is not busy, we look for a request -+ * on any queue on this host, and attempt to issue it. This may -+ * not be the queue we were asked to process. -+ */ -+static void mmc_request(request_queue_t *q) -+{ -+ struct mmc_queue *mq = q->queuedata; -+ -+ if (!mq->req && !blk_queue_plugged(q)) -+ wake_up(&mq->thread_wq); -+} -+ -+/** -+ * mmc_init_queue - initialise a queue structure. -+ * @mq: mmc queue -+ * @card: mmc card to attach this queue -+ * @lock: queue lock -+ * -+ * Initialise a MMC card request queue. -+ */ -+int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock) -+{ -+ u64 limit = BLK_BOUNCE_HIGH; -+ int ret; -+ -+ if (card->host->dev->dma_mask) -+ limit = *card->host->dev->dma_mask; -+ -+ mq->card = card; -+ mq->queue = blk_init_queue(mmc_request, lock); -+ blk_queue_prep_rq(mq->queue, mmc_prep_request); -+ blk_queue_bounce_limit(mq->queue, limit); -+ -+ mq->queue->queuedata = mq; -+ mq->req = NULL; -+ -+ init_completion(&mq->thread_complete); -+ init_waitqueue_head(&mq->thread_wq); -+ -+ ret = kernel_thread(mmc_queue_thread, mq, CLONE_KERNEL); -+ if (ret < 0) { -+ blk_cleanup_queue(mq->queue); -+ } else { -+ wait_for_completion(&mq->thread_complete); -+ init_completion(&mq->thread_complete); -+ } -+ -+ return ret; -+} -+ -+EXPORT_SYMBOL(mmc_init_queue); -+ -+void mmc_cleanup_queue(struct mmc_queue *mq) -+{ -+ mq->thread = NULL; -+ wake_up(&mq->thread_wq); -+ wait_for_completion(&mq->thread_complete); -+ blk_cleanup_queue(mq->queue); -+ -+ mq->card = NULL; -+} -+ -+EXPORT_SYMBOL(mmc_cleanup_queue); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/media/mmc/pxamci.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,587 @@ -+/* -+ * linux/drivers/media/mmc/pxa.c - PXA MMCI driver -+ * -+ * Copyright (C) 2003 Russell King, 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. -+ * -+ * This hardware is really sick. No way to clear interrupts. Have -+ * to turn off the clock whenever we touch the device. Yuck! -+ * -+ * 1 and 3 byte data transfers not supported -+ * max block length up to 1023 -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "pxamci.h" -+ -+#ifdef CONFIG_MMC_DEBUG -+#define DBG(x...) printk(KERN_DEBUG x) -+#else -+#define DBG(x...) do { } while (0) -+#endif -+ -+struct pxamci_host { -+ struct mmc_host mmc; -+ spinlock_t lock; -+ struct resource *res; -+ void *base; -+ int irq; -+ int dma; -+ unsigned int clkrt; -+ unsigned int cmdat; -+ unsigned int imask; -+ unsigned int power_mode; -+ -+ struct mmc_request *req; -+ struct mmc_command *cmd; -+ struct mmc_data *data; -+ -+ dma_addr_t sg_dma; -+ struct pxa_dma_desc *sg_cpu; -+ -+ dma_addr_t dma_buf; -+ unsigned int dma_size; -+ unsigned int dma_dir; -+}; -+ -+#define to_pxamci_host(x) container_of(x, struct pxamci_host, mmc) -+ -+/* -+ * The base MMC clock rate -+ */ -+#define CLOCKRATE 20000000 -+ -+static inline unsigned int ns_to_clocks(unsigned int ns) -+{ -+ return (ns * (CLOCKRATE / 1000000) + 999) / 1000; -+} -+ -+static void pxamci_stop_clock(struct pxamci_host *host) -+{ -+ if (readl(host->base + MMC_STAT) & STAT_CLK_EN) { -+ unsigned long flags; -+ unsigned int v; -+ -+ writel(STOP_CLOCK, host->base + MMC_STRPCL); -+ -+ /* -+ * Wait for the "clock has stopped" interrupt. -+ * We need to unmask the interrupt to receive -+ * the notification. Sigh. -+ */ -+ spin_lock_irqsave(&host->lock, flags); -+ writel(host->imask & ~CLK_IS_OFF, host->base + MMC_I_MASK); -+ do { -+ v = readl(host->base + MMC_I_REG); -+ } while (!(v & CLK_IS_OFF)); -+ writel(host->imask, host->base + MMC_I_MASK); -+ spin_unlock_irqrestore(&host->lock, flags); -+ } -+} -+ -+static void pxamci_enable_irq(struct pxamci_host *host, unsigned int mask) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ host->imask &= ~mask; -+ writel(host->imask, host->base + MMC_I_MASK); -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ host->imask |= mask; -+ writel(host->imask, host->base + MMC_I_MASK); -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) -+{ -+ unsigned int nob = data->blocks; -+ unsigned int timeout, size; -+ dma_addr_t dma; -+ u32 dcmd; -+ int i; -+ -+ host->data = data; -+ -+ if (data->flags & MMC_DATA_STREAM) -+ nob = 0xffff; -+ -+ writel(nob, host->base + MMC_NOB); -+ writel(1 << data->blksz_bits, host->base + MMC_BLKLEN); -+ -+ timeout = ns_to_clocks(data->timeout_ns) + data->timeout_clks; -+ writel((timeout + 255) / 256, host->base + MMC_RDTO); -+ -+ if (data->flags & MMC_DATA_READ) { -+ host->dma_dir = DMA_FROM_DEVICE; -+ dcmd = DCMD_INCTRGADDR | DCMD_FLOWTRG; -+ DRCMRTXMMC = 0; -+ DRCMRRXMMC = host->dma | DRCMR_MAPVLD; -+ } else { -+ host->dma_dir = DMA_TO_DEVICE; -+ dcmd = DCMD_INCSRCADDR | DCMD_FLOWSRC; -+ DRCMRRXMMC = 0; -+ DRCMRTXMMC = host->dma | DRCMR_MAPVLD; -+ } -+ -+ dcmd |= DCMD_BURST32 | DCMD_WIDTH1; -+ -+ host->dma_size = data->blocks << data->blksz_bits; -+ host->dma_buf = dma_map_single(host->mmc.dev, data->rq->buffer, -+ host->dma_size, host->dma_dir); -+ -+ for (i = 0, size = host->dma_size, dma = host->dma_buf; size; i++) { -+ u32 len = size; -+ -+ if (len > DCMD_LENGTH) -+ len = 0x1000; -+ -+ if (data->flags & MMC_DATA_READ) { -+ host->sg_cpu[i].dsadr = host->res->start + MMC_RXFIFO; -+ host->sg_cpu[i].dtadr = dma; -+ } else { -+ host->sg_cpu[i].dsadr = dma; -+ host->sg_cpu[i].dtadr = host->res->start + MMC_TXFIFO; -+ } -+ host->sg_cpu[i].dcmd = dcmd | len; -+ -+ dma += len; -+ size -= len; -+ -+ if (size) { -+ host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) * -+ sizeof(struct pxa_dma_desc); -+ } else { -+ host->sg_cpu[i].ddadr = DDADR_STOP; -+ } -+ } -+ wmb(); -+ -+ DDADR(host->dma) = host->sg_dma; -+ DCSR(host->dma) = DCSR_RUN; -+} -+ -+static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, unsigned int cmdat) -+{ -+ WARN_ON(host->cmd != NULL); -+ host->cmd = cmd; -+ -+ if (cmd->flags & MMC_RSP_BUSY) -+ cmdat |= CMDAT_BUSY; -+ -+ switch (cmd->flags & (MMC_RSP_MASK | MMC_RSP_CRC)) { -+ case MMC_RSP_SHORT | MMC_RSP_CRC: -+ cmdat |= CMDAT_RESP_SHORT; -+ break; -+ case MMC_RSP_SHORT: -+ cmdat |= CMDAT_RESP_R3; -+ break; -+ case MMC_RSP_LONG | MMC_RSP_CRC: -+ cmdat |= CMDAT_RESP_R2; -+ break; -+ default: -+ break; -+ } -+ -+ writel(cmd->opcode, host->base + MMC_CMD); -+ writel(cmd->arg >> 16, host->base + MMC_ARGH); -+ writel(cmd->arg & 0xffff, host->base + MMC_ARGL); -+ writel(cmdat, host->base + MMC_CMDAT); -+ writel(host->clkrt, host->base + MMC_CLKRT); -+ -+ writel(START_CLOCK, host->base + MMC_STRPCL); -+ -+ pxamci_enable_irq(host, END_CMD_RES); -+} -+ -+static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *req) -+{ -+ DBG("PXAMCI: request done\n"); -+ host->req = NULL; -+ host->cmd = NULL; -+ host->data = NULL; -+ mmc_request_done(&host->mmc, req); -+} -+ -+static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat) -+{ -+ struct mmc_command *cmd = host->cmd; -+ int i; -+ u32 v; -+ -+ if (!cmd) -+ return 0; -+ -+ host->cmd = NULL; -+ -+ /* -+ * Did I mention this is Sick. We always need to -+ * discard the upper 8 bits of the first 16-bit word. -+ */ -+ v = readl(host->base + MMC_RES) & 0xffff; -+ for (i = 0; i < 4; i++) { -+ u32 w1 = readl(host->base + MMC_RES) & 0xffff; -+ u32 w2 = readl(host->base + MMC_RES) & 0xffff; -+ cmd->resp[i] = v << 24 | w1 << 8 | w2 >> 8; -+ v = w2; -+ } -+ -+ if (stat & STAT_TIME_OUT_RESPONSE) { -+ cmd->error = MMC_ERR_TIMEOUT; -+ } else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) { -+ cmd->error = MMC_ERR_BADCRC; -+ } -+ -+ pxamci_disable_irq(host, END_CMD_RES); -+ if (host->data && cmd->error == MMC_ERR_NONE) { -+ pxamci_enable_irq(host, DATA_TRAN_DONE); -+ } else { -+ pxamci_finish_request(host, host->req); -+ } -+ -+ return 1; -+} -+ -+static int pxamci_data_done(struct pxamci_host *host, unsigned int stat) -+{ -+ struct mmc_data *data = host->data; -+ -+ if (!data) -+ return 0; -+ -+ DCSR(host->dma) = 0; -+ dma_unmap_single(host->mmc.dev, host->dma_buf, host->dma_size, -+ host->dma_dir); -+ -+ if (stat & STAT_READ_TIME_OUT) -+ data->error = MMC_ERR_TIMEOUT; -+ else if (stat & (STAT_CRC_READ_ERROR|STAT_CRC_WRITE_ERROR)) -+ data->error = MMC_ERR_BADCRC; -+ -+ data->bytes_xfered = (data->blocks - readl(host->base + MMC_NOB)) -+ << data->blksz_bits; -+ -+ pxamci_disable_irq(host, DATA_TRAN_DONE); -+ -+ host->data = NULL; -+ if (host->req->stop && data->error == MMC_ERR_NONE) { -+ pxamci_stop_clock(host); -+ pxamci_start_cmd(host, host->req->stop, 0); -+ } else { -+ pxamci_finish_request(host, host->req); -+ } -+ -+ return 1; -+} -+ -+static irqreturn_t pxamci_irq(int irq, void *devid, struct pt_regs *regs) -+{ -+ struct pxamci_host *host = devid; -+ unsigned int ireg; -+ int handled = 0; -+ -+ ireg = readl(host->base + MMC_I_REG); -+ -+ DBG("PXAMCI: irq %08x\n", ireg); -+ -+ if (ireg) { -+ unsigned stat = readl(host->base + MMC_STAT); -+ -+ DBG("PXAMCI: stat %08x\n", stat); -+ -+ if (ireg & END_CMD_RES) -+ handled |= pxamci_cmd_done(host, stat); -+ if (ireg & DATA_TRAN_DONE) -+ handled |= pxamci_data_done(host, stat); -+ } -+ -+ return IRQ_RETVAL(handled); -+} -+ -+static void pxamci_request(struct mmc_host *mmc, struct mmc_request *req) -+{ -+ struct pxamci_host *host = to_pxamci_host(mmc); -+ unsigned int cmdat; -+ -+ WARN_ON(host->req != NULL); -+ -+ host->req = req; -+ -+ pxamci_stop_clock(host); -+ -+ cmdat = host->cmdat; -+ host->cmdat &= ~CMDAT_INIT; -+ -+ if (req->data) { -+ pxamci_setup_data(host, req->data); -+ -+ cmdat &= ~CMDAT_BUSY; -+ cmdat |= CMDAT_DATAEN | CMDAT_DMAEN; -+ if (req->data->flags & MMC_DATA_WRITE) -+ cmdat |= CMDAT_WRITE; -+ -+ if (req->data->flags & MMC_DATA_STREAM) -+ cmdat |= CMDAT_STREAM; -+ } -+ -+ pxamci_start_cmd(host, req->cmd, cmdat); -+} -+ -+static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -+{ -+ struct pxamci_host *host = to_pxamci_host(mmc); -+ -+ DBG("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; -+ if (CLOCKRATE / clk > ios->clock) -+ clk <<= 1; -+ host->clkrt = fls(clk) - 1; -+ -+ /* -+ * we write clkrt on the next command -+ */ -+ } else if (readl(host->base + MMC_STAT) & STAT_CLK_EN) { -+ /* -+ * Ensure that the clock is off. -+ */ -+ writel(STOP_CLOCK, host->base + MMC_STRPCL); -+ } -+ -+ if (host->power_mode != ios->power_mode) { -+ host->power_mode = ios->power_mode; -+ -+ /* -+ * power control? none on the lubbock. -+ */ -+ -+ if (ios->power_mode == MMC_POWER_ON) -+ host->cmdat |= CMDAT_INIT; -+ } -+ -+ DBG("pxamci_set_ios: clkrt = %x cmdat = %x\n", -+ host->clkrt, host->cmdat); -+} -+ -+static struct mmc_host_ops pxamci_ops = { -+ .request = pxamci_request, -+ .set_ios = pxamci_set_ios, -+}; -+ -+static struct resource *platform_device_resource(struct platform_device *dev, unsigned int mask, int nr) -+{ -+ int i; -+ -+ for (i = 0; i < dev->num_resources; i++) -+ if (dev->resource[i].flags == mask && nr-- == 0) -+ return &dev->resource[i]; -+ return NULL; -+} -+ -+static int platform_device_irq(struct platform_device *dev, int nr) -+{ -+ int i; -+ -+ for (i = 0; i < dev->num_resources; i++) -+ if (dev->resource[i].flags == IORESOURCE_IRQ && nr-- == 0) -+ return dev->resource[i].start; -+ return NO_IRQ; -+} -+ -+static void pxamci_dma_irq(int dma, void *devid, struct pt_regs *regs) -+{ -+ printk(KERN_ERR "DMA%d: IRQ???\n", dma); -+ DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; -+} -+ -+static int pxamci_probe(struct device *dev) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct pxamci_host *host; -+ struct resource *r; -+ int ret, irq; -+ -+ r = platform_device_resource(pdev, IORESOURCE_MEM, 0); -+ irq = platform_device_irq(pdev, 0); -+ if (!r || irq == NO_IRQ) -+ return -ENXIO; -+ -+ r = request_mem_region(r->start, SZ_4K, "PXAMCI"); -+ if (!r) -+ return -EBUSY; -+ -+ host = kmalloc(sizeof(struct pxamci_host), GFP_KERNEL); -+ if (!host) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ memset(host, 0, sizeof(struct pxamci_host)); -+ host->dma = -1; -+ -+ host->sg_cpu = dma_alloc_coherent(dev, PAGE_SIZE, &host->sg_dma, GFP_KERNEL); -+ if (!host->sg_cpu) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ ret = mmc_init_host(&host->mmc); -+ if (ret) -+ goto out; -+ -+ spin_lock_init(&host->lock); -+ host->res = r; -+ host->irq = irq; -+ host->imask = TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD| -+ END_CMD_RES|PRG_DONE|DATA_TRAN_DONE; -+ host->mmc.dev = dev; -+ host->mmc.ops = &pxamci_ops; -+ host->mmc.f_min = 312500; -+ host->mmc.f_max = 20000000; -+ host->mmc.ocr_avail = MMC_VDD_32_33; -+ -+ host->base = ioremap(r->start, SZ_4K); -+ if (!host->base) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ /* -+ * Ensure that the host controller is shut down, and setup -+ * with our defaults. -+ */ -+ pxamci_stop_clock(host); -+ writel(0, host->base + MMC_SPI); -+ writel(64, host->base + MMC_RESTO); -+ -+#ifdef CONFIG_PREEMPT -+#error Not Preempt-safe -+#endif -+ pxa_gpio_mode(GPIO6_MMCCLK_MD); -+ pxa_gpio_mode(GPIO8_MMCCS0_MD); -+ CKEN |= CKEN12_MMC; -+ -+ host->dma = pxa_request_dma("PXAMCI", DMA_PRIO_LOW, pxamci_dma_irq, host); -+ if (host->dma < 0) -+ goto out; -+ -+ ret = request_irq(host->irq, pxamci_irq, 0, "PXAMCI", host); -+ if (ret) -+ goto out; -+ -+ dev_set_drvdata(dev, host); -+ -+ mmc_add_host(&host->mmc); -+ -+ return 0; -+ -+ out: -+ if (host) { -+ if (host->dma >= 0) -+ pxa_free_dma(host->dma); -+ if (host->base) -+ iounmap(host->base); -+ if (host->sg_cpu) -+ dma_free_coherent(dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); -+ kfree(host); -+ } -+ release_resource(r); -+ return ret; -+} -+ -+static int pxamci_remove(struct device *dev) -+{ -+ struct pxamci_host *host = dev_get_drvdata(dev); -+ -+ dev_set_drvdata(dev, NULL); -+ -+ if (host) { -+ mmc_remove_host(&host->mmc); -+ -+ pxamci_stop_clock(host); -+ writel(TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD| -+ END_CMD_RES|PRG_DONE|DATA_TRAN_DONE, -+ host->base + MMC_I_MASK); -+ -+ free_irq(host->irq, host); -+ pxa_free_dma(host->dma); -+ iounmap(host->base); -+ dma_free_coherent(dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); -+ -+ release_resource(host->res); -+ -+ kfree(host); -+ } -+ return 0; -+} -+ -+static int pxamci_suspend(struct device *dev, u32 state, u32 level) -+{ -+ struct pxamci_host *host = dev_get_drvdata(dev); -+ int ret = 0; -+ -+ if (host && level == SUSPEND_DISABLE) -+ ret = mmc_suspend_host(&host->mmc, state); -+ return ret; -+} -+ -+static int pxamci_resume(struct device *dev, u32 level) -+{ -+ struct pxamci_host *host = dev_get_drvdata(dev); -+ int ret = 0; -+ -+ if (host && level == RESUME_ENABLE) -+ ret = mmc_resume_host(&host->mmc); -+ return ret; -+} -+ -+static struct device_driver pxamci_driver = { -+ .name = "pxamci", -+ .bus = &platform_bus_type, -+ .probe = pxamci_probe, -+ .remove = pxamci_remove, -+ .suspend = pxamci_suspend, -+ .resume = pxamci_resume, -+}; -+ -+static int __init pxamci_init(void) -+{ -+ return driver_register(&pxamci_driver); -+} -+ -+static void __exit pxamci_exit(void) -+{ -+ driver_unregister(&pxamci_driver); -+} -+ -+module_init(pxamci_init); -+module_exit(pxamci_exit); -+ -+MODULE_DESCRIPTION("PXA Multimedia Card Interface Driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/media/mmc/mmc.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,15 @@ -+/* -+ * linux/drivers/media/mmc/mmc.h -+ * -+ * Copyright (C) 2003 Russell King, 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. -+ */ -+#ifndef _MMC_H -+/* core-internal functions */ -+void mmc_init_card(struct mmc_card *card, struct mmc_host *host); -+int mmc_register_card(struct mmc_card *card); -+void mmc_remove_card(struct mmc_card *card); -+#endif ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/media/mmc/mmc_sysfs.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,231 @@ -+/* -+ * linux/drivers/media/mmc/mmc_sysfs.c -+ * -+ * Copyright (C) 2003 Russell King, 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. -+ * -+ * MMC sysfs/driver model support. -+ */ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "mmc.h" -+ -+#define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev) -+#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) -+ -+static void mmc_release_card(struct device *dev) -+{ -+ struct mmc_card *card = dev_to_mmc_card(dev); -+ -+ kfree(card); -+} -+ -+/* -+ * This currently matches any MMC driver to any MMC card - drivers -+ * themselves make the decision whether to drive this card in their -+ * probe method. -+ */ -+static int mmc_bus_match(struct device *dev, struct device_driver *drv) -+{ -+ return 1; -+} -+ -+static int -+mmc_bus_hotplug(struct device *dev, char **envp, int num_envp, char *buf, -+ int buf_size) -+{ -+ struct mmc_card *card = dev_to_mmc_card(dev); -+ char ccc[13]; -+ int i = 0; -+ -+#define add_env(fmt,val) \ -+ ({ \ -+ int len, ret = -ENOMEM; \ -+ if (i < num_envp) { \ -+ envp[i++] = buf; \ -+ len = snprintf(buf, buf_size, fmt, val) + 1; \ -+ buf_size -= len; \ -+ buf += len; \ -+ if (buf_size >= 0) \ -+ ret = 0; \ -+ } \ -+ ret; \ -+ }) -+ -+ for (i = 0; i < 12; i++) -+ ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0'; -+ ccc[12] = '\0'; -+ -+ i = 0; -+ add_env("MMC_CCC=%s", ccc); -+ add_env("MMC_MANFID=%03x", card->cid.manfid); -+ add_env("MMC_SLOT_NAME=%s", card->dev.bus_id); -+ -+ return 0; -+} -+ -+static int mmc_bus_suspend(struct device *dev, u32 state) -+{ -+ struct mmc_driver *drv = to_mmc_driver(dev->driver); -+ struct mmc_card *card = dev_to_mmc_card(dev); -+ int ret = 0; -+ -+ if (dev->driver && drv->suspend) -+ ret = drv->suspend(card, state); -+ return ret; -+} -+ -+static int mmc_bus_resume(struct device *dev) -+{ -+ struct mmc_driver *drv = to_mmc_driver(dev->driver); -+ struct mmc_card *card = dev_to_mmc_card(dev); -+ int ret = 0; -+ -+ if (dev->driver && drv->resume) -+ ret = drv->resume(card); -+ return ret; -+} -+ -+static struct bus_type mmc_bus_type = { -+ .name = "mmc", -+ .match = mmc_bus_match, -+ .hotplug = mmc_bus_hotplug, -+ .suspend = mmc_bus_suspend, -+ .resume = mmc_bus_resume, -+}; -+ -+ -+static int mmc_drv_probe(struct device *dev) -+{ -+ struct mmc_driver *drv = to_mmc_driver(dev->driver); -+ struct mmc_card *card = dev_to_mmc_card(dev); -+ -+ return drv->probe(card); -+} -+ -+static int mmc_drv_remove(struct device *dev) -+{ -+ struct mmc_driver *drv = to_mmc_driver(dev->driver); -+ struct mmc_card *card = dev_to_mmc_card(dev); -+ -+ drv->remove(card); -+ -+ return 0; -+} -+ -+ -+/** -+ * mmc_register_driver - register a media driver -+ * @drv: MMC media driver -+ */ -+int mmc_register_driver(struct mmc_driver *drv) -+{ -+ drv->drv.bus = &mmc_bus_type; -+ drv->drv.probe = mmc_drv_probe; -+ drv->drv.remove = mmc_drv_remove; -+ return driver_register(&drv->drv); -+} -+ -+EXPORT_SYMBOL(mmc_register_driver); -+ -+/** -+ * mmc_unregister_driver - unregister a media driver -+ * @drv: MMC media driver -+ */ -+void mmc_unregister_driver(struct mmc_driver *drv) -+{ -+ drv->drv.bus = &mmc_bus_type; -+ driver_unregister(&drv->drv); -+} -+ -+EXPORT_SYMBOL(mmc_unregister_driver); -+ -+ -+#define MMC_ATTR(name, fmt, args...) \ -+static ssize_t mmc_dev_show_##name (struct device *dev, char *buf) \ -+{ \ -+ struct mmc_card *card = dev_to_mmc_card(dev); \ -+ return sprintf(buf, fmt, args); \ -+} \ -+static DEVICE_ATTR(name, S_IRUGO, mmc_dev_show_##name, NULL) -+ -+MMC_ATTR(date, "%02d/%04d\n", card->cid.month, 1997 + card->cid.year); -+MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev); -+MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev); -+MMC_ATTR(manfid, "0x%03x\n", card->cid.manfid); -+MMC_ATTR(serial, "0x%06x\n", card->cid.serial); -+MMC_ATTR(name, "%s\n", card->cid.prod_name); -+ -+static struct device_attribute *mmc_dev_attributes[] = { -+ &dev_attr_date, -+ &dev_attr_fwrev, -+ &dev_attr_hwrev, -+ &dev_attr_manfid, -+ &dev_attr_serial, -+ &dev_attr_name, -+}; -+ -+/* -+ * Internal function. Initialise a MMC card structure. -+ */ -+void mmc_init_card(struct mmc_card *card, struct mmc_host *host) -+{ -+ memset(card, 0, sizeof(struct mmc_card)); -+ card->host = host; -+ device_initialize(&card->dev); -+ card->dev.parent = card->host->dev; -+ card->dev.bus = &mmc_bus_type; -+ card->dev.release = mmc_release_card; -+} -+ -+/* -+ * Internal function. Register a new MMC card with the driver model. -+ */ -+int mmc_register_card(struct mmc_card *card) -+{ -+ int ret, i; -+ -+ snprintf(card->dev.bus_id, sizeof(card->dev.bus_id), -+ "mmc%02x:%04x", card->host->host_num, card->rca); -+ -+ ret = device_add(&card->dev); -+ if (ret == 0) -+ for (i = 0; i < ARRAY_SIZE(mmc_dev_attributes); i++) -+ device_create_file(&card->dev, mmc_dev_attributes[i]); -+ -+ return ret; -+} -+ -+/* -+ * Internal function. Unregister a new MMC card with the -+ * driver model, and (eventually) free it. -+ */ -+void mmc_remove_card(struct mmc_card *card) -+{ -+ if (mmc_card_present(card)) -+ device_del(&card->dev); -+ -+ put_device(&card->dev); -+} -+ -+ -+static int __init mmc_init(void) -+{ -+ return bus_register(&mmc_bus_type); -+} -+ -+static void __exit mmc_exit(void) -+{ -+ bus_unregister(&mmc_bus_type); -+} -+ -+module_init(mmc_init); -+module_exit(mmc_exit); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/media/mmc/mmci.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,445 @@ -+/* -+ * linux/drivers/media/mmc/mmci.c - ARM PrimeCell MMCI PL180/1 driver -+ * -+ * Copyright (C) 2003 Deep Blue Solutions, Ltd, 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. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "mmci.h" -+ -+#define DRIVER_NAME "mmci-pl18x" -+ -+#ifdef CONFIG_MMC_DEBUG -+#define DBG(x...) printk(KERN_DEBUG x) -+#else -+#define DBG(x...) do { } while (0) -+#endif -+ -+static int fmax = 515633; -+ -+static void -+mmci_request_end(struct mmci_host *host, struct mmc_request *req) -+{ -+ writel(0, host->base + MMCICOMMAND); -+ host->req = NULL; -+ host->cmd = NULL; -+ host->data = NULL; -+ -+ if (req->data) -+ req->data->bytes_xfered = host->data_xfered; -+ -+ mmc_request_done(&host->mmc, req); -+} -+ -+static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) -+{ -+ unsigned int datactrl; -+ -+ DBG("MMCI: data: blksz %04x blks %04x flags %08x\n", -+ 1 << data->blksz_bits, data->blocks, data->flags); -+ -+ datactrl = MCI_DPSM_ENABLE | data->blksz_bits << 4; -+ -+ if (data->flags & MMC_DATA_READ) -+ datactrl |= MCI_DPSM_DIRECTION; -+ -+ host->data = data; -+ host->buffer = data->rq->buffer; -+ host->size = data->blocks << data->blksz_bits; -+ host->data_xfered = 0; -+ -+ writel(0x800000, host->base + MMCIDATATIMER); -+ writel(host->size, host->base + MMCIDATALENGTH); -+ writel(datactrl, host->base + MMCIDATACTRL); -+} -+ -+static void -+mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) -+{ -+ DBG("MMCI: cmd: op %02x arg %08x flags %08x\n", -+ cmd->opcode, cmd->arg, cmd->flags); -+ -+ if (readl(host->base + MMCICOMMAND) & MCI_CPSM_ENABLE) { -+ writel(0, host->base + MMCICOMMAND); -+ udelay(1); -+ } -+ -+ c |= cmd->opcode | MCI_CPSM_ENABLE; -+ switch (cmd->flags & MMC_RSP_MASK) { -+ case MMC_RSP_NONE: -+ default: -+ break; -+ case MMC_RSP_LONG: -+ c |= MCI_CPSM_LONGRSP; -+ case MMC_RSP_SHORT: -+ c |= MCI_CPSM_RESPONSE; -+ break; -+ } -+ if (/*interrupt*/0) -+ c |= MCI_CPSM_INTERRUPT; -+ -+ host->cmd = cmd; -+ -+ writel(cmd->arg, host->base + MMCIARGUMENT); -+ writel(c, host->base + MMCICOMMAND); -+} -+ -+static void -+mmci_data_irq(struct mmci_host *host, struct mmc_data *data, -+ unsigned int status) -+{ -+ if (status & MCI_DATABLOCKEND) { -+ host->data_xfered += 1 << data->blksz_bits; -+ } -+ if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { -+ if (status & MCI_DATACRCFAIL) -+ data->error = MMC_ERR_BADCRC; -+ else if (status & MCI_DATATIMEOUT) -+ data->error = MMC_ERR_TIMEOUT; -+ else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) -+ data->error = MMC_ERR_FIFO; -+ status |= MCI_DATAEND; -+ } -+ if (status & MCI_DATAEND) { -+ host->data = NULL; -+ if (!data->stop) { -+ mmci_request_end(host, data->req); -+ } else /*if (readl(host->base + MMCIDATACNT) > 6)*/ { -+ mmci_start_command(host, data->stop, 0); -+ } -+ } -+} -+ -+static void -+mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, -+ unsigned int status) -+{ -+ host->cmd = NULL; -+ -+ cmd->resp[0] = readl(host->base + MMCIRESPONSE0); -+ cmd->resp[1] = readl(host->base + MMCIRESPONSE1); -+ cmd->resp[2] = readl(host->base + MMCIRESPONSE2); -+ cmd->resp[3] = readl(host->base + MMCIRESPONSE3); -+ -+ if (status & MCI_CMDTIMEOUT) { -+ cmd->error = MMC_ERR_TIMEOUT; -+ } else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) { -+ cmd->error = MMC_ERR_BADCRC; -+ } -+ -+ if (!cmd->data || cmd->error != MMC_ERR_NONE) { -+ mmci_request_end(host, cmd->req); -+ } else if (!(cmd->data->flags & MMC_DATA_READ)) { -+ mmci_start_data(host, cmd->data); -+ } -+} -+ -+static irqreturn_t mmci_irq(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ struct mmci_host *host = dev_id; -+ u32 status; -+ int ret = 0; -+ -+ do { -+ struct mmc_command *cmd; -+ struct mmc_data *data; -+ -+ status = readl(host->base + MMCISTATUS); -+ writel(status, host->base + MMCICLEAR); -+ -+ if (!(status & MCI_IRQMASK)) -+ break; -+ -+ DBG("MMCI: irq %08x\n", status); -+ -+ if (status & (MCI_RXDATAAVLBL|MCI_RXFIFOHALFFULL)) { -+ int count = host->size - (readl(host->base + MMCIFIFOCNT) << 2); -+ if (count < 0) -+ count = 0; -+ if (count && host->buffer) { -+ readsl(host->base + MMCIFIFO, host->buffer, count >> 2); -+ host->buffer += count; -+ host->size -= count; -+ if (host->size == 0) -+ host->buffer = NULL; -+ } else { -+ static int first = 1; -+ if (first) { -+ first = 0; -+ printk(KERN_ERR "MMCI: sinking excessive data\n"); -+ } -+ readl(host->base + MMCIFIFO); -+ } -+ } -+ if (status & (MCI_TXFIFOEMPTY|MCI_TXFIFOHALFEMPTY)) { -+ int count = host->size; -+ if (count > MCI_FIFOHALFSIZE) -+ count = MCI_FIFOHALFSIZE; -+ if (count && host->buffer) { -+ writesl(host->base + MMCIFIFO, host->buffer, count >> 2); -+ host->buffer += count; -+ host->size -= count; -+ if (host->size == 0) -+ host->buffer = NULL; -+ } else { -+ static int first = 1; -+ if (first) { -+ first = 0; -+ printk(KERN_ERR "MMCI: ran out of source data\n"); -+ } -+ } -+ } -+ -+ data = host->data; -+ if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN| -+ MCI_RXOVERRUN|MCI_DATAEND|MCI_DATABLOCKEND)) -+ mmci_data_irq(host, data, status); -+ -+ cmd = host->cmd; -+ if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND) && cmd) -+ mmci_cmd_irq(host, cmd, status); -+ -+ ret = 1; -+ } while (status); -+ -+ return IRQ_RETVAL(ret); -+} -+ -+static void mmci_request(struct mmc_host *mmc, struct mmc_request *req) -+{ -+ struct mmci_host *host = to_mmci_host(mmc); -+ -+ WARN_ON(host->req != NULL); -+ -+ host->req = req; -+ -+ if (req->data && req->data->flags & MMC_DATA_READ) -+ mmci_start_data(host, req->data); -+ -+ mmci_start_command(host, req->cmd, 0); -+} -+ -+static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -+{ -+ struct mmci_host *host = to_mmci_host(mmc); -+ u32 clk = 0, pwr = 0; -+ -+ DBG("MMCI: set_ios: clock %dHz busmode %d powermode %d Vdd %d.%02d\n", -+ ios->clock, ios->bus_mode, ios->power_mode, -+ ios->vdd / 100, ios->vdd % 100); -+ -+ if (ios->clock) { -+ clk = host->mclk / (2 * ios->clock) - 1; -+ if (clk > 256) -+ clk = 255; -+ clk |= MCI_CLK_ENABLE; -+ } -+ -+ switch (ios->power_mode) { -+ case MMC_POWER_OFF: -+ break; -+ case MMC_POWER_UP: -+ pwr |= MCI_PWR_UP; -+ break; -+ case MMC_POWER_ON: -+ pwr |= MCI_PWR_ON; -+ break; -+ } -+ -+ if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) -+ pwr |= MCI_ROD; -+ -+ writel(clk, host->base + MMCICLOCK); -+ -+ if (host->pwr != pwr) { -+ host->pwr = pwr; -+ writel(pwr, host->base + MMCIPOWER); -+ } -+} -+ -+static struct mmc_host_ops mmci_ops = { -+ .request = mmci_request, -+ .set_ios = mmci_set_ios, -+}; -+ -+static int mmci_probe(struct amba_device *dev, void *id) -+{ -+ struct mmci_host *host; -+ int ret; -+// void *tmp; -+ -+ /* enable the interrupt via the VIC */ -+// tmp = ioremap(0xc3000000, SZ_4K); -+// if (tmp) { -+// u32 val = readl(tmp + 0x10); -+// writel(val | 0x180, tmp + 0x10); -+// iounmap(tmp); -+// } -+ -+ if (!request_mem_region(dev->res.start, SZ_4K, DRIVER_NAME)) -+ return -EBUSY; -+ -+ host = kmalloc(sizeof(struct mmci_host), GFP_KERNEL); -+ if (!host) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ memset(host, 0, sizeof(struct mmci_host)); -+ -+ ret = mmc_init_host(&host->mmc); -+ if (ret) -+ goto out; -+ -+ host->base = ioremap(dev->res.start, SZ_4K); -+ if (!host->base) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ host->irq = dev->irq; -+ host->mclk = 33000000; /* impd1 */ -+ host->mmc.dev = &dev->dev; -+ host->mmc.ops = &mmci_ops; -+ host->mmc.f_min = (host->mclk + 511) / 512; -+ host->mmc.f_max = host->mclk / 2; -+ if (host->mmc.f_max > fmax) -+ host->mmc.f_max = fmax; -+ -+ host->mmc.ocr_avail = MMC_VDD_35_36; -+ -+ writel(0, host->base + MMCIMASK0); -+ writel(0, host->base + MMCIMASK1); -+ writel(0xfff, host->base + MMCICLEAR); -+ -+ ret = request_irq(host->irq, mmci_irq, SA_SHIRQ, DRIVER_NAME, host); -+ if (ret) -+ goto out; -+ -+ writel(MCI_IRQENABLE, host->base + MMCIMASK0); -+ -+ amba_set_drvdata(dev, host); -+ -+ mmc_add_host(&host->mmc); -+ -+ return 0; -+ -+ out: -+ if (host) { -+ if (host->base) -+ iounmap(host->base); -+ kfree(host); -+ } -+ release_mem_region(dev->res.start, SZ_4K); -+ return ret; -+} -+ -+static int mmci_remove(struct amba_device *dev) -+{ -+ struct mmci_host *host = amba_get_drvdata(dev); -+ -+ amba_set_drvdata(dev, NULL); -+ -+ if (host) { -+ mmc_remove_host(&host->mmc); -+ -+ writel(0, host->base + MMCIMASK0); -+ writel(0, host->base + MMCIMASK1); -+ -+ writel(0, host->base + MMCICOMMAND); -+ writel(0, host->base + MMCIDATACTRL); -+ -+ free_irq(host->irq, host); -+ -+ iounmap(host->base); -+ -+ kfree(host); -+ -+ release_mem_region(dev->res.start, SZ_4K); -+ } -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int mmci_suspend(struct amba_device *dev, u32 state) -+{ -+ struct mmci_host *host = amba_get_drvdata(dev); -+ -+ return host ? mmc_suspend_host(&host->mmc, state) : 0; -+} -+ -+static int mmci_resume(struct amba_device *dev) -+{ -+ struct mmci_host *host = amba_get_drvdata(dev); -+ int ret = 0; -+ -+ if (host) { -+ writel(MCI_IRQENABLE, host->base + MMCIMASK0); -+ ret = mmc_resume_host(&host->mmc); -+ } -+ -+ return ret; -+} -+#else -+#define mmci_suspend NULL -+#define mmci_resume NULL -+#endif -+ -+static struct amba_id mmci_ids[] = { -+ { -+ .id = 0x00041180, -+ .mask = 0x000fffff, -+ }, -+ { -+ .id = 0x00041181, -+ .mask = 0x000fffff, -+ }, -+ { 0, 0 }, -+}; -+ -+static struct amba_driver mmci_driver = { -+ .drv = { -+ .name = DRIVER_NAME, -+ }, -+ .probe = mmci_probe, -+ .remove = mmci_remove, -+ .suspend = mmci_suspend, -+ .resume = mmci_resume, -+ .id_table = mmci_ids, -+}; -+ -+static int __init mmci_init(void) -+{ -+ return amba_driver_register(&mmci_driver); -+} -+ -+static void __exit mmci_exit(void) -+{ -+ amba_driver_unregister(&mmci_driver); -+} -+ -+module_init(mmci_init); -+module_exit(mmci_exit); -+module_param(fmax, int, 0444); -+ -+MODULE_DESCRIPTION("ARM PrimeCell PL180/181 Multimedia Card Interface driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/media/mmc/mmc_queue.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,29 @@ -+#ifndef MMC_QUEUE_H -+#define MMC_QUEUE_H -+ -+struct request; -+struct task_struct; -+ -+struct mmc_queue { -+ struct mmc_card *card; -+ struct completion thread_complete; -+ wait_queue_head_t thread_wq; -+ struct task_struct *thread; -+ struct request *req; -+ int (*prep_fn)(struct mmc_queue *, struct request *); -+ int (*issue_fn)(struct mmc_queue *, struct request *); -+ void *data; -+ struct request_queue *queue; -+}; -+ -+struct mmc_io_request { -+ struct request *rq; -+ int num; -+ struct mmc_command selcmd; /* mmc_queue private */ -+ struct mmc_command cmd[4]; /* max 4 commands */ -+}; -+ -+extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *); -+extern void mmc_cleanup_queue(struct mmc_queue *); -+ -+#endif ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/media/mmc/mmc_block.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,482 @@ -+/* -+ * Block driver for media (i.e., flash cards) -+ * -+ * Copyright 2002 Hewlett-Packard Company -+ * -+ * Use consistent with the GNU GPL is permitted, -+ * provided that this copyright notice is -+ * preserved in its entirety in all copies and derived works. -+ * -+ * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, -+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS -+ * FITNESS FOR ANY PARTICULAR PURPOSE. -+ * -+ * Many thanks to Alessandro Rubini and Jonathan Corbet! -+ * -+ * Author: Andrew Christian -+ * 28 May 2002 -+ */ -+#include -+#include -+#include -+ -+#include -+#include /* printk() */ -+#include /* everything... */ -+#include /* error codes */ -+#include /* HDIO_GETGEO */ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+ -+#include "mmc_queue.h" -+ -+#define MMC_SHIFT 3 /* max 8 partitions per card */ -+ -+static int mmc_major; -+static int maxsectors = 8; -+ -+/* -+ * There is one mmc_blk_data per slot. -+ */ -+struct mmc_blk_data { -+ spinlock_t lock; -+ struct gendisk *disk; -+ struct mmc_queue queue; -+ -+ unsigned int usage; -+ unsigned int block_bits; -+ unsigned int suspended; -+}; -+ -+static DECLARE_MUTEX(open_lock); -+ -+static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) -+{ -+ struct mmc_blk_data *md; -+ -+ down(&open_lock); -+ md = disk->private_data; -+ if (md && md->usage == 0) -+ md = NULL; -+ if (md) -+ md->usage++; -+ up(&open_lock); -+ -+ return md; -+} -+ -+static void mmc_blk_put(struct mmc_blk_data *md) -+{ -+ down(&open_lock); -+ md->usage--; -+ if (md->usage == 0) { -+ put_disk(md->disk); -+ mmc_cleanup_queue(&md->queue); -+ kfree(md); -+ } -+ up(&open_lock); -+} -+ -+static int mmc_blk_open(struct inode *inode, struct file *filp) -+{ -+ struct mmc_blk_data *md; -+ int ret = -ENXIO; -+ -+ md = mmc_blk_get(inode->i_bdev->bd_disk); -+ if (md) { -+ if (md->usage == 2) -+ check_disk_change(inode->i_bdev); -+ ret = 0; -+ } -+ -+ return ret; -+} -+ -+static int mmc_blk_release(struct inode *inode, struct file *filp) -+{ -+ struct mmc_blk_data *md = inode->i_bdev->bd_disk->private_data; -+ -+ mmc_blk_put(md); -+ return 0; -+} -+ -+static int -+mmc_blk_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -+{ -+ struct block_device *bdev = inode->i_bdev; -+ -+ if (cmd == HDIO_GETGEO) { -+ struct hd_geometry geo; -+ -+ memset(&geo, 0, sizeof(struct hd_geometry)); -+ -+ geo.cylinders = get_capacity(bdev->bd_disk) / (4 * 16); -+ geo.heads = 4; -+ geo.sectors = 16; -+ geo.start = get_start_sect(bdev); -+ -+ return copy_to_user((void *)arg, &geo, sizeof(geo)) -+ ? -EFAULT : 0; -+ } -+ -+ return -ENOTTY; -+} -+ -+static struct block_device_operations mmc_bdops = { -+ .open = mmc_blk_open, -+ .release = mmc_blk_release, -+ .ioctl = mmc_blk_ioctl, -+ .owner = THIS_MODULE, -+}; -+ -+struct mmc_blk_request { -+ struct mmc_request req; -+ struct mmc_command cmd; -+ struct mmc_command stop; -+ struct mmc_data data; -+}; -+ -+static int mmc_blk_prep_rq(struct mmc_queue *mq, struct request *req) -+{ -+ struct mmc_blk_data *md = mq->data; -+ -+ /* -+ * If we have no device, we haven't finished initialising. -+ */ -+ if (!md || !mq->card) { -+ printk("killing request - no device/host\n"); -+ goto kill; -+ } -+ -+ if (md->suspended) { -+ blk_plug_device(md->queue.queue); -+ goto defer; -+ } -+ -+ /* -+ * Check for excessive requests. -+ */ -+ if (req->sector + req->nr_sectors > get_capacity(req->rq_disk)) { -+ printk("bad request size\n"); -+ goto kill; -+ } -+ -+ return BLKPREP_OK; -+ -+ defer: -+ return BLKPREP_DEFER; -+ kill: -+ return BLKPREP_KILL; -+} -+ -+static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) -+{ -+ struct mmc_blk_data *md = mq->data; -+ struct mmc_card *card = md->queue.card; -+ int err, sz = 0; -+ -+ err = mmc_card_claim_host(card); -+ if (err) -+ goto cmd_err; -+ -+ do { -+ struct mmc_blk_request rq; -+ struct mmc_command cmd; -+ -+ memset(&rq, 0, sizeof(struct mmc_blk_request)); -+ rq.req.cmd = &rq.cmd; -+ rq.req.data = &rq.data; -+ -+ rq.cmd.arg = req->sector << 9; -+ rq.cmd.flags = MMC_RSP_SHORT | MMC_RSP_CRC; -+ rq.data.rq = req; -+ rq.data.timeout_ns = card->csd.tacc_ns * 10; -+ rq.data.timeout_clks = card->csd.tacc_clks * 10; -+ rq.data.blksz_bits = md->block_bits; -+ rq.data.blocks = req->current_nr_sectors >> (md->block_bits - 9); -+ rq.stop.opcode = MMC_STOP_TRANSMISSION; -+ rq.stop.arg = 0; -+ rq.stop.flags = MMC_RSP_SHORT | MMC_RSP_CRC | MMC_RSP_BUSY; -+ -+ if (rq_data_dir(req) == READ) { -+ rq.cmd.opcode = rq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK; -+ rq.data.flags |= MMC_DATA_READ; -+ } else { -+ rq.cmd.opcode = MMC_WRITE_BLOCK; -+ rq.cmd.flags |= MMC_RSP_BUSY; -+ rq.data.flags |= MMC_DATA_WRITE; -+ rq.data.blocks = 1; -+ } -+ rq.req.stop = rq.data.blocks > 1 ? &rq.stop : NULL; -+ -+ mmc_wait_for_req(card->host, &rq.req); -+ if (rq.cmd.error) { -+ err = rq.cmd.error; -+ printk("error %d sending read/write command\n", err); -+ goto cmd_err; -+ } -+ -+ if (rq_data_dir(req) == READ) { -+ sz = rq.data.bytes_xfered; -+ } else { -+ sz = 0; -+ } -+ -+ if (rq.data.error) { -+ err = rq.data.error; -+ printk("error %d transferring data\n", err); -+ goto cmd_err; -+ } -+ -+ if (rq.stop.error) { -+ err = rq.stop.error; -+ printk("error %d sending stop command\n", err); -+ goto cmd_err; -+ } -+ -+ do { -+ cmd.opcode = MMC_SEND_STATUS; -+ cmd.arg = card->rca << 16; -+ cmd.flags = MMC_RSP_SHORT | MMC_RSP_CRC; -+ err = mmc_wait_for_cmd(card->host, &cmd, 5); -+ if (err) { -+ printk("error %d requesting status\n", err); -+ goto cmd_err; -+ } -+ } while (!(cmd.resp[0] & R1_READY_FOR_DATA)); -+ -+#if 0 -+ if (cmd.resp[0] & ~0x00000900) -+ printk("status = %08x\n", cmd.resp[0]); -+ err = mmc_decode_status(cmd.resp); -+ if (err) -+ goto cmd_err; -+#endif -+ -+ sz = rq.data.bytes_xfered; -+ } while (end_that_request_chunk(req, 1, sz)); -+ -+ mmc_card_release_host(card); -+ -+ return 1; -+ -+ cmd_err: -+ mmc_card_release_host(card); -+ -+ end_that_request_chunk(req, 1, sz); -+ req->errors = err; -+ -+ return 0; -+} -+ -+#define MMC_NUM_MINORS (256 >> MMC_SHIFT) -+ -+static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))]; -+ -+static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) -+{ -+ struct mmc_blk_data *md; -+ int devidx; -+ -+ devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS); -+ if (devidx >= MMC_NUM_MINORS) -+ return NULL; -+ __set_bit(devidx, dev_use); -+ -+ md = kmalloc(sizeof(struct mmc_blk_data), GFP_KERNEL); -+ if (md) { -+ memset(md, 0, sizeof(struct mmc_blk_data)); -+ -+ md->disk = alloc_disk(1 << MMC_SHIFT); -+ if (md->disk == NULL) { -+ kfree(md); -+ md = NULL; -+ goto out; -+ } -+ -+ spin_lock_init(&md->lock); -+ md->usage = 1; -+ -+ mmc_init_queue(&md->queue, card, &md->lock); -+ md->queue.prep_fn = mmc_blk_prep_rq; -+ md->queue.issue_fn = mmc_blk_issue_rq; -+ md->queue.data = md; -+ -+ md->disk->major = mmc_major; -+ md->disk->first_minor = devidx << MMC_SHIFT; -+ md->disk->fops = &mmc_bdops; -+ md->disk->private_data = md; -+ md->disk->queue = md->queue.queue; -+ md->disk->driverfs_dev = &card->dev; -+ -+ sprintf(md->disk->disk_name, "mmcblk%d", devidx); -+ sprintf(md->disk->devfs_name, "mmc/blk%d", devidx); -+ -+ md->block_bits = md->queue.card->csd.read_blkbits; -+ -+ blk_queue_max_sectors(md->queue.queue, maxsectors); -+ blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits); -+ set_capacity(md->disk, md->queue.card->csd.capacity); -+ } -+ out: -+ return md; -+} -+ -+static int -+mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) -+{ -+ struct mmc_command cmd; -+ int err; -+ -+ mmc_card_claim_host(card); -+ cmd.opcode = MMC_SET_BLOCKLEN; -+ cmd.arg = 1 << card->csd.read_blkbits; -+ cmd.flags = MMC_RSP_SHORT | MMC_RSP_CRC; -+ err = mmc_wait_for_cmd(card->host, &cmd, 5); -+ mmc_card_release_host(card); -+ -+ if (err) { -+ printk(KERN_ERR "%s: unable to set block size to %d: %d\n", -+ md->disk->disk_name, cmd.arg, err); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int mmc_blk_probe(struct mmc_card *card) -+{ -+ struct mmc_blk_data *md; -+ int err; -+ -+ if (card->csd.cmdclass & ~0x1ff) -+ return -ENODEV; -+ -+ if (card->csd.read_blkbits < 9) { -+ printk(KERN_WARNING "%s: read blocksize too small (%u)\n", -+ mmc_card_id(card), 1 << card->csd.read_blkbits); -+ return -ENODEV; -+ } -+ -+ md = mmc_blk_alloc(card); -+ if (md == NULL) -+ return -ENOMEM; -+ -+ err = mmc_blk_set_blksize(md, card); -+ if (err) -+ goto out; -+ -+ printk(KERN_INFO "%s: %s %s %dKiB\n", -+ md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), -+ (card->csd.capacity << card->csd.read_blkbits) / 1024); -+ -+ mmc_set_drvdata(card, md); -+ add_disk(md->disk); -+ return 0; -+ -+ out: -+ mmc_blk_put(md); -+ -+ return err; -+} -+ -+static void mmc_blk_remove(struct mmc_card *card) -+{ -+ struct mmc_blk_data *md = mmc_get_drvdata(card); -+ -+ if (md) { -+ int devidx; -+ -+ del_gendisk(md->disk); -+ -+ /* -+ * I think this is needed. -+ */ -+ md->disk->queue = NULL; -+ -+ devidx = md->disk->first_minor >> MMC_SHIFT; -+ __clear_bit(devidx, dev_use); -+ -+ mmc_blk_put(md); -+ } -+ mmc_set_drvdata(card, NULL); -+} -+ -+#ifdef CONFIG_PM -+static int mmc_blk_suspend(struct mmc_card *card, u32 state) -+{ -+ struct mmc_blk_data *md = mmc_get_drvdata(card); -+ -+ if (md) { -+ blk_stop_queue(md->queue.queue); -+ } -+ return 0; -+} -+ -+static int mmc_blk_resume(struct mmc_card *card) -+{ -+ struct mmc_blk_data *md = mmc_get_drvdata(card); -+ -+ if (md) { -+ mmc_blk_set_blksize(md, md->queue.card); -+ blk_start_queue(md->queue.queue); -+ } -+ return 0; -+} -+#else -+#define mmc_blk_suspend NULL -+#define mmc_blk_resume NULL -+#endif -+ -+static struct mmc_driver mmc_driver = { -+ .drv = { -+ .name = "mmcblk", -+ }, -+ .probe = mmc_blk_probe, -+ .remove = mmc_blk_remove, -+ .suspend = mmc_blk_suspend, -+ .resume = mmc_blk_resume, -+}; -+ -+static int __init mmc_blk_init(void) -+{ -+ int res = -ENOMEM; -+ -+ res = register_blkdev(mmc_major, "mmc"); -+ if (res < 0) { -+ printk(KERN_WARNING "Unable to get major %d for MMC media: %d\n", -+ mmc_major, res); -+ goto out; -+ } -+ if (mmc_major == 0) -+ mmc_major = res; -+ -+ devfs_mk_dir("mmc"); -+ return mmc_register_driver(&mmc_driver); -+ -+ out: -+ return res; -+} -+ -+static void __exit mmc_blk_exit(void) -+{ -+ mmc_unregister_driver(&mmc_driver); -+ devfs_remove("mmc"); -+ unregister_blkdev(mmc_major, "mmc"); -+} -+ -+module_init(mmc_blk_init); -+module_exit(mmc_blk_exit); -+module_param(maxsectors, int, 0444); -+ -+MODULE_PARM_DESC(maxsectors, "Maximum number of sectors for a single request"); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/media/mmc/pxamci.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,94 @@ -+#undef MMC_STRPCL -+#undef MMC_STAT -+#undef MMC_CLKRT -+#undef MMC_SPI -+#undef MMC_CMDAT -+#undef MMC_RESTO -+#undef MMC_RDTO -+#undef MMC_BLKLEN -+#undef MMC_NOB -+#undef MMC_PRTBUF -+#undef MMC_I_MASK -+#undef END_CMD_RES -+#undef PRG_DONE -+#undef DATA_TRAN_DONE -+#undef MMC_I_REG -+#undef MMC_CMD -+#undef MMC_ARGH -+#undef MMC_ARGL -+#undef MMC_RES -+#undef MMC_RXFIFO -+#undef MMC_TXFIFO -+ -+#define MMC_STRPCL 0x0000 -+#define STOP_CLOCK (1 << 0) -+#define START_CLOCK (2 << 0) -+ -+#define MMC_STAT 0x0004 -+#define STAT_END_CMD_RES (1 << 13) -+#define STAT_PRG_DONE (1 << 12) -+#define STAT_DATA_TRAN_DONE (1 << 11) -+#define STAT_CLK_EN (1 << 8) -+#define STAT_RECV_FIFO_FULL (1 << 7) -+#define STAT_XMIT_FIFO_EMPTY (1 << 6) -+#define STAT_RES_CRC_ERR (1 << 5) -+#define STAT_SPI_READ_ERROR_TOKEN (1 << 4) -+#define STAT_CRC_READ_ERROR (1 << 3) -+#define STAT_CRC_WRITE_ERROR (1 << 2) -+#define STAT_TIME_OUT_RESPONSE (1 << 1) -+#define STAT_READ_TIME_OUT (1 << 0) -+ -+#define MMC_CLKRT 0x0008 /* 3 bit */ -+ -+#define MMC_SPI 0x000c -+#define SPI_CS_ADDRESS (1 << 3) -+#define SPI_CS_EN (1 << 2) -+#define CRC_ON (1 << 1) -+#define SPI_EN (1 << 0) -+ -+#define MMC_CMDAT 0x0010 -+#define CMDAT_DMAEN (1 << 7) -+#define CMDAT_INIT (1 << 6) -+#define CMDAT_BUSY (1 << 5) -+#define CMDAT_STREAM (1 << 4) /* 1 = stream */ -+#define CMDAT_WRITE (1 << 3) /* 1 = write */ -+#define CMDAT_DATAEN (1 << 2) -+#define CMDAT_RESP_NONE (0 << 0) -+#define CMDAT_RESP_SHORT (1 << 0) -+#define CMDAT_RESP_R2 (2 << 0) -+#define CMDAT_RESP_R3 (3 << 0) -+ -+#define MMC_RESTO 0x0014 /* 7 bit */ -+ -+#define MMC_RDTO 0x0018 /* 16 bit */ -+ -+#define MMC_BLKLEN 0x001c /* 10 bit */ -+ -+#define MMC_NOB 0x0020 /* 16 bit */ -+ -+#define MMC_PRTBUF 0x0024 -+#define BUF_PART_FULL (1 << 0) -+ -+#define MMC_I_MASK 0x0028 -+#define TXFIFO_WR_REQ (1 << 6) -+#define RXFIFO_RD_REQ (1 << 5) -+#define CLK_IS_OFF (1 << 4) -+#define STOP_CMD (1 << 3) -+#define END_CMD_RES (1 << 2) -+#define PRG_DONE (1 << 1) -+#define DATA_TRAN_DONE (1 << 0) -+ -+#define MMC_I_REG 0x002c -+/* same as MMC_I_MASK */ -+ -+#define MMC_CMD 0x0030 -+ -+#define MMC_ARGH 0x0034 /* 16 bit */ -+ -+#define MMC_ARGL 0x0038 /* 16 bit */ -+ -+#define MMC_RES 0x003c /* 16 bit */ -+ -+#define MMC_RXFIFO 0x0040 /* 8 bit */ -+ -+#define MMC_TXFIFO 0x0044 /* 8 bit */ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/media/mmc/mmci.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,147 @@ -+/* -+ * linux/drivers/media/mmc/mmci.h - ARM PrimeCell MMCI PL180/1 driver -+ * -+ * Copyright (C) 2003 Deep Blue Solutions, Ltd, 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. -+ */ -+#define MMCIPOWER 0x000 -+#define MCI_PWR_OFF 0x00 -+#define MCI_PWR_UP 0x02 -+#define MCI_PWR_ON 0x03 -+#define MCI_OD (1 << 6) -+#define MCI_ROD (1 << 7) -+ -+#define MMCICLOCK 0x004 -+#define MCI_CLK_ENABLE (1 << 8) -+#define MCI_PWRSAVE (1 << 9) -+#define MCI_BYPASS (1 << 10) -+ -+#define MMCIARGUMENT 0x008 -+#define MMCICOMMAND 0x00c -+#define MCI_CPSM_RESPONSE (1 << 6) -+#define MCI_CPSM_LONGRSP (1 << 7) -+#define MCI_CPSM_INTERRUPT (1 << 8) -+#define MCI_CPSM_PENDING (1 << 9) -+#define MCI_CPSM_ENABLE (1 << 10) -+ -+#define MMCIRESPCMD 0x010 -+#define MMCIRESPONSE0 0x014 -+#define MMCIRESPONSE1 0x018 -+#define MMCIRESPONSE2 0x01c -+#define MMCIRESPONSE3 0x020 -+#define MMCIDATATIMER 0x024 -+#define MMCIDATALENGTH 0x028 -+#define MMCIDATACTRL 0x02c -+#define MCI_DPSM_ENABLE (1 << 0) -+#define MCI_DPSM_DIRECTION (1 << 1) -+#define MCI_DPSM_MODE (1 << 2) -+#define MCI_DPSM_DMAENABLE (1 << 3) -+ -+#define MMCIDATACNT 0x030 -+#define MMCISTATUS 0x034 -+#define MCI_CMDCRCFAIL (1 << 0) -+#define MCI_DATACRCFAIL (1 << 1) -+#define MCI_CMDTIMEOUT (1 << 2) -+#define MCI_DATATIMEOUT (1 << 3) -+#define MCI_TXUNDERRUN (1 << 4) -+#define MCI_RXOVERRUN (1 << 5) -+#define MCI_CMDRESPEND (1 << 6) -+#define MCI_CMDSENT (1 << 7) -+#define MCI_DATAEND (1 << 8) -+#define MCI_DATABLOCKEND (1 << 10) -+#define MCI_CMDACTIVE (1 << 11) -+#define MCI_TXACTIVE (1 << 12) -+#define MCI_RXACTIVE (1 << 13) -+#define MCI_TXFIFOHALFEMPTY (1 << 14) -+#define MCI_RXFIFOHALFFULL (1 << 15) -+#define MCI_TXFIFOFULL (1 << 16) -+#define MCI_RXFIFOFULL (1 << 17) -+#define MCI_TXFIFOEMPTY (1 << 18) -+#define MCI_RXFIFOEMPTY (1 << 19) -+#define MCI_TXDATAAVLBL (1 << 20) -+#define MCI_RXDATAAVLBL (1 << 21) -+ -+#define MMCICLEAR 0x038 -+#define MCI_CMDCRCFAILCLR (1 << 0) -+#define MCI_DATACRCFAILCLR (1 << 1) -+#define MCI_CMDTIMEOUTCLR (1 << 2) -+#define MCI_DATATIMEOUTCLR (1 << 3) -+#define MCI_TXUNDERRUNCLR (1 << 4) -+#define MCI_RXOVERRUNCLR (1 << 5) -+#define MCI_CMDRESPENDCLR (1 << 6) -+#define MCI_CMDSENTCLR (1 << 7) -+#define MCI_DATAENDCLR (1 << 8) -+#define MCI_DATABLOCKENDCLR (1 << 10) -+ -+#define MMCIMASK0 0x03c -+#define MCI_CMDCRCFAILMASK (1 << 0) -+#define MCI_DATACRCFAILMASK (1 << 1) -+#define MCI_CMDTIMEOUTMASK (1 << 2) -+#define MCI_DATATIMEOUTMASK (1 << 3) -+#define MCI_TXUNDERRUNMASK (1 << 4) -+#define MCI_RXOVERRUNMASK (1 << 5) -+#define MCI_CMDRESPENDMASK (1 << 6) -+#define MCI_CMDSENTMASK (1 << 7) -+#define MCI_DATAENDMASK (1 << 8) -+#define MCI_DATABLOCKENDMASK (1 << 10) -+#define MCI_CMDACTIVEMASK (1 << 11) -+#define MCI_TXACTIVEMASK (1 << 12) -+#define MCI_RXACTIVEMASK (1 << 13) -+#define MCI_TXFIFOHALFEMPTYMASK (1 << 14) -+#define MCI_RXFIFOHALFFULLMASK (1 << 15) -+#define MCI_TXFIFOFULLMASK (1 << 16) -+#define MCI_RXFIFOFULLMASK (1 << 17) -+#define MCI_TXFIFOEMPTYMASK (1 << 18) -+#define MCI_RXFIFOEMPTYMASK (1 << 19) -+#define MCI_TXDATAAVLBLMASK (1 << 20) -+#define MCI_RXDATAAVLBLMASK (1 << 21) -+ -+#define MMCIMASK1 0x040 -+#define MMCIFIFOCNT 0x048 -+#define MMCIFIFO 0x080 /* to 0x0bc */ -+ -+#define MCI_IRQMASK \ -+ (MCI_CMDCRCFAIL|MCI_DATACRCFAIL|MCI_CMDTIMEOUT|MCI_DATATIMEOUT| \ -+ MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_CMDRESPEND|MCI_CMDSENT| \ -+ MCI_DATAEND|MCI_DATABLOCKEND| \ -+ MCI_TXFIFOHALFEMPTY|MCI_RXFIFOHALFFULL| \ -+ MCI_TXFIFOEMPTY|MCI_RXDATAAVLBL) -+ -+#define MCI_IRQENABLE \ -+ (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \ -+ MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ -+ MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATAENDMASK| \ -+ MCI_DATABLOCKENDMASK|MCI_TXFIFOHALFEMPTYMASK| \ -+ MCI_RXFIFOHALFFULLMASK) -+ -+#define MCI_FIFOSIZE 16 -+ -+#define MCI_FIFOHALFSIZE (MCI_FIFOSIZE / 2) -+ -+struct mmci_host { -+ struct mmc_host mmc; -+ void *base; -+ int irq; -+ unsigned int mclk; -+ u32 pwr; -+ -+ struct mmc_request *req; -+ struct mmc_command *cmd; -+ struct mmc_data *data; -+ -+ unsigned int data_xfered; -+ -+ /* pio stuff */ -+ void *buffer; -+ unsigned int size; -+ -+ /* dma stuff */ -+// struct scatterlist *sg_list; -+// int sg_len; -+// int sg_dir; -+}; -+ -+#define to_mmci_host(mmc) container_of(mmc, struct mmci_host, mmc) ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/media/mmc/mmc.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,801 @@ -+/* -+ * linux/drivers/media/mmc/mmc.c -+ * -+ * Copyright (C) 2003 Russell King, 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. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#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 -+ -+/* -+ * OCR Bit positions to 10s of Vdd mV. -+ */ -+static const unsigned short mmc_ocr_bit_to_vdd[] = { -+ 150, 155, 160, 165, 170, 180, 190, 200, -+ 210, 220, 230, 240, 250, 260, 270, 280, -+ 290, 300, 310, 320, 330, 340, 350, 360 -+}; -+ -+static const unsigned int tran_exp[] = { -+ 10000, 100000, 1000000, 10000000, -+ 0, 0, 0, 0 -+}; -+ -+static const unsigned char tran_mant[] = { -+ 0, 10, 12, 13, 15, 20, 25, 30, -+ 35, 40, 45, 50, 55, 60, 70, 80, -+}; -+ -+static const unsigned int tacc_exp[] = { -+ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, -+}; -+ -+static const unsigned int tacc_mant[] = { -+ 0, 10, 12, 13, 15, 20, 25, 30, -+ 35, 40, 45, 50, 55, 60, 70, 80, -+}; -+ -+ -+/** -+ * mmc_request_done - finish processing an MMC command -+ * @host: MMC host which completed command -+ * @cmd: MMC command which completed -+ * @err: MMC error code -+ * -+ * MMC drivers should call this function when they have completed -+ * their processing of a command. This should be called before the -+ * data part of the command has completed. -+ */ -+void mmc_request_done(struct mmc_host *host, struct mmc_request *req) -+{ -+ struct mmc_command *cmd = req->cmd; -+ int err = req->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]); -+ -+ if (err && cmd->retries) { -+ cmd->retries--; -+ cmd->error = 0; -+ host->ops->request(host, req); -+ } else if (req->done) { -+ req->done(req); -+ } -+} -+ -+EXPORT_SYMBOL(mmc_request_done); -+ -+/** -+ * mmc_start_request - start a command on a host -+ * @host: MMC host to start command on -+ * @cmd: MMC command to start -+ * -+ * Queue a command on the specified host. We expect the -+ * caller to be holding the host lock with interrupts disabled. -+ */ -+void -+mmc_start_request(struct mmc_host *host, struct mmc_request *req) -+{ -+ DBG("MMC: starting cmd %02x arg %08x flags %08x\n", -+ req->cmd->opcode, req->cmd->arg, req->cmd->flags); -+ -+ req->cmd->error = 0; -+ req->cmd->req = req; -+ if (req->data) { -+ req->cmd->data = req->data; -+ req->data->error = 0; -+ req->data->req = req; -+ if (req->stop) { -+ req->data->stop = req->stop; -+ req->stop->error = 0; -+ req->stop->req = req; -+ } -+ } -+ host->ops->request(host, req); -+} -+ -+EXPORT_SYMBOL(mmc_start_request); -+ -+static void mmc_wait_done(struct mmc_request *req) -+{ -+ complete(req->done_data); -+} -+ -+int mmc_wait_for_req(struct mmc_host *host, struct mmc_request *req) -+{ -+ DECLARE_COMPLETION(complete); -+ -+ req->done_data = &complete; -+ req->done = mmc_wait_done; -+ -+ mmc_start_request(host, req); -+ -+ wait_for_completion(&complete); -+ -+ return 0; -+} -+ -+EXPORT_SYMBOL(mmc_wait_for_req); -+ -+/** -+ * mmc_wait_for_cmd - start a command and wait for completion -+ * @host: MMC host to start command -+ * @cmd: MMC command to start -+ * @retries: maximum number of retries -+ * -+ * Start a new MMC command for a host, and wait for the command -+ * to complete. Return any error that occurred while the command -+ * was executing. Do not attempt to parse the response. -+ */ -+int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries) -+{ -+ struct mmc_request req; -+ -+ BUG_ON(host->card_busy == NULL); -+ -+ memset(&req, 0, sizeof(struct mmc_request)); -+ -+ memset(cmd->resp, 0, sizeof(cmd->resp)); -+ cmd->retries = retries; -+ -+ req.cmd = cmd; -+ cmd->data = NULL; -+ -+ mmc_wait_for_req(host, &req); -+ -+ return cmd->error; -+} -+ -+EXPORT_SYMBOL(mmc_wait_for_cmd); -+ -+ -+ -+/** -+ * __mmc_claim_host - exclusively claim a host -+ * @host: mmc host to claim -+ * @card: mmc card to claim host for -+ * -+ * Claim a host for a set of operations. If a valid card -+ * is passed and this wasn't the last card selected, select -+ * the card before returning. -+ * -+ * Note: you should use mmc_card_claim_host or mmc_claim_host. -+ */ -+int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ unsigned long flags; -+ int err = 0; -+ -+ add_wait_queue(&host->wq, &wait); -+ spin_lock_irqsave(&host->lock, flags); -+ while (1) { -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ if (host->card_busy == NULL) -+ break; -+ spin_unlock_irqrestore(&host->lock, flags); -+ schedule(); -+ spin_lock_irqsave(&host->lock, flags); -+ } -+ set_current_state(TASK_RUNNING); -+ host->card_busy = card; -+ spin_unlock_irqrestore(&host->lock, flags); -+ remove_wait_queue(&host->wq, &wait); -+ -+ if (card != (void *)-1 && host->card_selected != card) { -+ struct mmc_command cmd; -+ -+ host->card_selected = card; -+ -+ cmd.opcode = MMC_SELECT_CARD; -+ cmd.arg = card->rca << 16; -+ cmd.flags = MMC_RSP_SHORT | MMC_RSP_CRC; -+ -+ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); -+ } -+ -+ return err; -+} -+ -+EXPORT_SYMBOL(__mmc_claim_host); -+ -+/** -+ * mmc_release_host - release a host -+ * @host: mmc host to release -+ * -+ * Release a MMC host, allowing others to claim the host -+ * for their operations. -+ */ -+void mmc_release_host(struct mmc_host *host) -+{ -+ unsigned long flags; -+ -+ BUG_ON(host->card_busy == NULL); -+ -+ spin_lock_irqsave(&host->lock, flags); -+ host->card_busy = NULL; -+ spin_unlock_irqrestore(&host->lock, flags); -+ -+ wake_up(&host->wq); -+} -+ -+EXPORT_SYMBOL(mmc_release_host); -+ -+static void mmc_deselect_cards(struct mmc_host *host) -+{ -+ struct mmc_command cmd; -+ -+ /* -+ * Ensure that no card is selected. -+ */ -+ if (host->card_selected) { -+ host->card_selected = NULL; -+ -+ cmd.opcode = MMC_SELECT_CARD; -+ cmd.arg = 0; -+ cmd.flags = MMC_RSP_NONE; -+ -+ mmc_wait_for_cmd(host, &cmd, 0); -+ } -+} -+ -+ -+static inline void mmc_delay(unsigned int ms) -+{ -+ if (ms < HZ / 1000) { -+ yield(); -+ mdelay(ms); -+ } else { -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(ms * HZ / 1000); -+ } -+} -+ -+static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) -+{ -+ int bit; -+ -+ /* -+ * Mask off any voltages we don't support -+ */ -+ ocr &= host->ocr_avail; -+ -+ /* -+ * Select the lowest voltage -+ */ -+ bit = ffs(ocr); -+ if (bit) { -+ bit -= 1; -+ -+ ocr = 1 << bit; -+ -+ host->ios.vdd = mmc_ocr_bit_to_vdd[bit]; -+ host->ops->set_ios(host, &host->ios); -+ } else { -+ ocr = 0; -+ } -+ -+ return ocr; -+} -+ -+static void mmc_decode_cid(struct mmc_cid *cid, u32 *resp) -+{ -+ memset(cid, 0, sizeof(struct mmc_cid)); -+ -+ cid->manfid = resp[0] >> 8; -+ cid->prod_name[0] = resp[0]; -+ cid->prod_name[1] = resp[1] >> 24; -+ cid->prod_name[2] = resp[1] >> 16; -+ cid->prod_name[3] = resp[1] >> 8; -+ cid->prod_name[4] = resp[1]; -+ cid->prod_name[5] = resp[2] >> 24; -+ cid->prod_name[6] = resp[2] >> 16; -+ cid->prod_name[7] = '\0'; -+ cid->hwrev = (resp[2] >> 12) & 15; -+ cid->fwrev = (resp[2] >> 8) & 15; -+ cid->serial = (resp[2] & 255) << 16 | (resp[3] >> 16); -+ cid->month = (resp[3] >> 12) & 15; -+ cid->year = (resp[3] >> 8) & 15; -+} -+ -+static void mmc_decode_csd(struct mmc_csd *csd, u32 *resp) -+{ -+ unsigned int e, m; -+ -+ csd->mmc_prot = (resp[0] >> 26) & 15; -+ m = (resp[0] >> 19) & 15; -+ e = (resp[0] >> 16) & 7; -+ csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; -+ csd->tacc_clks = ((resp[0] >> 8) & 255) * 100; -+ -+ m = (resp[0] >> 3) & 15; -+ e = resp[0] & 7; -+ csd->max_dtr = tran_exp[e] * tran_mant[m]; -+ csd->cmdclass = (resp[1] >> 20) & 0xfff; -+ -+ e = (resp[2] >> 15) & 7; -+ m = (resp[1] << 2 | resp[2] >> 30) & 0x3fff; -+ csd->capacity = (1 + m) << (e + 2); -+ -+ csd->read_blkbits = (resp[1] >> 16) & 15; -+} -+ -+/* -+ * Locate a MMC card on this MMC host given a CID. -+ */ -+static struct mmc_card * -+mmc_find_card(struct mmc_host *host, struct mmc_cid *cid) -+{ -+ struct mmc_card *card; -+ -+ list_for_each_entry(card, &host->cards, node) { -+ if (memcmp(&card->cid, cid, sizeof(struct mmc_cid)) == 0) -+ return card; -+ } -+ return NULL; -+} -+ -+/* -+ * Allocate a new MMC card, and assign a unique RCA. -+ */ -+static struct mmc_card * -+mmc_alloc_card(struct mmc_host *host, struct mmc_cid *cid, unsigned int *frca) -+{ -+ struct mmc_card *card, *c; -+ unsigned int rca = *frca; -+ -+ card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL); -+ if (!card) -+ return ERR_PTR(-ENOMEM); -+ -+ mmc_init_card(card, host); -+ memcpy(&card->cid, cid, sizeof(struct mmc_cid)); -+ -+ again: -+ list_for_each_entry(c, &host->cards, node) -+ if (c->rca == rca) { -+ rca++; -+ goto again; -+ } -+ -+ card->rca = rca; -+ -+ *frca = rca; -+ -+ return card; -+} -+ -+/* -+ * Apply power to the MMC stack. -+ */ -+static void mmc_power_up(struct mmc_host *host) -+{ -+ struct mmc_command cmd; -+ int bit = fls(host->ocr_avail) - 1; -+ -+ host->ios.vdd = mmc_ocr_bit_to_vdd[bit]; -+ host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; -+ host->ios.power_mode = MMC_POWER_UP; -+ host->ops->set_ios(host, &host->ios); -+ -+ mmc_delay(1); -+ -+ host->ios.clock = host->f_min; -+ host->ios.power_mode = MMC_POWER_ON; -+ host->ops->set_ios(host, &host->ios); -+ -+ mmc_delay(2); -+ -+ cmd.opcode = MMC_GO_IDLE_STATE; -+ cmd.arg = 0; -+ cmd.flags = MMC_RSP_NONE; -+ -+ mmc_wait_for_cmd(host, &cmd, 0); -+} -+ -+static void mmc_power_off(struct mmc_host *host) -+{ -+ host->ios.clock = 0; -+ host->ios.vdd = 0; -+ host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; -+ host->ios.power_mode = MMC_POWER_OFF; -+ host->ops->set_ios(host, &host->ios); -+} -+ -+static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) -+{ -+ struct mmc_command cmd; -+ int i, err = 0; -+ -+ cmd.opcode = MMC_SEND_OP_COND; -+ cmd.arg = ocr; -+ cmd.flags = MMC_RSP_SHORT; -+ -+ for (i = 100; i; i--) { -+ err = mmc_wait_for_cmd(host, &cmd, 0); -+ if (err != MMC_ERR_NONE) -+ break; -+ -+ if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0) -+ break; -+ -+ err = MMC_ERR_TIMEOUT; -+ } -+ -+ if (rocr) -+ *rocr = cmd.resp[0]; -+ -+ return err; -+} -+ -+/* -+ * Discover cards by requesting their CID. If this command -+ * times out, it is not an error; there are no further cards -+ * to be discovered. Add new cards to the list. -+ * -+ * Create a mmc_card entry for each discovered card, assigning -+ * it an RCA, and save the CID. -+ */ -+static void mmc_discover_cards(struct mmc_host *host) -+{ -+ struct mmc_card *card; -+ unsigned int first_rca = 1, err; -+ -+ while (1) { -+ struct mmc_command cmd; -+ struct mmc_cid cid; -+ -+ /* -+ * Read CID -+ */ -+ cmd.opcode = MMC_ALL_SEND_CID; -+ cmd.arg = 0; -+ cmd.flags = MMC_RSP_LONG | MMC_RSP_CRC; -+ -+ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); -+ if (err == MMC_ERR_TIMEOUT) { -+ err = MMC_ERR_NONE; -+ break; -+ } -+ if (err != MMC_ERR_NONE) { -+ printk(KERN_ERR "MMC: mmc%d error requesting CID: %d\n", -+ host->host_num, err); -+ break; -+ } -+ -+ mmc_decode_cid(&cid, cmd.resp); -+ -+ card = mmc_find_card(host, &cid); -+ if (!card) { -+ card = mmc_alloc_card(host, &cid, &first_rca); -+ if (IS_ERR(card)) { -+ err = PTR_ERR(card); -+ break; -+ } -+ list_add(&card->node, &host->cards); -+ } -+ -+ card->state &= ~MMC_STATE_DEAD; -+ -+ cmd.opcode = MMC_SET_RELATIVE_ADDR; -+ cmd.arg = card->rca << 16; -+ cmd.flags = MMC_RSP_SHORT | MMC_RSP_CRC; -+ -+ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); -+ if (err != MMC_ERR_NONE) -+ card->state |= MMC_STATE_DEAD; -+ } -+} -+ -+static void mmc_read_csds(struct mmc_host *host) -+{ -+ struct mmc_card *card; -+ -+ list_for_each_entry(card, &host->cards, node) { -+ struct mmc_command cmd; -+ int err; -+ -+ if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT)) -+ continue; -+ -+ cmd.opcode = MMC_SEND_CSD; -+ cmd.arg = card->rca << 16; -+ cmd.flags = MMC_RSP_LONG | MMC_RSP_CRC; -+ -+ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); -+ if (err != MMC_ERR_NONE) { -+ card->state |= MMC_STATE_DEAD; -+ continue; -+ } -+ -+ mmc_decode_csd(&card->csd, cmd.resp); -+ } -+} -+ -+static unsigned int mmc_calculate_clock(struct mmc_host *host) -+{ -+ struct mmc_card *card; -+ unsigned int max_dtr = host->f_max; -+ -+ list_for_each_entry(card, &host->cards, node) -+ 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); -+ -+ return max_dtr; -+} -+ -+/* -+ * Check whether cards we already know about are still present. -+ * We do this by requesting status, and checking whether a card -+ * responds. -+ * -+ * A request for status does not cause a state change in data -+ * transfer mode. -+ */ -+static void mmc_check_cards(struct mmc_host *host) -+{ -+ struct list_head *l, *n; -+ -+ mmc_deselect_cards(host); -+ -+ list_for_each_safe(l, n, &host->cards) { -+ struct mmc_card *card = mmc_list_to_card(l); -+ struct mmc_command cmd; -+ int err; -+ -+ cmd.opcode = MMC_SEND_STATUS; -+ cmd.arg = card->rca << 16; -+ cmd.flags = MMC_RSP_LONG | MMC_RSP_CRC; -+ -+ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); -+ if (err == MMC_ERR_NONE) -+ continue; -+ -+ /* -+ * Ok, we believe this card has been removed. -+ */ -+ card->state |= MMC_STATE_DEAD; -+ } -+} -+ -+static void mmc_setup(struct mmc_host *host) -+{ -+ if (host->ios.power_mode != MMC_POWER_ON) { -+ int err; -+ u32 ocr; -+ -+ mmc_power_up(host); -+ -+ err = mmc_send_op_cond(host, 0, &ocr); -+ if (err != MMC_ERR_NONE) -+ return; -+ -+ host->ocr = mmc_select_voltage(host, ocr); -+ } else { -+ host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; -+ host->ios.clock = host->f_min; -+ host->ops->set_ios(host, &host->ios); -+ -+ /* -+ * We should remember the OCR mask from the existing -+ * cards, and detect the new cards OCR mask, combine -+ * the two and re-select the VDD. However, if we do -+ * change VDD, we should do an idle, and then do a -+ * full re-initialisation. We would need to notify -+ * drivers so that they can re-setup the cards as -+ * well, while keeping their queues at bay. -+ * -+ * For the moment, we take the easy way out - if the -+ * new cards don't like our currently selected VDD, -+ * they drop off the bus. -+ */ -+ } -+ -+ if (host->ocr == 0) -+ return; -+ -+ /* -+ * Send the selected OCR multiple times... until the cards -+ * all get the idea that they should be ready for CMD2. -+ * (My SanDisk card seems to need this.) -+ */ -+ mmc_send_op_cond(host, host->ocr, NULL); -+ -+ mmc_discover_cards(host); -+ -+ /* -+ * Ok, now switch to push-pull mode. -+ */ -+ host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; -+ host->ops->set_ios(host, &host->ios); -+ -+ mmc_read_csds(host); -+} -+ -+ -+/** -+ * mmc_detect_change - process change of state on a MMC socket -+ * @host: host which changed state. -+ * -+ * All we know is that card(s) have been inserted or removed -+ * from the socket(s). We don't know which socket or cards. -+ */ -+void mmc_detect_change(struct mmc_host *host) -+{ -+ struct list_head *l, *n; -+ -+ mmc_claim_host(host); -+ -+ if (host->ios.power_mode == MMC_POWER_ON) -+ mmc_check_cards(host); -+ -+ mmc_setup(host); -+ -+ if (!list_empty(&host->cards)) { -+ /* -+ * (Re-)calculate the fastest clock rate which the -+ * attached cards and the host support. -+ */ -+ host->ios.clock = mmc_calculate_clock(host); -+ host->ops->set_ios(host, &host->ios); -+ } -+ -+ mmc_release_host(host); -+ -+ list_for_each_safe(l, n, &host->cards) { -+ struct mmc_card *card = mmc_list_to_card(l); -+ -+ /* -+ * If this is a new and good card, register it. -+ */ -+ if (!mmc_card_present(card) && !mmc_card_dead(card)) { -+ if (mmc_register_card(card)) -+ card->state |= MMC_STATE_DEAD; -+ else -+ card->state |= MMC_STATE_PRESENT; -+ } -+ -+ /* -+ * If this card is dead, destroy it. -+ */ -+ if (mmc_card_dead(card)) { -+ list_del(&card->node); -+ mmc_remove_card(card); -+ } -+ } -+ -+ /* -+ * If we discover that there are no cards on the -+ * bus, turn off the clock and power down. -+ */ -+ if (list_empty(&host->cards)) -+ mmc_power_off(host); -+} -+ -+EXPORT_SYMBOL(mmc_detect_change); -+ -+ -+/** -+ * mmc_init_host - initialise the per-host structure. -+ * @host: mmc host -+ * -+ * Initialise the per-host structure. -+ */ -+int mmc_init_host(struct mmc_host *host) -+{ -+ static unsigned int host_num; -+ -+ memset(host, 0, sizeof(struct mmc_host)); -+ -+ host->host_num = host_num++; -+ -+ spin_lock_init(&host->lock); -+ init_waitqueue_head(&host->wq); -+ INIT_LIST_HEAD(&host->cards); -+ -+ return 0; -+} -+ -+EXPORT_SYMBOL(mmc_init_host); -+ -+/** -+ * mmc_add_host - initialise host hardware -+ * @host: mmc host -+ */ -+int mmc_add_host(struct mmc_host *host) -+{ -+ mmc_power_off(host); -+ mmc_detect_change(host); -+ -+ return 0; -+} -+ -+EXPORT_SYMBOL(mmc_add_host); -+ -+/** -+ * mmc_remove_host - remove host hardware -+ * @host: mmc host -+ * -+ * Unregister and remove all cards associated with this host, -+ * and power down the MMC bus. -+ */ -+void mmc_remove_host(struct mmc_host *host) -+{ -+ struct list_head *l, *n; -+ -+ list_for_each_safe(l, n, &host->cards) { -+ struct mmc_card *card = mmc_list_to_card(l); -+ -+ mmc_remove_card(card); -+ } -+ -+ mmc_power_off(host); -+} -+ -+EXPORT_SYMBOL(mmc_remove_host); -+ -+#ifdef CONFIG_PM -+ -+/** -+ * mmc_suspend_host - suspend a host -+ * @host: mmc host -+ * @state: suspend mode (PM_SUSPEND_xxx) -+ */ -+int mmc_suspend_host(struct mmc_host *host, u32 state) -+{ -+ mmc_claim_host(host); -+ mmc_deselect_cards(host); -+ mmc_power_off(host); -+ mmc_release_host(host); -+ -+ return 0; -+} -+ -+/** -+ * mmc_resume_host - resume a previously suspended host -+ * @host: mmc host -+ */ -+int mmc_resume_host(struct mmc_host *host) -+{ -+ mmc_detect_change(host); -+ -+ return 0; -+} -+ -+ -+#else /* CONFIG_PM is not set */ -+ -+int mmc_suspend_host(struct mmc_host *host, u32 state) { return 0; } -+int mmc_resume_host(struct mmc_host *host) { return 0; } -+ -+#endif -+ -+EXPORT_SYMBOL(mmc_suspend_host); -+EXPORT_SYMBOL(mmc_resume_host); -+ -+MODULE_LICENSE("GPL"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/media/mmc/Makefile 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,21 @@ -+# -+# Makefile for the kernel mmc device drivers. -+# -+ -+# -+# Core -+# -+obj-$(CONFIG_MMC) += mmc_core.o -+ -+# -+# Media drivers -+# -+obj-$(CONFIG_MMC_BLOCK) += mmc_block.o -+ -+# -+# Host drivers -+# -+obj-$(CONFIG_MMC_ARMMMCI) += mmci.o -+obj-$(CONFIG_MMC_PXA) += pxamci.o -+ -+mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o ---- linux-2.6.5/drivers/media/Makefile~heh 2004-04-03 22:38:15.000000000 -0500 -+++ linux-2.6.5/drivers/media/Makefile 2004-04-30 20:57:36.000000000 -0400 -@@ -3,3 +3,6 @@ - # - - obj-y := video/ radio/ dvb/ common/ -+ -+obj-$(CONFIG_MMC) += mmc/ -+ ---- linux-2.6.5/drivers/serial/Kconfig~heh 2004-04-03 22:38:15.000000000 -0500 -+++ linux-2.6.5/drivers/serial/Kconfig 2004-04-30 20:57:36.000000000 -0400 -@@ -315,6 +315,29 @@ - your boot loader (lilo or loadlin) about how to pass options to the - kernel at boot time.) - -+config SERIAL_PXA -+ bool "PXA serial port support" -+ depends on ARM && ARCH_PXA -+ select SERIAL_CORE -+ help -+ If you have a machine based on an Intel XScale PXA2xx CPU you -+ can enable its onboard serial ports by enabling this option. -+ -+config SERIAL_PXA_CONSOLE -+ bool "Console on PXA serial port" -+ depends on SERIAL_PXA -+ select SERIAL_CORE_CONSOLE -+ help -+ If you have enabled the serial port on the Intel XScale PXA -+ CPU you can make it the console by answering Y to this option. -+ -+ Even if you say Y here, the currently visible virtual console -+ (/dev/tty0) will still be used as the system console by default, but -+ you can alter that using a kernel command line option such as -+ "console=ttySA0". (Try "man bootparam" or see the documentation of -+ your boot loader (lilo or loadlin) about how to pass options to the -+ kernel at boot time.) -+ - config SERIAL_SA1100 - bool "SA1100 serial port support" - depends on ARM && ARCH_SA1100 ---- linux-2.6.5/drivers/serial/pxa.c~heh 2004-04-03 22:38:16.000000000 -0500 -+++ linux-2.6.5/drivers/serial/pxa.c 2004-04-30 20:57:36.000000000 -0400 -@@ -294,7 +294,6 @@ - unsigned char status; - unsigned int ret; - --return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; - spin_lock_irqsave(&up->port.lock, flags); - status = serial_in(up, UART_MSR); - spin_unlock_irqrestore(&up->port.lock, flags); -@@ -800,6 +799,21 @@ - .ops = &serial_pxa_pops, - .line = 2, - }, -+ }, { /* HWUART */ -+ .name = "HWUART", -+ .cken = CKEN4_HWUART, -+ .port = { -+ .type = PORT_PXA, -+ .iotype = SERIAL_IO_MEM, -+ .membase = (void *)&HWUART, -+ .mapbase = __PREG(HWUART), -+ .irq = IRQ_HWUART, -+ .uartclk = 921600 * 16, -+ .fifosize = 64, -+ .flags = ASYNC_SKIP_TEST, -+ .ops = &serial_pxa_pops, -+ .line = 3, -+ }, - } - }; - ---- linux-2.6.5/drivers/serial/sa1100.c~heh 2004-04-03 22:36:24.000000000 -0500 -+++ linux-2.6.5/drivers/serial/sa1100.c 2004-04-30 20:57:36.000000000 -0400 -@@ -448,6 +448,15 @@ - unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; - - /* -+ * If we don't support modem control lines, don't allow -+ * these to be set. -+ */ -+ if (0) { -+ termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR); -+ termios->c_cflag |= CLOCAL; -+ } -+ -+ /* - * We only support CS7 and CS8. - */ - while ((termios->c_cflag & CSIZE) != CS7 && -@@ -894,6 +903,7 @@ - if (sa1100_ports[i].port.mapbase != res->start) - continue; - -+ sa1100_ports[i].port.dev = _dev; - uart_add_one_port(&sa1100_reg, &sa1100_ports[i].port); - dev_set_drvdata(_dev, &sa1100_ports[i]); - break; ---- linux-2.6.5/drivers/mtd/mtd_blkdevs.c~heh 2004-04-03 22:36:14.000000000 -0500 -+++ linux-2.6.5/drivers/mtd/mtd_blkdevs.c 2004-04-30 20:57:36.000000000 -0400 -@@ -81,7 +81,7 @@ - struct request_queue *rq = tr->blkcore_priv->rq; - - /* we might get involved when memory gets low, so use PF_MEMALLOC */ -- current->flags |= PF_MEMALLOC; -+ current->flags |= PF_MEMALLOC|PF_IOTHREAD; - - daemonize("%sd", tr->name); - ---- linux-2.6.5/drivers/mtd/devices/doc1000.c~heh 2004-04-03 22:37:36.000000000 -0500 -+++ linux-2.6.5/drivers/mtd/devices/doc1000.c 2004-04-30 20:57:36.000000000 -0400 -@@ -1,6 +1,6 @@ - /*====================================================================== - -- $Id$ -+ $Id$ - - ======================================================================*/ - -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -482,7 +483,7 @@ - else - priv->devstat[erase->dev] = erase->state = MTD_ERASE_PENDING; - } -- else if (erase->time + erase_timeout < jiffies) -+ else if (time_after(jiffies, erase->time + erase_timeout)) - { - printk("Flash erase timed out. The world is broken.\n"); - ---- linux-2.6.5/drivers/mtd/mtdconcat.c~heh 2004-04-03 22:37:37.000000000 -0500 -+++ linux-2.6.5/drivers/mtd/mtdconcat.c 2004-04-30 20:57:36.000000000 -0400 -@@ -7,7 +7,7 @@ - * - * This code is GPL - * -- * $Id$ -+ * $Id$ - */ - - #include -@@ -26,7 +26,7 @@ - */ - struct mtd_concat { - struct mtd_info mtd; -- int num_subdev; -+ int num_subdev; - struct mtd_info **subdev; - }; - -@@ -37,21 +37,20 @@ - #define SIZEOF_STRUCT_MTD_CONCAT(num_subdev) \ - ((sizeof(struct mtd_concat) + (num_subdev) * sizeof(struct mtd_info *))) - -- - /* - * Given a pointer to the MTD object in the mtd_concat structure, - * we can retrieve the pointer to that structure with this macro. - */ - #define CONCAT(x) ((struct mtd_concat *)(x)) - -- - /* - * MTD methods which look up the relevant subdevice, translate the - * effective address and pass through to the subdevice. - */ - --static int concat_read (struct mtd_info *mtd, loff_t from, size_t len, -- size_t *retlen, u_char *buf) -+static int -+concat_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t * retlen, u_char * buf) - { - struct mtd_concat *concat = CONCAT(mtd); - int err = -EINVAL; -@@ -59,43 +58,43 @@ - - *retlen = 0; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size, retsize; - -- if (from >= subdev->size) -- { /* Not destined for this subdev */ -- size = 0; -+ if (from >= subdev->size) { -+ /* Not destined for this subdev */ -+ size = 0; - from -= subdev->size; -+ continue; - } -+ if (from + len > subdev->size) -+ /* First part goes into this subdev */ -+ size = subdev->size - from; - else -- { -- if (from + len > subdev->size) -- size = subdev->size - from; /* First part goes into this subdev */ -- else -- size = len; /* Entire transaction goes into this subdev */ -+ /* Entire transaction goes into this subdev */ -+ size = len; - -- err = subdev->read(subdev, from, size, &retsize, buf); -+ err = subdev->read(subdev, from, size, &retsize, buf); - -- if(err) -- break; -+ if (err) -+ break; - -- *retlen += retsize; -- len -= size; -- if(len == 0) -- break; -+ *retlen += retsize; -+ len -= size; -+ if (len == 0) -+ break; - -- err = -EINVAL; -- buf += size; -- from = 0; -- } -+ err = -EINVAL; -+ buf += size; -+ from = 0; - } - return err; - } - --static int concat_write (struct mtd_info *mtd, loff_t to, size_t len, -- size_t *retlen, const u_char *buf) -+static int -+concat_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t * retlen, const u_char * buf) - { - struct mtd_concat *concat = CONCAT(mtd); - int err = -EINVAL; -@@ -106,46 +105,44 @@ - - *retlen = 0; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size, retsize; - -- if (to >= subdev->size) -- { -- size = 0; -+ if (to >= subdev->size) { -+ size = 0; - to -= subdev->size; -+ continue; - } -+ if (to + len > subdev->size) -+ size = subdev->size - to; - else -- { -- if (to + len > subdev->size) -- size = subdev->size - to; -- else -- size = len; -+ size = len; - -- if (!(subdev->flags & MTD_WRITEABLE)) -- err = -EROFS; -- else -- err = subdev->write(subdev, to, size, &retsize, buf); -+ if (!(subdev->flags & MTD_WRITEABLE)) -+ err = -EROFS; -+ else -+ err = subdev->write(subdev, to, size, &retsize, buf); - -- if(err) -- break; -+ if (err) -+ break; - -- *retlen += retsize; -- len -= size; -- if(len == 0) -- break; -+ *retlen += retsize; -+ len -= size; -+ if (len == 0) -+ break; - -- err = -EINVAL; -- buf += size; -- to = 0; -- } -+ err = -EINVAL; -+ buf += size; -+ to = 0; - } - return err; - } - --static int concat_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, -- size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel) -+static int -+concat_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t * retlen, u_char * buf, u_char * eccbuf, -+ struct nand_oobinfo *oobsel) - { - struct mtd_concat *concat = CONCAT(mtd); - int err = -EINVAL; -@@ -153,53 +150,56 @@ - - *retlen = 0; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size, retsize; -- -- if (from >= subdev->size) -- { /* Not destined for this subdev */ -- size = 0; -+ -+ if (from >= subdev->size) { -+ /* Not destined for this subdev */ -+ size = 0; - from -= subdev->size; -+ continue; - } -+ -+ if (from + len > subdev->size) -+ /* First part goes into this subdev */ -+ size = subdev->size - from; - else -- { -- if (from + len > subdev->size) -- size = subdev->size - from; /* First part goes into this subdev */ -- else -- size = len; /* Entire transaction goes into this subdev */ -- -- if (subdev->read_ecc) -- err = subdev->read_ecc(subdev, from, size, &retsize, buf, eccbuf, oobsel); -- else -- err = -EINVAL; -+ /* Entire transaction goes into this subdev */ -+ size = len; - -- if(err) -- break; -+ if (subdev->read_ecc) -+ err = subdev->read_ecc(subdev, from, size, -+ &retsize, buf, eccbuf, oobsel); -+ else -+ err = -EINVAL; - -- *retlen += retsize; -- len -= size; -- if(len == 0) -- break; -+ if (err) -+ break; - -- err = -EINVAL; -- buf += size; -- if (eccbuf) -- { -- eccbuf += subdev->oobsize; -- /* in nand.c at least, eccbufs are tagged with 2 (int)eccstatus', -- we must account for these */ -- eccbuf += 2 * (sizeof(int)); -- } -- from = 0; -+ *retlen += retsize; -+ len -= size; -+ if (len == 0) -+ break; -+ -+ err = -EINVAL; -+ buf += size; -+ if (eccbuf) { -+ eccbuf += subdev->oobsize; -+ /* in nand.c at least, eccbufs are -+ tagged with 2 (int)eccstatus'; we -+ must account for these */ -+ eccbuf += 2 * (sizeof (int)); - } -+ from = 0; - } - return err; - } - --static int concat_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, -- size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel) -+static int -+concat_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t * retlen, const u_char * buf, u_char * eccbuf, -+ struct nand_oobinfo *oobsel) - { - struct mtd_concat *concat = CONCAT(mtd); - int err = -EINVAL; -@@ -210,50 +210,48 @@ - - *retlen = 0; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size, retsize; -- -- if (to >= subdev->size) -- { -- size = 0; -+ -+ if (to >= subdev->size) { -+ size = 0; - to -= subdev->size; -+ continue; - } -+ if (to + len > subdev->size) -+ size = subdev->size - to; - else -- { -- if (to + len > subdev->size) -- size = subdev->size - to; -- else -- size = len; -+ size = len; - -- if (!(subdev->flags & MTD_WRITEABLE)) -- err = -EROFS; -- else if (subdev->write_ecc) -- err = subdev->write_ecc(subdev, to, size, &retsize, buf, eccbuf, oobsel); -- else -- err = -EINVAL; -+ if (!(subdev->flags & MTD_WRITEABLE)) -+ err = -EROFS; -+ else if (subdev->write_ecc) -+ err = subdev->write_ecc(subdev, to, size, -+ &retsize, buf, eccbuf, oobsel); -+ else -+ err = -EINVAL; - -- if(err) -- break; -+ if (err) -+ break; - -- *retlen += retsize; -- len -= size; -- if(len == 0) -- break; -+ *retlen += retsize; -+ len -= size; -+ if (len == 0) -+ break; - -- err = -EINVAL; -- buf += size; -- if (eccbuf) -- eccbuf += subdev->oobsize; -- to = 0; -- } -+ err = -EINVAL; -+ buf += size; -+ if (eccbuf) -+ eccbuf += subdev->oobsize; -+ to = 0; - } - return err; - } - --static int concat_read_oob (struct mtd_info *mtd, loff_t from, size_t len, -- size_t *retlen, u_char *buf) -+static int -+concat_read_oob(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t * retlen, u_char * buf) - { - struct mtd_concat *concat = CONCAT(mtd); - int err = -EINVAL; -@@ -261,46 +259,47 @@ - - *retlen = 0; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size, retsize; -- -- if (from >= subdev->size) -- { /* Not destined for this subdev */ -- size = 0; -+ -+ if (from >= subdev->size) { -+ /* Not destined for this subdev */ -+ size = 0; - from -= subdev->size; -+ continue; - } -+ if (from + len > subdev->size) -+ /* First part goes into this subdev */ -+ size = subdev->size - from; - else -- { -- if (from + len > subdev->size) -- size = subdev->size - from; /* First part goes into this subdev */ -- else -- size = len; /* Entire transaction goes into this subdev */ -- -- if (subdev->read_oob) -- err = subdev->read_oob(subdev, from, size, &retsize, buf); -- else -- err = -EINVAL; -+ /* Entire transaction goes into this subdev */ -+ size = len; - -- if(err) -- break; -+ if (subdev->read_oob) -+ err = subdev->read_oob(subdev, from, size, -+ &retsize, buf); -+ else -+ err = -EINVAL; - -- *retlen += retsize; -- len -= size; -- if(len == 0) -- break; -+ if (err) -+ break; - -- err = -EINVAL; -- buf += size; -- from = 0; -- } -+ *retlen += retsize; -+ len -= size; -+ if (len == 0) -+ break; -+ -+ err = -EINVAL; -+ buf += size; -+ from = 0; - } - return err; - } - --static int concat_write_oob (struct mtd_info *mtd, loff_t to, size_t len, -- size_t *retlen, const u_char *buf) -+static int -+concat_write_oob(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t * retlen, const u_char * buf) - { - struct mtd_concat *concat = CONCAT(mtd); - int err = -EINVAL; -@@ -311,50 +310,46 @@ - - *retlen = 0; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size, retsize; -- -- if (to >= subdev->size) -- { -- size = 0; -+ -+ if (to >= subdev->size) { -+ size = 0; - to -= subdev->size; -+ continue; - } -+ if (to + len > subdev->size) -+ size = subdev->size - to; - else -- { -- if (to + len > subdev->size) -- size = subdev->size - to; -- else -- size = len; -+ size = len; - -- if (!(subdev->flags & MTD_WRITEABLE)) -- err = -EROFS; -- else if (subdev->write_oob) -- err = subdev->write_oob(subdev, to, size, &retsize, buf); -- else -- err = -EINVAL; -+ if (!(subdev->flags & MTD_WRITEABLE)) -+ err = -EROFS; -+ else if (subdev->write_oob) -+ err = subdev->write_oob(subdev, to, size, &retsize, -+ buf); -+ else -+ err = -EINVAL; - -- if(err) -- break; -+ if (err) -+ break; - -- *retlen += retsize; -- len -= size; -- if(len == 0) -- break; -+ *retlen += retsize; -+ len -= size; -+ if (len == 0) -+ break; - -- err = -EINVAL; -- buf += size; -- to = 0; -- } -+ err = -EINVAL; -+ buf += size; -+ to = 0; - } - return err; - } - -- --static void concat_erase_callback (struct erase_info *instr) -+static void concat_erase_callback(struct erase_info *instr) - { -- wake_up((wait_queue_head_t *)instr->priv); -+ wake_up((wait_queue_head_t *) instr->priv); - } - - static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase) -@@ -370,18 +365,18 @@ - - erase->mtd = mtd; - erase->callback = concat_erase_callback; -- erase->priv = (unsigned long)&waitq; -- -+ erase->priv = (unsigned long) &waitq; -+ - /* - * FIXME: Allow INTERRUPTIBLE. Which means - * not having the wait_queue head on the stack. - */ - err = mtd->erase(mtd, erase); -- if (!err) -- { -+ if (!err) { - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&waitq, &wait); -- if (erase->state != MTD_ERASE_DONE && erase->state != MTD_ERASE_FAILED) -+ if (erase->state != MTD_ERASE_DONE -+ && erase->state != MTD_ERASE_FAILED) - schedule(); - remove_wait_queue(&waitq, &wait); - set_current_state(TASK_RUNNING); -@@ -391,7 +386,7 @@ - return err; - } - --static int concat_erase (struct mtd_info *mtd, struct erase_info *instr) -+static int concat_erase(struct mtd_info *mtd, struct erase_info *instr) - { - struct mtd_concat *concat = CONCAT(mtd); - struct mtd_info *subdev; -@@ -402,10 +397,10 @@ - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; - -- if(instr->addr > concat->mtd.size) -+ if (instr->addr > concat->mtd.size) - return -EINVAL; - -- if(instr->len + instr->addr > concat->mtd.size) -+ if (instr->len + instr->addr > concat->mtd.size) - return -EINVAL; - - /* -@@ -414,23 +409,22 @@ - * region info rather than looking at each particular sub-device - * in turn. - */ -- if (!concat->mtd.numeraseregions) -- { /* the easy case: device has uniform erase block size */ -- if(instr->addr & (concat->mtd.erasesize - 1)) -+ if (!concat->mtd.numeraseregions) { -+ /* the easy case: device has uniform erase block size */ -+ if (instr->addr & (concat->mtd.erasesize - 1)) - return -EINVAL; -- if(instr->len & (concat->mtd.erasesize - 1)) -+ if (instr->len & (concat->mtd.erasesize - 1)) - return -EINVAL; -- } -- else -- { /* device has variable erase size */ -- struct mtd_erase_region_info *erase_regions = concat->mtd.eraseregions; -+ } else { -+ /* device has variable erase size */ -+ struct mtd_erase_region_info *erase_regions = -+ concat->mtd.eraseregions; - - /* - * Find the erase region where the to-be-erased area begins: - */ -- for(i = 0; i < concat->mtd.numeraseregions && -- instr->addr >= erase_regions[i].offset; i++) -- ; -+ for (i = 0; i < concat->mtd.numeraseregions && -+ instr->addr >= erase_regions[i].offset; i++) ; - --i; - - /* -@@ -438,25 +432,26 @@ - * to-be-erased area begins. Verify that the starting - * offset is aligned to this region's erase size: - */ -- if (instr->addr & (erase_regions[i].erasesize-1)) -+ if (instr->addr & (erase_regions[i].erasesize - 1)) - return -EINVAL; - - /* - * now find the erase region where the to-be-erased area ends: - */ -- for(; i < concat->mtd.numeraseregions && -- (instr->addr + instr->len) >= erase_regions[i].offset ; ++i) -- ; -+ for (; i < concat->mtd.numeraseregions && -+ (instr->addr + instr->len) >= erase_regions[i].offset; -+ ++i) ; - --i; - /* - * check if the ending offset is aligned to this region's erase size - */ -- if ((instr->addr + instr->len) & (erase_regions[i].erasesize-1)) -+ if ((instr->addr + instr->len) & (erase_regions[i].erasesize - -+ 1)) - return -EINVAL; - } - - /* make a local copy of instr to avoid modifying the caller's struct */ -- erase = kmalloc(sizeof(struct erase_info),GFP_KERNEL); -+ erase = kmalloc(sizeof (struct erase_info), GFP_KERNEL); - - if (!erase) - return -ENOMEM; -@@ -468,39 +463,40 @@ - * find the subdevice where the to-be-erased area begins, adjust - * starting offset to be relative to the subdevice start - */ -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - subdev = concat->subdev[i]; -- if(subdev->size <= erase->addr) -+ if (subdev->size <= erase->addr) - erase->addr -= subdev->size; - else - break; -- } -- if(i >= concat->num_subdev) /* must never happen since size */ -- BUG(); /* limit has been verified above */ -+ } -+ -+ /* must never happen since size limit has been verified above */ -+ if (i >= concat->num_subdev) -+ BUG(); - - /* now do the erase: */ - err = 0; -- for(;length > 0; i++) /* loop for all subevices affected by this request */ -- { -- subdev = concat->subdev[i]; /* get current subdevice */ -+ for (; length > 0; i++) { -+ /* loop for all subdevices affected by this request */ -+ subdev = concat->subdev[i]; /* get current subdevice */ - - /* limit length to subdevice's size: */ -- if(erase->addr + length > subdev->size) -+ if (erase->addr + length > subdev->size) - erase->len = subdev->size - erase->addr; - else - erase->len = length; - -- if (!(subdev->flags & MTD_WRITEABLE)) -- { -+ if (!(subdev->flags & MTD_WRITEABLE)) { - err = -EROFS; - break; - } - length -= erase->len; -- if ((err = concat_dev_erase(subdev, erase))) -- { -- if(err == -EINVAL) /* sanity check: must never happen since */ -- BUG(); /* block alignment has been checked above */ -+ if ((err = concat_dev_erase(subdev, erase))) { -+ /* sanity check: should never happen since -+ * block alignment has been checked above */ -+ if (err == -EINVAL) -+ BUG(); - break; - } - /* -@@ -523,85 +519,79 @@ - return 0; - } - --static int concat_lock (struct mtd_info *mtd, loff_t ofs, size_t len) -+static int concat_lock(struct mtd_info *mtd, loff_t ofs, size_t len) - { - struct mtd_concat *concat = CONCAT(mtd); - int i, err = -EINVAL; - -- if ((len + ofs) > mtd->size) -+ if ((len + ofs) > mtd->size) - return -EINVAL; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size; - -- if (ofs >= subdev->size) -- { -- size = 0; -+ if (ofs >= subdev->size) { -+ size = 0; - ofs -= subdev->size; -+ continue; - } -+ if (ofs + len > subdev->size) -+ size = subdev->size - ofs; - else -- { -- if (ofs + len > subdev->size) -- size = subdev->size - ofs; -- else -- size = len; -+ size = len; - -- err = subdev->lock(subdev, ofs, size); -+ err = subdev->lock(subdev, ofs, size); - -- if(err) -- break; -+ if (err) -+ break; - -- len -= size; -- if(len == 0) -- break; -+ len -= size; -+ if (len == 0) -+ break; - -- err = -EINVAL; -- ofs = 0; -- } -+ err = -EINVAL; -+ ofs = 0; - } -+ - return err; - } - --static int concat_unlock (struct mtd_info *mtd, loff_t ofs, size_t len) -+static int concat_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) - { - struct mtd_concat *concat = CONCAT(mtd); - int i, err = 0; - -- if ((len + ofs) > mtd->size) -+ if ((len + ofs) > mtd->size) - return -EINVAL; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size; - -- if (ofs >= subdev->size) -- { -- size = 0; -+ if (ofs >= subdev->size) { -+ size = 0; - ofs -= subdev->size; -+ continue; - } -+ if (ofs + len > subdev->size) -+ size = subdev->size - ofs; - else -- { -- if (ofs + len > subdev->size) -- size = subdev->size - ofs; -- else -- size = len; -+ size = len; - -- err = subdev->unlock(subdev, ofs, size); -+ err = subdev->unlock(subdev, ofs, size); - -- if(err) -- break; -+ if (err) -+ break; - -- len -= size; -- if(len == 0) -- break; -+ len -= size; -+ if (len == 0) -+ break; - -- err = -EINVAL; -- ofs = 0; -- } -+ err = -EINVAL; -+ ofs = 0; - } -+ - return err; - } - -@@ -610,8 +600,7 @@ - struct mtd_concat *concat = CONCAT(mtd); - int i; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - subdev->sync(subdev); - } -@@ -622,10 +611,9 @@ - struct mtd_concat *concat = CONCAT(mtd); - int i, rc = 0; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; -- if((rc = subdev->suspend(subdev)) < 0) -+ if ((rc = subdev->suspend(subdev)) < 0) - return rc; - } - return rc; -@@ -636,8 +624,7 @@ - struct mtd_concat *concat = CONCAT(mtd); - int i; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - subdev->resume(subdev); - } -@@ -649,11 +636,10 @@ - * stored to *new_dev upon success. This function does _not_ - * register any devices: this is the caller's responsibility. - */ --struct mtd_info *mtd_concat_create( -- struct mtd_info *subdev[], /* subdevices to concatenate */ -- int num_devs, /* number of subdevices */ -- char *name) /* name for the new device */ --{ -+struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to concatenate */ -+ int num_devs, /* number of subdevices */ -+ char *name) -+{ /* name for the new device */ - int i; - size_t size; - struct mtd_concat *concat; -@@ -661,94 +647,103 @@ - int num_erase_region; - - printk(KERN_NOTICE "Concatenating MTD devices:\n"); -- for(i = 0; i < num_devs; i++) -+ for (i = 0; i < num_devs; i++) - printk(KERN_NOTICE "(%d): \"%s\"\n", i, subdev[i]->name); - printk(KERN_NOTICE "into device \"%s\"\n", name); - - /* allocate the device structure */ - size = SIZEOF_STRUCT_MTD_CONCAT(num_devs); -- concat = kmalloc (size, GFP_KERNEL); -- if(!concat) -- { -- printk ("memory allocation error while creating concatenated device \"%s\"\n", -- name); -- return NULL; -+ concat = kmalloc(size, GFP_KERNEL); -+ if (!concat) { -+ printk -+ ("memory allocation error while creating concatenated device \"%s\"\n", -+ name); -+ return NULL; - } - memset(concat, 0, size); -- concat->subdev = (struct mtd_info **)(concat + 1); -+ concat->subdev = (struct mtd_info **) (concat + 1); - - /* - * Set up the new "super" device's MTD object structure, check for - * incompatibilites between the subdevices. - */ -- concat->mtd.type = subdev[0]->type; -- concat->mtd.flags = subdev[0]->flags; -- concat->mtd.size = subdev[0]->size; -+ concat->mtd.type = subdev[0]->type; -+ concat->mtd.flags = subdev[0]->flags; -+ concat->mtd.size = subdev[0]->size; - concat->mtd.erasesize = subdev[0]->erasesize; -- concat->mtd.oobblock = subdev[0]->oobblock; -- concat->mtd.oobsize = subdev[0]->oobsize; -- concat->mtd.ecctype = subdev[0]->ecctype; -- concat->mtd.eccsize = subdev[0]->eccsize; -+ concat->mtd.oobblock = subdev[0]->oobblock; -+ concat->mtd.oobsize = subdev[0]->oobsize; -+ concat->mtd.ecctype = subdev[0]->ecctype; -+ concat->mtd.eccsize = subdev[0]->eccsize; -+ if (subdev[0]->read_ecc) -+ concat->mtd.read_ecc = concat_read_ecc; -+ if (subdev[0]->write_ecc) -+ concat->mtd.write_ecc = concat_write_ecc; -+ if (subdev[0]->read_oob) -+ concat->mtd.read_oob = concat_read_oob; -+ if (subdev[0]->write_oob) -+ concat->mtd.write_oob = concat_write_oob; - -- concat->subdev[0] = subdev[0]; -+ concat->subdev[0] = subdev[0]; - -- for(i = 1; i < num_devs; i++) -- { -- if(concat->mtd.type != subdev[i]->type) -- { -+ for (i = 1; i < num_devs; i++) { -+ if (concat->mtd.type != subdev[i]->type) { - kfree(concat); -- printk ("Incompatible device type on \"%s\"\n", subdev[i]->name); -+ printk("Incompatible device type on \"%s\"\n", -+ subdev[i]->name); - return NULL; - } -- if(concat->mtd.flags != subdev[i]->flags) -- { /* -- * Expect all flags except MTD_WRITEABLE to be equal on -- * all subdevices. -+ if (concat->mtd.flags != subdev[i]->flags) { -+ /* -+ * Expect all flags except MTD_WRITEABLE to be -+ * equal on all subdevices. - */ -- if((concat->mtd.flags ^ subdev[i]->flags) & ~MTD_WRITEABLE) -- { -+ if ((concat->mtd.flags ^ subdev[i]-> -+ flags) & ~MTD_WRITEABLE) { - kfree(concat); -- printk ("Incompatible device flags on \"%s\"\n", subdev[i]->name); -+ printk("Incompatible device flags on \"%s\"\n", -+ subdev[i]->name); - return NULL; -- } -- else /* if writeable attribute differs, make super device writeable */ -- concat->mtd.flags |= subdev[i]->flags & MTD_WRITEABLE; -+ } else -+ /* if writeable attribute differs, -+ make super device writeable */ -+ concat->mtd.flags |= -+ subdev[i]->flags & MTD_WRITEABLE; - } - concat->mtd.size += subdev[i]->size; -- if(concat->mtd.oobblock != subdev[i]->oobblock || -- concat->mtd.oobsize != subdev[i]->oobsize || -- concat->mtd.ecctype != subdev[i]->ecctype || -- concat->mtd.eccsize != subdev[i]->eccsize) -- { -+ if (concat->mtd.oobblock != subdev[i]->oobblock || -+ concat->mtd.oobsize != subdev[i]->oobsize || -+ concat->mtd.ecctype != subdev[i]->ecctype || -+ concat->mtd.eccsize != subdev[i]->eccsize || -+ !concat->mtd.read_ecc != !subdev[i]->read_ecc || -+ !concat->mtd.write_ecc != !subdev[i]->write_ecc || -+ !concat->mtd.read_oob != !subdev[i]->read_oob || -+ !concat->mtd.write_oob != !subdev[i]->write_oob) { - kfree(concat); -- printk ("Incompatible OOB or ECC data on \"%s\"\n", subdev[i]->name); -+ printk("Incompatible OOB or ECC data on \"%s\"\n", -+ subdev[i]->name); - return NULL; - } - concat->subdev[i] = subdev[i]; -- -+ - } - -- concat->num_subdev = num_devs; -- concat->mtd.name = name; -+ concat->num_subdev = num_devs; -+ concat->mtd.name = name; - - /* - * NOTE: for now, we do not provide any readv()/writev() methods - * because they are messy to implement and they are not - * used to a great extent anyway. - */ -- concat->mtd.erase = concat_erase; -- concat->mtd.read = concat_read; -- concat->mtd.write = concat_write; -- concat->mtd.read_ecc = concat_read_ecc; -- concat->mtd.write_ecc = concat_write_ecc; -- concat->mtd.read_oob = concat_read_oob; -- concat->mtd.write_oob = concat_write_oob; -- concat->mtd.sync = concat_sync; -- concat->mtd.lock = concat_lock; -- concat->mtd.unlock = concat_unlock; -- concat->mtd.suspend = concat_suspend; -- concat->mtd.resume = concat_resume; -- -+ concat->mtd.erase = concat_erase; -+ concat->mtd.read = concat_read; -+ concat->mtd.write = concat_write; -+ concat->mtd.sync = concat_sync; -+ concat->mtd.lock = concat_lock; -+ concat->mtd.unlock = concat_unlock; -+ concat->mtd.suspend = concat_suspend; -+ concat->mtd.resume = concat_resume; - - /* - * Combine the erase block size info of the subdevices: -@@ -758,44 +753,44 @@ - */ - max_erasesize = curr_erasesize = subdev[0]->erasesize; - num_erase_region = 1; -- for(i = 0; i < num_devs; i++) -- { -- if(subdev[i]->numeraseregions == 0) -- { /* current subdevice has uniform erase size */ -- if(subdev[i]->erasesize != curr_erasesize) -- { /* if it differs from the last subdevice's erase size, count it */ -+ for (i = 0; i < num_devs; i++) { -+ if (subdev[i]->numeraseregions == 0) { -+ /* current subdevice has uniform erase size */ -+ if (subdev[i]->erasesize != curr_erasesize) { -+ /* if it differs from the last subdevice's erase size, count it */ - ++num_erase_region; - curr_erasesize = subdev[i]->erasesize; -- if(curr_erasesize > max_erasesize) -+ if (curr_erasesize > max_erasesize) - max_erasesize = curr_erasesize; - } -- } -- else -- { /* current subdevice has variable erase size */ -+ } else { -+ /* current subdevice has variable erase size */ - int j; -- for(j = 0; j < subdev[i]->numeraseregions; j++) -- { /* walk the list of erase regions, count any changes */ -- if(subdev[i]->eraseregions[j].erasesize != curr_erasesize) -- { -+ for (j = 0; j < subdev[i]->numeraseregions; j++) { -+ -+ /* walk the list of erase regions, count any changes */ -+ if (subdev[i]->eraseregions[j].erasesize != -+ curr_erasesize) { - ++num_erase_region; -- curr_erasesize = subdev[i]->eraseregions[j].erasesize; -- if(curr_erasesize > max_erasesize) -+ curr_erasesize = -+ subdev[i]->eraseregions[j]. -+ erasesize; -+ if (curr_erasesize > max_erasesize) - max_erasesize = curr_erasesize; - } - } - } - } - -- if(num_erase_region == 1) -- { /* -+ if (num_erase_region == 1) { -+ /* - * All subdevices have the same uniform erase size. - * This is easy: - */ - concat->mtd.erasesize = curr_erasesize; - concat->mtd.numeraseregions = 0; -- } -- else -- { /* -+ } else { -+ /* - * erase block size varies across the subdevices: allocate - * space to store the data describing the variable erase regions - */ -@@ -804,13 +799,14 @@ - - concat->mtd.erasesize = max_erasesize; - concat->mtd.numeraseregions = num_erase_region; -- concat->mtd.eraseregions = erase_region_p = kmalloc ( -- num_erase_region * sizeof(struct mtd_erase_region_info), GFP_KERNEL); -- if(!erase_region_p) -- { -+ concat->mtd.eraseregions = erase_region_p = -+ kmalloc(num_erase_region * -+ sizeof (struct mtd_erase_region_info), GFP_KERNEL); -+ if (!erase_region_p) { - kfree(concat); -- printk ("memory allocation error while creating erase region list" -- " for device \"%s\"\n", name); -+ printk -+ ("memory allocation error while creating erase region list" -+ " for device \"%s\"\n", name); - return NULL; - } - -@@ -820,46 +816,53 @@ - */ - curr_erasesize = subdev[0]->erasesize; - begin = position = 0; -- for(i = 0; i < num_devs; i++) -- { -- if(subdev[i]->numeraseregions == 0) -- { /* current subdevice has uniform erase size */ -- if(subdev[i]->erasesize != curr_erasesize) -- { /* -+ for (i = 0; i < num_devs; i++) { -+ if (subdev[i]->numeraseregions == 0) { -+ /* current subdevice has uniform erase size */ -+ if (subdev[i]->erasesize != curr_erasesize) { -+ /* - * fill in an mtd_erase_region_info structure for the area - * we have walked so far: - */ -- erase_region_p->offset = begin; -- erase_region_p->erasesize = curr_erasesize; -- erase_region_p->numblocks = (position - begin) / curr_erasesize; -+ erase_region_p->offset = begin; -+ erase_region_p->erasesize = -+ curr_erasesize; -+ erase_region_p->numblocks = -+ (position - begin) / curr_erasesize; - begin = position; - - curr_erasesize = subdev[i]->erasesize; - ++erase_region_p; - } - position += subdev[i]->size; -- } -- else -- { /* current subdevice has variable erase size */ -+ } else { -+ /* current subdevice has variable erase size */ - int j; -- for(j = 0; j < subdev[i]->numeraseregions; j++) -- { /* walk the list of erase regions, count any changes */ -- if(subdev[i]->eraseregions[j].erasesize != curr_erasesize) -- { -- erase_region_p->offset = begin; -- erase_region_p->erasesize = curr_erasesize; -- erase_region_p->numblocks = (position - begin) / curr_erasesize; -+ for (j = 0; j < subdev[i]->numeraseregions; j++) { -+ /* walk the list of erase regions, count any changes */ -+ if (subdev[i]->eraseregions[j]. -+ erasesize != curr_erasesize) { -+ erase_region_p->offset = begin; -+ erase_region_p->erasesize = -+ curr_erasesize; -+ erase_region_p->numblocks = -+ (position - -+ begin) / curr_erasesize; - begin = position; - -- curr_erasesize = subdev[i]->eraseregions[j].erasesize; -+ curr_erasesize = -+ subdev[i]->eraseregions[j]. -+ erasesize; - ++erase_region_p; - } -- position += subdev[i]->eraseregions[j].numblocks * curr_erasesize; -+ position += -+ subdev[i]->eraseregions[j]. -+ numblocks * curr_erasesize; - } - } - } - /* Now write the final entry */ -- erase_region_p->offset = begin; -+ erase_region_p->offset = begin; - erase_region_p->erasesize = curr_erasesize; - erase_region_p->numblocks = (position - begin) / curr_erasesize; - } -@@ -874,16 +877,14 @@ - void mtd_concat_destroy(struct mtd_info *mtd) - { - struct mtd_concat *concat = CONCAT(mtd); -- if(concat->mtd.numeraseregions) -+ if (concat->mtd.numeraseregions) - kfree(concat->mtd.eraseregions); - kfree(concat); - } - -- - EXPORT_SYMBOL(mtd_concat_create); - EXPORT_SYMBOL(mtd_concat_destroy); - -- - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Robert Kaiser "); - MODULE_DESCRIPTION("Generic support for concatenating of MTD devices"); ---- linux-2.6.5/drivers/mtd/maps/Makefile~heh 2004-04-03 22:36:12.000000000 -0500 -+++ linux-2.6.5/drivers/mtd/maps/Makefile 2004-04-30 20:57:36.000000000 -0400 -@@ -17,12 +17,14 @@ - obj-$(CONFIG_MTD_ELAN_104NC) += elan-104nc.o - obj-$(CONFIG_MTD_EPXA10DB) += epxa10db-flash.o - obj-$(CONFIG_MTD_IQ80310) += iq80310.o -+obj-$(CONFIG_MTD_IQ80321) += iq80321.o - obj-$(CONFIG_MTD_L440GX) += l440gx.o - obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o - obj-$(CONFIG_MTD_ICH2ROM) += ich2rom.o - obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o - obj-$(CONFIG_MTD_LUBBOCK) += lubbock-flash.o - obj-$(CONFIG_MTD_MBX860) += mbx860.o -+obj-$(CONFIG_MTD_NORA) += nora.o - obj-$(CONFIG_MTD_CEIVA) += ceiva.o - obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o - obj-$(CONFIG_MTD_PHYSMAP) += physmap.o ---- linux-2.6.5/drivers/mtd/maps/sa1100-flash.c~heh 2004-04-03 22:36:51.000000000 -0500 -+++ linux-2.6.5/drivers/mtd/maps/sa1100-flash.c 2004-04-30 20:57:36.000000000 -0400 -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -887,6 +888,7 @@ - int width; - void *vbase; - void (*set_vpp)(struct map_info *, int); -+ char name[16]; - struct map_info *map; - struct mtd_info *mtd; - struct resource *res; -@@ -925,6 +927,8 @@ - } - - sa[i].map = maps + i; -+ sa[i].map->name = sa[i].name; -+ sprintf(sa[i].name, "sa1100-%d", i); - - sa[i].vbase = ioremap(sa[i].base, sa[i].size); - if (!sa[i].vbase) { -@@ -986,7 +990,7 @@ - */ - #ifdef CONFIG_MTD_CONCAT - *rmtd = mtd_concat_create(subdev, found, -- "sa1100 flash"); -+ "sa1100"); - if (*rmtd == NULL) - ret = -ENXIO; - #else -@@ -1044,13 +1048,9 @@ - * - Is the MSC setup for flash (no -> failure) - * - Probe for flash - */ -- --static struct map_info sa1100_probe_map __initdata = { -- .name = "SA1100-flash", --}; -- --static void __init sa1100_probe_one_cs(unsigned int msc, unsigned long phys) -+static void sa1100_probe_one_cs(unsigned int msc, unsigned long phys) - { -+ struct map_info map; - struct mtd_info *mtd; - - printk(KERN_INFO "* Probing 0x%08lx: MSC = 0x%04x %d bit ", -@@ -1066,19 +1066,23 @@ - return; - } - -- sa1100_probe_map.buswidth = msc & MSC_RBW ? 2 : 4; -- sa1100_probe_map.size = SZ_1M; -- sa1100_probe_map.phys = phys; -- sa1100_probe_map.virt = (unsigned long)ioremap(phys, SZ_1M); -- if (sa1100_probe_map.virt == 0) -+ memset(&map, 0, sizeof(map)); -+ -+ map.name = "Probe"; -+ map.buswidth = msc & MSC_RBW ? 2 : 4; -+ map.size = SZ_1M; -+ map.phys = NO_XIP; -+ map.virt = (unsigned long)ioremap(phys, SZ_1M); -+ if (map.virt == 0) - goto fail; -- simple_map_init(&sa1100_probe_map); -+ -+ simple_map_init(&map); - - /* Shame cfi_probe blurts out kernel messages... */ -- mtd = do_map_probe("cfi_probe", &sa1100_probe_map); -+ mtd = do_map_probe("cfi_probe", &map); - if (mtd) - map_destroy(mtd); -- iounmap((void *)sa1100_probe_map.virt); -+ iounmap((void *)map.virt); - - if (!mtd) - goto fail; -@@ -1090,7 +1094,7 @@ - printk("failed\n"); - } - --static void __init sa1100_probe_flash(void) -+static void sa1100_probe_flash(void) - { - printk(KERN_INFO "-- SA11xx Flash probe. Please report results.\n"); - sa1100_probe_one_cs(MSC0, SA1100_CS0_PHYS); -@@ -1321,10 +1325,9 @@ - kfree(parsed_parts); - } - --static struct mtd_info *mymtd; -- --static int __init sa1100_mtd_init(void) -+static int __init sa1100_mtd_probe(struct device *dev) - { -+ struct mtd_info *mtd; - int ret; - int nr; - -@@ -1332,21 +1335,74 @@ - if (nr < 0) - return nr; - -- ret = sa1100_setup_mtd(info, nr, &mymtd); -- if (ret == 0) -- sa1100_locate_partitions(mymtd); -+ ret = sa1100_setup_mtd(info, nr, &mtd); -+ if (ret == 0) { -+ sa1100_locate_partitions(mtd); -+ dev_set_drvdata(dev, mtd); -+ } - - return ret; - } - --static void __exit sa1100_mtd_cleanup(void) -+static int __exit sa1100_mtd_remove(struct device *dev) - { -- sa1100_destroy_mtd(info, mymtd); -+ struct mtd_info *mtd = dev_get_drvdata(dev); -+ sa1100_destroy_mtd(info, mtd); - sa1100_destroy_partitions(); -+ return 0; -+} -+ -+static int sa1100_mtd_suspend(struct device *dev, u32 level, u32 state) -+{ -+ struct mtd_info *mtd = dev_get_drvdata(dev); -+ if (level == SUSPEND_SAVE_STATE) -+ mtd->suspend(mtd); -+ return 0; -+} -+ -+static int sa1100_mtd_resume(struct device *dev, u32 level) -+{ -+ struct mtd_info *mtd = dev_get_drvdata(dev); -+ if (level == RESUME_RESTORE_STATE) -+ mtd->resume(mtd); -+ return 0; -+} -+ -+static struct platform_device sa1100_mtd_device = { -+ .name = "flash", -+ .id = 0, -+}; -+ -+static struct device_driver sa1100_mtd_driver = { -+ .name = "flash", -+ .bus = &platform_bus_type, -+ .probe = sa1100_mtd_probe, -+#ifdef MODULE -+ .remove = sa1100_mtd_remove, -+#endif -+ .suspend = sa1100_mtd_suspend, -+ .resume = sa1100_mtd_resume, -+}; -+ -+static int __init sa1100_mtd_init(void) -+{ -+ int ret = driver_register(&sa1100_mtd_driver); -+ if (ret == 0) { -+ ret = platform_device_register(&sa1100_mtd_device); -+ if (ret) -+ driver_unregister(&sa1100_mtd_driver); -+ } -+ return ret; -+} -+ -+static void __exit sa1100_mtd_exit(void) -+{ -+ platform_device_unregister(&sa1100_mtd_device); -+ driver_unregister(&sa1100_mtd_driver); - } - - module_init(sa1100_mtd_init); --module_exit(sa1100_mtd_cleanup); -+module_exit(sa1100_mtd_exit); - - MODULE_AUTHOR("Nicolas Pitre"); - MODULE_DESCRIPTION("SA1100 CFI map driver"); ---- linux-2.6.5/drivers/mtd/maps/pcmciamtd.c~heh 2004-04-03 22:36:19.000000000 -0500 -+++ linux-2.6.5/drivers/mtd/maps/pcmciamtd.c 2004-04-30 20:57:36.000000000 -0400 -@@ -25,10 +25,9 @@ - #include - - #include --#include - --#ifdef CONFIG_MTD_DEBUG --static int debug = CONFIG_MTD_DEBUG_VERBOSE; -+#if 1 //def CONFIG_MTD_DEBUG -+static int debug = 5; //CONFIG_MTD_DEBUG_VERBOSE; - MODULE_PARM(debug, "i"); - MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy"); - #undef DEBUG -@@ -88,7 +87,7 @@ - static int setvpp; - - /* Force card to be treated as FLASH, ROM or RAM */ --static int mem_type; -+static int mem_type = 1; - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Simon Evans "); ---- linux-2.6.5/drivers/mtd/maps/pci.c~heh 2004-04-03 22:36:56.000000000 -0500 -+++ linux-2.6.5/drivers/mtd/maps/pci.c 2004-04-30 20:57:36.000000000 -0400 -@@ -22,6 +22,8 @@ - #include - #include - -+#include -+ - struct map_pci_info; - - struct mtd_pci_info { ---- linux-2.6.5/drivers/input/Kconfig~heh 2004-04-03 22:36:18.000000000 -0500 -+++ linux-2.6.5/drivers/input/Kconfig 2004-04-30 20:57:36.000000000 -0400 -@@ -80,7 +80,7 @@ - module will be called joydev. - - config INPUT_TSDEV -- tristate "Touchscreen interface" -+ tristate "Compaq Touchscreen interface" - depends on INPUT - ---help--- - Say Y here if you have an application that only can understand the -@@ -102,6 +102,10 @@ - depends on INPUT_TSDEV - default "320" - -+config INPUT_TSLIBDEV -+ tristate "TSLIB Touchscreen interface" -+ depends on INPUT -+ - config INPUT_EVDEV - tristate "Event interface" - depends on INPUT ---- linux-2.6.5/drivers/input/serio/Kconfig~heh 2004-04-03 22:37:07.000000000 -0500 -+++ linux-2.6.5/drivers/input/serio/Kconfig 2004-04-30 20:57:36.000000000 -0400 -@@ -80,7 +80,7 @@ - - config SERIO_RPCKBD - tristate "Acorn RiscPC keyboard controller" -- depends on ARCH_ACORN && SERIO -+ depends on (ARCH_ACORN || ARCH_CLPS7500) && SERIO - default y - help - Say Y here if you have the Acorn RiscPC and want to use an AT -@@ -89,6 +89,18 @@ - To compile this driver as a module, choose M here: the - module will be called rpckbd. - -+config SERIO_CLPS7500 -+ tristate "CLPS7500 PS/2 mouse port controller" -+ depends on ARCH_CLPS7500 && SERIO -+ help -+ Say Y here if you have CLPS7500 based hardware and want to use -+ the mouse port. -+ -+ This driver is also available as a module ( = code which can be -+ inserted in and removed from the running kernel whenever you want). -+ The module will be called clps7500ps2. If you want to compile it -+ as a module, say M here and read . -+ - config SERIO_AMBAKMI - tristate "AMBA KMI keyboard controller" - depends on ARCH_INTEGRATOR && SERIO ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/input/serio/sa1100ir.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,90 @@ -+/* -+ * linux/drivers/input/serio/sa1100ir.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. -+ */ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+ -+ -+struct sa1100_kbd { -+ struct serio io; -+ void *base; -+ int irq; -+}; -+ -+static void sa1100ir_int(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ struct sa1100_kbd *kbd = dev_id; -+ unsigned int status; -+ -+ do { -+ unsigned int flag, data; -+ -+ status = readl(kbd->base + UTSR1); -+ if (!(status & UTSR1_RNE)) -+ break; -+ -+ flag = (status & UTSR1_FRE ? SERIO_FRAME : 0) | -+ (status & UTSR1_PRE ? SERIO_PARITY : 0); -+ -+ data = readl(kbd->base + UTDR); -+ -+ serio_interrupt(&kbd->io, data, flag); -+ } while (1); -+ -+ status = readl(kbd->base + UTSR0) & UTSR0_RID | UTSR0_RBB | UTSR0_REB; -+ if (status) -+ writel(status, kbd->base + UTSR0); -+} -+ -+static int sa1100ir_kbd_open(struct serio *io) -+{ -+ struct sa1100_kbd *kbd = io->driver; -+ int ret; -+ -+ ret = request_irq(kbd->irq, sa1100ir_int, 0, kbd->io.phys, kbd); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static void sa1100ir_kbd_close(struct serio *io) -+{ -+ struct sa1100_kbd *kbd = io->driver; -+ -+ free_irq(kbd->irq, kbd); -+} -+ -+static struct sa1100_kbd sa1100_kbd = { -+ .io = { -+ .type = 0, -+ .open = sa1100ir_kbd_open, -+ .close = sa1100ir_kbd_close, -+ .name = "SA11x0 IR port", -+ .phys = "sa11x0/ir", -+ .driver = &sa1100_kbd, -+ }, -+}; -+ -+static int __init sa1100_kbd_init(void) -+{ -+ serio_register_port(&sa1100_kbd.io); -+} -+ -+static void __exit sa1100_kbd_exit(void) -+{ -+ serio_unregister_port(&sa1100_kbd.io); -+} -+ -+module_init(sa1100_kbd_init); -+module_exit(sa1100_kbd_exit); ---- linux-2.6.5/drivers/input/serio/Makefile~heh 2004-04-03 22:36:16.000000000 -0500 -+++ linux-2.6.5/drivers/input/serio/Makefile 2004-04-30 20:57:36.000000000 -0400 -@@ -10,6 +10,7 @@ - obj-$(CONFIG_SERIO_SERPORT) += serport.o - obj-$(CONFIG_SERIO_CT82C710) += ct82c710.o - obj-$(CONFIG_SERIO_RPCKBD) += rpckbd.o -+obj-$(CONFIG_SERIO_CLPS7500) += clps7500ps2.o - obj-$(CONFIG_SERIO_SA1111) += sa1111ps2.o - obj-$(CONFIG_SERIO_AMBAKMI) += ambakmi.o - obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/input/tslibdev.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,358 @@ -+/* -+ * linux/drivers/input/tslibdev.c -+ * -+ * Copyright (C) 2002 Russell King -+ * -+ * From tsdev.c: -+ * -+ * Copyright (c) 2001 "Crazy" james Simmons -+ * -+ * Input driver to Touchscreen device driver module. -+ * -+ * Sponsored by Transvirtual Technology -+ */ -+ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the 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 -+ * -+ * Should you need to contact me, the author, you can do so either by -+ * e-mail - mail your message to . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct ucb1x00_dev { -+ int exist; -+ char name[16]; -+ wait_queue_head_t wait; -+ struct list_head list; -+ struct input_handle handle; -+ int x; -+ int y; -+ int pressure; -+}; -+ -+struct ts_event { -+ u16 pressure; -+ u16 x; -+ u16 y; -+ u16 pad; -+ struct timeval stamp; -+}; -+ -+#define TSDEV_BUFFER_SIZE 64 -+ -+struct ucb1x00_list { -+ struct list_head list; -+ struct fasync_struct *fasync; -+ struct ucb1x00_dev *tsdev; -+ unsigned int head; -+ unsigned int tail; -+ struct ts_event event[TSDEV_BUFFER_SIZE]; -+}; -+ -+static struct input_handler ucb1x00_handler; -+static struct ucb1x00_dev *ucb1x00_dev; -+ -+static void ucb1x00_remove(struct ucb1x00_dev *tsdev); -+ -+ -+static int ucb1x00_fasync(int fd, struct file *file, int on) -+{ -+ struct ucb1x00_list *list = file->private_data; -+ int retval; -+ -+ retval = fasync_helper(fd, file, on, &list->fasync); -+ return retval < 0 ? retval : 0; -+} -+ -+static int ucb1x00_open(struct inode *inode, struct file *file) -+{ -+ struct ucb1x00_list *list; -+ int empty; -+ -+ if (!ucb1x00_dev || !ucb1x00_dev->exist) -+ return -ENODEV; -+ -+ printk(KERN_WARNING -+ "tslibdev: process %s (%d) uses obsolete tslib device\n", -+ current->comm, current->pid); -+ -+ list = kmalloc(sizeof(struct ucb1x00_list), GFP_KERNEL); -+ if (!list) -+ return -ENOMEM; -+ -+ memset(list, 0, sizeof(struct ucb1x00_list)); -+ -+ empty = list_empty(&ucb1x00_dev->list); -+ -+ list->tsdev = ucb1x00_dev; -+ list_add(&list->list, &list->tsdev->list); -+ -+ file->private_data = list; -+ -+ if (empty && list->tsdev->exist) -+ input_open_device(&list->tsdev->handle); -+ -+ return 0; -+} -+ -+static int ucb1x00_release(struct inode *inode, struct file *file) -+{ -+ struct ucb1x00_list *list = file->private_data; -+ -+ ucb1x00_fasync(-1, file, 0); -+ -+ list_del(&list->list); -+ -+ ucb1x00_remove(list->tsdev); -+ -+ kfree(list); -+ -+ return 0; -+} -+ -+static ssize_t -+ucb1x00_read(struct file *file, char *buffer, size_t count, loff_t * ppos) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ struct ucb1x00_list *list = file->private_data; -+ int retval = 0; -+ -+ if (list->head == list->tail) { -+ add_wait_queue(&list->tsdev->wait, &wait); -+ -+ while (list->head == list->tail) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ -+ if (!list->tsdev->exist) { -+ retval = -ENODEV; -+ break; -+ } -+ if (file->f_flags & O_NONBLOCK) { -+ retval = -EAGAIN; -+ break; -+ } -+ if (signal_pending(current)) { -+ retval = -ERESTARTSYS; -+ break; -+ } -+ schedule(); -+ } -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&list->tsdev->wait, &wait); -+ } -+ -+ if (retval) -+ return retval; -+ -+ while (list->head != list->tail && count >= sizeof(struct ts_event)) { -+ if (copy_to_user(buffer, list->event + list->tail, -+ sizeof(struct ts_event))) -+ return retval ? retval : -EFAULT; -+ list->tail = (list->tail + 1) & (TSDEV_BUFFER_SIZE - 1); -+ retval += sizeof(struct ts_event); -+ buffer += sizeof(struct ts_event); -+ count -= sizeof(struct ts_event); -+ } -+ return retval; -+} -+ -+/* No kernel lock - fine */ -+static unsigned int ucb1x00_poll(struct file *file, poll_table * wait) -+{ -+ struct ucb1x00_list *list = file->private_data; -+ -+ poll_wait(file, &list->tsdev->wait, wait); -+ if (list->head != list->tail || !list->tsdev->exist) -+ return POLLIN | POLLRDNORM; -+ return 0; -+} -+ -+static int -+ucb1x00_ioctl(struct inode *inode, struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ return -EINVAL; -+} -+ -+struct file_operations ucb1x00_fops = { -+ .owner = THIS_MODULE, -+ .open = ucb1x00_open, -+ .release = ucb1x00_release, -+ .read = ucb1x00_read, -+ .poll = ucb1x00_poll, -+ .fasync = ucb1x00_fasync, -+ .ioctl = ucb1x00_ioctl, -+}; -+ -+/* -+ * The official UCB1x00 touchscreen is a miscdevice: -+ * 10 char Non-serial mice, misc features -+ * 14 = /dev/touchscreen/ucb1x00 UCB 1x00 touchscreen -+ */ -+static struct miscdevice ucb1x00_ts_dev = { -+ .minor = 14, -+ .name = "touchscreen/ucb1x00", -+ .fops = &ucb1x00_fops, -+ .devfs_name = "touchscreen/ucb1x00", -+}; -+ -+static void ucb1x00_remove(struct ucb1x00_dev *tsdev) -+{ -+ if (list_empty(&tsdev->list)) { -+ if (tsdev->exist) { -+ input_close_device(&tsdev->handle); -+ wake_up_interruptible(&tsdev->wait); -+ } else { -+ misc_deregister(&ucb1x00_ts_dev); -+ ucb1x00_dev = NULL; -+ kfree(tsdev); -+ } -+ } -+} -+ -+ -+static void -+ucb1x00_event(struct input_handle *handle, unsigned int type, unsigned int code, -+ int value) -+{ -+ struct ucb1x00_dev *tsdev = handle->private; -+ struct list_head *l; -+ -+ /* sorry, we only handle absolute stuff */ -+ if (type == EV_ABS) { -+ switch (code) { -+ case ABS_X: -+ tsdev->x = value; -+ break; -+ case ABS_Y: -+ tsdev->y = value; -+ break; -+ case ABS_PRESSURE: -+ tsdev->pressure = value; -+ break; -+ } -+ return; -+ } -+ -+ if (type != EV_SYN || code != SYN_REPORT) -+ return; -+ -+ list_for_each(l, &tsdev->list) { -+ struct ucb1x00_list *list = list_entry(l, struct ucb1x00_list, list); -+ list->event[list->head].pressure = tsdev->pressure; -+ if (tsdev->pressure) { -+ list->event[list->head].x = tsdev->x; -+ list->event[list->head].y = tsdev->y; -+ } else { -+ list->event[list->head].x = 0; -+ list->event[list->head].y = 0; -+ } -+ do_gettimeofday(&list->event[list->head].stamp); -+ list->head = (list->head + 1) & (TSDEV_BUFFER_SIZE - 1); -+ kill_fasync(&list->fasync, SIGIO, POLL_IN); -+ } -+ wake_up_interruptible(&tsdev->wait); -+} -+ -+static struct input_handle * -+ucb1x00_connect(struct input_handler *handler, struct input_dev *dev, -+ struct input_device_id *id) -+{ -+ struct ucb1x00_dev *tsdev; -+ -+ if (ucb1x00_dev) -+ return NULL; -+ -+ tsdev = kmalloc(sizeof(struct ucb1x00_dev), GFP_KERNEL); -+ if (!tsdev) -+ return NULL; -+ -+ memset(tsdev, 0, sizeof(struct ucb1x00_dev)); -+ init_waitqueue_head(&tsdev->wait); -+ INIT_LIST_HEAD(&tsdev->list); -+ -+ ucb1x00_dev = tsdev; -+ -+ strcpy(tsdev->name, ucb1x00_ts_dev.name); -+ -+ tsdev->handle.dev = dev; -+ tsdev->handle.name = tsdev->name; -+ tsdev->handle.handler = handler; -+ tsdev->handle.private = tsdev; -+ -+ misc_register(&ucb1x00_ts_dev); -+ -+ tsdev->exist = 1; -+ -+ return &tsdev->handle; -+} -+ -+static void ucb1x00_disconnect(struct input_handle *handle) -+{ -+ struct ucb1x00_dev *tsdev = handle->private; -+ -+ tsdev->exist = 0; -+ ucb1x00_remove(tsdev); -+} -+ -+static struct input_device_id ucb1x00_ids[] = { -+ { -+ .flags = INPUT_DEVICE_ID_MATCH_ABSBIT, -+ .evbit = { BIT(EV_ABS) }, -+ .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) }, -+ }, -+ -+ {},/* Terminating entry */ -+}; -+ -+MODULE_DEVICE_TABLE(input, ucb1x00_ids); -+ -+static struct input_handler ucb1x00_handler = { -+ .event = ucb1x00_event, -+ .connect = ucb1x00_connect, -+ .disconnect = ucb1x00_disconnect, -+ .name = "touchscreen/ucb1x00", -+ .id_table = ucb1x00_ids, -+}; -+ -+static int __init ucb1x00_init(void) -+{ -+ input_register_handler(&ucb1x00_handler); -+ printk(KERN_INFO "ts: UCB1x00 touchscreen protocol output\n"); -+ return 0; -+} -+ -+static void __exit ucb1x00_exit(void) -+{ -+ input_unregister_handler(&ucb1x00_handler); -+} -+ -+module_init(ucb1x00_init); -+module_exit(ucb1x00_exit); -+ -+MODULE_AUTHOR("Russell King "); -+MODULE_DESCRIPTION("Input driver to UCB1x00 touchscreen converter"); ---- linux-2.6.5/drivers/input/Makefile~heh 2004-04-03 22:38:17.000000000 -0500 -+++ linux-2.6.5/drivers/input/Makefile 2004-04-30 20:57:36.000000000 -0400 -@@ -8,6 +8,7 @@ - obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o - obj-$(CONFIG_INPUT_JOYDEV) += joydev.o - obj-$(CONFIG_INPUT_EVDEV) += evdev.o -+obj-$(CONFIG_INPUT_TSLIBDEV) += tslibdev.o - obj-$(CONFIG_INPUT_TSDEV) += tsdev.o - obj-$(CONFIG_INPUT_POWER) += power.o - obj-$(CONFIG_INPUT_EVBUG) += evbug.o ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/char/sa1100-rtc.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,416 @@ -+/* -+ * Real Time Clock interface for Linux on Intel SA11x0/PXA2xx -+ * -+ * Copyright (c) 2000 Nils Faerber -+ * -+ * Based on rtc.c by Paul Gortmaker -+ * Date/time conversion routines taken from arch/arm/kernel/time.c -+ * by Linus Torvalds and Russel King -+ * and the GNU C Library -+ * ( ... I love the GPL ... just take what you need! ;) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * 1.00 2001-06-08 Nicolas Pitre -+ * - added periodic timer capability using OSMR1 -+ * - flag compatibility with other RTC chips -+ * - permission checks for ioctls -+ * - major cleanup, partial rewrite -+ * -+ * 0.03 2001-03-07 CIH -+ * - Modify the bug setups RTC clock. -+ * -+ * 0.02 2001-02-27 Nils Faerber -+ * - removed mktime(), added alarm irq clear -+ * -+ * 0.01 2000-10-01 Nils Faerber -+ * - initial release -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#define TIMER_FREQ 3686400 -+ -+#define RTC_DEF_DIVIDER 32768 - 1 -+#define RTC_DEF_TRIM 0 -+ -+/* Those are the bits from a classic RTC we want to mimic */ -+#define RTC_IRQF 0x80 /* any of the following 3 is active */ -+#define RTC_PF 0x40 -+#define RTC_AF 0x20 -+#define RTC_UF 0x10 -+ -+static unsigned long rtc_freq = 1024; -+static struct rtc_time rtc_alarm = { -+ .tm_year = 0, -+ .tm_mon = 0, -+ .tm_mday = 0, -+ .tm_hour = 0, -+ .tm_mon = 0, -+ .tm_sec = 0, -+}; -+ -+extern spinlock_t rtc_lock; -+ -+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 rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ unsigned int rtsr; -+ unsigned long events = 0; -+ -+ spin_lock(&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(1, events); -+ -+ if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm)) -+ rtc_update_alarm(&rtc_alarm); -+ -+ spin_unlock(&rtc_lock); -+ -+ return IRQ_HANDLED; -+} -+ -+#if 0 -+static unsigned long rtc_irq_data; -+ -+static irqreturn_t timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ /* -+ * If we match for the first time, the periodic interrupt flag won't -+ * be set. If it is, then we did wrap around (very unlikely but -+ * still possible) and 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 */ -+ if (rtc_irq_data & RTC_PF) { -+ rtc_irq_data += (rtc_freq * ((1<<30)/(TIMER_FREQ>>2))) << 8; -+ } else { -+ rtc_update(1, RTC_PF | RTC_IRQF); -+ } -+ -+ wake_up_interruptible(&rtc_wait); -+ kill_fasync (&rtc_async_queue, SIGIO, POLL_IN); -+ -+ return IRQ_HANDLED; -+} -+#endif -+ -+static int sa1100_rtc_open(void) -+{ -+ int ret; -+ -+ ret = request_irq(IRQ_RTC1Hz, rtc_interrupt, SA_INTERRUPT, "rtc 1Hz", NULL); -+ if (ret) { -+ printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTC1Hz); -+ goto fail_ui; -+ } -+ ret = request_irq(IRQ_RTCAlrm, rtc_interrupt, SA_INTERRUPT, "rtc Alrm", NULL); -+ if (ret) { -+ printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTCAlrm); -+ goto fail_ai; -+ } -+#if 0 -+ ret = request_irq(IRQ_OST1, timer1_interrupt, SA_INTERRUPT, "rtc timer", NULL); -+ if (ret) { -+ printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_OST1); -+ goto fail_pi; -+ } -+ rtc_irq_data = 0; -+#endif -+ 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(void) -+{ -+ spin_lock_irq (&rtc_lock); -+ RTSR = 0; -+ OIER &= ~OIER_E1; -+ OSSR = OSSR_M1; -+ spin_unlock_irq (&rtc_lock); -+ -+// free_irq(IRQ_OST1, NULL); -+ free_irq(IRQ_RTCAlrm, NULL); -+ free_irq(IRQ_RTC1Hz, NULL); -+} -+ -+#if 0 -+ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ unsigned long data; -+ ssize_t retval; -+ -+ if (count < sizeof(unsigned long)) -+ return -EINVAL; -+ -+ add_wait_queue(&rtc_wait, &wait); -+ set_current_state(TASK_INTERRUPTIBLE); -+ for (;;) { -+ spin_lock_irq (&rtc_lock); -+ data = rtc_irq_data; -+ if (data != 0) { -+ rtc_irq_data = 0; -+ break; -+ } -+ spin_unlock_irq (&rtc_lock); -+ -+ if (file->f_flags & O_NONBLOCK) { -+ retval = -EAGAIN; -+ goto out; -+ } -+ -+ if (signal_pending(current)) { -+ retval = -ERESTARTSYS; -+ goto out; -+ } -+ -+ schedule(); -+ } -+ -+ if (data & RTC_PF) { -+ /* interpolate missed periods and set match for the next one */ -+ 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 */ -+ while( (signed long)((osmr1 = OSMR1) - OSCR) <= 0 ) { -+ data += 0x100; -+ OSSR = OSSR_M1; /* clear match on timer 1 */ -+ OSMR1 = osmr1 + period; -+ } -+ } -+ spin_unlock_irq (&rtc_lock); -+ -+ data -= 0x100; /* the first IRQ wasn't actually missed */ -+ -+ retval = put_user(data, (unsigned long *)buf); -+ if (!retval) -+ retval = sizeof(unsigned long); -+ -+out: -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&rtc_wait, &wait); -+ return retval; -+} -+#endif -+ -+static int sa1100_rtc_ioctl(unsigned int cmd, unsigned long arg) -+{ -+ switch (cmd) { -+ case RTC_AIE_OFF: -+ spin_lock_irq(&rtc_lock); -+ RTSR &= ~RTSR_ALE; -+// rtc_irq_data = 0; -+ spin_unlock_irq(&rtc_lock); -+ return 0; -+ case RTC_AIE_ON: -+ spin_lock_irq(&rtc_lock); -+ RTSR |= RTSR_ALE; -+// rtc_irq_data = 0; -+ spin_unlock_irq(&rtc_lock); -+ return 0; -+ case RTC_UIE_OFF: -+ spin_lock_irq(&rtc_lock); -+ RTSR &= ~RTSR_HZE; -+// rtc_irq_data = 0; -+ spin_unlock_irq(&rtc_lock); -+ return 0; -+ case RTC_UIE_ON: -+ spin_lock_irq(&rtc_lock); -+ RTSR |= RTSR_HZE; -+// rtc_irq_data = 0; -+ spin_unlock_irq(&rtc_lock); -+ return 0; -+#if 0 -+ case RTC_PIE_OFF: -+ spin_lock_irq(&rtc_lock); -+ OIER &= ~OIER_E1; -+// rtc_irq_data = 0; -+ spin_unlock_irq(&rtc_lock); -+ return 0; -+ case RTC_PIE_ON: -+ if ((rtc_freq > 64) && !capable(CAP_SYS_RESOURCE)) -+ return -EACCES; -+ spin_lock_irq(&rtc_lock); -+ OSMR1 = TIMER_FREQ/rtc_freq + OSCR; -+ OIER |= OIER_E1; -+// rtc_irq_data = 0; -+ spin_unlock_irq(&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; -+#endif -+ } -+ return -EINVAL; -+} -+ -+static void sa1100_rtc_read_time(struct rtc_time *tm) -+{ -+ rtc_time_to_tm(RCNR, tm); -+} -+ -+static int sa1100_rtc_set_time(struct rtc_time *tm) -+{ -+ unsigned long time; -+ int ret; -+ -+ ret = rtc_tm_to_time(tm, &time); -+ if (ret == 0) -+ RCNR = time; -+ return ret; -+} -+ -+static void sa1100_rtc_read_alarm(struct rtc_wkalrm *alrm) -+{ -+ memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time)); -+ alrm->pending = RTSR & RTSR_AL ? 1 : 0; -+} -+ -+static int sa1100_rtc_set_alarm(struct rtc_wkalrm *alrm) -+{ -+ int ret; -+ -+ spin_lock_irq(&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(&rtc_lock); -+ -+ return ret; -+} -+ -+static int sa1100_rtc_proc(char *buf) -+{ -+ char *p = buf; -+ -+ p += sprintf(p, "trim/divider\t: 0x%08x\n", RTTR); -+ p += sprintf(p, "alarm_IRQ\t: %s\n", (RTSR & RTSR_ALE) ? "yes" : "no" ); -+ p += sprintf(p, "update_IRQ\t: %s\n", (RTSR & RTSR_HZE) ? "yes" : "no"); -+ p += sprintf(p, "periodic_IRQ\t: %s\n", (OIER & OIER_E1) ? "yes" : "no"); -+ p += sprintf(p, "periodic_freq\t: %ld\n", rtc_freq); -+ -+ return p - buf; -+} -+ -+static struct rtc_ops sa1100_rtc_ops = { -+ .owner = THIS_MODULE, -+ .open = sa1100_rtc_open, -+ .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 __init rtc_init(void) -+{ -+ /* -+ * 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; -+ } -+ -+ register_rtc(&sa1100_rtc_ops); -+ -+ return 0; -+} -+ -+static void __exit rtc_exit(void) -+{ -+ unregister_rtc(&sa1100_rtc_ops); -+} -+ -+module_init(rtc_init); -+module_exit(rtc_exit); -+ -+MODULE_AUTHOR("Nils Faerber "); -+MODULE_DESCRIPTION("SA11x0/PXA2xx Realtime Clock Driver (RTC)"); -+MODULE_LICENSE("GPL"); /* so says the header */ ---- linux-2.6.5/drivers/char/Kconfig~heh 2004-04-03 22:36:15.000000000 -0500 -+++ linux-2.6.5/drivers/char/Kconfig 2004-04-30 20:57:36.000000000 -0400 -@@ -814,6 +814,10 @@ - - If unsure, say N. - -+config SA1100_RTC -+ tristate "SA1100 or PXA Real Time Clock" -+ depends on ARCH_SA1100 || ARCH_PXA -+ - config DTLK - tristate "Double Talk PC internal speech card support" - help ---- linux-2.6.5/drivers/char/tty_io.c~heh 2004-04-03 22:37:23.000000000 -0500 -+++ linux-2.6.5/drivers/char/tty_io.c 2004-04-30 20:57:36.000000000 -0400 -@@ -1535,10 +1535,17 @@ - return 0; - } - -+/* -+ * In the case of pty's, "tty" is the master side -+ * and "real_tty" is the slave side. -+ */ - static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, - struct winsize * arg) - { - struct winsize tmp_ws; -+ struct task_struct *p; -+ struct list_head *l; -+ struct pid *pid; - - if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) - return -EFAULT; -@@ -1558,8 +1565,21 @@ - #endif - if (tty->pgrp > 0) - kill_pg(tty->pgrp, SIGWINCH, 1); -- if ((real_tty->pgrp != tty->pgrp) && (real_tty->pgrp > 0)) -- kill_pg(real_tty->pgrp, SIGWINCH, 1); -+ -+ /* -+ * Send SIGWINCH to the whole session on the slave tty. -+ * However, in the case of non-master pty's, be careful -+ * not to send two SIGWINCH to the same procress group. -+ */ -+ if (real_tty->session > 0) { -+ read_lock(&tasklist_lock); -+ for_each_task_pid(real_tty->session, PIDTYPE_SID, p, l, pid) { -+ if (process_group(p) != tty->pgrp) -+ group_send_sig_info(SIGWINCH, (void *)1L, p); -+ } -+ read_unlock(&tasklist_lock); -+ } -+ - tty->winsize = tmp_ws; - real_tty->winsize = tmp_ws; - return 0; ---- linux-2.6.5/drivers/Makefile~heh 2004-04-03 22:37:43.000000000 -0500 -+++ linux-2.6.5/drivers/Makefile 2004-04-30 20:57:36.000000000 -0400 -@@ -11,6 +11,8 @@ - # PnP must come after ACPI since it will eventually need to check if acpi - # was used and do nothing if so - obj-$(CONFIG_PNP) += pnp/ -+obj-$(CONFIG_I2C) += i2c/ -+obj-$(CONFIG_L3) += l3/ - - # char/ comes before serial/ etc so that the VT console is the boot-time - # default. -@@ -41,7 +43,6 @@ - obj-$(CONFIG_GAMEPORT) += input/gameport/ - obj-$(CONFIG_SERIO) += input/serio/ - obj-$(CONFIG_I2O) += message/ --obj-$(CONFIG_I2C) += i2c/ - obj-$(CONFIG_PHONE) += telephony/ - obj-$(CONFIG_MD) += md/ - obj-$(CONFIG_BT) += bluetooth/ ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/l3/Kconfig 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,24 @@ -+# -+# L3 bus configuration -+# -+ -+menu "L3 serial bus support" -+ -+config L3 -+ tristate "L3 support" -+ -+config L3_ALGOBIT -+ bool "L3 bit-banging interfaces" -+ depends on L3=y -+ -+config L3_BIT_SA1100_GPIO -+ bool "SA11x0 GPIO adapter" -+ depends on L3_ALGOBIT && ARCH_SA1100 -+ -+# i2c must come before this -+config BIT_SA1100_GPIO -+ bool -+ depends on L3_BIT_SA1100_GPIO || I2C_BIT_SA1100_GPIO=y -+ default y -+ -+endmenu ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/l3/l3-core.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,203 @@ -+/* -+ * linux/drivers/l3/l3-core.c -+ * -+ * Copyright (C) 2001 Russell King -+ * -+ * General structure taken from i2c-core.c by Simon G. Vogl -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License. -+ * -+ * See linux/Documentation/l3 for further documentation. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static DECLARE_MUTEX(adapter_lock); -+static LIST_HEAD(adapter_list); -+ -+static DECLARE_MUTEX(driver_lock); -+static LIST_HEAD(driver_list); -+ -+/** -+ * l3_add_adapter - register a new L3 bus adapter -+ * @adap: l3_adapter structure for the registering adapter -+ * -+ * Make the adapter available for use by clients using name adap->name. -+ * The adap->adapters list is initialised by this function. -+ * -+ * Returns 0; -+ */ -+int l3_add_adapter(struct l3_adapter *adap) -+{ -+ down(&adapter_lock); -+ list_add(&adap->adapters, &adapter_list); -+ up(&adapter_lock); -+ return 0; -+} -+ -+/** -+ * l3_del_adapter - unregister a L3 bus adapter -+ * @adap: l3_adapter structure to unregister -+ * -+ * Remove an adapter from the list of available L3 Bus adapters. -+ * -+ * Returns 0; -+ */ -+int l3_del_adapter(struct l3_adapter *adap) -+{ -+ down(&adapter_lock); -+ list_del(&adap->adapters); -+ up(&adapter_lock); -+ return 0; -+} -+ -+static struct l3_adapter *__l3_get_adapter(const char *name) -+{ -+ struct list_head *l; -+ -+ list_for_each(l, &adapter_list) { -+ struct l3_adapter *adap = list_entry(l, struct l3_adapter, adapters); -+ -+ if (strcmp(adap->name, name) == 0) -+ return adap; -+ } -+ -+ return NULL; -+} -+ -+/** -+ * l3_get_adapter - get a reference to an adapter -+ * @name: driver name -+ * -+ * Obtain a l3_adapter structure for the specified adapter. If the adapter -+ * is not currently load, then load it. The adapter will be locked in core -+ * until all references are released via l3_put_adapter. -+ */ -+struct l3_adapter *l3_get_adapter(const char *name) -+{ -+ struct l3_adapter *adap; -+ int try; -+ -+ for (try = 0; try < 2; try ++) { -+ down(&adapter_lock); -+ adap = __l3_get_adapter(name); -+ if (adap && !try_module_get(adap->owner)) -+ adap = NULL; -+ up(&adapter_lock); -+ -+ if (adap) -+ break; -+ -+ if (try == 0) -+ request_module(name); -+ } -+ -+ return adap; -+} -+ -+/** -+ * l3_put_adapter - release a reference to an adapter -+ * @adap: driver to release reference -+ * -+ * Indicate to the L3 core that you no longer require the adapter reference. -+ * The adapter module may be unloaded when there are no references to its -+ * data structure. -+ * -+ * You must not use the reference after calling this function. -+ */ -+void l3_put_adapter(struct l3_adapter *adap) -+{ -+ if (adap && adap->owner) -+ module_put(adap->owner); -+} -+ -+/** -+ * l3_transfer - transfer information on an L3 bus -+ * @adap: adapter structure to perform transfer on -+ * @msgs: array of l3_msg structures describing transfer -+ * @num: number of l3_msg structures -+ * -+ * Transfer the specified messages to/from a device on the L3 bus. -+ * -+ * Returns number of messages successfully transferred, otherwise negative -+ * error code. -+ */ -+int l3_transfer(struct l3_adapter *adap, struct l3_msg msgs[], int num) -+{ -+ int ret = -ENOSYS; -+ -+ if (adap->algo->xfer) { -+ down(adap->lock); -+ ret = adap->algo->xfer(adap, msgs, num); -+ up(adap->lock); -+ } -+ return ret; -+} -+ -+/** -+ * l3_write - send data to a device on an L3 bus -+ * @adap: L3 bus adapter -+ * @addr: L3 bus address -+ * @buf: buffer for bytes to send -+ * @len: number of bytes to send -+ * -+ * Send len bytes pointed to by buf to device address addr on the L3 bus -+ * described by client. -+ * -+ * Returns the number of bytes transferred, or negative error code. -+ */ -+int l3_write(struct l3_adapter *adap, int addr, const char *buf, int len) -+{ -+ struct l3_msg msg; -+ int ret; -+ -+ msg.addr = addr; -+ msg.flags = 0; -+ msg.buf = (char *)buf; -+ msg.len = len; -+ -+ ret = l3_transfer(adap, &msg, 1); -+ return ret == 1 ? len : ret; -+} -+ -+/** -+ * l3_read - receive data from a device on an L3 bus -+ * @adap: L3 bus adapter -+ * @addr: L3 bus address -+ * @buf: buffer for bytes to receive -+ * @len: number of bytes to receive -+ * -+ * Receive len bytes from device address addr on the L3 bus described by -+ * client to a buffer pointed to by buf. -+ * -+ * Returns the number of bytes transferred, or negative error code. -+ */ -+int l3_read(struct l3_adapter *adap, int addr, char *buf, int len) -+{ -+ struct l3_msg msg; -+ int ret; -+ -+ msg.addr = addr; -+ msg.flags = L3_M_RD; -+ msg.buf = buf; -+ msg.len = len; -+ -+ ret = l3_transfer(adap, &msg, 1); -+ return ret == 1 ? len : ret; -+} -+ -+EXPORT_SYMBOL(l3_add_adapter); -+EXPORT_SYMBOL(l3_del_adapter); -+EXPORT_SYMBOL(l3_get_adapter); -+EXPORT_SYMBOL(l3_put_adapter); -+EXPORT_SYMBOL(l3_transfer); -+EXPORT_SYMBOL(l3_write); -+EXPORT_SYMBOL(l3_read); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/l3/l3-algo-bit.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,175 @@ -+/* -+ * L3 bus algorithm module. -+ * -+ * Copyright (C) 2001 Russell King, 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 L3 buses can share the same pins as I2C buses, so we must -+ * _not_ generate an I2C start condition. An I2C start condition is -+ * defined as a high-to-low transition of the data line while the clock -+ * is high. Therefore, we must only change the data line while the -+ * clock is low. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define setdat(adap,val) adap->setdat(adap->data, val) -+#define setclk(adap,val) adap->setclk(adap->data, val) -+#define setmode(adap,val) adap->setmode(adap->data, val) -+#define setdatin(adap) adap->setdir(adap->data, 1) -+#define setdatout(adap) adap->setdir(adap->data, 0) -+#define getdat(adap) adap->getdat(adap->data) -+ -+/* -+ * Send one byte of data to the chip. Data is latched into the chip on -+ * the rising edge of the clock. -+ */ -+static void sendbyte(struct l3_algo_bit_data *adap, unsigned int byte) -+{ -+ int i; -+ -+ for (i = 0; i < 8; i++) { -+ setclk(adap, 0); -+ udelay(adap->data_hold); -+ setdat(adap, byte & 1); -+ udelay(adap->data_setup); -+ setclk(adap, 1); -+ udelay(adap->clock_high); -+ byte >>= 1; -+ } -+} -+ -+/* -+ * Send a set of bytes to the chip. We need to pulse the MODE line -+ * between each byte, but never at the start nor at the end of the -+ * transfer. -+ */ -+static void sendbytes(struct l3_algo_bit_data *adap, const char *buf, int len) -+{ -+ int i; -+ -+ for (i = 0; i < len; i++) { -+ if (i) { -+ udelay(adap->mode_hold); -+ setmode(adap, 0); -+ udelay(adap->mode); -+ } -+ setmode(adap, 1); -+ udelay(adap->mode_setup); -+ sendbyte(adap, buf[i]); -+ } -+} -+ -+/* -+ * Read one byte of data from the chip. Data is latched into the chip on -+ * the rising edge of the clock. -+ */ -+static unsigned int readbyte(struct l3_algo_bit_data *adap) -+{ -+ unsigned int byte = 0; -+ int i; -+ -+ for (i = 0; i < 8; i++) { -+ setclk(adap, 0); -+ udelay(adap->data_hold + adap->data_setup); -+ setclk(adap, 1); -+ if (getdat(adap)) -+ byte |= 1 << i; -+ udelay(adap->clock_high); -+ } -+ -+ return byte; -+} -+ -+/* -+ * Read a set of bytes from the chip. We need to pulse the MODE line -+ * between each byte, but never at the start nor at the end of the -+ * transfer. -+ */ -+static void readbytes(struct l3_algo_bit_data *adap, char *buf, int len) -+{ -+ int i; -+ -+ for (i = 0; i < len; i++) { -+ if (i) { -+ udelay(adap->mode_hold); -+ setmode(adap, 0); -+ } -+ setmode(adap, 1); -+ udelay(adap->mode_setup); -+ buf[i] = readbyte(adap); -+ } -+} -+ -+static int l3_xfer(struct l3_adapter *l3_adap, struct l3_msg msgs[], int num) -+{ -+ struct l3_algo_bit_data *adap = l3_adap->algo_data; -+ int i; -+ -+ /* -+ * If we share an I2C bus, ensure that it is in STOP mode -+ */ -+ setclk(adap, 1); -+ setdat(adap, 1); -+ setmode(adap, 1); -+ setdatout(adap); -+ udelay(adap->mode); -+ -+ for (i = 0; i < num; i++) { -+ struct l3_msg *pmsg = &msgs[i]; -+ -+ if (!(pmsg->flags & L3_M_NOADDR)) { -+ setmode(adap, 0); -+ udelay(adap->mode_setup); -+ sendbyte(adap, pmsg->addr); -+ udelay(adap->mode_hold); -+ } -+ -+ if (pmsg->flags & L3_M_RD) { -+ setdatin(adap); -+ readbytes(adap, pmsg->buf, pmsg->len); -+ } else { -+ setdatout(adap); -+ sendbytes(adap, pmsg->buf, pmsg->len); -+ } -+ } -+ -+ /* -+ * Ensure that we leave the bus in I2C stop mode. -+ */ -+ setclk(adap, 1); -+ setdat(adap, 1); -+ setmode(adap, 0); -+ setdatin(adap); -+ -+ return num; -+} -+ -+static struct l3_algorithm l3_bit_algo = { -+ name: "L3 bit-shift algorithm", -+ xfer: l3_xfer, -+}; -+ -+int l3_bit_add_bus(struct l3_adapter *adap) -+{ -+ adap->algo = &l3_bit_algo; -+ return l3_add_adapter(adap); -+} -+ -+int l3_bit_del_bus(struct l3_adapter *adap) -+{ -+ return l3_del_adapter(adap); -+} -+ -+EXPORT_SYMBOL(l3_bit_add_bus); -+EXPORT_SYMBOL(l3_bit_del_bus); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/l3/Makefile 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,11 @@ -+# -+# Makefile for the L3 bus driver. -+# -+ -+# Link order: -+# (core, adapters, algorithms, drivers) then clients -+ -+l3-$(CONFIG_L3_ALGOBIT) += l3-algo-bit.o -+l3-$(CONFIG_BIT_SA1100_GPIO) += l3-bit-sa1100.o -+ -+obj-$(CONFIG_L3) += l3-core.o $(l3-y) $(l3-drv-y) ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/l3/l3-bit-sa1100.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,271 @@ -+/* -+ * linux/drivers/l3/l3-bit-sa1100.c -+ * -+ * 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 version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This is a combined I2C and L3 bus driver. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#define NAME "l3-bit-sa1100-gpio" -+ -+struct bit_data { -+ unsigned int sda; -+ unsigned int scl; -+ unsigned int l3_mode; -+}; -+ -+static int getsda(void *data) -+{ -+ struct bit_data *bits = data; -+ -+ return GPLR & bits->sda; -+} -+ -+#ifdef CONFIG_I2C_BIT_SA1100_GPIO -+static void i2c_setsda(void *data, int state) -+{ -+ struct bit_data *bits = data; -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ if (state) -+ GPDR &= ~bits->sda; -+ else { -+ GPCR = bits->sda; -+ GPDR |= bits->sda; -+ } -+ local_irq_restore(flags); -+} -+ -+static void i2c_setscl(void *data, int state) -+{ -+ struct bit_data *bits = data; -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ if (state) -+ GPDR &= ~bits->scl; -+ else { -+ GPCR = bits->scl; -+ GPDR |= bits->scl; -+ } -+ local_irq_restore(flags); -+} -+ -+static int i2c_getscl(void *data) -+{ -+ struct bit_data *bits = data; -+ -+ return GPLR & bits->scl; -+} -+ -+static struct i2c_algo_bit_data i2c_bit_data = { -+ .setsda = i2c_setsda, -+ .setscl = i2c_setscl, -+ .getsda = getsda, -+ .getscl = i2c_getscl, -+ .udelay = 10, -+ .mdelay = 10, -+ .timeout = 100, -+}; -+ -+static struct i2c_adapter i2c_adapter = { -+ .algo_data = &i2c_bit_data, -+}; -+ -+#define LOCK &i2c_adapter.bus_lock -+ -+static int __init i2c_init(struct bit_data *bits) -+{ -+ i2c_bit_data.data = bits; -+ return i2c_bit_add_bus(&i2c_adapter); -+} -+ -+static void i2c_exit(void) -+{ -+ i2c_bit_del_bus(&i2c_adapter); -+} -+ -+#else -+static DECLARE_MUTEX(l3_lock); -+#define LOCK &l3_lock -+#define i2c_init(bits) (0) -+#define i2c_exit() do { } while (0) -+#endif -+ -+#ifdef CONFIG_L3_BIT_SA1100_GPIO -+/* -+ * iPAQs need the clock line driven hard high and low. -+ */ -+static void l3_setscl(void *data, int state) -+{ -+ struct bit_data *bits = data; -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ if (state) -+ GPSR = bits->scl; -+ else -+ GPCR = bits->scl; -+ GPDR |= bits->scl; -+ local_irq_restore(flags); -+} -+ -+static void l3_setsda(void *data, int state) -+{ -+ struct bit_data *bits = data; -+ -+ if (state) -+ GPSR = bits->sda; -+ else -+ GPCR = bits->sda; -+} -+ -+static void l3_setdir(void *data, int in) -+{ -+ struct bit_data *bits = data; -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ if (in) -+ GPDR &= ~bits->sda; -+ else -+ GPDR |= bits->sda; -+ local_irq_restore(flags); -+} -+ -+static void l3_setmode(void *data, int state) -+{ -+ struct bit_data *bits = data; -+ -+ if (state) -+ GPSR = bits->l3_mode; -+ else -+ GPCR = bits->l3_mode; -+} -+ -+static struct l3_algo_bit_data l3_bit_data = { -+ .data = NULL, -+ .setdat = l3_setsda, -+ .setclk = l3_setscl, -+ .setmode = l3_setmode, -+ .setdir = l3_setdir, -+ .getdat = getsda, -+ .data_hold = 1, -+ .data_setup = 1, -+ .clock_high = 1, -+ .mode_hold = 1, -+ .mode_setup = 1, -+}; -+ -+static struct l3_adapter l3_adapter = { -+ .owner = THIS_MODULE, -+ .name = NAME, -+ .algo_data = &l3_bit_data, -+ .lock = LOCK, -+}; -+ -+static int __init l3_init(struct bit_data *bits) -+{ -+ l3_bit_data.data = bits; -+ return l3_bit_add_bus(&l3_adapter); -+} -+ -+static void __exit l3_exit(void) -+{ -+ l3_bit_del_bus(&l3_adapter); -+} -+#else -+#define l3_init(bits) (0) -+#define l3_exit() do { } while (0) -+#endif -+ -+static struct bit_data bit_data; -+ -+static int __init bus_init(void) -+{ -+ struct bit_data *bit = &bit_data; -+ unsigned long flags; -+ int ret; -+ -+ if (machine_is_assabet() || machine_is_pangolin()) { -+ bit->sda = GPIO_GPIO15; -+ bit->scl = GPIO_GPIO18; -+ bit->l3_mode = GPIO_GPIO17; -+ } -+ -+ if (machine_is_h3600() || machine_is_h3100()) { -+ bit->sda = GPIO_GPIO14; -+ bit->scl = GPIO_GPIO16; -+ bit->l3_mode = GPIO_GPIO15; -+ } -+ -+ if (machine_is_stork()) { -+ bit->sda = GPIO_GPIO15; -+ bit->scl = GPIO_GPIO18; -+ bit->l3_mode = GPIO_GPIO17; -+ } -+ -+ if (!bit->sda) -+ return -ENODEV; -+ -+ /* -+ * Default level for L3 mode is low. -+ * We set SCL and SDA high (i2c idle state). -+ */ -+ local_irq_save(flags); -+ GPDR &= ~(bit->scl | bit->sda); -+ GPCR = bit->l3_mode | bit->scl | bit->sda; -+ GPDR |= bit->l3_mode; -+ local_irq_restore(flags); -+ -+ if (machine_is_assabet()) { -+ /* -+ * Release reset on UCB1300, ADI7171 and UDA1341. We -+ * need to do this here so that we can communicate on -+ * the I2C/L3 buses. -+ */ -+ ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); -+ mdelay(1); -+ ASSABET_BCR_clear(ASSABET_BCR_CODEC_RST); -+ mdelay(1); -+ ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); -+ } -+ -+ ret = i2c_init(bit); -+ if (ret == 0 && bit->l3_mode) { -+ ret = l3_init(bit); -+ if (ret) -+ i2c_exit(); -+ } -+ -+ return ret; -+} -+ -+static void __exit bus_exit(void) -+{ -+ l3_exit(); -+ i2c_exit(); -+} -+ -+module_init(bus_init); -+module_exit(bus_exit); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/misc/switches.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,22 @@ -+/* -+ * linux/drivers/misc/switches.h -+ * -+ * Copyright (C) 2001 John Dorsey -+ * -+ * 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. -+ * -+ * 19 December 2001 - created. -+ */ -+ -+#if !defined(_SWITCHES_H) -+# define _SWITCHES_H -+ -+#include -+ -+#define SWITCHES_NAME "switches" -+ -+extern int switches_event(switches_mask_t *mask); -+ -+#endif /* !defined(_SWITCHES_H) */ ---- linux-2.6.5/drivers/misc/Kconfig~heh 2004-04-03 22:36:26.000000000 -0500 -+++ linux-2.6.5/drivers/misc/Kconfig 2004-04-30 20:57:36.000000000 -0400 -@@ -21,5 +21,62 @@ - - If unsure, say N. - -+menu "Multimedia Capabilities Port drivers" -+ -+config MCP -+ tristate "Multimedia drivers" -+ -+# Interface drivers -+config MCP_SA1100 -+ tristate "Support SA1100 MCP interface" -+ depends on MCP && ARCH_SA1100 -+ -+# Chip drivers -+config MCP_UCB1200 -+ tristate "Support for UCB1200 / UCB1300" -+ depends on MCP -+ -+config MCP_UCB1200_AUDIO -+ tristate "Audio / Telephony interface support" -+ depends on MCP_UCB1200 && SOUND -+ -+config MCP_UCB1200_TS -+ tristate "Touchscreen interface support" -+ depends on MCP_UCB1200 && INPUT -+ -+endmenu -+ -+ -+menu "Console Switches" -+ -+config SWITCHES -+ tristate "Console Switch Support" -+ help -+ Say Y here to include support for simple console momentary switches. -+ This driver implements a miscellaneous character device (named -+ `switches' in /proc/misc) which can be read by userland programs -+ to respond to switch press events. This mechanism is efficient for -+ systems which may not implement a traditional heavyweight console -+ server. -+ -+ It is also possible to say M to build this driver as a module (named -+ `switches.o'). -+ -+config SWITCHES_SA1100 -+ tristate "SA-1100 switches" -+ depends on SWITCHES && ARCH_SA1100 -+ help -+ Say Y here to include support for switches routed directly to -+ interruptable signals on StrongARM SA-1100 systems. -+ -+config SWITCHES_UCB1X00 -+ tristate "UCB1x00 switches" -+ depends on SWITCHES && MCP_UCB1200 -+ help -+ Say Y here to include support for switches routed through a -+ UCB1x00 modem/audio analog front-end device. -+ -+endmenu -+ - endmenu - ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/misc/ucb1x00-assabet.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,73 @@ -+/* -+ * linux/drivers/misc/ucb1x00-assabet.c -+ * -+ * Copyright (C) 2001-2003 Russell King, 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. -+ * -+ * We handle the machine-specific bits of the UCB1x00 driver here. -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "ucb1x00.h" -+ -+#define UCB1X00_ATTR(name,input)\ -+static ssize_t name##_show(struct class_device *dev, char *buf) \ -+{ \ -+ struct ucb1x00 *ucb = classdev_to_ucb1x00(dev); \ -+ int val; \ -+ ucb1x00_adc_enable(ucb); \ -+ val = ucb1x00_adc_read(ucb, input, UCB_NOSYNC); \ -+ ucb1x00_adc_disable(ucb); \ -+ return sprintf(buf, "%d\n", val); \ -+} \ -+static CLASS_DEVICE_ATTR(name,0444,name##_show,NULL) -+ -+UCB1X00_ATTR(vbatt, UCB_ADC_INP_AD1); -+UCB1X00_ATTR(vcharger, UCB_ADC_INP_AD0); -+UCB1X00_ATTR(batt_temp, UCB_ADC_INP_AD2); -+ -+static int ucb1x00_assabet_add(struct class_device *dev) -+{ -+ class_device_create_file(dev, &class_device_attr_vbatt); -+ class_device_create_file(dev, &class_device_attr_vcharger); -+ class_device_create_file(dev, &class_device_attr_batt_temp); -+ return 0; -+} -+ -+static void ucb1x00_assabet_remove(struct class_device *dev) -+{ -+ class_device_remove_file(dev, &class_device_attr_batt_temp); -+ class_device_remove_file(dev, &class_device_attr_vcharger); -+ class_device_remove_file(dev, &class_device_attr_vbatt); -+} -+ -+static struct class_interface ucb1x00_assabet_interface = { -+ .add = ucb1x00_assabet_add, -+ .remove = ucb1x00_assabet_remove, -+}; -+ -+static int __init ucb1x00_assabet_init(void) -+{ -+ return ucb1x00_register_interface(&ucb1x00_assabet_interface); -+} -+ -+static void __exit ucb1x00_assabet_exit(void) -+{ -+ ucb1x00_unregister_interface(&ucb1x00_assabet_interface); -+} -+ -+module_init(ucb1x00_assabet_init); -+module_exit(ucb1x00_assabet_exit); -+ -+MODULE_AUTHOR("Russell King "); -+MODULE_DESCRIPTION("Assabet noddy testing only example ADC driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/misc/mcp-pxa.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,57 @@ -+/* -+ * linux/drivers/misc/mcp-pxa.c -+ * -+ * 2002-01-10 Jeff Sutherland -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License. -+ * -+ * NOTE: This is a quick hack to gain access to the aclink codec's -+ * touch screen facility. Its audio is handled by a separate -+ * (non-mcp) driver at the present time. -+ */ -+ -+#include -+#include -+#include -+ -+#include "mcp.h" -+ -+ -+extern int pxa_ac97_get(struct ac97_codec **codec); -+extern void pxa_ac97_put(void); -+ -+ -+struct mcp *mcp_get(void) -+{ -+ struct ac97_codec *codec; -+ if (pxa_ac97_get(&codec) < 0) -+ return NULL; -+ return (struct mcp *)codec; -+} -+ -+void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val) -+{ -+ struct ac97_codec *codec = (struct ac97_codec *)mcp; -+ codec->codec_write(codec, reg, val); -+} -+ -+unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg) -+{ -+ struct ac97_codec *codec = (struct ac97_codec *)mcp; -+ return codec->codec_read(codec, reg); -+} -+ -+void mcp_enable(struct mcp *mcp) -+{ -+ /* -+ * Should we do something here to make sure the aclink -+ * codec is alive??? -+ * A: not for now --NP -+ */ -+} -+ -+void mcp_disable(struct mcp *mcp) -+{ -+} ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/misc/mcp-core.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,235 @@ -+/* -+ * linux/drivers/misc/mcp-core.c -+ * -+ * 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. -+ * -+ * Generic MCP (Multimedia Communications Port) layer. All MCP locking -+ * is solely held within this file. -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "mcp.h" -+ -+#define to_mcp(d) container_of(d, struct mcp, attached_device) -+#define to_mcp_driver(d) container_of(d, struct mcp_driver, drv) -+ -+static int mcp_bus_match(struct device *dev, struct device_driver *drv) -+{ -+ return 1; -+} -+ -+static int mcp_bus_probe(struct device *dev) -+{ -+ struct mcp *mcp = to_mcp(dev); -+ struct mcp_driver *drv = to_mcp_driver(dev->driver); -+ -+ return drv->probe(mcp); -+} -+ -+static int mcp_bus_remove(struct device *dev) -+{ -+ struct mcp *mcp = to_mcp(dev); -+ struct mcp_driver *drv = to_mcp_driver(dev->driver); -+ -+ drv->remove(mcp); -+ return 0; -+} -+ -+static int mcp_bus_suspend(struct device *dev, u32 state) -+{ -+ struct mcp *mcp = to_mcp(dev); -+ int ret = 0; -+ -+ if (dev->driver) { -+ struct mcp_driver *drv = to_mcp_driver(dev->driver); -+ -+ ret = drv->suspend(mcp, state); -+ } -+ return ret; -+} -+ -+static int mcp_bus_resume(struct device *dev) -+{ -+ struct mcp *mcp = to_mcp(dev); -+ int ret = 0; -+ -+ if (dev->driver) { -+ struct mcp_driver *drv = to_mcp_driver(dev->driver); -+ -+ ret = drv->resume(mcp); -+ } -+ return ret; -+} -+ -+static struct bus_type mcp_bus_type = { -+ .name = "mcp", -+ .match = mcp_bus_match, -+ .suspend = mcp_bus_suspend, -+ .resume = mcp_bus_resume, -+}; -+ -+/** -+ * mcp_set_telecom_divisor - set the telecom divisor -+ * @mcp: MCP interface structure -+ * @div: SIB clock divisor -+ * -+ * Set the telecom divisor on the MCP interface. The resulting -+ * sample rate is SIBCLOCK/div. -+ */ -+void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div) -+{ -+ spin_lock_irq(&mcp->lock); -+ mcp->set_telecom_divisor(mcp, div); -+ spin_unlock_irq(&mcp->lock); -+} -+ -+/** -+ * mcp_set_audio_divisor - set the audio divisor -+ * @mcp: MCP interface structure -+ * @div: SIB clock divisor -+ * -+ * Set the audio divisor on the MCP interface. -+ */ -+void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div) -+{ -+ spin_lock_irq(&mcp->lock); -+ mcp->set_audio_divisor(mcp, div); -+ spin_unlock_irq(&mcp->lock); -+} -+ -+/** -+ * mcp_reg_write - write a device register -+ * @mcp: MCP interface structure -+ * @reg: 4-bit register index -+ * @val: 16-bit data value -+ * -+ * Write a device register. The MCP interface must be enabled -+ * to prevent this function hanging. -+ */ -+void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&mcp->lock, flags); -+ mcp->reg_write(mcp, reg, val); -+ spin_unlock_irqrestore(&mcp->lock, flags); -+} -+ -+/** -+ * mcp_reg_read - read a device register -+ * @mcp: MCP interface structure -+ * @reg: 4-bit register index -+ * -+ * Read a device register and return its value. The MCP interface -+ * must be enabled to prevent this function hanging. -+ */ -+unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg) -+{ -+ unsigned long flags; -+ unsigned int val; -+ -+ spin_lock_irqsave(&mcp->lock, flags); -+ val = mcp->reg_read(mcp, reg); -+ spin_unlock_irqrestore(&mcp->lock, flags); -+ -+ return val; -+} -+ -+/** -+ * mcp_enable - enable the MCP interface -+ * @mcp: MCP interface to enable -+ * -+ * Enable the MCP interface. Each call to mcp_enable will need -+ * a corresponding call to mcp_disable to disable the interface. -+ */ -+void mcp_enable(struct mcp *mcp) -+{ -+ spin_lock_irq(&mcp->lock); -+ if (mcp->use_count++ == 0) -+ mcp->enable(mcp); -+ spin_unlock_irq(&mcp->lock); -+} -+ -+/** -+ * mcp_disable - disable the MCP interface -+ * @mcp: MCP interface to disable -+ * -+ * Disable the MCP interface. The MCP interface will only be -+ * disabled once the number of calls to mcp_enable matches the -+ * number of calls to mcp_disable. -+ */ -+void mcp_disable(struct mcp *mcp) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&mcp->lock, flags); -+ if (--mcp->use_count == 0) -+ mcp->disable(mcp); -+ spin_unlock_irqrestore(&mcp->lock, flags); -+} -+ -+int mcp_host_register(struct mcp *mcp, struct device *parent) -+{ -+ mcp->attached_device.parent = parent; -+ mcp->attached_device.bus = &mcp_bus_type; -+ mcp->attached_device.dma_mask = parent->dma_mask; -+ strcpy(mcp->attached_device.bus_id, "mcp0"); -+ return device_register(&mcp->attached_device); -+} -+ -+void mcp_host_unregister(struct mcp *mcp) -+{ -+ device_unregister_wait(&mcp->attached_device); -+} -+ -+int mcp_driver_register(struct mcp_driver *mcpdrv) -+{ -+ mcpdrv->drv.bus = &mcp_bus_type; -+ mcpdrv->drv.probe = mcp_bus_probe; -+ mcpdrv->drv.remove = mcp_bus_remove; -+ return driver_register(&mcpdrv->drv); -+} -+ -+void mcp_driver_unregister(struct mcp_driver *mcpdrv) -+{ -+ driver_unregister(&mcpdrv->drv); -+} -+ -+static int __init mcp_init(void) -+{ -+ return bus_register(&mcp_bus_type); -+} -+ -+static void __exit mcp_exit(void) -+{ -+ bus_unregister(&mcp_bus_type); -+} -+ -+module_init(mcp_init); -+module_exit(mcp_exit); -+ -+EXPORT_SYMBOL(mcp_set_telecom_divisor); -+EXPORT_SYMBOL(mcp_set_audio_divisor); -+EXPORT_SYMBOL(mcp_reg_write); -+EXPORT_SYMBOL(mcp_reg_read); -+EXPORT_SYMBOL(mcp_enable); -+EXPORT_SYMBOL(mcp_disable); -+EXPORT_SYMBOL(mcp_host_register); -+EXPORT_SYMBOL(mcp_host_unregister); -+EXPORT_SYMBOL(mcp_driver_register); -+EXPORT_SYMBOL(mcp_driver_unregister); -+ -+MODULE_AUTHOR("Russell King "); -+MODULE_DESCRIPTION("Core multimedia communications port driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/misc/ucb1x00-ts.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,465 @@ -+/* -+ * linux/drivers/misc/ucb1x00-ts.c -+ * -+ * Copyright (C) 2001 Russell King, 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. -+ * -+ * 21-Jan-2002 : -+ * -+ * Added support for synchronous A/D mode. This mode is useful to -+ * avoid noise induced in the touchpanel by the LCD, provided that -+ * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin. -+ * It is important to note that the signal connected to the ADCSYNC -+ * pin should provide pulses even when the LCD is blanked, otherwise -+ * a pen touch needed to unblank the LCD will never be read. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "ucb1x00.h" -+ -+ -+struct ucb1x00_ts { -+ struct input_dev idev; -+ struct ucb1x00 *ucb; -+ -+ struct semaphore irq_wait; -+ struct semaphore sem; -+ struct completion init_exit; -+ struct task_struct *rtask; -+ int use_count; -+ u16 x_res; -+ u16 y_res; -+ -+ int restart:1; -+ int adcsync:1; -+}; -+ -+static int adcsync = UCB_NOSYNC; -+ -+static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y) -+{ -+ input_report_abs(&ts->idev, ABS_X, x); -+ input_report_abs(&ts->idev, ABS_Y, y); -+ input_report_abs(&ts->idev, ABS_PRESSURE, pressure); -+ input_sync(&ts->idev); -+} -+ -+static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts) -+{ -+ input_report_abs(&ts->idev, ABS_PRESSURE, 0); -+ input_sync(&ts->idev); -+} -+ -+/* -+ * Switch to interrupt mode. -+ */ -+static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts) -+{ -+ if (ts->ucb->id == UCB_ID_1400_BUGGY) -+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | -+ UCB_TS_CR_MODE_INT); -+ else -+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | -+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | -+ UCB_TS_CR_MODE_INT); -+} -+ -+/* -+ * Switch to pressure mode, and read pressure. We don't need to wait -+ * here, since both plates are being driven. -+ */ -+static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts) -+{ -+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | -+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | -+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -+ -+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync); -+} -+ -+/* -+ * Switch to X position mode and measure Y plate. We switch the plate -+ * configuration in pressure mode, then switch to position mode. This -+ * gives a faster response time. Even so, we need to wait about 55us -+ * for things to stabilise. -+ */ -+static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts) -+{ -+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | -+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | -+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | -+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); -+ -+ udelay(55); -+ -+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync); -+} -+ -+/* -+ * Switch to Y position mode and measure X plate. We switch the plate -+ * configuration in pressure mode, then switch to position mode. This -+ * gives a faster response time. Even so, we need to wait about 55us -+ * for things to stabilise. -+ */ -+static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts) -+{ -+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | -+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | -+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | -+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); -+ -+ udelay(55); -+ -+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync); -+} -+ -+/* -+ * Switch to X plate resistance mode. Set MX to ground, PX to -+ * supply. Measure current. -+ */ -+static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts) -+{ -+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | -+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -+ return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync); -+} -+ -+/* -+ * Switch to Y plate resistance mode. Set MY to ground, PY to -+ * supply. Measure current. -+ */ -+static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts) -+{ -+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | -+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -+ return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync); -+} -+ -+/* -+ * This is a RT kernel thread that handles the ADC accesses -+ * (mainly so we can use semaphores in the UCB1200 core code -+ * to serialise accesses to the ADC, and in the UCB1400 case where -+ * any register access may sleep). -+ */ -+static int ucb1x00_thread(void *_ts) -+{ -+ struct ucb1x00_ts *ts = _ts; -+ struct task_struct *tsk = current; -+ int valid; -+ -+ ts->rtask = tsk; -+ -+ daemonize("ktsd"); -+ /* only want to receive SIGKILL */ -+ allow_signal(SIGKILL); -+ -+ /* -+ * We could run as a real-time thread. However, thus far -+ * this doesn't seem to be necessary. -+ */ -+// tsk->policy = SCHED_FIFO; -+// tsk->rt_priority = 1; -+ -+ complete(&ts->init_exit); -+ -+ valid = 0; -+ -+ for (;;) { -+ unsigned int x, y, p, val; -+ -+ ts->restart = 0; -+ -+ ucb1x00_adc_enable(ts->ucb); -+ -+ x = ucb1x00_ts_read_xpos(ts); -+ y = ucb1x00_ts_read_ypos(ts); -+ p = ucb1x00_ts_read_pressure(ts); -+ -+ /* -+ * Switch back to interrupt mode. -+ */ -+ ucb1x00_ts_mode_int(ts); -+ ucb1x00_adc_disable(ts->ucb); -+ -+ set_task_state(tsk, TASK_UNINTERRUPTIBLE); -+ schedule_timeout(HZ / 100); -+ if (signal_pending(tsk)) -+ break; -+ -+ ucb1x00_enable(ts->ucb); -+ val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR); -+ -+ if (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)) { -+ ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING); -+ ucb1x00_disable(ts->ucb); -+ -+ /* -+ * If we spat out a valid sample set last time, -+ * spit out a "pen off" sample here. -+ */ -+ if (valid) { -+ ucb1x00_ts_event_release(ts); -+ valid = 0; -+ } -+ -+ /* -+ * Since ucb1x00_enable_irq() might sleep due -+ * to the way the UCB1400 regs are accessed, we -+ * can't use set_task_state() before that call, -+ * and not changing state before enabling the -+ * interrupt is racy. A semaphore solves all -+ * those issues quite nicely. -+ */ -+ down_interruptible(&ts->irq_wait); -+ } else { -+ ucb1x00_disable(ts->ucb); -+ -+ /* -+ * Filtering is policy. Policy belongs in user -+ * space. We therefore leave it to user space -+ * to do any filtering they please. -+ */ -+ if (!ts->restart) { -+ ucb1x00_ts_evt_add(ts, p, x, y); -+ valid = 1; -+ } -+ -+ set_task_state(tsk, TASK_INTERRUPTIBLE); -+ } -+ -+ schedule_timeout(HZ / 100); -+ if (signal_pending(tsk)) -+ break; -+ } -+ -+ ts->rtask = NULL; -+ complete_and_exit(&ts->init_exit, 0); -+} -+ -+/* -+ * We only detect touch screen _touches_ with this interrupt -+ * handler, and even then we just schedule our task. -+ */ -+static void ucb1x00_ts_irq(int idx, void *id) -+{ -+ struct ucb1x00_ts *ts = id; -+ ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING); -+ up(&ts->irq_wait); -+} -+ -+static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts) -+{ -+ input_report_abs(&ts->idev, ABS_PRESSURE, 0); -+} -+ -+static int ucb1x00_ts_open(struct input_dev *idev) -+{ -+ struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev; -+ int ret = 0; -+ -+ if (down_interruptible(&ts->sem)) -+ return -EINTR; -+ -+ if (ts->use_count++ != 0) -+ goto out; -+ -+ if (ts->rtask) -+ panic("ucb1x00: rtask running?"); -+ -+ sema_init(&ts->irq_wait, 0); -+ ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts); -+ if (ret < 0) -+ goto out; -+ -+ /* -+ * If we do this at all, we should allow the user to -+ * measure and read the X and Y resistance at any time. -+ */ -+ ucb1x00_adc_enable(ts->ucb); -+ ts->x_res = ucb1x00_ts_read_xres(ts); -+ ts->y_res = ucb1x00_ts_read_yres(ts); -+ ucb1x00_adc_disable(ts->ucb); -+ -+ init_completion(&ts->init_exit); -+ ret = kernel_thread(ucb1x00_thread, ts, CLONE_KERNEL); -+ if (ret >= 0) { -+ wait_for_completion(&ts->init_exit); -+ ret = 0; -+ } else { -+ ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); -+ } -+ -+ out: -+ if (ret) -+ ts->use_count--; -+ up(&ts->sem); -+ return ret; -+} -+ -+/* -+ * Release touchscreen resources. Disable IRQs. -+ */ -+static void ucb1x00_ts_close(struct input_dev *idev) -+{ -+ struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev; -+ -+ down(&ts->sem); -+ if (--ts->use_count == 0) { -+ if (ts->rtask) { -+ send_sig(SIGKILL, ts->rtask, 1); -+ wait_for_completion(&ts->init_exit); -+ } -+ -+ ucb1x00_enable(ts->ucb); -+ ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); -+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0); -+ ucb1x00_disable(ts->ucb); -+ } -+ up(&ts->sem); -+} -+ -+#if 0 -+static int ucb1x00_ts_resume(struct device *_dev, u32 level) -+{ -+ struct ucb1x00_device *dev = ucb1x00_dev(_dev); -+ struct ucb1x00_ts *ts = ucb1x00_get_drvdata(dev); -+ -+ if (level == RESUME_ENABLE && ts->rtask != NULL) { -+ /* -+ * Restart the TS thread to ensure the -+ * TS interrupt mode is set up again -+ * after sleep. -+ */ -+ ts->restart = 1; -+ up(&ts->irq_wait); -+ } -+ return 0; -+} -+#endif -+ -+ -+/* -+ * Initialisation. -+ */ -+static int ucb1x00_ts_add(struct class_device *dev) -+{ -+ struct ucb1x00 *ucb = classdev_to_ucb1x00(dev); -+ struct ucb1x00_ts *ts; -+ -+ ts = kmalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL); -+ if (!ts) -+ return -ENOMEM; -+ -+ memset(ts, 0, sizeof(struct ucb1x00_ts)); -+ -+ ts->ucb = ucb; -+ ts->adcsync = adcsync; -+ init_MUTEX(&ts->sem); -+ -+ ts->idev.name = "Touchscreen panel"; -+ ts->idev.id.product = ts->ucb->id; -+ ts->idev.open = ucb1x00_ts_open; -+ ts->idev.close = ucb1x00_ts_close; -+ -+ __set_bit(EV_ABS, ts->idev.evbit); -+ __set_bit(ABS_X, ts->idev.absbit); -+ __set_bit(ABS_Y, ts->idev.absbit); -+ __set_bit(ABS_PRESSURE, ts->idev.absbit); -+ -+ input_register_device(&ts->idev); -+ -+ ucb->ts_data = ts; -+ -+ return 0; -+} -+ -+static void ucb1x00_ts_remove(struct class_device *dev) -+{ -+ struct ucb1x00 *ucb = classdev_to_ucb1x00(dev); -+ struct ucb1x00_ts *ts = ucb->ts_data; -+ -+ input_unregister_device(&ts->idev); -+ kfree(ts); -+} -+ -+static struct class_interface ucb1x00_ts_interface = { -+ .add = ucb1x00_ts_add, -+ .remove = ucb1x00_ts_remove, -+}; -+ -+static int __init ucb1x00_ts_init(void) -+{ -+ return ucb1x00_register_interface(&ucb1x00_ts_interface); -+} -+ -+static void __exit ucb1x00_ts_exit(void) -+{ -+ ucb1x00_unregister_interface(&ucb1x00_ts_interface); -+} -+ -+#ifndef MODULE -+ -+/* -+ * Parse kernel command-line options. -+ * -+ * syntax : ucbts=[sync|nosync],... -+ */ -+static int __init ucb1x00_ts_setup(char *str) -+{ -+ char *p; -+ -+ while ((p = strsep(&str, ",")) != NULL) { -+ if (strcmp(p, "sync") == 0) -+ adcsync = UCB_SYNC; -+ } -+ -+ return 1; -+} -+ -+__setup("ucbts=", ucb1x00_ts_setup); -+ -+#else -+ -+MODULE_PARM(adcsync, "i"); -+MODULE_PARM_DESC(adcsync, "Enable use of ADCSYNC signal"); -+ -+#endif -+ -+module_init(ucb1x00_ts_init); -+module_exit(ucb1x00_ts_exit); -+ -+MODULE_AUTHOR("Russell King "); -+MODULE_DESCRIPTION("UCB1x00 touchscreen driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/misc/ucb1x00-core.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,624 @@ -+/* -+ * linux/drivers/misc/ucb1x00-core.c -+ * -+ * Copyright (C) 2001 Russell King, 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. -+ * -+ * The UCB1x00 core driver provides basic services for handling IO, -+ * the ADC, interrupts, and accessing registers. It is designed -+ * such that everything goes through this layer, thereby providing -+ * a consistent locking methodology, as well as allowing the drivers -+ * to be used on other non-MCP-enabled hardware platforms. -+ * -+ * Note that all locks are private to this file. Nothing else may -+ * touch them. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "ucb1x00.h" -+ -+/** -+ * ucb1x00_io_set_dir - set IO direction -+ * @ucb: UCB1x00 structure describing chip -+ * @in: bitfield of IO pins to be set as inputs -+ * @out: bitfield of IO pins to be set as outputs -+ * -+ * Set the IO direction of the ten general purpose IO pins on -+ * the UCB1x00 chip. The @in bitfield has priority over the -+ * @out bitfield, in that if you specify a pin as both input -+ * and output, it will end up as an input. -+ * -+ * ucb1x00_enable must have been called to enable the comms -+ * before using this function. -+ * -+ * This function takes a spinlock, disabling interrupts. -+ */ -+void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int in, unsigned int out) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ucb->io_lock, flags); -+ ucb->io_dir |= out; -+ ucb->io_dir &= ~in; -+ -+ ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); -+ spin_unlock_irqrestore(&ucb->io_lock, flags); -+} -+ -+/** -+ * ucb1x00_io_write - set or clear IO outputs -+ * @ucb: UCB1x00 structure describing chip -+ * @set: bitfield of IO pins to set to logic '1' -+ * @clear: bitfield of IO pins to set to logic '0' -+ * -+ * Set the IO output state of the specified IO pins. The value -+ * is retained if the pins are subsequently configured as inputs. -+ * The @clear bitfield has priority over the @set bitfield - -+ * outputs will be cleared. -+ * -+ * ucb1x00_enable must have been called to enable the comms -+ * before using this function. -+ * -+ * This function takes a spinlock, disabling interrupts. -+ */ -+void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ucb->io_lock, flags); -+ ucb->io_out |= set; -+ ucb->io_out &= ~clear; -+ -+ ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); -+ spin_unlock_irqrestore(&ucb->io_lock, flags); -+} -+ -+/** -+ * ucb1x00_io_read - read the current state of the IO pins -+ * @ucb: UCB1x00 structure describing chip -+ * -+ * Return a bitfield describing the logic state of the ten -+ * general purpose IO pins. -+ * -+ * ucb1x00_enable must have been called to enable the comms -+ * before using this function. -+ * -+ * This function does not take any semaphores or spinlocks. -+ */ -+unsigned int ucb1x00_io_read(struct ucb1x00 *ucb) -+{ -+ return ucb1x00_reg_read(ucb, UCB_IO_DATA); -+} -+ -+/* -+ * UCB1300 data sheet says we must: -+ * 1. enable ADC => 5us (including reference startup time) -+ * 2. select input => 51*tsibclk => 4.3us -+ * 3. start conversion => 102*tsibclk => 8.5us -+ * (tsibclk = 1/11981000) -+ * Period between SIB 128-bit frames = 10.7us -+ */ -+ -+/** -+ * ucb1x00_adc_enable - enable the ADC converter -+ * @ucb: UCB1x00 structure describing chip -+ * -+ * Enable the ucb1x00 and ADC converter on the UCB1x00 for use. -+ * Any code wishing to use the ADC converter must call this -+ * function prior to using it. -+ * -+ * This function takes the ADC semaphore to prevent two or more -+ * concurrent uses, and therefore may sleep. As a result, it -+ * can only be called from process context, not interrupt -+ * context. -+ * -+ * You should release the ADC as soon as possible using -+ * ucb1x00_adc_disable. -+ */ -+void ucb1x00_adc_enable(struct ucb1x00 *ucb) -+{ -+ down(&ucb->adc_sem); -+ -+ ucb->adc_cr |= UCB_ADC_ENA; -+ -+ ucb1x00_enable(ucb); -+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr); -+} -+ -+/** -+ * ucb1x00_adc_read - read the specified ADC channel -+ * @ucb: UCB1x00 structure describing chip -+ * @adc_channel: ADC channel mask -+ * @sync: wait for syncronisation pulse. -+ * -+ * Start an ADC conversion and wait for the result. Note that -+ * synchronised ADC conversions (via the ADCSYNC pin) must wait -+ * until the trigger is asserted and the conversion is finished. -+ * -+ * This function currently spins waiting for the conversion to -+ * complete (2 frames max without sync). -+ * -+ * If called for a synchronised ADC conversion, it may sleep -+ * with the ADC semaphore held. -+ * -+ * See ucb1x00.h for definition of the UCB_ADC_DAT macro. It -+ * addresses a bug in the ucb1200/1300 which, of course, Philips -+ * decided to finally fix in the ucb1400 ;-) -jws -+ */ -+unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync) -+{ -+ unsigned int val; -+ -+ if (sync) -+ adc_channel |= UCB_ADC_SYNC_ENA; -+ -+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel); -+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel | UCB_ADC_START); -+ -+ for (;;) { -+ val = ucb1x00_reg_read(ucb, UCB_ADC_DATA); -+ if (val & UCB_ADC_DAT_VAL) -+ break; -+ /* yield to other processes */ -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(1); -+ } -+ -+ return UCB_ADC_DAT(val); -+} -+ -+/** -+ * ucb1x00_adc_disable - disable the ADC converter -+ * @ucb: UCB1x00 structure describing chip -+ * -+ * Disable the ADC converter and release the ADC semaphore. -+ */ -+void ucb1x00_adc_disable(struct ucb1x00 *ucb) -+{ -+ ucb->adc_cr &= ~UCB_ADC_ENA; -+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr); -+ ucb1x00_disable(ucb); -+ -+ up(&ucb->adc_sem); -+} -+ -+/* -+ * UCB1x00 Interrupt handling. -+ * -+ * The UCB1x00 can generate interrupts when the SIBCLK is stopped. -+ * Since we need to read an internal register, we must re-enable -+ * SIBCLK to talk to the chip. We leave the clock running until -+ * we have finished processing all interrupts from the chip. -+ * -+ * A restriction with interrupts exists when using the ucb1400, as -+ * the codec read/write routines may sleep while waiting for codec -+ * access completion and uses semaphores for access control to the -+ * AC97 bus. A complete codec read cycle could take anywhere from -+ * 60 to 100uSec so we *definitely* don't want to spin inside the -+ * interrupt handler waiting for codec access. So, we handle the -+ * interrupt by scheduling a RT kernel thread to run in process -+ * context instead of interrupt context. -+ */ -+ -+static int ucb1x00_thread(void *_ucb) -+{ -+ struct task_struct *tsk = current; -+ DECLARE_WAITQUEUE(wait, tsk); -+ struct ucb1x00 *ucb = _ucb; -+ struct ucb1x00_irq *irq; -+ unsigned int isr, i; -+ -+ ucb->rtask = tsk; -+ -+ daemonize(); -+ reparent_to_init(); -+ tsk->tty = NULL; -+ tsk->policy = SCHED_FIFO; -+ tsk->rt_priority = 1; -+ strcpy(tsk->comm, "kUCB1x00d"); -+ -+ /* only want to receive SIGKILL */ -+ spin_lock_irq(&tsk->sigmask_lock); -+ siginitsetinv(&tsk->blocked, sigmask(SIGKILL)); -+ recalc_sigpending(); -+ spin_unlock_irq(&tsk->sigmask_lock); -+ -+ add_wait_queue(&ucb->irq_wait, &wait); -+ set_task_state(tsk, TASK_INTERRUPTIBLE); -+ complete(&ucb->complete); -+ -+ for (;;) { -+ if (signal_pending(tsk)) -+ break; -+ enable_irq(ucb->irq); -+ schedule(); -+ -+ ucb1x00_enable(ucb); -+ isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS); -+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr); -+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); -+ -+ for (i = 0, irq = ucb->irq_handler; -+ i < 16 && isr; -+ i++, isr >>= 1, irq++) -+ if (isr & 1 && irq->fn) -+ irq->fn(i, irq->devid); -+ ucb1x00_disable(ucb); -+ -+ set_task_state(tsk, TASK_INTERRUPTIBLE); -+ } -+ -+ remove_wait_queue(&ucb->irq_wait, &wait); -+ ucb->rtask = NULL; -+ complete_and_exit(&ucb->complete, 0); -+} -+ -+static irqreturn_t ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs) -+{ -+ struct ucb1x00 *ucb = devid; -+ disable_irq(irqnr); -+ wake_up(&ucb->irq_wait); -+ return IRQ_HANDLED; -+} -+ -+/** -+ * ucb1x00_hook_irq - hook a UCB1x00 interrupt -+ * @ucb: UCB1x00 structure describing chip -+ * @idx: interrupt index -+ * @fn: function to call when interrupt is triggered -+ * @devid: device id to pass to interrupt handler -+ * -+ * Hook the specified interrupt. You can only register one handler -+ * for each interrupt source. The interrupt source is not enabled -+ * by this function; use ucb1x00_enable_irq instead. -+ * -+ * Interrupt handlers will be called with other interrupts enabled. -+ * -+ * Returns zero on success, or one of the following errors: -+ * -EINVAL if the interrupt index is invalid -+ * -EBUSY if the interrupt has already been hooked -+ */ -+int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid) -+{ -+ struct ucb1x00_irq *irq; -+ int ret = -EINVAL; -+ -+ if (idx < 16) { -+ irq = ucb->irq_handler + idx; -+ ret = -EBUSY; -+ -+ spin_lock_irq(&ucb->lock); -+ if (irq->fn == NULL) { -+ irq->devid = devid; -+ irq->fn = fn; -+ ret = 0; -+ } -+ spin_unlock_irq(&ucb->lock); -+ } -+ return ret; -+} -+ -+/** -+ * ucb1x00_enable_irq - enable an UCB1x00 interrupt source -+ * @ucb: UCB1x00 structure describing chip -+ * @idx: interrupt index -+ * @edges: interrupt edges to enable -+ * -+ * Enable the specified interrupt to trigger on %UCB_RISING, -+ * %UCB_FALLING or both edges. The interrupt should have been -+ * hooked by ucb1x00_hook_irq. -+ */ -+void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges) -+{ -+ unsigned long flags; -+ -+ if (idx < 16) { -+ spin_lock_irqsave(&ucb->lock, flags); -+ -+ ucb1x00_enable(ucb); -+ -+ /* This prevents spurious interrupts on the UCB1400 */ -+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 1 << idx); -+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); -+ -+ if (edges & UCB_RISING) { -+ ucb->irq_ris_enbl |= 1 << idx; -+ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); -+ } -+ if (edges & UCB_FALLING) { -+ ucb->irq_fal_enbl |= 1 << idx; -+ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); -+ } -+ ucb1x00_disable(ucb); -+ spin_unlock_irqrestore(&ucb->lock, flags); -+ } -+} -+ -+/** -+ * ucb1x00_disable_irq - disable an UCB1x00 interrupt source -+ * @ucb: UCB1x00 structure describing chip -+ * @edges: interrupt edges to disable -+ * -+ * Disable the specified interrupt triggering on the specified -+ * (%UCB_RISING, %UCB_FALLING or both) edges. -+ */ -+void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges) -+{ -+ unsigned long flags; -+ -+ if (idx < 16) { -+ spin_lock_irqsave(&ucb->lock, flags); -+ -+ ucb1x00_enable(ucb); -+ if (edges & UCB_RISING) { -+ ucb->irq_ris_enbl &= ~(1 << idx); -+ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); -+ } -+ if (edges & UCB_FALLING) { -+ ucb->irq_fal_enbl &= ~(1 << idx); -+ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); -+ } -+ ucb1x00_disable(ucb); -+ spin_unlock_irqrestore(&ucb->lock, flags); -+ } -+} -+ -+/** -+ * ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt -+ * @ucb: UCB1x00 structure describing chip -+ * @idx: interrupt index -+ * @devid: device id. -+ * -+ * Disable the interrupt source and remove the handler. devid must -+ * match the devid passed when hooking the interrupt. -+ * -+ * Returns zero on success, or one of the following errors: -+ * -EINVAL if the interrupt index is invalid -+ * -ENOENT if devid does not match -+ */ -+int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid) -+{ -+ struct ucb1x00_irq *irq; -+ int ret; -+ -+ if (idx >= 16) -+ goto bad; -+ -+ irq = ucb->irq_handler + idx; -+ ret = -ENOENT; -+ -+ spin_lock_irq(&ucb->lock); -+ if (irq->devid == devid) { -+ ucb->irq_ris_enbl &= ~(1 << idx); -+ ucb->irq_fal_enbl &= ~(1 << idx); -+ -+ ucb1x00_enable(ucb); -+ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); -+ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); -+ ucb1x00_disable(ucb); -+ -+ irq->fn = NULL; -+ irq->devid = NULL; -+ ret = 0; -+ } -+ spin_unlock_irq(&ucb->lock); -+ return ret; -+ -+bad: -+ printk(KERN_ERR "Freeing bad UCB1x00 irq %d\n", idx); -+ return -EINVAL; -+} -+ -+/* -+ * Try to probe our interrupt, rather than relying on lots of -+ * hard-coded machine dependencies. For reference, the expected -+ * IRQ mappings are: -+ * -+ * Machine Default IRQ -+ * adsbitsy IRQ_GPCIN4 -+ * cerf IRQ_GPIO_UCB1200_IRQ -+ * flexanet IRQ_GPIO_GUI -+ * freebird IRQ_GPIO_FREEBIRD_UCB1300_IRQ -+ * graphicsclient ADS_EXT_IRQ(8) -+ * graphicsmaster ADS_EXT_IRQ(8) -+ * lart LART_IRQ_UCB1200 -+ * omnimeter IRQ_GPIO23 -+ * pfs168 IRQ_GPIO_UCB1300_IRQ -+ * simpad IRQ_GPIO_UCB1300_IRQ -+ * shannon SHANNON_IRQ_GPIO_IRQ_CODEC -+ * yopy IRQ_GPIO_UCB1200_IRQ -+ */ -+static int ucb1x00_detect_irq(struct ucb1x00 *ucb) -+{ -+ unsigned long mask; -+ -+ mask = probe_irq_on(); -+ if (!mask) -+ return NO_IRQ; -+ -+ /* -+ * Enable the ADC interrupt. -+ */ -+ ucb1x00_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC); -+ ucb1x00_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC); -+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff); -+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); -+ -+ /* -+ * Cause an ADC interrupt. -+ */ -+ ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA); -+ ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START); -+ -+ /* -+ * Wait for the conversion to complete. -+ */ -+ while ((ucb1x00_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VAL) == 0); -+ ucb1x00_reg_write(ucb, UCB_ADC_CR, 0); -+ -+ /* -+ * Disable and clear interrupt. -+ */ -+ ucb1x00_reg_write(ucb, UCB_IE_RIS, 0); -+ ucb1x00_reg_write(ucb, UCB_IE_FAL, 0); -+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff); -+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); -+ -+ /* -+ * Read triggered interrupt. -+ */ -+ return probe_irq_off(mask); -+} -+ -+static int ucb1x00_probe(struct mcp *mcp) -+{ -+ struct ucb1x00 *ucb; -+ unsigned int id; -+ int ret = -ENODEV; -+ -+ mcp_enable(mcp); -+ id = mcp_reg_read(mcp, UCB_ID); -+ -+ if (id != UCB_ID_1200 && id != UCB_ID_1300) { -+ printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id); -+ goto err_disable; -+ } -+ -+ ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL); -+ ret = -ENOMEM; -+ if (!ucb) -+ goto err_disable; -+ -+ memset(ucb, 0, sizeof(struct ucb1x00)); -+ -+ ucb->cdev.class = &ucb1x00_class; -+ ucb->cdev.dev = &mcp->attached_device; -+ strlcpy(ucb->cdev.class_id, "ucb1x00", sizeof(ucb->cdev.class_id)); -+ -+ spin_lock_init(&ucb->lock); -+ spin_lock_init(&ucb->io_lock); -+ sema_init(&ucb->adc_sem, 1); -+ -+ ucb->id = id; -+ ucb->mcp = mcp; -+ ucb->irq = ucb1x00_detect_irq(ucb); -+ if (ucb->irq == NO_IRQ) { -+ printk(KERN_ERR "UCB1x00: IRQ probe failed\n"); -+ ret = -ENODEV; -+ goto err_free; -+ } -+ -+ ret = request_irq(ucb->irq, ucb1x00_irq, 0, "UCB1x00", ucb); -+ if (ret) { -+ printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", -+ ucb->irq, ret); -+ goto err_free; -+ } -+ -+ set_irq_type(ucb->irq, IRQT_RISING); -+ mcp_set_drvdata(mcp, ucb); -+ -+ ret = class_device_register(&ucb->cdev); -+ if (ret) { -+ free_irq(ucb->irq, ucb); -+ err_free: -+ kfree(ucb); -+ } -+ err_disable: -+ mcp_disable(mcp); -+ return ret; -+} -+ -+static void ucb1x00_remove(struct mcp *mcp) -+{ -+ struct ucb1x00 *ucb = mcp_get_drvdata(mcp); -+ -+ class_device_unregister(&ucb->cdev); -+ free_irq(ucb->irq, ucb); -+} -+ -+static void ucb1x00_release(struct class_device *dev) -+{ -+ struct ucb1x00 *ucb = classdev_to_ucb1x00(dev); -+ kfree(ucb); -+} -+ -+static struct class ucb1x00_class = { -+ .name = "ucb1x00", -+ .release = ucb1x00_release, -+}; -+ -+int ucb1x00_register_interface(struct class_interface *intf) -+{ -+ intf->class = &ucb1x00_class; -+ return class_interface_register(intf); -+} -+ -+void ucb1x00_unregister_interface(struct class_interface *intf) -+{ -+ class_interface_unregister(intf); -+} -+ -+static struct mcp_driver ucb1x00_driver = { -+ .drv = { -+ .name = "ucb1x00", -+ }, -+ .probe = ucb1x00_probe, -+ .remove = ucb1x00_remove, -+}; -+ -+static int __init ucb1x00_init(void) -+{ -+ int ret = class_register(&ucb1x00_class); -+ if (ret == 0) { -+ ret = mcp_driver_register(&ucb1x00_driver); -+ if (ret) -+ class_unregister(&ucb1x00_class); -+ } -+ return ret; -+} -+ -+static void __exit ucb1x00_exit(void) -+{ -+ mcp_driver_unregister(&ucb1x00_driver); -+ class_unregister(&ucb1x00_class); -+} -+ -+module_init(ucb1x00_init); -+module_exit(ucb1x00_exit); -+ -+EXPORT_SYMBOL(ucb1x00_class); -+ -+EXPORT_SYMBOL(ucb1x00_io_set_dir); -+EXPORT_SYMBOL(ucb1x00_io_write); -+EXPORT_SYMBOL(ucb1x00_io_read); -+ -+EXPORT_SYMBOL(ucb1x00_adc_enable); -+EXPORT_SYMBOL(ucb1x00_adc_read); -+EXPORT_SYMBOL(ucb1x00_adc_disable); -+ -+EXPORT_SYMBOL(ucb1x00_hook_irq); -+EXPORT_SYMBOL(ucb1x00_free_irq); -+EXPORT_SYMBOL(ucb1x00_enable_irq); -+EXPORT_SYMBOL(ucb1x00_disable_irq); -+ -+EXPORT_SYMBOL(ucb1x00_register_interface); -+EXPORT_SYMBOL(ucb1x00_unregister_interface); -+ -+MODULE_AUTHOR("Russell King "); -+MODULE_DESCRIPTION("UCB1x00 core driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/misc/switches-ucb1x00.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,214 @@ -+/* -+ * linux/drivers/misc/switches-ucb1x00.c -+ * -+ * Copyright (C) 2001 John Dorsey -+ * -+ * 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. -+ * -+ * 19 December 2001 - created from sa1100_switches.c. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_SA1100_ASSABET -+#include -+#endif -+ -+#include "switches.h" -+#include "ucb1x00.h" -+ -+ -+static void switches_ucb1x00_handler(int irq, void *devid); -+ -+ -+#ifdef CONFIG_SA1100_ASSABET -+ -+/* Assabet -+ * ^^^^^^^ -+ * Six switches are routed to GPIO pins on the UCB1300: S3 -- S8. -+ * This code sets bits in the range [3, 8] in the mask that we -+ * return to userland. Note that we transpose signals SW7 and SW8; -+ * see assabet_switches_ucb1x00_handler(). -+ */ -+ -+static int assabet_switches_ucb1x00_init(struct ucb1x00 *ucb) -+{ -+ int i; -+ -+ ucb1x00_enable(ucb); -+ -+ ucb1x00_io_set_dir(ucb, -+ UCB_IO_0 | UCB_IO_1 | UCB_IO_2 | -+ UCB_IO_3 | UCB_IO_4 | UCB_IO_5, 0); -+ -+ for (i = 0; i < 6; ++i) { -+ ucb1x00_enable_irq(ucb, i, UCB_RISING | UCB_FALLING); -+ -+ if (ucb1x00_hook_irq(ucb, i, -+ switches_ucb1x00_handler, ucb) < 0) { -+ printk(KERN_ERR "%s: unable to hook IRQ for " -+ "UCB1300 IO_%d\n", SWITCHES_NAME, i); -+ -+ /* FIXME: BUGGY ERROR HANDLING */ -+ return -EBUSY; -+ } -+ -+ } -+ -+ ucb1x00_disable(ucb); -+ -+ return 0; -+ -+} -+ -+static void assabet_switches_ucb1x00_shutdown(struct ucb1x00 *ucb) -+{ -+ int i; -+ -+ ucb1x00_enable(ucb); -+ -+ for (i = 5; i >= 0; --i) { -+ ucb1x00_disable_irq(ucb, i, UCB_RISING | UCB_FALLING); -+ -+ /* Only error conditions are ENOENT and EINVAL; silently -+ * ignore: -+ */ -+ ucb1x00_free_irq(ucb, i, ucb); -+ } -+ -+ ucb1x00_disable(ucb); -+} -+ -+static void assabet_switches_ucb1x00_handler(struct ucb1x00 *ucb, int irq, switches_mask_t *mask) -+{ -+ unsigned int last, this; -+ static unsigned int states = 0; -+ -+ last = ((states & (1 << irq)) != 0); -+ this = ((ucb1x00_io_read(ucb) & (1 << irq)) != 0); -+ -+ if (last == this) /* debounce */ -+ return; -+ -+ /* Intel StrongARM SA-1110 Development Board -+ * Schematics Figure 5, Sheet 5 of 12 -+ * -+ * See switches S8 and S7. Notice their -+ * relationship to signals SW7 and SW8. Hmmm. -+ */ -+ -+ switch (irq) { -+ -+ case 4: -+ -+ SWITCHES_SET(mask, 8, this); -+ break; -+ -+ case 5: -+ -+ SWITCHES_SET(mask, 7, this); -+ break; -+ -+ default: -+ -+ SWITCHES_SET(mask, irq + 3, this); -+ -+ } -+ -+ states = this ? (states | (1 << irq)) : (states & ~(1 << irq)); -+ -+} -+#endif /* CONFIG_SA1100_ASSABET */ -+ -+ -+/* switches_ucb1x00_handler() -+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^ -+ * This routine is a generalized handler for UCB1x00 GPIO switches -+ * which calls a board-specific service routine and passes an event -+ * mask to the core event handler. This routine is appropriate for -+ * systems which use the ucb1x00 framework, and can be registered -+ * using ucb1x00_hook_irq(). -+ */ -+static void switches_ucb1x00_handler(int irq, void *devid) -+{ -+ struct ucb1x00 *ucb = devid; -+ switches_mask_t mask; -+ -+ SWITCHES_ZERO(&mask); -+ -+ /* Porting note: call a board-specific UCB1x00 switch handler here. -+ * The handler can assume that sufficient storage for `mask' has -+ * been allocated, and that the corresponding switches_mask_t -+ * structure has been zeroed. -+ */ -+ -+#ifdef CONFIG_SA1100_ASSABET -+ if (machine_is_assabet()) { -+ assabet_switches_ucb1x00_handler(ucb, irq, &mask); -+ } -+#endif -+ -+ switches_event(&mask); -+} -+ -+static int switches_add(struct class_device *dev) -+{ -+ struct ucb1x00 *ucb = classdev_to_ucb1x00(dev); -+ int ret = -ENODEV; -+ -+#ifdef CONFIG_SA1100_ASSABET -+ if (machine_is_assabet()) { -+ ret = assabet_switches_ucb1x00_init(ucb); -+ } -+#endif -+ /* Porting note: call a board-specific init routine here. */ -+ -+ return ret; -+} -+ -+static void switches_remove(struct class_device *dev) -+{ -+ struct ucb1x00 *ucb = classdev_to_ucb1x00(dev); -+ -+ /* Porting note: call a board-specific shutdown routine here. */ -+ -+#ifdef CONFIG_SA1100_ASSABET -+ if (machine_is_assabet()) { -+ assabet_switches_ucb1x00_shutdown(ucb); -+ } -+#endif -+} -+ -+static struct class_interface ucb1x00_switches_interface = { -+ .add = switches_add, -+ .remove = switches_remove, -+}; -+ -+static int __init switches_ucb1x00_init(void) -+{ -+ return ucb1x00_register_interface(&ucb1x00_switches_interface); -+} -+ -+static void __exit switches_ucb1x00_exit(void) -+{ -+ ucb1x00_unregister_interface(&ucb1x00_switches_interface); -+} -+ -+module_init(switches_ucb1x00_init); -+module_exit(switches_ucb1x00_exit); -+ -+MODULE_DESCRIPTION("ucb1x00 switches driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/misc/switches-core.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,200 @@ -+/* -+ * linux/drivers/misc/switches-core.c -+ * -+ * Copyright (C) 2000-2001 John Dorsey -+ * -+ * 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. -+ * -+ * 5 October 2000 - created. -+ * -+ * 25 October 2000 - userland file interface added. -+ * -+ * 13 January 2001 - added support for Spot. -+ * -+ * 11 September 2001 - UCB1200 driver framework support added. -+ * -+ * 19 December 2001 - separated out SA-1100 and UCB1x00 code. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "switches.h" -+ -+ -+MODULE_AUTHOR("John Dorsey"); -+MODULE_DESCRIPTION("Console switch support"); -+MODULE_LICENSE("GPL"); -+ -+ -+struct switches_action { -+ struct list_head list; -+ switches_mask_t mask; -+}; -+ -+ -+static int switches_users = 0; -+ -+static spinlock_t switches_lock = SPIN_LOCK_UNLOCKED; -+ -+DECLARE_WAIT_QUEUE_HEAD(switches_wait); -+LIST_HEAD(switches_event_queue); -+ -+ -+static ssize_t switches_read(struct file *file, char *buffer, -+ size_t count, loff_t *pos) -+{ -+ unsigned long flags; -+ struct list_head *event; -+ struct switches_action *action; -+ -+ if (count < sizeof(struct switches_mask_t)) -+ return -EINVAL; -+ -+ while (list_empty(&switches_event_queue)) { -+ -+ if (file->f_flags & O_NDELAY) -+ return -EAGAIN; -+ -+ interruptible_sleep_on(&switches_wait); -+ -+ if (signal_pending(current)) -+ return -ERESTARTSYS; -+ -+ } -+ -+ if (verify_area(VERIFY_WRITE, buffer, sizeof(struct switches_mask_t))) -+ return -EFAULT; -+ -+ spin_lock_irqsave(&switches_lock, flags); -+ -+ event = switches_event_queue.next; -+ action = list_entry(event, struct switches_action, list); -+ copy_to_user(buffer, &(action->mask), sizeof(struct switches_mask_t)); -+ list_del(event); -+ kfree(action); -+ -+ spin_unlock_irqrestore(&switches_lock, flags); -+ -+ return 0; -+ -+} -+ -+static ssize_t switches_write(struct file *file, const char *buffer, -+ size_t count, loff_t *ppos) -+{ -+ return -EINVAL; -+} -+ -+static unsigned int switches_poll(struct file *file, poll_table *wait) -+{ -+ -+ poll_wait(file, &switches_wait, wait); -+ -+ if (!list_empty(&switches_event_queue)) -+ return POLLIN | POLLRDNORM; -+ -+ return 0; -+ -+} -+ -+static int switches_open(struct inode *inode, struct file *file) -+{ -+ -+ if (switches_users > 0) -+ return -EBUSY; -+ -+ ++switches_users; -+ return 0; -+ -+} -+ -+static int switches_release(struct inode *inode, struct file *file) -+{ -+ -+ --switches_users; -+ return 0; -+ -+} -+ -+static struct file_operations switches_ops = { -+ .owner = THIS_MODULE, -+ .read = switches_read, -+ .write = switches_write, -+ .poll = switches_poll, -+ .open = switches_open, -+ .release = switches_release, -+}; -+ -+static struct miscdevice switches_misc = { -+ .minor = MISC_DYNAMIC_MINOR, -+ .name = SWITCHES_NAME, -+ .fops = &switches_ops, -+}; -+ -+int switches_event(switches_mask_t *mask) -+{ -+ struct switches_action *action; -+ -+ if ((switches_users > 0) && (SWITCHES_COUNT(mask) > 0)) { -+ -+ if ((action = (struct switches_action *) -+ kmalloc(sizeof(struct switches_action), -+ GFP_KERNEL)) == NULL) { -+ printk(KERN_ERR "%s: unable to allocate action " -+ "descriptor\n", SWITCHES_NAME); -+ return -1; -+ } -+ -+ action->mask = *mask; -+ -+ spin_lock(&switches_lock); -+ list_add_tail(&action->list, &switches_event_queue); -+ spin_unlock(&switches_lock); -+ -+ wake_up_interruptible(&switches_wait); -+ -+ } -+ -+ return 0; -+ -+} -+ -+EXPORT_SYMBOL(switches_event); -+ -+ -+static int __init switches_init(void) -+{ -+ if (misc_register(&switches_misc) < 0) { -+ printk(KERN_ERR "%s: unable to register misc device\n", -+ SWITCHES_NAME); -+ return -EIO; -+ } -+ -+ printk(KERN_INFO "Console switches initialized\n"); -+ -+ return 0; -+} -+ -+static void __exit switches_exit(void) -+{ -+ if (misc_deregister(&switches_misc) < 0) -+ printk(KERN_ERR "%s: unable to deregister misc device\n", -+ SWITCHES_NAME); -+} -+ -+module_init(switches_init); -+module_exit(switches_exit); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/misc/ucb1x00-audio.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,439 @@ -+/* -+ * linux/drivers/misc/ucb1x00-audio.c -+ * -+ * Copyright (C) 2001 Russell King, 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. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "ucb1x00.h" -+ -+#include "../sound/oss/sa1100-audio.h" -+ -+#define MAGIC 0x41544154 -+ -+struct ucb1x00_audio { -+ struct file_operations fops; -+ struct file_operations mops; -+ struct ucb1x00 *ucb; -+ audio_stream_t output_stream; -+ audio_stream_t input_stream; -+ audio_state_t state; -+ unsigned int rate; -+ int dev_id; -+ int mix_id; -+ unsigned int daa_oh_bit; -+ unsigned int telecom; -+ unsigned int magic; -+ unsigned int ctrl_a; -+ unsigned int ctrl_b; -+ -+ /* mixer info */ -+ unsigned int mod_cnt; -+ unsigned short output_level; -+ unsigned short input_level; -+}; -+ -+#define REC_MASK (SOUND_MASK_VOLUME | SOUND_MASK_MIC) -+#define DEV_MASK REC_MASK -+ -+static int -+ucb1x00_mixer_ioctl(struct inode *ino, struct file *filp, uint cmd, ulong arg) -+{ -+ struct ucb1x00_audio *ucba; -+ unsigned int val, gain; -+ int ret = 0; -+ -+ ucba = list_entry(filp->f_op, struct ucb1x00_audio, mops); -+ -+ if (_IOC_TYPE(cmd) != 'M') -+ return -EINVAL; -+ -+ if (cmd == SOUND_MIXER_INFO) { -+ struct mixer_info mi; -+ -+ strncpy(mi.id, "UCB1x00", sizeof(mi.id)); -+ strncpy(mi.name, "Philips UCB1x00", sizeof(mi.name)); -+ mi.modify_counter = ucba->mod_cnt; -+ return copy_to_user((void *)arg, &mi, sizeof(mi)) ? -EFAULT : 0; -+ } -+ -+ if (_IOC_DIR(cmd) & _IOC_WRITE) { -+ unsigned int left, right; -+ -+ ret = get_user(val, (unsigned int *)arg); -+ if (ret) -+ goto out; -+ -+ left = val & 255; -+ right = val >> 8; -+ -+ if (left > 100) -+ left = 100; -+ if (right > 100) -+ right = 100; -+ -+ gain = (left + right) / 2; -+ -+ ret = -EINVAL; -+ if (!ucba->telecom) { -+ switch(_IOC_NR(cmd)) { -+ case SOUND_MIXER_VOLUME: -+ ucba->output_level = gain | gain << 8; -+ ucba->mod_cnt++; -+ ucba->ctrl_b = (ucba->ctrl_b & 0xff00) | -+ ((gain * 31) / 100); -+ ucb1x00_reg_write(ucba->ucb, UCB_AC_B, -+ ucba->ctrl_b); -+ ret = 0; -+ break; -+ -+ case SOUND_MIXER_MIC: -+ ucba->input_level = gain | gain << 8; -+ ucba->mod_cnt++; -+ ucba->ctrl_a = (ucba->ctrl_a & 0x7f) | -+ (((gain * 31) / 100) << 7); -+ ucb1x00_reg_write(ucba->ucb, UCB_AC_A, -+ ucba->ctrl_a); -+ ret = 0; -+ break; -+ } -+ } -+ } -+ -+ if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) { -+ switch (_IOC_NR(cmd)) { -+ case SOUND_MIXER_VOLUME: -+ val = ucba->output_level; -+ break; -+ -+ case SOUND_MIXER_MIC: -+ val = ucba->input_level; -+ break; -+ -+ case SOUND_MIXER_RECSRC: -+ case SOUND_MIXER_RECMASK: -+ val = ucba->telecom ? 0 : REC_MASK; -+ break; -+ -+ case SOUND_MIXER_DEVMASK: -+ val = ucba->telecom ? 0 : DEV_MASK; -+ break; -+ -+ case SOUND_MIXER_CAPS: -+ case SOUND_MIXER_STEREODEVS: -+ val = 0; -+ break; -+ -+ default: -+ val = 0; -+ ret = -EINVAL; -+ break; -+ } -+ -+ if (ret == 0) -+ ret = put_user(val, (int *)arg); -+ } -+ out: -+ return ret; -+} -+ -+static int ucb1x00_audio_setrate(struct ucb1x00_audio *ucba, int rate) -+{ -+ unsigned int div_rate = ucb1x00_clkrate(ucba->ucb) / 32; -+ unsigned int div; -+ -+ div = (div_rate + (rate / 2)) / rate; -+ if (div < 6) -+ div = 6; -+ if (div > 127) -+ div = 127; -+ -+ ucba->ctrl_a = (ucba->ctrl_a & ~0x7f) | div; -+ -+ if (ucba->telecom) { -+ ucb1x00_reg_write(ucba->ucb, UCB_TC_B, 0); -+ ucb1x00_set_telecom_divisor(ucba->ucb, div * 32); -+ ucb1x00_reg_write(ucba->ucb, UCB_TC_A, ucba->ctrl_a); -+ ucb1x00_reg_write(ucba->ucb, UCB_TC_B, ucba->ctrl_b); -+ } else { -+ ucb1x00_reg_write(ucba->ucb, UCB_AC_B, 0); -+ ucb1x00_set_audio_divisor(ucba->ucb, div * 32); -+ ucb1x00_reg_write(ucba->ucb, UCB_AC_A, ucba->ctrl_a); -+ ucb1x00_reg_write(ucba->ucb, UCB_AC_B, ucba->ctrl_b); -+ } -+ -+ ucba->rate = div_rate / div; -+ -+ return ucba->rate; -+} -+ -+static int ucb1x00_audio_getrate(struct ucb1x00_audio *ucba) -+{ -+ return ucba->rate; -+} -+ -+static void ucb1x00_audio_startup(void *data) -+{ -+ struct ucb1x00_audio *ucba = data; -+ -+ ucb1x00_enable(ucba->ucb); -+ ucb1x00_audio_setrate(ucba, ucba->rate); -+ -+ ucb1x00_reg_write(ucba->ucb, UCB_MODE, UCB_MODE_DYN_VFLAG_ENA); -+ -+ /* -+ * Take off-hook -+ */ -+ if (ucba->daa_oh_bit) -+ ucb1x00_io_write(ucba->ucb, 0, ucba->daa_oh_bit); -+} -+ -+static void ucb1x00_audio_shutdown(void *data) -+{ -+ struct ucb1x00_audio *ucba = data; -+ -+ /* -+ * Place on-hook -+ */ -+ if (ucba->daa_oh_bit) -+ ucb1x00_io_write(ucba->ucb, ucba->daa_oh_bit, 0); -+ -+ ucb1x00_reg_write(ucba->ucb, ucba->telecom ? UCB_TC_B : UCB_AC_B, 0); -+ ucb1x00_disable(ucba->ucb); -+} -+ -+static int -+ucb1x00_audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) -+{ -+ struct ucb1x00_audio *ucba; -+ int val, ret = 0; -+ -+ ucba = list_entry(file->f_op, struct ucb1x00_audio, fops); -+ -+ /* -+ * Make sure we have our magic number -+ */ -+ if (ucba->magic != MAGIC) -+ return -ENODEV; -+ -+ switch (cmd) { -+ case SNDCTL_DSP_STEREO: -+ ret = get_user(val, (int *)arg); -+ if (ret) -+ return ret; -+ if (val != 0) -+ return -EINVAL; -+ val = 0; -+ break; -+ -+ case SNDCTL_DSP_CHANNELS: -+ case SOUND_PCM_READ_CHANNELS: -+ val = 1; -+ break; -+ -+ case SNDCTL_DSP_SPEED: -+ ret = get_user(val, (int *)arg); -+ if (ret) -+ return ret; -+ val = ucb1x00_audio_setrate(ucba, val); -+ break; -+ -+ case SOUND_PCM_READ_RATE: -+ val = ucb1x00_audio_getrate(ucba); -+ break; -+ -+ case SNDCTL_DSP_SETFMT: -+ case SNDCTL_DSP_GETFMTS: -+ val = AFMT_S16_LE; -+ break; -+ -+ default: -+ return ucb1x00_mixer_ioctl(inode, file, cmd, arg); -+ } -+ -+ return put_user(val, (int *)arg); -+} -+ -+static int ucb1x00_audio_open(struct inode *inode, struct file *file) -+{ -+ struct ucb1x00_audio *ucba; -+ -+ ucba = list_entry(file->f_op, struct ucb1x00_audio, fops); -+ -+ return sa1100_audio_attach(inode, file, &ucba->state); -+} -+ -+static struct ucb1x00_audio *ucb1x00_audio_alloc(struct ucb1x00 *ucb) -+{ -+ struct ucb1x00_audio *ucba; -+ -+ ucba = kmalloc(sizeof(*ucba), GFP_KERNEL); -+ if (ucba) { -+ memset(ucba, 0, sizeof(*ucba)); -+ -+ ucba->magic = MAGIC; -+ ucba->ucb = ucb; -+ ucba->fops.owner = THIS_MODULE; -+ ucba->fops.open = ucb1x00_audio_open; -+ ucba->mops.owner = THIS_MODULE; -+ ucba->mops.ioctl = ucb1x00_mixer_ioctl; -+ ucba->state.output_stream = &ucba->output_stream; -+ ucba->state.input_stream = &ucba->input_stream; -+ ucba->state.data = ucba; -+ ucba->state.hw_init = ucb1x00_audio_startup; -+ ucba->state.hw_shutdown = ucb1x00_audio_shutdown; -+ ucba->state.client_ioctl = ucb1x00_audio_ioctl; -+ -+ /* There is a bug in the StrongARM causes corrupt MCP data to be sent to -+ * the codec when the FIFOs are empty and writes are made to the OS timer -+ * match register 0. To avoid this we must make sure that data is always -+ * sent to the codec. -+ */ -+ ucba->state.need_tx_for_rx = 1; -+ -+ init_MUTEX(&ucba->state.sem); -+ ucba->rate = 8000; -+ } -+ return ucba; -+} -+ -+static struct ucb1x00_audio *ucb1x00_audio_add_one(struct ucb1x00 *ucb, int telecom) -+{ -+ struct ucb1x00_audio *a; -+ -+ a = ucb1x00_audio_alloc(ucb); -+ if (a) { -+ a->telecom = telecom; -+ -+ a->input_stream.dev = ucb->cdev.dev; -+ a->output_stream.dev = ucb->cdev.dev; -+ a->ctrl_a = 0; -+ -+ if (a->telecom) { -+ a->input_stream.dma_dev = ucb->mcp->dma_telco_rd; -+ a->input_stream.id = "UCB1x00 telco in"; -+ a->output_stream.dma_dev = ucb->mcp->dma_telco_wr; -+ a->output_stream.id = "UCB1x00 telco out"; -+ a->ctrl_b = UCB_TC_B_IN_ENA|UCB_TC_B_OUT_ENA; -+#if 0 -+ a->daa_oh_bit = UCB_IO_8; -+ -+ ucb1x00_enable(ucb); -+ ucb1x00_io_write(ucb, a->daa_oh_bit, 0); -+ ucb1x00_io_set_dir(ucb, UCB_IO_7 | UCB_IO_6, a->daa_oh_bit); -+ ucb1x00_disable(ucb); -+#endif -+ } else { -+ a->input_stream.dma_dev = ucb->mcp->dma_audio_rd; -+ a->input_stream.id = "UCB1x00 audio in"; -+ a->output_stream.dma_dev = ucb->mcp->dma_audio_wr; -+ a->output_stream.id = "UCB1x00 audio out"; -+ a->ctrl_b = UCB_AC_B_IN_ENA|UCB_AC_B_OUT_ENA; -+ } -+ -+ a->dev_id = register_sound_dsp(&a->fops, -1); -+ a->mix_id = register_sound_mixer(&a->mops, -1); -+ -+ printk("Sound: UCB1x00 %s: dsp id %d mixer id %d\n", -+ a->telecom ? "telecom" : "audio", -+ a->dev_id, a->mix_id); -+ } -+ -+ return a; -+} -+ -+static void ucb1x00_audio_remove_one(struct ucb1x00_audio *a) -+{ -+ unregister_sound_dsp(a->dev_id); -+ unregister_sound_mixer(a->mix_id); -+ kfree(a); -+} -+ -+static int ucb1x00_audio_add(struct class_device *cdev) -+{ -+ struct ucb1x00 *ucb = classdev_to_ucb1x00(cdev); -+ -+ if (ucb->cdev.dev == NULL || ucb->cdev.dev->dma_mask == NULL) -+ return -ENXIO; -+ -+ ucb->audio_data = ucb1x00_audio_add_one(ucb, 0); -+ ucb->telecom_data = ucb1x00_audio_add_one(ucb, 1); -+ -+ return 0; -+} -+ -+static void ucb1x00_audio_remove(struct class_device *cdev) -+{ -+ struct ucb1x00 *ucb = classdev_to_ucb1x00(cdev); -+ -+ ucb1x00_audio_remove_one(ucb->audio_data); -+ ucb1x00_audio_remove_one(ucb->telecom_data); -+} -+ -+#if 0 //def CONFIG_PM -+static int ucb1x00_audio_suspend(struct ucb1x00 *ucb, u32 state) -+{ -+ struct ucb1x00_audio *a; -+ -+ a = ucb->audio_data; -+ sa1100_audio_suspend(&a->state, state); -+ a = ucb->telecom_data; -+ sa1100_audio_suspend(&a->state, state); -+ -+ return 0; -+} -+ -+static int ucb1x00_audio_resume(struct ucb1x00 *ucb) -+{ -+ struct ucb1x00_audio *a; -+ -+ a = ucb->audio_data; -+ sa1100_audio_resume(&a->state); -+ a = ucb->telecom_data; -+ sa1100_audio_resume(&a->state); -+ -+ return 0; -+} -+#else -+#define ucb1x00_audio_suspend NULL -+#define ucb1x00_audio_resume NULL -+#endif -+ -+static struct class_interface ucb1x00_audio_interface = { -+ .add = ucb1x00_audio_add, -+ .remove = ucb1x00_audio_remove, -+}; -+ -+static int __init ucb1x00_audio_init(void) -+{ -+ return ucb1x00_register_interface(&ucb1x00_audio_interface); -+} -+ -+static void __exit ucb1x00_audio_exit(void) -+{ -+ ucb1x00_unregister_interface(&ucb1x00_audio_interface); -+} -+ -+module_init(ucb1x00_audio_init); -+module_exit(ucb1x00_audio_exit); -+ -+MODULE_AUTHOR("Russell King "); -+MODULE_DESCRIPTION("UCB1x00 telecom/audio driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/misc/mcp-sa1100.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,275 @@ -+/* -+ * linux/drivers/misc/mcp-sa1100.c -+ * -+ * 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. -+ * -+ * SA1100 MCP (Multimedia Communications Port) driver. -+ * -+ * MCP read/write timeouts from Jordi Colomer, rehacked by rmk. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "mcp.h" -+ -+static void -+mcp_sa1100_set_telecom_divisor(struct mcp *mcp, unsigned int divisor) -+{ -+ unsigned int mccr0; -+ -+ divisor /= 32; -+ -+ mccr0 = Ser4MCCR0 & ~0x00007f00; -+ mccr0 |= divisor << 8; -+ Ser4MCCR0 = mccr0; -+} -+ -+static void -+mcp_sa1100_set_audio_divisor(struct mcp *mcp, unsigned int divisor) -+{ -+ unsigned int mccr0; -+ -+ divisor /= 32; -+ -+ mccr0 = Ser4MCCR0 & ~0x0000007f; -+ mccr0 |= divisor; -+ Ser4MCCR0 = mccr0; -+} -+ -+/* -+ * Write data to the device. The bit should be set after 3 subframe -+ * times (each frame is 64 clocks). We wait a maximum of 6 subframes. -+ * We really should try doing something more productive while we -+ * wait. -+ */ -+static void -+mcp_sa1100_write(struct mcp *mcp, unsigned int reg, unsigned int val) -+{ -+ int ret = -ETIME; -+ int i; -+ -+ Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff); -+ -+ for (i = 0; i < 2; i++) { -+ udelay(mcp->rw_timeout); -+ if (Ser4MCSR & MCSR_CWC) { -+ ret = 0; -+ break; -+ } -+ } -+ -+ if (ret < 0) -+ printk(KERN_WARNING "mcp: write timed out\n"); -+} -+ -+/* -+ * Read data from the device. The bit should be set after 3 subframe -+ * times (each frame is 64 clocks). We wait a maximum of 6 subframes. -+ * We really should try doing something more productive while we -+ * wait. -+ */ -+static unsigned int -+mcp_sa1100_read(struct mcp *mcp, unsigned int reg) -+{ -+ int ret = -ETIME; -+ int i; -+ -+ Ser4MCDR2 = reg << 17 | MCDR2_Rd; -+ -+ for (i = 0; i < 2; i++) { -+ udelay(mcp->rw_timeout); -+ if (Ser4MCSR & MCSR_CRC) { -+ ret = Ser4MCDR2 & 0xffff; -+ break; -+ } -+ } -+ -+ if (ret < 0) -+ printk(KERN_WARNING "mcp: read timed out\n"); -+ -+ return ret; -+} -+ -+static void mcp_sa1100_enable(struct mcp *mcp) -+{ -+ Ser4MCSR = -1; -+ Ser4MCCR0 |= MCCR0_MCE; -+} -+ -+static void mcp_sa1100_disable(struct mcp *mcp) -+{ -+ Ser4MCCR0 &= ~MCCR0_MCE; -+} -+ -+/* -+ * Our methods. -+ */ -+static struct mcp mcp_sa1100 = { -+ .owner = THIS_MODULE, -+ .lock = SPIN_LOCK_UNLOCKED, -+ .sclk_rate = 11981000, -+ .dma_audio_rd = DMA_Ser4MCP0Rd, -+ .dma_audio_wr = DMA_Ser4MCP0Wr, -+ .dma_telco_rd = DMA_Ser4MCP1Rd, -+ .dma_telco_wr = DMA_Ser4MCP1Wr, -+ .set_telecom_divisor = mcp_sa1100_set_telecom_divisor, -+ .set_audio_divisor = mcp_sa1100_set_audio_divisor, -+ .reg_write = mcp_sa1100_write, -+ .reg_read = mcp_sa1100_read, -+ .enable = mcp_sa1100_enable, -+ .disable = mcp_sa1100_disable, -+}; -+ -+static int mcp_sa1100_probe(struct device *dev) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct mcp *mcp = &mcp_sa1100; -+ int ret; -+ -+ if (!machine_is_adsbitsy() && !machine_is_assabet() && -+ !machine_is_cerf() && !machine_is_flexanet() && -+ !machine_is_freebird() && !machine_is_graphicsclient() && -+ !machine_is_graphicsmaster() && !machine_is_lart() && -+ !machine_is_omnimeter() && !machine_is_pfs168() && -+ !machine_is_shannon() && !machine_is_simpad() && -+ !machine_is_yopy()) -+ return -ENODEV; -+ -+ if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp")) -+ return -EBUSY; -+ -+ mcp->me = dev; -+ dev_set_drvdata(dev, mcp); -+ -+ if (machine_is_assabet()) { -+ ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); -+ } -+ -+ /* -+ * Setup the PPC unit correctly. -+ */ -+ PPDR &= ~PPC_RXD4; -+ PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; -+ PSDR |= PPC_RXD4; -+ PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); -+ PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); -+ -+ Ser4MCSR = -1; -+ Ser4MCCR1 = 0; -+ Ser4MCCR0 = 0x00007f7f | MCCR0_ADM; -+ -+ /* -+ * Calculate the read/write timeout (us) from the bit clock -+ * rate. This is the period for 3 64-bit frames. Always -+ * round this time up. -+ */ -+ mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) / -+ mcp->sclk_rate; -+ -+ ret = mcp_host_register(mcp, &pdev->dev); -+ if (ret != 0) { -+ release_mem_region(0x80060000, 0x60); -+ dev_set_drvdata(dev, NULL); -+ } -+ -+ return ret; -+} -+ -+static int mcp_sa1100_remove(struct device *dev) -+{ -+ struct mcp *mcp = dev_get_drvdata(dev); -+ -+ dev_set_drvdata(dev, NULL); -+ -+ mcp_host_unregister(mcp); -+ release_mem_region(0x80060000, 0x60); -+ -+ return 0; -+} -+ -+struct mcp_sa1100_state { -+ u32 mccr0; -+ u32 mccr1; -+}; -+ -+static int mcp_sa1100_suspend(struct device *dev, u32 state, u32 level) -+{ -+ struct mcp_sa1100_state *s = (struct mcp_sa1100_state *)dev->saved_state; -+ -+ if (!s) { -+ s = kmalloc(sizeof(struct mcp_sa1100_state), GFP_KERNEL); -+ dev->saved_state = (unsigned char *)s; -+ } -+ -+ if (s) { -+ s->mccr0 = Ser4MCCR0; -+ s->mccr1 = Ser4MCCR1; -+ } -+ -+ if (level == SUSPEND_DISABLE) -+ Ser4MCCR0 &= ~MCCR0_MCE; -+ return 0; -+} -+ -+static int mcp_sa1100_resume(struct device *dev, u32 level) -+{ -+ struct mcp_sa1100_state *s = (struct mcp_sa1100_state *)dev->saved_state; -+ -+ if (s && level == RESUME_RESTORE_STATE) { -+ Ser4MCCR1 = s->mccr1; -+ Ser4MCCR0 = s->mccr0; -+ -+ dev->saved_state = NULL; -+ kfree(s); -+ } -+ return 0; -+} -+ -+/* -+ * The driver for the SA11x0 MCP port. -+ */ -+static struct device_driver mcp_sa1100_driver = { -+ .name = "sa11x0-mcp", -+ .bus = &platform_bus_type, -+ .probe = mcp_sa1100_probe, -+ .remove = mcp_sa1100_remove, -+ .suspend = mcp_sa1100_suspend, -+ .resume = mcp_sa1100_resume, -+}; -+ -+/* -+ * This needs re-working -+ */ -+static int __init mcp_sa1100_init(void) -+{ -+ return driver_register(&mcp_sa1100_driver); -+} -+ -+static void __exit mcp_sa1100_exit(void) -+{ -+ driver_unregister(&mcp_sa1100_driver); -+} -+ -+module_init(mcp_sa1100_init); -+module_exit(mcp_sa1100_exit); -+ -+MODULE_AUTHOR("Russell King "); -+MODULE_DESCRIPTION("SA11x0 multimedia communications port driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/misc/mcp.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,58 @@ -+/* -+ * linux/drivers/misc/mcp.h -+ * -+ * Copyright (C) 2001 Russell King, 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. -+ */ -+#ifndef MCP_H -+#define MCP_H -+ -+struct mcp { -+ struct module *owner; -+ struct device *me; -+ spinlock_t lock; -+ int use_count; -+ unsigned int sclk_rate; -+ unsigned int rw_timeout; -+ dma_device_t dma_audio_rd; -+ dma_device_t dma_audio_wr; -+ dma_device_t dma_telco_rd; -+ dma_device_t dma_telco_wr; -+ void (*set_telecom_divisor)(struct mcp *, unsigned int); -+ void (*set_audio_divisor)(struct mcp *, unsigned int); -+ void (*reg_write)(struct mcp *, unsigned int, unsigned int); -+ unsigned int (*reg_read)(struct mcp *, unsigned int); -+ void (*enable)(struct mcp *); -+ void (*disable)(struct mcp *); -+ struct device attached_device; -+}; -+ -+void mcp_set_telecom_divisor(struct mcp *, unsigned int); -+void mcp_set_audio_divisor(struct mcp *, unsigned int); -+void mcp_reg_write(struct mcp *, unsigned int, unsigned int); -+unsigned int mcp_reg_read(struct mcp *, unsigned int); -+void mcp_enable(struct mcp *); -+void mcp_disable(struct mcp *); -+#define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate) -+ -+int mcp_host_register(struct mcp *, struct device *); -+void mcp_host_unregister(struct mcp *); -+ -+struct mcp_driver { -+ struct device_driver drv; -+ int (*probe)(struct mcp *); -+ void (*remove)(struct mcp *); -+ int (*suspend)(struct mcp *, u32); -+ int (*resume)(struct mcp *); -+}; -+ -+int mcp_driver_register(struct mcp_driver *); -+void mcp_driver_unregister(struct mcp_driver *); -+ -+#define mcp_get_drvdata(mcp) dev_get_drvdata(&(mcp)->attached_device) -+#define mcp_set_drvdata(mcp,d) dev_set_drvdata(&(mcp)->attached_device, d) -+ -+#endif ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/misc/ucb1x00-input.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,233 @@ -+/* -+ * linux/drivers/misc/ucb1x00.h -+ * -+ * Copyright (C) 2001 Russell King, 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. -+ */ -+#ifndef UCB1200_H -+#define UCB1200_H -+ -+#define UCB_IO_DATA 0x00 -+#define UCB_IO_DIR 0x01 -+ -+#define UCB_IO_0 (1 << 0) -+#define UCB_IO_1 (1 << 1) -+#define UCB_IO_2 (1 << 2) -+#define UCB_IO_3 (1 << 3) -+#define UCB_IO_4 (1 << 4) -+#define UCB_IO_5 (1 << 5) -+#define UCB_IO_6 (1 << 6) -+#define UCB_IO_7 (1 << 7) -+#define UCB_IO_8 (1 << 8) -+#define UCB_IO_9 (1 << 9) -+ -+#define UCB_IE_RIS 0x02 -+#define UCB_IE_FAL 0x03 -+#define UCB_IE_STATUS 0x04 -+#define UCB_IE_CLEAR 0x04 -+#define UCB_IE_ADC (1 << 11) -+#define UCB_IE_TSPX (1 << 12) -+#define UCB_IE_TSMX (1 << 13) -+#define UCB_IE_TCLIP (1 << 14) -+#define UCB_IE_ACLIP (1 << 15) -+ -+#define UCB_IRQ_TSPX 12 -+ -+#define UCB_TC_A 0x05 -+#define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */ -+#define UCB_TC_A_AMPL (1 << 7) /* UCB1300 */ -+ -+#define UCB_TC_B 0x06 -+#define UCB_TC_B_VOICE_ENA (1 << 3) -+#define UCB_TC_B_CLIP (1 << 4) -+#define UCB_TC_B_ATT (1 << 6) -+#define UCB_TC_B_SIDE_ENA (1 << 11) -+#define UCB_TC_B_MUTE (1 << 13) -+#define UCB_TC_B_IN_ENA (1 << 14) -+#define UCB_TC_B_OUT_ENA (1 << 15) -+ -+#define UCB_AC_A 0x07 -+#define UCB_AC_B 0x08 -+#define UCB_AC_B_LOOP (1 << 8) -+#define UCB_AC_B_MUTE (1 << 13) -+#define UCB_AC_B_IN_ENA (1 << 14) -+#define UCB_AC_B_OUT_ENA (1 << 15) -+ -+#define UCB_TS_CR 0x09 -+#define UCB_TS_CR_TSMX_POW (1 << 0) -+#define UCB_TS_CR_TSPX_POW (1 << 1) -+#define UCB_TS_CR_TSMY_POW (1 << 2) -+#define UCB_TS_CR_TSPY_POW (1 << 3) -+#define UCB_TS_CR_TSMX_GND (1 << 4) -+#define UCB_TS_CR_TSPX_GND (1 << 5) -+#define UCB_TS_CR_TSMY_GND (1 << 6) -+#define UCB_TS_CR_TSPY_GND (1 << 7) -+#define UCB_TS_CR_MODE_INT (0 << 8) -+#define UCB_TS_CR_MODE_PRES (1 << 8) -+#define UCB_TS_CR_MODE_POS (2 << 8) -+#define UCB_TS_CR_BIAS_ENA (1 << 11) -+#define UCB_TS_CR_TSPX_LOW (1 << 12) -+#define UCB_TS_CR_TSMX_LOW (1 << 13) -+ -+#define UCB_ADC_CR 0x0a -+#define UCB_ADC_SYNC_ENA (1 << 0) -+#define UCB_ADC_VREFBYP_CON (1 << 1) -+#define UCB_ADC_INP_TSPX (0 << 2) -+#define UCB_ADC_INP_TSMX (1 << 2) -+#define UCB_ADC_INP_TSPY (2 << 2) -+#define UCB_ADC_INP_TSMY (3 << 2) -+#define UCB_ADC_INP_AD0 (4 << 2) -+#define UCB_ADC_INP_AD1 (5 << 2) -+#define UCB_ADC_INP_AD2 (6 << 2) -+#define UCB_ADC_INP_AD3 (7 << 2) -+#define UCB_ADC_EXT_REF (1 << 5) -+#define UCB_ADC_START (1 << 7) -+#define UCB_ADC_ENA (1 << 15) -+ -+#define UCB_ADC_DATA 0x0b -+#define UCB_ADC_DAT_VAL (1 << 15) -+#define UCB_ADC_DAT(x) (((x) & 0x7fe0) >> 5) -+ -+#define UCB_ID 0x0c -+#define UCB_ID_1200 0x1004 -+#define UCB_ID_1300 0x1005 -+#define UCB_ID_1400 0x4304 -+#define UCB_ID_1400_BUGGY 0x4303 /* fake ID */ -+ -+#define UCB_MODE 0x0d -+#define UCB_MODE_DYN_VFLAG_ENA (1 << 12) -+#define UCB_MODE_AUD_OFF_CAN (1 << 13) -+ -+#include "mcp.h" -+ -+struct ucb1x00; -+ -+struct ucb1x00_irq { -+ void *devid; -+ void (*fn)(int, void *); -+}; -+ -+struct ucb1x00 { -+ spinlock_t lock; -+ struct mcp *mcp; -+ unsigned int irq; -+ struct semaphore adc_sem; -+ spinlock_t io_lock; -+ u16 id; -+ u16 io_dir; -+ u16 io_out; -+ u16 adc_cr; -+ u16 irq_fal_enbl; -+ u16 irq_ris_enbl; -+ struct ucb1x00_irq irq_handler[16]; -+}; -+ -+/** -+ * ucb1x00_clkrate - return the UCB1x00 SIB clock rate -+ * @ucb: UCB1x00 structure describing chip -+ * -+ * Return the SIB clock rate in Hz. -+ */ -+static inline unsigned int ucb1x00_clkrate(struct ucb1x00 *ucb) -+{ -+ return mcp_get_sclk_rate(ucb->mcp); -+} -+ -+/** -+ * ucb1x00_enable - enable the UCB1x00 SIB clock -+ * @ucb: UCB1x00 structure describing chip -+ * -+ * Enable the SIB clock. This can be called multiple times. -+ */ -+static inline void ucb1x00_enable(struct ucb1x00 *ucb) -+{ -+ mcp_enable(ucb->mcp); -+} -+ -+/** -+ * ucb1x00_disable - disable the UCB1x00 SIB clock -+ * @ucb: UCB1x00 structure describing chip -+ * -+ * Disable the SIB clock. The SIB clock will only be disabled -+ * when the number of ucb1x00_enable calls match the number of -+ * ucb1x00_disable calls. -+ */ -+static inline void ucb1x00_disable(struct ucb1x00 *ucb) -+{ -+ mcp_disable(ucb->mcp); -+} -+ -+/** -+ * ucb1x00_reg_write - write a UCB1x00 register -+ * @ucb: UCB1x00 structure describing chip -+ * @reg: UCB1x00 4-bit register index to write -+ * @val: UCB1x00 16-bit value to write -+ * -+ * Write the UCB1x00 register @reg with value @val. The SIB -+ * clock must be running for this function to return. -+ */ -+static inline void ucb1x00_reg_write(struct ucb1x00 *ucb, unsigned int reg, unsigned int val) -+{ -+ mcp_reg_write(ucb->mcp, reg, val); -+} -+ -+/** -+ * ucb1x00_reg_read - read a UCB1x00 register -+ * @ucb: UCB1x00 structure describing chip -+ * @reg: UCB1x00 4-bit register index to write -+ * -+ * Read the UCB1x00 register @reg and return its value. The SIB -+ * clock must be running for this function to return. -+ */ -+static inline unsigned int ucb1x00_reg_read(struct ucb1x00 *ucb, unsigned int reg) -+{ -+ return mcp_reg_read(ucb->mcp, reg); -+} -+/** -+ * ucb1x00_set_audio_divisor - -+ * @ucb: UCB1x00 structure describing chip -+ * @div: SIB clock divisor -+ */ -+static inline void ucb1x00_set_audio_divisor(struct ucb1x00 *ucb, unsigned int div) -+{ -+ mcp_set_audio_divisor(ucb->mcp, div); -+} -+ -+/** -+ * ucb1x00_set_telecom_divisor - -+ * @ucb: UCB1x00 structure describing chip -+ * @div: SIB clock divisor -+ */ -+static inline void ucb1x00_set_telecom_divisor(struct ucb1x00 *ucb, unsigned int div) -+{ -+ mcp_set_telecom_divisor(ucb->mcp, div); -+} -+ -+struct ucb1x00 *ucb1x00_get(void); -+ -+void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int, unsigned int); -+void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int, unsigned int); -+unsigned int ucb1x00_io_read(struct ucb1x00 *ucb); -+ -+#define UCB_NOSYNC (0) -+#define UCB_SYNC (1) -+ -+unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync); -+void ucb1x00_adc_enable(struct ucb1x00 *ucb); -+void ucb1x00_adc_disable(struct ucb1x00 *ucb); -+ -+/* -+ * Which edges of the IRQ do you want to control today? -+ */ -+#define UCB_RISING (1 << 0) -+#define UCB_FALLING (1 << 1) -+ -+int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid); -+void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges); -+void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges); -+int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid); -+ -+#endif ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/misc/ucb1x00.h 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,271 @@ -+/* -+ * linux/drivers/misc/ucb1x00.h -+ * -+ * Copyright (C) 2001 Russell King, 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. -+ */ -+#ifndef UCB1200_H -+#define UCB1200_H -+ -+#ifdef CONFIG_ARCH_PXA -+ -+/* ucb1400 aclink register mappings: */ -+ -+#define UCB_IO_DATA 0x5a -+#define UCB_IO_DIR 0x5c -+#define UCB_IE_RIS 0x5e -+#define UCB_IE_FAL 0x60 -+#define UCB_IE_STATUS 0x62 -+#define UCB_IE_CLEAR 0x62 -+#define UCB_TS_CR 0x64 -+#define UCB_ADC_CR 0x66 -+#define UCB_ADC_DATA 0x68 -+#define UCB_ID 0x7e /* 7c is mfr id, 7e part id (from aclink spec) */ -+ -+#define UCB_ADC_DAT(x) ((x) & 0x3ff) -+ -+#else -+ -+/* ucb1x00 SIB register mappings: */ -+ -+#define UCB_IO_DATA 0x00 -+#define UCB_IO_DIR 0x01 -+#define UCB_IE_RIS 0x02 -+#define UCB_IE_FAL 0x03 -+#define UCB_IE_STATUS 0x04 -+#define UCB_IE_CLEAR 0x04 -+#define UCB_TC_A 0x05 -+#define UCB_TC_B 0x06 -+#define UCB_AC_A 0x07 -+#define UCB_AC_B 0x08 -+#define UCB_TS_CR 0x09 -+#define UCB_ADC_CR 0x0a -+#define UCB_ADC_DATA 0x0b -+#define UCB_ID 0x0c -+#define UCB_MODE 0x0d -+ -+#define UCB_ADC_DAT(x) (((x) & 0x7fe0) >> 5) -+ -+#endif -+ -+ -+#define UCB_IO_0 (1 << 0) -+#define UCB_IO_1 (1 << 1) -+#define UCB_IO_2 (1 << 2) -+#define UCB_IO_3 (1 << 3) -+#define UCB_IO_4 (1 << 4) -+#define UCB_IO_5 (1 << 5) -+#define UCB_IO_6 (1 << 6) -+#define UCB_IO_7 (1 << 7) -+#define UCB_IO_8 (1 << 8) -+#define UCB_IO_9 (1 << 9) -+ -+#define UCB_IE_ADC (1 << 11) -+#define UCB_IE_TSPX (1 << 12) -+#define UCB_IE_TSMX (1 << 13) -+#define UCB_IE_TCLIP (1 << 14) -+#define UCB_IE_ACLIP (1 << 15) -+ -+#define UCB_IRQ_TSPX 12 -+ -+#define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */ -+#define UCB_TC_A_AMPL (1 << 7) /* UCB1300 */ -+ -+#define UCB_TC_B_VOICE_ENA (1 << 3) -+#define UCB_TC_B_CLIP (1 << 4) -+#define UCB_TC_B_ATT (1 << 6) -+#define UCB_TC_B_SIDE_ENA (1 << 11) -+#define UCB_TC_B_MUTE (1 << 13) -+#define UCB_TC_B_IN_ENA (1 << 14) -+#define UCB_TC_B_OUT_ENA (1 << 15) -+ -+#define UCB_AC_B_LOOP (1 << 8) -+#define UCB_AC_B_MUTE (1 << 13) -+#define UCB_AC_B_IN_ENA (1 << 14) -+#define UCB_AC_B_OUT_ENA (1 << 15) -+ -+#define UCB_TS_CR_TSMX_POW (1 << 0) -+#define UCB_TS_CR_TSPX_POW (1 << 1) -+#define UCB_TS_CR_TSMY_POW (1 << 2) -+#define UCB_TS_CR_TSPY_POW (1 << 3) -+#define UCB_TS_CR_TSMX_GND (1 << 4) -+#define UCB_TS_CR_TSPX_GND (1 << 5) -+#define UCB_TS_CR_TSMY_GND (1 << 6) -+#define UCB_TS_CR_TSPY_GND (1 << 7) -+#define UCB_TS_CR_MODE_INT (0 << 8) -+#define UCB_TS_CR_MODE_PRES (1 << 8) -+#define UCB_TS_CR_MODE_POS (2 << 8) -+#define UCB_TS_CR_BIAS_ENA (1 << 11) -+#define UCB_TS_CR_TSPX_LOW (1 << 12) -+#define UCB_TS_CR_TSMX_LOW (1 << 13) -+ -+#define UCB_ADC_SYNC_ENA (1 << 0) -+#define UCB_ADC_VREFBYP_CON (1 << 1) -+#define UCB_ADC_INP_TSPX (0 << 2) -+#define UCB_ADC_INP_TSMX (1 << 2) -+#define UCB_ADC_INP_TSPY (2 << 2) -+#define UCB_ADC_INP_TSMY (3 << 2) -+#define UCB_ADC_INP_AD0 (4 << 2) -+#define UCB_ADC_INP_AD1 (5 << 2) -+#define UCB_ADC_INP_AD2 (6 << 2) -+#define UCB_ADC_INP_AD3 (7 << 2) -+#define UCB_ADC_EXT_REF (1 << 5) -+#define UCB_ADC_START (1 << 7) -+#define UCB_ADC_ENA (1 << 15) -+ -+#define UCB_ADC_DAT_VAL (1 << 15) -+ -+#define UCB_ID_1200 0x1004 -+#define UCB_ID_1300 0x1005 -+#define UCB_ID_1400 0x4304 -+#define UCB_ID_1400_BUGGY 0x4303 /* fake ID */ -+ -+#define UCB_MODE_DYN_VFLAG_ENA (1 << 12) -+#define UCB_MODE_AUD_OFF_CAN (1 << 13) -+ -+#include -+#include "mcp.h" -+ -+struct ucb1x00_irq { -+ void *devid; -+ void (*fn)(int, void *); -+}; -+ -+extern struct class ucb1x00_class; -+ -+struct ucb1x00 { -+ spinlock_t lock; -+ struct mcp *mcp; -+ unsigned int irq; -+ struct semaphore adc_sem; -+ spinlock_t io_lock; -+ wait_queue_head_t irq_wait; -+ struct completion complete; -+ struct task_struct *rtask; -+ u16 id; -+ u16 io_dir; -+ u16 io_out; -+ u16 adc_cr; -+ u16 irq_fal_enbl; -+ u16 irq_ris_enbl; -+ struct ucb1x00_irq irq_handler[16]; -+ struct class_device cdev; -+ void *audio_data; -+ void *telecom_data; -+ void *ts_data; -+}; -+ -+#define classdev_to_ucb1x00(cd) container_of(cd, struct ucb1x00, cdev) -+ -+int ucb1x00_register_interface(struct class_interface *intf); -+void ucb1x00_unregister_interface(struct class_interface *intf); -+ -+/** -+ * ucb1x00_clkrate - return the UCB1x00 SIB clock rate -+ * @ucb: UCB1x00 structure describing chip -+ * -+ * Return the SIB clock rate in Hz. -+ */ -+static inline unsigned int ucb1x00_clkrate(struct ucb1x00 *ucb) -+{ -+ return mcp_get_sclk_rate(ucb->mcp); -+} -+ -+/** -+ * ucb1x00_enable - enable the UCB1x00 SIB clock -+ * @ucb: UCB1x00 structure describing chip -+ * -+ * Enable the SIB clock. This can be called multiple times. -+ */ -+static inline void ucb1x00_enable(struct ucb1x00 *ucb) -+{ -+ mcp_enable(ucb->mcp); -+} -+ -+/** -+ * ucb1x00_disable - disable the UCB1x00 SIB clock -+ * @ucb: UCB1x00 structure describing chip -+ * -+ * Disable the SIB clock. The SIB clock will only be disabled -+ * when the number of ucb1x00_enable calls match the number of -+ * ucb1x00_disable calls. -+ */ -+static inline void ucb1x00_disable(struct ucb1x00 *ucb) -+{ -+ mcp_disable(ucb->mcp); -+} -+ -+/** -+ * ucb1x00_reg_write - write a UCB1x00 register -+ * @ucb: UCB1x00 structure describing chip -+ * @reg: UCB1x00 4-bit register index to write -+ * @val: UCB1x00 16-bit value to write -+ * -+ * Write the UCB1x00 register @reg with value @val. The SIB -+ * clock must be running for this function to return. -+ */ -+static inline void ucb1x00_reg_write(struct ucb1x00 *ucb, unsigned int reg, unsigned int val) -+{ -+ mcp_reg_write(ucb->mcp, reg, val); -+} -+ -+/** -+ * ucb1x00_reg_read - read a UCB1x00 register -+ * @ucb: UCB1x00 structure describing chip -+ * @reg: UCB1x00 4-bit register index to write -+ * -+ * Read the UCB1x00 register @reg and return its value. The SIB -+ * clock must be running for this function to return. -+ */ -+static inline unsigned int ucb1x00_reg_read(struct ucb1x00 *ucb, unsigned int reg) -+{ -+ return mcp_reg_read(ucb->mcp, reg); -+} -+/** -+ * ucb1x00_set_audio_divisor - -+ * @ucb: UCB1x00 structure describing chip -+ * @div: SIB clock divisor -+ */ -+static inline void ucb1x00_set_audio_divisor(struct ucb1x00 *ucb, unsigned int div) -+{ -+ mcp_set_audio_divisor(ucb->mcp, div); -+} -+ -+/** -+ * ucb1x00_set_telecom_divisor - -+ * @ucb: UCB1x00 structure describing chip -+ * @div: SIB clock divisor -+ */ -+static inline void ucb1x00_set_telecom_divisor(struct ucb1x00 *ucb, unsigned int div) -+{ -+ mcp_set_telecom_divisor(ucb->mcp, div); -+} -+ -+#define ucb1x00_get() NULL -+ -+void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int, unsigned int); -+void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int, unsigned int); -+unsigned int ucb1x00_io_read(struct ucb1x00 *ucb); -+ -+#define UCB_NOSYNC (0) -+#define UCB_SYNC (1) -+ -+unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync); -+void ucb1x00_adc_enable(struct ucb1x00 *ucb); -+void ucb1x00_adc_disable(struct ucb1x00 *ucb); -+ -+/* -+ * Which edges of the IRQ do you want to control today? -+ */ -+#define UCB_RISING (1 << 0) -+#define UCB_FALLING (1 << 1) -+ -+int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid); -+void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges); -+void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges); -+int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid); -+ -+#endif ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/misc/switches-sa1100.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,323 @@ -+/* -+ * linux/drivers/misc/switches-sa1100.c -+ * -+ * Copyright (C) 2001 John Dorsey -+ * -+ * 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. -+ * -+ * 19 December 2001 - created from sa1100_switches.c. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "switches.h" -+ -+ -+static irqreturn_t switches_sa1100_handler(int irq, void *dev_id, -+ struct pt_regs *regs); -+ -+ -+#ifdef CONFIG_SA1100_ASSABET -+ -+/* Assabet -+ * ^^^^^^^ -+ * We have two general-purpose switches, S1 and S2, available via GPIO -+ * on Assabet. This code sets bits in the range [1, 2] in the mask that -+ * we return to userland. -+ */ -+ -+static int assabet_switches_sa1100_init(void) -+{ -+ -+ if (machine_has_neponset()) -+ NCR_0 |= NCR_GP01_OFF; -+ -+ if (request_irq(IRQ_GPIO0, switches_sa1100_handler, SA_INTERRUPT, -+ SWITCHES_NAME, NULL) < 0) { -+ printk(KERN_ERR "%s: unable to register IRQ for GPIO 0\n", -+ SWITCHES_NAME); -+ return -EIO; -+ } -+ -+ if (request_irq(IRQ_GPIO1, switches_sa1100_handler, SA_INTERRUPT, -+ SWITCHES_NAME, NULL) < 0) { -+ printk(KERN_ERR "%s: unable to register IRQ for GPIO 1\n", -+ SWITCHES_NAME); -+ free_irq(IRQ_GPIO0, NULL); -+ return -EIO; -+ } -+ -+ set_irq_type(IRQ_GPIO0, IRQT_BOTHEDGE); -+ set_irq_type(IRQ_GPIO1, IRQT_BOTHEDGE); -+ -+ return 0; -+ -+} -+ -+static void assabet_switches_sa1100_shutdown(void) -+{ -+ -+ free_irq(IRQ_GPIO1, NULL); -+ free_irq(IRQ_GPIO0, NULL); -+ -+} -+ -+static irqreturn_t assabet_switches_sa1100_handler(int irq, switches_mask_t *mask) -+{ -+ unsigned int s, last, this; -+ static unsigned int states = 0; -+ -+ switch (irq) { -+ -+ case IRQ_GPIO0: s = 0; break; -+ -+ case IRQ_GPIO1: s = 1; break; -+ -+ default: return IRQ_NONE; -+ -+ } -+ -+ last = ((states & (1 << s)) != 0); -+ this = ((GPLR & GPIO_GPIO(s)) != 0); -+ -+ if (last == this) /* debounce */ -+ return IRQ_HANDLED; -+ -+ SWITCHES_SET(mask, s + 1, this); -+ -+ states = this ? (states | (1 << s)) : (states & ~(1 << s)); -+ -+ return IRQ_HANDLED; -+} -+#endif /* CONFIG_SA1100_ASSABET */ -+ -+#ifdef CONFIG_SA1100_BADGE4 -+ -+/* BadgePAD 4 -+ * ^^^^^^^^^^ -+ * -+ * Here we use test point J6 (BADGE4_GPIO_TESTPT_J6 aka GPIO 23) as a -+ * general purpose switch input. We map this to switch #0. -+ */ -+ -+#define BADGE4_SW0_GPIO GPIO_GPIO23 /* aka BADGE4_GPIO_TESTPT_J6 */ -+#define BADGE4_SW0_IRQ IRQ_GPIO23 -+ -+static int badge4_switches_sa1100_init(void) -+{ -+ if (request_irq(BADGE4_SW0_IRQ, switches_sa1100_handler, SA_INTERRUPT, -+ SWITCHES_NAME, NULL) < 0) { -+ printk(KERN_ERR "%s: unable to register IRQ for SW0\n", -+ SWITCHES_NAME); -+ return -EIO; -+ } -+ -+ set_irq_type(BADGE4_SW0_IRQ, IRQT_BOTHEDGE); -+ -+ return 0; -+} -+ -+static void badge4_switches_sa1100_shutdown(void) -+{ -+ free_irq(BADGE4_SW0_IRQ, NULL); -+} -+ -+static irqreturn_t badge4_switches_sa1100_handler(int irq, switches_mask_t *mask) -+{ -+ unsigned int swno, last, this, gpio; -+ static unsigned int states = 0; -+ -+ switch (irq) { -+ case BADGE4_SW0_IRQ: -+ swno = 0; -+ gpio = BADGE4_SW0_GPIO; -+ break; -+ default: -+ return IRQ_NONE; -+ } -+ -+ last = ((states & gpio) != 0); -+ this = ((GPLR & gpio) != 0); -+ -+ if (last == this) /* debounce */ -+ return IRQ_HANDLED; -+ -+ SWITCHES_SET(mask, swno, this); -+ -+ states = this ? (states | gpio) : (states & ~gpio); -+ -+ return IRQ_HANDLED; -+} -+#endif /* CONFIG_SA1100_BADGE4 */ -+ -+ -+#ifdef CONFIG_SA1100_SPOT -+ -+/* Spot -+ * ^^^^ -+ * Spot (R2, R3) has a single general-purpose switch (S1), which is -+ * also the power-on switch. We set bit [1] in the mask we return to -+ * userland. -+ */ -+ -+static int spot_switches_sa1100_init(void) -+{ -+ -+ set_GPIO_IRQ_edge(GPIO_SW1, GPIO_BOTH_EDGES); -+ -+ if (request_irq(IRQ_GPIO_SW1, switches_sa1100_handler, SA_INTERRUPT, -+ SWITCHES_NAME, NULL) < 0) { -+ printk(KERN_ERR "%s: unable to register IRQ for SW1\n", -+ SWITCHES_NAME); -+ return -EIO; -+ } -+ -+ return 0; -+ -+} -+ -+static void spot_switches_sa1100_shutdown(void) -+{ -+ -+ free_irq(IRQ_GPIO_SW1, NULL); -+ -+} -+ -+static irqreturn_t spot_switches_sa1100_handler(int irq, switches_mask_t *mask) -+{ -+ unsigned int s, last, this; -+ static unsigned int states = 0; -+ -+ switch (irq) { -+ -+ case IRQ_GPIO_SW1: s = 0; break; -+ -+ default: return IRQ_NONE; -+ -+ } -+ -+ last = ((states & (1 << s)) != 0); -+ this = ((GPLR & GPIO_GPIO(s)) != 0); -+ -+ if (last == this) /* debounce */ -+ return IRQ_HANDLED; -+ -+ SWITCHES_SET(mask, s + 1, this); -+ -+ states = this ? (states | (1 << s)) : (states & ~(1 << s)); -+ -+ return IRQ_HANDLED; -+ -+} -+#endif /* CONFIG_SA1100_SPOT */ -+ -+ -+/* switches_sa1100_handler() -+ * ^^^^^^^^^^^^^^^^^^^^^^^^^ -+ * This routine is a generalized handler for SA-1100 switches -+ * which manages action descriptors and calls a board-specific -+ * service routine. This routine is appropriate for GPIO switches -+ * or other primary interrupt sources, and can be registered as a -+ * first-class IRQ handler using request_irq(). -+ */ -+static irqreturn_t switches_sa1100_handler(int irq, void *dev_id, -+ struct pt_regs *regs) -+{ -+ switches_mask_t mask; -+ irqreturn_t ret = IRQ_NONE; -+ -+ SWITCHES_ZERO(&mask); -+ -+ /* Porting note: call a board-specific switch interrupt handler -+ * here. The handler can assume that sufficient storage for -+ * `mask' has been allocated, and that the corresponding -+ * switches_mask_t structure has been zeroed. -+ */ -+ -+ if (machine_is_assabet()) { -+#ifdef CONFIG_SA1100_ASSABET -+ ret = assabet_switches_sa1100_handler(irq, &mask); -+#endif -+ } else if (machine_is_badge4()) { -+#ifdef CONFIG_SA1100_BADGE4 -+ ret = badge4_switches_sa1100_handler(irq, &mask); -+#endif -+ } else if (machine_is_spot()) { -+#ifdef CONFIG_SA1100_SPOT -+ ret = spot_switches_sa1100_handler(irq, &mask); -+#endif -+ } -+ -+ switches_event(&mask); -+ -+ return ret; -+} -+ -+int __init switches_sa1100_init(void) -+{ -+ -+ /* Porting note: call a board-specific init routine here. */ -+ -+ if (machine_is_assabet()) { -+#ifdef CONFIG_SA1100_ASSABET -+ if (assabet_switches_sa1100_init() < 0) -+ return -EIO; -+#endif -+ } else if (machine_is_badge4()) { -+#ifdef CONFIG_SA1100_BADGE4 -+ if (badge4_switches_sa1100_init() < 0) -+ return -EIO; -+#endif -+ } else if (machine_is_spot()) { -+#ifdef CONFIG_SA1100_SPOT -+ if (spot_switches_sa1100_init() < 0) -+ return -EIO; -+#endif -+ } -+ -+ return 0; -+ -+} -+ -+void __exit switches_sa1100_exit(void) -+{ -+ -+ /* Porting note: call a board-specific shutdown routine here. */ -+ -+ if (machine_is_assabet()) { -+#ifdef CONFIG_SA1100_ASSABET -+ assabet_switches_sa1100_shutdown(); -+#endif -+ } else if (machine_is_badge4()) { -+#ifdef CONFIG_SA1100_BADGE4 -+ badge4_switches_sa1100_shutdown(); -+#endif -+ } else if (machine_is_spot()) { -+#ifdef CONFIG_SA1100_SPOT -+ spot_switches_sa1100_shutdown(); -+#endif -+ } -+ -+} -+ -+module_init(switches_sa1100_init); -+module_exit(switches_sa1100_exit); -+ -+MODULE_DESCRIPTION("SA-1100 switches driver"); -+MODULE_LICENSE("GPL"); ---- linux-2.6.5/drivers/misc/Makefile~heh 2004-04-03 22:38:17.000000000 -0500 -+++ linux-2.6.5/drivers/misc/Makefile 2004-04-30 20:57:36.000000000 -0400 -@@ -4,3 +4,21 @@ - obj- := misc.o # Dummy rule to force built-in.o to be made - - obj-$(CONFIG_IBM_ASM) += ibmasm/ -+ -+obj-$(CONFIG_MCP) += mcp-core.o -+obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o -+obj-$(CONFIG_MCP_UCB1200_AUDIO) += ucb1x00-audio.o -+obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o -+ -+ifeq ($(CONFIG_SA1100_ASSABET),y) -+obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o -+endif -+ -+obj-$(CONFIG_SWITCHES) += switches-core.o -+obj-$(CONFIG_SWITCHES_SA1100) += switches-sa1100.o -+obj-$(CONFIG_SWITCHES_UCB1X00) += switches-ucb1x00.o -+ -+obj-$(CONFIG_MCP_SA1100) += mcp-sa1100.o -+ -+obj-$(CONFIG_UCB1400_TS) += mcp-pxa.o ucb1x00-core.o ucb1x00-ts.o -+ ---- linux-2.6.5/drivers/i2c/busses/Kconfig~heh 2004-04-03 22:38:10.000000000 -0500 -+++ linux-2.6.5/drivers/i2c/busses/Kconfig 2004-04-30 20:57:36.000000000 -0400 -@@ -70,6 +70,16 @@ - This support is also available as a module. If so, the module - will be called i2c-hydra. - -+config I2C_BIT_SA1100_GPIO -+ bool "SA1100 I2C GPIO adapter" -+ depends on ARCH_SA1100 && I2C_ALGOBIT -+ help -+ This supports I2C on the SA11x0 processor GPIO pins. This -+ shares support with the L3 driver. -+ -+ This support is also available as a module. If so, the module -+ will be called l3-bit-sa1100. -+ - config I2C_I801 - tristate "Intel 801" - depends on I2C && PCI && EXPERIMENTAL -@@ -241,6 +251,18 @@ - This support is also available as a module. If so, the module - will be called i2c-prosavage. - -+config I2C_PXA2XX -+ tristate "PXA I2C Interface" -+ depends on I2C && ARCH_PXA -+ select I2C_ALGOPXA -+ help -+ This supports the use of the PXA I2C interface found on the Intel -+ PXA 25x and PXA 26x systems. Say Y if you have one of these. -+ -+ This support is also available as a module. If you want to compile -+ it as a module, say M here and read Documentation/modules.txt. -+ The module will be called i2c-adap-pxa. -+ - config I2C_RPXLITE - tristate "Embedded Planet RPX Lite/Classic support" - depends on (RPXLITE || RPXCLASSIC) && I2C ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/i2c/busses/pxa2xx_i2c.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,388 @@ -+/* -+ * i2c_adap_pxa.c -+ * -+ * I2C adapter for the PXA I2C bus access. -+ * -+ * Copyright (C) 2002 Intrinsyc Software Inc. -+ * -+ * 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. -+ * -+ * History: -+ * Apr 2002: Initial version [CS] -+ * Jun 2002: Properly seperated algo/adap [FB] -+ * Jan 2003: Fixed several bugs concerning interrupt handling [Kai-Uwe Bloem] -+ * Jan 2003: added limited signal handling [Kai-Uwe Bloem] -+ * Jun 2003: updated for 2.5 [Dustin McIntire] -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include /* for IRQ_I2C */ -+ -+#include -+ -+/* -+ * Set this to zero to remove all debug statements via dead code elimination. -+ */ -+//#define DEBUG 1 -+ -+#if DEBUG -+static unsigned int i2c_debug = DEBUG; -+#else -+#define i2c_debug 0 -+#endif -+ -+static int irq = 0; -+static volatile int i2c_pending = 0; /* interrupt pending when 1 */ -+static volatile int bus_error = 0; -+static volatile int tx_finished = 0; -+static volatile int rx_finished = 0; -+ -+static wait_queue_head_t i2c_wait; -+static void i2c_pxa_transfer( int lastbyte, int receive, int midbyte); -+ -+/* place a byte in the transmit register */ -+static void i2c_pxa_write_byte(u8 value) -+{ -+ IDBR = value; -+} -+ -+/* read byte in the receive register */ -+static u8 i2c_pxa_read_byte(void) -+{ -+ return (u8) (0xff & IDBR); -+} -+ -+static void i2c_pxa_start(void) -+{ -+ unsigned long icr = ICR; -+ icr |= ICR_START; -+ icr &= ~(ICR_STOP | ICR_ALDIE | ICR_ACKNAK); -+ ICR = icr; -+ -+ bus_error=0; /* clear any bus_error from previous txfers */ -+ tx_finished=0; /* clear rx and tx interrupts from previous txfers */ -+ rx_finished=0; -+ i2c_pending = 0; -+} -+ -+static void i2c_pxa_repeat_start(void) -+{ -+ unsigned long icr = ICR; -+ icr |= ICR_START; -+ icr &= ~(ICR_STOP | ICR_ALDIE); -+ ICR = icr; -+ -+ bus_error=0; /* clear any bus_error from previous txfers */ -+ tx_finished=0; /* clear rx and tx interrupts from previous txfers */ -+ rx_finished=0; -+ i2c_pending = 0; -+} -+ -+static void i2c_pxa_stop(void) -+{ -+ unsigned long icr = ICR; -+ icr |= ICR_STOP; -+ icr &= ~(ICR_START); -+ ICR = icr; -+} -+ -+static void i2c_pxa_midbyte(void) -+{ -+ unsigned long icr = ICR; -+ icr &= ~(ICR_START | ICR_STOP); -+ ICR = icr; -+} -+ -+static void i2c_pxa_abort(void) -+{ -+ unsigned long timeout = jiffies + HZ/4; -+ -+#ifdef PXA_ABORT_MA -+ while ((long)(timeout - jiffies) > 0 && (ICR & ICR_TB)) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(1); -+ } -+ -+ ICR |= ICR_MA; -+ udelay(100); -+#else -+ while ((long)(timeout - jiffies) > 0 && (IBMR & 0x1) == 0) { -+ i2c_pxa_transfer( 1, I2C_RECEIVE, 1); -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(1); -+ } -+#endif -+ ICR &= ~(ICR_MA | ICR_START | ICR_STOP); -+} -+ -+static int i2c_pxa_wait_bus_not_busy( void) -+{ -+ int timeout = DEF_TIMEOUT; -+ -+ while (timeout-- && (ISR & ISR_IBB)) { -+ udelay(100); /* wait for 100 us */ -+ } -+ -+ return (timeout<=0); -+} -+ -+spinlock_t i2c_pxa_irqlock = SPIN_LOCK_UNLOCKED; -+ -+static void i2c_pxa_wait_for_ite(void){ -+ unsigned long flags; -+ if (irq > 0) { -+ spin_lock_irqsave(&i2c_pxa_irqlock, flags); -+ if (i2c_pending == 0) { -+ interruptible_sleep_on_timeout(&i2c_wait, I2C_SLEEP_TIMEOUT ); -+ } -+ i2c_pending = 0; -+ spin_unlock_irqrestore(&i2c_pxa_irqlock, flags); -+ } else { -+ udelay(100); -+ } -+} -+ -+static int i2c_pxa_wait_for_int( int wait_type) -+{ -+ int timeout = DEF_TIMEOUT; -+#ifdef DEBUG -+ if (bus_error) -+ printk(KERN_INFO"i2c_pxa_wait_for_int: Bus error on enter\n"); -+ if (rx_finished) -+ printk(KERN_INFO"i2c_pxa_wait_for_int: Receive interrupt on enter\n"); -+ if (tx_finished) -+ printk(KERN_INFO"i2c_pxa_wait_for_int: Transmit interrupt on enter\n"); -+#endif -+ -+ if (wait_type == I2C_RECEIVE){ /* wait on receive */ -+ -+ do { -+ i2c_pxa_wait_for_ite(); -+ } while (!(rx_finished) && timeout-- && !signal_pending(current)); -+ -+#ifdef DEBUG -+ if (timeout<0){ -+ if (tx_finished) -+ printk("Error: i2c-algo-pxa.o: received a tx" -+ " interrupt while waiting on a rx in wait_for_int"); -+ } -+#endif -+ } else { /* wait on transmit */ -+ -+ do { -+ i2c_pxa_wait_for_ite(); -+ } while (!(tx_finished) && timeout-- && !signal_pending(current)); -+ -+#ifdef DEBUG -+ if (timeout<0){ -+ if (rx_finished) -+ printk("Error: i2c-algo-pxa.o: received a rx" -+ " interrupt while waiting on a tx in wait_for_int"); -+ } -+#endif -+ } -+ -+ udelay(ACK_DELAY); /* this is needed for the bus error */ -+ -+ tx_finished=0; -+ rx_finished=0; -+ -+ if (bus_error){ -+ bus_error=0; -+ if( i2c_debug > 2)printk("wait_for_int: error - no ack.\n"); -+ return BUS_ERROR; -+ } -+ -+ if (signal_pending(current)) { -+ return (-ERESTARTSYS); -+ } else if (timeout < 0) { -+ if( i2c_debug > 2)printk("wait_for_int: timeout.\n"); -+ return(-EIO); -+ } else -+ return(0); -+} -+ -+static void i2c_pxa_transfer( int lastbyte, int receive, int midbyte) -+{ -+ if( lastbyte) -+ { -+ if( receive==I2C_RECEIVE) ICR |= ICR_ACKNAK; -+ i2c_pxa_stop(); -+ } -+ else if( midbyte) -+ { -+ i2c_pxa_midbyte(); -+ } -+ ICR |= ICR_TB; -+} -+ -+static void i2c_pxa_reset( void) -+{ -+#ifdef DEBUG -+ printk("Resetting I2C Controller Unit\n"); -+#endif -+ -+ /* abort any transfer currently under way */ -+ i2c_pxa_abort(); -+ -+ /* reset according to 9.8 */ -+ ICR = ICR_UR; -+ ISR = I2C_ISR_INIT; -+ ICR &= ~ICR_UR; -+ -+ /* set the global I2C clock on */ -+ CKEN |= CKEN14_I2C; -+ -+ /* set our slave address */ -+ ISAR = I2C_PXA_SLAVE_ADDR; -+ -+ /* set control register values */ -+ ICR = I2C_ICR_INIT; -+ -+ /* clear any leftover states from prior transmissions */ -+ i2c_pending = rx_finished = tx_finished = bus_error = 0; -+ -+ /* enable unit */ -+ ICR |= ICR_IUE; -+ udelay(100); -+} -+ -+static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *regs) -+{ -+ unsigned long flags; -+ int status, wakeup = 0; -+ status = (ISR); -+ -+ if (status & ISR_BED){ -+ (ISR) |= ISR_BED; -+ bus_error=ISR_BED; -+ wakeup = 1; -+ } -+ if (status & ISR_ITE){ -+ (ISR) |= ISR_ITE; -+ tx_finished=ISR_ITE; -+ wakeup = 1; -+ } -+ if (status & ISR_IRF){ -+ (ISR) |= ISR_IRF; -+ rx_finished=ISR_IRF; -+ wakeup = 1; -+ } -+ if (wakeup) { -+ spin_lock_irqsave(&i2c_pxa_irqlock, flags); -+ i2c_pending = 1; -+ spin_unlock_irqrestore(&i2c_pxa_irqlock, flags); -+ wake_up_interruptible(&i2c_wait); -+ } -+ return IRQ_HANDLED; -+} -+ -+static int i2c_pxa_resource_init( void) -+{ -+ init_waitqueue_head(&i2c_wait); -+ -+ if (request_irq(IRQ_I2C, &i2c_pxa_handler, SA_INTERRUPT, "I2C", 0) < 0) { -+ irq = 0; -+ if(i2c_debug) -+ printk(KERN_INFO "I2C: Failed to register I2C irq %i\n", IRQ_I2C); -+ return -ENODEV; -+ } -+ return 0; -+} -+ -+static void i2c_pxa_resource_release( void) -+{ -+ if( irq > 0) -+ { -+ disable_irq(irq); -+ free_irq(irq,0); -+ irq=0; -+ } -+} -+ -+static int i2c_pxa_client_register(struct i2c_client *client) -+{ -+ return 0; -+} -+ -+static int i2c_pxa_client_unregister(struct i2c_client *client) -+{ -+ return 0; -+} -+ -+static struct i2c_algo_pxa_data i2c_pxa_data = { -+ write_byte: i2c_pxa_write_byte, -+ read_byte: i2c_pxa_read_byte, -+ -+ start: i2c_pxa_start, -+ repeat_start: i2c_pxa_repeat_start, -+ stop: i2c_pxa_stop, -+ abort: i2c_pxa_abort, -+ -+ wait_bus_not_busy: i2c_pxa_wait_bus_not_busy, -+ wait_for_interrupt: i2c_pxa_wait_for_int, -+ transfer: i2c_pxa_transfer, -+ reset: i2c_pxa_reset, -+ -+ udelay: 10, -+ timeout: DEF_TIMEOUT, -+}; -+ -+static struct i2c_adapter i2c_pxa_ops = { -+ .owner = THIS_MODULE, -+ .id = I2C_ALGO_PXA, -+ .algo_data = &i2c_pxa_data, -+ .dev = { -+ .name = "PXA I2C Adapter", -+ }, -+ .client_register = i2c_pxa_client_register, -+ .client_unregister = i2c_pxa_client_unregister, -+ .retries = 2, -+}; -+ -+extern int i2c_pxa_add_bus(struct i2c_adapter *); -+extern int i2c_pxa_del_bus(struct i2c_adapter *); -+ -+static int __init i2c_adap_pxa_init(void) -+{ -+ if( i2c_pxa_resource_init() == 0) { -+ -+ if (i2c_pxa_add_bus(&i2c_pxa_ops) < 0) { -+ i2c_pxa_resource_release(); -+ printk(KERN_INFO "I2C: Failed to add bus\n"); -+ return -ENODEV; -+ } -+ } else { -+ return -ENODEV; -+ } -+ -+ printk(KERN_INFO "I2C: Successfully added bus\n"); -+ -+ return 0; -+} -+ -+static void i2c_adap_pxa_exit(void) -+{ -+ i2c_pxa_del_bus( &i2c_pxa_ops); -+ i2c_pxa_resource_release(); -+ -+ printk(KERN_INFO "I2C: Successfully removed bus\n"); -+} -+ -+module_init(i2c_adap_pxa_init); -+module_exit(i2c_adap_pxa_exit); ---- linux-2.6.5/drivers/i2c/busses/Makefile~heh 2004-04-03 22:36:17.000000000 -0500 -+++ linux-2.6.5/drivers/i2c/busses/Makefile 2004-04-30 20:57:36.000000000 -0400 -@@ -21,6 +21,7 @@ - obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o - obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o - obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o -+obj-$(CONFIG_I2C_PXA) += pxa2xx_i2c.o - obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o - obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o - obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o ---- linux-2.6.5/drivers/i2c/algos/Kconfig~heh 2004-04-03 22:37:59.000000000 -0500 -+++ linux-2.6.5/drivers/i2c/algos/Kconfig 2004-04-30 20:57:36.000000000 -0400 -@@ -38,6 +38,18 @@ - This support is also available as a module. If so, the module - will be called i2c-algo-ite. - -+config I2C_ALGOPXA -+ tristate "PXA I2C Algorithm" -+ depends on ARCH_PXA && I2C -+ help -+ This supports the use of the PXA I2C interface found on the Intel -+ PXA 25x and PXA 26x systems. Say Y if you have one of these. -+ You should also say Y for the PXA I2C peripheral driver support below. -+ -+ This support is also available as a module. If you want to compile -+ it as a module, say M here and read Documentation/modules.txt. -+ The module will be called i2c-algo-pxa. -+ - config I2C_ALGO8XX - tristate "MPC8xx CPM I2C interface" - depends on 8xx && I2C ---- /dev/null 2003-09-23 18:19:32.000000000 -0400 -+++ linux-2.6.5/drivers/i2c/algos/i2c-algo-pxa.c 2004-04-30 20:57:36.000000000 -0400 -@@ -0,0 +1,384 @@ -+/* -+ * i2c-algo-pxa.c -+ * -+ * I2C algorithm for the PXA I2C bus access. -+ * Byte driven algorithm similar to pcf. -+ * -+ * Copyright (C) 2002 Intrinsyc Software Inc. -+ * -+ * 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. -+ * -+ * History: -+ * Apr 2002: Initial version [CS] -+ * Jun 2002: Properly seperated algo/adap [FB] -+ * Jan 2003: added limited signal handling [Kai-Uwe Bloem] -+ * Jan 2003: allow SMBUS_QUICK as valid msg [FB] -+ * Jun 2003: updated for 2.5 [Dustin McIntire] -+ * -+ */ -+#include -+#include -+ -+#include -+#include -+#include -+#include /* struct i2c_msg and others */ -+#include -+ -+#include -+ -+/* -+ * Set this to zero to remove all the debug statements via dead code elimination. -+ */ -+//#define DEBUG 1 -+ -+#if DEBUG -+static unsigned int i2c_debug = DEBUG; -+#else -+#define i2c_debug 0 -+#endif -+ -+static int pxa_scan = 1; -+ -+static int i2c_pxa_valid_messages( struct i2c_msg msgs[], int num) -+{ -+ int i; -+ if (num < 1 || num > MAX_MESSAGES){ -+ if( i2c_debug) -+ printk(KERN_INFO "Invalid number of messages (max=%d, num=%d)\n", -+ MAX_MESSAGES, num); -+ return -EINVAL; -+ } -+ -+ /* check consistency of our messages */ -+ for (i=0;ialgo_data; -+ -+ /* increment number of bytes to read by one -- read dummy byte */ -+ for (i = 0; i <= count; i++) { -+ if (i!=0){ -+ /* set ACK to NAK for last received byte ICR[ACKNAK] = 1 -+ only if not a repeated start */ -+ -+ if ((i == count) && last) { -+ adap->transfer( last, I2C_RECEIVE, 0); -+ }else{ -+ adap->transfer( 0, I2C_RECEIVE, 1); -+ } -+ -+ timeout = adap->wait_for_interrupt(I2C_RECEIVE); -+ -+#ifdef DEBUG -+ if (timeout==BUS_ERROR){ -+ printk(KERN_INFO "i2c_pxa_readbytes: bus error -> forcing reset\n"); -+ adap->reset(); -+ return I2C_RETRY; -+ } else -+#endif -+ if (timeout == -ERESTARTSYS) { -+ adap->abort(); -+ return timeout; -+ } else -+ if (timeout){ -+#ifdef DEBUG -+ printk(KERN_INFO "i2c_pxa_readbytes: timeout -> forcing reset\n"); -+#endif -+ adap->reset(); -+ return I2C_RETRY; -+ } -+ -+ } -+ -+ if (i) { -+ buf[i - 1] = adap->read_byte(); -+ } else { -+ adap->read_byte(); /* dummy read */ -+ } -+ } -+ return (i - 1); -+} -+ -+static int i2c_pxa_sendbytes(struct i2c_adapter *i2c_adap, const char *buf, -+ int count, int last) -+{ -+ -+ struct i2c_algo_pxa_data *adap = i2c_adap->algo_data; -+ int wrcount, timeout; -+ -+ for (wrcount=0; wrcountwrite_byte(buf[wrcount]); -+ if ((wrcount==(count-1)) && last) { -+ adap->transfer( last, I2C_TRANSMIT, 0); -+ }else{ -+ adap->transfer( 0, I2C_TRANSMIT, 1); -+ } -+ -+ timeout = adap->wait_for_interrupt(I2C_TRANSMIT); -+ -+#ifdef DEBUG -+ if (timeout==BUS_ERROR) { -+ printk(KERN_INFO "i2c_pxa_sendbytes: bus error -> forcing reset.\n"); -+ adap->reset(); -+ return I2C_RETRY; -+ } else -+#endif -+ if (timeout == -ERESTARTSYS) { -+ adap->abort(); -+ return timeout; -+ } else -+ if (timeout) { -+#ifdef DEBUG -+ printk(KERN_INFO "i2c_pxa_sendbytes: timeout -> forcing reset\n"); -+#endif -+ adap->reset(); -+ return I2C_RETRY; -+ } -+ } -+ return (wrcount); -+} -+ -+ -+static inline int i2c_pxa_set_ctrl_byte(struct i2c_algo_pxa_data * adap, struct i2c_msg *msg) -+{ -+ u16 flags = msg->flags; -+ u8 addr; -+ addr = (u8) ( (0x7f & msg->addr) << 1 ); -+ if (flags & I2C_M_RD ) -+ addr |= 1; -+ if (flags & I2C_M_REV_DIR_ADDR ) -+ addr ^= 1; -+ adap->write_byte(addr); -+ return 0; -+} -+ -+static int i2c_pxa_do_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) -+{ -+ struct i2c_algo_pxa_data * adap; -+ struct i2c_msg *pmsg=NULL; -+ int i; -+ int ret=0, timeout; -+ -+ adap = i2c_adap->algo_data; -+ -+ timeout = adap->wait_bus_not_busy(); -+ -+ if (timeout) { -+ return I2C_RETRY; -+ } -+ -+ for (i = 0;ret >= 0 && i < num; i++) { -+ int last = i + 1 == num; -+ pmsg = &msgs[i]; -+ -+ ret = i2c_pxa_set_ctrl_byte(adap,pmsg); -+ -+ /* Send START */ -+ if (i == 0) { -+ adap->start(); -+ }else{ -+ adap->repeat_start(); -+ } -+ -+ adap->transfer(0, I2C_TRANSMIT, 0); -+ -+ /* Wait for ITE (transmit empty) */ -+ timeout = adap->wait_for_interrupt(I2C_TRANSMIT); -+ -+#ifdef DEBUG -+ /* Check for ACK (bus error) */ -+ if (timeout==BUS_ERROR){ -+ printk(KERN_INFO "i2c_pxa_do_xfer: bus error -> forcing reset\n"); -+ adap->reset(); -+ return I2C_RETRY; -+ } else -+#endif -+ if (timeout == -ERESTARTSYS) { -+ adap->abort(); -+ return timeout; -+ } else -+ if (timeout) { -+#ifdef DEBUG -+ printk(KERN_INFO "i2c_pxa_do_xfer: timeout -> forcing reset\n"); -+#endif -+ adap->reset(); -+ return I2C_RETRY; -+ } -+/* FIXME: handle arbitration... */ -+#if 0 -+ /* Check for bus arbitration loss */ -+ if (adap->arbitration_loss()){ -+ printk("Arbitration loss detected \n"); -+ adap->reset(); -+ return I2C_RETRY; -+ } -+#endif -+ -+ /* Read */ -+ if (pmsg->flags & I2C_M_RD) { -+ /* read bytes into buffer*/ -+ ret = i2c_pxa_readbytes(i2c_adap, pmsg->buf, pmsg->len, last); -+#if DEBUG > 2 -+ if (ret != pmsg->len) { -+ printk(KERN_INFO"i2c_pxa_do_xfer: read %d/%d bytes.\n", -+ ret, pmsg->len); -+ } else { -+ printk(KERN_INFO"i2c_pxa_do_xfer: read %d bytes.\n",ret); -+ } -+#endif -+ } else { /* Write */ -+ ret = i2c_pxa_sendbytes(i2c_adap, pmsg->buf, pmsg->len, last); -+#if DEBUG > 2 -+ if (ret != pmsg->len) { -+ printk(KERN_INFO"i2c_pxa_do_xfer: wrote %d/%d bytes.\n", -+ ret, pmsg->len); -+ } else { -+ printk(KERN_INFO"i2c_pxa_do_xfer: wrote %d bytes.\n",ret); -+ } -+#endif -+ } -+ } -+ -+ if (ret<0){ -+ return ret; -+ }else{ -+ return i; -+ } -+} -+ -+static int i2c_pxa_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) -+{ -+ int retval = i2c_pxa_valid_messages( msgs, num); -+ if( retval > 0) -+ { -+ int i; -+ for (i=i2c_adap->retries; i>=0; i--){ -+ int retval = i2c_pxa_do_xfer(i2c_adap,msgs,num); -+ if (retval!=I2C_RETRY){ -+ return retval; -+ } -+ if( i2c_debug)printk(KERN_INFO"Retrying transmission \n"); -+ udelay(100); -+ } -+ if( i2c_debug)printk(KERN_INFO"Retried %i times\n",i2c_adap->retries); -+ return -EREMOTEIO; -+ -+ } -+ return retval; -+} -+ -+static u32 i2c_pxa_functionality(struct i2c_adapter * adapter) -+{ -+ /* Emulate the SMBUS functions */ -+ return I2C_FUNC_SMBUS_EMUL; -+} -+ -+struct i2c_algorithm i2c_pxa_algorithm = { -+ name: "PXA I2C Algorithm", -+ id: I2C_ALGO_PXA, -+ master_xfer: i2c_pxa_xfer, -+ smbus_xfer: NULL, -+ slave_send: NULL, -+ slave_recv: NULL, -+ algo_control: NULL, -+ functionality: i2c_pxa_functionality, -+}; -+ -+/* -+ * registering functions to load algorithms at runtime -+ */ -+int i2c_pxa_add_bus(struct i2c_adapter *i2c_adap) -+{ -+ struct i2c_algo_pxa_data *adap = i2c_adap->algo_data; -+ -+ printk(KERN_INFO"I2C: Adding %s.\n", i2c_adap->dev.name); -+ -+ i2c_adap->algo = &i2c_pxa_algorithm; -+ -+ MOD_INC_USE_COUNT; -+ -+ /* register new adapter to i2c module... */ -+ i2c_add_adapter(i2c_adap); -+ -+ adap->reset(); -+ -+ /* scan bus */ -+ if (pxa_scan) { -+ int i; -+ printk(KERN_INFO "I2C: Scanning bus "); -+ for (i = 0x02; i < 0xff; i+=2) { -+ if( i==(I2C_PXA_SLAVE_ADDR<<1)) continue; -+ -+ if (adap->wait_bus_not_busy()) { -+ printk(KERN_INFO "I2C: scanning bus %s - TIMEOUT.\n", -+ i2c_adap->dev.name); -+ return -EIO; -+ } -+ adap->write_byte(i); -+ adap->start(); -+ adap->transfer(0, I2C_TRANSMIT, 0); -+ -+ if ((adap->wait_for_interrupt(I2C_TRANSMIT) != BUS_ERROR)) { -+ printk("(%02x)",i>>1); -+ adap->abort(); -+ } else { -+// printk("."); -+ adap->stop(); -+ } -+ udelay(adap->udelay); -+ } -+ printk("\n"); -+ } -+ return 0; -+} -+ -+int i2c_pxa_del_bus(struct i2c_adapter *i2c_adap) -+{ -+ int res; -+ if ((res = i2c_del_adapter(i2c_adap)) < 0) -+ return res; -+ -+ MOD_DEC_USE_COUNT; -+ -+ printk(KERN_INFO "I2C: Removing %s.\n", i2c_adap->dev.name); -+ -+ return 0; -+} -+ -+static int __init i2c_algo_pxa_init (void) -+{ -+ printk(KERN_INFO "I2C: PXA algorithm module loaded.\n"); -+ return 0; -+} -+ -+EXPORT_SYMBOL(i2c_pxa_add_bus); -+EXPORT_SYMBOL(i2c_pxa_del_bus); -+ -+MODULE_PARM(pxa_scan, "i"); -+MODULE_PARM_DESC(pxa_scan, "Scan for active chips on the bus"); -+ -+MODULE_AUTHOR("Intrinsyc Software Inc."); -+MODULE_LICENSE("GPL"); -+ -+module_init(i2c_algo_pxa_init); ---- linux-2.6.5/drivers/i2c/algos/Makefile~heh 2004-04-03 22:37:37.000000000 -0500 -+++ linux-2.6.5/drivers/i2c/algos/Makefile 2004-04-30 20:57:36.000000000 -0400 -@@ -4,6 +4,7 @@ - - obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o - obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o -+obj-$(CONFIG_I2C_ALGOPXA) += i2c-algo-pxa.o - obj-$(CONFIG_I2C_ALGOITE) += i2c-algo-ite.o - - ifeq ($(CONFIG_I2C_DEBUG_ALGO),y) ---- linux-2.6.5/Makefile~heh 2004-04-03 22:37:36.000000000 -0500 -+++ linux-2.6.5/Makefile 2004-04-30 20:57:58.000000000 -0400 -@@ -1,7 +1,7 @@ - VERSION = 2 - PATCHLEVEL = 6 - SUBLEVEL = 5 --EXTRAVERSION = -+EXTRAVERSION = -gnalm1 - NAME=Zonked Quokka - - # *DOCUMENTATION* diff --git a/linux/gumstix_2.6.5-gnalm1-gum0.bb b/linux/gumstix_2.6.5-gnalm1-gum0.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.12/defconfig-ipaqpxa b/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.12/defconfig-ipaqpxa deleted file mode 100644 index 9446168fdb..0000000000 --- a/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.12/defconfig-ipaqpxa +++ /dev/null @@ -1,1575 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_GENERIC_BUST_SPINLOCK is not set -# CONFIG_GENERIC_ISA_DMA is not set - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# System Type -# -# CONFIG_ARCH_ANAKIN is not set -# CONFIG_ARCH_ARCA5K is not set -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -CONFIG_ARCH_PXA=y -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_OMAHA is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_MX1ADS is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_RISCSTATION is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_AT91RM9200DK is not set -# CONFIG_MINIMAL_OOPS is not set - -# -# Linux As Bootldr support -# -# CONFIG_LAB is not set -# CONFIG_BIG_KERNEL is not set -# CONFIG_USE_DATE_CODE is not set - -# -# Archimedes/A5000 Implementations -# - -# -# Archimedes/A5000 Implementations (select only ONE) -# -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set - -# -# Footbridge Implementations -# -# CONFIG_ARCH_CATS is not set -# CONFIG_ARCH_PERSONAL_SERVER is not set -# CONFIG_ARCH_EBSA285_ADDIN is not set -# CONFIG_ARCH_EBSA285_HOST is not set -# CONFIG_ARCH_NETWINDER is not set - -# -# SA11x0 Implementations -# -# CONFIG_SA1100_ACCELENT is not set -# CONFIG_SA1100_ASSABET is not set -# CONFIG_ASSABET_NEPONSET is not set -# CONFIG_SA1100_ADSBITSY is not set -# CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_CEP is not set -# CONFIG_SA1100_CERF is not set -# CONFIG_SA1100_H3100 is not set -# CONFIG_SA1100_H3600 is not set -# CONFIG_SA1100_H3800 is not set -# CONFIG_SA1100_CONSUS is not set -# CONFIG_SA1100_EXTENEX1 is not set -# CONFIG_SA1100_FLEXANET is not set -# CONFIG_SA1100_FREEBIRD is not set -# CONFIG_SA1100_FRODO is not set -# CONFIG_SA1100_GRAPHICSCLIENT is not set -# CONFIG_SA1100_GRAPHICSMASTER is not set -# CONFIG_SA1100_HACKKIT is not set -# CONFIG_SA1100_BADGE4 is not set -# CONFIG_SA1100_JORNADA720 is not set -# CONFIG_SA1100_JORNADA56X is not set -# CONFIG_SA1100_HUW_WEBPANEL is not set -# CONFIG_SA1100_ITSY is not set -# CONFIG_SA1100_LART is not set -# CONFIG_SA1100_NANOENGINE is not set -# CONFIG_SA1100_OMNIMETER is not set -# CONFIG_SA1100_PANGOLIN is not set -# CONFIG_SA1100_PLEB is not set -# CONFIG_SA1100_PT_SYSTEM3 is not set -# CONFIG_SA1100_SHANNON is not set -# CONFIG_SA1100_SHERMAN is not set -# CONFIG_SA1100_SIMPAD is not set -# CONFIG_SA1100_SIMPUTER is not set -# CONFIG_SA1100_PFS168 is not set -# CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_XP860 is not set -# CONFIG_SA1100_YOPY is not set -# CONFIG_SA1100_USB is not set -# CONFIG_SA1100_USB_NETLINK is not set -# CONFIG_SA1100_USB_CHAR is not set -# CONFIG_REGISTERS is not set - -# -# Intel PXA250/210 Implementations -# -# CONFIG_ARCH_LUBBOCK is not set -# CONFIG_ARCH_PXA_IDP is not set -# CONFIG_ARCH_PXA_CERF is not set -CONFIG_ARCH_H3900=y -CONFIG_ARCH_H1900=y -CONFIG_ARCH_H5400=y -# CONFIG_ARCH_H2200 is not set -CONFIG_ARCH_AXIM=y -CONFIG_PXA_USB=m -CONFIG_PXA_USB_NETLINK=m -CONFIG_PXA_USB_CHAR=m - -# -# CLPS711X/EP721X Implementations -# -# CONFIG_ARCH_AUTCPU12 is not set -# CONFIG_ARCH_CDB89712 is not set -# CONFIG_ARCH_CLEP7312 is not set -# CONFIG_ARCH_EDB7211 is not set -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_FORTUNET is not set -# CONFIG_ARCH_EP7211 is not set -# CONFIG_ARCH_EP7212 is not set -# CONFIG_ARCH_ACORN is not set -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set - -# -# Processor Type -# -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -# CONFIG_CPU_ARM610 is not set -# CONFIG_CPU_ARM710 is not set -# CONFIG_CPU_ARM720T is not set -# CONFIG_CPU_ARM920T is not set -# CONFIG_CPU_ARM922T is not set -# CONFIG_PLD is not set -# CONFIG_CPU_ARM926T is not set -# CONFIG_CPU_ARM1020 is not set -# CONFIG_CPU_ARM1026 is not set -# CONFIG_CPU_SA110 is not set -# CONFIG_CPU_SA1100 is not set -CONFIG_CPU_32v5=y -CONFIG_CPU_XSCALE=y -CONFIG_XSCALE_PXA250=y -# CONFIG_XSCALE_80200_OLD is not set -# CONFIG_CPU_32v3 is not set -# CONFIG_CPU_32v4 is not set -# CONFIG_SA1100_IPAQ is not set -CONFIG_PXA_IPAQ=y -CONFIG_IPAQ_HANDHELD=y - -# -# Compaq iPAQ Handheld -# -CONFIG_IPAQ_HAL=m -# CONFIG_H3600_MICRO is not set -CONFIG_IPAQ_HAS_ROSELLA=y -CONFIG_H3600_ASIC=m -CONFIG_H3900_ASIC_DEBUG=m -CONFIG_H5400_ASIC=m -CONFIG_H1900_ASIC=m -CONFIG_H1900_TS=m -CONFIG_H3600_HARDWARE=y -CONFIG_IPAQ_SLEEVE=m -CONFIG_SLEEVE_DEBUG=y -CONFIG_SLEEVE_DEBUG_VERBOSE=0 -# CONFIG_SLEEVE_IRQ_DEMUX is not set - -# -# Dell Axim X5 -# -CONFIG_AXIM_HAL=m - -# -# Processor Features -# -# CONFIG_DISCONTIGMEM is not set - -# -# General setup -# -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set -# CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_CPU_FREQ=y -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -# CONFIG_I82092 is not set -# CONFIG_I82365 is not set -# CONFIG_TCIC is not set -# CONFIG_PCMCIA_CLPS6700 is not set -# CONFIG_PCMCIA_SA1100 is not set -CONFIG_PCMCIA_PXA=m -# CONFIG_MERCURY_BACKPAQ is not set - -# -# MMC/SD Card support -# -CONFIG_MMC=m -CONFIG_MMC_DEBUG=y -CONFIG_MMC_DEBUG_VERBOSE=0 -CONFIG_MMC_SAMSUNG_ASIC=m -# CONFIG_MMC_S3C2410 is not set -CONFIG_MMC_H5400=m -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_XIP_KERNEL is not set - -# -# At least one math emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_FASTFPE is not set -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_PM=y -CONFIG_APM=m -# CONFIG_HWTIMER is not set -# CONFIG_ARTHUR is not set -CONFIG_CMDLINE="keepinitrd" -CONFIG_ALIGNMENT_TRAP=y - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -# CONFIG_PARPORT_SERIAL is not set -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_ARC is not set -# CONFIG_PARPORT_IDP is not set -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -# CONFIG_PARPORT_1284 is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -CONFIG_MTD_DEBUG=y -CONFIG_MTD_DEBUG_VERBOSE=1 -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -CONFIG_MTD_JEDECPROBE=m -CONFIG_MTD_GEN_PROBE=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_NOSWAP=y -# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -CONFIG_MTD_CFI_GEOMETRY=y -# CONFIG_MTD_CFI_B1 is not set -CONFIG_MTD_CFI_B2=y -CONFIG_MTD_CFI_B4=y -# CONFIG_MTD_CFI_B8 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set -# CONFIG_MTD_JEDEC is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -CONFIG_MTD_IPAQ=y -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_CDB89712 is not set -# CONFIG_MTD_SA1100 is not set -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_IQ80310 is not set -# CONFIG_MTD_LUBBOCK is not set -# CONFIG_MTD_EPXA10DB is not set -# CONFIG_MTD_FORTUNET is not set -# CONFIG_MTD_AUTCPU12 is not set -# CONFIG_MTD_EDB7312 is not set -# CONFIG_MTD_H720X is not set -# CONFIG_MTD_IMPA7 is not set -# CONFIG_MTD_CEIVA is not set -# CONFIG_MTD_PCI is not set -# CONFIG_MTD_PCMCIA is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -CONFIG_MTD_BLKMTD=m - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -# CONFIG_MTD_DOCPROBE is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -CONFIG_NVRD=m - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -CONFIG_BLK_DEV_LVM=m -CONFIG_BLK_DEV_DM=m - -# -# Networking options -# -CONFIG_PACKET=m -CONFIG_PACKET_MMAP=y -# CONFIG_NETLINK_DEV is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -# CONFIG_IP_NF_AMANDA is not set -# CONFIG_IP_NF_TFTP is not set -CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_QUEUE is not set -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -# CONFIG_IP_NF_MATCH_PKTTYPE is not set -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -# CONFIG_IP_NF_MATCH_RECENT is not set -# CONFIG_IP_NF_MATCH_ECN is not set -# CONFIG_IP_NF_MATCH_DSCP is not set -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -# CONFIG_IP_NF_MATCH_HELPER is not set -CONFIG_IP_NF_MATCH_STATE=m -# CONFIG_IP_NF_MATCH_CONNTRACK is not set -# CONFIG_IP_NF_MATCH_UNCLEAN is not set -# CONFIG_IP_NF_MATCH_OWNER is not set -CONFIG_IP_NF_FILTER=m -# CONFIG_IP_NF_TARGET_REJECT is not set -# CONFIG_IP_NF_TARGET_MIRROR is not set -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_NAT_LOCAL is not set -# CONFIG_IP_NF_NAT_SNMP_BASIC is not set -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -# CONFIG_IP_NF_TARGET_ECN is not set -# CONFIG_IP_NF_TARGET_DSCP is not set -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -# CONFIG_IP_NF_ARPTABLES is not set -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -# CONFIG_IP_NF_COMPAT_IPFWADM is not set -CONFIG_IPV6=m -CONFIG_IPV6_SUBTREES=y -CONFIG_IPV6_IPV6_TUNNEL=m -CONFIG_IPV6_MOBILITY=m -CONFIG_IPV6_MOBILITY_MN=m -# CONFIG_IPV6_MOBILITY_HA is not set -CONFIG_IPV6_MOBILITY_DEBUG=y - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -# CONFIG_IP6_NF_MATCH_RT is not set -# CONFIG_IP6_NF_MATCH_OPTS is not set -# CONFIG_IP6_NF_MATCH_FRAG is not set -# CONFIG_IP6_NF_MATCH_HL is not set -CONFIG_IP6_NF_MATCH_MULTIPORT=m -# CONFIG_IP6_NF_MATCH_OWNER is not set -CONFIG_IP6_NF_MATCH_MARK=m -# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set -# CONFIG_IP6_NF_MATCH_AHESP is not set -# CONFIG_IP6_NF_MATCH_LENGTH is not set -# CONFIG_IP6_NF_MATCH_EUI64 is not set -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_IPSEC=m - -# -# IPSec options (FreeS/WAN) -# -CONFIG_IPSEC_IPIP=y -CONFIG_IPSEC_AH=y -CONFIG_IPSEC_AUTH_HMAC_MD5=y -CONFIG_IPSEC_AUTH_HMAC_SHA1=y -CONFIG_IPSEC_ESP=y -CONFIG_IPSEC_ENC_3DES=y -CONFIG_IPSEC_IPCOMP=y -CONFIG_IPSEC_DEBUG=y - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -# CONFIG_NET_ETHERNET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_MPPE=m -# CONFIG_PPPOE is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -# CONFIG_STRIP is not set -# CONFIG_WAVELAN is not set -# CONFIG_ARLAN is not set -# CONFIG_AIRONET4500 is not set -# CONFIG_AIRONET4500_NONCS is not set -# CONFIG_AIRONET4500_PROC is not set -# CONFIG_HERMES is not set -# CONFIG_SPECTRUM24T is not set - -# -# Wireless Pcmcia cards support -# -# CONFIG_PCMCIA_HERMES is not set -# CONFIG_AIRO_CS is not set -# CONFIG_WVLAN_CS is not set -# CONFIG_MWVLAN_CS is not set -# CONFIG_HOSTAP is not set -# CONFIG_HOSTAP_CS is not set -CONFIG_NET_WIRELESS=y -CONFIG_ATMELWLAN=y -CONFIG_ATMELWLAN_USB_503A_RFMD=m -CONFIG_ATMELWLAN_PCMCIA_502A=m -CONFIG_ATMELWLAN_PCMCIA_3COM=m -CONFIG_ATMELWLAN_PCMCIA_502AD=m -CONFIG_ATMELWLAN_PCMCIA_502AE=m -CONFIG_ATMELWLAN_PCMCIA_504=m - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_AXNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -# CONFIG_ARCNET_COM20020_CS is not set -# CONFIG_PCMCIA_IBMTR is not set -CONFIG_NET_PCMCIA_RADIO=y -CONFIG_PCMCIA_RAYCS=m -CONFIG_PCMCIA_NETWAVE=m -CONFIG_PCMCIA_WAVELAN=m -# CONFIG_AIRONET4500_CS is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -CONFIG_IRDA=m - -# -# IrDA protocols -# -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y - -# -# IrDA options -# -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -CONFIG_IRDA_DEBUG=y - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m - -# -# Dongle support -# -# CONFIG_DONGLE is not set - -# -# FIR device drivers -# -# CONFIG_USB_IRDA is not set -# CONFIG_NSC_FIR is not set -# CONFIG_WINBOND_FIR is not set -# CONFIG_TOSHIBA_FIR is not set -# CONFIG_SMC_IRCC_FIR is not set -# CONFIG_ALI_FIR is not set -# CONFIG_VLSI_FIR is not set -CONFIG_PXA_FIR=m - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=m - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=m - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=m -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set -# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set -# CONFIG_BLK_DEV_IDEDISK_IBM is not set -# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set -# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set -# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set -# CONFIG_BLK_DEV_IDEDISK_WD is not set -# CONFIG_BLK_DEV_COMMERIAL is not set -# CONFIG_BLK_DEV_TIVO is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=m -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_IDE_CHIPSETS is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_DMA_NONPCI is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set - -# -# SCSI support -# -CONFIG_SCSI=m - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=40 -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_PPA is not set -# CONFIG_SCSI_IMM is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_DEBUG is not set - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_PCMCIA=y -# CONFIG_PCMCIA_AHA152X is not set -# CONFIG_PCMCIA_FDOMAIN is not set -# CONFIG_PCMCIA_NINJA_SCSI is not set -# CONFIG_PCMCIA_QLOGIC is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m -CONFIG_INPUT_UINPUT=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_EXTENDED=y -# CONFIG_SERIAL_MANY_PORTS is not set -# CONFIG_SERIAL_SHARE_IRQ is not set -# CONFIG_SERIAL_DETECT_IRQ is not set -# CONFIG_SERIAL_MULTIPORT is not set -# CONFIG_HUB6 is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_ANAKIN is not set -# CONFIG_SERIAL_ANAKIN_CONSOLE is not set -# CONFIG_SERIAL_S3C2410 is not set -# CONFIG_SERIAL_S3C2410_CONSOLE is not set -# CONFIG_SERIAL_AMBA is not set -# CONFIG_SERIAL_AMBA_CONSOLE is not set -# CONFIG_SERIAL_CLPS711X is not set -# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE is not set -# CONFIG_SERIAL_UART00 is not set -# CONFIG_SERIAL_UART00_CONSOLE is not set -# CONFIG_SERIAL_SA1100 is not set -# CONFIG_SERIAL_SA1100_CONSOLE is not set -# CONFIG_SERIAL_SIR_PXA is not set -# CONFIG_SERIAL_8250 is not set -# CONFIG_SERIAL_8250_CONSOLE is not set -# CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SERIAL_8250_MANY_PORTS is not set -# CONFIG_SERIAL_8250_SHARE_IRQ is not set -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_HUB6 is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 -# CONFIG_PRINTER is not set -# CONFIG_PPDEV is not set -CONFIG_NEWTONKBD=m -# CONFIG_SA1100_PROFILER is not set - -# -# Compaq iPAQ H3600 support -# -CONFIG_TOUCHSCREEN_H3600=m -# CONFIG_H3600_BACKPAQ_FPGA is not set -# CONFIG_H3600_BACKPAQ_ACCEL is not set -# CONFIG_H3600_BACKPAQ_GASGAUGE is not set -# CONFIG_H3600_BACKPAQ_SRAM is not set -# CONFIG_H3600_BACKPAQ_AUDIO is not set -# CONFIG_H3600_STOWAWAY is not set -# CONFIG_H3800_MICROKBD is not set -# CONFIG_SA1100_LIRC is not set -CONFIG_H5400_BUZZER=m -CONFIG_H5400_FSI=m - -# -# I2C support -# -CONFIG_I2C=m -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -CONFIG_I2C_PXA_ALGO=m -CONFIG_I2C_PXA_ADAP=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_PROC=m -# CONFIG_I2C_DS1307 is not set - -# -# L3 serial bus support -# -# CONFIG_L3 is not set -# CONFIG_L3_ALGOBIT is not set -# CONFIG_L3_BIT_SA1100_GPIO is not set - -# -# Other L3 adapters -# -# CONFIG_L3_S3C2410 is not set -# CONFIG_L3_SA1111 is not set -# CONFIG_L3_BACKPAQ is not set -# CONFIG_BIT_SA1100_GPIO is not set - -# -# SPI support -# -# CONFIG_SPI is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=m -# CONFIG_PSMOUSE is not set -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set -# CONFIG_MK712_MOUSE is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_INPUT_NS558 is not set -# CONFIG_INPUT_LIGHTNING is not set -# CONFIG_INPUT_PCIGAME is not set -# CONFIG_INPUT_CS461X is not set -# CONFIG_INPUT_EMU10K1 is not set -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m - -# -# Joysticks -# -# CONFIG_INPUT_ANALOG is not set -# CONFIG_INPUT_A3D is not set -# CONFIG_INPUT_ADI is not set -# CONFIG_INPUT_COBRA is not set -# CONFIG_INPUT_GF2K is not set -# CONFIG_INPUT_GRIP is not set -# CONFIG_INPUT_INTERACT is not set -# CONFIG_INPUT_TMDC is not set -# CONFIG_INPUT_SIDEWINDER is not set -# CONFIG_INPUT_IFORCE_USB is not set -# CONFIG_INPUT_IFORCE_232 is not set -# CONFIG_INPUT_WARRIOR is not set -# CONFIG_INPUT_MAGELLAN is not set -# CONFIG_INPUT_SPACEORB is not set -# CONFIG_INPUT_SPACEBALL is not set -# CONFIG_INPUT_STINGER is not set -# CONFIG_INPUT_DB9 is not set -# CONFIG_INPUT_GAMECON is not set -# CONFIG_INPUT_TURBOGRAFX is not set -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -# CONFIG_ALIM7101_WDT is not set -# CONFIG_SC520_WDT is not set -# CONFIG_PCWATCHDOG is not set -# CONFIG_21285_WATCHDOG is not set -# CONFIG_977_WATCHDOG is not set -# CONFIG_SA1100_WATCHDOG is not set -CONFIG_PXA_WATCHDOG=m -# CONFIG_OMAHA_WATCHDOG is not set -# CONFIG_EUROTECH_WDT is not set -# CONFIG_IB700_WDT is not set -# CONFIG_WAFER_WDT is not set -# CONFIG_I810_TCO is not set -# CONFIG_MIXCOMWD is not set -# CONFIG_60XX_WDT is not set -# CONFIG_SC1200_WDT is not set -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_W83877F_WDT is not set -# CONFIG_WDT is not set -# CONFIG_WDTPCI is not set -# CONFIG_MACHZ_WDT is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -CONFIG_PXA_RTC=m -CONFIG_PXA_RTC_HACK=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# PCMCIA character devices -# -CONFIG_PCMCIA_SERIAL_CS=m -CONFIG_PCMCIA_MOBILISCAN_CS=m -# CONFIG_AXIM_TS is not set -CONFIG_AXIM_KEY=m -# CONFIG_AXIM_KEY_FIX is not set - -# -# Multimedia devices -# -CONFIG_MEDIA=m -CONFIG_VIDEO_DEV=m -CONFIG_V4L2_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -# CONFIG_I2C_PARPORT is not set - -# -# Video Adapters -# -# CONFIG_VIDEO_PMS is not set -# CONFIG_VIDEO_BWQCAM is not set -# CONFIG_VIDEO_CQCAM is not set -CONFIG_VIDEO_CPIA=m -CONFIG_VIDEO_CPIA_USB=m -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_ZORAN_BUZ is not set -# CONFIG_VIDEO_ZORAN_DC10 is not set -# CONFIG_VIDEO_ZORAN_LML33 is not set -# CONFIG_VIDEO_ZR36120 is not set -# CONFIG_VIDEO_MEYE is not set -# CONFIG_VIDEO_CYBERPRO is not set -# CONFIG_VIDEO_H3600_BACKPAQ is not set -# CONFIG_VIDEO_HAWKEYE is not set - -# -# Video for Linux 2 (V4L2) -# -CONFIG_VIDEO_WINNOV_CS=m - -# -# Radio Adapters -# -# CONFIG_RADIO_CADET is not set -# CONFIG_RADIO_RTRACK is not set -# CONFIG_RADIO_RTRACK2 is not set -# CONFIG_RADIO_AZTECH is not set -# CONFIG_RADIO_GEMTEK is not set -# CONFIG_RADIO_GEMTEK_PCI is not set -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_MAESTRO is not set -# CONFIG_RADIO_MIROPCM20 is not set -# CONFIG_RADIO_MIROPCM20_RDS is not set -# CONFIG_RADIO_SF16FMI is not set -# CONFIG_RADIO_TERRATEC is not set -# CONFIG_RADIO_TRUST is not set -# CONFIG_RADIO_TYPHOON is not set -# CONFIG_RADIO_ZOLTRIX is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -CONFIG_CRAMFS=y -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=m -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DRIVERFS_FS is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=m -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_UTF8=m - -# -# Console drivers -# -CONFIG_PC_KEYMAP=y -# CONFIG_VGA_CONSOLE is not set - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_ACORN is not set -# CONFIG_FB_ANAKIN is not set -# CONFIG_FB_CLPS711X is not set -# CONFIG_FB_S3C2410 is not set -# CONFIG_FB_SA1100 is not set -# CONFIG_FB_EPSON1356 is not set -# CONFIG_FB_MQ200 is not set -CONFIG_FB_PXA=y -# CONFIG_FB_PXA_8BPP is not set -CONFIG_FB_PXA_16BPP=y -CONFIG_FB_MQ1100=y -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_VIRTUAL is not set -CONFIG_FBCON_ADVANCED=y -# CONFIG_FBCON_MFB is not set -# CONFIG_FBCON_CFB2 is not set -# CONFIG_FBCON_CFB4 is not set -# CONFIG_FBCON_CFB8 is not set -CONFIG_FBCON_CFB16=y -# CONFIG_FBCON_CFB24 is not set -# CONFIG_FBCON_CFB32 is not set -# CONFIG_FBCON_AFB is not set -# CONFIG_FBCON_ILBM is not set -# CONFIG_FBCON_IPLAN2P2 is not set -# CONFIG_FBCON_IPLAN2P4 is not set -# CONFIG_FBCON_IPLAN2P8 is not set -# CONFIG_FBCON_MAC is not set -# CONFIG_FBCON_VGA_PLANES is not set -# CONFIG_FBCON_VGA is not set -# CONFIG_FBCON_HGA is not set -# CONFIG_FBCON_NO_LOGO is not set -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -CONFIG_FONT_8x8=y -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set - -# -# Sound -# -CONFIG_SOUND=y -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_MIDI_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_MAESTRO3 is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_RME96XX is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -# CONFIG_MIDI_VIA82CXXX is not set -CONFIG_SOUND_H3900_UDA1380=m -CONFIG_SOUND_H5400=m -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -# CONFIG_SOUND_DMAP is not set -# CONFIG_SOUND_AD1816 is not set -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_ADLIB is not set -# CONFIG_SOUND_ACI_MIXER is not set -# CONFIG_SOUND_CS4232 is not set -# CONFIG_SOUND_SSCAPE is not set -# CONFIG_SOUND_GUS is not set -# CONFIG_SOUND_VMIDI is not set -# CONFIG_SOUND_TRIX is not set -# CONFIG_SOUND_MSS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_NM256 is not set -# CONFIG_SOUND_MAD16 is not set -# CONFIG_SOUND_PAS is not set -# CONFIG_PAS_JOYSTICK is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_SB is not set -# CONFIG_SOUND_AWE32_SYNTH is not set -# CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_OPL3SA2 is not set -# CONFIG_SOUND_YMFPCI is not set -# CONFIG_SOUND_YMFPCI_LEGACY is not set -# CONFIG_SOUND_UART6850 is not set -# CONFIG_SOUND_AEDSP16 is not set -# CONFIG_SOUND_VIDC is not set -# CONFIG_SOUND_WAVEARTIST is not set -CONFIG_SOUND_PXA_AC97=m -# CONFIG_SOUND_TVMIXER is not set - -# -# Multimedia Capabilities Port drivers -# -# CONFIG_MCP is not set -# CONFIG_MCP_SA1100 is not set -# CONFIG_MCP_UCB1200 is not set -# CONFIG_MCP_UCB1200_AUDIO is not set -# CONFIG_MCP_UCB1200_TS is not set -# CONFIG_MCP_UCB1400_TS is not set - -# -# Console Switches -# -# CONFIG_SWITCHES is not set - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_LONG_TIMEOUT is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -CONFIG_USB_OHCI=m -# CONFIG_USB_OHCI_SA1111 is not set -CONFIG_USB_OHCI_H5400=m -# CONFIG_USB_OHCI_S3C2410 is not set -# CONFIG_USB_SL811HS is not set - -# -# USB Device Class drivers -# -CONFIG_USB_AUDIO=m -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_BLUETOOTH is not set -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_ACM is not set -CONFIG_USB_PRINTER=m - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_WACOM is not set - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# -CONFIG_USB_IBMCAM=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -# CONFIG_USB_DSBR is not set -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -CONFIG_USB_CDCETHER=m -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_IPAQ is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_KLSI is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_XIRCOM is not set -# CONFIG_USB_SERIAL_OMNINET is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_BRLVGER is not set - -# -# Linux As Bootldr Modules -# -# CONFIG_BIG_KERNEL is not set -# CONFIG_USE_DATE_CODE is not set -# CONFIG_YMODEM is not set -# CONFIG_LAB_DUMMY is not set -# CONFIG_LAB_CRC is not set -# CONFIG_LAB_YMODEM is not set -# CONFIG_LAB_MTD is not set -# CONFIG_LAB_COPY is not set -# CONFIG_LAB_COPY_YMODEM is not set -# CONFIG_LAB_COPY_FLASH is not set -# CONFIG_LAB_COPY_FS is not set -# CONFIG_LAB_COPY_WRAPPER is not set - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -# CONFIG_BLUEZ_HCIUSB is not set -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -# CONFIG_BLUEZ_HCIUART_BCSP_TXCRC is not set -# CONFIG_BLUEZ_HCIBFUSB is not set -CONFIG_BLUEZ_HCIDTL1=m -CONFIG_BLUEZ_HCIBT3C=m -CONFIG_BLUEZ_HCIBLUECARD=m -CONFIG_BLUEZ_HCIBTUART=m -# CONFIG_BLUEZ_HCIVHCI is not set - -# -# Kernel hacking -# -# CONFIG_FRAME_POINTER is not set -# CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_INFO is not set -# CONFIG_NO_PGT_CACHE is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -CONFIG_DEBUG_ERRORS=y -# CONFIG_DEBUG_LL is not set -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.12/ipsec.patch b/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.12/ipsec.patch deleted file mode 100644 index 4e2efc035b..0000000000 --- a/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.12/ipsec.patch +++ /dev/null @@ -1,1446 +0,0 @@ ---- linux/net/Makefile 3 Dec 2003 19:15:16 -0000 1.25 -+++ linux/net/Makefile 20 Feb 2003 15:50:38 -0000 1.24 -@@ -19,6 +19,7 @@ - subdir-$(CONFIG_NETFILTER) += ipv4/netfilter - subdir-$(CONFIG_UNIX) += unix - subdir-$(CONFIG_IPV6) += ipv6 -+subdir-$(CONFIG_IPSEC) += ipsec - - ifneq ($(CONFIG_IPV6),n) - ifneq ($(CONFIG_IPV6),) ---- /dev/null 2004-02-02 20:32:13.000000000 +0000 -+++ linux/include/zlib/zlib.h 2004-07-05 23:56:59.000000000 +0100 -@@ -0,0 +1,893 @@ -+/* zlib.h -- interface of the 'zlib' general purpose compression library -+ version 1.1.4, March 11th, 2002 -+ -+ Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler -+ -+ This software is provided 'as-is', without any express or implied -+ warranty. In no event will the authors be held liable for any damages -+ arising from the use of this software. -+ -+ Permission is granted to anyone to use this software for any purpose, -+ including commercial applications, and to alter it and redistribute it -+ freely, subject to the following restrictions: -+ -+ 1. The origin of this software must not be misrepresented; you must not -+ claim that you wrote the original software. If you use this software -+ in a product, an acknowledgment in the product documentation would be -+ appreciated but is not required. -+ 2. Altered source versions must be plainly marked as such, and must not be -+ misrepresented as being the original software. -+ 3. This notice may not be removed or altered from any source distribution. -+ -+ Jean-loup Gailly Mark Adler -+ jloup@gzip.org madler@alumni.caltech.edu -+ -+ -+ The data format used by the zlib library is described by RFCs (Request for -+ Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt -+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -+*/ -+ -+#ifndef _ZLIB_H -+#define _ZLIB_H -+ -+#include "zconf.h" -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#define ZLIB_VERSION "1.1.4" -+ -+/* -+ The 'zlib' compression library provides in-memory compression and -+ decompression functions, including integrity checks of the uncompressed -+ data. This version of the library supports only one compression method -+ (deflation) but other algorithms will be added later and will have the same -+ stream interface. -+ -+ Compression can be done in a single step if the buffers are large -+ enough (for example if an input file is mmap'ed), or can be done by -+ repeated calls of the compression function. In the latter case, the -+ application must provide more input and/or consume the output -+ (providing more output space) before each call. -+ -+ The library also supports reading and writing files in gzip (.gz) format -+ with an interface similar to that of stdio. -+ -+ The library does not install any signal handler. The decoder checks -+ the consistency of the compressed data, so the library should never -+ crash even in case of corrupted input. -+*/ -+ -+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -+typedef void (*free_func) OF((voidpf opaque, voidpf address)); -+ -+struct internal_state; -+ -+typedef struct z_stream_s { -+ Bytef *next_in; /* next input byte */ -+ uInt avail_in; /* number of bytes available at next_in */ -+ uLong total_in; /* total nb of input bytes read so far */ -+ -+ Bytef *next_out; /* next output byte should be put there */ -+ uInt avail_out; /* remaining free space at next_out */ -+ uLong total_out; /* total nb of bytes output so far */ -+ -+ const char *msg; /* last error message, NULL if no error */ -+ struct internal_state FAR *state; /* not visible by applications */ -+ -+ alloc_func zalloc; /* used to allocate the internal state */ -+ free_func zfree; /* used to free the internal state */ -+ voidpf opaque; /* private data object passed to zalloc and zfree */ -+ -+ int data_type; /* best guess about the data type: ascii or binary */ -+ uLong adler; /* adler32 value of the uncompressed data */ -+ uLong reserved; /* reserved for future use */ -+} z_stream; -+ -+typedef z_stream FAR *z_streamp; -+ -+/* -+ The application must update next_in and avail_in when avail_in has -+ dropped to zero. It must update next_out and avail_out when avail_out -+ has dropped to zero. The application must initialize zalloc, zfree and -+ opaque before calling the init function. All other fields are set by the -+ compression library and must not be updated by the application. -+ -+ The opaque value provided by the application will be passed as the first -+ parameter for calls of zalloc and zfree. This can be useful for custom -+ memory management. The compression library attaches no meaning to the -+ opaque value. -+ -+ zalloc must return Z_NULL if there is not enough memory for the object. -+ If zlib is used in a multi-threaded application, zalloc and zfree must be -+ thread safe. -+ -+ On 16-bit systems, the functions zalloc and zfree must be able to allocate -+ exactly 65536 bytes, but will not be required to allocate more than this -+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, -+ pointers returned by zalloc for objects of exactly 65536 bytes *must* -+ have their offset normalized to zero. The default allocation function -+ provided by this library ensures this (see zutil.c). To reduce memory -+ requirements and avoid any allocation of 64K objects, at the expense of -+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). -+ -+ The fields total_in and total_out can be used for statistics or -+ progress reports. After compression, total_in holds the total size of -+ the uncompressed data and may be saved for use in the decompressor -+ (particularly if the decompressor wants to decompress everything in -+ a single step). -+*/ -+ -+ /* constants */ -+ -+#define Z_NO_FLUSH 0 -+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ -+#define Z_SYNC_FLUSH 2 -+#define Z_FULL_FLUSH 3 -+#define Z_FINISH 4 -+/* Allowed flush values; see deflate() below for details */ -+ -+#define Z_OK 0 -+#define Z_STREAM_END 1 -+#define Z_NEED_DICT 2 -+#define Z_ERRNO (-1) -+#define Z_STREAM_ERROR (-2) -+#define Z_DATA_ERROR (-3) -+#define Z_MEM_ERROR (-4) -+#define Z_BUF_ERROR (-5) -+#define Z_VERSION_ERROR (-6) -+/* Return codes for the compression/decompression functions. Negative -+ * values are errors, positive values are used for special but normal events. -+ */ -+ -+#define Z_NO_COMPRESSION 0 -+#define Z_BEST_SPEED 1 -+#define Z_BEST_COMPRESSION 9 -+#define Z_DEFAULT_COMPRESSION (-1) -+/* compression levels */ -+ -+#define Z_FILTERED 1 -+#define Z_HUFFMAN_ONLY 2 -+#define Z_DEFAULT_STRATEGY 0 -+/* compression strategy; see deflateInit2() below for details */ -+ -+#define Z_BINARY 0 -+#define Z_ASCII 1 -+#define Z_UNKNOWN 2 -+/* Possible values of the data_type field */ -+ -+#define Z_DEFLATED 8 -+/* The deflate compression method (the only one supported in this version) */ -+ -+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ -+ -+#define zlib_version zlibVersion() -+/* for compatibility with versions < 1.0.2 */ -+ -+ /* basic functions */ -+ -+ZEXTERN const char * ZEXPORT zlibVersion OF((void)); -+/* The application can compare zlibVersion and ZLIB_VERSION for consistency. -+ If the first character differs, the library code actually used is -+ not compatible with the zlib.h header file used by the application. -+ This check is automatically made by deflateInit and inflateInit. -+ */ -+ -+/* -+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); -+ -+ Initializes the internal stream state for compression. The fields -+ zalloc, zfree and opaque must be initialized before by the caller. -+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to -+ use default allocation functions. -+ -+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: -+ 1 gives best speed, 9 gives best compression, 0 gives no compression at -+ all (the input data is simply copied a block at a time). -+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and -+ compression (currently equivalent to level 6). -+ -+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory, Z_STREAM_ERROR if level is not a valid compression level, -+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible -+ with the version assumed by the caller (ZLIB_VERSION). -+ msg is set to null if there is no error message. deflateInit does not -+ perform any compression: this will be done by deflate(). -+*/ -+ -+ -+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); -+/* -+ deflate compresses as much data as possible, and stops when the input -+ buffer becomes empty or the output buffer becomes full. It may introduce some -+ output latency (reading input without producing any output) except when -+ forced to flush. -+ -+ The detailed semantics are as follows. deflate performs one or both of the -+ following actions: -+ -+ - Compress more input starting at next_in and update next_in and avail_in -+ accordingly. If not all input can be processed (because there is not -+ enough room in the output buffer), next_in and avail_in are updated and -+ processing will resume at this point for the next call of deflate(). -+ -+ - Provide more output starting at next_out and update next_out and avail_out -+ accordingly. This action is forced if the parameter flush is non zero. -+ Forcing flush frequently degrades the compression ratio, so this parameter -+ should be set only when necessary (in interactive applications). -+ Some output may be provided even if flush is not set. -+ -+ Before the call of deflate(), the application should ensure that at least -+ one of the actions is possible, by providing more input and/or consuming -+ more output, and updating avail_in or avail_out accordingly; avail_out -+ should never be zero before the call. The application can consume the -+ compressed output when it wants, for example when the output buffer is full -+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK -+ and with zero avail_out, it must be called again after making room in the -+ output buffer because there might be more output pending. -+ -+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is -+ flushed to the output buffer and the output is aligned on a byte boundary, so -+ that the decompressor can get all input data available so far. (In particular -+ avail_in is zero after the call if enough output space has been provided -+ before the call.) Flushing may degrade compression for some compression -+ algorithms and so it should be used only when necessary. -+ -+ If flush is set to Z_FULL_FLUSH, all output is flushed as with -+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can -+ restart from this point if previous compressed data has been damaged or if -+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade -+ the compression. -+ -+ If deflate returns with avail_out == 0, this function must be called again -+ with the same value of the flush parameter and more output space (updated -+ avail_out), until the flush is complete (deflate returns with non-zero -+ avail_out). -+ -+ If the parameter flush is set to Z_FINISH, pending input is processed, -+ pending output is flushed and deflate returns with Z_STREAM_END if there -+ was enough output space; if deflate returns with Z_OK, this function must be -+ called again with Z_FINISH and more output space (updated avail_out) but no -+ more input data, until it returns with Z_STREAM_END or an error. After -+ deflate has returned Z_STREAM_END, the only possible operations on the -+ stream are deflateReset or deflateEnd. -+ -+ Z_FINISH can be used immediately after deflateInit if all the compression -+ is to be done in a single step. In this case, avail_out must be at least -+ 0.1% larger than avail_in plus 12 bytes. If deflate does not return -+ Z_STREAM_END, then it must be called again as described above. -+ -+ deflate() sets strm->adler to the adler32 checksum of all input read -+ so far (that is, total_in bytes). -+ -+ deflate() may update data_type if it can make a good guess about -+ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered -+ binary. This field is only for information purposes and does not affect -+ the compression algorithm in any manner. -+ -+ deflate() returns Z_OK if some progress has been made (more input -+ processed or more output produced), Z_STREAM_END if all input has been -+ consumed and all output has been produced (only when flush is set to -+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example -+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible -+ (for example avail_in or avail_out was zero). -+*/ -+ -+ -+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -+/* -+ All dynamically allocated data structures for this stream are freed. -+ This function discards any unprocessed input and does not flush any -+ pending output. -+ -+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the -+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed -+ prematurely (some input or output was discarded). In the error case, -+ msg may be set but then points to a static string (which must not be -+ deallocated). -+*/ -+ -+ -+/* -+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); -+ -+ Initializes the internal stream state for decompression. The fields -+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by -+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact -+ value depends on the compression method), inflateInit determines the -+ compression method from the zlib header and allocates all data structures -+ accordingly; otherwise the allocation will be deferred to the first call of -+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to -+ use default allocation functions. -+ -+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the -+ version assumed by the caller. msg is set to null if there is no error -+ message. inflateInit does not perform any decompression apart from reading -+ the zlib header if present: this will be done by inflate(). (So next_in and -+ avail_in may be modified, but next_out and avail_out are unchanged.) -+*/ -+ -+ -+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -+/* -+ inflate decompresses as much data as possible, and stops when the input -+ buffer becomes empty or the output buffer becomes full. It may some -+ introduce some output latency (reading input without producing any output) -+ except when forced to flush. -+ -+ The detailed semantics are as follows. inflate performs one or both of the -+ following actions: -+ -+ - Decompress more input starting at next_in and update next_in and avail_in -+ accordingly. If not all input can be processed (because there is not -+ enough room in the output buffer), next_in is updated and processing -+ will resume at this point for the next call of inflate(). -+ -+ - Provide more output starting at next_out and update next_out and avail_out -+ accordingly. inflate() provides as much output as possible, until there -+ is no more input data or no more space in the output buffer (see below -+ about the flush parameter). -+ -+ Before the call of inflate(), the application should ensure that at least -+ one of the actions is possible, by providing more input and/or consuming -+ more output, and updating the next_* and avail_* values accordingly. -+ The application can consume the uncompressed output when it wants, for -+ example when the output buffer is full (avail_out == 0), or after each -+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it -+ must be called again after making room in the output buffer because there -+ might be more output pending. -+ -+ If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much -+ output as possible to the output buffer. The flushing behavior of inflate is -+ not specified for values of the flush parameter other than Z_SYNC_FLUSH -+ and Z_FINISH, but the current implementation actually flushes as much output -+ as possible anyway. -+ -+ inflate() should normally be called until it returns Z_STREAM_END or an -+ error. However if all decompression is to be performed in a single step -+ (a single call of inflate), the parameter flush should be set to -+ Z_FINISH. In this case all pending input is processed and all pending -+ output is flushed; avail_out must be large enough to hold all the -+ uncompressed data. (The size of the uncompressed data may have been saved -+ by the compressor for this purpose.) The next operation on this stream must -+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH -+ is never required, but can be used to inform inflate that a faster routine -+ may be used for the single inflate() call. -+ -+ If a preset dictionary is needed at this point (see inflateSetDictionary -+ below), inflate sets strm-adler to the adler32 checksum of the -+ dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise -+ it sets strm->adler to the adler32 checksum of all output produced -+ so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or -+ an error code as described below. At the end of the stream, inflate() -+ checks that its computed adler32 checksum is equal to that saved by the -+ compressor and returns Z_STREAM_END only if the checksum is correct. -+ -+ inflate() returns Z_OK if some progress has been made (more input processed -+ or more output produced), Z_STREAM_END if the end of the compressed data has -+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a -+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was -+ corrupted (input stream not conforming to the zlib format or incorrect -+ adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent -+ (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not -+ enough memory, Z_BUF_ERROR if no progress is possible or if there was not -+ enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR -+ case, the application may then call inflateSync to look for a good -+ compression block. -+*/ -+ -+ -+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -+/* -+ All dynamically allocated data structures for this stream are freed. -+ This function discards any unprocessed input and does not flush any -+ pending output. -+ -+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state -+ was inconsistent. In the error case, msg may be set but then points to a -+ static string (which must not be deallocated). -+*/ -+ -+ /* Advanced functions */ -+ -+/* -+ The following functions are needed only in some special applications. -+*/ -+ -+/* -+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, -+ int level, -+ int method, -+ int windowBits, -+ int memLevel, -+ int strategy)); -+ -+ This is another version of deflateInit with more compression options. The -+ fields next_in, zalloc, zfree and opaque must be initialized before by -+ the caller. -+ -+ The method parameter is the compression method. It must be Z_DEFLATED in -+ this version of the library. -+ -+ The windowBits parameter is the base two logarithm of the window size -+ (the size of the history buffer). It should be in the range 8..15 for this -+ version of the library. Larger values of this parameter result in better -+ compression at the expense of memory usage. The default value is 15 if -+ deflateInit is used instead. -+ -+ The memLevel parameter specifies how much memory should be allocated -+ for the internal compression state. memLevel=1 uses minimum memory but -+ is slow and reduces compression ratio; memLevel=9 uses maximum memory -+ for optimal speed. The default value is 8. See zconf.h for total memory -+ usage as a function of windowBits and memLevel. -+ -+ The strategy parameter is used to tune the compression algorithm. Use the -+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a -+ filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no -+ string match). Filtered data consists mostly of small values with a -+ somewhat random distribution. In this case, the compression algorithm is -+ tuned to compress them better. The effect of Z_FILTERED is to force more -+ Huffman coding and less string matching; it is somewhat intermediate -+ between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects -+ the compression ratio but not the correctness of the compressed output even -+ if it is not set appropriately. -+ -+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid -+ method). msg is set to null if there is no error message. deflateInit2 does -+ not perform any compression: this will be done by deflate(). -+*/ -+ -+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, -+ const Bytef *dictionary, -+ uInt dictLength)); -+/* -+ Initializes the compression dictionary from the given byte sequence -+ without producing any compressed output. This function must be called -+ immediately after deflateInit, deflateInit2 or deflateReset, before any -+ call of deflate. The compressor and decompressor must use exactly the same -+ dictionary (see inflateSetDictionary). -+ -+ The dictionary should consist of strings (byte sequences) that are likely -+ to be encountered later in the data to be compressed, with the most commonly -+ used strings preferably put towards the end of the dictionary. Using a -+ dictionary is most useful when the data to be compressed is short and can be -+ predicted with good accuracy; the data can then be compressed better than -+ with the default empty dictionary. -+ -+ Depending on the size of the compression data structures selected by -+ deflateInit or deflateInit2, a part of the dictionary may in effect be -+ discarded, for example if the dictionary is larger than the window size in -+ deflate or deflate2. Thus the strings most likely to be useful should be -+ put at the end of the dictionary, not at the front. -+ -+ Upon return of this function, strm->adler is set to the Adler32 value -+ of the dictionary; the decompressor may later use this value to determine -+ which dictionary has been used by the compressor. (The Adler32 value -+ applies to the whole dictionary even if only a subset of the dictionary is -+ actually used by the compressor.) -+ -+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a -+ parameter is invalid (such as NULL dictionary) or the stream state is -+ inconsistent (for example if deflate has already been called for this stream -+ or if the compression method is bsort). deflateSetDictionary does not -+ perform any compression: this will be done by deflate(). -+*/ -+ -+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, -+ z_streamp source)); -+/* -+ Sets the destination stream as a complete copy of the source stream. -+ -+ This function can be useful when several compression strategies will be -+ tried, for example when there are several ways of pre-processing the input -+ data with a filter. The streams that will be discarded should then be freed -+ by calling deflateEnd. Note that deflateCopy duplicates the internal -+ compression state which can be quite large, so this strategy is slow and -+ can consume lots of memory. -+ -+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent -+ (such as zalloc being NULL). msg is left unchanged in both source and -+ destination. -+*/ -+ -+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -+/* -+ This function is equivalent to deflateEnd followed by deflateInit, -+ but does not free and reallocate all the internal compression state. -+ The stream will keep the same compression level and any other attributes -+ that may have been set by deflateInit2. -+ -+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source -+ stream state was inconsistent (such as zalloc or state being NULL). -+*/ -+ -+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, -+ int level, -+ int strategy)); -+/* -+ Dynamically update the compression level and compression strategy. The -+ interpretation of level and strategy is as in deflateInit2. This can be -+ used to switch between compression and straight copy of the input data, or -+ to switch to a different kind of input data requiring a different -+ strategy. If the compression level is changed, the input available so far -+ is compressed with the old level (and may be flushed); the new level will -+ take effect only at the next call of deflate(). -+ -+ Before the call of deflateParams, the stream state must be set as for -+ a call of deflate(), since the currently available input may have to -+ be compressed and flushed. In particular, strm->avail_out must be non-zero. -+ -+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source -+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR -+ if strm->avail_out was zero. -+*/ -+ -+/* -+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, -+ int windowBits)); -+ -+ This is another version of inflateInit with an extra parameter. The -+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized -+ before by the caller. -+ -+ The windowBits parameter is the base two logarithm of the maximum window -+ size (the size of the history buffer). It should be in the range 8..15 for -+ this version of the library. The default value is 15 if inflateInit is used -+ instead. If a compressed stream with a larger window size is given as -+ input, inflate() will return with the error code Z_DATA_ERROR instead of -+ trying to allocate a larger window. -+ -+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative -+ memLevel). msg is set to null if there is no error message. inflateInit2 -+ does not perform any decompression apart from reading the zlib header if -+ present: this will be done by inflate(). (So next_in and avail_in may be -+ modified, but next_out and avail_out are unchanged.) -+*/ -+ -+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, -+ const Bytef *dictionary, -+ uInt dictLength)); -+/* -+ Initializes the decompression dictionary from the given uncompressed byte -+ sequence. This function must be called immediately after a call of inflate -+ if this call returned Z_NEED_DICT. The dictionary chosen by the compressor -+ can be determined from the Adler32 value returned by this call of -+ inflate. The compressor and decompressor must use exactly the same -+ dictionary (see deflateSetDictionary). -+ -+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a -+ parameter is invalid (such as NULL dictionary) or the stream state is -+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the -+ expected one (incorrect Adler32 value). inflateSetDictionary does not -+ perform any decompression: this will be done by subsequent calls of -+ inflate(). -+*/ -+ -+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -+/* -+ Skips invalid compressed data until a full flush point (see above the -+ description of deflate with Z_FULL_FLUSH) can be found, or until all -+ available input is skipped. No output is provided. -+ -+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR -+ if no more input was provided, Z_DATA_ERROR if no flush point has been found, -+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success -+ case, the application may save the current current value of total_in which -+ indicates where valid compressed data was found. In the error case, the -+ application may repeatedly call inflateSync, providing more input each time, -+ until success or end of the input data. -+*/ -+ -+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -+/* -+ This function is equivalent to inflateEnd followed by inflateInit, -+ but does not free and reallocate all the internal decompression state. -+ The stream will keep attributes that may have been set by inflateInit2. -+ -+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source -+ stream state was inconsistent (such as zalloc or state being NULL). -+*/ -+ -+ -+ /* utility functions */ -+ -+/* -+ The following utility functions are implemented on top of the -+ basic stream-oriented functions. To simplify the interface, some -+ default options are assumed (compression level and memory usage, -+ standard memory allocation functions). The source code of these -+ utility functions can easily be modified if you need special options. -+*/ -+ -+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, -+ const Bytef *source, uLong sourceLen)); -+/* -+ Compresses the source buffer into the destination buffer. sourceLen is -+ the byte length of the source buffer. Upon entry, destLen is the total -+ size of the destination buffer, which must be at least 0.1% larger than -+ sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the -+ compressed buffer. -+ This function can be used to compress a whole file at once if the -+ input file is mmap'ed. -+ compress returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory, Z_BUF_ERROR if there was not enough room in the output -+ buffer. -+*/ -+ -+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, -+ const Bytef *source, uLong sourceLen, -+ int level)); -+/* -+ Compresses the source buffer into the destination buffer. The level -+ parameter has the same meaning as in deflateInit. sourceLen is the byte -+ length of the source buffer. Upon entry, destLen is the total size of the -+ destination buffer, which must be at least 0.1% larger than sourceLen plus -+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. -+ -+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_BUF_ERROR if there was not enough room in the output buffer, -+ Z_STREAM_ERROR if the level parameter is invalid. -+*/ -+ -+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, -+ const Bytef *source, uLong sourceLen)); -+/* -+ Decompresses the source buffer into the destination buffer. sourceLen is -+ the byte length of the source buffer. Upon entry, destLen is the total -+ size of the destination buffer, which must be large enough to hold the -+ entire uncompressed data. (The size of the uncompressed data must have -+ been saved previously by the compressor and transmitted to the decompressor -+ by some mechanism outside the scope of this compression library.) -+ Upon exit, destLen is the actual size of the compressed buffer. -+ This function can be used to decompress a whole file at once if the -+ input file is mmap'ed. -+ -+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory, Z_BUF_ERROR if there was not enough room in the output -+ buffer, or Z_DATA_ERROR if the input data was corrupted. -+*/ -+ -+ -+typedef voidp gzFile; -+ -+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); -+/* -+ Opens a gzip (.gz) file for reading or writing. The mode parameter -+ is as in fopen ("rb" or "wb") but can also include a compression level -+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for -+ Huffman only compression as in "wb1h". (See the description -+ of deflateInit2 for more information about the strategy parameter.) -+ -+ gzopen can be used to read a file which is not in gzip format; in this -+ case gzread will directly read from the file without decompression. -+ -+ gzopen returns NULL if the file could not be opened or if there was -+ insufficient memory to allocate the (de)compression state; errno -+ can be checked to distinguish the two cases (if errno is zero, the -+ zlib error is Z_MEM_ERROR). */ -+ -+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -+/* -+ gzdopen() associates a gzFile with the file descriptor fd. File -+ descriptors are obtained from calls like open, dup, creat, pipe or -+ fileno (in the file has been previously opened with fopen). -+ The mode parameter is as in gzopen. -+ The next call of gzclose on the returned gzFile will also close the -+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file -+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). -+ gzdopen returns NULL if there was insufficient memory to allocate -+ the (de)compression state. -+*/ -+ -+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -+/* -+ Dynamically update the compression level or strategy. See the description -+ of deflateInit2 for the meaning of these parameters. -+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not -+ opened for writing. -+*/ -+ -+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -+/* -+ Reads the given number of uncompressed bytes from the compressed file. -+ If the input file was not in gzip format, gzread copies the given number -+ of bytes into the buffer. -+ gzread returns the number of uncompressed bytes actually read (0 for -+ end of file, -1 for error). */ -+ -+ZEXTERN int ZEXPORT gzwrite OF((gzFile file, -+ const voidp buf, unsigned len)); -+/* -+ Writes the given number of uncompressed bytes into the compressed file. -+ gzwrite returns the number of uncompressed bytes actually written -+ (0 in case of error). -+*/ -+ -+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); -+/* -+ Converts, formats, and writes the args to the compressed file under -+ control of the format string, as in fprintf. gzprintf returns the number of -+ uncompressed bytes actually written (0 in case of error). -+*/ -+ -+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -+/* -+ Writes the given null-terminated string to the compressed file, excluding -+ the terminating null character. -+ gzputs returns the number of characters written, or -1 in case of error. -+*/ -+ -+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -+/* -+ Reads bytes from the compressed file until len-1 characters are read, or -+ a newline character is read and transferred to buf, or an end-of-file -+ condition is encountered. The string is then terminated with a null -+ character. -+ gzgets returns buf, or Z_NULL in case of error. -+*/ -+ -+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -+/* -+ Writes c, converted to an unsigned char, into the compressed file. -+ gzputc returns the value that was written, or -1 in case of error. -+*/ -+ -+ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -+/* -+ Reads one byte from the compressed file. gzgetc returns this byte -+ or -1 in case of end of file or error. -+*/ -+ -+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -+/* -+ Flushes all pending output into the compressed file. The parameter -+ flush is as in the deflate() function. The return value is the zlib -+ error number (see function gzerror below). gzflush returns Z_OK if -+ the flush parameter is Z_FINISH and all output could be flushed. -+ gzflush should be called only when strictly necessary because it can -+ degrade compression. -+*/ -+ -+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, -+ z_off_t offset, int whence)); -+/* -+ Sets the starting position for the next gzread or gzwrite on the -+ given compressed file. The offset represents a number of bytes in the -+ uncompressed data stream. The whence parameter is defined as in lseek(2); -+ the value SEEK_END is not supported. -+ If the file is opened for reading, this function is emulated but can be -+ extremely slow. If the file is opened for writing, only forward seeks are -+ supported; gzseek then compresses a sequence of zeroes up to the new -+ starting position. -+ -+ gzseek returns the resulting offset location as measured in bytes from -+ the beginning of the uncompressed stream, or -1 in case of error, in -+ particular if the file is opened for writing and the new starting position -+ would be before the current position. -+*/ -+ -+ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -+/* -+ Rewinds the given file. This function is supported only for reading. -+ -+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -+*/ -+ -+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); -+/* -+ Returns the starting position for the next gzread or gzwrite on the -+ given compressed file. This position represents a number of bytes in the -+ uncompressed data stream. -+ -+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -+*/ -+ -+ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -+/* -+ Returns 1 when EOF has previously been detected reading the given -+ input stream, otherwise zero. -+*/ -+ -+ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -+/* -+ Flushes all pending output if necessary, closes the compressed file -+ and deallocates all the (de)compression state. The return value is the zlib -+ error number (see function gzerror below). -+*/ -+ -+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -+/* -+ Returns the error message for the last error which occurred on the -+ given compressed file. errnum is set to zlib error number. If an -+ error occurred in the file system and not in the compression library, -+ errnum is set to Z_ERRNO and the application may consult errno -+ to get the exact error code. -+*/ -+ -+ /* checksum functions */ -+ -+/* -+ These functions are not related to compression but are exported -+ anyway because they might be useful in applications using the -+ compression library. -+*/ -+ -+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -+ -+/* -+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and -+ return the updated checksum. If buf is NULL, this function returns -+ the required initial value for the checksum. -+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed -+ much faster. Usage example: -+ -+ uLong adler = adler32(0L, Z_NULL, 0); -+ -+ while (read_buffer(buffer, length) != EOF) { -+ adler = adler32(adler, buffer, length); -+ } -+ if (adler != original_adler) error(); -+*/ -+ -+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -+/* -+ Update a running crc with the bytes buf[0..len-1] and return the updated -+ crc. If buf is NULL, this function returns the required initial value -+ for the crc. Pre- and post-conditioning (one's complement) is performed -+ within this function so it shouldn't be done by the application. -+ Usage example: -+ -+ uLong crc = crc32(0L, Z_NULL, 0); -+ -+ while (read_buffer(buffer, length) != EOF) { -+ crc = crc32(crc, buffer, length); -+ } -+ if (crc != original_crc) error(); -+*/ -+ -+ -+ /* various hacks, don't look :) */ -+ -+/* deflateInit and inflateInit are macros to allow checking the zlib version -+ * and the compiler's view of z_stream: -+ */ -+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, -+ const char *version, int stream_size)); -+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, -+ const char *version, int stream_size)); -+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, -+ int windowBits, int memLevel, -+ int strategy, const char *version, -+ int stream_size)); -+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, -+ const char *version, int stream_size)); -+#define deflateInit(strm, level) \ -+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -+#define inflateInit(strm) \ -+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ -+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ -+ (strategy), ZLIB_VERSION, sizeof(z_stream)) -+#define inflateInit2(strm, windowBits) \ -+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) -+ -+ -+#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) -+ struct internal_state {int dummy;}; /* hack for buggy compilers */ -+#endif -+ -+ZEXTERN const char * ZEXPORT zError OF((int err)); -+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); -+ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* _ZLIB_H */ ---- /dev/null 2004-02-02 20:32:13.000000000 +0000 -+++ linux/include/zlib/zutil.h 2004-07-05 23:59:30.000000000 +0100 -@@ -0,0 +1,225 @@ -+/* zutil.h -- internal interface and configuration of the compression library -+ * Copyright (C) 1995-2002 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+/* @(#) $Id$ */ -+ -+#ifndef _Z_UTIL_H -+#define _Z_UTIL_H -+ -+#include "zlib.h" -+ -+#include -+#define HAVE_MEMCPY -+ -+#if 0 // #ifdef STDC -+# include -+# include -+# include -+#endif -+#ifndef __KERNEL__ -+#ifdef NO_ERRNO_H -+ extern int errno; -+#else -+# include -+#endif -+#endif -+ -+#ifndef local -+# define local static -+#endif -+/* compile with -Dlocal if your debugger can't find static symbols */ -+ -+typedef unsigned char uch; -+typedef uch FAR uchf; -+typedef unsigned short ush; -+typedef ush FAR ushf; -+typedef unsigned long ulg; -+ -+extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ -+/* (size given to avoid silly warnings with Visual C++) */ -+ -+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] -+ -+#define ERR_RETURN(strm,err) \ -+ return (strm->msg = ERR_MSG(err), (err)) -+/* To be used only when the state is known to be valid */ -+ -+ /* common constants */ -+ -+#ifndef DEF_WBITS -+# define DEF_WBITS MAX_WBITS -+#endif -+/* default windowBits for decompression. MAX_WBITS is for compression only */ -+ -+#if MAX_MEM_LEVEL >= 8 -+# define DEF_MEM_LEVEL 8 -+#else -+# define DEF_MEM_LEVEL MAX_MEM_LEVEL -+#endif -+/* default memLevel */ -+ -+#define STORED_BLOCK 0 -+#define STATIC_TREES 1 -+#define DYN_TREES 2 -+/* The three kinds of block type */ -+ -+#define MIN_MATCH 3 -+#define MAX_MATCH 258 -+/* The minimum and maximum match lengths */ -+ -+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ -+ -+ /* target dependencies */ -+ -+#ifdef MSDOS -+# define OS_CODE 0x00 -+# if defined(__TURBOC__) || defined(__BORLANDC__) -+# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) -+ /* Allow compilation with ANSI keywords only enabled */ -+ void _Cdecl farfree( void *block ); -+ void *_Cdecl farmalloc( unsigned long nbytes ); -+# else -+# include -+# endif -+# else /* MSC or DJGPP */ -+# include -+# endif -+#endif -+ -+#ifdef OS2 -+# define OS_CODE 0x06 -+#endif -+ -+#ifdef WIN32 /* Window 95 & Windows NT */ -+# define OS_CODE 0x0b -+#endif -+ -+#if defined(VAXC) || defined(VMS) -+# define OS_CODE 0x02 -+# define F_OPEN(name, mode) \ -+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") -+#endif -+ -+#ifdef AMIGA -+# define OS_CODE 0x01 -+#endif -+ -+#if defined(ATARI) || defined(atarist) -+# define OS_CODE 0x05 -+#endif -+ -+#if defined(MACOS) || defined(TARGET_OS_MAC) -+# define OS_CODE 0x07 -+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -+# include /* for fdopen */ -+# else -+# ifndef fdopen -+# define fdopen(fd,mode) NULL /* No fdopen() */ -+# endif -+# endif -+#endif -+ -+#ifdef __50SERIES /* Prime/PRIMOS */ -+# define OS_CODE 0x0F -+#endif -+ -+#ifdef TOPS20 -+# define OS_CODE 0x0a -+#endif -+ -+#if defined(_BEOS_) || defined(RISCOS) -+# define fdopen(fd,mode) NULL /* No fdopen() */ -+#endif -+ -+#if (defined(_MSC_VER) && (_MSC_VER > 600)) -+# define fdopen(fd,type) _fdopen(fd,type) -+#endif -+ -+ -+ /* Common defaults */ -+ -+#ifndef OS_CODE -+# define OS_CODE 0x03 /* assume Unix */ -+#endif -+ -+#ifndef F_OPEN -+# define F_OPEN(name, mode) fopen((name), (mode)) -+#endif -+ -+ /* functions */ -+ -+#ifdef HAVE_STRERROR -+ extern char *strerror OF((int)); -+# define zstrerror(errnum) strerror(errnum) -+#else -+# define zstrerror(errnum) "" -+#endif -+ -+#if defined(pyr) -+# define NO_MEMCPY -+#endif -+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) -+ /* Use our own functions for small and medium model with MSC <= 5.0. -+ * You may have to use the same strategy for Borland C (untested). -+ * The __SC__ check is for Symantec. -+ */ -+# define NO_MEMCPY -+#endif -+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) -+# define HAVE_MEMCPY -+#endif -+#ifdef HAVE_MEMCPY -+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ -+# define zmemcpy _fmemcpy -+# define zmemcmp _fmemcmp -+# define zmemzero(dest, len) _fmemset(dest, 0, len) -+# else -+# define zmemcpy memcpy -+# define zmemcmp memcmp -+# define zmemzero(dest, len) memset(dest, 0, len) -+# endif -+#else -+ extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); -+ extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); -+ extern void zmemzero OF((Bytef* dest, uInt len)); -+#endif -+ -+/* Diagnostic functions */ -+#ifdef DEBUG -+# include -+ extern int z_verbose; -+ extern void z_error OF((char *m)); -+# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -+# define Trace(x) {if (z_verbose>=0) fprintf x ;} -+# define Tracev(x) {if (z_verbose>0) fprintf x ;} -+# define Tracevv(x) {if (z_verbose>1) fprintf x ;} -+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} -+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} -+#else -+# define Assert(cond,msg) -+# define Trace(x) -+# define Tracev(x) -+# define Tracevv(x) -+# define Tracec(c,x) -+# define Tracecv(c,x) -+#endif -+ -+ -+typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, -+ uInt len)); -+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); -+void zcfree OF((voidpf opaque, voidpf ptr)); -+ -+#define ZALLOC(strm, items, size) \ -+ (*((strm)->zalloc))((strm)->opaque, (items), (size)) -+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) -+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} -+ -+#endif /* _Z_UTIL_H */ ---- /dev/null 2004-02-02 20:32:13.000000000 +0000 -+++ linux/include/zconf.h 2004-07-04 15:38:31.000000000 +0100 -@@ -0,0 +1,309 @@ -+/* zconf.h -- configuration of the zlib compression library -+ * Copyright (C) 1995-2002 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* @(#) $Id$ */ -+ -+#ifndef _ZCONF_H -+#define _ZCONF_H -+ -+/* -+ * If you *really* need a unique prefix for all types and library functions, -+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. -+ */ -+#ifdef IPCOMP_PREFIX -+# define deflateInit_ ipcomp_deflateInit_ -+# define deflate ipcomp_deflate -+# define deflateEnd ipcomp_deflateEnd -+# define inflateInit_ ipcomp_inflateInit_ -+# define inflate ipcomp_inflate -+# define inflateEnd ipcomp_inflateEnd -+# define deflateInit2_ ipcomp_deflateInit2_ -+# define deflateSetDictionary ipcomp_deflateSetDictionary -+# define deflateCopy ipcomp_deflateCopy -+# define deflateReset ipcomp_deflateReset -+# define deflateParams ipcomp_deflateParams -+# define inflateInit2_ ipcomp_inflateInit2_ -+# define inflateSetDictionary ipcomp_inflateSetDictionary -+# define inflateSync ipcomp_inflateSync -+# define inflateSyncPoint ipcomp_inflateSyncPoint -+# define inflateReset ipcomp_inflateReset -+# define compress ipcomp_compress -+# define compress2 ipcomp_compress2 -+# define uncompress ipcomp_uncompress -+# define adler32 ipcomp_adler32 -+# define crc32 ipcomp_crc32 -+# define get_crc_table ipcomp_get_crc_table -+/* SSS: these also need to be prefixed to avoid clash with ppp_deflate and ext2compression */ -+# define inflate_blocks ipcomp_deflate_blocks -+# define inflate_blocks_free ipcomp_deflate_blocks_free -+# define inflate_blocks_new ipcomp_inflate_blocks_new -+# define inflate_blocks_reset ipcomp_inflate_blocks_reset -+# define inflate_blocks_sync_point ipcomp_inflate_blocks_sync_point -+# define inflate_set_dictionary ipcomp_inflate_set_dictionary -+# define inflate_codes ipcomp_inflate_codes -+# define inflate_codes_free ipcomp_inflate_codes_free -+# define inflate_codes_new ipcomp_inflate_codes_new -+# define inflate_fast ipcomp_inflate_fast -+# define inflate_trees_bits ipcomp_inflate_trees_bits -+# define inflate_trees_dynamic ipcomp_inflate_trees_dynamic -+# define inflate_trees_fixed ipcomp_inflate_trees_fixed -+# define inflate_flush ipcomp_inflate_flush -+# define inflate_mask ipcomp_inflate_mask -+# define _dist_code _ipcomp_dist_code -+# define _length_code _ipcomp_length_code -+# define _tr_align _ipcomp_tr_align -+# define _tr_flush_block _ipcomp_tr_flush_block -+# define _tr_init _ipcomp_tr_init -+# define _tr_stored_block _ipcomp_tr_stored_block -+# define _tr_tally _ipcomp_tr_tally -+# define zError ipcomp_zError -+# define z_errmsg ipcomp_z_errmsg -+# define zlibVersion ipcomp_zlibVersion -+# define match_init ipcomp_match_init -+# define longest_match ipcomp_longest_match -+#endif -+ -+#ifdef Z_PREFIX -+# define Byte z_Byte -+# define uInt z_uInt -+# define uLong z_uLong -+# define Bytef z_Bytef -+# define charf z_charf -+# define intf z_intf -+# define uIntf z_uIntf -+# define uLongf z_uLongf -+# define voidpf z_voidpf -+# define voidp z_voidp -+#endif -+ -+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) -+# define WIN32 -+#endif -+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) -+# ifndef __32BIT__ -+# define __32BIT__ -+# endif -+#endif -+#if defined(__MSDOS__) && !defined(MSDOS) -+# define MSDOS -+#endif -+ -+/* -+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more -+ * than 64k bytes at a time (needed on systems with 16-bit int). -+ */ -+#if defined(MSDOS) && !defined(__32BIT__) -+# define MAXSEG_64K -+#endif -+#ifdef MSDOS -+# define UNALIGNED_OK -+#endif -+ -+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) -+# define STDC -+#endif -+#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) -+# ifndef STDC -+# define STDC -+# endif -+#endif -+ -+#ifndef STDC -+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -+# define const -+# endif -+#endif -+ -+/* Some Mac compilers merge all .h files incorrectly: */ -+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) -+# define NO_DUMMY_DECL -+#endif -+ -+/* Old Borland C incorrectly complains about missing returns: */ -+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) -+# define NEED_DUMMY_RETURN -+#endif -+ -+ -+/* Maximum value for memLevel in deflateInit2 */ -+#ifndef MAX_MEM_LEVEL -+# ifdef MAXSEG_64K -+# define MAX_MEM_LEVEL 8 -+# else -+# define MAX_MEM_LEVEL 9 -+# endif -+#endif -+ -+/* Maximum value for windowBits in deflateInit2 and inflateInit2. -+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files -+ * created by gzip. (Files created by minigzip can still be extracted by -+ * gzip.) -+ */ -+#ifndef MAX_WBITS -+# define MAX_WBITS 15 /* 32K LZ77 window */ -+#endif -+ -+/* The memory requirements for deflate are (in bytes): -+ (1 << (windowBits+2)) + (1 << (memLevel+9)) -+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) -+ plus a few kilobytes for small objects. For example, if you want to reduce -+ the default memory requirements from 256K to 128K, compile with -+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" -+ Of course this will generally degrade compression (there's no free lunch). -+ -+ The memory requirements for inflate are (in bytes) 1 << windowBits -+ that is, 32K for windowBits=15 (default value) plus a few kilobytes -+ for small objects. -+*/ -+ -+ /* Type declarations */ -+ -+#ifndef OF /* function prototypes */ -+# ifdef STDC -+# define OF(args) args -+# else -+# define OF(args) () -+# endif -+#endif -+ -+/* The following definitions for FAR are needed only for MSDOS mixed -+ * model programming (small or medium model with some far allocations). -+ * This was tested only with MSC; for other MSDOS compilers you may have -+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, -+ * just define FAR to be empty. -+ */ -+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) -+ /* MSC small or medium model */ -+# define SMALL_MEDIUM -+# ifdef _MSC_VER -+# define FAR _far -+# else -+# define FAR far -+# endif -+#endif -+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) -+# ifndef __32BIT__ -+# define SMALL_MEDIUM -+# define FAR _far -+# endif -+#endif -+ -+/* Compile with -DZLIB_DLL for Windows DLL support */ -+#if defined(ZLIB_DLL) -+# if defined(_WINDOWS) || defined(WINDOWS) -+# ifdef FAR -+# undef FAR -+# endif -+# include -+# define ZEXPORT WINAPI -+# ifdef WIN32 -+# define ZEXPORTVA WINAPIV -+# else -+# define ZEXPORTVA FAR _cdecl _export -+# endif -+# endif -+# if defined (__BORLANDC__) -+# if (__BORLANDC__ >= 0x0500) && defined (WIN32) -+# include -+# define ZEXPORT __declspec(dllexport) WINAPI -+# define ZEXPORTRVA __declspec(dllexport) WINAPIV -+# else -+# if defined (_Windows) && defined (__DLL__) -+# define ZEXPORT _export -+# define ZEXPORTVA _export -+# endif -+# endif -+# endif -+#endif -+ -+#if defined (__BEOS__) -+# if defined (ZLIB_DLL) -+# define ZEXTERN extern __declspec(dllexport) -+# else -+# define ZEXTERN extern __declspec(dllimport) -+# endif -+#endif -+ -+#ifndef ZEXPORT -+# define ZEXPORT -+#endif -+#ifndef ZEXPORTVA -+# define ZEXPORTVA -+#endif -+#ifndef ZEXTERN -+# define ZEXTERN extern -+#endif -+ -+#ifndef FAR -+# define FAR -+#endif -+ -+#if !defined(MACOS) && !defined(TARGET_OS_MAC) -+typedef unsigned char Byte; /* 8 bits */ -+#endif -+typedef unsigned int uInt; /* 16 bits or more */ -+typedef unsigned long uLong; /* 32 bits or more */ -+ -+#ifdef SMALL_MEDIUM -+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -+# define Bytef Byte FAR -+#else -+ typedef Byte FAR Bytef; -+#endif -+typedef char FAR charf; -+typedef int FAR intf; -+typedef uInt FAR uIntf; -+typedef uLong FAR uLongf; -+ -+#ifdef STDC -+ typedef void FAR *voidpf; -+ typedef void *voidp; -+#else -+ typedef Byte FAR *voidpf; -+ typedef Byte *voidp; -+#endif -+ -+#ifdef HAVE_UNISTD_H -+# include /* for off_t */ -+# include /* for SEEK_* and off_t */ -+# define z_off_t off_t -+#endif -+#ifndef SEEK_SET -+# define SEEK_SET 0 /* Seek from beginning of file. */ -+# define SEEK_CUR 1 /* Seek from current position. */ -+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -+#endif -+#ifndef z_off_t -+# define z_off_t long -+#endif -+ -+/* MVS linker does not support external names larger than 8 bytes */ -+#if defined(__MVS__) -+# pragma map(deflateInit_,"DEIN") -+# pragma map(deflateInit2_,"DEIN2") -+# pragma map(deflateEnd,"DEEND") -+# pragma map(inflateInit_,"ININ") -+# pragma map(inflateInit2_,"ININ2") -+# pragma map(inflateEnd,"INEND") -+# pragma map(inflateSync,"INSY") -+# pragma map(inflateSetDictionary,"INSEDI") -+# pragma map(inflate_blocks,"INBL") -+# pragma map(inflate_blocks_new,"INBLNE") -+# pragma map(inflate_blocks_free,"INBLFR") -+# pragma map(inflate_blocks_reset,"INBLRE") -+# pragma map(inflate_codes_free,"INCOFR") -+# pragma map(inflate_codes,"INCO") -+# pragma map(inflate_fast,"INFA") -+# pragma map(inflate_flush,"INFLU") -+# pragma map(inflate_mask,"INMA") -+# pragma map(inflate_set_dictionary,"INSEDI2") -+# pragma map(ipcomp_inflate_copyright,"INCOPY") -+# pragma map(inflate_trees_bits,"INTRBI") -+# pragma map(inflate_trees_dynamic,"INTRDY") -+# pragma map(inflate_trees_fixed,"INTRFI") -+# pragma map(inflate_trees_free,"INTRFR") -+#endif -+ -+#endif /* _ZCONF_H */ diff --git a/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.13/defconfig-ipaqpxa b/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.13/defconfig-ipaqpxa deleted file mode 100644 index 681818f9ab..0000000000 --- a/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.13/defconfig-ipaqpxa +++ /dev/null @@ -1,1577 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_GENERIC_BUST_SPINLOCK is not set -# CONFIG_GENERIC_ISA_DMA is not set - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# System Type -# -# CONFIG_ARCH_ANAKIN is not set -# CONFIG_ARCH_ARCA5K is not set -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -CONFIG_ARCH_PXA=y -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_OMAHA is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_MX1ADS is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_RISCSTATION is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_AT91RM9200DK is not set -# CONFIG_MINIMAL_OOPS is not set - -# -# Linux As Bootldr support -# -# CONFIG_LAB is not set -# CONFIG_BIG_KERNEL is not set -# CONFIG_USE_DATE_CODE is not set - -# -# Archimedes/A5000 Implementations -# - -# -# Archimedes/A5000 Implementations (select only ONE) -# -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set - -# -# Footbridge Implementations -# -# CONFIG_ARCH_CATS is not set -# CONFIG_ARCH_PERSONAL_SERVER is not set -# CONFIG_ARCH_EBSA285_ADDIN is not set -# CONFIG_ARCH_EBSA285_HOST is not set -# CONFIG_ARCH_NETWINDER is not set - -# -# SA11x0 Implementations -# -# CONFIG_SA1100_ACCELENT is not set -# CONFIG_SA1100_ASSABET is not set -# CONFIG_ASSABET_NEPONSET is not set -# CONFIG_SA1100_ADSBITSY is not set -# CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_CEP is not set -# CONFIG_SA1100_CERF is not set -# CONFIG_SA1100_H3100 is not set -# CONFIG_SA1100_H3600 is not set -# CONFIG_SA1100_H3800 is not set -# CONFIG_SA1100_CONSUS is not set -# CONFIG_SA1100_EXTENEX1 is not set -# CONFIG_SA1100_FLEXANET is not set -# CONFIG_SA1100_FREEBIRD is not set -# CONFIG_SA1100_FRODO is not set -# CONFIG_SA1100_GRAPHICSCLIENT is not set -# CONFIG_SA1100_GRAPHICSMASTER is not set -# CONFIG_SA1100_HACKKIT is not set -# CONFIG_SA1100_BADGE4 is not set -# CONFIG_SA1100_JORNADA720 is not set -# CONFIG_SA1100_JORNADA56X is not set -# CONFIG_SA1100_HUW_WEBPANEL is not set -# CONFIG_SA1100_ITSY is not set -# CONFIG_SA1100_LART is not set -# CONFIG_SA1100_NANOENGINE is not set -# CONFIG_SA1100_OMNIMETER is not set -# CONFIG_SA1100_PANGOLIN is not set -# CONFIG_SA1100_PLEB is not set -# CONFIG_SA1100_PT_SYSTEM3 is not set -# CONFIG_SA1100_SHANNON is not set -# CONFIG_SA1100_SHERMAN is not set -# CONFIG_SA1100_SIMPAD is not set -# CONFIG_SA1100_SIMPUTER is not set -# CONFIG_SA1100_PFS168 is not set -# CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_XP860 is not set -# CONFIG_SA1100_YOPY is not set -# CONFIG_SA1100_USB is not set -# CONFIG_SA1100_USB_NETLINK is not set -# CONFIG_SA1100_USB_CHAR is not set -# CONFIG_REGISTERS is not set - -# -# Intel PXA250/210 Implementations -# -# CONFIG_ARCH_LUBBOCK is not set -# CONFIG_ARCH_PXA_IDP is not set -# CONFIG_ARCH_PXA_CERF is not set -CONFIG_ARCH_H3900=y -CONFIG_ARCH_H1900=y -CONFIG_ARCH_H5400=y -# CONFIG_ARCH_H2200 is not set -CONFIG_ARCH_AXIM=y -CONFIG_PXA_USB=m -CONFIG_PXA_USB_NETLINK=m -CONFIG_PXA_USB_CHAR=m - -# -# CLPS711X/EP721X Implementations -# -# CONFIG_ARCH_AUTCPU12 is not set -# CONFIG_ARCH_CDB89712 is not set -# CONFIG_ARCH_CLEP7312 is not set -# CONFIG_ARCH_EDB7211 is not set -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_FORTUNET is not set -# CONFIG_ARCH_EP7211 is not set -# CONFIG_ARCH_EP7212 is not set -# CONFIG_ARCH_ACORN is not set -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set - -# -# Processor Type -# -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -# CONFIG_CPU_ARM610 is not set -# CONFIG_CPU_ARM710 is not set -# CONFIG_CPU_ARM720T is not set -# CONFIG_CPU_ARM920T is not set -# CONFIG_CPU_ARM922T is not set -# CONFIG_PLD is not set -# CONFIG_CPU_ARM926T is not set -# CONFIG_CPU_ARM1020 is not set -# CONFIG_CPU_ARM1026 is not set -# CONFIG_CPU_SA110 is not set -# CONFIG_CPU_SA1100 is not set -CONFIG_CPU_32v5=y -CONFIG_CPU_XSCALE=y -CONFIG_XSCALE_PXA250=y -# CONFIG_XSCALE_80200_OLD is not set -# CONFIG_CPU_32v3 is not set -# CONFIG_CPU_32v4 is not set -# CONFIG_SA1100_IPAQ is not set -CONFIG_PXA_IPAQ=y -CONFIG_IPAQ_HANDHELD=y - -# -# Compaq iPAQ Handheld -# -CONFIG_IPAQ_HAL=m -# CONFIG_H3600_MICRO is not set -CONFIG_IPAQ_HAS_ROSELLA=y -CONFIG_IPAQ_HAS_ASIC3=y -CONFIG_H3600_ASIC=m -CONFIG_H3900_ASIC_DEBUG=m -CONFIG_H5400_ASIC=m -CONFIG_H1900_ASIC=m -CONFIG_H1900_TS=m -CONFIG_H3600_HARDWARE=y -CONFIG_IPAQ_SLEEVE=m -CONFIG_SLEEVE_DEBUG=y -CONFIG_SLEEVE_DEBUG_VERBOSE=0 -# CONFIG_SLEEVE_IRQ_DEMUX is not set - -# -# Dell Axim X5 -# -CONFIG_AXIM_HAL=m - -# -# Processor Features -# -# CONFIG_DISCONTIGMEM is not set - -# -# General setup -# -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set -# CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_CPU_FREQ=y -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -# CONFIG_I82092 is not set -# CONFIG_I82365 is not set -# CONFIG_TCIC is not set -# CONFIG_PCMCIA_CLPS6700 is not set -# CONFIG_PCMCIA_SA1100 is not set -CONFIG_PCMCIA_PXA=m -# CONFIG_MERCURY_BACKPAQ is not set - -# -# MMC/SD Card support -# -CONFIG_MMC=m -CONFIG_MMC_DEBUG=y -CONFIG_MMC_DEBUG_VERBOSE=0 -CONFIG_MMC_SAMSUNG_ASIC=m -# CONFIG_MMC_S3C2410 is not set -CONFIG_MMC_H5400=m -CONFIG_MMC_ASIC3=m -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_XIP_KERNEL is not set - -# -# At least one math emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_FASTFPE is not set -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_PM=y -CONFIG_APM=m -# CONFIG_HWTIMER is not set -# CONFIG_ARTHUR is not set -CONFIG_CMDLINE="keepinitrd" -CONFIG_ALIGNMENT_TRAP=y - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -# CONFIG_PARPORT_SERIAL is not set -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_ARC is not set -# CONFIG_PARPORT_IDP is not set -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -# CONFIG_PARPORT_1284 is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -CONFIG_MTD_DEBUG=y -CONFIG_MTD_DEBUG_VERBOSE=1 -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -CONFIG_MTD_JEDECPROBE=m -CONFIG_MTD_GEN_PROBE=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_NOSWAP=y -# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -CONFIG_MTD_CFI_GEOMETRY=y -# CONFIG_MTD_CFI_B1 is not set -CONFIG_MTD_CFI_B2=y -CONFIG_MTD_CFI_B4=y -# CONFIG_MTD_CFI_B8 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set -# CONFIG_MTD_JEDEC is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -CONFIG_MTD_IPAQ=y -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_CDB89712 is not set -# CONFIG_MTD_SA1100 is not set -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_IQ80310 is not set -# CONFIG_MTD_LUBBOCK is not set -# CONFIG_MTD_EPXA10DB is not set -# CONFIG_MTD_FORTUNET is not set -# CONFIG_MTD_AUTCPU12 is not set -# CONFIG_MTD_EDB7312 is not set -# CONFIG_MTD_H720X is not set -# CONFIG_MTD_IMPA7 is not set -# CONFIG_MTD_CEIVA is not set -# CONFIG_MTD_PCI is not set -# CONFIG_MTD_PCMCIA is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -CONFIG_MTD_BLKMTD=m - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -# CONFIG_MTD_DOCPROBE is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -CONFIG_NVRD=m - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -CONFIG_BLK_DEV_LVM=m -CONFIG_BLK_DEV_DM=m - -# -# Networking options -# -CONFIG_PACKET=m -CONFIG_PACKET_MMAP=y -# CONFIG_NETLINK_DEV is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -# CONFIG_IP_NF_AMANDA is not set -# CONFIG_IP_NF_TFTP is not set -CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_QUEUE is not set -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -# CONFIG_IP_NF_MATCH_PKTTYPE is not set -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -# CONFIG_IP_NF_MATCH_RECENT is not set -# CONFIG_IP_NF_MATCH_ECN is not set -# CONFIG_IP_NF_MATCH_DSCP is not set -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -# CONFIG_IP_NF_MATCH_HELPER is not set -CONFIG_IP_NF_MATCH_STATE=m -# CONFIG_IP_NF_MATCH_CONNTRACK is not set -# CONFIG_IP_NF_MATCH_UNCLEAN is not set -# CONFIG_IP_NF_MATCH_OWNER is not set -CONFIG_IP_NF_FILTER=m -# CONFIG_IP_NF_TARGET_REJECT is not set -# CONFIG_IP_NF_TARGET_MIRROR is not set -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_NAT_LOCAL is not set -# CONFIG_IP_NF_NAT_SNMP_BASIC is not set -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -# CONFIG_IP_NF_TARGET_ECN is not set -# CONFIG_IP_NF_TARGET_DSCP is not set -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -# CONFIG_IP_NF_ARPTABLES is not set -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -# CONFIG_IP_NF_COMPAT_IPFWADM is not set -CONFIG_IPV6=m -CONFIG_IPV6_SUBTREES=y -CONFIG_IPV6_IPV6_TUNNEL=m -CONFIG_IPV6_MOBILITY=m -CONFIG_IPV6_MOBILITY_MN=m -# CONFIG_IPV6_MOBILITY_HA is not set -CONFIG_IPV6_MOBILITY_DEBUG=y - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -# CONFIG_IP6_NF_MATCH_RT is not set -# CONFIG_IP6_NF_MATCH_OPTS is not set -# CONFIG_IP6_NF_MATCH_FRAG is not set -# CONFIG_IP6_NF_MATCH_HL is not set -CONFIG_IP6_NF_MATCH_MULTIPORT=m -# CONFIG_IP6_NF_MATCH_OWNER is not set -CONFIG_IP6_NF_MATCH_MARK=m -# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set -# CONFIG_IP6_NF_MATCH_AHESP is not set -# CONFIG_IP6_NF_MATCH_LENGTH is not set -# CONFIG_IP6_NF_MATCH_EUI64 is not set -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_IPSEC=m - -# -# IPSec options (FreeS/WAN) -# -CONFIG_IPSEC_IPIP=y -CONFIG_IPSEC_AH=y -CONFIG_IPSEC_AUTH_HMAC_MD5=y -CONFIG_IPSEC_AUTH_HMAC_SHA1=y -CONFIG_IPSEC_ESP=y -CONFIG_IPSEC_ENC_3DES=y -CONFIG_IPSEC_IPCOMP=y -CONFIG_IPSEC_DEBUG=y - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -# CONFIG_NET_ETHERNET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_MPPE=m -# CONFIG_PPPOE is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -# CONFIG_STRIP is not set -# CONFIG_WAVELAN is not set -# CONFIG_ARLAN is not set -# CONFIG_AIRONET4500 is not set -# CONFIG_AIRONET4500_NONCS is not set -# CONFIG_AIRONET4500_PROC is not set -# CONFIG_HERMES is not set -# CONFIG_SPECTRUM24T is not set - -# -# Wireless Pcmcia cards support -# -# CONFIG_PCMCIA_HERMES is not set -# CONFIG_AIRO_CS is not set -# CONFIG_WVLAN_CS is not set -# CONFIG_MWVLAN_CS is not set -# CONFIG_HOSTAP is not set -# CONFIG_HOSTAP_CS is not set -CONFIG_NET_WIRELESS=y -CONFIG_ATMELWLAN=y -CONFIG_ATMELWLAN_USB_503A_RFMD=m -CONFIG_ATMELWLAN_PCMCIA_502A=m -CONFIG_ATMELWLAN_PCMCIA_3COM=m -CONFIG_ATMELWLAN_PCMCIA_502AD=m -CONFIG_ATMELWLAN_PCMCIA_502AE=m -CONFIG_ATMELWLAN_PCMCIA_504=m - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_AXNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -# CONFIG_ARCNET_COM20020_CS is not set -# CONFIG_PCMCIA_IBMTR is not set -CONFIG_NET_PCMCIA_RADIO=y -CONFIG_PCMCIA_RAYCS=m -CONFIG_PCMCIA_NETWAVE=m -CONFIG_PCMCIA_WAVELAN=m -# CONFIG_AIRONET4500_CS is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -CONFIG_IRDA=m - -# -# IrDA protocols -# -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y - -# -# IrDA options -# -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -CONFIG_IRDA_DEBUG=y - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m - -# -# Dongle support -# -# CONFIG_DONGLE is not set - -# -# FIR device drivers -# -# CONFIG_USB_IRDA is not set -# CONFIG_NSC_FIR is not set -# CONFIG_WINBOND_FIR is not set -# CONFIG_TOSHIBA_FIR is not set -# CONFIG_SMC_IRCC_FIR is not set -# CONFIG_ALI_FIR is not set -# CONFIG_VLSI_FIR is not set -CONFIG_PXA_FIR=m - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=m - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=m - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=m -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set -# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set -# CONFIG_BLK_DEV_IDEDISK_IBM is not set -# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set -# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set -# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set -# CONFIG_BLK_DEV_IDEDISK_WD is not set -# CONFIG_BLK_DEV_COMMERIAL is not set -# CONFIG_BLK_DEV_TIVO is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=m -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_IDE_CHIPSETS is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_DMA_NONPCI is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set - -# -# SCSI support -# -CONFIG_SCSI=m - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=40 -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_PPA is not set -# CONFIG_SCSI_IMM is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_DEBUG is not set - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_PCMCIA=y -# CONFIG_PCMCIA_AHA152X is not set -# CONFIG_PCMCIA_FDOMAIN is not set -# CONFIG_PCMCIA_NINJA_SCSI is not set -# CONFIG_PCMCIA_QLOGIC is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m -CONFIG_INPUT_UINPUT=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_EXTENDED=y -# CONFIG_SERIAL_MANY_PORTS is not set -# CONFIG_SERIAL_SHARE_IRQ is not set -# CONFIG_SERIAL_DETECT_IRQ is not set -# CONFIG_SERIAL_MULTIPORT is not set -# CONFIG_HUB6 is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_ANAKIN is not set -# CONFIG_SERIAL_ANAKIN_CONSOLE is not set -# CONFIG_SERIAL_S3C2410 is not set -# CONFIG_SERIAL_S3C2410_CONSOLE is not set -# CONFIG_SERIAL_AMBA is not set -# CONFIG_SERIAL_AMBA_CONSOLE is not set -# CONFIG_SERIAL_CLPS711X is not set -# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE is not set -# CONFIG_SERIAL_UART00 is not set -# CONFIG_SERIAL_UART00_CONSOLE is not set -# CONFIG_SERIAL_SA1100 is not set -# CONFIG_SERIAL_SA1100_CONSOLE is not set -# CONFIG_SERIAL_SIR_PXA is not set -# CONFIG_SERIAL_8250 is not set -# CONFIG_SERIAL_8250_CONSOLE is not set -# CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SERIAL_8250_MANY_PORTS is not set -# CONFIG_SERIAL_8250_SHARE_IRQ is not set -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_HUB6 is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 -# CONFIG_PRINTER is not set -# CONFIG_PPDEV is not set -CONFIG_NEWTONKBD=m -# CONFIG_SA1100_PROFILER is not set - -# -# Compaq iPAQ H3600 support -# -CONFIG_TOUCHSCREEN_H3600=m -# CONFIG_H3600_BACKPAQ_FPGA is not set -# CONFIG_H3600_BACKPAQ_ACCEL is not set -# CONFIG_H3600_BACKPAQ_GASGAUGE is not set -# CONFIG_H3600_BACKPAQ_SRAM is not set -# CONFIG_H3600_BACKPAQ_AUDIO is not set -# CONFIG_H3600_STOWAWAY is not set -# CONFIG_H3800_MICROKBD is not set -# CONFIG_SA1100_LIRC is not set -CONFIG_H5400_BUZZER=m -CONFIG_H5400_FSI=m - -# -# I2C support -# -CONFIG_I2C=m -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -CONFIG_I2C_PXA_ALGO=m -CONFIG_I2C_PXA_ADAP=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_PROC=m -# CONFIG_I2C_DS1307 is not set - -# -# L3 serial bus support -# -# CONFIG_L3 is not set -# CONFIG_L3_ALGOBIT is not set -# CONFIG_L3_BIT_SA1100_GPIO is not set - -# -# Other L3 adapters -# -# CONFIG_L3_S3C2410 is not set -# CONFIG_L3_SA1111 is not set -# CONFIG_L3_BACKPAQ is not set -# CONFIG_BIT_SA1100_GPIO is not set - -# -# SPI support -# -# CONFIG_SPI is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=m -# CONFIG_PSMOUSE is not set -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set -# CONFIG_MK712_MOUSE is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_INPUT_NS558 is not set -# CONFIG_INPUT_LIGHTNING is not set -# CONFIG_INPUT_PCIGAME is not set -# CONFIG_INPUT_CS461X is not set -# CONFIG_INPUT_EMU10K1 is not set -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m - -# -# Joysticks -# -# CONFIG_INPUT_ANALOG is not set -# CONFIG_INPUT_A3D is not set -# CONFIG_INPUT_ADI is not set -# CONFIG_INPUT_COBRA is not set -# CONFIG_INPUT_GF2K is not set -# CONFIG_INPUT_GRIP is not set -# CONFIG_INPUT_INTERACT is not set -# CONFIG_INPUT_TMDC is not set -# CONFIG_INPUT_SIDEWINDER is not set -# CONFIG_INPUT_IFORCE_USB is not set -# CONFIG_INPUT_IFORCE_232 is not set -# CONFIG_INPUT_WARRIOR is not set -# CONFIG_INPUT_MAGELLAN is not set -# CONFIG_INPUT_SPACEORB is not set -# CONFIG_INPUT_SPACEBALL is not set -# CONFIG_INPUT_STINGER is not set -# CONFIG_INPUT_DB9 is not set -# CONFIG_INPUT_GAMECON is not set -# CONFIG_INPUT_TURBOGRAFX is not set -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -# CONFIG_ALIM7101_WDT is not set -# CONFIG_SC520_WDT is not set -# CONFIG_PCWATCHDOG is not set -# CONFIG_21285_WATCHDOG is not set -# CONFIG_977_WATCHDOG is not set -# CONFIG_SA1100_WATCHDOG is not set -CONFIG_PXA_WATCHDOG=m -# CONFIG_OMAHA_WATCHDOG is not set -# CONFIG_EUROTECH_WDT is not set -# CONFIG_IB700_WDT is not set -# CONFIG_WAFER_WDT is not set -# CONFIG_I810_TCO is not set -# CONFIG_MIXCOMWD is not set -# CONFIG_60XX_WDT is not set -# CONFIG_SC1200_WDT is not set -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_W83877F_WDT is not set -# CONFIG_WDT is not set -# CONFIG_WDTPCI is not set -# CONFIG_MACHZ_WDT is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -CONFIG_PXA_RTC=m -CONFIG_PXA_RTC_HACK=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# PCMCIA character devices -# -CONFIG_PCMCIA_SERIAL_CS=m -CONFIG_PCMCIA_MOBILISCAN_CS=m -# CONFIG_AXIM_TS is not set -CONFIG_AXIM_KEY=m -# CONFIG_AXIM_KEY_FIX is not set - -# -# Multimedia devices -# -CONFIG_MEDIA=m -CONFIG_VIDEO_DEV=m -CONFIG_V4L2_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -# CONFIG_I2C_PARPORT is not set - -# -# Video Adapters -# -# CONFIG_VIDEO_PMS is not set -# CONFIG_VIDEO_BWQCAM is not set -# CONFIG_VIDEO_CQCAM is not set -CONFIG_VIDEO_CPIA=m -CONFIG_VIDEO_CPIA_USB=m -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_ZORAN_BUZ is not set -# CONFIG_VIDEO_ZORAN_DC10 is not set -# CONFIG_VIDEO_ZORAN_LML33 is not set -# CONFIG_VIDEO_ZR36120 is not set -# CONFIG_VIDEO_MEYE is not set -# CONFIG_VIDEO_CYBERPRO is not set -# CONFIG_VIDEO_H3600_BACKPAQ is not set -# CONFIG_VIDEO_HAWKEYE is not set - -# -# Video for Linux 2 (V4L2) -# -CONFIG_VIDEO_WINNOV_CS=m - -# -# Radio Adapters -# -# CONFIG_RADIO_CADET is not set -# CONFIG_RADIO_RTRACK is not set -# CONFIG_RADIO_RTRACK2 is not set -# CONFIG_RADIO_AZTECH is not set -# CONFIG_RADIO_GEMTEK is not set -# CONFIG_RADIO_GEMTEK_PCI is not set -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_MAESTRO is not set -# CONFIG_RADIO_MIROPCM20 is not set -# CONFIG_RADIO_MIROPCM20_RDS is not set -# CONFIG_RADIO_SF16FMI is not set -# CONFIG_RADIO_TERRATEC is not set -# CONFIG_RADIO_TRUST is not set -# CONFIG_RADIO_TYPHOON is not set -# CONFIG_RADIO_ZOLTRIX is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -CONFIG_CRAMFS=y -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=m -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DRIVERFS_FS is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=m -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_UTF8=m - -# -# Console drivers -# -CONFIG_PC_KEYMAP=y -# CONFIG_VGA_CONSOLE is not set - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_ACORN is not set -# CONFIG_FB_ANAKIN is not set -# CONFIG_FB_CLPS711X is not set -# CONFIG_FB_S3C2410 is not set -# CONFIG_FB_SA1100 is not set -# CONFIG_FB_EPSON1356 is not set -# CONFIG_FB_MQ200 is not set -CONFIG_FB_PXA=y -# CONFIG_FB_PXA_8BPP is not set -CONFIG_FB_PXA_16BPP=y -CONFIG_FB_MQ1100=y -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_VIRTUAL is not set -CONFIG_FBCON_ADVANCED=y -# CONFIG_FBCON_MFB is not set -# CONFIG_FBCON_CFB2 is not set -# CONFIG_FBCON_CFB4 is not set -# CONFIG_FBCON_CFB8 is not set -CONFIG_FBCON_CFB16=y -# CONFIG_FBCON_CFB24 is not set -# CONFIG_FBCON_CFB32 is not set -# CONFIG_FBCON_AFB is not set -# CONFIG_FBCON_ILBM is not set -# CONFIG_FBCON_IPLAN2P2 is not set -# CONFIG_FBCON_IPLAN2P4 is not set -# CONFIG_FBCON_IPLAN2P8 is not set -# CONFIG_FBCON_MAC is not set -# CONFIG_FBCON_VGA_PLANES is not set -# CONFIG_FBCON_VGA is not set -# CONFIG_FBCON_HGA is not set -# CONFIG_FBCON_NO_LOGO is not set -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -CONFIG_FONT_8x8=y -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set - -# -# Sound -# -CONFIG_SOUND=y -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_MIDI_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_MAESTRO3 is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_RME96XX is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -# CONFIG_MIDI_VIA82CXXX is not set -CONFIG_SOUND_H3900_UDA1380=m -CONFIG_SOUND_H5400=m -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -# CONFIG_SOUND_DMAP is not set -# CONFIG_SOUND_AD1816 is not set -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_ADLIB is not set -# CONFIG_SOUND_ACI_MIXER is not set -# CONFIG_SOUND_CS4232 is not set -# CONFIG_SOUND_SSCAPE is not set -# CONFIG_SOUND_GUS is not set -# CONFIG_SOUND_VMIDI is not set -# CONFIG_SOUND_TRIX is not set -# CONFIG_SOUND_MSS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_NM256 is not set -# CONFIG_SOUND_MAD16 is not set -# CONFIG_SOUND_PAS is not set -# CONFIG_PAS_JOYSTICK is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_SB is not set -# CONFIG_SOUND_AWE32_SYNTH is not set -# CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_OPL3SA2 is not set -# CONFIG_SOUND_YMFPCI is not set -# CONFIG_SOUND_YMFPCI_LEGACY is not set -# CONFIG_SOUND_UART6850 is not set -# CONFIG_SOUND_AEDSP16 is not set -# CONFIG_SOUND_VIDC is not set -# CONFIG_SOUND_WAVEARTIST is not set -CONFIG_SOUND_PXA_AC97=m -# CONFIG_SOUND_TVMIXER is not set - -# -# Multimedia Capabilities Port drivers -# -# CONFIG_MCP is not set -# CONFIG_MCP_SA1100 is not set -# CONFIG_MCP_UCB1200 is not set -# CONFIG_MCP_UCB1200_AUDIO is not set -# CONFIG_MCP_UCB1200_TS is not set -# CONFIG_MCP_UCB1400_TS is not set - -# -# Console Switches -# -# CONFIG_SWITCHES is not set - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_LONG_TIMEOUT is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -CONFIG_USB_OHCI=m -# CONFIG_USB_OHCI_SA1111 is not set -CONFIG_USB_OHCI_H5400=m -# CONFIG_USB_OHCI_S3C2410 is not set -# CONFIG_USB_SL811HS is not set - -# -# USB Device Class drivers -# -CONFIG_USB_AUDIO=m -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_BLUETOOTH is not set -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_ACM is not set -CONFIG_USB_PRINTER=m - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_WACOM is not set - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# -CONFIG_USB_IBMCAM=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -# CONFIG_USB_DSBR is not set -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -CONFIG_USB_CDCETHER=m -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_IPAQ is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_KLSI is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_XIRCOM is not set -# CONFIG_USB_SERIAL_OMNINET is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_BRLVGER is not set - -# -# Linux As Bootldr Modules -# -# CONFIG_BIG_KERNEL is not set -# CONFIG_USE_DATE_CODE is not set -# CONFIG_YMODEM is not set -# CONFIG_LAB_DUMMY is not set -# CONFIG_LAB_CRC is not set -# CONFIG_LAB_YMODEM is not set -# CONFIG_LAB_MTD is not set -# CONFIG_LAB_COPY is not set -# CONFIG_LAB_COPY_YMODEM is not set -# CONFIG_LAB_COPY_FLASH is not set -# CONFIG_LAB_COPY_FS is not set -# CONFIG_LAB_COPY_WRAPPER is not set - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -# CONFIG_BLUEZ_HCIUSB is not set -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -# CONFIG_BLUEZ_HCIUART_BCSP_TXCRC is not set -# CONFIG_BLUEZ_HCIBFUSB is not set -CONFIG_BLUEZ_HCIDTL1=m -CONFIG_BLUEZ_HCIBT3C=m -CONFIG_BLUEZ_HCIBLUECARD=m -CONFIG_BLUEZ_HCIBTUART=m -# CONFIG_BLUEZ_HCIVHCI is not set - -# -# Kernel hacking -# -# CONFIG_FRAME_POINTER is not set -# CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_INFO is not set -# CONFIG_NO_PGT_CACHE is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -CONFIG_DEBUG_ERRORS=y -# CONFIG_DEBUG_LL is not set -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.14/defconfig-ipaqpxa b/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.14/defconfig-ipaqpxa deleted file mode 100644 index fc9682743a..0000000000 --- a/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh36.14/defconfig-ipaqpxa +++ /dev/null @@ -1,1578 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_GENERIC_BUST_SPINLOCK is not set -# CONFIG_GENERIC_ISA_DMA is not set - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# System Type -# -# CONFIG_ARCH_ANAKIN is not set -# CONFIG_ARCH_ARCA5K is not set -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -CONFIG_ARCH_PXA=y -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_OMAHA is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_MX1ADS is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_RISCSTATION is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_AT91RM9200DK is not set -# CONFIG_MINIMAL_OOPS is not set - -# -# Linux As Bootldr support -# -# CONFIG_LAB is not set -# CONFIG_BIG_KERNEL is not set -# CONFIG_USE_DATE_CODE is not set - -# -# Archimedes/A5000 Implementations -# - -# -# Archimedes/A5000 Implementations (select only ONE) -# -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set - -# -# Footbridge Implementations -# -# CONFIG_ARCH_CATS is not set -# CONFIG_ARCH_PERSONAL_SERVER is not set -# CONFIG_ARCH_EBSA285_ADDIN is not set -# CONFIG_ARCH_EBSA285_HOST is not set -# CONFIG_ARCH_NETWINDER is not set - -# -# SA11x0 Implementations -# -# CONFIG_SA1100_ACCELENT is not set -# CONFIG_SA1100_ASSABET is not set -# CONFIG_ASSABET_NEPONSET is not set -# CONFIG_SA1100_ADSBITSY is not set -# CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_CEP is not set -# CONFIG_SA1100_CERF is not set -# CONFIG_SA1100_H3100 is not set -# CONFIG_SA1100_H3600 is not set -# CONFIG_SA1100_H3800 is not set -# CONFIG_SA1100_CONSUS is not set -# CONFIG_SA1100_EXTENEX1 is not set -# CONFIG_SA1100_FLEXANET is not set -# CONFIG_SA1100_FREEBIRD is not set -# CONFIG_SA1100_FRODO is not set -# CONFIG_SA1100_GRAPHICSCLIENT is not set -# CONFIG_SA1100_GRAPHICSMASTER is not set -# CONFIG_SA1100_HACKKIT is not set -# CONFIG_SA1100_BADGE4 is not set -# CONFIG_SA1100_JORNADA720 is not set -# CONFIG_SA1100_JORNADA56X is not set -# CONFIG_SA1100_HUW_WEBPANEL is not set -# CONFIG_SA1100_ITSY is not set -# CONFIG_SA1100_LART is not set -# CONFIG_SA1100_NANOENGINE is not set -# CONFIG_SA1100_OMNIMETER is not set -# CONFIG_SA1100_PANGOLIN is not set -# CONFIG_SA1100_PLEB is not set -# CONFIG_SA1100_PT_SYSTEM3 is not set -# CONFIG_SA1100_SHANNON is not set -# CONFIG_SA1100_SHERMAN is not set -# CONFIG_SA1100_SIMPAD is not set -# CONFIG_SA1100_SIMPUTER is not set -# CONFIG_SA1100_PFS168 is not set -# CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_XP860 is not set -# CONFIG_SA1100_YOPY is not set -# CONFIG_SA1100_USB is not set -# CONFIG_SA1100_USB_NETLINK is not set -# CONFIG_SA1100_USB_CHAR is not set -# CONFIG_REGISTERS is not set - -# -# Intel PXA250/210 Implementations -# -# CONFIG_ARCH_LUBBOCK is not set -# CONFIG_ARCH_PXA_IDP is not set -# CONFIG_ARCH_PXA_CERF is not set -CONFIG_ARCH_H3900=y -CONFIG_ARCH_H1900=y -CONFIG_ARCH_H5400=y -# CONFIG_ARCH_H2200 is not set -CONFIG_ARCH_AXIM=y -CONFIG_PXA_USB=m -CONFIG_PXA_USB_NETLINK=m -CONFIG_PXA_USB_CHAR=m - -# -# CLPS711X/EP721X Implementations -# -# CONFIG_ARCH_AUTCPU12 is not set -# CONFIG_ARCH_CDB89712 is not set -# CONFIG_ARCH_CLEP7312 is not set -# CONFIG_ARCH_EDB7211 is not set -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_FORTUNET is not set -# CONFIG_ARCH_EP7211 is not set -# CONFIG_ARCH_EP7212 is not set -# CONFIG_ARCH_ACORN is not set -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set - -# -# Processor Type -# -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -# CONFIG_CPU_ARM610 is not set -# CONFIG_CPU_ARM710 is not set -# CONFIG_CPU_ARM720T is not set -# CONFIG_CPU_ARM920T is not set -# CONFIG_CPU_ARM922T is not set -# CONFIG_PLD is not set -# CONFIG_CPU_ARM926T is not set -# CONFIG_CPU_ARM1020 is not set -# CONFIG_CPU_ARM1026 is not set -# CONFIG_CPU_SA110 is not set -# CONFIG_CPU_SA1100 is not set -CONFIG_CPU_32v5=y -CONFIG_CPU_XSCALE=y -CONFIG_XSCALE_PXA250=y -# CONFIG_XSCALE_80200_OLD is not set -# CONFIG_CPU_32v3 is not set -# CONFIG_CPU_32v4 is not set -# CONFIG_SA1100_IPAQ is not set -CONFIG_PXA_IPAQ=y -CONFIG_IPAQ_HANDHELD=y - -# -# Compaq iPAQ Handheld -# -CONFIG_IPAQ_HAL=m -# CONFIG_H3600_MICRO is not set -CONFIG_IPAQ_HAS_ROSELLA=y -CONFIG_IPAQ_HAS_ASIC3=y -CONFIG_H3600_ASIC=m -CONFIG_H3900_ASIC_DEBUG=m -CONFIG_H5400_ASIC=m -CONFIG_H1900_ASIC=m -CONFIG_H1900_TS=m -CONFIG_H3600_HARDWARE=y -CONFIG_IPAQ_SLEEVE=m -CONFIG_SLEEVE_DEBUG=y -CONFIG_SLEEVE_DEBUG_VERBOSE=0 -# CONFIG_SLEEVE_IRQ_DEMUX is not set - -# -# Dell Axim X5 -# -CONFIG_AXIM_HAL=m - -# -# Processor Features -# -# CONFIG_DISCONTIGMEM is not set - -# -# General setup -# -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set -# CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_CPU_FREQ=y -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -# CONFIG_I82092 is not set -# CONFIG_I82365 is not set -# CONFIG_TCIC is not set -# CONFIG_PCMCIA_CLPS6700 is not set -# CONFIG_PCMCIA_SA1100 is not set -CONFIG_PCMCIA_PXA=m -# CONFIG_MERCURY_BACKPAQ is not set - -# -# MMC/SD Card support -# -CONFIG_MMC=m -CONFIG_MMC_DEBUG=y -CONFIG_MMC_DEBUG_VERBOSE=0 -CONFIG_MMC_SAMSUNG_ASIC=m -# CONFIG_MMC_S3C2410 is not set -CONFIG_MMC_H5400=m -CONFIG_MMC_ASIC3=m -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_XIP_KERNEL is not set - -# -# At least one math emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_FASTFPE is not set -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_PM=y -CONFIG_APM=m -# CONFIG_HWTIMER is not set -# CONFIG_ARTHUR is not set -CONFIG_CMDLINE="keepinitrd" -CONFIG_ALIGNMENT_TRAP=y - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -# CONFIG_PARPORT_SERIAL is not set -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_ARC is not set -# CONFIG_PARPORT_IDP is not set -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -# CONFIG_PARPORT_1284 is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -CONFIG_MTD_DEBUG=y -CONFIG_MTD_DEBUG_VERBOSE=1 -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -CONFIG_MTD_JEDECPROBE=m -CONFIG_MTD_GEN_PROBE=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_NOSWAP=y -# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -CONFIG_MTD_CFI_GEOMETRY=y -# CONFIG_MTD_CFI_B1 is not set -CONFIG_MTD_CFI_B2=y -CONFIG_MTD_CFI_B4=y -# CONFIG_MTD_CFI_B8 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set -# CONFIG_MTD_JEDEC is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -CONFIG_MTD_IPAQ=y -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_CDB89712 is not set -# CONFIG_MTD_SA1100 is not set -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_IQ80310 is not set -# CONFIG_MTD_LUBBOCK is not set -# CONFIG_MTD_EPXA10DB is not set -# CONFIG_MTD_FORTUNET is not set -# CONFIG_MTD_AUTCPU12 is not set -# CONFIG_MTD_EDB7312 is not set -# CONFIG_MTD_H720X is not set -# CONFIG_MTD_IMPA7 is not set -# CONFIG_MTD_CEIVA is not set -# CONFIG_MTD_PCI is not set -# CONFIG_MTD_PCMCIA is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -CONFIG_MTD_BLKMTD=m - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -# CONFIG_MTD_DOCPROBE is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -CONFIG_NVRD=m - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -CONFIG_BLK_DEV_LVM=m -CONFIG_BLK_DEV_DM=m - -# -# Networking options -# -CONFIG_PACKET=m -CONFIG_PACKET_MMAP=y -# CONFIG_NETLINK_DEV is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -# CONFIG_IP_NF_AMANDA is not set -# CONFIG_IP_NF_TFTP is not set -CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_QUEUE is not set -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -# CONFIG_IP_NF_MATCH_PKTTYPE is not set -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -# CONFIG_IP_NF_MATCH_RECENT is not set -# CONFIG_IP_NF_MATCH_ECN is not set -# CONFIG_IP_NF_MATCH_DSCP is not set -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -# CONFIG_IP_NF_MATCH_HELPER is not set -CONFIG_IP_NF_MATCH_STATE=m -# CONFIG_IP_NF_MATCH_CONNTRACK is not set -# CONFIG_IP_NF_MATCH_UNCLEAN is not set -# CONFIG_IP_NF_MATCH_OWNER is not set -CONFIG_IP_NF_FILTER=m -# CONFIG_IP_NF_TARGET_REJECT is not set -# CONFIG_IP_NF_TARGET_MIRROR is not set -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_NAT_LOCAL is not set -# CONFIG_IP_NF_NAT_SNMP_BASIC is not set -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -# CONFIG_IP_NF_TARGET_ECN is not set -# CONFIG_IP_NF_TARGET_DSCP is not set -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -# CONFIG_IP_NF_ARPTABLES is not set -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -# CONFIG_IP_NF_COMPAT_IPFWADM is not set -CONFIG_IPV6=m -CONFIG_IPV6_SUBTREES=y -CONFIG_IPV6_IPV6_TUNNEL=m -CONFIG_IPV6_MOBILITY=m -CONFIG_IPV6_MOBILITY_MN=m -# CONFIG_IPV6_MOBILITY_HA is not set -CONFIG_IPV6_MOBILITY_DEBUG=y - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -# CONFIG_IP6_NF_MATCH_RT is not set -# CONFIG_IP6_NF_MATCH_OPTS is not set -# CONFIG_IP6_NF_MATCH_FRAG is not set -# CONFIG_IP6_NF_MATCH_HL is not set -CONFIG_IP6_NF_MATCH_MULTIPORT=m -# CONFIG_IP6_NF_MATCH_OWNER is not set -CONFIG_IP6_NF_MATCH_MARK=m -# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set -# CONFIG_IP6_NF_MATCH_AHESP is not set -# CONFIG_IP6_NF_MATCH_LENGTH is not set -# CONFIG_IP6_NF_MATCH_EUI64 is not set -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_IPSEC=m - -# -# IPSec options (FreeS/WAN) -# -CONFIG_KLIPS_AUTH_HMAC_MD5=y -CONFIG_KLIPS_AUTH_HMAC_SHA1=y -CONFIG_KLIPS_ENC_3DES=y - -# -# ESP always enabled with tunnel mode -# -CONFIG_KLIPS_IPCOMP=y -CONFIG_KLIPS_DEBUG=y - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -# CONFIG_NET_ETHERNET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_MPPE=m -# CONFIG_PPPOE is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -# CONFIG_STRIP is not set -# CONFIG_WAVELAN is not set -# CONFIG_ARLAN is not set -# CONFIG_AIRONET4500 is not set -# CONFIG_AIRONET4500_NONCS is not set -# CONFIG_AIRONET4500_PROC is not set -# CONFIG_HERMES is not set -# CONFIG_SPECTRUM24T is not set - -# -# Wireless Pcmcia cards support -# -# CONFIG_PCMCIA_HERMES is not set -# CONFIG_AIRO_CS is not set -# CONFIG_WVLAN_CS is not set -# CONFIG_MWVLAN_CS is not set -# CONFIG_HOSTAP is not set -# CONFIG_HOSTAP_CS is not set -CONFIG_NET_WIRELESS=y -CONFIG_ATMELWLAN=y -CONFIG_ATMELWLAN_USB_503A_RFMD=m -CONFIG_ATMELWLAN_PCMCIA_502A=m -CONFIG_ATMELWLAN_PCMCIA_3COM=m -CONFIG_ATMELWLAN_PCMCIA_502AD=m -CONFIG_ATMELWLAN_PCMCIA_502AE=m -CONFIG_ATMELWLAN_PCMCIA_504=m - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_AXNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -# CONFIG_ARCNET_COM20020_CS is not set -# CONFIG_PCMCIA_IBMTR is not set -CONFIG_NET_PCMCIA_RADIO=y -CONFIG_PCMCIA_RAYCS=m -CONFIG_PCMCIA_NETWAVE=m -CONFIG_PCMCIA_WAVELAN=m -# CONFIG_AIRONET4500_CS is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -CONFIG_IRDA=m - -# -# IrDA protocols -# -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y - -# -# IrDA options -# -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -CONFIG_IRDA_DEBUG=y - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m - -# -# Dongle support -# -# CONFIG_DONGLE is not set - -# -# FIR device drivers -# -# CONFIG_USB_IRDA is not set -# CONFIG_NSC_FIR is not set -# CONFIG_WINBOND_FIR is not set -# CONFIG_TOSHIBA_FIR is not set -# CONFIG_SMC_IRCC_FIR is not set -# CONFIG_ALI_FIR is not set -# CONFIG_VLSI_FIR is not set -CONFIG_PXA_FIR=m - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=m - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=m - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=m -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set -# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set -# CONFIG_BLK_DEV_IDEDISK_IBM is not set -# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set -# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set -# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set -# CONFIG_BLK_DEV_IDEDISK_WD is not set -# CONFIG_BLK_DEV_COMMERIAL is not set -# CONFIG_BLK_DEV_TIVO is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=m -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_IDE_CHIPSETS is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_DMA_NONPCI is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set - -# -# SCSI support -# -CONFIG_SCSI=m - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=40 -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_PPA is not set -# CONFIG_SCSI_IMM is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_DEBUG is not set - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_PCMCIA=y -# CONFIG_PCMCIA_AHA152X is not set -# CONFIG_PCMCIA_FDOMAIN is not set -# CONFIG_PCMCIA_NINJA_SCSI is not set -# CONFIG_PCMCIA_QLOGIC is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m -CONFIG_INPUT_UINPUT=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_EXTENDED=y -# CONFIG_SERIAL_MANY_PORTS is not set -# CONFIG_SERIAL_SHARE_IRQ is not set -# CONFIG_SERIAL_DETECT_IRQ is not set -# CONFIG_SERIAL_MULTIPORT is not set -# CONFIG_HUB6 is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_ANAKIN is not set -# CONFIG_SERIAL_ANAKIN_CONSOLE is not set -# CONFIG_SERIAL_S3C2410 is not set -# CONFIG_SERIAL_S3C2410_CONSOLE is not set -# CONFIG_SERIAL_AMBA is not set -# CONFIG_SERIAL_AMBA_CONSOLE is not set -# CONFIG_SERIAL_CLPS711X is not set -# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE is not set -# CONFIG_SERIAL_UART00 is not set -# CONFIG_SERIAL_UART00_CONSOLE is not set -# CONFIG_SERIAL_SA1100 is not set -# CONFIG_SERIAL_SA1100_CONSOLE is not set -# CONFIG_SERIAL_SIR_PXA is not set -# CONFIG_SERIAL_8250 is not set -# CONFIG_SERIAL_8250_CONSOLE is not set -# CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SERIAL_8250_MANY_PORTS is not set -# CONFIG_SERIAL_8250_SHARE_IRQ is not set -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_HUB6 is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 -# CONFIG_PRINTER is not set -# CONFIG_PPDEV is not set -CONFIG_NEWTONKBD=m -# CONFIG_SA1100_PROFILER is not set - -# -# Compaq iPAQ H3600 support -# -CONFIG_TOUCHSCREEN_H3600=m -# CONFIG_H3600_BACKPAQ_FPGA is not set -# CONFIG_H3600_BACKPAQ_ACCEL is not set -# CONFIG_H3600_BACKPAQ_GASGAUGE is not set -# CONFIG_H3600_BACKPAQ_SRAM is not set -# CONFIG_H3600_BACKPAQ_AUDIO is not set -# CONFIG_H3600_STOWAWAY is not set -# CONFIG_H3800_MICROKBD is not set -# CONFIG_SA1100_LIRC is not set -CONFIG_H5400_BUZZER=m -CONFIG_H5400_FSI=m - -# -# I2C support -# -CONFIG_I2C=m -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -CONFIG_I2C_PXA_ALGO=m -CONFIG_I2C_PXA_ADAP=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_PROC=m -# CONFIG_I2C_DS1307 is not set - -# -# L3 serial bus support -# -# CONFIG_L3 is not set -# CONFIG_L3_ALGOBIT is not set -# CONFIG_L3_BIT_SA1100_GPIO is not set - -# -# Other L3 adapters -# -# CONFIG_L3_S3C2410 is not set -# CONFIG_L3_SA1111 is not set -# CONFIG_L3_BACKPAQ is not set -# CONFIG_BIT_SA1100_GPIO is not set - -# -# SPI support -# -# CONFIG_SPI is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=m -# CONFIG_PSMOUSE is not set -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set -# CONFIG_MK712_MOUSE is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_INPUT_NS558 is not set -# CONFIG_INPUT_LIGHTNING is not set -# CONFIG_INPUT_PCIGAME is not set -# CONFIG_INPUT_CS461X is not set -# CONFIG_INPUT_EMU10K1 is not set -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m - -# -# Joysticks -# -# CONFIG_INPUT_ANALOG is not set -# CONFIG_INPUT_A3D is not set -# CONFIG_INPUT_ADI is not set -# CONFIG_INPUT_COBRA is not set -# CONFIG_INPUT_GF2K is not set -# CONFIG_INPUT_GRIP is not set -# CONFIG_INPUT_INTERACT is not set -# CONFIG_INPUT_TMDC is not set -# CONFIG_INPUT_SIDEWINDER is not set -# CONFIG_INPUT_IFORCE_USB is not set -# CONFIG_INPUT_IFORCE_232 is not set -# CONFIG_INPUT_WARRIOR is not set -# CONFIG_INPUT_MAGELLAN is not set -# CONFIG_INPUT_SPACEORB is not set -# CONFIG_INPUT_SPACEBALL is not set -# CONFIG_INPUT_STINGER is not set -# CONFIG_INPUT_DB9 is not set -# CONFIG_INPUT_GAMECON is not set -# CONFIG_INPUT_TURBOGRAFX is not set -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -# CONFIG_ALIM7101_WDT is not set -# CONFIG_SC520_WDT is not set -# CONFIG_PCWATCHDOG is not set -# CONFIG_21285_WATCHDOG is not set -# CONFIG_977_WATCHDOG is not set -# CONFIG_SA1100_WATCHDOG is not set -CONFIG_PXA_WATCHDOG=m -# CONFIG_OMAHA_WATCHDOG is not set -# CONFIG_EUROTECH_WDT is not set -# CONFIG_IB700_WDT is not set -# CONFIG_WAFER_WDT is not set -# CONFIG_I810_TCO is not set -# CONFIG_MIXCOMWD is not set -# CONFIG_60XX_WDT is not set -# CONFIG_SC1200_WDT is not set -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_W83877F_WDT is not set -# CONFIG_WDT is not set -# CONFIG_WDTPCI is not set -# CONFIG_MACHZ_WDT is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -CONFIG_PXA_RTC=m -CONFIG_PXA_RTC_HACK=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# PCMCIA character devices -# -CONFIG_PCMCIA_SERIAL_CS=m -CONFIG_PCMCIA_MOBILISCAN_CS=m -# CONFIG_AXIM_TS is not set -CONFIG_AXIM_KEY=m -# CONFIG_AXIM_KEY_FIX is not set - -# -# Multimedia devices -# -CONFIG_MEDIA=m -CONFIG_VIDEO_DEV=m -CONFIG_V4L2_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -# CONFIG_I2C_PARPORT is not set - -# -# Video Adapters -# -# CONFIG_VIDEO_PMS is not set -# CONFIG_VIDEO_BWQCAM is not set -# CONFIG_VIDEO_CQCAM is not set -CONFIG_VIDEO_CPIA=m -CONFIG_VIDEO_CPIA_USB=m -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_ZORAN_BUZ is not set -# CONFIG_VIDEO_ZORAN_DC10 is not set -# CONFIG_VIDEO_ZORAN_LML33 is not set -# CONFIG_VIDEO_ZR36120 is not set -# CONFIG_VIDEO_MEYE is not set -# CONFIG_VIDEO_CYBERPRO is not set -# CONFIG_VIDEO_H3600_BACKPAQ is not set -# CONFIG_VIDEO_HAWKEYE is not set - -# -# Video for Linux 2 (V4L2) -# -CONFIG_VIDEO_WINNOV_CS=m - -# -# Radio Adapters -# -# CONFIG_RADIO_CADET is not set -# CONFIG_RADIO_RTRACK is not set -# CONFIG_RADIO_RTRACK2 is not set -# CONFIG_RADIO_AZTECH is not set -# CONFIG_RADIO_GEMTEK is not set -# CONFIG_RADIO_GEMTEK_PCI is not set -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_MAESTRO is not set -# CONFIG_RADIO_MIROPCM20 is not set -# CONFIG_RADIO_MIROPCM20_RDS is not set -# CONFIG_RADIO_SF16FMI is not set -# CONFIG_RADIO_TERRATEC is not set -# CONFIG_RADIO_TRUST is not set -# CONFIG_RADIO_TYPHOON is not set -# CONFIG_RADIO_ZOLTRIX is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -CONFIG_CRAMFS=y -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=m -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DRIVERFS_FS is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=m -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_UTF8=m - -# -# Console drivers -# -CONFIG_PC_KEYMAP=y -# CONFIG_VGA_CONSOLE is not set - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_ACORN is not set -# CONFIG_FB_ANAKIN is not set -# CONFIG_FB_CLPS711X is not set -# CONFIG_FB_S3C2410 is not set -# CONFIG_FB_SA1100 is not set -# CONFIG_FB_EPSON1356 is not set -# CONFIG_FB_MQ200 is not set -CONFIG_FB_PXA=y -# CONFIG_FB_PXA_8BPP is not set -CONFIG_FB_PXA_16BPP=y -CONFIG_FB_MQ1100=y -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_VIRTUAL is not set -CONFIG_FBCON_ADVANCED=y -# CONFIG_FBCON_MFB is not set -# CONFIG_FBCON_CFB2 is not set -# CONFIG_FBCON_CFB4 is not set -# CONFIG_FBCON_CFB8 is not set -CONFIG_FBCON_CFB16=y -# CONFIG_FBCON_CFB24 is not set -# CONFIG_FBCON_CFB32 is not set -# CONFIG_FBCON_AFB is not set -# CONFIG_FBCON_ILBM is not set -# CONFIG_FBCON_IPLAN2P2 is not set -# CONFIG_FBCON_IPLAN2P4 is not set -# CONFIG_FBCON_IPLAN2P8 is not set -# CONFIG_FBCON_MAC is not set -# CONFIG_FBCON_VGA_PLANES is not set -# CONFIG_FBCON_VGA is not set -# CONFIG_FBCON_HGA is not set -# CONFIG_FBCON_NO_LOGO is not set -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -CONFIG_FONT_8x8=y -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set - -# -# Sound -# -CONFIG_SOUND=y -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_MIDI_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_MAESTRO3 is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_RME96XX is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -# CONFIG_MIDI_VIA82CXXX is not set -CONFIG_SOUND_H3900_UDA1380=m -CONFIG_SOUND_H5400=m -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -# CONFIG_SOUND_DMAP is not set -# CONFIG_SOUND_AD1816 is not set -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_ADLIB is not set -# CONFIG_SOUND_ACI_MIXER is not set -# CONFIG_SOUND_CS4232 is not set -# CONFIG_SOUND_SSCAPE is not set -# CONFIG_SOUND_GUS is not set -# CONFIG_SOUND_VMIDI is not set -# CONFIG_SOUND_TRIX is not set -# CONFIG_SOUND_MSS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_NM256 is not set -# CONFIG_SOUND_MAD16 is not set -# CONFIG_SOUND_PAS is not set -# CONFIG_PAS_JOYSTICK is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_SB is not set -# CONFIG_SOUND_AWE32_SYNTH is not set -# CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_OPL3SA2 is not set -# CONFIG_SOUND_YMFPCI is not set -# CONFIG_SOUND_YMFPCI_LEGACY is not set -# CONFIG_SOUND_UART6850 is not set -# CONFIG_SOUND_AEDSP16 is not set -# CONFIG_SOUND_VIDC is not set -# CONFIG_SOUND_WAVEARTIST is not set -CONFIG_SOUND_PXA_AC97=m -# CONFIG_SOUND_TVMIXER is not set - -# -# Multimedia Capabilities Port drivers -# -# CONFIG_MCP is not set -# CONFIG_MCP_SA1100 is not set -# CONFIG_MCP_UCB1200 is not set -# CONFIG_MCP_UCB1200_AUDIO is not set -# CONFIG_MCP_UCB1200_TS is not set -# CONFIG_MCP_UCB1400_TS is not set - -# -# Console Switches -# -# CONFIG_SWITCHES is not set - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_LONG_TIMEOUT is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -CONFIG_USB_OHCI=m -# CONFIG_USB_OHCI_SA1111 is not set -CONFIG_USB_OHCI_H5400=m -# CONFIG_USB_OHCI_S3C2410 is not set -# CONFIG_USB_SL811HS is not set - -# -# USB Device Class drivers -# -CONFIG_USB_AUDIO=m -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_BLUETOOTH is not set -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_ACM is not set -CONFIG_USB_PRINTER=m - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_WACOM is not set - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# -CONFIG_USB_IBMCAM=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -# CONFIG_USB_DSBR is not set -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -CONFIG_USB_CDCETHER=m -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_IPAQ is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_KLSI is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_XIRCOM is not set -# CONFIG_USB_SERIAL_OMNINET is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_BRLVGER is not set - -# -# Linux As Bootldr Modules -# -# CONFIG_BIG_KERNEL is not set -# CONFIG_USE_DATE_CODE is not set -# CONFIG_YMODEM is not set -# CONFIG_LAB_DUMMY is not set -# CONFIG_LAB_CRC is not set -# CONFIG_LAB_YMODEM is not set -# CONFIG_LAB_MTD is not set -# CONFIG_LAB_COPY is not set -# CONFIG_LAB_COPY_YMODEM is not set -# CONFIG_LAB_COPY_FLASH is not set -# CONFIG_LAB_COPY_FS is not set -# CONFIG_LAB_COPY_WRAPPER is not set - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -# CONFIG_BLUEZ_HCIUSB is not set -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -# CONFIG_BLUEZ_HCIUART_BCSP_TXCRC is not set -# CONFIG_BLUEZ_HCIBFUSB is not set -CONFIG_BLUEZ_HCIDTL1=m -CONFIG_BLUEZ_HCIBT3C=m -CONFIG_BLUEZ_HCIBLUECARD=m -CONFIG_BLUEZ_HCIBTUART=m -# CONFIG_BLUEZ_HCIVHCI is not set - -# -# Kernel hacking -# -# CONFIG_FRAME_POINTER is not set -# CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_INFO is not set -# CONFIG_NO_PGT_CACHE is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -CONFIG_DEBUG_ERRORS=y -# CONFIG_DEBUG_LL is not set -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh37.1/defconfig-ipaqpxa b/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh37.1/defconfig-ipaqpxa deleted file mode 100644 index ee30cf0a42..0000000000 --- a/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh37.1/defconfig-ipaqpxa +++ /dev/null @@ -1,1578 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_GENERIC_BUST_SPINLOCK is not set -# CONFIG_GENERIC_ISA_DMA is not set - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# System Type -# -# CONFIG_ARCH_ANAKIN is not set -# CONFIG_ARCH_ARCA5K is not set -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -CONFIG_ARCH_PXA=y -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_OMAHA is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_MX1ADS is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_RISCSTATION is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_AT91RM9200DK is not set -# CONFIG_MINIMAL_OOPS is not set - -# -# Linux As Bootldr support -# -# CONFIG_LAB is not set -# CONFIG_BIG_KERNEL is not set -# CONFIG_USE_DATE_CODE is not set - -# -# Archimedes/A5000 Implementations -# - -# -# Archimedes/A5000 Implementations (select only ONE) -# -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set - -# -# Footbridge Implementations -# -# CONFIG_ARCH_CATS is not set -# CONFIG_ARCH_PERSONAL_SERVER is not set -# CONFIG_ARCH_EBSA285_ADDIN is not set -# CONFIG_ARCH_EBSA285_HOST is not set -# CONFIG_ARCH_NETWINDER is not set - -# -# SA11x0 Implementations -# -# CONFIG_SA1100_ACCELENT is not set -# CONFIG_SA1100_ASSABET is not set -# CONFIG_ASSABET_NEPONSET is not set -# CONFIG_SA1100_ADSBITSY is not set -# CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_CEP is not set -# CONFIG_SA1100_CERF is not set -# CONFIG_SA1100_H3100 is not set -# CONFIG_SA1100_H3600 is not set -# CONFIG_SA1100_H3800 is not set -# CONFIG_SA1100_CONSUS is not set -# CONFIG_SA1100_EXTENEX1 is not set -# CONFIG_SA1100_FLEXANET is not set -# CONFIG_SA1100_FREEBIRD is not set -# CONFIG_SA1100_FRODO is not set -# CONFIG_SA1100_GRAPHICSCLIENT is not set -# CONFIG_SA1100_GRAPHICSMASTER is not set -# CONFIG_SA1100_HACKKIT is not set -# CONFIG_SA1100_BADGE4 is not set -# CONFIG_SA1100_JORNADA720 is not set -# CONFIG_SA1100_JORNADA56X is not set -# CONFIG_SA1100_HUW_WEBPANEL is not set -# CONFIG_SA1100_ITSY is not set -# CONFIG_SA1100_LART is not set -# CONFIG_SA1100_NANOENGINE is not set -# CONFIG_SA1100_OMNIMETER is not set -# CONFIG_SA1100_PANGOLIN is not set -# CONFIG_SA1100_PLEB is not set -# CONFIG_SA1100_PT_SYSTEM3 is not set -# CONFIG_SA1100_SHANNON is not set -# CONFIG_SA1100_SHERMAN is not set -# CONFIG_SA1100_SIMPAD is not set -# CONFIG_SA1100_SIMPUTER is not set -# CONFIG_SA1100_PFS168 is not set -# CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_XP860 is not set -# CONFIG_SA1100_YOPY is not set -# CONFIG_SA1100_USB is not set -# CONFIG_SA1100_USB_NETLINK is not set -# CONFIG_SA1100_USB_CHAR is not set -# CONFIG_REGISTERS is not set - -# -# Intel PXA250/210 Implementations -# -# CONFIG_ARCH_LUBBOCK is not set -# CONFIG_ARCH_PXA_IDP is not set -# CONFIG_ARCH_PXA_CERF is not set -CONFIG_ARCH_H3900=y -CONFIG_ARCH_H1900=y -CONFIG_ARCH_H5400=y -# CONFIG_ARCH_H2200 is not set -CONFIG_ARCH_AXIM=y -CONFIG_PXA_USB=m -CONFIG_PXA_USB_NETLINK=m -CONFIG_PXA_USB_CHAR=m - -# -# CLPS711X/EP721X Implementations -# -# CONFIG_ARCH_AUTCPU12 is not set -# CONFIG_ARCH_CDB89712 is not set -# CONFIG_ARCH_CLEP7312 is not set -# CONFIG_ARCH_EDB7211 is not set -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_FORTUNET is not set -# CONFIG_ARCH_EP7211 is not set -# CONFIG_ARCH_EP7212 is not set -# CONFIG_ARCH_ACORN is not set -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set - -# -# Processor Type -# -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -# CONFIG_CPU_ARM610 is not set -# CONFIG_CPU_ARM710 is not set -# CONFIG_CPU_ARM720T is not set -# CONFIG_CPU_ARM920T is not set -# CONFIG_CPU_ARM922T is not set -# CONFIG_PLD is not set -# CONFIG_CPU_ARM926T is not set -# CONFIG_CPU_ARM1020 is not set -# CONFIG_CPU_ARM1026 is not set -# CONFIG_CPU_SA110 is not set -# CONFIG_CPU_SA1100 is not set -CONFIG_CPU_32v5=y -CONFIG_CPU_XSCALE=y -CONFIG_XSCALE_PXA250=y -# CONFIG_XSCALE_80200_OLD is not set -# CONFIG_CPU_32v3 is not set -# CONFIG_CPU_32v4 is not set -# CONFIG_SA1100_IPAQ is not set -CONFIG_PXA_IPAQ=y -CONFIG_IPAQ_HANDHELD=y - -# -# Compaq iPAQ Handheld -# -CONFIG_IPAQ_HAL=m -# CONFIG_H3600_MICRO is not set -CONFIG_IPAQ_HAS_ROSELLA=y -CONFIG_IPAQ_HAS_ASIC3=y -CONFIG_H3600_ASIC=m -CONFIG_H3900_ASIC_DEBUG=m -CONFIG_H5400_ASIC=m -CONFIG_H1900_ASIC=m -CONFIG_H1900_TS=m -CONFIG_H3600_HARDWARE=y -CONFIG_IPAQ_SLEEVE=m -CONFIG_SLEEVE_DEBUG=y -CONFIG_SLEEVE_DEBUG_VERBOSE=0 -# CONFIG_SLEEVE_IRQ_DEMUX is not set - -# -# Dell Axim X5 -# -CONFIG_AXIM_HAL=m - -# -# Processor Features -# -# CONFIG_DISCONTIGMEM is not set - -# -# General setup -# -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set -# CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_CPU_FREQ=y -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -# CONFIG_I82092 is not set -# CONFIG_I82365 is not set -# CONFIG_TCIC is not set -# CONFIG_PCMCIA_CLPS6700 is not set -# CONFIG_PCMCIA_SA1100 is not set -CONFIG_PCMCIA_PXA=m -# CONFIG_MERCURY_BACKPAQ is not set - -# -# MMC/SD Card support -# -CONFIG_MMC=m -CONFIG_MMC_DEBUG=y -CONFIG_MMC_DEBUG_VERBOSE=0 -CONFIG_MMC_SAMSUNG_ASIC=m -# CONFIG_MMC_S3C2410 is not set -CONFIG_MMC_H5400=m -CONFIG_MMC_ASIC3=m -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_XIP_KERNEL is not set - -# -# At least one math emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_FASTFPE is not set -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_PM=y -CONFIG_APM=m -# CONFIG_HWTIMER is not set -# CONFIG_ARTHUR is not set -CONFIG_CMDLINE="keepinitrd" -CONFIG_ALIGNMENT_TRAP=y - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -# CONFIG_PARPORT_SERIAL is not set -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_ARC is not set -# CONFIG_PARPORT_IDP is not set -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -# CONFIG_PARPORT_1284 is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -CONFIG_MTD_DEBUG=y -CONFIG_MTD_DEBUG_VERBOSE=1 -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -CONFIG_MTD_JEDECPROBE=m -CONFIG_MTD_GEN_PROBE=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_NOSWAP=y -# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -CONFIG_MTD_CFI_GEOMETRY=y -# CONFIG_MTD_CFI_B1 is not set -CONFIG_MTD_CFI_B2=y -CONFIG_MTD_CFI_B4=y -# CONFIG_MTD_CFI_B8 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set -# CONFIG_MTD_JEDEC is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -CONFIG_MTD_IPAQ=y -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_CDB89712 is not set -# CONFIG_MTD_SA1100 is not set -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_IQ80310 is not set -# CONFIG_MTD_LUBBOCK is not set -# CONFIG_MTD_EPXA10DB is not set -# CONFIG_MTD_FORTUNET is not set -# CONFIG_MTD_AUTCPU12 is not set -# CONFIG_MTD_EDB7312 is not set -# CONFIG_MTD_H720X is not set -# CONFIG_MTD_IMPA7 is not set -# CONFIG_MTD_CEIVA is not set -# CONFIG_MTD_PCI is not set -# CONFIG_MTD_PCMCIA is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -CONFIG_MTD_BLKMTD=m - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -# CONFIG_MTD_DOCPROBE is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -CONFIG_NVRD=m - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -CONFIG_BLK_DEV_LVM=m -CONFIG_BLK_DEV_DM=m - -# -# Networking options -# -CONFIG_PACKET=m -CONFIG_PACKET_MMAP=y -# CONFIG_NETLINK_DEV is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -# CONFIG_IP_NF_AMANDA is not set -# CONFIG_IP_NF_TFTP is not set -CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_QUEUE is not set -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -# CONFIG_IP_NF_MATCH_PKTTYPE is not set -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -# CONFIG_IP_NF_MATCH_RECENT is not set -# CONFIG_IP_NF_MATCH_ECN is not set -# CONFIG_IP_NF_MATCH_DSCP is not set -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -# CONFIG_IP_NF_MATCH_HELPER is not set -CONFIG_IP_NF_MATCH_STATE=m -# CONFIG_IP_NF_MATCH_CONNTRACK is not set -# CONFIG_IP_NF_MATCH_UNCLEAN is not set -# CONFIG_IP_NF_MATCH_OWNER is not set -CONFIG_IP_NF_FILTER=m -# CONFIG_IP_NF_TARGET_REJECT is not set -# CONFIG_IP_NF_TARGET_MIRROR is not set -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_NAT_LOCAL is not set -# CONFIG_IP_NF_NAT_SNMP_BASIC is not set -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -# CONFIG_IP_NF_TARGET_ECN is not set -# CONFIG_IP_NF_TARGET_DSCP is not set -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -# CONFIG_IP_NF_ARPTABLES is not set -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -# CONFIG_IP_NF_COMPAT_IPFWADM is not set -CONFIG_IPV6=m -CONFIG_IPV6_SUBTREES=y -CONFIG_IPV6_TUNNEL=m -CONFIG_IPV6_MOBILITY=m -CONFIG_IPV6_MOBILITY_MN=m -# CONFIG_IPV6_MOBILITY_HA is not set -CONFIG_IPV6_MOBILITY_DEBUG=y - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -# CONFIG_IP6_NF_MATCH_RT is not set -# CONFIG_IP6_NF_MATCH_OPTS is not set -# CONFIG_IP6_NF_MATCH_FRAG is not set -# CONFIG_IP6_NF_MATCH_HL is not set -CONFIG_IP6_NF_MATCH_MULTIPORT=m -# CONFIG_IP6_NF_MATCH_OWNER is not set -CONFIG_IP6_NF_MATCH_MARK=m -# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set -# CONFIG_IP6_NF_MATCH_AHESP is not set -# CONFIG_IP6_NF_MATCH_LENGTH is not set -# CONFIG_IP6_NF_MATCH_EUI64 is not set -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_IPSEC=m - -# -# IPSec options (FreeS/WAN) -# -CONFIG_KLIPS_AUTH_HMAC_MD5=y -CONFIG_KLIPS_AUTH_HMAC_SHA1=y -CONFIG_KLIPS_ENC_3DES=y - -# -# ESP always enabled with tunnel mode -# -CONFIG_KLIPS_IPCOMP=y -CONFIG_KLIPS_DEBUG=y - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -# CONFIG_NET_ETHERNET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_MPPE=m -# CONFIG_PPPOE is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -# CONFIG_STRIP is not set -# CONFIG_WAVELAN is not set -# CONFIG_ARLAN is not set -# CONFIG_AIRONET4500 is not set -# CONFIG_AIRONET4500_NONCS is not set -# CONFIG_AIRONET4500_PROC is not set -# CONFIG_HERMES is not set -# CONFIG_SPECTRUM24T is not set - -# -# Wireless Pcmcia cards support -# -# CONFIG_PCMCIA_HERMES is not set -# CONFIG_AIRO_CS is not set -# CONFIG_WVLAN_CS is not set -# CONFIG_MWVLAN_CS is not set -# CONFIG_HOSTAP is not set -# CONFIG_HOSTAP_CS is not set -CONFIG_NET_WIRELESS=y -CONFIG_ATMELWLAN=y -CONFIG_ATMELWLAN_USB_503A_RFMD=m -CONFIG_ATMELWLAN_PCMCIA_502A=m -CONFIG_ATMELWLAN_PCMCIA_3COM=m -CONFIG_ATMELWLAN_PCMCIA_502AD=m -CONFIG_ATMELWLAN_PCMCIA_502AE=m -CONFIG_ATMELWLAN_PCMCIA_504=m - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_AXNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -# CONFIG_ARCNET_COM20020_CS is not set -# CONFIG_PCMCIA_IBMTR is not set -CONFIG_NET_PCMCIA_RADIO=y -CONFIG_PCMCIA_RAYCS=m -CONFIG_PCMCIA_NETWAVE=m -CONFIG_PCMCIA_WAVELAN=m -# CONFIG_AIRONET4500_CS is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -CONFIG_IRDA=m - -# -# IrDA protocols -# -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y - -# -# IrDA options -# -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -CONFIG_IRDA_DEBUG=y - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m - -# -# Dongle support -# -# CONFIG_DONGLE is not set - -# -# FIR device drivers -# -# CONFIG_USB_IRDA is not set -# CONFIG_NSC_FIR is not set -# CONFIG_WINBOND_FIR is not set -# CONFIG_TOSHIBA_FIR is not set -# CONFIG_SMC_IRCC_FIR is not set -# CONFIG_ALI_FIR is not set -# CONFIG_VLSI_FIR is not set -CONFIG_PXA_FIR=m - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=m - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=m - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=m -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set -# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set -# CONFIG_BLK_DEV_IDEDISK_IBM is not set -# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set -# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set -# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set -# CONFIG_BLK_DEV_IDEDISK_WD is not set -# CONFIG_BLK_DEV_COMMERIAL is not set -# CONFIG_BLK_DEV_TIVO is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=m -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_IDE_CHIPSETS is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_DMA_NONPCI is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set - -# -# SCSI support -# -CONFIG_SCSI=m - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=40 -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_PPA is not set -# CONFIG_SCSI_IMM is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_DEBUG is not set - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_PCMCIA=y -# CONFIG_PCMCIA_AHA152X is not set -# CONFIG_PCMCIA_FDOMAIN is not set -# CONFIG_PCMCIA_NINJA_SCSI is not set -# CONFIG_PCMCIA_QLOGIC is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m -CONFIG_INPUT_UINPUT=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_EXTENDED=y -# CONFIG_SERIAL_MANY_PORTS is not set -# CONFIG_SERIAL_SHARE_IRQ is not set -# CONFIG_SERIAL_DETECT_IRQ is not set -# CONFIG_SERIAL_MULTIPORT is not set -# CONFIG_HUB6 is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_ANAKIN is not set -# CONFIG_SERIAL_ANAKIN_CONSOLE is not set -# CONFIG_SERIAL_S3C2410 is not set -# CONFIG_SERIAL_S3C2410_CONSOLE is not set -# CONFIG_SERIAL_AMBA is not set -# CONFIG_SERIAL_AMBA_CONSOLE is not set -# CONFIG_SERIAL_CLPS711X is not set -# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE is not set -# CONFIG_SERIAL_UART00 is not set -# CONFIG_SERIAL_UART00_CONSOLE is not set -# CONFIG_SERIAL_SA1100 is not set -# CONFIG_SERIAL_SA1100_CONSOLE is not set -# CONFIG_SERIAL_SIR_PXA is not set -# CONFIG_SERIAL_8250 is not set -# CONFIG_SERIAL_8250_CONSOLE is not set -# CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SERIAL_8250_MANY_PORTS is not set -# CONFIG_SERIAL_8250_SHARE_IRQ is not set -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_HUB6 is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 -# CONFIG_PRINTER is not set -# CONFIG_PPDEV is not set -CONFIG_NEWTONKBD=m -# CONFIG_SA1100_PROFILER is not set - -# -# Compaq iPAQ H3600 support -# -CONFIG_TOUCHSCREEN_H3600=m -# CONFIG_H3600_BACKPAQ_FPGA is not set -# CONFIG_H3600_BACKPAQ_ACCEL is not set -# CONFIG_H3600_BACKPAQ_GASGAUGE is not set -# CONFIG_H3600_BACKPAQ_SRAM is not set -# CONFIG_H3600_BACKPAQ_AUDIO is not set -# CONFIG_H3600_STOWAWAY is not set -# CONFIG_H3800_MICROKBD is not set -# CONFIG_SA1100_LIRC is not set -CONFIG_H5400_BUZZER=m -CONFIG_H5400_FSI=m - -# -# I2C support -# -CONFIG_I2C=m -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -CONFIG_I2C_PXA_ALGO=m -CONFIG_I2C_PXA_ADAP=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_PROC=m -# CONFIG_I2C_DS1307 is not set - -# -# L3 serial bus support -# -# CONFIG_L3 is not set -# CONFIG_L3_ALGOBIT is not set -# CONFIG_L3_BIT_SA1100_GPIO is not set - -# -# Other L3 adapters -# -# CONFIG_L3_S3C2410 is not set -# CONFIG_L3_SA1111 is not set -# CONFIG_L3_BACKPAQ is not set -# CONFIG_BIT_SA1100_GPIO is not set - -# -# SPI support -# -# CONFIG_SPI is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=m -# CONFIG_PSMOUSE is not set -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set -# CONFIG_MK712_MOUSE is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_INPUT_NS558 is not set -# CONFIG_INPUT_LIGHTNING is not set -# CONFIG_INPUT_PCIGAME is not set -# CONFIG_INPUT_CS461X is not set -# CONFIG_INPUT_EMU10K1 is not set -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m - -# -# Joysticks -# -# CONFIG_INPUT_ANALOG is not set -# CONFIG_INPUT_A3D is not set -# CONFIG_INPUT_ADI is not set -# CONFIG_INPUT_COBRA is not set -# CONFIG_INPUT_GF2K is not set -# CONFIG_INPUT_GRIP is not set -# CONFIG_INPUT_INTERACT is not set -# CONFIG_INPUT_TMDC is not set -# CONFIG_INPUT_SIDEWINDER is not set -# CONFIG_INPUT_IFORCE_USB is not set -# CONFIG_INPUT_IFORCE_232 is not set -# CONFIG_INPUT_WARRIOR is not set -# CONFIG_INPUT_MAGELLAN is not set -# CONFIG_INPUT_SPACEORB is not set -# CONFIG_INPUT_SPACEBALL is not set -# CONFIG_INPUT_STINGER is not set -# CONFIG_INPUT_DB9 is not set -# CONFIG_INPUT_GAMECON is not set -# CONFIG_INPUT_TURBOGRAFX is not set -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -# CONFIG_ALIM7101_WDT is not set -# CONFIG_SC520_WDT is not set -# CONFIG_PCWATCHDOG is not set -# CONFIG_21285_WATCHDOG is not set -# CONFIG_977_WATCHDOG is not set -# CONFIG_SA1100_WATCHDOG is not set -CONFIG_PXA_WATCHDOG=m -# CONFIG_OMAHA_WATCHDOG is not set -# CONFIG_EUROTECH_WDT is not set -# CONFIG_IB700_WDT is not set -# CONFIG_WAFER_WDT is not set -# CONFIG_I810_TCO is not set -# CONFIG_MIXCOMWD is not set -# CONFIG_60XX_WDT is not set -# CONFIG_SC1200_WDT is not set -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_W83877F_WDT is not set -# CONFIG_WDT is not set -# CONFIG_WDTPCI is not set -# CONFIG_MACHZ_WDT is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -CONFIG_PXA_RTC=m -CONFIG_PXA_RTC_HACK=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# PCMCIA character devices -# -CONFIG_PCMCIA_SERIAL_CS=m -CONFIG_PCMCIA_MOBILISCAN_CS=m -# CONFIG_AXIM_TS is not set -CONFIG_AXIM_KEY=m -# CONFIG_AXIM_KEY_FIX is not set - -# -# Multimedia devices -# -CONFIG_MEDIA=m -CONFIG_VIDEO_DEV=m -CONFIG_V4L2_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -# CONFIG_I2C_PARPORT is not set - -# -# Video Adapters -# -# CONFIG_VIDEO_PMS is not set -# CONFIG_VIDEO_BWQCAM is not set -# CONFIG_VIDEO_CQCAM is not set -CONFIG_VIDEO_CPIA=m -CONFIG_VIDEO_CPIA_USB=m -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_ZORAN_BUZ is not set -# CONFIG_VIDEO_ZORAN_DC10 is not set -# CONFIG_VIDEO_ZORAN_LML33 is not set -# CONFIG_VIDEO_ZR36120 is not set -# CONFIG_VIDEO_MEYE is not set -# CONFIG_VIDEO_CYBERPRO is not set -# CONFIG_VIDEO_H3600_BACKPAQ is not set -# CONFIG_VIDEO_HAWKEYE is not set - -# -# Video for Linux 2 (V4L2) -# -CONFIG_VIDEO_WINNOV_CS=m - -# -# Radio Adapters -# -# CONFIG_RADIO_CADET is not set -# CONFIG_RADIO_RTRACK is not set -# CONFIG_RADIO_RTRACK2 is not set -# CONFIG_RADIO_AZTECH is not set -# CONFIG_RADIO_GEMTEK is not set -# CONFIG_RADIO_GEMTEK_PCI is not set -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_MAESTRO is not set -# CONFIG_RADIO_MIROPCM20 is not set -# CONFIG_RADIO_MIROPCM20_RDS is not set -# CONFIG_RADIO_SF16FMI is not set -# CONFIG_RADIO_TERRATEC is not set -# CONFIG_RADIO_TRUST is not set -# CONFIG_RADIO_TYPHOON is not set -# CONFIG_RADIO_ZOLTRIX is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -CONFIG_CRAMFS=y -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=m -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DRIVERFS_FS is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=m -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_UTF8=m - -# -# Console drivers -# -CONFIG_PC_KEYMAP=y -# CONFIG_VGA_CONSOLE is not set - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_ACORN is not set -# CONFIG_FB_ANAKIN is not set -# CONFIG_FB_CLPS711X is not set -# CONFIG_FB_S3C2410 is not set -# CONFIG_FB_SA1100 is not set -# CONFIG_FB_EPSON1356 is not set -# CONFIG_FB_MQ200 is not set -CONFIG_FB_PXA=y -# CONFIG_FB_PXA_8BPP is not set -CONFIG_FB_PXA_16BPP=y -CONFIG_FB_MQ1100=y -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_VIRTUAL is not set -CONFIG_FBCON_ADVANCED=y -# CONFIG_FBCON_MFB is not set -# CONFIG_FBCON_CFB2 is not set -# CONFIG_FBCON_CFB4 is not set -# CONFIG_FBCON_CFB8 is not set -CONFIG_FBCON_CFB16=y -# CONFIG_FBCON_CFB24 is not set -# CONFIG_FBCON_CFB32 is not set -# CONFIG_FBCON_AFB is not set -# CONFIG_FBCON_ILBM is not set -# CONFIG_FBCON_IPLAN2P2 is not set -# CONFIG_FBCON_IPLAN2P4 is not set -# CONFIG_FBCON_IPLAN2P8 is not set -# CONFIG_FBCON_MAC is not set -# CONFIG_FBCON_VGA_PLANES is not set -# CONFIG_FBCON_VGA is not set -# CONFIG_FBCON_HGA is not set -# CONFIG_FBCON_NO_LOGO is not set -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -CONFIG_FONT_8x8=y -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set - -# -# Sound -# -CONFIG_SOUND=y -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_MIDI_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_MAESTRO3 is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_RME96XX is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -# CONFIG_MIDI_VIA82CXXX is not set -CONFIG_SOUND_H3900_UDA1380=m -CONFIG_SOUND_H5400=m -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -# CONFIG_SOUND_DMAP is not set -# CONFIG_SOUND_AD1816 is not set -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_ADLIB is not set -# CONFIG_SOUND_ACI_MIXER is not set -# CONFIG_SOUND_CS4232 is not set -# CONFIG_SOUND_SSCAPE is not set -# CONFIG_SOUND_GUS is not set -# CONFIG_SOUND_VMIDI is not set -# CONFIG_SOUND_TRIX is not set -# CONFIG_SOUND_MSS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_NM256 is not set -# CONFIG_SOUND_MAD16 is not set -# CONFIG_SOUND_PAS is not set -# CONFIG_PAS_JOYSTICK is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_SB is not set -# CONFIG_SOUND_AWE32_SYNTH is not set -# CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_OPL3SA2 is not set -# CONFIG_SOUND_YMFPCI is not set -# CONFIG_SOUND_YMFPCI_LEGACY is not set -# CONFIG_SOUND_UART6850 is not set -# CONFIG_SOUND_AEDSP16 is not set -# CONFIG_SOUND_VIDC is not set -# CONFIG_SOUND_WAVEARTIST is not set -CONFIG_SOUND_PXA_AC97=m -# CONFIG_SOUND_TVMIXER is not set - -# -# Multimedia Capabilities Port drivers -# -# CONFIG_MCP is not set -# CONFIG_MCP_SA1100 is not set -# CONFIG_MCP_UCB1200 is not set -# CONFIG_MCP_UCB1200_AUDIO is not set -# CONFIG_MCP_UCB1200_TS is not set -# CONFIG_MCP_UCB1400_TS is not set - -# -# Console Switches -# -# CONFIG_SWITCHES is not set - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_LONG_TIMEOUT is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -CONFIG_USB_OHCI=m -# CONFIG_USB_OHCI_SA1111 is not set -CONFIG_USB_OHCI_H5400=m -# CONFIG_USB_OHCI_S3C2410 is not set -# CONFIG_USB_SL811HS is not set - -# -# USB Device Class drivers -# -CONFIG_USB_AUDIO=m -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_BLUETOOTH is not set -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_ACM is not set -CONFIG_USB_PRINTER=m - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_WACOM is not set - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# -CONFIG_USB_IBMCAM=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -# CONFIG_USB_DSBR is not set -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -CONFIG_USB_CDCETHER=m -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_IPAQ is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_KLSI is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_XIRCOM is not set -# CONFIG_USB_SERIAL_OMNINET is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_BRLVGER is not set - -# -# Linux As Bootldr Modules -# -# CONFIG_BIG_KERNEL is not set -# CONFIG_USE_DATE_CODE is not set -# CONFIG_YMODEM is not set -# CONFIG_LAB_DUMMY is not set -# CONFIG_LAB_CRC is not set -# CONFIG_LAB_YMODEM is not set -# CONFIG_LAB_MTD is not set -# CONFIG_LAB_COPY is not set -# CONFIG_LAB_COPY_YMODEM is not set -# CONFIG_LAB_COPY_FLASH is not set -# CONFIG_LAB_COPY_FS is not set -# CONFIG_LAB_COPY_WRAPPER is not set - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -# CONFIG_BLUEZ_HCIUSB is not set -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -# CONFIG_BLUEZ_HCIUART_BCSP_TXCRC is not set -# CONFIG_BLUEZ_HCIBFUSB is not set -CONFIG_BLUEZ_HCIDTL1=m -CONFIG_BLUEZ_HCIBT3C=m -CONFIG_BLUEZ_HCIBLUECARD=m -CONFIG_BLUEZ_HCIBTUART=m -# CONFIG_BLUEZ_HCIVHCI is not set - -# -# Kernel hacking -# -# CONFIG_FRAME_POINTER is not set -# CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_INFO is not set -# CONFIG_NO_PGT_CACHE is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -CONFIG_DEBUG_ERRORS=y -# CONFIG_DEBUG_LL is not set -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh37.4/defconfig-ipaqpxa b/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh37.4/defconfig-ipaqpxa deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh37.4/mmc_h5400.patch b/linux/handhelds-pxa-2.4.19-rmk6-pxa1-hh37.4/mmc_h5400.patch deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/handhelds-pxa-2.6/defconfig b/linux/handhelds-pxa-2.6/defconfig deleted file mode 100644 index cd92420627..0000000000 --- a/linux/handhelds-pxa-2.6/defconfig +++ /dev/null @@ -1,1328 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_ARM=y -CONFIG_MMU=y -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -# CONFIG_CLEAN_COMPILE is not set -CONFIG_BROKEN=y -CONFIG_BROKEN_ON_SMP=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_HOTPLUG=y -CONFIG_IKCONFIG=y -# CONFIG_MINIMAL_OOPS is not set -CONFIG_IKCONFIG_PROC=y -CONFIG_EMBEDDED=y -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -# CONFIG_IOSCHED_CFQ is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# System Type -# -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP3XX is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_L7200 is not set -CONFIG_ARCH_PXA=y -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_LH7A40X is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE_PB is not set - -# -# Intel PXA2xx Implementations -# -CONFIG_PXA25x=y -# CONFIG_PXA27x is not set -# CONFIG_ARCH_LUBBOCK is not set -# CONFIG_MACH_MAINSTONE is not set -# CONFIG_ARCH_PXA_IDP is not set -CONFIG_ARCH_ESERIES=y -CONFIG_MACH_E740=y -CONFIG_MACH_E750=y -CONFIG_MACH_E800=y -CONFIG_ESERIES_TMIO=y -CONFIG_OHCI_TMIO=y -# CONFIG_MTD_NAND_TMIO is not set -CONFIG_ESERIES_UDC=y -# CONFIG_E740_PCMCIA is not set -# CONFIG_E750_PCMCIA is not set -# CONFIG_E800_PCMCIA is not set -# CONFIG_MACH_A620 is not set -# CONFIG_ARCH_H1900 is not set -CONFIG_ARCH_H2200=y -CONFIG_H2200_PCMCIA=m -CONFIG_H2200_LCD=m -CONFIG_H2200_TS=m -CONFIG_ARCH_H3900=y -CONFIG_MACH_H4000=y -CONFIG_ARCH_H5400=y -# CONFIG_MACH_HIMALAYA is not set -# CONFIG_HIMALAYA_USB is not set -# CONFIG_PXA_NSSP is not set -# CONFIG_HIMALAYA_INPUT is not set -# CONFIG_HIMALAYA_LEDS is not set -# CONFIG_ARCH_AXIMX5 is not set -# CONFIG_AXIMX5_MISC is not set -# CONFIG_AXIMX5_LCD is not set -# CONFIG_AXIMX5_PCMCIA is not set -# CONFIG_AXIMX5_BUTTONS is not set -# CONFIG_ARCH_AXIMX3 is not set -# CONFIG_ARCH_ROVERP1 is not set -# CONFIG_ARCH_ROVERP5P is not set - -# -# Linux As Bootloader -# -# CONFIG_LAB is not set - -# -# Processor Type -# -CONFIG_CPU_32=y -CONFIG_CPU_XSCALE=y -CONFIG_CPU_XSCALE_PXA250=y -CONFIG_CPU_32v5=y -CONFIG_CPU_ABRT_EV5T=y -CONFIG_CPU_TLB_V4WBI=y -CONFIG_CPU_MINICACHE=y - -# -# Processor Features -# -# CONFIG_ARM_FASTCALL is not set -CONFIG_ARM_THUMB=y -CONFIG_XSCALE_PMU=y - -# -# Compaq/iPAQ Options -# -CONFIG_PXA_IPAQ=y - -# -# XScale-based iPAQ -# -CONFIG_IPAQ_HANDHELD=y -CONFIG_IPAQ_SLEEVE=m -CONFIG_IPAQ_ASIC2=m -CONFIG_IPAQ_ASIC2_TOUCHSCREEN=m -CONFIG_IPAQ_ASIC3=m -CONFIG_IPAQ_H3900_LCD=m -CONFIG_IPAQ_H4000_LCD=m -CONFIG_IPAQ_SAMCOP=m -CONFIG_IPAQ_SAMCOP_ADC=m -CONFIG_IPAQ_SAMCOP_TOUCHSCREEN=m -CONFIG_IPAQ_SHAMCOP=m -CONFIG_IPAQ_SHAMCOP_ADC=m -CONFIG_IPAQ_SHAMCOP_TOUCHSCREEN=m -CONFIG_IPAQ_SHAMCOP_NAND=m -CONFIG_IPAQ_H5400_LCD=m -CONFIG_IPAQ_H5400_WIFI=m - -# -# General setup -# -# CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -# CONFIG_CPU_FREQ is not set - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -# CONFIG_PCMCIA_DEBUG is not set -# CONFIG_TCIC is not set -CONFIG_PCMCIA_PXA2XX=m - -# -# At least one math emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set -# CONFIG_FPE_FASTFPE is not set -# CONFIG_VFP is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_AOUT is not set -# CONFIG_BINFMT_MISC is not set - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set -CONFIG_SOC_DEVICE=m -# CONFIG_DOCKING_HOTPLUG is not set -# CONFIG_DEBUG_DRIVER is not set -CONFIG_PM=y -# CONFIG_PREEMPT is not set -# CONFIG_APM is not set -# CONFIG_ARTHUR is not set -CONFIG_CMDLINE="keepinitrd" -CONFIG_ALIGNMENT_TRAP=y - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -CONFIG_MTD_DEBUG=y -CONFIG_MTD_DEBUG_VERBOSE=1 -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_CONCAT=m -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_NOSWAP=y -# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -CONFIG_MTD_CFI_GEOMETRY=y -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -CONFIG_MTD_IPAQ=y -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_EDB7312 is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -CONFIG_MTD_NAND=m -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -# CONFIG_MTD_NAND_H1900 is not set -CONFIG_MTD_NAND_IDS=m -# CONFIG_MTD_NAND_DISKONCHIP is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set -# CONFIG_MMC_TOSHIBA is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_BLK_DEV_INITRD=y - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=m -CONFIG_PACKET_MMAP=y -# CONFIG_NETLINK_DEV is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=m -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m - -# -# IP: Virtual Server Configuration -# -# CONFIG_IP_VS is not set -CONFIG_IPV6=m -# CONFIG_IPV6_PRIVACY is not set -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_BRIDGE_NETFILTER=y - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_TFTP is not set -# CONFIG_IP_NF_AMANDA is not set -# CONFIG_IP_NF_QUEUE is not set -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -# CONFIG_IP_NF_MATCH_IPRANGE is not set -CONFIG_IP_NF_MATCH_MAC=m -# CONFIG_IP_NF_MATCH_PKTTYPE is not set -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -# CONFIG_IP_NF_MATCH_RECENT is not set -# CONFIG_IP_NF_MATCH_ECN is not set -# CONFIG_IP_NF_MATCH_DSCP is not set -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -# CONFIG_IP_NF_MATCH_HELPER is not set -CONFIG_IP_NF_MATCH_STATE=m -# CONFIG_IP_NF_MATCH_CONNTRACK is not set -# CONFIG_IP_NF_MATCH_OWNER is not set -# CONFIG_IP_NF_MATCH_PHYSDEV is not set -CONFIG_IP_NF_FILTER=m -# CONFIG_IP_NF_TARGET_REJECT is not set -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_TARGET_NETMAP is not set -# CONFIG_IP_NF_TARGET_SAME is not set -# CONFIG_IP_NF_NAT_LOCAL is not set -# CONFIG_IP_NF_NAT_SNMP_BASIC is not set -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -# CONFIG_IP_NF_TARGET_ECN is not set -# CONFIG_IP_NF_TARGET_DSCP is not set -CONFIG_IP_NF_TARGET_MARK=m -# CONFIG_IP_NF_TARGET_CLASSIFY is not set -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -# CONFIG_IP_NF_ARPTABLES is not set -CONFIG_IP_NF_COMPAT_IPCHAINS=m -# CONFIG_IP_NF_COMPAT_IPFWADM is not set -# CONFIG_IP_NF_RAW is not set -# CONFIG_IP_NF_MATCH_ADDRTYPE is not set -# CONFIG_IP_NF_MATCH_REALM is not set - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -# CONFIG_IP6_NF_MATCH_RT is not set -# CONFIG_IP6_NF_MATCH_OPTS is not set -# CONFIG_IP6_NF_MATCH_FRAG is not set -# CONFIG_IP6_NF_MATCH_HL is not set -CONFIG_IP6_NF_MATCH_MULTIPORT=m -# CONFIG_IP6_NF_MATCH_OWNER is not set -CONFIG_IP6_NF_MATCH_MARK=m -# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set -# CONFIG_IP6_NF_MATCH_AHESP is not set -# CONFIG_IP6_NF_MATCH_LENGTH is not set -# CONFIG_IP6_NF_MATCH_EUI64 is not set -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -# CONFIG_IP6_NF_RAW is not set - -# -# Bridge: Netfilter Configuration -# -# CONFIG_BRIDGE_NF_EBTABLES is not set -CONFIG_XFRM=y -CONFIG_XFRM_USER=m - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -CONFIG_BRIDGE=m -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -CONFIG_IRDA=m - -# -# IrDA protocols -# -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y - -# -# IrDA options -# -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -CONFIG_IRDA_DEBUG=y - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -CONFIG_IRTTY_SIR=m - -# -# Dongle support -# -# CONFIG_DONGLE is not set - -# -# Old SIR device drivers -# -CONFIG_IRPORT_SIR=m - -# -# Old Serial dongle support -# -# CONFIG_DONGLE_OLD is not set - -# -# FIR device drivers -# -# CONFIG_USB_IRDA is not set -# CONFIG_SIGMATEL_FIR is not set -CONFIG_BT=m -# CONFIG_BT_L2CAP is not set -# CONFIG_BT_SCO is not set - -# -# Bluetooth device drivers -# -# CONFIG_BT_HCIUSB is not set -# CONFIG_BT_HCIUART is not set -# CONFIG_BT_HCIBCM203X is not set -# CONFIG_BT_HCIBFUSB is not set -# CONFIG_BT_HCIDTL1 is not set -# CONFIG_BT_HCIBT3C is not set -# CONFIG_BT_HCIBLUECARD is not set -# CONFIG_BT_HCIBTUART is not set -# CONFIG_BT_HCIVHCI is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m - -# -# Ethernet (10 or 100Mbit) -# -# CONFIG_NET_ETHERNET is not set -CONFIG_MII=m - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y - -# -# Obsolete Wireless cards support (pre-802.11) -# -# CONFIG_STRIP is not set -CONFIG_PCMCIA_WAVELAN=m -CONFIG_PCMCIA_NETWAVE=m - -# -# Wireless 802.11 Frequency Hopping cards support -# -CONFIG_PCMCIA_RAYCS=m - -# -# Wireless 802.11b ISA/PCI cards support -# -CONFIG_HERMES=m -# CONFIG_ATMEL is not set - -# -# Wireless 802.11b Pcmcia/Cardbus cards support -# -CONFIG_PCMCIA_HERMES=m -CONFIG_AIRO_CS=m -# CONFIG_PCMCIA_WL3501 is not set -CONFIG_NET_WIRELESS=y -# CONFIG_HOSTAP is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -CONFIG_PCMCIA_AXNET=m - -# -# Wan interfaces -# -# CONFIG_WAN is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -# CONFIG_PPPOE is not set -# CONFIG_SLIP is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=m -CONFIG_BLK_DEV_IDE=m - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_IDE_SATA is not set -CONFIG_BLK_DEV_IDEDISK=m -# CONFIG_IDEDISK_MULTI_MODE is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=m -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_IDE_GENERIC=m -# CONFIG_IDE_ARM is not set -# CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI device support -# -CONFIG_SCSI=m -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI Transport Attributes -# -# CONFIG_SCSI_SPI_ATTRS is not set -# CONFIG_SCSI_FC_ATTRS is not set - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_DEBUG is not set - -# -# PCMCIA SCSI adapter support -# -# CONFIG_PCMCIA_AHA152X is not set -# CONFIG_PCMCIA_FDOMAIN is not set -# CONFIG_PCMCIA_NINJA_SCSI is not set -# CONFIG_PCMCIA_QLOGIC is not set -# CONFIG_PCMCIA_SYM53C500 is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -CONFIG_INPUT_TSDEV=m -CONFIG_INPUT_TSDEV_SCREEN_X=240 -CONFIG_INPUT_TSDEV_SCREEN_Y=320 -CONFIG_INPUT_TSLIBDEV=m -CONFIG_INPUT_EVDEV=m -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=m -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=m -# CONFIG_SERIO_CT82C710 is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -# CONFIG_KEYBOARD_ATKBD is not set -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -CONFIG_KEYBOARD_NEWTON=m -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -CONFIG_INPUT_TOUCHSCREEN=y -# CONFIG_TOUCHSCREEN_GUNZE is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -# CONFIG_SERIAL_DZ is not set -CONFIG_SERIAL_PXA=y -CONFIG_SERIAL_PXA_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m - -# -# I2C Algorithms -# -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -# CONFIG_I2C_ALGOPXA is not set - -# -# I2C Hardware Bus support -# -# CONFIG_I2C_AMD756 is not set -# CONFIG_I2C_AMD8111 is not set -# CONFIG_I2C_ELV is not set -# CONFIG_I2C_ISA is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_PXA is not set -# CONFIG_SCx200_ACB is not set - -# -# Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ASB100 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_FSCHER is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83627HF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_EEPROM is not set -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set - -# -# L3 serial bus support -# -CONFIG_L3=m - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_SA1100_WATCHDOG is not set - -# -# USB-based Watchdog Cards -# -# CONFIG_USBPCWATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# PCMCIA character devices -# -# CONFIG_SYNCLINK_CS is not set -# CONFIG_RAW_DRIVER is not set - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# - -# -# Video Adapters -# -CONFIG_VIDEO_CPIA=m -# CONFIG_VIDEO_CPIA_USB is not set -# CONFIG_VIDEO_SAA5246A is not set -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_OVCAMCHIP is not set - -# -# Radio Adapters -# -# CONFIG_RADIO_MAESTRO is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_REISERFS_FS_XATTR is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -CONFIG_ROMFS_FS=m -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=m - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -# CONFIG_ZISOFS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_SYSFS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS_XATTR is not set -CONFIG_TMPFS=y -# CONFIG_HUGETLBFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_JFFS2_FS_NAND=y -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set -CONFIG_JFFS2_ZLIB=y -CONFIG_JFFS2_RTIME=y -# CONFIG_JFFS2_RUBIN is not set -CONFIG_CRAMFS=m -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -# CONFIG_NFSD_V4 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=m -CONFIG_SUNRPC=m -# CONFIG_RPCSEC_GSS_KRB5 is not set -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set - -# -# Native Language Support -# -CONFIG_NLS=m -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -# CONFIG_NLS_ASCII is not set -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_UTF8=m - -# -# Profiling support -# -# CONFIG_PROFILING is not set - -# -# Graphics support -# -CONFIG_FB=y -CONFIG_FB_MODES=y -CONFIG_LCD_CLASS_DEVICE=m -CONFIG_LCD_DEVICE=y -CONFIG_BACKLIGHT_CLASS_DEVICE=m -CONFIG_BACKLIGHT_DEVICE=y -# CONFIG_FB_VSFB is not set -CONFIG_FB_MQ1100=m -CONFIG_FB_PXA=m -# CONFIG_FB_PXA_PARAMETERS is not set -# CONFIG_FB_PXA_8BPP is not set -CONFIG_FB_PXA_16BPP=y -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=m -CONFIG_FONTS=y -# CONFIG_FONT_8x8 is not set -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set -CONFIG_FONT_MINI_4x6=y -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set - -# -# Logo configuration -# -# CONFIG_LOGO is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# Misc devices -# - -# -# SoC drivers -# -CONFIG_SOC_MQ11XX=m -# CONFIG_BATTERY_MONITOR is not set - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_DYNAMIC_MINORS is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_EHCI_HCD is not set -CONFIG_USB_OHCI_HCD=m -# CONFIG_USB_UHCI_HCD is not set -# CONFIG_USB_SL811HS is not set -# CONFIG_USB_SL811HS_ALT is not set - -# -# USB Device Class drivers -# - -# -# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem -# -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_STORAGE is not set - -# -# USB Human Interface Devices (HID) -# -# CONFIG_USB_HID is not set - -# -# USB HID Boot Protocol drivers -# -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_EGALAX is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_PWC is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_STV680 is not set - -# -# USB Network adaptors -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_TIGL is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGETSERVO is not set -# CONFIG_USB_TEST is not set - -# -# USB Gadget Support -# -CONFIG_USB_GADGET=y -# CONFIG_USB_GADGET_NET2280 is not set -CONFIG_USB_GADGET_PXA2XX=y -CONFIG_USB_PXA2XX=y -CONFIG_USB_PXA2XX_SMALL=y -# CONFIG_USB_GADGET_GOKU is not set -# CONFIG_USB_GADGET_SA1100 is not set -# CONFIG_USB_GADGET_MQ11XX is not set -# CONFIG_USB_GADGET_DUMMY_HCD is not set -# CONFIG_USB_GADGET_DUALSPEED is not set -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -# CONFIG_USB_ETH_RNDIS is not set -# CONFIG_USB_GADGETFS is not set -CONFIG_USB_FILE_STORAGE=m -# CONFIG_USB_FILE_STORAGE_TEST is not set -# CONFIG_USB_G_SERIAL is not set -# CONFIG_USB_G_CHAR is not set - -# -# Kernel hacking -# -CONFIG_FRAME_POINTER=y -# CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_INFO is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_LL_PXA_JTAG is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -CONFIG_DEBUG_ERRORS=y -# CONFIG_DEBUG_LL is not set - -# -# 1-Wire subsystem -# -# CONFIG_ONEWIRE is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=m -CONFIG_CRYPTO_SHA1=m -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_DES=m -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -# CONFIG_CRYPTO_TEA is not set -CONFIG_CRYPTO_ARC4=m -# CONFIG_CRYPTO_KHAZAD is not set -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_CRC32C=m -# CONFIG_CRYPTO_TEST is not set - -# -# Library routines -# -CONFIG_CRC_CCITT=m -CONFIG_CRC32=m -CONFIG_LIBCRC32C=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/linux/handhelds-pxa-2.6/defconfig-ipaq-pxa-2.6 b/linux/handhelds-pxa-2.6/defconfig-ipaq-pxa-2.6 deleted file mode 100644 index 0a7d4a6694..0000000000 --- a/linux/handhelds-pxa-2.6/defconfig-ipaq-pxa-2.6 +++ /dev/null @@ -1,1304 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_ARM=y -CONFIG_MMU=y -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -# CONFIG_CLEAN_COMPILE is not set -CONFIG_STANDALONE=y -CONFIG_BROKEN=y -CONFIG_BROKEN_ON_SMP=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_HOTPLUG=y -CONFIG_IKCONFIG=y -# CONFIG_MINIMAL_OOPS is not set -CONFIG_IKCONFIG_PROC=y -CONFIG_EMBEDDED=y -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -# CONFIG_IOSCHED_CFQ is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# System Type -# -# CONFIG_ARCH_ADIFCC is not set -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -CONFIG_ARCH_PXA=y -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP3XX is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_LH7A40X is not set -# CONFIG_ARCH_VERSATILE_PB is not set - -# -# Intel PXA250/210 Implementations -# -# CONFIG_ARCH_LUBBOCK is not set -# CONFIG_ARCH_PXA_IDP is not set -# CONFIG_ARCH_H1900 is not set -CONFIG_ARCH_H2200=y -CONFIG_H2200_PCMCIA=m -CONFIG_H2200_LCD=m -# CONFIG_H2200_BATTERY is not set -CONFIG_H2200_TS=m -CONFIG_ARCH_H3900=y -CONFIG_MACH_H4000=y -CONFIG_ARCH_H5400=y -CONFIG_ARCH_AXIMX5=y -# CONFIG_AXIMX5_MISC is not set -# CONFIG_AXIMX5_LCD is not set -# CONFIG_AXIMX5_PCMCIA is not set -# CONFIG_AXIMX5_BUTTONS is not set -# CONFIG_ARCH_AXIMX3 is not set -CONFIG_MACH_E740=y -CONFIG_MACH_E750=y -CONFIG_MACH_E800=y -CONFIG_ARCH_ESERIES=y -# CONFIG_ARCH_ROVERP5P is not set - -# -# S3C2410 Implementations -# - -# -# Linux As Bootloader -# -# CONFIG_LAB is not set - -# -# Processor Type -# -CONFIG_CPU_32=y -CONFIG_CPU_XSCALE=y -CONFIG_CPU_XSCALE_PXA250=y -CONFIG_CPU_32v5=y -CONFIG_CPU_ABRT_EV5T=y -CONFIG_CPU_TLB_V4WBI=y -CONFIG_CPU_MINICACHE=y - -# -# Processor Features -# -# CONFIG_ARM_FASTCALL is not set -CONFIG_ARM_THUMB=y -CONFIG_XSCALE_PMU=y - -# -# Compaq/iPAQ Options -# -CONFIG_PXA_IPAQ=y - -# -# XScale-based iPAQ -# -CONFIG_IPAQ_HANDHELD=y -CONFIG_IPAQ_SLEEVE=m -CONFIG_IPAQ_ASIC2=m -CONFIG_IPAQ_ASIC2_TOUCHSCREEN=m -CONFIG_IPAQ_ASIC3=m -CONFIG_IPAQ_H3900_LCD=m -CONFIG_IPAQ_H4000_LCD=m -CONFIG_IPAQ_SAMCOP=m -CONFIG_IPAQ_SAMCOP_ADC=m -CONFIG_IPAQ_SAMCOP_TOUCHSCREEN=m -CONFIG_IPAQ_SHAMCOP=m -CONFIG_IPAQ_SHAMCOP_ADC=m -CONFIG_IPAQ_SHAMCOP_TOUCHSCREEN=m -CONFIG_IPAQ_SHAMCOP_NAND=m -CONFIG_IPAQ_H5400_LCD=m -CONFIG_IPAQ_H5400_WIFI=m - -# -# General setup -# -# CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -# CONFIG_CPU_FREQ is not set - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -# CONFIG_PCMCIA_DEBUG is not set -# CONFIG_TCIC is not set -CONFIG_PCMCIA_PXA2XX=m - -# -# At least one math emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set -# CONFIG_FPE_FASTFPE is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_AOUT is not set -# CONFIG_BINFMT_MISC is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set -CONFIG_SOC_DEVICE=m -# CONFIG_DOCKING_HOTPLUG is not set -# CONFIG_DEBUG_DRIVER is not set -CONFIG_PM=y -# CONFIG_PREEMPT is not set -# CONFIG_APM is not set -# CONFIG_ARTHUR is not set -CONFIG_CMDLINE="keepinitrd" -CONFIG_ALIGNMENT_TRAP=y - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -CONFIG_MTD_DEBUG=y -CONFIG_MTD_DEBUG_VERBOSE=1 -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_CONCAT=m -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_NOSWAP=y -# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -CONFIG_MTD_CFI_GEOMETRY=y -# CONFIG_MTD_CFI_B1 is not set -CONFIG_MTD_CFI_B2=y -CONFIG_MTD_CFI_B4=y -# CONFIG_MTD_CFI_B8 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -CONFIG_MTD_IPAQ=y -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_EDB7312 is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -CONFIG_MTD_NAND=m -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -# CONFIG_MTD_NAND_H1900 is not set -CONFIG_MTD_NAND_IDS=m - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_BLK_DEV_INITRD=y - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=m -CONFIG_PACKET_MMAP=y -# CONFIG_NETLINK_DEV is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=m -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m - -# -# IP: Virtual Server Configuration -# -# CONFIG_IP_VS is not set -CONFIG_IPV6=m -# CONFIG_IPV6_PRIVACY is not set -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_BRIDGE_NETFILTER=y - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_TFTP is not set -# CONFIG_IP_NF_AMANDA is not set -# CONFIG_IP_NF_QUEUE is not set -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -# CONFIG_IP_NF_MATCH_IPRANGE is not set -CONFIG_IP_NF_MATCH_MAC=m -# CONFIG_IP_NF_MATCH_PKTTYPE is not set -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -# CONFIG_IP_NF_MATCH_RECENT is not set -# CONFIG_IP_NF_MATCH_ECN is not set -# CONFIG_IP_NF_MATCH_DSCP is not set -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -# CONFIG_IP_NF_MATCH_HELPER is not set -CONFIG_IP_NF_MATCH_STATE=m -# CONFIG_IP_NF_MATCH_CONNTRACK is not set -# CONFIG_IP_NF_MATCH_OWNER is not set -# CONFIG_IP_NF_MATCH_PHYSDEV is not set -CONFIG_IP_NF_FILTER=m -# CONFIG_IP_NF_TARGET_REJECT is not set -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_TARGET_NETMAP is not set -# CONFIG_IP_NF_TARGET_SAME is not set -# CONFIG_IP_NF_NAT_LOCAL is not set -# CONFIG_IP_NF_NAT_SNMP_BASIC is not set -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -# CONFIG_IP_NF_TARGET_ECN is not set -# CONFIG_IP_NF_TARGET_DSCP is not set -CONFIG_IP_NF_TARGET_MARK=m -# CONFIG_IP_NF_TARGET_CLASSIFY is not set -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -# CONFIG_IP_NF_ARPTABLES is not set -CONFIG_IP_NF_COMPAT_IPCHAINS=m -# CONFIG_IP_NF_COMPAT_IPFWADM is not set -# CONFIG_IP_NF_RAW is not set - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -# CONFIG_IP6_NF_MATCH_RT is not set -# CONFIG_IP6_NF_MATCH_OPTS is not set -# CONFIG_IP6_NF_MATCH_FRAG is not set -# CONFIG_IP6_NF_MATCH_HL is not set -CONFIG_IP6_NF_MATCH_MULTIPORT=m -# CONFIG_IP6_NF_MATCH_OWNER is not set -CONFIG_IP6_NF_MATCH_MARK=m -# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set -# CONFIG_IP6_NF_MATCH_AHESP is not set -# CONFIG_IP6_NF_MATCH_LENGTH is not set -# CONFIG_IP6_NF_MATCH_EUI64 is not set -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -# CONFIG_IP6_NF_RAW is not set - -# -# Bridge: Netfilter Configuration -# -# CONFIG_BRIDGE_NF_EBTABLES is not set -CONFIG_XFRM=y -CONFIG_XFRM_USER=m - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -CONFIG_BRIDGE=m -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -CONFIG_IRDA=m - -# -# IrDA protocols -# -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y - -# -# IrDA options -# -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -CONFIG_IRDA_DEBUG=y - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -CONFIG_IRTTY_SIR=m - -# -# Dongle support -# -# CONFIG_DONGLE is not set - -# -# Old SIR device drivers -# -CONFIG_IRPORT_SIR=m - -# -# Old Serial dongle support -# -# CONFIG_DONGLE_OLD is not set - -# -# FIR device drivers -# -# CONFIG_USB_IRDA is not set -# CONFIG_SIGMATEL_FIR is not set -# CONFIG_TOSHIBA_FIR is not set -CONFIG_BT=m -# CONFIG_BT_L2CAP is not set -# CONFIG_BT_SCO is not set - -# -# Bluetooth device drivers -# -# CONFIG_BT_HCIUSB is not set -# CONFIG_BT_HCIUART is not set -# CONFIG_BT_HCIBCM203X is not set -# CONFIG_BT_HCIBFUSB is not set -# CONFIG_BT_HCIDTL1 is not set -# CONFIG_BT_HCIBT3C is not set -# CONFIG_BT_HCIBLUECARD is not set -# CONFIG_BT_HCIBTUART is not set -# CONFIG_BT_HCIVHCI is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m - -# -# Ethernet (10 or 100Mbit) -# -# CONFIG_NET_ETHERNET is not set -CONFIG_MII=m -# CONFIG_SMC91X is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y - -# -# Obsolete Wireless cards support (pre-802.11) -# -# CONFIG_STRIP is not set -CONFIG_PCMCIA_WAVELAN=m -CONFIG_PCMCIA_NETWAVE=m - -# -# Wireless 802.11 Frequency Hopping cards support -# -CONFIG_PCMCIA_RAYCS=m - -# -# Wireless 802.11b ISA/PCI cards support -# -CONFIG_HERMES=m -# CONFIG_ATMEL is not set - -# -# Wireless 802.11b Pcmcia/Cardbus cards support -# -CONFIG_PCMCIA_HERMES=m -CONFIG_AIRO_CS=m -# CONFIG_PCMCIA_WL3501 is not set -CONFIG_NET_WIRELESS=y -# CONFIG_HOSTAP is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -CONFIG_PCMCIA_AXNET=m - -# -# Wan interfaces -# -# CONFIG_WAN is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -# CONFIG_PPPOE is not set -# CONFIG_SLIP is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=m -CONFIG_BLK_DEV_IDE=m - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -CONFIG_BLK_DEV_IDEDISK=m -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=m -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_IDE_GENERIC=m -# CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI device support -# -CONFIG_SCSI=m -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_REPORT_LUNS=y -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI Transport Attributes -# -# CONFIG_SCSI_SPI_ATTRS is not set -# CONFIG_SCSI_FC_ATTRS is not set - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_DEBUG is not set - -# -# PCMCIA SCSI adapter support -# -# CONFIG_PCMCIA_AHA152X is not set -# CONFIG_PCMCIA_FDOMAIN is not set -# CONFIG_PCMCIA_NINJA_SCSI is not set -# CONFIG_PCMCIA_QLOGIC is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -CONFIG_INPUT_TSDEV=m -CONFIG_INPUT_TSDEV_SCREEN_X=240 -CONFIG_INPUT_TSDEV_SCREEN_Y=320 -CONFIG_INPUT_TSLIBDEV=m -CONFIG_INPUT_EVDEV=m -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=m -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=m -# CONFIG_SERIO_CT82C710 is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -# CONFIG_KEYBOARD_ATKBD is not set -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -CONFIG_KEYBOARD_NEWTON=m -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -CONFIG_INPUT_TOUCHSCREEN=y -# CONFIG_TOUCHSCREEN_GUNZE is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -# CONFIG_SERIAL_DZ is not set -CONFIG_SERIAL_PXA=y -CONFIG_SERIAL_PXA_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_PXA_JTAG is not set -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m - -# -# I2C Algorithms -# -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -# CONFIG_I2C_ALGOPXA is not set - -# -# I2C Hardware Bus support -# -# CONFIG_I2C_AMD756 is not set -# CONFIG_I2C_AMD8111 is not set -# CONFIG_I2C_ELV is not set -# CONFIG_I2C_ISA is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_PXA is not set -# CONFIG_SCx200_ACB is not set - -# -# Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ASB100 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_FSCHER is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_VIA686A is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83627HF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_EEPROM is not set -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set - -# -# L3 serial bus support -# -CONFIG_L3=m - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set - -# -# USB-based Watchdog Cards -# -# CONFIG_USBPCWATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# PCMCIA character devices -# -# CONFIG_SYNCLINK_CS is not set -# CONFIG_RAW_DRIVER is not set - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# - -# -# Video Adapters -# -CONFIG_VIDEO_CPIA=m -# CONFIG_VIDEO_CPIA_USB is not set -# CONFIG_VIDEO_SAA5246A is not set -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set - -# -# Radio Adapters -# -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_MAESTRO is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -CONFIG_ROMFS_FS=m -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=m - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -# CONFIG_ZISOFS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_SYSFS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS_XATTR is not set -CONFIG_TMPFS=y -# CONFIG_HUGETLBFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=m -CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_JFFS2_FS_NAND=y -CONFIG_CRAMFS=m -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -# CONFIG_NFSD_V4 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=m -CONFIG_SUNRPC=m -# CONFIG_RPCSEC_GSS_KRB5 is not set -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set - -# -# Native Language Support -# -CONFIG_NLS=m -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_UTF8=m - -# -# Profiling support -# -# CONFIG_PROFILING is not set - -# -# Graphics support -# -CONFIG_FB=y -CONFIG_FB_MODES=y -CONFIG_LCD_CLASS_DEVICE=m -CONFIG_LCD_DEVICE=y -CONFIG_BACKLIGHT_CLASS_DEVICE=m -CONFIG_BACKLIGHT_DEVICE=y -# CONFIG_FB_VSFB is not set -CONFIG_FB_MQ1100=m -CONFIG_FB_PXA=m -# CONFIG_FB_PXA_8BPP is not set -CONFIG_FB_PXA_16BPP=y -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=m -CONFIG_PCI_CONSOLE=y -CONFIG_FONTS=y -# CONFIG_FONT_8x8 is not set -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set -CONFIG_FONT_MINI_4x6=y -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set - -# -# Logo configuration -# -# CONFIG_LOGO is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# Misc devices -# - -# -# Multimedia Capabilities Port drivers -# -# CONFIG_MCP is not set - -# -# Console Switches -# -CONFIG_SWITCHES=m - -# -# SoC drivers -# -CONFIG_SOC_MQ11XX=m -# CONFIG_BATTERY_MONITOR is not set - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_DYNAMIC_MINORS is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_EHCI_HCD is not set -CONFIG_USB_OHCI_HCD=m -# CONFIG_USB_UHCI_HCD is not set -# CONFIG_USB_SL811HS is not set -# CONFIG_USB_SL811HS_ALT is not set - -# -# USB Device Class drivers -# - -# -# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem -# -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_STORAGE is not set - -# -# USB Human Interface Devices (HID) -# -# CONFIG_USB_HID is not set - -# -# USB HID Boot Protocol drivers -# -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_PWC is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_STV680 is not set -# CONFIG_USB_W9968CF is not set - -# -# USB Network adaptors -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_TIGL is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_TEST is not set - -# -# USB Gadget Support -# -CONFIG_USB_GADGET=y - -# -# USB Device Controller drivers -# -CONFIG_USB_GADGET_PXA2XX=m -CONFIG_USB_PXA2XX=y -CONFIG_USB_PXA2XX_SMALL=y -CONFIG_USB_GADGET_MQ11XX=m -CONFIG_USB_MQ11XX=y -# CONFIG_USB_GADGET_DUMMY_HCD is not set -# CONFIG_USB_GADGET_DUALSPEED is not set - -# -# USB Gadget Drivers -# -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -# CONFIG_USB_ETH_RNDIS is not set -# CONFIG_USB_GADGETFS is not set -CONFIG_USB_FILE_STORAGE=m -# CONFIG_USB_FILE_STORAGE_TEST is not set -# CONFIG_USB_G_SERIAL is not set -# CONFIG_USB_G_CHAR is not set - -# -# Kernel hacking -# -CONFIG_FRAME_POINTER=y -# CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_INFO is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_LL_PXA_JTAG is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -CONFIG_DEBUG_ERRORS=y -# CONFIG_DEBUG_LL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=m -CONFIG_CRYPTO_SHA1=m -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_DES=m -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_CRC32C=m -# CONFIG_CRYPTO_TEST is not set - -# -# Library routines -# -CONFIG_CRC32=m -CONFIG_LIBCRC32C=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/linux/handhelds-pxa-2.6/defconfig-ipaq-pxa-2.6_2.6.8.1-hh0 b/linux/handhelds-pxa-2.6/defconfig-ipaq-pxa-2.6_2.6.8.1-hh0 deleted file mode 100644 index 8d03220347..0000000000 --- a/linux/handhelds-pxa-2.6/defconfig-ipaq-pxa-2.6_2.6.8.1-hh0 +++ /dev/null @@ -1,1382 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_ARM=y -CONFIG_MMU=y -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -# CONFIG_CLEAN_COMPILE is not set -CONFIG_BROKEN=y -CONFIG_BROKEN_ON_SMP=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_HOTPLUG=y -CONFIG_IKCONFIG=y -# CONFIG_MINIMAL_OOPS is not set -CONFIG_IKCONFIG_PROC=y -CONFIG_EMBEDDED=y -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -# CONFIG_IOSCHED_CFQ is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# System Type -# -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP3XX is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_L7200 is not set -CONFIG_ARCH_PXA=y -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_LH7A40X is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE_PB is not set - -# -# Intel PXA2xx Implementations -# -CONFIG_PXA25x=y -# CONFIG_PXA27x is not set -# CONFIG_ARCH_LUBBOCK is not set -# CONFIG_MACH_MAINSTONE is not set -# CONFIG_ARCH_PXA_IDP is not set -CONFIG_ARCH_ESERIES=y -CONFIG_MACH_E740=y -CONFIG_MACH_E750=y -CONFIG_MACH_E800=y -CONFIG_ESERIES_TMIO=y -CONFIG_OHCI_TMIO=y -CONFIG_MTD_NAND_TMIO=y -CONFIG_ESERIES_UDC=y -# CONFIG_E740_PCMCIA is not set -# CONFIG_E750_PCMCIA is not set -# CONFIG_E800_PCMCIA is not set -CONFIG_MACH_A620=y -CONFIG_A620_LCD=m -CONFIG_A620_BUTTONS=m -CONFIG_ARCH_H1900=y -CONFIG_ARCH_H2200=y -CONFIG_H2200_PCMCIA=m -CONFIG_H2200_LCD=m -# CONFIG_H2200_BATTERY is not set -CONFIG_H2200_TS=m -CONFIG_H2200_AUDIO=m -CONFIG_ARCH_H3900=y -CONFIG_MACH_H4000=y -CONFIG_ARCH_H5400=y -# CONFIG_ARCH_AXIMX5 is not set -# CONFIG_ARCH_AXIMX3 is not set -CONFIG_ARCH_ROVERP1=y -CONFIG_ARCH_ROVERP5P=y -CONFIG_ROVERP5P_LCD=m -CONFIG_ROVERP5P_PCMCIA=m - -# -# Linux As Bootloader -# -# CONFIG_LAB is not set - -# -# Processor Type -# -CONFIG_CPU_32=y -CONFIG_CPU_XSCALE=y -CONFIG_CPU_XSCALE_PXA250=y -CONFIG_CPU_32v5=y -CONFIG_CPU_ABRT_EV5T=y -CONFIG_CPU_TLB_V4WBI=y -CONFIG_CPU_MINICACHE=y - -# -# Processor Features -# -# CONFIG_ARM_FASTCALL is not set -CONFIG_ARM_THUMB=y -CONFIG_XSCALE_PMU=y - -# -# Compaq/iPAQ Options -# -CONFIG_PXA_IPAQ=y - -# -# XScale-based iPAQ -# -CONFIG_IPAQ_HANDHELD=y -# CONFIG_IPAQ_SLEEVE is not set -CONFIG_IPAQ_ASIC2=m -CONFIG_IPAQ_ASIC2_TOUCHSCREEN=m -CONFIG_IPAQ_ASIC3=m -# CONFIG_IPAQ_H1900_LCD is not set -# CONFIG_IPAQ_H3900_LCD is not set -CONFIG_IPAQ_H4000_LCD=m -CONFIG_IPAQ_SAMCOP=m -CONFIG_IPAQ_SAMCOP_ADC=m -CONFIG_IPAQ_SAMCOP_TOUCHSCREEN=m -CONFIG_IPAQ_SHAMCOP=m -CONFIG_IPAQ_SHAMCOP_ADC=m -CONFIG_IPAQ_SHAMCOP_TOUCHSCREEN=m -CONFIG_IPAQ_SHAMCOP_NAND=m -CONFIG_IPAQ_H5400_LCD=m -CONFIG_IPAQ_H5400_WIFI=m - -# -# General setup -# -# CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -# CONFIG_CPU_FREQ is not set - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -# CONFIG_PCMCIA_DEBUG is not set -# CONFIG_TCIC is not set -CONFIG_PCMCIA_PXA2XX=m - -# -# At least one math emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set -# CONFIG_FPE_FASTFPE is not set -# CONFIG_VFP is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_AOUT is not set -# CONFIG_BINFMT_MISC is not set - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set -CONFIG_SOC_DEVICE=m -# CONFIG_DOCKING_HOTPLUG is not set -# CONFIG_DEBUG_DRIVER is not set -CONFIG_PM=y -# CONFIG_PREEMPT is not set -# CONFIG_APM is not set -# CONFIG_ARTHUR is not set -CONFIG_CMDLINE="keepinitrd" -CONFIG_ALIGNMENT_TRAP=y - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -CONFIG_MTD_DEBUG=y -CONFIG_MTD_DEBUG_VERBOSE=1 -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_CONCAT=m -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_NOSWAP=y -# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -CONFIG_MTD_CFI_GEOMETRY=y -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -CONFIG_MTD_IPAQ=y -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_EDB7312 is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -CONFIG_MTD_NAND=m -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -# CONFIG_MTD_NAND_H1900 is not set -CONFIG_MTD_NAND_IDS=m -# CONFIG_MTD_NAND_DISKONCHIP is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_BLK_DEV_INITRD=y - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=m -CONFIG_PACKET_MMAP=y -# CONFIG_NETLINK_DEV is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=m -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m - -# -# IP: Virtual Server Configuration -# -# CONFIG_IP_VS is not set -CONFIG_IPV6=m -# CONFIG_IPV6_PRIVACY is not set -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_BRIDGE_NETFILTER=y - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_TFTP is not set -# CONFIG_IP_NF_AMANDA is not set -# CONFIG_IP_NF_QUEUE is not set -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -# CONFIG_IP_NF_MATCH_IPRANGE is not set -CONFIG_IP_NF_MATCH_MAC=m -# CONFIG_IP_NF_MATCH_PKTTYPE is not set -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -# CONFIG_IP_NF_MATCH_RECENT is not set -# CONFIG_IP_NF_MATCH_ECN is not set -# CONFIG_IP_NF_MATCH_DSCP is not set -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -# CONFIG_IP_NF_MATCH_HELPER is not set -CONFIG_IP_NF_MATCH_STATE=m -# CONFIG_IP_NF_MATCH_CONNTRACK is not set -# CONFIG_IP_NF_MATCH_OWNER is not set -# CONFIG_IP_NF_MATCH_PHYSDEV is not set -CONFIG_IP_NF_FILTER=m -# CONFIG_IP_NF_TARGET_REJECT is not set -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_TARGET_NETMAP is not set -# CONFIG_IP_NF_TARGET_SAME is not set -# CONFIG_IP_NF_NAT_LOCAL is not set -# CONFIG_IP_NF_NAT_SNMP_BASIC is not set -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -# CONFIG_IP_NF_TARGET_ECN is not set -# CONFIG_IP_NF_TARGET_DSCP is not set -CONFIG_IP_NF_TARGET_MARK=m -# CONFIG_IP_NF_TARGET_CLASSIFY is not set -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -# CONFIG_IP_NF_ARPTABLES is not set -CONFIG_IP_NF_COMPAT_IPCHAINS=m -# CONFIG_IP_NF_COMPAT_IPFWADM is not set -# CONFIG_IP_NF_RAW is not set -# CONFIG_IP_NF_MATCH_ADDRTYPE is not set -# CONFIG_IP_NF_MATCH_REALM is not set - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -# CONFIG_IP6_NF_MATCH_RT is not set -# CONFIG_IP6_NF_MATCH_OPTS is not set -# CONFIG_IP6_NF_MATCH_FRAG is not set -# CONFIG_IP6_NF_MATCH_HL is not set -CONFIG_IP6_NF_MATCH_MULTIPORT=m -# CONFIG_IP6_NF_MATCH_OWNER is not set -CONFIG_IP6_NF_MATCH_MARK=m -# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set -# CONFIG_IP6_NF_MATCH_AHESP is not set -# CONFIG_IP6_NF_MATCH_LENGTH is not set -# CONFIG_IP6_NF_MATCH_EUI64 is not set -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -# CONFIG_IP6_NF_RAW is not set - -# -# Bridge: Netfilter Configuration -# -# CONFIG_BRIDGE_NF_EBTABLES is not set -CONFIG_XFRM=y -CONFIG_XFRM_USER=m - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -CONFIG_BRIDGE=m -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -CONFIG_IRDA=m - -# -# IrDA protocols -# -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y - -# -# IrDA options -# -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -CONFIG_IRDA_DEBUG=y - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -CONFIG_IRTTY_SIR=m - -# -# Dongle support -# -# CONFIG_DONGLE is not set - -# -# Old SIR device drivers -# -CONFIG_IRPORT_SIR=m - -# -# Old Serial dongle support -# -# CONFIG_DONGLE_OLD is not set - -# -# FIR device drivers -# -# CONFIG_USB_IRDA is not set -# CONFIG_SIGMATEL_FIR is not set -CONFIG_BT=m -# CONFIG_BT_L2CAP is not set -# CONFIG_BT_SCO is not set - -# -# Bluetooth device drivers -# -# CONFIG_BT_HCIUSB is not set -# CONFIG_BT_HCIUART is not set -# CONFIG_BT_HCIBCM203X is not set -# CONFIG_BT_HCIBFUSB is not set -# CONFIG_BT_HCIDTL1 is not set -# CONFIG_BT_HCIBT3C is not set -# CONFIG_BT_HCIBLUECARD is not set -# CONFIG_BT_HCIBTUART is not set -# CONFIG_BT_HCIVHCI is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m - -# -# Ethernet (10 or 100Mbit) -# -# CONFIG_NET_ETHERNET is not set -CONFIG_MII=m - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y - -# -# Obsolete Wireless cards support (pre-802.11) -# -# CONFIG_STRIP is not set -CONFIG_PCMCIA_WAVELAN=m -CONFIG_PCMCIA_NETWAVE=m - -# -# Wireless 802.11 Frequency Hopping cards support -# -CONFIG_PCMCIA_RAYCS=m - -# -# Wireless 802.11b ISA/PCI cards support -# -CONFIG_HERMES=m -# CONFIG_ATMEL is not set - -# -# Wireless 802.11b Pcmcia/Cardbus cards support -# -CONFIG_PCMCIA_HERMES=m -CONFIG_AIRO_CS=m -# CONFIG_PCMCIA_WL3501 is not set -CONFIG_NET_WIRELESS=y -# CONFIG_HOSTAP is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -CONFIG_PCMCIA_AXNET=m - -# -# Wan interfaces -# -# CONFIG_WAN is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -# CONFIG_PPPOE is not set -# CONFIG_SLIP is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=m -CONFIG_BLK_DEV_IDE=m - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_IDE_SATA is not set -CONFIG_BLK_DEV_IDEDISK=m -# CONFIG_IDEDISK_MULTI_MODE is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=m -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_IDE_GENERIC=m -# CONFIG_IDE_ARM is not set -# CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI device support -# -CONFIG_SCSI=m -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI Transport Attributes -# -# CONFIG_SCSI_SPI_ATTRS is not set -# CONFIG_SCSI_FC_ATTRS is not set - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_DEBUG is not set - -# -# PCMCIA SCSI adapter support -# -# CONFIG_PCMCIA_AHA152X is not set -# CONFIG_PCMCIA_FDOMAIN is not set -# CONFIG_PCMCIA_NINJA_SCSI is not set -# CONFIG_PCMCIA_QLOGIC is not set -# CONFIG_PCMCIA_SYM53C500 is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -CONFIG_INPUT_TSDEV=m -CONFIG_INPUT_TSDEV_SCREEN_X=240 -CONFIG_INPUT_TSDEV_SCREEN_Y=320 -CONFIG_INPUT_TSLIBDEV=m -CONFIG_INPUT_EVDEV=m -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=m -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=m -# CONFIG_SERIO_CT82C710 is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -# CONFIG_KEYBOARD_ATKBD is not set -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -CONFIG_KEYBOARD_NEWTON=m -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -CONFIG_INPUT_TOUCHSCREEN=y -# CONFIG_TOUCHSCREEN_GUNZE is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -# CONFIG_SERIAL_DZ is not set -CONFIG_SERIAL_PXA=y -CONFIG_SERIAL_PXA_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m - -# -# I2C Algorithms -# -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -CONFIG_I2C_ALGOPXA=m - -# -# I2C Hardware Bus support -# -# CONFIG_I2C_AMD756 is not set -# CONFIG_I2C_AMD8111 is not set -# CONFIG_I2C_ELV is not set -# CONFIG_I2C_ISA is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -CONFIG_I2C_PXA=m -# CONFIG_SCx200_ACB is not set - -# -# Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ASB100 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_FSCHER is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83627HF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_EEPROM is not set -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -CONFIG_I2C_DEBUG_CORE=y -CONFIG_I2C_DEBUG_ALGO=y -CONFIG_I2C_DEBUG_BUS=y -CONFIG_I2C_DEBUG_CHIP=y - -# -# L3 serial bus support -# -CONFIG_L3=m - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_SA1100_WATCHDOG is not set - -# -# USB-based Watchdog Cards -# -# CONFIG_USBPCWATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# PCMCIA character devices -# -# CONFIG_SYNCLINK_CS is not set -# CONFIG_RAW_DRIVER is not set - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# - -# -# Video Adapters -# -CONFIG_VIDEO_CPIA=m -# CONFIG_VIDEO_CPIA_USB is not set -# CONFIG_VIDEO_SAA5246A is not set -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_OVCAMCHIP is not set - -# -# Radio Adapters -# -# CONFIG_RADIO_MAESTRO is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_REISERFS_FS_XATTR is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -CONFIG_ROMFS_FS=m -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=m - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -# CONFIG_ZISOFS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_SYSFS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS_XATTR is not set -CONFIG_TMPFS=y -# CONFIG_HUGETLBFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=m -CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_JFFS2_FS_NAND=y -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set -CONFIG_JFFS2_ZLIB=y -CONFIG_JFFS2_RTIME=y -# CONFIG_JFFS2_RUBIN is not set -CONFIG_CRAMFS=m -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -# CONFIG_NFSD_V4 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=m -CONFIG_SUNRPC=m -# CONFIG_RPCSEC_GSS_KRB5 is not set -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_EFI_PARTITION is not set - -# -# Native Language Support -# -CONFIG_NLS=m -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -# CONFIG_NLS_ASCII is not set -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_UTF8=m - -# -# Profiling support -# -# CONFIG_PROFILING is not set - -# -# Graphics support -# -CONFIG_FB=y -CONFIG_FB_MODES=y -CONFIG_LCD_CLASS_DEVICE=m -CONFIG_LCD_DEVICE=y -CONFIG_BACKLIGHT_CLASS_DEVICE=m -CONFIG_BACKLIGHT_DEVICE=y -# CONFIG_FB_VSFB is not set -CONFIG_FB_MQ1100=m -CONFIG_FB_PXA=m -# CONFIG_FB_PXA_PARAMETERS is not set -# CONFIG_FB_PXA_8BPP is not set -CONFIG_FB_PXA_16BPP=y -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=m -CONFIG_FONTS=y -# CONFIG_FONT_8x8 is not set -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set -CONFIG_FONT_MINI_4x6=y -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set - -# -# Logo configuration -# -# CONFIG_LOGO is not set - -# -# Sound -# -CONFIG_SOUND=m - -# -# Advanced Linux Sound Architecture -# -CONFIG_SND=m -CONFIG_SND_TIMER=m -CONFIG_SND_PCM=m -# CONFIG_SND_SEQUENCER is not set -CONFIG_SND_OSSEMUL=y -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -CONFIG_SND_VERBOSE_PRINTK=y -CONFIG_SND_DEBUG=y -CONFIG_SND_DEBUG_MEMORY=y -CONFIG_SND_DEBUG_DETECT=y - -# -# Generic devices -# -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_MTPAV is not set -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set - -# -# ALSA ARM devices -# -CONFIG_SND_PXA2XX_UDA1380=m -# CONFIG_SND_H5XXX_AK4535 is not set -# CONFIG_SND_PXA_AC97 is not set - -# -# ALSA USB devices -# -# CONFIG_SND_USB_AUDIO is not set - -# -# PCMCIA devices -# - -# -# Open Sound System -# -# CONFIG_SOUND_PRIME is not set -# CONFIG_SOUND_UDA1341 is not set - -# -# Misc devices -# - -# -# SoC drivers -# -CONFIG_SOC_MQ11XX=m -# CONFIG_BATTERY_MONITOR is not set - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_DYNAMIC_MINORS is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_EHCI_HCD is not set -CONFIG_USB_OHCI_HCD=m -# CONFIG_USB_UHCI_HCD is not set -# CONFIG_USB_SL811HS is not set -# CONFIG_USB_SL811HS_ALT is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set - -# -# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem -# -# CONFIG_USB_MIDI is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_STORAGE is not set - -# -# USB Human Interface Devices (HID) -# -# CONFIG_USB_HID is not set - -# -# USB HID Boot Protocol drivers -# -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_EGALAX is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_PWC is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_STV680 is not set - -# -# USB Network adaptors -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_TIGL is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGETSERVO is not set -# CONFIG_USB_TEST is not set - -# -# USB Gadget Support -# -CONFIG_USB_GADGET=m -# CONFIG_USB_GADGET_NET2280 is not set -CONFIG_USB_GADGET_PXA2XX=y -CONFIG_USB_PXA2XX=m -# CONFIG_USB_PXA2XX_SMALL is not set -# CONFIG_USB_GADGET_GOKU is not set -# CONFIG_USB_GADGET_SA1100 is not set -# CONFIG_USB_GADGET_MQ11XX is not set -# CONFIG_USB_GADGET_DUMMY_HCD is not set -# CONFIG_USB_GADGET_DUALSPEED is not set -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -# CONFIG_USB_ETH_RNDIS is not set -# CONFIG_USB_GADGETFS is not set -CONFIG_USB_FILE_STORAGE=m -# CONFIG_USB_FILE_STORAGE_TEST is not set -# CONFIG_USB_G_SERIAL is not set -# CONFIG_USB_G_CHAR is not set - -# -# Kernel hacking -# -CONFIG_FRAME_POINTER=y -# CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_INFO is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_LL_PXA_JTAG is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -CONFIG_DEBUG_ERRORS=y -# CONFIG_DEBUG_LL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=m -CONFIG_CRYPTO_SHA1=m -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_DES=m -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -# CONFIG_CRYPTO_TEA is not set -CONFIG_CRYPTO_ARC4=m -# CONFIG_CRYPTO_KHAZAD is not set -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_CRC32C=m -# CONFIG_CRYPTO_TEST is not set - -# -# Library routines -# -CONFIG_CRC_CCITT=m -CONFIG_CRC32=m -CONFIG_LIBCRC32C=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/linux/handhelds-pxa-2.6_2.6.6-hh0.bb b/linux/handhelds-pxa-2.6_2.6.6-hh0.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/handhelds-pxa-2.6_2.6.8.1-hh0.bb b/linux/handhelds-pxa-2.6_2.6.8.1-hh0.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/handhelds-pxa-2.6_cvs.bb b/linux/handhelds-pxa-2.6_cvs.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh36.12.bb b/linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh36.12.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh36.13.bb b/linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh36.13.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh36.14.bb b/linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh36.14.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh37.1.bb b/linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh37.1.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh37.4.bb b/linux/handhelds-pxa_2.4.19-rmk6-pxa1-hh37.4.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/defconfig-ipaqsa b/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/defconfig-ipaqsa deleted file mode 100644 index f144aa6c17..0000000000 --- a/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/defconfig-ipaqsa +++ /dev/null @@ -1,1505 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_GENERIC_BUST_SPINLOCK is not set -# CONFIG_GENERIC_ISA_DMA is not set - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# System Type -# -# CONFIG_ARCH_ANAKIN is not set -# CONFIG_ARCH_ARCA5K is not set -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_OMAHA is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_MX1ADS is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_RISCSTATION is not set -CONFIG_ARCH_SA1100=y -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_AT91RM9200DK is not set -# CONFIG_MINIMAL_OOPS is not set - -# -# Linux As Bootldr support -# -# CONFIG_LAB is not set -# CONFIG_BIG_KERNEL is not set -# CONFIG_USE_DATE_CODE is not set - -# -# Archimedes/A5000 Implementations -# - -# -# Archimedes/A5000 Implementations (select only ONE) -# -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set - -# -# Footbridge Implementations -# -# CONFIG_ARCH_CATS is not set -# CONFIG_ARCH_PERSONAL_SERVER is not set -# CONFIG_ARCH_EBSA285_ADDIN is not set -# CONFIG_ARCH_EBSA285_HOST is not set -# CONFIG_ARCH_NETWINDER is not set - -# -# SA11x0 Implementations -# -# CONFIG_SA1100_ACCELENT is not set -# CONFIG_SA1100_ASSABET is not set -# CONFIG_ASSABET_NEPONSET is not set -# CONFIG_SA1100_ADSBITSY is not set -# CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_CEP is not set -# CONFIG_SA1100_CERF is not set -CONFIG_SA1100_H3100=y -CONFIG_SA1100_H3600=y -CONFIG_SA1100_H3800=y -# CONFIG_SA1100_CONSUS is not set -# CONFIG_SA1100_EXTENEX1 is not set -# CONFIG_SA1100_FLEXANET is not set -# CONFIG_SA1100_FREEBIRD is not set -# CONFIG_SA1100_FRODO is not set -# CONFIG_SA1100_GRAPHICSCLIENT is not set -# CONFIG_SA1100_GRAPHICSMASTER is not set -# CONFIG_SA1100_HACKKIT is not set -# CONFIG_SA1100_BADGE4 is not set -# CONFIG_SA1100_JORNADA720 is not set -# CONFIG_SA1100_JORNADA56X is not set -# CONFIG_SA1100_HUW_WEBPANEL is not set -# CONFIG_SA1100_ITSY is not set -# CONFIG_SA1100_LART is not set -# CONFIG_SA1100_NANOENGINE is not set -# CONFIG_SA1100_OMNIMETER is not set -# CONFIG_SA1100_PANGOLIN is not set -# CONFIG_SA1100_PLEB is not set -# CONFIG_SA1100_PT_SYSTEM3 is not set -# CONFIG_SA1100_SHANNON is not set -# CONFIG_SA1100_SHERMAN is not set -# CONFIG_SA1100_SIMPAD is not set -# CONFIG_SA1100_SIMPUTER is not set -# CONFIG_SA1100_PFS168 is not set -# CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_XP860 is not set -# CONFIG_SA1100_YOPY is not set -CONFIG_SA1100_USB=m -CONFIG_SA1100_USB_NETLINK=m -CONFIG_SA1100_USB_CHAR=m -CONFIG_REGISTERS=m - -# -# Intel PXA250/210 Implementations -# -# CONFIG_ARCH_LUBBOCK is not set -# CONFIG_ARCH_PXA_IDP is not set -# CONFIG_ARCH_PXA_CERF is not set -# CONFIG_ARCH_H3900 is not set -# CONFIG_ARCH_H1900 is not set -# CONFIG_ARCH_H5400 is not set -# CONFIG_ARCH_H2200 is not set -# CONFIG_ARCH_AXIM is not set -# CONFIG_PXA_USB is not set -# CONFIG_PXA_USB_NETLINK is not set -# CONFIG_PXA_USB_CHAR is not set - -# -# CLPS711X/EP721X Implementations -# -# CONFIG_ARCH_AUTCPU12 is not set -# CONFIG_ARCH_CDB89712 is not set -# CONFIG_ARCH_CLEP7312 is not set -# CONFIG_ARCH_EDB7211 is not set -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_FORTUNET is not set -# CONFIG_ARCH_EP7211 is not set -# CONFIG_ARCH_EP7212 is not set -# CONFIG_ARCH_ACORN is not set -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set - -# -# Processor Type -# -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -# CONFIG_CPU_ARM610 is not set -# CONFIG_CPU_ARM710 is not set -# CONFIG_CPU_ARM720T is not set -# CONFIG_CPU_ARM920T is not set -# CONFIG_CPU_ARM922T is not set -# CONFIG_PLD is not set -# CONFIG_CPU_ARM926T is not set -# CONFIG_CPU_ARM1020 is not set -# CONFIG_CPU_ARM1026 is not set -# CONFIG_CPU_SA110 is not set -CONFIG_CPU_SA1100=y -# CONFIG_CPU_32v3 is not set -CONFIG_CPU_32v4=y -CONFIG_SA1100_IPAQ=y -# CONFIG_PXA_IPAQ is not set -CONFIG_IPAQ_HANDHELD=y - -# -# Compaq iPAQ Handheld -# -CONFIG_IPAQ_HAL=m -CONFIG_H3600_MICRO=m -CONFIG_IPAQ_HAS_ROSELLA=y -CONFIG_H3600_ASIC=m -CONFIG_H3900_ASIC_DEBUG=y -# CONFIG_H5400_ASIC is not set -# CONFIG_H1900_ASIC is not set -# CONFIG_H1900_TS is not set -CONFIG_H3600_HARDWARE=y -CONFIG_IPAQ_SLEEVE=m -CONFIG_SLEEVE_DEBUG=y -CONFIG_SLEEVE_DEBUG_VERBOSE=0 -# CONFIG_SLEEVE_IRQ_DEMUX is not set - -# -# Processor Features -# -CONFIG_DISCONTIGMEM=y - -# -# General setup -# -# CONFIG_PCI is not set -CONFIG_ISA=y -# CONFIG_ISA_DMA is not set -# CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_CPU_FREQ=y -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -# CONFIG_I82092 is not set -# CONFIG_I82365 is not set -# CONFIG_TCIC is not set -# CONFIG_PCMCIA_CLPS6700 is not set -CONFIG_PCMCIA_SA1100=m -# CONFIG_PCMCIA_PXA is not set -CONFIG_MERCURY_BACKPAQ=m - -# -# MMC/SD Card support -# -CONFIG_MMC=m -CONFIG_MMC_DEBUG=y -CONFIG_MMC_DEBUG_VERBOSE=0 -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y - -# -# At least one math emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_FASTFPE is not set -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_PM=y -CONFIG_APM=m -CONFIG_HWTIMER=m -# CONFIG_ARTHUR is not set -CONFIG_CMDLINE="keepinitrd" -# CONFIG_LEDS is not set -CONFIG_ALIGNMENT_TRAP=y - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -CONFIG_MTD_DEBUG=y -CONFIG_MTD_DEBUG_VERBOSE=1 -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_NOSWAP=y -# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -CONFIG_MTD_CFI_GEOMETRY=y -# CONFIG_MTD_CFI_B1 is not set -CONFIG_MTD_CFI_B2=y -CONFIG_MTD_CFI_B4=y -# CONFIG_MTD_CFI_B8 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set -# CONFIG_MTD_JEDEC is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -CONFIG_MTD_IPAQ=y -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_CDB89712 is not set -# CONFIG_MTD_SA1100 is not set -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_IQ80310 is not set -# CONFIG_MTD_LUBBOCK is not set -# CONFIG_MTD_EPXA10DB is not set -# CONFIG_MTD_FORTUNET is not set -# CONFIG_MTD_AUTCPU12 is not set -# CONFIG_MTD_EDB7312 is not set -# CONFIG_MTD_H720X is not set -# CONFIG_MTD_IMPA7 is not set -# CONFIG_MTD_CEIVA is not set -# CONFIG_MTD_PCI is not set -# CONFIG_MTD_PCMCIA is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -CONFIG_MTD_MTDRAM=m -CONFIG_MTDRAM_TOTAL_SIZE=4096 -CONFIG_MTDRAM_ERASE_SIZE=128 -CONFIG_MTD_BLKMTD=m - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -# CONFIG_MTD_DOCPROBE is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -CONFIG_NVRD=m - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -CONFIG_BLK_DEV_LVM=m -CONFIG_BLK_DEV_DM=m - -# -# Networking options -# -CONFIG_PACKET=m -CONFIG_PACKET_MMAP=y -# CONFIG_NETLINK_DEV is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -# CONFIG_IP_NF_AMANDA is not set -# CONFIG_IP_NF_TFTP is not set -CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_QUEUE is not set -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -# CONFIG_IP_NF_MATCH_PKTTYPE is not set -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -# CONFIG_IP_NF_MATCH_RECENT is not set -# CONFIG_IP_NF_MATCH_ECN is not set -# CONFIG_IP_NF_MATCH_DSCP is not set -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -# CONFIG_IP_NF_MATCH_HELPER is not set -CONFIG_IP_NF_MATCH_STATE=m -# CONFIG_IP_NF_MATCH_CONNTRACK is not set -# CONFIG_IP_NF_MATCH_UNCLEAN is not set -# CONFIG_IP_NF_MATCH_OWNER is not set -CONFIG_IP_NF_FILTER=m -# CONFIG_IP_NF_TARGET_REJECT is not set -# CONFIG_IP_NF_TARGET_MIRROR is not set -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_NAT_LOCAL is not set -# CONFIG_IP_NF_NAT_SNMP_BASIC is not set -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -# CONFIG_IP_NF_TARGET_ECN is not set -# CONFIG_IP_NF_TARGET_DSCP is not set -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -# CONFIG_IP_NF_ARPTABLES is not set -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -# CONFIG_IP_NF_COMPAT_IPFWADM is not set -CONFIG_IPV6=m -CONFIG_IPV6_SUBTREES=y -CONFIG_IPV6_IPV6_TUNNEL=m -CONFIG_IPV6_MOBILITY=m -CONFIG_IPV6_MOBILITY_MN=m -# CONFIG_IPV6_MOBILITY_HA is not set -CONFIG_IPV6_MOBILITY_DEBUG=y - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -# CONFIG_IP6_NF_MATCH_RT is not set -# CONFIG_IP6_NF_MATCH_OPTS is not set -# CONFIG_IP6_NF_MATCH_FRAG is not set -# CONFIG_IP6_NF_MATCH_HL is not set -CONFIG_IP6_NF_MATCH_MULTIPORT=m -# CONFIG_IP6_NF_MATCH_OWNER is not set -CONFIG_IP6_NF_MATCH_MARK=m -# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set -# CONFIG_IP6_NF_MATCH_AHESP is not set -# CONFIG_IP6_NF_MATCH_LENGTH is not set -# CONFIG_IP6_NF_MATCH_EUI64 is not set -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_IPSEC=m - -# -# IPSec options (FreeS/WAN) -# -CONFIG_IPSEC_IPIP=y -CONFIG_IPSEC_AH=y -CONFIG_IPSEC_AUTH_HMAC_MD5=y -CONFIG_IPSEC_AUTH_HMAC_SHA1=y -CONFIG_IPSEC_ESP=y -CONFIG_IPSEC_ENC_3DES=y -CONFIG_IPSEC_IPCOMP=y -CONFIG_IPSEC_DEBUG=y - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -# CONFIG_NET_ETHERNET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -# CONFIG_PPP_MPPE is not set -# CONFIG_PPPOE is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -# CONFIG_STRIP is not set -# CONFIG_WAVELAN is not set -# CONFIG_ARLAN is not set -# CONFIG_AIRONET4500 is not set -# CONFIG_AIRONET4500_NONCS is not set -# CONFIG_AIRONET4500_PROC is not set -# CONFIG_HERMES is not set -# CONFIG_SPECTRUM24T is not set - -# -# Wireless Pcmcia cards support -# -# CONFIG_PCMCIA_HERMES is not set -# CONFIG_AIRO_CS is not set -# CONFIG_WVLAN_CS is not set -# CONFIG_MWVLAN_CS is not set -# CONFIG_HOSTAP is not set -# CONFIG_HOSTAP_CS is not set -CONFIG_NET_WIRELESS=y -CONFIG_ATMELWLAN=y -# CONFIG_ATMELWLAN_USB_503A_RFMD is not set -CONFIG_ATMELWLAN_PCMCIA_502A=m -CONFIG_ATMELWLAN_PCMCIA_3COM=m -CONFIG_ATMELWLAN_PCMCIA_502AD=m -CONFIG_ATMELWLAN_PCMCIA_502AE=m -CONFIG_ATMELWLAN_PCMCIA_504=m - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_AXNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -# CONFIG_ARCNET_COM20020_CS is not set -# CONFIG_PCMCIA_IBMTR is not set -CONFIG_NET_PCMCIA_RADIO=y -CONFIG_PCMCIA_RAYCS=m -CONFIG_PCMCIA_NETWAVE=m -CONFIG_PCMCIA_WAVELAN=m -# CONFIG_AIRONET4500_CS is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -CONFIG_IRDA=m - -# -# IrDA protocols -# -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y - -# -# IrDA options -# -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -CONFIG_IRDA_DEBUG=y - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m - -# -# Dongle support -# -# CONFIG_DONGLE is not set - -# -# FIR device drivers -# -# CONFIG_USB_IRDA is not set -# CONFIG_NSC_FIR is not set -# CONFIG_WINBOND_FIR is not set -# CONFIG_TOSHIBA_FIR is not set -# CONFIG_SMC_IRCC_FIR is not set -# CONFIG_ALI_FIR is not set -# CONFIG_VLSI_FIR is not set -CONFIG_SA1100_FIR=m - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=m - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=m - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=m -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set -# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set -# CONFIG_BLK_DEV_IDEDISK_IBM is not set -# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set -# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set -# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set -# CONFIG_BLK_DEV_IDEDISK_WD is not set -# CONFIG_BLK_DEV_COMMERIAL is not set -# CONFIG_BLK_DEV_TIVO is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=m -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_IDE_CHIPSETS is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_DMA_NONPCI is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set - -# -# SCSI support -# -CONFIG_SCSI=m - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=m -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_DEBUG is not set - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_PCMCIA=y -# CONFIG_PCMCIA_AHA152X is not set -# CONFIG_PCMCIA_FDOMAIN is not set -# CONFIG_PCMCIA_NINJA_SCSI is not set -# CONFIG_PCMCIA_QLOGIC is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m -CONFIG_INPUT_UINPUT=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=m -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_ANAKIN is not set -# CONFIG_SERIAL_ANAKIN_CONSOLE is not set -# CONFIG_SERIAL_S3C2410 is not set -# CONFIG_SERIAL_S3C2410_CONSOLE is not set -# CONFIG_SERIAL_AMBA is not set -# CONFIG_SERIAL_AMBA_CONSOLE is not set -# CONFIG_SERIAL_CLPS711X is not set -# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE is not set -# CONFIG_SERIAL_UART00 is not set -# CONFIG_SERIAL_UART00_CONSOLE is not set -CONFIG_SERIAL_SA1100=y -CONFIG_SERIAL_SA1100_CONSOLE=y -CONFIG_SA1100_DEFAULT_BAUDRATE=115200 -CONFIG_SERIAL_H3800_ASIC=m -# CONFIG_SERIAL_SIR_PXA is not set -# CONFIG_SERIAL_8250 is not set -# CONFIG_SERIAL_8250_CONSOLE is not set -# CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SERIAL_8250_MANY_PORTS is not set -# CONFIG_SERIAL_8250_SHARE_IRQ is not set -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_HUB6 is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 -CONFIG_NEWTONKBD=m -CONFIG_SA1100_PROFILER=m - -# -# Compaq iPAQ H3600 support -# -CONFIG_TOUCHSCREEN_H3600=m -CONFIG_H3600_BACKPAQ_FPGA=m -CONFIG_H3600_BACKPAQ_ACCEL=m -CONFIG_H3600_BACKPAQ_GASGAUGE=m -CONFIG_H3600_BACKPAQ_SRAM=m -CONFIG_H3600_BACKPAQ_AUDIO=m -CONFIG_H3600_STOWAWAY=m -CONFIG_H3800_MICROKBD=m -CONFIG_SA1100_LIRC=m -# CONFIG_H5400_BUZZER is not set -# CONFIG_H5400_FSI is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# L3 serial bus support -# -CONFIG_L3=y -CONFIG_L3_ALGOBIT=y -CONFIG_L3_BIT_SA1100_GPIO=y - -# -# Other L3 adapters -# -# CONFIG_L3_S3C2410 is not set -# CONFIG_L3_SA1111 is not set -CONFIG_L3_BACKPAQ=m -CONFIG_BIT_SA1100_GPIO=y - -# -# SPI support -# -# CONFIG_SPI is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=m -# CONFIG_PSMOUSE is not set -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set -# CONFIG_MK712_MOUSE is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_INPUT_NS558 is not set -# CONFIG_INPUT_LIGHTNING is not set -# CONFIG_INPUT_PCIGAME is not set -# CONFIG_INPUT_CS461X is not set -# CONFIG_INPUT_EMU10K1 is not set -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m - -# -# Joysticks -# -# CONFIG_INPUT_ANALOG is not set -# CONFIG_INPUT_A3D is not set -# CONFIG_INPUT_ADI is not set -# CONFIG_INPUT_COBRA is not set -# CONFIG_INPUT_GF2K is not set -# CONFIG_INPUT_GRIP is not set -# CONFIG_INPUT_INTERACT is not set -# CONFIG_INPUT_TMDC is not set -# CONFIG_INPUT_SIDEWINDER is not set -# CONFIG_INPUT_IFORCE_USB is not set -# CONFIG_INPUT_IFORCE_232 is not set -# CONFIG_INPUT_WARRIOR is not set -# CONFIG_INPUT_MAGELLAN is not set -# CONFIG_INPUT_SPACEORB is not set -# CONFIG_INPUT_SPACEBALL is not set -# CONFIG_INPUT_STINGER is not set -# CONFIG_INPUT_DB9 is not set -# CONFIG_INPUT_GAMECON is not set -# CONFIG_INPUT_TURBOGRAFX is not set -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -# CONFIG_ALIM7101_WDT is not set -# CONFIG_SC520_WDT is not set -# CONFIG_PCWATCHDOG is not set -# CONFIG_21285_WATCHDOG is not set -# CONFIG_977_WATCHDOG is not set -CONFIG_SA1100_WATCHDOG=m -# CONFIG_PXA_WATCHDOG is not set -# CONFIG_OMAHA_WATCHDOG is not set -# CONFIG_EUROTECH_WDT is not set -# CONFIG_IB700_WDT is not set -# CONFIG_WAFER_WDT is not set -# CONFIG_I810_TCO is not set -# CONFIG_MIXCOMWD is not set -# CONFIG_60XX_WDT is not set -# CONFIG_SC1200_WDT is not set -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_W83877F_WDT is not set -# CONFIG_WDT is not set -# CONFIG_WDTPCI is not set -# CONFIG_MACHZ_WDT is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -CONFIG_SA1100_RTC=m -# CONFIG_PXA_RTC_HACK is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# PCMCIA character devices -# -CONFIG_PCMCIA_SERIAL_CS=m -# CONFIG_PCMCIA_MOBILISCAN_CS is not set -# CONFIG_AXIM_KEY_FIX is not set - -# -# Multimedia devices -# -CONFIG_MEDIA=m -CONFIG_VIDEO_DEV=m -CONFIG_V4L2_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -# CONFIG_I2C_PARPORT is not set - -# -# Video Adapters -# -# CONFIG_VIDEO_PMS is not set -# CONFIG_VIDEO_CPIA is not set -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_ZORAN_BUZ is not set -# CONFIG_VIDEO_ZORAN_DC10 is not set -# CONFIG_VIDEO_ZORAN_LML33 is not set -# CONFIG_VIDEO_ZR36120 is not set -# CONFIG_VIDEO_MEYE is not set -# CONFIG_VIDEO_CYBERPRO is not set -CONFIG_VIDEO_H3600_BACKPAQ=m -# CONFIG_VIDEO_HAWKEYE is not set - -# -# Video for Linux 2 (V4L2) -# -CONFIG_VIDEO_WINNOV_CS=m - -# -# Radio Adapters -# -# CONFIG_RADIO_CADET is not set -# CONFIG_RADIO_RTRACK is not set -# CONFIG_RADIO_RTRACK2 is not set -# CONFIG_RADIO_AZTECH is not set -# CONFIG_RADIO_GEMTEK is not set -# CONFIG_RADIO_GEMTEK_PCI is not set -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_MAESTRO is not set -# CONFIG_RADIO_MIROPCM20 is not set -# CONFIG_RADIO_MIROPCM20_RDS is not set -# CONFIG_RADIO_SF16FMI is not set -# CONFIG_RADIO_TERRATEC is not set -# CONFIG_RADIO_TRUST is not set -# CONFIG_RADIO_TYPHOON is not set -# CONFIG_RADIO_ZOLTRIX is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -CONFIG_CRAMFS=y -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=m -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DRIVERFS_FS is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=m -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_UTF8=m - -# -# Console drivers -# -CONFIG_PC_KEYMAP=y -# CONFIG_VGA_CONSOLE is not set - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_ACORN is not set -# CONFIG_FB_ANAKIN is not set -# CONFIG_FB_CLPS711X is not set -# CONFIG_FB_S3C2410 is not set -CONFIG_FB_SA1100=y -# CONFIG_FB_EPSON1356 is not set -# CONFIG_FB_MQ200 is not set -# CONFIG_FB_PXA is not set -# CONFIG_FB_MQ1100 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_VIRTUAL is not set -CONFIG_FBCON_ADVANCED=y -# CONFIG_FBCON_MFB is not set -# CONFIG_FBCON_CFB2 is not set -CONFIG_FBCON_CFB4=y -# CONFIG_FBCON_CFB8 is not set -CONFIG_FBCON_CFB16=y -# CONFIG_FBCON_CFB24 is not set -# CONFIG_FBCON_CFB32 is not set -# CONFIG_FBCON_AFB is not set -# CONFIG_FBCON_ILBM is not set -# CONFIG_FBCON_IPLAN2P2 is not set -# CONFIG_FBCON_IPLAN2P4 is not set -# CONFIG_FBCON_IPLAN2P8 is not set -# CONFIG_FBCON_MAC is not set -# CONFIG_FBCON_VGA_PLANES is not set -# CONFIG_FBCON_VGA is not set -# CONFIG_FBCON_HGA is not set -# CONFIG_FBCON_NO_LOGO is not set -CONFIG_FBCON_FONTWIDTH8_ONLY=y -CONFIG_FBCON_FONTS=y -CONFIG_FONT_8x8=y -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set - -# -# Sound -# -CONFIG_SOUND=y -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_MIDI_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_MAESTRO3 is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_RME96XX is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -# CONFIG_MIDI_VIA82CXXX is not set -CONFIG_SOUND_SA1100=m -CONFIG_SOUND_UDA1341=m -# CONFIG_SOUND_SA1100_MONO is not set -# CONFIG_SOUND_ASSABET_UDA1341 is not set -CONFIG_SOUND_H3600_UDA1341=m -# CONFIG_SOUND_PANGOLIN_UDA1341 is not set -# CONFIG_SOUND_SA1111_UDA1341 is not set -# CONFIG_SOUND_SA1100SSP is not set -# CONFIG_SOUND_OSS is not set -# CONFIG_SOUND_VIDC is not set -# CONFIG_SOUND_WAVEARTIST is not set -# CONFIG_SOUND_PXA_AC97 is not set -# CONFIG_SOUND_TVMIXER is not set - -# -# Multimedia Capabilities Port drivers -# -# CONFIG_MCP is not set -# CONFIG_MCP_SA1100 is not set -# CONFIG_MCP_UCB1200 is not set -# CONFIG_MCP_UCB1200_AUDIO is not set -# CONFIG_MCP_UCB1200_TS is not set -# CONFIG_MCP_UCB1400_TS is not set - -# -# Console Switches -# -# CONFIG_SWITCHES is not set - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -# CONFIG_USB_DEVICEFS is not set -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_LONG_TIMEOUT is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set -# CONFIG_USB_OHCI_SA1111 is not set -# CONFIG_USB_OHCI_H5400 is not set -# CONFIG_USB_OHCI_S3C2410 is not set -CONFIG_USB_SL811HS=m - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_BLUETOOTH is not set -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_ACM is not set -CONFIG_USB_PRINTER=m - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_WACOM is not set - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# -CONFIG_USB_IBMCAM=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -# CONFIG_USB_DSBR is not set -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -CONFIG_USB_CDCETHER=m -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_IPAQ is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_KLSI is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_XIRCOM is not set -# CONFIG_USB_SERIAL_OMNINET is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_BRLVGER is not set - -# -# Linux As Bootldr Modules -# -# CONFIG_BIG_KERNEL is not set -# CONFIG_USE_DATE_CODE is not set -# CONFIG_YMODEM is not set -# CONFIG_LAB_DUMMY is not set -# CONFIG_LAB_CRC is not set -# CONFIG_LAB_YMODEM is not set -# CONFIG_LAB_MTD is not set -# CONFIG_LAB_COPY is not set -# CONFIG_LAB_COPY_YMODEM is not set -# CONFIG_LAB_COPY_FLASH is not set -# CONFIG_LAB_COPY_FS is not set -# CONFIG_LAB_COPY_WRAPPER is not set - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -# CONFIG_BLUEZ_HCIUSB is not set -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -# CONFIG_BLUEZ_HCIUART_BCSP_TXCRC is not set -# CONFIG_BLUEZ_HCIBFUSB is not set -CONFIG_BLUEZ_HCIDTL1=m -CONFIG_BLUEZ_HCIBT3C=m -CONFIG_BLUEZ_HCIBLUECARD=m -CONFIG_BLUEZ_HCIBTUART=m -# CONFIG_BLUEZ_HCIVHCI is not set - -# -# Kernel hacking -# -CONFIG_FRAME_POINTER=y -# CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_INFO is not set -# CONFIG_NO_PGT_CACHE is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -CONFIG_DEBUG_ERRORS=y -# CONFIG_DEBUG_LL is not set -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/disable-pcmcia-probe.patch b/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/disable-pcmcia-probe.patch deleted file mode 100644 index 79ba036323..0000000000 --- a/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/disable-pcmcia-probe.patch +++ /dev/null @@ -1,17 +0,0 @@ - -# -# Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher -# - ---- linux/drivers/pcmcia/Config.in~disable-pcmcia-probe 2003-05-13 11:18:23.000000000 +0200 -+++ linux/drivers/pcmcia/Config.in 2004-05-27 13:59:50.000000000 +0200 -@@ -15,9 +15,6 @@ - tristate 'PCMCIA/CardBus support' CONFIG_PCMCIA - if [ "$CONFIG_PCMCIA" != "n" ]; then - # yes, I really mean the following... -- if [ "$CONFIG_ISA" = "y" -o "$CONFIG_ARCH_SA1100" = "y" ]; then -- define_bool CONFIG_PCMCIA_PROBE y -- fi - if [ "$CONFIG_PCI" != "n" ]; then - bool ' CardBus support' CONFIG_CARDBUS - fi diff --git a/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/ipsec.patch b/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/ipsec.patch deleted file mode 100644 index 4e2efc035b..0000000000 --- a/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/ipsec.patch +++ /dev/null @@ -1,1446 +0,0 @@ ---- linux/net/Makefile 3 Dec 2003 19:15:16 -0000 1.25 -+++ linux/net/Makefile 20 Feb 2003 15:50:38 -0000 1.24 -@@ -19,6 +19,7 @@ - subdir-$(CONFIG_NETFILTER) += ipv4/netfilter - subdir-$(CONFIG_UNIX) += unix - subdir-$(CONFIG_IPV6) += ipv6 -+subdir-$(CONFIG_IPSEC) += ipsec - - ifneq ($(CONFIG_IPV6),n) - ifneq ($(CONFIG_IPV6),) ---- /dev/null 2004-02-02 20:32:13.000000000 +0000 -+++ linux/include/zlib/zlib.h 2004-07-05 23:56:59.000000000 +0100 -@@ -0,0 +1,893 @@ -+/* zlib.h -- interface of the 'zlib' general purpose compression library -+ version 1.1.4, March 11th, 2002 -+ -+ Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler -+ -+ This software is provided 'as-is', without any express or implied -+ warranty. In no event will the authors be held liable for any damages -+ arising from the use of this software. -+ -+ Permission is granted to anyone to use this software for any purpose, -+ including commercial applications, and to alter it and redistribute it -+ freely, subject to the following restrictions: -+ -+ 1. The origin of this software must not be misrepresented; you must not -+ claim that you wrote the original software. If you use this software -+ in a product, an acknowledgment in the product documentation would be -+ appreciated but is not required. -+ 2. Altered source versions must be plainly marked as such, and must not be -+ misrepresented as being the original software. -+ 3. This notice may not be removed or altered from any source distribution. -+ -+ Jean-loup Gailly Mark Adler -+ jloup@gzip.org madler@alumni.caltech.edu -+ -+ -+ The data format used by the zlib library is described by RFCs (Request for -+ Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt -+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -+*/ -+ -+#ifndef _ZLIB_H -+#define _ZLIB_H -+ -+#include "zconf.h" -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#define ZLIB_VERSION "1.1.4" -+ -+/* -+ The 'zlib' compression library provides in-memory compression and -+ decompression functions, including integrity checks of the uncompressed -+ data. This version of the library supports only one compression method -+ (deflation) but other algorithms will be added later and will have the same -+ stream interface. -+ -+ Compression can be done in a single step if the buffers are large -+ enough (for example if an input file is mmap'ed), or can be done by -+ repeated calls of the compression function. In the latter case, the -+ application must provide more input and/or consume the output -+ (providing more output space) before each call. -+ -+ The library also supports reading and writing files in gzip (.gz) format -+ with an interface similar to that of stdio. -+ -+ The library does not install any signal handler. The decoder checks -+ the consistency of the compressed data, so the library should never -+ crash even in case of corrupted input. -+*/ -+ -+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -+typedef void (*free_func) OF((voidpf opaque, voidpf address)); -+ -+struct internal_state; -+ -+typedef struct z_stream_s { -+ Bytef *next_in; /* next input byte */ -+ uInt avail_in; /* number of bytes available at next_in */ -+ uLong total_in; /* total nb of input bytes read so far */ -+ -+ Bytef *next_out; /* next output byte should be put there */ -+ uInt avail_out; /* remaining free space at next_out */ -+ uLong total_out; /* total nb of bytes output so far */ -+ -+ const char *msg; /* last error message, NULL if no error */ -+ struct internal_state FAR *state; /* not visible by applications */ -+ -+ alloc_func zalloc; /* used to allocate the internal state */ -+ free_func zfree; /* used to free the internal state */ -+ voidpf opaque; /* private data object passed to zalloc and zfree */ -+ -+ int data_type; /* best guess about the data type: ascii or binary */ -+ uLong adler; /* adler32 value of the uncompressed data */ -+ uLong reserved; /* reserved for future use */ -+} z_stream; -+ -+typedef z_stream FAR *z_streamp; -+ -+/* -+ The application must update next_in and avail_in when avail_in has -+ dropped to zero. It must update next_out and avail_out when avail_out -+ has dropped to zero. The application must initialize zalloc, zfree and -+ opaque before calling the init function. All other fields are set by the -+ compression library and must not be updated by the application. -+ -+ The opaque value provided by the application will be passed as the first -+ parameter for calls of zalloc and zfree. This can be useful for custom -+ memory management. The compression library attaches no meaning to the -+ opaque value. -+ -+ zalloc must return Z_NULL if there is not enough memory for the object. -+ If zlib is used in a multi-threaded application, zalloc and zfree must be -+ thread safe. -+ -+ On 16-bit systems, the functions zalloc and zfree must be able to allocate -+ exactly 65536 bytes, but will not be required to allocate more than this -+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, -+ pointers returned by zalloc for objects of exactly 65536 bytes *must* -+ have their offset normalized to zero. The default allocation function -+ provided by this library ensures this (see zutil.c). To reduce memory -+ requirements and avoid any allocation of 64K objects, at the expense of -+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). -+ -+ The fields total_in and total_out can be used for statistics or -+ progress reports. After compression, total_in holds the total size of -+ the uncompressed data and may be saved for use in the decompressor -+ (particularly if the decompressor wants to decompress everything in -+ a single step). -+*/ -+ -+ /* constants */ -+ -+#define Z_NO_FLUSH 0 -+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ -+#define Z_SYNC_FLUSH 2 -+#define Z_FULL_FLUSH 3 -+#define Z_FINISH 4 -+/* Allowed flush values; see deflate() below for details */ -+ -+#define Z_OK 0 -+#define Z_STREAM_END 1 -+#define Z_NEED_DICT 2 -+#define Z_ERRNO (-1) -+#define Z_STREAM_ERROR (-2) -+#define Z_DATA_ERROR (-3) -+#define Z_MEM_ERROR (-4) -+#define Z_BUF_ERROR (-5) -+#define Z_VERSION_ERROR (-6) -+/* Return codes for the compression/decompression functions. Negative -+ * values are errors, positive values are used for special but normal events. -+ */ -+ -+#define Z_NO_COMPRESSION 0 -+#define Z_BEST_SPEED 1 -+#define Z_BEST_COMPRESSION 9 -+#define Z_DEFAULT_COMPRESSION (-1) -+/* compression levels */ -+ -+#define Z_FILTERED 1 -+#define Z_HUFFMAN_ONLY 2 -+#define Z_DEFAULT_STRATEGY 0 -+/* compression strategy; see deflateInit2() below for details */ -+ -+#define Z_BINARY 0 -+#define Z_ASCII 1 -+#define Z_UNKNOWN 2 -+/* Possible values of the data_type field */ -+ -+#define Z_DEFLATED 8 -+/* The deflate compression method (the only one supported in this version) */ -+ -+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ -+ -+#define zlib_version zlibVersion() -+/* for compatibility with versions < 1.0.2 */ -+ -+ /* basic functions */ -+ -+ZEXTERN const char * ZEXPORT zlibVersion OF((void)); -+/* The application can compare zlibVersion and ZLIB_VERSION for consistency. -+ If the first character differs, the library code actually used is -+ not compatible with the zlib.h header file used by the application. -+ This check is automatically made by deflateInit and inflateInit. -+ */ -+ -+/* -+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); -+ -+ Initializes the internal stream state for compression. The fields -+ zalloc, zfree and opaque must be initialized before by the caller. -+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to -+ use default allocation functions. -+ -+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: -+ 1 gives best speed, 9 gives best compression, 0 gives no compression at -+ all (the input data is simply copied a block at a time). -+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and -+ compression (currently equivalent to level 6). -+ -+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory, Z_STREAM_ERROR if level is not a valid compression level, -+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible -+ with the version assumed by the caller (ZLIB_VERSION). -+ msg is set to null if there is no error message. deflateInit does not -+ perform any compression: this will be done by deflate(). -+*/ -+ -+ -+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); -+/* -+ deflate compresses as much data as possible, and stops when the input -+ buffer becomes empty or the output buffer becomes full. It may introduce some -+ output latency (reading input without producing any output) except when -+ forced to flush. -+ -+ The detailed semantics are as follows. deflate performs one or both of the -+ following actions: -+ -+ - Compress more input starting at next_in and update next_in and avail_in -+ accordingly. If not all input can be processed (because there is not -+ enough room in the output buffer), next_in and avail_in are updated and -+ processing will resume at this point for the next call of deflate(). -+ -+ - Provide more output starting at next_out and update next_out and avail_out -+ accordingly. This action is forced if the parameter flush is non zero. -+ Forcing flush frequently degrades the compression ratio, so this parameter -+ should be set only when necessary (in interactive applications). -+ Some output may be provided even if flush is not set. -+ -+ Before the call of deflate(), the application should ensure that at least -+ one of the actions is possible, by providing more input and/or consuming -+ more output, and updating avail_in or avail_out accordingly; avail_out -+ should never be zero before the call. The application can consume the -+ compressed output when it wants, for example when the output buffer is full -+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK -+ and with zero avail_out, it must be called again after making room in the -+ output buffer because there might be more output pending. -+ -+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is -+ flushed to the output buffer and the output is aligned on a byte boundary, so -+ that the decompressor can get all input data available so far. (In particular -+ avail_in is zero after the call if enough output space has been provided -+ before the call.) Flushing may degrade compression for some compression -+ algorithms and so it should be used only when necessary. -+ -+ If flush is set to Z_FULL_FLUSH, all output is flushed as with -+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can -+ restart from this point if previous compressed data has been damaged or if -+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade -+ the compression. -+ -+ If deflate returns with avail_out == 0, this function must be called again -+ with the same value of the flush parameter and more output space (updated -+ avail_out), until the flush is complete (deflate returns with non-zero -+ avail_out). -+ -+ If the parameter flush is set to Z_FINISH, pending input is processed, -+ pending output is flushed and deflate returns with Z_STREAM_END if there -+ was enough output space; if deflate returns with Z_OK, this function must be -+ called again with Z_FINISH and more output space (updated avail_out) but no -+ more input data, until it returns with Z_STREAM_END or an error. After -+ deflate has returned Z_STREAM_END, the only possible operations on the -+ stream are deflateReset or deflateEnd. -+ -+ Z_FINISH can be used immediately after deflateInit if all the compression -+ is to be done in a single step. In this case, avail_out must be at least -+ 0.1% larger than avail_in plus 12 bytes. If deflate does not return -+ Z_STREAM_END, then it must be called again as described above. -+ -+ deflate() sets strm->adler to the adler32 checksum of all input read -+ so far (that is, total_in bytes). -+ -+ deflate() may update data_type if it can make a good guess about -+ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered -+ binary. This field is only for information purposes and does not affect -+ the compression algorithm in any manner. -+ -+ deflate() returns Z_OK if some progress has been made (more input -+ processed or more output produced), Z_STREAM_END if all input has been -+ consumed and all output has been produced (only when flush is set to -+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example -+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible -+ (for example avail_in or avail_out was zero). -+*/ -+ -+ -+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -+/* -+ All dynamically allocated data structures for this stream are freed. -+ This function discards any unprocessed input and does not flush any -+ pending output. -+ -+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the -+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed -+ prematurely (some input or output was discarded). In the error case, -+ msg may be set but then points to a static string (which must not be -+ deallocated). -+*/ -+ -+ -+/* -+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); -+ -+ Initializes the internal stream state for decompression. The fields -+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by -+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact -+ value depends on the compression method), inflateInit determines the -+ compression method from the zlib header and allocates all data structures -+ accordingly; otherwise the allocation will be deferred to the first call of -+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to -+ use default allocation functions. -+ -+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the -+ version assumed by the caller. msg is set to null if there is no error -+ message. inflateInit does not perform any decompression apart from reading -+ the zlib header if present: this will be done by inflate(). (So next_in and -+ avail_in may be modified, but next_out and avail_out are unchanged.) -+*/ -+ -+ -+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -+/* -+ inflate decompresses as much data as possible, and stops when the input -+ buffer becomes empty or the output buffer becomes full. It may some -+ introduce some output latency (reading input without producing any output) -+ except when forced to flush. -+ -+ The detailed semantics are as follows. inflate performs one or both of the -+ following actions: -+ -+ - Decompress more input starting at next_in and update next_in and avail_in -+ accordingly. If not all input can be processed (because there is not -+ enough room in the output buffer), next_in is updated and processing -+ will resume at this point for the next call of inflate(). -+ -+ - Provide more output starting at next_out and update next_out and avail_out -+ accordingly. inflate() provides as much output as possible, until there -+ is no more input data or no more space in the output buffer (see below -+ about the flush parameter). -+ -+ Before the call of inflate(), the application should ensure that at least -+ one of the actions is possible, by providing more input and/or consuming -+ more output, and updating the next_* and avail_* values accordingly. -+ The application can consume the uncompressed output when it wants, for -+ example when the output buffer is full (avail_out == 0), or after each -+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it -+ must be called again after making room in the output buffer because there -+ might be more output pending. -+ -+ If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much -+ output as possible to the output buffer. The flushing behavior of inflate is -+ not specified for values of the flush parameter other than Z_SYNC_FLUSH -+ and Z_FINISH, but the current implementation actually flushes as much output -+ as possible anyway. -+ -+ inflate() should normally be called until it returns Z_STREAM_END or an -+ error. However if all decompression is to be performed in a single step -+ (a single call of inflate), the parameter flush should be set to -+ Z_FINISH. In this case all pending input is processed and all pending -+ output is flushed; avail_out must be large enough to hold all the -+ uncompressed data. (The size of the uncompressed data may have been saved -+ by the compressor for this purpose.) The next operation on this stream must -+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH -+ is never required, but can be used to inform inflate that a faster routine -+ may be used for the single inflate() call. -+ -+ If a preset dictionary is needed at this point (see inflateSetDictionary -+ below), inflate sets strm-adler to the adler32 checksum of the -+ dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise -+ it sets strm->adler to the adler32 checksum of all output produced -+ so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or -+ an error code as described below. At the end of the stream, inflate() -+ checks that its computed adler32 checksum is equal to that saved by the -+ compressor and returns Z_STREAM_END only if the checksum is correct. -+ -+ inflate() returns Z_OK if some progress has been made (more input processed -+ or more output produced), Z_STREAM_END if the end of the compressed data has -+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a -+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was -+ corrupted (input stream not conforming to the zlib format or incorrect -+ adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent -+ (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not -+ enough memory, Z_BUF_ERROR if no progress is possible or if there was not -+ enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR -+ case, the application may then call inflateSync to look for a good -+ compression block. -+*/ -+ -+ -+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -+/* -+ All dynamically allocated data structures for this stream are freed. -+ This function discards any unprocessed input and does not flush any -+ pending output. -+ -+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state -+ was inconsistent. In the error case, msg may be set but then points to a -+ static string (which must not be deallocated). -+*/ -+ -+ /* Advanced functions */ -+ -+/* -+ The following functions are needed only in some special applications. -+*/ -+ -+/* -+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, -+ int level, -+ int method, -+ int windowBits, -+ int memLevel, -+ int strategy)); -+ -+ This is another version of deflateInit with more compression options. The -+ fields next_in, zalloc, zfree and opaque must be initialized before by -+ the caller. -+ -+ The method parameter is the compression method. It must be Z_DEFLATED in -+ this version of the library. -+ -+ The windowBits parameter is the base two logarithm of the window size -+ (the size of the history buffer). It should be in the range 8..15 for this -+ version of the library. Larger values of this parameter result in better -+ compression at the expense of memory usage. The default value is 15 if -+ deflateInit is used instead. -+ -+ The memLevel parameter specifies how much memory should be allocated -+ for the internal compression state. memLevel=1 uses minimum memory but -+ is slow and reduces compression ratio; memLevel=9 uses maximum memory -+ for optimal speed. The default value is 8. See zconf.h for total memory -+ usage as a function of windowBits and memLevel. -+ -+ The strategy parameter is used to tune the compression algorithm. Use the -+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a -+ filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no -+ string match). Filtered data consists mostly of small values with a -+ somewhat random distribution. In this case, the compression algorithm is -+ tuned to compress them better. The effect of Z_FILTERED is to force more -+ Huffman coding and less string matching; it is somewhat intermediate -+ between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects -+ the compression ratio but not the correctness of the compressed output even -+ if it is not set appropriately. -+ -+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid -+ method). msg is set to null if there is no error message. deflateInit2 does -+ not perform any compression: this will be done by deflate(). -+*/ -+ -+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, -+ const Bytef *dictionary, -+ uInt dictLength)); -+/* -+ Initializes the compression dictionary from the given byte sequence -+ without producing any compressed output. This function must be called -+ immediately after deflateInit, deflateInit2 or deflateReset, before any -+ call of deflate. The compressor and decompressor must use exactly the same -+ dictionary (see inflateSetDictionary). -+ -+ The dictionary should consist of strings (byte sequences) that are likely -+ to be encountered later in the data to be compressed, with the most commonly -+ used strings preferably put towards the end of the dictionary. Using a -+ dictionary is most useful when the data to be compressed is short and can be -+ predicted with good accuracy; the data can then be compressed better than -+ with the default empty dictionary. -+ -+ Depending on the size of the compression data structures selected by -+ deflateInit or deflateInit2, a part of the dictionary may in effect be -+ discarded, for example if the dictionary is larger than the window size in -+ deflate or deflate2. Thus the strings most likely to be useful should be -+ put at the end of the dictionary, not at the front. -+ -+ Upon return of this function, strm->adler is set to the Adler32 value -+ of the dictionary; the decompressor may later use this value to determine -+ which dictionary has been used by the compressor. (The Adler32 value -+ applies to the whole dictionary even if only a subset of the dictionary is -+ actually used by the compressor.) -+ -+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a -+ parameter is invalid (such as NULL dictionary) or the stream state is -+ inconsistent (for example if deflate has already been called for this stream -+ or if the compression method is bsort). deflateSetDictionary does not -+ perform any compression: this will be done by deflate(). -+*/ -+ -+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, -+ z_streamp source)); -+/* -+ Sets the destination stream as a complete copy of the source stream. -+ -+ This function can be useful when several compression strategies will be -+ tried, for example when there are several ways of pre-processing the input -+ data with a filter. The streams that will be discarded should then be freed -+ by calling deflateEnd. Note that deflateCopy duplicates the internal -+ compression state which can be quite large, so this strategy is slow and -+ can consume lots of memory. -+ -+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent -+ (such as zalloc being NULL). msg is left unchanged in both source and -+ destination. -+*/ -+ -+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -+/* -+ This function is equivalent to deflateEnd followed by deflateInit, -+ but does not free and reallocate all the internal compression state. -+ The stream will keep the same compression level and any other attributes -+ that may have been set by deflateInit2. -+ -+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source -+ stream state was inconsistent (such as zalloc or state being NULL). -+*/ -+ -+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, -+ int level, -+ int strategy)); -+/* -+ Dynamically update the compression level and compression strategy. The -+ interpretation of level and strategy is as in deflateInit2. This can be -+ used to switch between compression and straight copy of the input data, or -+ to switch to a different kind of input data requiring a different -+ strategy. If the compression level is changed, the input available so far -+ is compressed with the old level (and may be flushed); the new level will -+ take effect only at the next call of deflate(). -+ -+ Before the call of deflateParams, the stream state must be set as for -+ a call of deflate(), since the currently available input may have to -+ be compressed and flushed. In particular, strm->avail_out must be non-zero. -+ -+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source -+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR -+ if strm->avail_out was zero. -+*/ -+ -+/* -+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, -+ int windowBits)); -+ -+ This is another version of inflateInit with an extra parameter. The -+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized -+ before by the caller. -+ -+ The windowBits parameter is the base two logarithm of the maximum window -+ size (the size of the history buffer). It should be in the range 8..15 for -+ this version of the library. The default value is 15 if inflateInit is used -+ instead. If a compressed stream with a larger window size is given as -+ input, inflate() will return with the error code Z_DATA_ERROR instead of -+ trying to allocate a larger window. -+ -+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative -+ memLevel). msg is set to null if there is no error message. inflateInit2 -+ does not perform any decompression apart from reading the zlib header if -+ present: this will be done by inflate(). (So next_in and avail_in may be -+ modified, but next_out and avail_out are unchanged.) -+*/ -+ -+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, -+ const Bytef *dictionary, -+ uInt dictLength)); -+/* -+ Initializes the decompression dictionary from the given uncompressed byte -+ sequence. This function must be called immediately after a call of inflate -+ if this call returned Z_NEED_DICT. The dictionary chosen by the compressor -+ can be determined from the Adler32 value returned by this call of -+ inflate. The compressor and decompressor must use exactly the same -+ dictionary (see deflateSetDictionary). -+ -+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a -+ parameter is invalid (such as NULL dictionary) or the stream state is -+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the -+ expected one (incorrect Adler32 value). inflateSetDictionary does not -+ perform any decompression: this will be done by subsequent calls of -+ inflate(). -+*/ -+ -+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -+/* -+ Skips invalid compressed data until a full flush point (see above the -+ description of deflate with Z_FULL_FLUSH) can be found, or until all -+ available input is skipped. No output is provided. -+ -+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR -+ if no more input was provided, Z_DATA_ERROR if no flush point has been found, -+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success -+ case, the application may save the current current value of total_in which -+ indicates where valid compressed data was found. In the error case, the -+ application may repeatedly call inflateSync, providing more input each time, -+ until success or end of the input data. -+*/ -+ -+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -+/* -+ This function is equivalent to inflateEnd followed by inflateInit, -+ but does not free and reallocate all the internal decompression state. -+ The stream will keep attributes that may have been set by inflateInit2. -+ -+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source -+ stream state was inconsistent (such as zalloc or state being NULL). -+*/ -+ -+ -+ /* utility functions */ -+ -+/* -+ The following utility functions are implemented on top of the -+ basic stream-oriented functions. To simplify the interface, some -+ default options are assumed (compression level and memory usage, -+ standard memory allocation functions). The source code of these -+ utility functions can easily be modified if you need special options. -+*/ -+ -+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, -+ const Bytef *source, uLong sourceLen)); -+/* -+ Compresses the source buffer into the destination buffer. sourceLen is -+ the byte length of the source buffer. Upon entry, destLen is the total -+ size of the destination buffer, which must be at least 0.1% larger than -+ sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the -+ compressed buffer. -+ This function can be used to compress a whole file at once if the -+ input file is mmap'ed. -+ compress returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory, Z_BUF_ERROR if there was not enough room in the output -+ buffer. -+*/ -+ -+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, -+ const Bytef *source, uLong sourceLen, -+ int level)); -+/* -+ Compresses the source buffer into the destination buffer. The level -+ parameter has the same meaning as in deflateInit. sourceLen is the byte -+ length of the source buffer. Upon entry, destLen is the total size of the -+ destination buffer, which must be at least 0.1% larger than sourceLen plus -+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. -+ -+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_BUF_ERROR if there was not enough room in the output buffer, -+ Z_STREAM_ERROR if the level parameter is invalid. -+*/ -+ -+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, -+ const Bytef *source, uLong sourceLen)); -+/* -+ Decompresses the source buffer into the destination buffer. sourceLen is -+ the byte length of the source buffer. Upon entry, destLen is the total -+ size of the destination buffer, which must be large enough to hold the -+ entire uncompressed data. (The size of the uncompressed data must have -+ been saved previously by the compressor and transmitted to the decompressor -+ by some mechanism outside the scope of this compression library.) -+ Upon exit, destLen is the actual size of the compressed buffer. -+ This function can be used to decompress a whole file at once if the -+ input file is mmap'ed. -+ -+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory, Z_BUF_ERROR if there was not enough room in the output -+ buffer, or Z_DATA_ERROR if the input data was corrupted. -+*/ -+ -+ -+typedef voidp gzFile; -+ -+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); -+/* -+ Opens a gzip (.gz) file for reading or writing. The mode parameter -+ is as in fopen ("rb" or "wb") but can also include a compression level -+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for -+ Huffman only compression as in "wb1h". (See the description -+ of deflateInit2 for more information about the strategy parameter.) -+ -+ gzopen can be used to read a file which is not in gzip format; in this -+ case gzread will directly read from the file without decompression. -+ -+ gzopen returns NULL if the file could not be opened or if there was -+ insufficient memory to allocate the (de)compression state; errno -+ can be checked to distinguish the two cases (if errno is zero, the -+ zlib error is Z_MEM_ERROR). */ -+ -+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -+/* -+ gzdopen() associates a gzFile with the file descriptor fd. File -+ descriptors are obtained from calls like open, dup, creat, pipe or -+ fileno (in the file has been previously opened with fopen). -+ The mode parameter is as in gzopen. -+ The next call of gzclose on the returned gzFile will also close the -+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file -+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). -+ gzdopen returns NULL if there was insufficient memory to allocate -+ the (de)compression state. -+*/ -+ -+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -+/* -+ Dynamically update the compression level or strategy. See the description -+ of deflateInit2 for the meaning of these parameters. -+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not -+ opened for writing. -+*/ -+ -+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -+/* -+ Reads the given number of uncompressed bytes from the compressed file. -+ If the input file was not in gzip format, gzread copies the given number -+ of bytes into the buffer. -+ gzread returns the number of uncompressed bytes actually read (0 for -+ end of file, -1 for error). */ -+ -+ZEXTERN int ZEXPORT gzwrite OF((gzFile file, -+ const voidp buf, unsigned len)); -+/* -+ Writes the given number of uncompressed bytes into the compressed file. -+ gzwrite returns the number of uncompressed bytes actually written -+ (0 in case of error). -+*/ -+ -+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); -+/* -+ Converts, formats, and writes the args to the compressed file under -+ control of the format string, as in fprintf. gzprintf returns the number of -+ uncompressed bytes actually written (0 in case of error). -+*/ -+ -+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -+/* -+ Writes the given null-terminated string to the compressed file, excluding -+ the terminating null character. -+ gzputs returns the number of characters written, or -1 in case of error. -+*/ -+ -+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -+/* -+ Reads bytes from the compressed file until len-1 characters are read, or -+ a newline character is read and transferred to buf, or an end-of-file -+ condition is encountered. The string is then terminated with a null -+ character. -+ gzgets returns buf, or Z_NULL in case of error. -+*/ -+ -+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -+/* -+ Writes c, converted to an unsigned char, into the compressed file. -+ gzputc returns the value that was written, or -1 in case of error. -+*/ -+ -+ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -+/* -+ Reads one byte from the compressed file. gzgetc returns this byte -+ or -1 in case of end of file or error. -+*/ -+ -+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -+/* -+ Flushes all pending output into the compressed file. The parameter -+ flush is as in the deflate() function. The return value is the zlib -+ error number (see function gzerror below). gzflush returns Z_OK if -+ the flush parameter is Z_FINISH and all output could be flushed. -+ gzflush should be called only when strictly necessary because it can -+ degrade compression. -+*/ -+ -+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, -+ z_off_t offset, int whence)); -+/* -+ Sets the starting position for the next gzread or gzwrite on the -+ given compressed file. The offset represents a number of bytes in the -+ uncompressed data stream. The whence parameter is defined as in lseek(2); -+ the value SEEK_END is not supported. -+ If the file is opened for reading, this function is emulated but can be -+ extremely slow. If the file is opened for writing, only forward seeks are -+ supported; gzseek then compresses a sequence of zeroes up to the new -+ starting position. -+ -+ gzseek returns the resulting offset location as measured in bytes from -+ the beginning of the uncompressed stream, or -1 in case of error, in -+ particular if the file is opened for writing and the new starting position -+ would be before the current position. -+*/ -+ -+ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -+/* -+ Rewinds the given file. This function is supported only for reading. -+ -+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -+*/ -+ -+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); -+/* -+ Returns the starting position for the next gzread or gzwrite on the -+ given compressed file. This position represents a number of bytes in the -+ uncompressed data stream. -+ -+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -+*/ -+ -+ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -+/* -+ Returns 1 when EOF has previously been detected reading the given -+ input stream, otherwise zero. -+*/ -+ -+ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -+/* -+ Flushes all pending output if necessary, closes the compressed file -+ and deallocates all the (de)compression state. The return value is the zlib -+ error number (see function gzerror below). -+*/ -+ -+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -+/* -+ Returns the error message for the last error which occurred on the -+ given compressed file. errnum is set to zlib error number. If an -+ error occurred in the file system and not in the compression library, -+ errnum is set to Z_ERRNO and the application may consult errno -+ to get the exact error code. -+*/ -+ -+ /* checksum functions */ -+ -+/* -+ These functions are not related to compression but are exported -+ anyway because they might be useful in applications using the -+ compression library. -+*/ -+ -+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -+ -+/* -+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and -+ return the updated checksum. If buf is NULL, this function returns -+ the required initial value for the checksum. -+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed -+ much faster. Usage example: -+ -+ uLong adler = adler32(0L, Z_NULL, 0); -+ -+ while (read_buffer(buffer, length) != EOF) { -+ adler = adler32(adler, buffer, length); -+ } -+ if (adler != original_adler) error(); -+*/ -+ -+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -+/* -+ Update a running crc with the bytes buf[0..len-1] and return the updated -+ crc. If buf is NULL, this function returns the required initial value -+ for the crc. Pre- and post-conditioning (one's complement) is performed -+ within this function so it shouldn't be done by the application. -+ Usage example: -+ -+ uLong crc = crc32(0L, Z_NULL, 0); -+ -+ while (read_buffer(buffer, length) != EOF) { -+ crc = crc32(crc, buffer, length); -+ } -+ if (crc != original_crc) error(); -+*/ -+ -+ -+ /* various hacks, don't look :) */ -+ -+/* deflateInit and inflateInit are macros to allow checking the zlib version -+ * and the compiler's view of z_stream: -+ */ -+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, -+ const char *version, int stream_size)); -+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, -+ const char *version, int stream_size)); -+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, -+ int windowBits, int memLevel, -+ int strategy, const char *version, -+ int stream_size)); -+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, -+ const char *version, int stream_size)); -+#define deflateInit(strm, level) \ -+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -+#define inflateInit(strm) \ -+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ -+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ -+ (strategy), ZLIB_VERSION, sizeof(z_stream)) -+#define inflateInit2(strm, windowBits) \ -+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) -+ -+ -+#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) -+ struct internal_state {int dummy;}; /* hack for buggy compilers */ -+#endif -+ -+ZEXTERN const char * ZEXPORT zError OF((int err)); -+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); -+ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* _ZLIB_H */ ---- /dev/null 2004-02-02 20:32:13.000000000 +0000 -+++ linux/include/zlib/zutil.h 2004-07-05 23:59:30.000000000 +0100 -@@ -0,0 +1,225 @@ -+/* zutil.h -- internal interface and configuration of the compression library -+ * Copyright (C) 1995-2002 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+/* @(#) $Id$ */ -+ -+#ifndef _Z_UTIL_H -+#define _Z_UTIL_H -+ -+#include "zlib.h" -+ -+#include -+#define HAVE_MEMCPY -+ -+#if 0 // #ifdef STDC -+# include -+# include -+# include -+#endif -+#ifndef __KERNEL__ -+#ifdef NO_ERRNO_H -+ extern int errno; -+#else -+# include -+#endif -+#endif -+ -+#ifndef local -+# define local static -+#endif -+/* compile with -Dlocal if your debugger can't find static symbols */ -+ -+typedef unsigned char uch; -+typedef uch FAR uchf; -+typedef unsigned short ush; -+typedef ush FAR ushf; -+typedef unsigned long ulg; -+ -+extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ -+/* (size given to avoid silly warnings with Visual C++) */ -+ -+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] -+ -+#define ERR_RETURN(strm,err) \ -+ return (strm->msg = ERR_MSG(err), (err)) -+/* To be used only when the state is known to be valid */ -+ -+ /* common constants */ -+ -+#ifndef DEF_WBITS -+# define DEF_WBITS MAX_WBITS -+#endif -+/* default windowBits for decompression. MAX_WBITS is for compression only */ -+ -+#if MAX_MEM_LEVEL >= 8 -+# define DEF_MEM_LEVEL 8 -+#else -+# define DEF_MEM_LEVEL MAX_MEM_LEVEL -+#endif -+/* default memLevel */ -+ -+#define STORED_BLOCK 0 -+#define STATIC_TREES 1 -+#define DYN_TREES 2 -+/* The three kinds of block type */ -+ -+#define MIN_MATCH 3 -+#define MAX_MATCH 258 -+/* The minimum and maximum match lengths */ -+ -+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ -+ -+ /* target dependencies */ -+ -+#ifdef MSDOS -+# define OS_CODE 0x00 -+# if defined(__TURBOC__) || defined(__BORLANDC__) -+# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) -+ /* Allow compilation with ANSI keywords only enabled */ -+ void _Cdecl farfree( void *block ); -+ void *_Cdecl farmalloc( unsigned long nbytes ); -+# else -+# include -+# endif -+# else /* MSC or DJGPP */ -+# include -+# endif -+#endif -+ -+#ifdef OS2 -+# define OS_CODE 0x06 -+#endif -+ -+#ifdef WIN32 /* Window 95 & Windows NT */ -+# define OS_CODE 0x0b -+#endif -+ -+#if defined(VAXC) || defined(VMS) -+# define OS_CODE 0x02 -+# define F_OPEN(name, mode) \ -+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") -+#endif -+ -+#ifdef AMIGA -+# define OS_CODE 0x01 -+#endif -+ -+#if defined(ATARI) || defined(atarist) -+# define OS_CODE 0x05 -+#endif -+ -+#if defined(MACOS) || defined(TARGET_OS_MAC) -+# define OS_CODE 0x07 -+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -+# include /* for fdopen */ -+# else -+# ifndef fdopen -+# define fdopen(fd,mode) NULL /* No fdopen() */ -+# endif -+# endif -+#endif -+ -+#ifdef __50SERIES /* Prime/PRIMOS */ -+# define OS_CODE 0x0F -+#endif -+ -+#ifdef TOPS20 -+# define OS_CODE 0x0a -+#endif -+ -+#if defined(_BEOS_) || defined(RISCOS) -+# define fdopen(fd,mode) NULL /* No fdopen() */ -+#endif -+ -+#if (defined(_MSC_VER) && (_MSC_VER > 600)) -+# define fdopen(fd,type) _fdopen(fd,type) -+#endif -+ -+ -+ /* Common defaults */ -+ -+#ifndef OS_CODE -+# define OS_CODE 0x03 /* assume Unix */ -+#endif -+ -+#ifndef F_OPEN -+# define F_OPEN(name, mode) fopen((name), (mode)) -+#endif -+ -+ /* functions */ -+ -+#ifdef HAVE_STRERROR -+ extern char *strerror OF((int)); -+# define zstrerror(errnum) strerror(errnum) -+#else -+# define zstrerror(errnum) "" -+#endif -+ -+#if defined(pyr) -+# define NO_MEMCPY -+#endif -+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) -+ /* Use our own functions for small and medium model with MSC <= 5.0. -+ * You may have to use the same strategy for Borland C (untested). -+ * The __SC__ check is for Symantec. -+ */ -+# define NO_MEMCPY -+#endif -+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) -+# define HAVE_MEMCPY -+#endif -+#ifdef HAVE_MEMCPY -+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ -+# define zmemcpy _fmemcpy -+# define zmemcmp _fmemcmp -+# define zmemzero(dest, len) _fmemset(dest, 0, len) -+# else -+# define zmemcpy memcpy -+# define zmemcmp memcmp -+# define zmemzero(dest, len) memset(dest, 0, len) -+# endif -+#else -+ extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); -+ extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); -+ extern void zmemzero OF((Bytef* dest, uInt len)); -+#endif -+ -+/* Diagnostic functions */ -+#ifdef DEBUG -+# include -+ extern int z_verbose; -+ extern void z_error OF((char *m)); -+# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -+# define Trace(x) {if (z_verbose>=0) fprintf x ;} -+# define Tracev(x) {if (z_verbose>0) fprintf x ;} -+# define Tracevv(x) {if (z_verbose>1) fprintf x ;} -+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} -+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} -+#else -+# define Assert(cond,msg) -+# define Trace(x) -+# define Tracev(x) -+# define Tracevv(x) -+# define Tracec(c,x) -+# define Tracecv(c,x) -+#endif -+ -+ -+typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, -+ uInt len)); -+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); -+void zcfree OF((voidpf opaque, voidpf ptr)); -+ -+#define ZALLOC(strm, items, size) \ -+ (*((strm)->zalloc))((strm)->opaque, (items), (size)) -+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) -+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} -+ -+#endif /* _Z_UTIL_H */ ---- /dev/null 2004-02-02 20:32:13.000000000 +0000 -+++ linux/include/zconf.h 2004-07-04 15:38:31.000000000 +0100 -@@ -0,0 +1,309 @@ -+/* zconf.h -- configuration of the zlib compression library -+ * Copyright (C) 1995-2002 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* @(#) $Id$ */ -+ -+#ifndef _ZCONF_H -+#define _ZCONF_H -+ -+/* -+ * If you *really* need a unique prefix for all types and library functions, -+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. -+ */ -+#ifdef IPCOMP_PREFIX -+# define deflateInit_ ipcomp_deflateInit_ -+# define deflate ipcomp_deflate -+# define deflateEnd ipcomp_deflateEnd -+# define inflateInit_ ipcomp_inflateInit_ -+# define inflate ipcomp_inflate -+# define inflateEnd ipcomp_inflateEnd -+# define deflateInit2_ ipcomp_deflateInit2_ -+# define deflateSetDictionary ipcomp_deflateSetDictionary -+# define deflateCopy ipcomp_deflateCopy -+# define deflateReset ipcomp_deflateReset -+# define deflateParams ipcomp_deflateParams -+# define inflateInit2_ ipcomp_inflateInit2_ -+# define inflateSetDictionary ipcomp_inflateSetDictionary -+# define inflateSync ipcomp_inflateSync -+# define inflateSyncPoint ipcomp_inflateSyncPoint -+# define inflateReset ipcomp_inflateReset -+# define compress ipcomp_compress -+# define compress2 ipcomp_compress2 -+# define uncompress ipcomp_uncompress -+# define adler32 ipcomp_adler32 -+# define crc32 ipcomp_crc32 -+# define get_crc_table ipcomp_get_crc_table -+/* SSS: these also need to be prefixed to avoid clash with ppp_deflate and ext2compression */ -+# define inflate_blocks ipcomp_deflate_blocks -+# define inflate_blocks_free ipcomp_deflate_blocks_free -+# define inflate_blocks_new ipcomp_inflate_blocks_new -+# define inflate_blocks_reset ipcomp_inflate_blocks_reset -+# define inflate_blocks_sync_point ipcomp_inflate_blocks_sync_point -+# define inflate_set_dictionary ipcomp_inflate_set_dictionary -+# define inflate_codes ipcomp_inflate_codes -+# define inflate_codes_free ipcomp_inflate_codes_free -+# define inflate_codes_new ipcomp_inflate_codes_new -+# define inflate_fast ipcomp_inflate_fast -+# define inflate_trees_bits ipcomp_inflate_trees_bits -+# define inflate_trees_dynamic ipcomp_inflate_trees_dynamic -+# define inflate_trees_fixed ipcomp_inflate_trees_fixed -+# define inflate_flush ipcomp_inflate_flush -+# define inflate_mask ipcomp_inflate_mask -+# define _dist_code _ipcomp_dist_code -+# define _length_code _ipcomp_length_code -+# define _tr_align _ipcomp_tr_align -+# define _tr_flush_block _ipcomp_tr_flush_block -+# define _tr_init _ipcomp_tr_init -+# define _tr_stored_block _ipcomp_tr_stored_block -+# define _tr_tally _ipcomp_tr_tally -+# define zError ipcomp_zError -+# define z_errmsg ipcomp_z_errmsg -+# define zlibVersion ipcomp_zlibVersion -+# define match_init ipcomp_match_init -+# define longest_match ipcomp_longest_match -+#endif -+ -+#ifdef Z_PREFIX -+# define Byte z_Byte -+# define uInt z_uInt -+# define uLong z_uLong -+# define Bytef z_Bytef -+# define charf z_charf -+# define intf z_intf -+# define uIntf z_uIntf -+# define uLongf z_uLongf -+# define voidpf z_voidpf -+# define voidp z_voidp -+#endif -+ -+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) -+# define WIN32 -+#endif -+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) -+# ifndef __32BIT__ -+# define __32BIT__ -+# endif -+#endif -+#if defined(__MSDOS__) && !defined(MSDOS) -+# define MSDOS -+#endif -+ -+/* -+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more -+ * than 64k bytes at a time (needed on systems with 16-bit int). -+ */ -+#if defined(MSDOS) && !defined(__32BIT__) -+# define MAXSEG_64K -+#endif -+#ifdef MSDOS -+# define UNALIGNED_OK -+#endif -+ -+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) -+# define STDC -+#endif -+#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) -+# ifndef STDC -+# define STDC -+# endif -+#endif -+ -+#ifndef STDC -+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -+# define const -+# endif -+#endif -+ -+/* Some Mac compilers merge all .h files incorrectly: */ -+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) -+# define NO_DUMMY_DECL -+#endif -+ -+/* Old Borland C incorrectly complains about missing returns: */ -+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) -+# define NEED_DUMMY_RETURN -+#endif -+ -+ -+/* Maximum value for memLevel in deflateInit2 */ -+#ifndef MAX_MEM_LEVEL -+# ifdef MAXSEG_64K -+# define MAX_MEM_LEVEL 8 -+# else -+# define MAX_MEM_LEVEL 9 -+# endif -+#endif -+ -+/* Maximum value for windowBits in deflateInit2 and inflateInit2. -+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files -+ * created by gzip. (Files created by minigzip can still be extracted by -+ * gzip.) -+ */ -+#ifndef MAX_WBITS -+# define MAX_WBITS 15 /* 32K LZ77 window */ -+#endif -+ -+/* The memory requirements for deflate are (in bytes): -+ (1 << (windowBits+2)) + (1 << (memLevel+9)) -+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) -+ plus a few kilobytes for small objects. For example, if you want to reduce -+ the default memory requirements from 256K to 128K, compile with -+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" -+ Of course this will generally degrade compression (there's no free lunch). -+ -+ The memory requirements for inflate are (in bytes) 1 << windowBits -+ that is, 32K for windowBits=15 (default value) plus a few kilobytes -+ for small objects. -+*/ -+ -+ /* Type declarations */ -+ -+#ifndef OF /* function prototypes */ -+# ifdef STDC -+# define OF(args) args -+# else -+# define OF(args) () -+# endif -+#endif -+ -+/* The following definitions for FAR are needed only for MSDOS mixed -+ * model programming (small or medium model with some far allocations). -+ * This was tested only with MSC; for other MSDOS compilers you may have -+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, -+ * just define FAR to be empty. -+ */ -+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) -+ /* MSC small or medium model */ -+# define SMALL_MEDIUM -+# ifdef _MSC_VER -+# define FAR _far -+# else -+# define FAR far -+# endif -+#endif -+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) -+# ifndef __32BIT__ -+# define SMALL_MEDIUM -+# define FAR _far -+# endif -+#endif -+ -+/* Compile with -DZLIB_DLL for Windows DLL support */ -+#if defined(ZLIB_DLL) -+# if defined(_WINDOWS) || defined(WINDOWS) -+# ifdef FAR -+# undef FAR -+# endif -+# include -+# define ZEXPORT WINAPI -+# ifdef WIN32 -+# define ZEXPORTVA WINAPIV -+# else -+# define ZEXPORTVA FAR _cdecl _export -+# endif -+# endif -+# if defined (__BORLANDC__) -+# if (__BORLANDC__ >= 0x0500) && defined (WIN32) -+# include -+# define ZEXPORT __declspec(dllexport) WINAPI -+# define ZEXPORTRVA __declspec(dllexport) WINAPIV -+# else -+# if defined (_Windows) && defined (__DLL__) -+# define ZEXPORT _export -+# define ZEXPORTVA _export -+# endif -+# endif -+# endif -+#endif -+ -+#if defined (__BEOS__) -+# if defined (ZLIB_DLL) -+# define ZEXTERN extern __declspec(dllexport) -+# else -+# define ZEXTERN extern __declspec(dllimport) -+# endif -+#endif -+ -+#ifndef ZEXPORT -+# define ZEXPORT -+#endif -+#ifndef ZEXPORTVA -+# define ZEXPORTVA -+#endif -+#ifndef ZEXTERN -+# define ZEXTERN extern -+#endif -+ -+#ifndef FAR -+# define FAR -+#endif -+ -+#if !defined(MACOS) && !defined(TARGET_OS_MAC) -+typedef unsigned char Byte; /* 8 bits */ -+#endif -+typedef unsigned int uInt; /* 16 bits or more */ -+typedef unsigned long uLong; /* 32 bits or more */ -+ -+#ifdef SMALL_MEDIUM -+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -+# define Bytef Byte FAR -+#else -+ typedef Byte FAR Bytef; -+#endif -+typedef char FAR charf; -+typedef int FAR intf; -+typedef uInt FAR uIntf; -+typedef uLong FAR uLongf; -+ -+#ifdef STDC -+ typedef void FAR *voidpf; -+ typedef void *voidp; -+#else -+ typedef Byte FAR *voidpf; -+ typedef Byte *voidp; -+#endif -+ -+#ifdef HAVE_UNISTD_H -+# include /* for off_t */ -+# include /* for SEEK_* and off_t */ -+# define z_off_t off_t -+#endif -+#ifndef SEEK_SET -+# define SEEK_SET 0 /* Seek from beginning of file. */ -+# define SEEK_CUR 1 /* Seek from current position. */ -+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -+#endif -+#ifndef z_off_t -+# define z_off_t long -+#endif -+ -+/* MVS linker does not support external names larger than 8 bytes */ -+#if defined(__MVS__) -+# pragma map(deflateInit_,"DEIN") -+# pragma map(deflateInit2_,"DEIN2") -+# pragma map(deflateEnd,"DEEND") -+# pragma map(inflateInit_,"ININ") -+# pragma map(inflateInit2_,"ININ2") -+# pragma map(inflateEnd,"INEND") -+# pragma map(inflateSync,"INSY") -+# pragma map(inflateSetDictionary,"INSEDI") -+# pragma map(inflate_blocks,"INBL") -+# pragma map(inflate_blocks_new,"INBLNE") -+# pragma map(inflate_blocks_free,"INBLFR") -+# pragma map(inflate_blocks_reset,"INBLRE") -+# pragma map(inflate_codes_free,"INCOFR") -+# pragma map(inflate_codes,"INCO") -+# pragma map(inflate_fast,"INFA") -+# pragma map(inflate_flush,"INFLU") -+# pragma map(inflate_mask,"INMA") -+# pragma map(inflate_set_dictionary,"INSEDI2") -+# pragma map(ipcomp_inflate_copyright,"INCOPY") -+# pragma map(inflate_trees_bits,"INTRBI") -+# pragma map(inflate_trees_dynamic,"INTRDY") -+# pragma map(inflate_trees_fixed,"INTRFI") -+# pragma map(inflate_trees_free,"INTRFR") -+#endif -+ -+#endif /* _ZCONF_H */ diff --git a/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/mkdep.patch b/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/mkdep.patch deleted file mode 100644 index 4daeaa11be..0000000000 --- a/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh36.12/mkdep.patch +++ /dev/null @@ -1,16 +0,0 @@ - -# -# Made by http://www.mn-logistik.de/unsupported/pxa250/patcher -# - ---- linux/Makefile~mkdep 2003-12-19 09:36:51.000000000 -0800 -+++ linux/Makefile 2003-12-19 09:57:44.000000000 -0800 -@@ -458,7 +458,7 @@ - - dep-files: scripts/mkdep archdep include/linux/version.h - scripts/mkdep -- init/*.c > .depend -- scripts/mkdep -- `find $(FINDHPATH) -name SCCS -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend -+ $(foreach, dir, $(FINDHPATH), scripts/mkdep -- `find $(dir) -name SCCS -prune -o -follow -name \*.h ! -name modversions.h -print` >> .hdepend) - $(MAKE) $(patsubst %,_sfdep_%,$(SUBDIRS)) _FASTDEP_ALL_SUB_DIRS="$(SUBDIRS)" - ifdef CONFIG_MODVERSIONS - $(MAKE) update-modverfile diff --git a/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh37.1/defconfig-ipaqsa b/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh37.1/defconfig-ipaqsa deleted file mode 100644 index c440fd3d59..0000000000 --- a/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh37.1/defconfig-ipaqsa +++ /dev/null @@ -1,1508 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_GENERIC_BUST_SPINLOCK is not set -# CONFIG_GENERIC_ISA_DMA is not set - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# System Type -# -# CONFIG_ARCH_ANAKIN is not set -# CONFIG_ARCH_ARCA5K is not set -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_OMAHA is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_MX1ADS is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_RISCSTATION is not set -CONFIG_ARCH_SA1100=y -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_AT91RM9200DK is not set -# CONFIG_MINIMAL_OOPS is not set - -# -# Linux As Bootldr support -# -# CONFIG_LAB is not set -# CONFIG_BIG_KERNEL is not set -# CONFIG_USE_DATE_CODE is not set - -# -# Archimedes/A5000 Implementations -# - -# -# Archimedes/A5000 Implementations (select only ONE) -# -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set - -# -# Footbridge Implementations -# -# CONFIG_ARCH_CATS is not set -# CONFIG_ARCH_PERSONAL_SERVER is not set -# CONFIG_ARCH_EBSA285_ADDIN is not set -# CONFIG_ARCH_EBSA285_HOST is not set -# CONFIG_ARCH_NETWINDER is not set - -# -# SA11x0 Implementations -# -# CONFIG_SA1100_ACCELENT is not set -# CONFIG_SA1100_ASSABET is not set -# CONFIG_ASSABET_NEPONSET is not set -# CONFIG_SA1100_ADSBITSY is not set -# CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_CEP is not set -# CONFIG_SA1100_CERF is not set -CONFIG_SA1100_H3100=y -CONFIG_SA1100_H3600=y -CONFIG_SA1100_H3800=y -# CONFIG_SA1100_CONSUS is not set -# CONFIG_SA1100_EXTENEX1 is not set -# CONFIG_SA1100_FLEXANET is not set -# CONFIG_SA1100_FREEBIRD is not set -# CONFIG_SA1100_FRODO is not set -# CONFIG_SA1100_GRAPHICSCLIENT is not set -# CONFIG_SA1100_GRAPHICSMASTER is not set -# CONFIG_SA1100_HACKKIT is not set -# CONFIG_SA1100_BADGE4 is not set -# CONFIG_SA1100_JORNADA720 is not set -# CONFIG_SA1100_JORNADA56X is not set -# CONFIG_SA1100_HUW_WEBPANEL is not set -# CONFIG_SA1100_ITSY is not set -# CONFIG_SA1100_LART is not set -# CONFIG_SA1100_NANOENGINE is not set -# CONFIG_SA1100_OMNIMETER is not set -# CONFIG_SA1100_PANGOLIN is not set -# CONFIG_SA1100_PLEB is not set -# CONFIG_SA1100_PT_SYSTEM3 is not set -# CONFIG_SA1100_SHANNON is not set -# CONFIG_SA1100_SHERMAN is not set -# CONFIG_SA1100_SIMPAD is not set -# CONFIG_SA1100_SIMPUTER is not set -# CONFIG_SA1100_PFS168 is not set -# CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_XP860 is not set -# CONFIG_SA1100_YOPY is not set -CONFIG_SA1100_USB=m -CONFIG_SA1100_USB_NETLINK=m -CONFIG_SA1100_USB_CHAR=m -CONFIG_REGISTERS=m - -# -# Intel PXA250/210 Implementations -# -# CONFIG_ARCH_LUBBOCK is not set -# CONFIG_ARCH_PXA_IDP is not set -# CONFIG_ARCH_PXA_CERF is not set -# CONFIG_ARCH_H3900 is not set -# CONFIG_ARCH_H1900 is not set -# CONFIG_ARCH_H5400 is not set -# CONFIG_ARCH_H2200 is not set -# CONFIG_ARCH_AXIM is not set -# CONFIG_PXA_USB is not set -# CONFIG_PXA_USB_NETLINK is not set -# CONFIG_PXA_USB_CHAR is not set - -# -# CLPS711X/EP721X Implementations -# -# CONFIG_ARCH_AUTCPU12 is not set -# CONFIG_ARCH_CDB89712 is not set -# CONFIG_ARCH_CLEP7312 is not set -# CONFIG_ARCH_EDB7211 is not set -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_FORTUNET is not set -# CONFIG_ARCH_EP7211 is not set -# CONFIG_ARCH_EP7212 is not set -# CONFIG_ARCH_ACORN is not set -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set - -# -# Processor Type -# -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -# CONFIG_CPU_ARM610 is not set -# CONFIG_CPU_ARM710 is not set -# CONFIG_CPU_ARM720T is not set -# CONFIG_CPU_ARM920T is not set -# CONFIG_CPU_ARM922T is not set -# CONFIG_PLD is not set -# CONFIG_CPU_ARM926T is not set -# CONFIG_CPU_ARM1020 is not set -# CONFIG_CPU_ARM1026 is not set -# CONFIG_CPU_SA110 is not set -CONFIG_CPU_SA1100=y -# CONFIG_CPU_32v3 is not set -CONFIG_CPU_32v4=y -CONFIG_SA1100_IPAQ=y -# CONFIG_PXA_IPAQ is not set -CONFIG_IPAQ_HANDHELD=y - -# -# Compaq iPAQ Handheld -# -CONFIG_IPAQ_HAL=m -CONFIG_H3600_MICRO=m -CONFIG_IPAQ_HAS_ROSELLA=y -# CONFIG_IPAQ_HAS_ASIC3 is not set -CONFIG_H3600_ASIC=m -CONFIG_H3900_ASIC_DEBUG=y -# CONFIG_H5400_ASIC is not set -# CONFIG_H1900_ASIC is not set -# CONFIG_H1900_TS is not set -CONFIG_H3600_HARDWARE=y -CONFIG_IPAQ_SLEEVE=m -CONFIG_SLEEVE_DEBUG=y -CONFIG_SLEEVE_DEBUG_VERBOSE=0 -# CONFIG_SLEEVE_IRQ_DEMUX is not set - -# -# Processor Features -# -CONFIG_DISCONTIGMEM=y - -# -# General setup -# -# CONFIG_PCI is not set -CONFIG_ISA=y -# CONFIG_ISA_DMA is not set -# CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_CPU_FREQ=y -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -# CONFIG_I82092 is not set -# CONFIG_I82365 is not set -# CONFIG_TCIC is not set -# CONFIG_PCMCIA_CLPS6700 is not set -CONFIG_PCMCIA_SA1100=m -# CONFIG_PCMCIA_PXA is not set -CONFIG_MERCURY_BACKPAQ=m - -# -# MMC/SD Card support -# -CONFIG_MMC=m -CONFIG_MMC_DEBUG=y -CONFIG_MMC_DEBUG_VERBOSE=0 -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y - -# -# At least one math emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_FASTFPE is not set -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_PM=y -CONFIG_APM=m -CONFIG_HWTIMER=m -# CONFIG_ARTHUR is not set -CONFIG_CMDLINE="keepinitrd" -# CONFIG_LEDS is not set -CONFIG_ALIGNMENT_TRAP=y - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -CONFIG_MTD_DEBUG=y -CONFIG_MTD_DEBUG_VERBOSE=1 -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_NOSWAP=y -# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -CONFIG_MTD_CFI_GEOMETRY=y -# CONFIG_MTD_CFI_B1 is not set -CONFIG_MTD_CFI_B2=y -CONFIG_MTD_CFI_B4=y -# CONFIG_MTD_CFI_B8 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set -# CONFIG_MTD_JEDEC is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -CONFIG_MTD_IPAQ=y -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_CDB89712 is not set -# CONFIG_MTD_SA1100 is not set -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_IQ80310 is not set -# CONFIG_MTD_LUBBOCK is not set -# CONFIG_MTD_EPXA10DB is not set -# CONFIG_MTD_FORTUNET is not set -# CONFIG_MTD_AUTCPU12 is not set -# CONFIG_MTD_EDB7312 is not set -# CONFIG_MTD_H720X is not set -# CONFIG_MTD_IMPA7 is not set -# CONFIG_MTD_CEIVA is not set -# CONFIG_MTD_PCI is not set -# CONFIG_MTD_PCMCIA is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -CONFIG_MTD_MTDRAM=m -CONFIG_MTDRAM_TOTAL_SIZE=4096 -CONFIG_MTDRAM_ERASE_SIZE=128 -CONFIG_MTD_BLKMTD=m - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -# CONFIG_MTD_DOCPROBE is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -CONFIG_NVRD=m - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -CONFIG_BLK_DEV_LVM=m -CONFIG_BLK_DEV_DM=m - -# -# Networking options -# -CONFIG_PACKET=m -CONFIG_PACKET_MMAP=y -# CONFIG_NETLINK_DEV is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -# CONFIG_IP_NF_AMANDA is not set -# CONFIG_IP_NF_TFTP is not set -CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_QUEUE is not set -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -# CONFIG_IP_NF_MATCH_PKTTYPE is not set -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -# CONFIG_IP_NF_MATCH_RECENT is not set -# CONFIG_IP_NF_MATCH_ECN is not set -# CONFIG_IP_NF_MATCH_DSCP is not set -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -# CONFIG_IP_NF_MATCH_HELPER is not set -CONFIG_IP_NF_MATCH_STATE=m -# CONFIG_IP_NF_MATCH_CONNTRACK is not set -# CONFIG_IP_NF_MATCH_UNCLEAN is not set -# CONFIG_IP_NF_MATCH_OWNER is not set -CONFIG_IP_NF_FILTER=m -# CONFIG_IP_NF_TARGET_REJECT is not set -# CONFIG_IP_NF_TARGET_MIRROR is not set -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_NAT_LOCAL is not set -# CONFIG_IP_NF_NAT_SNMP_BASIC is not set -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -# CONFIG_IP_NF_TARGET_ECN is not set -# CONFIG_IP_NF_TARGET_DSCP is not set -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -# CONFIG_IP_NF_ARPTABLES is not set -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -# CONFIG_IP_NF_COMPAT_IPFWADM is not set -CONFIG_IPV6=m -CONFIG_IPV6_SUBTREES=y -CONFIG_IPV6_TUNNEL=m -CONFIG_IPV6_MOBILITY=m -CONFIG_IPV6_MOBILITY_MN=m -# CONFIG_IPV6_MOBILITY_HA is not set -CONFIG_IPV6_MOBILITY_DEBUG=y - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -# CONFIG_IP6_NF_MATCH_RT is not set -# CONFIG_IP6_NF_MATCH_OPTS is not set -# CONFIG_IP6_NF_MATCH_FRAG is not set -# CONFIG_IP6_NF_MATCH_HL is not set -CONFIG_IP6_NF_MATCH_MULTIPORT=m -# CONFIG_IP6_NF_MATCH_OWNER is not set -CONFIG_IP6_NF_MATCH_MARK=m -# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set -# CONFIG_IP6_NF_MATCH_AHESP is not set -# CONFIG_IP6_NF_MATCH_LENGTH is not set -# CONFIG_IP6_NF_MATCH_EUI64 is not set -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_IPSEC=m - -# -# IPSec options (FreeS/WAN) -# -CONFIG_KLIPS_AUTH_HMAC_MD5=y -CONFIG_KLIPS_AUTH_HMAC_SHA1=y -CONFIG_KLIPS_ENC_3DES=y - -# -# ESP always enabled with tunnel mode -# -CONFIG_KLIPS_IPCOMP=y -CONFIG_KLIPS_DEBUG=y - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -# CONFIG_NET_ETHERNET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -# CONFIG_PPP_MPPE is not set -# CONFIG_PPPOE is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -# CONFIG_STRIP is not set -# CONFIG_WAVELAN is not set -# CONFIG_ARLAN is not set -# CONFIG_AIRONET4500 is not set -# CONFIG_AIRONET4500_NONCS is not set -# CONFIG_AIRONET4500_PROC is not set -# CONFIG_AIRO is not set -# CONFIG_HERMES is not set -# CONFIG_SPECTRUM24T is not set - -# -# Wireless Pcmcia cards support -# -# CONFIG_PCMCIA_HERMES is not set -# CONFIG_AIRO_CS is not set -# CONFIG_WVLAN_CS is not set -# CONFIG_MWVLAN_CS is not set -# CONFIG_HOSTAP is not set -# CONFIG_HOSTAP_CS is not set -CONFIG_NET_WIRELESS=y -CONFIG_ATMELWLAN=y -# CONFIG_ATMELWLAN_USB_503A_RFMD is not set -CONFIG_ATMELWLAN_PCMCIA_502A=m -CONFIG_ATMELWLAN_PCMCIA_3COM=m -CONFIG_ATMELWLAN_PCMCIA_502AD=m -CONFIG_ATMELWLAN_PCMCIA_502AE=m -CONFIG_ATMELWLAN_PCMCIA_504=m - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_AXNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -# CONFIG_ARCNET_COM20020_CS is not set -# CONFIG_PCMCIA_IBMTR is not set -CONFIG_NET_PCMCIA_RADIO=y -CONFIG_PCMCIA_RAYCS=m -CONFIG_PCMCIA_NETWAVE=m -CONFIG_PCMCIA_WAVELAN=m -# CONFIG_AIRONET4500_CS is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -CONFIG_IRDA=m - -# -# IrDA protocols -# -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y - -# -# IrDA options -# -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -CONFIG_IRDA_DEBUG=y - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m - -# -# Dongle support -# -# CONFIG_DONGLE is not set - -# -# FIR device drivers -# -# CONFIG_USB_IRDA is not set -# CONFIG_NSC_FIR is not set -# CONFIG_WINBOND_FIR is not set -# CONFIG_TOSHIBA_FIR is not set -# CONFIG_SMC_IRCC_FIR is not set -# CONFIG_ALI_FIR is not set -# CONFIG_VLSI_FIR is not set -CONFIG_SA1100_FIR=m - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=m - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=m - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=m -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set -# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set -# CONFIG_BLK_DEV_IDEDISK_IBM is not set -# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set -# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set -# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set -# CONFIG_BLK_DEV_IDEDISK_WD is not set -# CONFIG_BLK_DEV_COMMERIAL is not set -# CONFIG_BLK_DEV_TIVO is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=m -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_IDE_CHIPSETS is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_DMA_NONPCI is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set - -# -# SCSI support -# -CONFIG_SCSI=m - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=m -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_DEBUG is not set - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_PCMCIA=y -# CONFIG_PCMCIA_AHA152X is not set -# CONFIG_PCMCIA_FDOMAIN is not set -# CONFIG_PCMCIA_NINJA_SCSI is not set -# CONFIG_PCMCIA_QLOGIC is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m -CONFIG_INPUT_UINPUT=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=m -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_ANAKIN is not set -# CONFIG_SERIAL_ANAKIN_CONSOLE is not set -# CONFIG_SERIAL_S3C2410 is not set -# CONFIG_SERIAL_S3C2410_CONSOLE is not set -# CONFIG_SERIAL_AMBA is not set -# CONFIG_SERIAL_AMBA_CONSOLE is not set -# CONFIG_SERIAL_CLPS711X is not set -# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE is not set -# CONFIG_SERIAL_UART00 is not set -# CONFIG_SERIAL_UART00_CONSOLE is not set -CONFIG_SERIAL_SA1100=y -CONFIG_SERIAL_SA1100_CONSOLE=y -CONFIG_SA1100_DEFAULT_BAUDRATE=115200 -CONFIG_SERIAL_H3800_ASIC=m -# CONFIG_SERIAL_SIR_PXA is not set -# CONFIG_SERIAL_8250 is not set -# CONFIG_SERIAL_8250_CONSOLE is not set -# CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SERIAL_8250_MANY_PORTS is not set -# CONFIG_SERIAL_8250_SHARE_IRQ is not set -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_HUB6 is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 -CONFIG_NEWTONKBD=m -CONFIG_SA1100_PROFILER=m - -# -# Compaq iPAQ H3600 support -# -CONFIG_TOUCHSCREEN_H3600=m -CONFIG_H3600_BACKPAQ_FPGA=m -CONFIG_H3600_BACKPAQ_ACCEL=m -CONFIG_H3600_BACKPAQ_GASGAUGE=m -CONFIG_H3600_BACKPAQ_SRAM=m -CONFIG_H3600_BACKPAQ_AUDIO=m -CONFIG_H3600_STOWAWAY=m -CONFIG_H3800_MICROKBD=m -CONFIG_SA1100_LIRC=m -# CONFIG_H5400_BUZZER is not set -# CONFIG_H5400_FSI is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# L3 serial bus support -# -CONFIG_L3=y -CONFIG_L3_ALGOBIT=y -CONFIG_L3_BIT_SA1100_GPIO=y - -# -# Other L3 adapters -# -# CONFIG_L3_S3C2410 is not set -# CONFIG_L3_SA1111 is not set -CONFIG_L3_BACKPAQ=m -CONFIG_BIT_SA1100_GPIO=y - -# -# SPI support -# -# CONFIG_SPI is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=m -# CONFIG_PSMOUSE is not set -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set -# CONFIG_MK712_MOUSE is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_INPUT_NS558 is not set -# CONFIG_INPUT_LIGHTNING is not set -# CONFIG_INPUT_PCIGAME is not set -# CONFIG_INPUT_CS461X is not set -# CONFIG_INPUT_EMU10K1 is not set -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m - -# -# Joysticks -# -# CONFIG_INPUT_ANALOG is not set -# CONFIG_INPUT_A3D is not set -# CONFIG_INPUT_ADI is not set -# CONFIG_INPUT_COBRA is not set -# CONFIG_INPUT_GF2K is not set -# CONFIG_INPUT_GRIP is not set -# CONFIG_INPUT_INTERACT is not set -# CONFIG_INPUT_TMDC is not set -# CONFIG_INPUT_SIDEWINDER is not set -# CONFIG_INPUT_IFORCE_USB is not set -# CONFIG_INPUT_IFORCE_232 is not set -# CONFIG_INPUT_WARRIOR is not set -# CONFIG_INPUT_MAGELLAN is not set -# CONFIG_INPUT_SPACEORB is not set -# CONFIG_INPUT_SPACEBALL is not set -# CONFIG_INPUT_STINGER is not set -# CONFIG_INPUT_DB9 is not set -# CONFIG_INPUT_GAMECON is not set -# CONFIG_INPUT_TURBOGRAFX is not set -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -# CONFIG_ALIM7101_WDT is not set -# CONFIG_SC520_WDT is not set -# CONFIG_PCWATCHDOG is not set -# CONFIG_21285_WATCHDOG is not set -# CONFIG_977_WATCHDOG is not set -CONFIG_SA1100_WATCHDOG=m -# CONFIG_PXA_WATCHDOG is not set -# CONFIG_OMAHA_WATCHDOG is not set -# CONFIG_EUROTECH_WDT is not set -# CONFIG_IB700_WDT is not set -# CONFIG_WAFER_WDT is not set -# CONFIG_I810_TCO is not set -# CONFIG_MIXCOMWD is not set -# CONFIG_60XX_WDT is not set -# CONFIG_SC1200_WDT is not set -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_W83877F_WDT is not set -# CONFIG_WDT is not set -# CONFIG_WDTPCI is not set -# CONFIG_MACHZ_WDT is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -CONFIG_SA1100_RTC=m -# CONFIG_PXA_RTC_HACK is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# PCMCIA character devices -# -CONFIG_PCMCIA_SERIAL_CS=m -# CONFIG_PCMCIA_MOBILISCAN_CS is not set -# CONFIG_AXIM_KEY_FIX is not set - -# -# Multimedia devices -# -CONFIG_MEDIA=m -CONFIG_VIDEO_DEV=m -CONFIG_V4L2_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -# CONFIG_I2C_PARPORT is not set - -# -# Video Adapters -# -# CONFIG_VIDEO_PMS is not set -# CONFIG_VIDEO_CPIA is not set -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_ZORAN_BUZ is not set -# CONFIG_VIDEO_ZORAN_DC10 is not set -# CONFIG_VIDEO_ZORAN_LML33 is not set -# CONFIG_VIDEO_ZR36120 is not set -# CONFIG_VIDEO_MEYE is not set -# CONFIG_VIDEO_CYBERPRO is not set -CONFIG_VIDEO_H3600_BACKPAQ=m -# CONFIG_VIDEO_HAWKEYE is not set - -# -# Video for Linux 2 (V4L2) -# -CONFIG_VIDEO_WINNOV_CS=m - -# -# Radio Adapters -# -# CONFIG_RADIO_CADET is not set -# CONFIG_RADIO_RTRACK is not set -# CONFIG_RADIO_RTRACK2 is not set -# CONFIG_RADIO_AZTECH is not set -# CONFIG_RADIO_GEMTEK is not set -# CONFIG_RADIO_GEMTEK_PCI is not set -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_MAESTRO is not set -# CONFIG_RADIO_MIROPCM20 is not set -# CONFIG_RADIO_MIROPCM20_RDS is not set -# CONFIG_RADIO_SF16FMI is not set -# CONFIG_RADIO_TERRATEC is not set -# CONFIG_RADIO_TRUST is not set -# CONFIG_RADIO_TYPHOON is not set -# CONFIG_RADIO_ZOLTRIX is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -CONFIG_CRAMFS=y -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=m -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DRIVERFS_FS is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=m -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_UTF8=m - -# -# Console drivers -# -CONFIG_PC_KEYMAP=y -# CONFIG_VGA_CONSOLE is not set - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_ACORN is not set -# CONFIG_FB_ANAKIN is not set -# CONFIG_FB_CLPS711X is not set -# CONFIG_FB_S3C2410 is not set -CONFIG_FB_SA1100=y -# CONFIG_FB_EPSON1356 is not set -# CONFIG_FB_MQ200 is not set -# CONFIG_FB_PXA is not set -# CONFIG_FB_MQ1100 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_VIRTUAL is not set -CONFIG_FBCON_ADVANCED=y -# CONFIG_FBCON_MFB is not set -# CONFIG_FBCON_CFB2 is not set -CONFIG_FBCON_CFB4=y -# CONFIG_FBCON_CFB8 is not set -CONFIG_FBCON_CFB16=y -# CONFIG_FBCON_CFB24 is not set -# CONFIG_FBCON_CFB32 is not set -# CONFIG_FBCON_AFB is not set -# CONFIG_FBCON_ILBM is not set -# CONFIG_FBCON_IPLAN2P2 is not set -# CONFIG_FBCON_IPLAN2P4 is not set -# CONFIG_FBCON_IPLAN2P8 is not set -# CONFIG_FBCON_MAC is not set -# CONFIG_FBCON_VGA_PLANES is not set -# CONFIG_FBCON_VGA is not set -# CONFIG_FBCON_HGA is not set -# CONFIG_FBCON_NO_LOGO is not set -CONFIG_FBCON_FONTWIDTH8_ONLY=y -CONFIG_FBCON_FONTS=y -CONFIG_FONT_8x8=y -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set - -# -# Sound -# -CONFIG_SOUND=y -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_MIDI_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_MAESTRO3 is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_RME96XX is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -# CONFIG_MIDI_VIA82CXXX is not set -CONFIG_SOUND_SA1100=m -CONFIG_SOUND_UDA1341=m -# CONFIG_SOUND_SA1100_MONO is not set -# CONFIG_SOUND_ASSABET_UDA1341 is not set -CONFIG_SOUND_H3600_UDA1341=m -# CONFIG_SOUND_PANGOLIN_UDA1341 is not set -# CONFIG_SOUND_SA1111_UDA1341 is not set -# CONFIG_SOUND_SA1100SSP is not set -# CONFIG_SOUND_OSS is not set -# CONFIG_SOUND_VIDC is not set -# CONFIG_SOUND_WAVEARTIST is not set -# CONFIG_SOUND_PXA_AC97 is not set -# CONFIG_SOUND_TVMIXER is not set - -# -# Multimedia Capabilities Port drivers -# -# CONFIG_MCP is not set -# CONFIG_MCP_SA1100 is not set -# CONFIG_MCP_UCB1200 is not set -# CONFIG_MCP_UCB1200_AUDIO is not set -# CONFIG_MCP_UCB1200_TS is not set -# CONFIG_MCP_UCB1400_TS is not set - -# -# Console Switches -# -# CONFIG_SWITCHES is not set - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -# CONFIG_USB_DEVICEFS is not set -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_LONG_TIMEOUT is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set -# CONFIG_USB_OHCI_SA1111 is not set -# CONFIG_USB_OHCI_H5400 is not set -# CONFIG_USB_OHCI_S3C2410 is not set -CONFIG_USB_SL811HS=m - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_BLUETOOTH is not set -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_ACM is not set -CONFIG_USB_PRINTER=m - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_WACOM is not set - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# -CONFIG_USB_IBMCAM=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -# CONFIG_USB_DSBR is not set -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -CONFIG_USB_CDCETHER=m -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_IPAQ is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_KLSI is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_XIRCOM is not set -# CONFIG_USB_SERIAL_OMNINET is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_BRLVGER is not set - -# -# Linux As Bootldr Modules -# -# CONFIG_BIG_KERNEL is not set -# CONFIG_USE_DATE_CODE is not set -# CONFIG_YMODEM is not set -# CONFIG_LAB_DUMMY is not set -# CONFIG_LAB_CRC is not set -# CONFIG_LAB_YMODEM is not set -# CONFIG_LAB_MTD is not set -# CONFIG_LAB_COPY is not set -# CONFIG_LAB_COPY_YMODEM is not set -# CONFIG_LAB_COPY_FLASH is not set -# CONFIG_LAB_COPY_FS is not set -# CONFIG_LAB_COPY_WRAPPER is not set - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -# CONFIG_BLUEZ_HCIUSB is not set -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -# CONFIG_BLUEZ_HCIUART_BCSP_TXCRC is not set -# CONFIG_BLUEZ_HCIBFUSB is not set -CONFIG_BLUEZ_HCIDTL1=m -CONFIG_BLUEZ_HCIBT3C=m -CONFIG_BLUEZ_HCIBLUECARD=m -CONFIG_BLUEZ_HCIBTUART=m -# CONFIG_BLUEZ_HCIVHCI is not set - -# -# Kernel hacking -# -CONFIG_FRAME_POINTER=y -# CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_INFO is not set -# CONFIG_NO_PGT_CACHE is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -CONFIG_DEBUG_ERRORS=y -# CONFIG_DEBUG_LL is not set -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh37.4/defconfig-ipaqsa b/linux/handhelds-sa-2.4.19-rmk6-pxa1-hh37.4/defconfig-ipaqsa deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/handhelds-sa-2.6/defconfig-jornada56x b/linux/handhelds-sa-2.6/defconfig-jornada56x deleted file mode 100644 index ebc9a88f2c..0000000000 --- a/linux/handhelds-sa-2.6/defconfig-jornada56x +++ /dev/null @@ -1,877 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_ARM=y -CONFIG_MMU=y -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y -CONFIG_BROKEN_ON_SMP=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_HOTPLUG=y -# CONFIG_IKCONFIG is not set -# CONFIG_MINIMAL_OOPS is not set -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODULE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# System Type -# -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP3XX is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_RPC is not set -CONFIG_ARCH_SA1100=y -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_LH7A40X is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE_PB is not set - -# -# SA11x0 Implementations -# -# CONFIG_SA1100_ASSABET is not set -# CONFIG_SA1100_ADSBITSY is not set -# CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_CERF is not set -# CONFIG_SA1100_COLLIE is not set -# CONFIG_SA1100_H3100 is not set -# CONFIG_SA1100_H3600 is not set -# CONFIG_SA1100_H3800 is not set -# CONFIG_SA1100_EXTENEX1 is not set -# CONFIG_SA1100_FLEXANET is not set -# CONFIG_SA1100_FREEBIRD is not set -# CONFIG_SA1100_GRAPHICSCLIENT is not set -# CONFIG_SA1100_GRAPHICSMASTER is not set -# CONFIG_SA1100_BADGE4 is not set -CONFIG_SA1100_JORNADA56X=y -# CONFIG_SA1100_JORNADA720 is not set -# CONFIG_SA1100_HACKKIT is not set -# CONFIG_SA1100_HUW_WEBPANEL is not set -# CONFIG_SA1100_ITSY is not set -# CONFIG_SA1100_LART is not set -# CONFIG_SA1100_NANOENGINE is not set -# CONFIG_SA1100_OMNIMETER is not set -# CONFIG_SA1100_PANGOLIN is not set -# CONFIG_SA1100_PLEB is not set -# CONFIG_SA1100_PT_SYSTEM3 is not set -# CONFIG_SA1100_SHANNON is not set -# CONFIG_SA1100_SHERMAN is not set -# CONFIG_SA1100_SIMPAD is not set -# CONFIG_SA1100_PFS168 is not set -# CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_XP860 is not set -# CONFIG_SA1100_YOPY is not set -# CONFIG_SA1100_STORK is not set -# CONFIG_SA1100_SSP is not set -CONFIG_SA1100_USB=y -CONFIG_SA1100_USB_NETLINK=y -# CONFIG_SA1100_USB_CHAR is not set - -# -# Linux As Bootloader -# -# CONFIG_LAB is not set - -# -# Processor Type -# -CONFIG_CPU_32=y -CONFIG_CPU_SA1100=y -CONFIG_CPU_32v4=y -CONFIG_CPU_ABRT_EV4=y -CONFIG_CPU_CACHE_V4WB=y -CONFIG_CPU_TLB_V4WB=y -CONFIG_CPU_MINICACHE=y - -# -# Processor Features -# -# CONFIG_ARM_FASTCALL is not set - -# -# Compaq/iPAQ Options -# - -# -# General setup -# -CONFIG_DISCONTIGMEM=y -CONFIG_ISA=y -# CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZBOOT_ROM_BSS=0 -# CONFIG_CPU_FREQ is not set - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=y -# CONFIG_PCMCIA_DEBUG is not set -# CONFIG_I82365 is not set -# CONFIG_TCIC is not set -CONFIG_PCMCIA_SA1100=y - -# -# At least one math emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set -# CONFIG_FPE_FASTFPE is not set -# CONFIG_VFP is not set -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_AOUT=y -CONFIG_BINFMT_MISC=y - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m -# CONFIG_SOC_DEVICE is not set -# CONFIG_DOCKING_HOTPLUG is not set -CONFIG_PM=y -CONFIG_PREEMPT=y -CONFIG_APM=y -# CONFIG_ARTHUR is not set -CONFIG_CMDLINE="" -# CONFIG_LEDS is not set -CONFIG_ALIGNMENT_TRAP=y - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -CONFIG_MTD_DEBUG=y -CONFIG_MTD_DEBUG_VERBOSE=3 -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_ARM_INTEGRATOR is not set -CONFIG_MTD_SA1100=y -# CONFIG_MTD_EDB7312 is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=m -# CONFIG_BLK_DEV_RAM is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -# CONFIG_NETLINK_DEV is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set - -# -# IP: Virtual Server Configuration -# -# CONFIG_IP_VS is not set -# CONFIG_IPV6 is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set - -# -# IP: Netfilter Configuration -# -# CONFIG_IP_NF_CONNTRACK is not set -# CONFIG_IP_NF_QUEUE is not set -# CONFIG_IP_NF_IPTABLES is not set -# CONFIG_IP_NF_ARPTABLES is not set -# CONFIG_IP_NF_COMPAT_IPCHAINS is not set -# CONFIG_IP_NF_COMPAT_IPFWADM is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -CONFIG_BT=m -# CONFIG_BT_L2CAP is not set -# CONFIG_BT_SCO is not set - -# -# Bluetooth device drivers -# -# CONFIG_BT_HCIUART is not set -CONFIG_BT_HCIDTL1=m -CONFIG_BT_HCIBT3C=m -CONFIG_BT_HCIBLUECARD=m -CONFIG_BT_HCIBTUART=m -# CONFIG_BT_HCIVHCI is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set - -# -# Ethernet (10 or 100Mbit) -# -# CONFIG_NET_ETHERNET is not set -CONFIG_MII=m - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# -# CONFIG_TR is not set - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y - -# -# Obsolete Wireless cards support (pre-802.11) -# -# CONFIG_STRIP is not set -CONFIG_ARLAN=m -CONFIG_WAVELAN=m -CONFIG_PCMCIA_WAVELAN=m -# CONFIG_PCMCIA_NETWAVE is not set - -# -# Wireless 802.11 Frequency Hopping cards support -# -# CONFIG_PCMCIA_RAYCS is not set - -# -# Wireless 802.11b ISA/PCI cards support -# -CONFIG_HERMES=m -# CONFIG_ATMEL is not set - -# -# Wireless 802.11b Pcmcia/Cardbus cards support -# -CONFIG_PCMCIA_HERMES=m -CONFIG_AIRO_CS=m -# CONFIG_PCMCIA_WL3501 is not set -CONFIG_NET_WIRELESS=y -# CONFIG_HOSTAP is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -# CONFIG_PCMCIA_AXNET is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -CONFIG_PPP=m -# CONFIG_PPP_MULTILINK is not set -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -# CONFIG_PPPOE is not set -# CONFIG_SLIP is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=m -CONFIG_BLK_DEV_IDE=m - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_IDE_SATA is not set -CONFIG_BLK_DEV_IDEDISK=m -# CONFIG_IDEDISK_MULTI_MODE is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_IDE_GENERIC=m -# CONFIG_IDE_ARM is not set -# CONFIG_IDE_CHIPSETS is not set -# CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support -# - -# -# I2O device support -# - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=640 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240 -# CONFIG_INPUT_JOYDEV is not set -CONFIG_INPUT_TSDEV=y -CONFIG_INPUT_TSDEV_SCREEN_X=240 -CONFIG_INPUT_TSDEV_SCREEN_Y=320 -# CONFIG_INPUT_TSLIBDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set -# CONFIG_SERIO_I8042 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -CONFIG_INPUT_TOUCHSCREEN=y -# CONFIG_TOUCHSCREEN_GUNZE is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -# CONFIG_SERIAL_DZ is not set -CONFIG_SERIAL_SA1100=y -CONFIG_SERIAL_SA1100_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# L3 serial bus support -# -# CONFIG_L3 is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set -CONFIG_SA1100_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# PCMCIA character devices -# -# CONFIG_SYNCLINK_CS is not set -# CONFIG_RAW_DRIVER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=m -# CONFIG_EXT2_FS_XATTR is not set -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_REISERFS_FS_XATTR is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=y - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=m -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_SYSFS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -CONFIG_DEVFS_DEBUG=y -# CONFIG_DEVPTS_FS_XATTR is not set -# CONFIG_TMPFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set -CONFIG_JFFS2_ZLIB=y -CONFIG_JFFS2_RTIME=y -# CONFIG_JFFS2_RUBIN is not set -CONFIG_CRAMFS=m -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=m -# CONFIG_RPCSEC_GSS_KRB5 is not set -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set - -# -# Native Language Support -# -CONFIG_NLS=m -CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ASCII is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Profiling support -# -# CONFIG_PROFILING is not set - -# -# Graphics support -# -CONFIG_FB=y -CONFIG_FB_MODES=y -CONFIG_LCD_CLASS_DEVICE=y -CONFIG_LCD_DEVICE=y -CONFIG_BACKLIGHT_CLASS_DEVICE=y -CONFIG_BACKLIGHT_DEVICE=y -CONFIG_FB_SA1100=y -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FONTS=y -# CONFIG_FONT_8x8 is not set -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set -CONFIG_FONT_MINI_4x6=y -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set - -# -# Logo configuration -# -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -CONFIG_LOGO_LINUX_CLUT224=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# Misc devices -# - -# -# SoC drivers -# -# CONFIG_BATTERY_MONITOR is not set - -# -# USB support -# - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# Kernel hacking -# -CONFIG_FRAME_POINTER=y -# CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -CONFIG_CRC_CCITT=m -CONFIG_CRC32=y -# CONFIG_LIBCRC32C is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/linux/handhelds-sa-2.6_cvs.bb b/linux/handhelds-sa-2.6_cvs.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/handhelds-sa_2.4.19-rmk6-pxa1-hh36.12.bb b/linux/handhelds-sa_2.4.19-rmk6-pxa1-hh36.12.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/handhelds-sa_2.4.19-rmk6-pxa1-hh37.1.bb b/linux/handhelds-sa_2.4.19-rmk6-pxa1-hh37.1.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/handhelds-sa_2.4.19-rmk6-pxa1-hh37.4.bb b/linux/handhelds-sa_2.4.19-rmk6-pxa1-hh37.4.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/ipod_2.4.24-ipod0.bb b/linux/ipod_2.4.24-ipod0.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-bast-2.4.25-vrs1-bast1/defconfig b/linux/linux-bast-2.4.25-vrs1-bast1/defconfig deleted file mode 100644 index 1dc6f19154..0000000000 --- a/linux/linux-bast-2.4.25-vrs1-bast1/defconfig +++ /dev/null @@ -1,1115 +0,0 @@ -# -# Automatically generated by make menuconfig: don't edit -# -CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_GENERIC_BUST_SPINLOCK is not set -# CONFIG_GENERIC_ISA_DMA is not set - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -# CONFIG_KMOD is not set - -# -# System Type -# -# CONFIG_ARCH_ANAKIN is not set -# CONFIG_ARCH_ARCA5K is not set -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_OMAHA is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_MX1ADS is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_RISCSTATION is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_SHARK is not set -CONFIG_ARCH_BAST=y -# CONFIG_ARCH_AT91RM9200 is not set - -# -# Archimedes/A5000 Implementations -# -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set - -# -# Footbridge Implementations -# -# CONFIG_ARCH_CATS is not set -# CONFIG_ARCH_PERSONAL_SERVER is not set -# CONFIG_ARCH_EBSA285_ADDIN is not set -# CONFIG_ARCH_EBSA285_HOST is not set -# CONFIG_ARCH_NETWINDER is not set - -# -# SA11x0 Implementations -# -# CONFIG_SA1100_ACCELENT is not set -# CONFIG_SA1100_ASSABET is not set -# CONFIG_ASSABET_NEPONSET is not set -# CONFIG_SA1100_ADSAGC is not set -# CONFIG_SA1100_ADSBITSY is not set -# CONFIG_SA1100_ADSBITSYPLUS is not set -# CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_CEP is not set -# CONFIG_SA1100_CERF is not set -# CONFIG_SA1100_H3100 is not set -# CONFIG_SA1100_H3600 is not set -# CONFIG_SA1100_H3800 is not set -# CONFIG_SA1100_H3XXX is not set -# CONFIG_H3600_SLEEVE is not set -# CONFIG_SA1100_EXTENEX1 is not set -# CONFIG_SA1100_FLEXANET is not set -# CONFIG_SA1100_FREEBIRD is not set -# CONFIG_SA1100_FRODO is not set -# CONFIG_SA1100_GRAPHICSCLIENT is not set -# CONFIG_SA1100_GRAPHICSMASTER is not set -# CONFIG_SA1100_HACKKIT is not set -# CONFIG_SA1100_BADGE4 is not set -# CONFIG_SA1100_JORNADA720 is not set -# CONFIG_SA1100_HUW_WEBPANEL is not set -# CONFIG_SA1100_ITSY is not set -# CONFIG_SA1100_LART is not set -# CONFIG_SA1100_NANOENGINE is not set -# CONFIG_SA1100_OMNIMETER is not set -# CONFIG_SA1100_PANGOLIN is not set -# CONFIG_SA1100_PLEB is not set -# CONFIG_SA1100_PT_SYSTEM3 is not set -# CONFIG_SA1100_SHANNON is not set -# CONFIG_SA1100_SHERMAN is not set -# CONFIG_SA1100_SIMPAD is not set -# CONFIG_SA1100_SIMPUTER is not set -# CONFIG_SA1100_PFS168 is not set -# CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_XP860 is not set -# CONFIG_SA1100_YOPY is not set -# CONFIG_SA1100_USB is not set -# CONFIG_SA1100_USB_NETLINK is not set -# CONFIG_SA1100_USB_CHAR is not set -# CONFIG_SA1100_SSP is not set - -# -# AT91RM9200 Implementations -# -# CONFIG_ARCH_AT91RM9200DK is not set - -# -# CLPS711X/EP721X Implementations -# -# CONFIG_ARCH_AUTCPU12 is not set -# CONFIG_ARCH_CDB89712 is not set -# CONFIG_ARCH_CLEP7312 is not set -# CONFIG_ARCH_EDB7211 is not set -# CONFIG_ARCH_FORTUNET is not set -# CONFIG_ARCH_GUIDEA07 is not set -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_EP7211 is not set -# CONFIG_ARCH_EP7212 is not set -# CONFIG_ARCH_ACORN is not set -# CONFIG_PLD is not set -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -# CONFIG_CPU_ARM610 is not set -# CONFIG_CPU_ARM710 is not set -# CONFIG_CPU_ARM720T is not set -# CONFIG_CPU_ARM920T is not set -CONFIG_CPU_ARM920T=y -CONFIG_CPU_S3C2410X=y -# CONFIG_CPU_ARM922T is not set -# CONFIG_CPU_ARM926T is not set -# CONFIG_CPU_ARM1020 is not set -# CONFIG_CPU_ARM1020E is not set -# CONFIG_CPU_ARM1022 is not set -# CONFIG_CPU_ARM1026 is not set -# CONFIG_CPU_SA110 is not set -# CONFIG_CPU_SA1100 is not set -# CONFIG_CPU_32v3 is not set -CONFIG_CPU_32v4=y -# CONFIG_ARM_THUMB is not set -# CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_WRITETHROUGH is not set -# CONFIG_DISCONTIGMEM is not set - -# -# General setup -# -# CONFIG_PCI is not set -CONFIG_ISA=y -# CONFIG_ISA_DMA is not set -# CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZBOOT_ROM_BSS=0 -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set -# CONFIG_FPE_FASTFPE is not set -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=y -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=y -# CONFIG_PM is not set -# CONFIG_ARTHUR is not set -CONFIG_CMDLINE="root=/dev/hda1 ro" -CONFIG_ALIGNMENT_TRAP=y - -# -# Parallel port support -# -CONFIG_PARPORT=y -CONFIG_PARPORT_PC=y -# CONFIG_PARPORT_PC_FIFO is not set -CONFIG_PARPORT_PC_SUPERIO=y -# CONFIG_PARPORT_PC_PCMCIA is not set -# CONFIG_PARPORT_ARC is not set -# CONFIG_PARPORT_IDP is not set -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_IP22 is not set -CONFIG_PARPORT_OTHER=y -CONFIG_PARPORT_1284=y - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -CONFIG_MTD_DEBUG=y -CONFIG_MTD_DEBUG_VERBOSE=1 -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_CONCAT=y -CONFIG_MTD_REDBOOT_PARTS=y -# CONFIG_MTD_CMDLINE_PARTS is not set -CONFIG_MTD_AFS_PARTS=y -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -CONFIG_NFTL=y -CONFIG_NFTL_RW=y - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_CFI_INTELEXT=y -CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_RAM=y -CONFIG_MTD_ROM=y -CONFIG_MTD_ABSENT=y -# CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set -# CONFIG_MTD_JEDEC is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_NORA is not set -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_CDB89712 is not set -# CONFIG_MTD_SA1100 is not set -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_IQ80310 is not set -# CONFIG_MTD_FORTUNET is not set -# CONFIG_MTD_EPXA is not set -# CONFIG_MTD_BAST is not set -# CONFIG_MTD_AUTCPU12 is not set -# CONFIG_MTD_EDB7312 is not set -# CONFIG_MTD_IMPA7 is not set -# CONFIG_MTD_CEIVA is not set -# CONFIG_MTD_PCI is not set -# CONFIG_MTD_PCMCIA is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set -# CONFIG_MTD_DOC1000 is not set -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOCPROBE is not set - -# -# NAND Flash Device Drivers -# -CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_VERIFY_WRITE=y -CONFIG_MTD_NAND_IDS=y - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_CISS_MONITOR_THREAD is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_NBD=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -# CONFIG_BLK_STATS is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -# CONFIG_BLK_DEV_LVM is not set - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -CONFIG_NETFILTER=y -CONFIG_NETFILTER_DEBUG=y -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_IP_PNP_RARP=y -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set - -# -# IP: Netfilter Configuration -# -# CONFIG_IP_NF_CONNTRACK is not set -# CONFIG_IP_NF_QUEUE is not set -# CONFIG_IP_NF_IPTABLES is not set -# CONFIG_IP_NF_ARPTABLES is not set -# CONFIG_IP_NF_COMPAT_IPCHAINS is not set -# CONFIG_IP_NF_COMPAT_IPFWADM is not set - -# -# IP: Virtual Server Configuration -# -# CONFIG_IP_VS is not set -# CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_ARM_AM79C961A is not set -# CONFIG_ARM_CIRRUS is not set -CONFIG_NE2K_BAST=y -CONFIG_DM9000_BAST=y -# CONFIG_SUNLANCE is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set -# CONFIG_HP100 is not set -CONFIG_NET_ISA=y -# CONFIG_E2100 is not set -# CONFIG_EWRK3 is not set -# CONFIG_EEXPRESS is not set -# CONFIG_EEXPRESS_PRO is not set -# CONFIG_HPLAN_PLUS is not set -# CONFIG_HPLAN is not set -# CONFIG_LP486E is not set -# CONFIG_ETH16I is not set -# CONFIG_NE2000 is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -# CONFIG_PPP is not set -CONFIG_SLIP=y -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -CONFIG_SLIP_MODE_SLIP6=y - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -CONFIG_IRDA=y -CONFIG_IRLAN=y -# CONFIG_IRNET is not set -CONFIG_IRCOMM=y -CONFIG_IRDA_ULTRA=y -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -CONFIG_IRDA_DEBUG=y - -# -# Infrared-port device drivers -# -# CONFIG_IRTTY_SIR is not set -# CONFIG_IRPORT_SIR is not set -# CONFIG_DONGLE is not set -# CONFIG_USB_IRDA is not set -CONFIG_NSC_FIR=y -# CONFIG_WINBOND_FIR is not set -# CONFIG_TOSHIBA_OLD is not set -# CONFIG_TOSHIBA_FIR is not set -# CONFIG_SMC_IRCC_FIR is not set -# CONFIG_ALI_FIR is not set -# CONFIG_VLSI_FIR is not set -# CONFIG_VIA_IRCC_FIR is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECS is not set -CONFIG_BLK_DEV_IDECD=y -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -CONFIG_BLK_DEV_IDE_BAST=y -# CONFIG_IDE_CHIPSETS is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_DMA_NONPCI is not set -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set -# CONFIG_BLK_DEV_ATARAID_SII is not set - -# -# SCSI support -# -# CONFIG_SCSI is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input core support -# -CONFIG_INPUT=y -CONFIG_INPUT_KEYBDEV=y -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=y -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_UINPUT is not set -# CONFIG_INPUT_MX1TS is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set -CONFIG_DUMMY_KEYB=y - -# -# Serial drivers -# -# CONFIG_SERIAL_ANAKIN is not set -# CONFIG_SERIAL_ANAKIN_CONSOLE is not set -# CONFIG_SERIAL_AMBA is not set -# CONFIG_SERIAL_AMBA_CONSOLE is not set -# CONFIG_SERIAL_CLPS711X is not set -# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE is not set -# CONFIG_SERIAL_UART00 is not set -# CONFIG_SERIAL_UART00_CONSOLE is not set -# CONFIG_SERIAL_SA1100 is not set -# CONFIG_SERIAL_SA1100_CONSOLE is not set -# CONFIG_SERIAL_OMAHA is not set -# CONFIG_SERIAL_OMAHA_CONSOLE is not set -# CONFIG_SERIAL_AT91 is not set -# CONFIG_SERIAL_AT91_CONSOLE is not set -CONFIG_SERIAL_S3C2410X=y -CONFIG_SERIAL_S3C2410X_CONSOLE=y -# CONFIG_SERIAL_8250 is not set -# CONFIG_SERIAL_8250_CONSOLE is not set -# CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SERIAL_8250_MANY_PORTS is not set -# CONFIG_SERIAL_8250_SHARE_IRQ is not set -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_HUB6 is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 -CONFIG_PRINTER=y -# CONFIG_LP_CONSOLE is not set -CONFIG_PPDEV=y -# CONFIG_TIPAR is not set - -# -# I2C support -# -CONFIG_I2C=y -CONFIG_I2C_ALGOBIT=y -CONFIG_I2C_PHILIPSPAR=y -# CONFIG_I2C_ELV is not set -# CONFIG_I2C_VELLEMAN is not set -# CONFIG_SCx200_I2C is not set -# CONFIG_I2C_GUIDE is not set -CONFIG_I2C_S3C2410BIT=y -# CONFIG_SCx200_ACB is not set -# CONFIG_I2C_ALGOPCF is not set -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_PROC=y -# CONFIG_I2C_DS1307 is not set - -# -# L3 serial bus support -# -# CONFIG_L3 is not set -# CONFIG_L3_ALGOBIT is not set -# CONFIG_L3_BIT_SA1100_GPIO is not set -# CONFIG_L3_SA1111 is not set -# CONFIG_BIT_SA1100_GPIO is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set -# CONFIG_MK712_MOUSE is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_INPUT_NS558 is not set -# CONFIG_INPUT_LIGHTNING is not set -# CONFIG_INPUT_PCIGAME is not set -# CONFIG_INPUT_CS461X is not set -# CONFIG_INPUT_EMU10K1 is not set -# CONFIG_INPUT_SERIO is not set -# CONFIG_INPUT_SERPORT is not set -# CONFIG_INPUT_ANALOG is not set -# CONFIG_INPUT_A3D is not set -# CONFIG_INPUT_ADI is not set -# CONFIG_INPUT_COBRA is not set -# CONFIG_INPUT_GF2K is not set -# CONFIG_INPUT_GRIP is not set -# CONFIG_INPUT_INTERACT is not set -# CONFIG_INPUT_TMDC is not set -# CONFIG_INPUT_SIDEWINDER is not set -# CONFIG_INPUT_IFORCE_USB is not set -# CONFIG_INPUT_IFORCE_232 is not set -# CONFIG_INPUT_WARRIOR is not set -# CONFIG_INPUT_MAGELLAN is not set -# CONFIG_INPUT_SPACEORB is not set -# CONFIG_INPUT_SPACEBALL is not set -# CONFIG_INPUT_STINGER is not set -# CONFIG_INPUT_DB9 is not set -# CONFIG_INPUT_GAMECON is not set -# CONFIG_INPUT_TURBOGRAFX is not set -# CONFIG_QIC02_TAPE is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_DEVICE_INTERFACE is not set -# CONFIG_IPMI_KCS is not set -# CONFIG_IPMI_WATCHDOG is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -# CONFIG_ALIM1535_WDT is not set -# CONFIG_ALIM7101_WDT is not set -# CONFIG_SC520_WDT is not set -# CONFIG_PCWATCHDOG is not set -# CONFIG_21285_WATCHDOG is not set -# CONFIG_977_WATCHDOG is not set -# CONFIG_SA1100_WATCHDOG is not set -# CONFIG_EPXA_WATCHDOG is not set -# CONFIG_OMAHA_WATCHDOG is not set -CONFIG_S3C2410_WATCHDOG=y -# CONFIG_AT91_WATCHDOG is not set -# CONFIG_EUROTECH_WDT is not set -# CONFIG_IB700_WDT is not set -# CONFIG_WAFER_WDT is not set -# CONFIG_I810_TCO is not set -# CONFIG_MIXCOMWD is not set -# CONFIG_60XX_WDT is not set -# CONFIG_SC1200_WDT is not set -# CONFIG_SCx200_WDT is not set -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_W83877F_WDT is not set -# CONFIG_WDT is not set -# CONFIG_WDTPCI is not set -# CONFIG_MACHZ_WDT is not set -# CONFIG_AMD7XX_TCO is not set -# CONFIG_SCx200 is not set -# CONFIG_SCx200_GPIO is not set -# CONFIG_AMD_PM768 is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -CONFIG_BAST_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set - -# -# Direct Rendering Manager (XFree86 DRI support) -# -# CONFIG_DRM is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_QFMT_V2 is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -CONFIG_REISERFS_FS=y -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BEFS_DEBUG is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -# CONFIG_UMSDOS_FS is not set -CONFIG_VFAT_FS=y -# CONFIG_EFS_FS is not set -CONFIG_JFFS_FS=y -CONFIG_JFFS_FS_VERBOSE=0 -CONFIG_JFFS_PROC_FS=y -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_CRAMFS=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -# CONFIG_JFS_FS is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=y -CONFIG_EXT2_FS=y -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set -# CONFIG_XFS_FS is not set -# CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_RT is not set -# CONFIG_XFS_TRACE is not set -# CONFIG_XFS_DEBUG is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_DIRECTIO is not set -CONFIG_ROOT_NFS=y -# CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -# CONFIG_SMB_FS is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -CONFIG_ZISOFS_FS=y - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_EFI_PARTITION is not set -# CONFIG_SMB_NLS is not set -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=y -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -CONFIG_NLS_CODEPAGE_850=y -CONFIG_NLS_CODEPAGE_852=y -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Console drivers -# -# CONFIG_VGA_CONSOLE is not set - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_ACORN is not set -# CONFIG_FB_ANAKIN is not set -# CONFIG_FB_CLPS711X is not set -# CONFIG_FB_SA1100 is not set -CONFIG_FB_S3C2410=y -# CONFIG_FB_DBMX1 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_VIRTUAL is not set -CONFIG_FBCON_ADVANCED=y -# CONFIG_FBCON_MFB is not set -# CONFIG_FBCON_CFB2 is not set -CONFIG_FBCON_CFB4=y -CONFIG_FBCON_CFB8=y -# CONFIG_FBCON_CFB16 is not set -# CONFIG_FBCON_CFB24 is not set -# CONFIG_FBCON_CFB32 is not set -# CONFIG_FBCON_AFB is not set -# CONFIG_FBCON_ILBM is not set -# CONFIG_FBCON_IPLAN2P2 is not set -# CONFIG_FBCON_IPLAN2P4 is not set -# CONFIG_FBCON_IPLAN2P8 is not set -# CONFIG_FBCON_MAC is not set -# CONFIG_FBCON_VGA_PLANES is not set -# CONFIG_FBCON_VGA is not set -# CONFIG_FBCON_HGA is not set -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -CONFIG_FONT_ACORN_8x8=y - -# -# Sound -# -CONFIG_SOUND=y -# CONFIG_SOUND_ALI5455 is not set -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_MIDI_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_MAESTRO3 is not set -# CONFIG_SOUND_FORTE is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_RME96XX is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -# CONFIG_MIDI_VIA82CXXX is not set -CONFIG_SOUND_S3C2410=y -CONFIG_SOUND_S3C2410_TLV320AIC23=y -# CONFIG_SOUND_OSS is not set -# CONFIG_SOUND_VIDC is not set -# CONFIG_SOUND_WAVEARTIST is not set -# CONFIG_SOUND_TVMIXER is not set -# CONFIG_SOUND_AD1980 is not set -# CONFIG_SOUND_WM97XX is not set - -# -# Multimedia Capabilities Port drivers -# -# CONFIG_MCP is not set -# CONFIG_MCP_SA1100 is not set -# CONFIG_MCP_UCB1200 is not set -# CONFIG_MCP_UCB1200_AUDIO is not set -# CONFIG_MCP_UCB1200_TS is not set - -# -# USB support -# -CONFIG_USB=y -CONFIG_USB_DEBUG=y -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set -# CONFIG_USB_OHCI_SA1111 is not set -CONFIG_USB_OHCI_S3C2410=y -# CONFIG_USB_SL811HS_ALT is not set -# CONFIG_USB_SL811HS is not set -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_MIDI is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_SDDR55 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_ACM is not set -CONFIG_USB_PRINTER=y -CONFIG_USB_HID=y -CONFIG_USB_HIDINPUT=y -CONFIG_USB_HIDDEV=y -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -CONFIG_USB_USBNET=y -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=y -# CONFIG_USB_SERIAL_DEBUG is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -CONFIG_USB_SERIAL_FTDI_SIO=y -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_IPAQ is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_EDGEPORT_TI is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_KLSI is not set -# CONFIG_USB_SERIAL_KOBIL_SCT is not set -CONFIG_USB_SERIAL_PL2303=y -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_XIRCOM is not set -# CONFIG_USB_SERIAL_OMNINET is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_TIGL is not set -# CONFIG_USB_BRLVGER is not set -# CONFIG_USB_LCD is not set - -# -# Support for USB gadgets -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BLUEZ is not set - -# -# Kernel hacking -# -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_USER=y -CONFIG_DEBUG_INFO=y -# CONFIG_NO_PGT_CACHE is not set -CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_SLAB=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_WAITQ=y -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_LL=y -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set -CONFIG_DEBUG_S3C2410X_UART0=y - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/linux/linux-bast-2.4.25-vrs1-bast1/mkdep.patch b/linux/linux-bast-2.4.25-vrs1-bast1/mkdep.patch deleted file mode 100644 index 57218a7d1a..0000000000 --- a/linux/linux-bast-2.4.25-vrs1-bast1/mkdep.patch +++ /dev/null @@ -1,16 +0,0 @@ - -# -# Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher -# - ---- linux-2.4.25/Makefile~mkdep 2004-03-31 17:15:12.000000000 +0200 -+++ linux-2.4.25/Makefile 2004-03-31 17:18:50.000000000 +0200 -@@ -502,7 +502,7 @@ - ifdef CONFIG_MODVERSIONS - $(MAKE) update-modverfile - endif -- scripts/mkdep -- `find $(FINDHPATH) \( -name SCCS -o -name .svn \) -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend -+ $(foreach, dir, $(FINDHPATH), scripts/mkdep -- `find $(dir) -name SCCS -prune -o -follow -name \*.h ! -name modversions.h -print` >> .hdepend) - scripts/mkdep -- init/*.c > .depend - - ifdef CONFIG_MODVERSIONS diff --git a/linux/linux-bast_2.4.25-vrs1-bast1.bb b/linux/linux-bast_2.4.25-vrs1-bast1.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-colinux-2.4.28/colinux-0.6.1.patch b/linux/linux-colinux-2.4.28/colinux-0.6.1.patch deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-colinux-2.4.28/defconfig b/linux/linux-colinux-2.4.28/defconfig deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-colinux-2.4.28/gcc-registerparanoia.patch b/linux/linux-colinux-2.4.28/gcc-registerparanoia.patch deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-colinux-2.4.28/gcc340-fixes-v2.4.26-try3.patch b/linux/linux-colinux-2.4.28/gcc340-fixes-v2.4.26-try3.patch deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-colinux-2.4.28/linux-2.4.24-attribute-used.patch b/linux/linux-colinux-2.4.28/linux-2.4.24-attribute-used.patch deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-colinux-2.4.28/nofpu.patch b/linux/linux-colinux-2.4.28/nofpu.patch deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-colinux-2.4.28/shortloadbytes.patch b/linux/linux-colinux-2.4.28/shortloadbytes.patch deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-colinux_2.4.28.bb b/linux/linux-colinux_2.4.28.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-epia-2.6.8.1/epia_defconfig b/linux/linux-epia-2.6.8.1/epia_defconfig deleted file mode 100644 index 7984e3c14c..0000000000 --- a/linux/linux-epia-2.6.8.1/epia_defconfig +++ /dev/null @@ -1,1480 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_X86=y -CONFIG_MMU=y -CONFIG_UID16=y -CONFIG_GENERIC_ISA_DMA=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y -CONFIG_BROKEN_ON_SMP=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_HOTPLUG=y -# CONFIG_IKCONFIG is not set -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# Processor type and features -# -CONFIG_X86_PC=y -# CONFIG_X86_ELAN is not set -# CONFIG_X86_VOYAGER is not set -# CONFIG_X86_NUMAQ is not set -# CONFIG_X86_SUMMIT is not set -# CONFIG_X86_BIGSMP is not set -# CONFIG_X86_VISWS is not set -# CONFIG_X86_GENERICARCH is not set -# CONFIG_X86_ES7000 is not set -# CONFIG_M386 is not set -# CONFIG_M486 is not set -# CONFIG_M586 is not set -# CONFIG_M586TSC is not set -# CONFIG_M586MMX is not set -# CONFIG_M686 is not set -# CONFIG_MPENTIUMII is not set -# CONFIG_MPENTIUMIII is not set -# CONFIG_MPENTIUMM is not set -# CONFIG_MPENTIUM4 is not set -# CONFIG_MK6 is not set -# CONFIG_MK7 is not set -# CONFIG_MK8 is not set -# CONFIG_MCRUSOE is not set -# CONFIG_MWINCHIPC6 is not set -# CONFIG_MWINCHIP2 is not set -# CONFIG_MWINCHIP3D is not set -CONFIG_MCYRIXIII=y -# CONFIG_MVIAC3_2 is not set -# CONFIG_X86_GENERIC is not set -CONFIG_X86_CMPXCHG=y -CONFIG_X86_XADD=y -CONFIG_X86_L1_CACHE_SHIFT=5 -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_INVLPG=y -CONFIG_X86_BSWAP=y -CONFIG_X86_POPAD_OK=y -CONFIG_X86_ALIGNMENT_16=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_USE_3DNOW=y -# CONFIG_HPET_TIMER is not set -# CONFIG_SMP is not set -# CONFIG_PREEMPT is not set -# CONFIG_X86_UP_APIC is not set -CONFIG_X86_TSC=y -CONFIG_X86_MCE=y -# CONFIG_X86_MCE_NONFATAL is not set -# CONFIG_TOSHIBA is not set -# CONFIG_I8K is not set -# CONFIG_MICROCODE is not set -# CONFIG_X86_MSR is not set -# CONFIG_X86_CPUID is not set - -# -# Firmware Drivers -# -# CONFIG_EDD is not set -CONFIG_NOHIGHMEM=y -# CONFIG_HIGHMEM4G is not set -# CONFIG_HIGHMEM64G is not set -# CONFIG_MATH_EMULATION is not set -CONFIG_MTRR=y -# CONFIG_EFI is not set -CONFIG_REGPARM=y - -# -# Power management options (ACPI, APM) -# -CONFIG_PM=y -CONFIG_SOFTWARE_SUSPEND=y -# CONFIG_PM_DISK is not set - -# -# ACPI (Advanced Configuration and Power Interface) Support -# -CONFIG_ACPI=y -CONFIG_ACPI_BOOT=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_SLEEP=y -CONFIG_ACPI_SLEEP_PROC_FS=y -CONFIG_ACPI_AC=y -CONFIG_ACPI_BATTERY=y -CONFIG_ACPI_BUTTON=y -CONFIG_ACPI_FAN=y -CONFIG_ACPI_PROCESSOR=y -CONFIG_ACPI_THERMAL=y -# CONFIG_ACPI_ASUS is not set -# CONFIG_ACPI_TOSHIBA is not set -# CONFIG_ACPI_DEBUG is not set -CONFIG_ACPI_BUS=y -CONFIG_ACPI_EC=y -CONFIG_ACPI_POWER=y -CONFIG_ACPI_PCI=y -CONFIG_ACPI_SYSTEM=y -# CONFIG_X86_PM_TIMER is not set - -# -# APM (Advanced Power Management) BIOS Support -# -# CONFIG_APM is not set - -# -# CPU Frequency scaling -# -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_PROC_INTF is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -CONFIG_CPU_FREQ_GOV_USERSPACE=y -# CONFIG_CPU_FREQ_24_API is not set -CONFIG_CPU_FREQ_TABLE=y - -# -# CPUFreq processor drivers -# -CONFIG_X86_ACPI_CPUFREQ=m -# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set -# CONFIG_X86_POWERNOW_K6 is not set -# CONFIG_X86_POWERNOW_K7 is not set -# CONFIG_X86_POWERNOW_K8 is not set -# CONFIG_X86_GX_SUSPMOD is not set -# CONFIG_X86_SPEEDSTEP_CENTRINO is not set -# CONFIG_X86_SPEEDSTEP_ICH is not set -# CONFIG_X86_SPEEDSTEP_SMI is not set -# CONFIG_X86_P4_CLOCKMOD is not set -# CONFIG_X86_LONGRUN is not set -CONFIG_X86_LONGHAUL=y - -# -# Bus options (PCI, PCMCIA, EISA, MCA, ISA) -# -CONFIG_PCI=y -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GOMMCONFIG is not set -# CONFIG_PCI_GODIRECT is not set -CONFIG_PCI_GOANY=y -CONFIG_PCI_BIOS=y -CONFIG_PCI_DIRECT=y -CONFIG_PCI_MMCONFIG=y -# CONFIG_PCI_LEGACY_PROC is not set -# CONFIG_PCI_NAMES is not set -CONFIG_ISA=y -# CONFIG_EISA is not set -# CONFIG_MCA is not set -# CONFIG_SCx200 is not set - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set -CONFIG_PCMCIA_PROBE=y - -# -# PCI Hotplug Support -# -# CONFIG_HOTPLUG_PCI is not set - -# -# Executable file formats -# -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_MISC=m - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -# CONFIG_PARPORT_SERIAL is not set -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -# CONFIG_PARPORT_OTHER is not set -# CONFIG_PARPORT_1284 is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Block devices -# -CONFIG_BLK_DEV_FD=m -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_SX8 is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -CONFIG_LBD=y - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_IDE_SATA is not set -# CONFIG_BLK_DEV_HD_IDE is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -CONFIG_BLK_DEV_IDECD=y -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y - -# -# IDE chipset support/bugfixes -# -CONFIG_IDE_GENERIC=y -# CONFIG_BLK_DEV_CMD640 is not set -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_IDEPCI_SHARE_IRQ=y -# CONFIG_BLK_DEV_OFFBOARD is not set -CONFIG_BLK_DEV_GENERIC=y -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_RZ1000 is not set -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_ADMA=y -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_BLK_DEV_ATIIXP is not set -# CONFIG_BLK_DEV_CMD64X is not set -# CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5520 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_SC1200 is not set -# CONFIG_BLK_DEV_PIIX is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_BLK_DEV_PDC202XX_NEW is not set -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SIIMAGE is not set -# CONFIG_BLK_DEV_SIS5513 is not set -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_TRM290 is not set -CONFIG_BLK_DEV_VIA82CXXX=y -# CONFIG_IDE_ARM is not set -# CONFIG_IDE_CHIPSETS is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_IVB is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI device support -# -CONFIG_SCSI=y -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -CONFIG_CHR_DEV_ST=m -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI Transport Attributes -# -# CONFIG_SCSI_SPI_ATTRS is not set -# CONFIG_SCSI_FC_ATTRS is not set - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_3W_9XXX is not set -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set -# CONFIG_SCSI_IPS is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_PPA is not set -# CONFIG_SCSI_IMM is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA21XX is not set -# CONFIG_SCSI_QLA22XX is not set -# CONFIG_SCSI_QLA2300 is not set -# CONFIG_SCSI_QLA2322 is not set -# CONFIG_SCSI_QLA6312 is not set -# CONFIG_SCSI_QLA6322 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_ULTRASTOR is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# -CONFIG_IEEE1394=y - -# -# Subsystem Options -# -# CONFIG_IEEE1394_VERBOSEDEBUG is not set -# CONFIG_IEEE1394_OUI_DB is not set -CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y -CONFIG_IEEE1394_CONFIG_ROM_IP1394=y - -# -# Device Drivers -# -# CONFIG_IEEE1394_PCILYNX is not set -CONFIG_IEEE1394_OHCI1394=y - -# -# Protocol Drivers -# -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_SBP2=m -# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set -CONFIG_IEEE1394_ETH1394=m -CONFIG_IEEE1394_DV1394=m -CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK_DEV is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set - -# -# IP: Virtual Server Configuration -# -# CONFIG_IP_VS is not set -CONFIG_IPV6=y -# CONFIG_IPV6_PRIVACY is not set -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_IPV6_TUNNEL is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=y -# CONFIG_IP_NF_FTP is not set -# CONFIG_IP_NF_IRC is not set -# CONFIG_IP_NF_TFTP is not set -# CONFIG_IP_NF_AMANDA is not set -CONFIG_IP_NF_QUEUE=y -CONFIG_IP_NF_IPTABLES=y -CONFIG_IP_NF_MATCH_LIMIT=y -CONFIG_IP_NF_MATCH_IPRANGE=y -CONFIG_IP_NF_MATCH_MAC=y -CONFIG_IP_NF_MATCH_PKTTYPE=y -CONFIG_IP_NF_MATCH_MARK=y -CONFIG_IP_NF_MATCH_MULTIPORT=y -CONFIG_IP_NF_MATCH_TOS=y -CONFIG_IP_NF_MATCH_RECENT=y -CONFIG_IP_NF_MATCH_ECN=y -CONFIG_IP_NF_MATCH_DSCP=y -CONFIG_IP_NF_MATCH_AH_ESP=y -CONFIG_IP_NF_MATCH_LENGTH=y -CONFIG_IP_NF_MATCH_TTL=y -CONFIG_IP_NF_MATCH_TCPMSS=y -CONFIG_IP_NF_MATCH_HELPER=y -CONFIG_IP_NF_MATCH_STATE=y -CONFIG_IP_NF_MATCH_CONNTRACK=y -CONFIG_IP_NF_MATCH_OWNER=y -CONFIG_IP_NF_FILTER=y -CONFIG_IP_NF_TARGET_REJECT=y -CONFIG_IP_NF_NAT=y -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=y -CONFIG_IP_NF_TARGET_REDIRECT=y -CONFIG_IP_NF_TARGET_NETMAP=y -CONFIG_IP_NF_TARGET_SAME=y -# CONFIG_IP_NF_NAT_LOCAL is not set -# CONFIG_IP_NF_NAT_SNMP_BASIC is not set -CONFIG_IP_NF_MANGLE=y -CONFIG_IP_NF_TARGET_TOS=y -CONFIG_IP_NF_TARGET_ECN=y -CONFIG_IP_NF_TARGET_DSCP=y -CONFIG_IP_NF_TARGET_MARK=y -CONFIG_IP_NF_TARGET_CLASSIFY=y -CONFIG_IP_NF_TARGET_LOG=y -CONFIG_IP_NF_TARGET_ULOG=y -CONFIG_IP_NF_TARGET_TCPMSS=y -CONFIG_IP_NF_ARPTABLES=y -CONFIG_IP_NF_ARPFILTER=y -CONFIG_IP_NF_ARP_MANGLE=y -# CONFIG_IP_NF_RAW is not set -# CONFIG_IP_NF_MATCH_ADDRTYPE is not set -# CONFIG_IP_NF_MATCH_REALM is not set - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -# CONFIG_IP6_NF_IPTABLES is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -CONFIG_BT=m -CONFIG_BT_L2CAP=m -CONFIG_BT_SCO=m -CONFIG_BT_RFCOMM=m -# CONFIG_BT_RFCOMM_TTY is not set -CONFIG_BT_BNEP=m -# CONFIG_BT_BNEP_MC_FILTER is not set -# CONFIG_BT_BNEP_PROTO_FILTER is not set -# CONFIG_BT_HIDP is not set - -# -# Bluetooth device drivers -# -CONFIG_BT_HCIUSB=m -CONFIG_BT_HCIUSB_SCO=y -# CONFIG_BT_HCIUART is not set -# CONFIG_BT_HCIBCM203X is not set -# CONFIG_BT_HCIBFUSB is not set -# CONFIG_BT_HCIVHCI is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -CONFIG_MII=y -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set -# CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -CONFIG_NET_PCI=y -# CONFIG_PCNET32 is not set -# CONFIG_AMD8111_ETH is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_AC3200 is not set -# CONFIG_APRICOT is not set -# CONFIG_B44 is not set -# CONFIG_FORCEDETH is not set -# CONFIG_CS89x0 is not set -# CONFIG_DGRS is not set -# CONFIG_EEPRO100 is not set -# CONFIG_E100 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -# CONFIG_NE2K_PCI is not set -# CONFIG_8139CP is not set -# CONFIG_8139TOO is not set -# CONFIG_SIS900 is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_TLAN is not set -CONFIG_VIA_RHINE=y -# CONFIG_VIA_RHINE_MMIO is not set -# CONFIG_VIA_VELOCITY is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_S2IO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -# CONFIG_INPUT_TSDEV is not set -CONFIG_INPUT_EVDEV=m -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=m -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PARKBD is not set -# CONFIG_SERIO_PCIPS2 is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=m -# CONFIG_MOUSE_SERIAL is not set -# CONFIG_MOUSE_INPORT is not set -# CONFIG_MOUSE_LOGIBM is not set -# CONFIG_MOUSE_PC110PAD is not set -# CONFIG_MOUSE_VSXXXAA is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -CONFIG_INPUT_MISC=y -# CONFIG_INPUT_PCSPKR is not set -CONFIG_INPUT_UINPUT=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -# CONFIG_SERIAL_8250_CONSOLE is not set -# CONFIG_SERIAL_8250_ACPI is not set -CONFIG_SERIAL_8250_NR_UARTS=4 -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_UNIX98_PTYS=y -# CONFIG_LEGACY_PTYS is not set -CONFIG_PRINTER=m -# CONFIG_LP_CONSOLE is not set -CONFIG_PPDEV=m -# CONFIG_TIPAR is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_HW_RANDOM is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -CONFIG_CLE266VGAIO=m -CONFIG_AGP=y -# CONFIG_AGP_ALI is not set -# CONFIG_AGP_ATI is not set -# CONFIG_AGP_AMD is not set -# CONFIG_AGP_AMD64 is not set -# CONFIG_AGP_INTEL is not set -# CONFIG_AGP_INTEL_MCH is not set -# CONFIG_AGP_NVIDIA is not set -# CONFIG_AGP_SIS is not set -# CONFIG_AGP_SWORKS is not set -CONFIG_AGP_VIA=y -# CONFIG_AGP_EFFICEON is not set -CONFIG_DRM=y -# CONFIG_DRM_TDFX is not set -# CONFIG_DRM_GAMMA is not set -# CONFIG_DRM_R128 is not set -# CONFIG_DRM_RADEON is not set -# CONFIG_DRM_MGA is not set -# CONFIG_DRM_SIS is not set -CONFIG_DRM_VIA=m -# CONFIG_DRM_MACH64 is not set -# CONFIG_MWAVE is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HPET is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m - -# -# I2C Algorithms -# -CONFIG_I2C_ALGOBIT=m -# CONFIG_I2C_ALGOPCF is not set - -# -# I2C Hardware Bus support -# -# CONFIG_I2C_ALI1535 is not set -# CONFIG_I2C_ALI1563 is not set -# CONFIG_I2C_ALI15X3 is not set -# CONFIG_I2C_AMD756 is not set -# CONFIG_I2C_AMD8111 is not set -# CONFIG_I2C_ELEKTOR is not set -# CONFIG_I2C_I801 is not set -# CONFIG_I2C_I810 is not set -CONFIG_I2C_ISA=m -# CONFIG_I2C_NFORCE2 is not set -# CONFIG_I2C_PARPORT is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_PIIX4 is not set -# CONFIG_I2C_PROSAVAGE is not set -# CONFIG_I2C_SAVAGE4 is not set -# CONFIG_SCx200_ACB is not set -# CONFIG_I2C_SIS5595 is not set -# CONFIG_I2C_SIS630 is not set -# CONFIG_I2C_SIS96X is not set -CONFIG_I2C_VIA=m -CONFIG_I2C_VIAPRO=m -# CONFIG_I2C_VOODOO3 is not set - -# -# Hardware Sensors Chip support -# -CONFIG_I2C_SENSOR=m -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ASB100 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_FSCHER is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_VIA686A is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83627HF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_EEPROM is not set -CONFIG_SENSORS_VT1211=m -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set - -# -# Dallas's 1-wire bus -# -# CONFIG_W1 is not set - -# -# Misc devices -# -# CONFIG_IBM_ASM is not set - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# - -# -# Video Adapters -# -# CONFIG_VIDEO_BT848 is not set -# CONFIG_VIDEO_PMS is not set -# CONFIG_VIDEO_BWQCAM is not set -# CONFIG_VIDEO_CQCAM is not set -# CONFIG_VIDEO_CPIA is not set -# CONFIG_VIDEO_SAA5246A is not set -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_SAA7134 is not set -# CONFIG_VIDEO_MXB is not set -# CONFIG_VIDEO_DPC is not set -# CONFIG_VIDEO_HEXIUM_ORION is not set -# CONFIG_VIDEO_HEXIUM_GEMINI is not set -# CONFIG_VIDEO_CX88 is not set -# CONFIG_VIDEO_OVCAMCHIP is not set - -# -# Radio Adapters -# -# CONFIG_RADIO_CADET is not set -# CONFIG_RADIO_RTRACK is not set -# CONFIG_RADIO_RTRACK2 is not set -# CONFIG_RADIO_AZTECH is not set -# CONFIG_RADIO_GEMTEK is not set -# CONFIG_RADIO_GEMTEK_PCI is not set -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_MAESTRO is not set -# CONFIG_RADIO_SF16FMI is not set -# CONFIG_RADIO_SF16FMR2 is not set -# CONFIG_RADIO_TERRATEC is not set -# CONFIG_RADIO_TRUST is not set -# CONFIG_RADIO_TYPHOON is not set -# CONFIG_RADIO_ZOLTRIX is not set - -# -# Digital Video Broadcasting Devices -# -CONFIG_DVB=y -CONFIG_DVB_CORE=m - -# -# Supported Frontend Modules -# -# CONFIG_DVB_STV0299 is not set -# CONFIG_DVB_SP887X is not set -# CONFIG_DVB_ALPS_TDLB7 is not set -# CONFIG_DVB_ALPS_TDMB7 is not set -# CONFIG_DVB_ATMEL_AT76C651 is not set -# CONFIG_DVB_CX24110 is not set -# CONFIG_DVB_GRUNDIG_29504_491 is not set -CONFIG_DVB_GRUNDIG_29504_401=m -# CONFIG_DVB_MT312 is not set -# CONFIG_DVB_VES1820 is not set -# CONFIG_DVB_VES1X93 is not set -CONFIG_DVB_TDA1004X=m -CONFIG_DVB_TDA1004X_FIRMWARE_FILE="/usr/lib/hotplug/firmware/tda1004x.bin" -CONFIG_DVB_NXT6000=m - -# -# Supported SAA7146 based PCI Adapters -# -CONFIG_DVB_AV7110=m -# CONFIG_DVB_AV7110_OSD is not set -CONFIG_DVB_BUDGET=m -CONFIG_DVB_BUDGET_CI=m -# CONFIG_DVB_BUDGET_AV is not set -CONFIG_DVB_BUDGET_PATCH=m - -# -# Supported USB Adapters -# -# CONFIG_DVB_TTUSB_BUDGET is not set -# CONFIG_DVB_TTUSB_DEC is not set - -# -# Supported FlexCopII (B2C2) Adapters -# -# CONFIG_DVB_B2C2_SKYSTAR is not set - -# -# Supported BT878 Adapters -# -CONFIG_VIDEO_SAA7146=m -CONFIG_VIDEO_SAA7146_VV=m -CONFIG_VIDEO_VIDEOBUF=m -CONFIG_VIDEO_BUF=m - -# -# Graphics support -# -# CONFIG_FB is not set -# CONFIG_VIDEO_SELECT is not set - -# -# Console display driver support -# -CONFIG_VGA_CONSOLE=y -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# -CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# -CONFIG_SND=y -CONFIG_SND_TIMER=y -CONFIG_SND_PCM=y -CONFIG_SND_RAWMIDI=y -CONFIG_SND_SEQUENCER=y -# CONFIG_SND_SEQ_DUMMY is not set -CONFIG_SND_OSSEMUL=y -CONFIG_SND_MIXER_OSS=y -CONFIG_SND_PCM_OSS=y -CONFIG_SND_SEQUENCER_OSS=y -# CONFIG_SND_VERBOSE_PRINTK is not set -# CONFIG_SND_DEBUG is not set - -# -# Generic devices -# -CONFIG_SND_MPU401_UART=y -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_VIRMIDI is not set -# CONFIG_SND_MTPAV is not set -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set - -# -# ISA devices -# -# CONFIG_SND_AD1848 is not set -# CONFIG_SND_CS4231 is not set -# CONFIG_SND_CS4232 is not set -# CONFIG_SND_CS4236 is not set -# CONFIG_SND_ES1688 is not set -# CONFIG_SND_ES18XX is not set -# CONFIG_SND_GUSCLASSIC is not set -# CONFIG_SND_GUSEXTREME is not set -# CONFIG_SND_GUSMAX is not set -# CONFIG_SND_INTERWAVE is not set -# CONFIG_SND_INTERWAVE_STB is not set -# CONFIG_SND_OPTI92X_AD1848 is not set -# CONFIG_SND_OPTI92X_CS4231 is not set -# CONFIG_SND_OPTI93X is not set -# CONFIG_SND_SB8 is not set -# CONFIG_SND_SB16 is not set -# CONFIG_SND_SBAWE is not set -# CONFIG_SND_WAVEFRONT is not set -# CONFIG_SND_CMI8330 is not set -# CONFIG_SND_OPL3SA2 is not set -# CONFIG_SND_SGALAXY is not set -# CONFIG_SND_SSCAPE is not set - -# -# PCI devices -# -CONFIG_SND_AC97_CODEC=y -# CONFIG_SND_ALI5451 is not set -# CONFIG_SND_ATIIXP is not set -# CONFIG_SND_AU8810 is not set -# CONFIG_SND_AU8820 is not set -# CONFIG_SND_AU8830 is not set -# CONFIG_SND_AZT3328 is not set -# CONFIG_SND_BT87X is not set -# CONFIG_SND_CS46XX is not set -# CONFIG_SND_CS4281 is not set -# CONFIG_SND_EMU10K1 is not set -# CONFIG_SND_KORG1212 is not set -# CONFIG_SND_MIXART is not set -# CONFIG_SND_NM256 is not set -# CONFIG_SND_RME32 is not set -# CONFIG_SND_RME96 is not set -# CONFIG_SND_RME9652 is not set -# CONFIG_SND_HDSP is not set -# CONFIG_SND_TRIDENT is not set -# CONFIG_SND_YMFPCI is not set -# CONFIG_SND_ALS4000 is not set -# CONFIG_SND_CMIPCI is not set -# CONFIG_SND_ENS1370 is not set -# CONFIG_SND_ENS1371 is not set -# CONFIG_SND_ES1938 is not set -# CONFIG_SND_ES1968 is not set -# CONFIG_SND_MAESTRO3 is not set -# CONFIG_SND_FM801 is not set -# CONFIG_SND_ICE1712 is not set -# CONFIG_SND_ICE1724 is not set -# CONFIG_SND_INTEL8X0 is not set -# CONFIG_SND_INTEL8X0M is not set -# CONFIG_SND_SONICVIBES is not set -CONFIG_SND_VIA82XX=y -# CONFIG_SND_VX222 is not set - -# -# ALSA USB devices -# -# CONFIG_SND_USB_AUDIO is not set - -# -# Open Sound System -# -# CONFIG_SOUND_PRIME is not set - -# -# USB support -# -CONFIG_USB=y -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_DYNAMIC_MINORS is not set - -# -# USB Host Controller Drivers -# -CONFIG_USB_EHCI_HCD=y -# CONFIG_USB_EHCI_SPLIT_ISO is not set -# CONFIG_USB_EHCI_ROOT_HUB_TT is not set -# CONFIG_USB_OHCI_HCD is not set -CONFIG_USB_UHCI_HCD=y - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set - -# -# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem -# -# CONFIG_USB_MIDI is not set -# CONFIG_USB_ACM is not set -CONFIG_USB_PRINTER=m -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_RW_DETECT is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_SDDR55 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=y -CONFIG_USB_HIDINPUT=y -# CONFIG_HID_FF is not set -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_EGALAX is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_PWC is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_STV680 is not set - -# -# USB Network adaptors -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_TIGL is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGETSERVO is not set -# CONFIG_USB_TEST is not set - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_XFS_FS=y -# CONFIG_XFS_RT is not set -# CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_SECURITY is not set -# CONFIG_XFS_POSIX_ACL is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=y - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -# CONFIG_ZISOFS is not set -CONFIG_UDF_FS=y -CONFIG_UDF_NLS=y - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_KCORE=y -CONFIG_SYSFS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS_XATTR is not set -CONFIG_TMPFS=y -# CONFIG_HUGETLBFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -CONFIG_HFSPLUS_FS=m -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -CONFIG_CRAMFS=y -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set -# CONFIG_ROOT_NFS is not set -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_EFI_PARTITION is not set - -# -# Native Language Support -# -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=y -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ASCII is not set -CONFIG_NLS_ISO8859_1=y -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=y - -# -# Kernel hacking -# -# CONFIG_DEBUG_KERNEL is not set -CONFIG_EARLY_PRINTK=y -CONFIG_DEBUG_SPINLOCK_SLEEP=y -# CONFIG_FRAME_POINTER is not set -# CONFIG_4KSTACKS is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC_CCITT is not set -CONFIG_CRC32=y -# CONFIG_LIBCRC32C is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_X86_BIOS_REBOOT=y -CONFIG_PC=y diff --git a/linux/linux-epia_2.6.8.1.bb b/linux/linux-epia_2.6.8.1.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-mtx-1-2.4.24/01-mtd-2004-01-27.diff b/linux/linux-mtx-1-2.4.24/01-mtd-2004-01-27.diff deleted file mode 100644 index 1a31cb79fb..0000000000 --- a/linux/linux-mtx-1-2.4.24/01-mtd-2004-01-27.diff +++ /dev/null @@ -1,51462 +0,0 @@ -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/Config.in linux/drivers/mtd/Config.in ---- linux-mips-2.4.24-pre2/drivers/mtd/Config.in 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/Config.in 2004-11-17 18:17:58.809348880 +0100 -@@ -1,5 +1,5 @@ - --# $Id$ -+# $Id$ - - mainmenu_option next_comment - comment 'Memory Technology Devices (MTD)' -@@ -30,6 +30,7 @@ - if [ "$CONFIG_NFTL" = "y" -o "$CONFIG_NFTL" = "m" ]; then - bool ' Write support for NFTL (BETA)' CONFIG_NFTL_RW - fi -+ dep_tristate ' INFTL (Inverse NAND Flash Translation Layer) support' CONFIG_INFTL $CONFIG_MTD - - source drivers/mtd/chips/Config.in - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/Makefile linux/drivers/mtd/Makefile ---- linux-mips-2.4.24-pre2/drivers/mtd/Makefile 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/Makefile 2004-11-17 18:17:58.826346296 +0100 -@@ -1,30 +1,7 @@ - # - # Makefile for the memory technology device drivers. - # --# Note! Dependencies are done automagically by 'make dep', which also --# removes any old dependencies. DON'T put your own dependencies here --# unless it's something special (ie not a .c file). --# --# Note 2! The CFLAGS definitions are now inherited from the --# parent makes.. --# --# $Id$ -- -- --obj-y += chips/chipslink.o maps/mapslink.o \ -- devices/devlink.o nand/nandlink.o --obj-m := --obj-n := --obj- := -- --O_TARGET := mtdlink.o -- --export-objs := mtdcore.o mtdpart.o redboot.o cmdlinepart.o afs.o mtdconcat.o --list-multi := nftl.o -- --mod-subdirs := --subdir-y := chips maps devices nand --subdir-m := $(subdir-y) -+# $Id$ - - # *** BIG UGLY NOTE *** - # -@@ -52,15 +29,44 @@ - - # 'Users' - code which presents functionality to userspace. - obj-$(CONFIG_MTD_CHAR) += mtdchar.o --obj-$(CONFIG_MTD_BLOCK) += mtdblock.o --obj-$(CONFIG_MTD_BLOCK_RO) += mtdblock_ro.o --obj-$(CONFIG_FTL) += ftl.o --obj-$(CONFIG_NFTL) += nftl.o -+obj-$(CONFIG_MTD_BLOCK) += mtdblock.o mtd_blkdevs.o -+obj-$(CONFIG_MTD_BLOCK_RO) += mtdblock_ro.o mtd_blkdevs.o -+obj-$(CONFIG_FTL) += ftl.o mtd_blkdevs.o -+obj-$(CONFIG_NFTL) += nftl.o mtd_blkdevs.o -+obj-$(CONFIG_INFTL) += inftl.o mtd_blkdevs.o - - nftl-objs := nftlcore.o nftlmount.o -+inftl-objs := inftlcore.o inftlmount.o -+ -+ifeq ($(PATCHLEVEL),4) -+ -+export-objs := mtdcore.o mtdpart.o redboot.o cmdlinepart.o afs.o \ -+ mtdconcat.o mtd_blkdevs-24.o -+ -+mtd_blkdevs-objs := mtd_blkdevs-24.o -+ -+obj-y += chips/chipslink.o maps/mapslink.o \ -+ devices/devlink.o nand/nandlink.o -+ -+O_TARGET := mtdlink.o -+ -+list-multi := nftl.o inftl.o mtd_blkdevs.o -+ -+mod-subdirs := -+subdir-y := chips maps devices nand -+subdir-m := $(subdir-y) - - include $(TOPDIR)/Rules.make - - nftl.o: $(nftl-objs) - $(LD) -r -o $@ $(nftl-objs) - -+inftl.o: $(inftl-objs) -+ $(LD) -r -o $@ $(inftl-objs) -+ -+mtd_blkdevs.o: $(mtd_blkdevs-objs) -+ $(LD) -r -o $@ $(mtd_blkdevs-objs) -+ -+else -+obj-y += chips/ maps/ devices/ nand/ -+endif -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/afs.c linux/drivers/mtd/afs.c ---- linux-mips-2.4.24-pre2/drivers/mtd/afs.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/afs.c 2004-11-17 18:17:58.827346144 +0100 -@@ -21,7 +21,7 @@ - This is access code for flashes using ARM's flash partitioning - standards. - -- $Id$ -+ $Id$ - - ======================================================================*/ - -@@ -76,17 +76,19 @@ - return ret; - } - -+ ret = 1; -+ - /* - * Does it contain the magic number? - */ - if (fs.signature != 0xa0ffff9f) -- ret = 1; -+ ret = 0; - - /* - * Don't touch the SIB. - */ - if (fs.type == 2) -- ret = 1; -+ ret = 0; - - *iis_start = fs.image_info_base & mask; - *img_start = fs.image_start & mask; -@@ -96,14 +98,14 @@ - * be located after the footer structure. - */ - if (*iis_start >= ptr) -- ret = 1; -+ ret = 0; - - /* - * Check the start of this image. The image - * data can not be located after this block. - */ - if (*img_start > off) -- ret = 1; -+ ret = 0; - - return ret; - } -@@ -125,7 +127,9 @@ - return ret; - } - --int parse_afs_partitions(struct mtd_info *mtd, struct mtd_partition **pparts) -+static int parse_afs_partitions(struct mtd_info *mtd, -+ struct mtd_partition **pparts, -+ unsigned long origin) - { - struct mtd_partition *parts; - u_int mask, off, idx, sz; -@@ -150,7 +154,7 @@ - ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask); - if (ret < 0) - break; -- if (ret == 1) -+ if (ret == 0) - continue; - - ret = afs_read_iis(mtd, &iis, iis_ptr); -@@ -183,7 +187,7 @@ - ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask); - if (ret < 0) - break; -- if (ret == 1) -+ if (ret == 0) - continue; - - /* Read the image info block */ -@@ -227,7 +231,25 @@ - return idx ? idx : ret; - } - --EXPORT_SYMBOL(parse_afs_partitions); -+static struct mtd_part_parser afs_parser = { -+ .owner = THIS_MODULE, -+ .parse_fn = parse_afs_partitions, -+ .name = "afs", -+}; -+ -+static int __init afs_parser_init(void) -+{ -+ return register_mtd_parser(&afs_parser); -+} -+ -+static void __exit afs_parser_exit(void) -+{ -+ deregister_mtd_parser(&afs_parser); -+} -+ -+module_init(afs_parser_init); -+module_exit(afs_parser_exit); -+ - - MODULE_AUTHOR("ARM Ltd"); - MODULE_DESCRIPTION("ARM Firmware Suite partition parser"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/Config.in linux/drivers/mtd/chips/Config.in ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/Config.in 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/chips/Config.in 2004-11-17 18:17:58.905334288 +0100 -@@ -1,6 +1,6 @@ - # drivers/mtd/chips/Config.in - --# $Id$ -+# $Id$ - - mainmenu_option next_comment - -@@ -11,13 +11,12 @@ - - if [ "$CONFIG_MTD_CFI" = "y" -o "$CONFIG_MTD_JEDECPROBE" = "y" ]; then - define_bool CONFIG_MTD_GEN_PROBE y --else -- if [ "$CONFIG_MTD_CFI" = "m" -o "$CONFIG_MTD_JEDECPROBE" = "m" ]; then -+elif [ "$CONFIG_MTD_CFI" = "m" -o "$CONFIG_MTD_JEDECPROBE" = "m" ]; then - define_bool CONFIG_MTD_GEN_PROBE m -- else -+else - define_bool CONFIG_MTD_GEN_PROBE n -- fi - fi -+ - if [ "$CONFIG_MTD_GEN_PROBE" = "y" -o "$CONFIG_MTD_GEN_PROBE" = "m" ]; then - bool ' Flash chip driver advanced configuration options' CONFIG_MTD_CFI_ADV_OPTIONS - if [ "$CONFIG_MTD_CFI_ADV_OPTIONS" = "y" ]; then -@@ -44,8 +43,27 @@ - fi - dep_tristate ' Support for Intel/Sharp flash chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_GEN_PROBE - dep_tristate ' Support for AMD/Fujitsu flash chips' CONFIG_MTD_CFI_AMDSTD $CONFIG_MTD_GEN_PROBE -+if [ "$CONFIG_MTD_CFI_AMDSTD" = "y" -o "$CONFIG_MTD_CFI_AMDSTD" = "m" ]; then -+ bool ' Retry failed commands (erase/program)' CONFIG_MTD_CFI_AMDSTD_RETRY n -+ if [ "$CONFIG_MTD_CFI_AMDSTD_RETRY" = "y" ]; then -+ int ' Max retries of failed commands (erase/program)' CONFIG_MTD_CFI_AMDSTD_RETRY_MAX 0 -+ fi -+fi -+ - dep_tristate ' Support for ST (Advanced Architecture) flash chips' CONFIG_MTD_CFI_STAA $CONFIG_MTD_GEN_PROBE - -+if [ "$CONFIG_MTD_CFI_INTELEXT" = "y" \ -+ -o "$CONFIG_MTD_CFI_AMDSTD" = "y" \ -+ -o "$CONFIG_MTD_CFI_STAA" = "y" ]; then -+ define_bool CONFIG_MTD_CFI_UTIL y -+elif [ "$CONFIG_MTD_CFI_INTELEXT" = "m" \ -+ -o "$CONFIG_MTD_CFI_AMDSTD" = "m" \ -+ -o "$CONFIG_MTD_CFI_STAA" = "m" ]; then -+ define_bool CONFIG_MTD_CFI_UTIL m -+else -+ define_bool CONFIG_MTD_CFI_UTIL n -+fi -+ - dep_tristate ' Support for RAM chips in bus mapping' CONFIG_MTD_RAM $CONFIG_MTD - dep_tristate ' Support for ROM chips in bus mapping' CONFIG_MTD_ROM $CONFIG_MTD - dep_tristate ' Support for absent chips in bus mapping' CONFIG_MTD_ABSENT $CONFIG_MTD -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/Makefile linux/drivers/mtd/chips/Makefile ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/Makefile 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/chips/Makefile 2004-11-17 18:17:58.907333984 +0100 -@@ -1,11 +1,12 @@ - # - # linux/drivers/chips/Makefile - # --# $Id$ -+# $Id$ - -+ifeq ($(PATCHLEVEL),4) - O_TARGET := chipslink.o -- --export-objs := chipreg.o gen_probe.o -+export-objs := chipreg.o gen_probe.o cfi_util.o -+endif - - # *** BIG UGLY NOTE *** - # -@@ -17,6 +18,7 @@ - obj-$(CONFIG_MTD) += chipreg.o - obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o - obj-$(CONFIG_MTD_CFI) += cfi_probe.o -+obj-$(CONFIG_MTD_CFI_UTIL) += cfi_util.o - obj-$(CONFIG_MTD_CFI_STAA) += cfi_cmdset_0020.o - obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o - obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o -@@ -28,4 +30,4 @@ - obj-$(CONFIG_MTD_SHARP) += sharp.o - obj-$(CONFIG_MTD_ABSENT) += map_absent.o - --include $(TOPDIR)/Rules.make -+-include $(TOPDIR)/Rules.make -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/amd_flash.c linux/drivers/mtd/chips/amd_flash.c ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/amd_flash.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/chips/amd_flash.c 2004-11-17 18:17:58.909333680 +0100 -@@ -3,7 +3,7 @@ - * - * Author: Jonas Holmberg - * -- * $Id$ -+ * $Id$ - * - * Copyright (c) 2001 Axis Communications AB - * -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -125,10 +126,10 @@ - - - static struct mtd_chip_driver amd_flash_chipdrv = { -- probe: amd_flash_probe, -- destroy: amd_flash_destroy, -- name: "amd_flash", -- module: THIS_MODULE -+ .probe = amd_flash_probe, -+ .destroy = amd_flash_destroy, -+ .name = "amd_flash", -+ .module = THIS_MODULE - }; - - -@@ -140,11 +141,11 @@ - static inline __u32 wide_read(struct map_info *map, __u32 addr) - { - if (map->buswidth == 1) { -- return map->read8(map, addr); -+ return map_read8(map, addr); - } else if (map->buswidth == 2) { -- return map->read16(map, addr); -+ return map_read16(map, addr); - } else if (map->buswidth == 4) { -- return map->read32(map, addr); -+ return map_read32(map, addr); - } - - return 0; -@@ -153,11 +154,11 @@ - static inline void wide_write(struct map_info *map, __u32 val, __u32 addr) - { - if (map->buswidth == 1) { -- map->write8(map, val, addr); -+ map_write8(map, val, addr); - } else if (map->buswidth == 2) { -- map->write16(map, val, addr); -+ map_write16(map, val, addr); - } else if (map->buswidth == 4) { -- map->write32(map, val, addr); -+ map_write32(map, val, addr); - } - } - -@@ -424,231 +425,228 @@ - - static struct mtd_info *amd_flash_probe(struct map_info *map) - { -- /* Keep this table on the stack so that it gets deallocated after the -- * probe is done. -- */ -- const struct amd_flash_info table[] = { -+ static const struct amd_flash_info table[] = { - { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV160DT, -- name: "AMD AM29LV160DT", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, -- { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV160DT, -+ .name = "AMD AM29LV160DT", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, -+ { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV160DB, -- name: "AMD AM29LV160DB", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, -- { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV160DB, -+ .name = "AMD AM29LV160DB", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, -+ { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVT160, -- name: "Toshiba TC58FVT160", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, -- { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVT160, -+ .name = "Toshiba TC58FVT160", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, -+ { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV160TE, -- name: "Fujitsu MBM29LV160TE", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, -- { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV160TE, -+ .name = "Fujitsu MBM29LV160TE", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, -+ { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVB160, -- name: "Toshiba TC58FVB160", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, -- { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVB160, -+ .name = "Toshiba TC58FVB160", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, -+ { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV160BE, -- name: "Fujitsu MBM29LV160BE", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, -- { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV160BE, -+ .name = "Fujitsu MBM29LV160BE", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, -+ { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV800BB, -- name: "AMD AM29LV800BB", -- size: 0x00100000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, -- { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 15 } -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV800BB, -+ .name = "AMD AM29LV800BB", -+ .size = 0x00100000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, -+ { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 } - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F800BB, -- name: "AMD AM29F800BB", -- size: 0x00100000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, -- { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 15 } -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F800BB, -+ .name = "AMD AM29F800BB", -+ .size = 0x00100000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, -+ { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 } - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV800BT, -- name: "AMD AM29LV800BT", -- size: 0x00100000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, -- { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV800BT, -+ .name = "AMD AM29LV800BT", -+ .size = 0x00100000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, -+ { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F800BT, -- name: "AMD AM29F800BT", -- size: 0x00100000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, -- { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F800BT, -+ .name = "AMD AM29F800BT", -+ .size = 0x00100000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, -+ { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV800BB, -- name: "AMD AM29LV800BB", -- size: 0x00100000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, -- { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV800BB, -+ .name = "AMD AM29LV800BB", -+ .size = 0x00100000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, -+ { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV800BB, -- name: "Fujitsu MBM29LV800BB", -- size: 0x00100000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, -- { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 15 } -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV800BB, -+ .name = "Fujitsu MBM29LV800BB", -+ .size = 0x00100000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, -+ { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 } - } - }, { -- mfr_id: MANUFACTURER_ST, -- dev_id: M29W800T, -- name: "ST M29W800T", -- size: 0x00100000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, -- { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_ST, -+ .dev_id = M29W800T, -+ .name = "ST M29W800T", -+ .size = 0x00100000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, -+ { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_ST, -- dev_id: M29W160DT, -- name: "ST M29W160DT", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, -- { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_ST, -+ .dev_id = M29W160DT, -+ .name = "ST M29W160DT", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, -+ { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_ST, -- dev_id: M29W160DB, -- name: "ST M29W160DB", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, -- { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } -+ .mfr_id = MANUFACTURER_ST, -+ .dev_id = M29W160DB, -+ .name = "ST M29W160DB", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, -+ { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29BDS323D, -- name: "AMD AM29BDS323D", -- size: 0x00400000, -- numeraseregions: 3, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 48 }, -- { offset: 0x300000, erasesize: 0x10000, numblocks: 15 }, -- { offset: 0x3f0000, erasesize: 0x02000, numblocks: 8 }, -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29BDS323D, -+ .name = "AMD AM29BDS323D", -+ .size = 0x00400000, -+ .numeraseregions = 3, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 48 }, -+ { .offset = 0x300000, .erasesize = 0x10000, .numblocks = 15 }, -+ { .offset = 0x3f0000, .erasesize = 0x02000, .numblocks = 8 }, - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29BDS643D, -- name: "AMD AM29BDS643D", -- size: 0x00800000, -- numeraseregions: 3, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 96 }, -- { offset: 0x600000, erasesize: 0x10000, numblocks: 31 }, -- { offset: 0x7f0000, erasesize: 0x02000, numblocks: 8 }, -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29BDS643D, -+ .name = "AMD AM29BDS643D", -+ .size = 0x00800000, -+ .numeraseregions = 3, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 96 }, -+ { .offset = 0x600000, .erasesize = 0x10000, .numblocks = 31 }, -+ { .offset = 0x7f0000, .erasesize = 0x02000, .numblocks = 8 }, - } - }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT49xV16x, -- name: "Atmel AT49xV16x", -- size: 0x00200000, -- numeraseregions: 2, -- regions: { -- { offset: 0x000000, erasesize: 0x02000, numblocks: 8 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT49xV16x, -+ .name = "Atmel AT49xV16x", -+ .size = 0x00200000, -+ .numeraseregions = 2, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x02000, .numblocks = 8 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } - } - }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT49xV16xT, -- name: "Atmel AT49xV16xT", -- size: 0x00200000, -- numeraseregions: 2, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, -- { offset: 0x1F0000, erasesize: 0x02000, numblocks: 8 } -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT49xV16xT, -+ .name = "Atmel AT49xV16xT", -+ .size = 0x00200000, -+ .numeraseregions = 2, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, -+ { .offset = 0x1F0000, .erasesize = 0x02000, .numblocks = 8 } - } - } - }; -@@ -822,7 +820,7 @@ - - chip->state = FL_READY; - -- map->copy_from(map, buf, adr, len); -+ map_copy_from(map, buf, adr, len); - - wake_up(&chip->wq); - spin_unlock_bh(chip->mutex); -@@ -984,7 +982,7 @@ - u_char tmp_buf[4]; - __u32 datum; - -- map->copy_from(map, tmp_buf, -+ map_copy_from(map, tmp_buf, - bus_ofs + private->chips[chipnum].start, - map->buswidth); - while (len && i < map->buswidth) -@@ -1057,7 +1055,7 @@ - u_char tmp_buf[2]; - __u32 datum; - -- map->copy_from(map, tmp_buf, -+ map_copy_from(map, tmp_buf, - ofs + private->chips[chipnum].start, - map->buswidth); - while (len--) { -@@ -1178,7 +1176,7 @@ - __u8 verify; - - for (address = adr; address < (adr + size); address++) { -- if ((verify = map->read8(map, address)) != 0xFF) { -+ if ((verify = map_read8(map, address)) != 0xFF) { - error = 1; - break; - } -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/cfi_cmdset_0001.c linux/drivers/mtd/chips/cfi_cmdset_0001.c ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/cfi_cmdset_0001.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/chips/cfi_cmdset_0001.c 2004-11-17 18:17:58.910333528 +0100 -@@ -4,7 +4,7 @@ - * - * (C) 2000 Red Hat. GPL'd - * -- * $Id$ -+ * $Id$ - * - * - * 10/10/2000 Nicolas Pitre -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -29,10 +30,14 @@ - #include - #include - #include --#include -+#include - #include -+#include -+ -+/* #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE */ - --// debugging, turns off buffer write mode #define FORCE_WORD_WRITE -+// debugging, turns off buffer write mode if set to 1 -+#define FORCE_WORD_WRITE 0 - - static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); - static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); -@@ -52,16 +57,21 @@ - - static struct mtd_info *cfi_intelext_setup (struct map_info *); - --static int do_point (struct mtd_info *mtd, loff_t from, size_t len, -+static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char **mtdbuf); --static void do_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, -+static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, - size_t len); - -+ -+/* -+ * *********** SETUP AND PROBE BITS *********** -+ */ -+ - static struct mtd_chip_driver cfi_intelext_chipdrv = { -- probe: NULL, /* Not usable directly */ -- destroy: cfi_intelext_destroy, -- name: "cfi_cmdset_0001", -- module: THIS_MODULE -+ .probe = NULL, /* Not usable directly */ -+ .destroy = cfi_intelext_destroy, -+ .name = "cfi_cmdset_0001", -+ .module = THIS_MODULE - }; - - /* #define DEBUG_LOCK_BITS */ -@@ -102,13 +112,63 @@ - } - - printk(" Vcc Logic Supply Optimum Program/Erase Voltage: %d.%d V\n", -- extp->VccOptimal >> 8, extp->VccOptimal & 0xf); -+ extp->VccOptimal >> 4, extp->VccOptimal & 0xf); - if (extp->VppOptimal) - printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n", -- extp->VppOptimal >> 8, extp->VppOptimal & 0xf); -+ extp->VppOptimal >> 4, extp->VppOptimal & 0xf); - } - #endif - -+#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE -+/* Some Intel Strata Flash prior to FPO revision C has bugs in this area */ -+static void fixup_intel_strataflash(struct map_info *map, void* param) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ struct cfi_pri_amdstd *extp = cfi->cmdset_priv; -+ -+ printk(KERN_WARNING "cfi_cmdset_0001: Suspend " -+ "erase on write disabled.\n"); -+ extp->SuspendCmdSupport &= ~1; -+} -+#endif -+ -+static void fixup_st_m28w320ct(struct map_info *map, void* param) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ -+ cfi->cfiq->BufWriteTimeoutTyp = 0; /* Not supported */ -+ cfi->cfiq->BufWriteTimeoutMax = 0; /* Not supported */ -+} -+ -+static void fixup_st_m28w320cb(struct map_info *map, void* param) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ -+ /* Note this is done after the region info is endian swapped */ -+ cfi->cfiq->EraseRegionInfo[1] = -+ (cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e; -+}; -+ -+static struct cfi_fixup fixup_table[] = { -+#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE -+ { -+ CFI_MFR_ANY, CFI_ID_ANY, -+ fixup_intel_strataflash, NULL -+ }, -+#endif -+ { -+ 0x0020, /* STMicroelectronics */ -+ 0x00ba, /* M28W320CT */ -+ fixup_st_m28w320ct, NULL -+ }, { -+ 0x0020, /* STMicroelectronics */ -+ 0x00bb, /* M28W320CB */ -+ fixup_st_m28w320cb, NULL -+ }, { -+ 0, 0, NULL, NULL -+ } -+}; -+ - /* This routine is made available to other mtd code via - * inter_module_register. It must only be accessed through - * inter_module_get which will bump the use count of this module. The -@@ -120,7 +180,6 @@ - { - struct cfi_private *cfi = map->fldrv_priv; - int i; -- __u32 base = cfi->chips[0].start; - - if (cfi->cfi_mode == CFI_MODE_CFI) { - /* -@@ -130,59 +189,29 @@ - */ - __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; - struct cfi_pri_intelext *extp; -- int ofs_factor = cfi->interleave * cfi->device_type; -- -- //printk(" Intel/Sharp Extended Query Table at 0x%4.4X\n", adr); -- if (!adr) -- return NULL; - -- /* Switch it into Query Mode */ -- cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); -- -- extp = kmalloc(sizeof(*extp), GFP_KERNEL); -- if (!extp) { -- printk(KERN_ERR "Failed to allocate memory\n"); -+ extp = (struct cfi_pri_intelext*)cfi_read_pri(map, adr, sizeof(*extp), "Intel/Sharp"); -+ if (!extp) - return NULL; -- } -- -- /* Read in the Extended Query Table */ -- for (i=0; iMajorVersion != '1' || -- (extp->MinorVersion < '0' || extp->MinorVersion > '3')) { -- printk(KERN_WARNING " Unknown IntelExt Extended Query " -- "version %c.%c.\n", extp->MajorVersion, -- extp->MinorVersion); -- kfree(extp); -- return NULL; -- } - - /* Do some byteswapping if necessary */ - extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport); - extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask); - extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr); - -+ /* Install our own private info structure */ -+ cfi->cmdset_priv = extp; -+ -+ cfi_fixup(map, fixup_table); -+ - #ifdef DEBUG_CFI_FEATURES - /* Tell the user about it in lots of lovely detail */ - cfi_tell_features(extp); - #endif - - if(extp->SuspendCmdSupport & 1) { --//#define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE --#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE --/* Some Intel Strata Flash prior to FPO revision C has bugs in this area */ -- printk(KERN_WARNING "cfi_cmdset_0001: Suspend " -- "erase on write disabled.\n"); -- extp->SuspendCmdSupport &= ~1; --#else - printk(KERN_NOTICE "cfi_cmdset_0001: Erase suspend on write enabled\n"); --#endif - } -- /* Install our own private info structure */ -- cfi->cmdset_priv = extp; - } - - for (i=0; i< cfi->numchips; i++) { -@@ -194,8 +223,6 @@ - - map->fldrv = &cfi_intelext_chipdrv; - -- /* Make sure it's in read mode */ -- cfi_send_gen_cmd(0xff, 0x55, base, map, cfi, cfi->device_type, NULL); - return cfi_intelext_setup(map); - } - -@@ -261,20 +288,16 @@ - mtd->erase = cfi_intelext_erase_varsize; - mtd->read = cfi_intelext_read; - -- if(map->point && map->unpoint){ -- mtd->point = do_point; -- mtd->unpoint = do_unpoint; -+ if (map_is_linear(map)) { -+ mtd->point = cfi_intelext_point; -+ mtd->unpoint = cfi_intelext_unpoint; - } - --#ifndef FORCE_WORD_WRITE -- if ( cfi->cfiq->BufWriteTimeoutTyp ) { -- printk("Using buffer write method\n" ); -+ if ( cfi->cfiq->BufWriteTimeoutTyp && !FORCE_WORD_WRITE) { -+ printk(KERN_INFO "Using buffer write method\n" ); - mtd->write = cfi_intelext_write_buffers; - } else { --#else -- { --#endif -- printk("Using word write method\n" ); -+ printk(KERN_INFO "Using word write method\n" ); - mtd->write = cfi_intelext_write_words; - } - mtd->read_user_prot_reg = cfi_intelext_read_user_prot_reg; -@@ -286,8 +309,8 @@ - mtd->resume = cfi_intelext_resume; - mtd->flags = MTD_CAP_NORFLASH; - map->fldrv = &cfi_intelext_chipdrv; -- MOD_INC_USE_COUNT; - mtd->name = map->name; -+ __module_get(THIS_MODULE); - return mtd; - - setup_err: -@@ -301,78 +324,170 @@ - return NULL; - } - --static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) -+/* -+ * *********** CHIP ACCESS FUNCTIONS *********** -+ */ -+ -+static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode) - { -- cfi_word status, status_OK; -- unsigned long timeo; - DECLARE_WAITQUEUE(wait, current); -- unsigned long cmd_addr; - struct cfi_private *cfi = map->fldrv_priv; -+ cfi_word status, status_OK = CMD(0x80); -+ unsigned long timeo; -+ struct cfi_pri_intelext *cfip = (struct cfi_pri_intelext *)cfi->cmdset_priv; - -- adr += chip->start; -- -- /* Ensure cmd read/writes are aligned. */ -- cmd_addr = adr & ~(CFIDEV_BUSWIDTH-1); -- -- /* Let's determine this according to the interleave only once */ -- status_OK = CMD(0x80); -- -+ resettime: - timeo = jiffies + HZ; - retry: -- spin_lock(chip->mutex); -- -- /* Check that the chip's ready to talk to us. -- * If it's in FL_ERASING state, suspend it and make it talk now. -- */ - switch (chip->state) { - -- case FL_READY: -- case FL_POINT: -+ case FL_STATUS: -+ for (;;) { -+ status = cfi_read(map, adr); -+ if ((status & status_OK) == status_OK) - break; - -+ if (time_after(jiffies, timeo)) { -+ printk(KERN_ERR "Waiting for chip to be ready timed out. Status %llx\n", -+ (long long)status); -+ spin_unlock(chip->mutex); -+ return -EIO; -+ } -+ spin_unlock(chip->mutex); -+ cfi_udelay(1); -+ spin_lock(chip->mutex); -+ /* Someone else might have been playing with it. */ -+ goto retry; -+ } -+ -+ case FL_READY: - case FL_CFI_QUERY: - case FL_JEDEC_QUERY: -- cfi_write(map, CMD(0x70), cmd_addr); -- chip->state = FL_STATUS; -+ return 0; - -- case FL_STATUS: -- status = cfi_read(map, cmd_addr); -- if ((status & status_OK) == status_OK) { -- cfi_write(map, CMD(0xff), cmd_addr); -- chip->state = FL_READY; -+ case FL_ERASING: -+ if (!(cfip->FeatureSupport & 2) || -+ !(mode == FL_READY || mode == FL_POINT || -+ (mode == FL_WRITING && (cfip->SuspendCmdSupport & 1)))) -+ goto sleep; -+ -+ -+ /* Erase suspend */ -+ cfi_write(map, CMD(0xB0), adr); -+ -+ /* If the flash has finished erasing, then 'erase suspend' -+ * appears to make some (28F320) flash devices switch to -+ * 'read' mode. Make sure that we switch to 'read status' -+ * mode so we get the right data. --rmk -+ */ -+ cfi_write(map, CMD(0x70), adr); -+ chip->oldstate = FL_ERASING; -+ chip->state = FL_ERASE_SUSPENDING; -+ chip->erase_suspended = 1; -+ for (;;) { -+ status = cfi_read(map, adr); -+ if ((status & status_OK) == status_OK) - break; -- } - -- /* Urgh. Chip not yet ready to talk to us. */ - if (time_after(jiffies, timeo)) { -- spin_unlock(chip->mutex); -- printk(KERN_ERR "waiting for chip to be ready timed out in read. WSM status = %llx\n", (__u64)status); -+ /* Urgh. Resume and pretend we weren't here. */ -+ cfi_write(map, CMD(0xd0), adr); -+ /* Make sure we're in 'read status' mode if it had finished */ -+ cfi_write(map, CMD(0x70), adr); -+ chip->state = FL_ERASING; -+ chip->oldstate = FL_READY; -+ printk(KERN_ERR "Chip not ready after erase " -+ "suspended: status = 0x%x\n", status); - return -EIO; - } - -- /* Latency issues. Drop the lock, wait a while and retry */ - spin_unlock(chip->mutex); - cfi_udelay(1); -- goto retry; -+ spin_lock(chip->mutex); -+ /* Nobody will touch it while it's in state FL_ERASE_SUSPENDING. -+ So we can just loop here. */ -+ } -+ chip->state = FL_STATUS; -+ return 0; -+ -+ case FL_POINT: -+ /* Only if there's no operation suspended... */ -+ if (mode == FL_READY && chip->oldstate == FL_READY) -+ return 0; - - default: -- /* Stick ourselves on a wait queue to be woken when -- someone changes the status */ -+ sleep: - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); -- timeo = jiffies + HZ; -- goto retry; -+ spin_lock(chip->mutex); -+ goto resettime; - } -+} -+ -+static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ -+ switch(chip->oldstate) { -+ case FL_ERASING: -+ chip->state = chip->oldstate; -+ /* What if one interleaved chip has finished and the -+ other hasn't? The old code would leave the finished -+ one in READY mode. That's bad, and caused -EROFS -+ errors to be returned from do_erase_oneblock because -+ that's the only bit it checked for at the time. -+ As the state machine appears to explicitly allow -+ sending the 0x70 (Read Status) command to an erasing -+ chip and expecting it to be ignored, that's what we -+ do. */ -+ cfi_write(map, CMD(0xd0), adr); -+ cfi_write(map, CMD(0x70), adr); -+ chip->oldstate = FL_READY; -+ chip->state = FL_ERASING; -+ break; -+ -+ case FL_READY: -+ case FL_STATUS: -+ /* We should really make set_vpp() count, rather than doing this */ -+ DISABLE_VPP(map); -+ break; -+ default: -+ printk(KERN_ERR "put_chip() called with oldstate %d!!\n", chip->oldstate); -+ } -+ wake_up(&chip->wq); -+} -+ -+static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) -+{ -+ unsigned long cmd_addr; -+ struct cfi_private *cfi = map->fldrv_priv; -+ int ret = 0; -+ -+ adr += chip->start; -+ -+ /* Ensure cmd read/writes are aligned. */ -+ cmd_addr = adr & ~(CFIDEV_BUSWIDTH-1); -+ -+ spin_lock(chip->mutex); -+ -+ ret = get_chip(map, chip, cmd_addr, FL_POINT); -+ -+ if (!ret) { -+ if (chip->state != FL_POINT && chip->state != FL_READY) -+ cfi_write(map, CMD(0xff), cmd_addr); - - chip->state = FL_POINT; - chip->ref_point_counter++; -+ } - spin_unlock(chip->mutex); -- return 0; -+ -+ return ret; - } --static int do_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) -+ -+static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) - { - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; -@@ -380,12 +495,10 @@ - int chipnum; - int ret = 0; - -- if (from + len > mtd->size) -+ if (!map->virt || (from + len > mtd->size)) - return -EINVAL; - -- *mtdbuf = map->point(map, from, len); -- if(*mtdbuf == NULL) -- return -EINVAL; /* can not point this region */ -+ *mtdbuf = (void *)map->virt + from; - *retlen = 0; - - /* Now lock the chip(s) to POINT state */ -@@ -418,14 +531,13 @@ - return 0; - } - --static void do_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) -+static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) - { - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - unsigned long ofs; - int chipnum; - -- map->unpoint(map, addr, from, len); - /* Now unlock the chip(s) POINT state */ - - /* ofs: offset within the first chip that the first read should start */ -@@ -446,13 +558,14 @@ - thislen = len; - - spin_lock(chip->mutex); -- if(chip->state == FL_POINT){ -+ if (chip->state == FL_POINT) { - chip->ref_point_counter--; - if(chip->ref_point_counter == 0) - chip->state = FL_READY; - } else -- printk("Warning: unpoint called on non pointed region\n"); /* Should this give an error? */ -- wake_up(&chip->wq); -+ printk(KERN_ERR "Warning: unpoint called on non pointed region\n"); /* Should this give an error? */ -+ -+ put_chip(map, chip, chip->start); - spin_unlock(chip->mutex); - - len -= thislen; -@@ -463,136 +576,32 @@ - - static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) - { -- cfi_word status, status_OK; -- unsigned long timeo; -- DECLARE_WAITQUEUE(wait, current); -- int suspended = 0; - unsigned long cmd_addr; - struct cfi_private *cfi = map->fldrv_priv; -+ int ret; - - adr += chip->start; - - /* Ensure cmd read/writes are aligned. */ - cmd_addr = adr & ~(CFIDEV_BUSWIDTH-1); - -- /* Let's determine this according to the interleave only once */ -- status_OK = CMD(0x80); -- -- timeo = jiffies + HZ; -- retry: - spin_lock(chip->mutex); -- -- /* Check that the chip's ready to talk to us. -- * If it's in FL_ERASING state, suspend it and make it talk now. -- */ -- switch (chip->state) { -- case FL_ERASING: -- if (!cfi->cmdset_priv || -- !(((struct cfi_pri_intelext *)cfi->cmdset_priv)->FeatureSupport & 2)) -- goto sleep; /* We don't support erase suspend */ -- -- cfi_write (map, CMD(0xb0), cmd_addr); -- /* If the flash has finished erasing, then 'erase suspend' -- * appears to make some (28F320) flash devices switch to -- * 'read' mode. Make sure that we switch to 'read status' -- * mode so we get the right data. --rmk -- */ -- cfi_write(map, CMD(0x70), cmd_addr); -- chip->oldstate = FL_ERASING; -- chip->state = FL_ERASE_SUSPENDING; -- // printk("Erase suspending at 0x%lx\n", cmd_addr); -- for (;;) { -- status = cfi_read(map, cmd_addr); -- if ((status & status_OK) == status_OK) -- break; -- -- if (time_after(jiffies, timeo)) { -- /* Urgh */ -- cfi_write(map, CMD(0xd0), cmd_addr); -- /* make sure we're in 'read status' mode */ -- cfi_write(map, CMD(0x70), cmd_addr); -- chip->state = FL_ERASING; -- spin_unlock(chip->mutex); -- printk(KERN_ERR "Chip not ready after erase " -- "suspended: status = 0x%llx\n", (__u64)status); -- return -EIO; -- } -- -+ ret = get_chip(map, chip, cmd_addr, FL_READY); -+ if (ret) { - spin_unlock(chip->mutex); -- cfi_udelay(1); -- spin_lock(chip->mutex); -+ return ret; - } - -- suspended = 1; -+ if (chip->state != FL_POINT && chip->state != FL_READY) { - cfi_write(map, CMD(0xff), cmd_addr); -- chip->state = FL_READY; -- break; -- --#if 0 -- case FL_WRITING: -- /* Not quite yet */ --#endif -- -- case FL_READY: -- case FL_POINT: -- break; -- -- case FL_CFI_QUERY: -- case FL_JEDEC_QUERY: -- cfi_write(map, CMD(0x70), cmd_addr); -- chip->state = FL_STATUS; - -- case FL_STATUS: -- status = cfi_read(map, cmd_addr); -- if ((status & status_OK) == status_OK) { -- cfi_write(map, CMD(0xff), cmd_addr); - chip->state = FL_READY; -- break; - } - -- /* Urgh. Chip not yet ready to talk to us. */ -- if (time_after(jiffies, timeo)) { -- spin_unlock(chip->mutex); -- printk(KERN_ERR "waiting for chip to be ready timed out in read. WSM status = %llx\n", (__u64)status); -- return -EIO; -- } -+ map_copy_from(map, buf, adr, len); - -- /* Latency issues. Drop the lock, wait a while and retry */ -- spin_unlock(chip->mutex); -- cfi_udelay(1); -- goto retry; -+ put_chip(map, chip, cmd_addr); - -- default: -- sleep: -- /* Stick ourselves on a wait queue to be woken when -- someone changes the status */ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -- spin_unlock(chip->mutex); -- schedule(); -- remove_wait_queue(&chip->wq, &wait); -- timeo = jiffies + HZ; -- goto retry; -- } -- -- map->copy_from(map, buf, adr, len); -- -- if (suspended) { -- chip->state = chip->oldstate; -- /* What if one interleaved chip has finished and the -- other hasn't? The old code would leave the finished -- one in READY mode. That's bad, and caused -EROFS -- errors to be returned from do_erase_oneblock because -- that's the only bit it checked for at the time. -- As the state machine appears to explicitly allow -- sending the 0x70 (Read Status) command to an erasing -- chip and expecting it to be ignored, that's what we -- do. */ -- cfi_write(map, CMD(0xd0), cmd_addr); -- cfi_write(map, CMD(0x70), cmd_addr); -- } -- -- wake_up(&chip->wq); - spin_unlock(chip->mutex); - return 0; - } -@@ -640,70 +649,52 @@ - { - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; -- struct cfi_pri_intelext *extp=cfi->cmdset_priv; -- int ofs_factor = cfi->interleave * cfi->device_type; -- int count=len; -+ struct cfi_pri_intelext *extp = cfi->cmdset_priv; - struct flchip *chip; -- int chip_num,offst; -- unsigned long timeo; -- DECLARE_WAITQUEUE(wait, current); -+ int ofs_factor = cfi->interleave * cfi->device_type; -+ int count = len; -+ int chip_num, offst; -+ int ret; - -- chip=0; -- /* Calculate which chip & protection register offset we need */ -- chip_num=((unsigned int)from/reg_sz); -- offst=from-(reg_sz*chip_num)+base_offst; -+ chip_num = ((unsigned int)from/reg_sz); -+ offst = from - (reg_sz*chip_num)+base_offst; - -- while(count){ -+ while (count) { -+ /* Calculate which chip & protection register offset we need */ - -- if(chip_num>=cfi->numchips) -+ if (chip_num >= cfi->numchips) - goto out; - -- /* Make sure that the chip is in the right state */ -+ chip = &cfi->chips[chip_num]; - -- timeo = jiffies + HZ; -- chip=&cfi->chips[chip_num]; -- retry: - spin_lock(chip->mutex); -- -- switch (chip->state) { -- case FL_READY: -- case FL_STATUS: -- case FL_CFI_QUERY: -- case FL_JEDEC_QUERY: -- break; -- -- default: -- /* Stick ourselves on a wait queue to be woken when -- someone changes the status */ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ ret = get_chip(map, chip, chip->start, FL_JEDEC_QUERY); -+ if (ret) { - spin_unlock(chip->mutex); -- schedule(); -- remove_wait_queue(&chip->wq, &wait); -- timeo = jiffies + HZ; -- goto retry; -+ return (len-count)?:ret; - } - -- /* Now read the data required from this flash */ -+ if (chip->state != FL_JEDEC_QUERY) { -+ cfi_write(map, CMD(0x90), chip->start); -+ chip->state = FL_JEDEC_QUERY; -+ } - -- cfi_send_gen_cmd(0x90, 0x55,chip->start, map, cfi, cfi->device_type, NULL); -- while(count && ((offst-base_offst)read8(map,(chip->start+((extp->ProtRegAddr+1)*ofs_factor)+offst)); -+ while (count && ((offst-base_offst) < reg_sz)) { -+ *buf = map_read8(map,(chip->start+((extp->ProtRegAddr+1)*ofs_factor)+offst)); - buf++; - offst++; - count--; - } - -- chip->state=FL_CFI_QUERY; -+ put_chip(map, chip, chip->start); - spin_unlock(chip->mutex); -+ - /* Move on to the next chip */ - chip_num++; -- offst=base_offst; -- -+ offst = base_offst; - } - - out: -- wake_up(&chip->wq); - return len-count; - } - -@@ -749,103 +740,20 @@ - static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, cfi_word datum) - { - struct cfi_private *cfi = map->fldrv_priv; -- struct cfi_pri_intelext *extp = cfi->cmdset_priv; -- cfi_word status, status_OK; -- unsigned long timeo; -- DECLARE_WAITQUEUE(wait, current); -- int z, suspended=0, ret=0; -- -- adr += chip->start; -- -- /* Let's determine this according to the interleave only once */ -- status_OK = CMD(0x80); -- -- timeo = jiffies + HZ; -- retry: -- spin_lock(chip->mutex); -- -- /* Check that the chip's ready to talk to us. -- * Later, we can actually think about interrupting it -- * if it's in FL_ERASING state. -- * Not just yet, though. -- */ -- switch (chip->state) { -- case FL_READY: -- break; -- -- case FL_CFI_QUERY: -- case FL_JEDEC_QUERY: -- cfi_write(map, CMD(0x70), adr); -- chip->state = FL_STATUS; -- -- case FL_STATUS: -- status = cfi_read(map, adr); -- if ((status & status_OK) == status_OK) -- break; -- -- /* Urgh. Chip not yet ready to talk to us. */ -- if (time_after(jiffies, timeo)) { -- spin_unlock(chip->mutex); -- printk(KERN_ERR "waiting for chip to be ready timed out in read\n"); -- return -EIO; -- } -- -- /* Latency issues. Drop the lock, wait a while and retry */ -- spin_unlock(chip->mutex); -- cfi_udelay(1); -- goto retry; -- -- case FL_ERASING: -- if (!extp || -- !((extp->FeatureSupport & 2) && (extp->SuspendCmdSupport & 1))) -- goto sleep; /* We don't support erase suspend */ -- -- cfi_write (map, CMD(0xb0), adr); -- -- /* If the flash has finished erasing, then 'erase suspend' -- * appears to make some (28F320) flash devices switch to -- * 'read' mode. Make sure that we switch to 'read status' -- * mode so we get the right data. --rmk -- */ -- cfi_write(map, CMD(0x70), adr); -- chip->oldstate = FL_ERASING; -- chip->state = FL_ERASE_SUSPENDING; -- for (;;) { -- status = cfi_read(map, adr); -- if ((status & status_OK) == status_OK) -- break; -+ cfi_word status, status_OK; -+ unsigned long timeo; -+ int z, ret=0; - -- if (time_after(jiffies, timeo)) { -- /* Urgh */ -- cfi_write(map, CMD(0xd0), adr); -- /* make sure we're in 'read status' mode */ -- cfi_write(map, CMD(0x70), adr); -- chip->state = FL_ERASING; -- spin_unlock(chip->mutex); -- printk(KERN_ERR "Chip not ready after erase " -- "suspended: status = 0x%x\n", status); -- return -EIO; -- } -+ adr += chip->start; - -- spin_unlock(chip->mutex); -- cfi_udelay(1); -- spin_lock(chip->mutex); -- } -- suspended = 1; -- chip->state = FL_STATUS; -- break; -+ /* Let's determine this according to the interleave only once */ -+ status_OK = CMD(0x80); - -- default: -- sleep: -- /* Stick ourselves on a wait queue to be woken when -- someone changes the status */ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ spin_lock(chip->mutex); -+ ret = get_chip(map, chip, adr, FL_WRITING); -+ if (ret) { - spin_unlock(chip->mutex); -- schedule(); -- remove_wait_queue(&chip->wq, &wait); -- timeo = jiffies + HZ; -- goto retry; -+ return ret; - } - - ENABLE_VPP(map); -@@ -862,6 +770,8 @@ - for (;;) { - if (chip->state != FL_WRITING) { - /* Someone's suspended the write. Sleep */ -+ DECLARE_WAITQUEUE(wait, current); -+ - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - spin_unlock(chip->mutex); -@@ -879,7 +789,6 @@ - /* OK Still waiting */ - if (time_after(jiffies, timeo)) { - chip->state = FL_STATUS; -- DISABLE_VPP(map); - printk(KERN_ERR "waiting for chip to be ready timed out in word write\n"); - ret = -EIO; - goto out; -@@ -908,27 +817,11 @@ - /* put back into read status register mode */ - cfi_write(map, CMD(0x70), adr); - ret = -EROFS; -- goto out; - } - out: -- if (suspended) { -- chip->state = chip->oldstate; -- /* What if one interleaved chip has finished and the -- other hasn't? The old code would leave the finished -- one in READY mode. That's bad, and caused -EROFS -- errors to be returned from do_erase_oneblock because -- that's the only bit it checked for at the time. -- As the state machine appears to explicitly allow -- sending the 0x70 (Read Status) command to an erasing -- chip and expecting it to be ignored, that's what we -- do. */ -- cfi_write(map, CMD(0xd0), adr); -- cfi_write(map, CMD(0x70), adr); -- } else -- DISABLE_VPP(map); /* must not clear the VPP if there is a suspended erase to be resumed */ -- -- wake_up(&chip->wq); -+ put_chip(map, chip, adr); - spin_unlock(chip->mutex); -+ - return ret; - } - -@@ -1059,11 +952,9 @@ - unsigned long adr, const u_char *buf, int len) - { - struct cfi_private *cfi = map->fldrv_priv; -- struct cfi_pri_intelext *extp = cfi->cmdset_priv; - cfi_word status, status_OK; - unsigned long cmd_adr, timeo; -- DECLARE_WAITQUEUE(wait, current); -- int wbufsize, z, suspended=0, ret=0; -+ int wbufsize, z, ret=0, bytes, words; - - wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize; - adr += chip->start; -@@ -1072,91 +963,18 @@ - /* Let's determine this according to the interleave only once */ - status_OK = CMD(0x80); - -- timeo = jiffies + HZ; -- retry: - spin_lock(chip->mutex); -- -- /* Check that the chip's ready to talk to us. -- * Later, we can actually think about interrupting it -- * if it's in FL_ERASING state. -- * Not just yet, though. -- */ -- switch (chip->state) { -- case FL_READY: -- case FL_CFI_QUERY: -- case FL_JEDEC_QUERY: -- cfi_write(map, CMD(0x70), cmd_adr); -- chip->state = FL_STATUS; -- -- case FL_STATUS: -- status = cfi_read(map, cmd_adr); -- if ((status & status_OK) == status_OK) -- break; -- /* Urgh. Chip not yet ready to talk to us. */ -- if (time_after(jiffies, timeo)) { -+ ret = get_chip(map, chip, cmd_adr, FL_WRITING); -+ if (ret) { - spin_unlock(chip->mutex); -- printk(KERN_ERR "waiting for chip to be ready timed out in buffer write\n"); -- return -EIO; -+ return ret; - } - -- /* Latency issues. Drop the lock, wait a while and retry */ -- spin_unlock(chip->mutex); -- cfi_udelay(1); -- goto retry; -- -- case FL_ERASING: -- if (!extp || -- !((extp->FeatureSupport & 2) && (extp->SuspendCmdSupport & 1))) -- goto sleep; /* We don't support erase suspend */ -- -- cfi_write (map, CMD(0xb0), adr); -- -- /* If the flash has finished erasing, then 'erase suspend' -- * appears to make some (28F320) flash devices switch to -- * 'read' mode. Make sure that we switch to 'read status' -- * mode so we get the right data. --rmk -- */ -- cfi_write(map, CMD(0x70), adr); -- chip->oldstate = FL_ERASING; -- chip->state = FL_ERASE_SUSPENDING; -- for (;;) { -- status = cfi_read(map, adr); -- if ((status & status_OK) == status_OK) -- break; -- -- if (time_after(jiffies, timeo)) { -- /* Urgh */ -- cfi_write(map, CMD(0xd0), adr); -- /* make sure we're in 'read status' mode */ -- cfi_write(map, CMD(0x70), adr); -- chip->state = FL_ERASING; -- spin_unlock(chip->mutex); -- printk(KERN_ERR "Chip not ready after erase " -- "suspended: status = 0x%x\n", status); -- return -EIO; -- } -+ if (chip->state != FL_STATUS) -+ cfi_write(map, CMD(0x70), cmd_adr); - -- spin_unlock(chip->mutex); -- cfi_udelay(1); -- spin_lock(chip->mutex); -- } -- suspended = 1; -- chip->state = FL_STATUS; -- break; -+ status = cfi_read(map, cmd_adr); - -- default: -- sleep: -- /* Stick ourselves on a wait queue to be woken when -- someone changes the status */ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -- spin_unlock(chip->mutex); -- schedule(); -- remove_wait_queue(&chip->wq, &wait); -- timeo = jiffies + HZ; -- goto retry; -- } -- /* We know we're now in FL_STATUS mode, and 'status' is current */ - /* §4.8 of the 28FxxxJ3A datasheet says "Any time SR.4 and/or SR.5 is set - [...], the device will not accept any more Write to Buffer commands". - So we must check here and reset those bits if they're set. Otherwise -@@ -1185,7 +1003,6 @@ - /* Argh. Not ready for write to buffer */ - cfi_write(map, CMD(0x70), cmd_adr); - chip->state = FL_STATUS; -- DISABLE_VPP(map); - printk(KERN_ERR "Chip not ready for buffer write. Xstatus = %llx, status = %llx\n", (__u64)status, (__u64)cfi_read(map, cmd_adr)); - /* Odd. Clear status bits */ - cfi_write(map, CMD(0x50), cmd_adr); -@@ -1196,20 +1013,42 @@ - } - - /* Write length of data to come */ -- cfi_write(map, CMD(len/CFIDEV_BUSWIDTH-1), cmd_adr ); -+ bytes = len & (CFIDEV_BUSWIDTH-1); -+ words = len / CFIDEV_BUSWIDTH; -+ cfi_write(map, CMD(words - !bytes), cmd_adr ); - - /* Write data */ -- for (z = 0; z < len; z += CFIDEV_BUSWIDTH) { -+ z = 0; -+ while(z < words * CFIDEV_BUSWIDTH) { - if (cfi_buswidth_is_1()) { -- map->write8 (map, *((__u8*)buf)++, adr+z); -+ map_write8 (map, *((__u8*)buf)++, adr+z); - } else if (cfi_buswidth_is_2()) { -- map->write16 (map, *((__u16*)buf)++, adr+z); -+ map_write16 (map, *((__u16*)buf)++, adr+z); - } else if (cfi_buswidth_is_4()) { -- map->write32 (map, *((__u32*)buf)++, adr+z); -+ map_write32 (map, *((__u32*)buf)++, adr+z); - } else if (cfi_buswidth_is_8()) { -- map->write64 (map, *((__u64*)buf)++, adr+z); -+ map_write64 (map, *((__u64*)buf)++, adr+z); -+ } else { -+ ret = -EINVAL; -+ goto out; -+ } -+ z += CFIDEV_BUSWIDTH; -+ } -+ if (bytes) { -+ int i = 0, n = 0; -+ u_char tmp_buf[8], *tmp_p = tmp_buf; -+ -+ while (bytes--) -+ tmp_buf[i++] = buf[n++]; -+ while (i < CFIDEV_BUSWIDTH) -+ tmp_buf[i++] = 0xff; -+ if (cfi_buswidth_is_2()) { -+ map_write16 (map, *((__u16*)tmp_p)++, adr+z); -+ } else if (cfi_buswidth_is_4()) { -+ map_write32 (map, *((__u32*)tmp_p)++, adr+z); -+ } else if (cfi_buswidth_is_8()) { -+ map_write64 (map, *((__u64*)tmp_p)++, adr+z); - } else { -- DISABLE_VPP(map); - ret = -EINVAL; - goto out; - } -@@ -1227,6 +1066,7 @@ - for (;;) { - if (chip->state != FL_WRITING) { - /* Someone's suspended the write. Sleep */ -+ DECLARE_WAITQUEUE(wait, current); - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - spin_unlock(chip->mutex); -@@ -1244,7 +1084,6 @@ - /* OK Still waiting */ - if (time_after(jiffies, timeo)) { - chip->state = FL_STATUS; -- DISABLE_VPP(map); - printk(KERN_ERR "waiting for chip to be ready timed out in bufwrite\n"); - ret = -EIO; - goto out; -@@ -1266,6 +1105,7 @@ - - /* Done and happy. */ - chip->state = FL_STATUS; -+ - /* check for lock bit */ - if (status & CMD(0x02)) { - /* clear status */ -@@ -1273,26 +1113,10 @@ - /* put back into read status register mode */ - cfi_write(map, CMD(0x70), adr); - ret = -EROFS; -- goto out; - } -- out: -- if (suspended) { -- chip->state = chip->oldstate; -- /* What if one interleaved chip has finished and the -- other hasn't? The old code would leave the finished -- one in READY mode. That's bad, and caused -EROFS -- errors to be returned from do_erase_oneblock because -- that's the only bit it checked for at the time. -- As the state machine appears to explicitly allow -- sending the 0x70 (Read Status) command to an erasing -- chip and expecting it to be ignored, that's what we -- do. */ -- cfi_write(map, CMD(0xd0), adr); -- cfi_write(map, CMD(0x70), adr); -- } else -- DISABLE_VPP(map); /* must not clear the VPP if there is a suspended erase to be resumed */ - -- wake_up(&chip->wq); -+ out: -+ put_chip(map, chip, cmd_adr); - spin_unlock(chip->mutex); - return ret; - } -@@ -1336,12 +1160,12 @@ - } - - /* Write buffer is worth it only if more than one word to write... */ -- while(len > CFIDEV_BUSWIDTH) { -+ while(len) { - /* We must not cross write block boundaries */ - int size = wbufsize - (ofs & (wbufsize-1)); - - if (size > len) -- size = len & ~(CFIDEV_BUSWIDTH-1); -+ size = len; - ret = do_write_buffer(map, &cfi->chips[chipnum], - ofs, buf, size); - if (ret) -@@ -1359,17 +1183,6 @@ - return 0; - } - } -- -- /* ... and write the remaining bytes */ -- if (len > 0) { -- size_t local_retlen; -- ret = cfi_intelext_write_words(mtd, ofs + (chipnum << cfi->chipshift), -- len, &local_retlen, buf); -- if (ret) -- return ret; -- (*retlen) += local_retlen; -- } -- - return 0; - } - -@@ -1479,45 +1292,12 @@ - /* Let's determine this according to the interleave only once */ - status_OK = CMD(0x80); - -- timeo = jiffies + HZ; --retry: -+ retry: - spin_lock(chip->mutex); -- -- /* Check that the chip's ready to talk to us. */ -- switch (chip->state) { -- case FL_CFI_QUERY: -- case FL_JEDEC_QUERY: -- case FL_READY: -- cfi_write(map, CMD(0x70), adr); -- chip->state = FL_STATUS; -- -- case FL_STATUS: -- status = cfi_read(map, adr); -- if ((status & status_OK) == status_OK) -- break; -- -- /* Urgh. Chip not yet ready to talk to us. */ -- if (time_after(jiffies, timeo)) { -- spin_unlock(chip->mutex); -- printk(KERN_ERR "waiting for chip to be ready timed out in erase\n"); -- return -EIO; -- } -- -- /* Latency issues. Drop the lock, wait a while and retry */ -- spin_unlock(chip->mutex); -- cfi_udelay(1); -- goto retry; -- -- default: -- /* Stick ourselves on a wait queue to be woken when -- someone changes the status */ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ ret = get_chip(map, chip, adr, FL_ERASING); -+ if (ret) { - spin_unlock(chip->mutex); -- schedule(); -- remove_wait_queue(&chip->wq, &wait); -- timeo = jiffies + HZ; -- goto retry; -+ return ret; - } - - ENABLE_VPP(map); -@@ -1528,7 +1308,7 @@ - cfi_write(map, CMD(0x20), adr); - cfi_write(map, CMD(0xD0), adr); - chip->state = FL_ERASING; -- chip->oldstate = 0; -+ chip->erase_suspended = 0; - - spin_unlock(chip->mutex); - set_current_state(TASK_UNINTERRUPTIBLE); -@@ -1550,11 +1330,11 @@ - spin_lock(chip->mutex); - continue; - } -- if (chip->oldstate) { -+ if (chip->erase_suspended) { - /* This erase was suspended and resumed. - Adjust the timeout */ - timeo = jiffies + (HZ*20); /* FIXME */ -- chip->oldstate = 0; -+ chip->erase_suspended = 0; - } - - status = cfi_read(map, adr); -@@ -1658,39 +1438,22 @@ - int i; - struct flchip *chip; - int ret = 0; -- DECLARE_WAITQUEUE(wait, current); - - for (i=0; !ret && inumchips; i++) { - chip = &cfi->chips[i]; - -- retry: - spin_lock(chip->mutex); -+ ret = get_chip(map, chip, chip->start, FL_SYNCING); - -- switch(chip->state) { -- case FL_READY: -- case FL_STATUS: -- case FL_CFI_QUERY: -- case FL_JEDEC_QUERY: -+ if (!ret) { - chip->oldstate = chip->state; - chip->state = FL_SYNCING; - /* No need to wake_up() on this state change - - * as the whole point is that nobody can do anything - * with the chip now anyway. - */ -- case FL_SYNCING: -- spin_unlock(chip->mutex); -- break; -- -- default: -- /* Not an idle state */ -- add_wait_queue(&chip->wq, &wait); -- -- spin_unlock(chip->mutex); -- schedule(); -- remove_wait_queue(&chip->wq, &wait); -- -- goto retry; - } -+ spin_unlock(chip->mutex); - } - - /* Unlock the chips again */ -@@ -1731,52 +1494,18 @@ - struct cfi_private *cfi = map->fldrv_priv; - cfi_word status, status_OK; - unsigned long timeo = jiffies + HZ; -- DECLARE_WAITQUEUE(wait, current); -+ int ret; - - adr += chip->start; - - /* Let's determine this according to the interleave only once */ - status_OK = CMD(0x80); - -- timeo = jiffies + HZ; --retry: - spin_lock(chip->mutex); -- -- /* Check that the chip's ready to talk to us. */ -- switch (chip->state) { -- case FL_CFI_QUERY: -- case FL_JEDEC_QUERY: -- case FL_READY: -- cfi_write(map, CMD(0x70), adr); -- chip->state = FL_STATUS; -- -- case FL_STATUS: -- status = cfi_read(map, adr); -- if ((status & status_OK) == status_OK) -- break; -- -- /* Urgh. Chip not yet ready to talk to us. */ -- if (time_after(jiffies, timeo)) { -- spin_unlock(chip->mutex); -- printk(KERN_ERR "%s: waiting for chip to be ready timed out\n", __FUNCTION__); -- return -EIO; -- } -- -- /* Latency issues. Drop the lock, wait a while and retry */ -- spin_unlock(chip->mutex); -- cfi_udelay(1); -- goto retry; -- -- default: -- /* Stick ourselves on a wait queue to be woken when -- someone changes the status */ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ ret = get_chip(map, chip, adr, FL_LOCKING); -+ if (ret) { - spin_unlock(chip->mutex); -- schedule(); -- remove_wait_queue(&chip->wq, &wait); -- timeo = jiffies + HZ; -- goto retry; -+ return ret; - } - - ENABLE_VPP(map); -@@ -1823,8 +1552,7 @@ - - /* Done and happy. */ - chip->state = FL_STATUS; -- DISABLE_VPP(map); -- wake_up(&chip->wq); -+ put_chip(map, chip, adr); - spin_unlock(chip->mutex); - return 0; - } -@@ -1889,22 +1617,23 @@ - - spin_lock(chip->mutex); - -- switch(chip->state) { -+ switch (chip->state) { - case FL_READY: - case FL_STATUS: - case FL_CFI_QUERY: - case FL_JEDEC_QUERY: -+ if (chip->oldstate == FL_READY) { - chip->oldstate = chip->state; - chip->state = FL_PM_SUSPENDED; - /* No need to wake_up() on this state change - - * as the whole point is that nobody can do anything - * with the chip now anyway. - */ -- case FL_PM_SUSPENDED: -+ } - break; -- - default: - ret = -EAGAIN; -+ case FL_PM_SUSPENDED: - break; - } - spin_unlock(chip->mutex); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/cfi_cmdset_0002.c linux/drivers/mtd/chips/cfi_cmdset_0002.c ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/cfi_cmdset_0002.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/chips/cfi_cmdset_0002.c 2004-11-17 18:17:58.937329424 +0100 -@@ -6,16 +6,22 @@ - * - * 2_by_8 routines added by Simon Munton - * -+ * 4_by_16 work by Carolyn J. Smith -+ * -+ * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com -+ * - * This code is GPL - * -- * $Id$ -+ * $Id$ - * - */ - -+#include - #include - #include - #include - #include -+#include - #include - #include - -@@ -23,16 +29,50 @@ - #include - #include - #include -+#include - #include -+#include - #include - - #define AMD_BOOTLOC_BUG -+#define FORCE_WORD_WRITE 0 -+ -+ -+/* -+ * This is an attempt to coalesce the retry logic in one place - that way -+ * there aren't #ifdefs scattered throughout. -+ */ -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+ -+#ifndef CONFIG_MTD_CFI_AMDSTD_RETRY_MAX -+#define CONFIG_MTD_CFI_AMDSTD_RETRY_MAX 0 -+#endif -+ -+#define RETRY_CMD_LABEL retry_cmd: do {} while (0) -+#define HANDLE_WACKY_STATE() handle_wacky_state(__func__, retry_cmd_cnt, adr, datum, prev_oldstatus, prev_status, oldstatus, status) -+static int retry_cmd_max = CONFIG_MTD_CFI_AMDSTD_RETRY_MAX; -+#define DECLARE_RETRY_CMD_CNT() int retry_cmd_cnt = 0 -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+#define CHECK_RETRIES() do { if (++retry_cmd_cnt <= retry_cmd_max) goto retry_cmd; } while (0) -+#endif -+ -+#else -+ -+#define RETRY_CMD_LABEL do {} while (0) -+#define HANDLE_WACKY_STATE() handle_wacky_state(__func__, adr, datum, prev_oldstatus, prev_status, oldstatus, status) -+#define DECLARE_RETRY_CMD_CNT() -+#define CHECK_RETRIES() -+ -+#endif /* !defined(CONFIG_MTD_CFI_AMDSTD_RETRY) */ -+ - - static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); --static int cfi_amdstd_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -+static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -+static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); - static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *); --static int cfi_amdstd_erase_onesize(struct mtd_info *, struct erase_info *); - static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *); -+static int cfi_amdstd_lock_varsize(struct mtd_info *, loff_t, size_t); -+static int cfi_amdstd_unlock_varsize(struct mtd_info *, loff_t, size_t); - static void cfi_amdstd_sync (struct mtd_info *); - static int cfi_amdstd_suspend (struct mtd_info *); - static void cfi_amdstd_resume (struct mtd_info *); -@@ -45,55 +85,136 @@ - - - static struct mtd_chip_driver cfi_amdstd_chipdrv = { -- probe: NULL, /* Not usable directly */ -- destroy: cfi_amdstd_destroy, -- name: "cfi_cmdset_0002", -- module: THIS_MODULE -+ .probe = NULL, /* Not usable directly */ -+ .destroy = cfi_amdstd_destroy, -+ .name = "cfi_cmdset_0002", -+ .module = THIS_MODULE - }; - --struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) -+ -+/* #define DEBUG_LOCK_BITS */ -+/* #define DEBUG_CFI_FEATURES */ -+ -+ -+#ifdef DEBUG_CFI_FEATURES -+static void cfi_tell_features(struct cfi_pri_amdstd *extp) - { -- struct cfi_private *cfi = map->fldrv_priv; -- unsigned char bootloc; -- int ofs_factor = cfi->interleave * cfi->device_type; -- int i; -- __u8 major, minor; -- __u32 base = cfi->chips[0].start; -+ const char* erase_suspend[3] = { -+ "Not supported", "Read only", "Read/write" -+ }; -+ const char* top_bottom[6] = { -+ "No WP", "8x8KiB sectors at top & bottom, no WP", -+ "Bottom boot", "Top boot", -+ "Uniform, Bottom WP", "Uniform, Top WP" -+ }; -+ -+ printk(" Silicon revision: %d\n", extp->SiliconRevision >> 1); -+ printk(" Address sensitive unlock: %s\n", -+ (extp->SiliconRevision & 1) ? "Not required" : "Required"); - -- if (cfi->cfi_mode==CFI_MODE_CFI){ -- __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; -+ if (extp->EraseSuspend < ARRAY_SIZE(erase_suspend)) -+ printk(" Erase Suspend: %s\n", erase_suspend[extp->EraseSuspend]); -+ else -+ printk(" Erase Suspend: Unknown value %d\n", extp->EraseSuspend); - -- cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); -+ if (extp->BlkProt == 0) -+ printk(" Block protection: Not supported\n"); -+ else -+ printk(" Block protection: %d sectors per group\n", extp->BlkProt); -+ -+ -+ printk(" Temporary block unprotect: %s\n", -+ extp->TmpBlkUnprotect ? "Supported" : "Not supported"); -+ printk(" Block protect/unprotect scheme: %d\n", extp->BlkProtUnprot); -+ printk(" Number of simultaneous operations: %d\n", extp->SimultaneousOps); -+ printk(" Burst mode: %s\n", -+ extp->BurstMode ? "Supported" : "Not supported"); -+ if (extp->PageMode == 0) -+ printk(" Page mode: Not supported\n"); -+ else -+ printk(" Page mode: %d word page\n", extp->PageMode << 2); - -- major = cfi_read_query(map, base + (adr+3)*ofs_factor); -- minor = cfi_read_query(map, base + (adr+4)*ofs_factor); -+ printk(" Vpp Supply Minimum Program/Erase Voltage: %d.%d V\n", -+ extp->VppMin >> 4, extp->VppMin & 0xf); -+ printk(" Vpp Supply Maximum Program/Erase Voltage: %d.%d V\n", -+ extp->VppMax >> 4, extp->VppMax & 0xf); - -- printk(KERN_NOTICE " Amd/Fujitsu Extended Query Table v%c.%c at 0x%4.4X\n", -- major, minor, adr); -- cfi_send_gen_cmd(0xf0, 0x55, base, map, cfi, cfi->device_type, NULL); -- -- cfi_send_gen_cmd(0xaa, 0x555, base, map, cfi, cfi->device_type, NULL); -- cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL); -- cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL); -- cfi->mfr = cfi_read_query(map, base); -- cfi->id = cfi_read_query(map, base + ofs_factor); -+ if (extp->TopBottom < ARRAY_SIZE(top_bottom)) -+ printk(" Top/Bottom Boot Block: %s\n", top_bottom[extp->TopBottom]); -+ else -+ printk(" Top/Bottom Boot Block: Unknown value %d\n", extp->TopBottom); -+} -+#endif - -- /* Wheee. Bring me the head of someone at AMD. */ - #ifdef AMD_BOOTLOC_BUG -+/* Wheee. Bring me the head of someone at AMD. */ -+static void fixup_amd_bootblock(struct map_info *map, void* param) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ struct cfi_pri_amdstd *extp = cfi->cmdset_priv; -+ __u8 major = extp->MajorVersion; -+ __u8 minor = extp->MinorVersion; -+ - if (((major << 8) | minor) < 0x3131) { - /* CFI version 1.0 => don't trust bootloc */ - if (cfi->id & 0x80) { - printk(KERN_WARNING "%s: JEDEC Device ID is 0x%02X. Assuming broken CFI table.\n", map->name, cfi->id); -- bootloc = 3; /* top boot */ -+ extp->TopBottom = 3; /* top boot */ - } else { -- bootloc = 2; /* bottom boot */ -+ extp->TopBottom = 2; /* bottom boot */ - } -- } else -+ } -+} - #endif -+ -+static struct cfi_fixup fixup_table[] = { -+#ifdef AMD_BOOTLOC_BUG - { -- cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); -- bootloc = cfi_read_query(map, base + (adr+15)*ofs_factor); -+ 0x0001, /* AMD */ -+ CFI_ID_ANY, -+ fixup_amd_bootblock, NULL -+ }, -+#endif -+ { 0, 0, NULL, NULL } -+}; -+ -+ -+struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ unsigned char bootloc; -+ int i; -+ -+ if (cfi->cfi_mode==CFI_MODE_CFI){ -+ /* -+ * It's a real CFI chip, not one for which the probe -+ * routine faked a CFI structure. So we read the feature -+ * table from it. -+ */ -+ __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; -+ struct cfi_pri_amdstd *extp; -+ -+ extp = (struct cfi_pri_amdstd*)cfi_read_pri(map, adr, sizeof(*extp), "Amd/Fujitsu"); -+ if (!extp) -+ return NULL; -+ -+ /* Install our own private info structure */ -+ cfi->cmdset_priv = extp; -+ -+ cfi_fixup(map, fixup_table); -+ -+#ifdef DEBUG_CFI_FEATURES -+ /* Tell the user about it in lots of lovely detail */ -+ cfi_tell_features(extp); -+#endif -+ -+ bootloc = extp->TopBottom; -+ if ((bootloc != 2) && (bootloc != 3)) { -+ printk(KERN_WARNING "%s: CFI does not contain boot " -+ "bank location. Assuming top.\n", map->name); -+ bootloc = 2; - } -+ - if (bootloc == 3 && cfi->cfiq->NumEraseRegions > 1) { - printk(KERN_WARNING "%s: Swapping erase regions for broken CFI table.\n", map->name); - -@@ -106,6 +227,11 @@ - cfi->cfiq->EraseRegionInfo[j] = swap; - } - } -+ /* -+ * These might already be setup (more correctly) by -+ * jedec_probe.c - still need it for cfi_probe.c path. -+ */ -+ if ( ! (cfi->addr_unlock1 && cfi->addr_unlock2) ) { - switch (cfi->device_type) { - case CFI_DEVICETYPE_X8: - cfi->addr_unlock1 = 0x555; -@@ -125,9 +251,13 @@ - cfi->addr_unlock2 = 0xaaa; - break; - default: -- printk(KERN_NOTICE "Eep. Unknown cfi_cmdset_0002 device type %d\n", cfi->device_type); -+ printk(KERN_WARNING -+ "MTD %s(): Unsupported device type %d\n", -+ __func__, cfi->device_type); - return NULL; - } -+ } -+ - } /* CFI mode */ - - for (i=0; i< cfi->numchips; i++) { -@@ -138,15 +268,17 @@ - - map->fldrv = &cfi_amdstd_chipdrv; - -- cfi_send_gen_cmd(0xf0, 0x55, base, map, cfi, cfi->device_type, NULL); - return cfi_amdstd_setup(map); - } - -+ - static struct mtd_info *cfi_amdstd_setup(struct map_info *map) - { - struct cfi_private *cfi = map->fldrv_priv; - struct mtd_info *mtd; - unsigned long devsize = (1<cfiq->DevSize) * cfi->interleave; -+ unsigned long offset = 0; -+ int i,j; - - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); - printk(KERN_NOTICE "number of %s chips: %d\n", -@@ -163,15 +295,9 @@ - /* Also select the correct geometry setup too */ - mtd->size = devsize * cfi->numchips; - -- if (cfi->cfiq->NumEraseRegions == 1) { -- /* No need to muck about with multiple erase sizes */ -- mtd->erasesize = ((cfi->cfiq->EraseRegionInfo[0] >> 8) & ~0xff) * cfi->interleave; -- } else { -- unsigned long offset = 0; -- int i,j; -- - mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; -- mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL); -+ mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) -+ * mtd->numeraseregions, GFP_KERNEL); - if (!mtd->eraseregions) { - printk(KERN_WARNING "Failed to allocate memory for MTD erase region info\n"); - goto setup_err; -@@ -206,39 +332,52 @@ - mtd->eraseregions[i].numblocks); - } - #endif -- } - - switch (CFIDEV_BUSWIDTH) - { - case 1: - case 2: - case 4: --#if 1 -- if (mtd->numeraseregions > 1) -- mtd->erase = cfi_amdstd_erase_varsize; -- else -+#ifdef CFI_WORD_64 -+ case 8: - #endif -- if (((cfi->cfiq->EraseRegionInfo[0] & 0xffff) + 1) == 1) -+ if (mtd->numeraseregions == 1 -+ && ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) + 1) == 1) { - mtd->erase = cfi_amdstd_erase_chip; -- else -- mtd->erase = cfi_amdstd_erase_onesize; -+ } else { -+ mtd->erase = cfi_amdstd_erase_varsize; -+ mtd->lock = cfi_amdstd_lock_varsize; -+ mtd->unlock = cfi_amdstd_unlock_varsize; -+ } -+ -+ if ( cfi->cfiq->BufWriteTimeoutTyp && !FORCE_WORD_WRITE) { -+ DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" ); -+ mtd->write = cfi_amdstd_write_buffers; -+ } else { -+ DEBUG(MTD_DEBUG_LEVEL1, "Using word write method\n" ); -+ mtd->write = cfi_amdstd_write_words; -+ } -+ - mtd->read = cfi_amdstd_read; -- mtd->write = cfi_amdstd_write; - break; - - default: -- printk(KERN_WARNING "Unsupported buswidth\n"); -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); - goto setup_err; - break; - } - if (cfi->fast_prog) { -- /* In cfi_amdstd_write() we frob the protection stuff -+ /* In cfi_amdstd_write_words() we frob the protection stuff - without paying any attention to the state machine. - This upsets in-progress erases. So we turn this flag - off for now till the code gets fixed. */ - printk(KERN_NOTICE "cfi_cmdset_0002: Disabling fast programming due to code brokenness.\n"); - cfi->fast_prog = 0; - } -+ /* FIXME: erase-suspend-program is broken. See -+ http://lists.infradead.org/pipermail/linux-mtd/2003-December/009001.html */ -+ printk(KERN_NOTICE "cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.\n"); - - - /* does this chip have a secsi area? */ -@@ -266,7 +405,7 @@ - mtd->flags = MTD_CAP_NORFLASH; - map->fldrv = &cfi_amdstd_chipdrv; - mtd->name = map->name; -- MOD_INC_USE_COUNT; -+ __module_get(THIS_MODULE); - return mtd; - - setup_err: -@@ -280,46 +419,210 @@ - return NULL; - } - --static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) -+ -+/* This is more work to coalesce the retry #ifdefs in one location */ -+static inline void handle_wacky_state(const char *func, -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+ int retry_cmd_cnt, -+#endif -+ unsigned long adr, -+ cfi_word datum, -+ cfi_word prev_oldstatus, -+ cfi_word prev_status, -+ cfi_word oldstatus, -+ cfi_word status) -+{ -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+ if ( retry_cmd_cnt == retry_cmd_max ) { -+#endif -+ printk(KERN_WARNING -+ "MTD %s(): Wacky! Unable to decode failure status\n" -+ "Possible buggy device - try " -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+ "increasing retry_cmd_max from %d\n" -+#else -+ "enabling CONFIG_MTD_CFI_AMDSTD_RETRY\n" -+ "in your kernel config and setting driver retry_cmd_max\n" -+#endif -+ , func -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+ , retry_cmd_max -+#endif -+ ); -+ -+ printk(KERN_WARNING -+ "MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", -+ func, adr, datum, -+ prev_oldstatus, prev_status, -+ oldstatus, status); -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+ } -+#endif -+} -+ -+ -+static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode) - { - DECLARE_WAITQUEUE(wait, current); -- unsigned long timeo = jiffies + HZ; -+ struct cfi_private *cfi = map->fldrv_priv; -+ cfi_word status, oldstatus; -+ cfi_word dq6 = CMD(1<<6); -+ cfi_word dq2 = CMD(1<<2); -+ unsigned long timeo; -+ struct cfi_pri_amdstd *cfip = (struct cfi_pri_amdstd *)cfi->cmdset_priv; - -+ resettime: -+ timeo = jiffies + HZ; - retry: -+ switch (chip->state) { -+ -+ case FL_STATUS: -+ for (;;) { -+ oldstatus = cfi_read(map, adr); -+ status = cfi_read(map, adr); -+ if (((oldstatus ^ status) & (dq6 | dq2)) == 0) -+ break; -+ -+ if (time_after(jiffies, timeo)) { -+ printk(KERN_ERR "Waiting for chip to be ready timed out. Status %llx\n", -+ (long long)status); -+ cfi_spin_unlock(chip->mutex); -+ return -EIO; -+ } -+ cfi_spin_unlock(chip->mutex); -+ cfi_udelay(1); - cfi_spin_lock(chip->mutex); -+ /* Someone else might have been playing with it. */ -+ goto retry; -+ } - -- if (chip->state != FL_READY){ --#if 0 -- printk(KERN_DEBUG "Waiting for chip to read, status = %d\n", chip->state); --#endif -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ case FL_READY: -+ case FL_CFI_QUERY: -+ case FL_JEDEC_QUERY: -+ return 0; -+ -+ case FL_ERASING: -+ if (mode == FL_WRITING) /* FIXME: Erase-suspend-program appears broken. */ -+ goto sleep; -+ -+ if (!(mode == FL_READY || mode == FL_POINT -+ || (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)) -+ || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1)))) -+ goto sleep; -+ -+ oldstatus = cfi_read(map, adr); -+ status = cfi_read(map, adr); -+ if ((oldstatus ^ status) & dq2) { -+ printk(KERN_ERR "Can't suspend erase -- block in progress\n"); -+ goto sleep; -+ } -+ -+ /* Erase suspend */ -+ /* FIXME - is there a way to verify suspend? */ -+ cfi_write(map, CMD(0xB0), chip->in_progress_block_addr); -+ chip->oldstate = FL_ERASING; -+ chip->state = FL_ERASE_SUSPENDING; -+ chip->erase_suspended = 1; -+ for (;;) { -+ oldstatus = cfi_read(map, chip->in_progress_block_addr); -+ status = cfi_read(map, chip->in_progress_block_addr); -+ if (((oldstatus ^ status) & dq6) == 0) -+ break; -+ -+ if (time_after(jiffies, timeo)) { -+ /* Urgh. Resume and pretend we weren't here. */ -+ /* FIXME - is there a way to verify resume? */ -+ cfi_write(map, CMD(0x30), chip->in_progress_block_addr); -+ chip->state = FL_ERASING; -+ chip->oldstate = FL_READY; -+ printk(KERN_ERR "Chip not ready after erase " -+ "suspended: status = 0x%x\n", status); -+ return -EIO; -+ } - - cfi_spin_unlock(chip->mutex); -+ cfi_udelay(1); -+ cfi_spin_lock(chip->mutex); -+ /* Nobody will touch it while it's in state FL_ERASE_SUSPENDING. -+ So we can just loop here. */ -+ } -+ chip->state = FL_READY; -+ return 0; -+ -+ case FL_POINT: -+ /* Only if there's no operation suspended... */ -+ if (mode == FL_READY && chip->oldstate == FL_READY) -+ return 0; - -+ default: -+ sleep: -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ add_wait_queue(&chip->wq, &wait); -+ cfi_spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); --#if 0 -- if(signal_pending(current)) -- return -EINTR; --#endif -- timeo = jiffies + HZ; -+ cfi_spin_lock(chip->mutex); -+ goto resettime; -+ } -+} - -- goto retry; -+ -+static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ -+ switch(chip->oldstate) { -+ case FL_ERASING: -+ chip->state = chip->oldstate; -+ cfi_write(map, CMD(0x30), chip->in_progress_block_addr); -+ chip->oldstate = FL_READY; -+ chip->state = FL_ERASING; -+ break; -+ -+ case FL_READY: -+ case FL_STATUS: -+ /* We should really make set_vpp() count, rather than doing this */ -+ DISABLE_VPP(map); -+ break; -+ default: -+ printk(KERN_ERR "MTD: put_chip() called with oldstate %d!!\n", chip->oldstate); - } -+ wake_up(&chip->wq); -+} -+ -+ -+static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) -+{ -+ unsigned long cmd_addr; -+ struct cfi_private *cfi = map->fldrv_priv; -+ int ret; - - adr += chip->start; - -+ /* Ensure cmd read/writes are aligned. */ -+ cmd_addr = adr & ~(CFIDEV_BUSWIDTH-1); -+ -+ cfi_spin_lock(chip->mutex); -+ ret = get_chip(map, chip, cmd_addr, FL_READY); -+ if (ret) { -+ cfi_spin_unlock(chip->mutex); -+ return ret; -+ } -+ -+ if (chip->state != FL_POINT && chip->state != FL_READY) { -+ cfi_write(map, CMD(0xf0), cmd_addr); - chip->state = FL_READY; -+ } - -- map->copy_from(map, buf, adr, len); -+ map_copy_from(map, buf, adr, len); - -- wake_up(&chip->wq); -- cfi_spin_unlock(chip->mutex); -+ put_chip(map, chip, cmd_addr); - -+ cfi_spin_unlock(chip->mutex); - return 0; - } - -+ - static int cfi_amdstd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) - { - struct map_info *map = mtd->priv; -@@ -361,6 +664,7 @@ - return ret; - } - -+ - static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) - { - DECLARE_WAITQUEUE(wait, current); -@@ -394,12 +698,14 @@ - - chip->state = FL_READY; - -+ /* should these be CFI_DEVICETYPE_X8 instead of cfi->device_type? */ - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); - cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); - -- map->copy_from(map, buf, adr, len); -+ map_copy_from(map, buf, adr, len); - -+ /* should these be CFI_DEVICETYPE_X8 instead of cfi->device_type? */ - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); - cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); -@@ -454,125 +760,241 @@ - return ret; - } - --static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum, int fast) -+ -+static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, cfi_word datum, int fast) - { -- unsigned long timeo = jiffies + HZ; -- unsigned int oldstatus, status; -- unsigned int dq6, dq5; - struct cfi_private *cfi = map->fldrv_priv; -- DECLARE_WAITQUEUE(wait, current); -+ unsigned long timeo = jiffies + HZ; -+ cfi_word oldstatus, status, prev_oldstatus, prev_status; -+ cfi_word dq6 = CMD(1<<6); -+ /* -+ * We use a 1ms + 1 jiffies generic timeout for writes (most devices -+ * have a max write time of a few hundreds usec). However, we should -+ * use the maximum timeout value given by the chip at probe time -+ * instead. Unfortunately, struct flchip does have a field for -+ * maximum timeout, only for typical which can be far too short -+ * depending of the conditions. The ' + 1' is to avoid having a -+ * timeout of 0 jiffies if HZ is smaller than 1000. -+ */ -+ unsigned long uWriteTimeout = ( HZ / 1000 ) + 1; - int ret = 0; -+ int ta = 0; -+ DECLARE_RETRY_CMD_CNT(); - -- retry: -- cfi_spin_lock(chip->mutex); -- -- if (chip->state != FL_READY) { --#if 0 -- printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", chip->state); --#endif -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ adr += chip->start; - -+ cfi_spin_lock(chip->mutex); -+ ret = get_chip(map, chip, adr, FL_WRITING); -+ if (ret) { - cfi_spin_unlock(chip->mutex); -- -- schedule(); -- remove_wait_queue(&chip->wq, &wait); --#if 0 -- printk(KERN_DEBUG "Wake up to write:\n"); -- if(signal_pending(current)) -- return -EINTR; --#endif -- timeo = jiffies + HZ; -- -- goto retry; -+ return ret; - } - -- chip->state = FL_WRITING; -+ RETRY_CMD_LABEL; -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8x)\n", -+ __func__, adr, datum ); -+ -+ /* -+ * Check for a NOP for the case when the datum to write is already -+ * present - it saves time and works around buggy chips that corrupt -+ * data at other locations when 0xff is written to a location that -+ * already contains 0xff. -+ */ -+ status = cfi_read(map, adr); -+ if (status == datum) { -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): NOP 0x%.8x == 0x%.8x\n", -+ __func__, status, datum ); -+ goto op_done; -+ } - -- adr += chip->start; - ENABLE_VPP(map); - if (fast) { /* Unlock bypass */ - cfi_send_gen_cmd(0xA0, 0, chip->start, map, cfi, cfi->device_type, NULL); -- } -- else { -+ } else { -+ /* -+ * The CFI_DEVICETYPE_X8 argument is needed even when -+ * cfi->device_type != CFI_DEVICETYPE_X8. The addresses for -+ * command sequences don't scale even when the device is -+ * wider. This is the case for many of the cfi_send_gen_cmd() -+ * below. I'm not sure, however, why some use -+ * cfi->device_type. -+ */ - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - } -- - cfi_write(map, datum, adr); -+ chip->state = FL_WRITING; - - cfi_spin_unlock(chip->mutex); - cfi_udelay(chip->word_write_time); - cfi_spin_lock(chip->mutex); - -- /* Polling toggle bits instead of reading back many times -- This ensures that write operation is really completed, -- or tells us why it failed. */ -- dq6 = CMD(1<<6); -- dq5 = CMD(1<<5); -- timeo = jiffies + (HZ/1000); /* setting timeout to 1ms for now */ -+ /* -+ * Polling toggle bits instead of reading back many times This ensures -+ * that write operation is really completed, or tells us why it -+ * failed. -+ * -+ * It may appear that the polling and decoding of error state might be -+ * simplified. Don't do it unless you really know what you are doing. -+ * -+ * You must remember that JESD21-C 3.5.3 states that the status must -+ * be read back an _additional_ two times before a failure is -+ * determined. This is because these devices have internal state -+ * machines that are asynchronous to the external data bus. During an -+ * erase or write the read-back status of the polling bits might be -+ * transitioning internaly when the external read-back occurs. This -+ * means that the bits aren't in the final state and they might appear -+ * to report an error as they are in a transient state: dq7 is -+ * asynchronous with dq6 and other status bits. -+ * -+ * This asynchronous behaviour can cause infrequent errors that will -+ * usually disappear the next time an erase or write happens (Try -+ * tracking those errors down!). To ensure that the bits are not in -+ * transition, the location must be read-back two more times and -+ * compared against what was written - BOTH reads MUST match what was -+ * written. Don't think this can be simplified to only the last read -+ * matching the datum written: status bits *can* match the datum -+ * written. -+ * -+ * If the final comparison fails, error state can *then* be decoded. -+ * -+ * - Thayne Harbaugh -+ */ -+ /* See comment above for timeout value. */ -+ timeo = jiffies + uWriteTimeout; -+ for (;;) { -+ if (chip->state != FL_WRITING) { -+ /* Someone's suspended the write. Sleep */ -+ DECLARE_WAITQUEUE(wait, current); -+ -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ add_wait_queue(&chip->wq, &wait); -+ cfi_spin_unlock(chip->mutex); -+ schedule(); -+ remove_wait_queue(&chip->wq, &wait); -+ timeo = jiffies + (HZ / 2); /* FIXME */ -+ cfi_spin_lock(chip->mutex); -+ continue; -+ } - - oldstatus = cfi_read(map, adr); - status = cfi_read(map, adr); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); - -- while( (status & dq6) != (oldstatus & dq6) && -- (status & dq5) != dq5 && -- !time_after(jiffies, timeo) ) { -+ /* -+ * This only checks if dq6 is still toggling and that our -+ * timer hasn't expired. We purposefully ignore the chip's -+ * internal timer that will assert dq5 and leave dq6 toggling. -+ * This is done for a variety of reasons: -+ * -+ * 1) Not all chips support dq5. -+ * -+ * 2) Dealing with asynchronous status bit and data updates -+ * and reading a device two more times creates _messy_ logic -+ * when trying to deal with interleaved devices - some may be -+ * changing while others are still busy. -+ * -+ * 3) Checking dq5 only helps to optimize an error case that -+ * should at worst be infrequent and at best non-existent. -+ * -+ * If our timeout occurs _then_ we will check dq5 to see if -+ * the device also had an internal timeout. -+ */ -+ if ( (((status ^ oldstatus) & dq6) == 0) -+ || ( ta = time_after(jiffies, timeo)) ) -+ break; - -- if (need_resched()) { -+ /* Latency issues. Drop the lock, wait a while and retry */ - cfi_spin_unlock(chip->mutex); -- yield(); -+ cfi_udelay(1); - cfi_spin_lock(chip->mutex); -- } else -- udelay(1); -- -- oldstatus = cfi_read( map, adr ); -- status = cfi_read( map, adr ); - } - -- if( (status & dq6) != (oldstatus & dq6) ) { -- /* The erasing didn't stop?? */ -- if( (status & dq5) == dq5 ) { -- /* When DQ5 raises, we must check once again -- if DQ6 is toggling. If not, the erase has been -- completed OK. If not, reset chip. */ -+ /* -+ * Something kicked us out of the read-back loop. We'll check success -+ * befor checking failure. Even though dq6 might be true data, it is -+ * unkown if all of the other bits have changed to true data due to -+ * the asynchronous nature of the internal state machine. We will -+ * read two more times and use this to either verify that the write -+ * completed successfully or that something really went wrong. BOTH -+ * reads must match what was written - this certifies that bits aren't -+ * still changing and that the status bits erroneously match the datum -+ * that was written. -+ */ -+ prev_oldstatus = oldstatus; -+ prev_status = status; - oldstatus = cfi_read(map, adr); - status = cfi_read(map, adr); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); - -- if ( (oldstatus & 0x00FF) == (status & 0x00FF) ) { -- printk(KERN_WARNING "Warning: DQ5 raised while program operation was in progress, however operation completed OK\n" ); -+ if ( oldstatus == datum && status == datum ) { -+ /* success - do nothing */ -+ goto op_done; -+ } -+ -+ if ( ta ) { -+ /* Only check dq5 on the chips that are still toggling. */ -+ cfi_word dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1; -+ if ( status & dq5mask ) { -+ /* dq5 asserted - decode interleave chips */ -+ printk( KERN_WARNING -+ "MTD %s(): FLASH internal timeout: 0x%.8x 0x%.8x 0x%8x\n", -+ __func__, -+ status & dq5mask, status, datum ); - } else { -- /* DQ5 is active so we can do a reset and stop the erase */ -- cfi_write(map, CMD(0xF0), chip->start); -- printk(KERN_WARNING "Internal flash device timeout occurred or write operation was performed while flash was programming.\n" ); -+ printk( KERN_WARNING -+ "MTD %s(): Software timed out during write.\n", -+ __func__ ); -+ } -+ goto op_failed; - } -- } else { -- printk(KERN_WARNING "Waiting for write to complete timed out in do_write_oneword."); - -+ /* -+ * If we get to here then it means that something -+ * is wrong and it's not a timeout. Something -+ * is seriously wacky! Dump some debug info. -+ */ -+ /* -+ * Found a clue about the chips that reach this state. -+ * Some flash chips (SST >cough<) -+ * are horribly broken. They do not ignore traffic that is -+ * destined to other devices. This happens because some solutions -+ * are on shared busses, the erase and program sequences have -+ * have multiple commands, and the sequence is interspersed with -+ * commands destined to other devices. A good flash chip will -+ * examine the command and destination address and will ignore -+ * commands that are for other devices. -+ */ -+ HANDLE_WACKY_STATE(); -+ -+ op_failed: -+ /* reset on all failures. */ -+ cfi_write( map, CMD(0xF0), chip->start ); -+ /* FIXME - should have reset delay before continuing */ -+ CHECK_RETRIES(); -+ ret = -EIO; -+ -+ op_done: - chip->state = FL_READY; -- wake_up(&chip->wq); -- cfi_spin_unlock(chip->mutex); -- DISABLE_VPP(map); -- ret = -EIO; -- } -- } -- -- DISABLE_VPP(map); -- chip->state = FL_READY; -- wake_up(&chip->wq); -+ put_chip(map, chip, adr); - cfi_spin_unlock(chip->mutex); - - return ret; - } - --static int cfi_amdstd_write (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf) -+ -+static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) - { - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - int ret = 0; - int chipnum; - unsigned long ofs, chipstart; -+ DECLARE_WAITQUEUE(wait, current); - - *retlen = 0; - if (!len) -@@ -587,19 +1009,52 @@ - unsigned long bus_ofs = ofs & ~(CFIDEV_BUSWIDTH-1); - int i = ofs - bus_ofs; - int n = 0; -- u_char tmp_buf[4]; -- __u32 datum; -+ u_char tmp_buf[8]; -+ cfi_word datum; -+ -+ retry: -+ cfi_spin_lock(cfi->chips[chipnum].mutex); -+ -+ if (cfi->chips[chipnum].state != FL_READY) { -+#if 0 -+ printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state); -+#endif -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ add_wait_queue(&cfi->chips[chipnum].wq, &wait); -+ -+ cfi_spin_unlock(cfi->chips[chipnum].mutex); -+ -+ schedule(); -+ remove_wait_queue(&cfi->chips[chipnum].wq, &wait); -+#if 0 -+ if(signal_pending(current)) -+ return -EINTR; -+#endif -+ goto retry; -+ } -+ -+ map_copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); - -- map->copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); -- while (len && i < CFIDEV_BUSWIDTH) -- tmp_buf[i++] = buf[n++], len--; -+ cfi_spin_unlock(cfi->chips[chipnum].mutex); -+ -+ while (len && i < CFIDEV_BUSWIDTH) { -+ tmp_buf[i++] = buf[n++]; -+ len--; -+ } - -+ /* already know that buswidth > 1 */ - if (cfi_buswidth_is_2()) { - datum = *(__u16*)tmp_buf; - } else if (cfi_buswidth_is_4()) { - datum = *(__u32*)tmp_buf; -+#ifdef CFI_WORD_64 -+ } else if (cfi_buswidth_is_8()) { -+ datum = *(__u64*)tmp_buf; -+#endif - } else { -- return -EINVAL; /* should never happen, but be safe */ -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); -+ return -EINVAL; - } - - ret = do_write_oneword(map, &cfi->chips[chipnum], -@@ -628,7 +1083,7 @@ - - /* We are now aligned, write as much as possible */ - while(len >= CFIDEV_BUSWIDTH) { -- __u32 datum; -+ cfi_word datum; - - if (cfi_buswidth_is_1()) { - datum = *(__u8*)buf; -@@ -636,7 +1091,13 @@ - datum = *(__u16*)buf; - } else if (cfi_buswidth_is_4()) { - datum = *(__u32*)buf; -+#ifdef CFI_WORD_64 -+ } else if (cfi_buswidth_is_8()) { -+ datum = *(__u64*)buf; -+#endif - } else { -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); - return -EINVAL; - } - ret = do_write_oneword(map, &cfi->chips[chipnum], -@@ -685,10 +1146,34 @@ - /* Write the trailing bytes if any */ - if (len & (CFIDEV_BUSWIDTH-1)) { - int i = 0, n = 0; -- u_char tmp_buf[4]; -- __u32 datum; -+ u_char tmp_buf[8]; -+ cfi_word datum; -+ -+ retry1: -+ cfi_spin_lock(cfi->chips[chipnum].mutex); -+ -+ if (cfi->chips[chipnum].state != FL_READY) { -+#if 0 -+ printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state); -+#endif -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ add_wait_queue(&cfi->chips[chipnum].wq, &wait); -+ -+ cfi_spin_unlock(cfi->chips[chipnum].mutex); -+ -+ schedule(); -+ remove_wait_queue(&cfi->chips[chipnum].wq, &wait); -+#if 0 -+ if(signal_pending(current)) -+ return -EINTR; -+#endif -+ goto retry1; -+ } -+ -+ map_copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); -+ -+ cfi_spin_unlock(cfi->chips[chipnum].mutex); - -- map->copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); - while (len--) - tmp_buf[i++] = buf[n++]; - -@@ -696,8 +1181,14 @@ - datum = *(__u16*)tmp_buf; - } else if (cfi_buswidth_is_4()) { - datum = *(__u32*)tmp_buf; -+#ifdef CFI_WORD_64 -+ } else if (cfi_buswidth_is_8()) { -+ datum = *(__u64*)tmp_buf; -+#endif - } else { -- return -EINVAL; /* should never happen, but be safe */ -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); -+ return -EINVAL; - } - - ret = do_write_oneword(map, &cfi->chips[chipnum], -@@ -711,289 +1202,446 @@ - return 0; - } - --static inline int do_erase_chip(struct map_info *map, struct flchip *chip) -+ -+/* -+ * FIXME: interleaved mode not tested, and probably not supported! -+ */ -+static inline int do_write_buffer(struct map_info *map, struct flchip *chip, -+ unsigned long adr, const u_char *buf, int len) - { -- unsigned int oldstatus, status; -- unsigned int dq6, dq5; -- unsigned long timeo = jiffies + HZ; -- unsigned int adr; - struct cfi_private *cfi = map->fldrv_priv; -- DECLARE_WAITQUEUE(wait, current); -- -- retry: -- cfi_spin_lock(chip->mutex); -+ unsigned long timeo = jiffies + HZ; -+ cfi_word oldstatus, status, prev_oldstatus, prev_status; -+ cfi_word dq6 = CMD(1<<6); -+ /* see comments in do_write_oneword() regarding uWriteTimeo. */ -+ static unsigned long uWriteTimeout = ( HZ / 1000 ) + 1; -+ int ret = -EIO; -+ int ta = 0; -+ unsigned long cmd_adr; -+ int z, bytes, words; -+ cfi_word datum; -+ DECLARE_RETRY_CMD_CNT(); - -- if (chip->state != FL_READY){ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ adr += chip->start; -+ cmd_adr = adr; - -+ cfi_spin_lock(chip->mutex); -+ ret = get_chip(map, chip, adr, FL_WRITING); -+ if (ret) { - cfi_spin_unlock(chip->mutex); -+ return ret; -+ } - -- schedule(); -- remove_wait_queue(&chip->wq, &wait); --#if 0 -- if(signal_pending(current)) -- return -EINTR; -+ if (cfi_buswidth_is_1()) { -+ datum = *(__u8*)buf; -+ } else if (cfi_buswidth_is_2()) { -+ datum = *(__u16*)buf; -+ } else if (cfi_buswidth_is_4()) { -+ datum = *(__u32*)buf; -+#ifdef CFI_WORD_64 -+ } else if (cfi_buswidth_is_8()) { -+ datum = *(__u64*)buf; - #endif -- timeo = jiffies + HZ; -- -- goto retry; -+ } else { -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); -+ return -EINVAL; - } - -- chip->state = FL_ERASING; -+ RETRY_CMD_LABEL; -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8x)\n", -+ __func__, adr, datum ); - -- /* Handle devices with one erase region, that only implement -- * the chip erase command. -- */ - ENABLE_VPP(map); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -- cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -- cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -- cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -- cfi_send_gen_cmd(0x10, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -- timeo = jiffies + (HZ*20); -- adr = cfi->addr_unlock1; -+ //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - -- /* Wait for the end of programing/erasure by using the toggle method. -- * As long as there is a programming procedure going on, bit 6 of the last -- * written byte is toggling it's state with each consectuve read. -- * The toggling stops as soon as the procedure is completed. -- * -- * If the process has gone on for too long on the chip bit 5 gets. -- * After bit5 is set you can kill the operation by sending a reset -- * command to the chip. -- */ -- dq6 = CMD(1<<6); -- dq5 = CMD(1<<5); -+ /* Write Buffer Load */ -+ cfi_write(map, CMD(0x25), cmd_adr); - -- oldstatus = cfi_read(map, adr); -- status = cfi_read(map, adr); -- while( ((status & dq6) != (oldstatus & dq6)) && -- ((status & dq5) != dq5) && -- !time_after(jiffies, timeo)) { -- int wait_reps; -+ chip->state = FL_WRITING_TO_BUFFER; -+ -+ /* Write length of data to come */ -+ bytes = len & (CFIDEV_BUSWIDTH-1); -+ words = len / CFIDEV_BUSWIDTH; -+ cfi_write(map, CMD(words - !bytes), cmd_adr ); -+ /* Write data */ -+ z = 0; -+ while(z < words * CFIDEV_BUSWIDTH) { -+ if (cfi_buswidth_is_1()) { -+ datum = *((__u8*)buf); -+ map_write8 (map, *((__u8*)buf)++, adr+z); -+ } else if (cfi_buswidth_is_2()) { -+ datum = *((__u16*)buf); -+ map_write16 (map, *((__u16*)buf)++, adr+z); -+ } else if (cfi_buswidth_is_4()) { -+ datum = *((__u32*)buf); -+ map_write32 (map, *((__u32*)buf)++, adr+z); -+#ifdef CFI_WORD_64 -+ } else if (cfi_buswidth_is_8()) { -+ datum = *((__u64*)buf); -+ map_write64 (map, *((__u64*)buf)++, adr+z); -+#endif -+ } else { -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); -+ ret = -EINVAL; -+ goto op_failed; -+ } -+ z += CFIDEV_BUSWIDTH; -+ } -+ if (bytes) { -+ int i = 0, n = 0; -+ u_char tmp_buf[8], *tmp_p = tmp_buf; -+ -+ while (bytes--) -+ tmp_buf[i++] = buf[n++]; -+ while (i < CFIDEV_BUSWIDTH) -+ tmp_buf[i++] = 0xff; -+ if (cfi_buswidth_is_2()) { -+ datum = *((__u16*)tmp_p); -+ map_write16 (map, *((__u16*)tmp_p)++, adr+z); -+ } else if (cfi_buswidth_is_4()) { -+ datum = *((__u32*)tmp_p); -+ map_write32 (map, *((__u32*)tmp_p)++, adr+z); -+#ifdef CFI_WORD_64 -+ } else if (cfi_buswidth_is_8()) { -+ datum = *((__u64*)tmp_p); -+ map_write64 (map, *((__u64*)tmp_p)++, adr+z); -+#endif -+ } else { -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); -+ ret = -EINVAL; -+ goto op_failed; -+ } -+ } else if (words > 0) { -+ z -= CFIDEV_BUSWIDTH; -+ } -+ -+ adr += z; -+ -+ /* Write Buffer Program Confirm: GO GO GO */ -+ cfi_write(map, CMD(0x29), cmd_adr); -+ chip->state = FL_WRITING; - -- /* an initial short sleep */ - cfi_spin_unlock(chip->mutex); -- schedule_timeout(HZ/100); -+ cfi_udelay(chip->buffer_write_time); - cfi_spin_lock(chip->mutex); - -- if (chip->state != FL_ERASING) { -- /* Someone's suspended the erase. Sleep */ -+ timeo = jiffies + uWriteTimeout; -+ -+ for (;;) { -+ if (chip->state != FL_WRITING) { -+ /* Someone's suspended the write. Sleep */ -+ DECLARE_WAITQUEUE(wait, current); -+ - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); -- - cfi_spin_unlock(chip->mutex); -- printk("erase suspended. Sleeping\n"); -- - schedule(); - remove_wait_queue(&chip->wq, &wait); --#if 0 -- if (signal_pending(current)) -- return -EINTR; --#endif -- timeo = jiffies + (HZ*2); /* FIXME */ -+ timeo = jiffies + (HZ / 2); /* FIXME */ - cfi_spin_lock(chip->mutex); - continue; - } - -- /* Busy wait for 1/10 of a milisecond */ -- for(wait_reps = 0; -- (wait_reps < 100) && -- ((status & dq6) != (oldstatus & dq6)) && -- ((status & dq5) != dq5); -- wait_reps++) { -+ oldstatus = cfi_read(map, adr); -+ status = cfi_read(map, adr); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); -+ -+ /* See comments in do_write_oneword() about checking status */ -+ if ( (((status ^ oldstatus) & dq6) == 0) -+ || ( ta = time_after(jiffies, timeo)) ) { -+ break; -+ } - - /* Latency issues. Drop the lock, wait a while and retry */ - cfi_spin_unlock(chip->mutex); -- - cfi_udelay(1); -- - cfi_spin_lock(chip->mutex); -- oldstatus = cfi_read(map, adr); -- status = cfi_read(map, adr); - } -+ -+ /* See comments in do_write_oneword() about "two more checks" */ -+ prev_oldstatus = oldstatus; -+ prev_status = status; - oldstatus = cfi_read(map, adr); - status = cfi_read(map, adr); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); -+ -+ if ( oldstatus == datum && status == datum ) { -+ /* success - do nothing */ -+ goto op_done; -+ } -+ -+ if ( ta ) { -+ /* Only check dq5 on the chips that are still toggling. */ -+ cfi_word dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1; -+ if ( status & dq5mask ) { -+ /* dq5 asserted - decode interleave chips */ -+ printk( KERN_WARNING -+ "MTD %s(): FLASH internal timeout: 0x%.8x 0x%.8x 0x%8x\n", -+ __func__, -+ status & dq5mask, status, datum ); -+ } else { -+ printk( KERN_WARNING -+ "MTD %s(): Software timed out during write.\n", -+ __func__ ); - } -- if ((status & dq6) != (oldstatus & dq6)) { -- /* The erasing didn't stop?? */ -- if ((status & dq5) == dq5) { -- /* dq5 is active so we can do a reset and stop the erase */ -- cfi_write(map, CMD(0xF0), chip->start); -+ goto op_failed; - } -+ -+ HANDLE_WACKY_STATE(); -+ -+ op_failed: -+ /* reset on all failures. */ -+ cfi_write( map, CMD(0xF0), chip->start ); -+ /* FIXME - should have reset delay before continuing */ -+ CHECK_RETRIES(); -+ ret = -EIO; -+ -+ op_done: - chip->state = FL_READY; -- wake_up(&chip->wq); -+ put_chip(map, chip, adr); - cfi_spin_unlock(chip->mutex); -- printk("waiting for erase to complete timed out."); -- DISABLE_VPP(map); -- return -EIO; -+ -+ return ret; -+} -+ -+ -+static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ struct map_info *map = mtd->priv; -+ struct cfi_private *cfi = map->fldrv_priv; -+ int wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize; -+ int ret = 0; -+ int chipnum; -+ unsigned long ofs; -+ -+ *retlen = 0; -+ if (!len) -+ return 0; -+ -+ chipnum = to >> cfi->chipshift; -+ ofs = to - (chipnum << cfi->chipshift); -+ -+ /* If it's not bus-aligned, do the first word write */ -+ if (ofs & (CFIDEV_BUSWIDTH-1)) { -+ size_t local_len = (-ofs)&(CFIDEV_BUSWIDTH-1); -+ if (local_len > len) -+ local_len = len; -+ ret = cfi_amdstd_write_words(mtd, to, local_len, -+ retlen, buf); -+ if (ret) -+ return ret; -+ ofs += local_len; -+ buf += local_len; -+ len -= local_len; -+ -+ if (ofs >> cfi->chipshift) { -+ chipnum ++; -+ ofs = 0; -+ if (chipnum == cfi->numchips) -+ return 0; -+ } -+ } -+ -+ /* Write buffer is worth it only if more than one word to write... */ -+ while (len) { -+ /* We must not cross write block boundaries */ -+ int size = wbufsize - (ofs & (wbufsize-1)); -+ -+ if (size > len) -+ size = len; -+ ret = do_write_buffer(map, &cfi->chips[chipnum], -+ ofs, buf, size); -+ if (ret) -+ return ret; -+ -+ ofs += size; -+ buf += size; -+ (*retlen) += size; -+ len -= size; -+ -+ if (ofs >> cfi->chipshift) { -+ chipnum ++; -+ ofs = 0; -+ if (chipnum == cfi->numchips) -+ return 0; -+ } - } -- DISABLE_VPP(map); -- chip->state = FL_READY; -- wake_up(&chip->wq); -- cfi_spin_unlock(chip->mutex); - - return 0; - } - --static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) -+ -+/* -+ * Handle devices with one erase region, that only implement -+ * the chip erase command. -+ */ -+static inline int do_erase_chip(struct map_info *map, struct flchip *chip) - { -- unsigned int oldstatus, status; -- unsigned int dq6, dq5; -- unsigned long timeo = jiffies + HZ; - struct cfi_private *cfi = map->fldrv_priv; -+ cfi_word oldstatus, status, prev_oldstatus, prev_status; -+ cfi_word dq6 = CMD(1<<6); -+ unsigned long timeo = jiffies + HZ; -+ unsigned long int adr; - DECLARE_WAITQUEUE(wait, current); -+ int ret = 0; -+ int ta = 0; -+ cfi_word datum = 0; -+ DECLARE_RETRY_CMD_CNT(); - -- retry: -- cfi_spin_lock(chip->mutex); -- -- if (chip->state != FL_READY){ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ adr = cfi->addr_unlock1; - -+ cfi_spin_lock(chip->mutex); -+ ret = get_chip(map, chip, adr, FL_WRITING); -+ if (ret) { - cfi_spin_unlock(chip->mutex); -- -- schedule(); -- remove_wait_queue(&chip->wq, &wait); --#if 0 -- if(signal_pending(current)) -- return -EINTR; --#endif -- timeo = jiffies + HZ; -- -- goto retry; -+ return ret; - } - -- chip->state = FL_ERASING; -+ RETRY_CMD_LABEL; -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n", -+ __func__, chip->start ); - -- adr += chip->start; - ENABLE_VPP(map); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -- cfi_write(map, CMD(0x30), adr); -- -- timeo = jiffies + (HZ*20); -- -- /* Wait for the end of programing/erasure by using the toggle method. -- * As long as there is a programming procedure going on, bit 6 of the last -- * written byte is toggling it's state with each consectuve read. -- * The toggling stops as soon as the procedure is completed. -- * -- * If the process has gone on for too long on the chip bit 5 gets. -- * After bit5 is set you can kill the operation by sending a reset -- * command to the chip. -- */ -- dq6 = CMD(1<<6); -- dq5 = CMD(1<<5); -+ cfi_send_gen_cmd(0x10, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - -- oldstatus = cfi_read(map, adr); -- status = cfi_read(map, adr); -- while( ((status & dq6) != (oldstatus & dq6)) && -- ((status & dq5) != dq5) && -- !time_after(jiffies, timeo)) { -- int wait_reps; -+ chip->state = FL_ERASING; -+ chip->erase_suspended = 0; -+ chip->in_progress_block_addr = adr; - -- /* an initial short sleep */ - cfi_spin_unlock(chip->mutex); -- schedule_timeout(HZ/100); -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ schedule_timeout((chip->erase_time*HZ)/(2*1000)); - cfi_spin_lock(chip->mutex); - -+ timeo = jiffies + (HZ*20); -+ -+ for (;;) { - if (chip->state != FL_ERASING) { - /* Someone's suspended the erase. Sleep */ - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); -- - cfi_spin_unlock(chip->mutex); -- printk(KERN_DEBUG "erase suspended. Sleeping\n"); -- - schedule(); - remove_wait_queue(&chip->wq, &wait); --#if 0 -- if (signal_pending(current)) -- return -EINTR; --#endif -- timeo = jiffies + (HZ*2); /* FIXME */ - cfi_spin_lock(chip->mutex); - continue; - } -+ if (chip->erase_suspended) { -+ /* This erase was suspended and resumed. -+ Adjust the timeout */ -+ timeo = jiffies + (HZ*20); /* FIXME */ -+ chip->erase_suspended = 0; -+ } - -- /* Busy wait for 1/10 of a milisecond */ -- for(wait_reps = 0; -- (wait_reps < 100) && -- ((status & dq6) != (oldstatus & dq6)) && -- ((status & dq5) != dq5); -- wait_reps++) { -+ oldstatus = cfi_read(map, adr); -+ status = cfi_read(map, adr); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); -+ if ( (((status ^ oldstatus) & dq6) == 0) -+ || ( ta = time_after(jiffies, timeo)) ) -+ break; - - /* Latency issues. Drop the lock, wait a while and retry */ - cfi_spin_unlock(chip->mutex); -- -- cfi_udelay(1); -- -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ schedule_timeout(1); - cfi_spin_lock(chip->mutex); -- oldstatus = cfi_read(map, adr); -- status = cfi_read(map, adr); - } -+ -+ prev_oldstatus = oldstatus; -+ prev_status = status; - oldstatus = cfi_read(map, adr); - status = cfi_read(map, adr); -- } -- if( (status & dq6) != (oldstatus & dq6) ) -- { -- /* The erasing didn't stop?? */ -- if( ( status & dq5 ) == dq5 ) -- { -- /* When DQ5 raises, we must check once again if DQ6 is toggling. -- If not, the erase has been completed OK. If not, reset chip. */ -- oldstatus = cfi_read( map, adr ); -- status = cfi_read( map, adr ); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); - -- if( ( oldstatus & 0x00FF ) == ( status & 0x00FF ) ) -- { -- printk( "Warning: DQ5 raised while erase operation was in progress, but erase completed OK\n" ); -- } -- else -- { -- /* DQ5 is active so we can do a reset and stop the erase */ -- cfi_write(map, CMD(0xF0), chip->start); -- printk( KERN_WARNING "Internal flash device timeout occured or write operation was performed while flash was erasing\n" ); -+ if ( cfi_buswidth_is_1() ) { -+ datum = (__u8)~0; -+ } else if ( cfi_buswidth_is_2() ) { -+ datum = (__u16)~0; -+ } else if ( cfi_buswidth_is_4() ) { -+ datum = (__u32)~0; -+#ifdef CFI_WORD_64 -+ } else if ( cfi_buswidth_is_8() ) { -+ datum = (__u64)~0; -+#endif -+ } else { -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); -+ goto op_failed; -+ } -+ -+ if ( oldstatus == datum && status == datum ) { -+ /* success - do nothing */ -+ goto op_done; -+ } -+ -+ if ( ta ) { -+ /* Only check dq5 on the chips that are still toggling. */ -+ cfi_word dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1; -+ if ( status & dq5mask ) { -+ /* dq5 asserted - decode interleave chips */ -+ printk( KERN_WARNING -+ "MTD %s(): FLASH internal timeout: 0x%.8x\n", -+ __func__, -+ status & dq5mask ); -+ } else { -+ printk( KERN_WARNING -+ "MTD %s(): Software timed out during write.\n", -+ __func__ ); - } -+ goto op_failed; - } -- else -- { -- printk( "Waiting for erase to complete timed out in do_erase_oneblock."); - -- chip->state = FL_READY; -- wake_up(&chip->wq); -- cfi_spin_unlock(chip->mutex); -- DISABLE_VPP(map); -- return -EIO; -- } -- } -+ HANDLE_WACKY_STATE(); - -- DISABLE_VPP(map); -+ op_failed: -+ /* reset on all failures. */ -+ cfi_write( map, CMD(0xF0), chip->start ); -+ /* FIXME - should have reset delay before continuing */ -+ CHECK_RETRIES(); -+ ret = -EIO; -+ -+ op_done: - chip->state = FL_READY; -- wake_up(&chip->wq); -+ put_chip(map, chip, adr); - cfi_spin_unlock(chip->mutex); -- return 0; -+ -+ return ret; - } - --static int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) -+ -+typedef int (*frob_t)(struct map_info *map, struct flchip *chip, -+ unsigned long adr, void *thunk); -+ -+ -+static int cfi_amdstd_varsize_frob(struct mtd_info *mtd, frob_t frob, -+ loff_t ofs, size_t len, void *thunk) - { - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; -- unsigned long adr, len; -+ unsigned long adr; - int chipnum, ret = 0; - int i, first; - struct mtd_erase_region_info *regions = mtd->eraseregions; - -- if (instr->addr > mtd->size) -+ if (ofs > mtd->size) - return -EINVAL; - -- if ((instr->len + instr->addr) > mtd->size) -+ if ((len + ofs) > mtd->size) - return -EINVAL; - - /* Check that both start and end of the requested erase are -@@ -1008,7 +1656,7 @@ - start of the requested erase, and then go back one. - */ - -- while (i < mtd->numeraseregions && instr->addr >= regions[i].offset) -+ while (i < mtd->numeraseregions && ofs >= regions[i].offset) - i++; - i--; - -@@ -1018,7 +1666,7 @@ - effect here. - */ - -- if (instr->addr & (regions[i].erasesize-1)) -+ if (ofs & (regions[i].erasesize-1)) - return -EINVAL; - - /* Remember the erase region we start on */ -@@ -1028,7 +1676,7 @@ - * with the erase region at that address. - */ - -- while (inumeraseregions && (instr->addr + instr->len) >= regions[i].offset) -+ while (inumeraseregions && (ofs + len) >= regions[i].offset) - i++; - - /* As before, drop back one to point at the region in which -@@ -1036,17 +1684,16 @@ - */ - i--; - -- if ((instr->addr + instr->len) & (regions[i].erasesize-1)) -+ if ((ofs + len) & (regions[i].erasesize-1)) - return -EINVAL; - -- chipnum = instr->addr >> cfi->chipshift; -- adr = instr->addr - (chipnum << cfi->chipshift); -- len = instr->len; -+ chipnum = ofs >> cfi->chipshift; -+ adr = ofs - (chipnum << cfi->chipshift); - - i=first; - -- while(len) { -- ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr); -+ while (len) { -+ ret = (*frob)(map, &cfi->chips[chipnum], adr, thunk); - - if (ret) - return ret; -@@ -1066,50 +1713,171 @@ - } - } - -- instr->state = MTD_ERASE_DONE; -- if (instr->callback) -- instr->callback(instr); -- - return 0; - } - --static int cfi_amdstd_erase_onesize(struct mtd_info *mtd, struct erase_info *instr) -+ -+static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, void *thunk) - { -- struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; -- unsigned long adr, len; -- int chipnum, ret = 0; -+ cfi_word oldstatus, status, prev_oldstatus, prev_status; -+ cfi_word dq6 = CMD(1<<6); -+ unsigned long timeo = jiffies + HZ; -+ DECLARE_WAITQUEUE(wait, current); -+ int ret = 0; -+ int ta = 0; -+ cfi_word datum = 0; -+ DECLARE_RETRY_CMD_CNT(); - -- if (instr->addr & (mtd->erasesize - 1)) -- return -EINVAL; -+ adr += chip->start; - -- if (instr->len & (mtd->erasesize -1)) -- return -EINVAL; -+ cfi_spin_lock(chip->mutex); -+ ret = get_chip(map, chip, adr, FL_ERASING); -+ if (ret) { -+ cfi_spin_unlock(chip->mutex); -+ return ret; -+ } - -- if ((instr->len + instr->addr) > mtd->size) -- return -EINVAL; -+ RETRY_CMD_LABEL; -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n", -+ __func__, adr ); - -- chipnum = instr->addr >> cfi->chipshift; -- adr = instr->addr - (chipnum << cfi->chipshift); -- len = instr->len; -+ ENABLE_VPP(map); -+ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ cfi_write(map, CMD(0x30), adr); - -- while(len) { -- ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr); -+ chip->state = FL_ERASING; -+ chip->erase_suspended = 0; -+ chip->in_progress_block_addr = adr; - -- if (ret) -- return ret; -+ cfi_spin_unlock(chip->mutex); -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ schedule_timeout((chip->erase_time*HZ)/(2*1000)); -+ cfi_spin_lock(chip->mutex); - -- adr += mtd->erasesize; -- len -= mtd->erasesize; -+ timeo = jiffies + (HZ*20); - -- if (adr >> cfi->chipshift) { -- adr = 0; -- chipnum++; -+ /* Wait for the end of programing/erasure by using the toggle method. -+ * As long as there is a programming procedure going on, bit 6 is -+ * toggling its state with each consecutive read. The toggling stops -+ * as soon as the procedure is completed. -+ * -+ * If the process has gone on for too long on the chip, bit 5 gets -+ * set. After bit5 is set you can kill the operation by sending a -+ * reset command to the chip. -+ */ -+ /* See comments in do_write_oneword(). */ - -- if (chipnum >= cfi->numchips) -+ for (;;) { -+ if (chip->state != FL_ERASING) { -+ /* Someone's suspended the erase. Sleep */ -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ add_wait_queue(&chip->wq, &wait); -+ cfi_spin_unlock(chip->mutex); -+ schedule(); -+ remove_wait_queue(&chip->wq, &wait); -+ cfi_spin_lock(chip->mutex); -+ continue; -+ } -+ if (chip->erase_suspended) { -+ /* This erase was suspended and resumed. -+ Adjust the timeout */ -+ timeo = jiffies + (HZ*20); /* FIXME */ -+ chip->erase_suspended = 0; -+ } -+ -+ oldstatus = cfi_read(map, adr); -+ status = cfi_read(map, adr); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); -+ if ( (((status ^ oldstatus) & dq6) == 0) -+ || ( ta = time_after(jiffies, timeo)) ) - break; -+ -+ /* Latency issues. Drop the lock, wait a while and retry */ -+ cfi_spin_unlock(chip->mutex); -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ schedule_timeout(1); -+ cfi_spin_lock(chip->mutex); - } -+ -+ prev_oldstatus = oldstatus; -+ prev_status = status; -+ oldstatus = cfi_read(map, adr); -+ status = cfi_read(map, adr); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); -+ -+ if ( cfi_buswidth_is_1() ) { -+ datum = (__u8)~0; -+ } else if ( cfi_buswidth_is_2() ) { -+ datum = (__u16)~0; -+ } else if ( cfi_buswidth_is_4() ) { -+ datum = (__u32)~0; -+#ifdef CFI_WORD_64 -+ } else if ( cfi_buswidth_is_8() ) { -+ datum = (__u64)~0; -+#endif -+ } else { -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); -+ goto op_failed; -+ } -+ -+ if ( oldstatus == datum && status == datum ) { -+ /* success - do nothing */ -+ goto op_done; -+ } -+ -+ if ( ta ) { -+ /* Only check dq5 on the chips that are still toggling. */ -+ cfi_word dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1; -+ if ( status & dq5mask ) { -+ /* dq5 asserted - decode interleave chips */ -+ printk( KERN_WARNING -+ "MTD %s(): FLASH internal timeout: 0x%.8x\n", -+ __func__, -+ status & dq5mask ); -+ } else { -+ printk( KERN_WARNING -+ "MTD %s(): Software timed out during write.\n", -+ __func__ ); - } -+ goto op_failed; -+ } -+ -+ HANDLE_WACKY_STATE(); -+ -+ op_failed: -+ /* reset on all failures. */ -+ cfi_write( map, CMD(0xF0), chip->start ); -+ /* FIXME - should have reset delay before continuing */ -+ CHECK_RETRIES(); -+ ret = -EIO; -+ -+ op_done: -+ chip->state = FL_READY; -+ put_chip(map, chip, adr); -+ cfi_spin_unlock(chip->mutex); -+ return ret; -+} -+ -+ -+int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ unsigned long ofs, len; -+ int ret; -+ -+ ofs = instr->addr; -+ len = instr->len; -+ -+ ret = cfi_amdstd_varsize_frob(mtd, do_erase_oneblock, ofs, len, 0); -+ if (ret) -+ return ret; - - instr->state = MTD_ERASE_DONE; - if (instr->callback) -@@ -1118,6 +1886,7 @@ - return 0; - } - -+ - static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr) - { - struct map_info *map = mtd->priv; -@@ -1141,6 +1910,7 @@ - return 0; - } - -+ - static void cfi_amdstd_sync (struct mtd_info *mtd) - { - struct map_info *map = mtd->priv; -@@ -1254,6 +2024,7 @@ - return ret; - } - -+ - static void cfi_amdstd_resume(struct mtd_info *mtd) - { - struct map_info *map = mtd->priv; -@@ -1279,6 +2050,137 @@ - } - } - -+ -+#ifdef DEBUG_LOCK_BITS -+ -+static int do_printlockstatus_oneblock(struct map_info *map, -+ struct flchip *chip, -+ unsigned long adr, -+ void *thunk) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ int ofs_factor = cfi->interleave * cfi->device_type; -+ -+ cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL); -+ printk(KERN_DEBUG "block status register for 0x%08lx is %x\n", -+ adr, cfi_read_query(map, adr+(2*ofs_factor))); -+ cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL); -+ -+ return 0; -+} -+ -+ -+#define debug_dump_locks(mtd, frob, ofs, len, thunk) \ -+ cfi_amdstd_varsize_frob((mtd), (frob), (ofs), (len), (thunk)) -+ -+#else -+ -+#define debug_dump_locks(...) -+ -+#endif /* DEBUG_LOCK_BITS */ -+ -+ -+struct xxlock_thunk { -+ cfi_word val; -+ flstate_t state; -+}; -+ -+ -+#define DO_XXLOCK_ONEBLOCK_LOCK ((struct xxlock_thunk){0x01, FL_LOCKING}) -+#define DO_XXLOCK_ONEBLOCK_UNLOCK ((struct xxlock_thunk){0x00, FL_UNLOCKING}) -+ -+ -+/* -+ * FIXME - this is *very* specific to a particular chip. It likely won't -+ * work for all chips that require unlock. It also hasn't been tested -+ * with interleaved chips. -+ */ -+static int do_xxlock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, void *thunk) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ struct xxlock_thunk *xxlt = (struct xxlock_thunk *)thunk; -+ int ret; -+ -+ /* -+ * This is easy because these are writes to registers and not writes -+ * to flash memory - that means that we don't have to check status -+ * and timeout. -+ */ -+ -+ adr += chip->start; -+ /* -+ * lock block registers: -+ * - on 64k boundariesand -+ * - bit 1 set high -+ * - block lock registers are 4MiB lower - overflow subtract (danger) -+ */ -+ adr = ((adr & ~0xffff) | 0x2) + ~0x3fffff; -+ -+ cfi_spin_lock(chip->mutex); -+ ret = get_chip(map, chip, adr, FL_LOCKING); -+ if (ret) { -+ cfi_spin_unlock(chip->mutex); -+ return ret; -+ } -+ -+ chip->state = xxlt->state; -+ cfi_write(map, CMD(xxlt->val), adr); -+ -+ /* Done and happy. */ -+ chip->state = FL_READY; -+ put_chip(map, chip, adr); -+ cfi_spin_unlock(chip->mutex); -+ return 0; -+} -+ -+ -+static int cfi_amdstd_lock_varsize(struct mtd_info *mtd, -+ loff_t ofs, -+ size_t len) -+{ -+ int ret; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, -+ "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", -+ __func__, ofs, len); -+ debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); -+ -+ ret = cfi_amdstd_varsize_frob(mtd, do_xxlock_oneblock, ofs, len, -+ (void *)&DO_XXLOCK_ONEBLOCK_LOCK); -+ -+ DEBUG(MTD_DEBUG_LEVEL3, -+ "%s: lock status after, ret=%d\n", -+ __func__, ret); -+ -+ debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); -+ -+ return ret; -+} -+ -+ -+static int cfi_amdstd_unlock_varsize(struct mtd_info *mtd, -+ loff_t ofs, -+ size_t len) -+{ -+ int ret; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, -+ "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", -+ __func__, ofs, len); -+ debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); -+ -+ ret = cfi_amdstd_varsize_frob(mtd, do_xxlock_oneblock, ofs, len, -+ (void *)&DO_XXLOCK_ONEBLOCK_UNLOCK); -+ -+ DEBUG(MTD_DEBUG_LEVEL3, -+ "%s: lock status after, ret=%d\n", -+ __func__, ret); -+ debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); -+ -+ return ret; -+} -+ -+ - static void cfi_amdstd_destroy(struct mtd_info *mtd) - { - struct map_info *map = mtd->priv; -@@ -1291,17 +2193,20 @@ - - static char im_name[]="cfi_cmdset_0002"; - -+ - int __init cfi_amdstd_init(void) - { - inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0002); - return 0; - } - -+ - static void __exit cfi_amdstd_exit(void) - { - inter_module_unregister(im_name); - } - -+ - module_init(cfi_amdstd_init); - module_exit(cfi_amdstd_exit); - -@@ -1309,3 +2214,7 @@ - MODULE_AUTHOR("Crossnet Co. et al."); - MODULE_DESCRIPTION("MTD chip driver for AMD/Fujitsu flash chips"); - -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+MODULE_PARM(retry_cmd_max, "i"); -+MODULE_PARM_DESC(retry_cmd_max, "Number of times to retry an erase or program command if it fails - should only be needed by buggy hardware: default 0"); -+#endif -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/cfi_cmdset_0020.c linux/drivers/mtd/chips/cfi_cmdset_0020.c ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/cfi_cmdset_0020.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/chips/cfi_cmdset_0020.c 2004-11-17 18:17:58.945328208 +0100 -@@ -21,16 +21,19 @@ - #include - #include - #include -+#include - #include - #include - - #include -+#include - #include - #include - #include -+#include - #include - #include --#include -+#include - - - static int cfi_staa_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); -@@ -51,10 +54,10 @@ - static struct mtd_info *cfi_staa_setup (struct map_info *); - - static struct mtd_chip_driver cfi_staa_chipdrv = { -- probe: NULL, /* Not usable directly */ -- destroy: cfi_staa_destroy, -- name: "cfi_cmdset_0020", -- module: THIS_MODULE -+ .probe = NULL, /* Not usable directly */ -+ .destroy = cfi_staa_destroy, -+ .name = "cfi_cmdset_0020", -+ .module = THIS_MODULE - }; - - /* #define DEBUG_LOCK_BITS */ -@@ -113,7 +116,6 @@ - { - struct cfi_private *cfi = map->fldrv_priv; - int i; -- __u32 base = cfi->chips[0].start; - - if (cfi->cfi_mode) { - /* -@@ -123,35 +125,10 @@ - */ - __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; - struct cfi_pri_intelext *extp; -- int ofs_factor = cfi->interleave * cfi->device_type; -- -- printk(" ST Microelectronics Extended Query Table at 0x%4.4X\n", adr); -- if (!adr) -- return NULL; -- -- /* Switch it into Query Mode */ -- cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); -- -- extp = kmalloc(sizeof(*extp), GFP_KERNEL); -- if (!extp) { -- printk(KERN_ERR "Failed to allocate memory\n"); -- return NULL; -- } -- -- /* Read in the Extended Query Table */ -- for (i=0; iMajorVersion != '1' || -- (extp->MinorVersion < '0' || extp->MinorVersion > '2')) { -- printk(KERN_WARNING " Unknown staa Extended Query " -- "version %c.%c.\n", extp->MajorVersion, -- extp->MinorVersion); -- kfree(extp); -+ extp = (struct cfi_pri_intelext*)cfi_read_pri(map, adr, sizeof(*extp), "ST Microelectronics"); -+ if (!extp) - return NULL; -- } - - /* Do some byteswapping if necessary */ - extp->FeatureSupport = cfi32_to_cpu(extp->FeatureSupport); -@@ -172,11 +149,6 @@ - cfi->chips[i].erase_time = 1024; - } - -- map->fldrv = &cfi_staa_chipdrv; -- MOD_INC_USE_COUNT; -- -- /* Make sure it's in read mode */ -- cfi_send_gen_cmd(0xff, 0x55, base, map, cfi, cfi->device_type, NULL); - return cfi_staa_setup(map); - } - -@@ -208,6 +180,7 @@ - if (!mtd->eraseregions) { - printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n"); - kfree(cfi->cmdset_priv); -+ kfree(mtd); - return NULL; - } - -@@ -232,6 +205,7 @@ - printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize); - kfree(mtd->eraseregions); - kfree(cfi->cmdset_priv); -+ kfree(mtd); - return NULL; - } - -@@ -256,7 +230,7 @@ - mtd->flags |= MTD_ECC; /* FIXME: Not all STMicro flashes have this */ - mtd->eccsize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */ - map->fldrv = &cfi_staa_chipdrv; -- MOD_INC_USE_COUNT; -+ __module_get(THIS_MODULE); - mtd->name = map->name; - return mtd; - } -@@ -288,7 +262,7 @@ - */ - switch (chip->state) { - case FL_ERASING: -- if (!((struct cfi_pri_intelext *)cfi->cmdset_priv)->FeatureSupport & 2) -+ if (!(((struct cfi_pri_intelext *)cfi->cmdset_priv)->FeatureSupport & 2)) - goto sleep; /* We don't support erase suspend */ - - cfi_write (map, CMD(0xb0), cmd_addr); -@@ -374,7 +348,7 @@ - goto retry; - } - -- map->copy_from(map, buf, adr, len); -+ map_copy_from(map, buf, adr, len); - - if (suspended) { - chip->state = chip->oldstate; -@@ -540,11 +514,11 @@ - /* Write data */ - for (z = 0; z < len; z += CFIDEV_BUSWIDTH) { - if (cfi_buswidth_is_1()) { -- map->write8 (map, *((__u8*)buf)++, adr+z); -+ map_write8 (map, *((__u8*)buf)++, adr+z); - } else if (cfi_buswidth_is_2()) { -- map->write16 (map, *((__u16*)buf)++, adr+z); -+ map_write16 (map, *((__u16*)buf)++, adr+z); - } else if (cfi_buswidth_is_4()) { -- map->write32 (map, *((__u32*)buf)++, adr+z); -+ map_write32 (map, *((__u32*)buf)++, adr+z); - } else { - DISABLE_VPP(map); - return -EINVAL; -@@ -1436,13 +1410,13 @@ - - static char im_name[]="cfi_cmdset_0020"; - --mod_init_t cfi_staa_init(void) -+int __init cfi_staa_init(void) - { - inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0020); - return 0; - } - --mod_exit_t cfi_staa_exit(void) -+static void __exit cfi_staa_exit(void) - { - inter_module_unregister(im_name); - } -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/cfi_probe.c linux/drivers/mtd/chips/cfi_probe.c ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/cfi_probe.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/chips/cfi_probe.c 2004-11-17 18:17:58.947327904 +0100 -@@ -1,13 +1,14 @@ - /* - Common Flash Interface probe code. - (C) 2000 Red Hat. GPL'd. -- $Id$ -+ $Id$ - */ - - #include - #include - #include - #include -+#include - #include - #include - #include -@@ -25,7 +26,7 @@ - #endif - - static int cfi_probe_chip(struct map_info *map, __u32 base, -- struct flchip *chips, struct cfi_private *cfi); -+ unsigned long *chip_map, struct cfi_private *cfi); - static int cfi_chip_setup(struct map_info *map, struct cfi_private *cfi); - - struct mtd_info *cfi_probe(struct map_info *map); -@@ -48,7 +49,7 @@ - } - - static int cfi_probe_chip(struct map_info *map, __u32 base, -- struct flchip *chips, struct cfi_private *cfi) -+ unsigned long *chip_map, struct cfi_private *cfi) - { - int i; - -@@ -77,18 +78,24 @@ - } - - /* Check each previous chip to see if it's an alias */ -- for (i=0; inumchips; i++) { -+ for (i=0; i < (base >> cfi->chipshift); i++) { -+ unsigned long start; -+ if(!test_bit(i, chip_map)) { -+ /* Skip location; no valid chip at this address */ -+ continue; -+ } -+ start = i << cfi->chipshift; - /* This chip should be in read mode if it's one - we've already touched. */ -- if (qry_present(map,chips[i].start,cfi)) { -+ if (qry_present(map, start, cfi)) { - /* Eep. This chip also had the QRY marker. - * Is it an alias for the new one? */ -- cfi_send_gen_cmd(0xF0, 0, chips[i].start, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0xF0, 0, start, map, cfi, cfi->device_type, NULL); - - /* If the QRY marker goes away, it's an alias */ -- if (!qry_present(map, chips[i].start, cfi)) { -+ if (!qry_present(map, start, cfi)) { - printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", -- map->name, base, chips[i].start); -+ map->name, base, start); - return 0; - } - /* Yes, it's actually got QRY for data. Most -@@ -99,7 +106,7 @@ - - if (qry_present(map, base, cfi)) { - printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", -- map->name, base, chips[i].start); -+ map->name, base, start); - return 0; - } - } -@@ -107,13 +114,7 @@ - - /* OK, if we got to here, then none of the previous chips appear to - be aliases for the current one. */ -- if (cfi->numchips == MAX_CFI_CHIPS) { -- printk(KERN_WARNING"%s: Too many flash chips detected. Increase MAX_CFI_CHIPS from %d.\n", map->name, MAX_CFI_CHIPS); -- /* Doesn't matter about resetting it to Read Mode - we're not going to talk to it anyway */ -- return -1; -- } -- chips[cfi->numchips].start = base; -- chips[cfi->numchips].state = FL_READY; -+ set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */ - cfi->numchips++; - - /* Put it back into Read Mode */ -@@ -179,9 +180,28 @@ - (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1); - #endif - } -+ -+ /* Note we put the device back into Read Mode BEFORE going into Auto -+ * Select Mode, as some devices support nesting of modes, others -+ * don't. This way should always work. -+ * On cmdset 0001 the writes of 0xaa and 0x55 are not needed, and -+ * so should be treated as nops or illegal (and so put the device -+ * back into Read Mode, which is a nop in this case). -+ */ -+ cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0xaa, 0x555, base, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL); -+ cfi->mfr = cfi_read_query(map, base); -+ cfi->id = cfi_read_query(map, base + ofs_factor); -+ - /* Put it back into Read Mode */ - cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); - -+ printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit mode\n", -+ map->name, cfi->interleave, cfi->device_type*8, base, -+ map->buswidth*8); -+ - return 1; - } - -@@ -240,11 +260,11 @@ - printk("No Alternate Algorithm Table\n"); - - -- printk("Vcc Minimum: %x.%x V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf); -- printk("Vcc Maximum: %x.%x V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf); -+ printk("Vcc Minimum: %2d.%d V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf); -+ printk("Vcc Maximum: %2d.%d V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf); - if (cfip->VppMin) { -- printk("Vpp Minimum: %x.%x V\n", cfip->VppMin >> 4, cfip->VppMin & 0xf); -- printk("Vpp Maximum: %x.%x V\n", cfip->VppMax >> 4, cfip->VppMax & 0xf); -+ printk("Vpp Minimum: %2d.%d V\n", cfip->VppMin >> 4, cfip->VppMin & 0xf); -+ printk("Vpp Maximum: %2d.%d V\n", cfip->VppMax >> 4, cfip->VppMax & 0xf); - } - else - printk("No Vpp line\n"); -@@ -303,8 +323,8 @@ - #endif /* DEBUG_CFI */ - - static struct chip_probe cfi_chip_probe = { -- name: "CFI", -- probe_chip: cfi_probe_chip -+ .name = "CFI", -+ .probe_chip = cfi_probe_chip - }; - - struct mtd_info *cfi_probe(struct map_info *map) -@@ -317,9 +337,9 @@ - } - - static struct mtd_chip_driver cfi_chipdrv = { -- probe: cfi_probe, -- name: "cfi_probe", -- module: THIS_MODULE -+ .probe = cfi_probe, -+ .name = "cfi_probe", -+ .module = THIS_MODULE - }; - - int __init cfi_probe_init(void) -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/cfi_util.c linux/drivers/mtd/chips/cfi_util.c ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/cfi_util.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/chips/cfi_util.c 2004-11-17 18:17:58.000000000 +0100 -@@ -0,0 +1,91 @@ -+/* -+ * Common Flash Interface support: -+ * Generic utility functions not dependant on command set -+ * -+ * Copyright (C) 2002 Red Hat -+ * Copyright (C) 2003 STMicroelectronics Limited -+ * -+ * This code is covered by the GPL. -+ * -+ * $Id$ -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct cfi_extquery * -+cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ __u32 base = 0; // cfi->chips[0].start; -+ int ofs_factor = cfi->interleave * cfi->device_type; -+ int i; -+ struct cfi_extquery *extp = NULL; -+ -+ printk(" %s Extended Query Table at 0x%4.4X\n", name, adr); -+ if (!adr) -+ goto out; -+ -+ /* Switch it into Query Mode */ -+ cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); -+ -+ extp = kmalloc(size, GFP_KERNEL); -+ if (!extp) { -+ printk(KERN_ERR "Failed to allocate memory\n"); -+ goto out; -+ } -+ -+ /* Read in the Extended Query Table */ -+ for (i=0; iMajorVersion != '1' || -+ (extp->MinorVersion < '0' || extp->MinorVersion > '3')) { -+ printk(KERN_WARNING " Unknown %s Extended Query " -+ "version %c.%c.\n", name, extp->MajorVersion, -+ extp->MinorVersion); -+ kfree(extp); -+ extp = NULL; -+ goto out; -+ } -+ -+out: -+ /* Make sure it's in read mode */ -+ cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL); -+ -+ return extp; -+} -+ -+EXPORT_SYMBOL(cfi_read_pri); -+ -+void cfi_fixup(struct map_info *map, struct cfi_fixup* fixups) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ struct cfi_fixup *f; -+ -+ for (f=fixups; f->fixup; f++) { -+ if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi->mfr)) && -+ ((f->id == CFI_ID_ANY) || (f->id == cfi->id))) { -+ f->fixup(map, f->param); -+ } -+ } -+} -+ -+EXPORT_SYMBOL(cfi_fixup); -+ -+MODULE_LICENSE("GPL"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/chipreg.c linux/drivers/mtd/chips/chipreg.c ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/chipreg.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/chips/chipreg.c 2004-11-17 18:17:58.949327600 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Registration for chip drivers - * -@@ -7,10 +7,13 @@ - - #include - #include -+#include - #include - #include --#include -+#include - #include -+#include -+#include - - spinlock_t chip_drvs_lock = SPIN_LOCK_UNLOCKED; - static LIST_HEAD(chip_drvs_list); -@@ -44,10 +47,8 @@ - break; - } - } -- if (ret && !try_inc_mod_count(ret->module)) { -- /* Eep. Failed. */ -+ if (ret && !try_module_get(ret->module)) - ret = NULL; -- } - - spin_unlock(&chip_drvs_lock); - -@@ -64,32 +65,46 @@ - - drv = get_mtd_chip_driver(name); - -- if (!drv && !request_module(name)) -+ if (!drv && !request_module("%s", name)) - drv = get_mtd_chip_driver(name); - - if (!drv) - return NULL; - - ret = drv->probe(map); --#ifdef CONFIG_MODULES -+ - /* We decrease the use count here. It may have been a - probe-only module, which is no longer required from this - point, having given us a handle on (and increased the use - count of) the actual driver code. - */ -- if(drv->module) -- __MOD_DEC_USE_COUNT(drv->module); --#endif -+ module_put(drv->module); - - if (ret) - return ret; - - return NULL; - } -+/* -+ * Destroy an MTD device which was created for a map device. -+ * Make sure the MTD device is already unregistered before calling this -+ */ -+void map_destroy(struct mtd_info *mtd) -+{ -+ struct map_info *map = mtd->priv; -+ -+ if (map->fldrv->destroy) -+ map->fldrv->destroy(mtd); -+ -+ module_put(map->fldrv->module); -+ -+ kfree(mtd); -+} - - EXPORT_SYMBOL(register_mtd_chip_driver); - EXPORT_SYMBOL(unregister_mtd_chip_driver); - EXPORT_SYMBOL(do_map_probe); -+EXPORT_SYMBOL(map_destroy); - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("David Woodhouse "); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/gen_probe.c linux/drivers/mtd/chips/gen_probe.c ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/gen_probe.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/chips/gen_probe.c 2004-11-17 18:17:58.951327296 +0100 -@@ -1,14 +1,17 @@ - /* - * Routines common to all CFI-type probes. -- * (C) 2001, 2001 Red Hat, Inc. -+ * (C) 2001-2003 Red Hat, Inc. - * GPL'd -- * $Id$ -+ * $Id$ - */ - - #include -+#include -+#include - #include - #include - #include -+#include - #include - - static struct mtd_info *check_cmd_set(struct map_info *, int); -@@ -50,11 +53,11 @@ - - struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp) - { -- unsigned long base=0; - struct cfi_private cfi; - struct cfi_private *retcfi; -- struct flchip chip[MAX_CFI_CHIPS]; -- int i; -+ unsigned long *chip_map; -+ int i, j; -+ int max_chips; - - memset(&cfi, 0, sizeof(cfi)); - -@@ -77,8 +80,6 @@ - return NULL; - } - #endif -- chip[0].start = 0; -- chip[0].state = FL_READY; - cfi.chipshift = cfi.cfiq->DevSize; - - switch(cfi.interleave) { -@@ -103,20 +104,28 @@ - cfi.numchips = 1; - - /* -+ * Allocate memory for bitmap of valid chips. -+ * Align bitmap storage size to full byte. -+ */ -+ max_chips = map->size >> cfi.chipshift; -+ chip_map = kmalloc((max_chips / 8) + ((max_chips % 8) ? 1 : 0), GFP_KERNEL); -+ if (!chip_map) { -+ printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name); -+ kfree(cfi.cfiq); -+ return NULL; -+ } -+ -+ set_bit(0, chip_map); /* Mark first chip valid */ -+ -+ /* - * Now probe for other chips, checking sensibly for aliases while - * we're at it. The new_chip probe above should have let the first - * chip in read mode. -- * -- * NOTE: Here, we're checking if there is room for another chip -- * the same size within the mapping. Therefore, -- * base + chipsize <= map->size is the correct thing to do, -- * because, base + chipsize would be the _first_ byte of the -- * next chip, not the one we're currently pondering. - */ - -- for (base = (1<size; -- base += (1<probe_chip(map, base, &chip[0], &cfi); -+ for (i = 1; i < max_chips; i++) { -+ cp->probe_chip(map, i << cfi.chipshift, chip_map, &cfi); -+ } - - /* - * Now allocate the space for the structures we need to return to -@@ -128,19 +137,26 @@ - if (!retcfi) { - printk(KERN_WARNING "%s: kmalloc failed for CFI private structure\n", map->name); - kfree(cfi.cfiq); -+ kfree(chip_map); - return NULL; - } - - memcpy(retcfi, &cfi, sizeof(cfi)); -- memcpy(&retcfi->chips[0], chip, sizeof(struct flchip) * cfi.numchips); -+ memset(&retcfi->chips[0], 0, sizeof(struct flchip) * cfi.numchips); - -- /* Fix up the stuff that breaks when you move it */ -- for (i=0; i< retcfi->numchips; i++) { -- init_waitqueue_head(&retcfi->chips[i].wq); -- spin_lock_init(&retcfi->chips[i]._spinlock); -- retcfi->chips[i].mutex = &retcfi->chips[i]._spinlock; -+ for (i = 0, j = 0; (j < cfi.numchips) && (i < max_chips); i++) { -+ if(test_bit(i, chip_map)) { -+ struct flchip *pchip = &retcfi->chips[j++]; -+ -+ pchip->start = (i << cfi.chipshift); -+ pchip->state = FL_READY; -+ init_waitqueue_head(&pchip->wq); -+ spin_lock_init(&pchip->_spinlock); -+ pchip->mutex = &pchip->_spinlock; -+ } - } - -+ kfree(chip_map); - return retcfi; - } - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/jedec.c linux/drivers/mtd/chips/jedec.c ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/jedec.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/chips/jedec.c 2004-11-17 18:17:58.953326992 +0100 -@@ -11,10 +11,16 @@ - * not going to guess how to send commands to them, plus I expect they will - * all speak CFI.. - * -- * $Id$ -+ * $Id$ - */ - -+#include -+#include -+#include - #include -+#include -+#include -+#include - - static struct mtd_info *jedec_probe(struct map_info *); - static int jedec_probe8(struct map_info *map,unsigned long base, -@@ -33,14 +39,51 @@ - - /* Listing of parts and sizes. We need this table to learn the sector - size of the chip and the total length */ --static const struct JEDECTable JEDEC_table[] = -- {{0x013D,"AMD Am29F017D",2*1024*1024,64*1024,MTD_CAP_NORFLASH}, -- {0x01AD,"AMD Am29F016",2*1024*1024,64*1024,MTD_CAP_NORFLASH}, -- {0x01D5,"AMD Am29F080",1*1024*1024,64*1024,MTD_CAP_NORFLASH}, -- {0x01A4,"AMD Am29F040",512*1024,64*1024,MTD_CAP_NORFLASH}, -- {0x20E3,"AMD Am29W040B",512*1024,64*1024,MTD_CAP_NORFLASH}, -- {0xC2AD,"Macronix MX29F016",2*1024*1024,64*1024,MTD_CAP_NORFLASH}, -- {}}; -+static const struct JEDECTable JEDEC_table[] = { -+ { -+ .jedec = 0x013D, -+ .name = "AMD Am29F017D", -+ .size = 2*1024*1024, -+ .sectorsize = 64*1024, -+ .capabilities = MTD_CAP_NORFLASH -+ }, -+ { -+ .jedec = 0x01AD, -+ .name = "AMD Am29F016", -+ .size = 2*1024*1024, -+ .sectorsize = 64*1024, -+ .capabilities = MTD_CAP_NORFLASH -+ }, -+ { -+ .jedec = 0x01D5, -+ .name = "AMD Am29F080", -+ .size = 1*1024*1024, -+ .sectorsize = 64*1024, -+ .capabilities = MTD_CAP_NORFLASH -+ }, -+ { -+ .jedec = 0x01A4, -+ .name = "AMD Am29F040", -+ .size = 512*1024, -+ .sectorsize = 64*1024, -+ .capabilities = MTD_CAP_NORFLASH -+ }, -+ { -+ .jedec = 0x20E3, -+ .name = "AMD Am29W040B", -+ .size = 512*1024, -+ .sectorsize = 64*1024, -+ .capabilities = MTD_CAP_NORFLASH -+ }, -+ { -+ .jedec = 0xC2AD, -+ .name = "Macronix MX29F016", -+ .size = 2*1024*1024, -+ .sectorsize = 64*1024, -+ .capabilities = MTD_CAP_NORFLASH -+ }, -+ { .jedec = 0x0 } -+}; - - static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id); - static void jedec_sync(struct mtd_info *mtd) {}; -@@ -54,9 +97,9 @@ - - - static struct mtd_chip_driver jedec_chipdrv = { -- probe: jedec_probe, -- name: "jedec", -- module: THIS_MODULE -+ .probe = jedec_probe, -+ .name = "jedec", -+ .module = THIS_MODULE - }; - - /* Probe entry point */ -@@ -131,8 +174,7 @@ - /* Generate a part name that includes the number of different chips and - other configuration information */ - count = 1; -- strncpy(Part,map->name,sizeof(Part)-10); -- Part[sizeof(Part)-11] = 0; -+ strlcpy(Part,map->name,sizeof(Part)-10); - strcat(Part," "); - Uniq = 0; - for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) -@@ -209,8 +251,7 @@ - // printk("Part: '%s'\n",Part); - - memset(MTD,0,sizeof(*MTD)); -- // strncpy(MTD->name,Part,sizeof(MTD->name)); -- // MTD->name[sizeof(MTD->name)-1] = 0; -+ // strlcpy(MTD->name,Part,sizeof(MTD->name)); - MTD->name = map->name; - MTD->type = MTD_NORFLASH; - MTD->flags = MTD_CAP_NORFLASH; -@@ -229,7 +270,7 @@ - MTD->priv = map; - map->fldrv_priv = priv; - map->fldrv = &jedec_chipdrv; -- MOD_INC_USE_COUNT; -+ __module_get(THIS_MODULE); - return MTD; - } - -@@ -351,8 +392,8 @@ - static int jedec_probe8(struct map_info *map,unsigned long base, - struct jedec_private *priv) - { -- #define flread(x) map->read8(map,base+x) -- #define flwrite(v,x) map->write8(map,v,base+x) -+ #define flread(x) map_read8(map,base+x) -+ #define flwrite(v,x) map_write8(map,v,base+x) - - const unsigned long AutoSel1 = 0xAA; - const unsigned long AutoSel2 = 0x55; -@@ -411,8 +452,8 @@ - static int jedec_probe32(struct map_info *map,unsigned long base, - struct jedec_private *priv) - { -- #define flread(x) map->read32(map,base+((x)<<2)) -- #define flwrite(v,x) map->write32(map,v,base+((x)<<2)) -+ #define flread(x) map_read32(map,base+((x)<<2)) -+ #define flwrite(v,x) map_write32(map,v,base+((x)<<2)) - - const unsigned long AutoSel1 = 0xAAAAAAAA; - const unsigned long AutoSel2 = 0x55555555; -@@ -490,7 +531,7 @@ - { - struct map_info *map = (struct map_info *)mtd->priv; - -- map->copy_from(map, buf, from, len); -+ map_copy_from(map, buf, from, len); - *retlen = len; - return 0; - } -@@ -514,7 +555,7 @@ - get = priv->bank_fill[0] - offset; - - bank /= priv->bank_fill[0]; -- map->copy_from(map,buf + *retlen,bank*my_bank_size + offset,get); -+ map_copy_from(map,buf + *retlen,bank*my_bank_size + offset,get); - - len -= get; - *retlen += get; -@@ -545,8 +586,8 @@ - static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) - { - // Does IO to the currently selected chip -- #define flread(x) map->read8(map,chip->base+((x)<addrshift)) -- #define flwrite(v,x) map->write8(map,v,chip->base+((x)<addrshift)) -+ #define flread(x) map_read8(map,chip->base+((x)<addrshift)) -+ #define flwrite(v,x) map_write8(map,v,chip->base+((x)<addrshift)) - - unsigned long Time = 0; - unsigned long NoTime = 0; -@@ -608,7 +649,7 @@ - - /* Poll the flash for erasure completion, specs say this can take as long - as 480 seconds to do all the sectors (for a 2 meg flash). -- Erasure time is dependant on chip age, temp and wear.. */ -+ Erasure time is dependent on chip age, temp and wear.. */ - - /* This being a generic routine assumes a 32 bit bus. It does read32s - and bundles interleved chips into the same grouping. This will work -@@ -651,19 +692,19 @@ - or this is not really flash ;> */ - switch (map->buswidth) { - case 1: -- Last[0] = map->read8(map,(chip->base >> chip->addrshift) + chip->start + off); -- Last[1] = map->read8(map,(chip->base >> chip->addrshift) + chip->start + off); -- Last[2] = map->read8(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[0] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[1] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[2] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); - break; - case 2: -- Last[0] = map->read16(map,(chip->base >> chip->addrshift) + chip->start + off); -- Last[1] = map->read16(map,(chip->base >> chip->addrshift) + chip->start + off); -- Last[2] = map->read16(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[0] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[1] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[2] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); - break; - case 3: -- Last[0] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); -- Last[1] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); -- Last[2] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[0] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[1] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[2] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); - break; - } - Count = 3; -@@ -699,13 +740,13 @@ - - switch (map->buswidth) { - case 1: -- Last[Count % 4] = map->read8(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[Count % 4] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); - break; - case 2: -- Last[Count % 4] = map->read16(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[Count % 4] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); - break; - case 4: -- Last[Count % 4] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[Count % 4] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); - break; - } - Count++; -@@ -755,10 +796,10 @@ - size_t *retlen, const u_char *buf) - { - /* Does IO to the currently selected chip. It takes the bank addressing -- base (which is divisable by the chip size) adds the necesary lower bits -- of addrshift (interleve index) and then adds the control register index. */ -- #define flread(x) map->read8(map,base+(off&((1<addrshift)-1))+((x)<addrshift)) -- #define flwrite(v,x) map->write8(map,v,base+(off&((1<addrshift)-1))+((x)<addrshift)) -+ base (which is divisible by the chip size) adds the necessary lower bits -+ of addrshift (interleave index) and then adds the control register index. */ -+ #define flread(x) map_read8(map,base+(off&((1<addrshift)-1))+((x)<addrshift)) -+ #define flwrite(v,x) map_write8(map,v,base+(off&((1<addrshift)-1))+((x)<addrshift)) - - struct map_info *map = (struct map_info *)mtd->priv; - struct jedec_private *priv = (struct jedec_private *)map->fldrv_priv; -@@ -794,7 +835,7 @@ - // Loop over this page - for (; off != (chip->size << chip->addrshift) && len != 0; start++, len--, off++,buf++) - { -- unsigned char oldbyte = map->read8(map,base+off); -+ unsigned char oldbyte = map_read8(map,base+off); - unsigned char Last[4]; - unsigned long Count = 0; - -@@ -809,10 +850,10 @@ - flwrite(0xAA,0x555); - flwrite(0x55,0x2AA); - flwrite(0xA0,0x555); -- map->write8(map,*buf,base + off); -- Last[0] = map->read8(map,base + off); -- Last[1] = map->read8(map,base + off); -- Last[2] = map->read8(map,base + off); -+ map_write8(map,*buf,base + off); -+ Last[0] = map_read8(map,base + off); -+ Last[1] = map_read8(map,base + off); -+ Last[2] = map_read8(map,base + off); - - /* Wait for the flash to finish the operation. We store the last 4 - status bytes that have been retrieved so we can determine why -@@ -820,7 +861,7 @@ - failure */ - for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && - Count < 10000; Count++) -- Last[Count % 4] = map->read8(map,base + off); -+ Last[Count % 4] = map_read8(map,base + off); - if (Last[(Count - 1) % 4] != *buf) - { - jedec_flash_failed(Last[(Count - 3) % 4]); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/jedec_probe.c linux/drivers/mtd/chips/jedec_probe.c ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/jedec_probe.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/chips/jedec_probe.c 2004-11-17 18:17:58.954326840 +0100 -@@ -1,9 +1,11 @@ - /* - Common Flash Interface probe code. - (C) 2000 Red Hat. GPL'd. -- $Id$ -+ $Id$ - See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5) - for the standard this probe goes back to. -+ -+ Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com - */ - - #include -@@ -15,7 +17,9 @@ - #include - #include - #include -+#include - -+#include - #include - #include - #include -@@ -26,20 +30,24 @@ - #define MANUFACTURER_FUJITSU 0x0004 - #define MANUFACTURER_INTEL 0x0089 - #define MANUFACTURER_MACRONIX 0x00C2 --#define MANUFACTURER_ST 0x0020 -+#define MANUFACTURER_PMC 0x009D - #define MANUFACTURER_SST 0x00BF -+#define MANUFACTURER_ST 0x0020 - #define MANUFACTURER_TOSHIBA 0x0098 -+#define MANUFACTURER_WINBOND 0x00da - - - /* AMD */ - #define AM29F800BB 0x2258 - #define AM29F800BT 0x22D6 -+#define AM29LV400BB 0x22BA -+#define AM29LV400BT 0x22B9 - #define AM29LV800BB 0x225B - #define AM29LV800BT 0x22DA - #define AM29LV160DT 0x22C4 - #define AM29LV160DB 0x2249 - #define AM29F017D 0x003D --#define AM29F016 0x00AD -+#define AM29F016D 0x00AD - #define AM29F080 0x00D5 - #define AM29F040 0x00A4 - #define AM29LV040B 0x004F -@@ -54,6 +62,7 @@ - #define AT49BV32XT 0x00C9 - - /* Fujitsu */ -+#define MBM29F040C 0x00A4 - #define MBM29LV650UE 0x22D7 - #define MBM29LV320TE 0x22F6 - #define MBM29LV320BE 0x22F9 -@@ -61,6 +70,9 @@ - #define MBM29LV160BE 0x2249 - #define MBM29LV800BA 0x225B - #define MBM29LV800TA 0x22DA -+#define MBM29LV400TC 0x22B9 -+#define MBM29LV400BC 0x22BA -+ - - /* Intel */ - #define I28F004B3T 0x00d4 -@@ -93,8 +105,14 @@ - #define MX29F004T 0x0045 - #define MX29F004B 0x0046 - -+/* PMC */ -+#define PM49FL002 0x006D -+#define PM49FL004 0x006E -+#define PM49FL008 0x006A -+ - /* ST - www.st.com */ --#define M29W800T 0x00D7 -+#define M29W800DT 0x00D7 -+#define M29W800DB 0x005B - #define M29W160DT 0x22C4 - #define M29W160DB 0x2249 - #define M29W040B 0x00E3 -@@ -110,6 +128,7 @@ - #define SST39LF040 0x00D7 - #define SST39SF010A 0x00B5 - #define SST39SF020A 0x00B6 -+#define SST49LF004B 0x0060 - #define SST49LF030A 0x001C - #define SST49LF040A 0x0051 - #define SST49LF080A 0x005B -@@ -122,15 +141,87 @@ - #define TC58FVT641 0x0093 - #define TC58FVB641 0x0095 - -+/* Winbond */ -+#define W49V002A 0x00b0 -+ -+ -+/* -+ * Unlock address sets for AMD command sets. -+ * Intel command sets use the MTD_UADDR_UNNECESSARY. -+ * Each identifier, except MTD_UADDR_UNNECESSARY, and -+ * MTD_UADDR_NO_SUPPORT must be defined below in unlock_addrs[]. -+ * MTD_UADDR_NOT_SUPPORTED must be 0 so that structure -+ * initialization need not require initializing all of the -+ * unlock addresses for all bit widths. -+ */ -+enum uaddr { -+ MTD_UADDR_NOT_SUPPORTED = 0, /* data width not supported */ -+ MTD_UADDR_0x0555_0x02AA, -+ MTD_UADDR_0x0555_0x0AAA, -+ MTD_UADDR_0x5555_0x2AAA, -+ MTD_UADDR_0x0AAA_0x0555, -+ MTD_UADDR_DONT_CARE, /* Requires an arbitrary address */ -+ MTD_UADDR_UNNECESSARY, /* Does not require any address */ -+}; -+ -+ -+struct unlock_addr { -+ int addr1; -+ int addr2; -+}; -+ -+ -+/* -+ * I don't like the fact that the first entry in unlock_addrs[] -+ * exists, but is for MTD_UADDR_NOT_SUPPORTED - and, therefore, -+ * should not be used. The problem is that structures with -+ * initializers have extra fields initialized to 0. It is _very_ -+ * desireable to have the unlock address entries for unsupported -+ * data widths automatically initialized - that means that -+ * MTD_UADDR_NOT_SUPPORTED must be 0 and the first entry here -+ * must go unused. -+ */ -+static const struct unlock_addr unlock_addrs[] = { -+ [MTD_UADDR_NOT_SUPPORTED] = { -+ .addr1 = 0xffff, -+ .addr2 = 0xffff -+ }, -+ -+ [MTD_UADDR_0x0555_0x02AA] = { -+ .addr1 = 0x0555, -+ .addr2 = 0x02aa -+ }, -+ -+ [MTD_UADDR_0x0555_0x0AAA] = { -+ .addr1 = 0x0555, -+ .addr2 = 0x0aaa -+ }, -+ -+ [MTD_UADDR_0x5555_0x2AAA] = { -+ .addr1 = 0x5555, -+ .addr2 = 0x2aaa -+ }, -+ -+ [MTD_UADDR_0x0AAA_0x0555] = { -+ .addr1 = 0x0AAA, -+ .addr2 = 0x0555 -+ }, -+ -+ [MTD_UADDR_DONT_CARE] = { -+ .addr1 = 0x0000, /* Doesn't matter which address */ -+ .addr2 = 0x0000 /* is used - must be last entry */ -+ } -+}; -+ - - struct amd_flash_info { - const __u16 mfr_id; - const __u16 dev_id; - const char *name; - const int DevSize; -- const int InterfaceDesc; - const int NumEraseRegions; - const int CmdSet; -+ const __u8 uaddr[4]; /* unlock addrs for 8, 16, 32, 64 */ - const ulong regions[4]; - }; - -@@ -145,760 +236,1214 @@ - #define SIZE_4MiB 22 - #define SIZE_8MiB 23 - -+ -+/* -+ * Please keep this list ordered by manufacturer! -+ * Fortunately, the list isn't searched often and so a -+ * slow, linear search isn't so bad. -+ */ - static const struct amd_flash_info jedec_table[] = { - { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F032B, -- name: "AMD AM29F032B", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,64) -- } -- }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV160DT, -- name: "AMD AM29LV160DT", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,31), -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F032B, -+ .name = "AMD AM29F032B", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,64) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV160DT, -+ .name = "AMD AM29LV160DT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,31), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV160DB, -- name: "AMD AM29LV160DB", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV160DB, -+ .name = "AMD AM29LV160DB", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x08000,1), - ERASEINFO(0x10000,31) - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVT160, -- name: "Toshiba TC58FVT160", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,31), -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV400BB, -+ .name = "AMD AM29LV400BB", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x10000,7) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV400BT, -+ .name = "AMD AM29LV400BT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,7), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVB160, -- name: "Toshiba TC58FVB160", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV800BB, -+ .name = "AMD AM29LV800BB", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x08000,1), -- ERASEINFO(0x10000,31) -+ ERASEINFO(0x10000,15), - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVB321, -- name: "Toshiba TC58FVB321", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x02000,8), -- ERASEINFO(0x10000,63) -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F800BB, -+ .name = "AMD AM29F800BB", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x10000,15), - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVT321, -- name: "Toshiba TC58FVT321", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x10000,63), -- ERASEINFO(0x02000,8) -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV800BT, -+ .name = "AMD AM29LV800BT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,15), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVB641, -- name: "Toshiba TC58FVB641", -- DevSize: SIZE_8MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x02000,8), -- ERASEINFO(0x10000,127) -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F800BT, -+ .name = "AMD AM29F800BT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,15), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVT641, -- name: "Toshiba TC58FVT641", -- DevSize: SIZE_8MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x10000,127), -- ERASEINFO(0x02000,8) -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F017D, -+ .name = "AMD AM29F017D", -+ .uaddr = { -+ [0] = MTD_UADDR_DONT_CARE /* x8 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,32), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F016D, -+ .name = "AMD AM29F016D", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,32), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F080, -+ .name = "AMD AM29F080", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,16), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F040, -+ .name = "AMD AM29F040", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,8), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV040B, -+ .name = "AMD AM29LV040B", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,8), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT49BV512, -+ .name = "Atmel AT49BV512", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_64KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,1) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT29LV512, -+ .name = "Atmel AT29LV512", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_64KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x80,256), -+ ERASEINFO(0x80,256) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT49BV16X, -+ .name = "Atmel AT49BV16X", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x0AAA, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x0AAA /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x02000,8), -+ ERASEINFO(0x10000,31) - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV650UE, -- name: "Fujitsu MBM29LV650UE", -- DevSize: SIZE_8MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,128) -- } -- }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV320TE, -- name: "Fujitsu MBM29LV320TE", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x10000,63), -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT49BV16XT, -+ .name = "Atmel AT49BV16XT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x0AAA, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x0AAA /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x10000,31), - ERASEINFO(0x02000,8) - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV320BE, -- name: "Fujitsu MBM29LV320BE", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x02000,8), -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT49BV32X, -+ .name = "Atmel AT49BV32X", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x0AAA, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x0AAA /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x02000,8), - ERASEINFO(0x10000,63) - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV160TE, -- name: "Fujitsu MBM29LV160TE", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,31), -- ERASEINFO(0x08000,1), -- ERASEINFO(0x02000,2), -- ERASEINFO(0x04000,1) -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT49BV32XT, -+ .name = "Atmel AT49BV32XT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x0AAA, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x0AAA /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x10000,63), -+ ERASEINFO(0x02000,8) - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV160BE, -- name: "Fujitsu MBM29LV160BE", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -- ERASEINFO(0x02000,2), -- ERASEINFO(0x08000,1), -- ERASEINFO(0x10000,31) -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29F040C, -+ .name = "Fujitsu MBM29F040C", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,8) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV650UE, -+ .name = "Fujitsu MBM29LV650UE", -+ .uaddr = { -+ [0] = MTD_UADDR_DONT_CARE /* x16 */ -+ }, -+ .DevSize = SIZE_8MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,128) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV320TE, -+ .name = "Fujitsu MBM29LV320TE", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x10000,63), -+ ERASEINFO(0x02000,8) - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV800BA, -- name: "Fujitsu MBM29LV800BA", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -- ERASEINFO(0x02000,2), -- ERASEINFO(0x08000,1), -- ERASEINFO(0x10000,15) -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV320BE, -+ .name = "Fujitsu MBM29LV320BE", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x02000,8), -+ ERASEINFO(0x10000,63) - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV800TA, -- name: "Fujitsu MBM29LV800TA", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,15), -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV160TE, -+ .name = "Fujitsu MBM29LV160TE", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,31), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV800BB, -- name: "AMD AM29LV800BB", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV160BE, -+ .name = "Fujitsu MBM29LV160BE", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x08000,1), -- ERASEINFO(0x10000,15), -+ ERASEINFO(0x10000,31) - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F800BB, -- name: "AMD AM29F800BB", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV800BA, -+ .name = "Fujitsu MBM29LV800BA", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x08000,1), -- ERASEINFO(0x10000,15), -+ ERASEINFO(0x10000,15) - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV800BT, -- name: "AMD AM29LV800BT", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,15), -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV800TA, -+ .name = "Fujitsu MBM29LV800TA", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,15), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F800BT, -- name: "AMD AM29F800BT", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,15), -- ERASEINFO(0x08000,1), -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV400BC, -+ .name = "Fujitsu MBM29LV400BC", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), -- ERASEINFO(0x04000,1) -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x10000,7) - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV800BB, -- name: "AMD AM29LV800BB", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,15), -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV400TC, -+ .name = "Fujitsu MBM29LV400TC", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,7), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F004B3B, -- name: "Intel 28F004B3B", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F004B3B, -+ .name = "Intel 28F004B3B", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 7), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F004B3T, -- name: "Intel 28F004B3T", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F004B3T, -+ .name = "Intel 28F004B3T", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 7), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F400B3B, -- name: "Intel 28F400B3B", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F400B3B, -+ .name = "Intel 28F400B3B", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 7), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F400B3T, -- name: "Intel 28F400B3T", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F400B3T, -+ .name = "Intel 28F400B3T", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 7), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F008B3B, -- name: "Intel 28F008B3B", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F008B3B, -+ .name = "Intel 28F008B3B", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 15), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F008B3T, -- name: "Intel 28F008B3T", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F008B3T, -+ .name = "Intel 28F008B3T", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 15), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F008S5, -- name: "Intel 28F008S5", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_INTEL_EXT, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,16), -- } -- }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F016S5, -- name: "Intel 28F016S5", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_INTEL_EXT, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,32), -- } -- }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F008SA, -- name: "Intel 28F008SA", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 1, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F008S5, -+ .name = "Intel 28F008S5", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_INTEL_EXT, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,16), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F016S5, -+ .name = "Intel 28F016S5", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_INTEL_EXT, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,32), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F008SA, -+ .name = "Intel 28F008SA", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 1, -+ .regions = { - ERASEINFO(0x10000, 16), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F800B3B, -- name: "Intel 28F800B3B", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F800B3B, -+ .name = "Intel 28F800B3B", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 15), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F800B3T, -- name: "Intel 28F800B3T", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F800B3T, -+ .name = "Intel 28F800B3T", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 15), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F016B3B, -- name: "Intel 28F016B3B", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F016B3B, -+ .name = "Intel 28F016B3B", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 31), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F016S3, -- name: "Intel I28F016S3", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 1, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F016S3, -+ .name = "Intel I28F016S3", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 1, -+ .regions = { - ERASEINFO(0x10000, 32), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F016B3T, -- name: "Intel 28F016B3T", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F016B3T, -+ .name = "Intel 28F016B3T", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 31), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F160B3B, -- name: "Intel 28F160B3B", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F160B3B, -+ .name = "Intel 28F160B3B", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 31), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F160B3T, -- name: "Intel 28F160B3T", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F160B3T, -+ .name = "Intel 28F160B3T", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 31), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F320B3B, -- name: "Intel 28F320B3B", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F320B3B, -+ .name = "Intel 28F320B3B", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 63), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F320B3T, -- name: "Intel 28F320B3T", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F320B3T, -+ .name = "Intel 28F320B3T", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 63), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F640B3B, -- name: "Intel 28F640B3B", -- DevSize: SIZE_8MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F640B3B, -+ .name = "Intel 28F640B3B", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_8MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 127), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F640B3T, -- name: "Intel 28F640B3T", -- DevSize: SIZE_8MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F640B3T, -+ .name = "Intel 28F640B3T", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_8MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 127), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I82802AB, -- name: "Intel 82802AB", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_INTEL_EXT, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,8), -- } -- }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I82802AC, -- name: "Intel 82802AC", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_INTEL_EXT, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,16), -- } -- }, { -- mfr_id: MANUFACTURER_ST, -- dev_id: M29W800T, -- name: "ST M29W800T", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,15), -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I82802AB, -+ .name = "Intel 82802AB", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_INTEL_EXT, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,8), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I82802AC, -+ .name = "Intel 82802AC", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_INTEL_EXT, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,16), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_MACRONIX, -+ .dev_id = MX29LV160T, -+ .name = "MXIC MX29LV160T", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,31), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_ST, -- dev_id: M29W160DT, -- name: "ST M29W160DT", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,31), -- ERASEINFO(0x08000,1), -- ERASEINFO(0x02000,2), -- ERASEINFO(0x04000,1) -- } -- }, { -- mfr_id: MANUFACTURER_ST, -- dev_id: M29W160DB, -- name: "ST M29W160DB", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -+ .mfr_id = MANUFACTURER_MACRONIX, -+ .dev_id = MX29LV160B, -+ .name = "MXIC MX29LV160B", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x08000,1), - ERASEINFO(0x10000,31) - } - }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT49BV512, -- name: "Atmel AT49BV512", -- DevSize: SIZE_64KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,1) -- } -- }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT29LV512, -- name: "Atmel AT29LV512", -- DevSize: SIZE_64KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: { -- ERASEINFO(0x80,256), -- ERASEINFO(0x80,256) -- } -- }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT49BV16X, -- name: "Atmel AT49BV16X", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x02000,8), -- ERASEINFO(0x10000,31) -+ .mfr_id = MANUFACTURER_MACRONIX, -+ .dev_id = MX29F016, -+ .name = "Macronix MX29F016", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,32), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_MACRONIX, -+ .dev_id = MX29F004T, -+ .name = "Macronix MX29F004T", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,7), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x04000,1), - } - }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT49BV16XT, -- name: "Atmel AT49BV16XT", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x10000,31), -- ERASEINFO(0x02000,8) -+ .mfr_id = MANUFACTURER_MACRONIX, -+ .dev_id = MX29F004B, -+ .name = "Macronix MX29F004B", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x10000,7), - } - }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT49BV32X, -- name: "Atmel AT49BV32X", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x02000,8), -- ERASEINFO(0x10000,63) -+ .mfr_id = MANUFACTURER_PMC, -+ .dev_id = PM49FL002, -+ .name = "PMC Pm49FL002", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_256KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO( 0x01000, 64 ) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_PMC, -+ .dev_id = PM49FL004, -+ .name = "PMC Pm49FL004", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO( 0x01000, 128 ) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_PMC, -+ .dev_id = PM49FL008, -+ .name = "PMC Pm49FL008", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO( 0x01000, 256 ) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST39LF512, -+ .name = "SST 39LF512", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_64KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,16), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST39LF010, -+ .name = "SST 39LF010", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_128KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,32), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST39LF020, -+ .name = "SST 39LF020", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_256KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,64), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST39LF040, -+ .name = "SST 39LF040", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,128), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST39SF010A, -+ .name = "SST 39SF010A", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_128KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,32), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST39SF020A, -+ .name = "SST 39SF020A", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_256KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,64), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST49LF004B, -+ .name = "SST 49LF004B", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,128), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST49LF030A, -+ .name = "SST 49LF030A", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,96), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST49LF040A, -+ .name = "SST 49LF040A", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,128), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST49LF080A, -+ .name = "SST 49LF080A", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,256), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */ -+ .dev_id = M29W800DT, -+ .name = "ST M29W800DT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA, /* x8 */ -+ [1] = MTD_UADDR_0x5555_0x2AAA /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,15), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT49BV32XT, -- name: "Atmel AT49BV32XT", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x10000,63), -- ERASEINFO(0x02000,8) -+ .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */ -+ .dev_id = M29W800DB, -+ .name = "ST M29W800DB", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA, /* x8 */ -+ [1] = MTD_UADDR_0x5555_0x2AAA /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x10000,15) - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F017D, -- name: "AMD AM29F017D", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,32), -- } -- }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F016, -- name: "AMD AM29F016", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,32), -- } -- }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F080, -- name: "AMD AM29F080", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,16), -- } -- }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F040, -- name: "AMD AM29F040", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,8), -- } -- }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV040B, -- name: "AMD AM29LV040B", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,8), -- } -- }, { -- mfr_id: MANUFACTURER_ST, -- dev_id: M29W040B, -- name: "ST M29W040B", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,8), -- } -- }, { -- mfr_id: MANUFACTURER_MACRONIX, -- dev_id: MX29LV160T, -- name: "MXIC MX29LV160T", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,31), -+ .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */ -+ .dev_id = M29W160DT, -+ .name = "ST M29W160DT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,31), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_MACRONIX, -- dev_id: MX29LV160B, -- name: "MXIC MX29LV160B", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -+ .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */ -+ .dev_id = M29W160DB, -+ .name = "ST M29W160DB", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x08000,1), - ERASEINFO(0x10000,31) - } - }, { -- mfr_id: MANUFACTURER_MACRONIX, -- dev_id: MX29F016, -- name: "Macronix MX29F016", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,32), -- } -- }, { -- mfr_id: MANUFACTURER_MACRONIX, -- dev_id: MX29F004T, -- name: "Macronix MX29F004T", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,7), -+ .mfr_id = MANUFACTURER_ST, -+ .dev_id = M29W040B, -+ .name = "ST M29W040B", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,8), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVT160, -+ .name = "Toshiba TC58FVT160", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,31), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), -- ERASEINFO(0x04000,1), -+ ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_MACRONIX, -- dev_id: MX29F004B, -- name: "Macronix MX29F004B", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVB160, -+ .name = "Toshiba TC58FVB160", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x08000,1), -- ERASEINFO(0x10000,7), -+ ERASEINFO(0x10000,31) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVB321, -+ .name = "Toshiba TC58FVB321", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x02000,8), -+ ERASEINFO(0x10000,63) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVT321, -+ .name = "Toshiba TC58FVT321", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x10000,63), -+ ERASEINFO(0x02000,8) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVB641, -+ .name = "Toshiba TC58FVB641", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_8MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x02000,8), -+ ERASEINFO(0x10000,127) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVT641, -+ .name = "Toshiba TC58FVT641", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_8MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x10000,127), -+ ERASEINFO(0x02000,8) - } - }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST39LF512, -- name: "SST 39LF512", -- DevSize: SIZE_64KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,16), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST39LF010, -- name: "SST 39LF010", -- DevSize: SIZE_128KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,32), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST39LF020, -- name: "SST 39LF020", -- DevSize: SIZE_256KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,64), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST39LF040, -- name: "SST 39LF040", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,128), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST39SF010A, -- name: "SST 39SF010A", -- DevSize: SIZE_128KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,32), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST39SF020A, -- name: "SST 39SF020A", -- DevSize: SIZE_256KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,64), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST49LF030A, -- name: "SST 49LF030A", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,96), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST49LF040A, -- name: "SST 49LF040A", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,128), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST49LF080A, -- name: "SST 49LF080A", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,256), -+ .mfr_id = MANUFACTURER_WINBOND, -+ .dev_id = W49V002A, -+ .name = "Winbond W49V002A", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_256KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000, 3), -+ ERASEINFO(0x08000, 1), -+ ERASEINFO(0x02000, 2), -+ ERASEINFO(0x04000, 1), - } - } - }; -@@ -907,7 +1452,7 @@ - static int cfi_jedec_setup(struct cfi_private *p_cfi, int index); - - static int jedec_probe_chip(struct map_info *map, __u32 base, -- struct flchip *chips, struct cfi_private *cfi); -+ unsigned long *chip_map, struct cfi_private *cfi); - - struct mtd_info *jedec_probe(struct map_info *map); - -@@ -944,11 +1489,43 @@ - * this should be safe. - */ - cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); -+ /* FIXME - should have reset delay before continuing */ -+} - -+ -+static inline __u8 finfo_uaddr(const struct amd_flash_info *finfo, int device_type) -+{ -+ int uaddr_idx; -+ __u8 uaddr = MTD_UADDR_NOT_SUPPORTED; -+ -+ switch ( device_type ) { -+ case CFI_DEVICETYPE_X8: uaddr_idx = 0; break; -+ case CFI_DEVICETYPE_X16: uaddr_idx = 1; break; -+ case CFI_DEVICETYPE_X32: uaddr_idx = 2; break; -+ default: -+ printk(KERN_NOTICE "MTD: %s(): unknown device_type %d\n", -+ __func__, device_type); -+ goto uaddr_done; -+ } -+ -+ uaddr = finfo->uaddr[uaddr_idx]; -+ -+ if (uaddr != MTD_UADDR_NOT_SUPPORTED ) { -+ /* ASSERT("The unlock addresses for non-8-bit mode -+ are bollocks. We don't really need an array."); */ -+ uaddr = finfo->uaddr[0]; -+ } -+ -+ uaddr_done: -+ return uaddr; - } -+ -+ - static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) - { - int i,num_erase_regions; -+ unsigned long mask; -+ __u8 uaddr; - - printk("Found: %s\n",jedec_table[index].name); - -@@ -971,41 +1548,170 @@ - p_cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i]; - } - p_cfi->cmdset_priv = 0; -+ -+ /* This may be redundant for some cases, but it doesn't hurt */ -+ p_cfi->mfr = jedec_table[index].mfr_id; -+ p_cfi->id = jedec_table[index].dev_id; -+ -+ uaddr = finfo_uaddr(&jedec_table[index], p_cfi->device_type); -+ if ( uaddr == MTD_UADDR_NOT_SUPPORTED ) { -+ kfree( p_cfi->cfiq ); -+ return 0; -+ } -+ -+ /* Mask out address bits which are smaller than the device type */ -+ mask = ~(p_cfi->device_type-1); -+ p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 & mask; -+ p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 & mask; -+ - return 1; /* ok */ - } - --static int jedec_probe_chip(struct map_info *map, __u32 base, -- struct flchip *chips, struct cfi_private *cfi) -+ -+/* -+ * There is a BIG problem properly ID'ing the JEDEC devic and guaranteeing -+ * the mapped address, unlock addresses, and proper chip ID. This function -+ * attempts to minimize errors. It is doubtfull that this probe will ever -+ * be perfect - consequently there should be some module parameters that -+ * could be manually specified to force the chip info. -+ */ -+static inline int jedec_match( __u32 base, -+ struct map_info *map, -+ struct cfi_private *cfi, -+ const struct amd_flash_info *finfo ) - { -- int i; -- int unlockpass = 0; -+ int rc = 0; /* failure until all tests pass */ -+ u32 mfr, id; -+ __u8 uaddr; -+ unsigned long mask; - -- if (!cfi->numchips) { -+ /* -+ * The IDs must match. For X16 and X32 devices operating in -+ * a lower width ( X8 or X16 ), the device ID's are usually just -+ * the lower byte(s) of the larger device ID for wider mode. If -+ * a part is found that doesn't fit this assumption (device id for -+ * smaller width mode is completely unrealated to full-width mode) -+ * then the jedec_table[] will have to be augmented with the IDs -+ * for different widths. -+ */ - switch (cfi->device_type) { - case CFI_DEVICETYPE_X8: -- cfi->addr_unlock1 = 0x555; -- cfi->addr_unlock2 = 0x2aa; -+ mfr = (__u8)finfo->mfr_id; -+ id = (__u8)finfo->dev_id; - break; - case CFI_DEVICETYPE_X16: -- cfi->addr_unlock1 = 0xaaa; -- if (map->buswidth == cfi->interleave) { -- /* X16 chip(s) in X8 mode */ -- cfi->addr_unlock2 = 0x555; -- } else { -- cfi->addr_unlock2 = 0x554; -- } -+ mfr = (__u16)finfo->mfr_id; -+ id = (__u16)finfo->dev_id; - break; - case CFI_DEVICETYPE_X32: -- cfi->addr_unlock1 = 0x1555; -- cfi->addr_unlock2 = 0xaaa; -+ mfr = (__u16)finfo->mfr_id; -+ id = (__u32)finfo->dev_id; - break; - default: -- printk(KERN_NOTICE "Eep. Unknown jedec_probe device type %d\n", cfi->device_type); -- return 0; -+ printk(KERN_WARNING -+ "MTD %s(): Unsupported device type %d\n", -+ __func__, cfi->device_type); -+ goto match_done; -+ } -+ if ( cfi->mfr != mfr || cfi->id != id ) { -+ goto match_done; -+ } -+ -+ /* the part size must fit in the memory window */ -+ DEBUG( MTD_DEBUG_LEVEL3, -+ "MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n", -+ __func__, base, 1 << finfo->DevSize, base + (1 << finfo->DevSize) ); -+ if ( base + cfi->interleave * ( 1 << finfo->DevSize ) > map->size ) { -+ DEBUG( MTD_DEBUG_LEVEL3, -+ "MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n", -+ __func__, finfo->mfr_id, finfo->dev_id, -+ 1 << finfo->DevSize ); -+ goto match_done; -+ } -+ -+ uaddr = finfo_uaddr(finfo, cfi->device_type); -+ if ( uaddr == MTD_UADDR_NOT_SUPPORTED ) { -+ goto match_done; -+ } -+ -+ mask = ~(cfi->device_type-1); -+ -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n", -+ __func__, cfi->addr_unlock1, cfi->addr_unlock2 ); -+ if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr -+ && ( (unlock_addrs[uaddr].addr1 & mask) != cfi->addr_unlock1 || -+ (unlock_addrs[uaddr].addr2 & mask) != cfi->addr_unlock2 ) ) { -+ DEBUG( MTD_DEBUG_LEVEL3, -+ "MTD %s(): 0x%.4x 0x%.4x did not match\n", -+ __func__, -+ unlock_addrs[uaddr].addr1 & mask, -+ unlock_addrs[uaddr].addr2 & mask); -+ goto match_done; - } -+ -+ /* -+ * Make sure the ID's dissappear when the device is taken out of -+ * ID mode. The only time this should fail when it should succeed -+ * is when the ID's are written as data to the same -+ * addresses. For this rare and unfortunate case the chip -+ * cannot be probed correctly. -+ * FIXME - write a driver that takes all of the chip info as -+ * module parameters, doesn't probe but forces a load. -+ */ -+ DEBUG( MTD_DEBUG_LEVEL3, -+ "MTD %s(): check ID's disappear when not in ID mode\n", -+ __func__ ); -+ jedec_reset( base, map, cfi ); -+ mfr = jedec_read_mfr( map, base, cfi ); -+ id = jedec_read_id( map, base, cfi ); -+ if ( mfr == cfi->mfr && id == cfi->id ) { -+ DEBUG( MTD_DEBUG_LEVEL3, -+ "MTD %s(): ID 0x%.2x:0x%.2x did not change after reset:\n" -+ "You might need to manually specify JEDEC parameters.\n", -+ __func__, cfi->mfr, cfi->id ); -+ goto match_done; -+ } -+ -+ /* all tests passed - mark as success */ -+ rc = 1; -+ -+ /* -+ * Put the device back in ID mode - only need to do this if we -+ * were truly frobbing a real device. -+ */ -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): return to ID mode\n", __func__ ); -+ if(cfi->addr_unlock1) { -+ cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL); - } -+ cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ /* FIXME - should have a delay before continuing */ -+ -+ match_done: -+ return rc; -+} -+ -+ -+static int jedec_probe_chip(struct map_info *map, __u32 base, -+ unsigned long *chip_map, struct cfi_private *cfi) -+{ -+ int i; -+ enum uaddr uaddr_idx = MTD_UADDR_NOT_SUPPORTED; - - retry: -+ if (!cfi->numchips) { -+ unsigned long mask = ~(cfi->device_type-1); -+ -+ uaddr_idx++; -+ -+ if (MTD_UADDR_UNNECESSARY == uaddr_idx) -+ return 0; -+ -+ /* Mask out address bits which are smaller than the device type */ -+ cfi->addr_unlock1 = unlock_addrs[uaddr_idx].addr1 & mask; -+ cfi->addr_unlock2 = unlock_addrs[uaddr_idx].addr2 & mask; -+ } -+ - /* Make certain we aren't probing past the end of map */ - if (base >= map->size) { - printk(KERN_NOTICE -@@ -1038,6 +1744,7 @@ - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL); - } - cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ /* FIXME - should have a delay before continuing */ - - if (!cfi->numchips) { - /* This is the first time we're called. Set up the CFI -@@ -1045,26 +1752,21 @@ - - cfi->mfr = jedec_read_mfr(map, base, cfi); - cfi->id = jedec_read_id(map, base, cfi); -- printk(KERN_INFO "Search for id:(%02x %02x) interleave(%d) type(%d)\n", -+ DEBUG(MTD_DEBUG_LEVEL3, -+ "Search for id:(%02x %02x) interleave(%d) type(%d)\n", - cfi->mfr, cfi->id, cfi->interleave, cfi->device_type); - for (i=0; imfr == jedec_table[i].mfr_id && -- cfi->id == jedec_table[i].dev_id) { -+ if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) { -+ DEBUG( MTD_DEBUG_LEVEL3, -+ "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n", -+ __func__, cfi->mfr, cfi->id, -+ cfi->addr_unlock1, cfi->addr_unlock2 ); - if (!cfi_jedec_setup(cfi, i)) - return 0; - goto ok_out; - } - } -- switch(unlockpass++) { -- case 0: -- cfi->addr_unlock1 |= cfi->addr_unlock1 << 4; -- cfi->addr_unlock2 |= cfi->addr_unlock2 << 4; -- goto retry; -- case 1: -- cfi->addr_unlock1 = cfi->addr_unlock2 = 0; - goto retry; -- } -- return 0; - } else { - __u16 mfr; - __u16 id; -@@ -1081,21 +1783,24 @@ - } - } - -- /* Check each previous chip to see if it's an alias */ -- for (i=0; inumchips; i++) { -- /* This chip should be in read mode if it's one -- we've already touched. */ -- if (jedec_read_mfr(map, chips[i].start, cfi) == cfi->mfr && -- jedec_read_id(map, chips[i].start, cfi) == cfi->id) { -+ /* Check each previous chip locations to see if it's an alias */ -+ for (i=0; i < (base >> cfi->chipshift); i++) { -+ unsigned long start; -+ if(!test_bit(i, chip_map)) { -+ continue; /* Skip location; no valid chip at this address */ -+ } -+ start = i << cfi->chipshift; -+ if (jedec_read_mfr(map, start, cfi) == cfi->mfr && -+ jedec_read_id(map, start, cfi) == cfi->id) { - /* Eep. This chip also looks like it's in autoselect mode. - Is it an alias for the new one? */ -- jedec_reset(chips[i].start, map, cfi); -+ jedec_reset(start, map, cfi); - - /* If the device IDs go away, it's an alias */ - if (jedec_read_mfr(map, base, cfi) != cfi->mfr || - jedec_read_id(map, base, cfi) != cfi->id) { - printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", -- map->name, base, chips[i].start); -+ map->name, base, start); - return 0; - } - -@@ -1107,7 +1812,7 @@ - if (jedec_read_mfr(map, base, cfi) == cfi->mfr && - jedec_read_id(map, base, cfi) == cfi->id) { - printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", -- map->name, base, chips[i].start); -+ map->name, base, start); - return 0; - } - } -@@ -1115,13 +1820,7 @@ - - /* OK, if we got to here, then none of the previous chips appear to - be aliases for the current one. */ -- if (cfi->numchips == MAX_CFI_CHIPS) { -- printk(KERN_WARNING"%s: Too many flash chips detected. Increase MAX_CFI_CHIPS from %d.\n", map->name, MAX_CFI_CHIPS); -- /* Doesn't matter about resetting it to Read Mode - we're not going to talk to it anyway */ -- return -1; -- } -- chips[cfi->numchips].start = base; -- chips[cfi->numchips].state = FL_READY; -+ set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */ - cfi->numchips++; - - ok_out: -@@ -1136,8 +1835,8 @@ - } - - static struct chip_probe jedec_chip_probe = { -- name: "JEDEC", -- probe_chip: jedec_probe_chip -+ .name = "JEDEC", -+ .probe_chip = jedec_probe_chip - }; - - struct mtd_info *jedec_probe(struct map_info *map) -@@ -1150,9 +1849,9 @@ - } - - static struct mtd_chip_driver jedec_chipdrv = { -- probe: jedec_probe, -- name: "jedec_probe", -- module: THIS_MODULE -+ .probe = jedec_probe, -+ .name = "jedec_probe", -+ .module = THIS_MODULE - }; - - int __init jedec_probe_init(void) -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/map_absent.c linux/drivers/mtd/chips/map_absent.c ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/map_absent.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/chips/map_absent.c 2004-11-17 18:17:58.963325472 +0100 -@@ -1,7 +1,7 @@ - /* - * Common code to handle absent "placeholder" devices - * Copyright 2001 Resilience Corporation -- * $Id$ -+ * $Id$ - * - * This map driver is used to allocate "placeholder" MTD - * devices on systems that have socketed/removable media. -@@ -23,9 +23,10 @@ - #include - #include - #include -- -+#include -+#include - #include -- -+#include - - static int map_absent_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); - static int map_absent_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -@@ -36,10 +37,10 @@ - - - static struct mtd_chip_driver map_absent_chipdrv = { -- probe: map_absent_probe, -- destroy: map_absent_destroy, -- name: "map_absent", -- module: THIS_MODULE -+ .probe = map_absent_probe, -+ .destroy = map_absent_destroy, -+ .name = "map_absent", -+ .module = THIS_MODULE - }; - - static struct mtd_info *map_absent_probe(struct map_info *map) -@@ -65,7 +66,7 @@ - mtd->flags = 0; - mtd->erasesize = PAGE_SIZE; - -- MOD_INC_USE_COUNT; -+ __module_get(THIS_MODULE); - return mtd; - } - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/map_ram.c linux/drivers/mtd/chips/map_ram.c ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/map_ram.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/chips/map_ram.c 2004-11-17 18:17:58.965325168 +0100 -@@ -1,7 +1,7 @@ - /* - * Common code to handle map devices which are simple RAM - * (C) 2000 Red Hat. GPL'd. -- * $Id$ -+ * $Id$ - */ - - #include -@@ -11,8 +11,10 @@ - #include - #include - #include -- -+#include -+#include - #include -+#include - - - static int mapram_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); -@@ -23,9 +25,9 @@ - - - static struct mtd_chip_driver mapram_chipdrv = { -- probe: map_ram_probe, -- name: "map_ram", -- module: THIS_MODULE -+ .probe = map_ram_probe, -+ .name = "map_ram", -+ .module = THIS_MODULE - }; - - static struct mtd_info *map_ram_probe(struct map_info *map) -@@ -34,21 +36,21 @@ - - /* Check the first byte is RAM */ - #if 0 -- map->write8(map, 0x55, 0); -- if (map->read8(map, 0) != 0x55) -+ map_write8(map, 0x55, 0); -+ if (map_read8(map, 0) != 0x55) - return NULL; - -- map->write8(map, 0xAA, 0); -- if (map->read8(map, 0) != 0xAA) -+ map_write8(map, 0xAA, 0); -+ if (map_read8(map, 0) != 0xAA) - return NULL; - - /* Check the last byte is RAM */ -- map->write8(map, 0x55, map->size-1); -- if (map->read8(map, map->size-1) != 0x55) -+ map_write8(map, 0x55, map->size-1); -+ if (map_read8(map, map->size-1) != 0x55) - return NULL; - -- map->write8(map, 0xAA, map->size-1); -- if (map->read8(map, map->size-1) != 0xAA) -+ map_write8(map, 0xAA, map->size-1); -+ if (map_read8(map, map->size-1) != 0xAA) - return NULL; - #endif - /* OK. It seems to be RAM. */ -@@ -74,7 +76,7 @@ - while(mtd->size & (mtd->erasesize - 1)) - mtd->erasesize >>= 1; - -- MOD_INC_USE_COUNT; -+ __module_get(THIS_MODULE); - return mtd; - } - -@@ -83,7 +85,7 @@ - { - struct map_info *map = (struct map_info *)mtd->priv; - -- map->copy_from(map, buf, from, len); -+ map_copy_from(map, buf, from, len); - *retlen = len; - return 0; - } -@@ -92,7 +94,7 @@ - { - struct map_info *map = (struct map_info *)mtd->priv; - -- map->copy_to(map, to, buf, len); -+ map_copy_to(map, to, buf, len); - *retlen = len; - return 0; - } -@@ -105,7 +107,7 @@ - unsigned long i; - - for (i=0; ilen; i++) -- map->write8(map, 0xFF, instr->addr + i); -+ map_write8(map, 0xFF, instr->addr + i); - - if (instr->callback) - instr->callback(instr); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/map_rom.c linux/drivers/mtd/chips/map_rom.c ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/map_rom.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/chips/map_rom.c 2004-11-17 18:17:58.966325016 +0100 -@@ -1,7 +1,7 @@ - /* - * Common code to handle map devices which are simple ROM - * (C) 2000 Red Hat. GPL'd. -- * $Id$ -+ * $Id$ - */ - - #include -@@ -12,8 +12,10 @@ - #include - #include - #include -- -+#include -+#include - #include -+#include - - static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); - static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -@@ -21,9 +23,9 @@ - struct mtd_info *map_rom_probe(struct map_info *map); - - static struct mtd_chip_driver maprom_chipdrv = { -- probe: map_rom_probe, -- name: "map_rom", -- module: THIS_MODULE -+ .probe = map_rom_probe, -+ .name = "map_rom", -+ .module = THIS_MODULE - }; - - struct mtd_info *map_rom_probe(struct map_info *map) -@@ -49,7 +51,7 @@ - while(mtd->size & (mtd->erasesize - 1)) - mtd->erasesize >>= 1; - -- MOD_INC_USE_COUNT; -+ __module_get(THIS_MODULE); - return mtd; - } - -@@ -58,7 +60,7 @@ - { - struct map_info *map = (struct map_info *)mtd->priv; - -- map->copy_from(map, buf, from, len); -+ map_copy_from(map, buf, from, len); - *retlen = len; - return 0; - } -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/chips/sharp.c linux/drivers/mtd/chips/sharp.c ---- linux-mips-2.4.24-pre2/drivers/mtd/chips/sharp.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/chips/sharp.c 2004-11-17 18:17:58.968324712 +0100 -@@ -4,7 +4,7 @@ - * Copyright 2000,2001 David A. Schleef - * 2000,2001 Lineo, Inc. - * -- * $Id$ -+ * $Id$ - * - * Devices supported: - * LH28F016SCT Symmetrical block flash memory, 2Mx8 -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -98,10 +99,10 @@ - static void sharp_destroy(struct mtd_info *mtd); - - static struct mtd_chip_driver sharp_chipdrv = { -- probe: sharp_probe, -- destroy: sharp_destroy, -- name: "sharp", -- module: THIS_MODULE -+ .probe = sharp_probe, -+ .destroy = sharp_destroy, -+ .name = "sharp", -+ .module = THIS_MODULE - }; - - -@@ -116,8 +117,10 @@ - return NULL; - - sharp = kmalloc(sizeof(*sharp), GFP_KERNEL); -- if(!sharp) -+ if(!sharp) { -+ kfree(mtd); - return NULL; -+ } - - memset(mtd, 0, sizeof(*mtd)); - -@@ -163,12 +166,12 @@ - u32 read0, read4; - int width = 4; - -- tmp = map->read32(map, base+0); -+ tmp = map_read32(map, base+0); - -- map->write32(map, CMD_READ_ID, base+0); -+ map_write32(map, CMD_READ_ID, base+0); - -- read0=map->read32(map, base+0); -- read4=map->read32(map, base+4); -+ read0=map_read32(map, base+0); -+ read4=map_read32(map, base+4); - if(read0 == 0x89898989){ - printk("Looks like sharp flash\n"); - switch(read4){ -@@ -196,10 +199,10 @@ - printk("Sort-of looks like sharp flash, 0x%08x 0x%08x\n", - read0,read4); - } -- }else if((map->read32(map, base+0) == CMD_READ_ID)){ -+ }else if((map_read32(map, base+0) == CMD_READ_ID)){ - /* RAM, probably */ - printk("Looks like RAM\n"); -- map->write32(map, tmp, base+0); -+ map_write32(map, tmp, base+0); - }else{ - printk("Doesn't look like sharp flash, 0x%08x 0x%08x\n", - read0,read4); -@@ -221,10 +224,10 @@ - - switch(chip->state){ - case FL_READY: -- map->write32(map,CMD_READ_STATUS,adr); -+ map_write32(map,CMD_READ_STATUS,adr); - chip->state = FL_STATUS; - case FL_STATUS: -- status = map->read32(map,adr); -+ status = map_read32(map,adr); - //printk("status=%08x\n",status); - - udelay(100); -@@ -252,7 +255,7 @@ - goto retry; - } - -- map->write32(map,CMD_RESET, adr); -+ map_write32(map,CMD_RESET, adr); - - chip->state = FL_READY; - -@@ -293,7 +296,7 @@ - if(ret<0) - break; - -- map->copy_from(map,buf,ofs,thislen); -+ map_copy_from(map,buf,ofs,thislen); - - sharp_release(&sharp->chips[chipnum]); - -@@ -354,17 +357,17 @@ - ret = sharp_wait(map,chip); - - for(try=0;try<10;try++){ -- map->write32(map,CMD_BYTE_WRITE,adr); -+ map_write32(map,CMD_BYTE_WRITE,adr); - /* cpu_to_le32 -> hack to fix the writel be->le conversion */ -- map->write32(map,cpu_to_le32(datum),adr); -+ map_write32(map,cpu_to_le32(datum),adr); - - chip->state = FL_WRITING; - - timeo = jiffies + (HZ/2); - -- map->write32(map,CMD_READ_STATUS,adr); -+ map_write32(map,CMD_READ_STATUS,adr); - for(i=0;i<100;i++){ -- status = map->read32(map,adr); -+ status = map_read32(map,adr); - if((status & SR_READY)==SR_READY) - break; - } -@@ -377,9 +380,9 @@ - - printk("sharp: error writing byte at addr=%08lx status=%08x\n",adr,status); - -- map->write32(map,CMD_CLEAR_STATUS,adr); -+ map_write32(map,CMD_CLEAR_STATUS,adr); - } -- map->write32(map,CMD_RESET,adr); -+ map_write32(map,CMD_RESET,adr); - chip->state = FL_READY; - - wake_up(&chip->wq); -@@ -436,14 +439,14 @@ - int status; - DECLARE_WAITQUEUE(wait, current); - -- map->write32(map,CMD_READ_STATUS,adr); -- status = map->read32(map,adr); -+ map_write32(map,CMD_READ_STATUS,adr); -+ status = map_read32(map,adr); - - timeo = jiffies + HZ; - - while(time_before(jiffies, timeo)){ -- map->write32(map,CMD_READ_STATUS,adr); -- status = map->read32(map,adr); -+ map_write32(map,CMD_READ_STATUS,adr); -+ status = map_read32(map,adr); - if((status & SR_READY)==SR_READY){ - ret = 0; - goto out; -@@ -485,26 +488,26 @@ - sharp_unlock_oneblock(map,chip,adr); - #endif - -- map->write32(map,CMD_BLOCK_ERASE_1,adr); -- map->write32(map,CMD_BLOCK_ERASE_2,adr); -+ map_write32(map,CMD_BLOCK_ERASE_1,adr); -+ map_write32(map,CMD_BLOCK_ERASE_2,adr); - - chip->state = FL_ERASING; - - ret = sharp_do_wait_for_ready(map,chip,adr); - if(ret<0)return ret; - -- map->write32(map,CMD_READ_STATUS,adr); -- status = map->read32(map,adr); -+ map_write32(map,CMD_READ_STATUS,adr); -+ status = map_read32(map,adr); - - if(!(status&SR_ERRORS)){ -- map->write32(map,CMD_RESET,adr); -+ map_write32(map,CMD_RESET,adr); - chip->state = FL_READY; - //spin_unlock_bh(chip->mutex); - return 0; - } - - printk("sharp: error erasing block at addr=%08lx status=%08x\n",adr,status); -- map->write32(map,CMD_CLEAR_STATUS,adr); -+ map_write32(map,CMD_CLEAR_STATUS,adr); - - //spin_unlock_bh(chip->mutex); - -@@ -518,17 +521,17 @@ - int i; - int status; - -- map->write32(map,CMD_CLEAR_BLOCK_LOCKS_1,adr); -- map->write32(map,CMD_CLEAR_BLOCK_LOCKS_2,adr); -+ map_write32(map,CMD_CLEAR_BLOCK_LOCKS_1,adr); -+ map_write32(map,CMD_CLEAR_BLOCK_LOCKS_2,adr); - - udelay(100); - -- status = map->read32(map,adr); -+ status = map_read32(map,adr); - printk("status=%08x\n",status); - - for(i=0;i<1000;i++){ -- //map->write32(map,CMD_READ_STATUS,adr); -- status = map->read32(map,adr); -+ //map_write32(map,CMD_READ_STATUS,adr); -+ status = map_read32(map,adr); - if((status & SR_READY)==SR_READY) - break; - udelay(100); -@@ -538,13 +541,13 @@ - } - - if(!(status&SR_ERRORS)){ -- map->write32(map,CMD_RESET,adr); -+ map_write32(map,CMD_RESET,adr); - chip->state = FL_READY; - return; - } - - printk("sharp: error unlocking block at addr=%08lx status=%08x\n",adr,status); -- map->write32(map,CMD_CLEAR_STATUS,adr); -+ map_write32(map,CMD_CLEAR_STATUS,adr); - } - #endif - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/cmdlinepart.c linux/drivers/mtd/cmdlinepart.c ---- linux-mips-2.4.24-pre2/drivers/mtd/cmdlinepart.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/cmdlinepart.c 2004-11-17 18:17:58.829345840 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Read flash partition table from command line - * -@@ -28,7 +28,7 @@ - - #include - #include --#include -+#include - #include - - /* error message prefix */ -@@ -178,8 +178,7 @@ - parts[this_part].mask_flags = mask_flags; - if (name) - { -- strncpy(extra_mem, name, name_len); -- extra_mem[name_len] = 0; -+ strlcpy(extra_mem, name, name_len + 1); - } - else - { -@@ -258,8 +257,7 @@ - this_mtd->parts = parts; - this_mtd->num_parts = num_parts; - this_mtd->mtd_id = (char*)(this_mtd + 1); -- strncpy(this_mtd->mtd_id, mtd_id, mtd_id_len); -- this_mtd->mtd_id[mtd_id_len] = 0; -+ strlcpy(this_mtd->mtd_id, mtd_id, mtd_id_len + 1); - - /* link into chain */ - this_mtd->next = partitions; -@@ -291,13 +289,14 @@ - * information. It returns partitions for the requested mtd device, or - * the first one in the chain if a NULL mtd_id is passed in. - */ --int parse_cmdline_partitions(struct mtd_info *master, -+static int parse_cmdline_partitions(struct mtd_info *master, - struct mtd_partition **pparts, -- const char *mtd_id) -+ unsigned long origin) - { - unsigned long offset; - int i; - struct cmdline_mtd_partition *part; -+ char *mtd_id = master->name; - - if(!cmdline) - return -EINVAL; -@@ -349,7 +348,25 @@ - - __setup("mtdparts=", mtdpart_setup); - --EXPORT_SYMBOL(parse_cmdline_partitions); -+static struct mtd_part_parser cmdline_parser = { -+ .owner = THIS_MODULE, -+ .parse_fn = parse_cmdline_partitions, -+ .name = "cmdlinepart", -+}; -+ -+static int __init cmdline_parser_init(void) -+{ -+ return register_mtd_parser(&cmdline_parser); -+} -+ -+static void __exit cmdline_parser_exit(void) -+{ -+ deregister_mtd_parser(&cmdline_parser); -+} -+ -+module_init(cmdline_parser_init); -+module_exit(cmdline_parser_exit); -+ - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Marius Groeger "); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/Config.in linux/drivers/mtd/devices/Config.in ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/Config.in 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/devices/Config.in 2004-11-17 18:17:58.972324104 +0100 -@@ -1,6 +1,6 @@ --# drivers/mtd/maps/Config.in -+# drivers/mtd/devices/Config.in - --# $Id$ -+# $Id$ - - mainmenu_option next_comment - -@@ -28,13 +28,13 @@ - dep_tristate ' MTD emulation using block device' CONFIG_MTD_BLKMTD $CONFIG_MTD - - comment 'Disk-On-Chip Device Drivers' -- dep_tristate ' M-Systems Disk-On-Chip 1000' CONFIG_MTD_DOC1000 $CONFIG_MTD - dep_tristate ' M-Systems Disk-On-Chip 2000 and Millennium' CONFIG_MTD_DOC2000 $CONFIG_MTD - dep_tristate ' M-Systems Disk-On-Chip Millennium-only alternative driver (see help)' CONFIG_MTD_DOC2001 $CONFIG_MTD -- if [ "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" ]; then -+ dep_tristate ' M-Systems Disk-On-Chip Millennium Plus driver (see help)' CONFIG_MTD_DOC2001PLUS $CONFIG_MTD -+ if [ "$CONFIG_MTD_DOC2001PLUS" = "y" -o "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" ]; then - define_bool CONFIG_MTD_DOCPROBE y - else -- if [ "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" ]; then -+ if [ "$CONFIG_MTD_DOC2001PLUS" = "m" -o "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" ]; then - define_bool CONFIG_MTD_DOCPROBE m - else - define_bool CONFIG_MTD_DOCPROBE n -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/Makefile linux/drivers/mtd/devices/Makefile ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/Makefile 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/devices/Makefile 2004-11-17 18:17:58.974323800 +0100 -@@ -1,9 +1,12 @@ - # - # linux/drivers/devices/Makefile - # --# $Id$ -+# $Id$ - -+ifeq ($(PATCHLEVEL),4) - O_TARGET := devlink.o -+export-objs := docecc.o -+endif - - # *** BIG UGLY NOTE *** - # -@@ -12,15 +15,16 @@ - # here where previously there was none. We now have to ensure that - # doc200[01].o are linked before docprobe.o - --obj-$(CONFIG_MTD_DOC1000) += doc1000.o - obj-$(CONFIG_MTD_DOC2000) += doc2000.o - obj-$(CONFIG_MTD_DOC2001) += doc2001.o -+obj-$(CONFIG_MTD_DOC2001PLUS) += doc2001plus.o - obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o docecc.o - obj-$(CONFIG_MTD_SLRAM) += slram.o -+obj-$(CONFIG_MTD_PHRAM) += phram.o - obj-$(CONFIG_MTD_PMC551) += pmc551.o - obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o - obj-$(CONFIG_MTD_MTDRAM) += mtdram.o - obj-$(CONFIG_MTD_LART) += lart.o - obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o - --include $(TOPDIR)/Rules.make -+-include $(TOPDIR)/Rules.make -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/blkmtd-25.c linux/drivers/mtd/devices/blkmtd-25.c ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/blkmtd-25.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/devices/blkmtd-25.c 2004-11-17 18:17:58.000000000 +0100 -@@ -0,0 +1,827 @@ -+/* -+ * $Id$ -+ * -+ * blkmtd.c - use a block device as a fake MTD -+ * -+ * Author: Simon Evans -+ * -+ * Copyright (C) 2001,2002 Simon Evans -+ * -+ * Licence: GPL -+ * -+ * How it works: -+ * The driver uses raw/io to read/write the device and the page -+ * cache to cache access. Writes update the page cache with the -+ * new data and mark it dirty and add the page into a BIO which -+ * is then written out. -+ * -+ * It can be loaded Read-Only to prevent erases and writes to the -+ * medium. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#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) -+#define warn(format, arg...) printk(KERN_WARNING "blkmtd: " format "\n" , ## arg) -+#define crit(format, arg...) printk(KERN_CRIT "blkmtd: " format "\n" , ## arg) -+ -+ -+/* Default erase size in K, always make it a multiple of PAGE_SIZE */ -+#define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10) /* 128KiB */ -+#define VERSION "$Revision$" -+ -+/* Info for the block device */ -+struct blkmtd_dev { -+ struct list_head list; -+ struct block_device *blkdev; -+ struct mtd_info mtd_info; -+ struct semaphore wrbuf_mutex; -+}; -+ -+ -+/* Static info about the MTD, used in cleanup_module */ -+static LIST_HEAD(blkmtd_device_list); -+ -+ -+static void blkmtd_sync(struct mtd_info *mtd); -+ -+#define MAX_DEVICES 4 -+ -+/* Module parameters passed by insmod/modprobe */ -+char *device[MAX_DEVICES]; /* the block device to use */ -+int erasesz[MAX_DEVICES]; /* optional default erase size */ -+int ro[MAX_DEVICES]; /* optional read only flag */ -+int sync; -+ -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Simon Evans "); -+MODULE_DESCRIPTION("Emulate an MTD using a block device"); -+MODULE_PARM(device, "1-4s"); -+MODULE_PARM_DESC(device, "block device to use"); -+MODULE_PARM(erasesz, "1-4i"); -+MODULE_PARM_DESC(erasesz, "optional erase size to use in KiB. eg 4=4KiB."); -+MODULE_PARM(ro, "1-4i"); -+MODULE_PARM_DESC(ro, "1=Read only, writes and erases cause errors"); -+MODULE_PARM(sync, "i"); -+MODULE_PARM_DESC(sync, "1=Synchronous writes"); -+ -+ -+/* completion handler for BIO reads */ -+static int bi_read_complete(struct bio *bio, unsigned int bytes_done, int error) -+{ -+ if (bio->bi_size) -+ return 1; -+ -+ complete((struct completion*)bio->bi_private); -+ return 0; -+} -+ -+ -+/* completion handler for BIO writes */ -+static int bi_write_complete(struct bio *bio, unsigned int bytes_done, int error) -+{ -+ const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); -+ struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; -+ -+ if (bio->bi_size) -+ return 1; -+ -+ if(!uptodate) -+ err("bi_write_complete: not uptodate\n"); -+ -+ do { -+ struct page *page = bvec->bv_page; -+ DEBUG(3, "Cleaning up page %ld\n", page->index); -+ if (--bvec >= bio->bi_io_vec) -+ prefetchw(&bvec->bv_page->flags); -+ -+ if (uptodate) { -+ SetPageUptodate(page); -+ } else { -+ ClearPageUptodate(page); -+ SetPageError(page); -+ } -+ ClearPageDirty(page); -+ unlock_page(page); -+ page_cache_release(page); -+ } while (bvec >= bio->bi_io_vec); -+ -+ complete((struct completion*)bio->bi_private); -+ return 0; -+} -+ -+ -+/* read one page from the block device */ -+static int blkmtd_readpage(struct blkmtd_dev *dev, struct page *page) -+{ -+ struct bio *bio; -+ struct completion event; -+ int err = -ENOMEM; -+ -+ if(PageUptodate(page)) { -+ DEBUG(2, "blkmtd: readpage page %ld is already upto date\n", page->index); -+ unlock_page(page); -+ return 0; -+ } -+ -+ ClearPageUptodate(page); -+ ClearPageError(page); -+ -+ bio = bio_alloc(GFP_KERNEL, 1); -+ if(bio) { -+ init_completion(&event); -+ bio->bi_bdev = dev->blkdev; -+ bio->bi_sector = page->index << (PAGE_SHIFT-9); -+ bio->bi_private = &event; -+ bio->bi_end_io = bi_read_complete; -+ if(bio_add_page(bio, page, PAGE_SIZE, 0) == PAGE_SIZE) { -+ submit_bio(READ, bio); -+ blk_run_queues(); -+ wait_for_completion(&event); -+ err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO; -+ bio_put(bio); -+ } -+ } -+ -+ if(err) -+ SetPageError(page); -+ else -+ SetPageUptodate(page); -+ flush_dcache_page(page); -+ unlock_page(page); -+ return err; -+} -+ -+ -+/* write out the current BIO and wait for it to finish */ -+static int blkmtd_write_out(struct bio *bio) -+{ -+ struct completion event; -+ int err; -+ -+ if(!bio->bi_vcnt) { -+ bio_put(bio); -+ return 0; -+ } -+ -+ init_completion(&event); -+ bio->bi_private = &event; -+ bio->bi_end_io = bi_write_complete; -+ submit_bio(WRITE, bio); -+ blk_run_queues(); -+ wait_for_completion(&event); -+ DEBUG(3, "submit_bio completed, bi_vcnt = %d\n", bio->bi_vcnt); -+ err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO; -+ bio_put(bio); -+ return err; -+} -+ -+ -+/** -+ * blkmtd_add_page - add a page to the current BIO -+ * @bio: bio to add to (NULL to alloc initial bio) -+ * @blkdev: block device -+ * @page: page to add -+ * @pagecnt: pages left to add -+ * -+ * Adds a page to the current bio, allocating it if necessary. If it cannot be -+ * added, the current bio is written out and a new one is allocated. Returns -+ * the new bio to add or NULL on error -+ */ -+static struct bio *blkmtd_add_page(struct bio *bio, struct block_device *blkdev, -+ struct page *page, int pagecnt) -+{ -+ -+ retry: -+ if(!bio) { -+ bio = bio_alloc(GFP_KERNEL, pagecnt); -+ if(!bio) -+ return NULL; -+ bio->bi_sector = page->index << (PAGE_SHIFT-9); -+ bio->bi_bdev = blkdev; -+ } -+ -+ if(bio_add_page(bio, page, PAGE_SIZE, 0) != PAGE_SIZE) { -+ blkmtd_write_out(bio); -+ bio = NULL; -+ goto retry; -+ } -+ return bio; -+} -+ -+ -+/** -+ * write_pages - write block of data to device via the page cache -+ * @dev: device to write to -+ * @buf: data source or NULL if erase (output is set to 0xff) -+ * @to: offset into output device -+ * @len: amount to data to write -+ * @retlen: amount of data written -+ * -+ * Grab pages from the page cache and fill them with the source data. -+ * Non page aligned start and end result in a readin of the page and -+ * part of the page being modified. Pages are added to the bio and then written -+ * out. -+ */ -+static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to, -+ size_t len, size_t *retlen) -+{ -+ int pagenr, offset; -+ size_t start_len = 0, end_len; -+ int pagecnt = 0; -+ int err = 0; -+ struct bio *bio = NULL; -+ size_t thislen = 0; -+ -+ pagenr = to >> PAGE_SHIFT; -+ offset = to & ~PAGE_MASK; -+ -+ DEBUG(2, "blkmtd: write_pages: buf = %p to = %ld len = %d pagenr = %d offset = %d\n", -+ buf, (long)to, len, pagenr, offset); -+ -+ /* see if we have to do a partial write at the start */ -+ if(offset) { -+ start_len = ((offset + len) > PAGE_SIZE) ? PAGE_SIZE - offset : len; -+ len -= start_len; -+ } -+ -+ /* calculate the length of the other two regions */ -+ end_len = len & ~PAGE_MASK; -+ len -= end_len; -+ -+ if(start_len) -+ pagecnt++; -+ -+ if(len) -+ pagecnt += len >> PAGE_SHIFT; -+ -+ if(end_len) -+ pagecnt++; -+ -+ down(&dev->wrbuf_mutex); -+ -+ DEBUG(3, "blkmtd: write: start_len = %d len = %d end_len = %d pagecnt = %d\n", -+ start_len, len, end_len, pagecnt); -+ -+ if(start_len) { -+ /* do partial start region */ -+ struct page *page; -+ -+ DEBUG(3, "blkmtd: write: doing partial start, page = %d len = %d offset = %d\n", -+ pagenr, start_len, offset); -+ -+ BUG_ON(!buf); -+ page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev); -+ lock_page(page); -+ if(PageDirty(page)) { -+ err("to = %lld start_len = %d len = %d end_len = %d pagenr = %d\n", -+ to, start_len, len, end_len, pagenr); -+ BUG(); -+ } -+ memcpy(page_address(page)+offset, buf, start_len); -+ SetPageDirty(page); -+ SetPageUptodate(page); -+ buf += start_len; -+ thislen = start_len; -+ bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt); -+ if(!bio) { -+ err = -ENOMEM; -+ err("bio_add_page failed\n"); -+ goto write_err; -+ } -+ pagecnt--; -+ pagenr++; -+ } -+ -+ /* Now do the main loop to a page aligned, n page sized output */ -+ if(len) { -+ int pagesc = len >> PAGE_SHIFT; -+ DEBUG(3, "blkmtd: write: whole pages start = %d, count = %d\n", -+ pagenr, pagesc); -+ while(pagesc) { -+ struct page *page; -+ -+ /* see if page is in the page cache */ -+ DEBUG(3, "blkmtd: write: grabbing page %d from page cache\n", pagenr); -+ page = grab_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr); -+ if(PageDirty(page)) { -+ BUG(); -+ } -+ if(!page) { -+ warn("write: cannot grab cache page %d", pagenr); -+ err = -ENOMEM; -+ goto write_err; -+ } -+ if(!buf) { -+ memset(page_address(page), 0xff, PAGE_SIZE); -+ } else { -+ memcpy(page_address(page), buf, PAGE_SIZE); -+ buf += PAGE_SIZE; -+ } -+ bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt); -+ if(!bio) { -+ err = -ENOMEM; -+ err("bio_add_page failed\n"); -+ goto write_err; -+ } -+ pagenr++; -+ pagecnt--; -+ SetPageDirty(page); -+ SetPageUptodate(page); -+ pagesc--; -+ thislen += PAGE_SIZE; -+ } -+ } -+ -+ if(end_len) { -+ /* do the third region */ -+ struct page *page; -+ DEBUG(3, "blkmtd: write: doing partial end, page = %d len = %d\n", -+ pagenr, end_len); -+ BUG_ON(!buf); -+ page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev); -+ lock_page(page); -+ if(PageDirty(page)) { -+ err("to = %lld start_len = %d len = %d end_len = %d pagenr = %d\n", -+ to, start_len, len, end_len, pagenr); -+ BUG(); -+ } -+ memcpy(page_address(page), buf, end_len); -+ SetPageDirty(page); -+ SetPageUptodate(page); -+ DEBUG(3, "blkmtd: write: writing out partial end\n"); -+ thislen += end_len; -+ bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt); -+ if(!bio) { -+ err = -ENOMEM; -+ err("bio_add_page failed\n"); -+ goto write_err; -+ } -+ pagenr++; -+ } -+ -+ DEBUG(3, "blkmtd: write: got %d vectors to write\n", bio->bi_vcnt); -+ write_err: -+ if(bio) -+ blkmtd_write_out(bio); -+ -+ DEBUG(2, "blkmtd: write: end, retlen = %d, err = %d\n", *retlen, err); -+ up(&dev->wrbuf_mutex); -+ -+ if(retlen) -+ *retlen = thislen; -+ return err; -+} -+ -+ -+/* erase a specified part of the device */ -+static int blkmtd_erase(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ struct blkmtd_dev *dev = mtd->priv; -+ struct mtd_erase_region_info *einfo = mtd->eraseregions; -+ int numregions = mtd->numeraseregions; -+ size_t from; -+ u_long len; -+ int err = -EIO; -+ int retlen; -+ -+ instr->state = MTD_ERASING; -+ from = instr->addr; -+ len = instr->len; -+ -+ /* check erase region has valid start and length */ -+ DEBUG(2, "blkmtd: erase: dev = `%s' from = 0x%x len = 0x%lx\n", -+ mtd->name+9, from, len); -+ while(numregions) { -+ DEBUG(3, "blkmtd: checking erase region = 0x%08X size = 0x%X num = 0x%x\n", -+ einfo->offset, einfo->erasesize, einfo->numblocks); -+ if(from >= einfo->offset -+ && from < einfo->offset + (einfo->erasesize * einfo->numblocks)) { -+ if(len == einfo->erasesize -+ && ( (from - einfo->offset) % einfo->erasesize == 0)) -+ break; -+ } -+ numregions--; -+ einfo++; -+ } -+ -+ if(!numregions) { -+ /* Not a valid erase block */ -+ err("erase: invalid erase request 0x%lX @ 0x%08X", len, from); -+ instr->state = MTD_ERASE_FAILED; -+ err = -EIO; -+ } -+ -+ if(instr->state != MTD_ERASE_FAILED) { -+ /* do the erase */ -+ DEBUG(3, "Doing erase from = %d len = %ld\n", from, len); -+ err = write_pages(dev, NULL, from, len, &retlen); -+ if(err || retlen != len) { -+ err("erase failed err = %d", err); -+ instr->state = MTD_ERASE_FAILED; -+ } else { -+ instr->state = MTD_ERASE_DONE; -+ } -+ } -+ -+ DEBUG(3, "blkmtd: erase: checking callback\n"); -+ if (instr->callback) { -+ (*(instr->callback))(instr); -+ } -+ DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err); -+ return err; -+} -+ -+ -+/* read a range of the data via the page cache */ -+static int blkmtd_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ struct blkmtd_dev *dev = mtd->priv; -+ int err = 0; -+ int offset; -+ int pagenr, pages; -+ size_t thislen = 0; -+ -+ DEBUG(2, "blkmtd: read: dev = `%s' from = %ld len = %d buf = %p\n", -+ mtd->name+9, (long int)from, len, buf); -+ -+ if(from > mtd->size) -+ return -EINVAL; -+ if(from + len > mtd->size) -+ len = mtd->size - from; -+ -+ pagenr = from >> PAGE_SHIFT; -+ offset = from - (pagenr << PAGE_SHIFT); -+ -+ pages = (offset+len+PAGE_SIZE-1) >> PAGE_SHIFT; -+ DEBUG(3, "blkmtd: read: pagenr = %d offset = %d, pages = %d\n", -+ pagenr, offset, pages); -+ -+ while(pages) { -+ struct page *page; -+ int cpylen; -+ -+ DEBUG(3, "blkmtd: read: looking for page: %d\n", pagenr); -+ page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev); -+ if(IS_ERR(page)) { -+ err = -EIO; -+ goto readerr; -+ } -+ -+ cpylen = (PAGE_SIZE > len) ? len : PAGE_SIZE; -+ if(offset+cpylen > PAGE_SIZE) -+ cpylen = PAGE_SIZE-offset; -+ -+ memcpy(buf + thislen, page_address(page) + offset, cpylen); -+ offset = 0; -+ len -= cpylen; -+ thislen += cpylen; -+ pagenr++; -+ pages--; -+ if(!PageDirty(page)) -+ page_cache_release(page); -+ } -+ -+ readerr: -+ if(retlen) -+ *retlen = thislen; -+ DEBUG(2, "blkmtd: end read: retlen = %d, err = %d\n", thislen, err); -+ return err; -+} -+ -+ -+/* write data to the underlying device */ -+static int blkmtd_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ struct blkmtd_dev *dev = mtd->priv; -+ int err; -+ -+ if(!len) -+ return 0; -+ -+ DEBUG(2, "blkmtd: write: dev = `%s' to = %ld len = %d buf = %p\n", -+ mtd->name+9, (long int)to, len, buf); -+ -+ if(to >= mtd->size) { -+ return -ENOSPC; -+ } -+ -+ if(to + len > mtd->size) { -+ len = mtd->size - to; -+ } -+ -+ err = write_pages(dev, buf, to, len, retlen); -+ if(err > 0) -+ err = 0; -+ DEBUG(2, "blkmtd: write: end, err = %d\n", err); -+ return err; -+} -+ -+ -+/* sync the device - wait until the write queue is empty */ -+static void blkmtd_sync(struct mtd_info *mtd) -+{ -+ /* Currently all writes are synchronous */ -+} -+ -+ -+static void free_device(struct blkmtd_dev *dev) -+{ -+ DEBUG(2, "blkmtd: free_device() dev = %p\n", dev); -+ if(dev) { -+ if(dev->mtd_info.eraseregions) -+ kfree(dev->mtd_info.eraseregions); -+ if(dev->mtd_info.name) -+ kfree(dev->mtd_info.name); -+ -+ if(dev->blkdev) { -+ invalidate_inode_pages(dev->blkdev->bd_inode->i_mapping); -+ close_bdev_excl(dev->blkdev, BDEV_RAW); -+ } -+ kfree(dev); -+ } -+} -+ -+ -+/* For a given size and initial erase size, calculate the number -+ * and size of each erase region. Goes round the loop twice, -+ * once to find out how many regions, then allocates space, -+ * then round the loop again to fill it in. -+ */ -+static struct mtd_erase_region_info *calc_erase_regions( -+ size_t erase_size, size_t total_size, int *regions) -+{ -+ struct mtd_erase_region_info *info = NULL; -+ -+ DEBUG(2, "calc_erase_regions, es = %d size = %d regions = %d\n", -+ erase_size, total_size, *regions); -+ /* Make any user specified erasesize be a power of 2 -+ and at least PAGE_SIZE */ -+ if(erase_size) { -+ int es = erase_size; -+ erase_size = 1; -+ while(es != 1) { -+ es >>= 1; -+ erase_size <<= 1; -+ } -+ if(erase_size < PAGE_SIZE) -+ erase_size = PAGE_SIZE; -+ } else { -+ erase_size = CONFIG_MTD_BLKDEV_ERASESIZE; -+ } -+ -+ *regions = 0; -+ -+ do { -+ int tot_size = total_size; -+ int er_size = erase_size; -+ int count = 0, offset = 0, regcnt = 0; -+ -+ while(tot_size) { -+ count = tot_size / er_size; -+ if(count) { -+ tot_size = tot_size % er_size; -+ if(info) { -+ DEBUG(2, "adding to erase info off=%d er=%d cnt=%d\n", -+ offset, er_size, count); -+ (info+regcnt)->offset = offset; -+ (info+regcnt)->erasesize = er_size; -+ (info+regcnt)->numblocks = count; -+ (*regions)++; -+ } -+ regcnt++; -+ offset += (count * er_size); -+ } -+ while(er_size > tot_size) -+ er_size >>= 1; -+ } -+ if(info == NULL) { -+ info = kmalloc(regcnt * sizeof(struct mtd_erase_region_info), GFP_KERNEL); -+ if(!info) -+ break; -+ } -+ } while(!(*regions)); -+ DEBUG(2, "calc_erase_regions done, es = %d size = %d regions = %d\n", -+ erase_size, total_size, *regions); -+ return info; -+} -+ -+ -+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; -+ int mode; -+ struct blkmtd_dev *dev; -+ -+ if(!devname) -+ return NULL; -+ -+ /* Get a handle on the device */ -+ -+ -+#ifdef MODULE -+ mode = (readonly) ? O_RDONLY : O_RDWR; -+ bdev = open_bdev_excl(devname, mode, BDEV_RAW, NULL); -+#else -+ mode = (readonly) ? FMODE_READ : FMODE_WRITE; -+ bdev = open_by_devnum(name_to_dev_t(devname), mode, BDEV_RAW); -+#endif -+ if(IS_ERR(bdev)) { -+ err("error: cannot open device %s", devname); -+ DEBUG(2, "blkmtd: opening bdev returned %ld\n", PTR_ERR(bdev)); -+ return NULL; -+ } -+ -+ DEBUG(1, "blkmtd: found a block device major = %d, minor = %d\n", -+ MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev)); -+ -+ if(MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { -+ err("attempting to use an MTD device as a block device"); -+ blkdev_put(bdev, BDEV_RAW); -+ return NULL; -+ } -+ -+ dev = kmalloc(sizeof(struct blkmtd_dev), GFP_KERNEL); -+ if(dev == NULL) { -+ blkdev_put(bdev, BDEV_RAW); -+ return NULL; -+ } -+ -+ memset(dev, 0, sizeof(struct blkmtd_dev)); -+ if(!readonly) { -+ init_MUTEX(&dev->wrbuf_mutex); -+ } -+ -+ dev->blkdev = bdev; -+ dev->mtd_info.size = dev->blkdev->bd_inode->i_size & PAGE_MASK; -+ -+ /* Setup the MTD structure */ -+ /* make the name contain the block device in */ -+ dev->mtd_info.name = kmalloc(sizeof("blkmtd: ") + strlen(devname), GFP_KERNEL); -+ if(dev->mtd_info.name == NULL) -+ goto devinit_err; -+ -+ sprintf(dev->mtd_info.name, "blkmtd: %s", devname); -+ dev->mtd_info.eraseregions = calc_erase_regions(erase_size, dev->mtd_info.size, -+ &dev->mtd_info.numeraseregions); -+ if(dev->mtd_info.eraseregions == NULL) -+ goto devinit_err; -+ -+ dev->mtd_info.erasesize = dev->mtd_info.eraseregions->erasesize; -+ DEBUG(1, "blkmtd: init: found %d erase regions\n", -+ dev->mtd_info.numeraseregions); -+ -+ if(readonly) { -+ dev->mtd_info.type = MTD_ROM; -+ dev->mtd_info.flags = MTD_CAP_ROM; -+ } else { -+ dev->mtd_info.type = MTD_RAM; -+ dev->mtd_info.flags = MTD_CAP_RAM; -+ dev->mtd_info.erase = blkmtd_erase; -+ dev->mtd_info.write = blkmtd_write; -+ dev->mtd_info.writev = default_mtd_writev; -+ dev->mtd_info.sync = blkmtd_sync; -+ } -+ dev->mtd_info.read = blkmtd_read; -+ dev->mtd_info.readv = default_mtd_readv; -+ dev->mtd_info.priv = dev; -+ dev->mtd_info.owner = THIS_MODULE; -+ -+ list_add(&dev->list, &blkmtd_device_list); -+ if (add_mtd_device(&dev->mtd_info)) { -+ /* Device didnt get added, so free the entry */ -+ list_del(&dev->list); -+ goto devinit_err; -+ } else { -+ info("mtd%d: [%s] erase_size = %dKiB %s", -+ dev->mtd_info.index, dev->mtd_info.name + strlen("blkmtd: "), -+ dev->mtd_info.erasesize >> 10, -+ readonly ? "(read-only)" : ""); -+ } -+ -+ return dev; -+ -+ devinit_err: -+ free_device(dev); -+ return NULL; -+} -+ -+ -+/* Cleanup and exit - sync the device and kill of the kernel thread */ -+static void __devexit cleanup_blkmtd(void) -+{ -+ struct list_head *temp1, *temp2; -+ -+ /* Remove the MTD devices */ -+ list_for_each_safe(temp1, temp2, &blkmtd_device_list) { -+ struct blkmtd_dev *dev = list_entry(temp1, struct blkmtd_dev, -+ list); -+ blkmtd_sync(&dev->mtd_info); -+ del_mtd_device(&dev->mtd_info); -+ info("mtd%d: [%s] removed", dev->mtd_info.index, -+ dev->mtd_info.name + strlen("blkmtd: ")); -+ list_del(&dev->list); -+ free_device(dev); -+ } -+} -+ -+#ifndef MODULE -+ -+/* Handle kernel boot params */ -+ -+ -+static int __init param_blkmtd_device(char *str) -+{ -+ int i; -+ -+ for(i = 0; i < MAX_DEVICES; i++) { -+ device[i] = str; -+ DEBUG(2, "blkmtd: device setup: %d = %s\n", i, device[i]); -+ strsep(&str, ","); -+ } -+ return 1; -+} -+ -+ -+static int __init param_blkmtd_erasesz(char *str) -+{ -+ int i; -+ for(i = 0; i < MAX_DEVICES; i++) { -+ char *val = strsep(&str, ","); -+ if(val) -+ erasesz[i] = simple_strtoul(val, NULL, 0); -+ DEBUG(2, "blkmtd: erasesz setup: %d = %d\n", i, erasesz[i]); -+ } -+ -+ return 1; -+} -+ -+ -+static int __init param_blkmtd_ro(char *str) -+{ -+ int i; -+ for(i = 0; i < MAX_DEVICES; i++) { -+ char *val = strsep(&str, ","); -+ if(val) -+ ro[i] = simple_strtoul(val, NULL, 0); -+ DEBUG(2, "blkmtd: ro setup: %d = %d\n", i, ro[i]); -+ } -+ -+ return 1; -+} -+ -+ -+static int __init param_blkmtd_sync(char *str) -+{ -+ if(str[0] == '1') -+ sync = 1; -+ return 1; -+} -+ -+__setup("blkmtd_device=", param_blkmtd_device); -+__setup("blkmtd_erasesz=", param_blkmtd_erasesz); -+__setup("blkmtd_ro=", param_blkmtd_ro); -+__setup("blkmtd_sync=", param_blkmtd_sync); -+ -+#endif -+ -+ -+/* Startup */ -+static int __init init_blkmtd(void) -+{ -+ int i; -+ -+ info("version " VERSION); -+ /* Check args - device[0] is the bare minimum*/ -+ if(!device[0]) { -+ err("error: missing `device' name\n"); -+ return -EINVAL; -+ } -+ -+ for(i = 0; i < MAX_DEVICES; i++) -+ add_device(device[i], ro[i], erasesz[i] << 10); -+ -+ if(list_empty(&blkmtd_device_list)) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+module_init(init_blkmtd); -+module_exit(cleanup_blkmtd); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/blkmtd.c linux/drivers/mtd/devices/blkmtd.c ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/blkmtd.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/devices/blkmtd.c 2004-11-17 18:17:58.991321216 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * blkmtd.c - use a block device as a fake MTD - * -@@ -143,7 +143,7 @@ - for(cnt = 0; cnt < pages; cnt++) { - page = grab_cache_page(dev->binding->bd_inode->i_mapping, pagenrs[cnt]); - pagelst[cnt] = page; -- if(!PageUptodate(page)) { -+ if(!Page_Uptodate(page)) { - iobuf->blocks[iobuf->nr_pages] = pagenrs[cnt]; - iobuf->maplist[iobuf->nr_pages++] = page; - } -@@ -912,7 +912,7 @@ - dev->mtd_info.point = 0; - dev->mtd_info.unpoint = 0; - dev->mtd_info.priv = dev; -- dev->mtd_info.module = THIS_MODULE; -+ dev->mtd_info.owner = THIS_MODULE; - - list_add(&dev->list, &blkmtd_device_list); - if (add_mtd_device(&dev->mtd_info)) { -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/doc2000.c linux/drivers/mtd/devices/doc2000.c ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/doc2000.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/devices/doc2000.c 2004-11-17 18:17:58.994320760 +0100 -@@ -4,7 +4,7 @@ - * (c) 1999 Machine Vision Holdings, Inc. - * (c) 1999, 2000 David Woodhouse - * -- * $Id$ -+ * $Id$ - */ - - #include -@@ -25,6 +25,7 @@ - #include - - #define DOC_SUPPORT_2000 -+#define DOC_SUPPORT_2000TSOP - #define DOC_SUPPORT_MILLENNIUM - - #ifdef DOC_SUPPORT_2000 -@@ -33,7 +34,7 @@ - #define DoC_is_2000(doc) (0) - #endif - --#ifdef DOC_SUPPORT_MILLENNIUM -+#if defined(DOC_SUPPORT_2000TSOP) || defined(DOC_SUPPORT_MILLENNIUM) - #define DoC_is_Millennium(doc) (doc->ChipID == DOC_ChipID_DocMil) - #else - #define DoC_is_Millennium(doc) (0) -@@ -56,6 +57,9 @@ - size_t *retlen, u_char *buf, u_char *eccbuf, int oobsel); - static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf, u_char *eccbuf, int oobsel); -+static int doc_writev_ecc(struct mtd_info *mtd, const struct iovec *vecs, -+ unsigned long count, loff_t to, size_t *retlen, -+ u_char *eccbuf, struct nand_oobinfo *oobsel); - static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, u_char *buf); - static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, -@@ -92,6 +96,10 @@ - - /* Out-of-line routine to wait for chip response */ - while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { -+ /* issue 2 read from NOP register after reading from CDSNControl register -+ see Software Requirement 11.4 item 2. */ -+ DoC_Delay(doc, 2); -+ - if (time_after(jiffies, timeo)) { - DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); - return -EIO; -@@ -145,6 +153,8 @@ - - /* Send the command */ - WriteDOC_(command, docptr, doc->ioreg); -+ if (DoC_is_Millennium(doc)) -+ WriteDOC(command, docptr, WritePipeTerm); - - /* Lower the CLE line */ - WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl); -@@ -206,6 +216,9 @@ - } - } - -+ if (DoC_is_Millennium(doc)) -+ WriteDOC(ofs & 0xff, docptr, WritePipeTerm); -+ - DoC_Delay(doc, 2); /* Needed for some slow flash chips. mf. */ - - /* FIXME: The SlowIO's for millennium could be replaced by -@@ -344,15 +357,25 @@ - - /* Read the manufacturer and device id codes from the device */ - -- /* CDSN Slow IO register see Software Requirement 11.4 item 5. */ -+ if (DoC_is_Millennium(doc)) { -+ DoC_Delay(doc, 2); -+ dummy = ReadDOC(doc->virtadr, ReadPipeInit); -+ mfr = ReadDOC(doc->virtadr, LastDataRead); -+ -+ DoC_Delay(doc, 2); -+ dummy = ReadDOC(doc->virtadr, ReadPipeInit); -+ id = ReadDOC(doc->virtadr, LastDataRead); -+ } else { -+ /* CDSN Slow IO register see Software Req 11.4 item 5. */ - dummy = ReadDOC(doc->virtadr, CDSNSlowIO); - DoC_Delay(doc, 2); - mfr = ReadDOC_(doc->virtadr, doc->ioreg); - -- /* CDSN Slow IO register see Software Requirement 11.4 item 5. */ -+ /* CDSN Slow IO register see Software Req 11.4 item 5. */ - dummy = ReadDOC(doc->virtadr, CDSNSlowIO); - DoC_Delay(doc, 2); - id = ReadDOC_(doc->virtadr, doc->ioreg); -+ } - - /* No response - return failure */ - if (mfr == 0xff || mfr == 0) -@@ -410,20 +433,16 @@ - - /* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */ - --static void DoC_ScanChips(struct DiskOnChip *this) -+static void DoC_ScanChips(struct DiskOnChip *this, int maxchips) - { - int floor, chip; - int numchips[MAX_FLOORS]; -- int maxchips = MAX_CHIPS; - int ret = 1; - - this->numchips = 0; - this->mfr = 0; - this->id = 0; - -- if (DoC_is_Millennium(this)) -- maxchips = MAX_CHIPS_MIL; -- - /* For each floor, find the number of valid chips it contains */ - for (floor = 0; floor < MAX_FLOORS; floor++) { - ret = 1; -@@ -515,6 +534,7 @@ - { - struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; - struct DiskOnChip *old = NULL; -+ int maxchips; - - /* We must avoid being called twice for the same device. */ - -@@ -538,14 +558,28 @@ - - - switch (this->ChipID) { -+ case DOC_ChipID_Doc2kTSOP: -+ mtd->name = "DiskOnChip 2000 TSOP"; -+ this->ioreg = DoC_Mil_CDSN_IO; -+ /* Pretend it's a Millennium */ -+ this->ChipID = DOC_ChipID_DocMil; -+ maxchips = MAX_CHIPS; -+ break; - case DOC_ChipID_Doc2k: - mtd->name = "DiskOnChip 2000"; - this->ioreg = DoC_2k_CDSN_IO; -+ maxchips = MAX_CHIPS; - break; - case DOC_ChipID_DocMil: - mtd->name = "DiskOnChip Millennium"; - this->ioreg = DoC_Mil_CDSN_IO; -+ maxchips = MAX_CHIPS_MIL; - break; -+ default: -+ printk("Unknown ChipID 0x%02x\n", this->ChipID); -+ kfree(mtd); -+ iounmap((void *) this->virtadr); -+ return; - } - - printk(KERN_NOTICE "%s found at address 0x%lX\n", mtd->name, -@@ -553,11 +587,12 @@ - - mtd->type = MTD_NANDFLASH; - mtd->flags = MTD_CAP_NANDFLASH; -+ mtd->ecctype = MTD_ECC_RS_DiskOnChip; - mtd->size = 0; - mtd->erasesize = 0; - mtd->oobblock = 512; - mtd->oobsize = 16; -- mtd->module = THIS_MODULE; -+ mtd->owner = THIS_MODULE; - mtd->erase = doc_erase; - mtd->point = NULL; - mtd->unpoint = NULL; -@@ -565,6 +600,7 @@ - mtd->write = doc_write; - mtd->read_ecc = doc_read_ecc; - mtd->write_ecc = doc_write_ecc; -+ mtd->writev_ecc = doc_writev_ecc; - mtd->read_oob = doc_read_oob; - mtd->write_oob = doc_write_oob; - mtd->sync = NULL; -@@ -577,7 +613,7 @@ - init_MUTEX(&this->lock); - - /* Ident all the chips present. */ -- DoC_ScanChips(this); -+ DoC_ScanChips(this, maxchips); - - if (!this->totlen) { - kfree(mtd); -@@ -608,6 +644,7 @@ - unsigned char syndrome[6]; - volatile char dummy; - int i, len256 = 0, ret=0; -+ size_t left = len; - - docptr = this->virtadr; - -@@ -617,6 +654,10 @@ - - down(&this->lock); - -+ *retlen = 0; -+ while (left) { -+ len = left; -+ - /* Don't allow a single read to cross a 512-byte block boundary */ - if (from + len > ((from | 0x1ff) + 1)) - len = ((from | 0x1ff) + 1) - from; -@@ -673,7 +714,7 @@ - DoC_ReadBuf(this, &buf[len256], len - len256); - - /* Let the caller know we completed it */ -- *retlen = len; -+ *retlen += len; - - if (eccbuf) { - /* Read the ECC data through the DiskOnChip ECC logic */ -@@ -730,11 +771,16 @@ - - /* according to 11.4.1, we need to wait for the busy line - * drop if we read to the end of the page. */ -- if(0 == ((from + *retlen) & 0x1ff)) -+ if(0 == ((from + len) & 0x1ff)) - { - DoC_WaitReady(this); - } - -+ from += len; -+ left -= len; -+ buf += len; -+ } -+ - up(&this->lock); - - return ret; -@@ -757,6 +803,8 @@ - volatile char dummy; - int len256 = 0; - struct Nand *mychip; -+ size_t left = len; -+ int status; - - docptr = this->virtadr; - -@@ -766,15 +814,21 @@ - - down(&this->lock); - -+ *retlen = 0; -+ while (left) { -+ len = left; -+ - /* Don't allow a single write to cross a 512-byte block boundary */ - if (to + len > ((to | 0x1ff) + 1)) - len = ((to | 0x1ff) + 1) - to; - - /* The ECC will not be calculated correctly if less than 512 is written */ -+/* DBB- - if (len != 0x200 && eccbuf) - printk(KERN_WARNING - "ECC needs a full sector write (adr: %lx size %lx)\n", - (long) to, (long) len); -+ -DBB */ - - /* printk("DoC_Write (adr: %lx size %lx)\n", (long) to, (long) len); */ - -@@ -853,6 +907,9 @@ - WriteDOC_(0, docptr, this->ioreg); - } - -+ WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_FLASH_IO | CDSN_CTRL_CE, docptr, -+ CDSNControl); -+ - /* Read the ECC data through the DiskOnChip ECC logic */ - for (di = 0; di < 6; di++) { - eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di); -@@ -874,10 +931,16 @@ - DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); - /* There's an implicit DoC_WaitReady() in DoC_Command */ - -+ if (DoC_is_Millennium(this)) { -+ ReadDOC(docptr, ReadPipeInit); -+ status = ReadDOC(docptr, LastDataRead); -+ } else { - dummy = ReadDOC(docptr, CDSNSlowIO); - DoC_Delay(this, 2); -+ status = ReadDOC_(docptr, this->ioreg); -+ } - -- if (ReadDOC_(docptr, this->ioreg) & 1) { -+ if (status & 1) { - printk(KERN_ERR "Error programming flash\n"); - /* Error in programming */ - *retlen = 0; -@@ -886,7 +949,7 @@ - } - - /* Let the caller know we completed it */ -- *retlen = len; -+ *retlen += len; - - if (eccbuf) { - unsigned char x[8]; -@@ -901,13 +964,81 @@ - x[7]=0x55; - - ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x); -+ if (ret) { - up(&this->lock); - return ret; - } -+ } -+ -+ to += len; -+ left -= len; -+ buf += len; -+ } -+ - up(&this->lock); - return 0; - } - -+static int doc_writev_ecc(struct mtd_info *mtd, const struct iovec *vecs, -+ unsigned long count, loff_t to, size_t *retlen, -+ u_char *eccbuf, struct nand_oobinfo *oobsel) -+{ -+ static char static_buf[512]; -+ static DECLARE_MUTEX(writev_buf_sem); -+ -+ size_t totretlen = 0; -+ size_t thisvecofs = 0; -+ int ret= 0; -+ -+ down(&writev_buf_sem); -+ -+ while(count) { -+ size_t thislen, thisretlen; -+ unsigned char *buf; -+ -+ buf = vecs->iov_base + thisvecofs; -+ thislen = vecs->iov_len - thisvecofs; -+ -+ -+ if (thislen >= 512) { -+ thislen = thislen & ~(512-1); -+ thisvecofs += thislen; -+ } else { -+ /* Not enough to fill a page. Copy into buf */ -+ memcpy(static_buf, buf, thislen); -+ buf = &static_buf[thislen]; -+ -+ while(count && thislen < 512) { -+ vecs++; -+ count--; -+ thisvecofs = min((512-thislen), vecs->iov_len); -+ memcpy(buf, vecs->iov_base, thisvecofs); -+ thislen += thisvecofs; -+ buf += thisvecofs; -+ } -+ buf = static_buf; -+ } -+ if (count && thisvecofs == vecs->iov_len) { -+ thisvecofs = 0; -+ vecs++; -+ count--; -+ } -+ ret = doc_write_ecc(mtd, to, thislen, &thisretlen, buf, eccbuf, oobsel); -+ -+ totretlen += thisretlen; -+ -+ if (ret || thisretlen != thislen) -+ break; -+ -+ to += thislen; -+ } -+ -+ up(&writev_buf_sem); -+ *retlen = totretlen; -+ return ret; -+} -+ -+ - static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t * retlen, u_char * buf) - { -@@ -977,6 +1108,7 @@ - unsigned long docptr = this->virtadr; - struct Nand *mychip = &this->chips[ofs >> this->chipshift]; - volatile int dummy; -+ int status; - - // printk("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",(long)ofs, len, - // buf[0], buf[1], buf[2], buf[3], buf[8], buf[9], buf[14],buf[15]); -@@ -1025,10 +1157,16 @@ - DoC_Command(this, NAND_CMD_STATUS, 0); - /* DoC_WaitReady() is implicit in DoC_Command */ - -+ if (DoC_is_Millennium(this)) { -+ ReadDOC(docptr, ReadPipeInit); -+ status = ReadDOC(docptr, LastDataRead); -+ } else { - dummy = ReadDOC(docptr, CDSNSlowIO); - DoC_Delay(this, 2); -+ status = ReadDOC_(docptr, this->ioreg); -+ } - -- if (ReadDOC_(docptr, this->ioreg) & 1) { -+ if (status & 1) { - printk(KERN_ERR "Error programming oob data\n"); - /* There was an error */ - *retlen = 0; -@@ -1044,10 +1182,16 @@ - DoC_Command(this, NAND_CMD_STATUS, 0); - /* DoC_WaitReady() is implicit in DoC_Command */ - -+ if (DoC_is_Millennium(this)) { -+ ReadDOC(docptr, ReadPipeInit); -+ status = ReadDOC(docptr, LastDataRead); -+ } else { - dummy = ReadDOC(docptr, CDSNSlowIO); - DoC_Delay(this, 2); -+ status = ReadDOC_(docptr, this->ioreg); -+ } - -- if (ReadDOC_(docptr, this->ioreg) & 1) { -+ if (status & 1) { - printk(KERN_ERR "Error programming oob data\n"); - /* There was an error */ - *retlen = 0; -@@ -1080,6 +1224,7 @@ - volatile int dummy; - unsigned long docptr; - struct Nand *mychip; -+ int status; - - down(&this->lock); - -@@ -1111,10 +1256,16 @@ - - DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); - -+ if (DoC_is_Millennium(this)) { -+ ReadDOC(docptr, ReadPipeInit); -+ status = ReadDOC(docptr, LastDataRead); -+ } else { - dummy = ReadDOC(docptr, CDSNSlowIO); - DoC_Delay(this, 2); -+ status = ReadDOC_(docptr, this->ioreg); -+ } - -- if (ReadDOC_(docptr, this->ioreg) & 1) { -+ if (status & 1) { - printk(KERN_ERR "Error erasing at 0x%x\n", ofs); - /* There was an error */ - instr->state = MTD_ERASE_FAILED; -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/doc2001.c linux/drivers/mtd/devices/doc2001.c ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/doc2001.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/devices/doc2001.c 2004-11-17 18:17:58.995320608 +0100 -@@ -4,7 +4,7 @@ - * (c) 1999 Machine Vision Holdings, Inc. - * (c) 1999, 2000 David Woodhouse - * -- * $Id$ -+ * $Id$ - */ - - #include -@@ -359,14 +359,15 @@ - - mtd->type = MTD_NANDFLASH; - mtd->flags = MTD_CAP_NANDFLASH; -+ mtd->ecctype = MTD_ECC_RS_DiskOnChip; - mtd->size = 0; - -- /* FIXME: erase size is not always 8kB */ -+ /* FIXME: erase size is not always 8KiB */ - mtd->erasesize = 0x2000; - - mtd->oobblock = 512; - mtd->oobsize = 16; -- mtd->module = THIS_MODULE; -+ mtd->owner = THIS_MODULE; - mtd->erase = doc_erase; - mtd->point = NULL; - mtd->unpoint = NULL; -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/doc2001plus.c linux/drivers/mtd/devices/doc2001plus.c ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/doc2001plus.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/devices/doc2001plus.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,1154 @@ -+/* -+ * Linux driver for Disk-On-Chip Millennium Plus -+ * -+ * (c) 2002-2003 Greg Ungerer -+ * (c) 2002-2003 SnapGear Inc -+ * (c) 1999 Machine Vision Holdings, Inc. -+ * (c) 1999, 2000 David Woodhouse -+ * -+ * $Id$ -+ * -+ * Released under GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+/* #define ECC_DEBUG */ -+ -+/* I have no idea why some DoC chips can not use memcop_form|to_io(). -+ * This may be due to the different revisions of the ASIC controller built-in or -+ * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment -+ * this:*/ -+#undef USE_MEMCPY -+ -+static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf); -+static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf); -+static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf, u_char *eccbuf, -+ struct nand_oobinfo *oobsel); -+static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf, u_char *eccbuf, -+ struct nand_oobinfo *oobsel); -+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, -+ size_t *retlen, u_char *buf); -+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, -+ size_t *retlen, const u_char *buf); -+static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); -+ -+static struct mtd_info *docmilpluslist = NULL; -+ -+ -+/* Perform the required delay cycles by writing to the NOP register */ -+static void DoC_Delay(unsigned long docptr, int cycles) -+{ -+ int i; -+ -+ for (i = 0; (i < cycles); i++) -+ WriteDOC(0, docptr, Mplus_NOP); -+} -+ -+#define CDSN_CTRL_FR_B_MASK (CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1) -+ -+/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ -+static int _DoC_WaitReady(unsigned long docptr) -+{ -+ unsigned int c = 0xffff; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, -+ "_DoC_WaitReady called for out-of-line wait\n"); -+ -+ /* Out-of-line routine to wait for chip response */ -+ while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c) -+ ; -+ -+ if (c == 0) -+ DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); -+ -+ return (c == 0); -+} -+ -+static inline int DoC_WaitReady(unsigned long docptr) -+{ -+ /* This is inline, to optimise the common case, where it's ready instantly */ -+ int ret = 0; -+ -+ /* read form NOP register should be issued prior to the read from CDSNControl -+ see Software Requirement 11.4 item 2. */ -+ DoC_Delay(docptr, 4); -+ -+ if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) -+ /* Call the out-of-line routine to wait */ -+ ret = _DoC_WaitReady(docptr); -+ -+ return ret; -+} -+ -+/* For some reason the Millennium Plus seems to occassionally put itself -+ * into reset mode. For me this happens randomly, with no pattern that I -+ * can detect. M-systems suggest always check this on any block level -+ * operation and setting to normal mode if in reset mode. -+ */ -+static inline void DoC_CheckASIC(unsigned long docptr) -+{ -+ /* Make sure the DoC is in normal mode */ -+ if ((ReadDOC(docptr, Mplus_DOCControl) & DOC_MODE_NORMAL) == 0) { -+ WriteDOC((DOC_MODE_NORMAL | DOC_MODE_MDWREN), docptr, Mplus_DOCControl); -+ WriteDOC(~(DOC_MODE_NORMAL | DOC_MODE_MDWREN), docptr, Mplus_CtrlConfirm); -+ } -+} -+ -+/* DoC_Command: Send a flash command to the flash chip through the Flash -+ * command register. Need 2 Write Pipeline Terminates to complete send. -+ */ -+static inline void DoC_Command(unsigned long docptr, unsigned char command, -+ unsigned char xtraflags) -+{ -+ WriteDOC(command, docptr, Mplus_FlashCmd); -+ WriteDOC(command, docptr, Mplus_WritePipeTerm); -+ WriteDOC(command, docptr, Mplus_WritePipeTerm); -+} -+ -+/* DoC_Address: Set the current address for the flash chip through the Flash -+ * Address register. Need 2 Write Pipeline Terminates to complete send. -+ */ -+static inline void DoC_Address(struct DiskOnChip *doc, int numbytes, -+ unsigned long ofs, unsigned char xtraflags1, -+ unsigned char xtraflags2) -+{ -+ unsigned long docptr = doc->virtadr; -+ -+ /* Allow for possible Mill Plus internal flash interleaving */ -+ ofs >>= doc->interleave; -+ -+ switch (numbytes) { -+ case 1: -+ /* Send single byte, bits 0-7. */ -+ WriteDOC(ofs & 0xff, docptr, Mplus_FlashAddress); -+ break; -+ case 2: -+ /* Send bits 9-16 followed by 17-23 */ -+ WriteDOC((ofs >> 9) & 0xff, docptr, Mplus_FlashAddress); -+ WriteDOC((ofs >> 17) & 0xff, docptr, Mplus_FlashAddress); -+ break; -+ case 3: -+ /* Send 0-7, 9-16, then 17-23 */ -+ WriteDOC(ofs & 0xff, docptr, Mplus_FlashAddress); -+ WriteDOC((ofs >> 9) & 0xff, docptr, Mplus_FlashAddress); -+ WriteDOC((ofs >> 17) & 0xff, docptr, Mplus_FlashAddress); -+ break; -+ default: -+ return; -+ } -+ -+ WriteDOC(0x00, docptr, Mplus_WritePipeTerm); -+ WriteDOC(0x00, docptr, Mplus_WritePipeTerm); -+} -+ -+/* DoC_SelectChip: Select a given flash chip within the current floor */ -+static int DoC_SelectChip(unsigned long docptr, int chip) -+{ -+ /* No choice for flash chip on Millennium Plus */ -+ return 0; -+} -+ -+/* DoC_SelectFloor: Select a given floor (bank of flash chips) */ -+static int DoC_SelectFloor(unsigned long docptr, int floor) -+{ -+ WriteDOC((floor & 0x3), docptr, Mplus_DeviceSelect); -+ return 0; -+} -+ -+/* -+ * Translate the given offset into the appropriate command and offset. -+ * This does the mapping using the 16bit interleave layout defined by -+ * M-Systems, and looks like this for a sector pair: -+ * +-----------+-------+-------+-------+--------------+---------+-----------+ -+ * | 0 --- 511 |512-517|518-519|520-521| 522 --- 1033 |1034-1039|1040 - 1055| -+ * +-----------+-------+-------+-------+--------------+---------+-----------+ -+ * | Data 0 | ECC 0 |Flags0 |Flags1 | Data 1 |ECC 1 | OOB 1 + 2 | -+ * +-----------+-------+-------+-------+--------------+---------+-----------+ -+ */ -+/* FIXME: This lives in INFTL not here. Other users of flash devices -+ may not want it */ -+static unsigned int DoC_GetDataOffset(struct mtd_info *mtd, loff_t *from) -+{ -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ -+ if (this->interleave) { -+ unsigned int ofs = *from & 0x3ff; -+ unsigned int cmd; -+ -+ if (ofs < 512) { -+ cmd = NAND_CMD_READ0; -+ ofs &= 0x1ff; -+ } else if (ofs < 1014) { -+ cmd = NAND_CMD_READ1; -+ ofs = (ofs & 0x1ff) + 10; -+ } else { -+ cmd = NAND_CMD_READOOB; -+ ofs = ofs - 1014; -+ } -+ -+ *from = (*from & ~0x3ff) | ofs; -+ return cmd; -+ } else { -+ /* No interleave */ -+ if ((*from) & 0x100) -+ return NAND_CMD_READ1; -+ return NAND_CMD_READ0; -+ } -+} -+ -+static unsigned int DoC_GetECCOffset(struct mtd_info *mtd, loff_t *from) -+{ -+ unsigned int ofs, cmd; -+ -+ if (*from & 0x200) { -+ cmd = NAND_CMD_READOOB; -+ ofs = 10 + (*from & 0xf); -+ } else { -+ cmd = NAND_CMD_READ1; -+ ofs = (*from & 0xf); -+ } -+ -+ *from = (*from & ~0x3ff) | ofs; -+ return cmd; -+} -+ -+static unsigned int DoC_GetFlagsOffset(struct mtd_info *mtd, loff_t *from) -+{ -+ unsigned int ofs, cmd; -+ -+ cmd = NAND_CMD_READ1; -+ ofs = (*from & 0x200) ? 8 : 6; -+ *from = (*from & ~0x3ff) | ofs; -+ return cmd; -+} -+ -+static unsigned int DoC_GetHdrOffset(struct mtd_info *mtd, loff_t *from) -+{ -+ unsigned int ofs, cmd; -+ -+ cmd = NAND_CMD_READOOB; -+ ofs = (*from & 0x200) ? 24 : 16; -+ *from = (*from & ~0x3ff) | ofs; -+ return cmd; -+} -+ -+static inline void MemReadDOC(unsigned long docptr, unsigned char *buf, int len) -+{ -+#ifndef USE_MEMCPY -+ int i; -+ for (i = 0; i < len; i++) -+ buf[i] = ReadDOC(docptr, Mil_CDSN_IO + i); -+#else -+ memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len); -+#endif -+} -+ -+static inline void MemWriteDOC(unsigned long docptr, unsigned char *buf, int len) -+{ -+#ifndef USE_MEMCPY -+ int i; -+ for (i = 0; i < len; i++) -+ WriteDOC(buf[i], docptr, Mil_CDSN_IO + i); -+#else -+ memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len); -+#endif -+} -+ -+/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */ -+static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) -+{ -+ int mfr, id, i, j; -+ volatile char dummy; -+ unsigned long docptr = doc->virtadr; -+ -+ /* Page in the required floor/chip */ -+ DoC_SelectFloor(docptr, floor); -+ DoC_SelectChip(docptr, chip); -+ -+ /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ -+ WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect); -+ -+ /* Reset the chip, see Software Requirement 11.4 item 1. */ -+ DoC_Command(docptr, NAND_CMD_RESET, 0); -+ DoC_WaitReady(docptr); -+ -+ /* Read the NAND chip ID: 1. Send ReadID command */ -+ DoC_Command(docptr, NAND_CMD_READID, 0); -+ -+ /* Read the NAND chip ID: 2. Send address byte zero */ -+ DoC_Address(doc, 1, 0x00, 0, 0x00); -+ -+ WriteDOC(0, docptr, Mplus_FlashControl); -+ DoC_WaitReady(docptr); -+ -+ /* Read the manufacturer and device id codes of the flash device through -+ CDSN IO register see Software Requirement 11.4 item 5.*/ -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ -+ mfr = ReadDOC(docptr, Mil_CDSN_IO); -+ if (doc->interleave) -+ dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */ -+ -+ id = ReadDOC(docptr, Mil_CDSN_IO); -+ if (doc->interleave) -+ dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */ -+ -+ dummy = ReadDOC(docptr, Mplus_LastDataRead); -+ dummy = ReadDOC(docptr, Mplus_LastDataRead); -+ -+ /* Disable flash internally */ -+ WriteDOC(0, docptr, Mplus_FlashSelect); -+ -+ /* No response - return failure */ -+ if (mfr == 0xff || mfr == 0) -+ return 0; -+ -+ for (i = 0; nand_flash_ids[i].name != NULL; i++) { -+ if (id == nand_flash_ids[i].id) { -+ /* Try to identify manufacturer */ -+ for (j = 0; nand_manuf_ids[j].id != 0x0; j++) { -+ if (nand_manuf_ids[j].id == mfr) -+ break; -+ } -+ printk(KERN_INFO "Flash chip found: Manufacturer ID: %2.2X, " -+ "Chip ID: %2.2X (%s:%s)\n", mfr, id, -+ nand_manuf_ids[j].name, nand_flash_ids[i].name); -+ doc->mfr = mfr; -+ doc->id = id; -+ doc->chipshift = nand_flash_ids[i].chipshift; -+ doc->erasesize = nand_flash_ids[i].erasesize << doc->interleave; -+ break; -+ } -+ } -+ -+ if (nand_flash_ids[i].name == NULL) -+ return 0; -+ return 1; -+} -+ -+/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */ -+static void DoC_ScanChips(struct DiskOnChip *this) -+{ -+ int floor, chip; -+ int numchips[MAX_FLOORS_MPLUS]; -+ int ret; -+ -+ this->numchips = 0; -+ this->mfr = 0; -+ this->id = 0; -+ -+ /* Work out the intended interleave setting */ -+ this->interleave = 0; -+ if (this->ChipID == DOC_ChipID_DocMilPlus32) -+ this->interleave = 1; -+ -+ /* Check the ASIC agrees */ -+ if ( (this->interleave << 2) != -+ (ReadDOC(this->virtadr, Mplus_Configuration) & 4)) { -+ u_char conf = ReadDOC(this->virtadr, Mplus_Configuration); -+ printk(KERN_NOTICE "Setting DiskOnChip Millennium Plus interleave to %s\n", -+ this->interleave?"on (16-bit)":"off (8-bit)"); -+ conf ^= 4; -+ WriteDOC(this->virtadr, conf, Mplus_Configuration); -+ } -+ -+ /* For each floor, find the number of valid chips it contains */ -+ for (floor = 0,ret = 1; floor < MAX_FLOORS_MPLUS; floor++) { -+ numchips[floor] = 0; -+ for (chip = 0; chip < MAX_CHIPS_MPLUS && ret != 0; chip++) { -+ ret = DoC_IdentChip(this, floor, chip); -+ if (ret) { -+ numchips[floor]++; -+ this->numchips++; -+ } -+ } -+ } -+ /* If there are none at all that we recognise, bail */ -+ if (!this->numchips) { -+ printk("No flash chips recognised.\n"); -+ return; -+ } -+ -+ /* Allocate an array to hold the information for each chip */ -+ this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL); -+ if (!this->chips){ -+ printk("MTD: No memory for allocating chip info structures\n"); -+ return; -+ } -+ -+ /* Fill out the chip array with {floor, chipno} for each -+ * detected chip in the device. */ -+ for (floor = 0, ret = 0; floor < MAX_FLOORS_MPLUS; floor++) { -+ for (chip = 0 ; chip < numchips[floor] ; chip++) { -+ this->chips[ret].floor = floor; -+ this->chips[ret].chip = chip; -+ this->chips[ret].curadr = 0; -+ this->chips[ret].curmode = 0x50; -+ ret++; -+ } -+ } -+ -+ /* Calculate and print the total size of the device */ -+ this->totlen = this->numchips * (1 << this->chipshift); -+ printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld MiB\n", -+ this->numchips ,this->totlen >> 20); -+} -+ -+static int DoCMilPlus_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2) -+{ -+ int tmp1, tmp2, retval; -+ -+ if (doc1->physadr == doc2->physadr) -+ return 1; -+ -+ /* Use the alias resolution register which was set aside for this -+ * purpose. If it's value is the same on both chips, they might -+ * be the same chip, and we write to one and check for a change in -+ * the other. It's unclear if this register is usuable in the -+ * DoC 2000 (it's in the Millennium docs), but it seems to work. */ -+ tmp1 = ReadDOC(doc1->virtadr, Mplus_AliasResolution); -+ tmp2 = ReadDOC(doc2->virtadr, Mplus_AliasResolution); -+ if (tmp1 != tmp2) -+ return 0; -+ -+ WriteDOC((tmp1+1) % 0xff, doc1->virtadr, Mplus_AliasResolution); -+ tmp2 = ReadDOC(doc2->virtadr, Mplus_AliasResolution); -+ if (tmp2 == (tmp1+1) % 0xff) -+ retval = 1; -+ else -+ retval = 0; -+ -+ /* Restore register contents. May not be necessary, but do it just to -+ * be safe. */ -+ WriteDOC(tmp1, doc1->virtadr, Mplus_AliasResolution); -+ -+ return retval; -+} -+ -+static const char im_name[] = "DoCMilPlus_init"; -+ -+/* This routine is made available to other mtd code via -+ * inter_module_register. It must only be accessed through -+ * inter_module_get which will bump the use count of this module. The -+ * addresses passed back in mtd are valid as long as the use count of -+ * this module is non-zero, i.e. between inter_module_get and -+ * inter_module_put. Keith Owens 29 Oct 2000. -+ */ -+static void DoCMilPlus_init(struct mtd_info *mtd) -+{ -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ struct DiskOnChip *old = NULL; -+ -+ /* We must avoid being called twice for the same device. */ -+ if (docmilpluslist) -+ old = (struct DiskOnChip *)docmilpluslist->priv; -+ -+ while (old) { -+ if (DoCMilPlus_is_alias(this, old)) { -+ printk(KERN_NOTICE "Ignoring DiskOnChip Millennium " -+ "Plus at 0x%lX - already configured\n", -+ this->physadr); -+ iounmap((void *)this->virtadr); -+ kfree(mtd); -+ return; -+ } -+ if (old->nextdoc) -+ old = (struct DiskOnChip *)old->nextdoc->priv; -+ else -+ old = NULL; -+ } -+ -+ mtd->name = "DiskOnChip Millennium Plus"; -+ printk(KERN_NOTICE "DiskOnChip Millennium Plus found at " -+ "address 0x%lX\n", this->physadr); -+ -+ mtd->type = MTD_NANDFLASH; -+ mtd->flags = MTD_CAP_NANDFLASH; -+ mtd->ecctype = MTD_ECC_RS_DiskOnChip; -+ mtd->size = 0; -+ -+ mtd->erasesize = 0; -+ mtd->oobblock = 512; -+ mtd->oobsize = 16; -+ mtd->owner = THIS_MODULE; -+ mtd->erase = doc_erase; -+ mtd->point = NULL; -+ mtd->unpoint = NULL; -+ mtd->read = doc_read; -+ mtd->write = doc_write; -+ mtd->read_ecc = doc_read_ecc; -+ mtd->write_ecc = doc_write_ecc; -+ mtd->read_oob = doc_read_oob; -+ mtd->write_oob = doc_write_oob; -+ mtd->sync = NULL; -+ -+ this->totlen = 0; -+ this->numchips = 0; -+ this->curfloor = -1; -+ this->curchip = -1; -+ -+ /* Ident all the chips present. */ -+ DoC_ScanChips(this); -+ -+ if (!this->totlen) { -+ kfree(mtd); -+ iounmap((void *)this->virtadr); -+ } else { -+ this->nextdoc = docmilpluslist; -+ docmilpluslist = mtd; -+ mtd->size = this->totlen; -+ mtd->erasesize = this->erasesize; -+ add_mtd_device(mtd); -+ return; -+ } -+} -+ -+#if 0 -+static int doc_dumpblk(struct mtd_info *mtd, loff_t from) -+{ -+ int i; -+ loff_t fofs; -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ unsigned long docptr = this->virtadr; -+ struct Nand *mychip = &this->chips[from >> (this->chipshift)]; -+ unsigned char *bp, buf[1056]; -+ char c[32]; -+ -+ from &= ~0x3ff; -+ -+ /* Don't allow read past end of device */ -+ if (from >= this->totlen) -+ return -EINVAL; -+ -+ DoC_CheckASIC(docptr); -+ -+ /* Find the chip which is to be used and select it */ -+ if (this->curfloor != mychip->floor) { -+ DoC_SelectFloor(docptr, mychip->floor); -+ DoC_SelectChip(docptr, mychip->chip); -+ } else if (this->curchip != mychip->chip) { -+ DoC_SelectChip(docptr, mychip->chip); -+ } -+ this->curfloor = mychip->floor; -+ this->curchip = mychip->chip; -+ -+ /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ -+ WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect); -+ -+ /* Reset the chip, see Software Requirement 11.4 item 1. */ -+ DoC_Command(docptr, NAND_CMD_RESET, 0); -+ DoC_WaitReady(docptr); -+ -+ fofs = from; -+ DoC_Command(docptr, DoC_GetDataOffset(mtd, &fofs), 0); -+ DoC_Address(this, 3, fofs, 0, 0x00); -+ WriteDOC(0, docptr, Mplus_FlashControl); -+ DoC_WaitReady(docptr); -+ -+ /* disable the ECC engine */ -+ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); -+ -+ ReadDOC(docptr, Mplus_ReadPipeInit); -+ ReadDOC(docptr, Mplus_ReadPipeInit); -+ -+ /* Read the data via the internal pipeline through CDSN IO -+ register, see Pipelined Read Operations 11.3 */ -+ MemReadDOC(docptr, buf, 1054); -+ buf[1054] = ReadDOC(docptr, Mplus_LastDataRead); -+ buf[1055] = ReadDOC(docptr, Mplus_LastDataRead); -+ -+ memset(&c[0], 0, sizeof(c)); -+ printk("DUMP OFFSET=%x:\n", (int)from); -+ -+ for (i = 0, bp = &buf[0]; (i < 1056); i++) { -+ if ((i % 16) == 0) -+ printk("%08x: ", i); -+ printk(" %02x", *bp); -+ c[(i & 0xf)] = ((*bp >= 0x20) && (*bp <= 0x7f)) ? *bp : '.'; -+ bp++; -+ if (((i + 1) % 16) == 0) -+ printk(" %s\n", c); -+ } -+ printk("\n"); -+ -+ /* Disable flash internally */ -+ WriteDOC(0, docptr, Mplus_FlashSelect); -+ -+ return 0; -+} -+#endif -+ -+static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ /* Just a special case of doc_read_ecc */ -+ return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL); -+} -+ -+static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf, u_char *eccbuf, -+ struct nand_oobinfo *oobsel) -+{ -+ int ret, i; -+ volatile char dummy; -+ loff_t fofs; -+ unsigned char syndrome[6]; -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ unsigned long docptr = this->virtadr; -+ struct Nand *mychip = &this->chips[from >> (this->chipshift)]; -+ -+ /* Don't allow read past end of device */ -+ if (from >= this->totlen) -+ return -EINVAL; -+ -+ /* Don't allow a single read to cross a 512-byte block boundary */ -+ if (from + len > ((from | 0x1ff) + 1)) -+ len = ((from | 0x1ff) + 1) - from; -+ -+ DoC_CheckASIC(docptr); -+ -+ /* Find the chip which is to be used and select it */ -+ if (this->curfloor != mychip->floor) { -+ DoC_SelectFloor(docptr, mychip->floor); -+ DoC_SelectChip(docptr, mychip->chip); -+ } else if (this->curchip != mychip->chip) { -+ DoC_SelectChip(docptr, mychip->chip); -+ } -+ this->curfloor = mychip->floor; -+ this->curchip = mychip->chip; -+ -+ /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ -+ WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect); -+ -+ /* Reset the chip, see Software Requirement 11.4 item 1. */ -+ DoC_Command(docptr, NAND_CMD_RESET, 0); -+ DoC_WaitReady(docptr); -+ -+ fofs = from; -+ DoC_Command(docptr, DoC_GetDataOffset(mtd, &fofs), 0); -+ DoC_Address(this, 3, fofs, 0, 0x00); -+ WriteDOC(0, docptr, Mplus_FlashControl); -+ DoC_WaitReady(docptr); -+ -+ if (eccbuf) { -+ /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ -+ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); -+ WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf); -+ } else { -+ /* disable the ECC engine */ -+ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); -+ } -+ -+ /* Let the caller know we completed it */ -+ *retlen = len; -+ ret = 0; -+ -+ ReadDOC(docptr, Mplus_ReadPipeInit); -+ ReadDOC(docptr, Mplus_ReadPipeInit); -+ -+ if (eccbuf) { -+ /* Read the data via the internal pipeline through CDSN IO -+ register, see Pipelined Read Operations 11.3 */ -+ MemReadDOC(docptr, buf, len); -+ -+ /* Read the ECC data following raw data */ -+ MemReadDOC(docptr, eccbuf, 4); -+ eccbuf[4] = ReadDOC(docptr, Mplus_LastDataRead); -+ eccbuf[5] = ReadDOC(docptr, Mplus_LastDataRead); -+ -+ /* Flush the pipeline */ -+ dummy = ReadDOC(docptr, Mplus_ECCConf); -+ dummy = ReadDOC(docptr, Mplus_ECCConf); -+ -+ /* Check the ECC Status */ -+ if (ReadDOC(docptr, Mplus_ECCConf) & 0x80) { -+ int nb_errors; -+ /* There was an ECC error */ -+#ifdef ECC_DEBUG -+ printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); -+#endif -+ /* Read the ECC syndrom through the DiskOnChip ECC logic. -+ These syndrome will be all ZERO when there is no error */ -+ for (i = 0; i < 6; i++) -+ syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); -+ -+ nb_errors = doc_decode_ecc(buf, syndrome); -+#ifdef ECC_DEBUG -+ printk("ECC Errors corrected: %x\n", nb_errors); -+#endif -+ if (nb_errors < 0) { -+ /* We return error, but have actually done the read. Not that -+ this can be told to user-space, via sys_read(), but at least -+ MTD-aware stuff can know about it by checking *retlen */ -+#ifdef ECC_DEBUG -+ printk("%s(%d): Millennium Plus ECC error (from=0x%x:\n", -+ __FILE__, __LINE__, (int)from); -+ printk(" syndrome= %02x:%02x:%02x:%02x:%02x:" -+ "%02x\n", -+ syndrome[0], syndrome[1], syndrome[2], -+ syndrome[3], syndrome[4], syndrome[5]); -+ printk(" eccbuf= %02x:%02x:%02x:%02x:%02x:" -+ "%02x\n", -+ eccbuf[0], eccbuf[1], eccbuf[2], -+ eccbuf[3], eccbuf[4], eccbuf[5]); -+#endif -+ ret = -EIO; -+ } -+ } -+ -+#ifdef PSYCHO_DEBUG -+ printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", -+ (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], -+ eccbuf[4], eccbuf[5]); -+#endif -+ -+ /* disable the ECC engine */ -+ WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf); -+ } else { -+ /* Read the data via the internal pipeline through CDSN IO -+ register, see Pipelined Read Operations 11.3 */ -+ MemReadDOC(docptr, buf, len-2); -+ buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead); -+ buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead); -+ } -+ -+ /* Disable flash internally */ -+ WriteDOC(0, docptr, Mplus_FlashSelect); -+ -+ return ret; -+} -+ -+static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ char eccbuf[6]; -+ return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL); -+} -+ -+static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf, u_char *eccbuf, -+ struct nand_oobinfo *oobsel) -+{ -+ int i, before, ret = 0; -+ loff_t fto; -+ volatile char dummy; -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ unsigned long docptr = this->virtadr; -+ struct Nand *mychip = &this->chips[to >> (this->chipshift)]; -+ -+ /* Don't allow write past end of device */ -+ if (to >= this->totlen) -+ return -EINVAL; -+ -+ /* Don't allow writes which aren't exactly one block (512 bytes) */ -+ if ((to & 0x1ff) || (len != 0x200)) -+ return -EINVAL; -+ -+ /* Determine position of OOB flags, before or after data */ -+ before = (this->interleave && (to & 0x200)); -+ -+ DoC_CheckASIC(docptr); -+ -+ /* Find the chip which is to be used and select it */ -+ if (this->curfloor != mychip->floor) { -+ DoC_SelectFloor(docptr, mychip->floor); -+ DoC_SelectChip(docptr, mychip->chip); -+ } else if (this->curchip != mychip->chip) { -+ DoC_SelectChip(docptr, mychip->chip); -+ } -+ this->curfloor = mychip->floor; -+ this->curchip = mychip->chip; -+ -+ /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ -+ WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect); -+ -+ /* Reset the chip, see Software Requirement 11.4 item 1. */ -+ DoC_Command(docptr, NAND_CMD_RESET, 0); -+ DoC_WaitReady(docptr); -+ -+ /* Set device to appropriate plane of flash */ -+ fto = to; -+ WriteDOC(DoC_GetDataOffset(mtd, &fto), docptr, Mplus_FlashCmd); -+ -+ /* On interleaved devices the flags for 2nd half 512 are before data */ -+ if (eccbuf && before) -+ fto -= 2; -+ -+ /* issue the Serial Data In command to initial the Page Program process */ -+ DoC_Command(docptr, NAND_CMD_SEQIN, 0x00); -+ DoC_Address(this, 3, fto, 0x00, 0x00); -+ -+ /* Disable the ECC engine */ -+ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); -+ -+ if (eccbuf) { -+ if (before) { -+ /* Write the block status BLOCK_USED (0x5555) */ -+ WriteDOC(0x55, docptr, Mil_CDSN_IO); -+ WriteDOC(0x55, docptr, Mil_CDSN_IO); -+ } -+ -+ /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ -+ WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf); -+ } -+ -+ MemWriteDOC(docptr, (unsigned char *) buf, len); -+ -+ if (eccbuf) { -+ /* Write ECC data to flash, the ECC info is generated by -+ the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */ -+ DoC_Delay(docptr, 3); -+ -+ /* Read the ECC data through the DiskOnChip ECC logic */ -+ for (i = 0; i < 6; i++) -+ eccbuf[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); -+ -+ /* disable the ECC engine */ -+ WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); -+ -+ /* Write the ECC data to flash */ -+ MemWriteDOC(docptr, eccbuf, 6); -+ -+ if (!before) { -+ /* Write the block status BLOCK_USED (0x5555) */ -+ WriteDOC(0x55, docptr, Mil_CDSN_IO+6); -+ WriteDOC(0x55, docptr, Mil_CDSN_IO+7); -+ } -+ -+#ifdef PSYCHO_DEBUG -+ printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", -+ (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], -+ eccbuf[4], eccbuf[5]); -+#endif -+ } -+ -+ WriteDOC(0x00, docptr, Mplus_WritePipeTerm); -+ WriteDOC(0x00, docptr, Mplus_WritePipeTerm); -+ -+ /* Commit the Page Program command and wait for ready -+ see Software Requirement 11.4 item 1.*/ -+ DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00); -+ DoC_WaitReady(docptr); -+ -+ /* Read the status of the flash device through CDSN IO register -+ see Software Requirement 11.4 item 5.*/ -+ DoC_Command(docptr, NAND_CMD_STATUS, 0); -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ DoC_Delay(docptr, 2); -+ if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) { -+ printk("MTD: Error 0x%x programming at 0x%x\n", dummy, (int)to); -+ /* Error in programming -+ FIXME: implement Bad Block Replacement (in nftl.c ??) */ -+ *retlen = 0; -+ ret = -EIO; -+ } -+ dummy = ReadDOC(docptr, Mplus_LastDataRead); -+ -+ /* Disable flash internally */ -+ WriteDOC(0, docptr, Mplus_FlashSelect); -+ -+ /* Let the caller know we completed it */ -+ *retlen = len; -+ -+ return ret; -+} -+ -+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ loff_t fofs, base; -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ unsigned long docptr = this->virtadr; -+ struct Nand *mychip = &this->chips[ofs >> this->chipshift]; -+ size_t i, size, got, want; -+ -+ DoC_CheckASIC(docptr); -+ -+ /* Find the chip which is to be used and select it */ -+ if (this->curfloor != mychip->floor) { -+ DoC_SelectFloor(docptr, mychip->floor); -+ DoC_SelectChip(docptr, mychip->chip); -+ } else if (this->curchip != mychip->chip) { -+ DoC_SelectChip(docptr, mychip->chip); -+ } -+ this->curfloor = mychip->floor; -+ this->curchip = mychip->chip; -+ -+ /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ -+ WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect); -+ -+ /* disable the ECC engine */ -+ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); -+ DoC_WaitReady(docptr); -+ -+ /* Maximum of 16 bytes in the OOB region, so limit read to that */ -+ if (len > 16) -+ len = 16; -+ got = 0; -+ want = len; -+ -+ for (i = 0; ((i < 3) && (want > 0)); i++) { -+ /* Figure out which region we are accessing... */ -+ fofs = ofs; -+ base = ofs & 0xf; -+ if (!this->interleave) { -+ DoC_Command(docptr, NAND_CMD_READOOB, 0); -+ size = 16 - base; -+ } else if (base < 6) { -+ DoC_Command(docptr, DoC_GetECCOffset(mtd, &fofs), 0); -+ size = 6 - base; -+ } else if (base < 8) { -+ DoC_Command(docptr, DoC_GetFlagsOffset(mtd, &fofs), 0); -+ size = 8 - base; -+ } else { -+ DoC_Command(docptr, DoC_GetHdrOffset(mtd, &fofs), 0); -+ size = 16 - base; -+ } -+ if (size > want) -+ size = want; -+ -+ /* Issue read command */ -+ DoC_Address(this, 3, fofs, 0, 0x00); -+ WriteDOC(0, docptr, Mplus_FlashControl); -+ DoC_WaitReady(docptr); -+ -+ ReadDOC(docptr, Mplus_ReadPipeInit); -+ ReadDOC(docptr, Mplus_ReadPipeInit); -+ MemReadDOC(docptr, &buf[got], size - 2); -+ buf[got + size - 2] = ReadDOC(docptr, Mplus_LastDataRead); -+ buf[got + size - 1] = ReadDOC(docptr, Mplus_LastDataRead); -+ -+ ofs += size; -+ got += size; -+ want -= size; -+ } -+ -+ /* Disable flash internally */ -+ WriteDOC(0, docptr, Mplus_FlashSelect); -+ -+ *retlen = len; -+ return 0; -+} -+ -+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ volatile char dummy; -+ loff_t fofs, base; -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ unsigned long docptr = this->virtadr; -+ struct Nand *mychip = &this->chips[ofs >> this->chipshift]; -+ size_t i, size, got, want; -+ int ret = 0; -+ -+ DoC_CheckASIC(docptr); -+ -+ /* Find the chip which is to be used and select it */ -+ if (this->curfloor != mychip->floor) { -+ DoC_SelectFloor(docptr, mychip->floor); -+ DoC_SelectChip(docptr, mychip->chip); -+ } else if (this->curchip != mychip->chip) { -+ DoC_SelectChip(docptr, mychip->chip); -+ } -+ this->curfloor = mychip->floor; -+ this->curchip = mychip->chip; -+ -+ /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ -+ WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect); -+ -+ -+ /* Maximum of 16 bytes in the OOB region, so limit write to that */ -+ if (len > 16) -+ len = 16; -+ got = 0; -+ want = len; -+ -+ for (i = 0; ((i < 3) && (want > 0)); i++) { -+ /* Reset the chip, see Software Requirement 11.4 item 1. */ -+ DoC_Command(docptr, NAND_CMD_RESET, 0); -+ DoC_WaitReady(docptr); -+ -+ /* Figure out which region we are accessing... */ -+ fofs = ofs; -+ base = ofs & 0x0f; -+ if (!this->interleave) { -+ WriteDOC(NAND_CMD_READOOB, docptr, Mplus_FlashCmd); -+ size = 16 - base; -+ } else if (base < 6) { -+ WriteDOC(DoC_GetECCOffset(mtd, &fofs), docptr, Mplus_FlashCmd); -+ size = 6 - base; -+ } else if (base < 8) { -+ WriteDOC(DoC_GetFlagsOffset(mtd, &fofs), docptr, Mplus_FlashCmd); -+ size = 8 - base; -+ } else { -+ WriteDOC(DoC_GetHdrOffset(mtd, &fofs), docptr, Mplus_FlashCmd); -+ size = 16 - base; -+ } -+ if (size > want) -+ size = want; -+ -+ /* Issue the Serial Data In command to initial the Page Program process */ -+ DoC_Command(docptr, NAND_CMD_SEQIN, 0x00); -+ DoC_Address(this, 3, fofs, 0, 0x00); -+ -+ /* Disable the ECC engine */ -+ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); -+ -+ /* Write the data via the internal pipeline through CDSN IO -+ register, see Pipelined Write Operations 11.2 */ -+ MemWriteDOC(docptr, (unsigned char *) &buf[got], size); -+ WriteDOC(0x00, docptr, Mplus_WritePipeTerm); -+ WriteDOC(0x00, docptr, Mplus_WritePipeTerm); -+ -+ /* Commit the Page Program command and wait for ready -+ see Software Requirement 11.4 item 1.*/ -+ DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00); -+ DoC_WaitReady(docptr); -+ -+ /* Read the status of the flash device through CDSN IO register -+ see Software Requirement 11.4 item 5.*/ -+ DoC_Command(docptr, NAND_CMD_STATUS, 0x00); -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ DoC_Delay(docptr, 2); -+ if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) { -+ printk("MTD: Error 0x%x programming oob at 0x%x\n", -+ dummy, (int)ofs); -+ /* FIXME: implement Bad Block Replacement */ -+ *retlen = 0; -+ ret = -EIO; -+ } -+ dummy = ReadDOC(docptr, Mplus_LastDataRead); -+ -+ ofs += size; -+ got += size; -+ want -= size; -+ } -+ -+ /* Disable flash internally */ -+ WriteDOC(0, docptr, Mplus_FlashSelect); -+ -+ *retlen = len; -+ return ret; -+} -+ -+int doc_erase(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ volatile char dummy; -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ __u32 ofs = instr->addr; -+ __u32 len = instr->len; -+ unsigned long docptr = this->virtadr; -+ struct Nand *mychip = &this->chips[ofs >> this->chipshift]; -+ -+ DoC_CheckASIC(docptr); -+ -+ if (len != mtd->erasesize) -+ printk(KERN_WARNING "MTD: Erase not right size (%x != %x)n", -+ len, mtd->erasesize); -+ -+ /* Find the chip which is to be used and select it */ -+ if (this->curfloor != mychip->floor) { -+ DoC_SelectFloor(docptr, mychip->floor); -+ DoC_SelectChip(docptr, mychip->chip); -+ } else if (this->curchip != mychip->chip) { -+ DoC_SelectChip(docptr, mychip->chip); -+ } -+ this->curfloor = mychip->floor; -+ this->curchip = mychip->chip; -+ -+ instr->state = MTD_ERASE_PENDING; -+ -+ /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ -+ WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect); -+ -+ DoC_Command(docptr, NAND_CMD_RESET, 0x00); -+ DoC_WaitReady(docptr); -+ -+ DoC_Command(docptr, NAND_CMD_ERASE1, 0); -+ DoC_Address(this, 2, ofs, 0, 0x00); -+ DoC_Command(docptr, NAND_CMD_ERASE2, 0); -+ DoC_WaitReady(docptr); -+ instr->state = MTD_ERASING; -+ -+ /* Read the status of the flash device through CDSN IO register -+ see Software Requirement 11.4 item 5. */ -+ DoC_Command(docptr, NAND_CMD_STATUS, 0); -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) { -+ printk("MTD: Error 0x%x erasing at 0x%x\n", dummy, ofs); -+ /* FIXME: implement Bad Block Replacement (in nftl.c ??) */ -+ instr->state = MTD_ERASE_FAILED; -+ } else { -+ instr->state = MTD_ERASE_DONE; -+ } -+ dummy = ReadDOC(docptr, Mplus_LastDataRead); -+ -+ /* Disable flash internally */ -+ WriteDOC(0, docptr, Mplus_FlashSelect); -+ -+ if (instr->callback) -+ instr->callback(instr); -+ -+ return 0; -+} -+ -+/**************************************************************************** -+ * -+ * Module stuff -+ * -+ ****************************************************************************/ -+ -+int __init init_doc2001plus(void) -+{ -+ inter_module_register(im_name, THIS_MODULE, &DoCMilPlus_init); -+ return 0; -+} -+ -+static void __exit cleanup_doc2001plus(void) -+{ -+ struct mtd_info *mtd; -+ struct DiskOnChip *this; -+ -+ while ((mtd=docmilpluslist)) { -+ this = (struct DiskOnChip *)mtd->priv; -+ docmilpluslist = this->nextdoc; -+ -+ del_mtd_device(mtd); -+ -+ iounmap((void *)this->virtadr); -+ kfree(this->chips); -+ kfree(mtd); -+ } -+ inter_module_unregister(im_name); -+} -+ -+module_exit(cleanup_doc2001plus); -+module_init(init_doc2001plus); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Greg Ungerer et al."); -+MODULE_DESCRIPTION("Driver for DiskOnChip Millennium Plus"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/docecc.c linux/drivers/mtd/devices/docecc.c ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/docecc.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/devices/docecc.c 2004-11-17 18:17:59.019316960 +0100 -@@ -7,7 +7,7 @@ - * Author: Fabrice Bellard (fabrice.bellard@netgem.com) - * Copyright (C) 2000 Netgem S.A. - * -- * $Id$ -+ * $Id$ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -519,6 +519,8 @@ - return nb_errors; - } - -+EXPORT_SYMBOL_GPL(doc_decode_ecc); -+ - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Fabrice Bellard "); - MODULE_DESCRIPTION("ECC code for correcting errors detected by DiskOnChip 2000 and Millennium ECC hardware"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/docprobe.c linux/drivers/mtd/devices/docprobe.c ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/docprobe.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/devices/docprobe.c 2004-11-17 18:17:59.020316808 +0100 -@@ -4,7 +4,7 @@ - /* (C) 1999 Machine Vision Holdings, Inc. */ - /* (C) 1999-2003 David Woodhouse */ - --/* $Id$ */ -+/* $Id$ */ - - - -@@ -31,14 +31,12 @@ - /* DOC_SINGLE_DRIVER: - Millennium driver has been merged into DOC2000 driver. - -- The newly-merged driver doesn't appear to work for writing. It's the -- same with the DiskOnChip 2000 and the Millennium. If you have a -- Millennium and you want write support to work, remove the definition -- of DOC_SINGLE_DRIVER below to use the old doc2001-specific driver. -- -- Otherwise, it's left on in the hope that it'll annoy someone with -- a Millennium enough that they go through and work out what the -- difference is :) -+ The old Millennium-only driver has been retained just in case there -+ are problems with the new code. If the combined driver doesn't work -+ for you, you can try the old one by undefining DOC_SINGLE_DRIVER -+ below and also enabling it in your configuration. If this fixes the -+ problems, please send a report to the MTD mailing list at -+ . - */ - #define DOC_SINGLE_DRIVER - -@@ -47,18 +45,15 @@ - #include - #include - #include --#include --#include --#include - #include - #include --#include - #include - #include - - #include - #include - #include -+#include - - /* Where to look for the devices? */ - #ifndef CONFIG_MTD_DOCPROBE_ADDRESS -@@ -92,17 +87,17 @@ - 0xff000000, - #elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C) - 0xff000000, --#else -+##else - #warning Unknown architecture for DiskOnChip. No default probe locations defined - #endif -- 0 }; -+ 0xffffffff }; - - /* doccheck: Probe a given memory window to see if there's a DiskOnChip present */ - - static inline int __init doccheck(unsigned long potential, unsigned long physadr) - { - unsigned long window=potential; -- unsigned char tmp, ChipID; -+ unsigned char tmp, tmpb, tmpc, ChipID; - #ifndef DOC_PASSIVE_PROBE - unsigned char tmp2; - #endif -@@ -140,26 +135,80 @@ - window, DOCControl); - #endif /* !DOC_PASSIVE_PROBE */ - -+ /* We need to read the ChipID register four times. For some -+ newer DiskOnChip 2000 units, the first three reads will -+ return the DiskOnChip Millennium ident. Don't ask. */ - ChipID = ReadDOC(window, ChipID); - - switch (ChipID) { - case DOC_ChipID_Doc2k: - /* Check the TOGGLE bit in the ECC register */ - tmp = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT; -- if ((ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT) != tmp) -+ tmpb = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT; -+ tmpc = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT; -+ if (tmp != tmpb && tmp == tmpc) - return ChipID; - break; - - case DOC_ChipID_DocMil: -+ /* Check for the new 2000 with Millennium ASIC */ -+ ReadDOC(window, ChipID); -+ ReadDOC(window, ChipID); -+ if (ReadDOC(window, ChipID) != DOC_ChipID_DocMil) -+ ChipID = DOC_ChipID_Doc2kTSOP; -+ - /* Check the TOGGLE bit in the ECC register */ - tmp = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT; -- if ((ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT) != tmp) -+ tmpb = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT; -+ tmpc = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT; -+ if (tmp != tmpb && tmp == tmpc) -+ return ChipID; -+ break; -+ -+ case DOC_ChipID_DocMilPlus16: -+ case DOC_ChipID_DocMilPlus32: -+ case 0: -+ /* Possible Millennium+, need to do more checks */ -+#ifndef DOC_PASSIVE_PROBE -+ /* Possibly release from power down mode */ -+ for (tmp = 0; (tmp < 4); tmp++) -+ ReadDOC(window, Mplus_Power); -+ -+ /* Reset the DiskOnChip ASIC */ -+ tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | -+ DOC_MODE_BDECT; -+ WriteDOC(tmp, window, Mplus_DOCControl); -+ WriteDOC(~tmp, window, Mplus_CtrlConfirm); -+ -+ mdelay(1); -+ /* Enable the DiskOnChip ASIC */ -+ tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | -+ DOC_MODE_BDECT; -+ WriteDOC(tmp, window, Mplus_DOCControl); -+ WriteDOC(~tmp, window, Mplus_CtrlConfirm); -+ mdelay(1); -+#endif /* !DOC_PASSIVE_PROBE */ -+ -+ ChipID = ReadDOC(window, ChipID); -+ -+ switch (ChipID) { -+ case DOC_ChipID_DocMilPlus16: -+ case DOC_ChipID_DocMilPlus32: -+ /* Check the TOGGLE bit in the toggle register */ -+ tmp = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT; -+ tmpb = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT; -+ tmpc = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT; -+ if (tmp != tmpb && tmp == tmpc) - return ChipID; -+ default: - break; -+ } -+ /* FALL TRHU */ - - default: --#ifndef CONFIG_MTD_DOCPROBE_55AA -- printk(KERN_WARNING "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n", -+ -+#ifdef CONFIG_MTD_DOCPROBE_55AA -+ printk(KERN_DEBUG "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n", - ChipID, physadr); - #endif - #ifndef DOC_PASSIVE_PROBE -@@ -200,6 +249,12 @@ - return; - - if ((ChipID = doccheck(docptr, physadr))) { -+ if (ChipID == DOC_ChipID_Doc2kTSOP) { -+ /* Remove this at your own peril. The hardware driver works but nothing prevents you from erasing bad blocks */ -+ printk(KERN_NOTICE "Refusing to drive DiskOnChip 2000 TSOP until Bad Block Table is correctly supported by INFTL\n"); -+ iounmap((void *)docptr); -+ return; -+ } - docfound = 1; - mtd = kmalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL); - -@@ -221,6 +276,12 @@ - sprintf(namebuf, "with ChipID %2.2X", ChipID); - - switch(ChipID) { -+ case DOC_ChipID_Doc2kTSOP: -+ name="2000 TSOP"; -+ im_funcname = "DoC2k_init"; -+ im_modname = "doc2000"; -+ break; -+ - case DOC_ChipID_Doc2k: - name="2000"; - im_funcname = "DoC2k_init"; -@@ -237,6 +298,13 @@ - im_modname = "doc2001"; - #endif /* DOC_SINGLE_DRIVER */ - break; -+ -+ case DOC_ChipID_DocMilPlus16: -+ case DOC_ChipID_DocMilPlus32: -+ name="MillenniumPlus"; -+ im_funcname = "DoCMilPlus_init"; -+ im_modname = "doc2001plus"; -+ break; - } - - if (im_funcname) -@@ -248,6 +316,7 @@ - return; - } - printk(KERN_NOTICE "Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr); -+ kfree(mtd); - } - iounmap((void *)docptr); - } -@@ -267,7 +336,7 @@ - printk(KERN_INFO "Using configured DiskOnChip probe address 0x%lx\n", doc_config_location); - DoC_Probe(doc_config_location); - } else { -- for (i=0; doc_locations[i]; i++) { -+ for (i=0; (doc_locations[i] != 0xffffffff); i++) { - DoC_Probe(doc_locations[i]); - } - } -@@ -275,11 +344,7 @@ - found, so the user knows we at least tried. */ - if (!docfound) - printk(KERN_INFO "No recognised DiskOnChip devices found\n"); -- /* So it looks like we've been used and we get unloaded */ -- MOD_INC_USE_COUNT; -- MOD_DEC_USE_COUNT; -- return 0; -- -+ return -EAGAIN; - } - - module_init(init_doc); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/lart.c linux/drivers/mtd/devices/lart.c ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/lart.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/devices/lart.c 2004-11-17 18:17:59.022316504 +0100 -@@ -2,7 +2,7 @@ - /* - * MTD driver for the 28F160F3 Flash Memory (non-CFI) on LART. - * -- * $Id$ -+ * $Id$ - * - * Author: Abraham vd Merwe - * -@@ -584,45 +584,40 @@ - - static struct mtd_info mtd; - --static struct mtd_erase_region_info erase_regions[] = --{ -+static struct mtd_erase_region_info erase_regions[] = { - /* parameter blocks */ - { -- offset: 0x00000000, -- erasesize: FLASH_BLOCKSIZE_PARAM, -- numblocks: FLASH_NUMBLOCKS_16m_PARAM -+ .offset = 0x00000000, -+ .erasesize = FLASH_BLOCKSIZE_PARAM, -+ .numblocks = FLASH_NUMBLOCKS_16m_PARAM, - }, - /* main blocks */ - { -- offset: FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM, -- erasesize: FLASH_BLOCKSIZE_MAIN, -- numblocks: FLASH_NUMBLOCKS_16m_MAIN -+ .offset = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM, -+ .erasesize = FLASH_BLOCKSIZE_MAIN, -+ .numblocks = FLASH_NUMBLOCKS_16m_MAIN, - } - }; - - #ifdef HAVE_PARTITIONS --static struct mtd_partition lart_partitions[] = --{ -+static struct mtd_partition lart_partitions[] = { - /* blob */ - { -- name: "blob", -- offset: BLOB_START, -- size: BLOB_LEN, -- mask_flags: 0 -+ .name = "blob", -+ .offset = BLOB_START, -+ .size = BLOB_LEN, - }, - /* kernel */ - { -- name: "kernel", -- offset: KERNEL_START, /* MTDPART_OFS_APPEND */ -- size: KERNEL_LEN, -- mask_flags: 0 -+ .name = "kernel", -+ .offset = KERNEL_START, /* MTDPART_OFS_APPEND */ -+ .size = KERNEL_LEN, - }, - /* initial ramdisk / file system */ - { -- name: "file system", -- offset: INITRD_START, /* MTDPART_OFS_APPEND */ -- size: INITRD_LEN, /* MTDPART_SIZ_FULL */ -- mask_flags: 0 -+ .name = "file system", -+ .offset = INITRD_START, /* MTDPART_OFS_APPEND */ -+ .size = INITRD_LEN, /* MTDPART_SIZ_FULL */ - } - }; - #endif -@@ -646,10 +641,10 @@ - mtd.erasesize = FLASH_BLOCKSIZE_MAIN; - mtd.numeraseregions = NB_OF (erase_regions); - mtd.eraseregions = erase_regions; -- mtd.module = THIS_MODULE; - mtd.erase = flash_erase; - mtd.read = flash_read; - mtd.write = flash_write; -+ mtd.owner = THIS_MODULE; - - #ifdef LART_DEBUG - printk (KERN_DEBUG -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/ms02-nv.c linux/drivers/mtd/devices/ms02-nv.c ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/ms02-nv.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/devices/ms02-nv.c 2004-11-17 18:17:59.023316352 +0100 -@@ -6,7 +6,7 @@ - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * -- * $Id$ -+ * $Id$ - */ - - #include -@@ -38,9 +38,9 @@ - - /* - * Addresses we probe for an MS02-NV at. Modules may be located -- * at any 8MB boundary within a 0MB up to 112MB range or at any 32MB -- * boundary within a 0MB up to 448MB range. We don't support a module -- * at 0MB, though. -+ * at any 8MiB boundary within a 0MiB up to 112MiB range or at any 32MiB -+ * boundary within a 0MiB up to 448MiB range. We don't support a module -+ * at 0MiB, though. - */ - static ulong ms02nv_addrs[] __initdata = { - 0x07000000, 0x06800000, 0x06000000, 0x05800000, 0x05000000, -@@ -130,7 +130,7 @@ - - int ret = -ENODEV; - -- /* The module decodes 8MB of address space. */ -+ /* The module decodes 8MiB of address space. */ - mod_res = kmalloc(sizeof(*mod_res), GFP_KERNEL); - if (!mod_res) - return -ENOMEM; -@@ -222,7 +222,7 @@ - mtd->flags = MTD_CAP_RAM | MTD_XIP; - mtd->size = fixsize; - mtd->name = (char *)ms02nv_name; -- mtd->module = THIS_MODULE; -+ mtd->owner = THIS_MODULE; - mtd->read = ms02nv_read; - mtd->write = ms02nv_write; - -@@ -233,7 +233,7 @@ - goto err_out_csr_res; - } - -- printk(KERN_INFO "mtd%d: %s at 0x%08lx, size %uMB.\n", -+ printk(KERN_INFO "mtd%d: %s at 0x%08lx, size %uMiB.\n", - mtd->index, ms02nv_name, addr, size >> 20); - - mp->next = root_ms02nv_mtd; -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/ms02-nv.h linux/drivers/mtd/devices/ms02-nv.h ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/ms02-nv.h 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/devices/ms02-nv.h 2004-11-17 18:17:59.025316048 +0100 -@@ -9,6 +9,8 @@ - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. -+ * -+ * $Id$ - */ - - #include -@@ -39,8 +41,8 @@ - * The diagnostic area defines two status words to be read by an - * operating system, a magic ID to distinguish a MS02-NV board from - * anything else and a status information providing results of tests -- * as well as the size of SRAM available, which can be 1MB or 2MB -- * (that's what the firmware handles; no idea if 2MB modules ever -+ * as well as the size of SRAM available, which can be 1MiB or 2MiB -+ * (that's what the firmware handles; no idea if 2MiB modules ever - * existed). - * - * The firmware only handles the MS02-NV board if installed in the -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/mtdram.c linux/drivers/mtd/devices/mtdram.c ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/mtdram.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/devices/mtdram.c 2004-11-17 18:17:59.040313768 +0100 -@@ -1,6 +1,6 @@ - /* - * mtdram - a test mtd device -- * $Id$ -+ * $Id$ - * Author: Alexander Larsson - * - * Copyright (c) 1999 Alexander Larsson -@@ -13,6 +13,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - -@@ -136,7 +138,7 @@ - mtd->erasesize = MTDRAM_ERASE_SIZE; - mtd->priv = mapped_address; - -- mtd->module = THIS_MODULE; -+ mtd->owner = THIS_MODULE; - mtd->erase = ram_erase; - mtd->point = ram_point; - mtd->unpoint = ram_unpoint; -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/phram.c linux/drivers/mtd/devices/phram.c ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/phram.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/devices/phram.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,362 @@ -+/** -+ * -+ * $Id$ -+ * -+ * Copyright (c) Jochen Schaeuble -+ * 07/2003 rewritten by Joern Engel -+ * -+ * DISCLAIMER: This driver makes use of Rusty's excellent module code, -+ * so it will not work for 2.4 without changes and it wont work for 2.4 -+ * as a module without major changes. Oh well! -+ * -+ * Usage: -+ * -+ * one commend line parameter per device, each in the form: -+ * phram=,, -+ * may be up to 63 characters. -+ * and can be octal, decimal or hexadecimal. If followed -+ * by "k", "M" or "G", the numbers will be interpreted as kilo, mega or -+ * gigabytes. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define ERROR(fmt, args...) printk(KERN_ERR "phram: " fmt , ## args) -+ -+struct phram_mtd_list { -+ struct list_head list; -+ struct mtd_info *mtdinfo; -+}; -+ -+static LIST_HEAD(phram_list); -+ -+ -+ -+int phram_erase(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ u_char *start = (u_char *)mtd->priv; -+ -+ if (instr->addr + instr->len > mtd->size) -+ return -EINVAL; -+ -+ memset(start + instr->addr, 0xff, instr->len); -+ -+ /* This'll catch a few races. Free the thing before returning :) -+ * I don't feel at all ashamed. This kind of thing is possible anyway -+ * with flash, but unlikely. -+ */ -+ -+ instr->state = MTD_ERASE_DONE; -+ -+ if (instr->callback) -+ (*(instr->callback))(instr); -+ else -+ kfree(instr); -+ -+ return 0; -+} -+ -+int phram_point(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char **mtdbuf) -+{ -+ u_char *start = (u_char *)mtd->priv; -+ -+ if (from + len > mtd->size) -+ return -EINVAL; -+ -+ *mtdbuf = start + from; -+ *retlen = len; -+ return 0; -+} -+ -+void phram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) -+{ -+} -+ -+int phram_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ u_char *start = (u_char *)mtd->priv; -+ -+ if (from + len > mtd->size) -+ return -EINVAL; -+ -+ memcpy(buf, start + from, len); -+ -+ *retlen = len; -+ return 0; -+} -+ -+int phram_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ u_char *start = (u_char *)mtd->priv; -+ -+ if (to + len > mtd->size) -+ return -EINVAL; -+ -+ memcpy(start + to, buf, len); -+ -+ *retlen = len; -+ return 0; -+} -+ -+ -+ -+static void unregister_devices(void) -+{ -+ struct phram_mtd_list *this; -+ -+ list_for_each_entry(this, &phram_list, list) { -+ del_mtd_device(this->mtdinfo); -+ iounmap(this->mtdinfo->priv); -+ kfree(this->mtdinfo); -+ kfree(this); -+ } -+} -+ -+static int register_device(char *name, unsigned long start, unsigned long len) -+{ -+ struct phram_mtd_list *new; -+ int ret = -ENOMEM; -+ -+ new = kmalloc(sizeof(*new), GFP_KERNEL); -+ if (!new) -+ goto out0; -+ -+ new->mtdinfo = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); -+ if (!new->mtdinfo) -+ goto out1; -+ -+ memset(new->mtdinfo, 0, sizeof(struct mtd_info)); -+ -+ ret = -EIO; -+ new->mtdinfo->priv = ioremap(start, len); -+ if (!new->mtdinfo->priv) { -+ ERROR("ioremap failed\n"); -+ goto out2; -+ } -+ -+ -+ new->mtdinfo->name = name; -+ new->mtdinfo->size = len; -+ new->mtdinfo->flags = MTD_CAP_RAM | MTD_ERASEABLE | MTD_VOLATILE; -+ new->mtdinfo->erase = phram_erase; -+ new->mtdinfo->point = phram_point; -+ new->mtdinfo->unpoint = phram_unpoint; -+ new->mtdinfo->read = phram_read; -+ new->mtdinfo->write = phram_write; -+ new->mtdinfo->owner = THIS_MODULE; -+ new->mtdinfo->type = MTD_RAM; -+ new->mtdinfo->erasesize = 0x0; -+ -+ ret = -EAGAIN; -+ if (add_mtd_device(new->mtdinfo)) { -+ ERROR("Failed to register new device\n"); -+ goto out3; -+ } -+ -+ list_add_tail(&new->list, &phram_list); -+ return 0; -+ -+out3: -+ iounmap(new->mtdinfo->priv); -+out2: -+ kfree(new->mtdinfo); -+out1: -+ kfree(new); -+out0: -+ return ret; -+} -+ -+static int ustrtoul(const char *cp, char **endp, unsigned int base) -+{ -+ unsigned long result = simple_strtoul(cp, endp, base); -+ -+ switch (**endp) { -+ case 'G': -+ result *= 1024; -+ case 'M': -+ result *= 1024; -+ case 'k': -+ result *= 1024; -+ endp++; -+ } -+ return result; -+} -+ -+static int parse_num32(uint32_t *num32, const char *token) -+{ -+ char *endp; -+ unsigned long n; -+ -+ n = ustrtoul(token, &endp, 0); -+ if (*endp) -+ return -EINVAL; -+ -+ *num32 = n; -+ return 0; -+} -+ -+static int parse_name(char **pname, const char *token) -+{ -+ size_t len; -+ char *name; -+ -+ len = strlen(token) + 1; -+ if (len > 64) -+ return -ENOSPC; -+ -+ name = kmalloc(len, GFP_KERNEL); -+ if (!name) -+ return -ENOMEM; -+ -+ strcpy(name, token); -+ -+ *pname = name; -+ return 0; -+} -+ -+#define parse_err(fmt, args...) do { \ -+ ERROR(fmt , ## args); \ -+ return 0; \ -+} while (0) -+ -+static int phram_setup(const char *val, struct kernel_param *kp) -+{ -+ char buf[64+12+12], *str = buf; -+ char *token[3]; -+ char *name; -+ uint32_t start; -+ uint32_t len; -+ int i, ret; -+ -+ if (strnlen(val, sizeof(str)) >= sizeof(str)) -+ parse_err("parameter too long\n"); -+ -+ strcpy(str, val); -+ -+ for (i=0; i<3; i++) -+ token[i] = strsep(&str, ","); -+ -+ if (str) -+ parse_err("too many arguments\n"); -+ -+ if (!token[2]) -+ parse_err("not enough arguments\n"); -+ -+ ret = parse_name(&name, token[0]); -+ if (ret == -ENOMEM) -+ parse_err("out of memory\n"); -+ if (ret == -ENOSPC) -+ parse_err("name too long\n"); -+ if (ret) -+ return 0; -+ -+ ret = parse_num32(&start, token[1]); -+ if (ret) -+ parse_err("illegal start address\n"); -+ -+ ret = parse_num32(&len, token[2]); -+ if (ret) -+ parse_err("illegal device length\n"); -+ -+ register_device(name, start, len); -+ -+ return 0; -+} -+ -+module_param_call(phram, phram_setup, NULL, NULL, 000); -+MODULE_PARM_DESC(phram, "Memory region to map. \"map=,\""); -+ -+/* -+ * Just for compatibility with slram, this is horrible and should go someday. -+ */ -+static int __init slram_setup(const char *val, struct kernel_param *kp) -+{ -+ char buf[256], *str = buf; -+ -+ if (!val || !val[0]) -+ parse_err("no arguments to \"slram=\"\n"); -+ -+ if (strnlen(val, sizeof(str)) >= sizeof(str)) -+ parse_err("parameter too long\n"); -+ -+ strcpy(str, val); -+ -+ while (str) { -+ char *token[3]; -+ char *name; -+ uint32_t start; -+ uint32_t len; -+ int i, ret; -+ -+ for (i=0; i<3; i++) { -+ token[i] = strsep(&str, ","); -+ if (token[i]) -+ continue; -+ parse_err("wrong number of arguments to \"slram=\"\n"); -+ } -+ -+ /* name */ -+ ret = parse_name(&name, token[0]); -+ if (ret == -ENOMEM) -+ parse_err("of memory\n"); -+ if (ret == -ENOSPC) -+ parse_err("too long\n"); -+ if (ret) -+ return 1; -+ -+ /* start */ -+ ret = parse_num32(&start, token[1]); -+ if (ret) -+ parse_err("illegal start address\n"); -+ -+ /* len */ -+ if (token[2][0] == '+') -+ ret = parse_num32(&len, token[2] + 1); -+ else -+ ret = parse_num32(&len, token[2]); -+ -+ if (ret) -+ parse_err("illegal device length\n"); -+ -+ if (token[2][0] != '+') { -+ if (len < start) -+ parse_err("end < start\n"); -+ len -= start; -+ } -+ -+ register_device(name, start, len); -+ } -+ return 1; -+} -+ -+module_param_call(slram, slram_setup, NULL, NULL, 000); -+MODULE_PARM_DESC(slram, "List of memory regions to map. \"map=,\""); -+ -+ -+int __init init_phram(void) -+{ -+ printk(KERN_ERR "phram loaded\n"); -+ return 0; -+} -+ -+static void __exit cleanup_phram(void) -+{ -+ unregister_devices(); -+} -+ -+module_init(init_phram); -+module_exit(cleanup_phram); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jörn Engel "); -+MODULE_DESCRIPTION("MTD driver for physical RAM"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/pmc551.c linux/drivers/mtd/devices/pmc551.c ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/pmc551.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/devices/pmc551.c 2004-11-17 18:17:59.043313312 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * PMC551 PCI Mezzanine Ram Device - * -@@ -681,11 +681,6 @@ - - printk(KERN_INFO PMC551_VERSION); - -- if(!pci_present()) { -- printk(KERN_NOTICE "pmc551: PCI not enabled.\n"); -- return -ENODEV; -- } -- - /* - * PCU-bus chipset probe. - */ -@@ -787,10 +782,10 @@ - mtd->write = pmc551_write; - mtd->point = pmc551_point; - mtd->unpoint = pmc551_unpoint; -- mtd->module = THIS_MODULE; - mtd->type = MTD_RAM; - mtd->name = "PMC551 RAM board"; - mtd->erasesize = 0x10000; -+ mtd->owner = THIS_MODULE; - - if (add_mtd_device(mtd)) { - printk(KERN_NOTICE "pmc551: Failed to register new device\n"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/devices/slram.c linux/drivers/mtd/devices/slram.c ---- linux-mips-2.4.24-pre2/drivers/mtd/devices/slram.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/devices/slram.c 2004-11-17 18:17:59.044313160 +0100 -@@ -1,6 +1,6 @@ - /*====================================================================== - -- $Id$ -+ $Id$ - - This driver provides a method to access memory not used by the kernel - itself (i.e. if the kernel commandline mem=xxx is used). To actually -@@ -199,7 +199,7 @@ - (*curmtd)->mtdinfo->unpoint = slram_unpoint; - (*curmtd)->mtdinfo->read = slram_read; - (*curmtd)->mtdinfo->write = slram_write; -- (*curmtd)->mtdinfo->module = THIS_MODULE; -+ (*curmtd)->mtdinfo->owner = THIS_MODULE; - (*curmtd)->mtdinfo->type = MTD_RAM; - (*curmtd)->mtdinfo->erasesize = 0x0; - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/ftl.c linux/drivers/mtd/ftl.c ---- linux-mips-2.4.24-pre2/drivers/mtd/ftl.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/ftl.c 2004-11-17 18:17:58.837344624 +0100 -@@ -1,5 +1,5 @@ - /* This version ported to the Linux-MTD system by dwmw2@infradead.org -- * $Id$ -+ * $Id$ - * - * Fixes: Arnaldo Carvalho de Melo - * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups -@@ -55,8 +55,8 @@ - contact M-Systems (http://www.m-sys.com) directly. - - ======================================================================*/ -+#include - #include --#include - #include - /*#define PSYCHO_DEBUG */ - -@@ -68,43 +68,13 @@ - #include - #include - #include --#include -+#include - #include -- --#if (LINUX_VERSION_CODE >= 0x20100) - #include --#endif --#if (LINUX_VERSION_CODE >= 0x20303) - #include --#endif -+#include - - #include --/*====================================================================*/ --/* Stuff which really ought to be in compatmac.h */ -- --#if (LINUX_VERSION_CODE < 0x20328) --#define register_disk(dev, drive, minors, ops, size) \ -- do { (dev)->part[(drive)*(minors)].nr_sects = size; \ -- if (size == 0) (dev)->part[(drive)*(minors)].start_sect = -1; \ -- resetup_one_dev(dev, drive); } while (0) --#endif -- --#if (LINUX_VERSION_CODE < 0x20320) --#define BLK_DEFAULT_QUEUE(n) blk_dev[n].request_fn --#define blk_init_queue(q, req) q = (req) --#define blk_cleanup_queue(q) q = NULL --#define request_arg_t void --#else --#define request_arg_t request_queue_t *q --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14) --#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT --#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT --#else --#define BLK_INC_USE_COUNT do {} while(0) --#define BLK_DEC_USE_COUNT do {} while(0) --#endif - - /*====================================================================*/ - -@@ -119,19 +89,6 @@ - #define FTL_MAJOR 44 - #endif - --/* Funky stuff for setting up a block device */ --#define MAJOR_NR FTL_MAJOR --#define DEVICE_NAME "ftl" --#define DEVICE_REQUEST do_ftl_request --#define DEVICE_ON(device) --#define DEVICE_OFF(device) -- --#define DEVICE_NR(minor) ((minor)>>5) --#define REGION_NR(minor) (((minor)>>3)&3) --#define PART_NR(minor) ((minor)&7) --#define MINOR_NR(dev,reg,part) (((dev)<<5)+((reg)<<3)+(part)) -- --#include - - /*====================================================================*/ - -@@ -142,8 +99,7 @@ - #define MAX_REGION 4 - - /* Maximum number of partitions in an FTL region */ --#define PART_BITS 3 --#define MAX_PART 8 -+#define PART_BITS 4 - - /* Maximum number of outstanding erase requests per socket */ - #define MAX_ERASE 8 -@@ -154,7 +110,7 @@ - - /* Each memory region corresponds to a minor device */ - typedef struct partition_t { -- struct mtd_info *mtd; -+ struct mtd_blktrans_dev mbd; - u_int32_t state; - u_int32_t *VirtualBlockMap; - u_int32_t *VirtualPageMap; -@@ -179,21 +135,10 @@ - region_info_t region; - memory_handle_t handle; - #endif -- atomic_t open; - } partition_t; - --partition_t *myparts[MAX_MTD_DEVICES]; -- --static void ftl_notify_add(struct mtd_info *mtd); --static void ftl_notify_remove(struct mtd_info *mtd); -- - void ftl_freepart(partition_t *part); - --static struct mtd_notifier ftl_notifier = { -- add: ftl_notify_add, -- remove: ftl_notify_remove, --}; -- - /* Partition state flags */ - #define FTL_FORMATTED 0x01 - -@@ -204,51 +149,11 @@ - #define XFER_PREPARED 0x03 - #define XFER_FAILED 0x04 - --static struct hd_struct ftl_hd[MINOR_NR(MAX_DEV, 0, 0)]; --static int ftl_sizes[MINOR_NR(MAX_DEV, 0, 0)]; --static int ftl_blocksizes[MINOR_NR(MAX_DEV, 0, 0)]; -- --static struct gendisk ftl_gendisk = { -- major: FTL_MAJOR, -- major_name: "ftl", -- minor_shift: PART_BITS, -- max_p: MAX_PART, --#if (LINUX_VERSION_CODE < 0x20328) -- max_nr: MAX_DEV*MAX_PART, --#endif -- part: ftl_hd, -- sizes: ftl_sizes, --}; -- - /*====================================================================*/ - --static int ftl_ioctl(struct inode *inode, struct file *file, -- u_int cmd, u_long arg); --static int ftl_open(struct inode *inode, struct file *file); --static release_t ftl_close(struct inode *inode, struct file *file); --static int ftl_reread_partitions(int minor); - - static void ftl_erase_callback(struct erase_info *done); - --#if LINUX_VERSION_CODE < 0x20326 --static struct file_operations ftl_blk_fops = { -- open: ftl_open, -- release: ftl_close, -- ioctl: ftl_ioctl, -- read: block_read, -- write: block_write, -- fsync: block_fsync --}; --#else --static struct block_device_operations ftl_blk_fops = { --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14) -- owner: THIS_MODULE, --#endif -- open: ftl_open, -- release: ftl_close, -- ioctl: ftl_ioctl, --}; --#endif - - /*====================================================================== - -@@ -264,13 +169,13 @@ - loff_t offset, max_offset; - int ret; - part->header.FormattedSize = 0; -- max_offset = (0x100000mtd->size)?0x100000:part->mtd->size; -+ max_offset = (0x100000mbd.mtd->size)?0x100000:part->mbd.mtd->size; - /* Search first megabyte for a valid FTL header */ - for (offset = 0; - (offset + sizeof(header)) < max_offset; -- offset += part->mtd->erasesize ? : 0x2000) { -+ offset += part->mbd.mtd->erasesize ? : 0x2000) { - -- ret = part->mtd->read(part->mtd, offset, sizeof(header), &ret, -+ ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &ret, - (unsigned char *)&header); - - if (ret) -@@ -283,15 +188,15 @@ - printk(KERN_NOTICE "ftl_cs: FTL header not found.\n"); - return -ENOENT; - } -- if ((le16_to_cpu(header.NumEraseUnits) > 65536) || header.BlockSize != 9 || -+ if (header.BlockSize != 9 || - (header.EraseUnitSize < 10) || (header.EraseUnitSize > 31) || - (header.NumTransferUnits >= le16_to_cpu(header.NumEraseUnits))) { - printk(KERN_NOTICE "ftl_cs: FTL header corrupt!\n"); - return -1; - } -- if ((1 << header.EraseUnitSize) != part->mtd->erasesize) { -+ if ((1 << header.EraseUnitSize) != part->mbd.mtd->erasesize) { - printk(KERN_NOTICE "ftl: FTL EraseUnitSize %x != MTD erasesize %x\n", -- 1 << header.EraseUnitSize,part->mtd->erasesize); -+ 1 << header.EraseUnitSize,part->mbd.mtd->erasesize); - return -1; - } - part->header = header; -@@ -326,7 +231,7 @@ - for (i = 0; i < le16_to_cpu(part->header.NumEraseUnits); i++) { - offset = ((i + le16_to_cpu(part->header.FirstPhysicalEUN)) - << part->header.EraseUnitSize); -- ret = part->mtd->read(part->mtd, offset, sizeof(header), &retval, -+ ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &retval, - (unsigned char *)&header); - - if (ret) -@@ -391,7 +296,7 @@ - part->EUNInfo[i].Deleted = 0; - offset = part->EUNInfo[i].Offset + le32_to_cpu(header.BAMOffset); - -- ret = part->mtd->read(part->mtd, offset, -+ ret = part->mbd.mtd->read(part->mbd.mtd, offset, - part->BlocksPerUnit * sizeof(u_int32_t), &retval, - (unsigned char *)part->bam_cache); - -@@ -456,7 +361,7 @@ - erase->len = 1 << part->header.EraseUnitSize; - erase->priv = (u_long)part; - -- ret = part->mtd->erase(part->mtd, erase); -+ ret = part->mbd.mtd->erase(part->mbd.mtd, erase); - - if (!ret) - xfer->EraseCount++; -@@ -523,7 +428,7 @@ - header.LogicalEUN = cpu_to_le16(0xffff); - header.EraseCount = cpu_to_le32(xfer->EraseCount); - -- ret = part->mtd->write(part->mtd, xfer->Offset, sizeof(header), -+ ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset, sizeof(header), - &retlen, (u_char *)&header); - - if (ret) { -@@ -539,7 +444,7 @@ - - for (i = 0; i < nbam; i++, offset += sizeof(u_int32_t)) { - -- ret = part->mtd->write(part->mtd, offset, sizeof(u_int32_t), -+ ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t), - &retlen, (u_char *)&ctl); - - if (ret) -@@ -586,7 +491,7 @@ - - offset = eun->Offset + le32_to_cpu(part->header.BAMOffset); - -- ret = part->mtd->read(part->mtd, offset, -+ ret = part->mbd.mtd->read(part->mbd.mtd, offset, - part->BlocksPerUnit * sizeof(u_int32_t), - &retlen, (u_char *) (part->bam_cache)); - -@@ -604,7 +509,7 @@ - offset = xfer->Offset + 20; /* Bad! */ - unit = cpu_to_le16(0x7fff); - -- ret = part->mtd->write(part->mtd, offset, sizeof(u_int16_t), -+ ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int16_t), - &retlen, (u_char *) &unit); - - if (ret) { -@@ -624,7 +529,7 @@ - break; - case BLOCK_DATA: - case BLOCK_REPLACEMENT: -- ret = part->mtd->read(part->mtd, src, SECTOR_SIZE, -+ ret = part->mbd.mtd->read(part->mbd.mtd, src, SECTOR_SIZE, - &retlen, (u_char *) buf); - if (ret) { - printk(KERN_WARNING "ftl: Error reading old xfer unit in copy_erase_unit\n"); -@@ -632,7 +537,7 @@ - } - - -- ret = part->mtd->write(part->mtd, dest, SECTOR_SIZE, -+ ret = part->mbd.mtd->write(part->mbd.mtd, dest, SECTOR_SIZE, - &retlen, (u_char *) buf); - if (ret) { - printk(KERN_WARNING "ftl: Error writing new xfer unit in copy_erase_unit\n"); -@@ -651,7 +556,7 @@ - } - - /* Write the BAM to the transfer unit */ -- ret = part->mtd->write(part->mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset), -+ ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset), - part->BlocksPerUnit * sizeof(int32_t), &retlen, - (u_char *)part->bam_cache); - if (ret) { -@@ -661,7 +566,7 @@ - - - /* All clear? Then update the LogicalEUN again */ -- ret = part->mtd->write(part->mtd, xfer->Offset + 20, sizeof(u_int16_t), -+ ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + 20, sizeof(u_int16_t), - &retlen, (u_char *)&srcunitswap); - - if (ret) { -@@ -749,8 +654,8 @@ - if (queued) { - DEBUG(1, "ftl_cs: waiting for transfer " - "unit to be prepared...\n"); -- if (part->mtd->sync) -- part->mtd->sync(part->mtd); -+ if (part->mbd.mtd->sync) -+ part->mbd.mtd->sync(part->mbd.mtd); - } else { - static int ne = 0; - if (++ne < 5) -@@ -848,7 +753,7 @@ - /* Invalidate cache */ - part->bam_index = 0xffff; - -- ret = part->mtd->read(part->mtd, -+ ret = part->mbd.mtd->read(part->mbd.mtd, - part->EUNInfo[eun].Offset + le32_to_cpu(part->header.BAMOffset), - part->BlocksPerUnit * sizeof(u_int32_t), - &retlen, (u_char *) (part->bam_cache)); -@@ -877,78 +782,6 @@ - - } /* find_free */ - --/*====================================================================== -- -- This gets a memory handle for the region corresponding to the -- minor device number. -- --======================================================================*/ -- --static int ftl_open(struct inode *inode, struct file *file) --{ -- int minor = MINOR(inode->i_rdev); -- partition_t *partition; -- -- if (minor>>4 >= MAX_MTD_DEVICES) -- return -ENODEV; -- -- partition = myparts[minor>>4]; -- -- if (!partition) -- return -ENODEV; -- -- if (partition->state != FTL_FORMATTED) -- return -ENXIO; -- -- if (ftl_gendisk.part[minor].nr_sects == 0) -- return -ENXIO; -- -- BLK_INC_USE_COUNT; -- -- if (!get_mtd_device(partition->mtd, -1)) { -- BLK_DEC_USE_COUNT; -- return -ENXIO; -- } -- -- if ((file->f_mode & 2) && !(partition->mtd->flags & MTD_CLEAR_BITS) ) { -- put_mtd_device(partition->mtd); -- BLK_DEC_USE_COUNT; -- return -EROFS; -- } -- -- DEBUG(0, "ftl_cs: ftl_open(%d)\n", minor); -- -- atomic_inc(&partition->open); -- -- return 0; --} -- --/*====================================================================*/ -- --static release_t ftl_close(struct inode *inode, struct file *file) --{ -- int minor = MINOR(inode->i_rdev); -- partition_t *part = myparts[minor >> 4]; -- int i; -- -- DEBUG(0, "ftl_cs: ftl_close(%d)\n", minor); -- -- /* Wait for any pending erase operations to complete */ -- if (part->mtd->sync) -- part->mtd->sync(part->mtd); -- -- for (i = 0; i < part->header.NumTransferUnits; i++) { -- if (part->XferInfo[i].state == XFER_ERASED) -- prepare_xfer(part, i); -- } -- -- atomic_dec(&part->open); -- -- put_mtd_device(part->mtd); -- BLK_DEC_USE_COUNT; -- release_return(0); --} /* ftl_close */ -- - - /*====================================================================== - -@@ -983,7 +816,7 @@ - else { - offset = (part->EUNInfo[log_addr / bsize].Offset - + (log_addr % bsize)); -- ret = part->mtd->read(part->mtd, offset, SECTOR_SIZE, -+ ret = part->mbd.mtd->read(part->mbd.mtd, offset, SECTOR_SIZE, - &retlen, (u_char *) buffer); - - if (ret) { -@@ -1022,7 +855,7 @@ - le32_to_cpu(part->header.BAMOffset)); - - #ifdef PSYCHO_DEBUG -- ret = part->mtd->read(part->mtd, offset, sizeof(u_int32_t), -+ ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(u_int32_t), - &retlen, (u_char *)&old_addr); - if (ret) { - printk(KERN_WARNING"ftl: Error reading old_addr in set_bam_entry: %d\n",ret); -@@ -1059,7 +892,7 @@ - #endif - part->bam_cache[blk] = le_virt_addr; - } -- ret = part->mtd->write(part->mtd, offset, sizeof(u_int32_t), -+ ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t), - &retlen, (u_char *)&le_virt_addr); - - if (ret) { -@@ -1119,7 +952,7 @@ - part->EUNInfo[part->bam_index].Deleted++; - offset = (part->EUNInfo[part->bam_index].Offset + - blk * SECTOR_SIZE); -- ret = part->mtd->write(part->mtd, offset, SECTOR_SIZE, &retlen, -+ ret = part->mbd.mtd->write(part->mbd.mtd, offset, SECTOR_SIZE, &retlen, - buffer); - - if (ret) { -@@ -1151,164 +984,32 @@ - return 0; - } /* ftl_write */ - --/*====================================================================== -- -- IOCTL calls for getting device parameters. -- --======================================================================*/ -- --static int ftl_ioctl(struct inode *inode, struct file *file, -- u_int cmd, u_long arg) -+static int ftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) - { -- struct hd_geometry *geo = (struct hd_geometry *)arg; -- int ret = 0, minor = MINOR(inode->i_rdev); -- partition_t *part= myparts[minor >> 4]; -+ partition_t *part = (void *)dev; - u_long sect; - -- if (!part) -- return -ENODEV; /* How? */ -- -- switch (cmd) { -- case HDIO_GETGEO: -- ret = verify_area(VERIFY_WRITE, (long *)arg, sizeof(*geo)); -- if (ret) return ret; -- /* Sort of arbitrary: round size down to 4K boundary */ -+ /* Sort of arbitrary: round size down to 4KiB boundary */ - sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE; -- put_user(1, (char *)&geo->heads); -- put_user(8, (char *)&geo->sectors); -- put_user((sect>>3), (short *)&geo->cylinders); -- put_user(ftl_hd[minor].start_sect, (u_long *)&geo->start); -- break; -- case BLKGETSIZE: -- ret = put_user(ftl_hd[minor].nr_sects, (unsigned long *)arg); -- break; --#ifdef BLKGETSIZE64 -- case BLKGETSIZE64: -- ret = put_user((u64)ftl_hd[minor].nr_sects << 9, (u64 *)arg); -- break; --#endif -- case BLKRRPART: -- ret = ftl_reread_partitions(minor); -- break; --#if (LINUX_VERSION_CODE < 0x20303) -- case BLKFLSBUF: --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) -- if (!capable(CAP_SYS_ADMIN)) return -EACCES; --#endif -- fsync_dev(inode->i_rdev); -- invalidate_buffers(inode->i_rdev); -- break; -- RO_IOCTLS(inode->i_rdev, arg); --#else -- case BLKROSET: -- case BLKROGET: -- case BLKFLSBUF: -- ret = blk_ioctl(inode->i_rdev, cmd, arg); -- break; --#endif -- default: -- ret = -EINVAL; -- } -- -- return ret; --} /* ftl_ioctl */ -- --/*====================================================================== - -- Handler for block device requests -+ geo->heads = 1; -+ geo->sectors = 8; -+ geo->cylinders = sect >> 3; - --======================================================================*/ -- --static int ftl_reread_partitions(int minor) --{ -- partition_t *part = myparts[minor >> 4]; -- int i, whole; -- -- DEBUG(0, "ftl_cs: ftl_reread_partition(%d)\n", minor); -- if ((atomic_read(&part->open) > 1)) { -- return -EBUSY; -- } -- whole = minor & ~(MAX_PART-1); -- -- i = MAX_PART - 1; -- while (i-- > 0) { -- if (ftl_hd[whole+i].nr_sects > 0) { -- kdev_t rdev = MKDEV(FTL_MAJOR, whole+i); -- -- invalidate_device(rdev, 1); -- } -- ftl_hd[whole+i].start_sect = 0; -- ftl_hd[whole+i].nr_sects = 0; -- } -- -- scan_header(part); -- -- register_disk(&ftl_gendisk, whole >> PART_BITS, MAX_PART, -- &ftl_blk_fops, le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE); -- --#ifdef PCMCIA_DEBUG -- for (i = 0; i < MAX_PART; i++) { -- if (ftl_hd[whole+i].nr_sects > 0) -- printk(KERN_INFO " %d: start %ld size %ld\n", i, -- ftl_hd[whole+i].start_sect, -- ftl_hd[whole+i].nr_sects); -- } --#endif - return 0; - } - --/*====================================================================== -- -- Handler for block device requests -- --======================================================================*/ -- --static void do_ftl_request(request_arg_t) -+static int ftl_readsect(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buf) - { -- int ret, minor; -- partition_t *part; -- -- do { -- // sti(); -- INIT_REQUEST; -- -- minor = MINOR(CURRENT->rq_dev); -- -- part = myparts[minor >> 4]; -- if (part) { -- ret = 0; -- -- switch (CURRENT->cmd) { -- case READ: -- ret = ftl_read(part, CURRENT->buffer, -- CURRENT->sector+ftl_hd[minor].start_sect, -- CURRENT->current_nr_sectors); -- if (ret) printk("ftl_read returned %d\n", ret); -- break; -- -- case WRITE: -- ret = ftl_write(part, CURRENT->buffer, -- CURRENT->sector+ftl_hd[minor].start_sect, -- CURRENT->current_nr_sectors); -- if (ret) printk("ftl_write returned %d\n", ret); -- break; -- -- default: -- panic("ftl_cs: unknown block command!\n"); -- -- } -- } else { -- ret = 1; -- printk("NULL part in ftl_request\n"); -- } -- -- if (!ret) { -- CURRENT->sector += CURRENT->current_nr_sectors; -- } -+ return ftl_read((void *)dev, buf, block, 1); -+} - -- end_request((ret == 0) ? 1 : 0); -- } while (1); --} /* do_ftl_request */ -+static int ftl_writesect(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buf) -+{ -+ return ftl_write((void *)dev, buf, block, 1); -+} - - /*====================================================================*/ - -@@ -1337,19 +1038,9 @@ - - } /* ftl_freepart */ - --static void ftl_notify_add(struct mtd_info *mtd) -+static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) - { - partition_t *partition; -- int device; -- -- for (device=0; device < MAX_MTD_DEVICES && myparts[device]; device++) -- ; -- -- if (device == MAX_MTD_DEVICES) { -- printk(KERN_NOTICE "Maximum number of FTL partitions reached\n" -- "Not scanning <%s>\n", mtd->name); -- return; -- } - - partition = kmalloc(sizeof(partition_t), GFP_KERNEL); - -@@ -1361,92 +1052,55 @@ - - memset(partition, 0, sizeof(partition_t)); - -- partition->mtd = mtd; -+ partition->mbd.mtd = mtd; - - if ((scan_header(partition) == 0) && - (build_maps(partition) == 0)) { - - partition->state = FTL_FORMATTED; -- atomic_set(&partition->open, 0); -- myparts[device] = partition; -- ftl_reread_partitions(device << 4); - #ifdef PCMCIA_DEBUG -- printk(KERN_INFO "ftl_cs: opening %d kb FTL partition\n", -+ printk(KERN_INFO "ftl_cs: opening %d KiB FTL partition\n", - le32_to_cpu(partition->header.FormattedSize) >> 10); - #endif -+ partition->mbd.size = le32_to_cpu(partition->header.FormattedSize) >> 9; -+ partition->mbd.blksize = SECTOR_SIZE; -+ partition->mbd.tr = tr; -+ partition->mbd.devnum = -1; -+ if (add_mtd_blktrans_dev((void *)partition)) -+ kfree(partition); -+ - } else - kfree(partition); - } - --static void ftl_notify_remove(struct mtd_info *mtd) -+static void ftl_remove_dev(struct mtd_blktrans_dev *dev) - { -- int i,j; -- -- /* Q: What happens if you try to remove a device which has -- * a currently-open FTL partition on it? -- * -- * A: You don't. The ftl_open routine is responsible for -- * increasing the use count of the driver module which -- * it uses. -- */ -- -- /* That's the theory, anyway :) */ -- -- for (i=0; i< MAX_MTD_DEVICES; i++) -- if (myparts[i] && myparts[i]->mtd == mtd) { -- -- if (myparts[i]->state == FTL_FORMATTED) -- ftl_freepart(myparts[i]); -- -- myparts[i]->state = 0; -- for (j=0; j<16; j++) { -- ftl_gendisk.part[j].nr_sects=0; -- ftl_gendisk.part[j].start_sect=0; -- } -- kfree(myparts[i]); -- myparts[i] = NULL; -- } -+ del_mtd_blktrans_dev(dev); -+ kfree(dev); - } - -+struct mtd_blktrans_ops ftl_tr = { -+ .name = "ftl", -+ .major = FTL_MAJOR, -+ .part_bits = PART_BITS, -+ .readsect = ftl_readsect, -+ .writesect = ftl_writesect, -+ .getgeo = ftl_getgeo, -+ .add_mtd = ftl_add_mtd, -+ .remove_dev = ftl_remove_dev, -+ .owner = THIS_MODULE, -+}; -+ - int init_ftl(void) - { -- int i; -- -- memset(myparts, 0, sizeof(myparts)); -+ DEBUG(0, "$Id$\n"); - -- DEBUG(0, "$Id$\n"); -- -- if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) { -- printk(KERN_NOTICE "ftl_cs: unable to grab major " -- "device number!\n"); -- return -EAGAIN; -- } -- -- for (i = 0; i < MINOR_NR(MAX_DEV, 0, 0); i++) -- ftl_blocksizes[i] = 1024; -- for (i = 0; i < MAX_DEV*MAX_PART; i++) { -- ftl_hd[i].nr_sects = 0; -- ftl_hd[i].start_sect = 0; -- } -- blksize_size[FTL_MAJOR] = ftl_blocksizes; -- ftl_gendisk.major = FTL_MAJOR; -- blk_init_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR), &do_ftl_request); -- add_gendisk(&ftl_gendisk); -- -- register_mtd_user(&ftl_notifier); -- -- return 0; -+ return register_mtd_blktrans(&ftl_tr); - } - - static void __exit cleanup_ftl(void) - { -- unregister_mtd_user(&ftl_notifier); -- -- unregister_blkdev(FTL_MAJOR, "ftl"); -- blk_cleanup_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR)); -- blksize_size[FTL_MAJOR] = NULL; -- -- del_gendisk(&ftl_gendisk); -+ deregister_mtd_blktrans(&ftl_tr); - } - - module_init(init_ftl); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/inftlcore.c linux/drivers/mtd/inftlcore.c ---- linux-mips-2.4.24-pre2/drivers/mtd/inftlcore.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/inftlcore.c 2004-11-17 18:17:58.000000000 +0100 -@@ -0,0 +1,900 @@ -+/* -+ * inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL) -+ * -+ * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) -+ * -+ * Based heavily on the nftlcore.c code which is: -+ * (c) 1999 Machine Vision Holdings, Inc. -+ * Author: David Woodhouse -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the 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 -+ -+/* -+ * Maximum number of loops while examining next block, to have a -+ * chance to detect consistency problems (they should never happen -+ * because of the checks done in the mounting. -+ */ -+#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; -+ unsigned long temp; -+ -+ if (mtd->ecctype != MTD_ECC_RS_DiskOnChip) -+ return; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name); -+ -+ inftl = kmalloc(sizeof(*inftl), GFP_KERNEL); -+ -+ if (!inftl) { -+ printk(KERN_WARNING "INFTL: Out of memory for data structures\n"); -+ return; -+ } -+ memset(inftl, 0, sizeof(*inftl)); -+ -+ inftl->mbd.mtd = mtd; -+ inftl->mbd.devnum = -1; -+ inftl->mbd.blksize = 512; -+ inftl->mbd.tr = tr; -+ -+ if (INFTL_mount(inftl) < 0) { -+ printk(KERN_WARNING "INFTL: could not mount device\n"); -+ kfree(inftl); -+ return; -+ } -+ -+ /* OK, it's a new one. Set up all the data structures. */ -+ -+ /* Calculate geometry */ -+ inftl->cylinders = 1024; -+ inftl->heads = 16; -+ -+ temp = inftl->cylinders * inftl->heads; -+ inftl->sectors = inftl->mbd.size / temp; -+ if (inftl->mbd.size % temp) { -+ inftl->sectors++; -+ temp = inftl->cylinders * inftl->sectors; -+ inftl->heads = inftl->mbd.size / temp; -+ -+ if (inftl->mbd.size % temp) { -+ inftl->heads++; -+ temp = inftl->heads * inftl->sectors; -+ inftl->cylinders = inftl->mbd.size / temp; -+ } -+ } -+ -+ if (inftl->mbd.size != inftl->heads * inftl->cylinders * inftl->sectors) { -+ /* -+ Oh no we don't have -+ mbd.size == heads * cylinders * sectors -+ */ -+ printk(KERN_WARNING "INFTL: cannot calculate a geometry to " -+ "match size of 0x%lx.\n", inftl->mbd.size); -+ printk(KERN_WARNING "INFTL: using C:%d H:%d S:%d " -+ "(== 0x%lx sects)\n", -+ inftl->cylinders, inftl->heads , inftl->sectors, -+ (long)inftl->cylinders * (long)inftl->heads * -+ (long)inftl->sectors ); -+ } -+ -+ if (add_mtd_blktrans_dev(&inftl->mbd)) { -+ if (inftl->PUtable) -+ kfree(inftl->PUtable); -+ if (inftl->VUtable) -+ kfree(inftl->VUtable); -+ kfree(inftl); -+ return; -+ } -+#ifdef PSYCHO_DEBUG -+ printk(KERN_INFO "INFTL: Found new nftl%c\n", nftl->mbd.devnum + 'a'); -+#endif -+ return; -+} -+ -+static void inftl_remove_dev(struct mtd_blktrans_dev *dev) -+{ -+ struct INFTLrecord *inftl = (void *)dev; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: remove_dev (i=%d)\n", dev->devnum); -+ -+ del_mtd_blktrans_dev(dev); -+ -+ if (inftl->PUtable) -+ kfree(inftl->PUtable); -+ if (inftl->VUtable) -+ kfree(inftl->VUtable); -+ kfree(inftl); -+} -+ -+/* -+ * Actual INFTL access routines. -+ */ -+ -+/* -+ * INFTL_findfreeblock: Find a free Erase Unit on the INFTL partition. -+ * This function is used when the give Virtual Unit Chain. -+ */ -+static u16 INFTL_findfreeblock(struct INFTLrecord *inftl, int desperate) -+{ -+ u16 pot = inftl->LastFreeEUN; -+ int silly = inftl->nb_blocks; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findfreeblock(inftl=0x%x," -+ "desperate=%d)\n", (int)inftl, desperate); -+ -+ /* -+ * Normally, we force a fold to happen before we run out of free -+ * blocks completely. -+ */ -+ if (!desperate && inftl->numfreeEUNs < 2) { -+ DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free " -+ "EUNs (%d)\n", inftl->numfreeEUNs); -+ return 0xffff; -+ } -+ -+ /* Scan for a free block */ -+ do { -+ if (inftl->PUtable[pot] == BLOCK_FREE) { -+ inftl->LastFreeEUN = pot; -+ return pot; -+ } -+ -+ if (++pot > inftl->lastEUN) -+ pot = 0; -+ -+ if (!silly--) { -+ printk(KERN_WARNING "INFTL: no free blocks found! " -+ "EUN range = %d - %d\n", 0, inftl->LastFreeEUN); -+ return BLOCK_NIL; -+ } -+ } while (pot != inftl->LastFreeEUN); -+ -+ return BLOCK_NIL; -+} -+ -+static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned pendingblock) -+{ -+ u16 BlockMap[MAX_SECTORS_PER_UNIT]; -+ unsigned char BlockDeleted[MAX_SECTORS_PER_UNIT]; -+ unsigned int thisEUN, prevEUN, status; -+ int block, silly; -+ unsigned int targetEUN; -+ struct inftl_oob oob; -+ size_t retlen; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_foldchain(inftl=0x%x,thisVUC=%d," -+ "pending=%d)\n", (int)inftl, thisVUC, pendingblock); -+ -+ memset(BlockMap, 0xff, sizeof(BlockMap)); -+ memset(BlockDeleted, 0, sizeof(BlockDeleted)); -+ -+ thisEUN = targetEUN = inftl->VUtable[thisVUC]; -+ -+ if (thisEUN == BLOCK_NIL) { -+ printk(KERN_WARNING "INFTL: trying to fold non-existent " -+ "Virtual Unit Chain %d!\n", thisVUC); -+ return BLOCK_NIL; -+ } -+ -+ /* -+ * Scan to find the Erase Unit which holds the actual data for each -+ * 512-byte block within the Chain. -+ */ -+ silly = MAX_LOOPS; -+ while (thisEUN < inftl->nb_blocks) { -+ for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) { -+ if ((BlockMap[block] != 0xffff) || BlockDeleted[block]) -+ continue; -+ -+ if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) -+ + (block * SECTORSIZE), 16 , &retlen, -+ (char *)&oob) < 0) -+ status = SECTOR_IGNORE; -+ else -+ status = oob.b.Status | oob.b.Status1; -+ -+ switch(status) { -+ case SECTOR_FREE: -+ case SECTOR_IGNORE: -+ break; -+ case SECTOR_USED: -+ BlockMap[block] = thisEUN; -+ continue; -+ case SECTOR_DELETED: -+ BlockDeleted[block] = 1; -+ continue; -+ default: -+ printk(KERN_WARNING "INFTL: unknown status " -+ "for block %d in EUN %d: %x\n", -+ block, thisEUN, status); -+ break; -+ } -+ } -+ -+ if (!silly--) { -+ printk(KERN_WARNING "INFTL: infinite loop in Virtual " -+ "Unit Chain 0x%x\n", thisVUC); -+ return BLOCK_NIL; -+ } -+ -+ thisEUN = inftl->PUtable[thisEUN]; -+ } -+ -+ /* -+ * OK. We now know the location of every block in the Virtual Unit -+ * Chain, and the Erase Unit into which we are supposed to be copying. -+ * Go for it. -+ */ -+ DEBUG(MTD_DEBUG_LEVEL1, "INFTL: folding chain %d into unit %d\n", -+ thisVUC, targetEUN); -+ -+ for (block = 0; block < inftl->EraseSize/SECTORSIZE ; block++) { -+ unsigned char movebuf[SECTORSIZE]; -+ int ret; -+ -+ /* -+ * If it's in the target EUN already, or if it's pending write, -+ * do nothing. -+ */ -+ if (BlockMap[block] == targetEUN || (pendingblock == -+ (thisVUC * (inftl->EraseSize / SECTORSIZE) + block))) { -+ continue; -+ } -+ -+ /* -+ * Copy only in non free block (free blocks can only -+ * happen in case of media errors or deleted blocks). -+ */ -+ if (BlockMap[block] == BLOCK_NIL) -+ continue; -+ -+ ret = MTD_READECC(inftl->mbd.mtd, (inftl->EraseSize * -+ BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE, -+ &retlen, movebuf, (char *)&oob, NULL); -+ if (ret < 0) { -+ ret = MTD_READECC(inftl->mbd.mtd, (inftl->EraseSize * -+ BlockMap[block]) + (block * SECTORSIZE), -+ SECTORSIZE, &retlen, movebuf, (char *)&oob, -+ NULL); -+ if (ret != -EIO) -+ DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went " -+ "away on retry?\n"); -+ } -+ MTD_WRITEECC(inftl->mbd.mtd, (inftl->EraseSize * targetEUN) + -+ (block * SECTORSIZE), SECTORSIZE, &retlen, -+ movebuf, (char *)&oob, NULL); -+ } -+ -+ /* -+ * Newest unit in chain now contains data from _all_ older units. -+ * So go through and erase each unit in chain, oldest first. (This -+ * is important, by doing oldest first if we crash/reboot then it -+ * it is relatively simple to clean up the mess). -+ */ -+ DEBUG(MTD_DEBUG_LEVEL1, "INFTL: want to erase virtual chain %d\n", -+ thisVUC); -+ -+ for (;;) { -+ /* Find oldest unit in chain. */ -+ thisEUN = inftl->VUtable[thisVUC]; -+ prevEUN = BLOCK_NIL; -+ while (inftl->PUtable[thisEUN] != BLOCK_NIL) { -+ prevEUN = thisEUN; -+ thisEUN = inftl->PUtable[thisEUN]; -+ } -+ -+ /* Check if we are all done */ -+ if (thisEUN == targetEUN) -+ break; -+ -+ if (INFTL_formatblock(inftl, thisEUN) < 0) { -+ /* -+ * Could not erase : mark block as reserved. -+ * FixMe: Update Bad Unit Table on disk. -+ */ -+ inftl->PUtable[thisEUN] = BLOCK_RESERVED; -+ } else { -+ /* Correctly erased : mark it as free */ -+ inftl->PUtable[thisEUN] = BLOCK_FREE; -+ inftl->PUtable[prevEUN] = BLOCK_NIL; -+ inftl->numfreeEUNs++; -+ } -+ } -+ -+ return targetEUN; -+} -+ -+u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock) -+{ -+ /* -+ * This is the part that needs some cleverness applied. -+ * For now, I'm doing the minimum applicable to actually -+ * get the thing to work. -+ * Wear-levelling and other clever stuff needs to be implemented -+ * and we also need to do some assessment of the results when -+ * the system loses power half-way through the routine. -+ */ -+ u16 LongestChain = 0; -+ u16 ChainLength = 0, thislen; -+ u16 chain, EUN; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_makefreeblock(inftl=0x%x," -+ "pending=%d)\n", (int)inftl, pendingblock); -+ -+ for (chain = 0; chain < inftl->nb_blocks; chain++) { -+ EUN = inftl->VUtable[chain]; -+ thislen = 0; -+ -+ while (EUN <= inftl->lastEUN) { -+ thislen++; -+ EUN = inftl->PUtable[EUN]; -+ if (thislen > 0xff00) { -+ printk(KERN_WARNING "INFTL: endless loop in " -+ "Virtual Chain %d: Unit %x\n", -+ chain, EUN); -+ /* -+ * Actually, don't return failure. -+ * Just ignore this chain and get on with it. -+ */ -+ thislen = 0; -+ break; -+ } -+ } -+ -+ if (thislen > ChainLength) { -+ ChainLength = thislen; -+ LongestChain = chain; -+ } -+ } -+ -+ if (ChainLength < 2) { -+ printk(KERN_WARNING "INFTL: no Virtual Unit Chains available " -+ "for folding. Failing request\n"); -+ return BLOCK_NIL; -+ } -+ -+ return INFTL_foldchain(inftl, LongestChain, pendingblock); -+} -+ -+static int nrbits(unsigned int val, int bitcount) -+{ -+ int i, total = 0; -+ -+ for (i = 0; (i < bitcount); i++) -+ total += (((0x1 << i) & val) ? 1 : 0); -+ return total; -+} -+ -+/* -+ * INFTL_findwriteunit: Return the unit number into which we can write -+ * for this block. Make it available if it isn't already. -+ */ -+static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) -+{ -+ unsigned int thisVUC = block / (inftl->EraseSize / SECTORSIZE); -+ unsigned int thisEUN, writeEUN, prev_block, status; -+ unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize -1); -+ struct inftl_oob oob; -+ struct inftl_bci bci; -+ unsigned char anac, nacs, parity; -+ size_t retlen; -+ int silly, silly2 = 3; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findwriteunit(inftl=0x%x," -+ "block=%d)\n", (int)inftl, block); -+ -+ do { -+ /* -+ * Scan the media to find a unit in the VUC which has -+ * a free space for the block in question. -+ */ -+ writeEUN = BLOCK_NIL; -+ thisEUN = inftl->VUtable[thisVUC]; -+ silly = MAX_LOOPS; -+ -+ while (thisEUN <= inftl->lastEUN) { -+ MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) + -+ blockofs, 8, &retlen, (char *)&bci); -+ -+ status = bci.Status | bci.Status1; -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: status of block %d in " -+ "EUN %d is %x\n", block , writeEUN, status); -+ -+ switch(status) { -+ case SECTOR_FREE: -+ writeEUN = thisEUN; -+ break; -+ case SECTOR_DELETED: -+ case SECTOR_USED: -+ /* Can't go any further */ -+ goto hitused; -+ case SECTOR_IGNORE: -+ break; -+ default: -+ /* -+ * Invalid block. Don't use it any more. -+ * Must implement. -+ */ -+ break; -+ } -+ -+ if (!silly--) { -+ printk(KERN_WARNING "INFTL: infinite loop in " -+ "Virtual Unit Chain 0x%x\n", thisVUC); -+ return 0xffff; -+ } -+ -+ /* Skip to next block in chain */ -+ thisEUN = inftl->PUtable[thisEUN]; -+ } -+ -+hitused: -+ if (writeEUN != BLOCK_NIL) -+ return writeEUN; -+ -+ -+ /* -+ * OK. We didn't find one in the existing chain, or there -+ * is no existing chain. Allocate a new one. -+ */ -+ writeEUN = INFTL_findfreeblock(inftl, 0); -+ -+ if (writeEUN == BLOCK_NIL) { -+ /* -+ * That didn't work - there were no free blocks just -+ * waiting to be picked up. We're going to have to fold -+ * a chain to make room. -+ */ -+ thisEUN = INFTL_makefreeblock(inftl, 0xffff); -+ -+ /* -+ * Hopefully we free something, lets try again. -+ * This time we are desperate... -+ */ -+ DEBUG(MTD_DEBUG_LEVEL1, "INFTL: using desperate==1 " -+ "to find free EUN to accommodate write to " -+ "VUC %d\n", thisVUC); -+ writeEUN = INFTL_findfreeblock(inftl, 1); -+ if (writeEUN == BLOCK_NIL) { -+ /* -+ * Ouch. This should never happen - we should -+ * always be able to make some room somehow. -+ * If we get here, we've allocated more storage -+ * space than actual media, or our makefreeblock -+ * routine is missing something. -+ */ -+ printk(KERN_WARNING "INFTL: cannot make free " -+ "space.\n"); -+#ifdef DEBUG -+ INFTL_dumptables(inftl); -+ INFTL_dumpVUchains(inftl); -+#endif -+ return BLOCK_NIL; -+ } -+ } -+ -+ /* -+ * Insert new block into virtual chain. Firstly update the -+ * block headers in flash... -+ */ -+ anac = 0; -+ nacs = 0; -+ thisEUN = inftl->VUtable[thisVUC]; -+ if (thisEUN != BLOCK_NIL) { -+ MTD_READOOB(inftl->mbd.mtd, thisEUN * inftl->EraseSize -+ + 8, 8, &retlen, (char *)&oob.u); -+ anac = oob.u.a.ANAC + 1; -+ nacs = oob.u.a.NACs + 1; -+ } -+ -+ prev_block = inftl->VUtable[thisVUC]; -+ if (prev_block < inftl->nb_blocks) -+ prev_block -= inftl->firstEUN; -+ -+ parity = (nrbits(thisVUC, 16) & 0x1) ? 0x1 : 0; -+ parity |= (nrbits(prev_block, 16) & 0x1) ? 0x2 : 0; -+ parity |= (nrbits(anac, 8) & 0x1) ? 0x4 : 0; -+ parity |= (nrbits(nacs, 8) & 0x1) ? 0x8 : 0; -+ -+ oob.u.a.virtualUnitNo = cpu_to_le16(thisVUC); -+ oob.u.a.prevUnitNo = cpu_to_le16(prev_block); -+ oob.u.a.ANAC = anac; -+ oob.u.a.NACs = nacs; -+ oob.u.a.parityPerField = parity; -+ oob.u.a.discarded = 0xaa; -+ -+ MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize + 8, 8, -+ &retlen, (char *)&oob.u); -+ -+ /* Also back up header... */ -+ oob.u.b.virtualUnitNo = cpu_to_le16(thisVUC); -+ oob.u.b.prevUnitNo = cpu_to_le16(prev_block); -+ oob.u.b.ANAC = anac; -+ oob.u.b.NACs = nacs; -+ oob.u.b.parityPerField = parity; -+ oob.u.b.discarded = 0xaa; -+ -+ MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize + -+ SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u); -+ -+ inftl->PUtable[writeEUN] = inftl->VUtable[thisVUC]; -+ inftl->VUtable[thisVUC] = writeEUN; -+ -+ inftl->numfreeEUNs--; -+ return writeEUN; -+ -+ } while (silly2--); -+ -+ printk(KERN_WARNING "INFTL: error folding to make room for Virtual " -+ "Unit Chain 0x%x\n", thisVUC); -+ return 0xffff; -+} -+ -+/* -+ * Given a Virtual Unit Chain, see if it can be deleted, and if so do it. -+ */ -+static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC) -+{ -+ unsigned char BlockUsed[MAX_SECTORS_PER_UNIT]; -+ unsigned char BlockDeleted[MAX_SECTORS_PER_UNIT]; -+ unsigned int thisEUN, status; -+ int block, silly; -+ struct inftl_bci bci; -+ size_t retlen; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_trydeletechain(inftl=0x%x," -+ "thisVUC=%d)\n", (int)inftl, thisVUC); -+ -+ memset(BlockUsed, 0, sizeof(BlockUsed)); -+ memset(BlockDeleted, 0, sizeof(BlockDeleted)); -+ -+ thisEUN = inftl->VUtable[thisVUC]; -+ if (thisEUN == BLOCK_NIL) { -+ printk(KERN_WARNING "INFTL: trying to delete non-existent " -+ "Virtual Unit Chain %d!\n", thisVUC); -+ return; -+ } -+ -+ /* -+ * Scan through the Erase Units to determine whether any data is in -+ * each of the 512-byte blocks within the Chain. -+ */ -+ silly = MAX_LOOPS; -+ while (thisEUN < inftl->nb_blocks) { -+ for (block = 0; block < inftl->EraseSize/SECTORSIZE; block++) { -+ if (BlockUsed[block] || BlockDeleted[block]) -+ continue; -+ -+ if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) -+ + (block * SECTORSIZE), 8 , &retlen, -+ (char *)&bci) < 0) -+ status = SECTOR_IGNORE; -+ else -+ status = bci.Status | bci.Status1; -+ -+ switch(status) { -+ case SECTOR_FREE: -+ case SECTOR_IGNORE: -+ break; -+ case SECTOR_USED: -+ BlockUsed[block] = 1; -+ continue; -+ case SECTOR_DELETED: -+ BlockDeleted[block] = 1; -+ continue; -+ default: -+ printk(KERN_WARNING "INFTL: unknown status " -+ "for block %d in EUN %d: 0x%x\n", -+ block, thisEUN, status); -+ } -+ } -+ -+ if (!silly--) { -+ printk(KERN_WARNING "INFTL: infinite loop in Virtual " -+ "Unit Chain 0x%x\n", thisVUC); -+ return; -+ } -+ -+ thisEUN = inftl->PUtable[thisEUN]; -+ } -+ -+ for (block = 0; block < inftl->EraseSize/SECTORSIZE; block++) -+ if (BlockUsed[block]) -+ return; -+ -+ /* -+ * For each block in the chain free it and make it available -+ * for future use. Erase from the oldest unit first. -+ */ -+ DEBUG(MTD_DEBUG_LEVEL1, "INFTL: deleting empty VUC %d\n", thisVUC); -+ -+ for (;;) { -+ u16 *prevEUN = &inftl->VUtable[thisVUC]; -+ thisEUN = *prevEUN; -+ -+ /* If the chain is all gone already, we're done */ -+ if (thisEUN == BLOCK_NIL) { -+ DEBUG(MTD_DEBUG_LEVEL2, "INFTL: Empty VUC %d for deletion was already absent\n", thisEUN); -+ return; -+ } -+ -+ /* Find oldest unit in chain. */ -+ while (inftl->PUtable[thisEUN] != BLOCK_NIL) { -+ BUG_ON(thisEUN >= inftl->nb_blocks); -+ -+ prevEUN = &inftl->PUtable[thisEUN]; -+ thisEUN = *prevEUN; -+ } -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "Deleting EUN %d from VUC %d\n", -+ thisEUN, thisVUC); -+ -+ if (INFTL_formatblock(inftl, thisEUN) < 0) { -+ /* -+ * Could not erase : mark block as reserved. -+ * FixMe: Update Bad Unit Table on medium. -+ */ -+ inftl->PUtable[thisEUN] = BLOCK_RESERVED; -+ } else { -+ /* Correctly erased : mark it as free */ -+ inftl->PUtable[thisEUN] = BLOCK_FREE; -+ inftl->numfreeEUNs++; -+ } -+ -+ /* Now sort out whatever was pointing to it... */ -+ *prevEUN = BLOCK_NIL; -+ -+ /* Ideally we'd actually be responsive to new -+ requests while we're doing this -- if there's -+ free space why should others be made to wait? */ -+ cond_resched(); -+ } -+ -+ inftl->VUtable[thisVUC] = BLOCK_NIL; -+} -+ -+static int INFTL_deleteblock(struct INFTLrecord *inftl, unsigned block) -+{ -+ unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)]; -+ unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1); -+ unsigned int status; -+ int silly = MAX_LOOPS; -+ size_t retlen; -+ struct inftl_bci bci; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_deleteblock(inftl=0x%x," -+ "block=%d)\n", (int)inftl, block); -+ -+ while (thisEUN < inftl->nb_blocks) { -+ if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) + -+ blockofs, 8, &retlen, (char *)&bci) < 0) -+ status = SECTOR_IGNORE; -+ else -+ status = bci.Status | bci.Status1; -+ -+ switch (status) { -+ case SECTOR_FREE: -+ case SECTOR_IGNORE: -+ break; -+ case SECTOR_DELETED: -+ thisEUN = BLOCK_NIL; -+ goto foundit; -+ case SECTOR_USED: -+ goto foundit; -+ default: -+ printk(KERN_WARNING "INFTL: unknown status for " -+ "block %d in EUN %d: 0x%x\n", -+ block, thisEUN, status); -+ break; -+ } -+ -+ if (!silly--) { -+ printk(KERN_WARNING "INFTL: infinite loop in Virtual " -+ "Unit Chain 0x%x\n", -+ block / (inftl->EraseSize / SECTORSIZE)); -+ return 1; -+ } -+ thisEUN = inftl->PUtable[thisEUN]; -+ } -+ -+foundit: -+ if (thisEUN != BLOCK_NIL) { -+ loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs; -+ -+ if (MTD_READOOB(inftl->mbd.mtd, ptr, 8, &retlen, (char *)&bci) < 0) -+ return -EIO; -+ bci.Status = bci.Status1 = SECTOR_DELETED; -+ if (MTD_WRITEOOB(inftl->mbd.mtd, ptr, 8, &retlen, (char *)&bci) < 0) -+ return -EIO; -+ INFTL_trydeletechain(inftl, block / (inftl->EraseSize / SECTORSIZE)); -+ } -+ return 0; -+} -+ -+static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, -+ char *buffer) -+{ -+ struct INFTLrecord *inftl = (void *)mbd; -+ unsigned int writeEUN; -+ unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1); -+ size_t retlen; -+ u8 eccbuf[6]; -+ char *p, *pend; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_writeblock(inftl=0x%x,block=%d," -+ "buffer=0x%x)\n", (int)inftl, block, (int)buffer); -+ -+ /* Is block all zero? */ -+ pend = buffer + SECTORSIZE; -+ for (p = buffer; p < pend && !*p; p++) -+ ; -+ -+ if (p < pend) { -+ writeEUN = INFTL_findwriteunit(inftl, block); -+ -+ if (writeEUN == BLOCK_NIL) { -+ printk(KERN_WARNING "inftl_writeblock(): cannot find " -+ "block to write to\n"); -+ /* -+ * If we _still_ haven't got a block to use, -+ * we're screwed. -+ */ -+ return 1; -+ } -+ -+ MTD_WRITEECC(inftl->mbd.mtd, (writeEUN * inftl->EraseSize) + -+ blockofs, SECTORSIZE, &retlen, (char *)buffer, -+ (char *)eccbuf, NULL); -+ /* -+ * No need to write SECTOR_USED flags since they are written -+ * in mtd_writeecc -+ */ -+ } else { -+ INFTL_deleteblock(inftl, block); -+ } -+ -+ return 0; -+} -+ -+static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block, -+ char *buffer) -+{ -+ struct INFTLrecord *inftl = (void *)mbd; -+ unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)]; -+ unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1); -+ unsigned int status; -+ int silly = MAX_LOOPS; -+ struct inftl_bci bci; -+ size_t retlen; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=0x%x,block=%d," -+ "buffer=0x%x)\n", (int)inftl, block, (int)buffer); -+ -+ while (thisEUN < inftl->nb_blocks) { -+ if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) + -+ blockofs, 8, &retlen, (char *)&bci) < 0) -+ status = SECTOR_IGNORE; -+ else -+ status = bci.Status | bci.Status1; -+ -+ switch (status) { -+ case SECTOR_DELETED: -+ thisEUN = BLOCK_NIL; -+ goto foundit; -+ case SECTOR_USED: -+ goto foundit; -+ case SECTOR_FREE: -+ case SECTOR_IGNORE: -+ break; -+ default: -+ printk(KERN_WARNING "INFTL: unknown status for " -+ "block %ld in EUN %d: 0x%04x\n", -+ block, thisEUN, status); -+ break; -+ } -+ -+ if (!silly--) { -+ printk(KERN_WARNING "INFTL: infinite loop in " -+ "Virtual Unit Chain 0x%lx\n", -+ block / (inftl->EraseSize / SECTORSIZE)); -+ return 1; -+ } -+ -+ thisEUN = inftl->PUtable[thisEUN]; -+ } -+ -+foundit: -+ if (thisEUN == BLOCK_NIL) { -+ /* The requested block is not on the media, return all 0x00 */ -+ memset(buffer, 0, SECTORSIZE); -+ } else { -+ size_t retlen; -+ loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs; -+ u_char eccbuf[6]; -+ if (MTD_READECC(inftl->mbd.mtd, ptr, SECTORSIZE, &retlen, -+ buffer, eccbuf, NULL)) -+ return -EIO; -+ } -+ return 0; -+} -+ -+static int inftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) -+{ -+ struct INFTLrecord *inftl = (void *)dev; -+ -+ geo->heads = inftl->heads; -+ geo->sectors = inftl->sectors; -+ geo->cylinders = inftl->cylinders; -+ -+ return 0; -+} -+ -+struct mtd_blktrans_ops inftl_tr = { -+ .name = "inftl", -+ .major = INFTL_MAJOR, -+ .part_bits = INFTL_PARTN_BITS, -+ .getgeo = inftl_getgeo, -+ .readsect = inftl_readblock, -+ .writesect = inftl_writeblock, -+ .add_mtd = inftl_add_mtd, -+ .remove_dev = inftl_remove_dev, -+ .owner = THIS_MODULE, -+}; -+ -+extern char inftlmountrev[]; -+ -+int __init init_inftl(void) -+{ -+ printk(KERN_INFO "INFTL: inftlcore.c $Revision$, " -+ "inftlmount.c %s\n", inftlmountrev); -+ -+ return register_mtd_blktrans(&inftl_tr); -+} -+ -+static void __exit cleanup_inftl(void) -+{ -+ deregister_mtd_blktrans(&inftl_tr); -+} -+ -+module_init(init_inftl); -+module_exit(cleanup_inftl); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Greg Ungerer , David Woodhouse , Fabrice Bellard et al."); -+MODULE_DESCRIPTION("Support code for Inverse Flash Translation Layer, used on M-Systems DiskOnChip 2000, Millennium and Millennium Plus"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/inftlmount.c linux/drivers/mtd/inftlmount.c ---- linux-mips-2.4.24-pre2/drivers/mtd/inftlmount.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/inftlmount.c 2004-11-17 18:17:58.000000000 +0100 -@@ -0,0 +1,817 @@ -+/* -+ * inftlmount.c -- INFTL mount code with extensive checks. -+ * -+ * Author: Greg Ungerer (gerg@snapgear.com) -+ * (C) Copyright 2002-2003, Greg Ungerer (gerg@snapgear.com) -+ * -+ * Based heavily on the nftlmount.c code which is: -+ * Author: Fabrice Bellard (fabrice.bellard@netgem.com) -+ * Copyright (C) 2000 Netgem S.A. -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the 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 -+ -+char inftlmountrev[]="$Revision$"; -+ -+/* -+ * find_boot_record: Find the INFTL Media Header and its Spare copy which -+ * contains the various device information of the INFTL partition and -+ * Bad Unit Table. Update the PUtable[] table according to the Bad -+ * Unit Table. PUtable[] is used for management of Erase Unit in -+ * other routines in inftlcore.c and inftlmount.c. -+ */ -+static int find_boot_record(struct INFTLrecord *inftl) -+{ -+ struct inftl_unittail h1; -+ //struct inftl_oob oob; -+ unsigned int i, block, boot_record_count = 0; -+ u8 buf[SECTORSIZE]; -+ struct INFTLMediaHeader *mh = &inftl->MediaHdr; -+ struct INFTLPartition *ip; -+ int retlen; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: find_boot_record(inftl=0x%x)\n", -+ (int)inftl); -+ -+ /* -+ * Assume logical EraseSize == physical erasesize for starting the -+ * scan. We'll sort it out later if we find a MediaHeader which says -+ * otherwise. -+ */ -+ inftl->EraseSize = inftl->mbd.mtd->erasesize; -+ inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize; -+ -+ inftl->MediaUnit = BLOCK_NIL; -+ inftl->SpareMediaUnit = BLOCK_NIL; -+ -+ /* Search for a valid boot record */ -+ for (block = 0; block < inftl->nb_blocks; block++) { -+ int ret; -+ -+ /* -+ * Check for BNAND header first. Then whinge if it's found -+ * but later checks fail. -+ */ -+ if ((ret = MTD_READ(inftl->mbd.mtd, block * inftl->EraseSize, -+ SECTORSIZE, &retlen, buf))) { -+ static int warncount = 5; -+ -+ if (warncount) { -+ printk(KERN_WARNING "INFTL: block read at 0x%x " -+ "of mtd%d failed: %d\n", -+ block * inftl->EraseSize, -+ inftl->mbd.mtd->index, ret); -+ if (!--warncount) -+ printk(KERN_WARNING "INFTL: further " -+ "failures for this block will " -+ "not be printed\n"); -+ } -+ continue; -+ } -+ -+ if (retlen < 6 || memcmp(buf, "BNAND", 6)) { -+ /* BNAND\0 not found. Continue */ -+ continue; -+ } -+ -+ /* To be safer with BIOS, also use erase mark as discriminant */ -+ if ((ret = MTD_READOOB(inftl->mbd.mtd, block * inftl->EraseSize + -+ SECTORSIZE + 8, 8, &retlen, (char *)&h1) < 0)) { -+ printk(KERN_WARNING "INFTL: ANAND header found at " -+ "0x%x in mtd%d, but OOB data read failed " -+ "(err %d)\n", block * inftl->EraseSize, -+ inftl->mbd.mtd->index, ret); -+ continue; -+ } -+ -+ if (boot_record_count) { -+ /* -+ * We've already processed one. So we just check if -+ * this one is the same as the first one we found. -+ */ -+ if (memcmp(mh, buf, sizeof(struct INFTLMediaHeader))) { -+ printk(KERN_WARNING "INFTL: Media Headers at " -+ "0x%x and 0x%x disagree.\n", -+ inftl->MediaUnit * inftl->EraseSize, -+ block * inftl->EraseSize); -+ return -1; -+ } -+ if (boot_record_count == 1) -+ inftl->SpareMediaUnit = block; -+ -+ /* -+ * Mark this boot record (INFTL MediaHeader) block as -+ * reserved. -+ */ -+ inftl->PUtable[block] = BLOCK_RESERVED; -+ -+ boot_record_count++; -+ continue; -+ } -+ -+ /* -+ * This is the first we've seen. -+ * Copy the media header structure into place. -+ */ -+ memcpy(mh, buf, sizeof(struct INFTLMediaHeader)); -+ mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks); -+ mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions); -+ mh->NoOfBDTLPartitions = le32_to_cpu(mh->NoOfBDTLPartitions); -+ mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits); -+ mh->FormatFlags = le32_to_cpu(mh->FormatFlags); -+ mh->PercentUsed = le32_to_cpu(mh->PercentUsed); -+ -+#ifdef CONFIG_MTD_DEBUG_VERBOSE -+ if (CONFIG_MTD_DEBUG_VERBOSE >= 2) { -+ printk("INFTL: Media Header ->\n" -+ " bootRecordID = %s\n" -+ " NoOfBootImageBlocks = %d\n" -+ " NoOfBinaryPartitions = %d\n" -+ " NoOfBDTLPartitions = %d\n" -+ " BlockMultiplerBits = %d\n" -+ " FormatFlgs = %d\n" -+ " OsakVersion = 0x%x\n" -+ " PercentUsed = %d\n", -+ mh->bootRecordID, mh->NoOfBootImageBlocks, -+ mh->NoOfBinaryPartitions, -+ mh->NoOfBDTLPartitions, -+ mh->BlockMultiplierBits, mh->FormatFlags, -+ mh->OsakVersion, mh->PercentUsed); -+ } -+#endif -+ -+ if (mh->NoOfBDTLPartitions == 0) { -+ printk(KERN_WARNING "INFTL: Media Header sanity check " -+ "failed: NoOfBDTLPartitions (%d) == 0, " -+ "must be at least 1\n", mh->NoOfBDTLPartitions); -+ return -1; -+ } -+ -+ if ((mh->NoOfBDTLPartitions + mh->NoOfBinaryPartitions) > 4) { -+ printk(KERN_WARNING "INFTL: Media Header sanity check " -+ "failed: Total Partitions (%d) > 4, " -+ "BDTL=%d Binary=%d\n", mh->NoOfBDTLPartitions + -+ mh->NoOfBinaryPartitions, -+ mh->NoOfBDTLPartitions, -+ mh->NoOfBinaryPartitions); -+ return -1; -+ } -+ -+ if (mh->BlockMultiplierBits > 1) { -+ printk(KERN_WARNING "INFTL: sorry, we don't support " -+ "UnitSizeFactor 0x%02x\n", -+ mh->BlockMultiplierBits); -+ return -1; -+ } else if (mh->BlockMultiplierBits == 1) { -+ printk(KERN_WARNING "INFTL: support for INFTL with " -+ "UnitSizeFactor 0x%02x is experimental\n", -+ mh->BlockMultiplierBits); -+ inftl->EraseSize = inftl->mbd.mtd->erasesize << -+ (0xff - mh->BlockMultiplierBits); -+ inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize; -+ } -+ -+ /* Scan the partitions */ -+ for (i = 0; (i < 4); i++) { -+ ip = &mh->Partitions[i]; -+ ip->virtualUnits = le32_to_cpu(ip->virtualUnits); -+ ip->firstUnit = le32_to_cpu(ip->firstUnit); -+ ip->lastUnit = le32_to_cpu(ip->lastUnit); -+ ip->flags = le32_to_cpu(ip->flags); -+ ip->spareUnits = le32_to_cpu(ip->spareUnits); -+ ip->Reserved0 = le32_to_cpu(ip->Reserved0); -+ -+#ifdef CONFIG_MTD_DEBUG_VERBOSE -+ if (CONFIG_MTD_DEBUG_VERBOSE >= 2) { -+ printk(" PARTITION[%d] ->\n" -+ " virtualUnits = %d\n" -+ " firstUnit = %d\n" -+ " lastUnit = %d\n" -+ " flags = 0x%x\n" -+ " spareUnits = %d\n", -+ i, ip->virtualUnits, ip->firstUnit, -+ ip->lastUnit, ip->flags, -+ ip->spareUnits); -+ } -+#endif -+ -+ if (ip->Reserved0 != ip->firstUnit) { -+ struct erase_info *instr = &inftl->instr; -+ -+ /* -+ * Most likely this is using the -+ * undocumented qiuck mount feature. -+ * We don't support that, we will need -+ * to erase the hidden block for full -+ * compatibility. -+ */ -+ instr->addr = ip->Reserved0 * inftl->EraseSize; -+ instr->len = inftl->EraseSize; -+ MTD_ERASE(inftl->mbd.mtd, instr); -+ } -+ if ((ip->lastUnit - ip->firstUnit + 1) < ip->virtualUnits) { -+ printk(KERN_WARNING "INFTL: Media Header " -+ "Partition %d sanity check failed\n" -+ " firstUnit %d : lastUnit %d > " -+ "virtualUnits %d\n", i, ip->lastUnit, -+ ip->firstUnit, ip->Reserved0); -+ return -1; -+ } -+ if (ip->Reserved1 != 0) { -+ printk(KERN_WARNING "INFTL: Media Header " -+ "Partition %d sanity check failed: " -+ "Reserved1 %d != 0\n", -+ i, ip->Reserved1); -+ return -1; -+ } -+ -+ if (ip->flags & INFTL_BDTL) -+ break; -+ } -+ -+ if (i >= 4) { -+ printk(KERN_WARNING "INFTL: Media Header Partition " -+ "sanity check failed:\n No partition " -+ "marked as Disk Partition\n"); -+ return -1; -+ } -+ -+ inftl->nb_boot_blocks = ip->firstUnit; -+ inftl->numvunits = ip->virtualUnits; -+ if (inftl->numvunits > (inftl->nb_blocks - -+ inftl->nb_boot_blocks - 2)) { -+ printk(KERN_WARNING "INFTL: Media Header sanity check " -+ "failed:\n numvunits (%d) > nb_blocks " -+ "(%d) - nb_boot_blocks(%d) - 2\n", -+ inftl->numvunits, inftl->nb_blocks, -+ inftl->nb_boot_blocks); -+ return -1; -+ } -+ -+ inftl->mbd.size = inftl->numvunits * -+ (inftl->EraseSize / SECTORSIZE); -+ -+ /* -+ * Block count is set to last used EUN (we won't need to keep -+ * any meta-data past that point). -+ */ -+ inftl->firstEUN = ip->firstUnit; -+ inftl->lastEUN = ip->lastUnit; -+ inftl->nb_blocks = ip->lastUnit + 1; -+ -+ /* Memory alloc */ -+ inftl->PUtable = kmalloc(inftl->nb_blocks * sizeof(u16), GFP_KERNEL); -+ if (!inftl->PUtable) { -+ printk(KERN_WARNING "INFTL: allocation of PUtable " -+ "failed (%d bytes)\n", -+ inftl->nb_blocks * sizeof(u16)); -+ return -ENOMEM; -+ } -+ -+ inftl->VUtable = kmalloc(inftl->nb_blocks * sizeof(u16), GFP_KERNEL); -+ if (!inftl->VUtable) { -+ kfree(inftl->PUtable); -+ printk(KERN_WARNING "INFTL: allocation of VUtable " -+ "failed (%d bytes)\n", -+ inftl->nb_blocks * sizeof(u16)); -+ return -ENOMEM; -+ } -+ -+ /* Mark the blocks before INFTL MediaHeader as reserved */ -+ for (i = 0; i < inftl->nb_boot_blocks; i++) -+ inftl->PUtable[i] = BLOCK_RESERVED; -+ /* Mark all remaining blocks as potentially containing data */ -+ for (; i < inftl->nb_blocks; i++) -+ inftl->PUtable[i] = BLOCK_NOTEXPLORED; -+ -+ /* Mark this boot record (NFTL MediaHeader) block as reserved */ -+ inftl->PUtable[block] = BLOCK_RESERVED; -+ -+#if 0 -+ /* Read Bad Erase Unit Table and modify PUtable[] accordingly */ -+ for (i = 0; i < inftl->nb_blocks; i++) { -+ if ((i & (SECTORSIZE - 1)) == 0) { -+ /* read one sector for every SECTORSIZE of blocks */ -+ if ((ret = MTD_READECC(inftl->mbd.mtd, -+ block * inftl->EraseSize + i + SECTORSIZE, -+ SECTORSIZE, &retlen, buf, -+ (char *)&oob, NULL)) < 0) { -+ printk(KERN_WARNING "INFTL: read of " -+ "bad sector table failed " -+ "(err %d)\n", ret); -+ kfree(inftl->VUtable); -+ kfree(inftl->PUtable); -+ return -1; -+ } -+ } -+ /* Mark the Bad Erase Unit as RESERVED in PUtable */ -+ if (buf[i & (SECTORSIZE - 1)] != 0xff) -+ inftl->PUtable[i] = BLOCK_RESERVED; -+ } -+#endif -+ -+ inftl->MediaUnit = block; -+ boot_record_count++; -+ } -+ -+ return boot_record_count ? 0 : -1; -+} -+ -+static int memcmpb(void *a, int c, int n) -+{ -+ int i; -+ for (i = 0; i < n; i++) { -+ if (c != ((unsigned char *)a)[i]) -+ return 1; -+ } -+ return 0; -+} -+ -+/* -+ * check_free_sector: check if a free sector is actually FREE, -+ * i.e. All 0xff in data and oob area. -+ */ -+static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address, -+ int len, int check_oob) -+{ -+ int i, retlen; -+ u8 buf[SECTORSIZE]; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: check_free_sectors(inftl=0x%x," -+ "address=0x%x,len=%d,check_oob=%d)\n", (int)inftl, -+ address, len, check_oob); -+ -+ for (i = 0; i < len; i += SECTORSIZE) { -+ /* -+ * We want to read the sector without ECC check here since a -+ * free sector does not have ECC syndrome on it yet. -+ */ -+ if (MTD_READ(inftl->mbd.mtd, address, SECTORSIZE, &retlen, buf) < 0) -+ return -1; -+ if (memcmpb(buf, 0xff, SECTORSIZE) != 0) -+ return -1; -+ -+ if (check_oob) { -+ if (MTD_READOOB(inftl->mbd.mtd, address, -+ inftl->mbd.mtd->oobsize, &retlen, buf) < 0) -+ return -1; -+ if (memcmpb(buf, 0xff, inftl->mbd.mtd->oobsize) != 0) -+ return -1; -+ } -+ address += SECTORSIZE; -+ } -+ -+ return 0; -+} -+ -+/* -+ * INFTL_format: format a Erase Unit by erasing ALL Erase Zones in the Erase -+ * Unit and Update INFTL metadata. Each erase operation is -+ * checked with check_free_sectors. -+ * -+ * Return: 0 when succeed, -1 on error. -+ * -+ * ToDo: 1. Is it neceressary to check_free_sector after erasing ?? -+ * 2. UnitSizeFactor != 0xFF -+ */ -+int INFTL_formatblock(struct INFTLrecord *inftl, int block) -+{ -+ int retlen; -+ struct inftl_unittail uci; -+ struct erase_info *instr = &inftl->instr; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=0x%x," -+ "block=%d)\n", (int)inftl, block); -+ -+ memset(instr, 0, sizeof(struct erase_info)); -+ -+ /* FIXME: Shouldn't we be setting the 'discarded' flag to zero -+ _first_? */ -+ -+ /* Use async erase interface, test return code */ -+ instr->addr = block * inftl->EraseSize; -+ instr->len = inftl->EraseSize; -+ MTD_ERASE(inftl->mbd.mtd, instr); -+ -+ if (instr->state == MTD_ERASE_FAILED) { -+ /* -+ * Could not format, FixMe: We should update the BadUnitTable -+ * both in memory and on disk. -+ */ -+ printk(KERN_WARNING "INFTL: error while formatting block %d\n", -+ block); -+ return -1; -+ } -+ -+ /* -+ * Check the "freeness" of Erase Unit before updating metadata. -+ * FixMe: is this check really necessary? Since we have check the -+ * return code after the erase operation. -+ */ -+ if (check_free_sectors(inftl, instr->addr, inftl->EraseSize, 1) != 0) -+ return -1; -+ -+ uci.EraseMark = cpu_to_le16(ERASE_MARK); -+ uci.EraseMark1 = cpu_to_le16(ERASE_MARK); -+ uci.Reserved[0] = 0; -+ uci.Reserved[1] = 0; -+ uci.Reserved[2] = 0; -+ uci.Reserved[3] = 0; -+ if (MTD_WRITEOOB(inftl->mbd.mtd, block * inftl->EraseSize + SECTORSIZE * 2 + -+ 8, 8, &retlen, (char *)&uci) < 0) -+ return -1; -+ return 0; -+} -+ -+/* -+ * format_chain: Format an invalid Virtual Unit chain. It frees all the Erase -+ * Units in a Virtual Unit Chain, i.e. all the units are disconnected. -+ * -+ * Since the chain is invalid then we will have to erase it from its -+ * head (normally for INFTL we go from the oldest). But if it has a -+ * loop then there is no oldest... -+ */ -+static void format_chain(struct INFTLrecord *inftl, unsigned int first_block) -+{ -+ unsigned int block = first_block, block1; -+ -+ printk(KERN_WARNING "INFTL: formatting chain at block %d\n", -+ first_block); -+ -+ for (;;) { -+ block1 = inftl->PUtable[block]; -+ -+ printk(KERN_WARNING "INFTL: formatting block %d\n", block); -+ if (INFTL_formatblock(inftl, block) < 0) { -+ /* -+ * Cannot format !!!! Mark it as Bad Unit, -+ * FixMe: update the BadUnitTable on disk. -+ */ -+ inftl->PUtable[block] = BLOCK_RESERVED; -+ } else { -+ inftl->PUtable[block] = BLOCK_FREE; -+ } -+ -+ /* Goto next block on the chain */ -+ block = block1; -+ -+ if (block == BLOCK_NIL || block >= inftl->lastEUN) -+ break; -+ } -+} -+ -+void INFTL_dumptables(struct INFTLrecord *s) -+{ -+ int i; -+ -+ printk("-------------------------------------------" -+ "----------------------------------\n"); -+ -+ printk("VUtable[%d] ->", s->nb_blocks); -+ for (i = 0; i < s->nb_blocks; i++) { -+ if ((i % 8) == 0) -+ printk("\n%04x: ", i); -+ printk("%04x ", s->VUtable[i]); -+ } -+ -+ printk("\n-------------------------------------------" -+ "----------------------------------\n"); -+ -+ printk("PUtable[%d-%d=%d] ->", s->firstEUN, s->lastEUN, s->nb_blocks); -+ for (i = 0; i <= s->lastEUN; i++) { -+ if ((i % 8) == 0) -+ printk("\n%04x: ", i); -+ printk("%04x ", s->PUtable[i]); -+ } -+ -+ printk("\n-------------------------------------------" -+ "----------------------------------\n"); -+ -+ printk("INFTL ->\n" -+ " EraseSize = %d\n" -+ " h/s/c = %d/%d/%d\n" -+ " numvunits = %d\n" -+ " firstEUN = %d\n" -+ " lastEUN = %d\n" -+ " numfreeEUNs = %d\n" -+ " LastFreeEUN = %d\n" -+ " nb_blocks = %d\n" -+ " nb_boot_blocks = %d", -+ s->EraseSize, s->heads, s->sectors, s->cylinders, -+ s->numvunits, s->firstEUN, s->lastEUN, s->numfreeEUNs, -+ s->LastFreeEUN, s->nb_blocks, s->nb_boot_blocks); -+ -+ printk("\n-------------------------------------------" -+ "----------------------------------\n"); -+} -+ -+void INFTL_dumpVUchains(struct INFTLrecord *s) -+{ -+ int logical, block, i; -+ -+ printk("-------------------------------------------" -+ "----------------------------------\n"); -+ -+ printk("INFTL Virtual Unit Chains:\n"); -+ for (logical = 0; logical < s->nb_blocks; logical++) { -+ block = s->VUtable[logical]; -+ if (block > s->nb_blocks) -+ continue; -+ printk(" LOGICAL %d --> %d ", logical, block); -+ for (i = 0; i < s->nb_blocks; i++) { -+ if (s->PUtable[block] == BLOCK_NIL) -+ break; -+ block = s->PUtable[block]; -+ printk("%d ", block); -+ } -+ printk("\n"); -+ } -+ -+ printk("-------------------------------------------" -+ "----------------------------------\n"); -+} -+ -+int INFTL_mount(struct INFTLrecord *s) -+{ -+ unsigned int block, first_block, prev_block, last_block; -+ unsigned int first_logical_block, logical_block, erase_mark; -+ int chain_length, do_format_chain; -+ struct inftl_unithead1 h0; -+ struct inftl_unittail h1; -+ int i, retlen; -+ u8 *ANACtable, ANAC; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_mount(inftl=0x%x)\n", (int)s); -+ -+ /* Search for INFTL MediaHeader and Spare INFTL Media Header */ -+ if (find_boot_record(s) < 0) { -+ printk(KERN_WARNING "INFTL: could not find valid boot record?\n"); -+ return -1; -+ } -+ -+ /* Init the logical to physical table */ -+ for (i = 0; i < s->nb_blocks; i++) -+ s->VUtable[i] = BLOCK_NIL; -+ -+ logical_block = block = BLOCK_NIL; -+ -+ /* Temporary buffer to store ANAC numbers. */ -+ ANACtable = kmalloc(s->nb_blocks * sizeof(u8), GFP_KERNEL); -+ memset(ANACtable, 0, s->nb_blocks); -+ -+ /* -+ * First pass is to explore each physical unit, and construct the -+ * virtual chains that exist (newest physical unit goes into VUtable). -+ * Any block that is in any way invalid will be left in the -+ * NOTEXPLORED state. Then at the end we will try to format it and -+ * mark it as free. -+ */ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 1, explore each unit\n"); -+ for (first_block = s->firstEUN; first_block <= s->lastEUN; first_block++) { -+ if (s->PUtable[first_block] != BLOCK_NOTEXPLORED) -+ continue; -+ -+ do_format_chain = 0; -+ first_logical_block = BLOCK_NIL; -+ last_block = BLOCK_NIL; -+ block = first_block; -+ -+ for (chain_length = 0; ; chain_length++) { -+ -+ if ((chain_length == 0) && -+ (s->PUtable[block] != BLOCK_NOTEXPLORED)) { -+ /* Nothing to do here, onto next block */ -+ break; -+ } -+ -+ if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, -+ 8, &retlen, (char *)&h0) < 0 || -+ MTD_READOOB(s->mbd.mtd, block * s->EraseSize + -+ 2 * SECTORSIZE + 8, 8, &retlen, (char *)&h1) < 0) { -+ /* Should never happen? */ -+ do_format_chain++; -+ break; -+ } -+ -+ logical_block = le16_to_cpu(h0.virtualUnitNo); -+ prev_block = le16_to_cpu(h0.prevUnitNo); -+ erase_mark = le16_to_cpu((h1.EraseMark | h1.EraseMark1)); -+ ANACtable[block] = h0.ANAC; -+ -+ /* Previous block is relative to start of Partition */ -+ if (prev_block < s->nb_blocks) -+ prev_block += s->firstEUN; -+ -+ /* Already explored partial chain? */ -+ if (s->PUtable[block] != BLOCK_NOTEXPLORED) { -+ /* Check if chain for this logical */ -+ if (logical_block == first_logical_block) { -+ if (last_block != BLOCK_NIL) -+ s->PUtable[last_block] = block; -+ } -+ break; -+ } -+ -+ /* Check for invalid block */ -+ if (erase_mark != ERASE_MARK) { -+ printk(KERN_WARNING "INFTL: corrupt block %d " -+ "in chain %d, chain length %d, erase " -+ "mark 0x%x?\n", block, first_block, -+ chain_length, erase_mark); -+ /* -+ * Assume end of chain, probably incomplete -+ * fold/erase... -+ */ -+ if (chain_length == 0) -+ do_format_chain++; -+ break; -+ } -+ -+ /* Check for it being free already then... */ -+ if ((logical_block == BLOCK_FREE) || -+ (logical_block == BLOCK_NIL)) { -+ s->PUtable[block] = BLOCK_FREE; -+ break; -+ } -+ -+ /* Sanity checks on block numbers */ -+ if ((logical_block >= s->nb_blocks) || -+ ((prev_block >= s->nb_blocks) && -+ (prev_block != BLOCK_NIL))) { -+ if (chain_length > 0) { -+ printk(KERN_WARNING "INFTL: corrupt " -+ "block %d in chain %d?\n", -+ block, first_block); -+ do_format_chain++; -+ } -+ break; -+ } -+ -+ if (first_logical_block == BLOCK_NIL) { -+ first_logical_block = logical_block; -+ } else { -+ if (first_logical_block != logical_block) { -+ /* Normal for folded chain... */ -+ break; -+ } -+ } -+ -+ /* -+ * Current block is valid, so if we followed a virtual -+ * chain to get here then we can set the previous -+ * block pointer in our PUtable now. Then move onto -+ * the previous block in the chain. -+ */ -+ s->PUtable[block] = BLOCK_NIL; -+ if (last_block != BLOCK_NIL) -+ s->PUtable[last_block] = block; -+ last_block = block; -+ block = prev_block; -+ -+ /* Check for end of chain */ -+ if (block == BLOCK_NIL) -+ break; -+ -+ /* Validate next block before following it... */ -+ if (block > s->lastEUN) { -+ printk(KERN_WARNING "INFTL: invalid previous " -+ "block %d in chain %d?\n", block, -+ first_block); -+ do_format_chain++; -+ break; -+ } -+ } -+ -+ if (do_format_chain) { -+ format_chain(s, first_block); -+ continue; -+ } -+ -+ /* -+ * Looks like a valid chain then. It may not really be the -+ * newest block in the chain, but it is the newest we have -+ * found so far. We might update it in later iterations of -+ * this loop if we find something newer. -+ */ -+ s->VUtable[first_logical_block] = first_block; -+ logical_block = BLOCK_NIL; -+ } -+ -+#ifdef CONFIG_MTD_DEBUG_VERBOSE -+ if (CONFIG_MTD_DEBUG_VERBOSE >= 2) -+ INFTL_dumptables(s); -+#endif -+ -+ /* -+ * Second pass, check for infinite loops in chains. These are -+ * possible because we don't update the previous pointers when -+ * we fold chains. No big deal, just fix them up in PUtable. -+ */ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 2, validate virtual chains\n"); -+ for (logical_block = 0; logical_block < s->numvunits; logical_block++) { -+ block = s->VUtable[logical_block]; -+ last_block = BLOCK_NIL; -+ -+ /* Check for free/reserved/nil */ -+ if (block >= BLOCK_RESERVED) -+ continue; -+ -+ ANAC = ANACtable[block]; -+ for (i = 0; i < s->numvunits; i++) { -+ if (s->PUtable[block] == BLOCK_NIL) -+ break; -+ if (s->PUtable[block] > s->lastEUN) { -+ printk(KERN_WARNING "INFTL: invalid prev %d, " -+ "in virtual chain %d\n", -+ s->PUtable[block], logical_block); -+ s->PUtable[block] = BLOCK_NIL; -+ -+ } -+ if (ANACtable[block] != ANAC) { -+ /* -+ * Chain must point back to itself. This is ok, -+ * but we will need adjust the tables with this -+ * newest block and oldest block. -+ */ -+ s->VUtable[logical_block] = block; -+ s->PUtable[last_block] = BLOCK_NIL; -+ break; -+ } -+ -+ ANAC--; -+ last_block = block; -+ block = s->PUtable[block]; -+ } -+ -+ if (i >= s->nb_blocks) { -+ /* -+ * Uhoo, infinite chain with valid ANACS! -+ * Format whole chain... -+ */ -+ format_chain(s, first_block); -+ } -+ } -+ -+#ifdef CONFIG_MTD_DEBUG_VERBOSE -+ if (CONFIG_MTD_DEBUG_VERBOSE >= 2) -+ INFTL_dumptables(s); -+ if (CONFIG_MTD_DEBUG_VERBOSE >= 2) -+ INFTL_dumpVUchains(s); -+#endif -+ -+ /* -+ * Third pass, format unreferenced blocks and init free block count. -+ */ -+ s->numfreeEUNs = 0; -+ s->LastFreeEUN = BLOCK_NIL; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 3, format unused blocks\n"); -+ for (block = s->firstEUN; block <= s->lastEUN; block++) { -+ if (s->PUtable[block] == BLOCK_NOTEXPLORED) { -+ printk("INFTL: unreferenced block %d, formatting it\n", -+ block); -+ if (INFTL_formatblock(s, block) < 0) -+ s->PUtable[block] = BLOCK_RESERVED; -+ else -+ s->PUtable[block] = BLOCK_FREE; -+ } -+ if (s->PUtable[block] == BLOCK_FREE) { -+ s->numfreeEUNs++; -+ if (s->LastFreeEUN == BLOCK_NIL) -+ s->LastFreeEUN = block; -+ } -+ } -+ -+ kfree(ANACtable); -+ return 0; -+} -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/Config.in linux/drivers/mtd/maps/Config.in ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/Config.in 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/Config.in 2004-11-17 18:17:59.049312400 +0100 -@@ -1,17 +1,14 @@ - # drivers/mtd/maps/Config.in - --# $Id$ -+# $Id$ - - mainmenu_option next_comment - - comment 'Mapping drivers for chip access' - --dep_tristate ' CFI Flash device in physical memory map' CONFIG_MTD_PHYSMAP $CONFIG_MTD_GEN_PROBE --if [ "$CONFIG_MTD_PHYSMAP" = "y" -o "$CONFIG_MTD_PHYSMAP" = "m" ]; then -- hex ' Physical start address of flash mapping' CONFIG_MTD_PHYSMAP_START 0x8000000 -- hex ' Physical length of flash mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000 -- int ' Bus width in octets' CONFIG_MTD_PHYSMAP_BUSWIDTH 2 --fi -+bool ' Support for non-linear mappings of flash chips' CONFIG_MTD_COMPLEX_MAPPINGS -+ -+bool ' CFI Flash device in physical memory map' CONFIG_MTD_PHYSMAP $CONFIG_MTD_GEN_PROBE - - if [ "$CONFIG_SPARC" = "y" -o "$CONFIG_SPARC64" = "y" ]; then - dep_tristate ' Sun Microsystems userflash support' CONFIG_MTD_SUN_UFLASH $CONFIG_MTD_CFI -@@ -21,51 +18,68 @@ - dep_tristate ' CFI Flash device mapped on Photron PNC-2000' CONFIG_MTD_PNC2000 $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS - dep_tristate ' CFI Flash device mapped on AMD SC520 CDP' CONFIG_MTD_SC520CDP $CONFIG_MTD_CFI - dep_tristate ' CFI Flash device mapped on AMD NetSc520' CONFIG_MTD_NETSC520 $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS -- dep_tristate ' CFI Flash device mapped on Arcom SBC-GXx boards' CONFIG_MTD_SBC_GXX $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_PARTITIONS -- dep_tristate ' CFI Flash device mapped on Arcom ELAN-104NC' CONFIG_MTD_ELAN_104NC $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_PARTITIONS -+ dep_tristate ' CFI Flash device mapped on Arcom SBC-GXx boards' CONFIG_MTD_SBC_GXX $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_PARTITIONS $CONFIG_MTD_COMPLEX_MAPPINGS -+ dep_tristate ' CFI Flash device mapped on Arcom ELAN-104NC' CONFIG_MTD_ELAN_104NC $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_PARTITIONS $CONFIG_MTD_COMPLEX_MAPPINGS - dep_tristate ' CFI Flash device mapped on DIL/Net PC' CONFIG_MTD_DILNETPC $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_PARTITIONS $CONFIG_MTD_CONCAT - if [ "$CONFIG_MTD_DILNETPC" = "y" -o "$CONFIG_MTD_DILNETPC" = "m" ]; then - hex ' Size of boot partition' CONFIG_MTD_DILNETPC_BOOTSIZE 0x80000 - fi -- dep_tristate ' JEDEC Flash device mapped on Mixcom piggyback card' CONFIG_MTD_MIXMEM $CONFIG_MTD_JEDEC -- dep_tristate ' JEDEC Flash device mapped on Octagon 5066 SBC' CONFIG_MTD_OCTAGON $CONFIG_MTD_JEDEC -- dep_tristate ' JEDEC Flash device mapped on Tempustech VMAX SBC301' CONFIG_MTD_VMAX $CONFIG_MTD_JEDEC -+ dep_tristate ' JEDEC Flash device mapped on Octagon 5066 SBC' CONFIG_MTD_OCTAGON $CONFIG_MTD_JEDEC $CONFIG_MTD_COMPLEX_MAPPINGS -+ dep_tristate ' JEDEC Flash device mapped on Tempustech VMAX SBC301' CONFIG_MTD_VMAX $CONFIG_MTD_JEDEC $CONFIG_MTD_COMPLEX_MAPPINGS - dep_tristate ' Flash device mapped with DOCCS on NatSemi SCx200' CONFIG_MTD_SCx200_DOCFLASH $CONFIG_MTD_CFI - dep_tristate ' BIOS flash chip on Intel L440GX boards' CONFIG_MTD_L440GX $CONFIG_MTD_JEDECPROBE - dep_tristate ' ROM connected to AMD76X southbridge' CONFIG_MTD_AMD76XROM $CONFIG_MTD_GEN_PROBE -- dep_tristate ' ROM connected to Intel Hub Controller 2' CONFIG_MTD_ICH2ROM $CONFIG_MTD_JEDECPROBE -+ dep_tristate ' ROM connected to Intel Hub Controller 2/3/4/5' CONFIG_MTD_ICHXROM $CONFIG_MTD_JEDECPROBE $CONFIG_MTD_COMPLEX_MAPPINGS - dep_tristate ' CFI Flash device mapped on SnapGear/SecureEdge' CONFIG_MTD_NETtel $CONFIG_MTD_PARTITIONS - dep_tristate ' BIOS flash chip on Intel SCB2 boards' CONFIG_MTD_SCB2_FLASH $CONFIG_MTD_GEN_PROBE - fi - --if [ "$CONFIG_PPC" = "y" ]; then -- dep_tristate ' CFI Flash device mapped on TQM8XXL' CONFIG_MTD_TQM8XXL $CONFIG_MTD_CFI $CONFIG_TQM8xxL -+if [ "$CONFIG_PPC32" = "y" ]; then -+ if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "y" ]; then -+ dep_tristate ' Flash device on SBC8240' CONFIG_MTD_SBC8240 $CONFIG_MTD_JEDECPROBE -+ fi -+ if [ "$CONFIG_8xx" = "y" ]; then -+ if [ "$CONFIG_TQM8xxL" = "y" ]; then -+ dep_tristate ' CFI Flash device mapped on TQM8XXL' CONFIG_MTD_TQM8XXL $CONFIG_MTD_CFI -+ fi -+ if [ "$CONFIG_RPXLITE" = "y" -o "$CONFIG_RPXCLASSIC" = "y" ]; then - dep_tristate ' CFI Flash device mapped on RPX Lite or CLLF' CONFIG_MTD_RPXLITE $CONFIG_MTD_CFI -+ fi -+ if [ "$CONFIG_MBX" = "y" ]; then - dep_tristate ' System flash on MBX860 board' CONFIG_MTD_MBX860 $CONFIG_MTD_CFI -+ fi -+ if [ "$CONFIG_DBOX2" = "y" ]; then - dep_tristate ' CFI Flash device mapped on D-Box2' CONFIG_MTD_DBOX2 $CONFIG_MTD_CFI -+ fi - dep_tristate ' CFI Flash device mapping on FlagaDM' CONFIG_MTD_CFI_FLAGADM $CONFIG_MTD_CFI -- dep_tristate ' CFI Flash device mapped on IBM Redwood-4/5' CONFIG_MTD_REDWOOD $CONFIG_MTD_CFI -+ fi -+ if [ "$CONFIG_4xx" = "y" ]; then -+ if [ "$CONFIG_40x" = "y" ]; then -+ if [ "$CONFIG_REDWOOD_4" = "y" -o "$CONFIG_REDWOOD_5" = "y" -o "$CONFIG_REDWOOD_6" = "y" ]; then -+ dep_tristate ' CFI Flash device mapped on IBM Redwood' CONFIG_MTD_REDWOOD $CONFIG_MTD_CFI -+ fi -+ dep_tristate ' CFI Flash device mapped on IBM Beech' CONFIG_MTD_BEECH $CONFIG_MTD_CFI $CONFIG_BEECH -+ dep_tristate ' CFI Flash device mapped on IBM Arctic' CONFIG_MTD_ARCTIC $CONFIG_MTD_CFI $CONFIG_ARCTIC2 -+ fi -+ if [ "$CONFIG_440" = "y" ]; then -+ dep_tristate ' Flash devices mapped on IBM Ebony' CONFIG_MTD_EBONY $CONFIG_MTD_CFI $CONFIG_EBONY -+ fi -+ fi - fi - --if [ "$CONFIG_MIPS" = "y" ]; then -- dep_tristate ' Pb1000 MTD support' CONFIG_MTD_PB1000 $CONFIG_MIPS_PB1000 -- dep_tristate ' Pb1500 MTD support' CONFIG_MTD_PB1500 $CONFIG_MIPS_PB1500 -- dep_tristate ' Pb1100 MTD support' CONFIG_MTD_PB1100 $CONFIG_MIPS_PB1100 -- dep_tristate ' Bosporus MTD support' CONFIG_MTD_BOSPORUS $CONFIG_MIPS_BOSPORUS -- dep_tristate ' XXS1500 boot flash device' CONFIG_MTD_XXS1500 $CONFIG_MIPS_XXS1500 -- dep_tristate ' MTX-1 flash device' CONFIG_MTD_MTX1 $CONFIG_MIPS_MTX1 -- if [ "$CONFIG_MTD_PB1500" = "y" -o "$CONFIG_MTD_PB1500" = "m" \ -- -o "$CONFIG_MTD_PB1100" = "y" -o "$CONFIG_MTD_PB1100" = "m" ]; then -- bool ' Pb[15]00 boot flash device' CONFIG_MTD_PB1500_BOOT -- bool ' Pb[15]00 user flash device (2nd 32MiB bank)' CONFIG_MTD_PB1500_USER -+if [ "$CONFIG_MIPS" = "y" -o "$CONFIG_MIPS64" = "y" ]; then -+ if [ "$CONFIG_MIPS_PB1000" = "y" -o "$CONFIG_MIPS_PB1100" = "y" -o "$CONFIG_MIPS_PB1500" = "y" ]; then -+ tristate ' Pb1x00 MTD support' CONFIG_MTD_PB1XXX -+ if [ "$CONFIG_MIPS_PB1500" = "y" -o "$CONFIG_MIPS_PB1100" = "m" ]; then -+ bool ' Pb1x00 boot flash device' CONFIG_MTD_PB1500_BOOT -+ bool ' Pb1x00 user flash device (2nd 32MiB bank)' CONFIG_MTD_PB1500_USER -+ fi - fi - tristate ' Db1x00 MTD support' CONFIG_MTD_DB1X00 - if [ "$CONFIG_MTD_DB1X00" = "y" -o "$CONFIG_MTD_DB1X00" = "m" ]; then - bool ' Db1x00 boot flash device' CONFIG_MTD_DB1X00_BOOT - bool ' Db1x00 user flash device (2nd bank)' CONFIG_MTD_DB1X00_USER - fi -- dep_tristate ' Hydrogen 3 MTD support' CONFIG_MTD_HYDIII $CONFIG_MIPS_HYDROGEN3 -- dep_tristate ' Mirage MTD support' CONFIG_MTD_MIRAGE $CONFIG_MIPS_MIRAGE - dep_tristate ' Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board' CONFIG_MTD_CSTM_MIPS_IXX $CONFIG_MTD_CFI $CONFIG_MTD_JEDEC $CONFIG_MTD_PARTITIONS - if [ "$CONFIG_MTD_CSTM_MIPS_IXX" = "y" -o "$CONFIG_MTD_CSTM_MIPS_IXX" = "m" ]; then - hex ' Physical start address of flash mapping' CONFIG_MTD_CSTM_MIPS_IXX_START 0x8000000 -@@ -73,7 +87,7 @@ - int ' Bus width in octets' CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH 2 - fi - dep_tristate ' Momenco Ocelot boot flash device' CONFIG_MTD_OCELOT $CONFIG_MOMENCO_OCELOT -- dep_tristate ' LASAT flash device' CONFIG_MTD_LASAT $CONFIG_MTD_CFI $CONFIG_LASAT -+ dep_tristate ' LASAT flash device' CONFIG_MTD_LASAT $CONFIG_LASAT - fi - - if [ "$CONFIG_SUPERH" = "y" ]; then -@@ -85,21 +99,24 @@ - fi - - if [ "$CONFIG_ARM" = "y" ]; then -- dep_tristate ' CFI Flash device mapped on Nora' CONFIG_MTD_NORA $CONFIG_MTD_CFI - dep_tristate ' CFI Flash device mapped on ARM Integrator/P720T' CONFIG_MTD_ARM_INTEGRATOR $CONFIG_MTD_CFI - dep_tristate ' Cirrus CDB89712 evaluation board mappings' CONFIG_MTD_CDB89712 $CONFIG_MTD_CFI $CONFIG_ARCH_CDB89712 - dep_tristate ' CFI Flash device mapped on StrongARM SA11x0' CONFIG_MTD_SA1100 $CONFIG_MTD_CFI $CONFIG_ARCH_SA1100 $CONFIG_MTD_PARTITIONS -- dep_tristate ' CFI Flash device mapped on DC21285 Footbridge' CONFIG_MTD_DC21285 $CONFIG_MTD_CFI $CONFIG_ARCH_FOOTBRIDGE -+ dep_tristate ' CFI Flash device mapped on DC21285 Footbridge' CONFIG_MTD_DC21285 $CONFIG_MTD_CFI $CONFIG_ARCH_FOOTBRIDGE $CONFIG_MTD_COMPLEX_MAPPINGS - dep_tristate ' CFI Flash device mapped on the XScale IQ80310 board' CONFIG_MTD_IQ80310 $CONFIG_MTD_CFI $CONFIG_ARCH_IQ80310 -+ dep_tristate ' CFI Flash device mapped on the XScale Lubbock board' CONFIG_MTD_LUBBOCK $CONFIG_MTD_CFI $CONFIG_ARCH_LUBBOCK -+ dep_tristate ' CFI Flash device mapped on XScale IXP425 systems' CONFIG_MTD_IXP425 $CONFIG_MTD_CFI $CONFIG_MTD_COMPLEX_MAPPINGS - dep_tristate ' CFI Flash device mapped on Epxa10db' CONFIG_MTD_EPXA10DB $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_CAMELOT - dep_tristate ' CFI Flash device mapped on the FortuNet board' CONFIG_MTD_FORTUNET $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_SA1100_FORTUNET - dep_tristate ' NV-RAM mapping AUTCPU12 board' CONFIG_MTD_AUTCPU12 $CONFIG_ARCH_AUTCPU12 - dep_tristate ' CFI Flash device mapped on EDB7312' CONFIG_MTD_EDB7312 $CONFIG_MTD_CFI -+ dep_tristate ' CFI Flash device mapped on Hynix evaluation boards' CONFIG_MTD_H720X $CONFIG_MTD_CFI - dep_tristate ' JEDEC Flash device mapped on impA7' CONFIG_MTD_IMPA7 $CONFIG_MTD_JEDECPROBE - dep_tristate ' JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame' CONFIG_MTD_CEIVA $CONFIG_MTD_JEDECPROBE $CONFIG_ARCH_CEIVA -+ dep_tristate ' NOR Flash device on TOTO board' CONFIG_MTD_NOR_TOTO $CONFIG_MTD $CONFIG_OMAP_TOTO - fi - if [ "$CONFIG_ALPHA" = "y" ]; then -- dep_tristate ' Flash chip mapping on TSUNAMI' CONFIG_MTD_TSUNAMI $CONFIG_MTD_GENPROBE -+ dep_tristate ' Flash chip mapping on TSUNAMI' CONFIG_MTD_TSUNAMI $CONFIG_MTD_GENPROBE $CONFIG_MTD_COMPLEX_MAPPINGS - fi - - if [ "$CONFIG_UCLINUX" = "y" ]; then -@@ -107,7 +124,7 @@ - fi - - # This needs CFI or JEDEC, depending on the cards found. --dep_tristate ' PCI MTD driver' CONFIG_MTD_PCI $CONFIG_MTD $CONFIG_PCI --dep_tristate ' PCMCIA MTD driver' CONFIG_MTD_PCMCIA $CONFIG_MTD $CONFIG_PCMCIA -+dep_tristate ' PCI MTD driver' CONFIG_MTD_PCI $CONFIG_MTD $CONFIG_PCI $CONFIG_MTD_COMPLEX_MAPPINGS -+dep_tristate ' PCMCIA MTD driver' CONFIG_MTD_PCMCIA $CONFIG_MTD $CONFIG_PCMCIA $CONFIG_MTD_COMPLEX_MAPPINGS - - endmenu -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/Makefile linux/drivers/mtd/maps/Makefile ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/Makefile 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/Makefile 2004-11-17 18:17:59.051312096 +0100 -@@ -1,12 +1,16 @@ - # - # linux/drivers/maps/Makefile - # --# $Id$ -+# $Id$ - --BELOW25 := $(shell echo $(PATCHLEVEL) | sed s/[1234]/y/) -- --ifeq ($(BELOW25),y) -+ifeq ($(PATCHLEVEL),4) - O_TARGET := mapslink.o -+export-objs := map_funcs.o -+endif -+ -+ -+ifeq ($(CONFIG_MTD_COMPLEX_MAPPINGS),y) -+obj-$(CONFIG_MTD) += map_funcs.o - endif - - # Chip mappings -@@ -21,19 +25,13 @@ - obj-$(CONFIG_MTD_IQ80310) += iq80310.o - obj-$(CONFIG_MTD_L440GX) += l440gx.o - obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o --obj-$(CONFIG_MTD_ICH2ROM) += ich2rom.o -+obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o - obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o -+obj-$(CONFIG_MTD_LUBBOCK) += lubbock-flash.o - obj-$(CONFIG_MTD_MBX860) += mbx860.o --obj-$(CONFIG_MTD_NORA) += nora.o - obj-$(CONFIG_MTD_CEIVA) += ceiva.o - obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o --ifneq ($(CONFIG_MTD_PHYSMAP),n) -- ifeq ($(CONFIG_MTD_PHYSMAP_BUSWIDTH),8) -- obj-$(CONFIG_MTD_PHYSMAP) += physmap64.o -- else -- obj-$(CONFIG_MTD_PHYSMAP) += physmap.o -- endif --endif -+obj-$(CONFIG_MTD_PHYSMAP) += physmap.o - obj-$(CONFIG_MTD_PNC2000) += pnc2000.o - obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o - obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o -@@ -49,15 +47,9 @@ - obj-$(CONFIG_MTD_OCELOT) += ocelot.o - obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o - obj-$(CONFIG_MTD_PCI) += pci.o --obj-$(CONFIG_MTD_PB1000) += pb1xxx-flash.o --obj-$(CONFIG_MTD_PB1100) += pb1xxx-flash.o --obj-$(CONFIG_MTD_PB1500) += pb1xxx-flash.o --obj-$(CONFIG_MTD_XXS1500) += xxs1500.o --obj-$(CONFIG_MTD_MTX1) += mtx-1.o --obj-$(CONFIG_MTD_LASAT) += lasat.o -+obj-$(CONFIG_MTD_PB1XXX) += pb1xxx-flash.o - obj-$(CONFIG_MTD_DB1X00) += db1x00-flash.o --obj-$(CONFIG_MTD_HYDIII) += hydrogen3-flash.o --obj-$(CONFIG_MTD_BOSPORUS) += pb1xxx-flash.o -+obj-$(CONFIG_MTD_LASAT) += lasat.o - obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o - obj-$(CONFIG_MTD_EDB7312) += edb7312.o - obj-$(CONFIG_MTD_IMPA7) += impa7.o -@@ -66,6 +58,13 @@ - obj-$(CONFIG_MTD_UCLINUX) += uclinux.o - obj-$(CONFIG_MTD_NETtel) += nettel.o - obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o --obj-$(CONFIG_MTD_MIRAGE) += mirage-flash.o -+obj-$(CONFIG_MTD_EBONY) += ebony.o -+obj-$(CONFIG_MTD_BEECH) += beech-mtd.o -+obj-$(CONFIG_MTD_ARCTIC) += arctic-mtd.o -+obj-$(CONFIG_MTD_H720X) += h720x-flash.o -+obj-$(CONFIG_MTD_SBC8240) += sbc8240.o -+obj-$(CONFIG_MTD_NOR_TOTO) += omap-toto-flash.o -+obj-$(CONFIG_MTD_MPC1211) += mpc1211.o -+obj-$(CONFIG_MTD_IXP425) += ixp425.o - --include $(TOPDIR)/Rules.make -+-include $(TOPDIR)/Rules.make -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/amd76xrom.c linux/drivers/mtd/maps/amd76xrom.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/amd76xrom.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/amd76xrom.c 2004-11-17 18:17:59.052311944 +0100 -@@ -2,12 +2,13 @@ - * amd76xrom.c - * - * Normal mappings of chips in physical memory -- * $Id$ -+ * $Id$ - */ - - #include - #include - #include -+#include - #include - #include - #include -@@ -16,77 +17,59 @@ - #include - - -+#define xstr(s) str(s) -+#define str(s) #s -+#define MOD_NAME xstr(KBUILD_BASENAME) -+ -+#define MTD_DEV_NAME_LENGTH 16 -+ - struct amd76xrom_map_info { - struct map_info map; - struct mtd_info *mtd; - unsigned long window_addr; - u32 window_start, window_size; - struct pci_dev *pdev; -+ struct resource window_rsrc; -+ struct resource rom_rsrc; -+ char mtd_name[MTD_DEV_NAME_LENGTH]; - }; - --static __u8 amd76xrom_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --static __u16 amd76xrom_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} - --static __u32 amd76xrom_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -+static struct amd76xrom_map_info amd76xrom_map = { -+ .map = { -+ .name = MOD_NAME, -+ .size = 0, -+ .buswidth = 1, -+ } -+ /* remaining fields of structure are initialized to 0 */ -+}; - --static void amd76xrom_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} - --static void amd76xrom_write8(struct map_info *map, __u8 d, unsigned long adr) -+static void amd76xrom_cleanup(struct amd76xrom_map_info *info) - { -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -+ u8 byte; - --static void amd76xrom_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -+ /* Disable writes through the rom window */ -+ pci_read_config_byte(info->pdev, 0x40, &byte); -+ pci_write_config_byte(info->pdev, 0x40, byte & ~1); - --static void amd76xrom_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -+ if (info->mtd) { -+ del_mtd_device(info->mtd); -+ map_destroy(info->mtd); -+ info->mtd = NULL; -+ info->map.virt = 0; -+ } -+ if (info->rom_rsrc.parent) -+ release_resource(&info->rom_rsrc); -+ if (info->window_rsrc.parent) -+ release_resource(&info->window_rsrc); - --static void amd76xrom_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); -+ if (info->window_addr) { -+ iounmap((void *)(info->window_addr)); -+ info->window_addr = 0; -+ } - } - --static struct amd76xrom_map_info amd76xrom_map = { -- map: { -- name: "AMD76X rom", -- size: 0, -- buswidth: 1, -- read8: amd76xrom_read8, -- read16: amd76xrom_read16, -- read32: amd76xrom_read32, -- copy_from: amd76xrom_copy_from, -- write8: amd76xrom_write8, -- write16: amd76xrom_write16, -- write32: amd76xrom_write32, -- copy_to: amd76xrom_copy_to, -- /* The standard rom socket is for single power supply chips -- * that don't have an extra vpp. -- */ -- }, -- mtd: 0, -- window_addr: 0, --}; - - static int __devinit amd76xrom_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -@@ -97,6 +80,10 @@ - u8 segen_bits; - }; - static struct rom_window rom_window[] = { -+ /* -+ * Need the 5MiB window for chips that have block lock/unlock -+ * registers located below 4MiB window. -+ */ - { 0xffb00000, 5*1024*1024, (1<<7) | (1<<6), }, - { 0xffc00000, 4*1024*1024, (1<<7), }, - { 0xffff0000, 64*1024, 0 }, -@@ -112,19 +99,29 @@ - int i; - u32 rom_size; - -+ info->pdev = pdev; - window = &rom_window[0]; --#if 0 -- while(window->size) { -- if (request_mem_region(window->start, window->size, "amd76xrom")) { -- break; -- } -- window++; -- } -- if (!window->size) { -- printk(KERN_ERR "amd76xrom: cannot reserve rom window\n"); -- goto err_out_none; -+ -+ while (window->size) { -+ /* -+ * Try to reserve the window mem region. If this fails then -+ * it is likely due to a fragment of the window being -+ * "reseved" by the BIOS. In the case that the -+ * request_mem_region() fails then once the rom size is -+ * discovered we will try to reserve the unreserved fragment. -+ */ -+ info->window_rsrc.name = MOD_NAME; -+ info->window_rsrc.start = window->start; -+ info->window_rsrc.end = window->start + window->size - 1; -+ info->window_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; -+ if (request_resource(&iomem_resource, &info->window_rsrc)) { -+ info->window_rsrc.parent = NULL; -+ printk(KERN_ERR MOD_NAME -+ " %s(): Unable to register resource" -+ " 0x%.08lx-0x%.08lx - kernel bug?\n", -+ __func__, -+ info->window_rsrc.start, info->window_rsrc.end); - } --#endif - - /* Enable the selected rom window */ - pci_read_config_byte(pdev, 0x43, &byte); -@@ -136,49 +133,94 @@ - - /* FIXME handle registers 0x80 - 0x8C the bios region locks */ - -- printk(KERN_NOTICE "amd76xrom window : %x at %x\n", -+ printk(KERN_NOTICE MOD_NAME " window : %x at %x\n", - window->size, window->start); - /* For write accesses caches are useless */ -- info->window_addr = (unsigned long)ioremap_nocache(window->start, window->size); -+ info->window_addr = -+ (unsigned long)ioremap_nocache(window->start, -+ window->size); - - if (!info->window_addr) { - printk(KERN_ERR "Failed to ioremap\n"); -- goto err_out_free_mmio_region; -+ continue; - } -- info->mtd = 0; -+ -+ info->mtd = NULL; -+ - for(i = 0; (rom_size = rom_probe_sizes[i]); i++) { - char **chip_type; - if (rom_size > window->size) { - continue; - } -- info->map.map_priv_1 = -+ info->map.phys = window->start + window->size - rom_size; -+ info->map.virt = - info->window_addr + window->size - rom_size; - info->map.size = rom_size; -+ simple_map_init(&info->map); - chip_type = rom_probe_types; - for(; !info->mtd && *chip_type; chip_type++) { - info->mtd = do_map_probe(*chip_type, &amd76xrom_map.map); - } -- if (info->mtd) { -- break; -- } -+ if (info->mtd) goto found_mtd; - } -- if (!info->mtd) { -- goto err_out_iounmap; -+ iounmap((void *)(info->window_addr)); -+ info->window_addr = 0; -+ -+ /* Disable writes through the rom window */ -+ pci_read_config_byte(pdev, 0x40, &byte); -+ pci_write_config_byte(pdev, 0x40, byte & ~1); -+ -+ window++; - } -- printk(KERN_NOTICE "amd76xrom chip at offset: %x\n", -+ goto failed; -+ -+ found_mtd: -+ printk(KERN_NOTICE MOD_NAME " chip at offset: 0x%x\n", - window->size - rom_size); - -- info->mtd->module = THIS_MODULE; -+ info->mtd->owner = THIS_MODULE; -+ -+ if (!info->window_rsrc.parent) { -+ /* failed to reserve entire window - try fragments */ -+ info->window_rsrc.name = MOD_NAME; -+ info->window_rsrc.start = window->start; -+ info->window_rsrc.end = window->start + window->size - rom_size - 1; -+ info->window_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; -+ if (request_resource(&iomem_resource, &info->window_rsrc)) { -+ printk(KERN_ERR MOD_NAME -+ ": cannot reserve window resource fragment\n"); -+ goto failed; -+ } -+ } -+ - add_mtd_device(info->mtd); - info->window_start = window->start; - info->window_size = window->size; -+ -+ if (info->window_rsrc.parent) { -+ /* -+ * Registering the MTD device in iomem may not be possible -+ * if there is a BIOS "reserved" and BUSY range. If this -+ * fails then continue anyway. -+ */ -+ snprintf(info->mtd_name, MTD_DEV_NAME_LENGTH, -+ "mtd%d", info->mtd->index); -+ -+ info->rom_rsrc.name = info->mtd_name; -+ info->rom_rsrc.start = window->start + window->size - rom_size; -+ info->rom_rsrc.end = window->start + window->size - 1; -+ info->rom_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; -+ if (request_resource(&info->window_rsrc, &info->rom_rsrc)) { -+ printk(KERN_ERR MOD_NAME -+ ": cannot reserve MTD resource\n"); -+ info->rom_rsrc.parent = NULL; -+ } -+ } -+ - return 0; - --err_out_iounmap: -- iounmap((void *)(info->window_addr)); --err_out_free_mmio_region: -- release_mem_region(window->start, window->size); --err_out_none: -+ failed: -+ amd76xrom_cleanup(info); - return -ENODEV; - } - -@@ -186,21 +228,8 @@ - static void __devexit amd76xrom_remove_one (struct pci_dev *pdev) - { - struct amd76xrom_map_info *info = &amd76xrom_map; -- u8 byte; -- -- del_mtd_device(info->mtd); -- map_destroy(info->mtd); -- info->mtd = 0; -- info->map.map_priv_1 = 0; -- -- iounmap((void *)(info->window_addr)); -- info->window_addr = 0; -- -- /* Disable writes through the rom window */ -- pci_read_config_byte(pdev, 0x40, &byte); -- pci_write_config_byte(pdev, 0x40, byte & ~1); - -- release_mem_region(info->window_start, info->window_size); -+ amd76xrom_cleanup(info); - } - - static struct pci_device_id amd76xrom_pci_tbl[] __devinitdata = { -@@ -208,6 +237,7 @@ - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7440, - PCI_ANY_ID, PCI_ANY_ID, }, -+ { PCI_VENDOR_ID_AMD, 0x7468 }, /* amd8111 support */ - { 0, } - }; - -@@ -215,10 +245,10 @@ - - #if 0 - static struct pci_driver amd76xrom_driver = { -- name: "amd76xrom", -- id_table: amd76xrom_pci_tbl, -- probe: amd76xrom_init_one, -- remove: amd76xrom_remove_one, -+ .name = MOD_NAME, -+ .id_table = amd76xrom_pci_tbl, -+ .probe = amd76xrom_init_one, -+ .remove = amd76xrom_remove_one, - }; - #endif - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/arctic-mtd.c linux/drivers/mtd/maps/arctic-mtd.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/arctic-mtd.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/arctic-mtd.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,135 @@ -+/* -+ * $Id$ -+ * -+ * drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for -+ * IBM 405LP Arctic boards. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the 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 -+ * -+ * Copyright (C) 2002, International Business Machines Corporation -+ * All Rights Reserved. -+ * -+ * Bishop Brock -+ * IBM Research, Austin Center for Low-Power Computing -+ * bcbrock@us.ibm.com -+ * March 2002 -+ * -+ * modified for Arctic by, -+ * David Gibson -+ * IBM OzLabs, Canberra, Australia -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* -+ * 0 : 0xFE00 0000 - 0xFEFF FFFF : Filesystem 1 (16MiB) -+ * 1 : 0xFF00 0000 - 0xFF4F FFFF : kernel (5.12MiB) -+ * 2 : 0xFF50 0000 - 0xFFF5 FFFF : Filesystem 2 (10.624MiB) (if non-XIP) -+ * 3 : 0xFFF6 0000 - 0xFFFF FFFF : PIBS Firmware (640KiB) -+ */ -+ -+#define FFS1_SIZE 0x01000000 /* 16MiB */ -+#define KERNEL_SIZE 0x00500000 /* 5.12MiB */ -+#define FFS2_SIZE 0x00a60000 /* 10.624MiB */ -+#define FIRMWARE_SIZE 0x000a0000 /* 640KiB */ -+ -+ -+#define NAME "Arctic Linux Flash" -+#define PADDR SUBZERO_BOOTFLASH_PADDR -+#define BUSWIDTH 2 -+#define SIZE SUBZERO_BOOTFLASH_SIZE -+#define PARTITIONS 4 -+ -+/* Flash memories on these boards are memory resources, accessed big-endian. */ -+ -+{ -+ /* do nothing for now */ -+} -+ -+static struct map_info arctic_mtd_map = { -+ .name = NAME, -+ .size = SIZE, -+ .buswidth = BUSWIDTH, -+ .phys = PADDR, -+}; -+ -+static struct mtd_info *arctic_mtd; -+ -+static struct mtd_partition arctic_partitions[PARTITIONS] = { -+ { .name = "Filesystem", -+ .size = FFS1_SIZE, -+ .offset = 0,}, -+ { .name = "Kernel", -+ .size = KERNEL_SIZE, -+ .offset = FFS1_SIZE,}, -+ { .name = "Filesystem", -+ .size = FFS2_SIZE, -+ .offset = FFS1_SIZE + KERNEL_SIZE,}, -+ { .name = "Firmware", -+ .size = FIRMWARE_SIZE, -+ .offset = SUBZERO_BOOTFLASH_SIZE - FIRMWARE_SIZE,}, -+}; -+ -+static int __init -+init_arctic_mtd(void) -+{ -+ printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); -+ -+ arctic_mtd_map.virt = (unsigned long) ioremap(PADDR, SIZE); -+ -+ if (!arctic_mtd_map.virt) { -+ printk("%s: failed to ioremap 0x%x\n", NAME, PADDR); -+ return -EIO; -+ } -+ simple_map_init(&arctic_mtd_map); -+ -+ printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8); -+ arctic_mtd = do_map_probe("cfi_probe", &arctic_mtd_map); -+ -+ if (!arctic_mtd) -+ return -ENXIO; -+ -+ arctic_mtd->owner = THIS_MODULE; -+ -+ return add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS); -+} -+ -+static void __exit -+cleanup_arctic_mtd(void) -+{ -+ if (arctic_mtd) { -+ del_mtd_partitions(arctic_mtd); -+ map_destroy(arctic_mtd); -+ iounmap((void *) arctic_mtd_map.virt); -+ } -+} -+ -+module_init(init_arctic_mtd); -+module_exit(cleanup_arctic_mtd); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("David Gibson "); -+MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Arctic boards"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/autcpu12-nvram.c linux/drivers/mtd/maps/autcpu12-nvram.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/autcpu12-nvram.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/autcpu12-nvram.c 2004-11-17 18:17:59.059310880 +0100 -@@ -2,7 +2,7 @@ - * NV-RAM memory access on autcpu12 - * (C) 2002 Thomas Gleixner (gleixner@autronix.de) - * -- * $Id$ -+ * $Id$ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -32,80 +33,27 @@ - #include - #include - --__u8 autcpu12_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 autcpu12_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 autcpu12_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void autcpu12_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void autcpu12_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void autcpu12_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void autcpu12_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void autcpu12_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- while(len) { -- __raw_writeb(*(unsigned char *) from, map->map_priv_1 + to); -- from++; -- to++; -- len--; -- } --} - - static struct mtd_info *sram_mtd; - - struct map_info autcpu12_sram_map = { -- name: "SRAM", -- size: 32768, -- buswidth: 8, -- read8: autcpu12_read8, -- read16: autcpu12_read16, -- read32: autcpu12_read32, -- copy_from: autcpu12_copy_from, -- write8: autcpu12_write8, -- write16: autcpu12_write16, -- write32: autcpu12_write32, -- copy_to: autcpu12_copy_to -+ .name = "SRAM", -+ .size = 32768, -+ .buswidth = 4, -+ .phys = 0x12000000, - }; - - static int __init init_autcpu12_sram (void) - { - int err, save0, save1; - -- autcpu12_sram_map.map_priv_1 = (unsigned long)ioremap(0x12000000, SZ_128K); -- if (!autcpu12_sram_map.map_priv_1) { -+ autcpu12_sram_map.virt = (unsigned long)ioremap(0x12000000, SZ_128K); -+ if (!autcpu12_sram_map.virt) { - printk("Failed to ioremap autcpu12 NV-RAM space\n"); - err = -EIO; - goto out; - } -+ simple_map_init(&autcpu_sram_map); - - /* - * Check for 32K/128K -@@ -115,20 +63,20 @@ - * Read and check result on ofs 0x0 - * Restore contents - */ -- save0 = autcpu12_read32(&autcpu12_sram_map,0); -- save1 = autcpu12_read32(&autcpu12_sram_map,0x10000); -- autcpu12_write32(&autcpu12_sram_map,~save0,0x10000); -+ save0 = map_read32(&autcpu12_sram_map,0); -+ save1 = map_read32(&autcpu12_sram_map,0x10000); -+ map_write32(&autcpu12_sram_map,~save0,0x10000); - /* if we find this pattern on 0x0, we have 32K size - * restore contents and exit - */ -- if ( autcpu12_read32(&autcpu12_sram_map,0) != save0) { -- autcpu12_write32(&autcpu12_sram_map,save0,0x0); -+ if ( map_read32(&autcpu12_sram_map,0) != save0) { -+ map_write32(&autcpu12_sram_map,save0,0x0); - goto map; - } - /* We have a 128K found, restore 0x10000 and set size - * to 128K - */ -- autcpu12_write32(&autcpu12_sram_map,save1,0x10000); -+ ma[_write32(&autcpu12_sram_map,save1,0x10000); - autcpu12_sram_map.size = SZ_128K; - - map: -@@ -139,7 +87,7 @@ - goto out_ioremap; - } - -- sram_mtd->module = THIS_MODULE; -+ sram_mtd->owner = THIS_MODULE; - sram_mtd->erasesize = 16; - - if (add_mtd_device(sram_mtd)) { -@@ -148,7 +96,7 @@ - goto out_probe; - } - -- printk("NV-RAM device size %ldK registered on AUTCPU12\n",autcpu12_sram_map.size/SZ_1K); -+ printk("NV-RAM device size %ldKiB registered on AUTCPU12\n",autcpu12_sram_map.size/SZ_1K); - - return 0; - -@@ -157,7 +105,7 @@ - sram_mtd = 0; - - out_ioremap: -- iounmap((void *)autcpu12_sram_map.map_priv_1); -+ iounmap((void *)autcpu12_sram_map.virt); - out: - return err; - } -@@ -167,7 +115,7 @@ - if (sram_mtd) { - del_mtd_device(sram_mtd); - map_destroy(sram_mtd); -- iounmap((void *)autcpu12_sram_map.map_priv_1); -+ iounmap((void *)autcpu12_sram_map.virt); - } - } - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/beech-mtd.c linux/drivers/mtd/maps/beech-mtd.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/beech-mtd.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/beech-mtd.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,112 @@ -+/* -+ * $Id$ -+ * -+ * drivers/mtd/maps/beech-mtd.c MTD mappings and partition tables for -+ * IBM 405LP Beech boards. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the 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 -+ * -+ * Copyright (C) 2002, International Business Machines Corporation -+ * All Rights Reserved. -+ * -+ * Bishop Brock -+ * IBM Research, Austin Center for Low-Power Computing -+ * bcbrock@us.ibm.com -+ * March 2002 -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#define NAME "Beech Linux Flash" -+#define PADDR BEECH_BIGFLASH_PADDR -+#define SIZE BEECH_BIGFLASH_SIZE -+#define BUSWIDTH 1 -+ -+/* Flash memories on these boards are memory resources, accessed big-endian. */ -+ -+ -+static struct map_info beech_mtd_map = { -+ .name = NAME, -+ .size = SIZE, -+ .buswidth = BUSWIDTH, -+ .phys = PADDR -+}; -+ -+static struct mtd_info *beech_mtd; -+ -+static struct mtd_partition beech_partitions[2] = { -+ { -+ .name = "Linux Kernel", -+ .size = BEECH_KERNEL_SIZE, -+ .offset = BEECH_KERNEL_OFFSET -+ }, { -+ .name = "Free Area", -+ .size = BEECH_FREE_AREA_SIZE, -+ .offset = BEECH_FREE_AREA_OFFSET -+ } -+}; -+ -+static int __init -+init_beech_mtd(void) -+{ -+ printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); -+ -+ beech_mtd_map.virt = (unsigned long) ioremap(PADDR, SIZE); -+ -+ if (!beech_mtd_map.virt) { -+ printk("%s: failed to ioremap 0x%x\n", NAME, PADDR); -+ return -EIO; -+ } -+ -+ simple_map_init(&beech_mtd_map); -+ -+ printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8); -+ beech_mtd = do_map_probe("cfi_probe", &beech_mtd_map); -+ -+ if (!beech_mtd) -+ return -ENXIO; -+ -+ beech_mtd->owner = THIS_MODULE; -+ -+ return add_mtd_partitions(beech_mtd, beech_partitions, 2); -+} -+ -+static void __exit -+cleanup_beech_mtd(void) -+{ -+ if (beech_mtd) { -+ del_mtd_partitions(beech_mtd); -+ map_destroy(beech_mtd); -+ iounmap((void *) beech_mtd_map.virt); -+ } -+} -+ -+module_init(init_beech_mtd); -+module_exit(cleanup_beech_mtd); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Bishop Brock "); -+MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Beech boards"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/cdb89712.c linux/drivers/mtd/maps/cdb89712.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/cdb89712.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/cdb89712.c 2004-11-17 18:17:59.061310576 +0100 -@@ -1,13 +1,14 @@ - /* - * Flash on Cirrus CDB89712 - * -- * $Id$ -+ * $Id$ - */ - - #include - #include - #include - #include -+#include - #include - #include - #include -@@ -16,77 +17,21 @@ - - - --__u8 cdb89712_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 cdb89712_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 cdb89712_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void cdb89712_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void cdb89712_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void cdb89712_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void cdb89712_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- // printk ("cdb89712_copy_from: 0x%x@0x%x -> 0x%x\n", len, from, to); -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void cdb89712_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- while(len) { -- __raw_writeb(*(unsigned char *) from, map->map_priv_1 + to); -- from++; -- to++; -- len--; -- } --} -- - - static struct mtd_info *flash_mtd; - - struct map_info cdb89712_flash_map = { -- name: "flash", -- size: FLASH_SIZE, -- buswidth: FLASH_WIDTH, -- read8: cdb89712_read8, -- read16: cdb89712_read16, -- read32: cdb89712_read32, -- copy_from: cdb89712_copy_from, -- write8: cdb89712_write8, -- write16: cdb89712_write16, -- write32: cdb89712_write32, -- copy_to: cdb89712_copy_to -+ .name = "flash", -+ .size = FLASH_SIZE, -+ .buswidth = FLASH_WIDTH, -+ .phys = FLASH_START, - }; - - struct resource cdb89712_flash_resource = { -- name: "Flash", -- start: FLASH_START, -- end: FLASH_START + FLASH_SIZE - 1, -- flags: IORESOURCE_IO | IORESOURCE_BUSY, -+ .name = "Flash", -+ .start = FLASH_START, -+ .end = FLASH_START + FLASH_SIZE - 1, -+ .flags = IORESOURCE_IO | IORESOURCE_BUSY, - }; - - static int __init init_cdb89712_flash (void) -@@ -99,13 +44,13 @@ - goto out; - } - -- cdb89712_flash_map.map_priv_1 = (unsigned long)ioremap(FLASH_START, FLASH_SIZE); -- if (!cdb89712_flash_map.map_priv_1) { -+ cdb89712_flash_map.virt = (unsigned long)ioremap(FLASH_START, FLASH_SIZE); -+ if (!cdb89712_flash_map.virt) { - printk(KERN_NOTICE "Failed to ioremap Cdb89712 FLASH space\n"); - err = -EIO; - goto out_resource; - } -- -+ simple_map_init(&cdb89712_flash_map); - flash_mtd = do_map_probe("cfi_probe", &cdb89712_flash_map); - if (!flash_mtd) { - flash_mtd = do_map_probe("map_rom", &cdb89712_flash_map); -@@ -118,7 +63,7 @@ - goto out_ioremap; - } - -- flash_mtd->module = THIS_MODULE; -+ flash_mtd->owner = THIS_MODULE; - - if (add_mtd_device(flash_mtd)) { - printk("FLASH device addition failed\n"); -@@ -132,7 +77,7 @@ - map_destroy(flash_mtd); - flash_mtd = 0; - out_ioremap: -- iounmap((void *)cdb89712_flash_map.map_priv_1); -+ iounmap((void *)cdb89712_flash_map.virt); - out_resource: - release_resource (&cdb89712_flash_resource); - out: -@@ -146,24 +91,17 @@ - static struct mtd_info *sram_mtd; - - struct map_info cdb89712_sram_map = { -- name: "SRAM", -- size: SRAM_SIZE, -- buswidth: SRAM_WIDTH, -- read8: cdb89712_read8, -- read16: cdb89712_read16, -- read32: cdb89712_read32, -- copy_from: cdb89712_copy_from, -- write8: cdb89712_write8, -- write16: cdb89712_write16, -- write32: cdb89712_write32, -- copy_to: cdb89712_copy_to -+ .name = "SRAM", -+ .size = SRAM_SIZE, -+ .buswidth = SRAM_WIDTH, -+ .phys = SRAM_START, - }; - - struct resource cdb89712_sram_resource = { -- name: "SRAM", -- start: SRAM_START, -- end: SRAM_START + SRAM_SIZE - 1, -- flags: IORESOURCE_IO | IORESOURCE_BUSY, -+ .name = "SRAM", -+ .start = SRAM_START, -+ .end = SRAM_START + SRAM_SIZE - 1, -+ .flags = IORESOURCE_IO | IORESOURCE_BUSY, - }; - - static int __init init_cdb89712_sram (void) -@@ -176,13 +114,13 @@ - goto out; - } - -- cdb89712_sram_map.map_priv_1 = (unsigned long)ioremap(SRAM_START, SRAM_SIZE); -- if (!cdb89712_sram_map.map_priv_1) { -+ cdb89712_sram_map.virt = (unsigned long)ioremap(SRAM_START, SRAM_SIZE); -+ if (!cdb89712_sram_map.virt) { - printk(KERN_NOTICE "Failed to ioremap Cdb89712 SRAM space\n"); - err = -EIO; - goto out_resource; - } -- -+ simple_map_init(&cdb89712_sram_map); - sram_mtd = do_map_probe("map_ram", &cdb89712_sram_map); - if (!sram_mtd) { - printk("SRAM probe failed\n"); -@@ -190,7 +128,7 @@ - goto out_ioremap; - } - -- sram_mtd->module = THIS_MODULE; -+ sram_mtd->owner = THIS_MODULE; - sram_mtd->erasesize = 16; - - if (add_mtd_device(sram_mtd)) { -@@ -205,7 +143,7 @@ - map_destroy(sram_mtd); - sram_mtd = 0; - out_ioremap: -- iounmap((void *)cdb89712_sram_map.map_priv_1); -+ iounmap((void *)cdb89712_sram_map.virt); - out_resource: - release_resource (&cdb89712_sram_resource); - out: -@@ -221,20 +159,17 @@ - static struct mtd_info *bootrom_mtd; - - struct map_info cdb89712_bootrom_map = { -- name: "BootROM", -- size: BOOTROM_SIZE, -- buswidth: BOOTROM_WIDTH, -- read8: cdb89712_read8, -- read16: cdb89712_read16, -- read32: cdb89712_read32, -- copy_from: cdb89712_copy_from, -+ .name = "BootROM", -+ .size = BOOTROM_SIZE, -+ .buswidth = BOOTROM_WIDTH, -+ .phys = BOOTROM_START, - }; - - struct resource cdb89712_bootrom_resource = { -- name: "BootROM", -- start: BOOTROM_START, -- end: BOOTROM_START + BOOTROM_SIZE - 1, -- flags: IORESOURCE_IO | IORESOURCE_BUSY, -+ .name = "BootROM", -+ .start = BOOTROM_START, -+ .end = BOOTROM_START + BOOTROM_SIZE - 1, -+ .flags = IORESOURCE_IO | IORESOURCE_BUSY, - }; - - static int __init init_cdb89712_bootrom (void) -@@ -247,13 +182,13 @@ - goto out; - } - -- cdb89712_bootrom_map.map_priv_1 = (unsigned long)ioremap(BOOTROM_START, BOOTROM_SIZE); -- if (!cdb89712_bootrom_map.map_priv_1) { -+ cdb89712_bootrom_map.virt = (unsigned long)ioremap(BOOTROM_START, BOOTROM_SIZE); -+ if (!cdb89712_bootrom_map.virt) { - printk(KERN_NOTICE "Failed to ioremap Cdb89712 BootROM space\n"); - err = -EIO; - goto out_resource; - } -- -+ simple_map_init(&cdb89712_bootrom_map); - bootrom_mtd = do_map_probe("map_rom", &cdb89712_bootrom_map); - if (!bootrom_mtd) { - printk("BootROM probe failed\n"); -@@ -261,7 +196,7 @@ - goto out_ioremap; - } - -- bootrom_mtd->module = THIS_MODULE; -+ bootrom_mtd->owner = THIS_MODULE; - bootrom_mtd->erasesize = 0x10000; - - if (add_mtd_device(bootrom_mtd)) { -@@ -276,7 +211,7 @@ - map_destroy(bootrom_mtd); - bootrom_mtd = 0; - out_ioremap: -- iounmap((void *)cdb89712_bootrom_map.map_priv_1); -+ iounmap((void *)cdb89712_bootrom_map.virt); - out_resource: - release_resource (&cdb89712_bootrom_resource); - out: -@@ -306,21 +241,21 @@ - if (sram_mtd) { - del_mtd_device(sram_mtd); - map_destroy(sram_mtd); -- iounmap((void *)cdb89712_sram_map.map_priv_1); -+ iounmap((void *)cdb89712_sram_map.virt); - release_resource (&cdb89712_sram_resource); - } - - if (flash_mtd) { - del_mtd_device(flash_mtd); - map_destroy(flash_mtd); -- iounmap((void *)cdb89712_flash_map.map_priv_1); -+ iounmap((void *)cdb89712_flash_map.virt); - release_resource (&cdb89712_flash_resource); - } - - if (bootrom_mtd) { - del_mtd_device(bootrom_mtd); - map_destroy(bootrom_mtd); -- iounmap((void *)cdb89712_bootrom_map.map_priv_1); -+ iounmap((void *)cdb89712_bootrom_map.virt); - release_resource (&cdb89712_bootrom_resource); - } - } -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/ceiva.c linux/drivers/mtd/maps/ceiva.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/ceiva.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/ceiva.c 2004-11-17 18:17:59.063310272 +0100 -@@ -11,7 +11,7 @@ - * - * (C) 2000 Nicolas Pitre - * -- * $Id$ -+ * $Id$ - */ - - #include -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -31,62 +32,10 @@ - #include - - /* -- * This isnt complete yet, so... -+ * This isn't complete yet, so... - */ - #define CONFIG_MTD_CEIVA_STATICMAP - --static __u8 clps_read8(struct map_info *map, unsigned long ofs) --{ -- return readb(map->map_priv_1 + ofs); --} -- --static __u16 clps_read16(struct map_info *map, unsigned long ofs) --{ -- return readw(map->map_priv_1 + ofs); --} -- --static __u32 clps_read32(struct map_info *map, unsigned long ofs) --{ -- return readl(map->map_priv_1 + ofs); --} -- --static void clps_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy(to, (void *)(map->map_priv_1 + from), len); --} -- --static void clps_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, map->map_priv_1 + adr); --} -- --static void clps_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, map->map_priv_1 + adr); --} -- --static void clps_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- writel(d, map->map_priv_1 + adr); --} -- --static void clps_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy((void *)(map->map_priv_1 + to), from, len); --} -- --static struct map_info clps_map __initdata = { -- name: "clps flash", -- read8: clps_read8, -- read16: clps_read16, -- read32: clps_read32, -- copy_from: clps_copy_from, -- write8: clps_write8, -- write16: clps_write16, -- write32: clps_write32, -- copy_to: clps_copy_to, --}; -- - #ifdef CONFIG_MTD_CEIVA_STATICMAP - /* - * See include/linux/mtd/partitions.h for definition of the mtd_partition -@@ -176,7 +125,7 @@ - maps = kmalloc(sizeof(struct map_info) * nr, GFP_KERNEL); - if (!maps) - return -ENOMEM; -- -+ memset(maps, 0, sizeof(struct map_info) * nr); - /* - * Claim and then map the memory regions. - */ -@@ -191,7 +140,9 @@ - } - - clps[i].map = maps + i; -- memcpy(clps[i].map, &clps_map, sizeof(struct map_info)); -+ -+ clps[i].map->name = "clps flash"; -+ clps[i].map->phys = clps[i].base; - - clps[i].vbase = ioremap(clps[i].base, clps[i].size); - if (!clps[i].vbase) { -@@ -199,16 +150,18 @@ - break; - } - -- clps[i].map->map_priv_1 = (unsigned long)clps[i].vbase; -+ clps[i].map->virt = (unsigned long)clps[i].vbase; - clps[i].map->buswidth = clps[i].width; - clps[i].map->size = clps[i].size; - -+ simple_map_init(&clps[i].map); -+ - clps[i].mtd = do_map_probe("jedec_probe", clps[i].map); - if (clps[i].mtd == NULL) { - ret = -ENXIO; - break; - } -- clps[i].mtd->module = THIS_MODULE; -+ clps[i].mtd->owner = THIS_MODULE; - subdev[i] = clps[i].mtd; - - printk(KERN_INFO "clps flash: JEDEC device at 0x%08lx, %dMiB, " -@@ -318,10 +271,8 @@ - return nr; - } - --extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts); --extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, char *); -- - static struct mtd_partition *parsed_parts; -+static const char *probes[] = { "cmdlinepart", "RedBoot", NULL }; - - static void __init clps_locate_partitions(struct mtd_info *mtd) - { -@@ -331,20 +282,11 @@ - /* - * Partition selection stuff. - */ --#ifdef CONFIG_MTD_CMDLINE_PARTS -- nr_parts = parse_cmdline_partitions(mtd, &parsed_parts, "clps"); -+ nr_parts = parse_mtd_partitions(mtd, probes, &parsed_parts, 0); - if (nr_parts > 0) { - part_type = "command line"; - break; - } --#endif --#ifdef CONFIG_MTD_REDBOOT_PARTS -- nr_parts = parse_redboot_partitions(mtd, &parsed_parts); -- if (nr_parts > 0) { -- part_type = "RedBoot"; -- break; -- } --#endif - #ifdef CONFIG_MTD_CEIVA_STATICMAP - nr_parts = clps_static_partitions(&parsed_parts); - if (nr_parts > 0) { -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/cfi_flagadm.c linux/drivers/mtd/maps/cfi_flagadm.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/cfi_flagadm.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/cfi_flagadm.c 2004-11-17 18:17:59.064310120 +0100 -@@ -1,7 +1,7 @@ - /* - * Copyright © 2001 Flaga hf. Medical Devices, Kári Davíðsson - * -- * $Id$ -+ * $Id$ - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -55,83 +56,33 @@ - #define FLASH_PARTITION3_ADDR 0x00240000 - #define FLASH_PARTITION3_SIZE 0x001C0000 - --__u8 flagadm_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 flagadm_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 flagadm_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void flagadm_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void flagadm_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void flagadm_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void flagadm_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void flagadm_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - struct map_info flagadm_map = { -- name: "FlagaDM flash device", -- size: FLASH_SIZE, -- buswidth: 2, -- read8: flagadm_read8, -- read16: flagadm_read16, -- read32: flagadm_read32, -- copy_from: flagadm_copy_from, -- write8: flagadm_write8, -- write16: flagadm_write16, -- write32: flagadm_write32, -- copy_to: flagadm_copy_to -+ .name = "FlagaDM flash device", -+ .size = FLASH_SIZE, -+ .buswidth = 2, - }; - - struct mtd_partition flagadm_parts[] = { - { -- name : "Bootloader", -- offset : FLASH_PARTITION0_ADDR, -- size : FLASH_PARTITION0_SIZE -+ .name = "Bootloader", -+ .offset = FLASH_PARTITION0_ADDR, -+ .size = FLASH_PARTITION0_SIZE - }, - { -- name : "Kernel image", -- offset : FLASH_PARTITION1_ADDR, -- size : FLASH_PARTITION1_SIZE -+ .name = "Kernel image", -+ .offset = FLASH_PARTITION1_ADDR, -+ .size = FLASH_PARTITION1_SIZE - }, - { -- name : "Initial ramdisk image", -- offset : FLASH_PARTITION2_ADDR, -- size : FLASH_PARTITION2_SIZE -+ .name = "Initial ramdisk image", -+ .offset = FLASH_PARTITION2_ADDR, -+ .size = FLASH_PARTITION2_SIZE - }, - { -- name : "Persistant storage", -- offset : FLASH_PARTITION3_ADDR, -- size : FLASH_PARTITION3_SIZE -+ .name = "Persistant storage", -+ .offset = FLASH_PARTITION3_ADDR, -+ .size = FLASH_PARTITION3_SIZE - } - }; - -@@ -144,22 +95,26 @@ - printk(KERN_NOTICE "FlagaDM flash device: %x at %x\n", - FLASH_SIZE, FLASH_PHYS_ADDR); - -- flagadm_map.map_priv_1 = (unsigned long)ioremap(FLASH_PHYS_ADDR, -+ flagadm_map.phys = FLASH_PHYS_ADDR; -+ flagadm_map.virt = (unsigned long)ioremap(FLASH_PHYS_ADDR, - FLASH_SIZE); - -- if (!flagadm_map.map_priv_1) { -+ if (!flagadm_map.virt) { - printk("Failed to ioremap\n"); - return -EIO; - } -+ -+ simple_map_init(&flagadm_map); -+ - mymtd = do_map_probe("cfi_probe", &flagadm_map); - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - add_mtd_partitions(mymtd, flagadm_parts, PARTITION_COUNT); - printk(KERN_NOTICE "FlagaDM flash device initialized\n"); - return 0; - } - -- iounmap((void *)flagadm_map.map_priv_1); -+ iounmap((void *)flagadm_map.virt); - return -ENXIO; - } - -@@ -169,9 +124,9 @@ - del_mtd_partitions(mymtd); - map_destroy(mymtd); - } -- if (flagadm_map.map_priv_1) { -- iounmap((void *)flagadm_map.map_priv_1); -- flagadm_map.map_priv_1 = 0; -+ if (flagadm_map.virt) { -+ iounmap((void *)flagadm_map.virt); -+ flagadm_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/cstm_mips_ixx.c linux/drivers/mtd/maps/cstm_mips_ixx.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/cstm_mips_ixx.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/cstm_mips_ixx.c 2004-11-17 18:17:59.065309968 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions. - * Config with both CFI and JEDEC device support. -@@ -33,55 +33,13 @@ - #include - #include - #include -+#include - #include - #include - #include - #include - #include -- --#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) - #include --#endif -- --__u8 cstm_mips_ixx_read8(struct map_info *map, unsigned long ofs) --{ -- return *(__u8 *)(map->map_priv_1 + ofs); --} -- --__u16 cstm_mips_ixx_read16(struct map_info *map, unsigned long ofs) --{ -- return *(__u16 *)(map->map_priv_1 + ofs); --} -- --__u32 cstm_mips_ixx_read32(struct map_info *map, unsigned long ofs) --{ -- return *(__u32 *)(map->map_priv_1 + ofs); --} -- --void cstm_mips_ixx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void cstm_mips_ixx_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- *(__u8 *)(map->map_priv_1 + adr) = d; --} -- --void cstm_mips_ixx_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- *(__u16 *)(map->map_priv_1 + adr) = d; --} -- --void cstm_mips_ixx_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- *(__u32 *)(map->map_priv_1 + adr) = d; --} -- --void cstm_mips_ixx_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) - #define CC_GCR 0xB4013818 -@@ -97,10 +55,17 @@ - #define CC_GPAICR 0xB4013804 - #endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ - -+#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) - void cstm_mips_ixx_set_vpp(struct map_info *map,int vpp) - { -+ static spinlock_t vpp_lock = SPIN_LOCK_UNLOCKED; -+ static int vpp_count = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&vpp_lock, flags); -+ - if (vpp) { --#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) -+ if (!vpp_count++) { - __u16 data; - __u8 data1; - static u8 first = 1; -@@ -116,10 +81,9 @@ - enabling vpp after powerup */ - udelay(40); - } --#endif /* CONFIG_MIPS_ITE8172 */ - } -- else { --#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) -+ } else { -+ if (!--vpp_count) { - __u16 data; - - // Set GPIO port B pin3 to high -@@ -127,26 +91,11 @@ - data = (data & 0xff3f) | 0x0040; - *(__u16 *)CC_GPBCR = data; - *(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) & 0xf7; --#endif /* CONFIG_MIPS_ITE8172 */ - } -+ } -+ spin_unlock_irqrestore(&vpp_lock, flags); - } -- --const struct map_info basic_cstm_mips_ixx_map = { -- NULL, -- 0, -- 0, -- cstm_mips_ixx_read8, -- cstm_mips_ixx_read16, -- cstm_mips_ixx_read32, -- cstm_mips_ixx_copy_from, -- cstm_mips_ixx_write8, -- cstm_mips_ixx_write16, -- cstm_mips_ixx_write32, -- cstm_mips_ixx_copy_to, -- cstm_mips_ixx_set_vpp, -- 0, -- 0 --}; -+#endif - - /* board and partition description */ - -@@ -175,9 +124,9 @@ - static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = { - { // 28F128J3A in 2x16 configuration - { -- name: "main partition ", -- size: 0x02000000, // 128 x 2 x 128k byte sectors -- offset: 0, -+ .name = "main partition ", -+ .size = 0x02000000, // 128 x 2 x 128k byte sectors -+ .offset = 0, - }, - }, - }; -@@ -197,9 +146,9 @@ - static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = { - { - { -- name: "main partition", -- size: CONFIG_MTD_CSTM_MIPS_IXX_LEN, -- offset: 0, -+ .name = "main partition", -+ .size = CONFIG_MTD_CSTM_MIPS_IXX_LEN, -+ .offset = 0, - }, - }, - }; -@@ -216,17 +165,24 @@ - - /* Initialize mapping */ - for (i=0;imodule = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - cstm_mips_ixx_map[i].map_priv_2 = (unsigned long)mymtd; - add_mtd_partitions(mymtd, parts, cstm_mips_ixx_board_desc[i].num_partitions); -@@ -266,9 +222,9 @@ - del_mtd_partitions(mymtd); - map_destroy(mymtd); - } -- if (cstm_mips_ixx_map[i].map_priv_1) { -- iounmap((void *)cstm_mips_ixx_map[i].map_priv_1); -- cstm_mips_ixx_map[i].map_priv_1 = 0; -+ if (cstm_mips_ixx_map[i].virt) { -+ iounmap((void *)cstm_mips_ixx_map[i].virt); -+ cstm_mips_ixx_map[i].virt = 0; - } - } - } -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/db1x00-flash.c linux/drivers/mtd/maps/db1x00-flash.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/db1x00-flash.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/db1x00-flash.c 2004-11-17 18:17:59.067309664 +0100 -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -29,76 +30,6 @@ - static unsigned long flash_size; - - static BCSR * const bcsr = (BCSR *)0xAE000000; -- --__u8 physmap_read8(struct map_info *map, unsigned long ofs) --{ -- __u8 ret; -- ret = __raw_readb(map->map_priv_1 + ofs); -- DBG("read8 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --__u16 physmap_read16(struct map_info *map, unsigned long ofs) --{ -- __u16 ret; -- ret = __raw_readw(map->map_priv_1 + ofs); -- DBG("read16 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --__u32 physmap_read32(struct map_info *map, unsigned long ofs) --{ -- __u32 ret; -- ret = __raw_readl(map->map_priv_1 + ofs); -- DBG("read32 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- DBG("physmap_copy from %x to %x\n", (unsigned)from, (unsigned)to); -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void physmap_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- DBG("write8 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- DBG("write16 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- DBG("write32 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- DBG("physmap_copy_to %x from %x\n", (unsigned)to, (unsigned)from); -- memcpy_toio(map->map_priv_1 + to, from, len); --} -- --static struct map_info db1x00_map = { -- name: "Db1x00 flash", -- read8: physmap_read8, -- read16: physmap_read16, -- read32: physmap_read32, -- copy_from: physmap_copy_from, -- write8: physmap_write8, -- write16: physmap_write16, -- write32: physmap_write32, -- copy_to: physmap_copy_to, --}; -- - static unsigned char flash_buswidth = 4; - - /* -@@ -115,58 +46,62 @@ - */ - static struct mtd_partition db1x00_partitions[] = { - { -- name: "User FS", -- size: 0x1c00000, -- offset: 0x0000000 -+ .name = "User FS", -+ .size = 0x1c00000, -+ .offset = 0x0000000 - },{ -- name: "yamon", -- size: 0x0100000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE -+ .name = "yamon", -+ .size = 0x0100000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE - },{ -- name: "raw kernel", -- size: (0x300000-0x40000), /* last 256KB is yamon env */ -- offset: MTDPART_OFS_APPEND, -+ .name = "raw kernel", -+ .size = (0x300000-0x40000), /* last 256KB is env */ -+ .offset = MTDPART_OFS_APPEND, - } - }; - #elif defined(DB1X00_BOOT_ONLY) - static struct mtd_partition db1x00_partitions[] = { - { -- name: "User FS", -- size: 0x00c00000, -- offset: 0x0000000 -+ .name = "User FS", -+ .size = 0x00c00000, -+ .offset = 0x0000000 - },{ -- name: "yamon", -- size: 0x0100000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE -+ .name = "yamon", -+ .size = 0x0100000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE - },{ -- name: "raw kernel", -- size: (0x300000-0x40000), /* last 256KB is yamon env */ -- offset: MTDPART_OFS_APPEND, -+ .name = "raw kernel", -+ .size = (0x300000-0x40000), /* last 256KB is env */ -+ .offset = MTDPART_OFS_APPEND, - } - }; - #elif defined(DB1X00_USER_ONLY) - static struct mtd_partition db1x00_partitions[] = { - { -- name: "User FS", -- size: 0x0e00000, -- offset: 0x0000000 -+ .name = "User FS", -+ .size = 0x0e00000, -+ .offset = 0x0000000 - },{ -- name: "raw kernel", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .name = "raw kernel", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #else - #error MTD_DB1X00 define combo error /* should never happen */ - #endif -+#define NB_OF(x) (sizeof(x)/sizeof(x[0])) - -+#define NAME "Db1x00 Linux Flash" - --#define NB_OF(x) (sizeof(x)/sizeof(x[0])) -+static struct map_info db1xxx_mtd_map = { -+ .name = NAME, -+}; - - static struct mtd_partition *parsed_parts; --static struct mtd_info *mymtd; -+static struct mtd_info *db1xxx_mtd; - - /* - * Probe the flash density and setup window address and size -@@ -174,7 +109,7 @@ - * want the MTD driver to be probing the boot or user flash, - * so having the option to enable only one bank is important. - */ --int setup_flash_params() -+int setup_flash_params(void) - { - switch ((bcsr->status >> 14) & 0x3) { - case 0: /* 64Mbit devices */ -@@ -228,6 +163,10 @@ - default: - return 1; - } -+ db1xxx_mtd_map.size = window_size; -+ db1xxx_mtd_map.buswidth = flash_buswidth; -+ db1xxx_mtd_map.phys = window_addr; -+ db1xxx_mtd_map.buswidth = flash_buswidth; - return 0; - } - -@@ -235,10 +174,6 @@ - { - struct mtd_partition *parts; - int nb_parts = 0; -- char *part_type; -- -- /* Default flash buswidth */ -- db1x00_map.buswidth = flash_buswidth; - - if (setup_flash_params()) - return -ENXIO; -@@ -246,32 +181,29 @@ - /* - * Static partition definition selection - */ -- part_type = "static"; - parts = db1x00_partitions; - nb_parts = NB_OF(db1x00_partitions); -- db1x00_map.size = window_size; - - /* - * Now let's probe for the actual flash. Do it here since - * specific machine settings might have been set above. - */ - printk(KERN_NOTICE "Db1xxx flash: probing %d-bit flash bus\n", -- db1x00_map.buswidth*8); -- db1x00_map.map_priv_1 = -- (unsigned long)ioremap(window_addr, window_size); -- mymtd = do_map_probe("cfi_probe", &db1x00_map); -- if (!mymtd) return -ENXIO; -- mymtd->module = THIS_MODULE; -+ db1xxx_mtd_map.buswidth*8); -+ db1xxx_mtd_map.virt = (unsigned long)ioremap(window_addr, window_size); -+ db1xxx_mtd = do_map_probe("cfi_probe", &db1xxx_mtd_map); -+ if (!db1xxx_mtd) return -ENXIO; -+ db1xxx_mtd->owner = THIS_MODULE; - -- add_mtd_partitions(mymtd, parts, nb_parts); -+ add_mtd_partitions(db1xxx_mtd, parts, nb_parts); - return 0; - } - - static void __exit db1x00_mtd_cleanup(void) - { -- if (mymtd) { -- del_mtd_partitions(mymtd); -- map_destroy(mymtd); -+ if (db1xxx_mtd) { -+ del_mtd_partitions(db1xxx_mtd); -+ map_destroy(db1xxx_mtd); - if (parsed_parts) - kfree(parsed_parts); - } -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/dbox2-flash.c linux/drivers/mtd/maps/dbox2-flash.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/dbox2-flash.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/dbox2-flash.c 2004-11-17 18:17:59.068309512 +0100 -@@ -1,12 +1,13 @@ - /* -- * $Id$ -+ * $Id$ - * -- * Nokia / Sagem D-Box 2 flash driver -+ * D-Box 2 flash driver - */ - - #include - #include - #include -+#include - #include - #include - #include -@@ -16,22 +17,44 @@ - /* partition_info gives details on the logical partitions that the split the - * single flash device into. If the size if zero we use up to the end of the - * device. */ --static struct mtd_partition partition_info[]= {{name: "BR bootloader", // raw -- size: 128 * 1024, -- offset: 0, -- mask_flags: MTD_WRITEABLE}, -- {name: "PPC bootloader", // flfs -- size: 128 * 1024, -- offset: MTDPART_OFS_APPEND, -- mask_flags: 0}, -- {name: "Kernel", // idxfs -- size: 768 * 1024, -- offset: MTDPART_OFS_APPEND, -- mask_flags: 0}, -- {name: "System", // jffs -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -- mask_flags: 0}}; -+static struct mtd_partition partition_info[]= { -+ { -+ .name = "BR bootloader", -+ .size = 128 * 1024, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE -+ }, -+ { -+ .name = "flfs (ppcboot)", -+ .size = 128 * 1024, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = 0 -+ }, -+ { -+ .name = "root (cramfs)", -+ .size = 7040 * 1024, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = 0 -+ }, -+ { -+ .name = "var (jffs2)", -+ .size = 896 * 1024, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = 0 -+ }, -+ { -+ .name = "flash without bootloader", -+ .size = MTDPART_SIZ_FULL, -+ .offset = 128 * 1024, -+ .mask_flags = 0 -+ }, -+ { -+ .name = "complete flash", -+ .size = MTDPART_SIZ_FULL, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE -+ } -+}; - - #define NUM_PARTITIONS (sizeof(partition_info) / sizeof(partition_info[0])) - -@@ -40,72 +63,24 @@ - - static struct mtd_info *mymtd; - --__u8 dbox2_flash_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 dbox2_flash_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 dbox2_flash_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void dbox2_flash_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void dbox2_flash_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void dbox2_flash_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void dbox2_flash_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void dbox2_flash_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - struct map_info dbox2_flash_map = { -- name: "D-Box 2 flash memory", -- size: WINDOW_SIZE, -- buswidth: 4, -- read8: dbox2_flash_read8, -- read16: dbox2_flash_read16, -- read32: dbox2_flash_read32, -- copy_from: dbox2_flash_copy_from, -- write8: dbox2_flash_write8, -- write16: dbox2_flash_write16, -- write32: dbox2_flash_write32, -- copy_to: dbox2_flash_copy_to -+ .name = "D-Box 2 flash memory", -+ .size = WINDOW_SIZE, -+ .buswidth = 4, -+ .phys = WINDOW_ADDR, - }; - - int __init init_dbox2_flash(void) - { - printk(KERN_NOTICE "D-Box 2 flash driver (size->0x%X mem->0x%X)\n", WINDOW_SIZE, WINDOW_ADDR); -- dbox2_flash_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); -+ dbox2_flash_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); - -- if (!dbox2_flash_map.map_priv_1) { -+ if (!dbox2_flash_map.virt) { - printk("Failed to ioremap\n"); - return -EIO; - } -+ simple_map_init(&dbox2_flash_map); - - // Probe for dual Intel 28F320 or dual AMD - mymtd = do_map_probe("cfi_probe", &dbox2_flash_map); -@@ -117,7 +92,7 @@ - } - - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - /* Create MTD devices for each partition. */ - add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS); -@@ -125,7 +100,7 @@ - return 0; - } - -- iounmap((void *)dbox2_flash_map.map_priv_1); -+ iounmap((void *)dbox2_flash_map.virt); - return -ENXIO; - } - -@@ -135,9 +110,9 @@ - del_mtd_partitions(mymtd); - map_destroy(mymtd); - } -- if (dbox2_flash_map.map_priv_1) { -- iounmap((void *)dbox2_flash_map.map_priv_1); -- dbox2_flash_map.map_priv_1 = 0; -+ if (dbox2_flash_map.virt) { -+ iounmap((void *)dbox2_flash_map.virt); -+ dbox2_flash_map.virt = 0; - } - } - -@@ -146,5 +121,5 @@ - - - MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Kári Davíðsson "); --MODULE_DESCRIPTION("MTD map driver for Nokia/Sagem D-Box 2 board"); -+MODULE_AUTHOR("Kári Davíðsson , Bastian Blank , Alexander Wild "); -+MODULE_DESCRIPTION("MTD map driver for D-Box 2 board"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/dc21285.c linux/drivers/mtd/maps/dc21285.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/dc21285.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/dc21285.c 2004-11-17 18:17:59.069309360 +0100 -@@ -5,12 +5,13 @@ - * - * This code is GPL - * -- * $Id$ -+ * $Id$ - */ - #include - #include - #include - #include -+#include - - #include - #include -@@ -92,26 +93,42 @@ - } - - struct map_info dc21285_map = { -- name: "DC21285 flash", -- size: 16*1024*1024, -- read8: dc21285_read8, -- read16: dc21285_read16, -- read32: dc21285_read32, -- copy_from: dc21285_copy_from, -- write8: dc21285_write8, -- write16: dc21285_write16, -- write32: dc21285_write32, -- copy_to: dc21285_copy_to -+ .name = "DC21285 flash", -+ .phys = NO_XIP, -+ .size = 16*1024*1024, -+ .read8 = dc21285_read8, -+ .read16 = dc21285_read16, -+ .read32 = dc21285_read32, -+ .copy_from = dc21285_copy_from, -+ .write8 = dc21285_write8, -+ .write16 = dc21285_write16, -+ .write32 = dc21285_write32, -+ .copy_to = dc21285_copy_to - }; - - - /* Partition stuff */ - static struct mtd_partition *dc21285_parts; -- --extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **); -+#ifdef CONFIG_MTD_PARTITIONS -+static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; -+#endif - - int __init init_dc21285(void) - { -+ -+ /* -+ * Flash timing is determined with bits 19-16 of the -+ * CSR_SA110_CNTL. The value is the number of wait cycles, or -+ * 0 for 16 cycles (the default). Cycles are 20 ns. -+ * Here we use 7 for 140 ns flash chips. -+ */ -+ /* access time */ -+ *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x000f0000) | (7 << 16)); -+ /* burst time */ -+ *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20)); -+ /* tristate time */ -+ *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24)); -+ - /* Determine buswidth */ - switch (*CSR_SA110_CNTL & (3<<14)) { - case SA110_CNTL_ROMWIDTH_8: -@@ -141,33 +158,18 @@ - if (mymtd) { - int nrparts = 0; - -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - /* partition fixup */ - --#ifdef CONFIG_MTD_REDBOOT_PARTS -- nrparts = parse_redboot_partitions(mymtd, &dc21285_parts); --#endif -+#ifdef CONFIG_MTD_PARTITIONS -+ nrparts = parse_mtd_partitions(mymtd, probes, &dc21285_parts, (void *)0); - if (nrparts > 0) { - add_mtd_partitions(mymtd, dc21285_parts, nrparts); -- } else if (nrparts == 0) { -- printk(KERN_NOTICE "RedBoot partition table failed\n"); -- add_mtd_device(mymtd); -+ return 0; - } -- -- /* -- * Flash timing is determined with bits 19-16 of the -- * CSR_SA110_CNTL. The value is the number of wait cycles, or -- * 0 for 16 cycles (the default). Cycles are 20 ns. -- * Here we use 7 for 140 ns flash chips. -- */ -- /* access time */ -- *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x000f0000) | (7 << 16)); -- /* burst time */ -- *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20)); -- /* tristate time */ -- *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24)); -- -+#endif -+ add_mtd_device(mymtd); - return 0; - } - -@@ -177,17 +179,16 @@ - - static void __exit cleanup_dc21285(void) - { -- if (mymtd) { -+#ifdef CONFIG_MTD_PARTITIONS -+ if (dc21285_parts) { -+ del_mtd_partitions(mymtd); -+ kfree(dc21285_parts); -+ } else -+#endif - del_mtd_device(mymtd); -+ - map_destroy(mymtd); -- mymtd = NULL; -- } -- if (dc21285_map.map_priv_1) { - iounmap((void *)dc21285_map.map_priv_1); -- dc21285_map.map_priv_1 = 0; -- } -- if(dc21285_parts) -- kfree(dc21285_parts); - } - - module_init(init_dc21285); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/dilnetpc.c linux/drivers/mtd/maps/dilnetpc.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/dilnetpc.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/dilnetpc.c 2004-11-17 18:17:59.071309056 +0100 -@@ -14,7 +14,7 @@ - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * -- * $Id$ -+ * $Id$ - * - * The DIL/Net PC is a tiny embedded PC board made by SSV Embedded Systems - * featuring the AMD Elan SC410 processor. There are two variants of this -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -36,7 +37,7 @@ - #include - - /* --** The DIL/NetPC keeps it's BIOS in two distinct flash blocks. -+** The DIL/NetPC keeps its BIOS in two distinct flash blocks. - ** Destroying any of these blocks transforms the DNPC into - ** a paperweight (albeit not a very useful one, considering - ** it only weighs a few grams). -@@ -189,45 +190,6 @@ - } - - --static __u8 dnpc_read8(struct map_info *map, unsigned long ofs) --{ -- return readb(map->map_priv_1 + ofs); --} -- --static __u16 dnpc_read16(struct map_info *map, unsigned long ofs) --{ -- return readw(map->map_priv_1 + ofs); --} -- --static __u32 dnpc_read32(struct map_info *map, unsigned long ofs) --{ -- return readl(map->map_priv_1 + ofs); --} -- --static void dnpc_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); --} -- --static void dnpc_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, map->map_priv_1 + adr); --} -- --static void dnpc_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, map->map_priv_1 + adr); --} -- --static void dnpc_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- writel(d, map->map_priv_1 + adr); --} -- --static void dnpc_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio((void *)(map->map_priv_1 + to), from, len); --} - - /* - ************************************************************ -@@ -288,19 +250,11 @@ - #define WINDOW_ADDR FLASH_BASE - - static struct map_info dnpc_map = { -- name: "ADNP Flash Bank", -- size: ADNP_WINDOW_SIZE, -- buswidth: 1, -- read8: dnpc_read8, -- read16: dnpc_read16, -- read32: dnpc_read32, -- copy_from: dnpc_copy_from, -- write8: dnpc_write8, -- write16: dnpc_write16, -- write32: dnpc_write32, -- copy_to: dnpc_copy_to, -- set_vpp: adnp_set_vpp, -- map_priv_2: WINDOW_ADDR -+ .name = "ADNP Flash Bank", -+ .size = ADNP_WINDOW_SIZE, -+ .buswidth = 1, -+ .set_vpp = adnp_set_vpp, -+ .phys = WINDOW_ADDR - }; - - /* -@@ -316,29 +270,29 @@ - static struct mtd_partition partition_info[]= - { - { -- name: "ADNP boot", -- offset: 0, -- size: 0xf0000, -+ .name = "ADNP boot", -+ .offset = 0, -+ .size = 0xf0000, - }, - { -- name: "ADNP system BIOS", -- offset: MTDPART_OFS_NXTBLK, -- size: 0x10000, -+ .name = "ADNP system BIOS", -+ .offset = MTDPART_OFS_NXTBLK, -+ .size = 0x10000, - #ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED -- mask_flags: MTD_WRITEABLE, -+ .mask_flags = MTD_WRITEABLE, - #endif - }, - { -- name: "ADNP file system", -- offset: MTDPART_OFS_NXTBLK, -- size: 0x2f0000, -+ .name = "ADNP file system", -+ .offset = MTDPART_OFS_NXTBLK, -+ .size = 0x2f0000, - }, - { -- name: "ADNP system BIOS entry", -- offset: MTDPART_OFS_NXTBLK, -- size: MTDPART_SIZ_FULL, -+ .name = "ADNP system BIOS entry", -+ .offset = MTDPART_OFS_NXTBLK, -+ .size = MTDPART_SIZ_FULL, - #ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED -- mask_flags: MTD_WRITEABLE, -+ .mask_flags = MTD_WRITEABLE, - #endif - }, - }; -@@ -369,21 +323,21 @@ - static struct mtd_partition higlvl_partition_info[]= - { - { -- name: "ADNP boot block", -- offset: 0, -- size: CONFIG_MTD_DILNETPC_BOOTSIZE, -+ .name = "ADNP boot block", -+ .offset = 0, -+ .size = CONFIG_MTD_DILNETPC_BOOTSIZE, - }, - { -- name: "ADNP file system space", -- offset: MTDPART_OFS_NXTBLK, -- size: ADNP_WINDOW_SIZE-CONFIG_MTD_DILNETPC_BOOTSIZE-0x20000, -+ .name = "ADNP file system space", -+ .offset = MTDPART_OFS_NXTBLK, -+ .size = ADNP_WINDOW_SIZE-CONFIG_MTD_DILNETPC_BOOTSIZE-0x20000, - }, - { -- name: "ADNP system BIOS + BIOS Entry", -- offset: MTDPART_OFS_NXTBLK, -- size: MTDPART_SIZ_FULL, -+ .name = "ADNP system BIOS + BIOS Entry", -+ .offset = MTDPART_OFS_NXTBLK, -+ .size = MTDPART_SIZ_FULL, - #ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED -- mask_flags: MTD_WRITEABLE, -+ .mask_flags = MTD_WRITEABLE, - #endif - }, - }; -@@ -447,18 +401,19 @@ - } - - printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%lx\n", -- is_dnp ? "DNPC" : "ADNP", dnpc_map.size, dnpc_map.map_priv_2); -+ is_dnp ? "DNPC" : "ADNP", dnpc_map.size, dnpc_map.phys); - -- dnpc_map.map_priv_1 = (unsigned long)ioremap_nocache(dnpc_map.map_priv_2, dnpc_map.size); -+ dnpc_map.virt = (unsigned long)ioremap_nocache(dnpc_map.phys, dnpc_map.size); - -- dnpc_map_flash(dnpc_map.map_priv_2, dnpc_map.size); -+ dnpc_map_flash(dnpc_map.phys, dnpc_map.size); - -- if (!dnpc_map.map_priv_1) { -+ if (!dnpc_map.virt) { - printk("Failed to ioremap_nocache\n"); - return -EIO; - } -+ simple_map_init(&dnpc_map); - -- printk("FLASH virtual address: 0x%lx\n", dnpc_map.map_priv_1); -+ printk("FLASH virtual address: 0x%lx\n", dnpc_map.virt); - - mymtd = do_map_probe("jedec_probe", &dnpc_map); - -@@ -475,11 +430,11 @@ - mymtd->erasesize = 0x10000; - - if (!mymtd) { -- iounmap((void *)dnpc_map.map_priv_1); -+ iounmap((void *)dnpc_map.virt); - return -ENXIO; - } - -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - /* - ** Supply pointers to lowlvl_parts[] array to add_mtd_partitions() -@@ -525,10 +480,10 @@ - del_mtd_partitions(mymtd); - map_destroy(mymtd); - } -- if (dnpc_map.map_priv_1) { -- iounmap((void *)dnpc_map.map_priv_1); -+ if (dnpc_map.virt) { -+ iounmap((void *)dnpc_map.virt); - dnpc_unmap_flash(); -- dnpc_map.map_priv_1 = 0; -+ dnpc_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/ebony.c linux/drivers/mtd/maps/ebony.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/ebony.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/ebony.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,164 @@ -+/* -+ * $Id$ -+ * -+ * Mapping for Ebony user flash -+ * -+ * Matt Porter -+ * -+ * Copyright 2002 MontaVista Software Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static struct mtd_info *flash; -+ -+static struct map_info ebony_small_map = { -+ .name = "Ebony small flash", -+ .size = EBONY_SMALL_FLASH_SIZE, -+ .buswidth = 1, -+}; -+ -+static struct map_info ebony_large_map = { -+ .name = "Ebony large flash", -+ .size = EBONY_LARGE_FLASH_SIZE, -+ .buswidth = 1, -+}; -+ -+static struct mtd_partition ebony_small_partitions[] = { -+ { -+ .name = "OpenBIOS", -+ .offset = 0x0, -+ .size = 0x80000, -+ } -+}; -+ -+static struct mtd_partition ebony_large_partitions[] = { -+ { -+ .name = "fs", -+ .offset = 0, -+ .size = 0x380000, -+ }, -+ { -+ .name = "firmware", -+ .offset = 0x380000, -+ .size = 0x80000, -+ } -+}; -+ -+int __init init_ebony(void) -+{ -+ u8 fpga0_reg; -+ unsigned long fpga0_adr; -+ unsigned long long small_flash_base, large_flash_base; -+ -+ fpga0_adr = ioremap64(EBONY_FPGA_ADDR, 16); -+ if (!fpga0_adr) -+ return -ENOMEM; -+ -+ fpga0_reg = readb(fpga0_adr); -+ iounmap64(fpga0_adr); -+ -+ if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) && -+ !EBONY_FLASH_SEL(fpga0_reg)) -+ small_flash_base = EBONY_SMALL_FLASH_HIGH2; -+ else if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) && -+ EBONY_FLASH_SEL(fpga0_reg)) -+ small_flash_base = EBONY_SMALL_FLASH_HIGH1; -+ else if (!EBONY_BOOT_SMALL_FLASH(fpga0_reg) && -+ !EBONY_FLASH_SEL(fpga0_reg)) -+ small_flash_base = EBONY_SMALL_FLASH_LOW2; -+ else -+ small_flash_base = EBONY_SMALL_FLASH_LOW1; -+ -+ if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) && -+ !EBONY_ONBRD_FLASH_EN(fpga0_reg)) -+ large_flash_base = EBONY_LARGE_FLASH_LOW; -+ else -+ large_flash_base = EBONY_LARGE_FLASH_HIGH; -+ -+ ebony_small_map.phys = small_flash_base; -+ ebony_small_map.virt = -+ (unsigned long)ioremap64(small_flash_base, -+ ebony_small_map.size); -+ -+ if (!ebony_small_map.virt) { -+ printk("Failed to ioremap flash\n"); -+ return -EIO; -+ } -+ -+ simple_map_init(&ebony_small_map); -+ -+ flash = do_map_probe("map_rom", &ebony_small_map); -+ if (flash) { -+ flash->owner = THIS_MODULE; -+ add_mtd_partitions(flash, ebony_small_partitions, -+ ARRAY_SIZE(ebony_small_partitions)); -+ } else { -+ printk("map probe failed for flash\n"); -+ return -ENXIO; -+ } -+ -+ ebony_large_map.phys = large_flash_base; -+ ebony_large_map.virt = -+ (unsigned long)ioremap64(large_flash_base, -+ ebony_large_map.size); -+ -+ if (!ebony_large_map.virt) { -+ printk("Failed to ioremap flash\n"); -+ return -EIO; -+ } -+ -+ simple_map_init(&ebony_large_map); -+ -+ flash = do_map_probe("cfi_probe", &ebony_large_map); -+ if (flash) { -+ flash->owner = THIS_MODULE; -+ add_mtd_partitions(flash, ebony_large_partitions, -+ ARRAY_SIZE(ebony_large_partitions)); -+ } else { -+ printk("map probe failed for flash\n"); -+ return -ENXIO; -+ } -+ -+ return 0; -+} -+ -+static void __exit cleanup_ebony(void) -+{ -+ if (flash) { -+ del_mtd_partitions(flash); -+ map_destroy(flash); -+ } -+ -+ if (ebony_small_map.virt) { -+ iounmap((void *)ebony_small_map.virt); -+ ebony_small_map.virt = 0; -+ } -+ -+ if (ebony_large_map.virt) { -+ iounmap((void *)ebony_large_map.virt); -+ ebony_large_map.virt = 0; -+ } -+} -+ -+module_init(init_ebony); -+module_exit(cleanup_ebony); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Matt Porter "); -+MODULE_DESCRIPTION("MTD map and partitions for IBM 440GP Ebony boards"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/edb7312.c linux/drivers/mtd/maps/edb7312.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/edb7312.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/edb7312.c 2004-11-17 18:17:59.073308752 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Handle mapping of the NOR flash on Cogent EDB7312 boards - * -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -35,61 +36,11 @@ - - static struct mtd_info *mymtd; - --__u8 edb7312nor_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 edb7312nor_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 edb7312nor_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void edb7312nor_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void edb7312nor_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void edb7312nor_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void edb7312nor_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void edb7312nor_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} -- - struct map_info edb7312nor_map = { -- name: "NOR flash on EDB7312", -- size: WINDOW_SIZE, -- buswidth: BUSWIDTH, -- read8: edb7312nor_read8, -- read16: edb7312nor_read16, -- read32: edb7312nor_read32, -- copy_from: edb7312nor_copy_from, -- write8: edb7312nor_write8, -- write16: edb7312nor_write16, -- write32: edb7312nor_write32, -- copy_to: edb7312nor_copy_to -+ .name = "NOR flash on EDB7312", -+ .size = WINDOW_SIZE, -+ .buswidth = BUSWIDTH, -+ .phys = WINDOW_ADDR, - }; - - #ifdef CONFIG_MTD_PARTITIONS -@@ -100,29 +51,23 @@ - static struct mtd_partition static_partitions[3] = - { - { -- name: "ARMboot", -- size: 0x40000, -- offset: 0 -+ .name = "ARMboot", -+ .size = 0x40000, -+ .offset = 0 - }, - { -- name: "Kernel", -- size: 0x200000, -- offset: 0x40000 -+ .name = "Kernel", -+ .size = 0x200000, -+ .offset = 0x40000 - }, - { -- name: "RootFS", -- size: 0xDC0000, -- offset: 0x240000 -+ .name = "RootFS", -+ .size = 0xDC0000, -+ .offset = 0x240000 - }, - }; - --#define NB_OF(x) (sizeof (x) / sizeof (x[0])) -- --#ifdef CONFIG_MTD_CMDLINE_PARTS --int parse_cmdline_partitions(struct mtd_info *master, -- struct mtd_partition **pparts, -- const char *mtd_id); --#endif -+static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; - - #endif - -@@ -137,32 +82,33 @@ - - printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n", - WINDOW_SIZE, WINDOW_ADDR); -- edb7312nor_map.map_priv_1 = (unsigned long) -+ edb7312nor_map.virt = (unsigned long) - ioremap(WINDOW_ADDR, WINDOW_SIZE); - -- if (!edb7312nor_map.map_priv_1) { -+ if (!edb7312nor_map.virt) { - printk(MSG_PREFIX "failed to ioremap\n"); - return -EIO; - } - -+ simple_map_init(&edb7312nor_map); -+ - mymtd = 0; - type = rom_probe_types; - for(; !mymtd && *type; type++) { - mymtd = do_map_probe(*type, &edb7312nor_map); - } - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - #ifdef CONFIG_MTD_PARTITIONS --#ifdef CONFIG_MTD_CMDLINE_PARTS -- mtd_parts_nb = parse_cmdline_partitions(mymtd, &mtd_parts, MTDID); -+ mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, MTDID); - if (mtd_parts_nb > 0) -- part_type = "command line"; --#endif -+ part_type = "detected"; -+ - if (mtd_parts_nb == 0) - { - mtd_parts = static_partitions; -- mtd_parts_nb = NB_OF(static_partitions); -+ mtd_parts_nb = ARRAY_SIZE(static_partitions); - part_type = "static"; - } - #endif -@@ -178,7 +124,7 @@ - return 0; - } - -- iounmap((void *)edb7312nor_map.map_priv_1); -+ iounmap((void *)edb7312nor_map.virt); - return -ENXIO; - } - -@@ -188,9 +134,9 @@ - del_mtd_device(mymtd); - map_destroy(mymtd); - } -- if (edb7312nor_map.map_priv_1) { -- iounmap((void *)edb7312nor_map.map_priv_1); -- edb7312nor_map.map_priv_1 = 0; -+ if (edb7312nor_map.virt) { -+ iounmap((void *)edb7312nor_map.virt); -+ edb7312nor_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/elan-104nc.c linux/drivers/mtd/maps/elan-104nc.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/elan-104nc.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/elan-104nc.c 2004-11-17 18:17:59.074308600 +0100 -@@ -16,7 +16,7 @@ - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - -- $Id$ -+ $Id$ - - The ELAN-104NC has up to 8 Mibyte of Intel StrataFlash (28F320/28F640) in x16 - mode. This drivers uses the CFI probe and Intel Extended Command Set drivers. -@@ -40,6 +40,7 @@ - #include - - #include -+#include - #include - - #define WINDOW_START 0xb0000 -@@ -59,14 +60,14 @@ - * single flash device into. If the size if zero we use up to the end of the - * device. */ - static struct mtd_partition partition_info[]={ -- { name: "ELAN-104NC flash boot partition", -- offset: 0, -- size: 640*1024 }, -- { name: "ELAN-104NC flash partition 1", -- offset: 640*1024, -- size: 896*1024 }, -- { name: "ELAN-104NC flash partition 2", -- offset: (640+896)*1024 } -+ { .name = "ELAN-104NC flash boot partition", -+ .offset = 0, -+ .size = 640*1024 }, -+ { .name = "ELAN-104NC flash partition 1", -+ .offset = 640*1024, -+ .size = 896*1024 }, -+ { .name = "ELAN-104NC flash partition 2", -+ .offset = (640+896)*1024 } - }; - #define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0])) - -@@ -195,19 +196,20 @@ - } - - static struct map_info elan_104nc_map = { -- name: "ELAN-104NC flash", -- size: 8*1024*1024, /* this must be set to a maximum possible amount -+ .name = "ELAN-104NC flash", -+ .phys = NO_XIP, -+ .size = 8*1024*1024, /* this must be set to a maximum possible amount - of flash so the cfi probe routines find all - the chips */ -- buswidth: 2, -- read8: elan_104nc_read8, -- read16: elan_104nc_read16, -- read32: elan_104nc_read32, -- copy_from: elan_104nc_copy_from, -- write8: elan_104nc_write8, -- write16: elan_104nc_write16, -- write32: elan_104nc_write32, -- copy_to: elan_104nc_copy_to -+ .buswidth = 2, -+ .read8 = elan_104nc_read8, -+ .read16 = elan_104nc_read16, -+ .read32 = elan_104nc_read32, -+ .copy_from = elan_104nc_copy_from, -+ .write8 = elan_104nc_write8, -+ .write16 = elan_104nc_write16, -+ .write32 = elan_104nc_write32, -+ .copy_to = elan_104nc_copy_to - }; - - /* MTD device for all of the flash. */ -@@ -221,20 +223,13 @@ - } - - iounmap((void *)iomapadr); -- release_region(PAGE_IO,PAGE_IO_SIZE); - } - - int __init init_elan_104nc(void) - { -- /* Urg! We use I/O port 0x22 without request_region()ing it */ -- /* -- if (check_region(PAGE_IO,PAGE_IO_SIZE) != 0) { -- printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n", -- elan_104nc_map.name, -- PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 ); -- return -EAGAIN; -- } -- */ -+ /* Urg! We use I/O port 0x22 without request_region()ing it, -+ because it's already allocated to the PIC. */ -+ - iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); - if (!iomapadr) { - printk( KERN_ERR"%s: failed to ioremap memory region\n", -@@ -242,10 +237,6 @@ - return -EIO; - } - -- /* -- request_region( PAGE_IO, PAGE_IO_SIZE, "ELAN-104NC flash" ); -- */ -- - printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n", - elan_104nc_map.name, - PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1, -@@ -260,7 +251,7 @@ - return -ENXIO; - } - -- all_mtd->module=THIS_MODULE; -+ all_mtd->owner = THIS_MODULE; - - /* Create MTD devices for each partition. */ - add_mtd_partitions( all_mtd, partition_info, NUM_PARTITIONS ); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/epxa10db-flash.c linux/drivers/mtd/maps/epxa10db-flash.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/epxa10db-flash.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/epxa10db-flash.c 2004-11-17 18:17:59.079307840 +0100 -@@ -5,7 +5,7 @@ - * Copyright (C) 2001 Altera Corporation - * Copyright (C) 2001 Red Hat, Inc. - * -- * $Id$ -+ * $Id$ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -43,87 +44,38 @@ - - static struct mtd_info *mymtd; - --extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **); - static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts); - --static __u8 epxa_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --static __u16 epxa_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --static __u32 epxa_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --static void epxa_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); --} -- --static void epxa_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --static void epxa_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --static void epxa_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --static void epxa_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio((void *)(map->map_priv_1 + to), from, len); --} -- -- - - static struct map_info epxa_map = { -- name: "EPXA flash", -- size: FLASH_SIZE, -- buswidth: 2, -- read8: epxa_read8, -- read16: epxa_read16, -- read32: epxa_read32, -- copy_from: epxa_copy_from, -- write8: epxa_write8, -- write16: epxa_write16, -- write32: epxa_write32, -- copy_to: epxa_copy_to -+ .name = "EPXA flash", -+ .size = FLASH_SIZE, -+ .buswidth = 2, -+ .phys = FLASH_START, - }; - -+static const char *probes[] = { "RedBoot", "afs", NULL }; - - static int __init epxa_mtd_init(void) - { - int i; - -- printk(KERN_NOTICE "%s flash device: %x at %x\n", BOARD_NAME, FLASH_SIZE, FLASH_START); -- epxa_map.map_priv_1 = (unsigned long)ioremap(FLASH_START, FLASH_SIZE); -- if (!epxa_map.map_priv_1) { -+ printk(KERN_NOTICE "%s flash device: 0x%x at 0x%x\n", BOARD_NAME, FLASH_SIZE, FLASH_START); -+ -+ epxa_map.virt = (unsigned long)ioremap(FLASH_START, FLASH_SIZE); -+ if (!epxa_map.virt) { - printk("Failed to ioremap %s flash\n",BOARD_NAME); - return -EIO; - } -+ simple_map_init(&epxa_map); - - mymtd = do_map_probe("cfi_probe", &epxa_map); - if (!mymtd) { -- iounmap((void *)epxa_map.map_priv_1); -+ iounmap((void *)epxa_map.virt); - return -ENXIO; - } - -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - /* Unlock the flash device. */ - if(mymtd->unlock){ -@@ -135,23 +87,14 @@ - } - } - --#ifdef CONFIG_MTD_REDBOOT_PARTS -- nr_parts = parse_redboot_partitions(mymtd, &parts); -- -- if (nr_parts > 0) { -- add_mtd_partitions(mymtd, parts, nr_parts); -- return 0; -- } --#endif --#ifdef CONFIG_MTD_AFS_PARTS -- nr_parts = parse_afs_partitions(mymtd, &parts); -+#ifdef CONFIG_MTD_PARTITIONS -+ nr_parts = parse_mtd_partitions(mymtd, probes, &parts, 0); - - if (nr_parts > 0) { - add_mtd_partitions(mymtd, parts, nr_parts); - return 0; - } - #endif -- - /* No recognised partitioning schemes found - use defaults */ - nr_parts = epxa_default_partitions(mymtd, &parts); - if (nr_parts > 0) { -@@ -173,9 +116,9 @@ - del_mtd_device(mymtd); - map_destroy(mymtd); - } -- if (epxa_map.map_priv_1) { -- iounmap((void *)epxa_map.map_priv_1); -- epxa_map.map_priv_1 = 0; -+ if (epxa_map.virt) { -+ iounmap((void *)epxa_map.virt); -+ epxa_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/fortunet.c linux/drivers/mtd/maps/fortunet.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/fortunet.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/fortunet.c 2004-11-17 18:17:59.080307688 +0100 -@@ -1,11 +1,12 @@ - /* fortunet.c memory map - * -- * $Id$ -+ * $Id$ - */ - - #include - #include - #include -+#include - #include - #include - #include -@@ -23,7 +24,7 @@ - - struct map_region - { -- int window_addr_phyical; -+ int window_addr_physical; - int altbuswidth; - struct map_info map_info; - struct mtd_info *mymtd; -@@ -37,57 +38,10 @@ - static int map_regions_parts[MAX_NUM_REGIONS] = {0,0,0,0}; - - --__u8 fortunet_read8(struct map_info *map, unsigned long ofs) --{ -- return *(__u8 *)(map->map_priv_1 + ofs); --} -- --__u16 fortunet_read16(struct map_info *map, unsigned long ofs) --{ -- return *(__u16 *)(map->map_priv_1 + ofs); --} -- --__u32 fortunet_read32(struct map_info *map, unsigned long ofs) --{ -- return *(__u32 *)(map->map_priv_1 + ofs); --} -- --void fortunet_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy(to, (void *)(map->map_priv_1 + from), len); --} -- --void fortunet_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- *(__u8 *)(map->map_priv_1 + adr) = d; --} -- --void fortunet_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- *(__u16 *)(map->map_priv_1 + adr) = d; --} -- --void fortunet_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- *(__u32 *)(map->map_priv_1 + adr) = d; --} -- --void fortunet_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy((void *)(map->map_priv_1 + to), from, len); --} - - struct map_info default_map = { -- size: DEF_WINDOW_SIZE, -- buswidth: 4, -- read8: fortunet_read8, -- read16: fortunet_read16, -- read32: fortunet_read32, -- copy_from: fortunet_copy_from, -- write8: fortunet_write8, -- write16: fortunet_write16, -- write32: fortunet_write32, -- copy_to: fortunet_copy_to -+ .size = DEF_WINDOW_SIZE, -+ .buswidth = 4, - }; - - static char * __init get_string_option(char *dest,int dest_size,char *sor) -@@ -147,7 +101,7 @@ - get_options (get_string_option(string,sizeof(string),line),6,params); - if(params[0]<1) - { -- printk(MTD_FORTUNET_PK "Bad paramters for MTD Region " -+ printk(MTD_FORTUNET_PK "Bad parameters for MTD Region " - " name,region-number[,base,size,buswidth,altbuswidth]\n"); - return 1; - } -@@ -161,14 +115,14 @@ - memcpy(&map_regions[params[1]].map_info, - &default_map,sizeof(map_regions[params[1]].map_info)); - map_regions_set[params[1]] = 1; -- map_regions[params[1]].window_addr_phyical = DEF_WINDOW_ADDR_PHY; -+ map_regions[params[1]].window_addr_physical = DEF_WINDOW_ADDR_PHY; - map_regions[params[1]].altbuswidth = 2; - map_regions[params[1]].mymtd = NULL; - map_regions[params[1]].map_info.name = map_regions[params[1]].map_name; - strcpy(map_regions[params[1]].map_info.name,string); - if(params[0]>1) - { -- map_regions[params[1]].window_addr_phyical = params[2]; -+ map_regions[params[1]].window_addr_physical = params[2]; - } - if(params[0]>2) - { -@@ -185,14 +139,14 @@ - return 1; - } - --static int __init MTD_New_Partion(char *line) -+static int __init MTD_New_Partition(char *line) - { - char string[MAX_NAME_SIZE]; - int params[4]; - get_options (get_string_option(string,sizeof(string),line),4,params); - if(params[0]<3) - { -- printk(MTD_FORTUNET_PK "Bad paramters for MTD Partion " -+ printk(MTD_FORTUNET_PK "Bad parameters for MTD Partition " - " name,region-number,size,offset\n"); - return 1; - } -@@ -204,7 +158,7 @@ - } - if(map_regions_parts[params[1]]>=MAX_NUM_PARTITIONS) - { -- printk(MTD_FORTUNET_PK "Out of space for partion in this region\n"); -+ printk(MTD_FORTUNET_PK "Out of space for partition in this region\n"); - return 1; - } - map_regions[params[1]].parts[map_regions_parts[params[1]]].name = -@@ -220,7 +174,10 @@ - } - - __setup("MTD_Region=", MTD_New_Region); --__setup("MTD_Partion=", MTD_New_Partion); -+__setup("MTD_Partition=", MTD_New_Partition); -+ -+/* Backwards-spelling-compatibility */ -+__setup("MTD_Partion=", MTD_New_Partition); - - int __init init_fortunet(void) - { -@@ -229,13 +186,13 @@ - { - if(map_regions_parts[ix]&&(!map_regions_set[ix])) - { -- printk(MTD_FORTUNET_PK "Region %d is not setup (Seting to default)\n", -+ printk(MTD_FORTUNET_PK "Region %d is not setup (Setting to default)\n", - ix); - memset(&map_regions[ix],0,sizeof(map_regions[ix])); - memcpy(&map_regions[ix].map_info,&default_map, - sizeof(map_regions[ix].map_info)); - map_regions_set[ix] = 1; -- map_regions[ix].window_addr_phyical = DEF_WINDOW_ADDR_PHY; -+ map_regions[ix].window_addr_physical = DEF_WINDOW_ADDR_PHY; - map_regions[ix].altbuswidth = 2; - map_regions[ix].mymtd = NULL; - map_regions[ix].map_info.name = map_regions[ix].map_name; -@@ -244,30 +201,35 @@ - if(map_regions_set[ix]) - { - iy++; -- printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash device at phyicaly " -+ printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash device at physically " - " address %x size %x\n", - map_regions[ix].map_info.name, -- map_regions[ix].window_addr_phyical, -+ map_regions[ix].window_addr_physical, - map_regions[ix].map_info.size); -- map_regions[ix].map_info.map_priv_1 = -+ -+ map_regions[ix].map_info.phys = map_regions[ix].window_addr_physical, -+ -+ map_regions[ix].map_info.virt = - (int)ioremap_nocache( -- map_regions[ix].window_addr_phyical, -+ map_regions[ix].window_addr_physical, - map_regions[ix].map_info.size); -- if(!map_regions[ix].map_info.map_priv_1) -+ if(!map_regions[ix].map_info.virt) - { - printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n", - map_regions[ix].map_info.name); - return -ENXIO; - } -- printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash is veritualy at: %x\n", -+ simple_map_init(&map_regions[ix].map_info); -+ -+ printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash is virtually at: %x\n", - map_regions[ix].map_info.name, -- map_regions[ix].map_info.map_priv_1); -+ map_regions[ix].map_info.virt); - map_regions[ix].mymtd = do_map_probe("cfi_probe", - &map_regions[ix].map_info); - if((!map_regions[ix].mymtd)&&( - map_regions[ix].altbuswidth!=map_regions[ix].map_info.buswidth)) - { -- printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternet buswidth " -+ printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternate buswidth " - "for %s flash.\n", - map_regions[ix].map_info.name); - map_regions[ix].map_info.buswidth = -@@ -275,7 +237,7 @@ - map_regions[ix].mymtd = do_map_probe("cfi_probe", - &map_regions[ix].map_info); - } -- map_regions[ix].mymtd->module = THIS_MODULE; -+ map_regions[ix].mymtd->owner = THIS_MODULE; - add_mtd_partitions(map_regions[ix].mymtd, - map_regions[ix].parts,map_regions_parts[ix]); - } -@@ -297,7 +259,7 @@ - del_mtd_partitions( map_regions[ix].mymtd ); - map_destroy( map_regions[ix].mymtd ); - } -- iounmap((void *)map_regions[ix].map_info.map_priv_1); -+ iounmap((void *)map_regions[ix].map_info.virt); - } - } - } -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/h720x-flash.c linux/drivers/mtd/maps/h720x-flash.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/h720x-flash.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/h720x-flash.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,142 @@ -+/* -+ * Flash memory access on Hynix GMS30C7201/HMS30C7202 based -+ * evaluation boards -+ * -+ * (C) 2002 Jungjun Kim -+ * 2003 Thomas Gleixner -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static struct mtd_info *mymtd; -+ -+static struct map_info h720x_map = { -+ .name = "H720X", -+ .buswidth = 4, -+ .size = FLASH_SIZE, -+ .phys = FLASH_PHYS, -+}; -+ -+static struct mtd_partition h720x_partitions[] = { -+ { -+ .name = "ArMon", -+ .size = 0x00080000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE -+ },{ -+ .name = "Env", -+ .size = 0x00040000, -+ .offset = 0x00080000, -+ .mask_flags = MTD_WRITEABLE -+ },{ -+ .name = "Kernel", -+ .size = 0x00180000, -+ .offset = 0x000c0000, -+ .mask_flags = MTD_WRITEABLE -+ },{ -+ .name = "Ramdisk", -+ .size = 0x00400000, -+ .offset = 0x00240000, -+ .mask_flags = MTD_WRITEABLE -+ },{ -+ .name = "jffs2", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND -+ } -+}; -+ -+#define NUM_PARTITIONS (sizeof(h720x_partitions)/sizeof(h720x_partitions[0])) -+ -+static int nr_mtd_parts; -+static struct mtd_partition *mtd_parts; -+static const char *probes[] = { "cmdlinepart", NULL }; -+ -+/* -+ * Initialize FLASH support -+ */ -+int __init h720x_mtd_init(void) -+{ -+ -+ char *part_type = NULL; -+ -+ h720x_map.virt = (unsigned long)ioremap(FLASH_PHYS, FLASH_SIZE); -+ -+ if (!h720x_map.virt) { -+ printk(KERN_ERR "H720x-MTD: ioremap failed\n"); -+ return -EIO; -+ } -+ -+ simple_map_init(&h720x_map); -+ -+ // Probe for flash buswidth 4 -+ printk (KERN_INFO "H720x-MTD probing 32bit FLASH\n"); -+ mymtd = do_map_probe("cfi_probe", &h720x_map); -+ if (!mymtd) { -+ printk (KERN_INFO "H720x-MTD probing 16bit FLASH\n"); -+ // Probe for buswidth 2 -+ h720x_map.buswidth = 2; -+ mymtd = do_map_probe("cfi_probe", &h720x_map); -+ } -+ -+ if (mymtd) { -+ mymtd->owner = THIS_MODULE; -+ -+#ifdef CONFIG_MTD_PARTITIONS -+ nr_mtd_parts = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0); -+ if (nr_mtd_parts > 0) -+ part_type = "command line"; -+#endif -+ if (nr_mtd_parts <= 0) { -+ mtd_parts = h720x_partitions; -+ nr_mtd_parts = NUM_PARTITIONS; -+ part_type = "builtin"; -+ } -+ printk(KERN_INFO "Using %s partition table\n", part_type); -+ add_mtd_partitions(mymtd, mtd_parts, nr_mtd_parts); -+ return 0; -+ } -+ -+ iounmap((void *)h720x_map.virt); -+ return -ENXIO; -+} -+ -+/* -+ * Cleanup -+ */ -+static void __exit h720x_mtd_cleanup(void) -+{ -+ -+ if (mymtd) { -+ del_mtd_partitions(mymtd); -+ map_destroy(mymtd); -+ } -+ -+ /* Free partition info, if commandline partition was used */ -+ if (mtd_parts && (mtd_parts != h720x_partitions)) -+ kfree (mtd_parts); -+ -+ if (h720x_map.virt) { -+ iounmap((void *)h720x_map.virt); -+ h720x_map.virt = 0; -+ } -+} -+ -+ -+module_init(h720x_mtd_init); -+module_exit(h720x_mtd_cleanup); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Thomas Gleixner "); -+MODULE_DESCRIPTION("MTD map driver for Hynix evaluation boards"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/ichxrom.c linux/drivers/mtd/maps/ichxrom.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/ichxrom.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/ichxrom.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,380 @@ -+/* -+ * ichxrom.c -+ * -+ * Normal mappings of chips in physical memory -+ * $Id$ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define xstr(s) str(s) -+#define str(s) #s -+#define MOD_NAME xstr(KBUILD_BASENAME) -+ -+#define MTD_DEV_NAME_LENGTH 16 -+ -+#define RESERVE_MEM_REGION 0 -+ -+#define ICHX_FWH_REGION_START 0xFF000000UL -+#define ICHX_FWH_REGION_SIZE 0x01000000UL -+#define BIOS_CNTL 0x4e -+#define FWH_DEC_EN1 0xE3 -+#define FWH_DEC_EN2 0xF0 -+#define FWH_SEL1 0xE8 -+#define FWH_SEL2 0xEE -+ -+struct ichxrom_map_info { -+ struct map_info map; -+ struct mtd_info *mtd; -+ unsigned long window_addr; -+ struct pci_dev *pdev; -+ struct resource window_rsrc; -+ struct resource rom_rsrc; -+ char mtd_name[MTD_DEV_NAME_LENGTH]; -+}; -+ -+static inline unsigned long addr(struct map_info *map, unsigned long ofs) -+{ -+ unsigned long offset; -+ offset = ((8*1024*1024) - map->size) + ofs; -+ if (offset >= (4*1024*1024)) { -+ offset += 0x400000; -+ } -+ return map->map_priv_1 + 0x400000 + offset; -+} -+ -+static inline unsigned long dbg_addr(struct map_info *map, unsigned long addr) -+{ -+ return addr - map->map_priv_1 + ICHX_FWH_REGION_START; -+} -+ -+static __u8 ichxrom_read8(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readb(addr(map, ofs)); -+} -+ -+static __u16 ichxrom_read16(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readw(addr(map, ofs)); -+} -+ -+static __u32 ichxrom_read32(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readl(addr(map, ofs)); -+} -+ -+static void ichxrom_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -+{ -+ memcpy_fromio(to, addr(map, from), len); -+} -+ -+static void ichxrom_write8(struct map_info *map, __u8 d, unsigned long ofs) -+{ -+ __raw_writeb(d, addr(map,ofs)); -+ mb(); -+} -+ -+static void ichxrom_write16(struct map_info *map, __u16 d, unsigned long ofs) -+{ -+ __raw_writew(d, addr(map, ofs)); -+ mb(); -+} -+ -+static void ichxrom_write32(struct map_info *map, __u32 d, unsigned long ofs) -+{ -+ __raw_writel(d, addr(map, ofs)); -+ mb(); -+} -+ -+static void ichxrom_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -+{ -+ memcpy_toio(addr(map, to), from, len); -+} -+ -+static struct ichxrom_map_info ichxrom_map = { -+ .map = { -+ .name = MOD_NAME, -+ .phys = NO_XIP, -+ .size = 0, -+ .buswidth = 1, -+ .read8 = ichxrom_read8, -+ .read16 = ichxrom_read16, -+ .read32 = ichxrom_read32, -+ .copy_from = ichxrom_copy_from, -+ .write8 = ichxrom_write8, -+ .write16 = ichxrom_write16, -+ .write32 = ichxrom_write32, -+ .copy_to = ichxrom_copy_to, -+ /* Firmware hubs only use vpp when being programmed -+ * in a factory setting. So in-place programming -+ * needs to use a different method. -+ */ -+ }, -+ /* remaining fields of structure are initialized to 0 */ -+}; -+ -+enum fwh_lock_state { -+ FWH_DENY_WRITE = 1, -+ FWH_IMMUTABLE = 2, -+ FWH_DENY_READ = 4, -+}; -+ -+static void ichxrom_cleanup(struct ichxrom_map_info *info) -+{ -+ u16 word; -+ -+ /* Disable writes through the rom window */ -+ pci_read_config_word(info->pdev, BIOS_CNTL, &word); -+ pci_write_config_word(info->pdev, BIOS_CNTL, word & ~1); -+ -+ if (info->mtd) { -+ del_mtd_device(info->mtd); -+ map_destroy(info->mtd); -+ info->mtd = NULL; -+ info->map.virt = 0; -+ } -+ if (info->rom_rsrc.parent) -+ release_resource(&info->rom_rsrc); -+ if (info->window_rsrc.parent) -+ release_resource(&info->window_rsrc); -+ -+ if (info->window_addr) { -+ iounmap((void *)(info->window_addr)); -+ info->window_addr = 0; -+ } -+} -+ -+ -+static int ichxrom_set_lock_state(struct mtd_info *mtd, loff_t ofs, size_t len, -+ enum fwh_lock_state state) -+{ -+ struct map_info *map = mtd->priv; -+ unsigned long start = ofs; -+ unsigned long end = start + len -1; -+ -+ /* FIXME do I need to guard against concurrency here? */ -+ /* round down to 64K boundaries */ -+ start = start & ~0xFFFF; -+ end = end & ~0xFFFF; -+ while (start <= end) { -+ unsigned long ctrl_addr; -+ ctrl_addr = addr(map, start) - 0x400000 + 2; -+ writeb(state, ctrl_addr); -+ start = start + 0x10000; -+ } -+ return 0; -+} -+ -+static int ichxrom_lock(struct mtd_info *mtd, loff_t ofs, size_t len) -+{ -+ return ichxrom_set_lock_state(mtd, ofs, len, FWH_DENY_WRITE); -+} -+ -+static int ichxrom_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) -+{ -+ return ichxrom_set_lock_state(mtd, ofs, len, 0); -+} -+ -+static int __devinit ichxrom_init_one (struct pci_dev *pdev, -+ const struct pci_device_id *ent) -+{ -+ u16 word; -+ struct ichxrom_map_info *info = &ichxrom_map; -+ unsigned long map_size; -+ -+ /* For now I just handle the ichx and I assume there -+ * are not a lot of resources up at the top of the address -+ * space. It is possible to handle other devices in the -+ * top 16MB but it is very painful. Also since -+ * you can only really attach a FWH to an ICHX there -+ * a number of simplifications you can make. -+ * -+ * Also you can page firmware hubs if an 8MB window isn't enough -+ * but don't currently handle that case either. -+ */ -+ -+ info->pdev = pdev; -+ -+ /* -+ * Try to reserve the window mem region. If this fails then -+ * it is likely due to the window being "reseved" by the BIOS. -+ */ -+ info->window_rsrc.name = MOD_NAME; -+ info->window_rsrc.start = ICHX_FWH_REGION_START; -+ info->window_rsrc.end = ICHX_FWH_REGION_START + ICHX_FWH_REGION_SIZE - 1; -+ info->window_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; -+ if (request_resource(&iomem_resource, &info->window_rsrc)) { -+ info->window_rsrc.parent = NULL; -+ printk(KERN_ERR MOD_NAME -+ " %s(): Unable to register resource" -+ " 0x%.08lx-0x%.08lx - kernel bug?\n", -+ __func__, -+ info->window_rsrc.start, info->window_rsrc.end); -+ } -+ -+ /* Enable writes through the rom window */ -+ pci_read_config_word(pdev, BIOS_CNTL, &word); -+ if (!(word & 1) && (word & (1<<1))) { -+ /* The BIOS will generate an error if I enable -+ * this device, so don't even try. -+ */ -+ printk(KERN_ERR MOD_NAME ": firmware access control, I can't enable writes\n"); -+ goto failed; -+ } -+ pci_write_config_word(pdev, BIOS_CNTL, word | 1); -+ -+ -+ /* Map the firmware hub into my address space. */ -+ /* Does this use too much virtual address space? */ -+ info->window_addr = (unsigned long)ioremap( -+ ICHX_FWH_REGION_START, ICHX_FWH_REGION_SIZE); -+ if (!info->window_addr) { -+ printk(KERN_ERR "Failed to ioremap\n"); -+ goto failed; -+ } -+ -+ /* For now assume the firmware has setup all relevant firmware -+ * windows. We don't have enough information to handle this case -+ * intelligently. -+ */ -+ -+ /* FIXME select the firmware hub and enable a window to it. */ -+ -+ info->mtd = 0; -+ info->map.map_priv_1 = info->window_addr; -+ -+ map_size = ICHX_FWH_REGION_SIZE; -+ while(!info->mtd && (map_size > 0)) { -+ info->map.size = map_size; -+ info->mtd = do_map_probe("jedec_probe", &ichxrom_map.map); -+ map_size -= 512*1024; -+ } -+ if (!info->mtd) { -+ goto failed; -+ } -+ /* I know I can only be a firmware hub here so put -+ * in the special lock and unlock routines. -+ */ -+ info->mtd->lock = ichxrom_lock; -+ info->mtd->unlock = ichxrom_unlock; -+ -+ info->mtd->owner = THIS_MODULE; -+ add_mtd_device(info->mtd); -+ -+ if (info->window_rsrc.parent) { -+ /* -+ * Registering the MTD device in iomem may not be possible -+ * if there is a BIOS "reserved" and BUSY range. If this -+ * fails then continue anyway. -+ */ -+ snprintf(info->mtd_name, MTD_DEV_NAME_LENGTH, -+ "mtd%d", info->mtd->index); -+ -+ info->rom_rsrc.name = info->mtd_name; -+ info->rom_rsrc.start = ICHX_FWH_REGION_START -+ + ICHX_FWH_REGION_SIZE - map_size; -+ info->rom_rsrc.end = ICHX_FWH_REGION_START -+ + ICHX_FWH_REGION_SIZE; -+ info->rom_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; -+ if (request_resource(&info->window_rsrc, &info->rom_rsrc)) { -+ printk(KERN_ERR MOD_NAME -+ ": cannot reserve MTD resource\n"); -+ info->rom_rsrc.parent = NULL; -+ } -+ } -+ -+ return 0; -+ -+ failed: -+ ichxrom_cleanup(info); -+ return -ENODEV; -+} -+ -+ -+static void __devexit ichxrom_remove_one (struct pci_dev *pdev) -+{ -+ struct ichxrom_map_info *info = &ichxrom_map; -+ u16 word; -+ -+ del_mtd_device(info->mtd); -+ map_destroy(info->mtd); -+ info->mtd = 0; -+ info->map.map_priv_1 = 0; -+ -+ iounmap((void *)(info->window_addr)); -+ info->window_addr = 0; -+ -+ /* Disable writes through the rom window */ -+ pci_read_config_word(pdev, BIOS_CNTL, &word); -+ pci_write_config_word(pdev, BIOS_CNTL, word & ~1); -+ -+#if RESERVE_MEM_REGION -+ release_mem_region(ICHX_FWH_REGION_START, ICHX_FWH_REGION_SIZE); -+#endif -+} -+ -+static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = { -+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, -+ PCI_ANY_ID, PCI_ANY_ID, }, -+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, -+ PCI_ANY_ID, PCI_ANY_ID, }, -+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, -+ PCI_ANY_ID, PCI_ANY_ID, }, -+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, -+ PCI_ANY_ID, PCI_ANY_ID, }, -+ { 0, }, -+}; -+ -+MODULE_DEVICE_TABLE(pci, ichxrom_pci_tbl); -+ -+#if 0 -+static struct pci_driver ichxrom_driver = { -+ .name = MOD_NAME, -+ .id_table = ichxrom_pci_tbl, -+ .probe = ichxrom_init_one, -+ .remove = ichxrom_remove_one, -+}; -+#endif -+ -+static struct pci_dev *mydev; -+int __init init_ichxrom(void) -+{ -+ struct pci_dev *pdev; -+ struct pci_device_id *id; -+ pdev = 0; -+ for(id = ichxrom_pci_tbl; id->vendor; id++) { -+ pdev = pci_find_device(id->vendor, id->device, 0); -+ if (pdev) { -+ break; -+ } -+ } -+ if (pdev) { -+ mydev = pdev; -+ return ichxrom_init_one(pdev, &ichxrom_pci_tbl[0]); -+ } -+ return -ENXIO; -+#if 0 -+ return pci_module_init(&ichxrom_driver); -+#endif -+} -+ -+static void __exit cleanup_ichxrom(void) -+{ -+ ichxrom_remove_one(mydev); -+} -+ -+module_init(init_ichxrom); -+module_exit(cleanup_ichxrom); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Eric Biederman "); -+MODULE_DESCRIPTION("MTD map driver for BIOS chips on the ICHX southbridge"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/impa7.c linux/drivers/mtd/maps/impa7.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/impa7.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/impa7.c 2004-11-17 18:17:59.084307080 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Handle mapping of the NOR flash on implementa A7 boards - * -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -37,75 +38,17 @@ - - static struct mtd_info *impa7_mtd[NUM_FLASHBANKS] = { 0 }; - --__u8 impa7_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 impa7_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 impa7_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void impa7_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void impa7_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void impa7_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void impa7_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void impa7_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - static struct map_info impa7_map[NUM_FLASHBANKS] = { - { -- name: "impA7 NOR Flash Bank #0", -- size: WINDOW_SIZE0, -- buswidth: BUSWIDTH, -- read8: impa7_read8, -- read16: impa7_read16, -- read32: impa7_read32, -- copy_from: impa7_copy_from, -- write8: impa7_write8, -- write16: impa7_write16, -- write32: impa7_write32, -- copy_to: impa7_copy_to -+ .name = "impA7 NOR Flash Bank #0", -+ .size = WINDOW_SIZE0, -+ .buswidth = BUSWIDTH, - }, - { -- name: "impA7 NOR Flash Bank #1", -- size: WINDOW_SIZE1, -- buswidth: BUSWIDTH, -- read8: impa7_read8, -- read16: impa7_read16, -- read32: impa7_read32, -- copy_from: impa7_copy_from, -- write8: impa7_write8, -- write16: impa7_write16, -- write32: impa7_write32, -- copy_to: impa7_copy_to -+ .name = "impA7 NOR Flash Bank #1", -+ .size = WINDOW_SIZE1, -+ .buswidth = BUSWIDTH, - }, - }; - -@@ -117,24 +60,18 @@ - static struct mtd_partition static_partitions[] = - { - { -- name: "FileSystem", -- size: 0x800000, -- offset: 0x00000000 -+ .name = "FileSystem", -+ .size = 0x800000, -+ .offset = 0x00000000 - }, - }; - --#define NB_OF(x) (sizeof (x) / sizeof (x[0])) -+static int mtd_parts_nb[NUM_FLASHBANKS]; -+static struct mtd_partition *mtd_parts[NUM_FLASHBANKS]; - --#ifdef CONFIG_MTD_CMDLINE_PARTS --int parse_cmdline_partitions(struct mtd_info *master, -- struct mtd_partition **pparts, -- const char *mtd_id); - #endif - --#endif -- --static int mtd_parts_nb = 0; --static struct mtd_partition *mtd_parts = 0; -+static const char *probes[] = { "cmdlinepart", NULL }; - - int __init init_impa7(void) - { -@@ -146,20 +83,21 @@ - { WINDOW_ADDR0, WINDOW_SIZE0 }, - { WINDOW_ADDR1, WINDOW_SIZE1 }, - }; -- char mtdid[10]; - int devicesfound = 0; - - for(i=0; imodule = THIS_MODULE; -- add_mtd_device(impa7_mtd[i]); -+ if (impa7_mtd[i]) { -+ impa7_mtd[i]->owner = THIS_MODULE; - devicesfound++; - #ifdef CONFIG_MTD_PARTITIONS --#ifdef CONFIG_MTD_CMDLINE_PARTS -- sprintf(mtdid, MTDID, i); -- mtd_parts_nb = parse_cmdline_partitions(impa7_mtd[i], -- &mtd_parts, -- mtdid); -- if (mtd_parts_nb > 0) -+ mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i], -+ probes, -+ &mtd_parts[i], -+ 0); -+ if (mtd_parts_nb[i] > 0) { - part_type = "command line"; --#endif -- if (mtd_parts_nb <= 0) -- { -- mtd_parts = static_partitions; -- mtd_parts_nb = NB_OF(static_partitions); -+ } else { -+ mtd_parts[i] = static_partitions; -+ mtd_parts_nb[i] = ARRAY_SIZE(static_partitions); - part_type = "static"; - } -- if (mtd_parts_nb <= 0) -- { -- printk(KERN_NOTICE MSG_PREFIX -- "no partition info available\n"); -- } -- else -- { -+ - printk(KERN_NOTICE MSG_PREFIX - "using %s partition definition\n", - part_type); - add_mtd_partitions(impa7_mtd[i], -- mtd_parts, mtd_parts_nb); -- } -+ mtd_parts[i], mtd_parts_nb[i]); -+#else -+ add_mtd_device(impa7_mtd[i]); -+ - #endif - } - else -- iounmap((void *)impa7_map[i].map_priv_1); -+ iounmap((void *)impa7_map[i].virt); - } - return devicesfound == 0 ? -ENXIO : 0; - } -@@ -211,17 +140,16 @@ - static void __exit cleanup_impa7(void) - { - int i; -- for (i=0; i -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+// board specific stuff - sorry, it should be in arch/arm/mach-*. -+#ifdef CONFIG_ARCH_INTEGRATOR -+ -+#define FLASH_BASE INTEGRATOR_FLASH_BASE -+#define FLASH_SIZE INTEGRATOR_FLASH_SIZE -+ -+#define FLASH_PART_SIZE 0x400000 -+ -+#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET) -+#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET) -+#define EBI_CSR1 (IO_ADDRESS(INTEGRATOR_EBI_BASE) + INTEGRATOR_EBI_CSR1_OFFSET) -+#define EBI_LOCK (IO_ADDRESS(INTEGRATOR_EBI_BASE) + INTEGRATOR_EBI_LOCK_OFFSET) -+ -+/* -+ * Initialise the flash access systems: -+ * - Disable VPP -+ * - Assert WP -+ * - Set write enable bit in EBI reg -+ */ -+static void armflash_flash_init(void) -+{ -+ unsigned int tmp; -+ -+ __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC); -+ -+ tmp = __raw_readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE; -+ __raw_writel(tmp, EBI_CSR1); -+ -+ if (!(__raw_readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) { -+ __raw_writel(0xa05f, EBI_LOCK); -+ __raw_writel(tmp, EBI_CSR1); -+ __raw_writel(0, EBI_LOCK); -+ } -+} -+ -+/* -+ * Shutdown the flash access systems: -+ * - Disable VPP -+ * - Assert WP -+ * - Clear write enable bit in EBI reg -+ */ -+static void armflash_flash_exit(void) -+{ -+ unsigned int tmp; -+ -+ __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC); -+ -+ /* -+ * Clear the write enable bit in system controller EBI register. -+ */ -+ tmp = __raw_readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE; -+ __raw_writel(tmp, EBI_CSR1); -+ -+ if (__raw_readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) { -+ __raw_writel(0xa05f, EBI_LOCK); -+ __raw_writel(tmp, EBI_CSR1); -+ __raw_writel(0, EBI_LOCK); -+ } -+} -+ -+static void armflash_flash_wp(int on) -+{ -+ unsigned int reg; -+ -+ if (on) -+ reg = SC_CTRLC; -+ else -+ reg = SC_CTRLS; -+ -+ __raw_writel(INTEGRATOR_SC_CTRL_nFLWP, reg); -+} -+ -+static void armflash_set_vpp(struct map_info *map, int on) -+{ -+ unsigned int reg; -+ -+ if (on) -+ reg = SC_CTRLS; -+ else -+ reg = SC_CTRLC; -+ -+ __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg); -+} -+#endif -+ -+#ifdef CONFIG_ARCH_P720T -+ -+#define FLASH_BASE (0x04000000) -+#define FLASH_SIZE (64*1024*1024) -+ -+#define FLASH_PART_SIZE (4*1024*1024) -+#define FLASH_BLOCK_SIZE (128*1024) -+ -+static void armflash_flash_init(void) -+{ -+} -+ -+static void armflash_flash_exit(void) -+{ -+} -+ -+static void armflash_flash_wp(int on) -+{ -+} -+ -+static void armflash_set_vpp(struct map_info *map, int on) -+{ -+} -+#endif -+ -+ -+static struct map_info armflash_map = -+{ -+ .name = "AFS", -+ .set_vpp = armflash_set_vpp, -+ .phys = FLASH_BASE, -+}; -+ -+static struct mtd_info *mtd; -+static struct mtd_partition *parts; -+static const char *probes[] = { "RedBoot", "afs", NULL }; -+ -+static int __init armflash_cfi_init(void *base, u_int size) -+{ -+ int ret; -+ -+ armflash_flash_init(); -+ armflash_flash_wp(1); -+ -+ /* -+ * look for CFI based flash parts fitted to this board -+ */ -+ armflash_map.size = size; -+ armflash_map.buswidth = 4; -+ armflash_map.virt = (unsigned long) base; -+ -+ simple_map_init(&armflash_map); -+ -+ /* -+ * Also, the CFI layer automatically works out what size -+ * of chips we have, and does the necessary identification -+ * for us automatically. -+ */ -+ mtd = do_map_probe("cfi_probe", &armflash_map); -+ if (!mtd) -+ return -ENXIO; -+ -+ mtd->owner = THIS_MODULE; -+ -+ ret = parse_mtd_partitions(mtd, probes, &parts, (void *)0); -+ if (ret > 0) { -+ ret = add_mtd_partitions(mtd, parts, ret); -+ if (ret) -+ printk(KERN_ERR "mtd partition registration " -+ "failed: %d\n", ret); -+ } -+ -+ /* -+ * If we got an error, free all resources. -+ */ -+ if (ret < 0) { -+ del_mtd_partitions(mtd); -+ map_destroy(mtd); -+ } -+ -+ return ret; -+} -+ -+static void armflash_cfi_exit(void) -+{ -+ if (mtd) { -+ del_mtd_partitions(mtd); -+ map_destroy(mtd); -+ } -+ if (parts) -+ kfree(parts); -+} -+ -+static int __init armflash_init(void) -+{ -+ int err = -EBUSY; -+ void *base; -+ -+ if (request_mem_region(FLASH_BASE, FLASH_SIZE, "flash") == NULL) -+ goto out; -+ -+ base = ioremap(FLASH_BASE, FLASH_SIZE); -+ err = -ENOMEM; -+ if (base == NULL) -+ goto release; -+ -+ err = armflash_cfi_init(base, FLASH_SIZE); -+ if (err) { -+ iounmap(base); -+release: -+ release_mem_region(FLASH_BASE, FLASH_SIZE); -+ } -+out: -+ return err; -+} -+ -+static void __exit armflash_exit(void) -+{ -+ armflash_cfi_exit(); -+ iounmap((void *)armflash_map.virt); -+ release_mem_region(FLASH_BASE, FLASH_SIZE); -+ armflash_flash_exit(); -+} -+ -+module_init(armflash_init); -+module_exit(armflash_exit); -+ -+MODULE_AUTHOR("ARM Ltd"); -+MODULE_DESCRIPTION("ARM Integrator CFI map driver"); -+MODULE_LICENSE("GPL"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/integrator-flash.c linux/drivers/mtd/maps/integrator-flash.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/integrator-flash.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/integrator-flash.c 2004-11-17 18:17:59.101304496 +0100 -@@ -1,8 +1,9 @@ - /*====================================================================== - -- drivers/mtd/maps/armflash.c: ARM Flash Layout/Partitioning -+ drivers/mtd/maps/integrator-flash.c: ARM Integrator flash map driver - - Copyright (C) 2000 ARM Limited -+ Copyright (C) 2003 Deep Blue Solutions 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 -@@ -21,7 +22,7 @@ - This is access code for flashes using ARM's flash partitioning - standards. - -- $Id$ -+ $Id$ - - ======================================================================*/ - -@@ -31,268 +32,181 @@ - #include - #include - #include -+#include - #include - - #include - #include - #include - -+#include - #include - #include - #include - --extern int parse_afs_partitions(struct mtd_info *, struct mtd_partition **); -- --// board specific stuff - sorry, it should be in arch/arm/mach-*. --#ifdef CONFIG_ARCH_INTEGRATOR -- --#define FLASH_BASE INTEGRATOR_FLASH_BASE --#define FLASH_SIZE INTEGRATOR_FLASH_SIZE -- --#define FLASH_PART_SIZE 0x400000 -- --#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET) --#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET) --#define EBI_CSR1 (IO_ADDRESS(INTEGRATOR_EBI_BASE) + INTEGRATOR_EBI_CSR1_OFFSET) --#define EBI_LOCK (IO_ADDRESS(INTEGRATOR_EBI_BASE) + INTEGRATOR_EBI_LOCK_OFFSET) -- --/* -- * Initialise the flash access systems: -- * - Disable VPP -- * - Assert WP -- * - Set write enable bit in EBI reg -- */ --static void armflash_flash_init(void) --{ -- unsigned int tmp; -- -- __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC); -- -- tmp = __raw_readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE; -- __raw_writel(tmp, EBI_CSR1); -- -- if (!(__raw_readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) { -- __raw_writel(0xa05f, EBI_LOCK); -- __raw_writel(tmp, EBI_CSR1); -- __raw_writel(0, EBI_LOCK); -- } --} -- --/* -- * Shutdown the flash access systems: -- * - Disable VPP -- * - Assert WP -- * - Clear write enable bit in EBI reg -- */ --static void armflash_flash_exit(void) --{ -- unsigned int tmp; -- -- __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC); -- -- /* -- * Clear the write enable bit in system controller EBI register. -- */ -- tmp = __raw_readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE; -- __raw_writel(tmp, EBI_CSR1); -- -- if (__raw_readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) { -- __raw_writel(0xa05f, EBI_LOCK); -- __raw_writel(tmp, EBI_CSR1); -- __raw_writel(0, EBI_LOCK); -- } --} -- --static void armflash_flash_wp(int on) --{ -- unsigned int reg; -- -- if (on) -- reg = SC_CTRLC; -- else -- reg = SC_CTRLS; -- -- __raw_writel(INTEGRATOR_SC_CTRL_nFLWP, reg); --} -- --static void armflash_set_vpp(struct map_info *map, int on) --{ -- unsigned int reg; -- -- if (on) -- reg = SC_CTRLS; -- else -- reg = SC_CTRLC; -- -- __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg); --} --#endif -- - #ifdef CONFIG_ARCH_P720T -- - #define FLASH_BASE (0x04000000) - #define FLASH_SIZE (64*1024*1024) -- --#define FLASH_PART_SIZE (4*1024*1024) --#define FLASH_BLOCK_SIZE (128*1024) -- --static void armflash_flash_init(void) --{ --} -- --static void armflash_flash_exit(void) --{ --} -- --static void armflash_flash_wp(int on) --{ --} -- --static void armflash_set_vpp(struct map_info *map, int on) --{ --} - #endif - --static __u8 armflash_read8(struct map_info *map, unsigned long ofs) --{ -- return readb(ofs + map->map_priv_2); --} -- --static __u16 armflash_read16(struct map_info *map, unsigned long ofs) --{ -- return readw(ofs + map->map_priv_2); --} -+struct armflash_info { -+ struct flash_platform_data *plat; -+ struct resource *res; -+ struct mtd_partition *parts; -+ struct mtd_info *mtd; -+ struct map_info map; -+}; - --static __u32 armflash_read32(struct map_info *map, unsigned long ofs) -+static void armflash_set_vpp(struct map_info *map, int on) - { -- return readl(ofs + map->map_priv_2); --} -+ struct armflash_info *info = container_of(map, struct armflash_info, map); - --static void armflash_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy(to, (void *) (from + map->map_priv_2), len); -+ if (info->plat && info->plat->set_vpp) -+ info->plat->set_vpp(on); - } - --static void armflash_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, adr + map->map_priv_2); --} -- --static void armflash_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, adr + map->map_priv_2); --} -+static const char *probes[] = { "RedBoot", "afs", NULL }; - --static void armflash_write32(struct map_info *map, __u32 d, unsigned long adr) -+static int armflash_probe(struct device *_dev) - { -- writel(d, adr + map->map_priv_2); --} -+ struct platform_device *dev = to_platform_device(_dev); -+ struct flash_platform_data *plat = dev->dev.platform_data; -+ struct resource *res = dev->resource; -+ unsigned int size = res->end - res->start + 1; -+ struct armflash_info *info; -+ int err; -+ void *base; - --static void armflash_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy((void *) (to + map->map_priv_2), from, len); --} -+ info = kmalloc(sizeof(struct armflash_info), GFP_KERNEL); -+ if (!info) { -+ err = -ENOMEM; -+ goto out; -+ } - --static struct map_info armflash_map = --{ -- name: "AFS", -- read8: armflash_read8, -- read16: armflash_read16, -- read32: armflash_read32, -- copy_from: armflash_copy_from, -- write8: armflash_write8, -- write16: armflash_write16, -- write32: armflash_write32, -- copy_to: armflash_copy_to, -- set_vpp: armflash_set_vpp, --}; -+ memset(info, 0, sizeof(struct armflash_info)); - --static struct mtd_info *mtd; --static struct mtd_partition *parts; -+ info->plat = plat; -+ if (plat && plat->init) { -+ err = plat->init(); -+ if (err) -+ goto no_resource; -+ } - --static int __init armflash_cfi_init(void *base, u_int size) --{ -- int ret; -+ info->res = request_mem_region(res->start, size, "armflash"); -+ if (!info->res) { -+ err = -EBUSY; -+ goto no_resource; -+ } - -- armflash_flash_init(); -- armflash_flash_wp(1); -+ base = ioremap(res->start, size); -+ if (!base) { -+ err = -ENOMEM; -+ goto no_mem; -+ } - - /* - * look for CFI based flash parts fitted to this board - */ -- armflash_map.size = size; -- armflash_map.buswidth = 4; -- armflash_map.map_priv_2 = (unsigned long) base; -+ info->map.size = size; -+ info->map.buswidth = plat->width; -+ info->map.phys = res->start; -+ info->map.virt = (unsigned long) base; -+ info->map.name = dev->dev.bus_id; -+ info->map.set_vpp = armflash_set_vpp; -+ -+ simple_map_init(&info->map); - - /* - * Also, the CFI layer automatically works out what size - * of chips we have, and does the necessary identification - * for us automatically. - */ -- mtd = do_map_probe("cfi_probe", &armflash_map); -- if (!mtd) -- return -ENXIO; -- -- mtd->module = THIS_MODULE; -- -- ret = parse_afs_partitions(mtd, &parts); -- if (ret > 0) { -- ret = add_mtd_partitions(mtd, parts, ret); -- if (ret) -- printk(KERN_ERR "mtd partition registration " -- "failed: %d\n", ret); -+ info->mtd = do_map_probe(plat->map_name, &info->map); -+ if (!info->mtd) { -+ err = -ENXIO; -+ goto no_device; - } - -+ info->mtd->owner = THIS_MODULE; -+ -+ err = parse_mtd_partitions(info->mtd, probes, &info->parts, 0); -+ if (err > 0) { -+ err = add_mtd_partitions(info->mtd, info->parts, err); -+ if (err) -+ printk(KERN_ERR -+ "mtd partition registration failed: %d\n", err); -+ } -+ -+ if (err == 0) -+ dev_set_drvdata(&dev->dev, info); -+ - /* - * If we got an error, free all resources. - */ -- if (ret < 0) { -- del_mtd_partitions(mtd); -- map_destroy(mtd); -+ if (err < 0) { -+ if (info->mtd) { -+ del_mtd_partitions(info->mtd); -+ map_destroy(info->mtd); - } -+ if (info->parts) -+ kfree(info->parts); - -- return ret; --} -- --static void armflash_cfi_exit(void) --{ -- if (mtd) { -- del_mtd_partitions(mtd); -- map_destroy(mtd); -+ no_device: -+ iounmap(base); -+ no_mem: -+ release_mem_region(res->start, size); -+ no_resource: -+ if (plat && plat->exit) -+ plat->exit(); -+ kfree(info); - } -- if (parts) -- kfree(parts); -+ out: -+ return err; - } - --static int __init armflash_init(void) -+static int armflash_remove(struct device *_dev) - { -- int err = -EBUSY; -- void *base; -+ struct platform_device *dev = to_platform_device(_dev); -+ struct armflash_info *info = dev_get_drvdata(&dev->dev); - -- if (request_mem_region(FLASH_BASE, FLASH_SIZE, "flash") == NULL) -- goto out; -+ dev_set_drvdata(&dev->dev, NULL); - -- base = ioremap(FLASH_BASE, FLASH_SIZE); -- err = -ENOMEM; -- if (base == NULL) -- goto release; -+ if (info) { -+ if (info->mtd) { -+ del_mtd_partitions(info->mtd); -+ map_destroy(info->mtd); -+ } -+ if (info->parts) -+ kfree(info->parts); - -- err = armflash_cfi_init(base, FLASH_SIZE); -- if (err) { -- iounmap(base); --release: -- release_mem_region(FLASH_BASE, FLASH_SIZE); -+ iounmap((void *)info->map.virt); -+ release_resource(info->res); -+ kfree(info->res); -+ -+ if (info->plat && info->plat->exit) -+ info->plat->exit(); -+ -+ kfree(info); - } --out: -- return err; -+ -+ return 0; -+} -+ -+static struct device_driver armflash_driver = { -+ .name = "armflash", -+ .bus = &platform_bus_type, -+ .probe = armflash_probe, -+ .remove = armflash_remove, -+}; -+ -+static int __init armflash_init(void) -+{ -+ return driver_register(&armflash_driver); - } - - static void __exit armflash_exit(void) - { -- armflash_cfi_exit(); -- iounmap((void *)armflash_map.map_priv_2); -- release_mem_region(FLASH_BASE, FLASH_SIZE); -- armflash_flash_exit(); -+ driver_unregister(&armflash_driver); - } - - module_init(armflash_init); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/iq80310.c linux/drivers/mtd/maps/iq80310.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/iq80310.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/iq80310.c 2004-11-17 18:17:59.103304192 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Mapping for the Intel XScale IQ80310 evaluation board - * -@@ -14,6 +14,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -26,127 +28,72 @@ - - static struct mtd_info *mymtd; - --static __u8 iq80310_read8(struct map_info *map, unsigned long ofs) --{ -- return *(__u8 *)(map->map_priv_1 + ofs); --} -- --static __u16 iq80310_read16(struct map_info *map, unsigned long ofs) --{ -- return *(__u16 *)(map->map_priv_1 + ofs); --} -- --static __u32 iq80310_read32(struct map_info *map, unsigned long ofs) --{ -- return *(__u32 *)(map->map_priv_1 + ofs); --} -- --static void iq80310_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy(to, (void *)(map->map_priv_1 + from), len); --} -- --static void iq80310_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- *(__u8 *)(map->map_priv_1 + adr) = d; --} -- --static void iq80310_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- *(__u16 *)(map->map_priv_1 + adr) = d; --} -- --static void iq80310_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- *(__u32 *)(map->map_priv_1 + adr) = d; --} -- --static void iq80310_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy((void *)(map->map_priv_1 + to), from, len); --} -- - static struct map_info iq80310_map = { -- name: "IQ80310 flash", -- size: WINDOW_SIZE, -- buswidth: BUSWIDTH, -- read8: iq80310_read8, -- read16: iq80310_read16, -- read32: iq80310_read32, -- copy_from: iq80310_copy_from, -- write8: iq80310_write8, -- write16: iq80310_write16, -- write32: iq80310_write32, -- copy_to: iq80310_copy_to -+ .name = "IQ80310 flash", -+ .size = WINDOW_SIZE, -+ .buswidth = BUSWIDTH, -+ .phys = WINDOW_ADDR - }; - - static struct mtd_partition iq80310_partitions[4] = { - { -- name: "Firmware", -- size: 0x00080000, -- offset: 0, -- mask_flags: MTD_WRITEABLE /* force read-only */ -+ .name = "Firmware", -+ .size = 0x00080000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ - },{ -- name: "Kernel", -- size: 0x000a0000, -- offset: 0x00080000, -+ .name = "Kernel", -+ .size = 0x000a0000, -+ .offset = 0x00080000, - },{ -- name: "Filesystem", -- size: 0x00600000, -- offset: 0x00120000 -+ .name = "Filesystem", -+ .size = 0x00600000, -+ .offset = 0x00120000 - },{ -- name: "RedBoot", -- size: 0x000e0000, -- offset: 0x00720000, -- mask_flags: MTD_WRITEABLE -+ .name = "RedBoot", -+ .size = 0x000e0000, -+ .offset = 0x00720000, -+ .mask_flags = MTD_WRITEABLE - } - }; - --#define NB_OF(x) (sizeof(x)/sizeof(x[0])) -- - static struct mtd_info *mymtd; - static struct mtd_partition *parsed_parts; -- --extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts); -+static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; - - static int __init init_iq80310(void) - { - struct mtd_partition *parts; - int nb_parts = 0; - int parsed_nr_parts = 0; -- char *part_type = "static"; -+ int ret; - -- iq80310_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); -- if (!iq80310_map.map_priv_1) { -+ iq80310_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); -+ if (!iq80310_map.virt) { - printk("Failed to ioremap\n"); - return -EIO; - } -+ simple_map_init(&iq80310_map); -+ - mymtd = do_map_probe("cfi_probe", &iq80310_map); - if (!mymtd) { -- iounmap((void *)iq80310_map.map_priv_1); -+ iounmap((void *)iq80310_map.virt); - return -ENXIO; - } -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - --#ifdef CONFIG_MTD_REDBOOT_PARTS -- if (parsed_nr_parts == 0) { -- int ret = parse_redboot_partitions(mymtd, &parsed_parts); -+ ret = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0); - -- if (ret > 0) { -- part_type = "RedBoot"; -+ if (ret > 0) - parsed_nr_parts = ret; -- } -- } --#endif - - if (parsed_nr_parts > 0) { - parts = parsed_parts; - nb_parts = parsed_nr_parts; - } else { - parts = iq80310_partitions; -- nb_parts = NB_OF(iq80310_partitions); -+ nb_parts = ARRAY_SIZE(iq80310_partitions); - } -- printk(KERN_NOTICE "Using %s partition definition\n", part_type); - add_mtd_partitions(mymtd, parts, nb_parts); - return 0; - } -@@ -159,8 +106,8 @@ - if (parsed_parts) - kfree(parsed_parts); - } -- if (iq80310_map.map_priv_1) -- iounmap((void *)iq80310_map.map_priv_1); -+ if (iq80310_map.virt) -+ iounmap((void *)iq80310_map.virt); - } - - module_init(init_iq80310); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/ixp425.c linux/drivers/mtd/maps/ixp425.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/ixp425.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/ixp425.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,220 @@ -+/* -+ * $Id$ -+ * -+ * drivers/mtd/maps/ixp425.c -+ * -+ * MTD Map file for IXP425 based systems. Please do not make per-board -+ * map driver as the code will be 90% identical. For now just add -+ * if(machine_is_XXX()) checks to the code. I'll clean this stuff to -+ * use platform_data in the the future so we can get rid of that too. -+ * -+ * Original Author: Intel Corporation -+ * Maintainer: Deepak Saxena -+ * -+ * Copyright (C) 2002 Intel Corporation -+ * Copyright (C) 2003 MontaVista Software, Inc. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define WINDOW_ADDR 0x50000000 -+#define BUSWIDTH 2 -+ -+#ifndef __ARMEB__ -+#define BYTE0(h) ((h) & 0xFF) -+#define BYTE1(h) (((h) >> 8) & 0xFF) -+#else -+#define BYTE0(h) (((h) >> 8) & 0xFF) -+#define BYTE1(h) ((h) & 0xFF) -+#endif -+ -+static __u16 -+ixp425_read16(struct map_info *map, unsigned long ofs) -+{ -+ return *(__u16 *) (map->map_priv_1 + ofs); -+} -+ -+/* -+ * The IXP425 expansion bus only allows 16-bit wide acceses -+ * when attached to a 16-bit wide device (such as the 28F128J3A), -+ * so we can't just memcpy_fromio(). -+ */ -+static void -+ixp425_copy_from(struct map_info *map, void *to, -+ unsigned long from, ssize_t len) -+{ -+ int i; -+ u8 *dest = (u8 *) to; -+ u16 *src = (u16 *) (map->map_priv_1 + from); -+ u16 data; -+ -+ for (i = 0; i < (len / 2); i++) { -+ data = src[i]; -+ dest[i * 2] = BYTE0(data); -+ dest[i * 2 + 1] = BYTE1(data); -+ } -+ -+ if (len & 1) -+ dest[len - 1] = BYTE0(src[i]); -+} -+ -+static void -+ixp425_write16(struct map_info *map, __u16 d, unsigned long adr) -+{ -+ *(__u16 *) (map->map_priv_1 + adr) = d; -+} -+ -+static struct map_info ixp425_map = { -+ .name = "IXP425 Flash", -+ .buswidth = BUSWIDTH, -+ .read16 = ixp425_read16, -+ .copy_from = ixp425_copy_from, -+ .write16 = ixp425_write16, -+}; -+ -+/* -+ * Put flash back in read mode so RedBoot can boot properly. -+ */ -+int ixp425_mtd_reboot(struct notifier_block *n, unsigned long code, void *p) -+{ -+ if (code != SYS_RESTART) -+ return NOTIFY_DONE; -+ -+ ixp425_write16(&ixp425_map, 0xff, 0x55 * 0x2); -+ return NOTIFY_DONE; -+} -+ -+static struct notifier_block ixp425_mtd_notifier = { -+ notifier_call:ixp425_mtd_reboot, -+ next:NULL, -+ priority:0 -+}; -+ -+static struct mtd_partition *parsed_parts; -+static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; -+ -+static struct mtd_partition ixp425_partitions[] = { -+ { -+ .name = "image", -+ .offset = 0x00040000, -+ .size = 0x00400000, -+ }, { -+ .name = "user", -+ .offset = 0x00440000, -+ .size = MTDPART_SIZ_FULL -+ } -+}; -+ -+#define NB_OF(x) (sizeof(x)/sizeof(x[0])) -+ -+static struct mtd_info *ixp425_mtd; -+static struct resource *mtd_resource; -+ -+static void -+ixp425_exit(void) -+{ -+ if (ixp425_mtd) { -+ del_mtd_partitions(ixp425_mtd); -+ map_destroy(ixp425_mtd); -+ } -+ if (ixp425_map.map_priv_1) -+ iounmap((void *) ixp425_map.map_priv_1); -+ if (mtd_resource) -+ release_mem_region(WINDOW_ADDR, ixp425_map.size); -+ -+ if (parsed_parts) -+ kfree(parsed_parts); -+ -+ unregister_reboot_notifier(&ixp425_mtd_notifier); -+ -+ /* Disable flash write */ -+ *IXP425_EXP_CS0 &= ~IXP425_FLASH_WRITABLE; -+ -+ if(machine_is_adi_coyote()) -+ *IXP425_EXP_CS1 &= ~IXP425_FLASH_WRITABLE; -+} -+ -+static int __init -+ixp425_init(void) -+{ -+ int res = -1, npart; -+ -+ /* Enable flash write */ -+ *IXP425_EXP_CS0 |= IXP425_FLASH_WRITABLE; -+ -+ /* -+ * Coyote requires CS1 write to be enabled and has 32MB flash. -+ * This will move to the platform init code in 2.6 -+ */ -+ if(machine_is_adi_coyote()) { -+ *IXP425_EXP_CS1 |= IXP425_FLASH_WRITABLE; -+ ixp425_map.size = 0x02000000; -+ } else -+ ixp425_map.size = 0x01000000; -+ -+ ixp425_map.map_priv_1 = 0; -+ mtd_resource = -+ request_mem_region(WINDOW_ADDR, ixp425_map.size, "IXP425 Flash"); -+ if (!mtd_resource) { -+ printk(KERN_ERR -+ "ixp425 flash: Could not request mem region.\n"); -+ res = -ENOMEM; -+ goto Error; -+ } -+ -+ ixp425_map.map_priv_1 = -+ (unsigned long) ioremap(WINDOW_ADDR, ixp425_map.size); -+ if (!ixp425_map.map_priv_1) { -+ printk("ixp425 Flash: Failed to map IO region. (ioremap)\n"); -+ res = -EIO; -+ goto Error; -+ } -+ -+ ixp425_mtd = do_map_probe("cfi_probe", &ixp425_map); -+ if (!ixp425_mtd) { -+ res = -ENXIO; -+ goto Error; -+ } -+ ixp425_mtd->owner = THIS_MODULE; -+ -+ /* Try to parse RedBoot partitions */ -+ npart = parse_mtd_partitions(ixp425_mtd, probes, &parsed_parts, 0); -+ if (npart > 0) -+ res = add_mtd_partitions(ixp425_mtd, parsed_parts, npart); -+ else { -+ printk("IXP425 Flash: Using static MTD partitions.\n"); -+ res = add_mtd_partitions(ixp425_mtd, ixp425_partitions, -+ NB_OF(ixp425_partitions)); -+ } -+ -+ if (res) -+ goto Error; -+ -+ register_reboot_notifier(&ixp425_mtd_notifier); -+ -+ return res; -+ -+Error: -+ ixp425_exit(); -+ return res; -+} -+ -+module_init(ixp425_init); -+module_exit(ixp425_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("MTD map driver for ixp425 evaluation board"); -+MODULE_AUTHOR("Deepak Saxena"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/l440gx.c linux/drivers/mtd/maps/l440gx.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/l440gx.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/l440gx.c 2004-11-17 18:17:59.105303888 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * BIOS Flash chip on Intel 440GX board. - * -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -27,48 +28,6 @@ - - static struct mtd_info *mymtd; - --__u8 l440gx_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 l440gx_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 l440gx_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void l440gx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void l440gx_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void l440gx_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void l440gx_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void l440gx_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - /* Is this really the vpp port? */ - void l440gx_set_vpp(struct map_info *map, int vpp) -@@ -85,22 +44,15 @@ - } - - struct map_info l440gx_map = { -- name: "L440GX BIOS", -- size: WINDOW_SIZE, -- buswidth: BUSWIDTH, -- read8: l440gx_read8, -- read16: l440gx_read16, -- read32: l440gx_read32, -- copy_from: l440gx_copy_from, -- write8: l440gx_write8, -- write16: l440gx_write16, -- write32: l440gx_write32, -- copy_to: l440gx_copy_to, -+ .name = "L440GX BIOS", -+ .size = WINDOW_SIZE, -+ .buswidth = BUSWIDTH, -+ .phys = WINDOW_ADDR, - #if 0 - /* FIXME verify that this is the - * appripriate code for vpp enable/disable - */ -- set_vpp: l440gx_set_vpp -+ .set_vpp = l440gx_set_vpp - #endif - }; - -@@ -113,7 +65,6 @@ - dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_0, NULL); - -- - pm_dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_3, NULL); - -@@ -122,15 +73,14 @@ - return -ENODEV; - } - -+ l440gx_map.virt = (unsigned long)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE); - -- l440gx_map.map_priv_1 = (unsigned long)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE); -- -- if (!l440gx_map.map_priv_1) { -+ if (!l440gx_map.virt) { - printk(KERN_WARNING "Failed to ioremap L440GX flash region\n"); - return -ENOMEM; - } -- -- printk(KERN_NOTICE "window_addr = 0x%08lx\n", (unsigned long)l440gx_map.map_priv_1); -+ simple_map_init(&l440gx_map); -+ printk(KERN_NOTICE "window_addr = 0x%08lx\n", (unsigned long)l440gx_map.virt); - - /* Setup the pm iobase resource - * This code should move into some kind of generic bridge -@@ -153,7 +103,7 @@ - /* Allocate the resource region */ - if (pci_assign_resource(pm_dev, PIIXE_IOBASE_RESOURCE) != 0) { - printk(KERN_WARNING "Could not allocate pm iobase resource\n"); -- iounmap((void *)l440gx_map.map_priv_1); -+ iounmap((void *)l440gx_map.virt); - return -ENXIO; - } - } -@@ -181,13 +131,13 @@ - mymtd = do_map_probe("map_rom", &l440gx_map); - } - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - add_mtd_device(mymtd); - return 0; - } - -- iounmap((void *)l440gx_map.map_priv_1); -+ iounmap((void *)l440gx_map.virt); - return -ENXIO; - } - -@@ -196,7 +146,7 @@ - del_mtd_device(mymtd); - map_destroy(mymtd); - -- iounmap((void *)l440gx_map.map_priv_1); -+ iounmap((void *)l440gx_map.virt); - } - - module_init(init_l440gx); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/lasat.c linux/drivers/mtd/maps/lasat.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/lasat.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/lasat.c 2004-11-17 18:17:59.106303736 +0100 -@@ -1,11 +1,20 @@ - /* -- * Flash device on lasat 100 and 200 boards -+ * Flash device on Lasat 100 and 200 boards -+ * -+ * (C) 2002 Brian Murphy -+ * -+ * 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. -+ * -+ * $Id$ - * - */ - - #include - #include - #include -+#include - #include - #include - #include -@@ -13,123 +22,80 @@ - #include - #include - --static struct mtd_info *mymtd; -- --static __u8 sp_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --static __u16 sp_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --static __u32 sp_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --static void sp_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -+static struct mtd_info *lasat_mtd; - --static void sp_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --static void sp_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --static void sp_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -+static struct mtd_partition partition_info[LASAT_MTD_LAST]; -+static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Filesystem", "Config"}; - --static void sp_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -+static void lasat_set_vpp(struct map_info *map, int vpp) - { -- memcpy_toio(map->map_priv_1 + to, from, len); -+ if (vpp) -+ *lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit; -+ else -+ *lasat_misc->flash_wp_reg &= ~(1 << lasat_misc->flash_wp_bit); - } - --static struct map_info sp_map = { -- name: "SP flash", -- buswidth: 4, -- read8: sp_read8, -- read16: sp_read16, -- read32: sp_read32, -- copy_from: sp_copy_from, -- write8: sp_write8, -- write16: sp_write16, -- write32: sp_write32, -- copy_to: sp_copy_to -+static struct map_info lasat_map = { -+ .name = "LASAT flash", -+ .buswidth = 4, -+ .set_vpp = lasat_set_vpp - }; - --static struct mtd_partition partition_info[LASAT_MTD_LAST]; --static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Config", "Filesystem"}; -- --static int __init init_sp(void) -+static int __init init_lasat(void) - { - int i; -- int nparts = 0; -- /* this does not play well with the old flash code which -- * protects and uprotects the flash when necessary */ -+ /* since we use AMD chips and set_vpp is not implimented -+ * for these (yet) we still have to permanently enable flash write */ - printk(KERN_NOTICE "Unprotecting flash\n"); -- *lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit; -+ ENABLE_VPP((&lasat_map)); - -- sp_map.map_priv_1 = ioremap_nocache( -- lasat_flash_partition_start(LASAT_MTD_BOOTLOADER), -- lasat_board_info.li_flash_size); -- sp_map.size = lasat_board_info.li_flash_size; -+ lasat_map.phys = lasat_flash_partition_start(LASAT_MTD_BOOTLOADER); -+ lasat_map.virt = (unsigned long)ioremap_nocache( -+ lasat_map.phys, lasat_board_info.li_flash_size); -+ lasat_map.size = lasat_board_info.li_flash_size; - -- printk(KERN_NOTICE "sp flash device: %lx at %lx\n", -- sp_map.size, sp_map.map_priv_1); -+ simple_map_init(&lasat_map); - - for (i=0; i < LASAT_MTD_LAST; i++) - partition_info[i].name = lasat_mtd_partnames[i]; - -- mymtd = do_map_probe("cfi_probe", &sp_map); -- if (mymtd) { -+ lasat_mtd = do_map_probe("cfi_probe", &lasat_map); -+ -+ if (!lasat_mtd) -+ lasat_mtd = do_map_probe("jedec_probe", &lasat_map); -+ -+ if (lasat_mtd) { - u32 size, offset = 0; - -- mymtd->module = THIS_MODULE; -+ lasat_mtd->owner = THIS_MODULE; - - for (i=0; i < LASAT_MTD_LAST; i++) { - size = lasat_flash_partition_size(i); -- if (size != 0) { -- nparts++; - partition_info[i].size = size; - partition_info[i].offset = offset; - offset += size; - } -- } - -- add_mtd_partitions( mymtd, partition_info, nparts ); -+ add_mtd_partitions( lasat_mtd, partition_info, LASAT_MTD_LAST ); - return 0; - } - - return -ENXIO; - } - --static void __exit cleanup_sp(void) -+static void __exit cleanup_lasat(void) - { -- if (mymtd) { -- del_mtd_partitions(mymtd); -- map_destroy(mymtd); -+ if (lasat_mtd) { -+ del_mtd_partitions(lasat_mtd); -+ map_destroy(lasat_mtd); - } -- if (sp_map.map_priv_1) { -- sp_map.map_priv_1 = 0; -+ if (lasat_map.virt) { -+ lasat_map.virt = 0; - } - } - --module_init(init_sp); --module_exit(cleanup_sp); -+module_init(init_lasat); -+module_exit(cleanup_lasat); - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Brian Murphy "); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/lubbock-flash.c linux/drivers/mtd/maps/lubbock-flash.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/lubbock-flash.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/lubbock-flash.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,151 @@ -+/* -+ * $Id$ -+ * -+ * Map driver for the Lubbock developer platform. -+ * -+ * Author: Nicolas Pitre -+ * Copyright: (C) 2001 MontaVista Software Inc. -+ * -+ * 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 -+ -+ -+#define ROM_ADDR 0x00000000 -+#define FLASH_ADDR 0x04000000 -+ -+#define WINDOW_SIZE 64*1024*1024 -+ -+static struct map_info lubbock_maps[2] = { { -+ .size = WINDOW_SIZE, -+ .phys = 0x00000000, -+}, { -+ .size = WINDOW_SIZE, -+ .phys = 0x04000000, -+} }; -+ -+static struct mtd_partition lubbock_partitions[] = { -+ { -+ .name = "Bootloader", -+ .size = 0x00040000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ -+ },{ -+ .name = "Kernel", -+ .size = 0x00100000, -+ .offset = 0x00040000, -+ },{ -+ .name = "Filesystem", -+ .size = MTDPART_SIZ_FULL, -+ .offset = 0x00140000 -+ } -+}; -+ -+static struct mtd_info *mymtds[2]; -+static struct mtd_partition *parsed_parts[2]; -+static int nr_parsed_parts[2]; -+ -+static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; -+ -+static int __init init_lubbock(void) -+{ -+ int flashboot = (CONF_SWITCHES & 1); -+ int ret = 0, i; -+ -+ lubbock_maps[0].buswidth = lubbock_maps[1].buswidth = -+ (BOOT_DEF & 1) ? 2 : 4; -+ -+ /* Compensate for the nROMBT switch which swaps the flash banks */ -+ printk(KERN_NOTICE "Lubbock configured to boot from %s (bank %d)\n", -+ flashboot?"Flash":"ROM", flashboot); -+ -+ lubbock_maps[flashboot^1].name = "Lubbock Application Flash"; -+ lubbock_maps[flashboot].name = "Lubbock Boot ROM"; -+ -+ for (i = 0; i < 2; i++) { -+ lubbock_maps[i].virt = (unsigned long)__ioremap(lubbock_maps[i].phys, WINDOW_SIZE, 0); -+ if (!lubbock_maps[i].virt) { -+ printk(KERN_WARNING "Failed to ioremap %s\n", lubbock_maps[i].name); -+ if (!ret) -+ ret = -ENOMEM; -+ continue; -+ } -+ simple_map_init(&lubbock_maps[i]); -+ -+ printk(KERN_NOTICE "Probing %s at physical address 0x%08lx (%d-bit buswidth)\n", -+ lubbock_maps[i].name, lubbock_maps[i].phys, -+ lubbock_maps[i].buswidth * 8); -+ -+ mymtds[i] = do_map_probe("cfi_probe", &lubbock_maps[i]); -+ -+ if (!mymtds[i]) { -+ iounmap((void *)lubbock_maps[i].virt); -+ if (!ret) -+ ret = -EIO; -+ continue; -+ } -+ mymtds[i]->owner = THIS_MODULE; -+ -+ int ret = parse_mtd_partitions(mymtds[i], probes, -+ &parsed_parts[i], 0); -+ -+ if (ret > 0) -+ nr_parsed_parts[i] = ret; -+ } -+ -+ if (!mymtds[0] && !mymtds[1]) -+ return ret; -+ -+ for (i = 0; i < 2; i++) { -+ if (!mymtds[i]) { -+ printk(KERN_WARNING "%s is absent. Skipping\n", lubbock_maps[i].name); -+ } else if (nr_parsed_parts[i]) { -+ add_mtd_partitions(mymtds[i], parsed_parts[i], nr_parsed_parts[i]); -+ } else if (!i) { -+ printk("Using static partitions on %s\n", lubbock_maps[i].name); -+ add_mtd_partitions(mymtds[i], lubbock_partitions, ARRAY_SIZE(lubbock_partitions)); -+ } else { -+ printk("Registering %s as whole device\n", lubbock_maps[i].name); -+ add_mtd_device(mymtds[i]); -+ } -+ } -+ return 0; -+} -+ -+static void __exit cleanup_lubbock(void) -+{ -+ int i; -+ for (i = 0; i < 2; i++) { -+ if (!mymtds[i]) -+ continue; -+ -+ if (nr_parsed_parts[i] || !i) -+ del_mtd_partitions(mymtds[i]); -+ else -+ del_mtd_device(mymtds[i]); -+ -+ map_destroy(mymtds[i]); -+ iounmap((void *)lubbock_maps[i].virt); -+ -+ if (parsed_parts[i]) -+ kfree(parsed_parts[i]); -+ } -+} -+ -+module_init(init_lubbock); -+module_exit(cleanup_lubbock); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Nicolas Pitre "); -+MODULE_DESCRIPTION("MTD map driver for Intel Lubbock"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/map_funcs.c linux/drivers/mtd/maps/map_funcs.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/map_funcs.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/map_funcs.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,96 @@ -+/* -+ * $Id$ -+ * -+ * Out-of-line map I/O functions for simple maps when CONFIG_COMPLEX_MAPPINGS -+ * is enabled. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+static u8 simple_map_read8(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readb(map->virt + ofs); -+} -+ -+static u16 simple_map_read16(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readw(map->virt + ofs); -+} -+ -+static u32 simple_map_read32(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readl(map->virt + ofs); -+} -+ -+static u64 simple_map_read64(struct map_info *map, unsigned long ofs) -+{ -+#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */ -+ BUG(); -+ return 0; -+#else -+ return __raw_readll(map->virt + ofs); -+#endif -+} -+ -+static void simple_map_write8(struct map_info *map, u8 datum, unsigned long ofs) -+{ -+ __raw_writeb(datum, map->virt + ofs); -+ mb(); -+} -+ -+static void simple_map_write16(struct map_info *map, u16 datum, unsigned long ofs) -+{ -+ __raw_writew(datum, map->virt + ofs); -+ mb(); -+} -+ -+static void simple_map_write32(struct map_info *map, u32 datum, unsigned long ofs) -+{ -+ __raw_writel(datum, map->virt + ofs); -+ mb(); -+} -+ -+static void simple_map_write64(struct map_info *map, u64 datum, unsigned long ofs) -+{ -+#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */ -+ BUG(); -+#else -+ __raw_writell(datum, map->virt + ofs); -+ mb(); -+#endif /* CFI_B8 */ -+} -+ -+static void simple_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -+{ -+ memcpy_fromio(to, map->virt + from, len); -+} -+ -+static void simple_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -+{ -+ memcpy_toio(map->virt + to, from, len); -+} -+ -+void simple_map_init(struct map_info *map) -+{ -+ map->read8 = simple_map_read8; -+ map->read16 = simple_map_read16; -+ map->read32 = simple_map_read32; -+ map->read64 = simple_map_read64; -+ map->write8 = simple_map_write8; -+ map->write16 = simple_map_write16; -+ map->write32 = simple_map_write32; -+ map->write64 = simple_map_write64; -+ map->copy_from = simple_map_copy_from; -+ map->copy_to = simple_map_copy_to; -+} -+ -+EXPORT_SYMBOL(simple_map_init); -+ -+MODULE_LICENSE("GPL"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/mbx860.c linux/drivers/mtd/maps/mbx860.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/mbx860.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/mbx860.c 2004-11-17 18:17:59.110303128 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Handle mapping of the flash on MBX860 boards - * -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -36,91 +37,46 @@ - * single flash device into. If the size if zero we use up to the end of the - * device. */ - static struct mtd_partition partition_info[]={ -- { name: "MBX flash BOOT partition", -- offset: 0, -- size: BOOT_PARTITION_SIZE_KiB*1024 }, -- { name: "MBX flash DATA partition", -- offset: BOOT_PARTITION_SIZE_KiB*1024, -- size: (KERNEL_PARTITION_SIZE_KiB)*1024 }, -- { name: "MBX flash APPLICATION partition", -- offset: (BOOT_PARTITION_SIZE_KiB+KERNEL_PARTITION_SIZE_KiB)*1024 } -+ { .name = "MBX flash BOOT partition", -+ .offset = 0, -+ .size = BOOT_PARTITION_SIZE_KiB*1024 }, -+ { .name = "MBX flash DATA partition", -+ .offset = BOOT_PARTITION_SIZE_KiB*1024, -+ .size = (KERNEL_PARTITION_SIZE_KiB)*1024 }, -+ { .name = "MBX flash APPLICATION partition", -+ .offset = (BOOT_PARTITION_SIZE_KiB+KERNEL_PARTITION_SIZE_KiB)*1024 } - }; - - - static struct mtd_info *mymtd; - --__u8 mbx_read8(struct map_info *map, unsigned long ofs) --{ -- return readb(map->map_priv_1 + ofs); --} -- --__u16 mbx_read16(struct map_info *map, unsigned long ofs) --{ -- return readw(map->map_priv_1 + ofs); --} -- --__u32 mbx_read32(struct map_info *map, unsigned long ofs) --{ -- return readl(map->map_priv_1 + ofs); --} -- --void mbx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); --} -- --void mbx_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, map->map_priv_1 + adr); --} -- --void mbx_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, map->map_priv_1 + adr); --} -- --void mbx_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- writel(d, map->map_priv_1 + adr); --} -- --void mbx_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio((void *)(map->map_priv_1 + to), from, len); --} -- - struct map_info mbx_map = { -- name: "MBX flash", -- size: WINDOW_SIZE, -- buswidth: 4, -- read8: mbx_read8, -- read16: mbx_read16, -- read32: mbx_read32, -- copy_from: mbx_copy_from, -- write8: mbx_write8, -- write16: mbx_write16, -- write32: mbx_write32, -- copy_to: mbx_copy_to -+ .name = "MBX flash", -+ .size = WINDOW_SIZE, -+ .phys = WINDOW_ADDR, -+ .buswidth = 4, - }; - - int __init init_mbx(void) - { -- printk(KERN_NOTICE "Motorola MBX flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR); -- mbx_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); -+ printk(KERN_NOTICE "Motorola MBX flash device: 0x%x at 0x%x\n", WINDOW_SIZE*4, WINDOW_ADDR); -+ mbx_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); - -- if (!mbx_map.map_priv_1) { -+ if (!mbx_map.virt) { - printk("Failed to ioremap\n"); - return -EIO; - } -+ simple_map_init(&mbx_map); -+ - mymtd = do_map_probe("jedec_probe", &mbx_map); - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - add_mtd_device(mymtd); - add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS); - return 0; - } - -- iounmap((void *)mbx_map.map_priv_1); -+ iounmap((void *)mbx_map.virt); - return -ENXIO; - } - -@@ -130,9 +86,9 @@ - del_mtd_device(mymtd); - map_destroy(mymtd); - } -- if (mbx_map.map_priv_1) { -- iounmap((void *)mbx_map.map_priv_1); -- mbx_map.map_priv_1 = 0; -+ if (mbx_map.virt) { -+ iounmap((void *)mbx_map.virt); -+ mbx_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/mpc1211.c linux/drivers/mtd/maps/mpc1211.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/mpc1211.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/mpc1211.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,79 @@ -+/* -+ * Flash on MPC-1211 -+ * -+ * (C) 2002 Interface, Saito.K & Jeanne -+ * -+ * GPL'd -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static struct mtd_info *flash_mtd; -+static struct mtd_partition *parsed_parts; -+ -+struct map_info mpc1211_flash_map = { -+ .name = "MPC-1211 FLASH", -+ .size = 0x80000, -+ .buswidth = 1, -+}; -+ -+static struct mtd_partition mpc1211_partitions[] = { -+ { -+ .name = "IPL & ETH-BOOT", -+ .offset = 0x00000000, -+ .size = 0x10000, -+ }, -+ { -+ .name = "Flash FS", -+ .offset = 0x00010000, -+ .size = MTDPART_SIZ_FULL, -+ } -+}; -+ -+static int __init init_mpc1211_maps(void) -+{ -+ int nr_parts; -+ -+ mpc1211_flash_map.phys = 0; -+ mpc1211_flash_map.virt = P2SEGADDR(0); -+ -+ simple_map_init(&mpc1211_flash_map); -+ -+ printk(KERN_NOTICE "Probing for flash chips at 0x00000000:\n"); -+ flash_mtd = do_map_probe("jedec_probe", &mpc1211_flash_map); -+ if (!flash_mtd) { -+ printk(KERN_NOTICE "Flash chips not detected at either possible location.\n"); -+ return -ENXIO; -+ } -+ printk(KERN_NOTICE "MPC-1211: Flash at 0x%08lx\n", mpc1211_flash_map.virt & 0x1fffffff); -+ flash_mtd->module = THIS_MODULE; -+ -+ parsed_parts = mpc1211_partitions; -+ nr_parts = ARRAY_SIZE(mpc1211_partitions); -+ -+ add_mtd_partitions(flash_mtd, parsed_parts, nr_parts); -+ return 0; -+} -+ -+static void __exit cleanup_mpc1211_maps(void) -+{ -+ if (parsed_parts) -+ del_mtd_partitions(flash_mtd); -+ else -+ del_mtd_device(flash_mtd); -+ map_destroy(flash_mtd); -+} -+ -+module_init(init_mpc1211_maps); -+module_exit(cleanup_mpc1211_maps); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Saito.K & Jeanne "); -+MODULE_DESCRIPTION("MTD map driver for MPC-1211 boards. Interface"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/netsc520.c linux/drivers/mtd/maps/netsc520.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/netsc520.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/netsc520.c 2004-11-17 18:17:59.113302672 +0100 -@@ -3,7 +3,7 @@ - * Copyright (C) 2001 Mark Langsdorf (mark.langsdorf@amd.com) - * based on sc520cdp.c by Sysgo Real-Time Solutions GmbH - * -- * $Id$ -+ * $Id$ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -50,95 +51,41 @@ - ** recoverable afterwards. - */ - --static __u8 netsc520_read8(struct map_info *map, unsigned long ofs) --{ -- return readb(map->map_priv_1 + ofs); --} -- --static __u16 netsc520_read16(struct map_info *map, unsigned long ofs) --{ -- return readw(map->map_priv_1 + ofs); --} -- --static __u32 netsc520_read32(struct map_info *map, unsigned long ofs) --{ -- return readl(map->map_priv_1 + ofs); --} -- --static void netsc520_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); --} -- --static void netsc520_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, map->map_priv_1 + adr); --} -- --static void netsc520_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, map->map_priv_1 + adr); --} -- --static void netsc520_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- writel(d, map->map_priv_1 + adr); --} -- --static void netsc520_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio((void *)(map->map_priv_1 + to), from, len); --} -- - /* partition_info gives details on the logical partitions that the split the - * single flash device into. If the size if zero we use up to the end of the - * device. */ - static struct mtd_partition partition_info[]={ - { -- name: "NetSc520 boot kernel", -- offset: 0, -- size: 0xc0000 -+ .name = "NetSc520 boot kernel", -+ .offset = 0, -+ .size = 0xc0000 - }, - { -- name: "NetSc520 Low BIOS", -- offset: 0xc0000, -- size: 0x40000 -+ .name = "NetSc520 Low BIOS", -+ .offset = 0xc0000, -+ .size = 0x40000 - }, - { -- name: "NetSc520 file system", -- offset: 0x100000, -- size: 0xe80000 -+ .name = "NetSc520 file system", -+ .offset = 0x100000, -+ .size = 0xe80000 - }, - { -- name: "NetSc520 High BIOS", -- offset: 0xf80000, -- size: 0x80000 -+ .name = "NetSc520 High BIOS", -+ .offset = 0xf80000, -+ .size = 0x80000 - }, - }; - #define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0])) - --/* -- * If no idea what is going on here. This is taken from the FlashFX stuff. -- */ --#define ROMCS 1 -- -- - #define WINDOW_SIZE 0x00100000 - #define WINDOW_ADDR 0x00200000 - - static struct map_info netsc520_map = { -- name: "netsc520 Flash Bank", -- size: WINDOW_SIZE, -- buswidth: 4, -- read8: netsc520_read8, -- read16: netsc520_read16, -- read32: netsc520_read32, -- copy_from: netsc520_copy_from, -- write8: netsc520_write8, -- write16: netsc520_write16, -- write32: netsc520_write32, -- copy_to: netsc520_copy_to, -- map_priv_2: WINDOW_ADDR -+ .name = "netsc520 Flash Bank", -+ .size = WINDOW_SIZE, -+ .buswidth = 4, -+ .phys = WINDOW_ADDR, - }; - - #define NUM_FLASH_BANKS (sizeof(netsc520_map)/sizeof(struct map_info)) -@@ -147,13 +94,16 @@ - - static int __init init_netsc520(void) - { -- printk(KERN_NOTICE "NetSc520 flash device: %lx at %lx\n", netsc520_map.size, netsc520_map.map_priv_2); -- netsc520_map.map_priv_1 = (unsigned long)ioremap_nocache(netsc520_map.map_priv_2, netsc520_map.size); -+ printk(KERN_NOTICE "NetSc520 flash device: 0x%lx at 0x%lx\n", netsc520_map.size, netsc520_map.phys); -+ netsc520_map.virt = (unsigned long)ioremap_nocache(netsc520_map.phys, netsc520_map.size); - -- if (!netsc520_map.map_priv_1) { -+ if (!netsc520_map.virt) { - printk("Failed to ioremap_nocache\n"); - return -EIO; - } -+ -+ simple_map_init(&netsc520_map); -+ - mymtd = do_map_probe("cfi_probe", &netsc520_map); - if(!mymtd) - mymtd = do_map_probe("map_ram", &netsc520_map); -@@ -161,11 +111,11 @@ - mymtd = do_map_probe("map_rom", &netsc520_map); - - if (!mymtd) { -- iounmap((void *)netsc520_map.map_priv_1); -+ iounmap((void *)netsc520_map.virt); - return -ENXIO; - } - -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - add_mtd_partitions( mymtd, partition_info, NUM_PARTITIONS ); - return 0; - } -@@ -176,9 +126,9 @@ - del_mtd_partitions(mymtd); - map_destroy(mymtd); - } -- if (netsc520_map.map_priv_1) { -- iounmap((void *)netsc520_map.map_priv_1); -- netsc520_map.map_priv_1 = 0; -+ if (netsc520_map.virt) { -+ iounmap((void *)netsc520_map.virt); -+ netsc520_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/nettel.c linux/drivers/mtd/maps/nettel.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/nettel.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/nettel.c 2004-11-17 18:17:59.114302520 +0100 -@@ -6,7 +6,7 @@ - * (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com) - * (C) Copyright 2001-2002, SnapGear (www.snapgear.com) - * -- * $Id$ -+ * $Id$ - */ - - /****************************************************************************/ -@@ -59,128 +59,72 @@ - - /****************************************************************************/ - --static __u8 nettel_read8(struct map_info *map, unsigned long ofs) --{ -- return(readb(map->map_priv_1 + ofs)); --} -- --static __u16 nettel_read16(struct map_info *map, unsigned long ofs) --{ -- return(readw(map->map_priv_1 + ofs)); --} -- --static __u32 nettel_read32(struct map_info *map, unsigned long ofs) --{ -- return(readl(map->map_priv_1 + ofs)); --} -- --static void nettel_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --static void nettel_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, map->map_priv_1 + adr); --} -- --static void nettel_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, map->map_priv_1 + adr); --} -- --static void nettel_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- writel(d, map->map_priv_1 + adr); --} -- --static void nettel_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} -- - /****************************************************************************/ - - #ifdef CONFIG_MTD_CFI_INTELEXT - static struct map_info nettel_intel_map = { -- name: "SnapGear Intel", -- size: 0, -- buswidth: INTEL_BUSWIDTH, -- read8: nettel_read8, -- read16: nettel_read16, -- read32: nettel_read32, -- copy_from: nettel_copy_from, -- write8: nettel_write8, -- write16: nettel_write16, -- write32: nettel_write32, -- copy_to: nettel_copy_to -+ .name = "SnapGear Intel", -+ .size = 0, -+ .buswidth = INTEL_BUSWIDTH, - }; - - static struct mtd_partition nettel_intel_partitions[] = { - { -- name: "SnapGear kernel", -- offset: 0, -- size: 0x000e0000 -+ .name = "SnapGear kernel", -+ .offset = 0, -+ .size = 0x000e0000 - }, - { -- name: "SnapGear filesystem", -- offset: 0x00100000, -+ .name = "SnapGear filesystem", -+ .offset = 0x00100000, - }, - { -- name: "SnapGear config", -- offset: 0x000e0000, -- size: 0x00020000 -+ .name = "SnapGear config", -+ .offset = 0x000e0000, -+ .size = 0x00020000 - }, - { -- name: "SnapGear Intel", -- offset: 0 -+ .name = "SnapGear Intel", -+ .offset = 0 - }, - { -- name: "SnapGear BIOS Config", -- offset: 0x007e0000, -- size: 0x00020000 -+ .name = "SnapGear BIOS Config", -+ .offset = 0x007e0000, -+ .size = 0x00020000 - }, - { -- name: "SnapGear BIOS", -- offset: 0x007e0000, -- size: 0x00020000 -+ .name = "SnapGear BIOS", -+ .offset = 0x007e0000, -+ .size = 0x00020000 - }, - }; - #endif - - static struct map_info nettel_amd_map = { -- name: "SnapGear AMD", -- size: AMD_WINDOW_MAXSIZE, -- buswidth: AMD_BUSWIDTH, -- read8: nettel_read8, -- read16: nettel_read16, -- read32: nettel_read32, -- copy_from: nettel_copy_from, -- write8: nettel_write8, -- write16: nettel_write16, -- write32: nettel_write32, -- copy_to: nettel_copy_to -+ .name = "SnapGear AMD", -+ .size = AMD_WINDOW_MAXSIZE, -+ .buswidth = AMD_BUSWIDTH, - }; - - static struct mtd_partition nettel_amd_partitions[] = { - { -- name: "SnapGear BIOS config", -- offset: 0x000e0000, -- size: 0x00010000 -+ .name = "SnapGear BIOS config", -+ .offset = 0x000e0000, -+ .size = 0x00010000 - }, - { -- name: "SnapGear BIOS", -- offset: 0x000f0000, -- size: 0x00010000 -+ .name = "SnapGear BIOS", -+ .offset = 0x000f0000, -+ .size = 0x00010000 - }, - { -- name: "SnapGear AMD", -- offset: 0 -+ .name = "SnapGear AMD", -+ .offset = 0 - }, - { -- name: "SnapGear high BIOS", -- offset: 0x001f0000, -- size: 0x00010000 -+ .name = "SnapGear high BIOS", -+ .offset = 0x001f0000, -+ .size = 0x00010000 - } - }; - -@@ -328,18 +272,20 @@ - *amdpar = SC520_PAR(SC520_PAR_BOOTCS, amdaddr, maxsize); - __asm__ ("wbinvd"); - -- nettel_amd_map.map_priv_1 = (unsigned long) -+ nettel_amd_map.phys = amdaddr; -+ nettel_amd_map.virt = (unsigned long) - ioremap_nocache(amdaddr, maxsize); -- if (!nettel_amd_map.map_priv_1) { -+ if (!nettel_amd_map.virt) { - printk("SNAPGEAR: failed to ioremap() BOOTCS\n"); - return(-EIO); - } -+ simple_map_init(&nettel_amd_map); - - if ((amd_mtd = do_map_probe("jedec_probe", &nettel_amd_map))) { - printk(KERN_NOTICE "SNAPGEAR: AMD flash device size = %dK\n", - amd_mtd->size>>10); - -- amd_mtd->module = THIS_MODULE; -+ amd_mtd->owner = THIS_MODULE; - - /* The high BIOS partition is only present for 2MB units */ - num_amd_partitions = NUM_AMD_PARTITIONS; -@@ -387,8 +333,8 @@ - - /* Destroy useless AMD MTD mapping */ - amd_mtd = NULL; -- iounmap((void *) nettel_amd_map.map_priv_1); -- nettel_amd_map.map_priv_1 = (unsigned long) NULL; -+ iounmap((void *) nettel_amd_map.virt); -+ nettel_amd_map.virt = (unsigned long) NULL; - #else - /* Only AMD flash supported */ - return(-ENXIO); -@@ -411,16 +357,18 @@ - - /* Probe for the the size of the first Intel flash */ - nettel_intel_map.size = maxsize; -- nettel_intel_map.map_priv_1 = (unsigned long) -+ nettel_intel_map.phys = intel0addr; -+ nettel_intel_map.virt = (unsigned long) - ioremap_nocache(intel0addr, maxsize); -- if (!nettel_intel_map.map_priv_1) { -+ if (!nettel_intel_map.virt) { - printk("SNAPGEAR: failed to ioremap() ROMCS1\n"); - return(-EIO); - } -+ simple_map_init(&nettel_intel_map); - - intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); - if (! intel_mtd) { -- iounmap((void *) nettel_intel_map.map_priv_1); -+ iounmap((void *) nettel_intel_map.virt); - return(-ENXIO); - } - -@@ -441,19 +389,19 @@ - /* Delete the old map and probe again to do both chips */ - map_destroy(intel_mtd); - intel_mtd = NULL; -- iounmap((void *) nettel_intel_map.map_priv_1); -+ iounmap((void *) nettel_intel_map.virt); - - nettel_intel_map.size = maxsize; -- nettel_intel_map.map_priv_1 = (unsigned long) -+ nettel_intel_map.virt = (unsigned long) - ioremap_nocache(intel0addr, maxsize); -- if (!nettel_intel_map.map_priv_1) { -+ if (!nettel_intel_map.virt) { - printk("SNAPGEAR: failed to ioremap() ROMCS1/2\n"); - return(-EIO); - } - - intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); - if (! intel_mtd) { -- iounmap((void *) nettel_intel_map.map_priv_1); -+ iounmap((void *) nettel_intel_map.virt); - return(-ENXIO); - } - -@@ -468,7 +416,7 @@ - printk(KERN_NOTICE "SNAPGEAR: Intel flash device size = %dK\n", - (intel_mtd->size >> 10)); - -- intel_mtd->module = THIS_MODULE; -+ intel_mtd->owner = THIS_MODULE; - - #ifndef CONFIG_BLK_DEV_INITRD - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 1); -@@ -523,18 +471,18 @@ - del_mtd_partitions(amd_mtd); - map_destroy(amd_mtd); - } -- if (nettel_amd_map.map_priv_1) { -- iounmap((void *)nettel_amd_map.map_priv_1); -- nettel_amd_map.map_priv_1 = 0; -+ if (nettel_amd_map.virt) { -+ iounmap((void *)nettel_amd_map.virt); -+ nettel_amd_map.virt = 0; - } - #ifdef CONFIG_MTD_CFI_INTELEXT - if (intel_mtd) { - del_mtd_partitions(intel_mtd); - map_destroy(intel_mtd); - } -- if (nettel_intel_map.map_priv_1) { -- iounmap((void *)nettel_intel_map.map_priv_1); -- nettel_intel_map.map_priv_1 = 0; -+ if (nettel_intel_map.virt) { -+ iounmap((void *)nettel_intel_map.virt); -+ nettel_intel_map.virt = 0; - } - #endif - } -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/ocelot.c linux/drivers/mtd/maps/ocelot.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/ocelot.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/ocelot.c 2004-11-17 18:17:59.115302368 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Flash on Momenco Ocelot - */ -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -20,47 +21,23 @@ - #define NVRAM_WINDOW_SIZE 0x00007FF0 - #define NVRAM_BUSWIDTH 1 - --extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts); -- - static unsigned int cacheflush = 0; - - static struct mtd_info *flash_mtd; - static struct mtd_info *nvram_mtd; - --__u8 ocelot_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --void ocelot_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- cacheflush = 1; -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void ocelot_copy_from_cache(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- if (cacheflush) { -- dma_cache_inv(map->map_priv_2, map->size); -- cacheflush = 0; -- } -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void ocelot_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -+static void ocelot_ram_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) - { -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -+ struct map_info *map = (struct map_info *)mtd->priv; -+ size_t done = 0; - --void ocelot_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ - /* If we use memcpy, it does word-wide writes. Even though we told the - GT64120A that it's an 8-bit wide region, word-wide writes don't work. - We end up just writing the first byte of the four to all four bytes. - So we have this loop instead */ -+ *retlen = len; - while(len) { -- __raw_writeb(*(unsigned char *) from, map->map_priv_1 + to); -+ __raw_writeb(*(unsigned char *) from, map->virt + to); - from++; - to++; - len--; -@@ -70,24 +47,21 @@ - static struct mtd_partition *parsed_parts; - - struct map_info ocelot_flash_map = { -- name: "Ocelot boot flash", -- size: FLASH_WINDOW_SIZE, -- buswidth: FLASH_BUSWIDTH, -- read8: ocelot_read8, -- copy_from: ocelot_copy_from_cache, -- write8: ocelot_write8, -+ .name = "Ocelot boot flash", -+ .size = FLASH_WINDOW_SIZE, -+ .buswidth = FLASH_BUSWIDTH, -+ .phys = FLASH_WINDOW_ADDR, - }; - - struct map_info ocelot_nvram_map = { -- name: "Ocelot NVRAM", -- size: NVRAM_WINDOW_SIZE, -- buswidth: NVRAM_BUSWIDTH, -- read8: ocelot_read8, -- copy_from: ocelot_copy_from, -- write8: ocelot_write8, -- copy_to: ocelot_copy_to -+ .name = "Ocelot NVRAM", -+ .size = NVRAM_WINDOW_SIZE, -+ .buswidth = NVRAM_BUSWIDTH, -+ .phys = NVRAM_WINDOW_ADDR, - }; - -+static const char *probes[] = { "RedBoot", NULL }; -+ - static int __init init_ocelot_maps(void) - { - void *pld; -@@ -107,12 +81,13 @@ - iounmap(pld); - - /* Now ioremap the NVRAM space */ -- ocelot_nvram_map.map_priv_1 = (unsigned long)ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE); -- if (!ocelot_nvram_map.map_priv_1) { -+ ocelot_nvram_map.virt = (unsigned long)ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE); -+ if (!ocelot_nvram_map.virt) { - printk(KERN_NOTICE "Failed to ioremap Ocelot NVRAM space\n"); - return -EIO; - } -- // ocelot_nvram_map.map_priv_2 = ocelot_nvram_map.map_priv_1; -+ -+ simple_map_init(&ocelot_nvram_map); - - /* And do the RAM probe on it to get an MTD device */ - nvram_mtd = do_map_probe("map_ram", &ocelot_nvram_map); -@@ -120,22 +95,21 @@ - printk("NVRAM probe failed\n"); - goto fail_1; - } -- nvram_mtd->module = THIS_MODULE; -+ nvram_mtd->owner = THIS_MODULE; - nvram_mtd->erasesize = 16; -+ /* Override the write() method */ -+ nvram_mtd->write = ocelot_ram_write; - - /* Now map the flash space */ -- ocelot_flash_map.map_priv_1 = (unsigned long)ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE); -- if (!ocelot_flash_map.map_priv_1) { -+ ocelot_flash_map.virt = (unsigned long)ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE); -+ if (!ocelot_flash_map.virt) { - printk(KERN_NOTICE "Failed to ioremap Ocelot flash space\n"); - goto fail_2; - } - /* Now the cached version */ -- ocelot_flash_map.map_priv_2 = (unsigned long)__ioremap(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE, 0); -+ ocelot_flash_map.cached = (unsigned long)__ioremap(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE, 0); - -- if (!ocelot_flash_map.map_priv_2) { -- /* Doesn't matter if it failed. Just use the uncached version */ -- ocelot_flash_map.map_priv_2 = ocelot_flash_map.map_priv_1; -- } -+ simple_map_init(&ocelot_flash_map); - - /* Only probe for flash if the write jumper is present */ - if (brd_status & 0x40) { -@@ -155,10 +129,10 @@ - - add_mtd_device(nvram_mtd); - -- flash_mtd->module = THIS_MODULE; -- nr_parts = parse_redboot_partitions(flash_mtd, &parsed_parts); -+ flash_mtd->owner = THIS_MODULE; -+ nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0); - -- if (nr_parts) -+ if (nr_parts > 0) - add_mtd_partitions(flash_mtd, parsed_parts, nr_parts); - else - add_mtd_device(flash_mtd); -@@ -166,14 +140,13 @@ - return 0; - - fail3: -- iounmap((void *)ocelot_flash_map.map_priv_1); -- if (ocelot_flash_map.map_priv_2 && -- ocelot_flash_map.map_priv_2 != ocelot_flash_map.map_priv_1) -- iounmap((void *)ocelot_flash_map.map_priv_2); -+ iounmap((void *)ocelot_flash_map.virt); -+ if (ocelot_flash_map.cached) -+ iounmap((void *)ocelot_flash_map.cached); - fail_2: - map_destroy(nvram_mtd); - fail_1: -- iounmap((void *)ocelot_nvram_map.map_priv_1); -+ iounmap((void *)ocelot_nvram_map.virt); - - return -ENXIO; - } -@@ -182,16 +155,16 @@ - { - del_mtd_device(nvram_mtd); - map_destroy(nvram_mtd); -- iounmap((void *)ocelot_nvram_map.map_priv_1); -+ iounmap((void *)ocelot_nvram_map.virt); - - if (parsed_parts) - del_mtd_partitions(flash_mtd); - else - del_mtd_device(flash_mtd); - map_destroy(flash_mtd); -- iounmap((void *)ocelot_flash_map.map_priv_1); -- if (ocelot_flash_map.map_priv_2 != ocelot_flash_map.map_priv_1) -- iounmap((void *)ocelot_flash_map.map_priv_2); -+ iounmap((void *)ocelot_flash_map.virt); -+ if (ocelot_flash_map.cached) -+ iounmap((void *)ocelot_flash_map.cached); - } - - module_init(init_ocelot_maps); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/octagon-5066.c linux/drivers/mtd/maps/octagon-5066.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/octagon-5066.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/octagon-5066.c 2004-11-17 18:17:59.117302064 +0100 -@@ -1,4 +1,4 @@ --// $Id$ -+// $Id$ - /* ###################################################################### - - Octagon 5066 MTD Driver. -@@ -31,6 +31,7 @@ - #include - - #include -+#include - - #define WINDOW_START 0xe8000 - #define WINDOW_LENGTH 0x8000 -@@ -151,32 +152,34 @@ - - static struct map_info oct5066_map[2] = { - { -- name: "Octagon 5066 Socket", -- size: 512 * 1024, -- buswidth: 1, -- read8: oct5066_read8, -- read16: oct5066_read16, -- read32: oct5066_read32, -- copy_from: oct5066_copy_from, -- write8: oct5066_write8, -- write16: oct5066_write16, -- write32: oct5066_write32, -- copy_to: oct5066_copy_to, -- map_priv_1: 1<<6 -+ .name = "Octagon 5066 Socket", -+ .phys = NO_XIP, -+ .size = 512 * 1024, -+ .buswidth = 1, -+ .read8 = oct5066_read8, -+ .read16 = oct5066_read16, -+ .read32 = oct5066_read32, -+ .copy_from = oct5066_copy_from, -+ .write8 = oct5066_write8, -+ .write16 = oct5066_write16, -+ .write32 = oct5066_write32, -+ .copy_to = oct5066_copy_to, -+ .map_priv_1 = 1<<6 - }, - { -- name: "Octagon 5066 Internal Flash", -- size: 2 * 1024 * 1024, -- buswidth: 1, -- read8: oct5066_read8, -- read16: oct5066_read16, -- read32: oct5066_read32, -- copy_from: oct5066_copy_from, -- write8: oct5066_write8, -- write16: oct5066_write16, -- write32: oct5066_write32, -- copy_to: oct5066_copy_to, -- map_priv_1: 2<<6 -+ .name = "Octagon 5066 Internal Flash", -+ .phys = NO_XIP, -+ .size = 2 * 1024 * 1024, -+ .buswidth = 1, -+ .read8 = oct5066_read8, -+ .read16 = oct5066_read16, -+ .read32 = oct5066_read32, -+ .copy_from = oct5066_copy_from, -+ .write8 = oct5066_write8, -+ .write16 = oct5066_write16, -+ .write32 = oct5066_write32, -+ .copy_to = oct5066_copy_to, -+ .map_priv_1 = 2<<6 - } - }; - -@@ -244,6 +247,7 @@ - } - if (OctProbe() != 0) { - printk(KERN_NOTICE "5066: Octagon Probe Failed, is this an Octagon 5066 SBC?\n"); -+ iounmap((void *)iomapadr); - ret = -EAGAIN; - goto out_unmap; - } -@@ -261,7 +265,7 @@ - if (!oct5066_mtd[i]) - oct5066_mtd[i] = do_map_probe("map_rom", &oct5066_map[i]); - if (oct5066_mtd[i]) { -- oct5066_mtd[i]->module = THIS_MODULE; -+ oct5066_mtd[i]->owner = THIS_MODULE; - add_mtd_device(oct5066_mtd[i]); - } - } -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/omap-toto-flash.c linux/drivers/mtd/maps/omap-toto-flash.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/omap-toto-flash.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/omap-toto-flash.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,137 @@ -+/* -+ * NOR Flash memory access on TI Toto board -+ * -+ * jzhang@ti.com (C) 2003 Texas Instruments. -+ * -+ * (C) 2002 MontVista Software, Inc. -+ * -+ * $Id$ -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+ -+#ifndef CONFIG_ARCH_OMAP -+#error This is for OMAP architecture only -+#endif -+ -+//these lines need be moved to a hardware header file -+#define OMAP_TOTO_FLASH_BASE 0xd8000000 -+#define OMAP_TOTO_FLASH_SIZE 0x80000 -+ -+static struct map_info omap_toto_map_flash = { -+ .name = "OMAP Toto flash", -+ .buswidth = 2, -+ .virt = OMAP_TOTO_FLASH_BASE, -+}; -+ -+ -+static struct mtd_partition toto_flash_partitions[] = { -+ { -+ .name = "BootLoader", -+ .size = 0x00040000, /* hopefully u-boot will stay 128k + 128*/ -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "ReservedSpace", -+ .size = 0x00030000, -+ .offset = MTDPART_OFS_APPEND, -+ //mask_flags: MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "EnvArea", /* bottom 64KiB for env vars */ -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, -+ } -+}; -+ -+static struct mtd_partition *parsed_parts; -+ -+static struct mtd_info *flash_mtd; -+ -+static int __init init_flash (void) -+{ -+ -+ struct mtd_partition *parts; -+ int nb_parts = 0; -+ int parsed_nr_parts = 0; -+ const char *part_type; -+ -+ /* -+ * Static partition definition selection -+ */ -+ part_type = "static"; -+ -+ parts = toto_flash_partitions; -+ nb_parts = ARRAY_SIZE(toto_flash_partitions); -+ omap_toto_map_flash.size = OMAP_TOTO_FLASH_SIZE; -+ omap_toto_map_flash.phys = virt_to_phys(OMAP_TOTO_FLASH_BASE); -+ -+ simple_map_init(&omap_toto_map_flash); -+ /* -+ * Now let's probe for the actual flash. Do it here since -+ * specific machine settings might have been set above. -+ */ -+ printk(KERN_NOTICE "OMAP toto flash: probing %d-bit flash bus\n", -+ omap_toto_map_flash.buswidth*8); -+ flash_mtd = do_map_probe("jedec_probe", &omap_toto_map_flash); -+ if (!flash_mtd) -+ return -ENXIO; -+ -+ if (parsed_nr_parts > 0) { -+ parts = parsed_parts; -+ nb_parts = parsed_nr_parts; -+ } -+ -+ if (nb_parts == 0) { -+ printk(KERN_NOTICE "OMAP toto flash: no partition info available," -+ "registering whole flash at once\n"); -+ if (add_mtd_device(flash_mtd)){ -+ return -ENXIO; -+ } -+ } else { -+ printk(KERN_NOTICE "Using %s partition definition\n", -+ part_type); -+ return add_mtd_partitions(flash_mtd, parts, nb_parts); -+ } -+ return 0; -+} -+ -+int __init omap_toto_mtd_init(void) -+{ -+ int status; -+ -+ if (status = init_flash()) { -+ printk(KERN_ERR "OMAP Toto Flash: unable to init map for toto flash\n"); -+ } -+ return status; -+} -+ -+static void __exit omap_toto_mtd_cleanup(void) -+{ -+ if (flash_mtd) { -+ del_mtd_partitions(flash_mtd); -+ map_destroy(flash_mtd); -+ if (parsed_parts) -+ kfree(parsed_parts); -+ } -+} -+ -+module_init(omap_toto_mtd_init); -+module_exit(omap_toto_mtd_cleanup); -+ -+MODULE_AUTHOR("Jian Zhang"); -+MODULE_DESCRIPTION("OMAP Toto board map driver"); -+MODULE_LICENSE("GPL"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/pb1xxx-flash.c linux/drivers/mtd/maps/pb1xxx-flash.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/pb1xxx-flash.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/pb1xxx-flash.c 2004-11-17 18:17:59.119301760 +0100 -@@ -3,12 +3,13 @@ - * - * (C) 2001 Pete Popov - * -- * $Id$ -+ * $Id$ - */ - - #include - #include - #include -+#include - #include - - #include -@@ -25,210 +26,110 @@ - #endif - - #ifdef CONFIG_MIPS_PB1000 -+ - #define WINDOW_ADDR 0x1F800000 - #define WINDOW_SIZE 0x800000 --#endif -- --__u8 physmap_read8(struct map_info *map, unsigned long ofs) --{ -- __u8 ret; -- ret = __raw_readb(map->map_priv_1 + ofs); -- DBG("read8 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --__u16 physmap_read16(struct map_info *map, unsigned long ofs) --{ -- __u16 ret; -- ret = __raw_readw(map->map_priv_1 + ofs); -- DBG("read16 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --__u32 physmap_read32(struct map_info *map, unsigned long ofs) --{ -- __u32 ret; -- ret = __raw_readl(map->map_priv_1 + ofs); -- DBG("read32 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- DBG("physmap_copy from %x to %x\n", (unsigned)from, (unsigned)to); -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void physmap_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- DBG("write8 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- DBG("write16 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- DBG("write32 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- DBG("physmap_copy_to %x from %x\n", (unsigned)to, (unsigned)from); -- memcpy_toio(map->map_priv_1 + to, from, len); --} -- -- -- --static struct map_info pb1xxx_map = { -- name: "Pb1xxx flash", -- read8: physmap_read8, -- read16: physmap_read16, -- read32: physmap_read32, -- copy_from: physmap_copy_from, -- write8: physmap_write8, -- write16: physmap_write16, -- write32: physmap_write32, -- copy_to: physmap_copy_to, --}; - -- --#ifdef CONFIG_MIPS_PB1000 -- --static unsigned long flash_size = 0x00800000; --static unsigned char flash_buswidth = 4; - static struct mtd_partition pb1xxx_partitions[] = { - { -- name: "yamon env", -- size: 0x00020000, -- offset: 0, -- mask_flags: MTD_WRITEABLE -- },{ -- name: "User FS", -- size: 0x003e0000, -- offset: 0x20000, -- },{ -- name: "boot code", -- size: 0x100000, -- offset: 0x400000, -- mask_flags: MTD_WRITEABLE -- },{ -- name: "raw/kernel", -- size: 0x300000, -- offset: 0x500000 -- } -+ .name = "yamon env", -+ .size = 0x00020000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE}, -+ { -+ .name = "User FS", -+ .size = 0x003e0000, -+ .offset = 0x20000,}, -+ { -+ .name = "boot code", -+ .size = 0x100000, -+ .offset = 0x400000, -+ .mask_flags = MTD_WRITEABLE}, -+ { -+ .name = "raw/kernel", -+ .size = 0x300000, -+ .offset = 0x500000} - }; - - #elif defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) - --static unsigned char flash_buswidth = 4; - #if defined(CONFIG_MTD_PB1500_BOOT) && defined(CONFIG_MTD_PB1500_USER) --/* both 32MiB banks will be used. Combine the first 32MiB bank and the -- * first 28MiB of the second bank together into a single jffs/jffs2 -+/* both 32MB banks will be used. Combine the first 32MB bank and the -+ * first 28MB of the second bank together into a single jffs/jffs2 - * partition. - */ --static unsigned long flash_size = 0x04000000; - #define WINDOW_ADDR 0x1C000000 - #define WINDOW_SIZE 0x4000000 - static struct mtd_partition pb1xxx_partitions[] = { - { -- name: "User FS", -- size: 0x3c00000, -- offset: 0x0000000 -- },{ -- name: "yamon", -- size: 0x0100000, -- offset: 0x3c00000, -- mask_flags: MTD_WRITEABLE -- },{ -- name: "raw kernel", -- size: 0x02c0000, -- offset: 0x3d00000 -+ .name = "User FS", -+ .size = 0x3c00000, -+ .offset = 0x0000000 -+ },{ -+ .name = "yamon", -+ .size = 0x0100000, -+ .offset = 0x3c00000, -+ .mask_flags = MTD_WRITEABLE -+ },{ -+ .name = "raw kernel", -+ .size = 0x02c0000, -+ .offset = 0x3d00000 - } - }; - #elif defined(CONFIG_MTD_PB1500_BOOT) && !defined(CONFIG_MTD_PB1500_USER) --static unsigned long flash_size = 0x02000000; - #define WINDOW_ADDR 0x1E000000 - #define WINDOW_SIZE 0x2000000 - static struct mtd_partition pb1xxx_partitions[] = { - { -- name: "User FS", -- size: 0x1c00000, -- offset: 0x0000000 -- },{ -- name: "yamon", -- size: 0x0100000, -- offset: 0x1c00000, -- mask_flags: MTD_WRITEABLE -- },{ -- name: "raw kernel", -- size: 0x02c0000, -- offset: 0x1d00000 -+ .name = "User FS", -+ .size = 0x1c00000, -+ .offset = 0x0000000 -+ },{ -+ .name = "yamon", -+ .size = 0x0100000, -+ .offset = 0x1c00000, -+ .mask_flags = MTD_WRITEABLE -+ },{ -+ .name = "raw kernel", -+ .size = 0x02c0000, -+ .offset = 0x1d00000 - } - }; - #elif !defined(CONFIG_MTD_PB1500_BOOT) && defined(CONFIG_MTD_PB1500_USER) --static unsigned long flash_size = 0x02000000; - #define WINDOW_ADDR 0x1C000000 - #define WINDOW_SIZE 0x2000000 - static struct mtd_partition pb1xxx_partitions[] = { - { -- name: "User FS", -- size: 0x1e00000, -- offset: 0x0000000 -- },{ -- name: "raw kernel", -- size: 0x0200000, -- offset: 0x1e00000, -+ .name = "User FS", -+ .size = 0x1e00000, -+ .offset = 0x0000000 -+ },{ -+ .name = "raw kernel", -+ .size = 0x0200000, -+ .offset = 0x1e00000, - } - }; - #else - #error MTD_PB1500 define combo error /* should never happen */ - #endif --#elif defined(CONFIG_MTD_BOSPORUS) --static unsigned char flash_buswidth = 2; --static unsigned long flash_size = 0x02000000; --#define WINDOW_ADDR 0x1F000000 --#define WINDOW_SIZE 0x2000000 --static struct mtd_partition pb1xxx_partitions[] = { -- { -- name: "User FS", -- size: 0x00400000, -- offset: 0x00000000, -- },{ -- name: "Yamon-2", -- size: 0x00100000, -- offset: 0x00400000, -- },{ -- name: "Root FS", -- size: 0x00700000, -- offset: 0x00500000, -- },{ -- name: "Yamon-1", -- size: 0x00100000, -- offset: 0x00C00000, -- },{ -- name: "Kernel", -- size: 0x00300000, -- offset: 0x00D00000, -- } --}; - #else - #error Unsupported board - #endif - -+#define NAME "Pb1x00 Linux Flash" -+#define PADDR WINDOW_ADDR -+#define BUSWIDTH 4 -+#define SIZE WINDOW_SIZE -+#define PARTITIONS 4 -+ -+static struct map_info pb1xxx_mtd_map = { -+ .name = NAME, -+ .size = SIZE, -+ .buswidth = BUSWIDTH, -+ .phys = PADDR, -+}; - --#define NB_OF(x) (sizeof(x)/sizeof(x[0])) -- --static struct mtd_partition *parsed_parts; --static struct mtd_info *mymtd; -+static struct mtd_info *pb1xxx_mtd; - - int __init pb1xxx_mtd_init(void) - { -@@ -236,40 +137,37 @@ - int nb_parts = 0; - char *part_type; - -- /* Default flash buswidth */ -- pb1xxx_map.buswidth = flash_buswidth; -- - /* - * Static partition definition selection - */ - part_type = "static"; - parts = pb1xxx_partitions; -- nb_parts = NB_OF(pb1xxx_partitions); -- pb1xxx_map.size = flash_size; -+ nb_parts = ARRAY_SIZE(pb1xxx_partitions); - - /* - * Now let's probe for the actual flash. Do it here since - * specific machine settings might have been set above. - */ - printk(KERN_NOTICE "Pb1xxx flash: probing %d-bit flash bus\n", -- pb1xxx_map.buswidth*8); -- pb1xxx_map.map_priv_1 = -- (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); -- mymtd = do_map_probe("cfi_probe", &pb1xxx_map); -- if (!mymtd) return -ENXIO; -- mymtd->module = THIS_MODULE; -+ BUSWIDTH*8); -+ pb1xxx_mtd_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); -+ -+ simple_map_init(&pb1xxx_mtd_map); -+ -+ pb1xxx_mtd = do_map_probe("cfi_probe", &pb1xxx_mtd_map); -+ if (!pb1xxx_mtd) return -ENXIO; -+ pb1xxx_mtd->owner = THIS_MODULE; - -- add_mtd_partitions(mymtd, parts, nb_parts); -+ add_mtd_partitions(pb1xxx_mtd, parts, nb_parts); - return 0; - } - - static void __exit pb1xxx_mtd_cleanup(void) - { -- if (mymtd) { -- del_mtd_partitions(mymtd); -- map_destroy(mymtd); -- if (parsed_parts) -- kfree(parsed_parts); -+ if (pb1xxx_mtd) { -+ del_mtd_partitions(pb1xxx_mtd); -+ map_destroy(pb1xxx_mtd); -+ iounmap((void *) pb1xxx_mtd_map.virt); - } - } - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/pci.c linux/drivers/mtd/maps/pci.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/pci.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/pci.c 2004-11-17 18:17:59.121301456 +0100 -@@ -7,7 +7,7 @@ - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * -- * $Id$ -+ * $Id$ - * - * Generic PCI memory map driver. We support the following boards: - * - Intel IQ80310 ATU. -@@ -98,10 +98,10 @@ - } - - static struct mtd_pci_info intel_iq80310_info = { -- init: intel_iq80310_init, -- exit: intel_iq80310_exit, -- translate: intel_iq80310_translate, -- map_name: "cfi_probe", -+ .init = intel_iq80310_init, -+ .exit = intel_iq80310_exit, -+ .translate = intel_iq80310_translate, -+ .map_name = "cfi_probe", - }; - - /* -@@ -181,10 +181,10 @@ - } - - static struct mtd_pci_info intel_dc21285_info = { -- init: intel_dc21285_init, -- exit: intel_dc21285_exit, -- translate: intel_dc21285_translate, -- map_name: "jedec_probe", -+ .init = intel_dc21285_init, -+ .exit = intel_dc21285_exit, -+ .translate = intel_dc21285_translate, -+ .map_name = "jedec_probe", - }; - - /* -@@ -193,22 +193,20 @@ - - static struct pci_device_id mtd_pci_ids[] __devinitdata = { - { -- vendor: PCI_VENDOR_ID_INTEL, -- device: 0x530d, -- subvendor: PCI_ANY_ID, -- subdevice: PCI_ANY_ID, -- class: PCI_CLASS_MEMORY_OTHER << 8, -- class_mask: 0xffff00, -- driver_data: (unsigned long)&intel_iq80310_info, -+ .vendor = PCI_VENDOR_ID_INTEL, -+ .device = 0x530d, -+ .subvendor = PCI_ANY_ID, -+ .subdevice = PCI_ANY_ID, -+ .class = PCI_CLASS_MEMORY_OTHER << 8, -+ .class_mask = 0xffff00, -+ .driver_data = (unsigned long)&intel_iq80310_info, - }, - { -- vendor: PCI_VENDOR_ID_DEC, -- device: PCI_DEVICE_ID_DEC_21285, -- subvendor: 0, /* DC21285 defaults to 0 on reset */ -- subdevice: 0, /* DC21285 defaults to 0 on reset */ -- class: 0, -- class_mask: 0, -- driver_data: (unsigned long)&intel_dc21285_info, -+ .vendor = PCI_VENDOR_ID_DEC, -+ .device = PCI_DEVICE_ID_DEC_21285, -+ .subvendor = 0, /* DC21285 defaults to 0 on reset */ -+ .subdevice = 0, /* DC21285 defaults to 0 on reset */ -+ .driver_data = (unsigned long)&intel_dc21285_info, - }, - { 0, } - }; -@@ -275,14 +273,15 @@ - } - - static struct map_info mtd_pci_map = { -- read8: mtd_pci_read8, -- read16: mtd_pci_read16, -- read32: mtd_pci_read32, -- copy_from: mtd_pci_copyfrom, -- write8: mtd_pci_write8, -- write16: mtd_pci_write16, -- write32: mtd_pci_write32, -- copy_to: mtd_pci_copyto, -+ .phys = NO_XIP, -+ .read8 = mtd_pci_read8, -+ .read16 = mtd_pci_read16, -+ .read32 = mtd_pci_read32, -+ .copy_from = mtd_pci_copyfrom, -+ .write8 = mtd_pci_write8, -+ .write16 = mtd_pci_write16, -+ .write32 = mtd_pci_write32, -+ .copy_to = mtd_pci_copyto, - }; - - static int __devinit -@@ -322,7 +321,7 @@ - if (!mtd) - goto release; - -- mtd->module = THIS_MODULE; -+ mtd->owner = THIS_MODULE; - add_mtd_device(mtd); - - pci_set_drvdata(dev, mtd); -@@ -359,10 +358,10 @@ - } - - static struct pci_driver mtd_pci_driver = { -- name: "MTD PCI", -- probe: mtd_pci_probe, -- remove: __devexit_p(mtd_pci_remove), -- id_table: mtd_pci_ids, -+ .name = "MTD PCI", -+ .probe = mtd_pci_probe, -+ .remove = __devexit_p(mtd_pci_remove), -+ .id_table = mtd_pci_ids, - }; - - static int __init mtd_pci_maps_init(void) -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/pcmciamtd.c linux/drivers/mtd/maps/pcmciamtd.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/pcmciamtd.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/pcmciamtd.c 2004-11-17 18:17:59.122301304 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * pcmciamtd.c - MTD driver for PCMCIA flash memory cards - * -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -24,6 +25,7 @@ - #include - - #include -+#include - - #ifdef CONFIG_MTD_DEBUG - static int debug = CONFIG_MTD_DEBUG_VERBOSE; -@@ -47,7 +49,7 @@ - - - #define DRIVER_DESC "PCMCIA Flash memory card driver" --#define DRIVER_VERSION "$Revision$" -+#define DRIVER_VERSION "$Revision$" - - /* Size of the PCMCIA address space: 26 bits = 64 MB */ - #define MAX_PCMCIA_ADDR 0x4000000 -@@ -96,7 +98,7 @@ - MODULE_PARM(mem_speed, "i"); - MODULE_PARM_DESC(mem_speed, "Set memory access speed in ns"); - MODULE_PARM(force_size, "i"); --MODULE_PARM_DESC(force_size, "Force size of card in MB (1-64)"); -+MODULE_PARM_DESC(force_size, "Force size of card in MiB (1-64)"); - MODULE_PARM(setvpp, "i"); - MODULE_PARM_DESC(setvpp, "Set Vpp (0=Never, 1=On writes, 2=Always on, default=0)"); - MODULE_PARM(vpp, "i"); -@@ -106,11 +108,13 @@ - - - -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69) - static inline void cs_error(client_handle_t handle, int func, int ret) - { - error_info_t err = { func, ret }; - CardServices(ReportError, handle, &err); - } -+#endif - - - /* read/write{8,16} copy_{from,to} routines with window remapping to access whole card */ -@@ -529,6 +533,7 @@ - - card_settings(dev, link, &new_name); - -+ dev->pcmcia_map.phys = NO_XIP; - dev->pcmcia_map.read8 = pcmcia_read8_remap; - dev->pcmcia_map.read16 = pcmcia_read16_remap; - dev->pcmcia_map.copy_from = pcmcia_copy_from_remap; -@@ -539,7 +544,7 @@ - dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp; - - /* Request a memory window for PCMCIA. Some architeures can map windows upto the maximum -- that PCMCIA can support (64Mb) - this is ideal and we aim for a window the size of the -+ that PCMCIA can support (64MiB) - this is ideal and we aim for a window the size of the - whole card - otherwise we try smaller windows until we succeed */ - - req.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE; -@@ -552,7 +557,7 @@ - - do { - int ret; -- DEBUG(2, "requesting window with size = %dKB memspeed = %d", -+ DEBUG(2, "requesting window with size = %dKiB memspeed = %d", - req.Size >> 10, req.AccessSpeed); - link->win = (window_handle_t)link->handle; - ret = CardServices(RequestWindow, &link->win, &req); -@@ -560,7 +565,7 @@ - if(ret) { - req.Size >>= 1; - } else { -- DEBUG(2, "Got window of size %dKB", req.Size >> 10); -+ DEBUG(2, "Got window of size %dKiB", req.Size >> 10); - dev->win_size = req.Size; - break; - } -@@ -573,7 +578,7 @@ - pcmciamtd_release((u_long)link); - return; - } -- DEBUG(1, "Allocated a window of %dKB", dev->win_size >> 10); -+ DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10); - - /* Get write protect status */ - CS_CHECK(GetStatus, link->handle, &status); -@@ -642,21 +647,21 @@ - } - - dev->mtd_info = mtd; -- mtd->module = THIS_MODULE; -+ mtd->owner = THIS_MODULE; - - if(new_name) { - int size = 0; - char unit = ' '; - /* Since we are using a default name, make it better by adding in the - size */ -- if(mtd->size < 1048576) { /* <1MB in size, show size in K */ -+ if(mtd->size < 1048576) { /* <1MiB in size, show size in KiB */ - size = mtd->size >> 10; - unit = 'K'; - } else { - size = mtd->size >> 20; - unit = 'M'; - } -- snprintf(dev->mtd_name, sizeof(dev->mtd_name), "%d%cB %s", size, unit, "PCMCIA Memory card"); -+ snprintf(dev->mtd_name, sizeof(dev->mtd_name), "%d%ciB %s", size, unit, "PCMCIA Memory card"); - } - - /* If the memory found is fits completely into the mapped PCMCIA window, -@@ -828,16 +833,20 @@ - } - - -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,68) -+static struct pcmcia_driver pcmciamtd_driver = { -+ .drv = { -+ .name = "pcmciamtd" -+ }, -+ .attach = pcmciamtd_attach, -+ .detach = pcmciamtd_detach, -+ .owner = THIS_MODULE -+}; -+#endif -+ -+ - static int __init init_pcmciamtd(void) - { -- servinfo_t serv; -- -- info(DRIVER_DESC " " DRIVER_VERSION); -- CardServices(GetCardServicesInfo, &serv); -- if (serv.Revision != CS_RELEASE_CODE) { -- err("Card Services release does not match!"); -- return -1; -- } - - if(buswidth && buswidth != 1 && buswidth != 2) { - info("bad buswidth (%d), using default", buswidth); -@@ -851,15 +860,24 @@ - info("bad mem_type (%d), using default", mem_type); - mem_type = 0; - } -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,68) -+ return pcmcia_register_driver(&pcmciamtd_driver); -+#else - register_pccard_driver(&dev_info, &pcmciamtd_attach, &pcmciamtd_detach); - return 0; -+#endif - } - - - static void __exit exit_pcmciamtd(void) - { - DEBUG(1, DRIVER_DESC " unloading"); -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,68) -+ pcmcia_unregister_driver(&pcmciamtd_driver); -+#else - unregister_pccard_driver(&dev_info); -+#endif - - while(dev_list) { - dev_link_t *link = dev_list; -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/physmap.c linux/drivers/mtd/maps/physmap.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/physmap.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/physmap.c 2004-11-17 18:17:59.124301000 +0100 -@@ -1,179 +1,114 @@ - /* -- * $Id$ -+ * $Id$ - * - * Normal mappings of chips in physical memory -+ * -+ * Copyright (C) 2003 MontaVista Software Inc. -+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net -+ * -+ * 031022 - [jsun] add run-time configure and partition setup - */ - - #include - #include - #include -+#include -+#include - #include - #include - #include - #include -- --#ifdef CONFIG_MTD_PARTITIONS - #include --#endif -- --#define WINDOW_ADDR CONFIG_MTD_PHYSMAP_START --#define WINDOW_SIZE CONFIG_MTD_PHYSMAP_LEN --#define BUSWIDTH CONFIG_MTD_PHYSMAP_BUSWIDTH - - static struct mtd_info *mymtd; - --__u8 physmap_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 physmap_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 physmap_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -+struct map_info physmap_map = {.name = "phys_mapped_flash"}; - --void physmap_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -+#ifdef CONFIG_MTD_PARTITIONS -+static struct mtd_partition *mtd_parts; -+static int mtd_parts_nb; - --void physmap_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -+static int num_physmap_partitions; -+static struct mtd_partition *physmap_partitions; - --void physmap_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -+char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL}; - --void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -+void physmap_set_partitions(struct mtd_partition *parts, int num_parts) - { -- memcpy_toio(map->map_priv_1 + to, from, len); -+ physmap_partitions=parts; -+ num_physmap_partitions=num_parts; - } -- --struct map_info physmap_map = { -- name: "Physically mapped flash", -- size: WINDOW_SIZE, -- buswidth: BUSWIDTH, -- read8: physmap_read8, -- read16: physmap_read16, -- read32: physmap_read32, -- copy_from: physmap_copy_from, -- write8: physmap_write8, -- write16: physmap_write16, -- write32: physmap_write32, -- copy_to: physmap_copy_to --}; -- --#ifdef CONFIG_MTD_PARTITIONS --#ifdef CONFIG_MTD_CMDLINE_PARTS --static struct mtd_partition *mtd_parts = 0; --static int mtd_parts_nb = 0; --#else --static struct mtd_partition physmap_partitions[] = { --/* Put your own partition definitions here */ --#if 0 -- { -- name: "bootROM", -- size: 0x80000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "zImage", -- size: 0x100000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "ramdisk.gz", -- size: 0x300000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "User FS", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -- } --#endif --}; -- --#define NUM_PARTITIONS (sizeof(physmap_partitions)/sizeof(struct mtd_partition)) -- --#endif --#endif -+#endif /* CONFIG_MTD_PARTITIONS */ - - int __init init_physmap(void) - { - static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", 0 }; - const char **type; - -- printk(KERN_NOTICE "physmap flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); -- physmap_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); -+ printk(KERN_NOTICE "physmap flash device: %lx at %lx\n", physmap_map.size, physmap_map.phys); -+ physmap_map.virt = (unsigned long)ioremap(physmap_map.phys, physmap_map.size); - -- if (!physmap_map.map_priv_1) { -+ if (!physmap_map.virt) { - printk("Failed to ioremap\n"); - return -EIO; - } - -+ simple_map_init(&physmap_map); -+ - mymtd = 0; - type = rom_probe_types; - for(; !mymtd && *type; type++) { - mymtd = do_map_probe(*type, &physmap_map); - } - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - -- add_mtd_device(mymtd); - #ifdef CONFIG_MTD_PARTITIONS --#ifdef CONFIG_MTD_CMDLINE_PARTS -- mtd_parts_nb = parse_cmdline_partitions(mymtd, &mtd_parts, -- "phys"); -+ mtd_parts_nb = parse_mtd_partitions(mymtd, part_probes, -+ &mtd_parts, 0); -+ - if (mtd_parts_nb > 0) - { -- printk(KERN_NOTICE -- "Using command line partition definition\n"); - add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb); -+ return 0; - } --#else -- if (NUM_PARTITIONS != 0) -+ -+ if (num_physmap_partitions != 0) - { - printk(KERN_NOTICE - "Using physmap partition definition\n"); -- add_mtd_partitions (mymtd, physmap_partitions, NUM_PARTITIONS); -+ add_mtd_partitions (mymtd, physmap_partitions, num_physmap_partitions); -+ return 0; - } - - #endif --#endif -+ add_mtd_device(mymtd); -+ - return 0; - } - -- iounmap((void *)physmap_map.map_priv_1); -+ iounmap((void *)physmap_map.virt); - return -ENXIO; - } - - static void __exit cleanup_physmap(void) - { -- if (mymtd) { -+#ifdef CONFIG_MTD_PARTITIONS -+ if (mtd_parts_nb) { -+ del_mtd_partitions(mymtd); -+ kfree(mtd_parts); -+ } else if (num_physmap_partitions) { -+ del_mtd_partitions(mymtd); -+ } else { - del_mtd_device(mymtd); -- map_destroy(mymtd); -- } -- if (physmap_map.map_priv_1) { -- iounmap((void *)physmap_map.map_priv_1); -- physmap_map.map_priv_1 = 0; - } -+#else -+ del_mtd_device(mymtd); -+#endif -+ map_destroy(mymtd); -+ -+ iounmap((void *)physmap_map.virt); -+ physmap_map.virt = 0; - } - - module_init(init_physmap); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/pnc2000.c linux/drivers/mtd/maps/pnc2000.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/pnc2000.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/pnc2000.c 2004-11-17 18:17:59.125300848 +0100 -@@ -5,12 +5,13 @@ - * - * This code is GPL - * -- * $Id$ -+ * $Id$ - */ - - #include - #include - #include -+#include - - #include - #include -@@ -24,58 +25,13 @@ - * MAP DRIVER STUFF - */ - --__u8 pnc_read8(struct map_info *map, unsigned long ofs) --{ -- return *(__u8 *)(WINDOW_ADDR + ofs); --} -- --__u16 pnc_read16(struct map_info *map, unsigned long ofs) --{ -- return *(__u16 *)(WINDOW_ADDR + ofs); --} -- --__u32 pnc_read32(struct map_info *map, unsigned long ofs) --{ -- return *(volatile unsigned int *)(WINDOW_ADDR + ofs); --} -- --void pnc_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy(to, (void *)(WINDOW_ADDR + from), len); --} -- --void pnc_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- *(__u8 *)(WINDOW_ADDR + adr) = d; --} -- --void pnc_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- *(__u16 *)(WINDOW_ADDR + adr) = d; --} -- --void pnc_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- *(__u32 *)(WINDOW_ADDR + adr) = d; --} -- --void pnc_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy((void *)(WINDOW_ADDR + to), from, len); --} - - struct map_info pnc_map = { -- name: "PNC-2000", -- size: WINDOW_SIZE, -- buswidth: 4, -- read8: pnc_read8, -- read16: pnc_read16, -- read32: pnc_read32, -- copy_from: pnc_copy_from, -- write8: pnc_write8, -- write16: pnc_write16, -- write32: pnc_write32, -- copy_to: pnc_copy_to -+ .name = "PNC-2000", -+ .size = WINDOW_SIZE, -+ .buswidth = 4, -+ .phys = 0xFFFFFFFF, -+ .virt = WINDOW_ADDR, - }; - - -@@ -84,19 +40,19 @@ - */ - static struct mtd_partition pnc_partitions[3] = { - { -- name: "PNC-2000 boot firmware", -- size: 0x20000, -- offset: 0 -+ .name = "PNC-2000 boot firmware", -+ .size = 0x20000, -+ .offset = 0 - }, - { -- name: "PNC-2000 kernel", -- size: 0x1a0000, -- offset: 0x20000 -+ .name = "PNC-2000 kernel", -+ .size = 0x1a0000, -+ .offset = 0x20000 - }, - { -- name: "PNC-2000 filesystem", -- size: 0x240000, -- offset: 0x1c0000 -+ .name = "PNC-2000 filesystem", -+ .size = 0x240000, -+ .offset = 0x1c0000 - } - }; - -@@ -110,9 +66,11 @@ - { - printk(KERN_NOTICE "Photron PNC-2000 flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); - -+ simple_map_init(&pnc_map); -+ - mymtd = do_map_probe("cfi_probe", &pnc_map); - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - return add_mtd_partitions(mymtd, pnc_partitions, 3); - } - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/redwood.c linux/drivers/mtd/maps/redwood.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/redwood.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/redwood.c 2004-11-17 18:17:59.126300696 +0100 -@@ -1,38 +1,23 @@ - /* -- * $Id: -+ * $Id$ - * -- * redwood.c - mapper for IBM Redwood-4/5 board. -+ * drivers/mtd/maps/redwood.c - * -- * Copyright 2001 MontaVista Softare Inc. -+ * FLASH map for the IBM Redwood 4/5/6 boards. - * -- * This program is free software; you can redistribute it and/or modify it -- * under the terms of the 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. -- * -- * History: 12/17/2001 - Armin -- * migrated to use do_map_probe -+ * Author: MontaVista Software, Inc. - * -+ * 2001-2003 (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. - */ - -+#include - #include - #include - #include -+#include - - #include - #include -@@ -40,96 +25,102 @@ - - #include - -+#if !defined (CONFIG_REDWOOD_6) -+ - #define WINDOW_ADDR 0xffc00000 - #define WINDOW_SIZE 0x00400000 - --__u8 redwood_flash_read8(struct map_info *map, unsigned long ofs) --{ -- return *(__u8 *)(map->map_priv_1 + ofs); --} -- --__u16 redwood_flash_read16(struct map_info *map, unsigned long ofs) --{ -- return *(__u16 *)(map->map_priv_1 + ofs); --} -- --__u32 redwood_flash_read32(struct map_info *map, unsigned long ofs) --{ -- return *(volatile unsigned int *)(map->map_priv_1 + ofs); --} -- --void redwood_flash_copy_from(struct map_info *map, void *to, -- unsigned long from, ssize_t len) --{ -- memcpy(to, (void *)(map->map_priv_1 + from), len); --} -- --void redwood_flash_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- *(__u8 *)(map->map_priv_1 + adr) = d; --} -- --void redwood_flash_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- *(__u16 *)(map->map_priv_1 + adr) = d; --} -- --void redwood_flash_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- *(__u32 *)(map->map_priv_1 + adr) = d; --} -- --void redwood_flash_copy_to(struct map_info *map, unsigned long to, -- const void *from, ssize_t len) --{ -- memcpy((void *)(map->map_priv_1 + to), from, len); --} -+#define RW_PART0_OF 0 -+#define RW_PART0_SZ 0x10000 -+#define RW_PART1_OF RW_PART0_SZ -+#define RW_PART1_SZ 0x200000 - 0x10000 -+#define RW_PART2_OF 0x200000 -+#define RW_PART2_SZ 0x10000 -+#define RW_PART3_OF 0x210000 -+#define RW_PART3_SZ 0x200000 - (0x10000 + 0x20000) -+#define RW_PART4_OF 0x3e0000 -+#define RW_PART4_SZ 0x20000 - --struct map_info redwood_flash_map = { -- name: "IBM Redwood", -- size: WINDOW_SIZE, -- buswidth: 2, -- read8: redwood_flash_read8, -- read16: redwood_flash_read16, -- read32: redwood_flash_read32, -- copy_from: redwood_flash_copy_from, -- write8: redwood_flash_write8, -- write16: redwood_flash_write16, -- write32: redwood_flash_write32, -- copy_to: redwood_flash_copy_to -+static struct mtd_partition redwood_flash_partitions[] = { -+ { -+ .name = "Redwood OpenBIOS Vital Product Data", -+ .offset = RW_PART0_OF, -+ .size = RW_PART0_SZ, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ -+ }, -+ { -+ .name = "Redwood kernel", -+ .offset = RW_PART1_OF, -+ .size = RW_PART1_SZ -+ }, -+ { -+ .name = "Redwood OpenBIOS non-volatile storage", -+ .offset = RW_PART2_OF, -+ .size = RW_PART2_SZ, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ -+ }, -+ { -+ .name = "Redwood filesystem", -+ .offset = RW_PART3_OF, -+ .size = RW_PART3_SZ -+ }, -+ { -+ .name = "Redwood OpenBIOS", -+ .offset = RW_PART4_OF, -+ .size = RW_PART4_SZ, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ -+ } - }; - -+#else /* CONFIG_REDWOOD_6 */ -+/* FIXME: the window is bigger - armin */ -+#define WINDOW_ADDR 0xff800000 -+#define WINDOW_SIZE 0x00800000 -+ -+#define RW_PART0_OF 0 -+#define RW_PART0_SZ 0x400000 /* 4 MiB data */ -+#define RW_PART1_OF RW_PART0_OF + RW_PART0_SZ -+#define RW_PART1_SZ 0x10000 /* 64K VPD */ -+#define RW_PART2_OF RW_PART1_OF + RW_PART1_SZ -+#define RW_PART2_SZ 0x400000 - (0x10000 + 0x20000) -+#define RW_PART3_OF RW_PART2_OF + RW_PART2_SZ -+#define RW_PART3_SZ 0x20000 - - static struct mtd_partition redwood_flash_partitions[] = { - { -- name: "Redwood OpenBIOS Vital Product Data", -- offset: 0, -- size: 0x10000, -- mask_flags: MTD_WRITEABLE /* force read-only */ -+ .name = "Redwood filesystem", -+ .offset = RW_PART0_OF, -+ .size = RW_PART0_SZ - }, - { -- name: "Redwood kernel", -- offset: 0x10000, -- size: 0x200000 - 0x10000 -+ .name = "Redwood OpenBIOS Vital Product Data", -+ .offset = RW_PART1_OF, -+ .size = RW_PART1_SZ, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ - }, - { -- name: "Redwood OpenBIOS non-volatile storage", -- offset: 0x200000, -- size: 0x10000, -- mask_flags: MTD_WRITEABLE /* force read-only */ -+ .name = "Redwood kernel", -+ .offset = RW_PART2_OF, -+ .size = RW_PART2_SZ - }, - { -- name: "Redwood filesystem", -- offset: 0x210000, -- size: 0x200000 - (0x10000 + 0x20000) -- }, -- { -- name: "Redwood OpenBIOS", -- offset: 0x3e0000, -- size: 0x20000, -- mask_flags: MTD_WRITEABLE /* force read-only */ -+ .name = "Redwood OpenBIOS", -+ .offset = RW_PART3_OF, -+ .size = RW_PART3_SZ, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ - } - }; -+ -+#endif /* CONFIG_REDWOOD_6 */ -+ -+struct map_info redwood_flash_map = { -+ .name = "IBM Redwood", -+ .size = WINDOW_SIZE, -+ .buswidth = 2, -+ .phys = WINDOW_ADDR, -+}; -+ -+ - #define NUM_REDWOOD_FLASH_PARTITIONS \ - (sizeof(redwood_flash_partitions)/sizeof(redwood_flash_partitions[0])) - -@@ -140,18 +131,19 @@ - printk(KERN_NOTICE "redwood: flash mapping: %x at %x\n", - WINDOW_SIZE, WINDOW_ADDR); - -- redwood_flash_map.map_priv_1 = -+ redwood_flash_map.virt = - (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); - -- if (!redwood_flash_map.map_priv_1) { -+ if (!redwood_flash_map.virt) { - printk("init_redwood_flash: failed to ioremap\n"); - return -EIO; - } -+ simple_map_init(&redwood_flash_map); - - redwood_mtd = do_map_probe("cfi_probe",&redwood_flash_map); - - if (redwood_mtd) { -- redwood_mtd->module = THIS_MODULE; -+ redwood_mtd->owner = THIS_MODULE; - return add_mtd_partitions(redwood_mtd, - redwood_flash_partitions, - NUM_REDWOOD_FLASH_PARTITIONS); -@@ -164,10 +156,15 @@ - { - if (redwood_mtd) { - del_mtd_partitions(redwood_mtd); -- iounmap((void *)redwood_flash_map.map_priv_1); -+ /* moved iounmap after map_destroy - armin */ - map_destroy(redwood_mtd); -+ iounmap((void *)redwood_flash_map.virt); - } - } - - module_init(init_redwood_flash); - module_exit(cleanup_redwood_flash); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("MontaVista Software "); -+MODULE_DESCRIPTION("MTD map driver for the IBM Redwood reference boards"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/rpxlite.c linux/drivers/mtd/maps/rpxlite.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/rpxlite.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/rpxlite.c 2004-11-17 18:17:59.127300544 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Handle mapping of the flash on the RPX Lite and CLLF boards - */ -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -17,80 +18,31 @@ - - static struct mtd_info *mymtd; - --__u8 rpxlite_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 rpxlite_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 rpxlite_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void rpxlite_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); --} -- --void rpxlite_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void rpxlite_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void rpxlite_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void rpxlite_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio((void *)(map->map_priv_1 + to), from, len); --} -- --struct map_info rpxlite_map = { -- name: "RPX", -- size: WINDOW_SIZE, -- buswidth: 4, -- read8: rpxlite_read8, -- read16: rpxlite_read16, -- read32: rpxlite_read32, -- copy_from: rpxlite_copy_from, -- write8: rpxlite_write8, -- write16: rpxlite_write16, -- write32: rpxlite_write32, -- copy_to: rpxlite_copy_to -+static struct map_info rpxlite_map = { -+ .name = "RPX", -+ .size = WINDOW_SIZE, -+ .buswidth = 4, -+ .phys = WINDOW_ADDR, - }; - - int __init init_rpxlite(void) - { - printk(KERN_NOTICE "RPX Lite or CLLF flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR); -- rpxlite_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); -+ rpxlite_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); - -- if (!rpxlite_map.map_priv_1) { -+ if (!rpxlite_map.virt) { - printk("Failed to ioremap\n"); - return -EIO; - } -+ simple_map_init(&rpxlite_map); - mymtd = do_map_probe("cfi_probe", &rpxlite_map); - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - add_mtd_device(mymtd); - return 0; - } - -- iounmap((void *)rpxlite_map.map_priv_1); -+ iounmap((void *)rpxlite_map.virt); - return -ENXIO; - } - -@@ -100,9 +52,9 @@ - del_mtd_device(mymtd); - map_destroy(mymtd); - } -- if (rpxlite_map.map_priv_1) { -- iounmap((void *)rpxlite_map.map_priv_1); -- rpxlite_map.map_priv_1 = 0; -+ if (rpxlite_map.virt) { -+ iounmap((void *)rpxlite_map.virt); -+ rpxlite_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/sa1100-flash.c linux/drivers/mtd/maps/sa1100-flash.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/sa1100-flash.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/sa1100-flash.c 2004-11-17 18:17:59.129300240 +0100 -@@ -3,7 +3,7 @@ - * - * (C) 2000 Nicolas Pitre - * -- * $Id$ -+ * $Id$ - */ - - #include -@@ -11,278 +11,212 @@ - #include - #include - #include -+#include -+#include -+#include - - #include - #include - #include -+#include - - #include -+#include - #include -+#include - -+#include - - #ifndef CONFIG_ARCH_SA1100 - #error This is for SA1100 architecture only - #endif - -+/* -+ * This isnt complete yet, so... -+ */ -+#define CONFIG_MTD_SA1100_STATICMAP 1 - --#define WINDOW_ADDR 0xe8000000 -- --static __u8 sa1100_read8(struct map_info *map, unsigned long ofs) --{ -- return readb(map->map_priv_1 + ofs); --} -- --static __u16 sa1100_read16(struct map_info *map, unsigned long ofs) --{ -- return readw(map->map_priv_1 + ofs); --} -- --static __u32 sa1100_read32(struct map_info *map, unsigned long ofs) --{ -- return readl(map->map_priv_1 + ofs); --} -- --static void sa1100_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy(to, (void *)(map->map_priv_1 + from), len); --} -- --static void sa1100_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, map->map_priv_1 + adr); --} -- --static void sa1100_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, map->map_priv_1 + adr); --} -- --static void sa1100_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- writel(d, map->map_priv_1 + adr); --} -- --static void sa1100_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy((void *)(map->map_priv_1 + to), from, len); --} -- --static struct map_info sa1100_map = { -- name: "SA1100 flash", -- read8: sa1100_read8, -- read16: sa1100_read16, -- read32: sa1100_read32, -- copy_from: sa1100_copy_from, -- write8: sa1100_write8, -- write16: sa1100_write16, -- write32: sa1100_write32, -- copy_to: sa1100_copy_to, -- -- map_priv_1: WINDOW_ADDR, -- map_priv_2: -1, --}; -- -- -+#ifdef CONFIG_MTD_SA1100_STATICMAP - /* - * Here are partition information for all known SA1100-based devices. - * See include/linux/mtd/partitions.h for definition of the mtd_partition - * structure. - * -- * The *_max_flash_size is the maximum possible mapped flash size which -- * is not necessarily the actual flash size. It must be no more than -- * the value specified in the "struct map_desc *_io_desc" mapping -- * definition for the corresponding machine. -+ * Please note: -+ * 1. We no longer support static flash mappings via the machine io_desc -+ * structure. -+ * 2. The flash size given should be the largest flash size that can -+ * be accommodated. -+ * -+ * The MTD layer will detect flash chip aliasing and reduce the size of -+ * the map accordingly. - * - * Please keep these in alphabetical order, and formatted as per existing - * entries. Thanks. - */ - - #ifdef CONFIG_SA1100_ADSBITSY --#define ADSBITSY_FLASH_SIZE 0x02000000 - static struct mtd_partition adsbitsy_partitions[] = { - { -- name: "bootROM", -- size: 0x80000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "zImage", -- size: 0x100000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "ramdisk.gz", -- size: 0x300000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "User FS", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .name = "bootROM", -+ .size = 0x80000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "zImage", -+ .size = 0x100000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "ramdisk.gz", -+ .size = 0x300000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "User FS", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #endif - - #ifdef CONFIG_SA1100_ASSABET - /* Phase 4 Assabet has two 28F160B3 flash parts in bank 0: */ --#define ASSABET4_FLASH_SIZE 0x00400000 - static struct mtd_partition assabet4_partitions[] = { - { -- name: "bootloader", -- size: 0x00020000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "bootloader params", -- size: 0x00020000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "jffs", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .name = "bootloader", -+ .size = 0x00020000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "bootloader params", -+ .size = 0x00020000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "jffs", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - - /* Phase 5 Assabet has two 28F128J3A flash parts in bank 0: */ --#define ASSABET5_FLASH_SIZE 0x02000000 - static struct mtd_partition assabet5_partitions[] = { - { -- name: "bootloader", -- size: 0x00040000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "bootloader params", -- size: 0x00040000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "jffs", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .name = "bootloader", -+ .size = 0x00040000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "bootloader params", -+ .size = 0x00040000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "jffs", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - --#define ASSABET_FLASH_SIZE ASSABET5_FLASH_SIZE - #define assabet_partitions assabet5_partitions - #endif - - #ifdef CONFIG_SA1100_BADGE4 -- - /* -- * 1 x Intel 28F320C3BA100 Advanced+ Boot Block Flash (32 Mi bit) -+ * 1 x Intel 28F320C3 Advanced+ Boot Block Flash (32 Mi bit) - * Eight 4 KiW Parameter Bottom Blocks (64 KiB) - * Sixty-three 32 KiW Main Blocks (4032 Ki b) -+ * -+ * -+ * -+ * 1 x Intel 28F640C3 Advanced+ Boot Block Flash (64 Mi bit) -+ * Eight 4 KiW Parameter Bottom Blocks (64 KiB) -+ * One-hundred-twenty-seven 32 KiW Main Blocks (8128 Ki b) - */ --#define BADGE4_FLASH_SIZE 0x00400000 - static struct mtd_partition badge4_partitions[] = { - { -- name: "BLOB boot loader", -- offset: 0, -- size: 0x0000A000 -- }, { -- name: "params", -- offset: MTDPART_OFS_APPEND, -- size: 0x00006000 -- }, { -- name: "kernel", -- offset: MTDPART_OFS_APPEND, -- size: 0x00100000 -- }, { -- name: "root", -- offset: MTDPART_OFS_APPEND, -- size: MTDPART_SIZ_FULL -+ .name = "BLOB boot loader", -+ .offset = 0, -+ .size = 0x0000A000 -+ }, { -+ .name = "params", -+ .offset = MTDPART_OFS_APPEND, -+ .size = 0x00006000 -+ }, { -+ .name = "root", -+ .offset = MTDPART_OFS_APPEND, -+ .size = MTDPART_SIZ_FULL - } - }; -- - #endif - - - #ifdef CONFIG_SA1100_CERF - #ifdef CONFIG_SA1100_CERF_FLASH_32MB --#define CERF_FLASH_SIZE 0x02000000 --static struct mtd_partition cerf_partitions[] = { -- { -- name: "firmware", -- size: 0x00040000, -- offset: 0, -- }, { -- name: "params", -- size: 0x00040000, -- offset: 0x00040000, -- }, { -- name: "kernel", -- size: 0x00100000, -- offset: 0x00080000, -- }, { -- name: "rootdisk", -- size: 0x01E80000, -- offset: 0x00180000, -- } --}; -+# define CERF_FLASH_SIZE 0x02000000 - #elif defined CONFIG_SA1100_CERF_FLASH_16MB --#define CERF_FLASH_SIZE 0x01000000 -+# define CERF_FLASH_SIZE 0x01000000 -+#elif defined CONFIG_SA1100_CERF_FLASH_8MB -+# define CERF_FLASH_SIZE 0x00800000 -+#else -+# error "Undefined flash size for CERF in sa1100-flash.c" -+#endif -+ - static struct mtd_partition cerf_partitions[] = { - { -- name: "firmware", -- size: 0x00020000, -- offset: 0, -- }, { -- name: "params", -- size: 0x00020000, -- offset: 0x00020000, -- }, { -- name: "kernel", -- size: 0x00100000, -- offset: 0x00040000, -- }, { -- name: "rootdisk", -- size: 0x00EC0000, -- offset: 0x00140000, -+ .name = "Bootloader", -+ .size = 0x00020000, -+ .offset = 0x00000000, -+ }, { -+ .name = "Params", -+ .size = 0x00040000, -+ .offset = 0x00020000, -+ }, { -+ .name = "Kernel", -+ .size = 0x00100000, -+ .offset = 0x00060000, -+ }, { -+ .name = "Filesystem", -+ .size = CERF_FLASH_SIZE-0x00160000, -+ .offset = 0x00160000, - } - }; --#elif defined CONFIG_SA1100_CERF_FLASH_8MB --# error "Unwritten type definition" --#else --# error "Undefined memory orientation for CERF in sa1100-flash.c" --#endif - #endif - - #ifdef CONFIG_SA1100_CONSUS --#define CONSUS_FLASH_SIZE 0x02000000 - static struct mtd_partition consus_partitions[] = { - { -- name: "Consus boot firmware", -- offset: 0, -- size: 0x00040000, -- mask_flags: MTD_WRITABLE, /* force read-only */ -- }, { -- name: "Consus kernel", -- offset: 0x00040000, -- size: 0x00100000, -- mask_flags: 0, -+ .name = "Consus boot firmware", -+ .offset = 0, -+ .size = 0x00040000, -+ .mask_flags = MTD_WRITABLE, /* force read-only */ -+ }, { -+ .name = "Consus kernel", -+ .offset = 0x00040000, -+ .size = 0x00100000, -+ .mask_flags = 0, - }, { -- name: "Consus disk", -- offset: 0x00140000, -+ .name = "Consus disk", -+ .offset = 0x00140000, - /* The rest (up to 16M) for jffs. We could put 0 and - make it find the size automatically, but right now - i have 32 megs. jffs will use all 32 megs if given - the chance, and this leads to horrible problems - when you try to re-flash the image because blob - won't erase the whole partition. */ -- size: 0x01000000 - 0x00140000, -- mask_flags: 0, -+ .size = 0x01000000 - 0x00140000, -+ .mask_flags = 0, - }, { - /* this disk is a secondary disk, which can be used as - needed, for simplicity, make it the size of the other - consus partition, although realistically it could be - the remainder of the disk (depending on the file - system used) */ -- name: "Consus disk2", -- offset: 0x01000000, -- size: 0x01000000 - 0x00140000, -- mask_flags: 0, -+ .name = "Consus disk2", -+ .offset = 0x01000000, -+ .size = 0x01000000 - 0x00140000, -+ .mask_flags = 0, - } - }; - #endif -@@ -292,96 +226,95 @@ - #define FLEXANET_FLASH_SIZE 0x02000000 - static struct mtd_partition flexanet_partitions[] = { - { -- name: "bootloader", -- size: 0x00040000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "bootloader params", -- size: 0x00040000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "kernel", -- size: 0x000C0000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "altkernel", -- size: 0x000C0000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "root", -- size: 0x00400000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "free1", -- size: 0x00300000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "free2", -- size: 0x00300000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "free3", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -+ .name = "bootloader", -+ .size = 0x00040000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "bootloader params", -+ .size = 0x00040000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "kernel", -+ .size = 0x000C0000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "altkernel", -+ .size = 0x000C0000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "root", -+ .size = 0x00400000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "free1", -+ .size = 0x00300000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "free2", -+ .size = 0x00300000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "free3", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, - } - }; - #endif - - #ifdef CONFIG_SA1100_FREEBIRD --#define FREEBIRD_FLASH_SIZE 0x02000000 - static struct mtd_partition freebird_partitions[] = { --#if CONFIG_SA1100_FREEBIRD_NEW -+#ifdef CONFIG_SA1100_FREEBIRD_NEW - { -- name: "firmware", -- size: 0x00040000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "kernel", -- size: 0x00080000, -- offset: 0x00040000, -- }, { -- name: "params", -- size: 0x00040000, -- offset: 0x000C0000, -- }, { -- name: "initrd", -- size: 0x00100000, -- offset: 0x00100000, -- }, { -- name: "root cramfs", -- size: 0x00300000, -- offset: 0x00200000, -- }, { -- name: "usr cramfs", -- size: 0x00C00000, -- offset: 0x00500000, -- }, { -- name: "local", -- size: MTDPART_SIZ_FULL, -- offset: 0x01100000, -+ .name = "firmware", -+ .size = 0x00040000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "kernel", -+ .size = 0x00080000, -+ .offset = 0x00040000, -+ }, { -+ .name = "params", -+ .size = 0x00040000, -+ .offset = 0x000C0000, -+ }, { -+ .name = "initrd", -+ .size = 0x00100000, -+ .offset = 0x00100000, -+ }, { -+ .name = "root cramfs", -+ .size = 0x00300000, -+ .offset = 0x00200000, -+ }, { -+ .name = "usr cramfs", -+ .size = 0x00C00000, -+ .offset = 0x00500000, -+ }, { -+ .name = "local", -+ .size = MTDPART_SIZ_FULL, -+ .offset = 0x01100000, - } - #else - { -- size: 0x00040000, -- offset: 0, -+ .size = 0x00040000, -+ .offset = 0, - }, { -- size: 0x000c0000, -- offset: MTDPART_OFS_APPEND, -+ .size = 0x000c0000, -+ .offset = MTDPART_OFS_APPEND, - }, { -- size: 0x00400000, -- offset: MTDPART_OFS_APPEND, -+ .size = 0x00400000, -+ .offset = MTDPART_OFS_APPEND, - }, { -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - #endif - }; -@@ -389,178 +322,215 @@ - - #ifdef CONFIG_SA1100_FRODO - /* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */ --#define FRODO_FLASH_SIZE 0x02000000 - static struct mtd_partition frodo_partitions[] = - { - { -- name: "Boot Loader", -- size: 0x00040000, -- offset: 0x00000000 -- }, { -- name: "Parameter Block", -- size: 0x00040000, -- offset: MTDPART_OFS_APPEND -- }, { -- name: "Linux Kernel", -- size: 0x00100000, -- offset: MTDPART_OFS_APPEND -- }, { -- name: "Ramdisk", -- size: 0x00680000, -- offset: MTDPART_OFS_APPEND -- }, { -- name: "Flash File System", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND -+ .name = "bootloader", -+ .size = 0x00040000, -+ .offset = 0x00000000, -+ .mask_flags = MTD_WRITEABLE -+ }, { -+ .name = "bootloader params", -+ .size = 0x00040000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE -+ }, { -+ .name = "kernel", -+ .size = 0x00100000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE -+ }, { -+ .name = "ramdisk", -+ .size = 0x00400000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE -+ }, { -+ .name = "file system", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND - } - }; - #endif - - #ifdef CONFIG_SA1100_GRAPHICSCLIENT --#define GRAPHICSCLIENT_FLASH_SIZE 0x02000000 - static struct mtd_partition graphicsclient_partitions[] = { - { -- name: "zImage", -- size: 0x100000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "ramdisk.gz", -- size: 0x300000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "User FS", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .name = "zImage", -+ .size = 0x100000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "ramdisk.gz", -+ .size = 0x300000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "User FS", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #endif - - #ifdef CONFIG_SA1100_GRAPHICSMASTER --#define GRAPHICSMASTER_FLASH_SIZE 0x01000000 - static struct mtd_partition graphicsmaster_partitions[] = { - { -- name: "zImage", -- size: 0x100000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -+ .name = "zImage", -+ .size = 0x100000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, - { -- name: "ramdisk.gz", -- size: 0x300000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -+ .name = "ramdisk.gz", -+ .size = 0x300000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, - { -- name: "User FS", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .name = "User FS", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #endif - --#ifdef CONFIG_SA1100_H3600 --#define H3600_FLASH_SIZE 0x02000000 --static struct mtd_partition h3600_partitions[] = { -+#ifdef CONFIG_SA1100_H3XXX -+static struct mtd_partition h3xxx_partitions[] = { - { -- name: "H3600 boot firmware", -- size: 0x00040000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "H3600 kernel", -- size: 0x00080000, -- offset: 0x00040000, -+ .name = "H3XXX boot firmware", -+ .size = 0x00040000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { -- name: "H3600 params", -- size: 0x00040000, -- offset: 0x000C0000, -+#ifdef CONFIG_MTD_2PARTS_IPAQ -+ .name = "H3XXX root jffs2", -+ .size = MTDPART_SIZ_FULL, -+ .offset = 0x00040000, -+#else -+ .name = "H3XXX kernel", -+ .size = 0x00080000, -+ .offset = 0x00040000, -+ }, { -+ .name = "H3XXX params", -+ .size = 0x00040000, -+ .offset = 0x000C0000, - }, { - #ifdef CONFIG_JFFS2_FS -- name: "H3600 root jffs2", -- size: MTDPART_SIZ_FULL, -- offset: 0x00100000, -+ .name = "H3XXX root jffs2", -+ .size = MTDPART_SIZ_FULL, -+ .offset = 0x00100000, - #else -- name: "H3600 initrd", -- size: 0x00100000, -- offset: 0x00100000, -+ .name = "H3XXX initrd", -+ .size = 0x00100000, -+ .offset = 0x00100000, - }, { -- name: "H3600 root cramfs", -- size: 0x00300000, -- offset: 0x00200000, -+ .name = "H3XXX root cramfs", -+ .size = 0x00300000, -+ .offset = 0x00200000, - }, { -- name: "H3600 usr cramfs", -- size: 0x00800000, -- offset: 0x00500000, -+ .name = "H3XXX usr cramfs", -+ .size = 0x00800000, -+ .offset = 0x00500000, - }, { -- name: "H3600 usr local", -- size: MTDPART_SIZ_FULL, -- offset: 0x00d00000, -+ .name = "H3XXX usr local", -+ .size = MTDPART_SIZ_FULL, -+ .offset = 0x00d00000, -+#endif - #endif - } - }; - --static void h3600_set_vpp(struct map_info *map, int vpp) -+static void h3xxx_set_vpp(struct map_info *map, int vpp) - { - assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, vpp); - } -+#else -+#define h3xxx_set_vpp NULL -+#endif -+ -+#ifdef CONFIG_SA1100_HACKKIT -+static struct mtd_partition hackkit_partitions[] = { -+ { -+ .name = "BLOB", -+ .size = 0x00040000, -+ .offset = 0x00000000, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "config", -+ .size = 0x00040000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+ .name = "kernel", -+ .size = 0x00100000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+ .name = "initrd", -+ .size = 0x00180000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+ .name = "rootfs", -+ .size = 0x700000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+ .name = "data", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, -+ } -+}; - #endif - - #ifdef CONFIG_SA1100_HUW_WEBPANEL --#define HUW_WEBPANEL_FLASH_SIZE 0x01000000 - static struct mtd_partition huw_webpanel_partitions[] = { - { -- name: "Loader", -- size: 0x00040000, -- offset: 0, -- }, { -- name: "Sector 1", -- size: 0x00040000, -- offset: MTDPART_OFS_APPEND, -+ .name = "Loader", -+ .size = 0x00040000, -+ .offset = 0, -+ }, { -+ .name = "Sector 1", -+ .size = 0x00040000, -+ .offset = MTDPART_OFS_APPEND, - }, { -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #endif - - #ifdef CONFIG_SA1100_JORNADA720 --#define JORNADA720_FLASH_SIZE 0x02000000 - static struct mtd_partition jornada720_partitions[] = { - { -- name: "JORNADA720 boot firmware", -- size: 0x00040000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -+ .name = "JORNADA720 boot firmware", -+ .size = 0x00040000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { -- name: "JORNADA720 kernel", -- size: 0x000c0000, -- offset: 0x00040000, -+ .name = "JORNADA720 kernel", -+ .size = 0x000c0000, -+ .offset = 0x00040000, - }, { -- name: "JORNADA720 params", -- size: 0x00040000, -- offset: 0x00100000, -+ .name = "JORNADA720 params", -+ .size = 0x00040000, -+ .offset = 0x00100000, - }, { -- name: "JORNADA720 initrd", -- size: 0x00100000, -- offset: 0x00140000, -+ .name = "JORNADA720 initrd", -+ .size = 0x00100000, -+ .offset = 0x00140000, - }, { -- name: "JORNADA720 root cramfs", -- size: 0x00300000, -- offset: 0x00240000, -+ .name = "JORNADA720 root cramfs", -+ .size = 0x00300000, -+ .offset = 0x00240000, - }, { -- name: "JORNADA720 usr cramfs", -- size: 0x00800000, -- offset: 0x00540000, -+ .name = "JORNADA720 usr cramfs", -+ .size = 0x00800000, -+ .offset = 0x00540000, - }, { -- name: "JORNADA720 usr local", -- size: 0 /* will expand to the end of the flash */ -- offset: 0x00d00000, -+ .name = "JORNADA720 usr local", -+ .size = 0, /* will expand to the end of the flash */ -+ .offset = 0x00d00000, - } - }; - --static void jornada720_set_vpp(int vpp) -+static void jornada720_set_vpp(struct map_info *map, int vpp) - { - if (vpp) - PPSR |= 0x80; -@@ -568,454 +538,811 @@ - PPSR &= ~0x80; - PPDR |= 0x80; - } -- -+#else -+#define jornada720_set_vpp NULL - #endif - - #ifdef CONFIG_SA1100_PANGOLIN --#define PANGOLIN_FLASH_SIZE 0x04000000 - static struct mtd_partition pangolin_partitions[] = { - { -- name: "boot firmware", -- size: 0x00080000, -- offset: 0x00000000, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "kernel", -- size: 0x00100000, -- offset: 0x00080000, -- }, { -- name: "initrd", -- size: 0x00280000, -- offset: 0x00180000, -- }, { -- name: "initrd-test", -- size: 0x03C00000, -- offset: 0x00400000, -+ .name = "boot firmware", -+ .size = 0x00080000, -+ .offset = 0x00000000, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "kernel", -+ .size = 0x00100000, -+ .offset = 0x00080000, -+ }, { -+ .name = "initrd", -+ .size = 0x00280000, -+ .offset = 0x00180000, -+ }, { -+ .name = "initrd-test", -+ .size = 0x03C00000, -+ .offset = 0x00400000, - } - }; - #endif - - #ifdef CONFIG_SA1100_PT_SYSTEM3 - /* erase size is 0x40000 == 256k partitions have to have this boundary */ --#define SYSTEM3_FLASH_SIZE 0x01000000 - static struct mtd_partition system3_partitions[] = { - { -- name: "BLOB", -- size: 0x00040000, -- offset: 0x00000000, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "config", -- size: 0x00040000, -- offset: MTDPART_OFS_APPEND, -- }, { -- name: "kernel", -- size: 0x00100000, -- offset: MTDPART_OFS_APPEND, -- }, { -- name: "root", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .name = "BLOB", -+ .size = 0x00040000, -+ .offset = 0x00000000, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "config", -+ .size = 0x00040000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+ .name = "kernel", -+ .size = 0x00100000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+ .name = "root", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #endif - - #ifdef CONFIG_SA1100_SHANNON --#define SHANNON_FLASH_SIZE 0x00400000 - static struct mtd_partition shannon_partitions[] = { - { -- name: "BLOB boot loader", -- offset: 0, -- size: 0x20000 -+ .name = "BLOB boot loader", -+ .offset = 0, -+ .size = 0x20000 - }, - { -- name: "kernel", -- offset: MTDPART_OFS_APPEND, -- size: 0xe0000 -+ .name = "kernel", -+ .offset = MTDPART_OFS_APPEND, -+ .size = 0xe0000 - }, - { -- name: "initrd", -- offset: MTDPART_OFS_APPEND, -- size: MTDPART_SIZ_FULL -+ .name = "initrd", -+ .offset = MTDPART_OFS_APPEND, -+ .size = MTDPART_SIZ_FULL - } - }; - - #endif - - #ifdef CONFIG_SA1100_SHERMAN --#define SHERMAN_FLASH_SIZE 0x02000000 - static struct mtd_partition sherman_partitions[] = { - { -- size: 0x50000, -- offset: 0, -+ .size = 0x50000, -+ .offset = 0, - }, { -- size: 0x70000, -- offset: MTDPART_OFS_APPEND, -+ .size = 0x70000, -+ .offset = MTDPART_OFS_APPEND, - }, { -- size: 0x600000, -- offset: MTDPART_OFS_APPEND, -+ .size = 0x600000, -+ .offset = MTDPART_OFS_APPEND, - }, { -- size: 0xA0000, -- offset: MTDPART_OFS_APPEND, -+ .size = 0xA0000, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #endif - - #ifdef CONFIG_SA1100_SIMPAD --#define SIMPAD_FLASH_SIZE 0x02000000 - static struct mtd_partition simpad_partitions[] = { - { -- name: "SIMpad boot firmware", -- size: 0x00080000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "SIMpad kernel", -- size: 0x00100000, -- offset: 0x00080000, -- }, { --#ifdef CONFIG_JFFS2_FS -- name: "SIMpad root jffs2", -- size: MTDPART_SIZ_FULL, -- offset: 0x00180000, -+ .name = "SIMpad boot firmware", -+ .size = 0x00080000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "SIMpad kernel", -+ .size = 0x00100000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+#ifdef CONFIG_ROOT_CRAMFS -+ .name = "SIMpad root cramfs", -+ .size =0x00D80000, -+ .offset = MTDPART_OFS_APPEND -+ -+ }, { -+ .name = "SIMpad local jffs2", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND - #else -- name: "SIMpad initrd", -- size: 0x00300000, -- offset: 0x00180000, -- }, { -- name: "SIMpad root cramfs", -- size: 0x00300000, -- offset: 0x00480000, -- }, { -- name: "SIMpad usr cramfs", -- size: 0x005c0000, -- offset: 0x00780000, -- }, { -- name: "SIMpad usr local", -- size: MTDPART_SIZ_FULL, -- offset: 0x00d40000, -+ .name = "SIMpad root jffs2", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND - #endif - } - }; - #endif /* CONFIG_SA1100_SIMPAD */ - - #ifdef CONFIG_SA1100_STORK --#define STORK_FLASH_SIZE 0x02000000 - static struct mtd_partition stork_partitions[] = { - { -- name: "STORK boot firmware", -- size: 0x00040000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "STORK params", -- size: 0x00040000, -- offset: 0x00040000, -- }, { -- name: "STORK kernel", -- size: 0x00100000, -- offset: 0x00080000, -+ .name = "STORK boot firmware", -+ .size = 0x00040000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "STORK params", -+ .size = 0x00040000, -+ .offset = 0x00040000, -+ }, { -+ .name = "STORK kernel", -+ .size = 0x00100000, -+ .offset = 0x00080000, - }, { - #ifdef CONFIG_JFFS2_FS -- name: "STORK root jffs2", -- offset: 0x00180000, -- size: MTDPART_SIZ_FULL, -+ .name = "STORK root jffs2", -+ .offset = 0x00180000, -+ .size = MTDPART_SIZ_FULL, - #else -- name: "STORK initrd", -- size: 0x00100000, -- offset: 0x00180000, -- }, { -- name: "STORK root cramfs", -- size: 0x00300000, -- offset: 0x00280000, -- }, { -- name: "STORK usr cramfs", -- size: 0x00800000, -- offset: 0x00580000, -- }, { -- name: "STORK usr local", -- offset: 0x00d80000, -- size: MTDPART_SIZ_FULL, -+ .name = "STORK initrd", -+ .size = 0x00100000, -+ .offset = 0x00180000, -+ }, { -+ .name = "STORK root cramfs", -+ .size = 0x00300000, -+ .offset = 0x00280000, -+ }, { -+ .name = "STORK usr cramfs", -+ .size = 0x00800000, -+ .offset = 0x00580000, -+ }, { -+ .name = "STORK usr local", -+ .offset = 0x00d80000, -+ .size = MTDPART_SIZ_FULL, -+#endif -+ } -+}; - #endif -+ -+#ifdef CONFIG_SA1100_TRIZEPS -+static struct mtd_partition trizeps_partitions[] = { -+ { -+ .name = "Bootloader", -+ .size = 0x00100000, -+ .offset = 0, -+ }, { -+ .name = "Kernel", -+ .size = 0x00100000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+ .name = "root", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #endif - - #ifdef CONFIG_SA1100_YOPY --#define YOPY_FLASH_SIZE 0x08000000 - static struct mtd_partition yopy_partitions[] = { - { -- name: "boot firmware", -- size: 0x00040000, -- offset: 0x00000000, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -+ .name = "boot firmware", -+ .size = 0x00040000, -+ .offset = 0x00000000, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { -- name: "kernel", -- size: 0x00080000, -- offset: 0x00080000, -+ .name = "kernel", -+ .size = 0x00080000, -+ .offset = 0x00080000, - }, { -- name: "initrd", -- size: 0x00300000, -- offset: 0x00100000, -+ .name = "initrd", -+ .size = 0x00300000, -+ .offset = 0x00100000, - }, { -- name: "root", -- size: 0x01000000, -- offset: 0x00400000, -+ .name = "root", -+ .size = 0x01000000, -+ .offset = 0x00400000, - } - }; - #endif - --extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts); --extern int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts); -- --static struct mtd_partition *parsed_parts; --static struct mtd_info *mymtd; -- --int __init sa1100_mtd_init(void) -+static int __init sa1100_static_partitions(struct mtd_partition **parts) - { -- struct mtd_partition *parts; -- int nb_parts = 0, ret; -- int parsed_nr_parts = 0; -- const char *part_type; -- unsigned long base = -1UL; -- -- /* Default flash buswidth */ -- sa1100_map.buswidth = (MSC0 & MSC_RBW) ? 2 : 4; -- -- /* -- * Static partition definition selection -- */ -- part_type = "static"; -+ int nb_parts = 0; - - #ifdef CONFIG_SA1100_ADSBITSY - if (machine_is_adsbitsy()) { -- parts = adsbitsy_partitions; -+ *parts = adsbitsy_partitions; - nb_parts = ARRAY_SIZE(adsbitsy_partitions); -- sa1100_map.size = ADSBITSY_FLASH_SIZE; -- sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4; - } - #endif - #ifdef CONFIG_SA1100_ASSABET - if (machine_is_assabet()) { -- parts = assabet_partitions; -+ *parts = assabet_partitions; - nb_parts = ARRAY_SIZE(assabet_partitions); -- sa1100_map.size = ASSABET_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_BADGE4 - if (machine_is_badge4()) { -- parts = badge4_partitions; -+ *parts = badge4_partitions; - nb_parts = ARRAY_SIZE(badge4_partitions); -- sa1100_map.size = BADGE4_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_CERF - if (machine_is_cerf()) { -- parts = cerf_partitions; -+ *parts = cerf_partitions; - nb_parts = ARRAY_SIZE(cerf_partitions); -- sa1100_map.size = CERF_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_CONSUS - if (machine_is_consus()) { -- parts = consus_partitions; -+ *parts = consus_partitions; - nb_parts = ARRAY_SIZE(consus_partitions); -- sa1100_map.size = CONSUS_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_FLEXANET - if (machine_is_flexanet()) { -- parts = flexanet_partitions; -+ *parts = flexanet_partitions; - nb_parts = ARRAY_SIZE(flexanet_partitions); -- sa1100_map.size = FLEXANET_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_FREEBIRD - if (machine_is_freebird()) { -- parts = freebird_partitions; -+ *parts = freebird_partitions; - nb_parts = ARRAY_SIZE(freebird_partitions); -- sa1100_map.size = FREEBIRD_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_FRODO - if (machine_is_frodo()) { -- parts = frodo_partitions; -+ *parts = frodo_partitions; - nb_parts = ARRAY_SIZE(frodo_partitions); -- sa1100_map.size = FRODO_FLASH_SIZE; -- base = 0x00000000; - } - #endif - #ifdef CONFIG_SA1100_GRAPHICSCLIENT - if (machine_is_graphicsclient()) { -- parts = graphicsclient_partitions; -+ *parts = graphicsclient_partitions; - nb_parts = ARRAY_SIZE(graphicsclient_partitions); -- sa1100_map.size = GRAPHICSCLIENT_FLASH_SIZE; -- sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2:4; - } - #endif - #ifdef CONFIG_SA1100_GRAPHICSMASTER - if (machine_is_graphicsmaster()) { -- parts = graphicsmaster_partitions; -+ *parts = graphicsmaster_partitions; - nb_parts = ARRAY_SIZE(graphicsmaster_partitions); -- sa1100_map.size = GRAPHICSMASTER_FLASH_SIZE; -- sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2:4; - } - #endif --#ifdef CONFIG_SA1100_H3600 -- if (machine_is_h3600()) { -- parts = h3600_partitions; -- nb_parts = ARRAY_SIZE(h3600_partitions); -- sa1100_map.size = H3600_FLASH_SIZE; -- sa1100_map.set_vpp = h3600_set_vpp; -+#ifdef CONFIG_SA1100_H3XXX -+ if (machine_is_h3xxx()) { -+ *parts = h3xxx_partitions; -+ nb_parts = ARRAY_SIZE(h3xxx_partitions); -+ } -+#endif -+#ifdef CONFIG_SA1100_HACKKIT -+ if (machine_is_hackkit()) { -+ *parts = hackkit_partitions; -+ nb_parts = ARRAY_SIZE(hackkit_partitions); - } - #endif - #ifdef CONFIG_SA1100_HUW_WEBPANEL - if (machine_is_huw_webpanel()) { -- parts = huw_webpanel_partitions; -+ *parts = huw_webpanel_partitions; - nb_parts = ARRAY_SIZE(huw_webpanel_partitions); -- sa1100_map.size = HUW_WEBPANEL_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_JORNADA720 - if (machine_is_jornada720()) { -- parts = jornada720_partitions; -+ *parts = jornada720_partitions; - nb_parts = ARRAY_SIZE(jornada720_partitions); -- sa1100_map.size = JORNADA720_FLASH_SIZE; -- sa1100_map.set_vpp = jornada720_set_vpp; - } - #endif - #ifdef CONFIG_SA1100_PANGOLIN - if (machine_is_pangolin()) { -- parts = pangolin_partitions; -+ *parts = pangolin_partitions; - nb_parts = ARRAY_SIZE(pangolin_partitions); -- sa1100_map.size = PANGOLIN_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_PT_SYSTEM3 - if (machine_is_pt_system3()) { -- parts = system3_partitions; -+ *parts = system3_partitions; - nb_parts = ARRAY_SIZE(system3_partitions); -- sa1100_map.size = SYSTEM3_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_SHANNON - if (machine_is_shannon()) { -- parts = shannon_partitions; -+ *parts = shannon_partitions; - nb_parts = ARRAY_SIZE(shannon_partitions); -- sa1100_map.size = SHANNON_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_SHERMAN - if (machine_is_sherman()) { -- parts = sherman_partitions; -+ *parts = sherman_partitions; - nb_parts = ARRAY_SIZE(sherman_partitions); -- sa1100_map.size = SHERMAN_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_SIMPAD - if (machine_is_simpad()) { -- parts = simpad_partitions; -+ *parts = simpad_partitions; - nb_parts = ARRAY_SIZE(simpad_partitions); -- sa1100_map.size = SIMPAD_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_STORK - if (machine_is_stork()) { -- parts = stork_partitions; -+ *parts = stork_partitions; - nb_parts = ARRAY_SIZE(stork_partitions); -- sa1100_map.size = STORK_FLASH_SIZE; -+ } -+#endif -+#ifdef CONFIG_SA1100_TRIZEPS -+ if (machine_is_trizeps()) { -+ *parts = trizeps_partitions; -+ nb_parts = ARRAY_SIZE(trizeps_partitions); - } - #endif - #ifdef CONFIG_SA1100_YOPY - if (machine_is_yopy()) { -- parts = yopy_partitions; -+ *parts = yopy_partitions; - nb_parts = ARRAY_SIZE(yopy_partitions); -- sa1100_map.size = YOPY_FLASH_SIZE; - } - #endif - -+ return nb_parts; -+} -+#endif -+ -+struct sa_info { -+ unsigned long base; -+ unsigned long size; -+ int width; -+ void *vbase; -+ void (*set_vpp)(struct map_info *, int); -+ struct map_info *map; -+ struct mtd_info *mtd; -+ struct resource *res; -+}; -+ -+#define NR_SUBMTD 4 -+ -+static struct sa_info info[NR_SUBMTD]; -+ -+static int __init sa1100_setup_mtd(struct sa_info *sa, int nr, struct mtd_info **rmtd) -+{ -+ struct mtd_info *subdev[nr]; -+ struct map_info *maps; -+ int i, found = 0, ret = 0; -+ - /* -- * For simple flash devices, use ioremap to map the flash. -+ * Allocate the map_info structs in one go. - */ -- if (base != (unsigned long)-1) { -- if (!request_mem_region(base, sa1100_map.size, "flash")) -- return -EBUSY; -- sa1100_map.map_priv_2 = base; -- sa1100_map.map_priv_1 = (unsigned long) -- ioremap(base, sa1100_map.size); -+ maps = kmalloc(sizeof(struct map_info) * nr, GFP_KERNEL); -+ if (!maps) -+ return -ENOMEM; -+ -+ memset(maps, 0, sizeof(struct map_info) * nr); -+ -+ /* -+ * Claim and then map the memory regions. -+ */ -+ for (i = 0; i < nr; i++) { -+ if (sa[i].base == (unsigned long)-1) -+ break; -+ -+ sa[i].res = request_mem_region(sa[i].base, sa[i].size, "sa1100 flash"); -+ if (!sa[i].res) { -+ ret = -EBUSY; -+ break; -+ } -+ -+ sa[i].map = maps + i; -+ -+ sa[i].vbase = ioremap(sa[i].base, sa[i].size); -+ if (!sa[i].vbase) { - ret = -ENOMEM; -- if (!sa1100_map.map_priv_1) -- goto out_err; -+ break; - } - -+ sa[i].map->virt = (unsigned long)sa[i].vbase; -+ sa[i].map->phys = sa[i].base; -+ sa[i].map->set_vpp = sa[i].set_vpp; -+ sa[i].map->buswidth = sa[i].width; -+ sa[i].map->size = sa[i].size; -+ -+ simple_map_init(sa[i].map); -+ - /* - * Now let's probe for the actual flash. Do it here since - * specific machine settings might have been set above. - */ -- printk(KERN_NOTICE "SA1100 flash: probing %d-bit flash bus\n", sa1100_map.buswidth*8); -- mymtd = do_map_probe("cfi_probe", &sa1100_map); -+ sa[i].mtd = do_map_probe("cfi_probe", sa[i].map); -+ if (sa[i].mtd == NULL) { - ret = -ENXIO; -- if (!mymtd) -- goto out_err; -- mymtd->module = THIS_MODULE; -+ break; -+ } -+ sa[i].mtd->owner = THIS_MODULE; -+ subdev[i] = sa[i].mtd; -+ -+ printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, " -+ "%d-bit\n", sa[i].base, sa[i].mtd->size >> 20, -+ sa[i].width * 8); -+ found += 1; -+ } - - /* -- * Dynamic partition selection stuff (might override the static ones) -+ * ENXIO is special. It means we didn't find a chip when -+ * we probed. We need to tear down the mapping, free the -+ * resource and mark it as such. - */ --#ifdef CONFIG_MTD_REDBOOT_PARTS -- if (parsed_nr_parts == 0) { -- int ret = parse_redboot_partitions(mymtd, &parsed_parts); -+ if (ret == -ENXIO) { -+ iounmap(sa[i].vbase); -+ sa[i].vbase = NULL; -+ release_resource(sa[i].res); -+ sa[i].res = NULL; -+ } - -- if (ret > 0) { -- part_type = "RedBoot"; -- parsed_nr_parts = ret; -+ /* -+ * If we found one device, don't bother with concat support. -+ * If we found multiple devices, use concat if we have it -+ * available, otherwise fail. -+ */ -+ if (ret == 0 || ret == -ENXIO) { -+ if (found == 1) { -+ *rmtd = subdev[0]; -+ ret = 0; -+ } else if (found > 1) { -+ /* -+ * We detected multiple devices. Concatenate -+ * them together. -+ */ -+#ifdef CONFIG_MTD_CONCAT -+ *rmtd = mtd_concat_create(subdev, found, -+ "sa1100 flash"); -+ if (*rmtd == NULL) -+ ret = -ENXIO; -+#else -+ printk(KERN_ERR "SA1100 flash: multiple devices " -+ "found but MTD concat support disabled.\n"); -+ ret = -ENXIO; -+#endif - } - } -+ -+ /* -+ * If we failed, clean up. -+ */ -+ if (ret) { -+ do { -+ if (sa[i].mtd) -+ map_destroy(sa[i].mtd); -+ if (sa[i].vbase) -+ iounmap(sa[i].vbase); -+ if (sa[i].res) -+ release_resource(sa[i].res); -+ } while (i--); -+ -+ kfree(maps); -+ } -+ -+ return ret; -+} -+ -+static void __exit sa1100_destroy_mtd(struct sa_info *sa, struct mtd_info *mtd) -+{ -+ int i; -+ -+ del_mtd_partitions(mtd); -+ -+#ifdef CONFIG_MTD_CONCAT -+ if (mtd != sa[0].mtd) -+ mtd_concat_destroy(mtd); - #endif --#ifdef CONFIG_MTD_CMDLINE_PARTS -- if (parsed_nr_parts == 0) { -- int ret = parse_cmdline_partitions(mymtd, &parsed_parts, "sa1100"); -- if (ret > 0) { -- part_type = "Command Line"; -- parsed_nr_parts = ret; -+ -+ for (i = NR_SUBMTD; i >= 0; i--) { -+ if (sa[i].mtd) -+ map_destroy(sa[i].mtd); -+ if (sa[i].vbase) -+ iounmap(sa[i].vbase); -+ if (sa[i].res) -+ release_resource(sa[i].res); - } -+ kfree(sa[0].map); -+} -+ -+/* -+ * A Thought: can we automatically detect the flash? -+ * - Check to see if the region is busy (yes -> failure) -+ * - Is the MSC setup for flash (no -> failure) -+ * - Probe for flash -+ */ -+ -+static struct map_info sa1100_probe_map __initdata = { -+ .name = "SA1100-flash", -+}; -+ -+static void __init sa1100_probe_one_cs(unsigned int msc, unsigned long phys) -+{ -+ struct mtd_info *mtd; -+ -+ printk(KERN_INFO "* Probing 0x%08lx: MSC = 0x%04x %d bit ", -+ phys, msc & 0xffff, msc & MSC_RBW ? 16 : 32); -+ -+ if (check_mem_region(phys, 0x08000000)) { -+ printk("busy\n"); -+ return; - } --#endif - -- if (parsed_nr_parts > 0) { -- parts = parsed_parts; -- nb_parts = parsed_nr_parts; -+ if ((msc & 3) == 1) { -+ printk("wrong type\n"); -+ return; - } - -- if (nb_parts == 0) { -- printk(KERN_NOTICE "SA1100 flash: no partition info available, registering whole flash at once\n"); -- add_mtd_device(mymtd); -- } else { -- printk(KERN_NOTICE "Using %s partition definition\n", part_type); -- add_mtd_partitions(mymtd, parts, nb_parts); -+ sa1100_probe_map.buswidth = msc & MSC_RBW ? 2 : 4; -+ sa1100_probe_map.size = SZ_1M; -+ sa1100_probe_map.phys = phys; -+ sa1100_probe_map.virt = (unsigned long)ioremap(phys, SZ_1M); -+ if (sa1100_probe_map.virt == 0) -+ goto fail; -+ simple_map_init(&sa1100_probe_map); -+ -+ /* Shame cfi_probe blurts out kernel messages... */ -+ mtd = do_map_probe("cfi_probe", &sa1100_probe_map); -+ if (mtd) -+ map_destroy(mtd); -+ iounmap((void *)sa1100_probe_map.virt); -+ -+ if (!mtd) -+ goto fail; -+ -+ printk("pass\n"); -+ return; -+ -+ fail: -+ printk("failed\n"); -+} -+ -+static void __init sa1100_probe_flash(void) -+{ -+ printk(KERN_INFO "-- SA11xx Flash probe. Please report results.\n"); -+ sa1100_probe_one_cs(MSC0, SA1100_CS0_PHYS); -+ sa1100_probe_one_cs(MSC0 >> 16, SA1100_CS1_PHYS); -+ sa1100_probe_one_cs(MSC1, SA1100_CS2_PHYS); -+ sa1100_probe_one_cs(MSC1 >> 16, SA1100_CS3_PHYS); -+ sa1100_probe_one_cs(MSC2, SA1100_CS4_PHYS); -+ sa1100_probe_one_cs(MSC2 >> 16, SA1100_CS5_PHYS); -+ printk(KERN_INFO "-- SA11xx Flash probe complete.\n"); -+} -+ -+static int __init sa1100_locate_flash(void) -+{ -+ int i, nr = -ENODEV; -+ -+ sa1100_probe_flash(); -+ -+ if (machine_is_adsbitsy()) { -+ info[0].base = SA1100_CS1_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_assabet()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ info[1].base = SA1100_CS1_PHYS; /* neponset */ -+ info[1].size = SZ_32M; -+ nr = 2; -+ } -+ if (machine_is_badge4()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_64M; -+ nr = 1; -+ } -+ if (machine_is_cerf()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_consus()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_flexanet()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_freebird()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_frodo()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_graphicsclient()) { -+ info[0].base = SA1100_CS1_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; - } -- return 0; -+ if (machine_is_graphicsmaster()) { -+ info[0].base = SA1100_CS1_PHYS; -+ info[0].size = SZ_16M; -+ nr = 1; -+ } -+ if (machine_is_h3xxx()) { -+ info[0].set_vpp = h3xxx_set_vpp; -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_huw_webpanel()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_16M; -+ nr = 1; -+ } -+ if (machine_is_itsy()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_jornada720()) { -+ info[0].set_vpp = jornada720_set_vpp; -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_nanoengine()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[1].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_pangolin()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_64M; -+ nr = 1; -+ } -+ if (machine_is_pfs168()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_pleb()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_4M; -+ info[1].base = SA1100_CS1_PHYS; -+ info[1].size = SZ_4M; -+ nr = 2; -+ } -+ if (machine_is_pt_system3()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_16M; -+ nr = 1; -+ } -+ if (machine_is_shannon()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_4M; -+ nr = 1; -+ } -+ if (machine_is_sherman()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_simpad()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_16M; -+ info[1].base = SA1100_CS1_PHYS; -+ info[1].size = SZ_16M; -+ nr = 2; -+ } -+ if (machine_is_stork()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_trizeps()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_16M; -+ nr = 1; -+ } -+ if (machine_is_victor()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_2M; -+ nr = 1; -+ } -+ if (machine_is_yopy()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_64M; -+ info[1].base = SA1100_CS1_PHYS; -+ info[1].size = SZ_64M; -+ nr = 2; -+ } -+ -+ if (nr < 0) -+ return nr; - -- out_err: -- if (sa1100_map.map_priv_2 != -1) { -- iounmap((void *)sa1100_map.map_priv_1); -- release_mem_region(sa1100_map.map_priv_2, sa1100_map.size); -+ /* -+ * Retrieve the buswidth from the MSC registers. -+ * We currently only implement CS0 and CS1 here. -+ */ -+ for (i = 0; i < nr; i++) { -+ switch (info[i].base) { -+ default: -+ printk(KERN_WARNING "SA1100 flash: unknown base address " -+ "0x%08lx, assuming CS0\n", info[i].base); -+ case SA1100_CS0_PHYS: -+ info[i].width = (MSC0 & MSC_RBW) ? 2 : 4; -+ break; -+ -+ case SA1100_CS1_PHYS: -+ info[i].width = ((MSC0 >> 16) & MSC_RBW) ? 2 : 4; -+ break; - } -- return ret; -+ } -+ -+ return nr; - } - --static void __exit sa1100_mtd_cleanup(void) -+static struct mtd_partition *parsed_parts; -+const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; -+ -+static void __init sa1100_locate_partitions(struct mtd_info *mtd) - { -- if (mymtd) { -- del_mtd_partitions(mymtd); -- map_destroy(mymtd); -- if (parsed_parts) -- kfree(parsed_parts); -+ const char *part_type = NULL; -+ int nr_parts = 0; -+ -+ do { -+ /* -+ * Partition selection stuff. -+ */ -+#ifdef CONFIG_MTD_PARTITIONS -+ nr_parts = parse_mtd_partitions(mtd, part_probes, &parsed_parts, 0); -+ if (nr_parts > 0) { -+ part_type = "dynamic"; -+ break; - } -- if (sa1100_map.map_priv_2 != -1) { -- iounmap((void *)sa1100_map.map_priv_1); -- release_mem_region(sa1100_map.map_priv_2, sa1100_map.size); -+#endif -+#ifdef CONFIG_MTD_SA1100_STATICMAP -+ nr_parts = sa1100_static_partitions(&parsed_parts); -+ if (nr_parts > 0) { -+ part_type = "static"; -+ break; - } -+#endif -+ } while (0); -+ -+ if (nr_parts == 0) { -+ printk(KERN_NOTICE "SA1100 flash: no partition info " -+ "available, registering whole flash\n"); -+ add_mtd_device(mtd); -+ } else { -+ printk(KERN_NOTICE "SA1100 flash: using %s partition " -+ "definition\n", part_type); -+ add_mtd_partitions(mtd, parsed_parts, nr_parts); -+ } -+ -+ /* Always succeeds. */ -+} -+ -+static void __exit sa1100_destroy_partitions(void) -+{ -+ if (parsed_parts) -+ kfree(parsed_parts); -+} -+ -+static struct mtd_info *mymtd; -+ -+static int __init sa1100_mtd_init(void) -+{ -+ int ret; -+ int nr; -+ -+ nr = sa1100_locate_flash(); -+ if (nr < 0) -+ return nr; -+ -+ ret = sa1100_setup_mtd(info, nr, &mymtd); -+ if (ret == 0) -+ sa1100_locate_partitions(mymtd); -+ -+ return ret; -+} -+ -+static void __exit sa1100_mtd_cleanup(void) -+{ -+ sa1100_destroy_mtd(info, mymtd); -+ sa1100_destroy_partitions(); - } - - module_init(sa1100_mtd_init); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/sbc8240.c linux/drivers/mtd/maps/sbc8240.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/sbc8240.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/sbc8240.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,417 @@ -+/* -+ * Handle mapping of the flash memory access routines on the SBC8240 board. -+ * -+ * Carolyn Smith, Tektronix, Inc. -+ * -+ * This code is GPLed -+ * -+ * $Id$ -+ * -+ */ -+ -+/* -+ * The SBC8240 has 2 flash banks. -+ * Bank 0 is a 512 KiB AMD AM29F040B; 8 x 64 KiB sectors. -+ * It contains the U-Boot code (7 sectors) and the environment (1 sector). -+ * Bank 1 is 4 x 1 MiB AMD AM29LV800BT; 15 x 64 KiB sectors, 1 x 32 KiB sector, -+ * 2 x 8 KiB sectors, 1 x 16 KiB sectors. -+ * Both parts are JEDEC compatible. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#ifdef CONFIG_MTD_PARTITIONS -+#include -+#endif -+ -+#define DEBUG -+ -+#ifdef DEBUG -+# define debugk(fmt,args...) printk(fmt ,##args) -+#else -+# define debugk(fmt,args...) -+#endif -+ -+ -+#define WINDOW_ADDR0 0xFFF00000 /* 512 KiB */ -+#define WINDOW_SIZE0 0x00080000 -+#define BUSWIDTH0 1 -+ -+#define WINDOW_ADDR1 0xFF000000 /* 4 MiB */ -+#define WINDOW_SIZE1 0x00400000 -+#define BUSWIDTH1 8 -+ -+#define MSG_PREFIX "sbc8240:" /* prefix for our printk()'s */ -+#define MTDID "sbc8240-%d" /* for mtdparts= partitioning */ -+ -+ -+static __u8 sbc8240_read8 (struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readb(map->map_priv_1 + ofs); -+} -+ -+static __u16 sbc8240_read16 (struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readw(map->map_priv_1 + ofs); -+} -+ -+static __u32 sbc8240_read32 (struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readl(map->map_priv_1 + ofs); -+} -+ -+unsigned long long result64; -+ -+static __u64 sbc8240_read64 (struct map_info *map, unsigned long ofs) -+{ -+ unsigned long flags, msr, saved_msr; -+ volatile long saved_fr[2]; -+ volatile unsigned long long result; -+ volatile unsigned long *p; -+ -+ save_flags(flags); -+ cli(); -+ -+ /* turn off floating point unavailable exceptions */ -+ -+ __asm__ __volatile__ ( -+ "mfmsr %0" -+ : "=r" (msr) :); -+ -+ saved_msr = msr; -+ msr |= MSR_FP; -+ msr &= ~(MSR_FE0 | MSR_FE1); -+ -+ __asm__ __volatile__ ( -+ "mtmsr %0\n" -+ "isync\n" -+ : : "r" (msr)); -+ -+ /* read the data via a floating point register */ -+ -+ ofs = map->map_priv_1 + ofs; -+ p = (unsigned long *) &result64; -+ -+ __asm__ __volatile__ ( -+ "lfd 1,0(%1)\n" -+ "stfd 1,0(%0)\n" -+ : : "r" (p), "r" (ofs) -+ ); -+ -+ /* restore state */ -+ -+ __asm__ __volatile__ ( -+ "mtmsr %0\n" -+ "isync\n" -+ : : "r" (saved_msr)); -+ -+ restore_flags(flags); -+ -+ p = (unsigned long *) &result64; -+ debugk("sbc8240_read64 ofs 0x%x result 0x%08x%08x\n", ofs, *p, *(p+1)); -+ -+ return result64; -+} -+ -+static void sbc8240_copy_from (struct map_info *map, -+ void *to, unsigned long from, ssize_t len) -+{ -+ memcpy_fromio (to, (void *) (map->map_priv_1 + from), len); -+} -+ -+static void sbc8240_write8 (struct map_info *map, __u8 d, unsigned long adr) -+{ -+ __raw_writeb(d, map->map_priv_1 + adr); -+ mb(); -+} -+ -+static void sbc8240_write16 (struct map_info *map, __u16 d, -+ unsigned long adr) -+{ -+ __raw_writew(d, map->map_priv_1 + adr); -+ mb(); -+} -+ -+static void sbc8240_write32 (struct map_info *map, __u32 d, -+ unsigned long adr) -+{ -+ __raw_writel(d, map->map_priv_1 + adr); -+ mb(); -+} -+ -+static void sbc8240_write64 (struct map_info *map, __u64 data, -+ unsigned long adr) -+{ -+ unsigned long long tmp; -+ unsigned long flags, msr, saved_msr, *p; -+ volatile long saved_fr[2]; -+ -+ save_flags(flags); -+ cli(); -+ -+ /* turn off floating point unavailable exceptions */ -+ -+ __asm__ __volatile__ ( -+ "mfmsr %0" -+ : "=r" (msr) :); -+ -+ saved_msr = msr; -+ msr |= MSR_FP; -+ msr &= ~(MSR_FE0 | MSR_FE1); -+ -+ __asm__ __volatile__ ( -+ "mtmsr %0\n" -+ "isync\n" -+ : : "r" (msr)); -+ -+ -+ /* write the data via a floating point register */ -+ -+ tmp = data; -+ p = (unsigned long *) &tmp; -+ adr = map->map_priv_1 + adr; -+ debugk("sbc8240_write64 adr 0x%x data 0x%08x%08x\n", adr, *p, *(p+1)); -+ -+ __asm__ __volatile__ ( -+ "stfd 1,0(%2)\n" -+ "lfd 1,0(%0)\n" -+ "stfd 1,0(%1)\n" -+ "lfd 1,0(%2)\n" -+ : : "r" (p), "r" (adr), "b" (saved_fr) -+ ); -+ -+ /* restore state */ -+ -+ __asm__ __volatile__ ( -+ "mtmsr %0\n" -+ "isync\n" -+ : : "r" (saved_msr)); -+ -+ restore_flags(flags); -+} -+ -+static void sbc8240_copy_to (struct map_info *map, -+ unsigned long to, const void *from, ssize_t len) -+{ -+ memcpy_toio ((void *) (map->map_priv_1 + to), from, len); -+} -+ -+static struct map_info sbc8240_map[2] = { -+ { -+ .name = "sbc8240 Flash Bank #0", -+ .size = WINDOW_SIZE0, -+ .buswidth = BUSWIDTH0, -+ .read8 = sbc8240_read8, -+ .read16 = sbc8240_read16, -+ .read32 = sbc8240_read32, -+ .read64 = sbc8240_read64, -+ .copy_from = sbc8240_copy_from, -+ .write8 = sbc8240_write8, -+ .write16 = sbc8240_write16, -+ .write32 = sbc8240_write32, -+ .write64 = sbc8240_write64, -+ .copy_to = sbc8240_copy_to -+ }, -+ { -+ .name = "sbc8240 Flash Bank #1", -+ .size = WINDOW_SIZE1, -+ .buswidth = BUSWIDTH1, -+ .read8 = sbc8240_read8, -+ .read16 = sbc8240_read16, -+ .read32 = sbc8240_read32, -+ .read64 = sbc8240_read64, -+ .copy_from = sbc8240_copy_from, -+ .write8 = sbc8240_write8, -+ .write16 = sbc8240_write16, -+ .write32 = sbc8240_write32, -+ .write64 = sbc8240_write64, -+ .copy_to = sbc8240_copy_to -+ } -+}; -+ -+#define NUM_FLASH_BANKS (sizeof(sbc8240_map) / sizeof(struct map_info)) -+ -+/* -+ * The following defines the partition layout of SBC8240 boards. -+ * -+ * See include/linux/mtd/partitions.h for definition of the -+ * mtd_partition structure. -+ * -+ * The *_max_flash_size is the maximum possible mapped flash size -+ * which is not necessarily the actual flash size. It must correspond -+ * to the value specified in the mapping definition defined by the -+ * "struct map_desc *_io_desc" for the corresponding machine. -+ */ -+ -+#ifdef CONFIG_MTD_PARTITIONS -+ -+static struct mtd_partition sbc8240_uboot_partitions [] = { -+ /* Bank 0 */ -+ { -+ .name = "U-boot", /* U-Boot Firmware */ -+ .offset = 0, -+ .size = 0x00070000, /* 7 x 64 KiB sectors */ -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, -+ { -+ .name = "environment", /* U-Boot environment */ -+ .offset = 0x00070000, -+ .size = 0x00010000, /* 1 x 64 KiB sector */ -+ }, -+}; -+ -+static struct mtd_partition sbc8240_fs_partitions [] = { -+ { -+ .name = "jffs", /* JFFS filesystem */ -+ .offset = 0, -+ .size = 0x003C0000, /* 4 * 15 * 64KiB */ -+ }, -+ { -+ .name = "tmp32", -+ .offset = 0x003C0000, -+ .size = 0x00020000, /* 4 * 32KiB */ -+ }, -+ { -+ .name = "tmp8a", -+ .offset = 0x003E0000, -+ .size = 0x00008000, /* 4 * 8KiB */ -+ }, -+ { -+ .name = "tmp8b", -+ .offset = 0x003E8000, -+ .size = 0x00008000, /* 4 * 8KiB */ -+ }, -+ { -+ .name = "tmp16", -+ .offset = 0x003F0000, -+ .size = 0x00010000, /* 4 * 16KiB */ -+ } -+}; -+ -+#define NB_OF(x) (sizeof (x) / sizeof (x[0])) -+ -+/* trivial struct to describe partition information */ -+struct mtd_part_def -+{ -+ int nums; -+ unsigned char *type; -+ struct mtd_partition* mtd_part; -+}; -+ -+static struct mtd_info *sbc8240_mtd[NUM_FLASH_BANKS]; -+static struct mtd_part_def sbc8240_part_banks[NUM_FLASH_BANKS]; -+ -+ -+#endif /* CONFIG_MTD_PARTITIONS */ -+ -+ -+int __init init_sbc8240_mtd (void) -+{ -+ static struct _cjs { -+ u_long addr; -+ u_long size; -+ } pt[NUM_FLASH_BANKS] = { -+ { -+ .addr = WINDOW_ADDR0, -+ .size = WINDOW_SIZE0 -+ }, -+ { -+ .addr = WINDOW_ADDR1, -+ .size = WINDOW_SIZE1 -+ }, -+ }; -+ -+ int devicesfound = 0; -+ int i; -+ -+ for (i = 0; i < NUM_FLASH_BANKS; i++) { -+ printk (KERN_NOTICE MSG_PREFIX -+ "Probing 0x%08lx at 0x%08lx\n", pt[i].size, pt[i].addr); -+ -+ sbc8240_map[i].map_priv_1 = -+ (unsigned long) ioremap (pt[i].addr, pt[i].size); -+ if (!sbc8240_map[i].map_priv_1) { -+ printk (MSG_PREFIX "failed to ioremap\n"); -+ return -EIO; -+ } -+ -+ sbc8240_mtd[i] = do_map_probe("jedec_probe", &sbc8240_map[i]); -+ -+ if (sbc8240_mtd[i]) { -+ sbc8240_mtd[i]->module = THIS_MODULE; -+ devicesfound++; -+ } -+ } -+ -+ if (!devicesfound) { -+ printk(KERN_NOTICE MSG_PREFIX -+ "No suppported flash chips found!\n"); -+ return -ENXIO; -+ } -+ -+#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[1].mtd_part = sbc8240_fs_partitions; -+ sbc8240_part_banks[1].type = "static file system"; -+ sbc8240_part_banks[1].nums = NB_OF(sbc8240_fs_partitions); -+ -+ for (i = 0; i < NUM_FLASH_BANKS; i++) { -+ -+ if (!sbc8240_mtd[i]) continue; -+ if (sbc8240_part_banks[i].nums == 0) { -+ printk (KERN_NOTICE MSG_PREFIX -+ "No partition info available, registering whole device\n"); -+ add_mtd_device(sbc8240_mtd[i]); -+ } else { -+ printk (KERN_NOTICE MSG_PREFIX -+ "Using %s partition definition\n", sbc8240_part_banks[i].mtd_part->name); -+ add_mtd_partitions (sbc8240_mtd[i], -+ sbc8240_part_banks[i].mtd_part, -+ sbc8240_part_banks[i].nums); -+ } -+ } -+#else -+ printk(KERN_NOTICE MSG_PREFIX -+ "Registering %d flash banks at once\n", devicesfound); -+ -+ for (i = 0; i < devicesfound; i++) { -+ add_mtd_device(sbc8240_mtd[i]); -+ } -+#endif /* CONFIG_MTD_PARTITIONS */ -+ -+ return devicesfound == 0 ? -ENXIO : 0; -+} -+ -+static void __exit cleanup_sbc8240_mtd (void) -+{ -+ int i; -+ -+ for (i = 0; i < NUM_FLASH_BANKS; i++) { -+ if (sbc8240_mtd[i]) { -+ del_mtd_device (sbc8240_mtd[i]); -+ map_destroy (sbc8240_mtd[i]); -+ } -+ if (sbc8240_map[i].map_priv_1) { -+ iounmap ((void *) sbc8240_map[i].map_priv_1); -+ sbc8240_map[i].map_priv_1 = 0; -+ } -+ } -+} -+ -+module_init (init_sbc8240_mtd); -+module_exit (cleanup_sbc8240_mtd); -+ -+MODULE_LICENSE ("GPL"); -+MODULE_AUTHOR ("Carolyn Smith "); -+MODULE_DESCRIPTION ("MTD map driver for SBC8240 boards"); -+ -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/sbc_gxx.c linux/drivers/mtd/maps/sbc_gxx.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/sbc_gxx.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/sbc_gxx.c 2004-11-17 18:17:59.132299784 +0100 -@@ -17,7 +17,7 @@ - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - -- $Id$ -+ $Id$ - - The SBC-MediaGX / SBC-GXx has up to 16 MiB of - Intel StrataFlash (28F320/28F640) in x8 mode. -@@ -91,14 +91,14 @@ - * single flash device into. If the size if zero we use up to the end of the - * device. */ - static struct mtd_partition partition_info[]={ -- { name: "SBC-GXx flash boot partition", -- offset: 0, -- size: BOOT_PARTITION_SIZE_KiB*1024 }, -- { name: "SBC-GXx flash data partition", -- offset: BOOT_PARTITION_SIZE_KiB*1024, -- size: (DATA_PARTITION_SIZE_KiB)*1024 }, -- { name: "SBC-GXx flash application partition", -- offset: (BOOT_PARTITION_SIZE_KiB+DATA_PARTITION_SIZE_KiB)*1024 } -+ { .name = "SBC-GXx flash boot partition", -+ .offset = 0, -+ .size = BOOT_PARTITION_SIZE_KiB*1024 }, -+ { .name = "SBC-GXx flash data partition", -+ .offset = BOOT_PARTITION_SIZE_KiB*1024, -+ .size = (DATA_PARTITION_SIZE_KiB)*1024 }, -+ { .name = "SBC-GXx flash application partition", -+ .offset = (BOOT_PARTITION_SIZE_KiB+DATA_PARTITION_SIZE_KiB)*1024 } - }; - - #define NUM_PARTITIONS 3 -@@ -203,19 +203,20 @@ - } - - static struct map_info sbc_gxx_map = { -- name: "SBC-GXx flash", -- size: MAX_SIZE_KiB*1024, /* this must be set to a maximum possible amount -+ .name = "SBC-GXx flash", -+ .phys = NO_XIP, -+ .size = MAX_SIZE_KiB*1024, /* this must be set to a maximum possible amount - of flash so the cfi probe routines find all - the chips */ -- buswidth: 1, -- read8: sbc_gxx_read8, -- read16: sbc_gxx_read16, -- read32: sbc_gxx_read32, -- copy_from: sbc_gxx_copy_from, -- write8: sbc_gxx_write8, -- write16: sbc_gxx_write16, -- write32: sbc_gxx_write32, -- copy_to: sbc_gxx_copy_to -+ .buswidth = 1, -+ .read8 = sbc_gxx_read8, -+ .read16 = sbc_gxx_read16, -+ .read32 = sbc_gxx_read32, -+ .copy_from = sbc_gxx_copy_from, -+ .write8 = sbc_gxx_write8, -+ .write16 = sbc_gxx_write16, -+ .write32 = sbc_gxx_write32, -+ .copy_to = sbc_gxx_copy_to - }; - - /* MTD device for all of the flash. */ -@@ -234,12 +235,6 @@ - - int __init init_sbc_gxx(void) - { -- if (check_region(PAGE_IO,PAGE_IO_SIZE) != 0) { -- printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n", -- sbc_gxx_map.name, -- PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 ); -- return -EAGAIN; -- } - iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); - if (!iomapadr) { - printk( KERN_ERR"%s: failed to ioremap memory region\n", -@@ -247,7 +242,14 @@ - return -EIO; - } - -- request_region( PAGE_IO, PAGE_IO_SIZE, "SBC-GXx flash" ); -+ if (!request_region( PAGE_IO, PAGE_IO_SIZE, "SBC-GXx flash")) { -+ printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n", -+ sbc_gxx_map.name, -+ PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 ); -+ iounmap((void *)iomapadr); -+ return -EAGAIN; -+ } -+ - - printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n", - sbc_gxx_map.name, -@@ -261,7 +263,7 @@ - return -ENXIO; - } - -- all_mtd->module=THIS_MODULE; -+ all_mtd->owner = THIS_MODULE; - - /* Create MTD devices for each partition. */ - add_mtd_partitions(all_mtd, partition_info, NUM_PARTITIONS ); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/sc520cdp.c linux/drivers/mtd/maps/sc520cdp.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/sc520cdp.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/sc520cdp.c 2004-11-17 18:17:59.133299632 +0100 -@@ -16,7 +16,7 @@ - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * -- * $Id$ -+ * $Id$ - * - * - * The SC520CDP is an evaluation board for the Elan SC520 processor available -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -84,88 +85,25 @@ - #define WINDOW_SIZE_1 0x00800000 - #define WINDOW_SIZE_2 0x00080000 - --static __u8 sc520cdp_read8(struct map_info *map, unsigned long ofs) --{ -- return readb(map->map_priv_1 + ofs); --} -- --static __u16 sc520cdp_read16(struct map_info *map, unsigned long ofs) --{ -- return readw(map->map_priv_1 + ofs); --} -- --static __u32 sc520cdp_read32(struct map_info *map, unsigned long ofs) --{ -- return readl(map->map_priv_1 + ofs); --} -- --static void sc520cdp_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); --} -- --static void sc520cdp_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, map->map_priv_1 + adr); --} -- --static void sc520cdp_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, map->map_priv_1 + adr); --} -- --static void sc520cdp_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- writel(d, map->map_priv_1 + adr); --} -- --static void sc520cdp_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio((void *)(map->map_priv_1 + to), from, len); --} - - static struct map_info sc520cdp_map[] = { - { -- name: "SC520CDP Flash Bank #0", -- size: WINDOW_SIZE_0, -- buswidth: 4, -- read8: sc520cdp_read8, -- read16: sc520cdp_read16, -- read32: sc520cdp_read32, -- copy_from: sc520cdp_copy_from, -- write8: sc520cdp_write8, -- write16: sc520cdp_write16, -- write32: sc520cdp_write32, -- copy_to: sc520cdp_copy_to, -- map_priv_2: WINDOW_ADDR_0 -+ .name = "SC520CDP Flash Bank #0", -+ .size = WINDOW_SIZE_0, -+ .buswidth = 4, -+ .phys = WINDOW_ADDR_0 - }, - { -- name: "SC520CDP Flash Bank #1", -- size: WINDOW_SIZE_1, -- buswidth: 4, -- read8: sc520cdp_read8, -- read16: sc520cdp_read16, -- read32: sc520cdp_read32, -- copy_from: sc520cdp_copy_from, -- write8: sc520cdp_write8, -- write16: sc520cdp_write16, -- write32: sc520cdp_write32, -- copy_to: sc520cdp_copy_to, -- map_priv_2: WINDOW_ADDR_1 -+ .name = "SC520CDP Flash Bank #1", -+ .size = WINDOW_SIZE_1, -+ .buswidth = 4, -+ .phys = WINDOW_ADDR_1 - }, - { -- name: "SC520CDP DIL Flash", -- size: WINDOW_SIZE_2, -- buswidth: 1, -- read8: sc520cdp_read8, -- read16: sc520cdp_read16, -- read32: sc520cdp_read32, -- copy_from: sc520cdp_copy_from, -- write8: sc520cdp_write8, -- write16: sc520cdp_write16, -- write32: sc520cdp_write32, -- copy_to: sc520cdp_copy_to, -- map_priv_2: WINDOW_ADDR_2 -+ .name = "SC520CDP DIL Flash", -+ .size = WINDOW_SIZE_2, -+ .buswidth = 1, -+ .phys = WINDOW_ADDR_2 - }, - }; - -@@ -255,9 +193,9 @@ - /* map in SC520's MMCR area */ - mmcr = (unsigned long *)ioremap_nocache(SC520_MMCR_BASE, SC520_MMCR_EXTENT); - if(!mmcr) { /* ioremap_nocache failed: skip the PAR reprogramming */ -- /* force map_priv_2 fields to BIOS defaults: */ -+ /* force physical address fields to BIOS defaults: */ - for(i = 0; i < NUM_FLASH_BANKS; i++) -- sc520cdp_map[i].map_priv_2 = par_table[i].default_address; -+ sc520cdp_map[i].phys = par_table[i].default_address; - return; - } - -@@ -282,7 +220,7 @@ - sc520cdp_map[i].name); - printk(KERN_NOTICE "Trying default address 0x%lx\n", - par_table[i].default_address); -- sc520cdp_map[i].map_priv_2 = par_table[i].default_address; -+ sc520cdp_map[i].phys = par_table[i].default_address; - } - } - iounmap((void *)mmcr); -@@ -300,13 +238,18 @@ - #endif - - for (i = 0; i < NUM_FLASH_BANKS; i++) { -- printk(KERN_NOTICE "SC520 CDP flash device: %lx at %lx\n", sc520cdp_map[i].size, sc520cdp_map[i].map_priv_2); -- sc520cdp_map[i].map_priv_1 = (unsigned long)ioremap_nocache(sc520cdp_map[i].map_priv_2, sc520cdp_map[i].size); -+ printk(KERN_NOTICE "SC520 CDP flash device: 0x%lx at 0x%lx\n", -+ sc520cdp_map[i].size, sc520cdp_map[i].phys); - -- if (!sc520cdp_map[i].map_priv_1) { -+ sc520cdp_map[i].virt = (unsigned long)ioremap_nocache(sc520cdp_map[i].phys, sc520cdp_map[i].size); -+ -+ if (!sc520cdp_map[i].virt) { - printk("Failed to ioremap_nocache\n"); - return -EIO; - } -+ -+ simple_map_init(&sc520cdp_map[i]); -+ - mymtd[i] = do_map_probe("cfi_probe", &sc520cdp_map[i]); - if(!mymtd[i]) - mymtd[i] = do_map_probe("jedec_probe", &sc520cdp_map[i]); -@@ -314,11 +257,11 @@ - mymtd[i] = do_map_probe("map_rom", &sc520cdp_map[i]); - - if (mymtd[i]) { -- mymtd[i]->module = THIS_MODULE; -+ mymtd[i]->owner = THIS_MODULE; - ++devices_found; - } - else { -- iounmap((void *)sc520cdp_map[i].map_priv_1); -+ iounmap((void *)sc520cdp_map[i].virt); - } - } - if(devices_found >= 2) { -@@ -346,9 +289,9 @@ - for (i = 0; i < NUM_FLASH_BANKS; i++) { - if (mymtd[i]) - map_destroy(mymtd[i]); -- if (sc520cdp_map[i].map_priv_1) { -- iounmap((void *)sc520cdp_map[i].map_priv_1); -- sc520cdp_map[i].map_priv_1 = 0; -+ if (sc520cdp_map[i].virt) { -+ iounmap((void *)sc520cdp_map[i].virt); -+ sc520cdp_map[i].virt = 0; - } - } - } -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/scb2_flash.c linux/drivers/mtd/maps/scb2_flash.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/scb2_flash.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/scb2_flash.c 2004-11-17 18:17:59.135299328 +0100 -@@ -1,6 +1,6 @@ - /* - * MTD map driver for BIOS Flash on Intel SCB2 boards -- * $Id$ -+ * $Id$ - * Copyright (C) 2002 Sun Microsystems, Inc. - * Tim Hockin - * -@@ -14,7 +14,7 @@ - * try to request it here, but if it fails, we carry on anyway. - * - * This is how the chip is attached, so said the schematic: -- * * a 4 MiB (32 Mb) 16 bit chip -+ * * a 4 MiB (32 Mib) 16 bit chip - * * a 1 MiB memory region - * * A20 and A21 pulled up - * * D8-D15 ignored -@@ -48,6 +48,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -60,65 +61,13 @@ - #define SCB2_ADDR 0xfff00000 - #define SCB2_WINDOW 0x00100000 - --static __u8 scb2_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --static __u16 scb2_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --static __u32 scb2_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --static void scb2_copy_from(struct map_info *map, void *to, -- unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --static void scb2_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --static void scb2_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --static void scb2_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --static void scb2_copy_to(struct map_info *map, unsigned long to, -- const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - static void *scb2_ioaddr; - static struct mtd_info *scb2_mtd; - struct map_info scb2_map = { -- name: "SCB2 BIOS Flash", -- size: 0, -- buswidth: 1, -- read8: scb2_read8, -- read16: scb2_read16, -- read32: scb2_read32, -- copy_from: scb2_copy_from, -- write8: scb2_write8, -- write16: scb2_write16, -- write32: scb2_write32, -- copy_to: scb2_copy_to, -+ .name = "SCB2 BIOS Flash", -+ .size = 0, -+ .buswidth = 1, - }; - static int region_fail; - -@@ -137,6 +86,8 @@ - return -1; - } - -+ /* I wasn't here. I didn't see. dwmw2. */ -+ - /* the chip is sometimes bigger than the map - what a waste */ - mtd->size = map->size; - -@@ -211,9 +162,12 @@ - return -ENOMEM; - } - -- scb2_map.map_priv_1 = (unsigned long)scb2_ioaddr; -+ scb2_map.phys = SCB2_ADDR; -+ scb2_map.virt = (unsigned long)scb2_ioaddr; - scb2_map.size = SCB2_WINDOW; - -+ simple_map_init(&scb2_map); -+ - /* try to find a chip */ - scb2_mtd = do_map_probe("cfi_probe", &scb2_map); - -@@ -225,7 +179,7 @@ - return -ENODEV; - } - -- scb2_mtd->module = THIS_MODULE; -+ scb2_mtd->owner = THIS_MODULE; - if (scb2_fixup_mtd(scb2_mtd) < 0) { - del_mtd_device(scb2_mtd); - map_destroy(scb2_mtd); -@@ -235,7 +189,7 @@ - return -ENODEV; - } - -- printk(KERN_NOTICE MODNAME ": chip size %x at offset %x\n", -+ printk(KERN_NOTICE MODNAME ": chip size 0x%x at offset 0x%x\n", - scb2_mtd->size, SCB2_WINDOW - scb2_mtd->size); - - add_mtd_device(scb2_mtd); -@@ -266,19 +220,19 @@ - - static struct pci_device_id scb2_flash_pci_ids[] __devinitdata = { - { -- vendor: PCI_VENDOR_ID_SERVERWORKS, -- device: PCI_DEVICE_ID_SERVERWORKS_CSB5, -- subvendor: PCI_ANY_ID, -- subdevice: PCI_ANY_ID -+ .vendor = PCI_VENDOR_ID_SERVERWORKS, -+ .device = PCI_DEVICE_ID_SERVERWORKS_CSB5, -+ .subvendor = PCI_ANY_ID, -+ .subdevice = PCI_ANY_ID - }, - { 0, } - }; - - static struct pci_driver scb2_flash_driver = { -- name: "Intel SCB2 BIOS Flash", -- id_table: scb2_flash_pci_ids, -- probe: scb2_flash_probe, -- remove: __devexit_p(scb2_flash_remove), -+ .name = "Intel SCB2 BIOS Flash", -+ .id_table = scb2_flash_pci_ids, -+ .probe = scb2_flash_probe, -+ .remove = __devexit_p(scb2_flash_remove), - }; - - static int __init -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/scx200_docflash.c linux/drivers/mtd/maps/scx200_docflash.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/scx200_docflash.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/scx200_docflash.c 2004-11-17 18:17:59.136299176 +0100 -@@ -2,7 +2,7 @@ - - Copyright (c) 2001,2002 Christer Weinigel - -- $Id$ -+ $Id$ - - National Semiconductor SCx200 flash mapped with DOCCS - */ -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -75,46 +76,9 @@ - #define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0])) - #endif - --static __u8 scx200_docflash_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --static __u16 scx200_docflash_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --static void scx200_docflash_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --static void scx200_docflash_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --static void scx200_docflash_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --static void scx200_docflash_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - static struct map_info scx200_docflash_map = { - .name = "NatSemi SCx200 DOCCS Flash", -- .read8 = scx200_docflash_read8, -- .read16 = scx200_docflash_read16, -- .copy_from = scx200_docflash_copy_from, -- .write8 = scx200_docflash_write8, -- .write16 = scx200_docflash_write16, -- .copy_to = scx200_docflash_copy_to - }; - - int __init init_scx200_docflash(void) -@@ -213,8 +177,11 @@ - else - scx200_docflash_map.buswidth = 2; - -- scx200_docflash_map.map_priv_1 = (unsigned long)ioremap(docmem.start, scx200_docflash_map.size); -- if (!scx200_docflash_map.map_priv_1) { -+ simple_map_init(&scx200_docflash_map); -+ -+ scx200_docflash_map.phys = docmem.start; -+ scx200_docflash_map.virt = (unsigned long)ioremap(docmem.start, scx200_docflash_map.size); -+ if (!scx200_docflash_map.virt) { - printk(KERN_ERR NAME ": failed to ioremap the flash\n"); - release_resource(&docmem); - return -EIO; -@@ -223,7 +190,7 @@ - mymtd = do_map_probe(flashtype, &scx200_docflash_map); - if (!mymtd) { - printk(KERN_ERR NAME ": unable to detect flash\n"); -- iounmap((void *)scx200_docflash_map.map_priv_1); -+ iounmap((void *)scx200_docflash_map.virt); - release_resource(&docmem); - return -ENXIO; - } -@@ -231,7 +198,7 @@ - if (size < mymtd->size) - printk(KERN_WARNING NAME ": warning, flash mapping is smaller than flash size\n"); - -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - #if PARTITION - partition_info[3].offset = mymtd->size-partition_info[3].size; -@@ -253,8 +220,8 @@ - #endif - map_destroy(mymtd); - } -- if (scx200_docflash_map.map_priv_1) { -- iounmap((void *)scx200_docflash_map.map_priv_1); -+ if (scx200_docflash_map.virt) { -+ iounmap((void *)scx200_docflash_map.virt); - release_resource(&docmem); - } - } -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/solutionengine.c linux/drivers/mtd/maps/solutionengine.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/solutionengine.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/solutionengine.c 2004-11-17 18:17:59.137299024 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Flash and EPROM on Hitachi Solution Engine and similar boards. - * -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -18,60 +19,39 @@ - #include - - --extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts); -- --__u32 soleng_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void soleng_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void soleng_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- -- - static struct mtd_info *flash_mtd; - static struct mtd_info *eprom_mtd; - - static struct mtd_partition *parsed_parts; - - struct map_info soleng_eprom_map = { -- name: "Solution Engine EPROM", -- size: 0x400000, -- buswidth: 4, -- copy_from: soleng_copy_from, -+ .name = "Solution Engine EPROM", -+ .size = 0x400000, -+ .buswidth = 4, - }; - - struct map_info soleng_flash_map = { -- name: "Solution Engine FLASH", -- size: 0x400000, -- buswidth: 4, -- read32: soleng_read32, -- copy_from: soleng_copy_from, -- write32: soleng_write32, -+ .name = "Solution Engine FLASH", -+ .size = 0x400000, -+ .buswidth = 4, - }; - -+static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; -+ - #ifdef CONFIG_MTD_SUPERH_RESERVE - static struct mtd_partition superh_se_partitions[] = { - /* Reserved for boot code, read-only */ - { -- name: "flash_boot", -- offset: 0x00000000, -- size: CONFIG_MTD_SUPERH_RESERVE, -- mask_flags: MTD_WRITEABLE, -+ .name = "flash_boot", -+ .offset = 0x00000000, -+ .size = CONFIG_MTD_SUPERH_RESERVE, -+ .mask_flags = MTD_WRITEABLE, - }, - /* All else is writable (e.g. JFFS) */ - { -- name: "Flash FS", -- offset: MTDPART_OFS_NXTBLK, -- size: MTDPART_SIZ_FULL, -+ .name = "Flash FS", -+ .offset = MTDPART_OFS_NXTBLK, -+ .size = MTDPART_SIZ_FULL, - } - }; - #endif /* CONFIG_MTD_SUPERH_RESERVE */ -@@ -81,16 +61,22 @@ - int nr_parts = 0; - - /* First probe at offset 0 */ -- soleng_flash_map.map_priv_1 = P2SEGADDR(0); -- soleng_eprom_map.map_priv_1 = P1SEGADDR(0x01000000); -+ soleng_flash_map.phys = 0; -+ soleng_flash_map.virt = P2SEGADDR(0); -+ soleng_eprom_map.phys = 0x01000000; -+ soleng_eprom_map.virt = P1SEGADDR(0x01000000); -+ simple_map_init(&soleng_eprom_map); -+ simple_map_init(&soleng_flash_map); - - printk(KERN_NOTICE "Probing for flash chips at 0x00000000:\n"); - flash_mtd = do_map_probe("cfi_probe", &soleng_flash_map); - if (!flash_mtd) { - /* Not there. Try swapping */ - printk(KERN_NOTICE "Probing for flash chips at 0x01000000:\n"); -- soleng_flash_map.map_priv_1 = P2SEGADDR(0x01000000); -- soleng_eprom_map.map_priv_1 = P1SEGADDR(0); -+ soleng_flash_map.phys = 0x01000000; -+ soleng_flash_map.virt = P2SEGADDR(0x01000000); -+ soleng_eprom_map.phys = 0; -+ soleng_eprom_map.virt = P1SEGADDR(0); - flash_mtd = do_map_probe("cfi_probe", &soleng_flash_map); - if (!flash_mtd) { - /* Eep. */ -@@ -99,25 +85,20 @@ - } - } - printk(KERN_NOTICE "Solution Engine: Flash at 0x%08lx, EPROM at 0x%08lx\n", -- soleng_flash_map.map_priv_1 & 0x1fffffff, -- soleng_eprom_map.map_priv_1 & 0x1fffffff); -- flash_mtd->module = THIS_MODULE; -+ soleng_flash_map.phys & 0x1fffffff, -+ soleng_eprom_map.phys & 0x1fffffff); -+ flash_mtd->owner = THIS_MODULE; - - eprom_mtd = do_map_probe("map_rom", &soleng_eprom_map); - if (eprom_mtd) { -- eprom_mtd->module = THIS_MODULE; -+ eprom_mtd->owner = THIS_MODULE; - add_mtd_device(eprom_mtd); - } - --#ifdef CONFIG_MTD_REDBOOT_PARTS -- nr_parts = parse_redboot_partitions(flash_mtd, &parsed_parts); -- if (nr_parts > 0) -- printk(KERN_NOTICE "Found RedBoot partition table.\n"); -- else if (nr_parts < 0) -- printk(KERN_NOTICE "Error looking for RedBoot partitions.\n"); --#endif /* CONFIG_MTD_REDBOOT_PARTS */ -+ nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0); -+ - #if CONFIG_MTD_SUPERH_RESERVE -- if (nr_parts == 0) { -+ if (nr_parts <= 0) { - printk(KERN_NOTICE "Using configured partition at 0x%08x.\n", - CONFIG_MTD_SUPERH_RESERVE); - parsed_parts = superh_se_partitions; -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/sun_uflash.c linux/drivers/mtd/maps/sun_uflash.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/sun_uflash.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/sun_uflash.c 2004-11-17 18:17:59.139298720 +0100 -@@ -1,4 +1,4 @@ --/* $Id$ -+/* $Id$ - * - * sun_uflash - Driver implementation for user-programmable flash - * present on many Sun Microsystems SME boardsets. -@@ -48,60 +48,11 @@ - struct list_head list; - }; - --__u8 uflash_read8(struct map_info *map, unsigned long ofs) --{ -- return(__raw_readb(map->map_priv_1 + ofs)); --} -- --__u16 uflash_read16(struct map_info *map, unsigned long ofs) --{ -- return(__raw_readw(map->map_priv_1 + ofs)); --} -- --__u32 uflash_read32(struct map_info *map, unsigned long ofs) --{ -- return(__raw_readl(map->map_priv_1 + ofs)); --} -- --void uflash_copy_from(struct map_info *map, void *to, unsigned long from, -- ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void uflash_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); --} -- --void uflash_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); --} -- --void uflash_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); --} -- --void uflash_copy_to(struct map_info *map, unsigned long to, const void *from, -- ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - struct map_info uflash_map_templ = { -- name: "SUNW,???-????", -- size: UFLASH_WINDOW_SIZE, -- buswidth: UFLASH_BUSWIDTH, -- read8: uflash_read8, -- read16: uflash_read16, -- read32: uflash_read32, -- copy_from: uflash_copy_from, -- write8: uflash_write8, -- write16: uflash_write16, -- write32: uflash_write32, -- copy_to: uflash_copy_to -+ .name = "SUNW,???-????", -+ .size = UFLASH_WINDOW_SIZE, -+ .buswidth = UFLASH_BUSWIDTH, - }; - - int uflash_devinit(struct linux_ebus_device* edev) -@@ -145,20 +96,22 @@ - if(0 != pdev->name && 0 < strlen(pdev->name)) { - pdev->map.name = pdev->name; - } -- -- pdev->map.map_priv_1 = -+ pdev->phys = edev->resource[0].start; -+ pdev->virt = - (unsigned long)ioremap_nocache(edev->resource[0].start, pdev->map.size); -- if(0 == pdev->map.map_priv_1) { -+ if(0 == pdev->map.virt) { - printk("%s: failed to map device\n", __FUNCTION__); - kfree(pdev->name); - kfree(pdev); - return(-1); - } - -+ simple_map_init(&pdev->map); -+ - /* MTD registration */ - pdev->mtd = do_map_probe("cfi_probe", &pdev->map); - if(0 == pdev->mtd) { -- iounmap((void *)pdev->map.map_priv_1); -+ iounmap((void *)pdev->map.virt); - kfree(pdev->name); - kfree(pdev); - return(-ENXIO); -@@ -166,7 +119,7 @@ - - list_add(&pdev->list, &device_list); - -- pdev->mtd->module = THIS_MODULE; -+ pdev->mtd->owner = THIS_MODULE; - - add_mtd_device(pdev->mtd); - return(0); -@@ -211,9 +164,9 @@ - del_mtd_device(udev->mtd); - map_destroy(udev->mtd); - } -- if(0 != udev->map.map_priv_1) { -- iounmap((void*)udev->map.map_priv_1); -- udev->map.map_priv_1 = 0; -+ if(0 != udev->map.virt) { -+ iounmap((void*)udev->map.virt); -+ udev->map.virt = 0; - } - if(0 != udev->name) { - kfree(udev->name); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/tqm8xxl.c linux/drivers/mtd/maps/tqm8xxl.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/tqm8xxl.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/tqm8xxl.c 2004-11-17 18:17:59.140298568 +0100 -@@ -2,7 +2,7 @@ - * Handle mapping of the flash memory access routines - * on TQM8xxL based devices. - * -- * $Id$ -+ * $Id$ - * - * based on rpxlite.c - * -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -51,46 +52,6 @@ - static unsigned long num_banks; - static unsigned long start_scan_addr; - --__u8 tqm8xxl_read8(struct map_info *map, unsigned long ofs) --{ -- return *((__u8 *)(map->map_priv_1 + ofs)); --} -- --__u16 tqm8xxl_read16(struct map_info *map, unsigned long ofs) --{ -- return *((__u16 *)(map->map_priv_1 + ofs)); --} -- --__u32 tqm8xxl_read32(struct map_info *map, unsigned long ofs) --{ -- return *((__u32 *)(map->map_priv_1 + ofs)); --} -- --void tqm8xxl_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); --} -- --void tqm8xxl_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- *((__u8 *)(map->map_priv_1 + adr)) = d; --} -- --void tqm8xxl_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- *((__u16 *)( map->map_priv_1 + adr)) = d; --} -- --void tqm8xxl_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- *((__u32 *)(map->map_priv_1 + adr)) = d; --} -- --void tqm8xxl_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio((void *)(map->map_priv_1 + to), from, len); --} -- - /* - * Here are partition information for all known TQM8xxL series devices. - * See include/linux/mtd/partitions.h for definition of the mtd_partition -@@ -107,50 +68,48 @@ - static unsigned long tqm8xxl_max_flash_size = 0x00800000; - - /* partition definition for first flash bank -- * also ref. to "drivers\char\flash_config.c" -+ * (cf. "drivers/char/flash_config.c") - */ - static struct mtd_partition tqm8xxl_partitions[] = { - { -- name: "ppcboot", -- offset: 0x00000000, -- size: 0x00020000, /* 128KB */ -- mask_flags: MTD_WRITEABLE, /* force read-only */ -+ .name = "ppcboot", -+ .offset = 0x00000000, -+ .size = 0x00020000, /* 128KB */ -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, - { -- name: "kernel", /* default kernel image */ -- offset: 0x00020000, -- size: 0x000e0000, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -+ .name = "kernel", /* default kernel image */ -+ .offset = 0x00020000, -+ .size = 0x000e0000, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, - { -- name: "user", -- offset: 0x00100000, -- size: 0x00100000, -+ .name = "user", -+ .offset = 0x00100000, -+ .size = 0x00100000, - }, - { -- name: "initrd", -- offset: 0x00200000, -- size: 0x00200000, -+ .name = "initrd", -+ .offset = 0x00200000, -+ .size = 0x00200000, - } - }; --/* partition definition for second flahs bank */ -+/* partition definition for second flash bank */ - static struct mtd_partition tqm8xxl_fs_partitions[] = { - { -- name: "cramfs", -- offset: 0x00000000, -- size: 0x00200000, -+ .name = "cramfs", -+ .offset = 0x00000000, -+ .size = 0x00200000, - }, - { -- name: "jffs", -- offset: 0x00200000, -- size: 0x00200000, -- //size: MTDPART_SIZ_FULL, -+ .name = "jffs", -+ .offset = 0x00200000, -+ .size = 0x00200000, -+ .//size = MTDPART_SIZ_FULL, - } - }; - #endif - --#define NB_OF(x) (sizeof(x)/sizeof(x[0])) -- - int __init init_tqm_mtd(void) - { - int idx = 0, ret = 0; -@@ -160,67 +119,73 @@ - - flash_addr = bd->bi_flashstart; - flash_size = bd->bi_flashsize; -- //request maximum flash size address spzce -+ -+ //request maximum flash size address space - start_scan_addr = (unsigned long)ioremap(flash_addr, flash_size); - if (!start_scan_addr) { -- //printk("%s:Failed to ioremap address:0x%x\n", __FUNCTION__, FLASH_ADDR); -- printk("%s:Failed to ioremap address:0x%x\n", __FUNCTION__, flash_addr); -+ printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __FUNCTION__, flash_addr); - return -EIO; - } -- for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) -- { -+ -+ for (idx = 0 ; idx < FLASH_BANK_MAX ; idx++) { - if(mtd_size >= flash_size) - break; - -- printk("%s: chip probing count %d\n", __FUNCTION__, idx); -+ printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx); - - map_banks[idx] = (struct map_info *)kmalloc(sizeof(struct map_info), GFP_KERNEL); -- if(map_banks[idx] == NULL) -- { -- //return -ENOMEM; -+ if(map_banks[idx] == NULL) { - ret = -ENOMEM; -+ /* FIXME: What if some MTD devices were probed already? */ - goto error_mem; - } -+ - memset((void *)map_banks[idx], 0, sizeof(struct map_info)); - map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL); -- if(map_banks[idx]->name == NULL) -- { -- //return -ENOMEM; -+ -+ if (!map_banks[idx]->name) { - ret = -ENOMEM; -+ /* FIXME: What if some MTD devices were probed already? */ - goto error_mem; - } -- memset((void *)map_banks[idx]->name, 0, 16); -- - sprintf(map_banks[idx]->name, "TQM8xxL%d", idx); -+ - map_banks[idx]->size = flash_size; - map_banks[idx]->buswidth = 4; -- map_banks[idx]->read8 = tqm8xxl_read8; -- map_banks[idx]->read16 = tqm8xxl_read16; -- map_banks[idx]->read32 = tqm8xxl_read32; -- map_banks[idx]->copy_from = tqm8xxl_copy_from; -- map_banks[idx]->write8 = tqm8xxl_write8; -- map_banks[idx]->write16 = tqm8xxl_write16; -- map_banks[idx]->write32 = tqm8xxl_write32; -- map_banks[idx]->copy_to = tqm8xxl_copy_to; -+ -+ simple_map_init(map_banks[idx]); -+ -+ map_banks[idx]->virt = start_scan_addr; -+ map_banks[idx]->phys = flash_addr; -+ /* FIXME: This looks utterly bogus, but I'm trying to -+ preserve the behaviour of the original (shown here)... -+ - map_banks[idx]->map_priv_1 = - start_scan_addr + ((idx > 0) ? - (mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0); -+ */ -+ -+ if (idx && mtd_banks[idx-1]) { -+ map_banks[idx]->virt += mtd_banks[idx-1]->size; -+ map_banks[idx]->phys += mtd_banks[idx-1]->size; -+ } -+ - //start to probe flash chips - mtd_banks[idx] = do_map_probe("cfi_probe", map_banks[idx]); -- if(mtd_banks[idx]) -- { -- mtd_banks[idx]->module = THIS_MODULE; -+ -+ if (mtd_banks[idx]) { -+ mtd_banks[idx]->owner = THIS_MODULE; - mtd_size += mtd_banks[idx]->size; - num_banks++; -- printk("%s: bank%d, name:%s, size:%dbytes \n", __FUNCTION__, num_banks, -+ -+ printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __FUNCTION__, num_banks, - mtd_banks[idx]->name, mtd_banks[idx]->size); - } - } - - /* no supported flash chips found */ -- if(!num_banks) -- { -- printk("TQM8xxL: No support flash chips found!\n"); -+ if (!num_banks) { -+ printk(KERN_NOTICE "TQM8xxL: No support flash chips found!\n"); - ret = -ENXIO; - goto error_mem; - } -@@ -231,12 +196,13 @@ - */ - part_banks[0].mtd_part = tqm8xxl_partitions; - part_banks[0].type = "Static image"; -- part_banks[0].nums = NB_OF(tqm8xxl_partitions); -+ part_banks[0].nums = ARRAY_SIZE(tqm8xxl_partitions); -+ - part_banks[1].mtd_part = tqm8xxl_fs_partitions; - part_banks[1].type = "Static file system"; -- part_banks[1].nums = NB_OF(tqm8xxl_fs_partitions); -- for(idx = 0; idx < num_banks ; idx++) -- { -+ part_banks[1].nums = ARRAY_SIZE(tqm8xxl_fs_partitions); -+ -+ for(idx = 0; idx < num_banks ; idx++) { - if (part_banks[idx].nums == 0) { - printk(KERN_NOTICE "TQM flash%d: no partition info available, registering whole flash at once\n", idx); - add_mtd_device(mtd_banks[idx]); -@@ -254,12 +220,9 @@ - #endif - return 0; - error_mem: -- for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) -- { -- if(map_banks[idx] != NULL) -- { -- if(map_banks[idx]->name != NULL) -- { -+ for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) { -+ if(map_banks[idx] != NULL) { -+ if(map_banks[idx]->name != NULL) { - kfree(map_banks[idx]->name); - map_banks[idx]->name = NULL; - } -@@ -267,18 +230,15 @@ - map_banks[idx] = NULL; - } - } -- //return -ENOMEM; - error: - iounmap((void *)start_scan_addr); -- //return -ENXIO; - return ret; - } - - static void __exit cleanup_tqm_mtd(void) - { - unsigned int idx = 0; -- for(idx = 0 ; idx < num_banks ; idx++) -- { -+ for(idx = 0 ; idx < num_banks ; idx++) { - /* destroy mtd_info previously allocated */ - if (mtd_banks[idx]) { - del_mtd_partitions(mtd_banks[idx]); -@@ -288,6 +248,7 @@ - kfree(map_banks[idx]->name); - kfree(map_banks[idx]); - } -+ - if (start_scan_addr) { - iounmap((void *)start_scan_addr); - start_scan_addr = 0; -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/tsunami_flash.c linux/drivers/mtd/maps/tsunami_flash.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/tsunami_flash.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/tsunami_flash.c 2004-11-17 18:17:59.141298416 +0100 -@@ -2,11 +2,13 @@ - * tsunami_flash.c - * - * flash chip on alpha ds10... -- * $Id$ -+ * $Id$ - */ - #include - #include -+#include - #include -+#include - - #define FLASH_ENABLE_PORT 0x00C00001 - #define FLASH_ENABLE_BYTE 0x01 -@@ -58,18 +60,12 @@ - static struct map_info tsunami_flash_map = { - .name = "flash chip on the Tsunami TIG bus", - .size = MAX_TIG_FLASH_SIZE, -+ .phys = NO_XIP; - .buswidth = 1, - .read8 = tsunami_flash_read8, -- .read16 = 0, -- .read32 = 0, - .copy_from = tsunami_flash_copy_from, - .write8 = tsunami_flash_write8, -- .write16 = 0, -- .write32 = 0, - .copy_to = tsunami_flash_copy_to, -- .set_vpp = 0, -- .map_priv_1 = 0, -- - }; - - static struct mtd_info *tsunami_flash_mtd; -@@ -99,7 +95,7 @@ - tsunami_flash_mtd = do_map_probe(*type, &tsunami_flash_map); - } - if (tsunami_flash_mtd) { -- tsunami_flash_mtd->module = THIS_MODULE; -+ tsunami_flash_mtd->owner = THIS_MODULE; - add_mtd_device(tsunami_flash_mtd); - return 0; - } -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/uclinux.c linux/drivers/mtd/maps/uclinux.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/uclinux.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/uclinux.c 2004-11-17 18:17:59.142298264 +0100 -@@ -5,7 +5,7 @@ - * - * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) - * -- * $Id$ -+ * $Id$ - */ - - /****************************************************************************/ -@@ -24,58 +24,11 @@ - - /****************************************************************************/ - --__u8 uclinux_read8(struct map_info *map, unsigned long ofs) --{ -- return(*((__u8 *) (map->map_priv_1 + ofs))); --} -- --__u16 uclinux_read16(struct map_info *map, unsigned long ofs) --{ -- return(*((__u16 *) (map->map_priv_1 + ofs))); --} -- --__u32 uclinux_read32(struct map_info *map, unsigned long ofs) --{ -- return(*((__u32 *) (map->map_priv_1 + ofs))); --} -- --void uclinux_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy(to, (void *)(map->map_priv_1 + from), len); --} -- --void uclinux_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- *((__u8 *) (map->map_priv_1 + adr)) = d; --} -- --void uclinux_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- *((__u16 *) (map->map_priv_1 + adr)) = d; --} -- --void uclinux_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- *((__u32 *) (map->map_priv_1 + adr)) = d; --} -- --void uclinux_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy((void *) (map->map_priv_1 + to), from, len); --} - - /****************************************************************************/ - - struct map_info uclinux_ram_map = { -- name: "RAM", -- read8: uclinux_read8, -- read16: uclinux_read16, -- read32: uclinux_read32, -- copy_from: uclinux_copy_from, -- write8: uclinux_write8, -- write16: uclinux_write16, -- write32: uclinux_write32, -- copy_to: uclinux_copy_to, -+ .name = "RAM", - }; - - struct mtd_info *uclinux_ram_mtdinfo; -@@ -83,7 +36,7 @@ - /****************************************************************************/ - - struct mtd_partition uclinux_romfs[] = { -- { name: "ROMfs", offset: 0 } -+ { .name = "ROMfs" } - }; - - #define NUM_PARTITIONS (sizeof(uclinux_romfs) / sizeof(uclinux_romfs[0])) -@@ -94,7 +47,7 @@ - size_t *retlen, u_char **mtdbuf) - { - struct map_info *map = (struct map_info *) mtd->priv; -- *mtdbuf = (u_char *) (map->map_priv_1 + ((int) from)); -+ *mtdbuf = (u_char *) (map->virt + ((int) from)); - *retlen = len; - return(0); - } -@@ -108,29 +61,31 @@ - extern char _ebss; - - mapp = &uclinux_ram_map; -- mapp->map_priv_2 = (unsigned long) &_ebss; -+ mapp->phys = (unsigned long) &_ebss; - mapp->size = PAGE_ALIGN(*((unsigned long *)((&_ebss) + 8))); - mapp->buswidth = 4; - - printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n", - (int) mapp->map_priv_2, (int) mapp->size); - -- mapp->map_priv_1 = (unsigned long) -- ioremap_nocache(mapp->map_priv_2, mapp->size); -+ mapp->virt = (unsigned long) -+ ioremap_nocache(mapp->phys, mapp->size); - -- if (mapp->map_priv_1 == 0) { -+ if (mapp->virt == 0) { - printk("uclinux[mtd]: ioremap_nocache() failed\n"); - return(-EIO); - } - -+ simple_map_init(mapp); -+ - mtd = do_map_probe("map_ram", mapp); - if (!mtd) { - printk("uclinux[mtd]: failed to find a mapping?\n"); -- iounmap((void *) mapp->map_priv_1); -+ iounmap((void *) mapp->virt); - return(-ENXIO); - } - -- mtd->module = THIS_MODULE; -+ mtd->owner = THIS_MODULE; - mtd->point = uclinux_point; - mtd->priv = mapp; - -@@ -155,8 +110,8 @@ - uclinux_ram_mtdinfo = NULL; - } - if (uclinux_ram_map.map_priv_1) { -- iounmap((void *) uclinux_ram_map.map_priv_1); -- uclinux_ram_map.map_priv_1 = 0; -+ iounmap((void *) uclinux_ram_map.virt); -+ uclinux_ram_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/maps/vmax301.c linux/drivers/mtd/maps/vmax301.c ---- linux-mips-2.4.24-pre2/drivers/mtd/maps/vmax301.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/maps/vmax301.c 2004-11-17 18:17:59.144297960 +0100 -@@ -1,4 +1,4 @@ --// $Id$ -+// $Id$ - /* ###################################################################### - - Tempustech VMAX SBC301 MTD Driver. -@@ -24,6 +24,7 @@ - #include - - #include -+#include - - - #define WINDOW_START 0xd8000 -@@ -142,34 +143,36 @@ - - static struct map_info vmax_map[2] = { - { -- name: "VMAX301 Internal Flash", -- size: 3*2*1024*1024, -- buswidth: 1, -- read8: vmax301_read8, -- read16: vmax301_read16, -- read32: vmax301_read32, -- copy_from: vmax301_copy_from, -- write8: vmax301_write8, -- write16: vmax301_write16, -- write32: vmax301_write32, -- copy_to: vmax301_copy_to, -- map_priv_1: WINDOW_START + WINDOW_LENGTH, -- map_priv_2: 0xFFFFFFFF -+ .name = "VMAX301 Internal Flash", -+ .phys = NO_XIP, -+ .size = 3*2*1024*1024, -+ .buswidth = 1, -+ .read8 = vmax301_read8, -+ .read16 = vmax301_read16, -+ .read32 = vmax301_read32, -+ .copy_from = vmax301_copy_from, -+ .write8 = vmax301_write8, -+ .write16 = vmax301_write16, -+ .write32 = vmax301_write32, -+ .copy_to = vmax301_copy_to, -+ .map_priv_1 = WINDOW_START + WINDOW_LENGTH, -+ .map_priv_2 = 0xFFFFFFFF - }, - { -- name: "VMAX301 Socket", -- size: 0, -- buswidth: 1, -- read8: vmax301_read8, -- read16: vmax301_read16, -- read32: vmax301_read32, -- copy_from: vmax301_copy_from, -- write8: vmax301_write8, -- write16: vmax301_write16, -- write32: vmax301_write32, -- copy_to: vmax301_copy_to, -- map_priv_1: WINDOW_START + (3*WINDOW_LENGTH), -- map_priv_2: 0xFFFFFFFF -+ .name = "VMAX301 Socket", -+ .phys = NO_XIP, -+ .size = 0, -+ .buswidth = 1, -+ .read8 = vmax301_read8, -+ .read16 = vmax301_read16, -+ .read32 = vmax301_read32, -+ .copy_from = vmax301_copy_from, -+ .write8 = vmax301_write8, -+ .write16 = vmax301_write16, -+ .write32 = vmax301_write32, -+ .copy_to = vmax301_copy_to, -+ .map_priv_1 = WINDOW_START + (3*WINDOW_LENGTH), -+ .map_priv_2 = 0xFFFFFFFF - } - }; - -@@ -206,8 +209,8 @@ - address of the first half, because it's used more - often. - */ -- vmax_map[0].map_priv_1 = iomapadr + WINDOW_START; -- vmax_map[1].map_priv_1 = iomapadr + (3*WINDOW_START); -+ vmax_map[0].map_priv_2 = iomapadr + WINDOW_START; -+ vmax_map[1].map_priv_2 = iomapadr + (3*WINDOW_START); - - for (i=0; i<2; i++) { - vmax_mtd[i] = do_map_probe("cfi_probe", &vmax_map[i]); -@@ -218,7 +221,7 @@ - if (!vmax_mtd[i]) - vmax_mtd[i] = do_map_probe("map_rom", &vmax_map[i]); - if (vmax_mtd[i]) { -- vmax_mtd[i]->module = THIS_MODULE; -+ vmax_mtd[i]->owner = THIS_MODULE; - add_mtd_device(vmax_mtd[i]); - } - } -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/mtd_blkdevs-24.c linux/drivers/mtd/mtd_blkdevs-24.c ---- linux-mips-2.4.24-pre2/drivers/mtd/mtd_blkdevs-24.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/mtd_blkdevs-24.c 2004-11-17 18:17:58.000000000 +0100 -@@ -0,0 +1,699 @@ -+/* -+ * $Id$ -+ * -+ * (C) 2003 David Woodhouse -+ * -+ * Interface to Linux 2.4 block layer for MTD 'translation layers'. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static LIST_HEAD(blktrans_majors); -+ -+extern struct semaphore mtd_table_mutex; -+extern struct mtd_info *mtd_table[]; -+ -+struct mtd_blkcore_priv { -+ devfs_handle_t devfs_dir_handle; -+ int blksizes[256]; -+ int sizes[256]; -+ struct hd_struct part_table[256]; -+ struct gendisk gd; -+ spinlock_t devs_lock; /* See comment in _request function */ -+ struct completion thread_dead; -+ int exiting; -+ wait_queue_head_t thread_wq; -+}; -+ -+static inline struct mtd_blktrans_dev *tr_get_dev(struct mtd_blktrans_ops *tr, -+ int devnum) -+{ -+ struct list_head *this; -+ struct mtd_blktrans_dev *d; -+ -+ list_for_each(this, &tr->devs) { -+ d = list_entry(this, struct mtd_blktrans_dev, list); -+ -+ if (d->devnum == devnum) -+ return d; -+ } -+ return NULL; -+} -+ -+static inline struct mtd_blktrans_ops *get_tr(int major) -+{ -+ struct list_head *this; -+ struct mtd_blktrans_ops *t; -+ -+ list_for_each(this, &blktrans_majors) { -+ t = list_entry(this, struct mtd_blktrans_ops, list); -+ -+ if (t->major == major) -+ return t; -+ } -+ return NULL; -+} -+ -+static int do_blktrans_request(struct mtd_blktrans_ops *tr, -+ struct mtd_blktrans_dev *dev, -+ struct request *req) -+{ -+ unsigned long block, nsect; -+ char *buf; -+ int minor; -+ -+ minor = MINOR(req->rq_dev); -+ block = req->sector; -+ nsect = req->current_nr_sectors; -+ buf = req->buffer; -+ -+ if (block + nsect > tr->blkcore_priv->part_table[minor].nr_sects) { -+ printk(KERN_WARNING "Access beyond end of device.\n"); -+ return 0; -+ } -+ block += tr->blkcore_priv->part_table[minor].start_sect; -+ -+ switch(req->cmd) { -+ case READ: -+ for (; nsect > 0; nsect--, block++, buf += 512) -+ if (tr->readsect(dev, block, buf)) -+ return 0; -+ return 1; -+ -+ case WRITE: -+ if (!tr->writesect) -+ return 0; -+ -+ for (; nsect > 0; nsect--, block++, buf += 512) -+ if (tr->writesect(dev, block, buf)) -+ return 0; -+ return 1; -+ -+ default: -+ printk(KERN_NOTICE "Unknown request cmd %d\n", req->cmd); -+ return 0; -+ } -+} -+ -+static int mtd_blktrans_thread(void *arg) -+{ -+ struct mtd_blktrans_ops *tr = arg; -+ struct request_queue *rq = BLK_DEFAULT_QUEUE(tr->major); -+ -+ /* we might get involved when memory gets low, so use PF_MEMALLOC */ -+ current->flags |= PF_MEMALLOC; -+ -+ snprintf(current->comm, sizeof(current->comm), "%sd", tr->name); -+ -+ /* daemonize() doesn't do this for us since some kernel threads -+ actually want to deal with signals. We can't just call -+ exit_sighand() since that'll cause an oops when we finally -+ do exit. */ -+ -+#ifndef __rh_config_h__ /* HAVE_NPTL */ -+ spin_lock_irq(¤t->sigmask_lock); -+ sigfillset(¤t->blocked); -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+#else -+ spin_lock_irq(¤t->sighand->siglock); -+ sigfillset(¤t->blocked); -+ recalc_sigpending(); -+ spin_unlock_irq(¤t->sighand->siglock); -+#endif -+ daemonize(); -+ -+ while (!tr->blkcore_priv->exiting) { -+ struct request *req; -+ struct mtd_blktrans_dev *dev; -+ int devnum; -+ int res = 0; -+ DECLARE_WAITQUEUE(wait, current); -+ -+ spin_lock_irq(&io_request_lock); -+ -+ if (list_empty(&rq->queue_head)) { -+ -+ add_wait_queue(&tr->blkcore_priv->thread_wq, &wait); -+ set_current_state(TASK_INTERRUPTIBLE); -+ -+ spin_unlock_irq(&io_request_lock); -+ -+ schedule(); -+ remove_wait_queue(&tr->blkcore_priv->thread_wq, &wait); -+ -+ continue; -+ } -+ -+ req = blkdev_entry_next_request(&rq->queue_head); -+ -+ devnum = MINOR(req->rq_dev) >> tr->part_bits; -+ -+ /* The ll_rw_blk code knows not to touch the request -+ at the head of the queue */ -+ spin_unlock_irq(&io_request_lock); -+ -+ /* FIXME: Where can we store the dev, on which -+ we already have a refcount anyway? We need to -+ lock against concurrent addition/removal of devices, -+ but if we use the mtd_table_mutex we deadlock when -+ grok_partitions is called from the registration -+ callbacks. */ -+ spin_lock(&tr->blkcore_priv->devs_lock); -+ dev = tr_get_dev(tr, devnum); -+ spin_unlock(&tr->blkcore_priv->devs_lock); -+ -+ BUG_ON(!dev); -+ -+ /* Ensure serialisation of requests */ -+ down(&dev->sem); -+ -+ res = do_blktrans_request(tr, dev, req); -+ up(&dev->sem); -+ -+ if (!end_that_request_first(req, res, tr->name)) { -+ spin_lock_irq(&io_request_lock); -+ blkdev_dequeue_request(req); -+ end_that_request_last(req); -+ spin_unlock_irq(&io_request_lock); -+ } -+ } -+ complete_and_exit(&tr->blkcore_priv->thread_dead, 0); -+} -+ -+static void mtd_blktrans_request(struct request_queue *rq) -+{ -+ struct mtd_blktrans_ops *tr = rq->queuedata; -+ wake_up(&tr->blkcore_priv->thread_wq); -+} -+ -+int blktrans_open(struct inode *i, struct file *f) -+{ -+ struct mtd_blktrans_ops *tr = NULL; -+ struct mtd_blktrans_dev *dev = NULL; -+ int major_nr = MAJOR(i->i_rdev); -+ int minor_nr = MINOR(i->i_rdev); -+ int devnum; -+ int ret = -ENODEV; -+ -+ if (is_read_only(i->i_rdev) && (f->f_mode & FMODE_WRITE)) -+ return -EROFS; -+ -+ down(&mtd_table_mutex); -+ -+ tr = get_tr(major_nr); -+ -+ if (!tr) -+ goto out; -+ -+ devnum = minor_nr >> tr->part_bits; -+ -+ dev = tr_get_dev(tr, devnum); -+ -+ if (!dev) -+ goto out; -+ -+ if (!tr->blkcore_priv->part_table[minor_nr].nr_sects) { -+ ret = -ENODEV; -+ goto out; -+ } -+ -+ if (!try_inc_mod_count(dev->mtd->owner)) -+ goto out; -+ -+ if (!try_inc_mod_count(tr->owner)) -+ goto out_tr; -+ -+ dev->mtd->usecount++; -+ -+ ret = 0; -+ if (tr->open && (ret = tr->open(dev))) { -+ dev->mtd->usecount--; -+ if (dev->mtd->owner) -+ __MOD_DEC_USE_COUNT(dev->mtd->owner); -+ out_tr: -+ if (tr->owner) -+ __MOD_DEC_USE_COUNT(tr->owner); -+ } -+ out: -+ up(&mtd_table_mutex); -+ -+ return ret; -+} -+ -+int blktrans_release(struct inode *i, struct file *f) -+{ -+ struct mtd_blktrans_dev *dev; -+ struct mtd_blktrans_ops *tr; -+ int ret = 0; -+ int devnum; -+ -+ down(&mtd_table_mutex); -+ -+ tr = get_tr(MAJOR(i->i_rdev)); -+ if (!tr) { -+ up(&mtd_table_mutex); -+ return -ENODEV; -+ } -+ -+ devnum = MINOR(i->i_rdev) >> tr->part_bits; -+ dev = tr_get_dev(tr, devnum); -+ -+ if (!dev) { -+ up(&mtd_table_mutex); -+ return -ENODEV; -+ } -+ -+ if (tr->release) -+ ret = tr->release(dev); -+ -+ if (!ret) { -+ dev->mtd->usecount--; -+ if (dev->mtd->owner) -+ __MOD_DEC_USE_COUNT(dev->mtd->owner); -+ if (tr->owner) -+ __MOD_DEC_USE_COUNT(tr->owner); -+ } -+ -+ up(&mtd_table_mutex); -+ -+ return ret; -+} -+ -+static int mtd_blktrans_rrpart(kdev_t rdev, struct mtd_blktrans_ops *tr, -+ struct mtd_blktrans_dev *dev) -+{ -+ struct gendisk *gd = &(tr->blkcore_priv->gd); -+ int i; -+ int minor = MINOR(rdev); -+ -+ if (minor & ((1<part_bits)-1) || !tr->part_bits) { -+ /* BLKRRPART on a partition. Go away. */ -+ return -ENOTTY; -+ } -+ -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EACCES; -+ -+ /* We are required to prevent simultaneous open() ourselves. -+ The core doesn't do that for us. Did I ever mention how -+ much the Linux block layer sucks? Sledgehammer approach... */ -+ down(&mtd_table_mutex); -+ -+ for (i=0; i < (1<part_bits); i++) { -+ invalidate_device(MKDEV(tr->major, minor+i), 1); -+ gd->part[minor + i].start_sect = 0; -+ gd->part[minor + i].nr_sects = 0; -+ } -+ -+ grok_partitions(gd, minor, 1 << tr->part_bits, -+ tr->blkcore_priv->sizes[minor]); -+ up(&mtd_table_mutex); -+ -+ return 0; -+} -+ -+static int blktrans_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct mtd_blktrans_dev *dev; -+ struct mtd_blktrans_ops *tr; -+ int devnum; -+ -+ switch(cmd) { -+ case BLKGETSIZE: -+ case BLKGETSIZE64: -+ case BLKBSZSET: -+ case BLKBSZGET: -+ case BLKROSET: -+ case BLKROGET: -+ case BLKRASET: -+ case BLKRAGET: -+ case BLKPG: -+ case BLKELVGET: -+ case BLKELVSET: -+ return blk_ioctl(inode->i_rdev, cmd, arg); -+ } -+ -+ down(&mtd_table_mutex); -+ -+ tr = get_tr(MAJOR(inode->i_rdev)); -+ if (!tr) { -+ up(&mtd_table_mutex); -+ return -ENODEV; -+ } -+ -+ devnum = MINOR(inode->i_rdev) >> tr->part_bits; -+ dev = tr_get_dev(tr, devnum); -+ -+ up(&mtd_table_mutex); -+ -+ if (!dev) -+ return -ENODEV; -+ -+ switch(cmd) { -+ case BLKRRPART: -+ return mtd_blktrans_rrpart(inode->i_rdev, tr, dev); -+ -+ case BLKFLSBUF: -+ blk_ioctl(inode->i_rdev, cmd, arg); -+ if (tr->flush) -+ return tr->flush(dev); -+ /* The core code did the work, we had nothing to do. */ -+ return 0; -+ -+ case HDIO_GETGEO: -+ if (tr->getgeo) { -+ struct hd_geometry g; -+ struct gendisk *gd = &(tr->blkcore_priv->gd); -+ int ret; -+ -+ memset(&g, 0, sizeof(g)); -+ ret = tr->getgeo(dev, &g); -+ if (ret) -+ return ret; -+ -+ g.start = gd->part[MINOR(inode->i_rdev)].start_sect; -+ if (copy_to_user((void *)arg, &g, sizeof(g))) -+ return -EFAULT; -+ return 0; -+ } /* else */ -+ default: -+ return -ENOTTY; -+ } -+} -+ -+struct block_device_operations mtd_blktrans_ops = { -+ .owner = THIS_MODULE, -+ .open = blktrans_open, -+ .release = blktrans_release, -+ .ioctl = blktrans_ioctl, -+}; -+ -+int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) -+{ -+ struct mtd_blktrans_ops *tr = new->tr; -+ struct list_head *this; -+ int last_devnum = -1; -+ int i; -+ -+ if (!down_trylock(&mtd_table_mutex)) { -+ up(&mtd_table_mutex); -+ BUG(); -+ } -+ -+ spin_lock(&tr->blkcore_priv->devs_lock); -+ -+ list_for_each(this, &tr->devs) { -+ struct mtd_blktrans_dev *d = list_entry(this, struct mtd_blktrans_dev, list); -+ if (new->devnum == -1) { -+ /* Use first free number */ -+ if (d->devnum != last_devnum+1) { -+ /* Found a free devnum. Plug it in here */ -+ new->devnum = last_devnum+1; -+ list_add_tail(&new->list, &d->list); -+ goto added; -+ } -+ } else if (d->devnum == new->devnum) { -+ /* Required number taken */ -+ spin_unlock(&tr->blkcore_priv->devs_lock); -+ return -EBUSY; -+ } else if (d->devnum > new->devnum) { -+ /* Required number was free */ -+ list_add_tail(&new->list, &d->list); -+ goto added; -+ } -+ last_devnum = d->devnum; -+ } -+ if (new->devnum == -1) -+ new->devnum = last_devnum+1; -+ -+ if ((new->devnum << tr->part_bits) > 256) { -+ spin_unlock(&tr->blkcore_priv->devs_lock); -+ return -EBUSY; -+ } -+ -+ init_MUTEX(&new->sem); -+ list_add_tail(&new->list, &tr->devs); -+ added: -+ spin_unlock(&tr->blkcore_priv->devs_lock); -+ -+ if (!tr->writesect) -+ new->readonly = 1; -+ -+ for (i = new->devnum << tr->part_bits; -+ i < (new->devnum+1) << tr->part_bits; -+ i++) { -+ set_device_ro(MKDEV(tr->major, i), new->readonly); -+ tr->blkcore_priv->blksizes[i] = new->blksize; -+ tr->blkcore_priv->sizes[i] = 0; -+ tr->blkcore_priv->part_table[i].nr_sects = 0; -+ tr->blkcore_priv->part_table[i].start_sect = 0; -+ } -+ -+ /* -+ dwmw2: BLOCK_SIZE_BITS has nothing to do with block devices -+ dwmw2: any code which sets blk_size[][] should be -+ size >> 10 /+ 2.4 and its dumb units */ -+ -+ tr->blkcore_priv->sizes[new->devnum << tr->part_bits] = -+ (new->size * new->blksize) >> 10; /* 2.4 and its dumb units */ -+ -+ /* But this is still in device's sectors? $DEITY knows */ -+ tr->blkcore_priv->part_table[new->devnum << tr->part_bits].nr_sects = new->size; -+ -+ if (tr->part_bits) { -+ grok_partitions(&tr->blkcore_priv->gd, new->devnum, -+ 1 << tr->part_bits, new->size); -+ } -+#ifdef CONFIG_DEVFS_FS -+ if (!tr->part_bits) { -+ char name[2]; -+ -+ name[0] = '0' + new->devnum; -+ name[1] = 0; -+ -+ new->blkcore_priv = -+ devfs_register(tr->blkcore_priv->devfs_dir_handle, -+ name, DEVFS_FL_DEFAULT, tr->major, -+ new->devnum, S_IFBLK|S_IRUGO|S_IWUGO, -+ &mtd_blktrans_ops, NULL); -+ } -+#endif -+ return 0; -+} -+ -+int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) -+{ -+ struct mtd_blktrans_ops *tr = old->tr; -+ int i; -+ -+ if (!down_trylock(&mtd_table_mutex)) { -+ up(&mtd_table_mutex); -+ BUG(); -+ } -+ -+#ifdef CONFIG_DEVFS_FS -+ if (!tr->part_bits) { -+ devfs_unregister(old->blkcore_priv); -+ old->blkcore_priv = NULL; -+ } else { -+ devfs_register_partitions(&tr->blkcore_priv->gd, -+ old->devnum << tr->part_bits, 1); -+ } -+#endif -+ spin_lock(&tr->blkcore_priv->devs_lock); -+ list_del(&old->list); -+ spin_unlock(&tr->blkcore_priv->devs_lock); -+ -+ for (i = (old->devnum << tr->part_bits); -+ i < ((old->devnum+1) << tr->part_bits); i++) { -+ tr->blkcore_priv->sizes[i] = 0; -+ tr->blkcore_priv->part_table[i].nr_sects = 0; -+ tr->blkcore_priv->part_table[i].start_sect = 0; -+ } -+ -+ return 0; -+} -+ -+void blktrans_notify_remove(struct mtd_info *mtd) -+{ -+ struct list_head *this, *this2, *next; -+ -+ list_for_each(this, &blktrans_majors) { -+ struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list); -+ -+ list_for_each_safe(this2, next, &tr->devs) { -+ struct mtd_blktrans_dev *dev = list_entry(this2, struct mtd_blktrans_dev, list); -+ -+ if (dev->mtd == mtd) -+ tr->remove_dev(dev); -+ } -+ } -+} -+ -+void blktrans_notify_add(struct mtd_info *mtd) -+{ -+ struct list_head *this; -+ -+ if (mtd->type == MTD_ABSENT) -+ return; -+ -+ list_for_each(this, &blktrans_majors) { -+ struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list); -+ -+ tr->add_mtd(tr, mtd); -+ } -+ -+} -+ -+static struct mtd_notifier blktrans_notifier = { -+ .add = blktrans_notify_add, -+ .remove = blktrans_notify_remove, -+}; -+ -+int register_mtd_blktrans(struct mtd_blktrans_ops *tr) -+{ -+ int ret, i; -+ -+ /* Register the notifier if/when the first device type is -+ registered, to prevent the link/init ordering from fucking -+ us over. */ -+ if (!blktrans_notifier.list.next) -+ register_mtd_user(&blktrans_notifier); -+ -+ tr->blkcore_priv = kmalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL); -+ if (!tr->blkcore_priv) -+ return -ENOMEM; -+ -+ memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv)); -+ -+ down(&mtd_table_mutex); -+ -+ ret = devfs_register_blkdev(tr->major, tr->name, &mtd_blktrans_ops); -+ 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); -+ return ret; -+ } -+ -+ blk_init_queue(BLK_DEFAULT_QUEUE(tr->major), &mtd_blktrans_request); -+ (BLK_DEFAULT_QUEUE(tr->major))->queuedata = tr; -+ -+ init_completion(&tr->blkcore_priv->thread_dead); -+ init_waitqueue_head(&tr->blkcore_priv->thread_wq); -+ -+ ret = kernel_thread(mtd_blktrans_thread, tr, -+ CLONE_FS|CLONE_FILES|CLONE_SIGHAND); -+ if (ret < 0) { -+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(tr->major)); -+ devfs_unregister_blkdev(tr->major, tr->name); -+ kfree(tr->blkcore_priv); -+ up(&mtd_table_mutex); -+ return ret; -+ } -+ -+ tr->blkcore_priv->devfs_dir_handle = -+ devfs_mk_dir(NULL, tr->name, NULL); -+ -+ blksize_size[tr->major] = tr->blkcore_priv->blksizes; -+ blk_size[tr->major] = tr->blkcore_priv->sizes; -+ -+ tr->blkcore_priv->gd.major = tr->major; -+ tr->blkcore_priv->gd.major_name = tr->name; -+ tr->blkcore_priv->gd.minor_shift = tr->part_bits; -+ tr->blkcore_priv->gd.max_p = (1<part_bits) - 1; -+ tr->blkcore_priv->gd.part = tr->blkcore_priv->part_table; -+ tr->blkcore_priv->gd.sizes = tr->blkcore_priv->sizes; -+ tr->blkcore_priv->gd.nr_real = 256 >> tr->part_bits; -+ -+ spin_lock_init(&tr->blkcore_priv->devs_lock); -+ -+ add_gendisk(&tr->blkcore_priv->gd); -+ -+ INIT_LIST_HEAD(&tr->devs); -+ list_add(&tr->list, &blktrans_majors); -+ -+ for (i=0; itype != MTD_ABSENT) -+ tr->add_mtd(tr, mtd_table[i]); -+ } -+ up(&mtd_table_mutex); -+ -+ return 0; -+} -+ -+int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) -+{ -+ struct list_head *this, *next; -+ -+ down(&mtd_table_mutex); -+ -+ /* Clean up the kernel thread */ -+ tr->blkcore_priv->exiting = 1; -+ wake_up(&tr->blkcore_priv->thread_wq); -+ wait_for_completion(&tr->blkcore_priv->thread_dead); -+ -+ /* Remove it from the list of active majors */ -+ list_del(&tr->list); -+ -+ /* Remove each of its devices */ -+ list_for_each_safe(this, next, &tr->devs) { -+ struct mtd_blktrans_dev *dev = list_entry(this, struct mtd_blktrans_dev, list); -+ tr->remove_dev(dev); -+ } -+ -+ blksize_size[tr->major] = NULL; -+ blk_size[tr->major] = NULL; -+ -+ del_gendisk(&tr->blkcore_priv->gd); -+ -+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(tr->major)); -+ devfs_unregister_blkdev(tr->major, tr->name); -+ -+ devfs_unregister(tr->blkcore_priv->devfs_dir_handle); -+ -+ up(&mtd_table_mutex); -+ -+ kfree(tr->blkcore_priv); -+ -+ if (!list_empty(&tr->devs)) -+ BUG(); -+ return 0; -+} -+ -+static void __exit mtd_blktrans_exit(void) -+{ -+ /* No race here -- if someone's currently in register_mtd_blktrans -+ we're screwed anyway. */ -+ if (blktrans_notifier.list.next) -+ unregister_mtd_user(&blktrans_notifier); -+} -+ -+module_exit(mtd_blktrans_exit); -+ -+EXPORT_SYMBOL_GPL(register_mtd_blktrans); -+EXPORT_SYMBOL_GPL(deregister_mtd_blktrans); -+EXPORT_SYMBOL_GPL(add_mtd_blktrans_dev); -+EXPORT_SYMBOL_GPL(del_mtd_blktrans_dev); -+ -+MODULE_AUTHOR("David Woodhouse "); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Common interface to block layer for MTD 'translation layers'"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/mtd_blkdevs.c linux/drivers/mtd/mtd_blkdevs.c ---- linux-mips-2.4.24-pre2/drivers/mtd/mtd_blkdevs.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/mtd_blkdevs.c 2004-11-17 18:17:58.000000000 +0100 -@@ -0,0 +1,479 @@ -+/* -+ * $Id$ -+ * -+ * (C) 2003 David Woodhouse -+ * -+ * Interface to Linux 2.5 block layer for MTD 'translation layers'. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static LIST_HEAD(blktrans_majors); -+ -+extern struct semaphore mtd_table_mutex; -+extern struct mtd_info *mtd_table[]; -+ -+struct mtd_blkcore_priv { -+ struct completion thread_dead; -+ int exiting; -+ wait_queue_head_t thread_wq; -+ struct request_queue *rq; -+ spinlock_t queue_lock; -+}; -+ -+static int do_blktrans_request(struct mtd_blktrans_ops *tr, -+ struct mtd_blktrans_dev *dev, -+ struct request *req) -+{ -+ unsigned long block, nsect; -+ char *buf; -+ -+ block = req->sector; -+ nsect = req->current_nr_sectors; -+ buf = req->buffer; -+ -+ if (!(req->flags & REQ_CMD)) -+ return 0; -+ -+ if (block + nsect > get_capacity(req->rq_disk)) -+ return 0; -+ -+ switch(rq_data_dir(req)) { -+ case READ: -+ for (; nsect > 0; nsect--, block++, buf += 512) -+ if (tr->readsect(dev, block, buf)) -+ return 0; -+ return 1; -+ -+ case WRITE: -+ if (!tr->writesect) -+ return 0; -+ -+ for (; nsect > 0; nsect--, block++, buf += 512) -+ if (tr->writesect(dev, block, buf)) -+ return 0; -+ return 1; -+ -+ default: -+ printk(KERN_NOTICE "Unknown request %ld\n", rq_data_dir(req)); -+ return 0; -+ } -+} -+ -+static int mtd_blktrans_thread(void *arg) -+{ -+ struct mtd_blktrans_ops *tr = arg; -+ struct request_queue *rq = tr->blkcore_priv->rq; -+ -+ /* we might get involved when memory gets low, so use PF_MEMALLOC */ -+ current->flags |= PF_MEMALLOC; -+ -+ daemonize("%sd", tr->name); -+ -+ /* daemonize() doesn't do this for us since some kernel threads -+ actually want to deal with signals. We can't just call -+ exit_sighand() since that'll cause an oops when we finally -+ do exit. */ -+ spin_lock_irq(¤t->sighand->siglock); -+ sigfillset(¤t->blocked); -+ recalc_sigpending(); -+ spin_unlock_irq(¤t->sighand->siglock); -+ -+ spin_lock_irq(rq->queue_lock); -+ -+ while (!tr->blkcore_priv->exiting) { -+ struct request *req; -+ struct mtd_blktrans_dev *dev; -+ int res = 0; -+ DECLARE_WAITQUEUE(wait, current); -+ -+ req = elv_next_request(rq); -+ -+ if (!req) { -+ add_wait_queue(&tr->blkcore_priv->thread_wq, &wait); -+ set_current_state(TASK_INTERRUPTIBLE); -+ -+ spin_unlock_irq(rq->queue_lock); -+ -+ schedule(); -+ remove_wait_queue(&tr->blkcore_priv->thread_wq, &wait); -+ -+ spin_lock_irq(rq->queue_lock); -+ -+ continue; -+ } -+ -+ dev = req->rq_disk->private_data; -+ tr = dev->tr; -+ -+ spin_unlock_irq(rq->queue_lock); -+ -+ down(&dev->sem); -+ res = do_blktrans_request(tr, dev, req); -+ up(&dev->sem); -+ -+ spin_lock_irq(rq->queue_lock); -+ -+ end_request(req, res); -+ } -+ complete_and_exit(&tr->blkcore_priv->thread_dead, 0); -+} -+ -+static void mtd_blktrans_request(struct request_queue *rq) -+{ -+ struct mtd_blktrans_ops *tr = rq->queuedata; -+ wake_up(&tr->blkcore_priv->thread_wq); -+} -+ -+ -+int blktrans_open(struct inode *i, struct file *f) -+{ -+ struct mtd_blktrans_dev *dev; -+ struct mtd_blktrans_ops *tr; -+ int ret = -ENODEV; -+ -+ dev = i->i_bdev->bd_disk->private_data; -+ tr = dev->tr; -+ -+ if (!try_module_get(dev->mtd->owner)) -+ goto out; -+ -+ if (!try_module_get(tr->owner)) -+ goto out_tr; -+ -+ /* FIXME: Locking. A hot pluggable device can go away -+ (del_mtd_device can be called for it) without its module -+ being unloaded. */ -+ dev->mtd->usecount++; -+ -+ ret = 0; -+ if (tr->open && (ret = tr->open(dev))) { -+ dev->mtd->usecount--; -+ module_put(dev->mtd->owner); -+ out_tr: -+ module_put(tr->owner); -+ } -+ out: -+ return ret; -+} -+ -+int blktrans_release(struct inode *i, struct file *f) -+{ -+ struct mtd_blktrans_dev *dev; -+ struct mtd_blktrans_ops *tr; -+ int ret = 0; -+ -+ dev = i->i_bdev->bd_disk->private_data; -+ tr = dev->tr; -+ -+ if (tr->release) -+ ret = tr->release(dev); -+ -+ if (!ret) { -+ dev->mtd->usecount--; -+ module_put(dev->mtd->owner); -+ module_put(tr->owner); -+ } -+ -+ return ret; -+} -+ -+ -+static int blktrans_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct mtd_blktrans_dev *dev = inode->i_bdev->bd_disk->private_data; -+ struct mtd_blktrans_ops *tr = dev->tr; -+ -+ switch (cmd) { -+ case BLKFLSBUF: -+ if (tr->flush) -+ return tr->flush(dev); -+ /* The core code did the work, we had nothing to do. */ -+ return 0; -+ -+ case HDIO_GETGEO: -+ if (tr->getgeo) { -+ struct hd_geometry g; -+ int ret; -+ -+ memset(&g, 0, sizeof(g)); -+ ret = tr->getgeo(dev, &g); -+ -+ if (ret) -+ return ret; -+ -+ g.start = get_start_sect(inode->i_bdev); -+ if (copy_to_user((void *)arg, &g, sizeof(g))) -+ return -EFAULT; -+ return 0; -+ } /* else */ -+ default: -+ return -ENOTTY; -+ } -+} -+ -+struct block_device_operations mtd_blktrans_ops = { -+ .owner = THIS_MODULE, -+ .open = blktrans_open, -+ .release = blktrans_release, -+ .ioctl = blktrans_ioctl, -+}; -+ -+int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) -+{ -+ struct mtd_blktrans_ops *tr = new->tr; -+ struct list_head *this; -+ int last_devnum = -1; -+ struct gendisk *gd; -+ -+ if (!down_trylock(&mtd_table_mutex)) { -+ up(&mtd_table_mutex); -+ BUG(); -+ } -+ -+ list_for_each(this, &tr->devs) { -+ struct mtd_blktrans_dev *d = list_entry(this, struct mtd_blktrans_dev, list); -+ if (new->devnum == -1) { -+ /* Use first free number */ -+ if (d->devnum != last_devnum+1) { -+ /* Found a free devnum. Plug it in here */ -+ new->devnum = last_devnum+1; -+ list_add_tail(&new->list, &d->list); -+ goto added; -+ } -+ } else if (d->devnum == new->devnum) { -+ /* Required number taken */ -+ return -EBUSY; -+ } else if (d->devnum > new->devnum) { -+ /* Required number was free */ -+ list_add_tail(&new->list, &d->list); -+ goto added; -+ } -+ last_devnum = d->devnum; -+ } -+ if (new->devnum == -1) -+ new->devnum = last_devnum+1; -+ -+ if ((new->devnum << tr->part_bits) > 256) { -+ return -EBUSY; -+ } -+ -+ init_MUTEX(&new->sem); -+ list_add_tail(&new->list, &tr->devs); -+ added: -+ if (!tr->writesect) -+ new->readonly = 1; -+ -+ gd = alloc_disk(1 << tr->part_bits); -+ if (!gd) { -+ list_del(&new->list); -+ return -ENOMEM; -+ } -+ gd->major = tr->major; -+ gd->first_minor = (new->devnum) << tr->part_bits; -+ gd->fops = &mtd_blktrans_ops; -+ -+ snprintf(gd->disk_name, sizeof(gd->disk_name), -+ "%s%c", tr->name, (tr->part_bits?'a':'0') + new->devnum); -+ snprintf(gd->devfs_name, sizeof(gd->devfs_name), -+ "%s/%c", tr->name, (tr->part_bits?'a':'0') + new->devnum); -+ -+ /* 2.5 has capacity in units of 512 bytes while still -+ having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */ -+ set_capacity(gd, (new->size * new->blksize) >> 9); -+ -+ gd->private_data = new; -+ new->blkcore_priv = gd; -+ gd->queue = tr->blkcore_priv->rq; -+ -+ if (new->readonly) -+ set_disk_ro(gd, 1); -+ -+ add_disk(gd); -+ -+ return 0; -+} -+ -+int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) -+{ -+ if (!down_trylock(&mtd_table_mutex)) { -+ up(&mtd_table_mutex); -+ BUG(); -+ } -+ -+ list_del(&old->list); -+ -+ del_gendisk(old->blkcore_priv); -+ put_disk(old->blkcore_priv); -+ -+ return 0; -+} -+ -+void blktrans_notify_remove(struct mtd_info *mtd) -+{ -+ struct list_head *this, *this2, *next; -+ -+ list_for_each(this, &blktrans_majors) { -+ struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list); -+ -+ list_for_each_safe(this2, next, &tr->devs) { -+ struct mtd_blktrans_dev *dev = list_entry(this2, struct mtd_blktrans_dev, list); -+ -+ if (dev->mtd == mtd) -+ tr->remove_dev(dev); -+ } -+ } -+} -+ -+void blktrans_notify_add(struct mtd_info *mtd) -+{ -+ struct list_head *this; -+ -+ if (mtd->type == MTD_ABSENT) -+ return; -+ -+ list_for_each(this, &blktrans_majors) { -+ struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list); -+ -+ tr->add_mtd(tr, mtd); -+ } -+ -+} -+ -+static struct mtd_notifier blktrans_notifier = { -+ .add = blktrans_notify_add, -+ .remove = blktrans_notify_remove, -+}; -+ -+int register_mtd_blktrans(struct mtd_blktrans_ops *tr) -+{ -+ int ret, i; -+ -+ /* Register the notifier if/when the first device type is -+ registered, to prevent the link/init ordering from fucking -+ us over. */ -+ if (!blktrans_notifier.list.next) -+ register_mtd_user(&blktrans_notifier); -+ -+ tr->blkcore_priv = kmalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL); -+ if (!tr->blkcore_priv) -+ return -ENOMEM; -+ -+ memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv)); -+ -+ down(&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); -+ return ret; -+ } -+ spin_lock_init(&tr->blkcore_priv->queue_lock); -+ init_completion(&tr->blkcore_priv->thread_dead); -+ init_waitqueue_head(&tr->blkcore_priv->thread_wq); -+ -+ tr->blkcore_priv->rq = blk_init_queue(mtd_blktrans_request, &tr->blkcore_priv->queue_lock); -+ if (!tr->blkcore_priv->rq) { -+ unregister_blkdev(tr->major, tr->name); -+ kfree(tr->blkcore_priv); -+ up(&mtd_table_mutex); -+ return -ENOMEM; -+ } -+ -+ tr->blkcore_priv->rq->queuedata = tr; -+ -+ ret = kernel_thread(mtd_blktrans_thread, tr, -+ CLONE_FS|CLONE_FILES|CLONE_SIGHAND); -+ if (ret < 0) { -+ blk_cleanup_queue(tr->blkcore_priv->rq); -+ unregister_blkdev(tr->major, tr->name); -+ kfree(tr->blkcore_priv); -+ up(&mtd_table_mutex); -+ return ret; -+ } -+ -+ devfs_mk_dir(tr->name); -+ -+ INIT_LIST_HEAD(&tr->devs); -+ list_add(&tr->list, &blktrans_majors); -+ -+ for (i=0; itype != MTD_ABSENT) -+ tr->add_mtd(tr, mtd_table[i]); -+ } -+ -+ up(&mtd_table_mutex); -+ -+ return 0; -+} -+ -+int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) -+{ -+ struct list_head *this, *next; -+ -+ down(&mtd_table_mutex); -+ -+ /* Clean up the kernel thread */ -+ tr->blkcore_priv->exiting = 1; -+ wake_up(&tr->blkcore_priv->thread_wq); -+ wait_for_completion(&tr->blkcore_priv->thread_dead); -+ -+ /* Remove it from the list of active majors */ -+ list_del(&tr->list); -+ -+ list_for_each_safe(this, next, &tr->devs) { -+ struct mtd_blktrans_dev *dev = list_entry(this, struct mtd_blktrans_dev, list); -+ tr->remove_dev(dev); -+ } -+ -+ devfs_remove(tr->name); -+ blk_cleanup_queue(tr->blkcore_priv->rq); -+ unregister_blkdev(tr->major, tr->name); -+ -+ up(&mtd_table_mutex); -+ -+ kfree(tr->blkcore_priv); -+ -+ if (!list_empty(&tr->devs)) -+ BUG(); -+ return 0; -+} -+ -+static void __exit mtd_blktrans_exit(void) -+{ -+ /* No race here -- if someone's currently in register_mtd_blktrans -+ we're screwed anyway. */ -+ if (blktrans_notifier.list.next) -+ unregister_mtd_user(&blktrans_notifier); -+} -+ -+module_exit(mtd_blktrans_exit); -+ -+EXPORT_SYMBOL_GPL(register_mtd_blktrans); -+EXPORT_SYMBOL_GPL(deregister_mtd_blktrans); -+EXPORT_SYMBOL_GPL(add_mtd_blktrans_dev); -+EXPORT_SYMBOL_GPL(del_mtd_blktrans_dev); -+ -+MODULE_AUTHOR("David Woodhouse "); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Common interface to block layer for MTD 'translation layers'"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/mtdblock.c linux/drivers/mtd/mtdblock.c ---- linux-mips-2.4.24-pre2/drivers/mtd/mtdblock.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/mtdblock.c 2004-11-17 18:17:58.856341736 +0100 -@@ -1,52 +1,25 @@ - /* - * Direct MTD block device access - * -- * $Id$ -+ * $Id$ - * -- * 02-nov-2000 Nicolas Pitre Added read-modify-write with cache -+ * (C) 2000-2003 Nicolas Pitre -+ * (C) 1999-2003 David Woodhouse - */ - - #include - #include - #include - #include -+#include -+#include - #include -+#include - #include --#include -- --#define MAJOR_NR MTD_BLOCK_MAJOR --#define DEVICE_NAME "mtdblock" --#define DEVICE_REQUEST mtdblock_request --#define DEVICE_NR(device) (device) --#define DEVICE_ON(device) --#define DEVICE_OFF(device) --#define DEVICE_NO_RANDOM --#include --/* for old kernels... */ --#ifndef QUEUE_EMPTY --#define QUEUE_EMPTY (!CURRENT) --#endif --#if LINUX_VERSION_CODE < 0x20300 --#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].plug_tq.sync) --#else --#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].request_queue.plugged) --#endif -- --#ifdef CONFIG_DEVFS_FS --#include --static void mtd_notify_add(struct mtd_info* mtd); --static void mtd_notify_remove(struct mtd_info* mtd); --static struct mtd_notifier notifier = { -- mtd_notify_add, -- mtd_notify_remove, -- NULL --}; --static devfs_handle_t devfs_dir_handle = NULL; --static devfs_handle_t devfs_rw_handle[MAX_MTD_DEVICES]; --#endif -+#include - - static struct mtdblk_dev { -- struct mtd_info *mtd; /* Locked */ -+ struct mtd_info *mtd; - int count; - struct semaphore cache_sem; - unsigned char *cache_data; -@@ -55,19 +28,6 @@ - enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; - } *mtdblks[MAX_MTD_DEVICES]; - --static spinlock_t mtdblks_lock; -- --static int mtd_sizes[MAX_MTD_DEVICES]; --static int mtd_blksizes[MAX_MTD_DEVICES]; -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14) --#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT --#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT --#else --#define BLK_INC_USE_COUNT do {} while(0) --#define BLK_DEC_USE_COUNT do {} while(0) --#endif -- - /* - * Cache stuff... - * -@@ -151,7 +111,7 @@ - return ret; - - /* -- * Here we could argably set the cache state to STATE_CLEAN. -+ * Here we could argubly set the cache state to STATE_CLEAN. - * However this could lead to inconsistency since we will not - * be notified if this content is altered on the flash by other - * means. Let's declare it empty and leave buffering tasks to -@@ -277,57 +237,47 @@ - return 0; - } - -+static int mtdblock_readsect(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buf) -+{ -+ struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; -+ return do_cached_read(mtdblk, block<<9, 512, buf); -+} - -+static int mtdblock_writesect(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buf) -+{ -+ struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; -+ if (unlikely(!mtdblk->cache_data)) { -+ mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize); -+ if (!mtdblk->cache_data) -+ return -EINTR; -+ /* -EINTR is not really correct, but it is the best match -+ * documented in man 2 write for all cases. We could also -+ * return -EAGAIN sometimes, but why bother? -+ */ -+ } -+ return do_cached_write(mtdblk, block<<9, 512, buf); -+} - --static int mtdblock_open(struct inode *inode, struct file *file) -+static int mtdblock_open(struct mtd_blktrans_dev *mbd) - { - struct mtdblk_dev *mtdblk; -- struct mtd_info *mtd; -- int dev; -+ struct mtd_info *mtd = mbd->mtd; -+ int dev = mbd->devnum; - - DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n"); - -- if (!inode) -- return -EINVAL; -- -- dev = MINOR(inode->i_rdev); -- if (dev >= MAX_MTD_DEVICES) -- return -EINVAL; -- -- BLK_INC_USE_COUNT; -- -- mtd = get_mtd_device(NULL, dev); -- if (!mtd) -- return -ENODEV; -- if (MTD_ABSENT == mtd->type) { -- put_mtd_device(mtd); -- BLK_DEC_USE_COUNT; -- return -ENODEV; -- } -- -- spin_lock(&mtdblks_lock); -- -- /* If it's already open, no need to piss about. */ - if (mtdblks[dev]) { - mtdblks[dev]->count++; -- spin_unlock(&mtdblks_lock); -- put_mtd_device(mtd); - return 0; - } - -- /* OK, it's not open. Try to find it */ -- -- /* First we have to drop the lock, because we have to -- to things which might sleep. -- */ -- spin_unlock(&mtdblks_lock); -- -+ /* OK, it's not open. Create cache info for it */ - mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); -- if (!mtdblk) { -- put_mtd_device(mtd); -- BLK_DEC_USE_COUNT; -+ if (!mtdblk) - return -ENOMEM; -- } -+ - memset(mtdblk, 0, sizeof(*mtdblk)); - mtdblk->count = 1; - mtdblk->mtd = mtd; -@@ -337,336 +287,102 @@ - if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM && - mtdblk->mtd->erasesize) { - mtdblk->cache_size = mtdblk->mtd->erasesize; -- mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize); -- if (!mtdblk->cache_data) { -- put_mtd_device(mtdblk->mtd); -- kfree(mtdblk); -- BLK_DEC_USE_COUNT; -- return -ENOMEM; -- } -- } -- -- /* OK, we've created a new one. Add it to the list. */ -- -- spin_lock(&mtdblks_lock); -- -- if (mtdblks[dev]) { -- /* Another CPU made one at the same time as us. */ -- mtdblks[dev]->count++; -- spin_unlock(&mtdblks_lock); -- put_mtd_device(mtdblk->mtd); -- vfree(mtdblk->cache_data); -- kfree(mtdblk); -- return 0; -+ mtdblk->cache_data = NULL; - } - - mtdblks[dev] = mtdblk; -- mtd_sizes[dev] = mtdblk->mtd->size/1024; -- if (mtdblk->mtd->erasesize) -- mtd_blksizes[dev] = mtdblk->mtd->erasesize; -- if (mtd_blksizes[dev] > PAGE_SIZE) -- mtd_blksizes[dev] = PAGE_SIZE; -- set_device_ro (inode->i_rdev, !(mtdblk->mtd->flags & MTD_WRITEABLE)); -- -- spin_unlock(&mtdblks_lock); - - DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); - - return 0; - } - --static release_t mtdblock_release(struct inode *inode, struct file *file) -+static int mtdblock_release(struct mtd_blktrans_dev *mbd) - { -- int dev; -- struct mtdblk_dev *mtdblk; -- DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); -+ int dev = mbd->devnum; -+ struct mtdblk_dev *mtdblk = mtdblks[dev]; - -- if (inode == NULL) -- release_return(-ENODEV); -- -- dev = MINOR(inode->i_rdev); -- mtdblk = mtdblks[dev]; -+ DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); - - down(&mtdblk->cache_sem); - write_cached_data(mtdblk); - up(&mtdblk->cache_sem); - -- spin_lock(&mtdblks_lock); - if (!--mtdblk->count) { - /* It was the last usage. Free the device */ - mtdblks[dev] = NULL; -- spin_unlock(&mtdblks_lock); - if (mtdblk->mtd->sync) - mtdblk->mtd->sync(mtdblk->mtd); -- put_mtd_device(mtdblk->mtd); - vfree(mtdblk->cache_data); - kfree(mtdblk); -- } else { -- spin_unlock(&mtdblks_lock); - } -- - DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); - -- BLK_DEC_USE_COUNT; -- release_return(0); --} -- -- --/* -- * This is a special request_fn because it is executed in a process context -- * to be able to sleep independently of the caller. The io_request_lock -- * is held upon entry and exit. -- * The head of our request queue is considered active so there is no need -- * to dequeue requests before we are done. -- */ --static void handle_mtdblock_request(void) --{ -- struct request *req; -- struct mtdblk_dev *mtdblk; -- unsigned int res; -- -- for (;;) { -- INIT_REQUEST; -- req = CURRENT; -- spin_unlock_irq(&io_request_lock); -- mtdblk = mtdblks[MINOR(req->rq_dev)]; -- res = 0; -- -- if (MINOR(req->rq_dev) >= MAX_MTD_DEVICES) -- panic("%s: minor out of bounds", __FUNCTION__); -- -- if ((req->sector + req->current_nr_sectors) > (mtdblk->mtd->size >> 9)) -- goto end_req; -- -- // Handle the request -- switch (req->cmd) -- { -- int err; -- -- case READ: -- down(&mtdblk->cache_sem); -- err = do_cached_read (mtdblk, req->sector << 9, -- req->current_nr_sectors << 9, -- req->buffer); -- up(&mtdblk->cache_sem); -- if (!err) -- res = 1; -- break; -- -- case WRITE: -- // Read only device -- if ( !(mtdblk->mtd->flags & MTD_WRITEABLE) ) -- break; -- -- // Do the write -- down(&mtdblk->cache_sem); -- err = do_cached_write (mtdblk, req->sector << 9, -- req->current_nr_sectors << 9, -- req->buffer); -- up(&mtdblk->cache_sem); -- if (!err) -- res = 1; -- break; -- } -- --end_req: -- spin_lock_irq(&io_request_lock); -- end_request(res); -- } --} -- --static volatile int leaving = 0; --static DECLARE_MUTEX_LOCKED(thread_sem); --static DECLARE_WAIT_QUEUE_HEAD(thr_wq); -- --int mtdblock_thread(void *dummy) --{ -- struct task_struct *tsk = current; -- DECLARE_WAITQUEUE(wait, tsk); -- -- /* we might get involved when memory gets low, so use PF_MEMALLOC */ -- tsk->flags |= PF_MEMALLOC; -- strcpy(tsk->comm, "mtdblockd"); -- spin_lock_irq(&tsk->sigmask_lock); -- sigfillset(&tsk->blocked); -- recalc_sigpending(tsk); -- spin_unlock_irq(&tsk->sigmask_lock); -- daemonize(); -- -- while (!leaving) { -- add_wait_queue(&thr_wq, &wait); -- set_current_state(TASK_INTERRUPTIBLE); -- spin_lock_irq(&io_request_lock); -- if (QUEUE_EMPTY || QUEUE_PLUGGED) { -- spin_unlock_irq(&io_request_lock); -- schedule(); -- remove_wait_queue(&thr_wq, &wait); -- } else { -- remove_wait_queue(&thr_wq, &wait); -- set_current_state(TASK_RUNNING); -- handle_mtdblock_request(); -- spin_unlock_irq(&io_request_lock); -- } -- } -- -- up(&thread_sem); - return 0; - } - --#if LINUX_VERSION_CODE < 0x20300 --#define RQFUNC_ARG void --#else --#define RQFUNC_ARG request_queue_t *q --#endif -- --static void mtdblock_request(RQFUNC_ARG) -+static int mtdblock_flush(struct mtd_blktrans_dev *dev) - { -- /* Don't do anything, except wake the thread if necessary */ -- wake_up(&thr_wq); --} -+ struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; - -- --static int mtdblock_ioctl(struct inode * inode, struct file * file, -- unsigned int cmd, unsigned long arg) --{ -- struct mtdblk_dev *mtdblk; -- -- mtdblk = mtdblks[MINOR(inode->i_rdev)]; -- --#ifdef PARANOIA -- if (!mtdblk) -- BUG(); --#endif -- -- switch (cmd) { -- case BLKGETSIZE: /* Return device size */ -- return put_user((mtdblk->mtd->size >> 9), (unsigned long *) arg); -- --#ifdef BLKGETSIZE64 -- case BLKGETSIZE64: -- return put_user((u64)mtdblk->mtd->size, (u64 *)arg); --#endif -- -- case BLKFLSBUF: --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) -- if(!capable(CAP_SYS_ADMIN)) -- return -EACCES; --#endif -- fsync_dev(inode->i_rdev); -- invalidate_buffers(inode->i_rdev); - down(&mtdblk->cache_sem); - write_cached_data(mtdblk); - up(&mtdblk->cache_sem); -+ - if (mtdblk->mtd->sync) - mtdblk->mtd->sync(mtdblk->mtd); - return 0; -- -- default: -- return -EINVAL; -- } - } - --#if LINUX_VERSION_CODE < 0x20326 --static struct file_operations mtd_fops = -+static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) - { -- open: mtdblock_open, -- ioctl: mtdblock_ioctl, -- release: mtdblock_release, -- read: block_read, -- write: block_write --}; --#else --static struct block_device_operations mtd_fops = --{ --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14) -- owner: THIS_MODULE, --#endif -- open: mtdblock_open, -- release: mtdblock_release, -- ioctl: mtdblock_ioctl --}; --#endif -+ struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL); - --#ifdef CONFIG_DEVFS_FS --/* Notification that a new device has been added. Create the devfs entry for -- * it. */ -- --static void mtd_notify_add(struct mtd_info* mtd) --{ -- char name[8]; -- -- if (!mtd || mtd->type == MTD_ABSENT) -+ if (!dev) - return; - -- sprintf(name, "%d", mtd->index); -- devfs_rw_handle[mtd->index] = devfs_register(devfs_dir_handle, name, -- DEVFS_FL_DEFAULT, MTD_BLOCK_MAJOR, mtd->index, -- S_IFBLK | S_IRUGO | S_IWUGO, -- &mtd_fops, NULL); --} -- --static void mtd_notify_remove(struct mtd_info* mtd) --{ -- if (!mtd || mtd->type == MTD_ABSENT) -- return; -+ memset(dev, 0, sizeof(*dev)); - -- devfs_unregister(devfs_rw_handle[mtd->index]); --} --#endif -+ dev->mtd = mtd; -+ dev->devnum = mtd->index; -+ dev->blksize = 512; -+ dev->size = mtd->size >> 9; -+ dev->tr = tr; -+ -+ if (!(mtd->flags & MTD_WRITEABLE)) -+ dev->readonly = 1; -+ -+ add_mtd_blktrans_dev(dev); -+} -+ -+static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev) -+{ -+ del_mtd_blktrans_dev(dev); -+ kfree(dev); -+} -+ -+struct mtd_blktrans_ops mtdblock_tr = { -+ .name = "mtdblock", -+ .major = 31, -+ .part_bits = 0, -+ .open = mtdblock_open, -+ .flush = mtdblock_flush, -+ .release = mtdblock_release, -+ .readsect = mtdblock_readsect, -+ .writesect = mtdblock_writesect, -+ .add_mtd = mtdblock_add_mtd, -+ .remove_dev = mtdblock_remove_dev, -+ .owner = THIS_MODULE, -+}; - - int __init init_mtdblock(void) - { -- int i; -- -- spin_lock_init(&mtdblks_lock); --#ifdef CONFIG_DEVFS_FS -- if (devfs_register_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME, &mtd_fops)) -- { -- printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", -- MTD_BLOCK_MAJOR); -- return -EAGAIN; -- } -- -- devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL); -- register_mtd_user(¬ifier); --#else -- if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { -- printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", -- MTD_BLOCK_MAJOR); -- return -EAGAIN; -- } --#endif -- -- /* We fill it in at open() time. */ -- for (i=0; i< MAX_MTD_DEVICES; i++) { -- mtd_sizes[i] = 0; -- mtd_blksizes[i] = BLOCK_SIZE; -- } -- init_waitqueue_head(&thr_wq); -- /* Allow the block size to default to BLOCK_SIZE. */ -- blksize_size[MAJOR_NR] = mtd_blksizes; -- blk_size[MAJOR_NR] = mtd_sizes; -- -- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request); -- kernel_thread (mtdblock_thread, NULL, CLONE_FS|CLONE_FILES|CLONE_SIGHAND); -- return 0; -+ return register_mtd_blktrans(&mtdblock_tr); - } - - static void __exit cleanup_mtdblock(void) - { -- leaving = 1; -- wake_up(&thr_wq); -- down(&thread_sem); --#ifdef CONFIG_DEVFS_FS -- unregister_mtd_user(¬ifier); -- devfs_unregister(devfs_dir_handle); -- devfs_unregister_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME); --#else -- unregister_blkdev(MAJOR_NR,DEVICE_NAME); --#endif -- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); -- blksize_size[MAJOR_NR] = NULL; -- blk_size[MAJOR_NR] = NULL; -+ deregister_mtd_blktrans(&mtdblock_tr); - } - - module_init(init_mtdblock); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/mtdblock_ro.c linux/drivers/mtd/mtdblock_ro.c ---- linux-mips-2.4.24-pre2/drivers/mtd/mtdblock_ro.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/mtdblock_ro.c 2004-11-17 18:17:58.857341584 +0100 -@@ -1,301 +1,87 @@ - /* -- * $Id$ -+ * $Id$ - * -- * Read-only version of the mtdblock device, without the -- * read/erase/modify/writeback stuff -+ * (C) 2003 David Woodhouse -+ * -+ * Simple read-only (writable only for RAM) mtdblock driver - */ - --#ifdef MTDBLOCK_DEBUG --#define DEBUGLVL debug --#endif -- -- --#include --#include -- -+#include -+#include - #include --#include -- --#define MAJOR_NR MTD_BLOCK_MAJOR --#define DEVICE_NAME "mtdblock" --#define DEVICE_REQUEST mtdblock_request --#define DEVICE_NR(device) (device) --#define DEVICE_ON(device) --#define DEVICE_OFF(device) --#define DEVICE_NO_RANDOM --#include -- --#if LINUX_VERSION_CODE < 0x20300 --#define RQFUNC_ARG void --#define blkdev_dequeue_request(req) do {CURRENT = req->next;} while (0) --#else --#define RQFUNC_ARG request_queue_t *q --#endif -- --#ifdef MTDBLOCK_DEBUG --static int debug = MTDBLOCK_DEBUG; --MODULE_PARM(debug, "i"); --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14) --#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT --#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT --#else --#define BLK_INC_USE_COUNT do {} while(0) --#define BLK_DEC_USE_COUNT do {} while(0) --#endif -- --static int mtd_sizes[MAX_MTD_DEVICES]; -+#include - -- --static int mtdblock_open(struct inode *inode, struct file *file) -+static int mtdblock_readsect(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buf) - { -- struct mtd_info *mtd = NULL; -- -- int dev; -- -- DEBUG(1,"mtdblock_open\n"); -- -- if (inode == 0) -- return -EINVAL; -- -- dev = MINOR(inode->i_rdev); -- -- mtd = get_mtd_device(NULL, dev); -- if (!mtd) -- return -EINVAL; -- if (MTD_ABSENT == mtd->type) { -- put_mtd_device(mtd); -- return -EINVAL; -- } -- -- BLK_INC_USE_COUNT; -- -- mtd_sizes[dev] = mtd->size>>9; -- -- DEBUG(1, "ok\n"); -+ size_t retlen; - -+ if (dev->mtd->read(dev->mtd, (block * 512), 512, &retlen, buf)) -+ return 1; - return 0; - } - --static release_t mtdblock_release(struct inode *inode, struct file *file) -+static int mtdblock_writesect(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buf) - { -- int dev; -- struct mtd_info *mtd; -- -- DEBUG(1, "mtdblock_release\n"); -- -- if (inode == NULL) -- release_return(-ENODEV); -- -- dev = MINOR(inode->i_rdev); -- mtd = __get_mtd_device(NULL, dev); -- -- if (!mtd) { -- printk(KERN_WARNING "MTD device is absent on mtd_release!\n"); -- BLK_DEC_USE_COUNT; -- release_return(-ENODEV); -- } -- -- if (mtd->sync) -- mtd->sync(mtd); -- -- put_mtd_device(mtd); -- -- DEBUG(1, "ok\n"); -+ size_t retlen; - -- BLK_DEC_USE_COUNT; -- release_return(0); -+ if (dev->mtd->write(dev->mtd, (block * 512), 512, &retlen, buf)) -+ return 1; -+ return 0; - } - -- --static void mtdblock_request(RQFUNC_ARG) -+static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) - { -- struct request *current_request; -- unsigned int res = 0; -- struct mtd_info *mtd; -- -- while (1) -- { -- /* Grab the Request and unlink it from the request list, INIT_REQUEST -- will execute a return if we are done. */ -- INIT_REQUEST; -- current_request = CURRENT; -- -- if (MINOR(current_request->rq_dev) >= MAX_MTD_DEVICES) -- { -- printk("mtd: Unsupported device!\n"); -- end_request(0); -- continue; -- } -- -- // Grab our MTD structure -- -- mtd = __get_mtd_device(NULL, MINOR(current_request->rq_dev)); -- if (!mtd) { -- printk("MTD device %d doesn't appear to exist any more\n", CURRENT_DEV); -- end_request(0); -- } -- -- if (current_request->sector << 9 > mtd->size || -- (current_request->sector + current_request->current_nr_sectors) << 9 > mtd->size) -- { -- printk("mtd: Attempt to read past end of device!\n"); -- printk("size: %x, sector: %lx, nr_sectors %lx\n", mtd->size, -- current_request->sector, current_request->current_nr_sectors); -- end_request(0); -- continue; -- } -- -- /* Remove the request we are handling from the request list so nobody messes -- with it */ --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) -- /* Now drop the lock that the ll_rw_blk functions grabbed for us -- and process the request. This is necessary due to the extreme time -- we spend processing it. */ -- spin_unlock_irq(&io_request_lock); --#endif -- -- // Handle the request -- switch (current_request->cmd) -- { -- size_t retlen; -+ struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL); - -- case READ: -- if (MTD_READ(mtd,current_request->sector<<9, -- current_request->current_nr_sectors << 9, -- &retlen, current_request->buffer) == 0) -- res = 1; -- else -- res = 0; -- break; -+ if (!dev) -+ return; - -- case WRITE: -+ memset(dev, 0, sizeof(*dev)); - -- /* printk("mtdblock_request WRITE sector=%d(%d)\n",current_request->sector, -- current_request->current_nr_sectors); -- */ -+ dev->mtd = mtd; -+ dev->devnum = mtd->index; -+ dev->blksize = 512; -+ dev->size = mtd->size >> 9; -+ dev->tr = tr; -+ if ((mtd->flags & (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEABLE)) != -+ (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEABLE)) -+ dev->readonly = 1; - -- // Read only device -- if ((mtd->flags & MTD_CAP_RAM) == 0) -- { -- res = 0; -- break; -- } -- -- // Do the write -- if (MTD_WRITE(mtd,current_request->sector<<9, -- current_request->current_nr_sectors << 9, -- &retlen, current_request->buffer) == 0) -- res = 1; -- else -- res = 0; -- break; -- -- // Shouldn't happen -- default: -- printk("mtd: unknown request\n"); -- break; -- } -- -- // Grab the lock and re-thread the item onto the linked list --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) -- spin_lock_irq(&io_request_lock); --#endif -- end_request(res); -- } -+ add_mtd_blktrans_dev(dev); - } - -- -- --static int mtdblock_ioctl(struct inode * inode, struct file * file, -- unsigned int cmd, unsigned long arg) -+static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev) - { -- struct mtd_info *mtd; -- -- mtd = __get_mtd_device(NULL, MINOR(inode->i_rdev)); -- -- if (!mtd) return -EINVAL; -- -- switch (cmd) { -- case BLKGETSIZE: /* Return device size */ -- return put_user((mtd->size >> 9), (unsigned long *) arg); -- --#ifdef BLKGETSIZE64 -- case BLKGETSIZE64: -- return put_user((u64)mtd->size, (u64 *)arg); --#endif -- -- case BLKFLSBUF: --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) -- if(!capable(CAP_SYS_ADMIN)) return -EACCES; --#endif -- fsync_dev(inode->i_rdev); -- invalidate_buffers(inode->i_rdev); -- if (mtd->sync) -- mtd->sync(mtd); -- return 0; -- -- default: -- return -ENOTTY; -- } -+ del_mtd_blktrans_dev(dev); -+ kfree(dev); - } - --#if LINUX_VERSION_CODE < 0x20326 --static struct file_operations mtd_fops = --{ -- open: mtdblock_open, -- ioctl: mtdblock_ioctl, -- release: mtdblock_release, -- read: block_read, -- write: block_write --}; --#else --static struct block_device_operations mtd_fops = --{ --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14) -- owner: THIS_MODULE, --#endif -- open: mtdblock_open, -- release: mtdblock_release, -- ioctl: mtdblock_ioctl -+struct mtd_blktrans_ops mtdblock_tr = { -+ .name = "mtdblock", -+ .major = 31, -+ .part_bits = 0, -+ .readsect = mtdblock_readsect, -+ .writesect = mtdblock_writesect, -+ .add_mtd = mtdblock_add_mtd, -+ .remove_dev = mtdblock_remove_dev, -+ .owner = THIS_MODULE, - }; --#endif - --int __init init_mtdblock(void) -+static int __init mtdblock_init(void) - { -- int i; -- -- if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { -- printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", -- MTD_BLOCK_MAJOR); -- return -EAGAIN; -- } -- -- /* We fill it in at open() time. */ -- for (i=0; i< MAX_MTD_DEVICES; i++) { -- mtd_sizes[i] = 0; -- } -- -- /* Allow the block size to default to BLOCK_SIZE. */ -- blksize_size[MAJOR_NR] = NULL; -- blk_size[MAJOR_NR] = mtd_sizes; -- -- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request); -- return 0; -+ return register_mtd_blktrans(&mtdblock_tr); - } - --static void __exit cleanup_mtdblock(void) -+static void __exit mtdblock_exit(void) - { -- unregister_blkdev(MAJOR_NR,DEVICE_NAME); -- blk_size[MAJOR_NR] = NULL; -- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); -+ deregister_mtd_blktrans(&mtdblock_tr); - } - --module_init(init_mtdblock); --module_exit(cleanup_mtdblock); -- -+module_init(mtdblock_init); -+module_exit(mtdblock_exit); - - MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Erwin Authried et al."); -+MODULE_AUTHOR("David Woodhouse "); - MODULE_DESCRIPTION("Simple read-only block device emulation access to MTD devices"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/mtdchar.c linux/drivers/mtd/mtdchar.c ---- linux-mips-2.4.24-pre2/drivers/mtd/mtdchar.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/mtdchar.c 2004-11-17 18:17:58.859341280 +0100 -@@ -1,8 +1,7 @@ - /* -- * $Id$ -+ * $Id$ - * - * Character-device access to raw MTD devices. -- * Pure 2.4 version - compatibility cruft removed to mtdchar-compat.c - * - */ - -@@ -10,7 +9,11 @@ - #include - #include - #include -+#include - #include -+#include -+#include -+#include - - #ifdef CONFIG_DEVFS_FS - #include -@@ -18,8 +21,8 @@ - static void mtd_notify_remove(struct mtd_info* mtd); - - static struct mtd_notifier notifier = { -- add: mtd_notify_add, -- remove: mtd_notify_remove, -+ .add = mtd_notify_add, -+ .remove = mtd_notify_remove, - }; - - static devfs_handle_t devfs_dir_handle; -@@ -60,7 +63,7 @@ - - static int mtd_open(struct inode *inode, struct file *file) - { -- int minor = minor(inode->i_rdev); -+ int minor = iminor(inode); - int devnum = minor >> 1; - struct mtd_info *mtd; - -@@ -442,81 +445,13 @@ - break; - } - -- case MEMWRITEDATA: -+ case MEMSETOOBSEL: - { -- struct mtd_oob_buf buf; -- void *databuf; -- ssize_t retlen; -- -- if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf))) -- return -EFAULT; -- -- if (buf.length > 0x4096) -- return -EINVAL; -- -- if (!mtd->write_ecc) -- ret = -EOPNOTSUPP; -- else -- ret = verify_area(VERIFY_READ, (char *)buf.ptr, buf.length); -- -- if (ret) -- return ret; -- -- databuf = kmalloc(buf.length, GFP_KERNEL); -- if (!databuf) -- return -ENOMEM; -- -- if (copy_from_user(databuf, buf.ptr, buf.length)) { -- kfree(databuf); -+ if (copy_from_user(&mtd->oobinfo ,(void *)arg, sizeof(struct nand_oobinfo))) - return -EFAULT; -- } -- -- ret = (mtd->write_ecc)(mtd, buf.start, buf.length, &retlen, databuf, NULL, 0); -- -- if (copy_to_user((void *)arg + sizeof(u_int32_t), &retlen, sizeof(u_int32_t))) -- ret = -EFAULT; -- -- kfree(databuf); - break; -- - } - -- case MEMREADDATA: -- { -- struct mtd_oob_buf buf; -- void *databuf; -- ssize_t retlen = 0; -- -- if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf))) -- return -EFAULT; -- -- if (buf.length > 0x4096) -- return -EINVAL; -- -- if (!mtd->read_ecc) -- ret = -EOPNOTSUPP; -- else -- ret = verify_area(VERIFY_WRITE, (char *)buf.ptr, buf.length); -- -- if (ret) -- return ret; -- -- databuf = kmalloc(buf.length, GFP_KERNEL); -- if (!databuf) -- return -ENOMEM; -- -- ret = (mtd->read_ecc)(mtd, buf.start, buf.length, &retlen, databuf, NULL, 0); -- -- if (copy_to_user((void *)arg + sizeof(u_int32_t), &retlen, sizeof(u_int32_t))) -- ret = -EFAULT; -- else if (retlen && copy_to_user(buf.ptr, databuf, retlen)) -- ret = -EFAULT; -- -- kfree(databuf); -- break; -- } -- -- - default: - DEBUG(MTD_DEBUG_LEVEL0, "Invalid ioctl %x (MEMGETINFO = %x)\n", cmd, MEMGETINFO); - ret = -ENOTTY; -@@ -526,13 +461,13 @@ - } /* memory_ioctl */ - - static struct file_operations mtd_fops = { -- owner: THIS_MODULE, -- llseek: mtd_lseek, /* lseek */ -- read: mtd_read, /* read */ -- write: mtd_write, /* write */ -- ioctl: mtd_ioctl, /* ioctl */ -- open: mtd_open, /* open */ -- release: mtd_close, /* release */ -+ .owner = THIS_MODULE, -+ .llseek = mtd_lseek, -+ .read = mtd_read, -+ .write = mtd_write, -+ .ioctl = mtd_ioctl, -+ .open = mtd_open, -+ .release = mtd_close, - }; - - -@@ -572,26 +507,18 @@ - - static int __init init_mtdchar(void) - { --#ifdef CONFIG_DEVFS_FS -- if (devfs_register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) -+ if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) - { - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", - MTD_CHAR_MAJOR); - return -EAGAIN; - } - -+#ifdef CONFIG_DEVFS_FS - devfs_dir_handle = devfs_mk_dir(NULL, "mtd", NULL); - - register_mtd_user(¬ifier); --#else -- if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) -- { -- printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", -- MTD_CHAR_MAJOR); -- return -EAGAIN; -- } - #endif -- - return 0; - } - -@@ -600,10 +527,8 @@ - #ifdef CONFIG_DEVFS_FS - unregister_mtd_user(¬ifier); - devfs_unregister(devfs_dir_handle); -- devfs_unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); --#else -- unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); - #endif -+ unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); - } - - module_init(init_mtdchar); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/mtdconcat.c linux/drivers/mtd/mtdconcat.c ---- linux-mips-2.4.24-pre2/drivers/mtd/mtdconcat.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/mtdconcat.c 2004-11-17 18:17:58.860341128 +0100 -@@ -3,9 +3,11 @@ - * - * (C) 2002 Robert Kaiser - * -+ * NAND support by Christian Gan -+ * - * This code is GPL - * -- * $Id$ -+ * $Id$ - */ - - #include -@@ -35,21 +37,20 @@ - #define SIZEOF_STRUCT_MTD_CONCAT(num_subdev) \ - ((sizeof(struct mtd_concat) + (num_subdev) * sizeof(struct mtd_info *))) - -- - /* - * Given a pointer to the MTD object in the mtd_concat structure, - * we can retrieve the pointer to that structure with this macro. - */ - #define CONCAT(x) ((struct mtd_concat *)(x)) - -- - /* - * MTD methods which look up the relevant subdevice, translate the - * effective address and pass through to the subdevice. - */ - --static int concat_read (struct mtd_info *mtd, loff_t from, size_t len, -- size_t *retlen, u_char *buf) -+static int -+concat_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t * retlen, u_char * buf) - { - struct mtd_concat *concat = CONCAT(mtd); - int err = -EINVAL; -@@ -57,43 +58,43 @@ - - *retlen = 0; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size, retsize; - -- if (from >= subdev->size) -- { -+ if (from >= subdev->size) { -+ /* Not destined for this subdev */ - size = 0; - from -= subdev->size; -+ continue; - } -- else -- { - if (from + len > subdev->size) -+ /* First part goes into this subdev */ - size = subdev->size - from; - else -+ /* Entire transaction goes into this subdev */ - size = len; - - err = subdev->read(subdev, from, size, &retsize, buf); - -- if(err) -+ if (err) - break; - - *retlen += retsize; - len -= size; -- if(len == 0) -+ if (len == 0) - break; - - err = -EINVAL; - buf += size; - from = 0; - } -- } - return err; - } - --static int concat_write (struct mtd_info *mtd, loff_t to, size_t len, -- size_t *retlen, const u_char *buf) -+static int -+concat_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t * retlen, const u_char * buf) - { - struct mtd_concat *concat = CONCAT(mtd); - int err = -EINVAL; -@@ -104,18 +105,15 @@ - - *retlen = 0; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size, retsize; - -- if (to >= subdev->size) -- { -+ if (to >= subdev->size) { - size = 0; - to -= subdev->size; -+ continue; - } -- else -- { - if (to + len > subdev->size) - size = subdev->size - to; - else -@@ -126,25 +124,232 @@ - else - err = subdev->write(subdev, to, size, &retsize, buf); - -- if(err) -+ if (err) - break; - - *retlen += retsize; - len -= size; -- if(len == 0) -+ if (len == 0) - break; - - err = -EINVAL; - buf += size; - to = 0; - } -+ return err; -+} -+ -+static int -+concat_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t * retlen, u_char * buf, u_char * eccbuf, -+ struct nand_oobinfo *oobsel) -+{ -+ struct mtd_concat *concat = CONCAT(mtd); -+ int err = -EINVAL; -+ int i; -+ -+ *retlen = 0; -+ -+ for (i = 0; i < concat->num_subdev; i++) { -+ struct mtd_info *subdev = concat->subdev[i]; -+ size_t size, retsize; -+ -+ if (from >= subdev->size) { -+ /* Not destined for this subdev */ -+ size = 0; -+ from -= subdev->size; -+ continue; -+ } -+ -+ if (from + len > subdev->size) -+ /* First part goes into this subdev */ -+ size = subdev->size - from; -+ else -+ /* Entire transaction goes into this subdev */ -+ size = len; -+ -+ if (subdev->read_ecc) -+ err = subdev->read_ecc(subdev, from, size, -+ &retsize, buf, eccbuf, oobsel); -+ else -+ err = -EINVAL; -+ -+ if (err) -+ break; -+ -+ *retlen += retsize; -+ len -= size; -+ if (len == 0) -+ break; -+ -+ err = -EINVAL; -+ buf += size; -+ if (eccbuf) { -+ eccbuf += subdev->oobsize; -+ /* in nand.c at least, eccbufs are -+ tagged with 2 (int)eccstatus'; we -+ must account for these */ -+ eccbuf += 2 * (sizeof (int)); -+ } -+ from = 0; - } - return err; - } - --static void concat_erase_callback (struct erase_info *instr) -+static int -+concat_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t * retlen, const u_char * buf, u_char * eccbuf, -+ struct nand_oobinfo *oobsel) - { -- wake_up((wait_queue_head_t *)instr->priv); -+ struct mtd_concat *concat = CONCAT(mtd); -+ int err = -EINVAL; -+ int i; -+ -+ if (!(mtd->flags & MTD_WRITEABLE)) -+ return -EROFS; -+ -+ *retlen = 0; -+ -+ for (i = 0; i < concat->num_subdev; i++) { -+ struct mtd_info *subdev = concat->subdev[i]; -+ size_t size, retsize; -+ -+ if (to >= subdev->size) { -+ size = 0; -+ to -= subdev->size; -+ continue; -+ } -+ if (to + len > subdev->size) -+ size = subdev->size - to; -+ else -+ size = len; -+ -+ if (!(subdev->flags & MTD_WRITEABLE)) -+ err = -EROFS; -+ else if (subdev->write_ecc) -+ err = subdev->write_ecc(subdev, to, size, -+ &retsize, buf, eccbuf, oobsel); -+ else -+ err = -EINVAL; -+ -+ if (err) -+ break; -+ -+ *retlen += retsize; -+ len -= size; -+ if (len == 0) -+ break; -+ -+ err = -EINVAL; -+ buf += size; -+ if (eccbuf) -+ eccbuf += subdev->oobsize; -+ to = 0; -+ } -+ return err; -+} -+ -+static int -+concat_read_oob(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t * retlen, u_char * buf) -+{ -+ struct mtd_concat *concat = CONCAT(mtd); -+ int err = -EINVAL; -+ int i; -+ -+ *retlen = 0; -+ -+ for (i = 0; i < concat->num_subdev; i++) { -+ struct mtd_info *subdev = concat->subdev[i]; -+ size_t size, retsize; -+ -+ if (from >= subdev->size) { -+ /* Not destined for this subdev */ -+ size = 0; -+ from -= subdev->size; -+ continue; -+ } -+ if (from + len > subdev->size) -+ /* First part goes into this subdev */ -+ size = subdev->size - from; -+ else -+ /* Entire transaction goes into this subdev */ -+ size = len; -+ -+ if (subdev->read_oob) -+ err = subdev->read_oob(subdev, from, size, -+ &retsize, buf); -+ else -+ err = -EINVAL; -+ -+ if (err) -+ break; -+ -+ *retlen += retsize; -+ len -= size; -+ if (len == 0) -+ break; -+ -+ err = -EINVAL; -+ buf += size; -+ from = 0; -+ } -+ return err; -+} -+ -+static int -+concat_write_oob(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t * retlen, const u_char * buf) -+{ -+ struct mtd_concat *concat = CONCAT(mtd); -+ int err = -EINVAL; -+ int i; -+ -+ if (!(mtd->flags & MTD_WRITEABLE)) -+ return -EROFS; -+ -+ *retlen = 0; -+ -+ for (i = 0; i < concat->num_subdev; i++) { -+ struct mtd_info *subdev = concat->subdev[i]; -+ size_t size, retsize; -+ -+ if (to >= subdev->size) { -+ size = 0; -+ to -= subdev->size; -+ continue; -+ } -+ if (to + len > subdev->size) -+ size = subdev->size - to; -+ else -+ size = len; -+ -+ if (!(subdev->flags & MTD_WRITEABLE)) -+ err = -EROFS; -+ else if (subdev->write_oob) -+ err = subdev->write_oob(subdev, to, size, &retsize, -+ buf); -+ else -+ err = -EINVAL; -+ -+ if (err) -+ break; -+ -+ *retlen += retsize; -+ len -= size; -+ if (len == 0) -+ break; -+ -+ err = -EINVAL; -+ buf += size; -+ to = 0; -+ } -+ return err; -+} -+ -+static void concat_erase_callback(struct erase_info *instr) -+{ -+ wake_up((wait_queue_head_t *) instr->priv); - } - - static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase) -@@ -160,18 +365,18 @@ - - erase->mtd = mtd; - erase->callback = concat_erase_callback; -- erase->priv = (unsigned long)&waitq; -+ erase->priv = (unsigned long) &waitq; - - /* - * FIXME: Allow INTERRUPTIBLE. Which means - * not having the wait_queue head on the stack. - */ - err = mtd->erase(mtd, erase); -- if (!err) -- { -+ if (!err) { - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&waitq, &wait); -- if (erase->state != MTD_ERASE_DONE && erase->state != MTD_ERASE_FAILED) -+ if (erase->state != MTD_ERASE_DONE -+ && erase->state != MTD_ERASE_FAILED) - schedule(); - remove_wait_queue(&waitq, &wait); - set_current_state(TASK_RUNNING); -@@ -181,7 +386,7 @@ - return err; - } - --static int concat_erase (struct mtd_info *mtd, struct erase_info *instr) -+static int concat_erase(struct mtd_info *mtd, struct erase_info *instr) - { - struct mtd_concat *concat = CONCAT(mtd); - struct mtd_info *subdev; -@@ -192,10 +397,10 @@ - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; - -- if(instr->addr > concat->mtd.size) -+ if (instr->addr > concat->mtd.size) - return -EINVAL; - -- if(instr->len + instr->addr > concat->mtd.size) -+ if (instr->len + instr->addr > concat->mtd.size) - return -EINVAL; - - /* -@@ -204,23 +409,22 @@ - * region info rather than looking at each particular sub-device - * in turn. - */ -- if (!concat->mtd.numeraseregions) -- { /* the easy case: device has uniform erase block size */ -- if(instr->addr & (concat->mtd.erasesize - 1)) -+ if (!concat->mtd.numeraseregions) { -+ /* the easy case: device has uniform erase block size */ -+ if (instr->addr & (concat->mtd.erasesize - 1)) - return -EINVAL; -- if(instr->len & (concat->mtd.erasesize - 1)) -+ if (instr->len & (concat->mtd.erasesize - 1)) - return -EINVAL; -- } -- else -- { /* device has variable erase size */ -- struct mtd_erase_region_info *erase_regions = concat->mtd.eraseregions; -+ } else { -+ /* device has variable erase size */ -+ struct mtd_erase_region_info *erase_regions = -+ concat->mtd.eraseregions; - - /* - * Find the erase region where the to-be-erased area begins: - */ -- for(i = 0; i < concat->mtd.numeraseregions && -- instr->addr >= erase_regions[i].offset; i++) -- ; -+ for (i = 0; i < concat->mtd.numeraseregions && -+ instr->addr >= erase_regions[i].offset; i++) ; - --i; - - /* -@@ -228,25 +432,26 @@ - * to-be-erased area begins. Verify that the starting - * offset is aligned to this region's erase size: - */ -- if (instr->addr & (erase_regions[i].erasesize-1)) -+ if (instr->addr & (erase_regions[i].erasesize - 1)) - return -EINVAL; - - /* - * now find the erase region where the to-be-erased area ends: - */ -- for(; i < concat->mtd.numeraseregions && -- (instr->addr + instr->len) >= erase_regions[i].offset ; ++i) -- ; -+ for (; i < concat->mtd.numeraseregions && -+ (instr->addr + instr->len) >= erase_regions[i].offset; -+ ++i) ; - --i; - /* - * check if the ending offset is aligned to this region's erase size - */ -- if ((instr->addr + instr->len) & (erase_regions[i].erasesize-1)) -+ if ((instr->addr + instr->len) & (erase_regions[i].erasesize - -+ 1)) - return -EINVAL; - } - - /* make a local copy of instr to avoid modifying the caller's struct */ -- erase = kmalloc(sizeof(struct erase_info),GFP_KERNEL); -+ erase = kmalloc(sizeof (struct erase_info), GFP_KERNEL); - - if (!erase) - return -ENOMEM; -@@ -258,39 +463,40 @@ - * find the subdevice where the to-be-erased area begins, adjust - * starting offset to be relative to the subdevice start - */ -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - subdev = concat->subdev[i]; -- if(subdev->size <= erase->addr) -+ if (subdev->size <= erase->addr) - erase->addr -= subdev->size; - else - break; - } -- if(i >= concat->num_subdev) /* must never happen since size */ -- BUG(); /* limit has been verified above */ -+ -+ /* must never happen since size limit has been verified above */ -+ if (i >= concat->num_subdev) -+ BUG(); - - /* now do the erase: */ - err = 0; -- for(;length > 0; i++) /* loop for all subevices affected by this request */ -- { -+ for (; length > 0; i++) { -+ /* loop for all subdevices affected by this request */ - subdev = concat->subdev[i]; /* get current subdevice */ - - /* limit length to subdevice's size: */ -- if(erase->addr + length > subdev->size) -+ if (erase->addr + length > subdev->size) - erase->len = subdev->size - erase->addr; - else - erase->len = length; - -- if (!(subdev->flags & MTD_WRITEABLE)) -- { -+ if (!(subdev->flags & MTD_WRITEABLE)) { - err = -EROFS; - break; - } - length -= erase->len; -- if ((err = concat_dev_erase(subdev, erase))) -- { -- if(err == -EINVAL) /* sanity check: must never happen since */ -- BUG(); /* block alignment has been checked above */ -+ if ((err = concat_dev_erase(subdev, erase))) { -+ /* sanity check: should never happen since -+ * block alignment has been checked above */ -+ if (err == -EINVAL) -+ BUG(); - break; - } - /* -@@ -313,7 +519,7 @@ - return 0; - } - --static int concat_lock (struct mtd_info *mtd, loff_t ofs, size_t len) -+static int concat_lock(struct mtd_info *mtd, loff_t ofs, size_t len) - { - struct mtd_concat *concat = CONCAT(mtd); - int i, err = -EINVAL; -@@ -321,18 +527,15 @@ - if ((len + ofs) > mtd->size) - return -EINVAL; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size; - -- if (ofs >= subdev->size) -- { -+ if (ofs >= subdev->size) { - size = 0; - ofs -= subdev->size; -+ continue; - } -- else -- { - if (ofs + len > subdev->size) - size = subdev->size - ofs; - else -@@ -340,21 +543,21 @@ - - err = subdev->lock(subdev, ofs, size); - -- if(err) -+ if (err) - break; - - len -= size; -- if(len == 0) -+ if (len == 0) - break; - - err = -EINVAL; - ofs = 0; - } -- } -+ - return err; - } - --static int concat_unlock (struct mtd_info *mtd, loff_t ofs, size_t len) -+static int concat_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) - { - struct mtd_concat *concat = CONCAT(mtd); - int i, err = 0; -@@ -362,18 +565,15 @@ - if ((len + ofs) > mtd->size) - return -EINVAL; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size; - -- if (ofs >= subdev->size) -- { -+ if (ofs >= subdev->size) { - size = 0; - ofs -= subdev->size; -+ continue; - } -- else -- { - if (ofs + len > subdev->size) - size = subdev->size - ofs; - else -@@ -381,17 +581,17 @@ - - err = subdev->unlock(subdev, ofs, size); - -- if(err) -+ if (err) - break; - - len -= size; -- if(len == 0) -+ if (len == 0) - break; - - err = -EINVAL; - ofs = 0; - } -- } -+ - return err; - } - -@@ -400,8 +600,7 @@ - struct mtd_concat *concat = CONCAT(mtd); - int i; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - subdev->sync(subdev); - } -@@ -412,10 +611,9 @@ - struct mtd_concat *concat = CONCAT(mtd); - int i, rc = 0; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; -- if((rc = subdev->suspend(subdev)) < 0) -+ if ((rc = subdev->suspend(subdev)) < 0) - return rc; - } - return rc; -@@ -426,8 +624,7 @@ - struct mtd_concat *concat = CONCAT(mtd); - int i; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - subdev->resume(subdev); - } -@@ -439,11 +636,10 @@ - * stored to *new_dev upon success. This function does _not_ - * register any devices: this is the caller's responsibility. - */ --struct mtd_info *mtd_concat_create( -- struct mtd_info *subdev[], /* subdevices to concatenate */ -+struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to concatenate */ - int num_devs, /* number of subdevices */ -- char *name) /* name for the new device */ --{ -+ char *name) -+{ /* name for the new device */ - int i; - size_t size; - struct mtd_concat *concat; -@@ -451,21 +647,21 @@ - int num_erase_region; - - printk(KERN_NOTICE "Concatenating MTD devices:\n"); -- for(i = 0; i < num_devs; i++) -+ for (i = 0; i < num_devs; i++) - printk(KERN_NOTICE "(%d): \"%s\"\n", i, subdev[i]->name); - printk(KERN_NOTICE "into device \"%s\"\n", name); - - /* allocate the device structure */ - size = SIZEOF_STRUCT_MTD_CONCAT(num_devs); -- concat = kmalloc (size, GFP_KERNEL); -- if(!concat) -- { -- printk ("memory allocation error while creating concatenated device \"%s\"\n", -+ concat = kmalloc(size, GFP_KERNEL); -+ if (!concat) { -+ printk -+ ("memory allocation error while creating concatenated device \"%s\"\n", - name); - return NULL; - } - memset(concat, 0, size); -- concat->subdev = (struct mtd_info **)(concat + 1); -+ concat->subdev = (struct mtd_info **) (concat + 1); - - /* - * Set up the new "super" device's MTD object structure, check for -@@ -479,39 +675,53 @@ - concat->mtd.oobsize = subdev[0]->oobsize; - concat->mtd.ecctype = subdev[0]->ecctype; - concat->mtd.eccsize = subdev[0]->eccsize; -+ if (subdev[0]->read_ecc) -+ concat->mtd.read_ecc = concat_read_ecc; -+ if (subdev[0]->write_ecc) -+ concat->mtd.write_ecc = concat_write_ecc; -+ if (subdev[0]->read_oob) -+ concat->mtd.read_oob = concat_read_oob; -+ if (subdev[0]->write_oob) -+ concat->mtd.write_oob = concat_write_oob; - - concat->subdev[0] = subdev[0]; - -- for(i = 1; i < num_devs; i++) -- { -- if(concat->mtd.type != subdev[i]->type) -- { -+ for (i = 1; i < num_devs; i++) { -+ if (concat->mtd.type != subdev[i]->type) { - kfree(concat); -- printk ("Incompatible device type on \"%s\"\n", subdev[i]->name); -+ printk("Incompatible device type on \"%s\"\n", -+ subdev[i]->name); - return NULL; - } -- if(concat->mtd.flags != subdev[i]->flags) -- { /* -- * Expect all flags except MTD_WRITEABLE to be equal on -- * all subdevices. -+ if (concat->mtd.flags != subdev[i]->flags) { -+ /* -+ * Expect all flags except MTD_WRITEABLE to be -+ * equal on all subdevices. - */ -- if((concat->mtd.flags ^ subdev[i]->flags) & ~MTD_WRITEABLE) -- { -+ if ((concat->mtd.flags ^ subdev[i]-> -+ flags) & ~MTD_WRITEABLE) { - kfree(concat); -- printk ("Incompatible device flags on \"%s\"\n", subdev[i]->name); -+ printk("Incompatible device flags on \"%s\"\n", -+ subdev[i]->name); - return NULL; -- } -- else /* if writeable attribute differs, make super device writeable */ -- concat->mtd.flags |= subdev[i]->flags & MTD_WRITEABLE; -+ } else -+ /* if writeable attribute differs, -+ make super device writeable */ -+ concat->mtd.flags |= -+ subdev[i]->flags & MTD_WRITEABLE; - } - concat->mtd.size += subdev[i]->size; -- if(concat->mtd.oobblock != subdev[i]->oobblock || -+ if (concat->mtd.oobblock != subdev[i]->oobblock || - concat->mtd.oobsize != subdev[i]->oobsize || - concat->mtd.ecctype != subdev[i]->ecctype || -- concat->mtd.eccsize != subdev[i]->eccsize) -- { -+ concat->mtd.eccsize != subdev[i]->eccsize || -+ !concat->mtd.read_ecc != !subdev[i]->read_ecc || -+ !concat->mtd.write_ecc != !subdev[i]->write_ecc || -+ !concat->mtd.read_oob != !subdev[i]->read_oob || -+ !concat->mtd.write_oob != !subdev[i]->write_oob) { - kfree(concat); -- printk ("Incompatible OOB or ECC data on \"%s\"\n", subdev[i]->name); -+ printk("Incompatible OOB or ECC data on \"%s\"\n", -+ subdev[i]->name); - return NULL; - } - concat->subdev[i] = subdev[i]; -@@ -535,7 +745,6 @@ - concat->mtd.suspend = concat_suspend; - concat->mtd.resume = concat_resume; - -- - /* - * Combine the erase block size info of the subdevices: - * -@@ -544,44 +753,44 @@ - */ - max_erasesize = curr_erasesize = subdev[0]->erasesize; - num_erase_region = 1; -- for(i = 0; i < num_devs; i++) -- { -- if(subdev[i]->numeraseregions == 0) -- { /* current subdevice has uniform erase size */ -- if(subdev[i]->erasesize != curr_erasesize) -- { /* if it differs from the last subdevice's erase size, count it */ -+ for (i = 0; i < num_devs; i++) { -+ if (subdev[i]->numeraseregions == 0) { -+ /* current subdevice has uniform erase size */ -+ if (subdev[i]->erasesize != curr_erasesize) { -+ /* if it differs from the last subdevice's erase size, count it */ - ++num_erase_region; - curr_erasesize = subdev[i]->erasesize; -- if(curr_erasesize > max_erasesize) -+ if (curr_erasesize > max_erasesize) - max_erasesize = curr_erasesize; - } -- } -- else -- { /* current subdevice has variable erase size */ -+ } else { -+ /* current subdevice has variable erase size */ - int j; -- for(j = 0; j < subdev[i]->numeraseregions; j++) -- { /* walk the list of erase regions, count any changes */ -- if(subdev[i]->eraseregions[j].erasesize != curr_erasesize) -- { -+ for (j = 0; j < subdev[i]->numeraseregions; j++) { -+ -+ /* walk the list of erase regions, count any changes */ -+ if (subdev[i]->eraseregions[j].erasesize != -+ curr_erasesize) { - ++num_erase_region; -- curr_erasesize = subdev[i]->eraseregions[j].erasesize; -- if(curr_erasesize > max_erasesize) -+ curr_erasesize = -+ subdev[i]->eraseregions[j]. -+ erasesize; -+ if (curr_erasesize > max_erasesize) - max_erasesize = curr_erasesize; - } - } - } - } - -- if(num_erase_region == 1) -- { /* -+ if (num_erase_region == 1) { -+ /* - * All subdevices have the same uniform erase size. - * This is easy: - */ - concat->mtd.erasesize = curr_erasesize; - concat->mtd.numeraseregions = 0; -- } -- else -- { /* -+ } else { -+ /* - * erase block size varies across the subdevices: allocate - * space to store the data describing the variable erase regions - */ -@@ -590,12 +799,13 @@ - - concat->mtd.erasesize = max_erasesize; - concat->mtd.numeraseregions = num_erase_region; -- concat->mtd.eraseregions = erase_region_p = kmalloc ( -- num_erase_region * sizeof(struct mtd_erase_region_info), GFP_KERNEL); -- if(!erase_region_p) -- { -+ concat->mtd.eraseregions = erase_region_p = -+ kmalloc(num_erase_region * -+ sizeof (struct mtd_erase_region_info), GFP_KERNEL); -+ if (!erase_region_p) { - kfree(concat); -- printk ("memory allocation error while creating erase region list" -+ printk -+ ("memory allocation error while creating erase region list" - " for device \"%s\"\n", name); - return NULL; - } -@@ -606,41 +816,48 @@ - */ - curr_erasesize = subdev[0]->erasesize; - begin = position = 0; -- for(i = 0; i < num_devs; i++) -- { -- if(subdev[i]->numeraseregions == 0) -- { /* current subdevice has uniform erase size */ -- if(subdev[i]->erasesize != curr_erasesize) -- { /* -+ for (i = 0; i < num_devs; i++) { -+ if (subdev[i]->numeraseregions == 0) { -+ /* current subdevice has uniform erase size */ -+ if (subdev[i]->erasesize != curr_erasesize) { -+ /* - * fill in an mtd_erase_region_info structure for the area - * we have walked so far: - */ - erase_region_p->offset = begin; -- erase_region_p->erasesize = curr_erasesize; -- erase_region_p->numblocks = (position - begin) / curr_erasesize; -+ erase_region_p->erasesize = -+ curr_erasesize; -+ erase_region_p->numblocks = -+ (position - begin) / curr_erasesize; - begin = position; - - curr_erasesize = subdev[i]->erasesize; - ++erase_region_p; - } - position += subdev[i]->size; -- } -- else -- { /* current subdevice has variable erase size */ -+ } else { -+ /* current subdevice has variable erase size */ - int j; -- for(j = 0; j < subdev[i]->numeraseregions; j++) -- { /* walk the list of erase regions, count any changes */ -- if(subdev[i]->eraseregions[j].erasesize != curr_erasesize) -- { -+ for (j = 0; j < subdev[i]->numeraseregions; j++) { -+ /* walk the list of erase regions, count any changes */ -+ if (subdev[i]->eraseregions[j]. -+ erasesize != curr_erasesize) { - erase_region_p->offset = begin; -- erase_region_p->erasesize = curr_erasesize; -- erase_region_p->numblocks = (position - begin) / curr_erasesize; -+ erase_region_p->erasesize = -+ curr_erasesize; -+ erase_region_p->numblocks = -+ (position - -+ begin) / curr_erasesize; - begin = position; - -- curr_erasesize = subdev[i]->eraseregions[j].erasesize; -+ curr_erasesize = -+ subdev[i]->eraseregions[j]. -+ erasesize; - ++erase_region_p; - } -- position += subdev[i]->eraseregions[j].numblocks * curr_erasesize; -+ position += -+ subdev[i]->eraseregions[j]. -+ numblocks * curr_erasesize; - } - } - } -@@ -660,16 +877,14 @@ - void mtd_concat_destroy(struct mtd_info *mtd) - { - struct mtd_concat *concat = CONCAT(mtd); -- if(concat->mtd.numeraseregions) -+ if (concat->mtd.numeraseregions) - kfree(concat->mtd.eraseregions); - kfree(concat); - } - -- - EXPORT_SYMBOL(mtd_concat_create); - EXPORT_SYMBOL(mtd_concat_destroy); - -- - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Robert Kaiser "); - MODULE_DESCRIPTION("Generic support for concatenating of MTD devices"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/mtdcore.c linux/drivers/mtd/mtdcore.c ---- linux-mips-2.4.24-pre2/drivers/mtd/mtdcore.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/mtdcore.c 2004-11-17 18:17:58.862340824 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Core registration and callback routines for MTD - * drivers and users. -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include - #ifdef CONFIG_PROC_FS - #include -@@ -24,9 +25,15 @@ - - #include - --static DECLARE_MUTEX(mtd_table_mutex); --static struct mtd_info *mtd_table[MAX_MTD_DEVICES]; --static struct mtd_notifier *mtd_notifiers = NULL; -+/* These are exported solely for the purpose of mtd_blkdevs.c. You -+ should not use them for _anything_ else */ -+DECLARE_MUTEX(mtd_table_mutex); -+struct mtd_info *mtd_table[MAX_MTD_DEVICES]; -+ -+EXPORT_SYMBOL_GPL(mtd_table_mutex); -+EXPORT_SYMBOL_GPL(mtd_table); -+ -+static LIST_HEAD(mtd_notifiers); - - /** - * add_mtd_device - register an MTD device -@@ -44,21 +51,28 @@ - - down(&mtd_table_mutex); - -- for (i=0; i< MAX_MTD_DEVICES; i++) -- if (!mtd_table[i]) -- { -- struct mtd_notifier *not=mtd_notifiers; -+ for (i=0; i < MAX_MTD_DEVICES; i++) -+ if (!mtd_table[i]) { -+ struct list_head *this; - - mtd_table[i] = mtd; - mtd->index = i; -+ mtd->usecount = 0; -+ - DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name); -- while (not) -- { -- (*(not->add))(mtd); -- not = not->next; -+ /* No need to get a refcount on the module containing -+ the notifier, since we hold the mtd_table_mutex */ -+ list_for_each(this, &mtd_notifiers) { -+ struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list); -+ not->add(mtd); - } -+ - up(&mtd_table_mutex); -- MOD_INC_USE_COUNT; -+ /* 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 -+ either. :) */ -+ __module_get(THIS_MODULE); - return 0; - } - -@@ -78,29 +92,34 @@ - - int del_mtd_device (struct mtd_info *mtd) - { -- struct mtd_notifier *not=mtd_notifiers; -- int i; -+ int ret; - - down(&mtd_table_mutex); - -- for (i=0; i < MAX_MTD_DEVICES; i++) -- { -- if (mtd_table[i] == mtd) -- { -- while (not) -- { -- (*(not->remove))(mtd); -- not = not->next; -- } -- mtd_table[i] = NULL; -- up (&mtd_table_mutex); -- MOD_DEC_USE_COUNT; -- return 0; -+ if (mtd_table[mtd->index] != mtd) { -+ ret = -ENODEV; -+ } else if (mtd->usecount) { -+ printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n", -+ mtd->index, mtd->name, mtd->usecount); -+ ret = -EBUSY; -+ } else { -+ struct list_head *this; -+ -+ /* No need to get a refcount on the module containing -+ the notifier, since we hold the mtd_table_mutex */ -+ list_for_each(this, &mtd_notifiers) { -+ struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list); -+ not->remove(mtd); - } -+ -+ mtd_table[mtd->index] = NULL; -+ -+ module_put(THIS_MODULE); -+ ret = 0; - } - - up(&mtd_table_mutex); -- return 1; -+ return ret; - } - - /** -@@ -118,10 +137,9 @@ - - down(&mtd_table_mutex); - -- new->next = mtd_notifiers; -- mtd_notifiers = new; -+ list_add(&new->list, &mtd_notifiers); - -- MOD_INC_USE_COUNT; -+ __module_get(THIS_MODULE); - - for (i=0; i< MAX_MTD_DEVICES; i++) - if (mtd_table[i]) -@@ -142,34 +160,24 @@ - - int unregister_mtd_user (struct mtd_notifier *old) - { -- struct mtd_notifier **prev = &mtd_notifiers; -- struct mtd_notifier *cur; - int i; - - down(&mtd_table_mutex); - -- while ((cur = *prev)) { -- if (cur == old) { -- *prev = cur->next; -- -- MOD_DEC_USE_COUNT; -+ module_put(THIS_MODULE); - - for (i=0; i< MAX_MTD_DEVICES; i++) - if (mtd_table[i]) - old->remove(mtd_table[i]); - -+ list_del(&old->list); - up(&mtd_table_mutex); - return 0; -- } -- prev = &cur->next; -- } -- up(&mtd_table_mutex); -- return 1; - } - - - /** -- * __get_mtd_device - obtain a validated handle for an MTD device -+ * get_mtd_device - obtain a validated handle for an MTD device - * @mtd: last known address of the required MTD device - * @num: internal device number of the required MTD device - * -@@ -177,11 +185,10 @@ - * table, if any. Given an address and num == -1, search the device table - * for a device with that address and return if it's still present. Given - * both, return the num'th driver only if its address matches. Return NULL -- * if not. get_mtd_device() increases the use count, but -- * __get_mtd_device() doesn't - you should generally use get_mtd_device(). -+ * if not. - */ - --struct mtd_info *__get_mtd_device(struct mtd_info *mtd, int num) -+struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) - { - struct mtd_info *ret = NULL; - int i; -@@ -198,10 +205,27 @@ - ret = NULL; - } - -+ if (ret && !try_module_get(ret->owner)) -+ ret = NULL; -+ -+ if (ret) -+ ret->usecount++; -+ - up(&mtd_table_mutex); - return ret; - } - -+void put_mtd_device(struct mtd_info *mtd) -+{ -+ int c; -+ -+ down(&mtd_table_mutex); -+ c = --mtd->usecount; -+ up(&mtd_table_mutex); -+ BUG_ON(c < 0); -+ -+ module_put(mtd->owner); -+} - - /* default_mtd_writev - default mtd writev method for MTD devices that - * dont implement their own -@@ -265,7 +289,8 @@ - - EXPORT_SYMBOL(add_mtd_device); - EXPORT_SYMBOL(del_mtd_device); --EXPORT_SYMBOL(__get_mtd_device); -+EXPORT_SYMBOL(get_mtd_device); -+EXPORT_SYMBOL(put_mtd_device); - EXPORT_SYMBOL(register_mtd_user); - EXPORT_SYMBOL(unregister_mtd_user); - EXPORT_SYMBOL(default_mtd_writev); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/mtdpart.c linux/drivers/mtd/mtdpart.c ---- linux-mips-2.4.24-pre2/drivers/mtd/mtdpart.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/mtdpart.c 2004-11-17 18:17:58.863340672 +0100 -@@ -5,7 +5,7 @@ - * - * This code is GPL - * -- * $Id$ -+ * $Id$ - * - * 02-21-2002 Thomas Gleixner - * added support for read_oob, write_oob -@@ -16,10 +16,11 @@ - #include - #include - #include -- -+#include -+#include - #include - #include -- -+#include - - /* Our partition linked list */ - static LIST_HEAD(mtd_partitions); -@@ -54,8 +55,12 @@ - len = 0; - else if (from + len > mtd->size) - len = mtd->size - from; -+ if (part->master->read_ecc == NULL) - return part->master->read (part->master, from + part->offset, - len, retlen, buf); -+ else -+ return part->master->read_ecc (part->master, from + part->offset, -+ len, retlen, buf, NULL, &mtd->oobinfo); - } - - static int part_point (struct mtd_info *mtd, loff_t from, size_t len, -@@ -78,9 +83,11 @@ - - - static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, -- size_t *retlen, u_char *buf, u_char *eccbuf, int oobsel) -+ size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel) - { - struct mtd_part *part = PART(mtd); -+ if (oobsel == NULL) -+ oobsel = &mtd->oobinfo; - if (from >= mtd->size) - len = 0; - else if (from + len > mtd->size) -@@ -113,7 +120,7 @@ - size_t *retlen, u_char *buf) - { - struct mtd_part *part = PART(mtd); -- return part->master->read_user_prot_reg (part->master, from, -+ return part->master->read_fact_prot_reg (part->master, from, - len, retlen, buf); - } - -@@ -127,17 +134,24 @@ - len = 0; - else if (to + len > mtd->size) - len = mtd->size - to; -+ if (part->master->write_ecc == NULL) - return part->master->write (part->master, to + part->offset, - len, retlen, buf); -+ else -+ return part->master->write_ecc (part->master, to + part->offset, -+ len, retlen, buf, NULL, &mtd->oobinfo); -+ - } - - static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf, -- u_char *eccbuf, int oobsel) -+ u_char *eccbuf, struct nand_oobinfo *oobsel) - { - struct mtd_part *part = PART(mtd); - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; -+ if (oobsel == NULL) -+ oobsel = &mtd->oobinfo; - if (to >= mtd->size) - len = 0; - else if (to + len > mtd->size) -@@ -174,25 +188,37 @@ - struct mtd_part *part = PART(mtd); - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; -+ if (part->master->writev_ecc == NULL) - return part->master->writev (part->master, vecs, count, - to + part->offset, retlen); -+ else -+ return part->master->writev_ecc (part->master, vecs, count, -+ to + part->offset, retlen, -+ NULL, &mtd->oobinfo); - } - - static int part_readv (struct mtd_info *mtd, struct iovec *vecs, - unsigned long count, loff_t from, size_t *retlen) - { - struct mtd_part *part = PART(mtd); -+ if (part->master->readv_ecc == NULL) - return part->master->readv (part->master, vecs, count, - from + part->offset, retlen); -+ else -+ return part->master->readv_ecc (part->master, vecs, count, -+ from + part->offset, retlen, -+ NULL, &mtd->oobinfo); - } - - static int part_writev_ecc (struct mtd_info *mtd, const struct iovec *vecs, - unsigned long count, loff_t to, size_t *retlen, -- u_char *eccbuf, int oobsel) -+ u_char *eccbuf, struct nand_oobinfo *oobsel) - { - struct mtd_part *part = PART(mtd); - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; -+ if (oobsel == NULL) -+ oobsel = &mtd->oobinfo; - return part->master->writev_ecc (part->master, vecs, count, - to + part->offset, retlen, - eccbuf, oobsel); -@@ -200,9 +226,11 @@ - - static int part_readv_ecc (struct mtd_info *mtd, struct iovec *vecs, - unsigned long count, loff_t from, size_t *retlen, -- u_char *eccbuf, int oobsel) -+ u_char *eccbuf, struct nand_oobinfo *oobsel) - { - struct mtd_part *part = PART(mtd); -+ if (oobsel == NULL) -+ oobsel = &mtd->oobinfo; - return part->master->readv_ecc (part->master, vecs, count, - from + part->offset, retlen, - eccbuf, oobsel); -@@ -288,7 +316,7 @@ - */ - - int add_mtd_partitions(struct mtd_info *master, -- struct mtd_partition *parts, -+ const struct mtd_partition *parts, - int nbparts) - { - struct mtd_part *slave; -@@ -321,7 +349,7 @@ - - slave->mtd.name = parts[i].name; - slave->mtd.bank_size = master->bank_size; -- slave->mtd.module = master->module; -+ slave->mtd.owner = master->owner; - - slave->mtd.read = part_read; - slave->mtd.write = part_write; -@@ -452,6 +480,75 @@ - EXPORT_SYMBOL(add_mtd_partitions); - EXPORT_SYMBOL(del_mtd_partitions); - -+static spinlock_t part_parser_lock = SPIN_LOCK_UNLOCKED; -+static LIST_HEAD(part_parsers); -+ -+struct mtd_part_parser *get_partition_parser(const char *name) -+{ -+ struct list_head *this; -+ void *ret = NULL; -+ spin_lock(&part_parser_lock); -+ -+ list_for_each(this, &part_parsers) { -+ struct mtd_part_parser *p = list_entry(this, struct mtd_part_parser, list); -+ -+ if (!strcmp(p->name, name) && try_module_get(p->owner)) { -+ ret = p; -+ break; -+ } -+ } -+ spin_unlock(&part_parser_lock); -+ -+ return ret; -+} -+ -+int register_mtd_parser(struct mtd_part_parser *p) -+{ -+ spin_lock(&part_parser_lock); -+ list_add(&p->list, &part_parsers); -+ spin_unlock(&part_parser_lock); -+ -+ return 0; -+} -+ -+int deregister_mtd_parser(struct mtd_part_parser *p) -+{ -+ spin_lock(&part_parser_lock); -+ list_del(&p->list); -+ spin_unlock(&part_parser_lock); -+ return 0; -+} -+ -+int parse_mtd_partitions(struct mtd_info *master, const char **types, -+ struct mtd_partition **pparts, unsigned long origin) -+{ -+ struct mtd_part_parser *parser; -+ int ret = 0; -+ -+ for ( ; ret <= 0 && *types; types++) { -+ parser = get_partition_parser(*types); -+#ifdef CONFIG_KMOD -+ if (!parser && !request_module("%s", *types)) -+ parser = get_partition_parser(*types); -+#endif -+ if (!parser) { -+ printk(KERN_NOTICE "%s partition parsing not available\n", -+ *types); -+ continue; -+ } -+ ret = (*parser->parse_fn)(master, pparts, origin); -+ if (ret > 0) { -+ printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", -+ ret, parser->name, master->name); -+ } -+ put_partition_parser(parser); -+ } -+ return ret; -+} -+ -+EXPORT_SYMBOL_GPL(parse_mtd_partitions); -+EXPORT_SYMBOL_GPL(register_mtd_parser); -+EXPORT_SYMBOL_GPL(deregister_mtd_parser); - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Nicolas Pitre "); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/nand/Config.in linux/drivers/mtd/nand/Config.in ---- linux-mips-2.4.24-pre2/drivers/mtd/nand/Config.in 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/nand/Config.in 2004-11-17 18:17:59.159295680 +0100 -@@ -1,6 +1,6 @@ - # drivers/mtd/nand/Config.in - --# $Id$ -+# $Id$ - - mainmenu_option next_comment - -@@ -11,26 +11,27 @@ - bool ' Verify NAND page writes' CONFIG_MTD_NAND_VERIFY_WRITE - fi - --if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_P720T" = "y" ]; then -- dep_tristate ' NAND Flash device on SPIA board' CONFIG_MTD_NAND_SPIA $CONFIG_MTD_NAND -+if [ "$CONFIG_ARM" = "y" ]; then -+ dep_tristate ' NAND Flash device on SPIA board' CONFIG_MTD_NAND_SPIA $CONFIG_MTD_NAND $CONFIG_ARCH_P720T -+ dep_tristate ' NAND Flash device on TOTO board' CONFIG_MTD_NAND_TOTO $CONFIG_MTD_NAND $CONFIG_ARCH_OMAP -+ dep_tristate ' SmartMedia Card on AUTCPU12 board' CONFIG_MTD_NAND_AUTCPU12 $CONFIG_MTD_NAND $CONFIG_ARCH_AUTCPU12 -+ dep_tristate ' NAND Flash device on EDP7312 board' CONFIG_MTD_NAND_EDB7312 $CONFIG_MTD_NAND $CONFIG_ARCH_EDB7312 - fi - --if [ "$CONFIG_ARCH_AUTCPU12" = "y" ]; then -- dep_tristate ' SmartMedia Card on AUTCPU12 board' CONFIG_MTD_NAND_AUTCPU12 $CONFIG_MTD_NAND --fi -- --if [ "$CONFIG_ARCH_EDB7312" = "y" ]; then -- dep_tristate ' NAND Flash device on EDP7312 board' CONFIG_MTD_NAND_EDB7312 $CONFIG_MTD_NAND --fi -- --if [ "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" -o "$CONFIG_MTD_NAND" = "y" ]; then -+if [ "$CONFIG_MTD_DOC2001PLUS" = "y" -o "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" -o "$CONFIG_MTD_NAND" = "y" ]; then - define_bool CONFIG_MTD_NAND_IDS y -+else -+ if [ "$CONFIG_MTD_DOC2001PLUS" = "m" -o "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" -o "$CONFIG_MTD_NAND" = "m" ]; then -+ define_bool CONFIG_MTD_NAND_IDS m -+ fi - fi - --if [ "$CONFIG_MTD_NAND_IDS" != "y" ]; then --if [ "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" -o "$CONFIG_MTD_NAND" = "m" ]; then -- define_bool CONFIG_MTD_NAND_IDS m -+if [ "$CONFIG_TOSHIBA_RBTX4925" = "y" ]; then -+ dep_tristate ' SmartMedia Card on Toshiba RBTX4925 reference board' CONFIG_MTD_NAND_TX4925NDFMC $CONFIG_MTD_NAND $CONFIG_TOSHIBA_RBTX4925_MPLEX_NAND - fi -+ -+if [ "$CONFIG_TOSHIBA_RBTX4938" = "y" ]; then -+ dep_tristate ' NAND Flash device on Toshiba RBTX4938 reference board' CONFIG_MTD_NAND_TX4938NDFMC $CONFIG_MTD_NAND $CONFIG_TOSHIBA_RBTX4938_MPLEX_NAND - fi - - endmenu -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/nand/Makefile linux/drivers/mtd/nand/Makefile ---- linux-mips-2.4.24-pre2/drivers/mtd/nand/Makefile 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/nand/Makefile 2004-11-17 18:17:59.161295376 +0100 -@@ -1,16 +1,20 @@ - # - # linux/drivers/nand/Makefile - # --# $Id$ -+# $Id$ - -+ifeq ($(PATCHLEVEL),4) - O_TARGET := nandlink.o -- - export-objs := nand.o nand_ecc.o nand_ids.o -+endif - - obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o - obj-$(CONFIG_MTD_NAND_SPIA) += spia.o -+obj-$(CONFIG_MTD_NAND_TOTO) += toto.o - obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o - obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o -+obj-$(CONFIG_MTD_NAND_TX4925NDFMC) += tx4925ndfmc.o -+obj-$(CONFIG_MTD_NAND_TX4938NDFMC) += tx4938ndfmc.o - obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o - --include $(TOPDIR)/Rules.make -+-include $(TOPDIR)/Rules.make -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/nand/autcpu12.c linux/drivers/mtd/nand/autcpu12.c ---- linux-mips-2.4.24-pre2/drivers/mtd/nand/autcpu12.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/nand/autcpu12.c 2004-11-17 18:17:59.162295224 +0100 -@@ -4,9 +4,9 @@ - * Copyright (c) 2002 Thomas Gleixner - * - * Derived from drivers/mtd/spia.c -- * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) -+ * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) - * -- * $Id$ -+ * $Id$ - * - * 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 -@@ -25,10 +25,10 @@ - * added page_cache - * - * 10-06-2002 TG 128K card support added -- * - */ - - #include -+#include - #include - #include - #include -@@ -70,6 +70,7 @@ - /* - * Define partitions for flash devices - */ -+extern struct nand_oobinfo jffs2_oobinfo; - - static struct mtd_partition partition_info16k[] = { - { name: "AUTCPU12 flash partition 1", -@@ -95,7 +96,7 @@ - size: 16 * SZ_1M }, - { name: "AUTCPU12 flash partition 2", - offset: 16 * SZ_1M, -- size: 48 * SZ_1M}, -+ size: 48 * SZ_1M }, - }; - - static struct mtd_partition partition_info128k[] = { -@@ -104,7 +105,7 @@ - size: 16 * SZ_1M }, - { name: "AUTCPU12 flash partition 2", - offset: 16 * SZ_1M, -- size: 112 * SZ_1M}, -+ size: 112 * SZ_1M }, - }; - - #define NUM_PARTITIONS16K 2 -@@ -114,7 +115,7 @@ - /* - * hardware specific access to control-lines - */ --void autcpu12_hwcontrol(int cmd) -+static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd) - { - - switch(cmd){ -@@ -133,7 +134,7 @@ - /* - * read device ready pin - */ --int autcpu12_device_ready(void) -+int autcpu12_device_ready(struct mtd_info *mtd) - { - - return ( (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) & AUTCPU12_SMC_RDY) ? 1 : 0; -@@ -184,7 +185,7 @@ - this->eccmode = NAND_ECC_SOFT; - - /* Scan to find existance of the device */ -- if (nand_scan (autcpu12_mtd)) { -+ if (nand_scan (autcpu12_mtd, 1)) { - err = -ENXIO; - goto out_ior; - } -@@ -197,15 +198,6 @@ - goto out_ior; - } - -- /* Allocate memory for internal data buffer */ -- this->data_cache = kmalloc (sizeof(u_char) * (autcpu12_mtd->oobblock + autcpu12_mtd->oobsize), GFP_KERNEL); -- if (!this->data_cache) { -- printk ("Unable to allocate NAND data cache for AUTCPU12.\n"); -- err = -ENOMEM; -- goto out_buf; -- } -- this->cache_page = -1; -- - /* Register the partitions */ - switch(autcpu12_mtd->size){ - case SZ_16M: add_mtd_partitions(autcpu12_mtd, partition_info16k, NUM_PARTITIONS16K); break; -@@ -215,13 +207,11 @@ - default: { - printk ("Unsupported SmartMedia device\n"); - err = -ENXIO; -- goto out_cac; -+ goto out_buf; - } - } - goto out; - --out_cac: -- kfree (this->data_cache); - out_buf: - kfree (this->data_buf); - out_ior: -@@ -250,7 +240,6 @@ - - /* Free internal data buffers */ - kfree (this->data_buf); -- kfree (this->data_cache); - - /* unmap physical adress */ - iounmap((void *)autcpu12_fio_base); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/nand/diskonchip.c linux/drivers/mtd/nand/diskonchip.c ---- linux-mips-2.4.24-pre2/drivers/mtd/nand/diskonchip.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/nand/diskonchip.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,534 @@ -+/* -+ * drivers/mtd/nand/diskonchip.c -+ * -+ * (C) 2003 Red Hat, Inc. -+ * -+ * Author: David Woodhouse -+ * -+ * Interface to generic NAND code for M-Systems DiskOnChip devices -+ * -+ * $Id$ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+struct doc_priv { -+ unsigned long virtadr; -+ unsigned long physadr; -+ u_char ChipID; -+ u_char CDSNControl; -+ int chips_per_floor; /* The number of chips detected on each floor */ -+ int curfloor; -+ int curchip; -+}; -+ -+#define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil) -+#define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k) -+ -+static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd); -+static void doc200x_select_chip(struct mtd_info *mtd, int chip); -+ -+static int debug=0; -+MODULE_PARM(debug, "i"); -+ -+static int try_dword=1; -+MODULE_PARM(try_dword, "i"); -+ -+static void DoC_Delay(struct doc_priv *doc, unsigned short cycles) -+{ -+ volatile char dummy; -+ int i; -+ -+ for (i = 0; i < cycles; i++) { -+ if (DoC_is_Millennium(doc)) -+ dummy = ReadDOC(doc->virtadr, NOP); -+ else -+ dummy = ReadDOC(doc->virtadr, DOCStatus); -+ } -+ -+} -+/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ -+static int _DoC_WaitReady(struct doc_priv *doc) -+{ -+ unsigned long docptr = doc->virtadr; -+ unsigned long timeo = jiffies + (HZ * 10); -+ -+ if(debug) printk("_DoC_WaitReady...\n"); -+ /* Out-of-line routine to wait for chip response */ -+ while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { -+ if (time_after(jiffies, timeo)) { -+ printk("_DoC_WaitReady timed out.\n"); -+ return -EIO; -+ } -+ udelay(1); -+ cond_resched(); -+ } -+ -+ return 0; -+} -+ -+static inline int DoC_WaitReady(struct doc_priv *doc) -+{ -+ unsigned long docptr = doc->virtadr; -+ int ret = 0; -+ -+ DoC_Delay(doc, 4); -+ -+ if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) -+ /* Call the out-of-line routine to wait */ -+ ret = _DoC_WaitReady(doc); -+ -+ DoC_Delay(doc, 2); -+ if(debug) printk("DoC_WaitReady OK\n"); -+ return ret; -+} -+ -+static void doc2000_write_byte(struct mtd_info *mtd, u_char datum) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ -+ if(debug)printk("write_byte %02x\n", datum); -+ WriteDOC(datum, docptr, CDSNSlowIO); -+ WriteDOC(datum, docptr, 2k_CDSN_IO); -+} -+ -+static u_char doc2000_read_byte(struct mtd_info *mtd) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ -+ ReadDOC(docptr, CDSNSlowIO); -+ u_char ret = ReadDOC(docptr, 2k_CDSN_IO); -+ if (debug) printk("read_byte returns %02x\n", ret); -+ return ret; -+} -+static void doc2000_writebuf(struct mtd_info *mtd, -+ const u_char *buf, int len) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int i; -+ if (debug)printk("writebuf of %d bytes: ", len); -+ for (i=0; i < len; i++) { -+ WriteDOC_(buf[i], docptr, DoC_2k_CDSN_IO + i); -+ if (debug && i < 16) -+ printk("%02x ", buf[i]); -+ } -+ if (debug) printk("\n"); -+} -+ -+static void doc2000_readbuf(struct mtd_info *mtd, -+ u_char *buf, int len) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int i; -+ -+ if (debug)printk("readbuf of %d bytes: ", len); -+ -+ for (i=0; i < len; i++) { -+ buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i); -+ } -+} -+ -+static void doc2000_readbuf_dword(struct mtd_info *mtd, -+ u_char *buf, int len) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int i; -+ -+ if (debug) printk("readbuf_dword of %d bytes: ", len); -+ -+ if (unlikely((((unsigned long)buf)|len) & 3)) { -+ for (i=0; i < len; i++) { -+ *(uint8_t *)(&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i); -+ } -+ } else { -+ for (i=0; i < len; i+=4) { -+ *(uint32_t*)(&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i); -+ } -+ } -+} -+ -+static int doc2000_verifybuf(struct mtd_info *mtd, -+ const u_char *buf, int len) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int i; -+ -+ for (i=0; i < len; i++) -+ if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO)) -+ return i; -+ return 0; -+} -+ -+static uint16_t doc200x_ident_chip(struct mtd_info *mtd, int nr) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ uint16_t ret; -+ -+ doc200x_select_chip(mtd, nr); -+ doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); -+ this->write_byte(mtd, NAND_CMD_READID); -+ doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); -+ doc200x_hwcontrol(mtd, NAND_CTL_SETALE); -+ this->write_byte(mtd, 0); -+ doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); -+ -+ ret = this->read_byte(mtd) << 8; -+ ret |= this->read_byte(mtd); -+ -+ if (doc->ChipID == DOC_ChipID_Doc2k && try_dword && !nr) { -+ /* First chip probe. See if we get same results by 32-bit access */ -+ union { -+ uint32_t dword; -+ uint8_t byte[4]; -+ } ident; -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ -+ doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); -+ doc2000_write_byte(mtd, NAND_CMD_READID); -+ doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); -+ doc200x_hwcontrol(mtd, NAND_CTL_SETALE); -+ doc2000_write_byte(mtd, 0); -+ doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); -+ -+ ident.dword = readl(docptr + DoC_2k_CDSN_IO); -+ if (((ident.byte[0] << 8) | ident.byte[1]) == ret) { -+ printk(KERN_INFO "DiskOnChip 2000 responds to DWORD access\n"); -+ this->read_buf = &doc2000_readbuf_dword; -+ } -+ } -+ -+ return ret; -+} -+ -+static void doc2000_count_chips(struct mtd_info *mtd) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ uint16_t mfrid; -+ int i; -+ -+ /* Max 4 chips per floor on DiskOnChip 2000 */ -+ doc->chips_per_floor = 4; -+ -+ /* Find out what the first chip is */ -+ mfrid = doc200x_ident_chip(mtd, 0); -+ -+ /* Find how many chips in each floor. */ -+ for (i = 1; i < 4; i++) { -+ if (doc200x_ident_chip(mtd, i) != mfrid) -+ break; -+ } -+ doc->chips_per_floor = i; -+} -+ -+static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state) -+{ -+ struct doc_priv *doc = (void *)this->priv; -+ -+ int status; -+ -+ DoC_WaitReady(doc); -+ this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); -+ DoC_WaitReady(doc); -+ status = (int)this->read_byte(mtd); -+ -+ return status; -+} -+ -+static void doc2001_write_byte(struct mtd_info *mtd, u_char datum) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ -+ WriteDOC(datum, docptr, CDSNSlowIO); -+ WriteDOC(datum, docptr, Mil_CDSN_IO); -+ WriteDOC(datum, docptr, WritePipeTerm); -+} -+ -+static u_char doc2001_read_byte(struct mtd_info *mtd) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ -+ ReadDOC(docptr, CDSNSlowIO); -+ /* 11.4.5 -- delay twice to allow extended length cycle */ -+ DoC_Delay(doc, 2); -+ ReadDOC(docptr, ReadPipeInit); -+ return ReadDOC(docptr, Mil_CDSN_IO); -+} -+ -+static void doc2001_writebuf(struct mtd_info *mtd, -+ const u_char *buf, int len) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int i; -+ -+ for (i=0; i < len; i++) -+ WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); -+ /* Terminate write pipeline */ -+ WriteDOC(0x00, docptr, WritePipeTerm); -+} -+ -+static void doc2001_readbuf(struct mtd_info *mtd, -+ u_char *buf, int len) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int i; -+ -+ /* Start read pipeline */ -+ ReadDOC(docptr, ReadPipeInit); -+ -+ for (i=0; i < len-1; i++) -+ buf[i] = ReadDOC(docptr, Mil_CDSN_IO); -+ -+ /* Terminate read pipeline */ -+ buf[i] = ReadDOC(docptr, LastDataRead); -+} -+static int doc2001_verifybuf(struct mtd_info *mtd, -+ const u_char *buf, int len) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int i; -+ -+ /* Start read pipeline */ -+ ReadDOC(docptr, ReadPipeInit); -+ -+ for (i=0; i < len-1; i++) -+ if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { -+ ReadDOC(docptr, LastDataRead); -+ return i; -+ } -+ if (buf[i] != ReadDOC(docptr, LastDataRead)) -+ return i; -+ return 0; -+} -+ -+static void doc200x_select_chip(struct mtd_info *mtd, int chip) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int floor = 0; -+ -+ /* 11.4.4 -- deassert CE before changing chip */ -+ doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE); -+ -+ if(debug)printk("select chip (%d)\n", chip); -+ -+ if (chip == -1) -+ return; -+ -+ floor = chip / doc->chips_per_floor; -+ chip -= (floor * doc->chips_per_floor); -+ -+ WriteDOC(floor, docptr, FloorSelect); -+ WriteDOC(chip, docptr, CDSNDeviceSelect); -+ -+ doc200x_hwcontrol(mtd, NAND_CTL_SETNCE); -+ -+ doc->curchip = chip; -+ doc->curfloor = floor; -+} -+ -+static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ -+ switch(cmd) { -+ case NAND_CTL_SETNCE: -+ doc->CDSNControl |= CDSN_CTRL_CE; -+ break; -+ case NAND_CTL_CLRNCE: -+ doc->CDSNControl &= ~CDSN_CTRL_CE; -+ break; -+ case NAND_CTL_SETCLE: -+ doc->CDSNControl |= CDSN_CTRL_CLE; -+ break; -+ case NAND_CTL_CLRCLE: -+ doc->CDSNControl &= ~CDSN_CTRL_CLE; -+ break; -+ case NAND_CTL_SETALE: -+ doc->CDSNControl |= CDSN_CTRL_ALE; -+ break; -+ case NAND_CTL_CLRALE: -+ doc->CDSNControl &= ~CDSN_CTRL_ALE; -+ break; -+ case NAND_CTL_SETWP: -+ doc->CDSNControl |= CDSN_CTRL_WP; -+ break; -+ case NAND_CTL_CLRWP: -+ doc->CDSNControl &= ~CDSN_CTRL_WP; -+ break; -+ } -+ if (debug)printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl); -+ WriteDOC(doc->CDSNControl, docptr, CDSNControl); -+ /* 11.4.3 -- 4 NOPs after CSDNControl write */ -+ DoC_Delay(doc, 4); -+} -+ -+static int doc200x_dev_ready(struct mtd_info *mtd) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ -+ /* 11.4.2 -- must NOP four times before checking FR/B# */ -+ DoC_Delay(doc, 4); -+ if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { -+ if(debug) -+ printk("not ready\n"); -+ return 0; -+ } -+ /* 11.4.2 -- Must NOP twice if it's ready */ -+ DoC_Delay(doc, 2); -+ if (debug)printk("was ready\n"); -+ return 1; -+} -+ -+static int doc200x_block_bad(struct mtd_info *mtd, unsigned long block) -+{ -+ /* FIXME: Look it up in the BBT */ -+ return 0; -+} -+ -+struct doc_priv mydoc = { -+ .physadr = 0xd4000, -+ .curfloor = -1, -+ .curchip = -1, -+}; -+ -+u_char mydatabuf[528]; -+ -+struct nand_chip mynand = { -+ .priv = (void *)&mydoc, -+ .select_chip = doc200x_select_chip, -+ .hwcontrol = doc200x_hwcontrol, -+ .dev_ready = doc200x_dev_ready, -+ .waitfunc = doc200x_wait, -+ .block_bad = doc200x_block_bad, -+ .eccmode = NAND_ECC_SOFT, -+ .data_buf = mydatabuf, -+}; -+ -+struct mtd_info mymtd = { -+ .priv = (void *)&mynand, -+ .owner = THIS_MODULE, -+}; -+ -+int __init init_nanddoc(void) -+{ -+ mydoc.virtadr = (unsigned long)ioremap(mydoc.physadr, DOC_IOREMAP_LEN); -+ int nrchips = 1; -+ char *name; -+ -+ WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, -+ mydoc.virtadr, DOCControl); -+ WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, -+ mydoc.virtadr, DOCControl); -+ -+ WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, -+ mydoc.virtadr, DOCControl); -+ WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, -+ mydoc.virtadr, DOCControl); -+ -+ mydoc.ChipID = ReadDOC(mydoc.virtadr, ChipID); -+ -+ switch(mydoc.ChipID) { -+ case DOC_ChipID_DocMil: -+ mynand.write_byte = doc2001_write_byte; -+ mynand.read_byte = doc2001_read_byte; -+ mynand.write_buf = doc2001_writebuf; -+ mynand.read_buf = doc2001_readbuf; -+ mynand.verify_buf = doc2001_verifybuf; -+ -+ ReadDOC(mydoc.virtadr, ChipID); -+ ReadDOC(mydoc.virtadr, ChipID); -+ if (ReadDOC(mydoc.virtadr, ChipID) != DOC_ChipID_DocMil) { -+ /* It's not a Millennium; it's one of the newer -+ DiskOnChip 2000 units with a similar ASIC. -+ Treat it like a Millennium, except that it -+ can have multiple chips. */ -+ doc2000_count_chips(&mymtd); -+ nrchips = 4 * mydoc.chips_per_floor; -+ name = "DiskOnChip 2000 (INFTL Model)"; -+ } else { -+ /* Bog-standard Millennium */ -+ mydoc.chips_per_floor = 1; -+ nrchips = 1; -+ name = "DiskOnChip Millennium"; -+ } -+ break; -+ -+ case DOC_ChipID_Doc2k: -+ mynand.write_byte = doc2000_write_byte; -+ mynand.read_byte = doc2000_read_byte; -+ mynand.write_buf = doc2000_writebuf; -+ mynand.read_buf = doc2000_readbuf; -+ mynand.verify_buf = doc2000_verifybuf; -+ -+ doc2000_count_chips(&mymtd); -+ nrchips = 4 * mydoc.chips_per_floor; -+ name = "DiskOnChip 2000 (NFTL Model)"; -+ mydoc.CDSNControl |= CDSN_CTRL_FLASH_IO; -+ -+ break; -+ -+ default: -+ return -EIO; -+ } -+ if (nand_scan(&mymtd, nrchips)) { -+ iounmap((void *)mydoc.virtadr); -+ return -EIO; -+ } -+ mymtd.name = name; -+ add_mtd_device(&mymtd); -+ -+ return 0; -+} -+ -+void __exit cleanup_nanddoc(void) -+{ -+ del_mtd_device(&mymtd); -+ iounmap((void *)mydoc.virtadr); -+} -+ -+module_init(init_nanddoc); -+module_exit(cleanup_nanddoc); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("David Woodhouse "); -+MODULE_DESCRIPTION("M-Systems DiskOnChip 2000 and Millennium device driver\n"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/nand/edb7312.c linux/drivers/mtd/nand/edb7312.c ---- linux-mips-2.4.24-pre2/drivers/mtd/nand/edb7312.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/nand/edb7312.c 2004-11-17 18:17:59.165294768 +0100 -@@ -6,7 +6,7 @@ - * Derived from drivers/mtd/nand/autcpu12.c - * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) - * -- * $Id$ -+ * $Id$ - * - * 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 -@@ -20,6 +20,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -77,16 +78,13 @@ - }; - #define NUM_PARTITIONS 1 - --extern int parse_cmdline_partitions(struct mtd_info *master, -- struct mtd_partition **pparts, -- const char *mtd_id); - #endif - - - /* - * hardware specific access to control-lines - */ --static void ep7312_hwcontrol(int cmd) -+static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd) - { - switch(cmd) { - -@@ -116,10 +114,13 @@ - /* - * read device ready pin - */ --static int ep7312_device_ready(void) -+static int ep7312_device_ready(struct mtd_info *mtd) - { - return 1; - } -+#ifdef CONFIG_MTD_PARTITIONS -+const char *part_probes[] = { "cmdlinepart", NULL }; -+#endif - - /* - * Main initialization routine -@@ -174,7 +175,7 @@ - this->chip_delay = 15; - - /* Scan to find existence of the device */ -- if (nand_scan (ep7312_mtd)) { -+ if (nand_scan (ep7312_mtd, 1)) { - iounmap((void *)ep7312_fio_base); - kfree (ep7312_mtd); - return -ENXIO; -@@ -189,27 +190,16 @@ - return -ENOMEM; - } - -- /* Allocate memory for internal data buffer */ -- this->data_cache = kmalloc (sizeof(u_char) * (ep7312_mtd->oobblock + ep7312_mtd->oobsize), GFP_KERNEL); -- if (!this->data_cache) { -- printk("Unable to allocate NAND data cache for EDB7312.\n"); -- kfree (this->data_buf); -- iounmap((void *)ep7312_fio_base); -- kfree (ep7312_mtd); -- return -ENOMEM; -- } -- this->cache_page = -1; -- --#ifdef CONFIG_MTD_CMDLINE_PARTS -- mtd_parts_nb = parse_cmdline_partitions(ep7312_mtd, &mtd_parts, -- "edb7312-nand"); -+#ifdef CONFIG_PARTITIONS -+ ep7312_mtd->name = "edb7312-nand"; -+ mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, -+ &mtd_parts, 0); - if (mtd_parts_nb > 0) - part_type = "command line"; - else - mtd_parts_nb = 0; - #endif -- if (mtd_parts_nb == 0) -- { -+ if (mtd_parts_nb == 0) { - mtd_parts = partition_info; - mtd_parts_nb = NUM_PARTITIONS; - part_type = "static"; -@@ -236,7 +226,6 @@ - - /* Free internal data buffer */ - kfree (this->data_buf); -- kfree (this->data_cache); - - /* Free the MTD device structure */ - kfree (ep7312_mtd); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/nand/nand.c linux/drivers/mtd/nand/nand.c ---- linux-mips-2.4.24-pre2/drivers/mtd/nand/nand.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/nand/nand.c 2004-11-17 18:17:59.167294464 +0100 -@@ -8,7 +8,7 @@ - * Additional technical information is available on - * http://www.linux-mtd.infradead.org/tech/nand.html - * -- * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) -+ * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) - * 2002 Thomas Gleixner (tglx@linutronix.de) - * - * 10-29-2001 Thomas Gleixner (tglx@linutronix.de) -@@ -112,10 +112,27 @@ - * for mtd->read_ecc / mtd->write_ecc - * some minor cleanups - * -- * 12-05-2000 tglx: Dave Ellis (DGE@sixnetio) provided the fix for -+ * 12-05-2002 tglx: Dave Ellis (DGE@sixnetio) provided the fix for - * WRITE_VERIFY long time ago. Thanks for remembering me. - * -- * $Id$ -+ * 02-14-2003 tglx: Reject non page aligned writes -+ * Fixed ecc select in nand_write_page to match semantics. -+ * -+ * 02-18-2003 tglx: Changed oobsel to pointer. Added a default oob-selector -+ * -+ * 02-18-2003 tglx: Implemented oobsel again. Now it uses a pointer to -+ + a structure, which will be supplied by a filesystem driver -+ * If NULL is given, then the defaults (none or defaults -+ * supplied by ioctl (MEMSETOOBSEL) are used. -+ * For partitions the partition defaults are used (mtdpart.c) -+ * -+ * 06-04-2003 tglx: fix compile errors and fix write verify problem for -+ * some chips, which need either a delay between the readback -+ * and the next write command or have the CE removed. The -+ * CE disable/enable is much faster than a 20us delay and -+ * it should work on all available chips. -+ * -+ * $Id$ - * - * 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 -@@ -130,102 +147,151 @@ - #include - #include - #include -+#include - #include - #include - - /* -- * Macros for low-level register control -- */ --#define nand_select() this->hwcontrol(NAND_CTL_SETNCE); -- --#define nand_deselect() this->hwcontrol(NAND_CTL_CLRNCE); -- --/* -- * out of band configuration for different filesystems -- */ --static int oobconfigs[][6] = { -- { 0,0,0,0,0,0}, -- -- { NAND_JFFS2_OOB_ECCPOS0, NAND_JFFS2_OOB_ECCPOS1, NAND_JFFS2_OOB_ECCPOS2, -- NAND_JFFS2_OOB_ECCPOS3, NAND_JFFS2_OOB_ECCPOS4, NAND_JFFS2_OOB_ECCPOS5 }, -- -- { NAND_YAFFS_OOB_ECCPOS0, NAND_YAFFS_OOB_ECCPOS1, NAND_YAFFS_OOB_ECCPOS2, -- NAND_YAFFS_OOB_ECCPOS3, NAND_YAFFS_OOB_ECCPOS4, NAND_YAFFS_OOB_ECCPOS5 } --}; -- --/* - * NAND low-level MTD interface functions - */ -+static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len); -+static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len); -+static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len); -+ - static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf); - static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, -- size_t * retlen, u_char * buf, u_char * eccbuf, int oobsel); -+ size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel); - static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf); - static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf); - static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, -- size_t * retlen, const u_char * buf, u_char * eccbuf, int oobsel); -+ size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel); - static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char *buf); - static int nand_writev (struct mtd_info *mtd, const struct iovec *vecs, - unsigned long count, loff_t to, size_t * retlen); - static int nand_writev_ecc (struct mtd_info *mtd, const struct iovec *vecs, -- unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, int oobsel); -+ unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); - static int nand_erase (struct mtd_info *mtd, struct erase_info *instr); - static void nand_sync (struct mtd_info *mtd); --static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, int col, -- int last, u_char *oob_buf, int oobsel); -+static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf, struct nand_oobinfo *oobsel); -+ -+static u_char nand_read_byte(struct mtd_info *mtd) -+{ -+ struct nand_chip *this = mtd->priv; -+ return readb(this->IO_ADDR_R); -+} -+ -+static void nand_write_byte(struct mtd_info *mtd, u_char byte) -+{ -+ struct nand_chip *this = mtd->priv; -+ writeb(byte, this->IO_ADDR_W); -+} -+ -+static void nand_select_chip(struct mtd_info *mtd, int chip) -+{ -+ struct nand_chip *this = mtd->priv; -+ switch(chip) { -+ case -1: -+ this->hwcontrol(mtd, NAND_CTL_CLRNCE); -+ break; -+ case 0: -+ this->hwcontrol(mtd, NAND_CTL_SETNCE); -+ break; -+ -+ default: -+ BUG(); -+ } -+} -+ -+static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_W); -+} -+ -+static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_R); -+} -+ -+static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_R)) -+ return i; -+ -+ return 0; -+} -+ -+/* Appropriate chip should already be selected */ -+static int nand_block_bad(struct mtd_info *mtd, unsigned long page) -+{ -+ struct nand_chip *this = mtd->priv; -+ -+ this->cmdfunc (mtd, NAND_CMD_READOOB, NAND_BADBLOCK_POS, page); -+ if (this->read_byte(mtd) != 0xff) -+ return 1; -+ -+ return 0; -+} -+ - /* - * Send command to NAND device - */ - static void nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) - { - register struct nand_chip *this = mtd->priv; -- register unsigned long NAND_IO_ADDR = this->IO_ADDR_W; - - /* Begin command latch cycle */ -- this->hwcontrol (NAND_CTL_SETCLE); -+ this->hwcontrol(mtd, NAND_CTL_SETCLE); - /* - * Write out the command to the device. - */ -- if (command != NAND_CMD_SEQIN) -- writeb (command, NAND_IO_ADDR); -- else { -- if (mtd->oobblock == 256 && column >= 256) { -- column -= 256; -- writeb (NAND_CMD_READOOB, NAND_IO_ADDR); -- writeb (NAND_CMD_SEQIN, NAND_IO_ADDR); -- } else if (mtd->oobblock == 512 && column >= 256) { -- if (column < 512) { -- column -= 256; -- writeb (NAND_CMD_READ1, NAND_IO_ADDR); -- writeb (NAND_CMD_SEQIN, NAND_IO_ADDR); -- } else { -- column -= 512; -- writeb (NAND_CMD_READOOB, NAND_IO_ADDR); -- writeb (NAND_CMD_SEQIN, NAND_IO_ADDR); -- } -+ if (command == NAND_CMD_SEQIN) { -+ int readcmd; -+ -+ if (column >= mtd->oobblock) { -+ /* OOB area */ -+ column -= mtd->oobblock; -+ readcmd = NAND_CMD_READOOB; -+ } else if (column < 256) { -+ /* First 256 bytes --> READ0 */ -+ readcmd = NAND_CMD_READ0; - } else { -- writeb (NAND_CMD_READ0, NAND_IO_ADDR); -- writeb (NAND_CMD_SEQIN, NAND_IO_ADDR); -+ column -= 256; -+ readcmd = NAND_CMD_READ1; - } -+ this->write_byte(mtd, readcmd); - } -+ this->write_byte(mtd, command); - - /* Set ALE and clear CLE to start address cycle */ -- this->hwcontrol (NAND_CTL_CLRCLE); -+ this->hwcontrol(mtd, NAND_CTL_CLRCLE); - - if (column != -1 || page_addr != -1) { -- this->hwcontrol (NAND_CTL_SETALE); -+ this->hwcontrol(mtd, NAND_CTL_SETALE); - - /* Serially input address */ - if (column != -1) -- writeb (column, NAND_IO_ADDR); -+ this->write_byte(mtd, column); - if (page_addr != -1) { -- writeb ((unsigned char) (page_addr & 0xff), NAND_IO_ADDR); -- writeb ((unsigned char) ((page_addr >> 8) & 0xff), NAND_IO_ADDR); -+ this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); -+ this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); - /* One more address cycle for higher density devices */ - if (mtd->size & 0x0c000000) -- writeb ((unsigned char) ((page_addr >> 16) & 0x0f), NAND_IO_ADDR); -+ this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f)); - } - /* Latch in address */ -- this->hwcontrol (NAND_CTL_CLRALE); -+ this->hwcontrol(mtd, NAND_CTL_CLRALE); - } - - /* -@@ -244,10 +310,11 @@ - case NAND_CMD_RESET: - if (this->dev_ready) - break; -- this->hwcontrol (NAND_CTL_SETCLE); -- writeb (NAND_CMD_STATUS, NAND_IO_ADDR); -- this->hwcontrol (NAND_CTL_CLRCLE); -- while ( !(readb (this->IO_ADDR_R) & 0x40)); -+ udelay(this->chip_delay); -+ this->hwcontrol(mtd, NAND_CTL_SETCLE); -+ this->write_byte(mtd, NAND_CMD_STATUS); -+ this->hwcontrol(mtd, NAND_CTL_CLRCLE); -+ while ( !(this->read_byte(mtd) & 0x40)); - return; - - /* This applies to read commands */ -@@ -263,7 +330,7 @@ - } - - /* wait until command is processed */ -- while (!this->dev_ready()); -+ while (!this->dev_ready(mtd)); - } - - /* -@@ -288,17 +355,17 @@ - spin_unlock_bh (&this->chip_lock); - return; - } -- -+#if 0 /* This was broken. And of dubious utility */ - if (this->state == FL_ERASING) { - if (new_state != FL_ERASING) { - this->state = new_state; - spin_unlock_bh (&this->chip_lock); -- nand_select (); /* select in any case */ -+ this->select_chip(mtd, 0); /* select in any case */ - this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); - return; - } - } -- -+#endif - set_current_state (TASK_UNINTERRUPTIBLE); - add_wait_queue (&this->wq, &wait); - spin_unlock_bh (&this->chip_lock); -@@ -334,17 +401,17 @@ - return 0; - } - if (this->dev_ready) { -- if (this->dev_ready ()) -+ if (this->dev_ready(mtd)) - break; - } -- if (readb (this->IO_ADDR_R) & 0x40) -+ if (this->read_byte(mtd) & 0x40) - break; - - spin_unlock_bh (&this->chip_lock); - yield (); - spin_lock_bh (&this->chip_lock); - } -- status = (int) readb (this->IO_ADDR_R); -+ status = (int) this->read_byte(mtd); - spin_unlock_bh (&this->chip_lock); - - return status; -@@ -352,14 +419,15 @@ - - /* - * Nand_page_program function is used for write and writev ! -+ * This function will always program a full page of data -+ * If you call it with a non page aligned buffer, you're lost :) - */ --static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, -- int page, int col, int last, u_char *oob_buf, int oobsel) -+static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf, struct nand_oobinfo *oobsel) - { - int i, status; - u_char ecc_code[6], *oob_data; -- int eccmode = oobsel ? this->eccmode : NAND_ECC_NONE; -- int *oob_config = oobconfigs[oobsel]; -+ int eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; -+ int *oob_config = oobsel->eccpos; - - /* pad oob area, if we have no oob buffer from fs-driver */ - if (!oob_buf) { -@@ -369,66 +437,42 @@ - } else - oob_data = oob_buf; - -- /* software ecc 3 Bytes ECC / 256 Byte Data ? */ -- if (eccmode == NAND_ECC_SOFT) { -- /* Read back previous written data, if col > 0 */ -- if (col) { -- this->cmdfunc (mtd, NAND_CMD_READ0, 0, page); -- for (i = 0; i < col; i++) -- this->data_poi[i] = readb (this->IO_ADDR_R); -- } -- if ((col < this->eccsize) && (last >= this->eccsize)) { -- this->calculate_ecc (&this->data_poi[0], &(ecc_code[0])); -- for (i = 0; i < 3; i++) -- oob_data[oob_config[i]] = ecc_code[i]; -- } -- /* Calculate and write the second ECC if we have enough data */ -- if ((mtd->oobblock == 512) && (last == 512)) { -- this->calculate_ecc (&this->data_poi[256], &(ecc_code[3])); -- for (i = 3; i < 6; i++) -- oob_data[oob_config[i]] = ecc_code[i]; -- } -- } else { -- /* For hardware ECC skip ECC, if we have no full page write */ -- if (eccmode != NAND_ECC_NONE && (col || last != mtd->oobblock)) -- eccmode = NAND_ECC_NONE; -- } -- -- /* Prepad for partial page programming !!! */ -- for (i = 0; i < col; i++) -- this->data_poi[i] = 0xff; -- -- /* Postpad for partial page programming !!! oob is already padded */ -- for (i = last; i < mtd->oobblock; i++) -- this->data_poi[i] = 0xff; -- - /* Send command to begin auto page programming */ - this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page); - - /* Write out complete page of data, take care of eccmode */ -- switch (this->eccmode) { -+ switch (eccmode) { - /* No ecc and software ecc 3/256, write all */ - case NAND_ECC_NONE: -+ printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n"); -+ this->write_buf(mtd, this->data_poi, mtd->oobblock); -+ break; - case NAND_ECC_SOFT: -- for (i = 0; i < mtd->oobblock; i++) -- writeb ( this->data_poi[i] , this->IO_ADDR_W); -+ this->calculate_ecc(mtd, &this->data_poi[0], &(ecc_code[0])); -+ for (i = 0; i < 3; i++) -+ oob_data[oob_config[i]] = ecc_code[i]; -+ /* Calculate and write the second ECC for 512 Byte page size */ -+ if (mtd->oobblock == 512) { -+ this->calculate_ecc(mtd, &this->data_poi[256], &(ecc_code[3])); -+ for (i = 3; i < 6; i++) -+ oob_data[oob_config[i]] = ecc_code[i]; -+ } -+ this->write_buf(mtd, this->data_poi, mtd->oobblock); - break; - - /* Hardware ecc 3 byte / 256 data, write first half, get ecc, then second, if 512 byte pagesize */ - case NAND_ECC_HW3_256: -- this->enable_hwecc (NAND_ECC_WRITE); /* enable hardware ecc logic for write */ -- for (i = 0; i < mtd->eccsize; i++) -- writeb ( this->data_poi[i] , this->IO_ADDR_W); -+ this->enable_hwecc(mtd, NAND_ECC_WRITE); /* enable hardware ecc logic for write */ -+ this->write_buf(mtd, this->data_poi, mtd->eccsize); - -- this->calculate_ecc (NULL, &(ecc_code[0])); -+ this->calculate_ecc(mtd, NULL, &(ecc_code[0])); - for (i = 0; i < 3; i++) - oob_data[oob_config[i]] = ecc_code[i]; - - if (mtd->oobblock == 512) { -- this->enable_hwecc (NAND_ECC_WRITE); /* enable hardware ecc logic for write*/ -- for (i = mtd->eccsize; i < mtd->oobblock; i++) -- writeb ( this->data_poi[i] , this->IO_ADDR_W); -- this->calculate_ecc (NULL, &(ecc_code[3])); -+ this->enable_hwecc(mtd, NAND_ECC_WRITE); /* enable hardware ecc logic for write*/ -+ this->write_buf(mtd, &this->data_poi[mtd->eccsize], mtd->oobblock - mtd->eccsize); -+ this->calculate_ecc(mtd, NULL, &(ecc_code[3])); - for (i = 3; i < 6; i++) - oob_data[oob_config[i]] = ecc_code[i]; - } -@@ -436,20 +480,18 @@ - - /* Hardware ecc 3 byte / 512 byte data, write full page */ - case NAND_ECC_HW3_512: -- this->enable_hwecc (NAND_ECC_WRITE); /* enable hardware ecc logic */ -- for (i = 0; i < mtd->oobblock; i++) -- writeb ( this->data_poi[i] , this->IO_ADDR_W); -- this->calculate_ecc (NULL, &(ecc_code[0])); -+ this->enable_hwecc(mtd, NAND_ECC_WRITE); /* enable hardware ecc logic */ -+ this->write_buf(mtd, this->data_poi, mtd->oobblock); -+ this->calculate_ecc(mtd, NULL, &(ecc_code[0])); - for (i = 0; i < 3; i++) - oob_data[oob_config[i]] = ecc_code[i]; - break; - - /* Hardware ecc 6 byte / 512 byte data, write full page */ - case NAND_ECC_HW6_512: -- this->enable_hwecc (NAND_ECC_WRITE); /* enable hardware ecc logic */ -- for (i = 0; i < mtd->oobblock; i++) -- writeb ( this->data_poi[i] , this->IO_ADDR_W); -- this->calculate_ecc (NULL, &(ecc_code[0])); -+ this->enable_hwecc(mtd, NAND_ECC_WRITE); /* enable hardware ecc logic */ -+ this->write_buf(mtd, this->data_poi, mtd->oobblock); -+ this->calculate_ecc(mtd, NULL, &(ecc_code[0])); - for (i = 0; i < 6; i++) - oob_data[oob_config[i]] = ecc_code[i]; - break; -@@ -460,8 +502,7 @@ - } - - /* Write out OOB data */ -- for (i = 0; i < mtd->oobsize; i++) -- writeb ( oob_data[i] , this->IO_ADDR_W); -+ this->write_buf(mtd, oob_data, mtd->oobsize); - - /* Send command to actually program the data */ - this->cmdfunc (mtd, NAND_CMD_PAGEPROG, -1, -1); -@@ -490,25 +531,21 @@ - */ - - /* Send command to read back the page */ -- this->cmdfunc (mtd, NAND_CMD_READ0, col, page); -+ this->cmdfunc (mtd, NAND_CMD_READ0, 0, page); - /* Loop through and verify the data */ -- for (i = col; i < last; i++) { -- if (this->data_poi[i] != readb (this->IO_ADDR_R)) { -+ if (this->verify_buf(mtd, this->data_poi, mtd->oobblock)) { - DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); - return -EIO; - } -- } - - /* check, if we have a fs-supplied oob-buffer */ - if (oob_buf) { -- for (i = 0; i < mtd->oobsize; i++) { -- if (oob_data[i] != readb (this->IO_ADDR_R)) { -+ if (this->verify_buf(mtd, oob_data, mtd->oobsize)) { - DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); - return -EIO; - } -- } - } else { -- if (eccmode != NAND_ECC_NONE && !col && last == mtd->oobblock) { -+ if (eccmode != NAND_ECC_NONE) { - int ecc_bytes = 0; - - switch (this->eccmode) { -@@ -518,8 +555,7 @@ - case NAND_ECC_HW6_512: ecc_bytes = 6; break; - } - -- for (i = 0; i < mtd->oobsize; i++) -- oob_data[i] = readb (this->IO_ADDR_R); -+ this->read_buf(mtd, oob_data, mtd->oobsize); - - for (i = 0; i < ecc_bytes; i++) { - if (oob_data[oob_config[i]] != ecc_code[i]) { -@@ -531,6 +567,13 @@ - } - } - } -+ /* -+ * Terminate the read command. This is faster than sending a reset command or -+ * applying a 20us delay before issuing the next programm sequence. -+ * This is not a problem for all chips, but I have found a bunch of them. -+ */ -+ this->select_chip(mtd, -1); -+ this->select_chip(mtd, 0); - #endif - return 0; - } -@@ -540,7 +583,7 @@ - */ - static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf) - { -- return (nand_read_ecc (mtd, from, len, retlen, buf, NULL, 0)); -+ return nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL); - } - - -@@ -548,7 +591,7 @@ - * NAND read with ECC - */ - static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, -- size_t * retlen, u_char * buf, u_char * oob_buf, int oobsel) -+ size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel) - { - int j, col, page, end, ecc; - int erase_state = 0; -@@ -557,9 +600,15 @@ - u_char *data_poi, *oob_data = oob_buf; - u_char ecc_calc[6]; - u_char ecc_code[6]; -- int eccmode = oobsel ? this->eccmode : NAND_ECC_NONE; -+ int eccmode; -+ int *oob_config; -+ -+ // use chip default if zero -+ if (oobsel == NULL) -+ oobsel = &mtd->oobinfo; - -- int *oob_config = oobconfigs[oobsel]; -+ eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; -+ oob_config = oobsel->eccpos; - - DEBUG (MTD_DEBUG_LEVEL3, "nand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); - -@@ -574,7 +623,7 @@ - nand_get_chip (this, mtd ,FL_READING, &erase_state); - - /* Select the NAND device */ -- nand_select (); -+ this->select_chip(mtd, 0); - - /* First we calculate the starting page */ - page = from >> this->page_shift; -@@ -596,7 +645,7 @@ - if (!this->dev_ready) - udelay (this->chip_delay); - else -- while (!this->dev_ready()); -+ while (!this->dev_ready(mtd)); - } - - /* -@@ -616,39 +665,40 @@ - - j = 0; - switch (eccmode) { -- case NAND_ECC_NONE: /* No ECC, Read in a page */ -- while (j < end) -- data_poi[j++] = readb (this->IO_ADDR_R); -+ case NAND_ECC_NONE: { /* No ECC, Read in a page */ -+ static unsigned long lastwhinge = 0; -+ if ((lastwhinge / HZ) != (jiffies / HZ)) { -+ printk (KERN_WARNING "Reading data from NAND FLASH without ECC is not recommended\n"); -+ lastwhinge = jiffies; -+ } -+ this->read_buf(mtd, data_poi, end); - break; -+ } - - case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */ -- while (j < end) -- data_poi[j++] = readb (this->IO_ADDR_R); -- this->calculate_ecc (&data_poi[0], &ecc_calc[0]); -+ this->read_buf(mtd, data_poi, end); -+ this->calculate_ecc(mtd, &data_poi[0], &ecc_calc[0]); - if (mtd->oobblock == 512) -- this->calculate_ecc (&data_poi[256], &ecc_calc[3]); -+ this->calculate_ecc(mtd, &data_poi[256], &ecc_calc[3]); - break; - - case NAND_ECC_HW3_256: /* Hardware ECC 3 byte /256 byte data: Read in first 256 byte, get ecc, */ -- this->enable_hwecc (NAND_ECC_READ); -- while (j < ecc) -- data_poi[j++] = readb (this->IO_ADDR_R); -- this->calculate_ecc (&data_poi[0], &ecc_calc[0]); /* read from hardware */ -+ this->enable_hwecc(mtd, NAND_ECC_READ); -+ this->read_buf(mtd, data_poi, ecc); -+ this->calculate_ecc(mtd, &data_poi[0], &ecc_calc[0]); /* read from hardware */ - - if (mtd->oobblock == 512) { /* read second, if pagesize = 512 */ -- this->enable_hwecc (NAND_ECC_READ); -- while (j < end) -- data_poi[j++] = readb (this->IO_ADDR_R); -- this->calculate_ecc (&data_poi[256], &ecc_calc[3]); /* read from hardware */ -+ this->enable_hwecc(mtd, NAND_ECC_READ); -+ this->read_buf(mtd, &data_poi[ecc], end-ecc); -+ this->calculate_ecc(mtd, &data_poi[256], &ecc_calc[3]); /* read from hardware */ - } - break; - - case NAND_ECC_HW3_512: - case NAND_ECC_HW6_512: /* Hardware ECC 3/6 byte / 512 byte data : Read in a page */ -- this->enable_hwecc (NAND_ECC_READ); -- while (j < end) -- data_poi[j++] = readb (this->IO_ADDR_R); -- this->calculate_ecc (&data_poi[0], &ecc_calc[0]); /* read from hardware */ -+ this->enable_hwecc(mtd, NAND_ECC_READ); -+ this->read_buf(mtd, data_poi, end); -+ this->calculate_ecc(mtd, &data_poi[0], &ecc_calc[0]); /* read from hardware */ - break; - - default: -@@ -658,7 +708,7 @@ - - /* read oobdata */ - for (j = 0; j < mtd->oobsize; j++) -- oob_data[oob + j] = readb (this->IO_ADDR_R); -+ oob_data[oob + j] = this->read_byte(mtd); - - /* Skip ECC, if not active */ - if (eccmode == NAND_ECC_NONE) -@@ -669,7 +719,7 @@ - ecc_code[j] = oob_data[oob + oob_config[j]]; - - /* correct data, if neccecary */ -- ecc_status = this->correct_data (&data_poi[0], &ecc_code[0], &ecc_calc[0]); -+ ecc_status = this->correct_data(mtd, &data_poi[0], &ecc_code[0], &ecc_calc[0]); - /* check, if we have a fs supplied oob-buffer */ - if (oob_buf) { - oob += mtd->oobsize; -@@ -682,7 +732,7 @@ - } - - if (mtd->oobblock == 512 && eccmode != NAND_ECC_HW3_512) { -- ecc_status = this->correct_data (&data_poi[256], &ecc_code[3], &ecc_calc[3]); -+ ecc_status = this->correct_data(mtd, &data_poi[256], &ecc_code[3], &ecc_calc[3]); - if (oob_buf) { - *((int *)&oob_data[oob]) = ecc_status; - oob += sizeof(int); -@@ -705,7 +755,7 @@ - } - - /* De-select the NAND device */ -- nand_deselect (); -+ this->select_chip(mtd, -1); - - /* Wake up anyone waiting on the device */ - spin_lock_bh (&this->chip_lock); -@@ -753,7 +803,7 @@ - nand_get_chip (this, mtd , FL_READING, &erase_state); - - /* Select the NAND device */ -- nand_select (); -+ this->select_chip(mtd, 0); - - /* Send the read command */ - this->cmdfunc (mtd, NAND_CMD_READOOB, col, page); -@@ -761,13 +811,20 @@ - * Read the data, if we read more than one page - * oob data, let the device transfer the data ! - */ -- for (i = 0; i < len; i++) { -- buf[i] = readb (this->IO_ADDR_R); -- if ((col++ & (mtd->oobsize - 1)) == (mtd->oobsize - 1)) -+ i = 0; -+ while (i < len) { -+ int thislen = (mtd->oobsize - col) & (mtd->oobsize - 1); -+ if (!thislen) -+ thislen = mtd->oobsize; -+ thislen = min_t(int, thislen, len); -+ this->read_buf(mtd, &buf[i], thislen); -+ i += thislen; -+ col += thislen; -+ /* Delay between pages */ - udelay (this->chip_delay); - } - /* De-select the NAND device */ -- nand_deselect (); -+ this->select_chip(mtd, -1); - - /* Wake up anyone waiting on the device */ - spin_lock_bh (&this->chip_lock); -@@ -780,45 +837,54 @@ - return 0; - } - -+#define NOTALIGNED(x) (x & (mtd->oobblock-1)) != 0 -+ - /* - * Use NAND write ECC - */ - static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf) - { -- return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, 0)); -+ return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL)); - } - /* - * NAND write with ECC - */ - static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, -- size_t * retlen, const u_char * buf, u_char * eccbuf, int oobsel) -+ size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel) - { -- int i, page, col, cnt, ret = 0, oob = 0, written = 0; -+ int page, ret = 0, oob = 0, written = 0; - struct nand_chip *this = mtd->priv; - - DEBUG (MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); - - /* Do not allow write past end of device */ - if ((to + len) > mtd->size) { -- DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n"); -+ DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n"); -+ return -EINVAL; -+ } -+ -+ /* reject writes, which are not page aligned */ -+ if (NOTALIGNED (to) || NOTALIGNED(len)) { -+ printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); - return -EINVAL; - } - -+ // if oobsel is NULL, use chip defaults -+ if (oobsel == NULL) -+ oobsel = &mtd->oobinfo; -+ - /* Shift to get page */ - page = ((int) to) >> this->page_shift; - -- /* Get the starting column */ -- col = to & (mtd->oobblock - 1); -- - /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd, FL_WRITING, NULL); - - /* Select the NAND device */ -- nand_select (); -+ this->select_chip(mtd, 0); - - /* Check the WP bit */ - this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); -- if (!(readb (this->IO_ADDR_R) & 0x80)) { -+ if (!(this->read_byte(mtd) & 0x80)) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Device is write protected!!!\n"); - ret = -EIO; - goto out; -@@ -826,42 +892,27 @@ - - /* Loop until all data is written */ - while (written < len) { -- /* -- * Check, if we have a full page write, then we can -- * use the given buffer, else we have to copy -- */ -- if (!col && (len - written) >= mtd->oobblock) { -+ int cnt = mtd->oobblock; - this->data_poi = (u_char*) &buf[written]; -- cnt = mtd->oobblock; -- } else { -- cnt = 0; -- for (i = col; i < len && i < mtd->oobblock; i++) { -- this->data_buf[i] = buf[written + i]; -- cnt++; -- } -- this->data_poi = this->data_buf; -- } -- /* We use the same function for write and writev !) */ -+ /* We use the same function for write and writev */ - if (eccbuf) { -- ret = nand_write_page (mtd, this, page, col, cnt ,&eccbuf[oob], oobsel); -+ ret = nand_write_page (mtd, this, page, &eccbuf[oob], oobsel); - oob += mtd->oobsize; - } else -- ret = nand_write_page (mtd, this, page, col, cnt, NULL, oobsel); -+ ret = nand_write_page (mtd, this, page, NULL, oobsel); - - if (ret) - goto out; - - /* Update written bytes count */ - written += cnt; -- /* Next write is aligned */ -- col = 0; - /* Increment page address */ - page++; - } - - out: - /* De-select the NAND device */ -- nand_deselect (); -+ this->select_chip(mtd, -1); - - /* Wake up anyone waiting on the device */ - spin_lock_bh (&this->chip_lock); -@@ -873,13 +924,21 @@ - return ret; - } - -+static u_char ffchars[] = { -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -+}; -+ - /* - * NAND write out-of-band - */ - static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf) - { -- int i, column, page, status, ret = 0; -+ int column, page, status, ret = 0; - struct nand_chip *this = mtd->priv; -+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE -+ int i; -+#endif - - DEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); - -@@ -902,27 +961,31 @@ - nand_get_chip (this, mtd, FL_WRITING, NULL); - - /* Select the NAND device */ -- nand_select (); -+ this->select_chip(mtd, 0); -+ -+ /* Reset the chip. Some chips (like the Toshiba TC5832DC found -+ in one of my DiskOnChip 2000 test units) will clear the whole -+ data page too if we don't do this. I have no clue why, but -+ I seem to have 'fixed' it in the doc2000 driver in -+ August 1999. dwmw2. */ -+ this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); - - /* Check the WP bit */ - this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); -- if (!(readb (this->IO_ADDR_R) & 0x80)) { -+ if (!(this->read_byte(mtd) & 0x80)) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Device is write protected!!!\n"); - ret = -EIO; - goto out; - } -- - /* Write out desired data */ - this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock, page); -+ - /* prepad 0xff for partial programming */ -- for (i = 0; i < column; i++) -- writeb (0xff, this->IO_ADDR_W); -+ this->write_buf(mtd, ffchars, column); - /* write data */ -- for (i = 0; i < len; i++) -- writeb (buf[i], this->IO_ADDR_W); -+ this->write_buf(mtd, buf, len); - /* postpad 0xff for partial programming */ -- for (i = len + column; i < mtd->oobsize; i++) -- writeb (0xff, this->IO_ADDR_W); -+ this->write_buf(mtd, ffchars, mtd->oobsize - (len+column)); - - /* Send command to program the OOB data */ - this->cmdfunc (mtd, NAND_CMD_PAGEPROG, -1, -1); -@@ -944,7 +1007,7 @@ - - /* Loop through and verify the data */ - for (i = 0; i < len; i++) { -- if (buf[i] != readb (this->IO_ADDR_R)) { -+ if (buf[i] != this->read_byte(mtd)) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page); - ret = -EIO; - goto out; -@@ -954,7 +1017,7 @@ - - out: - /* De-select the NAND device */ -- nand_deselect (); -+ this->select_chip(mtd, -1); - - /* Wake up anyone waiting on the device */ - spin_lock_bh (&this->chip_lock); -@@ -976,9 +1039,9 @@ - } - - static int nand_writev_ecc (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, -- loff_t to, size_t * retlen, u_char *eccbuf, int oobsel) -+ loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel) - { -- int i, page, col, cnt, len, total_len, ret = 0, written = 0; -+ int i, page, len, total_len, ret = 0, written = 0; - struct nand_chip *this = mtd->priv; - - /* Calculate total length of data */ -@@ -995,39 +1058,42 @@ - return -EINVAL; - } - -+ /* reject writes, which are not page aligned */ -+ if (NOTALIGNED (to) || NOTALIGNED(total_len)) { -+ printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); -+ return -EINVAL; -+ } -+ -+ // if oobsel is NULL, use chip defaults -+ if (oobsel == NULL) -+ oobsel = &mtd->oobinfo; -+ - /* Shift to get page */ - page = ((int) to) >> this->page_shift; - -- /* Get the starting column */ -- col = to & (mtd->oobblock - 1); -- - /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd, FL_WRITING, NULL); - - /* Select the NAND device */ -- nand_select (); -+ this->select_chip(mtd, 0); - - /* Check the WP bit */ - this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); -- if (!(readb (this->IO_ADDR_R) & 0x80)) { -+ if (!(this->read_byte(mtd) & 0x80)) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_writev: Device is write protected!!!\n"); - ret = -EIO; - goto out; - } - - /* Loop until all iovecs' data has been written */ -- cnt = col; - len = 0; -- - while (count) { - /* -- * Check, if we write from offset 0 and if the tuple -- * gives us not enough data for a full page write. Then we -- * can use the iov direct, else we have to copy into -- * data_buf. -+ * Check, if the tuple gives us not enough data for a -+ * full page write. Then we can use the iov direct, -+ * else we have to copy into data_buf. - */ -- if (!cnt && (vecs->iov_len - len) >= mtd->oobblock) { -- cnt = mtd->oobblock; -+ if ((vecs->iov_len - len) >= mtd->oobblock) { - this->data_poi = (u_char *) vecs->iov_base; - this->data_poi += len; - len += mtd->oobblock; -@@ -1042,6 +1108,7 @@ - * Read data out of each tuple until we have a full page - * to write or we've read all the tuples. - */ -+ int cnt = 0; - while ((cnt < mtd->oobblock) && count) { - if (vecs->iov_base != NULL && vecs->iov_len) { - this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++]; -@@ -1057,15 +1124,12 @@ - } - - /* We use the same function for write and writev !) */ -- ret = nand_write_page (mtd, this, page, col, cnt, NULL, oobsel); -+ ret = nand_write_page (mtd, this, page, NULL, oobsel); - if (ret) - goto out; - - /* Update written bytes count */ -- written += (cnt - col); -- -- /* Reset written byte counter and column */ -- col = cnt = 0; -+ written += mtd->oobblock;; - - /* Increment page address */ - page++; -@@ -1073,7 +1137,7 @@ - - out: - /* De-select the NAND device */ -- nand_deselect (); -+ this->select_chip(mtd, -1); - - /* Wake up anyone waiting on the device */ - spin_lock_bh (&this->chip_lock); -@@ -1125,11 +1189,11 @@ - pages_per_block = mtd->erasesize / mtd->oobblock; - - /* Select the NAND device */ -- nand_select (); -+ this->select_chip(mtd, 0); - - /* Check the WP bit */ - this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); -- if (!(readb (this->IO_ADDR_R) & 0x80)) { -+ if (!(this->read_byte(mtd) & 0x80)) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Device is write protected!!!\n"); - instr->state = MTD_ERASE_FAILED; - goto erase_exit; -@@ -1142,8 +1206,7 @@ - - while (len) { - /* Check if we have a bad block, we do not erase bad blocks ! */ -- this->cmdfunc (mtd, NAND_CMD_READOOB, NAND_BADBLOCK_POS, page); -- if (readb (this->IO_ADDR_R) != 0xff) { -+ if (this->block_bad(mtd, page)) { - printk (KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page); - instr->state = MTD_ERASE_FAILED; - goto erase_exit; -@@ -1179,7 +1242,7 @@ - if (this->state == FL_ERASING || this->state == FL_READY) { - /* Select the NAND device again, if we were interrupted */ - this->state = FL_ERASING; -- nand_select (); -+ this->select_chip(mtd, 0); - continue; - } else { - set_current_state (TASK_UNINTERRUPTIBLE); -@@ -1194,7 +1257,7 @@ - - erase_exit: - /* De-select the NAND device */ -- nand_deselect (); -+ this->select_chip(mtd, -1); - spin_unlock_bh (&this->chip_lock); - - ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;; -@@ -1205,6 +1268,7 @@ - /* The device is ready */ - spin_lock_bh (&this->chip_lock); - this->state = FL_READY; -+ wake_up (&this->wq); - spin_unlock_bh (&this->chip_lock); - - /* Return more or less happy */ -@@ -1259,7 +1323,7 @@ - /* - * Scan for the NAND device - */ --int nand_scan (struct mtd_info *mtd) -+int nand_scan (struct mtd_info *mtd, int maxchips) - { - int i, nand_maf_id, nand_dev_id; - struct nand_chip *this = mtd->priv; -@@ -1276,23 +1340,38 @@ - if (this->waitfunc == NULL) - this->waitfunc = nand_wait; - -+ if (!this->block_bad) -+ this->block_bad = nand_block_bad; -+ if (!this->select_chip) -+ this->select_chip = nand_select_chip; -+ if (!this->write_byte) -+ this->write_byte = nand_write_byte; -+ if (!this->read_byte) -+ this->read_byte = nand_read_byte; -+ if (!this->write_buf) -+ this->write_buf = nand_write_buf; -+ if (!this->read_buf) -+ this->read_buf = nand_read_buf; -+ if (!this->verify_buf) -+ this->verify_buf = nand_verify_buf; -+ - /* Select the device */ -- nand_select (); -+ this->select_chip(mtd, 0); - - /* Send the command for reading device ID */ - this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1); - - /* Read manufacturer and device IDs */ -- nand_maf_id = readb (this->IO_ADDR_R); -- nand_dev_id = readb (this->IO_ADDR_R); -+ nand_maf_id = this->read_byte(mtd); -+ nand_dev_id = this->read_byte(mtd); - - /* Print and store flash device information */ - for (i = 0; nand_flash_ids[i].name != NULL; i++) { - if (nand_dev_id == nand_flash_ids[i].id && !mtd->size) { - mtd->name = nand_flash_ids[i].name; - mtd->erasesize = nand_flash_ids[i].erasesize; -- mtd->size = (1 << nand_flash_ids[i].chipshift); - mtd->eccsize = 256; -+ this->chipshift = nand_flash_ids[i].chipshift; - if (nand_flash_ids[i].page256) { - mtd->oobblock = 256; - mtd->oobsize = 8; -@@ -1307,13 +1386,34 @@ - if (nand_manuf_ids[i].id == nand_maf_id) - break; - } -- printk (KERN_INFO "NAND device: Manufacture ID:" -+ printk (KERN_INFO "NAND device: Manufacturer ID:" - " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, - nand_manuf_ids[i].name , mtd->name); - break; - } - } - -+ if (!mtd->name) { -+ printk (KERN_WARNING "No NAND device found!!!\n"); -+ return 1; -+ } -+ -+ for (i=1; i < maxchips; i++) { -+ this->select_chip(mtd, i); -+ -+ /* Send the command for reading device ID */ -+ this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1); -+ -+ /* Read manufacturer and device IDs */ -+ if (nand_maf_id != this->read_byte(mtd) || -+ nand_dev_id != this->read_byte(mtd)) -+ break; -+ } -+ if (i > 1) -+ printk(KERN_INFO "%d NAND chips detected\n", i); -+ -+ mtd->size = (1 << this->chipshift) /* * i when we fix the rest of the code */; -+ - /* - * check ECC mode, default to software - * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize -@@ -1324,6 +1424,7 @@ - switch (this->eccmode) { - - case NAND_ECC_HW3_512: -+ case NAND_ECC_HW6_512: - if (mtd->oobblock == 256) { - printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n"); - this->eccmode = NAND_ECC_SOFT; -@@ -1340,6 +1441,7 @@ - BUG(); - - case NAND_ECC_NONE: -+ printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n"); - this->eccmode = NAND_ECC_NONE; - break; - -@@ -1359,18 +1461,11 @@ - spin_lock_init (&this->chip_lock); - - /* De-select the device */ -- nand_deselect (); -- -- /* Print warning message for no device */ -- if (!mtd->size) { -- printk (KERN_WARNING "No NAND device found!!!\n"); -- return 1; -- } -+ this->select_chip(mtd, -1); - - /* Fill in remaining MTD driver data */ - mtd->type = MTD_NANDFLASH; - mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC; -- mtd->module = THIS_MODULE; - mtd->ecctype = MTD_ECC_SW; - mtd->erase = nand_erase; - mtd->point = NULL; -@@ -1389,6 +1484,7 @@ - mtd->unlock = NULL; - mtd->suspend = NULL; - mtd->resume = NULL; -+ mtd->owner = THIS_MODULE; - - /* Return happy */ - return 0; -@@ -1397,5 +1493,5 @@ - EXPORT_SYMBOL (nand_scan); - - MODULE_LICENSE ("GPL"); --MODULE_AUTHOR ("Steven J. Hill , Thomas Gleixner "); -+MODULE_AUTHOR ("Steven J. Hill , Thomas Gleixner "); - MODULE_DESCRIPTION ("Generic NAND flash driver code"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/nand/nand_ecc.c linux/drivers/mtd/nand/nand_ecc.c ---- linux-mips-2.4.24-pre2/drivers/mtd/nand/nand_ecc.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/nand/nand_ecc.c 2004-11-17 18:17:59.168294312 +0100 -@@ -1,10 +1,10 @@ - /* - * drivers/mtd/nand_ecc.c - * -- * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) -+ * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) - * Toshiba America Electronics Components, Inc. - * -- * $Id$ -+ * $Id$ - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - /* - * Pre-calculated 256-way 1 byte column parity -@@ -84,7 +85,7 @@ - /* - * Calculate 3 byte ECC code for 256 byte block - */ --void nand_calculate_ecc (const u_char *dat, u_char *ecc_code) -+void nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) - { - u_char idx, reg1, reg2, reg3; - int j; -@@ -119,7 +120,7 @@ - /* - * Detect and correct a 1 bit error for 256 byte block - */ --int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc) -+int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) - { - u_char a, b, c, d1, d2, d3, add, bit, i; - -@@ -209,5 +210,5 @@ - EXPORT_SYMBOL(nand_correct_data); - - MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Steven J. Hill "); -+MODULE_AUTHOR("Steven J. Hill "); - MODULE_DESCRIPTION("Generic NAND ECC support"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/nand/nand_ids.c linux/drivers/mtd/nand/nand_ids.c ---- linux-mips-2.4.24-pre2/drivers/mtd/nand/nand_ids.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/nand/nand_ids.c 2004-11-17 18:17:59.169294160 +0100 -@@ -4,7 +4,7 @@ - * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de) - * - * -- * $Id$ -+ * $Id$ - * - * 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 -@@ -18,21 +18,21 @@ - * Chip ID list - */ - struct nand_flash_dev nand_flash_ids[] = { -- {"NAND 1MB 5V", 0x6e, 20, 0x1000, 1}, // 1Mb 5V -- {"NAND 2MB 5V", 0x64, 21, 0x1000, 1}, // 2Mb 5V -- {"NAND 4MB 5V", 0x6b, 22, 0x2000, 0}, // 4Mb 5V -- {"NAND 1MB 3,3V", 0xe8, 20, 0x1000, 1}, // 1Mb 3.3V -- {"NAND 1MB 3,3V", 0xec, 20, 0x1000, 1}, // 1Mb 3.3V -- {"NAND 2MB 3,3V", 0xea, 21, 0x1000, 1}, // 2Mb 3.3V -- {"NAND 4MB 3,3V", 0xd5, 22, 0x2000, 0}, // 4Mb 3.3V -- {"NAND 4MB 3,3V", 0xe3, 22, 0x2000, 0}, // 4Mb 3.3V -- {"NAND 4MB 3,3V", 0xe5, 22, 0x2000, 0}, // 4Mb 3.3V -- {"NAND 8MB 3,3V", 0xd6, 23, 0x2000, 0}, // 8Mb 3.3V -- {"NAND 8MB 3,3V", 0xe6, 23, 0x2000, 0}, // 8Mb 3.3V -- {"NAND 16MB 3,3V", 0x73, 24, 0x4000, 0},// 16Mb 3,3V -- {"NAND 32MB 3,3V", 0x75, 25, 0x4000, 0}, // 32Mb 3,3V -- {"NAND 64MB 3,3V", 0x76, 26, 0x4000, 0}, // 64Mb 3,3V -- {"NAND 128MB 3,3V", 0x79, 27, 0x4000, 0}, // 128Mb 3,3V -+ {"NAND 1MiB 5V", 0x6e, 20, 0x1000, 1}, -+ {"NAND 2MiB 5V", 0x64, 21, 0x1000, 1}, -+ {"NAND 4MiB 5V", 0x6b, 22, 0x2000, 0}, -+ {"NAND 1MiB 3,3V", 0xe8, 20, 0x1000, 1}, -+ {"NAND 1MiB 3,3V", 0xec, 20, 0x1000, 1}, -+ {"NAND 2MiB 3,3V", 0xea, 21, 0x1000, 1}, -+ {"NAND 4MiB 3,3V", 0xd5, 22, 0x2000, 0}, -+ {"NAND 4MiB 3,3V", 0xe3, 22, 0x2000, 0}, -+ {"NAND 4MiB 3,3V", 0xe5, 22, 0x2000, 0}, -+ {"NAND 8MiB 3,3V", 0xd6, 23, 0x2000, 0}, -+ {"NAND 8MiB 3,3V", 0xe6, 23, 0x2000, 0}, -+ {"NAND 16MiB 3,3V", 0x73, 24, 0x4000, 0}, -+ {"NAND 32MiB 3,3V", 0x75, 25, 0x4000, 0}, -+ {"NAND 64MiB 3,3V", 0x76, 26, 0x4000, 0}, -+ {"NAND 128MiB 3,3V", 0x79, 27, 0x4000, 0}, - {NULL,} - }; - -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/nand/spia.c linux/drivers/mtd/nand/spia.c ---- linux-mips-2.4.24-pre2/drivers/mtd/nand/spia.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/nand/spia.c 2004-11-17 18:17:59.171293856 +0100 -@@ -1,14 +1,14 @@ - /* - * drivers/mtd/nand/spia.c - * -- * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) -+ * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) - * - * - * 10-29-2001 TG change to support hardwarespecific access - * to controllines (due to change in nand.c) - * page_cache added - * -- * $Id$ -+ * $Id$ - * - * 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 -@@ -20,6 +20,8 @@ - * a 64Mibit (8MiB x 8 bits) NAND flash device. - */ - -+#include -+#include - #include - #include - #include -@@ -35,14 +37,14 @@ - /* - * Values specific to the SPIA board (used with EP7212 processor) - */ --#define SPIA_IO_ADDR = 0xd0000000 /* Start of EP7212 IO address space */ --#define SPIA_FIO_ADDR = 0xf0000000 /* Address where flash is mapped */ --#define SPIA_PEDR = 0x0080 /* -+#define SPIA_IO_BASE 0xd0000000 /* Start of EP7212 IO address space */ -+#define SPIA_FIO_BASE 0xf0000000 /* Address where flash is mapped */ -+#define SPIA_PEDR 0x0080 /* - * IO offset to Port E data register - * where the CLE, ALE and NCE pins - * are wired to. - */ --#define SPIA_PEDDR = 0x00c0 /* -+#define SPIA_PEDDR 0x00c0 /* - * IO offset to Port E data direction - * register so we can control the IO - * lines. -@@ -62,21 +64,20 @@ - MODULE_PARM(spia_pedr, "i"); - MODULE_PARM(spia_peddr, "i"); - --__setup("spia_io_base=",spia_io_base); --__setup("spia_fio_base=",spia_fio_base); --__setup("spia_pedr=",spia_pedr); --__setup("spia_peddr=",spia_peddr); -- - /* - * Define partitions for flash device - */ - const static struct mtd_partition partition_info[] = { -- { name: "SPIA flash partition 1", -- offset: 0, -- size: 2*1024*1024 }, -- { name: "SPIA flash partition 2", -- offset: 2*1024*1024, -- size: 6*1024*1024 } -+ { -+ .name = "SPIA flash partition 1", -+ .offset = 0, -+ .size = 2*1024*1024 -+ }, -+ { -+ .name = "SPIA flash partition 2", -+ .offset = 2*1024*1024, -+ .size = 6*1024*1024 -+ } - }; - #define NUM_PARTITIONS 2 - -@@ -84,7 +85,7 @@ - /* - * hardware specific access to control-lines - */ --void spia_hwcontrol(int cmd){ -+static void spia_hwcontrol(struct mtd_info *mtd, int cmd){ - - switch(cmd){ - -@@ -139,7 +140,7 @@ - this->chip_delay = 15; - - /* Scan to find existence of the device */ -- if (nand_scan (spia_mtd)) { -+ if (nand_scan (spia_mtd, 1)) { - kfree (spia_mtd); - return -ENXIO; - } -@@ -152,16 +153,6 @@ - return -ENOMEM; - } - -- /* Allocate memory for internal data buffer */ -- this->data_cache = kmalloc (sizeof(u_char) * (spia_mtd->oobblock + spia_mtd->oobsize), GFP_KERNEL); -- if (!this->data_cache) { -- printk ("Unable to allocate NAND data cache for SPIA.\n"); -- kfree (this->data_buf); -- kfree (spia_mtd); -- return = -ENOMEM; -- } -- this->cache_page = -1; -- - /* Register the partitions */ - add_mtd_partitions(spia_mtd, partition_info, NUM_PARTITIONS); - -@@ -183,7 +174,6 @@ - - /* Free internal data buffer */ - kfree (this->data_buf); -- kfree (this->page_cache); - - /* Free the MTD device structure */ - kfree (spia_mtd); -@@ -192,5 +182,5 @@ - #endif - - MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Steven J. Hill -+ * -+ * 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. -+ * -+ * Overview: -+ * This is a device driver for the NAND flash device found on the -+ * TI fido board. It supports 32MiB and 64MiB cards -+ * -+ * $Id$ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * MTD structure for TOTO board -+ */ -+static struct mtd_info *toto_mtd = NULL; -+ -+static int toto_io_base = OMAP_FLASH_1_BASE; -+ -+#define CONFIG_NAND_WORKAROUND 1 -+ -+#define NAND_NCE 0x4000 -+#define NAND_CLE 0x1000 -+#define NAND_ALE 0x0002 -+#define NAND_MASK (NAND_CLE | NAND_ALE | NAND_NCE) -+ -+#define T_NAND_CTL_CLRALE(iob) gpiosetout(NAND_ALE, 0) -+#define T_NAND_CTL_SETALE(iob) gpiosetout(NAND_ALE, NAND_ALE) -+#ifdef CONFIG_NAND_WORKAROUND /* "some" dev boards busted, blue wired to rts2 :( */ -+#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0); rts2setout(2, 2) -+#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE); rts2setout(2, 0) -+#else -+#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0) -+#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE) -+#endif -+#define T_NAND_CTL_SETNCE(iob) gpiosetout(NAND_NCE, 0) -+#define T_NAND_CTL_CLRNCE(iob) gpiosetout(NAND_NCE, NAND_NCE) -+ -+/* -+ * Define partitions for flash devices -+ */ -+ -+static struct mtd_partition partition_info64M[] = { -+ { .name = "toto kernel partition 1", -+ .offset = 0, -+ .size = 2 * SZ_1M }, -+ { .name = "toto file sys partition 2", -+ .offset = 2 * SZ_1M, -+ .size = 14 * SZ_1M }, -+ { .name = "toto user partition 3", -+ .offset = 16 * SZ_1M, -+ .size = 16 * SZ_1M }, -+ { .name = "toto devboard extra partition 4", -+ .offset = 32 * SZ_1M, -+ .size = 32 * SZ_1M }, -+}; -+ -+static struct mtd_partition partition_info32M[] = { -+ { .name = "toto kernel partition 1", -+ .offset = 0, -+ .size = 2 * SZ_1M }, -+ { .name = "toto file sys partition 2", -+ .offset = 2 * SZ_1M, -+ .size = 14 * SZ_1M }, -+ { .name = "toto user partition 3", -+ .offset = 16 * SZ_1M, -+ .size = 16 * SZ_1M }, -+}; -+ -+#define NUM_PARTITIONS32M 3 -+#define NUM_PARTITIONS64M 4 -+/* -+ * hardware specific access to control-lines -+*/ -+ -+static void toto_hwcontrol(struct mtd_info *mtd, int cmd) -+{ -+ -+ udelay(1); /* hopefully enough time for tc make proceding write to clear */ -+ switch(cmd){ -+ -+ case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break; -+ case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break; -+ -+ case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break; -+ case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break; -+ -+ case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break; -+ case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break; -+ } -+ udelay(1); /* allow time to ensure gpio state to over take memory write */ -+} -+ -+/* -+ * Main initialization routine -+ */ -+int __init toto_init (void) -+{ -+ struct nand_chip *this; -+ int err = 0; -+ -+ /* Allocate memory for MTD device structure and private data */ -+ toto_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), -+ GFP_KERNEL); -+ if (!toto_mtd) { -+ printk (KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n"); -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ /* Get pointer to private data */ -+ this = (struct nand_chip *) (&toto_mtd[1]); -+ -+ /* Initialize structures */ -+ memset((char *) toto_mtd, 0, sizeof(struct mtd_info)); -+ memset((char *) this, 0, sizeof(struct nand_chip)); -+ -+ /* Link the private data with the MTD structure */ -+ toto_mtd->priv = this; -+ -+ /* Set address of NAND IO lines */ -+ this->IO_ADDR_R = toto_io_base; -+ this->IO_ADDR_W = toto_io_base; -+ this->hwcontrol = toto_hwcontrol; -+ this->dev_ready = NULL; -+ /* 25 us command delay time */ -+ this->chip_delay = 30; -+ this->eccmode = NAND_ECC_SOFT; -+ -+ /* Scan to find existance of the device */ -+ if (nand_scan (toto_mtd, 1)) { -+ err = -ENXIO; -+ goto out_mtd; -+ } -+ -+ /* Allocate memory for internal data buffer */ -+ this->data_buf = kmalloc (sizeof(u_char) * (toto_mtd->oobblock + toto_mtd->oobsize), GFP_KERNEL); -+ if (!this->data_buf) { -+ printk (KERN_WARNING "Unable to allocate NAND data buffer for toto.\n"); -+ err = -ENOMEM; -+ goto out_mtd; -+ } -+ -+ /* Register the partitions */ -+ switch(toto_mtd->size){ -+ case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break; -+ case SZ_32M: add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M); break; -+ default: { -+ printk (KERN_WARNING "Unsupported Nand device\n"); -+ err = -ENXIO; -+ goto out_buf; -+ } -+ } -+ -+ gpioreserve(NAND_MASK); /* claim our gpios */ -+ archflashwp(0,0); /* open up flash for writing */ -+ -+ goto out; -+ -+out_buf: -+ kfree (this->data_buf); -+out_mtd: -+ kfree (toto_mtd); -+out: -+ return err; -+} -+ -+module_init(toto_init); -+ -+/* -+ * Clean up routine -+ */ -+static void __exit toto_cleanup (void) -+{ -+ struct nand_chip *this = (struct nand_chip *) &toto_mtd[1]; -+ -+ /* Unregister partitions */ -+ del_mtd_partitions(toto_mtd); -+ -+ /* Unregister the device */ -+ del_mtd_device (toto_mtd); -+ -+ /* Free internal data buffers */ -+ kfree (this->data_buf); -+ -+ /* Free the MTD device structure */ -+ kfree (toto_mtd); -+ -+ /* stop flash writes */ -+ archflashwp(0,1); -+ -+ /* release gpios to system */ -+ gpiorelease(NAND_MASK); -+} -+module_exit(toto_cleanup); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Richard Woodruff "); -+MODULE_DESCRIPTION("Glue layer for NAND flash on toto board"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/nand/tx4925ndfmc.c linux/drivers/mtd/nand/tx4925ndfmc.c ---- linux-mips-2.4.24-pre2/drivers/mtd/nand/tx4925ndfmc.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/nand/tx4925ndfmc.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,442 @@ -+/* -+ * drivers/mtd/tx4925ndfmc.c -+ * -+ * Overview: -+ * This is a device driver for the NAND flash device found on the -+ * Toshiba RBTX4925 reference board, which is a SmartMediaCard. It supports -+ * 16MiB, 32MiB and 64MiB cards. -+ * -+ * Author: MontaVista Software, Inc. source@mvista.com -+ * -+ * Derived from drivers/mtd/autcpu12.c -+ * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) -+ * -+ * $Id$ -+ * -+ * Copyright (C) 2001 Toshiba Corporation -+ * -+ * 2003 (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. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+extern struct nand_oobinfo jffs2_oobinfo; -+ -+/* -+ * MTD structure for RBTX4925 board -+ */ -+static struct mtd_info *tx4925ndfmc_mtd = NULL; -+ -+/* -+ * Module stuff -+ */ -+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -+#define tx4925ndfmc_init init_module -+#define tx4925ndfmc_cleanup cleanup_module -+#endif -+ -+/* -+ * Define partitions for flash devices -+ */ -+ -+static struct mtd_partition partition_info16k[] = { -+ { .name = "RBTX4925 flash partition 1", -+ .offset = 0, -+ .size = 8 * 0x00100000 }, -+ { .name = "RBTX4925 flash partition 2", -+ .offset = 8 * 0x00100000, -+ .size = 8 * 0x00100000 }, -+}; -+ -+static struct mtd_partition partition_info32k[] = { -+ { .name = "RBTX4925 flash partition 1", -+ .offset = 0, -+ .size = 8 * 0x00100000 }, -+ { .name = "RBTX4925 flash partition 2", -+ .offset = 8 * 0x00100000, -+ .size = 24 * 0x00100000 }, -+}; -+ -+static struct mtd_partition partition_info64k[] = { -+ { .name = "User FS", -+ .offset = 0, -+ .size = 16 * 0x00100000 }, -+ { .name = "RBTX4925 flash partition 2", -+ .offset = 16 * 0x00100000, -+ .size = 48 * 0x00100000}, -+}; -+ -+static struct mtd_partition partition_info128k[] = { -+ { .name = "Skip bad section", -+ .offset = 0, -+ .size = 16 * 0x00100000 }, -+ { .name = "User FS", -+ .offset = 16 * 0x00100000, -+ .size = 112 * 0x00100000 }, -+}; -+#define NUM_PARTITIONS16K 2 -+#define NUM_PARTITIONS32K 2 -+#define NUM_PARTITIONS64K 2 -+#define NUM_PARTITIONS128K 2 -+ -+/* -+ * hardware specific access to control-lines -+*/ -+static void tx4925ndfmc_hwcontrol(struct mtd_info *mtd, int cmd) -+{ -+ -+ switch(cmd){ -+ -+ case NAND_CTL_SETCLE: -+ tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_CLE; -+ break; -+ case NAND_CTL_CLRCLE: -+ tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_CLE; -+ break; -+ case NAND_CTL_SETALE: -+ tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ALE; -+ break; -+ case NAND_CTL_CLRALE: -+ tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ALE; -+ break; -+ case NAND_CTL_SETNCE: -+ tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_CE; -+ break; -+ case NAND_CTL_CLRNCE: -+ tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_CE; -+ break; -+ case NAND_CTL_SETWP: -+ tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_WE; -+ break; -+ case NAND_CTL_CLRWP: -+ tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_WE; -+ break; -+ } -+} -+ -+/* -+* read device ready pin -+*/ -+static int tx4925ndfmc_device_ready(struct mtd_info *mtd) -+{ -+ int ready; -+ ready = (tx4925_ndfmcptr->sr & TX4925_NDSFR_BUSY) ? 0 : 1; -+ return ready; -+} -+void tx4925ndfmc_enable_hwecc(struct mtd_info *mtd, int mode) -+{ -+ /* reset first */ -+ tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_MASK; -+ tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK; -+ tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_ENAB; -+} -+static void tx4925ndfmc_disable_ecc(void) -+{ -+ tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK; -+} -+static void tx4925ndfmc_enable_read_ecc(void) -+{ -+ tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK; -+ tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_READ; -+} -+void tx4925ndfmc_readecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code){ -+ int i; -+ u_char *ecc = ecc_code; -+ tx4925ndfmc_enable_read_ecc(); -+ for (i = 0;i < 6;i++,ecc++) -+ *ecc = tx4925_read_nfmc(&(tx4925_ndfmcptr->dtr)); -+ tx4925ndfmc_disable_ecc(); -+} -+void tx4925ndfmc_device_setup(void) -+{ -+ -+ *(unsigned char *)0xbb005000 &= ~0x08; -+ -+ /* reset NDFMC */ -+ tx4925_ndfmcptr->rstr |= TX4925_NDFRSTR_RST; -+ while (tx4925_ndfmcptr->rstr & TX4925_NDFRSTR_RST); -+ -+ /* setup BusSeparete, Hold Time, Strobe Pulse Width */ -+ tx4925_ndfmcptr->mcr = TX4925_BSPRT ? TX4925_NDFMCR_BSPRT : 0; -+ tx4925_ndfmcptr->spr = TX4925_HOLD << 4 | TX4925_SPW; -+} -+static u_char tx4925ndfmc_nand_read_byte(struct mtd_info *mtd) -+{ -+ struct nand_chip *this = mtd->priv; -+ return tx4925_read_nfmc(this->IO_ADDR_R); -+} -+ -+static void tx4925ndfmc_nand_write_byte(struct mtd_info *mtd, u_char byte) -+{ -+ struct nand_chip *this = mtd->priv; -+ tx4925_write_nfmc(byte, this->IO_ADDR_W); -+} -+ -+static void tx4925ndfmc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_W); -+} -+ -+static void tx4925ndfmc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_R); -+} -+ -+static int tx4925ndfmc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_R)) -+ return i; -+ -+ return 0; -+} -+ -+/* -+ * Send command to NAND device -+ */ -+static void tx4925ndfmc_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) -+{ -+ register struct nand_chip *this = mtd->priv; -+ -+ /* Begin command latch cycle */ -+ this->hwcontrol(mtd, NAND_CTL_SETCLE); -+ /* -+ * Write out the command to the device. -+ */ -+ if (command == NAND_CMD_SEQIN) { -+ int readcmd; -+ -+ if (column >= mtd->oobblock) { -+ /* OOB area */ -+ column -= mtd->oobblock; -+ readcmd = NAND_CMD_READOOB; -+ } else if (column < 256) { -+ /* First 256 bytes --> READ0 */ -+ readcmd = NAND_CMD_READ0; -+ } else { -+ column -= 256; -+ readcmd = NAND_CMD_READ1; -+ } -+ this->write_byte(mtd, readcmd); -+ } -+ this->write_byte(mtd, command); -+ -+ /* Set ALE and clear CLE to start address cycle */ -+ this->hwcontrol(mtd, NAND_CTL_CLRCLE); -+ -+ if (column != -1 || page_addr != -1) { -+ this->hwcontrol(mtd, NAND_CTL_SETALE); -+ -+ /* Serially input address */ -+ if (column != -1) -+ this->write_byte(mtd, column); -+ if (page_addr != -1) { -+ this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); -+ this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); -+ /* One more address cycle for higher density devices */ -+ if (mtd->size & 0x0c000000) -+ this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f)); -+ } -+ /* Latch in address */ -+ this->hwcontrol(mtd, NAND_CTL_CLRALE); -+ } -+ -+ /* -+ * program and erase have their own busy handlers -+ * status and sequential in needs no delay -+ */ -+ switch (command) { -+ -+ case NAND_CMD_PAGEPROG: -+ /* Turn off WE */ -+ this->hwcontrol (mtd, NAND_CTL_CLRWP); -+ return; -+ -+ case NAND_CMD_SEQIN: -+ /* Turn on WE */ -+ this->hwcontrol (mtd, NAND_CTL_SETWP); -+ return; -+ -+ case NAND_CMD_ERASE1: -+ case NAND_CMD_ERASE2: -+ case NAND_CMD_STATUS: -+ return; -+ -+ case NAND_CMD_RESET: -+ if (this->dev_ready) -+ break; -+ this->hwcontrol(mtd, NAND_CTL_SETCLE); -+ this->write_byte(mtd, NAND_CMD_STATUS); -+ this->hwcontrol(mtd, NAND_CTL_CLRCLE); -+ while ( !(this->read_byte(mtd) & 0x40)); -+ return; -+ -+ /* This applies to read commands */ -+ default: -+ /* -+ * If we don't have access to the busy pin, we apply the given -+ * command delay -+ */ -+ if (!this->dev_ready) { -+ udelay (this->chip_delay); -+ return; -+ } -+ } -+ -+ /* wait until command is processed */ -+ while (!this->dev_ready(mtd)); -+} -+ -+#ifdef CONFIG_MTD_CMDLINE_PARTS -+extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partitio -+n **pparts, char *); -+#endif -+ -+/* -+ * Main initialization routine -+ */ -+extern int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc); -+int __init tx4925ndfmc_init (void) -+{ -+ struct nand_chip *this; -+ int err = 0; -+ -+ /* Allocate memory for MTD device structure and private data */ -+ tx4925ndfmc_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), -+ GFP_KERNEL); -+ if (!tx4925ndfmc_mtd) { -+ printk ("Unable to allocate RBTX4925 NAND MTD device structure.\n"); -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ tx4925ndfmc_device_setup(); -+ -+ /* io is indirect via a register so don't need to ioremap address */ -+ -+ /* Get pointer to private data */ -+ this = (struct nand_chip *) (&tx4925ndfmc_mtd[1]); -+ -+ /* Initialize structures */ -+ memset((char *) tx4925ndfmc_mtd, 0, sizeof(struct mtd_info)); -+ memset((char *) this, 0, sizeof(struct nand_chip)); -+ -+ /* Link the private data with the MTD structure */ -+ tx4925ndfmc_mtd->priv = this; -+ -+ /* Set address of NAND IO lines */ -+ this->IO_ADDR_R = (unsigned long)&(tx4925_ndfmcptr->dtr); -+ this->IO_ADDR_W = (unsigned long)&(tx4925_ndfmcptr->dtr); -+ this->hwcontrol = tx4925ndfmc_hwcontrol; -+ this->enable_hwecc = tx4925ndfmc_enable_hwecc; -+ this->calculate_ecc = tx4925ndfmc_readecc; -+ this->correct_data = nand_correct_data; -+ this->eccmode = NAND_ECC_HW6_512; -+ this->dev_ready = tx4925ndfmc_device_ready; -+ /* 20 us command delay time */ -+ this->chip_delay = 20; -+ this->read_byte = tx4925ndfmc_nand_read_byte; -+ this->write_byte = tx4925ndfmc_nand_write_byte; -+ this->cmdfunc = tx4925ndfmc_nand_command; -+ this->write_buf = tx4925ndfmc_nand_write_buf; -+ this->read_buf = tx4925ndfmc_nand_read_buf; -+ this->verify_buf = tx4925ndfmc_nand_verify_buf; -+ -+ /* Scan to find existance of the device */ -+ if (nand_scan (tx4925ndfmc_mtd, 1)) { -+ err = -ENXIO; -+ goto out_ior; -+ } -+ -+ /* Allocate memory for internal data buffer */ -+ this->data_buf = kmalloc (sizeof(u_char) * (tx4925ndfmc_mtd->oobblock + tx4925ndfmc_mtd->oobsize), GFP_KERNEL); -+ if (!this->data_buf) { -+ printk ("Unable to allocate NAND data buffer for RBTX4925.\n"); -+ err = -ENOMEM; -+ goto out_ior; -+ } -+ -+ /* Register the partitions */ -+#ifdef CONFIG_MTD_CMDLINE_PARTS -+ { -+ int mtd_parts_nb = 0; -+ struct mtd_partition *mtd_parts = 0; -+ mtd_parts_nb = parse_cmdline_partitions(tx4925ndfmc_mtd, &mtd_parts, "tx4925ndfmc"); -+ if (mtd_parts_nb > 0) -+ add_mtd_partitions(tx4925ndfmc_mtd, mtd_parts, mtd_parts_nb); -+ else -+ add_mtd_device(tx4925ndfmc_mtd); -+ } -+#else /* ifdef CONFIG_MTD_CMDLINE_PARTS */ -+ switch(tx4925ndfmc_mtd->size){ -+ case 0x01000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info16k, NUM_PARTITIONS16K); break; -+ case 0x02000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info32k, NUM_PARTITIONS32K); break; -+ case 0x04000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info64k, NUM_PARTITIONS64K); break; -+ case 0x08000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info128k, NUM_PARTITIONS128K); break; -+ default: { -+ printk ("Unsupported SmartMedia device\n"); -+ err = -ENXIO; -+ goto out_buf; -+ } -+ } -+#endif /* ifdef CONFIG_MTD_CMDLINE_PARTS */ -+ goto out; -+ -+out_buf: -+ kfree (this->data_buf); -+out_ior: -+out: -+ return err; -+} -+ -+module_init(tx4925ndfmc_init); -+ -+/* -+ * Clean up routine -+ */ -+#ifdef MODULE -+static void __exit tx4925ndfmc_cleanup (void) -+{ -+ struct nand_chip *this = (struct nand_chip *) &tx4925ndfmc_mtd[1]; -+ -+ /* Unregister partitions */ -+ del_mtd_partitions(tx4925ndfmc_mtd); -+ -+ /* Unregister the device */ -+ del_mtd_device (tx4925ndfmc_mtd); -+ -+ /* Free internal data buffers */ -+ kfree (this->data_buf); -+ -+ /* Free the MTD device structure */ -+ kfree (tx4925ndfmc_mtd); -+} -+module_exit(tx4925ndfmc_cleanup); -+#endif -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Alice Hennessy "); -+MODULE_DESCRIPTION("Glue layer for SmartMediaCard on Toshiba RBTX4925"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/nand/tx4938ndfmc.c linux/drivers/mtd/nand/tx4938ndfmc.c ---- linux-mips-2.4.24-pre2/drivers/mtd/nand/tx4938ndfmc.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/nand/tx4938ndfmc.c 2004-11-17 18:17:59.000000000 +0100 -@@ -0,0 +1,422 @@ -+/* -+ * drivers/mtd/nand/tx4938ndfmc.c -+ * -+ * Overview: -+ * This is a device driver for the NAND flash device connected to -+ * TX4938 internal NAND Memory Controller. -+ * TX4938 NDFMC is almost same as TX4925 NDFMC, but register size are 64 bit. -+ * -+ * Author: source@mvista.com -+ * -+ * Based on spia.c by Steven J. Hill -+ * -+ * $Id$ -+ * -+ * Copyright (C) 2000-2001 Toshiba Corporation -+ * -+ * 2003 (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. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+extern struct nand_oobinfo jffs2_oobinfo; -+ -+/* -+ * MTD structure for TX4938 NDFMC -+ */ -+static struct mtd_info *tx4938ndfmc_mtd; -+ -+/* -+ * Define partitions for flash device -+ */ -+#define flush_wb() (void)tx4938_ndfmcptr->mcr; -+ -+#define NUM_PARTITIONS 3 -+#define NUMBER_OF_CIS_BLOCKS 24 -+#define SIZE_OF_BLOCK 0x00004000 -+#define NUMBER_OF_BLOCK_PER_ZONE 1024 -+#define SIZE_OF_ZONE (NUMBER_OF_BLOCK_PER_ZONE * SIZE_OF_BLOCK) -+#ifndef CONFIG_MTD_CMDLINE_PARTS -+/* -+ * You can use the following sample of MTD partitions -+ * on the NAND Flash Memory 32MB or more. -+ * -+ * The following figure shows the image of the sample partition on -+ * the 32MB NAND Flash Memory. -+ * -+ * Block No. -+ * 0 +-----------------------------+ ------ -+ * | CIS | ^ -+ * 24 +-----------------------------+ | -+ * | kernel image | | Zone 0 -+ * | | | -+ * +-----------------------------+ | -+ * 1023 | unused area | v -+ * +-----------------------------+ ------ -+ * 1024 | JFFS2 | ^ -+ * | | | -+ * | | | Zone 1 -+ * | | | -+ * | | | -+ * | | v -+ * 2047 +-----------------------------+ ------ -+ * -+ */ -+static struct mtd_partition partition_info[NUM_PARTITIONS] = { -+ { -+ .name = "RBTX4938 CIS Area", -+ .offset = 0, -+ .size = (NUMBER_OF_CIS_BLOCKS * SIZE_OF_BLOCK), -+ .mask_flags = MTD_WRITEABLE /* This partition is NOT writable */ -+ }, -+ { -+ .name = "RBTX4938 kernel image", -+ .offset = MTDPART_OFS_APPEND, -+ .size = 8 * 0x00100000, /* 8MB (Depends on size of kernel image) */ -+ .mask_flags = MTD_WRITEABLE /* This partition is NOT writable */ -+ }, -+ { -+ .name = "Root FS (JFFS2)", -+ .offset = (0 + SIZE_OF_ZONE), /* start address of next zone */ -+ .size = MTDPART_SIZ_FULL -+ }, -+}; -+#endif -+ -+static void tx4938ndfmc_hwcontrol(struct mtd_info *mtd, int cmd) -+{ -+ switch (cmd) { -+ case NAND_CTL_SETCLE: -+ tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_CLE; -+ break; -+ case NAND_CTL_CLRCLE: -+ tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_CLE; -+ break; -+ case NAND_CTL_SETALE: -+ tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_ALE; -+ break; -+ case NAND_CTL_CLRALE: -+ tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_ALE; -+ break; -+ /* TX4938_NDFMCR_CE bit is 0:high 1:low */ -+ case NAND_CTL_SETNCE: -+ tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_CE; -+ break; -+ case NAND_CTL_CLRNCE: -+ tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_CE; -+ break; -+ case NAND_CTL_SETWP: -+ tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_WE; -+ break; -+ case NAND_CTL_CLRWP: -+ tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_WE; -+ break; -+ } -+} -+static int tx4938ndfmc_dev_ready(struct mtd_info *mtd) -+{ -+ flush_wb(); -+ return !(tx4938_ndfmcptr->sr & TX4938_NDFSR_BUSY); -+} -+static void tx4938ndfmc_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) -+{ -+ u32 mcr = tx4938_ndfmcptr->mcr; -+ mcr &= ~TX4938_NDFMCR_ECC_ALL; -+ tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF; -+ tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_READ; -+ ecc_code[1] = tx4938_ndfmcptr->dtr; -+ ecc_code[0] = tx4938_ndfmcptr->dtr; -+ ecc_code[2] = tx4938_ndfmcptr->dtr; -+ tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF; -+} -+static void tx4938ndfmc_enable_hwecc(struct mtd_info *mtd, int mode) -+{ -+ u32 mcr = tx4938_ndfmcptr->mcr; -+ mcr &= ~TX4938_NDFMCR_ECC_ALL; -+ tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_RESET; -+ tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF; -+ tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_ON; -+} -+ -+static u_char tx4938ndfmc_nand_read_byte(struct mtd_info *mtd) -+{ -+ struct nand_chip *this = mtd->priv; -+ return tx4938_read_nfmc(this->IO_ADDR_R); -+} -+ -+static void tx4938ndfmc_nand_write_byte(struct mtd_info *mtd, u_char byte) -+{ -+ struct nand_chip *this = mtd->priv; -+ tx4938_write_nfmc(byte, this->IO_ADDR_W); -+} -+ -+static void tx4938ndfmc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_W); -+} -+ -+static void tx4938ndfmc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_R); -+} -+ -+static int tx4938ndfmc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_R)) -+ return i; -+ -+ return 0; -+} -+ -+/* -+ * Send command to NAND device -+ */ -+static void tx4938ndfmc_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) -+{ -+ register struct nand_chip *this = mtd->priv; -+ -+ /* Begin command latch cycle */ -+ this->hwcontrol(mtd, NAND_CTL_SETCLE); -+ /* -+ * Write out the command to the device. -+ */ -+ if (command == NAND_CMD_SEQIN) { -+ int readcmd; -+ -+ if (column >= mtd->oobblock) { -+ /* OOB area */ -+ column -= mtd->oobblock; -+ readcmd = NAND_CMD_READOOB; -+ } else if (column < 256) { -+ /* First 256 bytes --> READ0 */ -+ readcmd = NAND_CMD_READ0; -+ } else { -+ column -= 256; -+ readcmd = NAND_CMD_READ1; -+ } -+ this->write_byte(mtd, readcmd); -+ } -+ this->write_byte(mtd, command); -+ -+ /* Set ALE and clear CLE to start address cycle */ -+ this->hwcontrol(mtd, NAND_CTL_CLRCLE); -+ -+ if (column != -1 || page_addr != -1) { -+ this->hwcontrol(mtd, NAND_CTL_SETALE); -+ -+ /* Serially input address */ -+ if (column != -1) -+ this->write_byte(mtd, column); -+ if (page_addr != -1) { -+ this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); -+ this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); -+ /* One more address cycle for higher density devices */ -+ if (mtd->size & 0x0c000000) -+ this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f)); -+ } -+ /* Latch in address */ -+ this->hwcontrol(mtd, NAND_CTL_CLRALE); -+ } -+ -+ /* -+ * program and erase have their own busy handlers -+ * status and sequential in needs no delay -+ */ -+ switch (command) { -+ -+ case NAND_CMD_PAGEPROG: -+ /* Turn off WE */ -+ this->hwcontrol (mtd, NAND_CTL_CLRWP); -+ return; -+ -+ case NAND_CMD_SEQIN: -+ /* Turn on WE */ -+ this->hwcontrol (mtd, NAND_CTL_SETWP); -+ return; -+ -+ case NAND_CMD_ERASE1: -+ case NAND_CMD_ERASE2: -+ case NAND_CMD_STATUS: -+ return; -+ -+ case NAND_CMD_RESET: -+ if (this->dev_ready) -+ break; -+ this->hwcontrol(mtd, NAND_CTL_SETCLE); -+ this->write_byte(mtd, NAND_CMD_STATUS); -+ this->hwcontrol(mtd, NAND_CTL_CLRCLE); -+ while ( !(this->read_byte(mtd) & 0x40)); -+ return; -+ -+ /* This applies to read commands */ -+ default: -+ /* -+ * If we don't have access to the busy pin, we apply the given -+ * command delay -+ */ -+ if (!this->dev_ready) { -+ udelay (this->chip_delay); -+ return; -+ } -+ } -+ -+ /* wait until command is processed */ -+ while (!this->dev_ready(mtd)); -+} -+ -+#ifdef CONFIG_MTD_CMDLINE_PARTS -+extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, char *); -+#endif -+/* -+ * Main initialization routine -+ */ -+int __init tx4938ndfmc_init (void) -+{ -+ struct nand_chip *this; -+ int bsprt = 0, hold = 0xf, spw = 0xf; -+ int protected = 0; -+ -+ if ((*rbtx4938_piosel_ptr & 0x0c) != 0x08) { -+ printk("TX4938 NDFMC: disabled by IOC PIOSEL\n"); -+ return -ENODEV; -+ } -+ bsprt = 1; -+ hold = 2; -+ spw = 9 - 1; /* 8 GBUSCLK = 80ns (@ GBUSCLK 100MHz) */ -+ -+ if ((tx4938_ccfgptr->pcfg & -+ (TX4938_PCFG_ATA_SEL|TX4938_PCFG_ISA_SEL|TX4938_PCFG_NDF_SEL)) -+ != TX4938_PCFG_NDF_SEL) { -+ printk("TX4938 NDFMC: disabled by PCFG.\n"); -+ return -ENODEV; -+ } -+ -+ /* reset NDFMC */ -+ tx4938_ndfmcptr->rstr |= TX4938_NDFRSTR_RST; -+ while (tx4938_ndfmcptr->rstr & TX4938_NDFRSTR_RST) -+ ; -+ /* setup BusSeparete, Hold Time, Strobe Pulse Width */ -+ tx4938_ndfmcptr->mcr = bsprt ? TX4938_NDFMCR_BSPRT : 0; -+ tx4938_ndfmcptr->spr = hold << 4 | spw; -+ -+ /* Allocate memory for MTD device structure and private data */ -+ tx4938ndfmc_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), -+ GFP_KERNEL); -+ if (!tx4938ndfmc_mtd) { -+ printk ("Unable to allocate TX4938 NDFMC MTD device structure.\n"); -+ return -ENOMEM; -+ } -+ -+ /* Get pointer to private data */ -+ this = (struct nand_chip *) (&tx4938ndfmc_mtd[1]); -+ -+ /* Initialize structures */ -+ memset((char *) tx4938ndfmc_mtd, 0, sizeof(struct mtd_info)); -+ memset((char *) this, 0, sizeof(struct nand_chip)); -+ -+ /* Link the private data with the MTD structure */ -+ tx4938ndfmc_mtd->priv = this; -+ -+ /* Set address of NAND IO lines */ -+ this->IO_ADDR_R = (unsigned long)&tx4938_ndfmcptr->dtr; -+ this->IO_ADDR_W = (unsigned long)&tx4938_ndfmcptr->dtr; -+ this->hwcontrol = tx4938ndfmc_hwcontrol; -+ this->dev_ready = tx4938ndfmc_dev_ready; -+ this->calculate_ecc = tx4938ndfmc_calculate_ecc; -+ this->correct_data = nand_correct_data; -+ this->enable_hwecc = tx4938ndfmc_enable_hwecc; -+ this->eccmode = NAND_ECC_HW3_256; -+ this->chip_delay = 100; -+ this->read_byte = tx4938ndfmc_nand_read_byte; -+ this->write_byte = tx4938ndfmc_nand_write_byte; -+ this->cmdfunc = tx4938ndfmc_nand_command; -+ this->write_buf = tx4938ndfmc_nand_write_buf; -+ this->read_buf = tx4938ndfmc_nand_read_buf; -+ this->verify_buf = tx4938ndfmc_nand_verify_buf; -+ -+ /* Scan to find existance of the device */ -+ if (nand_scan (tx4938ndfmc_mtd, 1)) { -+ kfree (tx4938ndfmc_mtd); -+ return -ENXIO; -+ } -+ -+ /* Allocate memory for internal data buffer */ -+ this->data_buf = kmalloc (sizeof(u_char) * (tx4938ndfmc_mtd->oobblock + tx4938ndfmc_mtd->oobsize), GFP_KERNEL); -+ if (!this->data_buf) { -+ printk ("Unable to allocate NAND data buffer for TX4938.\n"); -+ kfree (tx4938ndfmc_mtd); -+ return -ENOMEM; -+ } -+ -+ if (protected) { -+ printk(KERN_INFO "TX4938 NDFMC: write protected.\n"); -+ tx4938ndfmc_mtd->flags &= ~(MTD_WRITEABLE | MTD_ERASEABLE); -+ } -+ -+#ifdef CONFIG_MTD_CMDLINE_PARTS -+ { -+ int mtd_parts_nb = 0; -+ struct mtd_partition *mtd_parts = 0; -+ mtd_parts_nb = parse_cmdline_partitions(tx4938ndfmc_mtd, &mtd_parts, "tx4938ndfmc"); -+ if (mtd_parts_nb > 0) -+ add_mtd_partitions(tx4938ndfmc_mtd, mtd_parts, mtd_parts_nb); -+ else -+ add_mtd_device(tx4938ndfmc_mtd); -+ } -+#else -+ add_mtd_partitions(tx4938ndfmc_mtd, partition_info, NUM_PARTITIONS ); -+#endif -+ -+ return 0; -+} -+module_init(tx4938ndfmc_init); -+ -+/* -+ * Clean up routine -+ */ -+static void __exit tx4938ndfmc_cleanup (void) -+{ -+ struct nand_chip *this = (struct nand_chip *) tx4938ndfmc_mtd->priv; -+ -+ /* Unregister the device */ -+#ifdef CONFIG_MTD_CMDLINE_PARTS -+ del_mtd_partitions(tx4938ndfmc_mtd); -+#endif -+ del_mtd_device (tx4938ndfmc_mtd); -+ -+ /* Free the MTD device structure */ -+ kfree (tx4938ndfmc_mtd); -+ -+ /* Free internal data buffer */ -+ kfree (this->data_buf); -+} -+module_exit(tx4938ndfmc_cleanup); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Alice Hennessy "); -+MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on TX4938 NDFMC"); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/nftlcore.c linux/drivers/mtd/nftlcore.c ---- linux-mips-2.4.24-pre2/drivers/mtd/nftlcore.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/nftlcore.c 2004-11-17 18:17:58.881337936 +0100 -@@ -1,7 +1,7 @@ - /* Linux driver for NAND Flash Translation Layer */ - /* (c) 1999 Machine Vision Holdings, Inc. */ - /* Author: David Woodhouse */ --/* $Id$ */ -+/* $Id$ */ - - /* - The contents of this file are distributed under the GNU General -@@ -23,15 +23,13 @@ - #include - #include - #include --#include -+#include - --#ifdef CONFIG_KMOD - #include --#endif - #include - #include - #include --#include -+#include - - /* maximum number of loops while examining next block, to have a - chance to detect consistency problems (they should never happen -@@ -39,187 +37,95 @@ - - #define MAX_LOOPS 10000 - --/* NFTL block device stuff */ --#define MAJOR_NR NFTL_MAJOR --#define DEVICE_REQUEST nftl_request --#define DEVICE_OFF(device) -- -- --#include --#include -- --/* Linux-specific block device functions */ -- --/* I _HATE_ the Linux block device setup more than anything else I've ever -- * encountered, except ... -- */ -- --static int nftl_sizes[256]; --static int nftl_blocksizes[256]; -- --/* .. for the Linux partition table handling. */ --struct hd_struct part_table[256]; -- --#if LINUX_VERSION_CODE < 0x20328 --static void dummy_init (struct gendisk *crap) --{} --#endif -- --static struct gendisk nftl_gendisk = { -- major: MAJOR_NR, -- major_name: "nftl", -- minor_shift: NFTL_PARTN_BITS, /* Bits to shift to get real from partition */ -- max_p: (1<mtd == mtd) { -- /* This is a Spare Media Header for an NFTL we've already found */ -- DEBUG(MTD_DEBUG_LEVEL1, "MTD already mounted as NFTL\n"); -+ if (mtd->ecctype != MTD_ECC_RS_DiskOnChip) - return; -- } -- } -- if (firstfree == -1) { -- printk(KERN_WARNING "No more NFTL slot available\n"); -- return; -- } -+ -+ DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name); - - nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); -+ - if (!nftl) { -- printk(KERN_WARNING "Out of memory for NFTL data structures\n"); -+ printk(KERN_WARNING "NFTL: out of memory for data structures\n"); - return; - } -+ memset(nftl, 0, sizeof(*nftl)); - -- init_MUTEX(&nftl->mutex); -- -- nftl->mtd = mtd; -+ nftl->mbd.mtd = mtd; -+ nftl->mbd.devnum = -1; -+ nftl->mbd.blksize = 512; -+ nftl->mbd.tr = tr; - - if (NFTL_mount(nftl) < 0) { -- printk(KERN_WARNING "Could not mount NFTL device\n"); -+ printk(KERN_WARNING "NFTL: could not mount device\n"); - kfree(nftl); - return; - } - - /* OK, it's a new one. Set up all the data structures. */ --#ifdef PSYCHO_DEBUG -- printk("Found new NFTL nftl%c\n", firstfree + 'a'); --#endif - -- /* linux stuff */ -- nftl->usecount = 0; -+ /* Calculate geometry */ - nftl->cylinders = 1024; - nftl->heads = 16; - - temp = nftl->cylinders * nftl->heads; -- nftl->sectors = nftl->nr_sects / temp; -- if (nftl->nr_sects % temp) { -+ nftl->sectors = nftl->mbd.size / temp; -+ if (nftl->mbd.size % temp) { - nftl->sectors++; - temp = nftl->cylinders * nftl->sectors; -- nftl->heads = nftl->nr_sects / temp; -+ nftl->heads = nftl->mbd.size / temp; - -- if (nftl->nr_sects % temp) { -+ if (nftl->mbd.size % temp) { - nftl->heads++; - temp = nftl->heads * nftl->sectors; -- nftl->cylinders = nftl->nr_sects / temp; -+ nftl->cylinders = nftl->mbd.size / temp; - } - } - -- if (nftl->nr_sects != nftl->heads * nftl->cylinders * nftl->sectors) { -- printk(KERN_WARNING "Cannot calculate an NFTL geometry to " -- "match size of 0x%x.\n", nftl->nr_sects); -- printk(KERN_WARNING "Using C:%d H:%d S:%d (== 0x%lx sects)\n", -+ if (nftl->mbd.size != nftl->heads * nftl->cylinders * nftl->sectors) { -+ /* -+ Oh no we don't have -+ mbd.size == heads * cylinders * sectors -+ */ -+ printk(KERN_WARNING "NFTL: cannot calculate a geometry to " -+ "match size of 0x%lx.\n", nftl->mbd.size); -+ printk(KERN_WARNING "NFTL: using C:%d H:%d S:%d " -+ "(== 0x%lx sects)\n", - nftl->cylinders, nftl->heads , nftl->sectors, -- (long)nftl->cylinders * (long)nftl->heads * (long)nftl->sectors ); -- -- /* Oh no we don't have nftl->nr_sects = nftl->heads * nftl->cylinders * nftl->sectors; */ -+ (long)nftl->cylinders * (long)nftl->heads * -+ (long)nftl->sectors ); - } -- NFTLs[firstfree] = nftl; -- /* Finally, set up the block device sizes */ -- nftl_sizes[firstfree * 16] = nftl->nr_sects; -- //nftl_blocksizes[firstfree*16] = 512; -- part_table[firstfree * 16].nr_sects = nftl->nr_sects; -- -- nftl_gendisk.nr_real++; -- -- /* partition check ... */ --#if LINUX_VERSION_CODE < 0x20328 -- resetup_one_dev(&nftl_gendisk, firstfree); --#else -- grok_partitions(&nftl_gendisk, firstfree, 1<nr_sects); --#endif --} -- --static void NFTL_unsetup(int i) --{ -- struct NFTLrecord *nftl = NFTLs[i]; -- -- DEBUG(MTD_DEBUG_LEVEL1, "NFTL_unsetup %d\n", i); -- -- NFTLs[i] = NULL; - -+ if (add_mtd_blktrans_dev(&nftl->mbd)) { - if (nftl->ReplUnitTable) - kfree(nftl->ReplUnitTable); - if (nftl->EUNtable) - kfree(nftl->EUNtable); -- -- nftl_gendisk.nr_real--; - kfree(nftl); --} -- --/* Search the MTD device for NFTL partitions */ --static void NFTL_notify_add(struct mtd_info *mtd) --{ -- DEBUG(MTD_DEBUG_LEVEL1, "NFTL_notify_add for %s\n", mtd->name); -- -- if (mtd) { -- if (!mtd->read_oob) { -- /* If this MTD doesn't have out-of-band data, -- then there's no point continuing */ -- DEBUG(MTD_DEBUG_LEVEL1, "No OOB data, quitting\n"); - return; - } -- DEBUG(MTD_DEBUG_LEVEL3, "mtd->read = %p, size = %d, erasesize = %d\n", -- mtd->read, mtd->size, mtd->erasesize); -- -- NFTL_setup(mtd); -- } -+#ifdef PSYCHO_DEBUG -+ printk(KERN_INFO "NFTL: Found new nftl%c\n", nftl->mbd.devnum + 'a'); -+#endif - } - --static void NFTL_notify_remove(struct mtd_info *mtd) -+static void nftl_remove_dev(struct mtd_blktrans_dev *dev) - { -- int i; -+ struct NFTLrecord *nftl = (void *)dev; - -- for (i = 0; i < MAX_NFTLS; i++) { -- if (NFTLs[i] && NFTLs[i]->mtd == mtd) -- NFTL_unsetup(i); -- } -+ DEBUG(MTD_DEBUG_LEVEL1, "NFTL: remove_dev (i=%d)\n", dev->devnum); -+ -+ del_mtd_blktrans_dev(dev); -+ if (nftl->ReplUnitTable) -+ kfree(nftl->ReplUnitTable); -+ if (nftl->EUNtable) -+ kfree(nftl->EUNtable); -+ kfree(nftl); - } - - #ifdef CONFIG_NFTL_RW -@@ -303,7 +209,7 @@ - - targetEUN = thisEUN; - for (block = 0; block < nftl->EraseSize / 512; block ++) { -- MTD_READOOB(nftl->mtd, -+ MTD_READOOB(nftl->mbd.mtd, - (thisEUN * nftl->EraseSize) + (block * 512), - 16 , &retlen, (char *)&oob); - if (block == 2) { -@@ -420,7 +326,7 @@ - chain by selecting the longer one */ - oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS); - oob.u.c.unused = 0xffffffff; -- MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, -+ MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, - 8, &retlen, (char *)&oob.u); - } - -@@ -444,16 +350,16 @@ - if (BlockMap[block] == BLOCK_NIL) - continue; - -- ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512), -+ ret = MTD_READECC(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512), - 512, &retlen, movebuf, (char *)&oob, NAND_ECC_DISKONCHIP); - if (ret < 0) { -- ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block]) -+ ret = MTD_READECC(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) - + (block * 512), 512, &retlen, - movebuf, (char *)&oob, NAND_ECC_DISKONCHIP); - if (ret != -EIO) - printk("Error went away on retry.\n"); - } -- MTD_WRITEECC(nftl->mtd, (nftl->EraseSize * targetEUN) + (block * 512), -+ MTD_WRITEECC(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + (block * 512), - 512, &retlen, movebuf, (char *)&oob, NAND_ECC_DISKONCHIP); - } - -@@ -462,7 +368,7 @@ - = cpu_to_le16(thisVUC); - oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; - -- MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 8, -+ MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 8, - 8, &retlen, (char *)&oob.u); - - /* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */ -@@ -582,7 +488,7 @@ - - lastEUN = writeEUN; - -- MTD_READOOB(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs, -+ MTD_READOOB(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs, - 8, &retlen, (char *)&bci); - - DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n", -@@ -670,12 +576,12 @@ - nftl->ReplUnitTable[writeEUN] = BLOCK_NIL; - - /* ... and on the flash itself */ -- MTD_READOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8, -+ MTD_READOOB(nftl->mbd.mtd, writeEUN * nftl->EraseSize + 8, 8, - &retlen, (char *)&oob.u); - - oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); - -- MTD_WRITEOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8, -+ MTD_WRITEOOB(nftl->mbd.mtd, writeEUN * nftl->EraseSize + 8, 8, - &retlen, (char *)&oob.u); - - /* we link the new block to the chain only after the -@@ -685,13 +591,13 @@ - /* Both in our cache... */ - nftl->ReplUnitTable[lastEUN] = writeEUN; - /* ... and on the flash itself */ -- MTD_READOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8, -+ MTD_READOOB(nftl->mbd.mtd, (lastEUN * nftl->EraseSize) + 8, - 8, &retlen, (char *)&oob.u); - - oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum - = cpu_to_le16(writeEUN); - -- MTD_WRITEOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8, -+ MTD_WRITEOOB(nftl->mbd.mtd, (lastEUN * nftl->EraseSize) + 8, - 8, &retlen, (char *)&oob.u); - } - -@@ -704,8 +610,10 @@ - return 0xffff; - } - --static int NFTL_writeblock(struct NFTLrecord *nftl, unsigned block, char *buffer) -+static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, -+ char *buffer) - { -+ struct NFTLrecord *nftl = (void *)mbd; - u16 writeEUN; - unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1); - size_t retlen; -@@ -720,7 +628,7 @@ - return 1; - } - -- MTD_WRITEECC(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs, -+ MTD_WRITEECC(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs, - 512, &retlen, (char *)buffer, (char *)eccbuf, NAND_ECC_DISKONCHIP); - /* no need to write SECTOR_USED flags since they are written in mtd_writeecc */ - -@@ -728,8 +636,10 @@ - } - #endif /* CONFIG_NFTL_RW */ - --static int NFTL_readblock(struct NFTLrecord *nftl, unsigned block, char *buffer) -+static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block, -+ char *buffer) - { -+ struct NFTLrecord *nftl = (void *)mbd; - u16 lastgoodEUN; - u16 thisEUN = nftl->EUNtable[block / (nftl->EraseSize / 512)]; - unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1); -@@ -742,7 +652,7 @@ - - if (thisEUN != BLOCK_NIL) { - while (thisEUN < nftl->nb_blocks) { -- if (MTD_READOOB(nftl->mtd, (thisEUN * nftl->EraseSize) + blockofs, -+ if (MTD_READOOB(nftl->mbd.mtd, (thisEUN * nftl->EraseSize) + blockofs, - 8, &retlen, (char *)&bci) < 0) - status = SECTOR_IGNORE; - else -@@ -761,13 +671,13 @@ - case SECTOR_IGNORE: - break; - default: -- printk("Unknown status for block %d in EUN %d: %x\n", -+ printk("Unknown status for block %ld in EUN %d: %x\n", - block, thisEUN, status); - break; - } - - if (!silly--) { -- printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", -+ printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%lx\n", - block / (nftl->EraseSize / 512)); - return 1; - } -@@ -783,264 +693,22 @@ - loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs; - size_t retlen; - u_char eccbuf[6]; -- if (MTD_READECC(nftl->mtd, ptr, 512, &retlen, buffer, eccbuf, NAND_ECC_DISKONCHIP)) -+ if (MTD_READECC(nftl->mbd.mtd, ptr, 512, &retlen, buffer, eccbuf, NAND_ECC_DISKONCHIP)) - return -EIO; - } - return 0; - } - --static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) --{ -- struct NFTLrecord *nftl; -- int p; -- -- nftl = NFTLs[MINOR(inode->i_rdev) >> NFTL_PARTN_BITS]; -- -- if (!nftl) return -EINVAL; -- -- switch (cmd) { -- case HDIO_GETGEO: { -- struct hd_geometry g; -- -- g.heads = nftl->heads; -- g.sectors = nftl->sectors; -- g.cylinders = nftl->cylinders; -- g.start = part_table[MINOR(inode->i_rdev)].start_sect; -- return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0; -- } -- case BLKGETSIZE: /* Return device size */ -- return put_user(part_table[MINOR(inode->i_rdev)].nr_sects, -- (unsigned long *) arg); -- --#ifdef BLKGETSIZE64 -- case BLKGETSIZE64: -- return put_user((u64)part_table[MINOR(inode->i_rdev)].nr_sects << 9, -- (u64 *)arg); --#endif -- -- case BLKFLSBUF: -- if (!capable(CAP_SYS_ADMIN)) return -EACCES; -- fsync_dev(inode->i_rdev); -- invalidate_buffers(inode->i_rdev); -- if (nftl->mtd->sync) -- nftl->mtd->sync(nftl->mtd); -- return 0; -- -- case BLKRRPART: -- if (!capable(CAP_SYS_ADMIN)) return -EACCES; -- if (nftl->usecount > 1) return -EBUSY; -- /* -- * We have to flush all buffers and invalidate caches, -- * or we won't be able to re-use the partitions, -- * if there was a change and we don't want to reboot -- */ -- p = (1< 0) { -- kdev_t devp = MKDEV(MAJOR(inode->i_dev), MINOR(inode->i_dev)+p); -- if (part_table[p].nr_sects > 0) -- invalidate_device (devp, 1); -- -- part_table[MINOR(inode->i_dev)+p].start_sect = 0; -- part_table[MINOR(inode->i_dev)+p].nr_sects = 0; -- } -- --#if LINUX_VERSION_CODE < 0x20328 -- resetup_one_dev(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS); --#else -- grok_partitions(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS, -- 1<nr_sects); --#endif -- return 0; -- --#if (LINUX_VERSION_CODE < 0x20303) -- RO_IOCTLS(inode->i_rdev, arg); /* ref. linux/blk.h */ --#else -- case BLKROSET: -- case BLKROGET: -- case BLKSSZGET: -- return blk_ioctl(inode->i_rdev, cmd, arg); --#endif -- -- default: -- return -EINVAL; -- } --} -- --void nftl_request(RQFUNC_ARG) --{ -- unsigned int dev, block, nsect; -- struct NFTLrecord *nftl; -- char *buffer; -- struct request *req; -- int res; -- -- while (1) { -- INIT_REQUEST; /* blk.h */ -- req = CURRENT; -- -- /* We can do this because the generic code knows not to -- touch the request at the head of the queue */ -- spin_unlock_irq(&io_request_lock); -- -- DEBUG(MTD_DEBUG_LEVEL2, "NFTL_request\n"); -- DEBUG(MTD_DEBUG_LEVEL3, "NFTL %s request, from sector 0x%04lx for 0x%04lx sectors\n", -- (req->cmd == READ) ? "Read " : "Write", -- req->sector, req->current_nr_sectors); -- -- dev = MINOR(req->rq_dev); -- block = req->sector; -- nsect = req->current_nr_sectors; -- buffer = req->buffer; -- res = 1; /* succeed */ -- -- if (dev >= MAX_NFTLS * (1<rq_dev)); -- res = 0; /* fail */ -- goto repeat; -- } -- -- nftl = NFTLs[dev / (1<mutex); -- DEBUG(MTD_DEBUG_LEVEL3, "Got mutex\n"); -- -- if (block + nsect > part_table[dev].nr_sects) { -- /* access past the end of device */ -- printk("nftl%c%d: bad access: block = %d, count = %d\n", -- (MINOR(req->rq_dev)>>6)+'a', dev & 0xf, block, nsect); -- up(&nftl->mutex); -- res = 0; /* fail */ -- goto repeat; -- } -- -- block += part_table[dev].start_sect; -- -- if (req->cmd == READ) { -- DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request of 0x%x sectors @ %x " -- "(req->nr_sectors == %lx)\n", nsect, block, req->nr_sectors); -- -- for ( ; nsect > 0; nsect-- , block++, buffer += 512) { -- /* Read a single sector to req->buffer + (512 * i) */ -- if (NFTL_readblock(nftl, block, buffer)) { -- DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request failed\n"); -- up(&nftl->mutex); -- res = 0; -- goto repeat; -- } -- } -- -- DEBUG(MTD_DEBUG_LEVEL2,"NFTL read request completed OK\n"); -- up(&nftl->mutex); -- goto repeat; -- } else if (req->cmd == WRITE) { -- DEBUG(MTD_DEBUG_LEVEL2, "NFTL write request of 0x%x sectors @ %x " -- "(req->nr_sectors == %lx)\n", nsect, block, -- req->nr_sectors); --#ifdef CONFIG_NFTL_RW -- for ( ; nsect > 0; nsect-- , block++, buffer += 512) { -- /* Read a single sector to req->buffer + (512 * i) */ -- if (NFTL_writeblock(nftl, block, buffer)) { -- DEBUG(MTD_DEBUG_LEVEL1,"NFTL write request failed\n"); -- up(&nftl->mutex); -- res = 0; -- goto repeat; -- } -- } -- DEBUG(MTD_DEBUG_LEVEL2,"NFTL write request completed OK\n"); --#else -- res = 0; /* Writes always fail */ --#endif /* CONFIG_NFTL_RW */ -- up(&nftl->mutex); -- goto repeat; -- } else { -- DEBUG(MTD_DEBUG_LEVEL0, "NFTL unknown request\n"); -- up(&nftl->mutex); -- res = 0; -- goto repeat; -- } -- repeat: -- DEBUG(MTD_DEBUG_LEVEL3, "end_request(%d)\n", res); -- spin_lock_irq(&io_request_lock); -- end_request(res); -- } --} -- --static int nftl_open(struct inode *ip, struct file *fp) --{ -- int nftlnum = MINOR(ip->i_rdev) >> NFTL_PARTN_BITS; -- struct NFTLrecord *thisNFTL; -- thisNFTL = NFTLs[nftlnum]; -- -- DEBUG(MTD_DEBUG_LEVEL2,"NFTL_open\n"); -- --#ifdef CONFIG_KMOD -- if (!thisNFTL && nftlnum == 0) { -- request_module("docprobe"); -- thisNFTL = NFTLs[nftlnum]; -- } --#endif -- if (!thisNFTL) { -- DEBUG(MTD_DEBUG_LEVEL2,"ENODEV: thisNFTL = %d, minor = %d, ip = %p, fp = %p\n", -- nftlnum, ip->i_rdev, ip, fp); -- return -ENODEV; -- } -- --#ifndef CONFIG_NFTL_RW -- if (fp->f_mode & FMODE_WRITE) -- return -EROFS; --#endif /* !CONFIG_NFTL_RW */ -- -- thisNFTL->usecount++; -- BLK_INC_USE_COUNT; -- if (!get_mtd_device(thisNFTL->mtd, -1)) { -- BLK_DEC_USE_COUNT; -- return -ENXIO; -- } -- -- return 0; --} -- --static int nftl_release(struct inode *inode, struct file *fp) -+static int nftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) - { -- struct NFTLrecord *thisNFTL; -- -- thisNFTL = NFTLs[MINOR(inode->i_rdev) / 16]; -- -- DEBUG(MTD_DEBUG_LEVEL2, "NFTL_release\n"); -- -- if (thisNFTL->mtd->sync) -- thisNFTL->mtd->sync(thisNFTL->mtd); -- thisNFTL->usecount--; -- BLK_DEC_USE_COUNT; -+ struct NFTLrecord *nftl = (void *)dev; - -- put_mtd_device(thisNFTL->mtd); -+ geo->heads = nftl->heads; -+ geo->sectors = nftl->sectors; -+ geo->cylinders = nftl->cylinders; - - return 0; - } --#if LINUX_VERSION_CODE < 0x20326 --static struct file_operations nftl_fops = { -- read: block_read, -- write: block_write, -- ioctl: nftl_ioctl, -- open: nftl_open, -- release: nftl_release, -- fsync: block_fsync, --}; --#else --static struct block_device_operations nftl_fops = --{ --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14) -- owner: THIS_MODULE, --#endif -- open: nftl_open, -- release: nftl_release, -- ioctl: nftl_ioctl --}; --#endif -- -- - - /**************************************************************************** - * -@@ -1048,49 +716,33 @@ - * - ****************************************************************************/ - --static struct mtd_notifier nftl_notifier = { -- add: NFTL_notify_add, -- remove: NFTL_notify_remove -+ -+struct mtd_blktrans_ops nftl_tr = { -+ .name = "nftl", -+ .major = NFTL_MAJOR, -+ .part_bits = NFTL_PARTN_BITS, -+ .getgeo = nftl_getgeo, -+ .readsect = nftl_readblock, -+#ifdef CONFIG_NFTL_RW -+ .writesect = nftl_writeblock, -+#endif -+ .add_mtd = nftl_add_mtd, -+ .remove_dev = nftl_remove_dev, -+ .owner = THIS_MODULE, - }; - - extern char nftlmountrev[]; - - int __init init_nftl(void) - { -- int i; -- --#ifdef PRERELEASE -- printk(KERN_INFO "NFTL driver: nftlcore.c $Revision$, nftlmount.c %s\n", nftlmountrev); --#endif -- -- if (register_blkdev(MAJOR_NR, "nftl", &nftl_fops)){ -- printk("unable to register NFTL block device on major %d\n", MAJOR_NR); -- return -EBUSY; -- } else { -- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &nftl_request); -+ printk(KERN_INFO "NFTL driver: nftlcore.c $Revision$, nftlmount.c %s\n", nftlmountrev); - -- /* set block size to 1kB each */ -- for (i = 0; i < 256; i++) { -- nftl_blocksizes[i] = 1024; -- } -- blksize_size[MAJOR_NR] = nftl_blocksizes; -- -- add_gendisk(&nftl_gendisk); -- } -- -- register_mtd_user(&nftl_notifier); -- -- return 0; -+ return register_mtd_blktrans(&nftl_tr); - } - - static void __exit cleanup_nftl(void) - { -- unregister_mtd_user(&nftl_notifier); -- unregister_blkdev(MAJOR_NR, "nftl"); -- -- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); -- -- del_gendisk(&nftl_gendisk); -+ deregister_mtd_blktrans(&nftl_tr); - } - - module_init(init_nftl); -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/nftlmount.c linux/drivers/mtd/nftlmount.c ---- linux-mips-2.4.24-pre2/drivers/mtd/nftlmount.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/nftlmount.c 2004-11-17 18:17:58.899335200 +0100 -@@ -4,7 +4,7 @@ - * Author: Fabrice Bellard (fabrice.bellard@netgem.com) - * Copyright (C) 2000 Netgem S.A. - * -- * $Id$ -+ * $Id$ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -21,26 +21,17 @@ - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - --#define __NO_VERSION__ - #include --#include - #include --#include --#include --#include --#include - #include - #include --#include --#include - #include - #include - #include --#include - - #define SECTORSIZE 512 - --char nftlmountrev[]="$Revision$"; -+char nftlmountrev[]="$Revision$"; - - /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the - * various device information of the NFTL partition and Bad Unit Table. Update -@@ -59,8 +50,8 @@ - - /* Assume logical EraseSize == physical erasesize for starting the scan. - We'll sort it out later if we find a MediaHeader which says otherwise */ -- nftl->EraseSize = nftl->mtd->erasesize; -- nftl->nb_blocks = nftl->mtd->size / nftl->EraseSize; -+ nftl->EraseSize = nftl->mbd.mtd->erasesize; -+ nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize; - - nftl->MediaUnit = BLOCK_NIL; - nftl->SpareMediaUnit = BLOCK_NIL; -@@ -71,12 +62,12 @@ - - /* Check for ANAND header first. Then can whinge if it's found but later - checks fail */ -- if ((ret = MTD_READ(nftl->mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf))) { -+ if ((ret = MTD_READ(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf))) { - static int warncount = 5; - - if (warncount) { - printk(KERN_WARNING "Block read at 0x%x of mtd%d failed: %d\n", -- block * nftl->EraseSize, nftl->mtd->index, ret); -+ block * nftl->EraseSize, nftl->mbd.mtd->index, ret); - if (!--warncount) - printk(KERN_WARNING "Further failures for this block will not be printed\n"); - } -@@ -87,16 +78,16 @@ - /* ANAND\0 not found. Continue */ - #if 0 - printk(KERN_DEBUG "ANAND header not found at 0x%x in mtd%d\n", -- block * nftl->EraseSize, nftl->mtd->index); -+ block * nftl->EraseSize, nftl->mbd.mtd->index); - #endif - continue; - } - - /* To be safer with BIOS, also use erase mark as discriminant */ -- if ((ret = MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, -- 8, &retlen, (char *)&h1)) < 0) { -+ if ((ret = MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, -+ 8, &retlen, (char *)&h1) < 0)) { - printk(KERN_WARNING "ANAND header found at 0x%x in mtd%d, but OOB data read failed (err %d)\n", -- block * nftl->EraseSize, nftl->mtd->index, ret); -+ block * nftl->EraseSize, nftl->mbd.mtd->index, ret); - continue; - } - -@@ -106,23 +97,23 @@ - */ - if (le16_to_cpu(h1.EraseMark | h1.EraseMark1) != ERASE_MARK) { - printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but erase mark not present (0x%04x,0x%04x instead)\n", -- block * nftl->EraseSize, nftl->mtd->index, -+ block * nftl->EraseSize, nftl->mbd.mtd->index, - le16_to_cpu(h1.EraseMark), le16_to_cpu(h1.EraseMark1)); - continue; - } - - /* Finally reread to check ECC */ -- if ((ret = MTD_READECC(nftl->mtd, block * nftl->EraseSize, SECTORSIZE, -- &retlen, buf, (char *)&oob, NAND_ECC_DISKONCHIP)) < 0) { -+ if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, -+ &retlen, buf, (char *)&oob, NAND_ECC_DISKONCHIP) < 0)) { - printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n", -- block * nftl->EraseSize, nftl->mtd->index, ret); -+ block * nftl->EraseSize, nftl->mbd.mtd->index, ret); - continue; - } - - /* Paranoia. Check the ANAND header is still there after the ECC read */ - if (memcmp(buf, "ANAND", 6)) { - printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but went away on reread!\n", -- block * nftl->EraseSize, nftl->mtd->index); -+ block * nftl->EraseSize, nftl->mbd.mtd->index); - printk(KERN_NOTICE "New data are: %02x %02x %02x %02x %02x %02x\n", - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); - continue; -@@ -137,8 +128,12 @@ - printk(KERN_NOTICE "NFTL Media Headers at 0x%x and 0x%x disagree.\n", - nftl->MediaUnit * nftl->EraseSize, block * nftl->EraseSize); - /* if (debug) Print both side by side */ -+ if (boot_record_count < 2) { -+ /* We haven't yet seen two real ones */ - return -1; - } -+ continue; -+ } - if (boot_record_count == 1) - nftl->SpareMediaUnit = block; - -@@ -163,8 +158,8 @@ - } else if (mh->UnitSizeFactor != 0xff) { - printk(KERN_NOTICE "WARNING: Support for NFTL with UnitSizeFactor 0x%02x is experimental\n", - mh->UnitSizeFactor); -- nftl->EraseSize = nftl->mtd->erasesize << (0xff - mh->UnitSizeFactor); -- nftl->nb_blocks = nftl->mtd->size / nftl->EraseSize; -+ nftl->EraseSize = nftl->mbd.mtd->erasesize << (0xff - mh->UnitSizeFactor); -+ nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize; - } - nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN); - if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) { -@@ -182,7 +177,7 @@ - return -1; - } - -- nftl->nr_sects = nftl->numvunits * (nftl->EraseSize / SECTORSIZE); -+ nftl->mbd.size = nftl->numvunits * (nftl->EraseSize / SECTORSIZE); - - /* If we're not using the last sectors in the device for some reason, - reduce nb_blocks accordingly so we forget they're there */ -@@ -220,7 +215,7 @@ - for (i = 0; i < nftl->nb_blocks; i++) { - if ((i & (SECTORSIZE - 1)) == 0) { - /* read one sector for every SECTORSIZE of blocks */ -- if ((ret = MTD_READECC(nftl->mtd, block * nftl->EraseSize + -+ if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize + - i + SECTORSIZE, SECTORSIZE, &retlen, buf, - (char *)&oob, NAND_ECC_DISKONCHIP)) < 0) { - printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n", -@@ -263,16 +258,16 @@ - for (i = 0; i < len; i += SECTORSIZE) { - /* we want to read the sector without ECC check here since a free - sector does not have ECC syndrome on it yet */ -- if (MTD_READ(nftl->mtd, address, SECTORSIZE, &retlen, buf) < 0) -+ if (MTD_READ(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf) < 0) - return -1; - if (memcmpb(buf, 0xff, SECTORSIZE) != 0) - return -1; - - if (check_oob) { -- if (MTD_READOOB(nftl->mtd, address, nftl->mtd->oobsize, -+ if (MTD_READOOB(nftl->mbd.mtd, address, nftl->mbd.mtd->oobsize, - &retlen, buf) < 0) - return -1; -- if (memcmpb(buf, 0xff, nftl->mtd->oobsize) != 0) -+ if (memcmpb(buf, 0xff, nftl->mbd.mtd->oobsize) != 0) - return -1; - } - address += SECTORSIZE; -@@ -297,7 +292,7 @@ - struct erase_info *instr = &nftl->instr; - - /* Read the Unit Control Information #1 for Wear-Leveling */ -- if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, -+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, - 8, &retlen, (char *)&uci) < 0) - goto default_uci1; - -@@ -314,7 +309,7 @@ - /* XXX: use async erase interface, XXX: test return code */ - instr->addr = block * nftl->EraseSize; - instr->len = nftl->EraseSize; -- MTD_ERASE(nftl->mtd, instr); -+ MTD_ERASE(nftl->mbd.mtd, instr); - - if (instr->state == MTD_ERASE_FAILED) { - /* could not format, FixMe: We should update the BadUnitTable -@@ -337,7 +332,7 @@ - return -1; - - uci.WearInfo = le32_to_cpu(nb_erases); -- if (MTD_WRITEOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, -+ if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, - &retlen, (char *)&uci) < 0) - return -1; - return 0; -@@ -363,7 +358,7 @@ - block = first_block; - for (;;) { - for (i = 0; i < sectors_per_block; i++) { -- if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + i * SECTORSIZE, -+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i * SECTORSIZE, - 8, &retlen, (char *)&bci) < 0) - status = SECTOR_IGNORE; - else -@@ -383,7 +378,7 @@ - /* sector not free actually : mark it as SECTOR_IGNORE */ - bci.Status = SECTOR_IGNORE; - bci.Status1 = SECTOR_IGNORE; -- MTD_WRITEOOB(nftl->mtd, -+ MTD_WRITEOOB(nftl->mbd.mtd, - block * nftl->EraseSize + i * SECTORSIZE, - 8, &retlen, (char *)&bci); - } -@@ -476,7 +471,7 @@ - size_t retlen; - - /* check erase mark. */ -- if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, -+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, - &retlen, (char *)&h1) < 0) - return -1; - -@@ -491,7 +486,7 @@ - h1.EraseMark = cpu_to_le16(ERASE_MARK); - h1.EraseMark1 = cpu_to_le16(ERASE_MARK); - h1.WearInfo = cpu_to_le32(0); -- if (MTD_WRITEOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, -+ if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, - &retlen, (char *)&h1) < 0) - return -1; - } else { -@@ -503,7 +498,7 @@ - SECTORSIZE, 0) != 0) - return -1; - -- if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + i, -+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i, - 16, &retlen, buf) < 0) - return -1; - if (i == SECTORSIZE) { -@@ -533,7 +528,7 @@ - struct nftl_uci2 uci; - size_t retlen; - -- if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8, -+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8, - 8, &retlen, (char *)&uci) < 0) - return 0; - -@@ -572,9 +567,9 @@ - - for (;;) { - /* read the block header. If error, we format the chain */ -- if (MTD_READOOB(s->mtd, block * s->EraseSize + 8, 8, -+ if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8, - &retlen, (char *)&h0) < 0 || -- MTD_READOOB(s->mtd, block * s->EraseSize + SECTORSIZE + 8, 8, -+ MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8, - &retlen, (char *)&h1) < 0) { - s->ReplUnitTable[block] = BLOCK_NIL; - do_format_chain = 1; -diff -Nurb linux-mips-2.4.24-pre2/drivers/mtd/redboot.c linux/drivers/mtd/redboot.c ---- linux-mips-2.4.24-pre2/drivers/mtd/redboot.c 2004-11-17 18:04:53.000000000 +0100 -+++ linux/drivers/mtd/redboot.c 2004-11-17 18:17:58.901334896 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Parse RedBoot-style Flash Image System (FIS) tables and - * produce a Linux partition array to match. -@@ -7,6 +7,7 @@ - - #include - #include -+#include - - #include - #include -@@ -34,7 +35,9 @@ - return 1; - } - --int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts) -+static int parse_redboot_partitions(struct mtd_info *master, -+ struct mtd_partition **pparts, -+ unsigned long fis_origin) - { - int nrparts = 0; - struct fis_image_desc *buf; -@@ -43,7 +46,9 @@ - int ret, i; - size_t retlen; - char *names; -+ char *nullname; - int namelen = 0; -+ static char nullstring[] = "unallocated"; - - buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - -@@ -90,7 +95,11 @@ - goto out; - } - new_fl->img = &buf[i]; -+ if (fis_origin) { -+ buf[i].flash_base -= fis_origin; -+ } else { - buf[i].flash_base &= master->size-1; -+ } - - /* I'm sure the JFFS2 code has done me permanent damage. - * I now think the following is _normal_ -@@ -110,18 +119,24 @@ - if (tmp_fl->img->flash_base + tmp_fl->img->size + master->erasesize < tmp_fl->next->img->flash_base) - nrparts++; - } -- parts = kmalloc(sizeof(*parts)*nrparts + namelen, GFP_KERNEL); -+ parts = kmalloc(sizeof(*parts)*nrparts + sizeof(nullstring) + namelen, GFP_KERNEL); - - if (!parts) { - ret = -ENOMEM; - goto out; - } -- names = (char *)&parts[nrparts]; -+ - memset(parts, 0, sizeof(*parts)*nrparts + namelen); -+ -+ /* FIXME: Include nullname only if it's used */ -+ nullname = (char *)&parts[nrparts]; -+ sprintf(nullname, nullstring); -+ names = nullname + sizeof(nullstring); -+ - i=0; - - if (fl->img->flash_base) { -- parts[0].name = "unallocated space"; -+ parts[0].name = nullname; - parts[0].size = fl->img->flash_base; - parts[0].offset = 0; - } -@@ -133,11 +148,11 @@ - strcpy(names, fl->img->name); - names += strlen(names)+1; - -- if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize < fl->next->img->flash_base) { -+ if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) { - i++; - parts[i].offset = parts[i-1].size + parts[i-1].offset; - parts[i].size = fl->next->img->flash_base - parts[i].offset; -- parts[i].name = "unallocated space"; -+ parts[i].name = nullname; - } - tmp_fl = fl; - fl = fl->next; -@@ -155,7 +170,24 @@ - return ret; - } - --EXPORT_SYMBOL(parse_redboot_partitions); -+static struct mtd_part_parser redboot_parser = { -+ .owner = THIS_MODULE, -+ .parse_fn = parse_redboot_partitions, -+ .name = "RedBoot", -+}; -+ -+static int __init redboot_parser_init(void) -+{ -+ return register_mtd_parser(&redboot_parser); -+} -+ -+static void __exit redboot_parser_exit(void) -+{ -+ deregister_mtd_parser(&redboot_parser); -+} -+ -+module_init(redboot_parser_init); -+module_exit(redboot_parser_exit); - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Red Hat, Inc. - David Woodhouse "); -diff -Nurb linux-mips-2.4.24-pre2/fs/Config.in linux/fs/Config.in ---- linux-mips-2.4.24-pre2/fs/Config.in 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/Config.in 2004-11-17 18:17:59.489245520 +0100 -@@ -49,6 +49,7 @@ - dep_tristate 'Journalling Flash File System v2 (JFFS2) support' CONFIG_JFFS2_FS $CONFIG_MTD - if [ "$CONFIG_JFFS2_FS" = "y" -o "$CONFIG_JFFS2_FS" = "m" ] ; then - int 'JFFS2 debugging verbosity (0 = quiet, 2 = noisy)' CONFIG_JFFS2_FS_DEBUG 0 -+ bool 'JFFS2 support for NAND chips' CONFIG_JFFS2_FS_NAND - fi - tristate 'Compressed ROM file system support' CONFIG_CRAMFS - bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/Makefile linux/fs/jffs2/Makefile ---- linux-mips-2.4.24-pre2/fs/jffs2/Makefile 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/Makefile 2004-11-17 18:17:59.000000000 +0100 -@@ -1,7 +1,7 @@ - # - # Makefile for the linux Journalling Flash FileSystem (JFFS) routines. - # --# $Id$ -+# $Id$ - # - # Note! Dependencies are done automagically by 'make dep', which also - # removes any old dependencies. DON'T put your own dependencies here -@@ -10,16 +10,31 @@ - # Note 2! The CFLAGS definitions are now in the main makefile... - - --COMPR_OBJS := compr.o compr_rubin.o compr_rtime.o pushpull.o \ -- compr_zlib.o -+obj-$(CONFIG_JFFS2_FS) := jffs2.o -+ -+COMPR_OBJS := compr.o compr_rubin.o compr_rtime.o compr_zlib.o - JFFS2_OBJS := dir.o file.o ioctl.o nodelist.o malloc.o \ -- read.o nodemgmt.o readinode.o super.o write.o scan.o gc.o \ -- symlink.o build.o erase.o background.o -+ read.o nodemgmt.o readinode.o write.o scan.o gc.o \ -+ symlink.o build.o erase.o background.o fs.o writev.o - --O_TARGET := jffs2.o -+BELOW25 := $(shell echo $(PATCHLEVEL) | sed s/[1234]/y/) -+ -+ifeq ($(BELOW25),y) -+LINUX_OBJS := super-v24.o crc32.o rbtree.o -+else -+LINUX_OBJS := super.o -+endif - --obj-y := $(COMPR_OBJS) $(JFFS2_OBJS) --obj-m := $(O_TARGET) -+NAND_OBJS-$(CONFIG_JFFS2_FS_NAND) := wbuf.o - -+jffs2-objs := $(COMPR_OBJS) $(JFFS2_OBJS) $(VERS_OBJS) $(NAND_OBJS-y) \ -+ $(LINUX_OBJS) -+ -+ -+# 2.4 build compatibility -+ifeq ($(BELOW25),y) -+obj-y := $(jffs2-objs) -+O_TARGET := jffs2.o - include $(TOPDIR)/Rules.make -+endif - -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/background.c linux/fs/jffs2/background.c ---- linux-mips-2.4.24-pre2/fs/jffs2/background.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/background.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,61 +1,36 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #define __KERNEL_SYSCALLS__ - - #include --#include --#include - #include - #include --#include - #include -+#include -+#include -+#include - #include "nodelist.h" - - - static int jffs2_garbage_collect_thread(void *); --static int thread_should_wake(struct jffs2_sb_info *c); - - void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c) - { -- spin_lock_bh(&c->erase_completion_lock); -- if (c->gc_task && thread_should_wake(c)) -+ spin_lock(&c->erase_completion_lock); -+ if (c->gc_task && jffs2_thread_should_wake(c)) - send_sig(SIGHUP, c->gc_task, 1); -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - } - - /* This must only ever be called when no GC thread is currently running */ -@@ -86,12 +61,12 @@ - - void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c) - { -- spin_lock_bh(&c->erase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - if (c->gc_task) { - D1(printk(KERN_DEBUG "jffs2: Killing GC task %d\n", c->gc_task->pid)); - send_sig(SIGKILL, c->gc_task, 1); - } -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - wait_for_completion(&c->gc_thread_exit); - } - -@@ -99,34 +74,37 @@ - { - struct jffs2_sb_info *c = _c; - -- daemonize(); -- current->tty = NULL; -+ daemonize("jffs2_gcd_mtd%d", c->mtd->index); -+ allow_signal(SIGKILL); -+ allow_signal(SIGSTOP); -+ allow_signal(SIGCONT); -+ - c->gc_task = current; - up(&c->gc_thread_start); - -- sprintf(current->comm, "jffs2_gcd_mtd%d", c->mtd->index); -- -- /* FIXME in the 2.2 backport */ -- current->nice = 10; -+ set_user_nice(current, 10); - - for (;;) { -- spin_lock_irq(¤t->sigmask_lock); -- siginitsetinv (¤t->blocked, sigmask(SIGHUP) | sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT)); -- recalc_sigpending(current); -- spin_unlock_irq(¤t->sigmask_lock); -+ allow_signal(SIGHUP); - -- if (!thread_should_wake(c)) { -+ if (!jffs2_thread_should_wake(c)) { - set_current_state (TASK_INTERRUPTIBLE); - D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n")); -- /* Yes, there's a race here; we checked thread_should_wake() before -- setting current->state to TASK_INTERRUPTIBLE. But it doesn't -+ /* Yes, there's a race here; we checked jffs2_thread_should_wake() -+ before setting current->state to TASK_INTERRUPTIBLE. But it doesn't - matter - We don't care if we miss a wakeup, because the GC thread - is only an optimisation anyway. */ - schedule(); - } - -- if (current->need_resched) -- schedule(); -+ if (current->flags & PF_FREEZE) { -+ refrigerator(0); -+ /* refrigerator() should recalc sigpending for us -+ but doesn't. No matter - allow_signal() will. */ -+ continue; -+ } -+ -+ cond_resched(); - - /* Put_super will send a SIGKILL and then wait on the sem. - */ -@@ -134,9 +112,7 @@ - siginfo_t info; - unsigned long signr; - -- spin_lock_irq(¤t->sigmask_lock); -- signr = dequeue_signal(¤t->blocked, &info); -- spin_unlock_irq(¤t->sigmask_lock); -+ signr = dequeue_signal_lock(current, ¤t->blocked, &info); - - switch(signr) { - case SIGSTOP: -@@ -147,9 +123,10 @@ - - case SIGKILL: - D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGKILL received.\n")); -- spin_lock_bh(&c->erase_completion_lock); -+ die: -+ spin_lock(&c->erase_completion_lock); - c->gc_task = NULL; -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - complete_and_exit(&c->gc_thread_exit, 0); - - case SIGHUP: -@@ -157,27 +134,15 @@ - break; - default: - D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): signal %ld received\n", signr)); -- - } - } - /* We don't want SIGHUP to interrupt us. STOP and KILL are OK though. */ -- spin_lock_irq(¤t->sigmask_lock); -- siginitsetinv (¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT)); -- recalc_sigpending(current); -- spin_unlock_irq(¤t->sigmask_lock); -+ disallow_signal(SIGHUP); - - D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): pass\n")); -- jffs2_garbage_collect_pass(c); -+ if (jffs2_garbage_collect_pass(c) == -ENOSPC) { -+ printk(KERN_NOTICE "No space for garbage collection. Aborting GC thread\n"); -+ goto die; -+ } - } --} -- --static int thread_should_wake(struct jffs2_sb_info *c) --{ -- D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x\n", -- c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size)); -- if (c->nr_free_blocks + c->nr_erasing_blocks < JFFS2_RESERVED_BLOCKS_GCTRIGGER && -- c->dirty_size > c->sector_size) -- return 1; -- else -- return 0; - } -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/build.c linux/fs/jffs2/build.c ---- linux-mips-2.4.24-pre2/fs/jffs2/build.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/build.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,47 +1,22 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include --#include -+#include - #include - #include "nodelist.h" - --int jffs2_build_inode_pass1(struct jffs2_sb_info *, struct jffs2_inode_cache *); --int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, struct jffs2_inode_cache *); -+static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, struct jffs2_inode_cache *, struct jffs2_full_dirent **); - - static inline struct jffs2_inode_cache * - first_inode_chain(int *i, struct jffs2_sb_info *c) -@@ -68,16 +43,52 @@ - ic; \ - ic = next_inode(&i, ic, (c))) - -+ -+static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) -+{ -+ struct jffs2_full_dirent *fd; -+ -+ D1(printk(KERN_DEBUG "jffs2_build_inode building directory inode #%u\n", ic->ino)); -+ -+ /* For each child, increase nlink */ -+ for(fd = ic->scan_dents; fd; fd = fd->next) { -+ struct jffs2_inode_cache *child_ic; -+ if (!fd->ino) -+ continue; -+ -+ /* XXX: Can get high latency here with huge directories */ -+ -+ child_ic = jffs2_get_ino_cache(c, fd->ino); -+ if (!child_ic) { -+ printk(KERN_NOTICE "Eep. Child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n", -+ fd->name, fd->ino, ic->ino); -+ continue; -+ } -+ -+ if (child_ic->nlink++ && fd->type == DT_DIR) { -+ printk(KERN_NOTICE "Child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", fd->name, fd->ino, ic->ino); -+ if (fd->ino == 1 && ic->ino == 1) { -+ printk(KERN_NOTICE "This is mostly harmless, and probably caused by creating a JFFS2 image\n"); -+ printk(KERN_NOTICE "using a buggy version of mkfs.jffs2. Use at least v1.17.\n"); -+ } -+ /* What do we do about it? */ -+ } -+ D1(printk(KERN_DEBUG "Increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino)); -+ /* Can't free them. We might need them in pass 2 */ -+ } -+} -+ - /* Scan plan: - - Scan physical nodes. Build map of inodes/dirents. Allocate inocaches as we go - - Scan directory tree from top down, setting nlink in inocaches - - Scan inocaches for inodes with nlink==0 - */ --int jffs2_build_filesystem(struct jffs2_sb_info *c) -+static int jffs2_build_filesystem(struct jffs2_sb_info *c) - { - int ret; - int i; - struct jffs2_inode_cache *ic; -+ struct jffs2_full_dirent *dead_fds = NULL; - - /* First, scan the medium and build all the inode caches with - lists of physical nodes */ -@@ -90,14 +101,17 @@ - return ret; - - D1(printk(KERN_DEBUG "Scanned flash completely\n")); -- /* Now build the data map for each inode, marking obsoleted nodes -- as such, and also increase nlink of any children. */ -+ D1(jffs2_dump_block_lists(c)); -+ -+ /* Now scan the directory tree, increasing nlink according to every dirent found. */ - for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 1: ino #%u\n", ic->ino)); -- ret = jffs2_build_inode_pass1(c, ic); -- if (ret) { -- D1(printk(KERN_WARNING "Eep. jffs2_build_inode_pass1 for ino %d returned %d\n", ic->ino, ret)); -- return ret; -+ -+ D1(BUG_ON(ic->ino > c->highest_ino)); -+ -+ if (ic->scan_dents) { -+ jffs2_build_inode_pass1(c, ic); -+ cond_resched(); - } - } - D1(printk(KERN_DEBUG "Pass 1 complete\n")); -@@ -107,181 +121,226 @@ - children too, and repeat the scan. As that's going to be - a fairly uncommon occurrence, it's not so evil to do it this - way. Recursion bad. */ -- do { -- D1(printk(KERN_DEBUG "Pass 2 (re)starting\n")); -- ret = 0; -+ D1(printk(KERN_DEBUG "Pass 2 starting\n")); -+ - for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 2: ino #%u, nlink %d, ic %p, nodes %p\n", ic->ino, ic->nlink, ic, ic->nodes)); - if (ic->nlink) - continue; - -- ret = jffs2_build_remove_unlinked_inode(c, ic); -- if (ret) -- break; -- /* -EAGAIN means the inode's nlink was zero, so we deleted it, -- and furthermore that it had children and their nlink has now -- gone to zero too. So we have to restart the scan. */ -+ jffs2_build_remove_unlinked_inode(c, ic, &dead_fds); -+ cond_resched(); -+ } -+ -+ D1(printk(KERN_DEBUG "Pass 2a starting\n")); -+ -+ while (dead_fds) { -+ struct jffs2_inode_cache *ic; -+ struct jffs2_full_dirent *fd = dead_fds; -+ -+ dead_fds = fd->next; -+ -+ ic = jffs2_get_ino_cache(c, fd->ino); -+ D1(printk(KERN_DEBUG "Removing dead_fd ino #%u (\"%s\"), ic at %p\n", fd->ino, fd->name, ic)); -+ -+ if (ic) -+ jffs2_build_remove_unlinked_inode(c, ic, &dead_fds); -+ jffs2_free_full_dirent(fd); - } -- } while(ret == -EAGAIN); - - D1(printk(KERN_DEBUG "Pass 2 complete\n")); - -- /* Finally, we can scan again and free the dirent nodes and scan_info structs */ -+ /* Finally, we can scan again and free the dirent structs */ - for_each_inode(i, c, ic) { -- struct jffs2_scan_info *scan = ic->scan; - struct jffs2_full_dirent *fd; - D1(printk(KERN_DEBUG "Pass 3: ino #%u, ic %p, nodes %p\n", ic->ino, ic, ic->nodes)); -- if (!scan) { -- if (ic->nlink) { -- D1(printk(KERN_WARNING "Why no scan struct for ino #%u which has nlink %d?\n", ic->ino, ic->nlink)); -- } -- continue; -- } -- ic->scan = NULL; -- while(scan->dents) { -- fd = scan->dents; -- scan->dents = fd->next; -+ -+ while(ic->scan_dents) { -+ fd = ic->scan_dents; -+ ic->scan_dents = fd->next; - jffs2_free_full_dirent(fd); - } -- kfree(scan); -+ ic->scan_dents = NULL; -+ cond_resched(); - } - D1(printk(KERN_DEBUG "Pass 3 complete\n")); -+ D1(jffs2_dump_block_lists(c)); -+ -+ /* Rotate the lists by some number to ensure wear levelling */ -+ jffs2_rotate_lists(c); - - return ret; - } - --int jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) -+static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, struct jffs2_full_dirent **dead_fds) - { -- struct jffs2_tmp_dnode_info *tn; -+ struct jffs2_raw_node_ref *raw; - struct jffs2_full_dirent *fd; -- struct jffs2_node_frag *fraglist = NULL; -- struct jffs2_tmp_dnode_info *metadata = NULL; -- -- D1(printk(KERN_DEBUG "jffs2_build_inode building inode #%u\n", ic->ino)); -- if (ic->ino > c->highest_ino) -- c->highest_ino = ic->ino; - -- if (!ic->scan->tmpnodes && ic->ino != 1) { -- D1(printk(KERN_DEBUG "jffs2_build_inode: ino #%u has no data nodes!\n", ic->ino)); -- } -- /* Build the list to make sure any obsolete nodes are marked as such */ -- while(ic->scan->tmpnodes) { -- tn = ic->scan->tmpnodes; -- ic->scan->tmpnodes = tn->next; -- -- if (metadata && tn->version > metadata->version) { -- D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 ignoring old metadata at 0x%08x\n", -- metadata->fn->raw->flash_offset &~3)); -+ D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino)); - -- jffs2_free_full_dnode(metadata->fn); -- jffs2_free_tmp_dnode_info(metadata); -- metadata = NULL; -+ for (raw = ic->nodes; raw != (void *)ic; raw = raw->next_in_ino) { -+ D1(printk(KERN_DEBUG "obsoleting node at 0x%08x\n", ref_offset(raw))); -+ jffs2_mark_node_obsolete(c, raw); - } - -- if (tn->fn->size) { -- jffs2_add_full_dnode_to_fraglist (c, &fraglist, tn->fn); -- jffs2_free_tmp_dnode_info(tn); -- } else { -- if (!metadata) { -- metadata = tn; -- } else { -- D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 ignoring new metadata at 0x%08x\n", -- tn->fn->raw->flash_offset &~3)); -- -- jffs2_free_full_dnode(tn->fn); -- jffs2_free_tmp_dnode_info(tn); -- } -- } -- } -+ if (ic->scan_dents) { -+ int whinged = 0; -+ D1(printk(KERN_DEBUG "Inode #%u was a directory which may have children...\n", ic->ino)); - -- /* OK. Now clear up */ -- if (metadata) { -- jffs2_free_full_dnode(metadata->fn); -- jffs2_free_tmp_dnode_info(metadata); -- } -- metadata = NULL; -+ while(ic->scan_dents) { -+ struct jffs2_inode_cache *child_ic; - -- while (fraglist) { -- struct jffs2_node_frag *frag; -- frag = fraglist; -- fraglist = fraglist->next; -+ fd = ic->scan_dents; -+ ic->scan_dents = fd->next; - -- if (frag->node && !(--frag->node->frags)) { -- jffs2_free_full_dnode(frag->node); -+ if (!fd->ino) { -+ /* It's a deletion dirent. Ignore it */ -+ D1(printk(KERN_DEBUG "Child \"%s\" is a deletion dirent, skipping...\n", fd->name)); -+ jffs2_free_full_dirent(fd); -+ continue; - } -- jffs2_free_node_frag(frag); -+ if (!whinged) { -+ whinged = 1; -+ printk(KERN_NOTICE "Inode #%u was a directory with children - removing those too...\n", ic->ino); - } - -- /* Now for each child, increase nlink */ -- for(fd=ic->scan->dents; fd; fd = fd->next) { -- struct jffs2_inode_cache *child_ic; -- if (!fd->ino) -- continue; -+ D1(printk(KERN_DEBUG "Removing child \"%s\", ino #%u\n", -+ fd->name, fd->ino)); - - child_ic = jffs2_get_ino_cache(c, fd->ino); - if (!child_ic) { -- printk(KERN_NOTICE "Eep. Child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n", -- fd->name, fd->ino, ic->ino); -+ printk(KERN_NOTICE "Cannot remove child \"%s\", ino #%u, because it doesn't exist\n", fd->name, fd->ino); -+ jffs2_free_full_dirent(fd); - continue; - } - -- if (child_ic->nlink++ && fd->type == DT_DIR) { -- printk(KERN_NOTICE "Child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", fd->name, fd->ino, ic->ino); -- if (fd->ino == 1 && ic->ino == 1) { -- printk(KERN_NOTICE "This is mostly harmless, and probably caused by creating a JFFS2 image\n"); -- printk(KERN_NOTICE "using a buggy version of mkfs.jffs2. Use at least v1.17.\n"); -+ /* Reduce nlink of the child. If it's now zero, stick it on the -+ dead_fds list to be cleaned up later. Else just free the fd */ -+ -+ child_ic->nlink--; -+ -+ if (!child_ic->nlink) { -+ D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got zero nlink. Adding to dead_fds list.\n", -+ fd->ino, fd->name)); -+ fd->next = *dead_fds; -+ *dead_fds = fd; -+ } else { -+ D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got nlink %d. Ignoring.\n", -+ fd->ino, fd->name, child_ic->nlink)); -+ jffs2_free_full_dirent(fd); - } -- /* What do we do about it? */ - } -- D1(printk(KERN_DEBUG "Increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino)); -- /* Can't free them. We might need them in pass 2 */ - } -- return 0; -+ -+ /* -+ We don't delete the inocache from the hash list and free it yet. -+ The erase code will do that, when all the nodes are completely gone. -+ */ - } - --int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) -+static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) - { -- struct jffs2_raw_node_ref *raw; -- struct jffs2_full_dirent *fd; -- int ret = 0; -+ uint32_t size; - -- if(!ic->scan) { -- D1(printk(KERN_DEBUG "ino #%u was already removed\n", ic->ino)); -- return 0; -- } -+ /* Deletion should almost _always_ be allowed. We're fairly -+ buggered once we stop allowing people to delete stuff -+ because there's not enough free space... */ -+ c->resv_blocks_deletion = 2; -+ -+ /* Be conservative about how much space we need before we allow writes. -+ On top of that which is required for deletia, require an extra 2% -+ of the medium to be available, for overhead caused by nodes being -+ split across blocks, etc. */ -+ -+ size = c->flash_size / 50; /* 2% of flash size */ -+ size += c->nr_blocks * 100; /* And 100 bytes per eraseblock */ -+ size += c->sector_size - 1; /* ... and round up */ -+ -+ c->resv_blocks_write = c->resv_blocks_deletion + (size / c->sector_size); -+ -+ /* When do we let the GC thread run in the background */ -+ -+ c->resv_blocks_gctrigger = c->resv_blocks_write + 1; -+ -+ /* When do we allow garbage collection to merge nodes to make -+ long-term progress at the expense of short-term space exhaustion? */ -+ c->resv_blocks_gcmerge = c->resv_blocks_deletion + 1; -+ -+ /* When do we allow garbage collection to eat from bad blocks rather -+ than actually making progress? */ -+ c->resv_blocks_gcbad = 0;//c->resv_blocks_deletion + 2; -+ -+ /* If there's less than this amount of dirty space, don't bother -+ trying to GC to make more space. It'll be a fruitless task */ -+ c->nospc_dirty_size = c->sector_size + (c->flash_size / 100); -+ -+ D1(printk(KERN_DEBUG "JFFS2 trigger levels (size %d KiB, block size %d KiB, %d blocks)\n", -+ c->flash_size / 1024, c->sector_size / 1024, c->nr_blocks)); -+ D1(printk(KERN_DEBUG "Blocks required to allow deletion: %d (%d KiB)\n", -+ c->resv_blocks_deletion, c->resv_blocks_deletion*c->sector_size/1024)); -+ D1(printk(KERN_DEBUG "Blocks required to allow writes: %d (%d KiB)\n", -+ c->resv_blocks_write, c->resv_blocks_write*c->sector_size/1024)); -+ D1(printk(KERN_DEBUG "Blocks required to quiesce GC thread: %d (%d KiB)\n", -+ c->resv_blocks_gctrigger, c->resv_blocks_gctrigger*c->sector_size/1024)); -+ D1(printk(KERN_DEBUG "Blocks required to allow GC merges: %d (%d KiB)\n", -+ c->resv_blocks_gcmerge, c->resv_blocks_gcmerge*c->sector_size/1024)); -+ D1(printk(KERN_DEBUG "Blocks required to GC bad blocks: %d (%d KiB)\n", -+ c->resv_blocks_gcbad, c->resv_blocks_gcbad*c->sector_size/1024)); -+ D1(printk(KERN_DEBUG "Amount of dirty space required to GC: %d bytes\n", -+ c->nospc_dirty_size)); -+} - -- D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino)); -+int jffs2_do_mount_fs(struct jffs2_sb_info *c) -+{ -+ int i; - -- for (raw = ic->nodes; raw != (void *)ic; raw = raw->next_in_ino) { -- D1(printk(KERN_DEBUG "obsoleting node at 0x%08x\n", raw->flash_offset&~3)); -- jffs2_mark_node_obsolete(c, raw); -+ c->free_size = c->flash_size; -+ c->nr_blocks = c->flash_size / c->sector_size; -+ c->blocks = kmalloc(sizeof(struct jffs2_eraseblock) * c->nr_blocks, GFP_KERNEL); -+ if (!c->blocks) -+ return -ENOMEM; -+ for (i=0; inr_blocks; i++) { -+ INIT_LIST_HEAD(&c->blocks[i].list); -+ c->blocks[i].offset = i * c->sector_size; -+ c->blocks[i].free_size = c->sector_size; -+ c->blocks[i].dirty_size = 0; -+ c->blocks[i].wasted_size = 0; -+ c->blocks[i].unchecked_size = 0; -+ c->blocks[i].used_size = 0; -+ c->blocks[i].first_node = NULL; -+ c->blocks[i].last_node = NULL; -+ } -+ -+ init_MUTEX(&c->alloc_sem); -+ init_MUTEX(&c->erase_free_sem); -+ init_waitqueue_head(&c->erase_wait); -+ init_waitqueue_head(&c->inocache_wq); -+ spin_lock_init(&c->erase_completion_lock); -+ spin_lock_init(&c->inocache_lock); -+ -+ INIT_LIST_HEAD(&c->clean_list); -+ INIT_LIST_HEAD(&c->very_dirty_list); -+ INIT_LIST_HEAD(&c->dirty_list); -+ INIT_LIST_HEAD(&c->erasable_list); -+ INIT_LIST_HEAD(&c->erasing_list); -+ INIT_LIST_HEAD(&c->erase_pending_list); -+ INIT_LIST_HEAD(&c->erasable_pending_wbuf_list); -+ INIT_LIST_HEAD(&c->erase_complete_list); -+ INIT_LIST_HEAD(&c->free_list); -+ INIT_LIST_HEAD(&c->bad_list); -+ INIT_LIST_HEAD(&c->bad_used_list); -+ c->highest_ino = 1; -+ -+ if (jffs2_build_filesystem(c)) { -+ D1(printk(KERN_DEBUG "build_fs failed\n")); -+ jffs2_free_ino_caches(c); -+ jffs2_free_raw_node_refs(c); -+ kfree(c->blocks); -+ return -EIO; - } - -- if (ic->scan->dents) { -- printk(KERN_NOTICE "Inode #%u was a directory with children - removing those too...\n", ic->ino); -- -- while(ic->scan->dents) { -- struct jffs2_inode_cache *child_ic; -+ jffs2_calc_trigger_levels(c); - -- fd = ic->scan->dents; -- ic->scan->dents = fd->next; -- -- D1(printk(KERN_DEBUG "Removing child \"%s\", ino #%u\n", -- fd->name, fd->ino)); -- -- child_ic = jffs2_get_ino_cache(c, fd->ino); -- if (!child_ic) { -- printk(KERN_NOTICE "Cannot remove child \"%s\", ino #%u, because it doesn't exist\n", fd->name, fd->ino); -- continue; -- } -- jffs2_free_full_dirent(fd); -- child_ic->nlink--; -- } -- ret = -EAGAIN; -- } -- kfree(ic->scan); -- ic->scan = NULL; -- // jffs2_del_ino_cache(c, ic); -- // jffs2_free_inode_cache(ic); -- return ret; -+ return 0; - } -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/compr.c linux/fs/jffs2/compr.c ---- linux-mips-2.4.24-pre2/fs/jffs2/compr.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/compr.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,59 +1,37 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by Arjan van de Ven - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include - #include --#include - #include -+#include -+#include - #include -+#include "nodelist.h" - --int zlib_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 *sourcelen, __u32 *dstlen); --void zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, __u32 srclen, __u32 destlen); --int rtime_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 *sourcelen, __u32 *dstlen); --void rtime_decompress(unsigned char *data_in, unsigned char *cpage_out, __u32 srclen, __u32 destlen); --int rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 *sourcelen, __u32 *dstlen); --void rubinmips_decompress(unsigned char *data_in, unsigned char *cpage_out, __u32 srclen, __u32 destlen); --int dynrubin_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 *sourcelen, __u32 *dstlen); --void dynrubin_decompress(unsigned char *data_in, unsigned char *cpage_out, __u32 srclen, __u32 destlen); -+int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen); -+void jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, uint32_t srclen, uint32_t destlen); -+int jffs2_rtime_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen); -+void jffs2_rtime_decompress(unsigned char *data_in, unsigned char *cpage_out, uint32_t srclen, uint32_t destlen); -+int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen); -+void jffs2_rubinmips_decompress(unsigned char *data_in, unsigned char *cpage_out, uint32_t srclen, uint32_t destlen); -+int jffs2_dynrubin_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen); -+void jffs2_dynrubin_decompress(unsigned char *data_in, unsigned char *cpage_out, uint32_t srclen, uint32_t destlen); - - - /* jffs2_compress: - * @data: Pointer to uncompressed data -- * @cdata: Pointer to buffer for compressed data -+ * @cdata: Pointer to returned pointer to buffer for compressed data - * @datalen: On entry, holds the amount of data available for compression. - * On exit, expected to hold the amount of data actually compressed. - * @cdatalen: On entry, holds the amount of space available for compressed -@@ -68,47 +46,59 @@ - * jffs2_compress should compress as much as will fit, and should set - * *datalen accordingly to show the amount of data which were compressed. - */ --unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 *datalen, __u32 *cdatalen) -+unsigned char jffs2_compress(unsigned char *data_in, unsigned char **cpage_out, -+ uint32_t *datalen, uint32_t *cdatalen) - { -+#ifdef JFFS2_COMPRESSION - int ret; - -- ret = zlib_compress(data_in, cpage_out, datalen, cdatalen); -+ *cpage_out = kmalloc(*cdatalen, GFP_KERNEL); -+ if (!*cpage_out) { -+ printk(KERN_WARNING "No memory for compressor allocation. Compression failed\n"); -+ goto out; -+ } -+ -+#ifdef JFFS2_USE_ZLIB -+ ret = jffs2_zlib_compress(data_in, *cpage_out, datalen, cdatalen); - if (!ret) { - return JFFS2_COMPR_ZLIB; - } --#if 0 /* Disabled 23/9/1. With zlib it hardly ever gets a look in */ -- ret = dynrubin_compress(data_in, cpage_out, datalen, cdatalen); -+#endif -+#ifdef JFFS2_USE_DYNRUBIN -+ ret = jffs2_dynrubin_compress(data_in, *cpage_out, datalen, cdatalen); - if (!ret) { - return JFFS2_COMPR_DYNRUBIN; - } - #endif --#if 0 /* Disabled 26/2/1. Obsoleted by dynrubin */ -- ret = rubinmips_compress(data_in, cpage_out, datalen, cdatalen); -+#ifdef JFFS2_USE_RUBINMIPS -+ ret = jffs2_rubinmips_compress(data_in, *cpage_out, datalen, cdatalen); - if (!ret) { - return JFFS2_COMPR_RUBINMIPS; - } - #endif -+#ifdef JFFS2_USE_RTIME - /* rtime does manage to recompress already-compressed data */ -- ret = rtime_compress(data_in, cpage_out, datalen, cdatalen); -+ ret = jffs2_rtime_compress(data_in, *cpage_out, datalen, cdatalen); - if (!ret) { - return JFFS2_COMPR_RTIME; - } --#if 0 -- /* We don't need to copy. Let the caller special-case the COMPR_NONE case. */ -- /* If we get here, no compression is going to work */ -- /* But we might want to use the fragmentation part -- Arjan */ -- memcpy(cpage_out,data_in,min(*datalen,*cdatalen)); -- if (*datalen > *cdatalen) -- *datalen = *cdatalen; - #endif -+ kfree(*cpage_out); -+#endif /* Compression */ -+ out: -+ *cpage_out = data_in; -+ *datalen = *cdatalen; - return JFFS2_COMPR_NONE; /* We failed to compress */ -- - } - -+void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig) -+{ -+ if (orig != comprbuf) -+ kfree(comprbuf); -+} - - int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, -- unsigned char *data_out, __u32 cdatalen, __u32 datalen) -+ unsigned char *data_out, uint32_t cdatalen, uint32_t datalen) - { - switch (comprtype) { - case JFFS2_COMPR_NONE: -@@ -119,30 +109,27 @@ - case JFFS2_COMPR_ZERO: - memset(data_out, 0, datalen); - break; -- -+#ifdef JFFS2_USE_ZLIB - case JFFS2_COMPR_ZLIB: -- zlib_decompress(cdata_in, data_out, cdatalen, datalen); -+ jffs2_zlib_decompress(cdata_in, data_out, cdatalen, datalen); - break; -- -+#endif -+#ifdef JFFS2_USE_RTIME - case JFFS2_COMPR_RTIME: -- rtime_decompress(cdata_in, data_out, cdatalen, datalen); -+ jffs2_rtime_decompress(cdata_in, data_out, cdatalen, datalen); - break; -- -- case JFFS2_COMPR_RUBINMIPS: --#if 0 /* Disabled 23/9/1 */ -- rubinmips_decompress(cdata_in, data_out, cdatalen, datalen); --#else -- printk(KERN_WARNING "JFFS2: Rubinmips compression encountered but support not compiled in!\n"); - #endif -+#ifdef JFFS2_USE_RUBINMIPS -+ case JFFS2_COMPR_RUBINMIPS: -+ jffs2_rubinmips_decompress(cdata_in, data_out, cdatalen, datalen); - break; -- case JFFS2_COMPR_DYNRUBIN: --#if 1 /* Phase this one out */ -- dynrubin_decompress(cdata_in, data_out, cdatalen, datalen); --#else -- printk(KERN_WARNING "JFFS2: Dynrubin compression encountered but support not compiled in!\n"); - #endif -- break; -+#ifdef JFFS2_USE_DYNRUBIN -+ case JFFS2_COMPR_DYNRUBIN: - -+ jffs2_dynrubin_decompress(cdata_in, data_out, cdatalen, datalen); -+ break; -+#endif - default: - printk(KERN_NOTICE "Unknown JFFS2 compression type 0x%02x\n", comprtype); - return -EIO; -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/compr_rtime.c linux/fs/jffs2/compr_rtime.c ---- linux-mips-2.4.24-pre2/fs/jffs2/compr_rtime.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/compr_rtime.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,43 +1,19 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by Arjan van de Ven - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - * - * Very simple lz77-ish encoder. - * - * Theory of operation: Both encoder and decoder have a list of "last -- * occurances" for every possible source-value; after sending the -+ * occurrences" for every possible source-value; after sending the - * first source-byte, the second byte indicated the "run" length of - * matches - * -@@ -51,10 +27,10 @@ - #include - - /* _compress returns the compressed size, -1 if bigger */ --int rtime_compress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 *sourcelen, __u32 *dstlen) -+int jffs2_rtime_compress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t *sourcelen, uint32_t *dstlen) - { -- int positions[256]; -+ short positions[256]; - int outpos = 0; - int pos=0; - -@@ -91,10 +67,10 @@ - } - - --void rtime_decompress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 srclen, __u32 destlen) -+void jffs2_rtime_decompress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t srclen, uint32_t destlen) - { -- int positions[256]; -+ short positions[256]; - int outpos = 0; - int pos=0; - -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/compr_rubin.c linux/fs/jffs2/compr_rubin.c ---- linux-mips-2.4.24-pre2/fs/jffs2/compr_rubin.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/compr_rubin.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,37 +1,13 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001, 2002 Red Hat, Inc. - * - * Created by Arjan van de Ven - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - -@@ -43,7 +19,7 @@ - - - --void init_rubin(struct rubin_state *rs, int div, int *bits) -+static void init_rubin(struct rubin_state *rs, int div, int *bits) - { - int c; - -@@ -56,7 +32,7 @@ - } - - --int encode(struct rubin_state *rs, long A, long B, int symbol) -+static int encode(struct rubin_state *rs, long A, long B, int symbol) - { - - long i0, i1; -@@ -91,7 +67,7 @@ - } - - --void end_rubin(struct rubin_state *rs) -+static void end_rubin(struct rubin_state *rs) - { - - int i; -@@ -104,7 +80,7 @@ - } - - --void init_decode(struct rubin_state *rs, int div, int *bits) -+static void init_decode(struct rubin_state *rs, int div, int *bits) - { - init_rubin(rs, div, bits); - -@@ -151,7 +127,7 @@ - rs->rec_q = rec_q; - } - --int decode(struct rubin_state *rs, long A, long B) -+static int decode(struct rubin_state *rs, long A, long B) - { - unsigned long p = rs->p, q = rs->q; - long i0, threshold; -@@ -212,8 +188,8 @@ - - - --int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, -- unsigned char *cpage_out, __u32 *sourcelen, __u32 *dstlen) -+static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, -+ unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen) - { - int outpos = 0; - int pos=0; -@@ -246,20 +222,20 @@ - } - #if 0 - /* _compress returns the compressed size, -1 if bigger */ --int rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 *sourcelen, __u32 *dstlen) -+int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t *sourcelen, uint32_t *dstlen) - { - return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen); - } - #endif --int dynrubin_compress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 *sourcelen, __u32 *dstlen) -+int jffs2_dynrubin_compress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t *sourcelen, uint32_t *dstlen) - { - int bits[8]; - unsigned char histo[256]; - int i; - int ret; -- __u32 mysrclen, mydstlen; -+ uint32_t mysrclen, mydstlen; - - mysrclen = *sourcelen; - mydstlen = *dstlen - 8; -@@ -315,8 +291,8 @@ - return 0; - } - --void rubin_do_decompress(int bit_divider, int *bits, unsigned char *cdata_in, -- unsigned char *page_out, __u32 srclen, __u32 destlen) -+static void rubin_do_decompress(int bit_divider, int *bits, unsigned char *cdata_in, -+ unsigned char *page_out, uint32_t srclen, uint32_t destlen) - { - int outpos = 0; - struct rubin_state rs; -@@ -330,14 +306,14 @@ - } - - --void rubinmips_decompress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 sourcelen, __u32 dstlen) -+void jffs2_rubinmips_decompress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t sourcelen, uint32_t dstlen) - { - rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen); - } - --void dynrubin_decompress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 sourcelen, __u32 dstlen) -+void jffs2_dynrubin_decompress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t sourcelen, uint32_t dstlen) - { - int bits[8]; - int c; -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/compr_rubin.h linux/fs/jffs2/compr_rubin.h ---- linux-mips-2.4.24-pre2/fs/jffs2/compr_rubin.h 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/compr_rubin.h 2004-11-17 18:17:59.000000000 +0100 -@@ -1,7 +1,7 @@ - /* Rubin encoder/decoder header */ - /* work started at : aug 3, 1994 */ - /* last modification : aug 15, 1994 */ --/* $Id$ */ -+/* $Id$ */ - - #include "pushpull.h" - -@@ -19,10 +19,3 @@ - int bit_divider; - int bits[8]; - }; -- -- --void init_rubin (struct rubin_state *rs, int div, int *bits); --int encode (struct rubin_state *, long, long, int); --void end_rubin (struct rubin_state *); --void init_decode (struct rubin_state *, int div, int *bits); --int decode (struct rubin_state *, long, long); -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/compr_zlib.c linux/fs/jffs2/compr_zlib.c ---- linux-mips-2.4.24-pre2/fs/jffs2/compr_zlib.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/compr_zlib.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,50 +1,26 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001, 2002 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - --#ifndef __KERNEL__ -+#if !defined(__KERNEL__) && !defined(__ECOS) - #error "The userspace support got too messy and was removed. Update your mkfs.jffs2" - #endif - - #include - #include --#include /* for min() */ - #include --#include - #include -+#include -+#include - #include "nodelist.h" - - /* Plan: call deflate() with avail_in == *sourcelen, -@@ -58,21 +34,24 @@ - - static DECLARE_MUTEX(deflate_sem); - static DECLARE_MUTEX(inflate_sem); --static void *deflate_workspace; --static void *inflate_workspace; -+static z_stream inf_strm, def_strm; -+ -+#ifdef __KERNEL__ /* Linux-only */ -+#include -+#include - - int __init jffs2_zlib_init(void) - { -- deflate_workspace = vmalloc(zlib_deflate_workspacesize()); -- if (!deflate_workspace) { -+ def_strm.workspace = vmalloc(zlib_deflate_workspacesize()); -+ if (!def_strm.workspace) { - printk(KERN_WARNING "Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize()); - return -ENOMEM; - } - D1(printk(KERN_DEBUG "Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize())); -- inflate_workspace = vmalloc(zlib_inflate_workspacesize()); -- if (!inflate_workspace) { -+ inf_strm.workspace = vmalloc(zlib_inflate_workspacesize()); -+ if (!inf_strm.workspace) { - printk(KERN_WARNING "Failed to allocate %d bytes for inflate workspace\n", zlib_inflate_workspacesize()); -- vfree(deflate_workspace); -+ vfree(def_strm.workspace); - return -ENOMEM; - } - D1(printk(KERN_DEBUG "Allocated %d bytes for inflate workspace\n", zlib_inflate_workspacesize())); -@@ -81,97 +60,120 @@ - - void jffs2_zlib_exit(void) - { -- vfree(deflate_workspace); -- vfree(inflate_workspace); -+ vfree(def_strm.workspace); -+ vfree(inf_strm.workspace); - } -+#endif /* __KERNEL__ */ - --int zlib_compress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 *sourcelen, __u32 *dstlen) -+int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t *sourcelen, uint32_t *dstlen) - { -- z_stream strm; - int ret; - - if (*dstlen <= STREAM_END_SPACE) - return -1; - - down(&deflate_sem); -- strm.workspace = deflate_workspace; - -- if (Z_OK != zlib_deflateInit(&strm, 3)) { -+ if (Z_OK != zlib_deflateInit(&def_strm, 3)) { - printk(KERN_WARNING "deflateInit failed\n"); - up(&deflate_sem); - return -1; - } - -- strm.next_in = data_in; -- strm.total_in = 0; -+ def_strm.next_in = data_in; -+ def_strm.total_in = 0; - -- strm.next_out = cpage_out; -- strm.total_out = 0; -+ def_strm.next_out = cpage_out; -+ def_strm.total_out = 0; - -- while (strm.total_out < *dstlen - STREAM_END_SPACE && strm.total_in < *sourcelen) { -- strm.avail_out = *dstlen - (strm.total_out + STREAM_END_SPACE); -- strm.avail_in = min((unsigned)(*sourcelen-strm.total_in), strm.avail_out); -+ while (def_strm.total_out < *dstlen - STREAM_END_SPACE && def_strm.total_in < *sourcelen) { -+ def_strm.avail_out = *dstlen - (def_strm.total_out + STREAM_END_SPACE); -+ def_strm.avail_in = min((unsigned)(*sourcelen-def_strm.total_in), def_strm.avail_out); - D1(printk(KERN_DEBUG "calling deflate with avail_in %d, avail_out %d\n", -- strm.avail_in, strm.avail_out)); -- ret = zlib_deflate(&strm, Z_PARTIAL_FLUSH); -+ def_strm.avail_in, def_strm.avail_out)); -+ ret = zlib_deflate(&def_strm, Z_PARTIAL_FLUSH); - D1(printk(KERN_DEBUG "deflate returned with avail_in %d, avail_out %d, total_in %ld, total_out %ld\n", -- strm.avail_in, strm.avail_out, strm.total_in, strm.total_out)); -+ def_strm.avail_in, def_strm.avail_out, def_strm.total_in, def_strm.total_out)); - if (ret != Z_OK) { - D1(printk(KERN_DEBUG "deflate in loop returned %d\n", ret)); -- zlib_deflateEnd(&strm); -+ zlib_deflateEnd(&def_strm); - up(&deflate_sem); - return -1; - } - } -- strm.avail_out += STREAM_END_SPACE; -- strm.avail_in = 0; -- ret = zlib_deflate(&strm, Z_FINISH); -- zlib_deflateEnd(&strm); -- up(&deflate_sem); -+ def_strm.avail_out += STREAM_END_SPACE; -+ def_strm.avail_in = 0; -+ ret = zlib_deflate(&def_strm, Z_FINISH); -+ zlib_deflateEnd(&def_strm); -+ - if (ret != Z_STREAM_END) { - D1(printk(KERN_DEBUG "final deflate returned %d\n", ret)); -- return -1; -+ ret = -1; -+ goto out; - } - -- D1(printk(KERN_DEBUG "zlib compressed %ld bytes into %ld\n", -- strm.total_in, strm.total_out)); -+ if (def_strm.total_out >= def_strm.total_in) { -+ D1(printk(KERN_DEBUG "zlib compressed %ld bytes into %ld; failing\n", -+ def_strm.total_in, def_strm.total_out)); -+ ret = -1; -+ goto out; -+ } - -- if (strm.total_out >= strm.total_in) -- return -1; -+ D1(printk(KERN_DEBUG "zlib compressed %ld bytes into %ld\n", -+ def_strm.total_in, def_strm.total_out)); - -- *dstlen = strm.total_out; -- *sourcelen = strm.total_in; -- return 0; -+ *dstlen = def_strm.total_out; -+ *sourcelen = def_strm.total_in; -+ ret = 0; -+ out: -+ up(&deflate_sem); -+ return ret; - } - --void zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 srclen, __u32 destlen) -+void jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t srclen, uint32_t destlen) - { -- z_stream strm; - int ret; -+ int wbits = MAX_WBITS; - - down(&inflate_sem); -- strm.workspace = inflate_workspace; - -- if (Z_OK != zlib_inflateInit(&strm)) { -+ inf_strm.next_in = data_in; -+ inf_strm.avail_in = srclen; -+ inf_strm.total_in = 0; -+ -+ inf_strm.next_out = cpage_out; -+ inf_strm.avail_out = destlen; -+ inf_strm.total_out = 0; -+ -+ /* If it's deflate, and it's got no preset dictionary, then -+ we can tell zlib to skip the adler32 check. */ -+ if (srclen > 2 && !(data_in[1] & PRESET_DICT) && -+ ((data_in[0] & 0x0f) == Z_DEFLATED) && -+ !(((data_in[0]<<8) + data_in[1]) % 31)) { -+ -+ D2(printk(KERN_DEBUG "inflate skipping adler32\n")); -+ wbits = -((data_in[0] >> 4) + 8); -+ inf_strm.next_in += 2; -+ inf_strm.avail_in -= 2; -+ } else { -+ /* Let this remain D1 for now -- it should never happen */ -+ D1(printk(KERN_DEBUG "inflate not skipping adler32\n")); -+ } -+ -+ -+ if (Z_OK != zlib_inflateInit2(&inf_strm, wbits)) { - printk(KERN_WARNING "inflateInit failed\n"); - up(&inflate_sem); - return; - } -- strm.next_in = data_in; -- strm.avail_in = srclen; -- strm.total_in = 0; -- -- strm.next_out = cpage_out; -- strm.avail_out = destlen; -- strm.total_out = 0; - -- while((ret = zlib_inflate(&strm, Z_FINISH)) == Z_OK) -+ while((ret = zlib_inflate(&inf_strm, Z_FINISH)) == Z_OK) - ; - if (ret != Z_STREAM_END) { - printk(KERN_NOTICE "inflate returned %d\n", ret); - } -- zlib_inflateEnd(&strm); -+ zlib_inflateEnd(&inf_strm); - up(&inflate_sem); - } -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/comprtest.c linux/fs/jffs2/comprtest.c ---- linux-mips-2.4.24-pre2/fs/jffs2/comprtest.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/comprtest.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,4 +1,4 @@ --/* $Id$ */ -+/* $Id$ */ - - #include - #include -@@ -266,13 +266,13 @@ - static unsigned char decomprbuf[TESTDATA_LEN]; - - int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, -- unsigned char *data_out, __u32 cdatalen, __u32 datalen); -+ unsigned char *data_out, uint32_t cdatalen, uint32_t datalen); - unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 *datalen, __u32 *cdatalen); -+ uint32_t *datalen, uint32_t *cdatalen); - - int init_module(void ) { - unsigned char comprtype; -- __u32 c, d; -+ uint32_t c, d; - int ret; - - printk("Original data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/crc32.c linux/fs/jffs2/crc32.c ---- linux-mips-2.4.24-pre2/fs/jffs2/crc32.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/crc32.c 2004-11-17 18:17:59.283276832 +0100 -@@ -0,0 +1,97 @@ -+/* -+ * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or -+ * code or tables extracted from it, as desired without restriction. -+ * -+ * First, the polynomial itself and its table of feedback terms. The -+ * polynomial is -+ * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 -+ * -+ * Note that we take it "backwards" and put the highest-order term in -+ * the lowest-order bit. The X^32 term is "implied"; the LSB is the -+ * X^31 term, etc. The X^0 term (usually shown as "+1") results in -+ * the MSB being 1 -+ * -+ * Note that the usual hardware shift register implementation, which -+ * is what we're using (we're merely optimizing it by doing eight-bit -+ * chunks at a time) shifts bits into the lowest-order term. In our -+ * implementation, that means shifting towards the right. Why do we -+ * do it this way? Because the calculated CRC must be transmitted in -+ * order from highest-order term to lowest-order term. UARTs transmit -+ * characters in order from LSB to MSB. By storing the CRC this way -+ * we hand it to the UART in the order low-byte to high-byte; the UART -+ * sends each low-bit to hight-bit; and the result is transmission bit -+ * by bit from highest- to lowest-order term without requiring any bit -+ * shuffling on our part. Reception works similarly -+ * -+ * The feedback terms table consists of 256, 32-bit entries. Notes -+ * -+ * The table can be generated at runtime if desired; code to do so -+ * is shown later. It might not be obvious, but the feedback -+ * terms simply represent the results of eight shift/xor opera -+ * tions for all combinations of data and CRC register values -+ * -+ * The values must be right-shifted by eight bits by the "updcrc -+ * logic; the shift must be unsigned (bring in zeroes). On some -+ * hardware you could probably optimize the shift in assembler by -+ * using byte-swap instructions -+ * polynomial $edb88320 -+ */ -+ -+/* $Id$ */ -+ -+#include "crc32.h" -+ -+const uint32_t crc32_table[256] = { -+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, -+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, -+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, -+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, -+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, -+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, -+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, -+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, -+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, -+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, -+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, -+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, -+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, -+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, -+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, -+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, -+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, -+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, -+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, -+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, -+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, -+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, -+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, -+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, -+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, -+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, -+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, -+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, -+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, -+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, -+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, -+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, -+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, -+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, -+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, -+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, -+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, -+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, -+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, -+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, -+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, -+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, -+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, -+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, -+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, -+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, -+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, -+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, -+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, -+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, -+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, -+ 0x2d02ef8dL -+}; -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/crc32.h linux/fs/jffs2/crc32.h ---- linux-mips-2.4.24-pre2/fs/jffs2/crc32.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/crc32.h 2004-11-17 18:17:59.284276680 +0100 -@@ -0,0 +1,21 @@ -+#ifndef CRC32_H -+#define CRC32_H -+ -+/* $Id$ */ -+ -+#include -+ -+extern const uint32_t crc32_table[256]; -+ -+/* Return a 32-bit CRC of the contents of the buffer. */ -+ -+static inline uint32_t -+crc32(uint32_t val, const void *ss, int len) -+{ -+ const unsigned char *s = ss; -+ while (--len >= 0) -+ val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8); -+ return val; -+} -+ -+#endif -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/dir.c linux/fs/jffs2/dir.c ---- linux-mips-2.4.24-pre2/fs/jffs2/dir.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/dir.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,84 +1,73 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include - #include -+#include - #include --#include /* For completion */ -+#include - #include - #include - #include -+#include - #include "nodelist.h" --#include -+ -+/* Urgh. Please tell me there's a nicer way of doing these. */ -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,48) -+typedef int mknod_arg_t; -+#define NAMEI_COMPAT(x) ((void *)x) -+#else -+typedef dev_t mknod_arg_t; -+#define NAMEI_COMPAT(x) (x) -+#endif - - static int jffs2_readdir (struct file *, void *, filldir_t); - --static int jffs2_create (struct inode *,struct dentry *,int); --static struct dentry *jffs2_lookup (struct inode *,struct dentry *); -+static int jffs2_create (struct inode *,struct dentry *,int, -+ struct nameidata *); -+static struct dentry *jffs2_lookup (struct inode *,struct dentry *, -+ struct nameidata *); - static int jffs2_link (struct dentry *,struct inode *,struct dentry *); - static int jffs2_unlink (struct inode *,struct dentry *); - static int jffs2_symlink (struct inode *,struct dentry *,const char *); - static int jffs2_mkdir (struct inode *,struct dentry *,int); - static int jffs2_rmdir (struct inode *,struct dentry *); --static int jffs2_mknod (struct inode *,struct dentry *,int,int); -+static int jffs2_mknod (struct inode *,struct dentry *,int,mknod_arg_t); - static int jffs2_rename (struct inode *, struct dentry *, - struct inode *, struct dentry *); - - struct file_operations jffs2_dir_operations = - { -- read: generic_read_dir, -- readdir: jffs2_readdir, -- ioctl: jffs2_ioctl, -- fsync: jffs2_null_fsync -+ .read = generic_read_dir, -+ .readdir = jffs2_readdir, -+ .ioctl = jffs2_ioctl, -+ .fsync = jffs2_fsync - }; - - - struct inode_operations jffs2_dir_inode_operations = - { -- create: jffs2_create, -- lookup: jffs2_lookup, -- link: jffs2_link, -- unlink: jffs2_unlink, -- symlink: jffs2_symlink, -- mkdir: jffs2_mkdir, -- rmdir: jffs2_rmdir, -- mknod: jffs2_mknod, -- rename: jffs2_rename, -- setattr: jffs2_setattr, -+ .create = NAMEI_COMPAT(jffs2_create), -+ .lookup = NAMEI_COMPAT(jffs2_lookup), -+ .link = jffs2_link, -+ .unlink = jffs2_unlink, -+ .symlink = jffs2_symlink, -+ .mkdir = jffs2_mkdir, -+ .rmdir = jffs2_rmdir, -+ .mknod = jffs2_mknod, -+ .rename = jffs2_rename, -+ .setattr = jffs2_setattr, - }; - - /***********************************************************************/ -@@ -88,12 +77,13 @@ - and we use the same hash function as the dentries. Makes this - nice and simple - */ --static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target) -+static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, -+ struct nameidata *nd) - { - struct jffs2_inode_info *dir_f; - struct jffs2_sb_info *c; - struct jffs2_full_dirent *fd = NULL, *fd_list; -- __u32 ino = 0; -+ uint32_t ino = 0; - struct inode *inode = NULL; - - D1(printk(KERN_DEBUG "jffs2_lookup()\n")); -@@ -153,8 +143,9 @@ - offset++; - } - if (offset == 1) { -- D1(printk(KERN_DEBUG "Dirent 1: \"..\", ino #%lu\n", filp->f_dentry->d_parent->d_inode->i_ino)); -- if (filldir(dirent, "..", 2, 1, filp->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) -+ unsigned long pino = parent_ino(filp->f_dentry); -+ D1(printk(KERN_DEBUG "Dirent 1: \"..\", ino #%lu\n", pino)); -+ if (filldir(dirent, "..", 2, 1, pino, DT_DIR) < 0) - goto out; - offset++; - } -@@ -188,18 +179,14 @@ - - /***********************************************************************/ - --static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode) -+ -+static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, -+ struct nameidata *nd) - { -+ struct jffs2_raw_inode *ri; - struct jffs2_inode_info *f, *dir_f; - struct jffs2_sb_info *c; - struct inode *inode; -- struct jffs2_raw_inode *ri; -- struct jffs2_raw_dirent *rd; -- struct jffs2_full_dnode *fn; -- struct jffs2_full_dirent *fd; -- int namelen; -- __u32 alloclen, phys_ofs; -- __u32 writtenlen; - int ret; - - ri = jffs2_alloc_raw_inode(); -@@ -210,23 +197,11 @@ - - D1(printk(KERN_DEBUG "jffs2_create()\n")); - -- /* Try to reserve enough space for both node and dirent. -- * Just the node will do for now, though -- */ -- namelen = dentry->d_name.len; -- ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); -- D1(printk(KERN_DEBUG "jffs2_create(): reserved 0x%x bytes\n", alloclen)); -- if (ret) { -- jffs2_free_raw_inode(ri); -- return ret; -- } -- - inode = jffs2_new_inode(dir_i, mode, ri); - - if (IS_ERR(inode)) { - D1(printk(KERN_DEBUG "jffs2_new_inode() failed\n")); - jffs2_free_raw_inode(ri); -- jffs2_complete_reservation(c); - return PTR_ERR(inode); - } - -@@ -236,93 +211,22 @@ - inode->i_mapping->nrpages = 0; - - f = JFFS2_INODE_INFO(inode); -+ dir_f = JFFS2_INODE_INFO(dir_i); - -- ri->data_crc = 0; -- ri->node_crc = crc32(0, ri, sizeof(*ri)-8); -- -- fn = jffs2_write_dnode(inode, ri, NULL, 0, phys_ofs, &writtenlen); -- D1(printk(KERN_DEBUG "jffs2_create created file with mode 0x%x\n", ri->mode)); -- jffs2_free_raw_inode(ri); -- -- if (IS_ERR(fn)) { -- D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n")); -- /* Eeek. Wave bye bye */ -- up(&f->sem); -- jffs2_complete_reservation(c); -- jffs2_clear_inode(inode); -- return PTR_ERR(fn); -- } -- /* No data here. Only a metadata node, which will be -- obsoleted by the first data write -- */ -- f->metadata = fn; -- -- /* Work out where to put the dirent node now. */ -- writtenlen = PAD(writtenlen); -- phys_ofs += writtenlen; -- alloclen -= writtenlen; -- up(&f->sem); -- -- if (alloclen < sizeof(*rd)+namelen) { -- /* Not enough space left in this chunk. Get some more */ -- jffs2_complete_reservation(c); -- ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); -+ ret = jffs2_do_create(c, dir_f, f, ri, -+ dentry->d_name.name, dentry->d_name.len); - - if (ret) { -- /* Eep. */ -- D1(printk(KERN_DEBUG "jffs2_reserve_space() for dirent failed\n")); - jffs2_clear_inode(inode); -+ make_bad_inode(inode); -+ iput(inode); -+ jffs2_free_raw_inode(ri); - return ret; - } -- } - -- rd = jffs2_alloc_raw_dirent(); -- if (!rd) { -- /* Argh. Now we treat it like a normal delete */ -- jffs2_complete_reservation(c); -- jffs2_clear_inode(inode); -- return -ENOMEM; -- } -- -- dir_f = JFFS2_INODE_INFO(dir_i); -- down(&dir_f->sem); -- -- rd->magic = JFFS2_MAGIC_BITMASK; -- rd->nodetype = JFFS2_NODETYPE_DIRENT; -- rd->totlen = sizeof(*rd) + namelen; -- rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); -- -- rd->pino = dir_i->i_ino; -- rd->version = ++dir_f->highest_version; -- rd->ino = inode->i_ino; -- rd->mctime = CURRENT_TIME; -- rd->nsize = namelen; -- rd->type = DT_REG; -- rd->node_crc = crc32(0, rd, sizeof(*rd)-8); -- rd->name_crc = crc32(0, dentry->d_name.name, namelen); -- -- fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); -- -- jffs2_complete_reservation(c); -- -- if (IS_ERR(fd)) { -- /* dirent failed to write. Delete the inode normally -- as if it were the final unlink() */ -- jffs2_free_raw_dirent(rd); -- up(&dir_f->sem); -- jffs2_clear_inode(inode); -- return PTR_ERR(fd); -- } -- -- dir_i->i_mtime = dir_i->i_ctime = rd->mctime; -- -- jffs2_free_raw_dirent(rd); -- -- /* Link the fd into the inode's list, obsoleting an old -- one if necessary. */ -- jffs2_add_fd_to_list(c, fd, &dir_f->dents); -- up(&dir_f->sem); -+ dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime)); - -+ jffs2_free_raw_inode(ri); - d_instantiate(dentry, inode); - - D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n", -@@ -332,173 +236,48 @@ - - /***********************************************************************/ - --static int jffs2_do_unlink(struct inode *dir_i, struct dentry *dentry, int rename) --{ -- struct jffs2_inode_info *dir_f, *f; -- struct jffs2_sb_info *c; -- struct jffs2_raw_dirent *rd; -- struct jffs2_full_dirent *fd; -- __u32 alloclen, phys_ofs; -- int ret; -- -- c = JFFS2_SB_INFO(dir_i->i_sb); -- -- rd = jffs2_alloc_raw_dirent(); -- if (!rd) -- return -ENOMEM; -- -- ret = jffs2_reserve_space(c, sizeof(*rd)+dentry->d_name.len, &phys_ofs, &alloclen, ALLOC_DELETION); -- if (ret) { -- jffs2_free_raw_dirent(rd); -- return ret; -- } -- -- dir_f = JFFS2_INODE_INFO(dir_i); -- down(&dir_f->sem); -- -- /* Build a deletion node */ -- rd->magic = JFFS2_MAGIC_BITMASK; -- rd->nodetype = JFFS2_NODETYPE_DIRENT; -- rd->totlen = sizeof(*rd) + dentry->d_name.len; -- rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); -- -- rd->pino = dir_i->i_ino; -- rd->version = ++dir_f->highest_version; -- rd->ino = 0; -- rd->mctime = CURRENT_TIME; -- rd->nsize = dentry->d_name.len; -- rd->type = DT_UNKNOWN; -- rd->node_crc = crc32(0, rd, sizeof(*rd)-8); -- rd->name_crc = crc32(0, dentry->d_name.name, dentry->d_name.len); -- -- fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, dentry->d_name.len, phys_ofs, NULL); -- -- jffs2_complete_reservation(c); -- jffs2_free_raw_dirent(rd); -- -- if (IS_ERR(fd)) { -- up(&dir_f->sem); -- return PTR_ERR(fd); -- } -- -- /* File it. This will mark the old one obsolete. */ -- jffs2_add_fd_to_list(c, fd, &dir_f->dents); -- up(&dir_f->sem); -- -- if (!rename) { -- f = JFFS2_INODE_INFO(dentry->d_inode); -- down(&f->sem); -- -- while (f->dents) { -- /* There can be only deleted ones */ -- fd = f->dents; -- -- f->dents = fd->next; -- -- if (fd->ino) { -- printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n", -- f->inocache->ino, fd->name, fd->ino); -- } else { -- D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n", fd->name, f->inocache->ino)); -- } -- jffs2_mark_node_obsolete(c, fd->raw); -- jffs2_free_full_dirent(fd); -- } -- /* Don't oops on unlinking a bad inode */ -- if (f->inocache) -- f->inocache->nlink--; -- dentry->d_inode->i_nlink--; -- up(&f->sem); -- } -- -- return 0; --} - - static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry) - { -- return jffs2_do_unlink(dir_i, dentry, 0); --} --/***********************************************************************/ -- --static int jffs2_do_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry, int rename) --{ -- struct jffs2_inode_info *dir_f, *f; -- struct jffs2_sb_info *c; -- struct jffs2_raw_dirent *rd; -- struct jffs2_full_dirent *fd; -- __u32 alloclen, phys_ofs; -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb); -+ struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); -+ struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(dentry->d_inode); - int ret; - -- c = JFFS2_SB_INFO(dir_i->i_sb); -- -- rd = jffs2_alloc_raw_dirent(); -- if (!rd) -- return -ENOMEM; -- -- ret = jffs2_reserve_space(c, sizeof(*rd)+dentry->d_name.len, &phys_ofs, &alloclen, ALLOC_NORMAL); -- if (ret) { -- jffs2_free_raw_dirent(rd); -+ ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, -+ dentry->d_name.len, dead_f); -+ if (dead_f->inocache) -+ dentry->d_inode->i_nlink = dead_f->inocache->nlink; - return ret; -- } -- -- dir_f = JFFS2_INODE_INFO(dir_i); -- down(&dir_f->sem); -- -- /* Build a deletion node */ -- rd->magic = JFFS2_MAGIC_BITMASK; -- rd->nodetype = JFFS2_NODETYPE_DIRENT; -- rd->totlen = sizeof(*rd) + dentry->d_name.len; -- rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); -- -- rd->pino = dir_i->i_ino; -- rd->version = ++dir_f->highest_version; -- rd->ino = old_dentry->d_inode->i_ino; -- rd->mctime = CURRENT_TIME; -- rd->nsize = dentry->d_name.len; -- -- /* XXX: This is ugly. */ -- rd->type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; -- if (!rd->type) rd->type = DT_REG; -- -- rd->node_crc = crc32(0, rd, sizeof(*rd)-8); -- rd->name_crc = crc32(0, dentry->d_name.name, dentry->d_name.len); -- -- fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, dentry->d_name.len, phys_ofs, NULL); -- -- jffs2_complete_reservation(c); -- jffs2_free_raw_dirent(rd); -- -- if (IS_ERR(fd)) { -- up(&dir_f->sem); -- return PTR_ERR(fd); -- } -- -- /* File it. This will mark the old one obsolete. */ -- jffs2_add_fd_to_list(c, fd, &dir_f->dents); -- up(&dir_f->sem); -- -- if (!rename) { -- f = JFFS2_INODE_INFO(old_dentry->d_inode); -- down(&f->sem); -- old_dentry->d_inode->i_nlink = ++f->inocache->nlink; -- up(&f->sem); -- } -- return 0; - } -+/***********************************************************************/ -+ - - static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry) - { -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dentry->d_inode->i_sb); -+ struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); -+ struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); - int ret; -+ uint8_t type; - -- /* Can't link a bad inode. */ -- if (!JFFS2_INODE_INFO(old_dentry->d_inode)->inocache) -+ /* Don't let people make hard links to bad inodes. */ -+ if (!f->inocache) - return -EIO; - - if (S_ISDIR(old_dentry->d_inode->i_mode)) - return -EPERM; - -- ret = jffs2_do_link(old_dentry, dir_i, dentry, 0); -+ /* XXX: This is ugly */ -+ type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; -+ if (!type) type = DT_REG; -+ -+ ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len); -+ - if (!ret) { -+ down(&f->sem); -+ old_dentry->d_inode->i_nlink = ++f->inocache->nlink; -+ up(&f->sem); - d_instantiate(dentry, old_dentry->d_inode); - atomic_inc(&old_dentry->d_inode->i_count); - } -@@ -517,8 +296,7 @@ - struct jffs2_full_dnode *fn; - struct jffs2_full_dirent *fd; - int namelen; -- __u32 alloclen, phys_ofs; -- __u32 writtenlen; -+ uint32_t alloclen, phys_ofs; - int ret; - - /* FIXME: If you care. We'd need to use frags for the target -@@ -556,15 +334,16 @@ - - f = JFFS2_INODE_INFO(inode); - -- inode->i_size = ri->isize = ri->dsize = ri->csize = strlen(target); -- ri->totlen = sizeof(*ri) + ri->dsize; -- ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); -+ inode->i_size = strlen(target); -+ ri->isize = ri->dsize = ri->csize = cpu_to_je32(inode->i_size); -+ ri->totlen = cpu_to_je32(sizeof(*ri) + inode->i_size); -+ ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); - - ri->compr = JFFS2_COMPR_NONE; -- ri->data_crc = crc32(0, target, strlen(target)); -- ri->node_crc = crc32(0, ri, sizeof(*ri)-8); -+ ri->data_crc = cpu_to_je32(crc32(0, target, strlen(target))); -+ ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - -- fn = jffs2_write_dnode(inode, ri, target, strlen(target), phys_ofs, &writtenlen); -+ fn = jffs2_write_dnode(c, f, ri, target, strlen(target), phys_ofs, ALLOC_NORMAL); - - jffs2_free_raw_inode(ri); - -@@ -581,13 +360,6 @@ - f->metadata = fn; - up(&f->sem); - -- /* Work out where to put the dirent node now. */ -- writtenlen = (writtenlen+3)&~3; -- phys_ofs += writtenlen; -- alloclen -= writtenlen; -- -- if (alloclen < sizeof(*rd)+namelen) { -- /* Not enough space left in this chunk. Get some more */ - jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); - if (ret) { -@@ -595,7 +367,6 @@ - jffs2_clear_inode(inode); - return ret; - } -- } - - rd = jffs2_alloc_raw_dirent(); - if (!rd) { -@@ -608,41 +379,42 @@ - dir_f = JFFS2_INODE_INFO(dir_i); - down(&dir_f->sem); - -- rd->magic = JFFS2_MAGIC_BITMASK; -- rd->nodetype = JFFS2_NODETYPE_DIRENT; -- rd->totlen = sizeof(*rd) + namelen; -- rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); -- -- rd->pino = dir_i->i_ino; -- rd->version = ++dir_f->highest_version; -- rd->ino = inode->i_ino; -- rd->mctime = CURRENT_TIME; -+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); -+ rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); -+ rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); -+ -+ rd->pino = cpu_to_je32(dir_i->i_ino); -+ rd->version = cpu_to_je32(++dir_f->highest_version); -+ rd->ino = cpu_to_je32(inode->i_ino); -+ rd->mctime = cpu_to_je32(get_seconds()); - rd->nsize = namelen; - rd->type = DT_LNK; -- rd->node_crc = crc32(0, rd, sizeof(*rd)-8); -- rd->name_crc = crc32(0, dentry->d_name.name, namelen); -+ rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); -+ rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); - -- fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); -- -- jffs2_complete_reservation(c); -+ fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); - - if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally - as if it were the final unlink() */ -+ jffs2_complete_reservation(c); - jffs2_free_raw_dirent(rd); - up(&dir_f->sem); - jffs2_clear_inode(inode); - return PTR_ERR(fd); - } - -- dir_i->i_mtime = dir_i->i_ctime = rd->mctime; -+ dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); - - jffs2_free_raw_dirent(rd); - - /* Link the fd into the inode's list, obsoleting an old - one if necessary. */ - jffs2_add_fd_to_list(c, fd, &dir_f->dents); -+ - up(&dir_f->sem); -+ jffs2_complete_reservation(c); - - d_instantiate(dentry, inode); - return 0; -@@ -659,8 +431,7 @@ - struct jffs2_full_dnode *fn; - struct jffs2_full_dirent *fd; - int namelen; -- __u32 alloclen, phys_ofs; -- __u32 writtenlen; -+ uint32_t alloclen, phys_ofs; - int ret; - - mode |= S_IFDIR; -@@ -692,13 +463,15 @@ - - inode->i_op = &jffs2_dir_inode_operations; - inode->i_fop = &jffs2_dir_operations; -+ /* Directories get nlink 2 at start */ -+ inode->i_nlink = 2; - - f = JFFS2_INODE_INFO(inode); - -- ri->data_crc = 0; -- ri->node_crc = crc32(0, ri, sizeof(*ri)-8); -+ ri->data_crc = cpu_to_je32(0); -+ ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - -- fn = jffs2_write_dnode(inode, ri, NULL, 0, phys_ofs, &writtenlen); -+ fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); - - jffs2_free_raw_inode(ri); - -@@ -715,13 +488,6 @@ - f->metadata = fn; - up(&f->sem); - -- /* Work out where to put the dirent node now. */ -- writtenlen = PAD(writtenlen); -- phys_ofs += writtenlen; -- alloclen -= writtenlen; -- -- if (alloclen < sizeof(*rd)+namelen) { -- /* Not enough space left in this chunk. Get some more */ - jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); - if (ret) { -@@ -729,7 +495,6 @@ - jffs2_clear_inode(inode); - return ret; - } -- } - - rd = jffs2_alloc_raw_dirent(); - if (!rd) { -@@ -742,41 +507,43 @@ - dir_f = JFFS2_INODE_INFO(dir_i); - down(&dir_f->sem); - -- rd->magic = JFFS2_MAGIC_BITMASK; -- rd->nodetype = JFFS2_NODETYPE_DIRENT; -- rd->totlen = sizeof(*rd) + namelen; -- rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); -- -- rd->pino = dir_i->i_ino; -- rd->version = ++dir_f->highest_version; -- rd->ino = inode->i_ino; -- rd->mctime = CURRENT_TIME; -+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); -+ rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); -+ rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); -+ -+ rd->pino = cpu_to_je32(dir_i->i_ino); -+ rd->version = cpu_to_je32(++dir_f->highest_version); -+ rd->ino = cpu_to_je32(inode->i_ino); -+ rd->mctime = cpu_to_je32(get_seconds()); - rd->nsize = namelen; - rd->type = DT_DIR; -- rd->node_crc = crc32(0, rd, sizeof(*rd)-8); -- rd->name_crc = crc32(0, dentry->d_name.name, namelen); -+ rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); -+ rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); - -- fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); -- -- jffs2_complete_reservation(c); -+ fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); - - if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally - as if it were the final unlink() */ -+ jffs2_complete_reservation(c); - jffs2_free_raw_dirent(rd); - up(&dir_f->sem); - jffs2_clear_inode(inode); - return PTR_ERR(fd); - } - -- dir_i->i_mtime = dir_i->i_ctime = rd->mctime; -+ dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); -+ dir_i->i_nlink++; - - jffs2_free_raw_dirent(rd); - - /* Link the fd into the inode's list, obsoleting an old - one if necessary. */ - jffs2_add_fd_to_list(c, fd, &dir_f->dents); -+ - up(&dir_f->sem); -+ jffs2_complete_reservation(c); - - d_instantiate(dentry, inode); - return 0; -@@ -786,15 +553,19 @@ - { - struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); - struct jffs2_full_dirent *fd; -+ int ret; - - for (fd = f->dents ; fd; fd = fd->next) { - if (fd->ino) - return -ENOTEMPTY; - } -- return jffs2_unlink(dir_i, dentry); -+ ret = jffs2_unlink(dir_i, dentry); -+ if (!ret) -+ dir_i->i_nlink--; -+ return ret; - } - --static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, int rdev) -+static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, mknod_arg_t rdev) - { - struct jffs2_inode_info *f, *dir_f; - struct jffs2_sb_info *c; -@@ -804,12 +575,14 @@ - struct jffs2_full_dnode *fn; - struct jffs2_full_dirent *fd; - int namelen; -- unsigned short dev; -+ jint16_t dev; - int devlen = 0; -- __u32 alloclen, phys_ofs; -- __u32 writtenlen; -+ uint32_t alloclen, phys_ofs; - int ret; - -+ if (!old_valid_dev(rdev)) -+ return -EINVAL; -+ - ri = jffs2_alloc_raw_inode(); - if (!ri) - return -ENOMEM; -@@ -817,7 +590,7 @@ - c = JFFS2_SB_INFO(dir_i->i_sb); - - if (S_ISBLK(mode) || S_ISCHR(mode)) { -- dev = (MAJOR(to_kdev_t(rdev)) << 8) | MINOR(to_kdev_t(rdev)); -+ dev = cpu_to_je16(old_encode_dev(rdev)); - devlen = sizeof(dev); - } - -@@ -844,15 +617,15 @@ - - f = JFFS2_INODE_INFO(inode); - -- ri->dsize = ri->csize = devlen; -- ri->totlen = sizeof(*ri) + ri->csize; -- ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); -+ ri->dsize = ri->csize = cpu_to_je32(devlen); -+ ri->totlen = cpu_to_je32(sizeof(*ri) + devlen); -+ ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); - - ri->compr = JFFS2_COMPR_NONE; -- ri->data_crc = crc32(0, &dev, devlen); -- ri->node_crc = crc32(0, ri, sizeof(*ri)-8); -+ ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen)); -+ ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - -- fn = jffs2_write_dnode(inode, ri, (char *)&dev, devlen, phys_ofs, &writtenlen); -+ fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, phys_ofs, ALLOC_NORMAL); - - jffs2_free_raw_inode(ri); - -@@ -869,13 +642,6 @@ - f->metadata = fn; - up(&f->sem); - -- /* Work out where to put the dirent node now. */ -- writtenlen = (writtenlen+3)&~3; -- phys_ofs += writtenlen; -- alloclen -= writtenlen; -- -- if (alloclen < sizeof(*rd)+namelen) { -- /* Not enough space left in this chunk. Get some more */ - jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); - if (ret) { -@@ -883,7 +649,6 @@ - jffs2_clear_inode(inode); - return ret; - } -- } - - rd = jffs2_alloc_raw_dirent(); - if (!rd) { -@@ -896,44 +661,45 @@ - dir_f = JFFS2_INODE_INFO(dir_i); - down(&dir_f->sem); - -- rd->magic = JFFS2_MAGIC_BITMASK; -- rd->nodetype = JFFS2_NODETYPE_DIRENT; -- rd->totlen = sizeof(*rd) + namelen; -- rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); -- -- rd->pino = dir_i->i_ino; -- rd->version = ++dir_f->highest_version; -- rd->ino = inode->i_ino; -- rd->mctime = CURRENT_TIME; -+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); -+ rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); -+ rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); -+ -+ rd->pino = cpu_to_je32(dir_i->i_ino); -+ rd->version = cpu_to_je32(++dir_f->highest_version); -+ rd->ino = cpu_to_je32(inode->i_ino); -+ rd->mctime = cpu_to_je32(get_seconds()); - rd->nsize = namelen; - - /* XXX: This is ugly. */ - rd->type = (mode & S_IFMT) >> 12; - -- rd->node_crc = crc32(0, rd, sizeof(*rd)-8); -- rd->name_crc = crc32(0, dentry->d_name.name, namelen); -- -- fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); -+ rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); -+ rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); - -- jffs2_complete_reservation(c); -+ fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); - - if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally - as if it were the final unlink() */ -+ jffs2_complete_reservation(c); - jffs2_free_raw_dirent(rd); - up(&dir_f->sem); - jffs2_clear_inode(inode); - return PTR_ERR(fd); - } - -- dir_i->i_mtime = dir_i->i_ctime = rd->mctime; -+ dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); - - jffs2_free_raw_dirent(rd); - - /* Link the fd into the inode's list, obsoleting an old - one if necessary. */ - jffs2_add_fd_to_list(c, fd, &dir_f->dents); -+ - up(&dir_f->sem); -+ jffs2_complete_reservation(c); - - d_instantiate(dentry, inode); - -@@ -944,7 +710,9 @@ - struct inode *new_dir_i, struct dentry *new_dentry) - { - int ret; -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); - struct jffs2_inode_info *victim_f = NULL; -+ uint8_t type; - - /* The VFS will check for us and prevent trying to rename a - * file over a directory and vice versa, but if it's a directory, -@@ -973,7 +741,15 @@ - */ - - /* Make a hard link */ -- ret = jffs2_do_link(old_dentry, new_dir_i, new_dentry, 1); -+ -+ /* XXX: This is ugly */ -+ type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; -+ if (!type) type = DT_REG; -+ -+ ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), -+ old_dentry->d_inode->i_ino, type, -+ new_dentry->d_name.name, new_dentry->d_name.len); -+ - if (ret) - return ret; - -@@ -989,22 +765,36 @@ - } - } - -+ /* If it was a directory we moved, and there was no victim, -+ increase i_nlink on its new parent */ -+ if (S_ISDIR(old_dentry->d_inode->i_mode) && !victim_f) -+ new_dir_i->i_nlink++; -+ - /* Unlink the original */ -- ret = jffs2_do_unlink(old_dir_i, old_dentry, 1); -+ ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), -+ old_dentry->d_name.name, old_dentry->d_name.len, NULL); -+ -+ /* We don't touch inode->i_nlink */ - - if (ret) { - /* Oh shit. We really ought to make a single node which can do both atomically */ - struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); - down(&f->sem); -+ old_dentry->d_inode->i_nlink++; - if (f->inocache) -- old_dentry->d_inode->i_nlink = f->inocache->nlink++; -+ f->inocache->nlink++; - up(&f->sem); - - printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret); - /* Might as well let the VFS know */ - d_instantiate(new_dentry, old_dentry->d_inode); - atomic_inc(&old_dentry->d_inode->i_count); -- } - return ret; -+ } -+ -+ if (S_ISDIR(old_dentry->d_inode->i_mode)) -+ old_dir_i->i_nlink--; -+ -+ return 0; - } - -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/erase.c linux/fs/jffs2/erase.c ---- linux-mips-2.4.24-pre2/fs/jffs2/erase.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/erase.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,68 +1,60 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ -+ - #include - #include - #include --#include --#include --#include "nodelist.h" -+#include - #include -+#include -+#include -+#include "nodelist.h" - - struct erase_priv_struct { - struct jffs2_eraseblock *jeb; - struct jffs2_sb_info *c; - }; - -+#ifndef __ECOS - static void jffs2_erase_callback(struct erase_info *); -+#endif -+static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); - static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); - - void jffs2_erase_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) - { -- struct erase_info *instr; - int ret; -+#ifdef __ECOS -+ ret = jffs2_flash_erase(c, jeb); -+ if (!ret) { -+ jffs2_erase_succeeded(c, jeb); -+ return; -+ } -+#else /* Linux */ -+ struct erase_info *instr; - - instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL); - if (!instr) { - printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n"); -- spin_lock_bh(&c->erase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - list_del(&jeb->list); - list_add(&jeb->list, &c->erase_pending_list); - c->erasing_size -= c->sector_size; -- spin_unlock_bh(&c->erase_completion_lock); -+ c->dirty_size += c->sector_size; -+ jeb->dirty_size = c->sector_size; -+ spin_unlock(&c->erase_completion_lock); - return; - } - -@@ -77,19 +69,27 @@ - ((struct erase_priv_struct *)instr->priv)->jeb = jeb; - ((struct erase_priv_struct *)instr->priv)->c = c; - -+ /* NAND , read out the fail counter, if possible */ -+ if (!jffs2_can_mark_obsolete(c)) -+ jffs2_nand_read_failcnt(c,jeb); -+ - ret = c->mtd->erase(c->mtd, instr); -- if (!ret) { -+ if (!ret) - return; -- } -+ -+ kfree(instr); -+#endif /* __ECOS */ -+ - if (ret == -ENOMEM || ret == -EAGAIN) { - /* Erase failed immediately. Refile it on the list */ - D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret)); -- spin_lock_bh(&c->erase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - list_del(&jeb->list); - list_add(&jeb->list, &c->erase_pending_list); - c->erasing_size -= c->sector_size; -- spin_unlock_bh(&c->erase_completion_lock); -- kfree(instr); -+ c->dirty_size += c->sector_size; -+ jeb->dirty_size = c->sector_size; -+ spin_unlock(&c->erase_completion_lock); - return; - } - -@@ -97,74 +97,101 @@ - printk(KERN_WARNING "Erase at 0x%08x failed immediately: -EROFS. Is the sector locked?\n", jeb->offset); - else - printk(KERN_WARNING "Erase at 0x%08x failed immediately: errno %d\n", jeb->offset, ret); -- spin_lock_bh(&c->erase_completion_lock); -- list_del(&jeb->list); -- list_add(&jeb->list, &c->bad_list); -- c->nr_erasing_blocks--; -- c->bad_size += c->sector_size; -- c->erasing_size -= c->sector_size; -- spin_unlock_bh(&c->erase_completion_lock); -- wake_up(&c->erase_wait); -- kfree(instr); -+ -+ jffs2_erase_failed(c, jeb); - } - --void jffs2_erase_pending_blocks(struct jffs2_sb_info *c) -+void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) - { - struct jffs2_eraseblock *jeb; - -- spin_lock_bh(&c->erase_completion_lock); -- while (!list_empty(&c->erase_pending_list)) { -+ down(&c->erase_free_sem); - -- jeb = list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list); -+ spin_lock(&c->erase_completion_lock); - -- D1(printk(KERN_DEBUG "Starting erase of pending block 0x%08x\n", jeb->offset)); -+ while (!list_empty(&c->erase_complete_list) || -+ !list_empty(&c->erase_pending_list)) { - -+ if (!list_empty(&c->erase_complete_list)) { -+ jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list); -+ list_del(&jeb->list); -+ spin_unlock(&c->erase_completion_lock); -+ jffs2_mark_erased_block(c, jeb); -+ -+ if (!--count) { -+ D1(printk(KERN_DEBUG "Count reached. jffs2_erase_pending_blocks leaving\n")); -+ goto done; -+ } -+ -+ } else if (!list_empty(&c->erase_pending_list)) { -+ jeb = list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list); -+ D1(printk(KERN_DEBUG "Starting erase of pending block 0x%08x\n", jeb->offset)); - list_del(&jeb->list); - c->erasing_size += c->sector_size; -+ c->wasted_size -= jeb->wasted_size; - c->free_size -= jeb->free_size; - c->used_size -= jeb->used_size; - c->dirty_size -= jeb->dirty_size; -- jeb->used_size = jeb->dirty_size = jeb->free_size = 0; -+ jeb->wasted_size = jeb->used_size = jeb->dirty_size = jeb->free_size = 0; - jffs2_free_all_node_refs(c, jeb); - list_add(&jeb->list, &c->erasing_list); -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - - jffs2_erase_block(c, jeb); -+ -+ } else { -+ BUG(); -+ } -+ - /* Be nice */ -- if (current->need_resched) -- schedule(); -- spin_lock_bh(&c->erase_completion_lock); -+ cond_resched(); -+ spin_lock(&c->erase_completion_lock); - } -- spin_unlock_bh(&c->erase_completion_lock); -+ -+ spin_unlock(&c->erase_completion_lock); -+ done: - D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n")); -+ -+ up(&c->erase_free_sem); -+} -+ -+static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) -+{ -+ D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset)); -+ spin_lock(&c->erase_completion_lock); -+ list_del(&jeb->list); -+ list_add_tail(&jeb->list, &c->erase_complete_list); -+ spin_unlock(&c->erase_completion_lock); -+ /* Ensure that kupdated calls us again to mark them clean */ -+ jffs2_erase_pending_trigger(c); - } - -+static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) -+{ -+ spin_lock(&c->erase_completion_lock); -+ c->erasing_size -= c->sector_size; -+ c->bad_size += c->sector_size; -+ list_del(&jeb->list); -+ list_add(&jeb->list, &c->bad_list); -+ c->nr_erasing_blocks--; -+ spin_unlock(&c->erase_completion_lock); -+ wake_up(&c->erase_wait); -+} - -+#ifndef __ECOS - static void jffs2_erase_callback(struct erase_info *instr) - { - struct erase_priv_struct *priv = (void *)instr->priv; - - if(instr->state != MTD_ERASE_DONE) { - printk(KERN_WARNING "Erase at 0x%08x finished, but state != MTD_ERASE_DONE. State is 0x%x instead.\n", instr->addr, instr->state); -- spin_lock(&priv->c->erase_completion_lock); -- priv->c->erasing_size -= priv->c->sector_size; -- priv->c->bad_size += priv->c->sector_size; -- list_del(&priv->jeb->list); -- list_add(&priv->jeb->list, &priv->c->bad_list); -- priv->c->nr_erasing_blocks--; -- spin_unlock(&priv->c->erase_completion_lock); -- wake_up(&priv->c->erase_wait); -+ jffs2_erase_failed(priv->c, priv->jeb); - } else { -- D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", instr->addr)); -- spin_lock(&priv->c->erase_completion_lock); -- list_del(&priv->jeb->list); -- list_add_tail(&priv->jeb->list, &priv->c->erase_complete_list); -- spin_unlock(&priv->c->erase_completion_lock); -+ jffs2_erase_succeeded(priv->c, priv->jeb); - } -- /* Make sure someone picks up the block off the erase_complete list */ -- OFNI_BS_2SFFJ(priv->c)->s_dirt = 1; - kfree(instr); - } -+#endif /* !__ECOS */ - - /* Hmmm. Maybe we should accept the extra space it takes and make - this a standard doubly-linked list? */ -@@ -221,7 +248,7 @@ - this = ic->nodes; - - while(this) { -- printk( "0x%08x(%d)->", this->flash_offset & ~3, this->flash_offset &3); -+ printk( "0x%08x(%d)->", ref_offset(this), ref_flags(this)); - if (++i == 5) { - printk("\n" KERN_DEBUG); - i=0; -@@ -256,54 +283,43 @@ - jeb->last_node = NULL; - } - --void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) -+static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) - { -- OFNI_BS_2SFFJ(c)->s_dirt = 1; --} -- --void jffs2_mark_erased_blocks(struct jffs2_sb_info *c) --{ -- static struct jffs2_unknown_node marker = {JFFS2_MAGIC_BITMASK, JFFS2_NODETYPE_CLEANMARKER, sizeof(struct jffs2_unknown_node)}; -- struct jffs2_eraseblock *jeb; -- struct jffs2_raw_node_ref *marker_ref; -+ struct jffs2_raw_node_ref *marker_ref = NULL; - unsigned char *ebuf; -- ssize_t retlen; -+ size_t retlen; - int ret; - -- marker.hdr_crc = crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4); -- -- spin_lock_bh(&c->erase_completion_lock); -- while (!list_empty(&c->erase_complete_list)) { -- jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list); -- list_del(&jeb->list); -- spin_unlock_bh(&c->erase_completion_lock); -- -+ if (!jffs2_cleanmarker_oob(c)) { - marker_ref = jffs2_alloc_raw_node_ref(); - if (!marker_ref) { - printk(KERN_WARNING "Failed to allocate raw node ref for clean marker\n"); -- /* Come back later */ -+ /* Stick it back on the list from whence it came and come back later */ - jffs2_erase_pending_trigger(c); -+ spin_lock(&c->erase_completion_lock); -+ list_add(&jeb->list, &c->erase_complete_list); -+ spin_unlock(&c->erase_completion_lock); - return; - } -- -+ } - ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!ebuf) { - printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Assuming it worked\n", jeb->offset); - } else { -- __u32 ofs = jeb->offset; -+ uint32_t ofs = jeb->offset; - - D1(printk(KERN_DEBUG "Verifying erase at 0x%08x\n", jeb->offset)); - while(ofs < jeb->offset + c->sector_size) { -- __u32 readlen = min((__u32)PAGE_SIZE, jeb->offset + c->sector_size - ofs); -+ uint32_t readlen = min((uint32_t)PAGE_SIZE, jeb->offset + c->sector_size - ofs); - int i; - -- ret = c->mtd->read(c->mtd, ofs, readlen, &retlen, ebuf); -- if (ret < 0) { -+ ret = jffs2_flash_read(c, ofs, readlen, &retlen, ebuf); -+ if (ret) { - printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret); - goto bad; - } - if (retlen != readlen) { -- printk(KERN_WARNING "Short read from newly-erased block at 0x%08x. Wanted %d, got %d\n", ofs, readlen, retlen); -+ printk(KERN_WARNING "Short read from newly-erased block at 0x%08x. Wanted %d, got %zd\n", ofs, readlen, retlen); - goto bad; - } - for (i=0; ierase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - c->erasing_size -= c->sector_size; - c->bad_size += c->sector_size; - - list_add_tail(&jeb->list, &c->bad_list); - c->nr_erasing_blocks--; -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - wake_up(&c->erase_wait); - return; - } - } - ofs += readlen; -+ cond_resched(); - } - kfree(ebuf); - } - - /* Write the erase complete marker */ - D1(printk(KERN_DEBUG "Writing erased marker to block at 0x%08x\n", jeb->offset)); -- ret = c->mtd->write(c->mtd, jeb->offset, sizeof(marker), &retlen, (char *)&marker); -+ if (jffs2_cleanmarker_oob(c)) { -+ -+ if (jffs2_write_nand_cleanmarker(c, jeb)) -+ goto bad2; -+ -+ jeb->first_node = jeb->last_node = NULL; -+ -+ jeb->free_size = c->sector_size; -+ jeb->used_size = 0; -+ jeb->dirty_size = 0; -+ jeb->wasted_size = 0; -+ } else { -+ struct jffs2_unknown_node marker = { -+ .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK), -+ .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), -+ .totlen = cpu_to_je32(c->cleanmarker_size) -+ }; -+ -+ marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4)); -+ -+ /* We only write the header; the rest was noise or padding anyway */ -+ ret = jffs2_flash_write(c, jeb->offset, sizeof(marker), &retlen, (char *)&marker); - if (ret) { - printk(KERN_WARNING "Write clean marker to block at 0x%08x failed: %d\n", - jeb->offset, ret); - goto bad2; - } - if (retlen != sizeof(marker)) { -- printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %d, got %d\n", -+ printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %d, got %zd\n", - jeb->offset, sizeof(marker), retlen); - goto bad2; - } - - marker_ref->next_in_ino = NULL; - marker_ref->next_phys = NULL; -- marker_ref->flash_offset = jeb->offset; -- marker_ref->totlen = PAD(sizeof(marker)); -+ marker_ref->flash_offset = jeb->offset | REF_NORMAL; -+ marker_ref->__totlen = c->cleanmarker_size; - - jeb->first_node = jeb->last_node = marker_ref; - -- jeb->free_size = c->sector_size - marker_ref->totlen; -- jeb->used_size = marker_ref->totlen; -+ jeb->free_size = c->sector_size - c->cleanmarker_size; -+ jeb->used_size = c->cleanmarker_size; - jeb->dirty_size = 0; -+ jeb->wasted_size = 0; -+ } - -- spin_lock_bh(&c->erase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - c->erasing_size -= c->sector_size; - c->free_size += jeb->free_size; - c->used_size += jeb->used_size; - - ACCT_SANITY_CHECK(c,jeb); -- ACCT_PARANOIA_CHECK(jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); - - list_add_tail(&jeb->list, &c->free_list); - c->nr_erasing_blocks--; - c->nr_free_blocks++; -+ spin_unlock(&c->erase_completion_lock); - wake_up(&c->erase_wait); -- } -- spin_unlock_bh(&c->erase_completion_lock); - } -+ -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/file.c linux/fs/jffs2/file.c ---- linux-mips-2.4.24-pre2/fs/jffs2/file.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/file.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,319 +1,106 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - -+#include - #include --#include /* for min() */ - #include - #include -+#include - #include -+#include -+#include - #include - #include "nodelist.h" --#include - - extern int generic_file_open(struct inode *, struct file *) __attribute__((weak)); - extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) __attribute__((weak)); - - --int jffs2_null_fsync(struct file *filp, struct dentry *dentry, int datasync) -+int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync) - { -- /* Move along. Nothing to see here */ -+ struct inode *inode = dentry->d_inode; -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -+ -+ /* Trigger GC to flush any pending writes for this inode */ -+ jffs2_flush_wbuf_gc(c, inode->i_ino); -+ - return 0; - } - - struct file_operations jffs2_file_operations = - { -- llseek: generic_file_llseek, -- open: generic_file_open, -- read: generic_file_read, -- write: generic_file_write, -- ioctl: jffs2_ioctl, -- mmap: generic_file_mmap, -- fsync: jffs2_null_fsync -+ .llseek = generic_file_llseek, -+ .open = generic_file_open, -+ .read = generic_file_read, -+ .write = generic_file_write, -+ .ioctl = jffs2_ioctl, -+ .mmap = generic_file_readonly_mmap, -+ .fsync = jffs2_fsync, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,29) -+ .sendfile = generic_file_sendfile -+#endif - }; - - /* jffs2_file_inode_operations */ - - struct inode_operations jffs2_file_inode_operations = - { -- setattr: jffs2_setattr -+ .setattr = jffs2_setattr - }; - - struct address_space_operations jffs2_file_address_operations = - { -- readpage: jffs2_readpage, -- prepare_write: jffs2_prepare_write, -- commit_write: jffs2_commit_write -+ .readpage = jffs2_readpage, -+ .prepare_write =jffs2_prepare_write, -+ .commit_write = jffs2_commit_write - }; - --int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) --{ -- struct jffs2_full_dnode *old_metadata, *new_metadata; -- struct inode *inode = dentry->d_inode; -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); -- struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -- struct jffs2_raw_inode *ri; -- unsigned short dev; -- unsigned char *mdata = NULL; -- int mdatalen = 0; -- unsigned int ivalid; -- __u32 phys_ofs, alloclen; -- int ret; -- D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); -- ret = inode_change_ok(inode, iattr); -- if (ret) -- return ret; -- -- /* Special cases - we don't want more than one data node -- for these types on the medium at any time. So setattr -- must read the original data associated with the node -- (i.e. the device numbers or the target name) and write -- it out again with the appropriate data attached */ -- if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { -- /* For these, we don't actually need to read the old node */ -- dev = (MAJOR(to_kdev_t(dentry->d_inode->i_rdev)) << 8) | -- MINOR(to_kdev_t(dentry->d_inode->i_rdev)); -- mdata = (char *)&dev; -- mdatalen = sizeof(dev); -- D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen)); -- } else if (S_ISLNK(inode->i_mode)) { -- mdatalen = f->metadata->size; -- mdata = kmalloc(f->metadata->size, GFP_USER); -- if (!mdata) -- return -ENOMEM; -- ret = jffs2_read_dnode(c, f->metadata, mdata, 0, mdatalen); -- if (ret) { -- kfree(mdata); -- return ret; -- } -- D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen)); -- } -- -- ri = jffs2_alloc_raw_inode(); -- if (!ri) { -- if (S_ISLNK(inode->i_mode)) -- kfree(mdata); -- return -ENOMEM; -- } -- -- ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL); -- if (ret) { -- jffs2_free_raw_inode(ri); -- if (S_ISLNK(inode->i_mode)) -- kfree(mdata); -- return ret; -- } -- down(&f->sem); -- ivalid = iattr->ia_valid; -- -- ri->magic = JFFS2_MAGIC_BITMASK; -- ri->nodetype = JFFS2_NODETYPE_INODE; -- ri->totlen = sizeof(*ri) + mdatalen; -- ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); -- -- ri->ino = inode->i_ino; -- ri->version = ++f->highest_version; -- -- ri->mode = (ivalid & ATTR_MODE)?iattr->ia_mode:inode->i_mode; -- ri->uid = (ivalid & ATTR_UID)?iattr->ia_uid:inode->i_uid; -- ri->gid = (ivalid & ATTR_GID)?iattr->ia_gid:inode->i_gid; -- -- if (ivalid & ATTR_MODE && ri->mode & S_ISGID && -- !in_group_p(ri->gid) && !capable(CAP_FSETID)) -- ri->mode &= ~S_ISGID; -- -- ri->isize = (ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size; -- ri->atime = (ivalid & ATTR_ATIME)?iattr->ia_atime:inode->i_atime; -- ri->mtime = (ivalid & ATTR_MTIME)?iattr->ia_mtime:inode->i_mtime; -- ri->ctime = (ivalid & ATTR_CTIME)?iattr->ia_ctime:inode->i_ctime; -- -- ri->offset = 0; -- ri->csize = ri->dsize = mdatalen; -- ri->compr = JFFS2_COMPR_NONE; -- if (inode->i_size < ri->isize) { -- /* It's an extension. Make it a hole node */ -- ri->compr = JFFS2_COMPR_ZERO; -- ri->dsize = ri->isize - inode->i_size; -- ri->offset = inode->i_size; -- } -- ri->node_crc = crc32(0, ri, sizeof(*ri)-8); -- if (mdatalen) -- ri->data_crc = crc32(0, mdata, mdatalen); -- else -- ri->data_crc = 0; -- -- new_metadata = jffs2_write_dnode(inode, ri, mdata, mdatalen, phys_ofs, NULL); -- if (S_ISLNK(inode->i_mode)) -- kfree(mdata); -- -- jffs2_complete_reservation(c); -- -- if (IS_ERR(new_metadata)) { -- jffs2_free_raw_inode(ri); -- up(&f->sem); -- return PTR_ERR(new_metadata); -- } -- /* It worked. Update the inode */ -- inode->i_atime = ri->atime; -- inode->i_ctime = ri->ctime; -- inode->i_mtime = ri->mtime; -- inode->i_mode = ri->mode; -- inode->i_uid = ri->uid; -- inode->i_gid = ri->gid; -- -- -- old_metadata = f->metadata; -- -- if (inode->i_size > ri->isize) { -- vmtruncate(inode, ri->isize); -- jffs2_truncate_fraglist (c, &f->fraglist, ri->isize); -- } -- -- if (inode->i_size < ri->isize) { -- jffs2_add_full_dnode_to_inode(c, f, new_metadata); -- inode->i_size = ri->isize; -- f->metadata = NULL; -- } else { -- f->metadata = new_metadata; -- } -- if (old_metadata) { -- jffs2_mark_node_obsolete(c, old_metadata->raw); -- jffs2_free_full_dnode(old_metadata); -- } -- jffs2_free_raw_inode(ri); -- up(&f->sem); -- return 0; --} -- - int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg) - { - struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -- struct jffs2_node_frag *frag = f->fraglist; -- __u32 offset = pg->index << PAGE_CACHE_SHIFT; -- __u32 end = offset + PAGE_CACHE_SIZE; - unsigned char *pg_buf; - int ret; - -- D1(printk(KERN_DEBUG "jffs2_do_readpage_nolock(): ino #%lu, page at offset 0x%x\n", inode->i_ino, offset)); -+ D2(printk(KERN_DEBUG "jffs2_do_readpage_nolock(): ino #%lu, page at offset 0x%lx\n", inode->i_ino, pg->index << PAGE_CACHE_SHIFT)); - - if (!PageLocked(pg)) - PAGE_BUG(pg); - -- while(frag && frag->ofs + frag->size <= offset) { -- // D1(printk(KERN_DEBUG "skipping frag %d-%d; before the region we care about\n", frag->ofs, frag->ofs + frag->size)); -- frag = frag->next; -- } -- - pg_buf = kmap(pg); -+ /* FIXME: Can kmap fail? */ - -- /* XXX FIXME: Where a single physical node actually shows up in two -- frags, we read it twice. Don't do that. */ -- /* Now we're pointing at the first frag which overlaps our page */ -- while(offset < end) { -- D2(printk(KERN_DEBUG "jffs2_readpage: offset %d, end %d\n", offset, end)); -- if (!frag || frag->ofs > offset) { -- __u32 holesize = end - offset; -- if (frag) { -- D1(printk(KERN_NOTICE "Eep. Hole in ino %ld fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n", inode->i_ino, frag->ofs, offset)); -- holesize = min(holesize, frag->ofs - offset); -- D1(jffs2_print_frag_list(f)); -- } -- D1(printk(KERN_DEBUG "Filling non-frag hole from %d-%d\n", offset, offset+holesize)); -- memset(pg_buf, 0, holesize); -- pg_buf += holesize; -- offset += holesize; -- continue; -- } else if (frag->ofs < offset && (offset & (PAGE_CACHE_SIZE-1)) != 0) { -- D1(printk(KERN_NOTICE "Eep. Overlap in ino #%ld fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n", -- inode->i_ino, frag->ofs, offset)); -- D1(jffs2_print_frag_list(f)); -- memset(pg_buf, 0, end - offset); -- ClearPageUptodate(pg); -- SetPageError(pg); -- kunmap(pg); -- return -EIO; -- } else if (!frag->node) { -- __u32 holeend = min(end, frag->ofs + frag->size); -- D1(printk(KERN_DEBUG "Filling frag hole from %d-%d (frag 0x%x 0x%x)\n", offset, holeend, frag->ofs, frag->ofs + frag->size)); -- memset(pg_buf, 0, holeend - offset); -- pg_buf += holeend - offset; -- offset = holeend; -- frag = frag->next; -- continue; -- } else { -- __u32 readlen; -- __u32 fragofs; /* offset within the frag to start reading */ -+ ret = jffs2_read_inode_range(c, f, pg_buf, pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE); - -- fragofs = offset - frag->ofs; -- readlen = min(frag->size - fragofs, end - offset); -- D1(printk(KERN_DEBUG "Reading %d-%d from node at 0x%x\n", frag->ofs+fragofs, -- fragofs+frag->ofs+readlen, frag->node->raw->flash_offset & ~3)); -- ret = jffs2_read_dnode(c, frag->node, pg_buf, fragofs + frag->ofs - frag->node->ofs, readlen); -- D2(printk(KERN_DEBUG "node read done\n")); - if (ret) { -- D1(printk(KERN_DEBUG"jffs2_readpage error %d\n",ret)); -- memset(pg_buf, 0, readlen); - ClearPageUptodate(pg); - SetPageError(pg); -- kunmap(pg); -- return ret; -- } -- -- pg_buf += readlen; -- offset += readlen; -- frag = frag->next; -- D2(printk(KERN_DEBUG "node read was OK. Looping\n")); -- } -- } -- D2(printk(KERN_DEBUG "readpage finishing\n")); -+ } else { - SetPageUptodate(pg); - ClearPageError(pg); -+ } - - flush_dcache_page(pg); -- - kunmap(pg); -- D1(printk(KERN_DEBUG "readpage finished\n")); -+ -+ D2(printk(KERN_DEBUG "readpage finished\n")); - return 0; - } - - int jffs2_do_readpage_unlock(struct inode *inode, struct page *pg) - { - int ret = jffs2_do_readpage_nolock(inode, pg); -- UnlockPage(pg); -+ unlock_page(pg); - return ret; - } - -@@ -333,17 +120,17 @@ - { - struct inode *inode = pg->mapping->host; - struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); -- __u32 pageofs = pg->index << PAGE_CACHE_SHIFT; -+ uint32_t pageofs = pg->index << PAGE_CACHE_SHIFT; - int ret = 0; - -- D1(printk(KERN_DEBUG "jffs2_prepare_write() nrpages %ld\n", inode->i_mapping->nrpages)); -+ D1(printk(KERN_DEBUG "jffs2_prepare_write()\n")); - - if (pageofs > inode->i_size) { - /* Make new hole frag from old EOF to new page */ - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); - struct jffs2_raw_inode ri; - struct jffs2_full_dnode *fn; -- __u32 phys_ofs, alloc_len; -+ uint32_t phys_ofs, alloc_len; - - D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", - (unsigned int)inode->i_size, pageofs)); -@@ -355,29 +142,30 @@ - down(&f->sem); - memset(&ri, 0, sizeof(ri)); - -- ri.magic = JFFS2_MAGIC_BITMASK; -- ri.nodetype = JFFS2_NODETYPE_INODE; -- ri.totlen = sizeof(ri); -- ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4); -- -- ri.ino = f->inocache->ino; -- ri.version = ++f->highest_version; -- ri.mode = inode->i_mode; -- ri.uid = inode->i_uid; -- ri.gid = inode->i_gid; -- ri.isize = max((__u32)inode->i_size, pageofs); -- ri.atime = ri.ctime = ri.mtime = CURRENT_TIME; -- ri.offset = inode->i_size; -- ri.dsize = pageofs - inode->i_size; -- ri.csize = 0; -+ ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -+ ri.totlen = cpu_to_je32(sizeof(ri)); -+ ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); -+ -+ ri.ino = cpu_to_je32(f->inocache->ino); -+ ri.version = cpu_to_je32(++f->highest_version); -+ ri.mode = cpu_to_jemode(inode->i_mode); -+ ri.uid = cpu_to_je16(inode->i_uid); -+ ri.gid = cpu_to_je16(inode->i_gid); -+ ri.isize = cpu_to_je32(max((uint32_t)inode->i_size, pageofs)); -+ ri.atime = ri.ctime = ri.mtime = cpu_to_je32(get_seconds()); -+ ri.offset = cpu_to_je32(inode->i_size); -+ ri.dsize = cpu_to_je32(pageofs - inode->i_size); -+ ri.csize = cpu_to_je32(0); - ri.compr = JFFS2_COMPR_ZERO; -- ri.node_crc = crc32(0, &ri, sizeof(ri)-8); -- ri.data_crc = 0; -+ ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); -+ ri.data_crc = cpu_to_je32(0); -+ -+ fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_NORMAL); - -- fn = jffs2_write_dnode(inode, &ri, NULL, 0, phys_ofs, NULL); -- jffs2_complete_reservation(c); - if (IS_ERR(fn)) { - ret = PTR_ERR(fn); -+ jffs2_complete_reservation(c); - up(&f->sem); - return ret; - } -@@ -391,16 +179,17 @@ - D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in prepare_write, returned %d\n", ret)); - jffs2_mark_node_obsolete(c, fn->raw); - jffs2_free_full_dnode(fn); -+ jffs2_complete_reservation(c); - up(&f->sem); - return ret; - } -+ jffs2_complete_reservation(c); - inode->i_size = pageofs; - up(&f->sem); - } - -- - /* Read in the page if it wasn't already present, unless it's a whole page */ -- if (!Page_Uptodate(pg) && (start || end < PAGE_CACHE_SIZE)) { -+ if (!PageUptodate(pg) && (start || end < PAGE_CACHE_SIZE)) { - down(&f->sem); - ret = jffs2_do_readpage_nolock(inode, pg); - up(&f->sem); -@@ -417,14 +206,12 @@ - struct inode *inode = pg->mapping->host; - struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -- __u32 newsize = max_t(__u32, filp->f_dentry->d_inode->i_size, (pg->index << PAGE_CACHE_SHIFT) + end); -- __u32 file_ofs = (pg->index << PAGE_CACHE_SHIFT); -- __u32 writelen = min((__u32)PAGE_CACHE_SIZE, newsize - file_ofs); - struct jffs2_raw_inode *ri; - int ret = 0; -- ssize_t writtenlen = 0; -+ uint32_t writtenlen = 0; - -- D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n", inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags)); -+ D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n", -+ inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags)); - - if (!start && end == PAGE_CACHE_SIZE) { - /* We need to avoid deadlock with page_cache_read() in -@@ -435,109 +222,47 @@ - } - - ri = jffs2_alloc_raw_inode(); -- if (!ri) -- return -ENOMEM; -- -- while(writelen) { -- struct jffs2_full_dnode *fn; -- unsigned char *comprbuf = NULL; -- unsigned char comprtype = JFFS2_COMPR_NONE; -- __u32 phys_ofs, alloclen; -- __u32 datalen, cdatalen; - -- D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, file_ofs)); -- -- ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen, ALLOC_NORMAL); -- if (ret) { -- SetPageError(pg); -- D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); -- break; -+ if (!ri) { -+ D1(printk(KERN_DEBUG "jffs2_commit_write(): Allocation of raw inode failed\n")); -+ return -ENOMEM; - } -- down(&f->sem); -- datalen = writelen; -- cdatalen = min(alloclen - sizeof(*ri), writelen); -- -- comprbuf = kmalloc(cdatalen, GFP_KERNEL); -- if (comprbuf) { -- comprtype = jffs2_compress(page_address(pg)+ (file_ofs & (PAGE_CACHE_SIZE-1)), comprbuf, &datalen, &cdatalen); -- } -- if (comprtype == JFFS2_COMPR_NONE) { -- /* Either compression failed, or the allocation of comprbuf failed */ -- if (comprbuf) -- kfree(comprbuf); -- comprbuf = page_address(pg) + (file_ofs & (PAGE_CACHE_SIZE -1)); -- datalen = cdatalen; -- } -- /* Now comprbuf points to the data to be written, be it compressed or not. -- comprtype holds the compression type, and comprtype == JFFS2_COMPR_NONE means -- that the comprbuf doesn't need to be kfree()d. -- */ -- -- ri->magic = JFFS2_MAGIC_BITMASK; -- ri->nodetype = JFFS2_NODETYPE_INODE; -- ri->totlen = sizeof(*ri) + cdatalen; -- ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); -- -- ri->ino = inode->i_ino; -- ri->version = ++f->highest_version; -- ri->mode = inode->i_mode; -- ri->uid = inode->i_uid; -- ri->gid = inode->i_gid; -- ri->isize = max((__u32)inode->i_size, file_ofs + datalen); -- ri->atime = ri->ctime = ri->mtime = CURRENT_TIME; -- ri->offset = file_ofs; -- ri->csize = cdatalen; -- ri->dsize = datalen; -- ri->compr = comprtype; -- ri->node_crc = crc32(0, ri, sizeof(*ri)-8); -- ri->data_crc = crc32(0, comprbuf, cdatalen); -- -- fn = jffs2_write_dnode(inode, ri, comprbuf, cdatalen, phys_ofs, NULL); - -- jffs2_complete_reservation(c); -+ /* Set the fields that the generic jffs2_write_inode_range() code can't find */ -+ ri->ino = cpu_to_je32(inode->i_ino); -+ ri->mode = cpu_to_jemode(inode->i_mode); -+ ri->uid = cpu_to_je16(inode->i_uid); -+ ri->gid = cpu_to_je16(inode->i_gid); -+ ri->isize = cpu_to_je32((uint32_t)inode->i_size); -+ ri->atime = ri->ctime = ri->mtime = cpu_to_je32(get_seconds()); -+ -+ /* In 2.4, it was already kmapped by generic_file_write(). Doesn't -+ hurt to do it again. The alternative is ifdefs, which are ugly. */ -+ kmap(pg); -+ -+ ret = jffs2_write_inode_range(c, f, ri, page_address(pg) + start, -+ (pg->index << PAGE_CACHE_SHIFT) + start, -+ end - start, &writtenlen); - -- if (comprtype != JFFS2_COMPR_NONE) -- kfree(comprbuf); -+ kunmap(pg); - -- if (IS_ERR(fn)) { -- ret = PTR_ERR(fn); -- up(&f->sem); -- SetPageError(pg); -- break; -- } -- ret = jffs2_add_full_dnode_to_inode(c, f, fn); -- if (f->metadata) { -- jffs2_mark_node_obsolete(c, f->metadata->raw); -- jffs2_free_full_dnode(f->metadata); -- f->metadata = NULL; -- } -- up(&f->sem); - if (ret) { -- /* Eep */ -- D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in commit_write, returned %d\n", ret)); -- jffs2_mark_node_obsolete(c, fn->raw); -- jffs2_free_full_dnode(fn); -+ /* There was an error writing. */ - SetPageError(pg); -- break; - } -- inode->i_size = ri->isize; -+ -+ if (writtenlen) { -+ if (inode->i_size < (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen) { -+ inode->i_size = (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen; - inode->i_blocks = (inode->i_size + 511) >> 9; -- inode->i_ctime = inode->i_mtime = ri->ctime; -- if (!datalen) { -- printk(KERN_WARNING "Eep. We didn't actually write any bloody data\n"); -- ret = -EIO; -- SetPageError(pg); -- break; -+ -+ inode->i_ctime = inode->i_mtime = ITIME(je32_to_cpu(ri->ctime)); - } -- D1(printk(KERN_DEBUG "increasing writtenlen by %d\n", datalen)); -- writtenlen += datalen; -- file_ofs += datalen; -- writelen -= datalen; - } - - jffs2_free_raw_inode(ri); - -- if (writtenlen < end) { -+ if (start+writtenlen < end) { - /* generic_file_write has written more to the page cache than we've - actually written to the medium. Mark the page !Uptodate so that - it gets reread */ -@@ -545,13 +270,7 @@ - SetPageError(pg); - ClearPageUptodate(pg); - } -- if (writtenlen <= start) { -- /* We didn't even get to the start of the affected part */ -- ret = ret?ret:-ENOSPC; -- D1(printk(KERN_DEBUG "jffs2_commit_write(): Only %x bytes written to page. start (%x) not reached, returning %d\n", writtenlen, start, ret)); -- } -- writtenlen = min(end-start, writtenlen-start); - -- D1(printk(KERN_DEBUG "jffs2_commit_write() returning %d. nrpages is %ld\n",writtenlen?writtenlen:ret, inode->i_mapping->nrpages)); -+ D1(printk(KERN_DEBUG "jffs2_commit_write() returning %d\n",writtenlen?writtenlen:ret)); - return writtenlen?writtenlen:ret; - } -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/fs.c linux/fs/jffs2/fs.c ---- linux-mips-2.4.24-pre2/fs/jffs2/fs.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/fs.c 2004-11-17 18:17:59.301274096 +0100 -@@ -0,0 +1,618 @@ -+/* -+ * JFFS2 -- Journalling Flash File System, Version 2. -+ * -+ * Copyright (C) 2001-2003 Red Hat, Inc. -+ * -+ * Created by David Woodhouse -+ * -+ * For licensing information, see the file 'LICENCE' in this directory. -+ * -+ * $Id$ -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "nodelist.h" -+ -+ -+static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) -+{ -+ struct jffs2_full_dnode *old_metadata, *new_metadata; -+ struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -+ struct jffs2_raw_inode *ri; -+ unsigned short dev; -+ unsigned char *mdata = NULL; -+ int mdatalen = 0; -+ unsigned int ivalid; -+ uint32_t phys_ofs, alloclen; -+ int ret; -+ D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); -+ ret = inode_change_ok(inode, iattr); -+ if (ret) -+ return ret; -+ -+ /* Special cases - we don't want more than one data node -+ for these types on the medium at any time. So setattr -+ must read the original data associated with the node -+ (i.e. the device numbers or the target name) and write -+ it out again with the appropriate data attached */ -+ if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { -+ /* For these, we don't actually need to read the old node */ -+ dev = old_encode_dev(inode->i_rdev); -+ mdata = (char *)&dev; -+ mdatalen = sizeof(dev); -+ D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen)); -+ } else if (S_ISLNK(inode->i_mode)) { -+ mdatalen = f->metadata->size; -+ mdata = kmalloc(f->metadata->size, GFP_USER); -+ if (!mdata) -+ return -ENOMEM; -+ ret = jffs2_read_dnode(c, f->metadata, mdata, 0, mdatalen); -+ if (ret) { -+ kfree(mdata); -+ return ret; -+ } -+ D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen)); -+ } -+ -+ ri = jffs2_alloc_raw_inode(); -+ if (!ri) { -+ if (S_ISLNK(inode->i_mode)) -+ kfree(mdata); -+ return -ENOMEM; -+ } -+ -+ ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL); -+ if (ret) { -+ jffs2_free_raw_inode(ri); -+ if (S_ISLNK(inode->i_mode & S_IFMT)) -+ kfree(mdata); -+ return ret; -+ } -+ down(&f->sem); -+ ivalid = iattr->ia_valid; -+ -+ ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -+ ri->totlen = cpu_to_je32(sizeof(*ri) + mdatalen); -+ ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); -+ -+ ri->ino = cpu_to_je32(inode->i_ino); -+ ri->version = cpu_to_je32(++f->highest_version); -+ -+ ri->uid = cpu_to_je16((ivalid & ATTR_UID)?iattr->ia_uid:inode->i_uid); -+ ri->gid = cpu_to_je16((ivalid & ATTR_GID)?iattr->ia_gid:inode->i_gid); -+ -+ if (ivalid & ATTR_MODE) -+ if (iattr->ia_mode & S_ISGID && -+ !in_group_p(je16_to_cpu(ri->gid)) && !capable(CAP_FSETID)) -+ ri->mode = cpu_to_jemode(iattr->ia_mode & ~S_ISGID); -+ else -+ ri->mode = cpu_to_jemode(iattr->ia_mode); -+ else -+ ri->mode = cpu_to_jemode(inode->i_mode); -+ -+ -+ ri->isize = cpu_to_je32((ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size); -+ ri->atime = cpu_to_je32(I_SEC((ivalid & ATTR_ATIME)?iattr->ia_atime:inode->i_atime)); -+ ri->mtime = cpu_to_je32(I_SEC((ivalid & ATTR_MTIME)?iattr->ia_mtime:inode->i_mtime)); -+ ri->ctime = cpu_to_je32(I_SEC((ivalid & ATTR_CTIME)?iattr->ia_ctime:inode->i_ctime)); -+ -+ ri->offset = cpu_to_je32(0); -+ ri->csize = ri->dsize = cpu_to_je32(mdatalen); -+ ri->compr = JFFS2_COMPR_NONE; -+ if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { -+ /* It's an extension. Make it a hole node */ -+ ri->compr = JFFS2_COMPR_ZERO; -+ ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size); -+ ri->offset = cpu_to_je32(inode->i_size); -+ } -+ ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); -+ if (mdatalen) -+ ri->data_crc = cpu_to_je32(crc32(0, mdata, mdatalen)); -+ else -+ ri->data_crc = cpu_to_je32(0); -+ -+ new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, phys_ofs, ALLOC_NORMAL); -+ if (S_ISLNK(inode->i_mode)) -+ kfree(mdata); -+ -+ if (IS_ERR(new_metadata)) { -+ jffs2_complete_reservation(c); -+ jffs2_free_raw_inode(ri); -+ up(&f->sem); -+ return PTR_ERR(new_metadata); -+ } -+ /* It worked. Update the inode */ -+ inode->i_atime = ITIME(je32_to_cpu(ri->atime)); -+ inode->i_ctime = ITIME(je32_to_cpu(ri->ctime)); -+ inode->i_mtime = ITIME(je32_to_cpu(ri->mtime)); -+ inode->i_mode = jemode_to_cpu(ri->mode); -+ inode->i_uid = je16_to_cpu(ri->uid); -+ inode->i_gid = je16_to_cpu(ri->gid); -+ -+ -+ old_metadata = f->metadata; -+ -+ if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) -+ jffs2_truncate_fraglist (c, &f->fragtree, iattr->ia_size); -+ -+ if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { -+ jffs2_add_full_dnode_to_inode(c, f, new_metadata); -+ inode->i_size = iattr->ia_size; -+ f->metadata = NULL; -+ } else { -+ f->metadata = new_metadata; -+ } -+ if (old_metadata) { -+ jffs2_mark_node_obsolete(c, old_metadata->raw); -+ jffs2_free_full_dnode(old_metadata); -+ } -+ jffs2_free_raw_inode(ri); -+ -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ -+ /* We have to do the vmtruncate() without f->sem held, since -+ some pages may be locked and waiting for it in readpage(). -+ We are protected from a simultaneous write() extending i_size -+ back past iattr->ia_size, because do_truncate() holds the -+ generic inode semaphore. */ -+ if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) -+ vmtruncate(inode, iattr->ia_size); -+ -+ return 0; -+} -+ -+int jffs2_setattr(struct dentry *dentry, struct iattr *iattr) -+{ -+ return jffs2_do_setattr(dentry->d_inode, iattr); -+} -+ -+int jffs2_statfs(struct super_block *sb, struct kstatfs *buf) -+{ -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); -+ unsigned long avail; -+ -+ buf->f_type = JFFS2_SUPER_MAGIC; -+ buf->f_bsize = 1 << PAGE_SHIFT; -+ buf->f_blocks = c->flash_size >> PAGE_SHIFT; -+ buf->f_files = 0; -+ buf->f_ffree = 0; -+ buf->f_namelen = JFFS2_MAX_NAME_LEN; -+ -+ spin_lock(&c->erase_completion_lock); -+ -+ avail = c->dirty_size + c->free_size; -+ if (avail > c->sector_size * c->resv_blocks_write) -+ avail -= c->sector_size * c->resv_blocks_write; -+ else -+ avail = 0; -+ -+ buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT; -+ -+ D1(jffs2_dump_block_lists(c)); -+ -+ spin_unlock(&c->erase_completion_lock); -+ -+ return 0; -+} -+ -+ -+void jffs2_clear_inode (struct inode *inode) -+{ -+ /* We can forget about this inode for now - drop all -+ * the nodelists associated with it, etc. -+ */ -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -+ struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); -+ -+ D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); -+ -+ jffs2_do_clear_inode(c, f); -+} -+ -+void jffs2_read_inode (struct inode *inode) -+{ -+ struct jffs2_inode_info *f; -+ struct jffs2_sb_info *c; -+ struct jffs2_raw_inode latest_node; -+ int ret; -+ -+ D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino)); -+ -+ f = JFFS2_INODE_INFO(inode); -+ c = JFFS2_SB_INFO(inode->i_sb); -+ -+ jffs2_init_inode_info(f); -+ -+ ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); -+ -+ if (ret) { -+ make_bad_inode(inode); -+ up(&f->sem); -+ return; -+ } -+ inode->i_mode = jemode_to_cpu(latest_node.mode); -+ inode->i_uid = je16_to_cpu(latest_node.uid); -+ inode->i_gid = je16_to_cpu(latest_node.gid); -+ inode->i_size = je32_to_cpu(latest_node.isize); -+ inode->i_atime = ITIME(je32_to_cpu(latest_node.atime)); -+ inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime)); -+ inode->i_ctime = ITIME(je32_to_cpu(latest_node.ctime)); -+ -+ inode->i_nlink = f->inocache->nlink; -+ -+ inode->i_blksize = PAGE_SIZE; -+ inode->i_blocks = (inode->i_size + 511) >> 9; -+ -+ switch (inode->i_mode & S_IFMT) { -+ jint16_t rdev; -+ -+ case S_IFLNK: -+ inode->i_op = &jffs2_symlink_inode_operations; -+ break; -+ -+ case S_IFDIR: -+ { -+ struct jffs2_full_dirent *fd; -+ -+ for (fd=f->dents; fd; fd = fd->next) { -+ if (fd->type == DT_DIR && fd->ino) -+ inode->i_nlink++; -+ } -+ /* and '..' */ -+ inode->i_nlink++; -+ /* Root dir gets i_nlink 3 for some reason */ -+ if (inode->i_ino == 1) -+ inode->i_nlink++; -+ -+ inode->i_op = &jffs2_dir_inode_operations; -+ inode->i_fop = &jffs2_dir_operations; -+ break; -+ } -+ case S_IFREG: -+ inode->i_op = &jffs2_file_inode_operations; -+ inode->i_fop = &jffs2_file_operations; -+ inode->i_mapping->a_ops = &jffs2_file_address_operations; -+ inode->i_mapping->nrpages = 0; -+ break; -+ -+ case S_IFBLK: -+ case S_IFCHR: -+ /* Read the device numbers from the media */ -+ D1(printk(KERN_DEBUG "Reading device numbers from flash\n")); -+ if (jffs2_read_dnode(c, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) { -+ /* Eep */ -+ printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino); -+ up(&f->sem); -+ jffs2_do_clear_inode(c, f); -+ make_bad_inode(inode); -+ return; -+ } -+ -+ case S_IFSOCK: -+ case S_IFIFO: -+ inode->i_op = &jffs2_file_inode_operations; -+ init_special_inode(inode, inode->i_mode, -+ old_decode_dev((je16_to_cpu(rdev)))); -+ break; -+ -+ default: -+ printk(KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu\n", inode->i_mode, (unsigned long)inode->i_ino); -+ } -+ -+ up(&f->sem); -+ -+ D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n")); -+} -+ -+void jffs2_dirty_inode(struct inode *inode) -+{ -+ struct iattr iattr; -+ -+ if (!(inode->i_state & I_DIRTY_DATASYNC)) { -+ D2(printk(KERN_DEBUG "jffs2_dirty_inode() not calling setattr() for ino #%lu\n", inode->i_ino)); -+ return; -+ } -+ -+ D1(printk(KERN_DEBUG "jffs2_dirty_inode() calling setattr() for ino #%lu\n", inode->i_ino)); -+ -+ iattr.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_MTIME|ATTR_CTIME; -+ iattr.ia_mode = inode->i_mode; -+ iattr.ia_uid = inode->i_uid; -+ iattr.ia_gid = inode->i_gid; -+ iattr.ia_atime = inode->i_atime; -+ iattr.ia_mtime = inode->i_mtime; -+ iattr.ia_ctime = inode->i_ctime; -+ -+ jffs2_do_setattr(inode, &iattr); -+} -+ -+int jffs2_remount_fs (struct super_block *sb, int *flags, char *data) -+{ -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); -+ -+ if (c->flags & JFFS2_SB_FLAG_RO && !(sb->s_flags & MS_RDONLY)) -+ return -EROFS; -+ -+ /* We stop if it was running, then restart if it needs to. -+ This also catches the case where it was stopped and this -+ is just a remount to restart it */ -+ if (!(sb->s_flags & MS_RDONLY)) -+ jffs2_stop_garbage_collect_thread(c); -+ -+ if (!(*flags & MS_RDONLY)) -+ jffs2_start_garbage_collect_thread(c); -+ -+ sb->s_flags = (sb->s_flags & ~MS_RDONLY)|(*flags & MS_RDONLY); -+ -+ return 0; -+} -+ -+void jffs2_write_super (struct super_block *sb) -+{ -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); -+ sb->s_dirt = 0; -+ -+ if (sb->s_flags & MS_RDONLY) -+ return; -+ -+ D1(printk(KERN_DEBUG "jffs2_write_super()\n")); -+ jffs2_garbage_collect_trigger(c); -+ jffs2_erase_pending_blocks(c, 0); -+ jffs2_flush_wbuf_gc(c, 0); -+} -+ -+ -+/* jffs2_new_inode: allocate a new inode and inocache, add it to the hash, -+ fill in the raw_inode while you're at it. */ -+struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri) -+{ -+ struct inode *inode; -+ struct super_block *sb = dir_i->i_sb; -+ struct jffs2_sb_info *c; -+ struct jffs2_inode_info *f; -+ int ret; -+ -+ D1(printk(KERN_DEBUG "jffs2_new_inode(): dir_i %ld, mode 0x%x\n", dir_i->i_ino, mode)); -+ -+ c = JFFS2_SB_INFO(sb); -+ -+ inode = new_inode(sb); -+ -+ if (!inode) -+ return ERR_PTR(-ENOMEM); -+ -+ f = JFFS2_INODE_INFO(inode); -+ jffs2_init_inode_info(f); -+ -+ memset(ri, 0, sizeof(*ri)); -+ /* Set OS-specific defaults for new inodes */ -+ ri->uid = cpu_to_je16(current->fsuid); -+ -+ if (dir_i->i_mode & S_ISGID) { -+ ri->gid = cpu_to_je16(dir_i->i_gid); -+ if (S_ISDIR(mode)) -+ mode |= S_ISGID; -+ } else { -+ ri->gid = cpu_to_je16(current->fsgid); -+ } -+ ri->mode = cpu_to_jemode(mode); -+ ret = jffs2_do_new_inode (c, f, mode, ri); -+ if (ret) { -+ make_bad_inode(inode); -+ iput(inode); -+ return ERR_PTR(ret); -+ } -+ inode->i_nlink = 1; -+ inode->i_ino = je32_to_cpu(ri->ino); -+ inode->i_mode = jemode_to_cpu(ri->mode); -+ inode->i_gid = je16_to_cpu(ri->gid); -+ inode->i_uid = je16_to_cpu(ri->uid); -+ inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME; -+ ri->atime = ri->mtime = ri->ctime = cpu_to_je32(I_SEC(inode->i_mtime)); -+ -+ inode->i_blksize = PAGE_SIZE; -+ inode->i_blocks = 0; -+ inode->i_size = 0; -+ -+ insert_inode_hash(inode); -+ -+ return inode; -+} -+ -+ -+int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) -+{ -+ struct jffs2_sb_info *c; -+ struct inode *root_i; -+ int ret; -+ size_t blocks; -+ -+ c = JFFS2_SB_INFO(sb); -+ -+ c->flash_size = c->mtd->size; -+ -+ /* -+ * Check, if we have to concatenate physical blocks to larger virtual blocks -+ * to reduce the memorysize for c->blocks. (kmalloc allows max. 128K allocation) -+ */ -+ blocks = c->flash_size / c->mtd->erasesize; -+ while ((blocks * sizeof (struct jffs2_eraseblock)) > (128 * 1024)) -+ blocks >>= 1; -+ -+ c->sector_size = c->flash_size / blocks; -+ if (c->sector_size != c->mtd->erasesize) -+ printk(KERN_INFO "jffs2: Erase block size too small (%dKiB). Using virtual blocks size (%dKiB) instead\n", -+ c->mtd->erasesize / 1024, c->sector_size / 1024); -+ -+ if (c->flash_size < 5*c->sector_size) { -+ printk(KERN_ERR "jffs2: Too few erase blocks (%d)\n", c->flash_size / c->sector_size); -+ return -EINVAL; -+ } -+ -+ c->cleanmarker_size = sizeof(struct jffs2_unknown_node); -+ /* Joern -- stick alignment for weird 8-byte-page flash here */ -+ -+ if (jffs2_cleanmarker_oob(c)) { -+ /* NAND (or other bizarre) flash... do setup accordingly */ -+ ret = jffs2_nand_flash_setup(c); -+ if (ret) -+ return ret; -+ } -+ -+ c->inocache_list = kmalloc(INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *), GFP_KERNEL); -+ if (!c->inocache_list) { -+ ret = -ENOMEM; -+ goto out_wbuf; -+ } -+ memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *)); -+ -+ if ((ret = jffs2_do_mount_fs(c))) -+ goto out_inohash; -+ -+ ret = -EINVAL; -+ -+ D1(printk(KERN_DEBUG "jffs2_do_fill_super(): Getting root inode\n")); -+ root_i = iget(sb, 1); -+ if (is_bad_inode(root_i)) { -+ D1(printk(KERN_WARNING "get root inode failed\n")); -+ goto out_nodes; -+ } -+ -+ D1(printk(KERN_DEBUG "jffs2_do_fill_super(): d_alloc_root()\n")); -+ sb->s_root = d_alloc_root(root_i); -+ if (!sb->s_root) -+ goto out_root_i; -+ -+#if LINUX_VERSION_CODE >= 0x20403 -+ sb->s_maxbytes = 0xFFFFFFFF; -+#endif -+ sb->s_blocksize = PAGE_CACHE_SIZE; -+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT; -+ sb->s_magic = JFFS2_SUPER_MAGIC; -+ if (!(sb->s_flags & MS_RDONLY)) -+ jffs2_start_garbage_collect_thread(c); -+ return 0; -+ -+ out_root_i: -+ iput(root_i); -+ out_nodes: -+ jffs2_free_ino_caches(c); -+ jffs2_free_raw_node_refs(c); -+ kfree(c->blocks); -+ out_inohash: -+ kfree(c->inocache_list); -+ out_wbuf: -+ jffs2_nand_flash_cleanup(c); -+ -+ return ret; -+} -+ -+void jffs2_gc_release_inode(struct jffs2_sb_info *c, -+ struct jffs2_inode_info *f) -+{ -+ iput(OFNI_EDONI_2SFFJ(f)); -+} -+ -+struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, -+ int inum, int nlink) -+{ -+ struct inode *inode; -+ struct jffs2_inode_cache *ic; -+ if (!nlink) { -+ /* The inode has zero nlink but its nodes weren't yet marked -+ obsolete. This has to be because we're still waiting for -+ the final (close() and) iput() to happen. -+ -+ There's a possibility that the final iput() could have -+ happened while we were contemplating. In order to ensure -+ that we don't cause a new read_inode() (which would fail) -+ for the inode in question, we use ilookup() in this case -+ instead of iget(). -+ -+ The nlink can't _become_ zero at this point because we're -+ holding the alloc_sem, and jffs2_do_unlink() would also -+ need that while decrementing nlink on any inode. -+ */ -+ inode = ilookup(OFNI_BS_2SFFJ(c), inum); -+ if (!inode) { -+ D1(printk(KERN_DEBUG "ilookup() failed for ino #%u; inode is probably deleted.\n", -+ inum)); -+ -+ spin_lock(&c->inocache_lock); -+ ic = jffs2_get_ino_cache(c, inum); -+ if (!ic) { -+ D1(printk(KERN_DEBUG "Inode cache for ino #%u is gone.\n", inum)); -+ spin_unlock(&c->inocache_lock); -+ return NULL; -+ } -+ if (ic->state != INO_STATE_CHECKEDABSENT) { -+ /* Wait for progress. Don't just loop */ -+ D1(printk(KERN_DEBUG "Waiting for ino #%u in state %d\n", -+ ic->ino, ic->state)); -+ sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); -+ } else { -+ spin_unlock(&c->inocache_lock); -+ } -+ -+ return NULL; -+ } -+ } else { -+ /* Inode has links to it still; they're not going away because -+ jffs2_do_unlink() would need the alloc_sem and we have it. -+ Just iget() it, and if read_inode() is necessary that's OK. -+ */ -+ inode = iget(OFNI_BS_2SFFJ(c), inum); -+ if (!inode) -+ return ERR_PTR(-ENOMEM); -+ } -+ if (is_bad_inode(inode)) { -+ printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u. nlink %d\n", -+ inum, nlink); -+ /* NB. This will happen again. We need to do something appropriate here. */ -+ iput(inode); -+ return ERR_PTR(-EIO); -+ } -+ -+ return JFFS2_INODE_INFO(inode); -+} -+ -+unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, -+ struct jffs2_inode_info *f, -+ unsigned long offset, -+ unsigned long *priv) -+{ -+ struct inode *inode = OFNI_EDONI_2SFFJ(f); -+ struct page *pg; -+ -+ pg = read_cache_page(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, -+ (void *)jffs2_do_readpage_unlock, inode); -+ if (IS_ERR(pg)) -+ return (void *)pg; -+ -+ *priv = (unsigned long)pg; -+ return kmap(pg); -+} -+ -+void jffs2_gc_release_page(struct jffs2_sb_info *c, -+ unsigned char *ptr, -+ unsigned long *priv) -+{ -+ struct page *pg = (void *)*priv; -+ -+ kunmap(pg); -+ page_cache_release(pg); -+} -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/gc.c linux/fs/jffs2/gc.c ---- linux-mips-2.4.24-pre2/fs/jffs2/gc.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/gc.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,76 +1,67 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include - #include - #include --#include --#include --#include - #include --#include "nodelist.h" - #include -+#include -+#include -+#include "nodelist.h" - -+static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, -+ struct jffs2_inode_cache *ic, -+ struct jffs2_raw_node_ref *raw); - static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dnode *fd); -+ struct jffs2_inode_info *f, struct jffs2_full_dnode *fd); - static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dirent *fd); -+ struct jffs2_inode_info *f, struct jffs2_full_dirent *fd); - static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dirent *fd); -+ struct jffs2_inode_info *f, struct jffs2_full_dirent *fd); - static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *indeo, struct jffs2_full_dnode *fn, -- __u32 start, __u32 end); -+ struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, -+ uint32_t start, uint32_t end); - static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dnode *fn, -- __u32 start, __u32 end); -+ struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, -+ uint32_t start, uint32_t end); -+static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_node_ref *raw, struct jffs2_inode_info *f); - - /* Called with erase_completion_lock held */ - static struct jffs2_eraseblock *jffs2_find_gc_block(struct jffs2_sb_info *c) - { - struct jffs2_eraseblock *ret; - struct list_head *nextlist = NULL; -+ int n = jiffies % 128; - - /* Pick an eraseblock to garbage collect next. This is where we'll - put the clever wear-levelling algorithms. Eventually. */ -- if (!list_empty(&c->bad_used_list) && c->nr_free_blocks > JFFS2_RESERVED_BLOCKS_GCBAD) { -+ /* We possibly want to favour the dirtier blocks more when the -+ number of free blocks is low. */ -+ if (!list_empty(&c->bad_used_list) && c->nr_free_blocks > c->resv_blocks_gcbad) { - D1(printk(KERN_DEBUG "Picking block from bad_used_list to GC next\n")); - nextlist = &c->bad_used_list; -- } else if (jiffies % 100 && !list_empty(&c->dirty_list)) { -- /* Most of the time, pick one off the dirty list */ -+ } else if (n < 50 && !list_empty(&c->erasable_list)) { -+ /* Note that most of them will have gone directly to be erased. -+ So don't favour the erasable_list _too_ much. */ -+ D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next\n")); -+ nextlist = &c->erasable_list; -+ } else if (n < 110 && !list_empty(&c->very_dirty_list)) { -+ /* Most of the time, pick one off the very_dirty list */ -+ D1(printk(KERN_DEBUG "Picking block from very_dirty_list to GC next\n")); -+ nextlist = &c->very_dirty_list; -+ } else if (n < 126 && !list_empty(&c->dirty_list)) { - D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next\n")); - nextlist = &c->dirty_list; - } else if (!list_empty(&c->clean_list)) { -@@ -80,9 +71,16 @@ - D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next (clean_list was empty)\n")); - - nextlist = &c->dirty_list; -+ } else if (!list_empty(&c->very_dirty_list)) { -+ D1(printk(KERN_DEBUG "Picking block from very_dirty_list to GC next (clean_list and dirty_list were empty)\n")); -+ nextlist = &c->very_dirty_list; -+ } else if (!list_empty(&c->erasable_list)) { -+ D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next (clean_list and {very_,}dirty_list were empty)\n")); -+ -+ nextlist = &c->erasable_list; - } else { -- /* Eep. Both were empty */ -- printk(KERN_NOTICE "jffs2: No clean _or_ dirty blocks to GC from! Where are they all?\n"); -+ /* Eep. All were empty */ -+ printk(KERN_NOTICE "jffs2: No clean, dirty _or_ erasable blocks to GC from! Where are they all?\n"); - return NULL; - } - -@@ -94,6 +92,17 @@ - printk(KERN_WARNING "Eep. ret->gc_node for block at 0x%08x is NULL\n", ret->offset); - BUG(); - } -+ -+ /* Have we accidentally picked a clean block with wasted space ? */ -+ if (ret->wasted_size) { -+ D1(printk(KERN_DEBUG "Converting wasted_size %08x to dirty_size\n", ret->wasted_size)); -+ ret->dirty_size += ret->wasted_size; -+ c->wasted_size -= ret->wasted_size; -+ c->dirty_size += ret->wasted_size; -+ ret->wasted_size = 0; -+ } -+ -+ D1(jffs2_dump_block_lists(c)); - return ret; - } - -@@ -103,21 +112,90 @@ - */ - int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) - { -- struct jffs2_eraseblock *jeb; - struct jffs2_inode_info *f; -- struct jffs2_raw_node_ref *raw; -- struct jffs2_node_frag *frag; -- struct jffs2_full_dnode *fn = NULL; -- struct jffs2_full_dirent *fd; - struct jffs2_inode_cache *ic; -- __u32 start = 0, end = 0, nrfrags = 0; -- struct inode *inode; -- int ret = 0; -+ struct jffs2_eraseblock *jeb; -+ struct jffs2_raw_node_ref *raw; -+ int ret = 0, inum, nlink; - - if (down_interruptible(&c->alloc_sem)) - return -EINTR; - -- spin_lock_bh(&c->erase_completion_lock); -+ for (;;) { -+ spin_lock(&c->erase_completion_lock); -+ if (!c->unchecked_size) -+ break; -+ -+ /* We can't start doing GC yet. We haven't finished checking -+ the node CRCs etc. Do it now. */ -+ -+ /* checked_ino is protected by the alloc_sem */ -+ if (c->checked_ino > c->highest_ino) { -+ printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", -+ c->unchecked_size); -+ D1(jffs2_dump_block_lists(c)); -+ spin_unlock(&c->erase_completion_lock); -+ BUG(); -+ } -+ -+ spin_unlock(&c->erase_completion_lock); -+ -+ spin_lock(&c->inocache_lock); -+ -+ ic = jffs2_get_ino_cache(c, c->checked_ino++); -+ -+ if (!ic) { -+ spin_unlock(&c->inocache_lock); -+ continue; -+ } -+ -+ if (!ic->nlink) { -+ D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n", -+ ic->ino)); -+ spin_unlock(&c->inocache_lock); -+ continue; -+ } -+ switch(ic->state) { -+ case INO_STATE_CHECKEDABSENT: -+ case INO_STATE_PRESENT: -+ D1(printk(KERN_DEBUG "Skipping ino #%u already checked\n", ic->ino)); -+ spin_unlock(&c->inocache_lock); -+ continue; -+ -+ case INO_STATE_GC: -+ case INO_STATE_CHECKING: -+ printk(KERN_WARNING "Inode #%u is in state %d during CRC check phase!\n", ic->ino, ic->state); -+ spin_unlock(&c->inocache_lock); -+ BUG(); -+ -+ case INO_STATE_READING: -+ /* We need to wait for it to finish, lest we move on -+ and trigger the BUG() above while we haven't yet -+ finished checking all its nodes */ -+ D1(printk(KERN_DEBUG "Waiting for ino #%u to finish reading\n", ic->ino)); -+ up(&c->alloc_sem); -+ sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); -+ return 0; -+ -+ default: -+ BUG(); -+ -+ case INO_STATE_UNCHECKED: -+ ; -+ } -+ ic->state = INO_STATE_CHECKING; -+ spin_unlock(&c->inocache_lock); -+ -+ D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() triggering inode scan of ino#%u\n", ic->ino)); -+ -+ ret = jffs2_do_crccheck_inode(c, ic); -+ if (ret) -+ printk(KERN_WARNING "Returned error for crccheck of ino #%u. Expect badness...\n", ic->ino); -+ -+ jffs2_set_inocache_state(c, ic, INO_STATE_CHECKEDABSENT); -+ up(&c->alloc_sem); -+ return ret; -+ } - - /* First, work out which block we're garbage-collecting */ - jeb = c->gcblock; -@@ -127,12 +205,14 @@ - - if (!jeb) { - printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n"); -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - up(&c->alloc_sem); - return -EIO; - } - -- D1(printk(KERN_DEBUG "garbage collect from block at phys 0x%08x\n", jeb->offset)); -+ D1(printk(KERN_DEBUG "GC from block %08x, used_size %08x, dirty_size %08x, free_size %08x\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size)); -+ D1(if (c->nextblock) -+ printk(KERN_DEBUG "Nextblock at %08x, used_size %08x, dirty_size %08x, wasted_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->free_size)); - - if (!jeb->used_size) { - up(&c->alloc_sem); -@@ -141,92 +221,211 @@ - - raw = jeb->gc_node; - -- while(raw->flash_offset & 1) { -- D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", raw->flash_offset &~3)); -- jeb->gc_node = raw = raw->next_phys; -- if (!raw) { -+ while(ref_obsolete(raw)) { -+ D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw))); -+ raw = raw->next_phys; -+ if (unlikely(!raw)) { - printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n"); - printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size); -- spin_unlock_bh(&c->erase_completion_lock); -+ jeb->gc_node = raw; -+ spin_unlock(&c->erase_completion_lock); - up(&c->alloc_sem); - BUG(); - } - } -- D1(printk(KERN_DEBUG "Going to garbage collect node at 0x%08x\n", raw->flash_offset &~3)); -+ jeb->gc_node = raw; -+ -+ D1(printk(KERN_DEBUG "Going to garbage collect node at 0x%08x\n", ref_offset(raw))); -+ - if (!raw->next_in_ino) { - /* Inode-less node. Clean marker, snapshot or something like that */ -- spin_unlock_bh(&c->erase_completion_lock); -+ /* FIXME: If it's something that needs to be copied, including something -+ we don't grok that has JFFS2_NODETYPE_RWCOMPAT_COPY, we should do so */ -+ spin_unlock(&c->erase_completion_lock); - jffs2_mark_node_obsolete(c, raw); - up(&c->alloc_sem); - goto eraseit_lock; - } - - ic = jffs2_raw_ref_to_ic(raw); -- D1(printk(KERN_DEBUG "Inode number is #%u\n", ic->ino)); -- -- spin_unlock_bh(&c->erase_completion_lock); - -- D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass collecting from block @0x%08x. Node @0x%08x, ino #%u\n", jeb->offset, raw->flash_offset&~3, ic->ino)); -- if (!ic->nlink) { -- /* The inode has zero nlink but its nodes weren't yet marked -- obsolete. This has to be because we're still waiting for -- the final (close() and) iput() to happen. -- -- There's a possibility that the final iput() could have -- happened while we were contemplating. In order to ensure -- that we don't cause a new read_inode() (which would fail) -- for the inode in question, we use ilookup() in this case -- instead of iget(). -- -- The nlink can't _become_ zero at this point because we're -- holding the alloc_sem, and jffs2_do_unlink() would also -- need that while decrementing nlink on any inode. -+ /* We need to hold the inocache. Either the erase_completion_lock or -+ the inocache_lock are sufficient; we trade down since the inocache_lock -+ causes less contention. */ -+ spin_lock(&c->inocache_lock); -+ -+ spin_unlock(&c->erase_completion_lock); -+ -+ D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass collecting from block @0x%08x. Node @0x%08x(%d), ino #%u\n", jeb->offset, ref_offset(raw), ref_flags(raw), ic->ino)); -+ -+ /* Three possibilities: -+ 1. Inode is already in-core. We must iget it and do proper -+ updating to its fragtree, etc. -+ 2. Inode is not in-core, node is REF_PRISTINE. We lock the -+ inocache to prevent a read_inode(), copy the node intact. -+ 3. Inode is not in-core, node is not pristine. We must iget() -+ and take the slow path. - */ -- inode = ilookup(OFNI_BS_2SFFJ(c), ic->ino); -- if (!inode) { -- D1(printk(KERN_DEBUG "ilookup() failed for ino #%u; inode is probably deleted.\n", -+ -+ switch(ic->state) { -+ case INO_STATE_CHECKEDABSENT: -+ /* It's been checked, but it's not currently in-core. -+ We can just copy any pristine nodes, but have -+ to prevent anyone else from doing read_inode() while -+ we're at it, so we set the state accordingly */ -+ if (ref_flags(raw) == REF_PRISTINE) -+ ic->state = INO_STATE_GC; -+ else { -+ D1(printk(KERN_DEBUG "Ino #%u is absent but node not REF_PRISTINE. Reading.\n", - ic->ino)); -- up(&c->alloc_sem); -- return 0; - } -- } else { -- /* Inode has links to it still; they're not going away because -- jffs2_do_unlink() would need the alloc_sem and we have it. -- Just iget() it, and if read_inode() is necessary that's OK. -+ break; -+ -+ case INO_STATE_PRESENT: -+ /* It's in-core. GC must iget() it. */ -+ break; -+ -+ case INO_STATE_UNCHECKED: -+ case INO_STATE_CHECKING: -+ case INO_STATE_GC: -+ /* Should never happen. We should have finished checking -+ by the time we actually start doing any GC, and since -+ we're holding the alloc_sem, no other garbage collection -+ can happen. - */ -- inode = iget(OFNI_BS_2SFFJ(c), ic->ino); -- if (!inode) { -+ printk(KERN_CRIT "Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n", -+ ic->ino, ic->state); - up(&c->alloc_sem); -- return -ENOMEM; -+ spin_unlock(&c->inocache_lock); -+ BUG(); -+ -+ case INO_STATE_READING: -+ /* Someone's currently trying to read it. We must wait for -+ them to finish and then go through the full iget() route -+ to do the GC. However, sometimes read_inode() needs to get -+ the alloc_sem() (for marking nodes invalid) so we must -+ drop the alloc_sem before sleeping. */ -+ -+ up(&c->alloc_sem); -+ D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() waiting for ino #%u in state %d\n", -+ ic->ino, ic->state)); -+ sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); -+ /* And because we dropped the alloc_sem we must start again from the -+ beginning. Ponder chance of livelock here -- we're returning success -+ without actually making any progress. -+ -+ Q: What are the chances that the inode is back in INO_STATE_READING -+ again by the time we next enter this function? And that this happens -+ enough times to cause a real delay? -+ -+ A: Small enough that I don't care :) -+ */ -+ return 0; - } -+ -+ /* OK. Now if the inode is in state INO_STATE_GC, we are going to copy the -+ node intact, and we don't have to muck about with the fragtree etc. -+ because we know it's not in-core. If it _was_ in-core, we go through -+ all the iget() crap anyway */ -+ -+ if (ic->state == INO_STATE_GC) { -+ spin_unlock(&c->inocache_lock); -+ -+ ret = jffs2_garbage_collect_pristine(c, ic, raw); -+ -+ spin_lock(&c->inocache_lock); -+ ic->state = INO_STATE_CHECKEDABSENT; -+ wake_up(&c->inocache_wq); -+ -+ if (ret != -EBADFD) { -+ spin_unlock(&c->inocache_lock); -+ goto release_sem; - } -- if (is_bad_inode(inode)) { -- printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u\n", ic->ino); -- /* NB. This will happen again. We need to do something appropriate here. */ -+ -+ /* Fall through if it wanted us to, with inocache_lock held */ -+ } -+ -+ /* Prevent the fairly unlikely race where the gcblock is -+ entirely obsoleted by the final close of a file which had -+ the only valid nodes in the block, followed by erasure, -+ followed by freeing of the ic because the erased block(s) -+ held _all_ the nodes of that inode.... never been seen but -+ it's vaguely possible. */ -+ -+ inum = ic->ino; -+ nlink = ic->nlink; -+ spin_unlock(&c->inocache_lock); -+ -+ f = jffs2_gc_fetch_inode(c, inum, nlink); -+ if (IS_ERR(f)) -+ return PTR_ERR(f); -+ if (!f) -+ return 0; -+ -+ ret = jffs2_garbage_collect_live(c, jeb, raw, f); -+ -+ jffs2_gc_release_inode(c, f); -+ -+ release_sem: - up(&c->alloc_sem); -- iput(inode); -- return -EIO; -+ -+ eraseit_lock: -+ /* If we've finished this block, start it erasing */ -+ spin_lock(&c->erase_completion_lock); -+ -+ eraseit: -+ if (c->gcblock && !c->gcblock->used_size) { -+ D1(printk(KERN_DEBUG "Block at 0x%08x completely obsoleted by GC. Moving to erase_pending_list\n", c->gcblock->offset)); -+ /* We're GC'ing an empty block? */ -+ list_add_tail(&c->gcblock->list, &c->erase_pending_list); -+ c->gcblock = NULL; -+ c->nr_erasing_blocks++; -+ jffs2_erase_pending_trigger(c); - } -+ spin_unlock(&c->erase_completion_lock); -+ -+ return ret; -+} -+ -+static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_node_ref *raw, struct jffs2_inode_info *f) -+{ -+ struct jffs2_node_frag *frag; -+ struct jffs2_full_dnode *fn = NULL; -+ struct jffs2_full_dirent *fd; -+ uint32_t start = 0, end = 0, nrfrags = 0; -+ int ret = 0; - -- f = JFFS2_INODE_INFO(inode); - down(&f->sem); -+ - /* Now we have the lock for this inode. Check that it's still the one at the head - of the list. */ - -- if (raw->flash_offset & 1) { -+ spin_lock(&c->erase_completion_lock); -+ -+ if (c->gcblock != jeb) { -+ spin_unlock(&c->erase_completion_lock); -+ D1(printk(KERN_DEBUG "GC block is no longer gcblock. Restart\n")); -+ goto upnout; -+ } -+ if (ref_obsolete(raw)) { -+ spin_unlock(&c->erase_completion_lock); - D1(printk(KERN_DEBUG "node to be GC'd was obsoleted in the meantime.\n")); - /* They'll call again */ - goto upnout; - } -+ spin_unlock(&c->erase_completion_lock); -+ - /* OK. Looks safe. And nobody can get us now because we have the semaphore. Move the block */ - if (f->metadata && f->metadata->raw == raw) { - fn = f->metadata; -- ret = jffs2_garbage_collect_metadata(c, jeb, inode, fn); -+ ret = jffs2_garbage_collect_metadata(c, jeb, f, fn); - goto upnout; - } - -- for (frag = f->fraglist; frag; frag = frag->next) { -+ /* FIXME. Read node and do lookup? */ -+ for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) { - if (frag->node && frag->node->raw == raw) { - fn = frag->node; - end = frag->ofs + frag->size; -@@ -237,13 +436,22 @@ - } - } - if (fn) { -+ if (ref_flags(raw) == REF_PRISTINE) { -+ ret = jffs2_garbage_collect_pristine(c, f->inocache, raw); -+ if (!ret) { -+ /* Urgh. Return it sensibly. */ -+ frag->node->raw = f->inocache->nodes; -+ } -+ if (ret != -EBADFD) -+ goto upnout; -+ } - /* We found a datanode. Do the GC */ - if((start >> PAGE_CACHE_SHIFT) < ((end-1) >> PAGE_CACHE_SHIFT)) { - /* It crosses a page boundary. Therefore, it must be a hole. */ -- ret = jffs2_garbage_collect_hole(c, jeb, inode, fn, start, end); -+ ret = jffs2_garbage_collect_hole(c, jeb, f, fn, start, end); - } else { - /* It could still be a hole. But we GC the page this way anyway */ -- ret = jffs2_garbage_collect_dnode(c, jeb, inode, fn, start, end); -+ ret = jffs2_garbage_collect_dnode(c, jeb, f, fn, start, end); - } - goto upnout; - } -@@ -255,12 +463,13 @@ - } - - if (fd && fd->ino) { -- ret = jffs2_garbage_collect_dirent(c, jeb, inode, fd); -+ ret = jffs2_garbage_collect_dirent(c, jeb, f, fd); - } else if (fd) { -- ret = jffs2_garbage_collect_deletion_dirent(c, jeb, inode, fd); -+ ret = jffs2_garbage_collect_deletion_dirent(c, jeb, f, fd); - } else { -- printk(KERN_WARNING "Raw node at 0x%08x wasn't in node lists for ino #%lu\n", raw->flash_offset&~3, inode->i_ino); -- if (raw->flash_offset & 1) { -+ printk(KERN_WARNING "Raw node at 0x%08x wasn't in node lists for ino #%u\n", -+ ref_offset(raw), f->inocache->ino); -+ if (ref_obsolete(raw)) { - printk(KERN_WARNING "But it's obsolete so we don't mind too much\n"); - } else { - ret = -EIO; -@@ -268,46 +477,197 @@ - } - upnout: - up(&f->sem); -- up(&c->alloc_sem); -- iput(inode); - -- eraseit_lock: -- /* If we've finished this block, start it erasing */ -- spin_lock_bh(&c->erase_completion_lock); -+ return ret; -+} - -- eraseit: -- if (c->gcblock && !c->gcblock->used_size) { -- D1(printk(KERN_DEBUG "Block at 0x%08x completely obsoleted by GC. Moving to erase_pending_list\n", c->gcblock->offset)); -- /* We're GC'ing an empty block? */ -- list_add_tail(&c->gcblock->list, &c->erase_pending_list); -- c->gcblock = NULL; -- c->nr_erasing_blocks++; -- jffs2_erase_pending_trigger(c); -+static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, -+ struct jffs2_inode_cache *ic, -+ struct jffs2_raw_node_ref *raw) -+{ -+ union jffs2_node_union *node; -+ struct jffs2_raw_node_ref *nraw; -+ size_t retlen; -+ int ret; -+ uint32_t phys_ofs, alloclen; -+ uint32_t crc, rawlen; -+ int retried = 0; -+ -+ D1(printk(KERN_DEBUG "Going to GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw))); -+ -+ rawlen = ref_totlen(c, c->gcblock, raw); -+ -+ /* Ask for a small amount of space (or the totlen if smaller) because we -+ don't want to force wastage of the end of a block if splitting would -+ work. */ -+ ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN, -+ rawlen), &phys_ofs, &alloclen); -+ if (ret) -+ return ret; -+ -+ if (alloclen < rawlen) { -+ /* Doesn't fit untouched. We'll go the old route and split it */ -+ return -EBADFD; -+ } -+ -+ node = kmalloc(rawlen, GFP_KERNEL); -+ if (!node) -+ return -ENOMEM; -+ -+ ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)node); -+ if (!ret && retlen != rawlen) -+ ret = -EIO; -+ if (ret) -+ goto out_node; -+ -+ crc = crc32(0, node, sizeof(struct jffs2_unknown_node)-4); -+ if (je32_to_cpu(node->u.hdr_crc) != crc) { -+ printk(KERN_WARNING "Header CRC failed on REF_PRISTINE node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ref_offset(raw), je32_to_cpu(node->u.hdr_crc), crc); -+ goto bail; -+ } -+ -+ switch(je16_to_cpu(node->u.nodetype)) { -+ case JFFS2_NODETYPE_INODE: -+ crc = crc32(0, node, sizeof(node->i)-8); -+ if (je32_to_cpu(node->i.node_crc) != crc) { -+ printk(KERN_WARNING "Node CRC failed on REF_PRISTINE data node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ref_offset(raw), je32_to_cpu(node->i.node_crc), crc); -+ goto bail; -+ } -+ -+ if (je32_to_cpu(node->i.dsize)) { -+ crc = crc32(0, node->i.data, je32_to_cpu(node->i.csize)); -+ if (je32_to_cpu(node->i.data_crc) != crc) { -+ printk(KERN_WARNING "Data CRC failed on REF_PRISTINE data node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ref_offset(raw), je32_to_cpu(node->i.data_crc), crc); -+ goto bail; - } -- spin_unlock_bh(&c->erase_completion_lock); -+ } -+ break; -+ -+ case JFFS2_NODETYPE_DIRENT: -+ crc = crc32(0, node, sizeof(node->d)-8); -+ if (je32_to_cpu(node->d.node_crc) != crc) { -+ printk(KERN_WARNING "Node CRC failed on REF_PRISTINE dirent node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ref_offset(raw), je32_to_cpu(node->d.node_crc), crc); -+ goto bail; -+ } -+ -+ if (node->d.nsize) { -+ crc = crc32(0, node->d.name, node->d.nsize); -+ if (je32_to_cpu(node->d.name_crc) != crc) { -+ printk(KERN_WARNING "Name CRC failed on REF_PRISTINE dirent ode at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ref_offset(raw), je32_to_cpu(node->d.name_crc), crc); -+ goto bail; -+ } -+ } -+ break; -+ default: -+ printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", -+ ref_offset(raw), je16_to_cpu(node->u.nodetype)); -+ goto bail; -+ } -+ -+ nraw = jffs2_alloc_raw_node_ref(); -+ if (!nraw) { -+ ret = -ENOMEM; -+ goto out_node; -+ } -+ -+ /* OK, all the CRCs are good; this node can just be copied as-is. */ -+ retry: -+ nraw->flash_offset = phys_ofs; -+ nraw->__totlen = rawlen; -+ nraw->next_phys = NULL; -+ -+ ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node); -+ -+ if (ret || (retlen != rawlen)) { -+ printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n", -+ rawlen, phys_ofs, ret, retlen); -+ if (retlen) { -+ /* Doesn't belong to any inode */ -+ nraw->next_in_ino = NULL; -+ -+ nraw->flash_offset |= REF_OBSOLETE; -+ jffs2_add_physical_node_ref(c, nraw); -+ jffs2_mark_node_obsolete(c, nraw); -+ } else { -+ printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset); -+ jffs2_free_raw_node_ref(nraw); -+ } -+ if (!retried && (nraw == jffs2_alloc_raw_node_ref())) { -+ /* Try to reallocate space and retry */ -+ uint32_t dummy; -+ struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size]; -+ -+ retried = 1; -+ -+ D1(printk(KERN_DEBUG "Retrying failed write of REF_PRISTINE node.\n")); -+ -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ ret = jffs2_reserve_space_gc(c, rawlen, &phys_ofs, &dummy); -+ -+ if (!ret) { -+ D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", phys_ofs)); - -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ goto retry; -+ } -+ D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); -+ jffs2_free_raw_node_ref(nraw); -+ } -+ -+ if (!ret) -+ ret = -EIO; -+ goto out_node; -+ } -+ nraw->flash_offset |= REF_PRISTINE; -+ jffs2_add_physical_node_ref(c, nraw); -+ -+ /* Link into per-inode list. This is safe because of the ic -+ state being INO_STATE_GC. Note that if we're doing this -+ for an inode which is in-code, the 'nraw' pointer is then -+ going to be fetched from ic->nodes by our caller. */ -+ nraw->next_in_ino = ic->nodes; -+ ic->nodes = nraw; -+ -+ jffs2_mark_node_obsolete(c, raw); -+ D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw))); -+ -+ out_node: -+ kfree(node); - return ret; -+ bail: -+ ret = -EBADFD; -+ goto out_node; - } - - static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dnode *fn) -+ struct jffs2_inode_info *f, struct jffs2_full_dnode *fn) - { -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_full_dnode *new_fn; - struct jffs2_raw_inode ri; -- unsigned short dev; -+ jint16_t dev; - char *mdata = NULL, mdatalen = 0; -- __u32 alloclen, phys_ofs; -+ uint32_t alloclen, phys_ofs; - int ret; - -- if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { -+ if (S_ISBLK(JFFS2_F_I_MODE(f)) || -+ S_ISCHR(JFFS2_F_I_MODE(f)) ) { - /* For these, we don't actually need to read the old node */ -- dev = (MAJOR(to_kdev_t(inode->i_rdev)) << 8) | -- MINOR(to_kdev_t(inode->i_rdev)); -+ /* FIXME: for minor or major > 255. */ -+ dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) | -+ JFFS2_F_I_RDEV_MIN(f))); - mdata = (char *)&dev; - mdatalen = sizeof(dev); - D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen)); -- } else if (S_ISLNK(inode->i_mode)) { -+ } else if (S_ISLNK(JFFS2_F_I_MODE(f))) { - mdatalen = fn->size; - mdata = kmalloc(fn->size, GFP_KERNEL); - if (!mdata) { -@@ -326,34 +686,34 @@ - - ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen); - if (ret) { -- printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_metadata failed: %d\n", -+ printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_metadata failed: %d\n", - sizeof(ri)+ mdatalen, ret); - goto out; - } - - memset(&ri, 0, sizeof(ri)); -- ri.magic = JFFS2_MAGIC_BITMASK; -- ri.nodetype = JFFS2_NODETYPE_INODE; -- ri.totlen = sizeof(ri) + mdatalen; -- ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4); -- -- ri.ino = inode->i_ino; -- ri.version = ++f->highest_version; -- ri.mode = inode->i_mode; -- ri.uid = inode->i_uid; -- ri.gid = inode->i_gid; -- ri.isize = inode->i_size; -- ri.atime = inode->i_atime; -- ri.ctime = inode->i_ctime; -- ri.mtime = inode->i_mtime; -- ri.offset = 0; -- ri.csize = mdatalen; -- ri.dsize = mdatalen; -+ ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -+ ri.totlen = cpu_to_je32(sizeof(ri) + mdatalen); -+ ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); -+ -+ ri.ino = cpu_to_je32(f->inocache->ino); -+ ri.version = cpu_to_je32(++f->highest_version); -+ ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f)); -+ ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); -+ ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); -+ ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f)); -+ ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); -+ ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); -+ ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); -+ ri.offset = cpu_to_je32(0); -+ ri.csize = cpu_to_je32(mdatalen); -+ ri.dsize = cpu_to_je32(mdatalen); - ri.compr = JFFS2_COMPR_NONE; -- ri.node_crc = crc32(0, &ri, sizeof(ri)-8); -- ri.data_crc = crc32(0, mdata, mdatalen); -+ ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); -+ ri.data_crc = cpu_to_je32(crc32(0, mdata, mdatalen)); - -- new_fn = jffs2_write_dnode(inode, &ri, mdata, mdatalen, phys_ofs, NULL); -+ new_fn = jffs2_write_dnode(c, f, &ri, mdata, mdatalen, phys_ofs, ALLOC_GC); - - if (IS_ERR(new_fn)) { - printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn)); -@@ -364,41 +724,40 @@ - jffs2_free_full_dnode(fn); - f->metadata = new_fn; - out: -- if (S_ISLNK(inode->i_mode)) -+ if (S_ISLNK(JFFS2_F_I_MODE(f))) - kfree(mdata); - return ret; - } - - static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dirent *fd) -+ struct jffs2_inode_info *f, struct jffs2_full_dirent *fd) - { -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_full_dirent *new_fd; - struct jffs2_raw_dirent rd; -- __u32 alloclen, phys_ofs; -+ uint32_t alloclen, phys_ofs; - int ret; - -- rd.magic = JFFS2_MAGIC_BITMASK; -- rd.nodetype = JFFS2_NODETYPE_DIRENT; -+ rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ rd.nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); - rd.nsize = strlen(fd->name); -- rd.totlen = sizeof(rd) + rd.nsize; -- rd.hdr_crc = crc32(0, &rd, sizeof(struct jffs2_unknown_node)-4); -+ rd.totlen = cpu_to_je32(sizeof(rd) + rd.nsize); -+ rd.hdr_crc = cpu_to_je32(crc32(0, &rd, sizeof(struct jffs2_unknown_node)-4)); - -- rd.pino = inode->i_ino; -- rd.version = ++f->highest_version; -- rd.ino = fd->ino; -- rd.mctime = max(inode->i_mtime, inode->i_ctime); -+ rd.pino = cpu_to_je32(f->inocache->ino); -+ rd.version = cpu_to_je32(++f->highest_version); -+ rd.ino = cpu_to_je32(fd->ino); -+ rd.mctime = cpu_to_je32(max(JFFS2_F_I_MTIME(f), JFFS2_F_I_CTIME(f))); - rd.type = fd->type; -- rd.node_crc = crc32(0, &rd, sizeof(rd)-8); -- rd.name_crc = crc32(0, fd->name, rd.nsize); -+ rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); -+ rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); - - ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen); - if (ret) { -- printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_dirent failed: %d\n", -+ printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dirent failed: %d\n", - sizeof(rd)+rd.nsize, ret); - return ret; - } -- new_fd = jffs2_write_dirent(inode, &rd, fd->name, rd.nsize, phys_ofs, NULL); -+ new_fd = jffs2_write_dirent(c, f, &rd, fd->name, rd.nsize, phys_ofs, ALLOC_GC); - - if (IS_ERR(new_fd)) { - printk(KERN_WARNING "jffs2_write_dirent in garbage_collect_dirent failed: %ld\n", PTR_ERR(new_fd)); -@@ -409,19 +768,98 @@ - } - - static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dirent *fd) -+ struct jffs2_inode_info *f, struct jffs2_full_dirent *fd) - { -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_full_dirent **fdp = &f->dents; - int found = 0; - -- /* FIXME: When we run on NAND flash, we need to work out whether -- this deletion dirent is still needed to actively delete a -- 'real' dirent with the same name that's still somewhere else -- on the flash. For now, we know that we've actually obliterated -- all the older dirents when they became obsolete, so we didn't -- really need to write the deletion to flash in the first place. -- */ -+ /* On a medium where we can't actually mark nodes obsolete -+ pernamently, such as NAND flash, we need to work out -+ whether this deletion dirent is still needed to actively -+ delete a 'real' dirent with the same name that's still -+ somewhere else on the flash. */ -+ if (!jffs2_can_mark_obsolete(c)) { -+ struct jffs2_raw_dirent *rd; -+ struct jffs2_raw_node_ref *raw; -+ int ret; -+ size_t retlen; -+ int name_len = strlen(fd->name); -+ uint32_t name_crc = crc32(0, fd->name, name_len); -+ uint32_t rawlen = ref_totlen(c, jeb, fd->raw); -+ -+ rd = kmalloc(rawlen, GFP_KERNEL); -+ if (!rd) -+ return -ENOMEM; -+ -+ /* Prevent the erase code from nicking the obsolete node refs while -+ we're looking at them. I really don't like this extra lock but -+ can't see any alternative. Suggestions on a postcard to... */ -+ down(&c->erase_free_sem); -+ -+ for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) { -+ -+ /* We only care about obsolete ones */ -+ if (!(ref_obsolete(raw))) -+ continue; -+ -+ /* Any dirent with the same name is going to have the same length... */ -+ if (ref_totlen(c, NULL, raw) != rawlen) -+ continue; -+ -+ /* Doesn't matter if there's one in the same erase block. We're going to -+ delete it too at the same time. */ -+ if ((raw->flash_offset & ~(c->sector_size-1)) == -+ (fd->raw->flash_offset & ~(c->sector_size-1))) -+ continue; -+ -+ D1(printk(KERN_DEBUG "Check potential deletion dirent at %08x\n", ref_offset(raw))); -+ -+ /* This is an obsolete node belonging to the same directory, and it's of the right -+ length. We need to take a closer look...*/ -+ ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)rd); -+ if (ret) { -+ printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading obsolete node at %08x\n", ret, ref_offset(raw)); -+ /* If we can't read it, we don't need to continue to obsolete it. Continue */ -+ continue; -+ } -+ if (retlen != rawlen) { -+ printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Short read (%zd not %zd) reading header from obsolete node at %08x\n", -+ retlen, rawlen, ref_offset(raw)); -+ continue; -+ } -+ -+ if (je16_to_cpu(rd->nodetype) != JFFS2_NODETYPE_DIRENT) -+ continue; -+ -+ /* If the name CRC doesn't match, skip */ -+ if (je32_to_cpu(rd->name_crc) != name_crc) -+ continue; -+ -+ /* If the name length doesn't match, or it's another deletion dirent, skip */ -+ if (rd->nsize != name_len || !je32_to_cpu(rd->ino)) -+ continue; -+ -+ /* OK, check the actual name now */ -+ if (memcmp(rd->name, fd->name, name_len)) -+ continue; -+ -+ /* OK. The name really does match. There really is still an older node on -+ the flash which our deletion dirent obsoletes. So we have to write out -+ a new deletion dirent to replace it */ -+ up(&c->erase_free_sem); -+ -+ D1(printk(KERN_DEBUG "Deletion dirent at %08x still obsoletes real dirent \"%s\" at %08x for ino #%u\n", -+ ref_offset(fd->raw), fd->name, ref_offset(raw), je32_to_cpu(rd->ino))); -+ kfree(rd); -+ -+ return jffs2_garbage_collect_dirent(c, jeb, f, fd); -+ } -+ -+ up(&c->erase_free_sem); -+ kfree(rd); -+ } -+ -+ /* No need for it any more. Just mark it obsolete and remove it from the list */ - while (*fdp) { - if ((*fdp) == fd) { - found = 1; -@@ -431,7 +869,7 @@ - fdp = &(*fdp)->next; - } - if (!found) { -- printk(KERN_WARNING "Deletion dirent \"%s\" not found in list for ino #%lu\n", fd->name, inode->i_ino); -+ printk(KERN_WARNING "Deletion dirent \"%s\" not found in list for ino #%u\n", fd->name, f->inocache->ino); - } - jffs2_mark_node_obsolete(c, fd->raw); - jffs2_free_full_dirent(fd); -@@ -439,93 +877,95 @@ - } - - static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dnode *fn, -- __u32 start, __u32 end) -+ struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, -+ uint32_t start, uint32_t end) - { -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_raw_inode ri; - struct jffs2_node_frag *frag; - struct jffs2_full_dnode *new_fn; -- __u32 alloclen, phys_ofs; -+ uint32_t alloclen, phys_ofs; - int ret; - -- D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%lu from offset 0x%x to 0x%x\n", -- inode->i_ino, start, end)); -+ D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n", -+ f->inocache->ino, start, end)); - - memset(&ri, 0, sizeof(ri)); - - if(fn->frags > 1) { - size_t readlen; -- __u32 crc; -+ uint32_t crc; - /* It's partially obsoleted by a later write. So we have to - write it out again with the _same_ version as before */ -- ret = c->mtd->read(c->mtd, fn->raw->flash_offset & ~3, sizeof(ri), &readlen, (char *)&ri); -+ ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(ri), &readlen, (char *)&ri); - if (readlen != sizeof(ri) || ret) { -- printk(KERN_WARNING "Node read failed in jffs2_garbage_collect_hole. Ret %d, retlen %d. Data will be lost by writing new hold node\n", ret, readlen); -+ printk(KERN_WARNING "Node read failed in jffs2_garbage_collect_hole. Ret %d, retlen %zd. Data will be lost by writing new hole node\n", ret, readlen); - goto fill; - } -- if (ri.nodetype != JFFS2_NODETYPE_INODE) { -+ if (je16_to_cpu(ri.nodetype) != JFFS2_NODETYPE_INODE) { - printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had node type 0x%04x instead of JFFS2_NODETYPE_INODE(0x%04x)\n", -- fn->raw->flash_offset & ~3, ri.nodetype, JFFS2_NODETYPE_INODE); -+ ref_offset(fn->raw), -+ je16_to_cpu(ri.nodetype), JFFS2_NODETYPE_INODE); - return -EIO; - } -- if (ri.totlen != sizeof(ri)) { -- printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had totlen 0x%x instead of expected 0x%x\n", -- fn->raw->flash_offset & ~3, ri.totlen, sizeof(ri)); -+ if (je32_to_cpu(ri.totlen) != sizeof(ri)) { -+ printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had totlen 0x%x instead of expected 0x%zx\n", -+ ref_offset(fn->raw), -+ je32_to_cpu(ri.totlen), sizeof(ri)); - return -EIO; - } - crc = crc32(0, &ri, sizeof(ri)-8); -- if (crc != ri.node_crc) { -+ if (crc != je32_to_cpu(ri.node_crc)) { - printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had CRC 0x%08x which doesn't match calculated CRC 0x%08x\n", -- fn->raw->flash_offset & ~3, ri.node_crc, crc); -+ ref_offset(fn->raw), -+ je32_to_cpu(ri.node_crc), crc); - /* FIXME: We could possibly deal with this by writing new holes for each frag */ -- printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%lu will be lost\n", -- start, end, inode->i_ino); -+ printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", -+ start, end, f->inocache->ino); - goto fill; - } - if (ri.compr != JFFS2_COMPR_ZERO) { -- printk(KERN_WARNING "jffs2_garbage_collect_hole: Node 0x%08x wasn't a hole node!\n", fn->raw->flash_offset & ~3); -- printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%lu will be lost\n", -- start, end, inode->i_ino); -+ printk(KERN_WARNING "jffs2_garbage_collect_hole: Node 0x%08x wasn't a hole node!\n", ref_offset(fn->raw)); -+ printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", -+ start, end, f->inocache->ino); - goto fill; - } - } else { - fill: -- ri.magic = JFFS2_MAGIC_BITMASK; -- ri.nodetype = JFFS2_NODETYPE_INODE; -- ri.totlen = sizeof(ri); -- ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4); -- -- ri.ino = inode->i_ino; -- ri.version = ++f->highest_version; -- ri.offset = start; -- ri.dsize = end - start; -- ri.csize = 0; -+ ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -+ ri.totlen = cpu_to_je32(sizeof(ri)); -+ ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); -+ -+ ri.ino = cpu_to_je32(f->inocache->ino); -+ ri.version = cpu_to_je32(++f->highest_version); -+ ri.offset = cpu_to_je32(start); -+ ri.dsize = cpu_to_je32(end - start); -+ ri.csize = cpu_to_je32(0); - ri.compr = JFFS2_COMPR_ZERO; - } -- ri.mode = inode->i_mode; -- ri.uid = inode->i_uid; -- ri.gid = inode->i_gid; -- ri.isize = inode->i_size; -- ri.atime = inode->i_atime; -- ri.ctime = inode->i_ctime; -- ri.mtime = inode->i_mtime; -- ri.data_crc = 0; -- ri.node_crc = crc32(0, &ri, sizeof(ri)-8); -+ ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f)); -+ ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); -+ ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); -+ ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f)); -+ ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); -+ ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); -+ ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); -+ ri.data_crc = cpu_to_je32(0); -+ ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); - - ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen); - if (ret) { -- printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_hole failed: %d\n", -+ printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_hole failed: %d\n", - sizeof(ri), ret); - return ret; - } -- new_fn = jffs2_write_dnode(inode, &ri, NULL, 0, phys_ofs, NULL); -+ new_fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_GC); - - if (IS_ERR(new_fn)) { - printk(KERN_WARNING "Error writing new hole node: %ld\n", PTR_ERR(new_fn)); - return PTR_ERR(new_fn); - } -- if (ri.version == f->highest_version) { -+ if (je32_to_cpu(ri.version) == f->highest_version) { - jffs2_add_full_dnode_to_inode(c, f, new_fn); - if (f->metadata) { - jffs2_mark_node_obsolete(c, f->metadata->raw); -@@ -541,12 +981,17 @@ - * number as before. (Except in case of error -- see 'goto fill;' - * above.) - */ -- D1(if(fn->frags <= 1) { -+ D1(if(unlikely(fn->frags <= 1)) { - printk(KERN_WARNING "jffs2_garbage_collect_hole: Replacing fn with %d frag(s) but new ver %d != highest_version %d of ino #%d\n", -- fn->frags, ri.version, f->highest_version, ri.ino); -+ fn->frags, je32_to_cpu(ri.version), f->highest_version, -+ je32_to_cpu(ri.ino)); - }); - -- for (frag = f->fraglist; frag; frag = frag->next) { -+ /* This is a partially-overlapped hole node. Mark it REF_NORMAL not REF_PRISTINE */ -+ mark_ref_normal(new_fn->raw); -+ -+ for (frag = jffs2_lookup_node_frag(&f->fragtree, fn->ofs); -+ frag; frag = frag_next(frag)) { - if (frag->ofs > fn->size + fn->ofs) - break; - if (frag->node == fn) { -@@ -571,49 +1016,146 @@ - } - - static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dnode *fn, -- __u32 start, __u32 end) -+ struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, -+ uint32_t start, uint32_t end) - { -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_full_dnode *new_fn; - struct jffs2_raw_inode ri; -- __u32 alloclen, phys_ofs, offset, orig_end; -+ uint32_t alloclen, phys_ofs, offset, orig_end, orig_start; - int ret = 0; - unsigned char *comprbuf = NULL, *writebuf; -- struct page *pg; -+ unsigned long pg; - unsigned char *pg_ptr; - -- - memset(&ri, 0, sizeof(ri)); - -- D1(printk(KERN_DEBUG "Writing replacement dnode for ino #%lu from offset 0x%x to 0x%x\n", -- inode->i_ino, start, end)); -+ D1(printk(KERN_DEBUG "Writing replacement dnode for ino #%u from offset 0x%x to 0x%x\n", -+ f->inocache->ino, start, end)); - - orig_end = end; -+ orig_start = start; - -+ if (c->nr_free_blocks + c->nr_erasing_blocks > c->resv_blocks_gcmerge) { -+ /* Attempt to do some merging. But only expand to cover logically -+ adjacent frags if the block containing them is already considered -+ to be dirty. Otherwise we end up with GC just going round in -+ circles dirtying the nodes it already wrote out, especially -+ on NAND where we have small eraseblocks and hence a much higher -+ chance of nodes having to be split to cross boundaries. */ - -- /* If we're looking at the last node in the block we're -- garbage-collecting, we allow ourselves to merge as if the -- block was already erasing. We're likely to be GC'ing a -- partial page, and the next block we GC is likely to have -- the other half of this page right at the beginning, which -- means we'd expand it _then_, as nr_erasing_blocks would have -- increased since we checked, and in doing so would obsolete -- the partial node which we'd have written here. Meaning that -- the GC would churn and churn, and just leave dirty blocks in -- it's wake. -- */ -- if(c->nr_free_blocks + c->nr_erasing_blocks > JFFS2_RESERVED_BLOCKS_GCMERGE - (fn->raw->next_phys?0:1)) { -- /* Shitloads of space */ -- /* FIXME: Integrate this properly with GC calculations */ -- start &= ~(PAGE_CACHE_SIZE-1); -- end = min_t(__u32, start + PAGE_CACHE_SIZE, inode->i_size); -- D1(printk(KERN_DEBUG "Plenty of free space, so expanding to write from offset 0x%x to 0x%x\n", -- start, end)); -- if (end < orig_end) { -- printk(KERN_WARNING "Eep. jffs2_garbage_collect_dnode extended node to write, but it got smaller: start 0x%x, orig_end 0x%x, end 0x%x\n", start, orig_end, end); -- end = orig_end; -+ struct jffs2_node_frag *frag; -+ uint32_t min, max; -+ -+ min = start & ~(PAGE_CACHE_SIZE-1); -+ max = min + PAGE_CACHE_SIZE; -+ -+ frag = jffs2_lookup_node_frag(&f->fragtree, start); -+ -+ /* BUG_ON(!frag) but that'll happen anyway... */ -+ -+ BUG_ON(frag->ofs != start); -+ -+ /* First grow down... */ -+ while((frag = frag_prev(frag)) && frag->ofs >= min) { -+ -+ /* If the previous frag doesn't even reach the beginning, there's -+ excessive fragmentation. Just merge. */ -+ if (frag->ofs > min) { -+ D1(printk(KERN_DEBUG "Expanding down to cover partial frag (0x%x-0x%x)\n", -+ frag->ofs, frag->ofs+frag->size)); -+ start = frag->ofs; -+ continue; -+ } -+ /* OK. This frag holds the first byte of the page. */ -+ if (!frag->node || !frag->node->raw) { -+ D1(printk(KERN_DEBUG "First frag in page is hole (0x%x-0x%x). Not expanding down.\n", -+ frag->ofs, frag->ofs+frag->size)); -+ break; -+ } else { -+ -+ /* OK, it's a frag which extends to the beginning of the page. Does it live -+ in a block which is still considered clean? If so, don't obsolete it. -+ If not, cover it anyway. */ -+ -+ struct jffs2_raw_node_ref *raw = frag->node->raw; -+ struct jffs2_eraseblock *jeb; -+ -+ jeb = &c->blocks[raw->flash_offset / c->sector_size]; -+ -+ if (jeb == c->gcblock) { -+ D1(printk(KERN_DEBUG "Expanding down to cover frag (0x%x-0x%x) in gcblock at %08x\n", -+ frag->ofs, frag->ofs+frag->size, ref_offset(raw))); -+ start = frag->ofs; -+ break; - } -+ if (!ISDIRTY(jeb->dirty_size + jeb->wasted_size)) { -+ D1(printk(KERN_DEBUG "Not expanding down to cover frag (0x%x-0x%x) in clean block %08x\n", -+ frag->ofs, frag->ofs+frag->size, jeb->offset)); -+ break; -+ } -+ -+ D1(printk(KERN_DEBUG "Expanding down to cover frag (0x%x-0x%x) in dirty block %08x\n", -+ frag->ofs, frag->ofs+frag->size, jeb->offset)); -+ start = frag->ofs; -+ break; -+ } -+ } -+ -+ /* ... then up */ -+ -+ /* Find last frag which is actually part of the node we're to GC. */ -+ frag = jffs2_lookup_node_frag(&f->fragtree, end-1); -+ -+ while((frag = frag_next(frag)) && frag->ofs+frag->size <= max) { -+ -+ /* If the previous frag doesn't even reach the beginning, there's lots -+ of fragmentation. Just merge. */ -+ if (frag->ofs+frag->size < max) { -+ D1(printk(KERN_DEBUG "Expanding up to cover partial frag (0x%x-0x%x)\n", -+ frag->ofs, frag->ofs+frag->size)); -+ end = frag->ofs + frag->size; -+ continue; -+ } -+ -+ if (!frag->node || !frag->node->raw) { -+ D1(printk(KERN_DEBUG "Last frag in page is hole (0x%x-0x%x). Not expanding up.\n", -+ frag->ofs, frag->ofs+frag->size)); -+ break; -+ } else { -+ -+ /* OK, it's a frag which extends to the beginning of the page. Does it live -+ in a block which is still considered clean? If so, don't obsolete it. -+ If not, cover it anyway. */ -+ -+ struct jffs2_raw_node_ref *raw = frag->node->raw; -+ struct jffs2_eraseblock *jeb; -+ -+ jeb = &c->blocks[raw->flash_offset / c->sector_size]; -+ -+ if (jeb == c->gcblock) { -+ D1(printk(KERN_DEBUG "Expanding up to cover frag (0x%x-0x%x) in gcblock at %08x\n", -+ frag->ofs, frag->ofs+frag->size, ref_offset(raw))); -+ end = frag->ofs + frag->size; -+ break; -+ } -+ if (!ISDIRTY(jeb->dirty_size + jeb->wasted_size)) { -+ D1(printk(KERN_DEBUG "Not expanding up to cover frag (0x%x-0x%x) in clean block %08x\n", -+ frag->ofs, frag->ofs+frag->size, jeb->offset)); -+ break; -+ } -+ -+ D1(printk(KERN_DEBUG "Expanding up to cover frag (0x%x-0x%x) in dirty block %08x\n", -+ frag->ofs, frag->ofs+frag->size, jeb->offset)); -+ end = frag->ofs + frag->size; -+ break; -+ } -+ } -+ D1(printk(KERN_DEBUG "Expanded dnode to write from (0x%x-0x%x) to (0x%x-0x%x)\n", -+ orig_start, orig_end, start, end)); -+ -+ BUG_ON(end > JFFS2_F_I_SIZE(f)); -+ BUG_ON(end < orig_end); -+ BUG_ON(start > orig_start); - } - - /* First, use readpage() to read the appropriate page into the page cache */ -@@ -623,63 +1165,57 @@ - * page OK. We'll actually write it out again in commit_write, which is a little - * suboptimal, but at least we're correct. - */ -- pg = read_cache_page(inode->i_mapping, start >> PAGE_CACHE_SHIFT, (void *)jffs2_do_readpage_unlock, inode); -+ pg_ptr = jffs2_gc_fetch_page(c, f, start, &pg); - -- if (IS_ERR(pg)) { -- printk(KERN_WARNING "read_cache_page() returned error: %ld\n", PTR_ERR(pg)); -- return PTR_ERR(pg); -+ if (IS_ERR(pg_ptr)) { -+ printk(KERN_WARNING "read_cache_page() returned error: %ld\n", PTR_ERR(pg_ptr)); -+ return PTR_ERR(pg_ptr); - } -- pg_ptr = (char *)kmap(pg); -- comprbuf = kmalloc(end - start, GFP_KERNEL); - - offset = start; - while(offset < orig_end) { -- __u32 datalen; -- __u32 cdatalen; -+ uint32_t datalen; -+ uint32_t cdatalen; - char comprtype = JFFS2_COMPR_NONE; - - ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen); - - if (ret) { -- printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_dnode failed: %d\n", -+ printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dnode failed: %d\n", - sizeof(ri)+ JFFS2_MIN_DATA_LEN, ret); - break; - } -- cdatalen = min(alloclen - sizeof(ri), end - offset); -+ cdatalen = min_t(uint32_t, alloclen - sizeof(ri), end - offset); - datalen = end - offset; - - writebuf = pg_ptr + (offset & (PAGE_CACHE_SIZE -1)); - -- if (comprbuf) { -- comprtype = jffs2_compress(writebuf, comprbuf, &datalen, &cdatalen); -- } -- if (comprtype) { -- writebuf = comprbuf; -- } else { -- datalen = cdatalen; -- } -- ri.magic = JFFS2_MAGIC_BITMASK; -- ri.nodetype = JFFS2_NODETYPE_INODE; -- ri.totlen = sizeof(ri) + cdatalen; -- ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4); -- -- ri.ino = inode->i_ino; -- ri.version = ++f->highest_version; -- ri.mode = inode->i_mode; -- ri.uid = inode->i_uid; -- ri.gid = inode->i_gid; -- ri.isize = inode->i_size; -- ri.atime = inode->i_atime; -- ri.ctime = inode->i_ctime; -- ri.mtime = inode->i_mtime; -- ri.offset = offset; -- ri.csize = cdatalen; -- ri.dsize = datalen; -+ comprtype = jffs2_compress(writebuf, &comprbuf, &datalen, &cdatalen); -+ -+ ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -+ ri.totlen = cpu_to_je32(sizeof(ri) + cdatalen); -+ ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); -+ -+ ri.ino = cpu_to_je32(f->inocache->ino); -+ ri.version = cpu_to_je32(++f->highest_version); -+ ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f)); -+ ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); -+ ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); -+ ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f)); -+ ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); -+ ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); -+ ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); -+ ri.offset = cpu_to_je32(offset); -+ ri.csize = cpu_to_je32(cdatalen); -+ ri.dsize = cpu_to_je32(datalen); - ri.compr = comprtype; -- ri.node_crc = crc32(0, &ri, sizeof(ri)-8); -- ri.data_crc = crc32(0, writebuf, cdatalen); -+ ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); -+ ri.data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); -+ -+ new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, phys_ofs, ALLOC_GC); - -- new_fn = jffs2_write_dnode(inode, &ri, writebuf, cdatalen, phys_ofs, NULL); -+ jffs2_free_comprbuf(comprbuf, writebuf); - - if (IS_ERR(new_fn)) { - printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn)); -@@ -694,12 +1230,8 @@ - f->metadata = NULL; - } - } -- if (comprbuf) kfree(comprbuf); - -- kunmap(pg); -- /* XXX: Does the page get freed automatically? */ -- /* AAA: Judging by the unmount getting stuck in __wait_on_page, nope. */ -- page_cache_release(pg); -+ jffs2_gc_release_page(c, pg_ptr, &pg); - return ret; - } - -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/ioctl.c linux/fs/jffs2/ioctl.c ---- linux-mips-2.4.24-pre2/fs/jffs2/ioctl.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/ioctl.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,37 +1,13 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - -@@ -42,6 +18,6 @@ - { - /* Later, this will provide for lsattr.jffs2 and chattr.jffs2, which - will include compression support etc. */ -- return -EINVAL; -+ return -ENOTTY; - } - -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/malloc.c linux/fs/jffs2/malloc.c ---- linux-mips-2.4.24-pre2/fs/jffs2/malloc.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/malloc.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,37 +1,13 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - -@@ -47,6 +23,9 @@ - #define JFFS2_SLAB_POISON 0 - #endif - -+// replace this by #define D3 (x) x for cache debugging -+#define D3(x) -+ - /* These are initialised to NULL in the kernel startup code. - If you're porting to other operating systems, beware */ - static kmem_cache_t *full_dnode_slab; -@@ -57,57 +36,47 @@ - static kmem_cache_t *node_frag_slab; - static kmem_cache_t *inode_cache_slab; - --void jffs2_free_tmp_dnode_info_list(struct jffs2_tmp_dnode_info *tn) --{ -- struct jffs2_tmp_dnode_info *next; -- -- while (tn) { -- next = tn; -- tn = tn->next; -- jffs2_free_full_dnode(next->fn); -- jffs2_free_tmp_dnode_info(next); -- } --} -- --void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd) --{ -- struct jffs2_full_dirent *next; -- -- while (fd) { -- next = fd->next; -- jffs2_free_full_dirent(fd); -- fd = next; -- } --} -- - int __init jffs2_create_slab_caches(void) - { -- full_dnode_slab = kmem_cache_create("jffs2_full_dnode", sizeof(struct jffs2_full_dnode), 0, JFFS2_SLAB_POISON, NULL, NULL); -+ full_dnode_slab = kmem_cache_create("jffs2_full_dnode", -+ sizeof(struct jffs2_full_dnode), -+ 0, JFFS2_SLAB_POISON, NULL, NULL); - if (!full_dnode_slab) - goto err; - -- raw_dirent_slab = kmem_cache_create("jffs2_raw_dirent", sizeof(struct jffs2_raw_dirent), 0, JFFS2_SLAB_POISON, NULL, NULL); -+ raw_dirent_slab = kmem_cache_create("jffs2_raw_dirent", -+ sizeof(struct jffs2_raw_dirent), -+ 0, JFFS2_SLAB_POISON, NULL, NULL); - if (!raw_dirent_slab) - goto err; - -- raw_inode_slab = kmem_cache_create("jffs2_raw_inode", sizeof(struct jffs2_raw_inode), 0, JFFS2_SLAB_POISON, NULL, NULL); -+ raw_inode_slab = kmem_cache_create("jffs2_raw_inode", -+ sizeof(struct jffs2_raw_inode), -+ 0, JFFS2_SLAB_POISON, NULL, NULL); - if (!raw_inode_slab) - goto err; - -- tmp_dnode_info_slab = kmem_cache_create("jffs2_tmp_dnode", sizeof(struct jffs2_tmp_dnode_info), 0, JFFS2_SLAB_POISON, NULL, NULL); -+ tmp_dnode_info_slab = kmem_cache_create("jffs2_tmp_dnode", -+ sizeof(struct jffs2_tmp_dnode_info), -+ 0, JFFS2_SLAB_POISON, NULL, NULL); - if (!tmp_dnode_info_slab) - goto err; - -- raw_node_ref_slab = kmem_cache_create("jffs2_raw_node_ref", sizeof(struct jffs2_raw_node_ref), 0, JFFS2_SLAB_POISON, NULL, NULL); -+ raw_node_ref_slab = kmem_cache_create("jffs2_raw_node_ref", -+ sizeof(struct jffs2_raw_node_ref), -+ 0, JFFS2_SLAB_POISON, NULL, NULL); - if (!raw_node_ref_slab) - goto err; - -- node_frag_slab = kmem_cache_create("jffs2_node_frag", sizeof(struct jffs2_node_frag), 0, JFFS2_SLAB_POISON, NULL, NULL); -+ node_frag_slab = kmem_cache_create("jffs2_node_frag", -+ sizeof(struct jffs2_node_frag), -+ 0, JFFS2_SLAB_POISON, NULL, NULL); - if (!node_frag_slab) - goto err; - -- inode_cache_slab = kmem_cache_create("jffs2_inode_cache", sizeof(struct jffs2_inode_cache), 0, JFFS2_SLAB_POISON, NULL, NULL); -- -+ inode_cache_slab = kmem_cache_create("jffs2_inode_cache", -+ sizeof(struct jffs2_inode_cache), -+ 0, JFFS2_SLAB_POISON, NULL, NULL); - if (inode_cache_slab) - return 0; - err: -@@ -131,7 +100,6 @@ - kmem_cache_destroy(node_frag_slab); - if(inode_cache_slab) - kmem_cache_destroy(inode_cache_slab); -- - } - - struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize) -@@ -146,75 +114,92 @@ - - struct jffs2_full_dnode *jffs2_alloc_full_dnode(void) - { -- void *ret = kmem_cache_alloc(full_dnode_slab, GFP_KERNEL); -+ struct jffs2_full_dnode *ret = kmem_cache_alloc(full_dnode_slab, GFP_KERNEL); -+ D3 (printk (KERN_DEBUG "alloc_full_dnode at %p\n", ret)); - return ret; - } - - void jffs2_free_full_dnode(struct jffs2_full_dnode *x) - { -+ D3 (printk (KERN_DEBUG "free full_dnode at %p\n", x)); - kmem_cache_free(full_dnode_slab, x); - } - - struct jffs2_raw_dirent *jffs2_alloc_raw_dirent(void) - { -- return kmem_cache_alloc(raw_dirent_slab, GFP_KERNEL); -+ struct jffs2_raw_dirent *ret = kmem_cache_alloc(raw_dirent_slab, GFP_KERNEL); -+ D3 (printk (KERN_DEBUG "alloc_raw_dirent\n", ret)); -+ return ret; - } - - void jffs2_free_raw_dirent(struct jffs2_raw_dirent *x) - { -+ D3 (printk (KERN_DEBUG "free_raw_dirent at %p\n", x)); - kmem_cache_free(raw_dirent_slab, x); - } - - struct jffs2_raw_inode *jffs2_alloc_raw_inode(void) - { -- return kmem_cache_alloc(raw_inode_slab, GFP_KERNEL); -+ struct jffs2_raw_inode *ret = kmem_cache_alloc(raw_inode_slab, GFP_KERNEL); -+ D3 (printk (KERN_DEBUG "alloc_raw_inode at %p\n", ret)); -+ return ret; - } - - void jffs2_free_raw_inode(struct jffs2_raw_inode *x) - { -+ D3 (printk (KERN_DEBUG "free_raw_inode at %p\n", x)); - kmem_cache_free(raw_inode_slab, x); - } - - struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void) - { -- return kmem_cache_alloc(tmp_dnode_info_slab, GFP_KERNEL); -+ struct jffs2_tmp_dnode_info *ret = kmem_cache_alloc(tmp_dnode_info_slab, GFP_KERNEL); -+ D3 (printk (KERN_DEBUG "alloc_tmp_dnode_info at %p\n", ret)); -+ return ret; - } - - void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x) - { -+ D3 (printk (KERN_DEBUG "free_tmp_dnode_info at %p\n", x)); - kmem_cache_free(tmp_dnode_info_slab, x); - } - - struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) - { -- return kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); -+ struct jffs2_raw_node_ref *ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); -+ D3 (printk (KERN_DEBUG "alloc_raw_node_ref at %p\n", ret)); -+ return ret; - } - - void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) - { -+ D3 (printk (KERN_DEBUG "free_raw_node_ref at %p\n", x)); - kmem_cache_free(raw_node_ref_slab, x); - } - - struct jffs2_node_frag *jffs2_alloc_node_frag(void) - { -- return kmem_cache_alloc(node_frag_slab, GFP_KERNEL); -+ struct jffs2_node_frag *ret = kmem_cache_alloc(node_frag_slab, GFP_KERNEL); -+ D3 (printk (KERN_DEBUG "alloc_node_frag at %p\n", ret)); -+ return ret; - } - - void jffs2_free_node_frag(struct jffs2_node_frag *x) - { -+ D3 (printk (KERN_DEBUG "free_node_frag at %p\n", x)); - kmem_cache_free(node_frag_slab, x); - } - - struct jffs2_inode_cache *jffs2_alloc_inode_cache(void) - { - struct jffs2_inode_cache *ret = kmem_cache_alloc(inode_cache_slab, GFP_KERNEL); -- D1(printk(KERN_DEBUG "Allocated inocache at %p\n", ret)); -+ D3 (printk(KERN_DEBUG "Allocated inocache at %p\n", ret)); - return ret; - } - - void jffs2_free_inode_cache(struct jffs2_inode_cache *x) - { -- D1(printk(KERN_DEBUG "Freeing inocache at %p\n", x)); -+ D3 (printk(KERN_DEBUG "Freeing inocache at %p\n", x)); - kmem_cache_free(inode_cache_slab, x); - } - -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/nodelist.c linux/fs/jffs2/nodelist.c ---- linux-mips-2.4.24-pre2/fs/jffs2/nodelist.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/nodelist.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,44 +1,24 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001, 2002 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include --#include -+#include - #include - #include -+#include -+#include -+#include -+#include - #include "nodelist.h" - - void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list) -@@ -78,7 +58,7 @@ - /* Put a new tmp_dnode_info into the list, keeping the list in - order of increasing version - */ --void jffs2_add_tn_to_list(struct jffs2_tmp_dnode_info *tn, struct jffs2_tmp_dnode_info **list) -+static void jffs2_add_tn_to_list(struct jffs2_tmp_dnode_info *tn, struct jffs2_tmp_dnode_info **list) - { - struct jffs2_tmp_dnode_info **prev = list; - -@@ -89,13 +69,37 @@ - *prev = tn; - } - -+static void jffs2_free_tmp_dnode_info_list(struct jffs2_tmp_dnode_info *tn) -+{ -+ struct jffs2_tmp_dnode_info *next; -+ -+ while (tn) { -+ next = tn; -+ tn = tn->next; -+ jffs2_free_full_dnode(next->fn); -+ jffs2_free_tmp_dnode_info(next); -+ } -+} -+ -+static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd) -+{ -+ struct jffs2_full_dirent *next; -+ -+ while (fd) { -+ next = fd->next; -+ jffs2_free_full_dirent(fd); -+ fd = next; -+ } -+} -+ -+ - /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated - with this ino, returning the former in order of version */ - - int jffs2_get_inode_nodes(struct jffs2_sb_info *c, ino_t ino, struct jffs2_inode_info *f, - struct jffs2_tmp_dnode_info **tnp, struct jffs2_full_dirent **fdp, -- __u32 *highest_version, __u32 *latest_mctime, -- __u32 *mctime_ver) -+ uint32_t *highest_version, uint32_t *latest_mctime, -+ uint32_t *mctime_ver) - { - struct jffs2_raw_node_ref *ref = f->inocache->nodes; - struct jffs2_tmp_dnode_info *tn, *ret_tn = NULL; -@@ -109,43 +113,71 @@ - - D1(printk(KERN_DEBUG "jffs2_get_inode_nodes(): ino #%lu\n", ino)); - if (!f->inocache->nodes) { -- printk(KERN_WARNING "Eep. no nodes for ino #%lu\n", ino); -+ printk(KERN_WARNING "Eep. no nodes for ino #%lu\n", (unsigned long)ino); - } -+ -+ spin_lock(&c->erase_completion_lock); -+ - for (ref = f->inocache->nodes; ref && ref->next_in_ino; ref = ref->next_in_ino) { - /* Work out whether it's a data node or a dirent node */ -- if (ref->flash_offset & 1) { -+ if (ref_obsolete(ref)) { - /* FIXME: On NAND flash we may need to read these */ -- D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref->flash_offset &~3)); -+ D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref))); - continue; - } -- err = c->mtd->read(c->mtd, (ref->flash_offset & ~3), min(ref->totlen, sizeof(node)), &retlen, (void *)&node); -+ /* We can hold a pointer to a non-obsolete node without the spinlock, -+ but _obsolete_ nodes may disappear at any time, if the block -+ they're in gets erased */ -+ spin_unlock(&c->erase_completion_lock); -+ -+ cond_resched(); -+ -+ /* FIXME: point() */ -+ err = jffs2_flash_read(c, (ref_offset(ref)), -+ min_t(uint32_t, ref_totlen(c, NULL, ref), sizeof(node)), -+ &retlen, (void *)&node); - if (err) { -- printk(KERN_WARNING "error %d reading node at 0x%08x in get_inode_nodes()\n", err, (ref->flash_offset) & ~3); -+ printk(KERN_WARNING "error %d reading node at 0x%08x in get_inode_nodes()\n", err, ref_offset(ref)); - goto free_out; - } - - - /* Check we've managed to read at least the common node header */ -- if (retlen < min(ref->totlen, sizeof(node.u))) { -+ if (retlen < min_t(uint32_t, ref_totlen(c, NULL, ref), sizeof(node.u))) { - printk(KERN_WARNING "short read in get_inode_nodes()\n"); - err = -EIO; - goto free_out; - } - -- switch (node.u.nodetype) { -+ switch (je16_to_cpu(node.u.nodetype)) { - case JFFS2_NODETYPE_DIRENT: -- D1(printk(KERN_DEBUG "Node at %08x is a dirent node\n", ref->flash_offset &~3)); -+ D1(printk(KERN_DEBUG "Node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref))); -+ if (ref_flags(ref) == REF_UNCHECKED) { -+ printk(KERN_WARNING "BUG: Dirent node at 0x%08x never got checked? How?\n", ref_offset(ref)); -+ BUG(); -+ } - if (retlen < sizeof(node.d)) { - printk(KERN_WARNING "short read in get_inode_nodes()\n"); - err = -EIO; - goto free_out; - } -- if (node.d.version > *highest_version) -- *highest_version = node.d.version; -- if (ref->flash_offset & 1) { -- /* Obsoleted */ -+ /* sanity check */ -+ if (PAD((node.d.nsize + sizeof (node.d))) != PAD(je32_to_cpu (node.d.totlen))) { -+ printk(KERN_NOTICE "jffs2_get_inode_nodes(): Illegal nsize in node at 0x%08x: nsize 0x%02x, totlen %04x\n", -+ ref_offset(ref), node.d.nsize, je32_to_cpu(node.d.totlen)); -+ jffs2_mark_node_obsolete(c, ref); -+ spin_lock(&c->erase_completion_lock); - continue; - } -+ if (je32_to_cpu(node.d.version) > *highest_version) -+ *highest_version = je32_to_cpu(node.d.version); -+ if (ref_obsolete(ref)) { -+ /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ -+ printk(KERN_ERR "Dirent node at 0x%08x became obsolete while we weren't looking\n", -+ ref_offset(ref)); -+ BUG(); -+ } -+ - fd = jffs2_alloc_full_dirent(node.d.nsize+1); - if (!fd) { - err = -ENOMEM; -@@ -153,29 +185,30 @@ - } - memset(fd,0,sizeof(struct jffs2_full_dirent) + node.d.nsize+1); - fd->raw = ref; -- fd->version = node.d.version; -- fd->ino = node.d.ino; -+ fd->version = je32_to_cpu(node.d.version); -+ fd->ino = je32_to_cpu(node.d.ino); - fd->type = node.d.type; - - /* Pick out the mctime of the latest dirent */ - if(fd->version > *mctime_ver) { - *mctime_ver = fd->version; -- *latest_mctime = node.d.mctime; -+ *latest_mctime = je32_to_cpu(node.d.mctime); - } - - /* memcpy as much of the name as possible from the raw - dirent we've already read from the flash - */ - if (retlen > sizeof(struct jffs2_raw_dirent)) -- memcpy(&fd->name[0], &node.d.name[0], min((__u32)node.d.nsize, (retlen-sizeof(struct jffs2_raw_dirent)))); -+ memcpy(&fd->name[0], &node.d.name[0], min_t(uint32_t, node.d.nsize, (retlen-sizeof(struct jffs2_raw_dirent)))); - - /* Do we need to copy any more of the name directly - from the flash? - */ - if (node.d.nsize + sizeof(struct jffs2_raw_dirent) > retlen) { -+ /* FIXME: point() */ - int already = retlen - sizeof(struct jffs2_raw_dirent); - -- err = c->mtd->read(c->mtd, (ref->flash_offset & ~3) + retlen, -+ err = jffs2_flash_read(c, (ref_offset(ref)) + retlen, - node.d.nsize - already, &retlen, &fd->name[already]); - if (!err && retlen != node.d.nsize - already) - err = -EIO; -@@ -196,21 +229,126 @@ - break; - - case JFFS2_NODETYPE_INODE: -- D1(printk(KERN_DEBUG "Node at %08x is a data node\n", ref->flash_offset &~3)); -+ D1(printk(KERN_DEBUG "Node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref))); - if (retlen < sizeof(node.i)) { - printk(KERN_WARNING "read too short for dnode\n"); - err = -EIO; - goto free_out; - } -- if (node.i.version > *highest_version) -- *highest_version = node.i.version; -- D1(printk(KERN_DEBUG "version %d, highest_version now %d\n", node.i.version, *highest_version)); -- -- if (ref->flash_offset & 1) { -- D1(printk(KERN_DEBUG "obsoleted\n")); -- /* Obsoleted */ -+ if (je32_to_cpu(node.i.version) > *highest_version) -+ *highest_version = je32_to_cpu(node.i.version); -+ D1(printk(KERN_DEBUG "version %d, highest_version now %d\n", je32_to_cpu(node.i.version), *highest_version)); -+ -+ if (ref_obsolete(ref)) { -+ /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ -+ printk(KERN_ERR "Inode node at 0x%08x became obsolete while we weren't looking\n", -+ ref_offset(ref)); -+ BUG(); -+ } -+ -+ /* If we've never checked the CRCs on this node, check them now. */ -+ if (ref_flags(ref) == REF_UNCHECKED) { -+ uint32_t crc, len; -+ struct jffs2_eraseblock *jeb; -+ -+ crc = crc32(0, &node, sizeof(node.i)-8); -+ if (crc != je32_to_cpu(node.i.node_crc)) { -+ printk(KERN_NOTICE "jffs2_get_inode_nodes(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ref_offset(ref), je32_to_cpu(node.i.node_crc), crc); -+ jffs2_mark_node_obsolete(c, ref); -+ spin_lock(&c->erase_completion_lock); - continue; - } -+ -+ /* sanity checks */ -+ if ( je32_to_cpu(node.i.offset) > je32_to_cpu(node.i.isize) || -+ PAD(je32_to_cpu(node.i.csize) + sizeof (node.i)) != PAD(je32_to_cpu(node.i.totlen))) { -+ printk(KERN_NOTICE "jffs2_get_inode_nodes(): Inode corrupted at 0x%08x, totlen %d, #ino %d, version %d, isize %d, csize %d, dsize %d \n", -+ ref_offset(ref), je32_to_cpu(node.i.totlen), je32_to_cpu(node.i.ino), -+ je32_to_cpu(node.i.version), je32_to_cpu(node.i.isize), -+ je32_to_cpu(node.i.csize), je32_to_cpu(node.i.dsize)); -+ jffs2_mark_node_obsolete(c, ref); -+ spin_lock(&c->erase_completion_lock); -+ continue; -+ } -+ -+ if (node.i.compr != JFFS2_COMPR_ZERO && je32_to_cpu(node.i.csize)) { -+ unsigned char *buf=NULL; -+ uint32_t pointed = 0; -+#ifndef __ECOS -+ if (c->mtd->point) { -+ err = c->mtd->point (c->mtd, ref_offset(ref) + sizeof(node.i), je32_to_cpu(node.i.csize), -+ &retlen, &buf); -+ if (!err && retlen < je32_to_cpu(node.i.csize)) { -+ D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen)); -+ c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(node.i), je32_to_cpu(node.i.csize)); -+ } else if (err){ -+ D1(printk(KERN_DEBUG "MTD point failed %d\n", err)); -+ } else -+ pointed = 1; /* succefully pointed to device */ -+ } -+#endif -+ if(!pointed){ -+ buf = kmalloc(je32_to_cpu(node.i.csize), GFP_KERNEL); -+ if (!buf) -+ return -ENOMEM; -+ -+ err = jffs2_flash_read(c, ref_offset(ref) + sizeof(node.i), je32_to_cpu(node.i.csize), -+ &retlen, buf); -+ if (!err && retlen != je32_to_cpu(node.i.csize)) -+ err = -EIO; -+ if (err) { -+ kfree(buf); -+ return err; -+ } -+ } -+ crc = crc32(0, buf, je32_to_cpu(node.i.csize)); -+ if(!pointed) -+ kfree(buf); -+#ifndef __ECOS -+ else -+ c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(node.i), je32_to_cpu(node.i.csize)); -+#endif -+ -+ if (crc != je32_to_cpu(node.i.data_crc)) { -+ printk(KERN_NOTICE "jffs2_get_inode_nodes(): Data CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ref_offset(ref), je32_to_cpu(node.i.data_crc), crc); -+ jffs2_mark_node_obsolete(c, ref); -+ spin_lock(&c->erase_completion_lock); -+ continue; -+ } -+ -+ } -+ -+ /* Mark the node as having been checked and fix the accounting accordingly */ -+ spin_lock(&c->erase_completion_lock); -+ jeb = &c->blocks[ref->flash_offset / c->sector_size]; -+ len = ref_totlen(c, jeb, ref); -+ -+ jeb->used_size += len; -+ jeb->unchecked_size -= len; -+ c->used_size += len; -+ c->unchecked_size -= len; -+ -+ /* If node covers at least a whole page, or if it starts at the -+ beginning of a page and runs to the end of the file, or if -+ it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. -+ -+ If it's actually overlapped, it'll get made NORMAL (or OBSOLETE) -+ when the overlapping node(s) get added to the tree anyway. -+ */ -+ if ((je32_to_cpu(node.i.dsize) >= PAGE_CACHE_SIZE) || -+ ( ((je32_to_cpu(node.i.offset)&(PAGE_CACHE_SIZE-1))==0) && -+ (je32_to_cpu(node.i.dsize)+je32_to_cpu(node.i.offset) == je32_to_cpu(node.i.isize)))) { -+ D1(printk(KERN_DEBUG "Marking node at 0x%08x REF_PRISTINE\n", ref_offset(ref))); -+ ref->flash_offset = ref_offset(ref) | REF_PRISTINE; -+ } else { -+ D1(printk(KERN_DEBUG "Marking node at 0x%08x REF_NORMAL\n", ref_offset(ref))); -+ ref->flash_offset = ref_offset(ref) | REF_NORMAL; -+ } -+ spin_unlock(&c->erase_completion_lock); -+ } -+ - tn = jffs2_alloc_tmp_dnode_info(); - if (!tn) { - D1(printk(KERN_DEBUG "alloc tn failed\n")); -@@ -225,36 +363,76 @@ - jffs2_free_tmp_dnode_info(tn); - goto free_out; - } -- tn->version = node.i.version; -- tn->fn->ofs = node.i.offset; -+ tn->version = je32_to_cpu(node.i.version); -+ tn->fn->ofs = je32_to_cpu(node.i.offset); - /* There was a bug where we wrote hole nodes out with - csize/dsize swapped. Deal with it */ -- if (node.i.compr == JFFS2_COMPR_ZERO && !node.i.dsize && node.i.csize) -- tn->fn->size = node.i.csize; -+ if (node.i.compr == JFFS2_COMPR_ZERO && !je32_to_cpu(node.i.dsize) && je32_to_cpu(node.i.csize)) -+ tn->fn->size = je32_to_cpu(node.i.csize); - else // normal case... -- tn->fn->size = node.i.dsize; -+ tn->fn->size = je32_to_cpu(node.i.dsize); - tn->fn->raw = ref; -- D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %04x, dsize %04x\n", ref->flash_offset &~3, node.i.version, node.i.offset, node.i.dsize)); -+ D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %04x, dsize %04x\n", -+ ref_offset(ref), je32_to_cpu(node.i.version), -+ je32_to_cpu(node.i.offset), je32_to_cpu(node.i.dsize))); - jffs2_add_tn_to_list(tn, &ret_tn); - break; - - default: -- switch(node.u.nodetype & JFFS2_COMPAT_MASK) { -+ if (ref_flags(ref) == REF_UNCHECKED) { -+ struct jffs2_eraseblock *jeb; -+ uint32_t len; -+ -+ printk(KERN_ERR "Eep. Unknown node type %04x at %08x was marked REF_UNCHECKED\n", -+ je16_to_cpu(node.u.nodetype), ref_offset(ref)); -+ -+ /* Mark the node as having been checked and fix the accounting accordingly */ -+ spin_lock(&c->erase_completion_lock); -+ jeb = &c->blocks[ref->flash_offset / c->sector_size]; -+ len = ref_totlen(c, jeb, ref); -+ -+ jeb->used_size += len; -+ jeb->unchecked_size -= len; -+ c->used_size += len; -+ c->unchecked_size -= len; -+ -+ mark_ref_normal(ref); -+ spin_unlock(&c->erase_completion_lock); -+ } -+ node.u.nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(node.u.nodetype)); -+ if (crc32(0, &node, sizeof(struct jffs2_unknown_node)-4) != je32_to_cpu(node.u.hdr_crc)) { -+ /* Hmmm. This should have been caught at scan time. */ -+ printk(KERN_ERR "Node header CRC failed at %08x. But it must have been OK earlier.\n", -+ ref_offset(ref)); -+ printk(KERN_ERR "Node was: { %04x, %04x, %08x, %08x }\n", -+ je16_to_cpu(node.u.magic), je16_to_cpu(node.u.nodetype), je32_to_cpu(node.u.totlen), -+ je32_to_cpu(node.u.hdr_crc)); -+ jffs2_mark_node_obsolete(c, ref); -+ } else switch(je16_to_cpu(node.u.nodetype) & JFFS2_COMPAT_MASK) { - case JFFS2_FEATURE_INCOMPAT: -- printk(KERN_NOTICE "Unknown INCOMPAT nodetype %04X at %08X\n", node.u.nodetype, ref->flash_offset & ~3); -+ printk(KERN_NOTICE "Unknown INCOMPAT nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); -+ /* EEP */ -+ BUG(); - break; - case JFFS2_FEATURE_ROCOMPAT: -- printk(KERN_NOTICE "Unknown ROCOMPAT nodetype %04X at %08X\n", node.u.nodetype, ref->flash_offset & ~3); -+ printk(KERN_NOTICE "Unknown ROCOMPAT nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); -+ if (!(c->flags & JFFS2_SB_FLAG_RO)) -+ BUG(); - break; - case JFFS2_FEATURE_RWCOMPAT_COPY: -- printk(KERN_NOTICE "Unknown RWCOMPAT_COPY nodetype %04X at %08X\n", node.u.nodetype, ref->flash_offset & ~3); -+ printk(KERN_NOTICE "Unknown RWCOMPAT_COPY nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); - break; - case JFFS2_FEATURE_RWCOMPAT_DELETE: -- printk(KERN_NOTICE "Unknown RWCOMPAT_DELETE nodetype %04X at %08X\n", node.u.nodetype, ref->flash_offset & ~3); -+ printk(KERN_NOTICE "Unknown RWCOMPAT_DELETE nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); -+ jffs2_mark_node_obsolete(c, ref); - break; - } -+ - } -+ spin_lock(&c->erase_completion_lock); -+ - } -+ spin_unlock(&c->erase_completion_lock); - *tnp = ret_tn; - *fdp = ret_fd; - -@@ -266,19 +444,30 @@ - return err; - } - -+void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state) -+{ -+ spin_lock(&c->inocache_lock); -+ ic->state = state; -+ wake_up(&c->inocache_wq); -+ spin_unlock(&c->inocache_lock); -+} -+ -+/* During mount, this needs no locking. During normal operation, its -+ callers want to do other stuff while still holding the inocache_lock. -+ Rather than introducing special case get_ino_cache functions or -+ callbacks, we just let the caller do the locking itself. */ -+ - struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t ino) - { - struct jffs2_inode_cache *ret; - - D2(printk(KERN_DEBUG "jffs2_get_ino_cache(): ino %u\n", ino)); -- spin_lock (&c->inocache_lock); -+ - ret = c->inocache_list[ino % INOCACHE_HASHSIZE]; - while (ret && ret->ino < ino) { - ret = ret->next; - } - -- spin_unlock(&c->inocache_lock); -- - if (ret && ret->ino != ino) - ret = NULL; - -@@ -299,6 +488,7 @@ - } - new->next = *prev; - *prev = new; -+ - spin_unlock(&c->inocache_lock); - } - -@@ -316,6 +506,7 @@ - if ((*prev) == old) { - *prev = old->next; - } -+ - spin_unlock(&c->inocache_lock); - } - -@@ -352,3 +543,128 @@ - } - } - -+struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset) -+{ -+ /* The common case in lookup is that there will be a node -+ which precisely matches. So we go looking for that first */ -+ struct rb_node *next; -+ struct jffs2_node_frag *prev = NULL; -+ struct jffs2_node_frag *frag = NULL; -+ -+ D2(printk(KERN_DEBUG "jffs2_lookup_node_frag(%p, %d)\n", fragtree, offset)); -+ -+ next = fragtree->rb_node; -+ -+ while(next) { -+ frag = rb_entry(next, struct jffs2_node_frag, rb); -+ -+ D2(printk(KERN_DEBUG "Considering frag %d-%d (%p). left %p, right %p\n", -+ frag->ofs, frag->ofs+frag->size, frag, frag->rb.rb_left, frag->rb.rb_right)); -+ if (frag->ofs + frag->size <= offset) { -+ D2(printk(KERN_DEBUG "Going right from frag %d-%d, before the region we care about\n", -+ frag->ofs, frag->ofs+frag->size)); -+ /* Remember the closest smaller match on the way down */ -+ if (!prev || frag->ofs > prev->ofs) -+ prev = frag; -+ next = frag->rb.rb_right; -+ } else if (frag->ofs > offset) { -+ D2(printk(KERN_DEBUG "Going left from frag %d-%d, after the region we care about\n", -+ frag->ofs, frag->ofs+frag->size)); -+ next = frag->rb.rb_left; -+ } else { -+ D2(printk(KERN_DEBUG "Returning frag %d,%d, matched\n", -+ frag->ofs, frag->ofs+frag->size)); -+ return frag; -+ } -+ } -+ -+ /* Exact match not found. Go back up looking at each parent, -+ and return the closest smaller one */ -+ -+ if (prev) -+ D2(printk(KERN_DEBUG "No match. Returning frag %d,%d, closest previous\n", -+ prev->ofs, prev->ofs+prev->size)); -+ else -+ D2(printk(KERN_DEBUG "Returning NULL, empty fragtree\n")); -+ -+ return prev; -+} -+ -+/* Pass 'c' argument to indicate that nodes should be marked obsolete as -+ they're killed. */ -+void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) -+{ -+ struct jffs2_node_frag *frag; -+ struct jffs2_node_frag *parent; -+ -+ if (!root->rb_node) -+ return; -+ -+ frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb)); -+ -+ while(frag) { -+ if (frag->rb.rb_left) { -+ D2(printk(KERN_DEBUG "Going left from frag (%p) %d-%d\n", -+ frag, frag->ofs, frag->ofs+frag->size)); -+ frag = frag_left(frag); -+ continue; -+ } -+ if (frag->rb.rb_right) { -+ D2(printk(KERN_DEBUG "Going right from frag (%p) %d-%d\n", -+ frag, frag->ofs, frag->ofs+frag->size)); -+ frag = frag_right(frag); -+ continue; -+ } -+ -+ D2(printk(KERN_DEBUG "jffs2_kill_fragtree: frag at 0x%x-0x%x: node %p, frags %d--\n", -+ frag->ofs, frag->ofs+frag->size, frag->node, -+ frag->node?frag->node->frags:0)); -+ -+ if (frag->node && !(--frag->node->frags)) { -+ /* Not a hole, and it's the final remaining frag -+ of this node. Free the node */ -+ if (c) -+ jffs2_mark_node_obsolete(c, frag->node->raw); -+ -+ jffs2_free_full_dnode(frag->node); -+ } -+ parent = frag_parent(frag); -+ if (parent) { -+ if (frag_left(parent) == frag) -+ parent->rb.rb_left = NULL; -+ else -+ parent->rb.rb_right = NULL; -+ } -+ -+ jffs2_free_node_frag(frag); -+ frag = parent; -+ -+ cond_resched(); -+ } -+} -+ -+void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base) -+{ -+ struct rb_node *parent = &base->rb; -+ struct rb_node **link = &parent; -+ -+ D2(printk(KERN_DEBUG "jffs2_fragtree_insert(%p; %d-%d, %p)\n", newfrag, -+ newfrag->ofs, newfrag->ofs+newfrag->size, base)); -+ -+ while (*link) { -+ parent = *link; -+ base = rb_entry(parent, struct jffs2_node_frag, rb); -+ -+ D2(printk(KERN_DEBUG "fragtree_insert considering frag at 0x%x\n", base->ofs)); -+ if (newfrag->ofs > base->ofs) -+ link = &base->rb.rb_right; -+ else if (newfrag->ofs < base->ofs) -+ link = &base->rb.rb_left; -+ else { -+ printk(KERN_CRIT "Duplicate frag at %08x (%p,%p)\n", newfrag->ofs, newfrag, base); -+ BUG(); -+ } -+ } -+ -+ rb_link_node(&newfrag->rb, &base->rb, link); -+} -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/nodelist.h linux/fs/jffs2/nodelist.h ---- linux-mips-2.4.24-pre2/fs/jffs2/nodelist.h 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/nodelist.h 2004-11-17 18:17:59.000000000 +0100 -@@ -1,48 +1,35 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - -+#ifndef __JFFS2_NODELIST_H__ -+#define __JFFS2_NODELIST_H__ -+ - #include - #include -- -+#include -+#include - #include - #include - -+#ifdef __ECOS -+#include "os-ecos.h" -+#else -+#include /* For min/max in older kernels */ -+#include "os-linux.h" -+#endif -+ - #ifndef CONFIG_JFFS2_FS_DEBUG --#define CONFIG_JFFS2_FS_DEBUG 2 -+#define CONFIG_JFFS2_FS_DEBUG 1 - #endif - - #if CONFIG_JFFS2_FS_DEBUG > 0 -@@ -71,17 +58,21 @@ - for this inode instead. The inode_cache will have NULL in the first - word so you know when you've got there :) */ - struct jffs2_raw_node_ref *next_phys; -- // __u32 ino; -- __u32 flash_offset; -- __u32 totlen; --// __u16 nodetype; -+ uint32_t flash_offset; -+ uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */ -+}; - - /* flash_offset & 3 always has to be zero, because nodes are - always aligned at 4 bytes. So we have a couple of extra bits -- to play with. So we set the least significant bit to 1 to -- signify that the node is obsoleted by later nodes. -- */ --}; -+ to play with, which indicate the node's status; see below: */ -+#define REF_UNCHECKED 0 /* We haven't yet checked the CRC or built its inode */ -+#define REF_OBSOLETE 1 /* Obsolete, can be completely ignored */ -+#define REF_PRISTINE 2 /* Completely clean. GC without looking */ -+#define REF_NORMAL 3 /* Possibly overlapped. Read the page and write again on GC */ -+#define ref_flags(ref) ((ref)->flash_offset & 3) -+#define ref_offset(ref) ((ref)->flash_offset & ~3) -+#define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE) -+#define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0) - - /* - Used for keeping track of deletion nodes &c, which can only be marked -@@ -101,19 +92,35 @@ - a pointer to the first physical node which is part of this inode, too. - */ - struct jffs2_inode_cache { -- struct jffs2_scan_info *scan; /* Used during scan to hold -- temporary lists of nodes, and later must be set to -+ struct jffs2_full_dirent *scan_dents; /* Used during scan to hold -+ temporary lists of dirents, and later must be set to - NULL to mark the end of the raw_node_ref->next_in_ino - chain. */ - struct jffs2_inode_cache *next; - struct jffs2_raw_node_ref *nodes; -- __u32 ino; -+ uint32_t ino; - int nlink; -+ int state; - }; - -+/* Inode states for 'state' above. We need the 'GC' state to prevent -+ someone from doing a read_inode() while we're moving a 'REF_PRISTINE' -+ node without going through all the iget() nonsense */ -+#define INO_STATE_UNCHECKED 0 /* CRC checks not yet done */ -+#define INO_STATE_CHECKING 1 /* CRC checks in progress */ -+#define INO_STATE_PRESENT 2 /* In core */ -+#define INO_STATE_CHECKEDABSENT 3 /* Checked, cleared again */ -+#define INO_STATE_GC 4 /* GCing a 'pristine' node */ -+#define INO_STATE_READING 5 /* In read_inode() */ -+ -+#define INOCACHE_HASHSIZE 128 -+ - struct jffs2_scan_info { - struct jffs2_full_dirent *dents; - struct jffs2_tmp_dnode_info *tmpnodes; -+ /* Latest i_size info */ -+ uint32_t version; -+ uint32_t isize; - }; - /* - Larger representation of a raw node, kept in-core only when the -@@ -123,9 +130,9 @@ - struct jffs2_full_dnode - { - struct jffs2_raw_node_ref *raw; -- __u32 ofs; /* Don't really need this, but optimisation */ -- __u32 size; -- __u32 frags; /* Number of fragments which currently refer -+ uint32_t ofs; /* Don't really need this, but optimisation */ -+ uint32_t size; -+ uint32_t frags; /* Number of fragments which currently refer - to this node. When this reaches zero, - the node is obsolete. - */ -@@ -140,15 +147,15 @@ - { - struct jffs2_tmp_dnode_info *next; - struct jffs2_full_dnode *fn; -- __u32 version; -+ uint32_t version; - }; - - struct jffs2_full_dirent - { - struct jffs2_raw_node_ref *raw; - struct jffs2_full_dirent *next; -- __u32 version; -- __u32 ino; /* == zero for unlink */ -+ uint32_t version; -+ uint32_t ino; /* == zero for unlink */ - unsigned int nhash; - unsigned char type; - unsigned char name[0]; -@@ -159,21 +166,23 @@ - */ - struct jffs2_node_frag - { -- struct jffs2_node_frag *next; -+ struct rb_node rb; - struct jffs2_full_dnode *node; /* NULL for holes */ -- __u32 size; -- __u32 ofs; /* Don't really need this, but optimisation */ -+ uint32_t size; -+ uint32_t ofs; /* Don't really need this, but optimisation */ - }; - - struct jffs2_eraseblock - { - struct list_head list; - int bad_count; -- __u32 offset; /* of this block in the MTD */ -+ uint32_t offset; /* of this block in the MTD */ - -- __u32 used_size; -- __u32 dirty_size; -- __u32 free_size; /* Note that sector_size - free_size -+ uint32_t unchecked_size; -+ uint32_t used_size; -+ uint32_t dirty_size; -+ uint32_t wasted_size; -+ uint32_t free_size; /* Note that sector_size - free_size - is the address of the first free space */ - struct jffs2_raw_node_ref *first_node; - struct jffs2_raw_node_ref *last_node; -@@ -190,45 +199,134 @@ - }; - - #define ACCT_SANITY_CHECK(c, jeb) do { \ -- if (jeb->used_size + jeb->dirty_size + jeb->free_size != c->sector_size) { \ -- printk(KERN_NOTICE "Eeep. Space accounting for block at 0x%08x is screwed\n", jeb->offset); \ -- printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x != total %08x\n", \ -- jeb->free_size, jeb->dirty_size, jeb->used_size, c->sector_size); \ -+ struct jffs2_eraseblock *___j = jeb; \ -+ if ((___j) && ___j->used_size + ___j->dirty_size + ___j->free_size + ___j->wasted_size + ___j->unchecked_size != c->sector_size) { \ -+ printk(KERN_NOTICE "Eeep. Space accounting for block at 0x%08x is screwed\n", ___j->offset); \ -+ printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + wasted %08x + unchecked %08x != total %08x\n", \ -+ ___j->free_size, ___j->dirty_size, ___j->used_size, ___j->wasted_size, ___j->unchecked_size, c->sector_size); \ - BUG(); \ - } \ -- if (c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size != c->flash_size) { \ -+ if (c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size + c->wasted_size + c->unchecked_size != c->flash_size) { \ - printk(KERN_NOTICE "Eeep. Space accounting superblock info is screwed\n"); \ -- printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + erasing %08x + bad %08x != total %08x\n", \ -- c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, c->flash_size); \ -+ printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + erasing %08x + bad %08x + wasted %08x + unchecked %08x != total %08x\n", \ -+ c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, c->wasted_size, c->unchecked_size, c->flash_size); \ - BUG(); \ - } \ - } while(0) - -+static inline void paranoia_failed_dump(struct jffs2_eraseblock *jeb) -+{ -+ struct jffs2_raw_node_ref *ref; -+ int i=0; -+ -+ printk(KERN_NOTICE); -+ for (ref = jeb->first_node; ref; ref = ref->next_phys) { -+ printk("%08x->", ref_offset(ref)); -+ if (++i == 8) { -+ i = 0; -+ printk("\n" KERN_NOTICE); -+ } -+ } -+ printk("\n"); -+} -+ -+ - #define ACCT_PARANOIA_CHECK(jeb) do { \ -- __u32 my_used_size = 0; \ -+ uint32_t my_used_size = 0; \ -+ uint32_t my_unchecked_size = 0; \ - struct jffs2_raw_node_ref *ref2 = jeb->first_node; \ - while (ref2) { \ -- if (!(ref2->flash_offset & 1)) \ -- my_used_size += ref2->totlen; \ -+ if (unlikely(ref2->flash_offset < jeb->offset || \ -+ ref2->flash_offset > jeb->offset + c->sector_size)) { \ -+ printk(KERN_NOTICE "Node %08x shouldn't be in block at %08x!\n", \ -+ ref_offset(ref2), jeb->offset); \ -+ paranoia_failed_dump(jeb); \ -+ BUG(); \ -+ } \ -+ if (ref_flags(ref2) == REF_UNCHECKED) \ -+ my_unchecked_size += ref_totlen(c, jeb, ref2); \ -+ else if (!ref_obsolete(ref2)) \ -+ my_used_size += ref_totlen(c, jeb, ref2); \ -+ if (unlikely((!ref2->next_phys) != (ref2 == jeb->last_node))) { \ -+ printk("ref for node at %p (phys %08x) has next_phys->%p (%08x), last_node->%p (phys %08x)\n", \ -+ ref2, ref_offset(ref2), ref2->next_phys, ref_offset(ref2->next_phys), \ -+ jeb->last_node, ref_offset(jeb->last_node)); \ -+ paranoia_failed_dump(jeb); \ -+ BUG(); \ -+ } \ - ref2 = ref2->next_phys; \ - } \ - if (my_used_size != jeb->used_size) { \ - printk(KERN_NOTICE "Calculated used size %08x != stored used size %08x\n", my_used_size, jeb->used_size); \ - BUG(); \ - } \ -+ if (my_unchecked_size != jeb->unchecked_size) { \ -+ printk(KERN_NOTICE "Calculated unchecked size %08x != stored unchecked size %08x\n", my_unchecked_size, jeb->unchecked_size); \ -+ BUG(); \ -+ } \ - } while(0) - -+/* Calculate totlen from surrounding nodes or eraseblock */ -+static inline uint32_t __ref_totlen(struct jffs2_sb_info *c, -+ struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_node_ref *ref) -+{ -+ uint32_t ref_end; -+ -+ if (ref->next_phys) -+ ref_end = ref_offset(ref->next_phys); -+ else { -+ if (!jeb) -+ jeb = &c->blocks[ref->flash_offset / c->sector_size]; -+ -+ /* Last node in block. Use free_space */ -+ BUG_ON(ref != jeb->last_node); -+ ref_end = jeb->offset + c->sector_size - jeb->free_size; -+ } -+ return ref_end - ref_offset(ref); -+} -+ -+static inline uint32_t ref_totlen(struct jffs2_sb_info *c, -+ struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_node_ref *ref) -+{ -+ uint32_t ret; -+ -+ D1(if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) { -+ printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n", -+ jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref)); -+ BUG(); -+ }) -+ -+#if 1 -+ ret = ref->__totlen; -+#else -+ /* This doesn't actually work yet */ -+ ret = __ref_totlen(c, jeb, ref); -+ if (ret != ref->__totlen) { -+ printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n", -+ ref, ref_offset(ref), ref_offset(ref)+ref->__totlen, -+ ret, ref->__totlen); -+ if (!jeb) -+ jeb = &c->blocks[ref->flash_offset / c->sector_size]; -+ paranoia_failed_dump(jeb); -+ BUG(); -+ } -+#endif -+ return ret; -+} -+ -+ - #define ALLOC_NORMAL 0 /* Normal allocation */ - #define ALLOC_DELETION 1 /* Deletion node. Best to allow it */ - #define ALLOC_GC 2 /* Space requested for GC. Give it or die */ -+#define ALLOC_NORETRY 3 /* For jffs2_write_dnode: On failure, return -EAGAIN instead of retrying */ - --#define JFFS2_RESERVED_BLOCKS_BASE 3 /* Number of free blocks there must be before we... */ --#define JFFS2_RESERVED_BLOCKS_WRITE (JFFS2_RESERVED_BLOCKS_BASE + 2) /* ... allow a normal filesystem write */ --#define JFFS2_RESERVED_BLOCKS_DELETION (JFFS2_RESERVED_BLOCKS_BASE + 1) /* ... allow a normal filesystem deletion */ --#define JFFS2_RESERVED_BLOCKS_GCTRIGGER (JFFS2_RESERVED_BLOCKS_BASE + 3) /* ... wake up the GC thread */ --#define JFFS2_RESERVED_BLOCKS_GCBAD (JFFS2_RESERVED_BLOCKS_BASE + 1) /* ... pick a block from the bad_list to GC */ --#define JFFS2_RESERVED_BLOCKS_GCMERGE (JFFS2_RESERVED_BLOCKS_BASE) /* ... merge pages when garbage collecting */ -+/* How much dirty space before it goes on the very_dirty_list */ -+#define VERYDIRTY(c, size) ((size) >= ((c)->sector_size / 2)) - -+/* check if dirty space is more than 255 Byte */ -+#define ISDIRTY(size) ((size) > sizeof (struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN) - - #define PAD(x) (((x)+3)&~3) - -@@ -241,43 +339,75 @@ - return ((struct jffs2_inode_cache *)raw); - } - -+static inline struct jffs2_node_frag *frag_first(struct rb_root *root) -+{ -+ struct rb_node *node = root->rb_node; -+ -+ if (!node) -+ return NULL; -+ while(node->rb_left) -+ node = node->rb_left; -+ return rb_entry(node, struct jffs2_node_frag, rb); -+} -+#define rb_parent(rb) ((rb)->rb_parent) -+#define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb) -+#define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb) -+#define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb) -+#define frag_left(frag) rb_entry((frag)->rb.rb_left, struct jffs2_node_frag, rb) -+#define frag_right(frag) rb_entry((frag)->rb.rb_right, struct jffs2_node_frag, rb) -+#define frag_erase(frag, list) rb_erase(&frag->rb, list); -+ - /* nodelist.c */ - D1(void jffs2_print_frag_list(struct jffs2_inode_info *f)); - void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list); --void jffs2_add_tn_to_list(struct jffs2_tmp_dnode_info *tn, struct jffs2_tmp_dnode_info **list); - int jffs2_get_inode_nodes(struct jffs2_sb_info *c, ino_t ino, struct jffs2_inode_info *f, - struct jffs2_tmp_dnode_info **tnp, struct jffs2_full_dirent **fdp, -- __u32 *highest_version, __u32 *latest_mctime, -- __u32 *mctime_ver); -+ uint32_t *highest_version, uint32_t *latest_mctime, -+ uint32_t *mctime_ver); -+void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state); - struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t ino); - void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new); - void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old); - void jffs2_free_ino_caches(struct jffs2_sb_info *c); - void jffs2_free_raw_node_refs(struct jffs2_sb_info *c); -+struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset); -+void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c_delete); -+void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base); -+struct rb_node *rb_next(struct rb_node *); -+struct rb_node *rb_prev(struct rb_node *); -+void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); - - /* nodemgmt.c */ --int jffs2_reserve_space(struct jffs2_sb_info *c, __u32 minsize, __u32 *ofs, __u32 *len, int prio); --int jffs2_reserve_space_gc(struct jffs2_sb_info *c, __u32 minsize, __u32 *ofs, __u32 *len); --int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, __u32 len, int dirty); -+int jffs2_thread_should_wake(struct jffs2_sb_info *c); -+int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio); -+int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len); -+int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new); - void jffs2_complete_reservation(struct jffs2_sb_info *c); - void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); -+void jffs2_dump_block_lists(struct jffs2_sb_info *c); - - /* write.c */ --struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri); --struct jffs2_full_dnode *jffs2_write_dnode(struct inode *inode, struct jffs2_raw_inode *ri, const unsigned char *data, __u32 datalen, __u32 flash_ofs, __u32 *writelen); --struct jffs2_full_dirent *jffs2_write_dirent(struct inode *inode, struct jffs2_raw_dirent *rd, const unsigned char *name, __u32 namelen, __u32 flash_ofs, __u32 *writelen); -+int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri); -+ -+struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode); -+struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode); -+int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, -+ struct jffs2_raw_inode *ri, unsigned char *buf, -+ uint32_t offset, uint32_t writelen, uint32_t *retlen); -+int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen); -+int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f); -+int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen); -+ - - /* readinode.c */ --void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct jffs2_node_frag **list, __u32 size); --int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct jffs2_node_frag **list, struct jffs2_full_dnode *fn); -+void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); - int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); --void jffs2_read_inode (struct inode *); --void jffs2_clear_inode (struct inode *); -+int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, -+ uint32_t ino, struct jffs2_raw_inode *latest_node); -+int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); -+void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f); - - /* malloc.c */ --void jffs2_free_tmp_dnode_info_list(struct jffs2_tmp_dnode_info *tn); --void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd); -- - int jffs2_create_slab_caches(void); - void jffs2_destroy_slab_caches(void); - -@@ -301,54 +431,41 @@ - /* gc.c */ - int jffs2_garbage_collect_pass(struct jffs2_sb_info *c); - --/* background.c */ --int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c); --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 struct inode_operations jffs2_dir_inode_operations; -- --/* file.c */ --extern 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_null_fsync(struct file *, struct dentry *, int); --int jffs2_setattr (struct dentry *dentry, struct iattr *iattr); --int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg); --int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg); --int jffs2_readpage (struct file *, struct page *); --int jffs2_prepare_write (struct file *, struct page *, unsigned, unsigned); --int jffs2_commit_write (struct file *, struct page *, unsigned, unsigned); -- --/* ioctl.c */ --int jffs2_ioctl(struct inode *, struct file *, unsigned int, unsigned long); -- - /* read.c */ - int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsigned char *buf, int ofs, int len); -+int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, -+ unsigned char *buf, uint32_t offset, uint32_t len); -+char *jffs2_getlink(struct jffs2_sb_info *c, struct jffs2_inode_info *f); - - /* compr.c */ --unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 *datalen, __u32 *cdatalen); -+unsigned char jffs2_compress(unsigned char *data_in, unsigned char **cpage_out, -+ uint32_t *datalen, uint32_t *cdatalen); -+void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig); - int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, -- unsigned char *data_out, __u32 cdatalen, __u32 datalen); -+ unsigned char *data_out, uint32_t cdatalen, uint32_t datalen); - - /* scan.c */ - int jffs2_scan_medium(struct jffs2_sb_info *c); -+void jffs2_rotate_lists(struct jffs2_sb_info *c); - - /* build.c */ --int jffs2_build_filesystem(struct jffs2_sb_info *c); -- --/* symlink.c */ --extern struct inode_operations jffs2_symlink_inode_operations; -+int jffs2_do_mount_fs(struct jffs2_sb_info *c); - - /* erase.c */ - void jffs2_erase_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); --void jffs2_erase_pending_blocks(struct jffs2_sb_info *c); --void jffs2_mark_erased_blocks(struct jffs2_sb_info *c); --void jffs2_erase_pending_trigger(struct jffs2_sb_info *c); -+void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count); -+ -+#ifdef CONFIG_JFFS2_FS_NAND -+/* wbuf.c */ -+int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino); -+int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c); -+int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+int jffs2_nand_read_failcnt(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+#endif - - /* compr_zlib.c */ - int jffs2_zlib_init(void); - void jffs2_zlib_exit(void); -+ -+#endif /* __JFFS2_NODELIST_H__ */ -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/nodemgmt.c linux/fs/jffs2/nodemgmt.c ---- linux-mips-2.4.24-pre2/fs/jffs2/nodemgmt.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/nodemgmt.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,45 +1,21 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include - #include --#include - #include --#include -+#include -+#include /* For cond_resched() */ - #include "nodelist.h" - - /** -@@ -62,53 +38,95 @@ - * for the requested allocation. - */ - --static int jffs2_do_reserve_space(struct jffs2_sb_info *c, __u32 minsize, __u32 *ofs, __u32 *len); -+static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len); - --int jffs2_reserve_space(struct jffs2_sb_info *c, __u32 minsize, __u32 *ofs, __u32 *len, int prio) -+int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio) - { - int ret = -EAGAIN; -- int blocksneeded = JFFS2_RESERVED_BLOCKS_WRITE; -+ int blocksneeded = c->resv_blocks_write; - /* align it */ - minsize = PAD(minsize); - -- if (prio == ALLOC_DELETION) -- blocksneeded = JFFS2_RESERVED_BLOCKS_DELETION; -- - D1(printk(KERN_DEBUG "jffs2_reserve_space(): Requested 0x%x bytes\n", minsize)); - down(&c->alloc_sem); - - D1(printk(KERN_DEBUG "jffs2_reserve_space(): alloc sem got\n")); - -- spin_lock_bh(&c->erase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - -- /* this needs a little more thought */ -+ /* this needs a little more thought (true :)) */ - while(ret == -EAGAIN) { - while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) { - int ret; -+ uint32_t dirty, avail; -+ -+ /* calculate real dirty size -+ * dirty_size contains blocks on erase_pending_list -+ * those blocks are counted in c->nr_erasing_blocks. -+ * If one block is actually erased, it is not longer counted as dirty_space -+ * but it is counted in c->nr_erasing_blocks, so we add it and subtract it -+ * with c->nr_erasing_blocks * c->sector_size again. -+ * Blocks on erasable_list are counted as dirty_size, but not in c->nr_erasing_blocks -+ * This helps us to force gc and pick eventually a clean block to spread the load. -+ * We add unchecked_size here, as we hopefully will find some space to use. -+ * This will affect the sum only once, as gc first finishes checking -+ * of nodes. -+ */ -+ dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size + c->unchecked_size; -+ if (dirty < c->nospc_dirty_size) { -+ if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) { -+ printk(KERN_NOTICE "jffs2_reserve_space(): Low on dirty space to GC, but it's a deletion. Allowing...\n"); -+ break; -+ } -+ D1(printk(KERN_DEBUG "dirty size 0x%08x + unchecked_size 0x%08x < nospc_dirty_size 0x%08x, returning -ENOSPC\n", -+ dirty, c->unchecked_size, c->sector_size)); -+ -+ spin_unlock(&c->erase_completion_lock); -+ up(&c->alloc_sem); -+ return -ENOSPC; -+ } - -+ /* Calc possibly available space. Possibly available means that we -+ * don't know, if unchecked size contains obsoleted nodes, which could give us some -+ * more usable space. This will affect the sum only once, as gc first finishes checking -+ * of nodes. -+ + Return -ENOSPC, if the maximum possibly available space is less or equal than -+ * blocksneeded * sector_size. -+ * This blocks endless gc looping on a filesystem, which is nearly full, even if -+ * the check above passes. -+ */ -+ avail = c->free_size + c->dirty_size + c->erasing_size + c->unchecked_size; -+ if ( (avail / c->sector_size) <= blocksneeded) { -+ if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) { -+ printk(KERN_NOTICE "jffs2_reserve_space(): Low on possibly available space, but it's a deletion. Allowing...\n"); -+ break; -+ } -+ -+ D1(printk(KERN_DEBUG "max. available size 0x%08x < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n", -+ avail, blocksneeded * c->sector_size)); -+ spin_unlock(&c->erase_completion_lock); - up(&c->alloc_sem); -- if (c->dirty_size < c->sector_size) { -- D1(printk(KERN_DEBUG "Short on space, but total dirty size 0x%08x < sector size 0x%08x, so -ENOSPC\n", c->dirty_size, c->sector_size)); -- spin_unlock_bh(&c->erase_completion_lock); - return -ENOSPC; - } -- D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n", -- c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, -- c->free_size + c->dirty_size + c->used_size + c->erasing_size + c->bad_size, c->flash_size)); -- spin_unlock_bh(&c->erase_completion_lock); -+ -+ up(&c->alloc_sem); -+ -+ D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, wasted_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n", -+ c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->wasted_size, c->used_size, c->erasing_size, c->bad_size, -+ c->free_size + c->dirty_size + c->wasted_size + c->used_size + c->erasing_size + c->bad_size, c->flash_size)); -+ spin_unlock(&c->erase_completion_lock); - - ret = jffs2_garbage_collect_pass(c); - if (ret) - return ret; - -- if (current->need_resched) -- schedule(); -+ cond_resched(); - - if (signal_pending(current)) - return -EINTR; - - down(&c->alloc_sem); -- spin_lock_bh(&c->erase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - } - - ret = jffs2_do_reserve_space(c, minsize, ofs, len); -@@ -116,45 +134,72 @@ - D1(printk(KERN_DEBUG "jffs2_reserve_space: ret is %d\n", ret)); - } - } -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - if (ret) - up(&c->alloc_sem); - return ret; - } - --int jffs2_reserve_space_gc(struct jffs2_sb_info *c, __u32 minsize, __u32 *ofs, __u32 *len) -+int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len) - { - int ret = -EAGAIN; - minsize = PAD(minsize); - - D1(printk(KERN_DEBUG "jffs2_reserve_space_gc(): Requested 0x%x bytes\n", minsize)); - -- spin_lock_bh(&c->erase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - while(ret == -EAGAIN) { - ret = jffs2_do_reserve_space(c, minsize, ofs, len); - if (ret) { - D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret)); - } - } -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - return ret; - } - - /* Called with alloc sem _and_ erase_completion_lock */ --static int jffs2_do_reserve_space(struct jffs2_sb_info *c, __u32 minsize, __u32 *ofs, __u32 *len) -+static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len) - { - struct jffs2_eraseblock *jeb = c->nextblock; - - restart: - if (jeb && minsize > jeb->free_size) { - /* Skip the end of this block and file it as having some dirty space */ -- c->dirty_size += jeb->free_size; -+ /* If there's a pending write to it, flush now */ -+ if (jffs2_wbuf_dirty(c)) { -+ spin_unlock(&c->erase_completion_lock); -+ D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Flushing write buffer\n")); -+ jffs2_flush_wbuf_pad(c); -+ spin_lock(&c->erase_completion_lock); -+ jeb = c->nextblock; -+ goto restart; -+ } -+ c->wasted_size += jeb->free_size; - c->free_size -= jeb->free_size; -- jeb->dirty_size += jeb->free_size; -+ jeb->wasted_size += jeb->free_size; - jeb->free_size = 0; -+ -+ /* Check, if we have a dirty block now, or if it was dirty already */ -+ if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) { -+ c->dirty_size += jeb->wasted_size; -+ c->wasted_size -= jeb->wasted_size; -+ jeb->dirty_size += jeb->wasted_size; -+ jeb->wasted_size = 0; -+ if (VERYDIRTY(c, jeb->dirty_size)) { -+ D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", -+ jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); -+ list_add_tail(&jeb->list, &c->very_dirty_list); -+ } else { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->dirty_list); -+ } -+ } else { -+ D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", -+ jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); -+ list_add_tail(&jeb->list, &c->clean_list); -+ } - c->nextblock = jeb = NULL; - } - -@@ -164,33 +209,44 @@ - - if (list_empty(&c->free_list)) { - -- DECLARE_WAITQUEUE(wait, current); -+ if (!c->nr_erasing_blocks && -+ !list_empty(&c->erasable_list)) { -+ struct jffs2_eraseblock *ejeb; -+ -+ ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list); -+ list_del(&ejeb->list); -+ list_add_tail(&ejeb->list, &c->erase_pending_list); -+ c->nr_erasing_blocks++; -+ jffs2_erase_pending_trigger(c); -+ D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Triggering erase of erasable block at 0x%08x\n", -+ ejeb->offset)); -+ } -+ -+ if (!c->nr_erasing_blocks && -+ !list_empty(&c->erasable_pending_wbuf_list)) { -+ D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Flushing write buffer\n")); -+ /* c->nextblock is NULL, no update to c->nextblock allowed */ -+ spin_unlock(&c->erase_completion_lock); -+ jffs2_flush_wbuf_pad(c); -+ spin_lock(&c->erase_completion_lock); -+ /* Have another go. It'll be on the erasable_list now */ -+ return -EAGAIN; -+ } - - if (!c->nr_erasing_blocks) { --// if (list_empty(&c->erasing_list) && list_empty(&c->erase_pending_list) && list_empty(c->erase_complete_list)) { - /* Ouch. We're in GC, or we wouldn't have got here. - And there's no space left. At all. */ -- printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasingempty: %s, erasependingempty: %s)\n", -- c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no"); -+ printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", -+ c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasable_list)?"yes":"no", -+ list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no"); - return -ENOSPC; - } -- /* Make sure this can't deadlock. Someone has to start the erases -- of erase_pending blocks */ -- set_current_state(TASK_INTERRUPTIBLE); -- add_wait_queue(&c->erase_wait, &wait); -- D1(printk(KERN_DEBUG "Waiting for erases to complete. erasing_blocks is %d. (erasingempty: %s, erasependingempty: %s)\n", -- c->nr_erasing_blocks, list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no")); -- if (!list_empty(&c->erase_pending_list)) { -- D1(printk(KERN_DEBUG "Triggering pending erases\n")); -- jffs2_erase_pending_trigger(c); -- } -- spin_unlock_bh(&c->erase_completion_lock); -- schedule(); -- remove_wait_queue(&c->erase_wait, &wait); -- spin_lock_bh(&c->erase_completion_lock); -- if (signal_pending(current)) { -- return -EINTR; -- } -+ -+ spin_unlock(&c->erase_completion_lock); -+ /* Don't wait for it; just erase one right now */ -+ jffs2_erase_pending_blocks(c, 1); -+ spin_lock(&c->erase_completion_lock); -+ - /* An erase may have failed, decreasing the - amount of free space available. So we must - restart from the beginning */ -@@ -201,7 +257,8 @@ - list_del(next); - c->nextblock = jeb = list_entry(next, struct jffs2_eraseblock, list); - c->nr_free_blocks--; -- if (jeb->free_size != c->sector_size - sizeof(struct jffs2_unknown_node)) { -+ -+ if (jeb->free_size != c->sector_size - c->cleanmarker_size) { - printk(KERN_WARNING "Eep. Block 0x%08x taken from free_list had free_size of 0x%08x!!\n", jeb->offset, jeb->free_size); - goto restart; - } -@@ -210,6 +267,20 @@ - enough space */ - *ofs = jeb->offset + (c->sector_size - jeb->free_size); - *len = jeb->free_size; -+ -+ if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size && -+ !jeb->first_node->next_in_ino) { -+ /* Only node in it beforehand was a CLEANMARKER node (we think). -+ So mark it obsolete now that there's going to be another node -+ in the block. This will reduce used_size to zero but We've -+ already set c->nextblock so that jffs2_mark_node_obsolete() -+ won't try to refile it to the dirty_list. -+ */ -+ spin_unlock(&c->erase_completion_lock); -+ jffs2_mark_node_obsolete(c, jeb->first_node); -+ spin_lock(&c->erase_completion_lock); -+ } -+ - D1(printk(KERN_DEBUG "jffs2_do_reserve_space(): Giving 0x%x bytes at 0x%x\n", *len, *ofs)); - return 0; - } -@@ -217,9 +288,9 @@ - /** - * jffs2_add_physical_node_ref - add a physical node reference to the list - * @c: superblock info -- * @ofs: physical location of this physical node -+ * @new: new node reference to add - * @len: length of this physical node -- * @ino: inode number with which this physical node is associated -+ * @dirty: dirty flag for new node - * - * Should only be used to report nodes for which space has been allocated - * by jffs2_reserve_space. -@@ -227,47 +298,58 @@ - * Must be called with the alloc_sem held. - */ - --int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, __u32 len, int dirty) -+int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new) - { - struct jffs2_eraseblock *jeb; -+ uint32_t len; -+ -+ jeb = &c->blocks[new->flash_offset / c->sector_size]; -+ len = ref_totlen(c, jeb, new); - -- len = PAD(len); -- jeb = &c->blocks[(new->flash_offset & ~3) / c->sector_size]; -- D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x, size 0x%x\n", new->flash_offset & ~3, len)); -+ D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len)); - #if 1 -- if (jeb != c->nextblock || (new->flash_offset & ~3) != jeb->offset + (c->sector_size - jeb->free_size)) { -+ if (jeb != c->nextblock || (ref_offset(new)) != jeb->offset + (c->sector_size - jeb->free_size)) { - printk(KERN_WARNING "argh. node added in wrong place\n"); - jffs2_free_raw_node_ref(new); - return -EINVAL; - } - #endif -+ spin_lock(&c->erase_completion_lock); -+ - if (!jeb->first_node) - jeb->first_node = new; - if (jeb->last_node) - jeb->last_node->next_phys = new; - jeb->last_node = new; - -- spin_lock_bh(&c->erase_completion_lock); - jeb->free_size -= len; - c->free_size -= len; -- if (dirty) { -- new->flash_offset |= 1; -+ if (ref_obsolete(new)) { - jeb->dirty_size += len; - c->dirty_size += len; - } else { - jeb->used_size += len; - c->used_size += len; - } -- spin_unlock_bh(&c->erase_completion_lock); -+ - if (!jeb->free_size && !jeb->dirty_size) { - /* If it lives on the dirty_list, jffs2_reserve_space will put it there */ - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); -+ if (jffs2_wbuf_dirty(c)) { -+ /* Flush the last write in the block if it's outstanding */ -+ spin_unlock(&c->erase_completion_lock); -+ jffs2_flush_wbuf_pad(c); -+ spin_lock(&c->erase_completion_lock); -+ } -+ - list_add_tail(&jeb->list, &c->clean_list); - c->nextblock = NULL; - } - ACCT_SANITY_CHECK(c,jeb); -- ACCT_PARANOIA_CHECK(jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ spin_unlock(&c->erase_completion_lock); - - return 0; - } -@@ -280,20 +362,34 @@ - up(&c->alloc_sem); - } - -+static inline int on_list(struct list_head *obj, struct list_head *head) -+{ -+ struct list_head *this; -+ -+ list_for_each(this, head) { -+ if (this == obj) { -+ D1(printk("%p is on list at %p\n", obj, head)); -+ return 1; -+ -+ } -+ } -+ return 0; -+} -+ - void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref) - { - struct jffs2_eraseblock *jeb; - int blocknr; - struct jffs2_unknown_node n; -- int ret; -- ssize_t retlen; -+ int ret, addedsize; -+ size_t retlen; - - if(!ref) { - printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n"); - return; - } -- if (ref->flash_offset & 1) { -- D1(printk(KERN_DEBUG "jffs2_mark_node_obsolete called with already obsolete node at 0x%08x\n", ref->flash_offset &~3)); -+ if (ref_obsolete(ref)) { -+ D1(printk(KERN_DEBUG "jffs2_mark_node_obsolete called with already obsolete node at 0x%08x\n", ref_offset(ref))); - return; - } - blocknr = ref->flash_offset / c->sector_size; -@@ -302,22 +398,63 @@ - BUG(); - } - jeb = &c->blocks[blocknr]; -- if (jeb->used_size < ref->totlen) { -+ -+ spin_lock(&c->erase_completion_lock); -+ -+ if (ref_flags(ref) == REF_UNCHECKED) { -+ D1(if (unlikely(jeb->unchecked_size < ref_totlen(c, jeb, ref))) { -+ printk(KERN_NOTICE "raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n", -+ ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size); -+ BUG(); -+ }) -+ D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); -+ jeb->unchecked_size -= ref_totlen(c, jeb, ref); -+ c->unchecked_size -= ref_totlen(c, jeb, ref); -+ } else { -+ D1(if (unlikely(jeb->used_size < ref_totlen(c, jeb, ref))) { - printk(KERN_NOTICE "raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n", -- ref->totlen, blocknr, ref->flash_offset, jeb->used_size); -+ ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size); - BUG(); -+ }) -+ D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); -+ jeb->used_size -= ref_totlen(c, jeb, ref); -+ c->used_size -= ref_totlen(c, jeb, ref); -+ } -+ -+ // Take care, that wasted size is taken into concern -+ if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + ref_totlen(c, jeb, ref))) && jeb != c->nextblock) { -+ D1(printk("Dirtying\n")); -+ addedsize = ref_totlen(c, jeb, ref); -+ jeb->dirty_size += ref_totlen(c, jeb, ref); -+ c->dirty_size += ref_totlen(c, jeb, ref); -+ -+ /* Convert wasted space to dirty, if not a bad block */ -+ if (jeb->wasted_size) { -+ if (on_list(&jeb->list, &c->bad_used_list)) { -+ D1(printk(KERN_DEBUG "Leaving block at %08x on the bad_used_list\n", -+ jeb->offset)); -+ addedsize = 0; /* To fool the refiling code later */ -+ } else { -+ D1(printk(KERN_DEBUG "Converting %d bytes of wasted space to dirty in block at %08x\n", -+ jeb->wasted_size, jeb->offset)); -+ addedsize += jeb->wasted_size; -+ jeb->dirty_size += jeb->wasted_size; -+ c->dirty_size += jeb->wasted_size; -+ c->wasted_size -= jeb->wasted_size; -+ jeb->wasted_size = 0; - } -- -- spin_lock_bh(&c->erase_completion_lock); -- jeb->used_size -= ref->totlen; -- jeb->dirty_size += ref->totlen; -- c->used_size -= ref->totlen; -- c->dirty_size += ref->totlen; -- ref->flash_offset |= 1; -+ } -+ } else { -+ D1(printk("Wasting\n")); -+ addedsize = 0; -+ jeb->wasted_size += ref_totlen(c, jeb, ref); -+ c->wasted_size += ref_totlen(c, jeb, ref); -+ } -+ ref->flash_offset = ref_offset(ref) | REF_OBSOLETE; - - ACCT_SANITY_CHECK(c, jeb); - -- ACCT_PARANOIA_CHECK(jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); - - if (c->flags & JFFS2_SB_FLAG_MOUNTING) { - /* Mount in progress. Don't muck about with the block -@@ -325,68 +462,280 @@ - obliterate nodes that look obsolete. If they weren't - marked obsolete on the flash at the time they _became_ - obsolete, there was probably a reason for that. */ -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - return; - } -+ - if (jeb == c->nextblock) { - D2(printk(KERN_DEBUG "Not moving nextblock 0x%08x to dirty/erase_pending list\n", jeb->offset)); -- } else if (jeb == c->gcblock) { -- D2(printk(KERN_DEBUG "Not moving gcblock 0x%08x to dirty/erase_pending list\n", jeb->offset)); --#if 0 /* We no longer do this here. It can screw the wear levelling. If you have a lot of static -- data and a few blocks free, and you just create new files and keep deleting/overwriting -- them, then you'd keep erasing and reusing those blocks without ever moving stuff around. -- So we leave completely obsoleted blocks on the dirty_list and let the GC delete them -- when it finds them there. That way, we still get the 'once in a while, take a clean block' -- to spread out the flash usage */ -- } else if (!jeb->used_size) { -+ } else if (!jeb->used_size && !jeb->unchecked_size) { -+ if (jeb == c->gcblock) { -+ D1(printk(KERN_DEBUG "gcblock at 0x%08x completely dirtied. Clearing gcblock...\n", jeb->offset)); -+ c->gcblock = NULL; -+ } else { - D1(printk(KERN_DEBUG "Eraseblock at 0x%08x completely dirtied. Removing from (dirty?) list...\n", jeb->offset)); - list_del(&jeb->list); -+ } -+ if (jffs2_wbuf_dirty(c)) { -+ D1(printk(KERN_DEBUG "...and adding to erasable_pending_wbuf_list\n")); -+ list_add_tail(&jeb->list, &c->erasable_pending_wbuf_list); -+ } else { -+ if (jiffies & 127) { -+ /* Most of the time, we just erase it immediately. Otherwise we -+ spend ages scanning it on mount, etc. */ - D1(printk(KERN_DEBUG "...and adding to erase_pending_list\n")); - list_add_tail(&jeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; - jffs2_erase_pending_trigger(c); -- // OFNI_BS_2SFFJ(c)->s_dirt = 1; -+ } else { -+ /* Sometimes, however, we leave it elsewhere so it doesn't get -+ immediately reused, and we spread the load a bit. */ -+ D1(printk(KERN_DEBUG "...and adding to erasable_list\n")); -+ list_add_tail(&jeb->list, &c->erasable_list); -+ } -+ } - D1(printk(KERN_DEBUG "Done OK\n")); --#endif -- } else if (jeb->dirty_size == ref->totlen) { -+ } else if (jeb == c->gcblock) { -+ D2(printk(KERN_DEBUG "Not moving gcblock 0x%08x to dirty_list\n", jeb->offset)); -+ } else if (ISDIRTY(jeb->dirty_size) && !ISDIRTY(jeb->dirty_size - addedsize)) { - D1(printk(KERN_DEBUG "Eraseblock at 0x%08x is freshly dirtied. Removing from clean list...\n", jeb->offset)); - list_del(&jeb->list); - D1(printk(KERN_DEBUG "...and adding to dirty_list\n")); - list_add_tail(&jeb->list, &c->dirty_list); -+ } else if (VERYDIRTY(c, jeb->dirty_size) && -+ !VERYDIRTY(c, jeb->dirty_size - addedsize)) { -+ D1(printk(KERN_DEBUG "Eraseblock at 0x%08x is now very dirty. Removing from dirty list...\n", jeb->offset)); -+ list_del(&jeb->list); -+ D1(printk(KERN_DEBUG "...and adding to very_dirty_list\n")); -+ list_add_tail(&jeb->list, &c->very_dirty_list); -+ } else { -+ D1(printk(KERN_DEBUG "Eraseblock at 0x%08x not moved anywhere. (free 0x%08x, dirty 0x%08x, used 0x%08x)\n", -+ jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - } -- spin_unlock_bh(&c->erase_completion_lock); - -- if (c->mtd->type != MTD_NORFLASH && c->mtd->type != MTD_RAM) -+ spin_unlock(&c->erase_completion_lock); -+ -+ if (!jffs2_can_mark_obsolete(c)) - return; -- if (OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY) -+ if (jffs2_is_readonly(c)) - return; - -- D1(printk(KERN_DEBUG "obliterating obsoleted node at 0x%08x\n", ref->flash_offset &~3)); -- ret = c->mtd->read(c->mtd, ref->flash_offset &~3, sizeof(n), &retlen, (char *)&n); -+ D1(printk(KERN_DEBUG "obliterating obsoleted node at 0x%08x\n", ref_offset(ref))); -+ ret = jffs2_flash_read(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n); - if (ret) { -- printk(KERN_WARNING "Read error reading from obsoleted node at 0x%08x: %d\n", ref->flash_offset &~3, ret); -+ printk(KERN_WARNING "Read error reading from obsoleted node at 0x%08x: %d\n", ref_offset(ref), ret); - return; - } - if (retlen != sizeof(n)) { -- printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %d\n", ref->flash_offset &~3, retlen); -+ printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen); - return; - } -- if (PAD(n.totlen) != PAD(ref->totlen)) { -- printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen in node ref (0x%08x)\n", n.totlen, ref->totlen); -+ if (PAD(je32_to_cpu(n.totlen)) != PAD(ref_totlen(c, jeb, ref))) { -+ printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n", je32_to_cpu(n.totlen), ref_totlen(c, jeb, ref)); - return; - } -- if (!(n.nodetype & JFFS2_NODE_ACCURATE)) { -- D1(printk(KERN_DEBUG "Node at 0x%08x was already marked obsolete (nodetype 0x%04x\n", ref->flash_offset &~3, n.nodetype)); -+ if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) { -+ D1(printk(KERN_DEBUG "Node at 0x%08x was already marked obsolete (nodetype 0x%04x)\n", ref_offset(ref), je16_to_cpu(n.nodetype))); - return; - } -- n.nodetype &= ~JFFS2_NODE_ACCURATE; -- ret = c->mtd->write(c->mtd, ref->flash_offset&~3, sizeof(n), &retlen, (char *)&n); -+ /* XXX FIXME: This is ugly now */ -+ n.nodetype = cpu_to_je16(je16_to_cpu(n.nodetype) & ~JFFS2_NODE_ACCURATE); -+ ret = jffs2_flash_write(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n); - if (ret) { -- printk(KERN_WARNING "Write error in obliterating obsoleted node at 0x%08x: %d\n", ref->flash_offset &~3, ret); -+ printk(KERN_WARNING "Write error in obliterating obsoleted node at 0x%08x: %d\n", ref_offset(ref), ret); - return; - } - if (retlen != sizeof(n)) { -- printk(KERN_WARNING "Short write in obliterating obsoleted node at 0x%08x: %d\n", ref->flash_offset &~3, retlen); -+ printk(KERN_WARNING "Short write in obliterating obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen); - return; - } - } -+ -+#if CONFIG_JFFS2_FS_DEBUG > 0 -+void jffs2_dump_block_lists(struct jffs2_sb_info *c) -+{ -+ -+ -+ printk(KERN_DEBUG "jffs2_dump_block_lists:\n"); -+ printk(KERN_DEBUG "flash_size: %08x\n", c->flash_size); -+ printk(KERN_DEBUG "used_size: %08x\n", c->used_size); -+ printk(KERN_DEBUG "dirty_size: %08x\n", c->dirty_size); -+ printk(KERN_DEBUG "wasted_size: %08x\n", c->wasted_size); -+ printk(KERN_DEBUG "unchecked_size: %08x\n", c->unchecked_size); -+ printk(KERN_DEBUG "free_size: %08x\n", c->free_size); -+ printk(KERN_DEBUG "erasing_size: %08x\n", c->erasing_size); -+ printk(KERN_DEBUG "bad_size: %08x\n", c->bad_size); -+ printk(KERN_DEBUG "sector_size: %08x\n", c->sector_size); -+ printk(KERN_DEBUG "jffs2_reserved_blocks size: %08x\n",c->sector_size * c->resv_blocks_write); -+ -+ if (c->nextblock) { -+ printk(KERN_DEBUG "nextblock: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->unchecked_size, c->nextblock->free_size); -+ } else { -+ printk(KERN_DEBUG "nextblock: NULL\n"); -+ } -+ if (c->gcblock) { -+ printk(KERN_DEBUG "gcblock: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size); -+ } else { -+ printk(KERN_DEBUG "gcblock: NULL\n"); -+ } -+ if (list_empty(&c->clean_list)) { -+ printk(KERN_DEBUG "clean_list: empty\n"); -+ } else { -+ struct list_head *this; -+ int numblocks = 0; -+ uint32_t dirty = 0; -+ -+ list_for_each(this, &c->clean_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ numblocks ++; -+ dirty += jeb->wasted_size; -+ printk(KERN_DEBUG "clean_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ printk (KERN_DEBUG "Contains %d blocks with total wasted size %u, average wasted size: %u\n", numblocks, dirty, dirty / numblocks); -+ } -+ if (list_empty(&c->very_dirty_list)) { -+ printk(KERN_DEBUG "very_dirty_list: empty\n"); -+ } else { -+ struct list_head *this; -+ int numblocks = 0; -+ uint32_t dirty = 0; -+ -+ list_for_each(this, &c->very_dirty_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ numblocks ++; -+ dirty += jeb->dirty_size; -+ printk(KERN_DEBUG "very_dirty_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", -+ numblocks, dirty, dirty / numblocks); -+ } -+ if (list_empty(&c->dirty_list)) { -+ printk(KERN_DEBUG "dirty_list: empty\n"); -+ } else { -+ struct list_head *this; -+ int numblocks = 0; -+ uint32_t dirty = 0; -+ -+ list_for_each(this, &c->dirty_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ numblocks ++; -+ dirty += jeb->dirty_size; -+ printk(KERN_DEBUG "dirty_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", -+ numblocks, dirty, dirty / numblocks); -+ } -+ if (list_empty(&c->erasable_list)) { -+ printk(KERN_DEBUG "erasable_list: empty\n"); -+ } else { -+ struct list_head *this; -+ -+ list_for_each(this, &c->erasable_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ printk(KERN_DEBUG "erasable_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ } -+ if (list_empty(&c->erasing_list)) { -+ printk(KERN_DEBUG "erasing_list: empty\n"); -+ } else { -+ struct list_head *this; -+ -+ list_for_each(this, &c->erasing_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ printk(KERN_DEBUG "erasing_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ } -+ if (list_empty(&c->erase_pending_list)) { -+ printk(KERN_DEBUG "erase_pending_list: empty\n"); -+ } else { -+ struct list_head *this; -+ -+ list_for_each(this, &c->erase_pending_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ printk(KERN_DEBUG "erase_pending_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ } -+ if (list_empty(&c->erasable_pending_wbuf_list)) { -+ printk(KERN_DEBUG "erasable_pending_wbuf_list: empty\n"); -+ } else { -+ struct list_head *this; -+ -+ list_for_each(this, &c->erasable_pending_wbuf_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ printk(KERN_DEBUG "erasable_pending_wbuf_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ } -+ if (list_empty(&c->free_list)) { -+ printk(KERN_DEBUG "free_list: empty\n"); -+ } else { -+ struct list_head *this; -+ -+ list_for_each(this, &c->free_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ printk(KERN_DEBUG "free_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ } -+ if (list_empty(&c->bad_list)) { -+ printk(KERN_DEBUG "bad_list: empty\n"); -+ } else { -+ struct list_head *this; -+ -+ list_for_each(this, &c->bad_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ printk(KERN_DEBUG "bad_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ } -+ if (list_empty(&c->bad_used_list)) { -+ printk(KERN_DEBUG "bad_used_list: empty\n"); -+ } else { -+ struct list_head *this; -+ -+ list_for_each(this, &c->bad_used_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ printk(KERN_DEBUG "bad_used_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ } -+} -+#endif /* CONFIG_JFFS2_FS_DEBUG */ -+ -+int jffs2_thread_should_wake(struct jffs2_sb_info *c) -+{ -+ int ret = 0; -+ uint32_t dirty; -+ -+ if (c->unchecked_size) { -+ D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): unchecked_size %d, checked_ino #%d\n", -+ c->unchecked_size, c->checked_ino)); -+ return 1; -+ } -+ -+ /* dirty_size contains blocks on erase_pending_list -+ * those blocks are counted in c->nr_erasing_blocks. -+ * If one block is actually erased, it is not longer counted as dirty_space -+ * but it is counted in c->nr_erasing_blocks, so we add it and subtract it -+ * with c->nr_erasing_blocks * c->sector_size again. -+ * Blocks on erasable_list are counted as dirty_size, but not in c->nr_erasing_blocks -+ * This helps us to force gc and pick eventually a clean block to spread the load. -+ */ -+ dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size; -+ -+ if (c->nr_free_blocks + c->nr_erasing_blocks < c->resv_blocks_gctrigger && -+ (dirty > c->nospc_dirty_size)) -+ ret = 1; -+ -+ D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x: %s\n", -+ c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, ret?"yes":"no")); -+ -+ return ret; -+} -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/os-linux.h linux/fs/jffs2/os-linux.h ---- linux-mips-2.4.24-pre2/fs/jffs2/os-linux.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/os-linux.h 2004-11-17 18:17:59.365264368 +0100 -@@ -0,0 +1,212 @@ -+/* -+ * JFFS2 -- Journalling Flash File System, Version 2. -+ * -+ * Copyright (C) 2002-2003 Red Hat, Inc. -+ * -+ * Created by David Woodhouse -+ * -+ * For licensing information, see the file 'LICENCE' in this directory. -+ * -+ * $Id$ -+ * -+ */ -+ -+#ifndef __JFFS2_OS_LINUX_H__ -+#define __JFFS2_OS_LINUX_H__ -+#include -+ -+/* JFFS2 uses Linux mode bits natively -- no need for conversion */ -+#define os_to_jffs2_mode(x) (x) -+#define jffs2_to_os_mode(x) (x) -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,73) -+#define kstatfs statfs -+#endif -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2) -+#define JFFS2_INODE_INFO(i) (list_entry(i, struct jffs2_inode_info, vfs_inode)) -+#define OFNI_EDONI_2SFFJ(f) (&(f)->vfs_inode) -+#define JFFS2_SB_INFO(sb) (sb->s_fs_info) -+#define OFNI_BS_2SFFJ(c) ((struct super_block *)c->os_priv) -+#elif defined(JFFS2_OUT_OF_KERNEL) -+#define JFFS2_INODE_INFO(i) ((struct jffs2_inode_info *) &(i)->u) -+#define OFNI_EDONI_2SFFJ(f) ((struct inode *) ( ((char *)f) - ((char *)(&((struct inode *)NULL)->u)) ) ) -+#define JFFS2_SB_INFO(sb) ((struct jffs2_sb_info *) &(sb)->u) -+#define OFNI_BS_2SFFJ(c) ((struct super_block *) ( ((char *)c) - ((char *)(&((struct super_block *)NULL)->u)) ) ) -+#else -+#define JFFS2_INODE_INFO(i) (&i->u.jffs2_i) -+#define OFNI_EDONI_2SFFJ(f) ((struct inode *) ( ((char *)f) - ((char *)(&((struct inode *)NULL)->u)) ) ) -+#define JFFS2_SB_INFO(sb) (&sb->u.jffs2_sb) -+#define OFNI_BS_2SFFJ(c) ((struct super_block *) ( ((char *)c) - ((char *)(&((struct super_block *)NULL)->u)) ) ) -+#endif -+ -+ -+#define JFFS2_F_I_SIZE(f) (OFNI_EDONI_2SFFJ(f)->i_size) -+#define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode) -+#define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid) -+#define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid) -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,1) -+#define JFFS2_F_I_RDEV_MIN(f) (iminor(OFNI_EDONI_2SFFJ(f))) -+#define JFFS2_F_I_RDEV_MAJ(f) (imajor(OFNI_EDONI_2SFFJ(f))) -+#else -+#define JFFS2_F_I_RDEV_MIN(f) (MINOR(to_kdev_t(OFNI_EDONI_2SFFJ(f)->i_rdev))) -+#define JFFS2_F_I_RDEV_MAJ(f) (MAJOR(to_kdev_t(OFNI_EDONI_2SFFJ(f)->i_rdev))) -+#endif -+ -+/* Urgh. The things we do to keep the 2.4 build working */ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,47) -+#define ITIME(sec) ((struct timespec){sec, 0}) -+#define I_SEC(tv) ((tv).tv_sec) -+#define JFFS2_F_I_CTIME(f) (OFNI_EDONI_2SFFJ(f)->i_ctime.tv_sec) -+#define JFFS2_F_I_MTIME(f) (OFNI_EDONI_2SFFJ(f)->i_mtime.tv_sec) -+#define JFFS2_F_I_ATIME(f) (OFNI_EDONI_2SFFJ(f)->i_atime.tv_sec) -+#else -+#define ITIME(x) (x) -+#define I_SEC(x) (x) -+#define JFFS2_F_I_CTIME(f) (OFNI_EDONI_2SFFJ(f)->i_ctime) -+#define JFFS2_F_I_MTIME(f) (OFNI_EDONI_2SFFJ(f)->i_mtime) -+#define JFFS2_F_I_ATIME(f) (OFNI_EDONI_2SFFJ(f)->i_atime) -+#endif -+ -+#define sleep_on_spinunlock(wq, s) \ -+ do { \ -+ DECLARE_WAITQUEUE(__wait, current); \ -+ add_wait_queue((wq), &__wait); \ -+ set_current_state(TASK_UNINTERRUPTIBLE); \ -+ spin_unlock(s); \ -+ schedule(); \ -+ remove_wait_queue((wq), &__wait); \ -+ } while(0) -+ -+static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) -+{ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2) -+ f->highest_version = 0; -+ f->fragtree = RB_ROOT; -+ f->metadata = NULL; -+ f->dents = NULL; -+ f->flags = 0; -+ f->usercompr = 0; -+#else -+ memset(f, 0, sizeof(*f)); -+ init_MUTEX_LOCKED(&f->sem); -+#endif -+} -+ -+#define jffs2_is_readonly(c) (OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY) -+ -+#ifndef CONFIG_JFFS2_FS_NAND -+#define jffs2_can_mark_obsolete(c) (1) -+#define jffs2_cleanmarker_oob(c) (0) -+#define jffs2_write_nand_cleanmarker(c,jeb) (-EIO) -+ -+#define jffs2_flash_write(c, ofs, len, retlen, buf) ((c)->mtd->write((c)->mtd, ofs, len, retlen, buf)) -+#define jffs2_flash_read(c, ofs, len, retlen, buf) ((c)->mtd->read((c)->mtd, ofs, len, retlen, buf)) -+#define jffs2_flush_wbuf_pad(c) ({ (void)(c), 0; }) -+#define jffs2_flush_wbuf_gc(c, i) ({ (void)(c), (void) i, 0; }) -+#define jffs2_nand_read_failcnt(c,jeb) do { ; } while(0) -+#define jffs2_write_nand_badblock(c,jeb) do { ; } while(0) -+#define jffs2_nand_flash_setup(c) (0) -+#define jffs2_nand_flash_cleanup(c) do {} while(0) -+#define jffs2_wbuf_dirty(c) (0) -+#define jffs2_flash_writev(a,b,c,d,e,f) jffs2_flash_direct_writev(a,b,c,d,e) -+#define jffs2_wbuf_timeout NULL -+#define jffs2_wbuf_process NULL -+ -+#else /* NAND support present */ -+ -+#define jffs2_can_mark_obsolete(c) (c->mtd->type == MTD_NORFLASH || c->mtd->type == MTD_RAM) -+#define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH) -+ -+#define jffs2_flash_write_oob(c, ofs, len, retlen, buf) ((c)->mtd->write_oob((c)->mtd, ofs, len, retlen, buf)) -+#define jffs2_flash_read_oob(c, ofs, len, retlen, buf) ((c)->mtd->read_oob((c)->mtd, ofs, len, retlen, buf)) -+#define jffs2_wbuf_dirty(c) (!!(c)->wbuf_len) -+struct kstatfs; -+ -+/* wbuf.c */ -+int jffs2_flash_writev(struct jffs2_sb_info *c, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino); -+int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf); -+int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, u_char *buf); -+int jffs2_check_oob_empty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,int mode); -+int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+void jffs2_wbuf_timeout(unsigned long data); -+void jffs2_wbuf_process(void *data); -+int jffs2_nand_flash_setup(struct jffs2_sb_info *c); -+void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c); -+#endif /* NAND */ -+ -+/* erase.c */ -+static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) -+{ -+ OFNI_BS_2SFFJ(c)->s_dirt = 1; -+} -+ -+/* background.c */ -+int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c); -+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 struct inode_operations jffs2_dir_inode_operations; -+ -+/* file.c */ -+extern 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); -+int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg); -+int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg); -+int jffs2_readpage (struct file *, struct page *); -+int jffs2_prepare_write (struct file *, struct page *, unsigned, unsigned); -+int jffs2_commit_write (struct file *, struct page *, unsigned, unsigned); -+ -+/* ioctl.c */ -+int jffs2_ioctl(struct inode *, struct file *, unsigned int, unsigned long); -+ -+/* symlink.c */ -+extern struct inode_operations jffs2_symlink_inode_operations; -+ -+/* fs.c */ -+int jffs2_setattr (struct dentry *, struct iattr *); -+void jffs2_read_inode (struct inode *); -+void jffs2_clear_inode (struct inode *); -+void jffs2_dirty_inode(struct inode *inode); -+struct inode *jffs2_new_inode (struct inode *dir_i, int mode, -+ struct jffs2_raw_inode *ri); -+int jffs2_statfs (struct super_block *, struct kstatfs *); -+void jffs2_write_super (struct super_block *); -+int jffs2_remount_fs (struct super_block *, int *, char *); -+int jffs2_do_fill_super(struct super_block *sb, void *data, int silent); -+void jffs2_gc_release_inode(struct jffs2_sb_info *c, -+ struct jffs2_inode_info *f); -+struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, -+ int inum, int nlink); -+ -+unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, -+ struct jffs2_inode_info *f, -+ unsigned long offset, -+ unsigned long *priv); -+void jffs2_gc_release_page(struct jffs2_sb_info *c, -+ unsigned char *pg, -+ unsigned long *priv); -+ -+ -+/* writev.c */ -+int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs, -+ unsigned long count, loff_t to, size_t *retlen); -+ -+/* Compression config */ -+#define JFFS2_COMPRESSION -+#undef JFFS2_USE_DYNRUBIN /* Disabled 23/9/1. With zlib it hardly ever gets a look in */ -+#undef JFFS2_USE_RUBINMIPS /* Disabled 26/2/1. Obsoleted by dynrubin */ -+#define JFFS2_USE_ZLIB -+#define JFFS2_USE_RTIME /* rtime does manage to recompress already-compressed data */ -+ -+ -+#endif /* __JFFS2_OS_LINUX_H__ */ -+ -+ -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/pushpull.h linux/fs/jffs2/pushpull.h ---- linux-mips-2.4.24-pre2/fs/jffs2/pushpull.h 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/pushpull.h 2004-11-17 18:17:59.000000000 +0100 -@@ -1,42 +1,21 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001, 2002 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #ifndef __PUSHPULL_H__ - #define __PUSHPULL_H__ -+ -+#include -+ - struct pushpull { - unsigned char *buf; - unsigned int buflen; -@@ -44,9 +23,36 @@ - unsigned int reserve; - }; - --void init_pushpull(struct pushpull *, char *, unsigned, unsigned, unsigned); --int pushbit(struct pushpull *pp, int bit, int use_reserved); --int pushedbits(struct pushpull *pp); -+ -+static inline void init_pushpull(struct pushpull *pp, char *buf, unsigned buflen, unsigned ofs, unsigned reserve) -+{ -+ pp->buf = buf; -+ pp->buflen = buflen; -+ pp->ofs = ofs; -+ pp->reserve = reserve; -+} -+ -+static inline int pushbit(struct pushpull *pp, int bit, int use_reserved) -+{ -+ if (pp->ofs >= pp->buflen - (use_reserved?0:pp->reserve)) { -+ return -ENOSPC; -+ } -+ -+ if (bit) { -+ pp->buf[pp->ofs >> 3] |= (1<<(7-(pp->ofs &7))); -+ } -+ else { -+ pp->buf[pp->ofs >> 3] &= ~(1<<(7-(pp->ofs &7))); -+ } -+ pp->ofs++; -+ -+ return 0; -+} -+ -+static inline int pushedbits(struct pushpull *pp) -+{ -+ return pp->ofs; -+} - - static inline int pullbit(struct pushpull *pp) - { -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/rbtree.c linux/fs/jffs2/rbtree.c ---- linux-mips-2.4.24-pre2/fs/jffs2/rbtree.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/rbtree.c 2004-11-17 18:17:59.368263912 +0100 -@@ -0,0 +1,363 @@ -+/* -+ Red Black Trees -+ (C) 1999 Andrea Arcangeli -+ (C) 2002 David Woodhouse -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the 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 -+ -+ $Id$ -+*/ -+ -+#ifdef __ECOS /* This file is _not_ under the eCos licence; it is pure GPL. */ -+#error "Licence problem. eCos has its own rbtree code." -+#endif -+ -+#include -+#include -+ -+/* This wasn't present till 2.4.11, wasn't exported till 2.4.19 */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,11) || \ -+ (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19) && defined(MODULE)) -+static void __rb_rotate_left(struct rb_node * node, struct rb_root * root) -+{ -+ struct rb_node * right = node->rb_right; -+ -+ if ((node->rb_right = right->rb_left)) -+ right->rb_left->rb_parent = node; -+ right->rb_left = node; -+ -+ if ((right->rb_parent = node->rb_parent)) -+ { -+ if (node == node->rb_parent->rb_left) -+ node->rb_parent->rb_left = right; -+ else -+ node->rb_parent->rb_right = right; -+ } -+ else -+ root->rb_node = right; -+ node->rb_parent = right; -+} -+ -+static void __rb_rotate_right(struct rb_node * node, struct rb_root * root) -+{ -+ struct rb_node * left = node->rb_left; -+ -+ if ((node->rb_left = left->rb_right)) -+ left->rb_right->rb_parent = node; -+ left->rb_right = node; -+ -+ if ((left->rb_parent = node->rb_parent)) -+ { -+ if (node == node->rb_parent->rb_right) -+ node->rb_parent->rb_right = left; -+ else -+ node->rb_parent->rb_left = left; -+ } -+ else -+ root->rb_node = left; -+ node->rb_parent = left; -+} -+ -+void rb_insert_color(struct rb_node * node, struct rb_root * root) -+{ -+ struct rb_node * parent, * gparent; -+ -+ while ((parent = node->rb_parent) && parent->rb_color == RB_RED) -+ { -+ gparent = parent->rb_parent; -+ -+ if (parent == gparent->rb_left) -+ { -+ { -+ register struct rb_node * uncle = gparent->rb_right; -+ if (uncle && uncle->rb_color == RB_RED) -+ { -+ uncle->rb_color = RB_BLACK; -+ parent->rb_color = RB_BLACK; -+ gparent->rb_color = RB_RED; -+ node = gparent; -+ continue; -+ } -+ } -+ -+ if (parent->rb_right == node) -+ { -+ register struct rb_node * tmp; -+ __rb_rotate_left(parent, root); -+ tmp = parent; -+ parent = node; -+ node = tmp; -+ } -+ -+ parent->rb_color = RB_BLACK; -+ gparent->rb_color = RB_RED; -+ __rb_rotate_right(gparent, root); -+ } else { -+ { -+ register struct rb_node * uncle = gparent->rb_left; -+ if (uncle && uncle->rb_color == RB_RED) -+ { -+ uncle->rb_color = RB_BLACK; -+ parent->rb_color = RB_BLACK; -+ gparent->rb_color = RB_RED; -+ node = gparent; -+ continue; -+ } -+ } -+ -+ if (parent->rb_left == node) -+ { -+ register struct rb_node * tmp; -+ __rb_rotate_right(parent, root); -+ tmp = parent; -+ parent = node; -+ node = tmp; -+ } -+ -+ parent->rb_color = RB_BLACK; -+ gparent->rb_color = RB_RED; -+ __rb_rotate_left(gparent, root); -+ } -+ } -+ -+ root->rb_node->rb_color = RB_BLACK; -+} -+ -+static void __rb_erase_color(struct rb_node * node, struct rb_node * parent, -+ struct rb_root * root) -+{ -+ struct rb_node * other; -+ -+ while ((!node || node->rb_color == RB_BLACK) && node != root->rb_node) -+ { -+ if (parent->rb_left == node) -+ { -+ other = parent->rb_right; -+ if (other->rb_color == RB_RED) -+ { -+ other->rb_color = RB_BLACK; -+ parent->rb_color = RB_RED; -+ __rb_rotate_left(parent, root); -+ other = parent->rb_right; -+ } -+ if ((!other->rb_left || -+ other->rb_left->rb_color == RB_BLACK) -+ && (!other->rb_right || -+ other->rb_right->rb_color == RB_BLACK)) -+ { -+ other->rb_color = RB_RED; -+ node = parent; -+ parent = node->rb_parent; -+ } -+ else -+ { -+ if (!other->rb_right || -+ other->rb_right->rb_color == RB_BLACK) -+ { -+ register struct rb_node * o_left; -+ if ((o_left = other->rb_left)) -+ o_left->rb_color = RB_BLACK; -+ other->rb_color = RB_RED; -+ __rb_rotate_right(other, root); -+ other = parent->rb_right; -+ } -+ other->rb_color = parent->rb_color; -+ parent->rb_color = RB_BLACK; -+ if (other->rb_right) -+ other->rb_right->rb_color = RB_BLACK; -+ __rb_rotate_left(parent, root); -+ node = root->rb_node; -+ break; -+ } -+ } -+ else -+ { -+ other = parent->rb_left; -+ if (other->rb_color == RB_RED) -+ { -+ other->rb_color = RB_BLACK; -+ parent->rb_color = RB_RED; -+ __rb_rotate_right(parent, root); -+ other = parent->rb_left; -+ } -+ if ((!other->rb_left || -+ other->rb_left->rb_color == RB_BLACK) -+ && (!other->rb_right || -+ other->rb_right->rb_color == RB_BLACK)) -+ { -+ other->rb_color = RB_RED; -+ node = parent; -+ parent = node->rb_parent; -+ } -+ else -+ { -+ if (!other->rb_left || -+ other->rb_left->rb_color == RB_BLACK) -+ { -+ register struct rb_node * o_right; -+ if ((o_right = other->rb_right)) -+ o_right->rb_color = RB_BLACK; -+ other->rb_color = RB_RED; -+ __rb_rotate_left(other, root); -+ other = parent->rb_left; -+ } -+ other->rb_color = parent->rb_color; -+ parent->rb_color = RB_BLACK; -+ if (other->rb_left) -+ other->rb_left->rb_color = RB_BLACK; -+ __rb_rotate_right(parent, root); -+ node = root->rb_node; -+ break; -+ } -+ } -+ } -+ if (node) -+ node->rb_color = RB_BLACK; -+} -+ -+void rb_erase(struct rb_node * node, struct rb_root * root) -+{ -+ struct rb_node * child, * parent; -+ int color; -+ -+ if (!node->rb_left) -+ child = node->rb_right; -+ else if (!node->rb_right) -+ child = node->rb_left; -+ else -+ { -+ struct rb_node * old = node, * left; -+ -+ node = node->rb_right; -+ while ((left = node->rb_left)) -+ node = left; -+ child = node->rb_right; -+ parent = node->rb_parent; -+ color = node->rb_color; -+ -+ if (child) -+ child->rb_parent = parent; -+ if (parent) -+ { -+ if (parent->rb_left == node) -+ parent->rb_left = child; -+ else -+ parent->rb_right = child; -+ } -+ else -+ root->rb_node = child; -+ -+ if (node->rb_parent == old) -+ parent = node; -+ node->rb_parent = old->rb_parent; -+ node->rb_color = old->rb_color; -+ node->rb_right = old->rb_right; -+ node->rb_left = old->rb_left; -+ -+ if (old->rb_parent) -+ { -+ if (old->rb_parent->rb_left == old) -+ old->rb_parent->rb_left = node; -+ else -+ old->rb_parent->rb_right = node; -+ } else -+ root->rb_node = node; -+ -+ old->rb_left->rb_parent = node; -+ if (old->rb_right) -+ old->rb_right->rb_parent = node; -+ goto color; -+ } -+ -+ parent = node->rb_parent; -+ color = node->rb_color; -+ -+ if (child) -+ child->rb_parent = parent; -+ if (parent) -+ { -+ if (parent->rb_left == node) -+ parent->rb_left = child; -+ else -+ parent->rb_right = child; -+ } -+ else -+ root->rb_node = child; -+ -+ color: -+ if (color == RB_BLACK) -+ __rb_erase_color(child, parent, root); -+} -+#endif /* Before 2.4.11 */ -+ -+ /* These routines haven't made it into 2.4 (yet) */ -+struct rb_node *rb_next(struct rb_node *node) -+{ -+ /* If we have a right-hand child, go down and then left as far -+ as we can. */ -+ if (node->rb_right) { -+ node = node->rb_right; -+ while (node->rb_left) -+ node=node->rb_left; -+ return node; -+ } -+ -+ /* No right-hand children. Everything down and left is -+ smaller than us, so any 'next' node must be in the general -+ direction of our parent. Go up the tree; any time the -+ ancestor is a right-hand child of its parent, keep going -+ up. First time it's a left-hand child of its parent, said -+ parent is our 'next' node. */ -+ while (node->rb_parent && node == node->rb_parent->rb_right) -+ node = node->rb_parent; -+ -+ return node->rb_parent; -+} -+ -+struct rb_node *rb_prev(struct rb_node *node) -+{ -+ if (node->rb_left) { -+ node = node->rb_left; -+ while (node->rb_right) -+ node=node->rb_right; -+ return node; -+ } -+ while (node->rb_parent && node == node->rb_parent->rb_left) -+ node = node->rb_parent; -+ -+ return node->rb_parent; -+} -+ -+void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root) -+{ -+ struct rb_node *parent = victim->rb_parent; -+ -+ /* Set the surrounding nodes to point to the replacement */ -+ if (parent) { -+ if (victim == parent->rb_left) -+ parent->rb_left = new; -+ else -+ parent->rb_right = new; -+ } else { -+ root->rb_node = new; -+ } -+ if (victim->rb_left) -+ victim->rb_left->rb_parent = new; -+ if (victim->rb_right) -+ victim->rb_right->rb_parent = new; -+ -+ /* Copy the pointers/colour from the victim to the replacement */ -+ *new = *victim; -+} -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/read.c linux/fs/jffs2/read.c ---- linux-mips-2.4.24-pre2/fs/jffs2/read.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/read.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,52 +1,29 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include - #include --#include -+#include -+#include - #include -+#include - #include "nodelist.h" --#include - - int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsigned char *buf, int ofs, int len) - { - struct jffs2_raw_inode *ri; - size_t readlen; -- __u32 crc; -+ uint32_t crc; - unsigned char *decomprbuf = NULL; - unsigned char *readbuf = NULL; - int ret = 0; -@@ -55,35 +32,41 @@ - if (!ri) - return -ENOMEM; - -- ret = c->mtd->read(c->mtd, fd->raw->flash_offset & ~3, sizeof(*ri), &readlen, (char *)ri); -+ ret = jffs2_flash_read(c, ref_offset(fd->raw), sizeof(*ri), &readlen, (char *)ri); - if (ret) { - jffs2_free_raw_inode(ri); -- printk(KERN_WARNING "Error reading node from 0x%08x: %d\n", fd->raw->flash_offset & ~3, ret); -+ printk(KERN_WARNING "Error reading node from 0x%08x: %d\n", ref_offset(fd->raw), ret); - return ret; - } - if (readlen != sizeof(*ri)) { - jffs2_free_raw_inode(ri); -- printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%x bytes, got 0x%x\n", -- fd->raw->flash_offset & ~3, sizeof(*ri), readlen); -+ printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%zx bytes, got 0x%zx\n", -+ ref_offset(fd->raw), sizeof(*ri), readlen); - return -EIO; - } - crc = crc32(0, ri, sizeof(*ri)-8); - -- D1(printk(KERN_DEBUG "Node read from %08x: node_crc %08x, calculated CRC %08x. dsize %x, csize %x, offset %x, buf %p\n", fd->raw->flash_offset & ~3, ri->node_crc, crc, ri->dsize, ri->csize, ri->offset, buf)); -- if (crc != ri->node_crc) { -- printk(KERN_WARNING "Node CRC %08x != calculated CRC %08x for node at %08x\n", ri->node_crc, crc, fd->raw->flash_offset & ~3); -+ D1(printk(KERN_DEBUG "Node read from %08x: node_crc %08x, calculated CRC %08x. dsize %x, csize %x, offset %x, buf %p\n", -+ ref_offset(fd->raw), je32_to_cpu(ri->node_crc), -+ crc, je32_to_cpu(ri->dsize), je32_to_cpu(ri->csize), -+ je32_to_cpu(ri->offset), buf)); -+ if (crc != je32_to_cpu(ri->node_crc)) { -+ printk(KERN_WARNING "Node CRC %08x != calculated CRC %08x for node at %08x\n", -+ je32_to_cpu(ri->node_crc), crc, ref_offset(fd->raw)); - ret = -EIO; - goto out_ri; - } - /* There was a bug where we wrote hole nodes out with csize/dsize - swapped. Deal with it */ -- if (ri->compr == JFFS2_COMPR_ZERO && !ri->dsize && ri->csize) { -+ if (ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) && -+ je32_to_cpu(ri->csize)) { - ri->dsize = ri->csize; -- ri->csize = 0; -+ ri->csize = cpu_to_je32(0); - } - -- D1(if(ofs + len > ri->dsize) { -- printk(KERN_WARNING "jffs2_read_dnode() asked for %d bytes at %d from %d-byte node\n", len, ofs, ri->dsize); -+ D1(if(ofs + len > je32_to_cpu(ri->dsize)) { -+ printk(KERN_WARNING "jffs2_read_dnode() asked for %d bytes at %d from %d-byte node\n", -+ len, ofs, je32_to_cpu(ri->dsize)); - ret = -EINVAL; - goto out_ri; - }); -@@ -100,18 +83,18 @@ - Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy - Reading partial node and it's compressed - read into readbuf, check checksum, decompress to decomprbuf and copy - */ -- if (ri->compr == JFFS2_COMPR_NONE && len == ri->dsize) { -+ if (ri->compr == JFFS2_COMPR_NONE && len == je32_to_cpu(ri->dsize)) { - readbuf = buf; - } else { -- readbuf = kmalloc(ri->csize, GFP_KERNEL); -+ readbuf = kmalloc(je32_to_cpu(ri->csize), GFP_KERNEL); - if (!readbuf) { - ret = -ENOMEM; - goto out_ri; - } - } - if (ri->compr != JFFS2_COMPR_NONE) { -- if (len < ri->dsize) { -- decomprbuf = kmalloc(ri->dsize, GFP_KERNEL); -+ if (len < je32_to_cpu(ri->dsize)) { -+ decomprbuf = kmalloc(je32_to_cpu(ri->dsize), GFP_KERNEL); - if (!decomprbuf) { - ret = -ENOMEM; - goto out_readbuf; -@@ -123,31 +106,35 @@ - decomprbuf = readbuf; - } - -- D2(printk(KERN_DEBUG "Read %d bytes to %p\n", ri->csize, readbuf)); -- ret = c->mtd->read(c->mtd, (fd->raw->flash_offset &~3) + sizeof(*ri), ri->csize, &readlen, readbuf); -+ D2(printk(KERN_DEBUG "Read %d bytes to %p\n", je32_to_cpu(ri->csize), -+ readbuf)); -+ ret = jffs2_flash_read(c, (ref_offset(fd->raw)) + sizeof(*ri), -+ je32_to_cpu(ri->csize), &readlen, readbuf); - -- if (!ret && readlen != ri->csize) -+ if (!ret && readlen != je32_to_cpu(ri->csize)) - ret = -EIO; - if (ret) - goto out_decomprbuf; - -- crc = crc32(0, readbuf, ri->csize); -- if (crc != ri->data_crc) { -- printk(KERN_WARNING "Data CRC %08x != calculated CRC %08x for node at %08x\n", ri->data_crc, crc, fd->raw->flash_offset & ~3); -+ crc = crc32(0, readbuf, je32_to_cpu(ri->csize)); -+ if (crc != je32_to_cpu(ri->data_crc)) { -+ printk(KERN_WARNING "Data CRC %08x != calculated CRC %08x for node at %08x\n", -+ je32_to_cpu(ri->data_crc), crc, ref_offset(fd->raw)); - ret = -EIO; - goto out_decomprbuf; - } - D2(printk(KERN_DEBUG "Data CRC matches calculated CRC %08x\n", crc)); - if (ri->compr != JFFS2_COMPR_NONE) { -- D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n", ri->csize, readbuf, ri->dsize, decomprbuf)); -- ret = jffs2_decompress(ri->compr, readbuf, decomprbuf, ri->csize, ri->dsize); -+ D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n", -+ je32_to_cpu(ri->csize), readbuf, je32_to_cpu(ri->dsize), decomprbuf)); -+ ret = jffs2_decompress(ri->compr, readbuf, decomprbuf, je32_to_cpu(ri->csize), je32_to_cpu(ri->dsize)); - if (ret) { - printk(KERN_WARNING "Error: jffs2_decompress returned %d\n", ret); - goto out_decomprbuf; - } - } - -- if (len < ri->dsize) { -+ if (len < je32_to_cpu(ri->dsize)) { - memcpy(buf, decomprbuf+ofs, len); - } - out_decomprbuf: -@@ -161,3 +148,96 @@ - - return ret; - } -+ -+int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, -+ unsigned char *buf, uint32_t offset, uint32_t len) -+{ -+ uint32_t end = offset + len; -+ struct jffs2_node_frag *frag; -+ int ret; -+ -+ D1(printk(KERN_DEBUG "jffs2_read_inode_range: ino #%u, range 0x%08x-0x%08x\n", -+ f->inocache->ino, offset, offset+len)); -+ -+ frag = jffs2_lookup_node_frag(&f->fragtree, offset); -+ -+ /* XXX FIXME: Where a single physical node actually shows up in two -+ frags, we read it twice. Don't do that. */ -+ /* Now we're pointing at the first frag which overlaps our page */ -+ while(offset < end) { -+ D2(printk(KERN_DEBUG "jffs2_read_inode_range: offset %d, end %d\n", offset, end)); -+ if (unlikely(!frag || frag->ofs > offset)) { -+ uint32_t holesize = end - offset; -+ if (frag) { -+ D1(printk(KERN_NOTICE "Eep. Hole in ino #%u fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n", f->inocache->ino, frag->ofs, offset)); -+ holesize = min(holesize, frag->ofs - offset); -+ D1(jffs2_print_frag_list(f)); -+ } -+ D1(printk(KERN_DEBUG "Filling non-frag hole from %d-%d\n", offset, offset+holesize)); -+ memset(buf, 0, holesize); -+ buf += holesize; -+ offset += holesize; -+ continue; -+ } else if (unlikely(!frag->node)) { -+ uint32_t holeend = min(end, frag->ofs + frag->size); -+ D1(printk(KERN_DEBUG "Filling frag hole from %d-%d (frag 0x%x 0x%x)\n", offset, holeend, frag->ofs, frag->ofs + frag->size)); -+ memset(buf, 0, holeend - offset); -+ buf += holeend - offset; -+ offset = holeend; -+ frag = frag_next(frag); -+ continue; -+ } else { -+ uint32_t readlen; -+ uint32_t fragofs; /* offset within the frag to start reading */ -+ -+ fragofs = offset - frag->ofs; -+ readlen = min(frag->size - fragofs, end - offset); -+ D1(printk(KERN_DEBUG "Reading %d-%d from node at 0x%08x (%d)\n", -+ frag->ofs+fragofs, frag->ofs+fragofs+readlen, -+ ref_offset(frag->node->raw), ref_flags(frag->node->raw))); -+ ret = jffs2_read_dnode(c, frag->node, buf, fragofs + frag->ofs - frag->node->ofs, readlen); -+ D2(printk(KERN_DEBUG "node read done\n")); -+ if (ret) { -+ D1(printk(KERN_DEBUG"jffs2_read_inode_range error %d\n",ret)); -+ memset(buf, 0, readlen); -+ return ret; -+ } -+ buf += readlen; -+ offset += readlen; -+ frag = frag_next(frag); -+ D2(printk(KERN_DEBUG "node read was OK. Looping\n")); -+ } -+ } -+ return 0; -+} -+ -+/* Core function to read symlink target. */ -+char *jffs2_getlink(struct jffs2_sb_info *c, struct jffs2_inode_info *f) -+{ -+ char *buf; -+ int ret; -+ -+ down(&f->sem); -+ -+ if (!f->metadata) { -+ printk(KERN_NOTICE "No metadata for symlink inode #%u\n", f->inocache->ino); -+ up(&f->sem); -+ return ERR_PTR(-EINVAL); -+ } -+ buf = kmalloc(f->metadata->size+1, GFP_USER); -+ if (!buf) { -+ up(&f->sem); -+ return ERR_PTR(-ENOMEM); -+ } -+ buf[f->metadata->size]=0; -+ -+ ret = jffs2_read_dnode(c, f->metadata, buf, 0, f->metadata->size); -+ -+ up(&f->sem); -+ -+ if (ret) { -+ kfree(buf); -+ return ERR_PTR(ret); -+ } -+ return buf; -+} -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/readinode.c linux/fs/jffs2/readinode.c ---- linux-mips-2.4.24-pre2/fs/jffs2/readinode.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/readinode.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,79 +1,122 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - --/* Given an inode, probably with existing list of fragments, add the new node -- * to the fragment list. -- */ - #include - #include - #include -+#include -+#include - #include --#include -+#include - #include "nodelist.h" --#include - -+static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag); - --D1(void jffs2_print_frag_list(struct jffs2_inode_info *f) -+#if CONFIG_JFFS2_FS_DEBUG >= 1 -+static void jffs2_print_fragtree(struct rb_root *list, int permitbug) - { -- struct jffs2_node_frag *this = f->fraglist; -+ struct jffs2_node_frag *this = frag_first(list); -+ uint32_t lastofs = 0; -+ int buggy = 0; - - while(this) { - if (this->node) -- printk(KERN_DEBUG "frag %04x-%04x: 0x%08x on flash (*%p->%p)\n", this->ofs, this->ofs+this->size, this->node->raw->flash_offset &~3, this, this->next); -+ printk(KERN_DEBUG "frag %04x-%04x: 0x%08x(%d) on flash (*%p). left (%p), right (%p), parent (%p)\n", -+ this->ofs, this->ofs+this->size, ref_offset(this->node->raw), ref_flags(this->node->raw), -+ this, frag_left(this), frag_right(this), frag_parent(this)); - else -- printk(KERN_DEBUG "frag %04x-%04x: hole (*%p->%p)\n", this->ofs, this->ofs+this->size, this, this->next); -- this = this->next; -+ printk(KERN_DEBUG "frag %04x-%04x: hole (*%p). left (%p} right (%p), parent (%p)\n", this->ofs, -+ this->ofs+this->size, this, frag_left(this), frag_right(this), frag_parent(this)); -+ if (this->ofs != lastofs) -+ buggy = 1; -+ lastofs = this->ofs+this->size; -+ this = frag_next(this); -+ } -+ if (buggy && !permitbug) { -+ printk(KERN_CRIT "Frag tree got a hole in it\n"); -+ BUG(); - } -+} -+ -+void jffs2_print_frag_list(struct jffs2_inode_info *f) -+{ -+ jffs2_print_fragtree(&f->fragtree, 0); -+ - if (f->metadata) { -- printk(KERN_DEBUG "metadata at 0x%08x\n", f->metadata->raw->flash_offset &~3); -+ printk(KERN_DEBUG "metadata at 0x%08x\n", ref_offset(f->metadata->raw)); - } --}) -- -+} - --int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn) -+static int jffs2_sanitycheck_fragtree(struct jffs2_inode_info *f) - { -- int ret; -- D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)\n", f->inocache->ino, f, fn)); -+ struct jffs2_node_frag *frag; -+ int bitched = 0; - -- ret = jffs2_add_full_dnode_to_fraglist(c, &f->fraglist, fn); -+ for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) { - -- D2(jffs2_print_frag_list(f)); -- return ret; -+ struct jffs2_full_dnode *fn = frag->node; -+ if (!fn || !fn->raw) -+ continue; -+ -+ if (ref_flags(fn->raw) == REF_PRISTINE) { -+ -+ if (fn->frags > 1) { -+ printk(KERN_WARNING "REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2\n", ref_offset(fn->raw), fn->frags); -+ bitched = 1; -+ } -+ /* A hole node which isn't multi-page should be garbage-collected -+ and merged anyway, so we just check for the frag size here, -+ rather than mucking around with actually reading the node -+ and checking the compression type, which is the real way -+ to tell a hole node. */ -+ if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag) && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) { -+ printk(KERN_WARNING "REF_PRISTINE node at 0x%08x had a previous non-hole frag in the same page. Tell dwmw2\n", -+ ref_offset(fn->raw)); -+ bitched = 1; -+ } -+ -+ if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag) && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) { -+ printk(KERN_WARNING "REF_PRISTINE node at 0x%08x (%08x-%08x) had a following non-hole frag in the same page. Tell dwmw2\n", -+ ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size); -+ bitched = 1; -+ } -+ } -+ } -+ -+ if (bitched) { -+ struct jffs2_node_frag *thisfrag; -+ -+ printk(KERN_WARNING "Inode is #%u\n", f->inocache->ino); -+ thisfrag = frag_first(&f->fragtree); -+ while (thisfrag) { -+ if (!thisfrag->node) { -+ printk("Frag @0x%x-0x%x; node-less hole\n", -+ thisfrag->ofs, thisfrag->size + thisfrag->ofs); -+ } else if (!thisfrag->node->raw) { -+ printk("Frag @0x%x-0x%x; raw-less hole\n", -+ thisfrag->ofs, thisfrag->size + thisfrag->ofs); -+ } else { -+ printk("Frag @0x%x-0x%x; raw at 0x%08x(%d) (0x%x-0x%x)\n", -+ thisfrag->ofs, thisfrag->size + thisfrag->ofs, -+ ref_offset(thisfrag->node->raw), ref_flags(thisfrag->node->raw), -+ thisfrag->node->ofs, thisfrag->node->ofs+thisfrag->node->size); -+ } -+ thisfrag = frag_next(thisfrag); -+ } -+ } -+ return bitched; - } -+#endif /* D1 */ - - static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this) - { -@@ -82,42 +125,38 @@ - if (!this->node->frags) { - /* The node has no valid frags left. It's totally obsoleted */ - D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) obsolete\n", -- this->node->raw->flash_offset &~3, this->node->ofs, this->node->ofs+this->node->size)); -+ ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size)); - jffs2_mark_node_obsolete(c, this->node->raw); - jffs2_free_full_dnode(this->node); - } else { -- D2(printk(KERN_DEBUG "Not marking old node @0x%08x (0x%04x-0x%04x) obsolete. frags is %d\n", -- this->node->raw->flash_offset &~3, this->node->ofs, this->node->ofs+this->node->size, -+ D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n", -+ ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size, - this->node->frags)); -+ mark_ref_normal(this->node->raw); - } - - } - jffs2_free_node_frag(this); - } - --/* Doesn't set inode->i_size */ --int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct jffs2_node_frag **list, struct jffs2_full_dnode *fn) -+/* Given an inode, probably with existing list of fragments, add the new node -+ * to the fragment list. -+ */ -+int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn) - { -+ int ret; -+ struct jffs2_node_frag *newfrag; - -- struct jffs2_node_frag *this, **prev, *old; -- struct jffs2_node_frag *newfrag, *newfrag2; -- __u32 lastend = 0; -- -+ D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)\n", f->inocache->ino, f, fn)); - - newfrag = jffs2_alloc_node_frag(); -- if (!newfrag) { -+ if (unlikely(!newfrag)) - return -ENOMEM; -- } -- -- D2(if (fn->raw) -- printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, fn->raw->flash_offset &~3, newfrag); -- else -- printk(KERN_DEBUG "adding hole node %04x-%04x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, newfrag)); - -- prev = list; -- this = *list; -+ D2(printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n", -+ fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag)); - -- if (!fn->size) { -+ if (unlikely(!fn->size)) { - jffs2_free_node_frag(newfrag); - return 0; - } -@@ -126,176 +165,358 @@ - newfrag->size = fn->size; - newfrag->node = fn; - newfrag->node->frags = 1; -- newfrag->next = (void *)0xdeadbeef; -+ -+ ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag); -+ if (ret) -+ return ret; -+ -+ /* If we now share a page with other nodes, mark either previous -+ or next node REF_NORMAL, as appropriate. */ -+ if (newfrag->ofs & (PAGE_CACHE_SIZE-1)) { -+ struct jffs2_node_frag *prev = frag_prev(newfrag); -+ -+ mark_ref_normal(fn->raw); -+ /* If we don't start at zero there's _always_ a previous */ -+ if (prev->node) -+ mark_ref_normal(prev->node->raw); -+ } -+ -+ if ((newfrag->ofs+newfrag->size) & (PAGE_CACHE_SIZE-1)) { -+ struct jffs2_node_frag *next = frag_next(newfrag); -+ -+ if (next) { -+ mark_ref_normal(fn->raw); -+ if (next->node) -+ mark_ref_normal(next->node->raw); -+ } -+ } -+ D2(if (jffs2_sanitycheck_fragtree(f)) { -+ printk(KERN_WARNING "Just added node %04x-%04x @0x%08x on flash, newfrag *%p\n", -+ fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag); -+ return 0; -+ }) -+ D2(jffs2_print_frag_list(f)); -+ return 0; -+} -+ -+/* Doesn't set inode->i_size */ -+static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag) -+{ -+ struct jffs2_node_frag *this; -+ uint32_t lastend; - - /* Skip all the nodes which are completed before this one starts */ -- while(this && fn->ofs >= this->ofs+this->size) { -- lastend = this->ofs + this->size; -+ this = jffs2_lookup_node_frag(list, newfrag->node->ofs); - -- D2(printk(KERN_DEBUG "j_a_f_d_t_f: skipping frag 0x%04x-0x%04x; phys 0x%08x (*%p->%p)\n", -- this->ofs, this->ofs+this->size, this->node?(this->node->raw->flash_offset &~3):0xffffffff, this, this->next)); -- prev = &this->next; -- this = this->next; -+ if (this) { -+ D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", -+ this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this)); -+ lastend = this->ofs + this->size; -+ } else { -+ D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave no frag\n")); -+ lastend = 0; - } - - /* See if we ran off the end of the list */ -- if (!this) { -+ if (lastend <= newfrag->ofs) { - /* We did */ -- if (lastend < fn->ofs) { -+ -+ /* Check if 'this' node was on the same page as the new node. -+ If so, both 'this' and the new node get marked REF_NORMAL so -+ the GC can take a look. -+ */ -+ if ((lastend-1) >> PAGE_CACHE_SHIFT == newfrag->ofs >> PAGE_CACHE_SHIFT) { -+ if (this->node) -+ mark_ref_normal(this->node->raw); -+ mark_ref_normal(newfrag->node->raw); -+ } -+ -+ if (lastend < newfrag->node->ofs) { - /* ... and we need to put a hole in before the new node */ - struct jffs2_node_frag *holefrag = jffs2_alloc_node_frag(); -- if (!holefrag) -+ if (!holefrag) { -+ jffs2_free_node_frag(newfrag); - return -ENOMEM; -+ } - holefrag->ofs = lastend; -- holefrag->size = fn->ofs - lastend; -- holefrag->next = NULL; -+ holefrag->size = newfrag->node->ofs - lastend; - holefrag->node = NULL; -- *prev = holefrag; -- prev = &holefrag->next; -+ if (this) { -+ /* By definition, the 'this' node has no right-hand child, -+ because there are no frags with offset greater than it. -+ So that's where we want to put the hole */ -+ D2(printk(KERN_DEBUG "Adding hole frag (%p) on right of node at (%p)\n", holefrag, this)); -+ rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right); -+ } else { -+ D2(printk(KERN_DEBUG "Adding hole frag (%p) at root of tree\n", holefrag)); -+ rb_link_node(&holefrag->rb, NULL, &list->rb_node); -+ } -+ rb_insert_color(&holefrag->rb, list); -+ this = holefrag; - } -- newfrag->next = NULL; -- *prev = newfrag; -+ if (this) { -+ /* By definition, the 'this' node has no right-hand child, -+ because there are no frags with offset greater than it. -+ So that's where we want to put the hole */ -+ D2(printk(KERN_DEBUG "Adding new frag (%p) on right of node at (%p)\n", newfrag, this)); -+ rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); -+ } else { -+ D2(printk(KERN_DEBUG "Adding new frag (%p) at root of tree\n", newfrag)); -+ rb_link_node(&newfrag->rb, NULL, &list->rb_node); -+ } -+ rb_insert_color(&newfrag->rb, list); - return 0; - } - -- D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p->%p)\n", -- this->ofs, this->ofs+this->size, this->node?(this->node->raw->flash_offset &~3):0xffffffff, this, this->next)); -+ D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", -+ this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this)); - -- /* OK. 'this' is pointing at the first frag that fn->ofs at least partially obsoletes, -- * - i.e. fn->ofs < this->ofs+this->size && fn->ofs >= this->ofs -+ /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes, -+ * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs - */ -- if (fn->ofs > this->ofs) { -+ if (newfrag->ofs > this->ofs) { - /* This node isn't completely obsoleted. The start of it remains valid */ -- if (this->ofs + this->size > fn->ofs + fn->size) { -+ -+ /* Mark the new node and the partially covered node REF_NORMAL -- let -+ the GC take a look at them */ -+ mark_ref_normal(newfrag->node->raw); -+ if (this->node) -+ mark_ref_normal(this->node->raw); -+ -+ if (this->ofs + this->size > newfrag->ofs + newfrag->size) { - /* The new node splits 'this' frag into two */ -- newfrag2 = jffs2_alloc_node_frag(); -+ struct jffs2_node_frag *newfrag2 = jffs2_alloc_node_frag(); - if (!newfrag2) { - jffs2_free_node_frag(newfrag); - return -ENOMEM; - } -- D1(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size); -+ D2(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size); - if (this->node) -- printk("phys 0x%08x\n", this->node->raw->flash_offset &~3); -+ printk("phys 0x%08x\n", ref_offset(this->node->raw)); - else - printk("hole\n"); - ) -- newfrag2->ofs = fn->ofs + fn->size; -+ -+ /* New second frag pointing to this's node */ -+ newfrag2->ofs = newfrag->ofs + newfrag->size; - newfrag2->size = (this->ofs+this->size) - newfrag2->ofs; -- newfrag2->next = this->next; - newfrag2->node = this->node; - if (this->node) - this->node->frags++; -- newfrag->next = newfrag2; -- this->next = newfrag; -+ -+ /* Adjust size of original 'this' */ - this->size = newfrag->ofs - this->ofs; -+ -+ /* Now, we know there's no node with offset -+ greater than this->ofs but smaller than -+ newfrag2->ofs or newfrag->ofs, for obvious -+ reasons. So we can do a tree insert from -+ 'this' to insert newfrag, and a tree insert -+ from newfrag to insert newfrag2. */ -+ jffs2_fragtree_insert(newfrag, this); -+ rb_insert_color(&newfrag->rb, list); -+ -+ jffs2_fragtree_insert(newfrag2, newfrag); -+ rb_insert_color(&newfrag2->rb, list); -+ - return 0; - } - /* New node just reduces 'this' frag in size, doesn't split it */ -- this->size = fn->ofs - this->ofs; -- newfrag->next = this->next; -- this->next = newfrag; -- this = newfrag->next; -+ this->size = newfrag->ofs - this->ofs; -+ -+ /* Again, we know it lives down here in the tree */ -+ jffs2_fragtree_insert(newfrag, this); -+ rb_insert_color(&newfrag->rb, list); - } else { -- D2(printk(KERN_DEBUG "Inserting newfrag (*%p) in before 'this' (*%p)\n", newfrag, this)); -- *prev = newfrag; -- newfrag->next = this; -+ /* New frag starts at the same point as 'this' used to. Replace -+ it in the tree without doing a delete and insertion */ -+ D2(printk(KERN_DEBUG "Inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", -+ newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, -+ this, this->ofs, this->ofs+this->size)); -+ -+ rb_replace_node(&this->rb, &newfrag->rb, list); -+ -+ if (newfrag->ofs + newfrag->size >= this->ofs+this->size) { -+ D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size)); -+ jffs2_obsolete_node_frag(c, this); -+ } else { -+ this->ofs += newfrag->size; -+ this->size -= newfrag->size; -+ -+ jffs2_fragtree_insert(this, newfrag); -+ rb_insert_color(&this->rb, list); -+ return 0; - } -- /* OK, now we have newfrag added in the correct place in the list, but -- newfrag->next points to a fragment which may be overlapping it -+ } -+ /* OK, now we have newfrag added in the correct place in the tree, but -+ frag_next(newfrag) may be a fragment which is overlapped by it - */ -- while (this && newfrag->ofs + newfrag->size >= this->ofs + this->size) { -- /* 'this' frag is obsoleted. */ -- old = this; -- this = old->next; -- jffs2_obsolete_node_frag(c, old); -+ while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) { -+ /* 'this' frag is obsoleted completely. */ -+ D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x) and removing from tree\n", this, this->ofs, this->ofs+this->size)); -+ rb_erase(&this->rb, list); -+ jffs2_obsolete_node_frag(c, this); - } - /* Now we're pointing at the first frag which isn't totally obsoleted by - the new frag */ -- newfrag->next = this; - - if (!this || newfrag->ofs + newfrag->size == this->ofs) { - return 0; - } -- /* Still some overlap */ -+ /* Still some overlap but we don't need to move it in the tree */ - this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size); - this->ofs = newfrag->ofs + newfrag->size; -+ -+ /* And mark them REF_NORMAL so the GC takes a look at them */ -+ if (this->node) -+ mark_ref_normal(this->node->raw); -+ mark_ref_normal(newfrag->node->raw); -+ - return 0; - } - --void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct jffs2_node_frag **list, __u32 size) -+void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) - { -+ struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); -+ - D1(printk(KERN_DEBUG "Truncating fraglist to 0x%08x bytes\n", size)); - -- while (*list) { -- if ((*list)->ofs >= size) { -- struct jffs2_node_frag *this = *list; -- *list = this->next; -- D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", this->ofs, this->ofs+this->size)); -- jffs2_obsolete_node_frag(c, this); -- continue; -- } else if ((*list)->ofs + (*list)->size > size) { -- D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", (*list)->ofs, (*list)->ofs + (*list)->size)); -- (*list)->size = size - (*list)->ofs; -- } -- list = &(*list)->next; -+ /* We know frag->ofs <= size. That's what lookup does for us */ -+ if (frag && frag->ofs != size) { -+ if (frag->ofs+frag->size >= size) { -+ D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size)); -+ frag->size = size - frag->ofs; -+ } -+ frag = frag_next(frag); -+ } -+ while (frag && frag->ofs >= size) { -+ struct jffs2_node_frag *next = frag_next(frag); -+ -+ D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size)); -+ frag_erase(frag, list); -+ jffs2_obsolete_node_frag(c, frag); -+ frag = next; - } - } - - /* Scan the list of all nodes present for this ino, build map of versions, etc. */ - --void jffs2_read_inode (struct inode *inode) -+static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, -+ struct jffs2_inode_info *f, -+ struct jffs2_raw_inode *latest_node); -+ -+int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, -+ uint32_t ino, struct jffs2_raw_inode *latest_node) - { -- struct jffs2_tmp_dnode_info *tn_list, *tn; -- struct jffs2_full_dirent *fd_list; -- struct jffs2_inode_info *f; -- struct jffs2_full_dnode *fn = NULL; -- struct jffs2_sb_info *c; -- struct jffs2_raw_inode latest_node; -- __u32 latest_mctime, mctime_ver; -- __u32 mdata_ver = 0; -- int ret; -- ssize_t retlen; -+ D2(printk(KERN_DEBUG "jffs2_do_read_inode(): getting inocache\n")); - -- D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino)); -+ retry_inocache: -+ spin_lock(&c->inocache_lock); -+ f->inocache = jffs2_get_ino_cache(c, ino); -+ -+ D2(printk(KERN_DEBUG "jffs2_do_read_inode(): Got inocache at %p\n", f->inocache)); -+ -+ if (f->inocache) { -+ /* Check its state. We may need to wait before we can use it */ -+ switch(f->inocache->state) { -+ case INO_STATE_UNCHECKED: -+ case INO_STATE_CHECKEDABSENT: -+ f->inocache->state = INO_STATE_READING; -+ break; - -- f = JFFS2_INODE_INFO(inode); -- c = JFFS2_SB_INFO(inode->i_sb); -+ case INO_STATE_CHECKING: -+ case INO_STATE_GC: -+ /* If it's in either of these states, we need -+ to wait for whoever's got it to finish and -+ put it back. */ -+ D1(printk(KERN_DEBUG "jffs2_get_ino_cache_read waiting for ino #%u in state %d\n", -+ ino, f->inocache->state)); -+ sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); -+ goto retry_inocache; -+ -+ case INO_STATE_READING: -+ case INO_STATE_PRESENT: -+ /* Eep. This should never happen. It can -+ happen if Linux calls read_inode() again -+ before clear_inode() has finished though. */ -+ printk(KERN_WARNING "Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state); -+ /* Fail. That's probably better than allowing it to succeed */ -+ f->inocache = NULL; -+ break; - -- memset(f, 0, sizeof(*f)); -- D2(printk(KERN_DEBUG "getting inocache\n")); -- init_MUTEX(&f->sem); -- f->inocache = jffs2_get_ino_cache(c, inode->i_ino); -- D2(printk(KERN_DEBUG "jffs2_read_inode(): Got inocache at %p\n", f->inocache)); -+ default: -+ BUG(); -+ } -+ } -+ spin_unlock(&c->inocache_lock); - -- if (!f->inocache && inode->i_ino == 1) { -+ if (!f->inocache && ino == 1) { - /* Special case - no root inode on medium */ - f->inocache = jffs2_alloc_inode_cache(); - if (!f->inocache) { -- printk(KERN_CRIT "jffs2_read_inode(): Cannot allocate inocache for root inode\n"); -- make_bad_inode(inode); -- return; -+ printk(KERN_CRIT "jffs2_do_read_inode(): Cannot allocate inocache for root inode\n"); -+ return -ENOMEM; - } -- D1(printk(KERN_DEBUG "jffs2_read_inode(): Creating inocache for root inode\n")); -+ D1(printk(KERN_DEBUG "jffs2_do_read_inode(): Creating inocache for root inode\n")); - memset(f->inocache, 0, sizeof(struct jffs2_inode_cache)); - f->inocache->ino = f->inocache->nlink = 1; - f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; -+ f->inocache->state = INO_STATE_READING; - jffs2_add_ino_cache(c, f->inocache); - } - if (!f->inocache) { -- printk(KERN_WARNING "jffs2_read_inode() on nonexistent ino %lu\n", (unsigned long)inode->i_ino); -- make_bad_inode(inode); -- return; -+ printk(KERN_WARNING "jffs2_do_read_inode() on nonexistent ino %u\n", ino); -+ return -ENOENT; - } -- D1(printk(KERN_DEBUG "jffs2_read_inode(): ino #%lu nlink is %d\n", (unsigned long)inode->i_ino, f->inocache->nlink)); -- inode->i_nlink = f->inocache->nlink; -+ -+ return jffs2_do_read_inode_internal(c, f, latest_node); -+} -+ -+int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) -+{ -+ struct jffs2_raw_inode n; -+ struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL); -+ int ret; -+ -+ if (!f) -+ return -ENOMEM; -+ -+ memset(f, 0, sizeof(*f)); -+ init_MUTEX_LOCKED(&f->sem); -+ f->inocache = ic; -+ -+ ret = jffs2_do_read_inode_internal(c, f, &n); -+ if (!ret) { -+ up(&f->sem); -+ jffs2_do_clear_inode(c, f); -+ } -+ kfree (f); -+ return ret; -+} -+ -+static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, -+ struct jffs2_inode_info *f, -+ struct jffs2_raw_inode *latest_node) -+{ -+ struct jffs2_tmp_dnode_info *tn_list, *tn; -+ struct jffs2_full_dirent *fd_list; -+ struct jffs2_full_dnode *fn = NULL; -+ uint32_t crc; -+ uint32_t latest_mctime, mctime_ver; -+ uint32_t mdata_ver = 0; -+ size_t retlen; -+ int ret; -+ -+ D1(printk(KERN_DEBUG "jffs2_do_read_inode_internal(): ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink)); - - /* Grab all nodes relevant to this ino */ -- ret = jffs2_get_inode_nodes(c, inode->i_ino, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); -+ ret = jffs2_get_inode_nodes(c, f->inocache->ino, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); - - if (ret) { -- printk(KERN_CRIT "jffs2_get_inode_nodes() for ino %lu returned %d\n", inode->i_ino, ret); -- make_bad_inode(inode); -- return; -+ printk(KERN_CRIT "jffs2_get_inode_nodes() for ino %u returned %d\n", f->inocache->ino, ret); -+ if (f->inocache->state == INO_STATE_READING) -+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); -+ return ret; - } - f->dents = fd_list; - -@@ -304,205 +525,169 @@ - - fn = tn->fn; - -- if (f->metadata && tn->version > mdata_ver) { -- D1(printk(KERN_DEBUG "Obsoleting old metadata at 0x%08x\n", f->metadata->raw->flash_offset &~3)); -+ if (f->metadata) { -+ if (likely(tn->version >= mdata_ver)) { -+ D1(printk(KERN_DEBUG "Obsoleting old metadata at 0x%08x\n", ref_offset(f->metadata->raw))); - jffs2_mark_node_obsolete(c, f->metadata->raw); - jffs2_free_full_dnode(f->metadata); - f->metadata = NULL; - - mdata_ver = 0; -+ } else { -+ /* This should never happen. */ -+ printk(KERN_WARNING "Er. New metadata at 0x%08x with ver %d is actually older than previous ver %d at 0x%08x\n", -+ ref_offset(fn->raw), tn->version, mdata_ver, ref_offset(f->metadata->raw)); -+ jffs2_mark_node_obsolete(c, fn->raw); -+ jffs2_free_full_dnode(fn); -+ /* Fill in latest_node from the metadata, not this one we're about to free... */ -+ fn = f->metadata; -+ goto next_tn; -+ } - } - - if (fn->size) { - jffs2_add_full_dnode_to_inode(c, f, fn); - } else { - /* Zero-sized node at end of version list. Just a metadata update */ -- D1(printk(KERN_DEBUG "metadata @%08x: ver %d\n", fn->raw->flash_offset &~3, tn->version)); -+ D1(printk(KERN_DEBUG "metadata @%08x: ver %d\n", ref_offset(fn->raw), tn->version)); - f->metadata = fn; - mdata_ver = tn->version; - } -+ next_tn: - tn_list = tn->next; - jffs2_free_tmp_dnode_info(tn); - } -+ D1(jffs2_sanitycheck_fragtree(f)); -+ - if (!fn) { - /* No data nodes for this inode. */ -- if (inode->i_ino != 1) { -- printk(KERN_WARNING "jffs2_read_inode(): No data nodes found for ino #%lu\n", inode->i_ino); -+ if (f->inocache->ino != 1) { -+ printk(KERN_WARNING "jffs2_do_read_inode(): No data nodes found for ino #%u\n", f->inocache->ino); - if (!fd_list) { -- make_bad_inode(inode); -- return; -- } -- printk(KERN_WARNING "jffs2_read_inode(): But it has children so we fake some modes for it\n"); -+ if (f->inocache->state == INO_STATE_READING) -+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); -+ return -EIO; -+ } -+ printk(KERN_WARNING "jffs2_do_read_inode(): But it has children so we fake some modes for it\n"); -+ } -+ latest_node->mode = cpu_to_jemode(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO); -+ latest_node->version = cpu_to_je32(0); -+ latest_node->atime = latest_node->ctime = latest_node->mtime = cpu_to_je32(0); -+ latest_node->isize = cpu_to_je32(0); -+ latest_node->gid = cpu_to_je16(0); -+ latest_node->uid = cpu_to_je16(0); -+ if (f->inocache->state == INO_STATE_READING) -+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT); -+ return 0; - } -- inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO; -- latest_node.version = 0; -- inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME; -- inode->i_nlink = f->inocache->nlink; -- inode->i_size = 0; -- } else { -- __u32 crc; - -- ret = c->mtd->read(c->mtd, fn->raw->flash_offset & ~3, sizeof(latest_node), &retlen, (void *)&latest_node); -- if (ret || retlen != sizeof(latest_node)) { -- printk(KERN_NOTICE "MTD read in jffs2_read_inode() failed: Returned %d, %ld of %d bytes read\n", -- ret, (long)retlen, sizeof(latest_node)); -- jffs2_clear_inode(inode); -- make_bad_inode(inode); -- return; -- } -- -- crc = crc32(0, &latest_node, sizeof(latest_node)-8); -- if (crc != latest_node.node_crc) { -- printk(KERN_NOTICE "CRC failed for read_inode of inode %ld at physical location 0x%x\n", inode->i_ino, fn->raw->flash_offset & ~3); -- jffs2_clear_inode(inode); -- make_bad_inode(inode); -- return; -- } -- -- inode->i_mode = latest_node.mode; -- inode->i_uid = latest_node.uid; -- inode->i_gid = latest_node.gid; -- inode->i_size = latest_node.isize; -- if (S_ISREG(inode->i_mode)) -- jffs2_truncate_fraglist(c, &f->fraglist, latest_node.isize); -- inode->i_atime = latest_node.atime; -- inode->i_mtime = latest_node.mtime; -- inode->i_ctime = latest_node.ctime; -- } -- -- /* OK, now the special cases. Certain inode types should -- have only one data node, and it's kept as the metadata -- node */ -- if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode) || -- S_ISLNK(inode->i_mode)) { -- if (f->metadata) { -- printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o had metadata node\n", inode->i_ino, inode->i_mode); -- jffs2_clear_inode(inode); -- make_bad_inode(inode); -- return; -- } -- if (!f->fraglist) { -- printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o has no fragments\n", inode->i_ino, inode->i_mode); -- jffs2_clear_inode(inode); -- make_bad_inode(inode); -- return; -- } -- /* ASSERT: f->fraglist != NULL */ -- if (f->fraglist->next) { -- printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o had more than one node\n", inode->i_ino, inode->i_mode); -- /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ -- jffs2_clear_inode(inode); -- make_bad_inode(inode); -- return; -- } -- /* OK. We're happy */ -- f->metadata = f->fraglist->node; -- jffs2_free_node_frag(f->fraglist); -- f->fraglist = NULL; -+ ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node); -+ if (ret || retlen != sizeof(*latest_node)) { -+ printk(KERN_NOTICE "MTD read in jffs2_do_read_inode() failed: Returned %d, %zd of %zd bytes read\n", -+ ret, retlen, sizeof(*latest_node)); -+ /* FIXME: If this fails, there seems to be a memory leak. Find it. */ -+ up(&f->sem); -+ jffs2_do_clear_inode(c, f); -+ return ret?ret:-EIO; - } - -- inode->i_blksize = PAGE_SIZE; -- inode->i_blocks = (inode->i_size + 511) >> 9; -- -- switch (inode->i_mode & S_IFMT) { -- unsigned short rdev; -- -- case S_IFLNK: -- inode->i_op = &jffs2_symlink_inode_operations; -- /* Hack to work around broken isize in old symlink code. -- Remove this when dwmw2 comes to his senses and stops -- symlinks from being an entirely gratuitous special -- case. */ -- if (!inode->i_size) -- inode->i_size = latest_node.dsize; -- break; -+ crc = crc32(0, latest_node, sizeof(*latest_node)-8); -+ if (crc != je32_to_cpu(latest_node->node_crc)) { -+ printk(KERN_NOTICE "CRC failed for read_inode of inode %u at physical location 0x%x\n", f->inocache->ino, ref_offset(fn->raw)); -+ up(&f->sem); -+ jffs2_do_clear_inode(c, f); -+ return -EIO; -+ } - -+ switch(jemode_to_cpu(latest_node->mode) & S_IFMT) { - case S_IFDIR: -- if (mctime_ver > latest_node.version) { -+ if (mctime_ver > je32_to_cpu(latest_node->version)) { - /* The times in the latest_node are actually older than - mctime in the latest dirent. Cheat. */ -- inode->i_mtime = inode->i_ctime = inode->i_atime = -- latest_mctime; -+ latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime); - } -- inode->i_op = &jffs2_dir_inode_operations; -- inode->i_fop = &jffs2_dir_operations; - break; - -+ - case S_IFREG: -- inode->i_op = &jffs2_file_inode_operations; -- inode->i_fop = &jffs2_file_operations; -- inode->i_mapping->a_ops = &jffs2_file_address_operations; -- inode->i_mapping->nrpages = 0; -+ /* If it was a regular file, truncate it to the latest node's isize */ -+ jffs2_truncate_fraglist(c, &f->fragtree, je32_to_cpu(latest_node->isize)); - break; - -+ case S_IFLNK: -+ /* Hack to work around broken isize in old symlink code. -+ Remove this when dwmw2 comes to his senses and stops -+ symlinks from being an entirely gratuitous special -+ case. */ -+ if (!je32_to_cpu(latest_node->isize)) -+ latest_node->isize = latest_node->dsize; -+ /* fall through... */ -+ - case S_IFBLK: - case S_IFCHR: -- /* Read the device numbers from the media */ -- D1(printk(KERN_DEBUG "Reading device numbers from flash\n")); -- if (jffs2_read_dnode(c, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) { -- /* Eep */ -- printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino); -- jffs2_clear_inode(inode); -- make_bad_inode(inode); -- return; -+ /* Certain inode types should have only one data node, and it's -+ kept as the metadata node */ -+ if (f->metadata) { -+ printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had metadata node\n", -+ f->inocache->ino, jemode_to_cpu(latest_node->mode)); -+ up(&f->sem); -+ jffs2_do_clear_inode(c, f); -+ return -EIO; - } -- -- case S_IFSOCK: -- case S_IFIFO: -- inode->i_op = &jffs2_file_inode_operations; -- init_special_inode(inode, inode->i_mode, kdev_t_to_nr(MKDEV(rdev>>8, rdev&0xff))); -+ if (!frag_first(&f->fragtree)) { -+ printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o has no fragments\n", -+ f->inocache->ino, jemode_to_cpu(latest_node->mode)); -+ up(&f->sem); -+ jffs2_do_clear_inode(c, f); -+ return -EIO; -+ } -+ /* ASSERT: f->fraglist != NULL */ -+ if (frag_next(frag_first(&f->fragtree))) { -+ printk(KERN_WARNING "Argh. Special inode #%u with mode 0x%x had more than one node\n", -+ f->inocache->ino, jemode_to_cpu(latest_node->mode)); -+ /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ -+ up(&f->sem); -+ jffs2_do_clear_inode(c, f); -+ return -EIO; -+ } -+ /* OK. We're happy */ -+ f->metadata = frag_first(&f->fragtree)->node; -+ jffs2_free_node_frag(frag_first(&f->fragtree)); -+ f->fragtree = RB_ROOT; - break; -- -- default: -- printk(KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu", inode->i_mode, (unsigned long)inode->i_ino); - } -- D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n")); -+ if (f->inocache->state == INO_STATE_READING) -+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT); -+ -+ return 0; - } - --void jffs2_clear_inode (struct inode *inode) -+void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) - { -- /* We can forget about this inode for now - drop all -- * the nodelists associated with it, etc. -- */ -- struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -- struct jffs2_node_frag *frag, *frags; - struct jffs2_full_dirent *fd, *fds; -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - int deleted; - -- D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); -- - down(&f->sem); - deleted = f->inocache && !f->inocache->nlink; - -- frags = f->fraglist; -- fds = f->dents; - if (f->metadata) { - if (deleted) - jffs2_mark_node_obsolete(c, f->metadata->raw); - jffs2_free_full_dnode(f->metadata); - } - -- while (frags) { -- frag = frags; -- frags = frag->next; -- D2(printk(KERN_DEBUG "jffs2_clear_inode: frag at 0x%x-0x%x: node %p, frags %d--\n", frag->ofs, frag->ofs+frag->size, frag->node, frag->node?frag->node->frags:0)); -+ jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL); - -- if (frag->node && !(--frag->node->frags)) { -- /* Not a hole, and it's the final remaining frag of this node. Free the node */ -- if (deleted) -- jffs2_mark_node_obsolete(c, frag->node->raw); -+ fds = f->dents; - -- jffs2_free_full_dnode(frag->node); -- } -- jffs2_free_node_frag(frag); -- } - while(fds) { - fd = fds; - fds = fd->next; - jffs2_free_full_dirent(fd); - } - -- up(&f->sem); --}; -+ if (f->inocache && f->inocache->state != INO_STATE_CHECKING) -+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); - -+ up(&f->sem); -+} -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/scan.c linux/fs/jffs2/scan.c ---- linux-mips-2.4.24-pre2/fs/jffs2/scan.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/scan.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,47 +1,25 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - #include -+#include - #include --#include - #include - #include --#include "nodelist.h" - #include -+#include -+#include "nodelist.h" - -+#define EMPTY_SCAN_SIZE 1024 - - #define DIRTY_SPACE(x) do { typeof(x) _x = (x); \ - c->free_size -= _x; c->dirty_size += _x; \ -@@ -51,6 +29,10 @@ - c->free_size -= _x; c->used_size += _x; \ - jeb->free_size -= _x ; jeb->used_size += _x; \ - }while(0) -+#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \ -+ c->free_size -= _x; c->unchecked_size += _x; \ -+ jeb->free_size -= _x ; jeb->unchecked_size += _x; \ -+ }while(0) - - #define noisy_printk(noise, args...) do { \ - if (*(noise)) { \ -@@ -63,39 +45,84 @@ - } while(0) - - static uint32_t pseudo_random; --static void jffs2_rotate_lists(struct jffs2_sb_info *c); - --static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ unsigned char *buf, uint32_t buf_size); - - /* These helper functions _must_ increase ofs and also do the dirty/used space accounting. - * Returning an error will abort the mount - bad checksums etc. should just mark the space - * as dirty. - */ --static int jffs2_scan_empty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, __u32 *ofs, int *noise); --static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, __u32 *ofs); --static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, __u32 *ofs); -+static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_inode *ri, uint32_t ofs); -+static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_dirent *rd, uint32_t ofs); -+ -+#define BLK_STATE_ALLFF 0 -+#define BLK_STATE_CLEAN 1 -+#define BLK_STATE_PARTDIRTY 2 -+#define BLK_STATE_CLEANMARKER 3 -+#define BLK_STATE_ALLDIRTY 4 -+#define BLK_STATE_BADBLOCK 5 - -+static inline int min_free(struct jffs2_sb_info *c) -+{ -+ uint32_t min = 2 * sizeof(struct jffs2_raw_inode); -+#ifdef CONFIG_JFFS2_FS_NAND -+ if (!jffs2_can_mark_obsolete(c) && min < c->wbuf_pagesize) -+ return c->wbuf_pagesize; -+#endif -+ return min; - -+} - int jffs2_scan_medium(struct jffs2_sb_info *c) - { - int i, ret; -- __u32 empty_blocks = 0; -- -- if (!c->blocks) { -- printk(KERN_WARNING "EEEK! c->blocks is NULL!\n"); -- return -EINVAL; -+ uint32_t empty_blocks = 0, bad_blocks = 0; -+ unsigned char *flashbuf = NULL; -+ uint32_t buf_size = 0; -+#ifndef __ECOS -+ size_t pointlen; -+ -+ if (c->mtd->point) { -+ ret = c->mtd->point (c->mtd, 0, c->mtd->size, &pointlen, &flashbuf); -+ if (!ret && pointlen < c->mtd->size) { -+ /* Don't muck about if it won't let us point to the whole flash */ -+ D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", pointlen)); -+ c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size); -+ flashbuf = NULL; -+ } -+ if (ret) -+ D1(printk(KERN_DEBUG "MTD point failed %d\n", ret)); -+ } -+#endif -+ if (!flashbuf) { -+ /* For NAND it's quicker to read a whole eraseblock at a time, -+ apparently */ -+ if (jffs2_cleanmarker_oob(c)) -+ buf_size = c->sector_size; -+ else -+ buf_size = PAGE_SIZE; -+ -+ D1(printk(KERN_DEBUG "Allocating readbuf of %d bytes\n", buf_size)); -+ flashbuf = kmalloc(buf_size, GFP_KERNEL); -+ if (!flashbuf) -+ return -ENOMEM; - } -+ - for (i=0; inr_blocks; i++) { - struct jffs2_eraseblock *jeb = &c->blocks[i]; - -- ret = jffs2_scan_eraseblock(c, jeb); -+ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), buf_size); -+ - if (ret < 0) -- return ret; -+ goto out; - - ACCT_PARANOIA_CHECK(jeb); - - /* Now decide which list to put it on */ -- if (ret == 1) { -+ switch(ret) { -+ case BLK_STATE_ALLFF: - /* - * Empty block. Since we can't be sure it - * was entirely erased, we just queue it for erase -@@ -103,10 +130,12 @@ - * is complete. Meanwhile we still count it as empty - * for later checks. - */ -- list_add(&jeb->list, &c->erase_pending_list); - empty_blocks++; -+ list_add(&jeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; -- } else if (jeb->used_size == PAD(sizeof(struct jffs2_unknown_node)) && !jeb->first_node->next_in_ino) { -+ break; -+ -+ case BLK_STATE_CLEANMARKER: - /* Only a CLEANMARKER node is valid */ - if (!jeb->dirty_size) { - /* It's actually free */ -@@ -118,74 +147,227 @@ - list_add(&jeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; - } -- } else if (jeb->used_size > c->sector_size - (2*sizeof(struct jffs2_raw_inode))) { -+ break; -+ -+ case BLK_STATE_CLEAN: - /* Full (or almost full) of clean data. Clean list */ - list_add(&jeb->list, &c->clean_list); -- } else if (jeb->used_size) { -+ break; -+ -+ case BLK_STATE_PARTDIRTY: - /* Some data, but not full. Dirty list. */ - /* Except that we want to remember the block with most free space, - and stick it in the 'nextblock' position to start writing to it. - Later when we do snapshots, this must be the most recent block, - not the one with most free space. - */ -- if (jeb->free_size > 2*sizeof(struct jffs2_raw_inode) && -+ if (jeb->free_size > min_free(c) && - (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { - /* Better candidate for the next writes to go to */ -- if (c->nextblock) -+ if (c->nextblock) { -+ c->nextblock->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; -+ c->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; -+ c->free_size -= c->nextblock->free_size; -+ c->wasted_size -= c->nextblock->wasted_size; -+ c->nextblock->free_size = c->nextblock->wasted_size = 0; -+ if (VERYDIRTY(c, c->nextblock->dirty_size)) { -+ list_add(&c->nextblock->list, &c->very_dirty_list); -+ } else { - list_add(&c->nextblock->list, &c->dirty_list); -+ } -+ } - c->nextblock = jeb; - } else { -+ jeb->dirty_size += jeb->free_size + jeb->wasted_size; -+ c->dirty_size += jeb->free_size + jeb->wasted_size; -+ c->free_size -= jeb->free_size; -+ c->wasted_size -= jeb->wasted_size; -+ jeb->free_size = jeb->wasted_size = 0; -+ if (VERYDIRTY(c, jeb->dirty_size)) { -+ list_add(&jeb->list, &c->very_dirty_list); -+ } else { - list_add(&jeb->list, &c->dirty_list); - } -- } else { -+ } -+ break; -+ -+ case BLK_STATE_ALLDIRTY: - /* Nothing valid - not even a clean marker. Needs erasing. */ - /* For now we just put it on the erasing list. We'll start the erases later */ -- printk(KERN_NOTICE "JFFS2: Erase block at 0x%08x is not formatted. It will be erased\n", jeb->offset); -+ D1(printk(KERN_NOTICE "JFFS2: Erase block at 0x%08x is not formatted. It will be erased\n", jeb->offset)); - list_add(&jeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; -+ break; -+ -+ case BLK_STATE_BADBLOCK: -+ D1(printk(KERN_NOTICE "JFFS2: Block at 0x%08x is bad\n", jeb->offset)); -+ list_add(&jeb->list, &c->bad_list); -+ c->bad_size += c->sector_size; -+ c->free_size -= c->sector_size; -+ bad_blocks++; -+ break; -+ default: -+ printk(KERN_WARNING "jffs2_scan_medium(): unknown block state\n"); -+ BUG(); - } - } -- /* Rotate the lists by some number to ensure wear levelling */ -- jffs2_rotate_lists(c); - -+ /* Nextblock dirty is always seen as wasted, because we cannot recycle it now */ -+ if (c->nextblock && (c->nextblock->dirty_size)) { -+ c->nextblock->wasted_size += c->nextblock->dirty_size; -+ c->wasted_size += c->nextblock->dirty_size; -+ c->dirty_size -= c->nextblock->dirty_size; -+ c->nextblock->dirty_size = 0; -+ } -+#ifdef CONFIG_JFFS2_FS_NAND -+ if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) { -+ /* If we're going to start writing into a block which already -+ contains data, and the end of the data isn't page-aligned, -+ skip a little and align it. */ -+ -+ uint32_t skip = c->nextblock->free_size & (c->wbuf_pagesize-1); -+ -+ D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n", -+ skip)); -+ c->nextblock->wasted_size += skip; -+ c->wasted_size += skip; -+ -+ c->nextblock->free_size -= skip; -+ c->free_size -= skip; -+ } -+#endif - if (c->nr_erasing_blocks) { -- if (!c->used_size && empty_blocks != c->nr_blocks) { -+ if ( !c->used_size && ((empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) { - printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n"); -- return -EIO; -+ printk(KERN_NOTICE "empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",empty_blocks,bad_blocks,c->nr_blocks); -+ ret = -EIO; -+ goto out; - } - jffs2_erase_pending_trigger(c); - } -+ ret = 0; -+ out: -+ if (buf_size) -+ kfree(flashbuf); -+#ifndef __ECOS -+ else -+ c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size); -+#endif -+ return ret; -+} -+ -+static int jffs2_fill_scan_buf (struct jffs2_sb_info *c, unsigned char *buf, -+ uint32_t ofs, uint32_t len) -+{ -+ int ret; -+ size_t retlen; -+ -+ ret = jffs2_flash_read(c, ofs, len, &retlen, buf); -+ if (ret) { -+ D1(printk(KERN_WARNING "mtd->read(0x%x bytes from 0x%x) returned %d\n", len, ofs, ret)); -+ return ret; -+ } -+ if (retlen < len) { -+ D1(printk(KERN_WARNING "Read at 0x%x gave only 0x%zx bytes\n", ofs, retlen)); -+ return -EIO; -+ } -+ D2(printk(KERN_DEBUG "Read 0x%x bytes from 0x%08x into buf\n", len, ofs)); -+ D2(printk(KERN_DEBUG "000: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15])); - return 0; - } - --static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) { -- struct jffs2_unknown_node node; -- __u32 ofs, prevofs; -- __u32 hdr_crc, nodetype; -+static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ unsigned char *buf, uint32_t buf_size) { -+ struct jffs2_unknown_node *node; -+ struct jffs2_unknown_node crcnode; -+ uint32_t ofs, prevofs; -+ uint32_t hdr_crc, buf_ofs, buf_len; - int err; - int noise = 0; -+ int wasempty = 0; -+ uint32_t empty_start = 0; -+#ifdef CONFIG_JFFS2_FS_NAND -+ int cleanmarkerfound = 0; -+#endif - - ofs = jeb->offset; - prevofs = jeb->offset - 1; - - D1(printk(KERN_DEBUG "jffs2_scan_eraseblock(): Scanning block at 0x%x\n", ofs)); - -- err = jffs2_scan_empty(c, jeb, &ofs, &noise); -- if (err) return err; -- if (ofs == jeb->offset + c->sector_size) { -+#ifdef CONFIG_JFFS2_FS_NAND -+ if (jffs2_cleanmarker_oob(c)) { -+ int ret = jffs2_check_nand_cleanmarker(c, jeb); -+ D2(printk(KERN_NOTICE "jffs_check_nand_cleanmarker returned %d\n",ret)); -+ /* Even if it's not found, we still scan to see -+ if the block is empty. We use this information -+ to decide whether to erase it or not. */ -+ switch (ret) { -+ case 0: cleanmarkerfound = 1; break; -+ case 1: break; -+ case 2: return BLK_STATE_BADBLOCK; -+ case 3: return BLK_STATE_ALLDIRTY; /* Block has failed to erase min. once */ -+ default: return ret; -+ } -+ } -+#endif -+ buf_ofs = jeb->offset; -+ -+ if (!buf_size) { -+ buf_len = c->sector_size; -+ } else { -+ buf_len = EMPTY_SCAN_SIZE; -+ err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); -+ if (err) -+ return err; -+ } -+ -+ /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ -+ ofs = 0; -+ -+ /* Scan only 4KiB of 0xFF before declaring it's empty */ -+ while(ofs < EMPTY_SCAN_SIZE && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF) -+ ofs += 4; -+ -+ if (ofs == EMPTY_SCAN_SIZE) { -+#ifdef CONFIG_JFFS2_FS_NAND -+ if (jffs2_cleanmarker_oob(c)) { -+ /* scan oob, take care of cleanmarker */ -+ int ret = jffs2_check_oob_empty(c, jeb, cleanmarkerfound); -+ D2(printk(KERN_NOTICE "jffs2_check_oob_empty returned %d\n",ret)); -+ switch (ret) { -+ case 0: return cleanmarkerfound ? BLK_STATE_CLEANMARKER : BLK_STATE_ALLFF; -+ case 1: return BLK_STATE_ALLDIRTY; -+ case 2: return BLK_STATE_BADBLOCK; /* case 2/3 are paranoia checks */ -+ case 3: return BLK_STATE_ALLDIRTY; /* Block has failed to erase min. once */ -+ default: return ret; -+ } -+ } -+#endif - D1(printk(KERN_DEBUG "Block at 0x%08x is empty (erased)\n", jeb->offset)); -- return 1; /* special return code */ -+ return BLK_STATE_ALLFF; /* OK to erase if all blocks are like this */ -+ } -+ if (ofs) { -+ D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset, -+ jeb->offset + ofs)); -+ DIRTY_SPACE(ofs); - } - -+ /* Now ofs is a complete physical flash offset as it always was... */ -+ ofs += jeb->offset; -+ - noise = 10; - - while(ofs < jeb->offset + c->sector_size) { -- ssize_t retlen; -- ACCT_PARANOIA_CHECK(jeb); -+ -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ cond_resched(); - - if (ofs & 3) { - printk(KERN_WARNING "Eep. ofs 0x%08x not word-aligned!\n", ofs); -- ofs = (ofs+3)&~3; -+ ofs = PAD(ofs); - continue; - } - if (ofs == prevofs) { -@@ -196,102 +378,173 @@ - } - prevofs = ofs; - -- if (jeb->offset + c->sector_size < ofs + sizeof(node)) { -- D1(printk(KERN_DEBUG "Fewer than %d bytes left to end of block. Not reading\n", sizeof(struct jffs2_unknown_node))); -+ if (jeb->offset + c->sector_size < ofs + sizeof(*node)) { -+ D1(printk(KERN_DEBUG "Fewer than %zd bytes left to end of block. (%x+%x<%x+%zx) Not reading\n", sizeof(struct jffs2_unknown_node), -+ jeb->offset, c->sector_size, ofs, sizeof(*node))); - DIRTY_SPACE((jeb->offset + c->sector_size)-ofs); - break; - } - -- err = c->mtd->read(c->mtd, ofs, sizeof(node), &retlen, (char *)&node); -- -- if (err) { -- D1(printk(KERN_WARNING "mtd->read(0x%x bytes from 0x%x) returned %d\n", sizeof(node), ofs, err)); -+ if (buf_ofs + buf_len < ofs + sizeof(*node)) { -+ buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); -+ D1(printk(KERN_DEBUG "Fewer than %zd bytes (node header) left to end of buf. Reading 0x%x at 0x%08x\n", -+ sizeof(struct jffs2_unknown_node), buf_len, ofs)); -+ err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); -+ if (err) - return err; -+ buf_ofs = ofs; - } -- if (retlen < sizeof(node)) { -- D1(printk(KERN_WARNING "Read at 0x%x gave only 0x%x bytes\n", ofs, retlen)); -- DIRTY_SPACE(retlen); -- ofs += retlen; -- continue; -+ -+ node = (struct jffs2_unknown_node *)&buf[ofs-buf_ofs]; -+ -+ if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) { -+ uint32_t inbuf_ofs = ofs - buf_ofs + 4; -+ uint32_t scanend; -+ -+ empty_start = ofs; -+ ofs += 4; -+ -+ /* If scanning empty space after only a cleanmarker, don't -+ bother scanning the whole block */ -+ if (unlikely(empty_start == jeb->offset + c->cleanmarker_size && -+ jeb->offset + EMPTY_SCAN_SIZE < buf_ofs + buf_len)) -+ scanend = jeb->offset + EMPTY_SCAN_SIZE - buf_ofs; -+ else -+ scanend = buf_len; -+ -+ D1(printk(KERN_DEBUG "Found empty flash at 0x%08x\n", ofs)); -+ while (inbuf_ofs < scanend) { -+ if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) -+ goto emptyends; -+ -+ inbuf_ofs+=4; -+ ofs += 4; - } -+ /* Ran off end. */ -+ D1(printk(KERN_DEBUG "Empty flash ends normally at 0x%08x\n", ofs)); - -- if (node.magic == JFFS2_EMPTY_BITMASK && node.nodetype == JFFS2_EMPTY_BITMASK) { -- D1(printk(KERN_DEBUG "Found empty flash at 0x%x\n", ofs)); -- err = jffs2_scan_empty(c, jeb, &ofs, &noise); -- if (err) return err; -+ if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && -+ c->cleanmarker_size && !jeb->first_node->next_in_ino && !jeb->dirty_size) -+ return BLK_STATE_CLEANMARKER; -+ wasempty = 1; -+ continue; -+ } else if (wasempty) { -+ emptyends: -+ printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n", empty_start, ofs); -+ DIRTY_SPACE(ofs-empty_start); -+ wasempty = 0; - continue; - } - -- if (ofs == jeb->offset && node.magic == KSAMTIB_CIGAM_2SFFJ) { -+ if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) { - printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?\n", ofs); - DIRTY_SPACE(4); - ofs += 4; - continue; - } -- if (node.magic == JFFS2_DIRTY_BITMASK) { -- D1(printk(KERN_DEBUG "Empty bitmask at 0x%08x\n", ofs)); -+ if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) { -+ D1(printk(KERN_DEBUG "Dirty bitmask at 0x%08x\n", ofs)); - DIRTY_SPACE(4); - ofs += 4; - continue; - } -- if (node.magic == JFFS2_OLD_MAGIC_BITMASK) { -+ if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) { - printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs); - printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n"); - DIRTY_SPACE(4); - ofs += 4; - continue; - } -- if (node.magic != JFFS2_MAGIC_BITMASK) { -+ if (je16_to_cpu(node->magic) != JFFS2_MAGIC_BITMASK) { - /* OK. We're out of possibilities. Whinge and move on */ -- noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", JFFS2_MAGIC_BITMASK, ofs, node.magic); -+ noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", -+ JFFS2_MAGIC_BITMASK, ofs, -+ je16_to_cpu(node->magic)); - DIRTY_SPACE(4); - ofs += 4; - continue; - } - /* We seem to have a node of sorts. Check the CRC */ -- nodetype = node.nodetype; -- node.nodetype |= JFFS2_NODE_ACCURATE; -- hdr_crc = crc32(0, &node, sizeof(node)-4); -- node.nodetype = nodetype; -- if (hdr_crc != node.hdr_crc) { -+ crcnode.magic = node->magic; -+ crcnode.nodetype = cpu_to_je16( je16_to_cpu(node->nodetype) | JFFS2_NODE_ACCURATE); -+ crcnode.totlen = node->totlen; -+ hdr_crc = crc32(0, &crcnode, sizeof(crcnode)-4); -+ -+ if (hdr_crc != je32_to_cpu(node->hdr_crc)) { - noisy_printk(&noise, "jffs2_scan_eraseblock(): Node at 0x%08x {0x%04x, 0x%04x, 0x%08x) has invalid CRC 0x%08x (calculated 0x%08x)\n", -- ofs, node.magic, node.nodetype, node.totlen, node.hdr_crc, hdr_crc); -+ ofs, je16_to_cpu(node->magic), -+ je16_to_cpu(node->nodetype), -+ je32_to_cpu(node->totlen), -+ je32_to_cpu(node->hdr_crc), -+ hdr_crc); - DIRTY_SPACE(4); - ofs += 4; - continue; - } - -- if (ofs + node.totlen > jeb->offset + c->sector_size) { -+ if (ofs + je32_to_cpu(node->totlen) > -+ jeb->offset + c->sector_size) { - /* Eep. Node goes over the end of the erase block. */ - printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n", -- ofs, node.totlen); -+ ofs, je32_to_cpu(node->totlen)); - printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n"); - DIRTY_SPACE(4); - ofs += 4; - continue; - } - -- switch(node.nodetype | JFFS2_NODE_ACCURATE) { -+ if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) { -+ /* Wheee. This is an obsoleted node */ -+ D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs)); -+ DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); -+ ofs += PAD(je32_to_cpu(node->totlen)); -+ continue; -+ } -+ -+ switch(je16_to_cpu(node->nodetype)) { - case JFFS2_NODETYPE_INODE: -- err = jffs2_scan_inode_node(c, jeb, &ofs); -+ if (buf_ofs + buf_len < ofs + sizeof(struct jffs2_raw_inode)) { -+ buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); -+ D1(printk(KERN_DEBUG "Fewer than %zd bytes (inode node) left to end of buf. Reading 0x%x at 0x%08x\n", -+ sizeof(struct jffs2_raw_inode), buf_len, ofs)); -+ err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); -+ if (err) -+ return err; -+ buf_ofs = ofs; -+ node = (void *)buf; -+ } -+ err = jffs2_scan_inode_node(c, jeb, (void *)node, ofs); - if (err) return err; -+ ofs += PAD(je32_to_cpu(node->totlen)); - break; - - case JFFS2_NODETYPE_DIRENT: -- err = jffs2_scan_dirent_node(c, jeb, &ofs); -+ if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) { -+ buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); -+ D1(printk(KERN_DEBUG "Fewer than %d bytes (dirent node) left to end of buf. Reading 0x%x at 0x%08x\n", -+ je32_to_cpu(node->totlen), buf_len, ofs)); -+ err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); -+ if (err) -+ return err; -+ buf_ofs = ofs; -+ node = (void *)buf; -+ } -+ err = jffs2_scan_dirent_node(c, jeb, (void *)node, ofs); - if (err) return err; -+ ofs += PAD(je32_to_cpu(node->totlen)); - break; - - case JFFS2_NODETYPE_CLEANMARKER: -- if (node.totlen != sizeof(struct jffs2_unknown_node)) { -+ D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs)); -+ if (je32_to_cpu(node->totlen) != c->cleanmarker_size) { - printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", -- ofs, node.totlen, sizeof(struct jffs2_unknown_node)); -+ ofs, je32_to_cpu(node->totlen), c->cleanmarker_size); - DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); -+ ofs += PAD(sizeof(struct jffs2_unknown_node)); - } else if (jeb->first_node) { - printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset); - DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); - ofs += PAD(sizeof(struct jffs2_unknown_node)); -- continue; - } else { - struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); - if (!marker_ref) { -@@ -300,98 +553,80 @@ - } - marker_ref->next_in_ino = NULL; - marker_ref->next_phys = NULL; -- marker_ref->flash_offset = ofs; -- marker_ref->totlen = sizeof(struct jffs2_unknown_node); -+ marker_ref->flash_offset = ofs | REF_NORMAL; -+ marker_ref->__totlen = c->cleanmarker_size; - jeb->first_node = jeb->last_node = marker_ref; - -- USED_SPACE(PAD(sizeof(struct jffs2_unknown_node))); -+ USED_SPACE(PAD(c->cleanmarker_size)); -+ ofs += PAD(c->cleanmarker_size); - } -- ofs += PAD(sizeof(struct jffs2_unknown_node)); -+ break; -+ -+ case JFFS2_NODETYPE_PADDING: -+ DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); -+ ofs += PAD(je32_to_cpu(node->totlen)); - break; - - default: -- switch (node.nodetype & JFFS2_COMPAT_MASK) { -+ switch (je16_to_cpu(node->nodetype) & JFFS2_COMPAT_MASK) { - case JFFS2_FEATURE_ROCOMPAT: -- printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs); -+ printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs); - c->flags |= JFFS2_SB_FLAG_RO; -- if (!(OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY)) -+ if (!(jffs2_is_readonly(c))) - return -EROFS; -- DIRTY_SPACE(PAD(node.totlen)); -- ofs += PAD(node.totlen); -- continue; -+ DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); -+ ofs += PAD(je32_to_cpu(node->totlen)); -+ break; - - case JFFS2_FEATURE_INCOMPAT: -- printk(KERN_NOTICE "Incompatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs); -+ printk(KERN_NOTICE "Incompatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs); - return -EINVAL; - - case JFFS2_FEATURE_RWCOMPAT_DELETE: -- printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs); -- DIRTY_SPACE(PAD(node.totlen)); -- ofs += PAD(node.totlen); -+ D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); -+ DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); -+ ofs += PAD(je32_to_cpu(node->totlen)); - break; - - case JFFS2_FEATURE_RWCOMPAT_COPY: -- printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs); -- USED_SPACE(PAD(node.totlen)); -- ofs += PAD(node.totlen); -+ D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); -+ USED_SPACE(PAD(je32_to_cpu(node->totlen))); -+ ofs += PAD(je32_to_cpu(node->totlen)); - break; - } - } - } -- D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, used 0x%08x\n", jeb->offset, -- jeb->free_size, jeb->dirty_size, jeb->used_size)); -- return 0; --} - --/* We're pointing at the first empty word on the flash. Scan and account for the whole dirty region */ --static int jffs2_scan_empty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, __u32 *startofs, int *noise) --{ -- __u32 *buf; -- __u32 scanlen = (jeb->offset + c->sector_size) - *startofs; -- __u32 curofs = *startofs; -- -- buf = kmalloc(min((__u32)PAGE_SIZE, scanlen), GFP_KERNEL); -- if (!buf) { -- printk(KERN_WARNING "Scan buffer allocation failed\n"); -- return -ENOMEM; -- } -- while(scanlen) { -- ssize_t retlen; -- int ret, i; -- -- ret = c->mtd->read(c->mtd, curofs, min((__u32)PAGE_SIZE, scanlen), &retlen, (char *)buf); -- if(ret) { -- D1(printk(KERN_WARNING "jffs2_scan_empty(): Read 0x%x bytes at 0x%08x returned %d\n", min((__u32)PAGE_SIZE, scanlen), curofs, ret)); -- kfree(buf); -- return ret; -- } -- if (retlen < 4) { -- D1(printk(KERN_WARNING "Eep. too few bytes read in scan_empty()\n")); -- kfree(buf); -- return -EIO; -- } -- for (i=0; i<(retlen / 4); i++) { -- if (buf[i] != 0xffffffff) { -- curofs += i*4; -- -- noisy_printk(noise, "jffs2_scan_empty(): Empty block at 0x%08x ends at 0x%08x (with 0x%08x)! Marking dirty\n", *startofs, curofs, buf[i]); -- DIRTY_SPACE(curofs - (*startofs)); -- *startofs = curofs; -- kfree(buf); -- return 0; -- } -- } -- scanlen -= retlen&~3; -- curofs += retlen&~3; -- } - -- D1(printk(KERN_DEBUG "Empty flash detected from 0x%08x to 0x%08x\n", *startofs, curofs)); -- kfree(buf); -- *startofs = curofs; -- return 0; -+ D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, -+ jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size)); -+ -+ /* mark_node_obsolete can add to wasted !! */ -+ if (jeb->wasted_size) { -+ jeb->dirty_size += jeb->wasted_size; -+ c->dirty_size += jeb->wasted_size; -+ c->wasted_size -= jeb->wasted_size; -+ jeb->wasted_size = 0; -+ } -+ -+ if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size -+ && (!jeb->first_node || jeb->first_node->next_in_ino) ) -+ return BLK_STATE_CLEANMARKER; -+ -+ /* move blocks with max 4 byte dirty space to cleanlist */ -+ else if (!ISDIRTY(c->sector_size - (jeb->used_size + jeb->unchecked_size))) { -+ c->dirty_size -= jeb->dirty_size; -+ c->wasted_size += jeb->dirty_size; -+ jeb->wasted_size += jeb->dirty_size; -+ jeb->dirty_size = 0; -+ return BLK_STATE_CLEAN; -+ } else if (jeb->used_size || jeb->unchecked_size) -+ return BLK_STATE_PARTDIRTY; -+ else -+ return BLK_STATE_ALLDIRTY; - } - --static struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, __u32 ino) -+static struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino) - { - struct jffs2_inode_cache *ic; - -@@ -399,137 +634,77 @@ - if (ic) - return ic; - -+ if (ino > c->highest_ino) -+ c->highest_ino = ino; -+ - ic = jffs2_alloc_inode_cache(); - if (!ic) { - printk(KERN_NOTICE "jffs2_scan_make_inode_cache(): allocation of inode cache failed\n"); - return NULL; - } - memset(ic, 0, sizeof(*ic)); -- ic->scan = kmalloc(sizeof(struct jffs2_scan_info), GFP_KERNEL); -- if (!ic->scan) { -- printk(KERN_NOTICE "jffs2_scan_make_inode_cache(): allocation of scan info for inode cache failed\n"); -- jffs2_free_inode_cache(ic); -- return NULL; -- } -- memset(ic->scan, 0, sizeof(*ic->scan)); -+ - ic->ino = ino; - ic->nodes = (void *)ic; - jffs2_add_ino_cache(c, ic); - if (ino == 1) -- ic->nlink=1; -+ ic->nlink = 1; - return ic; - } - --static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, __u32 *ofs) -+static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_inode *ri, uint32_t ofs) - { - struct jffs2_raw_node_ref *raw; -- struct jffs2_full_dnode *fn; -- struct jffs2_tmp_dnode_info *tn, **tn_list; - struct jffs2_inode_cache *ic; -- struct jffs2_raw_inode ri; -- __u32 crc; -- __u16 oldnodetype; -- int ret; -- ssize_t retlen; -- -- D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", *ofs)); -- -- ret = c->mtd->read(c->mtd, *ofs, sizeof(ri), &retlen, (char *)&ri); -- if (ret) { -- printk(KERN_NOTICE "jffs2_scan_inode_node(): Read error at 0x%08x: %d\n", *ofs, ret); -- return ret; -- } -- if (retlen != sizeof(ri)) { -- printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", -- retlen, *ofs, sizeof(ri)); -- return -EIO; -- } -+ uint32_t ino = je32_to_cpu(ri->ino); - -- /* We sort of assume that the node was accurate when it was -- first written to the medium :) */ -- oldnodetype = ri.nodetype; -- ri.nodetype |= JFFS2_NODE_ACCURATE; -- crc = crc32(0, &ri, sizeof(ri)-8); -- ri.nodetype = oldnodetype; -+ D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs)); - -- if(crc != ri.node_crc) { -- printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -- *ofs, ri.node_crc, crc); -- /* FIXME: Why do we believe totlen? */ -- DIRTY_SPACE(4); -- *ofs += 4; -- return 0; -- } -- /* There was a bug where we wrote hole nodes out with csize/dsize -- swapped. Deal with it */ -- if (ri.compr == JFFS2_COMPR_ZERO && !ri.dsize && ri.csize) { -- ri.dsize = ri.csize; -- ri.csize = 0; -- } -+ /* We do very little here now. Just check the ino# to which we should attribute -+ this node; we can do all the CRC checking etc. later. There's a tradeoff here -- -+ we used to scan the flash once only, reading everything we want from it into -+ memory, then building all our in-core data structures and freeing the extra -+ information. Now we allow the first part of the mount to complete a lot quicker, -+ but we have to go _back_ to the flash in order to finish the CRC checking, etc. -+ Which means that the _full_ amount of time to get to proper write mode with GC -+ operational may actually be _longer_ than before. Sucks to be me. */ - -- if (ri.csize) { -- /* Check data CRC too */ -- unsigned char *dbuf; -- __u32 crc; -- -- dbuf = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL); -- if (!dbuf) { -- printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of temporary data buffer for CRC check failed\n"); -- return -ENOMEM; -- } -- ret = c->mtd->read(c->mtd, *ofs+sizeof(ri), ri.csize, &retlen, dbuf); -- if (ret) { -- printk(KERN_NOTICE "jffs2_scan_inode_node(): Read error at 0x%08x: %d\n", *ofs+sizeof(ri), ret); -- kfree(dbuf); -- return ret; -- } -- if (retlen != ri.csize) { -- printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", -- retlen, *ofs+ sizeof(ri), ri.csize); -- kfree(dbuf); -- return -EIO; -- } -- crc = crc32(0, dbuf, ri.csize); -- kfree(dbuf); -- if (crc != ri.data_crc) { -- printk(KERN_NOTICE "jffs2_scan_inode_node(): Data CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -- *ofs, ri.data_crc, crc); -- DIRTY_SPACE(PAD(ri.totlen)); -- *ofs += PAD(ri.totlen); -- return 0; -- } -- } -- -- /* Wheee. It worked */ - raw = jffs2_alloc_raw_node_ref(); - if (!raw) { - printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n"); - return -ENOMEM; - } -- tn = jffs2_alloc_tmp_dnode_info(); -- if (!tn) { -- jffs2_free_raw_node_ref(raw); -- return -ENOMEM; -- } -- fn = jffs2_alloc_full_dnode(); -- if (!fn) { -- jffs2_free_tmp_dnode_info(tn); -+ -+ ic = jffs2_get_ino_cache(c, ino); -+ if (!ic) { -+ /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the -+ first node we found for this inode. Do a CRC check to protect against the former -+ case */ -+ uint32_t crc = crc32(0, ri, sizeof(*ri)-8); -+ -+ if (crc != je32_to_cpu(ri->node_crc)) { -+ printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ofs, je32_to_cpu(ri->node_crc), crc); -+ /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ -+ DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen))); - jffs2_free_raw_node_ref(raw); -- return -ENOMEM; -+ return 0; - } -- ic = jffs2_scan_make_ino_cache(c, ri.ino); -+ ic = jffs2_scan_make_ino_cache(c, ino); - if (!ic) { -- jffs2_free_full_dnode(fn); -- jffs2_free_tmp_dnode_info(tn); - jffs2_free_raw_node_ref(raw); - return -ENOMEM; - } -+ } - -- /* Build the data structures and file them for later */ -- raw->flash_offset = *ofs; -- raw->totlen = PAD(ri.totlen); -+ /* Wheee. It worked */ -+ -+ raw->flash_offset = ofs | REF_UNCHECKED; -+ raw->__totlen = PAD(je32_to_cpu(ri->totlen)); - raw->next_phys = NULL; - raw->next_in_ino = ic->nodes; -+ - ic->nodes = raw; - if (!jeb->first_node) - jeb->first_node = raw; -@@ -538,134 +713,56 @@ - jeb->last_node = raw; - - D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", -- ri.ino, ri.version, ri.offset, ri.offset+ri.dsize)); -- -- pseudo_random += ri.version; -- -- for (tn_list = &ic->scan->tmpnodes; *tn_list; tn_list = &((*tn_list)->next)) { -- if ((*tn_list)->version < ri.version) -- continue; -- if ((*tn_list)->version > ri.version) -- break; -- /* Wheee. We've found another instance of the same version number. -- We should obsolete one of them. -- */ -- D1(printk(KERN_DEBUG "Duplicate version %d found in ino #%u. Previous one is at 0x%08x\n", ri.version, ic->ino, (*tn_list)->fn->raw->flash_offset &~3)); -- if (!jeb->used_size) { -- D1(printk(KERN_DEBUG "No valid nodes yet found in this eraseblock 0x%08x, so obsoleting the new instance at 0x%08x\n", -- jeb->offset, raw->flash_offset & ~3)); -- ri.nodetype &= ~JFFS2_NODE_ACCURATE; -- /* Perhaps we could also mark it as such on the medium. Maybe later */ -- } -- break; -- } -- -- if (ri.nodetype & JFFS2_NODE_ACCURATE) { -- memset(fn,0,sizeof(*fn)); -- -- fn->ofs = ri.offset; -- fn->size = ri.dsize; -- fn->frags = 0; -- fn->raw = raw; -- -- tn->next = NULL; -- tn->fn = fn; -- tn->version = ri.version; -+ je32_to_cpu(ri->ino), je32_to_cpu(ri->version), -+ je32_to_cpu(ri->offset), -+ je32_to_cpu(ri->offset)+je32_to_cpu(ri->dsize))); - -- USED_SPACE(PAD(ri.totlen)); -- jffs2_add_tn_to_list(tn, &ic->scan->tmpnodes); -- /* Make sure the one we just added is the _last_ in the list -- with this version number, so the older ones get obsoleted */ -- while (tn->next && tn->next->version == tn->version) { -+ pseudo_random += je32_to_cpu(ri->version); - -- D1(printk(KERN_DEBUG "Shifting new node at 0x%08x after other node at 0x%08x for version %d in list\n", -- fn->raw->flash_offset&~3, tn->next->fn->raw->flash_offset &~3, ri.version)); -- -- if(tn->fn != fn) -- BUG(); -- tn->fn = tn->next->fn; -- tn->next->fn = fn; -- tn = tn->next; -- } -- } else { -- jffs2_free_full_dnode(fn); -- jffs2_free_tmp_dnode_info(tn); -- raw->flash_offset |= 1; -- DIRTY_SPACE(PAD(ri.totlen)); -- } -- *ofs += PAD(ri.totlen); -+ UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen))); - return 0; - } - --static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, __u32 *ofs) -+static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_dirent *rd, uint32_t ofs) - { - struct jffs2_raw_node_ref *raw; - struct jffs2_full_dirent *fd; - struct jffs2_inode_cache *ic; -- struct jffs2_raw_dirent rd; -- __u16 oldnodetype; -- int ret; -- __u32 crc; -- ssize_t retlen; -- -- D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", *ofs)); -+ uint32_t crc; - -- ret = c->mtd->read(c->mtd, *ofs, sizeof(rd), &retlen, (char *)&rd); -- if (ret) { -- printk(KERN_NOTICE "jffs2_scan_dirent_node(): Read error at 0x%08x: %d\n", *ofs, ret); -- return ret; -- } -- if (retlen != sizeof(rd)) { -- printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", -- retlen, *ofs, sizeof(rd)); -- return -EIO; -- } -+ D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", ofs)); - -- /* We sort of assume that the node was accurate when it was -- first written to the medium :) */ -- oldnodetype = rd.nodetype; -- rd.nodetype |= JFFS2_NODE_ACCURATE; -- crc = crc32(0, &rd, sizeof(rd)-8); -- rd.nodetype = oldnodetype; -+ /* We don't get here unless the node is still valid, so we don't have to -+ mask in the ACCURATE bit any more. */ -+ crc = crc32(0, rd, sizeof(*rd)-8); - -- if (crc != rd.node_crc) { -+ if (crc != je32_to_cpu(rd->node_crc)) { - printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -- *ofs, rd.node_crc, crc); -- /* FIXME: Why do we believe totlen? */ -- DIRTY_SPACE(4); -- *ofs += 4; -+ ofs, je32_to_cpu(rd->node_crc), crc); -+ /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ -+ DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen))); - return 0; - } - -- pseudo_random += rd.version; -+ pseudo_random += je32_to_cpu(rd->version); - -- fd = jffs2_alloc_full_dirent(rd.nsize+1); -+ fd = jffs2_alloc_full_dirent(rd->nsize+1); - if (!fd) { - return -ENOMEM; --} -- ret = c->mtd->read(c->mtd, *ofs + sizeof(rd), rd.nsize, &retlen, &fd->name[0]); -- if (ret) { -- jffs2_free_full_dirent(fd); -- printk(KERN_NOTICE "jffs2_scan_dirent_node(): Read error at 0x%08x: %d\n", -- *ofs + sizeof(rd), ret); -- return ret; -- } -- if (retlen != rd.nsize) { -- jffs2_free_full_dirent(fd); -- printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", -- retlen, *ofs + sizeof(rd), rd.nsize); -- return -EIO; - } -- crc = crc32(0, fd->name, rd.nsize); -- if (crc != rd.name_crc) { -+ memcpy(&fd->name, rd->name, rd->nsize); -+ fd->name[rd->nsize] = 0; -+ -+ crc = crc32(0, fd->name, rd->nsize); -+ if (crc != je32_to_cpu(rd->name_crc)) { - printk(KERN_NOTICE "jffs2_scan_dirent_node(): Name CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -- *ofs, rd.name_crc, crc); -- fd->name[rd.nsize]=0; -- D1(printk(KERN_NOTICE "Name for which CRC failed is (now) '%s', ino #%d\n", fd->name, rd.ino)); -+ ofs, je32_to_cpu(rd->name_crc), crc); -+ D1(printk(KERN_NOTICE "Name for which CRC failed is (now) '%s', ino #%d\n", fd->name, je32_to_cpu(rd->ino))); - jffs2_free_full_dirent(fd); - /* FIXME: Why do we believe totlen? */ -- DIRTY_SPACE(PAD(rd.totlen)); -- *ofs += PAD(rd.totlen); -+ /* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */ -+ DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen))); - return 0; - } - raw = jffs2_alloc_raw_node_ref(); -@@ -674,15 +771,15 @@ - printk(KERN_NOTICE "jffs2_scan_dirent_node(): allocation of node reference failed\n"); - return -ENOMEM; - } -- ic = jffs2_scan_make_ino_cache(c, rd.pino); -+ ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino)); - if (!ic) { - jffs2_free_full_dirent(fd); - jffs2_free_raw_node_ref(raw); - return -ENOMEM; - } - -- raw->totlen = PAD(rd.totlen); -- raw->flash_offset = *ofs; -+ raw->__totlen = PAD(je32_to_cpu(rd->totlen)); -+ raw->flash_offset = ofs | REF_PRISTINE; - raw->next_phys = NULL; - raw->next_in_ino = ic->nodes; - ic->nodes = raw; -@@ -692,24 +789,15 @@ - jeb->last_node->next_phys = raw; - jeb->last_node = raw; - -- if (rd.nodetype & JFFS2_NODE_ACCURATE) { - fd->raw = raw; - fd->next = NULL; -- fd->version = rd.version; -- fd->ino = rd.ino; -- fd->name[rd.nsize]=0; -- fd->nhash = full_name_hash(fd->name, rd.nsize); -- fd->type = rd.type; -- -- USED_SPACE(PAD(rd.totlen)); -- jffs2_add_fd_to_list(c, fd, &ic->scan->dents); -- } else { -- raw->flash_offset |= 1; -- jffs2_free_full_dirent(fd); -+ fd->version = je32_to_cpu(rd->version); -+ fd->ino = je32_to_cpu(rd->ino); -+ fd->nhash = full_name_hash(fd->name, rd->nsize); -+ fd->type = rd->type; -+ USED_SPACE(PAD(je32_to_cpu(rd->totlen))); -+ jffs2_add_fd_to_list(c, fd, &ic->scan_dents); - -- DIRTY_SPACE(PAD(rd.totlen)); -- } -- *ofs += PAD(rd.totlen); - return 0; - } - -@@ -731,26 +819,90 @@ - struct list_head *n = head->next; - - list_del(head); -- while(count--) -+ while(count--) { - n = n->next; -+ } - list_add(head, n); - } - --static void jffs2_rotate_lists(struct jffs2_sb_info *c) -+void jffs2_rotate_lists(struct jffs2_sb_info *c) - { - uint32_t x; -+ uint32_t rotateby; - - x = count_list(&c->clean_list); -- if (x) -- rotate_list((&c->clean_list), pseudo_random % x); -+ if (x) { -+ rotateby = pseudo_random % x; -+ D1(printk(KERN_DEBUG "Rotating clean_list by %d\n", rotateby)); -+ -+ rotate_list((&c->clean_list), rotateby); -+ -+ D1(printk(KERN_DEBUG "Erase block at front of clean_list is at %08x\n", -+ list_entry(c->clean_list.next, struct jffs2_eraseblock, list)->offset)); -+ } else { -+ D1(printk(KERN_DEBUG "Not rotating empty clean_list\n")); -+ } -+ -+ x = count_list(&c->very_dirty_list); -+ if (x) { -+ rotateby = pseudo_random % x; -+ D1(printk(KERN_DEBUG "Rotating very_dirty_list by %d\n", rotateby)); -+ -+ rotate_list((&c->very_dirty_list), rotateby); -+ -+ D1(printk(KERN_DEBUG "Erase block at front of very_dirty_list is at %08x\n", -+ list_entry(c->very_dirty_list.next, struct jffs2_eraseblock, list)->offset)); -+ } else { -+ D1(printk(KERN_DEBUG "Not rotating empty very_dirty_list\n")); -+ } - - x = count_list(&c->dirty_list); -- if (x) -- rotate_list((&c->dirty_list), pseudo_random % x); -+ if (x) { -+ rotateby = pseudo_random % x; -+ D1(printk(KERN_DEBUG "Rotating dirty_list by %d\n", rotateby)); -+ -+ rotate_list((&c->dirty_list), rotateby); -+ -+ D1(printk(KERN_DEBUG "Erase block at front of dirty_list is at %08x\n", -+ list_entry(c->dirty_list.next, struct jffs2_eraseblock, list)->offset)); -+ } else { -+ D1(printk(KERN_DEBUG "Not rotating empty dirty_list\n")); -+ } -+ -+ x = count_list(&c->erasable_list); -+ if (x) { -+ rotateby = pseudo_random % x; -+ D1(printk(KERN_DEBUG "Rotating erasable_list by %d\n", rotateby)); - -- if (c->nr_erasing_blocks) -- rotate_list((&c->erase_pending_list), pseudo_random % c->nr_erasing_blocks); -+ rotate_list((&c->erasable_list), rotateby); - -- if (c->nr_free_blocks) /* Not that it should ever be zero */ -- rotate_list((&c->free_list), pseudo_random % c->nr_free_blocks); -+ D1(printk(KERN_DEBUG "Erase block at front of erasable_list is at %08x\n", -+ list_entry(c->erasable_list.next, struct jffs2_eraseblock, list)->offset)); -+ } else { -+ D1(printk(KERN_DEBUG "Not rotating empty erasable_list\n")); -+ } -+ -+ if (c->nr_erasing_blocks) { -+ rotateby = pseudo_random % c->nr_erasing_blocks; -+ D1(printk(KERN_DEBUG "Rotating erase_pending_list by %d\n", rotateby)); -+ -+ rotate_list((&c->erase_pending_list), rotateby); -+ -+ D1(printk(KERN_DEBUG "Erase block at front of erase_pending_list is at %08x\n", -+ list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list)->offset)); -+ } else { -+ D1(printk(KERN_DEBUG "Not rotating empty erase_pending_list\n")); -+ } -+ -+ if (c->nr_free_blocks) { -+ rotateby = pseudo_random % c->nr_free_blocks; -+ D1(printk(KERN_DEBUG "Rotating free_list by %d\n", rotateby)); -+ -+ rotate_list((&c->free_list), rotateby); -+ -+ D1(printk(KERN_DEBUG "Erase block at front of free_list is at %08x\n", -+ list_entry(c->free_list.next, struct jffs2_eraseblock, list)->offset)); -+ } else { -+ D1(printk(KERN_DEBUG "Not rotating empty free_list\n")); -+ } - } -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/super-v24.c linux/fs/jffs2/super-v24.c ---- linux-mips-2.4.24-pre2/fs/jffs2/super-v24.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/super-v24.c 2004-11-17 18:17:59.374263000 +0100 -@@ -0,0 +1,167 @@ -+/* -+ * JFFS2 -- Journalling Flash File System, Version 2. -+ * -+ * Copyright (C) 2001-2003 Red Hat, Inc. -+ * -+ * Created by David Woodhouse -+ * -+ * For licensing information, see the file 'LICENCE' in this directory. -+ * -+ * $Id$ -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "nodelist.h" -+ -+#ifndef MTD_BLOCK_MAJOR -+#define MTD_BLOCK_MAJOR 31 -+#endif -+ -+static void jffs2_put_super (struct super_block *); -+ -+static struct super_operations jffs2_super_operations = -+{ -+ .read_inode = jffs2_read_inode, -+ .put_super = jffs2_put_super, -+ .write_super = jffs2_write_super, -+ .statfs = jffs2_statfs, -+ .remount_fs = jffs2_remount_fs, -+ .clear_inode = jffs2_clear_inode, -+ .dirty_inode = jffs2_dirty_inode, -+}; -+ -+ -+static struct super_block *jffs2_read_super(struct super_block *sb, void *data, int silent) -+{ -+ struct jffs2_sb_info *c; -+ int ret; -+ -+ D1(printk(KERN_DEBUG "jffs2: read_super for device %s\n", kdevname(sb->s_dev))); -+ -+ if (major(sb->s_dev) != MTD_BLOCK_MAJOR) { -+ if (!silent) -+ printk(KERN_DEBUG "jffs2: attempt to mount non-MTD device %s\n", kdevname(sb->s_dev)); -+ return NULL; -+ } -+ -+ c = JFFS2_SB_INFO(sb); -+ memset(c, 0, sizeof(*c)); -+ -+ sb->s_op = &jffs2_super_operations; -+ -+ c->mtd = get_mtd_device(NULL, minor(sb->s_dev)); -+ if (!c->mtd) { -+ D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", minor(sb->s_dev))); -+ return NULL; -+ } -+ -+ ret = jffs2_do_fill_super(sb, data, silent); -+ if (ret) { -+ put_mtd_device(c->mtd); -+ return NULL; -+ } -+ -+ return sb; -+} -+ -+static void jffs2_put_super (struct super_block *sb) -+{ -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); -+ -+ D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n")); -+ -+ -+ if (!(sb->s_flags & MS_RDONLY)) -+ jffs2_stop_garbage_collect_thread(c); -+ down(&c->alloc_sem); -+ jffs2_flush_wbuf_pad(c); -+ up(&c->alloc_sem); -+ jffs2_free_ino_caches(c); -+ jffs2_free_raw_node_refs(c); -+ kfree(c->blocks); -+ jffs2_nand_flash_cleanup(c); -+ kfree(c->inocache_list); -+ if (c->mtd->sync) -+ c->mtd->sync(c->mtd); -+ put_mtd_device(c->mtd); -+ -+ D1(printk(KERN_DEBUG "jffs2_put_super returning\n")); -+} -+ -+static DECLARE_FSTYPE_DEV(jffs2_fs_type, "jffs2", jffs2_read_super); -+ -+static int __init init_jffs2_fs(void) -+{ -+ int ret; -+ -+ printk(KERN_INFO "JFFS2 version 2.2." -+#ifdef CONFIG_FS_JFFS2_NAND -+ " (NAND)" -+#endif -+ " (C) 2001-2003 Red Hat, Inc.\n"); -+ -+#ifdef JFFS2_OUT_OF_KERNEL -+ /* sanity checks. Could we do these at compile time? */ -+ if (sizeof(struct jffs2_sb_info) > sizeof (((struct super_block *)NULL)->u)) { -+ printk(KERN_ERR "JFFS2 error: struct jffs2_sb_info (%d bytes) doesn't fit in the super_block union (%d bytes)\n", -+ sizeof(struct jffs2_sb_info), sizeof (((struct super_block *)NULL)->u)); -+ return -EIO; -+ } -+ -+ if (sizeof(struct jffs2_inode_info) > sizeof (((struct inode *)NULL)->u)) { -+ printk(KERN_ERR "JFFS2 error: struct jffs2_inode_info (%d bytes) doesn't fit in the inode union (%d bytes)\n", -+ sizeof(struct jffs2_inode_info), sizeof (((struct inode *)NULL)->u)); -+ return -EIO; -+ } -+#endif -+ ret = jffs2_zlib_init(); -+ if (ret) { -+ printk(KERN_ERR "JFFS2 error: Failed to initialise zlib workspaces\n"); -+ goto out; -+ } -+ ret = jffs2_create_slab_caches(); -+ if (ret) { -+ printk(KERN_ERR "JFFS2 error: Failed to initialise slab caches\n"); -+ goto out_zlib; -+ } -+ ret = register_filesystem(&jffs2_fs_type); -+ if (ret) { -+ printk(KERN_ERR "JFFS2 error: Failed to register filesystem\n"); -+ goto out_slab; -+ } -+ return 0; -+ -+ out_slab: -+ jffs2_destroy_slab_caches(); -+ out_zlib: -+ jffs2_zlib_exit(); -+ out: -+ -+ return ret; -+} -+ -+static void __exit exit_jffs2_fs(void) -+{ -+ jffs2_destroy_slab_caches(); -+ jffs2_zlib_exit(); -+ unregister_filesystem(&jffs2_fs_type); -+} -+ -+module_init(init_jffs2_fs); -+module_exit(exit_jffs2_fs); -+ -+MODULE_DESCRIPTION("The Journalling Flash File System, v2"); -+MODULE_AUTHOR("Red Hat, Inc."); -+MODULE_LICENSE("GPL"); // Actually dual-licensed, but it doesn't matter for -+ // the sake of this tag. It's Free Software. -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/super.c linux/fs/jffs2/super.c ---- linux-mips-2.4.24-pre2/fs/jffs2/super.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/super.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,291 +1,257 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include - #include - #include --#include - #include - #include - #include - #include -+#include - #include - #include - #include --#include -+#include -+#include - #include "nodelist.h" - --#ifndef MTD_BLOCK_MAJOR --#define MTD_BLOCK_MAJOR 31 --#endif -+static void jffs2_put_super(struct super_block *); -+ -+static kmem_cache_t *jffs2_inode_cachep; -+ -+static struct inode *jffs2_alloc_inode(struct super_block *sb) -+{ -+ struct jffs2_inode_info *ei; -+ ei = (struct jffs2_inode_info *)kmem_cache_alloc(jffs2_inode_cachep, SLAB_KERNEL); -+ if (!ei) -+ return NULL; -+ return &ei->vfs_inode; -+} -+ -+static void jffs2_destroy_inode(struct inode *inode) -+{ -+ kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode)); -+} -+ -+static void jffs2_i_init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) -+{ -+ struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo; - --extern void jffs2_read_inode (struct inode *); --void jffs2_put_super (struct super_block *); --void jffs2_write_super (struct super_block *); --static int jffs2_statfs (struct super_block *, struct statfs *); --int jffs2_remount_fs (struct super_block *, int *, char *); --extern void jffs2_clear_inode (struct inode *); -+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == -+ SLAB_CTOR_CONSTRUCTOR) { -+ init_MUTEX_LOCKED(&ei->sem); -+ inode_init_once(&ei->vfs_inode); -+ } -+} - - static struct super_operations jffs2_super_operations = - { -- read_inode: jffs2_read_inode, --// delete_inode: jffs2_delete_inode, -- put_super: jffs2_put_super, -- write_super: jffs2_write_super, -- statfs: jffs2_statfs, -- remount_fs: jffs2_remount_fs, -- clear_inode: jffs2_clear_inode -+ .alloc_inode = jffs2_alloc_inode, -+ .destroy_inode =jffs2_destroy_inode, -+ .read_inode = jffs2_read_inode, -+ .put_super = jffs2_put_super, -+ .write_super = jffs2_write_super, -+ .statfs = jffs2_statfs, -+ .remount_fs = jffs2_remount_fs, -+ .clear_inode = jffs2_clear_inode, -+ .dirty_inode = jffs2_dirty_inode, - }; - --static int jffs2_statfs(struct super_block *sb, struct statfs *buf) -+static int jffs2_sb_compare(struct super_block *sb, void *data) - { -+ struct jffs2_sb_info *p = data; - struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); -- unsigned long avail; - -- buf->f_type = JFFS2_SUPER_MAGIC; -- buf->f_bsize = 1 << PAGE_SHIFT; -- buf->f_blocks = c->flash_size >> PAGE_SHIFT; -- buf->f_files = 0; -- buf->f_ffree = 0; -- buf->f_namelen = JFFS2_MAX_NAME_LEN; -- -- spin_lock_bh(&c->erase_completion_lock); -- -- avail = c->dirty_size + c->free_size; -- if (avail > c->sector_size * JFFS2_RESERVED_BLOCKS_WRITE) -- avail -= c->sector_size * JFFS2_RESERVED_BLOCKS_WRITE; -- else -- avail = 0; -- -- buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT; -- --#if CONFIG_JFFS2_FS_DEBUG > 0 -- printk(KERN_DEBUG "STATFS:\n"); -- printk(KERN_DEBUG "flash_size: %08x\n", c->flash_size); -- printk(KERN_DEBUG "used_size: %08x\n", c->used_size); -- printk(KERN_DEBUG "dirty_size: %08x\n", c->dirty_size); -- printk(KERN_DEBUG "free_size: %08x\n", c->free_size); -- printk(KERN_DEBUG "erasing_size: %08x\n", c->erasing_size); -- printk(KERN_DEBUG "bad_size: %08x\n", c->bad_size); -- printk(KERN_DEBUG "sector_size: %08x\n", c->sector_size); -- -- if (c->nextblock) { -- printk(KERN_DEBUG "nextblock: 0x%08x\n", c->nextblock->offset); -- } else { -- printk(KERN_DEBUG "nextblock: NULL\n"); -- } -- if (c->gcblock) { -- printk(KERN_DEBUG "gcblock: 0x%08x\n", c->gcblock->offset); -+ /* The superblocks are considered to be equivalent if the underlying MTD -+ device is the same one */ -+ if (c->mtd == p->mtd) { -+ D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", p->mtd->index, p->mtd->name)); -+ return 1; - } else { -- printk(KERN_DEBUG "gcblock: NULL\n"); -+ D1(printk(KERN_DEBUG "jffs2_sb_compare: No match, device %d (\"%s\"), device %d (\"%s\")\n", -+ c->mtd->index, c->mtd->name, p->mtd->index, p->mtd->name)); -+ return 0; - } -- if (list_empty(&c->clean_list)) { -- printk(KERN_DEBUG "clean_list: empty\n"); -- } else { -- struct list_head *this; -+} - -- list_for_each(this, &c->clean_list) { -- struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -- printk(KERN_DEBUG "clean_list: %08x\n", jeb->offset); -- } -- } -- if (list_empty(&c->dirty_list)) { -- printk(KERN_DEBUG "dirty_list: empty\n"); -- } else { -- struct list_head *this; -+static int jffs2_sb_set(struct super_block *sb, void *data) -+{ -+ struct jffs2_sb_info *p = data; - -- list_for_each(this, &c->dirty_list) { -- struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -- printk(KERN_DEBUG "dirty_list: %08x\n", jeb->offset); -- } -- } -- if (list_empty(&c->erasing_list)) { -- printk(KERN_DEBUG "erasing_list: empty\n"); -- } else { -- struct list_head *this; -+ /* For persistence of NFS exports etc. we use the same s_dev -+ each time we mount the device, don't just use an anonymous -+ device */ -+ sb->s_fs_info = p; -+ p->os_priv = sb; -+ sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, p->mtd->index); - -- list_for_each(this, &c->erasing_list) { -- struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -- printk(KERN_DEBUG "erasing_list: %08x\n", jeb->offset); -- } -- } -- if (list_empty(&c->erase_pending_list)) { -- printk(KERN_DEBUG "erase_pending_list: empty\n"); -- } else { -- struct list_head *this; -+ return 0; -+} - -- list_for_each(this, &c->erase_pending_list) { -- struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -- printk(KERN_DEBUG "erase_pending_list: %08x\n", jeb->offset); -- } -- } -- if (list_empty(&c->free_list)) { -- printk(KERN_DEBUG "free_list: empty\n"); -- } else { -- struct list_head *this; -+static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, -+ int flags, const char *dev_name, -+ void *data, struct mtd_info *mtd) -+{ -+ struct super_block *sb; -+ struct jffs2_sb_info *c; -+ int ret; - -- list_for_each(this, &c->free_list) { -- struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -- printk(KERN_DEBUG "free_list: %08x\n", jeb->offset); -- } -- } -- if (list_empty(&c->bad_list)) { -- printk(KERN_DEBUG "bad_list: empty\n"); -- } else { -- struct list_head *this; -+ c = kmalloc(sizeof(*c), GFP_KERNEL); -+ if (!c) -+ return ERR_PTR(-ENOMEM); -+ memset(c, 0, sizeof(*c)); -+ c->mtd = mtd; - -- list_for_each(this, &c->bad_list) { -- struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -- printk(KERN_DEBUG "bad_list: %08x\n", jeb->offset); -- } -- } -- if (list_empty(&c->bad_used_list)) { -- printk(KERN_DEBUG "bad_used_list: empty\n"); -- } else { -- struct list_head *this; -+ sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c); -+ -+ if (IS_ERR(sb)) -+ goto out_put; - -- list_for_each(this, &c->bad_used_list) { -- struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -- printk(KERN_DEBUG "bad_used_list: %08x\n", jeb->offset); -+ if (sb->s_root) { -+ /* New mountpoint for JFFS2 which is already mounted */ -+ D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n", -+ mtd->index, mtd->name)); -+ goto out_put; - } -+ -+ D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): New superblock for device %d (\"%s\")\n", -+ mtd->index, mtd->name)); -+ -+ sb->s_op = &jffs2_super_operations; -+ -+ ret = jffs2_do_fill_super(sb, data, (flags&MS_VERBOSE)?1:0); -+ -+ if (ret) { -+ /* Failure case... */ -+ up_write(&sb->s_umount); -+ deactivate_super(sb); -+ return ERR_PTR(ret); - } --#endif /* CONFIG_JFFS2_FS_DEBUG */ - -- spin_unlock_bh(&c->erase_completion_lock); -+ sb->s_flags |= MS_ACTIVE; -+ return sb; - -+ out_put: -+ kfree(c); -+ put_mtd_device(mtd); - -- return 0; -+ return sb; - } - --static struct super_block *jffs2_read_super(struct super_block *sb, void *data, int silent) -+static struct super_block *jffs2_get_sb_mtdnr(struct file_system_type *fs_type, -+ int flags, const char *dev_name, -+ void *data, int mtdnr) - { -- struct jffs2_sb_info *c; -- struct inode *root_i; -- int i; -- -- D1(printk(KERN_DEBUG "jffs2: read_super for device %s\n", kdevname(sb->s_dev))); -+ struct mtd_info *mtd; - -- if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) { -- if (!silent) -- printk(KERN_DEBUG "jffs2: attempt to mount non-MTD device %s\n", kdevname(sb->s_dev)); -- return NULL; -+ mtd = get_mtd_device(NULL, mtdnr); -+ if (!mtd) { -+ D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr)); -+ return ERR_PTR(-EINVAL); - } - -- c = JFFS2_SB_INFO(sb); -- memset(c, 0, sizeof(*c)); -+ return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); -+} - -- c->mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); -- if (!c->mtd) { -- D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", MINOR(sb->s_dev))); -- return NULL; -+static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, -+ int flags, const char *dev_name, -+ void *data) -+{ -+ int err; -+ struct nameidata nd; -+ int mtdnr; -+ -+ if (!dev_name) -+ return ERR_PTR(-EINVAL); -+ -+ D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name)); -+ -+ /* The preferred way of mounting in future; especially when -+ CONFIG_BLK_DEV is implemented - we specify the underlying -+ MTD device by number or by name, so that we don't require -+ block device support to be present in the kernel. */ -+ -+ /* FIXME: How to do the root fs this way? */ -+ -+ if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') { -+ /* Probably mounting without the blkdev crap */ -+ if (dev_name[3] == ':') { -+ struct mtd_info *mtd; -+ -+ /* Mount by MTD device name */ -+ D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4)); -+ for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) { -+ mtd = get_mtd_device(NULL, mtdnr); -+ if (mtd) { -+ if (!strcmp(mtd->name, dev_name+4)) -+ return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); -+ put_mtd_device(mtd); - } -- c->sector_size = c->mtd->erasesize; -- c->free_size = c->flash_size = c->mtd->size; -- c->nr_blocks = c->mtd->size / c->mtd->erasesize; -- c->blocks = kmalloc(sizeof(struct jffs2_eraseblock) * c->nr_blocks, GFP_KERNEL); -- if (!c->blocks) -- goto out_mtd; -- for (i=0; inr_blocks; i++) { -- INIT_LIST_HEAD(&c->blocks[i].list); -- c->blocks[i].offset = i * c->sector_size; -- c->blocks[i].free_size = c->sector_size; -- c->blocks[i].dirty_size = 0; -- c->blocks[i].used_size = 0; -- c->blocks[i].first_node = NULL; -- c->blocks[i].last_node = NULL; -- } -- -- spin_lock_init(&c->nodelist_lock); -- init_MUTEX(&c->alloc_sem); -- init_waitqueue_head(&c->erase_wait); -- spin_lock_init(&c->erase_completion_lock); -- spin_lock_init(&c->inocache_lock); -- -- INIT_LIST_HEAD(&c->clean_list); -- INIT_LIST_HEAD(&c->dirty_list); -- INIT_LIST_HEAD(&c->erasing_list); -- INIT_LIST_HEAD(&c->erase_pending_list); -- INIT_LIST_HEAD(&c->erase_complete_list); -- INIT_LIST_HEAD(&c->free_list); -- INIT_LIST_HEAD(&c->bad_list); -- INIT_LIST_HEAD(&c->bad_used_list); -- c->highest_ino = 1; -- -- if (jffs2_build_filesystem(c)) { -- D1(printk(KERN_DEBUG "build_fs failed\n")); -- goto out_nodes; - } -+ printk(KERN_NOTICE "jffs2_get_sb(): MTD device with name \"%s\" not found.\n", dev_name+4); -+ } else if (isdigit(dev_name[3])) { -+ /* Mount by MTD device number name */ -+ char *endptr; - -- sb->s_op = &jffs2_super_operations; -+ mtdnr = simple_strtoul(dev_name+3, &endptr, 0); -+ if (!*endptr) { -+ /* It was a valid number */ -+ D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr)); -+ return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); -+ } -+ } -+ } - -- D1(printk(KERN_DEBUG "jffs2_read_super(): Getting root inode\n")); -- root_i = iget(sb, 1); -- if (is_bad_inode(root_i)) { -- D1(printk(KERN_WARNING "get root inode failed\n")); -- goto out_nodes; -+ /* Try the old way - the hack where we allowed users to mount -+ /dev/mtdblock$(n) but didn't actually _use_ the blkdev */ -+ -+ err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); -+ -+ D1(printk(KERN_DEBUG "jffs2_get_sb(): path_lookup() returned %d, inode %p\n", -+ err, nd.dentry->d_inode)); -+ -+ if (err) -+ return ERR_PTR(err); -+ -+ err = -EINVAL; -+ -+ if (!S_ISBLK(nd.dentry->d_inode->i_mode)) -+ goto out; -+ -+ if (nd.mnt->mnt_flags & MNT_NODEV) { -+ err = -EACCES; -+ goto out; - } - -- D1(printk(KERN_DEBUG "jffs2_read_super(): d_alloc_root()\n")); -- sb->s_root = d_alloc_root(root_i); -- if (!sb->s_root) -- goto out_root_i; -+ if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) { -+ if (!(flags & MS_VERBOSE)) /* Yes I mean this. Strangely */ -+ printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n", -+ dev_name); -+ goto out; -+ } - --#if LINUX_VERSION_CODE >= 0x20403 -- sb->s_maxbytes = 0xFFFFFFFF; --#endif -- sb->s_blocksize = PAGE_CACHE_SIZE; -- sb->s_blocksize_bits = PAGE_CACHE_SHIFT; -- sb->s_magic = JFFS2_SUPER_MAGIC; -- if (!(sb->s_flags & MS_RDONLY)) -- jffs2_start_garbage_collect_thread(c); -- return sb; -+ mtdnr = iminor(nd.dentry->d_inode); -+ path_release(&nd); - -- out_root_i: -- iput(root_i); -- out_nodes: -- jffs2_free_ino_caches(c); -- jffs2_free_raw_node_refs(c); -- kfree(c->blocks); -- out_mtd: -- put_mtd_device(c->mtd); -- return NULL; -+ return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); -+ -+out: -+ path_release(&nd); -+ return ERR_PTR(err); - } - --void jffs2_put_super (struct super_block *sb) -+static void jffs2_put_super (struct super_block *sb) - { - struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); - -@@ -293,74 +259,53 @@ - - if (!(sb->s_flags & MS_RDONLY)) - jffs2_stop_garbage_collect_thread(c); -+ down(&c->alloc_sem); -+ jffs2_flush_wbuf_pad(c); -+ up(&c->alloc_sem); - jffs2_free_ino_caches(c); - jffs2_free_raw_node_refs(c); - kfree(c->blocks); -+ jffs2_nand_flash_cleanup(c); -+ kfree(c->inocache_list); - if (c->mtd->sync) - c->mtd->sync(c->mtd); -- put_mtd_device(c->mtd); - - D1(printk(KERN_DEBUG "jffs2_put_super returning\n")); - } - --int jffs2_remount_fs (struct super_block *sb, int *flags, char *data) -+static void jffs2_kill_sb(struct super_block *sb) - { - struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); -- -- if (c->flags & JFFS2_SB_FLAG_RO && !(sb->s_flags & MS_RDONLY)) -- return -EROFS; -- -- /* We stop if it was running, then restart if it needs to. -- This also catches the case where it was stopped and this -- is just a remount to restart it */ -- if (!(sb->s_flags & MS_RDONLY)) -- jffs2_stop_garbage_collect_thread(c); -- -- if (!(*flags & MS_RDONLY)) -- jffs2_start_garbage_collect_thread(c); -- -- sb->s_flags = (sb->s_flags & ~MS_RDONLY)|(*flags & MS_RDONLY); -- -- return 0; --} -- --void jffs2_write_super (struct super_block *sb) --{ -- struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); -- sb->s_dirt = 0; -- -- if (sb->s_flags & MS_RDONLY) -- return; -- -- jffs2_garbage_collect_trigger(c); -- jffs2_erase_pending_blocks(c); -- jffs2_mark_erased_blocks(c); -+ generic_shutdown_super(sb); -+ put_mtd_device(c->mtd); -+ kfree(c); - } - -- --static DECLARE_FSTYPE_DEV(jffs2_fs_type, "jffs2", jffs2_read_super); -+static struct file_system_type jffs2_fs_type = { -+ .owner = THIS_MODULE, -+ .name = "jffs2", -+ .get_sb = jffs2_get_sb, -+ .kill_sb = jffs2_kill_sb, -+}; - - static int __init init_jffs2_fs(void) - { - int ret; - -- printk(KERN_NOTICE "JFFS2 version 2.1. (C) 2001 Red Hat, Inc., designed by Axis Communications AB.\n"); -- --#ifdef JFFS2_OUT_OF_KERNEL -- /* sanity checks. Could we do these at compile time? */ -- if (sizeof(struct jffs2_sb_info) > sizeof (((struct super_block *)NULL)->u)) { -- printk(KERN_ERR "JFFS2 error: struct jffs2_sb_info (%d bytes) doesn't fit in the super_block union (%d bytes)\n", -- sizeof(struct jffs2_sb_info), sizeof (((struct super_block *)NULL)->u)); -- return -EIO; -- } -- -- if (sizeof(struct jffs2_inode_info) > sizeof (((struct inode *)NULL)->u)) { -- printk(KERN_ERR "JFFS2 error: struct jffs2_inode_info (%d bytes) doesn't fit in the inode union (%d bytes)\n", -- sizeof(struct jffs2_inode_info), sizeof (((struct inode *)NULL)->u)); -- return -EIO; -- } -+ printk(KERN_INFO "JFFS2 version 2.2." -+#ifdef CONFIG_FS_JFFS2_NAND -+ " (NAND)" - #endif -+ " (C) 2001-2003 Red Hat, Inc.\n"); - -+ jffs2_inode_cachep = kmem_cache_create("jffs2_i", -+ sizeof(struct jffs2_inode_info), -+ 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, -+ jffs2_i_init_once, NULL); -+ if (!jffs2_inode_cachep) { -+ printk(KERN_ERR "JFFS2 error: Failed to initialise inode cache\n"); -+ return -ENOMEM; -+ } - ret = jffs2_zlib_init(); - if (ret) { - printk(KERN_ERR "JFFS2 error: Failed to initialise zlib workspaces\n"); -@@ -388,9 +333,10 @@ - - static void __exit exit_jffs2_fs(void) - { -+ unregister_filesystem(&jffs2_fs_type); - jffs2_destroy_slab_caches(); - jffs2_zlib_exit(); -- unregister_filesystem(&jffs2_fs_type); -+ kmem_cache_destroy(jffs2_inode_cachep); - } - - module_init(init_jffs2_fs); -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/symlink.c linux/fs/jffs2/symlink.c ---- linux-mips-2.4.24-pre2/fs/jffs2/symlink.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/symlink.c 2004-11-17 18:17:59.000000000 +0100 -@@ -3,35 +3,11 @@ - * - * Copyright (C) 2001, 2002 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - -@@ -39,7 +15,6 @@ - #include - #include - #include --#include - #include "nodelist.h" - - int jffs2_readlink(struct dentry *dentry, char *buffer, int buflen); -@@ -47,45 +22,17 @@ - - struct inode_operations jffs2_symlink_inode_operations = - { -- readlink: jffs2_readlink, -- follow_link: jffs2_follow_link, -- setattr: jffs2_setattr -+ .readlink = jffs2_readlink, -+ .follow_link = jffs2_follow_link, -+ .setattr = jffs2_setattr - }; - --static char *jffs2_getlink(struct dentry *dentry) --{ -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); -- char *buf; -- int ret; -- -- down(&f->sem); -- if (!f->metadata) { -- up(&f->sem); -- printk(KERN_NOTICE "No metadata for symlink inode #%lu\n", dentry->d_inode->i_ino); -- return ERR_PTR(-EINVAL); -- } -- buf = kmalloc(f->metadata->size+1, GFP_USER); -- if (!buf) { -- up(&f->sem); -- return ERR_PTR(-ENOMEM); -- } -- buf[f->metadata->size]=0; -- -- ret = jffs2_read_dnode(JFFS2_SB_INFO(dentry->d_inode->i_sb), f->metadata, buf, 0, f->metadata->size); -- up(&f->sem); -- if (ret) { -- kfree(buf); -- return ERR_PTR(ret); -- } -- return buf; -- --} - int jffs2_readlink(struct dentry *dentry, char *buffer, int buflen) - { - unsigned char *kbuf; - int ret; - -- kbuf = jffs2_getlink(dentry); -+ kbuf = jffs2_getlink(JFFS2_SB_INFO(dentry->d_inode->i_sb), JFFS2_INODE_INFO(dentry->d_inode)); - if (IS_ERR(kbuf)) - return PTR_ERR(kbuf); - -@@ -99,7 +46,7 @@ - unsigned char *buf; - int ret; - -- buf = jffs2_getlink(dentry); -+ buf = jffs2_getlink(JFFS2_SB_INFO(dentry->d_inode->i_sb), JFFS2_INODE_INFO(dentry->d_inode)); - - if (IS_ERR(buf)) - return PTR_ERR(buf); -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/wbuf.c linux/fs/jffs2/wbuf.c ---- linux-mips-2.4.24-pre2/fs/jffs2/wbuf.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/wbuf.c 2004-11-17 18:17:59.409257680 +0100 -@@ -0,0 +1,1156 @@ -+/* -+ * JFFS2 -- Journalling Flash File System, Version 2. -+ * -+ * Copyright (C) 2001-2003 Red Hat, Inc. -+ * -+ * Created by David Woodhouse -+ * -+ * For licensing information, see the file 'LICENCE' in this directory. -+ * -+ * $Id$ -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "nodelist.h" -+ -+/* For testing write failures */ -+#undef BREAKME -+#undef BREAKMEHEADER -+ -+#ifdef BREAKME -+static unsigned char *brokenbuf; -+#endif -+ -+/* max. erase failures before we mark a block bad */ -+#define MAX_ERASE_FAILURES 5 -+ -+/* two seconds timeout for timed wbuf-flushing */ -+#define WBUF_FLUSH_TIMEOUT 2 * HZ -+ -+struct jffs2_inodirty { -+ uint32_t ino; -+ struct jffs2_inodirty *next; -+}; -+ -+static struct jffs2_inodirty inodirty_nomem; -+ -+static int jffs2_wbuf_pending_for_ino(struct jffs2_sb_info *c, uint32_t ino) -+{ -+ struct jffs2_inodirty *this = c->wbuf_inodes; -+ -+ /* If a malloc failed, consider _everything_ dirty */ -+ if (this == &inodirty_nomem) -+ return 1; -+ -+ /* If ino == 0, _any_ non-GC writes mean 'yes' */ -+ if (this && !ino) -+ return 1; -+ -+ /* Look to see if the inode in question is pending in the wbuf */ -+ while (this) { -+ if (this->ino == ino) -+ return 1; -+ this = this->next; -+ } -+ return 0; -+} -+ -+static void jffs2_clear_wbuf_ino_list(struct jffs2_sb_info *c) -+{ -+ struct jffs2_inodirty *this; -+ -+ this = c->wbuf_inodes; -+ -+ if (this != &inodirty_nomem) { -+ while (this) { -+ struct jffs2_inodirty *next = this->next; -+ kfree(this); -+ this = next; -+ } -+ } -+ c->wbuf_inodes = NULL; -+} -+ -+static void jffs2_wbuf_dirties_inode(struct jffs2_sb_info *c, uint32_t ino) -+{ -+ struct jffs2_inodirty *new; -+ -+ /* Mark the superblock dirty so that kupdated will flush... */ -+ OFNI_BS_2SFFJ(c)->s_dirt = 1; -+ -+ if (jffs2_wbuf_pending_for_ino(c, ino)) -+ return; -+ -+ new = kmalloc(sizeof(*new), GFP_KERNEL); -+ if (!new) { -+ D1(printk(KERN_DEBUG "No memory to allocate inodirty. Fallback to all considered dirty\n")); -+ jffs2_clear_wbuf_ino_list(c); -+ c->wbuf_inodes = &inodirty_nomem; -+ return; -+ } -+ new->ino = ino; -+ new->next = c->wbuf_inodes; -+ c->wbuf_inodes = new; -+ return; -+} -+ -+static inline void jffs2_refile_wbuf_blocks(struct jffs2_sb_info *c) -+{ -+ struct list_head *this, *next; -+ static int n; -+ -+ if (list_empty(&c->erasable_pending_wbuf_list)) -+ return; -+ -+ list_for_each_safe(this, next, &c->erasable_pending_wbuf_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ -+ D1(printk(KERN_DEBUG "Removing eraseblock at 0x%08x from erasable_pending_wbuf_list...\n", jeb->offset)); -+ list_del(this); -+ if ((jiffies + (n++)) & 127) { -+ /* Most of the time, we just erase it immediately. Otherwise we -+ spend ages scanning it on mount, etc. */ -+ D1(printk(KERN_DEBUG "...and adding to erase_pending_list\n")); -+ list_add_tail(&jeb->list, &c->erase_pending_list); -+ c->nr_erasing_blocks++; -+ jffs2_erase_pending_trigger(c); -+ } else { -+ /* Sometimes, however, we leave it elsewhere so it doesn't get -+ immediately reused, and we spread the load a bit. */ -+ D1(printk(KERN_DEBUG "...and adding to erasable_list\n")); -+ list_add_tail(&jeb->list, &c->erasable_list); -+ } -+ } -+} -+ -+/* Recover from failure to write wbuf. Recover the nodes up to the -+ * wbuf, not the one which we were starting to try to write. */ -+ -+static void jffs2_wbuf_recover(struct jffs2_sb_info *c) -+{ -+ struct jffs2_eraseblock *jeb, *new_jeb; -+ struct jffs2_raw_node_ref **first_raw, **raw; -+ size_t retlen; -+ int ret; -+ unsigned char *buf; -+ uint32_t start, end, ofs, len; -+ -+ spin_lock(&c->erase_completion_lock); -+ -+ jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; -+ -+ D1(printk("About to refile bad block at %08x\n", jeb->offset)); -+ -+ D2(jffs2_dump_block_lists(c)); -+ /* File the existing block on the bad_used_list.... */ -+ if (c->nextblock == jeb) -+ c->nextblock = NULL; -+ else /* Not sure this should ever happen... need more coffee */ -+ list_del(&jeb->list); -+ if (jeb->first_node) { -+ D1(printk("Refiling block at %08x to bad_used_list\n", jeb->offset)); -+ list_add(&jeb->list, &c->bad_used_list); -+ } else { -+ BUG(); -+ /* It has to have had some nodes or we couldn't be here */ -+ D1(printk("Refiling block at %08x to erase_pending_list\n", jeb->offset)); -+ list_add(&jeb->list, &c->erase_pending_list); -+ c->nr_erasing_blocks++; -+ jffs2_erase_pending_trigger(c); -+ } -+ D2(jffs2_dump_block_lists(c)); -+ -+ /* Adjust its size counts accordingly */ -+ c->wasted_size += jeb->free_size; -+ c->free_size -= jeb->free_size; -+ jeb->wasted_size += jeb->free_size; -+ jeb->free_size = 0; -+ -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ /* Find the first node to be recovered, by skipping over every -+ node which ends before the wbuf starts, or which is obsolete. */ -+ first_raw = &jeb->first_node; -+ while (*first_raw && -+ (ref_obsolete(*first_raw) || -+ (ref_offset(*first_raw)+ref_totlen(c, jeb, *first_raw)) < c->wbuf_ofs)) { -+ D1(printk(KERN_DEBUG "Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n", -+ ref_offset(*first_raw), ref_flags(*first_raw), -+ (ref_offset(*first_raw) + ref_totlen(c, jeb, *first_raw)), -+ c->wbuf_ofs)); -+ first_raw = &(*first_raw)->next_phys; -+ } -+ -+ if (!*first_raw) { -+ /* All nodes were obsolete. Nothing to recover. */ -+ D1(printk(KERN_DEBUG "No non-obsolete nodes to be recovered. Just filing block bad\n")); -+ spin_unlock(&c->erase_completion_lock); -+ return; -+ } -+ -+ start = ref_offset(*first_raw); -+ end = ref_offset(*first_raw) + ref_totlen(c, jeb, *first_raw); -+ -+ /* Find the last node to be recovered */ -+ raw = first_raw; -+ while ((*raw)) { -+ if (!ref_obsolete(*raw)) -+ end = ref_offset(*raw) + ref_totlen(c, jeb, *raw); -+ -+ raw = &(*raw)->next_phys; -+ } -+ spin_unlock(&c->erase_completion_lock); -+ -+ D1(printk(KERN_DEBUG "wbuf recover %08x-%08x\n", start, end)); -+ -+ buf = NULL; -+ if (start < c->wbuf_ofs) { -+ /* First affected node was already partially written. -+ * Attempt to reread the old data into our buffer. */ -+ -+ buf = kmalloc(end - start, GFP_KERNEL); -+ if (!buf) { -+ printk(KERN_CRIT "Malloc failure in wbuf recovery. Data loss ensues.\n"); -+ -+ goto read_failed; -+ } -+ -+ /* Do the read... */ -+ ret = c->mtd->read_ecc(c->mtd, start, c->wbuf_ofs - start, &retlen, buf, NULL, c->oobinfo); -+ if (ret == -EIO && retlen == c->wbuf_ofs - start) { -+ /* ECC recovered */ -+ ret = 0; -+ } -+ if (ret || retlen != c->wbuf_ofs - start) { -+ printk(KERN_CRIT "Old data are already lost in wbuf recovery. Data loss ensues.\n"); -+ -+ kfree(buf); -+ buf = NULL; -+ read_failed: -+ first_raw = &(*first_raw)->next_phys; -+ /* If this was the only node to be recovered, give up */ -+ if (!(*first_raw)) -+ return; -+ -+ /* It wasn't. Go on and try to recover nodes complete in the wbuf */ -+ start = ref_offset(*first_raw); -+ } else { -+ /* Read succeeded. Copy the remaining data from the wbuf */ -+ memcpy(buf + (c->wbuf_ofs - start), c->wbuf, end - c->wbuf_ofs); -+ } -+ } -+ /* OK... we're to rewrite (end-start) bytes of data from first_raw onwards. -+ Either 'buf' contains the data, or we find it in the wbuf */ -+ -+ -+ /* ... and get an allocation of space from a shiny new block instead */ -+ ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len); -+ if (ret) { -+ printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n"); -+ if (buf) -+ kfree(buf); -+ return; -+ } -+ if (end-start >= c->wbuf_pagesize) { -+ /* Need to do another write immediately. This, btw, -+ means that we'll be writing from 'buf' and not from -+ the wbuf. Since if we're writing from the wbuf there -+ won't be more than a wbuf full of data, now will -+ there? :) */ -+ -+ uint32_t towrite = (end-start) - ((end-start)%c->wbuf_pagesize); -+ -+ D1(printk(KERN_DEBUG "Write 0x%x bytes at 0x%08x in wbuf recover\n", -+ towrite, ofs)); -+ -+#ifdef BREAKMEHEADER -+ static int breakme; -+ if (breakme++ == 20) { -+ printk(KERN_NOTICE "Faking write error at 0x%08x\n", ofs); -+ breakme = 0; -+ c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen, -+ brokenbuf, NULL, c->oobinfo); -+ ret = -EIO; -+ } else -+#endif -+ ret = c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen, -+ buf, NULL, c->oobinfo); -+ -+ if (ret || retlen != towrite) { -+ /* Argh. We tried. Really we did. */ -+ printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n"); -+ kfree(buf); -+ -+ if (retlen) { -+ struct jffs2_raw_node_ref *raw2; -+ -+ raw2 = jffs2_alloc_raw_node_ref(); -+ if (!raw2) -+ return; -+ -+ raw2->flash_offset = ofs | REF_OBSOLETE; -+ raw2->__totlen = ref_totlen(c, jeb, *first_raw); -+ raw2->next_phys = NULL; -+ raw2->next_in_ino = NULL; -+ -+ jffs2_add_physical_node_ref(c, raw2); -+ } -+ return; -+ } -+ printk(KERN_NOTICE "Recovery of wbuf succeeded to %08x\n", ofs); -+ -+ c->wbuf_len = (end - start) - towrite; -+ c->wbuf_ofs = ofs + towrite; -+ memcpy(c->wbuf, buf + towrite, c->wbuf_len); -+ /* Don't muck about with c->wbuf_inodes. False positives are harmless. */ -+ -+ kfree(buf); -+ } else { -+ /* OK, now we're left with the dregs in whichever buffer we're using */ -+ if (buf) { -+ memcpy(c->wbuf, buf, end-start); -+ kfree(buf); -+ } else { -+ memmove(c->wbuf, c->wbuf + (start - c->wbuf_ofs), end - start); -+ } -+ c->wbuf_ofs = ofs; -+ c->wbuf_len = end - start; -+ } -+ -+ /* Now sort out the jffs2_raw_node_refs, moving them from the old to the next block */ -+ new_jeb = &c->blocks[ofs / c->sector_size]; -+ -+ spin_lock(&c->erase_completion_lock); -+ if (new_jeb->first_node) { -+ /* Odd, but possible with ST flash later maybe */ -+ new_jeb->last_node->next_phys = *first_raw; -+ } else { -+ new_jeb->first_node = *first_raw; -+ } -+ -+ raw = first_raw; -+ while (*raw) { -+ uint32_t rawlen = ref_totlen(c, jeb, *raw); -+ -+ D1(printk(KERN_DEBUG "Refiling block of %08x at %08x(%d) to %08x\n", -+ rawlen, ref_offset(*raw), ref_flags(*raw), ofs)); -+ -+ if (ref_obsolete(*raw)) { -+ /* Shouldn't really happen much */ -+ new_jeb->dirty_size += rawlen; -+ new_jeb->free_size -= rawlen; -+ c->dirty_size += rawlen; -+ } else { -+ new_jeb->used_size += rawlen; -+ new_jeb->free_size -= rawlen; -+ jeb->dirty_size += rawlen; -+ jeb->used_size -= rawlen; -+ c->dirty_size += rawlen; -+ } -+ c->free_size -= rawlen; -+ (*raw)->flash_offset = ofs | ref_flags(*raw); -+ ofs += rawlen; -+ new_jeb->last_node = *raw; -+ -+ raw = &(*raw)->next_phys; -+ } -+ -+ /* Fix up the original jeb now it's on the bad_list */ -+ *first_raw = NULL; -+ if (first_raw == &jeb->first_node) { -+ jeb->last_node = NULL; -+ D1(printk(KERN_DEBUG "Failing block at %08x is now empty. Moving to erase_pending_list\n", jeb->offset)); -+ list_del(&jeb->list); -+ list_add(&jeb->list, &c->erase_pending_list); -+ c->nr_erasing_blocks++; -+ jffs2_erase_pending_trigger(c); -+ } -+ else -+ jeb->last_node = container_of(first_raw, struct jffs2_raw_node_ref, next_phys); -+ -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ ACCT_SANITY_CHECK(c,new_jeb); -+ D1(ACCT_PARANOIA_CHECK(new_jeb)); -+ -+ spin_unlock(&c->erase_completion_lock); -+ -+ D1(printk(KERN_DEBUG "wbuf recovery completed OK\n")); -+} -+ -+/* Meaning of pad argument: -+ 0: Do not pad. Probably pointless - we only ever use this when we can't pad anyway. -+ 1: Pad, do not adjust nextblock free_size -+ 2: Pad, adjust nextblock free_size -+*/ -+static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) -+{ -+ int ret; -+ size_t retlen; -+ -+ /* Nothing to do if not NAND flash. In particular, we shouldn't -+ del_timer() the timer we never initialised. */ -+ if (jffs2_can_mark_obsolete(c)) -+ return 0; -+ -+ if (!down_trylock(&c->alloc_sem)) { -+ up(&c->alloc_sem); -+ printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n"); -+ BUG(); -+ } -+ -+ if(!c->wbuf || !c->wbuf_len) -+ return 0; -+ -+ /* claim remaining space on the page -+ this happens, if we have a change to a new block, -+ or if fsync forces us to flush the writebuffer. -+ if we have a switch to next page, we will not have -+ enough remaining space for this. -+ */ -+ if (pad) { -+ c->wbuf_len = PAD(c->wbuf_len); -+ -+ if ( c->wbuf_len + sizeof(struct jffs2_unknown_node) < c->wbuf_pagesize) { -+ struct jffs2_unknown_node *padnode = (void *)(c->wbuf + c->wbuf_len); -+ padnode->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ padnode->nodetype = cpu_to_je16(JFFS2_NODETYPE_PADDING); -+ padnode->totlen = cpu_to_je32(c->wbuf_pagesize - c->wbuf_len); -+ padnode->hdr_crc = cpu_to_je32(crc32(0, padnode, sizeof(*padnode)-4)); -+ } -+ } -+ /* else jffs2_flash_writev has actually filled in the rest of the -+ buffer for us, and will deal with the node refs etc. later. */ -+ -+#ifdef BREAKME -+ static int breakme; -+ if (breakme++ == 20) { -+ printk(KERN_NOTICE "Faking write error at 0x%08x\n", c->wbuf_ofs); -+ breakme = 0; -+ c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, -+ &retlen, brokenbuf, NULL, c->oobinfo); -+ ret = -EIO; -+ } else -+#endif -+ ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo); -+ -+ -+ if (ret || retlen != c->wbuf_pagesize) { -+ if (ret) -+ printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n",ret); -+ else { -+ printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n", -+ retlen, c->wbuf_pagesize); -+ ret = -EIO; -+ } -+ -+ jffs2_wbuf_recover(c); -+ -+ return ret; -+ } -+ -+ /* Adjusting free size of next block only, if it's called from fsync ! */ -+ if (pad == 2) { -+ D1(printk(KERN_DEBUG "jffs2_flush_wbuf() adjusting free_size of c->nextblock\n")); -+ spin_lock(&c->erase_completion_lock); -+ if (!c->nextblock) -+ BUG(); -+ /* wbuf_pagesize - wbuf_len is the amount of space that's to be -+ padded. If there is less free space in the block than that, -+ something screwed up */ -+ if (c->nextblock->free_size < (c->wbuf_pagesize - c->wbuf_len)) { -+ printk(KERN_CRIT "jffs2_flush_wbuf(): Accounting error. wbuf at 0x%08x has 0x%03x bytes, 0x%03x left.\n", -+ c->wbuf_ofs, c->wbuf_len, c->wbuf_pagesize-c->wbuf_len); -+ printk(KERN_CRIT "jffs2_flush_wbuf(): But free_size for block at 0x%08x is only 0x%08x\n", -+ c->nextblock->offset, c->nextblock->free_size); -+ BUG(); -+ } -+ c->nextblock->free_size -= (c->wbuf_pagesize - c->wbuf_len); -+ c->free_size -= (c->wbuf_pagesize - c->wbuf_len); -+ c->nextblock->wasted_size += (c->wbuf_pagesize - c->wbuf_len); -+ c->wasted_size += (c->wbuf_pagesize - c->wbuf_len); -+ spin_unlock(&c->erase_completion_lock); -+ } -+ -+ /* Stick any now-obsoleted blocks on the erase_pending_list */ -+ spin_lock(&c->erase_completion_lock); -+ jffs2_refile_wbuf_blocks(c); -+ jffs2_clear_wbuf_ino_list(c); -+ spin_unlock(&c->erase_completion_lock); -+ -+ memset(c->wbuf,0xff,c->wbuf_pagesize); -+ /* adjust write buffer offset, else we get a non contiguous write bug */ -+ c->wbuf_ofs += c->wbuf_pagesize; -+ c->wbuf_len = 0; -+ return 0; -+} -+ -+/* Trigger garbage collection to flush the write-buffer. -+ If ino arg is zero, do it if _any_ real (i.e. not GC) writes are -+ outstanding. If ino arg non-zero, do it only if a write for the -+ given inode is outstanding. */ -+int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino) -+{ -+ uint32_t old_wbuf_ofs; -+ uint32_t old_wbuf_len; -+ int ret = 0; -+ -+ D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() called for ino #%u...\n", ino)); -+ -+ down(&c->alloc_sem); -+ if (!jffs2_wbuf_pending_for_ino(c, ino)) { -+ D1(printk(KERN_DEBUG "Ino #%d not pending in wbuf. Returning\n", ino)); -+ up(&c->alloc_sem); -+ return 0; -+ } -+ -+ old_wbuf_ofs = c->wbuf_ofs; -+ old_wbuf_len = c->wbuf_len; -+ -+ if (c->unchecked_size) { -+ /* GC won't make any progress for a while */ -+ D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() padding. Not finished checking\n")); -+ ret = __jffs2_flush_wbuf(c, 2); -+ } else while (old_wbuf_len && -+ old_wbuf_ofs == c->wbuf_ofs) { -+ -+ up(&c->alloc_sem); -+ -+ D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() calls gc pass\n")); -+ -+ ret = jffs2_garbage_collect_pass(c); -+ if (ret) { -+ /* GC failed. Flush it with padding instead */ -+ down(&c->alloc_sem); -+ ret = __jffs2_flush_wbuf(c, 2); -+ break; -+ } -+ down(&c->alloc_sem); -+ } -+ -+ D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() ends...\n")); -+ -+ up(&c->alloc_sem); -+ return ret; -+} -+ -+/* Pad write-buffer to end and write it, wasting space. */ -+int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c) -+{ -+ return __jffs2_flush_wbuf(c, 1); -+} -+ -+ -+#define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) ) -+#define PAGE_MOD(x) ( (x) & (c->wbuf_pagesize - 1) ) -+int jffs2_flash_writev(struct jffs2_sb_info *c, const struct iovec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino) -+{ -+ struct iovec outvecs[3]; -+ uint32_t totlen = 0; -+ uint32_t split_ofs = 0; -+ uint32_t old_totlen; -+ int ret, splitvec = -1; -+ int invec, outvec; -+ size_t wbuf_retlen; -+ unsigned char *wbuf_ptr; -+ size_t donelen = 0; -+ uint32_t outvec_to = to; -+ -+ /* If not NAND flash, don't bother */ -+ if (!c->wbuf) -+ return jffs2_flash_direct_writev(c, invecs, count, to, retlen); -+ -+ /* If wbuf_ofs is not initialized, set it to target address */ -+ if (c->wbuf_ofs == 0xFFFFFFFF) { -+ c->wbuf_ofs = PAGE_DIV(to); -+ c->wbuf_len = PAGE_MOD(to); -+ memset(c->wbuf,0xff,c->wbuf_pagesize); -+ } -+ -+ /* Sanity checks on target address. -+ It's permitted to write at PAD(c->wbuf_len+c->wbuf_ofs), -+ and it's permitted to write at the beginning of a new -+ erase block. Anything else, and you die. -+ New block starts at xxx000c (0-b = block header) -+ */ -+ if ( (to & ~(c->sector_size-1)) != (c->wbuf_ofs & ~(c->sector_size-1)) ) { -+ /* It's a write to a new block */ -+ if (c->wbuf_len) { -+ D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx causes flush of wbuf at 0x%08x\n", (unsigned long)to, c->wbuf_ofs)); -+ ret = jffs2_flush_wbuf_pad(c); -+ if (ret) { -+ /* the underlying layer has to check wbuf_len to do the cleanup */ -+ D1(printk(KERN_WARNING "jffs2_flush_wbuf() called from jffs2_flash_writev() failed %d\n", ret)); -+ *retlen = 0; -+ return ret; -+ } -+ } -+ /* set pointer to new block */ -+ c->wbuf_ofs = PAGE_DIV(to); -+ c->wbuf_len = PAGE_MOD(to); -+ } -+ -+ if (to != PAD(c->wbuf_ofs + c->wbuf_len)) { -+ /* We're not writing immediately after the writebuffer. Bad. */ -+ printk(KERN_CRIT "jffs2_flash_writev(): Non-contiguous write to %08lx\n", (unsigned long)to); -+ if (c->wbuf_len) -+ printk(KERN_CRIT "wbuf was previously %08x-%08x\n", -+ c->wbuf_ofs, c->wbuf_ofs+c->wbuf_len); -+ BUG(); -+ } -+ -+ /* Note outvecs[3] above. We know count is never greater than 2 */ -+ if (count > 2) { -+ printk(KERN_CRIT "jffs2_flash_writev(): count is %ld\n", count); -+ BUG(); -+ } -+ -+ invec = 0; -+ outvec = 0; -+ -+ -+ /* Fill writebuffer first, if already in use */ -+ if (c->wbuf_len) { -+ uint32_t invec_ofs = 0; -+ -+ /* adjust alignment offset */ -+ if (c->wbuf_len != PAGE_MOD(to)) { -+ c->wbuf_len = PAGE_MOD(to); -+ /* take care of alignment to next page */ -+ if (!c->wbuf_len) -+ c->wbuf_len = c->wbuf_pagesize; -+ } -+ -+ while(c->wbuf_len < c->wbuf_pagesize) { -+ uint32_t thislen; -+ -+ if (invec == count) -+ goto alldone; -+ -+ thislen = c->wbuf_pagesize - c->wbuf_len; -+ -+ if (thislen >= invecs[invec].iov_len) -+ thislen = invecs[invec].iov_len; -+ -+ invec_ofs = thislen; -+ -+ memcpy(c->wbuf + c->wbuf_len, invecs[invec].iov_base, thislen); -+ c->wbuf_len += thislen; -+ donelen += thislen; -+ /* Get next invec, if actual did not fill the buffer */ -+ if (c->wbuf_len < c->wbuf_pagesize) -+ invec++; -+ } -+ -+ /* write buffer is full, flush buffer */ -+ ret = __jffs2_flush_wbuf(c, 0); -+ if (ret) { -+ /* the underlying layer has to check wbuf_len to do the cleanup */ -+ D1(printk(KERN_WARNING "jffs2_flush_wbuf() called from jffs2_flash_writev() failed %d\n", ret)); -+ /* Retlen zero to make sure our caller doesn't mark the space dirty. -+ We've already done everything that's necessary */ -+ *retlen = 0; -+ return ret; -+ } -+ outvec_to += donelen; -+ c->wbuf_ofs = outvec_to; -+ -+ /* All invecs done ? */ -+ if (invec == count) -+ goto alldone; -+ -+ /* Set up the first outvec, containing the remainder of the -+ invec we partially used */ -+ if (invecs[invec].iov_len > invec_ofs) { -+ outvecs[0].iov_base = invecs[invec].iov_base+invec_ofs; -+ totlen = outvecs[0].iov_len = invecs[invec].iov_len-invec_ofs; -+ if (totlen > c->wbuf_pagesize) { -+ splitvec = outvec; -+ split_ofs = outvecs[0].iov_len - PAGE_MOD(totlen); -+ } -+ outvec++; -+ } -+ invec++; -+ } -+ -+ /* OK, now we've flushed the wbuf and the start of the bits -+ we have been asked to write, now to write the rest.... */ -+ -+ /* totlen holds the amount of data still to be written */ -+ old_totlen = totlen; -+ for ( ; invec < count; invec++,outvec++ ) { -+ outvecs[outvec].iov_base = invecs[invec].iov_base; -+ totlen += outvecs[outvec].iov_len = invecs[invec].iov_len; -+ if (PAGE_DIV(totlen) != PAGE_DIV(old_totlen)) { -+ splitvec = outvec; -+ split_ofs = outvecs[outvec].iov_len - PAGE_MOD(totlen); -+ old_totlen = totlen; -+ } -+ } -+ -+ /* Now the outvecs array holds all the remaining data to write */ -+ /* Up to splitvec,split_ofs is to be written immediately. The rest -+ goes into the (now-empty) wbuf */ -+ -+ if (splitvec != -1) { -+ uint32_t remainder; -+ int ret; -+ -+ remainder = outvecs[splitvec].iov_len - split_ofs; -+ outvecs[splitvec].iov_len = split_ofs; -+ -+ /* We did cross a page boundary, so we write some now */ -+ ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo); -+ if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) { -+ /* At this point we have no problem, -+ c->wbuf is empty. -+ */ -+ *retlen = donelen; -+ return ret; -+ } -+ -+ donelen += wbuf_retlen; -+ c->wbuf_ofs = PAGE_DIV(outvec_to) + PAGE_DIV(totlen); -+ -+ if (remainder) { -+ outvecs[splitvec].iov_base += split_ofs; -+ outvecs[splitvec].iov_len = remainder; -+ } else { -+ splitvec++; -+ } -+ -+ } else { -+ splitvec = 0; -+ } -+ -+ /* Now splitvec points to the start of the bits we have to copy -+ into the wbuf */ -+ wbuf_ptr = c->wbuf; -+ -+ for ( ; splitvec < outvec; splitvec++) { -+ /* Don't copy the wbuf into itself */ -+ if (outvecs[splitvec].iov_base == c->wbuf) -+ continue; -+ memcpy(wbuf_ptr, outvecs[splitvec].iov_base, outvecs[splitvec].iov_len); -+ wbuf_ptr += outvecs[splitvec].iov_len; -+ donelen += outvecs[splitvec].iov_len; -+ } -+ c->wbuf_len = wbuf_ptr - c->wbuf; -+ -+ /* If there's a remainder in the wbuf and it's a non-GC write, -+ remember that the wbuf affects this ino */ -+alldone: -+ *retlen = donelen; -+ -+ if (c->wbuf_len && ino) -+ jffs2_wbuf_dirties_inode(c, ino); -+ -+ return 0; -+} -+ -+/* -+ * This is the entry for flash write. -+ * Check, if we work on NAND FLASH, if so build an iovec and write it via vritev -+*/ -+int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf) -+{ -+ struct iovec vecs[1]; -+ -+ if (jffs2_can_mark_obsolete(c)) -+ return c->mtd->write(c->mtd, ofs, len, retlen, buf); -+ -+ vecs[0].iov_base = (unsigned char *) buf; -+ vecs[0].iov_len = len; -+ return jffs2_flash_writev(c, vecs, 1, ofs, retlen, 0); -+} -+ -+/* -+ Handle readback from writebuffer and ECC failure return -+*/ -+int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, u_char *buf) -+{ -+ loff_t orbf = 0, owbf = 0, lwbf = 0; -+ int ret; -+ -+ /* Read flash */ -+ if (!jffs2_can_mark_obsolete(c)) { -+ ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo); -+ -+ if ( (ret == -EIO) && (*retlen == len) ) { -+ printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n", -+ len, ofs); -+ /* -+ * We have the raw data without ECC correction in the buffer, maybe -+ * we are lucky and all data or parts are correct. We check the node. -+ * If data are corrupted node check will sort it out. -+ * We keep this block, it will fail on write or erase and the we -+ * mark it bad. Or should we do that now? But we should give him a chance. -+ * Maybe we had a system crash or power loss before the ecc write or -+ * a erase was completed. -+ * So we return success. :) -+ */ -+ ret = 0; -+ } -+ } else -+ return c->mtd->read(c->mtd, ofs, len, retlen, buf); -+ -+ /* if no writebuffer available or write buffer empty, return */ -+ if (!c->wbuf_pagesize || !c->wbuf_len) -+ return ret; -+ -+ /* if we read in a different block, return */ -+ if ( (ofs & ~(c->sector_size-1)) != (c->wbuf_ofs & ~(c->sector_size-1)) ) -+ return ret; -+ -+ if (ofs >= c->wbuf_ofs) { -+ owbf = (ofs - c->wbuf_ofs); /* offset in write buffer */ -+ if (owbf > c->wbuf_len) /* is read beyond write buffer ? */ -+ return ret; -+ lwbf = c->wbuf_len - owbf; /* number of bytes to copy */ -+ if (lwbf > len) -+ lwbf = len; -+ } else { -+ orbf = (c->wbuf_ofs - ofs); /* offset in read buffer */ -+ if (orbf > len) /* is write beyond write buffer ? */ -+ return ret; -+ lwbf = len - orbf; /* number of bytes to copy */ -+ if (lwbf > c->wbuf_len) -+ lwbf = c->wbuf_len; -+ } -+ if (lwbf > 0) -+ memcpy(buf+orbf,c->wbuf+owbf,lwbf); -+ -+ return ret; -+} -+ -+/* -+ * Check, if the out of band area is empty -+ */ -+int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, int mode) -+{ -+ unsigned char *buf; -+ int ret = 0; -+ int i,len,page; -+ size_t retlen; -+ int oob_size; -+ -+ oob_size = c->mtd->oobsize; -+ -+ /* allocate a buffer for all oob data in this sector */ -+ len = 4 * oob_size; -+ buf = kmalloc(len, GFP_KERNEL); -+ if (!buf) { -+ printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n"); -+ return -ENOMEM; -+ } -+ /* -+ * if mode = 0, we scan for a total empty oob area, else we have -+ * to take care of the cleanmarker in the first page of the block -+ */ -+ ret = jffs2_flash_read_oob(c, jeb->offset, len , &retlen, buf); -+ if (ret) { -+ D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB failed %d for block at %08x\n", ret, jeb->offset)); -+ goto out; -+ } -+ -+ if (retlen < len) { -+ D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB return short read " -+ "(%zd bytes not %d) for block at %08x\n", retlen, len, jeb->offset)); -+ ret = -EIO; -+ goto out; -+ } -+ -+ /* Special check for first two pages */ -+ for (page = 0; page < 2 * oob_size; page += oob_size) { -+ /* Check for bad block marker */ -+ if (buf[page+c->badblock_pos] != 0xff) { -+ D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Bad or failed block at %08x\n",jeb->offset)); -+ /* Return 2 for bad and 3 for failed block -+ bad goes to list_bad and failed to list_erase */ -+ ret = (!page) ? 2 : 3; -+ goto out; -+ } -+ for(i = 0; i < oob_size ; i++) { -+ /* Yeah, we know about the cleanmarker. */ -+ if (mode && i >= c->fsdata_pos && -+ i < c->fsdata_pos+c->fsdata_len) -+ continue; -+ -+ if (buf[page+i] != 0xFF) { -+ D2(printk(KERN_DEBUG "Found %02x at %x in OOB for %08x\n", -+ buf[page+i], page+i, jeb->offset)); -+ ret = 1; -+ goto out; -+ } -+ } -+ /* only the first page can contain a cleanmarker !*/ -+ mode = 0; -+ } -+ -+ /* we know, we are aligned :) */ -+ for (; page < len; page += sizeof(long)) { -+ unsigned long dat = *(unsigned long *)(&buf[page]); -+ if(dat != -1) { -+ ret = 1; -+ goto out; -+ } -+ } -+ -+out: -+ kfree(buf); -+ -+ return ret; -+} -+ -+/* -+* Scan for a valid cleanmarker and for bad blocks -+* For virtual blocks (concatenated physical blocks) check the cleanmarker -+* only in the first page of the first physical block, but scan for bad blocks in all -+* physical blocks -+*/ -+int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) -+{ -+ struct jffs2_unknown_node n; -+ unsigned char buf[32]; -+ unsigned char *p; -+ int ret, i, cnt, retval = 0; -+ size_t retlen, offset; -+ int oob_size; -+ -+ offset = jeb->offset; -+ oob_size = c->mtd->oobsize; -+ -+ /* Loop through the physical blocks */ -+ for (cnt = 0; cnt < (c->sector_size / c->mtd->erasesize); cnt++) { -+ /* -+ * We read oob data from page 0 and 1 of the block. -+ * page 0 contains cleanmarker and badblock info -+ * page 1 contains failure count of this block -+ */ -+ ret = c->mtd->read_oob (c->mtd, offset, oob_size << 1, &retlen, buf); -+ -+ if (ret) { -+ D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB failed %d for block at %08x\n", ret, jeb->offset)); -+ return ret; -+ } -+ if (retlen < (oob_size << 1)) { -+ D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB return short read (%zd bytes not %d) for block at %08x\n", retlen, oob_size << 1, jeb->offset)); -+ return -EIO; -+ } -+ -+ /* Check for bad block marker */ -+ if (buf[c->badblock_pos] != 0xff) { -+ D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Bad block at %08x (has %02x %02x in badblock_pos %d\n", -+ jeb->offset, buf[c->badblock_pos], buf[c->badblock_pos + oob_size], c->badblock_pos)); -+ return 2; -+ } -+ -+ /* Check for failure counter in the second page */ -+ if (buf[c->badblock_pos + oob_size] != 0xff) { -+ D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Block marked as failed at %08x, fail count:%d\n", jeb->offset, buf[c->badblock_pos + oob_size])); -+ return 3; -+ } -+ -+ /* Check cleanmarker only on the first physical block */ -+ if (!cnt) { -+ n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK); -+ n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER); -+ n.totlen = cpu_to_je32 (8); -+ p = (unsigned char *) &n; -+ -+ for (i = 0; i < c->fsdata_len; i++) { -+ if (buf[c->fsdata_pos + i] != p[i]) { -+ retval = 1; -+ } -+ } -+ D1(if (retval == 1) { -+ printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): Cleanmarker node not detected in block at %08x\n", jeb->offset); -+ printk(KERN_WARNING "OOB at %08x was ", offset); -+ for (i=0; i < oob_size; i++) { -+ printk("%02x ", buf[i]); -+ } -+ printk("\n"); -+ }) -+ } -+ offset += c->mtd->erasesize; -+ } -+ return retval; -+} -+ -+int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) -+{ -+ struct jffs2_unknown_node n; -+ int ret; -+ size_t retlen; -+ -+ n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); -+ n.totlen = cpu_to_je32(8); -+ -+ ret = jffs2_flash_write_oob(c, jeb->offset + c->fsdata_pos, c->fsdata_len, &retlen, (unsigned char *)&n); -+ -+ if (ret) { -+ D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); -+ return ret; -+ } -+ if (retlen != c->fsdata_len) { -+ D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Short write for block at %08x: %zd not %d\n", jeb->offset, retlen, c->fsdata_len)); -+ return ret; -+ } -+ return 0; -+} -+ -+/* -+ * We try to get the failure count of this block. -+ */ -+int jffs2_nand_read_failcnt(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) { -+ -+ unsigned char buf[16]; -+ int ret; -+ size_t retlen; -+ int oob_size; -+ -+ oob_size = c->mtd->oobsize; -+ -+ ret = c->mtd->read_oob(c->mtd, jeb->offset + c->mtd->oobblock, oob_size , &retlen, buf); -+ -+ if (ret) { -+ D1(printk(KERN_WARNING "jffs2_nand_read_failcnt(): Read OOB failed %d for block at %08x\n", ret, jeb->offset)); -+ return ret; -+ } -+ -+ if (retlen < oob_size) { -+ D1(printk(KERN_WARNING "jffs2_nand_read_failcnt(): Read OOB return short read (%zd bytes not %d) for block at %08x\n", retlen, oob_size, jeb->offset)); -+ return -EIO; -+ } -+ -+ jeb->bad_count = buf[c->badblock_pos]; -+ return 0; -+} -+ -+/* -+ * On NAND we try to mark this block bad. We try to write how often -+ * the block was erased and mark it finaly bad, if the count -+ * is > MAX_ERASE_FAILURES. We read this information on mount ! -+ * jeb->bad_count contains the count before this erase. -+ * Don't care about failures. This block remains on the erase-pending -+ * or badblock list as long as nobody manipulates the flash with -+ * a bootloader or something like that. -+ */ -+ -+int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) -+{ -+ unsigned char buf = 0x0; -+ int ret; -+ size_t retlen; -+ -+ /* if the count is < max, we try to write the counter to the 2nd page oob area */ -+ if( ++jeb->bad_count < MAX_ERASE_FAILURES) { -+ buf = (unsigned char)jeb->bad_count; -+ c->badblock_pos += c->mtd->oobblock; -+ } -+ -+ ret = jffs2_flash_write_oob(c, jeb->offset + c->badblock_pos, 1, &retlen, &buf); -+ -+ if (ret) { -+ D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); -+ return ret; -+ } -+ if (retlen != 1) { -+ D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Short write for block at %08x: %zd not 1\n", jeb->offset, retlen)); -+ return ret; -+ } -+ return 0; -+} -+ -+#define JFFS2_OOB_ECCPOS0 0 -+#define JFFS2_OOB_ECCPOS1 1 -+#define JFFS2_OOB_ECCPOS2 2 -+#define JFFS2_OOB_ECCPOS3 3 -+#define JFFS2_OOB_ECCPOS4 6 -+#define JFFS2_OOB_ECCPOS5 7 -+ -+#define NAND_JFFS2_OOB8_FSDAPOS 6 -+#define NAND_JFFS2_OOB16_FSDAPOS 8 -+#define NAND_JFFS2_OOB8_FSDALEN 2 -+#define NAND_JFFS2_OOB16_FSDALEN 8 -+ -+static struct nand_oobinfo jffs2_oobinfo_swecc = { -+ .useecc = 1, -+ .eccpos = {JFFS2_OOB_ECCPOS0, JFFS2_OOB_ECCPOS1, JFFS2_OOB_ECCPOS2, -+ JFFS2_OOB_ECCPOS3, JFFS2_OOB_ECCPOS4, JFFS2_OOB_ECCPOS5} -+}; -+ -+static struct nand_oobinfo jffs2_oobinfo_docecc = { -+ .useecc = 1, -+ .eccpos = {0,1,2,3,4,5} -+}; -+ -+ -+ -+int jffs2_nand_flash_setup(struct jffs2_sb_info *c) -+{ -+ /* Cleanmarker is out-of-band, so inline size zero */ -+ c->cleanmarker_size = 0; -+ -+ /* Initialise write buffer */ -+ c->wbuf_pagesize = c->mtd->oobblock; -+ c->wbuf_ofs = 0xFFFFFFFF; -+ -+ /* FIXME: If we had a generic way of describing the hardware's -+ use of OOB area, we could perhaps make this generic too. */ -+ switch(c->mtd->ecctype) { -+ case MTD_ECC_SW: -+ D1(printk(KERN_DEBUG "JFFS2 using software ECC\n")); -+ c->oobinfo = &jffs2_oobinfo_swecc; -+ if (c->mtd->oobsize == 8) { -+ c->fsdata_pos = NAND_JFFS2_OOB8_FSDAPOS; -+ c->fsdata_len = NAND_JFFS2_OOB8_FSDALEN; -+ } else { -+ c->fsdata_pos = NAND_JFFS2_OOB16_FSDAPOS; -+ c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN; -+ } -+ c->badblock_pos = NAND_BADBLOCK_POS; -+ break; -+ -+ case MTD_ECC_RS_DiskOnChip: -+ D1(printk(KERN_DEBUG "JFFS2 using DiskOnChip hardware ECC\n")); -+ c->oobinfo = &jffs2_oobinfo_docecc; -+ c->fsdata_pos = 6; -+ c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN; -+ c->badblock_pos = 15; -+ break; -+ -+ default: -+ printk("JFFS2 doesn't yet know how to handle ECC type %d\n", -+ c->mtd->ecctype); -+ return -EINVAL; -+ } -+ -+ c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); -+ if (!c->wbuf) -+ return -ENOMEM; -+ -+#ifdef BREAKME -+ if (!brokenbuf) -+ brokenbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); -+ if (!brokenbuf) { -+ kfree(c->wbuf); -+ return -ENOMEM; -+ } -+ memset(brokenbuf, 0xdb, c->wbuf_pagesize); -+#endif -+ return 0; -+} -+ -+void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c) -+{ -+ kfree(c->wbuf); -+} -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/write.c linux/fs/jffs2/write.c ---- linux-mips-2.4.24-pre2/fs/jffs2/write.c 2004-11-17 18:05:04.000000000 +0100 -+++ linux/fs/jffs2/write.c 2004-11-17 18:17:59.000000000 +0100 -@@ -1,154 +1,70 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include - #include --#include -+#include -+#include -+#include - #include - #include "nodelist.h" --#include - --/* jffs2_new_inode: allocate a new inode and inocache, add it to the hash, -- fill in the raw_inode while you're at it. */ --struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri) -+ -+int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri) - { -- struct inode *inode; -- struct super_block *sb = dir_i->i_sb; - struct jffs2_inode_cache *ic; -- struct jffs2_sb_info *c; -- struct jffs2_inode_info *f; -- -- D1(printk(KERN_DEBUG "jffs2_new_inode(): dir_i %ld, mode 0x%x\n", dir_i->i_ino, mode)); -- -- c = JFFS2_SB_INFO(sb); -- memset(ri, 0, sizeof(*ri)); - - ic = jffs2_alloc_inode_cache(); - if (!ic) { -- return ERR_PTR(-ENOMEM); -+ return -ENOMEM; - } -- memset(ic, 0, sizeof(*ic)); -- -- inode = new_inode(sb); - -- if (!inode) { -- jffs2_free_inode_cache(ic); -- return ERR_PTR(-ENOMEM); -- } -- -- /* Alloc jffs2_inode_info when that's split in 2.5 */ -+ memset(ic, 0, sizeof(*ic)); - -- f = JFFS2_INODE_INFO(inode); -- memset(f, 0, sizeof(*f)); - init_MUTEX_LOCKED(&f->sem); - f->inocache = ic; -- inode->i_nlink = f->inocache->nlink = 1; -+ f->inocache->nlink = 1; - f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; -- f->inocache->ino = ri->ino = inode->i_ino = ++c->highest_ino; -- D1(printk(KERN_DEBUG "jffs2_new_inode(): Assigned ino# %d\n", ri->ino)); -- jffs2_add_ino_cache(c, f->inocache); -+ f->inocache->ino = ++c->highest_ino; -+ f->inocache->state = INO_STATE_PRESENT; - -- ri->magic = JFFS2_MAGIC_BITMASK; -- ri->nodetype = JFFS2_NODETYPE_INODE; -- ri->totlen = PAD(sizeof(*ri)); -- ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); -- ri->mode = mode; -- f->highest_version = ri->version = 1; -- ri->uid = current->fsuid; -- if (dir_i->i_mode & S_ISGID) { -- ri->gid = dir_i->i_gid; -- if (S_ISDIR(mode)) -- ri->mode |= S_ISGID; -- } else { -- ri->gid = current->fsgid; -- } -- inode->i_mode = ri->mode; -- inode->i_gid = ri->gid; -- inode->i_uid = ri->uid; -- inode->i_atime = inode->i_ctime = inode->i_mtime = -- ri->atime = ri->mtime = ri->ctime = CURRENT_TIME; -- inode->i_blksize = PAGE_SIZE; -- inode->i_blocks = 0; -- inode->i_size = 0; -+ ri->ino = cpu_to_je32(f->inocache->ino); - -- insert_inode_hash(inode); -+ D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino)); -+ jffs2_add_ino_cache(c, f->inocache); - -- return inode; --} -+ ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -+ ri->totlen = cpu_to_je32(PAD(sizeof(*ri))); -+ ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); -+ ri->mode = cpu_to_jemode(mode); - --/* This ought to be in core MTD code. All registered MTD devices -- without writev should have this put in place. Bug the MTD -- maintainer */ --static int mtd_fake_writev(struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen) --{ -- unsigned long i; -- size_t totlen = 0, thislen; -- int ret = 0; -+ f->highest_version = 1; -+ ri->version = cpu_to_je32(f->highest_version); - -- for (i=0; iwrite(mtd, to, vecs[i].iov_len, &thislen, vecs[i].iov_base); -- totlen += thislen; -- if (ret || thislen != vecs[i].iov_len) -- break; -- to += vecs[i].iov_len; -- } -- if (retlen) -- *retlen = totlen; -- return ret; --} -- -- --static inline int mtd_writev(struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen) --{ -- if (mtd->writev) -- return mtd->writev(mtd,vecs,count,to,retlen); -- else -- return mtd_fake_writev(mtd, vecs, count, to, retlen); -+ return 0; - } - --static void writecheck(struct mtd_info *mtd, __u32 ofs) -+#if CONFIG_JFFS2_FS_DEBUG > 0 -+static void writecheck(struct jffs2_sb_info *c, uint32_t ofs) - { - unsigned char buf[16]; -- ssize_t retlen; -+ size_t retlen; - int ret, i; - -- ret = mtd->read(mtd, ofs, 16, &retlen, buf); -- if (ret && retlen != 16) { -- D1(printk(KERN_DEBUG "read failed or short in writecheck(). ret %d, retlen %d\n", ret, retlen)); -+ ret = jffs2_flash_read(c, ofs, 16, &retlen, buf); -+ if (ret || (retlen != 16)) { -+ D1(printk(KERN_DEBUG "read failed or short in writecheck(). ret %d, retlen %zd\n", ret, retlen)); - return; - } - ret = 0; -@@ -157,32 +73,31 @@ - ret = 1; - } - if (ret) { -- printk(KERN_WARNING "ARGH. About to write node to 0x%08x on flash, but there's data already there:\n", ofs); -+ printk(KERN_WARNING "ARGH. About to write node to 0x%08x on flash, but there are data already there:\n", ofs); - printk(KERN_WARNING "0x%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - ofs, - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], - buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]); - } - } -- -- -+#endif - - - /* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, - write it to the flash, link it into the existing inode/fragment list */ - --struct jffs2_full_dnode *jffs2_write_dnode(struct inode *inode, struct jffs2_raw_inode *ri, const unsigned char *data, __u32 datalen, __u32 flash_ofs, __u32 *writelen) -+struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode) - - { -- struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_raw_node_ref *raw; - struct jffs2_full_dnode *fn; -- ssize_t retlen; -+ size_t retlen; - struct iovec vecs[2]; - int ret; -+ int retried = 0; -+ unsigned long cnt = 2; - -- D1(if(ri->hdr_crc != crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)) { -+ D1(if(je32_to_cpu(ri->hdr_crc) != crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)) { - printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dnode()\n"); - BUG(); - } -@@ -192,10 +107,10 @@ - vecs[1].iov_base = (unsigned char *)data; - vecs[1].iov_len = datalen; - -- writecheck(c->mtd, flash_ofs); -+ D1(writecheck(c, flash_ofs)); - -- if (ri->totlen != sizeof(*ri) + datalen) { -- printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08x) + datalen (0x%08x)\n", ri->totlen, sizeof(*ri), datalen); -+ if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { -+ printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); - } - raw = jffs2_alloc_raw_node_ref(); - if (!raw) -@@ -206,19 +121,28 @@ - jffs2_free_raw_node_ref(raw); - return ERR_PTR(-ENOMEM); - } -- raw->flash_offset = flash_ofs; -- raw->totlen = PAD(ri->totlen); -- raw->next_phys = NULL; - -- fn->ofs = ri->offset; -- fn->size = ri->dsize; -+ fn->ofs = je32_to_cpu(ri->offset); -+ fn->size = je32_to_cpu(ri->dsize); - fn->frags = 0; -+ -+ /* check number of valid vecs */ -+ if (!datalen || !data) -+ cnt = 1; -+ retry: - fn->raw = raw; - -- ret = mtd_writev(c->mtd, vecs, 2, flash_ofs, &retlen); -+ raw->flash_offset = flash_ofs; -+ raw->__totlen = PAD(sizeof(*ri)+datalen); -+ raw->next_phys = NULL; -+ -+ ret = jffs2_flash_writev(c, vecs, cnt, flash_ofs, &retlen, -+ (alloc_mode==ALLOC_GC)?0:f->inocache->ino); -+ - if (ret || (retlen != sizeof(*ri) + datalen)) { -- printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %d\n", -+ printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", - sizeof(*ri)+datalen, flash_ofs, ret, retlen); -+ - /* Mark the space as dirtied */ - if (retlen) { - /* Doesn't belong to any inode */ -@@ -229,48 +153,96 @@ - seem corrupted, in which case the scan would skip over - any node we write before the original intended end of - this node */ -- jffs2_add_physical_node_ref(c, raw, sizeof(*ri)+datalen, 1); -+ raw->flash_offset |= REF_OBSOLETE; -+ jffs2_add_physical_node_ref(c, raw); - jffs2_mark_node_obsolete(c, raw); - } else { - printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); - jffs2_free_raw_node_ref(raw); - } -+ if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) { -+ /* Try to reallocate space and retry */ -+ uint32_t dummy; -+ struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; -+ -+ retried = 1; -+ -+ D1(printk(KERN_DEBUG "Retrying failed write.\n")); -+ -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ if (alloc_mode == ALLOC_GC) { -+ ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, &dummy); -+ } else { -+ /* Locking pain */ -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ -+ ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, &dummy, alloc_mode); -+ down(&f->sem); -+ } -+ -+ if (!ret) { -+ D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); -+ -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); - -+ goto retry; -+ } -+ D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); -+ jffs2_free_raw_node_ref(raw); -+ } - /* Release the full_dnode which is now useless, and return */ - jffs2_free_full_dnode(fn); -- if (writelen) -- *writelen = retlen; - return ERR_PTR(ret?ret:-EIO); - } - /* Mark the space used */ -- jffs2_add_physical_node_ref(c, raw, retlen, 0); -+ /* If node covers at least a whole page, or if it starts at the -+ beginning of a page and runs to the end of the file, or if -+ it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. -+ */ -+ if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || -+ ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && -+ (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) { -+ raw->flash_offset |= REF_PRISTINE; -+ } else { -+ raw->flash_offset |= REF_NORMAL; -+ } -+ jffs2_add_physical_node_ref(c, raw); - - /* Link into per-inode list */ - raw->next_in_ino = f->inocache->nodes; - f->inocache->nodes = raw; - -- D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", flash_ofs, ri->dsize, ri->csize, ri->node_crc, ri->data_crc, ri->totlen)); -- if (writelen) -- *writelen = retlen; -+ D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", -+ flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), -+ je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), -+ je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); -+ -+ if (retried) { -+ ACCT_SANITY_CHECK(c,NULL); -+ } - -- f->inocache->nodes = raw; - return fn; - } - --struct jffs2_full_dirent *jffs2_write_dirent(struct inode *inode, struct jffs2_raw_dirent *rd, const unsigned char *name, __u32 namelen, __u32 flash_ofs, __u32 *writelen) -+struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode) - { -- struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_raw_node_ref *raw; - struct jffs2_full_dirent *fd; -- ssize_t retlen; -+ size_t retlen; - struct iovec vecs[2]; -+ int retried = 0; - int ret; - -- D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", rd->pino, name, name, rd->ino, rd->name_crc)); -- writecheck(c->mtd, flash_ofs); -+ D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", -+ je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino), -+ je32_to_cpu(rd->name_crc))); -+ D1(writecheck(c, flash_ofs)); - -- D1(if(rd->hdr_crc != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { -+ D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { - printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); - BUG(); - } -@@ -291,44 +263,414 @@ - jffs2_free_raw_node_ref(raw); - return ERR_PTR(-ENOMEM); - } -- raw->flash_offset = flash_ofs; -- raw->totlen = PAD(rd->totlen); -- raw->next_in_ino = f->inocache->nodes; -- f->inocache->nodes = raw; -- raw->next_phys = NULL; - -- fd->version = rd->version; -- fd->ino = rd->ino; -+ fd->version = je32_to_cpu(rd->version); -+ fd->ino = je32_to_cpu(rd->ino); - fd->nhash = full_name_hash(name, strlen(name)); - fd->type = rd->type; - memcpy(fd->name, name, namelen); - fd->name[namelen]=0; -+ -+ retry: - fd->raw = raw; - -- ret = mtd_writev(c->mtd, vecs, 2, flash_ofs, &retlen); -+ raw->flash_offset = flash_ofs; -+ raw->__totlen = PAD(sizeof(*rd)+namelen); -+ raw->next_phys = NULL; -+ -+ ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen, -+ (alloc_mode==ALLOC_GC)?0:je32_to_cpu(rd->pino)); - if (ret || (retlen != sizeof(*rd) + namelen)) { -- printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %d\n", -+ printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", - sizeof(*rd)+namelen, flash_ofs, ret, retlen); - /* Mark the space as dirtied */ - if (retlen) { -- jffs2_add_physical_node_ref(c, raw, sizeof(*rd)+namelen, 1); -+ raw->next_in_ino = NULL; -+ raw->flash_offset |= REF_OBSOLETE; -+ jffs2_add_physical_node_ref(c, raw); - jffs2_mark_node_obsolete(c, raw); - } else { - printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); - jffs2_free_raw_node_ref(raw); - } -+ if (!retried && (raw = jffs2_alloc_raw_node_ref())) { -+ /* Try to reallocate space and retry */ -+ uint32_t dummy; -+ struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; -+ -+ retried = 1; -+ -+ D1(printk(KERN_DEBUG "Retrying failed write.\n")); -+ -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ if (alloc_mode == ALLOC_GC) { -+ ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, &dummy); -+ } else { -+ /* Locking pain */ -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ -+ ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, &dummy, alloc_mode); -+ down(&f->sem); -+ } - -+ if (!ret) { -+ D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ goto retry; -+ } -+ D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); -+ jffs2_free_raw_node_ref(raw); -+ } - /* Release the full_dnode which is now useless, and return */ - jffs2_free_full_dirent(fd); -- if (writelen) -- *writelen = retlen; - return ERR_PTR(ret?ret:-EIO); - } - /* Mark the space used */ -- jffs2_add_physical_node_ref(c, raw, retlen, 0); -- if (writelen) -- *writelen = retlen; -+ raw->flash_offset |= REF_PRISTINE; -+ jffs2_add_physical_node_ref(c, raw); - -+ raw->next_in_ino = f->inocache->nodes; - f->inocache->nodes = raw; -+ -+ if (retried) { -+ ACCT_SANITY_CHECK(c,NULL); -+ } -+ - return fd; - } -+ -+/* The OS-specific code fills in the metadata in the jffs2_raw_inode for us, so that -+ we don't have to go digging in struct inode or its equivalent. It should set: -+ mode, uid, gid, (starting)isize, atime, ctime, mtime */ -+int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, -+ struct jffs2_raw_inode *ri, unsigned char *buf, -+ uint32_t offset, uint32_t writelen, uint32_t *retlen) -+{ -+ int ret = 0; -+ uint32_t writtenlen = 0; -+ -+ D1(printk(KERN_DEBUG "jffs2_write_inode_range(): Ino #%u, ofs 0x%x, len 0x%x\n", -+ f->inocache->ino, offset, writelen)); -+ -+ while(writelen) { -+ struct jffs2_full_dnode *fn; -+ unsigned char *comprbuf = NULL; -+ unsigned char comprtype = JFFS2_COMPR_NONE; -+ uint32_t phys_ofs, alloclen; -+ uint32_t datalen, cdatalen; -+ int retried = 0; -+ -+ retry: -+ D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset)); -+ -+ ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen, ALLOC_NORMAL); -+ if (ret) { -+ D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); -+ break; -+ } -+ down(&f->sem); -+ datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1))); -+ cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen); -+ -+ comprtype = jffs2_compress(buf, &comprbuf, &datalen, &cdatalen); -+ -+ ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -+ ri->totlen = cpu_to_je32(sizeof(*ri) + cdatalen); -+ ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); -+ -+ ri->ino = cpu_to_je32(f->inocache->ino); -+ ri->version = cpu_to_je32(++f->highest_version); -+ ri->isize = cpu_to_je32(max(je32_to_cpu(ri->isize), offset + datalen)); -+ ri->offset = cpu_to_je32(offset); -+ ri->csize = cpu_to_je32(cdatalen); -+ ri->dsize = cpu_to_je32(datalen); -+ ri->compr = comprtype; -+ ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); -+ ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); -+ -+ fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, phys_ofs, ALLOC_NORETRY); -+ -+ jffs2_free_comprbuf(comprbuf, buf); -+ -+ if (IS_ERR(fn)) { -+ ret = PTR_ERR(fn); -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ if (!retried) { -+ /* Write error to be retried */ -+ retried = 1; -+ D1(printk(KERN_DEBUG "Retrying node write in jffs2_write_inode_range()\n")); -+ goto retry; -+ } -+ break; -+ } -+ ret = jffs2_add_full_dnode_to_inode(c, f, fn); -+ if (f->metadata) { -+ jffs2_mark_node_obsolete(c, f->metadata->raw); -+ jffs2_free_full_dnode(f->metadata); -+ f->metadata = NULL; -+ } -+ if (ret) { -+ /* Eep */ -+ D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in commit_write, returned %d\n", ret)); -+ jffs2_mark_node_obsolete(c, fn->raw); -+ jffs2_free_full_dnode(fn); -+ -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ break; -+ } -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ if (!datalen) { -+ printk(KERN_WARNING "Eep. We didn't actually write any data in jffs2_write_inode_range()\n"); -+ ret = -EIO; -+ break; -+ } -+ D1(printk(KERN_DEBUG "increasing writtenlen by %d\n", datalen)); -+ writtenlen += datalen; -+ offset += datalen; -+ writelen -= datalen; -+ buf += datalen; -+ } -+ *retlen = writtenlen; -+ return ret; -+} -+ -+int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen) -+{ -+ struct jffs2_raw_dirent *rd; -+ struct jffs2_full_dnode *fn; -+ struct jffs2_full_dirent *fd; -+ uint32_t alloclen, phys_ofs; -+ int ret; -+ -+ /* Try to reserve enough space for both node and dirent. -+ * Just the node will do for now, though -+ */ -+ ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); -+ D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); -+ if (ret) { -+ up(&f->sem); -+ return ret; -+ } -+ -+ ri->data_crc = cpu_to_je32(0); -+ ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); -+ -+ fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); -+ -+ D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n", -+ jemode_to_cpu(ri->mode))); -+ -+ if (IS_ERR(fn)) { -+ D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n")); -+ /* Eeek. Wave bye bye */ -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ return PTR_ERR(fn); -+ } -+ /* No data here. Only a metadata node, which will be -+ obsoleted by the first data write -+ */ -+ f->metadata = fn; -+ -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); -+ -+ if (ret) { -+ /* Eep. */ -+ D1(printk(KERN_DEBUG "jffs2_reserve_space() for dirent failed\n")); -+ return ret; -+ } -+ -+ rd = jffs2_alloc_raw_dirent(); -+ if (!rd) { -+ /* Argh. Now we treat it like a normal delete */ -+ jffs2_complete_reservation(c); -+ return -ENOMEM; -+ } -+ -+ down(&dir_f->sem); -+ -+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); -+ rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); -+ rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); -+ -+ rd->pino = cpu_to_je32(dir_f->inocache->ino); -+ rd->version = cpu_to_je32(++dir_f->highest_version); -+ rd->ino = ri->ino; -+ rd->mctime = ri->ctime; -+ rd->nsize = namelen; -+ rd->type = DT_REG; -+ rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); -+ rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); -+ -+ fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); -+ -+ jffs2_free_raw_dirent(rd); -+ -+ if (IS_ERR(fd)) { -+ /* dirent failed to write. Delete the inode normally -+ as if it were the final unlink() */ -+ jffs2_complete_reservation(c); -+ up(&dir_f->sem); -+ return PTR_ERR(fd); -+ } -+ -+ /* Link the fd into the inode's list, obsoleting an old -+ one if necessary. */ -+ jffs2_add_fd_to_list(c, fd, &dir_f->dents); -+ -+ jffs2_complete_reservation(c); -+ up(&dir_f->sem); -+ -+ return 0; -+} -+ -+ -+int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, -+ const char *name, int namelen, struct jffs2_inode_info *dead_f) -+{ -+ struct jffs2_raw_dirent *rd; -+ struct jffs2_full_dirent *fd; -+ uint32_t alloclen, phys_ofs; -+ int ret; -+ -+ rd = jffs2_alloc_raw_dirent(); -+ if (!rd) -+ return -ENOMEM; -+ -+ ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_DELETION); -+ if (ret) { -+ jffs2_free_raw_dirent(rd); -+ return ret; -+ } -+ -+ down(&dir_f->sem); -+ -+ /* Build a deletion node */ -+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); -+ rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); -+ rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); -+ -+ rd->pino = cpu_to_je32(dir_f->inocache->ino); -+ rd->version = cpu_to_je32(++dir_f->highest_version); -+ rd->ino = cpu_to_je32(0); -+ rd->mctime = cpu_to_je32(get_seconds()); -+ rd->nsize = namelen; -+ rd->type = DT_UNKNOWN; -+ rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); -+ rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); -+ -+ fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION); -+ -+ jffs2_free_raw_dirent(rd); -+ -+ if (IS_ERR(fd)) { -+ jffs2_complete_reservation(c); -+ up(&dir_f->sem); -+ return PTR_ERR(fd); -+ } -+ -+ /* File it. This will mark the old one obsolete. */ -+ jffs2_add_fd_to_list(c, fd, &dir_f->dents); -+ -+ up(&dir_f->sem); -+ -+ /* dead_f is NULL if this was a rename not a real unlink */ -+ /* Also catch the !f->inocache case, where there was a dirent -+ pointing to an inode which didn't exist. */ -+ if (dead_f && dead_f->inocache) { -+ -+ down(&dead_f->sem); -+ -+ while (dead_f->dents) { -+ /* There can be only deleted ones */ -+ fd = dead_f->dents; -+ -+ dead_f->dents = fd->next; -+ -+ if (fd->ino) { -+ printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n", -+ dead_f->inocache->ino, fd->name, fd->ino); -+ } else { -+ D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n", fd->name, dead_f->inocache->ino)); -+ } -+ jffs2_mark_node_obsolete(c, fd->raw); -+ jffs2_free_full_dirent(fd); -+ } -+ -+ dead_f->inocache->nlink--; -+ /* NB: Caller must set inode nlink if appropriate */ -+ up(&dead_f->sem); -+ } -+ -+ jffs2_complete_reservation(c); -+ -+ return 0; -+} -+ -+ -+int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen) -+{ -+ struct jffs2_raw_dirent *rd; -+ struct jffs2_full_dirent *fd; -+ uint32_t alloclen, phys_ofs; -+ int ret; -+ -+ rd = jffs2_alloc_raw_dirent(); -+ if (!rd) -+ return -ENOMEM; -+ -+ ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); -+ if (ret) { -+ jffs2_free_raw_dirent(rd); -+ return ret; -+ } -+ -+ down(&dir_f->sem); -+ -+ /* Build a deletion node */ -+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); -+ rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); -+ rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); -+ -+ rd->pino = cpu_to_je32(dir_f->inocache->ino); -+ rd->version = cpu_to_je32(++dir_f->highest_version); -+ rd->ino = cpu_to_je32(ino); -+ rd->mctime = cpu_to_je32(get_seconds()); -+ rd->nsize = namelen; -+ -+ rd->type = type; -+ -+ rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); -+ rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); -+ -+ fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); -+ -+ jffs2_free_raw_dirent(rd); -+ -+ if (IS_ERR(fd)) { -+ jffs2_complete_reservation(c); -+ up(&dir_f->sem); -+ return PTR_ERR(fd); -+ } -+ -+ /* File it. This will mark the old one obsolete. */ -+ jffs2_add_fd_to_list(c, fd, &dir_f->dents); -+ -+ jffs2_complete_reservation(c); -+ up(&dir_f->sem); -+ -+ return 0; -+} -diff -Nurb linux-mips-2.4.24-pre2/fs/jffs2/writev.c linux/fs/jffs2/writev.c ---- linux-mips-2.4.24-pre2/fs/jffs2/writev.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/writev.c 2004-11-17 18:17:59.413257072 +0100 -@@ -0,0 +1,50 @@ -+/* -+ * JFFS2 -- Journalling Flash File System, Version 2. -+ * -+ * Copyright (C) 2001, 2002 Red Hat, Inc. -+ * -+ * Created by David Woodhouse -+ * -+ * For licensing information, see the file 'LICENCE' in this directory. -+ * -+ * $Id$ -+ * -+ */ -+ -+#include -+#include -+#include "nodelist.h" -+ -+/* This ought to be in core MTD code. All registered MTD devices -+ without writev should have this put in place. Bug the MTD -+ maintainer */ -+static inline int mtd_fake_writev(struct mtd_info *mtd, const struct iovec *vecs, -+ unsigned long count, loff_t to, size_t *retlen) -+{ -+ unsigned long i; -+ size_t totlen = 0, thislen; -+ int ret = 0; -+ -+ for (i=0; iwrite(mtd, to, vecs[i].iov_len, &thislen, vecs[i].iov_base); -+ totlen += thislen; -+ if (ret || thislen != vecs[i].iov_len) -+ break; -+ to += vecs[i].iov_len; -+ } -+ if (retlen) -+ *retlen = totlen; -+ return ret; -+} -+ -+int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs, -+ unsigned long count, loff_t to, size_t *retlen) -+{ -+ if (c->mtd->writev) -+ return c->mtd->writev(c->mtd, vecs, count, to, retlen); -+ else -+ return mtd_fake_writev(c->mtd, vecs, count, to, retlen); -+} -+ -diff -Nurb linux-mips-2.4.24-pre2/include/linux/jffs2.h linux/include/linux/jffs2.h ---- linux-mips-2.4.24-pre2/include/linux/jffs2.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/jffs2.h 2004-11-17 18:17:59.000000000 +0100 -@@ -1,50 +1,30 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in the -+ * jffs2 directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #ifndef __LINUX_JFFS2_H__ - #define __LINUX_JFFS2_H__ - --#include -+/* You must include something which defines the C99 uintXX_t types. -+ We don't do it from here because this file is used in too many -+ different environments. */ -+ - #define JFFS2_SUPER_MAGIC 0x72b6 - - /* Values we may expect to find in the 'magic' field */ - #define JFFS2_OLD_MAGIC_BITMASK 0x1984 - #define JFFS2_MAGIC_BITMASK 0x1985 --#define KSAMTIB_CIGAM_2SFFJ 0x5981 /* For detecting wrong-endian fs */ -+#define KSAMTIB_CIGAM_2SFFJ 0x8519 /* For detecting wrong-endian fs */ - #define JFFS2_EMPTY_BITMASK 0xffff - #define JFFS2_DIRTY_BITMASK 0x0000 - -@@ -78,16 +58,12 @@ - #define JFFS2_NODETYPE_DIRENT (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 1) - #define JFFS2_NODETYPE_INODE (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 2) - #define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) -+#define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4) - - // Maybe later... - //#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) - //#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4) - --/* Same as the non_ECC versions, but with extra space for real -- * ECC instead of just the checksum. For use on NAND flash -- */ --//#define JFFS2_NODETYPE_DIRENT_ECC (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 5) --//#define JFFS2_NODETYPE_INODE_ECC (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 6) - - #define JFFS2_INO_FLAG_PREREAD 1 /* Do read_inode() for this one at - mount time, don't wait for it to -@@ -96,31 +72,79 @@ - compression type */ - - -+/* These can go once we've made sure we've caught all uses without -+ byteswapping */ -+ -+typedef struct { -+ uint32_t v32; -+} __attribute__((packed)) jint32_t; -+ -+typedef struct { -+ uint32_t m; -+} __attribute__((packed)) jmode_t; -+ -+typedef struct { -+ uint16_t v16; -+} __attribute__((packed)) jint16_t; -+ -+#define JFFS2_NATIVE_ENDIAN -+ -+/* Note we handle mode bits conversion from JFFS2 (i.e. Linux) to/from -+ whatever OS we're actually running on here too. */ -+ -+#if defined(JFFS2_NATIVE_ENDIAN) -+#define cpu_to_je16(x) ((jint16_t){x}) -+#define cpu_to_je32(x) ((jint32_t){x}) -+#define cpu_to_jemode(x) ((jmode_t){os_to_jffs2_mode(x)}) -+ -+#define je16_to_cpu(x) ((x).v16) -+#define je32_to_cpu(x) ((x).v32) -+#define jemode_to_cpu(x) (jffs2_to_os_mode((x).m)) -+#elif defined(JFFS2_BIG_ENDIAN) -+#define cpu_to_je16(x) ((jint16_t){cpu_to_be16(x)}) -+#define cpu_to_je32(x) ((jint32_t){cpu_to_be32(x)}) -+#define cpu_to_jemode(x) ((jmode_t){cpu_to_be32(os_to_jffs2_mode(x))}) -+ -+#define je16_to_cpu(x) (be16_to_cpu(x.v16)) -+#define je32_to_cpu(x) (be32_to_cpu(x.v32)) -+#define jemode_to_cpu(x) (be32_to_cpu(jffs2_to_os_mode((x).m))) -+#elif defined(JFFS2_LITTLE_ENDIAN) -+#define cpu_to_je16(x) ((jint16_t){cpu_to_le16(x)}) -+#define cpu_to_je32(x) ((jint32_t){cpu_to_le32(x)}) -+#define cpu_to_jemode(x) ((jmode_t){cpu_to_le32(os_to_jffs2_mode(x))}) -+ -+#define je16_to_cpu(x) (le16_to_cpu(x.v16)) -+#define je32_to_cpu(x) (le32_to_cpu(x.v32)) -+#define jemode_to_cpu(x) (le32_to_cpu(jffs2_to_os_mode((x).m))) -+#else -+#error wibble -+#endif -+ - struct jffs2_unknown_node - { - /* All start like this */ -- __u16 magic; -- __u16 nodetype; -- __u32 totlen; /* So we can skip over nodes we don't grok */ -- __u32 hdr_crc; -+ jint16_t magic; -+ jint16_t nodetype; -+ jint32_t totlen; /* So we can skip over nodes we don't grok */ -+ jint32_t hdr_crc; - } __attribute__((packed)); - - struct jffs2_raw_dirent - { -- __u16 magic; -- __u16 nodetype; /* == JFFS_NODETYPE_DIRENT */ -- __u32 totlen; -- __u32 hdr_crc; -- __u32 pino; -- __u32 version; -- __u32 ino; /* == zero for unlink */ -- __u32 mctime; -- __u8 nsize; -- __u8 type; -- __u8 unused[2]; -- __u32 node_crc; -- __u32 name_crc; -- __u8 name[0]; -+ jint16_t magic; -+ jint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ -+ jint32_t totlen; -+ jint32_t hdr_crc; -+ jint32_t pino; -+ jint32_t version; -+ jint32_t ino; /* == zero for unlink */ -+ jint32_t mctime; -+ uint8_t nsize; -+ uint8_t type; -+ uint8_t unused[2]; -+ jint32_t node_crc; -+ jint32_t name_crc; -+ uint8_t name[0]; - } __attribute__((packed)); - - /* The JFFS2 raw inode structure: Used for storage on physical media. */ -@@ -131,28 +155,28 @@ - */ - struct jffs2_raw_inode - { -- __u16 magic; /* A constant magic number. */ -- __u16 nodetype; /* == JFFS_NODETYPE_INODE */ -- __u32 totlen; /* Total length of this node (inc data, etc.) */ -- __u32 hdr_crc; -- __u32 ino; /* Inode number. */ -- __u32 version; /* Version number. */ -- __u32 mode; /* The file's type or mode. */ -- __u16 uid; /* The file's owner. */ -- __u16 gid; /* The file's group. */ -- __u32 isize; /* Total resultant size of this inode (used for truncations) */ -- __u32 atime; /* Last access time. */ -- __u32 mtime; /* Last modification time. */ -- __u32 ctime; /* Change time. */ -- __u32 offset; /* Where to begin to write. */ -- __u32 csize; /* (Compressed) data size */ -- __u32 dsize; /* Size of the node's data. (after decompression) */ -- __u8 compr; /* Compression algorithm used */ -- __u8 usercompr; /* Compression algorithm requested by the user */ -- __u16 flags; /* See JFFS2_INO_FLAG_* */ -- __u32 data_crc; /* CRC for the (compressed) data. */ -- __u32 node_crc; /* CRC for the raw inode (excluding data) */ --// __u8 data[dsize]; -+ jint16_t magic; /* A constant magic number. */ -+ jint16_t nodetype; /* == JFFS_NODETYPE_INODE */ -+ jint32_t totlen; /* Total length of this node (inc data, etc.) */ -+ jint32_t hdr_crc; -+ jint32_t ino; /* Inode number. */ -+ jint32_t version; /* Version number. */ -+ jmode_t mode; /* The file's type or mode. */ -+ jint16_t uid; /* The file's owner. */ -+ jint16_t gid; /* The file's group. */ -+ jint32_t isize; /* Total resultant size of this inode (used for truncations) */ -+ jint32_t atime; /* Last access time. */ -+ jint32_t mtime; /* Last modification time. */ -+ jint32_t ctime; /* Change time. */ -+ jint32_t offset; /* Where to begin to write. */ -+ jint32_t csize; /* (Compressed) data size */ -+ jint32_t dsize; /* Size of the node's data. (after decompression) */ -+ uint8_t compr; /* Compression algorithm used */ -+ uint8_t usercompr; /* Compression algorithm requested by the user */ -+ jint16_t flags; /* See JFFS2_INO_FLAG_* */ -+ jint32_t data_crc; /* CRC for the (compressed) data. */ -+ jint32_t node_crc; /* CRC for the raw inode (excluding data) */ -+ uint8_t data[0]; - } __attribute__((packed)); - - union jffs2_node_union { -diff -Nurb linux-mips-2.4.24-pre2/include/linux/jffs2_fs_i.h linux/include/linux/jffs2_fs_i.h ---- linux-mips-2.4.24-pre2/include/linux/jffs2_fs_i.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/jffs2_fs_i.h 2004-11-17 18:17:59.000000000 +0100 -@@ -1,22 +1,12 @@ --/* $Id$ */ -+/* $Id$ */ - - #ifndef _JFFS2_FS_I - #define _JFFS2_FS_I - --/* Include the pipe_inode_info at the beginning so that we can still -- use the storage space in the inode when we have a pipe inode. -- This sucks. --*/ -- --#undef THISSUCKS /* Only for 2.2 */ --#ifdef THISSUCKS --#include --#endif -+#include -+#include - - struct jffs2_inode_info { --#ifdef THISSUCKS -- struct pipe_inode_info pipecrap; --#endif - /* We need an internal semaphore similar to inode->i_sem. - Unfortunately, we can't used the existing one, because - either the GC would deadlock, or we'd have to release it -@@ -26,10 +16,10 @@ - struct semaphore sem; - - /* The highest (datanode) version number used for this ino */ -- __u32 highest_version; -+ uint32_t highest_version; - - /* List of data fragments which make up the file */ -- struct jffs2_node_frag *fraglist; -+ struct rb_root fragtree; - - /* There may be one datanode which isn't referenced by any of the - above fragments, if it contains a metadata update but no actual -@@ -44,19 +34,13 @@ - /* Some stuff we just have to keep in-core at all times, for each inode. */ - struct jffs2_inode_cache *inocache; - -- /* Keep a pointer to the last physical node in the list. We don't -- use the doubly-linked lists because we don't want to increase -- the memory usage that much. This is simpler */ -- // struct jffs2_raw_node_ref *lastnode; -- __u16 flags; -- __u8 usercompr; --}; -- --#ifdef JFFS2_OUT_OF_KERNEL --#define JFFS2_INODE_INFO(i) ((struct jffs2_inode_info *) &(i)->u) --#else --#define JFFS2_INODE_INFO(i) (&i->u.jffs2_i) -+ uint16_t flags; -+ uint8_t usercompr; -+#if !defined (__ECOS) -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2) -+ struct inode vfs_inode; - #endif -+#endif -+}; - - #endif /* _JFFS2_FS_I */ -- -diff -Nurb linux-mips-2.4.24-pre2/include/linux/jffs2_fs_sb.h linux/include/linux/jffs2_fs_sb.h ---- linux-mips-2.4.24-pre2/include/linux/jffs2_fs_sb.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/jffs2_fs_sb.h 2004-11-17 18:17:59.000000000 +0100 -@@ -1,19 +1,22 @@ --/* $Id$ */ -+/* $Id$ */ - - #ifndef _JFFS2_FS_SB - #define _JFFS2_FS_SB - - #include - #include -+#include - #include - #include -+#include -+#include - #include - --#define INOCACHE_HASHSIZE 1 -- - #define JFFS2_SB_FLAG_RO 1 - #define JFFS2_SB_FLAG_MOUNTING 2 - -+struct jffs2_inodirty; -+ - /* A struct for the overall file system control. Pointers to - jffs2_sb_info structs are named `c' in the source code. - Nee jffs_control -@@ -21,36 +24,46 @@ - struct jffs2_sb_info { - struct mtd_info *mtd; - -- __u32 highest_ino; -+ uint32_t highest_ino; -+ uint32_t checked_ino; -+ - unsigned int flags; -- spinlock_t nodelist_lock; - -- // pid_t thread_pid; /* GC thread's PID */ - struct task_struct *gc_task; /* GC task struct */ - struct semaphore gc_thread_start; /* GC thread start mutex */ - struct completion gc_thread_exit; /* GC thread exit completion port */ -- // __u32 gc_minfree_threshold; /* GC trigger thresholds */ -- // __u32 gc_maxdirty_threshold; - - struct semaphore alloc_sem; /* Used to protect all the following - fields, and also to protect against - out-of-order writing of nodes. - And GC. - */ -- __u32 flash_size; -- __u32 used_size; -- __u32 dirty_size; -- __u32 free_size; -- __u32 erasing_size; -- __u32 bad_size; -- __u32 sector_size; -- // __u32 min_free_size; -- // __u32 max_chunk_size; -+ uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER -+ (i.e. zero for OOB CLEANMARKER */ -+ -+ uint32_t flash_size; -+ uint32_t used_size; -+ uint32_t dirty_size; -+ uint32_t wasted_size; -+ uint32_t free_size; -+ uint32_t erasing_size; -+ uint32_t bad_size; -+ uint32_t sector_size; -+ uint32_t unchecked_size; -+ -+ uint32_t nr_free_blocks; -+ uint32_t nr_erasing_blocks; -+ -+ /* Number of free blocks there must be before we... */ -+ uint8_t resv_blocks_write; /* ... allow a normal filesystem write */ -+ uint8_t resv_blocks_deletion; /* ... allow a normal filesystem deletion */ -+ uint8_t resv_blocks_gctrigger; /* ... wake up the GC thread */ -+ uint8_t resv_blocks_gcbad; /* ... pick a block from the bad_list to GC */ -+ uint8_t resv_blocks_gcmerge; /* ... merge pages when garbage collecting */ - -- __u32 nr_free_blocks; -- __u32 nr_erasing_blocks; -+ uint32_t nospc_dirty_size; - -- __u32 nr_blocks; -+ uint32_t nr_blocks; - struct jffs2_eraseblock *blocks; /* The whole array of blocks. Used for getting blocks - * from the offset (blocks[ofs / sector_size]) */ - struct jffs2_eraseblock *nextblock; /* The block we're currently filling */ -@@ -58,9 +71,12 @@ - struct jffs2_eraseblock *gcblock; /* The block we're currently garbage-collecting */ - - struct list_head clean_list; /* Blocks 100% full of clean data */ -+ struct list_head very_dirty_list; /* Blocks with lots of dirty space */ - struct list_head dirty_list; /* Blocks with some dirty space */ -+ struct list_head erasable_list; /* Blocks which are completely dirty, and need erasing */ -+ struct list_head erasable_pending_wbuf_list; /* Blocks which need erasing but only after the current wbuf is flushed */ - struct list_head erasing_list; /* Blocks which are currently erasing */ -- struct list_head erase_pending_list; /* Blocks which need erasing */ -+ struct list_head erase_pending_list; /* Blocks which need erasing now */ - struct list_head erase_complete_list; /* Blocks which are erased and need the clean marker written to them */ - struct list_head free_list; /* Blocks which are free and ready to be used */ - struct list_head bad_list; /* Bad blocks. */ -@@ -69,16 +85,33 @@ - spinlock_t erase_completion_lock; /* Protect free_list and erasing_list - against erase completion handler */ - wait_queue_head_t erase_wait; /* For waiting for erases to complete */ -- struct jffs2_inode_cache *inocache_list[INOCACHE_HASHSIZE]; -+ -+ wait_queue_head_t inocache_wq; -+ struct jffs2_inode_cache **inocache_list; - spinlock_t inocache_lock; --}; - --#ifdef JFFS2_OUT_OF_KERNEL --#define JFFS2_SB_INFO(sb) ((struct jffs2_sb_info *) &(sb)->u) --#else --#define JFFS2_SB_INFO(sb) (&sb->u.jffs2_sb) -+ /* Sem to allow jffs2_garbage_collect_deletion_dirent to -+ drop the erase_completion_lock while it's holding a pointer -+ to an obsoleted node. I don't like this. Alternatives welcomed. */ -+ struct semaphore erase_free_sem; -+ -+#ifdef CONFIG_JFFS2_FS_NAND -+ /* Write-behind buffer for NAND flash */ -+ unsigned char *wbuf; -+ uint32_t wbuf_ofs; -+ uint32_t wbuf_len; -+ uint32_t wbuf_pagesize; -+ struct jffs2_inodirty *wbuf_inodes; -+ -+ /* Information about out-of-band area usage... */ -+ struct nand_oobinfo *oobinfo; -+ uint32_t badblock_pos; -+ uint32_t fsdata_pos; -+ uint32_t fsdata_len; - #endif - --#define OFNI_BS_2SFFJ(c) ((struct super_block *) ( ((char *)c) - ((char *)(&((struct super_block *)NULL)->u)) ) ) -+ /* OS-private pointer for getting back to master superblock info */ -+ void *os_priv; -+}; - - #endif /* _JFFS2_FB_SB */ -diff -Nurb linux-mips-2.4.24-pre2/include/linux/mtd/blktrans.h linux/include/linux/mtd/blktrans.h ---- linux-mips-2.4.24-pre2/include/linux/mtd/blktrans.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/include/linux/mtd/blktrans.h 2004-11-17 18:17:59.205288688 +0100 -@@ -0,0 +1,72 @@ -+/* -+ * $Id$ -+ * -+ * (C) 2003 David Woodhouse -+ * -+ * Interface to Linux block layer for MTD 'translation layers'. -+ * -+ */ -+ -+#ifndef __MTD_TRANS_H__ -+#define __MTD_TRANS_H__ -+ -+#include -+ -+struct hd_geometry; -+struct mtd_info; -+struct mtd_blktrans_ops; -+struct file; -+struct inode; -+ -+struct mtd_blktrans_dev { -+ struct mtd_blktrans_ops *tr; -+ struct list_head list; -+ struct mtd_info *mtd; -+ struct semaphore sem; -+ int devnum; -+ int blksize; -+ unsigned long size; -+ int readonly; -+ void *blkcore_priv; /* gendisk in 2.5, devfs_handle in 2.4 */ -+}; -+ -+struct blkcore_priv; /* Differs for 2.4 and 2.5 kernels; private */ -+ -+struct mtd_blktrans_ops { -+ char *name; -+ int major; -+ int part_bits; -+ -+ /* Access functions */ -+ int (*readsect)(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buffer); -+ int (*writesect)(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buffer); -+ -+ /* Block layer ioctls */ -+ int (*getgeo)(struct mtd_blktrans_dev *dev, struct hd_geometry *geo); -+ int (*flush)(struct mtd_blktrans_dev *dev); -+ -+ /* Called with mtd_table_mutex held; no race with add/remove */ -+ int (*open)(struct mtd_blktrans_dev *dev); -+ int (*release)(struct mtd_blktrans_dev *dev); -+ -+ /* Called on {de,}registration and on subsequent addition/removal -+ of devices, with mtd_table_mutex held. */ -+ void (*add_mtd)(struct mtd_blktrans_ops *tr, struct mtd_info *mtd); -+ void (*remove_dev)(struct mtd_blktrans_dev *dev); -+ -+ struct list_head devs; -+ struct list_head list; -+ struct module *owner; -+ -+ struct mtd_blkcore_priv *blkcore_priv; -+}; -+ -+extern int register_mtd_blktrans(struct mtd_blktrans_ops *tr); -+extern int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr); -+extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); -+extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); -+ -+ -+#endif /* __MTD_TRANS_H__ */ -diff -Nurb linux-mips-2.4.24-pre2/include/linux/mtd/cfi.h linux/include/linux/mtd/cfi.h ---- linux-mips-2.4.24-pre2/include/linux/mtd/cfi.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/mtd/cfi.h 2004-11-17 18:17:59.207288384 +0100 -@@ -1,13 +1,14 @@ - - /* Common Flash Interface structures - * See http://support.intel.com/design/flash/technote/index.htm -- * $Id$ -+ * $Id$ - */ - - #ifndef __MTD_CFI_H__ - #define __MTD_CFI_H__ - - #include -+#include - #include - #include - #include -@@ -260,7 +261,8 @@ - __u8 pri[3]; - __u8 MajorVersion; - __u8 MinorVersion; -- __u32 FeatureSupport; -+ __u32 FeatureSupport; /* if bit 31 is set then an additional __u32 feature -+ block follows - FIXME - not currently supported */ - __u8 SuspendCmdSupport; - __u16 BlkStatusRegMask; - __u8 VccOptimal; -@@ -271,6 +273,25 @@ - __u8 UserProtRegSize; - } __attribute__((packed)); - -+/* Vendor-Specific PRI for AMD/Fujitsu Extended Command Set (0x0002) */ -+ -+struct cfi_pri_amdstd { -+ __u8 pri[3]; -+ __u8 MajorVersion; -+ __u8 MinorVersion; -+ __u8 SiliconRevision; /* bits 1-0: Address Sensitive Unlock */ -+ __u8 EraseSuspend; -+ __u8 BlkProt; -+ __u8 TmpBlkUnprotect; -+ __u8 BlkProtUnprot; -+ __u8 SimultaneousOps; -+ __u8 BurstMode; -+ __u8 PageMode; -+ __u8 VppMin; -+ __u8 VppMax; -+ __u8 TopBottom; -+} __attribute__((packed)); -+ - struct cfi_pri_query { - __u8 NumFields; - __u32 ProtField[1]; /* Not host ordered */ -@@ -314,8 +335,6 @@ - struct flchip chips[0]; /* per-chip data structure for each chip */ - }; - --#define MAX_CFI_CHIPS 8 /* Entirely arbitrary to avoid realloc() */ -- - /* - * Returns the command address according to the given geometry. - */ -@@ -387,13 +406,13 @@ - static inline cfi_word cfi_read(struct map_info *map, __u32 addr) - { - if (cfi_buswidth_is_1()) { -- return map->read8(map, addr); -+ return map_read8(map, addr); - } else if (cfi_buswidth_is_2()) { -- return map->read16(map, addr); -+ return map_read16(map, addr); - } else if (cfi_buswidth_is_4()) { -- return map->read32(map, addr); -+ return map_read32(map, addr); - } else if (cfi_buswidth_is_8()) { -- return map->read64(map, addr); -+ return map_read64(map, addr); - } else { - return 0; - } -@@ -406,13 +425,13 @@ - static inline void cfi_write(struct map_info *map, cfi_word val, __u32 addr) - { - if (cfi_buswidth_is_1()) { -- map->write8(map, val, addr); -+ map_write8(map, val, addr); - } else if (cfi_buswidth_is_2()) { -- map->write16(map, val, addr); -+ map_write16(map, val, addr); - } else if (cfi_buswidth_is_4()) { -- map->write32(map, val, addr); -+ map_write32(map, val, addr); - } else if (cfi_buswidth_is_8()) { -- map->write64(map, val, addr); -+ map_write64(map, val, addr); - } - } - -@@ -443,13 +462,13 @@ - static inline __u8 cfi_read_query(struct map_info *map, __u32 addr) - { - if (cfi_buswidth_is_1()) { -- return map->read8(map, addr); -+ return map_read8(map, addr); - } else if (cfi_buswidth_is_2()) { -- return cfi16_to_cpu(map->read16(map, addr)); -+ return cfi16_to_cpu(map_read16(map, addr)); - } else if (cfi_buswidth_is_4()) { -- return cfi32_to_cpu(map->read32(map, addr)); -+ return cfi32_to_cpu(map_read32(map, addr)); - } else if (cfi_buswidth_is_8()) { -- return cfi64_to_cpu(map->read64(map, addr)); -+ return cfi64_to_cpu(map_read64(map, addr)); - } else { - return 0; - } -@@ -479,5 +498,19 @@ - spin_unlock_bh(mutex); - } - -+struct cfi_extquery *cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, -+ const char* name); -+ -+struct cfi_fixup { -+ __u16 mfr; -+ __u16 id; -+ void (*fixup)(struct map_info *map, void* param); -+ void* param; -+}; -+ -+#define CFI_MFR_ANY 0xffff -+#define CFI_ID_ANY 0xffff -+ -+void cfi_fixup(struct map_info *map, struct cfi_fixup* fixups); - - #endif /* __MTD_CFI_H__ */ -diff -Nurb linux-mips-2.4.24-pre2/include/linux/mtd/compatmac.h linux/include/linux/mtd/compatmac.h ---- linux-mips-2.4.24-pre2/include/linux/mtd/compatmac.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/mtd/compatmac.h 2004-11-17 18:17:59.210287928 +0100 -@@ -1,573 +1,152 @@ -- - /* -- * mtd/include/compatmac.h -- * -- * $Id$ -+ * $Id$ - * - * Extensions and omissions from the normal 'linux/compatmac.h' - * files. hopefully this will end up empty as the 'real' one - * becomes fully-featured. - */ - -- --/* First, include the parts which the kernel is good enough to provide -- * to us -- */ -- - #ifndef __LINUX_MTD_COMPATMAC_H__ - #define __LINUX_MTD_COMPATMAC_H__ - --#include --#include --#ifndef LINUX_VERSION_CODE - #include --#endif -- --#ifndef VERSION_CODE --# define VERSION_CODE(vers,rel,seq) ( ((vers)<<16) | ((rel)<<8) | (seq) ) --#endif --#ifndef KERNEL_VERSION --# define KERNEL_VERSION(a,b,c) VERSION_CODE(a,b,c) --#endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,0,0) --# error "This kernel is too old: not supported by this file" --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) --#include /* used later in this header */ -- --#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) --#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) -- --typedef struct wait_queue * wait_queue_head_t; -- --#define DECLARE_WAITQUEUE(x,y) struct wait_queue x = {y,NULL} --#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue *x = NULL --#define init_waitqueue_head init_waitqueue --#define DECLARE_MUTEX(x) struct semaphore x = MUTEX --#define DECLARE_MUTEX_LOCKED(x) struct semaphore x = MUTEX_LOCKED -- --/* from sysdep-2.1.h */ --# include --# define access_ok(t,a,sz) (verify_area((t),(a),(sz)) ? 0 : 1) --# define verify_area_20 verify_area --# define copy_to_user(t,f,n) (memcpy_tofs(t,f,n), 0) --# define __copy_to_user(t,f,n) copy_to_user((t),(f),(n)) --# define copy_to_user_ret(t,f,n,r) copy_to_user((t),(f),(n)) --# define copy_from_user(t,f,n) (memcpy_fromfs((t),(f),(n)), 0) --# define __copy_from_user(t,f,n) copy_from_user((t),(f),(n)) --# define copy_from_user_ret(t,f,n,r) copy_from_user((t),(f),(n)) --//xxx # define PUT_USER(val,add) (put_user((val),(add)), 0) --# define Put_user(val,add) (put_user((val),(add)), 0) --# define __PUT_USER(val,add) PUT_USER((val),(add)) --# define PUT_USER_RET(val,add,ret) PUT_USER((val),(add)) --# define GET_USER(dest,add) ((dest)=get_user((add)), 0) --# define __GET_USER(dest,add) GET_USER((dest),(add)) --# define GET_USER_RET(dest,add,ret) GET_USER((dest),(add)) -- --#define ioremap(offset,size) vremap(offset,size) --#define iounmap(adr) /* */ -- --#define EXPORT_SYMBOL(s) /* */ --#define EXPORT_SYMBOL_NOVERS(s) /* */ -- --/* 2.1.10 and 2.1.43 introduced new functions. They are worth using */ -- --#if LINUX_VERSION_CODE < VERSION_CODE(2,1,10) -- --# include --# ifdef __LITTLE_ENDIAN --# define cpu_to_le16(x) (x) --# define cpu_to_le32(x) (x) --# define cpu_to_be16(x) htons((x)) --# define cpu_to_be32(x) htonl((x)) --# else --# define cpu_to_be16(x) (x) --# define cpu_to_be32(x) (x) -- extern inline __u16 cpu_to_le16(__u16 x) { return (x<<8) | (x>>8);} -- extern inline __u32 cpu_to_le32(__u32 x) { return((x>>24) | -- ((x>>8)&0xff00) | ((x<<8)&0xff0000) | (x<<24));} --# endif -- --# define le16_to_cpu(x) cpu_to_le16(x) --# define le32_to_cpu(x) cpu_to_le32(x) --# define be16_to_cpu(x) cpu_to_be16(x) --# define be32_to_cpu(x) cpu_to_be32(x) -- --#endif -- --#if LINUX_VERSION_CODE < VERSION_CODE(2,1,43) --# define cpu_to_le16p(addr) (cpu_to_le16(*(addr))) --# define cpu_to_le32p(addr) (cpu_to_le32(*(addr))) --# define cpu_to_be16p(addr) (cpu_to_be16(*(addr))) --# define cpu_to_be32p(addr) (cpu_to_be32(*(addr))) -- -- extern inline void cpu_to_le16s(__u16 *a) {*a = cpu_to_le16(*a);} -- extern inline void cpu_to_le32s(__u16 *a) {*a = cpu_to_le32(*a);} -- extern inline void cpu_to_be16s(__u16 *a) {*a = cpu_to_be16(*a);} -- extern inline void cpu_to_be32s(__u16 *a) {*a = cpu_to_be32(*a);} -- --# define le16_to_cpup(x) cpu_to_le16p(x) --# define le32_to_cpup(x) cpu_to_le32p(x) --# define be16_to_cpup(x) cpu_to_be16p(x) --# define be32_to_cpup(x) cpu_to_be32p(x) -- --# define le16_to_cpus(x) cpu_to_le16s(x) --# define le32_to_cpus(x) cpu_to_le32s(x) --# define be16_to_cpus(x) cpu_to_be16s(x) --# define be32_to_cpus(x) cpu_to_be32s(x) --#endif -- --// from 2.2, linux/types.h --#ifndef __BIT_TYPES_DEFINED__ --#define __BIT_TYPES_DEFINED__ -- --typedef __u8 u_int8_t; --typedef __s8 int8_t; --typedef __u16 u_int16_t; --typedef __s16 int16_t; --typedef __u32 u_int32_t; --typedef __s32 int32_t; -- --#endif /* !(__BIT_TYPES_DEFINED__) */ -- --#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) -- typedef struct { } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { } --#else -- typedef struct { int gcc_is_buggy; } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } --#endif -- --#define spin_lock_init(lock) do { } while(0) --#define spin_lock(lock) (void)(lock) /* Not "unused variable". */ --#define spin_trylock(lock) (1) --#define spin_unlock_wait(lock) do { } while(0) --#define spin_unlock(lock) do { } while(0) --#define spin_lock_irq(lock) cli() --#define spin_unlock_irq(lock) sti() -- --#define spin_lock_irqsave(lock, flags) \ -- do { save_flags(flags); cli(); } while (0) --#define spin_unlock_irqrestore(lock, flags) \ -- restore_flags(flags) -- --// Doesn't work when tqueue.h is included. --// #define queue_task queue_task_irq_off --#define tty_flip_buffer_push(tty) queue_task_irq_off(&tty->flip.tqueue, &tq_timer) --#define signal_pending(current) (current->signal & ~current->blocked) --#define schedule_timeout(to) do {current->timeout = jiffies + (to);schedule ();} while (0) --#define time_after(t1,t2) (((long)t1-t2) > 0) -- --#else -- #include --#endif // LINUX_VERSION_CODE < 0x020100 -- -- --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) --#include --#endif -- --/* Modularization issues */ --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,18) --# define __USE_OLD_SYMTAB__ --# define EXPORT_NO_SYMBOLS register_symtab(NULL); --# define REGISTER_SYMTAB(tab) register_symtab(tab) --#else --# define REGISTER_SYMTAB(tab) /* nothing */ --#endif -- --#ifdef __USE_OLD_SYMTAB__ --# define __MODULE_STRING(s) /* nothing */ --# define MODULE_PARM(v,t) /* nothing */ --# define MODULE_PARM_DESC(v,t) /* nothing */ --# define MODULE_AUTHOR(n) /* nothing */ --# define MODULE_DESCRIPTION(d) /* nothing */ --# define MODULE_SUPPORTED_DEVICE(n) /* nothing */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) -+#error "This kernel is too old: not supported by this file" - #endif - --/* -- * "select" changed in 2.1.23. The implementation is twin, but this -- * header is new -- */ --#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,22) --# include --#else --# define __USE_OLD_SELECT__ --#endif -+ /* O(1) scheduler stuff. */ - --/* Other change in the fops are solved using pseudo-types */ --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) --# define lseek_t long long --# define lseek_off_t long long --#else --# define lseek_t int --# define lseek_off_t off_t --#endif -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,5) && !defined(__rh_config_h__) -+#include -+static inline void __recalc_sigpending(void) -+{ -+ recalc_sigpending(current); -+} -+#undef recalc_sigpending -+#define recalc_sigpending() __recalc_sigpending () - --/* changed the prototype of read/write */ -+#define set_user_nice(tsk, n) do { (tsk)->nice = n; } while(0) - --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) || defined(__alpha__) --# define count_t unsigned long --# define read_write_t long --#else --# define count_t int --# define read_write_t int - #endif - - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,31) --# define release_t void --# define release_return(x) return --#else --# define release_t int --# define release_return(x) return (x) --#endif -- --#if LINUX_VERSION_CODE < 0x20300 --#define __exit --#endif --#if LINUX_VERSION_CODE < 0x20200 --#define __init --#else --#include --#endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) --#define init_MUTEX(x) do {*(x) = MUTEX;} while (0) --#define init_MUTEX_LOCKED(x) do {*(x) = MUTEX_LOCKED;} while (0) --#endif -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20) - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) --#define RQFUNC_ARG void --#define blkdev_dequeue_request(req) do {CURRENT = req->next;} while (0) --#else --#define RQFUNC_ARG request_queue_t *q -+#ifndef yield -+#define yield() do { set_current_state(TASK_RUNNING); schedule(); } while(0) - #endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,32) --#define blk_cleanup_queue(nr) do {blk_dev[nr].request_fn = 0;} while(0) --#define BLK_DEFAULT_QUEUE(nr) (blk_dev[nr].request_fn) --#define blk_init_queue(q, rq) do {q = rq;} while(0) -+#ifndef minor -+#define major(d) (MAJOR(to_kdev_t(d))) -+#define minor(d) (MINOR(to_kdev_t(d))) - #endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0) --#ifdef CONFIG_MODULES --#define __MOD_INC_USE_COUNT(mod) \ -- (atomic_inc(&(mod)->uc.usecount), (mod)->flags |= MOD_VISITED|MOD_USED_ONCE) --#define __MOD_DEC_USE_COUNT(mod) \ -- (atomic_dec(&(mod)->uc.usecount), (mod)->flags |= MOD_VISITED) --#else --#define __MOD_INC_USE_COUNT(mod) --#define __MOD_DEC_USE_COUNT(mod) --#endif -+#ifndef mk_kdev -+#define mk_kdev(ma,mi) MKDEV(ma,mi) -+#define kdev_t_to_nr(x) (x) - #endif - -+#define need_resched() (current->need_resched) -+#define cond_resched() do { if need_resched() { yield(); } } while(0) - --#ifndef HAVE_INTER_MODULE --static inline void *inter_module_get(char *x) {return NULL;} --static inline void *inter_module_get_request(char *x, char *y) {return NULL;} --static inline void inter_module_put(const char *x) {} --static inline void inter_module_register(const char *x, struct module *y, const void *z) {} --static inline void inter_module_unregister(const char *x) {} -+#endif /* < 2.4.20 */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,73) -+#define iminor(i) minor((i)->i_rdev) -+#define imajor(i) major((i)->i_rdev) -+#define old_encode_dev(d) ( (major(d)<<8) | minor(d) ) -+#define old_decode_dev(rdev) (kdev_t_to_nr(mk_kdev((rdev)>>8, (rdev)&0xff))) -+#define old_valid_dev(d) (1) - #endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,61) - --#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue *x = NULL --#define init_waitqueue_head init_waitqueue -+#include - -+#ifdef __rh_config_h__ -+#define sigmask_lock sighand->siglock -+#define sig sighand - #endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -- --static inline int try_inc_mod_count(struct module *mod) -+static inline void __daemonize_modvers(void) - { --#ifdef CONFIG_MODULES -- if (mod) -- __MOD_INC_USE_COUNT(mod); --#endif -- return 1; --} --#endif -+ daemonize(); - -+ spin_lock_irq(¤t->sigmask_lock); -+ sigfillset(¤t->blocked); -+ recalc_sigpending(); -+ spin_unlock_irq(¤t->sigmask_lock); -+} -+#undef daemonize -+#define daemonize(fmt, ...) do { \ -+ snprintf(current->comm, sizeof(current->comm), fmt ,##__VA_ARGS__); \ -+ __daemonize_modvers(); \ -+ } while(0) - --/* Yes, I'm aware that it's a fairly ugly hack. -- Until the __constant_* macros appear in Linus' own kernels, this is -- the way it has to be done. -- DW 19/1/00 -- */ -- --#include -- --#ifndef __constant_cpu_to_le16 -- --#ifdef __BIG_ENDIAN --#define __constant_cpu_to_le64(x) ___swab64((x)) --#define __constant_le64_to_cpu(x) ___swab64((x)) --#define __constant_cpu_to_le32(x) ___swab32((x)) --#define __constant_le32_to_cpu(x) ___swab32((x)) --#define __constant_cpu_to_le16(x) ___swab16((x)) --#define __constant_le16_to_cpu(x) ___swab16((x)) --#define __constant_cpu_to_be64(x) ((__u64)(x)) --#define __constant_be64_to_cpu(x) ((__u64)(x)) --#define __constant_cpu_to_be32(x) ((__u32)(x)) --#define __constant_be32_to_cpu(x) ((__u32)(x)) --#define __constant_cpu_to_be16(x) ((__u16)(x)) --#define __constant_be16_to_cpu(x) ((__u16)(x)) --#else --#ifdef __LITTLE_ENDIAN --#define __constant_cpu_to_le64(x) ((__u64)(x)) --#define __constant_le64_to_cpu(x) ((__u64)(x)) --#define __constant_cpu_to_le32(x) ((__u32)(x)) --#define __constant_le32_to_cpu(x) ((__u32)(x)) --#define __constant_cpu_to_le16(x) ((__u16)(x)) --#define __constant_le16_to_cpu(x) ((__u16)(x)) --#define __constant_cpu_to_be64(x) ___swab64((x)) --#define __constant_be64_to_cpu(x) ___swab64((x)) --#define __constant_cpu_to_be32(x) ___swab32((x)) --#define __constant_be32_to_cpu(x) ___swab32((x)) --#define __constant_cpu_to_be16(x) ___swab16((x)) --#define __constant_be16_to_cpu(x) ___swab16((x)) --#else --#error No (recognised) endianness defined (unless it,s PDP) --#endif /* __LITTLE_ENDIAN */ --#endif /* __BIG_ENDIAN */ -- --#endif /* ifndef __constant_cpu_to_le16 */ -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -- #define mod_init_t int __init -- #define mod_exit_t void --#else -- #define mod_init_t static int __init -- #define mod_exit_t static void __exit --#endif -- --#ifndef THIS_MODULE --#ifdef MODULE --#define THIS_MODULE (&__this_module) --#else --#define THIS_MODULE (NULL) --#endif --#endif -- --#if LINUX_VERSION_CODE < 0x20300 --#include --#define spin_lock_bh(lock) do {start_bh_atomic();spin_lock(lock);}while(0) --#define spin_unlock_bh(lock) do {spin_unlock(lock);end_bh_atomic();}while(0) --#else --#include --#include --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) --#define set_current_state(state_value) \ -- do { current->state = (state_value); } while (0) --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0) --static inline int invalidate_device(kdev_t dev, int do_sync) { -+static inline int dequeue_signal_lock(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) -+{ -+ unsigned long flags; -+ unsigned long ret; - -- if (do_sync) -- fsync_dev(dev); -+ spin_lock_irqsave(¤t->sigmask_lock, flags); -+ ret = dequeue_signal(mask, info); -+ spin_unlock_irqrestore(¤t->sigmask_lock, flags); - -- invalidate_buffers(dev); -- return 0; -+ return ret; - } --#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,4,5) --static inline int invalidate_device(kdev_t dev, int do_sync) { -- struct super_block *sb = get_super(dev); -- int res = 0; - -- if (do_sync) -- fsync_dev(dev); -- -- if (sb) -- res = invalidate_inodes(sb); -+static inline int allow_signal(int sig) -+{ -+ if (sig < 1 || sig > _NSIG) -+ return -EINVAL; - -- invalidate_buffers(dev); -- return res; -+ spin_lock_irq(¤t->sigmask_lock); -+ sigdelset(¤t->blocked, sig); -+ recalc_sigpending(); -+ /* Make sure the kernel neither eats it now converts to SIGKILL */ -+ current->sig->action[sig-1].sa.sa_handler = (void *)2; -+ spin_unlock_irq(¤t->sigmask_lock); -+ return 0; - } --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) --#undef min --#undef max --#undef min_t --#undef max_t --/* -- * min()/max() macros that also do -- * strict type-checking.. See the -- * "unnecessary" pointer comparison. -- */ --#define min(x,y) ({ \ -- const typeof(x) _x = (x); \ -- const typeof(y) _y = (y); \ -- (void) (&_x == &_y); \ -- _x < _y ? _x : _y; }) -- --#define max(x,y) ({ \ -- const typeof(x) _x = (x); \ -- const typeof(y) _y = (y); \ -- (void) (&_x == &_y); \ -- _x > _y ? _x : _y; }) -- --/* -- * ..and if you can't take the strict -- * types, you can specify one yourself. -- * -- * Or not use min/max at all, of course. -- */ --#define min_t(type,x,y) \ -- ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) --#define max_t(type,x,y) \ -- ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,7) --struct completion { -- struct semaphore s; --}; -- --#define complete(c) up(&(c)->s) --#define wait_for_completion(c) down(&(c)->s) --#define init_completion(c) init_MUTEX_LOCKED(&(c)->s); -- --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9) --/* This came later */ --#define complete_and_exit(c, r) do { complete(c); do_exit(r); } while(0) --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9) || \ -- (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) && !defined(__rh_config_h__)) -+static inline int disallow_signal(int sig) -+{ -+ if (sig < 1 || sig > _NSIG) -+ return -EINVAL; - --#include -+ spin_lock_irq(¤t->sigmask_lock); -+ sigaddset(¤t->blocked, sig); -+ recalc_sigpending(); - --static inline void add_gendisk(struct gendisk *gp) --{ -- gp->next = gendisk_head; -- gendisk_head = gp; -+ current->sig->action[sig-1].sa.sa_handler = SIG_DFL; -+ spin_unlock_irq(¤t->sigmask_lock); -+ return 0; - } - --static inline void del_gendisk(struct gendisk *gp) --{ -- struct gendisk *gd, **gdp; -+#undef sighand -+#undef sigmask_lock - -- for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) -- if (*gdp == gp) { -- gd = *gdp; *gdp = gd->next; -- break; -- } --} -+#define PF_FREEZE 0 -+#define refrigerator(x) do { ; } while(0) - #endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) && defined(MODULE) -+ /* Module bits */ - --#define module_init(func) \ --mod_init_t init_module(void) { \ -- return func(); \ --} - --#define module_exit(func) \ --mod_exit_t cleanup_module(void) { \ -- return func(); \ --} -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60) -+#define try_module_get(m) try_inc_mod_count(m) -+#define __module_get(m) do { if (!try_inc_mod_count(m)) BUG(); } while(0) -+#define module_put(m) do { if (m) __MOD_DEC_USE_COUNT((struct module *)(m)); } while(0) -+#define set_module_owner(x) do { x->owner = THIS_MODULE; } while(0) - #endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9) || \ -- (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) && !defined(__rh_config_h__)) --#define MODULE_LICENSE(x) /* */ --#endif - --/* Removed for 2.4.21 kernel. This really should have been renamed -- when it was changed -- this is a PITA */ --#if 0 && LINUX_VERSION_CODE < KERNEL_VERSION(2,5,5) --#include --static inline void __recalc_sigpending(void) --{ -- recalc_sigpending(current); --} --#undef recalc_sigpending --#define recalc_sigpending() __recalc_sigpending () --#endif -+ /* Random filesystem stuff, only for JFFS2 really */ - - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,5) - #define parent_ino(d) ((d)->d_parent->d_inode->i_ino) - #endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,3) --#define need_resched() (current->need_resched) --#define cond_resched() do { if need_resched() schedule(); } while(0) --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19) --#ifndef yield --#define yield() do { set_current_state(TASK_RUNNING); schedule(); } while(0) --#endif --#ifndef minor --#define major(d) (MAJOR(to_kdev_t(d))) --#define minor(d) (MINOR(to_kdev_t(d))) --#endif --#ifndef mk_kdev --#define mk_kdev(ma,mi) MKDEV(ma,mi) --#define kdev_t_to_nr(x) (x) --#endif --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -- /* Is this right? */ --#define set_user_nice(tsk, n) do { (tsk)->priority = 20-(n); } while(0) --#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,4,21) && !defined(RED_HAT_LINUX_KERNEL) --#define set_user_nice(tsk, n) do { (tsk)->nice = n; } while(0) --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,21) --#define rq_data_dir(x) ((x)->cmd) --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -- --#define IS_REQ_CMD(req) (1) -- --#define QUEUE_LOCK(q) (&io_request_lock) -- --#define BLK_INIT_QUEUE(q, req, lock) blk_init_queue((q), (req)) -- --#else /* > 2.5.0 */ -- --#define IS_REQ_CMD(req) ((req)->flags & REQ_CMD) -- --#define QUEUE_LOCK(q) ((q)->queue_lock) -- --#define BLK_INIT_QUEUE(q, req, lock) blk_init_queue((q), (req), (lock)) -- --#endif -- --/* Removed cos it broke stuff. Where is this required anyway? -- * #ifndef QUEUE_EMPTY -- * #define QUEUE_EMPTY (!CURRENT) -- * #endif -- */ --#if LINUX_VERSION_CODE < 0x20300 --#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].plug_tq.sync) --#elif LINUX_VERSION_CODE < 0x20500 //FIXME (Si) --#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].request_queue.plugged) --#else --#define QUEUE_PLUGGED (blk_queue_plugged(QUEUE)) --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14) --#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT --#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT --#else --#define BLK_INC_USE_COUNT do {} while(0) --#define BLK_DEC_USE_COUNT do {} while(0) --#endif -- - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,12) - #define PageUptodate(x) Page_Uptodate(x) - #endif -@@ -580,4 +159,31 @@ - #define generic_file_readonly_mmap generic_file_mmap - #endif - -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,70) -+ -+#include -+#include -+ -+static inline char *strlcpy(char *dest, const char *src, int len) -+{ -+ dest[len-1] = 0; -+ return strncpy(dest, src, len-1); -+} -+ -+static inline int do_old_request_module(const char *mod) -+{ -+ return request_module(mod); -+} -+#undef request_module -+#define request_module(fmt, ...) \ -+ ({ char modname[32]; snprintf(modname, 31, fmt ,##__VA_ARGS__); do_old_request_module(modname); }) -+ -+#endif /* 2.5.70 */ -+ -+#ifndef container_of -+#define container_of(ptr, type, member) ({ \ -+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ -+ (type *)( (char *)__mptr - offsetof(type,member) );}) -+#endif -+ - #endif /* __LINUX_MTD_COMPATMAC_H__ */ -diff -Nurb linux-mips-2.4.24-pre2/include/linux/mtd/doc2000.h linux/include/linux/mtd/doc2000.h ---- linux-mips-2.4.24-pre2/include/linux/mtd/doc2000.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/mtd/doc2000.h 2004-11-17 18:17:59.212287624 +0100 -@@ -1,13 +1,21 @@ -- --/* Linux driver for Disk-On-Chip 2000 */ --/* (c) 1999 Machine Vision Holdings, Inc. */ --/* Author: David Woodhouse */ --/* $Id$ */ -+/* -+ * Linux driver for Disk-On-Chip devices -+ * -+ * Copyright (C) 1999 Machine Vision Holdings, Inc. -+ * Copyright (C) 2001-2003 David Woodhouse -+ * Copyright (C) 2002-2003 Greg Ungerer -+ * Copyright (C) 2002-2003 SnapGear Inc -+ * -+ * $Id$ -+ * -+ * Released under GPL -+ */ - - #ifndef __MTD_DOC2000_H__ - #define __MTD_DOC2000_H__ - - #include -+#include - - #define DoC_Sig1 0 - #define DoC_Sig2 1 -@@ -38,18 +46,47 @@ - #define DoC_Mil_CDSN_IO 0x0800 - #define DoC_2k_CDSN_IO 0x1800 - -+#define DoC_Mplus_NOP 0x1002 -+#define DoC_Mplus_AliasResolution 0x1004 -+#define DoC_Mplus_DOCControl 0x1006 -+#define DoC_Mplus_AccessStatus 0x1008 -+#define DoC_Mplus_DeviceSelect 0x1008 -+#define DoC_Mplus_Configuration 0x100a -+#define DoC_Mplus_OutputControl 0x100c -+#define DoC_Mplus_FlashControl 0x1020 -+#define DoC_Mplus_FlashSelect 0x1022 -+#define DoC_Mplus_FlashCmd 0x1024 -+#define DoC_Mplus_FlashAddress 0x1026 -+#define DoC_Mplus_FlashData0 0x1028 -+#define DoC_Mplus_FlashData1 0x1029 -+#define DoC_Mplus_ReadPipeInit 0x102a -+#define DoC_Mplus_LastDataRead 0x102c -+#define DoC_Mplus_LastDataRead1 0x102d -+#define DoC_Mplus_WritePipeTerm 0x102e -+#define DoC_Mplus_ECCSyndrome0 0x1040 -+#define DoC_Mplus_ECCSyndrome1 0x1041 -+#define DoC_Mplus_ECCSyndrome2 0x1042 -+#define DoC_Mplus_ECCSyndrome3 0x1043 -+#define DoC_Mplus_ECCSyndrome4 0x1044 -+#define DoC_Mplus_ECCSyndrome5 0x1045 -+#define DoC_Mplus_ECCConf 0x1046 -+#define DoC_Mplus_Toggle 0x1046 -+#define DoC_Mplus_DownloadStatus 0x1074 -+#define DoC_Mplus_CtrlConfirm 0x1076 -+#define DoC_Mplus_Power 0x1fff -+ - /* How to access the device? - * On ARM, it'll be mmap'd directly with 32-bit wide accesses. - * On PPC, it's mmap'd and 16-bit wide. - * Others use readb/writeb - */ - #if defined(__arm__) --#define ReadDOC_(adr, reg) ((unsigned char)(*(__u32 *)(((unsigned long)adr)+((reg)<<2)))) --#define WriteDOC_(d, adr, reg) do{ *(__u32 *)(((unsigned long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0) -+#define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)))) -+#define WriteDOC_(d, adr, reg) do{ *(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0) - #define DOC_IOREMAP_LEN 0x8000 - #elif defined(__ppc__) --#define ReadDOC_(adr, reg) ((unsigned char)(*(__u16 *)(((unsigned long)adr)+((reg)<<1)))) --#define WriteDOC_(d, adr, reg) do{ *(__u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0) -+#define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u16 *)(((unsigned long)adr)+((reg)<<1)))) -+#define WriteDOC_(d, adr, reg) do{ *(volatile __u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0) - #define DOC_IOREMAP_LEN 0x4000 - #else - #define ReadDOC_(adr, reg) readb(((unsigned long)adr) + (reg)) -@@ -71,13 +108,21 @@ - #define DOC_MODE_RESERVED1 2 - #define DOC_MODE_RESERVED2 3 - --#define DOC_MODE_MDWREN 4 - #define DOC_MODE_CLR_ERR 0x80 -+#define DOC_MODE_RST_LAT 0x10 -+#define DOC_MODE_BDECT 0x08 -+#define DOC_MODE_MDWREN 0x04 - - #define DOC_ChipID_Doc2k 0x20 -+#define DOC_ChipID_Doc2kTSOP 0x21 /* internal number for MTD */ - #define DOC_ChipID_DocMil 0x30 -+#define DOC_ChipID_DocMilPlus32 0x40 -+#define DOC_ChipID_DocMilPlus16 0x41 - - #define CDSN_CTRL_FR_B 0x80 -+#define CDSN_CTRL_FR_B0 0x40 -+#define CDSN_CTRL_FR_B1 0x80 -+ - #define CDSN_CTRL_ECC_IO 0x20 - #define CDSN_CTRL_FLASH_IO 0x10 - #define CDSN_CTRL_WP 0x08 -@@ -93,6 +138,10 @@ - #define DOC_ECC_RESV 0x02 - #define DOC_ECC_IGNORE 0x01 - -+#define DOC_FLASH_CE 0x80 -+#define DOC_FLASH_WP 0x40 -+#define DOC_FLASH_BANK 0x02 -+ - /* We have to also set the reserved bit 1 for enable */ - #define DOC_ECC_EN (DOC_ECC__EN | DOC_ECC_RESV) - #define DOC_ECC_DIS (DOC_ECC_RESV) -@@ -107,9 +156,12 @@ - #define MAX_FLOORS 4 - #define MAX_CHIPS 4 - --#define MAX_FLOORS_MIL 4 -+#define MAX_FLOORS_MIL 1 - #define MAX_CHIPS_MIL 1 - -+#define MAX_FLOORS_MPLUS 2 -+#define MAX_CHIPS_MPLUS 1 -+ - #define ADDR_COLUMN 1 - #define ADDR_PAGE 2 - #define ADDR_COLUMN_PAGE 3 -@@ -118,7 +170,7 @@ - unsigned long physadr; - unsigned long virtadr; - unsigned long totlen; -- char ChipID; /* Type of DiskOnChip */ -+ unsigned char ChipID; /* Type of DiskOnChip */ - int ioreg; - - unsigned long mfr; /* Flash IDs - only one type of flash per device */ -@@ -126,6 +178,7 @@ - int chipshift; - char page256; - char pageadrlen; -+ char interleave; /* Internal interleaving - Millennium Plus style */ - unsigned long erasesize; - - int curfloor; -diff -Nurb linux-mips-2.4.24-pre2/include/linux/mtd/flashchip.h linux/include/linux/mtd/flashchip.h ---- linux-mips-2.4.24-pre2/include/linux/mtd/flashchip.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/mtd/flashchip.h 2004-11-17 18:17:59.214287320 +0100 -@@ -6,7 +6,7 @@ - * - * (C) 2000 Red Hat. GPLd. - * -- * $Id$ -+ * $Id$ - * - */ - -@@ -58,6 +58,11 @@ - int ref_point_counter; - flstate_t state; - flstate_t oldstate; -+ -+ int write_suspended:1; -+ int erase_suspended:1; -+ unsigned long in_progress_block_addr; -+ - spinlock_t *mutex; - spinlock_t _spinlock; /* We do it like this because sometimes they'll be shared. */ - wait_queue_head_t wq; /* Wait on here when we're waiting for the chip -diff -Nurb linux-mips-2.4.24-pre2/include/linux/mtd/gen_probe.h linux/include/linux/mtd/gen_probe.h ---- linux-mips-2.4.24-pre2/include/linux/mtd/gen_probe.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/mtd/gen_probe.h 2004-11-17 18:17:59.216287016 +0100 -@@ -1,7 +1,7 @@ - /* - * (C) 2001, 2001 Red Hat, Inc. - * GPL'd -- * $Id$ -+ * $Id$ - */ - - #ifndef __LINUX_MTD_GEN_PROBE_H__ -@@ -10,12 +10,12 @@ - #include - #include - #include -+#include - - struct chip_probe { - char *name; - int (*probe_chip)(struct map_info *map, __u32 base, -- struct flchip *chips, struct cfi_private *cfi); -- -+ unsigned long *chip_map, struct cfi_private *cfi); - }; - - struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp); -diff -Nurb linux-mips-2.4.24-pre2/include/linux/mtd/inftl.h linux/include/linux/mtd/inftl.h ---- linux-mips-2.4.24-pre2/include/linux/mtd/inftl.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/include/linux/mtd/inftl.h 2004-11-17 18:17:59.219286560 +0100 -@@ -0,0 +1,129 @@ -+/* -+ * inftl.h -- defines to support the Inverse NAND Flash Translation Layer -+ * -+ * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) -+ * -+ * $Id$ -+ */ -+ -+#ifndef __MTD_INFTL_H__ -+#define __MTD_INFTL_H__ -+ -+#include -+#include -+#include -+ -+#define OSAK_VERSION 0x5120 -+#define PERCENTUSED 98 -+ -+#define SECTORSIZE 512 -+ -+#ifndef INFTL_MAJOR -+#define INFTL_MAJOR 94 -+#endif -+#define INFTL_PARTN_BITS 4 -+ -+/* Block Control Information */ -+ -+struct inftl_bci { -+ __u8 ECCsig[6]; -+ __u8 Status; -+ __u8 Status1; -+} __attribute__((packed)); -+ -+struct inftl_unithead1 { -+ __u16 virtualUnitNo; -+ __u16 prevUnitNo; -+ __u8 ANAC; -+ __u8 NACs; -+ __u8 parityPerField; -+ __u8 discarded; -+} __attribute__((packed)); -+ -+struct inftl_unithead2 { -+ __u8 parityPerField; -+ __u8 ANAC; -+ __u16 prevUnitNo; -+ __u16 virtualUnitNo; -+ __u8 NACs; -+ __u8 discarded; -+} __attribute__((packed)); -+ -+struct inftl_unittail { -+ __u8 Reserved[4]; -+ __u16 EraseMark; -+ __u16 EraseMark1; -+} __attribute__((packed)); -+ -+union inftl_uci { -+ struct inftl_unithead1 a; -+ struct inftl_unithead2 b; -+ struct inftl_unittail c; -+}; -+ -+struct inftl_oob { -+ struct inftl_bci b; -+ union inftl_uci u; -+}; -+ -+ -+/* INFTL Media Header */ -+ -+struct INFTLPartition { -+ __u32 virtualUnits; -+ __u32 firstUnit; -+ __u32 lastUnit; -+ __u32 flags; -+ __u32 spareUnits; -+ __u32 Reserved0; -+ __u32 Reserved1; -+} __attribute__((packed)); -+ -+struct INFTLMediaHeader { -+ char bootRecordID[8]; -+ __u32 NoOfBootImageBlocks; -+ __u32 NoOfBinaryPartitions; -+ __u32 NoOfBDTLPartitions; -+ __u32 BlockMultiplierBits; -+ __u32 FormatFlags; -+ __u32 OsakVersion; -+ __u32 PercentUsed; -+ struct INFTLPartition Partitions[4]; -+} __attribute__((packed)); -+ -+/* Partition flag types */ -+#define INFTL_BINARY 0x20000000 -+#define INFTL_BDTL 0x40000000 -+#define INFTL_LAST 0x80000000 -+ -+ -+#ifdef __KERNEL__ -+ -+struct INFTLrecord { -+ struct mtd_blktrans_dev mbd; -+ __u16 MediaUnit, SpareMediaUnit; -+ __u32 EraseSize; -+ struct INFTLMediaHeader MediaHdr; -+ int usecount; -+ unsigned char heads; -+ unsigned char sectors; -+ unsigned short cylinders; -+ __u16 numvunits; -+ __u16 firstEUN; -+ __u16 lastEUN; -+ __u16 numfreeEUNs; -+ __u16 LastFreeEUN; /* To speed up finding a free EUN */ -+ int head,sect,cyl; -+ __u16 *PUtable; /* Physical Unit Table */ -+ __u16 *VUtable; /* Virtual Unit Table */ -+ unsigned int nb_blocks; /* number of physical blocks */ -+ unsigned int nb_boot_blocks; /* number of blocks used by the bios */ -+ struct erase_info instr; -+}; -+ -+int INFTL_mount(struct INFTLrecord *s); -+int INFTL_formatblock(struct INFTLrecord *s, int block); -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* __MTD_INFTL_H__ */ -diff -Nurb linux-mips-2.4.24-pre2/include/linux/mtd/jedec.h linux/include/linux/mtd/jedec.h ---- linux-mips-2.4.24-pre2/include/linux/mtd/jedec.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/mtd/jedec.h 2004-11-17 18:17:59.220286408 +0100 -@@ -7,14 +7,13 @@ - * - * See the AMD flash databook for information on how to operate the interface. - * -- * $Id$ -+ * $Id$ - */ - - #ifndef __LINUX_MTD_JEDEC_H__ - #define __LINUX_MTD_JEDEC_H__ - - #include --#include - - #define MAX_JEDEC_CHIPS 16 - -diff -Nurb linux-mips-2.4.24-pre2/include/linux/mtd/map.h linux/include/linux/mtd/map.h ---- linux-mips-2.4.24-pre2/include/linux/mtd/map.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/mtd/map.h 2004-11-17 18:17:59.221286256 +0100 -@@ -1,14 +1,15 @@ - - /* Overhauled routines for dealing with different mmap regions of flash */ --/* $Id$ */ -+/* $Id$ */ - - #ifndef __LINUX_MTD_MAP_H__ - #define __LINUX_MTD_MAP_H__ - - #include - #include --#include --#include -+#include -+#include -+#include - - /* The map stuff is very simple. You fill in your struct map_info with - a handful of routines for accessing the device, making sure they handle -@@ -29,39 +30,44 @@ - struct map_info { - char *name; - unsigned long size; -+ unsigned long phys; -+#define NO_XIP (-1UL) -+ -+ unsigned long virt; -+ void *cached; -+ - int buswidth; /* in octets */ -- __u8 (*read8)(struct map_info *, unsigned long); -- __u16 (*read16)(struct map_info *, unsigned long); -- __u32 (*read32)(struct map_info *, unsigned long); -- __u64 (*read64)(struct map_info *, unsigned long); -+ -+#ifdef CONFIG_MTD_COMPLEX_MAPPINGS -+ u8 (*read8)(struct map_info *, unsigned long); -+ u16 (*read16)(struct map_info *, unsigned long); -+ u32 (*read32)(struct map_info *, unsigned long); -+ u64 (*read64)(struct map_info *, unsigned long); - /* If it returned a 'long' I'd call it readl. - * It doesn't. - * I won't. - * dwmw2 */ - - void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t); -- void (*write8)(struct map_info *, __u8, unsigned long); -- void (*write16)(struct map_info *, __u16, unsigned long); -- void (*write32)(struct map_info *, __u32, unsigned long); -- void (*write64)(struct map_info *, __u64, unsigned long); -+ void (*write8)(struct map_info *, u8, unsigned long); -+ void (*write16)(struct map_info *, u16, unsigned long); -+ void (*write32)(struct map_info *, u32, unsigned long); -+ void (*write64)(struct map_info *, u64, unsigned long); - void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t); - -- u_char * (*point) (struct map_info *, loff_t, size_t); -- void (*unpoint) (struct map_info *, u_char *, loff_t, size_t); -- -+ /* We can perhaps put in 'point' and 'unpoint' methods, if we really -+ want to enable XIP for non-linear mappings. Not yet though. */ -+#endif -+ /* set_vpp() must handle being reentered -- enable, enable, disable -+ must leave it enabled. */ - void (*set_vpp)(struct map_info *, int); -- /* We put these two here rather than a single void *map_priv, -- because we want mappers to be able to have quickly-accessible -- cache for the 'currently-mapped page' without the _extra_ -- redirection that would be necessary. If you need more than -- two longs, turn the second into a pointer. dwmw2 */ -+ - unsigned long map_priv_1; - unsigned long map_priv_2; - void *fldrv_priv; - struct mtd_chip_driver *fldrv; - }; - -- - struct mtd_chip_driver { - struct mtd_info *(*probe)(struct map_info *map); - void (*destroy)(struct mtd_info *); -@@ -74,26 +80,93 @@ - void unregister_mtd_chip_driver(struct mtd_chip_driver *); - - struct mtd_info *do_map_probe(const char *name, struct map_info *map); -+void map_destroy(struct mtd_info *mtd); -+ -+#define ENABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 1); } while(0) -+#define DISABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 0); } while(0) -+ -+#ifdef CONFIG_MTD_COMPLEX_MAPPINGS -+#define map_read8(map, ofs) (map)->read8(map, ofs) -+#define map_read16(map, ofs) (map)->read16(map, ofs) -+#define map_read32(map, ofs) (map)->read32(map, ofs) -+#define map_read64(map, ofs) (map)->read64(map, ofs) -+#define map_copy_from(map, to, from, len) (map)->copy_from(map, to, from, len) -+#define map_write8(map, datum, ofs) (map)->write8(map, datum, ofs) -+#define map_write16(map, datum, ofs) (map)->write16(map, datum, ofs) -+#define map_write32(map, datum, ofs) (map)->write32(map, datum, ofs) -+#define map_write64(map, datum, ofs) (map)->write64(map, datum, ofs) -+#define map_copy_to(map, to, from, len) (map)->copy_to(map, to, from, len) - -+extern void simple_map_init(struct map_info *); -+#define map_is_linear(map) (map->phys != NO_XIP) - --/* -- * Destroy an MTD device which was created for a map device. -- * Make sure the MTD device is already unregistered before calling this -- */ --static inline void map_destroy(struct mtd_info *mtd) --{ -- struct map_info *map = mtd->priv; -- -- if (map->fldrv->destroy) -- map->fldrv->destroy(mtd); --#ifdef CONFIG_MODULES -- if (map->fldrv->module) -- __MOD_DEC_USE_COUNT(map->fldrv->module); -+#else -+static inline u8 map_read8(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readb(map->virt + ofs); -+} -+ -+static inline u16 map_read16(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readw(map->virt + ofs); -+} -+ -+static inline u32 map_read32(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readl(map->virt + ofs); -+} -+ -+static inline u64 map_read64(struct map_info *map, unsigned long ofs) -+{ -+#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */ -+ BUG(); -+ return 0; -+#else -+ return __raw_readll(map->virt + ofs); - #endif -- kfree(mtd); - } - --#define ENABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 1); } while(0) --#define DISABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 0); } while(0) -+static inline void map_write8(struct map_info *map, u8 datum, unsigned long ofs) -+{ -+ __raw_writeb(datum, map->virt + ofs); -+ mb(); -+} -+ -+static inline void map_write16(struct map_info *map, u16 datum, unsigned long ofs) -+{ -+ __raw_writew(datum, map->virt + ofs); -+ mb(); -+} -+ -+static inline void map_write32(struct map_info *map, u32 datum, unsigned long ofs) -+{ -+ __raw_writel(datum, map->virt + ofs); -+ mb(); -+} -+ -+static inline void map_write64(struct map_info *map, u64 datum, unsigned long ofs) -+{ -+#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */ -+ BUG(); -+#else -+ __raw_writell(datum, map->virt + ofs); -+ mb(); -+#endif /* CFI_B8 */ -+} -+ -+static inline void map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -+{ -+ memcpy_fromio(to, map->virt + from, len); -+} -+ -+static inline void map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -+{ -+ memcpy_toio(map->virt + to, from, len); -+} -+ -+#define simple_map_init(map) do { } while (0) -+#define map_is_linear(map) (1) -+ -+#endif /* !CONFIG_MTD_COMPLEX_MAPPINGS */ - - #endif /* __LINUX_MTD_MAP_H__ */ -diff -Nurb linux-mips-2.4.24-pre2/include/linux/mtd/mtd.h linux/include/linux/mtd/mtd.h ---- linux-mips-2.4.24-pre2/include/linux/mtd/mtd.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/mtd/mtd.h 2004-11-17 18:17:59.234284280 +0100 -@@ -1,5 +1,10 @@ -- --/* $Id$ */ -+/* -+ * $Id$ -+ * -+ * Copyright (C) 1999-2003 David Woodhouse et al. -+ * -+ * Released under GPL -+ */ - - #ifndef __MTD_MTD_H__ - #define __MTD_MTD_H__ -@@ -9,7 +14,6 @@ - #include - #include - #include --#include - #include - #include - -@@ -26,7 +30,6 @@ - unsigned char *ptr; - }; - -- - #define MTD_CHAR_MAJOR 90 - #define MTD_BLOCK_MAJOR 31 - #define MAX_MTD_DEVICES 16 -@@ -93,18 +96,23 @@ - #define MEMUNLOCK _IOW('M', 6, struct erase_info_user) - #define MEMGETREGIONCOUNT _IOR('M', 7, int) - #define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user) --#define MEMREADDATA _IOWR('M', 9, struct mtd_oob_buf) --#define MEMWRITEDATA _IOWR('M', 10, struct mtd_oob_buf) -+#define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo) -+ -+struct nand_oobinfo { -+ int useecc; -+ int eccpos[6]; -+}; -+ - - #ifndef __KERNEL__ - - typedef struct mtd_info_user mtd_info_t; - typedef struct erase_info_user erase_info_t; - typedef struct region_info_user region_info_t; -+typedef struct nand_oobinfo nand_oobinfo_t; - - /* User-space ioctl definitions */ - -- - #else /* __KERNEL__ */ - - -@@ -150,10 +158,14 @@ - u_int32_t ecctype; - u_int32_t eccsize; - -+ - // Kernel-only stuff starts here. - char *name; - int index; - -+ // oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO) -+ struct nand_oobinfo oobinfo; -+ - /* Data for variable erase regions. If numeraseregions is zero, - * it means that the whole device has erasesize as given above. - */ -@@ -163,7 +175,6 @@ - /* This really shouldn't be here. It can go away in 2.5 */ - u_int32_t bank_size; - -- struct module *module; - int (*erase) (struct mtd_info *mtd, struct erase_info *instr); - - /* This stuff for eXecute-In-Place */ -@@ -176,8 +187,8 @@ - int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); - int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); - -- int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, int oobsel); -- int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, int oobsel); -+ int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); -+ int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); - - int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); - int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); -@@ -201,10 +212,10 @@ - */ - int (*readv) (struct mtd_info *mtd, struct iovec *vecs, unsigned long count, loff_t from, size_t *retlen); - int (*readv_ecc) (struct mtd_info *mtd, struct iovec *vecs, unsigned long count, loff_t from, -- size_t *retlen, u_char *eccbuf, int oobsel); -+ size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); - int (*writev) (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen); - int (*writev_ecc) (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, -- size_t *retlen, u_char *eccbuf, int oobsel); -+ size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); - - /* Sync */ - void (*sync) (struct mtd_info *mtd); -@@ -218,6 +229,9 @@ - void (*resume) (struct mtd_info *mtd); - - void *priv; -+ -+ struct module *owner; -+ int usecount; - }; - - -@@ -226,31 +240,15 @@ - extern int add_mtd_device(struct mtd_info *mtd); - extern int del_mtd_device (struct mtd_info *mtd); - --extern struct mtd_info *__get_mtd_device(struct mtd_info *mtd, int num); -- --static inline struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) --{ -- struct mtd_info *ret; -+extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); - -- ret = __get_mtd_device(mtd, num); -- -- if (ret && ret->module && !try_inc_mod_count(ret->module)) -- return NULL; -- -- return ret; --} -- --static inline void put_mtd_device(struct mtd_info *mtd) --{ -- if (mtd->module) -- __MOD_DEC_USE_COUNT(mtd->module); --} -+extern void put_mtd_device(struct mtd_info *mtd); - - - struct mtd_notifier { - void (*add)(struct mtd_info *mtd); - void (*remove)(struct mtd_info *mtd); -- struct mtd_notifier *next; -+ struct list_head list; - }; - - -@@ -263,7 +261,6 @@ - int default_mtd_readv(struct mtd_info *mtd, struct iovec *vecs, - unsigned long count, loff_t from, size_t *retlen); - --#ifndef MTDC - #define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args) - #define MTD_POINT(mtd, a,b,c,d) (*(mtd->point))(mtd, a,b,c, (u_char **)(d)) - #define MTD_UNPOINT(mtd, arg) (*(mtd->unpoint))(mtd, (u_char *)arg) -@@ -276,7 +273,6 @@ - #define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args) - #define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args) - #define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0) --#endif /* MTDC */ - - /* - * Debugging macro and defines -@@ -293,7 +289,8 @@ - printk(KERN_INFO args); \ - } while(0) - #else /* CONFIG_MTD_DEBUG */ --#define DEBUG(n, args...) -+#define DEBUG(n, args...) do { } while(0) -+ - #endif /* CONFIG_MTD_DEBUG */ - - #endif /* __KERNEL__ */ -diff -Nurb linux-mips-2.4.24-pre2/include/linux/mtd/nand.h linux/include/linux/mtd/nand.h ---- linux-mips-2.4.24-pre2/include/linux/mtd/nand.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/mtd/nand.h 2004-11-17 18:17:59.236283976 +0100 -@@ -2,10 +2,10 @@ - * linux/include/linux/mtd/nand.h - * - * Copyright (c) 2000 David Woodhouse -- * Steven J. Hill -+ * Steven J. Hill - * Thomas Gleixner - * -- * $Id$ -+ * $Id$ - * - * 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 -@@ -49,12 +49,14 @@ - #define __LINUX_MTD_NAND_H - - #include --#include -+#include -+#include - -+struct mtd_info; - /* - * Searches for a NAND device - */ --extern int nand_scan (struct mtd_info *mtd); -+extern int nand_scan (struct mtd_info *mtd, int max_chips); - - /* - * Constants for hardware specific CLE/ALE/NCE function -@@ -65,6 +67,8 @@ - #define NAND_CTL_CLRCLE 4 - #define NAND_CTL_SETALE 5 - #define NAND_CTL_CLRALE 6 -+#define NAND_CTL_SETWP 7 -+#define NAND_CTL_CLRWP 8 - - /* - * Standard NAND flash commands -@@ -160,24 +164,33 @@ - struct nand_chip { - unsigned long IO_ADDR_R; - unsigned long IO_ADDR_W; -- void (*hwcontrol)(int cmd); -- int (*dev_ready)(void); -+ -+ u_char (*read_byte)(struct mtd_info *mtd); -+ void (*write_byte)(struct mtd_info *mtd, u_char byte); -+ -+ void (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len); -+ void (*read_buf)(struct mtd_info *mtd, u_char *buf, int len); -+ int (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len); -+ void (*select_chip)(struct mtd_info *mtd, int chip); -+ int (*block_bad)(struct mtd_info *mtd, unsigned long pos); -+ void (*hwcontrol)(struct mtd_info *mtd, int cmd); -+ int (*dev_ready)(struct mtd_info *mtd); - void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr); - int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state); -- void (*calculate_ecc)(const u_char *dat, u_char *ecc_code); -- int (*correct_data)(u_char *dat, u_char *read_ecc, u_char *calc_ecc); -- void (*enable_hwecc)(int mode); -+ void (*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code); -+ int (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc); -+ void (*enable_hwecc)(struct mtd_info *mtd, int mode); - int eccmode; - int eccsize; - int chip_delay; -+ int chipshift; - spinlock_t chip_lock; - wait_queue_head_t wq; - nand_state_t state; - int page_shift; - u_char *data_buf; - u_char *data_poi; -- u_char *data_cache; -- int cache_page; -+ void *priv; - }; - - /* -@@ -241,34 +254,4 @@ - */ - #define NAND_BADBLOCK_POS 5 - --#define NAND_NONE_OOB 0 --#define NAND_JFFS2_OOB 1 --#define NAND_YAFFS_OOB 2 -- --#define NAND_NOOB_ECCPOS0 0 --#define NAND_NOOB_ECCPOS1 1 --#define NAND_NOOB_ECCPOS2 2 --#define NAND_NOOB_ECCPOS3 3 --#define NAND_NOOB_ECCPOS4 6 --#define NAND_NOOB_ECCPOS5 7 -- --#define NAND_JFFS2_OOB_ECCPOS0 0 --#define NAND_JFFS2_OOB_ECCPOS1 1 --#define NAND_JFFS2_OOB_ECCPOS2 2 --#define NAND_JFFS2_OOB_ECCPOS3 3 --#define NAND_JFFS2_OOB_ECCPOS4 6 --#define NAND_JFFS2_OOB_ECCPOS5 7 -- --#define NAND_YAFFS_OOB_ECCPOS0 8 --#define NAND_YAFFS_OOB_ECCPOS1 9 --#define NAND_YAFFS_OOB_ECCPOS2 10 --#define NAND_YAFFS_OOB_ECCPOS3 13 --#define NAND_YAFFS_OOB_ECCPOS4 14 --#define NAND_YAFFS_OOB_ECCPOS5 15 -- --#define NAND_JFFS2_OOB8_FSDAPOS 6 --#define NAND_JFFS2_OOB16_FSDAPOS 8 --#define NAND_JFFS2_OOB8_FSDALEN 2 --#define NAND_JFFS2_OOB16_FSDALEN 8 -- - #endif /* __LINUX_MTD_NAND_H */ -diff -Nurb linux-mips-2.4.24-pre2/include/linux/mtd/nand_ecc.h linux/include/linux/mtd/nand_ecc.h ---- linux-mips-2.4.24-pre2/include/linux/mtd/nand_ecc.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/mtd/nand_ecc.h 2004-11-17 18:17:59.237283824 +0100 -@@ -1,9 +1,9 @@ - /* - * drivers/mtd/nand_ecc.h - * -- * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) -+ * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) - * -- * $Id$ -+ * $Id$ - * - * 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 -@@ -12,17 +12,19 @@ - * This file is the header for the ECC algorithm. - */ - --/* -- * Creates non-inverted ECC code from line parity -- */ --void nand_trans_result(u_char reg2, u_char reg3, u_char *ecc_code); -+#ifndef __MTD_NAND_ECC_H__ -+#define __MTD_NAND_ECC_H__ -+ -+struct mtd_info; - - /* - * Calculate 3 byte ECC code for 256 byte block - */ --void nand_calculate_ecc (const u_char *dat, u_char *ecc_code); -+void nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code); - - /* - * Detect and correct a 1 bit error for 256 byte block - */ --int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc); -+int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc); -+ -+#endif /* __MTD_NAND_ECC_H__ */ -diff -Nurb linux-mips-2.4.24-pre2/include/linux/mtd/nftl.h linux/include/linux/mtd/nftl.h ---- linux-mips-2.4.24-pre2/include/linux/mtd/nftl.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/mtd/nftl.h 2004-11-17 18:17:59.238283672 +0100 -@@ -1,15 +1,14 @@ -- --/* Defines for NAND Flash Translation Layer */ --/* (c) 1999 Machine Vision Holdings, Inc. */ --/* Author: David Woodhouse */ --/* $Id$ */ -+/* -+ * $Id$ -+ * -+ * (C) 1999-2003 David Woodhouse -+ */ - - #ifndef __MTD_NFTL_H__ - #define __MTD_NFTL_H__ - --#ifndef __BOOT__ - #include --#endif -+#include - - /* Block Control Information */ - -@@ -84,8 +83,7 @@ - #define BLOCK_RESERVED 0xfffc /* bios block or bad block */ - - struct NFTLrecord { -- struct mtd_info *mtd; -- struct semaphore mutex; -+ struct mtd_blktrans_dev mbd; - __u16 MediaUnit, SpareMediaUnit; - __u32 EraseSize; - struct NFTLMediaHeader MediaHdr; -@@ -97,7 +95,6 @@ - __u16 lastEUN; /* should be suppressed */ - __u16 numfreeEUNs; - __u16 LastFreeEUN; /* To speed up finding a free EUN */ -- __u32 nr_sects; - int head,sect,cyl; - __u16 *EUNtable; /* [numvunits]: First EUN for each virtual unit */ - __u16 *ReplUnitTable; /* [numEUNs]: ReplUnitNumber for each */ -@@ -114,7 +111,7 @@ - #endif - - #define MAX_NFTLS 16 --#define MAX_SECTORS_PER_UNIT 32 -+#define MAX_SECTORS_PER_UNIT 64 - #define NFTL_PARTN_BITS 4 - - #endif /* __KERNEL__ */ -diff -Nurb linux-mips-2.4.24-pre2/include/linux/mtd/partitions.h linux/include/linux/mtd/partitions.h ---- linux-mips-2.4.24-pre2/include/linux/mtd/partitions.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/mtd/partitions.h 2004-11-17 18:17:59.240283368 +0100 -@@ -5,7 +5,7 @@ - * - * This code is GPL - * -- * $Id$ -+ * $Id$ - */ - - #ifndef MTD_PARTITIONS_H -@@ -41,6 +41,7 @@ - u_int32_t size; /* partition size */ - u_int32_t offset; /* offset within the master MTD space */ - u_int32_t mask_flags; /* master MTD flags to mask out for this partition */ -+ struct nand_oobinfo *oobsel; /* out of band layout for this partition (NAND only)*/ - struct mtd_info **mtdp; /* pointer to store the MTD object */ - }; - -@@ -49,8 +50,27 @@ - #define MTDPART_SIZ_FULL (0) - - --int add_mtd_partitions(struct mtd_info *, struct mtd_partition *, int); -+int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); - int del_mtd_partitions(struct mtd_info *); - -+/* -+ * Functions dealing with the various ways of partitioning the space -+ */ -+ -+struct mtd_part_parser { -+ struct list_head list; -+ struct module *owner; -+ const char *name; -+ int (*parse_fn)(struct mtd_info *, struct mtd_partition **, unsigned long); -+}; -+ -+extern struct mtd_part_parser *get_partition_parser(const char *name); -+extern int register_mtd_parser(struct mtd_part_parser *parser); -+extern int deregister_mtd_parser(struct mtd_part_parser *parser); -+extern int parse_mtd_partitions(struct mtd_info *master, const char **types, -+ struct mtd_partition **pparts, unsigned long origin); -+ -+#define put_partition_parser(p) do { module_put((p)->owner); } while(0) -+ - #endif - -diff -Nurb linux-mips-2.4.24-pre2/include/linux/mtd/physmap.h linux/include/linux/mtd/physmap.h ---- linux-mips-2.4.24-pre2/include/linux/mtd/physmap.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/include/linux/mtd/physmap.h 2004-11-17 18:17:59.241283216 +0100 -@@ -0,0 +1,59 @@ -+/* -+ * For boards with physically mapped flash and using -+ * drivers/mtd/maps/physmap.c mapping driver. -+ * -+ * Copyright (C) 2003 MontaVista Software Inc. -+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the 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_MTD_PHYSMAP__ -+ -+#include -+ -+#if defined(CONFIG_MTD_PHYSMAP) -+ -+#include -+#include -+#include -+ -+/* -+ * The map_info for physmap. Board can override size, buswidth, phys, -+ * (*set_vpp)(), etc in their initial setup routine. -+ */ -+extern struct map_info physmap_map; -+ -+/* -+ * Board needs to specify the exact mapping during their setup time. -+ */ -+static inline void physmap_configure(unsigned long addr, unsigned long size, int buswidth, void (*set_vpp)(struct map_info *, int) ) -+{ -+ physmap_map.phys = addr; -+ physmap_map.size = size; -+ physmap_map.buswidth = buswidth; -+ physmap_map.set_vpp = set_vpp; -+} -+ -+#if defined(CONFIG_MTD_PARTITIONS) -+ -+/* -+ * Machines that wish to do flash partition may want to call this function in -+ * their setup routine. -+ * -+ * physmap_set_partitions(mypartitions, num_parts); -+ * -+ * Note that one can always override this hard-coded partition with -+ * command line partition (you need to enable CONFIG_MTD_CMDLINE_PARTS). -+ */ -+void physmap_set_partitions(struct mtd_partition *parts, int num_parts); -+ -+#endif /* defined(CONFIG_MTD_PARTITIONS) */ -+#endif /* defined(CONFIG_MTD) */ -+ -+#endif /* __LINUX_MTD_PHYSMAP__ */ -+ -diff -Nurb linux-mips-2.4.24-pre2/include/linux/rbtree-24.h linux/include/linux/rbtree-24.h ---- linux-mips-2.4.24-pre2/include/linux/rbtree-24.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/include/linux/rbtree-24.h 2004-11-17 18:17:59.443252512 +0100 -@@ -0,0 +1,133 @@ -+/* -+ Red Black Trees -+ (C) 1999 Andrea Arcangeli -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the 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 -+ -+ linux/include/linux/rbtree.h -+ -+ To use rbtrees you'll have to implement your own insert and search cores. -+ This will avoid us to use callbacks and to drop drammatically performances. -+ I know it's not the cleaner way, but in C (not in C++) to get -+ performances and genericity... -+ -+ Some example of insert and search follows here. The search is a plain -+ normal search over an ordered tree. The insert instead must be implemented -+ int two steps: as first thing the code must insert the element in -+ order as a red leaf in the tree, then the support library function -+ rb_insert_color() must be called. Such function will do the -+ not trivial work to rebalance the rbtree if necessary. -+ -+----------------------------------------------------------------------- -+static inline struct page * rb_search_page_cache(struct inode * inode, -+ unsigned long offset) -+{ -+ rb_node_t * n = inode->i_rb_page_cache.rb_node; -+ struct page * page; -+ -+ while (n) -+ { -+ page = rb_entry(n, struct page, rb_page_cache); -+ -+ if (offset < page->offset) -+ n = n->rb_left; -+ else if (offset > page->offset) -+ n = n->rb_right; -+ else -+ return page; -+ } -+ return NULL; -+} -+ -+static inline struct page * __rb_insert_page_cache(struct inode * inode, -+ unsigned long offset, -+ rb_node_t * node) -+{ -+ rb_node_t ** p = &inode->i_rb_page_cache.rb_node; -+ rb_node_t * parent = NULL; -+ struct page * page; -+ -+ while (*p) -+ { -+ parent = *p; -+ page = rb_entry(parent, struct page, rb_page_cache); -+ -+ if (offset < page->offset) -+ p = &(*p)->rb_left; -+ else if (offset > page->offset) -+ p = &(*p)->rb_right; -+ else -+ return page; -+ } -+ -+ rb_link_node(node, parent, p); -+ -+ return NULL; -+} -+ -+static inline struct page * rb_insert_page_cache(struct inode * inode, -+ unsigned long offset, -+ rb_node_t * node) -+{ -+ struct page * ret; -+ if ((ret = __rb_insert_page_cache(inode, offset, node))) -+ goto out; -+ rb_insert_color(node, &inode->i_rb_page_cache); -+ out: -+ return ret; -+} -+----------------------------------------------------------------------- -+*/ -+ -+#ifndef _LINUX_RBTREE_H -+#define _LINUX_RBTREE_H -+ -+#include -+#include -+ -+typedef struct rb_node_s -+{ -+ struct rb_node_s * rb_parent; -+ int rb_color; -+#define RB_RED 0 -+#define RB_BLACK 1 -+ struct rb_node_s * rb_right; -+ struct rb_node_s * rb_left; -+} -+rb_node_t; -+ -+typedef struct rb_root_s -+{ -+ struct rb_node_s * rb_node; -+} -+rb_root_t; -+ -+#define RB_ROOT (rb_root_t) { NULL, } -+#define rb_entry(ptr, type, member) \ -+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) -+ -+extern void rb_insert_color(rb_node_t *, rb_root_t *); -+extern void rb_erase(rb_node_t *, rb_root_t *); -+ -+static inline void rb_link_node(rb_node_t * node, rb_node_t * parent, rb_node_t ** rb_link) -+{ -+ node->rb_parent = parent; -+ node->rb_color = RB_RED; -+ node->rb_left = node->rb_right = NULL; -+ -+ *rb_link = node; -+} -+ -+#endif /* _LINUX_RBTREE_H */ -diff -Nurb linux-mips-2.4.24-pre2/include/linux/rbtree.h linux/include/linux/rbtree.h ---- linux-mips-2.4.24-pre2/include/linux/rbtree.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/rbtree.h 2004-11-17 18:17:59.000000000 +0100 -@@ -1,133 +1,25 @@ - /* -- Red Black Trees -- (C) 1999 Andrea Arcangeli -+ * 2.5 compatibility -+ * $Id$ -+ */ -+ -+#ifndef __MTD_COMPAT_RBTREE_H__ -+#define __MTD_COMPAT_RBTREE_H__ -+ -+#include -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,40) -+#include_next -+#else -+#define rb_node_s rb_node -+#define rb_root_s rb_root -+ -+#include -+ -+/* Find logical next and previous nodes in a tree */ -+extern struct rb_node *rb_next(struct rb_node *); -+extern struct rb_node *rb_prev(struct rb_node *); -+extern struct rb_node *rb_first(struct rb_root *); -+#endif - -- This program is free software; you can redistribute it and/or modify -- it under the terms of the 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 -- -- linux/include/linux/rbtree.h -- -- To use rbtrees you'll have to implement your own insert and search cores. -- This will avoid us to use callbacks and to drop drammatically performances. -- I know it's not the cleaner way, but in C (not in C++) to get -- performances and genericity... -- -- Some example of insert and search follows here. The search is a plain -- normal search over an ordered tree. The insert instead must be implemented -- int two steps: as first thing the code must insert the element in -- order as a red leaf in the tree, then the support library function -- rb_insert_color() must be called. Such function will do the -- not trivial work to rebalance the rbtree if necessary. -- ------------------------------------------------------------------------- --static inline struct page * rb_search_page_cache(struct inode * inode, -- unsigned long offset) --{ -- rb_node_t * n = inode->i_rb_page_cache.rb_node; -- struct page * page; -- -- while (n) -- { -- page = rb_entry(n, struct page, rb_page_cache); -- -- if (offset < page->offset) -- n = n->rb_left; -- else if (offset > page->offset) -- n = n->rb_right; -- else -- return page; -- } -- return NULL; --} -- --static inline struct page * __rb_insert_page_cache(struct inode * inode, -- unsigned long offset, -- rb_node_t * node) --{ -- rb_node_t ** p = &inode->i_rb_page_cache.rb_node; -- rb_node_t * parent = NULL; -- struct page * page; -- -- while (*p) -- { -- parent = *p; -- page = rb_entry(parent, struct page, rb_page_cache); -- -- if (offset < page->offset) -- p = &(*p)->rb_left; -- else if (offset > page->offset) -- p = &(*p)->rb_right; -- else -- return page; -- } -- -- rb_link_node(node, parent, p); -- -- return NULL; --} -- --static inline struct page * rb_insert_page_cache(struct inode * inode, -- unsigned long offset, -- rb_node_t * node) --{ -- struct page * ret; -- if ((ret = __rb_insert_page_cache(inode, offset, node))) -- goto out; -- rb_insert_color(node, &inode->i_rb_page_cache); -- out: -- return ret; --} ------------------------------------------------------------------------- --*/ -- --#ifndef _LINUX_RBTREE_H --#define _LINUX_RBTREE_H -- --#include --#include -- --typedef struct rb_node_s --{ -- struct rb_node_s * rb_parent; -- int rb_color; --#define RB_RED 0 --#define RB_BLACK 1 -- struct rb_node_s * rb_right; -- struct rb_node_s * rb_left; --} --rb_node_t; -- --typedef struct rb_root_s --{ -- struct rb_node_s * rb_node; --} --rb_root_t; -- --#define RB_ROOT (rb_root_t) { NULL, } --#define rb_entry(ptr, type, member) \ -- ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) -- --extern void rb_insert_color(rb_node_t *, rb_root_t *); --extern void rb_erase(rb_node_t *, rb_root_t *); -- --static inline void rb_link_node(rb_node_t * node, rb_node_t * parent, rb_node_t ** rb_link) --{ -- node->rb_parent = parent; -- node->rb_color = RB_RED; -- node->rb_left = node->rb_right = NULL; -- -- *rb_link = node; --} -- --#endif /* _LINUX_RBTREE_H */ -+#endif /* __MTD_COMPAT_RBTREE_H__ */ -diff -Nurb linux-mips-2.4.24-pre2/include/linux/suspend.h linux/include/linux/suspend.h ---- linux-mips-2.4.24-pre2/include/linux/suspend.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/include/linux/suspend.h 2004-11-17 18:17:59.450251448 +0100 -@@ -0,0 +1,10 @@ -+/* $Id$ */ -+ -+#ifndef __MTD_COMPAT_VERSION_H__ -+#include -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+#include_next -+#endif -+ -+#endif /* __MTD_COMPAT_VERSION_H__ */ -diff -Nurb linux-mips-2.4.24-pre2/include/linux/workqueue.h linux/include/linux/workqueue.h ---- linux-mips-2.4.24-pre2/include/linux/workqueue.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/include/linux/workqueue.h 2004-11-17 18:17:59.451251296 +0100 -@@ -0,0 +1,21 @@ -+/* -+ * 2.5 compatibility -+ * $Id$ -+ */ -+ -+#ifndef __MTD_COMPAT_WORKQUEUE_H__ -+#define __MTD_COMPAT_WORKQUEUE_H__ -+ -+#include -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,40) -+#include_next -+#else -+#include -+#define work_struct tq_struct -+#define schedule_work(x) schedule_task(x) -+#define flush_scheduled_work flush_scheduled_tasks -+#define INIT_WORK(x,y,z) INIT_TQUEUE(x,y,z) -+#endif -+ -+#endif /* __MTD_COMPAT_WORKQUEUE_H__ */ diff --git a/linux/linux-mtx-1-2.4.24/02-mtd-mtx-1-map.diff b/linux/linux-mtx-1-2.4.24/02-mtd-mtx-1-map.diff deleted file mode 100644 index ba24bb1381..0000000000 --- a/linux/linux-mtx-1-2.4.24/02-mtd-mtx-1-map.diff +++ /dev/null @@ -1,248 +0,0 @@ -diff -Nurb linux/drivers/mtd/maps/Config.in linux-mips-2.4.24-pre2+mtd-2004-01-27+mtx-map/drivers/mtd/maps/Config.in ---- linux/drivers/mtd/maps/Config.in 2004-11-17 18:17:59.049312400 +0100 -+++ linux-mips-2.4.24-pre2+mtd-2004-01-27+mtx-map/drivers/mtd/maps/Config.in 2004-11-17 18:12:26.000000000 +0100 -@@ -80,6 +80,7 @@ - bool ' Db1x00 boot flash device' CONFIG_MTD_DB1X00_BOOT - bool ' Db1x00 user flash device (2nd bank)' CONFIG_MTD_DB1X00_USER - fi -+ dep_tristate ' MTX-1 flash device' CONFIG_MTD_MTX1 $CONFIG_MIPS_MTX1 - dep_tristate ' Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board' CONFIG_MTD_CSTM_MIPS_IXX $CONFIG_MTD_CFI $CONFIG_MTD_JEDEC $CONFIG_MTD_PARTITIONS - if [ "$CONFIG_MTD_CSTM_MIPS_IXX" = "y" -o "$CONFIG_MTD_CSTM_MIPS_IXX" = "m" ]; then - hex ' Physical start address of flash mapping' CONFIG_MTD_CSTM_MIPS_IXX_START 0x8000000 -diff -Nurb linux/drivers/mtd/maps/Makefile linux-mips-2.4.24-pre2+mtd-2004-01-27+mtx-map/drivers/mtd/maps/Makefile ---- linux/drivers/mtd/maps/Makefile 2004-11-17 18:17:59.051312096 +0100 -+++ linux-mips-2.4.24-pre2+mtd-2004-01-27+mtx-map/drivers/mtd/maps/Makefile 2004-11-17 18:12:26.000000000 +0100 -@@ -49,6 +49,7 @@ - obj-$(CONFIG_MTD_PCI) += pci.o - obj-$(CONFIG_MTD_PB1XXX) += pb1xxx-flash.o - obj-$(CONFIG_MTD_DB1X00) += db1x00-flash.o -+obj-$(CONFIG_MTD_MTX1) += mtx-1.o - obj-$(CONFIG_MTD_LASAT) += lasat.o - obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o - obj-$(CONFIG_MTD_EDB7312) += edb7312.o -diff -Nurb linux/drivers/mtd/maps/mtx-1.c linux-mips-2.4.24-pre2+mtd-2004-01-27+mtx-map/drivers/mtd/maps/mtx-1.c ---- linux/drivers/mtd/maps/mtx-1.c 2004-11-17 18:17:02.689880336 +0100 -+++ linux-mips-2.4.24-pre2+mtd-2004-01-27+mtx-map/drivers/mtd/maps/mtx-1.c 2004-11-17 18:12:26.000000000 +0100 -@@ -1,166 +1,78 @@ - /* - * Flash memory access on 4G Systems MTX-1 board - * -- * (C) 2003 Pete Popov -- * Bruno Randolf -+ * (C) Bruno Randolf (4G Systeme GmbH) - */ - - #include - #include - #include - #include -+#include - - #include - #include - #include - - #include --#include - --#ifdef DEBUG_RW --#define DBG(x...) printk(x) --#else --#define DBG(x...) --#endif -- --#ifdef CONFIG_MIPS_MTX1 - #define WINDOW_ADDR 0x1E000000 - #define WINDOW_SIZE 0x2000000 --#endif -- --__u8 physmap_read8(struct map_info *map, unsigned long ofs) --{ -- __u8 ret; -- ret = __raw_readb(map->map_priv_1 + ofs); -- DBG("read8 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --__u16 physmap_read16(struct map_info *map, unsigned long ofs) --{ -- __u16 ret; -- ret = __raw_readw(map->map_priv_1 + ofs); -- DBG("read16 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --__u32 physmap_read32(struct map_info *map, unsigned long ofs) --{ -- __u32 ret; -- ret = __raw_readl(map->map_priv_1 + ofs); -- DBG("read32 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- DBG("physmap_copy from %x to %x\n", (unsigned)from, (unsigned)to); -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void physmap_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- DBG("write8 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- DBG("write16 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- DBG("write32 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- DBG("physmap_copy_to %x from %x\n", (unsigned)to, (unsigned)from); -- memcpy_toio(map->map_priv_1 + to, from, len); --} -- -- -+#define BUSWIDTH 4 - - static struct map_info mtx1_map = { -- name: "MTX-1 flash", -- read8: physmap_read8, -- read16: physmap_read16, -- read32: physmap_read32, -- copy_from: physmap_copy_from, -- write8: physmap_write8, -- write16: physmap_write16, -- write32: physmap_write32, -- copy_to: physmap_copy_to, -+ .name = "MTX-1 flash", -+ .size = WINDOW_SIZE, -+ .buswidth = BUSWIDTH, -+ .phys = WINDOW_ADDR - }; - -- --static unsigned long flash_size = 0x01000000; --static unsigned char flash_buswidth = 4; - static struct mtd_partition mtx1_partitions[] = { - { -- name: "user fs", -- size: 0x1c00000, -- offset: 0, -+ .name = "user fs", -+ .size = 0x1c00000, -+ .offset = 0, - },{ -- name: "yamon", -- size: 0x0100000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE -+ .name = "yamon", -+ .size = 0x0100000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ - },{ -- name: "raw kernel", -- size: 0x02c0000, -- offset: MTDPART_OFS_APPEND, -+ .name = "raw kernel", -+ .size = 0x02c0000, -+ .offset = MTDPART_OFS_APPEND, - },{ -- name: "yamon env vars", -- size: 0x0040000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE -+ .name = "yamon environment", -+ .size = 0x0040000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ - } - }; - -- --#define NB_OF(x) (sizeof(x)/sizeof(x[0])) -- --static struct mtd_partition *parsed_parts; - static struct mtd_info *mymtd; - - int __init mtx1_mtd_init(void) - { -- struct mtd_partition *parts; -- int nb_parts = 0; -- char *part_type; -+ printk(KERN_NOTICE "MTX-1 flash: probing %d-bit flash bus at %x\n", -+ mtx1_map.buswidth*8, WINDOW_ADDR); - -- /* Default flash buswidth */ -- mtx1_map.buswidth = flash_buswidth; -+ mtx1_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); -+ if (!mtx1_map.virt) { -+ printk("mtx_mtd_init: failed to ioremap\n"); -+ return -EIO; -+ } -+ -+ simple_map_init(&mtx1_map); - -- /* -- * Static partition definition selection -- */ -- part_type = "static"; -- parts = mtx1_partitions; -- nb_parts = NB_OF(mtx1_partitions); -- mtx1_map.size = flash_size; -- -- /* -- * Now let's probe for the actual flash. Do it here since -- * specific machine settings might have been set above. -- */ -- printk(KERN_NOTICE "MTX-1 flash: probing %d-bit flash bus\n", -- mtx1_map.buswidth*8); -- mtx1_map.map_priv_1 = -- (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); - mymtd = do_map_probe("cfi_probe", &mtx1_map); -- if (!mymtd) return -ENXIO; -- mymtd->module = THIS_MODULE; -+ if (!mymtd) { -+ iounmap(mtx1_map.virt); -+ return -ENXIO; -+ } -+ -+ mymtd->owner = THIS_MODULE; - -- add_mtd_partitions(mymtd, parts, nb_parts); -- return 0; -+ return add_mtd_partitions(mymtd, mtx1_partitions, ARRAY_SIZE(mtx1_partitions)); - } - - static void __exit mtx1_mtd_cleanup(void) -@@ -168,14 +80,14 @@ - if (mymtd) { - del_mtd_partitions(mymtd); - map_destroy(mymtd); -- if (parsed_parts) -- kfree(parsed_parts); - } -+ if (mtx1_map.virt) -+ iounmap(mtx1_map.virt); - } - - module_init(mtx1_mtd_init); - module_exit(mtx1_mtd_cleanup); - --MODULE_AUTHOR("Pete Popov"); -+MODULE_AUTHOR("Bruno Randolf "); - MODULE_DESCRIPTION("MTX-1 CFI map driver"); - MODULE_LICENSE("GPL"); - diff --git a/linux/linux-mtx-1-2.4.24/03-mtd-erase-compiler-bug.diff b/linux/linux-mtx-1-2.4.24/03-mtd-erase-compiler-bug.diff deleted file mode 100644 index 9e310bf327..0000000000 --- a/linux/linux-mtx-1-2.4.24/03-mtd-erase-compiler-bug.diff +++ /dev/null @@ -1,21 +0,0 @@ ---- linux-mips-2.4.24-pre2+mtd-2004-01-27/fs/jffs2/erase.c 2004-11-17 18:17:59.000000000 +0100 -+++ linux/fs/jffs2/erase.c 2004-11-17 18:44:52.260067088 +0100 -@@ -365,11 +365,13 @@ - jeb->dirty_size = 0; - jeb->wasted_size = 0; - } else { -- struct jffs2_unknown_node marker = { -- .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK), -- .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), -- .totlen = cpu_to_je32(c->cleanmarker_size) -- }; -+ /* compiler workaround, structure was not initialized before -+ on mipsel cross compilers -+ fix by Eugene.Wisor@flukenetworks.com */ -+ struct jffs2_unknown_node marker; -+ marker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ marker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); -+ marker.totlen = cpu_to_je32(c->cleanmarker_size); - - marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4)); - diff --git a/linux/linux-mtx-1-2.4.24/04-zboot-2.4.24.patch b/linux/linux-mtx-1-2.4.24/04-zboot-2.4.24.patch deleted file mode 100644 index 85f5fc3aa3..0000000000 --- a/linux/linux-mtx-1-2.4.24/04-zboot-2.4.24.patch +++ /dev/null @@ -1,5286 +0,0 @@ -diff -Naru linux/arch/mips/Makefile linux-new/arch/mips/Makefile ---- linux/arch/mips/Makefile 2003-10-22 02:58:37.000000000 -0400 -+++ linux-new/arch/mips/Makefile 2003-12-18 14:26:20.000000000 -0500 -@@ -724,15 +724,21 @@ - endif - - MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot -+MAKEZBOOT = $(MAKE) -C arch/$(ARCH)/zboot -+BOOT_TARGETS = zImage zImage.initrd zImage.flash - - vmlinux.ecoff: vmlinux - @$(MAKEBOOT) $@ - -+ $(BOOT_TARGETS): vmlinux -+ @$(MAKEZBOOT) $@ -+ - vmlinux.srec: vmlinux - @$(MAKEBOOT) $@ - - archclean: - @$(MAKEBOOT) clean -+ @$(MAKEZBOOT) clean - rm -f arch/$(ARCH)/ld.script - $(MAKE) -C arch/$(ARCH)/tools clean - $(MAKE) -C arch/mips/baget clean -diff -Naru linux/arch/mips/zboot/common/au1k_uart.c linux-new/arch/mips/zboot/common/au1k_uart.c ---- linux/arch/mips/zboot/common/au1k_uart.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/common/au1k_uart.c 2003-12-18 14:26:20.000000000 -0500 -@@ -0,0 +1,103 @@ -+/* -+ * BRIEF MODULE DESCRIPTION -+ * Simple Au1000 uart routines. -+ * -+ * Copyright 2001 MontaVista Software Inc. -+ * Author: MontaVista Software, Inc. -+ * ppopov@mvista.com or source@mvista.com -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * THIS 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 "ns16550.h" -+ -+typedef unsigned char uint8; -+typedef unsigned int uint32; -+ -+#define UART16550_BAUD_2400 2400 -+#define UART16550_BAUD_4800 4800 -+#define UART16550_BAUD_9600 9600 -+#define UART16550_BAUD_19200 19200 -+#define UART16550_BAUD_38400 38400 -+#define UART16550_BAUD_57600 57600 -+#define UART16550_BAUD_115200 115200 -+ -+#define UART16550_PARITY_NONE 0 -+#define UART16550_PARITY_ODD 0x08 -+#define UART16550_PARITY_EVEN 0x18 -+#define UART16550_PARITY_MARK 0x28 -+#define UART16550_PARITY_SPACE 0x38 -+ -+#define UART16550_DATA_5BIT 0x0 -+#define UART16550_DATA_6BIT 0x1 -+#define UART16550_DATA_7BIT 0x2 -+#define UART16550_DATA_8BIT 0x3 -+ -+#define UART16550_STOP_1BIT 0x0 -+#define UART16550_STOP_2BIT 0x4 -+ -+/* It would be nice if we had a better way to do this. -+ * It could be a variable defined in one of the board specific files. -+ */ -+#undef UART_BASE -+#ifdef CONFIG_COGENT_CSB250 -+#define UART_BASE UART3_ADDR -+#else -+#define UART_BASE UART0_ADDR -+#endif -+ -+/* memory-mapped read/write of the port */ -+#define UART16550_READ(y) (readl(UART_BASE + y) & 0xff) -+#define UART16550_WRITE(y,z) (writel(z&0xff, UART_BASE + y)) -+ -+/* -+ * We use uart 0, which is already initialized by -+ * yamon. -+ */ -+volatile struct NS16550 * -+serial_init(int chan) -+{ -+ volatile struct NS16550 *com_port; -+ com_port = (struct NS16550 *) UART_BASE; -+ return (com_port); -+} -+ -+void -+serial_putc(volatile struct NS16550 *com_port, unsigned char c) -+{ -+ while ((UART16550_READ(UART_LSR)&0x40) == 0); -+ UART16550_WRITE(UART_TX, c); -+} -+ -+unsigned char -+serial_getc(volatile struct NS16550 *com_port) -+{ -+ while((UART16550_READ(UART_LSR) & 0x1) == 0); -+ return UART16550_READ(UART_RX); -+} -+ -+int -+serial_tstc(volatile struct NS16550 *com_port) -+{ -+ return((UART16550_READ(UART_LSR) & LSR_DR) != 0); -+} -diff -Naru linux/arch/mips/zboot/common/ctype.c linux-new/arch/mips/zboot/common/ctype.c ---- linux/arch/mips/zboot/common/ctype.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/common/ctype.c 2003-12-18 14:26:20.000000000 -0500 -@@ -0,0 +1,35 @@ -+/* -+ * linux/lib/ctype.c -+ * -+ * Copyright (C) 1991, 1992 Linus Torvalds -+ */ -+ -+#include -+ -+unsigned char _ctype[] = { -+_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ -+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ -+_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ -+_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ -+_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ -+_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ -+_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ -+_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ -+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ -+_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ -+_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ -+_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ -+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ -+_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ -+_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ -+_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ -+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ -+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ -+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ -+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ -+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ -+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ -+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ -+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ -+ -+ -diff -Naru linux/arch/mips/zboot/common/dummy.c linux-new/arch/mips/zboot/common/dummy.c ---- linux/arch/mips/zboot/common/dummy.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/common/dummy.c 2003-12-18 14:26:20.000000000 -0500 -@@ -0,0 +1,4 @@ -+int main(void) -+{ -+ return 0; -+} -diff -Naru linux/arch/mips/zboot/common/Makefile linux-new/arch/mips/zboot/common/Makefile ---- linux/arch/mips/zboot/common/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/common/Makefile 2003-12-18 14:26:20.000000000 -0500 -@@ -0,0 +1,27 @@ -+# -+# arch/mips/zboot/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. -+# -+# Tom Rini January 2001 -+# -+ -+.c.s: -+ $(CC) $(CFLAGS) -S -o $*.s $< -+.s.o: -+ $(AS) -o $*.o $< -+.c.o: -+ $(CC) $(CFLAGS) -c -o $*.o $< -+.S.s: -+ $(CPP) $(AFLAGS) -o $*.o $< -+.S.o: -+ $(CC) $(AFLAGS) -c -o $*.o $< -+ -+clean: -+ rm -rf *.o -+ -+OBJCOPY_ARGS = -O elf32-tradlittlemips -+ -+include $(TOPDIR)/Rules.make -diff -Naru linux/arch/mips/zboot/common/misc-common.c linux-new/arch/mips/zboot/common/misc-common.c ---- linux/arch/mips/zboot/common/misc-common.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/common/misc-common.c 2003-12-18 14:26:20.000000000 -0500 -@@ -0,0 +1,437 @@ -+/* -+ * arch/mips/zboot/common/misc-common.c -+ * -+ * Misc. bootloader code (almost) all platforms can use -+ * -+ * Author: Johnnie Peters -+ * Editor: Tom Rini -+ * -+ * Derived from arch/ppc/boot/prep/misc.c -+ * -+ * Ported by Pete Popov to -+ * support mips board(s). I also got rid of the vga console -+ * code. -+ * -+ * Copyright 2000-2001 MontaVista Software Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * THIS 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 "zlib.h" -+#include -+ -+extern char *avail_ram; -+extern char *end_avail; -+extern char _end[]; -+ -+void puts(const char *); -+void putc(const char c); -+void puthex(unsigned long val); -+void _bcopy(char *src, char *dst, int len); -+void gunzip(void *, int, unsigned char *, int *); -+static int _cvt(unsigned long val, char *buf, long radix, char *digits); -+ -+void _vprintk(void(*)(const char), const char *, va_list ap); -+ -+struct NS16550 *com_port; -+ -+int serial_tstc(volatile struct NS16550 *); -+unsigned char serial_getc(volatile struct NS16550 *); -+void serial_putc(volatile struct NS16550 *, unsigned char); -+ -+void pause(void) -+{ -+ puts("pause\n"); -+} -+ -+void exit(void) -+{ -+ puts("exit\n"); -+ while(1); -+} -+ -+int tstc(void) -+{ -+ return (serial_tstc(com_port)); -+} -+ -+int getc(void) -+{ -+ while (1) { -+ if (serial_tstc(com_port)) -+ return (serial_getc(com_port)); -+ } -+} -+ -+void -+putc(const char c) -+{ -+ int x,y; -+ -+ serial_putc(com_port, c); -+ if ( c == '\n' ) -+ serial_putc(com_port, '\r'); -+} -+ -+void puts(const char *s) -+{ -+ char c; -+ while ( ( c = *s++ ) != '\0' ) { -+ serial_putc(com_port, c); -+ if ( c == '\n' ) serial_putc(com_port, '\r'); -+ } -+} -+ -+void error(char *x) -+{ -+ puts("\n\n"); -+ puts(x); -+ puts("\n\n -- System halted"); -+ -+ while(1); /* Halt */ -+} -+ -+void *zalloc(void *x, unsigned items, unsigned size) -+{ -+ void *p = avail_ram; -+ -+ size *= items; -+ size = (size + 7) & -8; -+ avail_ram += size; -+ if (avail_ram > end_avail) { -+ puts("oops... out of memory\n"); -+ pause(); -+ } -+ return p; -+} -+ -+void zfree(void *x, void *addr, unsigned nb) -+{ -+} -+ -+#define HEAD_CRC 2 -+#define EXTRA_FIELD 4 -+#define ORIG_NAME 8 -+#define COMMENT 0x10 -+#define RESERVED 0xe0 -+ -+#define DEFLATED 8 -+ -+void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) -+{ -+ z_stream s; -+ int r, i, flags; -+ -+ /* skip header */ -+ i = 10; -+ flags = src[3]; -+ if (src[2] != DEFLATED || (flags & RESERVED) != 0) { -+ puts("bad gzipped data\n"); -+ exit(); -+ } -+ if ((flags & EXTRA_FIELD) != 0) -+ i = 12 + src[10] + (src[11] << 8); -+ if ((flags & ORIG_NAME) != 0) -+ while (src[i++] != 0) -+ ; -+ if ((flags & COMMENT) != 0) -+ while (src[i++] != 0) -+ ; -+ if ((flags & HEAD_CRC) != 0) -+ i += 2; -+ if (i >= *lenp) { -+ puts("gunzip: ran out of data in header\n"); -+ exit(); -+ } -+ -+ s.zalloc = zalloc; -+ s.zfree = zfree; -+ r = inflateInit2(&s, -MAX_WBITS); -+ if (r != Z_OK) { -+ puts("inflateInit2 returned %d\n"); -+ exit(); -+ } -+ s.next_in = src + i; -+ s.avail_in = *lenp - i; -+ s.next_out = dst; -+ s.avail_out = dstlen; -+ r = inflate(&s, Z_FINISH); -+ if (r != Z_OK && r != Z_STREAM_END) { -+ puts("inflate returned %d\n"); -+ exit(); -+ } -+ *lenp = s.next_out - (unsigned char *) dst; -+ inflateEnd(&s); -+} -+ -+void -+puthex(unsigned long val) -+{ -+ -+ unsigned char buf[10]; -+ int i; -+ for (i = 7; i >= 0; i--) -+ { -+ buf[i] = "0123456789ABCDEF"[val & 0x0F]; -+ val >>= 4; -+ } -+ buf[8] = '\0'; -+ puts(buf); -+} -+ -+#define FALSE 0 -+#define TRUE 1 -+ -+void -+_printk(char const *fmt, ...) -+{ -+ va_list ap; -+ -+ va_start(ap, fmt); -+ _vprintk(putc, fmt, ap); -+ va_end(ap); -+ return; -+} -+ -+#define is_digit(c) ((c >= '0') && (c <= '9')) -+ -+void -+_vprintk(void(*putc)(const char), const char *fmt0, va_list ap) -+{ -+ char c, sign, *cp = 0; -+ int left_prec, right_prec, zero_fill, length = 0, pad, pad_on_right; -+ char buf[32]; -+ long val; -+ while ((c = *fmt0++)) -+ { -+ if (c == '%') -+ { -+ c = *fmt0++; -+ left_prec = right_prec = pad_on_right = 0; -+ if (c == '-') -+ { -+ c = *fmt0++; -+ pad_on_right++; -+ } -+ if (c == '0') -+ { -+ zero_fill = TRUE; -+ c = *fmt0++; -+ } else -+ { -+ zero_fill = FALSE; -+ } -+ while (is_digit(c)) -+ { -+ left_prec = (left_prec * 10) + (c - '0'); -+ c = *fmt0++; -+ } -+ if (c == '.') -+ { -+ c = *fmt0++; -+ zero_fill++; -+ while (is_digit(c)) -+ { -+ right_prec = (right_prec * 10) + (c - '0'); -+ c = *fmt0++; -+ } -+ } else -+ { -+ right_prec = left_prec; -+ } -+ sign = '\0'; -+ switch (c) -+ { -+ case 'd': -+ case 'x': -+ case 'X': -+ val = va_arg(ap, long); -+ switch (c) -+ { -+ case 'd': -+ if (val < 0) -+ { -+ sign = '-'; -+ val = -val; -+ } -+ length = _cvt(val, buf, 10, "0123456789"); -+ break; -+ case 'x': -+ length = _cvt(val, buf, 16, "0123456789abcdef"); -+ break; -+ case 'X': -+ length = _cvt(val, buf, 16, "0123456789ABCDEF"); -+ break; -+ } -+ cp = buf; -+ break; -+ case 's': -+ cp = va_arg(ap, char *); -+ length = strlen(cp); -+ break; -+ case 'c': -+ c = va_arg(ap, long /*char*/); -+ (*putc)(c); -+ continue; -+ default: -+ (*putc)('?'); -+ } -+ pad = left_prec - length; -+ if (sign != '\0') -+ { -+ pad--; -+ } -+ if (zero_fill) -+ { -+ c = '0'; -+ if (sign != '\0') -+ { -+ (*putc)(sign); -+ sign = '\0'; -+ } -+ } else -+ { -+ c = ' '; -+ } -+ if (!pad_on_right) -+ { -+ while (pad-- > 0) -+ { -+ (*putc)(c); -+ } -+ } -+ if (sign != '\0') -+ { -+ (*putc)(sign); -+ } -+ while (length-- > 0) -+ { -+ (*putc)(c = *cp++); -+ if (c == '\n') -+ { -+ (*putc)('\r'); -+ } -+ } -+ if (pad_on_right) -+ { -+ while (pad-- > 0) -+ { -+ (*putc)(c); -+ } -+ } -+ } else -+ { -+ (*putc)(c); -+ if (c == '\n') -+ { -+ (*putc)('\r'); -+ } -+ } -+ } -+} -+ -+int -+_cvt(unsigned long val, char *buf, long radix, char *digits) -+{ -+ char temp[80]; -+ char *cp = temp; -+ int length = 0; -+ if (val == 0) -+ { /* Special case */ -+ *cp++ = '0'; -+ } else -+ while (val) -+ { -+ *cp++ = digits[val % radix]; -+ val /= radix; -+ } -+ while (cp != temp) -+ { -+ *buf++ = *--cp; -+ length++; -+ } -+ *buf = '\0'; -+ return (length); -+} -+ -+void -+_dump_buf_with_offset(unsigned char *p, int s, unsigned char *base) -+{ -+ int i, c; -+ if ((unsigned int)s > (unsigned int)p) -+ { -+ s = (unsigned int)s - (unsigned int)p; -+ } -+ while (s > 0) -+ { -+ if (base) -+ { -+ _printk("%06X: ", (int)p - (int)base); -+ } else -+ { -+ _printk("%06X: ", p); -+ } -+ for (i = 0; i < 16; i++) -+ { -+ if (i < s) -+ { -+ _printk("%02X", p[i] & 0xFF); -+ } else -+ { -+ _printk(" "); -+ } -+ if ((i % 2) == 1) _printk(" "); -+ if ((i % 8) == 7) _printk(" "); -+ } -+ _printk(" |"); -+ for (i = 0; i < 16; i++) -+ { -+ if (i < s) -+ { -+ c = p[i] & 0xFF; -+ if ((c < 0x20) || (c >= 0x7F)) c = '.'; -+ } else -+ { -+ c = ' '; -+ } -+ _printk("%c", c); -+ } -+ _printk("|\n"); -+ s -= 16; -+ p += 16; -+ } -+} -+ -+void -+_dump_buf(unsigned char *p, int s) -+{ -+ _printk("\n"); -+ _dump_buf_with_offset(p, s, 0); -+} -+ -+/* -+ * Local variables: -+ * c-indent-level: 8 -+ * c-basic-offset: 8 -+ * tab-width: 8 -+ * End: -+ */ -diff -Naru linux/arch/mips/zboot/common/misc-simple.c linux-new/arch/mips/zboot/common/misc-simple.c ---- linux/arch/mips/zboot/common/misc-simple.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/common/misc-simple.c 2003-12-18 14:26:20.000000000 -0500 -@@ -0,0 +1,127 @@ -+/* -+ * arch/mips/zboot/common/misc-simple.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 -+ * your serial console. If a machine meets these requirements, it can quite -+ * likely use this code during boot. -+ * -+ * Author: Matt Porter -+ * Derived from arch/ppc/boot/prep/misc.c -+ * -+ * Copyright 2001 MontaVista Software 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 "zlib.h" -+ -+extern struct NS16550 *com_port; -+ -+char *avail_ram; -+char *end_avail; -+extern char _end[]; -+char *zimage_start; -+ -+#ifdef CONFIG_CMDLINE -+#define CMDLINE CONFIG_CMDLINE -+#else -+#define CMDLINE "" -+#endif -+char cmd_preset[] = CMDLINE; -+char cmd_buf[256]; -+char *cmd_line = cmd_buf; -+ -+/* The linker tells us where the image is. -+*/ -+extern unsigned char __image_begin, __image_end; -+extern unsigned char __ramdisk_begin, __ramdisk_end; -+unsigned long initrd_size; -+ -+extern void puts(const char *); -+extern void putc(const char c); -+extern void puthex(unsigned long val); -+extern void *memcpy(void * __dest, __const void * __src, -+ __kernel_size_t __n); -+extern void gunzip(void *, int, unsigned char *, int *); -+extern void udelay(long delay); -+extern int tstc(void); -+extern int getc(void); -+extern volatile struct NS16550 *serial_init(int chan); -+ -+void -+decompress_kernel(unsigned long load_addr, int num_words, -+ unsigned long cksum, unsigned long *sp) -+{ -+ int timer = 0; -+ extern unsigned long start; -+ char *cp, ch; -+ int i; -+ int zimage_size; -+ -+ com_port = (struct NS16550 *)serial_init(0); -+ -+ initrd_size = (unsigned long)(&__ramdisk_end) - -+ (unsigned long)(&__ramdisk_begin); -+ -+ /* -+ * Reveal where we were loaded at and where we -+ * were relocated to. -+ */ -+ puts("loaded at: "); puthex(load_addr); -+ puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n"); -+ if ( (unsigned long)load_addr != (unsigned long)&start ) -+ { -+ puts("relocated to: "); puthex((unsigned long)&start); -+ puts(" "); -+ puthex((unsigned long)((unsigned long)&start + (4*num_words))); -+ puts("\n"); -+ } -+ -+ /* -+ * We link ourself to an arbitrary low address. When we run, we -+ * relocate outself to that address. __image_being points to -+ * the part of the image where the zImage is. -- Tom -+ */ -+ zimage_start = (char *)(unsigned long)(&__image_begin); -+ zimage_size = (unsigned long)(&__image_end) - -+ (unsigned long)(&__image_begin); -+ -+ /* -+ * The zImage and initrd will be between start and _end, so they've -+ * already been moved once. We're good to go now. -- Tom -+ */ -+ puts("zimage at: "); puthex((unsigned long)zimage_start); -+ puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); -+ puts("\n"); -+ -+ if ( initrd_size ) { -+ puts("initrd at: "); -+ puthex((unsigned long)(&__ramdisk_begin)); -+ puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n"); -+ } -+ -+ /* assume the chunk below 8M is free */ -+ avail_ram = (char *)AVAIL_RAM_START; -+ end_avail = (char *)AVAIL_RAM_END; -+ -+ /* Display standard Linux/MIPS boot prompt for kernel args */ -+ puts("Uncompressing Linux at load address "); -+ puthex(LOADADDR); -+ puts("\n"); -+ /* I don't like this hard coded gunzip size (fixme) */ -+ gunzip((void *)LOADADDR, 0x400000, zimage_start, &zimage_size); -+ puts("Now booting the kernel\n"); -+} -diff -Naru linux/arch/mips/zboot/common/no_initrd.c linux-new/arch/mips/zboot/common/no_initrd.c ---- linux/arch/mips/zboot/common/no_initrd.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/common/no_initrd.c 2003-12-18 14:26:20.000000000 -0500 -@@ -0,0 +1,2 @@ -+char initrd_data[1]; -+int initrd_len = 0; -diff -Naru linux/arch/mips/zboot/common/ns16550.c linux-new/arch/mips/zboot/common/ns16550.c ---- linux/arch/mips/zboot/common/ns16550.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/common/ns16550.c 2003-12-18 14:26:20.000000000 -0500 -@@ -0,0 +1,57 @@ -+/* -+ * NS16550 support -+ */ -+ -+#include -+#include -+#include "ns16550.h" -+ -+typedef struct NS16550 *NS16550_t; -+ -+const NS16550_t COM_PORTS[] = { (NS16550_t) COM1, -+ (NS16550_t) COM2, -+ (NS16550_t) COM3, -+ (NS16550_t) COM4 }; -+ -+volatile struct NS16550 * -+serial_init(int chan) -+{ -+ volatile struct NS16550 *com_port; -+ com_port = (struct NS16550 *) COM_PORTS[chan]; -+ /* See if port is present */ -+ com_port->lcr = 0x00; -+ com_port->ier = 0xFF; -+#if 0 -+ if (com_port->ier != 0x0F) return ((struct NS16550 *)0); -+#endif -+ com_port->ier = 0x00; -+ com_port->lcr = 0x80; /* Access baud rate */ -+#ifdef CONFIG_SERIAL_CONSOLE_NONSTD -+ com_port->dll = (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD); -+ com_port->dlm = (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD) >> 8; -+#endif -+ com_port->lcr = 0x03; /* 8 data, 1 stop, no parity */ -+ com_port->mcr = 0x03; /* RTS/DTR */ -+ com_port->fcr = 0x07; /* Clear & enable FIFOs */ -+ return (com_port); -+} -+ -+void -+serial_putc(volatile struct NS16550 *com_port, unsigned char c) -+{ -+ while ((com_port->lsr & LSR_THRE) == 0) ; -+ com_port->thr = c; -+} -+ -+unsigned char -+serial_getc(volatile struct NS16550 *com_port) -+{ -+ while ((com_port->lsr & LSR_DR) == 0) ; -+ return (com_port->rbr); -+} -+ -+int -+serial_tstc(volatile struct NS16550 *com_port) -+{ -+ return ((com_port->lsr & LSR_DR) != 0); -+} ---- linux/arch/mips/zboot/common/string.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/common/string.c 2003-12-18 17:11:10.000000000 -0500 -@@ -0,0 +1,497 @@ -+/* -+ * linux/lib/string.c -+ * -+ * Copyright (C) 1991, 1992 Linus Torvalds -+ */ -+ -+/* -+ * stupid library routines.. The optimized versions should generally be found -+ * as inline code in -+ * -+ * These are buggy as well.. -+ * -+ * * Fri Jun 25 1999, Ingo Oeser -+ * - Added strsep() which will replace strtok() soon (because strsep() is -+ * reentrant and should be faster). Use only strsep() in new code, please. -+ */ -+ -+#include -+#include -+#include -+ -+/** -+ * strnicmp - Case insensitive, length-limited string comparison -+ * @s1: One string -+ * @s2: The other string -+ * @len: the maximum number of characters to compare -+ */ -+int strnicmp(const char *s1, const char *s2, size_t len) -+{ -+ /* Yes, Virginia, it had better be unsigned */ -+ unsigned char c1, c2; -+ -+ c1 = 0; c2 = 0; -+ if (len) { -+ do { -+ c1 = *s1; c2 = *s2; -+ s1++; s2++; -+ if (!c1) -+ break; -+ if (!c2) -+ break; -+ if (c1 == c2) -+ continue; -+ c1 = tolower(c1); -+ c2 = tolower(c2); -+ if (c1 != c2) -+ break; -+ } while (--len); -+ } -+ return (int)c1 - (int)c2; -+} -+ -+char * ___strtok; -+ -+#ifndef __HAVE_ARCH_STRCPY -+/** -+ * strcpy - Copy a %NUL terminated string -+ * @dest: Where to copy the string to -+ * @src: Where to copy the string from -+ */ -+char * strcpy(char * dest,const char *src) -+{ -+ char *tmp = dest; -+ -+ while ((*dest++ = *src++) != '\0') -+ /* nothing */; -+ return tmp; -+} -+#endif -+ -+#ifndef __HAVE_ARCH_STRNCPY -+/** -+ * strncpy - Copy a length-limited, %NUL-terminated string -+ * @dest: Where to copy the string to -+ * @src: Where to copy the string from -+ * @count: The maximum number of bytes to copy -+ * -+ * Note that unlike userspace strncpy, this does not %NUL-pad the buffer. -+ * However, the result is not %NUL-terminated if the source exceeds -+ * @count bytes. -+ */ -+char * strncpy(char * dest,const char *src,size_t count) -+{ -+ char *tmp = dest; -+ -+ while (count-- && (*dest++ = *src++) != '\0') -+ /* nothing */; -+ -+ return tmp; -+} -+#endif -+ -+/** -+ * strcat - Append one %NUL-terminated string to another -+ * @dest: The string to be appended to -+ * @src: The string to append to it -+ */ -+char * strcat(char * dest, const char * src) -+{ -+ char *tmp = dest; -+ -+ while (*dest) -+ dest++; -+ while ((*dest++ = *src++) != '\0') -+ ; -+ -+ return tmp; -+} -+ -+/** -+ * strncat - Append a length-limited, %NUL-terminated string to another -+ * @dest: The string to be appended to -+ * @src: The string to append to it -+ * @count: The maximum numbers of bytes to copy -+ * -+ * Note that in contrast to strncpy, strncat ensures the result is -+ * terminated. -+ */ -+char * strncat(char *dest, const char *src, size_t count) -+{ -+ char *tmp = dest; -+ -+ if (count) { -+ while (*dest) -+ dest++; -+ while ((*dest++ = *src++)) { -+ if (--count == 0) { -+ *dest = '\0'; -+ break; -+ } -+ } -+ } -+ -+ return tmp; -+} -+ -+#ifndef __HAVE_ARCH_STRCMP -+/** -+ * strcmp - Compare two strings -+ * @cs: One string -+ * @ct: Another string -+ */ -+int strcmp(const char * cs,const char * ct) -+{ -+ register signed char __res; -+ -+ while (1) { -+ if ((__res = *cs - *ct++) != 0 || !*cs++) -+ break; -+ } -+ -+ return __res; -+} -+#endif -+ -+#ifndef __HAVE_ARCH_STRNCMP -+/** -+ * strncmp - Compare two length-limited strings -+ * @cs: One string -+ * @ct: Another string -+ * @count: The maximum number of bytes to compare -+ */ -+int strncmp(const char * cs,const char * ct,size_t count) -+{ -+ register signed char __res = 0; -+ -+ while (count) { -+ if ((__res = *cs - *ct++) != 0 || !*cs++) -+ break; -+ count--; -+ } -+ -+ return __res; -+} -+#endif -+ -+/** -+ * strchr - Find the first occurrence of a character in a string -+ * @s: The string to be searched -+ * @c: The character to search for -+ */ -+char * strchr(const char * s, int c) -+{ -+ for(; *s != (char) c; ++s) -+ if (*s == '\0') -+ return NULL; -+ return (char *) s; -+} -+ -+/** -+ * strrchr - Find the last occurrence of a character in a string -+ * @s: The string to be searched -+ * @c: The character to search for -+ */ -+char * strrchr(const char * s, int c) -+{ -+ const char *p = s + strlen(s); -+ do { -+ if (*p == (char)c) -+ return (char *)p; -+ } while (--p >= s); -+ return NULL; -+} -+ -+/** -+ * strlen - Find the length of a string -+ * @s: The string to be sized -+ */ -+size_t strlen(const char * s) -+{ -+ const char *sc; -+ -+ for (sc = s; *sc != '\0'; ++sc) -+ /* nothing */; -+ return sc - s; -+} -+ -+/** -+ * strnlen - Find the length of a length-limited string -+ * @s: The string to be sized -+ * @count: The maximum number of bytes to search -+ */ -+size_t strnlen(const char * s, size_t count) -+{ -+ const char *sc; -+ -+ for (sc = s; count-- && *sc != '\0'; ++sc) -+ /* nothing */; -+ return sc - s; -+} -+ -+/** -+ * strspn - Calculate the length of the initial substring of @s which only -+ * contain letters in @accept -+ * @s: The string to be searched -+ * @accept: The string to search for -+ */ -+size_t strspn(const char *s, const char *accept) -+{ -+ const char *p; -+ const char *a; -+ size_t count = 0; -+ -+ for (p = s; *p != '\0'; ++p) { -+ for (a = accept; *a != '\0'; ++a) { -+ if (*p == *a) -+ break; -+ } -+ if (*a == '\0') -+ return count; -+ ++count; -+ } -+ -+ return count; -+} -+ -+/** -+ * strpbrk - Find the first occurrence of a set of characters -+ * @cs: The string to be searched -+ * @ct: The characters to search for -+ */ -+char * strpbrk(const char * cs,const char * ct) -+{ -+ const char *sc1,*sc2; -+ -+ for( sc1 = cs; *sc1 != '\0'; ++sc1) { -+ for( sc2 = ct; *sc2 != '\0'; ++sc2) { -+ if (*sc1 == *sc2) -+ return (char *) sc1; -+ } -+ } -+ return NULL; -+} -+ -+/** -+ * strtok - Split a string into tokens -+ * @s: The string to be searched -+ * @ct: The characters to search for -+ * -+ * WARNING: strtok is deprecated, use strsep instead. -+ */ -+char * strtok(char * s,const char * ct) -+{ -+ char *sbegin, *send; -+ -+ sbegin = s ? s : ___strtok; -+ if (!sbegin) { -+ return NULL; -+ } -+ sbegin += strspn(sbegin,ct); -+ if (*sbegin == '\0') { -+ ___strtok = NULL; -+ return( NULL ); -+ } -+ send = strpbrk( sbegin, ct); -+ if (send && *send != '\0') -+ *send++ = '\0'; -+ ___strtok = send; -+ return (sbegin); -+} -+ -+/** -+ * strsep - Split a string into tokens -+ * @s: The string to be searched -+ * @ct: The characters to search for -+ * -+ * strsep() updates @s to point after the token, ready for the next call. -+ * -+ * It returns empty tokens, too, behaving exactly like the libc function -+ * of that name. In fact, it was stolen from glibc2 and de-fancy-fied. -+ * Same semantics, slimmer shape. ;) -+ */ -+char * strsep(char **s, const char *ct) -+{ -+ char *sbegin = *s, *end; -+ -+ if (sbegin == NULL) -+ return NULL; -+ -+ end = strpbrk(sbegin, ct); -+ if (end) -+ *end++ = '\0'; -+ *s = end; -+ -+ return sbegin; -+} -+ -+/** -+ * memset - Fill a region of memory with the given value -+ * @s: Pointer to the start of the area. -+ * @c: The byte to fill the area with -+ * @count: The size of the area. -+ * -+ * Do not use memset() to access IO space, use memset_io() instead. -+ */ -+void * memset(void * s,int c, size_t count) -+{ -+ char *xs = (char *) s; -+ -+ while (count--) -+ *xs++ = c; -+ -+ return s; -+} -+ -+/** -+ * bcopy - Copy one area of memory to another -+ * @src: Where to copy from -+ * @dest: Where to copy to -+ * @count: The size of the area. -+ * -+ * Note that this is the same as memcpy(), with the arguments reversed. -+ * memcpy() is the standard, bcopy() is a legacy BSD function. -+ * -+ * You should not use this function to access IO space, use memcpy_toio() -+ * or memcpy_fromio() instead. -+ */ -+char * bcopy(const char * src, char * dest, int count) -+{ -+ char *tmp = dest; -+ -+ while (count--) -+ *tmp++ = *src++; -+ -+ return dest; -+} -+ -+/** -+ * memcpy - Copy one area of memory to another -+ * @dest: Where to copy to -+ * @src: Where to copy from -+ * @count: The size of the area. -+ * -+ * You should not use this function to access IO space, use memcpy_toio() -+ * or memcpy_fromio() instead. -+ */ -+void * memcpy(void * dest,const void *src,size_t count) -+{ -+ char *tmp = (char *) dest, *s = (char *) src; -+ -+ while (count--) -+ *tmp++ = *s++; -+ -+ return dest; -+} -+ -+/** -+ * memmove - Copy one area of memory to another -+ * @dest: Where to copy to -+ * @src: Where to copy from -+ * @count: The size of the area. -+ * -+ * Unlike memcpy(), memmove() copes with overlapping areas. -+ */ -+void * memmove(void * dest,const void *src,size_t count) -+{ -+ char *tmp, *s; -+ -+ if (dest <= src) { -+ tmp = (char *) dest; -+ s = (char *) src; -+ while (count--) -+ *tmp++ = *s++; -+ } -+ else { -+ tmp = (char *) dest + count; -+ s = (char *) src + count; -+ while (count--) -+ *--tmp = *--s; -+ } -+ -+ return dest; -+} -+ -+/** -+ * memcmp - Compare two areas of memory -+ * @cs: One area of memory -+ * @ct: Another area of memory -+ * @count: The size of the area. -+ */ -+int memcmp(const void * cs,const void * ct,size_t count) -+{ -+ const unsigned char *su1, *su2; -+ signed char res = 0; -+ -+ for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) -+ if ((res = *su1 - *su2) != 0) -+ break; -+ return res; -+} -+ -+#ifndef __HAVE_ARCH_MEMSCAN -+/** -+ * memscan - Find a character in an area of memory. -+ * @addr: The memory area -+ * @c: The byte to search for -+ * @size: The size of the area. -+ * -+ * returns the address of the first occurrence of @c, or 1 byte past -+ * the area if @c is not found -+ */ -+void * memscan(void * addr, int c, size_t size) -+{ -+ unsigned char * p = (unsigned char *) addr; -+ unsigned char * e = p + size; -+ -+ while (p != e) { -+ if (*p == c) -+ return (void *) p; -+ p++; -+ } -+ -+ return (void *) p; -+} -+#endif -+ -+/** -+ * strstr - Find the first substring in a %NUL terminated string -+ * @s1: The string to be searched -+ * @s2: The string to search for -+ */ -+char * strstr(const char * s1,const char * s2) -+{ -+ int l1, l2; -+ -+ l2 = strlen(s2); -+ if (!l2) -+ return (char *) s1; -+ l1 = strlen(s1); -+ while (l1 >= l2) { -+ l1--; -+ if (!memcmp(s1,s2,l2)) -+ return (char *) s1; -+ s1++; -+ } -+ return NULL; -+} -+ -+/** -+ * memchr - Find a character in an area of memory. -+ * @s: The memory area -+ * @c: The byte to search for -+ * @n: The size of the area. -+ * -+ * returns the address of the first occurrence of @c, or %NULL -+ * if @c is not found -+ */ -+void *memchr(const void *s, int c, size_t n) -+{ -+ const unsigned char *p = s; -+ while (n-- != 0) { -+ if ((unsigned char)c == *p++) { -+ return (void *)(p-1); -+ } -+ } -+ return NULL; -+} -diff -Naru linux/arch/mips/zboot/csb250/head.S linux-new/arch/mips/zboot/csb250/head.S ---- linux/arch/mips/zboot/csb250/head.S 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/csb250/head.S 2003-12-18 14:26:20.000000000 -0500 -@@ -0,0 +1,157 @@ -+/* -+ * arch/mips/kernel/head.S -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 1994, 1995 Waldorf Electronics -+ * Written by Ralf Baechle and Andreas Busse -+ * Copyright (C) 1995 - 1999 Ralf Baechle -+ * Copyright (C) 1996 Paul M. Antoine -+ * Modified for DECStation and hence R3000 support by Paul M. Antoine -+ * Further modifications by David S. Miller and Harald Koerfgen -+ * Copyright (C) 1999 Silicon Graphics, Inc. -+ * -+ * Head.S contains the MIPS exception handler and startup code. -+ * -+ ************************************************************************** -+ * 9 Nov, 2000. -+ * Added Cache Error exception handler and SBDDP EJTAG debug exception. -+ * -+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com -+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. -+ ************************************************************************** -+ */ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define IndexInvalidate_I 0x00 -+#define IndexWriteBack_D 0x01 -+ -+ .set noreorder -+ .cprestore -+ LEAF(start) -+start: -+ bal locate -+ nop -+ -+ .globl asize /* Someday we'll put the initrd info here. */ -+asize: .word 0 -+ .word 0 -+ .word 0 -+ .word 0 -+ -+locate: -+ subu s8, ra, 8 /* Where we were loaded */ -+ la sp, (.stack + 8192) -+ -+ move s0, a0 /* Save boot rom start args */ -+ move s1, a1 -+ move s2, a2 -+ move s3, a3 -+ -+ la a0, start /* Where we were linked to run */ -+ -+ move a1, s8 -+ la a2, _edata -+ subu t1, a2, a0 -+ srl t1, t1, 2 -+ -+ /* copy text section */ -+ li t0, 0 -+1: lw v0, 0(a1) -+ nop -+ sw v0, 0(a0) -+ xor t0, t0, v0 -+ addu a0, 4 -+ bne a2, a0, 1b -+ addu a1, 4 -+ -+ /* Clear BSS */ -+ la a0, _edata -+ la a2, _end -+2: sw zero, 0(a0) -+ bne a2, a0, 2b -+ addu a0, 4 -+ -+ /* push the D-Cache and invalidate I-Cache */ -+ li k0, 0x80000000 # start address -+ li k1, 0x80004000 # end address (16KB I-Cache) -+ subu k1, 128 -+ -+1: -+ .set mips3 -+ cache IndexWriteBack_D, 0(k0) -+ cache IndexWriteBack_D, 32(k0) -+ cache IndexWriteBack_D, 64(k0) -+ cache IndexWriteBack_D, 96(k0) -+ cache IndexInvalidate_I, 0(k0) -+ cache IndexInvalidate_I, 32(k0) -+ cache IndexInvalidate_I, 64(k0) -+ cache IndexInvalidate_I, 96(k0) -+ .set mips0 -+ -+ bne k0, k1, 1b -+ addu k0, k0, 128 -+ /* done */ -+ -+/* move a0, s8 /* load address */ -+ subu a0, s8, 0x1000 /* load address */ -+ move a1, t1 /* length in words */ -+ move a2, t0 /* checksum */ -+ move a3, sp -+ -+ la ra, 1f -+ la k0, decompress_kernel -+ jr k0 -+ nop -+1: -+ -+ la a2, __ramdisk_begin -+ la a3, initrd_size -+ lw a0, 0(a2) -+ lw a1, 0(a3) -+ li k0, KERNEL_ENTRY -+ jr k0 -+ nop -+3: -+ b 3b -+ END(start) -+ -+ LEAF(udelay) -+udelay: -+ END(udelay) -+ -+ -+ LEAF(FlushCache) -+ li k0, 0x80000000 # start address -+ li k1, 0x80004000 # end address (16KB I-Cache) -+ subu k1, 128 -+ -+1: -+ .set mips3 -+ cache IndexWriteBack_D, 0(k0) -+ cache IndexWriteBack_D, 32(k0) -+ cache IndexWriteBack_D, 64(k0) -+ cache IndexWriteBack_D, 96(k0) -+ cache IndexInvalidate_I, 0(k0) -+ cache IndexInvalidate_I, 32(k0) -+ cache IndexInvalidate_I, 64(k0) -+ cache IndexInvalidate_I, 96(k0) -+ .set mips0 -+ -+ bne k0, k1, 1b -+ addu k0, k0, 128 -+ jr ra -+ nop -+ END(FlushCache) -+ -+ .comm .stack,4096*2,4 -diff -Naru linux/arch/mips/zboot/csb250/Makefile linux-new/arch/mips/zboot/csb250/Makefile ---- linux/arch/mips/zboot/csb250/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/csb250/Makefile 2003-12-18 14:26:20.000000000 -0500 -@@ -0,0 +1,90 @@ -+# arch/mips/zboot/pb1xxx/Makefile -+# -+# Makefile for Cogent CSB250 Au1500 board. -+# All of the boot loader code was derived from the ppc -+# boot code. -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by the -+# Free Software Foundation; either version 2 of the License, or (at your -+# option) any later version. -+ -+.c.s: -+ $(CC) $(CFLAGS) -S -o $*.s $< -+.s.o: -+ $(AS) -o $*.o $< -+.c.o: -+ $(CC) $(CFLAGS) -D__BOOTER__ -c -o $*.o $< -+.S.s: -+ $(CPP) $(AFLAGS) -o $*.o $< -+.S.o: -+ $(CC) $(AFLAGS) -c -o $*.o $< -+ -+######################################################################### -+# START BOARD SPECIFIC VARIABLES -+BNAME=csb250 -+ -+# These two variables control where the zImage is stored -+# in flash and loaded in memory. It only controls how the srec -+# file is generated, the code is the same. -+RAM_RUN_ADDR = 0x80a00000 -+FLASH_LOAD_ADDR = 0xBFD00000 -+ -+# These two variables specify the free ram region -+# that can be used for temporary malloc area -+AVAIL_RAM_START=0x80400000 -+AVAIL_RAM_END=0x80800000 -+ -+# This one must match the LOADADDR in arch/mips/Makefile! -+LOADADDR=0x80100000 -+# END BOARD SPECIFIC VARIABLES -+######################################################################### -+ -+OBJECTS := head.o ../common/misc-common.o ../common/misc-simple.o \ -+ ../common/au1k_uart.o ../common/string.o ../common/ctype.o -+LIBS := ../lib/zlib.a -+ -+ENTRY := ../utils/entry -+OFFSET := ../utils/offset -+SIZE := ../utils/size -+ -+LD_ARGS := -T ../ld.script -Ttext $(RAM_RUN_ADDR) -Bstatic -+OBJCOPY_ARGS = -O elf32-tradbigmips -+ -+all: zImage -+ -+clean: -+ rm -rf *.o vmlinux* zvmlinux.* ../images/*.srec -+ -+head.o: head.S $(TOPDIR)/vmlinux -+ $(CC) $(AFLAGS) \ -+ -DKERNEL_ENTRY=$(shell sh $(ENTRY) $(NM) $(TOPDIR)/vmlinux ) \ -+ -c -o $*.o $< -+ -+../common/misc-simple.o: -+ $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \ -+ -DAVAIL_RAM_START=$(AVAIL_RAM_START) \ -+ -DAVAIL_RAM_END=$(AVAIL_RAM_END) \ -+ -DLOADADDR=$(LOADADDR) \ -+ -DZIMAGE_SIZE=0 -c -o $@ $*.c -+ -+zvmlinux: $(OBJECTS) $(LIBS) ../ld.script ../images/vmlinux.gz ../common/dummy.o -+ $(OBJCOPY) \ -+ --add-section=.image=../images/vmlinux.gz \ -+ --set-section-flags=.image=contents,alloc,load,readonly,data \ -+ ../common/dummy.o image.o -+ $(LD) $(LD_ARGS) -o $@ $(OBJECTS) image.o $(LIBS) -+ $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr \ -+ -R .initrd -R .sysmap -+ -+# Here we manipulate the image in order to get it the necessary -+# srecord file we need. -+zImage: zvmlinux -+ mv zvmlinux ../images/zImage.$(BNAME) -+ $(OBJCOPY) -O binary ../images/zImage.$(BNAME) ../images/$(BNAME).bin -+ -+zImage.flash: zImage -+ $(OBJCOPY) -O srec --adjust-vma 0x3ed00000 \ -+ ../images/zImage.$(BNAME) ../images/$(BNAME).flash.srec -+ -+include $(TOPDIR)/Rules.make -diff -Naru linux/arch/mips/zboot/images/Makefile linux-new/arch/mips/zboot/images/Makefile ---- linux/arch/mips/zboot/images/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/images/Makefile 2003-12-18 14:26:20.000000000 -0500 -@@ -0,0 +1,10 @@ -+ -+include $(TOPDIR)/Rules.make -+ -+vmlinux.gz: $(TOPDIR)/vmlinux -+ $(OBJCOPY) -S -O binary $(TOPDIR)/vmlinux vmlinux -+ gzip -vf vmlinux -+ -+clean: -+ rm -f vmlinux.* zImage.* -+ -diff -Naru linux/arch/mips/zboot/include/nonstdio.h linux-new/arch/mips/zboot/include/nonstdio.h ---- linux/arch/mips/zboot/include/nonstdio.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/include/nonstdio.h 2003-12-18 14:26:20.000000000 -0500 -@@ -0,0 +1,18 @@ -+/* -+ * Copyright (C) Paul Mackerras 1997. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+typedef int FILE; -+extern FILE *stdin, *stdout; -+#define NULL ((void *)0) -+#define EOF (-1) -+#define fopen(n, m) NULL -+#define fflush(f) 0 -+#define fclose(f) 0 -+extern char *fgets(); -+ -+#define perror(s) printf("%s: no files!\n", (s)) -diff -Naru linux/arch/mips/zboot/include/ns16550.h linux-new/arch/mips/zboot/include/ns16550.h ---- linux/arch/mips/zboot/include/ns16550.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/include/ns16550.h 2003-12-18 14:26:20.000000000 -0500 -@@ -0,0 +1,49 @@ -+/* -+ * NS16550 Serial Port -+ */ -+ -+/* -+ * Figure out which file will have the definitons of COMx -+ */ -+#if !defined(CONFIG_AU1X00_UART) -+#error no serial.h -+#endif -+ -+/* Some machines have their uart registers 16 bytes apart. Most don't. -+ * TODO: Make this work like drivers/char/serial does - Tom */ -+#if !defined(UART_REG_PAD) -+#define UART_REG_PAD(x) -+#endif -+ -+struct NS16550 -+ { -+ unsigned char rbr; /* 0 */ -+ UART_REG_PAD(rbr) -+ unsigned char ier; /* 1 */ -+ UART_REG_PAD(ier) -+ unsigned char fcr; /* 2 */ -+ UART_REG_PAD(fcr) -+ unsigned char lcr; /* 3 */ -+ UART_REG_PAD(lcr) -+ unsigned char mcr; /* 4 */ -+ UART_REG_PAD(mcr) -+ unsigned char lsr; /* 5 */ -+ UART_REG_PAD(lsr) -+ unsigned char msr; /* 6 */ -+ UART_REG_PAD(msr) -+ unsigned char scr; /* 7 */ -+ }; -+ -+#define thr rbr -+#define iir fcr -+#define dll rbr -+#define dlm ier -+ -+#define LSR_DR 0x01 /* Data ready */ -+#define LSR_OE 0x02 /* Overrun */ -+#define LSR_PE 0x04 /* Parity error */ -+#define LSR_FE 0x08 /* Framing error */ -+#define LSR_BI 0x10 /* Break */ -+#define LSR_THRE 0x20 /* Xmit holding register empty */ -+#define LSR_TEMT 0x40 /* Xmitter empty */ -+#define LSR_ERR 0x80 /* Error */ -diff -Naru linux/arch/mips/zboot/include/pb1000_serial.h linux-new/arch/mips/zboot/include/pb1000_serial.h ---- linux/arch/mips/zboot/include/pb1000_serial.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/include/pb1000_serial.h 2003-12-18 14:26:20.000000000 -0500 -@@ -0,0 +1,20 @@ -+/* -+ * arch/ppc/boot/include/sandpoint_serial.h -+ * -+ * Location of the COM ports on Motorola SPS Sandpoint machines -+ * -+ * Author: Mark A. Greer -+ * mgreer@mvista.com -+ * -+ * Copyright 2001 MontaVista Software 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. -+ */ -+ -+#define COM1 0xfe0003f8 -+#define COM2 0xfe0002f8 -+#define COM3 0x00000000 /* No COM3 */ -+#define COM4 0x00000000 /* No COM4 */ -diff -Naru linux/arch/mips/zboot/include/zlib.h linux-new/arch/mips/zboot/include/zlib.h ---- linux/arch/mips/zboot/include/zlib.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/include/zlib.h 2003-12-18 14:26:21.000000000 -0500 -@@ -0,0 +1,432 @@ -+/* $Id$ */ -+ -+/* -+ * This file is derived from zlib.h and zconf.h from the zlib-0.95 -+ * distribution by Jean-loup Gailly and Mark Adler, with some additions -+ * by Paul Mackerras to aid in implementing Deflate compression and -+ * decompression for PPP packets. -+ */ -+ -+/* -+ * ==FILEVERSION 960122== -+ * -+ * This marker is used by the Linux installation script to determine -+ * whether an up-to-date version of this file is already installed. -+ */ -+ -+/* zlib.h -- interface of the 'zlib' general purpose compression library -+ version 0.95, Aug 16th, 1995. -+ -+ Copyright (C) 1995 Jean-loup Gailly and Mark Adler -+ -+ This software is provided 'as-is', without any express or implied -+ warranty. In no event will the authors be held liable for any damages -+ arising from the use of this software. -+ -+ Permission is granted to anyone to use this software for any purpose, -+ including commercial applications, and to alter it and redistribute it -+ freely, subject to the following restrictions: -+ -+ 1. The origin of this software must not be misrepresented; you must not -+ claim that you wrote the original software. If you use this software -+ in a product, an acknowledgment in the product documentation would be -+ appreciated but is not required. -+ 2. Altered source versions must be plainly marked as such, and must not be -+ misrepresented as being the original software. -+ 3. This notice may not be removed or altered from any source distribution. -+ -+ Jean-loup Gailly Mark Adler -+ gzip@prep.ai.mit.edu madler@alumni.caltech.edu -+ */ -+ -+#ifndef _ZLIB_H -+#define _ZLIB_H -+ -+/* #include "zconf.h" */ /* included directly here */ -+ -+/* zconf.h -- configuration of the zlib compression library -+ * Copyright (C) 1995 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */ -+ -+/* -+ The library does not install any signal handler. It is recommended to -+ add at least a handler for SIGSEGV when decompressing; the library checks -+ the consistency of the input data whenever possible but may go nuts -+ for some forms of corrupted input. -+ */ -+ -+/* -+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more -+ * than 64k bytes at a time (needed on systems with 16-bit int). -+ * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints -+ * at addresses which are not a multiple of their size. -+ * Under DOS, -DFAR=far or -DFAR=__far may be needed. -+ */ -+ -+#ifndef STDC -+# if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus) -+# define STDC -+# endif -+#endif -+ -+#ifdef __MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */ -+# include -+#endif -+ -+/* Maximum value for memLevel in deflateInit2 */ -+#ifndef MAX_MEM_LEVEL -+# ifdef MAXSEG_64K -+# define MAX_MEM_LEVEL 8 -+# else -+# define MAX_MEM_LEVEL 9 -+# endif -+#endif -+ -+#ifndef FAR -+# define FAR -+#endif -+ -+/* Maximum value for windowBits in deflateInit2 and inflateInit2 */ -+#ifndef MAX_WBITS -+# define MAX_WBITS 15 /* 32K LZ77 window */ -+#endif -+ -+/* The memory requirements for deflate are (in bytes): -+ 1 << (windowBits+2) + 1 << (memLevel+9) -+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) -+ plus a few kilobytes for small objects. For example, if you want to reduce -+ the default memory requirements from 256K to 128K, compile with -+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" -+ Of course this will generally degrade compression (there's no free lunch). -+ -+ The memory requirements for inflate are (in bytes) 1 << windowBits -+ that is, 32K for windowBits=15 (default value) plus a few kilobytes -+ for small objects. -+*/ -+ -+ /* Type declarations */ -+ -+#ifndef OF /* function prototypes */ -+# ifdef STDC -+# define OF(args) args -+# else -+# define OF(args) () -+# endif -+#endif -+ -+typedef unsigned char Byte; /* 8 bits */ -+typedef unsigned int uInt; /* 16 bits or more */ -+typedef unsigned long uLong; /* 32 bits or more */ -+ -+typedef Byte FAR Bytef; -+typedef char FAR charf; -+typedef int FAR intf; -+typedef uInt FAR uIntf; -+typedef uLong FAR uLongf; -+ -+#ifdef STDC -+ typedef void FAR *voidpf; -+ typedef void *voidp; -+#else -+ typedef Byte FAR *voidpf; -+ typedef Byte *voidp; -+#endif -+ -+/* end of original zconf.h */ -+ -+#define ZLIB_VERSION "0.95P" -+ -+/* -+ The 'zlib' compression library provides in-memory compression and -+ decompression functions, including integrity checks of the uncompressed -+ data. This version of the library supports only one compression method -+ (deflation) but other algorithms may be added later and will have the same -+ stream interface. -+ -+ For compression the application must provide the output buffer and -+ may optionally provide the input buffer for optimization. For decompression, -+ the application must provide the input buffer and may optionally provide -+ the output buffer for optimization. -+ -+ Compression can be done in a single step if the buffers are large -+ enough (for example if an input file is mmap'ed), or can be done by -+ repeated calls of the compression function. In the latter case, the -+ application must provide more input and/or consume the output -+ (providing more output space) before each call. -+*/ -+ -+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -+typedef void (*free_func) OF((voidpf opaque, voidpf address, uInt nbytes)); -+ -+struct internal_state; -+ -+typedef struct z_stream_s { -+ Bytef *next_in; /* next input byte */ -+ uInt avail_in; /* number of bytes available at next_in */ -+ uLong total_in; /* total nb of input bytes read so far */ -+ -+ Bytef *next_out; /* next output byte should be put there */ -+ uInt avail_out; /* remaining free space at next_out */ -+ uLong total_out; /* total nb of bytes output so far */ -+ -+ char *msg; /* last error message, NULL if no error */ -+ struct internal_state FAR *state; /* not visible by applications */ -+ -+ alloc_func zalloc; /* used to allocate the internal state */ -+ free_func zfree; /* used to free the internal state */ -+ voidp opaque; /* private data object passed to zalloc and zfree */ -+ -+ Byte data_type; /* best guess about the data type: ascii or binary */ -+ -+} z_stream; -+ -+/* -+ The application must update next_in and avail_in when avail_in has -+ dropped to zero. It must update next_out and avail_out when avail_out -+ has dropped to zero. The application must initialize zalloc, zfree and -+ opaque before calling the init function. All other fields are set by the -+ compression library and must not be updated by the application. -+ -+ The opaque value provided by the application will be passed as the first -+ parameter for calls of zalloc and zfree. This can be useful for custom -+ memory management. The compression library attaches no meaning to the -+ opaque value. -+ -+ zalloc must return Z_NULL if there is not enough memory for the object. -+ On 16-bit systems, the functions zalloc and zfree must be able to allocate -+ exactly 65536 bytes, but will not be required to allocate more than this -+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, -+ pointers returned by zalloc for objects of exactly 65536 bytes *must* -+ have their offset normalized to zero. The default allocation function -+ provided by this library ensures this (see zutil.c). To reduce memory -+ requirements and avoid any allocation of 64K objects, at the expense of -+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). -+ -+ The fields total_in and total_out can be used for statistics or -+ progress reports. After compression, total_in holds the total size of -+ the uncompressed data and may be saved for use in the decompressor -+ (particularly if the decompressor wants to decompress everything in -+ a single step). -+*/ -+ -+ /* constants */ -+ -+#define Z_NO_FLUSH 0 -+#define Z_PARTIAL_FLUSH 1 -+#define Z_FULL_FLUSH 2 -+#define Z_SYNC_FLUSH 3 /* experimental: partial_flush + byte align */ -+#define Z_FINISH 4 -+#define Z_PACKET_FLUSH 5 -+/* See deflate() below for the usage of these constants */ -+ -+#define Z_OK 0 -+#define Z_STREAM_END 1 -+#define Z_ERRNO (-1) -+#define Z_STREAM_ERROR (-2) -+#define Z_DATA_ERROR (-3) -+#define Z_MEM_ERROR (-4) -+#define Z_BUF_ERROR (-5) -+/* error codes for the compression/decompression functions */ -+ -+#define Z_BEST_SPEED 1 -+#define Z_BEST_COMPRESSION 9 -+#define Z_DEFAULT_COMPRESSION (-1) -+/* compression levels */ -+ -+#define Z_FILTERED 1 -+#define Z_HUFFMAN_ONLY 2 -+#define Z_DEFAULT_STRATEGY 0 -+ -+#define Z_BINARY 0 -+#define Z_ASCII 1 -+#define Z_UNKNOWN 2 -+/* Used to set the data_type field */ -+ -+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ -+ -+extern char *zlib_version; -+/* The application can compare zlib_version and ZLIB_VERSION for consistency. -+ If the first character differs, the library code actually used is -+ not compatible with the zlib.h header file used by the application. -+ */ -+ -+ /* basic functions */ -+ -+extern int inflateInit OF((z_stream *strm)); -+/* -+ Initializes the internal stream state for decompression. The fields -+ zalloc and zfree must be initialized before by the caller. If zalloc and -+ zfree are set to Z_NULL, inflateInit updates them to use default allocation -+ functions. -+ -+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory. msg is set to null if there is no error message. -+ inflateInit does not perform any decompression: this will be done by -+ inflate(). -+*/ -+ -+ -+extern int inflate OF((z_stream *strm, int flush)); -+/* -+ Performs one or both of the following actions: -+ -+ - Decompress more input starting at next_in and update next_in and avail_in -+ accordingly. If not all input can be processed (because there is not -+ enough room in the output buffer), next_in is updated and processing -+ will resume at this point for the next call of inflate(). -+ -+ - Provide more output starting at next_out and update next_out and avail_out -+ accordingly. inflate() always provides as much output as possible -+ (until there is no more input data or no more space in the output buffer). -+ -+ Before the call of inflate(), the application should ensure that at least -+ one of the actions is possible, by providing more input and/or consuming -+ more output, and updating the next_* and avail_* values accordingly. -+ The application can consume the uncompressed output when it wants, for -+ example when the output buffer is full (avail_out == 0), or after each -+ call of inflate(). -+ -+ If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH, -+ inflate flushes as much output as possible to the output buffer. The -+ flushing behavior of inflate is not specified for values of the flush -+ parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the -+ current implementation actually flushes as much output as possible -+ anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data -+ has been consumed, it is expecting to see the length field of a stored -+ block; if not, it returns Z_DATA_ERROR. -+ -+ inflate() should normally be called until it returns Z_STREAM_END or an -+ error. However if all decompression is to be performed in a single step -+ (a single call of inflate), the parameter flush should be set to -+ Z_FINISH. In this case all pending input is processed and all pending -+ output is flushed; avail_out must be large enough to hold all the -+ uncompressed data. (The size of the uncompressed data may have been saved -+ by the compressor for this purpose.) The next operation on this stream must -+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH -+ is never required, but can be used to inform inflate that a faster routine -+ may be used for the single inflate() call. -+ -+ inflate() returns Z_OK if some progress has been made (more input -+ processed or more output produced), Z_STREAM_END if the end of the -+ compressed data has been reached and all uncompressed output has been -+ produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if -+ the stream structure was inconsistent (for example if next_in or next_out -+ was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no -+ progress is possible or if there was not enough room in the output buffer -+ when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then -+ call inflateSync to look for a good compression block. */ -+ -+ -+extern int inflateEnd OF((z_stream *strm)); -+/* -+ All dynamically allocated data structures for this stream are freed. -+ This function discards any unprocessed input and does not flush any -+ pending output. -+ -+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state -+ was inconsistent. In the error case, msg may be set but then points to a -+ static string (which must not be deallocated). -+*/ -+ -+ /* advanced functions */ -+ -+extern int inflateInit2 OF((z_stream *strm, -+ int windowBits)); -+/* -+ This is another version of inflateInit with more compression options. The -+ fields next_out, zalloc and zfree must be initialized before by the caller. -+ -+ The windowBits parameter is the base two logarithm of the maximum window -+ size (the size of the history buffer). It should be in the range 8..15 for -+ this version of the library (the value 16 will be allowed soon). The -+ default value is 15 if inflateInit is used instead. If a compressed stream -+ with a larger window size is given as input, inflate() will return with -+ the error code Z_DATA_ERROR instead of trying to allocate a larger window. -+ -+ If next_out is not null, the library will use this buffer for the history -+ buffer; the buffer must either be large enough to hold the entire output -+ data, or have at least 1<msg=z_errmsg[1-err], err) -+/* To be used only when the state is known to be valid */ -+ -+#ifndef NULL -+#define NULL ((void *) 0) -+#endif -+ -+ /* common constants */ -+ -+#define DEFLATED 8 -+ -+#ifndef DEF_WBITS -+# define DEF_WBITS MAX_WBITS -+#endif -+/* default windowBits for decompression. MAX_WBITS is for compression only */ -+ -+#if MAX_MEM_LEVEL >= 8 -+# define DEF_MEM_LEVEL 8 -+#else -+# define DEF_MEM_LEVEL MAX_MEM_LEVEL -+#endif -+/* default memLevel */ -+ -+#define STORED_BLOCK 0 -+#define STATIC_TREES 1 -+#define DYN_TREES 2 -+/* The three kinds of block type */ -+ -+#define MIN_MATCH 3 -+#define MAX_MATCH 258 -+/* The minimum and maximum match lengths */ -+ -+ /* functions */ -+ -+#include -+#define zmemcpy memcpy -+#define zmemzero(dest, len) memset(dest, 0, len) -+ -+/* Diagnostic functions */ -+#ifdef DEBUG_ZLIB -+# include -+# ifndef verbose -+# define verbose 0 -+# endif -+# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -+# define Trace(x) fprintf x -+# define Tracev(x) {if (verbose) fprintf x ;} -+# define Tracevv(x) {if (verbose>1) fprintf x ;} -+# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -+# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} -+#else -+# define Assert(cond,msg) -+# define Trace(x) -+# define Tracev(x) -+# define Tracevv(x) -+# define Tracec(c,x) -+# define Tracecv(c,x) -+#endif -+ -+ -+typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len)); -+ -+/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */ -+/* void zcfree OF((voidpf opaque, voidpf ptr)); */ -+ -+#define ZALLOC(strm, items, size) \ -+ (*((strm)->zalloc))((strm)->opaque, (items), (size)) -+#define ZFREE(strm, addr, size) \ -+ (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size)) -+#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);} -+ -+/* deflate.h -- internal compression state -+ * Copyright (C) 1995 Jean-loup Gailly -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+/*+++++*/ -+/* infblock.h -- header to use infblock.c -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+struct inflate_blocks_state; -+typedef struct inflate_blocks_state FAR inflate_blocks_statef; -+ -+local inflate_blocks_statef * inflate_blocks_new OF(( -+ z_stream *z, -+ check_func c, /* check function */ -+ uInt w)); /* window size */ -+ -+local int inflate_blocks OF(( -+ inflate_blocks_statef *, -+ z_stream *, -+ int)); /* initial return code */ -+ -+local void inflate_blocks_reset OF(( -+ inflate_blocks_statef *, -+ z_stream *, -+ uLongf *)); /* check value on output */ -+ -+local int inflate_blocks_free OF(( -+ inflate_blocks_statef *, -+ z_stream *, -+ uLongf *)); /* check value on output */ -+ -+local int inflate_addhistory OF(( -+ inflate_blocks_statef *, -+ z_stream *)); -+ -+local int inflate_packet_flush OF(( -+ inflate_blocks_statef *)); -+ -+/*+++++*/ -+/* inftrees.h -- header to use inftrees.c -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+/* Huffman code lookup table entry--this entry is four bytes for machines -+ that have 16-bit pointers (e.g. PC's in the small or medium model). */ -+ -+typedef struct inflate_huft_s FAR inflate_huft; -+ -+struct inflate_huft_s { -+ union { -+ struct { -+ Byte Exop; /* number of extra bits or operation */ -+ Byte Bits; /* number of bits in this code or subcode */ -+ } what; -+ uInt Nalloc; /* number of these allocated here */ -+ Bytef *pad; /* pad structure to a power of 2 (4 bytes for */ -+ } word; /* 16-bit, 8 bytes for 32-bit machines) */ -+ union { -+ uInt Base; /* literal, length base, or distance base */ -+ inflate_huft *Next; /* pointer to next level of table */ -+ } more; -+}; -+ -+#ifdef DEBUG_ZLIB -+ local uInt inflate_hufts; -+#endif -+ -+local int inflate_trees_bits OF(( -+ uIntf *, /* 19 code lengths */ -+ uIntf *, /* bits tree desired/actual depth */ -+ inflate_huft * FAR *, /* bits tree result */ -+ z_stream *)); /* for zalloc, zfree functions */ -+ -+local int inflate_trees_dynamic OF(( -+ uInt, /* number of literal/length codes */ -+ uInt, /* number of distance codes */ -+ uIntf *, /* that many (total) code lengths */ -+ uIntf *, /* literal desired/actual bit depth */ -+ uIntf *, /* distance desired/actual bit depth */ -+ inflate_huft * FAR *, /* literal/length tree result */ -+ inflate_huft * FAR *, /* distance tree result */ -+ z_stream *)); /* for zalloc, zfree functions */ -+ -+local int inflate_trees_fixed OF(( -+ uIntf *, /* literal desired/actual bit depth */ -+ uIntf *, /* distance desired/actual bit depth */ -+ inflate_huft * FAR *, /* literal/length tree result */ -+ inflate_huft * FAR *)); /* distance tree result */ -+ -+local int inflate_trees_free OF(( -+ inflate_huft *, /* tables to free */ -+ z_stream *)); /* for zfree function */ -+ -+ -+/*+++++*/ -+/* infcodes.h -- header to use infcodes.c -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+struct inflate_codes_state; -+typedef struct inflate_codes_state FAR inflate_codes_statef; -+ -+local inflate_codes_statef *inflate_codes_new OF(( -+ uInt, uInt, -+ inflate_huft *, inflate_huft *, -+ z_stream *)); -+ -+local int inflate_codes OF(( -+ inflate_blocks_statef *, -+ z_stream *, -+ int)); -+ -+local void inflate_codes_free OF(( -+ inflate_codes_statef *, -+ z_stream *)); -+ -+ -+/*+++++*/ -+/* inflate.c -- zlib interface to inflate modules -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* inflate private state */ -+struct internal_state { -+ -+ /* mode */ -+ enum { -+ METHOD, /* waiting for method byte */ -+ FLAG, /* waiting for flag byte */ -+ BLOCKS, /* decompressing blocks */ -+ CHECK4, /* four check bytes to go */ -+ CHECK3, /* three check bytes to go */ -+ CHECK2, /* two check bytes to go */ -+ CHECK1, /* one check byte to go */ -+ DONE, /* finished check, done */ -+ BAD} /* got an error--stay here */ -+ mode; /* current inflate mode */ -+ -+ /* mode dependent information */ -+ union { -+ uInt method; /* if FLAGS, method byte */ -+ struct { -+ uLong was; /* computed check value */ -+ uLong need; /* stream check value */ -+ } check; /* if CHECK, check values to compare */ -+ uInt marker; /* if BAD, inflateSync's marker bytes count */ -+ } sub; /* submode */ -+ -+ /* mode independent information */ -+ int nowrap; /* flag for no wrapper */ -+ uInt wbits; /* log2(window size) (8..15, defaults to 15) */ -+ inflate_blocks_statef -+ *blocks; /* current inflate_blocks state */ -+ -+}; -+ -+ -+int inflateReset(z) -+z_stream *z; -+{ -+ uLong c; -+ -+ if (z == Z_NULL || z->state == Z_NULL) -+ return Z_STREAM_ERROR; -+ z->total_in = z->total_out = 0; -+ z->msg = Z_NULL; -+ z->state->mode = z->state->nowrap ? BLOCKS : METHOD; -+ inflate_blocks_reset(z->state->blocks, z, &c); -+ Trace((stderr, "inflate: reset\n")); -+ return Z_OK; -+} -+ -+ -+int inflateEnd(z) -+z_stream *z; -+{ -+ uLong c; -+ -+ if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) -+ return Z_STREAM_ERROR; -+ if (z->state->blocks != Z_NULL) -+ inflate_blocks_free(z->state->blocks, z, &c); -+ ZFREE(z, z->state, sizeof(struct internal_state)); -+ z->state = Z_NULL; -+ Trace((stderr, "inflate: end\n")); -+ return Z_OK; -+} -+ -+ -+int inflateInit2(z, w) -+z_stream *z; -+int w; -+{ -+ /* initialize state */ -+ if (z == Z_NULL) -+ return Z_STREAM_ERROR; -+/* if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */ -+/* if (z->zfree == Z_NULL) z->zfree = zcfree; */ -+ if ((z->state = (struct internal_state FAR *) -+ ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) -+ return Z_MEM_ERROR; -+ z->state->blocks = Z_NULL; -+ -+ /* handle undocumented nowrap option (no zlib header or check) */ -+ z->state->nowrap = 0; -+ if (w < 0) -+ { -+ w = - w; -+ z->state->nowrap = 1; -+ } -+ -+ /* set window size */ -+ if (w < 8 || w > 15) -+ { -+ inflateEnd(z); -+ return Z_STREAM_ERROR; -+ } -+ z->state->wbits = (uInt)w; -+ -+ /* create inflate_blocks state */ -+ if ((z->state->blocks = -+ inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w)) -+ == Z_NULL) -+ { -+ inflateEnd(z); -+ return Z_MEM_ERROR; -+ } -+ Trace((stderr, "inflate: allocated\n")); -+ -+ /* reset state */ -+ inflateReset(z); -+ return Z_OK; -+} -+ -+ -+int inflateInit(z) -+z_stream *z; -+{ -+ return inflateInit2(z, DEF_WBITS); -+} -+ -+ -+#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;} -+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) -+ -+int inflate(z, f) -+z_stream *z; -+int f; -+{ -+ int r; -+ uInt b; -+ -+ if (z == Z_NULL || z->next_in == Z_NULL) -+ return Z_STREAM_ERROR; -+ r = Z_BUF_ERROR; -+ while (1) switch (z->state->mode) -+ { -+ case METHOD: -+ NEEDBYTE -+ if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED) -+ { -+ z->state->mode = BAD; -+ z->msg = "unknown compression method"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ if ((z->state->sub.method >> 4) + 8 > z->state->wbits) -+ { -+ z->state->mode = BAD; -+ z->msg = "invalid window size"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ z->state->mode = FLAG; -+ case FLAG: -+ NEEDBYTE -+ if ((b = NEXTBYTE) & 0x20) -+ { -+ z->state->mode = BAD; -+ z->msg = "invalid reserved bit"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ if (((z->state->sub.method << 8) + b) % 31) -+ { -+ z->state->mode = BAD; -+ z->msg = "incorrect header check"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ Trace((stderr, "inflate: zlib header ok\n")); -+ z->state->mode = BLOCKS; -+ case BLOCKS: -+ r = inflate_blocks(z->state->blocks, z, r); -+ if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0) -+ r = inflate_packet_flush(z->state->blocks); -+ if (r == Z_DATA_ERROR) -+ { -+ z->state->mode = BAD; -+ z->state->sub.marker = 0; /* can try inflateSync */ -+ break; -+ } -+ if (r != Z_STREAM_END) -+ return r; -+ r = Z_OK; -+ inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); -+ if (z->state->nowrap) -+ { -+ z->state->mode = DONE; -+ break; -+ } -+ z->state->mode = CHECK4; -+ case CHECK4: -+ NEEDBYTE -+ z->state->sub.check.need = (uLong)NEXTBYTE << 24; -+ z->state->mode = CHECK3; -+ case CHECK3: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE << 16; -+ z->state->mode = CHECK2; -+ case CHECK2: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE << 8; -+ z->state->mode = CHECK1; -+ case CHECK1: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE; -+ -+ if (z->state->sub.check.was != z->state->sub.check.need) -+ { -+ z->state->mode = BAD; -+ z->msg = "incorrect data check"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ Trace((stderr, "inflate: zlib check ok\n")); -+ z->state->mode = DONE; -+ case DONE: -+ return Z_STREAM_END; -+ case BAD: -+ return Z_DATA_ERROR; -+ default: -+ return Z_STREAM_ERROR; -+ } -+ -+ empty: -+ if (f != Z_PACKET_FLUSH) -+ return r; -+ z->state->mode = BAD; -+ z->state->sub.marker = 0; /* can try inflateSync */ -+ return Z_DATA_ERROR; -+} -+ -+/* -+ * This subroutine adds the data at next_in/avail_in to the output history -+ * without performing any output. The output buffer must be "caught up"; -+ * i.e. no pending output (hence s->read equals s->write), and the state must -+ * be BLOCKS (i.e. we should be willing to see the start of a series of -+ * BLOCKS). On exit, the output will also be caught up, and the checksum -+ * will have been updated if need be. -+ */ -+ -+int inflateIncomp(z) -+z_stream *z; -+{ -+ if (z->state->mode != BLOCKS) -+ return Z_DATA_ERROR; -+ return inflate_addhistory(z->state->blocks, z); -+} -+ -+ -+int inflateSync(z) -+z_stream *z; -+{ -+ uInt n; /* number of bytes to look at */ -+ Bytef *p; /* pointer to bytes */ -+ uInt m; /* number of marker bytes found in a row */ -+ uLong r, w; /* temporaries to save total_in and total_out */ -+ -+ /* set up */ -+ if (z == Z_NULL || z->state == Z_NULL) -+ return Z_STREAM_ERROR; -+ if (z->state->mode != BAD) -+ { -+ z->state->mode = BAD; -+ z->state->sub.marker = 0; -+ } -+ if ((n = z->avail_in) == 0) -+ return Z_BUF_ERROR; -+ p = z->next_in; -+ m = z->state->sub.marker; -+ -+ /* search */ -+ while (n && m < 4) -+ { -+ if (*p == (Byte)(m < 2 ? 0 : 0xff)) -+ m++; -+ else if (*p) -+ m = 0; -+ else -+ m = 4 - m; -+ p++, n--; -+ } -+ -+ /* restore */ -+ z->total_in += p - z->next_in; -+ z->next_in = p; -+ z->avail_in = n; -+ z->state->sub.marker = m; -+ -+ /* return no joy or set up to restart on a new block */ -+ if (m != 4) -+ return Z_DATA_ERROR; -+ r = z->total_in; w = z->total_out; -+ inflateReset(z); -+ z->total_in = r; z->total_out = w; -+ z->state->mode = BLOCKS; -+ return Z_OK; -+} -+ -+#undef NEEDBYTE -+#undef NEXTBYTE -+ -+/*+++++*/ -+/* infutil.h -- types and macros common to blocks and codes -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+/* inflate blocks semi-private state */ -+struct inflate_blocks_state { -+ -+ /* mode */ -+ enum { -+ TYPE, /* get type bits (3, including end bit) */ -+ LENS, /* get lengths for stored */ -+ STORED, /* processing stored block */ -+ TABLE, /* get table lengths */ -+ BTREE, /* get bit lengths tree for a dynamic block */ -+ DTREE, /* get length, distance trees for a dynamic block */ -+ CODES, /* processing fixed or dynamic block */ -+ DRY, /* output remaining window bytes */ -+ DONEB, /* finished last block, done */ -+ BADB} /* got a data error--stuck here */ -+ mode; /* current inflate_block mode */ -+ -+ /* mode dependent information */ -+ union { -+ uInt left; /* if STORED, bytes left to copy */ -+ struct { -+ uInt table; /* table lengths (14 bits) */ -+ uInt index; /* index into blens (or border) */ -+ uIntf *blens; /* bit lengths of codes */ -+ uInt bb; /* bit length tree depth */ -+ inflate_huft *tb; /* bit length decoding tree */ -+ int nblens; /* # elements allocated at blens */ -+ } trees; /* if DTREE, decoding info for trees */ -+ struct { -+ inflate_huft *tl, *td; /* trees to free */ -+ inflate_codes_statef -+ *codes; -+ } decode; /* if CODES, current state */ -+ } sub; /* submode */ -+ uInt last; /* true if this block is the last block */ -+ -+ /* mode independent information */ -+ uInt bitk; /* bits in bit buffer */ -+ uLong bitb; /* bit buffer */ -+ Bytef *window; /* sliding window */ -+ Bytef *end; /* one byte after sliding window */ -+ Bytef *read; /* window read pointer */ -+ Bytef *write; /* window write pointer */ -+ check_func checkfn; /* check function */ -+ uLong check; /* check on output */ -+ -+}; -+ -+ -+/* defines for inflate input/output */ -+/* update pointers and return */ -+#define UPDBITS {s->bitb=b;s->bitk=k;} -+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} -+#define UPDOUT {s->write=q;} -+#define UPDATE {UPDBITS UPDIN UPDOUT} -+#define LEAVE {UPDATE return inflate_flush(s,z,r);} -+/* get bytes and bits */ -+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} -+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} -+#define NEXTBYTE (n--,*p++) -+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} -+/* output bytes */ -+#define WAVAIL (qread?s->read-q-1:s->end-q) -+#define LOADOUT {q=s->write;m=WAVAIL;} -+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}} -+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} -+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} -+#define OUTBYTE(a) {*q++=(Byte)(a);m--;} -+/* load local pointers */ -+#define LOAD {LOADIN LOADOUT} -+ -+/* -+ * The IBM 150 firmware munges the data right after _etext[]. This -+ * protects it. -- Cort -+ */ -+local uInt protect_mask[] = {0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0}; -+/* And'ing with mask[n] masks the lower n bits */ -+local uInt inflate_mask[] = { -+ 0x0000, -+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, -+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -+}; -+ -+/* copy as much as possible from the sliding window to the output area */ -+local int inflate_flush OF(( -+ inflate_blocks_statef *, -+ z_stream *, -+ int)); -+ -+/*+++++*/ -+/* inffast.h -- header to use inffast.c -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+local int inflate_fast OF(( -+ uInt, -+ uInt, -+ inflate_huft *, -+ inflate_huft *, -+ inflate_blocks_statef *, -+ z_stream *)); -+ -+ -+/*+++++*/ -+/* infblock.c -- interpret and process block types to last block -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* Table for deflate from PKZIP's appnote.txt. */ -+local uInt border[] = { /* Order of the bit length code lengths */ -+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; -+ -+/* -+ Notes beyond the 1.93a appnote.txt: -+ -+ 1. Distance pointers never point before the beginning of the output -+ stream. -+ 2. Distance pointers can point back across blocks, up to 32k away. -+ 3. There is an implied maximum of 7 bits for the bit length table and -+ 15 bits for the actual data. -+ 4. If only one code exists, then it is encoded using one bit. (Zero -+ would be more efficient, but perhaps a little confusing.) If two -+ codes exist, they are coded using one bit each (0 and 1). -+ 5. There is no way of sending zero distance codes--a dummy must be -+ sent if there are none. (History: a pre 2.0 version of PKZIP would -+ store blocks with no distance codes, but this was discovered to be -+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow -+ zero distance codes, which is sent as one code of zero bits in -+ length. -+ 6. There are up to 286 literal/length codes. Code 256 represents the -+ end-of-block. Note however that the static length tree defines -+ 288 codes just to fill out the Huffman codes. Codes 286 and 287 -+ cannot be used though, since there is no length base or extra bits -+ defined for them. Similarily, there are up to 30 distance codes. -+ However, static trees define 32 codes (all 5 bits) to fill out the -+ Huffman codes, but the last two had better not show up in the data. -+ 7. Unzip can check dynamic Huffman blocks for complete code sets. -+ The exception is that a single code would not be complete (see #4). -+ 8. The five bits following the block type is really the number of -+ literal codes sent minus 257. -+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits -+ (1+6+6). Therefore, to output three times the length, you output -+ three codes (1+1+1), whereas to output four times the same length, -+ you only need two codes (1+3). Hmm. -+ 10. In the tree reconstruction algorithm, Code = Code + Increment -+ only if BitLength(i) is not zero. (Pretty obvious.) -+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) -+ 12. Note: length code 284 can represent 227-258, but length code 285 -+ really is 258. The last length deserves its own, short code -+ since it gets used a lot in very redundant files. The length -+ 258 is special since 258 - 3 (the min match length) is 255. -+ 13. The literal/length and distance code bit lengths are read as a -+ single stream of lengths. It is possible (and advantageous) for -+ a repeat code (16, 17, or 18) to go across the boundary between -+ the two sets of lengths. -+ */ -+ -+ -+local void inflate_blocks_reset(s, z, c) -+inflate_blocks_statef *s; -+z_stream *z; -+uLongf *c; -+{ -+ if (s->checkfn != Z_NULL) -+ *c = s->check; -+ if (s->mode == BTREE || s->mode == DTREE) -+ ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt)); -+ if (s->mode == CODES) -+ { -+ inflate_codes_free(s->sub.decode.codes, z); -+ inflate_trees_free(s->sub.decode.td, z); -+ inflate_trees_free(s->sub.decode.tl, z); -+ } -+ s->mode = TYPE; -+ s->bitk = 0; -+ s->bitb = 0; -+ s->read = s->write = s->window; -+ if (s->checkfn != Z_NULL) -+ s->check = (*s->checkfn)(0L, Z_NULL, 0); -+ Trace((stderr, "inflate: blocks reset\n")); -+} -+ -+ -+local inflate_blocks_statef *inflate_blocks_new(z, c, w) -+z_stream *z; -+check_func c; -+uInt w; -+{ -+ inflate_blocks_statef *s; -+ -+ if ((s = (inflate_blocks_statef *)ZALLOC -+ (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) -+ return s; -+ if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) -+ { -+ ZFREE(z, s, sizeof(struct inflate_blocks_state)); -+ return Z_NULL; -+ } -+ s->end = s->window + w; -+ s->checkfn = c; -+ s->mode = TYPE; -+ Trace((stderr, "inflate: blocks allocated\n")); -+ inflate_blocks_reset(s, z, &s->check); -+ return s; -+} -+ -+ -+local int inflate_blocks(s, z, r) -+inflate_blocks_statef *s; -+z_stream *z; -+int r; -+{ -+ uInt t; /* temporary storage */ -+ uLong b; /* bit buffer */ -+ uInt k; /* bits in bit buffer */ -+ Bytef *p; /* input data pointer */ -+ uInt n; /* bytes available there */ -+ Bytef *q; /* output window write pointer */ -+ uInt m; /* bytes to end of window or read pointer */ -+ -+ /* copy input/output information to locals (UPDATE macro restores) */ -+ LOAD -+ -+ /* process input based on current state */ -+ while (1) switch (s->mode) -+ { -+ case TYPE: -+ NEEDBITS(3) -+ t = (uInt)b & 7; -+ s->last = t & 1; -+ switch (t >> 1) -+ { -+ case 0: /* stored */ -+ Trace((stderr, "inflate: stored block%s\n", -+ s->last ? " (last)" : "")); -+ DUMPBITS(3) -+ t = k & 7; /* go to byte boundary */ -+ DUMPBITS(t) -+ s->mode = LENS; /* get length of stored block */ -+ break; -+ case 1: /* fixed */ -+ Trace((stderr, "inflate: fixed codes block%s\n", -+ s->last ? " (last)" : "")); -+ { -+ uInt bl, bd; -+ inflate_huft *tl, *td; -+ -+ inflate_trees_fixed(&bl, &bd, &tl, &td); -+ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); -+ if (s->sub.decode.codes == Z_NULL) -+ { -+ r = Z_MEM_ERROR; -+ LEAVE -+ } -+ s->sub.decode.tl = Z_NULL; /* don't try to free these */ -+ s->sub.decode.td = Z_NULL; -+ } -+ DUMPBITS(3) -+ s->mode = CODES; -+ break; -+ case 2: /* dynamic */ -+ Trace((stderr, "inflate: dynamic codes block%s\n", -+ s->last ? " (last)" : "")); -+ DUMPBITS(3) -+ s->mode = TABLE; -+ break; -+ case 3: /* illegal */ -+ DUMPBITS(3) -+ s->mode = BADB; -+ z->msg = "invalid block type"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+ break; -+ case LENS: -+ NEEDBITS(32) -+ if (((~b) >> 16) != (b & 0xffff)) -+ { -+ s->mode = BADB; -+ z->msg = "invalid stored block lengths"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+ s->sub.left = (uInt)b & 0xffff; -+ b = k = 0; /* dump bits */ -+ Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); -+ s->mode = s->sub.left ? STORED : TYPE; -+ break; -+ case STORED: -+ if (n == 0) -+ LEAVE -+ NEEDOUT -+ t = s->sub.left; -+ if (t > n) t = n; -+ if (t > m) t = m; -+ zmemcpy(q, p, t); -+ p += t; n -= t; -+ q += t; m -= t; -+ if ((s->sub.left -= t) != 0) -+ break; -+ Tracev((stderr, "inflate: stored end, %lu total out\n", -+ z->total_out + (q >= s->read ? q - s->read : -+ (s->end - s->read) + (q - s->window)))); -+ s->mode = s->last ? DRY : TYPE; -+ break; -+ case TABLE: -+ NEEDBITS(14) -+ s->sub.trees.table = t = (uInt)b & 0x3fff; -+#ifndef PKZIP_BUG_WORKAROUND -+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) -+ { -+ s->mode = BADB; -+ z->msg = "too many length or distance symbols"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+#endif -+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); -+ if (t < 19) -+ t = 19; -+ if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) -+ { -+ r = Z_MEM_ERROR; -+ LEAVE -+ } -+ s->sub.trees.nblens = t; -+ DUMPBITS(14) -+ s->sub.trees.index = 0; -+ Tracev((stderr, "inflate: table sizes ok\n")); -+ s->mode = BTREE; -+ case BTREE: -+ while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) -+ { -+ NEEDBITS(3) -+ s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; -+ DUMPBITS(3) -+ } -+ while (s->sub.trees.index < 19) -+ s->sub.trees.blens[border[s->sub.trees.index++]] = 0; -+ s->sub.trees.bb = 7; -+ t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, -+ &s->sub.trees.tb, z); -+ if (t != Z_OK) -+ { -+ r = t; -+ if (r == Z_DATA_ERROR) -+ s->mode = BADB; -+ LEAVE -+ } -+ s->sub.trees.index = 0; -+ Tracev((stderr, "inflate: bits tree ok\n")); -+ s->mode = DTREE; -+ case DTREE: -+ while (t = s->sub.trees.table, -+ s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) -+ { -+ inflate_huft *h; -+ uInt i, j, c; -+ -+ t = s->sub.trees.bb; -+ NEEDBITS(t) -+ h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); -+ t = h->word.what.Bits; -+ c = h->more.Base; -+ if (c < 16) -+ { -+ DUMPBITS(t) -+ s->sub.trees.blens[s->sub.trees.index++] = c; -+ } -+ else /* c == 16..18 */ -+ { -+ i = c == 18 ? 7 : c - 14; -+ j = c == 18 ? 11 : 3; -+ NEEDBITS(t + i) -+ DUMPBITS(t) -+ j += (uInt)b & inflate_mask[i]; -+ DUMPBITS(i) -+ i = s->sub.trees.index; -+ t = s->sub.trees.table; -+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || -+ (c == 16 && i < 1)) -+ { -+ s->mode = BADB; -+ z->msg = "invalid bit length repeat"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+ c = c == 16 ? s->sub.trees.blens[i - 1] : 0; -+ do { -+ s->sub.trees.blens[i++] = c; -+ } while (--j); -+ s->sub.trees.index = i; -+ } -+ } -+ inflate_trees_free(s->sub.trees.tb, z); -+ s->sub.trees.tb = Z_NULL; -+ { -+ uInt bl, bd; -+ inflate_huft *tl, *td; -+ inflate_codes_statef *c; -+ -+ bl = 9; /* must be <= 9 for lookahead assumptions */ -+ bd = 6; /* must be <= 9 for lookahead assumptions */ -+ t = s->sub.trees.table; -+ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), -+ s->sub.trees.blens, &bl, &bd, &tl, &td, z); -+ if (t != Z_OK) -+ { -+ if (t == (uInt)Z_DATA_ERROR) -+ s->mode = BADB; -+ r = t; -+ LEAVE -+ } -+ Tracev((stderr, "inflate: trees ok\n")); -+ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) -+ { -+ inflate_trees_free(td, z); -+ inflate_trees_free(tl, z); -+ r = Z_MEM_ERROR; -+ LEAVE -+ } -+ ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt)); -+ s->sub.decode.codes = c; -+ s->sub.decode.tl = tl; -+ s->sub.decode.td = td; -+ } -+ s->mode = CODES; -+ case CODES: -+ UPDATE -+ if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) -+ return inflate_flush(s, z, r); -+ r = Z_OK; -+ inflate_codes_free(s->sub.decode.codes, z); -+ inflate_trees_free(s->sub.decode.td, z); -+ inflate_trees_free(s->sub.decode.tl, z); -+ LOAD -+ Tracev((stderr, "inflate: codes end, %lu total out\n", -+ z->total_out + (q >= s->read ? q - s->read : -+ (s->end - s->read) + (q - s->window)))); -+ if (!s->last) -+ { -+ s->mode = TYPE; -+ break; -+ } -+ if (k > 7) /* return unused byte, if any */ -+ { -+ Assert(k < 16, "inflate_codes grabbed too many bytes") -+ k -= 8; -+ n++; -+ p--; /* can always return one */ -+ } -+ s->mode = DRY; -+ case DRY: -+ FLUSH -+ if (s->read != s->write) -+ LEAVE -+ s->mode = DONEB; -+ case DONEB: -+ r = Z_STREAM_END; -+ LEAVE -+ case BADB: -+ r = Z_DATA_ERROR; -+ LEAVE -+ default: -+ r = Z_STREAM_ERROR; -+ LEAVE -+ } -+} -+ -+ -+local int inflate_blocks_free(s, z, c) -+inflate_blocks_statef *s; -+z_stream *z; -+uLongf *c; -+{ -+ inflate_blocks_reset(s, z, c); -+ ZFREE(z, s->window, s->end - s->window); -+ ZFREE(z, s, sizeof(struct inflate_blocks_state)); -+ Trace((stderr, "inflate: blocks freed\n")); -+ return Z_OK; -+} -+ -+/* -+ * This subroutine adds the data at next_in/avail_in to the output history -+ * without performing any output. The output buffer must be "caught up"; -+ * i.e. no pending output (hence s->read equals s->write), and the state must -+ * be BLOCKS (i.e. we should be willing to see the start of a series of -+ * BLOCKS). On exit, the output will also be caught up, and the checksum -+ * will have been updated if need be. -+ */ -+local int inflate_addhistory(s, z) -+inflate_blocks_statef *s; -+z_stream *z; -+{ -+ uLong b; /* bit buffer */ /* NOT USED HERE */ -+ uInt k; /* bits in bit buffer */ /* NOT USED HERE */ -+ uInt t; /* temporary storage */ -+ Bytef *p; /* input data pointer */ -+ uInt n; /* bytes available there */ -+ Bytef *q; /* output window write pointer */ -+ uInt m; /* bytes to end of window or read pointer */ -+ -+ if (s->read != s->write) -+ return Z_STREAM_ERROR; -+ if (s->mode != TYPE) -+ return Z_DATA_ERROR; -+ -+ /* we're ready to rock */ -+ LOAD -+ /* while there is input ready, copy to output buffer, moving -+ * pointers as needed. -+ */ -+ while (n) { -+ t = n; /* how many to do */ -+ /* is there room until end of buffer? */ -+ if (t > m) t = m; -+ /* update check information */ -+ if (s->checkfn != Z_NULL) -+ s->check = (*s->checkfn)(s->check, q, t); -+ zmemcpy(q, p, t); -+ q += t; -+ p += t; -+ n -= t; -+ z->total_out += t; -+ s->read = q; /* drag read pointer forward */ -+/* WRAP */ /* expand WRAP macro by hand to handle s->read */ -+ if (q == s->end) { -+ s->read = q = s->window; -+ m = WAVAIL; -+ } -+ } -+ UPDATE -+ return Z_OK; -+} -+ -+ -+/* -+ * At the end of a Deflate-compressed PPP packet, we expect to have seen -+ * a `stored' block type value but not the (zero) length bytes. -+ */ -+local int inflate_packet_flush(s) -+ inflate_blocks_statef *s; -+{ -+ if (s->mode != LENS) -+ return Z_DATA_ERROR; -+ s->mode = TYPE; -+ return Z_OK; -+} -+ -+ -+/*+++++*/ -+/* inftrees.c -- generate Huffman trees for efficient decoding -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* simplify the use of the inflate_huft type with some defines */ -+#define base more.Base -+#define next more.Next -+#define exop word.what.Exop -+#define bits word.what.Bits -+ -+ -+local int huft_build OF(( -+ uIntf *, /* code lengths in bits */ -+ uInt, /* number of codes */ -+ uInt, /* number of "simple" codes */ -+ uIntf *, /* list of base values for non-simple codes */ -+ uIntf *, /* list of extra bits for non-simple codes */ -+ inflate_huft * FAR*,/* result: starting table */ -+ uIntf *, /* maximum lookup bits (returns actual) */ -+ z_stream *)); /* for zalloc function */ -+ -+local voidpf falloc OF(( -+ voidpf, /* opaque pointer (not used) */ -+ uInt, /* number of items */ -+ uInt)); /* size of item */ -+ -+local void ffree OF(( -+ voidpf q, /* opaque pointer (not used) */ -+ voidpf p, /* what to free (not used) */ -+ uInt n)); /* number of bytes (not used) */ -+ -+/* Tables for deflate from PKZIP's appnote.txt. */ -+local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */ -+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, -+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; -+ /* actually lengths - 2; also see note #13 above about 258 */ -+local uInt cplext[] = { /* Extra bits for literal codes 257..285 */ -+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, -+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */ -+local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */ -+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, -+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, -+ 8193, 12289, 16385, 24577}; -+local uInt cpdext[] = { /* Extra bits for distance codes */ -+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, -+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, -+ 12, 12, 13, 13}; -+ -+/* -+ Huffman code decoding is performed using a multi-level table lookup. -+ The fastest way to decode is to simply build a lookup table whose -+ size is determined by the longest code. However, the time it takes -+ to build this table can also be a factor if the data being decoded -+ is not very long. The most common codes are necessarily the -+ shortest codes, so those codes dominate the decoding time, and hence -+ the speed. The idea is you can have a shorter table that decodes the -+ shorter, more probable codes, and then point to subsidiary tables for -+ the longer codes. The time it costs to decode the longer codes is -+ then traded against the time it takes to make longer tables. -+ -+ This results of this trade are in the variables lbits and dbits -+ below. lbits is the number of bits the first level table for literal/ -+ length codes can decode in one step, and dbits is the same thing for -+ the distance codes. Subsequent tables are also less than or equal to -+ those sizes. These values may be adjusted either when all of the -+ codes are shorter than that, in which case the longest code length in -+ bits is used, or when the shortest code is *longer* than the requested -+ table size, in which case the length of the shortest code in bits is -+ used. -+ -+ There are two different values for the two tables, since they code a -+ different number of possibilities each. The literal/length table -+ codes 286 possible values, or in a flat code, a little over eight -+ bits. The distance table codes 30 possible values, or a little less -+ than five bits, flat. The optimum values for speed end up being -+ about one bit more than those, so lbits is 8+1 and dbits is 5+1. -+ The optimum values may differ though from machine to machine, and -+ possibly even between compilers. Your mileage may vary. -+ */ -+ -+ -+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ -+#define BMAX 15 /* maximum bit length of any code */ -+#define N_MAX 288 /* maximum number of codes in any set */ -+ -+#ifdef DEBUG_ZLIB -+ uInt inflate_hufts; -+#endif -+ -+local int huft_build(b, n, s, d, e, t, m, zs) -+uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ -+uInt n; /* number of codes (assumed <= N_MAX) */ -+uInt s; /* number of simple-valued codes (0..s-1) */ -+uIntf *d; /* list of base values for non-simple codes */ -+uIntf *e; /* list of extra bits for non-simple codes */ -+inflate_huft * FAR *t; /* result: starting table */ -+uIntf *m; /* maximum lookup bits, returns actual */ -+z_stream *zs; /* for zalloc function */ -+/* Given a list of code lengths and a maximum table size, make a set of -+ tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR -+ if the given code set is incomplete (the tables are still built in this -+ case), Z_DATA_ERROR if the input is invalid (all zero length codes or an -+ over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */ -+{ -+ -+ uInt a; /* counter for codes of length k */ -+ uInt c[BMAX+1]; /* bit length count table */ -+ uInt f; /* i repeats in table every f entries */ -+ int g; /* maximum code length */ -+ int h; /* table level */ -+ register uInt i; /* counter, current code */ -+ register uInt j; /* counter */ -+ register int k; /* number of bits in current code */ -+ int l; /* bits per table (returned in m) */ -+ register uIntf *p; /* pointer into c[], b[], or v[] */ -+ inflate_huft *q; /* points to current table */ -+ struct inflate_huft_s r; /* table entry for structure assignment */ -+ inflate_huft *u[BMAX]; /* table stack */ -+ uInt v[N_MAX]; /* values in order of bit length */ -+ register int w; /* bits before this table == (l * h) */ -+ uInt x[BMAX+1]; /* bit offsets, then code stack */ -+ uIntf *xp; /* pointer into x */ -+ int y; /* number of dummy codes added */ -+ uInt z; /* number of entries in current table */ -+ -+ -+ /* Generate counts for each bit length */ -+ p = c; -+#define C0 *p++ = 0; -+#define C2 C0 C0 C0 C0 -+#define C4 C2 C2 C2 C2 -+ C4 /* clear c[]--assume BMAX+1 is 16 */ -+ p = b; i = n; -+ do { -+ c[*p++]++; /* assume all entries <= BMAX */ -+ } while (--i); -+ if (c[0] == n) /* null input--all zero length codes */ -+ { -+ *t = (inflate_huft *)Z_NULL; -+ *m = 0; -+ return Z_OK; -+ } -+ -+ -+ /* Find minimum and maximum length, bound *m by those */ -+ l = *m; -+ for (j = 1; j <= BMAX; j++) -+ if (c[j]) -+ break; -+ k = j; /* minimum code length */ -+ if ((uInt)l < j) -+ l = j; -+ for (i = BMAX; i; i--) -+ if (c[i]) -+ break; -+ g = i; /* maximum code length */ -+ if ((uInt)l > i) -+ l = i; -+ *m = l; -+ -+ -+ /* Adjust last length count to fill out codes, if needed */ -+ for (y = 1 << j; j < i; j++, y <<= 1) -+ if ((y -= c[j]) < 0) -+ return Z_DATA_ERROR; -+ if ((y -= c[i]) < 0) -+ return Z_DATA_ERROR; -+ c[i] += y; -+ -+ -+ /* Generate starting offsets into the value table for each length */ -+ x[1] = j = 0; -+ p = c + 1; xp = x + 2; -+ while (--i) { /* note that i == g from above */ -+ *xp++ = (j += *p++); -+ } -+ -+ -+ /* Make a table of values in order of bit lengths */ -+ p = b; i = 0; -+ do { -+ if ((j = *p++) != 0) -+ v[x[j]++] = i; -+ } while (++i < n); -+ -+ -+ /* Generate the Huffman codes and for each, make the table entries */ -+ x[0] = i = 0; /* first Huffman code is zero */ -+ p = v; /* grab values in bit order */ -+ h = -1; /* no tables yet--level -1 */ -+ w = -l; /* bits decoded == (l * h) */ -+ u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ -+ q = (inflate_huft *)Z_NULL; /* ditto */ -+ z = 0; /* ditto */ -+ -+ /* go through the bit lengths (k already is bits in shortest code) */ -+ for (; k <= g; k++) -+ { -+ a = c[k]; -+ while (a--) -+ { -+ /* here i is the Huffman code of length k bits for value *p */ -+ /* make tables up to required level */ -+ while (k > w + l) -+ { -+ h++; -+ w += l; /* previous table always l bits */ -+ -+ /* compute minimum size table less than or equal to l bits */ -+ z = (z = g - w) > (uInt)l ? l : z; /* table size upper limit */ -+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ -+ { /* too few codes for k-w bit table */ -+ f -= a + 1; /* deduct codes from patterns left */ -+ xp = c + k; -+ if (j < z) -+ while (++j < z) /* try smaller tables up to z bits */ -+ { -+ if ((f <<= 1) <= *++xp) -+ break; /* enough codes to use up j bits */ -+ f -= *xp; /* else deduct codes from patterns */ -+ } -+ } -+ z = 1 << j; /* table entries for j-bit table */ -+ -+ /* allocate and link in new table */ -+ if ((q = (inflate_huft *)ZALLOC -+ (zs,z + 1,sizeof(inflate_huft))) == Z_NULL) -+ { -+ if (h) -+ inflate_trees_free(u[0], zs); -+ return Z_MEM_ERROR; /* not enough memory */ -+ } -+ q->word.Nalloc = z + 1; -+#ifdef DEBUG_ZLIB -+ inflate_hufts += z + 1; -+#endif -+ *t = q + 1; /* link to list for huft_free() */ -+ *(t = &(q->next)) = Z_NULL; -+ u[h] = ++q; /* table starts after link */ -+ -+ /* connect to last table, if there is one */ -+ if (h) -+ { -+ x[h] = i; /* save pattern for backing up */ -+ r.bits = (Byte)l; /* bits to dump before this table */ -+ r.exop = (Byte)j; /* bits in this table */ -+ r.next = q; /* pointer to this table */ -+ j = i >> (w - l); /* (get around Turbo C bug) */ -+ u[h-1][j] = r; /* connect to last table */ -+ } -+ } -+ -+ /* set up table entry in r */ -+ r.bits = (Byte)(k - w); -+ if (p >= v + n) -+ r.exop = 128 + 64; /* out of values--invalid code */ -+ else if (*p < s) -+ { -+ r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ -+ r.base = *p++; /* simple code is just the value */ -+ } -+ else -+ { -+ r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */ -+ r.base = d[*p++ - s]; -+ } -+ -+ /* fill code-like entries with r */ -+ f = 1 << (k - w); -+ for (j = i >> w; j < z; j += f) -+ q[j] = r; -+ -+ /* backwards increment the k-bit code i */ -+ for (j = 1 << (k - 1); i & j; j >>= 1) -+ i ^= j; -+ i ^= j; -+ -+ /* backup over finished tables */ -+ while ((i & ((1 << w) - 1)) != x[h]) -+ { -+ h--; /* don't need to update q */ -+ w -= l; -+ } -+ } -+ } -+ -+ -+ /* Return Z_BUF_ERROR if we were given an incomplete table */ -+ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; -+} -+ -+ -+local int inflate_trees_bits(c, bb, tb, z) -+uIntf *c; /* 19 code lengths */ -+uIntf *bb; /* bits tree desired/actual depth */ -+inflate_huft * FAR *tb; /* bits tree result */ -+z_stream *z; /* for zfree function */ -+{ -+ int r; -+ -+ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z); -+ if (r == Z_DATA_ERROR) -+ z->msg = "oversubscribed dynamic bit lengths tree"; -+ else if (r == Z_BUF_ERROR) -+ { -+ inflate_trees_free(*tb, z); -+ z->msg = "incomplete dynamic bit lengths tree"; -+ r = Z_DATA_ERROR; -+ } -+ return r; -+} -+ -+ -+local int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z) -+uInt nl; /* number of literal/length codes */ -+uInt nd; /* number of distance codes */ -+uIntf *c; /* that many (total) code lengths */ -+uIntf *bl; /* literal desired/actual bit depth */ -+uIntf *bd; /* distance desired/actual bit depth */ -+inflate_huft * FAR *tl; /* literal/length tree result */ -+inflate_huft * FAR *td; /* distance tree result */ -+z_stream *z; /* for zfree function */ -+{ -+ int r; -+ -+ /* build literal/length tree */ -+ if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK) -+ { -+ if (r == Z_DATA_ERROR) -+ z->msg = "oversubscribed literal/length tree"; -+ else if (r == Z_BUF_ERROR) -+ { -+ inflate_trees_free(*tl, z); -+ z->msg = "incomplete literal/length tree"; -+ r = Z_DATA_ERROR; -+ } -+ return r; -+ } -+ -+ /* build distance tree */ -+ if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK) -+ { -+ if (r == Z_DATA_ERROR) -+ z->msg = "oversubscribed literal/length tree"; -+ else if (r == Z_BUF_ERROR) { -+#ifdef PKZIP_BUG_WORKAROUND -+ r = Z_OK; -+ } -+#else -+ inflate_trees_free(*td, z); -+ z->msg = "incomplete literal/length tree"; -+ r = Z_DATA_ERROR; -+ } -+ inflate_trees_free(*tl, z); -+ return r; -+#endif -+ } -+ -+ /* done */ -+ return Z_OK; -+} -+ -+ -+/* build fixed tables only once--keep them here */ -+local int fixed_lock = 0; -+local int fixed_built = 0; -+#define FIXEDH 530 /* number of hufts used by fixed tables */ -+local uInt fixed_left = FIXEDH; -+local inflate_huft fixed_mem[FIXEDH]; -+local uInt fixed_bl; -+local uInt fixed_bd; -+local inflate_huft *fixed_tl; -+local inflate_huft *fixed_td; -+ -+ -+local voidpf falloc(q, n, s) -+voidpf q; /* opaque pointer (not used) */ -+uInt n; /* number of items */ -+uInt s; /* size of item */ -+{ -+ Assert(s == sizeof(inflate_huft) && n <= fixed_left, -+ "inflate_trees falloc overflow"); -+ if (q) s++; /* to make some compilers happy */ -+ fixed_left -= n; -+ return (voidpf)(fixed_mem + fixed_left); -+} -+ -+ -+local void ffree(q, p, n) -+voidpf q; -+voidpf p; -+uInt n; -+{ -+ Assert(0, "inflate_trees ffree called!"); -+ if (q) q = p; /* to make some compilers happy */ -+} -+ -+ -+local int inflate_trees_fixed(bl, bd, tl, td) -+uIntf *bl; /* literal desired/actual bit depth */ -+uIntf *bd; /* distance desired/actual bit depth */ -+inflate_huft * FAR *tl; /* literal/length tree result */ -+inflate_huft * FAR *td; /* distance tree result */ -+{ -+ /* build fixed tables if not built already--lock out other instances */ -+ while (++fixed_lock > 1) -+ fixed_lock--; -+ if (!fixed_built) -+ { -+ int k; /* temporary variable */ -+ unsigned c[288]; /* length list for huft_build */ -+ z_stream z; /* for falloc function */ -+ -+ /* set up fake z_stream for memory routines */ -+ z.zalloc = falloc; -+ z.zfree = ffree; -+ z.opaque = Z_NULL; -+ -+ /* literal table */ -+ for (k = 0; k < 144; k++) -+ c[k] = 8; -+ for (; k < 256; k++) -+ c[k] = 9; -+ for (; k < 280; k++) -+ c[k] = 7; -+ for (; k < 288; k++) -+ c[k] = 8; -+ fixed_bl = 7; -+ huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z); -+ -+ /* distance table */ -+ for (k = 0; k < 30; k++) -+ c[k] = 5; -+ fixed_bd = 5; -+ huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z); -+ -+ /* done */ -+ fixed_built = 1; -+ } -+ fixed_lock--; -+ *bl = fixed_bl; -+ *bd = fixed_bd; -+ *tl = fixed_tl; -+ *td = fixed_td; -+ return Z_OK; -+} -+ -+ -+local int inflate_trees_free(t, z) -+inflate_huft *t; /* table to free */ -+z_stream *z; /* for zfree function */ -+/* Free the malloc'ed tables built by huft_build(), which makes a linked -+ list of the tables it made, with the links in a dummy first entry of -+ each table. */ -+{ -+ register inflate_huft *p, *q; -+ -+ /* Go through linked list, freeing from the malloced (t[-1]) address. */ -+ p = t; -+ while (p != Z_NULL) -+ { -+ q = (--p)->next; -+ ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft)); -+ p = q; -+ } -+ return Z_OK; -+} -+ -+/*+++++*/ -+/* infcodes.c -- process literals and length/distance pairs -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* simplify the use of the inflate_huft type with some defines */ -+#define base more.Base -+#define next more.Next -+#define exop word.what.Exop -+#define bits word.what.Bits -+ -+/* inflate codes private state */ -+struct inflate_codes_state { -+ -+ /* mode */ -+ enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ -+ START, /* x: set up for LEN */ -+ LEN, /* i: get length/literal/eob next */ -+ LENEXT, /* i: getting length extra (have base) */ -+ DIST, /* i: get distance next */ -+ DISTEXT, /* i: getting distance extra */ -+ COPY, /* o: copying bytes in window, waiting for space */ -+ LIT, /* o: got literal, waiting for output space */ -+ WASH, /* o: got eob, possibly still output waiting */ -+ END, /* x: got eob and all data flushed */ -+ BADCODE} /* x: got error */ -+ mode; /* current inflate_codes mode */ -+ -+ /* mode dependent information */ -+ uInt len; -+ union { -+ struct { -+ inflate_huft *tree; /* pointer into tree */ -+ uInt need; /* bits needed */ -+ } code; /* if LEN or DIST, where in tree */ -+ uInt lit; /* if LIT, literal */ -+ struct { -+ uInt get; /* bits to get for extra */ -+ uInt dist; /* distance back to copy from */ -+ } copy; /* if EXT or COPY, where and how much */ -+ } sub; /* submode */ -+ -+ /* mode independent information */ -+ Byte lbits; /* ltree bits decoded per branch */ -+ Byte dbits; /* dtree bits decoder per branch */ -+ inflate_huft *ltree; /* literal/length/eob tree */ -+ inflate_huft *dtree; /* distance tree */ -+ -+}; -+ -+ -+local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) -+uInt bl, bd; -+inflate_huft *tl, *td; -+z_stream *z; -+{ -+ inflate_codes_statef *c; -+ -+ if ((c = (inflate_codes_statef *) -+ ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) -+ { -+ c->mode = START; -+ c->lbits = (Byte)bl; -+ c->dbits = (Byte)bd; -+ c->ltree = tl; -+ c->dtree = td; -+ Tracev((stderr, "inflate: codes new\n")); -+ } -+ return c; -+} -+ -+ -+local int inflate_codes(s, z, r) -+inflate_blocks_statef *s; -+z_stream *z; -+int r; -+{ -+ uInt j; /* temporary storage */ -+ inflate_huft *t; /* temporary pointer */ -+ uInt e; /* extra bits or operation */ -+ uLong b; /* bit buffer */ -+ uInt k; /* bits in bit buffer */ -+ Bytef *p; /* input data pointer */ -+ uInt n; /* bytes available there */ -+ Bytef *q; /* output window write pointer */ -+ uInt m; /* bytes to end of window or read pointer */ -+ Bytef *f; /* pointer to copy strings from */ -+ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ -+ -+ /* copy input/output information to locals (UPDATE macro restores) */ -+ LOAD -+ -+ /* process input and output based on current state */ -+ while (1) switch (c->mode) -+ { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ -+ case START: /* x: set up for LEN */ -+#ifndef SLOW -+ if (m >= 258 && n >= 10) -+ { -+ UPDATE -+ r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); -+ LOAD -+ if (r != Z_OK) -+ { -+ c->mode = r == Z_STREAM_END ? WASH : BADCODE; -+ break; -+ } -+ } -+#endif /* !SLOW */ -+ c->sub.code.need = c->lbits; -+ c->sub.code.tree = c->ltree; -+ c->mode = LEN; -+ case LEN: /* i: get length/literal/eob next */ -+ j = c->sub.code.need; -+ NEEDBITS(j) -+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); -+ DUMPBITS(t->bits) -+ e = (uInt)(t->exop); -+ if (e == 0) /* literal */ -+ { -+ c->sub.lit = t->base; -+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? -+ "inflate: literal '%c'\n" : -+ "inflate: literal 0x%02x\n", t->base)); -+ c->mode = LIT; -+ break; -+ } -+ if (e & 16) /* length */ -+ { -+ c->sub.copy.get = e & 15; -+ c->len = t->base; -+ c->mode = LENEXT; -+ break; -+ } -+ if ((e & 64) == 0) /* next table */ -+ { -+ c->sub.code.need = e; -+ c->sub.code.tree = t->next; -+ break; -+ } -+ if (e & 32) /* end of block */ -+ { -+ Tracevv((stderr, "inflate: end of block\n")); -+ c->mode = WASH; -+ break; -+ } -+ c->mode = BADCODE; /* invalid code */ -+ z->msg = "invalid literal/length code"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ case LENEXT: /* i: getting length extra (have base) */ -+ j = c->sub.copy.get; -+ NEEDBITS(j) -+ c->len += (uInt)b & inflate_mask[j]; -+ DUMPBITS(j) -+ c->sub.code.need = c->dbits; -+ c->sub.code.tree = c->dtree; -+ Tracevv((stderr, "inflate: length %u\n", c->len)); -+ c->mode = DIST; -+ case DIST: /* i: get distance next */ -+ j = c->sub.code.need; -+ NEEDBITS(j) -+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); -+ DUMPBITS(t->bits) -+ e = (uInt)(t->exop); -+ if (e & 16) /* distance */ -+ { -+ c->sub.copy.get = e & 15; -+ c->sub.copy.dist = t->base; -+ c->mode = DISTEXT; -+ break; -+ } -+ if ((e & 64) == 0) /* next table */ -+ { -+ c->sub.code.need = e; -+ c->sub.code.tree = t->next; -+ break; -+ } -+ c->mode = BADCODE; /* invalid code */ -+ z->msg = "invalid distance code"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ case DISTEXT: /* i: getting distance extra */ -+ j = c->sub.copy.get; -+ NEEDBITS(j) -+ c->sub.copy.dist += (uInt)b & inflate_mask[j]; -+ DUMPBITS(j) -+ Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); -+ c->mode = COPY; -+ case COPY: /* o: copying bytes in window, waiting for space */ -+#ifndef __TURBOC__ /* Turbo C bug for following expression */ -+ f = (uInt)(q - s->window) < c->sub.copy.dist ? -+ s->end - (c->sub.copy.dist - (q - s->window)) : -+ q - c->sub.copy.dist; -+#else -+ f = q - c->sub.copy.dist; -+ if ((uInt)(q - s->window) < c->sub.copy.dist) -+ f = s->end - (c->sub.copy.dist - (q - s->window)); -+#endif -+ while (c->len) -+ { -+ NEEDOUT -+ OUTBYTE(*f++) -+ if (f == s->end) -+ f = s->window; -+ c->len--; -+ } -+ c->mode = START; -+ break; -+ case LIT: /* o: got literal, waiting for output space */ -+ NEEDOUT -+ OUTBYTE(c->sub.lit) -+ c->mode = START; -+ break; -+ case WASH: /* o: got eob, possibly more output */ -+ FLUSH -+ if (s->read != s->write) -+ LEAVE -+ c->mode = END; -+ case END: -+ r = Z_STREAM_END; -+ LEAVE -+ case BADCODE: /* x: got error */ -+ r = Z_DATA_ERROR; -+ LEAVE -+ default: -+ r = Z_STREAM_ERROR; -+ LEAVE -+ } -+} -+ -+ -+local void inflate_codes_free(c, z) -+inflate_codes_statef *c; -+z_stream *z; -+{ -+ ZFREE(z, c, sizeof(struct inflate_codes_state)); -+ Tracev((stderr, "inflate: codes free\n")); -+} -+ -+/*+++++*/ -+/* inflate_util.c -- data and routines common to blocks and codes -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* copy as much as possible from the sliding window to the output area */ -+local int inflate_flush(s, z, r) -+inflate_blocks_statef *s; -+z_stream *z; -+int r; -+{ -+ uInt n; -+ Bytef *p, *q; -+ -+ /* local copies of source and destination pointers */ -+ p = z->next_out; -+ q = s->read; -+ -+ /* compute number of bytes to copy as far as end of window */ -+ n = (uInt)((q <= s->write ? s->write : s->end) - q); -+ if (n > z->avail_out) n = z->avail_out; -+ if (n && r == Z_BUF_ERROR) r = Z_OK; -+ -+ /* update counters */ -+ z->avail_out -= n; -+ z->total_out += n; -+ -+ /* update check information */ -+ if (s->checkfn != Z_NULL) -+ s->check = (*s->checkfn)(s->check, q, n); -+ -+ /* copy as far as end of window */ -+ zmemcpy(p, q, n); -+ p += n; -+ q += n; -+ -+ /* see if more to copy at beginning of window */ -+ if (q == s->end) -+ { -+ /* wrap pointers */ -+ q = s->window; -+ if (s->write == s->end) -+ s->write = s->window; -+ -+ /* compute bytes to copy */ -+ n = (uInt)(s->write - q); -+ if (n > z->avail_out) n = z->avail_out; -+ if (n && r == Z_BUF_ERROR) r = Z_OK; -+ -+ /* update counters */ -+ z->avail_out -= n; -+ z->total_out += n; -+ -+ /* update check information */ -+ if (s->checkfn != Z_NULL) -+ s->check = (*s->checkfn)(s->check, q, n); -+ -+ /* copy */ -+ zmemcpy(p, q, n); -+ p += n; -+ q += n; -+ } -+ -+ /* update pointers */ -+ z->next_out = p; -+ s->read = q; -+ -+ /* done */ -+ return r; -+} -+ -+ -+/*+++++*/ -+/* inffast.c -- process literals and length/distance pairs fast -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* simplify the use of the inflate_huft type with some defines */ -+#define base more.Base -+#define next more.Next -+#define exop word.what.Exop -+#define bits word.what.Bits -+ -+/* macros for bit input with no checking and for returning unused bytes */ -+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<>3);p-=c;k&=7;} -+ -+/* Called with number of bytes left to write in window at least 258 -+ (the maximum string length) and number of input bytes available -+ at least ten. The ten bytes are six bytes for the longest length/ -+ distance pair plus four bytes for overloading the bit buffer. */ -+ -+local int inflate_fast(bl, bd, tl, td, s, z) -+uInt bl, bd; -+inflate_huft *tl, *td; -+inflate_blocks_statef *s; -+z_stream *z; -+{ -+ inflate_huft *t; /* temporary pointer */ -+ uInt e; /* extra bits or operation */ -+ uLong b; /* bit buffer */ -+ uInt k; /* bits in bit buffer */ -+ Bytef *p; /* input data pointer */ -+ uInt n; /* bytes available there */ -+ Bytef *q; /* output window write pointer */ -+ uInt m; /* bytes to end of window or read pointer */ -+ uInt ml; /* mask for literal/length tree */ -+ uInt md; /* mask for distance tree */ -+ uInt c; /* bytes to copy */ -+ uInt d; /* distance back to copy from */ -+ Bytef *r; /* copy source pointer */ -+ -+ /* load input, output, bit values */ -+ LOAD -+ -+ /* initialize masks */ -+ ml = inflate_mask[bl]; -+ md = inflate_mask[bd]; -+ -+ /* do until not enough input or output space for fast loop */ -+ do { /* assume called with m >= 258 && n >= 10 */ -+ /* get literal/length code */ -+ GRABBITS(20) /* max bits for literal/length code */ -+ if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) -+ { -+ DUMPBITS(t->bits) -+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? -+ "inflate: * literal '%c'\n" : -+ "inflate: * literal 0x%02x\n", t->base)); -+ *q++ = (Byte)t->base; -+ m--; -+ continue; -+ } -+ do { -+ DUMPBITS(t->bits) -+ if (e & 16) -+ { -+ /* get extra bits for length */ -+ e &= 15; -+ c = t->base + ((uInt)b & inflate_mask[e]); -+ DUMPBITS(e) -+ Tracevv((stderr, "inflate: * length %u\n", c)); -+ -+ /* decode distance base of block to copy */ -+ GRABBITS(15); /* max bits for distance code */ -+ e = (t = td + ((uInt)b & md))->exop; -+ do { -+ DUMPBITS(t->bits) -+ if (e & 16) -+ { -+ /* get extra bits to add to distance base */ -+ e &= 15; -+ GRABBITS(e) /* get extra bits (up to 13) */ -+ d = t->base + ((uInt)b & inflate_mask[e]); -+ DUMPBITS(e) -+ Tracevv((stderr, "inflate: * distance %u\n", d)); -+ -+ /* do the copy */ -+ m -= c; -+ if ((uInt)(q - s->window) >= d) /* offset before dest */ -+ { /* just copy */ -+ r = q - d; -+ *q++ = *r++; c--; /* minimum count is three, */ -+ *q++ = *r++; c--; /* so unroll loop a little */ -+ } -+ else /* else offset after destination */ -+ { -+ e = d - (q - s->window); /* bytes from offset to end */ -+ r = s->end - e; /* pointer to offset */ -+ if (c > e) /* if source crosses, */ -+ { -+ c -= e; /* copy to end of window */ -+ do { -+ *q++ = *r++; -+ } while (--e); -+ r = s->window; /* copy rest from start of window */ -+ } -+ } -+ do { /* copy all or what's left */ -+ *q++ = *r++; -+ } while (--c); -+ break; -+ } -+ else if ((e & 64) == 0) -+ e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop; -+ else -+ { -+ z->msg = "invalid distance code"; -+ UNGRAB -+ UPDATE -+ return Z_DATA_ERROR; -+ } -+ } while (1); -+ break; -+ } -+ if ((e & 64) == 0) -+ { -+ if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0) -+ { -+ DUMPBITS(t->bits) -+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? -+ "inflate: * literal '%c'\n" : -+ "inflate: * literal 0x%02x\n", t->base)); -+ *q++ = (Byte)t->base; -+ m--; -+ break; -+ } -+ } -+ else if (e & 32) -+ { -+ Tracevv((stderr, "inflate: * end of block\n")); -+ UNGRAB -+ UPDATE -+ return Z_STREAM_END; -+ } -+ else -+ { -+ z->msg = "invalid literal/length code"; -+ UNGRAB -+ UPDATE -+ return Z_DATA_ERROR; -+ } -+ } while (1); -+ } while (m >= 258 && n >= 10); -+ -+ /* not enough input or output--restore pointers and return */ -+ UNGRAB -+ UPDATE -+ return Z_OK; -+} -+ -+ -+/*+++++*/ -+/* zutil.c -- target dependent utility functions for the compression library -+ * Copyright (C) 1995 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */ -+ -+char *zlib_version = ZLIB_VERSION; -+ -+char *z_errmsg[] = { -+"stream end", /* Z_STREAM_END 1 */ -+"", /* Z_OK 0 */ -+"file error", /* Z_ERRNO (-1) */ -+"stream error", /* Z_STREAM_ERROR (-2) */ -+"data error", /* Z_DATA_ERROR (-3) */ -+"insufficient memory", /* Z_MEM_ERROR (-4) */ -+"buffer error", /* Z_BUF_ERROR (-5) */ -+""}; -+ -+ -+/*+++++*/ -+/* adler32.c -- compute the Adler-32 checksum of a data stream -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */ -+ -+#define BASE 65521L /* largest prime smaller than 65536 */ -+#define NMAX 5552 -+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ -+ -+#define DO1(buf) {s1 += *buf++; s2 += s1;} -+#define DO2(buf) DO1(buf); DO1(buf); -+#define DO4(buf) DO2(buf); DO2(buf); -+#define DO8(buf) DO4(buf); DO4(buf); -+#define DO16(buf) DO8(buf); DO8(buf); -+ -+/* ========================================================================= */ -+uLong adler32(adler, buf, len) -+ uLong adler; -+ Bytef *buf; -+ uInt len; -+{ -+ unsigned long s1 = adler & 0xffff; -+ unsigned long s2 = (adler >> 16) & 0xffff; -+ int k; -+ -+ if (buf == Z_NULL) return 1L; -+ -+ while (len > 0) { -+ k = len < NMAX ? len : NMAX; -+ len -= k; -+ while (k >= 16) { -+ DO16(buf); -+ k -= 16; -+ } -+ if (k != 0) do { -+ DO1(buf); -+ } while (--k); -+ s1 %= BASE; -+ s2 %= BASE; -+ } -+ return (s2 << 16) | s1; -+} -diff -Naru linux/arch/mips/zboot/Makefile linux-new/arch/mips/zboot/Makefile ---- linux/arch/mips/zboot/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/Makefile 2003-12-18 14:26:21.000000000 -0500 -@@ -0,0 +1,79 @@ -+# -+# arch/mips/zboot/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. -+ -+# Adapted for MIPS Pete Popov, Dan Malek -+# -+# Copyright (C) 1994 by Linus Torvalds -+# Adapted for PowerPC by Gary Thomas -+# modified by Cort (cort@cs.nmt.edu) -+# -+ -+.c.s: -+ $(CC) $(CFLAGS) -S -o $*.s $< -+.s.o: -+ $(AS) -o $*.o $< -+.c.o: -+ $(CC) $(CFLAGS) -c -o $*.o $< -+.S.s: -+ $(CPP) $(AFLAGS) -o $*.o $< -+.S.o: -+ $(CC) $(AFLAGS) -c -o $*.o $< -+ -+GZIP_FLAGS = -v9f -+ -+CFLAGS := $(CPPFLAGS) -O2 -D__BOOTER__ \ -+ -fomit-frame-pointer -fno-strict-aliasing -fno-common \ -+ -G 0 -mno-abicalls -fno-pic -mcpu=r4600 -mips2 \ -+ -I$(TOPDIR)/arch/$(ARCH)/zboot/include \ -+ -I$(TOPDIR)/include/asm -+AFLAGS += -D__BOOTER__ -+ -+BOOT_TARGETS = zImage zImage.initrd zImage.flash zImage.initrd.flash -+ -+lib/zlib.a: -+ $(MAKE) -C lib -+ -+images/vmlinux.gz: $(TOPDIR)/vmlinux -+ $(MAKE) -C images vmlinux.gz -+ -+$(BOOT_TARGETS): lib/zlib.a images/vmlinux.gz -+ifdef CONFIG_MIPS_PB1000 -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_MIPS_PB1500 -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_MIPS_PB1100 -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_MIPS_DB1000 -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_MIPS_DB1100 -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_MIPS_DB1500 -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_MIPS_BOSPORUS -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_COGENT_CSB250 -+ $(MAKE) -C csb250 $@ -+endif -+ifdef CONFIG_MIPS_XXS1500 -+BOOT_DIR = xxs1500 -+endif -+ -+# Do the dirs -+clean: -+ $(MAKE) -C common clean -+ $(MAKE) -C images clean -+ $(MAKE) -C pb1xxx clean -+ $(MAKE) -C xxs1500 clean -+ -+include $(TOPDIR)/Rules.make -diff -Naru linux/arch/mips/zboot/pb1xxx/head.S linux-new/arch/mips/zboot/pb1xxx/head.S ---- linux/arch/mips/zboot/pb1xxx/head.S 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/pb1xxx/head.S 2003-12-18 14:26:21.000000000 -0500 -@@ -0,0 +1,149 @@ -+/* -+ * arch/mips/kernel/head.S -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 1994, 1995 Waldorf Electronics -+ * Written by Ralf Baechle and Andreas Busse -+ * Copyright (C) 1995 - 1999 Ralf Baechle -+ * Copyright (C) 1996 Paul M. Antoine -+ * Modified for DECStation and hence R3000 support by Paul M. Antoine -+ * Further modifications by David S. Miller and Harald Koerfgen -+ * Copyright (C) 1999 Silicon Graphics, Inc. -+ * -+ * Head.S contains the MIPS exception handler and startup code. -+ * -+ ************************************************************************** -+ * 9 Nov, 2000. -+ * Added Cache Error exception handler and SBDDP EJTAG debug exception. -+ * -+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com -+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. -+ ************************************************************************** -+ */ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define IndexInvalidate_I 0x00 -+#define IndexWriteBack_D 0x01 -+ -+ .set noreorder -+ .cprestore -+ LEAF(start) -+start: -+ bal locate -+ nop -+locate: -+ subu s8, ra, 8 /* Where we were loaded */ -+ la sp, (.stack + 8192) -+ -+ move s0, a0 /* Save boot rom start args */ -+ move s1, a1 -+ move s2, a2 -+ move s3, a3 -+ -+ la a0, start /* Where we were linked to run */ -+ -+ move a1, s8 -+ la a2, _edata -+ subu t1, a2, a0 -+ srl t1, t1, 2 -+ -+ /* copy text section */ -+ li t0, 0 -+1: lw v0, 0(a1) -+ nop -+ sw v0, 0(a0) -+ xor t0, t0, v0 -+ addu a0, 4 -+ bne a2, a0, 1b -+ addu a1, 4 -+ -+ /* Clear BSS */ -+ la a0, _edata -+ la a2, _end -+2: sw zero, 0(a0) -+ bne a2, a0, 2b -+ addu a0, 4 -+ -+ /* push the D-Cache and invalidate I-Cache */ -+ li k0, 0x80000000 # start address -+ li k1, 0x80004000 # end address (16KB I-Cache) -+ subu k1, 128 -+ -+1: -+ .set mips3 -+ cache IndexWriteBack_D, 0(k0) -+ cache IndexWriteBack_D, 32(k0) -+ cache IndexWriteBack_D, 64(k0) -+ cache IndexWriteBack_D, 96(k0) -+ cache IndexInvalidate_I, 0(k0) -+ cache IndexInvalidate_I, 32(k0) -+ cache IndexInvalidate_I, 64(k0) -+ cache IndexInvalidate_I, 96(k0) -+ .set mips0 -+ -+ bne k0, k1, 1b -+ addu k0, k0, 128 -+ /* done */ -+ -+ move a0, s8 /* load address */ -+ move a1, t1 /* length in words */ -+ move a2, t0 /* checksum */ -+ move a3, sp -+ -+ la ra, 1f -+ la k0, decompress_kernel -+ jr k0 -+ nop -+1: -+ -+ move a0, s0 -+ move a1, s1 -+ move a2, s2 -+ move a3, s3 -+ li k0, KERNEL_ENTRY -+ jr k0 -+ nop -+3: -+ b 3b -+ END(start) -+ -+ LEAF(udelay) -+udelay: -+ END(udelay) -+ -+ -+ LEAF(FlushCache) -+ li k0, 0x80000000 # start address -+ li k1, 0x80004000 # end address (16KB I-Cache) -+ subu k1, 128 -+ -+1: -+ .set mips3 -+ cache IndexWriteBack_D, 0(k0) -+ cache IndexWriteBack_D, 32(k0) -+ cache IndexWriteBack_D, 64(k0) -+ cache IndexWriteBack_D, 96(k0) -+ cache IndexInvalidate_I, 0(k0) -+ cache IndexInvalidate_I, 32(k0) -+ cache IndexInvalidate_I, 64(k0) -+ cache IndexInvalidate_I, 96(k0) -+ .set mips0 -+ -+ bne k0, k1, 1b -+ addu k0, k0, 128 -+ jr ra -+ nop -+ END(FlushCache) -+ -+ .comm .stack,4096*2,4 -diff -Naru linux/arch/mips/zboot/pb1xxx/Makefile linux-new/arch/mips/zboot/pb1xxx/Makefile ---- linux/arch/mips/zboot/pb1xxx/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/pb1xxx/Makefile 2003-12-18 14:26:21.000000000 -0500 -@@ -0,0 +1,123 @@ -+# arch/mips/zboot/pb1xxx/Makefile -+# -+# Makefile for Alchemy Semiconductor Pb1[015]00 boards. -+# All of the boot loader code was derived from the ppc -+# boot code. -+# -+# Copyright 2001,2002 MontaVista Software Inc. -+# -+# Author: Mark A. Greer -+# mgreer@mvista.com -+# Ported and modified for mips support by -+# Pete Popov -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by the -+# Free Software Foundation; either version 2 of the License, or (at your -+# option) any later version. -+ -+.c.s: -+ $(CC) $(CFLAGS) -S -o $*.s $< -+.s.o: -+ $(AS) -o $*.o $< -+.c.o: -+ $(CC) $(CFLAGS) -D__BOOTER__ -c -o $*.o $< -+.S.s: -+ $(CPP) $(AFLAGS) -o $*.o $< -+.S.o: -+ $(CC) $(AFLAGS) -c -o $*.o $< -+ -+######################################################################### -+# START BOARD SPECIFIC VARIABLES -+ifdef CONFIG_MIPS_PB1000 -+BNAME=pb1000 -+endif -+ -+ifdef CONFIG_MIPS_PB1100 -+BNAME=pb1100 -+endif -+ -+ifdef CONFIG_MIPS_PB1500 -+BNAME=pb1500 -+endif -+ -+ifdef CONFIG_MIPS_DB1000 -+BNAME=db1000 -+endif -+ -+ifdef CONFIG_MIPS_DB1100 -+BNAME=db1100 -+endif -+ -+ifdef CONFIG_MIPS_DB1500 -+BNAME=db1500 -+endif -+ -+ifdef CONFIG_MIPS_BOSPORUS -+BNAME=bosporus -+endif -+ -+# These two variables control where the zImage is stored -+# in flash and loaded in memory. It only controls how the srec -+# file is generated, the code is the same. -+RAM_RUN_ADDR = 0x81000000 -+FLASH_LOAD_ADDR = 0xBFD00000 -+ -+# These two variables specify the free ram region -+# that can be used for temporary malloc area -+AVAIL_RAM_START=0x80400000 -+AVAIL_RAM_END=0x80800000 -+ -+# This one must match the LOADADDR in arch/mips/Makefile! -+LOADADDR=0x80100000 -+# END BOARD SPECIFIC VARIABLES -+######################################################################### -+ -+OBJECTS := head.o ../common/misc-common.o ../common/misc-simple.o \ -+ ../common/au1k_uart.o ../common/string.o ../common/ctype.o -+LIBS := ../lib/zlib.a -+ -+ENTRY := ../utils/entry -+OFFSET := ../utils/offset -+SIZE := ../utils/size -+ -+LD_ARGS := -T ../ld.script -Ttext $(RAM_RUN_ADDR) -Bstatic -+OBJCOPY_ARGS = -O elf32-tradlittlemips -+ -+all: zImage -+ -+clean: -+ rm -rf *.o vmlinux* zvmlinux.* ../images/*.srec -+ -+head.o: head.S $(TOPDIR)/vmlinux -+ $(CC) $(AFLAGS) \ -+ -DKERNEL_ENTRY=$(shell sh $(ENTRY) $(NM) $(TOPDIR)/vmlinux ) \ -+ -c -o $*.o $< -+ -+../common/misc-simple.o: -+ $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \ -+ -DAVAIL_RAM_START=$(AVAIL_RAM_START) \ -+ -DAVAIL_RAM_END=$(AVAIL_RAM_END) \ -+ -DLOADADDR=$(LOADADDR) \ -+ -DZIMAGE_SIZE=0 -c -o $@ $*.c -+ -+zvmlinux: $(OBJECTS) $(LIBS) ../ld.script ../images/vmlinux.gz ../common/dummy.o -+ $(OBJCOPY) \ -+ --add-section=.image=../images/vmlinux.gz \ -+ --set-section-flags=.image=contents,alloc,load,readonly,data \ -+ ../common/dummy.o image.o -+ $(LD) $(LD_ARGS) -o $@ $(OBJECTS) image.o $(LIBS) -+ $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr \ -+ -R .initrd -R .sysmap -+ -+# Here we manipulate the image in order to get it the necessary -+# srecord file we need. -+zImage: zvmlinux -+ mv zvmlinux ../images/zImage.$(BNAME) -+ $(OBJCOPY) -O srec ../images/zImage.$(BNAME) ../images/$(BNAME).srec -+ -+zImage.flash: zImage -+ $(OBJCOPY) -O srec --adjust-vma 0x3ed00000 \ -+ ../images/zImage.$(BNAME) ../images/$(BNAME).flash.srec -+ -+include $(TOPDIR)/Rules.make -diff -Naru linux/arch/mips/zboot/utils/entry linux-new/arch/mips/zboot/utils/entry ---- linux/arch/mips/zboot/utils/entry 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/utils/entry 2003-12-18 14:26:21.000000000 -0500 -@@ -0,0 +1,12 @@ -+#!/bin/sh -+ -+# grab the kernel_entry address from the vmlinux elf image -+entry=`$1 $2 | grep kernel_entry` -+ -+fs=`echo $entry | grep ffffffff` # check toolchain output -+ -+if [ -n "$fs" ]; then -+ echo "0x"`$1 $2 | grep kernel_entry | cut -c9- | awk '{print $1}'` -+else -+ echo "0x"`$1 $2 | grep kernel_entry | cut -c1- | awk '{print $1}'` -+fi -diff -Naru linux/arch/mips/zboot/utils/offset linux-new/arch/mips/zboot/utils/offset ---- linux/arch/mips/zboot/utils/offset 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/utils/offset 2003-12-18 14:26:21.000000000 -0500 -@@ -0,0 +1,3 @@ -+#!/bin/sh -+ -+echo "0x"`$1 -h $2 | grep $3 | grep -v zvmlinux| awk '{print $6}'` -diff -Naru linux/arch/mips/zboot/utils/size linux-new/arch/mips/zboot/utils/size ---- linux/arch/mips/zboot/utils/size 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/utils/size 2003-12-18 14:26:21.000000000 -0500 -@@ -0,0 +1,4 @@ -+#!/bin/sh -+ -+OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux | awk '{print $3}'` -+echo "0x"$OFFSET -diff -Naru linux/arch/mips/zboot/xxs1500/head.S linux-new/arch/mips/zboot/xxs1500/head.S ---- linux/arch/mips/zboot/xxs1500/head.S 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/xxs1500/head.S 2003-12-18 14:26:21.000000000 -0500 -@@ -0,0 +1,137 @@ -+/* -+ * arch/mips/kernel/head.S -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 1994, 1995 Waldorf Electronics -+ * Written by Ralf Baechle and Andreas Busse -+ * Copyright (C) 1995 - 1999 Ralf Baechle -+ * Copyright (C) 1996 Paul M. Antoine -+ * Modified for DECStation and hence R3000 support by Paul M. Antoine -+ * Further modifications by David S. Miller and Harald Koerfgen -+ * Copyright (C) 1999 Silicon Graphics, Inc. -+ * -+ * Head.S contains the MIPS exception handler and startup code. -+ * -+ ************************************************************************** -+ * 9 Nov, 2000. -+ * Added Cache Error exception handler and SBDDP EJTAG debug exception. -+ * -+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com -+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. -+ ************************************************************************** -+ */ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define IndexInvalidate_I 0x00 -+ -+ .set noreorder -+ .cprestore -+ LEAF(start) -+start: -+ -+locate: -+ la sp, .stack -+ move s0, a0 -+ move s1, a1 -+ move s2, a2 -+ move s3, a3 -+ -+ la a0, start -+ -+ li a1, FLASH_LOAD_ADDR -+ la a2, _edata -+ subu t1, a2, a0 -+ srl t1, t1, 2 -+ -+ /* copy text section */ -+ li t0, 0 -+1: lw v0, 0(a1) -+ nop -+ sw v0, 0(a0) -+ xor t0, t0, v0 -+ addu a0, 4 -+ bne a2, a0, 1b -+ addu a1, 4 -+ -+ /* Clear BSS */ -+ la a0, _edata -+ la a2, _end -+2: sw zero, 0(a0) -+ bne a2, a0, 2b -+ addu a0, 4 -+ -+ /* flush the I-Cache */ -+ li k0, 0x80000000 # start address -+ li k1, 0x80004000 # end address (16KB I-Cache) -+ subu k1, 128 -+ -+1: -+ .set mips3 -+ cache IndexInvalidate_I, 0(k0) -+ cache IndexInvalidate_I, 32(k0) -+ cache IndexInvalidate_I, 64(k0) -+ cache IndexInvalidate_I, 96(k0) -+ .set mips0 -+ -+ bne k0, k1, 1b -+ addu k0, k0, 128 -+ /* done */ -+ -+ li a0, FLASH_LOAD_ADDR /* load address */ -+ move a1, t1 /* length in words */ -+ move a2, t0 /* checksum */ -+ move a3, sp -+ -+ la ra, 1f -+ la k0, decompress_kernel -+ jr k0 -+ nop -+1: -+ -+ move a0, s0 -+ move a1, s1 -+ move a2, s2 -+ move a3, s3 -+ li k0, KERNEL_ENTRY -+ jr k0 -+ nop -+3: -+ b 3b -+ END(start) -+ -+ LEAF(udelay) -+udelay: -+ END(udelay) -+ -+ -+ LEAF(FlushCache) -+ li k0, 0x80000000 # start address -+ li k1, 0x80004000 # end address (16KB I-Cache) -+ subu k1, 128 -+ -+1: -+ .set mips3 -+ cache IndexInvalidate_I, 0(k0) -+ cache IndexInvalidate_I, 32(k0) -+ cache IndexInvalidate_I, 64(k0) -+ cache IndexInvalidate_I, 96(k0) -+ .set mips0 -+ -+ bne k0, k1, 1b -+ addu k0, k0, 128 -+ jr ra -+ nop -+ END(FlushCache) -+ -+ .comm .stack,4096*2,4 -diff -Naru linux/arch/mips/zboot/xxs1500/ld.script linux-new/arch/mips/zboot/xxs1500/ld.script ---- linux/arch/mips/zboot/xxs1500/ld.script 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/xxs1500/ld.script 2003-12-18 14:26:21.000000000 -0500 -@@ -0,0 +1,147 @@ -+OUTPUT_ARCH(mips) -+ENTRY(start) -+SECTIONS -+{ -+ /* Read-only sections, merged into text segment: */ -+ /* . = 0x81000000; */ -+ .init : { *(.init) } =0 -+ .text : -+ { -+ _ftext = . ; -+ *(.text) -+ *(.rodata) -+ *(.rodata1) -+ /* .gnu.warning sections are handled specially by elf32.em. */ -+ *(.gnu.warning) -+ } =0 -+ .kstrtab : { *(.kstrtab) } -+ -+ . = ALIGN(16); /* Exception table */ -+ __start___ex_table = .; -+ __ex_table : { *(__ex_table) } -+ __stop___ex_table = .; -+ -+ __start___dbe_table = .; /* Exception table for data bus errors */ -+ __dbe_table : { *(__dbe_table) } -+ __stop___dbe_table = .; -+ -+ __start___ksymtab = .; /* Kernel symbol table */ -+ __ksymtab : { *(__ksymtab) } -+ __stop___ksymtab = .; -+ -+ _etext = .; -+ -+ . = ALIGN(8192); -+ .data.init_task : { *(.data.init_task) } -+ -+ /* Startup code */ -+ . = ALIGN(4096); -+ __init_begin = .; -+ .text.init : { *(.text.init) } -+ .data.init : { *(.data.init) } -+ . = ALIGN(16); -+ __setup_start = .; -+ .setup.init : { *(.setup.init) } -+ __setup_end = .; -+ __initcall_start = .; -+ .initcall.init : { *(.initcall.init) } -+ __initcall_end = .; -+ . = ALIGN(4096); /* Align double page for init_task_union */ -+ __init_end = .; -+ -+ . = ALIGN(4096); -+ .data.page_aligned : { *(.data.idt) } -+ -+ . = ALIGN(32); -+ .data.cacheline_aligned : { *(.data.cacheline_aligned) } -+ -+ .fini : { *(.fini) } =0 -+ .reginfo : { *(.reginfo) } -+ /* Adjust the address for the data segment. We want to adjust up to -+ the same address within the page on the next page up. It would -+ be more correct to do this: -+ . = .; -+ The current expression does not correctly handle the case of a -+ text segment ending precisely at the end of a page; it causes the -+ data segment to skip a page. The above expression does not have -+ this problem, but it will currently (2/95) cause BFD to allocate -+ a single segment, combining both text and data, for this case. -+ This will prevent the text segment from being shared among -+ multiple executions of the program; I think that is more -+ important than losing a page of the virtual address space (note -+ that no actual memory is lost; the page which is skipped can not -+ be referenced). */ -+ . = .; -+ .data : -+ { -+ _fdata = . ; -+ *(.data) -+ -+ /* Align the initial ramdisk image (INITRD) on page boundaries. */ -+ . = ALIGN(4096); -+ __rd_start = .; -+ *(.initrd) -+ __rd_end = .; -+ . = ALIGN(4096); -+ -+ CONSTRUCTORS -+ } -+ .data1 : { *(.data1) } -+ _gp = . + 0x8000; -+ .lit8 : { *(.lit8) } -+ .lit4 : { *(.lit4) } -+ .ctors : { *(.ctors) } -+ .dtors : { *(.dtors) } -+ .got : { *(.got.plt) *(.got) } -+ .dynamic : { *(.dynamic) } -+ /* We want the small data sections together, so single-instruction offsets -+ can access them all, and initialized data all before uninitialized, so -+ we can shorten the on-disk segment size. */ -+ .sdata : { *(.sdata) } -+ . = ALIGN(4); -+ _edata = .; -+ PROVIDE (edata = .); -+ -+ __bss_start = .; -+ _fbss = .; -+ .sbss : { *(.sbss) *(.scommon) } -+ .bss : -+ { -+ *(.dynbss) -+ *(.bss) -+ *(COMMON) -+ . = ALIGN(4); -+ _end = . ; -+ PROVIDE (end = .); -+ } -+ -+ /* Sections to be discarded */ -+ /DISCARD/ : -+ { -+ *(.text.exit) -+ *(.data.exit) -+ *(.exitcall.exit) -+ } -+ -+ /* This is the MIPS specific mdebug section. */ -+ .mdebug : { *(.mdebug) } -+ /* These are needed for ELF backends which have not yet been -+ converted to the new style linker. */ -+ .stab 0 : { *(.stab) } -+ .stabstr 0 : { *(.stabstr) } -+ /* DWARF debug sections. -+ Symbols in the .debug DWARF section are relative to the beginning of the -+ section so we begin .debug at 0. It's not clear yet what needs to happen -+ for the others. */ -+ .debug 0 : { *(.debug) } -+ .debug_srcinfo 0 : { *(.debug_srcinfo) } -+ .debug_aranges 0 : { *(.debug_aranges) } -+ .debug_pubnames 0 : { *(.debug_pubnames) } -+ .debug_sfnames 0 : { *(.debug_sfnames) } -+ .line 0 : { *(.line) } -+ /* These must appear regardless of . */ -+ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } -+ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } -+ .comment : { *(.comment) } -+ .note : { *(.note) } -+} -diff -Naru linux/arch/mips/zboot/xxs1500/Makefile linux-new/arch/mips/zboot/xxs1500/Makefile ---- linux/arch/mips/zboot/xxs1500/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ linux-new/arch/mips/zboot/xxs1500/Makefile 2003-12-18 14:26:21.000000000 -0500 -@@ -0,0 +1,123 @@ -+# arch/mips/compressed/alchemy/Makefile -+# -+# Makefile for Alchemy Semiconductor Pb1[015]00 boards. -+# All of the boot loader code was derived from the ppc -+# boot code. -+# -+# Copyright 2001,2002 MontaVista Software Inc. -+# -+# Author: Mark A. Greer -+# mgreer@mvista.com -+# Ported and modified for mips support by -+# Pete Popov -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by the -+# Free Software Foundation; either version 2 of the License, or (at your -+# option) any later version. -+ -+.c.s: -+ $(CC) $(CFLAGS) -S -o $*.s $< -+.s.o: -+ $(AS) -o $*.o $< -+.c.o: -+ $(CC) $(CFLAGS) -D__BOOTER__ -c -o $*.o $< -+.S.s: -+ $(CPP) $(AFLAGS) -o $*.o $< -+.S.o: -+ $(CC) $(AFLAGS) -c -o $*.o $< -+ -+######################################################################### -+# START BOARD SPECIFIC VARIABLES -+BNAME=xxs1500 -+ -+ -+# These two variables control where the zImage is stored -+# in flash and loaded in memory. If you change either one, -+# be sure to make the appropriate change to the zImage -+# rule. -+RAM_LOAD_ADDR = 0x81000000 -+FLASH_LOAD_ADDR = 0xBF000000 -+ -+# These two variables specify the free ram region -+# that can be used for temporary malloc area -+AVAIL_RAM_START=0x80400000 -+AVAIL_RAM_END=0x80800000 -+ -+# This one must match the LOADADDR in arch/mips/Makefile! -+LOADADDR=0x80100000 -+# END BOARD SPECIFIC VARIABLES -+######################################################################### -+ -+ZLINKFLAGS = -T ld.script -Ttext $(RAM_LOAD_ADDR) -+ -+OBJECTS := head.o ../common/misc-common.o ../common/misc-simple.o \ -+ ../common/au1k_uart.o ../common/string.o ../common/ctype.o -+LIBS := ../lib/zlib.a -+ -+ENTRY := ../utils/entry -+OFFSET := ../utils/offset -+SIZE := ../utils/size -+ -+all: zImage -+ -+clean: -+ rm -rf *.o vmlinux* zvmlinux.* -+ -+head.o: head.S $(TOPDIR)/vmlinux -+ $(CC) -DFLASH_LOAD_ADDR=$(FLASH_LOAD_ADDR) $(AFLAGS) \ -+ -DKERNEL_ENTRY=$(shell sh $(ENTRY) $(NM) $(TOPDIR)/vmlinux ) \ -+ -c -o $*.o $< -+ -+../common/misc-simple.o: -+ $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \ -+ -DAVAIL_RAM_START=$(AVAIL_RAM_START) \ -+ -DAVAIL_RAM_END=$(AVAIL_RAM_END) \ -+ -DLOADADDR=$(LOADADDR) \ -+ -DZIMAGE_SIZE=0 -c -o $@ $*.c -+ -+# This is the first pass at building the boot loader image, -+# without knowing the file offset where the vmlinuz.gz -+# kernel will end up. We build this image, check the offset, -+# and then rebuild it with the correct offset and size -+# passed to mips-simple.c -+zvmlinux.no: $(OBJECTS) $(LIBS) ../images/vmlinux.gz -+ $(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS) -+ $(OBJCOPY) -R .comment \ -+ --add-section=image=../images/vmlinux.gz \ -+ $@.tmp $@ -+ # rm -f $@.tmp -+ -+ -+# This is the final image we build, now that we know what -+# the vmlinuz.gz offset is. -+zvmlinux: $(OBJECTS) $(LIBS) ../images/vmlinux.gz zvmlinux.no -+ $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \ -+ -DZIMAGE_OFFSET=$(shell sh $(OFFSET) $(OBJDUMP) $@.no image) \ -+ -DZIMAGE_SIZE=$(shell sh $(SIZE) $(OBJDUMP) $@.no image) \ -+ -D__BOOTER__ \ -+ -DAVAIL_RAM_START=$(AVAIL_RAM_START) \ -+ -DAVAIL_RAM_END=$(AVAIL_RAM_END) \ -+ -DLOADADDR=$(LOADADDR) \ -+ -c -o ../common/misc-simple.o ../common/misc-simple.c -+ $(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS) -+ $(OBJCOPY) -R .comment \ -+ --add-section=image=../images/vmlinux.gz \ -+ $@.tmp $@ -+ $(OBJCOPY) --adjust-section-vma=image+$(RAM_LOAD_ADDR) $@ -+ $(OBJCOPY) --adjust-section-vma=image+$(shell sh $(OFFSET) \ -+ $(OBJDUMP) $@.no image ) $@ -+ # rm -f $@.tmp -+ # rm -f $@.no -+ -+ -+# Here we manipulate the image in order to get it the necessary -+# srecord file we need. -+zImage: zvmlinux -+ mv zvmlinux ../images/$@.$(BNAME) -+ $(OBJCOPY) --set-section-flags=image=alloc,load,code ../images/$@.$(BNAME) -+ $(OBJCOPY) -O srec --adjust-vma 0x3e000000 \ -+ ../images/$@.$(BNAME) ../images/$@.$(BNAME).srec -+ # rm ../images/vmlinux.gz -+ -+include $(TOPDIR)/Rules.make diff --git a/linux/linux-mtx-1-2.4.24/05-zboot-cflags.diff b/linux/linux-mtx-1-2.4.24/05-zboot-cflags.diff deleted file mode 100644 index 9ac0c31b45..0000000000 --- a/linux/linux-mtx-1-2.4.24/05-zboot-cflags.diff +++ /dev/null @@ -1,15 +0,0 @@ ---- linux-mips-2.4.24-pre2+zboot/arch/mips/zboot/Makefile 2004-11-17 19:25:04.538345048 +0100 -+++ linux/arch/mips/zboot/Makefile 2004-11-17 19:21:05.304714088 +0100 -@@ -25,11 +25,7 @@ - - GZIP_FLAGS = -v9f - --CFLAGS := $(CPPFLAGS) -O2 -D__BOOTER__ \ -- -fomit-frame-pointer -fno-strict-aliasing -fno-common \ -- -G 0 -mno-abicalls -fno-pic -mcpu=r4600 -mips2 \ -- -I$(TOPDIR)/arch/$(ARCH)/zboot/include \ -- -I$(TOPDIR)/include/asm -+CFLAGS += -D__BOOTER__ -I$(TOPDIR)/arch/$(ARCH)/zboot/include - AFLAGS += -D__BOOTER__ - - BOOT_TARGETS = zImage zImage.initrd zImage.flash zImage.initrd.flash diff --git a/linux/linux-mtx-1-2.4.24/06-zboot-mtx.diff b/linux/linux-mtx-1-2.4.24/06-zboot-mtx.diff deleted file mode 100644 index 82a3295564..0000000000 --- a/linux/linux-mtx-1-2.4.24/06-zboot-mtx.diff +++ /dev/null @@ -1,27 +0,0 @@ -diff -urb work/arch/mips/zboot/Makefile mtx/arch/mips/zboot/Makefile ---- work/arch/mips/zboot/Makefile 2003-07-01 20:09:20.000000000 +0200 -+++ mtx/arch/mips/zboot/Makefile 2003-07-01 19:20:29.000000000 +0200 -@@ -64,6 +64,9 @@ - ifdef CONFIG_MIPS_XXS1500 - BOOT_DIR = xxs1500 - endif -+ifdef CONFIG_MIPS_MTX1 -+ $(MAKE) -C pb1xxx $@ -+endif - - # Do the dirs - clean: -diff -urb work/arch/mips/zboot/pb1xxx/Makefile mtx/arch/mips/zboot/pb1xxx/Makefile ---- work/arch/mips/zboot/pb1xxx/Makefile 2003-07-01 20:09:20.000000000 +0200 -+++ mtx/arch/mips/zboot/pb1xxx/Makefile 2003-07-01 19:20:37.000000000 +0200 -@@ -57,6 +57,10 @@ - BNAME=bosporus - endif - -+ifdef CONFIG_MIPS_MTX1 -+BNAME=mtx-1 -+endif -+ - # These two variables control where the zImage is stored - # in flash and loaded in memory. It only controls how the srec - # file is generated, the code is the same. diff --git a/linux/linux-mtx-1-2.4.24/07-zimage-flash-bin.patch b/linux/linux-mtx-1-2.4.24/07-zimage-flash-bin.patch deleted file mode 100644 index ce13d9add7..0000000000 --- a/linux/linux-mtx-1-2.4.24/07-zimage-flash-bin.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -Nurb oe/tmp/work/linux-mtx-1-2.4.27-r0/linux/arch/mips/zboot/pb1xxx/Makefile linux.m/arch/mips/zboot/pb1xxx/Makefile ---- oe/tmp/work/linux-mtx-1-2.4.27-r0/linux/arch/mips/zboot/pb1xxx/Makefile 2004-10-13 21:08:49.840408328 +0200 -+++ linux.m/arch/mips/zboot/pb1xxx/Makefile 2004-10-13 21:08:29.736464592 +0200 -@@ -123,5 +123,7 @@ - zImage.flash: zImage - $(OBJCOPY) -O srec --adjust-vma 0x3ed00000 \ - ../images/zImage.$(BNAME) ../images/$(BNAME).flash.srec -+ $(OBJCOPY) -O binary --adjust-vma 0x3ed00000 \ -+ ../images/zImage.$(BNAME) ../images/$(BNAME).flash.bin - - include $(TOPDIR)/Rules.make diff --git a/linux/linux-mtx-1-2.4.24/08-usb-nonpci-2.4.24.patch b/linux/linux-mtx-1-2.4.24/08-usb-nonpci-2.4.24.patch deleted file mode 100644 index 89ed24f214..0000000000 --- a/linux/linux-mtx-1-2.4.24/08-usb-nonpci-2.4.24.patch +++ /dev/null @@ -1,173 +0,0 @@ -diff -Naru linux/drivers/usb/host/Config.in linux-new/drivers/usb/host/Config.in ---- linux/drivers/usb/host/Config.in 2003-11-16 20:07:42.000000000 -0500 -+++ linux-new/drivers/usb/host/Config.in 2003-12-18 14:19:37.000000000 -0500 -@@ -17,3 +17,4 @@ - dep_tristate ' SL811HS Alternate (x86, StrongARM, isosynchronous mode)' CONFIG_USB_SL811HS_ALT $CONFIG_USB $CONFIG_EXPERIMENTAL - dep_tristate ' SL811HS (x86, StrongARM) support, old driver' CONFIG_USB_SL811HS $CONFIG_USB $CONFIG_EXPERIMENTAL - fi -+dep_tristate ' Non-PCI OHCI support' CONFIG_USB_NON_PCI_OHCI $CONFIG_USB_OHCI -diff -Naru linux/drivers/usb/host/usb-ohci.c linux-new/drivers/usb/host/usb-ohci.c ---- linux/drivers/usb/host/usb-ohci.c 2003-08-13 13:19:23.000000000 -0400 -+++ linux-new/drivers/usb/host/usb-ohci.c 2003-12-18 14:19:53.000000000 -0500 -@@ -2517,6 +2517,7 @@ - hc_release_ohci (ohci); - return ret; - } -+#ifndef CONFIG_USB_NON_PCI_OHCI - ohci->flags = id->driver_data; - - /* Check for NSC87560. We have to look at the bridge (fn1) to identify -@@ -2535,6 +2536,7 @@ - printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n"); - if (ohci->flags & OHCI_QUIRK_AMD756) - printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n"); -+#endif - - if (hc_reset (ohci) < 0) { - hc_release_ohci (ohci); -@@ -2580,8 +2582,10 @@ - int temp; - int i; - -+#ifndef CONFIG_USB_NON_PCI_OHCI - if (ohci->pci_latency) - pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency); -+#endif - - ohci->disabled = 1; - ohci->sleeping = 0; -@@ -2611,6 +2615,7 @@ - - /*-------------------------------------------------------------------------*/ - -+#ifndef CONFIG_USB_NON_PCI_OHCI - /* configured so that an OHCI device is always provided */ - /* always called with process context; sleeping is OK */ - -@@ -2658,6 +2663,88 @@ - } - return status; - } -+#else /* CONFIG_USB_NON_PCI_OHCI */ -+ -+// Boot options -+static int ohci_base=0, ohci_len=0; -+static int ohci_irq=-1; -+ -+MODULE_PARM(ohci_base, "i"); -+MODULE_PARM(ohci_len, "i"); -+MODULE_PARM(ohci_irq, "i"); -+MODULE_PARM_DESC(ohci_base, "IO Base address of OHCI Oper. registers"); -+MODULE_PARM_DESC(ohci_len, "IO length of OHCI Oper. registers"); -+MODULE_PARM_DESC(ohci_irq, "IRQ for OHCI interrupts"); -+ -+// bogus pci_dev -+static struct pci_dev bogus_pcidev; -+ -+static struct pci_driver ohci_pci_driver = { -+ name: "usb-ohci", -+}; -+ -+static int __devinit -+ohci_non_pci_init (void) -+{ -+ void *mem_base; -+ -+ if (!ohci_base || !ohci_len || (ohci_irq < 0)) -+ return -ENODEV; -+ -+ if (!request_mem_region (ohci_base, ohci_len, ohci_pci_driver.name)) { -+ dbg ("controller already in use"); -+ return -EBUSY; -+ } -+ -+ mem_base = ioremap_nocache (ohci_base, ohci_len); -+ if (!mem_base) { -+ err("Error mapping OHCI memory"); -+ return -EFAULT; -+ } -+ -+ /* -+ * Fill in the bogus pci_dev. Only those members actually -+ * dereferenced in this driver are initialized. -+ */ -+ memset(&bogus_pcidev, 0, sizeof(struct pci_dev)); -+ strcpy(bogus_pcidev.name, "non-PCI OHCI"); -+ strcpy(bogus_pcidev.slot_name, "builtin"); -+ bogus_pcidev.resource[0].name = "OHCI Operational Registers"; -+ bogus_pcidev.resource[0].start = ohci_base; -+ bogus_pcidev.resource[0].end = ohci_base + ohci_len; -+ bogus_pcidev.resource[0].flags = 0; -+ bogus_pcidev.irq = ohci_irq; -+ -+ return hc_found_ohci (&bogus_pcidev, bogus_pcidev.irq, mem_base, NULL); -+} -+ -+#ifndef MODULE -+ -+static int __init -+ohci_setup (char* options) -+{ -+ char* this_opt; -+ -+ if (!options || !*options) -+ return 0; -+ -+ for(this_opt=strtok(options,",");this_opt;this_opt=strtok(NULL,",")) { -+ if (!strncmp(this_opt, "base:", 5)) { -+ ohci_base = simple_strtoul(this_opt+5, NULL, 0); -+ } else if (!strncmp(this_opt, "len:", 4)) { -+ ohci_len = simple_strtoul(this_opt+4, NULL, 0); -+ } else if (!strncmp(this_opt, "irq:", 4)) { -+ ohci_irq = simple_strtoul(this_opt+4, NULL, 0); -+ } -+ } -+ return 0; -+} -+ -+__setup("usb_ohci=", ohci_setup); -+ -+#endif /* !MODULE */ -+ -+#endif /* CONFIG_USB_NON_PCI_OHCI */ - - /*-------------------------------------------------------------------------*/ - -@@ -2698,6 +2785,7 @@ - } - - -+#ifndef CONFIG_USB_NON_PCI_OHCI - #ifdef CONFIG_PM - - /*-------------------------------------------------------------------------*/ -@@ -2936,20 +3024,29 @@ - resume: ohci_pci_resume, - #endif /* PM */ - }; -+#endif /* CONFIG_USB_NON_PCI_OHCI */ - - - /*-------------------------------------------------------------------------*/ - - static int __init ohci_hcd_init (void) - { -+#ifndef CONFIG_USB_NON_PCI_OHCI - return pci_module_init (&ohci_pci_driver); -+#else -+ return ohci_non_pci_init(); -+#endif - } - - /*-------------------------------------------------------------------------*/ - - static void __exit ohci_hcd_cleanup (void) - { -+#ifndef CONFIG_USB_NON_PCI_OHCI - pci_unregister_driver (&ohci_pci_driver); -+#else -+ ohci_pci_remove(&bogus_pcidev); -+#endif - } - - module_init (ohci_hcd_init); diff --git a/linux/linux-mtx-1-2.4.24/09-iw-max-spy-32.diff b/linux/linux-mtx-1-2.4.24/09-iw-max-spy-32.diff deleted file mode 100644 index e782d3d3dc..0000000000 --- a/linux/linux-mtx-1-2.4.24/09-iw-max-spy-32.diff +++ /dev/null @@ -1,11 +0,0 @@ ---- linux-mips-2.4.24-pre2/include/linux/wireless.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/wireless.h 2004-11-17 19:02:44.370081592 +0100 -@@ -334,7 +334,7 @@ - * a few of them in the struct iw_range. */ - - /* Maximum of address that you may set with SPY */ --#define IW_MAX_SPY 8 -+#define IW_MAX_SPY 32 - - /* Maximum of address that you may get in the - list of access points in range */ diff --git a/linux/linux-mtx-1-2.4.24/10-mtx-pci-slots.diff b/linux/linux-mtx-1-2.4.24/10-mtx-pci-slots.diff deleted file mode 100644 index 8cdde20440..0000000000 --- a/linux/linux-mtx-1-2.4.24/10-mtx-pci-slots.diff +++ /dev/null @@ -1,23 +0,0 @@ ---- linux-mips-2.4.24-pre2/arch/mips/au1000/common/pci_fixup.c 2004-11-17 18:04:41.000000000 +0100 -+++ linux/arch/mips/au1000/common/pci_fixup.c 2004-11-18 11:22:03.176289496 +0100 -@@ -118,6 +118,20 @@ - slot = PCI_SLOT(dev->devfn); - #if defined( CONFIG_SOC_AU1500 ) - switch (slot) { -+#if defined( CONFIG_MIPS_MTX1 ) -+ case 0: -+ dev->irq = AU1000_PCI_INTA; -+ break; -+ case 1: -+ dev->irq = AU1000_PCI_INTB; -+ break; -+ case 2: -+ dev->irq = AU1000_PCI_INTC; -+ break; -+ case 3: -+ dev->irq = AU1000_PCI_INTD; -+ break; -+#endif - case 12: - case 13: - default: diff --git a/linux/linux-mtx-1-2.4.24/11-mtx-extraversion.diff b/linux/linux-mtx-1-2.4.24/11-mtx-extraversion.diff deleted file mode 100644 index c57296981c..0000000000 --- a/linux/linux-mtx-1-2.4.24/11-mtx-extraversion.diff +++ /dev/null @@ -1,11 +0,0 @@ ---- linux-mips-2.4.24-pre2/Makefile 2004-11-17 18:04:38.000000000 +0100 -+++ linux/Makefile 2004-11-17 18:57:54.314176792 +0100 -@@ -1,7 +1,7 @@ - VERSION = 2 - PATCHLEVEL = 4 - SUBLEVEL = 24 --EXTRAVERSION = -pre2 -+EXTRAVERSION = mtx - - KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) - diff --git a/linux/linux-mtx-1-2.4.24/12-openswan-2.2.0-nat-t.diff b/linux/linux-mtx-1-2.4.24/12-openswan-2.2.0-nat-t.diff deleted file mode 100644 index 31bcbd8a5a..0000000000 --- a/linux/linux-mtx-1-2.4.24/12-openswan-2.2.0-nat-t.diff +++ /dev/null @@ -1,143 +0,0 @@ -diff -Nurb linux-1-11/include/net/sock.h linux/include/net/sock.h ---- linux-1-11/include/net/sock.h 2004-11-18 09:55:07.377211480 +0100 -+++ linux/include/net/sock.h 2004-11-18 09:55:43.605703912 +0100 -@@ -256,6 +256,13 @@ - __u32 end_seq; - }; - -+#if 1 -+#define UDP_OPT_IN_SOCK 1 -+struct udp_opt { -+ __u32 esp_in_udp; -+}; -+#endif -+ - struct tcp_opt { - int tcp_header_len; /* Bytes of tcp header to send */ - -@@ -601,6 +608,9 @@ - #if defined(CONFIG_SPX) || defined (CONFIG_SPX_MODULE) - struct spx_opt af_spx; - #endif /* CONFIG_SPX */ -+#if 1 -+ struct udp_opt af_udp; -+#endif - - } tp_pinfo; - -diff -Nurb linux-1-11/net/Config.in linux/net/Config.in ---- linux-1-11/net/Config.in 2004-11-18 09:55:07.545185944 +0100 -+++ linux/net/Config.in 2004-11-18 09:55:43.627700568 +0100 -@@ -102,4 +102,6 @@ - tristate 'Packet Generator (USE WITH CAUTION)' CONFIG_NET_PKTGEN - endmenu - -+bool 'IPSEC NAT-Traversal' CONFIG_IPSEC_NAT_TRAVERSAL -+ - endmenu -diff -Nurb linux-1-11/net/ipv4/udp.c linux/net/ipv4/udp.c ---- linux-1-11/net/ipv4/udp.c 2004-11-18 09:55:07.958123168 +0100 -+++ linux/net/ipv4/udp.c 2004-11-18 09:55:43.638698896 +0100 -@@ -804,6 +804,9 @@ - - static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) - { -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ struct udp_opt *tp = &(sk->tp_pinfo.af_udp); -+#endif - /* - * Charge it to the socket, dropping if the queue is full. - */ -@@ -821,6 +824,40 @@ - } - #endif - -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if (tp->esp_in_udp) { -+ /* -+ * Set skb->sk and xmit packet to ipsec_rcv. -+ * -+ * If ret != 0, ipsec_rcv refused the packet (not ESPinUDP), -+ * restore skb->sk and fall back to sock_queue_rcv_skb -+ */ -+ struct inet_protocol *esp = NULL; -+ -+#if defined(CONFIG_IPSEC) && !defined(CONFIG_IPSEC_MODULE) -+ /* optomize only when we know it is statically linked */ -+ extern struct inet_protocol esp_protocol; -+ esp = &esp_protocol; -+#else -+ for (esp = (struct inet_protocol *)inet_protos[IPPROTO_ESP & (MAX_INET_PROTOS - 1)]; -+ (esp) && (esp->protocol != IPPROTO_ESP); -+ esp = esp->next); -+#endif -+ -+ if (esp && esp->handler) { -+ struct sock *sav_sk = skb->sk; -+ skb->sk = sk; -+ if (esp->handler(skb) == 0) { -+ skb->sk = sav_sk; -+ /*not sure we might count ESPinUDP as UDP...*/ -+ UDP_INC_STATS_BH(UdpInDatagrams); -+ return 0; -+ } -+ skb->sk = sav_sk; -+ } -+ } -+#endif -+ - if (sock_queue_rcv_skb(sk,skb)<0) { - UDP_INC_STATS_BH(UdpInErrors); - IP_INC_STATS_BH(IpInDiscards); -@@ -1044,13 +1081,49 @@ - return len; - } - -+static int udp_setsockopt(struct sock *sk, int level, int optname, -+ char *optval, int optlen) -+{ -+ struct udp_opt *tp = &(sk->tp_pinfo.af_udp); -+ int val; -+ int err = 0; -+ -+ if (level != SOL_UDP) -+ return ip_setsockopt(sk, level, optname, optval, optlen); -+ -+ if(optlenesp_in_udp = val; -+ break; -+#endif -+ default: -+ err = -ENOPROTOOPT; -+ break; -+ } -+ -+ release_sock(sk); -+ return err; -+} -+ - struct proto udp_prot = { - name: "UDP", - close: udp_close, - connect: udp_connect, - disconnect: udp_disconnect, - ioctl: udp_ioctl, -- setsockopt: ip_setsockopt, -+ setsockopt: udp_setsockopt, - getsockopt: ip_getsockopt, - sendmsg: udp_sendmsg, - recvmsg: udp_recvmsg, - diff --git a/linux/linux-mtx-1-2.4.24/13-openswan-2.2.0.patch b/linux/linux-mtx-1-2.4.24/13-openswan-2.2.0.patch deleted file mode 100644 index db64219eda..0000000000 --- a/linux/linux-mtx-1-2.4.24/13-openswan-2.2.0.patch +++ /dev/null @@ -1,61573 +0,0 @@ -make[1]: Entering directory `/data/mtx/oe/tmp/work/openswan-2.2.0-r0/openswan-2.2.0' -packaging/utils/kernelpatch 2.4 ---- linux/Documentation/Configure.help.orig Fri Dec 21 12:41:53 2001 -+++ linux/Documentation/Configure.help Mon Jul 29 16:35:32 2002 -@@ -24237,5 +24237,65 @@ - --# -+IP Security Protocol (IPSEC) (EXPERIMENTAL) -+CONFIG_IPSEC -+ This unit is experimental code. -+ Pick 'y' for static linking, 'm' for module support or 'n' for none. -+ This option adds support for network layer packet encryption and/or -+ authentication with participating hosts. The standards start with: -+ RFCs 2411, 2407 and 2401. Others are mentioned where they refer to -+ specific features below. There are more pending which can be found -+ at: ftp://ftp.ietf.org/internet-drafts/draft-ietf-ipsec-*. -+ A description of each document can also be found at: -+ http://ietf.org/ids.by.wg/ipsec.html. -+ Their charter can be found at: -+ http://www.ietf.org/html.charters/ipsec-charter.html -+ Snapshots and releases of the current work can be found at: -+ http://www.freeswan.org/ -+ -+IPSEC: IP-in-IP encapsulation -+CONFIG_IPSEC_IPIP -+ This option provides support for tunnel mode IPSEC. It is recommended -+ to enable this. -+ -+IPSEC: Authentication Header -+CONFIG_IPSEC_AH -+ This option provides support for the IPSEC Authentication Header -+ (IP protocol 51) which provides packet layer sender and content -+ authentication. It is recommended to enable this. RFC2402 -+ -+HMAC-MD5 algorithm -+CONFIG_IPSEC_AUTH_HMAC_MD5 -+ Provides support for authentication using the HMAC MD5 -+ algorithm with 96 bits of hash used as the authenticator. RFC2403 -+ -+HMAC-SHA1 algorithm -+CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ Provides support for Authentication Header using the HMAC SHA1 -+ algorithm with 96 bits of hash used as the authenticator. RFC2404 -+ -+IPSEC: Encapsulating Security Payload -+CONFIG_IPSEC_ESP -+ This option provides support for the IPSEC Encapsulation Security -+ Payload (IP protocol 50) which provides packet layer content -+ hiding. It is recommended to enable this. RFC2406 -+ -+3DES algorithm -+CONFIG_IPSEC_ENC_3DES -+ Provides support for Encapsulation Security Payload protocol, using -+ the triple DES encryption algorithm. RFC2451 -+ -+IPSEC Debugging Option -+CONFIG_IPSEC_DEBUG -+ Enables IPSEC kernel debugging. It is further controlled by the -+ user space utility 'klipsdebug'. -+ -+IPSEC Regression Testing option -+CONFIG_IPSEC_REGRESS -+ Enables IPSEC regression testing. Creates a number of switches in -+ /proc/sys/net/ipsec which cause various failure modes in KLIPS. -+ For more details see FreeSWAN source under -+ testing/doc/regression_options.txt. -+ -+# - # A couple of things I keep forgetting: - # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, - # Intel, IRQ, ISDN, Linux, MSDOS, NetWare, NetWinder, ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/README.openswan-2 Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,112 @@ -+* -+* RCSID $Id$ -+* -+ -+ **************************************** -+ * IPSEC for Linux, Release 2.xx series * -+ **************************************** -+ -+ -+ -+1. Files -+ -+The contents of linux/net/ipsec/ (see below) join the linux kernel source tree. -+as provided for higher up. -+ -+The programs/ directory contains the user-level utilities which you need -+to run IPSEC. See the top-level top/INSTALL to compile and install them. -+ -+The testing/ directory contains test scripts. -+ -+The doc/ directory contains -- what else -- documentation. -+ -+1.1. Kernel files -+ -+The following are found in net/ipsec/: -+ -+Makefile The Makefile -+Config.in The configuration script for make menuconfig -+defconfig Configuration defaults for first time. -+ -+radij.c General-purpose radix-tree operations -+ -+ipsec_ipcomp.c IPCOMP encapsulate/decapsulate code. -+ipsec_ah.c Authentication Header (AH) encapsulate/decapsulate code. -+ipsec_esp.c Encapsulated Security Payload (ESP) encap/decap code. -+ -+pfkey_v2.c PF_KEYv2 socket interface code. -+pfkey_v2_parser.c PF_KEYv2 message parsing and processing code. -+ -+ipsec_init.c Initialization code, /proc interface. -+ipsec_radij.c Interface with the radix tree code. -+ipsec_netlink.c Interface with the netlink code. -+ipsec_xform.c Routines and structures common to transforms. -+ipsec_tunnel.c The outgoing packet processing code. -+ipsec_rcv.c The incoming packet processing code. -+ipsec_md5c.c Somewhat modified RSADSI MD5 C code. -+ipsec_sha1.c Somewhat modified Steve Reid SHA-1 C code. -+ -+sysctl_net_ipsec.c /proc/sys/net/ipsec/* variable definitions. -+ -+version.c symbolic link to project version. -+ -+radij.h Headers for radij.c -+ -+ipcomp.h Headers used by IPCOMP code. -+ -+ipsec_radij.h Interface with the radix tree code. -+ipsec_netlink.h Headers used by the netlink interface. -+ipsec_encap.h Headers defining encapsulation structures. -+ipsec_xform.h Transform headers. -+ipsec_tunnel.h Headers used by tunneling code. -+ipsec_ipe4.h Headers for the IP-in-IP code. -+ipsec_ah.h Headers common to AH transforms. -+ipsec_md5h.h RSADSI MD5 headers. -+ipsec_sha1.h SHA-1 headers. -+ipsec_esp.h Headers common to ESP transfroms. -+ipsec_rcv.h Headers for incoming packet processing code. -+ -+1.2. User-level files. -+ -+The following are found in utils/: -+ -+eroute.c Create an "extended route" source code -+spi.c Set up Security Associations source code -+spigrp.c Link SPIs together source code. -+tncfg.c Configure the tunneling features of the virtual interface -+ source code -+klipsdebug.c Set/reset klips debugging features source code. -+version.c symbolic link to project version. -+ -+eroute.8 Create an "extended route" manual page -+spi.8 Set up Security Associations manual page -+spigrp.8 Link SPIs together manual page -+tncfg.8 Configure the tunneling features of the virtual interface -+ manual page -+klipsdebug.8 Set/reset klips debugging features manual page -+ -+eroute.5 /proc/net/ipsec_eroute format manual page -+spi.5 /proc/net/ipsec_spi format manual page -+spigrp.5 /proc/net/ipsec_spigrp format manual page -+tncfg.5 /proc/net/ipsec_tncfg format manual page -+klipsdebug.5 /proc/net/ipsec_klipsdebug format manual page -+version.5 /proc/net/ipsec_version format manual page -+pf_key.5 /proc/net/pf_key format manual page -+ -+Makefile Utilities makefile. -+ -+*.8 Manpages for the respective utils. -+ -+ -+1.3. Test files -+ -+The test scripts are locate in testing/ and and documentation is found -+at doc/src/umltesting.html. Automated testing via "make check" is available -+provided that the User-Mode-Linux patches are available. -+ -+* -+* $Log$ -+* Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+* Turn off EOLN_NATIVE flag -+* -+* (Logical change 1.5010) -+* -+* Revision 1.1 2003/12/10 01:07:49 mcr -+* documentation for additions. -+* -+* ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/aes/Makefile.objs Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,13 @@ -+ -+ASM-$(ARCH_ASM):=1 -+ASM_X86:=$(ASM-i586)$(ASM-i686) -+ -+ifneq ($(strip $(ASM_X86)),) -+obj-$(CONFIG_IPSEC_ENC_AES) += aes-i586.o -+else -+obj-$(CONFIG_IPSEC_ENC_AES) += aes.o -+endif -+ -+obj-$(CONFIG_IPSEC_ENC_AES) += aes_cbc.o -+obj-$(CONFIG_IPSEC_ENC_AES) += aes_xcbc_mac.o -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/aes/aes-i586.S Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,892 @@ -+// -+// Copyright (c) 2001, Dr Brian Gladman , Worcester, UK. -+// All rights reserved. -+// -+// TERMS -+// -+// Redistribution and use in source and binary forms, with or without -+// modification, are permitted subject to the following conditions: -+// -+// 1. Redistributions of source code must retain the above copyright -+// notice, this list of conditions and the following disclaimer. -+// -+// 2. Redistributions in binary form must reproduce the above copyright -+// notice, this list of conditions and the following disclaimer in the -+// documentation and/or other materials provided with the distribution. -+// -+// 3. The copyright holder's name must not be used to endorse or promote -+// any products derived from this software without his specific prior -+// written permission. -+// -+// This software is provided 'as is' with no express or implied warranties -+// of correctness or fitness for purpose. -+ -+// Modified by Jari Ruusu, December 24 2001 -+// - Converted syntax to GNU CPP/assembler syntax -+// - C programming interface converted back to "old" API -+// - Minor portability cleanups and speed optimizations -+ -+// An AES (Rijndael) implementation for the Pentium. This version only -+// implements the standard AES block length (128 bits, 16 bytes). This code -+// does not preserve the eax, ecx or edx registers or the artihmetic status -+// flags. However, the ebx, esi, edi, and ebp registers are preserved across -+// calls. -+ -+// void aes_set_key(aes_context *cx, const unsigned char key[], const int key_len, const int f) -+// void aes_encrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) -+// void aes_decrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) -+ -+#if defined(USE_UNDERLINE) -+# define aes_set_key _aes_set_key -+# define aes_encrypt _aes_encrypt -+# define aes_decrypt _aes_decrypt -+#endif -+#if !defined(ALIGN32BYTES) -+# define ALIGN32BYTES 32 -+#endif -+ -+ .file "aes-i586.S" -+ .globl aes_set_key -+ .globl aes_encrypt -+ .globl aes_decrypt -+ -+#define tlen 1024 // length of each of 4 'xor' arrays (256 32-bit words) -+ -+// offsets to parameters with one register pushed onto stack -+ -+#define ctx 8 // AES context structure -+#define in_blk 12 // input byte array address parameter -+#define out_blk 16 // output byte array address parameter -+ -+// offsets in context structure -+ -+#define nkey 0 // key length, size 4 -+#define nrnd 4 // number of rounds, size 4 -+#define ekey 8 // encryption key schedule base address, size 256 -+#define dkey 264 // decryption key schedule base address, size 256 -+ -+// This macro performs a forward encryption cycle. It is entered with -+// the first previous round column values in %eax, %ebx, %esi and %edi and -+// exits with the final values in the same registers. -+ -+#define fwd_rnd(p1,p2) \ -+ mov %ebx,(%esp) ;\ -+ movzbl %al,%edx ;\ -+ mov %eax,%ecx ;\ -+ mov p2(%ebp),%eax ;\ -+ mov %edi,4(%esp) ;\ -+ mov p2+12(%ebp),%edi ;\ -+ xor p1(,%edx,4),%eax ;\ -+ movzbl %ch,%edx ;\ -+ shr $16,%ecx ;\ -+ mov p2+4(%ebp),%ebx ;\ -+ xor p1+tlen(,%edx,4),%edi ;\ -+ movzbl %cl,%edx ;\ -+ movzbl %ch,%ecx ;\ -+ xor p1+3*tlen(,%ecx,4),%ebx ;\ -+ mov %esi,%ecx ;\ -+ mov p1+2*tlen(,%edx,4),%esi ;\ -+ movzbl %cl,%edx ;\ -+ xor p1(,%edx,4),%esi ;\ -+ movzbl %ch,%edx ;\ -+ shr $16,%ecx ;\ -+ xor p1+tlen(,%edx,4),%ebx ;\ -+ movzbl %cl,%edx ;\ -+ movzbl %ch,%ecx ;\ -+ xor p1+2*tlen(,%edx,4),%eax ;\ -+ mov (%esp),%edx ;\ -+ xor p1+3*tlen(,%ecx,4),%edi ;\ -+ movzbl %dl,%ecx ;\ -+ xor p2+8(%ebp),%esi ;\ -+ xor p1(,%ecx,4),%ebx ;\ -+ movzbl %dh,%ecx ;\ -+ shr $16,%edx ;\ -+ xor p1+tlen(,%ecx,4),%eax ;\ -+ movzbl %dl,%ecx ;\ -+ movzbl %dh,%edx ;\ -+ xor p1+2*tlen(,%ecx,4),%edi ;\ -+ mov 4(%esp),%ecx ;\ -+ xor p1+3*tlen(,%edx,4),%esi ;\ -+ movzbl %cl,%edx ;\ -+ xor p1(,%edx,4),%edi ;\ -+ movzbl %ch,%edx ;\ -+ shr $16,%ecx ;\ -+ xor p1+tlen(,%edx,4),%esi ;\ -+ movzbl %cl,%edx ;\ -+ movzbl %ch,%ecx ;\ -+ xor p1+2*tlen(,%edx,4),%ebx ;\ -+ xor p1+3*tlen(,%ecx,4),%eax -+ -+// This macro performs an inverse encryption cycle. It is entered with -+// the first previous round column values in %eax, %ebx, %esi and %edi and -+// exits with the final values in the same registers. -+ -+#define inv_rnd(p1,p2) \ -+ movzbl %al,%edx ;\ -+ mov %ebx,(%esp) ;\ -+ mov %eax,%ecx ;\ -+ mov p2(%ebp),%eax ;\ -+ mov %edi,4(%esp) ;\ -+ mov p2+4(%ebp),%ebx ;\ -+ xor p1(,%edx,4),%eax ;\ -+ movzbl %ch,%edx ;\ -+ shr $16,%ecx ;\ -+ mov p2+12(%ebp),%edi ;\ -+ xor p1+tlen(,%edx,4),%ebx ;\ -+ movzbl %cl,%edx ;\ -+ movzbl %ch,%ecx ;\ -+ xor p1+3*tlen(,%ecx,4),%edi ;\ -+ mov %esi,%ecx ;\ -+ mov p1+2*tlen(,%edx,4),%esi ;\ -+ movzbl %cl,%edx ;\ -+ xor p1(,%edx,4),%esi ;\ -+ movzbl %ch,%edx ;\ -+ shr $16,%ecx ;\ -+ xor p1+tlen(,%edx,4),%edi ;\ -+ movzbl %cl,%edx ;\ -+ movzbl %ch,%ecx ;\ -+ xor p1+2*tlen(,%edx,4),%eax ;\ -+ mov (%esp),%edx ;\ -+ xor p1+3*tlen(,%ecx,4),%ebx ;\ -+ movzbl %dl,%ecx ;\ -+ xor p2+8(%ebp),%esi ;\ -+ xor p1(,%ecx,4),%ebx ;\ -+ movzbl %dh,%ecx ;\ -+ shr $16,%edx ;\ -+ xor p1+tlen(,%ecx,4),%esi ;\ -+ movzbl %dl,%ecx ;\ -+ movzbl %dh,%edx ;\ -+ xor p1+2*tlen(,%ecx,4),%edi ;\ -+ mov 4(%esp),%ecx ;\ -+ xor p1+3*tlen(,%edx,4),%eax ;\ -+ movzbl %cl,%edx ;\ -+ xor p1(,%edx,4),%edi ;\ -+ movzbl %ch,%edx ;\ -+ shr $16,%ecx ;\ -+ xor p1+tlen(,%edx,4),%eax ;\ -+ movzbl %cl,%edx ;\ -+ movzbl %ch,%ecx ;\ -+ xor p1+2*tlen(,%edx,4),%ebx ;\ -+ xor p1+3*tlen(,%ecx,4),%esi -+ -+// AES (Rijndael) Encryption Subroutine -+ -+ .text -+ .align ALIGN32BYTES -+aes_encrypt: -+ push %ebp -+ mov ctx(%esp),%ebp // pointer to context -+ mov in_blk(%esp),%ecx -+ push %ebx -+ push %esi -+ push %edi -+ mov nrnd(%ebp),%edx // number of rounds -+ lea ekey+16(%ebp),%ebp // key pointer -+ -+// input four columns and xor in first round key -+ -+ mov (%ecx),%eax -+ mov 4(%ecx),%ebx -+ mov 8(%ecx),%esi -+ mov 12(%ecx),%edi -+ xor -16(%ebp),%eax -+ xor -12(%ebp),%ebx -+ xor -8(%ebp),%esi -+ xor -4(%ebp),%edi -+ -+ sub $8,%esp // space for register saves on stack -+ -+ sub $10,%edx -+ je aes_15 -+ add $32,%ebp -+ sub $2,%edx -+ je aes_13 -+ add $32,%ebp -+ -+ fwd_rnd(aes_ft_tab,-64) // 14 rounds for 256-bit key -+ fwd_rnd(aes_ft_tab,-48) -+aes_13: fwd_rnd(aes_ft_tab,-32) // 12 rounds for 192-bit key -+ fwd_rnd(aes_ft_tab,-16) -+aes_15: fwd_rnd(aes_ft_tab,0) // 10 rounds for 128-bit key -+ fwd_rnd(aes_ft_tab,16) -+ fwd_rnd(aes_ft_tab,32) -+ fwd_rnd(aes_ft_tab,48) -+ fwd_rnd(aes_ft_tab,64) -+ fwd_rnd(aes_ft_tab,80) -+ fwd_rnd(aes_ft_tab,96) -+ fwd_rnd(aes_ft_tab,112) -+ fwd_rnd(aes_ft_tab,128) -+ fwd_rnd(aes_fl_tab,144) // last round uses a different table -+ -+// move final values to the output array. -+ -+ mov out_blk+20(%esp),%ebp -+ add $8,%esp -+ mov %eax,(%ebp) -+ mov %ebx,4(%ebp) -+ mov %esi,8(%ebp) -+ mov %edi,12(%ebp) -+ pop %edi -+ pop %esi -+ pop %ebx -+ pop %ebp -+ ret -+ -+ -+// AES (Rijndael) Decryption Subroutine -+ -+ .align ALIGN32BYTES -+aes_decrypt: -+ push %ebp -+ mov ctx(%esp),%ebp // pointer to context -+ mov in_blk(%esp),%ecx -+ push %ebx -+ push %esi -+ push %edi -+ mov nrnd(%ebp),%edx // number of rounds -+ lea dkey+16(%ebp),%ebp // key pointer -+ -+// input four columns and xor in first round key -+ -+ mov (%ecx),%eax -+ mov 4(%ecx),%ebx -+ mov 8(%ecx),%esi -+ mov 12(%ecx),%edi -+ xor -16(%ebp),%eax -+ xor -12(%ebp),%ebx -+ xor -8(%ebp),%esi -+ xor -4(%ebp),%edi -+ -+ sub $8,%esp // space for register saves on stack -+ -+ sub $10,%edx -+ je aes_25 -+ add $32,%ebp -+ sub $2,%edx -+ je aes_23 -+ add $32,%ebp -+ -+ inv_rnd(aes_it_tab,-64) // 14 rounds for 256-bit key -+ inv_rnd(aes_it_tab,-48) -+aes_23: inv_rnd(aes_it_tab,-32) // 12 rounds for 192-bit key -+ inv_rnd(aes_it_tab,-16) -+aes_25: inv_rnd(aes_it_tab,0) // 10 rounds for 128-bit key -+ inv_rnd(aes_it_tab,16) -+ inv_rnd(aes_it_tab,32) -+ inv_rnd(aes_it_tab,48) -+ inv_rnd(aes_it_tab,64) -+ inv_rnd(aes_it_tab,80) -+ inv_rnd(aes_it_tab,96) -+ inv_rnd(aes_it_tab,112) -+ inv_rnd(aes_it_tab,128) -+ inv_rnd(aes_il_tab,144) // last round uses a different table -+ -+// move final values to the output array. -+ -+ mov out_blk+20(%esp),%ebp -+ add $8,%esp -+ mov %eax,(%ebp) -+ mov %ebx,4(%ebp) -+ mov %esi,8(%ebp) -+ mov %edi,12(%ebp) -+ pop %edi -+ pop %esi -+ pop %ebx -+ pop %ebp -+ ret -+ -+// AES (Rijndael) Key Schedule Subroutine -+ -+// input/output parameters -+ -+#define aes_cx 12 // AES context -+#define in_key 16 // key input array address -+#define key_ln 20 // key length, bytes (16,24,32) or bits (128,192,256) -+#define ed_flg 24 // 0=create both encr/decr keys, 1=create encr key only -+ -+// offsets for locals -+ -+#define cnt -4 -+#define kpf -8 -+#define slen 8 -+ -+// This macro performs a column mixing operation on an input 32-bit -+// word to give a 32-bit result. It uses each of the 4 bytes in the -+// the input column to index 4 different tables of 256 32-bit words -+// that are xored together to form the output value. -+ -+#define mix_col(p1) \ -+ movzbl %bl,%ecx ;\ -+ mov p1(,%ecx,4),%eax ;\ -+ movzbl %bh,%ecx ;\ -+ ror $16,%ebx ;\ -+ xor p1+tlen(,%ecx,4),%eax ;\ -+ movzbl %bl,%ecx ;\ -+ xor p1+2*tlen(,%ecx,4),%eax ;\ -+ movzbl %bh,%ecx ;\ -+ xor p1+3*tlen(,%ecx,4),%eax -+ -+// Key Schedule Macros -+ -+#define ksc4(p1) \ -+ rol $24,%ebx ;\ -+ mix_col(aes_fl_tab) ;\ -+ ror $8,%ebx ;\ -+ xor 4*p1+aes_rcon_tab,%eax ;\ -+ xor %eax,%esi ;\ -+ xor %esi,%ebp ;\ -+ mov %esi,16*p1(%edi) ;\ -+ mov %ebp,16*p1+4(%edi) ;\ -+ xor %ebp,%edx ;\ -+ xor %edx,%ebx ;\ -+ mov %edx,16*p1+8(%edi) ;\ -+ mov %ebx,16*p1+12(%edi) -+ -+#define ksc6(p1) \ -+ rol $24,%ebx ;\ -+ mix_col(aes_fl_tab) ;\ -+ ror $8,%ebx ;\ -+ xor 4*p1+aes_rcon_tab,%eax ;\ -+ xor 24*p1-24(%edi),%eax ;\ -+ mov %eax,24*p1(%edi) ;\ -+ xor 24*p1-20(%edi),%eax ;\ -+ mov %eax,24*p1+4(%edi) ;\ -+ xor %eax,%esi ;\ -+ xor %esi,%ebp ;\ -+ mov %esi,24*p1+8(%edi) ;\ -+ mov %ebp,24*p1+12(%edi) ;\ -+ xor %ebp,%edx ;\ -+ xor %edx,%ebx ;\ -+ mov %edx,24*p1+16(%edi) ;\ -+ mov %ebx,24*p1+20(%edi) -+ -+#define ksc8(p1) \ -+ rol $24,%ebx ;\ -+ mix_col(aes_fl_tab) ;\ -+ ror $8,%ebx ;\ -+ xor 4*p1+aes_rcon_tab,%eax ;\ -+ xor 32*p1-32(%edi),%eax ;\ -+ mov %eax,32*p1(%edi) ;\ -+ xor 32*p1-28(%edi),%eax ;\ -+ mov %eax,32*p1+4(%edi) ;\ -+ xor 32*p1-24(%edi),%eax ;\ -+ mov %eax,32*p1+8(%edi) ;\ -+ xor 32*p1-20(%edi),%eax ;\ -+ mov %eax,32*p1+12(%edi) ;\ -+ push %ebx ;\ -+ mov %eax,%ebx ;\ -+ mix_col(aes_fl_tab) ;\ -+ pop %ebx ;\ -+ xor %eax,%esi ;\ -+ xor %esi,%ebp ;\ -+ mov %esi,32*p1+16(%edi) ;\ -+ mov %ebp,32*p1+20(%edi) ;\ -+ xor %ebp,%edx ;\ -+ xor %edx,%ebx ;\ -+ mov %edx,32*p1+24(%edi) ;\ -+ mov %ebx,32*p1+28(%edi) -+ -+ .align ALIGN32BYTES -+aes_set_key: -+ pushfl -+ push %ebp -+ mov %esp,%ebp -+ sub $slen,%esp -+ push %ebx -+ push %esi -+ push %edi -+ -+ mov aes_cx(%ebp),%edx // edx -> AES context -+ -+ mov key_ln(%ebp),%ecx // key length -+ cmpl $128,%ecx -+ jb aes_30 -+ shr $3,%ecx -+aes_30: cmpl $32,%ecx -+ je aes_32 -+ cmpl $24,%ecx -+ je aes_32 -+ mov $16,%ecx -+aes_32: shr $2,%ecx -+ mov %ecx,nkey(%edx) -+ -+ lea 6(%ecx),%eax // 10/12/14 for 4/6/8 32-bit key length -+ mov %eax,nrnd(%edx) -+ -+ mov in_key(%ebp),%esi // key input array -+ lea ekey(%edx),%edi // key position in AES context -+ cld -+ push %ebp -+ mov %ecx,%eax // save key length in eax -+ rep ; movsl // words in the key schedule -+ mov -4(%esi),%ebx // put some values in registers -+ mov -8(%esi),%edx // to allow faster code -+ mov -12(%esi),%ebp -+ mov -16(%esi),%esi -+ -+ cmpl $4,%eax // jump on key size -+ je aes_36 -+ cmpl $6,%eax -+ je aes_35 -+ -+ ksc8(0) -+ ksc8(1) -+ ksc8(2) -+ ksc8(3) -+ ksc8(4) -+ ksc8(5) -+ ksc8(6) -+ jmp aes_37 -+aes_35: ksc6(0) -+ ksc6(1) -+ ksc6(2) -+ ksc6(3) -+ ksc6(4) -+ ksc6(5) -+ ksc6(6) -+ ksc6(7) -+ jmp aes_37 -+aes_36: ksc4(0) -+ ksc4(1) -+ ksc4(2) -+ ksc4(3) -+ ksc4(4) -+ ksc4(5) -+ ksc4(6) -+ ksc4(7) -+ ksc4(8) -+ ksc4(9) -+aes_37: pop %ebp -+ mov aes_cx(%ebp),%edx // edx -> AES context -+ cmpl $0,ed_flg(%ebp) -+ jne aes_39 -+ -+// compile decryption key schedule from encryption schedule - reverse -+// order and do mix_column operation on round keys except first and last -+ -+ mov nrnd(%edx),%eax // kt = cx->d_key + nc * cx->Nrnd -+ shl $2,%eax -+ lea dkey(%edx,%eax,4),%edi -+ lea ekey(%edx),%esi // kf = cx->e_key -+ -+ movsl // copy first round key (unmodified) -+ movsl -+ movsl -+ movsl -+ sub $32,%edi -+ movl $1,cnt(%ebp) -+aes_38: // do mix column on each column of -+ lodsl // each round key -+ mov %eax,%ebx -+ mix_col(aes_im_tab) -+ stosl -+ lodsl -+ mov %eax,%ebx -+ mix_col(aes_im_tab) -+ stosl -+ lodsl -+ mov %eax,%ebx -+ mix_col(aes_im_tab) -+ stosl -+ lodsl -+ mov %eax,%ebx -+ mix_col(aes_im_tab) -+ stosl -+ sub $32,%edi -+ -+ incl cnt(%ebp) -+ mov cnt(%ebp),%eax -+ cmp nrnd(%edx),%eax -+ jb aes_38 -+ -+ movsl // copy last round key (unmodified) -+ movsl -+ movsl -+ movsl -+aes_39: pop %edi -+ pop %esi -+ pop %ebx -+ mov %ebp,%esp -+ pop %ebp -+ popfl -+ ret -+ -+ -+// finite field multiplies by {02}, {04} and {08} -+ -+#define f2(x) ((x<<1)^(((x>>7)&1)*0x11b)) -+#define f4(x) ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b)) -+#define f8(x) ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b)) -+ -+// finite field multiplies required in table generation -+ -+#define f3(x) (f2(x) ^ x) -+#define f9(x) (f8(x) ^ x) -+#define fb(x) (f8(x) ^ f2(x) ^ x) -+#define fd(x) (f8(x) ^ f4(x) ^ x) -+#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) -+ -+// These defines generate the forward table entries -+ -+#define u0(x) ((f3(x) << 24) | (x << 16) | (x << 8) | f2(x)) -+#define u1(x) ((x << 24) | (x << 16) | (f2(x) << 8) | f3(x)) -+#define u2(x) ((x << 24) | (f2(x) << 16) | (f3(x) << 8) | x) -+#define u3(x) ((f2(x) << 24) | (f3(x) << 16) | (x << 8) | x) -+ -+// These defines generate the inverse table entries -+ -+#define v0(x) ((fb(x) << 24) | (fd(x) << 16) | (f9(x) << 8) | fe(x)) -+#define v1(x) ((fd(x) << 24) | (f9(x) << 16) | (fe(x) << 8) | fb(x)) -+#define v2(x) ((f9(x) << 24) | (fe(x) << 16) | (fb(x) << 8) | fd(x)) -+#define v3(x) ((fe(x) << 24) | (fb(x) << 16) | (fd(x) << 8) | f9(x)) -+ -+// These defines generate entries for the last round tables -+ -+#define w0(x) (x) -+#define w1(x) (x << 8) -+#define w2(x) (x << 16) -+#define w3(x) (x << 24) -+ -+// macro to generate inverse mix column tables (needed for the key schedule) -+ -+#define im_data0(p1) \ -+ .long p1(0x00),p1(0x01),p1(0x02),p1(0x03),p1(0x04),p1(0x05),p1(0x06),p1(0x07) ;\ -+ .long p1(0x08),p1(0x09),p1(0x0a),p1(0x0b),p1(0x0c),p1(0x0d),p1(0x0e),p1(0x0f) ;\ -+ .long p1(0x10),p1(0x11),p1(0x12),p1(0x13),p1(0x14),p1(0x15),p1(0x16),p1(0x17) ;\ -+ .long p1(0x18),p1(0x19),p1(0x1a),p1(0x1b),p1(0x1c),p1(0x1d),p1(0x1e),p1(0x1f) -+#define im_data1(p1) \ -+ .long p1(0x20),p1(0x21),p1(0x22),p1(0x23),p1(0x24),p1(0x25),p1(0x26),p1(0x27) ;\ -+ .long p1(0x28),p1(0x29),p1(0x2a),p1(0x2b),p1(0x2c),p1(0x2d),p1(0x2e),p1(0x2f) ;\ -+ .long p1(0x30),p1(0x31),p1(0x32),p1(0x33),p1(0x34),p1(0x35),p1(0x36),p1(0x37) ;\ -+ .long p1(0x38),p1(0x39),p1(0x3a),p1(0x3b),p1(0x3c),p1(0x3d),p1(0x3e),p1(0x3f) -+#define im_data2(p1) \ -+ .long p1(0x40),p1(0x41),p1(0x42),p1(0x43),p1(0x44),p1(0x45),p1(0x46),p1(0x47) ;\ -+ .long p1(0x48),p1(0x49),p1(0x4a),p1(0x4b),p1(0x4c),p1(0x4d),p1(0x4e),p1(0x4f) ;\ -+ .long p1(0x50),p1(0x51),p1(0x52),p1(0x53),p1(0x54),p1(0x55),p1(0x56),p1(0x57) ;\ -+ .long p1(0x58),p1(0x59),p1(0x5a),p1(0x5b),p1(0x5c),p1(0x5d),p1(0x5e),p1(0x5f) -+#define im_data3(p1) \ -+ .long p1(0x60),p1(0x61),p1(0x62),p1(0x63),p1(0x64),p1(0x65),p1(0x66),p1(0x67) ;\ -+ .long p1(0x68),p1(0x69),p1(0x6a),p1(0x6b),p1(0x6c),p1(0x6d),p1(0x6e),p1(0x6f) ;\ -+ .long p1(0x70),p1(0x71),p1(0x72),p1(0x73),p1(0x74),p1(0x75),p1(0x76),p1(0x77) ;\ -+ .long p1(0x78),p1(0x79),p1(0x7a),p1(0x7b),p1(0x7c),p1(0x7d),p1(0x7e),p1(0x7f) -+#define im_data4(p1) \ -+ .long p1(0x80),p1(0x81),p1(0x82),p1(0x83),p1(0x84),p1(0x85),p1(0x86),p1(0x87) ;\ -+ .long p1(0x88),p1(0x89),p1(0x8a),p1(0x8b),p1(0x8c),p1(0x8d),p1(0x8e),p1(0x8f) ;\ -+ .long p1(0x90),p1(0x91),p1(0x92),p1(0x93),p1(0x94),p1(0x95),p1(0x96),p1(0x97) ;\ -+ .long p1(0x98),p1(0x99),p1(0x9a),p1(0x9b),p1(0x9c),p1(0x9d),p1(0x9e),p1(0x9f) -+#define im_data5(p1) \ -+ .long p1(0xa0),p1(0xa1),p1(0xa2),p1(0xa3),p1(0xa4),p1(0xa5),p1(0xa6),p1(0xa7) ;\ -+ .long p1(0xa8),p1(0xa9),p1(0xaa),p1(0xab),p1(0xac),p1(0xad),p1(0xae),p1(0xaf) ;\ -+ .long p1(0xb0),p1(0xb1),p1(0xb2),p1(0xb3),p1(0xb4),p1(0xb5),p1(0xb6),p1(0xb7) ;\ -+ .long p1(0xb8),p1(0xb9),p1(0xba),p1(0xbb),p1(0xbc),p1(0xbd),p1(0xbe),p1(0xbf) -+#define im_data6(p1) \ -+ .long p1(0xc0),p1(0xc1),p1(0xc2),p1(0xc3),p1(0xc4),p1(0xc5),p1(0xc6),p1(0xc7) ;\ -+ .long p1(0xc8),p1(0xc9),p1(0xca),p1(0xcb),p1(0xcc),p1(0xcd),p1(0xce),p1(0xcf) ;\ -+ .long p1(0xd0),p1(0xd1),p1(0xd2),p1(0xd3),p1(0xd4),p1(0xd5),p1(0xd6),p1(0xd7) ;\ -+ .long p1(0xd8),p1(0xd9),p1(0xda),p1(0xdb),p1(0xdc),p1(0xdd),p1(0xde),p1(0xdf) -+#define im_data7(p1) \ -+ .long p1(0xe0),p1(0xe1),p1(0xe2),p1(0xe3),p1(0xe4),p1(0xe5),p1(0xe6),p1(0xe7) ;\ -+ .long p1(0xe8),p1(0xe9),p1(0xea),p1(0xeb),p1(0xec),p1(0xed),p1(0xee),p1(0xef) ;\ -+ .long p1(0xf0),p1(0xf1),p1(0xf2),p1(0xf3),p1(0xf4),p1(0xf5),p1(0xf6),p1(0xf7) ;\ -+ .long p1(0xf8),p1(0xf9),p1(0xfa),p1(0xfb),p1(0xfc),p1(0xfd),p1(0xfe),p1(0xff) -+ -+// S-box data - 256 entries -+ -+#define sb_data0(p1) \ -+ .long p1(0x63),p1(0x7c),p1(0x77),p1(0x7b),p1(0xf2),p1(0x6b),p1(0x6f),p1(0xc5) ;\ -+ .long p1(0x30),p1(0x01),p1(0x67),p1(0x2b),p1(0xfe),p1(0xd7),p1(0xab),p1(0x76) ;\ -+ .long p1(0xca),p1(0x82),p1(0xc9),p1(0x7d),p1(0xfa),p1(0x59),p1(0x47),p1(0xf0) ;\ -+ .long p1(0xad),p1(0xd4),p1(0xa2),p1(0xaf),p1(0x9c),p1(0xa4),p1(0x72),p1(0xc0) -+#define sb_data1(p1) \ -+ .long p1(0xb7),p1(0xfd),p1(0x93),p1(0x26),p1(0x36),p1(0x3f),p1(0xf7),p1(0xcc) ;\ -+ .long p1(0x34),p1(0xa5),p1(0xe5),p1(0xf1),p1(0x71),p1(0xd8),p1(0x31),p1(0x15) ;\ -+ .long p1(0x04),p1(0xc7),p1(0x23),p1(0xc3),p1(0x18),p1(0x96),p1(0x05),p1(0x9a) ;\ -+ .long p1(0x07),p1(0x12),p1(0x80),p1(0xe2),p1(0xeb),p1(0x27),p1(0xb2),p1(0x75) -+#define sb_data2(p1) \ -+ .long p1(0x09),p1(0x83),p1(0x2c),p1(0x1a),p1(0x1b),p1(0x6e),p1(0x5a),p1(0xa0) ;\ -+ .long p1(0x52),p1(0x3b),p1(0xd6),p1(0xb3),p1(0x29),p1(0xe3),p1(0x2f),p1(0x84) ;\ -+ .long p1(0x53),p1(0xd1),p1(0x00),p1(0xed),p1(0x20),p1(0xfc),p1(0xb1),p1(0x5b) ;\ -+ .long p1(0x6a),p1(0xcb),p1(0xbe),p1(0x39),p1(0x4a),p1(0x4c),p1(0x58),p1(0xcf) -+#define sb_data3(p1) \ -+ .long p1(0xd0),p1(0xef),p1(0xaa),p1(0xfb),p1(0x43),p1(0x4d),p1(0x33),p1(0x85) ;\ -+ .long p1(0x45),p1(0xf9),p1(0x02),p1(0x7f),p1(0x50),p1(0x3c),p1(0x9f),p1(0xa8) ;\ -+ .long p1(0x51),p1(0xa3),p1(0x40),p1(0x8f),p1(0x92),p1(0x9d),p1(0x38),p1(0xf5) ;\ -+ .long p1(0xbc),p1(0xb6),p1(0xda),p1(0x21),p1(0x10),p1(0xff),p1(0xf3),p1(0xd2) -+#define sb_data4(p1) \ -+ .long p1(0xcd),p1(0x0c),p1(0x13),p1(0xec),p1(0x5f),p1(0x97),p1(0x44),p1(0x17) ;\ -+ .long p1(0xc4),p1(0xa7),p1(0x7e),p1(0x3d),p1(0x64),p1(0x5d),p1(0x19),p1(0x73) ;\ -+ .long p1(0x60),p1(0x81),p1(0x4f),p1(0xdc),p1(0x22),p1(0x2a),p1(0x90),p1(0x88) ;\ -+ .long p1(0x46),p1(0xee),p1(0xb8),p1(0x14),p1(0xde),p1(0x5e),p1(0x0b),p1(0xdb) -+#define sb_data5(p1) \ -+ .long p1(0xe0),p1(0x32),p1(0x3a),p1(0x0a),p1(0x49),p1(0x06),p1(0x24),p1(0x5c) ;\ -+ .long p1(0xc2),p1(0xd3),p1(0xac),p1(0x62),p1(0x91),p1(0x95),p1(0xe4),p1(0x79) ;\ -+ .long p1(0xe7),p1(0xc8),p1(0x37),p1(0x6d),p1(0x8d),p1(0xd5),p1(0x4e),p1(0xa9) ;\ -+ .long p1(0x6c),p1(0x56),p1(0xf4),p1(0xea),p1(0x65),p1(0x7a),p1(0xae),p1(0x08) -+#define sb_data6(p1) \ -+ .long p1(0xba),p1(0x78),p1(0x25),p1(0x2e),p1(0x1c),p1(0xa6),p1(0xb4),p1(0xc6) ;\ -+ .long p1(0xe8),p1(0xdd),p1(0x74),p1(0x1f),p1(0x4b),p1(0xbd),p1(0x8b),p1(0x8a) ;\ -+ .long p1(0x70),p1(0x3e),p1(0xb5),p1(0x66),p1(0x48),p1(0x03),p1(0xf6),p1(0x0e) ;\ -+ .long p1(0x61),p1(0x35),p1(0x57),p1(0xb9),p1(0x86),p1(0xc1),p1(0x1d),p1(0x9e) -+#define sb_data7(p1) \ -+ .long p1(0xe1),p1(0xf8),p1(0x98),p1(0x11),p1(0x69),p1(0xd9),p1(0x8e),p1(0x94) ;\ -+ .long p1(0x9b),p1(0x1e),p1(0x87),p1(0xe9),p1(0xce),p1(0x55),p1(0x28),p1(0xdf) ;\ -+ .long p1(0x8c),p1(0xa1),p1(0x89),p1(0x0d),p1(0xbf),p1(0xe6),p1(0x42),p1(0x68) ;\ -+ .long p1(0x41),p1(0x99),p1(0x2d),p1(0x0f),p1(0xb0),p1(0x54),p1(0xbb),p1(0x16) -+ -+// Inverse S-box data - 256 entries -+ -+#define ib_data0(p1) \ -+ .long p1(0x52),p1(0x09),p1(0x6a),p1(0xd5),p1(0x30),p1(0x36),p1(0xa5),p1(0x38) ;\ -+ .long p1(0xbf),p1(0x40),p1(0xa3),p1(0x9e),p1(0x81),p1(0xf3),p1(0xd7),p1(0xfb) ;\ -+ .long p1(0x7c),p1(0xe3),p1(0x39),p1(0x82),p1(0x9b),p1(0x2f),p1(0xff),p1(0x87) ;\ -+ .long p1(0x34),p1(0x8e),p1(0x43),p1(0x44),p1(0xc4),p1(0xde),p1(0xe9),p1(0xcb) -+#define ib_data1(p1) \ -+ .long p1(0x54),p1(0x7b),p1(0x94),p1(0x32),p1(0xa6),p1(0xc2),p1(0x23),p1(0x3d) ;\ -+ .long p1(0xee),p1(0x4c),p1(0x95),p1(0x0b),p1(0x42),p1(0xfa),p1(0xc3),p1(0x4e) ;\ -+ .long p1(0x08),p1(0x2e),p1(0xa1),p1(0x66),p1(0x28),p1(0xd9),p1(0x24),p1(0xb2) ;\ -+ .long p1(0x76),p1(0x5b),p1(0xa2),p1(0x49),p1(0x6d),p1(0x8b),p1(0xd1),p1(0x25) -+#define ib_data2(p1) \ -+ .long p1(0x72),p1(0xf8),p1(0xf6),p1(0x64),p1(0x86),p1(0x68),p1(0x98),p1(0x16) ;\ -+ .long p1(0xd4),p1(0xa4),p1(0x5c),p1(0xcc),p1(0x5d),p1(0x65),p1(0xb6),p1(0x92) ;\ -+ .long p1(0x6c),p1(0x70),p1(0x48),p1(0x50),p1(0xfd),p1(0xed),p1(0xb9),p1(0xda) ;\ -+ .long p1(0x5e),p1(0x15),p1(0x46),p1(0x57),p1(0xa7),p1(0x8d),p1(0x9d),p1(0x84) -+#define ib_data3(p1) \ -+ .long p1(0x90),p1(0xd8),p1(0xab),p1(0x00),p1(0x8c),p1(0xbc),p1(0xd3),p1(0x0a) ;\ -+ .long p1(0xf7),p1(0xe4),p1(0x58),p1(0x05),p1(0xb8),p1(0xb3),p1(0x45),p1(0x06) ;\ -+ .long p1(0xd0),p1(0x2c),p1(0x1e),p1(0x8f),p1(0xca),p1(0x3f),p1(0x0f),p1(0x02) ;\ -+ .long p1(0xc1),p1(0xaf),p1(0xbd),p1(0x03),p1(0x01),p1(0x13),p1(0x8a),p1(0x6b) -+#define ib_data4(p1) \ -+ .long p1(0x3a),p1(0x91),p1(0x11),p1(0x41),p1(0x4f),p1(0x67),p1(0xdc),p1(0xea) ;\ -+ .long p1(0x97),p1(0xf2),p1(0xcf),p1(0xce),p1(0xf0),p1(0xb4),p1(0xe6),p1(0x73) ;\ -+ .long p1(0x96),p1(0xac),p1(0x74),p1(0x22),p1(0xe7),p1(0xad),p1(0x35),p1(0x85) ;\ -+ .long p1(0xe2),p1(0xf9),p1(0x37),p1(0xe8),p1(0x1c),p1(0x75),p1(0xdf),p1(0x6e) -+#define ib_data5(p1) \ -+ .long p1(0x47),p1(0xf1),p1(0x1a),p1(0x71),p1(0x1d),p1(0x29),p1(0xc5),p1(0x89) ;\ -+ .long p1(0x6f),p1(0xb7),p1(0x62),p1(0x0e),p1(0xaa),p1(0x18),p1(0xbe),p1(0x1b) ;\ -+ .long p1(0xfc),p1(0x56),p1(0x3e),p1(0x4b),p1(0xc6),p1(0xd2),p1(0x79),p1(0x20) ;\ -+ .long p1(0x9a),p1(0xdb),p1(0xc0),p1(0xfe),p1(0x78),p1(0xcd),p1(0x5a),p1(0xf4) -+#define ib_data6(p1) \ -+ .long p1(0x1f),p1(0xdd),p1(0xa8),p1(0x33),p1(0x88),p1(0x07),p1(0xc7),p1(0x31) ;\ -+ .long p1(0xb1),p1(0x12),p1(0x10),p1(0x59),p1(0x27),p1(0x80),p1(0xec),p1(0x5f) ;\ -+ .long p1(0x60),p1(0x51),p1(0x7f),p1(0xa9),p1(0x19),p1(0xb5),p1(0x4a),p1(0x0d) ;\ -+ .long p1(0x2d),p1(0xe5),p1(0x7a),p1(0x9f),p1(0x93),p1(0xc9),p1(0x9c),p1(0xef) -+#define ib_data7(p1) \ -+ .long p1(0xa0),p1(0xe0),p1(0x3b),p1(0x4d),p1(0xae),p1(0x2a),p1(0xf5),p1(0xb0) ;\ -+ .long p1(0xc8),p1(0xeb),p1(0xbb),p1(0x3c),p1(0x83),p1(0x53),p1(0x99),p1(0x61) ;\ -+ .long p1(0x17),p1(0x2b),p1(0x04),p1(0x7e),p1(0xba),p1(0x77),p1(0xd6),p1(0x26) ;\ -+ .long p1(0xe1),p1(0x69),p1(0x14),p1(0x63),p1(0x55),p1(0x21),p1(0x0c),p1(0x7d) -+ -+// The rcon_table (needed for the key schedule) -+// -+// Here is original Dr Brian Gladman's source code: -+// _rcon_tab: -+// %assign x 1 -+// %rep 29 -+// dd x -+// %assign x f2(x) -+// %endrep -+// -+// Here is precomputed output (it's more portable this way): -+ -+ .align ALIGN32BYTES -+aes_rcon_tab: -+ .long 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 -+ .long 0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f -+ .long 0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4 -+ .long 0xb3,0x7d,0xfa,0xef,0xc5 -+ -+// The forward xor tables -+ -+ .align ALIGN32BYTES -+aes_ft_tab: -+ sb_data0(u0) -+ sb_data1(u0) -+ sb_data2(u0) -+ sb_data3(u0) -+ sb_data4(u0) -+ sb_data5(u0) -+ sb_data6(u0) -+ sb_data7(u0) -+ -+ sb_data0(u1) -+ sb_data1(u1) -+ sb_data2(u1) -+ sb_data3(u1) -+ sb_data4(u1) -+ sb_data5(u1) -+ sb_data6(u1) -+ sb_data7(u1) -+ -+ sb_data0(u2) -+ sb_data1(u2) -+ sb_data2(u2) -+ sb_data3(u2) -+ sb_data4(u2) -+ sb_data5(u2) -+ sb_data6(u2) -+ sb_data7(u2) -+ -+ sb_data0(u3) -+ sb_data1(u3) -+ sb_data2(u3) -+ sb_data3(u3) -+ sb_data4(u3) -+ sb_data5(u3) -+ sb_data6(u3) -+ sb_data7(u3) -+ -+ .align ALIGN32BYTES -+aes_fl_tab: -+ sb_data0(w0) -+ sb_data1(w0) -+ sb_data2(w0) -+ sb_data3(w0) -+ sb_data4(w0) -+ sb_data5(w0) -+ sb_data6(w0) -+ sb_data7(w0) -+ -+ sb_data0(w1) -+ sb_data1(w1) -+ sb_data2(w1) -+ sb_data3(w1) -+ sb_data4(w1) -+ sb_data5(w1) -+ sb_data6(w1) -+ sb_data7(w1) -+ -+ sb_data0(w2) -+ sb_data1(w2) -+ sb_data2(w2) -+ sb_data3(w2) -+ sb_data4(w2) -+ sb_data5(w2) -+ sb_data6(w2) -+ sb_data7(w2) -+ -+ sb_data0(w3) -+ sb_data1(w3) -+ sb_data2(w3) -+ sb_data3(w3) -+ sb_data4(w3) -+ sb_data5(w3) -+ sb_data6(w3) -+ sb_data7(w3) -+ -+// The inverse xor tables -+ -+ .align ALIGN32BYTES -+aes_it_tab: -+ ib_data0(v0) -+ ib_data1(v0) -+ ib_data2(v0) -+ ib_data3(v0) -+ ib_data4(v0) -+ ib_data5(v0) -+ ib_data6(v0) -+ ib_data7(v0) -+ -+ ib_data0(v1) -+ ib_data1(v1) -+ ib_data2(v1) -+ ib_data3(v1) -+ ib_data4(v1) -+ ib_data5(v1) -+ ib_data6(v1) -+ ib_data7(v1) -+ -+ ib_data0(v2) -+ ib_data1(v2) -+ ib_data2(v2) -+ ib_data3(v2) -+ ib_data4(v2) -+ ib_data5(v2) -+ ib_data6(v2) -+ ib_data7(v2) -+ -+ ib_data0(v3) -+ ib_data1(v3) -+ ib_data2(v3) -+ ib_data3(v3) -+ ib_data4(v3) -+ ib_data5(v3) -+ ib_data6(v3) -+ ib_data7(v3) -+ -+ .align ALIGN32BYTES -+aes_il_tab: -+ ib_data0(w0) -+ ib_data1(w0) -+ ib_data2(w0) -+ ib_data3(w0) -+ ib_data4(w0) -+ ib_data5(w0) -+ ib_data6(w0) -+ ib_data7(w0) -+ -+ ib_data0(w1) -+ ib_data1(w1) -+ ib_data2(w1) -+ ib_data3(w1) -+ ib_data4(w1) -+ ib_data5(w1) -+ ib_data6(w1) -+ ib_data7(w1) -+ -+ ib_data0(w2) -+ ib_data1(w2) -+ ib_data2(w2) -+ ib_data3(w2) -+ ib_data4(w2) -+ ib_data5(w2) -+ ib_data6(w2) -+ ib_data7(w2) -+ -+ ib_data0(w3) -+ ib_data1(w3) -+ ib_data2(w3) -+ ib_data3(w3) -+ ib_data4(w3) -+ ib_data5(w3) -+ ib_data6(w3) -+ ib_data7(w3) -+ -+// The inverse mix column tables -+ -+ .align ALIGN32BYTES -+aes_im_tab: -+ im_data0(v0) -+ im_data1(v0) -+ im_data2(v0) -+ im_data3(v0) -+ im_data4(v0) -+ im_data5(v0) -+ im_data6(v0) -+ im_data7(v0) -+ -+ im_data0(v1) -+ im_data1(v1) -+ im_data2(v1) -+ im_data3(v1) -+ im_data4(v1) -+ im_data5(v1) -+ im_data6(v1) -+ im_data7(v1) -+ -+ im_data0(v2) -+ im_data1(v2) -+ im_data2(v2) -+ im_data3(v2) -+ im_data4(v2) -+ im_data5(v2) -+ im_data6(v2) -+ im_data7(v2) -+ -+ im_data0(v3) -+ im_data1(v3) -+ im_data2(v3) -+ im_data3(v3) -+ im_data4(v3) -+ im_data5(v3) -+ im_data6(v3) -+ im_data7(v3) ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/aes/aes.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1415 @@ -+// I retain copyright in this code but I encourage its free use provided -+// that I don't carry any responsibility for the results. I am especially -+// happy to see it used in free and open source software. If you do use -+// it I would appreciate an acknowledgement of its origin in the code or -+// the product that results and I would also appreciate knowing a little -+// about the use to which it is being put. I am grateful to Frank Yellin -+// for some ideas that are used in this implementation. -+// -+// Dr B. R. Gladman 6th April 2001. -+// -+// This is an implementation of the AES encryption algorithm (Rijndael) -+// designed by Joan Daemen and Vincent Rijmen. This version is designed -+// to provide both fixed and dynamic block and key lengths and can also -+// run with either big or little endian internal byte order (see aes.h). -+// It inputs block and key lengths in bytes with the legal values being -+// 16, 24 and 32. -+ -+/* -+ * Modified by Jari Ruusu, May 1 2001 -+ * - Fixed some compile warnings, code was ok but gcc warned anyway. -+ * - Changed basic types: byte -> unsigned char, word -> u_int32_t -+ * - Major name space cleanup: Names visible to outside now begin -+ * with "aes_" or "AES_". A lot of stuff moved from aes.h to aes.c -+ * - Removed C++ and DLL support as part of name space cleanup. -+ * - Eliminated unnecessary recomputation of tables. (actual bug fix) -+ * - Merged precomputed constant tables to aes.c file. -+ * - Removed data alignment restrictions for portability reasons. -+ * - Made block and key lengths accept bit count (128/192/256) -+ * as well byte count (16/24/32). -+ * - Removed all error checks. This change also eliminated the need -+ * to preinitialize the context struct to zero. -+ * - Removed some totally unused constants. -+ */ -+ -+#include "crypto/aes.h" -+ -+// CONFIGURATION OPTIONS (see also aes.h) -+// -+// 1. Define UNROLL for full loop unrolling in encryption and decryption. -+// 2. Define PARTIAL_UNROLL to unroll two loops in encryption and decryption. -+// 3. Define FIXED_TABLES for compiled rather than dynamic tables. -+// 4. Define FF_TABLES to use tables for field multiplies and inverses. -+// Do not enable this without understanding stack space requirements. -+// 5. Define ARRAYS to use arrays to hold the local state block. If this -+// is not defined, individually declared 32-bit words are used. -+// 6. Define FAST_VARIABLE if a high speed variable block implementation -+// is needed (essentially three separate fixed block size code sequences) -+// 7. Define either ONE_TABLE or FOUR_TABLES for a fast table driven -+// version using 1 table (2 kbytes of table space) or 4 tables (8 -+// kbytes of table space) for higher speed. -+// 8. Define either ONE_LR_TABLE or FOUR_LR_TABLES for a further speed -+// increase by using tables for the last rounds but with more table -+// space (2 or 8 kbytes extra). -+// 9. If neither ONE_TABLE nor FOUR_TABLES is defined, a compact but -+// slower version is provided. -+// 10. If fast decryption key scheduling is needed define ONE_IM_TABLE -+// or FOUR_IM_TABLES for higher speed (2 or 8 kbytes extra). -+ -+#define UNROLL -+//#define PARTIAL_UNROLL -+ -+#define FIXED_TABLES -+//#define FF_TABLES -+//#define ARRAYS -+#define FAST_VARIABLE -+ -+//#define ONE_TABLE -+#define FOUR_TABLES -+ -+//#define ONE_LR_TABLE -+#define FOUR_LR_TABLES -+ -+//#define ONE_IM_TABLE -+#define FOUR_IM_TABLES -+ -+#if defined(UNROLL) && defined (PARTIAL_UNROLL) -+#error both UNROLL and PARTIAL_UNROLL are defined -+#endif -+ -+#if defined(ONE_TABLE) && defined (FOUR_TABLES) -+#error both ONE_TABLE and FOUR_TABLES are defined -+#endif -+ -+#if defined(ONE_LR_TABLE) && defined (FOUR_LR_TABLES) -+#error both ONE_LR_TABLE and FOUR_LR_TABLES are defined -+#endif -+ -+#if defined(ONE_IM_TABLE) && defined (FOUR_IM_TABLES) -+#error both ONE_IM_TABLE and FOUR_IM_TABLES are defined -+#endif -+ -+#if defined(AES_BLOCK_SIZE) && AES_BLOCK_SIZE != 16 && AES_BLOCK_SIZE != 24 && AES_BLOCK_SIZE != 32 -+#error an illegal block size has been specified -+#endif -+ -+// upr(x,n): rotates bytes within words by n positions, moving bytes -+// to higher index positions with wrap around into low positions -+// ups(x,n): moves bytes by n positions to higher index positions in -+// words but without wrap around -+// bval(x,n): extracts a byte from a word -+ -+#define upr(x,n) (((x) << 8 * (n)) | ((x) >> (32 - 8 * (n)))) -+#define ups(x,n) ((x) << 8 * (n)) -+#define bval(x,n) ((unsigned char)((x) >> 8 * (n))) -+#define bytes2word(b0, b1, b2, b3) \ -+ ((u_int32_t)(b3) << 24 | (u_int32_t)(b2) << 16 | (u_int32_t)(b1) << 8 | (b0)) -+ -+ -+/* little endian processor without data alignment restrictions: AES_LE_OK */ -+/* original code: i386 */ -+#if defined(i386) || defined(_I386) || defined(__i386__) || defined(__i386) -+#define AES_LE_OK 1 -+/* added (tested): alpha --jjo */ -+#elif defined(__alpha__)|| defined (__alpha) -+#define AES_LE_OK 1 -+/* added (tested): ia64 --jjo */ -+#elif defined(__ia64__)|| defined (__ia64) -+#define AES_LE_OK 1 -+#endif -+ -+#ifdef AES_LE_OK -+/* little endian processor without data alignment restrictions */ -+#define word_in(x) *(u_int32_t*)(x) -+#define const_word_in(x) *(const u_int32_t*)(x) -+#define word_out(x,v) *(u_int32_t*)(x) = (v) -+#define const_word_out(x,v) *(const u_int32_t*)(x) = (v) -+#else -+/* slower but generic big endian or with data alignment restrictions */ -+/* some additional "const" touches to stop "gcc -Wcast-qual" complains --jjo */ -+#define word_in(x) ((u_int32_t)(((unsigned char *)(x))[0])|((u_int32_t)(((unsigned char *)(x))[1])<<8)|((u_int32_t)(((unsigned char *)(x))[2])<<16)|((u_int32_t)(((unsigned char *)(x))[3])<<24)) -+#define const_word_in(x) ((const u_int32_t)(((const unsigned char *)(x))[0])|((const u_int32_t)(((const unsigned char *)(x))[1])<<8)|((const u_int32_t)(((const unsigned char *)(x))[2])<<16)|((const u_int32_t)(((const unsigned char *)(x))[3])<<24)) -+#define word_out(x,v) ((unsigned char *)(x))[0]=(v),((unsigned char *)(x))[1]=((v)>>8),((unsigned char *)(x))[2]=((v)>>16),((unsigned char *)(x))[3]=((v)>>24) -+#define const_word_out(x,v) ((const unsigned char *)(x))[0]=(v),((const unsigned char *)(x))[1]=((v)>>8),((const unsigned char *)(x))[2]=((v)>>16),((const unsigned char *)(x))[3]=((v)>>24) -+#endif -+ -+// Disable at least some poor combinations of options -+ -+#if !defined(ONE_TABLE) && !defined(FOUR_TABLES) -+#define FIXED_TABLES -+#undef UNROLL -+#undef ONE_LR_TABLE -+#undef FOUR_LR_TABLES -+#undef ONE_IM_TABLE -+#undef FOUR_IM_TABLES -+#elif !defined(FOUR_TABLES) -+#ifdef FOUR_LR_TABLES -+#undef FOUR_LR_TABLES -+#define ONE_LR_TABLE -+#endif -+#ifdef FOUR_IM_TABLES -+#undef FOUR_IM_TABLES -+#define ONE_IM_TABLE -+#endif -+#elif !defined(AES_BLOCK_SIZE) -+#if defined(UNROLL) -+#define PARTIAL_UNROLL -+#undef UNROLL -+#endif -+#endif -+ -+// the finite field modular polynomial and elements -+ -+#define ff_poly 0x011b -+#define ff_hi 0x80 -+ -+// multiply four bytes in GF(2^8) by 'x' {02} in parallel -+ -+#define m1 0x80808080 -+#define m2 0x7f7f7f7f -+#define m3 0x0000001b -+#define FFmulX(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * m3)) -+ -+// The following defines provide alternative definitions of FFmulX that might -+// give improved performance if a fast 32-bit multiply is not available. Note -+// that a temporary variable u needs to be defined where FFmulX is used. -+ -+// #define FFmulX(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) -+// #define m4 0x1b1b1b1b -+// #define FFmulX(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) -+ -+// perform column mix operation on four bytes in parallel -+ -+#define fwd_mcol(x) (f2 = FFmulX(x), f2 ^ upr(x ^ f2,3) ^ upr(x,2) ^ upr(x,1)) -+ -+#if defined(FIXED_TABLES) -+ -+// the S-Box table -+ -+static const unsigned char s_box[256] = -+{ -+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, -+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, -+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, -+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, -+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, -+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, -+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, -+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, -+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, -+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, -+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, -+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, -+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, -+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, -+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, -+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, -+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, -+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, -+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, -+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, -+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, -+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, -+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, -+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, -+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, -+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, -+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, -+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, -+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, -+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, -+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, -+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 -+}; -+ -+// the inverse S-Box table -+ -+static const unsigned char inv_s_box[256] = -+{ -+ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, -+ 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, -+ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, -+ 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, -+ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, -+ 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, -+ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, -+ 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, -+ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, -+ 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, -+ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, -+ 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, -+ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, -+ 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, -+ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, -+ 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, -+ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, -+ 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, -+ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, -+ 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, -+ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, -+ 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, -+ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, -+ 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, -+ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, -+ 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, -+ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, -+ 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, -+ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, -+ 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, -+ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, -+ 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d -+}; -+ -+#define w0(p) 0x000000##p -+ -+// Number of elements required in this table for different -+// block and key lengths is: -+// -+// Nk = 4 6 8 -+// ---------- -+// Nb = 4 | 10 8 7 -+// 6 | 19 12 11 -+// 8 | 29 19 14 -+// -+// this table can be a table of bytes if the key schedule -+// code is adjusted accordingly -+ -+static const u_int32_t rcon_tab[29] = -+{ -+ w0(01), w0(02), w0(04), w0(08), -+ w0(10), w0(20), w0(40), w0(80), -+ w0(1b), w0(36), w0(6c), w0(d8), -+ w0(ab), w0(4d), w0(9a), w0(2f), -+ w0(5e), w0(bc), w0(63), w0(c6), -+ w0(97), w0(35), w0(6a), w0(d4), -+ w0(b3), w0(7d), w0(fa), w0(ef), -+ w0(c5) -+}; -+ -+#undef w0 -+ -+#define r0(p,q,r,s) 0x##p##q##r##s -+#define r1(p,q,r,s) 0x##q##r##s##p -+#define r2(p,q,r,s) 0x##r##s##p##q -+#define r3(p,q,r,s) 0x##s##p##q##r -+#define w0(p) 0x000000##p -+#define w1(p) 0x0000##p##00 -+#define w2(p) 0x00##p##0000 -+#define w3(p) 0x##p##000000 -+ -+#if defined(FIXED_TABLES) && (defined(ONE_TABLE) || defined(FOUR_TABLES)) -+ -+// data for forward tables (other than last round) -+ -+#define f_table \ -+ r(a5,63,63,c6), r(84,7c,7c,f8), r(99,77,77,ee), r(8d,7b,7b,f6),\ -+ r(0d,f2,f2,ff), r(bd,6b,6b,d6), r(b1,6f,6f,de), r(54,c5,c5,91),\ -+ r(50,30,30,60), r(03,01,01,02), r(a9,67,67,ce), r(7d,2b,2b,56),\ -+ r(19,fe,fe,e7), r(62,d7,d7,b5), r(e6,ab,ab,4d), r(9a,76,76,ec),\ -+ r(45,ca,ca,8f), r(9d,82,82,1f), r(40,c9,c9,89), r(87,7d,7d,fa),\ -+ r(15,fa,fa,ef), r(eb,59,59,b2), r(c9,47,47,8e), r(0b,f0,f0,fb),\ -+ r(ec,ad,ad,41), r(67,d4,d4,b3), r(fd,a2,a2,5f), r(ea,af,af,45),\ -+ r(bf,9c,9c,23), r(f7,a4,a4,53), r(96,72,72,e4), r(5b,c0,c0,9b),\ -+ r(c2,b7,b7,75), r(1c,fd,fd,e1), r(ae,93,93,3d), r(6a,26,26,4c),\ -+ r(5a,36,36,6c), r(41,3f,3f,7e), r(02,f7,f7,f5), r(4f,cc,cc,83),\ -+ r(5c,34,34,68), r(f4,a5,a5,51), r(34,e5,e5,d1), r(08,f1,f1,f9),\ -+ r(93,71,71,e2), r(73,d8,d8,ab), r(53,31,31,62), r(3f,15,15,2a),\ -+ r(0c,04,04,08), r(52,c7,c7,95), r(65,23,23,46), r(5e,c3,c3,9d),\ -+ r(28,18,18,30), r(a1,96,96,37), r(0f,05,05,0a), r(b5,9a,9a,2f),\ -+ r(09,07,07,0e), r(36,12,12,24), r(9b,80,80,1b), r(3d,e2,e2,df),\ -+ r(26,eb,eb,cd), r(69,27,27,4e), r(cd,b2,b2,7f), r(9f,75,75,ea),\ -+ r(1b,09,09,12), r(9e,83,83,1d), r(74,2c,2c,58), r(2e,1a,1a,34),\ -+ r(2d,1b,1b,36), r(b2,6e,6e,dc), r(ee,5a,5a,b4), r(fb,a0,a0,5b),\ -+ r(f6,52,52,a4), r(4d,3b,3b,76), r(61,d6,d6,b7), r(ce,b3,b3,7d),\ -+ r(7b,29,29,52), r(3e,e3,e3,dd), r(71,2f,2f,5e), r(97,84,84,13),\ -+ r(f5,53,53,a6), r(68,d1,d1,b9), r(00,00,00,00), r(2c,ed,ed,c1),\ -+ r(60,20,20,40), r(1f,fc,fc,e3), r(c8,b1,b1,79), r(ed,5b,5b,b6),\ -+ r(be,6a,6a,d4), r(46,cb,cb,8d), r(d9,be,be,67), r(4b,39,39,72),\ -+ r(de,4a,4a,94), r(d4,4c,4c,98), r(e8,58,58,b0), r(4a,cf,cf,85),\ -+ r(6b,d0,d0,bb), r(2a,ef,ef,c5), r(e5,aa,aa,4f), r(16,fb,fb,ed),\ -+ r(c5,43,43,86), r(d7,4d,4d,9a), r(55,33,33,66), r(94,85,85,11),\ -+ r(cf,45,45,8a), r(10,f9,f9,e9), r(06,02,02,04), r(81,7f,7f,fe),\ -+ r(f0,50,50,a0), r(44,3c,3c,78), r(ba,9f,9f,25), r(e3,a8,a8,4b),\ -+ r(f3,51,51,a2), r(fe,a3,a3,5d), r(c0,40,40,80), r(8a,8f,8f,05),\ -+ r(ad,92,92,3f), r(bc,9d,9d,21), r(48,38,38,70), r(04,f5,f5,f1),\ -+ r(df,bc,bc,63), r(c1,b6,b6,77), r(75,da,da,af), r(63,21,21,42),\ -+ r(30,10,10,20), r(1a,ff,ff,e5), r(0e,f3,f3,fd), r(6d,d2,d2,bf),\ -+ r(4c,cd,cd,81), r(14,0c,0c,18), r(35,13,13,26), r(2f,ec,ec,c3),\ -+ r(e1,5f,5f,be), r(a2,97,97,35), r(cc,44,44,88), r(39,17,17,2e),\ -+ r(57,c4,c4,93), r(f2,a7,a7,55), r(82,7e,7e,fc), r(47,3d,3d,7a),\ -+ r(ac,64,64,c8), r(e7,5d,5d,ba), r(2b,19,19,32), r(95,73,73,e6),\ -+ r(a0,60,60,c0), r(98,81,81,19), r(d1,4f,4f,9e), r(7f,dc,dc,a3),\ -+ r(66,22,22,44), r(7e,2a,2a,54), r(ab,90,90,3b), r(83,88,88,0b),\ -+ r(ca,46,46,8c), r(29,ee,ee,c7), r(d3,b8,b8,6b), r(3c,14,14,28),\ -+ r(79,de,de,a7), r(e2,5e,5e,bc), r(1d,0b,0b,16), r(76,db,db,ad),\ -+ r(3b,e0,e0,db), r(56,32,32,64), r(4e,3a,3a,74), r(1e,0a,0a,14),\ -+ r(db,49,49,92), r(0a,06,06,0c), r(6c,24,24,48), r(e4,5c,5c,b8),\ -+ r(5d,c2,c2,9f), r(6e,d3,d3,bd), r(ef,ac,ac,43), r(a6,62,62,c4),\ -+ r(a8,91,91,39), r(a4,95,95,31), r(37,e4,e4,d3), r(8b,79,79,f2),\ -+ r(32,e7,e7,d5), r(43,c8,c8,8b), r(59,37,37,6e), r(b7,6d,6d,da),\ -+ r(8c,8d,8d,01), r(64,d5,d5,b1), r(d2,4e,4e,9c), r(e0,a9,a9,49),\ -+ r(b4,6c,6c,d8), r(fa,56,56,ac), r(07,f4,f4,f3), r(25,ea,ea,cf),\ -+ r(af,65,65,ca), r(8e,7a,7a,f4), r(e9,ae,ae,47), r(18,08,08,10),\ -+ r(d5,ba,ba,6f), r(88,78,78,f0), r(6f,25,25,4a), r(72,2e,2e,5c),\ -+ r(24,1c,1c,38), r(f1,a6,a6,57), r(c7,b4,b4,73), r(51,c6,c6,97),\ -+ r(23,e8,e8,cb), r(7c,dd,dd,a1), r(9c,74,74,e8), r(21,1f,1f,3e),\ -+ r(dd,4b,4b,96), r(dc,bd,bd,61), r(86,8b,8b,0d), r(85,8a,8a,0f),\ -+ r(90,70,70,e0), r(42,3e,3e,7c), r(c4,b5,b5,71), r(aa,66,66,cc),\ -+ r(d8,48,48,90), r(05,03,03,06), r(01,f6,f6,f7), r(12,0e,0e,1c),\ -+ r(a3,61,61,c2), r(5f,35,35,6a), r(f9,57,57,ae), r(d0,b9,b9,69),\ -+ r(91,86,86,17), r(58,c1,c1,99), r(27,1d,1d,3a), r(b9,9e,9e,27),\ -+ r(38,e1,e1,d9), r(13,f8,f8,eb), r(b3,98,98,2b), r(33,11,11,22),\ -+ r(bb,69,69,d2), r(70,d9,d9,a9), r(89,8e,8e,07), r(a7,94,94,33),\ -+ r(b6,9b,9b,2d), r(22,1e,1e,3c), r(92,87,87,15), r(20,e9,e9,c9),\ -+ r(49,ce,ce,87), r(ff,55,55,aa), r(78,28,28,50), r(7a,df,df,a5),\ -+ r(8f,8c,8c,03), r(f8,a1,a1,59), r(80,89,89,09), r(17,0d,0d,1a),\ -+ r(da,bf,bf,65), r(31,e6,e6,d7), r(c6,42,42,84), r(b8,68,68,d0),\ -+ r(c3,41,41,82), r(b0,99,99,29), r(77,2d,2d,5a), r(11,0f,0f,1e),\ -+ r(cb,b0,b0,7b), r(fc,54,54,a8), r(d6,bb,bb,6d), r(3a,16,16,2c) -+ -+// data for inverse tables (other than last round) -+ -+#define i_table \ -+ r(50,a7,f4,51), r(53,65,41,7e), r(c3,a4,17,1a), r(96,5e,27,3a),\ -+ r(cb,6b,ab,3b), r(f1,45,9d,1f), r(ab,58,fa,ac), r(93,03,e3,4b),\ -+ r(55,fa,30,20), r(f6,6d,76,ad), r(91,76,cc,88), r(25,4c,02,f5),\ -+ r(fc,d7,e5,4f), r(d7,cb,2a,c5), r(80,44,35,26), r(8f,a3,62,b5),\ -+ r(49,5a,b1,de), r(67,1b,ba,25), r(98,0e,ea,45), r(e1,c0,fe,5d),\ -+ r(02,75,2f,c3), r(12,f0,4c,81), r(a3,97,46,8d), r(c6,f9,d3,6b),\ -+ r(e7,5f,8f,03), r(95,9c,92,15), r(eb,7a,6d,bf), r(da,59,52,95),\ -+ r(2d,83,be,d4), r(d3,21,74,58), r(29,69,e0,49), r(44,c8,c9,8e),\ -+ r(6a,89,c2,75), r(78,79,8e,f4), r(6b,3e,58,99), r(dd,71,b9,27),\ -+ r(b6,4f,e1,be), r(17,ad,88,f0), r(66,ac,20,c9), r(b4,3a,ce,7d),\ -+ r(18,4a,df,63), r(82,31,1a,e5), r(60,33,51,97), r(45,7f,53,62),\ -+ r(e0,77,64,b1), r(84,ae,6b,bb), r(1c,a0,81,fe), r(94,2b,08,f9),\ -+ r(58,68,48,70), r(19,fd,45,8f), r(87,6c,de,94), r(b7,f8,7b,52),\ -+ r(23,d3,73,ab), r(e2,02,4b,72), r(57,8f,1f,e3), r(2a,ab,55,66),\ -+ r(07,28,eb,b2), r(03,c2,b5,2f), r(9a,7b,c5,86), r(a5,08,37,d3),\ -+ r(f2,87,28,30), r(b2,a5,bf,23), r(ba,6a,03,02), r(5c,82,16,ed),\ -+ r(2b,1c,cf,8a), r(92,b4,79,a7), r(f0,f2,07,f3), r(a1,e2,69,4e),\ -+ r(cd,f4,da,65), r(d5,be,05,06), r(1f,62,34,d1), r(8a,fe,a6,c4),\ -+ r(9d,53,2e,34), r(a0,55,f3,a2), r(32,e1,8a,05), r(75,eb,f6,a4),\ -+ r(39,ec,83,0b), r(aa,ef,60,40), r(06,9f,71,5e), r(51,10,6e,bd),\ -+ r(f9,8a,21,3e), r(3d,06,dd,96), r(ae,05,3e,dd), r(46,bd,e6,4d),\ -+ r(b5,8d,54,91), r(05,5d,c4,71), r(6f,d4,06,04), r(ff,15,50,60),\ -+ r(24,fb,98,19), r(97,e9,bd,d6), r(cc,43,40,89), r(77,9e,d9,67),\ -+ r(bd,42,e8,b0), r(88,8b,89,07), r(38,5b,19,e7), r(db,ee,c8,79),\ -+ r(47,0a,7c,a1), r(e9,0f,42,7c), r(c9,1e,84,f8), r(00,00,00,00),\ -+ r(83,86,80,09), r(48,ed,2b,32), r(ac,70,11,1e), r(4e,72,5a,6c),\ -+ r(fb,ff,0e,fd), r(56,38,85,0f), r(1e,d5,ae,3d), r(27,39,2d,36),\ -+ r(64,d9,0f,0a), r(21,a6,5c,68), r(d1,54,5b,9b), r(3a,2e,36,24),\ -+ r(b1,67,0a,0c), r(0f,e7,57,93), r(d2,96,ee,b4), r(9e,91,9b,1b),\ -+ r(4f,c5,c0,80), r(a2,20,dc,61), r(69,4b,77,5a), r(16,1a,12,1c),\ -+ r(0a,ba,93,e2), r(e5,2a,a0,c0), r(43,e0,22,3c), r(1d,17,1b,12),\ -+ r(0b,0d,09,0e), r(ad,c7,8b,f2), r(b9,a8,b6,2d), r(c8,a9,1e,14),\ -+ r(85,19,f1,57), r(4c,07,75,af), r(bb,dd,99,ee), r(fd,60,7f,a3),\ -+ r(9f,26,01,f7), r(bc,f5,72,5c), r(c5,3b,66,44), r(34,7e,fb,5b),\ -+ r(76,29,43,8b), r(dc,c6,23,cb), r(68,fc,ed,b6), r(63,f1,e4,b8),\ -+ r(ca,dc,31,d7), r(10,85,63,42), r(40,22,97,13), r(20,11,c6,84),\ -+ r(7d,24,4a,85), r(f8,3d,bb,d2), r(11,32,f9,ae), r(6d,a1,29,c7),\ -+ r(4b,2f,9e,1d), r(f3,30,b2,dc), r(ec,52,86,0d), r(d0,e3,c1,77),\ -+ r(6c,16,b3,2b), r(99,b9,70,a9), r(fa,48,94,11), r(22,64,e9,47),\ -+ r(c4,8c,fc,a8), r(1a,3f,f0,a0), r(d8,2c,7d,56), r(ef,90,33,22),\ -+ r(c7,4e,49,87), r(c1,d1,38,d9), r(fe,a2,ca,8c), r(36,0b,d4,98),\ -+ r(cf,81,f5,a6), r(28,de,7a,a5), r(26,8e,b7,da), r(a4,bf,ad,3f),\ -+ r(e4,9d,3a,2c), r(0d,92,78,50), r(9b,cc,5f,6a), r(62,46,7e,54),\ -+ r(c2,13,8d,f6), r(e8,b8,d8,90), r(5e,f7,39,2e), r(f5,af,c3,82),\ -+ r(be,80,5d,9f), r(7c,93,d0,69), r(a9,2d,d5,6f), r(b3,12,25,cf),\ -+ r(3b,99,ac,c8), r(a7,7d,18,10), r(6e,63,9c,e8), r(7b,bb,3b,db),\ -+ r(09,78,26,cd), r(f4,18,59,6e), r(01,b7,9a,ec), r(a8,9a,4f,83),\ -+ r(65,6e,95,e6), r(7e,e6,ff,aa), r(08,cf,bc,21), r(e6,e8,15,ef),\ -+ r(d9,9b,e7,ba), r(ce,36,6f,4a), r(d4,09,9f,ea), r(d6,7c,b0,29),\ -+ r(af,b2,a4,31), r(31,23,3f,2a), r(30,94,a5,c6), r(c0,66,a2,35),\ -+ r(37,bc,4e,74), r(a6,ca,82,fc), r(b0,d0,90,e0), r(15,d8,a7,33),\ -+ r(4a,98,04,f1), r(f7,da,ec,41), r(0e,50,cd,7f), r(2f,f6,91,17),\ -+ r(8d,d6,4d,76), r(4d,b0,ef,43), r(54,4d,aa,cc), r(df,04,96,e4),\ -+ r(e3,b5,d1,9e), r(1b,88,6a,4c), r(b8,1f,2c,c1), r(7f,51,65,46),\ -+ r(04,ea,5e,9d), r(5d,35,8c,01), r(73,74,87,fa), r(2e,41,0b,fb),\ -+ r(5a,1d,67,b3), r(52,d2,db,92), r(33,56,10,e9), r(13,47,d6,6d),\ -+ r(8c,61,d7,9a), r(7a,0c,a1,37), r(8e,14,f8,59), r(89,3c,13,eb),\ -+ r(ee,27,a9,ce), r(35,c9,61,b7), r(ed,e5,1c,e1), r(3c,b1,47,7a),\ -+ r(59,df,d2,9c), r(3f,73,f2,55), r(79,ce,14,18), r(bf,37,c7,73),\ -+ r(ea,cd,f7,53), r(5b,aa,fd,5f), r(14,6f,3d,df), r(86,db,44,78),\ -+ r(81,f3,af,ca), r(3e,c4,68,b9), r(2c,34,24,38), r(5f,40,a3,c2),\ -+ r(72,c3,1d,16), r(0c,25,e2,bc), r(8b,49,3c,28), r(41,95,0d,ff),\ -+ r(71,01,a8,39), r(de,b3,0c,08), r(9c,e4,b4,d8), r(90,c1,56,64),\ -+ r(61,84,cb,7b), r(70,b6,32,d5), r(74,5c,6c,48), r(42,57,b8,d0) -+ -+// generate the required tables in the desired endian format -+ -+#undef r -+#define r r0 -+ -+#if defined(ONE_TABLE) -+static const u_int32_t ft_tab[256] = -+ { f_table }; -+#elif defined(FOUR_TABLES) -+static const u_int32_t ft_tab[4][256] = -+{ { f_table }, -+#undef r -+#define r r1 -+ { f_table }, -+#undef r -+#define r r2 -+ { f_table }, -+#undef r -+#define r r3 -+ { f_table } -+}; -+#endif -+ -+#undef r -+#define r r0 -+#if defined(ONE_TABLE) -+static const u_int32_t it_tab[256] = -+ { i_table }; -+#elif defined(FOUR_TABLES) -+static const u_int32_t it_tab[4][256] = -+{ { i_table }, -+#undef r -+#define r r1 -+ { i_table }, -+#undef r -+#define r r2 -+ { i_table }, -+#undef r -+#define r r3 -+ { i_table } -+}; -+#endif -+ -+#endif -+ -+#if defined(FIXED_TABLES) && (defined(ONE_LR_TABLE) || defined(FOUR_LR_TABLES)) -+ -+// data for inverse tables (last round) -+ -+#define li_table \ -+ w(52), w(09), w(6a), w(d5), w(30), w(36), w(a5), w(38),\ -+ w(bf), w(40), w(a3), w(9e), w(81), w(f3), w(d7), w(fb),\ -+ w(7c), w(e3), w(39), w(82), w(9b), w(2f), w(ff), w(87),\ -+ w(34), w(8e), w(43), w(44), w(c4), w(de), w(e9), w(cb),\ -+ w(54), w(7b), w(94), w(32), w(a6), w(c2), w(23), w(3d),\ -+ w(ee), w(4c), w(95), w(0b), w(42), w(fa), w(c3), w(4e),\ -+ w(08), w(2e), w(a1), w(66), w(28), w(d9), w(24), w(b2),\ -+ w(76), w(5b), w(a2), w(49), w(6d), w(8b), w(d1), w(25),\ -+ w(72), w(f8), w(f6), w(64), w(86), w(68), w(98), w(16),\ -+ w(d4), w(a4), w(5c), w(cc), w(5d), w(65), w(b6), w(92),\ -+ w(6c), w(70), w(48), w(50), w(fd), w(ed), w(b9), w(da),\ -+ w(5e), w(15), w(46), w(57), w(a7), w(8d), w(9d), w(84),\ -+ w(90), w(d8), w(ab), w(00), w(8c), w(bc), w(d3), w(0a),\ -+ w(f7), w(e4), w(58), w(05), w(b8), w(b3), w(45), w(06),\ -+ w(d0), w(2c), w(1e), w(8f), w(ca), w(3f), w(0f), w(02),\ -+ w(c1), w(af), w(bd), w(03), w(01), w(13), w(8a), w(6b),\ -+ w(3a), w(91), w(11), w(41), w(4f), w(67), w(dc), w(ea),\ -+ w(97), w(f2), w(cf), w(ce), w(f0), w(b4), w(e6), w(73),\ -+ w(96), w(ac), w(74), w(22), w(e7), w(ad), w(35), w(85),\ -+ w(e2), w(f9), w(37), w(e8), w(1c), w(75), w(df), w(6e),\ -+ w(47), w(f1), w(1a), w(71), w(1d), w(29), w(c5), w(89),\ -+ w(6f), w(b7), w(62), w(0e), w(aa), w(18), w(be), w(1b),\ -+ w(fc), w(56), w(3e), w(4b), w(c6), w(d2), w(79), w(20),\ -+ w(9a), w(db), w(c0), w(fe), w(78), w(cd), w(5a), w(f4),\ -+ w(1f), w(dd), w(a8), w(33), w(88), w(07), w(c7), w(31),\ -+ w(b1), w(12), w(10), w(59), w(27), w(80), w(ec), w(5f),\ -+ w(60), w(51), w(7f), w(a9), w(19), w(b5), w(4a), w(0d),\ -+ w(2d), w(e5), w(7a), w(9f), w(93), w(c9), w(9c), w(ef),\ -+ w(a0), w(e0), w(3b), w(4d), w(ae), w(2a), w(f5), w(b0),\ -+ w(c8), w(eb), w(bb), w(3c), w(83), w(53), w(99), w(61),\ -+ w(17), w(2b), w(04), w(7e), w(ba), w(77), w(d6), w(26),\ -+ w(e1), w(69), w(14), w(63), w(55), w(21), w(0c), w(7d), -+ -+// generate the required tables in the desired endian format -+ -+#undef r -+#define r(p,q,r,s) w0(q) -+#if defined(ONE_LR_TABLE) -+static const u_int32_t fl_tab[256] = -+ { f_table }; -+#elif defined(FOUR_LR_TABLES) -+static const u_int32_t fl_tab[4][256] = -+{ { f_table }, -+#undef r -+#define r(p,q,r,s) w1(q) -+ { f_table }, -+#undef r -+#define r(p,q,r,s) w2(q) -+ { f_table }, -+#undef r -+#define r(p,q,r,s) w3(q) -+ { f_table } -+}; -+#endif -+ -+#undef w -+#define w w0 -+#if defined(ONE_LR_TABLE) -+static const u_int32_t il_tab[256] = -+ { li_table }; -+#elif defined(FOUR_LR_TABLES) -+static const u_int32_t il_tab[4][256] = -+{ { li_table }, -+#undef w -+#define w w1 -+ { li_table }, -+#undef w -+#define w w2 -+ { li_table }, -+#undef w -+#define w w3 -+ { li_table } -+}; -+#endif -+ -+#endif -+ -+#if defined(FIXED_TABLES) && (defined(ONE_IM_TABLE) || defined(FOUR_IM_TABLES)) -+ -+#define m_table \ -+ r(00,00,00,00), r(0b,0d,09,0e), r(16,1a,12,1c), r(1d,17,1b,12),\ -+ r(2c,34,24,38), r(27,39,2d,36), r(3a,2e,36,24), r(31,23,3f,2a),\ -+ r(58,68,48,70), r(53,65,41,7e), r(4e,72,5a,6c), r(45,7f,53,62),\ -+ r(74,5c,6c,48), r(7f,51,65,46), r(62,46,7e,54), r(69,4b,77,5a),\ -+ r(b0,d0,90,e0), r(bb,dd,99,ee), r(a6,ca,82,fc), r(ad,c7,8b,f2),\ -+ r(9c,e4,b4,d8), r(97,e9,bd,d6), r(8a,fe,a6,c4), r(81,f3,af,ca),\ -+ r(e8,b8,d8,90), r(e3,b5,d1,9e), r(fe,a2,ca,8c), r(f5,af,c3,82),\ -+ r(c4,8c,fc,a8), r(cf,81,f5,a6), r(d2,96,ee,b4), r(d9,9b,e7,ba),\ -+ r(7b,bb,3b,db), r(70,b6,32,d5), r(6d,a1,29,c7), r(66,ac,20,c9),\ -+ r(57,8f,1f,e3), r(5c,82,16,ed), r(41,95,0d,ff), r(4a,98,04,f1),\ -+ r(23,d3,73,ab), r(28,de,7a,a5), r(35,c9,61,b7), r(3e,c4,68,b9),\ -+ r(0f,e7,57,93), r(04,ea,5e,9d), r(19,fd,45,8f), r(12,f0,4c,81),\ -+ r(cb,6b,ab,3b), r(c0,66,a2,35), r(dd,71,b9,27), r(d6,7c,b0,29),\ -+ r(e7,5f,8f,03), r(ec,52,86,0d), r(f1,45,9d,1f), r(fa,48,94,11),\ -+ r(93,03,e3,4b), r(98,0e,ea,45), r(85,19,f1,57), r(8e,14,f8,59),\ -+ r(bf,37,c7,73), r(b4,3a,ce,7d), r(a9,2d,d5,6f), r(a2,20,dc,61),\ -+ r(f6,6d,76,ad), r(fd,60,7f,a3), r(e0,77,64,b1), r(eb,7a,6d,bf),\ -+ r(da,59,52,95), r(d1,54,5b,9b), r(cc,43,40,89), r(c7,4e,49,87),\ -+ r(ae,05,3e,dd), r(a5,08,37,d3), r(b8,1f,2c,c1), r(b3,12,25,cf),\ -+ r(82,31,1a,e5), r(89,3c,13,eb), r(94,2b,08,f9), r(9f,26,01,f7),\ -+ r(46,bd,e6,4d), r(4d,b0,ef,43), r(50,a7,f4,51), r(5b,aa,fd,5f),\ -+ r(6a,89,c2,75), r(61,84,cb,7b), r(7c,93,d0,69), r(77,9e,d9,67),\ -+ r(1e,d5,ae,3d), r(15,d8,a7,33), r(08,cf,bc,21), r(03,c2,b5,2f),\ -+ r(32,e1,8a,05), r(39,ec,83,0b), r(24,fb,98,19), r(2f,f6,91,17),\ -+ r(8d,d6,4d,76), r(86,db,44,78), r(9b,cc,5f,6a), r(90,c1,56,64),\ -+ r(a1,e2,69,4e), r(aa,ef,60,40), r(b7,f8,7b,52), r(bc,f5,72,5c),\ -+ r(d5,be,05,06), r(de,b3,0c,08), r(c3,a4,17,1a), r(c8,a9,1e,14),\ -+ r(f9,8a,21,3e), r(f2,87,28,30), r(ef,90,33,22), r(e4,9d,3a,2c),\ -+ r(3d,06,dd,96), r(36,0b,d4,98), r(2b,1c,cf,8a), r(20,11,c6,84),\ -+ r(11,32,f9,ae), r(1a,3f,f0,a0), r(07,28,eb,b2), r(0c,25,e2,bc),\ -+ r(65,6e,95,e6), r(6e,63,9c,e8), r(73,74,87,fa), r(78,79,8e,f4),\ -+ r(49,5a,b1,de), r(42,57,b8,d0), r(5f,40,a3,c2), r(54,4d,aa,cc),\ -+ r(f7,da,ec,41), r(fc,d7,e5,4f), r(e1,c0,fe,5d), r(ea,cd,f7,53),\ -+ r(db,ee,c8,79), r(d0,e3,c1,77), r(cd,f4,da,65), r(c6,f9,d3,6b),\ -+ r(af,b2,a4,31), r(a4,bf,ad,3f), r(b9,a8,b6,2d), r(b2,a5,bf,23),\ -+ r(83,86,80,09), r(88,8b,89,07), r(95,9c,92,15), r(9e,91,9b,1b),\ -+ r(47,0a,7c,a1), r(4c,07,75,af), r(51,10,6e,bd), r(5a,1d,67,b3),\ -+ r(6b,3e,58,99), r(60,33,51,97), r(7d,24,4a,85), r(76,29,43,8b),\ -+ r(1f,62,34,d1), r(14,6f,3d,df), r(09,78,26,cd), r(02,75,2f,c3),\ -+ r(33,56,10,e9), r(38,5b,19,e7), r(25,4c,02,f5), r(2e,41,0b,fb),\ -+ r(8c,61,d7,9a), r(87,6c,de,94), r(9a,7b,c5,86), r(91,76,cc,88),\ -+ r(a0,55,f3,a2), r(ab,58,fa,ac), r(b6,4f,e1,be), r(bd,42,e8,b0),\ -+ r(d4,09,9f,ea), r(df,04,96,e4), r(c2,13,8d,f6), r(c9,1e,84,f8),\ -+ r(f8,3d,bb,d2), r(f3,30,b2,dc), r(ee,27,a9,ce), r(e5,2a,a0,c0),\ -+ r(3c,b1,47,7a), r(37,bc,4e,74), r(2a,ab,55,66), r(21,a6,5c,68),\ -+ r(10,85,63,42), r(1b,88,6a,4c), r(06,9f,71,5e), r(0d,92,78,50),\ -+ r(64,d9,0f,0a), r(6f,d4,06,04), r(72,c3,1d,16), r(79,ce,14,18),\ -+ r(48,ed,2b,32), r(43,e0,22,3c), r(5e,f7,39,2e), r(55,fa,30,20),\ -+ r(01,b7,9a,ec), r(0a,ba,93,e2), r(17,ad,88,f0), r(1c,a0,81,fe),\ -+ r(2d,83,be,d4), r(26,8e,b7,da), r(3b,99,ac,c8), r(30,94,a5,c6),\ -+ r(59,df,d2,9c), r(52,d2,db,92), r(4f,c5,c0,80), r(44,c8,c9,8e),\ -+ r(75,eb,f6,a4), r(7e,e6,ff,aa), r(63,f1,e4,b8), r(68,fc,ed,b6),\ -+ r(b1,67,0a,0c), r(ba,6a,03,02), r(a7,7d,18,10), r(ac,70,11,1e),\ -+ r(9d,53,2e,34), r(96,5e,27,3a), r(8b,49,3c,28), r(80,44,35,26),\ -+ r(e9,0f,42,7c), r(e2,02,4b,72), r(ff,15,50,60), r(f4,18,59,6e),\ -+ r(c5,3b,66,44), r(ce,36,6f,4a), r(d3,21,74,58), r(d8,2c,7d,56),\ -+ r(7a,0c,a1,37), r(71,01,a8,39), r(6c,16,b3,2b), r(67,1b,ba,25),\ -+ r(56,38,85,0f), r(5d,35,8c,01), r(40,22,97,13), r(4b,2f,9e,1d),\ -+ r(22,64,e9,47), r(29,69,e0,49), r(34,7e,fb,5b), r(3f,73,f2,55),\ -+ r(0e,50,cd,7f), r(05,5d,c4,71), r(18,4a,df,63), r(13,47,d6,6d),\ -+ r(ca,dc,31,d7), r(c1,d1,38,d9), r(dc,c6,23,cb), r(d7,cb,2a,c5),\ -+ r(e6,e8,15,ef), r(ed,e5,1c,e1), r(f0,f2,07,f3), r(fb,ff,0e,fd),\ -+ r(92,b4,79,a7), r(99,b9,70,a9), r(84,ae,6b,bb), r(8f,a3,62,b5),\ -+ r(be,80,5d,9f), r(b5,8d,54,91), r(a8,9a,4f,83), r(a3,97,46,8d) -+ -+#undef r -+#define r r0 -+ -+#if defined(ONE_IM_TABLE) -+static const u_int32_t im_tab[256] = -+ { m_table }; -+#elif defined(FOUR_IM_TABLES) -+static const u_int32_t im_tab[4][256] = -+{ { m_table }, -+#undef r -+#define r r1 -+ { m_table }, -+#undef r -+#define r r2 -+ { m_table }, -+#undef r -+#define r r3 -+ { m_table } -+}; -+#endif -+ -+#endif -+ -+#else -+ -+static int tab_gen = 0; -+ -+static unsigned char s_box[256]; // the S box -+static unsigned char inv_s_box[256]; // the inverse S box -+static u_int32_t rcon_tab[AES_RC_LENGTH]; // table of round constants -+ -+#if defined(ONE_TABLE) -+static u_int32_t ft_tab[256]; -+static u_int32_t it_tab[256]; -+#elif defined(FOUR_TABLES) -+static u_int32_t ft_tab[4][256]; -+static u_int32_t it_tab[4][256]; -+#endif -+ -+#if defined(ONE_LR_TABLE) -+static u_int32_t fl_tab[256]; -+static u_int32_t il_tab[256]; -+#elif defined(FOUR_LR_TABLES) -+static u_int32_t fl_tab[4][256]; -+static u_int32_t il_tab[4][256]; -+#endif -+ -+#if defined(ONE_IM_TABLE) -+static u_int32_t im_tab[256]; -+#elif defined(FOUR_IM_TABLES) -+static u_int32_t im_tab[4][256]; -+#endif -+ -+// Generate the tables for the dynamic table option -+ -+#if !defined(FF_TABLES) -+ -+// It will generally be sensible to use tables to compute finite -+// field multiplies and inverses but where memory is scarse this -+// code might sometimes be better. -+ -+// return 2 ^ (n - 1) where n is the bit number of the highest bit -+// set in x with x in the range 1 < x < 0x00000200. This form is -+// used so that locals within FFinv can be bytes rather than words -+ -+static unsigned char hibit(const u_int32_t x) -+{ unsigned char r = (unsigned char)((x >> 1) | (x >> 2)); -+ -+ r |= (r >> 2); -+ r |= (r >> 4); -+ return (r + 1) >> 1; -+} -+ -+// return the inverse of the finite field element x -+ -+static unsigned char FFinv(const unsigned char x) -+{ unsigned char p1 = x, p2 = 0x1b, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; -+ -+ if(x < 2) return x; -+ -+ for(;;) -+ { -+ if(!n1) return v1; -+ -+ while(n2 >= n1) -+ { -+ n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2); -+ } -+ -+ if(!n2) return v2; -+ -+ while(n1 >= n2) -+ { -+ n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1); -+ } -+ } -+} -+ -+// define the finite field multiplies required for Rijndael -+ -+#define FFmul02(x) ((((x) & 0x7f) << 1) ^ ((x) & 0x80 ? 0x1b : 0)) -+#define FFmul03(x) ((x) ^ FFmul02(x)) -+#define FFmul09(x) ((x) ^ FFmul02(FFmul02(FFmul02(x)))) -+#define FFmul0b(x) ((x) ^ FFmul02((x) ^ FFmul02(FFmul02(x)))) -+#define FFmul0d(x) ((x) ^ FFmul02(FFmul02((x) ^ FFmul02(x)))) -+#define FFmul0e(x) FFmul02((x) ^ FFmul02((x) ^ FFmul02(x))) -+ -+#else -+ -+#define FFinv(x) ((x) ? pow[255 - log[x]]: 0) -+ -+#define FFmul02(x) (x ? pow[log[x] + 0x19] : 0) -+#define FFmul03(x) (x ? pow[log[x] + 0x01] : 0) -+#define FFmul09(x) (x ? pow[log[x] + 0xc7] : 0) -+#define FFmul0b(x) (x ? pow[log[x] + 0x68] : 0) -+#define FFmul0d(x) (x ? pow[log[x] + 0xee] : 0) -+#define FFmul0e(x) (x ? pow[log[x] + 0xdf] : 0) -+ -+#endif -+ -+// The forward and inverse affine transformations used in the S-box -+ -+#define fwd_affine(x) \ -+ (w = (u_int32_t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(unsigned char)(w^(w>>8))) -+ -+#define inv_affine(x) \ -+ (w = (u_int32_t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(unsigned char)(w^(w>>8))) -+ -+static void gen_tabs(void) -+{ u_int32_t i, w; -+ -+#if defined(FF_TABLES) -+ -+ unsigned char pow[512], log[256]; -+ -+ // log and power tables for GF(2^8) finite field with -+ // 0x011b as modular polynomial - the simplest primitive -+ // root is 0x03, used here to generate the tables -+ -+ i = 0; w = 1; -+ do -+ { -+ pow[i] = (unsigned char)w; -+ pow[i + 255] = (unsigned char)w; -+ log[w] = (unsigned char)i++; -+ w ^= (w << 1) ^ (w & ff_hi ? ff_poly : 0); -+ } -+ while (w != 1); -+ -+#endif -+ -+ for(i = 0, w = 1; i < AES_RC_LENGTH; ++i) -+ { -+ rcon_tab[i] = bytes2word(w, 0, 0, 0); -+ w = (w << 1) ^ (w & ff_hi ? ff_poly : 0); -+ } -+ -+ for(i = 0; i < 256; ++i) -+ { unsigned char b; -+ -+ s_box[i] = b = fwd_affine(FFinv((unsigned char)i)); -+ -+ w = bytes2word(b, 0, 0, 0); -+#if defined(ONE_LR_TABLE) -+ fl_tab[i] = w; -+#elif defined(FOUR_LR_TABLES) -+ fl_tab[0][i] = w; -+ fl_tab[1][i] = upr(w,1); -+ fl_tab[2][i] = upr(w,2); -+ fl_tab[3][i] = upr(w,3); -+#endif -+ w = bytes2word(FFmul02(b), b, b, FFmul03(b)); -+#if defined(ONE_TABLE) -+ ft_tab[i] = w; -+#elif defined(FOUR_TABLES) -+ ft_tab[0][i] = w; -+ ft_tab[1][i] = upr(w,1); -+ ft_tab[2][i] = upr(w,2); -+ ft_tab[3][i] = upr(w,3); -+#endif -+ inv_s_box[i] = b = FFinv(inv_affine((unsigned char)i)); -+ -+ w = bytes2word(b, 0, 0, 0); -+#if defined(ONE_LR_TABLE) -+ il_tab[i] = w; -+#elif defined(FOUR_LR_TABLES) -+ il_tab[0][i] = w; -+ il_tab[1][i] = upr(w,1); -+ il_tab[2][i] = upr(w,2); -+ il_tab[3][i] = upr(w,3); -+#endif -+ w = bytes2word(FFmul0e(b), FFmul09(b), FFmul0d(b), FFmul0b(b)); -+#if defined(ONE_TABLE) -+ it_tab[i] = w; -+#elif defined(FOUR_TABLES) -+ it_tab[0][i] = w; -+ it_tab[1][i] = upr(w,1); -+ it_tab[2][i] = upr(w,2); -+ it_tab[3][i] = upr(w,3); -+#endif -+#if defined(ONE_IM_TABLE) -+ im_tab[b] = w; -+#elif defined(FOUR_IM_TABLES) -+ im_tab[0][b] = w; -+ im_tab[1][b] = upr(w,1); -+ im_tab[2][b] = upr(w,2); -+ im_tab[3][b] = upr(w,3); -+#endif -+ -+ } -+} -+ -+#endif -+ -+#define no_table(x,box,vf,rf,c) bytes2word( \ -+ box[bval(vf(x,0,c),rf(0,c))], \ -+ box[bval(vf(x,1,c),rf(1,c))], \ -+ box[bval(vf(x,2,c),rf(2,c))], \ -+ box[bval(vf(x,3,c),rf(3,c))]) -+ -+#define one_table(x,op,tab,vf,rf,c) \ -+ ( tab[bval(vf(x,0,c),rf(0,c))] \ -+ ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \ -+ ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \ -+ ^ op(tab[bval(vf(x,3,c),rf(3,c))],3)) -+ -+#define four_tables(x,tab,vf,rf,c) \ -+ ( tab[0][bval(vf(x,0,c),rf(0,c))] \ -+ ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ -+ ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ -+ ^ tab[3][bval(vf(x,3,c),rf(3,c))]) -+ -+#define vf1(x,r,c) (x) -+#define rf1(r,c) (r) -+#define rf2(r,c) ((r-c)&3) -+ -+#if defined(FOUR_LR_TABLES) -+#define ls_box(x,c) four_tables(x,fl_tab,vf1,rf2,c) -+#elif defined(ONE_LR_TABLE) -+#define ls_box(x,c) one_table(x,upr,fl_tab,vf1,rf2,c) -+#else -+#define ls_box(x,c) no_table(x,s_box,vf1,rf2,c) -+#endif -+ -+#if defined(FOUR_IM_TABLES) -+#define inv_mcol(x) four_tables(x,im_tab,vf1,rf1,0) -+#elif defined(ONE_IM_TABLE) -+#define inv_mcol(x) one_table(x,upr,im_tab,vf1,rf1,0) -+#else -+#define inv_mcol(x) \ -+ (f9 = (x),f2 = FFmulX(f9), f4 = FFmulX(f2), f8 = FFmulX(f4), f9 ^= f8, \ -+ f2 ^= f4 ^ f8 ^ upr(f2 ^ f9,3) ^ upr(f4 ^ f9,2) ^ upr(f9,1)) -+#endif -+ -+// Subroutine to set the block size (if variable) in bytes, legal -+// values being 16, 24 and 32. -+ -+#if defined(AES_BLOCK_SIZE) -+#define nc (AES_BLOCK_SIZE / 4) -+#else -+#define nc (cx->aes_Ncol) -+ -+void aes_set_blk(aes_context *cx, int n_bytes) -+{ -+#if !defined(FIXED_TABLES) -+ if(!tab_gen) { gen_tabs(); tab_gen = 1; } -+#endif -+ -+ switch(n_bytes) { -+ case 32: /* bytes */ -+ case 256: /* bits */ -+ nc = 8; -+ break; -+ case 24: /* bytes */ -+ case 192: /* bits */ -+ nc = 6; -+ break; -+ case 16: /* bytes */ -+ case 128: /* bits */ -+ default: -+ nc = 4; -+ break; -+ } -+} -+ -+#endif -+ -+// Initialise the key schedule from the user supplied key. The key -+// length is now specified in bytes - 16, 24 or 32 as appropriate. -+// This corresponds to bit lengths of 128, 192 and 256 bits, and -+// to Nk values of 4, 6 and 8 respectively. -+ -+#define mx(t,f) (*t++ = inv_mcol(*f),f++) -+#define cp(t,f) *t++ = *f++ -+ -+#if AES_BLOCK_SIZE == 16 -+#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s) -+#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s) -+#elif AES_BLOCK_SIZE == 24 -+#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ -+ cp(d,s); cp(d,s) -+#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ -+ mx(d,s); mx(d,s) -+#elif AES_BLOCK_SIZE == 32 -+#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ -+ cp(d,s); cp(d,s); cp(d,s); cp(d,s) -+#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ -+ mx(d,s); mx(d,s); mx(d,s); mx(d,s) -+#else -+ -+#define cpy(d,s) \ -+switch(nc) \ -+{ case 8: cp(d,s); cp(d,s); \ -+ case 6: cp(d,s); cp(d,s); \ -+ case 4: cp(d,s); cp(d,s); \ -+ cp(d,s); cp(d,s); \ -+} -+ -+#define mix(d,s) \ -+switch(nc) \ -+{ case 8: mx(d,s); mx(d,s); \ -+ case 6: mx(d,s); mx(d,s); \ -+ case 4: mx(d,s); mx(d,s); \ -+ mx(d,s); mx(d,s); \ -+} -+ -+#endif -+ -+void aes_set_key(aes_context *cx, const unsigned char in_key[], int n_bytes, const int f) -+{ u_int32_t *kf, *kt, rci; -+ -+#if !defined(FIXED_TABLES) -+ if(!tab_gen) { gen_tabs(); tab_gen = 1; } -+#endif -+ -+ switch(n_bytes) { -+ case 32: /* bytes */ -+ case 256: /* bits */ -+ cx->aes_Nkey = 8; -+ break; -+ case 24: /* bytes */ -+ case 192: /* bits */ -+ cx->aes_Nkey = 6; -+ break; -+ case 16: /* bytes */ -+ case 128: /* bits */ -+ default: -+ cx->aes_Nkey = 4; -+ break; -+ } -+ -+ cx->aes_Nrnd = (cx->aes_Nkey > nc ? cx->aes_Nkey : nc) + 6; -+ -+ cx->aes_e_key[0] = const_word_in(in_key ); -+ cx->aes_e_key[1] = const_word_in(in_key + 4); -+ cx->aes_e_key[2] = const_word_in(in_key + 8); -+ cx->aes_e_key[3] = const_word_in(in_key + 12); -+ -+ kf = cx->aes_e_key; -+ kt = kf + nc * (cx->aes_Nrnd + 1) - cx->aes_Nkey; -+ rci = 0; -+ -+ switch(cx->aes_Nkey) -+ { -+ case 4: do -+ { kf[4] = kf[0] ^ ls_box(kf[3],3) ^ rcon_tab[rci++]; -+ kf[5] = kf[1] ^ kf[4]; -+ kf[6] = kf[2] ^ kf[5]; -+ kf[7] = kf[3] ^ kf[6]; -+ kf += 4; -+ } -+ while(kf < kt); -+ break; -+ -+ case 6: cx->aes_e_key[4] = const_word_in(in_key + 16); -+ cx->aes_e_key[5] = const_word_in(in_key + 20); -+ do -+ { kf[ 6] = kf[0] ^ ls_box(kf[5],3) ^ rcon_tab[rci++]; -+ kf[ 7] = kf[1] ^ kf[ 6]; -+ kf[ 8] = kf[2] ^ kf[ 7]; -+ kf[ 9] = kf[3] ^ kf[ 8]; -+ kf[10] = kf[4] ^ kf[ 9]; -+ kf[11] = kf[5] ^ kf[10]; -+ kf += 6; -+ } -+ while(kf < kt); -+ break; -+ -+ case 8: cx->aes_e_key[4] = const_word_in(in_key + 16); -+ cx->aes_e_key[5] = const_word_in(in_key + 20); -+ cx->aes_e_key[6] = const_word_in(in_key + 24); -+ cx->aes_e_key[7] = const_word_in(in_key + 28); -+ do -+ { kf[ 8] = kf[0] ^ ls_box(kf[7],3) ^ rcon_tab[rci++]; -+ kf[ 9] = kf[1] ^ kf[ 8]; -+ kf[10] = kf[2] ^ kf[ 9]; -+ kf[11] = kf[3] ^ kf[10]; -+ kf[12] = kf[4] ^ ls_box(kf[11],0); -+ kf[13] = kf[5] ^ kf[12]; -+ kf[14] = kf[6] ^ kf[13]; -+ kf[15] = kf[7] ^ kf[14]; -+ kf += 8; -+ } -+ while (kf < kt); -+ break; -+ } -+ -+ if(!f) -+ { u_int32_t i; -+ -+ kt = cx->aes_d_key + nc * cx->aes_Nrnd; -+ kf = cx->aes_e_key; -+ -+ cpy(kt, kf); kt -= 2 * nc; -+ -+ for(i = 1; i < cx->aes_Nrnd; ++i) -+ { -+#if defined(ONE_TABLE) || defined(FOUR_TABLES) -+#if !defined(ONE_IM_TABLE) && !defined(FOUR_IM_TABLES) -+ u_int32_t f2, f4, f8, f9; -+#endif -+ mix(kt, kf); -+#else -+ cpy(kt, kf); -+#endif -+ kt -= 2 * nc; -+ } -+ -+ cpy(kt, kf); -+ } -+} -+ -+// y = output word, x = input word, r = row, c = column -+// for r = 0, 1, 2 and 3 = column accessed for row r -+ -+#if defined(ARRAYS) -+#define s(x,c) x[c] -+#else -+#define s(x,c) x##c -+#endif -+ -+// I am grateful to Frank Yellin for the following constructions -+// which, given the column (c) of the output state variable that -+// is being computed, return the input state variables which are -+// needed for each row (r) of the state -+ -+// For the fixed block size options, compilers reduce these two -+// expressions to fixed variable references. For variable block -+// size code conditional clauses will sometimes be returned -+ -+#define unused 77 // Sunset Strip -+ -+#define fwd_var(x,r,c) \ -+ ( r==0 ? \ -+ ( c==0 ? s(x,0) \ -+ : c==1 ? s(x,1) \ -+ : c==2 ? s(x,2) \ -+ : c==3 ? s(x,3) \ -+ : c==4 ? s(x,4) \ -+ : c==5 ? s(x,5) \ -+ : c==6 ? s(x,6) \ -+ : s(x,7)) \ -+ : r==1 ? \ -+ ( c==0 ? s(x,1) \ -+ : c==1 ? s(x,2) \ -+ : c==2 ? s(x,3) \ -+ : c==3 ? nc==4 ? s(x,0) : s(x,4) \ -+ : c==4 ? s(x,5) \ -+ : c==5 ? nc==8 ? s(x,6) : s(x,0) \ -+ : c==6 ? s(x,7) \ -+ : s(x,0)) \ -+ : r==2 ? \ -+ ( c==0 ? nc==8 ? s(x,3) : s(x,2) \ -+ : c==1 ? nc==8 ? s(x,4) : s(x,3) \ -+ : c==2 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \ -+ : c==3 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \ -+ : c==4 ? nc==8 ? s(x,7) : s(x,0) \ -+ : c==5 ? nc==8 ? s(x,0) : s(x,1) \ -+ : c==6 ? s(x,1) \ -+ : s(x,2)) \ -+ : \ -+ ( c==0 ? nc==8 ? s(x,4) : s(x,3) \ -+ : c==1 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \ -+ : c==2 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \ -+ : c==3 ? nc==4 ? s(x,2) : nc==8 ? s(x,7) : s(x,0) \ -+ : c==4 ? nc==8 ? s(x,0) : s(x,1) \ -+ : c==5 ? nc==8 ? s(x,1) : s(x,2) \ -+ : c==6 ? s(x,2) \ -+ : s(x,3))) -+ -+#define inv_var(x,r,c) \ -+ ( r==0 ? \ -+ ( c==0 ? s(x,0) \ -+ : c==1 ? s(x,1) \ -+ : c==2 ? s(x,2) \ -+ : c==3 ? s(x,3) \ -+ : c==4 ? s(x,4) \ -+ : c==5 ? s(x,5) \ -+ : c==6 ? s(x,6) \ -+ : s(x,7)) \ -+ : r==1 ? \ -+ ( c==0 ? nc==4 ? s(x,3) : nc==8 ? s(x,7) : s(x,5) \ -+ : c==1 ? s(x,0) \ -+ : c==2 ? s(x,1) \ -+ : c==3 ? s(x,2) \ -+ : c==4 ? s(x,3) \ -+ : c==5 ? s(x,4) \ -+ : c==6 ? s(x,5) \ -+ : s(x,6)) \ -+ : r==2 ? \ -+ ( c==0 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \ -+ : c==1 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \ -+ : c==2 ? nc==8 ? s(x,7) : s(x,0) \ -+ : c==3 ? nc==8 ? s(x,0) : s(x,1) \ -+ : c==4 ? nc==8 ? s(x,1) : s(x,2) \ -+ : c==5 ? nc==8 ? s(x,2) : s(x,3) \ -+ : c==6 ? s(x,3) \ -+ : s(x,4)) \ -+ : \ -+ ( c==0 ? nc==4 ? s(x,1) : nc==8 ? s(x,4) : s(x,3) \ -+ : c==1 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \ -+ : c==2 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \ -+ : c==3 ? nc==8 ? s(x,7) : s(x,0) \ -+ : c==4 ? nc==8 ? s(x,0) : s(x,1) \ -+ : c==5 ? nc==8 ? s(x,1) : s(x,2) \ -+ : c==6 ? s(x,2) \ -+ : s(x,3))) -+ -+#define si(y,x,k,c) s(y,c) = const_word_in(x + 4 * c) ^ k[c] -+#define so(y,x,c) word_out(y + 4 * c, s(x,c)) -+ -+#if defined(FOUR_TABLES) -+#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,ft_tab,fwd_var,rf1,c) -+#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,it_tab,inv_var,rf1,c) -+#elif defined(ONE_TABLE) -+#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,ft_tab,fwd_var,rf1,c) -+#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,it_tab,inv_var,rf1,c) -+#else -+#define fwd_rnd(y,x,k,c) s(y,c) = fwd_mcol(no_table(x,s_box,fwd_var,rf1,c)) ^ (k)[c] -+#define inv_rnd(y,x,k,c) s(y,c) = inv_mcol(no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c]) -+#endif -+ -+#if defined(FOUR_LR_TABLES) -+#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,fl_tab,fwd_var,rf1,c) -+#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,il_tab,inv_var,rf1,c) -+#elif defined(ONE_LR_TABLE) -+#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,fl_tab,fwd_var,rf1,c) -+#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,il_tab,inv_var,rf1,c) -+#else -+#define fwd_lrnd(y,x,k,c) s(y,c) = no_table(x,s_box,fwd_var,rf1,c) ^ (k)[c] -+#define inv_lrnd(y,x,k,c) s(y,c) = no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c] -+#endif -+ -+#if AES_BLOCK_SIZE == 16 -+ -+#if defined(ARRAYS) -+#define locals(y,x) x[4],y[4] -+#else -+#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 -+// the following defines prevent the compiler requiring the declaration -+// of generated but unused variables in the fwd_var and inv_var macros -+#define b04 unused -+#define b05 unused -+#define b06 unused -+#define b07 unused -+#define b14 unused -+#define b15 unused -+#define b16 unused -+#define b17 unused -+#endif -+#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ -+ s(y,2) = s(x,2); s(y,3) = s(x,3); -+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) -+#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) -+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) -+ -+#elif AES_BLOCK_SIZE == 24 -+ -+#if defined(ARRAYS) -+#define locals(y,x) x[6],y[6] -+#else -+#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5, \ -+ y##0,y##1,y##2,y##3,y##4,y##5 -+#define b06 unused -+#define b07 unused -+#define b16 unused -+#define b17 unused -+#endif -+#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ -+ s(y,2) = s(x,2); s(y,3) = s(x,3); \ -+ s(y,4) = s(x,4); s(y,5) = s(x,5); -+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \ -+ si(y,x,k,3); si(y,x,k,4); si(y,x,k,5) -+#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); \ -+ so(y,x,3); so(y,x,4); so(y,x,5) -+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \ -+ rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5) -+#else -+ -+#if defined(ARRAYS) -+#define locals(y,x) x[8],y[8] -+#else -+#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5,x##6,x##7, \ -+ y##0,y##1,y##2,y##3,y##4,y##5,y##6,y##7 -+#endif -+#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ -+ s(y,2) = s(x,2); s(y,3) = s(x,3); \ -+ s(y,4) = s(x,4); s(y,5) = s(x,5); \ -+ s(y,6) = s(x,6); s(y,7) = s(x,7); -+ -+#if AES_BLOCK_SIZE == 32 -+ -+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); \ -+ si(y,x,k,4); si(y,x,k,5); si(y,x,k,6); si(y,x,k,7) -+#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); \ -+ so(y,x,4); so(y,x,5); so(y,x,6); so(y,x,7) -+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \ -+ rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7) -+#else -+ -+#define state_in(y,x,k) \ -+switch(nc) \ -+{ case 8: si(y,x,k,7); si(y,x,k,6); \ -+ case 6: si(y,x,k,5); si(y,x,k,4); \ -+ case 4: si(y,x,k,3); si(y,x,k,2); \ -+ si(y,x,k,1); si(y,x,k,0); \ -+} -+ -+#define state_out(y,x) \ -+switch(nc) \ -+{ case 8: so(y,x,7); so(y,x,6); \ -+ case 6: so(y,x,5); so(y,x,4); \ -+ case 4: so(y,x,3); so(y,x,2); \ -+ so(y,x,1); so(y,x,0); \ -+} -+ -+#if defined(FAST_VARIABLE) -+ -+#define round(rm,y,x,k) \ -+switch(nc) \ -+{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ -+ rm(y,x,k,5); rm(y,x,k,4); \ -+ rm(y,x,k,3); rm(y,x,k,2); \ -+ rm(y,x,k,1); rm(y,x,k,0); \ -+ break; \ -+ case 6: rm(y,x,k,5); rm(y,x,k,4); \ -+ rm(y,x,k,3); rm(y,x,k,2); \ -+ rm(y,x,k,1); rm(y,x,k,0); \ -+ break; \ -+ case 4: rm(y,x,k,3); rm(y,x,k,2); \ -+ rm(y,x,k,1); rm(y,x,k,0); \ -+ break; \ -+} -+#else -+ -+#define round(rm,y,x,k) \ -+switch(nc) \ -+{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ -+ case 6: rm(y,x,k,5); rm(y,x,k,4); \ -+ case 4: rm(y,x,k,3); rm(y,x,k,2); \ -+ rm(y,x,k,1); rm(y,x,k,0); \ -+} -+ -+#endif -+ -+#endif -+#endif -+ -+void aes_encrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) -+{ u_int32_t locals(b0, b1); -+ const u_int32_t *kp = cx->aes_e_key; -+ -+#if !defined(ONE_TABLE) && !defined(FOUR_TABLES) -+ u_int32_t f2; -+#endif -+ -+ state_in(b0, in_blk, kp); kp += nc; -+ -+#if defined(UNROLL) -+ -+ switch(cx->aes_Nrnd) -+ { -+ case 14: round(fwd_rnd, b1, b0, kp ); -+ round(fwd_rnd, b0, b1, kp + nc ); kp += 2 * nc; -+ case 12: round(fwd_rnd, b1, b0, kp ); -+ round(fwd_rnd, b0, b1, kp + nc ); kp += 2 * nc; -+ case 10: round(fwd_rnd, b1, b0, kp ); -+ round(fwd_rnd, b0, b1, kp + nc); -+ round(fwd_rnd, b1, b0, kp + 2 * nc); -+ round(fwd_rnd, b0, b1, kp + 3 * nc); -+ round(fwd_rnd, b1, b0, kp + 4 * nc); -+ round(fwd_rnd, b0, b1, kp + 5 * nc); -+ round(fwd_rnd, b1, b0, kp + 6 * nc); -+ round(fwd_rnd, b0, b1, kp + 7 * nc); -+ round(fwd_rnd, b1, b0, kp + 8 * nc); -+ round(fwd_lrnd, b0, b1, kp + 9 * nc); -+ } -+ -+#elif defined(PARTIAL_UNROLL) -+ { u_int32_t rnd; -+ -+ for(rnd = 0; rnd < (cx->aes_Nrnd >> 1) - 1; ++rnd) -+ { -+ round(fwd_rnd, b1, b0, kp); -+ round(fwd_rnd, b0, b1, kp + nc); kp += 2 * nc; -+ } -+ -+ round(fwd_rnd, b1, b0, kp); -+ round(fwd_lrnd, b0, b1, kp + nc); -+ } -+#else -+ { u_int32_t rnd; -+ -+ for(rnd = 0; rnd < cx->aes_Nrnd - 1; ++rnd) -+ { -+ round(fwd_rnd, b1, b0, kp); -+ l_copy(b0, b1); kp += nc; -+ } -+ -+ round(fwd_lrnd, b0, b1, kp); -+ } -+#endif -+ -+ state_out(out_blk, b0); -+} -+ -+void aes_decrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) -+{ u_int32_t locals(b0, b1); -+ const u_int32_t *kp = cx->aes_d_key; -+ -+#if !defined(ONE_TABLE) && !defined(FOUR_TABLES) -+ u_int32_t f2, f4, f8, f9; -+#endif -+ -+ state_in(b0, in_blk, kp); kp += nc; -+ -+#if defined(UNROLL) -+ -+ switch(cx->aes_Nrnd) -+ { -+ case 14: round(inv_rnd, b1, b0, kp ); -+ round(inv_rnd, b0, b1, kp + nc ); kp += 2 * nc; -+ case 12: round(inv_rnd, b1, b0, kp ); -+ round(inv_rnd, b0, b1, kp + nc ); kp += 2 * nc; -+ case 10: round(inv_rnd, b1, b0, kp ); -+ round(inv_rnd, b0, b1, kp + nc); -+ round(inv_rnd, b1, b0, kp + 2 * nc); -+ round(inv_rnd, b0, b1, kp + 3 * nc); -+ round(inv_rnd, b1, b0, kp + 4 * nc); -+ round(inv_rnd, b0, b1, kp + 5 * nc); -+ round(inv_rnd, b1, b0, kp + 6 * nc); -+ round(inv_rnd, b0, b1, kp + 7 * nc); -+ round(inv_rnd, b1, b0, kp + 8 * nc); -+ round(inv_lrnd, b0, b1, kp + 9 * nc); -+ } -+ -+#elif defined(PARTIAL_UNROLL) -+ { u_int32_t rnd; -+ -+ for(rnd = 0; rnd < (cx->aes_Nrnd >> 1) - 1; ++rnd) -+ { -+ round(inv_rnd, b1, b0, kp); -+ round(inv_rnd, b0, b1, kp + nc); kp += 2 * nc; -+ } -+ -+ round(inv_rnd, b1, b0, kp); -+ round(inv_lrnd, b0, b1, kp + nc); -+ } -+#else -+ { u_int32_t rnd; -+ -+ for(rnd = 0; rnd < cx->aes_Nrnd - 1; ++rnd) -+ { -+ round(inv_rnd, b1, b0, kp); -+ l_copy(b0, b1); kp += nc; -+ } -+ -+ round(inv_lrnd, b0, b1, kp); -+ } -+#endif -+ -+ state_out(out_blk, b0); -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/aes/aes_cbc.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,43 @@ -+/* -+// I retain copyright in this code but I encourage its free use provided -+// that I don't carry any responsibility for the results. I am especially -+// happy to see it used in free and open source software. If you do use -+// it I would appreciate an acknowledgement of its origin in the code or -+// the product that results and I would also appreciate knowing a little -+// about the use to which it is being put. I am grateful to Frank Yellin -+// for some ideas that are used in this implementation. -+// -+// Dr B. R. Gladman 6th April 2001. -+// -+// This is an implementation of the AES encryption algorithm (Rijndael) -+// designed by Joan Daemen and Vincent Rijmen. This version is designed -+// to provide both fixed and dynamic block and key lengths and can also -+// run with either big or little endian internal byte order (see aes.h). -+// It inputs block and key lengths in bytes with the legal values being -+// 16, 24 and 32. -+* -+*/ -+ -+#ifdef __KERNEL__ -+#include -+#else -+#include -+#endif -+#include "crypto/aes_cbc.h" -+#include "crypto/cbc_generic.h" -+ -+/* returns bool success */ -+int AES_set_key(aes_context *aes_ctx, const u_int8_t *key, int keysize) { -+ aes_set_key(aes_ctx, key, keysize, 0); -+ return 1; -+} -+CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, u_int8_t *, aes_encrypt, aes_decrypt); -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.1 2004/04/06 02:48:12 mcr -+ * pullup of AES cipher from alg-branch. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/aes/aes_xcbc_mac.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,67 @@ -+#ifdef __KERNEL__ -+#include -+#include -+#define DEBUG(x) -+#else -+#include -+#include -+#define DEBUG(x) x -+#endif -+ -+#include "crypto/aes.h" -+#include "crypto/aes_xcbc_mac.h" -+ -+int AES_xcbc_mac_set_key(aes_context_mac *ctxm, const u_int8_t *key, int keylen) -+{ -+ int ret=1; -+ aes_block kn[3] = { -+ { 0x01010101, 0x01010101, 0x01010101, 0x01010101 }, -+ { 0x02020202, 0x02020202, 0x02020202, 0x02020202 }, -+ { 0x03030303, 0x03030303, 0x03030303, 0x03030303 }, -+ }; -+ aes_set_key(&ctxm->ctx_k1, key, keylen, 0); -+ aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[0], (u_int8_t *) kn[0]); -+ aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[1], (u_int8_t *) ctxm->k2); -+ aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[2], (u_int8_t *) ctxm->k3); -+ aes_set_key(&ctxm->ctx_k1, (u_int8_t *) kn[0], 16, 0); -+ return ret; -+} -+static void do_pad_xor(u_int8_t *out, const u_int8_t *in, int len) { -+ int pos=0; -+ for (pos=1; pos <= 16; pos++, in++, out++) { -+ if (pos <= len) -+ *out ^= *in; -+ if (pos > len) { -+ DEBUG(printf("put 0x80 at pos=%d\n", pos)); -+ *out ^= 0x80; -+ break; -+ } -+ } -+} -+static void xor_block(aes_block res, const aes_block op) { -+ res[0] ^= op[0]; -+ res[1] ^= op[1]; -+ res[2] ^= op[2]; -+ res[3] ^= op[3]; -+} -+int AES_xcbc_mac_hash(const aes_context_mac *ctxm, const u_int8_t * in, int ilen, u_int8_t hash[16]) { -+ int ret=ilen; -+ u_int32_t out[4] = { 0, 0, 0, 0 }; -+ for (; ilen > 16 ; ilen-=16) { -+ xor_block(out, (const u_int32_t*) &in[0]); -+ aes_encrypt(&ctxm->ctx_k1, in, (u_int8_t *)&out[0]); -+ in+=16; -+ } -+ do_pad_xor((u_int8_t *)&out, in, ilen); -+ if (ilen==16) { -+ DEBUG(printf("using k3\n")); -+ xor_block(out, ctxm->k3); -+ } -+ else -+ { -+ DEBUG(printf("using k2\n")); -+ xor_block(out, ctxm->k2); -+ } -+ aes_encrypt(&ctxm->ctx_k1, (u_int8_t *)out, hash); -+ return ret; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/aes/test_main.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,41 @@ -+#include -+#include -+#include -+#include "aes_cbc.h" -+#define AES_BLOCK_SIZE 16 -+#define KEY_SIZE 128 /* bits */ -+#define KEY "1234567890123456" -+#define STR "hola guaso como estaisss ... 012" -+#define STRSZ (sizeof(STR)-1) -+ -+#define EMT_AESCBC_BLKLEN AES_BLOCK_SIZE -+#define AES_CONTEXT_T aes_context -+#define EMT_ESPAES_KEY_SZ 16 -+int pretty_print(const unsigned char *buf, int count) { -+ int i=0; -+ for (;i -+#include -+#include -+#include "aes.h" -+#include "aes_xcbc_mac.h" -+#define STR "Hola guasssso c|mo estais ...012" -+void print_hash(const __u8 *hash) { -+ printf("%08x %08x %08x %08x\n", -+ *(__u32*)(&hash[0]), -+ *(__u32*)(&hash[4]), -+ *(__u32*)(&hash[8]), -+ *(__u32*)(&hash[12])); -+} -+int main(int argc, char *argv[]) { -+ aes_block key= { 0xdeadbeef, 0xceedcaca, 0xcafebabe, 0xff010204 }; -+ __u8 hash[16]; -+ char *str = argv[1]; -+ aes_context_mac ctx; -+ if (str==NULL) { -+ fprintf(stderr, "pasame el str\n"); -+ return 255; -+ } -+ AES_xcbc_mac_set_key(&ctx, (__u8 *)&key, sizeof(key)); -+ AES_xcbc_mac_hash(&ctx, str, strlen(str), hash); -+ print_hash(hash); -+ str[2]='x'; -+ AES_xcbc_mac_hash(&ctx, str, strlen(str), hash); -+ print_hash(hash); -+ return 0; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/COPYRIGHT Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,50 @@ -+Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+All rights reserved. -+ -+This package is an DES implementation written by Eric Young (eay@cryptsoft.com). -+The implementation was written so as to conform with MIT's libdes. -+ -+This library is free for commercial and non-commercial use as long as -+the following conditions are aheared to. The following conditions -+apply to all code found in this distribution. -+ -+Copyright remains Eric Young's, and as such any Copyright notices in -+the code are not to be removed. -+If this package is used in a product, Eric Young should be given attribution -+as the author of that the SSL library. This can be in the form of a textual -+message at program startup or in documentation (online or textual) provided -+with the package. -+ -+Redistribution and use in source and binary forms, with or without -+modification, are permitted provided that the following conditions -+are met: -+1. Redistributions of source code must retain the copyright -+ notice, this list of conditions and the following disclaimer. -+2. Redistributions in binary form must reproduce the above copyright -+ notice, this list of conditions and the following disclaimer in the -+ documentation and/or other materials provided with the distribution. -+3. All advertising materials mentioning features or use of this software -+ must display the following acknowledgement: -+ This product includes software developed by Eric Young (eay@cryptsoft.com) -+ -+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+SUCH DAMAGE. -+ -+The license and distribution terms for any publically available version or -+derivative of this code cannot be changed. i.e. this code cannot simply be -+copied and put under another distrubution license -+[including the GNU Public License.] -+ -+The reason behind this being stated in this direct manner is past -+experience in code simply being copied and the attribution removed -+from it and then being distributed as part of other packages. This -+implementation was a non-trivial and unpaid effort. ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/INSTALL Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,69 @@ -+Check the CC and CFLAGS lines in the makefile -+ -+If your C library does not support the times(3) function, change the -+#define TIMES to -+#undef TIMES in speed.c -+If it does, check the HZ value for the times(3) function. -+If your system does not define CLK_TCK it will be assumed to -+be 100.0. -+ -+If possible use gcc v 2.7.? -+Turn on the maximum optimising (normally '-O3 -fomit-frame-pointer' for gcc) -+In recent times, some system compilers give better performace. -+ -+type 'make' -+ -+run './destest' to check things are ok. -+run './rpw' to check the tty code for reading passwords works. -+run './speed' to see how fast those optimisations make the library run :-) -+run './des_opts' to determin the best compile time options. -+ -+The output from des_opts should be put in the makefile options and des_enc.c -+should be rebuilt. For 64 bit computers, do not use the DES_PTR option. -+For the DEC Alpha, edit des.h and change DES_LONG to 'unsigned int' -+and then you can use the 'DES_PTR' option. -+ -+The file options.txt has the options listed for best speed on quite a -+few systems. Look and the options (UNROLL, PTR, RISC2 etc) and then -+turn on the relevent option in the Makefile -+ -+There are some special Makefile targets that make life easier. -+make cc - standard cc build -+make gcc - standard gcc build -+make x86-elf - x86 assembler (elf), linux-elf. -+make x86-out - x86 assembler (a.out), FreeBSD -+make x86-solaris- x86 assembler -+make x86-bsdi - x86 assembler (a.out with primative assembler). -+ -+If at all possible use the assembler (for Windows NT/95, use -+asm/win32.obj to link with). The x86 assembler is very very fast. -+ -+A make install will by default install -+libdes.a in /usr/local/lib/libdes.a -+des in /usr/local/bin/des -+des_crypt.man in /usr/local/man/man3/des_crypt.3 -+des.man in /usr/local/man/man1/des.1 -+des.h in /usr/include/des.h -+ -+des(1) should be compatible with sunOS's but I have been unable to -+test it. -+ -+These routines should compile on MSDOS, most 32bit and 64bit version -+of Unix (BSD and SYSV) and VMS, without modification. -+The only problems should be #include files that are in the wrong places. -+ -+These routines can be compiled under MSDOS. -+I have successfully encrypted files using des(1) under MSDOS and then -+decrypted the files on a SparcStation. -+I have been able to compile and test the routines with -+Microsoft C v 5.1 and Turbo C v 2.0. -+The code in this library is in no way optimised for the 16bit -+operation of MSDOS. -+ -+When building for glibc, ignore all of the above and just unpack into -+glibc-1.??/des and then gmake as per normal. -+ -+As a final note on performace. Certain CPUs like sparcs and Alpha often give -+a %10 speed difference depending on the link order. It is rather anoying -+when one program reports 'x' DES encrypts a second and another reports -+'x*0.9' the speed. ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/Makefile.objs Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,20 @@ -+obj-$(CONFIG_IPSEC_ENC_3DES) += cbc_enc.o -+#obj-$(CONFIG_IPSEC_ENC_3DES) += des_opts.o -+obj-$(CONFIG_IPSEC_ENC_3DES) += ecb_enc.o -+#obj-$(CONFIG_IPSEC_ENC_3DES) += fcrypt.o -+obj-$(CONFIG_IPSEC_ENC_3DES) += set_key.o -+ -+ifeq ($(strip ${SUBARCH}),) -+SUBARCH:=${ARCH} -+endif -+ -+ifeq (${SUBARCH},i386) -+obj-$(CONFIG_IPSEC_ENC_3DES) += dx86unix.o -+else -+obj-$(CONFIG_IPSEC_ENC_3DES) += des_enc.o -+endif -+ -+ -+ -+ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/README Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,54 @@ -+ -+ libdes, Version 4.01 10-Jan-97 -+ -+ Copyright (c) 1997, Eric Young -+ All rights reserved. -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms specified in COPYRIGHT. -+ -+-- -+The primary ftp site for this library is -+ftp://ftp.psy.uq.oz.au/pub/Crypto/DES/libdes-x.xx.tar.gz -+libdes is now also shipped with SSLeay. Primary ftp site of -+ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL/SSLeay-x.x.x.tar.gz -+ -+The best way to build this library is to build it as part of SSLeay. -+ -+This kit builds a DES encryption library and a DES encryption program. -+It supports ecb, cbc, ofb, cfb, triple ecb, triple cbc, triple ofb, -+triple cfb, desx, and MIT's pcbc encryption modes and also has a fast -+implementation of crypt(3). -+It contains support routines to read keys from a terminal, -+generate a random key, generate a key from an arbitrary length string, -+read/write encrypted data from/to a file descriptor. -+ -+The implementation was written so as to conform with the manual entry -+for the des_crypt(3) library routines from MIT's project Athena. -+ -+destest should be run after compilation to test the des routines. -+rpw should be run after compilation to test the read password routines. -+The des program is a replacement for the sun des command. I believe it -+conforms to the sun version. -+ -+The Imakefile is setup for use in the kerberos distribution. -+ -+These routines are best compiled with gcc or any other good -+optimising compiler. -+Just turn you optimiser up to the highest settings and run destest -+after the build to make sure everything works. -+ -+I believe these routines are close to the fastest and most portable DES -+routines that use small lookup tables (4.5k) that are publicly available. -+The fcrypt routine is faster than ufc's fcrypt (when compiling with -+gcc2 -O2) on the sparc 2 (1410 vs 1270) but is not so good on other machines -+(on a sun3/260 168 vs 336). It is a function of CPU on chip cache size. -+[ 10-Jan-97 and a function of an incorrect speed testing program in -+ ufc which gave much better test figures that reality ]. -+ -+It is worth noting that on sparc and Alpha CPUs, performance of the DES -+library can vary by upto %10 due to the positioning of files after application -+linkage. -+ -+Eric Young (eay@cryptsoft.com) -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/README.freeswan Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,33 @@ -+The only changes the FreeS/WAN project has made to libdes-lite 4.04b are: -+ -+We #ifdef-ed the declaration of DES_LONG in des.h, so it's more efficient -+on the Alpha, instead of just noting the issue in a comment. -+ -+We #ifdef-ed out the des_options() function in ecb_enc.c, because we don't -+use it, and its call to sprintf() can cause subtle difficulties when KLIPS -+is built as a module (depending on details of Linux configuration options). -+ -+We changed some instances of CC=$(CC) in the Makefile to CC='$(CC)' to make -+it cope better with Linux kernel Makefile stupidities, and took out an -+explicit CC=gcc (unwise on systems with strange compilers). -+ -+We deleted some references to and , and a declaration -+of one function found only in the full libdes (not in libdes-lite), to -+avoid dragging in bits of stdio/stdlib unnecessarily. (Our thanks to Hans -+Schultz for spotting this and pointing out the fixes.) -+ -+We deleted a couple of .obj files in the asm subdirectory, which appear to -+have been included in the original library by accident. -+ -+We have added an include of our Makefile.inc file, to permit overriding -+things like choice of compiler (although the libdes Makefile would -+probably need some work to make this effective). -+ -+ -+ -+Note that Eric Young is no longer at the email address listed in these -+files, and is (alas) no longer working on free crypto software. -+ -+ -+ -+This file is RCSID $Id$ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/VERSION Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,406 @@ -+Version 4.04 -+ Fixed a few tests in destest. Also added x86 assember for -+ des_ncbc_encrypt() which is the standard cbc mode function. -+ This makes a very very large performace difference. -+ Ariel Glenn ariel@columbia.edu reports that the terminal -+ 'turn echo off' can return (errno == EINVAL) under solaris -+ when redirection is used. So I now catch that as well as ENOTTY. -+ -+ -+Version 4.03 -+ Left a static out of enc_write.c, which caused to buffer to be -+ continiously malloc()ed. Does anyone use these functions? I keep -+ on feeling like removing them since I only had these in there -+ for a version of kerberised login. Anyway, this was pointed out -+ by Theo de Raadt -+ The 'n' bit ofb code was wrong, it was not shifting the shift -+ register. It worked correctly for n == 64. Thanks to -+ Gigi Ankeny for pointing this one out. -+ -+Version 4.02 -+ I was doing 'if (memcmp(weak_keys[i],key,sizeof(key)) == 0)' -+ when checking for weak keys which is wrong :-(, pointed out by -+ Markus F.X.J. Oberhumer . -+ -+Version 4.01 -+ Even faster inner loop in the DES assembler for x86 and a modification -+ for IP/FP which is faster on x86. Both of these changes are -+ from Svend Olaf Mikkelsen . His -+ changes make the assembler run %40 faster on a pentium. This is just -+ a case of getting the instruction sequence 'just right'. -+ All credit to 'Svend' :-) -+ Quite a few special x86 'make' targets. -+ A libdes-l (lite) distribution. -+ -+Version 4.00 -+ After a bit of a pause, I'll up the major version number since this -+ is mostly a performace release. I've added x86 assembler and -+ added more options for performance. A %28 speedup for gcc -+ on a pentium and the assembler is a %50 speedup. -+ MIPS CPU's, sparc and Alpha are the main CPU's with speedups. -+ Run des_opts to work out which options should be used. -+ DES_RISC1/DES_RISC2 use alternative inner loops which use -+ more registers but should give speedups on any CPU that does -+ dual issue (pentium). DES_UNROLL unrolls the inner loop, -+ which costs in code size. -+ -+Version 3.26 -+ I've finally removed one of the shifts in D_ENCRYPT. This -+ meant I've changed the des_SPtrans table (spr.h), the set_key() -+ function and some things in des_enc.c. This has definitly -+ made things faster :-). I've known about this one for some -+ time but I've been too lazy to follow it up :-). -+ Noticed that in the D_ENCRYPT() macro, we can just do L^=(..)^(..)^.. -+ instead of L^=((..)|(..)|(..).. This should save a register at -+ least. -+ Assember for x86. The file to replace is des_enc.c, which is replaced -+ by one of the assembler files found in asm. Look at des/asm/readme -+ for more info. -+ -+ /* Modification to fcrypt so it can be compiled to support -+ HPUX 10.x's long password format, define -DLONGCRYPT to use this. -+ Thanks to Jens Kupferschmidt . */ -+ -+ SIGWINCH case put in des_read_passwd() so the function does not -+ 'exit' if this function is recieved. -+ -+Version 3.25 17/07/96 -+ Modified read_pwd.c so that stdin can be read if not a tty. -+ Thanks to Jeff Barber for the patches. -+ des_init_random_number_generator() shortened due to VMS linker -+ limits. -+ Added RSA's DESX cbc mode. It is a form of cbc encryption, with 2 -+ 8 byte quantites xored before and after encryption. -+ des_xcbc_encryption() - the name is funny to preserve the des_ -+ prefix on all functions. -+ -+Version 3.24 20/04/96 -+ The DES_PTR macro option checked and used by SSLeay configuration -+ -+Version 3.23 11/04/96 -+ Added DES_LONG. If defined to 'unsigned int' on the DEC Alpha, -+ it gives a %20 speedup :-) -+ Fixed the problem with des.pl under perl5. The patches were -+ sent by Ed Kubaitis (ejk@uiuc.edu). -+ if fcrypt.c, changed values to handle illegal salt values the way -+ normal crypt() implementations do. Some programs apparently use -+ them :-(. The patch was sent by Bjorn Gronvall -+ -+Version 3.22 29/11/95 -+ Bug in des(1), an error with the uuencoding stuff when the -+ 'data' is small, thanks to Geoff Keating -+ for the patch. -+ -+Version 3.21 22/11/95 -+ After some emailing back and forth with -+ Colin Plumb , I've tweaked a few things -+ and in a future version I will probably put in some of the -+ optimisation he suggested for use with the DES_USE_PTR option. -+ Extra routines from Mark Murray for use in -+ freeBSD. They mostly involve random number generation for use -+ with kerberos. They involve evil machine specific system calls -+ etc so I would normally suggest pushing this stuff into the -+ application and/or using RAND_seed()/RAND_bytes() if you are -+ using this DES library as part of SSLeay. -+ Redone the read_pw() function so that it is cleaner and -+ supports termios, thanks to Sameer Parekh -+ for the initial patches for this. -+ Renamed 3ecb_encrypt() to ecb3_encrypt(). This has been -+ done just to make things more consistent. -+ I have also now added triple DES versions of cfb and ofb. -+ -+Version 3.20 -+ Damn, Damn, Damn, as pointed out by Mike_Spreitzer.PARC@xerox.com, -+ my des_random_seed() function was only copying 4 bytes of the -+ passed seed into the init structure. It is now fixed to copy 8. -+ My own suggestion is to used something like MD5 :-) -+ -+Version 3.19 -+ While looking at my code one day, I though, why do I keep on -+ calling des_encrypt(in,out,ks,enc) when every function that -+ calls it has in and out the same. So I dropped the 'out' -+ parameter, people should not be using this function. -+ -+Version 3.18 30/08/95 -+ Fixed a few bit with the distribution and the filenames. -+ 3.17 had been munged via a move to DOS and back again. -+ NO CODE CHANGES -+ -+Version 3.17 14/07/95 -+ Fixed ede3 cbc which I had broken in 3.16. I have also -+ removed some unneeded variables in 7-8 of the routines. -+ -+Version 3.16 26/06/95 -+ Added des_encrypt2() which does not use IP/FP, used by triple -+ des routines. Tweaked things a bit elsewhere. %13 speedup on -+ sparc and %6 on a R4400 for ede3 cbc mode. -+ -+Version 3.15 06/06/95 -+ Added des_ncbc_encrypt(), it is des_cbc mode except that it is -+ 'normal' and copies the new iv value back over the top of the -+ passed parameter. -+ CHANGED des_ede3_cbc_encrypt() so that it too now overwrites -+ the iv. THIS WILL BREAK EXISTING CODE, but since this function -+ only new, I feel I can change it, not so with des_cbc_encrypt :-(. -+ I need to update the documentation. -+ -+Version 3.14 31/05/95 -+ New release upon the world, as part of my SSL implementation. -+ New copyright and usage stuff. Basically free for all to use -+ as long as you say it came from me :-) -+ -+Version 3.13 31/05/95 -+ A fix in speed.c, if HZ is not defined, I set it to 100.0 -+ which is reasonable for most unixes except SunOS 4.x. -+ I now have a #ifdef sun but timing for SunOS 4.x looked very -+ good :-(. At my last job where I used SunOS 4.x, it was -+ defined to be 60.0 (look at the old INSTALL documentation), at -+ the last release had it changed to 100.0 since I now work with -+ Solaris2 and SVR4 boxes. -+ Thanks to Rory Chisholm for pointing this -+ one out. -+ -+Version 3.12 08/05/95 -+ As pointed out by The Crypt Keeper , -+ my D_ENCRYPT macro in crypt() had an un-necessary variable. -+ It has been removed. -+ -+Version 3.11 03/05/95 -+ Added des_ede3_cbc_encrypt() which is cbc mode des with 3 keys -+ and one iv. It is a standard and I needed it for my SSL code. -+ It makes more sense to use this for triple DES than -+ 3cbc_encrypt(). I have also added (or should I say tested :-) -+ cfb64_encrypt() which is cfb64 but it will encrypt a partial -+ number of bytes - 3 bytes in 3 bytes out. Again this is for -+ my SSL library, as a form of encryption to use with SSL -+ telnet. -+ -+Version 3.10 22/03/95 -+ Fixed a bug in 3cbc_encrypt() :-(. When making repeated calls -+ to cbc3_encrypt, the 2 iv values that were being returned to -+ be used in the next call were reversed :-(. -+ Many thanks to Bill Wade for pointing out -+ this error. -+ -+Version 3.09 01/02/95 -+ Fixed des_random_key to far more random, it was rather feeble -+ with regards to picking the initial seed. The problem was -+ pointed out by Olaf Kirch . -+ -+Version 3.08 14/12/94 -+ Added Makefile.PL so libdes can be built into perl5. -+ Changed des_locl.h so RAND is always defined. -+ -+Version 3.07 05/12/94 -+ Added GNUmake and stuff so the library can be build with -+ glibc. -+ -+Version 3.06 30/08/94 -+ Added rpc_enc.c which contains _des_crypt. This is for use in -+ secure_rpc v 4.0 -+ Finally fixed the cfb_enc problems. -+ Fixed a few parameter parsing bugs in des (-3 and -b), thanks -+ to Rob McMillan -+ -+Version 3.05 21/04/94 -+ for unsigned long l; gcc does not produce ((l>>34) == 0) -+ This causes bugs in cfb_enc. -+ Thanks to Hadmut Danisch -+ -+Version 3.04 20/04/94 -+ Added a version number to des.c and libdes.a -+ -+Version 3.03 12/01/94 -+ Fixed a bug in non zero iv in 3cbc_enc. -+ -+Version 3.02 29/10/93 -+ I now work in a place where there are 6+ architectures and 14+ -+ OS versions :-). -+ Fixed TERMIO definition so the most sys V boxes will work :-) -+ -+Release upon comp.sources.misc -+Version 3.01 08/10/93 -+ Added des_3cbc_encrypt() -+ -+Version 3.00 07/10/93 -+ Fixed up documentation. -+ quad_cksum definitely compatible with MIT's now. -+ -+Version 2.30 24/08/93 -+ Triple DES now defaults to triple cbc but can do triple ecb -+ with the -b flag. -+ Fixed some MSDOS uuen/uudecoding problems, thanks to -+ Added prototypes. -+ -+Version 2.22 29/06/93 -+ Fixed a bug in des_is_weak_key() which stopped it working :-( -+ thanks to engineering@MorningStar.Com. -+ -+Version 2.21 03/06/93 -+ des(1) with no arguments gives quite a bit of help. -+ Added -c (generate ckecksum) flag to des(1). -+ Added -3 (triple DES) flag to des(1). -+ Added cfb and ofb routines to the library. -+ -+Version 2.20 11/03/93 -+ Added -u (uuencode) flag to des(1). -+ I have been playing with byte order in quad_cksum to make it -+ compatible with MIT's version. All I can say is avid this -+ function if possible since MIT's output is endian dependent. -+ -+Version 2.12 14/10/92 -+ Added MSDOS specific macro in ecb_encrypt which gives a %70 -+ speed up when the code is compiled with turbo C. -+ -+Version 2.11 12/10/92 -+ Speedup in set_key (recoding of PC-1) -+ I now do it in 47 simple operations, down from 60. -+ Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) -+ for motivating me to look for a faster system :-) -+ The speedup is probably less that 1% but it is still 13 -+ instructions less :-). -+ -+Version 2.10 06/10/92 -+ The code now works on the 64bit ETA10 and CRAY without modifications or -+ #defines. I believe the code should work on any machine that -+ defines long, int or short to be 8 bytes long. -+ Thanks to Shabbir J. Safdar (shabby@mentor.cc.purdue.edu) -+ for helping me fix the code to run on 64bit machines (he had -+ access to an ETA10). -+ Thanks also to John Fletcher -+ for testing the routines on a CRAY. -+ read_password.c has been renamed to read_passwd.c -+ string_to_key.c has been renamed to string2key.c -+ -+Version 2.00 14/09/92 -+ Made mods so that the library should work on 64bit CPU's. -+ Removed all my uchar and ulong defs. To many different -+ versions of unix define them in their header files in too many -+ different combinations :-) -+ IRIX - Sillicon Graphics mods (mostly in read_password.c). -+ Thanks to Andrew Daviel (advax@erich.triumf.ca) -+ -+Version 1.99 26/08/92 -+ Fixed a bug or 2 in enc_read.c -+ Fixed a bug in enc_write.c -+ Fixed a pseudo bug in fcrypt.c (very obscure). -+ -+Version 1.98 31/07/92 -+ Support for the ETA10. This is a strange machine that defines -+ longs and ints as 8 bytes and shorts as 4 bytes. -+ Since I do evil things with long * that assume that they are 4 -+ bytes. Look in the Makefile for the option to compile for -+ this machine. quad_cksum appears to have problems but I -+ will don't have the time to fix it right now, and this is not -+ a function that uses DES and so will not effect the main uses -+ of the library. -+ -+Version 1.97 20/05/92 eay -+ Fixed the Imakefile and made some changes to des.h to fix some -+ problems when building this package with Kerberos v 4. -+ -+Version 1.96 18/05/92 eay -+ Fixed a small bug in string_to_key() where problems could -+ occur if des_check_key was set to true and the string -+ generated a weak key. -+ -+Patch2 posted to comp.sources.misc -+Version 1.95 13/05/92 eay -+ Added an alternative version of the D_ENCRYPT macro in -+ ecb_encrypt and fcrypt. Depending on the compiler, one version or the -+ other will be faster. This was inspired by -+ Dana How , and her pointers about doing the -+ *(ulong *)((uchar *)ptr+(value&0xfc)) -+ vs -+ ptr[value&0x3f] -+ to stop the C compiler doing a <<2 to convert the long array index. -+ -+Version 1.94 05/05/92 eay -+ Fixed an incompatibility between my string_to_key and the MIT -+ version. When the key is longer than 8 chars, I was wrapping -+ with a different method. To use the old version, define -+ OLD_STR_TO_KEY in the makefile. Thanks to -+ viktor@newsu.shearson.com (Viktor Dukhovni). -+ -+Version 1.93 28/04/92 eay -+ Fixed the VMS mods so that echo is now turned off in -+ read_password. Thanks again to brennan@coco.cchs.su.oz.AU. -+ MSDOS support added. The routines can be compiled with -+ Turbo C (v2.0) and MSC (v5.1). Make sure MSDOS is defined. -+ -+Patch1 posted to comp.sources.misc -+Version 1.92 13/04/92 eay -+ Changed D_ENCRYPT so that the rotation of R occurs outside of -+ the loop. This required rotating all the longs in sp.h (now -+ called spr.h). Thanks to Richard Outerbridge <71755.204@CompuServe.COM> -+ speed.c has been changed so it will work without SIGALRM. If -+ times(3) is not present it will try to use ftime() instead. -+ -+Version 1.91 08/04/92 eay -+ Added -E/-D options to des(1) so it can use string_to_key. -+ Added SVR4 mods suggested by witr@rwwa.COM -+ Added VMS mods suggested by brennan@coco.cchs.su.oz.AU. If -+ anyone knows how to turn of tty echo in VMS please tell me or -+ implement it yourself :-). -+ Changed FILE *IN/*OUT to *DES_IN/*DES_OUT since it appears VMS -+ does not like IN/OUT being used. -+ -+Libdes posted to comp.sources.misc -+Version 1.9 24/03/92 eay -+ Now contains a fast small crypt replacement. -+ Added des(1) command. -+ Added des_rw_mode so people can use cbc encryption with -+ enc_read and enc_write. -+ -+Version 1.8 15/10/91 eay -+ Bug in cbc_cksum. -+ Many thanks to Keith Reynolds (keithr@sco.COM) for pointing this -+ one out. -+ -+Version 1.7 24/09/91 eay -+ Fixed set_key :-) -+ set_key is 4 times faster and takes less space. -+ There are a few minor changes that could be made. -+ -+Version 1.6 19/09/1991 eay -+ Finally go IP and FP finished. -+ Now I need to fix set_key. -+ This version is quite a bit faster that 1.51 -+ -+Version 1.52 15/06/1991 eay -+ 20% speedup in ecb_encrypt by changing the E bit selection -+ to use 2 32bit words. This also required modification of the -+ sp table. There is still a way to speedup the IP and IP-1 -+ (hints from outer@sq.com) still working on this one :-(. -+ -+Version 1.51 07/06/1991 eay -+ Faster des_encrypt by loop unrolling -+ Fixed bug in quad_cksum.c (thanks to hughes@logos.ucs.indiana.edu) -+ -+Version 1.50 28/05/1991 eay -+ Optimised the code a bit more for the sparc. I have improved the -+ speed of the inner des_encrypt by speeding up the initial and -+ final permutations. -+ -+Version 1.40 23/10/1990 eay -+ Fixed des_random_key, it did not produce a random key :-( -+ -+Version 1.30 2/10/1990 eay -+ Have made des_quad_cksum the same as MIT's, the full package -+ should be compatible with MIT's -+ Have tested on a DECstation 3100 -+ Still need to fix des_set_key (make it faster). -+ Does des_cbc_encrypts at 70.5k/sec on a 3100. -+ -+Version 1.20 18/09/1990 eay -+ Fixed byte order dependencies. -+ Fixed (I hope) all the word alignment problems. -+ Speedup in des_ecb_encrypt. -+ -+Version 1.10 11/09/1990 eay -+ Added des_enc_read and des_enc_write. -+ Still need to fix des_quad_cksum. -+ Still need to document des_enc_read and des_enc_write. -+ -+Version 1.00 27/08/1990 eay -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/crypt586.pl Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,204 @@ -+#!/usr/bin/perl -+# -+# The inner loop instruction sequence and the IP/FP modifications are from -+# Svend Olaf Mikkelsen -+# I've added the stuff needed for crypt() but I've not worried about making -+# things perfect. -+# -+ -+push(@INC,"perlasm","../../perlasm"); -+require "x86asm.pl"; -+ -+&asm_init($ARGV[0],"crypt586.pl"); -+ -+$L="edi"; -+$R="esi"; -+ -+&external_label("des_SPtrans"); -+&fcrypt_body("fcrypt_body"); -+&asm_finish(); -+ -+sub fcrypt_body -+ { -+ local($name,$do_ip)=@_; -+ -+ &function_begin($name,"EXTRN _des_SPtrans:DWORD"); -+ -+ &comment(""); -+ &comment("Load the 2 words"); -+ $ks="ebp"; -+ -+ &xor( $L, $L); -+ &xor( $R, $R); -+ &mov($ks,&wparam(1)); -+ -+ &push(25); # add a variable -+ -+ &set_label("start"); -+ for ($i=0; $i<16; $i+=2) -+ { -+ &comment(""); -+ &comment("Round $i"); -+ &D_ENCRYPT($i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); -+ -+ &comment(""); -+ &comment("Round ".sprintf("%d",$i+1)); -+ &D_ENCRYPT($i+1,$R,$L,($i+1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); -+ } -+ &mov("ebx", &swtmp(0)); -+ &mov("eax", $L); -+ &dec("ebx"); -+ &mov($L, $R); -+ &mov($R, "eax"); -+ &mov(&swtmp(0), "ebx"); -+ &jnz(&label("start")); -+ -+ &comment(""); -+ &comment("FP"); -+ &mov("edx",&wparam(0)); -+ -+ &FP_new($R,$L,"eax",3); -+ &mov(&DWP(0,"edx","",0),"eax"); -+ &mov(&DWP(4,"edx","",0),$L); -+ -+ &pop("ecx"); # remove variable -+ -+ &function_end($name); -+ } -+ -+sub D_ENCRYPT -+ { -+ local($r,$L,$R,$S,$ks,$desSP,$u,$tmp1,$tmp2,$t)=@_; -+ -+ &mov( $u, &wparam(2)); # 2 -+ &mov( $t, $R); -+ &shr( $t, 16); # 1 -+ &mov( $tmp2, &wparam(3)); # 2 -+ &xor( $t, $R); # 1 -+ -+ &and( $u, $t); # 2 -+ &and( $t, $tmp2); # 2 -+ -+ &mov( $tmp1, $u); -+ &shl( $tmp1, 16); # 1 -+ &mov( $tmp2, $t); -+ &shl( $tmp2, 16); # 1 -+ &xor( $u, $tmp1); # 2 -+ &xor( $t, $tmp2); # 2 -+ &mov( $tmp1, &DWP(&n2a($S*4),$ks,"",0)); # 2 -+ &xor( $u, $tmp1); -+ &mov( $tmp2, &DWP(&n2a(($S+1)*4),$ks,"",0)); # 2 -+ &xor( $u, $R); -+ &xor( $t, $R); -+ &xor( $t, $tmp2); -+ -+ &and( $u, "0xfcfcfcfc" ); # 2 -+ &xor( $tmp1, $tmp1); # 1 -+ &and( $t, "0xcfcfcfcf" ); # 2 -+ &xor( $tmp2, $tmp2); -+ &movb( &LB($tmp1), &LB($u) ); -+ &movb( &LB($tmp2), &HB($u) ); -+ &rotr( $t, 4 ); -+ &mov( $ks, &DWP(" $desSP",$tmp1,"",0)); -+ &movb( &LB($tmp1), &LB($t) ); -+ &xor( $L, $ks); -+ &mov( $ks, &DWP("0x200+$desSP",$tmp2,"",0)); -+ &xor( $L, $ks); -+ &movb( &LB($tmp2), &HB($t) ); -+ &shr( $u, 16); -+ &mov( $ks, &DWP("0x100+$desSP",$tmp1,"",0)); -+ &xor( $L, $ks); -+ &movb( &LB($tmp1), &HB($u) ); -+ &shr( $t, 16); -+ &mov( $ks, &DWP("0x300+$desSP",$tmp2,"",0)); -+ &xor( $L, $ks); -+ &mov( $ks, &wparam(1)); -+ &movb( &LB($tmp2), &HB($t) ); -+ &and( $u, "0xff" ); -+ &and( $t, "0xff" ); -+ &mov( $tmp1, &DWP("0x600+$desSP",$tmp1,"",0)); -+ &xor( $L, $tmp1); -+ &mov( $tmp1, &DWP("0x700+$desSP",$tmp2,"",0)); -+ &xor( $L, $tmp1); -+ &mov( $tmp1, &DWP("0x400+$desSP",$u,"",0)); -+ &xor( $L, $tmp1); -+ &mov( $tmp1, &DWP("0x500+$desSP",$t,"",0)); -+ &xor( $L, $tmp1); -+ } -+ -+sub n2a -+ { -+ sprintf("%d",$_[0]); -+ } -+ -+# now has a side affect of rotating $a by $shift -+sub R_PERM_OP -+ { -+ local($a,$b,$tt,$shift,$mask,$last)=@_; -+ -+ &rotl( $a, $shift ) if ($shift != 0); -+ &mov( $tt, $a ); -+ &xor( $a, $b ); -+ &and( $a, $mask ); -+ if ($notlast eq $b) -+ { -+ &xor( $b, $a ); -+ &xor( $tt, $a ); -+ } -+ else -+ { -+ &xor( $tt, $a ); -+ &xor( $b, $a ); -+ } -+ &comment(""); -+ } -+ -+sub IP_new -+ { -+ local($l,$r,$tt,$lr)=@_; -+ -+ &R_PERM_OP($l,$r,$tt, 4,"0xf0f0f0f0",$l); -+ &R_PERM_OP($r,$tt,$l,20,"0xfff0000f",$l); -+ &R_PERM_OP($l,$tt,$r,14,"0x33333333",$r); -+ &R_PERM_OP($tt,$r,$l,22,"0x03fc03fc",$r); -+ &R_PERM_OP($l,$r,$tt, 9,"0xaaaaaaaa",$r); -+ -+ if ($lr != 3) -+ { -+ if (($lr-3) < 0) -+ { &rotr($tt, 3-$lr); } -+ else { &rotl($tt, $lr-3); } -+ } -+ if ($lr != 2) -+ { -+ if (($lr-2) < 0) -+ { &rotr($r, 2-$lr); } -+ else { &rotl($r, $lr-2); } -+ } -+ } -+ -+sub FP_new -+ { -+ local($l,$r,$tt,$lr)=@_; -+ -+ if ($lr != 2) -+ { -+ if (($lr-2) < 0) -+ { &rotl($r, 2-$lr); } -+ else { &rotr($r, $lr-2); } -+ } -+ if ($lr != 3) -+ { -+ if (($lr-3) < 0) -+ { &rotl($l, 3-$lr); } -+ else { &rotr($l, $lr-3); } -+ } -+ -+ &R_PERM_OP($l,$r,$tt, 0,"0xaaaaaaaa",$r); -+ &R_PERM_OP($tt,$r,$l,23,"0x03fc03fc",$r); -+ &R_PERM_OP($l,$r,$tt,10,"0x33333333",$l); -+ &R_PERM_OP($r,$tt,$l,18,"0xfff0000f",$l); -+ &R_PERM_OP($l,$tt,$r,12,"0xf0f0f0f0",$r); -+ &rotr($tt , 4); -+ } -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/des-586.pl Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,251 @@ -+#!/usr/bin/perl -+# -+# The inner loop instruction sequence and the IP/FP modifications are from -+# Svend Olaf Mikkelsen -+# -+ -+push(@INC,"perlasm","../../perlasm"); -+require "x86asm.pl"; -+require "cbc.pl"; -+require "desboth.pl"; -+ -+# base code is in microsft -+# op dest, source -+# format. -+# -+ -+&asm_init($ARGV[0],"des-586.pl"); -+ -+$L="edi"; -+$R="esi"; -+ -+&external_label("des_SPtrans"); -+&des_encrypt("des_encrypt",1); -+&des_encrypt("des_encrypt2",0); -+&des_encrypt3("des_encrypt3",1); -+&des_encrypt3("des_decrypt3",0); -+&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1); -+&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5); -+ -+&asm_finish(); -+ -+sub des_encrypt -+ { -+ local($name,$do_ip)=@_; -+ -+ &function_begin_B($name,"EXTRN _des_SPtrans:DWORD"); -+ -+ &push("esi"); -+ &push("edi"); -+ -+ &comment(""); -+ &comment("Load the 2 words"); -+ $ks="ebp"; -+ -+ if ($do_ip) -+ { -+ &mov($R,&wparam(0)); -+ &xor( "ecx", "ecx" ); -+ -+ &push("ebx"); -+ &push("ebp"); -+ -+ &mov("eax",&DWP(0,$R,"",0)); -+ &mov("ebx",&wparam(2)); # get encrypt flag -+ &mov($L,&DWP(4,$R,"",0)); -+ &comment(""); -+ &comment("IP"); -+ &IP_new("eax",$L,$R,3); -+ } -+ else -+ { -+ &mov("eax",&wparam(0)); -+ &xor( "ecx", "ecx" ); -+ -+ &push("ebx"); -+ &push("ebp"); -+ -+ &mov($R,&DWP(0,"eax","",0)); -+ &mov("ebx",&wparam(2)); # get encrypt flag -+ &rotl($R,3); -+ &mov($L,&DWP(4,"eax","",0)); -+ &rotl($L,3); -+ } -+ -+ &mov( $ks, &wparam(1) ); -+ &cmp("ebx","0"); -+ &je(&label("start_decrypt")); -+ -+ for ($i=0; $i<16; $i+=2) -+ { -+ &comment(""); -+ &comment("Round $i"); -+ &D_ENCRYPT($i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); -+ -+ &comment(""); -+ &comment("Round ".sprintf("%d",$i+1)); -+ &D_ENCRYPT($i+1,$R,$L,($i+1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); -+ } -+ &jmp(&label("end")); -+ -+ &set_label("start_decrypt"); -+ -+ for ($i=15; $i>0; $i-=2) -+ { -+ &comment(""); -+ &comment("Round $i"); -+ &D_ENCRYPT(15-$i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); -+ &comment(""); -+ &comment("Round ".sprintf("%d",$i-1)); -+ &D_ENCRYPT(15-$i+1,$R,$L,($i-1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); -+ } -+ -+ &set_label("end"); -+ -+ if ($do_ip) -+ { -+ &comment(""); -+ &comment("FP"); -+ &mov("edx",&wparam(0)); -+ &FP_new($L,$R,"eax",3); -+ -+ &mov(&DWP(0,"edx","",0),"eax"); -+ &mov(&DWP(4,"edx","",0),$R); -+ } -+ else -+ { -+ &comment(""); -+ &comment("Fixup"); -+ &rotr($L,3); # r -+ &mov("eax",&wparam(0)); -+ &rotr($R,3); # l -+ &mov(&DWP(0,"eax","",0),$L); -+ &mov(&DWP(4,"eax","",0),$R); -+ } -+ -+ &pop("ebp"); -+ &pop("ebx"); -+ &pop("edi"); -+ &pop("esi"); -+ &ret(); -+ -+ &function_end_B($name); -+ } -+ -+sub D_ENCRYPT -+ { -+ local($r,$L,$R,$S,$ks,$desSP,$u,$tmp1,$tmp2,$t)=@_; -+ -+ &mov( $u, &DWP(&n2a($S*4),$ks,"",0)); -+ &xor( $tmp1, $tmp1); -+ &mov( $t, &DWP(&n2a(($S+1)*4),$ks,"",0)); -+ &xor( $u, $R); -+ &xor( $t, $R); -+ &and( $u, "0xfcfcfcfc" ); -+ &and( $t, "0xcfcfcfcf" ); -+ &movb( &LB($tmp1), &LB($u) ); -+ &movb( &LB($tmp2), &HB($u) ); -+ &rotr( $t, 4 ); -+ &mov( $ks, &DWP(" $desSP",$tmp1,"",0)); -+ &movb( &LB($tmp1), &LB($t) ); -+ &xor( $L, $ks); -+ &mov( $ks, &DWP("0x200+$desSP",$tmp2,"",0)); -+ &xor( $L, $ks); ###### -+ &movb( &LB($tmp2), &HB($t) ); -+ &shr( $u, 16); -+ &mov( $ks, &DWP("0x100+$desSP",$tmp1,"",0)); -+ &xor( $L, $ks); ###### -+ &movb( &LB($tmp1), &HB($u) ); -+ &shr( $t, 16); -+ &mov( $ks, &DWP("0x300+$desSP",$tmp2,"",0)); -+ &xor( $L, $ks); -+ &mov( $ks, &wparam(1) ); -+ &movb( &LB($tmp2), &HB($t) ); -+ &and( $u, "0xff" ); -+ &and( $t, "0xff" ); -+ &mov( $tmp1, &DWP("0x600+$desSP",$tmp1,"",0)); -+ &xor( $L, $tmp1); -+ &mov( $tmp1, &DWP("0x700+$desSP",$tmp2,"",0)); -+ &xor( $L, $tmp1); -+ &mov( $tmp1, &DWP("0x400+$desSP",$u,"",0)); -+ &xor( $L, $tmp1); -+ &mov( $tmp1, &DWP("0x500+$desSP",$t,"",0)); -+ &xor( $L, $tmp1); -+ } -+ -+sub n2a -+ { -+ sprintf("%d",$_[0]); -+ } -+ -+# now has a side affect of rotating $a by $shift -+sub R_PERM_OP -+ { -+ local($a,$b,$tt,$shift,$mask,$last)=@_; -+ -+ &rotl( $a, $shift ) if ($shift != 0); -+ &mov( $tt, $a ); -+ &xor( $a, $b ); -+ &and( $a, $mask ); -+ if (!$last eq $b) -+ { -+ &xor( $b, $a ); -+ &xor( $tt, $a ); -+ } -+ else -+ { -+ &xor( $tt, $a ); -+ &xor( $b, $a ); -+ } -+ &comment(""); -+ } -+ -+sub IP_new -+ { -+ local($l,$r,$tt,$lr)=@_; -+ -+ &R_PERM_OP($l,$r,$tt, 4,"0xf0f0f0f0",$l); -+ &R_PERM_OP($r,$tt,$l,20,"0xfff0000f",$l); -+ &R_PERM_OP($l,$tt,$r,14,"0x33333333",$r); -+ &R_PERM_OP($tt,$r,$l,22,"0x03fc03fc",$r); -+ &R_PERM_OP($l,$r,$tt, 9,"0xaaaaaaaa",$r); -+ -+ if ($lr != 3) -+ { -+ if (($lr-3) < 0) -+ { &rotr($tt, 3-$lr); } -+ else { &rotl($tt, $lr-3); } -+ } -+ if ($lr != 2) -+ { -+ if (($lr-2) < 0) -+ { &rotr($r, 2-$lr); } -+ else { &rotl($r, $lr-2); } -+ } -+ } -+ -+sub FP_new -+ { -+ local($l,$r,$tt,$lr)=@_; -+ -+ if ($lr != 2) -+ { -+ if (($lr-2) < 0) -+ { &rotl($r, 2-$lr); } -+ else { &rotr($r, $lr-2); } -+ } -+ if ($lr != 3) -+ { -+ if (($lr-3) < 0) -+ { &rotl($l, 3-$lr); } -+ else { &rotr($l, $lr-3); } -+ } -+ -+ &R_PERM_OP($l,$r,$tt, 0,"0xaaaaaaaa",$r); -+ &R_PERM_OP($tt,$r,$l,23,"0x03fc03fc",$r); -+ &R_PERM_OP($l,$r,$tt,10,"0x33333333",$l); -+ &R_PERM_OP($r,$tt,$l,18,"0xfff0000f",$l); -+ &R_PERM_OP($l,$tt,$r,12,"0xf0f0f0f0",$r); -+ &rotr($tt , 4); -+ } -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/des686.pl Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,230 @@ -+#!/usr/bin/perl -+ -+$prog="des686.pl"; -+ -+# base code is in microsft -+# op dest, source -+# format. -+# -+ -+# WILL NOT WORK ANYMORE WITH desboth.pl -+require "desboth.pl"; -+ -+if ( ($ARGV[0] eq "elf")) -+ { require "x86unix.pl"; } -+elsif ( ($ARGV[0] eq "a.out")) -+ { $aout=1; require "x86unix.pl"; } -+elsif ( ($ARGV[0] eq "sol")) -+ { $sol=1; require "x86unix.pl"; } -+elsif ( ($ARGV[0] eq "cpp")) -+ { $cpp=1; require "x86unix.pl"; } -+elsif ( ($ARGV[0] eq "win32")) -+ { require "x86ms.pl"; } -+else -+ { -+ print STDERR <<"EOF"; -+Pick one target type from -+ elf - linux, FreeBSD etc -+ a.out - old linux -+ sol - x86 solaris -+ cpp - format so x86unix.cpp can be used -+ win32 - Windows 95/Windows NT -+EOF -+ exit(1); -+ } -+ -+&comment("Don't even think of reading this code"); -+&comment("It was automatically generated by $prog"); -+&comment("Which is a perl program used to generate the x86 assember for"); -+&comment("any of elf, a.out, Win32, or Solaris"); -+&comment("It can be found in SSLeay 0.6.5+ or in libdes 3.26+"); -+&comment("eric "); -+&comment(""); -+ -+&file("dx86xxxx"); -+ -+$L="edi"; -+$R="esi"; -+ -+&des_encrypt("des_encrypt",1); -+&des_encrypt("des_encrypt2",0); -+ -+&des_encrypt3("des_encrypt3",1); -+&des_encrypt3("des_decrypt3",0); -+ -+&file_end(); -+ -+sub des_encrypt -+ { -+ local($name,$do_ip)=@_; -+ -+ &function_begin($name,"EXTRN _des_SPtrans:DWORD"); -+ -+ &comment(""); -+ &comment("Load the 2 words"); -+ &mov("eax",&wparam(0)); -+ &mov($L,&DWP(0,"eax","",0)); -+ &mov($R,&DWP(4,"eax","",0)); -+ -+ $ksp=&wparam(1); -+ -+ if ($do_ip) -+ { -+ &comment(""); -+ &comment("IP"); -+ &IP_new($L,$R,"eax"); -+ } -+ -+ &comment(""); -+ &comment("fixup rotate"); -+ &rotl($R,3); -+ &rotl($L,3); -+ &exch($L,$R); -+ -+ &comment(""); -+ &comment("load counter, key_schedule and enc flag"); -+ &mov("eax",&wparam(2)); # get encrypt flag -+ &mov("ebp",&wparam(1)); # get ks -+ &cmp("eax","0"); -+ &je(&label("start_decrypt")); -+ -+ # encrypting part -+ -+ for ($i=0; $i<16; $i+=2) -+ { -+ &comment(""); -+ &comment("Round $i"); -+ &D_ENCRYPT($L,$R,$i*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); -+ -+ &comment(""); -+ &comment("Round ".sprintf("%d",$i+1)); -+ &D_ENCRYPT($R,$L,($i+1)*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); -+ } -+ &jmp(&label("end")); -+ -+ &set_label("start_decrypt"); -+ -+ for ($i=15; $i>0; $i-=2) -+ { -+ &comment(""); -+ &comment("Round $i"); -+ &D_ENCRYPT($L,$R,$i*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); -+ &comment(""); -+ &comment("Round ".sprintf("%d",$i-1)); -+ &D_ENCRYPT($R,$L,($i-1)*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); -+ } -+ -+ &set_label("end"); -+ -+ &comment(""); -+ &comment("Fixup"); -+ &rotr($L,3); # r -+ &rotr($R,3); # l -+ -+ if ($do_ip) -+ { -+ &comment(""); -+ &comment("FP"); -+ &FP_new($R,$L,"eax"); -+ } -+ -+ &mov("eax",&wparam(0)); -+ &mov(&DWP(0,"eax","",0),$L); -+ &mov(&DWP(4,"eax","",0),$R); -+ -+ &function_end($name); -+ } -+ -+ -+# The logic is to load R into 2 registers and operate on both at the same time. -+# We also load the 2 R's into 2 more registers so we can do the 'move word down a byte' -+# while also masking the other copy and doing a lookup. We then also accumulate the -+# L value in 2 registers then combine them at the end. -+sub D_ENCRYPT -+ { -+ local($L,$R,$S,$ks,$desSP,$u,$t,$tmp1,$tmp2,$tmp3)=@_; -+ -+ &mov( $u, &DWP(&n2a($S*4),$ks,"",0)); -+ &mov( $t, &DWP(&n2a(($S+1)*4),$ks,"",0)); -+ &xor( $u, $R ); -+ &xor( $t, $R ); -+ &rotr( $t, 4 ); -+ -+ # the numbers at the end of the line are origional instruction order -+ &mov( $tmp2, $u ); # 1 2 -+ &mov( $tmp1, $t ); # 1 1 -+ &and( $tmp2, "0xfc" ); # 1 4 -+ &and( $tmp1, "0xfc" ); # 1 3 -+ &shr( $t, 8 ); # 1 5 -+ &xor( $L, &DWP("0x100+$desSP",$tmp1,"",0)); # 1 7 -+ &shr( $u, 8 ); # 1 6 -+ &mov( $tmp1, &DWP(" $desSP",$tmp2,"",0)); # 1 8 -+ -+ &mov( $tmp2, $u ); # 2 2 -+ &xor( $L, $tmp1 ); # 1 9 -+ &and( $tmp2, "0xfc" ); # 2 4 -+ &mov( $tmp1, $t ); # 2 1 -+ &and( $tmp1, "0xfc" ); # 2 3 -+ &shr( $t, 8 ); # 2 5 -+ &xor( $L, &DWP("0x300+$desSP",$tmp1,"",0)); # 2 7 -+ &shr( $u, 8 ); # 2 6 -+ &mov( $tmp1, &DWP("0x200+$desSP",$tmp2,"",0)); # 2 8 -+ &mov( $tmp2, $u ); # 3 2 -+ -+ &xor( $L, $tmp1 ); # 2 9 -+ &and( $tmp2, "0xfc" ); # 3 4 -+ -+ &mov( $tmp1, $t ); # 3 1 -+ &shr( $u, 8 ); # 3 6 -+ &and( $tmp1, "0xfc" ); # 3 3 -+ &shr( $t, 8 ); # 3 5 -+ &xor( $L, &DWP("0x500+$desSP",$tmp1,"",0)); # 3 7 -+ &mov( $tmp1, &DWP("0x400+$desSP",$tmp2,"",0)); # 3 8 -+ -+ &and( $t, "0xfc" ); # 4 1 -+ &xor( $L, $tmp1 ); # 3 9 -+ -+ &and( $u, "0xfc" ); # 4 2 -+ &xor( $L, &DWP("0x700+$desSP",$t,"",0)); # 4 3 -+ &xor( $L, &DWP("0x600+$desSP",$u,"",0)); # 4 4 -+ } -+ -+sub PERM_OP -+ { -+ local($a,$b,$tt,$shift,$mask)=@_; -+ -+ &mov( $tt, $a ); -+ &shr( $tt, $shift ); -+ &xor( $tt, $b ); -+ &and( $tt, $mask ); -+ &xor( $b, $tt ); -+ &shl( $tt, $shift ); -+ &xor( $a, $tt ); -+ } -+ -+sub IP_new -+ { -+ local($l,$r,$tt)=@_; -+ -+ &PERM_OP($r,$l,$tt, 4,"0x0f0f0f0f"); -+ &PERM_OP($l,$r,$tt,16,"0x0000ffff"); -+ &PERM_OP($r,$l,$tt, 2,"0x33333333"); -+ &PERM_OP($l,$r,$tt, 8,"0x00ff00ff"); -+ &PERM_OP($r,$l,$tt, 1,"0x55555555"); -+ } -+ -+sub FP_new -+ { -+ local($l,$r,$tt)=@_; -+ -+ &PERM_OP($l,$r,$tt, 1,"0x55555555"); -+ &PERM_OP($r,$l,$tt, 8,"0x00ff00ff"); -+ &PERM_OP($l,$r,$tt, 2,"0x33333333"); -+ &PERM_OP($r,$l,$tt,16,"0x0000ffff"); -+ &PERM_OP($l,$r,$tt, 4,"0x0f0f0f0f"); -+ } -+ -+sub n2a -+ { -+ sprintf("%d",$_[0]); -+ } ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/desboth.pl Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,79 @@ -+#!/usr/bin/perl -+ -+$L="edi"; -+$R="esi"; -+ -+sub des_encrypt3 -+ { -+ local($name,$enc)=@_; -+ -+ &function_begin_B($name,""); -+ &push("ebx"); -+ &mov("ebx",&wparam(0)); -+ -+ &push("ebp"); -+ &push("esi"); -+ -+ &push("edi"); -+ -+ &comment(""); -+ &comment("Load the data words"); -+ &mov($L,&DWP(0,"ebx","",0)); -+ &mov($R,&DWP(4,"ebx","",0)); -+ &stack_push(3); -+ -+ &comment(""); -+ &comment("IP"); -+ &IP_new($L,$R,"edx",0); -+ -+ # put them back -+ -+ if ($enc) -+ { -+ &mov(&DWP(4,"ebx","",0),$R); -+ &mov("eax",&wparam(1)); -+ &mov(&DWP(0,"ebx","",0),"edx"); -+ &mov("edi",&wparam(2)); -+ &mov("esi",&wparam(3)); -+ } -+ else -+ { -+ &mov(&DWP(4,"ebx","",0),$R); -+ &mov("esi",&wparam(1)); -+ &mov(&DWP(0,"ebx","",0),"edx"); -+ &mov("edi",&wparam(2)); -+ &mov("eax",&wparam(3)); -+ } -+ &mov(&swtmp(2), (($enc)?"1":"0")); -+ &mov(&swtmp(1), "eax"); -+ &mov(&swtmp(0), "ebx"); -+ &call("des_encrypt2"); -+ &mov(&swtmp(2), (($enc)?"0":"1")); -+ &mov(&swtmp(1), "edi"); -+ &mov(&swtmp(0), "ebx"); -+ &call("des_encrypt2"); -+ &mov(&swtmp(2), (($enc)?"1":"0")); -+ &mov(&swtmp(1), "esi"); -+ &mov(&swtmp(0), "ebx"); -+ &call("des_encrypt2"); -+ -+ &stack_pop(3); -+ &mov($L,&DWP(0,"ebx","",0)); -+ &mov($R,&DWP(4,"ebx","",0)); -+ -+ &comment(""); -+ &comment("FP"); -+ &FP_new($L,$R,"eax",0); -+ -+ &mov(&DWP(0,"ebx","",0),"eax"); -+ &mov(&DWP(4,"ebx","",0),$R); -+ -+ &pop("edi"); -+ &pop("esi"); -+ &pop("ebp"); -+ &pop("ebx"); -+ &ret(); -+ &function_end_B($name); -+ } -+ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/perlasm/cbc.pl Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,342 @@ -+#!/usr/bin/perl -+ -+# void des_ncbc_encrypt(input, output, length, schedule, ivec, enc) -+# des_cblock (*input); -+# des_cblock (*output); -+# long length; -+# des_key_schedule schedule; -+# des_cblock (*ivec); -+# int enc; -+# -+# calls -+# des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); -+# -+ -+#&cbc("des_ncbc_encrypt","des_encrypt",0); -+#&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt", -+# 1,4,5,3,5,-1); -+#&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt", -+# 0,4,5,3,5,-1); -+#&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3", -+# 0,6,7,3,4,5); -+# -+# When doing a cipher that needs bigendian order, -+# for encrypt, the iv is kept in bigendian form, -+# while for decrypt, it is kept in little endian. -+sub cbc -+ { -+ local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_; -+ # name is the function name -+ # enc_func and dec_func and the functions to call for encrypt/decrypt -+ # swap is true if byte order needs to be reversed -+ # iv_off is parameter number for the iv -+ # enc_off is parameter number for the encrypt/decrypt flag -+ # p1,p2,p3 are the offsets for parameters to be passed to the -+ # underlying calls. -+ -+ &function_begin_B($name,""); -+ &comment(""); -+ -+ $in="esi"; -+ $out="edi"; -+ $count="ebp"; -+ -+ &push("ebp"); -+ &push("ebx"); -+ &push("esi"); -+ &push("edi"); -+ -+ $data_off=4; -+ $data_off+=4 if ($p1 > 0); -+ $data_off+=4 if ($p2 > 0); -+ $data_off+=4 if ($p3 > 0); -+ -+ &mov($count, &wparam(2)); # length -+ -+ &comment("getting iv ptr from parameter $iv_off"); -+ &mov("ebx", &wparam($iv_off)); # Get iv ptr -+ -+ &mov($in, &DWP(0,"ebx","",0));# iv[0] -+ &mov($out, &DWP(4,"ebx","",0));# iv[1] -+ -+ &push($out); -+ &push($in); -+ &push($out); # used in decrypt for iv[1] -+ &push($in); # used in decrypt for iv[0] -+ -+ &mov("ebx", "esp"); # This is the address of tin[2] -+ -+ &mov($in, &wparam(0)); # in -+ &mov($out, &wparam(1)); # out -+ -+ # We have loaded them all, how lets push things -+ &comment("getting encrypt flag from parameter $enc_off"); -+ &mov("ecx", &wparam($enc_off)); # Get enc flag -+ if ($p3 > 0) -+ { -+ &comment("get and push parameter $p3"); -+ if ($enc_off != $p3) -+ { &mov("eax", &wparam($p3)); &push("eax"); } -+ else { &push("ecx"); } -+ } -+ if ($p2 > 0) -+ { -+ &comment("get and push parameter $p2"); -+ if ($enc_off != $p2) -+ { &mov("eax", &wparam($p2)); &push("eax"); } -+ else { &push("ecx"); } -+ } -+ if ($p1 > 0) -+ { -+ &comment("get and push parameter $p1"); -+ if ($enc_off != $p1) -+ { &mov("eax", &wparam($p1)); &push("eax"); } -+ else { &push("ecx"); } -+ } -+ &push("ebx"); # push data/iv -+ -+ &cmp("ecx",0); -+ &jz(&label("decrypt")); -+ -+ &and($count,0xfffffff8); -+ &mov("eax", &DWP($data_off,"esp","",0)); # load iv[0] -+ &mov("ebx", &DWP($data_off+4,"esp","",0)); # load iv[1] -+ -+ &jz(&label("encrypt_finish")); -+ -+ ############################################################# -+ -+ &set_label("encrypt_loop"); -+ # encrypt start -+ # "eax" and "ebx" hold iv (or the last cipher text) -+ -+ &mov("ecx", &DWP(0,$in,"",0)); # load first 4 bytes -+ &mov("edx", &DWP(4,$in,"",0)); # second 4 bytes -+ -+ &xor("eax", "ecx"); -+ &xor("ebx", "edx"); -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call -+ &mov(&DWP($data_off+4,"esp","",0), "ebx"); # -+ -+ &call($enc_func); -+ -+ &mov("eax", &DWP($data_off,"esp","",0)); -+ &mov("ebx", &DWP($data_off+4,"esp","",0)); -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov(&DWP(0,$out,"",0),"eax"); -+ &mov(&DWP(4,$out,"",0),"ebx"); -+ -+ # eax and ebx are the next iv. -+ -+ &add($in, 8); -+ &add($out, 8); -+ -+ &sub($count, 8); -+ &jnz(&label("encrypt_loop")); -+ -+###################################################################3 -+ &set_label("encrypt_finish"); -+ &mov($count, &wparam(2)); # length -+ &and($count, 7); -+ &jz(&label("finish")); -+ &xor("ecx","ecx"); -+ &xor("edx","edx"); -+ &mov($count,&DWP(&label("cbc_enc_jmp_table"),"",$count,4)); -+ &jmp_ptr($count); -+ -+&set_label("ej7"); -+ &xor("edx", "edx") if $ppro; # ppro friendly -+ &movb(&HB("edx"), &BP(6,$in,"",0)); -+ &shl("edx",8); -+&set_label("ej6"); -+ &movb(&HB("edx"), &BP(5,$in,"",0)); -+&set_label("ej5"); -+ &movb(&LB("edx"), &BP(4,$in,"",0)); -+&set_label("ej4"); -+ &mov("ecx", &DWP(0,$in,"",0)); -+ &jmp(&label("ejend")); -+&set_label("ej3"); -+ &movb(&HB("ecx"), &BP(2,$in,"",0)); -+ &xor("ecx", "ecx") if $ppro; # ppro friendly -+ &shl("ecx",8); -+&set_label("ej2"); -+ &movb(&HB("ecx"), &BP(1,$in,"",0)); -+&set_label("ej1"); -+ &movb(&LB("ecx"), &BP(0,$in,"",0)); -+&set_label("ejend"); -+ -+ &xor("eax", "ecx"); -+ &xor("ebx", "edx"); -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call -+ &mov(&DWP($data_off+4,"esp","",0), "ebx"); # -+ -+ &call($enc_func); -+ -+ &mov("eax", &DWP($data_off,"esp","",0)); -+ &mov("ebx", &DWP($data_off+4,"esp","",0)); -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov(&DWP(0,$out,"",0),"eax"); -+ &mov(&DWP(4,$out,"",0),"ebx"); -+ -+ &jmp(&label("finish")); -+ -+ ############################################################# -+ ############################################################# -+ &set_label("decrypt",1); -+ # decrypt start -+ &and($count,0xfffffff8); -+ # The next 2 instructions are only for if the jz is taken -+ &mov("eax", &DWP($data_off+8,"esp","",0)); # get iv[0] -+ &mov("ebx", &DWP($data_off+12,"esp","",0)); # get iv[1] -+ &jz(&label("decrypt_finish")); -+ -+ &set_label("decrypt_loop"); -+ &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes -+ &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov(&DWP($data_off,"esp","",0), "eax"); # put back -+ &mov(&DWP($data_off+4,"esp","",0), "ebx"); # -+ -+ &call($dec_func); -+ -+ &mov("eax", &DWP($data_off,"esp","",0)); # get return -+ &mov("ebx", &DWP($data_off+4,"esp","",0)); # -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] -+ &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] -+ -+ &xor("ecx", "eax"); -+ &xor("edx", "ebx"); -+ -+ &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, -+ &mov("ebx", &DWP(4,$in,"",0)); # next iv actually -+ -+ &mov(&DWP(0,$out,"",0),"ecx"); -+ &mov(&DWP(4,$out,"",0),"edx"); -+ -+ &mov(&DWP($data_off+8,"esp","",0), "eax"); # save iv -+ &mov(&DWP($data_off+12,"esp","",0), "ebx"); # -+ -+ &add($in, 8); -+ &add($out, 8); -+ -+ &sub($count, 8); -+ &jnz(&label("decrypt_loop")); -+############################ ENDIT #######################3 -+ &set_label("decrypt_finish"); -+ &mov($count, &wparam(2)); # length -+ &and($count, 7); -+ &jz(&label("finish")); -+ -+ &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes -+ &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov(&DWP($data_off,"esp","",0), "eax"); # put back -+ &mov(&DWP($data_off+4,"esp","",0), "ebx"); # -+ -+ &call($dec_func); -+ -+ &mov("eax", &DWP($data_off,"esp","",0)); # get return -+ &mov("ebx", &DWP($data_off+4,"esp","",0)); # -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] -+ &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] -+ -+ &xor("ecx", "eax"); -+ &xor("edx", "ebx"); -+ -+ # this is for when we exit -+ &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, -+ &mov("ebx", &DWP(4,$in,"",0)); # next iv actually -+ -+&set_label("dj7"); -+ &rotr("edx", 16); -+ &movb(&BP(6,$out,"",0), &LB("edx")); -+ &shr("edx",16); -+&set_label("dj6"); -+ &movb(&BP(5,$out,"",0), &HB("edx")); -+&set_label("dj5"); -+ &movb(&BP(4,$out,"",0), &LB("edx")); -+&set_label("dj4"); -+ &mov(&DWP(0,$out,"",0), "ecx"); -+ &jmp(&label("djend")); -+&set_label("dj3"); -+ &rotr("ecx", 16); -+ &movb(&BP(2,$out,"",0), &LB("ecx")); -+ &shl("ecx",16); -+&set_label("dj2"); -+ &movb(&BP(1,$in,"",0), &HB("ecx")); -+&set_label("dj1"); -+ &movb(&BP(0,$in,"",0), &LB("ecx")); -+&set_label("djend"); -+ -+ # final iv is still in eax:ebx -+ &jmp(&label("finish")); -+ -+ -+############################ FINISH #######################3 -+ &set_label("finish",1); -+ &mov("ecx", &wparam($iv_off)); # Get iv ptr -+ -+ ################################################# -+ $total=16+4; -+ $total+=4 if ($p1 > 0); -+ $total+=4 if ($p2 > 0); -+ $total+=4 if ($p3 > 0); -+ &add("esp",$total); -+ -+ &mov(&DWP(0,"ecx","",0), "eax"); # save iv -+ &mov(&DWP(4,"ecx","",0), "ebx"); # save iv -+ -+ &function_end_A($name); -+ -+ &set_label("cbc_enc_jmp_table",1); -+ &data_word("0"); -+ &data_word(&label("ej1")); -+ &data_word(&label("ej2")); -+ &data_word(&label("ej3")); -+ &data_word(&label("ej4")); -+ &data_word(&label("ej5")); -+ &data_word(&label("ej6")); -+ &data_word(&label("ej7")); -+ &set_label("cbc_dec_jmp_table",1); -+ &data_word("0"); -+ &data_word(&label("dj1")); -+ &data_word(&label("dj2")); -+ &data_word(&label("dj3")); -+ &data_word(&label("dj4")); -+ &data_word(&label("dj5")); -+ &data_word(&label("dj6")); -+ &data_word(&label("dj7")); -+ -+ &function_end_B($name); -+ -+ } -+ -+1; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/perlasm/readme Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,124 @@ -+The perl scripts in this directory are my 'hack' to generate -+multiple different assembler formats via the one origional script. -+ -+The way to use this library is to start with adding the path to this directory -+and then include it. -+ -+push(@INC,"perlasm","../../perlasm"); -+require "x86asm.pl"; -+ -+The first thing we do is setup the file and type of assember -+ -+&asm_init($ARGV[0],$0); -+ -+The first argument is the 'type'. Currently -+'cpp', 'sol', 'a.out', 'elf' or 'win32'. -+Argument 2 is the file name. -+ -+The reciprocal function is -+&asm_finish() which should be called at the end. -+ -+There are 2 main 'packages'. x86ms.pl, which is the microsoft assembler, -+and x86unix.pl which is the unix (gas) version. -+ -+Functions of interest are: -+&external_label("des_SPtrans"); declare and external variable -+&LB(reg); Low byte for a register -+&HB(reg); High byte for a register -+&BP(off,base,index,scale) Byte pointer addressing -+&DWP(off,base,index,scale) Word pointer addressing -+&stack_push(num) Basically a 'sub esp, num*4' with extra -+&stack_pop(num) inverse of stack_push -+&function_begin(name,extra) Start a function with pushing of -+ edi, esi, ebx and ebp. extra is extra win32 -+ external info that may be required. -+&function_begin_B(name,extra) Same as norma function_begin but no pushing. -+&function_end(name) Call at end of function. -+&function_end_A(name) Standard pop and ret, for use inside functions -+&function_end_B(name) Call at end but with poping or 'ret'. -+&swtmp(num) Address on stack temp word. -+&wparam(num) Parameter number num, that was push -+ in C convention. This all works over pushes -+ and pops. -+&comment("hello there") Put in a comment. -+&label("loop") Refer to a label, normally a jmp target. -+&set_label("loop") Set a label at this point. -+&data_word(word) Put in a word of data. -+ -+So how does this all hold together? Given -+ -+int calc(int len, int *data) -+ { -+ int i,j=0; -+ -+ for (i=0; i"); -+&comment(""); -+ -+ $filename =~ s/\.pl$//; -+ &file($filename); -+ } -+ -+sub asm_finish_cpp -+ { -+ return unless $cpp; -+ -+ local($tmp,$i); -+ foreach $i (&get_labels()) -+ { -+ $tmp.="#define $i _$i\n"; -+ } -+ print <<"EOF"; -+/* Run the C pre-processor over this file with one of the following defined -+ * ELF - elf object files, -+ * OUT - a.out object files, -+ * BSDI - BSDI style a.out object files -+ * SOL - Solaris style elf -+ */ -+ -+#define TYPE(a,b) .type a,b -+#define SIZE(a,b) .size a,b -+ -+#if defined(OUT) || defined(BSDI) -+$tmp -+#endif -+ -+#ifdef OUT -+#define OK 1 -+#define ALIGN 4 -+#endif -+ -+#ifdef BSDI -+#define OK 1 -+#define ALIGN 4 -+#undef SIZE -+#undef TYPE -+#endif -+ -+#if defined(ELF) || defined(SOL) -+#define OK 1 -+#define ALIGN 16 -+#endif -+ -+#ifndef OK -+You need to define one of -+ELF - elf systems - linux-elf, NetBSD and DG-UX -+OUT - a.out systems - linux-a.out and FreeBSD -+SOL - solaris systems, which are elf with strange comment lines -+BSDI - a.out with a very primative version of as. -+#endif -+ -+/* Let the Assembler begin :-) */ -+EOF -+ } -+ -+1; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/perlasm/x86ms.pl Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,345 @@ -+#!/usr/bin/perl -+ -+package x86ms; -+ -+$label="L000"; -+ -+%lb=( 'eax', 'al', -+ 'ebx', 'bl', -+ 'ecx', 'cl', -+ 'edx', 'dl', -+ 'ax', 'al', -+ 'bx', 'bl', -+ 'cx', 'cl', -+ 'dx', 'dl', -+ ); -+ -+%hb=( 'eax', 'ah', -+ 'ebx', 'bh', -+ 'ecx', 'ch', -+ 'edx', 'dh', -+ 'ax', 'ah', -+ 'bx', 'bh', -+ 'cx', 'ch', -+ 'dx', 'dh', -+ ); -+ -+sub main'asm_init_output { @out=(); } -+sub main'asm_get_output { return(@out); } -+sub main'get_labels { return(@labels); } -+sub main'external_label { push(@labels,@_); } -+ -+sub main'LB -+ { -+ (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n"; -+ return($lb{$_[0]}); -+ } -+ -+sub main'HB -+ { -+ (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n"; -+ return($hb{$_[0]}); -+ } -+ -+sub main'BP -+ { -+ &get_mem("BYTE",@_); -+ } -+ -+sub main'DWP -+ { -+ &get_mem("DWORD",@_); -+ } -+ -+sub main'stack_push -+ { -+ local($num)=@_; -+ $stack+=$num*4; -+ &main'sub("esp",$num*4); -+ } -+ -+sub main'stack_pop -+ { -+ local($num)=@_; -+ $stack-=$num*4; -+ &main'add("esp",$num*4); -+ } -+ -+sub get_mem -+ { -+ local($size,$addr,$reg1,$reg2,$idx)=@_; -+ local($t,$post); -+ local($ret)="$size PTR "; -+ -+ $addr =~ s/^\s+//; -+ if ($addr =~ /^(.+)\+(.+)$/) -+ { -+ $reg2=&conv($1); -+ $addr="_$2"; -+ } -+ elsif ($addr =~ /^[_a-zA-Z]/) -+ { -+ $addr="_$addr"; -+ } -+ -+ $reg1="$regs{$reg1}" if defined($regs{$reg1}); -+ $reg2="$regs{$reg2}" if defined($regs{$reg2}); -+ if (($addr ne "") && ($addr ne 0)) -+ { -+ if ($addr !~ /^-/) -+ { $ret.=$addr; } -+ else { $post=$addr; } -+ } -+ if ($reg2 ne "") -+ { -+ $t=""; -+ $t="*$idx" if ($idx != 0); -+ $reg1="+".$reg1 if ("$reg1$post" ne ""); -+ $ret.="[$reg2$t$reg1$post]"; -+ } -+ else -+ { -+ $ret.="[$reg1$post]" -+ } -+ return($ret); -+ } -+ -+sub main'mov { &out2("mov",@_); } -+sub main'movb { &out2("mov",@_); } -+sub main'and { &out2("and",@_); } -+sub main'or { &out2("or",@_); } -+sub main'shl { &out2("shl",@_); } -+sub main'shr { &out2("shr",@_); } -+sub main'xor { &out2("xor",@_); } -+sub main'xorb { &out2("xor",@_); } -+sub main'add { &out2("add",@_); } -+sub main'adc { &out2("adc",@_); } -+sub main'sub { &out2("sub",@_); } -+sub main'rotl { &out2("rol",@_); } -+sub main'rotr { &out2("ror",@_); } -+sub main'exch { &out2("xchg",@_); } -+sub main'cmp { &out2("cmp",@_); } -+sub main'lea { &out2("lea",@_); } -+sub main'mul { &out1("mul",@_); } -+sub main'div { &out1("div",@_); } -+sub main'dec { &out1("dec",@_); } -+sub main'inc { &out1("inc",@_); } -+sub main'jmp { &out1("jmp",@_); } -+sub main'jmp_ptr { &out1p("jmp",@_); } -+sub main'je { &out1("je",@_); } -+sub main'jle { &out1("jle",@_); } -+sub main'jz { &out1("jz",@_); } -+sub main'jge { &out1("jge",@_); } -+sub main'jl { &out1("jl",@_); } -+sub main'jb { &out1("jb",@_); } -+sub main'jnz { &out1("jnz",@_); } -+sub main'jne { &out1("jne",@_); } -+sub main'push { &out1("push",@_); $stack+=4; } -+sub main'pop { &out1("pop",@_); $stack-=4; } -+sub main'bswap { &out1("bswap",@_); &using486(); } -+sub main'not { &out1("not",@_); } -+sub main'call { &out1("call",'_'.$_[0]); } -+sub main'ret { &out0("ret"); } -+sub main'nop { &out0("nop"); } -+ -+sub out2 -+ { -+ local($name,$p1,$p2)=@_; -+ local($l,$t); -+ -+ push(@out,"\t$name\t"); -+ $t=&conv($p1).","; -+ $l=length($t); -+ push(@out,$t); -+ $l=4-($l+9)/8; -+ push(@out,"\t" x $l); -+ push(@out,&conv($p2)); -+ push(@out,"\n"); -+ } -+ -+sub out0 -+ { -+ local($name)=@_; -+ -+ push(@out,"\t$name\n"); -+ } -+ -+sub out1 -+ { -+ local($name,$p1)=@_; -+ local($l,$t); -+ -+ push(@out,"\t$name\t".&conv($p1)."\n"); -+ } -+ -+sub conv -+ { -+ local($p)=@_; -+ -+ $p =~ s/0x([0-9A-Fa-f]+)/0$1h/; -+ return $p; -+ } -+ -+sub using486 -+ { -+ return if $using486; -+ $using486++; -+ grep(s/\.386/\.486/,@out); -+ } -+ -+sub main'file -+ { -+ local($file)=@_; -+ -+ local($tmp)=<<"EOF"; -+ TITLE $file.asm -+ .386 -+.model FLAT -+EOF -+ push(@out,$tmp); -+ } -+ -+sub main'function_begin -+ { -+ local($func,$extra)=@_; -+ -+ push(@labels,$func); -+ -+ local($tmp)=<<"EOF"; -+_TEXT SEGMENT -+PUBLIC _$func -+$extra -+_$func PROC NEAR -+ push ebp -+ push ebx -+ push esi -+ push edi -+EOF -+ push(@out,$tmp); -+ $stack=20; -+ } -+ -+sub main'function_begin_B -+ { -+ local($func,$extra)=@_; -+ -+ local($tmp)=<<"EOF"; -+_TEXT SEGMENT -+PUBLIC _$func -+$extra -+_$func PROC NEAR -+EOF -+ push(@out,$tmp); -+ $stack=4; -+ } -+ -+sub main'function_end -+ { -+ local($func)=@_; -+ -+ local($tmp)=<<"EOF"; -+ pop edi -+ pop esi -+ pop ebx -+ pop ebp -+ ret -+_$func ENDP -+_TEXT ENDS -+EOF -+ push(@out,$tmp); -+ $stack=0; -+ %label=(); -+ } -+ -+sub main'function_end_B -+ { -+ local($func)=@_; -+ -+ local($tmp)=<<"EOF"; -+_$func ENDP -+_TEXT ENDS -+EOF -+ push(@out,$tmp); -+ $stack=0; -+ %label=(); -+ } -+ -+sub main'function_end_A -+ { -+ local($func)=@_; -+ -+ local($tmp)=<<"EOF"; -+ pop edi -+ pop esi -+ pop ebx -+ pop ebp -+ ret -+EOF -+ push(@out,$tmp); -+ } -+ -+sub main'file_end -+ { -+ push(@out,"END\n"); -+ } -+ -+sub main'wparam -+ { -+ local($num)=@_; -+ -+ return(&main'DWP($stack+$num*4,"esp","",0)); -+ } -+ -+sub main'swtmp -+ { -+ return(&main'DWP($_[0]*4,"esp","",0)); -+ } -+ -+# Should use swtmp, which is above esp. Linix can trash the stack above esp -+#sub main'wtmp -+# { -+# local($num)=@_; -+# -+# return(&main'DWP(-(($num+1)*4),"esp","",0)); -+# } -+ -+sub main'comment -+ { -+ foreach (@_) -+ { -+ push(@out,"\t; $_\n"); -+ } -+ } -+ -+sub main'label -+ { -+ if (!defined($label{$_[0]})) -+ { -+ $label{$_[0]}="\$${label}${_[0]}"; -+ $label++; -+ } -+ return($label{$_[0]}); -+ } -+ -+sub main'set_label -+ { -+ if (!defined($label{$_[0]})) -+ { -+ $label{$_[0]}="${label}${_[0]}"; -+ $label++; -+ } -+ push(@out,"$label{$_[0]}:\n"); -+ } -+ -+sub main'data_word -+ { -+ push(@out,"\tDD\t$_[0]\n"); -+ } -+ -+sub out1p -+ { -+ local($name,$p1)=@_; -+ local($l,$t); -+ -+ push(@out,"\t$name\t ".&conv($p1)."\n"); -+ } ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/perlasm/x86unix.pl Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,403 @@ -+#!/usr/bin/perl -+ -+package x86unix; -+ -+$label="L000"; -+ -+$align=($main'aout)?"4":"16"; -+$under=($main'aout)?"_":""; -+$com_start=($main'sol)?"/":"#"; -+ -+sub main'asm_init_output { @out=(); } -+sub main'asm_get_output { return(@out); } -+sub main'get_labels { return(@labels); } -+sub main'external_label { push(@labels,@_); } -+ -+if ($main'cpp) -+ { -+ $align="ALIGN"; -+ $under=""; -+ $com_start='/*'; -+ $com_end='*/'; -+ } -+ -+%lb=( 'eax', '%al', -+ 'ebx', '%bl', -+ 'ecx', '%cl', -+ 'edx', '%dl', -+ 'ax', '%al', -+ 'bx', '%bl', -+ 'cx', '%cl', -+ 'dx', '%dl', -+ ); -+ -+%hb=( 'eax', '%ah', -+ 'ebx', '%bh', -+ 'ecx', '%ch', -+ 'edx', '%dh', -+ 'ax', '%ah', -+ 'bx', '%bh', -+ 'cx', '%ch', -+ 'dx', '%dh', -+ ); -+ -+%regs=( 'eax', '%eax', -+ 'ebx', '%ebx', -+ 'ecx', '%ecx', -+ 'edx', '%edx', -+ 'esi', '%esi', -+ 'edi', '%edi', -+ 'ebp', '%ebp', -+ 'esp', '%esp', -+ ); -+ -+%reg_val=( -+ 'eax', 0x00, -+ 'ebx', 0x03, -+ 'ecx', 0x01, -+ 'edx', 0x02, -+ 'esi', 0x06, -+ 'edi', 0x07, -+ 'ebp', 0x05, -+ 'esp', 0x04, -+ ); -+ -+sub main'LB -+ { -+ (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n"; -+ return($lb{$_[0]}); -+ } -+ -+sub main'HB -+ { -+ (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n"; -+ return($hb{$_[0]}); -+ } -+ -+sub main'DWP -+ { -+ local($addr,$reg1,$reg2,$idx)=@_; -+ -+ $ret=""; -+ $addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/; -+ $reg1="$regs{$reg1}" if defined($regs{$reg1}); -+ $reg2="$regs{$reg2}" if defined($regs{$reg2}); -+ $ret.=$addr if ($addr ne "") && ($addr ne 0); -+ if ($reg2 ne "") -+ { $ret.="($reg1,$reg2,$idx)"; } -+ else -+ { $ret.="($reg1)" } -+ return($ret); -+ } -+ -+sub main'BP -+ { -+ return(&main'DWP(@_)); -+ } -+ -+#sub main'BP -+# { -+# local($addr,$reg1,$reg2,$idx)=@_; -+# -+# $ret=""; -+# -+# $addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/; -+# $reg1="$regs{$reg1}" if defined($regs{$reg1}); -+# $reg2="$regs{$reg2}" if defined($regs{$reg2}); -+# $ret.=$addr if ($addr ne "") && ($addr ne 0); -+# if ($reg2 ne "") -+# { $ret.="($reg1,$reg2,$idx)"; } -+# else -+# { $ret.="($reg1)" } -+# return($ret); -+# } -+ -+sub main'mov { &out2("movl",@_); } -+sub main'movb { &out2("movb",@_); } -+sub main'and { &out2("andl",@_); } -+sub main'or { &out2("orl",@_); } -+sub main'shl { &out2("sall",@_); } -+sub main'shr { &out2("shrl",@_); } -+sub main'xor { &out2("xorl",@_); } -+sub main'xorb { &out2("xorb",@_); } -+sub main'add { &out2("addl",@_); } -+sub main'adc { &out2("adcl",@_); } -+sub main'sub { &out2("subl",@_); } -+sub main'rotl { &out2("roll",@_); } -+sub main'rotr { &out2("rorl",@_); } -+sub main'exch { &out2("xchg",@_); } -+sub main'cmp { &out2("cmpl",@_); } -+sub main'lea { &out2("leal",@_); } -+sub main'mul { &out1("mull",@_); } -+sub main'div { &out1("divl",@_); } -+sub main'jmp { &out1("jmp",@_); } -+sub main'jmp_ptr { &out1p("jmp",@_); } -+sub main'je { &out1("je",@_); } -+sub main'jle { &out1("jle",@_); } -+sub main'jne { &out1("jne",@_); } -+sub main'jnz { &out1("jnz",@_); } -+sub main'jz { &out1("jz",@_); } -+sub main'jge { &out1("jge",@_); } -+sub main'jl { &out1("jl",@_); } -+sub main'jb { &out1("jb",@_); } -+sub main'dec { &out1("decl",@_); } -+sub main'inc { &out1("incl",@_); } -+sub main'push { &out1("pushl",@_); $stack+=4; } -+sub main'pop { &out1("popl",@_); $stack-=4; } -+sub main'bswap { &out1("bswapl",@_); } -+sub main'not { &out1("notl",@_); } -+sub main'call { &out1("call",$under.$_[0]); } -+sub main'ret { &out0("ret"); } -+sub main'nop { &out0("nop"); } -+ -+sub out2 -+ { -+ local($name,$p1,$p2)=@_; -+ local($l,$ll,$t); -+ local(%special)=( "roll",0xD1C0,"rorl",0xD1C8, -+ "rcll",0xD1D0,"rcrl",0xD1D8, -+ "shll",0xD1E0,"shrl",0xD1E8, -+ "sarl",0xD1F8); -+ -+ if ((defined($special{$name})) && defined($regs{$p1}) && ($p2 == 1)) -+ { -+ $op=$special{$name}|$reg_val{$p1}; -+ $tmp1=sprintf ".byte %d\n",($op>>8)&0xff; -+ $tmp2=sprintf ".byte %d\t",$op &0xff; -+ push(@out,$tmp1); -+ push(@out,$tmp2); -+ -+ $p2=&conv($p2); -+ $p1=&conv($p1); -+ &main'comment("$name $p2 $p1"); -+ return; -+ } -+ -+ push(@out,"\t$name\t"); -+ $t=&conv($p2).","; -+ $l=length($t); -+ push(@out,$t); -+ $ll=4-($l+9)/8; -+ $tmp1=sprintf "\t" x $ll; -+ push(@out,$tmp1); -+ push(@out,&conv($p1)."\n"); -+ } -+ -+sub out1 -+ { -+ local($name,$p1)=@_; -+ local($l,$t); -+ -+ push(@out,"\t$name\t".&conv($p1)."\n"); -+ } -+ -+sub out1p -+ { -+ local($name,$p1)=@_; -+ local($l,$t); -+ -+ push(@out,"\t$name\t*".&conv($p1)."\n"); -+ } -+ -+sub out0 -+ { -+ push(@out,"\t$_[0]\n"); -+ } -+ -+sub conv -+ { -+ local($p)=@_; -+ -+# $p =~ s/0x([0-9A-Fa-f]+)/0$1h/; -+ -+ $p=$regs{$p} if (defined($regs{$p})); -+ -+ $p =~ s/^(-{0,1}[0-9A-Fa-f]+)$/\$$1/; -+ $p =~ s/^(0x[0-9A-Fa-f]+)$/\$$1/; -+ return $p; -+ } -+ -+sub main'file -+ { -+ local($file)=@_; -+ -+ local($tmp)=<<"EOF"; -+ .file "$file.s" -+ .version "01.01" -+gcc2_compiled.: -+EOF -+ push(@out,$tmp); -+ } -+ -+sub main'function_begin -+ { -+ local($func)=@_; -+ -+ $func=$under.$func; -+ -+ local($tmp)=<<"EOF"; -+.text -+ .align $align -+.globl $func -+EOF -+ push(@out,$tmp); -+ if ($main'cpp) -+ { $tmp=push(@out,"\tTYPE($func,\@function)\n"); } -+ else { $tmp=push(@out,"\t.type\t$func,\@function\n"); } -+ push(@out,"$func:\n"); -+ $tmp=<<"EOF"; -+ pushl %ebp -+ pushl %ebx -+ pushl %esi -+ pushl %edi -+ -+EOF -+ push(@out,$tmp); -+ $stack=20; -+ } -+ -+sub main'function_begin_B -+ { -+ local($func,$extra)=@_; -+ -+ $func=$under.$func; -+ -+ local($tmp)=<<"EOF"; -+.text -+ .align $align -+.globl $func -+EOF -+ push(@out,$tmp); -+ if ($main'cpp) -+ { push(@out,"\tTYPE($func,\@function)\n"); } -+ else { push(@out,"\t.type $func,\@function\n"); } -+ push(@out,"$func:\n"); -+ $stack=4; -+ } -+ -+sub main'function_end -+ { -+ local($func)=@_; -+ -+ $func=$under.$func; -+ -+ local($tmp)=<<"EOF"; -+ popl %edi -+ popl %esi -+ popl %ebx -+ popl %ebp -+ ret -+.${func}_end: -+EOF -+ push(@out,$tmp); -+ if ($main'cpp) -+ { push(@out,"\tSIZE($func,.${func}_end-$func)\n"); } -+ else { push(@out,"\t.size\t$func,.${func}_end-$func\n"); } -+ push(@out,".ident \"$func\"\n"); -+ $stack=0; -+ %label=(); -+ } -+ -+sub main'function_end_A -+ { -+ local($func)=@_; -+ -+ local($tmp)=<<"EOF"; -+ popl %edi -+ popl %esi -+ popl %ebx -+ popl %ebp -+ ret -+EOF -+ push(@out,$tmp); -+ } -+ -+sub main'function_end_B -+ { -+ local($func)=@_; -+ -+ $func=$under.$func; -+ -+ push(@out,".${func}_end:\n"); -+ if ($main'cpp) -+ { push(@out,"\tSIZE($func,.${func}_end-$func)\n"); } -+ else { push(@out,"\t.size\t$func,.${func}_end-$func\n"); } -+ push(@out,".ident \"desasm.pl\"\n"); -+ $stack=0; -+ %label=(); -+ } -+ -+sub main'wparam -+ { -+ local($num)=@_; -+ -+ return(&main'DWP($stack+$num*4,"esp","",0)); -+ } -+ -+sub main'stack_push -+ { -+ local($num)=@_; -+ $stack+=$num*4; -+ &main'sub("esp",$num*4); -+ } -+ -+sub main'stack_pop -+ { -+ local($num)=@_; -+ $stack-=$num*4; -+ &main'add("esp",$num*4); -+ } -+ -+sub main'swtmp -+ { -+ return(&main'DWP($_[0]*4,"esp","",0)); -+ } -+ -+# Should use swtmp, which is above esp. Linix can trash the stack above esp -+#sub main'wtmp -+# { -+# local($num)=@_; -+# -+# return(&main'DWP(-($num+1)*4,"esp","",0)); -+# } -+ -+sub main'comment -+ { -+ foreach (@_) -+ { -+ if (/^\s*$/) -+ { push(@out,"\n"); } -+ else -+ { push(@out,"\t$com_start $_ $com_end\n"); } -+ } -+ } -+ -+sub main'label -+ { -+ if (!defined($label{$_[0]})) -+ { -+ $label{$_[0]}=".${label}${_[0]}"; -+ $label++; -+ } -+ return($label{$_[0]}); -+ } -+ -+sub main'set_label -+ { -+ if (!defined($label{$_[0]})) -+ { -+ $label{$_[0]}=".${label}${_[0]}"; -+ $label++; -+ } -+ push(@out,".align $align\n") if ($_[1] != 0); -+ push(@out,"$label{$_[0]}:\n"); -+ } -+ -+sub main'file_end -+ { -+ } -+ -+sub main'data_word -+ { -+ push(@out,"\t.long $_[0]\n"); -+ } ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/readme Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,131 @@ -+First up, let me say I don't like writing in assembler. It is not portable, -+dependant on the particular CPU architecture release and is generally a pig -+to debug and get right. Having said that, the x86 architecture is probably -+the most important for speed due to number of boxes and since -+it appears to be the worst architecture to to get -+good C compilers for. So due to this, I have lowered myself to do -+assembler for the inner DES routines in libdes :-). -+ -+The file to implement in assembler is des_enc.c. Replace the following -+4 functions -+des_encrypt(DES_LONG data[2],des_key_schedule ks, int encrypt); -+des_encrypt2(DES_LONG data[2],des_key_schedule ks, int encrypt); -+des_encrypt3(DES_LONG data[2],des_key_schedule ks1,ks2,ks3); -+des_decrypt3(DES_LONG data[2],des_key_schedule ks1,ks2,ks3); -+ -+They encrypt/decrypt the 64 bits held in 'data' using -+the 'ks' key schedules. The only difference between the 4 functions is that -+des_encrypt2() does not perform IP() or FP() on the data (this is an -+optimization for when doing triple DES and des_encrypt3() and des_decrypt3() -+perform triple des. The triple DES routines are in here because it does -+make a big difference to have them located near the des_encrypt2 function -+at link time.. -+ -+Now as we all know, there are lots of different operating systems running on -+x86 boxes, and unfortunately they normally try to make sure their assembler -+formating is not the same as the other peoples. -+The 4 main formats I know of are -+Microsoft Windows 95/Windows NT -+Elf Includes Linux and FreeBSD(?). -+a.out The older Linux. -+Solaris Same as Elf but different comments :-(. -+ -+Now I was not overly keen to write 4 different copies of the same code, -+so I wrote a few perl routines to output the correct assembler, given -+a target assembler type. This code is ugly and is just a hack. -+The libraries are x86unix.pl and x86ms.pl. -+des586.pl, des686.pl and des-som[23].pl are the programs to actually -+generate the assembler. -+ -+So to generate elf assembler -+perl des-som3.pl elf >dx86-elf.s -+For Windows 95/NT -+perl des-som2.pl win32 >win32.asm -+ -+[ update 4 Jan 1996 ] -+I have added another way to do things. -+perl des-som3.pl cpp >dx86-cpp.s -+generates a file that will be included by dx86unix.cpp when it is compiled. -+To build for elf, a.out, solaris, bsdi etc, -+cc -E -DELF asm/dx86unix.cpp | as -o asm/dx86-elf.o -+cc -E -DSOL asm/dx86unix.cpp | as -o asm/dx86-sol.o -+cc -E -DOUT asm/dx86unix.cpp | as -o asm/dx86-out.o -+cc -E -DBSDI asm/dx86unix.cpp | as -o asm/dx86bsdi.o -+This was done to cut down the number of files in the distribution. -+ -+Now the ugly part. I acquired my copy of Intels -+"Optimization's For Intel's 32-Bit Processors" and found a few interesting -+things. First, the aim of the exersize is to 'extract' one byte at a time -+from a word and do an array lookup. This involves getting the byte from -+the 4 locations in the word and moving it to a new word and doing the lookup. -+The most obvious way to do this is -+xor eax, eax # clear word -+movb al, cl # get low byte -+xor edi DWORD PTR 0x100+des_SP[eax] # xor in word -+movb al, ch # get next byte -+xor edi DWORD PTR 0x300+des_SP[eax] # xor in word -+shr ecx 16 -+which seems ok. For the pentium, this system appears to be the best. -+One has to do instruction interleaving to keep both functional units -+operating, but it is basically very efficient. -+ -+Now the crunch. When a full register is used after a partial write, eg. -+mov al, cl -+xor edi, DWORD PTR 0x100+des_SP[eax] -+386 - 1 cycle stall -+486 - 1 cycle stall -+586 - 0 cycle stall -+686 - at least 7 cycle stall (page 22 of the above mentioned document). -+ -+So the technique that produces the best results on a pentium, according to -+the documentation, will produce hideous results on a pentium pro. -+ -+To get around this, des686.pl will generate code that is not as fast on -+a pentium, should be very good on a pentium pro. -+mov eax, ecx # copy word -+shr ecx, 8 # line up next byte -+and eax, 0fch # mask byte -+xor edi DWORD PTR 0x100+des_SP[eax] # xor in array lookup -+mov eax, ecx # get word -+shr ecx 8 # line up next byte -+and eax, 0fch # mask byte -+xor edi DWORD PTR 0x300+des_SP[eax] # xor in array lookup -+ -+Due to the execution units in the pentium, this actually works quite well. -+For a pentium pro it should be very good. This is the type of output -+Visual C++ generates. -+ -+There is a third option. instead of using -+mov al, ch -+which is bad on the pentium pro, one may be able to use -+movzx eax, ch -+which may not incur the partial write penalty. On the pentium, -+this instruction takes 4 cycles so is not worth using but on the -+pentium pro it appears it may be worth while. I need access to one to -+experiment :-). -+ -+eric (20 Oct 1996) -+ -+22 Nov 1996 - I have asked people to run the 2 different version on pentium -+pros and it appears that the intel documentation is wrong. The -+mov al,bh is still faster on a pentium pro, so just use the des586.pl -+install des686.pl -+ -+3 Dec 1996 - I added des_encrypt3/des_decrypt3 because I have moved these -+functions into des_enc.c because it does make a massive performance -+difference on some boxes to have the functions code located close to -+the des_encrypt2() function. -+ -+9 Jan 1997 - des-som2.pl is now the correct perl script to use for -+pentiums. It contains an inner loop from -+Svend Olaf Mikkelsen which does raw ecb DES calls at -+273,000 per second. He had a previous version at 250,000 and the best -+I was able to get was 203,000. The content has not changed, this is all -+due to instruction sequencing (and actual instructions choice) which is able -+to keep both functional units of the pentium going. -+We may have lost the ugly register usage restrictions when x86 went 32 bit -+but for the pentium it has been replaced by evil instruction ordering tricks. -+ -+13 Jan 1997 - des-som3.pl, more optimizations from Svend Olaf. -+raw DES at 281,000 per second on a pentium 100. -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/cbc_enc.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,135 @@ -+/* crypto/des/cbc_enc.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+#include "des_locl.h" -+ -+void des_cbc_encrypt(input, output, length, schedule, ivec, enc) -+des_cblock (*input); -+des_cblock (*output); -+long length; -+des_key_schedule schedule; -+des_cblock (*ivec); -+int enc; -+ { -+ register DES_LONG tin0,tin1; -+ register DES_LONG tout0,tout1,xor0,xor1; -+ register unsigned char *in,*out; -+ register long l=length; -+ DES_LONG tin[2]; -+ unsigned char *iv; -+ -+ in=(unsigned char *)input; -+ out=(unsigned char *)output; -+ iv=(unsigned char *)ivec; -+ -+ if (enc) -+ { -+ c2l(iv,tout0); -+ c2l(iv,tout1); -+ for (l-=8; l>=0; l-=8) -+ { -+ c2l(in,tin0); -+ c2l(in,tin1); -+ tin0^=tout0; tin[0]=tin0; -+ tin1^=tout1; tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); -+ tout0=tin[0]; l2c(tout0,out); -+ tout1=tin[1]; l2c(tout1,out); -+ } -+ if (l != -8) -+ { -+ c2ln(in,tin0,tin1,l+8); -+ tin0^=tout0; tin[0]=tin0; -+ tin1^=tout1; tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); -+ tout0=tin[0]; l2c(tout0,out); -+ tout1=tin[1]; l2c(tout1,out); -+ } -+ } -+ else -+ { -+ c2l(iv,xor0); -+ c2l(iv,xor1); -+ for (l-=8; l>=0; l-=8) -+ { -+ c2l(in,tin0); tin[0]=tin0; -+ c2l(in,tin1); tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); -+ tout0=tin[0]^xor0; -+ tout1=tin[1]^xor1; -+ l2c(tout0,out); -+ l2c(tout1,out); -+ xor0=tin0; -+ xor1=tin1; -+ } -+ if (l != -8) -+ { -+ c2l(in,tin0); tin[0]=tin0; -+ c2l(in,tin1); tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); -+ tout0=tin[0]^xor0; -+ tout1=tin[1]^xor1; -+ l2cn(tout0,tout1,out,l+8); -+ /* xor0=tin0; -+ xor1=tin1; */ -+ } -+ } -+ tin0=tin1=tout0=tout1=xor0=xor1=0; -+ tin[0]=tin[1]=0; -+ } -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/des.doc Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,505 @@ -+The DES library. -+ -+Please note that this library was originally written to operate with -+eBones, a version of Kerberos that had had encryption removed when it left -+the USA and then put back in. As such there are some routines that I will -+advise not using but they are still in the library for historical reasons. -+For all calls that have an 'input' and 'output' variables, they can be the -+same. -+ -+This library requires the inclusion of 'des.h'. -+ -+All of the encryption functions take what is called a des_key_schedule as an -+argument. A des_key_schedule is an expanded form of the des key. -+A des_key is 8 bytes of odd parity, the type used to hold the key is a -+des_cblock. A des_cblock is an array of 8 bytes, often in this library -+description I will refer to input bytes when the function specifies -+des_cblock's as input or output, this just means that the variable should -+be a multiple of 8 bytes. -+ -+The define DES_ENCRYPT is passed to specify encryption, DES_DECRYPT to -+specify decryption. The functions and global variable are as follows: -+ -+int des_check_key; -+ DES keys are supposed to be odd parity. If this variable is set to -+ a non-zero value, des_set_key() will check that the key has odd -+ parity and is not one of the known weak DES keys. By default this -+ variable is turned off; -+ -+void des_set_odd_parity( -+des_cblock *key ); -+ This function takes a DES key (8 bytes) and sets the parity to odd. -+ -+int des_is_weak_key( -+des_cblock *key ); -+ This function returns a non-zero value if the DES key passed is a -+ weak, DES key. If it is a weak key, don't use it, try a different -+ one. If you are using 'random' keys, the chances of hitting a weak -+ key are 1/2^52 so it is probably not worth checking for them. -+ -+int des_set_key( -+des_cblock *key, -+des_key_schedule schedule); -+ Des_set_key converts an 8 byte DES key into a des_key_schedule. -+ A des_key_schedule is an expanded form of the key which is used to -+ perform actual encryption. It can be regenerated from the DES key -+ so it only needs to be kept when encryption or decryption is about -+ to occur. Don't save or pass around des_key_schedule's since they -+ are CPU architecture dependent, DES keys are not. If des_check_key -+ is non zero, zero is returned if the key has the wrong parity or -+ the key is a weak key, else 1 is returned. -+ -+int des_key_sched( -+des_cblock *key, -+des_key_schedule schedule); -+ An alternative name for des_set_key(). -+ -+int des_rw_mode; /* defaults to DES_PCBC_MODE */ -+ This flag holds either DES_CBC_MODE or DES_PCBC_MODE (default). -+ This specifies the function to use in the enc_read() and enc_write() -+ functions. -+ -+void des_encrypt( -+unsigned long *data, -+des_key_schedule ks, -+int enc); -+ This is the DES encryption function that gets called by just about -+ every other DES routine in the library. You should not use this -+ function except to implement 'modes' of DES. I say this because the -+ functions that call this routine do the conversion from 'char *' to -+ long, and this needs to be done to make sure 'non-aligned' memory -+ access do not occur. The characters are loaded 'little endian', -+ have a look at my source code for more details on how I use this -+ function. -+ Data is a pointer to 2 unsigned long's and ks is the -+ des_key_schedule to use. enc, is non zero specifies encryption, -+ zero if decryption. -+ -+void des_encrypt2( -+unsigned long *data, -+des_key_schedule ks, -+int enc); -+ This functions is the same as des_encrypt() except that the DES -+ initial permutation (IP) and final permutation (FP) have been left -+ out. As for des_encrypt(), you should not use this function. -+ It is used by the routines in my library that implement triple DES. -+ IP() des_encrypt2() des_encrypt2() des_encrypt2() FP() is the same -+ as des_encrypt() des_encrypt() des_encrypt() except faster :-). -+ -+void des_ecb_encrypt( -+des_cblock *input, -+des_cblock *output, -+des_key_schedule ks, -+int enc); -+ This is the basic Electronic Code Book form of DES, the most basic -+ form. Input is encrypted into output using the key represented by -+ ks. If enc is non zero (DES_ENCRYPT), encryption occurs, otherwise -+ decryption occurs. Input is 8 bytes long and output is 8 bytes. -+ (the des_cblock structure is 8 chars). -+ -+void des_ecb3_encrypt( -+des_cblock *input, -+des_cblock *output, -+des_key_schedule ks1, -+des_key_schedule ks2, -+des_key_schedule ks3, -+int enc); -+ This is the 3 key EDE mode of ECB DES. What this means is that -+ the 8 bytes of input is encrypted with ks1, decrypted with ks2 and -+ then encrypted again with ks3, before being put into output; -+ C=E(ks3,D(ks2,E(ks1,M))). There is a macro, des_ecb2_encrypt() -+ that only takes 2 des_key_schedules that implements, -+ C=E(ks1,D(ks2,E(ks1,M))) in that the final encrypt is done with ks1. -+ -+void des_cbc_encrypt( -+des_cblock *input, -+des_cblock *output, -+long length, -+des_key_schedule ks, -+des_cblock *ivec, -+int enc); -+ This routine implements DES in Cipher Block Chaining mode. -+ Input, which should be a multiple of 8 bytes is encrypted -+ (or decrypted) to output which will also be a multiple of 8 bytes. -+ The number of bytes is in length (and from what I've said above, -+ should be a multiple of 8). If length is not a multiple of 8, I'm -+ not being held responsible :-). ivec is the initialisation vector. -+ This function does not modify this variable. To correctly implement -+ cbc mode, you need to do one of 2 things; copy the last 8 bytes of -+ cipher text for use as the next ivec in your application, -+ or use des_ncbc_encrypt(). -+ Only this routine has this problem with updating the ivec, all -+ other routines that are implementing cbc mode update ivec. -+ -+void des_ncbc_encrypt( -+des_cblock *input, -+des_cblock *output, -+long length, -+des_key_schedule sk, -+des_cblock *ivec, -+int enc); -+ For historical reasons, des_cbc_encrypt() did not update the -+ ivec with the value requires so that subsequent calls to -+ des_cbc_encrypt() would 'chain'. This was needed so that the same -+ 'length' values would not need to be used when decrypting. -+ des_ncbc_encrypt() does the right thing. It is the same as -+ des_cbc_encrypt accept that ivec is updates with the correct value -+ to pass in subsequent calls to des_ncbc_encrypt(). I advise using -+ des_ncbc_encrypt() instead of des_cbc_encrypt(); -+ -+void des_xcbc_encrypt( -+des_cblock *input, -+des_cblock *output, -+long length, -+des_key_schedule sk, -+des_cblock *ivec, -+des_cblock *inw, -+des_cblock *outw, -+int enc); -+ This is RSA's DESX mode of DES. It uses inw and outw to -+ 'whiten' the encryption. inw and outw are secret (unlike the iv) -+ and are as such, part of the key. So the key is sort of 24 bytes. -+ This is much better than cbc des. -+ -+void des_3cbc_encrypt( -+des_cblock *input, -+des_cblock *output, -+long length, -+des_key_schedule sk1, -+des_key_schedule sk2, -+des_cblock *ivec1, -+des_cblock *ivec2, -+int enc); -+ This function is flawed, do not use it. I have left it in the -+ library because it is used in my des(1) program and will function -+ correctly when used by des(1). If I removed the function, people -+ could end up unable to decrypt files. -+ This routine implements outer triple cbc encryption using 2 ks and -+ 2 ivec's. Use des_ede2_cbc_encrypt() instead. -+ -+void des_ede3_cbc_encrypt( -+des_cblock *input, -+des_cblock *output, -+long length, -+des_key_schedule ks1, -+des_key_schedule ks2, -+des_key_schedule ks3, -+des_cblock *ivec, -+int enc); -+ This function implements inner triple CBC DES encryption with 3 -+ keys. What this means is that each 'DES' operation -+ inside the cbc mode is really an C=E(ks3,D(ks2,E(ks1,M))). -+ Again, this is cbc mode so an ivec is requires. -+ This mode is used by SSL. -+ There is also a des_ede2_cbc_encrypt() that only uses 2 -+ des_key_schedule's, the first being reused for the final -+ encryption. C=E(ks1,D(ks2,E(ks1,M))). This form of triple DES -+ is used by the RSAref library. -+ -+void des_pcbc_encrypt( -+des_cblock *input, -+des_cblock *output, -+long length, -+des_key_schedule ks, -+des_cblock *ivec, -+int enc); -+ This is Propagating Cipher Block Chaining mode of DES. It is used -+ by Kerberos v4. It's parameters are the same as des_ncbc_encrypt(). -+ -+void des_cfb_encrypt( -+unsigned char *in, -+unsigned char *out, -+int numbits, -+long length, -+des_key_schedule ks, -+des_cblock *ivec, -+int enc); -+ Cipher Feedback Back mode of DES. This implementation 'feeds back' -+ in numbit blocks. The input (and output) is in multiples of numbits -+ bits. numbits should to be a multiple of 8 bits. Length is the -+ number of bytes input. If numbits is not a multiple of 8 bits, -+ the extra bits in the bytes will be considered padding. So if -+ numbits is 12, for each 2 input bytes, the 4 high bits of the -+ second byte will be ignored. So to encode 72 bits when using -+ a numbits of 12 take 12 bytes. To encode 72 bits when using -+ numbits of 9 will take 16 bytes. To encode 80 bits when using -+ numbits of 16 will take 10 bytes. etc, etc. This padding will -+ apply to both input and output. -+ -+ -+void des_cfb64_encrypt( -+unsigned char *in, -+unsigned char *out, -+long length, -+des_key_schedule ks, -+des_cblock *ivec, -+int *num, -+int enc); -+ This is one of the more useful functions in this DES library, it -+ implements CFB mode of DES with 64bit feedback. Why is this -+ useful you ask? Because this routine will allow you to encrypt an -+ arbitrary number of bytes, no 8 byte padding. Each call to this -+ routine will encrypt the input bytes to output and then update ivec -+ and num. num contains 'how far' we are though ivec. If this does -+ not make much sense, read more about cfb mode of DES :-). -+ -+void des_ede3_cfb64_encrypt( -+unsigned char *in, -+unsigned char *out, -+long length, -+des_key_schedule ks1, -+des_key_schedule ks2, -+des_key_schedule ks3, -+des_cblock *ivec, -+int *num, -+int enc); -+ Same as des_cfb64_encrypt() accept that the DES operation is -+ triple DES. As usual, there is a macro for -+ des_ede2_cfb64_encrypt() which reuses ks1. -+ -+void des_ofb_encrypt( -+unsigned char *in, -+unsigned char *out, -+int numbits, -+long length, -+des_key_schedule ks, -+des_cblock *ivec); -+ This is a implementation of Output Feed Back mode of DES. It is -+ the same as des_cfb_encrypt() in that numbits is the size of the -+ units dealt with during input and output (in bits). -+ -+void des_ofb64_encrypt( -+unsigned char *in, -+unsigned char *out, -+long length, -+des_key_schedule ks, -+des_cblock *ivec, -+int *num); -+ The same as des_cfb64_encrypt() except that it is Output Feed Back -+ mode. -+ -+void des_ede3_ofb64_encrypt( -+unsigned char *in, -+unsigned char *out, -+long length, -+des_key_schedule ks1, -+des_key_schedule ks2, -+des_key_schedule ks3, -+des_cblock *ivec, -+int *num); -+ Same as des_ofb64_encrypt() accept that the DES operation is -+ triple DES. As usual, there is a macro for -+ des_ede2_ofb64_encrypt() which reuses ks1. -+ -+int des_read_pw_string( -+char *buf, -+int length, -+char *prompt, -+int verify); -+ This routine is used to get a password from the terminal with echo -+ turned off. Buf is where the string will end up and length is the -+ size of buf. Prompt is a string presented to the 'user' and if -+ verify is set, the key is asked for twice and unless the 2 copies -+ match, an error is returned. A return code of -1 indicates a -+ system error, 1 failure due to use interaction, and 0 is success. -+ -+unsigned long des_cbc_cksum( -+des_cblock *input, -+des_cblock *output, -+long length, -+des_key_schedule ks, -+des_cblock *ivec); -+ This function produces an 8 byte checksum from input that it puts in -+ output and returns the last 4 bytes as a long. The checksum is -+ generated via cbc mode of DES in which only the last 8 byes are -+ kept. I would recommend not using this function but instead using -+ the EVP_Digest routines, or at least using MD5 or SHA. This -+ function is used by Kerberos v4 so that is why it stays in the -+ library. -+ -+char *des_fcrypt( -+const char *buf, -+const char *salt -+char *ret); -+ This is my fast version of the unix crypt(3) function. This version -+ takes only a small amount of space relative to other fast -+ crypt() implementations. This is different to the normal crypt -+ in that the third parameter is the buffer that the return value -+ is written into. It needs to be at least 14 bytes long. This -+ function is thread safe, unlike the normal crypt. -+ -+char *crypt( -+const char *buf, -+const char *salt); -+ This function calls des_fcrypt() with a static array passed as the -+ third parameter. This emulates the normal non-thread safe semantics -+ of crypt(3). -+ -+void des_string_to_key( -+char *str, -+des_cblock *key); -+ This function takes str and converts it into a DES key. I would -+ recommend using MD5 instead and use the first 8 bytes of output. -+ When I wrote the first version of these routines back in 1990, MD5 -+ did not exist but I feel these routines are still sound. This -+ routines is compatible with the one in MIT's libdes. -+ -+void des_string_to_2keys( -+char *str, -+des_cblock *key1, -+des_cblock *key2); -+ This function takes str and converts it into 2 DES keys. -+ I would recommend using MD5 and using the 16 bytes as the 2 keys. -+ I have nothing against these 2 'string_to_key' routines, it's just -+ that if you say that your encryption key is generated by using the -+ 16 bytes of an MD5 hash, every-one knows how you generated your -+ keys. -+ -+int des_read_password( -+des_cblock *key, -+char *prompt, -+int verify); -+ This routine combines des_read_pw_string() with des_string_to_key(). -+ -+int des_read_2passwords( -+des_cblock *key1, -+des_cblock *key2, -+char *prompt, -+int verify); -+ This routine combines des_read_pw_string() with des_string_to_2key(). -+ -+void des_random_seed( -+des_cblock key); -+ This routine sets a starting point for des_random_key(). -+ -+void des_random_key( -+des_cblock ret); -+ This function return a random key. Make sure to 'seed' the random -+ number generator (with des_random_seed()) before using this function. -+ I personally now use a MD5 based random number system. -+ -+int des_enc_read( -+int fd, -+char *buf, -+int len, -+des_key_schedule ks, -+des_cblock *iv); -+ This function will write to a file descriptor the encrypted data -+ from buf. This data will be preceded by a 4 byte 'byte count' and -+ will be padded out to 8 bytes. The encryption is either CBC of -+ PCBC depending on the value of des_rw_mode. If it is DES_PCBC_MODE, -+ pcbc is used, if DES_CBC_MODE, cbc is used. The default is to use -+ DES_PCBC_MODE. -+ -+int des_enc_write( -+int fd, -+char *buf, -+int len, -+des_key_schedule ks, -+des_cblock *iv); -+ This routines read stuff written by des_enc_read() and decrypts it. -+ I have used these routines quite a lot but I don't believe they are -+ suitable for non-blocking io. If you are after a full -+ authentication/encryption over networks, have a look at SSL instead. -+ -+unsigned long des_quad_cksum( -+des_cblock *input, -+des_cblock *output, -+long length, -+int out_count, -+des_cblock *seed); -+ This is a function from Kerberos v4 that is not anything to do with -+ DES but was needed. It is a cksum that is quicker to generate than -+ des_cbc_cksum(); I personally would use MD5 routines now. -+===== -+Modes of DES -+Quite a bit of the following information has been taken from -+ AS 2805.5.2 -+ Australian Standard -+ Electronic funds transfer - Requirements for interfaces, -+ Part 5.2: Modes of operation for an n-bit block cipher algorithm -+ Appendix A -+ -+There are several different modes in which DES can be used, they are -+as follows. -+ -+Electronic Codebook Mode (ECB) (des_ecb_encrypt()) -+- 64 bits are enciphered at a time. -+- The order of the blocks can be rearranged without detection. -+- The same plaintext block always produces the same ciphertext block -+ (for the same key) making it vulnerable to a 'dictionary attack'. -+- An error will only affect one ciphertext block. -+ -+Cipher Block Chaining Mode (CBC) (des_cbc_encrypt()) -+- a multiple of 64 bits are enciphered at a time. -+- The CBC mode produces the same ciphertext whenever the same -+ plaintext is encrypted using the same key and starting variable. -+- The chaining operation makes the ciphertext blocks dependent on the -+ current and all preceding plaintext blocks and therefore blocks can not -+ be rearranged. -+- The use of different starting variables prevents the same plaintext -+ enciphering to the same ciphertext. -+- An error will affect the current and the following ciphertext blocks. -+ -+Cipher Feedback Mode (CFB) (des_cfb_encrypt()) -+- a number of bits (j) <= 64 are enciphered at a time. -+- The CFB mode produces the same ciphertext whenever the same -+ plaintext is encrypted using the same key and starting variable. -+- The chaining operation makes the ciphertext variables dependent on the -+ current and all preceding variables and therefore j-bit variables are -+ chained together and can not be rearranged. -+- The use of different starting variables prevents the same plaintext -+ enciphering to the same ciphertext. -+- The strength of the CFB mode depends on the size of k (maximal if -+ j == k). In my implementation this is always the case. -+- Selection of a small value for j will require more cycles through -+ the encipherment algorithm per unit of plaintext and thus cause -+ greater processing overheads. -+- Only multiples of j bits can be enciphered. -+- An error will affect the current and the following ciphertext variables. -+ -+Output Feedback Mode (OFB) (des_ofb_encrypt()) -+- a number of bits (j) <= 64 are enciphered at a time. -+- The OFB mode produces the same ciphertext whenever the same -+ plaintext enciphered using the same key and starting variable. More -+ over, in the OFB mode the same key stream is produced when the same -+ key and start variable are used. Consequently, for security reasons -+ a specific start variable should be used only once for a given key. -+- The absence of chaining makes the OFB more vulnerable to specific attacks. -+- The use of different start variables values prevents the same -+ plaintext enciphering to the same ciphertext, by producing different -+ key streams. -+- Selection of a small value for j will require more cycles through -+ the encipherment algorithm per unit of plaintext and thus cause -+ greater processing overheads. -+- Only multiples of j bits can be enciphered. -+- OFB mode of operation does not extend ciphertext errors in the -+ resultant plaintext output. Every bit error in the ciphertext causes -+ only one bit to be in error in the deciphered plaintext. -+- OFB mode is not self-synchronising. If the two operation of -+ encipherment and decipherment get out of synchronism, the system needs -+ to be re-initialised. -+- Each re-initialisation should use a value of the start variable -+ different from the start variable values used before with the same -+ key. The reason for this is that an identical bit stream would be -+ produced each time from the same parameters. This would be -+ susceptible to a ' known plaintext' attack. -+ -+Triple ECB Mode (des_ecb3_encrypt()) -+- Encrypt with key1, decrypt with key2 and encrypt with key3 again. -+- As for ECB encryption but increases the key length to 168 bits. -+ There are theoretic attacks that can be used that make the effective -+ key length 112 bits, but this attack also requires 2^56 blocks of -+ memory, not very likely, even for the NSA. -+- If both keys are the same it is equivalent to encrypting once with -+ just one key. -+- If the first and last key are the same, the key length is 112 bits. -+ There are attacks that could reduce the key space to 55 bit's but it -+ requires 2^56 blocks of memory. -+- If all 3 keys are the same, this is effectively the same as normal -+ ecb mode. -+ -+Triple CBC Mode (des_ede3_cbc_encrypt()) -+- Encrypt with key1, decrypt with key2 and then encrypt with key3. -+- As for CBC encryption but increases the key length to 168 bits with -+ the same restrictions as for triple ecb mode. ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/des_crypt.man Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,508 @@ -+.TH DES_CRYPT 3 -+.SH NAME -+des_read_password, des_read_2password, -+des_string_to_key, des_string_to_2key, des_read_pw_string, -+des_random_key, des_set_key, -+des_key_sched, des_ecb_encrypt, des_ecb3_encrypt, des_cbc_encrypt, -+des_3cbc_encrypt, -+des_pcbc_encrypt, des_cfb_encrypt, des_ofb_encrypt, -+des_cbc_cksum, des_quad_cksum, -+des_enc_read, des_enc_write, des_set_odd_parity, -+des_is_weak_key, crypt \- (non USA) DES encryption -+.SH SYNOPSIS -+.nf -+.nj -+.ft B -+#include -+.PP -+.B int des_read_password(key,prompt,verify) -+des_cblock *key; -+char *prompt; -+int verify; -+.PP -+.B int des_read_2password(key1,key2,prompt,verify) -+des_cblock *key1,*key2; -+char *prompt; -+int verify; -+.PP -+.B int des_string_to_key(str,key) -+char *str; -+des_cblock *key; -+.PP -+.B int des_string_to_2keys(str,key1,key2) -+char *str; -+des_cblock *key1,*key2; -+.PP -+.B int des_read_pw_string(buf,length,prompt,verify) -+char *buf; -+int length; -+char *prompt; -+int verify; -+.PP -+.B int des_random_key(key) -+des_cblock *key; -+.PP -+.B int des_set_key(key,schedule) -+des_cblock *key; -+des_key_schedule schedule; -+.PP -+.B int des_key_sched(key,schedule) -+des_cblock *key; -+des_key_schedule schedule; -+.PP -+.B int des_ecb_encrypt(input,output,schedule,encrypt) -+des_cblock *input; -+des_cblock *output; -+des_key_schedule schedule; -+int encrypt; -+.PP -+.B int des_ecb3_encrypt(input,output,ks1,ks2,encrypt) -+des_cblock *input; -+des_cblock *output; -+des_key_schedule ks1,ks2; -+int encrypt; -+.PP -+.B int des_cbc_encrypt(input,output,length,schedule,ivec,encrypt) -+des_cblock *input; -+des_cblock *output; -+long length; -+des_key_schedule schedule; -+des_cblock *ivec; -+int encrypt; -+.PP -+.B int des_3cbc_encrypt(input,output,length,sk1,sk2,ivec1,ivec2,encrypt) -+des_cblock *input; -+des_cblock *output; -+long length; -+des_key_schedule sk1; -+des_key_schedule sk2; -+des_cblock *ivec1; -+des_cblock *ivec2; -+int encrypt; -+.PP -+.B int des_pcbc_encrypt(input,output,length,schedule,ivec,encrypt) -+des_cblock *input; -+des_cblock *output; -+long length; -+des_key_schedule schedule; -+des_cblock *ivec; -+int encrypt; -+.PP -+.B int des_cfb_encrypt(input,output,numbits,length,schedule,ivec,encrypt) -+unsigned char *input; -+unsigned char *output; -+int numbits; -+long length; -+des_key_schedule schedule; -+des_cblock *ivec; -+int encrypt; -+.PP -+.B int des_ofb_encrypt(input,output,numbits,length,schedule,ivec) -+unsigned char *input,*output; -+int numbits; -+long length; -+des_key_schedule schedule; -+des_cblock *ivec; -+.PP -+.B unsigned long des_cbc_cksum(input,output,length,schedule,ivec) -+des_cblock *input; -+des_cblock *output; -+long length; -+des_key_schedule schedule; -+des_cblock *ivec; -+.PP -+.B unsigned long des_quad_cksum(input,output,length,out_count,seed) -+des_cblock *input; -+des_cblock *output; -+long length; -+int out_count; -+des_cblock *seed; -+.PP -+.B int des_check_key; -+.PP -+.B int des_enc_read(fd,buf,len,sched,iv) -+int fd; -+char *buf; -+int len; -+des_key_schedule sched; -+des_cblock *iv; -+.PP -+.B int des_enc_write(fd,buf,len,sched,iv) -+int fd; -+char *buf; -+int len; -+des_key_schedule sched; -+des_cblock *iv; -+.PP -+.B extern int des_rw_mode; -+.PP -+.B void des_set_odd_parity(key) -+des_cblock *key; -+.PP -+.B int des_is_weak_key(key) -+des_cblock *key; -+.PP -+.B char *crypt(passwd,salt) -+char *passwd; -+char *salt; -+.PP -+.fi -+.SH DESCRIPTION -+This library contains a fast implementation of the DES encryption -+algorithm. -+.PP -+There are two phases to the use of DES encryption. -+The first is the generation of a -+.I des_key_schedule -+from a key, -+the second is the actual encryption. -+A des key is of type -+.I des_cblock. -+This type is made from 8 characters with odd parity. -+The least significant bit in the character is the parity bit. -+The key schedule is an expanded form of the key; it is used to speed the -+encryption process. -+.PP -+.I des_read_password -+writes the string specified by prompt to the standard output, -+turns off echo and reads an input string from standard input -+until terminated with a newline. -+If verify is non-zero, it prompts and reads the input again and verifies -+that both entered passwords are the same. -+The entered string is converted into a des key by using the -+.I des_string_to_key -+routine. -+The new key is placed in the -+.I des_cblock -+that was passed (by reference) to the routine. -+If there were no errors, -+.I des_read_password -+returns 0, -+-1 is returned if there was a terminal error and 1 is returned for -+any other error. -+.PP -+.I des_read_2password -+operates in the same way as -+.I des_read_password -+except that it generates 2 keys by using the -+.I des_string_to_2key -+function. -+.PP -+.I des_read_pw_string -+is called by -+.I des_read_password -+to read and verify a string from a terminal device. -+The string is returned in -+.I buf. -+The size of -+.I buf -+is passed to the routine via the -+.I length -+parameter. -+.PP -+.I des_string_to_key -+converts a string into a valid des key. -+.PP -+.I des_string_to_2key -+converts a string into 2 valid des keys. -+This routine is best suited for used to generate keys for use with -+.I des_ecb3_encrypt. -+.PP -+.I des_random_key -+returns a random key that is made of a combination of process id, -+time and an increasing counter. -+.PP -+Before a des key can be used it is converted into a -+.I des_key_schedule -+via the -+.I des_set_key -+routine. -+If the -+.I des_check_key -+flag is non-zero, -+.I des_set_key -+will check that the key passed is of odd parity and is not a week or -+semi-weak key. -+If the parity is wrong, -+then -1 is returned. -+If the key is a weak key, -+then -2 is returned. -+If an error is returned, -+the key schedule is not generated. -+.PP -+.I des_key_sched -+is another name for the -+.I des_set_key -+function. -+.PP -+The following routines mostly operate on an input and output stream of -+.I des_cblock's. -+.PP -+.I des_ecb_encrypt -+is the basic DES encryption routine that encrypts or decrypts a single 8-byte -+.I des_cblock -+in -+.I electronic code book -+mode. -+It always transforms the input data, pointed to by -+.I input, -+into the output data, -+pointed to by the -+.I output -+argument. -+If the -+.I encrypt -+argument is non-zero (DES_ENCRYPT), -+the -+.I input -+(cleartext) is encrypted in to the -+.I output -+(ciphertext) using the key_schedule specified by the -+.I schedule -+argument, -+previously set via -+.I des_set_key. -+If -+.I encrypt -+is zero (DES_DECRYPT), -+the -+.I input -+(now ciphertext) -+is decrypted into the -+.I output -+(now cleartext). -+Input and output may overlap. -+No meaningful value is returned. -+.PP -+.I des_ecb3_encrypt -+encrypts/decrypts the -+.I input -+block by using triple ecb DES encryption. -+This involves encrypting the input with -+.I ks1, -+decryption with the key schedule -+.I ks2, -+and then encryption with the first again. -+This routine greatly reduces the chances of brute force breaking of -+DES and has the advantage of if -+.I ks1 -+and -+.I ks2 -+are the same, it is equivalent to just encryption using ecb mode and -+.I ks1 -+as the key. -+.PP -+.I des_cbc_encrypt -+encrypts/decrypts using the -+.I cipher-block-chaining -+mode of DES. -+If the -+.I encrypt -+argument is non-zero, -+the routine cipher-block-chain encrypts the cleartext data pointed to by the -+.I input -+argument into the ciphertext pointed to by the -+.I output -+argument, -+using the key schedule provided by the -+.I schedule -+argument, -+and initialisation vector provided by the -+.I ivec -+argument. -+If the -+.I length -+argument is not an integral multiple of eight bytes, -+the last block is copied to a temporary area and zero filled. -+The output is always -+an integral multiple of eight bytes. -+To make multiple cbc encrypt calls on a large amount of data appear to -+be one -+.I des_cbc_encrypt -+call, the -+.I ivec -+of subsequent calls should be the last 8 bytes of the output. -+.PP -+.I des_3cbc_encrypt -+encrypts/decrypts the -+.I input -+block by using triple cbc DES encryption. -+This involves encrypting the input with key schedule -+.I ks1, -+decryption with the key schedule -+.I ks2, -+and then encryption with the first again. -+2 initialisation vectors are required, -+.I ivec1 -+and -+.I ivec2. -+Unlike -+.I des_cbc_encrypt, -+these initialisation vectors are modified by the subroutine. -+This routine greatly reduces the chances of brute force breaking of -+DES and has the advantage of if -+.I ks1 -+and -+.I ks2 -+are the same, it is equivalent to just encryption using cbc mode and -+.I ks1 -+as the key. -+.PP -+.I des_pcbc_encrypt -+encrypt/decrypts using a modified block chaining mode. -+It provides better error propagation characteristics than cbc -+encryption. -+.PP -+.I des_cfb_encrypt -+encrypt/decrypts using cipher feedback mode. This method takes an -+array of characters as input and outputs and array of characters. It -+does not require any padding to 8 character groups. Note: the ivec -+variable is changed and the new changed value needs to be passed to -+the next call to this function. Since this function runs a complete -+DES ecb encryption per numbits, this function is only suggested for -+use when sending small numbers of characters. -+.PP -+.I des_ofb_encrypt -+encrypt using output feedback mode. This method takes an -+array of characters as input and outputs and array of characters. It -+does not require any padding to 8 character groups. Note: the ivec -+variable is changed and the new changed value needs to be passed to -+the next call to this function. Since this function runs a complete -+DES ecb encryption per numbits, this function is only suggested for -+use when sending small numbers of characters. -+.PP -+.I des_cbc_cksum -+produces an 8 byte checksum based on the input stream (via cbc encryption). -+The last 4 bytes of the checksum is returned and the complete 8 bytes is -+placed in -+.I output. -+.PP -+.I des_quad_cksum -+returns a 4 byte checksum from the input bytes. -+The algorithm can be iterated over the input, -+depending on -+.I out_count, -+1, 2, 3 or 4 times. -+If -+.I output -+is non-NULL, -+the 8 bytes generated by each pass are written into -+.I output. -+.PP -+.I des_enc_write -+is used to write -+.I len -+bytes -+to file descriptor -+.I fd -+from buffer -+.I buf. -+The data is encrypted via -+.I pcbc_encrypt -+(default) using -+.I sched -+for the key and -+.I iv -+as a starting vector. -+The actual data send down -+.I fd -+consists of 4 bytes (in network byte order) containing the length of the -+following encrypted data. The encrypted data then follows, padded with random -+data out to a multiple of 8 bytes. -+.PP -+.I des_enc_read -+is used to read -+.I len -+bytes -+from file descriptor -+.I fd -+into buffer -+.I buf. -+The data being read from -+.I fd -+is assumed to have come from -+.I des_enc_write -+and is decrypted using -+.I sched -+for the key schedule and -+.I iv -+for the initial vector. -+The -+.I des_enc_read/des_enc_write -+pair can be used to read/write to files, pipes and sockets. -+I have used them in implementing a version of rlogin in which all -+data is encrypted. -+.PP -+.I des_rw_mode -+is used to specify the encryption mode to use with -+.I des_enc_read -+and -+.I des_end_write. -+If set to -+.I DES_PCBC_MODE -+(the default), des_pcbc_encrypt is used. -+If set to -+.I DES_CBC_MODE -+des_cbc_encrypt is used. -+These two routines and the variable are not part of the normal MIT library. -+.PP -+.I des_set_odd_parity -+sets the parity of the passed -+.I key -+to odd. This routine is not part of the standard MIT library. -+.PP -+.I des_is_weak_key -+returns 1 is the passed key is a weak key (pick again :-), -+0 if it is ok. -+This routine is not part of the standard MIT library. -+.PP -+.I crypt -+is a replacement for the normal system crypt. -+It is much faster than the system crypt. -+.PP -+.SH FILES -+/usr/include/des.h -+.br -+/usr/lib/libdes.a -+.PP -+The encryption routines have been tested on 16bit, 32bit and 64bit -+machines of various endian and even works under VMS. -+.PP -+.SH BUGS -+.PP -+If you think this manual is sparse, -+read the des_crypt(3) manual from the MIT kerberos (or bones outside -+of the USA) distribution. -+.PP -+.I des_cfb_encrypt -+and -+.I des_ofb_encrypt -+operates on input of 8 bits. What this means is that if you set -+numbits to 12, and length to 2, the first 12 bits will come from the 1st -+input byte and the low half of the second input byte. The second 12 -+bits will have the low 8 bits taken from the 3rd input byte and the -+top 4 bits taken from the 4th input byte. The same holds for output. -+This function has been implemented this way because most people will -+be using a multiple of 8 and because once you get into pulling bytes input -+bytes apart things get ugly! -+.PP -+.I des_read_pw_string -+is the most machine/OS dependent function and normally generates the -+most problems when porting this code. -+.PP -+.I des_string_to_key -+is probably different from the MIT version since there are lots -+of fun ways to implement one-way encryption of a text string. -+.PP -+The routines are optimised for 32 bit machines and so are not efficient -+on IBM PCs. -+.PP -+NOTE: extensive work has been done on this library since this document -+was origionally written. Please try to read des.doc from the libdes -+distribution since it is far more upto date and documents more of the -+functions. Libdes is now also being shipped as part of SSLeay, a -+general cryptographic library that amonst other things implements -+netscapes SSL protocoll. The most recent version can be found in -+SSLeay distributions. -+.SH AUTHOR -+Eric Young (eay@cryptsoft.com) ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/des_enc.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,502 @@ -+/* crypto/des/des_enc.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+#include "des_locl.h" -+ -+void des_encrypt(data, ks, enc) -+DES_LONG *data; -+des_key_schedule ks; -+int enc; -+ { -+ register DES_LONG l,r,t,u; -+#ifdef DES_PTR -+ register unsigned char *des_SP=(unsigned char *)des_SPtrans; -+#endif -+#ifndef DES_UNROLL -+ register int i; -+#endif -+ register DES_LONG *s; -+ -+ r=data[0]; -+ l=data[1]; -+ -+ IP(r,l); -+ /* Things have been modified so that the initial rotate is -+ * done outside the loop. This required the -+ * des_SPtrans values in sp.h to be rotated 1 bit to the right. -+ * One perl script later and things have a 5% speed up on a sparc2. -+ * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> -+ * for pointing this out. */ -+ /* clear the top bits on machines with 8byte longs */ -+ /* shift left by 2 */ -+ r=ROTATE(r,29)&0xffffffffL; -+ l=ROTATE(l,29)&0xffffffffL; -+ -+ s=(DES_LONG *)ks; -+ /* I don't know if it is worth the effort of loop unrolling the -+ * inner loop */ -+ if (enc) -+ { -+#ifdef DES_UNROLL -+ D_ENCRYPT(l,r, 0); /* 1 */ -+ D_ENCRYPT(r,l, 2); /* 2 */ -+ D_ENCRYPT(l,r, 4); /* 3 */ -+ D_ENCRYPT(r,l, 6); /* 4 */ -+ D_ENCRYPT(l,r, 8); /* 5 */ -+ D_ENCRYPT(r,l,10); /* 6 */ -+ D_ENCRYPT(l,r,12); /* 7 */ -+ D_ENCRYPT(r,l,14); /* 8 */ -+ D_ENCRYPT(l,r,16); /* 9 */ -+ D_ENCRYPT(r,l,18); /* 10 */ -+ D_ENCRYPT(l,r,20); /* 11 */ -+ D_ENCRYPT(r,l,22); /* 12 */ -+ D_ENCRYPT(l,r,24); /* 13 */ -+ D_ENCRYPT(r,l,26); /* 14 */ -+ D_ENCRYPT(l,r,28); /* 15 */ -+ D_ENCRYPT(r,l,30); /* 16 */ -+#else -+ for (i=0; i<32; i+=8) -+ { -+ D_ENCRYPT(l,r,i+0); /* 1 */ -+ D_ENCRYPT(r,l,i+2); /* 2 */ -+ D_ENCRYPT(l,r,i+4); /* 3 */ -+ D_ENCRYPT(r,l,i+6); /* 4 */ -+ } -+#endif -+ } -+ else -+ { -+#ifdef DES_UNROLL -+ D_ENCRYPT(l,r,30); /* 16 */ -+ D_ENCRYPT(r,l,28); /* 15 */ -+ D_ENCRYPT(l,r,26); /* 14 */ -+ D_ENCRYPT(r,l,24); /* 13 */ -+ D_ENCRYPT(l,r,22); /* 12 */ -+ D_ENCRYPT(r,l,20); /* 11 */ -+ D_ENCRYPT(l,r,18); /* 10 */ -+ D_ENCRYPT(r,l,16); /* 9 */ -+ D_ENCRYPT(l,r,14); /* 8 */ -+ D_ENCRYPT(r,l,12); /* 7 */ -+ D_ENCRYPT(l,r,10); /* 6 */ -+ D_ENCRYPT(r,l, 8); /* 5 */ -+ D_ENCRYPT(l,r, 6); /* 4 */ -+ D_ENCRYPT(r,l, 4); /* 3 */ -+ D_ENCRYPT(l,r, 2); /* 2 */ -+ D_ENCRYPT(r,l, 0); /* 1 */ -+#else -+ for (i=30; i>0; i-=8) -+ { -+ D_ENCRYPT(l,r,i-0); /* 16 */ -+ D_ENCRYPT(r,l,i-2); /* 15 */ -+ D_ENCRYPT(l,r,i-4); /* 14 */ -+ D_ENCRYPT(r,l,i-6); /* 13 */ -+ } -+#endif -+ } -+ -+ /* rotate and clear the top bits on machines with 8byte longs */ -+ l=ROTATE(l,3)&0xffffffffL; -+ r=ROTATE(r,3)&0xffffffffL; -+ -+ FP(r,l); -+ data[0]=l; -+ data[1]=r; -+ l=r=t=u=0; -+ } -+ -+void des_encrypt2(data, ks, enc) -+DES_LONG *data; -+des_key_schedule ks; -+int enc; -+ { -+ register DES_LONG l,r,t,u; -+#ifdef DES_PTR -+ register unsigned char *des_SP=(unsigned char *)des_SPtrans; -+#endif -+#ifndef DES_UNROLL -+ register int i; -+#endif -+ register DES_LONG *s; -+ -+ r=data[0]; -+ l=data[1]; -+ -+ /* Things have been modified so that the initial rotate is -+ * done outside the loop. This required the -+ * des_SPtrans values in sp.h to be rotated 1 bit to the right. -+ * One perl script later and things have a 5% speed up on a sparc2. -+ * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> -+ * for pointing this out. */ -+ /* clear the top bits on machines with 8byte longs */ -+ r=ROTATE(r,29)&0xffffffffL; -+ l=ROTATE(l,29)&0xffffffffL; -+ -+ s=(DES_LONG *)ks; -+ /* I don't know if it is worth the effort of loop unrolling the -+ * inner loop */ -+ if (enc) -+ { -+#ifdef DES_UNROLL -+ D_ENCRYPT(l,r, 0); /* 1 */ -+ D_ENCRYPT(r,l, 2); /* 2 */ -+ D_ENCRYPT(l,r, 4); /* 3 */ -+ D_ENCRYPT(r,l, 6); /* 4 */ -+ D_ENCRYPT(l,r, 8); /* 5 */ -+ D_ENCRYPT(r,l,10); /* 6 */ -+ D_ENCRYPT(l,r,12); /* 7 */ -+ D_ENCRYPT(r,l,14); /* 8 */ -+ D_ENCRYPT(l,r,16); /* 9 */ -+ D_ENCRYPT(r,l,18); /* 10 */ -+ D_ENCRYPT(l,r,20); /* 11 */ -+ D_ENCRYPT(r,l,22); /* 12 */ -+ D_ENCRYPT(l,r,24); /* 13 */ -+ D_ENCRYPT(r,l,26); /* 14 */ -+ D_ENCRYPT(l,r,28); /* 15 */ -+ D_ENCRYPT(r,l,30); /* 16 */ -+#else -+ for (i=0; i<32; i+=8) -+ { -+ D_ENCRYPT(l,r,i+0); /* 1 */ -+ D_ENCRYPT(r,l,i+2); /* 2 */ -+ D_ENCRYPT(l,r,i+4); /* 3 */ -+ D_ENCRYPT(r,l,i+6); /* 4 */ -+ } -+#endif -+ } -+ else -+ { -+#ifdef DES_UNROLL -+ D_ENCRYPT(l,r,30); /* 16 */ -+ D_ENCRYPT(r,l,28); /* 15 */ -+ D_ENCRYPT(l,r,26); /* 14 */ -+ D_ENCRYPT(r,l,24); /* 13 */ -+ D_ENCRYPT(l,r,22); /* 12 */ -+ D_ENCRYPT(r,l,20); /* 11 */ -+ D_ENCRYPT(l,r,18); /* 10 */ -+ D_ENCRYPT(r,l,16); /* 9 */ -+ D_ENCRYPT(l,r,14); /* 8 */ -+ D_ENCRYPT(r,l,12); /* 7 */ -+ D_ENCRYPT(l,r,10); /* 6 */ -+ D_ENCRYPT(r,l, 8); /* 5 */ -+ D_ENCRYPT(l,r, 6); /* 4 */ -+ D_ENCRYPT(r,l, 4); /* 3 */ -+ D_ENCRYPT(l,r, 2); /* 2 */ -+ D_ENCRYPT(r,l, 0); /* 1 */ -+#else -+ for (i=30; i>0; i-=8) -+ { -+ D_ENCRYPT(l,r,i-0); /* 16 */ -+ D_ENCRYPT(r,l,i-2); /* 15 */ -+ D_ENCRYPT(l,r,i-4); /* 14 */ -+ D_ENCRYPT(r,l,i-6); /* 13 */ -+ } -+#endif -+ } -+ /* rotate and clear the top bits on machines with 8byte longs */ -+ data[0]=ROTATE(l,3)&0xffffffffL; -+ data[1]=ROTATE(r,3)&0xffffffffL; -+ l=r=t=u=0; -+ } -+ -+void des_encrypt3(data,ks1,ks2,ks3) -+DES_LONG *data; -+des_key_schedule ks1; -+des_key_schedule ks2; -+des_key_schedule ks3; -+ { -+ register DES_LONG l,r; -+ -+ l=data[0]; -+ r=data[1]; -+ IP(l,r); -+ data[0]=l; -+ data[1]=r; -+ des_encrypt2((DES_LONG *)data,ks1,DES_ENCRYPT); -+ des_encrypt2((DES_LONG *)data,ks2,DES_DECRYPT); -+ des_encrypt2((DES_LONG *)data,ks3,DES_ENCRYPT); -+ l=data[0]; -+ r=data[1]; -+ FP(r,l); -+ data[0]=l; -+ data[1]=r; -+ } -+ -+void des_decrypt3(data,ks1,ks2,ks3) -+DES_LONG *data; -+des_key_schedule ks1; -+des_key_schedule ks2; -+des_key_schedule ks3; -+ { -+ register DES_LONG l,r; -+ -+ l=data[0]; -+ r=data[1]; -+ IP(l,r); -+ data[0]=l; -+ data[1]=r; -+ des_encrypt2((DES_LONG *)data,ks3,DES_DECRYPT); -+ des_encrypt2((DES_LONG *)data,ks2,DES_ENCRYPT); -+ des_encrypt2((DES_LONG *)data,ks1,DES_DECRYPT); -+ l=data[0]; -+ r=data[1]; -+ FP(r,l); -+ data[0]=l; -+ data[1]=r; -+ } -+ -+#ifndef DES_DEFAULT_OPTIONS -+ -+void des_ncbc_encrypt(input, output, length, schedule, ivec, enc) -+des_cblock (*input); -+des_cblock (*output); -+long length; -+des_key_schedule schedule; -+des_cblock (*ivec); -+int enc; -+ { -+ register DES_LONG tin0,tin1; -+ register DES_LONG tout0,tout1,xor0,xor1; -+ register unsigned char *in,*out; -+ register long l=length; -+ DES_LONG tin[2]; -+ unsigned char *iv; -+ -+ in=(unsigned char *)input; -+ out=(unsigned char *)output; -+ iv=(unsigned char *)ivec; -+ -+ if (enc) -+ { -+ c2l(iv,tout0); -+ c2l(iv,tout1); -+ for (l-=8; l>=0; l-=8) -+ { -+ c2l(in,tin0); -+ c2l(in,tin1); -+ tin0^=tout0; tin[0]=tin0; -+ tin1^=tout1; tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); -+ tout0=tin[0]; l2c(tout0,out); -+ tout1=tin[1]; l2c(tout1,out); -+ } -+ if (l != -8) -+ { -+ c2ln(in,tin0,tin1,l+8); -+ tin0^=tout0; tin[0]=tin0; -+ tin1^=tout1; tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); -+ tout0=tin[0]; l2c(tout0,out); -+ tout1=tin[1]; l2c(tout1,out); -+ } -+ iv=(unsigned char *)ivec; -+ l2c(tout0,iv); -+ l2c(tout1,iv); -+ } -+ else -+ { -+ c2l(iv,xor0); -+ c2l(iv,xor1); -+ for (l-=8; l>=0; l-=8) -+ { -+ c2l(in,tin0); tin[0]=tin0; -+ c2l(in,tin1); tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); -+ tout0=tin[0]^xor0; -+ tout1=tin[1]^xor1; -+ l2c(tout0,out); -+ l2c(tout1,out); -+ xor0=tin0; -+ xor1=tin1; -+ } -+ if (l != -8) -+ { -+ c2l(in,tin0); tin[0]=tin0; -+ c2l(in,tin1); tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); -+ tout0=tin[0]^xor0; -+ tout1=tin[1]^xor1; -+ l2cn(tout0,tout1,out,l+8); -+ xor0=tin0; -+ xor1=tin1; -+ } -+ -+ iv=(unsigned char *)ivec; -+ l2c(xor0,iv); -+ l2c(xor1,iv); -+ } -+ tin0=tin1=tout0=tout1=xor0=xor1=0; -+ tin[0]=tin[1]=0; -+ } -+ -+void des_ede3_cbc_encrypt(input, output, length, ks1, ks2, ks3, ivec, enc) -+des_cblock (*input); -+des_cblock (*output); -+long length; -+des_key_schedule ks1; -+des_key_schedule ks2; -+des_key_schedule ks3; -+des_cblock (*ivec); -+int enc; -+ { -+ register DES_LONG tin0,tin1; -+ register DES_LONG tout0,tout1,xor0,xor1; -+ register unsigned char *in,*out; -+ register long l=length; -+ DES_LONG tin[2]; -+ unsigned char *iv; -+ -+ in=(unsigned char *)input; -+ out=(unsigned char *)output; -+ iv=(unsigned char *)ivec; -+ -+ if (enc) -+ { -+ c2l(iv,tout0); -+ c2l(iv,tout1); -+ for (l-=8; l>=0; l-=8) -+ { -+ c2l(in,tin0); -+ c2l(in,tin1); -+ tin0^=tout0; -+ tin1^=tout1; -+ -+ tin[0]=tin0; -+ tin[1]=tin1; -+ des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); -+ tout0=tin[0]; -+ tout1=tin[1]; -+ -+ l2c(tout0,out); -+ l2c(tout1,out); -+ } -+ if (l != -8) -+ { -+ c2ln(in,tin0,tin1,l+8); -+ tin0^=tout0; -+ tin1^=tout1; -+ -+ tin[0]=tin0; -+ tin[1]=tin1; -+ des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); -+ tout0=tin[0]; -+ tout1=tin[1]; -+ -+ l2c(tout0,out); -+ l2c(tout1,out); -+ } -+ iv=(unsigned char *)ivec; -+ l2c(tout0,iv); -+ l2c(tout1,iv); -+ } -+ else -+ { -+ register DES_LONG t0,t1; -+ -+ c2l(iv,xor0); -+ c2l(iv,xor1); -+ for (l-=8; l>=0; l-=8) -+ { -+ c2l(in,tin0); -+ c2l(in,tin1); -+ -+ t0=tin0; -+ t1=tin1; -+ -+ tin[0]=tin0; -+ tin[1]=tin1; -+ des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); -+ tout0=tin[0]; -+ tout1=tin[1]; -+ -+ tout0^=xor0; -+ tout1^=xor1; -+ l2c(tout0,out); -+ l2c(tout1,out); -+ xor0=t0; -+ xor1=t1; -+ } -+ if (l != -8) -+ { -+ c2l(in,tin0); -+ c2l(in,tin1); -+ -+ t0=tin0; -+ t1=tin1; -+ -+ tin[0]=tin0; -+ tin[1]=tin1; -+ des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); -+ tout0=tin[0]; -+ tout1=tin[1]; -+ -+ tout0^=xor0; -+ tout1^=xor1; -+ l2cn(tout0,tout1,out,l+8); -+ xor0=t0; -+ xor1=t1; -+ } -+ -+ iv=(unsigned char *)ivec; -+ l2c(xor0,iv); -+ l2c(xor1,iv); -+ } -+ tin0=tin1=tout0=tout1=xor0=xor1=0; -+ tin[0]=tin[1]=0; -+ } -+ -+#endif /* DES_DEFAULT_OPTIONS */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/des_locl.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,515 @@ -+/* crypto/des/des_locl.org */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING -+ * -+ * Always modify des_locl.org since des_locl.h is automatically generated from -+ * it during SSLeay configuration. -+ * -+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING -+ */ -+ -+#ifndef HEADER_DES_LOCL_H -+#define HEADER_DES_LOCL_H -+ -+#if defined(WIN32) || defined(WIN16) -+#ifndef MSDOS -+#define MSDOS -+#endif -+#endif -+ -+#include "crypto/des.h" -+ -+#ifndef DES_DEFAULT_OPTIONS -+/* the following is tweaked from a config script, that is why it is a -+ * protected undef/define */ -+#ifndef DES_PTR -+#define DES_PTR -+#endif -+ -+/* This helps C compiler generate the correct code for multiple functional -+ * units. It reduces register dependancies at the expense of 2 more -+ * registers */ -+#ifndef DES_RISC1 -+#define DES_RISC1 -+#endif -+ -+#ifndef DES_RISC2 -+#undef DES_RISC2 -+#endif -+ -+#if defined(DES_RISC1) && defined(DES_RISC2) -+YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! -+#endif -+ -+/* Unroll the inner loop, this sometimes helps, sometimes hinders. -+ * Very mucy CPU dependant */ -+#ifndef DES_UNROLL -+#define DES_UNROLL -+#endif -+ -+/* These default values were supplied by -+ * Peter Gutman -+ * They are only used if nothing else has been defined */ -+#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) -+/* Special defines which change the way the code is built depending on the -+ CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find -+ even newer MIPS CPU's, but at the moment one size fits all for -+ optimization options. Older Sparc's work better with only UNROLL, but -+ there's no way to tell at compile time what it is you're running on */ -+ -+#if defined( sun ) /* Newer Sparc's */ -+ #define DES_PTR -+ #define DES_RISC1 -+ #define DES_UNROLL -+#elif defined( __ultrix ) /* Older MIPS */ -+ #define DES_PTR -+ #define DES_RISC2 -+ #define DES_UNROLL -+#elif defined( __osf1__ ) /* Alpha */ -+ #define DES_PTR -+ #define DES_RISC2 -+#elif defined ( _AIX ) /* RS6000 */ -+ /* Unknown */ -+#elif defined( __hpux ) /* HP-PA */ -+ /* Unknown */ -+#elif defined( __aux ) /* 68K */ -+ /* Unknown */ -+#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ -+ #define DES_UNROLL -+#elif defined( __sgi ) /* Newer MIPS */ -+ #define DES_PTR -+ #define DES_RISC2 -+ #define DES_UNROLL -+#elif defined( i386 ) /* x86 boxes, should be gcc */ -+ #define DES_PTR -+ #define DES_RISC1 -+ #define DES_UNROLL -+#endif /* Systems-specific speed defines */ -+#endif -+ -+#endif /* DES_DEFAULT_OPTIONS */ -+ -+#ifdef MSDOS /* Visual C++ 2.1 (Windows NT/95) */ -+#include -+#include -+#include -+#include -+#ifndef RAND -+#define RAND -+#endif -+#undef NOPROTO -+#endif -+ -+#if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS) -+#ifndef __KERNEL__ -+#include -+#else -+#include -+#endif -+#endif -+ -+#ifndef RAND -+#define RAND -+#endif -+ -+#ifdef linux -+#undef RAND -+#endif -+ -+#ifdef MSDOS -+#define getpid() 2 -+#define RAND -+#undef NOPROTO -+#endif -+ -+#if defined(NOCONST) -+#define const -+#endif -+ -+#ifdef __STDC__ -+#undef NOPROTO -+#endif -+ -+#ifdef RAND -+#define srandom(s) srand(s) -+#define random rand -+#endif -+ -+#define ITERATIONS 16 -+#define HALF_ITERATIONS 8 -+ -+/* used in des_read and des_write */ -+#define MAXWRITE (1024*16) -+#define BSIZE (MAXWRITE+4) -+ -+#define c2l(c,l) (l =((DES_LONG)(*((c)++))) , \ -+ l|=((DES_LONG)(*((c)++)))<< 8L, \ -+ l|=((DES_LONG)(*((c)++)))<<16L, \ -+ l|=((DES_LONG)(*((c)++)))<<24L) -+ -+/* NOTE - c is not incremented as per c2l */ -+#define c2ln(c,l1,l2,n) { \ -+ c+=n; \ -+ l1=l2=0; \ -+ switch (n) { \ -+ case 8: l2 =((DES_LONG)(*(--(c))))<<24L; \ -+ case 7: l2|=((DES_LONG)(*(--(c))))<<16L; \ -+ case 6: l2|=((DES_LONG)(*(--(c))))<< 8L; \ -+ case 5: l2|=((DES_LONG)(*(--(c)))); \ -+ case 4: l1 =((DES_LONG)(*(--(c))))<<24L; \ -+ case 3: l1|=((DES_LONG)(*(--(c))))<<16L; \ -+ case 2: l1|=((DES_LONG)(*(--(c))))<< 8L; \ -+ case 1: l1|=((DES_LONG)(*(--(c)))); \ -+ } \ -+ } -+ -+#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ -+ *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ -+ *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ -+ *((c)++)=(unsigned char)(((l)>>24L)&0xff)) -+ -+/* replacements for htonl and ntohl since I have no idea what to do -+ * when faced with machines with 8 byte longs. */ -+#define HDRSIZE 4 -+ -+#define n2l(c,l) (l =((DES_LONG)(*((c)++)))<<24L, \ -+ l|=((DES_LONG)(*((c)++)))<<16L, \ -+ l|=((DES_LONG)(*((c)++)))<< 8L, \ -+ l|=((DES_LONG)(*((c)++)))) -+ -+#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ -+ *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ -+ *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ -+ *((c)++)=(unsigned char)(((l) )&0xff)) -+ -+/* NOTE - c is not incremented as per l2c */ -+#define l2cn(l1,l2,c,n) { \ -+ c+=n; \ -+ switch (n) { \ -+ case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ -+ case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ -+ case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ -+ case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ -+ case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ -+ case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ -+ case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ -+ case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ -+ } \ -+ } -+ -+#if defined(WIN32) -+#define ROTATE(a,n) (_lrotr(a,n)) -+#else -+#define ROTATE(a,n) (((a)>>(n))+((a)<<(32-(n)))) -+#endif -+ -+/* Don't worry about the LOAD_DATA() stuff, that is used by -+ * fcrypt() to add it's little bit to the front */ -+ -+#ifdef DES_FCRYPT -+ -+#define LOAD_DATA_tmp(R,S,u,t,E0,E1) \ -+ { DES_LONG tmp; LOAD_DATA(R,S,u,t,E0,E1,tmp); } -+ -+#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ -+ t=R^(R>>16L); \ -+ u=t&E0; t&=E1; \ -+ tmp=(u<<16); u^=R^s[S ]; u^=tmp; \ -+ tmp=(t<<16); t^=R^s[S+1]; t^=tmp -+#else -+#define LOAD_DATA_tmp(a,b,c,d,e,f) LOAD_DATA(a,b,c,d,e,f,g) -+#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ -+ u=R^s[S ]; \ -+ t=R^s[S+1] -+#endif -+ -+/* The changes to this macro may help or hinder, depending on the -+ * compiler and the achitecture. gcc2 always seems to do well :-). -+ * Inspired by Dana How -+ * DO NOT use the alternative version on machines with 8 byte longs. -+ * It does not seem to work on the Alpha, even when DES_LONG is 4 -+ * bytes, probably an issue of accessing non-word aligned objects :-( */ -+#ifdef DES_PTR -+ -+/* It recently occured to me that 0^0^0^0^0^0^0 == 0, so there -+ * is no reason to not xor all the sub items together. This potentially -+ * saves a register since things can be xored directly into L */ -+ -+#if defined(DES_RISC1) || defined(DES_RISC2) -+#ifdef DES_RISC1 -+#define D_ENCRYPT(LL,R,S) { \ -+ unsigned int u1,u2,u3; \ -+ LOAD_DATA(R,S,u,t,E0,E1,u1); \ -+ u2=(int)u>>8L; \ -+ u1=(int)u&0xfc; \ -+ u2&=0xfc; \ -+ t=ROTATE(t,4); \ -+ u>>=16L; \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP +u1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \ -+ u3=(int)(u>>8L); \ -+ u1=(int)u&0xfc; \ -+ u3&=0xfc; \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+u1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+u3); \ -+ u2=(int)t>>8L; \ -+ u1=(int)t&0xfc; \ -+ u2&=0xfc; \ -+ t>>=16L; \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \ -+ u3=(int)t>>8L; \ -+ u1=(int)t&0xfc; \ -+ u3&=0xfc; \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+u1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+u3); } -+#endif -+#ifdef DES_RISC2 -+#define D_ENCRYPT(LL,R,S) { \ -+ unsigned int u1,u2,s1,s2; \ -+ LOAD_DATA(R,S,u,t,E0,E1,u1); \ -+ u2=(int)u>>8L; \ -+ u1=(int)u&0xfc; \ -+ u2&=0xfc; \ -+ t=ROTATE(t,4); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP +u1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \ -+ s1=(int)(u>>16L); \ -+ s2=(int)(u>>24L); \ -+ s1&=0xfc; \ -+ s2&=0xfc; \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+s1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+s2); \ -+ u2=(int)t>>8L; \ -+ u1=(int)t&0xfc; \ -+ u2&=0xfc; \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \ -+ s1=(int)(t>>16L); \ -+ s2=(int)(t>>24L); \ -+ s1&=0xfc; \ -+ s2&=0xfc; \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+s1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+s2); } -+#endif -+#else -+#define D_ENCRYPT(LL,R,S) { \ -+ LOAD_DATA_tmp(R,S,u,t,E0,E1); \ -+ t=ROTATE(t,4); \ -+ LL^= \ -+ *(DES_LONG *)((unsigned char *)des_SP +((u )&0xfc))^ \ -+ *(DES_LONG *)((unsigned char *)des_SP+0x200+((u>> 8L)&0xfc))^ \ -+ *(DES_LONG *)((unsigned char *)des_SP+0x400+((u>>16L)&0xfc))^ \ -+ *(DES_LONG *)((unsigned char *)des_SP+0x600+((u>>24L)&0xfc))^ \ -+ *(DES_LONG *)((unsigned char *)des_SP+0x100+((t )&0xfc))^ \ -+ *(DES_LONG *)((unsigned char *)des_SP+0x300+((t>> 8L)&0xfc))^ \ -+ *(DES_LONG *)((unsigned char *)des_SP+0x500+((t>>16L)&0xfc))^ \ -+ *(DES_LONG *)((unsigned char *)des_SP+0x700+((t>>24L)&0xfc)); } -+#endif -+ -+#else /* original version */ -+ -+#if defined(DES_RISC1) || defined(DES_RISC2) -+#ifdef DES_RISC1 -+#define D_ENCRYPT(LL,R,S) {\ -+ unsigned int u1,u2,u3; \ -+ LOAD_DATA(R,S,u,t,E0,E1,u1); \ -+ u>>=2L; \ -+ t=ROTATE(t,6); \ -+ u2=(int)u>>8L; \ -+ u1=(int)u&0x3f; \ -+ u2&=0x3f; \ -+ u>>=16L; \ -+ LL^=des_SPtrans[0][u1]; \ -+ LL^=des_SPtrans[2][u2]; \ -+ u3=(int)u>>8L; \ -+ u1=(int)u&0x3f; \ -+ u3&=0x3f; \ -+ LL^=des_SPtrans[4][u1]; \ -+ LL^=des_SPtrans[6][u3]; \ -+ u2=(int)t>>8L; \ -+ u1=(int)t&0x3f; \ -+ u2&=0x3f; \ -+ t>>=16L; \ -+ LL^=des_SPtrans[1][u1]; \ -+ LL^=des_SPtrans[3][u2]; \ -+ u3=(int)t>>8L; \ -+ u1=(int)t&0x3f; \ -+ u3&=0x3f; \ -+ LL^=des_SPtrans[5][u1]; \ -+ LL^=des_SPtrans[7][u3]; } -+#endif -+#ifdef DES_RISC2 -+#define D_ENCRYPT(LL,R,S) {\ -+ unsigned int u1,u2,s1,s2; \ -+ LOAD_DATA(R,S,u,t,E0,E1,u1); \ -+ u>>=2L; \ -+ t=ROTATE(t,6); \ -+ u2=(int)u>>8L; \ -+ u1=(int)u&0x3f; \ -+ u2&=0x3f; \ -+ LL^=des_SPtrans[0][u1]; \ -+ LL^=des_SPtrans[2][u2]; \ -+ s1=(int)u>>16L; \ -+ s2=(int)u>>24L; \ -+ s1&=0x3f; \ -+ s2&=0x3f; \ -+ LL^=des_SPtrans[4][s1]; \ -+ LL^=des_SPtrans[6][s2]; \ -+ u2=(int)t>>8L; \ -+ u1=(int)t&0x3f; \ -+ u2&=0x3f; \ -+ LL^=des_SPtrans[1][u1]; \ -+ LL^=des_SPtrans[3][u2]; \ -+ s1=(int)t>>16; \ -+ s2=(int)t>>24L; \ -+ s1&=0x3f; \ -+ s2&=0x3f; \ -+ LL^=des_SPtrans[5][s1]; \ -+ LL^=des_SPtrans[7][s2]; } -+#endif -+ -+#else -+ -+#define D_ENCRYPT(LL,R,S) {\ -+ LOAD_DATA_tmp(R,S,u,t,E0,E1); \ -+ t=ROTATE(t,4); \ -+ LL^=\ -+ des_SPtrans[0][(u>> 2L)&0x3f]^ \ -+ des_SPtrans[2][(u>>10L)&0x3f]^ \ -+ des_SPtrans[4][(u>>18L)&0x3f]^ \ -+ des_SPtrans[6][(u>>26L)&0x3f]^ \ -+ des_SPtrans[1][(t>> 2L)&0x3f]^ \ -+ des_SPtrans[3][(t>>10L)&0x3f]^ \ -+ des_SPtrans[5][(t>>18L)&0x3f]^ \ -+ des_SPtrans[7][(t>>26L)&0x3f]; } -+#endif -+#endif -+ -+ /* IP and FP -+ * The problem is more of a geometric problem that random bit fiddling. -+ 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 -+ 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 -+ 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 -+ 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 -+ -+ 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 -+ 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 -+ 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 -+ 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 -+ -+ The output has been subject to swaps of the form -+ 0 1 -> 3 1 but the odd and even bits have been put into -+ 2 3 2 0 -+ different words. The main trick is to remember that -+ t=((l>>size)^r)&(mask); -+ r^=t; -+ l^=(t<>(n))^(b))&(m)),\ -+ (b)^=(t),\ -+ (a)^=((t)<<(n))) -+ -+#define IP(l,r) \ -+ { \ -+ register DES_LONG tt; \ -+ PERM_OP(r,l,tt, 4,0x0f0f0f0fL); \ -+ PERM_OP(l,r,tt,16,0x0000ffffL); \ -+ PERM_OP(r,l,tt, 2,0x33333333L); \ -+ PERM_OP(l,r,tt, 8,0x00ff00ffL); \ -+ PERM_OP(r,l,tt, 1,0x55555555L); \ -+ } -+ -+#define FP(l,r) \ -+ { \ -+ register DES_LONG tt; \ -+ PERM_OP(l,r,tt, 1,0x55555555L); \ -+ PERM_OP(r,l,tt, 8,0x00ff00ffL); \ -+ PERM_OP(l,r,tt, 2,0x33333333L); \ -+ PERM_OP(r,l,tt,16,0x0000ffffL); \ -+ PERM_OP(l,r,tt, 4,0x0f0f0f0fL); \ -+ } -+ -+extern const DES_LONG des_SPtrans[8][64]; -+ -+#ifndef NOPROTO -+void fcrypt_body(DES_LONG *out,des_key_schedule ks, -+ DES_LONG Eswap0, DES_LONG Eswap1); -+#else -+void fcrypt_body(); -+#endif -+ -+#endif ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/des_opts.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,620 @@ -+/* crypto/des/des_opts.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+/* define PART1, PART2, PART3 or PART4 to build only with a few of the options. -+ * This is for machines with 64k code segment size restrictions. */ -+ -+#ifndef MSDOS -+#define TIMES -+#endif -+ -+#include -+#ifndef MSDOS -+#include -+#else -+#include -+extern void exit(); -+#endif -+#include -+#ifndef VMS -+#ifndef _IRIX -+#include -+#endif -+#ifdef TIMES -+#include -+#include -+#endif -+#else /* VMS */ -+#include -+struct tms { -+ time_t tms_utime; -+ time_t tms_stime; -+ time_t tms_uchild; /* I dunno... */ -+ time_t tms_uchildsys; /* so these names are a guess :-) */ -+ } -+#endif -+#ifndef TIMES -+#include -+#endif -+ -+#ifdef sun -+#include -+#include -+#endif -+ -+#include "des_locl.h" -+#include "spr.h" -+ -+#define DES_DEFAULT_OPTIONS -+ -+#if !defined(PART1) && !defined(PART2) && !defined(PART3) && !defined(PART4) -+#define PART1 -+#define PART2 -+#define PART3 -+#define PART4 -+#endif -+ -+#ifdef PART1 -+ -+#undef DES_UNROLL -+#undef DES_RISC1 -+#undef DES_RISC2 -+#undef DES_PTR -+#undef D_ENCRYPT -+#define des_encrypt des_encrypt_u4_cisc_idx -+#define des_encrypt2 des_encrypt2_u4_cisc_idx -+#define des_encrypt3 des_encrypt3_u4_cisc_idx -+#define des_decrypt3 des_decrypt3_u4_cisc_idx -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#define DES_UNROLL -+#undef DES_RISC1 -+#undef DES_RISC2 -+#undef DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u16_cisc_idx -+#define des_encrypt2 des_encrypt2_u16_cisc_idx -+#define des_encrypt3 des_encrypt3_u16_cisc_idx -+#define des_decrypt3 des_decrypt3_u16_cisc_idx -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#undef DES_UNROLL -+#define DES_RISC1 -+#undef DES_RISC2 -+#undef DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u4_risc1_idx -+#define des_encrypt2 des_encrypt2_u4_risc1_idx -+#define des_encrypt3 des_encrypt3_u4_risc1_idx -+#define des_decrypt3 des_decrypt3_u4_risc1_idx -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#endif -+ -+#ifdef PART2 -+ -+#undef DES_UNROLL -+#undef DES_RISC1 -+#define DES_RISC2 -+#undef DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u4_risc2_idx -+#define des_encrypt2 des_encrypt2_u4_risc2_idx -+#define des_encrypt3 des_encrypt3_u4_risc2_idx -+#define des_decrypt3 des_decrypt3_u4_risc2_idx -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#define DES_UNROLL -+#define DES_RISC1 -+#undef DES_RISC2 -+#undef DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u16_risc1_idx -+#define des_encrypt2 des_encrypt2_u16_risc1_idx -+#define des_encrypt3 des_encrypt3_u16_risc1_idx -+#define des_decrypt3 des_decrypt3_u16_risc1_idx -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#define DES_UNROLL -+#undef DES_RISC1 -+#define DES_RISC2 -+#undef DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u16_risc2_idx -+#define des_encrypt2 des_encrypt2_u16_risc2_idx -+#define des_encrypt3 des_encrypt3_u16_risc2_idx -+#define des_decrypt3 des_decrypt3_u16_risc2_idx -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#endif -+ -+#ifdef PART3 -+ -+#undef DES_UNROLL -+#undef DES_RISC1 -+#undef DES_RISC2 -+#define DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u4_cisc_ptr -+#define des_encrypt2 des_encrypt2_u4_cisc_ptr -+#define des_encrypt3 des_encrypt3_u4_cisc_ptr -+#define des_decrypt3 des_decrypt3_u4_cisc_ptr -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#define DES_UNROLL -+#undef DES_RISC1 -+#undef DES_RISC2 -+#define DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u16_cisc_ptr -+#define des_encrypt2 des_encrypt2_u16_cisc_ptr -+#define des_encrypt3 des_encrypt3_u16_cisc_ptr -+#define des_decrypt3 des_decrypt3_u16_cisc_ptr -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#undef DES_UNROLL -+#define DES_RISC1 -+#undef DES_RISC2 -+#define DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u4_risc1_ptr -+#define des_encrypt2 des_encrypt2_u4_risc1_ptr -+#define des_encrypt3 des_encrypt3_u4_risc1_ptr -+#define des_decrypt3 des_decrypt3_u4_risc1_ptr -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#endif -+ -+#ifdef PART4 -+ -+#undef DES_UNROLL -+#undef DES_RISC1 -+#define DES_RISC2 -+#define DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u4_risc2_ptr -+#define des_encrypt2 des_encrypt2_u4_risc2_ptr -+#define des_encrypt3 des_encrypt3_u4_risc2_ptr -+#define des_decrypt3 des_decrypt3_u4_risc2_ptr -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#define DES_UNROLL -+#define DES_RISC1 -+#undef DES_RISC2 -+#define DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u16_risc1_ptr -+#define des_encrypt2 des_encrypt2_u16_risc1_ptr -+#define des_encrypt3 des_encrypt3_u16_risc1_ptr -+#define des_decrypt3 des_decrypt3_u16_risc1_ptr -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#define DES_UNROLL -+#undef DES_RISC1 -+#define DES_RISC2 -+#define DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u16_risc2_ptr -+#define des_encrypt2 des_encrypt2_u16_risc2_ptr -+#define des_encrypt3 des_encrypt3_u16_risc2_ptr -+#define des_decrypt3 des_decrypt3_u16_risc2_ptr -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#endif -+ -+/* The following if from times(3) man page. It may need to be changed */ -+#ifndef HZ -+# ifndef CLK_TCK -+# ifndef _BSD_CLK_TCK_ /* FreeBSD fix */ -+# ifndef VMS -+# define HZ 100.0 -+# else /* VMS */ -+# define HZ 100.0 -+# endif -+# else /* _BSD_CLK_TCK_ */ -+# define HZ ((double)_BSD_CLK_TCK_) -+# endif -+# else /* CLK_TCK */ -+# define HZ ((double)CLK_TCK) -+# endif -+#endif -+ -+#define BUFSIZE ((long)1024) -+long run=0; -+ -+#ifndef NOPROTO -+double Time_F(int s); -+#else -+double Time_F(); -+#endif -+ -+#ifdef SIGALRM -+#if defined(__STDC__) || defined(sgi) -+#define SIGRETTYPE void -+#else -+#define SIGRETTYPE int -+#endif -+ -+#ifndef NOPROTO -+SIGRETTYPE sig_done(int sig); -+#else -+SIGRETTYPE sig_done(); -+#endif -+ -+SIGRETTYPE sig_done(sig) -+int sig; -+ { -+ signal(SIGALRM,sig_done); -+ run=0; -+#ifdef LINT -+ sig=sig; -+#endif -+ } -+#endif -+ -+#define START 0 -+#define STOP 1 -+ -+double Time_F(s) -+int s; -+ { -+ double ret; -+#ifdef TIMES -+ static struct tms tstart,tend; -+ -+ if (s == START) -+ { -+ times(&tstart); -+ return(0); -+ } -+ else -+ { -+ times(&tend); -+ ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ; -+ return((ret == 0.0)?1e-6:ret); -+ } -+#else /* !times() */ -+ static struct timeb tstart,tend; -+ long i; -+ -+ if (s == START) -+ { -+ ftime(&tstart); -+ return(0); -+ } -+ else -+ { -+ ftime(&tend); -+ i=(long)tend.millitm-(long)tstart.millitm; -+ ret=((double)(tend.time-tstart.time))+((double)i)/1000.0; -+ return((ret == 0.0)?1e-6:ret); -+ } -+#endif -+ } -+ -+#ifdef SIGALRM -+#define print_name(name) fprintf(stderr,"Doing %s's for 10 seconds\n",name); alarm(10); -+#else -+#define print_name(name) fprintf(stderr,"Doing %s %ld times\n",name,cb); -+#endif -+ -+#define time_it(func,name,index) \ -+ print_name(name); \ -+ Time_F(START); \ -+ for (count=0,run=1; COND(cb); count++) \ -+ { \ -+ unsigned long d[2]; \ -+ func(d,&(sch[0]),DES_ENCRYPT); \ -+ } \ -+ tm[index]=Time_F(STOP); \ -+ fprintf(stderr,"%ld %s's in %.2f second\n",count,name,tm[index]); \ -+ tm[index]=((double)COUNT(cb))/tm[index]; -+ -+#define print_it(name,index) \ -+ fprintf(stderr,"%s bytes per sec = %12.2f (%5.1fuS)\n",name, \ -+ tm[index]*8,1.0e6/tm[index]); -+ -+int main(argc,argv) -+int argc; -+char **argv; -+ { -+ long count; -+ static unsigned char buf[BUFSIZE]; -+ static des_cblock key ={0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0}; -+ static des_cblock key2={0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12}; -+ static des_cblock key3={0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34}; -+ des_key_schedule sch,sch2,sch3; -+ double d,tm[16],max=0; -+ int rank[16]; -+ char *str[16]; -+ int max_idx=0,i,num=0,j; -+#ifndef SIGALARM -+ long ca,cb,cc,cd,ce; -+#endif -+ -+ for (i=0; i<12; i++) -+ { -+ tm[i]=0.0; -+ rank[i]=0; -+ } -+ -+#ifndef TIMES -+ fprintf(stderr,"To get the most acurate results, try to run this\n"); -+ fprintf(stderr,"program when this computer is idle.\n"); -+#endif -+ -+ des_set_key((C_Block *)key,sch); -+ des_set_key((C_Block *)key2,sch2); -+ des_set_key((C_Block *)key3,sch3); -+ -+#ifndef SIGALRM -+ fprintf(stderr,"First we calculate the approximate speed ...\n"); -+ des_set_key((C_Block *)key,sch); -+ count=10; -+ do { -+ long i; -+ unsigned long data[2]; -+ -+ count*=2; -+ Time_F(START); -+ for (i=count; i; i--) -+ des_encrypt(data,&(sch[0]),DES_ENCRYPT); -+ d=Time_F(STOP); -+ } while (d < 3.0); -+ ca=count; -+ cb=count*3; -+ cc=count*3*8/BUFSIZE+1; -+ cd=count*8/BUFSIZE+1; -+ -+ ce=count/20+1; -+#define COND(d) (count != (d)) -+#define COUNT(d) (d) -+#else -+#define COND(c) (run) -+#define COUNT(d) (count) -+ signal(SIGALRM,sig_done); -+ alarm(10); -+#endif -+ -+#ifdef PART1 -+ time_it(des_encrypt_u4_cisc_idx, "des_encrypt_u4_cisc_idx ", 0); -+ time_it(des_encrypt_u16_cisc_idx, "des_encrypt_u16_cisc_idx ", 1); -+ time_it(des_encrypt_u4_risc1_idx, "des_encrypt_u4_risc1_idx ", 2); -+ num+=3; -+#endif -+#ifdef PART2 -+ time_it(des_encrypt_u16_risc1_idx,"des_encrypt_u16_risc1_idx", 3); -+ time_it(des_encrypt_u4_risc2_idx, "des_encrypt_u4_risc2_idx ", 4); -+ time_it(des_encrypt_u16_risc2_idx,"des_encrypt_u16_risc2_idx", 5); -+ num+=3; -+#endif -+#ifdef PART3 -+ time_it(des_encrypt_u4_cisc_ptr, "des_encrypt_u4_cisc_ptr ", 6); -+ time_it(des_encrypt_u16_cisc_ptr, "des_encrypt_u16_cisc_ptr ", 7); -+ time_it(des_encrypt_u4_risc1_ptr, "des_encrypt_u4_risc1_ptr ", 8); -+ num+=3; -+#endif -+#ifdef PART4 -+ time_it(des_encrypt_u16_risc1_ptr,"des_encrypt_u16_risc1_ptr", 9); -+ time_it(des_encrypt_u4_risc2_ptr, "des_encrypt_u4_risc2_ptr ",10); -+ time_it(des_encrypt_u16_risc2_ptr,"des_encrypt_u16_risc2_ptr",11); -+ num+=3; -+#endif -+ -+#ifdef PART1 -+ str[0]=" 4 c i"; -+ print_it("des_encrypt_u4_cisc_idx ",0); -+ max=tm[0]; -+ max_idx=0; -+ str[1]="16 c i"; -+ print_it("des_encrypt_u16_cisc_idx ",1); -+ if (max < tm[1]) { max=tm[1]; max_idx=1; } -+ str[2]=" 4 r1 i"; -+ print_it("des_encrypt_u4_risc1_idx ",2); -+ if (max < tm[2]) { max=tm[2]; max_idx=2; } -+#endif -+#ifdef PART2 -+ str[3]="16 r1 i"; -+ print_it("des_encrypt_u16_risc1_idx",3); -+ if (max < tm[3]) { max=tm[3]; max_idx=3; } -+ str[4]=" 4 r2 i"; -+ print_it("des_encrypt_u4_risc2_idx ",4); -+ if (max < tm[4]) { max=tm[4]; max_idx=4; } -+ str[5]="16 r2 i"; -+ print_it("des_encrypt_u16_risc2_idx",5); -+ if (max < tm[5]) { max=tm[5]; max_idx=5; } -+#endif -+#ifdef PART3 -+ str[6]=" 4 c p"; -+ print_it("des_encrypt_u4_cisc_ptr ",6); -+ if (max < tm[6]) { max=tm[6]; max_idx=6; } -+ str[7]="16 c p"; -+ print_it("des_encrypt_u16_cisc_ptr ",7); -+ if (max < tm[7]) { max=tm[7]; max_idx=7; } -+ str[8]=" 4 r1 p"; -+ print_it("des_encrypt_u4_risc1_ptr ",8); -+ if (max < tm[8]) { max=tm[8]; max_idx=8; } -+#endif -+#ifdef PART4 -+ str[9]="16 r1 p"; -+ print_it("des_encrypt_u16_risc1_ptr",9); -+ if (max < tm[9]) { max=tm[9]; max_idx=9; } -+ str[10]=" 4 r2 p"; -+ print_it("des_encrypt_u4_risc2_ptr ",10); -+ if (max < tm[10]) { max=tm[10]; max_idx=10; } -+ str[11]="16 r2 p"; -+ print_it("des_encrypt_u16_risc2_ptr",11); -+ if (max < tm[11]) { max=tm[11]; max_idx=11; } -+#endif -+ printf("options des ecb/s\n"); -+ printf("%s %12.2f 100.0%%\n",str[max_idx],tm[max_idx]); -+ d=tm[max_idx]; -+ tm[max_idx]= -2.0; -+ max= -1.0; -+ for (;;) -+ { -+ for (i=0; i<12; i++) -+ { -+ if (max < tm[i]) { max=tm[i]; j=i; } -+ } -+ if (max < 0.0) break; -+ printf("%s %12.2f %4.1f%%\n",str[j],tm[j],tm[j]/d*100.0); -+ tm[j]= -2.0; -+ max= -1.0; -+ } -+ -+ switch (max_idx) -+ { -+ case 0: -+ printf("-DDES_DEFAULT_OPTIONS\n"); -+ break; -+ case 1: -+ printf("-DDES_UNROLL\n"); -+ break; -+ case 2: -+ printf("-DDES_RISC1\n"); -+ break; -+ case 3: -+ printf("-DDES_UNROLL -DDES_RISC1\n"); -+ break; -+ case 4: -+ printf("-DDES_RISC2\n"); -+ break; -+ case 5: -+ printf("-DDES_UNROLL -DDES_RISC2\n"); -+ break; -+ case 6: -+ printf("-DDES_PTR\n"); -+ break; -+ case 7: -+ printf("-DDES_UNROLL -DDES_PTR\n"); -+ break; -+ case 8: -+ printf("-DDES_RISC1 -DDES_PTR\n"); -+ break; -+ case 9: -+ printf("-DDES_UNROLL -DDES_RISC1 -DDES_PTR\n"); -+ break; -+ case 10: -+ printf("-DDES_RISC2 -DDES_PTR\n"); -+ break; -+ case 11: -+ printf("-DDES_UNROLL -DDES_RISC2 -DDES_PTR\n"); -+ break; -+ } -+ exit(0); -+#if defined(LINT) || defined(MSDOS) -+ return(0); -+#endif -+ } ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/des_ver.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,60 @@ -+/* crypto/des/des_ver.h */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+extern char *DES_version; /* SSLeay version string */ -+extern char *libdes_version; /* old libdes version string */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/destest.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,871 @@ -+/* crypto/des/destest.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+#if defined(WIN32) || defined(WIN16) || defined(WINDOWS) -+#ifndef MSDOS -+#define MSDOS -+#endif -+#endif -+ -+#include -+#include -+#ifndef MSDOS -+#include -+#else -+#include -+#endif -+#include -+#include "des_locl.h" -+ -+/* tisk tisk - the test keys don't all have odd parity :-( */ -+/* test data */ -+#define NUM_TESTS 34 -+static unsigned char key_data[NUM_TESTS][8]={ -+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, -+ {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, -+ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, -+ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, -+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10}, -+ {0x7C,0xA1,0x10,0x45,0x4A,0x1A,0x6E,0x57}, -+ {0x01,0x31,0xD9,0x61,0x9D,0xC1,0x37,0x6E}, -+ {0x07,0xA1,0x13,0x3E,0x4A,0x0B,0x26,0x86}, -+ {0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E}, -+ {0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6}, -+ {0x01,0x13,0xB9,0x70,0xFD,0x34,0xF2,0xCE}, -+ {0x01,0x70,0xF1,0x75,0x46,0x8F,0xB5,0xE6}, -+ {0x43,0x29,0x7F,0xAD,0x38,0xE3,0x73,0xFE}, -+ {0x07,0xA7,0x13,0x70,0x45,0xDA,0x2A,0x16}, -+ {0x04,0x68,0x91,0x04,0xC2,0xFD,0x3B,0x2F}, -+ {0x37,0xD0,0x6B,0xB5,0x16,0xCB,0x75,0x46}, -+ {0x1F,0x08,0x26,0x0D,0x1A,0xC2,0x46,0x5E}, -+ {0x58,0x40,0x23,0x64,0x1A,0xBA,0x61,0x76}, -+ {0x02,0x58,0x16,0x16,0x46,0x29,0xB0,0x07}, -+ {0x49,0x79,0x3E,0xBC,0x79,0xB3,0x25,0x8F}, -+ {0x4F,0xB0,0x5E,0x15,0x15,0xAB,0x73,0xA7}, -+ {0x49,0xE9,0x5D,0x6D,0x4C,0xA2,0x29,0xBF}, -+ {0x01,0x83,0x10,0xDC,0x40,0x9B,0x26,0xD6}, -+ {0x1C,0x58,0x7F,0x1C,0x13,0x92,0x4F,0xEF}, -+ {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, -+ {0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E}, -+ {0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE}, -+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, -+ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, -+ {0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10}}; -+ -+static unsigned char plain_data[NUM_TESTS][8]={ -+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, -+ {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, -+ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, -+ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, -+ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, -+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, -+ {0x01,0xA1,0xD6,0xD0,0x39,0x77,0x67,0x42}, -+ {0x5C,0xD5,0x4C,0xA8,0x3D,0xEF,0x57,0xDA}, -+ {0x02,0x48,0xD4,0x38,0x06,0xF6,0x71,0x72}, -+ {0x51,0x45,0x4B,0x58,0x2D,0xDF,0x44,0x0A}, -+ {0x42,0xFD,0x44,0x30,0x59,0x57,0x7F,0xA2}, -+ {0x05,0x9B,0x5E,0x08,0x51,0xCF,0x14,0x3A}, -+ {0x07,0x56,0xD8,0xE0,0x77,0x47,0x61,0xD2}, -+ {0x76,0x25,0x14,0xB8,0x29,0xBF,0x48,0x6A}, -+ {0x3B,0xDD,0x11,0x90,0x49,0x37,0x28,0x02}, -+ {0x26,0x95,0x5F,0x68,0x35,0xAF,0x60,0x9A}, -+ {0x16,0x4D,0x5E,0x40,0x4F,0x27,0x52,0x32}, -+ {0x6B,0x05,0x6E,0x18,0x75,0x9F,0x5C,0xCA}, -+ {0x00,0x4B,0xD6,0xEF,0x09,0x17,0x60,0x62}, -+ {0x48,0x0D,0x39,0x00,0x6E,0xE7,0x62,0xF2}, -+ {0x43,0x75,0x40,0xC8,0x69,0x8F,0x3C,0xFA}, -+ {0x07,0x2D,0x43,0xA0,0x77,0x07,0x52,0x92}, -+ {0x02,0xFE,0x55,0x77,0x81,0x17,0xF1,0x2A}, -+ {0x1D,0x9D,0x5C,0x50,0x18,0xF7,0x28,0xC2}, -+ {0x30,0x55,0x32,0x28,0x6D,0x6F,0x29,0x5A}, -+ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, -+ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, -+ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, -+ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, -+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}; -+ -+static unsigned char cipher_data[NUM_TESTS][8]={ -+ {0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7}, -+ {0x73,0x59,0xB2,0x16,0x3E,0x4E,0xDC,0x58}, -+ {0x95,0x8E,0x6E,0x62,0x7A,0x05,0x55,0x7B}, -+ {0xF4,0x03,0x79,0xAB,0x9E,0x0E,0xC5,0x33}, -+ {0x17,0x66,0x8D,0xFC,0x72,0x92,0x53,0x2D}, -+ {0x8A,0x5A,0xE1,0xF8,0x1A,0xB8,0xF2,0xDD}, -+ {0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7}, -+ {0xED,0x39,0xD9,0x50,0xFA,0x74,0xBC,0xC4}, -+ {0x69,0x0F,0x5B,0x0D,0x9A,0x26,0x93,0x9B}, -+ {0x7A,0x38,0x9D,0x10,0x35,0x4B,0xD2,0x71}, -+ {0x86,0x8E,0xBB,0x51,0xCA,0xB4,0x59,0x9A}, -+ {0x71,0x78,0x87,0x6E,0x01,0xF1,0x9B,0x2A}, -+ {0xAF,0x37,0xFB,0x42,0x1F,0x8C,0x40,0x95}, -+ {0x86,0xA5,0x60,0xF1,0x0E,0xC6,0xD8,0x5B}, -+ {0x0C,0xD3,0xDA,0x02,0x00,0x21,0xDC,0x09}, -+ {0xEA,0x67,0x6B,0x2C,0xB7,0xDB,0x2B,0x7A}, -+ {0xDF,0xD6,0x4A,0x81,0x5C,0xAF,0x1A,0x0F}, -+ {0x5C,0x51,0x3C,0x9C,0x48,0x86,0xC0,0x88}, -+ {0x0A,0x2A,0xEE,0xAE,0x3F,0xF4,0xAB,0x77}, -+ {0xEF,0x1B,0xF0,0x3E,0x5D,0xFA,0x57,0x5A}, -+ {0x88,0xBF,0x0D,0xB6,0xD7,0x0D,0xEE,0x56}, -+ {0xA1,0xF9,0x91,0x55,0x41,0x02,0x0B,0x56}, -+ {0x6F,0xBF,0x1C,0xAF,0xCF,0xFD,0x05,0x56}, -+ {0x2F,0x22,0xE4,0x9B,0xAB,0x7C,0xA1,0xAC}, -+ {0x5A,0x6B,0x61,0x2C,0xC2,0x6C,0xCE,0x4A}, -+ {0x5F,0x4C,0x03,0x8E,0xD1,0x2B,0x2E,0x41}, -+ {0x63,0xFA,0xC0,0xD0,0x34,0xD9,0xF7,0x93}, -+ {0x61,0x7B,0x3A,0x0C,0xE8,0xF0,0x71,0x00}, -+ {0xDB,0x95,0x86,0x05,0xF8,0xC8,0xC6,0x06}, -+ {0xED,0xBF,0xD1,0xC6,0x6C,0x29,0xCC,0xC7}, -+ {0x35,0x55,0x50,0xB2,0x15,0x0E,0x24,0x51}, -+ {0xCA,0xAA,0xAF,0x4D,0xEA,0xF1,0xDB,0xAE}, -+ {0xD5,0xD4,0x4F,0xF7,0x20,0x68,0x3D,0x0D}, -+ {0x2A,0x2B,0xB0,0x08,0xDF,0x97,0xC2,0xF2}}; -+ -+static unsigned char cipher_ecb2[NUM_TESTS-1][8]={ -+ {0x92,0x95,0xB5,0x9B,0xB3,0x84,0x73,0x6E}, -+ {0x19,0x9E,0x9D,0x6D,0xF3,0x9A,0xA8,0x16}, -+ {0x2A,0x4B,0x4D,0x24,0x52,0x43,0x84,0x27}, -+ {0x35,0x84,0x3C,0x01,0x9D,0x18,0xC5,0xB6}, -+ {0x4A,0x5B,0x2F,0x42,0xAA,0x77,0x19,0x25}, -+ {0xA0,0x6B,0xA9,0xB8,0xCA,0x5B,0x17,0x8A}, -+ {0xAB,0x9D,0xB7,0xFB,0xED,0x95,0xF2,0x74}, -+ {0x3D,0x25,0x6C,0x23,0xA7,0x25,0x2F,0xD6}, -+ {0xB7,0x6F,0xAB,0x4F,0xBD,0xBD,0xB7,0x67}, -+ {0x8F,0x68,0x27,0xD6,0x9C,0xF4,0x1A,0x10}, -+ {0x82,0x57,0xA1,0xD6,0x50,0x5E,0x81,0x85}, -+ {0xA2,0x0F,0x0A,0xCD,0x80,0x89,0x7D,0xFA}, -+ {0xCD,0x2A,0x53,0x3A,0xDB,0x0D,0x7E,0xF3}, -+ {0xD2,0xC2,0xBE,0x27,0xE8,0x1B,0x68,0xE3}, -+ {0xE9,0x24,0xCF,0x4F,0x89,0x3C,0x5B,0x0A}, -+ {0xA7,0x18,0xC3,0x9F,0xFA,0x9F,0xD7,0x69}, -+ {0x77,0x2C,0x79,0xB1,0xD2,0x31,0x7E,0xB1}, -+ {0x49,0xAB,0x92,0x7F,0xD0,0x22,0x00,0xB7}, -+ {0xCE,0x1C,0x6C,0x7D,0x85,0xE3,0x4A,0x6F}, -+ {0xBE,0x91,0xD6,0xE1,0x27,0xB2,0xE9,0x87}, -+ {0x70,0x28,0xAE,0x8F,0xD1,0xF5,0x74,0x1A}, -+ {0xAA,0x37,0x80,0xBB,0xF3,0x22,0x1D,0xDE}, -+ {0xA6,0xC4,0xD2,0x5E,0x28,0x93,0xAC,0xB3}, -+ {0x22,0x07,0x81,0x5A,0xE4,0xB7,0x1A,0xAD}, -+ {0xDC,0xCE,0x05,0xE7,0x07,0xBD,0xF5,0x84}, -+ {0x26,0x1D,0x39,0x2C,0xB3,0xBA,0xA5,0x85}, -+ {0xB4,0xF7,0x0F,0x72,0xFB,0x04,0xF0,0xDC}, -+ {0x95,0xBA,0xA9,0x4E,0x87,0x36,0xF2,0x89}, -+ {0xD4,0x07,0x3A,0xF1,0x5A,0x17,0x82,0x0E}, -+ {0xEF,0x6F,0xAF,0xA7,0x66,0x1A,0x7E,0x89}, -+ {0xC1,0x97,0xF5,0x58,0x74,0x8A,0x20,0xE7}, -+ {0x43,0x34,0xCF,0xDA,0x22,0xC4,0x86,0xC8}, -+ {0x08,0xD7,0xB4,0xFB,0x62,0x9D,0x08,0x85}}; -+ -+static unsigned char cbc_key [8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; -+static unsigned char cbc2_key[8]={0xf0,0xe1,0xd2,0xc3,0xb4,0xa5,0x96,0x87}; -+static unsigned char cbc3_key[8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; -+static unsigned char cbc_iv [8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; -+static char cbc_data[40]="7654321 Now is the time for \0001"; -+ -+static unsigned char cbc_ok[32]={ -+ 0xcc,0xd1,0x73,0xff,0xab,0x20,0x39,0xf4, -+ 0xac,0xd8,0xae,0xfd,0xdf,0xd8,0xa1,0xeb, -+ 0x46,0x8e,0x91,0x15,0x78,0x88,0xba,0x68, -+ 0x1d,0x26,0x93,0x97,0xf7,0xfe,0x62,0xb4}; -+ -+static unsigned char xcbc_ok[32]={ -+ 0x86,0x74,0x81,0x0D,0x61,0xA4,0xA5,0x48, -+ 0xB9,0x93,0x03,0xE1,0xB8,0xBB,0xBD,0xBD, -+ 0x64,0x30,0x0B,0xB9,0x06,0x65,0x81,0x76, -+ 0x04,0x1D,0x77,0x62,0x17,0xCA,0x2B,0xD2, -+ }; -+ -+static unsigned char cbc3_ok[32]={ -+ 0x3F,0xE3,0x01,0xC9,0x62,0xAC,0x01,0xD0, -+ 0x22,0x13,0x76,0x3C,0x1C,0xBD,0x4C,0xDC, -+ 0x79,0x96,0x57,0xC0,0x64,0xEC,0xF5,0xD4, -+ 0x1C,0x67,0x38,0x12,0xCF,0xDE,0x96,0x75}; -+ -+static unsigned char pcbc_ok[32]={ -+ 0xcc,0xd1,0x73,0xff,0xab,0x20,0x39,0xf4, -+ 0x6d,0xec,0xb4,0x70,0xa0,0xe5,0x6b,0x15, -+ 0xae,0xa6,0xbf,0x61,0xed,0x7d,0x9c,0x9f, -+ 0xf7,0x17,0x46,0x3b,0x8a,0xb3,0xcc,0x88}; -+ -+static unsigned char cfb_key[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; -+static unsigned char cfb_iv[8]={0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef}; -+static unsigned char cfb_buf1[40],cfb_buf2[40],cfb_tmp[8]; -+static unsigned char plain[24]= -+ { -+ 0x4e,0x6f,0x77,0x20,0x69,0x73, -+ 0x20,0x74,0x68,0x65,0x20,0x74, -+ 0x69,0x6d,0x65,0x20,0x66,0x6f, -+ 0x72,0x20,0x61,0x6c,0x6c,0x20 -+ }; -+static unsigned char cfb_cipher8[24]= { -+ 0xf3,0x1f,0xda,0x07,0x01,0x14, 0x62,0xee,0x18,0x7f,0x43,0xd8, -+ 0x0a,0x7c,0xd9,0xb5,0xb0,0xd2, 0x90,0xda,0x6e,0x5b,0x9a,0x87 }; -+static unsigned char cfb_cipher16[24]={ -+ 0xF3,0x09,0x87,0x87,0x7F,0x57, 0xF7,0x3C,0x36,0xB6,0xDB,0x70, -+ 0xD8,0xD5,0x34,0x19,0xD3,0x86, 0xB2,0x23,0xB7,0xB2,0xAD,0x1B }; -+static unsigned char cfb_cipher32[24]={ -+ 0xF3,0x09,0x62,0x49,0xA4,0xDF, 0xA4,0x9F,0x33,0xDC,0x7B,0xAD, -+ 0x4C,0xC8,0x9F,0x64,0xE4,0x53, 0xE5,0xEC,0x67,0x20,0xDA,0xB6 }; -+static unsigned char cfb_cipher48[24]={ -+ 0xF3,0x09,0x62,0x49,0xC7,0xF4, 0x30,0xB5,0x15,0xEC,0xBB,0x85, -+ 0x97,0x5A,0x13,0x8C,0x68,0x60, 0xE2,0x38,0x34,0x3C,0xDC,0x1F }; -+static unsigned char cfb_cipher64[24]={ -+ 0xF3,0x09,0x62,0x49,0xC7,0xF4, 0x6E,0x51,0xA6,0x9E,0x83,0x9B, -+ 0x1A,0x92,0xF7,0x84,0x03,0x46, 0x71,0x33,0x89,0x8E,0xA6,0x22 }; -+ -+static unsigned char ofb_key[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; -+static unsigned char ofb_iv[8]={0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef}; -+static unsigned char ofb_buf1[24],ofb_buf2[24],ofb_tmp[8]; -+static unsigned char ofb_cipher[24]= -+ { -+ 0xf3,0x09,0x62,0x49,0xc7,0xf4,0x6e,0x51, -+ 0x35,0xf2,0x4a,0x24,0x2e,0xeb,0x3d,0x3f, -+ 0x3d,0x6d,0x5b,0xe3,0x25,0x5a,0xf8,0xc3 -+ }; -+ -+DES_LONG cbc_cksum_ret=0xB462FEF7L; -+unsigned char cbc_cksum_data[8]={0x1D,0x26,0x93,0x97,0xf7,0xfe,0x62,0xb4}; -+ -+#ifndef NOPROTO -+static char *pt(unsigned char *p); -+static int cfb_test(int bits, unsigned char *cfb_cipher); -+static int cfb64_test(unsigned char *cfb_cipher); -+static int ede_cfb64_test(unsigned char *cfb_cipher); -+#else -+static char *pt(); -+static int cfb_test(); -+static int cfb64_test(); -+static int ede_cfb64_test(); -+#endif -+ -+int main(argc,argv) -+int argc; -+char *argv[]; -+ { -+ int i,j,err=0; -+ des_cblock in,out,outin,iv3; -+ des_key_schedule ks,ks2,ks3; -+ unsigned char cbc_in[40]; -+ unsigned char cbc_out[40]; -+ DES_LONG cs; -+ unsigned char qret[4][4],cret[8]; -+ DES_LONG lqret[4]; -+ int num; -+ char *str; -+ -+ printf("Doing ecb\n"); -+ for (i=0; i>4)&0xf]; -+ ret[i*2+1]=f[p[i]&0xf]; -+ } -+ ret[16]='\0'; -+ return(ret); -+ } -+ -+#ifndef LIBDES_LIT -+ -+static int cfb_test(bits, cfb_cipher) -+int bits; -+unsigned char *cfb_cipher; -+ { -+ des_key_schedule ks; -+ int i,err=0; -+ -+ des_key_sched((C_Block *)cfb_key,ks); -+ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); -+ des_cfb_encrypt(plain,cfb_buf1,bits,(long)sizeof(plain),ks, -+ (C_Block *)cfb_tmp,DES_ENCRYPT); -+ if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0) -+ { -+ err=1; -+ printf("cfb_encrypt encrypt error\n"); -+ for (i=0; i<24; i+=8) -+ printf("%s\n",pt(&(cfb_buf1[i]))); -+ } -+ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); -+ des_cfb_encrypt(cfb_buf1,cfb_buf2,bits,(long)sizeof(plain),ks, -+ (C_Block *)cfb_tmp,DES_DECRYPT); -+ if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) -+ { -+ err=1; -+ printf("cfb_encrypt decrypt error\n"); -+ for (i=0; i<24; i+=8) -+ printf("%s\n",pt(&(cfb_buf1[i]))); -+ } -+ return(err); -+ } -+ -+static int cfb64_test(cfb_cipher) -+unsigned char *cfb_cipher; -+ { -+ des_key_schedule ks; -+ int err=0,i,n; -+ -+ des_key_sched((C_Block *)cfb_key,ks); -+ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); -+ n=0; -+ des_cfb64_encrypt(plain,cfb_buf1,(long)12,ks, -+ (C_Block *)cfb_tmp,&n,DES_ENCRYPT); -+ des_cfb64_encrypt(&(plain[12]),&(cfb_buf1[12]), -+ (long)sizeof(plain)-12,ks, -+ (C_Block *)cfb_tmp,&n,DES_ENCRYPT); -+ if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0) -+ { -+ err=1; -+ printf("cfb_encrypt encrypt error\n"); -+ for (i=0; i<24; i+=8) -+ printf("%s\n",pt(&(cfb_buf1[i]))); -+ } -+ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); -+ n=0; -+ des_cfb64_encrypt(cfb_buf1,cfb_buf2,(long)17,ks, -+ (C_Block *)cfb_tmp,&n,DES_DECRYPT); -+ des_cfb64_encrypt(&(cfb_buf1[17]),&(cfb_buf2[17]), -+ (long)sizeof(plain)-17,ks, -+ (C_Block *)cfb_tmp,&n,DES_DECRYPT); -+ if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) -+ { -+ err=1; -+ printf("cfb_encrypt decrypt error\n"); -+ for (i=0; i<24; i+=8) -+ printf("%s\n",pt(&(cfb_buf2[i]))); -+ } -+ return(err); -+ } -+ -+static int ede_cfb64_test(cfb_cipher) -+unsigned char *cfb_cipher; -+ { -+ des_key_schedule ks; -+ int err=0,i,n; -+ -+ des_key_sched((C_Block *)cfb_key,ks); -+ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); -+ n=0; -+ des_ede3_cfb64_encrypt(plain,cfb_buf1,(long)12,ks,ks,ks, -+ (C_Block *)cfb_tmp,&n,DES_ENCRYPT); -+ des_ede3_cfb64_encrypt(&(plain[12]),&(cfb_buf1[12]), -+ (long)sizeof(plain)-12,ks,ks,ks, -+ (C_Block *)cfb_tmp,&n,DES_ENCRYPT); -+ if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0) -+ { -+ err=1; -+ printf("ede_cfb_encrypt encrypt error\n"); -+ for (i=0; i<24; i+=8) -+ printf("%s\n",pt(&(cfb_buf1[i]))); -+ } -+ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); -+ n=0; -+ des_ede3_cfb64_encrypt(cfb_buf1,cfb_buf2,(long)17,ks,ks,ks, -+ (C_Block *)cfb_tmp,&n,DES_DECRYPT); -+ des_ede3_cfb64_encrypt(&(cfb_buf1[17]),&(cfb_buf2[17]), -+ (long)sizeof(plain)-17,ks,ks,ks, -+ (C_Block *)cfb_tmp,&n,DES_DECRYPT); -+ if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) -+ { -+ err=1; -+ printf("ede_cfb_encrypt decrypt error\n"); -+ for (i=0; i<24; i+=8) -+ printf("%s\n",pt(&(cfb_buf2[i]))); -+ } -+ return(err); -+ } -+ -+#endif -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/dx86unix.S Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,3160 @@ -+/* -+ * This file was originally generated by Michael Richardson -+ * via the perl scripts found in the ASM subdir. It remains copyright of -+ * Eric Young, see the file COPYRIGHT. -+ * -+ * This was last done on October 9, 2002. -+ * -+ * While this file does not need to go through cpp, we pass it through -+ * CPP by naming it dx86unix.S instead of dx86unix.s because there is -+ * a bug in Rules.make for .s builds - specifically it references EXTRA_CFLAGS -+ * which may contain stuff that AS doesn't understand instead of -+ * referencing EXTRA_AFLAGS. -+ */ -+ -+ .file "dx86unix.S" -+ .version "01.01" -+.text -+ .align 16 -+.globl des_encrypt -+ .type des_encrypt , @function -+des_encrypt: -+ pushl %esi -+ pushl %edi -+ -+ -+ movl 12(%esp), %esi -+ xorl %ecx, %ecx -+ pushl %ebx -+ pushl %ebp -+ movl (%esi), %eax -+ movl 28(%esp), %ebx -+ movl 4(%esi), %edi -+ -+ -+ roll $4, %eax -+ movl %eax, %esi -+ xorl %edi, %eax -+ andl $0xf0f0f0f0, %eax -+ xorl %eax, %esi -+ xorl %eax, %edi -+ -+ roll $20, %edi -+ movl %edi, %eax -+ xorl %esi, %edi -+ andl $0xfff0000f, %edi -+ xorl %edi, %eax -+ xorl %edi, %esi -+ -+ roll $14, %eax -+ movl %eax, %edi -+ xorl %esi, %eax -+ andl $0x33333333, %eax -+ xorl %eax, %edi -+ xorl %eax, %esi -+ -+ roll $22, %esi -+ movl %esi, %eax -+ xorl %edi, %esi -+ andl $0x03fc03fc, %esi -+ xorl %esi, %eax -+ xorl %esi, %edi -+ -+ roll $9, %eax -+ movl %eax, %esi -+ xorl %edi, %eax -+ andl $0xaaaaaaaa, %eax -+ xorl %eax, %esi -+ xorl %eax, %edi -+ -+.byte 209 -+.byte 199 -+ movl 24(%esp), %ebp -+ cmpl $0, %ebx -+ je .L000start_decrypt -+ -+ -+ movl (%ebp), %eax -+ xorl %ebx, %ebx -+ movl 4(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 8(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 12(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 16(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 20(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 24(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 28(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 32(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 36(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 40(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 44(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 48(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 52(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 56(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 60(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 64(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 68(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 72(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 76(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 80(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 84(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 88(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 92(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 96(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 100(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 104(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 108(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 112(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 116(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 120(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 124(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ jmp .L001end -+.L000start_decrypt: -+ -+ -+ movl 120(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 124(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 112(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 116(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 104(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 108(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 96(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 100(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 88(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 92(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 80(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 84(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 72(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 76(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 64(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 68(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 56(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 60(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 48(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 52(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 40(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 44(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 32(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 36(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 24(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 28(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 16(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 20(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 8(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 12(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl (%ebp), %eax -+ xorl %ebx, %ebx -+ movl 4(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+.L001end: -+ -+ -+ movl 20(%esp), %edx -+.byte 209 -+.byte 206 -+ movl %edi, %eax -+ xorl %esi, %edi -+ andl $0xaaaaaaaa, %edi -+ xorl %edi, %eax -+ xorl %edi, %esi -+ -+ roll $23, %eax -+ movl %eax, %edi -+ xorl %esi, %eax -+ andl $0x03fc03fc, %eax -+ xorl %eax, %edi -+ xorl %eax, %esi -+ -+ roll $10, %edi -+ movl %edi, %eax -+ xorl %esi, %edi -+ andl $0x33333333, %edi -+ xorl %edi, %eax -+ xorl %edi, %esi -+ -+ roll $18, %esi -+ movl %esi, %edi -+ xorl %eax, %esi -+ andl $0xfff0000f, %esi -+ xorl %esi, %edi -+ xorl %esi, %eax -+ -+ roll $12, %edi -+ movl %edi, %esi -+ xorl %eax, %edi -+ andl $0xf0f0f0f0, %edi -+ xorl %edi, %esi -+ xorl %edi, %eax -+ -+ rorl $4, %eax -+ movl %eax, (%edx) -+ movl %esi, 4(%edx) -+ popl %ebp -+ popl %ebx -+ popl %edi -+ popl %esi -+ ret -+.des_encrypt_end: -+ .size des_encrypt , .des_encrypt_end-des_encrypt -+.ident "desasm.pl" -+.text -+ .align 16 -+.globl des_encrypt2 -+ .type des_encrypt2 , @function -+des_encrypt2: -+ pushl %esi -+ pushl %edi -+ -+ -+ movl 12(%esp), %eax -+ xorl %ecx, %ecx -+ pushl %ebx -+ pushl %ebp -+ movl (%eax), %esi -+ movl 28(%esp), %ebx -+ roll $3, %esi -+ movl 4(%eax), %edi -+ roll $3, %edi -+ movl 24(%esp), %ebp -+ cmpl $0, %ebx -+ je .L002start_decrypt -+ -+ -+ movl (%ebp), %eax -+ xorl %ebx, %ebx -+ movl 4(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 8(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 12(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 16(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 20(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 24(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 28(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 32(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 36(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 40(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 44(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 48(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 52(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 56(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 60(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 64(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 68(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 72(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 76(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 80(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 84(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 88(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 92(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 96(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 100(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 104(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 108(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 112(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 116(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 120(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 124(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ jmp .L003end -+.L002start_decrypt: -+ -+ -+ movl 120(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 124(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 112(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 116(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 104(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 108(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 96(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 100(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 88(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 92(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 80(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 84(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 72(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 76(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 64(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 68(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 56(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 60(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 48(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 52(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 40(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 44(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 32(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 36(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 24(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 28(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 16(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 20(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 8(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 12(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl (%ebp), %eax -+ xorl %ebx, %ebx -+ movl 4(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+.L003end: -+ -+ -+ rorl $3, %edi -+ movl 20(%esp), %eax -+ rorl $3, %esi -+ movl %edi, (%eax) -+ movl %esi, 4(%eax) -+ popl %ebp -+ popl %ebx -+ popl %edi -+ popl %esi -+ ret -+.des_encrypt2_end: -+ .size des_encrypt2 , .des_encrypt2_end-des_encrypt2 -+.ident "desasm.pl" -+.text -+ .align 16 -+.globl des_encrypt3 -+ .type des_encrypt3 , @function -+des_encrypt3: -+ pushl %ebx -+ movl 8(%esp), %ebx -+ pushl %ebp -+ pushl %esi -+ pushl %edi -+ -+ -+ movl (%ebx), %edi -+ movl 4(%ebx), %esi -+ subl $12, %esp -+ -+ -+ roll $4, %edi -+ movl %edi, %edx -+ xorl %esi, %edi -+ andl $0xf0f0f0f0, %edi -+ xorl %edi, %edx -+ xorl %edi, %esi -+ -+ roll $20, %esi -+ movl %esi, %edi -+ xorl %edx, %esi -+ andl $0xfff0000f, %esi -+ xorl %esi, %edi -+ xorl %esi, %edx -+ -+ roll $14, %edi -+ movl %edi, %esi -+ xorl %edx, %edi -+ andl $0x33333333, %edi -+ xorl %edi, %esi -+ xorl %edi, %edx -+ -+ roll $22, %edx -+ movl %edx, %edi -+ xorl %esi, %edx -+ andl $0x03fc03fc, %edx -+ xorl %edx, %edi -+ xorl %edx, %esi -+ -+ roll $9, %edi -+ movl %edi, %edx -+ xorl %esi, %edi -+ andl $0xaaaaaaaa, %edi -+ xorl %edi, %edx -+ xorl %edi, %esi -+ -+ rorl $3, %edx -+ rorl $2, %esi -+ movl %esi, 4(%ebx) -+ movl 36(%esp), %eax -+ movl %edx, (%ebx) -+ movl 40(%esp), %edi -+ movl 44(%esp), %esi -+ movl $1, 8(%esp) -+ movl %eax, 4(%esp) -+ movl %ebx, (%esp) -+ call des_encrypt2 -+ movl $0, 8(%esp) -+ movl %edi, 4(%esp) -+ movl %ebx, (%esp) -+ call des_encrypt2 -+ movl $1, 8(%esp) -+ movl %esi, 4(%esp) -+ movl %ebx, (%esp) -+ call des_encrypt2 -+ addl $12, %esp -+ movl (%ebx), %edi -+ movl 4(%ebx), %esi -+ -+ -+ roll $2, %esi -+ roll $3, %edi -+ movl %edi, %eax -+ xorl %esi, %edi -+ andl $0xaaaaaaaa, %edi -+ xorl %edi, %eax -+ xorl %edi, %esi -+ -+ roll $23, %eax -+ movl %eax, %edi -+ xorl %esi, %eax -+ andl $0x03fc03fc, %eax -+ xorl %eax, %edi -+ xorl %eax, %esi -+ -+ roll $10, %edi -+ movl %edi, %eax -+ xorl %esi, %edi -+ andl $0x33333333, %edi -+ xorl %edi, %eax -+ xorl %edi, %esi -+ -+ roll $18, %esi -+ movl %esi, %edi -+ xorl %eax, %esi -+ andl $0xfff0000f, %esi -+ xorl %esi, %edi -+ xorl %esi, %eax -+ -+ roll $12, %edi -+ movl %edi, %esi -+ xorl %eax, %edi -+ andl $0xf0f0f0f0, %edi -+ xorl %edi, %esi -+ xorl %edi, %eax -+ -+ rorl $4, %eax -+ movl %eax, (%ebx) -+ movl %esi, 4(%ebx) -+ popl %edi -+ popl %esi -+ popl %ebp -+ popl %ebx -+ ret -+.des_encrypt3_end: -+ .size des_encrypt3 , .des_encrypt3_end-des_encrypt3 -+.ident "desasm.pl" -+.text -+ .align 16 -+.globl des_decrypt3 -+ .type des_decrypt3 , @function -+des_decrypt3: -+ pushl %ebx -+ movl 8(%esp), %ebx -+ pushl %ebp -+ pushl %esi -+ pushl %edi -+ -+ -+ movl (%ebx), %edi -+ movl 4(%ebx), %esi -+ subl $12, %esp -+ -+ -+ roll $4, %edi -+ movl %edi, %edx -+ xorl %esi, %edi -+ andl $0xf0f0f0f0, %edi -+ xorl %edi, %edx -+ xorl %edi, %esi -+ -+ roll $20, %esi -+ movl %esi, %edi -+ xorl %edx, %esi -+ andl $0xfff0000f, %esi -+ xorl %esi, %edi -+ xorl %esi, %edx -+ -+ roll $14, %edi -+ movl %edi, %esi -+ xorl %edx, %edi -+ andl $0x33333333, %edi -+ xorl %edi, %esi -+ xorl %edi, %edx -+ -+ roll $22, %edx -+ movl %edx, %edi -+ xorl %esi, %edx -+ andl $0x03fc03fc, %edx -+ xorl %edx, %edi -+ xorl %edx, %esi -+ -+ roll $9, %edi -+ movl %edi, %edx -+ xorl %esi, %edi -+ andl $0xaaaaaaaa, %edi -+ xorl %edi, %edx -+ xorl %edi, %esi -+ -+ rorl $3, %edx -+ rorl $2, %esi -+ movl %esi, 4(%ebx) -+ movl 36(%esp), %esi -+ movl %edx, (%ebx) -+ movl 40(%esp), %edi -+ movl 44(%esp), %eax -+ movl $0, 8(%esp) -+ movl %eax, 4(%esp) -+ movl %ebx, (%esp) -+ call des_encrypt2 -+ movl $1, 8(%esp) -+ movl %edi, 4(%esp) -+ movl %ebx, (%esp) -+ call des_encrypt2 -+ movl $0, 8(%esp) -+ movl %esi, 4(%esp) -+ movl %ebx, (%esp) -+ call des_encrypt2 -+ addl $12, %esp -+ movl (%ebx), %edi -+ movl 4(%ebx), %esi -+ -+ -+ roll $2, %esi -+ roll $3, %edi -+ movl %edi, %eax -+ xorl %esi, %edi -+ andl $0xaaaaaaaa, %edi -+ xorl %edi, %eax -+ xorl %edi, %esi -+ -+ roll $23, %eax -+ movl %eax, %edi -+ xorl %esi, %eax -+ andl $0x03fc03fc, %eax -+ xorl %eax, %edi -+ xorl %eax, %esi -+ -+ roll $10, %edi -+ movl %edi, %eax -+ xorl %esi, %edi -+ andl $0x33333333, %edi -+ xorl %edi, %eax -+ xorl %edi, %esi -+ -+ roll $18, %esi -+ movl %esi, %edi -+ xorl %eax, %esi -+ andl $0xfff0000f, %esi -+ xorl %esi, %edi -+ xorl %esi, %eax -+ -+ roll $12, %edi -+ movl %edi, %esi -+ xorl %eax, %edi -+ andl $0xf0f0f0f0, %edi -+ xorl %edi, %esi -+ xorl %edi, %eax -+ -+ rorl $4, %eax -+ movl %eax, (%ebx) -+ movl %esi, 4(%ebx) -+ popl %edi -+ popl %esi -+ popl %ebp -+ popl %ebx -+ ret -+.des_decrypt3_end: -+ .size des_decrypt3 , .des_decrypt3_end-des_decrypt3 -+.ident "desasm.pl" -+.text -+ .align 16 -+.globl des_ncbc_encrypt -+ .type des_ncbc_encrypt , @function -+des_ncbc_encrypt: -+ -+ pushl %ebp -+ pushl %ebx -+ pushl %esi -+ pushl %edi -+ movl 28(%esp), %ebp -+ -+ movl 36(%esp), %ebx -+ movl (%ebx), %esi -+ movl 4(%ebx), %edi -+ pushl %edi -+ pushl %esi -+ pushl %edi -+ pushl %esi -+ movl %esp, %ebx -+ movl 36(%esp), %esi -+ movl 40(%esp), %edi -+ -+ movl 56(%esp), %ecx -+ -+ pushl %ecx -+ -+ movl 52(%esp), %eax -+ pushl %eax -+ pushl %ebx -+ cmpl $0, %ecx -+ jz .L004decrypt -+ andl $4294967288, %ebp -+ movl 12(%esp), %eax -+ movl 16(%esp), %ebx -+ jz .L005encrypt_finish -+.L006encrypt_loop: -+ movl (%esi), %ecx -+ movl 4(%esi), %edx -+ xorl %ecx, %eax -+ xorl %edx, %ebx -+ movl %eax, 12(%esp) -+ movl %ebx, 16(%esp) -+ call des_encrypt -+ movl 12(%esp), %eax -+ movl 16(%esp), %ebx -+ movl %eax, (%edi) -+ movl %ebx, 4(%edi) -+ addl $8, %esi -+ addl $8, %edi -+ subl $8, %ebp -+ jnz .L006encrypt_loop -+.L005encrypt_finish: -+ movl 56(%esp), %ebp -+ andl $7, %ebp -+ jz .L007finish -+ xorl %ecx, %ecx -+ xorl %edx, %edx -+ movl .L008cbc_enc_jmp_table(,%ebp,4),%ebp -+ jmp *%ebp -+.L009ej7: -+ movb 6(%esi), %dh -+ sall $8, %edx -+.L010ej6: -+ movb 5(%esi), %dh -+.L011ej5: -+ movb 4(%esi), %dl -+.L012ej4: -+ movl (%esi), %ecx -+ jmp .L013ejend -+.L014ej3: -+ movb 2(%esi), %ch -+ sall $8, %ecx -+.L015ej2: -+ movb 1(%esi), %ch -+.L016ej1: -+ movb (%esi), %cl -+.L013ejend: -+ xorl %ecx, %eax -+ xorl %edx, %ebx -+ movl %eax, 12(%esp) -+ movl %ebx, 16(%esp) -+ call des_encrypt -+ movl 12(%esp), %eax -+ movl 16(%esp), %ebx -+ movl %eax, (%edi) -+ movl %ebx, 4(%edi) -+ jmp .L007finish -+.align 16 -+.L004decrypt: -+ andl $4294967288, %ebp -+ movl 20(%esp), %eax -+ movl 24(%esp), %ebx -+ jz .L017decrypt_finish -+.L018decrypt_loop: -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+ movl %eax, 12(%esp) -+ movl %ebx, 16(%esp) -+ call des_encrypt -+ movl 12(%esp), %eax -+ movl 16(%esp), %ebx -+ movl 20(%esp), %ecx -+ movl 24(%esp), %edx -+ xorl %eax, %ecx -+ xorl %ebx, %edx -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+ movl %ecx, (%edi) -+ movl %edx, 4(%edi) -+ movl %eax, 20(%esp) -+ movl %ebx, 24(%esp) -+ addl $8, %esi -+ addl $8, %edi -+ subl $8, %ebp -+ jnz .L018decrypt_loop -+.L017decrypt_finish: -+ movl 56(%esp), %ebp -+ andl $7, %ebp -+ jz .L007finish -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+ movl %eax, 12(%esp) -+ movl %ebx, 16(%esp) -+ call des_encrypt -+ movl 12(%esp), %eax -+ movl 16(%esp), %ebx -+ movl 20(%esp), %ecx -+ movl 24(%esp), %edx -+ xorl %eax, %ecx -+ xorl %ebx, %edx -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+.L019dj7: -+ rorl $16, %edx -+ movb %dl, 6(%edi) -+ shrl $16, %edx -+.L020dj6: -+ movb %dh, 5(%edi) -+.L021dj5: -+ movb %dl, 4(%edi) -+.L022dj4: -+ movl %ecx, (%edi) -+ jmp .L023djend -+.L024dj3: -+ rorl $16, %ecx -+ movb %cl, 2(%edi) -+ sall $16, %ecx -+.L025dj2: -+ movb %ch, 1(%esi) -+.L026dj1: -+ movb %cl, (%esi) -+.L023djend: -+ jmp .L007finish -+.align 16 -+.L007finish: -+ movl 64(%esp), %ecx -+ addl $28, %esp -+ movl %eax, (%ecx) -+ movl %ebx, 4(%ecx) -+ popl %edi -+ popl %esi -+ popl %ebx -+ popl %ebp -+ ret -+.align 16 -+.L008cbc_enc_jmp_table: -+ .long 0 -+ .long .L016ej1 -+ .long .L015ej2 -+ .long .L014ej3 -+ .long .L012ej4 -+ .long .L011ej5 -+ .long .L010ej6 -+ .long .L009ej7 -+.align 16 -+.L027cbc_dec_jmp_table: -+ .long 0 -+ .long .L026dj1 -+ .long .L025dj2 -+ .long .L024dj3 -+ .long .L022dj4 -+ .long .L021dj5 -+ .long .L020dj6 -+ .long .L019dj7 -+.des_ncbc_encrypt_end: -+ .size des_ncbc_encrypt , .des_ncbc_encrypt_end-des_ncbc_encrypt -+.ident "desasm.pl" -+.text -+ .align 16 -+.globl des_ede3_cbc_encrypt -+ .type des_ede3_cbc_encrypt , @function -+des_ede3_cbc_encrypt: -+ -+ pushl %ebp -+ pushl %ebx -+ pushl %esi -+ pushl %edi -+ movl 28(%esp), %ebp -+ -+ movl 44(%esp), %ebx -+ movl (%ebx), %esi -+ movl 4(%ebx), %edi -+ pushl %edi -+ pushl %esi -+ pushl %edi -+ pushl %esi -+ movl %esp, %ebx -+ movl 36(%esp), %esi -+ movl 40(%esp), %edi -+ -+ movl 64(%esp), %ecx -+ -+ movl 56(%esp), %eax -+ pushl %eax -+ -+ movl 56(%esp), %eax -+ pushl %eax -+ -+ movl 56(%esp), %eax -+ pushl %eax -+ pushl %ebx -+ cmpl $0, %ecx -+ jz .L028decrypt -+ andl $4294967288, %ebp -+ movl 16(%esp), %eax -+ movl 20(%esp), %ebx -+ jz .L029encrypt_finish -+.L030encrypt_loop: -+ movl (%esi), %ecx -+ movl 4(%esi), %edx -+ xorl %ecx, %eax -+ xorl %edx, %ebx -+ movl %eax, 16(%esp) -+ movl %ebx, 20(%esp) -+ call des_encrypt3 -+ movl 16(%esp), %eax -+ movl 20(%esp), %ebx -+ movl %eax, (%edi) -+ movl %ebx, 4(%edi) -+ addl $8, %esi -+ addl $8, %edi -+ subl $8, %ebp -+ jnz .L030encrypt_loop -+.L029encrypt_finish: -+ movl 60(%esp), %ebp -+ andl $7, %ebp -+ jz .L031finish -+ xorl %ecx, %ecx -+ xorl %edx, %edx -+ movl .L032cbc_enc_jmp_table(,%ebp,4),%ebp -+ jmp *%ebp -+.L033ej7: -+ movb 6(%esi), %dh -+ sall $8, %edx -+.L034ej6: -+ movb 5(%esi), %dh -+.L035ej5: -+ movb 4(%esi), %dl -+.L036ej4: -+ movl (%esi), %ecx -+ jmp .L037ejend -+.L038ej3: -+ movb 2(%esi), %ch -+ sall $8, %ecx -+.L039ej2: -+ movb 1(%esi), %ch -+.L040ej1: -+ movb (%esi), %cl -+.L037ejend: -+ xorl %ecx, %eax -+ xorl %edx, %ebx -+ movl %eax, 16(%esp) -+ movl %ebx, 20(%esp) -+ call des_encrypt3 -+ movl 16(%esp), %eax -+ movl 20(%esp), %ebx -+ movl %eax, (%edi) -+ movl %ebx, 4(%edi) -+ jmp .L031finish -+.align 16 -+.L028decrypt: -+ andl $4294967288, %ebp -+ movl 24(%esp), %eax -+ movl 28(%esp), %ebx -+ jz .L041decrypt_finish -+.L042decrypt_loop: -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+ movl %eax, 16(%esp) -+ movl %ebx, 20(%esp) -+ call des_decrypt3 -+ movl 16(%esp), %eax -+ movl 20(%esp), %ebx -+ movl 24(%esp), %ecx -+ movl 28(%esp), %edx -+ xorl %eax, %ecx -+ xorl %ebx, %edx -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+ movl %ecx, (%edi) -+ movl %edx, 4(%edi) -+ movl %eax, 24(%esp) -+ movl %ebx, 28(%esp) -+ addl $8, %esi -+ addl $8, %edi -+ subl $8, %ebp -+ jnz .L042decrypt_loop -+.L041decrypt_finish: -+ movl 60(%esp), %ebp -+ andl $7, %ebp -+ jz .L031finish -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+ movl %eax, 16(%esp) -+ movl %ebx, 20(%esp) -+ call des_decrypt3 -+ movl 16(%esp), %eax -+ movl 20(%esp), %ebx -+ movl 24(%esp), %ecx -+ movl 28(%esp), %edx -+ xorl %eax, %ecx -+ xorl %ebx, %edx -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+.L043dj7: -+ rorl $16, %edx -+ movb %dl, 6(%edi) -+ shrl $16, %edx -+.L044dj6: -+ movb %dh, 5(%edi) -+.L045dj5: -+ movb %dl, 4(%edi) -+.L046dj4: -+ movl %ecx, (%edi) -+ jmp .L047djend -+.L048dj3: -+ rorl $16, %ecx -+ movb %cl, 2(%edi) -+ sall $16, %ecx -+.L049dj2: -+ movb %ch, 1(%esi) -+.L050dj1: -+ movb %cl, (%esi) -+.L047djend: -+ jmp .L031finish -+.align 16 -+.L031finish: -+ movl 76(%esp), %ecx -+ addl $32, %esp -+ movl %eax, (%ecx) -+ movl %ebx, 4(%ecx) -+ popl %edi -+ popl %esi -+ popl %ebx -+ popl %ebp -+ ret -+.align 16 -+.L032cbc_enc_jmp_table: -+ .long 0 -+ .long .L040ej1 -+ .long .L039ej2 -+ .long .L038ej3 -+ .long .L036ej4 -+ .long .L035ej5 -+ .long .L034ej6 -+ .long .L033ej7 -+.align 16 -+.L051cbc_dec_jmp_table: -+ .long 0 -+ .long .L050dj1 -+ .long .L049dj2 -+ .long .L048dj3 -+ .long .L046dj4 -+ .long .L045dj5 -+ .long .L044dj6 -+ .long .L043dj7 -+.des_ede3_cbc_encrypt_end: -+ .size des_ede3_cbc_encrypt , .des_ede3_cbc_encrypt_end-des_ede3_cbc_encrypt -+.ident "desasm.pl" ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/ecb_enc.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,128 @@ -+/* crypto/des/ecb_enc.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+#include "des_locl.h" -+#include "spr.h" -+ -+char *libdes_version="libdes v 3.24 - 20-Apr-1996 - eay"; -+char *DES_version="DES part of SSLeay 0.8.2b 08-Jan-1998"; -+ -+/* RCSID $Id$ */ -+/* This function ifdef'ed out for FreeS/WAN project. */ -+#ifdef notdef -+char *des_options() -+ { -+ static int init=1; -+ static char buf[32]; -+ -+ if (init) -+ { -+ char *ptr,*unroll,*risc,*size; -+ -+ init=0; -+#ifdef DES_PTR -+ ptr="ptr"; -+#else -+ ptr="idx"; -+#endif -+#if defined(DES_RISC1) || defined(DES_RISC2) -+#ifdef DES_RISC1 -+ risc="risc1"; -+#endif -+#ifdef DES_RISC2 -+ risc="risc2"; -+#endif -+#else -+ risc="cisc"; -+#endif -+#ifdef DES_UNROLL -+ unroll="16"; -+#else -+ unroll="4"; -+#endif -+ if (sizeof(DES_LONG) != sizeof(long)) -+ size="int"; -+ else -+ size="long"; -+ sprintf(buf,"des(%s,%s,%s,%s)",ptr,risc,unroll,size); -+ } -+ return(buf); -+ } -+#endif -+ -+ -+void des_ecb_encrypt(input, output, ks, enc) -+des_cblock (*input); -+des_cblock (*output); -+des_key_schedule ks; -+int enc; -+ { -+ register DES_LONG l; -+ register unsigned char *in,*out; -+ DES_LONG ll[2]; -+ -+ in=(unsigned char *)input; -+ out=(unsigned char *)output; -+ c2l(in,l); ll[0]=l; -+ c2l(in,l); ll[1]=l; -+ des_encrypt(ll,ks,enc); -+ l=ll[0]; l2c(l,out); -+ l=ll[1]; l2c(l,out); -+ l=ll[0]=ll[1]=0; -+ } -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/fcrypt.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,152 @@ -+/* NOCW */ -+ -+/* This version of crypt has been developed from my MIT compatable -+ * DES library. -+ * The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au -+ * Eric Young (eay@cryptsoft.com) -+ */ -+ -+/* Modification by Jens Kupferschmidt (Cu) -+ * I have included directive PARA for shared memory computers. -+ * I have included a directive LONGCRYPT to using this routine to cipher -+ * passwords with more then 8 bytes like HP-UX 10.x it used. The MAXPLEN -+ * definition is the maximum of lenght of password and can changed. I have -+ * defined 24. -+ */ -+ -+#include "des_locl.h" -+ -+/* Added more values to handle illegal salt values the way normal -+ * crypt() implementations do. The patch was sent by -+ * Bjorn Gronvall -+ */ -+static unsigned const char con_salt[128]={ -+0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9, -+0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1, -+0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9, -+0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1, -+0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9, -+0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,0x00,0x01, -+0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, -+0x0A,0x0B,0x05,0x06,0x07,0x08,0x09,0x0A, -+0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12, -+0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A, -+0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22, -+0x23,0x24,0x25,0x20,0x21,0x22,0x23,0x24, -+0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C, -+0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34, -+0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C, -+0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44, -+}; -+ -+static unsigned const char cov_2char[64]={ -+0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35, -+0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44, -+0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C, -+0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54, -+0x55,0x56,0x57,0x58,0x59,0x5A,0x61,0x62, -+0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A, -+0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72, -+0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A -+}; -+ -+#ifndef NOPROTO -+void fcrypt_body(DES_LONG *out,des_key_schedule ks, -+ DES_LONG Eswap0, DES_LONG Eswap1); -+ -+#ifdef PERL5 -+char *des_crypt(const char *buf,const char *salt); -+#else -+char *crypt(const char *buf,const char *salt); -+#endif -+#else -+void fcrypt_body(); -+#ifdef PERL5 -+char *des_crypt(); -+#else -+char *crypt(); -+#endif -+#endif -+ -+#ifdef PERL5 -+char *des_crypt(buf,salt) -+#else -+char *crypt(buf,salt) -+#endif -+const char *buf; -+const char *salt; -+ { -+ static char buff[14]; -+ -+ return(des_fcrypt(buf,salt,buff)); -+ } -+ -+ -+char *des_fcrypt(buf,salt,ret) -+const char *buf; -+const char *salt; -+char *ret; -+ { -+ unsigned int i,j,x,y; -+ DES_LONG Eswap0,Eswap1; -+ DES_LONG out[2],ll; -+ des_cblock key; -+ des_key_schedule ks; -+ unsigned char bb[9]; -+ unsigned char *b=bb; -+ unsigned char c,u; -+ -+ /* eay 25/08/92 -+ * If you call crypt("pwd","*") as often happens when you -+ * have * as the pwd field in /etc/passwd, the function -+ * returns *\0XXXXXXXXX -+ * The \0 makes the string look like * so the pwd "*" would -+ * crypt to "*". This was found when replacing the crypt in -+ * our shared libraries. People found that the disbled -+ * accounts effectivly had no passwd :-(. */ -+ x=ret[0]=((salt[0] == '\0')?'A':salt[0]); -+ Eswap0=con_salt[x]<<2; -+ x=ret[1]=((salt[1] == '\0')?'A':salt[1]); -+ Eswap1=con_salt[x]<<6; -+ -+/* EAY -+r=strlen(buf); -+r=(r+7)/8; -+*/ -+ for (i=0; i<8; i++) -+ { -+ c= *(buf++); -+ if (!c) break; -+ key[i]=(c<<1); -+ } -+ for (; i<8; i++) -+ key[i]=0; -+ -+ des_set_key((des_cblock *)(key),ks); -+ fcrypt_body(&(out[0]),ks,Eswap0,Eswap1); -+ -+ ll=out[0]; l2c(ll,b); -+ ll=out[1]; l2c(ll,b); -+ y=0; -+ u=0x80; -+ bb[8]=0; -+ for (i=2; i<13; i++) -+ { -+ c=0; -+ for (j=0; j<6; j++) -+ { -+ c<<=1; -+ if (bb[y] & u) c|=1; -+ u>>=1; -+ if (!u) -+ { -+ y++; -+ u=0x80; -+ } -+ } -+ ret[i]=cov_2char[c]; -+ } -+ ret[13]='\0'; -+ return(ret); -+ } -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/fcrypt_b.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,148 @@ -+/* crypto/des/fcrypt_b.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+/* #include */ -+ -+/* This version of crypt has been developed from my MIT compatable -+ * DES library. -+ * The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au -+ * Eric Young (eay@cryptsoft.com) -+ */ -+ -+#define DES_FCRYPT -+#include "des_locl.h" -+#undef DES_FCRYPT -+ -+#undef PERM_OP -+#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ -+ (b)^=(t),\ -+ (a)^=((t)<<(n))) -+ -+#undef HPERM_OP -+#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ -+ (a)=(a)^(t)^(t>>(16-(n))))\ -+ -+void fcrypt_body(out, ks, Eswap0, Eswap1) -+DES_LONG *out; -+des_key_schedule ks; -+DES_LONG Eswap0; -+DES_LONG Eswap1; -+ { -+ register DES_LONG l,r,t,u; -+#ifdef DES_PTR -+ register unsigned char *des_SP=(unsigned char *)des_SPtrans; -+#endif -+ register DES_LONG *s; -+ register int j; -+ register DES_LONG E0,E1; -+ -+ l=0; -+ r=0; -+ -+ s=(DES_LONG *)ks; -+ E0=Eswap0; -+ E1=Eswap1; -+ -+ for (j=0; j<25; j++) -+ { -+#ifdef DES_UNROLL -+ register int i; -+ -+ for (i=0; i<32; i+=8) -+ { -+ D_ENCRYPT(l,r,i+0); /* 1 */ -+ D_ENCRYPT(r,l,i+2); /* 2 */ -+ D_ENCRYPT(l,r,i+4); /* 1 */ -+ D_ENCRYPT(r,l,i+6); /* 2 */ -+ } -+#else -+ D_ENCRYPT(l,r, 0); /* 1 */ -+ D_ENCRYPT(r,l, 2); /* 2 */ -+ D_ENCRYPT(l,r, 4); /* 3 */ -+ D_ENCRYPT(r,l, 6); /* 4 */ -+ D_ENCRYPT(l,r, 8); /* 5 */ -+ D_ENCRYPT(r,l,10); /* 6 */ -+ D_ENCRYPT(l,r,12); /* 7 */ -+ D_ENCRYPT(r,l,14); /* 8 */ -+ D_ENCRYPT(l,r,16); /* 9 */ -+ D_ENCRYPT(r,l,18); /* 10 */ -+ D_ENCRYPT(l,r,20); /* 11 */ -+ D_ENCRYPT(r,l,22); /* 12 */ -+ D_ENCRYPT(l,r,24); /* 13 */ -+ D_ENCRYPT(r,l,26); /* 14 */ -+ D_ENCRYPT(l,r,28); /* 15 */ -+ D_ENCRYPT(r,l,30); /* 16 */ -+#endif -+ -+ t=l; -+ l=r; -+ r=t; -+ } -+ l=ROTATE(l,3)&0xffffffffL; -+ r=ROTATE(r,3)&0xffffffffL; -+ -+ PERM_OP(l,r,t, 1,0x55555555L); -+ PERM_OP(r,l,t, 8,0x00ff00ffL); -+ PERM_OP(l,r,t, 2,0x33333333L); -+ PERM_OP(r,l,t,16,0x0000ffffL); -+ PERM_OP(l,r,t, 4,0x0f0f0f0fL); -+ -+ out[0]=r; -+ out[1]=l; -+ } -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/options.txt Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,39 @@ -+Note that the UNROLL option makes the 'inner' des loop unroll all 16 rounds -+instead of the default 4. -+RISC1 and RISC2 are 2 alternatives for the inner loop and -+PTR means to use pointers arithmatic instead of arrays. -+ -+FreeBSD - Pentium Pro 200mhz - gcc 2.7.2.2 - assembler 577,000 4620k/s -+IRIX 6.2 - R10000 195mhz - cc (-O3 -n32) - UNROLL RISC2 PTR 496,000 3968k/s -+solaris 2.5.1 usparc 167mhz?? - SC4.0 - UNROLL RISC1 PTR [1] 459,400 3672k/s -+FreeBSD - Pentium Pro 200mhz - gcc 2.7.2.2 - UNROLL RISC1 433,000 3468k/s -+solaris 2.5.1 usparc 167mhz?? - gcc 2.7.2 - UNROLL 380,000 3041k/s -+linux - pentium 100mhz - gcc 2.7.0 - assembler 281,000 2250k/s -+NT 4.0 - pentium 100mhz - VC 4.2 - assembler 281,000 2250k/s -+AIX 4.1? - PPC604 100mhz - cc - UNROLL 275,000 2200k/s -+IRIX 5.3 - R4400 200mhz - gcc 2.6.3 - UNROLL RISC2 PTR 235,300 1882k/s -+IRIX 5.3 - R4400 200mhz - cc - UNROLL RISC2 PTR 233,700 1869k/s -+NT 4.0 - pentium 100mhz - VC 4.2 - UNROLL RISC1 PTR 191,000 1528k/s -+DEC Alpha 165mhz?? - cc - RISC2 PTR [2] 181,000 1448k/s -+linux - pentium 100mhz - gcc 2.7.0 - UNROLL RISC1 PTR 158,500 1268k/s -+HPUX 10 - 9000/887 - cc - UNROLL [3] 148,000 1190k/s -+solaris 2.5.1 - sparc 10 50mhz - gcc 2.7.2 - UNROLL 123,600 989k/s -+IRIX 5.3 - R4000 100mhz - cc - UNROLL RISC2 PTR 101,000 808k/s -+DGUX - 88100 50mhz(?) - gcc 2.6.3 - UNROLL 81,000 648k/s -+solaris 2.4 486 50mhz - gcc 2.6.3 - assembler 65,000 522k/s -+HPUX 10 - 9000/887 - k&r cc (default compiler) - UNROLL PTR 76,000 608k/s -+solaris 2.4 486 50mhz - gcc 2.6.3 - UNROLL RISC2 43,500 344k/s -+AIX - old slow one :-) - cc - 39,000 312k/s -+ -+Notes. -+[1] For the ultra sparc, SunC 4.0 -+ cc -xtarget=ultra -xarch=v8plus -Xa -xO5, running 'des_opts' -+ gives a speed of 344,000 des/s while 'speed' gives 459,000 des/s. -+ I'll record the higher since it is coming from the library but it -+ is all rather weird. -+[2] Similar to the ultra sparc ([1]), 181,000 for 'des_opts' vs 175,000. -+[3] I was unable to get access to this machine when it was not heavily loaded. -+ As such, my timing program was never able to get more that %30 of the CPU. -+ This would cause the program to give much lower speed numbers because -+ it would be 'fighting' to stay in the cache with the other CPU burning -+ processes. ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/podd.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,75 @@ -+/* crypto/des/podd.h */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+static const unsigned char odd_parity[256]={ -+ 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, -+ 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, -+ 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, -+ 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, -+ 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, -+ 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, -+ 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, -+112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, -+128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, -+145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, -+161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, -+176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, -+193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, -+208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, -+224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, -+241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254}; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/set_key.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,246 @@ -+/* crypto/des/set_key.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+/* set_key.c v 1.4 eay 24/9/91 -+ * 1.4 Speed up by 400% :-) -+ * 1.3 added register declarations. -+ * 1.2 unrolled make_key_sched a bit more -+ * 1.1 added norm_expand_bits -+ * 1.0 First working version -+ */ -+#include "des_locl.h" -+#include "podd.h" -+#include "sk.h" -+ -+#ifndef NOPROTO -+static int check_parity(des_cblock (*key)); -+#else -+static int check_parity(); -+#endif -+ -+int des_check_key=0; -+ -+void des_set_odd_parity(key) -+des_cblock (*key); -+ { -+ int i; -+ -+ for (i=0; i>(n))^(b))&(m)),\ -+ * (b)^=(t),\ -+ * (a)=((a)^((t)<<(n)))) -+ */ -+ -+#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ -+ (a)=(a)^(t)^(t>>(16-(n)))) -+ -+/* return 0 if key parity is odd (correct), -+ * return -1 if key parity error, -+ * return -2 if illegal weak key. -+ */ -+int des_set_key(key, schedule) -+des_cblock (*key); -+des_key_schedule schedule; -+ { -+ static int shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0}; -+ register DES_LONG c,d,t,s,t2; -+ register unsigned char *in; -+ register DES_LONG *k; -+ register int i; -+ -+ if (des_check_key) -+ { -+ if (!check_parity(key)) -+ return(-1); -+ -+ if (des_is_weak_key(key)) -+ return(-2); -+ } -+ -+ k=(DES_LONG *)schedule; -+ in=(unsigned char *)key; -+ -+ c2l(in,c); -+ c2l(in,d); -+ -+ /* do PC1 in 60 simple operations */ -+/* PERM_OP(d,c,t,4,0x0f0f0f0fL); -+ HPERM_OP(c,t,-2, 0xcccc0000L); -+ HPERM_OP(c,t,-1, 0xaaaa0000L); -+ HPERM_OP(c,t, 8, 0x00ff0000L); -+ HPERM_OP(c,t,-1, 0xaaaa0000L); -+ HPERM_OP(d,t,-8, 0xff000000L); -+ HPERM_OP(d,t, 8, 0x00ff0000L); -+ HPERM_OP(d,t, 2, 0x33330000L); -+ d=((d&0x00aa00aaL)<<7L)|((d&0x55005500L)>>7L)|(d&0xaa55aa55L); -+ d=(d>>8)|((c&0xf0000000L)>>4); -+ c&=0x0fffffffL; */ -+ -+ /* I now do it in 47 simple operations :-) -+ * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) -+ * for the inspiration. :-) */ -+ PERM_OP (d,c,t,4,0x0f0f0f0fL); -+ HPERM_OP(c,t,-2,0xcccc0000L); -+ HPERM_OP(d,t,-2,0xcccc0000L); -+ PERM_OP (d,c,t,1,0x55555555L); -+ PERM_OP (c,d,t,8,0x00ff00ffL); -+ PERM_OP (d,c,t,1,0x55555555L); -+ d= (((d&0x000000ffL)<<16L)| (d&0x0000ff00L) | -+ ((d&0x00ff0000L)>>16L)|((c&0xf0000000L)>>4L)); -+ c&=0x0fffffffL; -+ -+ for (i=0; i>2L)|(c<<26L)); d=((d>>2L)|(d<<26L)); } -+ else -+ { c=((c>>1L)|(c<<27L)); d=((d>>1L)|(d<<27L)); } -+ c&=0x0fffffffL; -+ d&=0x0fffffffL; -+ /* could be a few less shifts but I am to lazy at this -+ * point in time to investigate */ -+ s= des_skb[0][ (c )&0x3f ]| -+ des_skb[1][((c>> 6)&0x03)|((c>> 7L)&0x3c)]| -+ des_skb[2][((c>>13)&0x0f)|((c>>14L)&0x30)]| -+ des_skb[3][((c>>20)&0x01)|((c>>21L)&0x06) | -+ ((c>>22L)&0x38)]; -+ t= des_skb[4][ (d )&0x3f ]| -+ des_skb[5][((d>> 7L)&0x03)|((d>> 8L)&0x3c)]| -+ des_skb[6][ (d>>15L)&0x3f ]| -+ des_skb[7][((d>>21L)&0x0f)|((d>>22L)&0x30)]; -+ -+ /* table contained 0213 4657 */ -+ t2=((t<<16L)|(s&0x0000ffffL))&0xffffffffL; -+ *(k++)=ROTATE(t2,30)&0xffffffffL; -+ -+ t2=((s>>16L)|(t&0xffff0000L)); -+ *(k++)=ROTATE(t2,26)&0xffffffffL; -+ } -+ return(0); -+ } -+ -+int des_key_sched(key, schedule) -+des_cblock (*key); -+des_key_schedule schedule; -+ { -+ return(des_set_key(key,schedule)); -+ } ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/sk.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,204 @@ -+/* crypto/des/sk.h */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+static const DES_LONG des_skb[8][64]={ -+{ -+/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ -+0x00000000L,0x00000010L,0x20000000L,0x20000010L, -+0x00010000L,0x00010010L,0x20010000L,0x20010010L, -+0x00000800L,0x00000810L,0x20000800L,0x20000810L, -+0x00010800L,0x00010810L,0x20010800L,0x20010810L, -+0x00000020L,0x00000030L,0x20000020L,0x20000030L, -+0x00010020L,0x00010030L,0x20010020L,0x20010030L, -+0x00000820L,0x00000830L,0x20000820L,0x20000830L, -+0x00010820L,0x00010830L,0x20010820L,0x20010830L, -+0x00080000L,0x00080010L,0x20080000L,0x20080010L, -+0x00090000L,0x00090010L,0x20090000L,0x20090010L, -+0x00080800L,0x00080810L,0x20080800L,0x20080810L, -+0x00090800L,0x00090810L,0x20090800L,0x20090810L, -+0x00080020L,0x00080030L,0x20080020L,0x20080030L, -+0x00090020L,0x00090030L,0x20090020L,0x20090030L, -+0x00080820L,0x00080830L,0x20080820L,0x20080830L, -+0x00090820L,0x00090830L,0x20090820L,0x20090830L, -+},{ -+/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ -+0x00000000L,0x02000000L,0x00002000L,0x02002000L, -+0x00200000L,0x02200000L,0x00202000L,0x02202000L, -+0x00000004L,0x02000004L,0x00002004L,0x02002004L, -+0x00200004L,0x02200004L,0x00202004L,0x02202004L, -+0x00000400L,0x02000400L,0x00002400L,0x02002400L, -+0x00200400L,0x02200400L,0x00202400L,0x02202400L, -+0x00000404L,0x02000404L,0x00002404L,0x02002404L, -+0x00200404L,0x02200404L,0x00202404L,0x02202404L, -+0x10000000L,0x12000000L,0x10002000L,0x12002000L, -+0x10200000L,0x12200000L,0x10202000L,0x12202000L, -+0x10000004L,0x12000004L,0x10002004L,0x12002004L, -+0x10200004L,0x12200004L,0x10202004L,0x12202004L, -+0x10000400L,0x12000400L,0x10002400L,0x12002400L, -+0x10200400L,0x12200400L,0x10202400L,0x12202400L, -+0x10000404L,0x12000404L,0x10002404L,0x12002404L, -+0x10200404L,0x12200404L,0x10202404L,0x12202404L, -+},{ -+/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ -+0x00000000L,0x00000001L,0x00040000L,0x00040001L, -+0x01000000L,0x01000001L,0x01040000L,0x01040001L, -+0x00000002L,0x00000003L,0x00040002L,0x00040003L, -+0x01000002L,0x01000003L,0x01040002L,0x01040003L, -+0x00000200L,0x00000201L,0x00040200L,0x00040201L, -+0x01000200L,0x01000201L,0x01040200L,0x01040201L, -+0x00000202L,0x00000203L,0x00040202L,0x00040203L, -+0x01000202L,0x01000203L,0x01040202L,0x01040203L, -+0x08000000L,0x08000001L,0x08040000L,0x08040001L, -+0x09000000L,0x09000001L,0x09040000L,0x09040001L, -+0x08000002L,0x08000003L,0x08040002L,0x08040003L, -+0x09000002L,0x09000003L,0x09040002L,0x09040003L, -+0x08000200L,0x08000201L,0x08040200L,0x08040201L, -+0x09000200L,0x09000201L,0x09040200L,0x09040201L, -+0x08000202L,0x08000203L,0x08040202L,0x08040203L, -+0x09000202L,0x09000203L,0x09040202L,0x09040203L, -+},{ -+/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ -+0x00000000L,0x00100000L,0x00000100L,0x00100100L, -+0x00000008L,0x00100008L,0x00000108L,0x00100108L, -+0x00001000L,0x00101000L,0x00001100L,0x00101100L, -+0x00001008L,0x00101008L,0x00001108L,0x00101108L, -+0x04000000L,0x04100000L,0x04000100L,0x04100100L, -+0x04000008L,0x04100008L,0x04000108L,0x04100108L, -+0x04001000L,0x04101000L,0x04001100L,0x04101100L, -+0x04001008L,0x04101008L,0x04001108L,0x04101108L, -+0x00020000L,0x00120000L,0x00020100L,0x00120100L, -+0x00020008L,0x00120008L,0x00020108L,0x00120108L, -+0x00021000L,0x00121000L,0x00021100L,0x00121100L, -+0x00021008L,0x00121008L,0x00021108L,0x00121108L, -+0x04020000L,0x04120000L,0x04020100L,0x04120100L, -+0x04020008L,0x04120008L,0x04020108L,0x04120108L, -+0x04021000L,0x04121000L,0x04021100L,0x04121100L, -+0x04021008L,0x04121008L,0x04021108L,0x04121108L, -+},{ -+/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ -+0x00000000L,0x10000000L,0x00010000L,0x10010000L, -+0x00000004L,0x10000004L,0x00010004L,0x10010004L, -+0x20000000L,0x30000000L,0x20010000L,0x30010000L, -+0x20000004L,0x30000004L,0x20010004L,0x30010004L, -+0x00100000L,0x10100000L,0x00110000L,0x10110000L, -+0x00100004L,0x10100004L,0x00110004L,0x10110004L, -+0x20100000L,0x30100000L,0x20110000L,0x30110000L, -+0x20100004L,0x30100004L,0x20110004L,0x30110004L, -+0x00001000L,0x10001000L,0x00011000L,0x10011000L, -+0x00001004L,0x10001004L,0x00011004L,0x10011004L, -+0x20001000L,0x30001000L,0x20011000L,0x30011000L, -+0x20001004L,0x30001004L,0x20011004L,0x30011004L, -+0x00101000L,0x10101000L,0x00111000L,0x10111000L, -+0x00101004L,0x10101004L,0x00111004L,0x10111004L, -+0x20101000L,0x30101000L,0x20111000L,0x30111000L, -+0x20101004L,0x30101004L,0x20111004L,0x30111004L, -+},{ -+/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ -+0x00000000L,0x08000000L,0x00000008L,0x08000008L, -+0x00000400L,0x08000400L,0x00000408L,0x08000408L, -+0x00020000L,0x08020000L,0x00020008L,0x08020008L, -+0x00020400L,0x08020400L,0x00020408L,0x08020408L, -+0x00000001L,0x08000001L,0x00000009L,0x08000009L, -+0x00000401L,0x08000401L,0x00000409L,0x08000409L, -+0x00020001L,0x08020001L,0x00020009L,0x08020009L, -+0x00020401L,0x08020401L,0x00020409L,0x08020409L, -+0x02000000L,0x0A000000L,0x02000008L,0x0A000008L, -+0x02000400L,0x0A000400L,0x02000408L,0x0A000408L, -+0x02020000L,0x0A020000L,0x02020008L,0x0A020008L, -+0x02020400L,0x0A020400L,0x02020408L,0x0A020408L, -+0x02000001L,0x0A000001L,0x02000009L,0x0A000009L, -+0x02000401L,0x0A000401L,0x02000409L,0x0A000409L, -+0x02020001L,0x0A020001L,0x02020009L,0x0A020009L, -+0x02020401L,0x0A020401L,0x02020409L,0x0A020409L, -+},{ -+/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ -+0x00000000L,0x00000100L,0x00080000L,0x00080100L, -+0x01000000L,0x01000100L,0x01080000L,0x01080100L, -+0x00000010L,0x00000110L,0x00080010L,0x00080110L, -+0x01000010L,0x01000110L,0x01080010L,0x01080110L, -+0x00200000L,0x00200100L,0x00280000L,0x00280100L, -+0x01200000L,0x01200100L,0x01280000L,0x01280100L, -+0x00200010L,0x00200110L,0x00280010L,0x00280110L, -+0x01200010L,0x01200110L,0x01280010L,0x01280110L, -+0x00000200L,0x00000300L,0x00080200L,0x00080300L, -+0x01000200L,0x01000300L,0x01080200L,0x01080300L, -+0x00000210L,0x00000310L,0x00080210L,0x00080310L, -+0x01000210L,0x01000310L,0x01080210L,0x01080310L, -+0x00200200L,0x00200300L,0x00280200L,0x00280300L, -+0x01200200L,0x01200300L,0x01280200L,0x01280300L, -+0x00200210L,0x00200310L,0x00280210L,0x00280310L, -+0x01200210L,0x01200310L,0x01280210L,0x01280310L, -+},{ -+/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ -+0x00000000L,0x04000000L,0x00040000L,0x04040000L, -+0x00000002L,0x04000002L,0x00040002L,0x04040002L, -+0x00002000L,0x04002000L,0x00042000L,0x04042000L, -+0x00002002L,0x04002002L,0x00042002L,0x04042002L, -+0x00000020L,0x04000020L,0x00040020L,0x04040020L, -+0x00000022L,0x04000022L,0x00040022L,0x04040022L, -+0x00002020L,0x04002020L,0x00042020L,0x04042020L, -+0x00002022L,0x04002022L,0x00042022L,0x04042022L, -+0x00000800L,0x04000800L,0x00040800L,0x04040800L, -+0x00000802L,0x04000802L,0x00040802L,0x04040802L, -+0x00002800L,0x04002800L,0x00042800L,0x04042800L, -+0x00002802L,0x04002802L,0x00042802L,0x04042802L, -+0x00000820L,0x04000820L,0x00040820L,0x04040820L, -+0x00000822L,0x04000822L,0x00040822L,0x04040822L, -+0x00002820L,0x04002820L,0x00042820L,0x04042820L, -+0x00002822L,0x04002822L,0x00042822L,0x04042822L, -+}}; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/speed.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,329 @@ -+/* crypto/des/speed.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+/* 11-Sep-92 Andrew Daviel Support for Silicon Graphics IRIX added */ -+/* 06-Apr-92 Luke Brennan Support for VMS and add extra signal calls */ -+ -+#ifndef MSDOS -+#define TIMES -+#endif -+ -+#include -+#ifndef MSDOS -+#include -+#else -+#include -+extern int exit(); -+#endif -+#include -+#ifndef VMS -+#ifndef _IRIX -+#include -+#endif -+#ifdef TIMES -+#include -+#include -+#endif -+#else /* VMS */ -+#include -+struct tms { -+ time_t tms_utime; -+ time_t tms_stime; -+ time_t tms_uchild; /* I dunno... */ -+ time_t tms_uchildsys; /* so these names are a guess :-) */ -+ } -+#endif -+#ifndef TIMES -+#include -+#endif -+ -+#ifdef sun -+#include -+#include -+#endif -+ -+#include "des_locl.h" -+ -+/* The following if from times(3) man page. It may need to be changed */ -+#ifndef HZ -+# ifndef CLK_TCK -+# ifndef _BSD_CLK_TCK_ /* FreeBSD fix */ -+# ifndef VMS -+# define HZ 100.0 -+# else /* VMS */ -+# define HZ 100.0 -+# endif -+# else /* _BSD_CLK_TCK_ */ -+# define HZ ((double)_BSD_CLK_TCK_) -+# endif -+# else /* CLK_TCK */ -+# define HZ ((double)CLK_TCK) -+# endif -+#endif -+ -+#define BUFSIZE ((long)1024) -+long run=0; -+ -+#ifndef NOPROTO -+double Time_F(int s); -+#else -+double Time_F(); -+#endif -+ -+#ifdef SIGALRM -+#if defined(__STDC__) || defined(sgi) || defined(_AIX) -+#define SIGRETTYPE void -+#else -+#define SIGRETTYPE int -+#endif -+ -+#ifndef NOPROTO -+SIGRETTYPE sig_done(int sig); -+#else -+SIGRETTYPE sig_done(); -+#endif -+ -+SIGRETTYPE sig_done(sig) -+int sig; -+ { -+ signal(SIGALRM,sig_done); -+ run=0; -+#ifdef LINT -+ sig=sig; -+#endif -+ } -+#endif -+ -+#define START 0 -+#define STOP 1 -+ -+double Time_F(s) -+int s; -+ { -+ double ret; -+#ifdef TIMES -+ static struct tms tstart,tend; -+ -+ if (s == START) -+ { -+ times(&tstart); -+ return(0); -+ } -+ else -+ { -+ times(&tend); -+ ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ; -+ return((ret == 0.0)?1e-6:ret); -+ } -+#else /* !times() */ -+ static struct timeb tstart,tend; -+ long i; -+ -+ if (s == START) -+ { -+ ftime(&tstart); -+ return(0); -+ } -+ else -+ { -+ ftime(&tend); -+ i=(long)tend.millitm-(long)tstart.millitm; -+ ret=((double)(tend.time-tstart.time))+((double)i)/1e3; -+ return((ret == 0.0)?1e-6:ret); -+ } -+#endif -+ } -+ -+int main(argc,argv) -+int argc; -+char **argv; -+ { -+ long count; -+ static unsigned char buf[BUFSIZE]; -+ static des_cblock key ={0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0}; -+ static des_cblock key2={0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12}; -+ static des_cblock key3={0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34}; -+ des_key_schedule sch,sch2,sch3; -+ double a,b,c,d,e; -+#ifndef SIGALRM -+ long ca,cb,cc,cd,ce; -+#endif -+ -+#ifndef TIMES -+ printf("To get the most acurate results, try to run this\n"); -+ printf("program when this computer is idle.\n"); -+#endif -+ -+ des_set_key((C_Block *)key2,sch2); -+ des_set_key((C_Block *)key3,sch3); -+ -+#ifndef SIGALRM -+ printf("First we calculate the approximate speed ...\n"); -+ des_set_key((C_Block *)key,sch); -+ count=10; -+ do { -+ long i; -+ DES_LONG data[2]; -+ -+ count*=2; -+ Time_F(START); -+ for (i=count; i; i--) -+ des_encrypt(data,&(sch[0]),DES_ENCRYPT); -+ d=Time_F(STOP); -+ } while (d < 3.0); -+ ca=count; -+ cb=count*3; -+ cc=count*3*8/BUFSIZE+1; -+ cd=count*8/BUFSIZE+1; -+ ce=count/20+1; -+ printf("Doing set_key %ld times\n",ca); -+#define COND(d) (count != (d)) -+#define COUNT(d) (d) -+#else -+#define COND(c) (run) -+#define COUNT(d) (count) -+ signal(SIGALRM,sig_done); -+ printf("Doing set_key for 10 seconds\n"); -+ alarm(10); -+#endif -+ -+ Time_F(START); -+ for (count=0,run=1; COND(ca); count++) -+ des_set_key((C_Block *)key,sch); -+ d=Time_F(STOP); -+ printf("%ld set_key's in %.2f seconds\n",count,d); -+ a=((double)COUNT(ca))/d; -+ -+#ifdef SIGALRM -+ printf("Doing des_encrypt's for 10 seconds\n"); -+ alarm(10); -+#else -+ printf("Doing des_encrypt %ld times\n",cb); -+#endif -+ Time_F(START); -+ for (count=0,run=1; COND(cb); count++) -+ { -+ DES_LONG data[2]; -+ -+ des_encrypt(data,&(sch[0]),DES_ENCRYPT); -+ } -+ d=Time_F(STOP); -+ printf("%ld des_encrypt's in %.2f second\n",count,d); -+ b=((double)COUNT(cb)*8)/d; -+ -+#ifdef SIGALRM -+ printf("Doing des_cbc_encrypt on %ld byte blocks for 10 seconds\n", -+ BUFSIZE); -+ alarm(10); -+#else -+ printf("Doing des_cbc_encrypt %ld times on %ld byte blocks\n",cc, -+ BUFSIZE); -+#endif -+ Time_F(START); -+ for (count=0,run=1; COND(cc); count++) -+ des_ncbc_encrypt((C_Block *)buf,(C_Block *)buf,BUFSIZE,&(sch[0]), -+ (C_Block *)&(key[0]),DES_ENCRYPT); -+ d=Time_F(STOP); -+ printf("%ld des_cbc_encrypt's of %ld byte blocks in %.2f second\n", -+ count,BUFSIZE,d); -+ c=((double)COUNT(cc)*BUFSIZE)/d; -+ -+#ifdef SIGALRM -+ printf("Doing des_ede_cbc_encrypt on %ld byte blocks for 10 seconds\n", -+ BUFSIZE); -+ alarm(10); -+#else -+ printf("Doing des_ede_cbc_encrypt %ld times on %ld byte blocks\n",cd, -+ BUFSIZE); -+#endif -+ Time_F(START); -+ for (count=0,run=1; COND(cd); count++) -+ des_ede3_cbc_encrypt((C_Block *)buf,(C_Block *)buf,BUFSIZE, -+ &(sch[0]), -+ &(sch2[0]), -+ &(sch3[0]), -+ (C_Block *)&(key[0]), -+ DES_ENCRYPT); -+ d=Time_F(STOP); -+ printf("%ld des_ede_cbc_encrypt's of %ld byte blocks in %.2f second\n", -+ count,BUFSIZE,d); -+ d=((double)COUNT(cd)*BUFSIZE)/d; -+ -+#ifdef SIGALRM -+ printf("Doing crypt for 10 seconds\n"); -+ alarm(10); -+#else -+ printf("Doing crypt %ld times\n",ce); -+#endif -+ Time_F(START); -+ for (count=0,run=1; COND(ce); count++) -+ crypt("testing1","ef"); -+ e=Time_F(STOP); -+ printf("%ld crypts in %.2f second\n",count,e); -+ e=((double)COUNT(ce))/e; -+ -+ printf("set_key per sec = %12.2f (%9.3fuS)\n",a,1.0e6/a); -+ printf("DES raw ecb bytes per sec = %12.2f (%9.3fuS)\n",b,8.0e6/b); -+ printf("DES cbc bytes per sec = %12.2f (%9.3fuS)\n",c,8.0e6/c); -+ printf("DES ede cbc bytes per sec = %12.2f (%9.3fuS)\n",d,8.0e6/d); -+ printf("crypt per sec = %12.2f (%9.3fuS)\n",e,1.0e6/e); -+ exit(0); -+#if defined(LINT) || defined(MSDOS) -+ return(0); -+#endif -+ } ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/spr.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,204 @@ -+/* crypto/des/spr.h */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+const DES_LONG des_SPtrans[8][64]={ -+{ -+/* nibble 0 */ -+0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L, -+0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L, -+0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L, -+0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L, -+0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L, -+0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L, -+0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L, -+0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L, -+0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L, -+0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L, -+0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L, -+0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L, -+0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L, -+0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L, -+0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L, -+0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L, -+},{ -+/* nibble 1 */ -+0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L, -+0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L, -+0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L, -+0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L, -+0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L, -+0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L, -+0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L, -+0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L, -+0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L, -+0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L, -+0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L, -+0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L, -+0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L, -+0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L, -+0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L, -+0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L, -+},{ -+/* nibble 2 */ -+0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L, -+0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L, -+0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L, -+0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L, -+0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L, -+0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L, -+0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L, -+0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L, -+0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L, -+0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L, -+0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L, -+0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L, -+0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L, -+0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L, -+0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L, -+0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L, -+},{ -+/* nibble 3 */ -+0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L, -+0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L, -+0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L, -+0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L, -+0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L, -+0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L, -+0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L, -+0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L, -+0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L, -+0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L, -+0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L, -+0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L, -+0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L, -+0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L, -+0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L, -+0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L, -+},{ -+/* nibble 4 */ -+0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L, -+0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L, -+0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L, -+0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L, -+0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L, -+0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L, -+0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L, -+0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L, -+0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L, -+0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L, -+0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L, -+0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L, -+0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L, -+0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L, -+0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L, -+0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L, -+},{ -+/* nibble 5 */ -+0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L, -+0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L, -+0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L, -+0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L, -+0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L, -+0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L, -+0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L, -+0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L, -+0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L, -+0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L, -+0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L, -+0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L, -+0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L, -+0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L, -+0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L, -+0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L, -+},{ -+/* nibble 6 */ -+0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L, -+0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L, -+0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L, -+0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L, -+0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L, -+0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L, -+0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L, -+0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L, -+0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L, -+0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L, -+0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L, -+0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L, -+0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L, -+0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L, -+0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L, -+0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L, -+},{ -+/* nibble 7 */ -+0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L, -+0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L, -+0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L, -+0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L, -+0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L, -+0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L, -+0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L, -+0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L, -+0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L, -+0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L, -+0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L, -+0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L, -+0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L, -+0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L, -+0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L, -+0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L, -+}}; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/crypto/aes.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,97 @@ -+// I retain copyright in this code but I encourage its free use provided -+// that I don't carry any responsibility for the results. I am especially -+// happy to see it used in free and open source software. If you do use -+// it I would appreciate an acknowledgement of its origin in the code or -+// the product that results and I would also appreciate knowing a little -+// about the use to which it is being put. I am grateful to Frank Yellin -+// for some ideas that are used in this implementation. -+// -+// Dr B. R. Gladman 6th April 2001. -+// -+// This is an implementation of the AES encryption algorithm (Rijndael) -+// designed by Joan Daemen and Vincent Rijmen. This version is designed -+// to provide both fixed and dynamic block and key lengths and can also -+// run with either big or little endian internal byte order (see aes.h). -+// It inputs block and key lengths in bytes with the legal values being -+// 16, 24 and 32. -+ -+/* -+ * Modified by Jari Ruusu, May 1 2001 -+ * - Fixed some compile warnings, code was ok but gcc warned anyway. -+ * - Changed basic types: byte -> unsigned char, word -> u_int32_t -+ * - Major name space cleanup: Names visible to outside now begin -+ * with "aes_" or "AES_". A lot of stuff moved from aes.h to aes.c -+ * - Removed C++ and DLL support as part of name space cleanup. -+ * - Eliminated unnecessary recomputation of tables. (actual bug fix) -+ * - Merged precomputed constant tables to aes.c file. -+ * - Removed data alignment restrictions for portability reasons. -+ * - Made block and key lengths accept bit count (128/192/256) -+ * as well byte count (16/24/32). -+ * - Removed all error checks. This change also eliminated the need -+ * to preinitialize the context struct to zero. -+ * - Removed some totally unused constants. -+ */ -+ -+#ifndef _AES_H -+#define _AES_H -+ -+#if defined(__linux__) && defined(__KERNEL__) -+# include -+#else -+# include -+#endif -+ -+// CONFIGURATION OPTIONS (see also aes.c) -+// -+// Define AES_BLOCK_SIZE to set the cipher block size (16, 24 or 32) or -+// leave this undefined for dynamically variable block size (this will -+// result in much slower code). -+// IMPORTANT NOTE: AES_BLOCK_SIZE is in BYTES (16, 24, 32 or undefined). If -+// left undefined a slower version providing variable block length is compiled -+ -+#define AES_BLOCK_SIZE 16 -+ -+// The number of key schedule words for different block and key lengths -+// allowing for method of computation which requires the length to be a -+// multiple of the key length -+// -+// Nk = 4 6 8 -+// ------------- -+// Nb = 4 | 60 60 64 -+// 6 | 96 90 96 -+// 8 | 120 120 120 -+ -+#if !defined(AES_BLOCK_SIZE) || (AES_BLOCK_SIZE == 32) -+#define AES_KS_LENGTH 120 -+#define AES_RC_LENGTH 29 -+#else -+#define AES_KS_LENGTH 4 * AES_BLOCK_SIZE -+#define AES_RC_LENGTH (9 * AES_BLOCK_SIZE) / 8 - 8 -+#endif -+ -+typedef struct -+{ -+ u_int32_t aes_Nkey; // the number of words in the key input block -+ u_int32_t aes_Nrnd; // the number of cipher rounds -+ u_int32_t aes_e_key[AES_KS_LENGTH]; // the encryption key schedule -+ u_int32_t aes_d_key[AES_KS_LENGTH]; // the decryption key schedule -+#if !defined(AES_BLOCK_SIZE) -+ u_int32_t aes_Ncol; // the number of columns in the cipher state -+#endif -+} aes_context; -+ -+// THE CIPHER INTERFACE -+ -+#if !defined(AES_BLOCK_SIZE) -+extern void aes_set_blk(aes_context *, const int); -+#endif -+extern void aes_set_key(aes_context *, const unsigned char [], const int, const int); -+extern void aes_encrypt(const aes_context *, const unsigned char [], unsigned char []); -+extern void aes_decrypt(const aes_context *, const unsigned char [], unsigned char []); -+ -+// The block length inputs to aes_set_block and aes_set_key are in numbers -+// of bytes or bits. The calls to subroutines must be made in the above -+// order but multiple calls can be made without repeating earlier calls -+// if their parameters have not changed. -+ -+#endif // _AES_H ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/crypto/aes_cbc.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,4 @@ -+/* Glue header */ -+#include "aes.h" -+int AES_set_key(aes_context *aes_ctx, const u_int8_t * key, int keysize); -+int AES_cbc_encrypt(aes_context *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt); ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/crypto/aes_xcbc_mac.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,12 @@ -+#ifndef _AES_XCBC_MAC_H -+#define _AES_XCBC_MAC_H -+ -+typedef u_int32_t aes_block[4]; -+typedef struct { -+ aes_context ctx_k1; -+ aes_block k2; -+ aes_block k3; -+} aes_context_mac; -+int AES_xcbc_mac_set_key(aes_context_mac *ctxm, const u_int8_t *key, int keylen); -+int AES_xcbc_mac_hash(const aes_context_mac *ctxm, const u_int8_t * in, int ilen, u_int8_t hash[16]); -+#endif /* _AES_XCBC_MAC_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/crypto/cbc_generic.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,110 @@ -+#ifndef _CBC_GENERIC_H -+#define _CBC_GENERIC_H -+/* -+ * CBC macro helpers -+ * -+ * Author: JuanJo Ciarlante -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ */ -+ -+/* -+ * Heavily inspired in loop_AES -+ */ -+#define CBC_IMPL_BLK16(name, ctx_type, addr_type, enc_func, dec_func) \ -+int name(ctx_type *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) { \ -+ int ret=ilen, pos; \ -+ const u_int32_t *iv_i; \ -+ if ((ilen) % 16) return 0; \ -+ if (encrypt) { \ -+ pos=0; \ -+ while(pos=0) { \ -+ dec_func(ctx, (const addr_type) in, (addr_type) out); \ -+ if (pos==0) \ -+ iv_i=(const u_int32_t*) (iv); \ -+ else \ -+ iv_i=(const u_int32_t*) (in-16); \ -+ *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \ -+ *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \ -+ *((u_int32_t *)(&out[ 8])) ^= iv_i[2]; \ -+ *((u_int32_t *)(&out[12])) ^= iv_i[3]; \ -+ in-=16; \ -+ out-=16; \ -+ pos-=16; \ -+ } \ -+ } \ -+ return ret; \ -+} -+#define CBC_IMPL_BLK8(name, ctx_type, addr_type, enc_func, dec_func) \ -+int name(ctx_type *ctx, u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) { \ -+ int ret=ilen, pos; \ -+ const u_int32_t *iv_i; \ -+ if ((ilen) % 8) return 0; \ -+ if (encrypt) { \ -+ pos=0; \ -+ while(pos=0) { \ -+ dec_func(ctx, (const addr_type)in, (addr_type)out); \ -+ if (pos==0) \ -+ iv_i=(const u_int32_t*) (iv); \ -+ else \ -+ iv_i=(const u_int32_t*) (in-8); \ -+ *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \ -+ *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \ -+ in-=8; \ -+ out-=8; \ -+ pos-=8; \ -+ } \ -+ } \ -+ return ret; \ -+} -+#define CBC_DECL(name, ctx_type) \ -+int name(ctx_type *ctx, u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) -+/* -+Eg.: -+CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, u_int8_t *, aes_encrypt, aes_decrypt); -+CBC_DECL(AES_cbc_encrypt, aes_context); -+*/ -+#endif /* _CBC_GENERIC_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/crypto/des.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,298 @@ -+/* crypto/des/des.org */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING -+ * -+ * Always modify des.org since des.h is automatically generated from -+ * it during SSLeay configuration. -+ * -+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING -+ */ -+ -+#ifndef HEADER_DES_H -+#define HEADER_DES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+ -+/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a -+ * %20 speed up (longs are 8 bytes, int's are 4). */ -+/* Must be unsigned int on ia64/Itanium or DES breaks badly */ -+ -+#ifdef __KERNEL__ -+#include -+#else -+#include -+#endif -+ -+#ifndef DES_LONG -+#define DES_LONG u_int32_t -+#endif -+ -+typedef unsigned char des_cblock[8]; -+typedef struct { des_cblock ks; } des_key_schedule[16]; -+ -+#define DES_KEY_SZ (sizeof(des_cblock)) -+#define DES_SCHEDULE_SZ (sizeof(des_key_schedule)) -+ -+#define DES_ENCRYPT 1 -+#define DES_DECRYPT 0 -+ -+#define DES_CBC_MODE 0 -+#define DES_PCBC_MODE 1 -+ -+#define des_ecb2_encrypt(i,o,k1,k2,e) \ -+ des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e)) -+ -+#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ -+ des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e)) -+ -+#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \ -+ des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e)) -+ -+#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \ -+ des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n)) -+ -+#define C_Block des_cblock -+#define Key_schedule des_key_schedule -+#ifdef KERBEROS -+#define ENCRYPT DES_ENCRYPT -+#define DECRYPT DES_DECRYPT -+#endif -+#define KEY_SZ DES_KEY_SZ -+#define string_to_key des_string_to_key -+#define read_pw_string des_read_pw_string -+#define random_key des_random_key -+#define pcbc_encrypt des_pcbc_encrypt -+#define set_key des_set_key -+#define key_sched des_key_sched -+#define ecb_encrypt des_ecb_encrypt -+#define cbc_encrypt des_cbc_encrypt -+#define ncbc_encrypt des_ncbc_encrypt -+#define xcbc_encrypt des_xcbc_encrypt -+#define cbc_cksum des_cbc_cksum -+#define quad_cksum des_quad_cksum -+ -+/* For compatibility with the MIT lib - eay 20/05/92 */ -+typedef des_key_schedule bit_64; -+#define des_fixup_key_parity des_set_odd_parity -+#define des_check_key_parity check_parity -+ -+extern int des_check_key; /* defaults to false */ -+extern int des_rw_mode; /* defaults to DES_PCBC_MODE */ -+ -+/* The next line is used to disable full ANSI prototypes, if your -+ * compiler has problems with the prototypes, make sure this line always -+ * evaluates to true :-) */ -+#if defined(MSDOS) || defined(__STDC__) -+#undef NOPROTO -+#endif -+#ifndef NOPROTO -+char *des_options(void); -+void des_ecb3_encrypt(des_cblock *input,des_cblock *output, -+ des_key_schedule ks1,des_key_schedule ks2, -+ des_key_schedule ks3, int enc); -+DES_LONG des_cbc_cksum(des_cblock *input,des_cblock *output, -+ long length,des_key_schedule schedule,des_cblock *ivec); -+void des_cbc_encrypt(des_cblock *input,des_cblock *output,long length, -+ des_key_schedule schedule,des_cblock *ivec,int enc); -+void des_ncbc_encrypt(des_cblock *input,des_cblock *output,long length, -+ des_key_schedule schedule,des_cblock *ivec,int enc); -+void des_xcbc_encrypt(des_cblock *input,des_cblock *output,long length, -+ des_key_schedule schedule,des_cblock *ivec, -+ des_cblock *inw,des_cblock *outw,int enc); -+void des_cfb_encrypt(unsigned char *in,unsigned char *out,int numbits, -+ long length,des_key_schedule schedule,des_cblock *ivec,int enc); -+void des_ecb_encrypt(des_cblock *input,des_cblock *output, -+ des_key_schedule ks,int enc); -+void des_encrypt(DES_LONG *data,des_key_schedule ks, int enc); -+void des_encrypt2(DES_LONG *data,des_key_schedule ks, int enc); -+void des_encrypt3(DES_LONG *data, des_key_schedule ks1, -+ des_key_schedule ks2, des_key_schedule ks3); -+void des_decrypt3(DES_LONG *data, des_key_schedule ks1, -+ des_key_schedule ks2, des_key_schedule ks3); -+void des_ede3_cbc_encrypt(des_cblock *input, des_cblock *output, -+ long length, des_key_schedule ks1, des_key_schedule ks2, -+ des_key_schedule ks3, des_cblock *ivec, int enc); -+void des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out, -+ long length, des_key_schedule ks1, des_key_schedule ks2, -+ des_key_schedule ks3, des_cblock *ivec, int *num, int enc); -+void des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out, -+ long length, des_key_schedule ks1, des_key_schedule ks2, -+ des_key_schedule ks3, des_cblock *ivec, int *num); -+ -+void des_xwhite_in2out(des_cblock (*des_key), des_cblock (*in_white), -+ des_cblock (*out_white)); -+ -+int des_enc_read(int fd,char *buf,int len,des_key_schedule sched, -+ des_cblock *iv); -+int des_enc_write(int fd,char *buf,int len,des_key_schedule sched, -+ des_cblock *iv); -+char *des_fcrypt(const char *buf,const char *salt, char *ret); -+#ifdef PERL5 -+char *des_crypt(const char *buf,const char *salt); -+#else -+/* some stupid compilers complain because I have declared char instead -+ * of const char */ -+#ifndef __KERNEL__ -+#ifdef HEADER_DES_LOCL_H -+char *crypt(const char *buf,const char *salt); -+#else /* HEADER_DES_LOCL_H */ -+char *crypt(void); -+#endif /* HEADER_DES_LOCL_H */ -+#endif /* __KERNEL__ */ -+#endif /* PERL5 */ -+void des_ofb_encrypt(unsigned char *in,unsigned char *out, -+ int numbits,long length,des_key_schedule schedule,des_cblock *ivec); -+void des_pcbc_encrypt(des_cblock *input,des_cblock *output,long length, -+ des_key_schedule schedule,des_cblock *ivec,int enc); -+DES_LONG des_quad_cksum(des_cblock *input,des_cblock *output, -+ long length,int out_count,des_cblock *seed); -+void des_random_seed(des_cblock key); -+void des_random_key(des_cblock ret); -+int des_read_password(des_cblock *key,char *prompt,int verify); -+int des_read_2passwords(des_cblock *key1,des_cblock *key2, -+ char *prompt,int verify); -+int des_read_pw_string(char *buf,int length,char *prompt,int verify); -+void des_set_odd_parity(des_cblock *key); -+int des_is_weak_key(des_cblock *key); -+int des_set_key(des_cblock *key,des_key_schedule schedule); -+int des_key_sched(des_cblock *key,des_key_schedule schedule); -+void des_string_to_key(char *str,des_cblock *key); -+void des_string_to_2keys(char *str,des_cblock *key1,des_cblock *key2); -+void des_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, -+ des_key_schedule schedule, des_cblock *ivec, int *num, int enc); -+void des_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, -+ des_key_schedule schedule, des_cblock *ivec, int *num); -+int des_read_pw(char *buf, char *buff, int size, char *prompt, int verify); -+ -+/* Extra functions from Mark Murray */ -+/* The following functions are not in the normal unix build or the -+ * SSLeay build. When using the SSLeay build, use RAND_seed() -+ * and RAND_bytes() instead. */ -+int des_new_random_key(des_cblock *key); -+void des_init_random_number_generator(des_cblock *key); -+void des_set_random_generator_seed(des_cblock *key); -+void des_set_sequence_number(des_cblock new_sequence_number); -+void des_generate_random_block(des_cblock *block); -+ -+#else -+ -+char *des_options(); -+void des_ecb3_encrypt(); -+DES_LONG des_cbc_cksum(); -+void des_cbc_encrypt(); -+void des_ncbc_encrypt(); -+void des_xcbc_encrypt(); -+void des_cfb_encrypt(); -+void des_ede3_cfb64_encrypt(); -+void des_ede3_ofb64_encrypt(); -+void des_ecb_encrypt(); -+void des_encrypt(); -+void des_encrypt2(); -+void des_encrypt3(); -+void des_decrypt3(); -+void des_ede3_cbc_encrypt(); -+int des_enc_read(); -+int des_enc_write(); -+char *des_fcrypt(); -+#ifdef PERL5 -+char *des_crypt(); -+#else -+char *crypt(); -+#endif -+void des_ofb_encrypt(); -+void des_pcbc_encrypt(); -+DES_LONG des_quad_cksum(); -+void des_random_seed(); -+void des_random_key(); -+int des_read_password(); -+int des_read_2passwords(); -+int des_read_pw_string(); -+void des_set_odd_parity(); -+int des_is_weak_key(); -+int des_set_key(); -+int des_key_sched(); -+void des_string_to_key(); -+void des_string_to_2keys(); -+void des_cfb64_encrypt(); -+void des_ofb64_encrypt(); -+int des_read_pw(); -+void des_xwhite_in2out(); -+ -+/* Extra functions from Mark Murray */ -+/* The following functions are not in the normal unix build or the -+ * SSLeay build. When using the SSLeay build, use RAND_seed() -+ * and RAND_bytes() instead. */ -+#ifdef FreeBSD -+int des_new_random_key(); -+void des_init_random_number_generator(); -+void des_set_random_generator_seed(); -+void des_set_sequence_number(); -+void des_generate_random_block(); -+#endif -+ -+#endif -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/mast.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,33 @@ -+struct mast_callbacks { -+ int (*packet_encap)(struct device *mast, void *context, -+ struct sk_buff *skb, int flowref); -+ int (*link_inquire)(struct device *mast, void *context); -+}; -+ -+ -+struct device *mast_init (int family, -+ struct mast_callbacks *callbacks, -+ unsigned int flags, -+ unsigned int desired_unit, -+ unsigned int max_flowref, -+ void *context); -+ -+int mast_destroy(struct device *mast); -+ -+int mast_recv(struct device *mast, struct sk_buff *skb, int flowref); -+ -+/* free this skb as being useless, increment failure count. */ -+int mast_toast(struct device *mast, struct sk_buff *skb, int flowref); -+ -+int mast_linkstat (struct device *mast, int flowref, -+ int status); -+ -+int mast_setreference (struct device *mast, -+ int defaultSA); -+ -+int mast_setneighbor (struct device *mast, -+ struct sockaddr *source, -+ struct sockaddr *destination, -+ int flowref); -+ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,513 @@ -+#ifndef _OPENSWAN_H -+/* -+ * header file for FreeS/WAN library functions -+ * Copyright (C) 1998, 1999, 2000 Henry Spencer. -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#define _OPENSWAN_H /* seen it, no need to see it again */ -+ -+ -+ -+/* -+ * We've just got to have some datatypes defined... And annoyingly, just -+ * where we get them depends on whether we're in userland or not. -+ */ -+/* things that need to come from one place or the other, depending */ -+#ifdef __KERNEL__ -+#include -+#include -+#include -+#include -+#include -+#define assert(foo) /* nothing */ -+#else -+#include -+#include -+#include -+#include -+#include -+#include -+ -+# define uint8_t u_int8_t -+# define uint16_t u_int16_t -+# define uint32_t u_int32_t -+# define uint64_t u_int64_t -+ -+ -+# define DEBUG_NO_STATIC static -+ -+#endif -+ -+#include -+ -+ -+/* -+ * Grab the kernel version to see if we have NET_21, and therefore -+ * IPv6. Some of this is repeated from ipsec_kversions.h. Of course, -+ * we aren't really testing if the kernel has IPv6, but rather if the -+ * the include files do. -+ */ -+#include -+#ifndef KERNEL_VERSION -+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) -+#define NET_21 -+#endif -+ -+#ifndef IPPROTO_COMP -+# define IPPROTO_COMP 108 -+#endif /* !IPPROTO_COMP */ -+ -+#ifndef IPPROTO_INT -+# define IPPROTO_INT 61 -+#endif /* !IPPROTO_INT */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+#ifndef DEBUG_NO_STATIC -+# define DEBUG_NO_STATIC -+#endif -+#else /* CONFIG_IPSEC_DEBUG */ -+#ifndef DEBUG_NO_STATIC -+# define DEBUG_NO_STATIC static -+#endif -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL /* KERNEL ifdef */ -+#ifndef NAT_TRAVERSAL -+#define NAT_TRAVERSAL -+#endif -+#endif -+#ifdef NAT_TRAVERSAL -+#define ESPINUDP_WITH_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ -+#define ESPINUDP_WITH_NON_ESP 2 /* draft-ietf-ipsec-nat-t-ike-02 */ -+#endif -+ -+/* -+ * Basic data types for the address-handling functions. -+ * ip_address and ip_subnet are supposed to be opaque types; do not -+ * use their definitions directly, they are subject to change! -+ */ -+ -+/* first, some quick fakes in case we're on an old system with no IPv6 */ -+#ifndef s6_addr16 -+struct in6_addr { -+ union -+ { -+ __u8 u6_addr8[16]; -+ __u16 u6_addr16[8]; -+ __u32 u6_addr32[4]; -+ } in6_u; -+#define s6_addr in6_u.u6_addr8 -+#define s6_addr16 in6_u.u6_addr16 -+#define s6_addr32 in6_u.u6_addr32 -+}; -+struct sockaddr_in6 { -+ unsigned short int sin6_family; /* AF_INET6 */ -+ __u16 sin6_port; /* Transport layer port # */ -+ __u32 sin6_flowinfo; /* IPv6 flow information */ -+ struct in6_addr sin6_addr; /* IPv6 address */ -+ __u32 sin6_scope_id; /* scope id (new in RFC2553) */ -+}; -+#endif /* !s6_addr16 */ -+ -+/* then the main types */ -+typedef struct { -+ union { -+ struct sockaddr_in v4; -+ struct sockaddr_in6 v6; -+ } u; -+} ip_address; -+typedef struct { -+ ip_address addr; -+ int maskbits; -+} ip_subnet; -+ -+/* and the SA ID stuff */ -+#ifdef __KERNEL__ -+typedef __u32 ipsec_spi_t; -+#else -+typedef u_int32_t ipsec_spi_t; -+#endif -+typedef struct { /* to identify an SA, we need: */ -+ ip_address dst; /* A. destination host */ -+ ipsec_spi_t spi; /* B. 32-bit SPI, assigned by dest. host */ -+# define SPI_PASS 256 /* magic values... */ -+# define SPI_DROP 257 /* ...for use... */ -+# define SPI_REJECT 258 /* ...with SA_INT */ -+# define SPI_HOLD 259 -+# define SPI_TRAP 260 -+# define SPI_TRAPSUBNET 261 -+ int proto; /* C. protocol */ -+# define SA_ESP 50 /* IPPROTO_ESP */ -+# define SA_AH 51 /* IPPROTO_AH */ -+# define SA_IPIP 4 /* IPPROTO_IPIP */ -+# define SA_COMP 108 /* IPPROTO_COMP */ -+# define SA_INT 61 /* IANA reserved for internal use */ -+} ip_said; -+ -+/* misc */ -+typedef const char *err_t; /* error message, or NULL for success */ -+struct prng { /* pseudo-random-number-generator guts */ -+ unsigned char sbox[256]; -+ int i, j; -+ unsigned long count; -+}; -+ -+ -+/* -+ * definitions for user space, taken from freeswan/ipsec_sa.h -+ */ -+typedef uint32_t IPsecSAref_t; -+ -+#define IPSEC_SA_REF_FIELD_WIDTH (8 * sizeof(IPsecSAref_t)) -+ -+#define IPsecSAref2NFmark(x) ((x) << (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH)) -+#define NFmark2IPsecSAref(x) ((x) >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH)) -+ -+#define IPSEC_SAREF_NULL (~((IPsecSAref_t)0)) -+ -+/* GCC magic for use in function definitions! */ -+#ifdef GCC_LINT -+# define PRINTF_LIKE(n) __attribute__ ((format(printf, n, n+1))) -+# define NEVER_RETURNS __attribute__ ((noreturn)) -+# define UNUSED __attribute__ ((unused)) -+# define BLANK_FORMAT " " /* GCC_LINT whines about empty formats */ -+#else -+# define PRINTF_LIKE(n) /* ignore */ -+# define NEVER_RETURNS /* ignore */ -+# define UNUSED /* ignore */ -+# define BLANK_FORMAT "" -+#endif -+ -+ -+ -+ -+ -+/* -+ * new IPv6-compatible functions -+ */ -+ -+/* text conversions */ -+err_t ttoul(const char *src, size_t srclen, int format, unsigned long *dst); -+size_t ultot(unsigned long src, int format, char *buf, size_t buflen); -+#define ULTOT_BUF (22+1) /* holds 64 bits in octal */ -+err_t ttoaddr(const char *src, size_t srclen, int af, ip_address *dst); -+err_t tnatoaddr(const char *src, size_t srclen, int af, ip_address *dst); -+size_t addrtot(const ip_address *src, int format, char *buf, size_t buflen); -+/* RFC 1886 old IPv6 reverse-lookup format is the bulkiest */ -+#define ADDRTOT_BUF (32*2 + 3 + 1 + 3 + 1 + 1) -+err_t ttosubnet(const char *src, size_t srclen, int af, ip_subnet *dst); -+size_t subnettot(const ip_subnet *src, int format, char *buf, size_t buflen); -+#define SUBNETTOT_BUF (ADDRTOT_BUF + 1 + 3) -+size_t subnetporttot(const ip_subnet *src, int format, char *buf, size_t buflen); -+#define SUBNETPROTOTOT_BUF (SUBNETTOTO_BUF + ULTOT_BUF) -+err_t ttosa(const char *src, size_t srclen, ip_said *dst); -+size_t satot(const ip_said *src, int format, char *bufptr, size_t buflen); -+#define SATOT_BUF (5 + ULTOA_BUF + 1 + ADDRTOT_BUF) -+err_t ttodata(const char *src, size_t srclen, int base, char *buf, -+ size_t buflen, size_t *needed); -+err_t ttodatav(const char *src, size_t srclen, int base, -+ char *buf, size_t buflen, size_t *needed, -+ char *errp, size_t errlen, unsigned int flags); -+#define TTODATAV_BUF 40 /* ttodatav's largest non-literal message */ -+#define TTODATAV_IGNORESPACE (1<<1) /* ignore spaces in base64 encodings*/ -+#define TTODATAV_SPACECOUNTS 0 /* do not ignore spaces in base64 */ -+ -+size_t datatot(const char *src, size_t srclen, int format, char *buf, -+ size_t buflen); -+size_t keyblobtoid(const unsigned char *src, size_t srclen, char *dst, -+ size_t dstlen); -+size_t splitkeytoid(const unsigned char *e, size_t elen, const unsigned char *m, -+ size_t mlen, char *dst, size_t dstlen); -+#define KEYID_BUF 10 /* up to 9 text digits plus NUL */ -+err_t ttoprotoport(char *src, size_t src_len, u_int8_t *proto, u_int16_t *port, -+ int *has_port_wildcard); -+ -+/* initializations */ -+void initsaid(const ip_address *addr, ipsec_spi_t spi, int proto, ip_said *dst); -+err_t loopbackaddr(int af, ip_address *dst); -+err_t unspecaddr(int af, ip_address *dst); -+err_t anyaddr(int af, ip_address *dst); -+err_t initaddr(const unsigned char *src, size_t srclen, int af, ip_address *dst); -+err_t initsubnet(const ip_address *addr, int maskbits, int clash, ip_subnet *dst); -+err_t addrtosubnet(const ip_address *addr, ip_subnet *dst); -+ -+/* misc. conversions and related */ -+err_t rangetosubnet(const ip_address *from, const ip_address *to, ip_subnet *dst); -+int addrtypeof(const ip_address *src); -+int subnettypeof(const ip_subnet *src); -+size_t addrlenof(const ip_address *src); -+size_t addrbytesptr(const ip_address *src, const unsigned char **dst); -+size_t addrbytesof(const ip_address *src, unsigned char *dst, size_t dstlen); -+int masktocount(const ip_address *src); -+void networkof(const ip_subnet *src, ip_address *dst); -+void maskof(const ip_subnet *src, ip_address *dst); -+ -+/* tests */ -+int sameaddr(const ip_address *a, const ip_address *b); -+int addrcmp(const ip_address *a, const ip_address *b); -+int samesubnet(const ip_subnet *a, const ip_subnet *b); -+int addrinsubnet(const ip_address *a, const ip_subnet *s); -+int subnetinsubnet(const ip_subnet *a, const ip_subnet *b); -+int subnetishost(const ip_subnet *s); -+int samesaid(const ip_said *a, const ip_said *b); -+int sameaddrtype(const ip_address *a, const ip_address *b); -+int samesubnettype(const ip_subnet *a, const ip_subnet *b); -+int isanyaddr(const ip_address *src); -+int isunspecaddr(const ip_address *src); -+int isloopbackaddr(const ip_address *src); -+ -+/* low-level grot */ -+int portof(const ip_address *src); -+void setportof(int port, ip_address *dst); -+struct sockaddr *sockaddrof(ip_address *src); -+size_t sockaddrlenof(const ip_address *src); -+ -+/* PRNG */ -+void prng_init(struct prng *prng, const unsigned char *key, size_t keylen); -+void prng_bytes(struct prng *prng, unsigned char *dst, size_t dstlen); -+unsigned long prng_count(struct prng *prng); -+void prng_final(struct prng *prng); -+ -+/* odds and ends */ -+const char *ipsec_version_code(void); -+const char *ipsec_version_string(void); -+const char **ipsec_copyright_notice(void); -+ -+const char *dns_string_rr(int rr, char *buf, int bufsize); -+const char *dns_string_datetime(time_t seconds, -+ char *buf, -+ int bufsize); -+ -+ -+/* -+ * old functions, to be deleted eventually -+ */ -+ -+/* unsigned long */ -+const char * /* NULL for success, else string literal */ -+atoul( -+ const char *src, -+ size_t srclen, /* 0 means strlen(src) */ -+ int base, /* 0 means figure it out */ -+ unsigned long *resultp -+); -+size_t /* space needed for full conversion */ -+ultoa( -+ unsigned long n, -+ int base, -+ char *dst, -+ size_t dstlen -+); -+#define ULTOA_BUF 21 /* just large enough for largest result, */ -+ /* assuming 64-bit unsigned long! */ -+ -+/* Internet addresses */ -+const char * /* NULL for success, else string literal */ -+atoaddr( -+ const char *src, -+ size_t srclen, /* 0 means strlen(src) */ -+ struct in_addr *addr -+); -+size_t /* space needed for full conversion */ -+addrtoa( -+ struct in_addr addr, -+ int format, /* character; 0 means default */ -+ char *dst, -+ size_t dstlen -+); -+#define ADDRTOA_BUF 16 /* just large enough for largest result */ -+ -+/* subnets */ -+const char * /* NULL for success, else string literal */ -+atosubnet( -+ const char *src, -+ size_t srclen, /* 0 means strlen(src) */ -+ struct in_addr *addr, -+ struct in_addr *mask -+); -+size_t /* space needed for full conversion */ -+subnettoa( -+ struct in_addr addr, -+ struct in_addr mask, -+ int format, /* character; 0 means default */ -+ char *dst, -+ size_t dstlen -+); -+#define SUBNETTOA_BUF 32 /* large enough for worst case result */ -+ -+/* ranges */ -+const char * /* NULL for success, else string literal */ -+atoasr( -+ const char *src, -+ size_t srclen, /* 0 means strlen(src) */ -+ char *type, /* 'a', 's', 'r' */ -+ struct in_addr *addrs /* two-element array */ -+); -+size_t /* space needed for full conversion */ -+rangetoa( -+ struct in_addr *addrs, /* two-element array */ -+ int format, /* character; 0 means default */ -+ char *dst, -+ size_t dstlen -+); -+#define RANGETOA_BUF 34 /* large enough for worst case result */ -+ -+/* data types for SA conversion functions */ -+ -+/* generic data, e.g. keys */ -+const char * /* NULL for success, else string literal */ -+atobytes( -+ const char *src, -+ size_t srclen, /* 0 means strlen(src) */ -+ char *dst, -+ size_t dstlen, -+ size_t *lenp /* NULL means don't bother telling me */ -+); -+size_t /* 0 failure, else true size */ -+bytestoa( -+ const char *src, -+ size_t srclen, -+ int format, /* character; 0 means default */ -+ char *dst, -+ size_t dstlen -+); -+ -+/* old versions of generic-data functions; deprecated */ -+size_t /* 0 failure, else true size */ -+atodata( -+ const char *src, -+ size_t srclen, /* 0 means strlen(src) */ -+ char *dst, -+ size_t dstlen -+); -+size_t /* 0 failure, else true size */ -+datatoa( -+ const char *src, -+ size_t srclen, -+ int format, /* character; 0 means default */ -+ char *dst, -+ size_t dstlen -+); -+ -+/* part extraction and special addresses */ -+struct in_addr -+subnetof( -+ struct in_addr addr, -+ struct in_addr mask -+); -+struct in_addr -+hostof( -+ struct in_addr addr, -+ struct in_addr mask -+); -+struct in_addr -+broadcastof( -+ struct in_addr addr, -+ struct in_addr mask -+); -+ -+/* mask handling */ -+int -+goodmask( -+ struct in_addr mask -+); -+int -+masktobits( -+ struct in_addr mask -+); -+struct in_addr -+bitstomask( -+ int n -+); -+ -+ -+ -+/* -+ * general utilities -+ */ -+ -+#ifndef __KERNEL__ -+/* option pickup from files (userland only because of use of FILE) */ -+const char *optionsfrom(const char *filename, int *argcp, char ***argvp, -+ int optind, FILE *errorreport); -+ -+/* sanitize a string */ -+extern size_t sanitize_string(char *buf, size_t size); -+ -+#endif -+ -+ -+/* -+ * ENUM of klips debugging values. Not currently used in klips. -+ * debug flag is actually 32 -bits, but only one bit is ever used, -+ * so we can actually pack it all into a single 32-bit word. -+ */ -+enum klips_debug_flags { -+ KDF_VERBOSE = 0, -+ KDF_XMIT = 1, -+ KDF_NETLINK = 2, /* obsolete */ -+ KDF_XFORM = 3, -+ KDF_EROUTE = 4, -+ KDF_SPI = 5, -+ KDF_RADIJ = 6, -+ KDF_ESP = 7, -+ KDF_AH = 8, /* obsolete */ -+ KDF_RCV = 9, -+ KDF_TUNNEL = 10, -+ KDF_PFKEY = 11, -+ KDF_COMP = 12 -+}; -+ -+ -+/* -+ * Debugging levels for pfkey_lib_debug -+ */ -+#define PF_KEY_DEBUG_PARSE_NONE 0 -+#define PF_KEY_DEBUG_PARSE_PROBLEM 1 -+#define PF_KEY_DEBUG_PARSE_STRUCT 2 -+#define PF_KEY_DEBUG_PARSE_FLOW 4 -+#define PF_KEY_DEBUG_BUILD 8 -+#define PF_KEY_DEBUG_PARSE_MAX 15 -+ -+extern unsigned int pfkey_lib_debug; /* bits selecting what to report */ -+ -+/* -+ * pluto and lwdnsq need to know the maximum size of the commands to, -+ * and replies from lwdnsq. -+ */ -+ -+#define LWDNSQ_CMDBUF_LEN 1024 -+#define LWDNSQ_RESULT_LEN_MAX 4096 -+ -+ -+/* syntax for passthrough SA */ -+#ifndef PASSTHROUGHNAME -+#define PASSTHROUGHNAME "%passthrough" -+#define PASSTHROUGH4NAME "%passthrough4" -+#define PASSTHROUGH6NAME "%passthrough6" -+#define PASSTHROUGHIS "tun0@0.0.0.0" -+#define PASSTHROUGH4IS "tun0@0.0.0.0" -+#define PASSTHROUGH6IS "tun0@::" -+#define PASSTHROUGHTYPE "tun" -+#define PASSTHROUGHSPI 0 -+#define PASSTHROUGHDST 0 -+#endif -+ -+ -+ -+#endif /* _OPENSWAN_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipcomp.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,61 @@ -+/* -+ * IPCOMP zlib interface code. -+ * Copyright (C) 2000 Svenning Soerensen -+ * Copyright (C) 2000, 2001 Richard Guy Briggs -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ -+ RCSID $Id$ -+ -+ */ -+ -+/* SSS */ -+ -+#ifndef _IPCOMP_H -+#define _IPCOMP_H -+ -+/* Prefix all global deflate symbols with "ipcomp_" to avoid collisions with ppp_deflate & ext2comp */ -+#ifndef IPCOMP_PREFIX -+#define IPCOMP_PREFIX -+#endif /* IPCOMP_PREFIX */ -+ -+#ifndef IPPROTO_COMP -+#define IPPROTO_COMP 108 -+#endif /* IPPROTO_COMP */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int sysctl_ipsec_debug_ipcomp; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+struct ipcomphdr { /* IPCOMP header */ -+ __u8 ipcomp_nh; /* Next header (protocol) */ -+ __u8 ipcomp_flags; /* Reserved, must be 0 */ -+ __u16 ipcomp_cpi; /* Compression Parameter Index */ -+}; -+ -+extern struct inet_protocol comp_protocol; -+extern int sysctl_ipsec_debug_ipcomp; -+ -+#define IPCOMP_UNCOMPRESSABLE 0x000000001 -+#define IPCOMP_COMPRESSIONERROR 0x000000002 -+#define IPCOMP_PARMERROR 0x000000004 -+#define IPCOMP_DECOMPRESSIONERROR 0x000000008 -+ -+#define IPCOMP_ADAPT_INITIAL_TRIES 8 -+#define IPCOMP_ADAPT_INITIAL_SKIP 4 -+#define IPCOMP_ADAPT_SUBSEQ_TRIES 2 -+#define IPCOMP_ADAPT_SUBSEQ_SKIP 8 -+ -+/* Function prototypes */ -+struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); -+struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); -+ -+#endif /* _IPCOMP_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_ah.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,190 @@ -+/* -+ * Authentication Header declarations -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#include "ipsec_md5h.h" -+#include "ipsec_sha1.h" -+ -+#ifndef IPPROTO_AH -+#define IPPROTO_AH 51 -+#endif /* IPPROTO_AH */ -+ -+#include "ipsec_auth.h" -+ -+#ifdef __KERNEL__ -+ -+extern struct inet_protocol ah_protocol; -+ -+struct options; -+ -+struct ahhdr /* Generic AH header */ -+{ -+ __u8 ah_nh; /* Next header (protocol) */ -+ __u8 ah_hl; /* AH length, in 32-bit words */ -+ __u16 ah_rv; /* reserved, must be 0 */ -+ __u32 ah_spi; /* Security Parameters Index */ -+ __u32 ah_rpl; /* Replay prevention */ -+ __u8 ah_data[AHHMAC_HASHLEN];/* Authentication hash */ -+}; -+#define AH_BASIC_LEN 8 /* basic AH header is 8 bytes, nh,hl,rv,spi -+ * and the ah_hl, says how many bytes after that -+ * to cover. */ -+ -+extern struct xform_functions ah_xform_funcs[]; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int debug_ah; -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif /* __KERNEL__ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.23 2004/04/05 19:55:04 mcr -+ * Moved from linux/include/freeswan/ipsec_ah.h,v -+ * -+ * Revision 1.22 2004/04/05 19:41:05 mcr -+ * merged alg-branch code. -+ * -+ * Revision 1.21 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.22 2003/12/11 20:14:58 mcr -+ * refactored the xmit code, to move all encapsulation -+ * code into protocol functions. Note that all functions -+ * are essentially done by a single function, which is probably -+ * wrong. -+ * the rcv_functions structures are renamed xform_functions. -+ * -+ * Revision 1.21 2003/12/06 21:21:19 mcr -+ * split up receive path into per-transform files, for -+ * easier later removal. -+ * -+ * Revision 1.20.8.1 2003/12/22 15:25:52 jjo -+ * Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.20 2003/02/06 02:21:34 rgb -+ * -+ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h . -+ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr". -+ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code. -+ * -+ * Revision 1.19 2002/09/16 21:19:13 mcr -+ * fixes for west-ah-icmp-01 - length of AH header must be -+ * calculated properly, and next_header field properly copied. -+ * -+ * Revision 1.18 2002/05/14 02:37:02 rgb -+ * Change reference from _TDB to _IPSA. -+ * -+ * Revision 1.17 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_ah.h,v -+ * -+ * Revision 1.16 2002/02/20 01:27:06 rgb -+ * Ditched a pile of structs only used by the old Netlink interface. -+ * -+ * Revision 1.15 2001/12/11 02:35:57 rgb -+ * Change "struct net_device" to "struct device" for 2.2 compatibility. -+ * -+ * Revision 1.14 2001/11/26 09:23:47 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.13.2.1 2001/09/25 02:18:24 mcr -+ * replace "struct device" with "struct netdevice" -+ * -+ * Revision 1.13 2001/06/14 19:35:08 rgb -+ * Update copyright date. -+ * -+ * Revision 1.12 2000/09/12 03:21:20 rgb -+ * Cleared out unused htonq. -+ * -+ * Revision 1.11 2000/09/08 19:12:55 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.10 2000/01/21 06:13:10 rgb -+ * Tidied up spacing. -+ * Added macros for HMAC padding magic numbers.(kravietz) -+ * -+ * Revision 1.9 1999/12/07 18:16:23 rgb -+ * Fixed comments at end of #endif lines. -+ * -+ * Revision 1.8 1999/04/11 00:28:56 henry -+ * GPL boilerplate -+ * -+ * Revision 1.7 1999/04/06 04:54:25 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.6 1999/01/26 02:06:01 rgb -+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro. -+ * -+ * Revision 1.5 1999/01/22 06:17:49 rgb -+ * Updated macro comments. -+ * Added context types to support algorithm switch code. -+ * 64-bit clean-up -- converting 'u long long' to __u64. -+ * -+ * Revision 1.4 1998/07/14 15:54:56 rgb -+ * Add #ifdef __KERNEL__ to protect kernel-only structures. -+ * -+ * Revision 1.3 1998/06/30 18:05:16 rgb -+ * Comment out references to htonq. -+ * -+ * Revision 1.2 1998/06/25 19:33:46 rgb -+ * Add prototype for protocol receive function. -+ * Rearrange for more logical layout. -+ * -+ * Revision 1.1 1998/06/18 21:27:43 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.4 1998/05/18 22:28:43 rgb -+ * Disable key printing facilities from /proc/net/ipsec_*. -+ * -+ * Revision 1.3 1998/04/21 21:29:07 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.2 1998/04/12 22:03:17 rgb -+ * Updated ESP-3DES-HMAC-MD5-96, -+ * ESP-DES-HMAC-MD5-96, -+ * AH-HMAC-MD5-96, -+ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository -+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts. -+ * -+ * Fixed eroute references in /proc/net/ipsec*. -+ * -+ * Started to patch module unloading memory leaks in ipsec_netlink and -+ * radij tree unloading. -+ * -+ * Revision 1.1 1998/04/09 03:05:55 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:02 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * Added definitions for new AH transforms. -+ * -+ * Revision 0.3 1996/11/20 14:35:48 ji -+ * Minor Cleanup. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_alg.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,260 @@ -+/* -+ * Modular extensions service and registration functions interface -+ * -+ * Author: JuanJo Ciarlante -+ * -+ * ipsec_alg.h,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp -+ * -+ */ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ */ -+#ifndef IPSEC_ALG_H -+#define IPSEC_ALG_H -+ -+/* -+ * gcc >= 3.2 has removed __FUNCTION__, replaced by C99 __func__ -+ * *BUT* its a compiler variable. -+ */ -+#if (__GNUC__ >= 3) -+#ifndef __FUNCTION__ -+#define __FUNCTION__ __func__ -+#endif -+#endif -+ -+/* Version 0.8.1-0 */ -+#define IPSEC_ALG_VERSION 0x00080100 -+ -+#include -+#include -+#include -+/* -+ * The following structs are used via pointers in ipsec_alg object to -+ * avoid ipsec_alg.h coupling with freeswan headers, thus simplifying -+ * module development -+ */ -+struct ipsec_sa; -+struct esp; -+ -+/************************************** -+ * -+ * Main registration object -+ * -+ *************************************/ -+#define IPSEC_ALG_VERSION_QUAD(v) \ -+ (v>>24),((v>>16)&0xff),((v>>8)&0xff),(v&0xff) -+/* -+ * Main ipsec_alg objects: "OOPrograming wannabe" -+ * Hierachy (carefully handled with _minimal_ cast'ing): -+ * -+ * ipsec_alg+ -+ * +->ipsec_alg_enc (ixt_alg_type=SADB_EXT_SUPPORTED_ENCRYPT) -+ * +->ipsec_alg_auth (ixt_alg_type=SADB_EXT_SUPPORTED_AUTH) -+ */ -+ -+/*************************************************************** -+ * -+ * INTERFACE object: struct ipsec_alg -+ * -+ ***************************************************************/ -+ -+/* -+ * common part for every struct ipsec_alg_* -+ * (sortof poor's man OOP) -+ */ -+#define IPSEC_ALG_STRUCT_COMMON \ -+ unsigned ixt_version; /* only allow this version (or 'near')*/ \ -+ struct list_head ixt_list; /* dlinked list */ \ -+ struct module *ixt_module; /* THIS_MODULE */ \ -+ unsigned ixt_state; /* state flags */ \ -+ atomic_t ixt_refcnt; /* ref. count when pointed from ipsec_sa */ \ -+ char ixt_name[16]; /* descriptive short name, eg. "3des" */ \ -+ void *ixt_data; /* private for algo implementation */ \ -+ uint8_t ixt_blocksize; /* blocksize in bytes */ \ -+ \ -+ /* THIS IS A COPY of struct supported (lib/pfkey.h) \ -+ * please keep in sync until we migrate 'supported' stuff \ -+ * to ipsec_alg \ -+ */ \ -+ uint16_t ixt_alg_type; /* correspond to IPSEC_ALG_{ENCRYPT,AUTH} */ \ -+ uint8_t ixt_alg_id; /* enc. alg. number, eg. ESP_3DES */ \ -+ uint8_t ixt_ivlen; /* ivlen in bits, expected to be multiple of 8! */ \ -+ uint16_t ixt_keyminbits;/* min. keybits (of entropy) */ \ -+ uint16_t ixt_keymaxbits;/* max. keybits (of entropy) */ -+ -+#define ixt_support ixt_alg_type -+ -+#define IPSEC_ALG_ST_SUPP 0x01 -+#define IPSEC_ALG_ST_REGISTERED 0x02 -+#define IPSEC_ALG_ST_EXCL 0x04 -+struct ipsec_alg { -+ IPSEC_ALG_STRUCT_COMMON -+}; -+/* -+ * Note the const in cbc_encrypt IV arg: -+ * some ciphers like to toast passed IV (eg. 3DES): make a local IV copy -+ */ -+struct ipsec_alg_enc { -+ IPSEC_ALG_STRUCT_COMMON -+ unsigned ixt_e_keylen; /* raw key length in bytes */ -+ unsigned ixt_e_ctx_size; /* sa_p->key_e_size */ -+ int (*ixt_e_set_key)(struct ipsec_alg_enc *alg, __u8 *key_e, const __u8 *key, size_t keysize); -+ __u8 *(*ixt_e_new_key)(struct ipsec_alg_enc *alg, const __u8 *key, size_t keysize); -+ void (*ixt_e_destroy_key)(struct ipsec_alg_enc *alg, __u8 *key_e); -+ int (*ixt_e_cbc_encrypt)(struct ipsec_alg_enc *alg, __u8 *key_e, __u8 *in, int ilen, const __u8 *iv, int encrypt); -+}; -+struct ipsec_alg_auth { -+ IPSEC_ALG_STRUCT_COMMON -+ unsigned ixt_a_keylen; /* raw key length in bytes */ -+ unsigned ixt_a_ctx_size; /* sa_p->key_a_size */ -+ unsigned ixt_a_authlen; /* 'natural' auth. hash len (bytes) */ -+ int (*ixt_a_hmac_set_key)(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *key, int keylen); -+ int (*ixt_a_hmac_hash)(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *dat, int len, __u8 *hash, int hashlen); -+}; -+/* -+ * These are _copies_ of SADB_EXT_SUPPORTED_{AUTH,ENCRYPT}, -+ * to avoid header coupling for true constants -+ * about headers ... "cp is your friend" --Linus -+ */ -+#define IPSEC_ALG_TYPE_AUTH 14 -+#define IPSEC_ALG_TYPE_ENCRYPT 15 -+ -+/*************************************************************** -+ * -+ * INTERFACE for module loading,testing, and unloading -+ * -+ ***************************************************************/ -+/* - registration calls */ -+int register_ipsec_alg(struct ipsec_alg *); -+int unregister_ipsec_alg(struct ipsec_alg *); -+/* - optional (simple test) for algos */ -+int ipsec_alg_test(unsigned alg_type, unsigned alg_id, int testparm); -+/* inline wrappers (usefull for type validation */ -+static inline int register_ipsec_alg_enc(struct ipsec_alg_enc *ixt) { -+ return register_ipsec_alg((struct ipsec_alg*)ixt); -+} -+static inline int unregister_ipsec_alg_enc(struct ipsec_alg_enc *ixt) { -+ return unregister_ipsec_alg((struct ipsec_alg*)ixt); -+} -+static inline int register_ipsec_alg_auth(struct ipsec_alg_auth *ixt) { -+ return register_ipsec_alg((struct ipsec_alg*)ixt); -+} -+static inline int unregister_ipsec_alg_auth(struct ipsec_alg_auth *ixt) { -+ return unregister_ipsec_alg((struct ipsec_alg*)ixt); -+} -+ -+/***************************************************************** -+ * -+ * INTERFACE for ENC services: key creation, encrypt function -+ * -+ *****************************************************************/ -+ -+#define IPSEC_ALG_ENCRYPT 1 -+#define IPSEC_ALG_DECRYPT 0 -+ -+/* encryption key context creation function */ -+int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p); -+/* -+ * ipsec_alg_esp_encrypt(): encrypt ilen bytes in idat returns -+ * 0 or ERR<0 -+ */ -+int ipsec_alg_esp_encrypt(struct ipsec_sa *sa_p, __u8 *idat, int ilen, const __u8 *iv, int action); -+ -+/*************************************************************** -+ * -+ * INTERFACE for AUTH services: key creation, hash functions -+ * -+ ***************************************************************/ -+int ipsec_alg_auth_key_create(struct ipsec_sa *sa_p); -+int ipsec_alg_sa_esp_hash(const struct ipsec_sa *sa_p, const __u8 *espp, int len, __u8 *hash, int hashlen) ; -+#define ipsec_alg_sa_esp_update(c,k,l) ipsec_alg_sa_esp_hash(c,k,l,NULL,0) -+ -+/* only called from ipsec_init.c */ -+int ipsec_alg_init(void); -+ -+/* algo module glue for static algos */ -+void ipsec_alg_static_init(void); -+typedef int (*ipsec_alg_init_func_t) (void); -+ -+/********************************************** -+ * -+ * INTERFACE for ipsec_sa init and wipe -+ * -+ **********************************************/ -+ -+/* returns true if ipsec_sa has ipsec_alg obj attached */ -+/* -+ * Initializes ipsec_sa's ipsec_alg object, using already loaded -+ * proto, authalg, encalg.; links ipsec_alg objects (enc, auth) -+ */ -+int ipsec_alg_sa_init(struct ipsec_sa *sa_p); -+/* -+ * Destroys ipsec_sa's ipsec_alg object -+ * unlinking ipsec_alg objects -+ */ -+int ipsec_alg_sa_wipe(struct ipsec_sa *sa_p); -+ -+#define IPSEC_ALG_MODULE_INIT_MOD( func_name ) \ -+ static int func_name(void); \ -+ module_init(func_name); \ -+ static int __init func_name(void) -+#define IPSEC_ALG_MODULE_EXIT_MOD( func_name ) \ -+ static void func_name(void); \ -+ module_exit(func_name); \ -+ static void __exit func_name(void) -+ -+#define IPSEC_ALG_MODULE_INIT_STATIC( func_name ) \ -+ extern int func_name(void); \ -+ int func_name(void) -+#define IPSEC_ALG_MODULE_EXIT_STATIC( func_name ) \ -+ extern void func_name(void); \ -+ void func_name(void) -+ -+/********************************************** -+ * -+ * 2.2 backport for some 2.4 useful module stuff -+ * -+ **********************************************/ -+#ifdef MODULE -+#ifndef THIS_MODULE -+#define THIS_MODULE (&__this_module) -+#endif -+#ifndef module_init -+typedef int (*__init_module_func_t)(void); -+typedef void (*__cleanup_module_func_t)(void); -+ -+#define module_init(x) \ -+ int init_module(void) __attribute__((alias(#x))); \ -+ static inline __init_module_func_t __init_module_inline(void) \ -+ { return x; } -+#define module_exit(x) \ -+ void cleanup_module(void) __attribute__((alias(#x))); \ -+ static inline __cleanup_module_func_t __cleanup_module_inline(void) \ -+ { return x; } -+#endif -+#define IPSEC_ALG_MODULE_INIT( func_name ) IPSEC_ALG_MODULE_INIT_MOD( func_name ) -+#define IPSEC_ALG_MODULE_EXIT( func_name ) IPSEC_ALG_MODULE_EXIT_MOD( func_name ) -+ -+#else /* not MODULE */ -+#ifndef THIS_MODULE -+#define THIS_MODULE NULL -+#endif -+/* -+ * I only want module_init() magic -+ * when algo.c file *is THE MODULE*, in all other -+ * cases, initialization is called explicitely from ipsec_alg_init() -+ */ -+#define IPSEC_ALG_MODULE_INIT( func_name ) IPSEC_ALG_MODULE_INIT_STATIC(func_name) -+#define IPSEC_ALG_MODULE_EXIT( func_name ) IPSEC_ALG_MODULE_EXIT_STATIC(func_name) -+#endif -+ -+#endif /* IPSEC_ALG_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_auth.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,100 @@ -+/* -+ * Authentication Header declarations -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#include "ipsec_md5h.h" -+#include "ipsec_sha1.h" -+ -+#ifndef IPSEC_AUTH_H -+#define IPSEC_AUTH_H -+ -+#define AH_FLENGTH 12 /* size of fixed part */ -+#define AHMD5_KMAX 64 /* MD5 max 512 bits key */ -+#define AHMD5_AMAX 12 /* MD5 96 bits of authenticator */ -+ -+#define AHMD596_KLEN 16 /* MD5 128 bits key */ -+#define AHSHA196_KLEN 20 /* SHA1 160 bits key */ -+ -+#define AHMD596_ALEN 16 /* MD5 128 bits authentication length */ -+#define AHSHA196_ALEN 20 /* SHA1 160 bits authentication length */ -+ -+#define AHMD596_BLKLEN 64 /* MD5 block length */ -+#define AHSHA196_BLKLEN 64 /* SHA1 block length */ -+#define AHSHA2_256_BLKLEN 64 /* SHA2-256 block length */ -+#define AHSHA2_384_BLKLEN 128 /* SHA2-384 block length (?) */ -+#define AHSHA2_512_BLKLEN 128 /* SHA2-512 block length */ -+ -+#define AH_BLKLEN_MAX 128 /* keep up to date! */ -+ -+ -+#define AH_AMAX AHSHA196_ALEN /* keep up to date! */ -+#define AHHMAC_HASHLEN 12 /* authenticator length of 96bits */ -+#define AHHMAC_RPLLEN 4 /* 32 bit replay counter */ -+ -+#define DB_AH_PKTRX 0x0001 -+#define DB_AH_PKTRX2 0x0002 -+#define DB_AH_DMP 0x0004 -+#define DB_AH_IPSA 0x0010 -+#define DB_AH_XF 0x0020 -+#define DB_AH_INAU 0x0040 -+#define DB_AH_REPLAY 0x0100 -+ -+#ifdef __KERNEL__ -+ -+/* General HMAC algorithm is described in RFC 2104 */ -+ -+#define HMAC_IPAD 0x36 -+#define HMAC_OPAD 0x5C -+ -+struct md5_ctx { -+ MD5_CTX ictx; /* context after H(K XOR ipad) */ -+ MD5_CTX octx; /* context after H(K XOR opad) */ -+}; -+ -+struct sha1_ctx { -+ SHA1_CTX ictx; /* context after H(K XOR ipad) */ -+ SHA1_CTX octx; /* context after H(K XOR opad) */ -+}; -+ -+struct auth_alg { -+ void (*init)(void *ctx); -+ void (*update)(void *ctx, unsigned char *bytes, __u32 len); -+ void (*final)(unsigned char *hash, void *ctx); -+ int hashlen; -+}; -+ -+struct options; -+ -+#endif /* __KERNEL__ */ -+#endif /* IPSEC_AUTH_H */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.3 2004/04/06 02:49:08 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.2 2004/04/05 19:55:04 mcr -+ * Moved from linux/include/freeswan/ipsec_auth.h,v -+ * -+ * Revision 1.1 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.1 2003/12/06 21:21:19 mcr -+ * split up receive path into per-transform files, for -+ * easier later removal. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_encap.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,149 @@ -+/* -+ * declarations relevant to encapsulation-like operations -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef _IPSEC_ENCAP_H_ -+ -+#define SENT_IP4 16 /* data is two struct in_addr + proto + ports*/ -+ /* (2 * sizeof(struct in_addr)) */ -+ /* sizeof(struct sockaddr_encap) -+ - offsetof(struct sockaddr_encap, Sen.Sip4.Src) */ -+ -+struct sockaddr_encap -+{ -+ __u8 sen_len; /* length */ -+ __u8 sen_family; /* AF_ENCAP */ -+ __u16 sen_type; /* see SENT_* */ -+ union -+ { -+ struct /* SENT_IP4 */ -+ { -+ struct in_addr Src; -+ struct in_addr Dst; -+ __u8 Proto; -+ __u16 Sport; -+ __u16 Dport; -+ } Sip4; -+ } Sen; -+}; -+ -+#define sen_ip_src Sen.Sip4.Src -+#define sen_ip_dst Sen.Sip4.Dst -+#define sen_proto Sen.Sip4.Proto -+#define sen_sport Sen.Sip4.Sport -+#define sen_dport Sen.Sip4.Dport -+ -+#ifndef AF_ENCAP -+#define AF_ENCAP 26 -+#endif /* AF_ENCAP */ -+ -+#define _IPSEC_ENCAP_H_ -+#endif /* _IPSEC_ENCAP_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.19 2004/04/05 19:55:04 mcr -+ * Moved from linux/include/freeswan/ipsec_encap.h,v -+ * -+ * Revision 1.18 2003/10/31 02:27:05 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.17.30.1 2003/09/21 13:59:38 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.17 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_encap.h,v -+ * -+ * Revision 1.16 2001/11/26 09:23:47 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.15.2.1 2001/09/25 02:18:54 mcr -+ * struct eroute moved to ipsec_eroute.h -+ * -+ * Revision 1.15 2001/09/14 16:58:36 rgb -+ * Added support for storing the first and last packets through a HOLD. -+ * -+ * Revision 1.14 2001/09/08 21:13:31 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.13 2001/06/14 19:35:08 rgb -+ * Update copyright date. -+ * -+ * Revision 1.12 2001/05/27 06:12:10 rgb -+ * Added structures for pid, packet count and last access time to eroute. -+ * Added packet count to beginning of /proc/net/ipsec_eroute. -+ * -+ * Revision 1.11 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.10 2000/03/22 16:15:36 rgb -+ * Fixed renaming of dev_get (MB). -+ * -+ * Revision 1.9 2000/01/21 06:13:26 rgb -+ * Added a macro for AF_ENCAP -+ * -+ * Revision 1.8 1999/12/31 14:56:55 rgb -+ * MB fix for 2.3 dev-use-count. -+ * -+ * Revision 1.7 1999/11/18 04:09:18 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.6 1999/09/24 00:34:13 rgb -+ * Add Marc Boucher's support for 2.3.xx+. -+ * -+ * Revision 1.5 1999/04/11 00:28:57 henry -+ * GPL boilerplate -+ * -+ * Revision 1.4 1999/04/06 04:54:25 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.3 1998/10/19 14:44:28 rgb -+ * Added inclusion of freeswan.h. -+ * sa_id structure implemented and used: now includes protocol. -+ * -+ * Revision 1.2 1998/07/14 18:19:33 rgb -+ * Added #ifdef __KERNEL__ directives to restrict scope of header. -+ * -+ * Revision 1.1 1998/06/18 21:27:44 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.2 1998/04/21 21:29:10 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.1 1998/04/09 03:05:58 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:02 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * Minor cosmetic changes. -+ * -+ * Revision 0.3 1996/11/20 14:35:48 ji -+ * Minor Cleanup. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_eroute.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,112 @@ -+/* -+ * @(#) declarations of eroute structures -+ * -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs -+ * Copyright (C) 2001 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ * derived from ipsec_encap.h 1.15 on 2001/9/18 by mcr. -+ * -+ */ -+ -+#ifndef _IPSEC_EROUTE_H_ -+ -+#include "radij.h" -+#include "ipsec_encap.h" -+#include "ipsec_radij.h" -+ -+/* -+ * The "type" is really part of the address as far as the routing -+ * system is concerned. By using only one bit in the type field -+ * for each type, we sort-of make sure that different types of -+ * encapsulation addresses won't be matched against the wrong type. -+ */ -+ -+/* -+ * An entry in the radix tree -+ */ -+ -+struct rjtentry -+{ -+ struct radij_node rd_nodes[2]; /* tree glue, and other values */ -+#define rd_key(r) ((struct sockaddr_encap *)((r)->rd_nodes->rj_key)) -+#define rd_mask(r) ((struct sockaddr_encap *)((r)->rd_nodes->rj_mask)) -+ short rd_flags; -+ short rd_count; -+}; -+ -+struct ident -+{ -+ __u16 type; /* identity type */ -+ __u64 id; /* identity id */ -+ __u8 len; /* identity len */ -+ caddr_t data; /* identity data */ -+}; -+ -+/* -+ * An encapsulation route consists of a pointer to a -+ * radix tree entry and a SAID (a destination_address/SPI/protocol triple). -+ */ -+ -+struct eroute -+{ -+ struct rjtentry er_rjt; -+ ip_said er_said; -+ uint32_t er_pid; -+ uint32_t er_count; -+ uint64_t er_lasttime; -+ struct sockaddr_encap er_eaddr; /* MCR get rid of _encap, it is silly*/ -+ struct sockaddr_encap er_emask; -+ struct ident er_ident_s; -+ struct ident er_ident_d; -+ struct sk_buff* er_first; -+ struct sk_buff* er_last; -+}; -+ -+#define er_dst er_said.dst -+#define er_spi er_said.spi -+ -+#define _IPSEC_EROUTE_H_ -+#endif /* _IPSEC_EROUTE_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.5 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_eroute.h,v -+ * -+ * Revision 1.4 2003/10/31 02:27:05 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.3.30.2 2003/10/29 01:10:19 mcr -+ * elimited "struct sa_id" -+ * -+ * Revision 1.3.30.1 2003/09/21 13:59:38 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.3 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_eroute.h,v -+ * -+ * Revision 1.2 2001/11/26 09:16:13 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:18:54 mcr -+ * struct eroute moved to ipsec_eroute.h -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_errs.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,53 @@ -+/* -+ * @(#) definition of ipsec_errs structure -+ * -+ * Copyright (C) 2001 Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ */ -+ -+/* -+ * This file describes the errors/statistics that FreeSWAN collects. -+ * -+ */ -+ -+struct ipsec_errs { -+ __u32 ips_alg_errs; /* number of algorithm errors */ -+ __u32 ips_auth_errs; /* # of authentication errors */ -+ __u32 ips_encsize_errs; /* # of encryption size errors*/ -+ __u32 ips_encpad_errs; /* # of encryption pad errors*/ -+ __u32 ips_replaywin_errs; /* # of pkt sequence errors */ -+}; -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.4 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_errs.h,v -+ * -+ * Revision 1.3 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_errs.h,v -+ * -+ * Revision 1.2 2001/11/26 09:16:13 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:25:57 mcr -+ * lifetime structure created and common functions created. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_esp.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,147 @@ -+/* -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#include "openswan/ipsec_md5h.h" -+#include "openswan/ipsec_sha1.h" -+ -+#include "crypto/des.h" -+ -+#ifndef IPPROTO_ESP -+#define IPPROTO_ESP 50 -+#endif /* IPPROTO_ESP */ -+ -+#define ESP_HEADER_LEN 8 /* 64 bits header (spi+rpl)*/ -+ -+#define EMT_ESPDESCBC_ULEN 20 /* coming from user mode */ -+#define EMT_ESPDES_KMAX 64 /* 512 bit secret key enough? */ -+#define EMT_ESPDES_KEY_SZ 8 /* 56 bit secret key with parity = 64 bits */ -+#define EMT_ESP3DES_KEY_SZ 24 /* 168 bit secret key with parity = 192 bits */ -+#define EMT_ESPDES_IV_SZ 8 /* IV size */ -+#define ESP_DESCBC_BLKLEN 8 /* DES-CBC block size */ -+ -+#define ESP_IV_MAXSZ 16 /* This is _critical_ */ -+#define ESP_IV_MAXSZ_INT (ESP_IV_MAXSZ/sizeof(int)) -+ -+#define DB_ES_PKTRX 0x0001 -+#define DB_ES_PKTRX2 0x0002 -+#define DB_ES_IPSA 0x0010 -+#define DB_ES_XF 0x0020 -+#define DB_ES_IPAD 0x0040 -+#define DB_ES_INAU 0x0080 -+#define DB_ES_OINFO 0x0100 -+#define DB_ES_OINFO2 0x0200 -+#define DB_ES_OH 0x0400 -+#define DB_ES_REPLAY 0x0800 -+ -+#ifdef __KERNEL__ -+struct des_eks { -+ des_key_schedule ks; -+}; -+ -+extern struct inet_protocol esp_protocol; -+ -+struct options; -+ -+struct esphdr -+{ -+ __u32 esp_spi; /* Security Parameters Index */ -+ __u32 esp_rpl; /* Replay counter */ -+ __u8 esp_iv[8]; /* iv */ -+}; -+ -+extern struct xform_functions esp_xform_funcs[]; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int debug_esp; -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif /* __KERNEL__ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.25 2004/04/06 02:49:08 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.24 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_esp.h,v -+ * -+ * Revision 1.23 2004/04/05 19:41:05 mcr -+ * merged alg-branch code. -+ * -+ * Revision 1.22 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.23 2003/12/11 20:14:58 mcr -+ * refactored the xmit code, to move all encapsulation -+ * code into protocol functions. Note that all functions -+ * are essentially done by a single function, which is probably -+ * wrong. -+ * the rcv_functions structures are renamed xform_functions. -+ * -+ * Revision 1.22 2003/12/06 21:21:19 mcr -+ * split up receive path into per-transform files, for -+ * easier later removal. -+ * -+ * Revision 1.21.8.1 2003/12/22 15:25:52 jjo -+ * Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.21 2003/02/06 02:21:34 rgb -+ * -+ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h . -+ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr". -+ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code. -+ * -+ * Revision 1.20 2002/05/14 02:37:02 rgb -+ * Change reference from _TDB to _IPSA. -+ * -+ * Revision 1.19 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.18 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_esp.h,v -+ * -+ * Revision 1.17 2002/02/20 01:27:07 rgb -+ * Ditched a pile of structs only used by the old Netlink interface. -+ * -+ * Revision 1.16 2001/12/11 02:35:57 rgb -+ * Change "struct net_device" to "struct device" for 2.2 compatibility. -+ * -+ * Revision 1.15 2001/11/26 09:23:48 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.14.2.3 2001/10/23 04:16:42 mcr -+ * get definition of des_key_schedule from des.h -+ * -+ * Revision 1.14.2.2 2001/10/22 20:33:13 mcr -+ * use "des_key_schedule" structure instead of cooking our own. -+ * -+ * Revision 1.14.2.1 2001/09/25 02:18:25 mcr -+ * replace "struct device" with "struct netdevice" -+ * -+ * Revision 1.14 2001/06/14 19:35:08 rgb -+ * Update copyright date. -+ * -+ * Revision 1.13 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.12 2000/08/01 14:51:50 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.11 2000/01/10 16:36:20 rgb -+ * Ditch last of EME option flags, including initiator. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_ipcomp.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,91 @@ -+/* -+ * IP compression header declations -+ * -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef IPSEC_IPCOMP_H -+#define IPSEC_IPCOMP_H -+ -+#include "openswan/ipsec_auth.h" -+ -+/* Prefix all global deflate symbols with "ipcomp_" to avoid collisions with ppp_deflate & ext2comp */ -+#ifndef IPCOMP_PREFIX -+#define IPCOMP_PREFIX -+#endif /* IPCOMP_PREFIX */ -+ -+#ifndef IPPROTO_COMP -+#define IPPROTO_COMP 108 -+#endif /* IPPROTO_COMP */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int sysctl_ipsec_debug_ipcomp; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+struct ipcomphdr { /* IPCOMP header */ -+ __u8 ipcomp_nh; /* Next header (protocol) */ -+ __u8 ipcomp_flags; /* Reserved, must be 0 */ -+ __u16 ipcomp_cpi; /* Compression Parameter Index */ -+}; -+ -+extern struct inet_protocol comp_protocol; -+extern int sysctl_ipsec_debug_ipcomp; -+ -+#define IPCOMP_UNCOMPRESSABLE 0x000000001 -+#define IPCOMP_COMPRESSIONERROR 0x000000002 -+#define IPCOMP_PARMERROR 0x000000004 -+#define IPCOMP_DECOMPRESSIONERROR 0x000000008 -+ -+#define IPCOMP_ADAPT_INITIAL_TRIES 8 -+#define IPCOMP_ADAPT_INITIAL_SKIP 4 -+#define IPCOMP_ADAPT_SUBSEQ_TRIES 2 -+#define IPCOMP_ADAPT_SUBSEQ_SKIP 8 -+ -+/* Function prototypes */ -+struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); -+struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); -+ -+extern struct xform_functions ipcomp_xform_funcs[]; -+ -+#endif /* IPSEC_IPCOMP_H */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.3 2004/04/06 02:49:08 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.2 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_ipcomp.h,v -+ * -+ * Revision 1.1 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.2 2003/12/11 20:14:58 mcr -+ * refactored the xmit code, to move all encapsulation -+ * code into protocol functions. Note that all functions -+ * are essentially done by a single function, which is probably -+ * wrong. -+ * the rcv_functions structures are renamed xform_functions. -+ * -+ * Revision 1.1 2003/12/06 21:21:19 mcr -+ * split up receive path into per-transform files, for -+ * easier later removal. -+ * -+ * -+ * -+ */ -+ -+ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_ipe4.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,68 @@ -+/* -+ * IP-in-IP Header declarations -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* The packet header is an IP header! */ -+ -+struct ipe4_xdata /* transform table data */ -+{ -+ struct in_addr i4_src; -+ struct in_addr i4_dst; -+}; -+ -+#define EMT_IPE4_ULEN 8 /* coming from user mode */ -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.6 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_ipe4.h,v -+ * -+ * Revision 1.5 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_ipe4.h,v -+ * -+ * Revision 1.4 2001/06/14 19:35:08 rgb -+ * Update copyright date. -+ * -+ * Revision 1.3 1999/04/11 00:28:57 henry -+ * GPL boilerplate -+ * -+ * Revision 1.2 1999/04/06 04:54:25 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.1 1998/06/18 21:27:47 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.1 1998/04/09 03:06:07 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:03 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:48:53 ji -+ * Release update only. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_ipip.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,45 @@ -+/* -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef _IPSEC_IPIP_H_ -+ -+#ifndef IPPROTO_IPIP -+#define IPPROTO_IPIP 4 -+#endif /* IPPROTO_ESP */ -+ -+extern struct xform_functions ipip_xform_funcs[]; -+ -+#define _IPSEC_IPIP_H_ -+ -+#endif /* _IPSEC_IPIP_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.2 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_ipip.h,v -+ * -+ * Revision 1.1 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.1 2003/12/11 20:14:58 mcr -+ * refactored the xmit code, to move all encapsulation -+ * code into protocol functions. Note that all functions -+ * are essentially done by a single function, which is probably -+ * wrong. -+ * the rcv_functions structures are renamed xform_functions. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_kversion.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,239 @@ -+#ifndef _FREESWAN_KVERSIONS_H -+/* -+ * header file for FreeS/WAN library functions -+ * Copyright (C) 1998, 1999, 2000 Henry Spencer. -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#define _FREESWAN_KVERSIONS_H /* seen it, no need to see it again */ -+ -+/* -+ * this file contains a series of atomic defines that depend upon -+ * kernel version numbers. The kernel versions are arranged -+ * in version-order number (which is often not chronological) -+ * and each clause enables or disables a feature. -+ */ -+ -+/* -+ * First, assorted kernel-version-dependent trickery. -+ */ -+#include -+#ifndef KERNEL_VERSION -+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) -+#define HEADER_CACHE_BIND_21 -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) -+#define SPINLOCK -+#define PROC_FS_21 -+#define NETLINK_SOCK -+#define NET_21 -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,19) -+#define net_device_stats enet_statistics -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) -+#define SPINLOCK_23 -+#define NETDEV_23 -+# ifndef CONFIG_IP_ALIAS -+# define CONFIG_IP_ALIAS -+# endif -+#include -+#include -+#include -+# ifdef NETLINK_XFRM -+# define NETDEV_25 -+# endif -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,25) -+#define PROC_FS_2325 -+#undef PROC_FS_21 -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30) -+#define PROC_NO_DUMMY -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,35) -+#define SKB_COPY_EXPAND -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,37) -+#define IP_SELECT_IDENT -+#endif -+ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,50)) && defined(CONFIG_NETFILTER) -+#define SKB_RESET_NFCT -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,2) -+#define IP_SELECT_IDENT_NEW -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) -+#define IPH_is_SKB_PULLED -+#define SKB_COW_NEW -+#define PROTO_HANDLER_SINGLE_PARM -+#define IP_FRAGMENT_LINEARIZE 1 -+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) */ -+# ifdef REDHAT_BOGOSITY -+# define IP_SELECT_IDENT_NEW -+# define IPH_is_SKB_PULLED -+# define SKB_COW_NEW -+# define PROTO_HANDLER_SINGLE_PARM -+# endif /* REDHAT_BOGOSITY */ -+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) */ -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) -+#define MALLOC_SLAB -+#define LINUX_KERNEL_HAS_SNPRINTF -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+#define HAVE_NETDEV_PRINTK 1 -+#endif -+ -+#ifdef NET_21 -+# include -+#else -+ /* old kernel in.h has some IPv6 stuff, but not quite enough */ -+# define s6_addr16 s6_addr -+# define AF_INET6 10 -+# define uint8_t __u8 -+# define uint16_t __u16 -+# define uint32_t __u32 -+# define uint64_t __u64 -+#endif -+ -+#ifdef NET_21 -+# define ipsec_kfree_skb(a) kfree_skb(a) -+#else /* NET_21 */ -+# define ipsec_kfree_skb(a) kfree_skb(a, FREE_WRITE) -+#endif /* NET_21 */ -+ -+#ifdef NETDEV_23 -+# define device net_device -+# define ipsec_dev_get dev_get_by_name -+# define __ipsec_dev_get __dev_get_by_name -+# define ipsec_dev_put(x) dev_put(x) -+# define __ipsec_dev_put(x) __dev_put(x) -+# define ipsec_dev_hold(x) dev_hold(x) -+#else /* NETDEV_23 */ -+# define ipsec_dev_get dev_get -+# define __ipsec_dev_put(x) -+# define ipsec_dev_put(x) -+# define ipsec_dev_hold(x) -+#endif /* NETDEV_23 */ -+ -+#ifndef SPINLOCK -+# include -+ /* simulate spin locks and read/write locks */ -+ typedef struct { -+ volatile char lock; -+ } spinlock_t; -+ -+ typedef struct { -+ volatile unsigned int lock; -+ } rwlock_t; -+ -+# define spin_lock_init(x) { (x)->lock = 0;} -+# define rw_lock_init(x) { (x)->lock = 0; } -+ -+# define spin_lock(x) { while ((x)->lock) barrier(); (x)->lock=1;} -+# define spin_lock_irq(x) { cli(); spin_lock(x);} -+# define spin_lock_irqsave(x,flags) { save_flags(flags); spin_lock_irq(x);} -+ -+# define spin_unlock(x) { (x)->lock=0;} -+# define spin_unlock_irq(x) { spin_unlock(x); sti();} -+# define spin_unlock_irqrestore(x,flags) { spin_unlock(x); restore_flags(flags);} -+ -+# define read_lock(x) spin_lock(x) -+# define read_lock_irq(x) spin_lock_irq(x) -+# define read_lock_irqsave(x,flags) spin_lock_irqsave(x,flags) -+ -+# define read_unlock(x) spin_unlock(x) -+# define read_unlock_irq(x) spin_unlock_irq(x) -+# define read_unlock_irqrestore(x,flags) spin_unlock_irqrestore(x,flags) -+ -+# define write_lock(x) spin_lock(x) -+# define write_lock_irq(x) spin_lock_irq(x) -+# define write_lock_irqsave(x,flags) spin_lock_irqsave(x,flags) -+ -+# define write_unlock(x) spin_unlock(x) -+# define write_unlock_irq(x) spin_unlock_irq(x) -+# define write_unlock_irqrestore(x,flags) spin_unlock_irqrestore(x,flags) -+#endif /* !SPINLOCK */ -+ -+#ifndef SPINLOCK_23 -+# define spin_lock_bh(x) spin_lock_irq(x) -+# define spin_unlock_bh(x) spin_unlock_irq(x) -+ -+# define read_lock_bh(x) read_lock_irq(x) -+# define read_unlock_bh(x) read_unlock_irq(x) -+ -+# define write_lock_bh(x) write_lock_irq(x) -+# define write_unlock_bh(x) write_unlock_irq(x) -+#endif /* !SPINLOCK_23 */ -+ -+#ifndef HAVE_NETDEV_PRINTK -+#define netdev_printk(sevlevel, netdev, msglevel, format, arg...) \ -+ printk(sevlevel "%s: " format , netdev->name , ## arg) -+#endif -+ -+#endif /* _FREESWAN_KVERSIONS_H */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.9 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_kversion.h,v -+ * -+ * Revision 1.8 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.7 2003/07/31 22:48:08 mcr -+ * derive NET25-ness from presence of NETLINK_XFRM macro. -+ * -+ * Revision 1.6 2003/06/24 20:22:32 mcr -+ * added new global: ipsecdevices[] so that we can keep track of -+ * the ipsecX devices. They will be referenced with dev_hold(), -+ * so 2.2 may need this as well. -+ * -+ * Revision 1.5 2003/04/03 17:38:09 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * -+ * Revision 1.4 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_kversion.h,v -+ * -+ * Revision 1.3 2002/04/12 03:21:17 mcr -+ * three parameter version of ip_select_ident appears first -+ * in 2.4.2 (RH7.1) not 2.4.4. -+ * -+ * Revision 1.2 2002/03/08 21:35:22 rgb -+ * Defined LINUX_KERNEL_HAS_SNPRINTF to shut up compiler warnings after -+ * 2.4.9. (Andreas Piesk). -+ * -+ * Revision 1.1 2002/01/29 02:11:42 mcr -+ * removal of kversions.h - sources that needed it now use ipsec_param.h. -+ * updating of IPv6 structures to match latest in6.h version. -+ * removed dead code from freeswan.h that also duplicated kversions.h -+ * code. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_life.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,112 @@ -+/* -+ * Definitions relevant to IPSEC lifetimes -+ * Copyright (C) 2001 Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ * This file derived from ipsec_xform.h on 2001/9/18 by mcr. -+ * -+ */ -+ -+/* -+ * This file describes the book keeping fields for the -+ * IPsec Security Association Structure. ("ipsec_sa") -+ * -+ * This structure is never allocated directly by kernel code, -+ * (it is always a static/auto or is part of a structure) -+ * so it does not have a reference count. -+ * -+ */ -+ -+#ifndef _IPSEC_LIFE_H_ -+ -+/* -+ * _count is total count. -+ * _hard is hard limit (kill SA after this number) -+ * _soft is soft limit (try to renew SA after this number) -+ * _last is used in some special cases. -+ * -+ */ -+ -+struct ipsec_lifetime64 -+{ -+ __u64 ipl_count; -+ __u64 ipl_soft; -+ __u64 ipl_hard; -+ __u64 ipl_last; -+}; -+ -+struct ipsec_lifetimes -+{ -+ /* number of bytes processed */ -+ struct ipsec_lifetime64 ipl_bytes; -+ -+ /* number of packets processed */ -+ struct ipsec_lifetime64 ipl_packets; -+ -+ /* time since SA was added */ -+ struct ipsec_lifetime64 ipl_addtime; -+ -+ /* time since SA was first used */ -+ struct ipsec_lifetime64 ipl_usetime; -+ -+ /* from rfc2367: -+ * For CURRENT, the number of different connections, -+ * endpoints, or flows that the association has been -+ * allocated towards. For HARD and SOFT, the number of -+ * these the association may be allocated towards -+ * before it expires. The concept of a connection, -+ * flow, or endpoint is system specific. -+ * -+ * mcr(2001-9-18) it is unclear what purpose these serve for FreeSWAN. -+ * They are maintained for PF_KEY compatibility. -+ */ -+ struct ipsec_lifetime64 ipl_allocations; -+}; -+ -+enum ipsec_life_alive { -+ ipsec_life_harddied = -1, -+ ipsec_life_softdied = 0, -+ ipsec_life_okay = 1 -+}; -+ -+enum ipsec_life_type { -+ ipsec_life_timebased = 1, -+ ipsec_life_countbased= 0 -+}; -+ -+#define _IPSEC_LIFE_H_ -+#endif /* _IPSEC_LIFE_H_ */ -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.4 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_life.h,v -+ * -+ * Revision 1.3 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_life.h,v -+ * -+ * Revision 1.2 2001/11/26 09:16:14 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:25:58 mcr -+ * lifetime structure created and common functions created. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_md5h.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,140 @@ -+/* -+ * RCSID $Id$ -+ */ -+ -+/* -+ * The rest of this file is Copyright RSA DSI. See the following comments -+ * for the full Copyright notice. -+ */ -+ -+#ifndef _IPSEC_MD5H_H_ -+#define _IPSEC_MD5H_H_ -+ -+/* GLOBAL.H - RSAREF types and constants -+ */ -+ -+/* PROTOTYPES should be set to one if and only if the compiler supports -+ function argument prototyping. -+ The following makes PROTOTYPES default to 0 if it has not already -+ been defined with C compiler flags. -+ */ -+#ifndef PROTOTYPES -+#define PROTOTYPES 1 -+#endif /* !PROTOTYPES */ -+ -+/* POINTER defines a generic pointer type */ -+typedef __u8 *POINTER; -+ -+/* UINT2 defines a two byte word */ -+typedef __u16 UINT2; -+ -+/* UINT4 defines a four byte word */ -+typedef __u32 UINT4; -+ -+/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. -+ If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it -+ returns an empty list. -+ */ -+ -+#if PROTOTYPES -+#define PROTO_LIST(list) list -+#else /* PROTOTYPES */ -+#define PROTO_LIST(list) () -+#endif /* PROTOTYPES */ -+ -+ -+/* MD5.H - header file for MD5C.C -+ */ -+ -+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -+rights reserved. -+ -+License to copy and use this software is granted provided that it -+is identified as the "RSA Data Security, Inc. MD5 Message-Digest -+Algorithm" in all material mentioning or referencing this software -+or this function. -+ -+License is also granted to make and use derivative works provided -+that such works are identified as "derived from the RSA Data -+Security, Inc. MD5 Message-Digest Algorithm" in all material -+mentioning or referencing the derived work. -+ -+RSA Data Security, Inc. makes no representations concerning either -+the merchantability of this software or the suitability of this -+software for any particular purpose. It is provided "as is" -+without express or implied warranty of any kind. -+ -+These notices must be retained in any copies of any part of this -+documentation and/or software. -+ */ -+ -+/* MD5 context. */ -+typedef struct { -+ UINT4 state[4]; /* state (ABCD) */ -+ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ -+ unsigned char buffer[64]; /* input buffer */ -+} MD5_CTX; -+ -+void MD5Init PROTO_LIST ((void *)); -+void MD5Update PROTO_LIST -+ ((void *, unsigned char *, __u32)); -+void MD5Final PROTO_LIST ((unsigned char [16], void *)); -+ -+#endif /* _IPSEC_MD5H_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.9 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_md5h.h,v -+ * -+ * Revision 1.8 2002/09/10 01:45:09 mcr -+ * changed type of MD5_CTX and SHA1_CTX to void * so that -+ * the function prototypes would match, and could be placed -+ * into a pointer to a function. -+ * -+ * Revision 1.7 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_md5h.h,v -+ * -+ * Revision 1.6 1999/12/13 13:59:13 rgb -+ * Quick fix to argument size to Update bugs. -+ * -+ * Revision 1.5 1999/12/07 18:16:23 rgb -+ * Fixed comments at end of #endif lines. -+ * -+ * Revision 1.4 1999/04/06 04:54:26 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.3 1999/01/22 06:19:58 rgb -+ * 64-bit clean-up. -+ * -+ * Revision 1.2 1998/11/30 13:22:54 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.1 1998/06/18 21:27:48 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.2 1998/04/23 20:54:03 rgb -+ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when -+ * verified. -+ * -+ * Revision 1.1 1998/04/09 03:04:21 henry -+ * sources moved up from linux/net/ipsec -+ * these two include files modified not to include others except in kernel -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:03 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:48:53 ji -+ * Release update only. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_param.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,333 @@ -+/* -+ * @(#) FreeSWAN tunable paramaters -+ * -+ * Copyright (C) 2001 Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ */ -+ -+/* -+ * This file provides a set of #define's which may be tuned by various -+ * people/configurations. It keeps all compile-time tunables in one place. -+ * -+ * This file should be included before all other IPsec kernel-only files. -+ * -+ */ -+ -+#ifndef _IPSEC_PARAM_H_ -+ -+#ifdef __KERNEL__ -+#include "ipsec_kversion.h" -+ -+/* Set number of ipsecX virtual devices here. */ -+/* This must be < exp(field width of IPSEC_DEV_FORMAT) */ -+/* It must also be reasonable so as not to overload the memory and CPU */ -+/* constraints of the host. */ -+#define IPSEC_NUM_IF 4 -+/* The field width must be < IF_NAM_SIZ - strlen("ipsec") - 1. */ -+/* With "ipsec" being 5 characters, that means 10 is the max field width */ -+/* but machine memory and CPU constraints are not likely to tollerate */ -+/* more than 3 digits. The default is one digit. */ -+/* Update: userland scripts get upset if they can't find "ipsec0", so */ -+/* for now, no "0"-padding should be used (which would have been helpful */ -+/* to make text-searches work */ -+#define IPSEC_DEV_FORMAT "ipsec%d" -+/* For, say, 500 virtual ipsec devices, I would recommend: */ -+/* #define IPSEC_NUM_IF 500 */ -+/* #define IPSEC_DEV_FORMAT "ipsec%03d" */ -+/* Note that the "interfaces=" line in /etc/ipsec.conf would be, um, challenging. */ -+ -+/* use dynamic ipsecX device allocation */ -+#ifndef CONFIG_IPSEC_DYNDEV -+#define CONFIG_IPSEC_DYNDEV 1 -+#endif /* CONFIG_IPSEC_DYNDEV */ -+ -+ -+#ifdef CONFIG_IPSEC_BIGGATE -+# define SADB_HASHMOD 8069 -+#else /* CONFIG_IPSEC_BIGGATE */ -+# define SADB_HASHMOD 257 -+#endif /* CONFIG_IPSEC_BIGGATE */ -+#endif /* __KERNEL__ */ -+ -+/* -+ * This is for the SA reference table. This number is related to the -+ * maximum number of SAs that KLIPS can concurrently deal with, plus enough -+ * space for keeping expired SAs around. -+ * -+ * TABLE_MAX_WIDTH is the number of bits that we will use. -+ * MAIN_TABLE_WIDTH is the number of bits used for the primary index table. -+ * -+ */ -+#ifndef IPSEC_SA_REF_TABLE_IDX_WIDTH -+# define IPSEC_SA_REF_TABLE_IDX_WIDTH 16 -+#endif -+ -+#ifndef IPSEC_SA_REF_MAINTABLE_IDX_WIDTH -+# define IPSEC_SA_REF_MAINTABLE_IDX_WIDTH 4 -+#endif -+ -+#ifndef IPSEC_SA_REF_FREELIST_NUM_ENTRIES -+# define IPSEC_SA_REF_FREELIST_NUM_ENTRIES 256 -+#endif -+ -+#ifndef IPSEC_SA_REF_CODE -+# define IPSEC_SA_REF_CODE 1 -+#endif -+ -+#ifdef __KERNEL__ -+/* This is defined for 2.4, but not 2.2.... */ -+#ifndef ARPHRD_VOID -+# define ARPHRD_VOID 0xFFFF -+#endif -+ -+/* -+ * Worry about PROC_FS stuff -+ */ -+#if defined(PROC_FS_2325) -+/* kernel 2.4 */ -+# define IPSEC_PROC_LAST_ARG ,int *eof,void *data -+# define IPSEC_PROCFS_DEBUG_NO_STATIC -+# define IPSEC_PROC_SUBDIRS -+#else -+/* kernel <2.4 */ -+# define IPSEC_PROCFS_DEBUG_NO_STATIC DEBUG_NO_STATIC -+ -+# ifndef PROC_NO_DUMMY -+# define IPSEC_PROC_LAST_ARG , int dummy -+# else -+# define IPSEC_PROC_LAST_ARG -+# endif /* !PROC_NO_DUMMY */ -+#endif /* PROC_FS_2325 */ -+ -+#if !defined(LINUX_KERNEL_HAS_SNPRINTF) -+/* GNU CPP specific! */ -+# define snprintf(buf, len, fmt...) sprintf(buf, ##fmt) -+#endif /* !LINUX_KERNEL_HAS_SNPRINTF */ -+ -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+ -+#ifndef KLIPS_FIXES_DES_PARITY -+# define KLIPS_FIXES_DES_PARITY 1 -+#endif /* !KLIPS_FIXES_DES_PARITY */ -+ -+/* we don't really want to print these unless there are really big problems */ -+#ifndef KLIPS_DIVULGE_CYPHER_KEY -+# define KLIPS_DIVULGE_CYPHER_KEY 0 -+#endif /* !KLIPS_DIVULGE_CYPHER_KEY */ -+ -+#ifndef KLIPS_DIVULGE_HMAC_KEY -+# define KLIPS_DIVULGE_HMAC_KEY 0 -+#endif /* !KLIPS_DIVULGE_HMAC_KEY */ -+ -+#ifndef IPSEC_DISALLOW_IPOPTIONS -+# define IPSEC_DISALLOW_IPOPTIONS 1 -+#endif /* !KLIPS_DIVULGE_HMAC_KEY */ -+ -+/* extra toggles for regression testing */ -+#ifdef CONFIG_IPSEC_REGRESS -+ -+/* -+ * should pfkey_acquire() become 100% lossy? -+ * -+ */ -+extern int sysctl_ipsec_regress_pfkey_lossage; -+#ifndef KLIPS_PFKEY_ACQUIRE_LOSSAGE -+# ifdef CONFIG_IPSEC_PFKEY_ACQUIRE_LOSSAGE -+# define KLIPS_PFKEY_ACQUIRE_LOSSAGE 100 -+# else /* CONFIG_IPSEC_PFKEY_ACQUIRE_LOSSAGE */ -+/* not by default! */ -+# define KLIPS_PFKEY_ACQUIRE_LOSSAGE 0 -+# endif /* CONFIG_IPSEC_PFKEY_ACQUIRE_LOSSAGE */ -+#endif /* KLIPS_PFKEY_ACQUIRE_LOSSAGE */ -+ -+#endif /* CONFIG_IPSEC_REGRESS */ -+ -+ -+/* -+ * debugging routines. -+ */ -+#ifdef CONFIG_IPSEC_DEBUG -+extern void ipsec_print_ip(struct iphdr *ip); -+ -+ #define KLIPS_PRINT(flag, format, args...) \ -+ ((flag) ? printk(KERN_INFO format , ## args) : 0) -+ #define KLIPS_PRINTMORE(flag, format, args...) \ -+ ((flag) ? printk(format , ## args) : 0) -+ #define KLIPS_IP_PRINT(flag, ip) \ -+ ((flag) ? ipsec_print_ip(ip) : 0) -+#else /* CONFIG_IPSEC_DEBUG */ -+ #define KLIPS_PRINT(flag, format, args...) do ; while(0) -+ #define KLIPS_PRINTMORE(flag, format, args...) do ; while(0) -+ #define KLIPS_IP_PRINT(flag, ip) do ; while(0) -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ -+/* -+ * Stupid kernel API differences in APIs. Not only do some -+ * kernels not have ip_select_ident, but some have differing APIs, -+ * and SuSE has one with one parameter, but no way of checking to -+ * see what is really what. -+ */ -+ -+#ifdef SUSE_LINUX_2_4_19_IS_STUPID -+#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph) -+#else -+ -+/* simplest case, nothing */ -+#if !defined(IP_SELECT_IDENT) -+#define KLIPS_IP_SELECT_IDENT(iph, skb) do { iph->id = htons(ip_id_count++); } while(0) -+#endif -+ -+/* kernels > 2.3.37-ish */ -+#if defined(IP_SELECT_IDENT) && !defined(IP_SELECT_IDENT_NEW) -+#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst) -+#endif -+ -+/* kernels > 2.4.2 */ -+#if defined(IP_SELECT_IDENT) && defined(IP_SELECT_IDENT_NEW) -+#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst, NULL) -+#endif -+ -+#endif /* SUSE_LINUX_2_4_19_IS_STUPID */ -+ -+/* -+ * make klips fail test:east-espiv-01. -+ * exploit is at testing/attacks/espiv -+ * -+ */ -+#define KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK 0 -+ -+ -+/* IP_FRAGMENT_LINEARIZE is set in freeswan.h if Kernel > 2.4.4 */ -+#ifndef IP_FRAGMENT_LINEARIZE -+# define IP_FRAGMENT_LINEARIZE 0 -+#endif /* IP_FRAGMENT_LINEARIZE */ -+#endif /* __KERNEL__ */ -+ -+#define _IPSEC_PARAM_H_ -+#endif /* _IPSEC_PARAM_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.24 2004/04/05 19:55:06 mcr -+ * Moved from linux/include/freeswan/ipsec_param.h,v -+ * -+ * Revision 1.23 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.22 2003/10/31 02:27:05 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.21.4.1 2003/10/29 01:10:19 mcr -+ * elimited "struct sa_id" -+ * -+ * Revision 1.21 2003/04/03 17:38:18 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * Change indentation for readability. -+ * -+ * Revision 1.20 2003/03/14 08:09:26 rgb -+ * Fixed up CONFIG_IPSEC_DYNDEV definitions. -+ * -+ * Revision 1.19 2003/01/30 02:31:43 rgb -+ * -+ * Rename SAref table macro names for clarity. -+ * -+ * Revision 1.18 2002/09/30 19:06:26 rgb -+ * Reduce default table to 16 bits width. -+ * -+ * Revision 1.17 2002/09/20 15:40:29 rgb -+ * Define switch to activate new SAref code. -+ * Prefix macros with "IPSEC_". -+ * Rework saref freelist. -+ * Restrict some bits to kernel context for use to klips utils. -+ * -+ * Revision 1.16 2002/09/20 05:00:31 rgb -+ * Define switch to divulge hmac keys for debugging. -+ * Added IPOPTIONS switch. -+ * -+ * Revision 1.15 2002/09/19 02:34:24 mcr -+ * define IPSEC_PROC_SUBDIRS if we are 2.4, and use that in ipsec_proc.c -+ * to decide if we are to create /proc/net/ipsec/. -+ * -+ * Revision 1.14 2002/08/30 01:20:54 mcr -+ * reorganized 2.0/2.2/2.4 procfs support macro so match -+ * 2.4 values/typedefs. -+ * -+ * Revision 1.13 2002/07/28 22:03:28 mcr -+ * added some documentation to SA_REF_* -+ * turned on fix for ESPIV attack, now that we have the attack code. -+ * -+ * Revision 1.12 2002/07/26 08:48:31 rgb -+ * Added SA ref table code. -+ * -+ * Revision 1.11 2002/07/23 02:57:45 rgb -+ * Define ARPHRD_VOID for < 2.4 kernels. -+ * -+ * Revision 1.10 2002/05/27 21:37:28 rgb -+ * Set the defaults sanely for those adventurous enough to try more than 1 -+ * digit of ipsec devices. -+ * -+ * Revision 1.9 2002/05/27 18:56:07 rgb -+ * Convert to dynamic ipsec device allocation. -+ * -+ * Revision 1.8 2002/04/24 07:36:47 mcr -+ * Moved from ./klips/net/ipsec/ipsec_param.h,v -+ * -+ * Revision 1.7 2002/04/20 00:12:25 rgb -+ * Added esp IV CBC attack fix, disabled. -+ * -+ * Revision 1.6 2002/01/29 02:11:42 mcr -+ * removal of kversions.h - sources that needed it now use ipsec_param.h. -+ * updating of IPv6 structures to match latest in6.h version. -+ * removed dead code from freeswan.h that also duplicated kversions.h -+ * code. -+ * -+ * Revision 1.5 2002/01/28 19:22:01 mcr -+ * by default, turn off LINEARIZE option -+ * (let kversions.h turn it on) -+ * -+ * Revision 1.4 2002/01/20 20:19:36 mcr -+ * renamed option to IP_FRAGMENT_LINEARIZE. -+ * -+ * Revision 1.3 2002/01/12 02:57:25 mcr -+ * first regression test causes acquire messages to be lost -+ * 100% of the time. This is to help testing of pluto. -+ * -+ * Revision 1.2 2001/11/26 09:16:14 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.3 2001/10/23 04:40:16 mcr -+ * added #define for DIVULGING session keys in debug output. -+ * -+ * Revision 1.1.2.2 2001/10/22 20:53:25 mcr -+ * added a define to control forcing of DES parity. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:20:19 mcr -+ * many common kernel configuration questions centralized. -+ * more things remain that should be moved from freeswan.h. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_policy.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,216 @@ -+#ifndef _IPSEC_POLICY_H -+/* -+ * policy interface file between pluto and applications -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#define _IPSEC_POLICY_H /* seen it, no need to see it again */ -+ -+ -+/* -+ * this file defines an interface between an application (or rather an -+ * application library) and a key/policy daemon. It provides for inquiries -+ * as to the current state of a connected socket, as well as for general -+ * questions. -+ * -+ * In general, the interface is defined as a series of functional interfaces, -+ * and the policy messages should be internal. However, because this is in -+ * fact an ABI between pieces of the system that may get compiled and revised -+ * seperately, this ABI must be public and revision controlled. -+ * -+ * It is expected that the daemon will always support previous versions. -+ */ -+ -+#define IPSEC_POLICY_MSG_REVISION (unsigned)200305061 -+ -+enum ipsec_policy_command { -+ IPSEC_CMD_QUERY_FD = 1, -+ IPSEC_CMD_QUERY_HOSTPAIR = 2, -+ IPSEC_CMD_QUERY_DSTONLY = 3, -+}; -+ -+struct ipsec_policy_msg_head { -+ u_int32_t ipm_version; -+ u_int32_t ipm_msg_len; -+ u_int32_t ipm_msg_type; -+ u_int32_t ipm_msg_seq; -+}; -+ -+enum ipsec_privacy_quality { -+ IPSEC_PRIVACY_NONE = 0, -+ IPSEC_PRIVACY_INTEGRAL = 4, /* not private at all. AH-like */ -+ IPSEC_PRIVACY_UNKNOWN = 8, /* something is claimed, but details unavail */ -+ IPSEC_PRIVACY_ROT13 = 12, /* trivially breakable, i.e. 1DES */ -+ IPSEC_PRIVACY_GAK = 16, /* known eavesdroppers */ -+ IPSEC_PRIVACY_PRIVATE = 32, /* secure for at least a decade */ -+ IPSEC_PRIVACY_STRONG = 64, /* ridiculously secure */ -+ IPSEC_PRIVACY_TORTOISE = 192, /* even stronger, but very slow */ -+ IPSEC_PRIVACY_OTP = 224, /* some kind of *true* one time pad */ -+}; -+ -+enum ipsec_bandwidth_quality { -+ IPSEC_QOS_UNKNOWN = 0, /* unknown bandwidth */ -+ IPSEC_QOS_INTERACTIVE = 16, /* reasonably moderate jitter, moderate fast. -+ Good enough for telnet/ssh. */ -+ IPSEC_QOS_VOIP = 32, /* faster crypto, predicable jitter */ -+ IPSEC_QOS_FTP = 64, /* higher throughput crypto, perhaps hardware -+ offloaded, but latency/jitter may be bad */ -+ IPSEC_QOS_WIRESPEED = 128, /* expect to be able to fill your pipe */ -+}; -+ -+/* moved from programs/pluto/constants.h */ -+/* IPsec AH transform values -+ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.3 -+ * and in http://www.iana.org/assignments/isakmp-registry -+ */ -+enum ipsec_authentication_algo { -+ AH_MD5=2, -+ AH_SHA=3, -+ AH_DES=4, -+ AH_SHA2_256=5, -+ AH_SHA2_384=6, -+ AH_SHA2_512=7 -+}; -+ -+/* IPsec ESP transform values -+ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.4 -+ * and from http://www.iana.org/assignments/isakmp-registry -+ */ -+ -+enum ipsec_cipher_algo { -+ ESP_reserved=0, -+ ESP_DES_IV64=1, -+ ESP_DES=2, -+ ESP_3DES=3, -+ ESP_RC5=4, -+ ESP_IDEA=5, -+ ESP_CAST=6, -+ ESP_BLOWFISH=7, -+ ESP_3IDEA=8, -+ ESP_DES_IV32=9, -+ ESP_RC4=10, -+ ESP_NULL=11, -+ ESP_AES=12, -+}; -+ -+/* IPCOMP transform values -+ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.5 -+ */ -+ -+enum ipsec_comp_algo { -+ IPCOMP_OUI= 1, -+ IPCOMP_DEFLATE= 2, -+ IPCOMP_LZS= 3, -+ IPCOMP_V42BIS= 4 -+}; -+ -+/* Identification type values -+ * RFC 2407 The Internet IP security Domain of Interpretation for ISAKMP 4.6.2.1 -+ */ -+ -+enum ipsec_id_type { -+ ID_IMPOSSIBLE= (-2), /* private to Pluto */ -+ ID_MYID= (-1), /* private to Pluto */ -+ ID_NONE= 0, /* private to Pluto */ -+ ID_IPV4_ADDR= 1, -+ ID_FQDN= 2, -+ ID_USER_FQDN= 3, -+ ID_IPV4_ADDR_SUBNET= 4, -+ ID_IPV6_ADDR= 5, -+ ID_IPV6_ADDR_SUBNET= 6, -+ ID_IPV4_ADDR_RANGE= 7, -+ ID_IPV6_ADDR_RANGE= 8, -+ ID_DER_ASN1_DN= 9, -+ ID_DER_ASN1_GN= 10, -+ ID_KEY_ID= 11 -+}; -+ -+/* Certificate type values -+ * RFC 2408 ISAKMP, chapter 3.9 -+ */ -+enum ipsec_cert_type { -+ CERT_NONE= 0, /* none, or guess from file contents */ -+ CERT_PKCS7_WRAPPED_X509= 1, /* self-signed certificate from disk */ -+ CERT_PGP= 2, -+ CERT_DNS_SIGNED_KEY= 3, /* KEY RR from DNS */ -+ CERT_X509_SIGNATURE= 4, -+ CERT_X509_KEY_EXCHANGE= 5, -+ CERT_KERBEROS_TOKENS= 6, -+ CERT_CRL= 7, -+ CERT_ARL= 8, -+ CERT_SPKI= 9, -+ CERT_X509_ATTRIBUTE= 10, -+ CERT_RAW_RSA= 11, /* raw RSA from config file */ -+}; -+ -+/* a SIG record in ASCII */ -+struct ipsec_dns_sig { -+ char fqdn[256]; -+ char dns_sig[768]; /* empty string if not signed */ -+}; -+ -+struct ipsec_raw_key { -+ char id_name[256]; -+ char fs_keyid[8]; -+}; -+ -+struct ipsec_identity { -+ enum ipsec_id_type ii_type; -+ enum ipsec_cert_type ii_format; -+ union { -+ struct ipsec_dns_sig ipsec_dns_signed; -+ /* some thing for PGP */ -+ /* some thing for PKIX */ -+ struct ipsec_raw_key ipsec_raw_key; -+ } ii_credential; -+}; -+ -+#define IPSEC_MAX_CREDENTIALS 32 -+ -+struct ipsec_policy_cmd_query { -+ struct ipsec_policy_msg_head head; -+ -+ /* Query section */ -+ ip_address query_local; /* us */ -+ ip_address query_remote; /* them */ -+ u_short src_port, dst_port; -+ -+ /* Answer section */ -+ enum ipsec_privacy_quality strength; -+ enum ipsec_bandwidth_quality bandwidth; -+ enum ipsec_authentication_algo auth_detail; -+ enum ipsec_cipher_algo esp_detail; -+ enum ipsec_comp_algo comp_detail; -+ -+ int credential_count; -+ -+ struct ipsec_identity credentials[IPSEC_MAX_CREDENTIALS]; -+}; -+ -+#define IPSEC_POLICY_SOCKET "/var/run/pluto.info" -+ -+/* prototypes */ -+extern err_t ipsec_policy_lookup(int fd, struct ipsec_policy_cmd_query *result); -+extern err_t ipsec_policy_init(void); -+extern err_t ipsec_policy_final(void); -+extern err_t ipsec_policy_readmsg(int policysock, -+ unsigned char *buf, size_t buflen); -+extern err_t ipsec_policy_sendrecv(unsigned char *buf, size_t buflen); -+extern err_t ipsec_policy_cgilookup(struct ipsec_policy_cmd_query *result); -+ -+ -+extern const char *ipsec_policy_version_code(void); -+extern const char *ipsec_policy_version_string(void); -+ -+#endif /* _IPSEC_POLICY_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_proto.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,151 @@ -+/* -+ * @(#) prototypes for FreeSWAN functions -+ * -+ * Copyright (C) 2001 Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ */ -+ -+#ifndef _IPSEC_PROTO_H_ -+ -+#include "ipsec_param.h" -+ -+/* -+ * This file is a kernel only file that declares prototypes for -+ * all intra-module function calls and global data structures. -+ * -+ * Include this file last. -+ * -+ */ -+ -+/* ipsec_init.c */ -+extern struct prng ipsec_prng; -+ -+/* ipsec_sa.c */ -+extern struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD]; -+extern spinlock_t tdb_lock; -+extern int ipsec_sadb_init(void); -+ -+extern struct ipsec_sa *ipsec_sa_getbyid(ip_said *); -+extern int ipsec_sa_put(struct ipsec_sa *); -+extern /* void */ int ipsec_sa_del(struct ipsec_sa *); -+extern /* void */ int ipsec_sa_delchain(struct ipsec_sa *); -+extern /* void */ int ipsec_sa_add(struct ipsec_sa *); -+ -+extern int ipsec_sadb_cleanup(__u8); -+extern int ipsec_sa_wipe(struct ipsec_sa *); -+ -+/* debug declarations */ -+ -+/* ipsec_proc.c */ -+extern int ipsec_proc_init(void); -+extern void ipsec_proc_cleanup(void); -+ -+/* ipsec_radij.c */ -+extern int ipsec_makeroute(struct sockaddr_encap *ea, -+ struct sockaddr_encap *em, -+ ip_said said, -+ uint32_t pid, -+ struct sk_buff *skb, -+ struct ident *ident_s, -+ struct ident *ident_d); -+ -+extern int ipsec_breakroute(struct sockaddr_encap *ea, -+ struct sockaddr_encap *em, -+ struct sk_buff **first, -+ struct sk_buff **last); -+ -+int ipsec_radijinit(void); -+int ipsec_cleareroutes(void); -+int ipsec_radijcleanup(void); -+ -+/* ipsec_life.c */ -+extern enum ipsec_life_alive ipsec_lifetime_check(struct ipsec_lifetime64 *il64, -+ const char *lifename, -+ const char *saname, -+ enum ipsec_life_type ilt, -+ enum ipsec_direction idir, -+ struct ipsec_sa *ips); -+ -+ -+extern int ipsec_lifetime_format(char *buffer, -+ int buflen, -+ char *lifename, -+ enum ipsec_life_type timebaselife, -+ struct ipsec_lifetime64 *lifetime); -+ -+extern void ipsec_lifetime_update_hard(struct ipsec_lifetime64 *lifetime, -+ __u64 newvalue); -+ -+extern void ipsec_lifetime_update_soft(struct ipsec_lifetime64 *lifetime, -+ __u64 newvalue); -+ -+ -+ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ -+extern int debug_xform; -+extern int debug_eroute; -+extern int debug_spi; -+extern int debug_netlink; -+ -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ -+ -+ -+#define _IPSEC_PROTO_H -+#endif /* _IPSEC_PROTO_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.8 2004/04/05 19:55:06 mcr -+ * Moved from linux/include/freeswan/ipsec_proto.h,v -+ * -+ * Revision 1.7 2003/10/31 02:27:05 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.6.30.1 2003/10/29 01:10:19 mcr -+ * elimited "struct sa_id" -+ * -+ * Revision 1.6 2002/05/23 07:13:48 rgb -+ * Added ipsec_sa_put() for releasing an ipsec_sa refcount. -+ * -+ * Revision 1.5 2002/05/14 02:36:40 rgb -+ * Converted reference from ipsec_sa_put to ipsec_sa_add to avoid confusion -+ * with "put" usage in the kernel. -+ * -+ * Revision 1.4 2002/04/24 07:36:47 mcr -+ * Moved from ./klips/net/ipsec/ipsec_proto.h,v -+ * -+ * Revision 1.3 2002/04/20 00:12:25 rgb -+ * Added esp IV CBC attack fix, disabled. -+ * -+ * Revision 1.2 2001/11/26 09:16:15 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:21:01 mcr -+ * ipsec_proto.h created to keep prototypes rather than deal with -+ * cyclic dependancies of structures and prototypes in .h files. -+ * -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_radij.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,176 @@ -+/* -+ * @(#) Definitions relevant to the IPSEC <> radij tree interfacing -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef _IPSEC_RADIJ_H -+ -+#include -+ -+int ipsec_walk(char *); -+ -+int ipsec_rj_walker_procprint(struct radij_node *, void *); -+int ipsec_rj_walker_delete(struct radij_node *, void *); -+ -+/* This structure is used to pass information between -+ * ipsec_eroute_get_info and ipsec_rj_walker_procprint -+ * (through rj_walktree) and between calls of ipsec_rj_walker_procprint. -+ */ -+struct wsbuf -+{ -+ /* from caller of ipsec_eroute_get_info: */ -+ char *const buffer; /* start of buffer provided */ -+ const int length; /* length of buffer provided */ -+ const off_t offset; /* file position of first character of interest */ -+ /* accumulated by ipsec_rj_walker_procprint: */ -+ int len; /* number of character filled into buffer */ -+ off_t begin; /* file position contained in buffer[0] (<=offset) */ -+}; -+ -+extern struct radij_node_head *rnh; -+extern spinlock_t eroute_lock; -+ -+struct eroute * ipsec_findroute(struct sockaddr_encap *); -+ -+#define O1(x) (int)(((x)>>24)&0xff) -+#define O2(x) (int)(((x)>>16)&0xff) -+#define O3(x) (int)(((x)>>8)&0xff) -+#define O4(x) (int)(((x))&0xff) -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int debug_radij; -+void rj_dumptrees(void); -+ -+#define DB_RJ_DUMPTREES 0x0001 -+#define DB_RJ_FINDROUTE 0x0002 -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#define _IPSEC_RADIJ_H -+#endif -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.21 2004/04/29 11:06:42 ken -+ * Last bits from 2.06 procfs updates -+ * -+ * Revision 1.20 2004/04/06 02:49:08 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.19 2004/04/05 19:55:06 mcr -+ * Moved from linux/include/freeswan/ipsec_radij.h,v -+ * -+ * Revision 1.18 2002/04/24 07:36:47 mcr -+ * Moved from ./klips/net/ipsec/ipsec_radij.h,v -+ * -+ * Revision 1.17 2001/11/26 09:23:49 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.16.2.1 2001/09/25 02:21:17 mcr -+ * ipsec_proto.h created to keep prototypes rather than deal with -+ * cyclic dependancies of structures and prototypes in .h files. -+ * -+ * Revision 1.16 2001/09/15 16:24:04 rgb -+ * Re-inject first and last HOLD packet when an eroute REPLACE is done. -+ * -+ * Revision 1.15 2001/09/14 16:58:37 rgb -+ * Added support for storing the first and last packets through a HOLD. -+ * -+ * Revision 1.14 2001/09/08 21:13:32 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.13 2001/06/14 19:35:09 rgb -+ * Update copyright date. -+ * -+ * Revision 1.12 2001/05/27 06:12:11 rgb -+ * Added structures for pid, packet count and last access time to eroute. -+ * Added packet count to beginning of /proc/net/ipsec_eroute. -+ * -+ * Revision 1.11 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.10 1999/11/17 15:53:39 rgb -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * -+ * Revision 1.9 1999/10/01 00:01:23 rgb -+ * Added eroute structure locking. -+ * -+ * Revision 1.8 1999/04/11 00:28:59 henry -+ * GPL boilerplate -+ * -+ * Revision 1.7 1999/04/06 04:54:26 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.6 1999/01/22 06:23:26 rgb -+ * Cruft clean-out. -+ * -+ * Revision 1.5 1998/10/25 02:42:08 rgb -+ * Change return type on ipsec_breakroute and ipsec_makeroute and add an -+ * argument to be able to transmit more infomation about errors. -+ * -+ * Revision 1.4 1998/10/19 14:44:29 rgb -+ * Added inclusion of freeswan.h. -+ * sa_id structure implemented and used: now includes protocol. -+ * -+ * Revision 1.3 1998/07/28 00:03:31 rgb -+ * Comment out temporary inet_nto4u() kluge. -+ * -+ * Revision 1.2 1998/07/14 18:22:00 rgb -+ * Add function to clear the eroute table. -+ * -+ * Revision 1.1 1998/06/18 21:27:49 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.5 1998/05/25 20:30:38 rgb -+ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions. -+ * -+ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and -+ * add ipsec_rj_walker_delete. -+ * -+ * Revision 1.4 1998/05/21 13:02:56 rgb -+ * Imported definitions from ipsec_radij.c and radij.c to support /proc 3k -+ * limit fix. -+ * -+ * Revision 1.3 1998/04/21 21:29:09 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.2 1998/04/14 17:30:39 rgb -+ * Fix up compiling errors for radij tree memory reclamation. -+ * -+ * Revision 1.1 1998/04/09 03:06:10 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:04 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:39:04 ji -+ * Minor cleanups. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_rcv.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,279 @@ -+/* -+ * -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef IPSEC_RCV_H -+#define IPSEC_RCV_H -+ -+#include "openswan/ipsec_auth.h" -+ -+#define DB_RX_PKTRX 0x0001 -+#define DB_RX_PKTRX2 0x0002 -+#define DB_RX_DMP 0x0004 -+#define DB_RX_IPSA 0x0010 -+#define DB_RX_XF 0x0020 -+#define DB_RX_IPAD 0x0040 -+#define DB_RX_INAU 0x0080 -+#define DB_RX_OINFO 0x0100 -+#define DB_RX_OINFO2 0x0200 -+#define DB_RX_OH 0x0400 -+#define DB_RX_REPLAY 0x0800 -+ -+#ifdef __KERNEL__ -+/* struct options; */ -+ -+#define __NO_VERSION__ -+#include -+#include /* for CONFIG_IP_FORWARD */ -+#include -+#include -+ -+#define IPSEC_BIRTH_TEMPLATE_MAXLEN 256 -+ -+struct ipsec_birth_reply { -+ int packet_template_len; -+ unsigned char packet_template[IPSEC_BIRTH_TEMPLATE_MAXLEN]; -+}; -+ -+extern struct ipsec_birth_reply ipsec_ipv4_birth_packet; -+extern struct ipsec_birth_reply ipsec_ipv6_birth_packet; -+ -+enum ipsec_rcv_value { -+ IPSEC_RCV_LASTPROTO=1, -+ IPSEC_RCV_OK=0, -+ IPSEC_RCV_BADPROTO=-1, -+ IPSEC_RCV_BADLEN=-2, -+ IPSEC_RCV_ESP_BADALG=-3, -+ IPSEC_RCV_3DES_BADBLOCKING=-4, -+ IPSEC_RCV_ESP_DECAPFAIL=-5, -+ IPSEC_RCV_DECAPFAIL=-6, -+ IPSEC_RCV_SAIDNOTFOUND=-7, -+ IPSEC_RCV_IPCOMPALONE=-8, -+ IPSEC_RCV_IPCOMPFAILED=-10, -+ IPSEC_RCV_SAIDNOTLIVE=-11, -+ IPSEC_RCV_FAILEDINBOUND=-12, -+ IPSEC_RCV_LIFETIMEFAILED=-13, -+ IPSEC_RCV_BADAUTH=-14, -+ IPSEC_RCV_REPLAYFAILED=-15, -+ IPSEC_RCV_AUTHFAILED=-16, -+ IPSEC_RCV_REPLAYROLLED=-17, -+ IPSEC_RCV_BAD_DECRYPT=-18 -+}; -+ -+struct ipsec_rcv_state { -+ struct sk_buff *skb; -+ struct net_device_stats *stats; -+ struct iphdr *ipp; -+ struct ipsec_sa *ipsp; -+ int len; -+ int ilen; -+ int authlen; -+ int hard_header_len; -+ int iphlen; -+ struct auth_alg *authfuncs; -+ ip_said said; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ __u8 next_header; -+ __u8 hash[AH_AMAX]; -+ char ipsaddr_txt[ADDRTOA_BUF]; -+ char ipdaddr_txt[ADDRTOA_BUF]; -+ __u8 *octx; -+ __u8 *ictx; -+ int ictx_len; -+ int octx_len; -+ union { -+ struct { -+ struct esphdr *espp; -+ } espstuff; -+ struct { -+ struct ahhdr *ahp; -+ } ahstuff; -+ struct { -+ struct ipcomphdr *compp; -+ } ipcompstuff; -+ } protostuff; -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ __u8 natt_type; -+ __u16 natt_sport; -+ __u16 natt_dport; -+ int natt_len; -+#endif -+}; -+ -+extern int -+#ifdef PROTO_HANDLER_SINGLE_PARM -+ipsec_rcv(struct sk_buff *skb); -+#else /* PROTO_HANDLER_SINGLE_PARM */ -+ipsec_rcv(struct sk_buff *skb, -+#ifdef NET_21 -+ unsigned short xlen); -+#else /* NET_21 */ -+ struct device *dev, -+ struct options *opt, -+ __u32 daddr, -+ unsigned short len, -+ __u32 saddr, -+ int redo, -+ struct inet_protocol *protocol); -+#endif /* NET_21 */ -+#endif /* PROTO_HANDLER_SINGLE_PARM */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int debug_rcv; -+#endif /* CONFIG_IPSEC_DEBUG */ -+#define ipsec_rcv_dmp(_x,_y, _z) if (debug_rcv && sysctl_ipsec_debug_verbose) ipsec_dmp(_x,_y,_z) -+ -+extern int sysctl_ipsec_inbound_policy_check; -+#endif /* __KERNEL__ */ -+ -+#endif /* IPSEC_RCV_H */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.21 2004/04/06 02:49:08 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.20 2004/04/05 19:55:06 mcr -+ * Moved from linux/include/freeswan/ipsec_rcv.h,v -+ * -+ * Revision 1.19 2003/12/15 18:13:09 mcr -+ * when compiling with NAT traversal, don't assume that the -+ * kernel has been patched, unless CONFIG_IPSEC_NAT_NON_ESP -+ * is set. -+ * -+ * Revision 1.18 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.17 2002/09/03 16:32:32 mcr -+ * definitions of ipsec_birth_reply. -+ * -+ * Revision 1.16 2002/05/14 02:36:00 rgb -+ * Change references to _TDB to _IPSA. -+ * -+ * Revision 1.15 2002/04/24 07:36:47 mcr -+ * Moved from ./klips/net/ipsec/ipsec_rcv.h,v -+ * -+ * Revision 1.14 2001/09/07 22:15:48 rgb -+ * Fix for removal of transport layer protocol handler arg in 2.4.4. -+ * -+ * Revision 1.13 2001/06/14 19:35:09 rgb -+ * Update copyright date. -+ * -+ * Revision 1.12 2001/03/16 07:36:44 rgb -+ * Fixed #endif comment to sate compiler. -+ * -+ * Revision 1.11 2000/09/21 04:34:21 rgb -+ * Moved declaration of sysctl_ipsec_inbound_policy_check outside -+ * CONFIG_IPSEC_DEBUG. (MB) -+ * -+ * Revision 1.10 2000/09/18 02:36:10 rgb -+ * Exported sysctl_ipsec_inbound_policy_check for skb_decompress(). -+ * -+ * Revision 1.9 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.8 1999/11/18 04:09:19 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.7 1999/05/25 01:45:37 rgb -+ * Fix version macros for 2.0.x as a module. -+ * -+ * Revision 1.6 1999/05/08 21:24:27 rgb -+ * Add includes for 2.2.x include into net/ipv4/protocol.c -+ * -+ * Revision 1.5 1999/05/05 22:02:32 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.4 1999/04/11 00:28:59 henry -+ * GPL boilerplate -+ * -+ * Revision 1.3 1999/04/06 04:54:27 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.2 1999/01/22 20:06:59 rgb -+ * Fixed cut-and-paste error from ipsec_esp.h. -+ * -+ * Revision 1.1 1999/01/21 20:29:12 rgb -+ * Converted from transform switching to algorithm switching. -+ * -+ * Log: ipsec_esp.h,v -+ * Revision 1.4 1998/08/12 00:07:32 rgb -+ * Added data structures for new xforms: null, {,3}dessha1. -+ * -+ * Revision 1.3 1998/07/14 15:57:01 rgb -+ * Add #ifdef __KERNEL__ to protect kernel-only structures. -+ * -+ * Revision 1.2 1998/06/25 19:33:46 rgb -+ * Add prototype for protocol receive function. -+ * Rearrange for more logical layout. -+ * -+ * Revision 1.1 1998/06/18 21:27:45 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.6 1998/06/05 02:28:08 rgb -+ * Minor comment fix. -+ * -+ * Revision 1.5 1998/05/27 22:34:00 rgb -+ * Changed structures to accomodate key separation. -+ * -+ * Revision 1.4 1998/05/18 22:28:43 rgb -+ * Disable key printing facilities from /proc/net/ipsec_*. -+ * -+ * Revision 1.3 1998/04/21 21:29:07 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.2 1998/04/12 22:03:20 rgb -+ * Updated ESP-3DES-HMAC-MD5-96, -+ * ESP-DES-HMAC-MD5-96, -+ * AH-HMAC-MD5-96, -+ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository -+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts. -+ * -+ * Fixed eroute references in /proc/net/ipsec*. -+ * -+ * Started to patch module unloading memory leaks in ipsec_netlink and -+ * radij tree unloading. -+ * -+ * Revision 1.1 1998/04/09 03:06:00 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:02 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.5 1997/06/03 04:24:48 ji -+ * Added ESP-3DES-MD5-96 transform. -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * Added definitions for new ESP transforms. -+ * -+ * Revision 0.3 1996/11/20 14:35:48 ji -+ * Minor Cleanup. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ -+ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_sa.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,341 @@ -+/* -+ * @(#) Definitions of IPsec Security Association (ipsec_sa) -+ * -+ * Copyright (C) 2001, 2002, 2003 -+ * Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ * This file derived from ipsec_xform.h on 2001/9/18 by mcr. -+ * -+ */ -+ -+/* -+ * This file describes the IPsec Security Association Structure. -+ * -+ * This structure keeps track of a single transform that may be done -+ * to a set of packets. It can describe applying the transform or -+ * apply the reverse. (e.g. compression vs expansion). However, it -+ * only describes one at a time. To describe both, two structures would -+ * be used, but since the sides of the transform are performed -+ * on different machines typically it is usual to have only one side -+ * of each association. -+ * -+ */ -+ -+#ifndef _IPSEC_SA_H_ -+ -+#ifdef __KERNEL__ -+#include "ipsec_stats.h" -+#include "ipsec_life.h" -+#include "ipsec_eroute.h" -+#endif /* __KERNEL__ */ -+#include "ipsec_param.h" -+ -+ -+/* SAs are held in a table. -+ * Entries in this table are referenced by IPsecSAref_t values. -+ * IPsecSAref_t values are conceptually subscripts. Because -+ * we want to allocate the table piece-meal, the subscripting -+ * is implemented with two levels, a bit like paged virtual memory. -+ * This representation mechanism is known as an Iliffe Vector. -+ * -+ * The Main table (AKA the refTable) consists of 2^IPSEC_SA_REF_MAINTABLE_IDX_WIDTH -+ * pointers to subtables. -+ * Each subtable has 2^IPSEC_SA_REF_SUBTABLE_IDX_WIDTH entries, each of which -+ * is a pointer to an SA. -+ * -+ * An IPsecSAref_t contains either an exceptional value (signified by the -+ * high-order bit being on) or a reference to a table entry. A table entry -+ * reference has the subtable subscript in the low-order -+ * IPSEC_SA_REF_SUBTABLE_IDX_WIDTH bits and the Main table subscript -+ * in the next lowest IPSEC_SA_REF_MAINTABLE_IDX_WIDTH bits. -+ * -+ * The Maintable entry for an IPsecSAref_t x, a pointer to its subtable, is -+ * IPsecSAref2table(x). It is of type struct IPsecSArefSubTable *. -+ * -+ * The pointer to the SA for x is IPsecSAref2SA(x). It is of type -+ * struct ipsec_sa*. The macro definition clearly shows the two-level -+ * access needed to find the SA pointer. -+ * -+ * The Maintable is allocated when IPsec is initialized. -+ * Each subtable is allocated when needed, but the first is allocated -+ * when IPsec is initialized. -+ * -+ * IPsecSAref_t is designed to be smaller than an NFmark so that -+ * they can be stored in NFmarks and still leave a few bits for other -+ * purposes. The spare bits are in the low order of the NFmark -+ * but in the high order of the IPsecSAref_t, so conversion is required. -+ * We pick the upper bits of NFmark on the theory that they are less likely to -+ * interfere with more pedestrian uses of nfmark. -+ */ -+ -+ -+typedef unsigned short int IPsecRefTableUnusedCount; -+ -+#define IPSEC_SA_REF_TABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH) -+ -+#ifdef __KERNEL__ -+#if ((IPSEC_SA_REF_TABLE_IDX_WIDTH - (1 + IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)) < 0) -+#error "IPSEC_SA_REF_TABLE_IDX_WIDTH("IPSEC_SA_REF_TABLE_IDX_WIDTH") MUST be < 1 + IPSEC_SA_REF_MAINTABLE_IDX_WIDTH("IPSEC_SA_REF_MAINTABLE_IDX_WIDTH")" -+#endif -+ -+#define IPSEC_SA_REF_SUBTABLE_IDX_WIDTH (IPSEC_SA_REF_TABLE_IDX_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH) -+ -+#define IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_MAINTABLE_IDX_WIDTH) -+#define IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) -+ -+#ifdef CONFIG_NETFILTER -+#define IPSEC_SA_REF_HOST_FIELD(x) ((struct sk_buff*)(x))->nfmark -+#define IPSEC_SA_REF_HOST_FIELD_TYPE typeof(IPSEC_SA_REF_HOST_FIELD(NULL)) -+#else /* CONFIG_NETFILTER */ -+/* just make it work for now, it doesn't matter, since there is no nfmark */ -+#define IPSEC_SA_REF_HOST_FIELD_TYPE unsigned long -+#endif /* CONFIG_NETFILTER */ -+#define IPSEC_SA_REF_HOST_FIELD_WIDTH (8 * sizeof(IPSEC_SA_REF_HOST_FIELD_TYPE)) -+#define IPSEC_SA_REF_FIELD_WIDTH (8 * sizeof(IPsecSAref_t)) -+ -+#define IPSEC_SA_REF_MASK (IPSEC_SAREF_NULL >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH)) -+#define IPSEC_SA_REF_TABLE_MASK ((IPSEC_SAREF_NULL >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)) << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) -+#define IPSEC_SA_REF_ENTRY_MASK (IPSEC_SAREF_NULL >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_SUBTABLE_IDX_WIDTH)) -+ -+#define IPsecSAref2table(x) (((x) & IPSEC_SA_REF_TABLE_MASK) >> IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) -+#define IPsecSAref2entry(x) ((x) & IPSEC_SA_REF_ENTRY_MASK) -+#define IPsecSArefBuild(x,y) (((x) << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) + (y)) -+ -+#define IPsecSAref2SA(x) (ipsec_sadb.refTable[IPsecSAref2table(x)]->entry[IPsecSAref2entry(x)]) -+#define IPsecSA2SAref(x) ((x)->ips_ref) -+ -+#define EMT_INBOUND 0x01 /* SA direction, 1=inbound */ -+ -+/* 'struct ipsec_sa' should be 64bit aligned when allocated. */ -+struct ipsec_sa -+{ -+ IPsecSAref_t ips_ref; /* reference table entry number */ -+ atomic_t ips_refcount; /* reference count for this struct */ -+ struct ipsec_sa *ips_hnext; /* next in hash chain */ -+ struct ipsec_sa *ips_inext; /* pointer to next xform */ -+ struct ipsec_sa *ips_onext; /* pointer to prev xform */ -+ -+ struct ifnet *ips_rcvif; /* related rcv encap interface */ -+ -+ ip_said ips_said; /* SA ID */ -+ -+ __u32 ips_seq; /* seq num of msg that initiated this SA */ -+ __u32 ips_pid; /* PID of process that initiated this SA */ -+ __u8 ips_authalg; /* auth algorithm for this SA */ -+ __u8 ips_encalg; /* enc algorithm for this SA */ -+ -+ struct ipsec_stats ips_errs; -+ -+ __u8 ips_replaywin; /* replay window size */ -+ __u8 ips_state; /* state of SA */ -+ __u32 ips_replaywin_lastseq; /* last pkt sequence num */ -+ __u64 ips_replaywin_bitmap; /* bitmap of received pkts */ -+ __u32 ips_replaywin_maxdiff; /* max pkt sequence difference */ -+ -+ __u32 ips_flags; /* generic xform flags */ -+ -+ -+ struct ipsec_lifetimes ips_life; /* lifetime records */ -+ -+ /* selector information */ -+ __u8 ips_transport_protocol; /* protocol for this SA, if ports are involved */ -+ struct sockaddr*ips_addr_s; /* src sockaddr */ -+ struct sockaddr*ips_addr_d; /* dst sockaddr */ -+ struct sockaddr*ips_addr_p; /* proxy sockaddr */ -+ __u16 ips_addr_s_size; -+ __u16 ips_addr_d_size; -+ __u16 ips_addr_p_size; -+ ip_address ips_flow_s; -+ ip_address ips_flow_d; -+ ip_address ips_mask_s; -+ ip_address ips_mask_d; -+ -+ __u16 ips_key_bits_a; /* size of authkey in bits */ -+ __u16 ips_auth_bits; /* size of authenticator in bits */ -+ __u16 ips_key_bits_e; /* size of enckey in bits */ -+ __u16 ips_iv_bits; /* size of IV in bits */ -+ __u8 ips_iv_size; -+ __u16 ips_key_a_size; -+ __u16 ips_key_e_size; -+ -+ caddr_t ips_key_a; /* authentication key */ -+ caddr_t ips_key_e; /* encryption key */ -+ caddr_t ips_iv; /* Initialisation Vector */ -+ -+ struct ident ips_ident_s; /* identity src */ -+ struct ident ips_ident_d; /* identity dst */ -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+ __u16 ips_comp_adapt_tries; /* ipcomp self-adaption tries */ -+ __u16 ips_comp_adapt_skip; /* ipcomp self-adaption to-skip */ -+ __u64 ips_comp_ratio_cbytes; /* compressed bytes */ -+ __u64 ips_comp_ratio_dbytes; /* decompressed (or uncompressed) bytes */ -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ __u8 ips_natt_type; -+ __u8 ips_natt_reserved[3]; -+ __u16 ips_natt_sport; -+ __u16 ips_natt_dport; -+ -+ struct sockaddr *ips_natt_oa; -+ __u16 ips_natt_oa_size; -+ __u16 ips_natt_reserved2; -+#endif -+ -+#if 0 -+ __u32 ips_sens_dpd; -+ __u8 ips_sens_sens_level; -+ __u8 ips_sens_sens_len; -+ __u64* ips_sens_sens_bitmap; -+ __u8 ips_sens_integ_level; -+ __u8 ips_sens_integ_len; -+ __u64* ips_sens_integ_bitmap; -+#endif -+ struct ipsec_alg_enc *ips_alg_enc; -+ struct ipsec_alg_auth *ips_alg_auth; -+ IPsecSAref_t ips_ref_rel; -+}; -+ -+struct IPsecSArefSubTable -+{ -+ struct ipsec_sa* entry[IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES]; -+}; -+ -+struct ipsec_sadb { -+ struct IPsecSArefSubTable* refTable[IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES]; -+ IPsecSAref_t refFreeList[IPSEC_SA_REF_FREELIST_NUM_ENTRIES]; -+ int refFreeListHead; -+ int refFreeListTail; -+ IPsecSAref_t refFreeListCont; -+ IPsecSAref_t said_hash[SADB_HASHMOD]; -+ spinlock_t sadb_lock; -+}; -+ -+extern struct ipsec_sadb ipsec_sadb; -+ -+extern int ipsec_SAref_recycle(void); -+extern int ipsec_SArefSubTable_alloc(unsigned table); -+extern int ipsec_saref_freelist_init(void); -+extern int ipsec_sadb_init(void); -+extern struct ipsec_sa *ipsec_sa_alloc(int*error); /* pass in error var by pointer */ -+extern IPsecSAref_t ipsec_SAref_alloc(int*erorr); /* pass in error var by pointer */ -+extern int ipsec_sa_free(struct ipsec_sa* ips); -+extern int ipsec_sa_put(struct ipsec_sa *ips); -+extern int ipsec_sa_add(struct ipsec_sa *ips); -+extern int ipsec_sa_del(struct ipsec_sa *ips); -+extern int ipsec_sa_delchain(struct ipsec_sa *ips); -+extern int ipsec_sadb_cleanup(__u8 proto); -+extern int ipsec_sadb_free(void); -+extern int ipsec_sa_wipe(struct ipsec_sa *ips); -+#endif /* __KERNEL__ */ -+ -+enum ipsec_direction { -+ ipsec_incoming = 1, -+ ipsec_outgoing = 2 -+}; -+ -+#define _IPSEC_SA_H_ -+#endif /* _IPSEC_SA_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.19 2004/04/05 19:55:06 mcr -+ * Moved from linux/include/freeswan/ipsec_sa.h,v -+ * -+ * Revision 1.18 2004/04/05 19:41:05 mcr -+ * merged alg-branch code. -+ * -+ * Revision 1.17.2.1 2003/12/22 15:25:52 jjo -+ * . Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.17 2003/12/10 01:20:06 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.16 2003/10/31 02:27:05 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.15.4.1 2003/10/29 01:10:19 mcr -+ * elimited "struct sa_id" -+ * -+ * Revision 1.15 2003/05/11 00:53:09 mcr -+ * IPsecSAref_t and macros were moved to freeswan.h. -+ * -+ * Revision 1.14 2003/02/12 19:31:55 rgb -+ * Fixed bug in "file seen" machinery. -+ * Updated copyright year. -+ * -+ * Revision 1.13 2003/01/30 02:31:52 rgb -+ * -+ * Re-wrote comments describing SAref system for accuracy. -+ * Rename SAref table macro names for clarity. -+ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. -+ * Transmit error code through to caller from callee for better diagnosis of problems. -+ * Enclose all macro arguments in parens to avoid any possible obscrure bugs. -+ * -+ * Revision 1.12 2002/10/07 18:31:19 rgb -+ * Change comment to reflect the flexible nature of the main and sub-table widths. -+ * Added a counter for the number of unused entries in each subtable. -+ * Further break up host field type macro to host field. -+ * Move field width sanity checks to ipsec_sa.c -+ * Define a mask for an entire saref. -+ * -+ * Revision 1.11 2002/09/20 15:40:33 rgb -+ * Re-write most of the SAref macros and types to eliminate any pointer references to Entrys. -+ * Fixed SAref/nfmark macros. -+ * Rework saref freeslist. -+ * Place all ipsec sadb globals into one struct. -+ * Restrict some bits to kernel context for use to klips utils. -+ * -+ * Revision 1.10 2002/09/20 05:00:34 rgb -+ * Update copyright date. -+ * -+ * Revision 1.9 2002/09/17 17:19:29 mcr -+ * make it compile even if there is no netfilter - we lost -+ * functionality, but it works, especially on 2.2. -+ * -+ * Revision 1.8 2002/07/28 22:59:53 mcr -+ * clarified/expanded one comment. -+ * -+ * Revision 1.7 2002/07/26 08:48:31 rgb -+ * Added SA ref table code. -+ * -+ * Revision 1.6 2002/05/31 17:27:48 rgb -+ * Comment fix. -+ * -+ * Revision 1.5 2002/05/27 18:55:03 rgb -+ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT. -+ * -+ * Revision 1.4 2002/05/23 07:13:36 rgb -+ * Convert "usecount" to "refcount" to remove ambiguity. -+ * -+ * Revision 1.3 2002/04/24 07:36:47 mcr -+ * Moved from ./klips/net/ipsec/ipsec_sa.h,v -+ * -+ * Revision 1.2 2001/11/26 09:16:15 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:24:58 mcr -+ * struct tdb -> struct ipsec_sa. -+ * sa(tdb) manipulation functions renamed and moved to ipsec_sa.c -+ * ipsec_xform.c removed. header file still contains useful things. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_sha1.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,79 @@ -+/* -+ * RCSID $Id$ -+ */ -+ -+/* -+ * Here is the original comment from the distribution: -+ -+SHA-1 in C -+By Steve Reid -+100% Public Domain -+ -+ * Adapted for use by the IPSEC code by John Ioannidis -+ */ -+ -+ -+#ifndef _IPSEC_SHA1_H_ -+#define _IPSEC_SHA1_H_ -+ -+typedef struct -+{ -+ __u32 state[5]; -+ __u32 count[2]; -+ __u8 buffer[64]; -+} SHA1_CTX; -+ -+void SHA1Transform(__u32 state[5], __u8 buffer[64]); -+void SHA1Init(void *context); -+void SHA1Update(void *context, unsigned char *data, __u32 len); -+void SHA1Final(unsigned char digest[20], void *context); -+ -+ -+#endif /* _IPSEC_SHA1_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.8 2004/04/05 19:55:07 mcr -+ * Moved from linux/include/freeswan/ipsec_sha1.h,v -+ * -+ * Revision 1.7 2002/09/10 01:45:09 mcr -+ * changed type of MD5_CTX and SHA1_CTX to void * so that -+ * the function prototypes would match, and could be placed -+ * into a pointer to a function. -+ * -+ * Revision 1.6 2002/04/24 07:36:47 mcr -+ * Moved from ./klips/net/ipsec/ipsec_sha1.h,v -+ * -+ * Revision 1.5 1999/12/13 13:59:13 rgb -+ * Quick fix to argument size to Update bugs. -+ * -+ * Revision 1.4 1999/12/07 18:16:23 rgb -+ * Fixed comments at end of #endif lines. -+ * -+ * Revision 1.3 1999/04/06 04:54:27 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.2 1998/11/30 13:22:54 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.1 1998/06/18 21:27:50 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.2 1998/04/23 20:54:05 rgb -+ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when -+ * verified. -+ * -+ * Revision 1.1 1998/04/09 03:04:21 henry -+ * sources moved up from linux/net/ipsec -+ * these two include files modified not to include others except in kernel -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:04 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * New transform -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_stats.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,75 @@ -+/* -+ * @(#) definition of ipsec_stats structure -+ * -+ * Copyright (C) 2001 Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ */ -+ -+/* -+ * This file describes the errors/statistics that FreeSWAN collects. -+ */ -+ -+#ifndef _IPSEC_STATS_H_ -+ -+struct ipsec_stats { -+ __u32 ips_alg_errs; /* number of algorithm errors */ -+ __u32 ips_auth_errs; /* # of authentication errors */ -+ __u32 ips_encsize_errs; /* # of encryption size errors*/ -+ __u32 ips_encpad_errs; /* # of encryption pad errors*/ -+ __u32 ips_replaywin_errs; /* # of pkt sequence errors */ -+}; -+ -+extern int ipsec_snprintf(char * buf, ssize_t size, const char *fmt, ...); -+ -+#define _IPSEC_STATS_H_ -+#endif /* _IPSEC_STATS_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.6 2004/04/05 19:55:07 mcr -+ * Moved from linux/include/freeswan/ipsec_stats.h,v -+ * -+ * Revision 1.5 2004/04/05 19:41:05 mcr -+ * merged alg-branch code. -+ * -+ * Revision 1.4 2004/03/28 20:27:19 paul -+ * Included tested and confirmed fixes mcr made and dhr verified for -+ * snprint statements. Changed one other snprintf to use ipsec_snprintf -+ * so it wouldnt break compatibility with 2.0/2.2 kernels. Verified with -+ * dhr. (thanks dhr!) -+ * -+ * Revision 1.4 2004/03/24 01:58:31 mcr -+ * sprintf->snprintf for formatting into proc buffer. -+ * -+ * Revision 1.3.34.1 2004/04/05 04:30:46 mcr -+ * patches for alg-branch to compile/work with 2.x openswan -+ * -+ * Revision 1.3 2002/04/24 07:36:47 mcr -+ * Moved from ./klips/net/ipsec/ipsec_stats.h,v -+ * -+ * Revision 1.2 2001/11/26 09:16:16 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:27:00 mcr -+ * statistics moved to seperate structure. -+ * -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_tunnel.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,265 @@ -+/* -+ * IPSEC tunneling code -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+ -+#ifdef NET_21 -+# define DEV_QUEUE_XMIT(skb, device, pri) {\ -+ skb->dev = device; \ -+ neigh_compat_output(skb); \ -+ /* skb->dst->output(skb); */ \ -+ } -+# define ICMP_SEND(skb_in, type, code, info, dev) \ -+ icmp_send(skb_in, type, code, htonl(info)) -+# define IP_SEND(skb, dev) \ -+ ip_send(skb); -+#else /* NET_21 */ -+# define DEV_QUEUE_XMIT(skb, device, pri) {\ -+ dev_queue_xmit(skb, device, pri); \ -+ } -+# define ICMP_SEND(skb_in, type, code, info, dev) \ -+ icmp_send(skb_in, type, code, info, dev) -+# define IP_SEND(skb, dev) \ -+ if(ntohs(iph->tot_len) > physmtu) { \ -+ ip_fragment(NULL, skb, dev, 0); \ -+ ipsec_kfree_skb(skb); \ -+ } else { \ -+ dev_queue_xmit(skb, dev, SOPRI_NORMAL); \ -+ } -+#endif /* NET_21 */ -+ -+ -+/* -+ * Heavily based on drivers/net/new_tunnel.c. Lots -+ * of ideas also taken from the 2.1.x version of drivers/net/shaper.c -+ */ -+ -+struct ipsectunnelconf -+{ -+ __u32 cf_cmd; -+ union -+ { -+ char cfu_name[12]; -+ } cf_u; -+#define cf_name cf_u.cfu_name -+}; -+ -+#define IPSEC_SET_DEV (SIOCDEVPRIVATE) -+#define IPSEC_DEL_DEV (SIOCDEVPRIVATE + 1) -+#define IPSEC_CLR_DEV (SIOCDEVPRIVATE + 2) -+ -+#ifdef __KERNEL__ -+#include -+#ifndef KERNEL_VERSION -+# define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -+#endif -+struct ipsecpriv -+{ -+ struct sk_buff_head sendq; -+ struct device *dev; -+ struct wait_queue *wait_queue; -+ char locked; -+ int (*hard_start_xmit) (struct sk_buff *skb, -+ struct device *dev); -+ int (*hard_header) (struct sk_buff *skb, -+ struct device *dev, -+ unsigned short type, -+ void *daddr, -+ void *saddr, -+ unsigned len); -+#ifdef NET_21 -+ int (*rebuild_header)(struct sk_buff *skb); -+#else /* NET_21 */ -+ int (*rebuild_header)(void *buff, struct device *dev, -+ unsigned long raddr, struct sk_buff *skb); -+#endif /* NET_21 */ -+ int (*set_mac_address)(struct device *dev, void *addr); -+#ifndef NET_21 -+ void (*header_cache_bind)(struct hh_cache **hhp, struct device *dev, -+ unsigned short htype, __u32 daddr); -+#endif /* !NET_21 */ -+ void (*header_cache_update)(struct hh_cache *hh, struct device *dev, unsigned char * haddr); -+ struct net_device_stats *(*get_stats)(struct device *dev); -+ struct net_device_stats mystats; -+ int mtu; /* What is the desired MTU? */ -+}; -+ -+extern char ipsec_tunnel_c_version[]; -+ -+extern struct device *ipsecdevices[IPSEC_NUM_IF]; -+ -+int ipsec_tunnel_init_devices(void); -+ -+/* void */ int ipsec_tunnel_cleanup_devices(void); -+ -+extern /* void */ int ipsec_init(void); -+ -+extern int ipsec_tunnel_start_xmit(struct sk_buff *skb, struct device *dev); -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int debug_tunnel; -+extern int sysctl_ipsec_debug_verbose; -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif /* __KERNEL__ */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+#define DB_TN_INIT 0x0001 -+#define DB_TN_PROCFS 0x0002 -+#define DB_TN_XMIT 0x0010 -+#define DB_TN_OHDR 0x0020 -+#define DB_TN_CROUT 0x0040 -+#define DB_TN_OXFS 0x0080 -+#define DB_TN_REVEC 0x0100 -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.29 2004/04/05 19:55:07 mcr -+ * Moved from linux/include/freeswan/ipsec_tunnel.h,v -+ * -+ * Revision 1.28 2003/06/24 20:22:32 mcr -+ * added new global: ipsecdevices[] so that we can keep track of -+ * the ipsecX devices. They will be referenced with dev_hold(), -+ * so 2.2 may need this as well. -+ * -+ * Revision 1.27 2003/04/03 17:38:09 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * -+ * Revision 1.26 2003/02/12 19:32:20 rgb -+ * Updated copyright year. -+ * -+ * Revision 1.25 2002/05/27 18:56:07 rgb -+ * Convert to dynamic ipsec device allocation. -+ * -+ * Revision 1.24 2002/04/24 07:36:48 mcr -+ * Moved from ./klips/net/ipsec/ipsec_tunnel.h,v -+ * -+ * Revision 1.23 2001/11/06 19:50:44 rgb -+ * Moved IP_SEND, ICMP_SEND, DEV_QUEUE_XMIT macros to ipsec_tunnel.h for -+ * use also by pfkey_v2_parser.c -+ * -+ * Revision 1.22 2001/09/15 16:24:05 rgb -+ * Re-inject first and last HOLD packet when an eroute REPLACE is done. -+ * -+ * Revision 1.21 2001/06/14 19:35:10 rgb -+ * Update copyright date. -+ * -+ * Revision 1.20 2000/09/15 11:37:02 rgb -+ * Merge in heavily modified Svenning Soerensen's -+ * IPCOMP zlib deflate code. -+ * -+ * Revision 1.19 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.18 2000/07/28 13:50:54 rgb -+ * Changed enet_statistics to net_device_stats and added back compatibility -+ * for pre-2.1.19. -+ * -+ * Revision 1.17 1999/11/19 01:12:15 rgb -+ * Purge unneeded proc_info prototypes, now that static linking uses -+ * dynamic proc_info registration. -+ * -+ * Revision 1.16 1999/11/18 18:51:00 rgb -+ * Changed all device registrations for static linking to -+ * dynamic to reduce the number and size of patches. -+ * -+ * Revision 1.15 1999/11/18 04:14:21 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * Added CONFIG_PROC_FS compiler directives in case it is shut off. -+ * Added Marc Boucher's 2.3.25 proc patches. -+ * -+ * Revision 1.14 1999/05/25 02:50:10 rgb -+ * Fix kernel version macros for 2.0.x static linking. -+ * -+ * Revision 1.13 1999/05/25 02:41:06 rgb -+ * Add ipsec_klipsdebug support for static linking. -+ * -+ * Revision 1.12 1999/05/05 22:02:32 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.11 1999/04/29 15:19:50 rgb -+ * Add return values to init and cleanup functions. -+ * -+ * Revision 1.10 1999/04/16 16:02:39 rgb -+ * Bump up macro to 4 ipsec I/Fs. -+ * -+ * Revision 1.9 1999/04/15 15:37:25 rgb -+ * Forward check changes from POST1_00 branch. -+ * -+ * Revision 1.5.2.1 1999/04/02 04:26:14 rgb -+ * Backcheck from HEAD, pre1.0. -+ * -+ * Revision 1.8 1999/04/11 00:29:01 henry -+ * GPL boilerplate -+ * -+ * Revision 1.7 1999/04/06 04:54:28 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.6 1999/03/31 05:44:48 rgb -+ * Keep PMTU reduction private. -+ * -+ * Revision 1.5 1999/02/10 22:31:20 rgb -+ * Change rebuild_header member to reflect generality of link layer. -+ * -+ * Revision 1.4 1998/12/01 13:22:04 rgb -+ * Added support for debug printing of version info. -+ * -+ * Revision 1.3 1998/07/29 20:42:46 rgb -+ * Add a macro for clearing all tunnel devices. -+ * Rearrange structures and declarations for sharing with userspace. -+ * -+ * Revision 1.2 1998/06/25 20:01:45 rgb -+ * Make prototypes available for ipsec_init and ipsec proc_dir_entries -+ * for static linking. -+ * -+ * Revision 1.1 1998/06/18 21:27:50 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.3 1998/05/18 21:51:50 rgb -+ * Added macros for num of I/F's and a procfs debug switch. -+ * -+ * Revision 1.2 1998/04/21 21:29:09 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.1 1998/04/09 03:06:13 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:05 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.5 1997/06/03 04:24:48 ji -+ * Added transport mode. -+ * Changed the way routing is done. -+ * Lots of bug fixes. -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:39:04 ji -+ * Minor cleanups. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_xform.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,254 @@ -+/* -+ * Definitions relevant to IPSEC transformations -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * COpyright (C) 2003 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef _IPSEC_XFORM_H_ -+ -+#include -+ -+#define XF_NONE 0 /* No transform set */ -+#define XF_IP4 1 /* IPv4 inside IPv4 */ -+#define XF_AHMD5 2 /* AH MD5 */ -+#define XF_AHSHA 3 /* AH SHA */ -+#define XF_ESP3DES 5 /* ESP DES3-CBC */ -+#define XF_AHHMACMD5 6 /* AH-HMAC-MD5 with opt replay prot */ -+#define XF_AHHMACSHA1 7 /* AH-HMAC-SHA1 with opt replay prot */ -+#define XF_ESP3DESMD5 9 /* triple DES, HMAC-MD-5, 128-bits of authentication */ -+#define XF_ESP3DESMD596 10 /* triple DES, HMAC-MD-5, 96-bits of authentication */ -+#define XF_ESPNULLMD596 12 /* NULL, HMAC-MD-5 with 96-bits of authentication */ -+#define XF_ESPNULLSHA196 13 /* NULL, HMAC-SHA-1 with 96-bits of authentication */ -+#define XF_ESP3DESSHA196 14 /* triple DES, HMAC-SHA-1, 96-bits of authentication */ -+#define XF_IP6 15 /* IPv6 inside IPv6 */ -+#define XF_COMPDEFLATE 16 /* IPCOMP deflate */ -+ -+#define XF_CLR 126 /* Clear SA table */ -+#define XF_DEL 127 /* Delete SA */ -+ -+/* IPsec AH transform values -+ * RFC 2407 -+ * draft-ietf-ipsec-doi-tc-mib-02.txt -+ */ -+ -+#define AH_NONE 0 -+#define AH_MD5 2 -+#define AH_SHA 3 -+/* draft-ietf-ipsec-ciph-aes-cbc-03.txt */ -+#define AH_SHA2_256 5 -+#define AH_SHA2_384 6 -+#define AH_SHA2_512 7 -+#define AH_RIPEMD 8 -+#define AH_MAX 15 -+ -+/* IPsec ESP transform values */ -+ -+#define ESP_NONE 0 -+#define ESP_DES 2 -+#define ESP_3DES 3 -+#define ESP_RC5 4 -+#define ESP_IDEA 5 -+#define ESP_CAST 6 -+#define ESP_BLOWFISH 7 -+#define ESP_3IDEA 8 -+#define ESP_RC4 10 -+#define ESP_NULL 11 -+#define ESP_AES 12 -+ -+/* as draft-ietf-ipsec-ciph-aes-cbc-02.txt */ -+#define ESP_MARS 249 -+#define ESP_RC6 250 -+#define ESP_SERPENT 252 -+#define ESP_TWOFISH 253 -+ -+/* IPCOMP transform values */ -+ -+#define IPCOMP_NONE 0 -+#define IPCOMP_OUI 1 -+#define IPCOMP_DEFLAT 2 -+#define IPCOMP_LZS 3 -+#define IPCOMP_V42BIS 4 -+ -+#define XFT_AUTH 0x0001 -+#define XFT_CONF 0x0100 -+ -+/* available if CONFIG_IPSEC_DEBUG is defined */ -+#define DB_XF_INIT 0x0001 -+ -+#define PROTO2TXT(x) \ -+ (x) == IPPROTO_AH ? "AH" : \ -+ (x) == IPPROTO_ESP ? "ESP" : \ -+ (x) == IPPROTO_IPIP ? "IPIP" : \ -+ (x) == IPPROTO_COMP ? "COMP" : \ -+ "UNKNOWN_proto" -+static inline const char *enc_name_id (unsigned id) { -+ static char buf[16]; -+ snprintf(buf, sizeof(buf), "_ID%d", id); -+ return buf; -+} -+static inline const char *auth_name_id (unsigned id) { -+ static char buf[16]; -+ snprintf(buf, sizeof(buf), "_ID%d", id); -+ return buf; -+} -+#define IPS_XFORM_NAME(x) \ -+ PROTO2TXT((x)->ips_said.proto), \ -+ (x)->ips_said.proto == IPPROTO_COMP ? \ -+ ((x)->ips_encalg == SADB_X_CALG_DEFLATE ? \ -+ "_DEFLATE" : "_UNKNOWN_comp") : \ -+ (x)->ips_encalg == ESP_NONE ? "" : \ -+ (x)->ips_encalg == ESP_3DES ? "_3DES" : \ -+ (x)->ips_encalg == ESP_AES ? "_AES" : \ -+ (x)->ips_encalg == ESP_SERPENT ? "_SERPENT" : \ -+ (x)->ips_encalg == ESP_TWOFISH ? "_TWOFISH" : \ -+ enc_name_id(x->ips_encalg)/* "_UNKNOWN_encr" */, \ -+ (x)->ips_authalg == AH_NONE ? "" : \ -+ (x)->ips_authalg == AH_MD5 ? "_HMAC_MD5" : \ -+ (x)->ips_authalg == AH_SHA ? "_HMAC_SHA1" : \ -+ (x)->ips_authalg == AH_SHA2_256 ? "_HMAC_SHA2_256" : \ -+ (x)->ips_authalg == AH_SHA2_384 ? "_HMAC_SHA2_384" : \ -+ (x)->ips_authalg == AH_SHA2_512 ? "_HMAC_SHA2_512" : \ -+ auth_name_id(x->ips_authalg) /* "_UNKNOWN_auth" */ \ -+ -+#ifdef __KERNEL__ -+struct ipsec_rcv_state; -+struct ipsec_xmit_state; -+ -+struct xform_functions { -+ enum ipsec_rcv_value (*rcv_checks)(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb); -+ enum ipsec_rcv_value (*rcv_decrypt)(struct ipsec_rcv_state *irs); -+ -+ enum ipsec_rcv_value (*rcv_setup_auth)(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb, -+ __u32 *replay, -+ unsigned char **authenticator); -+ enum ipsec_rcv_value (*rcv_calc_auth)(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb); -+ -+ enum ipsec_xmit_value (*xmit_setup)(struct ipsec_xmit_state *ixs); -+ enum ipsec_xmit_value (*xmit_encrypt)(struct ipsec_xmit_state *ixs); -+ -+ enum ipsec_xmit_value (*xmit_setup_auth)(struct ipsec_xmit_state *ixs, -+ struct sk_buff *skb, -+ __u32 *replay, -+ unsigned char **authenticator); -+ enum ipsec_xmit_value (*xmit_calc_auth)(struct ipsec_xmit_state *ixs, -+ struct sk_buff *skb); -+ int xmit_headroom; -+ int xmit_needtailroom; -+}; -+ -+#endif /* __KERNEL__ */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern void ipsec_dmp(char *s, caddr_t bb, int len); -+#else /* CONFIG_IPSEC_DEBUG */ -+#define ipsec_dmp(_x, _y, _z) -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ -+#define _IPSEC_XFORM_H_ -+#endif /* _IPSEC_XFORM_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.40 2004/04/06 02:49:08 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.39 2004/04/05 19:55:07 mcr -+ * Moved from linux/include/freeswan/ipsec_xform.h,v -+ * -+ * Revision 1.38 2004/04/05 19:41:05 mcr -+ * merged alg-branch code. -+ * -+ * Revision 1.37 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.36.34.1 2003/12/22 15:25:52 jjo -+ * Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.36 2002/04/24 07:36:48 mcr -+ * Moved from ./klips/net/ipsec/ipsec_xform.h,v -+ * -+ * Revision 1.35 2001/11/26 09:23:51 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.33.2.1 2001/09/25 02:24:58 mcr -+ * struct tdb -> struct ipsec_sa. -+ * sa(tdb) manipulation functions renamed and moved to ipsec_sa.c -+ * ipsec_xform.c removed. header file still contains useful things. -+ * -+ * Revision 1.34 2001/11/06 19:47:17 rgb -+ * Changed lifetime_packets to uint32 from uint64. -+ * -+ * Revision 1.33 2001/09/08 21:13:34 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.32 2001/07/06 07:40:01 rgb -+ * Reformatted for readability. -+ * Added inbound policy checking fields for use with IPIP SAs. -+ * -+ * Revision 1.31 2001/06/14 19:35:11 rgb -+ * Update copyright date. -+ * -+ * Revision 1.30 2001/05/30 08:14:03 rgb -+ * Removed vestiges of esp-null transforms. -+ * -+ * Revision 1.29 2001/01/30 23:42:47 rgb -+ * Allow pfkey msgs from pid other than user context required for ACQUIRE -+ * and subsequent ADD or UDATE. -+ * -+ * Revision 1.28 2000/11/06 04:30:40 rgb -+ * Add Svenning's adaptive content compression. -+ * -+ * Revision 1.27 2000/09/19 00:38:25 rgb -+ * Fixed algorithm name bugs introduced for ipcomp. -+ * -+ * Revision 1.26 2000/09/17 21:36:48 rgb -+ * Added proto2txt macro. -+ * -+ * Revision 1.25 2000/09/17 18:56:47 rgb -+ * Added IPCOMP support. -+ * -+ * Revision 1.24 2000/09/12 19:34:12 rgb -+ * Defined XF_IP6 from Gerhard for ipv6 tunnel support. -+ * -+ * Revision 1.23 2000/09/12 03:23:14 rgb -+ * Cleaned out now unused tdb_xform and tdb_xdata members of struct tdb. -+ * -+ * Revision 1.22 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.21 2000/09/01 18:32:43 rgb -+ * Added (disabled) sensitivity members to tdb struct. -+ * -+ * Revision 1.20 2000/08/30 05:31:01 rgb -+ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst. -+ * Kill remainder of tdb_xform, tdb_xdata, xformsw. -+ * -+ * Revision 1.19 2000/08/01 14:51:52 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.18 2000/01/21 06:17:45 rgb -+ * Tidied up spacing. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_xmit.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,176 @@ -+/* -+ * IPSEC tunneling code -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#include "openswan/ipsec_sa.h" -+ -+enum ipsec_xmit_value -+{ -+ IPSEC_XMIT_STOLEN=2, -+ IPSEC_XMIT_PASS=1, -+ IPSEC_XMIT_OK=0, -+ IPSEC_XMIT_ERRMEMALLOC=-1, -+ IPSEC_XMIT_ESP_BADALG=-2, -+ IPSEC_XMIT_BADPROTO=-3, -+ IPSEC_XMIT_ESP_PUSHPULLERR=-4, -+ IPSEC_XMIT_BADLEN=-5, -+ IPSEC_XMIT_AH_BADALG=-6, -+ IPSEC_XMIT_SAIDNOTFOUND=-7, -+ IPSEC_XMIT_SAIDNOTLIVE=-8, -+ IPSEC_XMIT_REPLAYROLLED=-9, -+ IPSEC_XMIT_LIFETIMEFAILED=-10, -+ IPSEC_XMIT_CANNOTFRAG=-11, -+ IPSEC_XMIT_MSSERR=-12, -+ IPSEC_XMIT_ERRSKBALLOC=-13, -+ IPSEC_XMIT_ENCAPFAIL=-14, -+ IPSEC_XMIT_NODEV=-15, -+ IPSEC_XMIT_NOPRIVDEV=-16, -+ IPSEC_XMIT_NOPHYSDEV=-17, -+ IPSEC_XMIT_NOSKB=-18, -+ IPSEC_XMIT_NOIPV6=-19, -+ IPSEC_XMIT_NOIPOPTIONS=-20, -+ IPSEC_XMIT_TTLEXPIRED=-21, -+ IPSEC_XMIT_BADHHLEN=-22, -+ IPSEC_XMIT_PUSHPULLERR=-23, -+ IPSEC_XMIT_ROUTEERR=-24, -+ IPSEC_XMIT_RECURSDETECT=-25, -+ IPSEC_XMIT_IPSENDFAILURE=-26, -+ IPSEC_XMIT_ESPUDP=-27, -+ IPSEC_XMIT_ESPUDP_BADTYPE=-28, -+}; -+ -+struct ipsec_xmit_state -+{ -+ struct sk_buff *skb; /* working skb pointer */ -+ struct device *dev; /* working dev pointer */ -+ struct ipsecpriv *prv; /* Our device' private space */ -+ struct sk_buff *oskb; /* Original skb pointer */ -+ struct net_device_stats *stats; /* This device's statistics */ -+ struct iphdr *iph; /* Our new IP header */ -+ __u32 newdst; /* The other SG's IP address */ -+ __u32 orgdst; /* Original IP destination address */ -+ __u32 orgedst; /* 1st SG's IP address */ -+ __u32 newsrc; /* The new source SG's IP address */ -+ __u32 orgsrc; /* Original IP source address */ -+ __u32 innersrc; /* Innermost IP source address */ -+ int iphlen; /* IP header length */ -+ int pyldsz; /* upper protocol payload size */ -+ int headroom; -+ int tailroom; -+ int authlen; -+ int max_headroom; /* The extra header space needed */ -+ int max_tailroom; /* The extra stuffing needed */ -+ int ll_headroom; /* The extra link layer hard_header space needed */ -+ int tot_headroom; /* The total header space needed */ -+ int tot_tailroom; /* The totalstuffing needed */ -+ __u8 *saved_header; /* saved copy of the hard header */ -+ unsigned short sport, dport; -+ -+ struct sockaddr_encap matcher; /* eroute search key */ -+ struct eroute *eroute; -+ struct ipsec_sa *ipsp, *ipsq; /* ipsec_sa pointers */ -+ char sa_txt[SATOT_BUF]; -+ size_t sa_len; -+ int hard_header_stripped; /* has the hard header been removed yet? */ -+ int hard_header_len; -+ struct device *physdev; -+/* struct device *virtdev; */ -+ short physmtu; -+ short mtudiff; -+#ifdef NET_21 -+ struct rtable *route; -+#endif /* NET_21 */ -+ ip_said outgoing_said; -+#ifdef NET_21 -+ int pass; -+#endif /* NET_21 */ -+ int error; -+ uint32_t eroute_pid; -+ struct ipsec_sa ips; -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ uint8_t natt_type; -+ uint8_t natt_head; -+ uint16_t natt_sport; -+ uint16_t natt_dport; -+#endif -+}; -+ -+enum ipsec_xmit_value -+ipsec_xmit_sanity_check_dev(struct ipsec_xmit_state *ixs); -+ -+enum ipsec_xmit_value -+ipsec_xmit_sanity_check_skb(struct ipsec_xmit_state *ixs); -+ -+enum ipsec_xmit_value -+ipsec_xmit_encap_bundle(struct ipsec_xmit_state *ixs); -+ -+extern void ipsec_extract_ports(struct iphdr * iph, struct sockaddr_encap * er); -+ -+ -+extern int ipsec_xmit_trap_count; -+extern int ipsec_xmit_trap_sendcount; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int debug_tunnel; -+extern int sysctl_ipsec_debug_verbose; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#define debug_xmit debug_tunnel -+ -+#define ipsec_xmit_dmp(_x,_y, _z) if (debug_xmit && sysctl_ipsec_debug_verbose) ipsec_dmp(_x,_y,_z) -+ -+extern int sysctl_ipsec_icmp; -+extern int sysctl_ipsec_tos; -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.9 2004/04/06 02:49:08 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.8 2004/04/05 19:55:07 mcr -+ * Moved from linux/include/freeswan/ipsec_xmit.h,v -+ * -+ * Revision 1.7 2004/02/03 03:11:40 mcr -+ * new xmit type if the UDP encapsulation is wrong. -+ * -+ * Revision 1.6 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.5 2003/12/10 01:20:06 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.4 2003/12/06 16:37:04 mcr -+ * 1.4.7a X.509 patch applied. -+ * -+ * Revision 1.3 2003/10/31 02:27:05 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.2.4.2 2003/10/29 01:10:19 mcr -+ * elimited "struct sa_id" -+ * -+ * Revision 1.2.4.1 2003/09/21 13:59:38 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.2 2003/06/20 01:42:13 mcr -+ * added counters to measure how many ACQUIREs we send to pluto, -+ * and how many are successfully sent. -+ * -+ * Revision 1.1 2003/02/12 19:31:03 rgb -+ * Refactored from ipsec_tunnel.c -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/passert.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,64 @@ -+/* -+ * sanitize a string into a printable format. -+ * -+ * Copyright (C) 1998-2002 D. Hugh Redelmeier. -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+ -+#include "openswan.h" -+ -+/* our versions of assert: log result */ -+ -+#ifdef DEBUG -+ -+extern void passert_fail(const char *pred_str -+ , const char *file_str, unsigned long line_no) NEVER_RETURNS; -+ -+extern void pexpect_log(const char *pred_str -+ , const char *file_str, unsigned long line_no); -+ -+# define impossible() passert_fail("impossible", __FILE__, __LINE__) -+ -+extern void switch_fail(int n -+ , const char *file_str, unsigned long line_no) NEVER_RETURNS; -+ -+# define bad_case(n) switch_fail((int) n, __FILE__, __LINE__) -+ -+# define passert(pred) { \ -+ if (!(pred)) \ -+ passert_fail(#pred, __FILE__, __LINE__); \ -+ } -+ -+# define pexpect(pred) { \ -+ if (!(pred)) \ -+ pexpect_log(#pred, __FILE__, __LINE__); \ -+ } -+ -+/* assert that an err_t is NULL; evaluate exactly once */ -+# define happy(x) { \ -+ err_t ugh = x; \ -+ if (ugh != NULL) \ -+ passert_fail(ugh, __FILE__, __LINE__); \ -+ } -+ -+#else /*!DEBUG*/ -+ -+# define impossible() abort() -+# define bad_case(n) abort() -+# define passert(pred) { } /* do nothing */ -+# define happy(x) { (void) x; } /* evaluate non-judgementally */ -+ -+#endif /*!DEBUG*/ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/pfkey_debug.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,54 @@ -+/* -+ * sanitize a string into a printable format. -+ * -+ * Copyright (C) 1998-2002 D. Hugh Redelmeier. -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef _FREESWAN_PFKEY_DEBUG_H -+#define _FREESWAN_PFKEY_DEBUG_H -+ -+#ifdef __KERNEL__ -+ -+/* note, kernel version ignores pfkey levels */ -+# define DEBUGGING(level,args...) \ -+ KLIPS_PRINT(debug_pfkey, "klips_debug:" args) -+ -+# define ERROR(args...) printk(KERN_ERR "klips:" args) -+ -+#else -+ -+extern unsigned int pfkey_lib_debug; -+ -+extern void (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1); -+extern void (*pfkey_error_func)(const char *message, ...) PRINTF_LIKE(1); -+ -+#define DEBUGGING(level,args...) if(pfkey_lib_debug & level) { \ -+ if(pfkey_debug_func != NULL) { \ -+ (*pfkey_debug_func)("pfkey_lib_debug:" args); \ -+ } else { \ -+ printf("pfkey_lib_debug:" args); \ -+ } } -+ -+#define ERROR(args...) if(pfkey_error_func != NULL) { \ -+ (*pfkey_error_func)("pfkey_lib_debug:" args); \ -+ } -+ -+# define MALLOC(size) malloc(size) -+# define FREE(obj) free(obj) -+ -+#endif -+ -+#endif ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/radij.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,280 @@ -+/* -+ * RCSID $Id$ -+ */ -+ -+/* -+ * This file is defived from ${SRC}/sys/net/radix.h of BSD 4.4lite -+ * -+ * Variable and procedure names have been modified so that they don't -+ * conflict with the original BSD code, as a small number of modifications -+ * have been introduced and we may want to reuse this code in BSD. -+ * -+ * The `j' in `radij' is pronounced as a voiceless guttural (like a Greek -+ * chi or a German ch sound (as `doch', not as in `milch'), or even a -+ * spanish j as in Juan. It is not as far back in the throat like -+ * the corresponding Hebrew sound, nor is it a soft breath like the English h. -+ * It has nothing to do with the Dutch ij sound. -+ * -+ * Here is the appropriate copyright notice: -+ */ -+ -+/* -+ * Copyright (c) 1988, 1989, 1993 -+ * The Regents of the University of California. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * This product includes software developed by the University of -+ * California, Berkeley and its contributors. -+ * 4. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * @(#)radix.h 8.1 (Berkeley) 6/10/93 -+ */ -+ -+#ifndef _RADIJ_H_ -+#define _RADIJ_H_ -+ -+/* -+#define RJ_DEBUG -+*/ -+ -+#ifdef __KERNEL__ -+ -+#ifndef __P -+#ifdef __STDC__ -+#define __P(x) x -+#else -+#define __P(x) () -+#endif -+#endif -+ -+/* -+ * Radix search tree node layout. -+ */ -+ -+struct radij_node -+{ -+ struct radij_mask *rj_mklist; /* list of masks contained in subtree */ -+ struct radij_node *rj_p; /* parent */ -+ short rj_b; /* bit offset; -1-index(netmask) */ -+ char rj_bmask; /* node: mask for bit test*/ -+ u_char rj_flags; /* enumerated next */ -+#define RJF_NORMAL 1 /* leaf contains normal route */ -+#define RJF_ROOT 2 /* leaf is root leaf for tree */ -+#define RJF_ACTIVE 4 /* This node is alive (for rtfree) */ -+ union { -+ struct { /* leaf only data: */ -+ caddr_t rj_Key; /* object of search */ -+ caddr_t rj_Mask; /* netmask, if present */ -+ struct radij_node *rj_Dupedkey; -+ } rj_leaf; -+ struct { /* node only data: */ -+ int rj_Off; /* where to start compare */ -+ struct radij_node *rj_L;/* progeny */ -+ struct radij_node *rj_R;/* progeny */ -+ }rj_node; -+ } rj_u; -+#ifdef RJ_DEBUG -+ int rj_info; -+ struct radij_node *rj_twin; -+ struct radij_node *rj_ybro; -+#endif -+}; -+ -+#define rj_dupedkey rj_u.rj_leaf.rj_Dupedkey -+#define rj_key rj_u.rj_leaf.rj_Key -+#define rj_mask rj_u.rj_leaf.rj_Mask -+#define rj_off rj_u.rj_node.rj_Off -+#define rj_l rj_u.rj_node.rj_L -+#define rj_r rj_u.rj_node.rj_R -+ -+/* -+ * Annotations to tree concerning potential routes applying to subtrees. -+ */ -+ -+extern struct radij_mask { -+ short rm_b; /* bit offset; -1-index(netmask) */ -+ char rm_unused; /* cf. rj_bmask */ -+ u_char rm_flags; /* cf. rj_flags */ -+ struct radij_mask *rm_mklist; /* more masks to try */ -+ caddr_t rm_mask; /* the mask */ -+ int rm_refs; /* # of references to this struct */ -+} *rj_mkfreelist; -+ -+#define MKGet(m) {\ -+ if (rj_mkfreelist) {\ -+ m = rj_mkfreelist; \ -+ rj_mkfreelist = (m)->rm_mklist; \ -+ } else \ -+ R_Malloc(m, struct radij_mask *, sizeof (*(m))); }\ -+ -+#define MKFree(m) { (m)->rm_mklist = rj_mkfreelist; rj_mkfreelist = (m);} -+ -+struct radij_node_head { -+ struct radij_node *rnh_treetop; -+ int rnh_addrsize; /* permit, but not require fixed keys */ -+ int rnh_pktsize; /* permit, but not require fixed keys */ -+#if 0 -+ struct radij_node *(*rnh_addaddr) /* add based on sockaddr */ -+ __P((void *v, void *mask, -+ struct radij_node_head *head, struct radij_node nodes[])); -+#endif -+ int (*rnh_addaddr) /* add based on sockaddr */ -+ __P((void *v, void *mask, -+ struct radij_node_head *head, struct radij_node nodes[])); -+ struct radij_node *(*rnh_addpkt) /* add based on packet hdr */ -+ __P((void *v, void *mask, -+ struct radij_node_head *head, struct radij_node nodes[])); -+#if 0 -+ struct radij_node *(*rnh_deladdr) /* remove based on sockaddr */ -+ __P((void *v, void *mask, struct radij_node_head *head)); -+#endif -+ int (*rnh_deladdr) /* remove based on sockaddr */ -+ __P((void *v, void *mask, struct radij_node_head *head, struct radij_node **node)); -+ struct radij_node *(*rnh_delpkt) /* remove based on packet hdr */ -+ __P((void *v, void *mask, struct radij_node_head *head)); -+ struct radij_node *(*rnh_matchaddr) /* locate based on sockaddr */ -+ __P((void *v, struct radij_node_head *head)); -+ struct radij_node *(*rnh_matchpkt) /* locate based on packet hdr */ -+ __P((void *v, struct radij_node_head *head)); -+ int (*rnh_walktree) /* traverse tree */ -+ __P((struct radij_node_head *head, int (*f)(struct radij_node *rn, void *w), void *w)); -+ struct radij_node rnh_nodes[3]; /* empty tree for common case */ -+}; -+ -+ -+#define Bcmp(a, b, n) memcmp(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n)) -+#define Bcopy(a, b, n) memmove(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n)) -+#define Bzero(p, n) memset((caddr_t)(p), 0, (unsigned)(n)) -+#define R_Malloc(p, t, n) ((p = (t) kmalloc((size_t)(n), GFP_ATOMIC)), Bzero((p),(n))) -+#define Free(p) kfree((caddr_t)p); -+ -+void rj_init __P((void)); -+int rj_inithead __P((void **, int)); -+int rj_refines __P((void *, void *)); -+int rj_walktree __P((struct radij_node_head *head, int (*f)(struct radij_node *rn, void *w), void *w)); -+struct radij_node -+ *rj_addmask __P((void *, int, int)) /* , rgb */ ; -+int /* * */ rj_addroute __P((void *, void *, struct radij_node_head *, -+ struct radij_node [2])) /* , rgb */ ; -+int /* * */ rj_delete __P((void *, void *, struct radij_node_head *, struct radij_node **)) /* , rgb */ ; -+struct radij_node /* rgb */ -+ *rj_insert __P((void *, struct radij_node_head *, int *, -+ struct radij_node [2])), -+ *rj_match __P((void *, struct radij_node_head *)), -+ *rj_newpair __P((void *, int, struct radij_node[2])), -+ *rj_search __P((void *, struct radij_node *)), -+ *rj_search_m __P((void *, struct radij_node *, void *)); -+ -+void rj_deltree(struct radij_node_head *); -+void rj_delnodes(struct radij_node *); -+void rj_free_mkfreelist(void); -+int radijcleartree(void); -+int radijcleanup(void); -+ -+extern struct radij_node_head *mask_rjhead; -+extern int maj_keylen; -+#endif /* __KERNEL__ */ -+ -+#endif /* _RADIJ_H_ */ -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.13 2004/04/05 19:55:08 mcr -+ * Moved from linux/include/freeswan/radij.h,v -+ * -+ * Revision 1.12 2002/04/24 07:36:48 mcr -+ * Moved from ./klips/net/ipsec/radij.h,v -+ * -+ * Revision 1.11 2001/09/20 15:33:00 rgb -+ * Min/max cleanup. -+ * -+ * Revision 1.10 1999/11/18 04:09:20 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.9 1999/05/05 22:02:33 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.8 1999/04/29 15:24:58 rgb -+ * Add check for existence of macros min/max. -+ * -+ * Revision 1.7 1999/04/11 00:29:02 henry -+ * GPL boilerplate -+ * -+ * Revision 1.6 1999/04/06 04:54:29 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.5 1999/01/22 06:30:32 rgb -+ * 64-bit clean-up. -+ * -+ * Revision 1.4 1998/11/30 13:22:55 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.3 1998/10/25 02:43:27 rgb -+ * Change return type on rj_addroute and rj_delete and add and argument -+ * to the latter to be able to transmit more infomation about errors. -+ * -+ * Revision 1.2 1998/07/14 18:09:51 rgb -+ * Add a routine to clear eroute table. -+ * Added #ifdef __KERNEL__ directives to restrict scope of header. -+ * -+ * Revision 1.1 1998/06/18 21:30:22 henry -+ * move sources from klips/src to klips/net/ipsec to keep stupid kernel -+ * build scripts happier about symlinks -+ * -+ * Revision 1.4 1998/05/25 20:34:16 rgb -+ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions. -+ * -+ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and -+ * add ipsec_rj_walker_delete. -+ * -+ * Recover memory for eroute table on unload of module. -+ * -+ * Revision 1.3 1998/04/22 16:51:37 rgb -+ * Tidy up radij debug code from recent rash of modifications to debug code. -+ * -+ * Revision 1.2 1998/04/14 17:30:38 rgb -+ * Fix up compiling errors for radij tree memory reclamation. -+ * -+ * Revision 1.1 1998/04/09 03:06:16 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:04 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:44:45 ji -+ * Release update only. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/pfkey.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,509 @@ -+/* -+ * FreeS/WAN specific PF_KEY headers -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef __NET_IPSEC_PF_KEY_H -+#define __NET_IPSEC_PF_KEY_H -+#ifdef __KERNEL__ -+extern struct proto_ops pfkey_proto_ops; -+typedef struct sock pfkey_sock; -+extern int debug_pfkey; -+ -+extern /* void */ int pfkey_init(void); -+extern /* void */ int pfkey_cleanup(void); -+ -+extern struct sock *pfkey_sock_list; -+struct socket_list -+{ -+ struct socket *socketp; -+ struct socket_list *next; -+}; -+extern int pfkey_list_insert_socket(struct socket*, struct socket_list**); -+extern int pfkey_list_remove_socket(struct socket*, struct socket_list**); -+extern struct socket_list *pfkey_open_sockets; -+extern struct socket_list *pfkey_registered_sockets[SADB_SATYPE_MAX+1]; -+ -+struct supported -+{ -+ uint16_t supported_alg_exttype; -+ uint8_t supported_alg_id; -+ uint8_t supported_alg_ivlen; -+ uint16_t supported_alg_minbits; -+ uint16_t supported_alg_maxbits; -+}; -+ -+extern struct supported_list *pfkey_supported_list[SADB_SATYPE_MAX+1]; -+struct supported_list -+{ -+ struct supported *supportedp; -+ struct supported_list *next; -+}; -+extern int pfkey_list_insert_supported(struct supported*, struct supported_list**); -+extern int pfkey_list_remove_supported(struct supported*, struct supported_list**); -+ -+struct sockaddr_key -+{ -+ uint16_t key_family; /* PF_KEY */ -+ uint16_t key_pad; /* not used */ -+ uint32_t key_pid; /* process ID */ -+}; -+ -+struct pfkey_extracted_data -+{ -+ struct ipsec_sa* ips; -+ struct ipsec_sa* ips2; -+ struct eroute *eroute; -+}; -+ -+extern int -+pfkey_alloc_eroute(struct eroute** eroute); -+ -+extern int -+pfkey_sa_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_lifetime_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_address_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_key_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_ident_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_sens_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_prop_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_supported_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_spirange_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_x_kmprivate_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_x_satype_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_x_debug_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int pfkey_upmsg(struct socket *, struct sadb_msg *); -+extern int pfkey_expire(struct ipsec_sa *, int); -+extern int pfkey_acquire(struct ipsec_sa *); -+#else /* ! __KERNEL__ */ -+ -+extern void (*pfkey_debug_func)(const char *message, ...); -+extern void (*pfkey_error_func)(const char *message, ...); -+extern void pfkey_print(struct sadb_msg *msg, FILE *out); -+ -+ -+#endif /* __KERNEL__ */ -+ -+extern uint8_t satype2proto(uint8_t satype); -+extern uint8_t proto2satype(uint8_t proto); -+extern char* satype2name(uint8_t satype); -+extern char* proto2name(uint8_t proto); -+ -+struct key_opt -+{ -+ uint32_t key_pid; /* process ID */ -+ struct sock *sk; -+}; -+ -+#define key_pid(sk) ((struct key_opt*)&((sk)->protinfo))->key_pid -+ -+/* XXX-mcr this is not an alignment, this is because the count is in 64-bit -+ * words. -+ */ -+#define IPSEC_PFKEYv2_ALIGN (sizeof(uint64_t)/sizeof(uint8_t)) -+#define BITS_PER_OCTET 8 -+#define OCTETBITS 8 -+#define PFKEYBITS 64 -+#define DIVUP(x,y) ((x + y -1) / y) /* divide, rounding upwards */ -+#define ALIGN_N(x,y) (DIVUP(x,y) * y) /* align on y boundary */ -+ -+#define IPSEC_PFKEYv2_LEN(x) ((x) * IPSEC_PFKEYv2_ALIGN) -+#define IPSEC_PFKEYv2_WORDS(x) ((x) / IPSEC_PFKEYv2_ALIGN) -+ -+ -+#define PFKEYv2_MAX_MSGSIZE 4096 -+ -+/* -+ * PF_KEYv2 permitted and required extensions in and out bitmaps -+ */ -+struct pf_key_ext_parsers_def { -+ int (*parser)(struct sadb_ext*); -+ char *parser_name; -+}; -+ -+ -+extern unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_MAX + 1/*ext*/]; -+#define EXT_BITS_IN 0 -+#define EXT_BITS_OUT 1 -+#define EXT_BITS_PERM 0 -+#define EXT_BITS_REQ 1 -+ -+extern void pfkey_extensions_init(struct sadb_ext *extensions[SADB_EXT_MAX + 1]); -+extern void pfkey_extensions_free(struct sadb_ext *extensions[SADB_EXT_MAX + 1]); -+extern void pfkey_msg_free(struct sadb_msg **pfkey_msg); -+ -+extern int pfkey_msg_parse(struct sadb_msg *pfkey_msg, -+ struct pf_key_ext_parsers_def *ext_parsers[], -+ struct sadb_ext **extensions, -+ int dir); -+ -+extern int pfkey_register_reply(int satype, struct sadb_msg *sadb_msg); -+ -+/* -+ * PF_KEYv2 build function prototypes -+ */ -+ -+int -+pfkey_msg_hdr_build(struct sadb_ext** pfkey_ext, -+ uint8_t msg_type, -+ uint8_t satype, -+ uint8_t msg_errno, -+ uint32_t seq, -+ uint32_t pid); -+ -+int -+pfkey_sa_ref_build(struct sadb_ext ** pfkey_ext, -+ uint16_t exttype, -+ uint32_t spi, /* in network order */ -+ uint8_t replay_window, -+ uint8_t sa_state, -+ uint8_t auth, -+ uint8_t encrypt, -+ uint32_t flags, -+ uint32_t/*IPsecSAref_t*/ ref); -+ -+int -+pfkey_sa_build(struct sadb_ext ** pfkey_ext, -+ uint16_t exttype, -+ uint32_t spi, /* in network order */ -+ uint8_t replay_window, -+ uint8_t sa_state, -+ uint8_t auth, -+ uint8_t encrypt, -+ uint32_t flags); -+ -+int -+pfkey_lifetime_build(struct sadb_ext ** pfkey_ext, -+ uint16_t exttype, -+ uint32_t allocations, -+ uint64_t bytes, -+ uint64_t addtime, -+ uint64_t usetime, -+ uint32_t packets); -+ -+int -+pfkey_address_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint8_t proto, -+ uint8_t prefixlen, -+ struct sockaddr* address); -+ -+int -+pfkey_key_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint16_t key_bits, -+ char* key); -+ -+int -+pfkey_ident_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint16_t ident_type, -+ uint64_t ident_id, -+ uint8_t ident_len, -+ char* ident_string); -+ -+#ifdef NAT_TRAVERSAL -+#ifdef __KERNEL__ -+extern int pfkey_nat_t_new_mapping(struct ipsec_sa *, struct sockaddr *, __u16); -+extern int pfkey_x_nat_t_type_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr); -+extern int pfkey_x_nat_t_port_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr); -+#endif /* __KERNEL__ */ -+int -+pfkey_x_nat_t_type_build(struct sadb_ext** pfkey_ext, -+ uint8_t type); -+int -+pfkey_x_nat_t_port_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint16_t port); -+#endif -+ -+int -+pfkey_sens_build(struct sadb_ext** pfkey_ext, -+ uint32_t dpd, -+ uint8_t sens_level, -+ uint8_t sens_len, -+ uint64_t* sens_bitmap, -+ uint8_t integ_level, -+ uint8_t integ_len, -+ uint64_t* integ_bitmap); -+ -+int pfkey_x_protocol_build(struct sadb_ext **, uint8_t); -+ -+ -+int -+pfkey_prop_build(struct sadb_ext** pfkey_ext, -+ uint8_t replay, -+ unsigned int comb_num, -+ struct sadb_comb* comb); -+ -+int -+pfkey_supported_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ unsigned int alg_num, -+ struct sadb_alg* alg); -+ -+int -+pfkey_spirange_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint32_t min, -+ uint32_t max); -+ -+int -+pfkey_x_kmprivate_build(struct sadb_ext** pfkey_ext); -+ -+int -+pfkey_x_satype_build(struct sadb_ext** pfkey_ext, -+ uint8_t satype); -+ -+int -+pfkey_x_debug_build(struct sadb_ext** pfkey_ext, -+ uint32_t tunnel, -+ uint32_t netlink, -+ uint32_t xform, -+ uint32_t eroute, -+ uint32_t spi, -+ uint32_t radij, -+ uint32_t esp, -+ uint32_t ah, -+ uint32_t rcv, -+ uint32_t pfkey, -+ uint32_t ipcomp, -+ uint32_t verbose); -+ -+int -+pfkey_msg_build(struct sadb_msg** pfkey_msg, -+ struct sadb_ext* extensions[], -+ int dir); -+ -+/* in pfkey_v2_debug.c - routines to decode numbers -> strings */ -+const char * -+pfkey_v2_sadb_ext_string(int extnum); -+ -+const char * -+pfkey_v2_sadb_type_string(int sadb_type); -+ -+ -+#endif /* __NET_IPSEC_PF_KEY_H */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.45 2004/04/06 02:49:00 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.44 2003/12/10 01:20:01 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.43 2003/10/31 02:26:44 mcr -+ * pulled up port-selector patches. -+ * -+ * Revision 1.42.2.2 2003/10/29 01:09:32 mcr -+ * added debugging for pfkey library. -+ * -+ * Revision 1.42.2.1 2003/09/21 13:59:34 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.42 2003/08/25 22:08:19 mcr -+ * removed pfkey_proto_init() from pfkey.h for 2.6 support. -+ * -+ * Revision 1.41 2003/05/07 17:28:57 mcr -+ * new function pfkey_debug_func added for us in debugging from -+ -+ * pfkey library. -+ * -+ * Revision 1.40 2003/01/30 02:31:34 rgb -+ * -+ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. -+ * -+ * Revision 1.39 2002/09/20 15:40:21 rgb -+ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc(). -+ * Added ref parameter to pfkey_sa_build(). -+ * Cleaned out unused cruft. -+ * -+ * Revision 1.38 2002/05/14 02:37:24 rgb -+ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips, -+ * ipsec_sa or ipsec_sa. -+ * Added function prototypes for the functions moved to -+ * pfkey_v2_ext_process.c. -+ * -+ * Revision 1.37 2002/04/24 07:36:49 mcr -+ * Moved from ./lib/pfkey.h,v -+ * -+ * Revision 1.36 2002/01/20 20:34:49 mcr -+ * added pfkey_v2_sadb_type_string to decode sadb_type to string. -+ * -+ * Revision 1.35 2001/11/27 05:27:47 mcr -+ * pfkey parses are now maintained by a structure -+ * that includes their name for debug purposes. -+ * -+ * Revision 1.34 2001/11/26 09:23:53 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.33 2001/11/06 19:47:47 rgb -+ * Added packet parameter to lifetime and comb structures. -+ * -+ * Revision 1.32 2001/09/08 21:13:34 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.31 2001/06/14 19:35:16 rgb -+ * Update copyright date. -+ * -+ * Revision 1.30 2001/02/27 07:04:52 rgb -+ * Added satype2name prototype. -+ * -+ * Revision 1.29 2001/02/26 19:59:33 rgb -+ * Ditch unused sadb_satype2proto[], replaced by satype2proto(). -+ * -+ * Revision 1.28 2000/10/10 20:10:19 rgb -+ * Added support for debug_ipcomp and debug_verbose to klipsdebug. -+ * -+ * Revision 1.27 2000/09/21 04:20:45 rgb -+ * Fixed array size off-by-one error. (Thanks Svenning!) -+ * -+ * Revision 1.26 2000/09/12 03:26:05 rgb -+ * Added pfkey_acquire prototype. -+ * -+ * Revision 1.25 2000/09/08 19:21:28 rgb -+ * Fix pfkey_prop_build() parameter to be only single indirection. -+ * -+ * Revision 1.24 2000/09/01 18:46:42 rgb -+ * Added a supported algorithms array lists, one per satype and registered -+ * existing algorithms. -+ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to -+ * list. -+ * -+ * Revision 1.23 2000/08/27 01:55:26 rgb -+ * Define OCTETBITS and PFKEYBITS to avoid using 'magic' numbers in code. -+ * -+ * Revision 1.22 2000/08/20 21:39:23 rgb -+ * Added kernel prototypes for kernel funcitions pfkey_upmsg() and -+ * pfkey_expire(). -+ * -+ * Revision 1.21 2000/08/15 17:29:23 rgb -+ * Fixes from SZI to untested pfkey_prop_build(). -+ * -+ * Revision 1.20 2000/05/10 20:14:19 rgb -+ * Fleshed out sensitivity, proposal and supported extensions. -+ * -+ * Revision 1.19 2000/03/16 14:07:23 rgb -+ * Renamed ALIGN macro to avoid fighting with others in kernel. -+ * -+ * Revision 1.18 2000/01/22 23:24:06 rgb -+ * Added prototypes for proto2satype(), satype2proto() and proto2name(). -+ * -+ * Revision 1.17 2000/01/21 06:26:59 rgb -+ * Converted from double tdb arguments to one structure (extr) -+ * containing pointers to all temporary information structures. -+ * Added klipsdebug switching capability. -+ * Dropped unused argument to pfkey_x_satype_build(). -+ * -+ * Revision 1.16 1999/12/29 21:17:41 rgb -+ * Changed pfkey_msg_build() I/F to include a struct sadb_msg** -+ * parameter for cleaner manipulation of extensions[] and to guard -+ * against potential memory leaks. -+ * Changed the I/F to pfkey_msg_free() for the same reason. -+ * -+ * Revision 1.15 1999/12/09 23:12:54 rgb -+ * Added macro for BITS_PER_OCTET. -+ * Added argument to pfkey_sa_build() to do eroutes. -+ * -+ * Revision 1.14 1999/12/08 20:33:25 rgb -+ * Changed sa_family_t to uint16_t for 2.0.xx compatibility. -+ * -+ * Revision 1.13 1999/12/07 19:53:40 rgb -+ * Removed unused first argument from extension parsers. -+ * Changed __u* types to uint* to avoid use of asm/types.h and -+ * sys/types.h in userspace code. -+ * Added function prototypes for pfkey message and extensions -+ * initialisation and cleanup. -+ * -+ * Revision 1.12 1999/12/01 22:19:38 rgb -+ * Change pfkey_sa_build to accept an SPI in network byte order. -+ * -+ * Revision 1.11 1999/11/27 11:55:26 rgb -+ * Added extern sadb_satype2proto to enable moving protocol lookup table -+ * to lib/pfkey_v2_parse.c. -+ * Delete unused, moved typedefs. -+ * Add argument to pfkey_msg_parse() for direction. -+ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array. -+ * -+ * Revision 1.10 1999/11/23 22:29:21 rgb -+ * This file has been moved in the distribution from klips/net/ipsec to -+ * lib. -+ * Add macros for dealing with alignment and rounding up more opaquely. -+ * The uint_t type defines have been moved to freeswan.h to avoid -+ * chicken-and-egg problems. -+ * Add macros for dealing with alignment and rounding up more opaque. -+ * Added prototypes for using extention header bitmaps. -+ * Added prototypes of all the build functions. -+ * -+ * Revision 1.9 1999/11/20 21:59:48 rgb -+ * Moved socketlist type declarations and prototypes for shared use. -+ * Slightly modified scope of sockaddr_key declaration. -+ * -+ * Revision 1.8 1999/11/17 14:34:25 rgb -+ * Protect sa_family_t from being used in userspace with GLIBC<2. -+ * -+ * Revision 1.7 1999/10/27 19:40:35 rgb -+ * Add a maximum PFKEY packet size macro. -+ * -+ * Revision 1.6 1999/10/26 16:58:58 rgb -+ * Created a sockaddr_key and key_opt socket extension structures. -+ * -+ * Revision 1.5 1999/06/10 05:24:41 rgb -+ * Renamed variables to reduce confusion. -+ * -+ * Revision 1.4 1999/04/29 15:21:11 rgb -+ * Add pfkey support to debugging. -+ * Add return values to init and cleanup functions. -+ * -+ * Revision 1.3 1999/04/15 17:58:07 rgb -+ * Add RCSID labels. -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/pfkeyv2.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,467 @@ -+/* -+ * RCSID $Id$ -+ */ -+ -+/* -+RFC 2367 PF_KEY Key Management API July 1998 -+ -+ -+Appendix D: Sample Header File -+ -+This file defines structures and symbols for the PF_KEY Version 2 -+key management interface. It was written at the U.S. Naval Research -+Laboratory. This file is in the public domain. The authors ask that -+you leave this credit intact on any copies of this file. -+*/ -+#ifndef __PFKEY_V2_H -+#define __PFKEY_V2_H 1 -+ -+#define PF_KEY_V2 2 -+#define PFKEYV2_REVISION 199806L -+ -+#define SADB_RESERVED 0 -+#define SADB_GETSPI 1 -+#define SADB_UPDATE 2 -+#define SADB_ADD 3 -+#define SADB_DELETE 4 -+#define SADB_GET 5 -+#define SADB_ACQUIRE 6 -+#define SADB_REGISTER 7 -+#define SADB_EXPIRE 8 -+#define SADB_FLUSH 9 -+#define SADB_DUMP 10 -+#define SADB_X_PROMISC 11 -+#define SADB_X_PCHANGE 12 -+#define SADB_X_GRPSA 13 -+#define SADB_X_ADDFLOW 14 -+#define SADB_X_DELFLOW 15 -+#define SADB_X_DEBUG 16 -+#define SADB_X_NAT_T_NEW_MAPPING 17 -+#define SADB_MAX 17 -+ -+struct sadb_msg { -+ uint8_t sadb_msg_version; -+ uint8_t sadb_msg_type; -+ uint8_t sadb_msg_errno; -+ uint8_t sadb_msg_satype; -+ uint16_t sadb_msg_len; -+ uint16_t sadb_msg_reserved; -+ uint32_t sadb_msg_seq; -+ uint32_t sadb_msg_pid; -+}; -+ -+struct sadb_ext { -+ uint16_t sadb_ext_len; -+ uint16_t sadb_ext_type; -+}; -+ -+struct sadb_sa { -+ uint16_t sadb_sa_len; -+ uint16_t sadb_sa_exttype; -+ uint32_t sadb_sa_spi; -+ uint8_t sadb_sa_replay; -+ uint8_t sadb_sa_state; -+ uint8_t sadb_sa_auth; -+ uint8_t sadb_sa_encrypt; -+ uint32_t sadb_sa_flags; -+ uint32_t /*IPsecSAref_t*/ sadb_x_sa_ref; /* 32 bits */ -+ uint8_t sadb_x_reserved[4]; -+}; -+ -+struct sadb_sa_v1 { -+ uint16_t sadb_sa_len; -+ uint16_t sadb_sa_exttype; -+ uint32_t sadb_sa_spi; -+ uint8_t sadb_sa_replay; -+ uint8_t sadb_sa_state; -+ uint8_t sadb_sa_auth; -+ uint8_t sadb_sa_encrypt; -+ uint32_t sadb_sa_flags; -+}; -+ -+struct sadb_lifetime { -+ uint16_t sadb_lifetime_len; -+ uint16_t sadb_lifetime_exttype; -+ uint32_t sadb_lifetime_allocations; -+ uint64_t sadb_lifetime_bytes; -+ uint64_t sadb_lifetime_addtime; -+ uint64_t sadb_lifetime_usetime; -+ uint32_t sadb_x_lifetime_packets; -+ uint32_t sadb_x_lifetime_reserved; -+}; -+ -+struct sadb_address { -+ uint16_t sadb_address_len; -+ uint16_t sadb_address_exttype; -+ uint8_t sadb_address_proto; -+ uint8_t sadb_address_prefixlen; -+ uint16_t sadb_address_reserved; -+}; -+ -+struct sadb_key { -+ uint16_t sadb_key_len; -+ uint16_t sadb_key_exttype; -+ uint16_t sadb_key_bits; -+ uint16_t sadb_key_reserved; -+}; -+ -+struct sadb_ident { -+ uint16_t sadb_ident_len; -+ uint16_t sadb_ident_exttype; -+ uint16_t sadb_ident_type; -+ uint16_t sadb_ident_reserved; -+ uint64_t sadb_ident_id; -+}; -+ -+struct sadb_sens { -+ uint16_t sadb_sens_len; -+ uint16_t sadb_sens_exttype; -+ uint32_t sadb_sens_dpd; -+ uint8_t sadb_sens_sens_level; -+ uint8_t sadb_sens_sens_len; -+ uint8_t sadb_sens_integ_level; -+ uint8_t sadb_sens_integ_len; -+ uint32_t sadb_sens_reserved; -+}; -+ -+struct sadb_prop { -+ uint16_t sadb_prop_len; -+ uint16_t sadb_prop_exttype; -+ uint8_t sadb_prop_replay; -+ uint8_t sadb_prop_reserved[3]; -+}; -+ -+struct sadb_comb { -+ uint8_t sadb_comb_auth; -+ uint8_t sadb_comb_encrypt; -+ uint16_t sadb_comb_flags; -+ uint16_t sadb_comb_auth_minbits; -+ uint16_t sadb_comb_auth_maxbits; -+ uint16_t sadb_comb_encrypt_minbits; -+ uint16_t sadb_comb_encrypt_maxbits; -+ uint32_t sadb_comb_reserved; -+ uint32_t sadb_comb_soft_allocations; -+ uint32_t sadb_comb_hard_allocations; -+ uint64_t sadb_comb_soft_bytes; -+ uint64_t sadb_comb_hard_bytes; -+ uint64_t sadb_comb_soft_addtime; -+ uint64_t sadb_comb_hard_addtime; -+ uint64_t sadb_comb_soft_usetime; -+ uint64_t sadb_comb_hard_usetime; -+ uint32_t sadb_x_comb_soft_packets; -+ uint32_t sadb_x_comb_hard_packets; -+}; -+ -+struct sadb_supported { -+ uint16_t sadb_supported_len; -+ uint16_t sadb_supported_exttype; -+ uint32_t sadb_supported_reserved; -+}; -+ -+struct sadb_alg { -+ uint8_t sadb_alg_id; -+ uint8_t sadb_alg_ivlen; -+ uint16_t sadb_alg_minbits; -+ uint16_t sadb_alg_maxbits; -+ uint16_t sadb_alg_reserved; -+}; -+ -+struct sadb_spirange { -+ uint16_t sadb_spirange_len; -+ uint16_t sadb_spirange_exttype; -+ uint32_t sadb_spirange_min; -+ uint32_t sadb_spirange_max; -+ uint32_t sadb_spirange_reserved; -+}; -+ -+struct sadb_x_kmprivate { -+ uint16_t sadb_x_kmprivate_len; -+ uint16_t sadb_x_kmprivate_exttype; -+ uint32_t sadb_x_kmprivate_reserved; -+}; -+ -+struct sadb_x_satype { -+ uint16_t sadb_x_satype_len; -+ uint16_t sadb_x_satype_exttype; -+ uint8_t sadb_x_satype_satype; -+ uint8_t sadb_x_satype_reserved[3]; -+}; -+ -+struct sadb_x_policy { -+ uint16_t sadb_x_policy_len; -+ uint16_t sadb_x_policy_exttype; -+ uint16_t sadb_x_policy_type; -+ uint8_t sadb_x_policy_dir; -+ uint8_t sadb_x_policy_reserved; -+ uint32_t sadb_x_policy_id; -+ uint32_t sadb_x_policy_reserved2; -+}; -+ -+struct sadb_x_debug { -+ uint16_t sadb_x_debug_len; -+ uint16_t sadb_x_debug_exttype; -+ uint32_t sadb_x_debug_tunnel; -+ uint32_t sadb_x_debug_netlink; -+ uint32_t sadb_x_debug_xform; -+ uint32_t sadb_x_debug_eroute; -+ uint32_t sadb_x_debug_spi; -+ uint32_t sadb_x_debug_radij; -+ uint32_t sadb_x_debug_esp; -+ uint32_t sadb_x_debug_ah; -+ uint32_t sadb_x_debug_rcv; -+ uint32_t sadb_x_debug_pfkey; -+ uint32_t sadb_x_debug_ipcomp; -+ uint32_t sadb_x_debug_verbose; -+ uint8_t sadb_x_debug_reserved[4]; -+}; -+ -+struct sadb_x_nat_t_type { -+ uint16_t sadb_x_nat_t_type_len; -+ uint16_t sadb_x_nat_t_type_exttype; -+ uint8_t sadb_x_nat_t_type_type; -+ uint8_t sadb_x_nat_t_type_reserved[3]; -+}; -+struct sadb_x_nat_t_port { -+ uint16_t sadb_x_nat_t_port_len; -+ uint16_t sadb_x_nat_t_port_exttype; -+ uint16_t sadb_x_nat_t_port_port; -+ uint16_t sadb_x_nat_t_port_reserved; -+}; -+ -+/* -+ * A protocol structure for passing through the transport level -+ * protocol. It contains more fields than are actually used/needed -+ * but it is this way to be compatible with the structure used in -+ * OpenBSD (http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pfkeyv2.h) -+ */ -+struct sadb_protocol { -+ uint16_t sadb_protocol_len; -+ uint16_t sadb_protocol_exttype; -+ uint8_t sadb_protocol_proto; -+ uint8_t sadb_protocol_direction; -+ uint8_t sadb_protocol_flags; -+ uint8_t sadb_protocol_reserved2; -+}; -+ -+#define SADB_EXT_RESERVED 0 -+#define SADB_EXT_SA 1 -+#define SADB_EXT_LIFETIME_CURRENT 2 -+#define SADB_EXT_LIFETIME_HARD 3 -+#define SADB_EXT_LIFETIME_SOFT 4 -+#define SADB_EXT_ADDRESS_SRC 5 -+#define SADB_EXT_ADDRESS_DST 6 -+#define SADB_EXT_ADDRESS_PROXY 7 -+#define SADB_EXT_KEY_AUTH 8 -+#define SADB_EXT_KEY_ENCRYPT 9 -+#define SADB_EXT_IDENTITY_SRC 10 -+#define SADB_EXT_IDENTITY_DST 11 -+#define SADB_EXT_SENSITIVITY 12 -+#define SADB_EXT_PROPOSAL 13 -+#define SADB_EXT_SUPPORTED_AUTH 14 -+#define SADB_EXT_SUPPORTED_ENCRYPT 15 -+#define SADB_EXT_SPIRANGE 16 -+#define SADB_X_EXT_KMPRIVATE 17 -+#define SADB_X_EXT_SATYPE2 18 -+#ifdef KERNEL26_HAS_KAME_DUPLICATES -+#define SADB_X_EXT_POLICY 18 -+#endif -+#define SADB_X_EXT_SA2 19 -+#define SADB_X_EXT_ADDRESS_DST2 20 -+#define SADB_X_EXT_ADDRESS_SRC_FLOW 21 -+#define SADB_X_EXT_ADDRESS_DST_FLOW 22 -+#define SADB_X_EXT_ADDRESS_SRC_MASK 23 -+#define SADB_X_EXT_ADDRESS_DST_MASK 24 -+#define SADB_X_EXT_DEBUG 25 -+#define SADB_X_EXT_PROTOCOL 26 -+#define SADB_X_EXT_NAT_T_TYPE 27 -+#define SADB_X_EXT_NAT_T_SPORT 28 -+#define SADB_X_EXT_NAT_T_DPORT 29 -+#define SADB_X_EXT_NAT_T_OA 30 -+#define SADB_EXT_MAX 30 -+ -+/* SADB_X_DELFLOW required over and above SADB_X_SAFLAGS_CLEARFLOW */ -+#define SADB_X_EXT_ADDRESS_DELFLOW \ -+ ( (1<adler to the adler32 checksum of all input read -+ so far (that is, total_in bytes). -+ -+ deflate() may update data_type if it can make a good guess about -+ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered -+ binary. This field is only for information purposes and does not affect -+ the compression algorithm in any manner. -+ -+ deflate() returns Z_OK if some progress has been made (more input -+ processed or more output produced), Z_STREAM_END if all input has been -+ consumed and all output has been produced (only when flush is set to -+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example -+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible -+ (for example avail_in or avail_out was zero). -+*/ -+ -+ -+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -+/* -+ All dynamically allocated data structures for this stream are freed. -+ This function discards any unprocessed input and does not flush any -+ pending output. -+ -+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the -+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed -+ prematurely (some input or output was discarded). In the error case, -+ msg may be set but then points to a static string (which must not be -+ deallocated). -+*/ -+ -+ -+/* -+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); -+ -+ Initializes the internal stream state for decompression. The fields -+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by -+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact -+ value depends on the compression method), inflateInit determines the -+ compression method from the zlib header and allocates all data structures -+ accordingly; otherwise the allocation will be deferred to the first call of -+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to -+ use default allocation functions. -+ -+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the -+ version assumed by the caller. msg is set to null if there is no error -+ message. inflateInit does not perform any decompression apart from reading -+ the zlib header if present: this will be done by inflate(). (So next_in and -+ avail_in may be modified, but next_out and avail_out are unchanged.) -+*/ -+ -+ -+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -+/* -+ inflate decompresses as much data as possible, and stops when the input -+ buffer becomes empty or the output buffer becomes full. It may some -+ introduce some output latency (reading input without producing any output) -+ except when forced to flush. -+ -+ The detailed semantics are as follows. inflate performs one or both of the -+ following actions: -+ -+ - Decompress more input starting at next_in and update next_in and avail_in -+ accordingly. If not all input can be processed (because there is not -+ enough room in the output buffer), next_in is updated and processing -+ will resume at this point for the next call of inflate(). -+ -+ - Provide more output starting at next_out and update next_out and avail_out -+ accordingly. inflate() provides as much output as possible, until there -+ is no more input data or no more space in the output buffer (see below -+ about the flush parameter). -+ -+ Before the call of inflate(), the application should ensure that at least -+ one of the actions is possible, by providing more input and/or consuming -+ more output, and updating the next_* and avail_* values accordingly. -+ The application can consume the uncompressed output when it wants, for -+ example when the output buffer is full (avail_out == 0), or after each -+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it -+ must be called again after making room in the output buffer because there -+ might be more output pending. -+ -+ If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much -+ output as possible to the output buffer. The flushing behavior of inflate is -+ not specified for values of the flush parameter other than Z_SYNC_FLUSH -+ and Z_FINISH, but the current implementation actually flushes as much output -+ as possible anyway. -+ -+ inflate() should normally be called until it returns Z_STREAM_END or an -+ error. However if all decompression is to be performed in a single step -+ (a single call of inflate), the parameter flush should be set to -+ Z_FINISH. In this case all pending input is processed and all pending -+ output is flushed; avail_out must be large enough to hold all the -+ uncompressed data. (The size of the uncompressed data may have been saved -+ by the compressor for this purpose.) The next operation on this stream must -+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH -+ is never required, but can be used to inform inflate that a faster routine -+ may be used for the single inflate() call. -+ -+ If a preset dictionary is needed at this point (see inflateSetDictionary -+ below), inflate sets strm-adler to the adler32 checksum of the -+ dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise -+ it sets strm->adler to the adler32 checksum of all output produced -+ so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or -+ an error code as described below. At the end of the stream, inflate() -+ checks that its computed adler32 checksum is equal to that saved by the -+ compressor and returns Z_STREAM_END only if the checksum is correct. -+ -+ inflate() returns Z_OK if some progress has been made (more input processed -+ or more output produced), Z_STREAM_END if the end of the compressed data has -+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a -+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was -+ corrupted (input stream not conforming to the zlib format or incorrect -+ adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent -+ (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not -+ enough memory, Z_BUF_ERROR if no progress is possible or if there was not -+ enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR -+ case, the application may then call inflateSync to look for a good -+ compression block. -+*/ -+ -+ -+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -+/* -+ All dynamically allocated data structures for this stream are freed. -+ This function discards any unprocessed input and does not flush any -+ pending output. -+ -+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state -+ was inconsistent. In the error case, msg may be set but then points to a -+ static string (which must not be deallocated). -+*/ -+ -+ /* Advanced functions */ -+ -+/* -+ The following functions are needed only in some special applications. -+*/ -+ -+/* -+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, -+ int level, -+ int method, -+ int windowBits, -+ int memLevel, -+ int strategy)); -+ -+ This is another version of deflateInit with more compression options. The -+ fields next_in, zalloc, zfree and opaque must be initialized before by -+ the caller. -+ -+ The method parameter is the compression method. It must be Z_DEFLATED in -+ this version of the library. -+ -+ The windowBits parameter is the base two logarithm of the window size -+ (the size of the history buffer). It should be in the range 8..15 for this -+ version of the library. Larger values of this parameter result in better -+ compression at the expense of memory usage. The default value is 15 if -+ deflateInit is used instead. -+ -+ The memLevel parameter specifies how much memory should be allocated -+ for the internal compression state. memLevel=1 uses minimum memory but -+ is slow and reduces compression ratio; memLevel=9 uses maximum memory -+ for optimal speed. The default value is 8. See zconf.h for total memory -+ usage as a function of windowBits and memLevel. -+ -+ The strategy parameter is used to tune the compression algorithm. Use the -+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a -+ filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no -+ string match). Filtered data consists mostly of small values with a -+ somewhat random distribution. In this case, the compression algorithm is -+ tuned to compress them better. The effect of Z_FILTERED is to force more -+ Huffman coding and less string matching; it is somewhat intermediate -+ between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects -+ the compression ratio but not the correctness of the compressed output even -+ if it is not set appropriately. -+ -+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid -+ method). msg is set to null if there is no error message. deflateInit2 does -+ not perform any compression: this will be done by deflate(). -+*/ -+ -+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, -+ const Bytef *dictionary, -+ uInt dictLength)); -+/* -+ Initializes the compression dictionary from the given byte sequence -+ without producing any compressed output. This function must be called -+ immediately after deflateInit, deflateInit2 or deflateReset, before any -+ call of deflate. The compressor and decompressor must use exactly the same -+ dictionary (see inflateSetDictionary). -+ -+ The dictionary should consist of strings (byte sequences) that are likely -+ to be encountered later in the data to be compressed, with the most commonly -+ used strings preferably put towards the end of the dictionary. Using a -+ dictionary is most useful when the data to be compressed is short and can be -+ predicted with good accuracy; the data can then be compressed better than -+ with the default empty dictionary. -+ -+ Depending on the size of the compression data structures selected by -+ deflateInit or deflateInit2, a part of the dictionary may in effect be -+ discarded, for example if the dictionary is larger than the window size in -+ deflate or deflate2. Thus the strings most likely to be useful should be -+ put at the end of the dictionary, not at the front. -+ -+ Upon return of this function, strm->adler is set to the Adler32 value -+ of the dictionary; the decompressor may later use this value to determine -+ which dictionary has been used by the compressor. (The Adler32 value -+ applies to the whole dictionary even if only a subset of the dictionary is -+ actually used by the compressor.) -+ -+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a -+ parameter is invalid (such as NULL dictionary) or the stream state is -+ inconsistent (for example if deflate has already been called for this stream -+ or if the compression method is bsort). deflateSetDictionary does not -+ perform any compression: this will be done by deflate(). -+*/ -+ -+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, -+ z_streamp source)); -+/* -+ Sets the destination stream as a complete copy of the source stream. -+ -+ This function can be useful when several compression strategies will be -+ tried, for example when there are several ways of pre-processing the input -+ data with a filter. The streams that will be discarded should then be freed -+ by calling deflateEnd. Note that deflateCopy duplicates the internal -+ compression state which can be quite large, so this strategy is slow and -+ can consume lots of memory. -+ -+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent -+ (such as zalloc being NULL). msg is left unchanged in both source and -+ destination. -+*/ -+ -+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -+/* -+ This function is equivalent to deflateEnd followed by deflateInit, -+ but does not free and reallocate all the internal compression state. -+ The stream will keep the same compression level and any other attributes -+ that may have been set by deflateInit2. -+ -+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source -+ stream state was inconsistent (such as zalloc or state being NULL). -+*/ -+ -+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, -+ int level, -+ int strategy)); -+/* -+ Dynamically update the compression level and compression strategy. The -+ interpretation of level and strategy is as in deflateInit2. This can be -+ used to switch between compression and straight copy of the input data, or -+ to switch to a different kind of input data requiring a different -+ strategy. If the compression level is changed, the input available so far -+ is compressed with the old level (and may be flushed); the new level will -+ take effect only at the next call of deflate(). -+ -+ Before the call of deflateParams, the stream state must be set as for -+ a call of deflate(), since the currently available input may have to -+ be compressed and flushed. In particular, strm->avail_out must be non-zero. -+ -+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source -+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR -+ if strm->avail_out was zero. -+*/ -+ -+/* -+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, -+ int windowBits)); -+ -+ This is another version of inflateInit with an extra parameter. The -+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized -+ before by the caller. -+ -+ The windowBits parameter is the base two logarithm of the maximum window -+ size (the size of the history buffer). It should be in the range 8..15 for -+ this version of the library. The default value is 15 if inflateInit is used -+ instead. If a compressed stream with a larger window size is given as -+ input, inflate() will return with the error code Z_DATA_ERROR instead of -+ trying to allocate a larger window. -+ -+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative -+ memLevel). msg is set to null if there is no error message. inflateInit2 -+ does not perform any decompression apart from reading the zlib header if -+ present: this will be done by inflate(). (So next_in and avail_in may be -+ modified, but next_out and avail_out are unchanged.) -+*/ -+ -+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, -+ const Bytef *dictionary, -+ uInt dictLength)); -+/* -+ Initializes the decompression dictionary from the given uncompressed byte -+ sequence. This function must be called immediately after a call of inflate -+ if this call returned Z_NEED_DICT. The dictionary chosen by the compressor -+ can be determined from the Adler32 value returned by this call of -+ inflate. The compressor and decompressor must use exactly the same -+ dictionary (see deflateSetDictionary). -+ -+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a -+ parameter is invalid (such as NULL dictionary) or the stream state is -+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the -+ expected one (incorrect Adler32 value). inflateSetDictionary does not -+ perform any decompression: this will be done by subsequent calls of -+ inflate(). -+*/ -+ -+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -+/* -+ Skips invalid compressed data until a full flush point (see above the -+ description of deflate with Z_FULL_FLUSH) can be found, or until all -+ available input is skipped. No output is provided. -+ -+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR -+ if no more input was provided, Z_DATA_ERROR if no flush point has been found, -+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success -+ case, the application may save the current current value of total_in which -+ indicates where valid compressed data was found. In the error case, the -+ application may repeatedly call inflateSync, providing more input each time, -+ until success or end of the input data. -+*/ -+ -+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -+/* -+ This function is equivalent to inflateEnd followed by inflateInit, -+ but does not free and reallocate all the internal decompression state. -+ The stream will keep attributes that may have been set by inflateInit2. -+ -+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source -+ stream state was inconsistent (such as zalloc or state being NULL). -+*/ -+ -+ -+ /* utility functions */ -+ -+/* -+ The following utility functions are implemented on top of the -+ basic stream-oriented functions. To simplify the interface, some -+ default options are assumed (compression level and memory usage, -+ standard memory allocation functions). The source code of these -+ utility functions can easily be modified if you need special options. -+*/ -+ -+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, -+ const Bytef *source, uLong sourceLen)); -+/* -+ Compresses the source buffer into the destination buffer. sourceLen is -+ the byte length of the source buffer. Upon entry, destLen is the total -+ size of the destination buffer, which must be at least 0.1% larger than -+ sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the -+ compressed buffer. -+ This function can be used to compress a whole file at once if the -+ input file is mmap'ed. -+ compress returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory, Z_BUF_ERROR if there was not enough room in the output -+ buffer. -+*/ -+ -+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, -+ const Bytef *source, uLong sourceLen, -+ int level)); -+/* -+ Compresses the source buffer into the destination buffer. The level -+ parameter has the same meaning as in deflateInit. sourceLen is the byte -+ length of the source buffer. Upon entry, destLen is the total size of the -+ destination buffer, which must be at least 0.1% larger than sourceLen plus -+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. -+ -+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_BUF_ERROR if there was not enough room in the output buffer, -+ Z_STREAM_ERROR if the level parameter is invalid. -+*/ -+ -+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, -+ const Bytef *source, uLong sourceLen)); -+/* -+ Decompresses the source buffer into the destination buffer. sourceLen is -+ the byte length of the source buffer. Upon entry, destLen is the total -+ size of the destination buffer, which must be large enough to hold the -+ entire uncompressed data. (The size of the uncompressed data must have -+ been saved previously by the compressor and transmitted to the decompressor -+ by some mechanism outside the scope of this compression library.) -+ Upon exit, destLen is the actual size of the compressed buffer. -+ This function can be used to decompress a whole file at once if the -+ input file is mmap'ed. -+ -+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory, Z_BUF_ERROR if there was not enough room in the output -+ buffer, or Z_DATA_ERROR if the input data was corrupted. -+*/ -+ -+ -+typedef voidp gzFile; -+ -+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); -+/* -+ Opens a gzip (.gz) file for reading or writing. The mode parameter -+ is as in fopen ("rb" or "wb") but can also include a compression level -+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for -+ Huffman only compression as in "wb1h". (See the description -+ of deflateInit2 for more information about the strategy parameter.) -+ -+ gzopen can be used to read a file which is not in gzip format; in this -+ case gzread will directly read from the file without decompression. -+ -+ gzopen returns NULL if the file could not be opened or if there was -+ insufficient memory to allocate the (de)compression state; errno -+ can be checked to distinguish the two cases (if errno is zero, the -+ zlib error is Z_MEM_ERROR). */ -+ -+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -+/* -+ gzdopen() associates a gzFile with the file descriptor fd. File -+ descriptors are obtained from calls like open, dup, creat, pipe or -+ fileno (in the file has been previously opened with fopen). -+ The mode parameter is as in gzopen. -+ The next call of gzclose on the returned gzFile will also close the -+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file -+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). -+ gzdopen returns NULL if there was insufficient memory to allocate -+ the (de)compression state. -+*/ -+ -+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -+/* -+ Dynamically update the compression level or strategy. See the description -+ of deflateInit2 for the meaning of these parameters. -+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not -+ opened for writing. -+*/ -+ -+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -+/* -+ Reads the given number of uncompressed bytes from the compressed file. -+ If the input file was not in gzip format, gzread copies the given number -+ of bytes into the buffer. -+ gzread returns the number of uncompressed bytes actually read (0 for -+ end of file, -1 for error). */ -+ -+ZEXTERN int ZEXPORT gzwrite OF((gzFile file, -+ const voidp buf, unsigned len)); -+/* -+ Writes the given number of uncompressed bytes into the compressed file. -+ gzwrite returns the number of uncompressed bytes actually written -+ (0 in case of error). -+*/ -+ -+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); -+/* -+ Converts, formats, and writes the args to the compressed file under -+ control of the format string, as in fprintf. gzprintf returns the number of -+ uncompressed bytes actually written (0 in case of error). -+*/ -+ -+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -+/* -+ Writes the given null-terminated string to the compressed file, excluding -+ the terminating null character. -+ gzputs returns the number of characters written, or -1 in case of error. -+*/ -+ -+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -+/* -+ Reads bytes from the compressed file until len-1 characters are read, or -+ a newline character is read and transferred to buf, or an end-of-file -+ condition is encountered. The string is then terminated with a null -+ character. -+ gzgets returns buf, or Z_NULL in case of error. -+*/ -+ -+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -+/* -+ Writes c, converted to an unsigned char, into the compressed file. -+ gzputc returns the value that was written, or -1 in case of error. -+*/ -+ -+ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -+/* -+ Reads one byte from the compressed file. gzgetc returns this byte -+ or -1 in case of end of file or error. -+*/ -+ -+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -+/* -+ Flushes all pending output into the compressed file. The parameter -+ flush is as in the deflate() function. The return value is the zlib -+ error number (see function gzerror below). gzflush returns Z_OK if -+ the flush parameter is Z_FINISH and all output could be flushed. -+ gzflush should be called only when strictly necessary because it can -+ degrade compression. -+*/ -+ -+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, -+ z_off_t offset, int whence)); -+/* -+ Sets the starting position for the next gzread or gzwrite on the -+ given compressed file. The offset represents a number of bytes in the -+ uncompressed data stream. The whence parameter is defined as in lseek(2); -+ the value SEEK_END is not supported. -+ If the file is opened for reading, this function is emulated but can be -+ extremely slow. If the file is opened for writing, only forward seeks are -+ supported; gzseek then compresses a sequence of zeroes up to the new -+ starting position. -+ -+ gzseek returns the resulting offset location as measured in bytes from -+ the beginning of the uncompressed stream, or -1 in case of error, in -+ particular if the file is opened for writing and the new starting position -+ would be before the current position. -+*/ -+ -+ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -+/* -+ Rewinds the given file. This function is supported only for reading. -+ -+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -+*/ -+ -+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); -+/* -+ Returns the starting position for the next gzread or gzwrite on the -+ given compressed file. This position represents a number of bytes in the -+ uncompressed data stream. -+ -+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -+*/ -+ -+ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -+/* -+ Returns 1 when EOF has previously been detected reading the given -+ input stream, otherwise zero. -+*/ -+ -+ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -+/* -+ Flushes all pending output if necessary, closes the compressed file -+ and deallocates all the (de)compression state. The return value is the zlib -+ error number (see function gzerror below). -+*/ -+ -+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -+/* -+ Returns the error message for the last error which occurred on the -+ given compressed file. errnum is set to zlib error number. If an -+ error occurred in the file system and not in the compression library, -+ errnum is set to Z_ERRNO and the application may consult errno -+ to get the exact error code. -+*/ -+ -+ /* checksum functions */ -+ -+/* -+ These functions are not related to compression but are exported -+ anyway because they might be useful in applications using the -+ compression library. -+*/ -+ -+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -+ -+/* -+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and -+ return the updated checksum. If buf is NULL, this function returns -+ the required initial value for the checksum. -+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed -+ much faster. Usage example: -+ -+ uLong adler = adler32(0L, Z_NULL, 0); -+ -+ while (read_buffer(buffer, length) != EOF) { -+ adler = adler32(adler, buffer, length); -+ } -+ if (adler != original_adler) error(); -+*/ -+ -+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -+/* -+ Update a running crc with the bytes buf[0..len-1] and return the updated -+ crc. If buf is NULL, this function returns the required initial value -+ for the crc. Pre- and post-conditioning (one's complement) is performed -+ within this function so it shouldn't be done by the application. -+ Usage example: -+ -+ uLong crc = crc32(0L, Z_NULL, 0); -+ -+ while (read_buffer(buffer, length) != EOF) { -+ crc = crc32(crc, buffer, length); -+ } -+ if (crc != original_crc) error(); -+*/ -+ -+ -+ /* various hacks, don't look :) */ -+ -+/* deflateInit and inflateInit are macros to allow checking the zlib version -+ * and the compiler's view of z_stream: -+ */ -+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, -+ const char *version, int stream_size)); -+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, -+ const char *version, int stream_size)); -+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, -+ int windowBits, int memLevel, -+ int strategy, const char *version, -+ int stream_size)); -+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, -+ const char *version, int stream_size)); -+#define deflateInit(strm, level) \ -+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -+#define inflateInit(strm) \ -+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ -+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ -+ (strategy), ZLIB_VERSION, sizeof(z_stream)) -+#define inflateInit2(strm, windowBits) \ -+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) -+ -+ -+#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) -+ struct internal_state {int dummy;}; /* hack for buggy compilers */ -+#endif -+ -+ZEXTERN const char * ZEXPORT zError OF((int err)); -+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); -+ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* _ZLIB_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/zlib/zutil.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,225 @@ -+/* zutil.h -- internal interface and configuration of the compression library -+ * Copyright (C) 1995-2002 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+/* @(#) $Id$ */ -+ -+#ifndef _Z_UTIL_H -+#define _Z_UTIL_H -+ -+#include "zlib.h" -+ -+#include -+#define HAVE_MEMCPY -+ -+#if 0 // #ifdef STDC -+# include -+# include -+# include -+#endif -+#ifndef __KERNEL__ -+#ifdef NO_ERRNO_H -+ extern int errno; -+#else -+# include -+#endif -+#endif -+ -+#ifndef local -+# define local static -+#endif -+/* compile with -Dlocal if your debugger can't find static symbols */ -+ -+typedef unsigned char uch; -+typedef uch FAR uchf; -+typedef unsigned short ush; -+typedef ush FAR ushf; -+typedef unsigned long ulg; -+ -+extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ -+/* (size given to avoid silly warnings with Visual C++) */ -+ -+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] -+ -+#define ERR_RETURN(strm,err) \ -+ return (strm->msg = ERR_MSG(err), (err)) -+/* To be used only when the state is known to be valid */ -+ -+ /* common constants */ -+ -+#ifndef DEF_WBITS -+# define DEF_WBITS MAX_WBITS -+#endif -+/* default windowBits for decompression. MAX_WBITS is for compression only */ -+ -+#if MAX_MEM_LEVEL >= 8 -+# define DEF_MEM_LEVEL 8 -+#else -+# define DEF_MEM_LEVEL MAX_MEM_LEVEL -+#endif -+/* default memLevel */ -+ -+#define STORED_BLOCK 0 -+#define STATIC_TREES 1 -+#define DYN_TREES 2 -+/* The three kinds of block type */ -+ -+#define MIN_MATCH 3 -+#define MAX_MATCH 258 -+/* The minimum and maximum match lengths */ -+ -+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ -+ -+ /* target dependencies */ -+ -+#ifdef MSDOS -+# define OS_CODE 0x00 -+# if defined(__TURBOC__) || defined(__BORLANDC__) -+# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) -+ /* Allow compilation with ANSI keywords only enabled */ -+ void _Cdecl farfree( void *block ); -+ void *_Cdecl farmalloc( unsigned long nbytes ); -+# else -+# include -+# endif -+# else /* MSC or DJGPP */ -+# include -+# endif -+#endif -+ -+#ifdef OS2 -+# define OS_CODE 0x06 -+#endif -+ -+#ifdef WIN32 /* Window 95 & Windows NT */ -+# define OS_CODE 0x0b -+#endif -+ -+#if defined(VAXC) || defined(VMS) -+# define OS_CODE 0x02 -+# define F_OPEN(name, mode) \ -+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") -+#endif -+ -+#ifdef AMIGA -+# define OS_CODE 0x01 -+#endif -+ -+#if defined(ATARI) || defined(atarist) -+# define OS_CODE 0x05 -+#endif -+ -+#if defined(MACOS) || defined(TARGET_OS_MAC) -+# define OS_CODE 0x07 -+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -+# include /* for fdopen */ -+# else -+# ifndef fdopen -+# define fdopen(fd,mode) NULL /* No fdopen() */ -+# endif -+# endif -+#endif -+ -+#ifdef __50SERIES /* Prime/PRIMOS */ -+# define OS_CODE 0x0F -+#endif -+ -+#ifdef TOPS20 -+# define OS_CODE 0x0a -+#endif -+ -+#if defined(_BEOS_) || defined(RISCOS) -+# define fdopen(fd,mode) NULL /* No fdopen() */ -+#endif -+ -+#if (defined(_MSC_VER) && (_MSC_VER > 600)) -+# define fdopen(fd,type) _fdopen(fd,type) -+#endif -+ -+ -+ /* Common defaults */ -+ -+#ifndef OS_CODE -+# define OS_CODE 0x03 /* assume Unix */ -+#endif -+ -+#ifndef F_OPEN -+# define F_OPEN(name, mode) fopen((name), (mode)) -+#endif -+ -+ /* functions */ -+ -+#ifdef HAVE_STRERROR -+ extern char *strerror OF((int)); -+# define zstrerror(errnum) strerror(errnum) -+#else -+# define zstrerror(errnum) "" -+#endif -+ -+#if defined(pyr) -+# define NO_MEMCPY -+#endif -+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) -+ /* Use our own functions for small and medium model with MSC <= 5.0. -+ * You may have to use the same strategy for Borland C (untested). -+ * The __SC__ check is for Symantec. -+ */ -+# define NO_MEMCPY -+#endif -+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) -+# define HAVE_MEMCPY -+#endif -+#ifdef HAVE_MEMCPY -+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ -+# define zmemcpy _fmemcpy -+# define zmemcmp _fmemcmp -+# define zmemzero(dest, len) _fmemset(dest, 0, len) -+# else -+# define zmemcpy memcpy -+# define zmemcmp memcmp -+# define zmemzero(dest, len) memset(dest, 0, len) -+# endif -+#else -+ extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); -+ extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); -+ extern void zmemzero OF((Bytef* dest, uInt len)); -+#endif -+ -+/* Diagnostic functions */ -+#ifdef DEBUG -+# include -+ extern int z_verbose; -+ extern void z_error OF((char *m)); -+# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -+# define Trace(x) {if (z_verbose>=0) fprintf x ;} -+# define Tracev(x) {if (z_verbose>0) fprintf x ;} -+# define Tracevv(x) {if (z_verbose>1) fprintf x ;} -+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} -+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} -+#else -+# define Assert(cond,msg) -+# define Trace(x) -+# define Tracev(x) -+# define Tracevv(x) -+# define Tracec(c,x) -+# define Tracecv(c,x) -+#endif -+ -+ -+typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, -+ uInt len)); -+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); -+void zcfree OF((voidpf opaque, voidpf ptr)); -+ -+#define ZALLOC(strm, items, size) \ -+ (*((strm)->zalloc))((strm)->opaque, (items), (size)) -+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) -+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} -+ -+#endif /* _Z_UTIL_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/Makefile.objs Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,21 @@ -+obj-y += satot.o -+obj-y += addrtot.o -+obj-y += ultot.o -+obj-y += addrtypeof.o -+obj-y += anyaddr.o -+obj-y += initaddr.o -+obj-y += ultoa.o -+obj-y += addrtoa.o -+obj-y += subnettoa.o -+obj-y += subnetof.o -+obj-y += goodmask.o -+obj-y += datatot.o -+obj-y += rangetoa.o -+obj-y += prng.o -+obj-y += pfkey_v2_parse.o -+obj-y += pfkey_v2_build.o -+obj-y += pfkey_v2_debug.o -+obj-y += pfkey_v2_ext_bits.o -+ -+#version.c: ${LIBFREESWANDIR}/version.in.c ${OPENSWANSRCDIR}/Makefile.ver -+# sed '/"/s/xxx/$(IPSECVERSION)/' ${LIBFREESWANDIR}/version.in.c >$@ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/addrtoa.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,67 @@ -+/* -+ * addresses to ASCII -+ * Copyright (C) 1998, 1999 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+#define NBYTES 4 /* bytes in an address */ -+#define PERBYTE 4 /* three digits plus a dot or NUL */ -+#define BUFLEN (NBYTES*PERBYTE) -+ -+#if BUFLEN != ADDRTOA_BUF -+#error "ADDRTOA_BUF in openswan.h inconsistent with addrtoa() code" -+#endif -+ -+/* -+ - addrtoa - convert binary address to ASCII dotted decimal -+ */ -+size_t /* space needed for full conversion */ -+addrtoa(addr, format, dst, dstlen) -+struct in_addr addr; -+int format; /* character */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ unsigned long a = ntohl(addr.s_addr); -+ int i; -+ size_t n; -+ unsigned long byte; -+ char buf[BUFLEN]; -+ char *p; -+ -+ switch (format) { -+ case 0: -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ p = buf; -+ for (i = NBYTES-1; i >= 0; i--) { -+ byte = (a >> (i*8)) & 0xff; -+ p += ultoa(byte, 10, p, PERBYTE); -+ if (i != 0) -+ *(p-1) = '.'; -+ } -+ n = p - buf; -+ -+ if (dstlen > 0) { -+ if (n > dstlen) -+ buf[dstlen - 1] = '\0'; -+ strcpy(dst, buf); -+ } -+ return n; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/addrtot.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,334 @@ -+/* -+ * addresses to text -+ * Copyright (C) 2000 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+#define IP4BYTES 4 /* bytes in an IPv4 address */ -+#define PERBYTE 4 /* three digits plus a dot or NUL */ -+#define IP6BYTES 16 /* bytes in an IPv6 address */ -+ -+/* forwards */ -+static size_t normal4(const unsigned char *s, size_t len, char *b, char **dp); -+static size_t normal6(const unsigned char *s, size_t len, char *b, char **dp, int squish); -+static size_t reverse4(const unsigned char *s, size_t len, char *b, char **dp); -+static size_t reverse6(const unsigned char *s, size_t len, char *b, char **dp); -+ -+/* -+ - addrtot - convert binary address to text (dotted decimal or IPv6 string) -+ */ -+size_t /* space needed for full conversion */ -+addrtot(src, format, dst, dstlen) -+const ip_address *src; -+int format; /* character */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ const unsigned char *b; -+ size_t n; -+ char buf[1+ADDRTOT_BUF+1]; /* :address: */ -+ char *p; -+ int t = addrtypeof(src); -+# define TF(t, f) (((t)<<8) | (f)) -+ -+ n = addrbytesptr(src, &b); -+ if (n == 0) { -+ bad: -+ dst[0]='\0'; -+ strncat(dst, "", dstlen); -+ return sizeof(""); -+ } -+ -+ switch (TF(t, format)) { -+ case TF(AF_INET, 0): -+ n = normal4(b, n, buf, &p); -+ break; -+ case TF(AF_INET6, 0): -+ n = normal6(b, n, buf, &p, 1); -+ break; -+ case TF(AF_INET, 'Q'): -+ n = normal4(b, n, buf, &p); -+ break; -+ case TF(AF_INET6, 'Q'): -+ n = normal6(b, n, buf, &p, 0); -+ break; -+ case TF(AF_INET, 'r'): -+ n = reverse4(b, n, buf, &p); -+ break; -+ case TF(AF_INET6, 'r'): -+ n = reverse6(b, n, buf, &p); -+ break; -+ default: /* including (AF_INET, 'R') */ -+ goto bad; -+ break; -+ } -+ -+ if (dstlen > 0) { -+ if (dstlen < n) -+ p[dstlen - 1] = '\0'; -+ strcpy(dst, p); -+ } -+ return n; -+} -+ -+/* -+ - normal4 - normal IPv4 address-text conversion -+ */ -+static size_t /* size of text, including NUL */ -+normal4(srcp, srclen, buf, dstp) -+const unsigned char *srcp; -+size_t srclen; -+char *buf; /* guaranteed large enough */ -+char **dstp; /* where to put result pointer */ -+{ -+ int i; -+ char *p; -+ -+ if (srclen != IP4BYTES) /* "can't happen" */ -+ return 0; -+ p = buf; -+ for (i = 0; i < IP4BYTES; i++) { -+ p += ultot(srcp[i], 10, p, PERBYTE); -+ if (i != IP4BYTES - 1) -+ *(p-1) = '.'; /* overwrites the NUL */ -+ } -+ *dstp = buf; -+ return p - buf; -+} -+ -+/* -+ - normal6 - normal IPv6 address-text conversion -+ */ -+static size_t /* size of text, including NUL */ -+normal6(srcp, srclen, buf, dstp, squish) -+const unsigned char *srcp; -+size_t srclen; -+char *buf; /* guaranteed large enough, plus 2 */ -+char **dstp; /* where to put result pointer */ -+int squish; /* whether to squish out 0:0 */ -+{ -+ int i; -+ unsigned long piece; -+ char *p; -+ char *q; -+ -+ if (srclen != IP6BYTES) /* "can't happen" */ -+ return 0; -+ p = buf; -+ *p++ = ':'; -+ for (i = 0; i < IP6BYTES/2; i++) { -+ piece = (srcp[2*i] << 8) + srcp[2*i + 1]; -+ p += ultot(piece, 16, p, 5); /* 5 = abcd + NUL */ -+ *(p-1) = ':'; /* overwrites the NUL */ -+ } -+ *p = '\0'; -+ q = strstr(buf, ":0:0:"); -+ if (squish && q != NULL) { /* zero squishing is possible */ -+ p = q + 1; -+ while (*p == '0' && *(p+1) == ':') -+ p += 2; -+ q++; -+ *q++ = ':'; /* overwrite first 0 */ -+ while (*p != '\0') -+ *q++ = *p++; -+ *q = '\0'; -+ if (!(*(q-1) == ':' && *(q-2) == ':')) -+ *--q = '\0'; /* strip final : unless :: */ -+ p = buf; -+ if (!(*p == ':' && *(p+1) == ':')) -+ p++; /* skip initial : unless :: */ -+ } else { -+ q = p; -+ *--q = '\0'; /* strip final : */ -+ p = buf + 1; /* skip initial : */ -+ } -+ *dstp = p; -+ return q - p + 1; -+} -+ -+/* -+ - reverse4 - IPv4 reverse-lookup conversion -+ */ -+static size_t /* size of text, including NUL */ -+reverse4(srcp, srclen, buf, dstp) -+const unsigned char *srcp; -+size_t srclen; -+char *buf; /* guaranteed large enough */ -+char **dstp; /* where to put result pointer */ -+{ -+ int i; -+ char *p; -+ -+ if (srclen != IP4BYTES) /* "can't happen" */ -+ return 0; -+ p = buf; -+ for (i = IP4BYTES-1; i >= 0; i--) { -+ p += ultot(srcp[i], 10, p, PERBYTE); -+ *(p-1) = '.'; /* overwrites the NUL */ -+ } -+ strcpy(p, "IN-ADDR.ARPA."); -+ *dstp = buf; -+ return strlen(buf) + 1; -+} -+ -+/* -+ - reverse6 - IPv6 reverse-lookup conversion (RFC 1886) -+ * A trifle inefficient, really shouldn't use ultot... -+ */ -+static size_t /* size of text, including NUL */ -+reverse6(srcp, srclen, buf, dstp) -+const unsigned char *srcp; -+size_t srclen; -+char *buf; /* guaranteed large enough */ -+char **dstp; /* where to put result pointer */ -+{ -+ int i; -+ unsigned long piece; -+ char *p; -+ -+ if (srclen != IP6BYTES) /* "can't happen" */ -+ return 0; -+ p = buf; -+ for (i = IP6BYTES-1; i >= 0; i--) { -+ piece = srcp[i]; -+ p += ultot(piece&0xf, 16, p, 2); -+ *(p-1) = '.'; -+ p += ultot(piece>>4, 16, p, 2); -+ *(p-1) = '.'; -+ } -+ strcpy(p, "IP6.ARPA."); -+ *dstp = buf; -+ return strlen(buf) + 1; -+} -+ -+/* -+ - reverse6 - modern IPv6 reverse-lookup conversion (RFC 2874) -+ * this version removed as it was obsoleted in the end. -+ */ -+ -+#ifdef ADDRTOT_MAIN -+ -+#include -+#include -+#include -+#include -+ -+void regress(void); -+ -+int -+main(int argc, char *argv[]) -+{ -+ if (argc < 2) { -+ fprintf(stderr, "Usage: %s {addr|net/mask|begin...end|-r}\n", -+ argv[0]); -+ exit(2); -+ } -+ -+ if (strcmp(argv[1], "-r") == 0) { -+ regress(); -+ fprintf(stderr, "regress() returned?!?\n"); -+ exit(1); -+ } -+ exit(0); -+} -+ -+struct rtab { -+ char *input; -+ char format; -+ char *output; /* NULL means error expected */ -+} rtab[] = { -+ {"1.2.3.0", 0, "1.2.3.0"}, -+ {"1:2::3:4", 0, "1:2::3:4"}, -+ {"1:2::3:4", 'Q', "1:2:0:0:0:0:3:4"}, -+ {"1:2:0:0:3:4:0:0", 0, "1:2::3:4:0:0"}, -+ {"1.2.3.4", 'r' , "4.3.2.1.IN-ADDR.ARPA."}, -+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -+ {"1:2::3:4", 'r', "4.0.0.0.3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.1.0.0.0.IP6.ARPA."}, -+ {NULL, 0, NULL} -+}; -+ -+void -+regress() -+{ -+ struct rtab *r; -+ int status = 0; -+ ip_address a; -+ char in[100]; -+ char buf[100]; -+ const char *oops; -+ size_t n; -+ -+ for (r = rtab; r->input != NULL; r++) { -+ strcpy(in, r->input); -+ -+ /* convert it *to* internal format */ -+ oops = ttoaddr(in, strlen(in), 0, &a); -+ -+ /* now convert it back */ -+ -+ n = addrtot(&a, r->format, buf, sizeof(buf)); -+ -+ if (n == 0 && r->output == NULL) -+ {} /* okay, error expected */ -+ -+ else if (n == 0) { -+ printf("`%s' atoasr failed\n", r->input); -+ status = 1; -+ -+ } else if (r->output == NULL) { -+ printf("`%s' atoasr succeeded unexpectedly '%c'\n", -+ r->input, r->format); -+ status = 1; -+ } else { -+ if (strcasecmp(r->output, buf) != 0) { -+ printf("`%s' '%c' gave `%s', expected `%s'\n", -+ r->input, r->format, buf, r->output); -+ status = 1; -+ } -+ } -+ } -+ exit(status); -+} -+ -+#endif /* ADDRTOT_MAIN */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.15 2004/04/11 17:39:25 mcr -+ * removed internal.h requirements. -+ * -+ * Revision 1.14 2004/03/08 01:59:08 ken -+ * freeswan.h -> openswan.h -+ * -+ * Revision 1.13 2004/01/05 23:21:05 mcr -+ * if the address type is invalid, then return length of -+ * string! -+ * -+ * Revision 1.12 2003/12/30 06:42:48 mcr -+ * added $Log$ -+ * added Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * added Turn off EOLN_NATIVE flag -+ * added -+ * added (Logical change 1.5010) -+ * added -+ * added Revision 1.15 2004/04/11 17:39:25 mcr -+ * added removed internal.h requirements. -+ * added -+ * added Revision 1.14 2004/03/08 01:59:08 ken -+ * added freeswan.h -> openswan.h -+ * added -+ * added Revision 1.13 2004/01/05 23:21:05 mcr -+ * added if the address type is invalid, then return length of -+ * added string! -+ * added -+ * -+ * -+ */ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/addrtypeof.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,93 @@ -+/* -+ * extract parts of an ip_address -+ * Copyright (C) 2000 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - addrtypeof - get the type of an ip_address -+ */ -+int -+addrtypeof(src) -+const ip_address *src; -+{ -+ return src->u.v4.sin_family; -+} -+ -+/* -+ - addrbytesptr - get pointer to the address bytes of an ip_address -+ */ -+size_t /* 0 for error */ -+addrbytesptr(src, dstp) -+const ip_address *src; -+const unsigned char **dstp; /* NULL means just a size query */ -+{ -+ const unsigned char *p; -+ size_t n; -+ -+ switch (src->u.v4.sin_family) { -+ case AF_INET: -+ p = (const unsigned char *)&src->u.v4.sin_addr.s_addr; -+ n = 4; -+ break; -+ case AF_INET6: -+ p = (const unsigned char *)&src->u.v6.sin6_addr; -+ n = 16; -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ if (dstp != NULL) -+ *dstp = p; -+ return n; -+} -+ -+/* -+ - addrlenof - get length of the address bytes of an ip_address -+ */ -+size_t /* 0 for error */ -+addrlenof(src) -+const ip_address *src; -+{ -+ return addrbytesptr(src, NULL); -+} -+ -+/* -+ - addrbytesof - get the address bytes of an ip_address -+ */ -+size_t /* 0 for error */ -+addrbytesof(src, dst, dstlen) -+const ip_address *src; -+unsigned char *dst; -+size_t dstlen; -+{ -+ const unsigned char *p; -+ size_t n; -+ size_t ncopy; -+ -+ n = addrbytesptr(src, &p); -+ if (n == 0) -+ return 0; -+ -+ if (dstlen > 0) { -+ ncopy = n; -+ if (ncopy > dstlen) -+ ncopy = dstlen; -+ memcpy(dst, p, ncopy); -+ } -+ return n; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/anyaddr.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,145 @@ -+/* -+ * special addresses -+ * Copyright (C) 2000 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* these are mostly fallbacks for the no-IPv6-support-in-library case */ -+#ifndef IN6ADDR_ANY_INIT -+#define IN6ADDR_ANY_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}} -+#endif -+#ifndef IN6ADDR_LOOPBACK_INIT -+#define IN6ADDR_LOOPBACK_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}} -+#endif -+ -+static struct in6_addr v6any = IN6ADDR_ANY_INIT; -+static struct in6_addr v6loop = IN6ADDR_LOOPBACK_INIT; -+ -+/* -+ - anyaddr - initialize to the any-address value -+ */ -+err_t /* NULL for success, else string literal */ -+anyaddr(af, dst) -+int af; /* address family */ -+ip_address *dst; -+{ -+ uint32_t v4any = htonl(INADDR_ANY); -+ -+ switch (af) { -+ case AF_INET: -+ return initaddr((unsigned char *)&v4any, sizeof(v4any), af, dst); -+ break; -+ case AF_INET6: -+ return initaddr((unsigned char *)&v6any, sizeof(v6any), af, dst); -+ break; -+ default: -+ return "unknown address family in anyaddr/unspecaddr"; -+ break; -+ } -+} -+ -+/* -+ - unspecaddr - initialize to the unspecified-address value -+ */ -+err_t /* NULL for success, else string literal */ -+unspecaddr(af, dst) -+int af; /* address family */ -+ip_address *dst; -+{ -+ return anyaddr(af, dst); -+} -+ -+/* -+ - loopbackaddr - initialize to the loopback-address value -+ */ -+err_t /* NULL for success, else string literal */ -+loopbackaddr(af, dst) -+int af; /* address family */ -+ip_address *dst; -+{ -+ uint32_t v4loop = htonl(INADDR_LOOPBACK); -+ -+ switch (af) { -+ case AF_INET: -+ return initaddr((unsigned char *)&v4loop, sizeof(v4loop), af, dst); -+ break; -+ case AF_INET6: -+ return initaddr((unsigned char *)&v6loop, sizeof(v6loop), af, dst); -+ break; -+ default: -+ return "unknown address family in loopbackaddr"; -+ break; -+ } -+} -+ -+/* -+ - isanyaddr - test for the any-address value -+ */ -+int -+isanyaddr(src) -+const ip_address *src; -+{ -+ uint32_t v4any = htonl(INADDR_ANY); -+ int cmp; -+ -+ switch (src->u.v4.sin_family) { -+ case AF_INET: -+ cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4any, sizeof(v4any)); -+ break; -+ case AF_INET6: -+ cmp = memcmp(&src->u.v6.sin6_addr, &v6any, sizeof(v6any)); -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ return (cmp == 0) ? 1 : 0; -+} -+ -+/* -+ - isunspecaddr - test for the unspecified-address value -+ */ -+int -+isunspecaddr(src) -+const ip_address *src; -+{ -+ return isanyaddr(src); -+} -+ -+/* -+ - isloopbackaddr - test for the loopback-address value -+ */ -+int -+isloopbackaddr(src) -+const ip_address *src; -+{ -+ uint32_t v4loop = htonl(INADDR_LOOPBACK); -+ int cmp; -+ -+ switch (src->u.v4.sin_family) { -+ case AF_INET: -+ cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4loop, sizeof(v4loop)); -+ break; -+ case AF_INET6: -+ cmp = memcmp(&src->u.v6.sin6_addr, &v6loop, sizeof(v6loop)); -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ return (cmp == 0) ? 1 : 0; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/datatot.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,232 @@ -+/* -+ * convert from binary data (e.g. key) to text form -+ * Copyright (C) 2000 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+static void convert(const char *src, size_t nreal, int format, char *out); -+ -+/* -+ - datatot - convert data bytes to text -+ */ -+size_t /* true length (with NUL) for success */ -+datatot(src, srclen, format, dst, dstlen) -+const char *src; -+size_t srclen; -+int format; /* character indicating what format */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ size_t inblocksize; /* process this many bytes at a time */ -+ size_t outblocksize; /* producing this many */ -+ size_t breakevery; /* add a _ every this many (0 means don't) */ -+ size_t sincebreak; /* output bytes since last _ */ -+ char breakchar; /* character used to break between groups */ -+ char inblock[10]; /* enough for any format */ -+ char outblock[10]; /* enough for any format */ -+ char fake[1]; /* fake output area for dstlen == 0 */ -+ size_t needed; /* return value */ -+ char *stop; /* where the terminating NUL will go */ -+ size_t ntodo; /* remaining input */ -+ size_t nreal; -+ char *out; -+ char *prefix; -+ -+ breakevery = 0; -+ breakchar = '_'; -+ -+ switch (format) { -+ case 0: -+ case 'h': -+ format = 'x'; -+ breakevery = 8; -+ /* FALLTHROUGH */ -+ case 'x': -+ inblocksize = 1; -+ outblocksize = 2; -+ prefix = "0x"; -+ break; -+ case ':': -+ format = 'x'; -+ breakevery = 2; -+ breakchar = ':'; -+ /* FALLTHROUGH */ -+ case 16: -+ inblocksize = 1; -+ outblocksize = 2; -+ prefix = ""; -+ format = 'x'; -+ break; -+ case 's': -+ inblocksize = 3; -+ outblocksize = 4; -+ prefix = "0s"; -+ break; -+ case 64: /* beware, equals ' ' */ -+ inblocksize = 3; -+ outblocksize = 4; -+ prefix = ""; -+ format = 's'; -+ break; -+ default: -+ return 0; -+ break; -+ } -+ assert(inblocksize < sizeof(inblock)); -+ assert(outblocksize < sizeof(outblock)); -+ assert(breakevery % outblocksize == 0); -+ -+ if (srclen == 0) -+ return 0; -+ ntodo = srclen; -+ -+ if (dstlen == 0) { /* dispose of awkward special case */ -+ dst = fake; -+ dstlen = 1; -+ } -+ stop = dst + dstlen - 1; -+ -+ nreal = strlen(prefix); -+ needed = nreal; /* for starters */ -+ if (dstlen <= nreal) { /* prefix won't fit */ -+ strncpy(dst, prefix, dstlen - 1); -+ dst += dstlen - 1; -+ } else { -+ strcpy(dst, prefix); -+ dst += nreal; -+ } -+ assert(dst <= stop); -+ sincebreak = 0; -+ -+ while (ntodo > 0) { -+ if (ntodo < inblocksize) { /* incomplete input */ -+ memset(inblock, 0, sizeof(inblock)); -+ memcpy(inblock, src, ntodo); -+ src = inblock; -+ nreal = ntodo; -+ ntodo = inblocksize; -+ } else -+ nreal = inblocksize; -+ out = (outblocksize > stop - dst) ? outblock : dst; -+ -+ convert(src, nreal, format, out); -+ needed += outblocksize; -+ sincebreak += outblocksize; -+ if (dst < stop) { -+ if (out != dst) { -+ assert(outblocksize > stop - dst); -+ memcpy(dst, out, stop - dst); -+ dst = stop; -+ } else -+ dst += outblocksize; -+ } -+ -+ src += inblocksize; -+ ntodo -= inblocksize; -+ if (breakevery != 0 && sincebreak >= breakevery && ntodo > 0) { -+ if (dst < stop) -+ *dst++ = breakchar; -+ needed++; -+ sincebreak = 0; -+ } -+ } -+ -+ assert(dst <= stop); -+ *dst++ = '\0'; -+ needed++; -+ -+ return needed; -+} -+ -+/* -+ - convert - convert one input block to one output block -+ */ -+static void -+convert(src, nreal, format, out) -+const char *src; -+size_t nreal; /* how much of the input block is real */ -+int format; -+char *out; -+{ -+ static char hex[] = "0123456789abcdef"; -+ static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -+ "abcdefghijklmnopqrstuvwxyz" -+ "0123456789+/"; -+ unsigned char c; -+ unsigned char c1, c2, c3; -+ -+ assert(nreal > 0); -+ switch (format) { -+ case 'x': -+ assert(nreal == 1); -+ c = (unsigned char)*src; -+ *out++ = hex[c >> 4]; -+ *out++ = hex[c & 0xf]; -+ break; -+ case 's': -+ c1 = (unsigned char)*src++; -+ c2 = (unsigned char)*src++; -+ c3 = (unsigned char)*src++; -+ *out++ = base64[c1 >> 2]; /* top 6 bits of c1 */ -+ c = (c1 & 0x3) << 4; /* bottom 2 of c1... */ -+ c |= c2 >> 4; /* ...top 4 of c2 */ -+ *out++ = base64[c]; -+ if (nreal == 1) -+ *out++ = '='; -+ else { -+ c = (c2 & 0xf) << 2; /* bottom 4 of c2... */ -+ c |= c3 >> 6; /* ...top 2 of c3 */ -+ *out++ = base64[c]; -+ } -+ if (nreal <= 2) -+ *out++ = '='; -+ else -+ *out++ = base64[c3 & 0x3f]; /* bottom 6 of c3 */ -+ break; -+ default: -+ assert(nreal == 0); /* unknown format */ -+ break; -+ } -+} -+ -+/* -+ - datatoa - convert data to ASCII -+ * backward-compatibility synonym for datatot -+ */ -+size_t /* true length (with NUL) for success */ -+datatoa(src, srclen, format, dst, dstlen) -+const char *src; -+size_t srclen; -+int format; /* character indicating what format */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ return datatot(src, srclen, format, dst, dstlen); -+} -+ -+/* -+ - bytestoa - convert data bytes to ASCII -+ * backward-compatibility synonym for datatot -+ */ -+size_t /* true length (with NUL) for success */ -+bytestoa(src, srclen, format, dst, dstlen) -+const char *src; -+size_t srclen; -+int format; /* character indicating what format */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ return datatot(src, srclen, format, dst, dstlen); -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/goodmask.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,100 @@ -+/* -+ * minor utilities for subnet-mask manipulation -+ * Copyright (C) 1998, 1999 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+#ifndef ABITS -+#define ABITS 32 /* bits in an IPv4 address */ -+#endif -+ -+/* -+ - goodmask - is this a good (^1*0*$) subnet mask? -+ * You are not expected to understand this. See Henry S. Warren Jr, -+ * "Functions realizable with word-parallel logical and two's-complement -+ * addition instructions", CACM 20.6 (June 1977), p.439. -+ */ -+int /* predicate */ -+goodmask(mask) -+struct in_addr mask; -+{ -+ unsigned long x = ntohl(mask.s_addr); -+ /* clear rightmost contiguous string of 1-bits */ -+# define CRCS1B(x) (((x|(x-1))+1)&x) -+# define TOPBIT (1UL << 31) -+ -+ /* either zero, or has one string of 1-bits which is left-justified */ -+ if (x == 0 || (CRCS1B(x) == 0 && (x&TOPBIT))) -+ return 1; -+ return 0; -+} -+ -+/* -+ - masktobits - how many bits in this mask? -+ * The algorithm is essentially a binary search, but highly optimized -+ * for this particular task. -+ */ -+int /* -1 means !goodmask() */ -+masktobits(mask) -+struct in_addr mask; -+{ -+ unsigned long m = ntohl(mask.s_addr); -+ int masklen; -+ -+ if (!goodmask(mask)) -+ return -1; -+ -+ if (m&0x00000001UL) -+ return 32; -+ masklen = 0; -+ if (m&(0x0000ffffUL<<1)) { /* <<1 for 1-origin numbering */ -+ masklen |= 0x10; -+ m <<= 16; -+ } -+ if (m&(0x00ff0000UL<<1)) { -+ masklen |= 0x08; -+ m <<= 8; -+ } -+ if (m&(0x0f000000UL<<1)) { -+ masklen |= 0x04; -+ m <<= 4; -+ } -+ if (m&(0x30000000UL<<1)) { -+ masklen |= 0x02; -+ m <<= 2; -+ } -+ if (m&(0x40000000UL<<1)) -+ masklen |= 0x01; -+ -+ return masklen; -+} -+ -+/* -+ - bitstomask - return a mask with this many high bits on -+ */ -+struct in_addr -+bitstomask(n) -+int n; -+{ -+ struct in_addr result; -+ -+ if (n > 0 && n <= ABITS) -+ result.s_addr = htonl(~((1UL << (ABITS - n)) - 1)); -+ else if (n == 0) -+ result.s_addr = 0; -+ else -+ result.s_addr = 0; /* best error report we can do */ -+ return result; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/initaddr.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,50 @@ -+/* -+ * initialize address structure -+ * Copyright (C) 2000 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - initaddr - initialize ip_address from bytes -+ */ -+err_t /* NULL for success, else string literal */ -+initaddr(src, srclen, af, dst) -+const unsigned char *src; -+size_t srclen; -+int af; /* address family */ -+ip_address *dst; -+{ -+ switch (af) { -+ case AF_INET: -+ if (srclen != 4) -+ return "IPv4 address must be exactly 4 bytes"; -+ dst->u.v4.sin_family = af; -+ dst->u.v4.sin_port = 0; /* unused */ -+ memcpy((char *)&dst->u.v4.sin_addr.s_addr, src, srclen); -+ break; -+ case AF_INET6: -+ if (srclen != 16) -+ return "IPv6 address must be exactly 16 bytes"; -+ dst->u.v6.sin6_family = af; -+ dst->u.v6.sin6_flowinfo = 0; /* unused */ -+ dst->u.v6.sin6_port = 0; /* unused */ -+ memcpy((char *)&dst->u.v6.sin6_addr, src, srclen); -+ break; -+ default: -+ return "unknown address family in initaddr"; -+ break; -+ } -+ return NULL; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/pfkey_v2_build.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1559 @@ -+/* -+ * RFC2367 PF_KEYv2 Key management API message parser -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* -+ * Template from klips/net/ipsec/ipsec/ipsec_parser.c. -+ */ -+ -+char pfkey_v2_build_c_version[] = "$Id$"; -+ -+/* -+ * Some ugly stuff to allow consistent debugging code for use in the -+ * kernel and in user space -+*/ -+ -+#ifdef __KERNEL__ -+ -+# include /* for printk */ -+ -+# include "openswan/ipsec_kversion.h" /* for malloc switch */ -+# ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+# else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+# endif /* MALLOC_SLAB */ -+# include /* error codes */ -+# include /* size_t */ -+# include /* mark_bh */ -+ -+# include /* struct device, and other headers */ -+# include /* eth_type_trans */ -+# include /* struct iphdr */ -+# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+# include /* struct ipv6hdr */ -+# endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ -+ -+# define MALLOC(size) kmalloc(size, GFP_ATOMIC) -+# define FREE(obj) kfree(obj) -+# include -+#else /* __KERNEL__ */ -+ -+# include -+# include -+# include -+# include -+# include /* memset */ -+ -+# include -+ -+#endif /* __KERNEL__ */ -+ -+#include -+#include -+ -+#ifdef __KERNEL__ -+#include "openswan/radij.h" /* rd_nodes */ -+#include "openswan/ipsec_encap.h" /* sockaddr_encap */ -+#endif /* __KERNEL__ */ -+ -+ -+#include "openswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */ -+#include "openswan/pfkey_debug.h" -+ -+ -+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) -+ -+void -+pfkey_extensions_init(struct sadb_ext *extensions[SADB_EXT_MAX + 1]) -+{ -+ int i; -+ -+ for (i = 0; i != SADB_EXT_MAX + 1; i++) { -+ extensions[i] = NULL; -+ } -+} -+ -+void -+pfkey_extensions_free(struct sadb_ext *extensions[SADB_EXT_MAX + 1]) -+{ -+ int i; -+ -+ if(!extensions) { -+ return; -+ } -+ -+ if(extensions[0]) { -+ memset(extensions[0], 0, sizeof(struct sadb_msg)); -+ FREE(extensions[0]); -+ extensions[0] = NULL; -+ } -+ -+ for (i = 1; i != SADB_EXT_MAX + 1; i++) { -+ if(extensions[i]) { -+ memset(extensions[i], 0, extensions[i]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); -+ FREE(extensions[i]); -+ extensions[i] = NULL; -+ } -+ } -+} -+ -+void -+pfkey_msg_free(struct sadb_msg **pfkey_msg) -+{ -+ if(*pfkey_msg) { -+ memset(*pfkey_msg, 0, (*pfkey_msg)->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); -+ FREE(*pfkey_msg); -+ *pfkey_msg = NULL; -+ } -+} -+ -+/* Default extension builders taken from the KLIPS code */ -+ -+int -+pfkey_msg_hdr_build(struct sadb_ext** pfkey_ext, -+ uint8_t msg_type, -+ uint8_t satype, -+ uint8_t msg_errno, -+ uint32_t seq, -+ uint32_t pid) -+{ -+ int error = 0; -+ struct sadb_msg *pfkey_msg = (struct sadb_msg *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build:\n"); -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build: " -+ "on_entry &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n", -+ &pfkey_ext, -+ pfkey_ext, -+ *pfkey_ext); -+ /* sanity checks... */ -+ if(pfkey_msg) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build: " -+ "why is pfkey_msg already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(!msg_type) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build: " -+ "msg type not set, must be non-zero..\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(msg_type > SADB_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build: " -+ "msg type too large:%d.\n", -+ msg_type); -+ SENDERR(EINVAL); -+ } -+ -+ if(satype > SADB_SATYPE_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build: " -+ "satype %d > max %d\n", -+ satype, SADB_SATYPE_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_msg = (struct sadb_msg*) -+ MALLOC(sizeof(struct sadb_msg)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_msg, 0, sizeof(struct sadb_msg)); -+ -+ pfkey_msg->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN; -+ -+ pfkey_msg->sadb_msg_type = msg_type; -+ pfkey_msg->sadb_msg_satype = satype; -+ -+ pfkey_msg->sadb_msg_version = PF_KEY_V2; -+ pfkey_msg->sadb_msg_errno = msg_errno; -+ pfkey_msg->sadb_msg_reserved = 0; -+ pfkey_msg->sadb_msg_seq = seq; -+ pfkey_msg->sadb_msg_pid = pid; -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build: " -+ "on_exit &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n", -+ &pfkey_ext, -+ pfkey_ext, -+ *pfkey_ext); -+errlab: -+ return error; -+} -+ -+int -+pfkey_sa_ref_build(struct sadb_ext ** pfkey_ext, -+ uint16_t exttype, -+ uint32_t spi, -+ uint8_t replay_window, -+ uint8_t sa_state, -+ uint8_t auth, -+ uint8_t encrypt, -+ uint32_t flags, -+ uint32_t/*IPsecSAref_t*/ ref) -+{ -+ int error = 0; -+ struct sadb_sa *pfkey_sa = (struct sadb_sa *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "spi=%08x replay=%d sa_state=%d auth=%d encrypt=%d flags=%d\n", -+ ntohl(spi), /* in network order */ -+ replay_window, -+ sa_state, -+ auth, -+ encrypt, -+ flags); -+ /* sanity checks... */ -+ if(pfkey_sa) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "why is pfkey_sa already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(exttype != SADB_EXT_SA && -+ exttype != SADB_X_EXT_SA2) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "invalid exttype=%d.\n", -+ exttype); -+ SENDERR(EINVAL); -+ } -+ -+ if(replay_window > 64) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "replay window size: %d -- must be 0 <= size <= 64\n", -+ replay_window); -+ SENDERR(EINVAL); -+ } -+ -+ if(auth > SADB_AALG_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "auth=%d > SADB_AALG_MAX=%d.\n", -+ auth, -+ SADB_AALG_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(encrypt > SADB_EALG_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "encrypt=%d > SADB_EALG_MAX=%d.\n", -+ encrypt, -+ SADB_EALG_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(sa_state > SADB_SASTATE_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "sa_state=%d exceeds MAX=%d.\n", -+ sa_state, -+ SADB_SASTATE_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(sa_state == SADB_SASTATE_DEAD) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "sa_state=%d is DEAD=%d is not allowed.\n", -+ sa_state, -+ SADB_SASTATE_DEAD); -+ SENDERR(EINVAL); -+ } -+ -+ if((IPSEC_SAREF_NULL != ref) && (ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n", -+ ref, -+ IPSEC_SAREF_NULL, -+ IPSEC_SA_REF_TABLE_NUM_ENTRIES); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_sa = (struct sadb_sa*) -+ MALLOC(sizeof(struct sadb_sa)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_sa, 0, sizeof(struct sadb_sa)); -+ -+ pfkey_sa->sadb_sa_len = sizeof(*pfkey_sa) / IPSEC_PFKEYv2_ALIGN; -+ pfkey_sa->sadb_sa_exttype = exttype; -+ pfkey_sa->sadb_sa_spi = spi; -+ pfkey_sa->sadb_sa_replay = replay_window; -+ pfkey_sa->sadb_sa_state = sa_state; -+ pfkey_sa->sadb_sa_auth = auth; -+ pfkey_sa->sadb_sa_encrypt = encrypt; -+ pfkey_sa->sadb_sa_flags = flags; -+ pfkey_sa->sadb_x_sa_ref = ref; -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_sa_build(struct sadb_ext ** pfkey_ext, -+ uint16_t exttype, -+ uint32_t spi, -+ uint8_t replay_window, -+ uint8_t sa_state, -+ uint8_t auth, -+ uint8_t encrypt, -+ uint32_t flags) -+{ -+ return pfkey_sa_ref_build(pfkey_ext, -+ exttype, -+ spi, -+ replay_window, -+ sa_state, -+ auth, -+ encrypt, -+ flags, -+ IPSEC_SAREF_NULL); -+} -+ -+int -+pfkey_lifetime_build(struct sadb_ext ** pfkey_ext, -+ uint16_t exttype, -+ uint32_t allocations, -+ uint64_t bytes, -+ uint64_t addtime, -+ uint64_t usetime, -+ uint32_t packets) -+{ -+ int error = 0; -+ struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_lifetime_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_lifetime) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_lifetime_build: " -+ "why is pfkey_lifetime already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(exttype != SADB_EXT_LIFETIME_CURRENT && -+ exttype != SADB_EXT_LIFETIME_HARD && -+ exttype != SADB_EXT_LIFETIME_SOFT) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_lifetime_build: " -+ "invalid exttype=%d.\n", -+ exttype); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_lifetime = (struct sadb_lifetime*) -+ MALLOC(sizeof(struct sadb_lifetime)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_lifetime_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_lifetime, 0, sizeof(struct sadb_lifetime)); -+ -+ pfkey_lifetime->sadb_lifetime_len = sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN; -+ pfkey_lifetime->sadb_lifetime_exttype = exttype; -+ pfkey_lifetime->sadb_lifetime_allocations = allocations; -+ pfkey_lifetime->sadb_lifetime_bytes = bytes; -+ pfkey_lifetime->sadb_lifetime_addtime = addtime; -+ pfkey_lifetime->sadb_lifetime_usetime = usetime; -+ pfkey_lifetime->sadb_x_lifetime_packets = packets; -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_address_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint8_t proto, -+ uint8_t prefixlen, -+ struct sockaddr* address) -+{ -+ int error = 0; -+ int saddr_len = 0; -+ char ipaddr_txt[ADDRTOT_BUF + 6/*extra for port number*/]; -+ struct sadb_address *pfkey_address = (struct sadb_address *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_address_build: " -+ "exttype=%d proto=%d prefixlen=%d\n", -+ exttype, -+ proto, -+ prefixlen); -+ /* sanity checks... */ -+ if(pfkey_address) { -+ ERROR("pfkey_address_build: " -+ "why is pfkey_address already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if (!address) { -+ ERROR("pfkey_address_build: " "address is NULL\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(exttype) { -+ case SADB_EXT_ADDRESS_SRC: -+ case SADB_EXT_ADDRESS_DST: -+ case SADB_EXT_ADDRESS_PROXY: -+ case SADB_X_EXT_ADDRESS_DST2: -+ case SADB_X_EXT_ADDRESS_SRC_FLOW: -+ case SADB_X_EXT_ADDRESS_DST_FLOW: -+ case SADB_X_EXT_ADDRESS_SRC_MASK: -+ case SADB_X_EXT_ADDRESS_DST_MASK: -+#ifdef NAT_TRAVERSAL -+ case SADB_X_EXT_NAT_T_OA: -+#endif -+ break; -+ default: -+ ERROR("pfkey_address_build: " -+ "unrecognised ext_type=%d.\n", -+ exttype); -+ SENDERR(EINVAL); -+ } -+ -+ switch(address->sa_family) { -+ case AF_INET: -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_address_build: " -+ "found address family AF_INET.\n"); -+ saddr_len = sizeof(struct sockaddr_in); -+ sprintf(ipaddr_txt, "%d.%d.%d.%d:%d" -+ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 0) & 0xFF -+ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 8) & 0xFF -+ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 16) & 0xFF -+ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 24) & 0xFF -+ , ntohs(((struct sockaddr_in*)address)->sin_port)); -+ break; -+ case AF_INET6: -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_address_build: " -+ "found address family AF_INET6.\n"); -+ saddr_len = sizeof(struct sockaddr_in6); -+ sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x-%x" -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[0]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[1]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[2]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[3]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[4]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[5]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[6]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[7]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_port)); -+ break; -+ default: -+ ERROR("pfkey_address_build: " -+ "address->sa_family=%d not supported.\n", -+ address->sa_family); -+ SENDERR(EPFNOSUPPORT); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_address_build: " -+ "found address=%s.\n", -+ ipaddr_txt); -+ if(prefixlen != 0) { -+ ERROR("pfkey_address_build: " -+ "address prefixes not supported yet.\n"); -+ SENDERR(EAFNOSUPPORT); /* not supported yet */ -+ } -+ -+ /* allocate some memory for the extension */ -+ pfkey_address = (struct sadb_address*) -+ MALLOC(ALIGN_N(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)); -+ *pfkey_ext = (struct sadb_ext*)pfkey_address; -+ -+ if(pfkey_address == NULL ) { -+ ERROR("pfkey_lifetime_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_address, -+ 0, -+ ALIGN_N(sizeof(struct sadb_address) + saddr_len, -+ IPSEC_PFKEYv2_ALIGN)); -+ -+ pfkey_address->sadb_address_len = DIVUP(sizeof(struct sadb_address) + saddr_len, -+ IPSEC_PFKEYv2_ALIGN); -+ -+ pfkey_address->sadb_address_exttype = exttype; -+ pfkey_address->sadb_address_proto = proto; -+ pfkey_address->sadb_address_prefixlen = prefixlen; -+ pfkey_address->sadb_address_reserved = 0; -+ -+ memcpy((char*)pfkey_address + sizeof(struct sadb_address), -+ address, -+ saddr_len); -+ -+#if 0 -+ for(i = 0; i < sizeof(struct sockaddr_in) - offsetof(struct sockaddr_in, sin_zero); i++) { -+ pfkey_address_s_ska.sin_zero[i] = 0; -+ } -+#endif -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_address_build: " -+ "successful created len: %d.\n", pfkey_address->sadb_address_len); -+ -+ errlab: -+ return error; -+} -+ -+int -+pfkey_key_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint16_t key_bits, -+ char* key) -+{ -+ int error = 0; -+ struct sadb_key *pfkey_key = (struct sadb_key *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_key_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_key) { -+ ERROR("pfkey_key_build: " -+ "why is pfkey_key already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(!key_bits) { -+ ERROR("pfkey_key_build: " -+ "key_bits is zero, it must be non-zero.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if( !((exttype == SADB_EXT_KEY_AUTH) || (exttype == SADB_EXT_KEY_ENCRYPT))) { -+ ERROR("pfkey_key_build: " -+ "unsupported extension type=%d.\n", -+ exttype); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_key = (struct sadb_key*) -+ MALLOC(sizeof(struct sadb_key) + -+ DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN))) { -+ ERROR("pfkey_key_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_key, -+ 0, -+ sizeof(struct sadb_key) + -+ DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN); -+ -+ pfkey_key->sadb_key_len = DIVUP(sizeof(struct sadb_key) * IPSEC_PFKEYv2_ALIGN + key_bits, -+ 64); -+ pfkey_key->sadb_key_exttype = exttype; -+ pfkey_key->sadb_key_bits = key_bits; -+ pfkey_key->sadb_key_reserved = 0; -+ memcpy((char*)pfkey_key + sizeof(struct sadb_key), -+ key, -+ DIVUP(key_bits, 8)); -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_ident_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint16_t ident_type, -+ uint64_t ident_id, -+ uint8_t ident_len, -+ char* ident_string) -+{ -+ int error = 0; -+ struct sadb_ident *pfkey_ident = (struct sadb_ident *)*pfkey_ext; -+ int data_len = ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_ident_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_ident) { -+ ERROR("pfkey_ident_build: " -+ "why is pfkey_ident already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if( ! ((exttype == SADB_EXT_IDENTITY_SRC) || -+ (exttype == SADB_EXT_IDENTITY_DST))) { -+ ERROR("pfkey_ident_build: " -+ "unsupported extension type=%d.\n", -+ exttype); -+ SENDERR(EINVAL); -+ } -+ -+ if((ident_type == SADB_IDENTTYPE_RESERVED)) { -+ ERROR("pfkey_ident_build: " -+ "ident_type must be non-zero.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(ident_type > SADB_IDENTTYPE_MAX) { -+ ERROR("pfkey_ident_build: " -+ "identtype=%d out of range.\n", -+ ident_type); -+ SENDERR(EINVAL); -+ } -+ -+ if(((ident_type == SADB_IDENTTYPE_PREFIX) || -+ (ident_type == SADB_IDENTTYPE_FQDN)) && -+ !ident_string) { -+ ERROR("pfkey_ident_build: " -+ "string required to allocate size of extension.\n"); -+ SENDERR(EINVAL); -+ } -+ -+#if 0 -+ if((ident_type == SADB_IDENTTYPE_USERFQDN) ) { -+ } -+#endif -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_ident = (struct sadb_ident*) -+ MALLOC(ident_len * IPSEC_PFKEYv2_ALIGN))) { -+ ERROR("pfkey_ident_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_ident, 0, ident_len * IPSEC_PFKEYv2_ALIGN); -+ -+ pfkey_ident->sadb_ident_len = ident_len; -+ pfkey_ident->sadb_ident_exttype = exttype; -+ pfkey_ident->sadb_ident_type = ident_type; -+ pfkey_ident->sadb_ident_reserved = 0; -+ pfkey_ident->sadb_ident_id = ident_id; -+ memcpy((char*)pfkey_ident + sizeof(struct sadb_ident), -+ ident_string, -+ data_len); -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_sens_build(struct sadb_ext** pfkey_ext, -+ uint32_t dpd, -+ uint8_t sens_level, -+ uint8_t sens_len, -+ uint64_t* sens_bitmap, -+ uint8_t integ_level, -+ uint8_t integ_len, -+ uint64_t* integ_bitmap) -+{ -+ int error = 0; -+ struct sadb_sens *pfkey_sens = (struct sadb_sens *)*pfkey_ext; -+ int i; -+ uint64_t* bitmap; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sens_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_sens) { -+ ERROR("pfkey_sens_build: " -+ "why is pfkey_sens already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sens_build: " -+ "Sorry, I can't build exttype=%d yet.\n", -+ (*pfkey_ext)->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_sens = (struct sadb_sens*) -+ MALLOC(sizeof(struct sadb_sens) + -+ (sens_len + integ_len) * sizeof(uint64_t)))) { -+ ERROR("pfkey_sens_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_sens, -+ 0, -+ sizeof(struct sadb_sens) + -+ (sens_len + integ_len) * sizeof(uint64_t)); -+ -+ pfkey_sens->sadb_sens_len = (sizeof(struct sadb_sens) + -+ (sens_len + integ_len) * sizeof(uint64_t)) / IPSEC_PFKEYv2_ALIGN; -+ pfkey_sens->sadb_sens_exttype = SADB_EXT_SENSITIVITY; -+ pfkey_sens->sadb_sens_dpd = dpd; -+ pfkey_sens->sadb_sens_sens_level = sens_level; -+ pfkey_sens->sadb_sens_sens_len = sens_len; -+ pfkey_sens->sadb_sens_integ_level = integ_level; -+ pfkey_sens->sadb_sens_integ_len = integ_len; -+ pfkey_sens->sadb_sens_reserved = 0; -+ -+ bitmap = (uint64_t*)((char*)pfkey_ext + sizeof(struct sadb_sens)); -+ for(i = 0; i < sens_len; i++) { -+ *bitmap = sens_bitmap[i]; -+ bitmap++; -+ } -+ for(i = 0; i < integ_len; i++) { -+ *bitmap = integ_bitmap[i]; -+ bitmap++; -+ } -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_prop_build(struct sadb_ext** pfkey_ext, -+ uint8_t replay, -+ unsigned int comb_num, -+ struct sadb_comb* comb) -+{ -+ int error = 0; -+ int i; -+ struct sadb_prop *pfkey_prop = (struct sadb_prop *)*pfkey_ext; -+ struct sadb_comb *combp; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_prop_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_prop) { -+ ERROR("pfkey_prop_build: " -+ "why is pfkey_prop already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_prop = (struct sadb_prop*) -+ MALLOC(sizeof(struct sadb_prop) + -+ comb_num * sizeof(struct sadb_comb)))) { -+ ERROR("pfkey_prop_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_prop, -+ 0, -+ sizeof(struct sadb_prop) + -+ comb_num * sizeof(struct sadb_comb)); -+ -+ pfkey_prop->sadb_prop_len = (sizeof(struct sadb_prop) + -+ comb_num * sizeof(struct sadb_comb)) / IPSEC_PFKEYv2_ALIGN; -+ -+ pfkey_prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; -+ pfkey_prop->sadb_prop_replay = replay; -+ -+ for(i=0; i<3; i++) { -+ pfkey_prop->sadb_prop_reserved[i] = 0; -+ } -+ -+ combp = (struct sadb_comb*)((char*)*pfkey_ext + sizeof(struct sadb_prop)); -+ for(i = 0; i < comb_num; i++) { -+ memcpy (combp, &(comb[i]), sizeof(struct sadb_comb)); -+ combp++; -+ } -+ -+#if 0 -+ uint8_t sadb_comb_auth; -+ uint8_t sadb_comb_encrypt; -+ uint16_t sadb_comb_flags; -+ uint16_t sadb_comb_auth_minbits; -+ uint16_t sadb_comb_auth_maxbits; -+ uint16_t sadb_comb_encrypt_minbits; -+ uint16_t sadb_comb_encrypt_maxbits; -+ uint32_t sadb_comb_reserved; -+ uint32_t sadb_comb_soft_allocations; -+ uint32_t sadb_comb_hard_allocations; -+ uint64_t sadb_comb_soft_bytes; -+ uint64_t sadb_comb_hard_bytes; -+ uint64_t sadb_comb_soft_addtime; -+ uint64_t sadb_comb_hard_addtime; -+ uint64_t sadb_comb_soft_usetime; -+ uint64_t sadb_comb_hard_usetime; -+ uint32_t sadb_comb_soft_packets; -+ uint32_t sadb_comb_hard_packets; -+#endif -+errlab: -+ return error; -+} -+ -+int -+pfkey_supported_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ unsigned int alg_num, -+ struct sadb_alg* alg) -+{ -+ int error = 0; -+ unsigned int i; -+ struct sadb_supported *pfkey_supported = (struct sadb_supported *)*pfkey_ext; -+ struct sadb_alg *pfkey_alg; -+ -+ /* sanity checks... */ -+ if(pfkey_supported) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_supported_build: " -+ "why is pfkey_supported already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if( !((exttype == SADB_EXT_SUPPORTED_AUTH) || (exttype == SADB_EXT_SUPPORTED_ENCRYPT))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_supported_build: " -+ "unsupported extension type=%d.\n", -+ exttype); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_supported = (struct sadb_supported*) -+ MALLOC(sizeof(struct sadb_supported) + -+ alg_num * -+ sizeof(struct sadb_alg)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_supported_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_supported, -+ 0, -+ sizeof(struct sadb_supported) + -+ alg_num * -+ sizeof(struct sadb_alg)); -+ -+ pfkey_supported->sadb_supported_len = (sizeof(struct sadb_supported) + -+ alg_num * -+ sizeof(struct sadb_alg)) / -+ IPSEC_PFKEYv2_ALIGN; -+ pfkey_supported->sadb_supported_exttype = exttype; -+ pfkey_supported->sadb_supported_reserved = 0; -+ -+ pfkey_alg = (struct sadb_alg*)((char*)pfkey_supported + sizeof(struct sadb_supported)); -+ for(i = 0; i < alg_num; i++) { -+ memcpy (pfkey_alg, &(alg[i]), sizeof(struct sadb_alg)); -+ pfkey_alg->sadb_alg_reserved = 0; -+ pfkey_alg++; -+ } -+ -+#if 0 -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_supported_build: " -+ "Sorry, I can't build exttype=%d yet.\n", -+ (*pfkey_ext)->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ -+ uint8_t sadb_alg_id; -+ uint8_t sadb_alg_ivlen; -+ uint16_t sadb_alg_minbits; -+ uint16_t sadb_alg_maxbits; -+ uint16_t sadb_alg_reserved; -+#endif -+errlab: -+ return error; -+} -+ -+int -+pfkey_spirange_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint32_t min, /* in network order */ -+ uint32_t max) /* in network order */ -+{ -+ int error = 0; -+ struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)*pfkey_ext; -+ -+ /* sanity checks... */ -+ if(pfkey_spirange) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_spirange_build: " -+ "why is pfkey_spirange already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(ntohl(max) < ntohl(min)) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_spirange_build: " -+ "minspi=%08x must be < maxspi=%08x.\n", -+ ntohl(min), -+ ntohl(max)); -+ SENDERR(EINVAL); -+ } -+ -+ if(ntohl(min) <= 255) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_spirange_build: " -+ "minspi=%08x must be > 255.\n", -+ ntohl(min)); -+ SENDERR(EEXIST); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_spirange = (struct sadb_spirange*) -+ MALLOC(sizeof(struct sadb_spirange)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_spirange_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_spirange, -+ 0, -+ sizeof(struct sadb_spirange)); -+ -+ pfkey_spirange->sadb_spirange_len = sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN; -+ -+ pfkey_spirange->sadb_spirange_exttype = SADB_EXT_SPIRANGE; -+ pfkey_spirange->sadb_spirange_min = min; -+ pfkey_spirange->sadb_spirange_max = max; -+ pfkey_spirange->sadb_spirange_reserved = 0; -+ errlab: -+ return error; -+} -+ -+int -+pfkey_x_kmprivate_build(struct sadb_ext** pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)*pfkey_ext; -+ -+ /* sanity checks... */ -+ if(pfkey_x_kmprivate) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_kmprivate_build: " -+ "why is pfkey_x_kmprivate already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_kmprivate_build: " -+ "Sorry, I can't build exttype=%d yet.\n", -+ (*pfkey_ext)->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_x_kmprivate = (struct sadb_x_kmprivate*) -+ MALLOC(sizeof(struct sadb_x_kmprivate)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_kmprivate_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_x_kmprivate, -+ 0, -+ sizeof(struct sadb_x_kmprivate)); -+ -+ pfkey_x_kmprivate->sadb_x_kmprivate_len = -+ sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN; -+ -+ pfkey_x_kmprivate->sadb_x_kmprivate_exttype = SADB_X_EXT_KMPRIVATE; -+ pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0; -+errlab: -+ return error; -+} -+ -+int -+pfkey_x_satype_build(struct sadb_ext** pfkey_ext, -+ uint8_t satype) -+{ -+ int error = 0; -+ int i; -+ struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_satype_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_x_satype) { -+ ERROR("pfkey_x_satype_build: " -+ "why is pfkey_x_satype already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(!satype) { -+ ERROR("pfkey_x_satype_build: " -+ "SA type not set, must be non-zero.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(satype > SADB_SATYPE_MAX) { -+ ERROR("pfkey_x_satype_build: " -+ "satype %d > max %d\n", -+ satype, SADB_SATYPE_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_satype = (struct sadb_x_satype*) -+ MALLOC(sizeof(struct sadb_x_satype)))) { -+ ERROR("pfkey_x_satype_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_x_satype, -+ 0, -+ sizeof(struct sadb_x_satype)); -+ -+ pfkey_x_satype->sadb_x_satype_len = sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN; -+ -+ pfkey_x_satype->sadb_x_satype_exttype = SADB_X_EXT_SATYPE2; -+ pfkey_x_satype->sadb_x_satype_satype = satype; -+ for(i=0; i<3; i++) { -+ pfkey_x_satype->sadb_x_satype_reserved[i] = 0; -+ } -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_x_debug_build(struct sadb_ext** pfkey_ext, -+ uint32_t tunnel, -+ uint32_t netlink, -+ uint32_t xform, -+ uint32_t eroute, -+ uint32_t spi, -+ uint32_t radij, -+ uint32_t esp, -+ uint32_t ah, -+ uint32_t rcv, -+ uint32_t pfkey, -+ uint32_t ipcomp, -+ uint32_t verbose) -+{ -+ int error = 0; -+ int i; -+ struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_debug_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_x_debug) { -+ ERROR("pfkey_x_debug_build: " -+ "why is pfkey_x_debug already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_debug_build: " -+ "tunnel=%x netlink=%x xform=%x eroute=%x spi=%x radij=%x esp=%x ah=%x rcv=%x pfkey=%x ipcomp=%x verbose=%x?\n", -+ tunnel, netlink, xform, eroute, spi, radij, esp, ah, rcv, pfkey, ipcomp, verbose); -+ -+ if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_debug = (struct sadb_x_debug*) -+ MALLOC(sizeof(struct sadb_x_debug)))) { -+ ERROR("pfkey_x_debug_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+#if 0 -+ memset(pfkey_x_debug, -+ 0, -+ sizeof(struct sadb_x_debug)); -+#endif -+ -+ pfkey_x_debug->sadb_x_debug_len = sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN; -+ pfkey_x_debug->sadb_x_debug_exttype = SADB_X_EXT_DEBUG; -+ -+ pfkey_x_debug->sadb_x_debug_tunnel = tunnel; -+ pfkey_x_debug->sadb_x_debug_netlink = netlink; -+ pfkey_x_debug->sadb_x_debug_xform = xform; -+ pfkey_x_debug->sadb_x_debug_eroute = eroute; -+ pfkey_x_debug->sadb_x_debug_spi = spi; -+ pfkey_x_debug->sadb_x_debug_radij = radij; -+ pfkey_x_debug->sadb_x_debug_esp = esp; -+ pfkey_x_debug->sadb_x_debug_ah = ah; -+ pfkey_x_debug->sadb_x_debug_rcv = rcv; -+ pfkey_x_debug->sadb_x_debug_pfkey = pfkey; -+ pfkey_x_debug->sadb_x_debug_ipcomp = ipcomp; -+ pfkey_x_debug->sadb_x_debug_verbose = verbose; -+ -+ for(i=0; i<4; i++) { -+ pfkey_x_debug->sadb_x_debug_reserved[i] = 0; -+ } -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_x_nat_t_type_build(struct sadb_ext** pfkey_ext, -+ uint8_t type) -+{ -+ int error = 0; -+ int i; -+ struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_type_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_x_nat_t_type) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_type_build: " -+ "why is pfkey_x_nat_t_type already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_type_build: " -+ "type=%d\n", type); -+ -+ if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_type = (struct sadb_x_nat_t_type*) -+ MALLOC(sizeof(struct sadb_x_nat_t_type)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_type_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ -+ pfkey_x_nat_t_type->sadb_x_nat_t_type_len = sizeof(struct sadb_x_nat_t_type) / IPSEC_PFKEYv2_ALIGN; -+ pfkey_x_nat_t_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE; -+ pfkey_x_nat_t_type->sadb_x_nat_t_type_type = type; -+ for(i=0; i<3; i++) { -+ pfkey_x_nat_t_type->sadb_x_nat_t_type_reserved[i] = 0; -+ } -+ -+errlab: -+ return error; -+} -+int -+pfkey_x_nat_t_port_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint16_t port) -+{ -+ int error = 0; -+ struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_port_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_x_nat_t_port) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_port_build: " -+ "why is pfkey_x_nat_t_port already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(exttype) { -+ case SADB_X_EXT_NAT_T_SPORT: -+ case SADB_X_EXT_NAT_T_DPORT: -+ break; -+ default: -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_nat_t_port_build: " -+ "unrecognised ext_type=%d.\n", -+ exttype); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_port_build: " -+ "ext=%d, port=%d\n", exttype, port); -+ -+ if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_port = (struct sadb_x_nat_t_port*) -+ MALLOC(sizeof(struct sadb_x_nat_t_port)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_port_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ -+ pfkey_x_nat_t_port->sadb_x_nat_t_port_len = sizeof(struct sadb_x_nat_t_port) / IPSEC_PFKEYv2_ALIGN; -+ pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype = exttype; -+ pfkey_x_nat_t_port->sadb_x_nat_t_port_port = port; -+ pfkey_x_nat_t_port->sadb_x_nat_t_port_reserved = 0; -+ -+errlab: -+ return error; -+} -+ -+int pfkey_x_protocol_build(struct sadb_ext **pfkey_ext, -+ uint8_t protocol) -+{ -+ int error = 0; -+ struct sadb_protocol * p = (struct sadb_protocol *)*pfkey_ext; -+ DEBUGGING(PF_KEY_DEBUG_BUILD,"pfkey_x_protocol_build: protocol=%u\n", protocol); -+ /* sanity checks... */ -+ if (p != 0) { -+ ERROR("pfkey_x_protocol_build: bogus protocol pointer\n"); -+ SENDERR(EINVAL); -+ } -+ if ((p = (struct sadb_protocol*)MALLOC(sizeof(*p))) == 0) { -+ ERROR("pfkey_build: memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ *pfkey_ext = (struct sadb_ext *)p; -+ p->sadb_protocol_len = sizeof(*p) / sizeof(uint64_t); -+ p->sadb_protocol_exttype = SADB_X_EXT_PROTOCOL; -+ p->sadb_protocol_proto = protocol; -+ p->sadb_protocol_flags = 0; -+ p->sadb_protocol_reserved2 = 0; -+ errlab: -+ return error; -+} -+ -+ -+#if I_DONT_THINK_THIS_WILL_BE_USEFUL -+int (*ext_default_builders[SADB_EXT_MAX +1])(struct sadb_msg*, struct sadb_ext*) -+ = -+{ -+ NULL, /* pfkey_msg_build, */ -+ pfkey_sa_build, -+ pfkey_lifetime_build, -+ pfkey_lifetime_build, -+ pfkey_lifetime_build, -+ pfkey_address_build, -+ pfkey_address_build, -+ pfkey_address_build, -+ pfkey_key_build, -+ pfkey_key_build, -+ pfkey_ident_build, -+ pfkey_ident_build, -+ pfkey_sens_build, -+ pfkey_prop_build, -+ pfkey_supported_build, -+ pfkey_supported_build, -+ pfkey_spirange_build, -+ pfkey_x_kmprivate_build, -+ pfkey_x_satype_build, -+ pfkey_sa_build, -+ pfkey_address_build, -+ pfkey_address_build, -+ pfkey_address_build, -+ pfkey_address_build, -+ pfkey_address_build, -+ pfkey_x_ext_debug_build -+}; -+#endif -+ -+int -+pfkey_msg_build(struct sadb_msg **pfkey_msg, struct sadb_ext *extensions[], int dir) -+{ -+ int error = 0; -+ unsigned ext; -+ unsigned total_size; -+ struct sadb_ext *pfkey_ext; -+ int extensions_seen = 0; -+#ifndef __KERNEL__ -+ struct sadb_ext *extensions_check[SADB_EXT_MAX + 1]; -+#endif -+ -+ if(!extensions[0]) { -+ ERROR("pfkey_msg_build: " -+ "extensions[0] must be specified (struct sadb_msg).\n"); -+ SENDERR(EINVAL); -+ } -+ -+ /* figure out the total size for all the requested extensions */ -+ total_size = IPSEC_PFKEYv2_WORDS(sizeof(struct sadb_msg)); -+ for(ext = 1; ext <= SADB_EXT_MAX; ext++) { -+ if(extensions[ext]) { -+ total_size += (extensions[ext])->sadb_ext_len; -+ } -+ } -+ -+ /* allocate that much space */ -+ *pfkey_msg = (struct sadb_msg*)MALLOC(total_size * IPSEC_PFKEYv2_ALIGN); -+ if(*pfkey_msg == NULL) { -+ ERROR("pfkey_msg_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_build: " -+ "pfkey_msg=0p%p allocated %lu bytes, &(extensions[0])=0p%p\n", -+ *pfkey_msg, -+ (unsigned long)(total_size * IPSEC_PFKEYv2_ALIGN), -+ &(extensions[0])); -+ -+ memcpy(*pfkey_msg, -+ extensions[0], -+ sizeof(struct sadb_msg)); -+ (*pfkey_msg)->sadb_msg_len = total_size; -+ (*pfkey_msg)->sadb_msg_reserved = 0; -+ extensions_seen = 1 ; -+ -+ /* -+ * point pfkey_ext to immediately after the space for the header, -+ * i.e. at the first extension location. -+ */ -+ pfkey_ext = (struct sadb_ext*)(((char*)(*pfkey_msg)) + sizeof(struct sadb_msg)); -+ -+ for(ext = 1; ext <= SADB_EXT_MAX; ext++) { -+ /* copy from extension[ext] to buffer */ -+ if(extensions[ext]) { -+ /* Is this type of extension permitted for this type of message? */ -+ if(!(extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type] & -+ 1<sadb_msg_type], -+ 1<sadb_ext_len * IPSEC_PFKEYv2_ALIGN), -+ ext, -+ extensions[ext]->sadb_ext_type); -+ -+ memcpy(pfkey_ext, -+ extensions[ext], -+ (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); -+ ((char*)pfkey_ext) += (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN; -+ /* Mark that we have seen this extension and remember the header location */ -+ extensions_seen |= ( 1 << ext ); -+ } -+ } -+ -+ /* check required extensions */ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_build: " -+ "extensions permitted=%08x, seen=%08x, required=%08x.\n", -+ extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type], -+ extensions_seen, -+ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]); -+ -+ if((extensions_seen & -+ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) != -+ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_build: " -+ "required extensions missing:%08x.\n", -+ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type] - -+ (extensions_seen & -+ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) ); -+ SENDERR(EINVAL); -+ } -+ -+#ifndef __KERNEL__ -+/* -+ * this is silly, there is no need to reparse the message that we just built. -+ * -+ */ -+ if((error = pfkey_msg_parse(*pfkey_msg, NULL, extensions_check, dir))) { -+ ERROR( -+ "pfkey_msg_build: " -+ "Trouble parsing newly built pfkey message, error=%d.\n", -+ error); -+ SENDERR(-error); -+ } -+#endif -+ -+errlab: -+ -+ return error; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.49 2004/04/12 02:59:06 mcr -+ * erroneously moved pfkey_v2_build.c -+ * -+ * Revision 1.48 2004/04/09 18:00:40 mcr -+ * Moved from linux/lib/libfreeswan/pfkey_v2_build.c,v -+ * -+ * Revision 1.47 2004/03/08 01:59:08 ken -+ * freeswan.h -> openswan.h -+ * -+ * Revision 1.46 2003/12/10 01:20:19 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.45 2003/12/04 23:01:12 mcr -+ * removed ipsec_netlink.h -+ * -+ * Revision 1.44 2003/10/31 02:27:12 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.43.4.2 2003/10/29 01:11:32 mcr -+ * added debugging for pfkey library. -+ * -+ * Revision 1.43.4.1 2003/09/21 13:59:44 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.43 2003/05/07 17:29:17 mcr -+ * new function pfkey_debug_func added for us in debugging from -+ * pfkey library. -+ * -+ * Revision 1.42 2003/01/30 02:32:09 rgb -+ * -+ * Rename SAref table macro names for clarity. -+ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. -+ * -+ * Revision 1.41 2002/12/13 18:16:02 mcr -+ * restored sa_ref code -+ * -+ * Revision 1.40 2002/12/13 18:06:52 mcr -+ * temporarily removed sadb_x_sa_ref reference for 2.xx -+ * -+ * Revision 1.39 2002/12/13 17:43:28 mcr -+ * commented out access to sadb_x_sa_ref for 2.xx branch -+ * -+ * Revision 1.38 2002/10/09 03:12:05 dhr -+ * -+ * [kenb+dhr] 64-bit fixes -+ * -+ * Revision 1.37 2002/09/20 15:40:39 rgb -+ * Added new function pfkey_sa_ref_build() to accomodate saref parameter. -+ * -+ * Revision 1.36 2002/09/20 05:01:22 rgb -+ * Generalise for platform independance: fix (ia64) using unsigned for sizes. -+ * -+ * Revision 1.35 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.34 2002/05/23 07:14:11 rgb -+ * Cleaned up %p variants to 0p%p for test suite cleanup. -+ * -+ * Revision 1.33 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.32 2002/04/24 07:36:40 mcr -+ * Moved from ./lib/pfkey_v2_build.c,v -+ * -+ * Revision 1.31 2002/01/29 22:25:35 rgb -+ * Re-add ipsec_kversion.h to keep MALLOC happy. -+ * -+ * Revision 1.30 2002/01/29 01:59:09 mcr -+ * removal of kversions.h - sources that needed it now use ipsec_param.h. -+ * updating of IPv6 structures to match latest in6.h version. -+ * removed dead code from openswan.h that also duplicated kversions.h -+ * code. -+ * -+ * Revision 1.29 2001/12/19 21:06:09 rgb -+ * Added port numbers to pfkey_address_build() debugging. -+ * -+ * Revision 1.28 2001/11/06 19:47:47 rgb -+ * Added packet parameter to lifetime and comb structures. -+ * -+ * Revision 1.27 2001/10/18 04:45:24 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/openswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.26 2001/09/08 21:13:34 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.25 2001/06/14 19:35:16 rgb -+ * Update copyright date. -+ * -+ * Revision 1.24 2001/03/20 03:49:45 rgb -+ * Ditch superfluous debug_pfkey declaration. -+ * Move misplaced openswan.h inclusion for kernel case. -+ * -+ * Revision 1.23 2001/03/16 07:41:50 rgb -+ * Put openswan.h include before pluto includes. -+ * -+ * Revision 1.22 2001/02/27 22:24:56 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.21 2000/11/17 18:10:30 rgb -+ * Fixed bugs mostly relating to spirange, to treat all spi variables as -+ * network byte order since this is the way PF_KEYv2 stored spis. -+ * -+ * Revision 1.20 2000/10/12 00:02:39 rgb -+ * Removed 'format, ##' nonsense from debug macros for RH7.0. -+ * -+ * Revision 1.19 2000/10/10 20:10:20 rgb -+ * Added support for debug_ipcomp and debug_verbose to klipsdebug. -+ * -+ * Revision 1.18 2000/09/12 18:59:54 rgb -+ * Added Gerhard's IPv6 support to pfkey parts of libopenswan. -+ * -+ * Revision 1.17 2000/09/12 03:27:00 rgb -+ * Moved DEBUGGING definition to compile kernel with debug off. -+ * -+ * Revision 1.16 2000/09/08 19:22:12 rgb -+ * Fixed pfkey_prop_build() parameter to be only single indirection. -+ * Fixed struct alg copy. -+ * -+ * Revision 1.15 2000/08/20 21:40:01 rgb -+ * Added an address parameter sanity check to pfkey_address_build(). -+ * -+ * Revision 1.14 2000/08/15 17:29:23 rgb -+ * Fixes from SZI to untested pfkey_prop_build(). -+ * -+ * Revision 1.13 2000/06/02 22:54:14 rgb -+ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support. -+ * -+ * Revision 1.12 2000/05/10 19:24:01 rgb -+ * Fleshed out sensitivity, proposal and supported extensions. -+ * -+ * Revision 1.11 2000/03/16 14:07:23 rgb -+ * Renamed ALIGN macro to avoid fighting with others in kernel. -+ * -+ * Revision 1.10 2000/01/24 21:14:35 rgb -+ * Added disabled pluto pfkey lib debug flag. -+ * -+ * Revision 1.9 2000/01/21 06:27:32 rgb -+ * Added address cases for eroute flows. -+ * Removed unused code. -+ * Dropped unused argument to pfkey_x_satype_build(). -+ * Indented compiler directives for readability. -+ * Added klipsdebug switching capability. -+ * Fixed SADB_EXT_MAX bug not permitting last extension access. -+ * -+ * Revision 1.8 1999/12/29 21:17:41 rgb -+ * Changed pfkey_msg_build() I/F to include a struct sadb_msg** -+ * parameter for cleaner manipulation of extensions[] and to guard -+ * against potential memory leaks. -+ * Changed the I/F to pfkey_msg_free() for the same reason. -+ * -+ * Revision 1.7 1999/12/09 23:12:20 rgb -+ * Removed unused cruft. -+ * Added argument to pfkey_sa_build() to do eroutes. -+ * Fixed exttype check in as yet unused pfkey_lifetime_build(). -+ * -+ * Revision 1.6 1999/12/07 19:54:29 rgb -+ * Removed static pluto debug flag. -+ * Added functions for pfkey message and extensions initialisation -+ * and cleanup. -+ * -+ * Revision 1.5 1999/12/01 22:20:06 rgb -+ * Changed pfkey_sa_build to accept an SPI in network byte order. -+ * Added to quiet userspace compiler. -+ * Moved pfkey_lib_debug variable into the library. -+ * Removed SATYPE check from pfkey_msg_hdr_build so FLUSH will work. -+ * Added extension assembly debugging. -+ * Isolated assignment with brackets to be sure of scope. -+ * -+ * Revision 1.4 1999/11/27 11:57:35 rgb -+ * Added ipv6 headers. -+ * Remove over-zealous algorithm sanity checkers from pfkey_sa_build. -+ * Debugging error messages added. -+ * Fixed missing auth and encrypt assignment bug. -+ * Add argument to pfkey_msg_parse() for direction. -+ * Move parse-after-build check inside pfkey_msg_build(). -+ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array. -+ * Add CVS log entry to bottom of file. -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/pfkey_v2_debug.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,176 @@ -+/* -+ * @(#) pfkey version 2 debugging messages -+ * -+ * Copyright (C) 2001 Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ */ -+ -+#ifdef __KERNEL__ -+ -+# include /* for printk */ -+ -+# include "openswan/ipsec_kversion.h" /* for malloc switch */ -+# ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+# else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+# endif /* MALLOC_SLAB */ -+# include /* error codes */ -+# include /* size_t */ -+# include /* mark_bh */ -+ -+# include /* struct device, and other headers */ -+# include /* eth_type_trans */ -+extern int debug_pfkey; -+ -+#else /* __KERNEL__ */ -+ -+# include -+# include -+# include -+ -+#endif /* __KERNEL__ */ -+ -+#include "openswan.h" -+#include "pfkeyv2.h" -+#include "pfkey.h" -+ -+/* -+ * This file provides ASCII translations of PF_KEY magic numbers. -+ * -+ */ -+ -+static char *pfkey_sadb_ext_strings[]={ -+ "reserved", /* SADB_EXT_RESERVED 0 */ -+ "security-association", /* SADB_EXT_SA 1 */ -+ "lifetime-current", /* SADB_EXT_LIFETIME_CURRENT 2 */ -+ "lifetime-hard", /* SADB_EXT_LIFETIME_HARD 3 */ -+ "lifetime-soft", /* SADB_EXT_LIFETIME_SOFT 4 */ -+ "source-address", /* SADB_EXT_ADDRESS_SRC 5 */ -+ "destination-address", /* SADB_EXT_ADDRESS_DST 6 */ -+ "proxy-address", /* SADB_EXT_ADDRESS_PROXY 7 */ -+ "authentication-key", /* SADB_EXT_KEY_AUTH 8 */ -+ "cipher-key", /* SADB_EXT_KEY_ENCRYPT 9 */ -+ "source-identity", /* SADB_EXT_IDENTITY_SRC 10 */ -+ "destination-identity", /* SADB_EXT_IDENTITY_DST 11 */ -+ "sensitivity-label", /* SADB_EXT_SENSITIVITY 12 */ -+ "proposal", /* SADB_EXT_PROPOSAL 13 */ -+ "supported-auth", /* SADB_EXT_SUPPORTED_AUTH 14 */ -+ "supported-cipher", /* SADB_EXT_SUPPORTED_ENCRYPT 15 */ -+ "spi-range", /* SADB_EXT_SPIRANGE 16 */ -+ "X-kmpprivate", /* SADB_X_EXT_KMPRIVATE 17 */ -+ "X-satype2", /* SADB_X_EXT_SATYPE2 18 */ -+ "X-security-association", /* SADB_X_EXT_SA2 19 */ -+ "X-destination-address2", /* SADB_X_EXT_ADDRESS_DST2 20 */ -+ "X-source-flow-address", /* SADB_X_EXT_ADDRESS_SRC_FLOW 21 */ -+ "X-dest-flow-address", /* SADB_X_EXT_ADDRESS_DST_FLOW 22 */ -+ "X-source-mask", /* SADB_X_EXT_ADDRESS_SRC_MASK 23 */ -+ "X-dest-mask", /* SADB_X_EXT_ADDRESS_DST_MASK 24 */ -+ "X-set-debug", /* SADB_X_EXT_DEBUG 25 */ -+#ifdef NAT_TRAVERSAL -+ "X-NAT-T-type", /* SADB_X_EXT_NAT_T_TYPE 26 */ -+ "X-NAT-T-sport", /* SADB_X_EXT_NAT_T_SPORT 27 */ -+ "X-NAT-T-dport", /* SADB_X_EXT_NAT_T_DPORT 28 */ -+ "X-NAT-T-OA", /* SADB_X_EXT_NAT_T_OA 29 */ -+#endif -+}; -+ -+const char * -+pfkey_v2_sadb_ext_string(int ext) -+{ -+ if(ext <= SADB_EXT_MAX) { -+ return pfkey_sadb_ext_strings[ext]; -+ } else { -+ return "unknown-ext"; -+ } -+} -+ -+ -+static char *pfkey_sadb_type_strings[]={ -+ "reserved", /* SADB_RESERVED */ -+ "getspi", /* SADB_GETSPI */ -+ "update", /* SADB_UPDATE */ -+ "add", /* SADB_ADD */ -+ "delete", /* SADB_DELETE */ -+ "get", /* SADB_GET */ -+ "acquire", /* SADB_ACQUIRE */ -+ "register", /* SADB_REGISTER */ -+ "expire", /* SADB_EXPIRE */ -+ "flush", /* SADB_FLUSH */ -+ "dump", /* SADB_DUMP */ -+ "x-promisc", /* SADB_X_PROMISC */ -+ "x-pchange", /* SADB_X_PCHANGE */ -+ "x-groupsa", /* SADB_X_GRPSA */ -+ "x-addflow(eroute)", /* SADB_X_ADDFLOW */ -+ "x-delflow(eroute)", /* SADB_X_DELFLOW */ -+ "x-debug", /* SADB_X_DEBUG */ -+}; -+ -+const char * -+pfkey_v2_sadb_type_string(int sadb_type) -+{ -+ if(sadb_type <= SADB_MAX) { -+ return pfkey_sadb_type_strings[sadb_type]; -+ } else { -+ return "unknown-sadb-type"; -+ } -+} -+ -+ -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.9 2004/03/08 01:59:08 ken -+ * freeswan.h -> openswan.h -+ * -+ * Revision 1.8 2003/12/10 01:20:19 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.7 2002/09/20 05:01:26 rgb -+ * Fixed limit inclusion error in both type and ext string conversion. -+ * -+ * Revision 1.6 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.5 2002/04/24 07:36:40 mcr -+ * Moved from ./lib/pfkey_v2_debug.c,v -+ * -+ * Revision 1.4 2002/01/29 22:25:36 rgb -+ * Re-add ipsec_kversion.h to keep MALLOC happy. -+ * -+ * Revision 1.3 2002/01/29 01:59:09 mcr -+ * removal of kversions.h - sources that needed it now use ipsec_param.h. -+ * updating of IPv6 structures to match latest in6.h version. -+ * removed dead code from openswan.h that also duplicated kversions.h -+ * code. -+ * -+ * Revision 1.2 2002/01/20 20:34:50 mcr -+ * added pfkey_v2_sadb_type_string to decode sadb_type to string. -+ * -+ * Revision 1.1 2001/11/27 05:30:06 mcr -+ * initial set of debug strings for pfkey debugging. -+ * this will eventually only be included for debug builds. -+ * -+ * Revision 1.1 2001/09/21 04:12:03 mcr -+ * first compilable version. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/pfkey_v2_ext_bits.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,808 @@ -+/* -+ * RFC2367 PF_KEYv2 Key management API message parser -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* -+ * Template from klips/net/ipsec/ipsec/ipsec_parse.c. -+ */ -+ -+char pfkey_v2_ext_bits_c_version[] = "$Id$"; -+ -+/* -+ * Some ugly stuff to allow consistent debugging code for use in the -+ * kernel and in user space -+*/ -+ -+#ifdef __KERNEL__ -+ -+# include /* for printk */ -+ -+# include "openswan/ipsec_kversion.h" /* for malloc switch */ -+# ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+# else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+# endif /* MALLOC_SLAB */ -+# include /* error codes */ -+# include /* size_t */ -+# include /* mark_bh */ -+ -+# include /* struct device, and other headers */ -+# include /* eth_type_trans */ -+# include /* struct iphdr */ -+# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+# include -+# endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ -+ -+#else /* __KERNEL__ */ -+ -+# include -+# include -+# include -+#endif -+ -+#include -+#include -+#include -+ -+unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_MAX + 1/*ext*/] = { -+ -+/* INBOUND EXTENSIONS */ -+{ -+ -+/* PERMITTED IN */ -+{ -+/* SADB_RESERVED */ -+0 -+, -+/* SADB_GETSPI */ -+1< openswan.h -+ * -+ * Revision 1.19 2003/12/22 21:38:13 mcr -+ * removed extraenous #endif. -+ * -+ * Revision 1.18 2003/12/22 19:34:41 mcr -+ * added 0.6c NAT-T patch. -+ * -+ * Revision 1.17 2003/12/10 01:20:19 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.16 2003/10/31 02:27:12 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.15.30.1 2003/09/21 13:59:44 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.15 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.14 2002/04/24 07:36:40 mcr -+ * Moved from ./lib/pfkey_v2_ext_bits.c,v -+ * -+ * Revision 1.13 2002/01/29 22:25:36 rgb -+ * Re-add ipsec_kversion.h to keep MALLOC happy. -+ * -+ * Revision 1.12 2002/01/29 01:59:10 mcr -+ * removal of kversions.h - sources that needed it now use ipsec_param.h. -+ * updating of IPv6 structures to match latest in6.h version. -+ * removed dead code from openswan.h that also duplicated kversions.h -+ * code. -+ * -+ * Revision 1.11 2001/10/18 04:45:24 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/openswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.10 2001/09/08 21:13:35 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.9 2001/06/14 19:35:16 rgb -+ * Update copyright date. -+ * -+ * Revision 1.8 2001/03/26 23:07:36 rgb -+ * Remove requirement for auth and enc key from UPDATE. -+ * -+ * Revision 1.7 2000/09/12 22:35:37 rgb -+ * Restructured to remove unused extensions from CLEARFLOW messages. -+ * -+ * Revision 1.6 2000/09/09 06:39:01 rgb -+ * Added comments for clarity. -+ * -+ * Revision 1.5 2000/06/02 22:54:14 rgb -+ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support. -+ * -+ * Revision 1.4 2000/01/21 06:27:56 rgb -+ * Added address cases for eroute flows. -+ * Added comments for each message type. -+ * Added klipsdebug switching capability. -+ * Fixed GRPSA bitfields. -+ * -+ * Revision 1.3 1999/12/01 22:20:27 rgb -+ * Remove requirement for a proxy address in an incoming getspi message. -+ * -+ * Revision 1.2 1999/11/27 11:57:06 rgb -+ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array. -+ * Add CVS log entry to bottom of file. -+ * Cleaned out unused bits. -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/pfkey_v2_parse.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1820 @@ -+/* -+ * RFC2367 PF_KEYv2 Key management API message parser -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* -+ * Template from klips/net/ipsec/ipsec/ipsec_parser.c. -+ */ -+ -+char pfkey_v2_parse_c_version[] = "$Id$"; -+ -+/* -+ * Some ugly stuff to allow consistent debugging code for use in the -+ * kernel and in user space -+*/ -+ -+#ifdef __KERNEL__ -+ -+# include /* for printk */ -+ -+#include "openswan/ipsec_kversion.h" /* for malloc switch */ -+ -+# ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+# else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+# endif /* MALLOC_SLAB */ -+# include /* error codes */ -+# include /* size_t */ -+# include /* mark_bh */ -+ -+# include /* struct device, and other headers */ -+# include /* eth_type_trans */ -+# include /* struct iphdr */ -+# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+# include /* struct ipv6hdr */ -+# endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ -+extern int debug_pfkey; -+ -+# include -+ -+#include "openswan/ipsec_encap.h" -+ -+#else /* __KERNEL__ */ -+ -+# include -+# include -+# include -+ -+# include -+# include "constants.h" -+# include "programs/pluto/defs.h" /* for PRINTF_LIKE */ -+ -+#endif /* __KERNEL__ */ -+ -+ -+#include -+#include -+ -+#include "openswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */ -+ -+/* -+ * how to handle debugging for pfkey. -+ */ -+#include -+ -+unsigned int pfkey_lib_debug = PF_KEY_DEBUG_PARSE_NONE; -+void (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1); -+void (*pfkey_error_func)(const char *message, ...) PRINTF_LIKE(1); -+ -+ -+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) -+ -+struct satype_tbl { -+ uint8_t proto; -+ uint8_t satype; -+ char* name; -+} static satype_tbl[] = { -+#ifdef __KERNEL__ -+ { IPPROTO_ESP, SADB_SATYPE_ESP, "ESP" }, -+ { IPPROTO_AH, SADB_SATYPE_AH, "AH" }, -+ { IPPROTO_IPIP, SADB_X_SATYPE_IPIP, "IPIP" }, -+#ifdef CONFIG_IPSEC_IPCOMP -+ { IPPROTO_COMP, SADB_X_SATYPE_COMP, "COMP" }, -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ { IPPROTO_INT, SADB_X_SATYPE_INT, "INT" }, -+#else /* __KERNEL__ */ -+ { SA_ESP, SADB_SATYPE_ESP, "ESP" }, -+ { SA_AH, SADB_SATYPE_AH, "AH" }, -+ { SA_IPIP, SADB_X_SATYPE_IPIP, "IPIP" }, -+ { SA_COMP, SADB_X_SATYPE_COMP, "COMP" }, -+ { SA_INT, SADB_X_SATYPE_INT, "INT" }, -+#endif /* __KERNEL__ */ -+ { 0, 0, "UNKNOWN" } -+}; -+ -+uint8_t -+satype2proto(uint8_t satype) -+{ -+ int i =0; -+ -+ while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) { -+ i++; -+ } -+ return satype_tbl[i].proto; -+} -+ -+uint8_t -+proto2satype(uint8_t proto) -+{ -+ int i = 0; -+ -+ while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) { -+ i++; -+ } -+ return satype_tbl[i].satype; -+} -+ -+char* -+satype2name(uint8_t satype) -+{ -+ int i = 0; -+ -+ while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) { -+ i++; -+ } -+ return satype_tbl[i].name; -+} -+ -+char* -+proto2name(uint8_t proto) -+{ -+ int i = 0; -+ -+ while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) { -+ i++; -+ } -+ return satype_tbl[i].name; -+} -+ -+/* Default extension parsers taken from the KLIPS code */ -+ -+DEBUG_NO_STATIC int -+pfkey_sa_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext; -+#if 0 -+ struct sadb_sa sav2; -+#endif -+ -+ /* sanity checks... */ -+ if(!pfkey_sa) { -+ ERROR("pfkey_sa_parse: " -+ "NULL pointer passed in.\n"); -+ SENDERR(EINVAL); -+ } -+ -+#if 0 -+ /* check if this structure is short, and if so, fix it up. -+ * XXX this is NOT the way to do things. -+ */ -+ if(pfkey_sa->sadb_sa_len == sizeof(struct sadb_sa_v1)/IPSEC_PFKEYv2_ALIGN) { -+ -+ /* yes, so clear out a temporary structure, and copy first */ -+ memset(&sav2, 0, sizeof(sav2)); -+ memcpy(&sav2, pfkey_sa, sizeof(struct sadb_sa_v1)); -+ sav2.sadb_x_sa_ref=-1; -+ sav2.sadb_sa_len = sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN; -+ -+ pfkey_sa = &sav2; -+ } -+#endif -+ -+ -+ if(pfkey_sa->sadb_sa_len != sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN) { -+ ERROR( -+ "pfkey_sa_parse: " -+ "length wrong pfkey_sa->sadb_sa_len=%d sizeof(struct sadb_sa)=%d.\n", -+ pfkey_sa->sadb_sa_len, -+ (int)sizeof(struct sadb_sa)); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_sa->sadb_sa_encrypt > SADB_EALG_MAX) { -+ ERROR( -+ "pfkey_sa_parse: " -+ "pfkey_sa->sadb_sa_encrypt=%d > SADB_EALG_MAX=%d.\n", -+ pfkey_sa->sadb_sa_encrypt, -+ SADB_EALG_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_sa->sadb_sa_auth > SADB_AALG_MAX) { -+ ERROR( -+ "pfkey_sa_parse: " -+ "pfkey_sa->sadb_sa_auth=%d > SADB_AALG_MAX=%d.\n", -+ pfkey_sa->sadb_sa_auth, -+ SADB_AALG_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_sa->sadb_sa_state > SADB_SASTATE_MAX) { -+ ERROR( -+ "pfkey_sa_parse: " -+ "state=%d exceeds MAX=%d.\n", -+ pfkey_sa->sadb_sa_state, -+ SADB_SASTATE_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_sa->sadb_sa_state == SADB_SASTATE_DEAD) { -+ ERROR( -+ "pfkey_sa_parse: " -+ "state=%d is DEAD=%d.\n", -+ pfkey_sa->sadb_sa_state, -+ SADB_SASTATE_DEAD); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_sa->sadb_sa_replay > 64) { -+ ERROR( -+ "pfkey_sa_parse: " -+ "replay window size: %d -- must be 0 <= size <= 64\n", -+ pfkey_sa->sadb_sa_replay); -+ SENDERR(EINVAL); -+ } -+ -+ if(! ((pfkey_sa->sadb_sa_exttype == SADB_EXT_SA) || -+ (pfkey_sa->sadb_sa_exttype == SADB_X_EXT_SA2))) -+ { -+ ERROR( -+ "pfkey_sa_parse: " -+ "unknown exttype=%d, expecting SADB_EXT_SA=%d or SADB_X_EXT_SA2=%d.\n", -+ pfkey_sa->sadb_sa_exttype, -+ SADB_EXT_SA, -+ SADB_X_EXT_SA2); -+ SENDERR(EINVAL); -+ } -+ -+ if((IPSEC_SAREF_NULL != pfkey_sa->sadb_x_sa_ref) && (pfkey_sa->sadb_x_sa_ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH))) { -+ ERROR( -+ "pfkey_sa_parse: " -+ "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n", -+ pfkey_sa->sadb_x_sa_ref, -+ IPSEC_SAREF_NULL, -+ IPSEC_SA_REF_TABLE_NUM_ENTRIES); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_sa_parse: " -+ "successfully found len=%d exttype=%d(%s) spi=%08lx replay=%d state=%d auth=%d encrypt=%d flags=%d ref=%d.\n", -+ pfkey_sa->sadb_sa_len, -+ pfkey_sa->sadb_sa_exttype, -+ pfkey_v2_sadb_ext_string(pfkey_sa->sadb_sa_exttype), -+ (long unsigned int)ntohl(pfkey_sa->sadb_sa_spi), -+ pfkey_sa->sadb_sa_replay, -+ pfkey_sa->sadb_sa_state, -+ pfkey_sa->sadb_sa_auth, -+ pfkey_sa->sadb_sa_encrypt, -+ pfkey_sa->sadb_sa_flags, -+ pfkey_sa->sadb_x_sa_ref); -+ -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_lifetime_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_lifetime_parse:enter\n"); -+ /* sanity checks... */ -+ if(!pfkey_lifetime) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_lifetime_parse: " -+ "NULL pointer passed in.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_lifetime->sadb_lifetime_len != -+ sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_lifetime_parse: " -+ "length wrong pfkey_lifetime->sadb_lifetime_len=%d sizeof(struct sadb_lifetime)=%d.\n", -+ pfkey_lifetime->sadb_lifetime_len, -+ (int)sizeof(struct sadb_lifetime)); -+ SENDERR(EINVAL); -+ } -+ -+ if((pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_HARD) && -+ (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_SOFT) && -+ (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_CURRENT)) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_lifetime_parse: " -+ "unexpected ext_type=%d.\n", -+ pfkey_lifetime->sadb_lifetime_exttype); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_lifetime_parse: " -+ "life_type=%d(%s) alloc=%u bytes=%u add=%u use=%u pkts=%u.\n", -+ pfkey_lifetime->sadb_lifetime_exttype, -+ pfkey_v2_sadb_ext_string(pfkey_lifetime->sadb_lifetime_exttype), -+ pfkey_lifetime->sadb_lifetime_allocations, -+ (unsigned)pfkey_lifetime->sadb_lifetime_bytes, -+ (unsigned)pfkey_lifetime->sadb_lifetime_addtime, -+ (unsigned)pfkey_lifetime->sadb_lifetime_usetime, -+ pfkey_lifetime->sadb_x_lifetime_packets); -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_address_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ int saddr_len = 0; -+ struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext; -+ struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address)); -+ char ipaddr_txt[ADDRTOT_BUF]; -+ -+ /* sanity checks... */ -+ if(!pfkey_address) { -+ ERROR( -+ "pfkey_address_parse: " -+ "NULL pointer passed in.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_address->sadb_address_len < -+ (sizeof(struct sadb_address) + sizeof(struct sockaddr))/ -+ IPSEC_PFKEYv2_ALIGN) { -+ ERROR("pfkey_address_parse: " -+ "size wrong 1 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n", -+ pfkey_address->sadb_address_len, -+ (int)sizeof(struct sadb_address), -+ (int)sizeof(struct sockaddr)); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_address->sadb_address_reserved) { -+ ERROR("pfkey_address_parse: " -+ "res=%d, must be zero.\n", -+ pfkey_address->sadb_address_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_address->sadb_address_exttype) { -+ case SADB_EXT_ADDRESS_SRC: -+ case SADB_EXT_ADDRESS_DST: -+ case SADB_EXT_ADDRESS_PROXY: -+ case SADB_X_EXT_ADDRESS_DST2: -+ case SADB_X_EXT_ADDRESS_SRC_FLOW: -+ case SADB_X_EXT_ADDRESS_DST_FLOW: -+ case SADB_X_EXT_ADDRESS_SRC_MASK: -+ case SADB_X_EXT_ADDRESS_DST_MASK: -+#ifdef NAT_TRAVERSAL -+ case SADB_X_EXT_NAT_T_OA: -+#endif -+ break; -+ default: -+ ERROR( -+ "pfkey_address_parse: " -+ "unexpected ext_type=%d.\n", -+ pfkey_address->sadb_address_exttype); -+ SENDERR(EINVAL); -+ } -+ -+ switch(s->sa_family) { -+ case AF_INET: -+ saddr_len = sizeof(struct sockaddr_in); -+ sprintf(ipaddr_txt, "%d.%d.%d.%d" -+ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 0) & 0xFF -+ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 8) & 0xFF -+ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 16) & 0xFF -+ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 24) & 0xFF); -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_address_parse: " -+ "found exttype=%u(%s) family=%d(AF_INET) address=%s proto=%u port=%u.\n", -+ pfkey_address->sadb_address_exttype, -+ pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype), -+ s->sa_family, -+ ipaddr_txt, -+ pfkey_address->sadb_address_proto, -+ ntohs(((struct sockaddr_in*)s)->sin_port)); -+ break; -+ case AF_INET6: -+ saddr_len = sizeof(struct sockaddr_in6); -+ sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x" -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[0]) -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[1]) -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[2]) -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[3]) -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[4]) -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[5]) -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[6]) -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[7])); -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_address_parse: " -+ "found exttype=%u(%s) family=%d(AF_INET6) address=%s proto=%u port=%u.\n", -+ pfkey_address->sadb_address_exttype, -+ pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype), -+ s->sa_family, -+ ipaddr_txt, -+ pfkey_address->sadb_address_proto, -+ ((struct sockaddr_in6*)s)->sin6_port); -+ break; -+ default: -+ ERROR( -+ "pfkey_address_parse: " -+ "s->sa_family=%d not supported.\n", -+ s->sa_family); -+ SENDERR(EPFNOSUPPORT); -+ } -+ -+ if(pfkey_address->sadb_address_len != -+ DIVUP(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)) { -+ ERROR( -+ "pfkey_address_parse: " -+ "size wrong 2 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n", -+ pfkey_address->sadb_address_len, -+ (int)sizeof(struct sadb_address), -+ saddr_len); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_address->sadb_address_prefixlen != 0) { -+ ERROR( -+ "pfkey_address_parse: " -+ "address prefixes not supported yet.\n"); -+ SENDERR(EAFNOSUPPORT); /* not supported yet */ -+ } -+ -+ /* XXX check if port!=0 */ -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_address_parse: successful.\n"); -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_key_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_key *pfkey_key = (struct sadb_key *)pfkey_ext; -+ -+ /* sanity checks... */ -+ -+ if(!pfkey_key) { -+ ERROR( -+ "pfkey_key_parse: " -+ "NULL pointer passed in.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_key->sadb_key_len < sizeof(struct sadb_key) / IPSEC_PFKEYv2_ALIGN) { -+ ERROR( -+ "pfkey_key_parse: " -+ "size wrong ext_len=%d, key_ext_len=%d.\n", -+ pfkey_key->sadb_key_len, -+ (int)sizeof(struct sadb_key)); -+ SENDERR(EINVAL); -+ } -+ -+ if(!pfkey_key->sadb_key_bits) { -+ ERROR( -+ "pfkey_key_parse: " -+ "key length set to zero, must be non-zero.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_key->sadb_key_len != -+ DIVUP(sizeof(struct sadb_key) * OCTETBITS + pfkey_key->sadb_key_bits, -+ PFKEYBITS)) { -+ ERROR( -+ "pfkey_key_parse: " -+ "key length=%d does not agree with extension length=%d.\n", -+ pfkey_key->sadb_key_bits, -+ pfkey_key->sadb_key_len); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_key->sadb_key_reserved) { -+ ERROR( -+ "pfkey_key_parse: " -+ "res=%d, must be zero.\n", -+ pfkey_key->sadb_key_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ if(! ( (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_AUTH) || -+ (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_ENCRYPT))) { -+ ERROR( -+ "pfkey_key_parse: " -+ "expecting extension type AUTH or ENCRYPT, got %d.\n", -+ pfkey_key->sadb_key_exttype); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_key_parse: " -+ "success, found len=%d exttype=%d(%s) bits=%d reserved=%d.\n", -+ pfkey_key->sadb_key_len, -+ pfkey_key->sadb_key_exttype, -+ pfkey_v2_sadb_ext_string(pfkey_key->sadb_key_exttype), -+ pfkey_key->sadb_key_bits, -+ pfkey_key->sadb_key_reserved); -+ -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_ident_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_ident *pfkey_ident = (struct sadb_ident *)pfkey_ext; -+ -+ /* sanity checks... */ -+ if(pfkey_ident->sadb_ident_len < sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) { -+ ERROR( -+ "pfkey_ident_parse: " -+ "size wrong ext_len=%d, key_ext_len=%d.\n", -+ pfkey_ident->sadb_ident_len, -+ (int)sizeof(struct sadb_ident)); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_ident->sadb_ident_type > SADB_IDENTTYPE_MAX) { -+ ERROR( -+ "pfkey_ident_parse: " -+ "ident_type=%d out of range, must be less than %d.\n", -+ pfkey_ident->sadb_ident_type, -+ SADB_IDENTTYPE_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_ident->sadb_ident_reserved) { -+ ERROR( -+ "pfkey_ident_parse: " -+ "res=%d, must be zero.\n", -+ pfkey_ident->sadb_ident_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ /* string terminator/padding must be zero */ -+ if(pfkey_ident->sadb_ident_len > sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) { -+ if(*((char*)pfkey_ident + pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1)) { -+ ERROR( -+ "pfkey_ident_parse: " -+ "string padding must be zero, last is 0x%02x.\n", -+ *((char*)pfkey_ident + -+ pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1)); -+ SENDERR(EINVAL); -+ } -+ } -+ -+ if( ! ((pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC) || -+ (pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_DST))) { -+ ERROR( -+ "pfkey_key_parse: " -+ "expecting extension type IDENTITY_SRC or IDENTITY_DST, got %d.\n", -+ pfkey_ident->sadb_ident_exttype); -+ SENDERR(EINVAL); -+ } -+ -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_sens_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_sens *pfkey_sens = (struct sadb_sens *)pfkey_ext; -+ -+ /* sanity checks... */ -+ if(pfkey_sens->sadb_sens_len < sizeof(struct sadb_sens) / IPSEC_PFKEYv2_ALIGN) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_sens_parse: " -+ "size wrong ext_len=%d, key_ext_len=%d.\n", -+ pfkey_sens->sadb_sens_len, -+ (int)sizeof(struct sadb_sens)); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_sens_parse: " -+ "Sorry, I can't parse exttype=%d yet.\n", -+ pfkey_ext->sadb_ext_type); -+#if 0 -+ SENDERR(EINVAL); /* don't process these yet */ -+#endif -+ -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_prop_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ int i, num_comb; -+ struct sadb_prop *pfkey_prop = (struct sadb_prop *)pfkey_ext; -+ struct sadb_comb *pfkey_comb = (struct sadb_comb *)((char*)pfkey_ext + sizeof(struct sadb_prop)); -+ -+ /* sanity checks... */ -+ if((pfkey_prop->sadb_prop_len < sizeof(struct sadb_prop) / IPSEC_PFKEYv2_ALIGN) || -+ (((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) % sizeof(struct sadb_comb))) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "size wrong ext_len=%d, prop_ext_len=%d comb_ext_len=%d.\n", -+ pfkey_prop->sadb_prop_len, -+ (int)sizeof(struct sadb_prop), -+ (int)sizeof(struct sadb_comb)); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_prop->sadb_prop_replay > 64) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "replay window size: %d -- must be 0 <= size <= 64\n", -+ pfkey_prop->sadb_prop_replay); -+ SENDERR(EINVAL); -+ } -+ -+ for(i=0; i<3; i++) { -+ if(pfkey_prop->sadb_prop_reserved[i]) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "res[%d]=%d, must be zero.\n", -+ i, pfkey_prop->sadb_prop_reserved[i]); -+ SENDERR(EINVAL); -+ } -+ } -+ -+ num_comb = ((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) / sizeof(struct sadb_comb); -+ -+ for(i = 0; i < num_comb; i++) { -+ if(pfkey_comb->sadb_comb_auth > SADB_AALG_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_auth=%d > SADB_AALG_MAX=%d.\n", -+ i, -+ pfkey_comb->sadb_comb_auth, -+ SADB_AALG_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_comb->sadb_comb_auth) { -+ if(!pfkey_comb->sadb_comb_auth_minbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_auth_minbits=0, fatal.\n", -+ i); -+ SENDERR(EINVAL); -+ } -+ if(!pfkey_comb->sadb_comb_auth_maxbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_auth_maxbits=0, fatal.\n", -+ i); -+ SENDERR(EINVAL); -+ } -+ if(pfkey_comb->sadb_comb_auth_minbits > pfkey_comb->sadb_comb_auth_maxbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_auth_minbits=%d > maxbits=%d, fatal.\n", -+ i, -+ pfkey_comb->sadb_comb_auth_minbits, -+ pfkey_comb->sadb_comb_auth_maxbits); -+ SENDERR(EINVAL); -+ } -+ } else { -+ if(pfkey_comb->sadb_comb_auth_minbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_auth_minbits=%d != 0, fatal.\n", -+ i, -+ pfkey_comb->sadb_comb_auth_minbits); -+ SENDERR(EINVAL); -+ } -+ if(pfkey_comb->sadb_comb_auth_maxbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_auth_maxbits=%d != 0, fatal.\n", -+ i, -+ pfkey_comb->sadb_comb_auth_maxbits); -+ SENDERR(EINVAL); -+ } -+ } -+ -+ if(pfkey_comb->sadb_comb_encrypt > SADB_EALG_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_comb_parse: " -+ "pfkey_comb[%d]->sadb_comb_encrypt=%d > SADB_EALG_MAX=%d.\n", -+ i, -+ pfkey_comb->sadb_comb_encrypt, -+ SADB_EALG_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_comb->sadb_comb_encrypt) { -+ if(!pfkey_comb->sadb_comb_encrypt_minbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_encrypt_minbits=0, fatal.\n", -+ i); -+ SENDERR(EINVAL); -+ } -+ if(!pfkey_comb->sadb_comb_encrypt_maxbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=0, fatal.\n", -+ i); -+ SENDERR(EINVAL); -+ } -+ if(pfkey_comb->sadb_comb_encrypt_minbits > pfkey_comb->sadb_comb_encrypt_maxbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d > maxbits=%d, fatal.\n", -+ i, -+ pfkey_comb->sadb_comb_encrypt_minbits, -+ pfkey_comb->sadb_comb_encrypt_maxbits); -+ SENDERR(EINVAL); -+ } -+ } else { -+ if(pfkey_comb->sadb_comb_encrypt_minbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d != 0, fatal.\n", -+ i, -+ pfkey_comb->sadb_comb_encrypt_minbits); -+ SENDERR(EINVAL); -+ } -+ if(pfkey_comb->sadb_comb_encrypt_maxbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=%d != 0, fatal.\n", -+ i, -+ pfkey_comb->sadb_comb_encrypt_maxbits); -+ SENDERR(EINVAL); -+ } -+ } -+ -+ /* XXX do sanity check on flags */ -+ -+ if(pfkey_comb->sadb_comb_hard_allocations && pfkey_comb->sadb_comb_soft_allocations > pfkey_comb->sadb_comb_hard_allocations) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_soft_allocations=%d > hard_allocations=%d, fatal.\n", -+ i, -+ pfkey_comb->sadb_comb_soft_allocations, -+ pfkey_comb->sadb_comb_hard_allocations); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_comb->sadb_comb_hard_bytes && pfkey_comb->sadb_comb_soft_bytes > pfkey_comb->sadb_comb_hard_bytes) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_soft_bytes=%Ld > hard_bytes=%Ld, fatal.\n", -+ i, -+ (unsigned long long int)pfkey_comb->sadb_comb_soft_bytes, -+ (unsigned long long int)pfkey_comb->sadb_comb_hard_bytes); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_comb->sadb_comb_hard_addtime && pfkey_comb->sadb_comb_soft_addtime > pfkey_comb->sadb_comb_hard_addtime) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_soft_addtime=%Ld > hard_addtime=%Ld, fatal.\n", -+ i, -+ (unsigned long long int)pfkey_comb->sadb_comb_soft_addtime, -+ (unsigned long long int)pfkey_comb->sadb_comb_hard_addtime); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_comb->sadb_comb_hard_usetime && pfkey_comb->sadb_comb_soft_usetime > pfkey_comb->sadb_comb_hard_usetime) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_soft_usetime=%Ld > hard_usetime=%Ld, fatal.\n", -+ i, -+ (unsigned long long int)pfkey_comb->sadb_comb_soft_usetime, -+ (unsigned long long int)pfkey_comb->sadb_comb_hard_usetime); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_comb->sadb_x_comb_hard_packets && pfkey_comb->sadb_x_comb_soft_packets > pfkey_comb->sadb_x_comb_hard_packets) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_x_comb_soft_packets=%d > hard_packets=%d, fatal.\n", -+ i, -+ pfkey_comb->sadb_x_comb_soft_packets, -+ pfkey_comb->sadb_x_comb_hard_packets); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_comb->sadb_comb_reserved) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "comb[%d].res=%d, must be zero.\n", -+ i, -+ pfkey_comb->sadb_comb_reserved); -+ SENDERR(EINVAL); -+ } -+ pfkey_comb++; -+ } -+ -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_supported_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ unsigned int i, num_alg; -+ struct sadb_supported *pfkey_supported = (struct sadb_supported *)pfkey_ext; -+ struct sadb_alg *pfkey_alg = (struct sadb_alg*)((char*)pfkey_ext + sizeof(struct sadb_supported)); -+ -+ /* sanity checks... */ -+ if((pfkey_supported->sadb_supported_len < -+ sizeof(struct sadb_supported) / IPSEC_PFKEYv2_ALIGN) || -+ (((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) - -+ sizeof(struct sadb_supported)) % sizeof(struct sadb_alg))) { -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_supported_parse: " -+ "size wrong ext_len=%d, supported_ext_len=%d alg_ext_len=%d.\n", -+ pfkey_supported->sadb_supported_len, -+ (int)sizeof(struct sadb_supported), -+ (int)sizeof(struct sadb_alg)); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_supported->sadb_supported_reserved) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_supported_parse: " -+ "res=%d, must be zero.\n", -+ pfkey_supported->sadb_supported_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ num_alg = ((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_supported)) / sizeof(struct sadb_alg); -+ -+ for(i = 0; i < num_alg; i++) { -+ /* process algo description */ -+ if(pfkey_alg->sadb_alg_reserved) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_supported_parse: " -+ "alg[%d], id=%d, ivlen=%d, minbits=%d, maxbits=%d, res=%d, must be zero.\n", -+ i, -+ pfkey_alg->sadb_alg_id, -+ pfkey_alg->sadb_alg_ivlen, -+ pfkey_alg->sadb_alg_minbits, -+ pfkey_alg->sadb_alg_maxbits, -+ pfkey_alg->sadb_alg_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ /* XXX can alg_id auth/enc be determined from info given? -+ Yes, but OpenBSD's method does not iteroperate with rfc2367. -+ rgb, 2000-04-06 */ -+ -+ switch(pfkey_supported->sadb_supported_exttype) { -+ case SADB_EXT_SUPPORTED_AUTH: -+ if(pfkey_alg->sadb_alg_id > SADB_AALG_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_supported_parse: " -+ "alg[%d], alg_id=%d > SADB_AALG_MAX=%d, fatal.\n", -+ i, -+ pfkey_alg->sadb_alg_id, -+ SADB_AALG_MAX); -+ SENDERR(EINVAL); -+ } -+ break; -+ case SADB_EXT_SUPPORTED_ENCRYPT: -+ if(pfkey_alg->sadb_alg_id > SADB_EALG_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_supported_parse: " -+ "alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n", -+ i, -+ pfkey_alg->sadb_alg_id, -+ SADB_EALG_MAX); -+ SENDERR(EINVAL); -+ } -+ break; -+ default: -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_supported_parse: " -+ "alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n", -+ i, -+ pfkey_alg->sadb_alg_id, -+ SADB_EALG_MAX); -+ SENDERR(EINVAL); -+ } -+ pfkey_alg++; -+ } -+ -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_spirange_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)pfkey_ext; -+ -+ /* sanity checks... */ -+ if(pfkey_spirange->sadb_spirange_len != -+ sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_spirange_parse: " -+ "size wrong ext_len=%d, key_ext_len=%d.\n", -+ pfkey_spirange->sadb_spirange_len, -+ (int)sizeof(struct sadb_spirange)); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_spirange->sadb_spirange_reserved) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_spirange_parse: " -+ "reserved=%d must be set to zero.\n", -+ pfkey_spirange->sadb_spirange_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ if(ntohl(pfkey_spirange->sadb_spirange_max) < ntohl(pfkey_spirange->sadb_spirange_min)) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_spirange_parse: " -+ "minspi=%08x must be < maxspi=%08x.\n", -+ ntohl(pfkey_spirange->sadb_spirange_min), -+ ntohl(pfkey_spirange->sadb_spirange_max)); -+ SENDERR(EINVAL); -+ } -+ -+ if(ntohl(pfkey_spirange->sadb_spirange_min) <= 255) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_spirange_parse: " -+ "minspi=%08x must be > 255.\n", -+ ntohl(pfkey_spirange->sadb_spirange_min)); -+ SENDERR(EEXIST); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_spirange_parse: " -+ "ext_len=%u ext_type=%u(%s) min=%u max=%u res=%u.\n", -+ pfkey_spirange->sadb_spirange_len, -+ pfkey_spirange->sadb_spirange_exttype, -+ pfkey_v2_sadb_ext_string(pfkey_spirange->sadb_spirange_exttype), -+ pfkey_spirange->sadb_spirange_min, -+ pfkey_spirange->sadb_spirange_max, -+ pfkey_spirange->sadb_spirange_reserved); -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_kmprivate_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)pfkey_ext; -+ -+ /* sanity checks... */ -+ if(pfkey_x_kmprivate->sadb_x_kmprivate_len < -+ sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_kmprivate_parse: " -+ "size wrong ext_len=%d, key_ext_len=%d.\n", -+ pfkey_x_kmprivate->sadb_x_kmprivate_len, -+ (int)sizeof(struct sadb_x_kmprivate)); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_x_kmprivate->sadb_x_kmprivate_reserved) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_kmprivate_parse: " -+ "reserved=%d must be set to zero.\n", -+ pfkey_x_kmprivate->sadb_x_kmprivate_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_kmprivate_parse: " -+ "Sorry, I can't parse exttype=%d yet.\n", -+ pfkey_ext->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_satype_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ int i; -+ struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_x_satype_parse: enter\n"); -+ /* sanity checks... */ -+ if(pfkey_x_satype->sadb_x_satype_len != -+ sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_satype_parse: " -+ "size wrong ext_len=%d, key_ext_len=%d.\n", -+ pfkey_x_satype->sadb_x_satype_len, -+ (int)sizeof(struct sadb_x_satype)); -+ SENDERR(EINVAL); -+ } -+ -+ if(!pfkey_x_satype->sadb_x_satype_satype) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_satype_parse: " -+ "satype is zero, must be non-zero.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_x_satype->sadb_x_satype_satype > SADB_SATYPE_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_satype_parse: " -+ "satype %d > max %d, invalid.\n", -+ pfkey_x_satype->sadb_x_satype_satype, SADB_SATYPE_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(satype2proto(pfkey_x_satype->sadb_x_satype_satype))) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_satype_parse: " -+ "proto lookup from satype=%d failed.\n", -+ pfkey_x_satype->sadb_x_satype_satype); -+ SENDERR(EINVAL); -+ } -+ -+ for(i = 0; i < 3; i++) { -+ if(pfkey_x_satype->sadb_x_satype_reserved[i]) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_satype_parse: " -+ "reserved[%d]=%d must be set to zero.\n", -+ i, pfkey_x_satype->sadb_x_satype_reserved[i]); -+ SENDERR(EINVAL); -+ } -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_x_satype_parse: " -+ "len=%u ext=%u(%s) satype=%u(%s) res=%u,%u,%u.\n", -+ pfkey_x_satype->sadb_x_satype_len, -+ pfkey_x_satype->sadb_x_satype_exttype, -+ pfkey_v2_sadb_ext_string(pfkey_x_satype->sadb_x_satype_exttype), -+ pfkey_x_satype->sadb_x_satype_satype, -+ satype2name(pfkey_x_satype->sadb_x_satype_satype), -+ pfkey_x_satype->sadb_x_satype_reserved[0], -+ pfkey_x_satype->sadb_x_satype_reserved[1], -+ pfkey_x_satype->sadb_x_satype_reserved[2]); -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_ext_debug_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ int i; -+ struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_x_debug_parse: enter\n"); -+ /* sanity checks... */ -+ if(pfkey_x_debug->sadb_x_debug_len != -+ sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_debug_parse: " -+ "size wrong ext_len=%d, key_ext_len=%d.\n", -+ pfkey_x_debug->sadb_x_debug_len, -+ (int)sizeof(struct sadb_x_debug)); -+ SENDERR(EINVAL); -+ } -+ -+ for(i = 0; i < 4; i++) { -+ if(pfkey_x_debug->sadb_x_debug_reserved[i]) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_debug_parse: " -+ "reserved[%d]=%d must be set to zero.\n", -+ i, pfkey_x_debug->sadb_x_debug_reserved[i]); -+ SENDERR(EINVAL); -+ } -+ } -+ -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_ext_protocol_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_protocol *p = (struct sadb_protocol *)pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_protocol_parse:\n"); -+ /* sanity checks... */ -+ -+ if (p->sadb_protocol_len != sizeof(*p)/IPSEC_PFKEYv2_ALIGN) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_protocol_parse: size wrong ext_len=%d, key_ext_len=%d.\n", -+ p->sadb_protocol_len, (int)sizeof(*p)); -+ SENDERR(EINVAL); -+ } -+ -+ if (p->sadb_protocol_reserved2 != 0) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_protocol_parse: res=%d, must be zero.\n", -+ p->sadb_protocol_reserved2); -+ SENDERR(EINVAL); -+ } -+ -+ errlab: -+ return error; -+} -+ -+#ifdef NAT_TRAVERSAL -+DEBUG_NO_STATIC int -+pfkey_x_ext_nat_t_type_parse(struct sadb_ext *pfkey_ext) -+{ -+ return 0; -+} -+DEBUG_NO_STATIC int -+pfkey_x_ext_nat_t_port_parse(struct sadb_ext *pfkey_ext) -+{ -+ return 0; -+} -+#endif -+ -+#define DEFINEPARSER(NAME) static struct pf_key_ext_parsers_def NAME##_def={NAME, #NAME}; -+ -+DEFINEPARSER(pfkey_sa_parse); -+DEFINEPARSER(pfkey_lifetime_parse); -+DEFINEPARSER(pfkey_address_parse); -+DEFINEPARSER(pfkey_key_parse); -+DEFINEPARSER(pfkey_ident_parse); -+DEFINEPARSER(pfkey_sens_parse); -+DEFINEPARSER(pfkey_prop_parse); -+DEFINEPARSER(pfkey_supported_parse); -+DEFINEPARSER(pfkey_spirange_parse); -+DEFINEPARSER(pfkey_x_kmprivate_parse); -+DEFINEPARSER(pfkey_x_satype_parse); -+DEFINEPARSER(pfkey_x_ext_debug_parse); -+DEFINEPARSER(pfkey_x_ext_protocol_parse); -+#ifdef NAT_TRAVERSAL -+DEFINEPARSER(pfkey_x_ext_nat_t_type_parse); -+DEFINEPARSER(pfkey_x_ext_nat_t_port_parse); -+#endif -+ -+struct pf_key_ext_parsers_def *ext_default_parsers[]= -+{ -+ NULL, /* pfkey_msg_parse, */ -+ &pfkey_sa_parse_def, -+ &pfkey_lifetime_parse_def, -+ &pfkey_lifetime_parse_def, -+ &pfkey_lifetime_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_key_parse_def, -+ &pfkey_key_parse_def, -+ &pfkey_ident_parse_def, -+ &pfkey_ident_parse_def, -+ &pfkey_sens_parse_def, -+ &pfkey_prop_parse_def, -+ &pfkey_supported_parse_def, -+ &pfkey_supported_parse_def, -+ &pfkey_spirange_parse_def, -+ &pfkey_x_kmprivate_parse_def, -+ &pfkey_x_satype_parse_def, -+ &pfkey_sa_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_x_ext_debug_parse_def, -+ &pfkey_x_ext_protocol_parse_def -+#ifdef NAT_TRAVERSAL -+ , -+ &pfkey_x_ext_nat_t_type_parse_def, -+ &pfkey_x_ext_nat_t_port_parse_def, -+ &pfkey_x_ext_nat_t_port_parse_def, -+ &pfkey_address_parse_def -+#endif -+}; -+ -+int -+pfkey_msg_parse(struct sadb_msg *pfkey_msg, -+ struct pf_key_ext_parsers_def *ext_parsers[], -+ struct sadb_ext *extensions[], -+ int dir) -+{ -+ int error = 0; -+ int remain; -+ struct sadb_ext *pfkey_ext; -+ int extensions_seen = 0; -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_msg_parse: " -+ "parsing message ver=%d, type=%d(%s), errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n", -+ pfkey_msg->sadb_msg_version, -+ pfkey_msg->sadb_msg_type, -+ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type), -+ pfkey_msg->sadb_msg_errno, -+ pfkey_msg->sadb_msg_satype, -+ satype2name(pfkey_msg->sadb_msg_satype), -+ pfkey_msg->sadb_msg_len, -+ pfkey_msg->sadb_msg_reserved, -+ pfkey_msg->sadb_msg_seq, -+ pfkey_msg->sadb_msg_pid); -+ -+ if(ext_parsers == NULL) ext_parsers = ext_default_parsers; -+ -+ pfkey_extensions_init(extensions); -+ -+ remain = pfkey_msg->sadb_msg_len; -+ remain -= sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN; -+ -+ pfkey_ext = (struct sadb_ext*)((char*)pfkey_msg + -+ sizeof(struct sadb_msg)); -+ -+ extensions[0] = (struct sadb_ext *) pfkey_msg; -+ -+ -+ if(pfkey_msg->sadb_msg_version != PF_KEY_V2) { -+ ERROR("pfkey_msg_parse: " -+ "not PF_KEY_V2 msg, found %d, should be %d.\n", -+ pfkey_msg->sadb_msg_version, -+ PF_KEY_V2); -+ SENDERR(EINVAL); -+ } -+ -+ if(!pfkey_msg->sadb_msg_type) { -+ ERROR("pfkey_msg_parse: " -+ "msg type not set, must be non-zero..\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_msg->sadb_msg_type > SADB_MAX) { -+ ERROR("pfkey_msg_parse: " -+ "msg type=%d > max=%d.\n", -+ pfkey_msg->sadb_msg_type, -+ SADB_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_msg->sadb_msg_type) { -+ case SADB_GETSPI: -+ case SADB_UPDATE: -+ case SADB_ADD: -+ case SADB_DELETE: -+ case SADB_GET: -+ case SADB_X_GRPSA: -+ case SADB_X_ADDFLOW: -+ if(!satype2proto(pfkey_msg->sadb_msg_satype)) { -+ ERROR("pfkey_msg_parse: " -+ "satype %d conversion to proto failed for msg_type %d (%s).\n", -+ pfkey_msg->sadb_msg_satype, -+ pfkey_msg->sadb_msg_type, -+ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type)); -+ SENDERR(EINVAL); -+ } else { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "satype %d(%s) conversion to proto gives %d for msg_type %d(%s).\n", -+ pfkey_msg->sadb_msg_satype, -+ satype2name(pfkey_msg->sadb_msg_satype), -+ satype2proto(pfkey_msg->sadb_msg_satype), -+ pfkey_msg->sadb_msg_type, -+ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type)); -+ } -+ case SADB_ACQUIRE: -+ case SADB_REGISTER: -+ case SADB_EXPIRE: -+ if(!pfkey_msg->sadb_msg_satype) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "satype is zero, must be non-zero for msg_type %d(%s).\n", -+ pfkey_msg->sadb_msg_type, -+ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type)); -+ SENDERR(EINVAL); -+ } -+ default: -+ break; -+ } -+ -+ /* errno must not be set in downward messages */ -+ /* this is not entirely true... a response to an ACQUIRE could return an error */ -+ if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type != SADB_ACQUIRE) && pfkey_msg->sadb_msg_errno) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "errno set to %d.\n", -+ pfkey_msg->sadb_msg_errno); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_msg_parse: " -+ "remain=%d, ext_type=%d(%s), ext_len=%d.\n", -+ remain, -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), -+ pfkey_ext->sadb_ext_len); -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_msg_parse: " -+ "extensions permitted=%08x, required=%08x.\n", -+ extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type], -+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]); -+ -+ extensions_seen = 1; -+ -+ while( (remain * IPSEC_PFKEYv2_ALIGN) >= sizeof(struct sadb_ext) ) { -+ /* Is there enough message left to support another extension header? */ -+ if(remain < pfkey_ext->sadb_ext_len) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "remain %d less than ext len %d.\n", -+ remain, pfkey_ext->sadb_ext_len); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_msg_parse: " -+ "parsing ext type=%d(%s) remain=%d.\n", -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), -+ remain); -+ -+ /* Is the extension header type valid? */ -+ if((pfkey_ext->sadb_ext_type > SADB_EXT_MAX) || (!pfkey_ext->sadb_ext_type)) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "ext type %d(%s) invalid, SADB_EXT_MAX=%d.\n", -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), -+ SADB_EXT_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ /* Have we already seen this type of extension? */ -+ if((extensions_seen & ( 1 << pfkey_ext->sadb_ext_type )) != 0) -+ { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "ext type %d(%s) already seen.\n", -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type)); -+ SENDERR(EINVAL); -+ } -+ -+ /* Do I even know about this type of extension? */ -+ if(ext_parsers[pfkey_ext->sadb_ext_type]==NULL) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "ext type %d(%s) unknown, ignoring.\n", -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type)); -+ goto next_ext; -+ } -+ -+ /* Is this type of extension permitted for this type of message? */ -+ if(!(extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type] & -+ 1<sadb_ext_type)) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "ext type %d(%s) not permitted, exts_perm_in=%08x, 1<sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), -+ extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type], -+ 1<sadb_ext_type); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_msg_parse: " -+ "remain=%d ext_type=%d(%s) ext_len=%d parsing ext 0p%p with parser %s.\n", -+ remain, -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), -+ pfkey_ext->sadb_ext_len, -+ pfkey_ext, -+ ext_parsers[pfkey_ext->sadb_ext_type]->parser_name); -+ -+ /* Parse the extension */ -+ if((error = -+ (*ext_parsers[pfkey_ext->sadb_ext_type]->parser)(pfkey_ext))) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "extension parsing for type %d(%s) failed with error %d.\n", -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), -+ error); -+ SENDERR(-error); -+ } -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_msg_parse: " -+ "Extension %d(%s) parsed.\n", -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type)); -+ -+ /* Mark that we have seen this extension and remember the header location */ -+ extensions_seen |= ( 1 << pfkey_ext->sadb_ext_type ); -+ extensions[pfkey_ext->sadb_ext_type] = pfkey_ext; -+ -+ next_ext: -+ /* Calculate how much message remains */ -+ remain -= pfkey_ext->sadb_ext_len; -+ -+ if(!remain) { -+ break; -+ } -+ /* Find the next extension header */ -+ pfkey_ext = (struct sadb_ext*)((char*)pfkey_ext + -+ pfkey_ext->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); -+ } -+ -+ if(remain) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "unexpected remainder of %d.\n", -+ remain); -+ /* why is there still something remaining? */ -+ SENDERR(EINVAL); -+ } -+ -+ /* check required extensions */ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_msg_parse: " -+ "extensions permitted=%08x, seen=%08x, required=%08x.\n", -+ extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type], -+ extensions_seen, -+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]); -+ -+ /* don't check further if it is an error return message since it -+ may not have a body */ -+ if(pfkey_msg->sadb_msg_errno) { -+ SENDERR(-error); -+ } -+ -+ if((extensions_seen & -+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]) != -+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "required extensions missing:%08x.\n", -+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type] - -+ (extensions_seen & -+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type])); -+ SENDERR(EINVAL); -+ } -+ -+ if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type == SADB_X_DELFLOW) -+ && ((extensions_seen & SADB_X_EXT_ADDRESS_DELFLOW) -+ != SADB_X_EXT_ADDRESS_DELFLOW) -+ && (((extensions_seen & (1<sadb_sa_flags -+ & SADB_X_SAFLAGS_CLEARFLOW) -+ != SADB_X_SAFLAGS_CLEARFLOW))) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "required SADB_X_DELFLOW extensions missing: either %08x must be present or %08x must be present with SADB_X_SAFLAGS_CLEARFLOW set.\n", -+ SADB_X_EXT_ADDRESS_DELFLOW -+ - (extensions_seen & SADB_X_EXT_ADDRESS_DELFLOW), -+ (1<sadb_msg_type) { -+ case SADB_ADD: -+ case SADB_UPDATE: -+ /* check maturity */ -+ if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != -+ SADB_SASTATE_MATURE) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "state=%d for add or update should be MATURE=%d.\n", -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state, -+ SADB_SASTATE_MATURE); -+ SENDERR(EINVAL); -+ } -+ -+ /* check AH and ESP */ -+ switch(((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype) { -+ case SADB_SATYPE_AH: -+ if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) && -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_auth != -+ SADB_AALG_NONE)) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "auth alg is zero, must be non-zero for AH SAs.\n"); -+ SENDERR(EINVAL); -+ } -+ if(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt != -+ SADB_EALG_NONE) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "AH handed encalg=%d, must be zero.\n", -+ ((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt); -+ SENDERR(EINVAL); -+ } -+ break; -+ case SADB_SATYPE_ESP: -+ if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) && -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt != -+ SADB_EALG_NONE)) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "encrypt alg=%d is zero, must be non-zero for ESP=%d SAs.\n", -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype); -+ SENDERR(EINVAL); -+ } -+ if((((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt == -+ SADB_EALG_NULL) && -+ (((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth == -+ SADB_AALG_NONE) ) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "ESP handed encNULL+authNONE, illegal combination.\n"); -+ SENDERR(EINVAL); -+ } -+ break; -+ case SADB_X_SATYPE_COMP: -+ if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) && -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt != -+ SADB_EALG_NONE)) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "encrypt alg=%d is zero, must be non-zero for COMP=%d SAs.\n", -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype); -+ SENDERR(EINVAL); -+ } -+ if(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth != -+ SADB_AALG_NONE) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "COMP handed auth=%d, must be zero.\n", -+ ((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth); -+ SENDERR(EINVAL); -+ } -+ break; -+ default: -+ break; -+ } -+ if(ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi) <= 255) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "spi=%08x must be > 255.\n", -+ ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi)); -+ SENDERR(EINVAL); -+ } -+ default: -+ break; -+ } -+errlab: -+ -+ return error; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.59 2004/04/18 03:03:49 mcr -+ * renamed common include files from pluto directory. -+ * -+ * Revision 1.58 2004/03/08 01:59:08 ken -+ * freeswan.h -> openswan.h -+ * -+ * Revision 1.57 2003/12/10 01:20:19 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.56 2003/12/04 23:01:12 mcr -+ * removed ipsec_netlink.h -+ * -+ * Revision 1.55 2003/11/07 01:30:37 ken -+ * Cast sizeof() to int to keep things 64bit clean -+ * -+ * Revision 1.54 2003/10/31 02:27:12 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.53.20.2 2003/10/29 01:11:32 mcr -+ * added debugging for pfkey library. -+ * -+ * Revision 1.53.20.1 2003/09/21 13:59:44 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.53 2003/01/30 02:32:09 rgb -+ * -+ * Rename SAref table macro names for clarity. -+ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. -+ * -+ * Revision 1.52 2002/12/30 06:53:07 mcr -+ * deal with short SA structures... #if 0 out for now. Probably -+ * not quite the right way. -+ * -+ * Revision 1.51 2002/12/13 18:16:02 mcr -+ * restored sa_ref code -+ * -+ * Revision 1.50 2002/12/13 18:06:52 mcr -+ * temporarily removed sadb_x_sa_ref reference for 2.xx -+ * -+ * Revision 1.49 2002/10/05 05:02:58 dhr -+ * -+ * C labels go on statements -+ * -+ * Revision 1.48 2002/09/20 15:40:45 rgb -+ * Added sadb_x_sa_ref to struct sadb_sa. -+ * -+ * Revision 1.47 2002/09/20 05:01:31 rgb -+ * Fixed usage of pfkey_lib_debug. -+ * Format for function declaration style consistency. -+ * Added text labels to elucidate numeric values presented. -+ * Re-organised debug output to reduce noise in output. -+ * -+ * Revision 1.46 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.45 2002/05/23 07:14:11 rgb -+ * Cleaned up %p variants to 0p%p for test suite cleanup. -+ * -+ * Revision 1.44 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.43 2002/04/24 07:36:40 mcr -+ * Moved from ./lib/pfkey_v2_parse.c,v -+ * -+ * Revision 1.42 2002/01/29 22:25:36 rgb -+ * Re-add ipsec_kversion.h to keep MALLOC happy. -+ * -+ * Revision 1.41 2002/01/29 01:59:10 mcr -+ * removal of kversions.h - sources that needed it now use ipsec_param.h. -+ * updating of IPv6 structures to match latest in6.h version. -+ * removed dead code from openswan.h that also duplicated kversions.h -+ * code. -+ * -+ * Revision 1.40 2002/01/20 20:34:50 mcr -+ * added pfkey_v2_sadb_type_string to decode sadb_type to string. -+ * -+ * Revision 1.39 2001/11/27 05:29:22 mcr -+ * pfkey parses are now maintained by a structure -+ * that includes their name for debug purposes. -+ * DEBUGGING() macro changed so that it takes a debug -+ * level so that pf_key() can use this to decode the -+ * structures without innundanting humans. -+ * Also uses pfkey_v2_sadb_ext_string() in messages. -+ * -+ * Revision 1.38 2001/11/06 19:47:47 rgb -+ * Added packet parameter to lifetime and comb structures. -+ * -+ * Revision 1.37 2001/10/18 04:45:24 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/openswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.36 2001/06/14 19:35:16 rgb -+ * Update copyright date. -+ * -+ * Revision 1.35 2001/05/03 19:44:51 rgb -+ * Standardise on SENDERR() macro. -+ * -+ * Revision 1.34 2001/03/16 07:41:51 rgb -+ * Put openswan.h include before pluto includes. -+ * -+ * Revision 1.33 2001/02/27 07:13:51 rgb -+ * Added satype2name() function. -+ * Added text to default satype_tbl entry. -+ * Added satype2name() conversions for most satype debug output. -+ * -+ * Revision 1.32 2001/02/26 20:01:09 rgb -+ * Added internal IP protocol 61 for magic SAs. -+ * Ditch unused sadb_satype2proto[], replaced by satype2proto(). -+ * Re-formatted debug output (split lines, consistent spacing). -+ * Removed acquire, register and expire requirements for a known satype. -+ * Changed message type checking to a switch structure. -+ * Verify expected NULL auth for IPCOMP. -+ * Enforced spi > 0x100 requirement, now that pass uses a magic SA for -+ * appropriate message types. -+ * -+ * Revision 1.31 2000/12/01 07:09:00 rgb -+ * Added ipcomp sanity check to require encalgo is set. -+ * -+ * Revision 1.30 2000/11/17 18:10:30 rgb -+ * Fixed bugs mostly relating to spirange, to treat all spi variables as -+ * network byte order since this is the way PF_KEYv2 stored spis. -+ * -+ * Revision 1.29 2000/10/12 00:02:39 rgb -+ * Removed 'format, ##' nonsense from debug macros for RH7.0. -+ * -+ * Revision 1.28 2000/09/20 16:23:04 rgb -+ * Remove over-paranoid extension check in the presence of sadb_msg_errno. -+ * -+ * Revision 1.27 2000/09/20 04:04:21 rgb -+ * Changed static functions to DEBUG_NO_STATIC to reveal function names in -+ * oopsen. -+ * -+ * Revision 1.26 2000/09/15 11:37:02 rgb -+ * Merge in heavily modified Svenning Soerensen's -+ * IPCOMP zlib deflate code. -+ * -+ * Revision 1.25 2000/09/12 22:35:37 rgb -+ * Restructured to remove unused extensions from CLEARFLOW messages. -+ * -+ * Revision 1.24 2000/09/12 18:59:54 rgb -+ * Added Gerhard's IPv6 support to pfkey parts of libopenswan. -+ * -+ * Revision 1.23 2000/09/12 03:27:00 rgb -+ * Moved DEBUGGING definition to compile kernel with debug off. -+ * -+ * Revision 1.22 2000/09/09 06:39:27 rgb -+ * Restrict pfkey errno check to downward messages only. -+ * -+ * Revision 1.21 2000/09/08 19:22:34 rgb -+ * Enabled pfkey_sens_parse(). -+ * Added check for errno on downward acquire messages only. -+ * -+ * Revision 1.20 2000/09/01 18:48:23 rgb -+ * Fixed reserved check bug and added debug output in -+ * pfkey_supported_parse(). -+ * Fixed debug output label bug in pfkey_ident_parse(). -+ * -+ * Revision 1.19 2000/08/27 01:55:26 rgb -+ * Define OCTETBITS and PFKEYBITS to avoid using 'magic' numbers in code. -+ * -+ * Revision 1.18 2000/08/24 17:00:36 rgb -+ * Ignore unknown extensions instead of failing. -+ * -+ * Revision 1.17 2000/06/02 22:54:14 rgb -+ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support. -+ * -+ * Revision 1.16 2000/05/10 19:25:11 rgb -+ * Fleshed out proposal and supported extensions. -+ * -+ * Revision 1.15 2000/01/24 21:15:31 rgb -+ * Added disabled pluto pfkey lib debug flag. -+ * Added algo debugging reporting. -+ * -+ * Revision 1.14 2000/01/22 23:24:29 rgb -+ * Added new functions proto2satype() and satype2proto() and lookup -+ * table satype_tbl. Also added proto2name() since it was easy. -+ * -+ * Revision 1.13 2000/01/21 09:43:59 rgb -+ * Cast ntohl(spi) as (unsigned long int) to shut up compiler. -+ * -+ * Revision 1.12 2000/01/21 06:28:19 rgb -+ * Added address cases for eroute flows. -+ * Indented compiler directives for readability. -+ * Added klipsdebug switching capability. -+ * -+ * Revision 1.11 1999/12/29 21:14:59 rgb -+ * Fixed debug text cut and paste typo. -+ * -+ * Revision 1.10 1999/12/10 17:45:24 rgb -+ * Added address debugging. -+ * -+ * Revision 1.9 1999/12/09 23:11:42 rgb -+ * Ditched include since we no longer use memset(). -+ * Use new pfkey_extensions_init() instead of memset(). -+ * Added check for SATYPE in pfkey_msg_build(). -+ * Tidy up comments and debugging comments. -+ * -+ * Revision 1.8 1999/12/07 19:55:26 rgb -+ * Removed unused first argument from extension parsers. -+ * Removed static pluto debug flag. -+ * Moved message type and state checking to pfkey_msg_parse(). -+ * Changed print[fk] type from lx to x to quiet compiler. -+ * Removed redundant remain check. -+ * Changed __u* types to uint* to avoid use of asm/types.h and -+ * sys/types.h in userspace code. -+ * -+ * Revision 1.7 1999/12/01 22:20:51 rgb -+ * Moved pfkey_lib_debug variable into the library. -+ * Added pfkey version check into header parsing. -+ * Added check for SATYPE only for those extensions that require a -+ * non-zero value. -+ * -+ * Revision 1.6 1999/11/27 11:58:05 rgb -+ * Added ipv6 headers. -+ * Moved sadb_satype2proto protocol lookup table from -+ * klips/net/ipsec/pfkey_v2_parser.c. -+ * Enable lifetime_current checking. -+ * Debugging error messages added. -+ * Add argument to pfkey_msg_parse() for direction. -+ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array. -+ * Add CVS log entry to bottom of file. -+ * Moved auth and enc alg check to pfkey_msg_parse(). -+ * Enable accidentally disabled spirange parsing. -+ * Moved protocol/algorithm checks from klips/net/ipsec/pfkey_v2_parser.c -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/prng.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,201 @@ -+/* -+ * crypto-class pseudorandom number generator -+ * currently uses same algorithm as RC4(TM), from Schneier 2nd ed p397 -+ * Copyright (C) 2002 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - prng_init - initialize PRNG from a key -+ */ -+void -+prng_init(prng, key, keylen) -+struct prng *prng; -+const unsigned char *key; -+size_t keylen; -+{ -+ unsigned char k[256]; -+ int i, j; -+ unsigned const char *p; -+ unsigned const char *keyend = key + keylen; -+ unsigned char t; -+ -+ for (i = 0; i <= 255; i++) -+ prng->sbox[i] = i; -+ p = key; -+ for (i = 0; i <= 255; i++) { -+ k[i] = *p++; -+ if (p >= keyend) -+ p = key; -+ } -+ j = 0; -+ for (i = 0; i <= 255; i++) { -+ j = (j + prng->sbox[i] + k[i]) & 0xff; -+ t = prng->sbox[i]; -+ prng->sbox[i] = prng->sbox[j]; -+ prng->sbox[j] = t; -+ k[i] = 0; /* clear out key memory */ -+ } -+ prng->i = 0; -+ prng->j = 0; -+ prng->count = 0; -+} -+ -+/* -+ - prng_bytes - get some pseudorandom bytes from PRNG -+ */ -+void -+prng_bytes(prng, dst, dstlen) -+struct prng *prng; -+unsigned char *dst; -+size_t dstlen; -+{ -+ int i, j, t; -+ unsigned char *p = dst; -+ size_t remain = dstlen; -+# define MAX 4000000000ul -+ -+ while (remain > 0) { -+ i = (prng->i + 1) & 0xff; -+ prng->i = i; -+ j = (prng->j + prng->sbox[i]) & 0xff; -+ prng->j = j; -+ t = prng->sbox[i]; -+ prng->sbox[i] = prng->sbox[j]; -+ prng->sbox[j] = t; -+ t = (t + prng->sbox[i]) & 0xff; -+ *p++ = prng->sbox[t]; -+ remain--; -+ } -+ if (prng->count < MAX - dstlen) -+ prng->count += dstlen; -+ else -+ prng->count = MAX; -+} -+ -+/* -+ - prnt_count - how many bytes have been extracted from PRNG so far? -+ */ -+unsigned long -+prng_count(prng) -+struct prng *prng; -+{ -+ return prng->count; -+} -+ -+/* -+ - prng_final - clear out PRNG to ensure nothing left in memory -+ */ -+void -+prng_final(prng) -+struct prng *prng; -+{ -+ int i; -+ -+ for (i = 0; i <= 255; i++) -+ prng->sbox[i] = 0; -+ prng->i = 0; -+ prng->j = 0; -+ prng->count = 0; /* just for good measure */ -+} -+ -+ -+ -+#ifdef PRNG_MAIN -+ -+#include -+ -+void regress(); -+ -+int -+main(argc, argv) -+int argc; -+char *argv[]; -+{ -+ struct prng pr; -+ unsigned char buf[100]; -+ unsigned char *p; -+ size_t n; -+ -+ if (argc < 2) { -+ fprintf(stderr, "Usage: %s {key|-r}\n", argv[0]); -+ exit(2); -+ } -+ -+ if (strcmp(argv[1], "-r") == 0) { -+ regress(); -+ fprintf(stderr, "regress() returned?!?\n"); -+ exit(1); -+ } -+ -+ prng_init(&pr, argv[1], strlen(argv[1])); -+ prng_bytes(&pr, buf, 32); -+ printf("0x"); -+ for (p = buf, n = 32; n > 0; p++, n--) -+ printf("%02x", *p); -+ printf("\n%lu bytes\n", prng_count(&pr)); -+ prng_final(&pr); -+ exit(0); -+} -+ -+void -+regress() -+{ -+ struct prng pr; -+ unsigned char buf[100]; -+ unsigned char *p; -+ size_t n; -+ /* somewhat non-random sample key */ -+ unsigned char key[] = "here we go gathering nuts in May"; -+ /* first thirty bytes of output from that key */ -+ unsigned char good[] = "\x3f\x02\x8e\x4a\x2a\xea\x23\x18\x92\x7c" -+ "\x09\x52\x83\x61\xaa\x26\xce\xbb\x9d\x71" -+ "\x71\xe5\x10\x22\xaf\x60\x54\x8d\x5b\x28"; -+ int nzero, none; -+ int show = 0; -+ -+ prng_init(&pr, key, strlen(key)); -+ prng_bytes(&pr, buf, sizeof(buf)); -+ for (p = buf, n = sizeof(buf); n > 0; p++, n--) { -+ if (*p == 0) -+ nzero++; -+ if (*p == 255) -+ none++; -+ } -+ if (nzero > 3 || none > 3) { -+ fprintf(stderr, "suspiciously non-random output!\n"); -+ show = 1; -+ } -+ if (memcmp(buf, good, strlen(good)) != 0) { -+ fprintf(stderr, "incorrect output!\n"); -+ show = 1; -+ } -+ if (show) { -+ fprintf(stderr, "0x"); -+ for (p = buf, n = sizeof(buf); n > 0; p++, n--) -+ fprintf(stderr, "%02x", *p); -+ fprintf(stderr, "\n"); -+ exit(1); -+ } -+ if (prng_count(&pr) != sizeof(buf)) { -+ fprintf(stderr, "got %u bytes, but count is %lu\n", -+ sizeof(buf), prng_count(&pr)); -+ exit(1); -+ } -+ prng_final(&pr); -+ exit(0); -+} -+ -+#endif /* PRNG_MAIN */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/rangetoa.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,60 @@ -+/* -+ * convert binary form of address range to ASCII -+ * Copyright (C) 1998, 1999 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - rangetoa - convert address range to ASCII -+ */ -+size_t /* space needed for full conversion */ -+rangetoa(addrs, format, dst, dstlen) -+struct in_addr addrs[2]; -+int format; /* character */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ size_t len; -+ size_t rest; -+ int n; -+ char *p; -+ -+ switch (format) { -+ case 0: -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ len = addrtoa(addrs[0], 0, dst, dstlen); -+ if (len < dstlen) -+ for (p = dst + len - 1, n = 3; len < dstlen && n > 0; -+ p++, len++, n--) -+ *p = '.'; -+ else -+ p = NULL; -+ if (len < dstlen) -+ rest = dstlen - len; -+ else { -+ if (dstlen > 0) -+ *(dst + dstlen - 1) = '\0'; -+ rest = 0; -+ } -+ -+ len += addrtoa(addrs[1], 0, p, rest); -+ -+ return len; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/satot.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,133 @@ -+/* -+ * convert from binary form of SA ID to text -+ * Copyright (C) 2000, 2001 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+static struct typename { -+ char type; -+ char *name; -+} typenames[] = { -+ { SA_AH, "ah" }, -+ { SA_ESP, "esp" }, -+ { SA_IPIP, "tun" }, -+ { SA_COMP, "comp" }, -+ { SA_INT, "int" }, -+ { 0, NULL } -+}; -+ -+/* -+ - satot - convert SA to text "ah507@1.2.3.4" -+ */ -+size_t /* space needed for full conversion */ -+satot(sa, format, dst, dstlen) -+const ip_said *sa; -+int format; /* character */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ size_t len = 0; /* 0 means "not recognized yet" */ -+ int base; -+ int showversion; /* use delimiter to show IP version? */ -+ struct typename *tn; -+ char *p; -+ char *pre; -+ char buf[10+1+ULTOT_BUF+ADDRTOT_BUF]; -+ char unk[10]; -+ -+ switch (format) { -+ case 0: -+ base = 16; -+ showversion = 1; -+ break; -+ case 'f': -+ base = 17; -+ showversion = 1; -+ break; -+ case 'x': -+ base = 'x'; -+ showversion = 0; -+ break; -+ case 'd': -+ base = 10; -+ showversion = 0; -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ memset(buf, 0, sizeof(buf)); -+ -+ pre = NULL; -+ for (tn = typenames; tn->name != NULL; tn++) -+ if (sa->proto == tn->type) { -+ pre = tn->name; -+ break; /* NOTE BREAK OUT */ -+ } -+ if (pre == NULL) { /* unknown protocol */ -+ strcpy(unk, "unk"); -+ (void) ultot((unsigned char)sa->proto, 10, unk+strlen(unk), -+ sizeof(unk)-strlen(unk)); -+ pre = unk; -+ } -+ -+ if (strcmp(pre, PASSTHROUGHTYPE) == 0 && -+ sa->spi == PASSTHROUGHSPI && -+ isunspecaddr(&sa->dst)) { -+ strcpy(buf, (addrtypeof(&sa->dst) == AF_INET) ? -+ PASSTHROUGH4NAME : -+ PASSTHROUGH6NAME); -+ len = strlen(buf); -+ } -+ -+ if (sa->proto == SA_INT) { -+ switch (ntohl(sa->spi)) { -+ case SPI_PASS: p = "%pass"; break; -+ case SPI_DROP: p = "%drop"; break; -+ case SPI_REJECT: p = "%reject"; break; -+ case SPI_HOLD: p = "%hold"; break; -+ case SPI_TRAP: p = "%trap"; break; -+ case SPI_TRAPSUBNET: p = "%trapsubnet"; break; -+ default: p = NULL; break; -+ } -+ if (p != NULL) { -+ strcpy(buf, p); -+ len = strlen(buf); -+ } -+ } -+ -+ if (len == 0) { /* general case needed */ -+ strcpy(buf, pre); -+ len = strlen(buf); -+ if (showversion) { -+ *(buf+len) = (addrtypeof(&sa->dst) == AF_INET) ? '.' : -+ ':'; -+ len++; -+ *(buf+len) = '\0'; -+ } -+ len += ultot(ntohl(sa->spi), base, buf+len, sizeof(buf)-len); -+ *(buf+len-1) = '@'; -+ len += addrtot(&sa->dst, 0, buf+len, sizeof(buf)-len); -+ *(buf+len) = '\0'; -+ } -+ -+ if (dst != NULL) { -+ if (len > dstlen) -+ *(buf+dstlen-1) = '\0'; -+ strcpy(dst, buf); -+ } -+ return len; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/subnetof.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,59 @@ -+/* -+ * minor network-address manipulation utilities -+ * Copyright (C) 1998, 1999 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - subnetof - given address and mask, return subnet part -+ */ -+struct in_addr -+subnetof(addr, mask) -+struct in_addr addr; -+struct in_addr mask; -+{ -+ struct in_addr result; -+ -+ result.s_addr = addr.s_addr & mask.s_addr; -+ return result; -+} -+ -+/* -+ - hostof - given address and mask, return host part -+ */ -+struct in_addr -+hostof(addr, mask) -+struct in_addr addr; -+struct in_addr mask; -+{ -+ struct in_addr result; -+ -+ result.s_addr = addr.s_addr & ~mask.s_addr; -+ return result; -+} -+ -+/* -+ - broadcastof - given (network) address and mask, return broadcast address -+ */ -+struct in_addr -+broadcastof(addr, mask) -+struct in_addr addr; -+struct in_addr mask; -+{ -+ struct in_addr result; -+ -+ result.s_addr = addr.s_addr | ~mask.s_addr; -+ return result; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/subnettoa.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,61 @@ -+/* -+ * convert binary form of subnet description to ASCII -+ * Copyright (C) 1998, 1999 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - subnettoa - convert address and mask to ASCII "addr/mask" -+ * Output expresses the mask as a bit count if possible, else dotted decimal. -+ */ -+size_t /* space needed for full conversion */ -+subnettoa(addr, mask, format, dst, dstlen) -+struct in_addr addr; -+struct in_addr mask; -+int format; /* character */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ size_t len; -+ size_t rest; -+ int n; -+ char *p; -+ -+ switch (format) { -+ case 0: -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ len = addrtoa(addr, 0, dst, dstlen); -+ if (len < dstlen) { -+ dst[len - 1] = '/'; -+ p = dst + len; -+ rest = dstlen - len; -+ } else { -+ p = NULL; -+ rest = 0; -+ } -+ -+ n = masktobits(mask); -+ if (n >= 0) -+ len += ultoa((unsigned long)n, 10, p, rest); -+ else -+ len += addrtoa(mask, 0, p, rest); -+ -+ return len; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/ultoa.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,66 @@ -+/* -+ * convert unsigned long to ASCII -+ * Copyright (C) 1998, 1999 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - ultoa - convert unsigned long to decimal ASCII -+ */ -+size_t /* length required for full conversion */ -+ultoa(n, base, dst, dstlen) -+unsigned long n; -+int base; -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ char buf[3*sizeof(unsigned long) + 1]; -+ char *bufend = buf + sizeof(buf); -+ size_t len; -+ char *p; -+ static char hex[] = "0123456789abcdef"; -+ -+ p = bufend; -+ *--p = '\0'; -+ if (base == 10) { -+ do { -+ *--p = n%10 + '0'; -+ n /= 10; -+ } while (n != 0); -+ } else if (base == 16) { -+ do { -+ *--p = hex[n&0xf]; -+ n >>= 4; -+ } while (n != 0); -+ *--p = 'x'; -+ *--p = '0'; -+ } else if (base == 8) { -+ do { -+ *--p = (n&07) + '0'; -+ n >>= 3; -+ } while (n != 0); -+ *--p = '0'; -+ } else -+ *--p = '?'; -+ -+ len = bufend - p; -+ -+ if (dstlen > 0) { -+ if (len > dstlen) -+ *(p + dstlen - 1) = '\0'; -+ strcpy(dst, p); -+ } -+ return len; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/ultot.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,82 @@ -+/* -+ * convert unsigned long to text -+ * Copyright (C) 2000 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - ultot - convert unsigned long to text -+ */ -+size_t /* length required for full conversion */ -+ultot(n, base, dst, dstlen) -+unsigned long n; -+int base; -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ char buf[3*sizeof(unsigned long) + 1]; -+ char *bufend = buf + sizeof(buf); -+ size_t len; -+ char *p; -+ static char hex[] = "0123456789abcdef"; -+# define HEX32 (32/4) -+ -+ p = bufend; -+ *--p = '\0'; -+ switch (base) { -+ case 10: -+ case 'd': -+ do { -+ *--p = n%10 + '0'; -+ n /= 10; -+ } while (n != 0); -+ break; -+ case 16: -+ case 17: -+ case 'x': -+ do { -+ *--p = hex[n&0xf]; -+ n >>= 4; -+ } while (n != 0); -+ if (base == 17) -+ while (bufend - p < HEX32 + 1) -+ *--p = '0'; -+ if (base == 'x') { -+ *--p = 'x'; -+ *--p = '0'; -+ } -+ break; -+ case 8: -+ case 'o': -+ do { -+ *--p = (n&07) + '0'; -+ n >>= 3; -+ } while (n != 0); -+ if (base == 'o') -+ *--p = '0'; -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ len = bufend - p; -+ if (dstlen > 0) { -+ if (len > dstlen) -+ *(p + dstlen - 1) = '\0'; -+ strcpy(dst, p); -+ } -+ return len; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/Makefile Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,118 @@ -+# (kernel) Makefile for IPCOMP zlib deflate code -+# Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+# Copyright (C) 2000 Svenning Soerensen -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by the -+# Free Software Foundation; either version 2 of the License, or (at your -+# option) any later version. See . -+# -+# This program is distributed in 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. -+# -+# RCSID $Id$ -+# -+ -+ -+ -+include ../Makefile.inc -+ -+ -+ -+ifndef TOPDIR -+TOPDIR := /usr/src/linux -+endif -+ -+ -+L_TARGET := zlib.a -+ -+obj-y := -+ -+include Makefile.objs -+ -+EXTRA_CFLAGS += $(KLIPSCOMPILE) -+ -+EXTRA_CFLAGS += -Wall -+#EXTRA_CFLAGS += -Wconversion -+#EXTRA_CFLAGS += -Wmissing-prototypes -+EXTRA_CFLAGS += -Wpointer-arith -+#EXTRA_CFLAGS += -Wcast-qual -+#EXTRA_CFLAGS += -Wmissing-declarations -+EXTRA_CFLAGS += -Wstrict-prototypes -+#EXTRA_CFLAGS += -pedantic -+#EXTRA_CFLAGS += -W -+#EXTRA_CFLAGS += -Wwrite-strings -+EXTRA_CFLAGS += -Wbad-function-cast -+EXTRA_CFLAGS += -DIPCOMP_PREFIX -+ -+.S.o: -+ $(CC) -D__ASSEMBLY__ -DNO_UNDERLINE -traditional -c $< -o $*.o -+ -+asm-obj-$(CONFIG_M586) += match586.o -+asm-obj-$(CONFIG_M586TSC) += match586.o -+asm-obj-$(CONFIG_M586MMX) += match586.o -+asm-obj-$(CONFIG_M686) += match686.o -+asm-obj-$(CONFIG_MPENTIUMIII) += match686.o -+asm-obj-$(CONFIG_MPENTIUM4) += match686.o -+asm-obj-$(CONFIG_MK6) += match586.o -+asm-obj-$(CONFIG_MK7) += match686.o -+asm-obj-$(CONFIG_MCRUSOE) += match586.o -+asm-obj-$(CONFIG_MWINCHIPC6) += match586.o -+asm-obj-$(CONFIG_MWINCHIP2) += match686.o -+asm-obj-$(CONFIG_MWINCHIP3D) += match686.o -+ -+obj-y += $(asm-obj-y) -+ifneq ($(strip $(asm-obj-y)),) -+ EXTRA_CFLAGS += -DASMV -+endif -+ -+active-objs := $(sort $(obj-y) $(obj-m)) -+L_OBJS := $(obj-y) -+M_OBJS := $(obj-m) -+MIX_OBJS := $(filter $(export-objs), $(active-objs)) -+ -+include $(TOPDIR)/Rules.make -+ -+$(obj-y) : $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h -+ -+ -+clean: -+ -rm -f *.o *.a -+ -+checkprograms: -+programs: $(L_TARGET) -+ -+# -+# $Log$ -+# Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+# Turn off EOLN_NATIVE flag -+# -+# (Logical change 1.5010) -+# -+# Revision 1.9 2002/04/24 07:55:32 mcr -+# #include patches and Makefiles for post-reorg compilation. -+# -+# Revision 1.8 2002/04/24 07:36:44 mcr -+# Moved from ./zlib/Makefile,v -+# -+# Revision 1.7 2002/03/27 23:34:35 mcr -+# added programs: target -+# -+# Revision 1.6 2001/12/05 20:19:08 henry -+# use new compile-control variable -+# -+# Revision 1.5 2001/11/27 16:38:08 mcr -+# added new "checkprograms" target to deal with programs that -+# are required for "make check", but that may not be ready to -+# build for every user due to external dependancies. -+# -+# Revision 1.4 2001/10/24 14:46:24 henry -+# Makefile.inc -+# -+# Revision 1.3 2001/04/21 23:05:24 rgb -+# Update asm directives for 2.4 style makefiles. -+# -+# Revision 1.2 2001/01/29 22:22:00 rgb -+# Convert to 2.4 new style with back compat. -+# -+# Revision 1.1.1.1 2000/09/29 18:51:33 rgb -+# zlib_beginnings -+# -+# ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/Makefile.objs Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,27 @@ -+obj-$(CONFIG_IPSEC_IPCOMP) += adler32.o -+obj-$(CONFIG_IPSEC_IPCOMP) += deflate.o -+obj-$(CONFIG_IPSEC_IPCOMP) += infblock.o -+obj-$(CONFIG_IPSEC_IPCOMP) += infcodes.o -+obj-$(CONFIG_IPSEC_IPCOMP) += inffast.o -+obj-$(CONFIG_IPSEC_IPCOMP) += inflate.o -+obj-$(CONFIG_IPSEC_IPCOMP) += inftrees.o -+obj-$(CONFIG_IPSEC_IPCOMP) += infutil.o -+obj-$(CONFIG_IPSEC_IPCOMP) += trees.o -+obj-$(CONFIG_IPSEC_IPCOMP) += zutil.o -+ -+asm-obj-$(CONFIG_M586) += ${LIBZLIBSRCDIR}/match586.o -+asm-obj-$(CONFIG_M586TSC) += ${LIBZLIBSRCDIR}/match586.o -+asm-obj-$(CONFIG_M586MMX) += ${LIBZLIBSRCDIR}/match586.o -+asm-obj-$(CONFIG_M686) += ${LIBZLIBSRCDIR}/match686.o -+asm-obj-$(CONFIG_MPENTIUMIII) += ${LIBZLIBSRCDIR}/match686.o -+asm-obj-$(CONFIG_MPENTIUM4) += ${LIBZLIBSRCDIR}/match686.o -+asm-obj-$(CONFIG_MK6) += ${LIBZLIBSRCDIR}/match586.o -+asm-obj-$(CONFIG_MK7) += ${LIBZLIBSRCDIR}/match686.o -+asm-obj-$(CONFIG_MCRUSOE) += ${LIBZLIBSRCDIR}/match586.o -+asm-obj-$(CONFIG_MWINCHIPC6) += ${LIBZLIBSRCDIR}/match586.o -+asm-obj-$(CONFIG_MWINCHIP2) += ${LIBZLIBSRCDIR}/match686.o -+asm-obj-$(CONFIG_MWINCHIP3D) += ${LIBZLIBSRCDIR}/match686.o -+ -+EXTRA_CFLAGS += -DIPCOMP_PREFIX -+ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/README Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,147 @@ -+zlib 1.1.4 is a general purpose data compression library. All the code -+is thread safe. The data format used by the zlib library -+is described by RFCs (Request for Comments) 1950 to 1952 in the files -+http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate -+format) and rfc1952.txt (gzip format). These documents are also available in -+other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html -+ -+All functions of the compression library are documented in the file zlib.h -+(volunteer to write man pages welcome, contact jloup@gzip.org). A usage -+example of the library is given in the file example.c which also tests that -+the library is working correctly. Another example is given in the file -+minigzip.c. The compression library itself is composed of all source files -+except example.c and minigzip.c. -+ -+To compile all files and run the test program, follow the instructions -+given at the top of Makefile. In short "make test; make install" -+should work for most machines. For Unix: "./configure; make test; make install" -+For MSDOS, use one of the special makefiles such as Makefile.msc. -+For VMS, use Make_vms.com or descrip.mms. -+ -+Questions about zlib should be sent to , or to -+Gilles Vollant for the Windows DLL version. -+The zlib home page is http://www.zlib.org or http://www.gzip.org/zlib/ -+Before reporting a problem, please check this site to verify that -+you have the latest version of zlib; otherwise get the latest version and -+check whether the problem still exists or not. -+ -+PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html -+before asking for help. -+ -+Mark Nelson wrote an article about zlib for the Jan. 1997 -+issue of Dr. Dobb's Journal; a copy of the article is available in -+http://dogma.net/markn/articles/zlibtool/zlibtool.htm -+ -+The changes made in version 1.1.4 are documented in the file ChangeLog. -+The only changes made since 1.1.3 are bug corrections: -+ -+- ZFREE was repeated on same allocation on some error conditions. -+ This creates a security problem described in -+ http://www.zlib.org/advisory-2002-03-11.txt -+- Returned incorrect error (Z_MEM_ERROR) on some invalid data -+- Avoid accesses before window for invalid distances with inflate window -+ less than 32K. -+- force windowBits > 8 to avoid a bug in the encoder for a window size -+ of 256 bytes. (A complete fix will be available in 1.1.5). -+ -+The beta version 1.1.5beta includes many more changes. A new official -+version 1.1.5 will be released as soon as extensive testing has been -+completed on it. -+ -+ -+Unsupported third party contributions are provided in directory "contrib". -+ -+A Java implementation of zlib is available in the Java Development Kit -+http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html -+See the zlib home page http://www.zlib.org for details. -+ -+A Perl interface to zlib written by Paul Marquess -+is in the CPAN (Comprehensive Perl Archive Network) sites -+http://www.cpan.org/modules/by-module/Compress/ -+ -+A Python interface to zlib written by A.M. Kuchling -+is available in Python 1.5 and later versions, see -+http://www.python.org/doc/lib/module-zlib.html -+ -+A zlib binding for TCL written by Andreas Kupries -+is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html -+ -+An experimental package to read and write files in .zip format, -+written on top of zlib by Gilles Vollant , is -+available at http://www.winimage.com/zLibDll/unzip.html -+and also in the contrib/minizip directory of zlib. -+ -+ -+Notes for some targets: -+ -+- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc -+ and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL -+ The zlib DLL support was initially done by Alessandro Iacopetti and is -+ now maintained by Gilles Vollant . Check the zlib DLL -+ home page at http://www.winimage.com/zLibDll -+ -+ From Visual Basic, you can call the DLL functions which do not take -+ a structure as argument: compress, uncompress and all gz* functions. -+ See contrib/visual-basic.txt for more information, or get -+ http://www.tcfb.com/dowseware/cmp-z-it.zip -+ -+- For 64-bit Irix, deflate.c must be compiled without any optimization. -+ With -O, one libpng test fails. The test works in 32 bit mode (with -+ the -n32 compiler flag). The compiler bug has been reported to SGI. -+ -+- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 -+ it works when compiled with cc. -+ -+- on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 -+ is necessary to get gzprintf working correctly. This is done by configure. -+ -+- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works -+ with other compilers. Use "make test" to check your compiler. -+ -+- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. -+ -+- For Turbo C the small model is supported only with reduced performance to -+ avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 -+ -+- For PalmOs, see http://www.cs.uit.no/~perm/PASTA/pilot/software.html -+ Per Harald Myrvang -+ -+ -+Acknowledgments: -+ -+ The deflate format used by zlib was defined by Phil Katz. The deflate -+ and zlib specifications were written by L. Peter Deutsch. Thanks to all the -+ people who reported problems and suggested various improvements in zlib; -+ they are too numerous to cite here. -+ -+Copyright notice: -+ -+ (C) 1995-2002 Jean-loup Gailly and Mark Adler -+ -+ This software is provided 'as-is', without any express or implied -+ warranty. In no event will the authors be held liable for any damages -+ arising from the use of this software. -+ -+ Permission is granted to anyone to use this software for any purpose, -+ including commercial applications, and to alter it and redistribute it -+ freely, subject to the following restrictions: -+ -+ 1. The origin of this software must not be misrepresented; you must not -+ claim that you wrote the original software. If you use this software -+ in a product, an acknowledgment in the product documentation would be -+ appreciated but is not required. -+ 2. Altered source versions must be plainly marked as such, and must not be -+ misrepresented as being the original software. -+ 3. This notice may not be removed or altered from any source distribution. -+ -+ Jean-loup Gailly Mark Adler -+ jloup@gzip.org madler@alumni.caltech.edu -+ -+If you use the zlib library in a product, we would appreciate *not* -+receiving lengthy legal documents to sign. The sources are provided -+for free but without warranty of any kind. The library has been -+entirely written by Jean-loup Gailly and Mark Adler; it does not -+include third-party code. -+ -+If you redistribute modified sources, we would appreciate that you include -+in the file ChangeLog history information documenting your changes. ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/README.freeswan Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,13 @@ -+The only changes made to these files for use in FreeS/WAN are: -+ -+ - In zconf.h, macros are defined to prefix global symbols with "ipcomp_" -+ (or "_ipcomp"), when compiled with -DIPCOMP_PREFIX. -+ - The copyright strings are defined local (static) -+ -+ The above changes are made to avoid name collisions with ppp_deflate -+ and ext2compr. -+ -+ - Files not needed for FreeS/WAN have been removed -+ -+ See the "README" file for information about where to obtain the complete -+ zlib package. ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/adler32.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,49 @@ -+/* adler32.c -- compute the Adler-32 checksum of a data stream -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* @(#) $Id$ */ -+ -+#include -+#include "zconf.h" -+ -+#define BASE 65521L /* largest prime smaller than 65536 */ -+#define NMAX 5552 -+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ -+ -+#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} -+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); -+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); -+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); -+#define DO16(buf) DO8(buf,0); DO8(buf,8); -+ -+/* ========================================================================= */ -+uLong ZEXPORT adler32(adler, buf, len) -+ uLong adler; -+ const Bytef *buf; -+ uInt len; -+{ -+ unsigned long s1 = adler & 0xffff; -+ unsigned long s2 = (adler >> 16) & 0xffff; -+ int k; -+ -+ if (buf == Z_NULL) return 1L; -+ -+ while (len > 0) { -+ k = len < NMAX ? len : NMAX; -+ len -= k; -+ while (k >= 16) { -+ DO16(buf); -+ buf += 16; -+ k -= 16; -+ } -+ if (k != 0) do { -+ s1 += *buf++; -+ s2 += s1; -+ } while (--k); -+ s1 %= BASE; -+ s2 %= BASE; -+ } -+ return (s2 << 16) | s1; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/deflate.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1351 @@ -+/* deflate.c -- compress data using the deflation algorithm -+ * Copyright (C) 1995-2002 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* -+ * ALGORITHM -+ * -+ * The "deflation" process depends on being able to identify portions -+ * of the input text which are identical to earlier input (within a -+ * sliding window trailing behind the input currently being processed). -+ * -+ * The most straightforward technique turns out to be the fastest for -+ * most input files: try all possible matches and select the longest. -+ * The key feature of this algorithm is that insertions into the string -+ * dictionary are very simple and thus fast, and deletions are avoided -+ * completely. Insertions are performed at each input character, whereas -+ * string matches are performed only when the previous match ends. So it -+ * is preferable to spend more time in matches to allow very fast string -+ * insertions and avoid deletions. The matching algorithm for small -+ * strings is inspired from that of Rabin & Karp. A brute force approach -+ * is used to find longer strings when a small match has been found. -+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze -+ * (by Leonid Broukhis). -+ * A previous version of this file used a more sophisticated algorithm -+ * (by Fiala and Greene) which is guaranteed to run in linear amortized -+ * time, but has a larger average cost, uses more memory and is patented. -+ * However the F&G algorithm may be faster for some highly redundant -+ * files if the parameter max_chain_length (described below) is too large. -+ * -+ * ACKNOWLEDGEMENTS -+ * -+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and -+ * I found it in 'freeze' written by Leonid Broukhis. -+ * Thanks to many people for bug reports and testing. -+ * -+ * REFERENCES -+ * -+ * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". -+ * Available in ftp://ds.internic.net/rfc/rfc1951.txt -+ * -+ * A description of the Rabin and Karp algorithm is given in the book -+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. -+ * -+ * Fiala,E.R., and Greene,D.H. -+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 -+ * -+ */ -+ -+/* @(#) $Id$ */ -+ -+#include "deflate.h" -+ -+local const char deflate_copyright[] = -+ " deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly "; -+/* -+ If you use the zlib library in a product, an acknowledgment is welcome -+ in the documentation of your product. If for some reason you cannot -+ include such an acknowledgment, I would appreciate that you keep this -+ copyright string in the executable of your product. -+ */ -+ -+/* =========================================================================== -+ * Function prototypes. -+ */ -+typedef enum { -+ need_more, /* block not completed, need more input or more output */ -+ block_done, /* block flush performed */ -+ finish_started, /* finish started, need only more output at next deflate */ -+ finish_done /* finish done, accept no more input or output */ -+} block_state; -+ -+typedef block_state (*compress_func) OF((deflate_state *s, int flush)); -+/* Compression function. Returns the block state after the call. */ -+ -+local void fill_window OF((deflate_state *s)); -+local block_state deflate_stored OF((deflate_state *s, int flush)); -+local block_state deflate_fast OF((deflate_state *s, int flush)); -+local block_state deflate_slow OF((deflate_state *s, int flush)); -+local void lm_init OF((deflate_state *s)); -+local void putShortMSB OF((deflate_state *s, uInt b)); -+local void flush_pending OF((z_streamp strm)); -+local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); -+#ifdef ASMV -+ void match_init OF((void)); /* asm code initialization */ -+ uInt longest_match OF((deflate_state *s, IPos cur_match)); -+#else -+local uInt longest_match OF((deflate_state *s, IPos cur_match)); -+#endif -+ -+#ifdef DEBUG -+local void check_match OF((deflate_state *s, IPos start, IPos match, -+ int length)); -+#endif -+ -+/* =========================================================================== -+ * Local data -+ */ -+ -+#define NIL 0 -+/* Tail of hash chains */ -+ -+#ifndef TOO_FAR -+# define TOO_FAR 4096 -+#endif -+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ -+ -+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -+/* Minimum amount of lookahead, except at the end of the input file. -+ * See deflate.c for comments about the MIN_MATCH+1. -+ */ -+ -+/* Values for max_lazy_match, good_match and max_chain_length, depending on -+ * the desired pack level (0..9). The values given below have been tuned to -+ * exclude worst case performance for pathological files. Better values may be -+ * found for specific files. -+ */ -+typedef struct config_s { -+ ush good_length; /* reduce lazy search above this match length */ -+ ush max_lazy; /* do not perform lazy search above this match length */ -+ ush nice_length; /* quit search above this match length */ -+ ush max_chain; -+ compress_func func; -+} config; -+ -+local const config configuration_table[10] = { -+/* good lazy nice chain */ -+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -+/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ -+/* 2 */ {4, 5, 16, 8, deflate_fast}, -+/* 3 */ {4, 6, 32, 32, deflate_fast}, -+ -+/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ -+/* 5 */ {8, 16, 32, 32, deflate_slow}, -+/* 6 */ {8, 16, 128, 128, deflate_slow}, -+/* 7 */ {8, 32, 128, 256, deflate_slow}, -+/* 8 */ {32, 128, 258, 1024, deflate_slow}, -+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ -+ -+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 -+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different -+ * meaning. -+ */ -+ -+#define EQUAL 0 -+/* result of memcmp for equal strings */ -+ -+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ -+ -+/* =========================================================================== -+ * Update a hash value with the given input byte -+ * IN assertion: all calls to to UPDATE_HASH are made with consecutive -+ * input characters, so that a running hash key can be computed from the -+ * previous key instead of complete recalculation each time. -+ */ -+#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) -+ -+ -+/* =========================================================================== -+ * Insert string str in the dictionary and set match_head to the previous head -+ * of the hash chain (the most recent string with same hash key). Return -+ * the previous length of the hash chain. -+ * If this file is compiled with -DFASTEST, the compression level is forced -+ * to 1, and no hash chains are maintained. -+ * IN assertion: all calls to to INSERT_STRING are made with consecutive -+ * input characters and the first MIN_MATCH bytes of str are valid -+ * (except for the last MIN_MATCH-1 bytes of the input file). -+ */ -+#ifdef FASTEST -+#define INSERT_STRING(s, str, match_head) \ -+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ -+ match_head = s->head[s->ins_h], \ -+ s->head[s->ins_h] = (Pos)(str)) -+#else -+#define INSERT_STRING(s, str, match_head) \ -+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ -+ s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ -+ s->head[s->ins_h] = (Pos)(str)) -+#endif -+ -+/* =========================================================================== -+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems). -+ * prev[] will be initialized on the fly. -+ */ -+#define CLEAR_HASH(s) \ -+ s->head[s->hash_size-1] = NIL; \ -+ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); -+ -+/* ========================================================================= */ -+int ZEXPORT deflateInit_(strm, level, version, stream_size) -+ z_streamp strm; -+ int level; -+ const char *version; -+ int stream_size; -+{ -+ return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, -+ Z_DEFAULT_STRATEGY, version, stream_size); -+ /* To do: ignore strm->next_in if we use it as window */ -+} -+ -+/* ========================================================================= */ -+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, -+ version, stream_size) -+ z_streamp strm; -+ int level; -+ int method; -+ int windowBits; -+ int memLevel; -+ int strategy; -+ const char *version; -+ int stream_size; -+{ -+ deflate_state *s; -+ int noheader = 0; -+ static const char* my_version = ZLIB_VERSION; -+ -+ ushf *overlay; -+ /* We overlay pending_buf and d_buf+l_buf. This works since the average -+ * output size for (length,distance) codes is <= 24 bits. -+ */ -+ -+ if (version == Z_NULL || version[0] != my_version[0] || -+ stream_size != sizeof(z_stream)) { -+ return Z_VERSION_ERROR; -+ } -+ if (strm == Z_NULL) return Z_STREAM_ERROR; -+ -+ strm->msg = Z_NULL; -+ if (strm->zalloc == Z_NULL) { -+ return Z_STREAM_ERROR; -+/* strm->zalloc = zcalloc; -+ strm->opaque = (voidpf)0;*/ -+ } -+ if (strm->zfree == Z_NULL) return Z_STREAM_ERROR; /* strm->zfree = zcfree; */ -+ -+ if (level == Z_DEFAULT_COMPRESSION) level = 6; -+#ifdef FASTEST -+ level = 1; -+#endif -+ -+ if (windowBits < 0) { /* undocumented feature: suppress zlib header */ -+ noheader = 1; -+ windowBits = -windowBits; -+ } -+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || -+ windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || -+ strategy < 0 || strategy > Z_HUFFMAN_ONLY) { -+ return Z_STREAM_ERROR; -+ } -+ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); -+ if (s == Z_NULL) return Z_MEM_ERROR; -+ strm->state = (struct internal_state FAR *)s; -+ s->strm = strm; -+ -+ s->noheader = noheader; -+ s->w_bits = windowBits; -+ s->w_size = 1 << s->w_bits; -+ s->w_mask = s->w_size - 1; -+ -+ s->hash_bits = memLevel + 7; -+ s->hash_size = 1 << s->hash_bits; -+ s->hash_mask = s->hash_size - 1; -+ s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); -+ -+ s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); -+ s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); -+ s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); -+ -+ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ -+ -+ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); -+ s->pending_buf = (uchf *) overlay; -+ s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); -+ -+ if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || -+ s->pending_buf == Z_NULL) { -+ strm->msg = ERR_MSG(Z_MEM_ERROR); -+ deflateEnd (strm); -+ return Z_MEM_ERROR; -+ } -+ s->d_buf = overlay + s->lit_bufsize/sizeof(ush); -+ s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; -+ -+ s->level = level; -+ s->strategy = strategy; -+ s->method = (Byte)method; -+ -+ return deflateReset(strm); -+} -+ -+/* ========================================================================= */ -+int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) -+ z_streamp strm; -+ const Bytef *dictionary; -+ uInt dictLength; -+{ -+ deflate_state *s; -+ uInt length = dictLength; -+ uInt n; -+ IPos hash_head = 0; -+ -+ if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || -+ strm->state->status != INIT_STATE) return Z_STREAM_ERROR; -+ -+ s = strm->state; -+ strm->adler = adler32(strm->adler, dictionary, dictLength); -+ -+ if (length < MIN_MATCH) return Z_OK; -+ if (length > MAX_DIST(s)) { -+ length = MAX_DIST(s); -+#ifndef USE_DICT_HEAD -+ dictionary += dictLength - length; /* use the tail of the dictionary */ -+#endif -+ } -+ zmemcpy(s->window, dictionary, length); -+ s->strstart = length; -+ s->block_start = (long)length; -+ -+ /* Insert all strings in the hash table (except for the last two bytes). -+ * s->lookahead stays null, so s->ins_h will be recomputed at the next -+ * call of fill_window. -+ */ -+ s->ins_h = s->window[0]; -+ UPDATE_HASH(s, s->ins_h, s->window[1]); -+ for (n = 0; n <= length - MIN_MATCH; n++) { -+ INSERT_STRING(s, n, hash_head); -+ } -+ if (hash_head) hash_head = 0; /* to make compiler happy */ -+ return Z_OK; -+} -+ -+/* ========================================================================= */ -+int ZEXPORT deflateReset (strm) -+ z_streamp strm; -+{ -+ deflate_state *s; -+ -+ if (strm == Z_NULL || strm->state == Z_NULL || -+ strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; -+ -+ strm->total_in = strm->total_out = 0; -+ strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ -+ strm->data_type = Z_UNKNOWN; -+ -+ s = (deflate_state *)strm->state; -+ s->pending = 0; -+ s->pending_out = s->pending_buf; -+ -+ if (s->noheader < 0) { -+ s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ -+ } -+ s->status = s->noheader ? BUSY_STATE : INIT_STATE; -+ strm->adler = 1; -+ s->last_flush = Z_NO_FLUSH; -+ -+ _tr_init(s); -+ lm_init(s); -+ -+ return Z_OK; -+} -+ -+/* ========================================================================= */ -+int ZEXPORT deflateParams(strm, level, strategy) -+ z_streamp strm; -+ int level; -+ int strategy; -+{ -+ deflate_state *s; -+ compress_func func; -+ int err = Z_OK; -+ -+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; -+ s = strm->state; -+ -+ if (level == Z_DEFAULT_COMPRESSION) { -+ level = 6; -+ } -+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { -+ return Z_STREAM_ERROR; -+ } -+ func = configuration_table[s->level].func; -+ -+ if (func != configuration_table[level].func && strm->total_in != 0) { -+ /* Flush the last buffer: */ -+ err = deflate(strm, Z_PARTIAL_FLUSH); -+ } -+ if (s->level != level) { -+ s->level = level; -+ s->max_lazy_match = configuration_table[level].max_lazy; -+ s->good_match = configuration_table[level].good_length; -+ s->nice_match = configuration_table[level].nice_length; -+ s->max_chain_length = configuration_table[level].max_chain; -+ } -+ s->strategy = strategy; -+ return err; -+} -+ -+/* ========================================================================= -+ * Put a short in the pending buffer. The 16-bit value is put in MSB order. -+ * IN assertion: the stream state is correct and there is enough room in -+ * pending_buf. -+ */ -+local void putShortMSB (s, b) -+ deflate_state *s; -+ uInt b; -+{ -+ put_byte(s, (Byte)(b >> 8)); -+ put_byte(s, (Byte)(b & 0xff)); -+} -+ -+/* ========================================================================= -+ * Flush as much pending output as possible. All deflate() output goes -+ * through this function so some applications may wish to modify it -+ * to avoid allocating a large strm->next_out buffer and copying into it. -+ * (See also read_buf()). -+ */ -+local void flush_pending(strm) -+ z_streamp strm; -+{ -+ unsigned len = strm->state->pending; -+ -+ if (len > strm->avail_out) len = strm->avail_out; -+ if (len == 0) return; -+ -+ zmemcpy(strm->next_out, strm->state->pending_out, len); -+ strm->next_out += len; -+ strm->state->pending_out += len; -+ strm->total_out += len; -+ strm->avail_out -= len; -+ strm->state->pending -= len; -+ if (strm->state->pending == 0) { -+ strm->state->pending_out = strm->state->pending_buf; -+ } -+} -+ -+/* ========================================================================= */ -+int ZEXPORT deflate (strm, flush) -+ z_streamp strm; -+ int flush; -+{ -+ int old_flush; /* value of flush param for previous deflate call */ -+ deflate_state *s; -+ -+ if (strm == Z_NULL || strm->state == Z_NULL || -+ flush > Z_FINISH || flush < 0) { -+ return Z_STREAM_ERROR; -+ } -+ s = strm->state; -+ -+ if (strm->next_out == Z_NULL || -+ (strm->next_in == Z_NULL && strm->avail_in != 0) || -+ (s->status == FINISH_STATE && flush != Z_FINISH)) { -+ ERR_RETURN(strm, Z_STREAM_ERROR); -+ } -+ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); -+ -+ s->strm = strm; /* just in case */ -+ old_flush = s->last_flush; -+ s->last_flush = flush; -+ -+ /* Write the zlib header */ -+ if (s->status == INIT_STATE) { -+ -+ uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; -+ uInt level_flags = (s->level-1) >> 1; -+ -+ if (level_flags > 3) level_flags = 3; -+ header |= (level_flags << 6); -+ if (s->strstart != 0) header |= PRESET_DICT; -+ header += 31 - (header % 31); -+ -+ s->status = BUSY_STATE; -+ putShortMSB(s, header); -+ -+ /* Save the adler32 of the preset dictionary: */ -+ if (s->strstart != 0) { -+ putShortMSB(s, (uInt)(strm->adler >> 16)); -+ putShortMSB(s, (uInt)(strm->adler & 0xffff)); -+ } -+ strm->adler = 1L; -+ } -+ -+ /* Flush as much pending output as possible */ -+ if (s->pending != 0) { -+ flush_pending(strm); -+ if (strm->avail_out == 0) { -+ /* Since avail_out is 0, deflate will be called again with -+ * more output space, but possibly with both pending and -+ * avail_in equal to zero. There won't be anything to do, -+ * but this is not an error situation so make sure we -+ * return OK instead of BUF_ERROR at next call of deflate: -+ */ -+ s->last_flush = -1; -+ return Z_OK; -+ } -+ -+ /* Make sure there is something to do and avoid duplicate consecutive -+ * flushes. For repeated and useless calls with Z_FINISH, we keep -+ * returning Z_STREAM_END instead of Z_BUFF_ERROR. -+ */ -+ } else if (strm->avail_in == 0 && flush <= old_flush && -+ flush != Z_FINISH) { -+ ERR_RETURN(strm, Z_BUF_ERROR); -+ } -+ -+ /* User must not provide more input after the first FINISH: */ -+ if (s->status == FINISH_STATE && strm->avail_in != 0) { -+ ERR_RETURN(strm, Z_BUF_ERROR); -+ } -+ -+ /* Start a new block or continue the current one. -+ */ -+ if (strm->avail_in != 0 || s->lookahead != 0 || -+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { -+ block_state bstate; -+ -+ bstate = (*(configuration_table[s->level].func))(s, flush); -+ -+ if (bstate == finish_started || bstate == finish_done) { -+ s->status = FINISH_STATE; -+ } -+ if (bstate == need_more || bstate == finish_started) { -+ if (strm->avail_out == 0) { -+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ -+ } -+ return Z_OK; -+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call -+ * of deflate should use the same flush parameter to make sure -+ * that the flush is complete. So we don't have to output an -+ * empty block here, this will be done at next call. This also -+ * ensures that for a very small output buffer, we emit at most -+ * one empty block. -+ */ -+ } -+ if (bstate == block_done) { -+ if (flush == Z_PARTIAL_FLUSH) { -+ _tr_align(s); -+ } else { /* FULL_FLUSH or SYNC_FLUSH */ -+ _tr_stored_block(s, (char*)0, 0L, 0); -+ /* For a full flush, this empty block will be recognized -+ * as a special marker by inflate_sync(). -+ */ -+ if (flush == Z_FULL_FLUSH) { -+ CLEAR_HASH(s); /* forget history */ -+ } -+ } -+ flush_pending(strm); -+ if (strm->avail_out == 0) { -+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ -+ return Z_OK; -+ } -+ } -+ } -+ Assert(strm->avail_out > 0, "bug2"); -+ -+ if (flush != Z_FINISH) return Z_OK; -+ if (s->noheader) return Z_STREAM_END; -+ -+ /* Write the zlib trailer (adler32) */ -+ putShortMSB(s, (uInt)(strm->adler >> 16)); -+ putShortMSB(s, (uInt)(strm->adler & 0xffff)); -+ flush_pending(strm); -+ /* If avail_out is zero, the application will call deflate again -+ * to flush the rest. -+ */ -+ s->noheader = -1; /* write the trailer only once! */ -+ return s->pending != 0 ? Z_OK : Z_STREAM_END; -+} -+ -+/* ========================================================================= */ -+int ZEXPORT deflateEnd (strm) -+ z_streamp strm; -+{ -+ int status; -+ -+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; -+ -+ status = strm->state->status; -+ if (status != INIT_STATE && status != BUSY_STATE && -+ status != FINISH_STATE) { -+ return Z_STREAM_ERROR; -+ } -+ -+ /* Deallocate in reverse order of allocations: */ -+ TRY_FREE(strm, strm->state->pending_buf); -+ TRY_FREE(strm, strm->state->head); -+ TRY_FREE(strm, strm->state->prev); -+ TRY_FREE(strm, strm->state->window); -+ -+ ZFREE(strm, strm->state); -+ strm->state = Z_NULL; -+ -+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; -+} -+ -+/* ========================================================================= -+ * Copy the source state to the destination state. -+ * To simplify the source, this is not supported for 16-bit MSDOS (which -+ * doesn't have enough memory anyway to duplicate compression states). -+ */ -+int ZEXPORT deflateCopy (dest, source) -+ z_streamp dest; -+ z_streamp source; -+{ -+#ifdef MAXSEG_64K -+ return Z_STREAM_ERROR; -+#else -+ deflate_state *ds; -+ deflate_state *ss; -+ ushf *overlay; -+ -+ -+ if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { -+ return Z_STREAM_ERROR; -+ } -+ -+ ss = source->state; -+ -+ *dest = *source; -+ -+ ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); -+ if (ds == Z_NULL) return Z_MEM_ERROR; -+ dest->state = (struct internal_state FAR *) ds; -+ *ds = *ss; -+ ds->strm = dest; -+ -+ ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); -+ ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); -+ ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); -+ overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); -+ ds->pending_buf = (uchf *) overlay; -+ -+ if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || -+ ds->pending_buf == Z_NULL) { -+ deflateEnd (dest); -+ return Z_MEM_ERROR; -+ } -+ /* following zmemcpy do not work for 16-bit MSDOS */ -+ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); -+ zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); -+ zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); -+ zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); -+ -+ ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); -+ ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); -+ ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; -+ -+ ds->l_desc.dyn_tree = ds->dyn_ltree; -+ ds->d_desc.dyn_tree = ds->dyn_dtree; -+ ds->bl_desc.dyn_tree = ds->bl_tree; -+ -+ return Z_OK; -+#endif -+} -+ -+/* =========================================================================== -+ * Read a new buffer from the current input stream, update the adler32 -+ * and total number of bytes read. All deflate() input goes through -+ * this function so some applications may wish to modify it to avoid -+ * allocating a large strm->next_in buffer and copying from it. -+ * (See also flush_pending()). -+ */ -+local int read_buf(strm, buf, size) -+ z_streamp strm; -+ Bytef *buf; -+ unsigned size; -+{ -+ unsigned len = strm->avail_in; -+ -+ if (len > size) len = size; -+ if (len == 0) return 0; -+ -+ strm->avail_in -= len; -+ -+ if (!strm->state->noheader) { -+ strm->adler = adler32(strm->adler, strm->next_in, len); -+ } -+ zmemcpy(buf, strm->next_in, len); -+ strm->next_in += len; -+ strm->total_in += len; -+ -+ return (int)len; -+} -+ -+/* =========================================================================== -+ * Initialize the "longest match" routines for a new zlib stream -+ */ -+local void lm_init (s) -+ deflate_state *s; -+{ -+ s->window_size = (ulg)2L*s->w_size; -+ -+ CLEAR_HASH(s); -+ -+ /* Set the default configuration parameters: -+ */ -+ s->max_lazy_match = configuration_table[s->level].max_lazy; -+ s->good_match = configuration_table[s->level].good_length; -+ s->nice_match = configuration_table[s->level].nice_length; -+ s->max_chain_length = configuration_table[s->level].max_chain; -+ -+ s->strstart = 0; -+ s->block_start = 0L; -+ s->lookahead = 0; -+ s->match_length = s->prev_length = MIN_MATCH-1; -+ s->match_available = 0; -+ s->ins_h = 0; -+#ifdef ASMV -+ match_init(); /* initialize the asm code */ -+#endif -+} -+ -+/* =========================================================================== -+ * Set match_start to the longest match starting at the given string and -+ * return its length. Matches shorter or equal to prev_length are discarded, -+ * in which case the result is equal to prev_length and match_start is -+ * garbage. -+ * IN assertions: cur_match is the head of the hash chain for the current -+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 -+ * OUT assertion: the match length is not greater than s->lookahead. -+ */ -+#ifndef ASMV -+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or -+ * match.S. The code will be functionally equivalent. -+ */ -+#ifndef FASTEST -+local uInt longest_match(s, cur_match) -+ deflate_state *s; -+ IPos cur_match; /* current match */ -+{ -+ unsigned chain_length = s->max_chain_length;/* max hash chain length */ -+ register Bytef *scan = s->window + s->strstart; /* current string */ -+ register Bytef *match; /* matched string */ -+ register int len; /* length of current match */ -+ int best_len = s->prev_length; /* best match length so far */ -+ int nice_match = s->nice_match; /* stop if match long enough */ -+ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? -+ s->strstart - (IPos)MAX_DIST(s) : NIL; -+ /* Stop when cur_match becomes <= limit. To simplify the code, -+ * we prevent matches with the string of window index 0. -+ */ -+ Posf *prev = s->prev; -+ uInt wmask = s->w_mask; -+ -+#ifdef UNALIGNED_OK -+ /* Compare two bytes at a time. Note: this is not always beneficial. -+ * Try with and without -DUNALIGNED_OK to check. -+ */ -+ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; -+ register ush scan_start = *(ushf*)scan; -+ register ush scan_end = *(ushf*)(scan+best_len-1); -+#else -+ register Bytef *strend = s->window + s->strstart + MAX_MATCH; -+ register Byte scan_end1 = scan[best_len-1]; -+ register Byte scan_end = scan[best_len]; -+#endif -+ -+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. -+ * It is easy to get rid of this optimization if necessary. -+ */ -+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); -+ -+ /* Do not waste too much time if we already have a good match: */ -+ if (s->prev_length >= s->good_match) { -+ chain_length >>= 2; -+ } -+ /* Do not look for matches beyond the end of the input. This is necessary -+ * to make deflate deterministic. -+ */ -+ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; -+ -+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); -+ -+ do { -+ Assert(cur_match < s->strstart, "no future"); -+ match = s->window + cur_match; -+ -+ /* Skip to next match if the match length cannot increase -+ * or if the match length is less than 2: -+ */ -+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) -+ /* This code assumes sizeof(unsigned short) == 2. Do not use -+ * UNALIGNED_OK if your compiler uses a different size. -+ */ -+ if (*(ushf*)(match+best_len-1) != scan_end || -+ *(ushf*)match != scan_start) continue; -+ -+ /* It is not necessary to compare scan[2] and match[2] since they are -+ * always equal when the other bytes match, given that the hash keys -+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at -+ * strstart+3, +5, ... up to strstart+257. We check for insufficient -+ * lookahead only every 4th comparison; the 128th check will be made -+ * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is -+ * necessary to put more guard bytes at the end of the window, or -+ * to check more often for insufficient lookahead. -+ */ -+ Assert(scan[2] == match[2], "scan[2]?"); -+ scan++, match++; -+ do { -+ } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && -+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) && -+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) && -+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) && -+ scan < strend); -+ /* The funny "do {}" generates better code on most compilers */ -+ -+ /* Here, scan <= window+strstart+257 */ -+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); -+ if (*scan == *match) scan++; -+ -+ len = (MAX_MATCH - 1) - (int)(strend-scan); -+ scan = strend - (MAX_MATCH-1); -+ -+#else /* UNALIGNED_OK */ -+ -+ if (match[best_len] != scan_end || -+ match[best_len-1] != scan_end1 || -+ *match != *scan || -+ *++match != scan[1]) continue; -+ -+ /* The check at best_len-1 can be removed because it will be made -+ * again later. (This heuristic is not always a win.) -+ * It is not necessary to compare scan[2] and match[2] since they -+ * are always equal when the other bytes match, given that -+ * the hash keys are equal and that HASH_BITS >= 8. -+ */ -+ scan += 2, match++; -+ Assert(*scan == *match, "match[2]?"); -+ -+ /* We check for insufficient lookahead only every 8th comparison; -+ * the 256th check will be made at strstart+258. -+ */ -+ do { -+ } while (*++scan == *++match && *++scan == *++match && -+ *++scan == *++match && *++scan == *++match && -+ *++scan == *++match && *++scan == *++match && -+ *++scan == *++match && *++scan == *++match && -+ scan < strend); -+ -+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); -+ -+ len = MAX_MATCH - (int)(strend - scan); -+ scan = strend - MAX_MATCH; -+ -+#endif /* UNALIGNED_OK */ -+ -+ if (len > best_len) { -+ s->match_start = cur_match; -+ best_len = len; -+ if (len >= nice_match) break; -+#ifdef UNALIGNED_OK -+ scan_end = *(ushf*)(scan+best_len-1); -+#else -+ scan_end1 = scan[best_len-1]; -+ scan_end = scan[best_len]; -+#endif -+ } -+ } while ((cur_match = prev[cur_match & wmask]) > limit -+ && --chain_length != 0); -+ -+ if ((uInt)best_len <= s->lookahead) return (uInt)best_len; -+ return s->lookahead; -+} -+ -+#else /* FASTEST */ -+/* --------------------------------------------------------------------------- -+ * Optimized version for level == 1 only -+ */ -+local uInt longest_match(s, cur_match) -+ deflate_state *s; -+ IPos cur_match; /* current match */ -+{ -+ register Bytef *scan = s->window + s->strstart; /* current string */ -+ register Bytef *match; /* matched string */ -+ register int len; /* length of current match */ -+ register Bytef *strend = s->window + s->strstart + MAX_MATCH; -+ -+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. -+ * It is easy to get rid of this optimization if necessary. -+ */ -+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); -+ -+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); -+ -+ Assert(cur_match < s->strstart, "no future"); -+ -+ match = s->window + cur_match; -+ -+ /* Return failure if the match length is less than 2: -+ */ -+ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; -+ -+ /* The check at best_len-1 can be removed because it will be made -+ * again later. (This heuristic is not always a win.) -+ * It is not necessary to compare scan[2] and match[2] since they -+ * are always equal when the other bytes match, given that -+ * the hash keys are equal and that HASH_BITS >= 8. -+ */ -+ scan += 2, match += 2; -+ Assert(*scan == *match, "match[2]?"); -+ -+ /* We check for insufficient lookahead only every 8th comparison; -+ * the 256th check will be made at strstart+258. -+ */ -+ do { -+ } while (*++scan == *++match && *++scan == *++match && -+ *++scan == *++match && *++scan == *++match && -+ *++scan == *++match && *++scan == *++match && -+ *++scan == *++match && *++scan == *++match && -+ scan < strend); -+ -+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); -+ -+ len = MAX_MATCH - (int)(strend - scan); -+ -+ if (len < MIN_MATCH) return MIN_MATCH - 1; -+ -+ s->match_start = cur_match; -+ return len <= s->lookahead ? len : s->lookahead; -+} -+#endif /* FASTEST */ -+#endif /* ASMV */ -+ -+#ifdef DEBUG -+/* =========================================================================== -+ * Check that the match at match_start is indeed a match. -+ */ -+local void check_match(s, start, match, length) -+ deflate_state *s; -+ IPos start, match; -+ int length; -+{ -+ /* check that the match is indeed a match */ -+ if (zmemcmp(s->window + match, -+ s->window + start, length) != EQUAL) { -+ fprintf(stderr, " start %u, match %u, length %d\n", -+ start, match, length); -+ do { -+ fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); -+ } while (--length != 0); -+ z_error("invalid match"); -+ } -+ if (z_verbose > 1) { -+ fprintf(stderr,"\\[%d,%d]", start-match, length); -+ do { putc(s->window[start++], stderr); } while (--length != 0); -+ } -+} -+#else -+# define check_match(s, start, match, length) -+#endif -+ -+/* =========================================================================== -+ * Fill the window when the lookahead becomes insufficient. -+ * Updates strstart and lookahead. -+ * -+ * IN assertion: lookahead < MIN_LOOKAHEAD -+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD -+ * At least one byte has been read, or avail_in == 0; reads are -+ * performed for at least two bytes (required for the zip translate_eol -+ * option -- not supported here). -+ */ -+local void fill_window(s) -+ deflate_state *s; -+{ -+ register unsigned n, m; -+ register Posf *p; -+ unsigned more; /* Amount of free space at the end of the window. */ -+ uInt wsize = s->w_size; -+ -+ do { -+ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); -+ -+ /* Deal with !@#$% 64K limit: */ -+ if (more == 0 && s->strstart == 0 && s->lookahead == 0) { -+ more = wsize; -+ -+ } else if (more == (unsigned)(-1)) { -+ /* Very unlikely, but possible on 16 bit machine if strstart == 0 -+ * and lookahead == 1 (input done one byte at time) -+ */ -+ more--; -+ -+ /* If the window is almost full and there is insufficient lookahead, -+ * move the upper half to the lower one to make room in the upper half. -+ */ -+ } else if (s->strstart >= wsize+MAX_DIST(s)) { -+ -+ zmemcpy(s->window, s->window+wsize, (unsigned)wsize); -+ s->match_start -= wsize; -+ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ -+ s->block_start -= (long) wsize; -+ -+ /* Slide the hash table (could be avoided with 32 bit values -+ at the expense of memory usage). We slide even when level == 0 -+ to keep the hash table consistent if we switch back to level > 0 -+ later. (Using level 0 permanently is not an optimal usage of -+ zlib, so we don't care about this pathological case.) -+ */ -+ n = s->hash_size; -+ p = &s->head[n]; -+ do { -+ m = *--p; -+ *p = (Pos)(m >= wsize ? m-wsize : NIL); -+ } while (--n); -+ -+ n = wsize; -+#ifndef FASTEST -+ p = &s->prev[n]; -+ do { -+ m = *--p; -+ *p = (Pos)(m >= wsize ? m-wsize : NIL); -+ /* If n is not on any hash chain, prev[n] is garbage but -+ * its value will never be used. -+ */ -+ } while (--n); -+#endif -+ more += wsize; -+ } -+ if (s->strm->avail_in == 0) return; -+ -+ /* If there was no sliding: -+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && -+ * more == window_size - lookahead - strstart -+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) -+ * => more >= window_size - 2*WSIZE + 2 -+ * In the BIG_MEM or MMAP case (not yet supported), -+ * window_size == input_size + MIN_LOOKAHEAD && -+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. -+ * Otherwise, window_size == 2*WSIZE so more >= 2. -+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2. -+ */ -+ Assert(more >= 2, "more < 2"); -+ -+ n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); -+ s->lookahead += n; -+ -+ /* Initialize the hash value now that we have some input: */ -+ if (s->lookahead >= MIN_MATCH) { -+ s->ins_h = s->window[s->strstart]; -+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -+#if MIN_MATCH != 3 -+ Call UPDATE_HASH() MIN_MATCH-3 more times -+#endif -+ } -+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, -+ * but this is not important since only literal bytes will be emitted. -+ */ -+ -+ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); -+} -+ -+/* =========================================================================== -+ * Flush the current block, with given end-of-file flag. -+ * IN assertion: strstart is set to the end of the current match. -+ */ -+#define FLUSH_BLOCK_ONLY(s, eof) { \ -+ _tr_flush_block(s, (s->block_start >= 0L ? \ -+ (charf *)&s->window[(unsigned)s->block_start] : \ -+ (charf *)Z_NULL), \ -+ (ulg)((long)s->strstart - s->block_start), \ -+ (eof)); \ -+ s->block_start = s->strstart; \ -+ flush_pending(s->strm); \ -+ Tracev((stderr,"[FLUSH]")); \ -+} -+ -+/* Same but force premature exit if necessary. */ -+#define FLUSH_BLOCK(s, eof) { \ -+ FLUSH_BLOCK_ONLY(s, eof); \ -+ if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ -+} -+ -+/* =========================================================================== -+ * Copy without compression as much as possible from the input stream, return -+ * the current block state. -+ * This function does not insert new strings in the dictionary since -+ * uncompressible data is probably not useful. This function is used -+ * only for the level=0 compression option. -+ * NOTE: this function should be optimized to avoid extra copying from -+ * window to pending_buf. -+ */ -+local block_state deflate_stored(s, flush) -+ deflate_state *s; -+ int flush; -+{ -+ /* Stored blocks are limited to 0xffff bytes, pending_buf is limited -+ * to pending_buf_size, and each stored block has a 5 byte header: -+ */ -+ ulg max_block_size = 0xffff; -+ ulg max_start; -+ -+ if (max_block_size > s->pending_buf_size - 5) { -+ max_block_size = s->pending_buf_size - 5; -+ } -+ -+ /* Copy as much as possible from input to output: */ -+ for (;;) { -+ /* Fill the window as much as possible: */ -+ if (s->lookahead <= 1) { -+ -+ Assert(s->strstart < s->w_size+MAX_DIST(s) || -+ s->block_start >= (long)s->w_size, "slide too late"); -+ -+ fill_window(s); -+ if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; -+ -+ if (s->lookahead == 0) break; /* flush the current block */ -+ } -+ Assert(s->block_start >= 0L, "block gone"); -+ -+ s->strstart += s->lookahead; -+ s->lookahead = 0; -+ -+ /* Emit a stored block if pending_buf will be full: */ -+ max_start = s->block_start + max_block_size; -+ if (s->strstart == 0 || (ulg)s->strstart >= max_start) { -+ /* strstart == 0 is possible when wraparound on 16-bit machine */ -+ s->lookahead = (uInt)(s->strstart - max_start); -+ s->strstart = (uInt)max_start; -+ FLUSH_BLOCK(s, 0); -+ } -+ /* Flush if we may have to slide, otherwise block_start may become -+ * negative and the data will be gone: -+ */ -+ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { -+ FLUSH_BLOCK(s, 0); -+ } -+ } -+ FLUSH_BLOCK(s, flush == Z_FINISH); -+ return flush == Z_FINISH ? finish_done : block_done; -+} -+ -+/* =========================================================================== -+ * Compress as much as possible from the input stream, return the current -+ * block state. -+ * This function does not perform lazy evaluation of matches and inserts -+ * new strings in the dictionary only for unmatched strings or for short -+ * matches. It is used only for the fast compression options. -+ */ -+local block_state deflate_fast(s, flush) -+ deflate_state *s; -+ int flush; -+{ -+ IPos hash_head = NIL; /* head of the hash chain */ -+ int bflush; /* set if current block must be flushed */ -+ -+ for (;;) { -+ /* Make sure that we always have enough lookahead, except -+ * at the end of the input file. We need MAX_MATCH bytes -+ * for the next match, plus MIN_MATCH bytes to insert the -+ * string following the next match. -+ */ -+ if (s->lookahead < MIN_LOOKAHEAD) { -+ fill_window(s); -+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { -+ return need_more; -+ } -+ if (s->lookahead == 0) break; /* flush the current block */ -+ } -+ -+ /* Insert the string window[strstart .. strstart+2] in the -+ * dictionary, and set hash_head to the head of the hash chain: -+ */ -+ if (s->lookahead >= MIN_MATCH) { -+ INSERT_STRING(s, s->strstart, hash_head); -+ } -+ -+ /* Find the longest match, discarding those <= prev_length. -+ * At this point we have always match_length < MIN_MATCH -+ */ -+ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { -+ /* To simplify the code, we prevent matches with the string -+ * of window index 0 (in particular we have to avoid a match -+ * of the string with itself at the start of the input file). -+ */ -+ if (s->strategy != Z_HUFFMAN_ONLY) { -+ s->match_length = longest_match (s, hash_head); -+ } -+ /* longest_match() sets match_start */ -+ } -+ if (s->match_length >= MIN_MATCH) { -+ check_match(s, s->strstart, s->match_start, s->match_length); -+ -+ _tr_tally_dist(s, s->strstart - s->match_start, -+ s->match_length - MIN_MATCH, bflush); -+ -+ s->lookahead -= s->match_length; -+ -+ /* Insert new strings in the hash table only if the match length -+ * is not too large. This saves time but degrades compression. -+ */ -+#ifndef FASTEST -+ if (s->match_length <= s->max_insert_length && -+ s->lookahead >= MIN_MATCH) { -+ s->match_length--; /* string at strstart already in hash table */ -+ do { -+ s->strstart++; -+ INSERT_STRING(s, s->strstart, hash_head); -+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are -+ * always MIN_MATCH bytes ahead. -+ */ -+ } while (--s->match_length != 0); -+ s->strstart++; -+ } else -+#endif -+ { -+ s->strstart += s->match_length; -+ s->match_length = 0; -+ s->ins_h = s->window[s->strstart]; -+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -+#if MIN_MATCH != 3 -+ Call UPDATE_HASH() MIN_MATCH-3 more times -+#endif -+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not -+ * matter since it will be recomputed at next deflate call. -+ */ -+ } -+ } else { -+ /* No match, output a literal byte */ -+ Tracevv((stderr,"%c", s->window[s->strstart])); -+ _tr_tally_lit (s, s->window[s->strstart], bflush); -+ s->lookahead--; -+ s->strstart++; -+ } -+ if (bflush) FLUSH_BLOCK(s, 0); -+ } -+ FLUSH_BLOCK(s, flush == Z_FINISH); -+ return flush == Z_FINISH ? finish_done : block_done; -+} -+ -+/* =========================================================================== -+ * Same as above, but achieves better compression. We use a lazy -+ * evaluation for matches: a match is finally adopted only if there is -+ * no better match at the next window position. -+ */ -+local block_state deflate_slow(s, flush) -+ deflate_state *s; -+ int flush; -+{ -+ IPos hash_head = NIL; /* head of hash chain */ -+ int bflush; /* set if current block must be flushed */ -+ -+ /* Process the input block. */ -+ for (;;) { -+ /* Make sure that we always have enough lookahead, except -+ * at the end of the input file. We need MAX_MATCH bytes -+ * for the next match, plus MIN_MATCH bytes to insert the -+ * string following the next match. -+ */ -+ if (s->lookahead < MIN_LOOKAHEAD) { -+ fill_window(s); -+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { -+ return need_more; -+ } -+ if (s->lookahead == 0) break; /* flush the current block */ -+ } -+ -+ /* Insert the string window[strstart .. strstart+2] in the -+ * dictionary, and set hash_head to the head of the hash chain: -+ */ -+ if (s->lookahead >= MIN_MATCH) { -+ INSERT_STRING(s, s->strstart, hash_head); -+ } -+ -+ /* Find the longest match, discarding those <= prev_length. -+ */ -+ s->prev_length = s->match_length, s->prev_match = s->match_start; -+ s->match_length = MIN_MATCH-1; -+ -+ if (hash_head != NIL && s->prev_length < s->max_lazy_match && -+ s->strstart - hash_head <= MAX_DIST(s)) { -+ /* To simplify the code, we prevent matches with the string -+ * of window index 0 (in particular we have to avoid a match -+ * of the string with itself at the start of the input file). -+ */ -+ if (s->strategy != Z_HUFFMAN_ONLY) { -+ s->match_length = longest_match (s, hash_head); -+ } -+ /* longest_match() sets match_start */ -+ -+ if (s->match_length <= 5 && (s->strategy == Z_FILTERED || -+ (s->match_length == MIN_MATCH && -+ s->strstart - s->match_start > TOO_FAR))) { -+ -+ /* If prev_match is also MIN_MATCH, match_start is garbage -+ * but we will ignore the current match anyway. -+ */ -+ s->match_length = MIN_MATCH-1; -+ } -+ } -+ /* If there was a match at the previous step and the current -+ * match is not better, output the previous match: -+ */ -+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { -+ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; -+ /* Do not insert strings in hash table beyond this. */ -+ -+ check_match(s, s->strstart-1, s->prev_match, s->prev_length); -+ -+ _tr_tally_dist(s, s->strstart -1 - s->prev_match, -+ s->prev_length - MIN_MATCH, bflush); -+ -+ /* Insert in hash table all strings up to the end of the match. -+ * strstart-1 and strstart are already inserted. If there is not -+ * enough lookahead, the last two strings are not inserted in -+ * the hash table. -+ */ -+ s->lookahead -= s->prev_length-1; -+ s->prev_length -= 2; -+ do { -+ if (++s->strstart <= max_insert) { -+ INSERT_STRING(s, s->strstart, hash_head); -+ } -+ } while (--s->prev_length != 0); -+ s->match_available = 0; -+ s->match_length = MIN_MATCH-1; -+ s->strstart++; -+ -+ if (bflush) FLUSH_BLOCK(s, 0); -+ -+ } else if (s->match_available) { -+ /* If there was no match at the previous position, output a -+ * single literal. If there was a match but the current match -+ * is longer, truncate the previous match to a single literal. -+ */ -+ Tracevv((stderr,"%c", s->window[s->strstart-1])); -+ _tr_tally_lit(s, s->window[s->strstart-1], bflush); -+ if (bflush) { -+ FLUSH_BLOCK_ONLY(s, 0); -+ } -+ s->strstart++; -+ s->lookahead--; -+ if (s->strm->avail_out == 0) return need_more; -+ } else { -+ /* There is no previous match to compare with, wait for -+ * the next step to decide. -+ */ -+ s->match_available = 1; -+ s->strstart++; -+ s->lookahead--; -+ } -+ } -+ Assert (flush != Z_NO_FLUSH, "no flush?"); -+ if (s->match_available) { -+ Tracevv((stderr,"%c", s->window[s->strstart-1])); -+ _tr_tally_lit(s, s->window[s->strstart-1], bflush); -+ s->match_available = 0; -+ } -+ FLUSH_BLOCK(s, flush == Z_FINISH); -+ return flush == Z_FINISH ? finish_done : block_done; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/deflate.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,318 @@ -+/* deflate.h -- internal compression state -+ * Copyright (C) 1995-2002 Jean-loup Gailly -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+/* @(#) $Id$ */ -+ -+#ifndef _DEFLATE_H -+#define _DEFLATE_H -+ -+#include "zlib/zutil.h" -+ -+/* =========================================================================== -+ * Internal compression state. -+ */ -+ -+#define LENGTH_CODES 29 -+/* number of length codes, not counting the special END_BLOCK code */ -+ -+#define LITERALS 256 -+/* number of literal bytes 0..255 */ -+ -+#define L_CODES (LITERALS+1+LENGTH_CODES) -+/* number of Literal or Length codes, including the END_BLOCK code */ -+ -+#define D_CODES 30 -+/* number of distance codes */ -+ -+#define BL_CODES 19 -+/* number of codes used to transfer the bit lengths */ -+ -+#define HEAP_SIZE (2*L_CODES+1) -+/* maximum heap size */ -+ -+#define MAX_BITS 15 -+/* All codes must not exceed MAX_BITS bits */ -+ -+#define INIT_STATE 42 -+#define BUSY_STATE 113 -+#define FINISH_STATE 666 -+/* Stream status */ -+ -+ -+/* Data structure describing a single value and its code string. */ -+typedef struct ct_data_s { -+ union { -+ ush freq; /* frequency count */ -+ ush code; /* bit string */ -+ } fc; -+ union { -+ ush dad; /* father node in Huffman tree */ -+ ush len; /* length of bit string */ -+ } dl; -+} FAR ct_data; -+ -+#define Freq fc.freq -+#define Code fc.code -+#define Dad dl.dad -+#define Len dl.len -+ -+typedef struct static_tree_desc_s static_tree_desc; -+ -+typedef struct tree_desc_s { -+ ct_data *dyn_tree; /* the dynamic tree */ -+ int max_code; /* largest code with non zero frequency */ -+ static_tree_desc *stat_desc; /* the corresponding static tree */ -+} FAR tree_desc; -+ -+typedef ush Pos; -+typedef Pos FAR Posf; -+typedef unsigned IPos; -+ -+/* A Pos is an index in the character window. We use short instead of int to -+ * save space in the various tables. IPos is used only for parameter passing. -+ */ -+ -+typedef struct internal_state { -+ z_streamp strm; /* pointer back to this zlib stream */ -+ int status; /* as the name implies */ -+ Bytef *pending_buf; /* output still pending */ -+ ulg pending_buf_size; /* size of pending_buf */ -+ Bytef *pending_out; /* next pending byte to output to the stream */ -+ int pending; /* nb of bytes in the pending buffer */ -+ int noheader; /* suppress zlib header and adler32 */ -+ Byte data_type; /* UNKNOWN, BINARY or ASCII */ -+ Byte method; /* STORED (for zip only) or DEFLATED */ -+ int last_flush; /* value of flush param for previous deflate call */ -+ -+ /* used by deflate.c: */ -+ -+ uInt w_size; /* LZ77 window size (32K by default) */ -+ uInt w_bits; /* log2(w_size) (8..16) */ -+ uInt w_mask; /* w_size - 1 */ -+ -+ Bytef *window; -+ /* Sliding window. Input bytes are read into the second half of the window, -+ * and move to the first half later to keep a dictionary of at least wSize -+ * bytes. With this organization, matches are limited to a distance of -+ * wSize-MAX_MATCH bytes, but this ensures that IO is always -+ * performed with a length multiple of the block size. Also, it limits -+ * the window size to 64K, which is quite useful on MSDOS. -+ * To do: use the user input buffer as sliding window. -+ */ -+ -+ ulg window_size; -+ /* Actual size of window: 2*wSize, except when the user input buffer -+ * is directly used as sliding window. -+ */ -+ -+ Posf *prev; -+ /* Link to older string with same hash index. To limit the size of this -+ * array to 64K, this link is maintained only for the last 32K strings. -+ * An index in this array is thus a window index modulo 32K. -+ */ -+ -+ Posf *head; /* Heads of the hash chains or NIL. */ -+ -+ uInt ins_h; /* hash index of string to be inserted */ -+ uInt hash_size; /* number of elements in hash table */ -+ uInt hash_bits; /* log2(hash_size) */ -+ uInt hash_mask; /* hash_size-1 */ -+ -+ uInt hash_shift; -+ /* Number of bits by which ins_h must be shifted at each input -+ * step. It must be such that after MIN_MATCH steps, the oldest -+ * byte no longer takes part in the hash key, that is: -+ * hash_shift * MIN_MATCH >= hash_bits -+ */ -+ -+ long block_start; -+ /* Window position at the beginning of the current output block. Gets -+ * negative when the window is moved backwards. -+ */ -+ -+ uInt match_length; /* length of best match */ -+ IPos prev_match; /* previous match */ -+ int match_available; /* set if previous match exists */ -+ uInt strstart; /* start of string to insert */ -+ uInt match_start; /* start of matching string */ -+ uInt lookahead; /* number of valid bytes ahead in window */ -+ -+ uInt prev_length; -+ /* Length of the best match at previous step. Matches not greater than this -+ * are discarded. This is used in the lazy match evaluation. -+ */ -+ -+ uInt max_chain_length; -+ /* To speed up deflation, hash chains are never searched beyond this -+ * length. A higher limit improves compression ratio but degrades the -+ * speed. -+ */ -+ -+ uInt max_lazy_match; -+ /* Attempt to find a better match only when the current match is strictly -+ * smaller than this value. This mechanism is used only for compression -+ * levels >= 4. -+ */ -+# define max_insert_length max_lazy_match -+ /* Insert new strings in the hash table only if the match length is not -+ * greater than this length. This saves time but degrades compression. -+ * max_insert_length is used only for compression levels <= 3. -+ */ -+ -+ int level; /* compression level (1..9) */ -+ int strategy; /* favor or force Huffman coding*/ -+ -+ uInt good_match; -+ /* Use a faster search when the previous match is longer than this */ -+ -+ int nice_match; /* Stop searching when current match exceeds this */ -+ -+ /* used by trees.c: */ -+ /* Didn't use ct_data typedef below to supress compiler warning */ -+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ -+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ -+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ -+ -+ struct tree_desc_s l_desc; /* desc. for literal tree */ -+ struct tree_desc_s d_desc; /* desc. for distance tree */ -+ struct tree_desc_s bl_desc; /* desc. for bit length tree */ -+ -+ ush bl_count[MAX_BITS+1]; -+ /* number of codes at each bit length for an optimal tree */ -+ -+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ -+ int heap_len; /* number of elements in the heap */ -+ int heap_max; /* element of largest frequency */ -+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. -+ * The same heap array is used to build all trees. -+ */ -+ -+ uch depth[2*L_CODES+1]; -+ /* Depth of each subtree used as tie breaker for trees of equal frequency -+ */ -+ -+ uchf *l_buf; /* buffer for literals or lengths */ -+ -+ uInt lit_bufsize; -+ /* Size of match buffer for literals/lengths. There are 4 reasons for -+ * limiting lit_bufsize to 64K: -+ * - frequencies can be kept in 16 bit counters -+ * - if compression is not successful for the first block, all input -+ * data is still in the window so we can still emit a stored block even -+ * when input comes from standard input. (This can also be done for -+ * all blocks if lit_bufsize is not greater than 32K.) -+ * - if compression is not successful for a file smaller than 64K, we can -+ * even emit a stored file instead of a stored block (saving 5 bytes). -+ * This is applicable only for zip (not gzip or zlib). -+ * - creating new Huffman trees less frequently may not provide fast -+ * adaptation to changes in the input data statistics. (Take for -+ * example a binary file with poorly compressible code followed by -+ * a highly compressible string table.) Smaller buffer sizes give -+ * fast adaptation but have of course the overhead of transmitting -+ * trees more frequently. -+ * - I can't count above 4 -+ */ -+ -+ uInt last_lit; /* running index in l_buf */ -+ -+ ushf *d_buf; -+ /* Buffer for distances. To simplify the code, d_buf and l_buf have -+ * the same number of elements. To use different lengths, an extra flag -+ * array would be necessary. -+ */ -+ -+ ulg opt_len; /* bit length of current block with optimal trees */ -+ ulg static_len; /* bit length of current block with static trees */ -+ uInt matches; /* number of string matches in current block */ -+ int last_eob_len; /* bit length of EOB code for last block */ -+ -+#ifdef DEBUG -+ ulg compressed_len; /* total bit length of compressed file mod 2^32 */ -+ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ -+#endif -+ -+ ush bi_buf; -+ /* Output buffer. bits are inserted starting at the bottom (least -+ * significant bits). -+ */ -+ int bi_valid; -+ /* Number of valid bits in bi_buf. All bits above the last valid bit -+ * are always zero. -+ */ -+ -+} FAR deflate_state; -+ -+/* Output a byte on the stream. -+ * IN assertion: there is enough room in pending_buf. -+ */ -+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} -+ -+ -+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -+/* Minimum amount of lookahead, except at the end of the input file. -+ * See deflate.c for comments about the MIN_MATCH+1. -+ */ -+ -+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) -+/* In order to simplify the code, particularly on 16 bit machines, match -+ * distances are limited to MAX_DIST instead of WSIZE. -+ */ -+ -+ /* in trees.c */ -+void _tr_init OF((deflate_state *s)); -+int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); -+void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, -+ int eof)); -+void _tr_align OF((deflate_state *s)); -+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, -+ int eof)); -+ -+#define d_code(dist) \ -+ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) -+/* Mapping from a distance to a distance code. dist is the distance - 1 and -+ * must not have side effects. _dist_code[256] and _dist_code[257] are never -+ * used. -+ */ -+ -+#ifndef DEBUG -+/* Inline versions of _tr_tally for speed: */ -+ -+#if defined(GEN_TREES_H) || !defined(STDC) -+ extern uch _length_code[]; -+ extern uch _dist_code[]; -+#else -+ extern const uch _length_code[]; -+ extern const uch _dist_code[]; -+#endif -+ -+# define _tr_tally_lit(s, c, flush) \ -+ { uch cc = (c); \ -+ s->d_buf[s->last_lit] = 0; \ -+ s->l_buf[s->last_lit++] = cc; \ -+ s->dyn_ltree[cc].Freq++; \ -+ flush = (s->last_lit == s->lit_bufsize-1); \ -+ } -+# define _tr_tally_dist(s, distance, length, flush) \ -+ { uch len = (length); \ -+ ush dist = (distance); \ -+ s->d_buf[s->last_lit] = dist; \ -+ s->l_buf[s->last_lit++] = len; \ -+ dist--; \ -+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ -+ s->dyn_dtree[d_code(dist)].Freq++; \ -+ flush = (s->last_lit == s->lit_bufsize-1); \ -+ } -+#else -+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) -+# define _tr_tally_dist(s, distance, length, flush) \ -+ flush = _tr_tally(s, distance, length) -+#endif -+ -+#endif /* _DEFLATE_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/infblock.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,403 @@ -+/* infblock.c -- interpret and process block types to last block -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+#include -+#include "infblock.h" -+#include "inftrees.h" -+#include "infcodes.h" -+#include "infutil.h" -+ -+struct inflate_codes_state {int dummy;}; /* for buggy compilers */ -+ -+/* simplify the use of the inflate_huft type with some defines */ -+#define exop word.what.Exop -+#define bits word.what.Bits -+ -+/* Table for deflate from PKZIP's appnote.txt. */ -+local const uInt border[] = { /* Order of the bit length code lengths */ -+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; -+ -+/* -+ Notes beyond the 1.93a appnote.txt: -+ -+ 1. Distance pointers never point before the beginning of the output -+ stream. -+ 2. Distance pointers can point back across blocks, up to 32k away. -+ 3. There is an implied maximum of 7 bits for the bit length table and -+ 15 bits for the actual data. -+ 4. If only one code exists, then it is encoded using one bit. (Zero -+ would be more efficient, but perhaps a little confusing.) If two -+ codes exist, they are coded using one bit each (0 and 1). -+ 5. There is no way of sending zero distance codes--a dummy must be -+ sent if there are none. (History: a pre 2.0 version of PKZIP would -+ store blocks with no distance codes, but this was discovered to be -+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow -+ zero distance codes, which is sent as one code of zero bits in -+ length. -+ 6. There are up to 286 literal/length codes. Code 256 represents the -+ end-of-block. Note however that the static length tree defines -+ 288 codes just to fill out the Huffman codes. Codes 286 and 287 -+ cannot be used though, since there is no length base or extra bits -+ defined for them. Similarily, there are up to 30 distance codes. -+ However, static trees define 32 codes (all 5 bits) to fill out the -+ Huffman codes, but the last two had better not show up in the data. -+ 7. Unzip can check dynamic Huffman blocks for complete code sets. -+ The exception is that a single code would not be complete (see #4). -+ 8. The five bits following the block type is really the number of -+ literal codes sent minus 257. -+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits -+ (1+6+6). Therefore, to output three times the length, you output -+ three codes (1+1+1), whereas to output four times the same length, -+ you only need two codes (1+3). Hmm. -+ 10. In the tree reconstruction algorithm, Code = Code + Increment -+ only if BitLength(i) is not zero. (Pretty obvious.) -+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) -+ 12. Note: length code 284 can represent 227-258, but length code 285 -+ really is 258. The last length deserves its own, short code -+ since it gets used a lot in very redundant files. The length -+ 258 is special since 258 - 3 (the min match length) is 255. -+ 13. The literal/length and distance code bit lengths are read as a -+ single stream of lengths. It is possible (and advantageous) for -+ a repeat code (16, 17, or 18) to go across the boundary between -+ the two sets of lengths. -+ */ -+ -+ -+void inflate_blocks_reset(s, z, c) -+inflate_blocks_statef *s; -+z_streamp z; -+uLongf *c; -+{ -+ if (c != Z_NULL) -+ *c = s->check; -+ if (s->mode == BTREE || s->mode == DTREE) -+ ZFREE(z, s->sub.trees.blens); -+ if (s->mode == CODES) -+ inflate_codes_free(s->sub.decode.codes, z); -+ s->mode = TYPE; -+ s->bitk = 0; -+ s->bitb = 0; -+ s->read = s->write = s->window; -+ if (s->checkfn != Z_NULL) -+ z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); -+ Tracev((stderr, "inflate: blocks reset\n")); -+} -+ -+ -+inflate_blocks_statef *inflate_blocks_new(z, c, w) -+z_streamp z; -+check_func c; -+uInt w; -+{ -+ inflate_blocks_statef *s; -+ -+ if ((s = (inflate_blocks_statef *)ZALLOC -+ (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) -+ return s; -+ if ((s->hufts = -+ (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) -+ { -+ ZFREE(z, s); -+ return Z_NULL; -+ } -+ if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) -+ { -+ ZFREE(z, s->hufts); -+ ZFREE(z, s); -+ return Z_NULL; -+ } -+ s->end = s->window + w; -+ s->checkfn = c; -+ s->mode = TYPE; -+ Tracev((stderr, "inflate: blocks allocated\n")); -+ inflate_blocks_reset(s, z, Z_NULL); -+ return s; -+} -+ -+ -+int inflate_blocks(s, z, r) -+inflate_blocks_statef *s; -+z_streamp z; -+int r; -+{ -+ uInt t; /* temporary storage */ -+ uLong b; /* bit buffer */ -+ uInt k; /* bits in bit buffer */ -+ Bytef *p; /* input data pointer */ -+ uInt n; /* bytes available there */ -+ Bytef *q; /* output window write pointer */ -+ uInt m; /* bytes to end of window or read pointer */ -+ -+ /* copy input/output information to locals (UPDATE macro restores) */ -+ LOAD -+ -+ /* process input based on current state */ -+ while (1) switch (s->mode) -+ { -+ case TYPE: -+ NEEDBITS(3) -+ t = (uInt)b & 7; -+ s->last = t & 1; -+ switch (t >> 1) -+ { -+ case 0: /* stored */ -+ Tracev((stderr, "inflate: stored block%s\n", -+ s->last ? " (last)" : "")); -+ DUMPBITS(3) -+ t = k & 7; /* go to byte boundary */ -+ DUMPBITS(t) -+ s->mode = LENS; /* get length of stored block */ -+ break; -+ case 1: /* fixed */ -+ Tracev((stderr, "inflate: fixed codes block%s\n", -+ s->last ? " (last)" : "")); -+ { -+ uInt bl, bd; -+ inflate_huft *tl, *td; -+ -+ inflate_trees_fixed(&bl, &bd, &tl, &td, z); -+ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); -+ if (s->sub.decode.codes == Z_NULL) -+ { -+ r = Z_MEM_ERROR; -+ LEAVE -+ } -+ } -+ DUMPBITS(3) -+ s->mode = CODES; -+ break; -+ case 2: /* dynamic */ -+ Tracev((stderr, "inflate: dynamic codes block%s\n", -+ s->last ? " (last)" : "")); -+ DUMPBITS(3) -+ s->mode = TABLE; -+ break; -+ case 3: /* illegal */ -+ DUMPBITS(3) -+ s->mode = BAD; -+ z->msg = (char*)"invalid block type"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+ break; -+ case LENS: -+ NEEDBITS(32) -+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) -+ { -+ s->mode = BAD; -+ z->msg = (char*)"invalid stored block lengths"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+ s->sub.left = (uInt)b & 0xffff; -+ b = k = 0; /* dump bits */ -+ Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); -+ s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); -+ break; -+ case STORED: -+ if (n == 0) -+ LEAVE -+ NEEDOUT -+ t = s->sub.left; -+ if (t > n) t = n; -+ if (t > m) t = m; -+ zmemcpy(q, p, t); -+ p += t; n -= t; -+ q += t; m -= t; -+ if ((s->sub.left -= t) != 0) -+ break; -+ Tracev((stderr, "inflate: stored end, %lu total out\n", -+ z->total_out + (q >= s->read ? q - s->read : -+ (s->end - s->read) + (q - s->window)))); -+ s->mode = s->last ? DRY : TYPE; -+ break; -+ case TABLE: -+ NEEDBITS(14) -+ s->sub.trees.table = t = (uInt)b & 0x3fff; -+#ifndef PKZIP_BUG_WORKAROUND -+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) -+ { -+ s->mode = BAD; -+ z->msg = (char*)"too many length or distance symbols"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+#endif -+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); -+ if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) -+ { -+ r = Z_MEM_ERROR; -+ LEAVE -+ } -+ DUMPBITS(14) -+ s->sub.trees.index = 0; -+ Tracev((stderr, "inflate: table sizes ok\n")); -+ s->mode = BTREE; -+ case BTREE: -+ while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) -+ { -+ NEEDBITS(3) -+ s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; -+ DUMPBITS(3) -+ } -+ while (s->sub.trees.index < 19) -+ s->sub.trees.blens[border[s->sub.trees.index++]] = 0; -+ s->sub.trees.bb = 7; -+ t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, -+ &s->sub.trees.tb, s->hufts, z); -+ if (t != Z_OK) -+ { -+ r = t; -+ if (r == Z_DATA_ERROR) -+ { -+ ZFREE(z, s->sub.trees.blens); -+ s->mode = BAD; -+ } -+ LEAVE -+ } -+ s->sub.trees.index = 0; -+ Tracev((stderr, "inflate: bits tree ok\n")); -+ s->mode = DTREE; -+ case DTREE: -+ while (t = s->sub.trees.table, -+ s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) -+ { -+ inflate_huft *h; -+ uInt i, j, c; -+ -+ t = s->sub.trees.bb; -+ NEEDBITS(t) -+ h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); -+ t = h->bits; -+ c = h->base; -+ if (c < 16) -+ { -+ DUMPBITS(t) -+ s->sub.trees.blens[s->sub.trees.index++] = c; -+ } -+ else /* c == 16..18 */ -+ { -+ i = c == 18 ? 7 : c - 14; -+ j = c == 18 ? 11 : 3; -+ NEEDBITS(t + i) -+ DUMPBITS(t) -+ j += (uInt)b & inflate_mask[i]; -+ DUMPBITS(i) -+ i = s->sub.trees.index; -+ t = s->sub.trees.table; -+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || -+ (c == 16 && i < 1)) -+ { -+ ZFREE(z, s->sub.trees.blens); -+ s->mode = BAD; -+ z->msg = (char*)"invalid bit length repeat"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+ c = c == 16 ? s->sub.trees.blens[i - 1] : 0; -+ do { -+ s->sub.trees.blens[i++] = c; -+ } while (--j); -+ s->sub.trees.index = i; -+ } -+ } -+ s->sub.trees.tb = Z_NULL; -+ { -+ uInt bl, bd; -+ inflate_huft *tl, *td; -+ inflate_codes_statef *c; -+ -+ bl = 9; /* must be <= 9 for lookahead assumptions */ -+ bd = 6; /* must be <= 9 for lookahead assumptions */ -+ t = s->sub.trees.table; -+ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), -+ s->sub.trees.blens, &bl, &bd, &tl, &td, -+ s->hufts, z); -+ if (t != Z_OK) -+ { -+ if (t == (uInt)Z_DATA_ERROR) -+ { -+ ZFREE(z, s->sub.trees.blens); -+ s->mode = BAD; -+ } -+ r = t; -+ LEAVE -+ } -+ Tracev((stderr, "inflate: trees ok\n")); -+ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) -+ { -+ r = Z_MEM_ERROR; -+ LEAVE -+ } -+ s->sub.decode.codes = c; -+ } -+ ZFREE(z, s->sub.trees.blens); -+ s->mode = CODES; -+ case CODES: -+ UPDATE -+ if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) -+ return inflate_flush(s, z, r); -+ r = Z_OK; -+ inflate_codes_free(s->sub.decode.codes, z); -+ LOAD -+ Tracev((stderr, "inflate: codes end, %lu total out\n", -+ z->total_out + (q >= s->read ? q - s->read : -+ (s->end - s->read) + (q - s->window)))); -+ if (!s->last) -+ { -+ s->mode = TYPE; -+ break; -+ } -+ s->mode = DRY; -+ case DRY: -+ FLUSH -+ if (s->read != s->write) -+ LEAVE -+ s->mode = DONE; -+ case DONE: -+ r = Z_STREAM_END; -+ LEAVE -+ case BAD: -+ r = Z_DATA_ERROR; -+ LEAVE -+ default: -+ r = Z_STREAM_ERROR; -+ LEAVE -+ } -+} -+ -+ -+int inflate_blocks_free(s, z) -+inflate_blocks_statef *s; -+z_streamp z; -+{ -+ inflate_blocks_reset(s, z, Z_NULL); -+ ZFREE(z, s->window); -+ ZFREE(z, s->hufts); -+ ZFREE(z, s); -+ Tracev((stderr, "inflate: blocks freed\n")); -+ return Z_OK; -+} -+ -+ -+void inflate_set_dictionary(s, d, n) -+inflate_blocks_statef *s; -+const Bytef *d; -+uInt n; -+{ -+ zmemcpy(s->window, d, n); -+ s->read = s->write = s->window + n; -+} -+ -+ -+/* Returns true if inflate is currently at the end of a block generated -+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. -+ * IN assertion: s != Z_NULL -+ */ -+int inflate_blocks_sync_point(s) -+inflate_blocks_statef *s; -+{ -+ return s->mode == LENS; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/infblock.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,39 @@ -+/* infblock.h -- header to use infblock.c -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+struct inflate_blocks_state; -+typedef struct inflate_blocks_state FAR inflate_blocks_statef; -+ -+extern inflate_blocks_statef * inflate_blocks_new OF(( -+ z_streamp z, -+ check_func c, /* check function */ -+ uInt w)); /* window size */ -+ -+extern int inflate_blocks OF(( -+ inflate_blocks_statef *, -+ z_streamp , -+ int)); /* initial return code */ -+ -+extern void inflate_blocks_reset OF(( -+ inflate_blocks_statef *, -+ z_streamp , -+ uLongf *)); /* check value on output */ -+ -+extern int inflate_blocks_free OF(( -+ inflate_blocks_statef *, -+ z_streamp)); -+ -+extern void inflate_set_dictionary OF(( -+ inflate_blocks_statef *s, -+ const Bytef *d, /* dictionary */ -+ uInt n)); /* dictionary length */ -+ -+extern int inflate_blocks_sync_point OF(( -+ inflate_blocks_statef *s)); ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/infcodes.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,251 @@ -+/* infcodes.c -- process literals and length/distance pairs -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+#include -+#include "inftrees.h" -+#include "infblock.h" -+#include "infcodes.h" -+#include "infutil.h" -+#include "inffast.h" -+ -+/* simplify the use of the inflate_huft type with some defines */ -+#define exop word.what.Exop -+#define bits word.what.Bits -+ -+typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ -+ START, /* x: set up for LEN */ -+ LEN, /* i: get length/literal/eob next */ -+ LENEXT, /* i: getting length extra (have base) */ -+ DIST, /* i: get distance next */ -+ DISTEXT, /* i: getting distance extra */ -+ COPY, /* o: copying bytes in window, waiting for space */ -+ LIT, /* o: got literal, waiting for output space */ -+ WASH, /* o: got eob, possibly still output waiting */ -+ END, /* x: got eob and all data flushed */ -+ BADCODE} /* x: got error */ -+inflate_codes_mode; -+ -+/* inflate codes private state */ -+struct inflate_codes_state { -+ -+ /* mode */ -+ inflate_codes_mode mode; /* current inflate_codes mode */ -+ -+ /* mode dependent information */ -+ uInt len; -+ union { -+ struct { -+ inflate_huft *tree; /* pointer into tree */ -+ uInt need; /* bits needed */ -+ } code; /* if LEN or DIST, where in tree */ -+ uInt lit; /* if LIT, literal */ -+ struct { -+ uInt get; /* bits to get for extra */ -+ uInt dist; /* distance back to copy from */ -+ } copy; /* if EXT or COPY, where and how much */ -+ } sub; /* submode */ -+ -+ /* mode independent information */ -+ Byte lbits; /* ltree bits decoded per branch */ -+ Byte dbits; /* dtree bits decoder per branch */ -+ inflate_huft *ltree; /* literal/length/eob tree */ -+ inflate_huft *dtree; /* distance tree */ -+ -+}; -+ -+ -+inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) -+uInt bl, bd; -+inflate_huft *tl; -+inflate_huft *td; /* need separate declaration for Borland C++ */ -+z_streamp z; -+{ -+ inflate_codes_statef *c; -+ -+ if ((c = (inflate_codes_statef *) -+ ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) -+ { -+ c->mode = START; -+ c->lbits = (Byte)bl; -+ c->dbits = (Byte)bd; -+ c->ltree = tl; -+ c->dtree = td; -+ Tracev((stderr, "inflate: codes new\n")); -+ } -+ return c; -+} -+ -+ -+int inflate_codes(s, z, r) -+inflate_blocks_statef *s; -+z_streamp z; -+int r; -+{ -+ uInt j; /* temporary storage */ -+ inflate_huft *t; /* temporary pointer */ -+ uInt e; /* extra bits or operation */ -+ uLong b; /* bit buffer */ -+ uInt k; /* bits in bit buffer */ -+ Bytef *p; /* input data pointer */ -+ uInt n; /* bytes available there */ -+ Bytef *q; /* output window write pointer */ -+ uInt m; /* bytes to end of window or read pointer */ -+ Bytef *f; /* pointer to copy strings from */ -+ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ -+ -+ /* copy input/output information to locals (UPDATE macro restores) */ -+ LOAD -+ -+ /* process input and output based on current state */ -+ while (1) switch (c->mode) -+ { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ -+ case START: /* x: set up for LEN */ -+#ifndef SLOW -+ if (m >= 258 && n >= 10) -+ { -+ UPDATE -+ r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); -+ LOAD -+ if (r != Z_OK) -+ { -+ c->mode = r == Z_STREAM_END ? WASH : BADCODE; -+ break; -+ } -+ } -+#endif /* !SLOW */ -+ c->sub.code.need = c->lbits; -+ c->sub.code.tree = c->ltree; -+ c->mode = LEN; -+ case LEN: /* i: get length/literal/eob next */ -+ j = c->sub.code.need; -+ NEEDBITS(j) -+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); -+ DUMPBITS(t->bits) -+ e = (uInt)(t->exop); -+ if (e == 0) /* literal */ -+ { -+ c->sub.lit = t->base; -+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? -+ "inflate: literal '%c'\n" : -+ "inflate: literal 0x%02x\n", t->base)); -+ c->mode = LIT; -+ break; -+ } -+ if (e & 16) /* length */ -+ { -+ c->sub.copy.get = e & 15; -+ c->len = t->base; -+ c->mode = LENEXT; -+ break; -+ } -+ if ((e & 64) == 0) /* next table */ -+ { -+ c->sub.code.need = e; -+ c->sub.code.tree = t + t->base; -+ break; -+ } -+ if (e & 32) /* end of block */ -+ { -+ Tracevv((stderr, "inflate: end of block\n")); -+ c->mode = WASH; -+ break; -+ } -+ c->mode = BADCODE; /* invalid code */ -+ z->msg = (char*)"invalid literal/length code"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ case LENEXT: /* i: getting length extra (have base) */ -+ j = c->sub.copy.get; -+ NEEDBITS(j) -+ c->len += (uInt)b & inflate_mask[j]; -+ DUMPBITS(j) -+ c->sub.code.need = c->dbits; -+ c->sub.code.tree = c->dtree; -+ Tracevv((stderr, "inflate: length %u\n", c->len)); -+ c->mode = DIST; -+ case DIST: /* i: get distance next */ -+ j = c->sub.code.need; -+ NEEDBITS(j) -+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); -+ DUMPBITS(t->bits) -+ e = (uInt)(t->exop); -+ if (e & 16) /* distance */ -+ { -+ c->sub.copy.get = e & 15; -+ c->sub.copy.dist = t->base; -+ c->mode = DISTEXT; -+ break; -+ } -+ if ((e & 64) == 0) /* next table */ -+ { -+ c->sub.code.need = e; -+ c->sub.code.tree = t + t->base; -+ break; -+ } -+ c->mode = BADCODE; /* invalid code */ -+ z->msg = (char*)"invalid distance code"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ case DISTEXT: /* i: getting distance extra */ -+ j = c->sub.copy.get; -+ NEEDBITS(j) -+ c->sub.copy.dist += (uInt)b & inflate_mask[j]; -+ DUMPBITS(j) -+ Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); -+ c->mode = COPY; -+ case COPY: /* o: copying bytes in window, waiting for space */ -+ f = q - c->sub.copy.dist; -+ while (f < s->window) /* modulo window size-"while" instead */ -+ f += s->end - s->window; /* of "if" handles invalid distances */ -+ while (c->len) -+ { -+ NEEDOUT -+ OUTBYTE(*f++) -+ if (f == s->end) -+ f = s->window; -+ c->len--; -+ } -+ c->mode = START; -+ break; -+ case LIT: /* o: got literal, waiting for output space */ -+ NEEDOUT -+ OUTBYTE(c->sub.lit) -+ c->mode = START; -+ break; -+ case WASH: /* o: got eob, possibly more output */ -+ if (k > 7) /* return unused byte, if any */ -+ { -+ Assert(k < 16, "inflate_codes grabbed too many bytes") -+ k -= 8; -+ n++; -+ p--; /* can always return one */ -+ } -+ FLUSH -+ if (s->read != s->write) -+ LEAVE -+ c->mode = END; -+ case END: -+ r = Z_STREAM_END; -+ LEAVE -+ case BADCODE: /* x: got error */ -+ r = Z_DATA_ERROR; -+ LEAVE -+ default: -+ r = Z_STREAM_ERROR; -+ LEAVE -+ } -+#ifdef NEED_DUMMY_RETURN -+ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ -+#endif -+} -+ -+ -+void inflate_codes_free(c, z) -+inflate_codes_statef *c; -+z_streamp z; -+{ -+ ZFREE(z, c); -+ Tracev((stderr, "inflate: codes free\n")); -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/infcodes.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,31 @@ -+/* infcodes.h -- header to use infcodes.c -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+#ifndef _INFCODES_H -+#define _INFCODES_H -+ -+struct inflate_codes_state; -+typedef struct inflate_codes_state FAR inflate_codes_statef; -+ -+extern inflate_codes_statef *inflate_codes_new OF(( -+ uInt, uInt, -+ inflate_huft *, inflate_huft *, -+ z_streamp )); -+ -+extern int inflate_codes OF(( -+ inflate_blocks_statef *, -+ z_streamp , -+ int)); -+ -+extern void inflate_codes_free OF(( -+ inflate_codes_statef *, -+ z_streamp )); -+ -+#endif /* _INFCODES_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/inffast.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,183 @@ -+/* inffast.c -- process literals and length/distance pairs fast -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+#include -+#include "inftrees.h" -+#include "infblock.h" -+#include "infcodes.h" -+#include "infutil.h" -+#include "inffast.h" -+ -+struct inflate_codes_state {int dummy;}; /* for buggy compilers */ -+ -+/* simplify the use of the inflate_huft type with some defines */ -+#define exop word.what.Exop -+#define bits word.what.Bits -+ -+/* macros for bit input with no checking and for returning unused bytes */ -+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;} -+ -+/* Called with number of bytes left to write in window at least 258 -+ (the maximum string length) and number of input bytes available -+ at least ten. The ten bytes are six bytes for the longest length/ -+ distance pair plus four bytes for overloading the bit buffer. */ -+ -+int inflate_fast(bl, bd, tl, td, s, z) -+uInt bl, bd; -+inflate_huft *tl; -+inflate_huft *td; /* need separate declaration for Borland C++ */ -+inflate_blocks_statef *s; -+z_streamp z; -+{ -+ inflate_huft *t; /* temporary pointer */ -+ uInt e; /* extra bits or operation */ -+ uLong b; /* bit buffer */ -+ uInt k; /* bits in bit buffer */ -+ Bytef *p; /* input data pointer */ -+ uInt n; /* bytes available there */ -+ Bytef *q; /* output window write pointer */ -+ uInt m; /* bytes to end of window or read pointer */ -+ uInt ml; /* mask for literal/length tree */ -+ uInt md; /* mask for distance tree */ -+ uInt c; /* bytes to copy */ -+ uInt d; /* distance back to copy from */ -+ Bytef *r; /* copy source pointer */ -+ -+ /* load input, output, bit values */ -+ LOAD -+ -+ /* initialize masks */ -+ ml = inflate_mask[bl]; -+ md = inflate_mask[bd]; -+ -+ /* do until not enough input or output space for fast loop */ -+ do { /* assume called with m >= 258 && n >= 10 */ -+ /* get literal/length code */ -+ GRABBITS(20) /* max bits for literal/length code */ -+ if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) -+ { -+ DUMPBITS(t->bits) -+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? -+ "inflate: * literal '%c'\n" : -+ "inflate: * literal 0x%02x\n", t->base)); -+ *q++ = (Byte)t->base; -+ m--; -+ continue; -+ } -+ do { -+ DUMPBITS(t->bits) -+ if (e & 16) -+ { -+ /* get extra bits for length */ -+ e &= 15; -+ c = t->base + ((uInt)b & inflate_mask[e]); -+ DUMPBITS(e) -+ Tracevv((stderr, "inflate: * length %u\n", c)); -+ -+ /* decode distance base of block to copy */ -+ GRABBITS(15); /* max bits for distance code */ -+ e = (t = td + ((uInt)b & md))->exop; -+ do { -+ DUMPBITS(t->bits) -+ if (e & 16) -+ { -+ /* get extra bits to add to distance base */ -+ e &= 15; -+ GRABBITS(e) /* get extra bits (up to 13) */ -+ d = t->base + ((uInt)b & inflate_mask[e]); -+ DUMPBITS(e) -+ Tracevv((stderr, "inflate: * distance %u\n", d)); -+ -+ /* do the copy */ -+ m -= c; -+ r = q - d; -+ if (r < s->window) /* wrap if needed */ -+ { -+ do { -+ r += s->end - s->window; /* force pointer in window */ -+ } while (r < s->window); /* covers invalid distances */ -+ e = s->end - r; -+ if (c > e) -+ { -+ c -= e; /* wrapped copy */ -+ do { -+ *q++ = *r++; -+ } while (--e); -+ r = s->window; -+ do { -+ *q++ = *r++; -+ } while (--c); -+ } -+ else /* normal copy */ -+ { -+ *q++ = *r++; c--; -+ *q++ = *r++; c--; -+ do { -+ *q++ = *r++; -+ } while (--c); -+ } -+ } -+ else /* normal copy */ -+ { -+ *q++ = *r++; c--; -+ *q++ = *r++; c--; -+ do { -+ *q++ = *r++; -+ } while (--c); -+ } -+ break; -+ } -+ else if ((e & 64) == 0) -+ { -+ t += t->base; -+ e = (t += ((uInt)b & inflate_mask[e]))->exop; -+ } -+ else -+ { -+ z->msg = (char*)"invalid distance code"; -+ UNGRAB -+ UPDATE -+ return Z_DATA_ERROR; -+ } -+ } while (1); -+ break; -+ } -+ if ((e & 64) == 0) -+ { -+ t += t->base; -+ if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) -+ { -+ DUMPBITS(t->bits) -+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? -+ "inflate: * literal '%c'\n" : -+ "inflate: * literal 0x%02x\n", t->base)); -+ *q++ = (Byte)t->base; -+ m--; -+ break; -+ } -+ } -+ else if (e & 32) -+ { -+ Tracevv((stderr, "inflate: * end of block\n")); -+ UNGRAB -+ UPDATE -+ return Z_STREAM_END; -+ } -+ else -+ { -+ z->msg = (char*)"invalid literal/length code"; -+ UNGRAB -+ UPDATE -+ return Z_DATA_ERROR; -+ } -+ } while (1); -+ } while (m >= 258 && n >= 10); -+ -+ /* not enough input or output--restore pointers and return */ -+ UNGRAB -+ UPDATE -+ return Z_OK; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/inffast.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,22 @@ -+/* inffast.h -- header to use inffast.c -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+#ifndef _INFFAST_H -+#define _INFFAST_H -+ -+extern int inflate_fast OF(( -+ uInt, -+ uInt, -+ inflate_huft *, -+ inflate_huft *, -+ inflate_blocks_statef *, -+ z_streamp )); -+ -+#endif /* _INFFAST_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/inffixed.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,151 @@ -+/* inffixed.h -- table for decoding fixed codes -+ * Generated automatically by the maketree.c program -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+local uInt fixed_bl = 9; -+local uInt fixed_bd = 5; -+local inflate_huft fixed_tl[] = { -+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, -+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, -+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, -+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, -+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, -+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, -+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, -+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, -+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, -+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, -+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, -+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, -+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, -+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, -+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, -+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, -+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, -+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, -+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, -+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, -+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, -+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, -+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, -+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, -+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, -+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, -+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, -+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, -+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, -+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, -+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, -+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, -+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, -+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, -+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, -+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, -+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, -+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, -+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, -+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, -+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, -+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, -+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, -+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, -+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, -+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, -+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, -+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, -+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, -+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, -+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, -+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, -+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, -+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, -+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, -+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, -+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, -+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, -+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, -+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, -+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, -+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, -+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, -+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, -+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, -+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, -+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, -+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, -+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, -+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, -+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, -+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, -+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, -+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, -+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, -+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, -+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, -+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, -+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, -+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, -+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, -+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, -+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, -+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, -+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, -+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, -+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, -+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, -+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, -+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, -+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, -+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, -+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, -+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, -+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, -+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, -+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, -+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, -+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, -+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, -+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, -+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, -+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, -+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, -+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, -+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, -+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, -+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, -+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, -+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, -+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, -+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, -+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, -+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, -+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, -+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, -+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, -+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, -+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, -+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, -+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, -+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, -+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, -+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, -+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, -+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, -+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, -+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} -+ }; -+local inflate_huft fixed_td[] = { -+ {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, -+ {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, -+ {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, -+ {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, -+ {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, -+ {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, -+ {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, -+ {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} -+ }; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/inflate.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,368 @@ -+/* inflate.c -- zlib interface to inflate modules -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+#include -+#include "infblock.h" -+ -+struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ -+ -+typedef enum { -+ METHOD, /* waiting for method byte */ -+ FLAG, /* waiting for flag byte */ -+ DICT4, /* four dictionary check bytes to go */ -+ DICT3, /* three dictionary check bytes to go */ -+ DICT2, /* two dictionary check bytes to go */ -+ DICT1, /* one dictionary check byte to go */ -+ DICT0, /* waiting for inflateSetDictionary */ -+ BLOCKS, /* decompressing blocks */ -+ CHECK4, /* four check bytes to go */ -+ CHECK3, /* three check bytes to go */ -+ CHECK2, /* two check bytes to go */ -+ CHECK1, /* one check byte to go */ -+ DONE, /* finished check, done */ -+ BAD} /* got an error--stay here */ -+inflate_mode; -+ -+/* inflate private state */ -+struct internal_state { -+ -+ /* mode */ -+ inflate_mode mode; /* current inflate mode */ -+ -+ /* mode dependent information */ -+ union { -+ uInt method; /* if FLAGS, method byte */ -+ struct { -+ uLong was; /* computed check value */ -+ uLong need; /* stream check value */ -+ } check; /* if CHECK, check values to compare */ -+ uInt marker; /* if BAD, inflateSync's marker bytes count */ -+ } sub; /* submode */ -+ -+ /* mode independent information */ -+ int nowrap; /* flag for no wrapper */ -+ uInt wbits; /* log2(window size) (8..15, defaults to 15) */ -+ inflate_blocks_statef -+ *blocks; /* current inflate_blocks state */ -+ -+}; -+ -+ -+int ZEXPORT inflateReset(z) -+z_streamp z; -+{ -+ if (z == Z_NULL || z->state == Z_NULL) -+ return Z_STREAM_ERROR; -+ z->total_in = z->total_out = 0; -+ z->msg = Z_NULL; -+ z->state->mode = z->state->nowrap ? BLOCKS : METHOD; -+ inflate_blocks_reset(z->state->blocks, z, Z_NULL); -+ Tracev((stderr, "inflate: reset\n")); -+ return Z_OK; -+} -+ -+ -+int ZEXPORT inflateEnd(z) -+z_streamp z; -+{ -+ if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) -+ return Z_STREAM_ERROR; -+ if (z->state->blocks != Z_NULL) -+ inflate_blocks_free(z->state->blocks, z); -+ ZFREE(z, z->state); -+ z->state = Z_NULL; -+ Tracev((stderr, "inflate: end\n")); -+ return Z_OK; -+} -+ -+ -+int ZEXPORT inflateInit2_(z, w, version, stream_size) -+z_streamp z; -+int w; -+const char *version; -+int stream_size; -+{ -+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || -+ stream_size != sizeof(z_stream)) -+ return Z_VERSION_ERROR; -+ -+ /* initialize state */ -+ if (z == Z_NULL) -+ return Z_STREAM_ERROR; -+ z->msg = Z_NULL; -+ if (z->zalloc == Z_NULL) -+ { -+ return Z_STREAM_ERROR; -+/* z->zalloc = zcalloc; -+ z->opaque = (voidpf)0; -+*/ -+ } -+ if (z->zfree == Z_NULL) return Z_STREAM_ERROR; /* z->zfree = zcfree; */ -+ if ((z->state = (struct internal_state FAR *) -+ ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) -+ return Z_MEM_ERROR; -+ z->state->blocks = Z_NULL; -+ -+ /* handle undocumented nowrap option (no zlib header or check) */ -+ z->state->nowrap = 0; -+ if (w < 0) -+ { -+ w = - w; -+ z->state->nowrap = 1; -+ } -+ -+ /* set window size */ -+ if (w < 8 || w > 15) -+ { -+ inflateEnd(z); -+ return Z_STREAM_ERROR; -+ } -+ z->state->wbits = (uInt)w; -+ -+ /* create inflate_blocks state */ -+ if ((z->state->blocks = -+ inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) -+ == Z_NULL) -+ { -+ inflateEnd(z); -+ return Z_MEM_ERROR; -+ } -+ Tracev((stderr, "inflate: allocated\n")); -+ -+ /* reset state */ -+ inflateReset(z); -+ return Z_OK; -+} -+ -+ -+int ZEXPORT inflateInit_(z, version, stream_size) -+z_streamp z; -+const char *version; -+int stream_size; -+{ -+ return inflateInit2_(z, DEF_WBITS, version, stream_size); -+} -+ -+ -+#define NEEDBYTE {if(z->avail_in==0)return r;r=f;} -+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) -+ -+int ZEXPORT inflate(z, f) -+z_streamp z; -+int f; -+{ -+ int r; -+ uInt b; -+ -+ if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) -+ return Z_STREAM_ERROR; -+ f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; -+ r = Z_BUF_ERROR; -+ while (1) switch (z->state->mode) -+ { -+ case METHOD: -+ NEEDBYTE -+ if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) -+ { -+ z->state->mode = BAD; -+ z->msg = (char*)"unknown compression method"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ if ((z->state->sub.method >> 4) + 8 > z->state->wbits) -+ { -+ z->state->mode = BAD; -+ z->msg = (char*)"invalid window size"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ z->state->mode = FLAG; -+ case FLAG: -+ NEEDBYTE -+ b = NEXTBYTE; -+ if (((z->state->sub.method << 8) + b) % 31) -+ { -+ z->state->mode = BAD; -+ z->msg = (char*)"incorrect header check"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ Tracev((stderr, "inflate: zlib header ok\n")); -+ if (!(b & PRESET_DICT)) -+ { -+ z->state->mode = BLOCKS; -+ break; -+ } -+ z->state->mode = DICT4; -+ case DICT4: -+ NEEDBYTE -+ z->state->sub.check.need = (uLong)NEXTBYTE << 24; -+ z->state->mode = DICT3; -+ case DICT3: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE << 16; -+ z->state->mode = DICT2; -+ case DICT2: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE << 8; -+ z->state->mode = DICT1; -+ case DICT1: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE; -+ z->adler = z->state->sub.check.need; -+ z->state->mode = DICT0; -+ return Z_NEED_DICT; -+ case DICT0: -+ z->state->mode = BAD; -+ z->msg = (char*)"need dictionary"; -+ z->state->sub.marker = 0; /* can try inflateSync */ -+ return Z_STREAM_ERROR; -+ case BLOCKS: -+ r = inflate_blocks(z->state->blocks, z, r); -+ if (r == Z_DATA_ERROR) -+ { -+ z->state->mode = BAD; -+ z->state->sub.marker = 0; /* can try inflateSync */ -+ break; -+ } -+ if (r == Z_OK) -+ r = f; -+ if (r != Z_STREAM_END) -+ return r; -+ r = f; -+ inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); -+ if (z->state->nowrap) -+ { -+ z->state->mode = DONE; -+ break; -+ } -+ z->state->mode = CHECK4; -+ case CHECK4: -+ NEEDBYTE -+ z->state->sub.check.need = (uLong)NEXTBYTE << 24; -+ z->state->mode = CHECK3; -+ case CHECK3: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE << 16; -+ z->state->mode = CHECK2; -+ case CHECK2: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE << 8; -+ z->state->mode = CHECK1; -+ case CHECK1: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE; -+ -+ if (z->state->sub.check.was != z->state->sub.check.need) -+ { -+ z->state->mode = BAD; -+ z->msg = (char*)"incorrect data check"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ Tracev((stderr, "inflate: zlib check ok\n")); -+ z->state->mode = DONE; -+ case DONE: -+ return Z_STREAM_END; -+ case BAD: -+ return Z_DATA_ERROR; -+ default: -+ return Z_STREAM_ERROR; -+ } -+#ifdef NEED_DUMMY_RETURN -+ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ -+#endif -+} -+ -+ -+int ZEXPORT inflateSetDictionary(z, dictionary, dictLength) -+z_streamp z; -+const Bytef *dictionary; -+uInt dictLength; -+{ -+ uInt length = dictLength; -+ -+ if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0) -+ return Z_STREAM_ERROR; -+ -+ if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR; -+ z->adler = 1L; -+ -+ if (length >= ((uInt)1<state->wbits)) -+ { -+ length = (1<state->wbits)-1; -+ dictionary += dictLength - length; -+ } -+ inflate_set_dictionary(z->state->blocks, dictionary, length); -+ z->state->mode = BLOCKS; -+ return Z_OK; -+} -+ -+ -+int ZEXPORT inflateSync(z) -+z_streamp z; -+{ -+ uInt n; /* number of bytes to look at */ -+ Bytef *p; /* pointer to bytes */ -+ uInt m; /* number of marker bytes found in a row */ -+ uLong r, w; /* temporaries to save total_in and total_out */ -+ -+ /* set up */ -+ if (z == Z_NULL || z->state == Z_NULL) -+ return Z_STREAM_ERROR; -+ if (z->state->mode != BAD) -+ { -+ z->state->mode = BAD; -+ z->state->sub.marker = 0; -+ } -+ if ((n = z->avail_in) == 0) -+ return Z_BUF_ERROR; -+ p = z->next_in; -+ m = z->state->sub.marker; -+ -+ /* search */ -+ while (n && m < 4) -+ { -+ static const Byte mark[4] = {0, 0, 0xff, 0xff}; -+ if (*p == mark[m]) -+ m++; -+ else if (*p) -+ m = 0; -+ else -+ m = 4 - m; -+ p++, n--; -+ } -+ -+ /* restore */ -+ z->total_in += p - z->next_in; -+ z->next_in = p; -+ z->avail_in = n; -+ z->state->sub.marker = m; -+ -+ /* return no joy or set up to restart on a new block */ -+ if (m != 4) -+ return Z_DATA_ERROR; -+ r = z->total_in; w = z->total_out; -+ inflateReset(z); -+ z->total_in = r; z->total_out = w; -+ z->state->mode = BLOCKS; -+ return Z_OK; -+} -+ -+ -+/* Returns true if inflate is currently at the end of a block generated -+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP -+ * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH -+ * but removes the length bytes of the resulting empty stored block. When -+ * decompressing, PPP checks that at the end of input packet, inflate is -+ * waiting for these length bytes. -+ */ -+int ZEXPORT inflateSyncPoint(z) -+z_streamp z; -+{ -+ if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL) -+ return Z_STREAM_ERROR; -+ return inflate_blocks_sync_point(z->state->blocks); -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/inftrees.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,454 @@ -+/* inftrees.c -- generate Huffman trees for efficient decoding -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+#include -+#include "inftrees.h" -+ -+#if !defined(BUILDFIXED) && !defined(STDC) -+# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */ -+#endif -+ -+local const char inflate_copyright[] = -+ " inflate 1.1.4 Copyright 1995-2002 Mark Adler "; -+/* -+ If you use the zlib library in a product, an acknowledgment is welcome -+ in the documentation of your product. If for some reason you cannot -+ include such an acknowledgment, I would appreciate that you keep this -+ copyright string in the executable of your product. -+ */ -+struct internal_state {int dummy;}; /* for buggy compilers */ -+ -+/* simplify the use of the inflate_huft type with some defines */ -+#define exop word.what.Exop -+#define bits word.what.Bits -+ -+ -+local int huft_build OF(( -+ uIntf *, /* code lengths in bits */ -+ uInt, /* number of codes */ -+ uInt, /* number of "simple" codes */ -+ const uIntf *, /* list of base values for non-simple codes */ -+ const uIntf *, /* list of extra bits for non-simple codes */ -+ inflate_huft * FAR*,/* result: starting table */ -+ uIntf *, /* maximum lookup bits (returns actual) */ -+ inflate_huft *, /* space for trees */ -+ uInt *, /* hufts used in space */ -+ uIntf * )); /* space for values */ -+ -+/* Tables for deflate from PKZIP's appnote.txt. */ -+local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ -+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, -+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; -+ /* see note #13 above about 258 */ -+local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ -+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, -+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ -+local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ -+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, -+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, -+ 8193, 12289, 16385, 24577}; -+local const uInt cpdext[30] = { /* Extra bits for distance codes */ -+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, -+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, -+ 12, 12, 13, 13}; -+ -+/* -+ Huffman code decoding is performed using a multi-level table lookup. -+ The fastest way to decode is to simply build a lookup table whose -+ size is determined by the longest code. However, the time it takes -+ to build this table can also be a factor if the data being decoded -+ is not very long. The most common codes are necessarily the -+ shortest codes, so those codes dominate the decoding time, and hence -+ the speed. The idea is you can have a shorter table that decodes the -+ shorter, more probable codes, and then point to subsidiary tables for -+ the longer codes. The time it costs to decode the longer codes is -+ then traded against the time it takes to make longer tables. -+ -+ This results of this trade are in the variables lbits and dbits -+ below. lbits is the number of bits the first level table for literal/ -+ length codes can decode in one step, and dbits is the same thing for -+ the distance codes. Subsequent tables are also less than or equal to -+ those sizes. These values may be adjusted either when all of the -+ codes are shorter than that, in which case the longest code length in -+ bits is used, or when the shortest code is *longer* than the requested -+ table size, in which case the length of the shortest code in bits is -+ used. -+ -+ There are two different values for the two tables, since they code a -+ different number of possibilities each. The literal/length table -+ codes 286 possible values, or in a flat code, a little over eight -+ bits. The distance table codes 30 possible values, or a little less -+ than five bits, flat. The optimum values for speed end up being -+ about one bit more than those, so lbits is 8+1 and dbits is 5+1. -+ The optimum values may differ though from machine to machine, and -+ possibly even between compilers. Your mileage may vary. -+ */ -+ -+ -+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ -+#define BMAX 15 /* maximum bit length of any code */ -+ -+local int huft_build(b, n, s, d, e, t, m, hp, hn, v) -+uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ -+uInt n; /* number of codes (assumed <= 288) */ -+uInt s; /* number of simple-valued codes (0..s-1) */ -+const uIntf *d; /* list of base values for non-simple codes */ -+const uIntf *e; /* list of extra bits for non-simple codes */ -+inflate_huft * FAR *t; /* result: starting table */ -+uIntf *m; /* maximum lookup bits, returns actual */ -+inflate_huft *hp; /* space for trees */ -+uInt *hn; /* hufts used in space */ -+uIntf *v; /* working area: values in order of bit length */ -+/* Given a list of code lengths and a maximum table size, make a set of -+ tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR -+ if the given code set is incomplete (the tables are still built in this -+ case), or Z_DATA_ERROR if the input is invalid. */ -+{ -+ -+ uInt a; /* counter for codes of length k */ -+ uInt c[BMAX+1]; /* bit length count table */ -+ uInt f; /* i repeats in table every f entries */ -+ int g; /* maximum code length */ -+ int h; /* table level */ -+ register uInt i; /* counter, current code */ -+ register uInt j; /* counter */ -+ register int k; /* number of bits in current code */ -+ int l; /* bits per table (returned in m) */ -+ uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ -+ register uIntf *p; /* pointer into c[], b[], or v[] */ -+ inflate_huft *q; /* points to current table */ -+ struct inflate_huft_s r; /* table entry for structure assignment */ -+ inflate_huft *u[BMAX]; /* table stack */ -+ register int w; /* bits before this table == (l * h) */ -+ uInt x[BMAX+1]; /* bit offsets, then code stack */ -+ uIntf *xp; /* pointer into x */ -+ int y; /* number of dummy codes added */ -+ uInt z; /* number of entries in current table */ -+ -+ -+ /* Generate counts for each bit length */ -+ p = c; -+#define C0 *p++ = 0; -+#define C2 C0 C0 C0 C0 -+#define C4 C2 C2 C2 C2 -+ C4 /* clear c[]--assume BMAX+1 is 16 */ -+ p = b; i = n; -+ do { -+ c[*p++]++; /* assume all entries <= BMAX */ -+ } while (--i); -+ if (c[0] == n) /* null input--all zero length codes */ -+ { -+ *t = (inflate_huft *)Z_NULL; -+ *m = 0; -+ return Z_OK; -+ } -+ -+ -+ /* Find minimum and maximum length, bound *m by those */ -+ l = *m; -+ for (j = 1; j <= BMAX; j++) -+ if (c[j]) -+ break; -+ k = j; /* minimum code length */ -+ if ((uInt)l < j) -+ l = j; -+ for (i = BMAX; i; i--) -+ if (c[i]) -+ break; -+ g = i; /* maximum code length */ -+ if ((uInt)l > i) -+ l = i; -+ *m = l; -+ -+ -+ /* Adjust last length count to fill out codes, if needed */ -+ for (y = 1 << j; j < i; j++, y <<= 1) -+ if ((y -= c[j]) < 0) -+ return Z_DATA_ERROR; -+ if ((y -= c[i]) < 0) -+ return Z_DATA_ERROR; -+ c[i] += y; -+ -+ -+ /* Generate starting offsets into the value table for each length */ -+ x[1] = j = 0; -+ p = c + 1; xp = x + 2; -+ while (--i) { /* note that i == g from above */ -+ *xp++ = (j += *p++); -+ } -+ -+ -+ /* Make a table of values in order of bit lengths */ -+ p = b; i = 0; -+ do { -+ if ((j = *p++) != 0) -+ v[x[j]++] = i; -+ } while (++i < n); -+ n = x[g]; /* set n to length of v */ -+ -+ -+ /* Generate the Huffman codes and for each, make the table entries */ -+ x[0] = i = 0; /* first Huffman code is zero */ -+ p = v; /* grab values in bit order */ -+ h = -1; /* no tables yet--level -1 */ -+ w = -l; /* bits decoded == (l * h) */ -+ u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ -+ q = (inflate_huft *)Z_NULL; /* ditto */ -+ z = 0; /* ditto */ -+ -+ /* go through the bit lengths (k already is bits in shortest code) */ -+ for (; k <= g; k++) -+ { -+ a = c[k]; -+ while (a--) -+ { -+ /* here i is the Huffman code of length k bits for value *p */ -+ /* make tables up to required level */ -+ while (k > w + l) -+ { -+ h++; -+ w += l; /* previous table always l bits */ -+ -+ /* compute minimum size table less than or equal to l bits */ -+ z = g - w; -+ z = z > (uInt)l ? l : z; /* table size upper limit */ -+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ -+ { /* too few codes for k-w bit table */ -+ f -= a + 1; /* deduct codes from patterns left */ -+ xp = c + k; -+ if (j < z) -+ while (++j < z) /* try smaller tables up to z bits */ -+ { -+ if ((f <<= 1) <= *++xp) -+ break; /* enough codes to use up j bits */ -+ f -= *xp; /* else deduct codes from patterns */ -+ } -+ } -+ z = 1 << j; /* table entries for j-bit table */ -+ -+ /* allocate new table */ -+ if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ -+ return Z_DATA_ERROR; /* overflow of MANY */ -+ u[h] = q = hp + *hn; -+ *hn += z; -+ -+ /* connect to last table, if there is one */ -+ if (h) -+ { -+ x[h] = i; /* save pattern for backing up */ -+ r.bits = (Byte)l; /* bits to dump before this table */ -+ r.exop = (Byte)j; /* bits in this table */ -+ j = i >> (w - l); -+ r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ -+ u[h-1][j] = r; /* connect to last table */ -+ } -+ else -+ *t = q; /* first table is returned result */ -+ } -+ -+ /* set up table entry in r */ -+ r.bits = (Byte)(k - w); -+ if (p >= v + n) -+ r.exop = 128 + 64; /* out of values--invalid code */ -+ else if (*p < s) -+ { -+ r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ -+ r.base = *p++; /* simple code is just the value */ -+ } -+ else -+ { -+ r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ -+ r.base = d[*p++ - s]; -+ } -+ -+ /* fill code-like entries with r */ -+ f = 1 << (k - w); -+ for (j = i >> w; j < z; j += f) -+ q[j] = r; -+ -+ /* backwards increment the k-bit code i */ -+ for (j = 1 << (k - 1); i & j; j >>= 1) -+ i ^= j; -+ i ^= j; -+ -+ /* backup over finished tables */ -+ mask = (1 << w) - 1; /* needed on HP, cc -O bug */ -+ while ((i & mask) != x[h]) -+ { -+ h--; /* don't need to update q */ -+ w -= l; -+ mask = (1 << w) - 1; -+ } -+ } -+ } -+ -+ -+ /* Return Z_BUF_ERROR if we were given an incomplete table */ -+ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; -+} -+ -+ -+int inflate_trees_bits(c, bb, tb, hp, z) -+uIntf *c; /* 19 code lengths */ -+uIntf *bb; /* bits tree desired/actual depth */ -+inflate_huft * FAR *tb; /* bits tree result */ -+inflate_huft *hp; /* space for trees */ -+z_streamp z; /* for messages */ -+{ -+ int r; -+ uInt hn = 0; /* hufts used in space */ -+ uIntf *v; /* work area for huft_build */ -+ -+ if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) -+ return Z_MEM_ERROR; -+ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, -+ tb, bb, hp, &hn, v); -+ if (r == Z_DATA_ERROR) -+ z->msg = (char*)"oversubscribed dynamic bit lengths tree"; -+ else if (r == Z_BUF_ERROR || *bb == 0) -+ { -+ z->msg = (char*)"incomplete dynamic bit lengths tree"; -+ r = Z_DATA_ERROR; -+ } -+ ZFREE(z, v); -+ return r; -+} -+ -+ -+int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z) -+uInt nl; /* number of literal/length codes */ -+uInt nd; /* number of distance codes */ -+uIntf *c; /* that many (total) code lengths */ -+uIntf *bl; /* literal desired/actual bit depth */ -+uIntf *bd; /* distance desired/actual bit depth */ -+inflate_huft * FAR *tl; /* literal/length tree result */ -+inflate_huft * FAR *td; /* distance tree result */ -+inflate_huft *hp; /* space for trees */ -+z_streamp z; /* for messages */ -+{ -+ int r; -+ uInt hn = 0; /* hufts used in space */ -+ uIntf *v; /* work area for huft_build */ -+ -+ /* allocate work area */ -+ if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) -+ return Z_MEM_ERROR; -+ -+ /* build literal/length tree */ -+ r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); -+ if (r != Z_OK || *bl == 0) -+ { -+ if (r == Z_DATA_ERROR) -+ z->msg = (char*)"oversubscribed literal/length tree"; -+ else if (r != Z_MEM_ERROR) -+ { -+ z->msg = (char*)"incomplete literal/length tree"; -+ r = Z_DATA_ERROR; -+ } -+ ZFREE(z, v); -+ return r; -+ } -+ -+ /* build distance tree */ -+ r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); -+ if (r != Z_OK || (*bd == 0 && nl > 257)) -+ { -+ if (r == Z_DATA_ERROR) -+ z->msg = (char*)"oversubscribed distance tree"; -+ else if (r == Z_BUF_ERROR) { -+#ifdef PKZIP_BUG_WORKAROUND -+ r = Z_OK; -+ } -+#else -+ z->msg = (char*)"incomplete distance tree"; -+ r = Z_DATA_ERROR; -+ } -+ else if (r != Z_MEM_ERROR) -+ { -+ z->msg = (char*)"empty distance tree with lengths"; -+ r = Z_DATA_ERROR; -+ } -+ ZFREE(z, v); -+ return r; -+#endif -+ } -+ -+ /* done */ -+ ZFREE(z, v); -+ return Z_OK; -+} -+ -+ -+/* build fixed tables only once--keep them here */ -+#ifdef BUILDFIXED -+local int fixed_built = 0; -+#define FIXEDH 544 /* number of hufts used by fixed tables */ -+local inflate_huft fixed_mem[FIXEDH]; -+local uInt fixed_bl; -+local uInt fixed_bd; -+local inflate_huft *fixed_tl; -+local inflate_huft *fixed_td; -+#else -+#include "inffixed.h" -+#endif -+ -+ -+int inflate_trees_fixed(bl, bd, tl, td, z) -+uIntf *bl; /* literal desired/actual bit depth */ -+uIntf *bd; /* distance desired/actual bit depth */ -+inflate_huft * FAR *tl; /* literal/length tree result */ -+inflate_huft * FAR *td; /* distance tree result */ -+z_streamp z; /* for memory allocation */ -+{ -+#ifdef BUILDFIXED -+ /* build fixed tables if not already */ -+ if (!fixed_built) -+ { -+ int k; /* temporary variable */ -+ uInt f = 0; /* number of hufts used in fixed_mem */ -+ uIntf *c; /* length list for huft_build */ -+ uIntf *v; /* work area for huft_build */ -+ -+ /* allocate memory */ -+ if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) -+ return Z_MEM_ERROR; -+ if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) -+ { -+ ZFREE(z, c); -+ return Z_MEM_ERROR; -+ } -+ -+ /* literal table */ -+ for (k = 0; k < 144; k++) -+ c[k] = 8; -+ for (; k < 256; k++) -+ c[k] = 9; -+ for (; k < 280; k++) -+ c[k] = 7; -+ for (; k < 288; k++) -+ c[k] = 8; -+ fixed_bl = 9; -+ huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, -+ fixed_mem, &f, v); -+ -+ /* distance table */ -+ for (k = 0; k < 30; k++) -+ c[k] = 5; -+ fixed_bd = 5; -+ huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, -+ fixed_mem, &f, v); -+ -+ /* done */ -+ ZFREE(z, v); -+ ZFREE(z, c); -+ fixed_built = 1; -+ } -+#endif -+ *bl = fixed_bl; -+ *bd = fixed_bd; -+ *tl = fixed_tl; -+ *td = fixed_td; -+ return Z_OK; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/inftrees.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,63 @@ -+/* inftrees.h -- header to use inftrees.c -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+/* Huffman code lookup table entry--this entry is four bytes for machines -+ that have 16-bit pointers (e.g. PC's in the small or medium model). */ -+ -+#ifndef _INFTREES_H -+#define _INFTREES_H -+ -+typedef struct inflate_huft_s FAR inflate_huft; -+ -+struct inflate_huft_s { -+ union { -+ struct { -+ Byte Exop; /* number of extra bits or operation */ -+ Byte Bits; /* number of bits in this code or subcode */ -+ } what; -+ uInt pad; /* pad structure to a power of 2 (4 bytes for */ -+ } word; /* 16-bit, 8 bytes for 32-bit int's) */ -+ uInt base; /* literal, length base, distance base, -+ or table offset */ -+}; -+ -+/* Maximum size of dynamic tree. The maximum found in a long but non- -+ exhaustive search was 1004 huft structures (850 for length/literals -+ and 154 for distances, the latter actually the result of an -+ exhaustive search). The actual maximum is not known, but the -+ value below is more than safe. */ -+#define MANY 1440 -+ -+extern int inflate_trees_bits OF(( -+ uIntf *, /* 19 code lengths */ -+ uIntf *, /* bits tree desired/actual depth */ -+ inflate_huft * FAR *, /* bits tree result */ -+ inflate_huft *, /* space for trees */ -+ z_streamp)); /* for messages */ -+ -+extern int inflate_trees_dynamic OF(( -+ uInt, /* number of literal/length codes */ -+ uInt, /* number of distance codes */ -+ uIntf *, /* that many (total) code lengths */ -+ uIntf *, /* literal desired/actual bit depth */ -+ uIntf *, /* distance desired/actual bit depth */ -+ inflate_huft * FAR *, /* literal/length tree result */ -+ inflate_huft * FAR *, /* distance tree result */ -+ inflate_huft *, /* space for trees */ -+ z_streamp)); /* for messages */ -+ -+extern int inflate_trees_fixed OF(( -+ uIntf *, /* literal desired/actual bit depth */ -+ uIntf *, /* distance desired/actual bit depth */ -+ inflate_huft * FAR *, /* literal/length tree result */ -+ inflate_huft * FAR *, /* distance tree result */ -+ z_streamp)); /* for memory allocation */ -+ -+#endif /* _INFTREES_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/infutil.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,87 @@ -+/* inflate_util.c -- data and routines common to blocks and codes -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+#include -+#include "infblock.h" -+#include "inftrees.h" -+#include "infcodes.h" -+#include "infutil.h" -+ -+struct inflate_codes_state {int dummy;}; /* for buggy compilers */ -+ -+/* And'ing with mask[n] masks the lower n bits */ -+uInt inflate_mask[17] = { -+ 0x0000, -+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, -+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -+}; -+ -+ -+/* copy as much as possible from the sliding window to the output area */ -+int inflate_flush(s, z, r) -+inflate_blocks_statef *s; -+z_streamp z; -+int r; -+{ -+ uInt n; -+ Bytef *p; -+ Bytef *q; -+ -+ /* local copies of source and destination pointers */ -+ p = z->next_out; -+ q = s->read; -+ -+ /* compute number of bytes to copy as far as end of window */ -+ n = (uInt)((q <= s->write ? s->write : s->end) - q); -+ if (n > z->avail_out) n = z->avail_out; -+ if (n && r == Z_BUF_ERROR) r = Z_OK; -+ -+ /* update counters */ -+ z->avail_out -= n; -+ z->total_out += n; -+ -+ /* update check information */ -+ if (s->checkfn != Z_NULL) -+ z->adler = s->check = (*s->checkfn)(s->check, q, n); -+ -+ /* copy as far as end of window */ -+ zmemcpy(p, q, n); -+ p += n; -+ q += n; -+ -+ /* see if more to copy at beginning of window */ -+ if (q == s->end) -+ { -+ /* wrap pointers */ -+ q = s->window; -+ if (s->write == s->end) -+ s->write = s->window; -+ -+ /* compute bytes to copy */ -+ n = (uInt)(s->write - q); -+ if (n > z->avail_out) n = z->avail_out; -+ if (n && r == Z_BUF_ERROR) r = Z_OK; -+ -+ /* update counters */ -+ z->avail_out -= n; -+ z->total_out += n; -+ -+ /* update check information */ -+ if (s->checkfn != Z_NULL) -+ z->adler = s->check = (*s->checkfn)(s->check, q, n); -+ -+ /* copy */ -+ zmemcpy(p, q, n); -+ p += n; -+ q += n; -+ } -+ -+ /* update pointers */ -+ z->next_out = p; -+ s->read = q; -+ -+ /* done */ -+ return r; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/infutil.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,98 @@ -+/* infutil.h -- types and macros common to blocks and codes -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+#ifndef _INFUTIL_H -+#define _INFUTIL_H -+ -+typedef enum { -+ TYPE, /* get type bits (3, including end bit) */ -+ LENS, /* get lengths for stored */ -+ STORED, /* processing stored block */ -+ TABLE, /* get table lengths */ -+ BTREE, /* get bit lengths tree for a dynamic block */ -+ DTREE, /* get length, distance trees for a dynamic block */ -+ CODES, /* processing fixed or dynamic block */ -+ DRY, /* output remaining window bytes */ -+ DONE, /* finished last block, done */ -+ BAD} /* got a data error--stuck here */ -+inflate_block_mode; -+ -+/* inflate blocks semi-private state */ -+struct inflate_blocks_state { -+ -+ /* mode */ -+ inflate_block_mode mode; /* current inflate_block mode */ -+ -+ /* mode dependent information */ -+ union { -+ uInt left; /* if STORED, bytes left to copy */ -+ struct { -+ uInt table; /* table lengths (14 bits) */ -+ uInt index; /* index into blens (or border) */ -+ uIntf *blens; /* bit lengths of codes */ -+ uInt bb; /* bit length tree depth */ -+ inflate_huft *tb; /* bit length decoding tree */ -+ } trees; /* if DTREE, decoding info for trees */ -+ struct { -+ inflate_codes_statef -+ *codes; -+ } decode; /* if CODES, current state */ -+ } sub; /* submode */ -+ uInt last; /* true if this block is the last block */ -+ -+ /* mode independent information */ -+ uInt bitk; /* bits in bit buffer */ -+ uLong bitb; /* bit buffer */ -+ inflate_huft *hufts; /* single malloc for tree space */ -+ Bytef *window; /* sliding window */ -+ Bytef *end; /* one byte after sliding window */ -+ Bytef *read; /* window read pointer */ -+ Bytef *write; /* window write pointer */ -+ check_func checkfn; /* check function */ -+ uLong check; /* check on output */ -+ -+}; -+ -+ -+/* defines for inflate input/output */ -+/* update pointers and return */ -+#define UPDBITS {s->bitb=b;s->bitk=k;} -+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} -+#define UPDOUT {s->write=q;} -+#define UPDATE {UPDBITS UPDIN UPDOUT} -+#define LEAVE {UPDATE return inflate_flush(s,z,r);} -+/* get bytes and bits */ -+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} -+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} -+#define NEXTBYTE (n--,*p++) -+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} -+/* output bytes */ -+#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) -+#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} -+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} -+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} -+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} -+#define OUTBYTE(a) {*q++=(Byte)(a);m--;} -+/* load local pointers */ -+#define LOAD {LOADIN LOADOUT} -+ -+/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ -+extern uInt inflate_mask[17]; -+ -+/* copy as much as possible from the sliding window to the output area */ -+extern int inflate_flush OF(( -+ inflate_blocks_statef *, -+ z_streamp , -+ int)); -+ -+struct internal_state {int dummy;}; /* for buggy compilers */ -+ -+#endif /* _INFUTIL_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/match586.S Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,357 @@ -+/* match.s -- Pentium-optimized version of longest_match() -+ * Written for zlib 1.1.2 -+ * Copyright (C) 1998 Brian Raiter -+ * -+ * This is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License. -+ */ -+ -+#ifndef NO_UNDERLINE -+#define match_init _ipcomp_match_init -+#define longest_match _ipcomp_longest_match -+#else -+#define match_init ipcomp_match_init -+#define longest_match ipcomp_longest_match -+#endif -+ -+#define MAX_MATCH (258) -+#define MIN_MATCH (3) -+#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) -+#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) -+ -+/* stack frame offsets */ -+ -+#define wmask 0 /* local copy of s->wmask */ -+#define window 4 /* local copy of s->window */ -+#define windowbestlen 8 /* s->window + bestlen */ -+#define chainlenscanend 12 /* high word: current chain len */ -+ /* low word: last bytes sought */ -+#define scanstart 16 /* first two bytes of string */ -+#define scanalign 20 /* dword-misalignment of string */ -+#define nicematch 24 /* a good enough match size */ -+#define bestlen 28 /* size of best match so far */ -+#define scan 32 /* ptr to string wanting match */ -+ -+#define LocalVarsSize (36) -+/* saved ebx 36 */ -+/* saved edi 40 */ -+/* saved esi 44 */ -+/* saved ebp 48 */ -+/* return address 52 */ -+#define deflatestate 56 /* the function arguments */ -+#define curmatch 60 -+ -+/* Offsets for fields in the deflate_state structure. These numbers -+ * are calculated from the definition of deflate_state, with the -+ * assumption that the compiler will dword-align the fields. (Thus, -+ * changing the definition of deflate_state could easily cause this -+ * program to crash horribly, without so much as a warning at -+ * compile time. Sigh.) -+ */ -+#define dsWSize 36 -+#define dsWMask 44 -+#define dsWindow 48 -+#define dsPrev 56 -+#define dsMatchLen 88 -+#define dsPrevMatch 92 -+#define dsStrStart 100 -+#define dsMatchStart 104 -+#define dsLookahead 108 -+#define dsPrevLen 112 -+#define dsMaxChainLen 116 -+#define dsGoodMatch 132 -+#define dsNiceMatch 136 -+ -+ -+.file "match.S" -+ -+.globl match_init, longest_match -+ -+.text -+ -+/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ -+ -+longest_match: -+ -+/* Save registers that the compiler may be using, and adjust %esp to */ -+/* make room for our stack frame. */ -+ -+ pushl %ebp -+ pushl %edi -+ pushl %esi -+ pushl %ebx -+ subl $LocalVarsSize, %esp -+ -+/* Retrieve the function arguments. %ecx will hold cur_match */ -+/* throughout the entire function. %edx will hold the pointer to the */ -+/* deflate_state structure during the function's setup (before */ -+/* entering the main loop). */ -+ -+ movl deflatestate(%esp), %edx -+ movl curmatch(%esp), %ecx -+ -+/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ -+ -+ movl dsNiceMatch(%edx), %eax -+ movl dsLookahead(%edx), %ebx -+ cmpl %eax, %ebx -+ jl LookaheadLess -+ movl %eax, %ebx -+LookaheadLess: movl %ebx, nicematch(%esp) -+ -+/* register Bytef *scan = s->window + s->strstart; */ -+ -+ movl dsWindow(%edx), %esi -+ movl %esi, window(%esp) -+ movl dsStrStart(%edx), %ebp -+ lea (%esi,%ebp), %edi -+ movl %edi, scan(%esp) -+ -+/* Determine how many bytes the scan ptr is off from being */ -+/* dword-aligned. */ -+ -+ movl %edi, %eax -+ negl %eax -+ andl $3, %eax -+ movl %eax, scanalign(%esp) -+ -+/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ -+/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ -+ -+ movl dsWSize(%edx), %eax -+ subl $MIN_LOOKAHEAD, %eax -+ subl %eax, %ebp -+ jg LimitPositive -+ xorl %ebp, %ebp -+LimitPositive: -+ -+/* unsigned chain_length = s->max_chain_length; */ -+/* if (s->prev_length >= s->good_match) { */ -+/* chain_length >>= 2; */ -+/* } */ -+ -+ movl dsPrevLen(%edx), %eax -+ movl dsGoodMatch(%edx), %ebx -+ cmpl %ebx, %eax -+ movl dsMaxChainLen(%edx), %ebx -+ jl LastMatchGood -+ shrl $2, %ebx -+LastMatchGood: -+ -+/* chainlen is decremented once beforehand so that the function can */ -+/* use the sign flag instead of the zero flag for the exit test. */ -+/* It is then shifted into the high word, to make room for the scanend */ -+/* scanend value, which it will always accompany. */ -+ -+ decl %ebx -+ shll $16, %ebx -+ -+/* int best_len = s->prev_length; */ -+ -+ movl dsPrevLen(%edx), %eax -+ movl %eax, bestlen(%esp) -+ -+/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ -+ -+ addl %eax, %esi -+ movl %esi, windowbestlen(%esp) -+ -+/* register ush scan_start = *(ushf*)scan; */ -+/* register ush scan_end = *(ushf*)(scan+best_len-1); */ -+ -+ movw (%edi), %bx -+ movw %bx, scanstart(%esp) -+ movw -1(%edi,%eax), %bx -+ movl %ebx, chainlenscanend(%esp) -+ -+/* Posf *prev = s->prev; */ -+/* uInt wmask = s->w_mask; */ -+ -+ movl dsPrev(%edx), %edi -+ movl dsWMask(%edx), %edx -+ mov %edx, wmask(%esp) -+ -+/* Jump into the main loop. */ -+ -+ jmp LoopEntry -+ -+.balign 16 -+ -+/* do { -+ * match = s->window + cur_match; -+ * if (*(ushf*)(match+best_len-1) != scan_end || -+ * *(ushf*)match != scan_start) continue; -+ * [...] -+ * } while ((cur_match = prev[cur_match & wmask]) > limit -+ * && --chain_length != 0); -+ * -+ * Here is the inner loop of the function. The function will spend the -+ * majority of its time in this loop, and majority of that time will -+ * be spent in the first ten instructions. -+ * -+ * Within this loop: -+ * %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend) -+ * %ecx = curmatch -+ * %edx = curmatch & wmask -+ * %esi = windowbestlen - i.e., (window + bestlen) -+ * %edi = prev -+ * %ebp = limit -+ * -+ * Two optimization notes on the choice of instructions: -+ * -+ * The first instruction uses a 16-bit address, which costs an extra, -+ * unpairable cycle. This is cheaper than doing a 32-bit access and -+ * zeroing the high word, due to the 3-cycle misalignment penalty which -+ * would occur half the time. This also turns out to be cheaper than -+ * doing two separate 8-bit accesses, as the memory is so rarely in the -+ * L1 cache. -+ * -+ * The window buffer, however, apparently spends a lot of time in the -+ * cache, and so it is faster to retrieve the word at the end of the -+ * match string with two 8-bit loads. The instructions that test the -+ * word at the beginning of the match string, however, are executed -+ * much less frequently, and there it was cheaper to use 16-bit -+ * instructions, which avoided the necessity of saving off and -+ * subsequently reloading one of the other registers. -+ */ -+LookupLoop: -+ /* 1 U & V */ -+ movw (%edi,%edx,2), %cx /* 2 U pipe */ -+ movl wmask(%esp), %edx /* 2 V pipe */ -+ cmpl %ebp, %ecx /* 3 U pipe */ -+ jbe LeaveNow /* 3 V pipe */ -+ subl $0x00010000, %ebx /* 4 U pipe */ -+ js LeaveNow /* 4 V pipe */ -+LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */ -+ andl %ecx, %edx /* 5 V pipe */ -+ cmpb %bl, %al /* 6 U pipe */ -+ jnz LookupLoop /* 6 V pipe */ -+ movb (%esi,%ecx), %ah -+ cmpb %bh, %ah -+ jnz LookupLoop -+ movl window(%esp), %eax -+ movw (%eax,%ecx), %ax -+ cmpw scanstart(%esp), %ax -+ jnz LookupLoop -+ -+/* Store the current value of chainlen. */ -+ -+ movl %ebx, chainlenscanend(%esp) -+ -+/* Point %edi to the string under scrutiny, and %esi to the string we */ -+/* are hoping to match it up with. In actuality, %esi and %edi are */ -+/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ -+/* initialized to -(MAX_MATCH_8 - scanalign). */ -+ -+ movl window(%esp), %esi -+ movl scan(%esp), %edi -+ addl %ecx, %esi -+ movl scanalign(%esp), %eax -+ movl $(-MAX_MATCH_8), %edx -+ lea MAX_MATCH_8(%edi,%eax), %edi -+ lea MAX_MATCH_8(%esi,%eax), %esi -+ -+/* Test the strings for equality, 8 bytes at a time. At the end, -+ * adjust %edx so that it is offset to the exact byte that mismatched. -+ * -+ * We already know at this point that the first three bytes of the -+ * strings match each other, and they can be safely passed over before -+ * starting the compare loop. So what this code does is skip over 0-3 -+ * bytes, as much as necessary in order to dword-align the %edi -+ * pointer. (%esi will still be misaligned three times out of four.) -+ * -+ * It should be confessed that this loop usually does not represent -+ * much of the total running time. Replacing it with a more -+ * straightforward "rep cmpsb" would not drastically degrade -+ * performance. -+ */ -+LoopCmps: -+ movl (%esi,%edx), %eax -+ movl (%edi,%edx), %ebx -+ xorl %ebx, %eax -+ jnz LeaveLoopCmps -+ movl 4(%esi,%edx), %eax -+ movl 4(%edi,%edx), %ebx -+ xorl %ebx, %eax -+ jnz LeaveLoopCmps4 -+ addl $8, %edx -+ jnz LoopCmps -+ jmp LenMaximum -+LeaveLoopCmps4: addl $4, %edx -+LeaveLoopCmps: testl $0x0000FFFF, %eax -+ jnz LenLower -+ addl $2, %edx -+ shrl $16, %eax -+LenLower: subb $1, %al -+ adcl $0, %edx -+ -+/* Calculate the length of the match. If it is longer than MAX_MATCH, */ -+/* then automatically accept it as the best possible match and leave. */ -+ -+ lea (%edi,%edx), %eax -+ movl scan(%esp), %edi -+ subl %edi, %eax -+ cmpl $MAX_MATCH, %eax -+ jge LenMaximum -+ -+/* If the length of the match is not longer than the best match we */ -+/* have so far, then forget it and return to the lookup loop. */ -+ -+ movl deflatestate(%esp), %edx -+ movl bestlen(%esp), %ebx -+ cmpl %ebx, %eax -+ jg LongerMatch -+ movl chainlenscanend(%esp), %ebx -+ movl windowbestlen(%esp), %esi -+ movl dsPrev(%edx), %edi -+ movl wmask(%esp), %edx -+ andl %ecx, %edx -+ jmp LookupLoop -+ -+/* s->match_start = cur_match; */ -+/* best_len = len; */ -+/* if (len >= nice_match) break; */ -+/* scan_end = *(ushf*)(scan+best_len-1); */ -+ -+LongerMatch: movl nicematch(%esp), %ebx -+ movl %eax, bestlen(%esp) -+ movl %ecx, dsMatchStart(%edx) -+ cmpl %ebx, %eax -+ jge LeaveNow -+ movl window(%esp), %esi -+ addl %eax, %esi -+ movl %esi, windowbestlen(%esp) -+ movl chainlenscanend(%esp), %ebx -+ movw -1(%edi,%eax), %bx -+ movl dsPrev(%edx), %edi -+ movl %ebx, chainlenscanend(%esp) -+ movl wmask(%esp), %edx -+ andl %ecx, %edx -+ jmp LookupLoop -+ -+/* Accept the current string, with the maximum possible length. */ -+ -+LenMaximum: movl deflatestate(%esp), %edx -+ movl $MAX_MATCH, bestlen(%esp) -+ movl %ecx, dsMatchStart(%edx) -+ -+/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ -+/* return s->lookahead; */ -+ -+LeaveNow: -+ movl deflatestate(%esp), %edx -+ movl bestlen(%esp), %ebx -+ movl dsLookahead(%edx), %eax -+ cmpl %eax, %ebx -+ jg LookaheadRet -+ movl %ebx, %eax -+LookaheadRet: -+ -+/* Restore the stack and return from whence we came. */ -+ -+ addl $LocalVarsSize, %esp -+ popl %ebx -+ popl %esi -+ popl %edi -+ popl %ebp -+match_init: ret ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/match686.S Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,330 @@ -+/* match.s -- Pentium-Pro-optimized version of longest_match() -+ * Written for zlib 1.1.2 -+ * Copyright (C) 1998 Brian Raiter -+ * -+ * This is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License. -+ */ -+ -+#ifndef NO_UNDERLINE -+#define match_init _ipcomp_match_init -+#define longest_match _ipcomp_longest_match -+#else -+#define match_init ipcomp_match_init -+#define longest_match ipcomp_longest_match -+#endif -+ -+#define MAX_MATCH (258) -+#define MIN_MATCH (3) -+#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) -+#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) -+ -+/* stack frame offsets */ -+ -+#define chainlenwmask 0 /* high word: current chain len */ -+ /* low word: s->wmask */ -+#define window 4 /* local copy of s->window */ -+#define windowbestlen 8 /* s->window + bestlen */ -+#define scanstart 16 /* first two bytes of string */ -+#define scanend 12 /* last two bytes of string */ -+#define scanalign 20 /* dword-misalignment of string */ -+#define nicematch 24 /* a good enough match size */ -+#define bestlen 28 /* size of best match so far */ -+#define scan 32 /* ptr to string wanting match */ -+ -+#define LocalVarsSize (36) -+/* saved ebx 36 */ -+/* saved edi 40 */ -+/* saved esi 44 */ -+/* saved ebp 48 */ -+/* return address 52 */ -+#define deflatestate 56 /* the function arguments */ -+#define curmatch 60 -+ -+/* Offsets for fields in the deflate_state structure. These numbers -+ * are calculated from the definition of deflate_state, with the -+ * assumption that the compiler will dword-align the fields. (Thus, -+ * changing the definition of deflate_state could easily cause this -+ * program to crash horribly, without so much as a warning at -+ * compile time. Sigh.) -+ */ -+#define dsWSize 36 -+#define dsWMask 44 -+#define dsWindow 48 -+#define dsPrev 56 -+#define dsMatchLen 88 -+#define dsPrevMatch 92 -+#define dsStrStart 100 -+#define dsMatchStart 104 -+#define dsLookahead 108 -+#define dsPrevLen 112 -+#define dsMaxChainLen 116 -+#define dsGoodMatch 132 -+#define dsNiceMatch 136 -+ -+ -+.file "match.S" -+ -+.globl match_init, longest_match -+ -+.text -+ -+/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ -+ -+longest_match: -+ -+/* Save registers that the compiler may be using, and adjust %esp to */ -+/* make room for our stack frame. */ -+ -+ pushl %ebp -+ pushl %edi -+ pushl %esi -+ pushl %ebx -+ subl $LocalVarsSize, %esp -+ -+/* Retrieve the function arguments. %ecx will hold cur_match */ -+/* throughout the entire function. %edx will hold the pointer to the */ -+/* deflate_state structure during the function's setup (before */ -+/* entering the main loop). */ -+ -+ movl deflatestate(%esp), %edx -+ movl curmatch(%esp), %ecx -+ -+/* uInt wmask = s->w_mask; */ -+/* unsigned chain_length = s->max_chain_length; */ -+/* if (s->prev_length >= s->good_match) { */ -+/* chain_length >>= 2; */ -+/* } */ -+ -+ movl dsPrevLen(%edx), %eax -+ movl dsGoodMatch(%edx), %ebx -+ cmpl %ebx, %eax -+ movl dsWMask(%edx), %eax -+ movl dsMaxChainLen(%edx), %ebx -+ jl LastMatchGood -+ shrl $2, %ebx -+LastMatchGood: -+ -+/* chainlen is decremented once beforehand so that the function can */ -+/* use the sign flag instead of the zero flag for the exit test. */ -+/* It is then shifted into the high word, to make room for the wmask */ -+/* value, which it will always accompany. */ -+ -+ decl %ebx -+ shll $16, %ebx -+ orl %eax, %ebx -+ movl %ebx, chainlenwmask(%esp) -+ -+/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ -+ -+ movl dsNiceMatch(%edx), %eax -+ movl dsLookahead(%edx), %ebx -+ cmpl %eax, %ebx -+ jl LookaheadLess -+ movl %eax, %ebx -+LookaheadLess: movl %ebx, nicematch(%esp) -+ -+/* register Bytef *scan = s->window + s->strstart; */ -+ -+ movl dsWindow(%edx), %esi -+ movl %esi, window(%esp) -+ movl dsStrStart(%edx), %ebp -+ lea (%esi,%ebp), %edi -+ movl %edi, scan(%esp) -+ -+/* Determine how many bytes the scan ptr is off from being */ -+/* dword-aligned. */ -+ -+ movl %edi, %eax -+ negl %eax -+ andl $3, %eax -+ movl %eax, scanalign(%esp) -+ -+/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ -+/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ -+ -+ movl dsWSize(%edx), %eax -+ subl $MIN_LOOKAHEAD, %eax -+ subl %eax, %ebp -+ jg LimitPositive -+ xorl %ebp, %ebp -+LimitPositive: -+ -+/* int best_len = s->prev_length; */ -+ -+ movl dsPrevLen(%edx), %eax -+ movl %eax, bestlen(%esp) -+ -+/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ -+ -+ addl %eax, %esi -+ movl %esi, windowbestlen(%esp) -+ -+/* register ush scan_start = *(ushf*)scan; */ -+/* register ush scan_end = *(ushf*)(scan+best_len-1); */ -+/* Posf *prev = s->prev; */ -+ -+ movzwl (%edi), %ebx -+ movl %ebx, scanstart(%esp) -+ movzwl -1(%edi,%eax), %ebx -+ movl %ebx, scanend(%esp) -+ movl dsPrev(%edx), %edi -+ -+/* Jump into the main loop. */ -+ -+ movl chainlenwmask(%esp), %edx -+ jmp LoopEntry -+ -+.balign 16 -+ -+/* do { -+ * match = s->window + cur_match; -+ * if (*(ushf*)(match+best_len-1) != scan_end || -+ * *(ushf*)match != scan_start) continue; -+ * [...] -+ * } while ((cur_match = prev[cur_match & wmask]) > limit -+ * && --chain_length != 0); -+ * -+ * Here is the inner loop of the function. The function will spend the -+ * majority of its time in this loop, and majority of that time will -+ * be spent in the first ten instructions. -+ * -+ * Within this loop: -+ * %ebx = scanend -+ * %ecx = curmatch -+ * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) -+ * %esi = windowbestlen - i.e., (window + bestlen) -+ * %edi = prev -+ * %ebp = limit -+ */ -+LookupLoop: -+ andl %edx, %ecx -+ movzwl (%edi,%ecx,2), %ecx -+ cmpl %ebp, %ecx -+ jbe LeaveNow -+ subl $0x00010000, %edx -+ js LeaveNow -+LoopEntry: movzwl -1(%esi,%ecx), %eax -+ cmpl %ebx, %eax -+ jnz LookupLoop -+ movl window(%esp), %eax -+ movzwl (%eax,%ecx), %eax -+ cmpl scanstart(%esp), %eax -+ jnz LookupLoop -+ -+/* Store the current value of chainlen. */ -+ -+ movl %edx, chainlenwmask(%esp) -+ -+/* Point %edi to the string under scrutiny, and %esi to the string we */ -+/* are hoping to match it up with. In actuality, %esi and %edi are */ -+/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ -+/* initialized to -(MAX_MATCH_8 - scanalign). */ -+ -+ movl window(%esp), %esi -+ movl scan(%esp), %edi -+ addl %ecx, %esi -+ movl scanalign(%esp), %eax -+ movl $(-MAX_MATCH_8), %edx -+ lea MAX_MATCH_8(%edi,%eax), %edi -+ lea MAX_MATCH_8(%esi,%eax), %esi -+ -+/* Test the strings for equality, 8 bytes at a time. At the end, -+ * adjust %edx so that it is offset to the exact byte that mismatched. -+ * -+ * We already know at this point that the first three bytes of the -+ * strings match each other, and they can be safely passed over before -+ * starting the compare loop. So what this code does is skip over 0-3 -+ * bytes, as much as necessary in order to dword-align the %edi -+ * pointer. (%esi will still be misaligned three times out of four.) -+ * -+ * It should be confessed that this loop usually does not represent -+ * much of the total running time. Replacing it with a more -+ * straightforward "rep cmpsb" would not drastically degrade -+ * performance. -+ */ -+LoopCmps: -+ movl (%esi,%edx), %eax -+ xorl (%edi,%edx), %eax -+ jnz LeaveLoopCmps -+ movl 4(%esi,%edx), %eax -+ xorl 4(%edi,%edx), %eax -+ jnz LeaveLoopCmps4 -+ addl $8, %edx -+ jnz LoopCmps -+ jmp LenMaximum -+LeaveLoopCmps4: addl $4, %edx -+LeaveLoopCmps: testl $0x0000FFFF, %eax -+ jnz LenLower -+ addl $2, %edx -+ shrl $16, %eax -+LenLower: subb $1, %al -+ adcl $0, %edx -+ -+/* Calculate the length of the match. If it is longer than MAX_MATCH, */ -+/* then automatically accept it as the best possible match and leave. */ -+ -+ lea (%edi,%edx), %eax -+ movl scan(%esp), %edi -+ subl %edi, %eax -+ cmpl $MAX_MATCH, %eax -+ jge LenMaximum -+ -+/* If the length of the match is not longer than the best match we */ -+/* have so far, then forget it and return to the lookup loop. */ -+ -+ movl deflatestate(%esp), %edx -+ movl bestlen(%esp), %ebx -+ cmpl %ebx, %eax -+ jg LongerMatch -+ movl windowbestlen(%esp), %esi -+ movl dsPrev(%edx), %edi -+ movl scanend(%esp), %ebx -+ movl chainlenwmask(%esp), %edx -+ jmp LookupLoop -+ -+/* s->match_start = cur_match; */ -+/* best_len = len; */ -+/* if (len >= nice_match) break; */ -+/* scan_end = *(ushf*)(scan+best_len-1); */ -+ -+LongerMatch: movl nicematch(%esp), %ebx -+ movl %eax, bestlen(%esp) -+ movl %ecx, dsMatchStart(%edx) -+ cmpl %ebx, %eax -+ jge LeaveNow -+ movl window(%esp), %esi -+ addl %eax, %esi -+ movl %esi, windowbestlen(%esp) -+ movzwl -1(%edi,%eax), %ebx -+ movl dsPrev(%edx), %edi -+ movl %ebx, scanend(%esp) -+ movl chainlenwmask(%esp), %edx -+ jmp LookupLoop -+ -+/* Accept the current string, with the maximum possible length. */ -+ -+LenMaximum: movl deflatestate(%esp), %edx -+ movl $MAX_MATCH, bestlen(%esp) -+ movl %ecx, dsMatchStart(%edx) -+ -+/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ -+/* return s->lookahead; */ -+ -+LeaveNow: -+ movl deflatestate(%esp), %edx -+ movl bestlen(%esp), %ebx -+ movl dsLookahead(%edx), %eax -+ cmpl %eax, %ebx -+ jg LookaheadRet -+ movl %ebx, %eax -+LookaheadRet: -+ -+/* Restore the stack and return from whence we came. */ -+ -+ addl $LocalVarsSize, %esp -+ popl %ebx -+ popl %esi -+ popl %edi -+ popl %ebp -+match_init: ret ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/trees.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1214 @@ -+/* trees.c -- output deflated data using Huffman coding -+ * Copyright (C) 1995-2002 Jean-loup Gailly -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* -+ * ALGORITHM -+ * -+ * The "deflation" process uses several Huffman trees. The more -+ * common source values are represented by shorter bit sequences. -+ * -+ * Each code tree is stored in a compressed form which is itself -+ * a Huffman encoding of the lengths of all the code strings (in -+ * ascending order by source values). The actual code strings are -+ * reconstructed from the lengths in the inflate process, as described -+ * in the deflate specification. -+ * -+ * REFERENCES -+ * -+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". -+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc -+ * -+ * Storer, James A. -+ * Data Compression: Methods and Theory, pp. 49-50. -+ * Computer Science Press, 1988. ISBN 0-7167-8156-5. -+ * -+ * Sedgewick, R. -+ * Algorithms, p290. -+ * Addison-Wesley, 1983. ISBN 0-201-06672-6. -+ */ -+ -+/* @(#) $Id$ */ -+ -+/* #define GEN_TREES_H */ -+ -+#include "deflate.h" -+ -+#ifdef DEBUG -+# include -+#endif -+ -+/* =========================================================================== -+ * Constants -+ */ -+ -+#define MAX_BL_BITS 7 -+/* Bit length codes must not exceed MAX_BL_BITS bits */ -+ -+#define END_BLOCK 256 -+/* end of block literal code */ -+ -+#define REP_3_6 16 -+/* repeat previous bit length 3-6 times (2 bits of repeat count) */ -+ -+#define REPZ_3_10 17 -+/* repeat a zero length 3-10 times (3 bits of repeat count) */ -+ -+#define REPZ_11_138 18 -+/* repeat a zero length 11-138 times (7 bits of repeat count) */ -+ -+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ -+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; -+ -+local const int extra_dbits[D_CODES] /* extra bits for each distance code */ -+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; -+ -+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ -+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; -+ -+local const uch bl_order[BL_CODES] -+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; -+/* The lengths of the bit length codes are sent in order of decreasing -+ * probability, to avoid transmitting the lengths for unused bit length codes. -+ */ -+ -+#define Buf_size (8 * 2*sizeof(char)) -+/* Number of bits used within bi_buf. (bi_buf might be implemented on -+ * more than 16 bits on some systems.) -+ */ -+ -+/* =========================================================================== -+ * Local data. These are initialized only once. -+ */ -+ -+#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ -+ -+#if defined(GEN_TREES_H) || !defined(STDC) -+/* non ANSI compilers may not accept trees.h */ -+ -+local ct_data static_ltree[L_CODES+2]; -+/* The static literal tree. Since the bit lengths are imposed, there is no -+ * need for the L_CODES extra codes used during heap construction. However -+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init -+ * below). -+ */ -+ -+local ct_data static_dtree[D_CODES]; -+/* The static distance tree. (Actually a trivial tree since all codes use -+ * 5 bits.) -+ */ -+ -+uch _dist_code[DIST_CODE_LEN]; -+/* Distance codes. The first 256 values correspond to the distances -+ * 3 .. 258, the last 256 values correspond to the top 8 bits of -+ * the 15 bit distances. -+ */ -+ -+uch _length_code[MAX_MATCH-MIN_MATCH+1]; -+/* length code for each normalized match length (0 == MIN_MATCH) */ -+ -+local int base_length[LENGTH_CODES]; -+/* First normalized length for each code (0 = MIN_MATCH) */ -+ -+local int base_dist[D_CODES]; -+/* First normalized distance for each code (0 = distance of 1) */ -+ -+#else -+# include "trees.h" -+#endif /* GEN_TREES_H */ -+ -+struct static_tree_desc_s { -+ const ct_data *static_tree; /* static tree or NULL */ -+ const intf *extra_bits; /* extra bits for each code or NULL */ -+ int extra_base; /* base index for extra_bits */ -+ int elems; /* max number of elements in the tree */ -+ int max_length; /* max bit length for the codes */ -+}; -+ -+local static_tree_desc static_l_desc = -+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; -+ -+local static_tree_desc static_d_desc = -+{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; -+ -+local static_tree_desc static_bl_desc = -+{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; -+ -+/* =========================================================================== -+ * Local (static) routines in this file. -+ */ -+ -+local void tr_static_init OF((void)); -+local void init_block OF((deflate_state *s)); -+local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); -+local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); -+local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); -+local void build_tree OF((deflate_state *s, tree_desc *desc)); -+local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); -+local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); -+local int build_bl_tree OF((deflate_state *s)); -+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, -+ int blcodes)); -+local void compress_block OF((deflate_state *s, const ct_data *ltree, -+ const ct_data *dtree)); -+local void set_data_type OF((deflate_state *s)); -+local unsigned bi_reverse OF((unsigned value, int length)); -+local void bi_windup OF((deflate_state *s)); -+local void bi_flush OF((deflate_state *s)); -+local void copy_block OF((deflate_state *s, charf *buf, unsigned len, -+ int header)); -+ -+#ifdef GEN_TREES_H -+local void gen_trees_header OF((void)); -+#endif -+ -+#ifndef DEBUG -+# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) -+ /* Send a code of the given tree. c and tree must not have side effects */ -+ -+#else /* DEBUG */ -+# define send_code(s, c, tree) \ -+ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ -+ send_bits(s, tree[c].Code, tree[c].Len); } -+#endif -+ -+/* =========================================================================== -+ * Output a short LSB first on the stream. -+ * IN assertion: there is enough room in pendingBuf. -+ */ -+#define put_short(s, w) { \ -+ put_byte(s, (uch)((w) & 0xff)); \ -+ put_byte(s, (uch)((ush)(w) >> 8)); \ -+} -+ -+/* =========================================================================== -+ * Send a value on a given number of bits. -+ * IN assertion: length <= 16 and value fits in length bits. -+ */ -+#ifdef DEBUG -+local void send_bits OF((deflate_state *s, int value, int length)); -+ -+local void send_bits(s, value, length) -+ deflate_state *s; -+ int value; /* value to send */ -+ int length; /* number of bits */ -+{ -+ Tracevv((stderr," l %2d v %4x ", length, value)); -+ Assert(length > 0 && length <= 15, "invalid length"); -+ s->bits_sent += (ulg)length; -+ -+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and -+ * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) -+ * unused bits in value. -+ */ -+ if (s->bi_valid > (int)Buf_size - length) { -+ s->bi_buf |= (value << s->bi_valid); -+ put_short(s, s->bi_buf); -+ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); -+ s->bi_valid += length - Buf_size; -+ } else { -+ s->bi_buf |= value << s->bi_valid; -+ s->bi_valid += length; -+ } -+} -+#else /* !DEBUG */ -+ -+#define send_bits(s, value, length) \ -+{ int len = length;\ -+ if (s->bi_valid > (int)Buf_size - len) {\ -+ int val = value;\ -+ s->bi_buf |= (val << s->bi_valid);\ -+ put_short(s, s->bi_buf);\ -+ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ -+ s->bi_valid += len - Buf_size;\ -+ } else {\ -+ s->bi_buf |= (value) << s->bi_valid;\ -+ s->bi_valid += len;\ -+ }\ -+} -+#endif /* DEBUG */ -+ -+ -+#define MAX(a,b) (a >= b ? a : b) -+/* the arguments must not have side effects */ -+ -+/* =========================================================================== -+ * Initialize the various 'constant' tables. -+ */ -+local void tr_static_init() -+{ -+#if defined(GEN_TREES_H) || !defined(STDC) -+ static int static_init_done = 0; -+ int n; /* iterates over tree elements */ -+ int bits; /* bit counter */ -+ int length; /* length value */ -+ int code; /* code value */ -+ int dist; /* distance index */ -+ ush bl_count[MAX_BITS+1]; -+ /* number of codes at each bit length for an optimal tree */ -+ -+ if (static_init_done) return; -+ -+ /* For some embedded targets, global variables are not initialized: */ -+ static_l_desc.static_tree = static_ltree; -+ static_l_desc.extra_bits = extra_lbits; -+ static_d_desc.static_tree = static_dtree; -+ static_d_desc.extra_bits = extra_dbits; -+ static_bl_desc.extra_bits = extra_blbits; -+ -+ /* Initialize the mapping length (0..255) -> length code (0..28) */ -+ length = 0; -+ for (code = 0; code < LENGTH_CODES-1; code++) { -+ base_length[code] = length; -+ for (n = 0; n < (1< dist code (0..29) */ -+ dist = 0; -+ for (code = 0 ; code < 16; code++) { -+ base_dist[code] = dist; -+ for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ -+ for ( ; code < D_CODES; code++) { -+ base_dist[code] = dist << 7; -+ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { -+ _dist_code[256 + dist++] = (uch)code; -+ } -+ } -+ Assert (dist == 256, "tr_static_init: 256+dist != 512"); -+ -+ /* Construct the codes of the static literal tree */ -+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; -+ n = 0; -+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; -+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; -+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; -+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; -+ /* Codes 286 and 287 do not exist, but we must include them in the -+ * tree construction to get a canonical Huffman tree (longest code -+ * all ones) -+ */ -+ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); -+ -+ /* The static distance tree is trivial: */ -+ for (n = 0; n < D_CODES; n++) { -+ static_dtree[n].Len = 5; -+ static_dtree[n].Code = bi_reverse((unsigned)n, 5); -+ } -+ static_init_done = 1; -+ -+# ifdef GEN_TREES_H -+ gen_trees_header(); -+# endif -+#endif /* defined(GEN_TREES_H) || !defined(STDC) */ -+} -+ -+/* =========================================================================== -+ * Genererate the file trees.h describing the static trees. -+ */ -+#ifdef GEN_TREES_H -+# ifndef DEBUG -+# include -+# endif -+ -+# define SEPARATOR(i, last, width) \ -+ ((i) == (last)? "\n};\n\n" : \ -+ ((i) % (width) == (width)-1 ? ",\n" : ", ")) -+ -+void gen_trees_header() -+{ -+ FILE *header = fopen("trees.h", "w"); -+ int i; -+ -+ Assert (header != NULL, "Can't open trees.h"); -+ fprintf(header, -+ "/* header created automatically with -DGEN_TREES_H */\n\n"); -+ -+ fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); -+ for (i = 0; i < L_CODES+2; i++) { -+ fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, -+ static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); -+ } -+ -+ fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); -+ for (i = 0; i < D_CODES; i++) { -+ fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, -+ static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); -+ } -+ -+ fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); -+ for (i = 0; i < DIST_CODE_LEN; i++) { -+ fprintf(header, "%2u%s", _dist_code[i], -+ SEPARATOR(i, DIST_CODE_LEN-1, 20)); -+ } -+ -+ fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); -+ for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { -+ fprintf(header, "%2u%s", _length_code[i], -+ SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); -+ } -+ -+ fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); -+ for (i = 0; i < LENGTH_CODES; i++) { -+ fprintf(header, "%1u%s", base_length[i], -+ SEPARATOR(i, LENGTH_CODES-1, 20)); -+ } -+ -+ fprintf(header, "local const int base_dist[D_CODES] = {\n"); -+ for (i = 0; i < D_CODES; i++) { -+ fprintf(header, "%5u%s", base_dist[i], -+ SEPARATOR(i, D_CODES-1, 10)); -+ } -+ -+ fclose(header); -+} -+#endif /* GEN_TREES_H */ -+ -+/* =========================================================================== -+ * Initialize the tree data structures for a new zlib stream. -+ */ -+void _tr_init(s) -+ deflate_state *s; -+{ -+ tr_static_init(); -+ -+ s->l_desc.dyn_tree = s->dyn_ltree; -+ s->l_desc.stat_desc = &static_l_desc; -+ -+ s->d_desc.dyn_tree = s->dyn_dtree; -+ s->d_desc.stat_desc = &static_d_desc; -+ -+ s->bl_desc.dyn_tree = s->bl_tree; -+ s->bl_desc.stat_desc = &static_bl_desc; -+ -+ s->bi_buf = 0; -+ s->bi_valid = 0; -+ s->last_eob_len = 8; /* enough lookahead for inflate */ -+#ifdef DEBUG -+ s->compressed_len = 0L; -+ s->bits_sent = 0L; -+#endif -+ -+ /* Initialize the first block of the first file: */ -+ init_block(s); -+} -+ -+/* =========================================================================== -+ * Initialize a new block. -+ */ -+local void init_block(s) -+ deflate_state *s; -+{ -+ int n; /* iterates over tree elements */ -+ -+ /* Initialize the trees. */ -+ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; -+ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; -+ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; -+ -+ s->dyn_ltree[END_BLOCK].Freq = 1; -+ s->opt_len = s->static_len = 0L; -+ s->last_lit = s->matches = 0; -+} -+ -+#define SMALLEST 1 -+/* Index within the heap array of least frequent node in the Huffman tree */ -+ -+ -+/* =========================================================================== -+ * Remove the smallest element from the heap and recreate the heap with -+ * one less element. Updates heap and heap_len. -+ */ -+#define pqremove(s, tree, top) \ -+{\ -+ top = s->heap[SMALLEST]; \ -+ s->heap[SMALLEST] = s->heap[s->heap_len--]; \ -+ pqdownheap(s, tree, SMALLEST); \ -+} -+ -+/* =========================================================================== -+ * Compares to subtrees, using the tree depth as tie breaker when -+ * the subtrees have equal frequency. This minimizes the worst case length. -+ */ -+#define smaller(tree, n, m, depth) \ -+ (tree[n].Freq < tree[m].Freq || \ -+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) -+ -+/* =========================================================================== -+ * Restore the heap property by moving down the tree starting at node k, -+ * exchanging a node with the smallest of its two sons if necessary, stopping -+ * when the heap property is re-established (each father smaller than its -+ * two sons). -+ */ -+local void pqdownheap(s, tree, k) -+ deflate_state *s; -+ ct_data *tree; /* the tree to restore */ -+ int k; /* node to move down */ -+{ -+ int v = s->heap[k]; -+ int j = k << 1; /* left son of k */ -+ while (j <= s->heap_len) { -+ /* Set j to the smallest of the two sons: */ -+ if (j < s->heap_len && -+ smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { -+ j++; -+ } -+ /* Exit if v is smaller than both sons */ -+ if (smaller(tree, v, s->heap[j], s->depth)) break; -+ -+ /* Exchange v with the smallest son */ -+ s->heap[k] = s->heap[j]; k = j; -+ -+ /* And continue down the tree, setting j to the left son of k */ -+ j <<= 1; -+ } -+ s->heap[k] = v; -+} -+ -+/* =========================================================================== -+ * Compute the optimal bit lengths for a tree and update the total bit length -+ * for the current block. -+ * IN assertion: the fields freq and dad are set, heap[heap_max] and -+ * above are the tree nodes sorted by increasing frequency. -+ * OUT assertions: the field len is set to the optimal bit length, the -+ * array bl_count contains the frequencies for each bit length. -+ * The length opt_len is updated; static_len is also updated if stree is -+ * not null. -+ */ -+local void gen_bitlen(s, desc) -+ deflate_state *s; -+ tree_desc *desc; /* the tree descriptor */ -+{ -+ ct_data *tree = desc->dyn_tree; -+ int max_code = desc->max_code; -+ const ct_data *stree = desc->stat_desc->static_tree; -+ const intf *extra = desc->stat_desc->extra_bits; -+ int base = desc->stat_desc->extra_base; -+ int max_length = desc->stat_desc->max_length; -+ int h; /* heap index */ -+ int n, m; /* iterate over the tree elements */ -+ int bits; /* bit length */ -+ int xbits; /* extra bits */ -+ ush f; /* frequency */ -+ int overflow = 0; /* number of elements with bit length too large */ -+ -+ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; -+ -+ /* In a first pass, compute the optimal bit lengths (which may -+ * overflow in the case of the bit length tree). -+ */ -+ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ -+ -+ for (h = s->heap_max+1; h < HEAP_SIZE; h++) { -+ n = s->heap[h]; -+ bits = tree[tree[n].Dad].Len + 1; -+ if (bits > max_length) bits = max_length, overflow++; -+ tree[n].Len = (ush)bits; -+ /* We overwrite tree[n].Dad which is no longer needed */ -+ -+ if (n > max_code) continue; /* not a leaf node */ -+ -+ s->bl_count[bits]++; -+ xbits = 0; -+ if (n >= base) xbits = extra[n-base]; -+ f = tree[n].Freq; -+ s->opt_len += (ulg)f * (bits + xbits); -+ if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); -+ } -+ if (overflow == 0) return; -+ -+ Trace((stderr,"\nbit length overflow\n")); -+ /* This happens for example on obj2 and pic of the Calgary corpus */ -+ -+ /* Find the first bit length which could increase: */ -+ do { -+ bits = max_length-1; -+ while (s->bl_count[bits] == 0) bits--; -+ s->bl_count[bits]--; /* move one leaf down the tree */ -+ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ -+ s->bl_count[max_length]--; -+ /* The brother of the overflow item also moves one step up, -+ * but this does not affect bl_count[max_length] -+ */ -+ overflow -= 2; -+ } while (overflow > 0); -+ -+ /* Now recompute all bit lengths, scanning in increasing frequency. -+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all -+ * lengths instead of fixing only the wrong ones. This idea is taken -+ * from 'ar' written by Haruhiko Okumura.) -+ */ -+ for (bits = max_length; bits != 0; bits--) { -+ n = s->bl_count[bits]; -+ while (n != 0) { -+ m = s->heap[--h]; -+ if (m > max_code) continue; -+ if (tree[m].Len != (unsigned) bits) { -+ Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); -+ s->opt_len += ((long)bits - (long)tree[m].Len) -+ *(long)tree[m].Freq; -+ tree[m].Len = (ush)bits; -+ } -+ n--; -+ } -+ } -+} -+ -+/* =========================================================================== -+ * Generate the codes for a given tree and bit counts (which need not be -+ * optimal). -+ * IN assertion: the array bl_count contains the bit length statistics for -+ * the given tree and the field len is set for all tree elements. -+ * OUT assertion: the field code is set for all tree elements of non -+ * zero code length. -+ */ -+local void gen_codes (tree, max_code, bl_count) -+ ct_data *tree; /* the tree to decorate */ -+ int max_code; /* largest code with non zero frequency */ -+ ushf *bl_count; /* number of codes at each bit length */ -+{ -+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */ -+ ush code = 0; /* running code value */ -+ int bits; /* bit index */ -+ int n; /* code index */ -+ -+ /* The distribution counts are first used to generate the code values -+ * without bit reversal. -+ */ -+ for (bits = 1; bits <= MAX_BITS; bits++) { -+ next_code[bits] = code = (code + bl_count[bits-1]) << 1; -+ } -+ /* Check that the bit counts in bl_count are consistent. The last code -+ * must be all ones. -+ */ -+ Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; -+ const ct_data *stree = desc->stat_desc->static_tree; -+ int elems = desc->stat_desc->elems; -+ int n, m; /* iterate over heap elements */ -+ int max_code = -1; /* largest code with non zero frequency */ -+ int node; /* new node being created */ -+ -+ /* Construct the initial heap, with least frequent element in -+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. -+ * heap[0] is not used. -+ */ -+ s->heap_len = 0, s->heap_max = HEAP_SIZE; -+ -+ for (n = 0; n < elems; n++) { -+ if (tree[n].Freq != 0) { -+ s->heap[++(s->heap_len)] = max_code = n; -+ s->depth[n] = 0; -+ } else { -+ tree[n].Len = 0; -+ } -+ } -+ -+ /* The pkzip format requires that at least one distance code exists, -+ * and that at least one bit should be sent even if there is only one -+ * possible code. So to avoid special checks later on we force at least -+ * two codes of non zero frequency. -+ */ -+ while (s->heap_len < 2) { -+ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); -+ tree[node].Freq = 1; -+ s->depth[node] = 0; -+ s->opt_len--; if (stree) s->static_len -= stree[node].Len; -+ /* node is 0 or 1 so it does not have extra bits */ -+ } -+ desc->max_code = max_code; -+ -+ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, -+ * establish sub-heaps of increasing lengths: -+ */ -+ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); -+ -+ /* Construct the Huffman tree by repeatedly combining the least two -+ * frequent nodes. -+ */ -+ node = elems; /* next internal node of the tree */ -+ do { -+ pqremove(s, tree, n); /* n = node of least frequency */ -+ m = s->heap[SMALLEST]; /* m = node of next least frequency */ -+ -+ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ -+ s->heap[--(s->heap_max)] = m; -+ -+ /* Create a new node father of n and m */ -+ tree[node].Freq = tree[n].Freq + tree[m].Freq; -+ s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); -+ tree[n].Dad = tree[m].Dad = (ush)node; -+#ifdef DUMP_BL_TREE -+ if (tree == s->bl_tree) { -+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", -+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); -+ } -+#endif -+ /* and insert the new node in the heap */ -+ s->heap[SMALLEST] = node++; -+ pqdownheap(s, tree, SMALLEST); -+ -+ } while (s->heap_len >= 2); -+ -+ s->heap[--(s->heap_max)] = s->heap[SMALLEST]; -+ -+ /* At this point, the fields freq and dad are set. We can now -+ * generate the bit lengths. -+ */ -+ gen_bitlen(s, (tree_desc *)desc); -+ -+ /* The field len is now set, we can generate the bit codes */ -+ gen_codes ((ct_data *)tree, max_code, s->bl_count); -+} -+ -+/* =========================================================================== -+ * Scan a literal or distance tree to determine the frequencies of the codes -+ * in the bit length tree. -+ */ -+local void scan_tree (s, tree, max_code) -+ deflate_state *s; -+ ct_data *tree; /* the tree to be scanned */ -+ int max_code; /* and its largest code of non zero frequency */ -+{ -+ int n; /* iterates over all tree elements */ -+ int prevlen = -1; /* last emitted length */ -+ int curlen; /* length of current code */ -+ int nextlen = tree[0].Len; /* length of next code */ -+ int count = 0; /* repeat count of the current code */ -+ int max_count = 7; /* max repeat count */ -+ int min_count = 4; /* min repeat count */ -+ -+ if (nextlen == 0) max_count = 138, min_count = 3; -+ tree[max_code+1].Len = (ush)0xffff; /* guard */ -+ -+ for (n = 0; n <= max_code; n++) { -+ curlen = nextlen; nextlen = tree[n+1].Len; -+ if (++count < max_count && curlen == nextlen) { -+ continue; -+ } else if (count < min_count) { -+ s->bl_tree[curlen].Freq += count; -+ } else if (curlen != 0) { -+ if (curlen != prevlen) s->bl_tree[curlen].Freq++; -+ s->bl_tree[REP_3_6].Freq++; -+ } else if (count <= 10) { -+ s->bl_tree[REPZ_3_10].Freq++; -+ } else { -+ s->bl_tree[REPZ_11_138].Freq++; -+ } -+ count = 0; prevlen = curlen; -+ if (nextlen == 0) { -+ max_count = 138, min_count = 3; -+ } else if (curlen == nextlen) { -+ max_count = 6, min_count = 3; -+ } else { -+ max_count = 7, min_count = 4; -+ } -+ } -+} -+ -+/* =========================================================================== -+ * Send a literal or distance tree in compressed form, using the codes in -+ * bl_tree. -+ */ -+local void send_tree (s, tree, max_code) -+ deflate_state *s; -+ ct_data *tree; /* the tree to be scanned */ -+ int max_code; /* and its largest code of non zero frequency */ -+{ -+ int n; /* iterates over all tree elements */ -+ int prevlen = -1; /* last emitted length */ -+ int curlen; /* length of current code */ -+ int nextlen = tree[0].Len; /* length of next code */ -+ int count = 0; /* repeat count of the current code */ -+ int max_count = 7; /* max repeat count */ -+ int min_count = 4; /* min repeat count */ -+ -+ /* tree[max_code+1].Len = -1; */ /* guard already set */ -+ if (nextlen == 0) max_count = 138, min_count = 3; -+ -+ for (n = 0; n <= max_code; n++) { -+ curlen = nextlen; nextlen = tree[n+1].Len; -+ if (++count < max_count && curlen == nextlen) { -+ continue; -+ } else if (count < min_count) { -+ do { send_code(s, curlen, s->bl_tree); } while (--count != 0); -+ -+ } else if (curlen != 0) { -+ if (curlen != prevlen) { -+ send_code(s, curlen, s->bl_tree); count--; -+ } -+ Assert(count >= 3 && count <= 6, " 3_6?"); -+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); -+ -+ } else if (count <= 10) { -+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); -+ -+ } else { -+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); -+ } -+ count = 0; prevlen = curlen; -+ if (nextlen == 0) { -+ max_count = 138, min_count = 3; -+ } else if (curlen == nextlen) { -+ max_count = 6, min_count = 3; -+ } else { -+ max_count = 7, min_count = 4; -+ } -+ } -+} -+ -+/* =========================================================================== -+ * Construct the Huffman tree for the bit lengths and return the index in -+ * bl_order of the last bit length code to send. -+ */ -+local int build_bl_tree(s) -+ deflate_state *s; -+{ -+ int max_blindex; /* index of last bit length code of non zero freq */ -+ -+ /* Determine the bit length frequencies for literal and distance trees */ -+ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); -+ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); -+ -+ /* Build the bit length tree: */ -+ build_tree(s, (tree_desc *)(&(s->bl_desc))); -+ /* opt_len now includes the length of the tree representations, except -+ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. -+ */ -+ -+ /* Determine the number of bit length codes to send. The pkzip format -+ * requires that at least 4 bit length codes be sent. (appnote.txt says -+ * 3 but the actual value used is 4.) -+ */ -+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { -+ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; -+ } -+ /* Update opt_len to include the bit length tree and counts */ -+ s->opt_len += 3*(max_blindex+1) + 5+5+4; -+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", -+ s->opt_len, s->static_len)); -+ -+ return max_blindex; -+} -+ -+/* =========================================================================== -+ * Send the header for a block using dynamic Huffman trees: the counts, the -+ * lengths of the bit length codes, the literal tree and the distance tree. -+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. -+ */ -+local void send_all_trees(s, lcodes, dcodes, blcodes) -+ deflate_state *s; -+ int lcodes, dcodes, blcodes; /* number of codes for each tree */ -+{ -+ int rank; /* index in bl_order */ -+ -+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); -+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, -+ "too many codes"); -+ Tracev((stderr, "\nbl counts: ")); -+ send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ -+ send_bits(s, dcodes-1, 5); -+ send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ -+ for (rank = 0; rank < blcodes; rank++) { -+ Tracev((stderr, "\nbl code %2d ", bl_order[rank])); -+ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); -+ } -+ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); -+ -+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ -+ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); -+ -+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ -+ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -+} -+ -+/* =========================================================================== -+ * Send a stored block -+ */ -+void _tr_stored_block(s, buf, stored_len, eof) -+ deflate_state *s; -+ charf *buf; /* input block */ -+ ulg stored_len; /* length of input block */ -+ int eof; /* true if this is the last block for a file */ -+{ -+ send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ -+#ifdef DEBUG -+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; -+ s->compressed_len += (stored_len + 4) << 3; -+#endif -+ copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ -+} -+ -+/* =========================================================================== -+ * Send one empty static block to give enough lookahead for inflate. -+ * This takes 10 bits, of which 7 may remain in the bit buffer. -+ * The current inflate code requires 9 bits of lookahead. If the -+ * last two codes for the previous block (real code plus EOB) were coded -+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode -+ * the last real code. In this case we send two empty static blocks instead -+ * of one. (There are no problems if the previous block is stored or fixed.) -+ * To simplify the code, we assume the worst case of last real code encoded -+ * on one bit only. -+ */ -+void _tr_align(s) -+ deflate_state *s; -+{ -+ send_bits(s, STATIC_TREES<<1, 3); -+ send_code(s, END_BLOCK, static_ltree); -+#ifdef DEBUG -+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ -+#endif -+ bi_flush(s); -+ /* Of the 10 bits for the empty block, we have already sent -+ * (10 - bi_valid) bits. The lookahead for the last real code (before -+ * the EOB of the previous block) was thus at least one plus the length -+ * of the EOB plus what we have just sent of the empty static block. -+ */ -+ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { -+ send_bits(s, STATIC_TREES<<1, 3); -+ send_code(s, END_BLOCK, static_ltree); -+#ifdef DEBUG -+ s->compressed_len += 10L; -+#endif -+ bi_flush(s); -+ } -+ s->last_eob_len = 7; -+} -+ -+/* =========================================================================== -+ * Determine the best encoding for the current block: dynamic trees, static -+ * trees or store, and output the encoded block to the zip file. -+ */ -+void _tr_flush_block(s, buf, stored_len, eof) -+ deflate_state *s; -+ charf *buf; /* input block, or NULL if too old */ -+ ulg stored_len; /* length of input block */ -+ int eof; /* true if this is the last block for a file */ -+{ -+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ -+ int max_blindex = 0; /* index of last bit length code of non zero freq */ -+ -+ /* Build the Huffman trees unless a stored block is forced */ -+ if (s->level > 0) { -+ -+ /* Check if the file is ascii or binary */ -+ if (s->data_type == Z_UNKNOWN) set_data_type(s); -+ -+ /* Construct the literal and distance trees */ -+ build_tree(s, (tree_desc *)(&(s->l_desc))); -+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, -+ s->static_len)); -+ -+ build_tree(s, (tree_desc *)(&(s->d_desc))); -+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, -+ s->static_len)); -+ /* At this point, opt_len and static_len are the total bit lengths of -+ * the compressed block data, excluding the tree representations. -+ */ -+ -+ /* Build the bit length tree for the above two trees, and get the index -+ * in bl_order of the last bit length code to send. -+ */ -+ max_blindex = build_bl_tree(s); -+ -+ /* Determine the best encoding. Compute first the block length in bytes*/ -+ opt_lenb = (s->opt_len+3+7)>>3; -+ static_lenb = (s->static_len+3+7)>>3; -+ -+ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", -+ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, -+ s->last_lit)); -+ -+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb; -+ -+ } else { -+ Assert(buf != (char*)0, "lost buf"); -+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ -+ } -+ -+#ifdef FORCE_STORED -+ if (buf != (char*)0) { /* force stored block */ -+#else -+ if (stored_len+4 <= opt_lenb && buf != (char*)0) { -+ /* 4: two words for the lengths */ -+#endif -+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. -+ * Otherwise we can't have processed more than WSIZE input bytes since -+ * the last block flush, because compression would have been -+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to -+ * transform a block into a stored block. -+ */ -+ _tr_stored_block(s, buf, stored_len, eof); -+ -+#ifdef FORCE_STATIC -+ } else if (static_lenb >= 0) { /* force static trees */ -+#else -+ } else if (static_lenb == opt_lenb) { -+#endif -+ send_bits(s, (STATIC_TREES<<1)+eof, 3); -+ compress_block(s, static_ltree, static_dtree); -+#ifdef DEBUG -+ s->compressed_len += 3 + s->static_len; -+#endif -+ } else { -+ send_bits(s, (DYN_TREES<<1)+eof, 3); -+ send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, -+ max_blindex+1); -+ compress_block(s, s->dyn_ltree, s->dyn_dtree); -+#ifdef DEBUG -+ s->compressed_len += 3 + s->opt_len; -+#endif -+ } -+ Assert (s->compressed_len == s->bits_sent, "bad compressed size"); -+ /* The above check is made mod 2^32, for files larger than 512 MB -+ * and uLong implemented on 32 bits. -+ */ -+ init_block(s); -+ -+ if (eof) { -+ bi_windup(s); -+#ifdef DEBUG -+ s->compressed_len += 7; /* align on byte boundary */ -+#endif -+ } -+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, -+ s->compressed_len-7*eof)); -+} -+ -+/* =========================================================================== -+ * Save the match info and tally the frequency counts. Return true if -+ * the current block must be flushed. -+ */ -+int _tr_tally (s, dist, lc) -+ deflate_state *s; -+ unsigned dist; /* distance of matched string */ -+ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -+{ -+ s->d_buf[s->last_lit] = (ush)dist; -+ s->l_buf[s->last_lit++] = (uch)lc; -+ if (dist == 0) { -+ /* lc is the unmatched char */ -+ s->dyn_ltree[lc].Freq++; -+ } else { -+ s->matches++; -+ /* Here, lc is the match length - MIN_MATCH */ -+ dist--; /* dist = match distance - 1 */ -+ Assert((ush)dist < (ush)MAX_DIST(s) && -+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && -+ (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); -+ -+ s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; -+ s->dyn_dtree[d_code(dist)].Freq++; -+ } -+ -+#ifdef TRUNCATE_BLOCK -+ /* Try to guess if it is profitable to stop the current block here */ -+ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { -+ /* Compute an upper bound for the compressed length */ -+ ulg out_length = (ulg)s->last_lit*8L; -+ ulg in_length = (ulg)((long)s->strstart - s->block_start); -+ int dcode; -+ for (dcode = 0; dcode < D_CODES; dcode++) { -+ out_length += (ulg)s->dyn_dtree[dcode].Freq * -+ (5L+extra_dbits[dcode]); -+ } -+ out_length >>= 3; -+ Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", -+ s->last_lit, in_length, out_length, -+ 100L - out_length*100L/in_length)); -+ if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; -+ } -+#endif -+ return (s->last_lit == s->lit_bufsize-1); -+ /* We avoid equality with lit_bufsize because of wraparound at 64K -+ * on 16 bit machines and because stored blocks are restricted to -+ * 64K-1 bytes. -+ */ -+} -+ -+/* =========================================================================== -+ * Send the block data compressed using the given Huffman trees -+ */ -+local void compress_block(s, ltree, dtree) -+ deflate_state *s; -+ const ct_data *ltree; /* literal tree */ -+ const ct_data *dtree; /* distance tree */ -+{ -+ unsigned dist; /* distance of matched string */ -+ int lc; /* match length or unmatched char (if dist == 0) */ -+ unsigned lx = 0; /* running index in l_buf */ -+ unsigned code; /* the code to send */ -+ int extra; /* number of extra bits to send */ -+ -+ if (s->last_lit != 0) do { -+ dist = s->d_buf[lx]; -+ lc = s->l_buf[lx++]; -+ if (dist == 0) { -+ send_code(s, lc, ltree); /* send a literal byte */ -+ Tracecv(isgraph(lc), (stderr," '%c' ", lc)); -+ } else { -+ /* Here, lc is the match length - MIN_MATCH */ -+ code = _length_code[lc]; -+ send_code(s, code+LITERALS+1, ltree); /* send the length code */ -+ extra = extra_lbits[code]; -+ if (extra != 0) { -+ lc -= base_length[code]; -+ send_bits(s, lc, extra); /* send the extra length bits */ -+ } -+ dist--; /* dist is now the match distance - 1 */ -+ code = d_code(dist); -+ Assert (code < D_CODES, "bad d_code"); -+ -+ send_code(s, code, dtree); /* send the distance code */ -+ extra = extra_dbits[code]; -+ if (extra != 0) { -+ dist -= base_dist[code]; -+ send_bits(s, dist, extra); /* send the extra distance bits */ -+ } -+ } /* literal or match pair ? */ -+ -+ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ -+ Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); -+ -+ } while (lx < s->last_lit); -+ -+ send_code(s, END_BLOCK, ltree); -+ s->last_eob_len = ltree[END_BLOCK].Len; -+} -+ -+/* =========================================================================== -+ * Set the data type to ASCII or BINARY, using a crude approximation: -+ * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. -+ * IN assertion: the fields freq of dyn_ltree are set and the total of all -+ * frequencies does not exceed 64K (to fit in an int on 16 bit machines). -+ */ -+local void set_data_type(s) -+ deflate_state *s; -+{ -+ int n = 0; -+ unsigned ascii_freq = 0; -+ unsigned bin_freq = 0; -+ while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; -+ while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; -+ while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; -+ s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); -+} -+ -+/* =========================================================================== -+ * Reverse the first len bits of a code, using straightforward code (a faster -+ * method would use a table) -+ * IN assertion: 1 <= len <= 15 -+ */ -+local unsigned bi_reverse(code, len) -+ unsigned code; /* the value to invert */ -+ int len; /* its bit length */ -+{ -+ register unsigned res = 0; -+ do { -+ res |= code & 1; -+ code >>= 1, res <<= 1; -+ } while (--len > 0); -+ return res >> 1; -+} -+ -+/* =========================================================================== -+ * Flush the bit buffer, keeping at most 7 bits in it. -+ */ -+local void bi_flush(s) -+ deflate_state *s; -+{ -+ if (s->bi_valid == 16) { -+ put_short(s, s->bi_buf); -+ s->bi_buf = 0; -+ s->bi_valid = 0; -+ } else if (s->bi_valid >= 8) { -+ put_byte(s, (Byte)s->bi_buf); -+ s->bi_buf >>= 8; -+ s->bi_valid -= 8; -+ } -+} -+ -+/* =========================================================================== -+ * Flush the bit buffer and align the output on a byte boundary -+ */ -+local void bi_windup(s) -+ deflate_state *s; -+{ -+ if (s->bi_valid > 8) { -+ put_short(s, s->bi_buf); -+ } else if (s->bi_valid > 0) { -+ put_byte(s, (Byte)s->bi_buf); -+ } -+ s->bi_buf = 0; -+ s->bi_valid = 0; -+#ifdef DEBUG -+ s->bits_sent = (s->bits_sent+7) & ~7; -+#endif -+} -+ -+/* =========================================================================== -+ * Copy a stored block, storing first the length and its -+ * one's complement if requested. -+ */ -+local void copy_block(s, buf, len, header) -+ deflate_state *s; -+ charf *buf; /* the input data */ -+ unsigned len; /* its length */ -+ int header; /* true if block header must be written */ -+{ -+ bi_windup(s); /* align on byte boundary */ -+ s->last_eob_len = 8; /* enough lookahead for inflate */ -+ -+ if (header) { -+ put_short(s, (ush)len); -+ put_short(s, (ush)~len); -+#ifdef DEBUG -+ s->bits_sent += 2*16; -+#endif -+ } -+#ifdef DEBUG -+ s->bits_sent += (ulg)len<<3; -+#endif -+ while (len--) { -+ put_byte(s, *buf++); -+ } -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/trees.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,128 @@ -+/* header created automatically with -DGEN_TREES_H */ -+ -+local const ct_data static_ltree[L_CODES+2] = { -+{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, -+{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, -+{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, -+{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, -+{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, -+{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, -+{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, -+{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, -+{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, -+{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, -+{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, -+{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, -+{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, -+{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, -+{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, -+{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, -+{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, -+{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, -+{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, -+{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, -+{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, -+{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, -+{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, -+{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, -+{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, -+{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, -+{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, -+{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, -+{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, -+{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, -+{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, -+{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, -+{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, -+{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, -+{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, -+{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, -+{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, -+{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, -+{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, -+{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, -+{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, -+{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, -+{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, -+{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, -+{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, -+{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, -+{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, -+{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, -+{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, -+{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, -+{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, -+{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, -+{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, -+{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, -+{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, -+{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, -+{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, -+{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} -+}; -+ -+local const ct_data static_dtree[D_CODES] = { -+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, -+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, -+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, -+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, -+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, -+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} -+}; -+ -+const uch _dist_code[DIST_CODE_LEN] = { -+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, -+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, -+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, -+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, -+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, -+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, -+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, -+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, -+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, -+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, -+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 -+}; -+ -+const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { -+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, -+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, -+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, -+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, -+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, -+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, -+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, -+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 -+}; -+ -+local const int base_length[LENGTH_CODES] = { -+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, -+64, 80, 96, 112, 128, 160, 192, 224, 0 -+}; -+ -+local const int base_dist[D_CODES] = { -+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, -+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, -+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 -+}; -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/zconf.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,309 @@ -+/* zconf.h -- configuration of the zlib compression library -+ * Copyright (C) 1995-2002 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* @(#) $Id$ */ -+ -+#ifndef _ZCONF_H -+#define _ZCONF_H -+ -+/* -+ * If you *really* need a unique prefix for all types and library functions, -+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. -+ */ -+#ifdef IPCOMP_PREFIX -+# define deflateInit_ ipcomp_deflateInit_ -+# define deflate ipcomp_deflate -+# define deflateEnd ipcomp_deflateEnd -+# define inflateInit_ ipcomp_inflateInit_ -+# define inflate ipcomp_inflate -+# define inflateEnd ipcomp_inflateEnd -+# define deflateInit2_ ipcomp_deflateInit2_ -+# define deflateSetDictionary ipcomp_deflateSetDictionary -+# define deflateCopy ipcomp_deflateCopy -+# define deflateReset ipcomp_deflateReset -+# define deflateParams ipcomp_deflateParams -+# define inflateInit2_ ipcomp_inflateInit2_ -+# define inflateSetDictionary ipcomp_inflateSetDictionary -+# define inflateSync ipcomp_inflateSync -+# define inflateSyncPoint ipcomp_inflateSyncPoint -+# define inflateReset ipcomp_inflateReset -+# define compress ipcomp_compress -+# define compress2 ipcomp_compress2 -+# define uncompress ipcomp_uncompress -+# define adler32 ipcomp_adler32 -+# define crc32 ipcomp_crc32 -+# define get_crc_table ipcomp_get_crc_table -+/* SSS: these also need to be prefixed to avoid clash with ppp_deflate and ext2compression */ -+# define inflate_blocks ipcomp_deflate_blocks -+# define inflate_blocks_free ipcomp_deflate_blocks_free -+# define inflate_blocks_new ipcomp_inflate_blocks_new -+# define inflate_blocks_reset ipcomp_inflate_blocks_reset -+# define inflate_blocks_sync_point ipcomp_inflate_blocks_sync_point -+# define inflate_set_dictionary ipcomp_inflate_set_dictionary -+# define inflate_codes ipcomp_inflate_codes -+# define inflate_codes_free ipcomp_inflate_codes_free -+# define inflate_codes_new ipcomp_inflate_codes_new -+# define inflate_fast ipcomp_inflate_fast -+# define inflate_trees_bits ipcomp_inflate_trees_bits -+# define inflate_trees_dynamic ipcomp_inflate_trees_dynamic -+# define inflate_trees_fixed ipcomp_inflate_trees_fixed -+# define inflate_flush ipcomp_inflate_flush -+# define inflate_mask ipcomp_inflate_mask -+# define _dist_code _ipcomp_dist_code -+# define _length_code _ipcomp_length_code -+# define _tr_align _ipcomp_tr_align -+# define _tr_flush_block _ipcomp_tr_flush_block -+# define _tr_init _ipcomp_tr_init -+# define _tr_stored_block _ipcomp_tr_stored_block -+# define _tr_tally _ipcomp_tr_tally -+# define zError ipcomp_zError -+# define z_errmsg ipcomp_z_errmsg -+# define zlibVersion ipcomp_zlibVersion -+# define match_init ipcomp_match_init -+# define longest_match ipcomp_longest_match -+#endif -+ -+#ifdef Z_PREFIX -+# define Byte z_Byte -+# define uInt z_uInt -+# define uLong z_uLong -+# define Bytef z_Bytef -+# define charf z_charf -+# define intf z_intf -+# define uIntf z_uIntf -+# define uLongf z_uLongf -+# define voidpf z_voidpf -+# define voidp z_voidp -+#endif -+ -+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) -+# define WIN32 -+#endif -+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) -+# ifndef __32BIT__ -+# define __32BIT__ -+# endif -+#endif -+#if defined(__MSDOS__) && !defined(MSDOS) -+# define MSDOS -+#endif -+ -+/* -+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more -+ * than 64k bytes at a time (needed on systems with 16-bit int). -+ */ -+#if defined(MSDOS) && !defined(__32BIT__) -+# define MAXSEG_64K -+#endif -+#ifdef MSDOS -+# define UNALIGNED_OK -+#endif -+ -+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) -+# define STDC -+#endif -+#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) -+# ifndef STDC -+# define STDC -+# endif -+#endif -+ -+#ifndef STDC -+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -+# define const -+# endif -+#endif -+ -+/* Some Mac compilers merge all .h files incorrectly: */ -+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) -+# define NO_DUMMY_DECL -+#endif -+ -+/* Old Borland C incorrectly complains about missing returns: */ -+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) -+# define NEED_DUMMY_RETURN -+#endif -+ -+ -+/* Maximum value for memLevel in deflateInit2 */ -+#ifndef MAX_MEM_LEVEL -+# ifdef MAXSEG_64K -+# define MAX_MEM_LEVEL 8 -+# else -+# define MAX_MEM_LEVEL 9 -+# endif -+#endif -+ -+/* Maximum value for windowBits in deflateInit2 and inflateInit2. -+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files -+ * created by gzip. (Files created by minigzip can still be extracted by -+ * gzip.) -+ */ -+#ifndef MAX_WBITS -+# define MAX_WBITS 15 /* 32K LZ77 window */ -+#endif -+ -+/* The memory requirements for deflate are (in bytes): -+ (1 << (windowBits+2)) + (1 << (memLevel+9)) -+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) -+ plus a few kilobytes for small objects. For example, if you want to reduce -+ the default memory requirements from 256K to 128K, compile with -+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" -+ Of course this will generally degrade compression (there's no free lunch). -+ -+ The memory requirements for inflate are (in bytes) 1 << windowBits -+ that is, 32K for windowBits=15 (default value) plus a few kilobytes -+ for small objects. -+*/ -+ -+ /* Type declarations */ -+ -+#ifndef OF /* function prototypes */ -+# ifdef STDC -+# define OF(args) args -+# else -+# define OF(args) () -+# endif -+#endif -+ -+/* The following definitions for FAR are needed only for MSDOS mixed -+ * model programming (small or medium model with some far allocations). -+ * This was tested only with MSC; for other MSDOS compilers you may have -+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, -+ * just define FAR to be empty. -+ */ -+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) -+ /* MSC small or medium model */ -+# define SMALL_MEDIUM -+# ifdef _MSC_VER -+# define FAR _far -+# else -+# define FAR far -+# endif -+#endif -+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) -+# ifndef __32BIT__ -+# define SMALL_MEDIUM -+# define FAR _far -+# endif -+#endif -+ -+/* Compile with -DZLIB_DLL for Windows DLL support */ -+#if defined(ZLIB_DLL) -+# if defined(_WINDOWS) || defined(WINDOWS) -+# ifdef FAR -+# undef FAR -+# endif -+# include -+# define ZEXPORT WINAPI -+# ifdef WIN32 -+# define ZEXPORTVA WINAPIV -+# else -+# define ZEXPORTVA FAR _cdecl _export -+# endif -+# endif -+# if defined (__BORLANDC__) -+# if (__BORLANDC__ >= 0x0500) && defined (WIN32) -+# include -+# define ZEXPORT __declspec(dllexport) WINAPI -+# define ZEXPORTRVA __declspec(dllexport) WINAPIV -+# else -+# if defined (_Windows) && defined (__DLL__) -+# define ZEXPORT _export -+# define ZEXPORTVA _export -+# endif -+# endif -+# endif -+#endif -+ -+#if defined (__BEOS__) -+# if defined (ZLIB_DLL) -+# define ZEXTERN extern __declspec(dllexport) -+# else -+# define ZEXTERN extern __declspec(dllimport) -+# endif -+#endif -+ -+#ifndef ZEXPORT -+# define ZEXPORT -+#endif -+#ifndef ZEXPORTVA -+# define ZEXPORTVA -+#endif -+#ifndef ZEXTERN -+# define ZEXTERN extern -+#endif -+ -+#ifndef FAR -+# define FAR -+#endif -+ -+#if !defined(MACOS) && !defined(TARGET_OS_MAC) -+typedef unsigned char Byte; /* 8 bits */ -+#endif -+typedef unsigned int uInt; /* 16 bits or more */ -+typedef unsigned long uLong; /* 32 bits or more */ -+ -+#ifdef SMALL_MEDIUM -+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -+# define Bytef Byte FAR -+#else -+ typedef Byte FAR Bytef; -+#endif -+typedef char FAR charf; -+typedef int FAR intf; -+typedef uInt FAR uIntf; -+typedef uLong FAR uLongf; -+ -+#ifdef STDC -+ typedef void FAR *voidpf; -+ typedef void *voidp; -+#else -+ typedef Byte FAR *voidpf; -+ typedef Byte *voidp; -+#endif -+ -+#ifdef HAVE_UNISTD_H -+# include /* for off_t */ -+# include /* for SEEK_* and off_t */ -+# define z_off_t off_t -+#endif -+#ifndef SEEK_SET -+# define SEEK_SET 0 /* Seek from beginning of file. */ -+# define SEEK_CUR 1 /* Seek from current position. */ -+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -+#endif -+#ifndef z_off_t -+# define z_off_t long -+#endif -+ -+/* MVS linker does not support external names larger than 8 bytes */ -+#if defined(__MVS__) -+# pragma map(deflateInit_,"DEIN") -+# pragma map(deflateInit2_,"DEIN2") -+# pragma map(deflateEnd,"DEEND") -+# pragma map(inflateInit_,"ININ") -+# pragma map(inflateInit2_,"ININ2") -+# pragma map(inflateEnd,"INEND") -+# pragma map(inflateSync,"INSY") -+# pragma map(inflateSetDictionary,"INSEDI") -+# pragma map(inflate_blocks,"INBL") -+# pragma map(inflate_blocks_new,"INBLNE") -+# pragma map(inflate_blocks_free,"INBLFR") -+# pragma map(inflate_blocks_reset,"INBLRE") -+# pragma map(inflate_codes_free,"INCOFR") -+# pragma map(inflate_codes,"INCO") -+# pragma map(inflate_fast,"INFA") -+# pragma map(inflate_flush,"INFLU") -+# pragma map(inflate_mask,"INMA") -+# pragma map(inflate_set_dictionary,"INSEDI2") -+# pragma map(ipcomp_inflate_copyright,"INCOPY") -+# pragma map(inflate_trees_bits,"INTRBI") -+# pragma map(inflate_trees_dynamic,"INTRDY") -+# pragma map(inflate_trees_fixed,"INTRFI") -+# pragma map(inflate_trees_free,"INTRFR") -+#endif -+ -+#endif /* _ZCONF_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/zutil.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,227 @@ -+/* zutil.c -- target dependent utility functions for the compression library -+ * Copyright (C) 1995-2002 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* @(#) $Id$ */ -+ -+#include -+ -+#define MY_ZCALLOC -+ -+struct internal_state {int dummy;}; /* for buggy compilers */ -+ -+#ifndef STDC -+extern void exit OF((int)); -+#endif -+ -+const char *z_errmsg[10] = { -+"need dictionary", /* Z_NEED_DICT 2 */ -+"stream end", /* Z_STREAM_END 1 */ -+"", /* Z_OK 0 */ -+"file error", /* Z_ERRNO (-1) */ -+"stream error", /* Z_STREAM_ERROR (-2) */ -+"data error", /* Z_DATA_ERROR (-3) */ -+"insufficient memory", /* Z_MEM_ERROR (-4) */ -+"buffer error", /* Z_BUF_ERROR (-5) */ -+"incompatible version",/* Z_VERSION_ERROR (-6) */ -+""}; -+ -+ -+const char * ZEXPORT zlibVersion() -+{ -+ return ZLIB_VERSION; -+} -+ -+#ifdef DEBUG -+ -+# ifndef verbose -+# define verbose 0 -+# endif -+int z_verbose = verbose; -+ -+void z_error (m) -+ char *m; -+{ -+ fprintf(stderr, "%s\n", m); -+ exit(1); -+} -+#endif -+ -+/* exported to allow conversion of error code to string for compress() and -+ * uncompress() -+ */ -+const char * ZEXPORT zError(err) -+ int err; -+{ -+ return ERR_MSG(err); -+} -+ -+ -+#ifndef HAVE_MEMCPY -+ -+void zmemcpy(dest, source, len) -+ Bytef* dest; -+ const Bytef* source; -+ uInt len; -+{ -+ if (len == 0) return; -+ do { -+ *dest++ = *source++; /* ??? to be unrolled */ -+ } while (--len != 0); -+} -+ -+int zmemcmp(s1, s2, len) -+ const Bytef* s1; -+ const Bytef* s2; -+ uInt len; -+{ -+ uInt j; -+ -+ for (j = 0; j < len; j++) { -+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; -+ } -+ return 0; -+} -+ -+void zmemzero(dest, len) -+ Bytef* dest; -+ uInt len; -+{ -+ if (len == 0) return; -+ do { -+ *dest++ = 0; /* ??? to be unrolled */ -+ } while (--len != 0); -+} -+#endif -+ -+#ifdef __TURBOC__ -+#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) -+/* Small and medium model in Turbo C are for now limited to near allocation -+ * with reduced MAX_WBITS and MAX_MEM_LEVEL -+ */ -+# define MY_ZCALLOC -+ -+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes -+ * and farmalloc(64K) returns a pointer with an offset of 8, so we -+ * must fix the pointer. Warning: the pointer must be put back to its -+ * original form in order to free it, use zcfree(). -+ */ -+ -+#define MAX_PTR 10 -+/* 10*64K = 640K */ -+ -+local int next_ptr = 0; -+ -+typedef struct ptr_table_s { -+ voidpf org_ptr; -+ voidpf new_ptr; -+} ptr_table; -+ -+local ptr_table table[MAX_PTR]; -+/* This table is used to remember the original form of pointers -+ * to large buffers (64K). Such pointers are normalized with a zero offset. -+ * Since MSDOS is not a preemptive multitasking OS, this table is not -+ * protected from concurrent access. This hack doesn't work anyway on -+ * a protected system like OS/2. Use Microsoft C instead. -+ */ -+ -+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) -+{ -+ voidpf buf = opaque; /* just to make some compilers happy */ -+ ulg bsize = (ulg)items*size; -+ -+ /* If we allocate less than 65520 bytes, we assume that farmalloc -+ * will return a usable pointer which doesn't have to be normalized. -+ */ -+ if (bsize < 65520L) { -+ buf = farmalloc(bsize); -+ if (*(ush*)&buf != 0) return buf; -+ } else { -+ buf = farmalloc(bsize + 16L); -+ } -+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL; -+ table[next_ptr].org_ptr = buf; -+ -+ /* Normalize the pointer to seg:0 */ -+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; -+ *(ush*)&buf = 0; -+ table[next_ptr++].new_ptr = buf; -+ return buf; -+} -+ -+void zcfree (voidpf opaque, voidpf ptr) -+{ -+ int n; -+ if (*(ush*)&ptr != 0) { /* object < 64K */ -+ farfree(ptr); -+ return; -+ } -+ /* Find the original pointer */ -+ for (n = 0; n < next_ptr; n++) { -+ if (ptr != table[n].new_ptr) continue; -+ -+ farfree(table[n].org_ptr); -+ while (++n < next_ptr) { -+ table[n-1] = table[n]; -+ } -+ next_ptr--; -+ return; -+ } -+ ptr = opaque; /* just to make some compilers happy */ -+ Assert(0, "zcfree: ptr not found"); -+} -+#endif -+#endif /* __TURBOC__ */ -+ -+ -+#if defined(M_I86) && !defined(__32BIT__) -+/* Microsoft C in 16-bit mode */ -+ -+# define MY_ZCALLOC -+ -+#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) -+# define _halloc halloc -+# define _hfree hfree -+#endif -+ -+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) -+{ -+ if (opaque) opaque = 0; /* to make compiler happy */ -+ return _halloc((long)items, size); -+} -+ -+void zcfree (voidpf opaque, voidpf ptr) -+{ -+ if (opaque) opaque = 0; /* to make compiler happy */ -+ _hfree(ptr); -+} -+ -+#endif /* MSC */ -+ -+ -+#ifndef MY_ZCALLOC /* Any system without a special alloc function */ -+ -+#ifndef STDC -+extern voidp calloc OF((uInt items, uInt size)); -+extern void free OF((voidpf ptr)); -+#endif -+ -+voidpf zcalloc (opaque, items, size) -+ voidpf opaque; -+ unsigned items; -+ unsigned size; -+{ -+ if (opaque) items += size - size; /* make compiler happy */ -+ return (voidpf)calloc(items, size); -+} -+ -+void zcfree (opaque, ptr) -+ voidpf opaque; -+ voidpf ptr; -+{ -+ free(ptr); -+ if (opaque) return; /* make compiler happy */ -+} -+ -+#endif /* MY_ZCALLOC */ ---- linux/net/Config.in.orig Fri Feb 9 14:34:13 2001 -+++ linux/net/Config.in Thu Feb 22 19:40:08 2001 -@@ -88,4 +88,9 @@ - #bool 'Network code profiler' CONFIG_NET_PROFILE - endmenu - -+tristate 'IP Security Protocol (FreeS/WAN IPSEC)' CONFIG_IPSEC -+if [ "$CONFIG_IPSEC" != "n" ]; then -+ source net/ipsec/Config.in -+fi -+ - endmenu -RCSID $Id$ ---- linux/net/Makefile.preipsec Mon Jun 11 22:15:27 2001 -+++ linux/net/Makefile Tue Nov 6 21:07:43 2001 -@@ -17,6 +17,7 @@ - subdir-$(CONFIG_NET) += 802 sched - subdir-$(CONFIG_INET) += ipv4 - subdir-$(CONFIG_NETFILTER) += ipv4/netfilter -+subdir-$(CONFIG_IPSEC) += ipsec - subdir-$(CONFIG_UNIX) += unix - subdir-$(CONFIG_IPV6) += ipv6 - ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/Config.in Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,76 @@ -+# -+# IPSEC configuration -+# Copyright (C) 1998, 1999, 2000,2001 Richard Guy Briggs. -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by the -+# Free Software Foundation; either version 2 of the License, or (at your -+# option) any later version. See . -+# -+# This program is distributed in 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. -+# -+# RCSID $Id$ -+ -+comment 'IPSec options (Openswan)' -+ -+bool ' IPSEC: IP-in-IP encapsulation (tunnel mode)' CONFIG_IPSEC_IPIP -+ -+bool ' IPSEC: Authentication Header' CONFIG_IPSEC_AH -+if [ "$CONFIG_IPSEC_AH" = "y" -o "$CONFIG_IPSEC_ESP" = "y" ]; then -+ bool ' HMAC-MD5 authentication algorithm' CONFIG_IPSEC_AUTH_HMAC_MD5 -+ bool ' HMAC-SHA1 authentication algorithm' CONFIG_IPSEC_AUTH_HMAC_SHA1 -+fi -+ -+bool ' IPSEC: Encapsulating Security Payload' CONFIG_IPSEC_ESP -+if [ "$CONFIG_IPSEC_ESP" = "y" ]; then -+ bool ' 3DES encryption algorithm' CONFIG_IPSEC_ENC_3DES -+ bool ' AES encryption algorithm' CONFIG_IPSEC_ENC_AES -+fi -+ -+bool ' IPSEC Modular Extensions' CONFIG_IPSEC_ALG -+if [ "$CONFIG_IPSEC_ALG" != "n" ]; then -+ source net/ipsec/alg/Config.in -+fi -+ -+bool ' IPSEC: IP Compression' CONFIG_IPSEC_IPCOMP -+ -+bool ' IPSEC Debugging Option' CONFIG_IPSEC_DEBUG -+ -+# -+# -+# $Log$ -+# Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+# Turn off EOLN_NATIVE flag -+# -+# (Logical change 1.5010) -+# -+# Revision 1.30 2004/06/23 09:49:37 ken -+# Free -> Open -+# -+# Revision 1.29 2004/04/06 02:49:25 mcr -+# pullup of algo code from alg-branch. -+# -+# Revision 1.28 2004/02/03 03:12:26 mcr -+# remove NAT-traversal option from IPsec config, -+# as it should be in the kernel configuration if -+# the NAT-T patch is installed. -+# -+# Revision 1.27.2.2 2004/04/05 04:30:46 mcr -+# patches for alg-branch to compile/work with 2.x openswan -+# -+# Revision 1.27.2.1 2003/12/23 12:48:25 jjo -+# Added missing alg part to linux/net/ipsec/Config.in -+# -+# Revision 1.27 2003/12/10 01:14:27 mcr -+# NAT-traversal patches to KLIPS. -+# -+# Revision 1.26 2002/04/24 07:36:26 mcr -+# Moved from ./klips/net/ipsec/Config.in,v -+# -+# Revision 1.25 2002/02/21 19:55:12 mcr -+# removed all traces of IPSEC_CONFIG_REGRESS because it -+# screwed up 2.2's "make menuconfig" scripts. -+# -+# Revision 1.24 2002/01/28 20:24:31 mcr -+# commented out IPSEC_REGRESS option from user visible config. -+# -+# -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/Makefile Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,337 @@ -+# Makefile for KLIPS kernel code as a module -+# Copyright (C) 1998, 1999, 2000,2001 Richard Guy Briggs. -+# Copyright (C) 2002 Michael Richardson -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by the -+# Free Software Foundation; either version 2 of the License, or (at your -+# option) any later version. See . -+# -+# This program is distributed in 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. -+# -+# RCSID $Id$ -+# -+# Note! Dependencies are done automagically by 'make dep', which also -+# removes any old dependencies. DON'T put your own dependencies here -+# unless it's something special (ie not a .c file). -+# -+ -+ifeq ($(strip $(KLIPSMODULE)),) -+OPENSWANSRCDIR=. -+else -+OPENSWANSRCDIR=../../.. -+endif -+-include ${OPENSWANSRCDIR}/Makefile.ver -+ -+ifeq ($(strip $(KLIPS_TOP)),) -+KLIPS_TOP=../.. -+endif -+ -+ifneq ($(strip $(KLIPSMODULE)),) -+ -+ifndef TOPDIR -+TOPDIR:=/usr/src/linux -+endif -+export TOPDIR -+ -+endif -+ -+# -+# This magic from User-Mode-Linux list. It gets list of -I options, as -+# UML needs some extra, that varry by revision. -+# -+KERNEL_CFLAGS= $(shell $(MAKE) -C $(TOPDIR) --no-print-directory -s -f Makefile ARCH=$(ARCH) MAKEFLAGS= script SCRIPT='@echo $$(CFLAGS)' ) -+ -+MODULE_CFLAGS= $(shell $(MAKE) -C $(TOPDIR) --no-print-directory -s -f Makefile ARCH=$(ARCH) MAKEFLAGS= script SCRIPT='@echo $$(MODFLAGS)' ) -+ -+subdir- := -+subdir-n := -+subdir-y := -+subdir-m := -+ -+ -+MOD_DESTDIR:=net/ipsec -+ -+export TOPDIR -+ -+all: ipsec.o -+ -+foo: -+ echo KERNEL: ${KERNEL_CFLAGS} -+ echo MODULE: ${MODULE_CFLAGS} -+ -+ipsec.o: foo -+ -+O_TARGET := ipsec.o -+obj-y := ipsec_init.o ipsec_sa.o ipsec_radij.o radij.o -+obj-y += ipsec_life.o ipsec_proc.o -+obj-y += ipsec_tunnel.o ipsec_xmit.o ipsec_rcv.o ipsec_ipip.o -+obj-y += sysctl_net_ipsec.o -+obj-y += pfkey_v2.o pfkey_v2_parser.o pfkey_v2_ext_process.o -+obj-y += version.o -+obj-$(CONFIG_IPSEC_AH) += ipsec_ah.o -+obj-$(CONFIG_IPSEC_ESP) += ipsec_esp.o -+obj-$(CONFIG_IPSEC_IPCOMP)+= ipsec_ipcomp.o -+ -+CFLAGS_ipsec_alg.o += -DEXPORT_SYMTAB -+obj-$(CONFIG_IPSEC_ALG) += ipsec_alg.o -+obj-$(CONFIG_IPSEC_ENC_AES) += ipsec_alg_aes.o -+obj-$(CONFIG_IPSEC_ENC_CRYPTOAPI) += ipsec_alg_cryptoapi.o -+ -+export-objs += ipsec_alg.o -+ -+ -+LIBDESDIR=${KLIPS_TOP}/crypto/ciphers/des -+VPATH+= ${LIBDESDIR} -+ -+include ${LIBDESDIR}/Makefile.objs -+ -+LIBFREESWANDIR=${KLIPS_TOP}/lib/libfreeswan -+VPATH+=${LIBFREESWANDIR} -+ -+include ${LIBFREESWANDIR}/Makefile.objs -+ -+# IPcomp stuff -+obj-$(CONFIG_IPSEC_IPCOMP) += ipcomp.o -+ -+LIBZLIBSRCDIR=${KLIPS_TOP}/lib/zlib -+VPATH+=${LIBZLIBSRCDIR} -+ -+LIBAESDIR=$(KLIPS_TOP)/crypto/ciphers/aes -+VPATH+=${LIBAESDIR} -+include ${LIBAESDIR}/Makefile.objs -+ -+# CFLAGS='$(CFLAGS)' \ -+# MODULE_CFLAGS='$(MODULE_CFLAGS)' KERNEL_CFLAGS='$(KERNEL_CFLAGS)' \ -+# -+include ${LIBZLIBSRCDIR}/Makefile.objs -+ -+export-objs := radij.o -+ -+EXTRA_CFLAGS += $(ALGO_FLAGS) -+ -+ -+# include file with .h-style macros that would otherwise be created by -+# config. Must occur before other includes. -+ifneq ($(strip $(MODULE_DEF_INCLUDE)),) -+EXTRA_CFLAGS += -include ${MODULE_DEF_INCLUDE} -+endif -+ -+# 'override CFLAGS' should really be 'EXTRA_CFLAGS' -+#EXTRA_CFLAGS += -nostdinc -+EXTRA_CFLAGS += -I${KLIPS_TOP}/include -+ -+EXTRA_CFLAGS += -I${TOPDIR}/include -+EXTRA_CFLAGS += -I${LIBZLIBSRCDIR} -+ -+ifeq ($(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION),2.4.2-2) -+EXTRA_CFLAGS += -DREDHAT_BOGOSITY -+endif -+ -+ifeq ($(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION),2.4.3-12) -+EXTRA_CFLAGS += -DREDHAT_BOGOSITY -+endif -+ -+ -+#ifeq ($(CONFIG_IPSEC_DEBUG),y) -+#EXTRA_CFLAGS += -g -+#endif -+ -+#ifeq ($(CONFIG_IPSEC_ALG), y) -+EXTRA_CFLAGS += -DCONFIG_IPSEC_ALG -+#endif -+# MOST of these flags are in KERNEL_CFLAGS already! -+ -+EXTRA_CFLAGS += $(KLIPSCOMPILE) -+EXTRA_CFLAGS += -Wall -+#EXTRA_CFLAGS += -Werror -+#EXTRA_CFLAGS += -Wconversion -+#EXTRA_CFLAGS += -Wmissing-prototypes -+# cannot use both -Wpointer-arith and -Werror with CONFIG_HIGHMEM -+# include/linux/highmem.h has an inline function definition that uses void* arithmentic. -+ifeq ($(CONFIG_NOHIGHMEM),y) -+EXTRA_CFLAGS += -Wpointer-arith -+endif -+#EXTRA_CFLAGS += -Wcast-qual -+#EXTRA_CFLAGS += -Wmissing-declarations -+#EXTRA_CFLAGS += -Wstrict-prototypes -+#EXTRA_CFLAGS += -pedantic -+#EXTRA_CFLAGS += -O3 -+#EXTRA_CFLAGS += -W -+#EXTRA_CFLAGS += -Wwrite-strings -+#EXTRA_CFLAGS += -Wbad-function-cast -+ -+ifneq ($(strip $(KLIPSMODULE)),) -+# for when we aren't building in the kernel tree -+EXTRA_CFLAGS += -DARCH=${ARCH} -+EXTRA_CFLAGS += -DMODVERSIONS -+EXTRA_CFLAGS += -include ${TOPDIR}/include/linux/modversions.h -+EXTRA_CFLAGS += ${MODULE_CFLAGS} -+endif -+ -+EXTRA_CFLAGS += ${KERNEL_CFLAGS} -+ -+#EXTRA_CFLAGS += -DRJ_DEBUG -DRJ_DEBUG2 -+ -+ -+# GCC 3.2 (and we presume any other 3.x) wants -falign-functions -+# in place of the traditional -malign-functions. Getting this -+# wrong leads to a warning, which is fatal due to our use of -Werror. -+ifeq ($(patsubst 3.%,3,$(shell $(CC) -dumpversion)),3) -+override CFLAGS:=$(subst -malign-functions=,-falign-functions=,$(CFLAGS)) -+endif -+ -+ -+obj-$(CONFIG_IPSEC_AUTH_HMAC_MD5) += ipsec_md5c.o -+obj-$(CONFIG_IPSEC_AUTH_HMAC_SHA1) += ipsec_sha1.o -+ -+### -+### Pre Rules.make -+### -+# undo O_TARGET, obj-y if no static -+ifneq ($(CONFIG_IPSEC),y) -+O_TARGET := -+ipsec_obj-y := $(obj-y) -+obj-y := -+subdir-y := -+endif -+ -+# Define obj-m if modular ipsec -+ifeq ($(CONFIG_IPSEC),m) -+obj-m += ipsec.o -+endif -+ -+ -+# These rules translate from new to old makefile rules -+# Translate to Rules.make lists. -+multi-used := $(filter $(list-multi), $(obj-y) $(obj-m)) -+multi-objs := $(foreach m, $(multi-used), $($(basename $(m))-objs)) -+active-objs := $(sort $(multi-objs) $(obj-y) $(obj-m)) -+O_OBJS := $(obj-y) -+M_OBJS := $(obj-m) -+MIX_OBJS := $(filter $(export-objs), $(active-objs)) -+OX_OBJS := $(export-objs) -+SUB_DIRS := $(subdir-y) -+ALL_SUB_DIRS := $(subdir-y) $(subdir-m) -+MOD_SUB_DIRS := $(subdir-m) -+ -+# dunno why, but some 2.2 setups may need explicit -DEXPORT_SYMTAB -+# uncomment next line if ipsec_alg.c compilation fails with -+# "parse error before `EXPORT_SYMTAB_not_defined'" --Juanjo -+ -+include $(TOPDIR)/Rules.make -+ -+### -+### Post Rules.make -+### -+# for modular ipsec, no O_TARGET defined => define ipsec.o creation rules -+ifeq ($(CONFIG_IPSEC),m) -+ipsec.o : $(ipsec_obj-y) -+ rm -f $@ -+ $(LD) $(LD_EXTRAFLAGS) -r $(ipsec_obj-y) -o $@ -+endif -+ -+$(ipsec_obj-y) $(obj-y) $(obj-m): $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h -+ -+#$(obj-y) $(obj-m): $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h -+ -+USE_STANDARD_AS_RULE=true -+ -+clean: -+ $(MAKE) -C alg clean -+ -rm -f *.o -+ -rm -f .*.o.flags -+ -rm -f version.c -+ -+tags TAGS: *.c *.h libfreeswan/*.c libfreeswan/*.h -+ etags *.c ../../include/*.h ../../include/freeswan/*.h -+ ctags *.c ../../include/*.h ../../include/freeswan/*.h -+ -+tar: -+ tar -cvf /dev/f1 . -+ -+# -+# $Log$ -+# Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+# Turn off EOLN_NATIVE flag -+# -+# (Logical change 1.5010) -+# -+# Revision 1.72 2004/06/22 14:44:07 ken -+# Merge nice version of Nate's CryptoAPI patch -+# -+# Revision 1.71 2004/04/18 03:04:21 mcr -+# removed duplicate version.o reference. -+# -+# Revision 1.70 2004/04/14 05:09:39 ken -+# We need to link version.o -+# -+# Revision 1.69 2004/04/12 04:02:39 ken -+# version.o no longer exists -+# -+# Revision 1.68 2004/04/11 17:08:41 mcr -+# moved PASSTHROUGH definitions to openswan.h -+# requirement for internal.h removed. -+# version.c is now generated by patch at patch-time. -+# -+# Revision 1.67 2004/04/06 02:49:25 mcr -+# pullup of algo code from alg-branch. -+# -+# Revision 1.66 2004/04/03 19:44:41 ken -+# FREESWANSRCDIR -> OPENSWANSRCDIR (patch by folken) -+# -+# Revision 1.65 2004/02/09 16:22:07 paul -+# Added -f to rm version.c in clean target to prevent bogus error -+# -+# Revision 1.64 2003/12/22 19:40:57 mcr -+# NAT-T patches 0.6c. -+# -+# Revision 1.63 2003/12/13 19:10:21 mcr -+# refactored rcv and xmit code - same as FS 2.05. -+# -+# Revision 1.62.4.2 2004/04/05 04:30:46 mcr -+# patches for alg-branch to compile/work with 2.x openswan -+# -+# Revision 1.62.4.1 2003/12/22 15:25:52 jjo -+# Merged algo-0.8.1-rc11-test1 into alg-branch -+# -+# Revision 1.62 2003/10/31 02:27:55 mcr -+# pulled up port-selector patches and sa_id elimination. -+# -+# Revision 1.61.4.1 2003/10/29 01:30:41 mcr -+# elimited "struct sa_id". -+# -+# Revision 1.61 2003/06/22 21:07:46 mcr -+# adjusted TAGS target in makefile to be useful in 2.00 source layout. -+# -+# Revision 1.60 2003/05/03 23:45:23 mcr -+# rm .o.flags and generated version.c file. -+# -+# Revision 1.59 2003/02/12 19:32:47 rgb -+# Added ipsec_xmit to the list of object files. -+# -+# Revision 1.58 2003/01/03 00:36:44 rgb -+# -+# Added emacs compile-command. -+# -+# Revision 1.57 2002/11/08 23:49:53 mcr -+# use KERNEL_CFLAGS and MODULE_CFLAGS to get proper list -+# of include directories. -+# This also eliminates some of the guesswork in the kernel -+# configuration file. -+# -+# Revision 1.56 2002/11/08 23:23:18 mcr -+# attempt to guess kernel compilation flags (i.e. list of -I) -+# by using some magic targets in the kernel makefile. -+# -+# Revision 1.55 2002/11/08 10:13:33 mcr -+# added additional include directories for module builds for 2.4.19. -+# -+# Revision 1.54 2002/10/20 06:10:30 build -+# CONFIG_NOHIGHMEM for -Wpointer-arith RPM building issues. -+# -+# (elided rest of log) -+# -+# Local Variables: -+# compile-command: "(cd ../../.. && source umlsetup.sh && make -C ${POOLSPACE} module/ipsec.o)" -+# End Variables: -+# -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/Config.alg_aes.in Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,3 @@ -+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then -+ tristate ' AES encryption algorithm' CONFIG_IPSEC_ALG_AES -+fi ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/Config.alg_cryptoapi.in Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,6 @@ -+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then -+ dep_tristate ' CRYPTOAPI ciphers support (needs cryptoapi patch)' CONFIG_IPSEC_ALG_CRYPTOAPI $CONFIG_CRYPTO -+ if [ "$CONFIG_IPSEC_ALG_CRYPTOAPI" != "n" ]; then -+ bool ' CRYPTOAPI proprietary ciphers ' CONFIG_IPSEC_ALG_NON_LIBRE -+ fi -+fi ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/Config.in Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,3 @@ -+#Placeholder -+source net/ipsec/alg/Config.alg_aes.in -+source net/ipsec/alg/Config.alg_cryptoapi.in ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/Makefile Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,112 @@ -+# Makefile,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp -+ifeq ($(strip $(KLIPSMODULE)),) -+FREESWANSRCDIR=. -+else -+FREESWANSRCDIR=../../../.. -+endif -+ifeq ($(strip $(KLIPS_TOP)),) -+KLIPS_TOP=../../.. -+override EXTRA_CFLAGS += -I$(KLIPS_TOP)/include -+endif -+ -+ifeq ($(CONFIG_IPSEC_DEBUG),y) -+override EXTRA_CFLAGS += -g -+endif -+ -+# LIBCRYPTO normally comes as an argument from "parent" Makefile -+# (this applies both to FS' "make module" and eg. Linux' "make modules" -+# But make dep doest follow same evaluations, so we need this default: -+LIBCRYPTO=$(TOPDIR)/lib/libcrypto -+ -+override EXTRA_CFLAGS += -I$(LIBCRYPTO)/include -+override EXTRA_CFLAGS += -Wall -Wpointer-arith -Wstrict-prototypes -+ -+MOD_LIST_NAME := NET_MISC_MODULES -+ -+#O_TARGET := static_init.o -+ -+subdir- := -+subdir-n := -+subdir-y := -+subdir-m := -+ -+obj-y := static_init.o -+ -+ARCH_ASM-y := -+ARCH_ASM-$(CONFIG_M586) := i586 -+ARCH_ASM-$(CONFIG_M586TSC) := i586 -+ARCH_ASM-$(CONFIG_M586MMX) := i586 -+ARCH_ASM-$(CONFIG_MK6) := i586 -+ARCH_ASM-$(CONFIG_M686) := i686 -+ARCH_ASM-$(CONFIG_MPENTIUMIII) := i686 -+ARCH_ASM-$(CONFIG_MPENTIUM4) := i686 -+ARCH_ASM-$(CONFIG_MK7) := i686 -+ARCH_ASM-$(CONFIG_MCRUSOE) := i586 -+ARCH_ASM-$(CONFIG_MWINCHIPC6) := i586 -+ARCH_ASM-$(CONFIG_MWINCHIP2) := i586 -+ARCH_ASM-$(CONFIG_MWINCHIP3D) := i586 -+ARCH_ASM-$(CONFIG_USERMODE) := i586 -+ -+ARCH_ASM :=$(ARCH_ASM-y) -+ifdef NO_ASM -+ARCH_ASM := -+endif -+ -+# The algorithm makefiles may put dependences, short-circuit them -+null: -+ -+makefiles=$(filter-out %.preipsec, $(wildcard Makefile.alg_*)) -+ifneq ($(makefiles),) -+#include Makefile.alg_aes -+#include Makefile.alg_aes-opt -+include $(makefiles) -+endif -+ -+# These rules translate from new to old makefile rules -+# Translate to Rules.make lists. -+multi-used := $(filter $(list-multi), $(obj-y) $(obj-m)) -+multi-objs := $(foreach m, $(multi-used), $($(basename $(m))-objs)) -+active-objs := $(sort $(multi-objs) $(obj-y) $(obj-m)) -+O_OBJS := $(obj-y) -+M_OBJS := $(obj-m) -+MIX_OBJS := $(filter $(export-objs), $(active-objs)) -+#OX_OBJS := $(export-objs) -+SUB_DIRS := $(subdir-y) -+ALL_SUB_DIRS := $(subdir-y) $(subdir-m) -+MOD_SUB_DIRS := $(subdir-m) -+ -+ -+static_init_mod.o: $(obj-y) -+ rm -f $@ -+ $(LD) $(LD_EXTRAFLAGS) $(obj-y) -r -o $@ -+ -+perlasm: $(LIBCRYPTO)/perlasm -+ ln -sf $? $@ -+ -+$(obj-y) $(obj-m): $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h $(KLIPS_TOP)/include/freeswan/ipsec_alg.h -+$(alg_obj-y) $(alg_obj-m): perlasm $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h $(KLIPS_TOP)/include/freeswan/ipsec_alg.h -+ -+ -+all_alg_modules: perlasm $(ALG_MODULES) -+ @echo "ALG_MODULES=$(ALG_MODULES)" -+ -+ -+# -+# Construct alg. init. function: call ipsec_ALGO_init() for every static algo -+# Needed when there are static algos (with static or modular ipsec.o) -+# -+static_init.c: $(TOPDIR)/include/linux/autoconf.h Makefile $(makefiles) scripts/mk-static_init.c.sh -+ @echo "Re-creating $@" -+ $(SHELL) scripts/mk-static_init.c.sh $(static_init-func-y) > $@ -+ -+clean: -+ @for i in $(ALG_SUBDIRS);do test -d $$i && make -C $$i clean;done;exit 0 -+ @find . -type l -exec rm -f {} \; -+ -rm -f perlasm -+ -rm -rf $(ALG_SUBDIRS) -+ -rm -f *.o static_init.c -+ -+ifdef TOPDIR -+include $(TOPDIR)/Rules.make -+endif -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/Makefile.alg_aes Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,23 @@ -+MOD_AES := ipsec_aes.o -+ -+ALG_MODULES += $(MOD_AES) -+ALG_SUBDIRS += libaes -+ -+obj-$(CONFIG_IPSEC_ALG_AES) += $(MOD_AES) -+static_init-func-$(CONFIG_IPSEC_ALG_AES)+= ipsec_aes_init -+alg_obj-$(CONFIG_IPSEC_ALG_AES) += ipsec_alg_aes.o -+ -+AES_OBJS := ipsec_alg_aes.o libaes/libaes.a -+ -+$(MOD_AES): libaes $(AES_OBJS) -+ $(LD) $(EXTRA_LDFLAGS) -r $(AES_OBJS) -o $@ -+ -+libaes: $(LIBCRYPTO)/libaes -+ test -d $@ || mkdir $@ ;exit 0 -+ test -d $@/asm || mkdir $@/asm;exit 0 -+ cd $@ && ln -sf $?/Makefile $?/*.[chS] . -+ cd $@/asm && ln -sf $?/asm/*.S . -+ -+libaes/libaes.a: libaes -+ ( cd libaes && \ -+ $(MAKE) CC='$(CC)' 'ARCH_ASM=$(ARCH_ASM)' CFLAGS='$(CFLAGS) $(EXTRA_CFLAGS)' libaes.a ;) ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/Makefile.alg_cryptoapi Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,14 @@ -+MOD_CRYPTOAPI := ipsec_cryptoapi.o -+ -+ifneq ($(wildcard $(TOPDIR)/include/linux/crypto.h),) -+ALG_MODULES += $(MOD_CRYPTOAPI) -+obj-$(CONFIG_IPSEC_ALG_CRYPTOAPI) += $(MOD_CRYPTOAPI) -+static_init-func-$(CONFIG_IPSEC_ALG_CRYPTOAPI)+= ipsec_cryptoapi_init -+alg_obj-$(CONFIG_IPSEC_ALG_CRYPTOAPI) += ipsec_alg_cryptoapi.o -+else -+$(warning "Linux CryptoAPI (2.4.22+ or 2.6.x) not found, not building ipsec_cryptoapi.o") -+endif -+ -+CRYPTOAPI_OBJS := ipsec_alg_cryptoapi.o -+$(MOD_CRYPTOAPI): $(CRYPTOAPI_OBJS) -+ $(LD) -r $(CRYPTOAPI_OBJS) -o $@ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/ipsec_alg_aes.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,253 @@ -+/* -+ * ipsec_alg AES cipher stubs -+ * -+ * Author: JuanJo Ciarlante -+ * -+ * ipsec_alg_aes.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * Fixes by: -+ * PK: Pawel Krawczyk -+ * Fixes list: -+ * PK: make XCBC comply with latest draft (keylength) -+ * -+ */ -+#include -+#include -+ -+/* -+ * special case: ipsec core modular with this static algo inside: -+ * must avoid MODULE magic for this file -+ */ -+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_AES -+#undef MODULE -+#endif -+ -+#include -+#include -+ -+#include /* printk() */ -+#include /* error codes */ -+#include /* size_t */ -+#include -+ -+/* Check if __exit is defined, if not null it */ -+#ifndef __exit -+#define __exit -+#endif -+ -+/* Low freeswan header coupling */ -+#include "freeswan/ipsec_alg.h" -+#include "libaes/aes_cbc.h" -+ -+#define CONFIG_IPSEC_ALG_AES_MAC 1 -+ -+#define AES_CONTEXT_T aes_context -+MODULE_AUTHOR("JuanJo Ciarlante "); -+static int debug=0; -+MODULE_PARM(debug, "i"); -+static int test=0; -+MODULE_PARM(test, "i"); -+static int excl=0; -+MODULE_PARM(excl, "i"); -+static int keyminbits=0; -+MODULE_PARM(keyminbits, "i"); -+static int keymaxbits=0; -+MODULE_PARM(keymaxbits, "i"); -+ -+#if CONFIG_IPSEC_ALG_AES_MAC -+#include "libaes/aes_xcbc_mac.h" -+ -+/* -+ * Not IANA number yet (draft-ietf-ipsec-ciph-aes-xcbc-mac-00.txt). -+ * We use 9 for non-modular algorithm and none for modular, thus -+ * forcing user to specify one on module load. -kravietz -+ */ -+#ifdef MODULE -+static int auth_id=0; -+#else -+static int auth_id=9; -+#endif -+MODULE_PARM(auth_id, "i"); -+#endif -+ -+#define ESP_AES 12 /* truely _constant_ :) */ -+ -+/* 128, 192 or 256 */ -+#define ESP_AES_KEY_SZ_MIN 16 /* 128 bit secret key */ -+#define ESP_AES_KEY_SZ_MAX 32 /* 256 bit secret key */ -+#define ESP_AES_CBC_BLK_LEN 16 /* AES-CBC block size */ -+ -+/* Values according to draft-ietf-ipsec-ciph-aes-xcbc-mac-02.txt -+ * -kravietz -+ */ -+#define ESP_AES_MAC_KEY_SZ 16 /* 128 bit MAC key */ -+#define ESP_AES_MAC_BLK_LEN 16 /* 128 bit block */ -+ -+static int _aes_set_key(struct ipsec_alg_enc *alg, __u8 * key_e, const __u8 * key, size_t keysize) { -+ int ret; -+ AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e; -+ ret=AES_set_key(ctx, key, keysize)!=0? 0: -EINVAL; -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_aes_set_key:" -+ "ret=%d key_e=%p key=%p keysize=%d\n", -+ ret, key_e, key, keysize); -+ return ret; -+} -+static int _aes_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) { -+ AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e; -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_aes_cbc_encrypt:" -+ "key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n", -+ key_e, in, ilen, iv, encrypt); -+ return AES_cbc_encrypt(ctx, in, in, ilen, iv, encrypt); -+} -+#if CONFIG_IPSEC_ALG_AES_MAC -+static int _aes_mac_set_key(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * key, int keylen) { -+ aes_context_mac *ctxm=(aes_context_mac *)key_a; -+ return AES_xcbc_mac_set_key(ctxm, key, keylen)? 0 : -EINVAL; -+} -+static int _aes_mac_hash(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * dat, int len, __u8 * hash, int hashlen) { -+ int ret; -+ char hash_buf[16]; -+ aes_context_mac *ctxm=(aes_context_mac *)key_a; -+ ret=AES_xcbc_mac_hash(ctxm, dat, len, hash_buf); -+ memcpy(hash, hash_buf, hashlen); -+ return ret; -+} -+static struct ipsec_alg_auth ipsec_alg_AES_MAC = { -+ ixt_version: IPSEC_ALG_VERSION, -+ ixt_module: THIS_MODULE, -+ ixt_refcnt: ATOMIC_INIT(0), -+ ixt_alg_type: IPSEC_ALG_TYPE_AUTH, -+ ixt_alg_id: 0, -+ ixt_name: "aes_mac", -+ ixt_blocksize: ESP_AES_MAC_BLK_LEN, -+ ixt_keyminbits: ESP_AES_MAC_KEY_SZ*8, -+ ixt_keymaxbits: ESP_AES_MAC_KEY_SZ*8, -+ ixt_a_keylen: ESP_AES_MAC_KEY_SZ, -+ ixt_a_ctx_size: sizeof(aes_context_mac), -+ ixt_a_hmac_set_key: _aes_mac_set_key, -+ ixt_a_hmac_hash:_aes_mac_hash, -+}; -+#endif /* CONFIG_IPSEC_ALG_AES_MAC */ -+static struct ipsec_alg_enc ipsec_alg_AES = { -+ ixt_version: IPSEC_ALG_VERSION, -+ ixt_module: THIS_MODULE, -+ ixt_refcnt: ATOMIC_INIT(0), -+ ixt_alg_type: IPSEC_ALG_TYPE_ENCRYPT, -+ ixt_alg_id: ESP_AES, -+ ixt_name: "aes", -+ ixt_blocksize: ESP_AES_CBC_BLK_LEN, -+ ixt_keyminbits: ESP_AES_KEY_SZ_MIN*8, -+ ixt_keymaxbits: ESP_AES_KEY_SZ_MAX*8, -+ ixt_e_keylen: ESP_AES_KEY_SZ_MAX, -+ ixt_e_ctx_size: sizeof(AES_CONTEXT_T), -+ ixt_e_set_key: _aes_set_key, -+ ixt_e_cbc_encrypt:_aes_cbc_encrypt, -+}; -+ -+IPSEC_ALG_MODULE_INIT( ipsec_aes_init ) -+{ -+ int ret, test_ret; -+ if (keyminbits) -+ ipsec_alg_AES.ixt_keyminbits=keyminbits; -+ if (keymaxbits) { -+ ipsec_alg_AES.ixt_keymaxbits=keymaxbits; -+ if (keymaxbits*8>ipsec_alg_AES.ixt_keymaxbits) -+ ipsec_alg_AES.ixt_e_keylen=keymaxbits*8; -+ } -+ if (excl) ipsec_alg_AES.ixt_state |= IPSEC_ALG_ST_EXCL; -+ ret=register_ipsec_alg_enc(&ipsec_alg_AES); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", -+ ipsec_alg_AES.ixt_alg_type, -+ ipsec_alg_AES.ixt_alg_id, -+ ipsec_alg_AES.ixt_name, -+ ret); -+ if (ret==0 && test) { -+ test_ret=ipsec_alg_test( -+ ipsec_alg_AES.ixt_alg_type, -+ ipsec_alg_AES.ixt_alg_id, -+ test); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", -+ ipsec_alg_AES.ixt_alg_type, -+ ipsec_alg_AES.ixt_alg_id, -+ test_ret); -+ } -+#if CONFIG_IPSEC_ALG_AES_MAC -+ if (auth_id!=0){ -+ int ret; -+ ipsec_alg_AES_MAC.ixt_alg_id=auth_id; -+ ret=register_ipsec_alg_auth(&ipsec_alg_AES_MAC); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", -+ ipsec_alg_AES_MAC.ixt_alg_type, -+ ipsec_alg_AES_MAC.ixt_alg_id, -+ ipsec_alg_AES_MAC.ixt_name, -+ ret); -+ if (ret==0 && test) { -+ test_ret=ipsec_alg_test( -+ ipsec_alg_AES_MAC.ixt_alg_type, -+ ipsec_alg_AES_MAC.ixt_alg_id, -+ test); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", -+ ipsec_alg_AES_MAC.ixt_alg_type, -+ ipsec_alg_AES_MAC.ixt_alg_id, -+ test_ret); -+ } -+ } else { -+ printk(KERN_DEBUG "klips_debug: experimental ipsec_alg_AES_MAC not registered [Ok] (auth_id=%d)\n", auth_id); -+ } -+#endif /* CONFIG_IPSEC_ALG_AES_MAC */ -+ return ret; -+} -+IPSEC_ALG_MODULE_EXIT( ipsec_aes_fini ) -+{ -+#if CONFIG_IPSEC_ALG_AES_MAC -+ if (auth_id) unregister_ipsec_alg_auth(&ipsec_alg_AES_MAC); -+#endif /* CONFIG_IPSEC_ALG_AES_MAC */ -+ unregister_ipsec_alg_enc(&ipsec_alg_AES); -+ return; -+} -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+#if 0+NOT_YET -+#ifndef MODULE -+/* -+ * This is intended for static module setups, currently -+ * doesn't work for modular ipsec.o with static algos inside -+ */ -+static int setup_keybits(const char *str) -+{ -+ unsigned aux; -+ char *end; -+ -+ aux = simple_strtoul(str,&end,0); -+ if (aux != 128 && aux != 192 && aux != 256) -+ return 0; -+ keyminbits = aux; -+ -+ if (*end == 0 || *end != ',') -+ return 1; -+ str=end+1; -+ aux = simple_strtoul(str, NULL, 0); -+ if (aux != 128 && aux != 192 && aux != 256) -+ return 0; -+ if (aux >= keyminbits) -+ keymaxbits = aux; -+ return 1; -+} -+__setup("ipsec_aes_keybits=", setup_keybits); -+#endif -+#endif -+EXPORT_NO_SYMBOLS; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/ipsec_alg_cryptoapi.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,421 @@ -+/* -+ * ipsec_alg to linux cryptoapi GLUE -+ * -+ * Authors: CODE.ar TEAM -+ * Harpo MAxx -+ * JuanJo Ciarlante -+ * Luciano Ruete -+ * -+ * ipsec_alg_cryptoapi.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * Example usage: -+ * modinfo -p ipsec_cryptoapi (quite useful info, including supported algos) -+ * modprobe ipsec_cryptoapi -+ * modprobe ipsec_cryptoapi test=1 -+ * modprobe ipsec_cryptoapi excl=1 (exclusive cipher/algo) -+ * modprobe ipsec_cryptoapi noauto=1 aes=1 twofish=1 (only these ciphers) -+ * modprobe ipsec_cryptoapi aes=128,128 (force these keylens) -+ * modprobe ipsec_cryptoapi des_ede3=0 (everything but 3DES) -+ */ -+#include -+#include -+ -+/* -+ * special case: ipsec core modular with this static algo inside: -+ * must avoid MODULE magic for this file -+ */ -+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_CRYPTOAPI -+#undef MODULE -+#endif -+ -+#include -+#include -+ -+#include /* printk() */ -+#include /* error codes */ -+#include /* size_t */ -+#include -+ -+/* Check if __exit is defined, if not null it */ -+#ifndef __exit -+#define __exit -+#endif -+ -+/* warn the innocent */ -+#if !defined (CONFIG_CRYPTO) && !defined (CONFIG_CRYPTO_MODULE) -+#warning "No linux CryptoAPI found, install 2.4.22+ or 2.6.x" -+#define NO_CRYPTOAPI_SUPPORT -+#endif -+/* Low freeswan header coupling */ -+#include "freeswan/ipsec_alg.h" -+ -+#include -+#ifdef CRYPTO_API_VERSION_CODE -+#warning "Old CryptoAPI is not supported. Only linux-2.4.22+ or linux-2.6.x are supported" -+#define NO_CRYPTOAPI_SUPPORT -+#endif -+ -+#ifdef NO_CRYPTOAPI_SUPPORT -+#warning "Building an unusable module :P" -+/* Catch old CryptoAPI by not allowing module to load */ -+IPSEC_ALG_MODULE_INIT( ipsec_cryptoapi_init ) -+{ -+ printk(KERN_WARNING "ipsec_cryptoapi.o was not built on stock Linux CryptoAPI (2.4.22+ or 2.6.x), not loading.\n"); -+ return -EINVAL; -+} -+#else -+#include -+#include -+#include -+ -+#define CIPHERNAME_AES "aes" -+#define CIPHERNAME_3DES "des3_ede" -+#define CIPHERNAME_BLOWFISH "blowfish" -+#define CIPHERNAME_CAST "cast5" -+#define CIPHERNAME_SERPENT "serpent" -+#define CIPHERNAME_TWOFISH "twofish" -+ -+#define ESP_3DES 3 -+#define ESP_AES 12 -+#define ESP_BLOWFISH 7 /* truely _constant_ :) */ -+#define ESP_CAST 6 /* quite constant :) */ -+#define ESP_SERPENT 252 /* from ipsec drafts */ -+#define ESP_TWOFISH 253 /* from ipsec drafts */ -+ -+#define AH_MD5 2 -+#define AH_SHA 3 -+#define DIGESTNAME_MD5 "md5" -+#define DIGESTNAME_SHA1 "sha1" -+ -+MODULE_AUTHOR("Juanjo Ciarlante, Harpo MAxx, Luciano Ruete"); -+static int debug=0; -+MODULE_PARM(debug, "i"); -+static int test=0; -+MODULE_PARM(test, "i"); -+static int excl=0; -+MODULE_PARM(excl, "i"); -+ -+static int noauto = 0; -+MODULE_PARM(noauto,"i"); -+MODULE_PARM_DESC(noauto, "Dont try all known algos, just setup enabled ones"); -+ -+static int des_ede3[] = {-1, -1}; -+static int aes[] = {-1, -1}; -+static int blowfish[] = {-1, -1}; -+static int cast[] = {-1, -1}; -+static int serpent[] = {-1, -1}; -+static int twofish[] = {-1, -1}; -+ -+MODULE_PARM(des_ede3,"1-2i"); -+MODULE_PARM(aes,"1-2i"); -+MODULE_PARM(blowfish,"1-2i"); -+MODULE_PARM(cast,"1-2i"); -+MODULE_PARM(serpent,"1-2i"); -+MODULE_PARM(twofish,"1-2i"); -+MODULE_PARM_DESC(des_ede3, "0: disable | 1: force_enable | min,max: dontuse"); -+MODULE_PARM_DESC(aes, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(blowfish, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(cast, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(serpent, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(twofish, "0: disable | 1: force_enable | min,max: keybitlens"); -+ -+struct ipsec_alg_capi_cipher { -+ const char *ciphername; /* cryptoapi's ciphername */ -+ unsigned blocksize; -+ unsigned short minbits; -+ unsigned short maxbits; -+ int *parm; /* lkm param for this cipher */ -+ struct ipsec_alg_enc alg; /* note it's not a pointer */ -+}; -+static struct ipsec_alg_capi_cipher alg_capi_carray[] = { -+ { CIPHERNAME_AES , 16, 128, 256, aes , { ixt_alg_id: ESP_AES, }}, -+ { CIPHERNAME_TWOFISH , 16, 128, 256, twofish, { ixt_alg_id: ESP_TWOFISH, }}, -+ { CIPHERNAME_SERPENT , 16, 128, 256, serpent, { ixt_alg_id: ESP_SERPENT, }}, -+ { CIPHERNAME_CAST , 8, 128, 128, cast , { ixt_alg_id: ESP_CAST, }}, -+ { CIPHERNAME_BLOWFISH , 8, 96, 448, blowfish,{ ixt_alg_id: ESP_BLOWFISH, }}, -+ { CIPHERNAME_3DES , 8, 192, 192, des_ede3,{ ixt_alg_id: ESP_3DES, }}, -+ { NULL, 0, 0, 0, NULL, {} } -+}; -+#ifdef NOT_YET -+struct ipsec_alg_capi_digest { -+ const char *digestname; /* cryptoapi's digestname */ -+ struct digest_implementation *di; -+ struct ipsec_alg_auth alg; /* note it's not a pointer */ -+}; -+static struct ipsec_alg_capi_cipher alg_capi_darray[] = { -+ { DIGESTNAME_MD5, NULL, { ixt_alg_id: AH_MD5, }}, -+ { DIGESTNAME_SHA1, NULL, { ixt_alg_id: AH_SHA, }}, -+ { NULL, NULL, {} } -+}; -+#endif -+/* -+ * "generic" linux cryptoapi setup_cipher() function -+ */ -+int setup_cipher(const char *ciphername) -+{ -+ return crypto_alg_available(ciphername, 0); -+} -+ -+/* -+ * setups ipsec_alg_capi_cipher "hyper" struct components, calling -+ * register_ipsec_alg for cointaned ipsec_alg object -+ */ -+static void _capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e); -+static __u8 * _capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen); -+static int _capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt); -+ -+static int -+setup_ipsec_alg_capi_cipher(struct ipsec_alg_capi_cipher *cptr) -+{ -+ int ret; -+ cptr->alg.ixt_version = IPSEC_ALG_VERSION; -+ cptr->alg.ixt_module = THIS_MODULE; -+ atomic_set (& cptr->alg.ixt_refcnt, 0); -+ strncpy (cptr->alg.ixt_name , cptr->ciphername, sizeof (cptr->alg.ixt_name)); -+ -+ cptr->alg.ixt_blocksize=cptr->blocksize; -+ cptr->alg.ixt_keyminbits=cptr->minbits; -+ cptr->alg.ixt_keymaxbits=cptr->maxbits; -+ cptr->alg.ixt_state = 0; -+ if (excl) cptr->alg.ixt_state |= IPSEC_ALG_ST_EXCL; -+ cptr->alg.ixt_e_keylen=cptr->alg.ixt_keymaxbits/8; -+ cptr->alg.ixt_e_ctx_size = 0; -+ cptr->alg.ixt_alg_type = IPSEC_ALG_TYPE_ENCRYPT; -+ cptr->alg.ixt_e_new_key = _capi_new_key; -+ cptr->alg.ixt_e_destroy_key = _capi_destroy_key; -+ cptr->alg.ixt_e_cbc_encrypt = _capi_cbc_encrypt; -+ cptr->alg.ixt_data = cptr; -+ -+ ret=register_ipsec_alg_enc(&cptr->alg); -+ printk("setup_ipsec_alg_capi_cipher(): " -+ "alg_type=%d alg_id=%d name=%s " -+ "keyminbits=%d keymaxbits=%d, ret=%d\n", -+ cptr->alg.ixt_alg_type, -+ cptr->alg.ixt_alg_id, -+ cptr->alg.ixt_name, -+ cptr->alg.ixt_keyminbits, -+ cptr->alg.ixt_keymaxbits, -+ ret); -+ return ret; -+} -+/* -+ * called in ipsec_sa_wipe() time, will destroy key contexts -+ * and do 1 unbind() -+ */ -+static void -+_capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e) -+{ -+ struct crypto_tfm *tfm=(struct crypto_tfm*)key_e; -+ -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug: _capi_destroy_key:" -+ "name=%s key_e=%p \n", -+ alg->ixt_name, key_e); -+ if (!key_e) { -+ printk(KERN_ERR "klips_debug: _capi_destroy_key:" -+ "name=%s NULL key_e!\n", -+ alg->ixt_name); -+ return; -+ } -+ crypto_free_tfm(tfm); -+} -+ -+/* -+ * create new key context, need alg->ixt_data to know which -+ * (of many) cipher inside this module is the target -+ */ -+static __u8 * -+_capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen) -+{ -+ struct ipsec_alg_capi_cipher *cptr; -+ struct crypto_tfm *tfm=NULL; -+ -+ cptr = alg->ixt_data; -+ if (!cptr) { -+ printk(KERN_ERR "_capi_new_key(): " -+ "NULL ixt_data (?!) for \"%s\" algo\n" -+ , alg->ixt_name); -+ goto err; -+ } -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_capi_new_key:" -+ "name=%s cptr=%p key=%p keysize=%d\n", -+ alg->ixt_name, cptr, key, keylen); -+ -+ /* -+ * alloc tfm -+ */ -+ tfm = crypto_alloc_tfm(cptr->ciphername, CRYPTO_TFM_MODE_CBC); -+ if (!tfm) { -+ printk(KERN_ERR "_capi_new_key(): " -+ "NULL tfm for \"%s\" cryptoapi (\"%s\") algo\n" -+ , alg->ixt_name, cptr->ciphername); -+ goto err; -+ } -+ if (crypto_cipher_setkey(tfm, key, keylen) < 0) { -+ printk(KERN_ERR "_capi_new_key(): " -+ "failed new_key() for \"%s\" cryptoapi algo (keylen=%d)\n" -+ , alg->ixt_name, keylen); -+ crypto_free_tfm(tfm); -+ tfm=NULL; -+ } -+err: -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_capi_new_key:" -+ "name=%s key=%p keylen=%d tfm=%p\n", -+ alg->ixt_name, key, keylen, tfm); -+ return (__u8 *) tfm; -+} -+/* -+ * core encryption function: will use cx->ci to call actual cipher's -+ * cbc function -+ */ -+static int -+_capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) { -+ int error =0; -+ struct crypto_tfm *tfm=(struct crypto_tfm *)key_e; -+ struct scatterlist sg = { -+ .page = virt_to_page(in), -+ .offset = (unsigned long)(in) % PAGE_SIZE, -+ .length=ilen, -+ }; -+ if (debug > 1) -+ printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" -+ "key_e=%p " -+ "in=%p out=%p ilen=%d iv=%p encrypt=%d\n" -+ , key_e -+ , in, in, ilen, iv, encrypt); -+ crypto_cipher_set_iv(tfm, iv, crypto_tfm_alg_ivsize(tfm)); -+ if (encrypt) -+ error = crypto_cipher_encrypt (tfm, &sg, &sg, ilen); -+ else -+ error = crypto_cipher_decrypt (tfm, &sg, &sg, ilen); -+ if (debug > 1) -+ printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" -+ "error=%d\n" -+ , error); -+ return (error<0)? error : ilen; -+} -+/* -+ * main initialization loop: for each cipher in list, do -+ * 1) setup cryptoapi cipher else continue -+ * 2) register ipsec_alg object -+ */ -+static int -+setup_cipher_list (struct ipsec_alg_capi_cipher* clist) -+{ -+ struct ipsec_alg_capi_cipher *cptr; -+ /* foreach cipher in list ... */ -+ for (cptr=clist;cptr->ciphername;cptr++) { -+ /* -+ * see if cipher has been disabled (0) or -+ * if noauto set and not enabled (1) -+ */ -+ if (cptr->parm[0] == 0 || (noauto && cptr->parm[0] < 0)) { -+ if (debug>0) -+ printk(KERN_INFO "setup_cipher_list(): " -+ "ciphername=%s skipped at user request: " -+ "noauto=%d parm[0]=%d parm[1]=%d\n" -+ , cptr->ciphername -+ , noauto -+ , cptr->parm[0] -+ , cptr->parm[1]); -+ continue; -+ } -+ /* -+ * use a local ci to avoid touching cptr->ci, -+ * if register ipsec_alg success then bind cipher -+ */ -+ if( setup_cipher(cptr->ciphername) ) { -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:" -+ "setup_cipher_list():" -+ "ciphername=%s found\n" -+ , cptr->ciphername); -+ if (setup_ipsec_alg_capi_cipher(cptr) == 0) { -+ -+ -+ } else { -+ printk(KERN_ERR "klips_debug:" -+ "setup_cipher_list():" -+ "ciphername=%s failed ipsec_alg_register\n" -+ , cptr->ciphername); -+ } -+ } else { -+ if (debug>0) -+ printk(KERN_INFO "setup_cipher_list(): lookup for ciphername=%s: not found \n", -+ cptr->ciphername); -+ } -+ } -+ return 0; -+} -+/* -+ * deregister ipsec_alg objects and unbind ciphers -+ */ -+static int -+unsetup_cipher_list (struct ipsec_alg_capi_cipher* clist) -+{ -+ struct ipsec_alg_capi_cipher *cptr; -+ /* foreach cipher in list ... */ -+ for (cptr=clist;cptr->ciphername;cptr++) { -+ if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) { -+ unregister_ipsec_alg_enc(&cptr->alg); -+ } -+ } -+ return 0; -+} -+/* -+ * test loop for registered algos -+ */ -+static int -+test_cipher_list (struct ipsec_alg_capi_cipher* clist) -+{ -+ int test_ret; -+ struct ipsec_alg_capi_cipher *cptr; -+ /* foreach cipher in list ... */ -+ for (cptr=clist;cptr->ciphername;cptr++) { -+ if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) { -+ test_ret=ipsec_alg_test( -+ cptr->alg.ixt_alg_type, -+ cptr->alg.ixt_alg_id, -+ test); -+ printk("test_cipher_list(alg_type=%d alg_id=%d): test_ret=%d\n", -+ cptr->alg.ixt_alg_type, -+ cptr->alg.ixt_alg_id, -+ test_ret); -+ } -+ } -+ return 0; -+} -+ -+IPSEC_ALG_MODULE_INIT( ipsec_cryptoapi_init ) -+{ -+ int ret, test_ret; -+ if ((ret=setup_cipher_list(alg_capi_carray)) < 0) -+ return -EPROTONOSUPPORT; -+ if (ret==0 && test) { -+ test_ret=test_cipher_list(alg_capi_carray); -+ } -+ return ret; -+} -+IPSEC_ALG_MODULE_EXIT( ipsec_cryptoapi_fini ) -+{ -+ unsetup_cipher_list(alg_capi_carray); -+ return; -+} -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+EXPORT_NO_SYMBOLS; -+#endif /* NO_CRYPTOAPI_SUPPORT */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/scripts/mk-static_init.c.sh Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,18 @@ -+#!/bin/sh -+cat << EOF -+#include -+#include -+#include "freeswan/ipsec_alg.h" -+$(for i in $*; do -+ test -z "$i" && continue -+ echo "extern int $i(void);" -+done) -+void ipsec_alg_static_init(void){ -+ int __attribute__ ((unused)) err=0; -+$(for i in $*; do -+ test -z "$i" && continue -+ echo " if ((err=$i()) < 0)" -+ echo " printk(KERN_WARNING \"$i() returned %d\", err);" -+done) -+} -+EOF ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/defconfig Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,146 @@ -+ -+# -+# RCSID $Id$ -+# -+ -+# -+# FreeS/WAN IPSec implementation, KLIPS kernel config defaults -+# -+ -+# -+# First, lets override stuff already set or not in the kernel config. -+# -+# We can't even think about leaving this off... -+CONFIG_INET=y -+ -+# -+# This must be on for subnet protection. -+CONFIG_IP_FORWARD=y -+ -+# Shut off IPSEC masquerading if it has been enabled, since it will -+# break the compile. IPPROTO_ESP and IPPROTO_AH were included in -+# net/ipv4/ip_masq.c when they should have gone into include/linux/in.h. -+CONFIG_IP_MASQUERADE_IPSEC=n -+ -+# -+# Next, lets set the recommended FreeS/WAN configuration. -+# -+ -+# To config as static (preferred), 'y'. To config as module, 'm'. -+CONFIG_IPSEC=y -+ -+# To do tunnel mode IPSec, this must be enabled. -+CONFIG_IPSEC_IPIP=y -+ -+# To enable authentication, say 'y'. (Highly recommended) -+CONFIG_IPSEC_AH=y -+ -+# Authentication algorithm(s): -+CONFIG_IPSEC_AUTH_HMAC_MD5=y -+CONFIG_IPSEC_AUTH_HMAC_SHA1=y -+ -+# To enable encryption, say 'y'. (Highly recommended) -+CONFIG_IPSEC_ESP=y -+ -+# Encryption algorithm(s): -+CONFIG_IPSEC_ENC_3DES=y -+CONFIG_IPSEC_ENC_AES=y -+ -+# modular algo extensions (and new ALGOs) -+CONFIG_IPSEC_ALG=y -+CONFIG_IPSEC_ENC_3DES=y -+CONFIG_IPSEC_ENC_AES=y -+ -+CONFIG_IPSEC_ALG_TWOFISH=m -+CONFIG_IPSEC_ALG_BLOWFISH=m -+CONFIG_IPSEC_ALG_SERPENT=m -+CONFIG_IPSEC_ALG_MD5=m -+CONFIG_IPSEC_ALG_SHA1=m -+CONFIG_IPSEC_ALG_SHA2=m -+#CONFIG_IPSEC_ALG_CAST=n -+#CONFIG_IPSEC_ALG_NULL=n -+ -+# Use CryptoAPI for ALG? - by default, no. -+CONFIG_IPSEC_ENC_CRYPTOAPI=n -+ -+ -+# IP Compression: new, probably still has minor bugs. -+CONFIG_IPSEC_IPCOMP=y -+ -+# To enable userspace-switchable KLIPS debugging, say 'y'. -+CONFIG_IPSEC_DEBUG=y -+ -+# NAT Traversal -+CONFIG_IPSEC_NAT_TRAVERSAL=y -+ -+# -+# -+# $Log$ -+# Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+# Turn off EOLN_NATIVE flag -+# -+# (Logical change 1.5010) -+# -+# Revision 1.25 2004/07/05 01:03:53 mcr -+# fix for adding cryptoapi code. -+# keep it off for now, since UMLs do not have it yet. -+# -+# Revision 1.24 2004/04/06 02:49:25 mcr -+# pullup of algo code from alg-branch. -+# -+# Revision 1.23.2.2 2004/04/05 04:30:46 mcr -+# patches for alg-branch to compile/work with 2.x openswan -+# -+# Revision 1.23.2.1 2003/12/22 15:25:52 jjo -+# . Merged algo-0.8.1-rc11-test1 into alg-branch -+# -+# Revision 1.23 2003/12/10 01:14:27 mcr -+# NAT-traversal patches to KLIPS. -+# -+# Revision 1.22 2003/02/24 19:37:27 mcr -+# changed default compilation mode to static. -+# -+# Revision 1.21 2002/04/24 07:36:27 mcr -+# Moved from ./klips/net/ipsec/defconfig,v -+# -+# Revision 1.20 2002/04/02 04:07:40 mcr -+# default build is now 'm'odule for KLIPS -+# -+# Revision 1.19 2002/03/08 18:57:17 rgb -+# Added a blank line at the beginning of the file to make it easier for -+# other projects to patch ./arch/i386/defconfig, for example -+# LIDS+grSecurity requested by Jason Pattie. -+# -+# Revision 1.18 2000/11/30 17:26:56 rgb -+# Cleaned out unused options and enabled ipcomp by default. -+# -+# Revision 1.17 2000/09/15 11:37:01 rgb -+# Merge in heavily modified Svenning Soerensen's -+# IPCOMP zlib deflate code. -+# -+# Revision 1.16 2000/09/08 19:12:55 rgb -+# Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+# -+# Revision 1.15 2000/05/24 19:37:13 rgb -+# *** empty log message *** -+# -+# Revision 1.14 2000/05/11 21:14:57 henry -+# just commenting the FOOBAR=y lines out is not enough -+# -+# Revision 1.13 2000/05/10 20:17:58 rgb -+# Comment out netlink defaults, which are no longer needed. -+# -+# Revision 1.12 2000/05/10 19:13:38 rgb -+# Added configure option to shut off no eroute passthrough. -+# -+# Revision 1.11 2000/03/16 07:09:46 rgb -+# Hardcode PF_KEYv2 support. -+# Disable IPSEC_ICMP by default. -+# Remove DES config option from defaults file. -+# -+# Revision 1.10 2000/01/11 03:09:42 rgb -+# Added a default of 'y' to PF_KEYv2 keying I/F. -+# -+# Revision 1.9 1999/05/08 21:23:12 rgb -+# Added support for 2.2.x kernels. -+# -+# Revision 1.8 1999/04/06 04:54:25 rgb -+# Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+# patch shell fixes. -+# -+# ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipcomp.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,725 @@ -+/* -+ * IPCOMP zlib interface code. -+ * Copyright (C) 2000 Svenning Soerensen -+ * Copyright (C) 2000, 2001 Richard Guy Briggs -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipcomp_c_version[] = "RCSID $Id$"; -+ -+/* SSS */ -+ -+#include -+#include -+ -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include -+#include -+#include -+#include -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+ -+#include -+ -+#ifdef NET_21 -+# include -+# include -+# include -+# define proto_priv cb -+#endif /* NET21 */ -+#include -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" /* sysctl_ipsec_inbound_policy_check */ -+#include "openswan/ipcomp.h" -+#include "zlib/zlib.h" -+#include "zlib/zutil.h" -+ -+#include /* SADB_X_CALG_DEFLATE */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int sysctl_ipsec_debug_ipcomp = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+static -+struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask); -+ -+static -+voidpf my_zcalloc(voidpf opaque, uInt items, uInt size) -+{ -+ return (voidpf) kmalloc(items*size, GFP_ATOMIC); -+} -+ -+static -+void my_zfree(voidpf opaque, voidpf address) -+{ -+ kfree(address); -+} -+ -+struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags) -+{ -+ struct iphdr *iph; -+ unsigned int iphlen, pyldsz, cpyldsz; -+ unsigned char *buffer; -+ z_stream zs; -+ int zresult; -+ -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: .\n"); -+ -+ if(skb == NULL) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "passed in NULL skb, returning ERROR.\n"); -+ if(flags != NULL) { -+ *flags |= IPCOMP_PARMERROR; -+ } -+ return skb; -+ } -+ -+ if(ips == NULL) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "passed in NULL ipsec_sa needed for cpi, returning ERROR.\n"); -+ if(flags) { -+ *flags |= IPCOMP_PARMERROR; -+ } -+ return skb; -+ } -+ -+ if (flags == NULL) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "passed in NULL flags, returning ERROR.\n"); -+ ipsec_kfree_skb(skb); -+ return NULL; -+ } -+ -+#ifdef NET_21 -+ iph = skb->nh.iph; -+#else /* NET_21 */ -+ iph = skb->ip_hdr; -+#endif /* NET_21 */ -+ -+ switch (iph->protocol) { -+ case IPPROTO_COMP: -+ case IPPROTO_AH: -+ case IPPROTO_ESP: -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "skipping compression of packet with ip protocol %d.\n", -+ iph->protocol); -+ *flags |= IPCOMP_UNCOMPRESSABLE; -+ return skb; -+ } -+ -+ /* Don't compress packets already fragmented */ -+ if (iph->frag_off & __constant_htons(IP_MF | IP_OFFSET)) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "skipping compression of fragmented packet.\n"); -+ *flags |= IPCOMP_UNCOMPRESSABLE; -+ return skb; -+ } -+ -+ iphlen = iph->ihl << 2; -+ pyldsz = ntohs(iph->tot_len) - iphlen; -+ -+ /* Don't compress less than 90 bytes (rfc 2394) */ -+ if (pyldsz < 90) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "skipping compression of tiny packet, len=%d.\n", -+ pyldsz); -+ *flags |= IPCOMP_UNCOMPRESSABLE; -+ return skb; -+ } -+ -+ /* Adaptive decision */ -+ if (ips->ips_comp_adapt_skip) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "skipping compression: ips_comp_adapt_skip=%d.\n", -+ ips->ips_comp_adapt_skip); -+ ips->ips_comp_adapt_skip--; -+ *flags |= IPCOMP_UNCOMPRESSABLE; -+ return skb; -+ } -+ -+ zs.zalloc = my_zcalloc; -+ zs.zfree = my_zfree; -+ zs.opaque = 0; -+ -+ /* We want to use deflateInit2 because we don't want the adler -+ header. */ -+ zresult = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -11, -+ DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); -+ if (zresult != Z_OK) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_compress: " -+ "deflateInit2() returned error %d (%s), " -+ "skipping compression.\n", -+ zresult, -+ zs.msg ? zs.msg : zError(zresult)); -+ *flags |= IPCOMP_COMPRESSIONERROR; -+ return skb; -+ } -+ -+ -+ /* Max output size. Result should be max this size. -+ * Implementation specific tweak: -+ * If it's not at least 32 bytes and 6.25% smaller than -+ * the original packet, it's probably not worth wasting -+ * the receiver's CPU cycles decompressing it. -+ * Your mileage may vary. -+ */ -+ cpyldsz = pyldsz - sizeof(struct ipcomphdr) - (pyldsz <= 512 ? 32 : pyldsz >> 4); -+ -+ buffer = kmalloc(cpyldsz, GFP_ATOMIC); -+ if (!buffer) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_compress: " -+ "unable to kmalloc(%d, GFP_ATOMIC), " -+ "skipping compression.\n", -+ cpyldsz); -+ *flags |= IPCOMP_COMPRESSIONERROR; -+ deflateEnd(&zs); -+ return skb; -+ } -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { -+ __u8 *c; -+ int i; -+ -+ c = (__u8*)iph + iphlen; -+ for(i = 0; i < pyldsz; i++, c++) { -+ if(!(i % 16)) { -+ printk(KERN_INFO "skb_compress: before:"); -+ } -+ printk("%02x ", *c); -+ if(!((i + 1) % 16)) { -+ printk("\n"); -+ } -+ } -+ if(i % 16) { -+ printk("\n"); -+ } -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ zs.next_in = (char *) iph + iphlen; /* start of payload */ -+ zs.avail_in = pyldsz; -+ zs.next_out = buffer; /* start of compressed payload */ -+ zs.avail_out = cpyldsz; -+ -+ /* Finish compression in one step */ -+ zresult = deflate(&zs, Z_FINISH); -+ -+ /* Free all dynamically allocated buffers */ -+ deflateEnd(&zs); -+ if (zresult != Z_STREAM_END) { -+ *flags |= IPCOMP_UNCOMPRESSABLE; -+ kfree(buffer); -+ -+ /* Adjust adaptive counters */ -+ if (++(ips->ips_comp_adapt_tries) == IPCOMP_ADAPT_INITIAL_TRIES) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "first %d packets didn't compress, " -+ "skipping next %d\n", -+ IPCOMP_ADAPT_INITIAL_TRIES, -+ IPCOMP_ADAPT_INITIAL_SKIP); -+ ips->ips_comp_adapt_skip = IPCOMP_ADAPT_INITIAL_SKIP; -+ } -+ else if (ips->ips_comp_adapt_tries == IPCOMP_ADAPT_INITIAL_TRIES + IPCOMP_ADAPT_SUBSEQ_TRIES) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "next %d packets didn't compress, " -+ "skipping next %d\n", -+ IPCOMP_ADAPT_SUBSEQ_TRIES, -+ IPCOMP_ADAPT_SUBSEQ_SKIP); -+ ips->ips_comp_adapt_skip = IPCOMP_ADAPT_SUBSEQ_SKIP; -+ ips->ips_comp_adapt_tries = IPCOMP_ADAPT_INITIAL_TRIES; -+ } -+ -+ return skb; -+ } -+ -+ /* resulting compressed size */ -+ cpyldsz -= zs.avail_out; -+ -+ /* Insert IPCOMP header */ -+ ((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_nh = iph->protocol; -+ ((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_flags = 0; -+ /* use the bottom 16 bits of the spi for the cpi. The top 16 bits are -+ for internal reference only. */ -+ ((struct ipcomphdr*) (((char*)iph) + iphlen))->ipcomp_cpi = htons((__u16)(ntohl(ips->ips_said.spi) & 0x0000ffff)); -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: raw=%d, comp=%d.\n", -+ ntohl(ips->ips_said.spi), -+ ntohl(ips->ips_said.spi) & 0x0000ffff, -+ ntohs(((struct ipcomphdr*)(((char*)iph)+iphlen))->ipcomp_cpi), -+ pyldsz, -+ cpyldsz); -+ -+ /* Update IP header */ -+ iph->protocol = IPPROTO_COMP; -+ iph->tot_len = htons(iphlen + sizeof(struct ipcomphdr) + cpyldsz); -+#if 1 /* XXX checksum is done by ipsec_tunnel ? */ -+ iph->check = 0; -+ iph->check = ip_fast_csum((char *) iph, iph->ihl); -+#endif -+ -+ /* Copy compressed payload */ -+ memcpy((char *) iph + iphlen + sizeof(struct ipcomphdr), -+ buffer, -+ cpyldsz); -+ kfree(buffer); -+ -+ /* Update skb length/tail by "unputting" the shrinkage */ -+ skb_put(skb, -+ cpyldsz + sizeof(struct ipcomphdr) - pyldsz); -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { -+ __u8 *c; -+ int i; -+ -+ c = (__u8*)iph + iphlen + sizeof(struct ipcomphdr); -+ for(i = 0; i < cpyldsz; i++, c++) { -+ if(!(i % 16)) { -+ printk(KERN_INFO "skb_compress: result:"); -+ } -+ printk("%02x ", *c); -+ if(!((i + 1) % 16)) { -+ printk("\n"); -+ } -+ } -+ if(i % 16) { -+ printk("\n"); -+ } -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ ips->ips_comp_adapt_skip = 0; -+ ips->ips_comp_adapt_tries = 0; -+ -+ return skb; -+} -+ -+struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags) -+{ -+ struct sk_buff *nskb = NULL; -+ -+ /* original ip header */ -+ struct iphdr *oiph, *iph; -+ unsigned int iphlen, pyldsz, cpyldsz; -+ z_stream zs; -+ int zresult; -+ -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_decompress: .\n"); -+ -+ if(!skb) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "passed in NULL skb, returning ERROR.\n"); -+ if (flags) *flags |= IPCOMP_PARMERROR; -+ return skb; -+ } -+ -+ if(!ips && sysctl_ipsec_inbound_policy_check) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "passed in NULL ipsec_sa needed for comp alg, returning ERROR.\n"); -+ if (flags) *flags |= IPCOMP_PARMERROR; -+ return skb; -+ } -+ -+ if (!flags) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "passed in NULL flags, returning ERROR.\n"); -+ ipsec_kfree_skb(skb); -+ return NULL; -+ } -+ -+#ifdef NET_21 -+ oiph = skb->nh.iph; -+#else /* NET_21 */ -+ oiph = skb->ip_hdr; -+#endif /* NET_21 */ -+ -+ iphlen = oiph->ihl << 2; -+ -+ if (oiph->protocol != IPPROTO_COMP) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "called with non-IPCOMP packet (protocol=%d)," -+ "skipping decompression.\n", -+ oiph->protocol); -+ *flags |= IPCOMP_PARMERROR; -+ return skb; -+ } -+ -+ if ( (((struct ipcomphdr*)((char*) oiph + iphlen))->ipcomp_flags != 0) -+ || ((((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi -+ != htons(SADB_X_CALG_DEFLATE)) -+ && sysctl_ipsec_inbound_policy_check -+ && (!ips || (ips && (ips->ips_encalg != SADB_X_CALG_DEFLATE)))) ) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "called with incompatible IPCOMP packet (flags=%d, " -+ "cpi=%d), ips-compalg=%d, skipping decompression.\n", -+ ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_flags), -+ ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi), -+ ips ? ips->ips_encalg : 0); -+ *flags |= IPCOMP_PARMERROR; -+ -+ return skb; -+ } -+ -+ if (ntohs(oiph->frag_off) & ~0x4000) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "called with fragmented IPCOMP packet, " -+ "skipping decompression.\n"); -+ *flags |= IPCOMP_PARMERROR; -+ return skb; -+ } -+ -+ /* original compressed payload size */ -+ cpyldsz = ntohs(oiph->tot_len) - iphlen - sizeof(struct ipcomphdr); -+ -+ zs.zalloc = my_zcalloc; -+ zs.zfree = my_zfree; -+ zs.opaque = 0; -+ -+ zs.next_in = (char *) oiph + iphlen + sizeof(struct ipcomphdr); -+ zs.avail_in = cpyldsz; -+ -+ /* Maybe we should be a bit conservative about memory -+ requirements and use inflateInit2 */ -+ /* Beware, that this might make us unable to decompress packets -+ from other implementations - HINT: check PGPnet source code */ -+ /* We want to use inflateInit2 because we don't want the adler -+ header. */ -+ zresult = inflateInit2(&zs, -15); -+ if (zresult != Z_OK) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "inflateInit2() returned error %d (%s), " -+ "skipping decompression.\n", -+ zresult, -+ zs.msg ? zs.msg : zError(zresult)); -+ *flags |= IPCOMP_DECOMPRESSIONERROR; -+ -+ return skb; -+ } -+ -+ /* We have no way of knowing the exact length of the resulting -+ decompressed output before we have actually done the decompression. -+ For now, we guess that the packet will not be bigger than the -+ attached ipsec device's mtu or 16260, whichever is biggest. -+ This may be wrong, since the sender's mtu may be bigger yet. -+ XXX This must be dealt with later XXX -+ */ -+ -+ /* max payload size */ -+ pyldsz = skb->dev ? (skb->dev->mtu < 16260 ? 16260 : skb->dev->mtu) -+ : (65520 - iphlen); -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_decompress: " -+ "max payload size: %d\n", pyldsz); -+ -+ while (pyldsz > (cpyldsz + sizeof(struct ipcomphdr)) && -+ (nskb = skb_copy_ipcomp(skb, -+ pyldsz - cpyldsz - sizeof(struct ipcomphdr), -+ GFP_ATOMIC)) == NULL) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "unable to skb_copy_ipcomp(skb, %d, GFP_ATOMIC), " -+ "trying with less payload size.\n", -+ (int)(pyldsz - cpyldsz - sizeof(struct ipcomphdr))); -+ pyldsz >>=1; -+ } -+ -+ if (!nskb) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "unable to allocate memory, dropping packet.\n"); -+ *flags |= IPCOMP_DECOMPRESSIONERROR; -+ inflateEnd(&zs); -+ -+ return skb; -+ } -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { -+ __u8 *c; -+ int i; -+ -+ c = (__u8*)oiph + iphlen + sizeof(struct ipcomphdr); -+ for(i = 0; i < cpyldsz; i++, c++) { -+ if(!(i % 16)) { -+ printk(KERN_INFO "skb_decompress: before:"); -+ } -+ printk("%02x ", *c); -+ if(!((i + 1) % 16)) { -+ printk("\n"); -+ } -+ } -+ if(i % 16) { -+ printk("\n"); -+ } -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#ifdef NET_21 -+ iph = nskb->nh.iph; -+#else /* NET_21 */ -+ iph = nskb->ip_hdr; -+#endif /* NET_21 */ -+ zs.next_out = (char *)iph + iphlen; -+ zs.avail_out = pyldsz; -+ -+ zresult = inflate(&zs, Z_SYNC_FLUSH); -+ -+ /* work around a bug in zlib, which sometimes wants to taste an extra -+ * byte when being used in the (undocumented) raw deflate mode. -+ */ -+ if (zresult == Z_OK && !zs.avail_in && zs.avail_out) { -+ __u8 zerostuff = 0; -+ -+ zs.next_in = &zerostuff; -+ zs.avail_in = 1; -+ zresult = inflate(&zs, Z_FINISH); -+ } -+ -+ inflateEnd(&zs); -+ if (zresult != Z_STREAM_END) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "inflate() returned error %d (%s), " -+ "skipping decompression.\n", -+ zresult, -+ zs.msg ? zs.msg : zError(zresult)); -+ *flags |= IPCOMP_DECOMPRESSIONERROR; -+ ipsec_kfree_skb(nskb); -+ -+ return skb; -+ } -+ -+ /* Update IP header */ -+ /* resulting decompressed size */ -+ pyldsz -= zs.avail_out; -+ iph->tot_len = htons(iphlen + pyldsz); -+ iph->protocol = ((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_nh; -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_decompress: " -+ "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: comp=%d, raw=%d, nh=%d.\n", -+ ips ? ntohl(ips->ips_said.spi) : 0, -+ ips ? ntohl(ips->ips_said.spi) & 0x0000ffff : 0, -+ ntohs(((struct ipcomphdr*)(((char*)oiph)+iphlen))->ipcomp_cpi), -+ cpyldsz, -+ pyldsz, -+ iph->protocol); -+ -+#if 1 /* XXX checksum is done by ipsec_rcv ? */ -+ iph->check = 0; -+ iph->check = ip_fast_csum((char*) iph, iph->ihl); -+#endif -+ -+ /* Update skb length/tail by "unputting" the unused data area */ -+ skb_put(nskb, -zs.avail_out); -+ -+ ipsec_kfree_skb(skb); -+ -+ if (iph->protocol == IPPROTO_COMP) -+ { -+#ifdef CONFIG_IPSEC_DEBUG -+ if(sysctl_ipsec_debug_ipcomp) -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_decompress: " -+ "Eh? inner packet is also compressed, dropping.\n"); -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ ipsec_kfree_skb(nskb); -+ return NULL; -+ } -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { -+ __u8 *c; -+ int i; -+ -+ c = (__u8*)iph + iphlen; -+ for(i = 0; i < pyldsz; i++, c++) { -+ if(!(i % 16)) { -+ printk(KERN_INFO "skb_decompress: result:"); -+ } -+ printk("%02x ", *c); -+ if(!((i + 1) % 16)) { -+ printk("\n"); -+ } -+ } -+ if(i % 16) { -+ printk("\n"); -+ } -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ return nskb; -+} -+ -+ -+/* this is derived from skb_copy() in linux 2.2.14 */ -+/* May be incompatible with other kernel versions!! */ -+static -+struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask) -+{ -+ struct sk_buff *n; -+ struct iphdr *iph; -+ unsigned long offset; -+ unsigned int iphlen; -+ -+ if(!skb) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_copy_ipcomp: " -+ "passed in NULL skb, returning NULL.\n"); -+ return NULL; -+ } -+ -+ /* -+ * Allocate the copy buffer -+ */ -+ -+#ifdef NET_21 -+ iph = skb->nh.iph; -+#else /* NET_21 */ -+ iph = skb->ip_hdr; -+#endif /* NET_21 */ -+ if (!iph) return NULL; -+ iphlen = iph->ihl << 2; -+ -+ n=alloc_skb(skb->end - skb->head + data_growth, gfp_mask); -+ if(n==NULL) -+ return NULL; -+ -+ /* -+ * Shift between the two data areas in bytes -+ */ -+ -+ offset=n->head-skb->head; -+ -+ /* Set the data pointer */ -+ skb_reserve(n,skb->data-skb->head); -+ /* Set the tail pointer and length */ -+ skb_put(n,skb->len+data_growth); -+ /* Copy the bytes up to and including the ip header */ -+ memcpy(n->head, -+ skb->head, -+ ((char *)iph - (char *)skb->head) + iphlen); -+ n->list=NULL; -+ n->next=NULL; -+ n->prev=NULL; -+ n->sk=NULL; -+ n->dev=skb->dev; -+ if (skb->h.raw) -+ n->h.raw=skb->h.raw+offset; -+ else -+ n->h.raw=NULL; -+ n->protocol=skb->protocol; -+#ifdef NET_21 -+ n->csum = 0; -+ n->priority=skb->priority; -+ n->dst=dst_clone(skb->dst); -+ n->nh.raw=skb->nh.raw+offset; -+#ifndef NETDEV_23 -+ n->is_clone=0; -+#endif /* NETDEV_23 */ -+ atomic_set(&n->users, 1); -+ n->destructor = NULL; -+ n->security=skb->security; -+ memcpy(n->cb, skb->cb, sizeof(skb->cb)); -+#ifdef CONFIG_IP_FIREWALL -+ n->fwmark = skb->fwmark; -+#endif -+#else /* NET_21 */ -+ n->link3=NULL; -+ n->when=skb->when; -+ n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset); -+ n->saddr=skb->saddr; -+ n->daddr=skb->daddr; -+ n->raddr=skb->raddr; -+ n->seq=skb->seq; -+ n->end_seq=skb->end_seq; -+ n->ack_seq=skb->ack_seq; -+ n->acked=skb->acked; -+ n->free=1; -+ n->arp=skb->arp; -+ n->tries=0; -+ n->lock=0; -+ n->users=0; -+ memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv)); -+#endif /* NET_21 */ -+ if (skb->mac.raw) -+ n->mac.raw=skb->mac.raw+offset; -+ else -+ n->mac.raw=NULL; -+#ifndef NETDEV_23 -+ n->used=skb->used; -+#endif /* !NETDEV_23 */ -+ n->pkt_type=skb->pkt_type; -+#ifndef NETDEV_23 -+ n->pkt_bridged=skb->pkt_bridged; -+#endif /* NETDEV_23 */ -+ n->ip_summed=0; -+ n->stamp=skb->stamp; -+#ifndef NETDEV_23 /* this seems to have been removed in 2.4 */ -+#if defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE) -+ n->shapelatency=skb->shapelatency; /* Latency on frame */ -+ n->shapeclock=skb->shapeclock; /* Time it should go out */ -+ n->shapelen=skb->shapelen; /* Frame length in clocks */ -+ n->shapestamp=skb->shapestamp; /* Stamp for shaper */ -+ n->shapepend=skb->shapepend; /* Pending */ -+#endif /* defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE) */ -+#endif /* NETDEV_23 */ -+#ifdef CONFIG_HIPPI -+ n->private.ifield=skb->private.ifield; -+#endif /* CONFIG_HIPPI */ -+ -+ return n; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_ah.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,363 @@ -+/* -+ * processing code for AH -+ * Copyright (C) 2003-2004 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_ah_c_version[] = "RCSID $Id$"; -+#include -+#include -+ -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define proto_priv cb -+#endif /* NET21 */ -+#include -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipsec_xmit.h" -+ -+#include "openswan/ipsec_auth.h" -+ -+#ifdef CONFIG_IPSEC_AH -+#include "openswan/ipsec_ah.h" -+#endif /* CONFIG_IPSEC_AH */ -+ -+#include "openswan/ipsec_proto.h" -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_ah = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+__u32 zeroes[AH_AMAX]; -+ -+#ifdef CONFIG_IPSEC_AH -+enum ipsec_rcv_value -+ipsec_rcv_ah_checks(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb) -+{ -+ int ahminlen; -+ -+ ahminlen = irs->hard_header_len + sizeof(struct iphdr); -+ -+ /* take care not to deref this pointer until we check the minlen though */ -+ irs->protostuff.ahstuff.ahp = (struct ahhdr *) (skb->data + irs->iphlen); -+ -+ if((skb->len < ahminlen+sizeof(struct ahhdr)) || -+ (skb->len < ahminlen+(irs->protostuff.ahstuff.ahp->ah_hl << 2))) { -+ KLIPS_PRINT(debug_rcv & DB_RX_INAU, -+ "klips_debug:ipsec_rcv: " -+ "runt ah packet of skb->len=%d received from %s, dropped.\n", -+ skb->len, -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_BADLEN; -+ } -+ -+ irs->said.spi = irs->protostuff.ahstuff.ahp->ah_spi; -+ -+ /* XXX we only support the one 12-byte authenticator for now */ -+ if(irs->protostuff.ahstuff.ahp->ah_hl != ((AHHMAC_HASHLEN+AHHMAC_RPLLEN) >> 2)) { -+ KLIPS_PRINT(debug_rcv & DB_RX_INAU, -+ "klips_debug:ipsec_rcv: " -+ "bad authenticator length %ld, expected %lu from %s.\n", -+ (long)(irs->protostuff.ahstuff.ahp->ah_hl << 2), -+ (unsigned long) sizeof(struct ahhdr), -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_BADLEN; -+ } -+ -+ return IPSEC_RCV_OK; -+} -+ -+ -+enum ipsec_rcv_value -+ipsec_rcv_ah_setup_auth(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb, -+ __u32 *replay, -+ unsigned char **authenticator) -+{ -+ struct ahhdr *ahp = irs->protostuff.ahstuff.ahp; -+ -+ *replay = ntohl(ahp->ah_rpl); -+ *authenticator = ahp->ah_data; -+ -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_rcv_value -+ipsec_rcv_ah_authcalc(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb) -+{ -+ struct auth_alg *aa; -+ struct ahhdr *ahp = irs->protostuff.ahstuff.ahp; -+ union { -+ MD5_CTX md5; -+ SHA1_CTX sha1; -+ } tctx; -+ struct iphdr ipo; -+ int ahhlen; -+ -+ aa = irs->authfuncs; -+ -+ /* copy the initialized keying material */ -+ memcpy(&tctx, irs->ictx, irs->ictx_len); -+ -+ ipo = *irs->ipp; -+ ipo.tos = 0; /* mutable RFC 2402 3.3.3.1.1.1 */ -+ ipo.frag_off = 0; -+ ipo.ttl = 0; -+ ipo.check = 0; -+ -+ -+ /* do the sanitized header */ -+ (*aa->update)((void*)&tctx, (caddr_t)&ipo, sizeof(struct iphdr)); -+ -+ /* XXX we didn't do the options here! */ -+ -+ /* now do the AH header itself */ -+ ahhlen = AH_BASIC_LEN + (ahp->ah_hl << 2); -+ (*aa->update)((void*)&tctx, (caddr_t)ahp, ahhlen - AHHMAC_HASHLEN); -+ -+ /* now, do some zeroes */ -+ (*aa->update)((void*)&tctx, (caddr_t)zeroes, AHHMAC_HASHLEN); -+ -+ /* finally, do the packet contents themselves */ -+ (*aa->update)((void*)&tctx, -+ (caddr_t)skb->data + irs->iphlen + ahhlen, -+ skb->len - irs->iphlen - ahhlen); -+ -+ (*aa->final)(irs->hash, (void *)&tctx); -+ -+ memcpy(&tctx, irs->octx, irs->octx_len); -+ -+ (*aa->update)((void *)&tctx, irs->hash, aa->hashlen); -+ (*aa->final)(irs->hash, (void *)&tctx); -+ -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_rcv_value -+ipsec_rcv_ah_decap(struct ipsec_rcv_state *irs) -+{ -+ struct ahhdr *ahp = irs->protostuff.ahstuff.ahp; -+ struct sk_buff *skb; -+ int ahhlen; -+ -+ skb=irs->skb; -+ -+ ahhlen = AH_BASIC_LEN + (ahp->ah_hl << 2); -+ -+ irs->ipp->tot_len = htons(ntohs(irs->ipp->tot_len) - ahhlen); -+ irs->next_header = ahp->ah_nh; -+ -+ /* -+ * move the IP header forward by the size of the AH header, which -+ * will remove the the AH header from the packet. -+ */ -+ memmove((void *)(skb->data + ahhlen), -+ (void *)(skb->data), irs->iphlen); -+ -+ ipsec_rcv_dmp("ah postmove", skb->data, skb->len); -+ -+ /* skb_pull below, will move up by ahhlen */ -+ -+ /* XXX not clear how this can happen, as the message indicates */ -+ if(skb->len < ahhlen) { -+ printk(KERN_WARNING -+ "klips_error:ipsec_rcv: " -+ "tried to skb_pull ahhlen=%d, %d available. This should never happen, please report.\n", -+ ahhlen, -+ (int)(skb->len)); -+ return IPSEC_RCV_DECAPFAIL; -+ } -+ skb_pull(skb, ahhlen); -+ -+ irs->ipp = (struct iphdr *)skb->data; -+ -+ ipsec_rcv_dmp("ah postpull", skb->data, skb->len); -+ -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_xmit_ah_setup(struct ipsec_xmit_state *ixs) -+{ -+ struct iphdr ipo; -+ struct ahhdr *ahp; -+ __u8 hash[AH_AMAX]; -+ union { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ MD5_CTX md5; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ SHA1_CTX sha1; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ } tctx; -+ unsigned char *dat = (unsigned char *)ixs->iph; -+ -+ ahp = (struct ahhdr *)(dat + ixs->iphlen); -+ ahp->ah_spi = ixs->ipsp->ips_said.spi; -+ ahp->ah_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); -+ ahp->ah_rv = 0; -+ ahp->ah_nh = ixs->iph->protocol; -+ ahp->ah_hl = (sizeof(struct ahhdr) >> 2) - sizeof(__u64)/sizeof(__u32); -+ ixs->iph->protocol = IPPROTO_AH; -+ ipsec_xmit_dmp("ahp", (char*)ahp, sizeof(*ahp)); -+ -+ ipo = *ixs->iph; -+ ipo.tos = 0; -+ ipo.frag_off = 0; -+ ipo.ttl = 0; -+ ipo.check = 0; -+ ipsec_xmit_dmp("ipo", (char*)&ipo, sizeof(ipo)); -+ -+ switch(ixs->ipsp->ips_authalg) { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ ipsec_xmit_dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr)); -+ ipsec_xmit_dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (unsigned char *)ahp, -+ sizeof(struct ahhdr) - sizeof(ahp->ah_data)); -+ ipsec_xmit_dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN); -+ ipsec_xmit_dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, dat + ixs->iphlen + sizeof(struct ahhdr), -+ ixs->skb->len - ixs->iphlen - sizeof(struct ahhdr)); -+ ipsec_xmit_dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ ipsec_xmit_dmp("ictx hash", (char*)&hash, sizeof(hash)); -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ ipsec_xmit_dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, hash, AHMD596_ALEN); -+ ipsec_xmit_dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ ipsec_xmit_dmp("octx hash", (char*)&hash, sizeof(hash)); -+ -+ memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ SHA1Update(&tctx.sha1, (unsigned char *)&ipo, sizeof (struct iphdr)); -+ SHA1Update(&tctx.sha1, (unsigned char *)ahp, sizeof(struct ahhdr) - sizeof(ahp->ah_data)); -+ SHA1Update(&tctx.sha1, (unsigned char *)zeroes, AHHMAC_HASHLEN); -+ SHA1Update(&tctx.sha1, dat + ixs->iphlen + sizeof(struct ahhdr), -+ ixs->skb->len - ixs->iphlen - sizeof(struct ahhdr)); -+ SHA1Final(hash, &tctx.sha1); -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); -+ SHA1Final(hash, &tctx.sha1); -+ -+ memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_AH_BADALG; -+ } -+#ifdef NET_21 -+ ixs->skb->h.raw = (unsigned char*)ahp; -+#endif /* NET_21 */ -+ -+ return IPSEC_XMIT_OK; -+} -+ -+struct xform_functions ah_xform_funcs[]={ -+ { rcv_checks: ipsec_rcv_ah_checks, -+ rcv_setup_auth: ipsec_rcv_ah_setup_auth, -+ rcv_calc_auth: ipsec_rcv_ah_authcalc, -+ rcv_decrypt: ipsec_rcv_ah_decap, -+ -+ xmit_setup: ipsec_xmit_ah_setup, -+ xmit_headroom: sizeof(struct ahhdr), -+ xmit_needtailroom: 0, -+ }, -+}; -+ -+struct inet_protocol ah_protocol = -+{ -+ ipsec_rcv, /* AH handler */ -+ NULL, /* TUNNEL error control */ -+#ifdef NETDEV_25 -+ 1, /* no policy */ -+#else -+ 0, /* next */ -+ IPPROTO_AH, /* protocol ID */ -+ 0, /* copy */ -+ NULL, /* data */ -+ "AH" /* name */ -+#endif -+}; -+ -+#endif /* CONFIG_IPSEC_AH */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.2 2004/04/06 02:49:25 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_alg.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,953 @@ -+/* -+ * Modular extensions service and registration functions -+ * -+ * Author: JuanJo Ciarlante -+ * -+ * Version: 0.8.1 -+ * -+ * ipsec_alg.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ */ -+#ifdef CONFIG_IPSEC_ALG -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#include -+#include -+#include /* memcmp() */ -+#include /* get_random_bytes() */ -+#include /* error codes */ -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define proto_priv cb -+#endif /* NET21 */ -+#include "openswan/ipsec_param.h" -+#include -+#include "openswan/ipsec_sa.h" -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+#if defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH) -+# include "openswan/ipsec_ah.h" -+#endif /* defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH) */ -+#ifdef CONFIG_IPSEC_ESP -+# include "openswan/ipsec_esp.h" -+#endif /* !CONFIG_IPSEC_ESP */ -+#ifdef CONFIG_IPSEC_IPCOMP -+# include "openswan/ipcomp.h" -+#endif /* CONFIG_IPSEC_COMP */ -+ -+#include -+#include -+ -+#include "openswan/ipsec_alg.h" -+ -+#ifndef CONFIG_IPSEC_ALG -+#error This file _MUST_ be compiled with CONFIG_IPSEC_ALG enabled ! -+#endif -+#if SADB_EALG_MAX < 255 -+#warning Compiling with limited ESP support ( SADB_EALG_MAX < 256 ) -+#endif -+ -+static rwlock_t ipsec_alg_lock = RW_LOCK_UNLOCKED; -+#define IPSEC_ALG_HASHSZ 16 /* must be power of 2, even 2^0=1 */ -+static struct list_head ipsec_alg_hash_table[IPSEC_ALG_HASHSZ]; -+ -+/* Old gcc's will fail here */ -+#define barf_out(fmt, args...) do { printk(KERN_ERR "%s: (%s) " fmt, __FUNCTION__, ixt->ixt_name , ## args)\ -+ ; goto out; } while(0) -+ -+/* -+ * Must be already protected by lock -+ */ -+static void __ipsec_alg_usage_inc(struct ipsec_alg *ixt) { -+ if (ixt->ixt_module) -+ __MOD_INC_USE_COUNT(ixt->ixt_module); -+ atomic_inc(&ixt->ixt_refcnt); -+} -+static void __ipsec_alg_usage_dec(struct ipsec_alg *ixt) { -+ atomic_dec(&ixt->ixt_refcnt); -+ if (ixt->ixt_module) -+ __MOD_DEC_USE_COUNT(ixt->ixt_module); -+} -+/* -+ * simple hash function, optimized for 0-hash (1 list) special -+ * case -+ */ -+#if IPSEC_ALG_HASHSZ > 1 -+static inline unsigned ipsec_alg_hashfn(int alg_type, int alg_id) { -+ return ((alg_type^alg_id)&(IPSEC_ALG_HASHSZ-1)); -+} -+#else -+#define ipsec_alg_hashfn(x,y) (0) -+#endif -+ -+/***************************************************************** -+ * -+ * INTERNAL table handling: insert, delete, find -+ * -+ *****************************************************************/ -+ -+/* -+ * hash table initialization, called from ipsec_alg_init() -+ */ -+static void ipsec_alg_hash_init(void) { -+ struct list_head *head = ipsec_alg_hash_table; -+ int i = IPSEC_ALG_HASHSZ; -+ do { -+ INIT_LIST_HEAD(head); -+ head++; -+ i--; -+ } while (i); -+} -+/* -+ * hash list lookup by {alg_type, alg_id} and table head, -+ * must be already protected by lock -+ */ -+static struct ipsec_alg *__ipsec_alg_find(unsigned alg_type, unsigned alg_id, struct list_head * head) { -+ struct list_head *p; -+ struct ipsec_alg *ixt=NULL; -+ for (p=head->next; p!=head; p=p->next) { -+ ixt = list_entry(p, struct ipsec_alg, ixt_list); -+ if (ixt->ixt_alg_type == alg_type && ixt->ixt_alg_id==alg_id) { -+ goto out; -+ } -+ } -+ ixt=NULL; -+out: -+ return ixt; -+} -+/* -+ * inserts (in front) a new entry in hash table, -+ * called from ipsec_alg_register() when new algorithm is registered. -+ */ -+static int ipsec_alg_insert(struct ipsec_alg *ixt) { -+ int ret=-EINVAL; -+ unsigned hashval=ipsec_alg_hashfn(ixt->ixt_alg_type, ixt->ixt_alg_id); -+ struct list_head *head= ipsec_alg_hash_table + hashval; -+ struct ipsec_alg *ixt_cur; -+ /* new element must be virgin ... */ -+ if (ixt->ixt_list.next != &ixt->ixt_list || -+ ixt->ixt_list.prev != &ixt->ixt_list) { -+ printk(KERN_ERR "ipsec_alg_insert: ixt object \"%s\" " -+ "list head not initialized\n", -+ ixt->ixt_name); -+ return ret; -+ } -+ write_lock_bh(&ipsec_alg_lock); -+ ixt_cur = __ipsec_alg_find(ixt->ixt_alg_type, ixt->ixt_alg_id, head); -+ /* if previous (current) ipsec_alg found check excl flag of _anyone_ */ -+ if (ixt_cur && ((ixt->ixt_state|ixt_cur->ixt_state) & IPSEC_ALG_ST_EXCL)) -+ barf_out("ipsec_alg for alg_type=%d, alg_id=%d already exist. " -+ "Not loaded (ret=%d).\n", -+ ixt->ixt_alg_type, -+ ixt->ixt_alg_id, ret=-EEXIST); -+ list_add(&ixt->ixt_list, head); -+ ixt->ixt_state |= IPSEC_ALG_ST_REGISTERED; -+ ret=0; -+out: -+ write_unlock_bh(&ipsec_alg_lock); -+ return ret; -+} -+/* -+ * deletes an existing entry in hash table, -+ * called from ipsec_alg_unregister() when algorithm is unregistered. -+ */ -+static int ipsec_alg_delete(struct ipsec_alg *ixt) { -+ write_lock_bh(&ipsec_alg_lock); -+ list_del(&ixt->ixt_list); -+ write_unlock_bh(&ipsec_alg_lock); -+ return 0; -+} -+/* -+ * here @user context (read-only when @kernel bh context) -+ * -> no bh disabling -+ * -+ * called from ipsec_sa_init() -> ipsec_alg_sa_init() -+ */ -+static struct ipsec_alg *ipsec_alg_get(int alg_type, int alg_id) { -+ unsigned hashval=ipsec_alg_hashfn(alg_type, alg_id); -+ struct list_head *head= ipsec_alg_hash_table + hashval; -+ struct ipsec_alg *ixt; -+ read_lock(&ipsec_alg_lock); -+ ixt=__ipsec_alg_find(alg_type, alg_id, head); -+ if (ixt) __ipsec_alg_usage_inc(ixt); -+ read_unlock(&ipsec_alg_lock); -+ return ixt; -+} -+ -+static void ipsec_alg_put(struct ipsec_alg *ixt) { -+ __ipsec_alg_usage_dec((struct ipsec_alg *)ixt); -+} -+ -+/***************************************************************** -+ * -+ * INTERFACE for ENC services: key creation, encrypt function -+ * -+ *****************************************************************/ -+ -+/* -+ * main encrypt service entry point -+ * called from ipsec_rcv() with encrypt=IPSEC_ALG_DECRYPT and -+ * ipsec_tunnel_start_xmit with encrypt=IPSEC_ALG_ENCRYPT -+ */ -+int ipsec_alg_esp_encrypt(struct ipsec_sa *sa_p, __u8 * idat, int ilen, const __u8 * iv, int encrypt) { -+ int ret; -+ struct ipsec_alg_enc *ixt_e=sa_p->ips_alg_enc; -+ KLIPS_PRINT(debug_rcv||debug_tunnel, -+ "klips_debug:ipsec_alg_esp_encrypt: " -+ "entering with encalg=%d, ixt_e=%p\n", -+ sa_p->ips_encalg, ixt_e); -+ if (!ixt_e) { -+ KLIPS_PRINT(debug_rcv||debug_tunnel, -+ "klips_debug:ipsec_alg_esp_encrypt: " -+ "NULL ipsec_alg_enc object\n"); -+ return -1; -+ } -+ KLIPS_PRINT(debug_rcv||debug_tunnel, -+ "klips_debug:ipsec_alg_esp_encrypt: " -+ "calling cbc_encrypt encalg=%d " -+ "ips_key_e=%p idat=%p ilen=%d iv=%p, encrypt=%d\n", -+ sa_p->ips_encalg, -+ sa_p->ips_key_e, idat, ilen, iv, encrypt); -+ ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, sa_p->ips_key_e, idat, ilen, iv, encrypt); -+ KLIPS_PRINT(debug_rcv||debug_tunnel, -+ "klips_debug:ipsec_alg_esp_encrypt: " -+ "returned ret=%d\n", -+ ret); -+ return ret; -+} -+/* -+ * encryption key context creation function -+ * called from pfkey_v2_parser.c:pfkey_ips_init() -+ */ -+int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p) { -+ int ret=-EINVAL; -+ int keyminbits, keymaxbits; -+ caddr_t ekp; -+ struct ipsec_alg_enc *ixt_e=sa_p->ips_alg_enc; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_alg_enc_key_create: " -+ "entering with encalg=%d ixt_e=%p\n", -+ sa_p->ips_encalg, ixt_e); -+ if (!ixt_e) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_alg_enc_key_create: " -+ "NULL ipsec_alg_enc object\n"); -+ return -EPROTO; -+ } -+ -+ /* -+ * grRRR... DES 7bits jurassic stuff ... f*ckk --jjo -+ */ -+ switch(ixt_e->ixt_alg_id) { -+ case ESP_3DES: -+ keyminbits=keymaxbits=192;break; -+ case ESP_DES: -+ keyminbits=keymaxbits=64;break; -+ default: -+ keyminbits=ixt_e->ixt_keyminbits; -+ keymaxbits=ixt_e->ixt_keymaxbits; -+ } -+ if(sa_p->ips_key_bits_eips_key_bits_e>keymaxbits) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_alg_enc_key_create: " -+ "incorrect encryption key size for id=%d: %d bits -- " -+ "must be between %d,%d bits\n" /*octets (bytes)\n"*/, -+ ixt_e->ixt_alg_id, -+ sa_p->ips_key_bits_e, keyminbits, keymaxbits); -+ ret=-EINVAL; -+ goto ixt_out; -+ } -+ /* save encryption key pointer */ -+ ekp = sa_p->ips_key_e; -+ -+ -+ if (ixt_e->ixt_e_new_key) { -+ sa_p->ips_key_e = ixt_e->ixt_e_new_key(ixt_e, -+ ekp, sa_p->ips_key_bits_e/8); -+ ret = (sa_p->ips_key_e)? 0 : -EINVAL; -+ } else { -+ if((sa_p->ips_key_e = (caddr_t) -+ kmalloc((sa_p->ips_key_e_size = ixt_e->ixt_e_ctx_size), -+ GFP_ATOMIC)) == NULL) { -+ ret=-ENOMEM; -+ goto ixt_out; -+ } -+ /* zero-out key_e */ -+ memset(sa_p->ips_key_e, 0, sa_p->ips_key_e_size); -+ -+ /* I cast here to allow more decoupling in alg module */ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_alg_enc_key_create: about to call:" -+ "set_key(key_e=%p, ekp=%p, key_size=%d)\n", -+ (caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8); -+ ret = ixt_e->ixt_e_set_key(ixt_e, (caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8); -+ } -+ /* paranoid */ -+ memset(ekp, 0, sa_p->ips_key_bits_e/8); -+ kfree(ekp); -+ixt_out: -+ return ret; -+} -+ -+/*************************************************************** -+ * -+ * INTERFACE for AUTH services: key creation, hash functions -+ * -+ ***************************************************************/ -+ -+/* -+ * auth key context creation function -+ * called from pfkey_v2_parser.c:pfkey_ips_init() -+ */ -+int ipsec_alg_auth_key_create(struct ipsec_sa *sa_p) { -+ int ret=-EINVAL; -+ struct ipsec_alg_auth *ixt_a=sa_p->ips_alg_auth; -+ int keyminbits, keymaxbits; -+ unsigned char *akp; -+ unsigned int aks; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_alg_auth_key_create: " -+ "entering with authalg=%d ixt_a=%p\n", -+ sa_p->ips_authalg, ixt_a); -+ if (!ixt_a) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_alg_auth_key_create: " -+ "NULL ipsec_alg_auth object\n"); -+ return -EPROTO; -+ } -+ keyminbits=ixt_a->ixt_keyminbits; -+ keymaxbits=ixt_a->ixt_keymaxbits; -+ if(sa_p->ips_key_bits_aips_key_bits_a>keymaxbits) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_alg_auth_key_create: incorrect auth" -+ "key size: %d bits -- must be between %d,%d bits\n"/*octets (bytes)\n"*/, -+ sa_p->ips_key_bits_a, keyminbits, keymaxbits); -+ ret=-EINVAL; -+ goto ixt_out; -+ } -+ /* save auth key pointer */ -+ sa_p->ips_auth_bits = ixt_a->ixt_a_keylen * 8; /* XXX XXX */ -+ akp = sa_p->ips_key_a; -+ aks = sa_p->ips_key_a_size; -+ -+ /* will hold: 2 ctx and a blocksize buffer: kb */ -+ sa_p->ips_key_a_size = ixt_a->ixt_a_ctx_size; -+ if((sa_p->ips_key_a = -+ (caddr_t) kmalloc(sa_p->ips_key_a_size, GFP_ATOMIC)) == NULL) { -+ ret=-ENOMEM; -+ goto ixt_out; -+ } -+ ixt_a->ixt_a_hmac_set_key(ixt_a, sa_p->ips_key_a, akp, sa_p->ips_key_bits_a/8); /* XXX XXX */ -+ ret=0; -+ memset(akp, 0, aks); -+ kfree(akp); -+ -+ixt_out: -+ return ret; -+} -+ -+ -+int ipsec_alg_sa_esp_hash(const struct ipsec_sa *sa_p, const __u8 *espp, int len, __u8 *hash, int hashlen) { -+ struct ipsec_alg_auth *ixt_a=sa_p->ips_alg_auth; -+ if (!ixt_a) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_sa_esp_hash: " -+ "NULL ipsec_alg_auth object\n"); -+ return -EPROTO; -+ } -+ KLIPS_PRINT(debug_tunnel|debug_rcv, -+ "klips_debug:ipsec_sa_esp_hash: " -+ "hashing %p (%d bytes) to %p (%d bytes)\n", -+ espp, len, -+ hash, hashlen); -+ ixt_a->ixt_a_hmac_hash(ixt_a, -+ sa_p->ips_key_a, -+ espp, len, -+ hash, hashlen); -+ return 0; -+} -+ -+/*************************************************************** -+ * -+ * INTERFACE for module loading,testing, and unloading -+ * -+ ***************************************************************/ -+ -+/* validation for registering (enc) module */ -+static int check_enc(struct ipsec_alg_enc *ixt) { -+ int ret=-EINVAL; -+ if (ixt->ixt_alg_id==0 || ixt->ixt_alg_id > SADB_EALG_MAX) -+ barf_out("invalid alg_id=%d >= %d\n", ixt->ixt_alg_id, SADB_EALG_MAX); -+ if (ixt->ixt_blocksize==0) /* || ixt->ixt_blocksize%2) need for ESP_NULL */ -+ barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_blocksize); -+ if (ixt->ixt_keyminbits==0 && ixt->ixt_keymaxbits==0 && ixt->ixt_e_keylen==0) -+ goto zero_key_ok; -+ if (ixt->ixt_keyminbits==0) -+ barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_keyminbits); -+ if (ixt->ixt_keymaxbits==0) -+ barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_keymaxbits); -+ if (ixt->ixt_e_keylen==0) -+ barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_e_keylen); -+zero_key_ok: -+ if (ixt->ixt_e_ctx_size==0 && ixt->ixt_e_new_key == NULL) -+ barf_out(KERN_ERR "invalid key_e_size=%d and ixt_e_new_key=NULL\n", ixt->ixt_e_ctx_size); -+ if (ixt->ixt_e_cbc_encrypt==NULL) -+ barf_out(KERN_ERR "e_cbc_encrypt() must be not NULL\n"); -+ ret=0; -+out: -+ return ret; -+} -+ -+/* validation for registering (auth) module */ -+static int check_auth(struct ipsec_alg_auth *ixt) -+{ -+ int ret=-EINVAL; -+ if (ixt->ixt_alg_id==0 || ixt->ixt_alg_id > SADB_AALG_MAX) -+ barf_out("invalid alg_id=%d > %d (SADB_AALG_MAX)\n", ixt->ixt_alg_id, SADB_AALG_MAX); -+ if (ixt->ixt_blocksize==0 || ixt->ixt_blocksize%2) -+ barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_blocksize); -+ if (ixt->ixt_blocksize>AH_BLKLEN_MAX) -+ barf_out(KERN_ERR "sorry blocksize=%d > %d. " -+ "Please increase AH_BLKLEN_MAX and recompile\n", -+ ixt->ixt_blocksize, -+ AH_BLKLEN_MAX); -+ if (ixt->ixt_keyminbits==0 && ixt->ixt_keymaxbits==0 && ixt->ixt_a_keylen==0) -+ goto zero_key_ok; -+ if (ixt->ixt_keyminbits==0) -+ barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_keyminbits); -+ if (ixt->ixt_keymaxbits==0) -+ barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_keymaxbits); -+ if (ixt->ixt_keymaxbits!=ixt->ixt_keyminbits) -+ barf_out(KERN_ERR "keymaxbits must equal keyminbits (not sure).\n"); -+ if (ixt->ixt_a_keylen==0) -+ barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_a_keylen); -+zero_key_ok: -+ if (ixt->ixt_a_ctx_size==0) -+ barf_out(KERN_ERR "invalid a_ctx_size=%d\n", ixt->ixt_a_ctx_size); -+ if (ixt->ixt_a_hmac_set_key==NULL) -+ barf_out(KERN_ERR "a_hmac_set_key() must be not NULL\n"); -+ if (ixt->ixt_a_hmac_hash==NULL) -+ barf_out(KERN_ERR "a_hmac_hash() must be not NULL\n"); -+ ret=0; -+out: -+ return ret; -+} -+ -+/* -+ * Generic (enc, auth) registration entry point -+ */ -+int register_ipsec_alg(struct ipsec_alg *ixt) { -+ int ret=-EINVAL; -+ /* Validation */ -+ if (ixt==NULL) -+ barf_out("NULL ipsec_alg object passed\n"); -+ if ((ixt->ixt_version&0xffffff00) != (IPSEC_ALG_VERSION&0xffffff00)) -+ barf_out("incorrect version: %d.%d.%d-%d, " -+ "must be %d.%d.%d[-%d]\n", -+ IPSEC_ALG_VERSION_QUAD(ixt->ixt_version), -+ IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION)); -+ switch(ixt->ixt_alg_type) { -+ case IPSEC_ALG_TYPE_AUTH: -+ if ((ret=check_auth((struct ipsec_alg_auth *)ixt)<0)) -+ goto out; -+ break; -+ case IPSEC_ALG_TYPE_ENCRYPT: -+ if ((ret=check_enc((struct ipsec_alg_enc *)ixt)<0)) -+ goto out; -+ /* -+ * Adapted two lines below: -+ * ivlen == 0 is possible (NULL enc has blocksize==1) -+ * -+ * fixed NULL support by David De Reu -+ */ -+ if (ixt->ixt_ivlen == 0 && ixt->ixt_blocksize > 1) -+ ixt->ixt_ivlen = ixt->ixt_blocksize*8; -+ break; -+ default: -+ barf_out("alg_type=%d not supported\n", ixt->ixt_alg_type); -+ } -+ INIT_LIST_HEAD(&ixt->ixt_list); -+ ret = ipsec_alg_insert(ixt); -+ if (ret<0) -+ barf_out(KERN_WARNING "ipsec_alg for alg_id=%d failed." -+ "Not loaded (ret=%d).\n", -+ ixt->ixt_alg_id, ret); -+ -+ ret = pfkey_list_insert_supported((struct supported *)&ixt->ixt_support, &(pfkey_supported_list[SADB_SATYPE_ESP])); -+ if (ret==0) { -+ ixt->ixt_state |= IPSEC_ALG_ST_SUPP; -+ /* send register event to userspace */ -+ pfkey_register_reply(SADB_SATYPE_ESP, NULL); -+ } else -+ printk(KERN_ERR "pfkey_list_insert_supported returned %d. " -+ "Loading anyway.\n", ret); -+ ret=0; -+out: -+ return ret; -+} -+ -+/* -+ * unregister ipsec_alg object from own tables, if -+ * success => calls pfkey_list_remove_supported() -+ */ -+int unregister_ipsec_alg(struct ipsec_alg *ixt) { -+ int ret= -EINVAL; -+ switch(ixt->ixt_alg_type) { -+ case IPSEC_ALG_TYPE_AUTH: -+ case IPSEC_ALG_TYPE_ENCRYPT: -+ break; -+ default: -+ /* this is not a typo :) */ -+ barf_out("frog found in list (\"%s\"): ixt_p=NULL\n", -+ ixt->ixt_name); -+ } -+ -+ ret=ipsec_alg_delete(ixt); -+ if (ixt->ixt_state&IPSEC_ALG_ST_SUPP) { -+ ixt->ixt_state &= ~IPSEC_ALG_ST_SUPP; -+ pfkey_list_remove_supported((struct supported *)&ixt->ixt_support, &(pfkey_supported_list[SADB_SATYPE_ESP])); -+ /* send register event to userspace */ -+ pfkey_register_reply(SADB_SATYPE_ESP, NULL); -+ } -+ -+out: -+ return ret; -+} -+ -+/* -+ * Must be called from user context -+ * used at module load type for testing algo implementation -+ */ -+static int ipsec_alg_test_encrypt(int enc_alg, int test) { -+ int ret; -+ caddr_t buf = NULL; -+ int iv_size, keysize, key_e_size; -+ struct ipsec_alg_enc *ixt_e; -+ void *tmp_key_e = NULL; -+ #define BUFSZ 1024 -+ #define MARGIN 0 -+ #define test_enc (buf+MARGIN) -+ #define test_dec (test_enc+BUFSZ+MARGIN) -+ #define test_tmp (test_dec+BUFSZ+MARGIN) -+ #define test_key_e (test_tmp+BUFSZ+MARGIN) -+ #define test_iv (test_key_e+key_e_size+MARGIN) -+ #define test_key (test_iv+iv_size+MARGIN) -+ #define test_size (BUFSZ*3+key_e_size+iv_size+keysize+MARGIN*7) -+ ixt_e=(struct ipsec_alg_enc *)ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, enc_alg); -+ if (ixt_e==NULL) { -+ KLIPS_PRINT(1, -+ "klips_debug: ipsec_alg_test_encrypt: " -+ "encalg=%d object not found\n", -+ enc_alg); -+ ret=-EINVAL; -+ goto out; -+ } -+ iv_size=ixt_e->ixt_ivlen / 8; -+ key_e_size=ixt_e->ixt_e_ctx_size; -+ keysize=ixt_e->ixt_e_keylen; -+ KLIPS_PRINT(1, -+ "klips_debug: ipsec_alg_test_encrypt: " -+ "enc_alg=%d blocksize=%d key_e_size=%d keysize=%d\n", -+ enc_alg, iv_size, key_e_size, keysize); -+ if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) { -+ ret= -ENOMEM; -+ goto out; -+ } -+ get_random_bytes(test_key, keysize); -+ get_random_bytes(test_iv, iv_size); -+ if (ixt_e->ixt_e_new_key) { -+ tmp_key_e = ixt_e->ixt_e_new_key(ixt_e, test_key, keysize); -+ ret = tmp_key_e ? 0 : -EINVAL; -+ } else { -+ tmp_key_e = test_key_e; -+ ret = ixt_e->ixt_e_set_key(ixt_e, test_key_e, test_key, keysize); -+ } -+ if (ret < 0) -+ goto out; -+ get_random_bytes(test_enc, BUFSZ); -+ memcpy(test_tmp, test_enc, BUFSZ); -+ ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_enc, BUFSZ, test_iv, 1); -+ printk(KERN_INFO -+ "klips_info: ipsec_alg_test_encrypt: " -+ "cbc_encrypt=1 ret=%d\n", -+ ret); -+ ret=memcmp(test_enc, test_tmp, BUFSZ); -+ printk(KERN_INFO -+ "klips_info: ipsec_alg_test_encrypt: " -+ "memcmp(enc, tmp) ret=%d: %s\n", ret, -+ ret!=0? "OK. (encr->DIFFers)" : "FAIL! (encr->SAME)" ); -+ memcpy(test_dec, test_enc, BUFSZ); -+ ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_dec, BUFSZ, test_iv, 0); -+ printk(KERN_INFO -+ "klips_info: ipsec_alg_test_encrypt: " -+ "cbc_encrypt=0 ret=%d\n", ret); -+ ret=memcmp(test_dec, test_tmp, BUFSZ); -+ printk(KERN_INFO -+ "klips_info: ipsec_alg_test_encrypt: " -+ "memcmp(dec,tmp) ret=%d: %s\n", ret, -+ ret==0? "OK. (encr->decr->SAME)" : "FAIL! (encr->decr->DIFFers)" ); -+ { -+ /* Shamelessly taken from drivers/md sources O:) */ -+ unsigned long now; -+ int i, count, max=0; -+ int encrypt, speed; -+ for (encrypt=0; encrypt <2;encrypt ++) { -+ for (i = 0; i < 5; i++) { -+ now = jiffies; -+ count = 0; -+ while (jiffies == now) { -+ mb(); -+ ixt_e->ixt_e_cbc_encrypt(ixt_e, -+ tmp_key_e, test_tmp, -+ BUFSZ, test_iv, encrypt); -+ mb(); -+ count++; -+ mb(); -+ } -+ if (count > max) -+ max = count; -+ } -+ speed = max * (HZ * BUFSZ / 1024); -+ printk(KERN_INFO -+ "klips_info: ipsec_alg_test_encrypt: " -+ "%s %s speed=%d KB/s\n", -+ ixt_e->ixt_name, -+ encrypt? "encrypt": "decrypt", speed); -+ } -+ } -+out: -+ if (tmp_key_e && ixt_e->ixt_e_destroy_key) ixt_e->ixt_e_destroy_key(ixt_e, tmp_key_e); -+ if (buf) kfree(buf); -+ if (ixt_e) ipsec_alg_put((struct ipsec_alg *)ixt_e); -+ return ret; -+ #undef test_enc -+ #undef test_dec -+ #undef test_tmp -+ #undef test_key_e -+ #undef test_iv -+ #undef test_key -+ #undef test_size -+} -+ -+/* -+ * Must be called from user context -+ * used at module load type for testing algo implementation -+ */ -+static int ipsec_alg_test_auth(int auth_alg, int test) { -+ int ret; -+ caddr_t buf = NULL; -+ int blocksize, keysize, key_a_size; -+ struct ipsec_alg_auth *ixt_a; -+ #define BUFSZ 1024 -+ #define MARGIN 0 -+ #define test_auth (buf+MARGIN) -+ #define test_key_a (test_auth+BUFSZ+MARGIN) -+ #define test_key (test_key_a+key_a_size+MARGIN) -+ #define test_hash (test_key+keysize+MARGIN) -+ #define test_size (BUFSZ+key_a_size+keysize+AHHMAC_HASHLEN+MARGIN*4) -+ ixt_a=(struct ipsec_alg_auth *)ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, auth_alg); -+ if (ixt_a==NULL) { -+ KLIPS_PRINT(1, -+ "klips_debug: ipsec_alg_test_auth: " -+ "encalg=%d object not found\n", -+ auth_alg); -+ ret=-EINVAL; -+ goto out; -+ } -+ blocksize=ixt_a->ixt_blocksize; -+ key_a_size=ixt_a->ixt_a_ctx_size; -+ keysize=ixt_a->ixt_a_keylen; -+ KLIPS_PRINT(1, -+ "klips_debug: ipsec_alg_test_auth: " -+ "auth_alg=%d blocksize=%d key_a_size=%d keysize=%d\n", -+ auth_alg, blocksize, key_a_size, keysize); -+ if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) { -+ ret= -ENOMEM; -+ goto out; -+ } -+ get_random_bytes(test_key, keysize); -+ ret = ixt_a->ixt_a_hmac_set_key(ixt_a, test_key_a, test_key, keysize); -+ if (ret < 0 ) -+ goto out; -+ get_random_bytes(test_auth, BUFSZ); -+ ret=ixt_a->ixt_a_hmac_hash(ixt_a, test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN); -+ printk(KERN_INFO -+ "klips_info: ipsec_alg_test_auth: " -+ "ret=%d\n", ret); -+ { -+ /* Shamelessly taken from drivers/md sources O:) */ -+ unsigned long now; -+ int i, count, max=0; -+ int speed; -+ for (i = 0; i < 5; i++) { -+ now = jiffies; -+ count = 0; -+ while (jiffies == now) { -+ mb(); -+ ixt_a->ixt_a_hmac_hash(ixt_a, test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN); -+ mb(); -+ count++; -+ mb(); -+ } -+ if (count > max) -+ max = count; -+ } -+ speed = max * (HZ * BUFSZ / 1024); -+ printk(KERN_INFO -+ "klips_info: ipsec_alg_test_auth: " -+ "%s hash speed=%d KB/s\n", -+ ixt_a->ixt_name, -+ speed); -+ } -+out: -+ if (buf) kfree(buf); -+ if (ixt_a) ipsec_alg_put((struct ipsec_alg *)ixt_a); -+ return ret; -+ #undef test_auth -+ #undef test_key_a -+ #undef test_key -+ #undef test_hash -+ #undef test_size -+} -+ -+int ipsec_alg_test(unsigned alg_type, unsigned alg_id, int test) { -+ switch(alg_type) { -+ case IPSEC_ALG_TYPE_ENCRYPT: -+ return ipsec_alg_test_encrypt(alg_id, test); -+ break; -+ case IPSEC_ALG_TYPE_AUTH: -+ return ipsec_alg_test_auth(alg_id, test); -+ break; -+ } -+ printk(KERN_ERR "klips_info: ipsec_alg_test() called incorrectly: " -+ "alg_type=%d alg_id=%d\n", -+ alg_type, alg_id); -+ return -EINVAL; -+} -+ -+int ipsec_alg_init(void) { -+ KLIPS_PRINT(1, "klips_info:ipsec_alg_init: " -+ "KLIPS alg v=%d.%d.%d-%d (EALG_MAX=%d, AALG_MAX=%d)\n", -+ IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION), -+ SADB_EALG_MAX, SADB_AALG_MAX); -+ /* Initialize tables */ -+ write_lock_bh(&ipsec_alg_lock); -+ ipsec_alg_hash_init(); -+ write_unlock_bh(&ipsec_alg_lock); -+ -+ /* Initialize static algos */ -+ KLIPS_PRINT(1, "klips_info:ipsec_alg_init: " -+ "calling ipsec_alg_static_init()\n"); -+ -+ /* If we are suppose to use our AES, and don't have CryptoAPI enabled... */ -+#if defined(CONFIG_IPSEC_ENC_AES) && CONFIG_IPSEC_ENC_AES && !defined(CONFIG_IPSEC_ENC_AES_MODULE) && !CONFIG_IPSEC_ENC_CRYPTOAPI && !defined(CONFIG_IPSEC_ENC_CRYPTOAPI_MODULE) -+ { -+ extern int ipsec_aes_init(void); -+ ipsec_aes_init(); -+ } -+#endif -+ -+ /* If we are doing CryptoAPI, then init */ -+#if defined(CONFIG_IPSEC_ENC_CRYPTOAPI) && CONFIG_IPSEC_ENC_CRYPTOAPI && !defined(CONFIG_IPSEC_ENC_CRYPTOAPI_MODULE) -+ { -+ extern int ipsec_cryptoapi_init(void); -+ ipsec_cryptoapi_init(); -+ } -+#endif -+ -+ -+ return 0; -+} -+ -+/********************************************** -+ * -+ * INTERFACE for ipsec_sa init and wipe -+ * -+ **********************************************/ -+ -+/* -+ * Called from pluto -> pfkey_v2_parser.c:pfkey_ipsec_sa_init() -+ */ -+int ipsec_alg_sa_init(struct ipsec_sa *sa_p) { -+ struct ipsec_alg_enc *ixt_e; -+ struct ipsec_alg_auth *ixt_a; -+ -+ /* Only ESP for now ... */ -+ if (sa_p->ips_said.proto != IPPROTO_ESP) -+ return -EPROTONOSUPPORT; -+ KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_init() :" -+ "entering for encalg=%d, authalg=%d\n", -+ sa_p->ips_encalg, sa_p->ips_authalg); -+ if ((ixt_e=(struct ipsec_alg_enc *) -+ ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, sa_p->ips_encalg))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug: ipsec_alg_sa_init() :" -+ "found ipsec_alg (ixt_e=%p) for encalg=%d\n", -+ ixt_e, sa_p->ips_encalg); -+ sa_p->ips_alg_enc=ixt_e; -+ } -+ if ((ixt_a=(struct ipsec_alg_auth *) -+ ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, sa_p->ips_authalg))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug: ipsec_alg_sa_init() :" -+ "found ipsec_alg (ixt_a=%p) for auth=%d\n", -+ ixt_a, sa_p->ips_authalg); -+ sa_p->ips_alg_auth=ixt_a; -+ } -+ return 0; -+} -+ -+/* -+ * Called from pluto -> ipsec_sa.c:ipsec_sa_delchain() -+ */ -+int ipsec_alg_sa_wipe(struct ipsec_sa *sa_p) { -+ struct ipsec_alg *ixt; -+ if ((ixt=(struct ipsec_alg *)sa_p->ips_alg_enc)) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_wipe() :" -+ "unlinking for encalg=%d\n", -+ ixt->ixt_alg_id); -+ ipsec_alg_put(ixt); -+ } -+ if ((ixt=(struct ipsec_alg *)sa_p->ips_alg_auth)) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_wipe() :" -+ "unlinking for authalg=%d\n", -+ ixt->ixt_alg_id); -+ ipsec_alg_put(ixt); -+ } -+ return 0; -+} -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_xform_get_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length IPSEC_PROC_LAST_ARG) -+{ -+ int len = 0; -+ off_t begin = 0; -+ int i; -+ struct list_head *head; -+ struct ipsec_alg *ixt; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_tncfg_get_info: " -+ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", -+ buffer, -+ *start, -+ (int)offset, -+ length); -+ -+ for(i = 0, head = ipsec_alg_hash_table; i< IPSEC_ALG_HASHSZ; i++, head++) -+ { -+ struct list_head *p; -+ for (p=head->next; p!=head; p=p->next) -+ { -+ ixt = list_entry(p, struct ipsec_alg, ixt_list); -+ len += ipsec_snprintf(buffer+len, length-len, -+ "VERSION=%d TYPE=%d ID=%d NAME=%s REFCNT=%d ", -+ ixt->ixt_version, ixt->ixt_alg_type, ixt->ixt_alg_id, -+ ixt->ixt_name, ixt->ixt_refcnt); -+ -+ len += ipsec_snprintf(buffer+len, length-len, -+ "STATE=%08x BLOCKSIZE=%d IVLEN=%d KEYMINBITS=%d KEYMAXBITS=%d ", -+ ixt->ixt_state, ixt->ixt_blocksize, -+ ixt->ixt_ivlen, ixt->ixt_keyminbits, ixt->ixt_keymaxbits); -+ -+ len += ipsec_snprintf(buffer+len, length-len, -+ "IVLEN=%d KEYMINBITS=%d KEYMAXBITS=%d ", -+ ixt->ixt_ivlen, ixt->ixt_keyminbits, ixt->ixt_keymaxbits); -+ -+ switch(ixt->ixt_alg_type) -+ { -+ case IPSEC_ALG_TYPE_AUTH: -+ { -+ struct ipsec_alg_auth *auth = (struct ipsec_alg_auth *)ixt; -+ -+ len += ipsec_snprintf(buffer+len, length-len, -+ "KEYLEN=%d CTXSIZE=%d AUTHLEN=%d ", -+ auth->ixt_a_keylen, auth->ixt_a_ctx_size, -+ auth->ixt_a_authlen); -+ break; -+ } -+ case IPSEC_ALG_TYPE_ENCRYPT: -+ { -+ struct ipsec_alg_enc *enc = (struct ipsec_alg_enc *)ixt; -+ len += ipsec_snprintf(buffer+len, length-len, -+ "KEYLEN=%d CTXSIZE=%d ", -+ enc->ixt_e_keylen, enc->ixt_e_ctx_size); -+ -+ break; -+ } -+ } -+ -+ len += ipsec_snprintf(buffer+len, length-len, "\n"); -+ } -+ } -+ -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ len -= (offset - begin); /* Start slop */ -+ if (len > length) -+ len = length; -+ return len; -+} -+ -+ -+/* -+ * As the author of this module, I ONLY ALLOW using it from -+ * GPL (or same LICENSE TERMS as kernel source) modules. -+ * -+ * In respect to hardware crypto engines this means: -+ * * Closed-source device drivers ARE NOT ALLOWED to use -+ * this interface. -+ * * Closed-source VHDL/Verilog firmware running on -+ * the crypto hardware device IS ALLOWED to use this interface -+ * via a GPL (or same LICENSE TERMS as kernel source) device driver. -+ * --Juan Jose Ciarlante 20/03/2002 (thanks RGB for the correct wording) -+ */ -+ -+/* -+ * These symbols can only be used from GPL modules -+ * for now, I'm disabling this because it creates false -+ * symbol problems for old modutils. -+ */ -+ -+/* #ifndef EXPORT_SYMBOL_GPL */ -+#undef EXPORT_SYMBOL_GPL -+#define EXPORT_SYMBOL_GPL EXPORT_SYMBOL -+/* #endif */ -+EXPORT_SYMBOL_GPL(register_ipsec_alg); -+EXPORT_SYMBOL_GPL(unregister_ipsec_alg); -+EXPORT_SYMBOL_GPL(ipsec_alg_test); -+#endif /* CONFIG_IPSEC_ALG */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_alg_aes.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,263 @@ -+/* -+ * ipsec_alg AES cipher stubs -+ * -+ * Author: JuanJo Ciarlante -+ * -+ * ipsec_alg_aes.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * Fixes by: -+ * PK: Pawel Krawczyk -+ * Fixes list: -+ * PK: make XCBC comply with latest draft (keylength) -+ * -+ */ -+#include -+#include -+ -+/* -+ * special case: ipsec core modular with this static algo inside: -+ * must avoid MODULE magic for this file -+ */ -+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_AES -+#undef MODULE -+#endif -+ -+#include -+#include -+ -+#include /* printk() */ -+#include /* error codes */ -+#include /* size_t */ -+#include -+ -+/* Check if __exit is defined, if not null it */ -+#ifndef __exit -+#define __exit -+#endif -+ -+/* Low freeswan header coupling */ -+#include "openswan/ipsec_alg.h" -+#include "crypto/aes_cbc.h" -+ -+#define CONFIG_IPSEC_ALG_AES_MAC 1 -+ -+#define AES_CONTEXT_T aes_context -+MODULE_AUTHOR("JuanJo Ciarlante "); -+static int debug=0; -+MODULE_PARM(debug, "i"); -+static int test=0; -+MODULE_PARM(test, "i"); -+static int excl=0; -+MODULE_PARM(excl, "i"); -+static int keyminbits=0; -+MODULE_PARM(keyminbits, "i"); -+static int keymaxbits=0; -+MODULE_PARM(keymaxbits, "i"); -+ -+#if CONFIG_IPSEC_ALG_AES_MAC -+#include "crypto/aes_xcbc_mac.h" -+ -+/* -+ * Not IANA number yet (draft-ietf-ipsec-ciph-aes-xcbc-mac-00.txt). -+ * We use 9 for non-modular algorithm and none for modular, thus -+ * forcing user to specify one on module load. -kravietz -+ */ -+#ifdef MODULE -+static int auth_id=0; -+#else -+static int auth_id=9; -+#endif -+MODULE_PARM(auth_id, "i"); -+#endif -+ -+#define ESP_AES 12 /* truely _constant_ :) */ -+ -+/* 128, 192 or 256 */ -+#define ESP_AES_KEY_SZ_MIN 16 /* 128 bit secret key */ -+#define ESP_AES_KEY_SZ_MAX 32 /* 256 bit secret key */ -+#define ESP_AES_CBC_BLK_LEN 16 /* AES-CBC block size */ -+ -+/* Values according to draft-ietf-ipsec-ciph-aes-xcbc-mac-02.txt -+ * -kravietz -+ */ -+#define ESP_AES_MAC_KEY_SZ 16 /* 128 bit MAC key */ -+#define ESP_AES_MAC_BLK_LEN 16 /* 128 bit block */ -+ -+static int _aes_set_key(struct ipsec_alg_enc *alg, __u8 * key_e, const __u8 * key, size_t keysize) { -+ int ret; -+ AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e; -+ ret=AES_set_key(ctx, key, keysize)!=0? 0: -EINVAL; -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_aes_set_key:" -+ "ret=%d key_e=%p key=%p keysize=%d\n", -+ ret, key_e, key, keysize); -+ return ret; -+} -+static int _aes_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) { -+ AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e; -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_aes_cbc_encrypt:" -+ "key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n", -+ key_e, in, ilen, iv, encrypt); -+ return AES_cbc_encrypt(ctx, in, in, ilen, iv, encrypt); -+} -+#if CONFIG_IPSEC_ALG_AES_MAC -+static int _aes_mac_set_key(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * key, int keylen) { -+ aes_context_mac *ctxm=(aes_context_mac *)key_a; -+ return AES_xcbc_mac_set_key(ctxm, key, keylen)? 0 : -EINVAL; -+} -+static int _aes_mac_hash(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * dat, int len, __u8 * hash, int hashlen) { -+ int ret; -+ char hash_buf[16]; -+ aes_context_mac *ctxm=(aes_context_mac *)key_a; -+ ret=AES_xcbc_mac_hash(ctxm, dat, len, hash_buf); -+ memcpy(hash, hash_buf, hashlen); -+ return ret; -+} -+static struct ipsec_alg_auth ipsec_alg_AES_MAC = { -+ ixt_version: IPSEC_ALG_VERSION, -+ ixt_module: THIS_MODULE, -+ ixt_refcnt: ATOMIC_INIT(0), -+ ixt_alg_type: IPSEC_ALG_TYPE_AUTH, -+ ixt_alg_id: 0, -+ ixt_name: "aes_mac", -+ ixt_blocksize: ESP_AES_MAC_BLK_LEN, -+ ixt_keyminbits: ESP_AES_MAC_KEY_SZ*8, -+ ixt_keymaxbits: ESP_AES_MAC_KEY_SZ*8, -+ ixt_a_keylen: ESP_AES_MAC_KEY_SZ, -+ ixt_a_ctx_size: sizeof(aes_context_mac), -+ ixt_a_hmac_set_key: _aes_mac_set_key, -+ ixt_a_hmac_hash:_aes_mac_hash, -+}; -+#endif /* CONFIG_IPSEC_ALG_AES_MAC */ -+static struct ipsec_alg_enc ipsec_alg_AES = { -+ ixt_version: IPSEC_ALG_VERSION, -+ ixt_module: THIS_MODULE, -+ ixt_refcnt: ATOMIC_INIT(0), -+ ixt_alg_type: IPSEC_ALG_TYPE_ENCRYPT, -+ ixt_alg_id: ESP_AES, -+ ixt_name: "aes", -+ ixt_blocksize: ESP_AES_CBC_BLK_LEN, -+ ixt_keyminbits: ESP_AES_KEY_SZ_MIN*8, -+ ixt_keymaxbits: ESP_AES_KEY_SZ_MAX*8, -+ ixt_e_keylen: ESP_AES_KEY_SZ_MAX, -+ ixt_e_ctx_size: sizeof(AES_CONTEXT_T), -+ ixt_e_set_key: _aes_set_key, -+ ixt_e_cbc_encrypt:_aes_cbc_encrypt, -+}; -+ -+#if defined(CONFIG_IPSEC_ENC_AES_MODULE) -+IPSEC_ALG_MODULE_INIT_MOD( ipsec_aes_init ) -+#else -+IPSEC_ALG_MODULE_INIT_STATIC( ipsec_aes_init ) -+#endif -+{ -+ int ret, test_ret; -+ -+ if (keyminbits) -+ ipsec_alg_AES.ixt_keyminbits=keyminbits; -+ if (keymaxbits) { -+ ipsec_alg_AES.ixt_keymaxbits=keymaxbits; -+ if (keymaxbits*8>ipsec_alg_AES.ixt_keymaxbits) -+ ipsec_alg_AES.ixt_e_keylen=keymaxbits*8; -+ } -+ if (excl) ipsec_alg_AES.ixt_state |= IPSEC_ALG_ST_EXCL; -+ ret=register_ipsec_alg_enc(&ipsec_alg_AES); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", -+ ipsec_alg_AES.ixt_alg_type, -+ ipsec_alg_AES.ixt_alg_id, -+ ipsec_alg_AES.ixt_name, -+ ret); -+ if (ret==0 && test) { -+ test_ret=ipsec_alg_test( -+ ipsec_alg_AES.ixt_alg_type, -+ ipsec_alg_AES.ixt_alg_id, -+ test); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", -+ ipsec_alg_AES.ixt_alg_type, -+ ipsec_alg_AES.ixt_alg_id, -+ test_ret); -+ } -+#if CONFIG_IPSEC_ALG_AES_MAC -+ if (auth_id!=0){ -+ int ret; -+ ipsec_alg_AES_MAC.ixt_alg_id=auth_id; -+ ret=register_ipsec_alg_auth(&ipsec_alg_AES_MAC); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", -+ ipsec_alg_AES_MAC.ixt_alg_type, -+ ipsec_alg_AES_MAC.ixt_alg_id, -+ ipsec_alg_AES_MAC.ixt_name, -+ ret); -+ if (ret==0 && test) { -+ test_ret=ipsec_alg_test( -+ ipsec_alg_AES_MAC.ixt_alg_type, -+ ipsec_alg_AES_MAC.ixt_alg_id, -+ test); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", -+ ipsec_alg_AES_MAC.ixt_alg_type, -+ ipsec_alg_AES_MAC.ixt_alg_id, -+ test_ret); -+ } -+ } else { -+ printk(KERN_DEBUG "klips_debug: experimental ipsec_alg_AES_MAC not registered [Ok] (auth_id=%d)\n", auth_id); -+ } -+#endif /* CONFIG_IPSEC_ALG_AES_MAC */ -+ return ret; -+} -+ -+#if defined(CONFIG_IPSEC_ENC_AES_MODULE) -+IPSEC_ALG_MODULE_EXIT_MOD( ipsec_aes_fini ) -+#else -+IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_aes_fini ) -+#endif -+{ -+#if CONFIG_IPSEC_ALG_AES_MAC -+ if (auth_id) unregister_ipsec_alg_auth(&ipsec_alg_AES_MAC); -+#endif /* CONFIG_IPSEC_ALG_AES_MAC */ -+ unregister_ipsec_alg_enc(&ipsec_alg_AES); -+ return; -+} -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+#if 0+NOT_YET -+#ifndef MODULE -+/* -+ * This is intended for static module setups, currently -+ * doesn't work for modular ipsec.o with static algos inside -+ */ -+static int setup_keybits(const char *str) -+{ -+ unsigned aux; -+ char *end; -+ -+ aux = simple_strtoul(str,&end,0); -+ if (aux != 128 && aux != 192 && aux != 256) -+ return 0; -+ keyminbits = aux; -+ -+ if (*end == 0 || *end != ',') -+ return 1; -+ str=end+1; -+ aux = simple_strtoul(str, NULL, 0); -+ if (aux != 128 && aux != 192 && aux != 256) -+ return 0; -+ if (aux >= keyminbits) -+ keymaxbits = aux; -+ return 1; -+} -+__setup("ipsec_aes_keybits=", setup_keybits); -+#endif -+#endif -+EXPORT_NO_SYMBOLS; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_alg_cryptoapi.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,421 @@ -+/* -+ * ipsec_alg to linux cryptoapi GLUE -+ * -+ * Authors: CODE.ar TEAM -+ * Harpo MAxx -+ * JuanJo Ciarlante -+ * Luciano Ruete -+ * -+ * ipsec_alg_cryptoapi.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * Example usage: -+ * modinfo -p ipsec_cryptoapi (quite useful info, including supported algos) -+ * modprobe ipsec_cryptoapi -+ * modprobe ipsec_cryptoapi test=1 -+ * modprobe ipsec_cryptoapi excl=1 (exclusive cipher/algo) -+ * modprobe ipsec_cryptoapi noauto=1 aes=1 twofish=1 (only these ciphers) -+ * modprobe ipsec_cryptoapi aes=128,128 (force these keylens) -+ * modprobe ipsec_cryptoapi des_ede3=0 (everything but 3DES) -+ */ -+#include -+#include -+ -+/* -+ * special case: ipsec core modular with this static algo inside: -+ * must avoid MODULE magic for this file -+ */ -+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_CRYPTOAPI -+#undef MODULE -+#endif -+ -+#include -+#include -+ -+#include /* printk() */ -+#include /* error codes */ -+#include /* size_t */ -+#include -+ -+/* Check if __exit is defined, if not null it */ -+#ifndef __exit -+#define __exit -+#endif -+ -+/* warn the innocent */ -+#if !defined (CONFIG_CRYPTO) && !defined (CONFIG_CRYPTO_MODULE) -+#warning "No linux CryptoAPI found, install 2.4.22+ or 2.6.x" -+#define NO_CRYPTOAPI_SUPPORT -+#endif -+/* Low Openswan header coupling */ -+#include "openswan/ipsec_alg.h" -+ -+#include -+#ifdef CRYPTO_API_VERSION_CODE -+#warning "Old CryptoAPI is not supported. Only linux-2.4.22+ or linux-2.6.x are supported" -+#define NO_CRYPTOAPI_SUPPORT -+#endif -+ -+#ifdef NO_CRYPTOAPI_SUPPORT -+#warning "Building an unusable module :P" -+/* Catch old CryptoAPI by not allowing module to load */ -+IPSEC_ALG_MODULE_INIT_STATIC( ipsec_cryptoapi_init ) -+{ -+ printk(KERN_WARNING "ipsec_cryptoapi.o was not built on stock Linux CryptoAPI (2.4.22+ or 2.6.x), not loading.\n"); -+ return -EINVAL; -+} -+#else -+#include -+#include -+#include -+ -+#define CIPHERNAME_AES "aes" -+#define CIPHERNAME_3DES "des3_ede" -+#define CIPHERNAME_BLOWFISH "blowfish" -+#define CIPHERNAME_CAST "cast5" -+#define CIPHERNAME_SERPENT "serpent" -+#define CIPHERNAME_TWOFISH "twofish" -+ -+#define ESP_3DES 3 -+#define ESP_AES 12 -+#define ESP_BLOWFISH 7 /* truely _constant_ :) */ -+#define ESP_CAST 6 /* quite constant :) */ -+#define ESP_SERPENT 252 /* from ipsec drafts */ -+#define ESP_TWOFISH 253 /* from ipsec drafts */ -+ -+#define AH_MD5 2 -+#define AH_SHA 3 -+#define DIGESTNAME_MD5 "md5" -+#define DIGESTNAME_SHA1 "sha1" -+ -+MODULE_AUTHOR("Juanjo Ciarlante, Harpo MAxx, Luciano Ruete"); -+static int debug=0; -+MODULE_PARM(debug, "i"); -+static int test=0; -+MODULE_PARM(test, "i"); -+static int excl=0; -+MODULE_PARM(excl, "i"); -+ -+static int noauto = 0; -+MODULE_PARM(noauto,"i"); -+MODULE_PARM_DESC(noauto, "Dont try all known algos, just setup enabled ones"); -+ -+static int des_ede3[] = {-1, -1}; -+static int aes[] = {-1, -1}; -+static int blowfish[] = {-1, -1}; -+static int cast[] = {-1, -1}; -+static int serpent[] = {-1, -1}; -+static int twofish[] = {-1, -1}; -+ -+MODULE_PARM(des_ede3,"1-2i"); -+MODULE_PARM(aes,"1-2i"); -+MODULE_PARM(blowfish,"1-2i"); -+MODULE_PARM(cast,"1-2i"); -+MODULE_PARM(serpent,"1-2i"); -+MODULE_PARM(twofish,"1-2i"); -+MODULE_PARM_DESC(des_ede3, "0: disable | 1: force_enable | min,max: dontuse"); -+MODULE_PARM_DESC(aes, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(blowfish, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(cast, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(serpent, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(twofish, "0: disable | 1: force_enable | min,max: keybitlens"); -+ -+struct ipsec_alg_capi_cipher { -+ const char *ciphername; /* cryptoapi's ciphername */ -+ unsigned blocksize; -+ unsigned short minbits; -+ unsigned short maxbits; -+ int *parm; /* lkm param for this cipher */ -+ struct ipsec_alg_enc alg; /* note it's not a pointer */ -+}; -+static struct ipsec_alg_capi_cipher alg_capi_carray[] = { -+ { CIPHERNAME_AES , 16, 128, 256, aes , { ixt_alg_id: ESP_AES, }}, -+ { CIPHERNAME_TWOFISH , 16, 128, 256, twofish, { ixt_alg_id: ESP_TWOFISH, }}, -+ { CIPHERNAME_SERPENT , 16, 128, 256, serpent, { ixt_alg_id: ESP_SERPENT, }}, -+ { CIPHERNAME_CAST , 8, 128, 128, cast , { ixt_alg_id: ESP_CAST, }}, -+ { CIPHERNAME_BLOWFISH , 8, 96, 448, blowfish,{ ixt_alg_id: ESP_BLOWFISH, }}, -+ { CIPHERNAME_3DES , 8, 192, 192, des_ede3,{ ixt_alg_id: ESP_3DES, }}, -+ { NULL, 0, 0, 0, NULL, {} } -+}; -+#ifdef NOT_YET -+struct ipsec_alg_capi_digest { -+ const char *digestname; /* cryptoapi's digestname */ -+ struct digest_implementation *di; -+ struct ipsec_alg_auth alg; /* note it's not a pointer */ -+}; -+static struct ipsec_alg_capi_cipher alg_capi_darray[] = { -+ { DIGESTNAME_MD5, NULL, { ixt_alg_id: AH_MD5, }}, -+ { DIGESTNAME_SHA1, NULL, { ixt_alg_id: AH_SHA, }}, -+ { NULL, NULL, {} } -+}; -+#endif -+/* -+ * "generic" linux cryptoapi setup_cipher() function -+ */ -+int setup_cipher(const char *ciphername) -+{ -+ return crypto_alg_available(ciphername, 0); -+} -+ -+/* -+ * setups ipsec_alg_capi_cipher "hyper" struct components, calling -+ * register_ipsec_alg for cointaned ipsec_alg object -+ */ -+static void _capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e); -+static __u8 * _capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen); -+static int _capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt); -+ -+static int -+setup_ipsec_alg_capi_cipher(struct ipsec_alg_capi_cipher *cptr) -+{ -+ int ret; -+ cptr->alg.ixt_version = IPSEC_ALG_VERSION; -+ cptr->alg.ixt_module = THIS_MODULE; -+ atomic_set (& cptr->alg.ixt_refcnt, 0); -+ strncpy (cptr->alg.ixt_name , cptr->ciphername, sizeof (cptr->alg.ixt_name)); -+ -+ cptr->alg.ixt_blocksize=cptr->blocksize; -+ cptr->alg.ixt_keyminbits=cptr->minbits; -+ cptr->alg.ixt_keymaxbits=cptr->maxbits; -+ cptr->alg.ixt_state = 0; -+ if (excl) cptr->alg.ixt_state |= IPSEC_ALG_ST_EXCL; -+ cptr->alg.ixt_e_keylen=cptr->alg.ixt_keymaxbits/8; -+ cptr->alg.ixt_e_ctx_size = 0; -+ cptr->alg.ixt_alg_type = IPSEC_ALG_TYPE_ENCRYPT; -+ cptr->alg.ixt_e_new_key = _capi_new_key; -+ cptr->alg.ixt_e_destroy_key = _capi_destroy_key; -+ cptr->alg.ixt_e_cbc_encrypt = _capi_cbc_encrypt; -+ cptr->alg.ixt_data = cptr; -+ -+ ret=register_ipsec_alg_enc(&cptr->alg); -+ printk("setup_ipsec_alg_capi_cipher(): " -+ "alg_type=%d alg_id=%d name=%s " -+ "keyminbits=%d keymaxbits=%d, ret=%d\n", -+ cptr->alg.ixt_alg_type, -+ cptr->alg.ixt_alg_id, -+ cptr->alg.ixt_name, -+ cptr->alg.ixt_keyminbits, -+ cptr->alg.ixt_keymaxbits, -+ ret); -+ return ret; -+} -+/* -+ * called in ipsec_sa_wipe() time, will destroy key contexts -+ * and do 1 unbind() -+ */ -+static void -+_capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e) -+{ -+ struct crypto_tfm *tfm=(struct crypto_tfm*)key_e; -+ -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug: _capi_destroy_key:" -+ "name=%s key_e=%p \n", -+ alg->ixt_name, key_e); -+ if (!key_e) { -+ printk(KERN_ERR "klips_debug: _capi_destroy_key:" -+ "name=%s NULL key_e!\n", -+ alg->ixt_name); -+ return; -+ } -+ crypto_free_tfm(tfm); -+} -+ -+/* -+ * create new key context, need alg->ixt_data to know which -+ * (of many) cipher inside this module is the target -+ */ -+static __u8 * -+_capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen) -+{ -+ struct ipsec_alg_capi_cipher *cptr; -+ struct crypto_tfm *tfm=NULL; -+ -+ cptr = alg->ixt_data; -+ if (!cptr) { -+ printk(KERN_ERR "_capi_new_key(): " -+ "NULL ixt_data (?!) for \"%s\" algo\n" -+ , alg->ixt_name); -+ goto err; -+ } -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_capi_new_key:" -+ "name=%s cptr=%p key=%p keysize=%d\n", -+ alg->ixt_name, cptr, key, keylen); -+ -+ /* -+ * alloc tfm -+ */ -+ tfm = crypto_alloc_tfm(cptr->ciphername, CRYPTO_TFM_MODE_CBC); -+ if (!tfm) { -+ printk(KERN_ERR "_capi_new_key(): " -+ "NULL tfm for \"%s\" cryptoapi (\"%s\") algo\n" -+ , alg->ixt_name, cptr->ciphername); -+ goto err; -+ } -+ if (crypto_cipher_setkey(tfm, key, keylen) < 0) { -+ printk(KERN_ERR "_capi_new_key(): " -+ "failed new_key() for \"%s\" cryptoapi algo (keylen=%d)\n" -+ , alg->ixt_name, keylen); -+ crypto_free_tfm(tfm); -+ tfm=NULL; -+ } -+err: -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_capi_new_key:" -+ "name=%s key=%p keylen=%d tfm=%p\n", -+ alg->ixt_name, key, keylen, tfm); -+ return (__u8 *) tfm; -+} -+/* -+ * core encryption function: will use cx->ci to call actual cipher's -+ * cbc function -+ */ -+static int -+_capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) { -+ int error =0; -+ struct crypto_tfm *tfm=(struct crypto_tfm *)key_e; -+ struct scatterlist sg = { -+ .page = virt_to_page(in), -+ .offset = (unsigned long)(in) % PAGE_SIZE, -+ .length=ilen, -+ }; -+ if (debug > 1) -+ printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" -+ "key_e=%p " -+ "in=%p out=%p ilen=%d iv=%p encrypt=%d\n" -+ , key_e -+ , in, in, ilen, iv, encrypt); -+ crypto_cipher_set_iv(tfm, iv, crypto_tfm_alg_ivsize(tfm)); -+ if (encrypt) -+ error = crypto_cipher_encrypt (tfm, &sg, &sg, ilen); -+ else -+ error = crypto_cipher_decrypt (tfm, &sg, &sg, ilen); -+ if (debug > 1) -+ printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" -+ "error=%d\n" -+ , error); -+ return (error<0)? error : ilen; -+} -+/* -+ * main initialization loop: for each cipher in list, do -+ * 1) setup cryptoapi cipher else continue -+ * 2) register ipsec_alg object -+ */ -+static int -+setup_cipher_list (struct ipsec_alg_capi_cipher* clist) -+{ -+ struct ipsec_alg_capi_cipher *cptr; -+ /* foreach cipher in list ... */ -+ for (cptr=clist;cptr->ciphername;cptr++) { -+ /* -+ * see if cipher has been disabled (0) or -+ * if noauto set and not enabled (1) -+ */ -+ if (cptr->parm[0] == 0 || (noauto && cptr->parm[0] < 0)) { -+ if (debug>0) -+ printk(KERN_INFO "setup_cipher_list(): " -+ "ciphername=%s skipped at user request: " -+ "noauto=%d parm[0]=%d parm[1]=%d\n" -+ , cptr->ciphername -+ , noauto -+ , cptr->parm[0] -+ , cptr->parm[1]); -+ continue; -+ } -+ /* -+ * use a local ci to avoid touching cptr->ci, -+ * if register ipsec_alg success then bind cipher -+ */ -+ if( setup_cipher(cptr->ciphername) ) { -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:" -+ "setup_cipher_list():" -+ "ciphername=%s found\n" -+ , cptr->ciphername); -+ if (setup_ipsec_alg_capi_cipher(cptr) == 0) { -+ -+ -+ } else { -+ printk(KERN_ERR "klips_debug:" -+ "setup_cipher_list():" -+ "ciphername=%s failed ipsec_alg_register\n" -+ , cptr->ciphername); -+ } -+ } else { -+ if (debug>0) -+ printk(KERN_INFO "setup_cipher_list(): lookup for ciphername=%s: not found \n", -+ cptr->ciphername); -+ } -+ } -+ return 0; -+} -+/* -+ * deregister ipsec_alg objects and unbind ciphers -+ */ -+static int -+unsetup_cipher_list (struct ipsec_alg_capi_cipher* clist) -+{ -+ struct ipsec_alg_capi_cipher *cptr; -+ /* foreach cipher in list ... */ -+ for (cptr=clist;cptr->ciphername;cptr++) { -+ if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) { -+ unregister_ipsec_alg_enc(&cptr->alg); -+ } -+ } -+ return 0; -+} -+/* -+ * test loop for registered algos -+ */ -+static int -+test_cipher_list (struct ipsec_alg_capi_cipher* clist) -+{ -+ int test_ret; -+ struct ipsec_alg_capi_cipher *cptr; -+ /* foreach cipher in list ... */ -+ for (cptr=clist;cptr->ciphername;cptr++) { -+ if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) { -+ test_ret=ipsec_alg_test( -+ cptr->alg.ixt_alg_type, -+ cptr->alg.ixt_alg_id, -+ test); -+ printk("test_cipher_list(alg_type=%d alg_id=%d): test_ret=%d\n", -+ cptr->alg.ixt_alg_type, -+ cptr->alg.ixt_alg_id, -+ test_ret); -+ } -+ } -+ return 0; -+} -+ -+IPSEC_ALG_MODULE_INIT_STATIC( ipsec_cryptoapi_init ) -+{ -+ int ret, test_ret; -+ if ((ret=setup_cipher_list(alg_capi_carray)) < 0) -+ return -EPROTONOSUPPORT; -+ if (ret==0 && test) { -+ test_ret=test_cipher_list(alg_capi_carray); -+ } -+ return ret; -+} -+IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_cryptoapi_fini ) -+{ -+ unsetup_cipher_list(alg_capi_carray); -+ return; -+} -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+EXPORT_NO_SYMBOLS; -+#endif /* NO_CRYPTOAPI_SUPPORT */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_esp.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,558 @@ -+/* -+ * processing code for ESP -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_esp_c_version[] = "RCSID $Id$"; -+#include -+#include -+ -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define proto_priv cb -+#endif /* NET21 */ -+#include -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipsec_xmit.h" -+ -+#include "openswan/ipsec_auth.h" -+ -+#ifdef CONFIG_IPSEC_ESP -+#include "openswan/ipsec_esp.h" -+#endif /* CONFIG_IPSEC_ESP */ -+ -+#include "openswan/ipsec_proto.h" -+#include "openswan/ipsec_alg.h" -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_esp = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ -+#ifdef CONFIG_IPSEC_ESP -+enum ipsec_rcv_value -+ipsec_rcv_esp_checks(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb) -+{ -+ __u8 proto; -+ int len; /* packet length */ -+ -+ len = skb->len; -+ proto = irs->ipp->protocol; -+ -+ /* XXX this will need to be 8 for IPv6 */ -+ if ((proto == IPPROTO_ESP) && ((len - irs->iphlen) % 4)) { -+ printk("klips_error:ipsec_rcv: " -+ "got packet with content length = %d from %s -- should be on 4 octet boundary, packet dropped\n", -+ len - irs->iphlen, -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_BADLEN; -+ } -+ -+ if(skb->len < (irs->hard_header_len + sizeof(struct iphdr) + sizeof(struct esphdr))) { -+ KLIPS_PRINT(debug_rcv & DB_RX_INAU, -+ "klips_debug:ipsec_rcv: " -+ "runt esp packet of skb->len=%d received from %s, dropped.\n", -+ skb->len, -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_BADLEN; -+ } -+ -+ irs->protostuff.espstuff.espp = (struct esphdr *)(skb->data + irs->iphlen); -+ irs->said.spi = irs->protostuff.espstuff.espp->esp_spi; -+ -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_rcv_value -+ipsec_rcv_esp_decrypt_setup(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb, -+ __u32 *replay, -+ unsigned char **authenticator) -+{ -+ struct esphdr *espp = irs->protostuff.espstuff.espp; -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "packet from %s received with seq=%d (iv)=0x%08x%08x iplen=%d esplen=%d sa=%s\n", -+ irs->ipsaddr_txt, -+ (__u32)ntohl(espp->esp_rpl), -+ (__u32)ntohl(*((__u32 *)(espp->esp_iv) )), -+ (__u32)ntohl(*((__u32 *)(espp->esp_iv) + 1)), -+ irs->len, -+ irs->ilen, -+ irs->sa_len ? irs->sa : " (error)"); -+ -+ *replay = ntohl(espp->esp_rpl); -+ *authenticator = &(skb->data[irs->len - irs->authlen]); -+ -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_rcv_value -+ipsec_rcv_esp_authcalc(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb) -+{ -+ struct auth_alg *aa; -+ struct esphdr *espp = irs->protostuff.espstuff.espp; -+ union { -+ MD5_CTX md5; -+ SHA1_CTX sha1; -+ } tctx; -+ -+#ifdef CONFIG_IPSEC_ALG -+ if (irs->ipsp->ips_alg_auth) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "ipsec_alg hashing proto=%d... ", -+ irs->said.proto); -+ if(irs->said.proto == IPPROTO_ESP) { -+ ipsec_alg_sa_esp_hash(irs->ipsp, -+ (caddr_t)espp, irs->ilen, -+ irs->hash, AHHMAC_HASHLEN); -+ return IPSEC_RCV_OK; -+ } -+ return IPSEC_RCV_BADPROTO; -+ } -+#endif -+ aa = irs->authfuncs; -+ -+ /* copy the initialized keying material */ -+ memcpy(&tctx, irs->ictx, irs->ictx_len); -+ -+ (*aa->update)((void *)&tctx, (caddr_t)espp, irs->ilen); -+ -+ (*aa->final)(irs->hash, (void *)&tctx); -+ -+ memcpy(&tctx, irs->octx, irs->octx_len); -+ -+ (*aa->update)((void *)&tctx, irs->hash, aa->hashlen); -+ (*aa->final)(irs->hash, (void *)&tctx); -+ -+ return IPSEC_RCV_OK; -+} -+ -+ -+enum ipsec_rcv_value -+ipsec_rcv_esp_decrypt(struct ipsec_rcv_state *irs) -+{ -+ struct ipsec_sa *ipsp = irs->ipsp; -+ struct esphdr *espp = irs->protostuff.espstuff.espp; -+ int esphlen = 0; -+ __u8 *idat; /* pointer to content to be decrypted/authenticated */ -+ __u32 iv[2]; -+ int pad = 0, padlen; -+ int badpad = 0; -+ int i; -+ struct sk_buff *skb; -+#ifdef CONFIG_IPSEC_ALG -+ struct ipsec_alg_enc *ixt_e=NULL; -+#endif /* CONFIG_IPSEC_ALG */ -+ -+ skb=irs->skb; -+ -+ idat = skb->data + irs->iphlen; -+ -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_e=ipsp->ips_alg_enc)) { -+ esphlen = ESP_HEADER_LEN + ixt_e->ixt_ivlen/8; -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "encalg=%d esphlen=%d\n", -+ ipsp->ips_encalg, esphlen); -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ipsp->ips_encalg) { -+ case ESP_3DES: -+ iv[0] = *((__u32 *)(espp->esp_iv) ); -+ iv[1] = *((__u32 *)(espp->esp_iv) + 1); -+ esphlen = sizeof(struct esphdr); -+ break; -+ default: -+ ipsp->ips_errs.ips_alg_errs += 1; -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_ESP_BADALG; -+ } -+ -+ idat += esphlen; -+ irs->ilen -= esphlen; -+ -+#ifdef CONFIG_IPSEC_ALG -+ if (ixt_e) -+ { -+ if (ipsec_alg_esp_encrypt(ipsp, -+ idat, irs->ilen, espp->esp_iv, -+ IPSEC_ALG_DECRYPT) <= 0) -+ { -+ printk("klips_error:ipsec_rcv: " -+ "got packet with esplen = %d " -+ "from %s -- should be on " -+ "ENC(%d) octet boundary, " -+ "packet dropped\n", -+ irs->ilen, -+ irs->ipsaddr_txt, -+ ipsp->ips_encalg); -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_BAD_DECRYPT; -+ } -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ipsp->ips_encalg) { -+ case ESP_3DES: -+ if ((irs->ilen) % 8) { -+ ipsp->ips_errs.ips_encsize_errs += 1; -+ printk("klips_error:ipsec_rcv: " -+ "got packet with esplen = %d from %s -- should be on 8 octet boundary, packet dropped\n", -+ irs->ilen, -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_3DES_BADBLOCKING; -+ } -+ des_ede3_cbc_encrypt((des_cblock *)idat, -+ (des_cblock *)idat, -+ irs->ilen, -+ ((struct des_eks *)(ipsp->ips_key_e))[0].ks, -+ ((struct des_eks *)(ipsp->ips_key_e))[1].ks, -+ ((struct des_eks *)(ipsp->ips_key_e))[2].ks, -+ (des_cblock *)iv, 0); -+ break; -+ } -+ -+ ipsec_rcv_dmp("postdecrypt", skb->data, skb->len); -+ -+ irs->next_header = idat[irs->ilen - 1]; -+ padlen = idat[irs->ilen - 2]; -+ pad = padlen + 2 + irs->authlen; -+ -+ KLIPS_PRINT(debug_rcv & DB_RX_IPAD, -+ "klips_debug:ipsec_rcv: " -+ "padlen=%d, contents: 0x: 0x 0x ...\n", -+ padlen); -+ -+ for (i = 1; i <= padlen; i++) { -+ if((i % 16) == 1) { -+ KLIPS_PRINT(debug_rcv & DB_RX_IPAD, -+ "klips_debug: %02x:", -+ i - 1); -+ } -+ KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD, -+ " %02x", -+ idat[irs->ilen - 2 - padlen + i - 1]); -+ if(i != idat[irs->ilen - 2 - padlen + i - 1]) { -+ badpad = 1; -+ } -+ if((i % 16) == 0) { -+ KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD, -+ "\n"); -+ } -+ } -+ if((i % 16) != 1) { -+ KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD, -+ "\n"); -+ } -+ if(badpad) { -+ KLIPS_PRINT(debug_rcv & DB_RX_IPAD, -+ "klips_debug:ipsec_rcv: " -+ "warning, decrypted packet from %s has bad padding\n", -+ irs->ipsaddr_txt); -+ KLIPS_PRINT(debug_rcv & DB_RX_IPAD, -+ "klips_debug:ipsec_rcv: " -+ "...may be bad decryption -- not dropped\n"); -+ ipsp->ips_errs.ips_encpad_errs += 1; -+ } -+ -+ KLIPS_PRINT(debug_rcv & DB_RX_IPAD, -+ "klips_debug:ipsec_rcv: " -+ "packet decrypted from %s: next_header = %d, padding = %d\n", -+ irs->ipsaddr_txt, -+ irs->next_header, -+ pad - 2 - irs->authlen); -+ -+ irs->ipp->tot_len = htons(ntohs(irs->ipp->tot_len) - (esphlen + pad)); -+ -+ /* -+ * move the IP header forward by the size of the ESP header, which -+ * will remove the the ESP header from the packet. -+ */ -+ memmove((void *)(skb->data + esphlen), -+ (void *)(skb->data), irs->iphlen); -+ -+ ipsec_rcv_dmp("esp postmove", skb->data, skb->len); -+ -+ /* skb_pull below, will move up by esphlen */ -+ -+ /* XXX not clear how this can happen, as the message indicates */ -+ if(skb->len < esphlen) { -+ printk(KERN_WARNING -+ "klips_error:ipsec_rcv: " -+ "tried to skb_pull esphlen=%d, %d available. This should never happen, please report.\n", -+ esphlen, (int)(skb->len)); -+ return IPSEC_RCV_ESP_DECAPFAIL; -+ } -+ skb_pull(skb, esphlen); -+ -+ irs->ipp = (struct iphdr *)skb->data; -+ -+ ipsec_rcv_dmp("esp postpull", skb->data, skb->len); -+ -+ /* now, trip off the padding from the end */ -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "trimming to %d.\n", -+ irs->len - esphlen - pad); -+ if(pad + esphlen <= irs->len) { -+ skb_trim(skb, irs->len - esphlen - pad); -+ } else { -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "bogus packet, size is zero or negative, dropping.\n"); -+ return IPSEC_RCV_DECAPFAIL; -+ } -+ -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_xmit_esp_setup(struct ipsec_xmit_state *ixs) -+{ -+ __u32 iv[2]; -+ struct esphdr *espp; -+ int ilen = 0; -+ int padlen = 0, i; -+ unsigned char *dat; -+ unsigned char *idat, *pad; -+ __u8 hash[AH_AMAX]; -+ union { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ MD5_CTX md5; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ SHA1_CTX sha1; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ } tctx; -+ -+ dat = (unsigned char *)ixs->iph; -+ -+ espp = (struct esphdr *)(dat + ixs->iphlen); -+ espp->esp_spi = ixs->ipsp->ips_said.spi; -+ espp->esp_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); -+ -+ switch(ixs->ipsp->ips_encalg) { -+#if defined(CONFIG_IPSEC_ENC_3DES) -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ iv[0] = *((__u32*)&(espp->esp_iv) ) = -+ ((__u32*)(ixs->ipsp->ips_iv))[0]; -+ iv[1] = *((__u32*)&(espp->esp_iv) + 1) = -+ ((__u32*)(ixs->ipsp->ips_iv))[1]; -+ break; -+#endif /* defined(CONFIG_IPSEC_ENC_3DES) */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+ -+ idat = dat + ixs->iphlen + sizeof(struct esphdr); -+ ilen = ixs->skb->len - (ixs->iphlen + sizeof(struct esphdr) + ixs->authlen); -+ -+ /* Self-describing padding */ -+ pad = &dat[ixs->skb->len - ixs->tailroom]; -+ padlen = ixs->tailroom - 2 - ixs->authlen; -+ for (i = 0; i < padlen; i++) { -+ pad[i] = i + 1; -+ } -+ dat[ixs->skb->len - ixs->authlen - 2] = padlen; -+ -+ dat[ixs->skb->len - ixs->authlen - 1] = ixs->iph->protocol; -+ ixs->iph->protocol = IPPROTO_ESP; -+ -+ switch(ixs->ipsp->ips_encalg) { -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+ des_ede3_cbc_encrypt((des_cblock *)idat, -+ (des_cblock *)idat, -+ ilen, -+ ((struct des_eks *)(ixs->ipsp->ips_key_e))[0].ks, -+ ((struct des_eks *)(ixs->ipsp->ips_key_e))[1].ks, -+ ((struct des_eks *)(ixs->ipsp->ips_key_e))[2].ks, -+ (des_cblock *)iv, 1); -+ break; -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+ -+ switch(ixs->ipsp->ips_encalg) { -+#if defined(CONFIG_IPSEC_ENC_3DES) -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ /* XXX update IV with the last 8 octets of the encryption */ -+#if KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK -+ ((__u32*)(ixs->ipsp->ips_iv))[0] = -+ ((__u32 *)(idat))[(ilen >> 2) - 2]; -+ ((__u32*)(ixs->ipsp->ips_iv))[1] = -+ ((__u32 *)(idat))[(ilen >> 2) - 1]; -+#else /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */ -+ prng_bytes(&ipsec_prng, (char *)ixs->ipsp->ips_iv, EMT_ESPDES_IV_SZ); -+#endif /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */ -+ break; -+#endif /* defined(CONFIG_IPSEC_ENC_3DES) */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+ -+ switch(ixs->ipsp->ips_authalg) { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: -+ ipsec_xmit_dmp("espp", (char*)espp, ixs->skb->len - ixs->iphlen - ixs->authlen); -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ ipsec_xmit_dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (caddr_t)espp, ixs->skb->len - ixs->iphlen - ixs->authlen); -+ ipsec_xmit_dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ ipsec_xmit_dmp("ictx hash", (char*)&hash, sizeof(hash)); -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ ipsec_xmit_dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, hash, AHMD596_ALEN); -+ ipsec_xmit_dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ ipsec_xmit_dmp("octx hash", (char*)&hash, sizeof(hash)); -+ memcpy(&(dat[ixs->skb->len - ixs->authlen]), hash, ixs->authlen); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ SHA1Update(&tctx.sha1, (caddr_t)espp, ixs->skb->len - ixs->iphlen - ixs->authlen); -+ SHA1Final(hash, &tctx.sha1); -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); -+ SHA1Final(hash, &tctx.sha1); -+ memcpy(&(dat[ixs->skb->len - ixs->authlen]), hash, ixs->authlen); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ case AH_NONE: -+ break; -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_AH_BADALG; -+ } -+#ifdef NET_21 -+ ixs->skb->h.raw = (unsigned char*)espp; -+#endif /* NET_21 */ -+ -+ return IPSEC_XMIT_OK; -+} -+ -+ -+struct xform_functions esp_xform_funcs[]={ -+ { rcv_checks: ipsec_rcv_esp_checks, -+ rcv_setup_auth: ipsec_rcv_esp_decrypt_setup, -+ rcv_calc_auth: ipsec_rcv_esp_authcalc, -+ rcv_decrypt: ipsec_rcv_esp_decrypt, -+ -+ xmit_setup: ipsec_xmit_esp_setup, -+ xmit_headroom: sizeof(struct esphdr), -+ xmit_needtailroom: 1, -+ }, -+}; -+ -+struct inet_protocol esp_protocol = -+{ -+ ipsec_rcv, /* ESP handler */ -+ NULL, /* TUNNEL error control */ -+#ifdef NETDEV_25 -+ 1, /* no policy */ -+#else -+ 0, /* next */ -+ IPPROTO_ESP, /* protocol ID */ -+ 0, /* copy */ -+ NULL, /* data */ -+ "ESP" /* name */ -+#endif -+}; -+ -+ -+ -+#endif /* !CONFIG_IPSEC_ESP */ -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.2 2004/04/06 02:49:25 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_init.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,531 @@ -+/* -+ * @(#) Initialization code. -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998 - 2002 Richard Guy Briggs -+ * 2001 - 2004 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * /proc system code was split out into ipsec_proc.c after rev. 1.70. -+ * -+ */ -+ -+char ipsec_init_c_version[] = "RCSID $Id$"; -+ -+#include -+#include -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include /* struct sockaddr_in */ -+#include -+#include /* get_random_bytes() */ -+#include -+ -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* 23_SPINLOCK */ -+# include /* *lock* */ -+# endif /* 23_SPINLOCK */ -+#endif /* SPINLOCK */ -+ -+#ifdef NET_21 -+# include -+# include -+#endif /* NET_21 */ -+ -+#include -+#include -+ -+#ifdef CONFIG_PROC_FS -+# include -+#endif /* CONFIG_PROC_FS */ -+ -+#ifdef NETLINK_SOCK -+# include -+#else -+# include -+#endif -+ -+#include "openswan/radij.h" -+ -+#include "openswan/ipsec_life.h" -+#include "openswan/ipsec_stats.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+ -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+# include "openswan/ipcomp.h" -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#include "openswan/ipsec_proto.h" -+#include "openswan/ipsec_alg.h" -+ -+#include -+#include -+ -+#if !defined(CONFIG_IPSEC_ESP) && !defined(CONFIG_IPSEC_AH) -+#error "kernel configuration must include ESP or AH" -+#endif -+ -+/* -+ * seems to be present in 2.4.10 (Linus), but also in some RH and other -+ * distro kernels of a lower number. -+ */ -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_eroute = 0; -+int debug_spi = 0; -+int debug_netlink = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+struct prng ipsec_prng; -+ -+extern int ipsec_device_event(struct notifier_block *dnot, unsigned long event, void *ptr); -+/* -+ * the following structure is required so that we receive -+ * event notifications when network devices are enabled and -+ * disabled (ifconfig up and down). -+ */ -+static struct notifier_block ipsec_dev_notifier={ -+ ipsec_device_event, -+ NULL, -+ 0 -+}; -+ -+#ifdef CONFIG_SYSCTL -+extern int ipsec_sysctl_register(void); -+extern void ipsec_sysctl_unregister(void); -+#endif -+ -+static inline int -+openswan_inet_add_protocol(struct inet_protocol *prot, unsigned protocol) -+{ -+#ifdef NETDEV_25 -+ return inet_add_protocol(prot, protocol); -+#else -+ inet_add_protocol(prot); -+ return 0; -+#endif -+} -+ -+static inline int -+openswan_inet_del_protocol(struct inet_protocol *prot, unsigned protocol) -+{ -+#ifdef NETDEV_25 -+ return inet_del_protocol(prot, protocol); -+#else -+ inet_del_protocol(prot); -+ return 0; -+#endif -+} -+ -+/* void */ -+int -+ipsec_init(void) -+{ -+ int error = 0; -+ unsigned char seed[256]; -+#ifdef CONFIG_IPSEC_ENC_3DES -+ extern int des_check_key; -+ -+ /* turn off checking of keys */ -+ des_check_key=0; -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ -+ KLIPS_PRINT(1, "klips_info:ipsec_init: " -+ "KLIPS startup, Openswan KLIPS IPsec stack version: %s\n", -+ ipsec_version_code()); -+ -+ error |= ipsec_proc_init(); -+ -+#ifdef SPINLOCK -+ ipsec_sadb.sadb_lock = SPIN_LOCK_UNLOCKED; -+#else /* SPINLOCK */ -+ ipsec_sadb.sadb_lock = 0; -+#endif /* SPINLOCK */ -+ -+#ifndef SPINLOCK -+ tdb_lock.lock = 0; -+ eroute_lock.lock = 0; -+#endif /* !SPINLOCK */ -+ -+ error |= ipsec_sadb_init(); -+ error |= ipsec_radijinit(); -+ -+ error |= pfkey_init(); -+ -+ error |= register_netdevice_notifier(&ipsec_dev_notifier); -+ -+#ifdef CONFIG_IPSEC_ESP -+ openswan_inet_add_protocol(&esp_protocol, IPPROTO_ESP); -+#endif /* CONFIG_IPSEC_ESP */ -+ -+#ifdef CONFIG_IPSEC_AH -+ openswan_inet_add_protocol(&ah_protocol, IPPROTO_AH); -+#endif /* CONFIG_IPSEC_AH */ -+ -+/* we never actually link IPCOMP to the stack */ -+#ifdef IPCOMP_USED_ALONE -+#ifdef CONFIG_IPSEC_IPCOMP -+ openswan_inet_add_protocol(&comp_protocol, IPPROTO_COMP); -+#endif /* CONFIG_IPSEC_IPCOMP */ -+#endif -+ -+ error |= ipsec_tunnel_init_devices(); -+ -+ -+#ifdef CONFIG_SYSCTL -+ error |= ipsec_sysctl_register(); -+#endif -+ -+#ifdef CONFIG_IPSEC_ALG -+ ipsec_alg_init(); -+#endif -+ -+ get_random_bytes((void *)seed, sizeof(seed)); -+ prng_init(&ipsec_prng, seed, sizeof(seed)); -+ -+ return error; -+} -+ -+ -+/* void */ -+int -+ipsec_cleanup(void) -+{ -+ int error = 0; -+ -+#ifdef CONFIG_SYSCTL -+ ipsec_sysctl_unregister(); -+#endif -+ KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ -+ "klips_debug:ipsec_cleanup: " -+ "calling ipsec_tunnel_cleanup_devices.\n"); -+ error |= ipsec_tunnel_cleanup_devices(); -+ -+ KLIPS_PRINT(debug_netlink, "called ipsec_tunnel_cleanup_devices"); -+ -+/* we never actually link IPCOMP to the stack */ -+#ifdef IPCOMP_USED_ALONE -+#ifdef CONFIG_IPSEC_IPCOMP -+ if (openswan_inet_del_protocol(&comp_protocol, IPPROTO_COMP) < 0) -+ printk(KERN_INFO "klips_debug:ipsec_cleanup: " -+ "comp close: can't remove protocol\n"); -+#endif /* CONFIG_IPSEC_IPCOMP */ -+#endif /* IPCOMP_USED_ALONE */ -+ -+#ifdef CONFIG_IPSEC_AH -+ if (openswan_inet_del_protocol(&ah_protocol, IPPROTO_AH) < 0) -+ printk(KERN_INFO "klips_debug:ipsec_cleanup: " -+ "ah close: can't remove protocol\n"); -+#endif /* CONFIG_IPSEC_AH */ -+ -+#ifdef CONFIG_IPSEC_ESP -+ if (openswan_inet_del_protocol(&esp_protocol, IPPROTO_ESP) < 0) -+ printk(KERN_INFO "klips_debug:ipsec_cleanup: " -+ "esp close: can't remove protocol\n"); -+#endif /* CONFIG_IPSEC_ESP */ -+ -+ error |= unregister_netdevice_notifier(&ipsec_dev_notifier); -+ -+ KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ -+ "klips_debug:ipsec_cleanup: " -+ "calling ipsec_sadb_cleanup.\n"); -+ error |= ipsec_sadb_cleanup(0); -+ error |= ipsec_sadb_free(); -+ -+ KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ -+ "klips_debug:ipsec_cleanup: " -+ "calling ipsec_radijcleanup.\n"); -+ error |= ipsec_radijcleanup(); -+ -+ KLIPS_PRINT(debug_pfkey, /* debug_tunnel & DB_TN_INIT, */ -+ "klips_debug:ipsec_cleanup: " -+ "calling pfkey_cleanup.\n"); -+ error |= pfkey_cleanup(); -+ -+ ipsec_proc_cleanup(); -+ -+ prng_final(&ipsec_prng); -+ -+ return error; -+} -+ -+#ifdef MODULE -+int -+init_module(void) -+{ -+ int error = 0; -+ -+ error |= ipsec_init(); -+ -+ return error; -+} -+ -+int -+cleanup_module(void) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ -+ "klips_debug:cleanup_module: " -+ "calling ipsec_cleanup.\n"); -+ -+ error |= ipsec_cleanup(); -+ -+ KLIPS_PRINT(1, "klips_info:cleanup_module: " -+ "ipsec module unloaded.\n"); -+ -+ return error; -+} -+#endif /* MODULE */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.93 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.92 2004/03/30 15:30:39 ken -+ * Proper Capitalization -+ * -+ * Revision 1.91 2004/03/22 01:51:51 ken -+ * We are open -+ * -+ * Revision 1.90.4.2 2004/04/05 04:30:46 mcr -+ * patches for alg-branch to compile/work with 2.x openswan -+ * -+ * Revision 1.90.4.1 2003/12/22 15:25:52 jjo -+ * Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.90 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.89.4.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.89 2003/07/31 22:47:16 mcr -+ * preliminary (untested by FS-team) 2.5 patches. -+ * -+ * Revision 1.88 2003/06/22 20:05:36 mcr -+ * clarified why IPCOMP was not being registered, and put a new -+ * #ifdef in rather than #if 0. -+ * -+ * Revision 1.87 2002/09/20 15:40:51 rgb -+ * Added a lock to the global ipsec_sadb struct for future use. -+ * Split ipsec_sadb_cleanup from new funciton ipsec_sadb_free to avoid problem -+ * of freeing newly created structures when clearing the reftable upon startup -+ * to start from a known state. -+ * -+ * Revision 1.86 2002/08/15 18:39:15 rgb -+ * Move ipsec_prng outside debug code. -+ * -+ * Revision 1.85 2002/05/14 02:35:29 rgb -+ * Change reference to tdb to ipsa. -+ * -+ * Revision 1.84 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.83 2002/04/24 07:36:28 mcr -+ * Moved from ./klips/net/ipsec/ipsec_init.c,v -+ * -+ * Revision 1.82 2002/04/20 00:12:25 rgb -+ * Added esp IV CBC attack fix, disabled. -+ * -+ * Revision 1.81 2002/04/09 16:13:32 mcr -+ * switch license to straight GPL. -+ * -+ * Revision 1.80 2002/03/24 07:34:08 rgb -+ * Sanity check for at least one of AH or ESP configured. -+ * -+ * Revision 1.79 2002/02/05 22:55:15 mcr -+ * added MODULE_LICENSE declaration. -+ * This macro does not appear in all kernel versions (see comment). -+ * -+ * Revision 1.78 2002/01/29 17:17:55 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.77 2002/01/29 04:00:51 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.76 2002/01/29 02:13:17 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.75 2001/11/26 09:23:48 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.74 2001/11/22 05:44:11 henry -+ * new version stuff -+ * -+ * Revision 1.71.2.2 2001/10/22 20:51:00 mcr -+ * explicitely set des_check_key. -+ * -+ * Revision 1.71.2.1 2001/09/25 02:19:39 mcr -+ * /proc manipulation code moved to new ipsec_proc.c -+ * -+ * Revision 1.73 2001/11/06 19:47:17 rgb -+ * Changed lifetime_packets to uint32 from uint64. -+ * -+ * Revision 1.72 2001/10/18 04:45:19 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.71 2001/09/20 15:32:45 rgb -+ * Minor pfkey lifetime fixes. -+ * -+ * Revision 1.70 2001/07/06 19:51:21 rgb -+ * Added inbound policy checking code for IPIP SAs. -+ * -+ * Revision 1.69 2001/06/14 19:33:26 rgb -+ * Silence startup message for console, but allow it to be logged. -+ * Update copyright date. -+ * -+ * Revision 1.68 2001/05/29 05:14:36 rgb -+ * Added PMTU to /proc/net/ipsec_tncfg output. See 'man 5 ipsec_tncfg'. -+ * -+ * Revision 1.67 2001/05/04 16:34:52 rgb -+ * Rremove erroneous checking of return codes for proc_net_* in 2.4. -+ * -+ * Revision 1.66 2001/05/03 19:40:34 rgb -+ * Check error return codes in startup and shutdown. -+ * -+ * Revision 1.65 2001/02/28 05:03:27 rgb -+ * Clean up and rationalise startup messages. -+ * -+ * Revision 1.64 2001/02/27 22:24:53 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.63 2000/11/29 20:14:06 rgb -+ * Add src= to the output of /proc/net/ipsec_spi and delete dst from IPIP. -+ * -+ * Revision 1.62 2000/11/06 04:31:24 rgb -+ * Ditched spin_lock_irqsave in favour of spin_lock_bh. -+ * Fixed longlong for pre-2.4 kernels (Svenning). -+ * Add Svenning's adaptive content compression. -+ * Disabled registration of ipcomp handler. -+ * -+ * Revision 1.61 2000/10/11 13:37:54 rgb -+ * #ifdef out debug print that causes proc/net/ipsec_version to oops. -+ * -+ * Revision 1.60 2000/09/20 03:59:01 rgb -+ * Change static info functions to DEBUG_NO_STATIC to reveal function names -+ * in oopsen. -+ * -+ * Revision 1.59 2000/09/16 01:06:26 rgb -+ * Added cast of var to silence compiler warning about long fed to int -+ * format. -+ * -+ * Revision 1.58 2000/09/15 11:37:01 rgb -+ * Merge in heavily modified Svenning Soerensen's -+ * IPCOMP zlib deflate code. -+ * -+ * Revision 1.57 2000/09/12 03:21:50 rgb -+ * Moved radij_c_version printing to ipsec_version_get_info(). -+ * Reformatted ipsec_version_get_info(). -+ * Added sysctl_{,un}register() calls. -+ * -+ * Revision 1.56 2000/09/08 19:16:50 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * Removed all references to CONFIG_IPSEC_PFKEYv2. -+ * -+ * Revision 1.55 2000/08/30 05:19:03 rgb -+ * Cleaned up no longer used spi_next, netlink register/unregister, other -+ * minor cleanup. -+ * Removed cruft replaced by TDB_XFORM_NAME. -+ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst. -+ * Moved debug version strings to printk when /proc/net/ipsec_version is -+ * called. -+ * -+ * Revision 1.54 2000/08/20 18:31:05 rgb -+ * Changed cosmetic alignment in spi_info. -+ * Changed addtime and usetime to use actual value which is relative -+ * anyways, as intended. (Momchil) -+ * -+ * Revision 1.53 2000/08/18 17:37:03 rgb -+ * Added an (int) cast to shut up the compiler... -+ * -+ * Revision 1.52 2000/08/01 14:51:50 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.51 2000/07/25 20:41:22 rgb -+ * Removed duplicate parameter in spi_getinfo. -+ * -+ * Revision 1.50 2000/07/17 03:21:45 rgb -+ * Removed /proc/net/ipsec_spinew. -+ * -+ * Revision 1.49 2000/06/28 05:46:51 rgb -+ * Renamed ivlen to iv_bits for consistency. -+ * Changed output of add and use times to be relative to now. -+ * -+ * Revision 1.48 2000/05/11 18:26:10 rgb -+ * Commented out calls to netlink_attach/detach to avoid activating netlink -+ * in the kenrel config. -+ * -+ * Revision 1.47 2000/05/10 22:35:26 rgb -+ * Comment out most of the startup version information. -+ * -+ * Revision 1.46 2000/03/22 16:15:36 rgb -+ * Fixed renaming of dev_get (MB). -+ * -+ * Revision 1.45 2000/03/16 06:40:48 rgb -+ * Hardcode PF_KEYv2 support. -+ * -+ * Revision 1.44 2000/01/22 23:19:20 rgb -+ * Simplified code to use existing macro TDB_XFORM_NAME(). -+ * -+ * Revision 1.43 2000/01/21 06:14:04 rgb -+ * Print individual stats only if non-zero. -+ * Removed 'bits' from each keylength for brevity. -+ * Shortened lifetimes legend for brevity. -+ * Changed wording from 'last_used' to the clearer 'idle'. -+ * -+ * Revision 1.42 1999/12/31 14:57:19 rgb -+ * MB fix for new dummy-less proc_get_info in 2.3.35. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_ipcomp.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,276 @@ -+/* -+ * processing code for IPCOMP -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_ipcomp_c_version[] = "RCSID $Id$"; -+#include -+#include -+ -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define proto_priv cb -+#endif /* NET21 */ -+#include -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipsec_xmit.h" -+ -+#include "openswan/ipsec_auth.h" -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+#include "openswan/ipsec_ipcomp.h" -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#include "openswan/ipsec_proto.h" -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_ipcomp = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+enum ipsec_rcv_value -+ipsec_rcv_ipcomp_checks(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb) -+{ -+ int ipcompminlen; -+ -+ ipcompminlen = irs->hard_header_len + sizeof(struct iphdr); -+ -+ if(skb->len < (ipcompminlen + sizeof(struct ipcomphdr))) { -+ KLIPS_PRINT(debug_rcv & DB_RX_INAU, -+ "klips_debug:ipsec_rcv: " -+ "runt comp packet of skb->len=%d received from %s, dropped.\n", -+ skb->len, -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_BADLEN; -+ } -+ -+ irs->protostuff.ipcompstuff.compp = (struct ipcomphdr *)(skb->data + irs->iphlen); -+ irs->said.spi = htonl((__u32)ntohs(irs->protostuff.ipcompstuff.compp->ipcomp_cpi)); -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_rcv_value -+ipsec_rcv_ipcomp_decomp(struct ipsec_rcv_state *irs) -+{ -+ unsigned int flags = 0; -+ struct ipsec_sa *ipsp = irs->ipsp; -+ struct sk_buff *skb; -+ -+ skb=irs->skb; -+ -+ ipsec_xmit_dmp("ipcomp", skb->data, skb->len); -+ -+ if(ipsp == NULL) { -+ return IPSEC_RCV_SAIDNOTFOUND; -+ } -+ -+#if 0 -+ /* we want to check that this wasn't the first SA on the list, because -+ * we don't support bare IPCOMP, for unexplained reasons. MCR -+ */ -+ if (ipsp->ips_onext != NULL) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "Incoming packet with outer IPCOMP header SA:%s: not yet supported by KLIPS, dropped\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ -+ return IPSEC_RCV_IPCOMPALONE; -+ } -+#endif -+ -+ if(sysctl_ipsec_inbound_policy_check && -+ ((((ntohl(ipsp->ips_said.spi) & 0x0000ffff) != ntohl(irs->said.spi)) && -+ (ipsp->ips_encalg != ntohl(irs->said.spi)) /* this is a workaround for peer non-compliance with rfc2393 */ -+ ))) { -+ char sa2[SATOT_BUF]; -+ size_t sa_len2 = 0; -+ -+ sa_len2 = satot(&ipsp->ips_said, 0, sa2, sizeof(sa2)); -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "Incoming packet with SA(IPCA):%s does not match policy SA(IPCA):%s cpi=%04x cpi->spi=%08x spi=%08x, spi->cpi=%04x for SA grouping, dropped.\n", -+ irs->sa_len ? irs->sa : " (error)", -+ ipsp != NULL ? (sa_len2 ? sa2 : " (error)") : "NULL", -+ ntohs(irs->protostuff.ipcompstuff.compp->ipcomp_cpi), -+ (__u32)ntohl(irs->said.spi), -+ ipsp != NULL ? (__u32)ntohl((ipsp->ips_said.spi)) : 0, -+ ipsp != NULL ? (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff) : 0); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_SAIDNOTFOUND; -+ } -+ -+ ipsp->ips_comp_ratio_cbytes += ntohs(irs->ipp->tot_len); -+ irs->next_header = irs->protostuff.ipcompstuff.compp->ipcomp_nh; -+ -+ skb = skb_decompress(skb, ipsp, &flags); -+ if (!skb || flags) { -+ spin_unlock(&tdb_lock); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "skb_decompress() returned error flags=%x, dropped.\n", -+ flags); -+ if (irs->stats) { -+ if (flags) -+ irs->stats->rx_errors++; -+ else -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_IPCOMPFAILED; -+ } -+ -+ /* make sure we update the pointer */ -+ irs->skb = skb; -+ -+#ifdef NET_21 -+ irs->ipp = skb->nh.iph; -+#else /* NET_21 */ -+ irs->ipp = skb->ip_hdr; -+#endif /* NET_21 */ -+ -+ ipsp->ips_comp_ratio_dbytes += ntohs(irs->ipp->tot_len); -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "packet decompressed SA(IPCA):%s cpi->spi=%08x spi=%08x, spi->cpi=%04x, nh=%d.\n", -+ irs->sa_len ? irs->sa : " (error)", -+ (__u32)ntohl(irs->said.spi), -+ ipsp != NULL ? (__u32)ntohl((ipsp->ips_said.spi)) : 0, -+ ipsp != NULL ? (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff) : 0, -+ irs->next_header); -+ KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, irs->ipp); -+ -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_xmit_ipcomp_setup(struct ipsec_xmit_state *ixs) -+{ -+ unsigned int flags = 0; -+#ifdef CONFIG_IPSEC_DEBUG -+ unsigned int old_tot_len = ntohs(ixs->iph->tot_len); -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ ixs->ipsp->ips_comp_ratio_dbytes += ntohs(ixs->iph->tot_len); -+ -+ ixs->skb = skb_compress(ixs->skb, ixs->ipsp, &flags); -+ -+#ifdef NET_21 -+ ixs->iph = ixs->skb->nh.iph; -+#else /* NET_21 */ -+ ixs->iph = ixs->skb->ip_hdr; -+#endif /* NET_21 */ -+ -+ ixs->ipsp->ips_comp_ratio_cbytes += ntohs(ixs->iph->tot_len); -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_tunnel & DB_TN_CROUT) -+ { -+ if (old_tot_len > ntohs(ixs->iph->tot_len)) -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "packet shrunk from %d to %d bytes after compression, cpi=%04x (should be from spi=%08x, spi&0xffff=%04x.\n", -+ old_tot_len, ntohs(ixs->iph->tot_len), -+ ntohs(((struct ipcomphdr*)(((char*)ixs->iph) + ((ixs->iph->ihl) << 2)))->ipcomp_cpi), -+ ntohl(ixs->ipsp->ips_said.spi), -+ (__u16)(ntohl(ixs->ipsp->ips_said.spi) & 0x0000ffff)); -+ else -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "packet did not compress (flags = %d).\n", -+ flags); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ return IPSEC_XMIT_OK; -+} -+ -+struct xform_functions ipcomp_xform_funcs[]={ -+ {rcv_checks: ipsec_rcv_ipcomp_checks, -+ rcv_decrypt: ipsec_rcv_ipcomp_decomp, -+ xmit_setup: ipsec_xmit_ipcomp_setup, -+ xmit_headroom: 0, -+ xmit_needtailroom: 0, -+ }, -+}; -+ -+#if 0 -+/* We probably don't want to install a pure IPCOMP protocol handler, but -+ only want to handle IPCOMP if it is encapsulated inside an ESP payload -+ (which is already handled) */ -+#ifdef CONFIG_IPSEC_IPCOMP -+struct inet_protocol comp_protocol = -+{ -+ ipsec_rcv, /* COMP handler */ -+ NULL, /* COMP error control */ -+#ifdef NETDEV_25 -+ 1, /* no policy */ -+#else -+ 0, /* next */ -+ IPPROTO_COMP, /* protocol ID */ -+ 0, /* copy */ -+ NULL, /* data */ -+ "COMP" /* name */ -+#endif -+}; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+#endif -+ -+#endif /* CONFIG_IPSEC_IPCOMP */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_ipip.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,133 @@ -+/* -+ * processing code for IPIP -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_ipip_c_version[] = "RCSID $Id$"; -+#include -+#include -+ -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define proto_priv cb -+#endif /* NET21 */ -+#include -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipsec_xmit.h" -+ -+#include "openswan/ipsec_auth.h" -+#include "openswan/ipsec_ipip.h" -+#include "openswan/ipsec_param.h" -+ -+#include "openswan/ipsec_proto.h" -+ -+enum ipsec_xmit_value -+ipsec_xmit_ipip_setup(struct ipsec_xmit_state *ixs) -+{ -+ ixs->iph->version = 4; -+ -+ switch(sysctl_ipsec_tos) { -+ case 0: -+#ifdef NET_21 -+ ixs->iph->tos = ixs->skb->nh.iph->tos; -+#else /* NET_21 */ -+ ixs->iph->tos = ixs->skb->ip_hdr->tos; -+#endif /* NET_21 */ -+ break; -+ case 1: -+ ixs->iph->tos = 0; -+ break; -+ default: -+ break; -+ } -+#ifdef NET_21 -+#ifdef NETDEV_23 -+ ixs->iph->ttl = sysctl_ip_default_ttl; -+#else /* NETDEV_23 */ -+ ixs->iph->ttl = ip_statistics.IpDefaultTTL; -+#endif /* NETDEV_23 */ -+#else /* NET_21 */ -+ ixs->iph->ttl = 64; /* ip_statistics.IpDefaultTTL; */ -+#endif /* NET_21 */ -+ ixs->iph->frag_off = 0; -+ ixs->iph->saddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_s))->sin_addr.s_addr; -+ ixs->iph->daddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_d))->sin_addr.s_addr; -+ ixs->iph->protocol = IPPROTO_IPIP; -+ ixs->iph->ihl = sizeof(struct iphdr) >> 2; -+ -+ KLIPS_IP_SELECT_IDENT(ixs->iph, ixs->skb); -+ -+ ixs->newdst = (__u32)ixs->iph->daddr; -+ ixs->newsrc = (__u32)ixs->iph->saddr; -+ -+#ifdef NET_21 -+ ixs->skb->h.ipiph = ixs->skb->nh.iph; -+#endif /* NET_21 */ -+ return IPSEC_XMIT_OK; -+} -+ -+struct xform_functions ipip_xform_funcs[]={ -+ { rcv_checks: NULL, -+ rcv_setup_auth: NULL, -+ rcv_calc_auth: NULL, -+ rcv_decrypt: NULL, -+ -+ xmit_setup: ipsec_xmit_ipip_setup, -+ xmit_headroom: sizeof(struct iphdr), -+ xmit_needtailroom: 0, -+ }, -+}; -+ -+ -+ -+ -+ -+ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_life.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,263 @@ -+/* -+ * @(#) lifetime structure utilities -+ * -+ * Copyright (C) 2001 Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ */ -+ -+/* -+ * This provides series of utility functions for dealing with lifetime -+ * structures. -+ * -+ * ipsec_check_lifetime - returns -1 hard lifetime exceeded -+ * 0 soft lifetime exceeded -+ * 1 everything is okay -+ * based upon whether or not the count exceeds hard/soft -+ * -+ */ -+ -+#define __NO_VERSION__ -+#include -+#include /* for CONFIG_IP_FORWARD */ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#include /* struct device, struct net_device_stats and other headers */ -+#include /* eth_type_trans */ -+#include -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_life.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_eroute.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+ -+#include "openswan/ipsec_sa.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_ipe4.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+#include "openswan/ipcomp.h" -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+ -+ -+enum ipsec_life_alive -+ipsec_lifetime_check(struct ipsec_lifetime64 *il64, -+ const char *lifename, -+ const char *saname, -+ enum ipsec_life_type ilt, -+ enum ipsec_direction idir, -+ struct ipsec_sa *ips) -+{ -+ __u64 count; -+ const char *dir; -+ -+ if(saname == NULL) { -+ saname = "unknown-SA"; -+ } -+ -+ if(idir == ipsec_incoming) { -+ dir = "incoming"; -+ } else { -+ dir = "outgoing"; -+ } -+ -+ -+ if(ilt == ipsec_life_timebased) { -+ count = jiffies/HZ - il64->ipl_count; -+ } else { -+ count = il64->ipl_count; -+ } -+ -+ if(il64->ipl_hard && -+ (count > il64->ipl_hard)) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_lifetime_check: " -+ "hard %s lifetime of SA:<%s%s%s> %s has been reached, SA expired, " -+ "%s packet dropped.\n", -+ lifename, -+ IPS_XFORM_NAME(ips), -+ saname, -+ dir); -+ -+ pfkey_expire(ips, 1); -+ return ipsec_life_harddied; -+ } -+ -+ if(il64->ipl_soft && -+ (count > il64->ipl_soft)) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_lifetime_check: " -+ "soft %s lifetime of SA:<%s%s%s> %s has been reached, SA expiring, " -+ "soft expire message sent up, %s packet still processed.\n", -+ lifename, -+ IPS_XFORM_NAME(ips), -+ saname, -+ dir); -+ -+ if(ips->ips_state != SADB_SASTATE_DYING) { -+ pfkey_expire(ips, 0); -+ } -+ ips->ips_state = SADB_SASTATE_DYING; -+ -+ return ipsec_life_softdied; -+ } -+ return ipsec_life_okay; -+} -+ -+ -+/* -+ * This function takes a buffer (with length), a lifetime name and type, -+ * and formats a string to represent the current values of the lifetime. -+ * -+ * It returns the number of bytes that the format took (or would take, -+ * if the buffer were large enough: snprintf semantics). -+ * This is used in /proc routines and in debug output. -+ */ -+int -+ipsec_lifetime_format(char *buffer, -+ int buflen, -+ char *lifename, -+ enum ipsec_life_type timebaselife, -+ struct ipsec_lifetime64 *lifetime) -+{ -+ int len = 0; -+ __u64 count; -+ -+ if(timebaselife == ipsec_life_timebased) { -+ count = jiffies/HZ - lifetime->ipl_count; -+ } else { -+ count = lifetime->ipl_count; -+ } -+ -+ if(lifetime->ipl_count > 1 || -+ lifetime->ipl_soft || -+ lifetime->ipl_hard) { -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)) -+ len = ipsec_snprintf(buffer, buflen, -+ "%s(%Lu,%Lu,%Lu)", -+ lifename, -+ count, -+ lifetime->ipl_soft, -+ lifetime->ipl_hard); -+#else /* XXX high 32 bits are not displayed */ -+ len = ipsec_snprintf(buffer, buflen, -+ "%s(%lu,%lu,%lu)", -+ lifename, -+ (unsigned long)count, -+ (unsigned long)lifetime->ipl_soft, -+ (unsigned long)lifetime->ipl_hard); -+#endif -+ } -+ -+ return len; -+} -+ -+void -+ipsec_lifetime_update_hard(struct ipsec_lifetime64 *lifetime, -+ __u64 newvalue) -+{ -+ if(newvalue && -+ (!lifetime->ipl_hard || -+ (newvalue < lifetime->ipl_hard))) { -+ lifetime->ipl_hard = newvalue; -+ -+ if(!lifetime->ipl_soft && -+ (lifetime->ipl_hard < lifetime->ipl_soft)) { -+ lifetime->ipl_soft = lifetime->ipl_hard; -+ } -+ } -+} -+ -+void -+ipsec_lifetime_update_soft(struct ipsec_lifetime64 *lifetime, -+ __u64 newvalue) -+{ -+ if(newvalue && -+ (!lifetime->ipl_soft || -+ (newvalue < lifetime->ipl_soft))) { -+ lifetime->ipl_soft = newvalue; -+ -+ if(lifetime->ipl_hard && -+ (lifetime->ipl_hard < lifetime->ipl_soft)) { -+ lifetime->ipl_soft = lifetime->ipl_hard; -+ } -+ } -+} -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.12 2004/04/23 20:44:35 ken -+ * Update comments -+ * -+ * Revision 1.11 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.10 2004/03/30 11:03:10 paul -+ * two more occurances of snprintf, found by Sam from a users oops msg. -+ * -+ * Revision 1.9 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.8.4.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.8 2003/02/06 02:00:10 rgb -+ * Fixed incorrect debugging text label -+ * -+ * Revision 1.7 2002/05/23 07:16:26 rgb -+ * Fixed absolute/relative reference to lifetime count printout. -+ * -+ * Revision 1.6 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.5 2002/04/24 07:36:28 mcr -+ * Moved from ./klips/net/ipsec/ipsec_life.c,v -+ * -+ * Revision 1.4 2002/01/29 17:17:55 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.3 2002/01/29 02:13:17 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.2 2001/11/26 09:16:14 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:25:57 mcr -+ * lifetime structure created and common functions created. -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_mast.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1080 @@ -+/* -+ * IPSEC MAST code. -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_mast_c_version[] = "RCSID $Id$"; -+ -+#define __NO_VERSION__ -+#include -+#include /* for CONFIG_IP_FORWARD */ -+#include -+#include /* printk() */ -+ -+#include "freeswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include /* struct tcphdr */ -+#include /* struct udphdr */ -+#include -+#include -+#include -+#include -+#include -+#undef dev_kfree_skb -+#define dev_kfree_skb(a,b) kfree_skb(a) -+#define PHYSDEV_TYPE -+#include -+#include /* icmp_send() */ -+#include -+#include -+ -+#include -+ -+#include "freeswan/radij.h" -+#include "freeswan/ipsec_life.h" -+#include "freeswan/ipsec_xform.h" -+#include "freeswan/ipsec_eroute.h" -+#include "freeswan/ipsec_encap.h" -+#include "freeswan/ipsec_radij.h" -+#include "freeswan/ipsec_sa.h" -+#include "freeswan/ipsec_tunnel.h" -+#include "freeswan/ipsec_mast.h" -+#include "freeswan/ipsec_ipe4.h" -+#include "freeswan/ipsec_ah.h" -+#include "freeswan/ipsec_esp.h" -+ -+#include -+#include -+ -+#include "freeswan/ipsec_proto.h" -+ -+int ipsec_maxdevice_count = -1; -+ -+DEBUG_NO_STATIC int -+ipsec_mast_open(struct device *dev) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ -+ /* -+ * Can't open until attached. -+ */ -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_open: " -+ "dev = %s, prv->dev = %s\n", -+ dev->name, prv->dev?prv->dev->name:"NONE"); -+ -+ if (prv->dev == NULL) -+ return -ENODEV; -+ -+ MOD_INC_USE_COUNT; -+ return 0; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_mast_close(struct device *dev) -+{ -+ MOD_DEC_USE_COUNT; -+ return 0; -+} -+ -+static inline int ipsec_mast_xmit2(struct sk_buff *skb) -+{ -+ return ip_send(skb); -+} -+ -+enum ipsec_xmit_value -+ipsec_mast_send(struct ipsec_xmit_state*ixs) -+{ -+ /* new route/dst cache code from James Morris */ -+ ixs->skb->dev = ixs->physdev; -+ /*skb_orphan(ixs->skb);*/ -+ if((ixs->error = ip_route_output(&ixs->route, -+ ixs->skb->nh.iph->daddr, -+ ixs->pass ? 0 : ixs->skb->nh.iph->saddr, -+ RT_TOS(ixs->skb->nh.iph->tos), -+ ixs->physdev->iflink /* rgb: should this be 0? */))) { -+ ixs->stats->tx_errors++; -+ KLIPS_PRINT(debug_mast & DB_MAST_XMIT, -+ "klips_debug:ipsec_xmit_send: " -+ "ip_route_output failed with error code %d, rt->u.dst.dev=%s, dropped\n", -+ ixs->error, -+ ixs->route->u.dst.dev->name); -+ return IPSEC_XMIT_ROUTEERR; -+ } -+ if(ixs->dev == ixs->route->u.dst.dev) { -+ ip_rt_put(ixs->route); -+ /* This is recursion, drop it. */ -+ ixs->stats->tx_errors++; -+ KLIPS_PRINT(debug_mast & DB_MAST_XMIT, -+ "klips_debug:ipsec_xmit_send: " -+ "suspect recursion, dev=rt->u.dst.dev=%s, dropped\n", -+ ixs->dev->name); -+ return IPSEC_XMIT_RECURSDETECT; -+ } -+ dst_release(ixs->skb->dst); -+ ixs->skb->dst = &ixs->route->u.dst; -+ ixs->stats->tx_bytes += ixs->skb->len; -+ if(ixs->skb->len < ixs->skb->nh.raw - ixs->skb->data) { -+ ixs->stats->tx_errors++; -+ printk(KERN_WARNING -+ "klips_error:ipsec_xmit_send: " -+ "tried to __skb_pull nh-data=%ld, %d available. This should never happen, please report.\n", -+ (unsigned long)(ixs->skb->nh.raw - ixs->skb->data), -+ ixs->skb->len); -+ return IPSEC_XMIT_PUSHPULLERR; -+ } -+ __skb_pull(ixs->skb, ixs->skb->nh.raw - ixs->skb->data); -+#ifdef SKB_RESET_NFCT -+ nf_conntrack_put(ixs->skb->nfct); -+ ixs->skb->nfct = NULL; -+#ifdef CONFIG_NETFILTER_DEBUG -+ ixs->skb->nf_debug = 0; -+#endif /* CONFIG_NETFILTER_DEBUG */ -+#endif /* SKB_RESET_NFCT */ -+ KLIPS_PRINT(debug_mast & DB_MAST_XMIT, -+ "klips_debug:ipsec_xmit_send: " -+ "...done, calling ip_send() on device:%s\n", -+ ixs->skb->dev ? ixs->skb->dev->name : "NULL"); -+ KLIPS_IP_PRINT(debug_mast & DB_MAST_XMIT, ixs->skb->nh.iph); -+ { -+ int err; -+ -+ err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, ixs->skb, NULL, ixs->route->u.dst.dev, -+ ipsec_mast_xmit2); -+ if(err != NET_XMIT_SUCCESS && err != NET_XMIT_CN) { -+ if(net_ratelimit()) -+ printk(KERN_ERR -+ "klips_error:ipsec_xmit_send: " -+ "ip_send() failed, err=%d\n", -+ -err); -+ ixs->stats->tx_errors++; -+ ixs->stats->tx_aborted_errors++; -+ ixs->skb = NULL; -+ return IPSEC_XMIT_IPSENDFAILURE; -+ } -+ } -+ ixs->stats->tx_packets++; -+ -+ ixs->skb = NULL; -+ -+ return IPSEC_XMIT_OK; -+} -+ -+void -+ipsec_mast_cleanup(struct ipsec_xmit_state*ixs) -+{ -+#if defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) -+ netif_wake_queue(ixs->dev); -+#else /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ -+ ixs->dev->tbusy = 0; -+#endif /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ -+ if(ixs->saved_header) { -+ kfree(ixs->saved_header); -+ } -+ if(ixs->skb) { -+ dev_kfree_skb(ixs->skb, FREE_WRITE); -+ } -+ if(ixs->oskb) { -+ dev_kfree_skb(ixs->oskb, FREE_WRITE); -+ } -+ if (ixs->ips.ips_ident_s.data) { -+ kfree(ixs->ips.ips_ident_s.data); -+ } -+ if (ixs->ips.ips_ident_d.data) { -+ kfree(ixs->ips.ips_ident_d.data); -+ } -+} -+ -+#if 0 -+/* -+ * This function assumes it is being called from dev_queue_xmit() -+ * and that skb is filled properly by that function. -+ */ -+int -+ipsec_mast_start_xmit(struct sk_buff *skb, struct device *dev, IPsecSAref_t SAref) -+{ -+ struct ipsec_xmit_state ixs_mem; -+ struct ipsec_xmit_state *ixs = &ixs_mem; -+ enum ipsec_xmit_value stat = IPSEC_XMIT_OK; -+ -+ /* dev could be a mast device, but should be optional, I think... */ -+ /* SAref is also optional, but one of the two must be present. */ -+ /* I wonder if it could accept no device or saref and guess? */ -+ -+/* ipsec_xmit_sanity_check_dev(ixs); */ -+ -+ ipsec_xmit_sanity_check_skb(ixs); -+ -+ ipsec_xmit_adjust_hard_header(ixs); -+ -+ stat = ipsec_xmit_encap_bundle(ixs); -+ if(stat != IPSEC_XMIT_OK) { -+ /* SA processing failed */ -+ } -+ -+ ipsec_xmit_hard_header_restore(); -+} -+#endif -+ -+DEBUG_NO_STATIC struct net_device_stats * -+ipsec_mast_get_stats(struct device *dev) -+{ -+ return &(((struct ipsecpriv *)(dev->priv))->mystats); -+} -+ -+/* -+ * Revectored calls. -+ * For each of these calls, a field exists in our private structure. -+ */ -+ -+DEBUG_NO_STATIC int -+ipsec_mast_hard_header(struct sk_buff *skb, struct device *dev, -+ unsigned short type, void *daddr, void *saddr, unsigned len) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ struct device *tmp; -+ int ret; -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(skb == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_hard_header: " -+ "no skb...\n"); -+ return -ENODATA; -+ } -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_hard_header: " -+ "no device...\n"); -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_hard_header: " -+ "skb->dev=%s dev=%s.\n", -+ skb->dev ? skb->dev->name : "NULL", -+ dev->name); -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_hard_header: " -+ "no private space associated with dev=%s\n", -+ dev->name ? dev->name : "NULL"); -+ return -ENODEV; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_hard_header: " -+ "no physical device associated with dev=%s\n", -+ dev->name ? dev->name : "NULL"); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ /* check if we have to send a IPv6 packet. It might be a Router -+ Solicitation, where the building of the packet happens in -+ reverse order: -+ 1. ll hdr, -+ 2. IPv6 hdr, -+ 3. ICMPv6 hdr -+ -> skb->nh.raw is still uninitialized when this function is -+ called!! If this is no IPv6 packet, we can print debugging -+ messages, otherwise we skip all debugging messages and just -+ build the ll header */ -+ if(type != ETH_P_IPV6) { -+ /* execute this only, if we don't have to build the -+ header for a IPv6 packet */ -+ if(!prv->hard_header) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_hard_header: " -+ "physical device has been detached, packet dropped 0p%p->0p%p len=%d type=%d dev=%s->NULL ", -+ saddr, -+ daddr, -+ len, -+ type, -+ dev->name); -+ KLIPS_PRINTMORE(debug_mast & DB_MAST_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+#define da ((struct device *)(prv->dev))->dev_addr -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_hard_header: " -+ "Revectored 0p%p->0p%p len=%d type=%d dev=%s->%s dev_addr=%02x:%02x:%02x:%02x:%02x:%02x ", -+ saddr, -+ daddr, -+ len, -+ type, -+ dev->name, -+ prv->dev->name, -+ da[0], da[1], da[2], da[3], da[4], da[5]); -+ KLIPS_PRINTMORE(debug_mast & DB_MAST_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+ } else { -+ KLIPS_PRINT(debug_mast, -+ "klips_debug:ipsec_mast_hard_header: " -+ "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n"); -+ } -+ tmp = skb->dev; -+ skb->dev = prv->dev; -+ ret = prv->hard_header(skb, prv->dev, type, (void *)daddr, (void *)saddr, len); -+ skb->dev = tmp; -+ return ret; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_mast_rebuild_header(struct sk_buff *skb) -+{ -+ struct ipsecpriv *prv = skb->dev->priv; -+ struct device *tmp; -+ int ret; -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(skb->dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_rebuild_header: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_rebuild_header: " -+ "no private space associated with dev=%s", -+ skb->dev->name ? skb->dev->name : "NULL"); -+ return -ENODEV; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_rebuild_header: " -+ "no physical device associated with dev=%s", -+ skb->dev->name ? skb->dev->name : "NULL"); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ if(!prv->rebuild_header) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_rebuild_header: " -+ "physical device has been detached, packet dropped skb->dev=%s->NULL ", -+ skb->dev->name); -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast: " -+ "Revectored rebuild_header dev=%s->%s ", -+ skb->dev->name, prv->dev->name); -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+ tmp = skb->dev; -+ skb->dev = prv->dev; -+ -+ ret = prv->rebuild_header(skb); -+ skb->dev = tmp; -+ return ret; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_mast_set_mac_address(struct device *dev, void *addr) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_set_mac_address: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_set_mac_address: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return -ENODEV; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_set_mac_address: " -+ "no physical device associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ if(!prv->set_mac_address) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_set_mac_address: " -+ "physical device has been detached, cannot set - skb->dev=%s->NULL\n", -+ dev->name); -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_set_mac_address: " -+ "Revectored dev=%s->%s addr=0p%p\n", -+ dev->name, prv->dev->name, addr); -+ return prv->set_mac_address(prv->dev, addr); -+ -+} -+ -+DEBUG_NO_STATIC void -+ipsec_mast_cache_update(struct hh_cache *hh, struct device *dev, unsigned char * haddr) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_cache_update: " -+ "no device..."); -+ return; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_cache_update: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_cache_update: " -+ "no physical device associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ stats->tx_dropped++; -+ return; -+ } -+ -+ if(!prv->header_cache_update) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_cache_update: " -+ "physical device has been detached, cannot set - skb->dev=%s->NULL\n", -+ dev->name); -+ return; -+ } -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast: " -+ "Revectored cache_update\n"); -+ prv->header_cache_update(hh, prv->dev, haddr); -+ return; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_mast_neigh_setup(struct neighbour *n) -+{ -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_neigh_setup:\n"); -+ -+ if (n->nud_state == NUD_NONE) { -+ n->ops = &arp_broken_ops; -+ n->output = n->ops->output; -+ } -+ return 0; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_mast_neigh_setup_dev(struct device *dev, struct neigh_parms *p) -+{ -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_neigh_setup_dev: " -+ "setting up %s\n", -+ dev ? dev->name : "NULL"); -+ -+ if (p->tbl->family == AF_INET) { -+ p->neigh_setup = ipsec_mast_neigh_setup; -+ p->ucast_probes = 0; -+ p->mcast_probes = 0; -+ } -+ return 0; -+} -+ -+/* -+ * We call the attach routine to attach another device. -+ */ -+ -+DEBUG_NO_STATIC int -+ipsec_mast_attach(struct device *dev, struct device *physdev) -+{ -+ int i; -+ struct ipsecpriv *prv = dev->priv; -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_attach: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_attach: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return -ENODATA; -+ } -+ -+ prv->dev = physdev; -+ prv->hard_start_xmit = physdev->hard_start_xmit; -+ prv->get_stats = physdev->get_stats; -+ -+ if (physdev->hard_header) { -+ prv->hard_header = physdev->hard_header; -+ dev->hard_header = ipsec_mast_hard_header; -+ } else -+ dev->hard_header = NULL; -+ -+ if (physdev->rebuild_header) { -+ prv->rebuild_header = physdev->rebuild_header; -+ dev->rebuild_header = ipsec_mast_rebuild_header; -+ } else -+ dev->rebuild_header = NULL; -+ -+ if (physdev->set_mac_address) { -+ prv->set_mac_address = physdev->set_mac_address; -+ dev->set_mac_address = ipsec_mast_set_mac_address; -+ } else -+ dev->set_mac_address = NULL; -+ -+ if (physdev->header_cache_update) { -+ prv->header_cache_update = physdev->header_cache_update; -+ dev->header_cache_update = ipsec_mast_cache_update; -+ } else -+ dev->header_cache_update = NULL; -+ -+ dev->hard_header_len = physdev->hard_header_len; -+ -+/* prv->neigh_setup = physdev->neigh_setup; */ -+ dev->neigh_setup = ipsec_mast_neigh_setup_dev; -+ dev->mtu = 16260; /* 0xfff0; */ /* dev->mtu; */ -+ prv->mtu = physdev->mtu; -+ -+#ifdef PHYSDEV_TYPE -+ dev->type = physdev->type; /* ARPHRD_MAST; */ -+#endif /* PHYSDEV_TYPE */ -+ -+ dev->addr_len = physdev->addr_len; -+ for (i=0; iaddr_len; i++) { -+ dev->dev_addr[i] = physdev->dev_addr[i]; -+ } -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_mast & DB_MAST_INIT) { -+ printk(KERN_INFO "klips_debug:ipsec_mast_attach: " -+ "physical device %s being attached has HW address: %2x", -+ physdev->name, physdev->dev_addr[0]); -+ for (i=1; i < physdev->addr_len; i++) { -+ printk(":%02x", physdev->dev_addr[i]); -+ } -+ printk("\n"); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ return 0; -+} -+ -+/* -+ * We call the detach routine to detach the ipsec mast from another device. -+ */ -+ -+DEBUG_NO_STATIC int -+ipsec_mast_detach(struct device *dev) -+{ -+ int i; -+ struct ipsecpriv *prv = dev->priv; -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_detach: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_detach: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return -ENODATA; -+ } -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_detach: " -+ "physical device %s being detached from virtual device %s\n", -+ prv->dev ? prv->dev->name : "NULL", -+ dev->name); -+ -+ prv->dev = NULL; -+ prv->hard_start_xmit = NULL; -+ prv->get_stats = NULL; -+ -+ prv->hard_header = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->hard_header = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+ prv->rebuild_header = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->rebuild_header = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+ prv->set_mac_address = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->set_mac_address = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+ prv->header_cache_update = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->header_cache_update = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+#ifdef DETACH_AND_DOWN -+ dev->neigh_setup = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+ dev->hard_header_len = 0; -+#ifdef DETACH_AND_DOWN -+ dev->mtu = 0; -+#endif /* DETACH_AND_DOWN */ -+ prv->mtu = 0; -+ for (i=0; idev_addr[i] = 0; -+ } -+ dev->addr_len = 0; -+#ifdef PHYSDEV_TYPE -+ dev->type = ARPHRD_VOID; /* ARPHRD_MAST; */ -+#endif /* PHYSDEV_TYPE */ -+ -+ return 0; -+} -+ -+/* -+ * We call the clear routine to detach all ipsec masts from other devices. -+ */ -+DEBUG_NO_STATIC int -+ipsec_mast_clear(void) -+{ -+ int i; -+ struct device *ipsecdev = NULL, *prvdev; -+ struct ipsecpriv *prv; -+ char name[9]; -+ int ret; -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_clear: .\n"); -+ -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ sprintf(name, IPSEC_DEV_FORMAT, i); -+ if((ipsecdev = ipsec_dev_get(name)) != NULL) { -+ if((prv = (struct ipsecpriv *)(ipsecdev->priv))) { -+ prvdev = (struct device *)(prv->dev); -+ if(prvdev) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_clear: " -+ "physical device for device %s is %s\n", -+ name, prvdev->name); -+ if((ret = ipsec_mast_detach(ipsecdev))) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_clear: " -+ "error %d detatching device %s from device %s.\n", -+ ret, name, prvdev->name); -+ return ret; -+ } -+ } -+ } -+ } -+ } -+ return 0; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_mast_ioctl(struct device *dev, struct ifreq *ifr, int cmd) -+{ -+ struct ipsecmastconf *cf = (struct ipsecmastconf *)&ifr->ifr_data; -+ struct ipsecpriv *prv = dev->priv; -+ struct device *them; /* physical device */ -+#ifdef CONFIG_IP_ALIAS -+ char *colon; -+ char realphysname[IFNAMSIZ]; -+#endif /* CONFIG_IP_ALIAS */ -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "device not supplied.\n"); -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "tncfg service call #%d for dev=%s\n", -+ cmd, -+ dev->name ? dev->name : "NULL"); -+ switch (cmd) { -+ /* attach a virtual ipsec? device to a physical device */ -+ case IPSEC_SET_DEV: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "calling ipsec_mast_attatch...\n"); -+#ifdef CONFIG_IP_ALIAS -+ /* If this is an IP alias interface, get its real physical name */ -+ strncpy(realphysname, cf->cf_name, IFNAMSIZ); -+ realphysname[IFNAMSIZ-1] = 0; -+ colon = strchr(realphysname, ':'); -+ if (colon) *colon = 0; -+ them = ipsec_dev_get(realphysname); -+#else /* CONFIG_IP_ALIAS */ -+ them = ipsec_dev_get(cf->cf_name); -+#endif /* CONFIG_IP_ALIAS */ -+ -+ if (them == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "physical device %s requested is null\n", -+ cf->cf_name); -+ return -ENXIO; -+ } -+ -+#if 0 -+ if (them->flags & IFF_UP) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "physical device %s requested is not up.\n", -+ cf->cf_name); -+ return -ENXIO; -+ } -+#endif -+ -+ if (prv && prv->dev) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "virtual device is already connected to %s.\n", -+ prv->dev->name ? prv->dev->name : "NULL"); -+ return -EBUSY; -+ } -+ return ipsec_mast_attach(dev, them); -+ -+ case IPSEC_DEL_DEV: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "calling ipsec_mast_detatch.\n"); -+ if (! prv->dev) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "physical device not connected.\n"); -+ return -ENODEV; -+ } -+ return ipsec_mast_detach(dev); -+ -+ case IPSEC_CLR_DEV: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "calling ipsec_mast_clear.\n"); -+ return ipsec_mast_clear(); -+ -+ default: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "unknown command %d.\n", -+ cmd); -+ return -EOPNOTSUPP; -+ } -+} -+ -+int -+ipsec_mast_device_event(struct notifier_block *unused, unsigned long event, void *ptr) -+{ -+ struct device *dev = ptr; -+ struct device *ipsec_dev; -+ struct ipsecpriv *priv; -+ char name[9]; -+ int i; -+ -+ if (dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "dev=NULL for event type %ld.\n", -+ event); -+ return(NOTIFY_DONE); -+ } -+ -+ /* check for loopback devices */ -+ if (dev && (dev->flags & IFF_LOOPBACK)) { -+ return(NOTIFY_DONE); -+ } -+ -+ switch (event) { -+ case NETDEV_DOWN: -+ /* look very carefully at the scope of these compiler -+ directives before changing anything... -- RGB */ -+ -+ case NETDEV_UNREGISTER: -+ switch (event) { -+ case NETDEV_DOWN: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_DOWN dev=%s flags=%x\n", -+ dev->name, -+ dev->flags); -+ if(strncmp(dev->name, "ipsec", strlen("ipsec")) == 0) { -+ printk(KERN_CRIT "IPSEC EVENT: KLIPS device %s shut down.\n", -+ dev->name); -+ } -+ break; -+ case NETDEV_UNREGISTER: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_UNREGISTER dev=%s flags=%x\n", -+ dev->name, -+ dev->flags); -+ break; -+ } -+ -+ /* find the attached physical device and detach it. */ -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ sprintf(name, IPSEC_DEV_FORMAT, i); -+ ipsec_dev = ipsec_dev_get(name); -+ if(ipsec_dev) { -+ priv = (struct ipsecpriv *)(ipsec_dev->priv); -+ if(priv) { -+ ; -+ if(((struct device *)(priv->dev)) == dev) { -+ /* dev_close(ipsec_dev); */ -+ /* return */ ipsec_mast_detach(ipsec_dev); -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "device '%s' has been detached.\n", -+ ipsec_dev->name); -+ break; -+ } -+ } else { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "device '%s' has no private data space!\n", -+ ipsec_dev->name); -+ } -+ } -+ } -+ break; -+ case NETDEV_UP: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_UP dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_REBOOT: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_REBOOT dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_CHANGE: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_CHANGE dev=%s flags=%x\n", -+ dev->name, -+ dev->flags); -+ break; -+ case NETDEV_REGISTER: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_REGISTER dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_CHANGEMTU: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_CHANGEMTU dev=%s to mtu=%d\n", -+ dev->name, -+ dev->mtu); -+ break; -+ case NETDEV_CHANGEADDR: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_CHANGEADDR dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_GOING_DOWN: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_GOING_DOWN dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_CHANGENAME: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_CHANGENAME dev=%s\n", -+ dev->name); -+ break; -+ default: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "event type %ld unrecognised for dev=%s\n", -+ event, -+ dev->name); -+ break; -+ } -+ return NOTIFY_DONE; -+} -+ -+/* -+ * Called when an ipsec mast device is initialized. -+ * The ipsec mast device structure is passed to us. -+ */ -+ -+int -+ipsec_mast_init(struct device *dev) -+{ -+ int i; -+ -+ KLIPS_PRINT(debug_mast, -+ "klips_debug:ipsec_mast_init: " -+ "allocating %lu bytes initialising device: %s\n", -+ (unsigned long) sizeof(struct ipsecpriv), -+ dev->name ? dev->name : "NULL"); -+ -+ /* Add our mast functions to the device */ -+ dev->open = ipsec_mast_open; -+ dev->stop = ipsec_mast_close; -+ dev->hard_start_xmit = ipsec_mast_start_xmit; -+ dev->get_stats = ipsec_mast_get_stats; -+ -+ dev->priv = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL); -+ if (dev->priv == NULL) -+ return -ENOMEM; -+ memset((caddr_t)(dev->priv), 0, sizeof(struct ipsecpriv)); -+ -+ for(i = 0; i < sizeof(zeroes); i++) { -+ ((__u8*)(zeroes))[i] = 0; -+ } -+ -+ dev->set_multicast_list = NULL; -+ dev->do_ioctl = ipsec_mast_ioctl; -+ dev->hard_header = NULL; -+ dev->rebuild_header = NULL; -+ dev->set_mac_address = NULL; -+ dev->header_cache_update= NULL; -+ dev->neigh_setup = ipsec_mast_neigh_setup_dev; -+ dev->hard_header_len = 0; -+ dev->mtu = 0; -+ dev->addr_len = 0; -+ dev->type = ARPHRD_VOID; /* ARPHRD_MAST; */ /* ARPHRD_ETHER; */ -+ dev->tx_queue_len = 10; /* Small queue */ -+ memset((caddr_t)(dev->broadcast),0xFF, ETH_ALEN); /* what if this is not attached to ethernet? */ -+ -+ /* New-style flags. */ -+ dev->flags = IFF_NOARP /* 0 */ /* Petr Novak */; -+ dev_init_buffers(dev); -+ -+ /* We're done. Have I forgotten anything? */ -+ return 0; -+} -+ -+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -+/* Module specific interface (but it links with the rest of IPSEC) */ -+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -+ -+int -+ipsec_mast_probe(struct device *dev) -+{ -+ ipsec_mast_init(dev); -+ return 0; -+} -+ -+int -+ipsec_mast_init_devices(void) -+{ -+ return 0; -+} -+ -+/* void */ -+int -+ipsec_mast_cleanup_devices(void) -+{ -+ int error = 0; -+ int i; -+ char name[10]; -+ struct device *dev_mast; -+ -+ for(i = 0; i < ipsec_mastdevice_count; i++) { -+ sprintf(name, MAST_DEV_FORMAT, i); -+ if((dev_mast = ipsec_dev_get(name)) == NULL) { -+ break; -+ } -+ unregister_netdev(dev_mast); -+ kfree(dev_mast->priv); -+ dev_mast->priv=NULL; -+ } -+ return error; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.3 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.2.4.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.2 2003/06/22 20:06:17 mcr -+ * refactored mast code still had lots of ipsecX junk in it. -+ * -+ * Revision 1.1 2003/02/12 19:31:12 rgb -+ * Refactored from ipsec_tunnel.c -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_md5c.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,448 @@ -+/* -+ * RCSID $Id$ -+ */ -+ -+/* -+ * The rest of the code is derived from MD5C.C by RSADSI. Minor cosmetic -+ * changes to accomodate it in the kernel by ji. -+ */ -+ -+#include -+#include -+ -+#include "openswan/ipsec_md5h.h" -+ -+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm -+ */ -+ -+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -+rights reserved. -+ -+License to copy and use this software is granted provided that it -+is identified as the "RSA Data Security, Inc. MD5 Message-Digest -+Algorithm" in all material mentioning or referencing this software -+or this function. -+ -+License is also granted to make and use derivative works provided -+that such works are identified as "derived from the RSA Data -+Security, Inc. MD5 Message-Digest Algorithm" in all material -+mentioning or referencing the derived work. -+ -+RSA Data Security, Inc. makes no representations concerning either -+the merchantability of this software or the suitability of this -+software for any particular purpose. It is provided "as is" -+without express or implied warranty of any kind. -+ -+These notices must be retained in any copies of any part of this -+documentation and/or software. -+ */ -+ -+/* -+ * Additions by JI -+ * -+ * HAVEMEMCOPY is defined if mem* routines are available -+ * -+ * HAVEHTON is defined if htons() and htonl() can be used -+ * for big/little endian conversions -+ * -+ */ -+ -+#define HAVEMEMCOPY -+#ifdef __LITTLE_ENDIAN -+#define LITTLENDIAN -+#endif -+#ifdef __BIG_ENDIAN -+#define BIGENDIAN -+#endif -+ -+/* Constants for MD5Transform routine. -+ */ -+ -+#define S11 7 -+#define S12 12 -+#define S13 17 -+#define S14 22 -+#define S21 5 -+#define S22 9 -+#define S23 14 -+#define S24 20 -+#define S31 4 -+#define S32 11 -+#define S33 16 -+#define S34 23 -+#define S41 6 -+#define S42 10 -+#define S43 15 -+#define S44 21 -+ -+static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); -+ -+#ifdef LITTLEENDIAN -+#define Encode MD5_memcpy -+#define Decode MD5_memcpy -+#else -+static void Encode PROTO_LIST -+ ((unsigned char *, UINT4 *, unsigned int)); -+static void Decode PROTO_LIST -+ ((UINT4 *, unsigned char *, unsigned int)); -+#endif -+ -+#ifdef HAVEMEMCOPY -+/* no need to include here; defines these */ -+#define MD5_memcpy memcpy -+#define MD5_memset memset -+#else -+#ifdef HAVEBCOPY -+#define MD5_memcpy(_a,_b,_c) bcopy((_b),(_a),(_c)) -+#define MD5_memset(_a,_b,_c) bzero((_a),(_c)) -+#else -+static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); -+static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); -+#endif -+#endif -+static unsigned char PADDING[64] = { -+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -+}; -+ -+/* F, G, H and I are basic MD5 functions. -+ */ -+#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -+#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) -+#define H(x, y, z) ((x) ^ (y) ^ (z)) -+#define I(x, y, z) ((y) ^ ((x) | (~z))) -+ -+/* ROTATE_LEFT rotates x left n bits. -+ */ -+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) -+ -+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. -+Rotation is separate from addition to prevent recomputation. -+ */ -+#define FF(a, b, c, d, x, s, ac) { \ -+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ -+ (a) = ROTATE_LEFT ((a), (s)); \ -+ (a) += (b); \ -+ } -+#define GG(a, b, c, d, x, s, ac) { \ -+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ -+ (a) = ROTATE_LEFT ((a), (s)); \ -+ (a) += (b); \ -+ } -+#define HH(a, b, c, d, x, s, ac) { \ -+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ -+ (a) = ROTATE_LEFT ((a), (s)); \ -+ (a) += (b); \ -+ } -+#define II(a, b, c, d, x, s, ac) { \ -+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ -+ (a) = ROTATE_LEFT ((a), (s)); \ -+ (a) += (b); \ -+ } -+ -+/* -+ * MD5 initialization. Begins an MD5 operation, writing a new context. -+ */ -+void MD5Init(void *vcontext) -+{ -+ MD5_CTX *context = vcontext; -+ -+ context->count[0] = context->count[1] = 0; -+ /* Load magic initialization constants. -+*/ -+ context->state[0] = 0x67452301; -+ context->state[1] = 0xefcdab89; -+ context->state[2] = 0x98badcfe; -+ context->state[3] = 0x10325476; -+} -+ -+/* MD5 block update operation. Continues an MD5 message-digest -+ operation, processing another message block, and updating the -+ context. -+ */ -+void MD5Update (vcontext, input, inputLen) -+ void *vcontext; -+ unsigned char *input; /* input block */ -+ __u32 inputLen; /* length of input block */ -+{ -+ MD5_CTX *context = vcontext; -+ __u32 i; -+ unsigned int index, partLen; -+ -+ /* Compute number of bytes mod 64 */ -+ index = (unsigned int)((context->count[0] >> 3) & 0x3F); -+ -+ /* Update number of bits */ -+ if ((context->count[0] += ((UINT4)inputLen << 3)) -+ < ((UINT4)inputLen << 3)) -+ context->count[1]++; -+ context->count[1] += ((UINT4)inputLen >> 29); -+ -+ partLen = 64 - index; -+ -+ /* Transform as many times as possible. -+*/ -+ if (inputLen >= partLen) { -+ MD5_memcpy -+ ((POINTER)&context->buffer[index], (POINTER)input, partLen); -+ MD5Transform (context->state, context->buffer); -+ -+ for (i = partLen; i + 63 < inputLen; i += 64) -+ MD5Transform (context->state, &input[i]); -+ -+ index = 0; -+ } -+ else -+ i = 0; -+ -+ /* Buffer remaining input */ -+ MD5_memcpy -+ ((POINTER)&context->buffer[index], (POINTER)&input[i], -+ inputLen-i); -+} -+ -+/* MD5 finalization. Ends an MD5 message-digest operation, writing the -+ the message digest and zeroizing the context. -+ */ -+void MD5Final (digest, vcontext) -+unsigned char digest[16]; /* message digest */ -+void *vcontext; /* context */ -+{ -+ MD5_CTX *context = vcontext; -+ unsigned char bits[8]; -+ unsigned int index, padLen; -+ -+ /* Save number of bits */ -+ Encode (bits, context->count, 8); -+ -+ /* Pad out to 56 mod 64. -+*/ -+ index = (unsigned int)((context->count[0] >> 3) & 0x3f); -+ padLen = (index < 56) ? (56 - index) : (120 - index); -+ MD5Update (context, PADDING, padLen); -+ -+ /* Append length (before padding) */ -+ MD5Update (context, bits, 8); -+ -+ if (digest != NULL) /* Bill Simpson's padding */ -+ { -+ /* store state in digest */ -+ Encode (digest, context->state, 16); -+ -+ /* Zeroize sensitive information. -+ */ -+ MD5_memset ((POINTER)context, 0, sizeof (*context)); -+ } -+} -+ -+/* MD5 basic transformation. Transforms state based on block. -+ */ -+static void MD5Transform (state, block) -+UINT4 state[4]; -+unsigned char block[64]; -+{ -+ UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; -+ -+ Decode (x, block, 64); -+ -+ /* Round 1 */ -+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ -+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ -+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ -+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ -+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ -+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ -+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ -+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ -+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ -+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ -+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ -+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ -+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ -+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ -+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ -+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ -+ -+ /* Round 2 */ -+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ -+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ -+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ -+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ -+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ -+ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ -+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ -+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ -+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ -+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ -+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ -+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ -+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ -+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ -+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ -+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ -+ -+ /* Round 3 */ -+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ -+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ -+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ -+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ -+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ -+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ -+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ -+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ -+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ -+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ -+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ -+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ -+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ -+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ -+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ -+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ -+ -+ /* Round 4 */ -+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ -+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ -+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ -+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ -+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ -+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ -+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ -+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ -+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ -+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ -+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ -+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ -+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ -+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ -+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ -+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ -+ -+ state[0] += a; -+ state[1] += b; -+ state[2] += c; -+ state[3] += d; -+ -+ /* Zeroize sensitive information. -+*/ -+ MD5_memset ((POINTER)x, 0, sizeof (x)); -+} -+ -+#ifndef LITTLEENDIAN -+ -+/* Encodes input (UINT4) into output (unsigned char). Assumes len is -+ a multiple of 4. -+ */ -+static void Encode (output, input, len) -+unsigned char *output; -+UINT4 *input; -+unsigned int len; -+{ -+ unsigned int i, j; -+ -+ for (i = 0, j = 0; j < len; i++, j += 4) { -+ output[j] = (unsigned char)(input[i] & 0xff); -+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); -+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); -+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); -+ } -+} -+ -+/* Decodes input (unsigned char) into output (UINT4). Assumes len is -+ a multiple of 4. -+ */ -+static void Decode (output, input, len) -+UINT4 *output; -+unsigned char *input; -+unsigned int len; -+{ -+ unsigned int i, j; -+ -+ for (i = 0, j = 0; j < len; i++, j += 4) -+ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | -+ (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); -+} -+ -+#endif -+ -+#ifndef HAVEMEMCOPY -+#ifndef HAVEBCOPY -+/* Note: Replace "for loop" with standard memcpy if possible. -+ */ -+ -+static void MD5_memcpy (output, input, len) -+POINTER output; -+POINTER input; -+unsigned int len; -+{ -+ unsigned int i; -+ -+ for (i = 0; i < len; i++) -+ -+ output[i] = input[i]; -+} -+ -+/* Note: Replace "for loop" with standard memset if possible. -+ */ -+ -+static void MD5_memset (output, value, len) -+POINTER output; -+int value; -+unsigned int len; -+{ -+ unsigned int i; -+ -+ for (i = 0; i < len; i++) -+ ((char *)output)[i] = (char)value; -+} -+#endif -+#endif -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.8 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.7 2002/09/10 01:45:14 mcr -+ * changed type of MD5_CTX and SHA1_CTX to void * so that -+ * the function prototypes would match, and could be placed -+ * into a pointer to a function. -+ * -+ * Revision 1.6 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.5 2002/04/24 07:36:28 mcr -+ * Moved from ./klips/net/ipsec/ipsec_md5c.c,v -+ * -+ * Revision 1.4 1999/12/13 13:59:12 rgb -+ * Quick fix to argument size to Update bugs. -+ * -+ * Revision 1.3 1999/05/21 18:09:28 henry -+ * unnecessary include causes trouble in 2.2 -+ * -+ * Revision 1.2 1999/04/06 04:54:26 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.1 1998/06/18 21:27:48 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.2 1998/04/23 20:54:02 rgb -+ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when -+ * verified. -+ * -+ * Revision 1.1 1998/04/09 03:06:08 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:04 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.3 1996/11/20 14:48:53 ji -+ * Release update only. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_proc.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1127 @@ -+/* -+ * @(#) /proc file system interface code. -+ * -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs -+ * 2001 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * Split out from ipsec_init.c version 1.70. -+ */ -+ -+char ipsec_proc_c_version[] = "RCSID $Id$"; -+ -+ -+#include -+#include -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include /* struct sockaddr_in */ -+#include -+#include -+#ifdef SPINLOCK -+#ifdef SPINLOCK_23 -+#include /* *lock* */ -+#else /* SPINLOCK_23 */ -+#include /* *lock* */ -+#endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+#include -+#include -+#endif /* NET_21 */ -+#include -+#include -+#ifdef CONFIG_PROC_FS -+#include -+#endif /* CONFIG_PROC_FS */ -+#ifdef NETLINK_SOCK -+#include -+#else -+#include -+#endif -+ -+#include "openswan/radij.h" -+ -+#include "openswan/ipsec_life.h" -+#include "openswan/ipsec_stats.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_xmit.h" -+ -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+#include "openswan/ipcomp.h" -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#include "openswan/ipsec_proto.h" -+ -+#include -+#include -+ -+#ifdef CONFIG_PROC_FS -+ -+#ifdef IPSEC_PROC_SUBDIRS -+static struct proc_dir_entry *proc_net_ipsec_dir = NULL; -+static struct proc_dir_entry *proc_eroute_dir = NULL; -+static struct proc_dir_entry *proc_spi_dir = NULL; -+static struct proc_dir_entry *proc_spigrp_dir = NULL; -+static struct proc_dir_entry *proc_birth_dir = NULL; -+static struct proc_dir_entry *proc_stats_dir = NULL; -+#endif -+ -+struct ipsec_birth_reply ipsec_ipv4_birth_packet; -+struct ipsec_birth_reply ipsec_ipv6_birth_packet; -+ -+#define DECREMENT_UNSIGNED(X, amount) ((amount < (X)) ? (X)-amount : 0) -+ -+extern int ipsec_xform_get_info(char *buffer, char **start, -+ off_t offset, int length IPSEC_PROC_LAST_ARG); -+ -+ -+/* ipsec_snprintf: like snprintf except -+ * - size is signed and a negative value is treated as if it were 0 -+ * - the returned result is never negative -- -+ * an error generates a "?" or null output (depending on space). -+ * (Our callers are too lazy to check for an error return.) -+ * -+ * @param buf String buffer -+ * @param size Size of the string -+ * @param fmt printf string -+ * @param ... Variables to be displayed in fmt -+ * @return int Return code -+ */ -+int ipsec_snprintf(char *buf, ssize_t size, const char *fmt, ...) -+{ -+ va_list args; -+ int i; -+ size_t possize = size < 0? 0 : size; -+ va_start(args, fmt); -+ i = vsnprintf(buf,possize,fmt,args); -+ va_end(args); -+ if (i < 0) { -+ /* create empty output in place of error */ -+ i = 0; -+ if (size > 0) { -+ *buf = '\0'; -+ } -+ } -+ return i; -+} -+ -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_eroute_get_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length IPSEC_PROC_LAST_ARG) -+{ -+ struct wsbuf w = {buffer, length, offset, 0, 0}; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_radij & DB_RJ_DUMPTREES) -+ rj_dumptrees(); /* XXXXXXXXX */ -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_eroute_get_info: " -+ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", -+ buffer, -+ *start, -+ (int)offset, -+ length); -+ -+ spin_lock_bh(&eroute_lock); -+ -+ rj_walktree(rnh, ipsec_rj_walker_procprint, &w); -+/* rj_walktree(mask_rjhead, ipsec_rj_walker_procprint, &w); */ -+ -+ spin_unlock_bh(&eroute_lock); -+ -+ *start = buffer + (offset - w.begin); /* Start of wanted data */ -+ return w.len - (offset - w.begin); -+} -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_spi_get_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length IPSEC_PROC_LAST_ARG) -+{ -+ const int max_content = length > 0? length-1 : 0; -+ int len = 0; -+ off_t begin = 0; -+ int i; -+ struct ipsec_sa *sa_p; -+ char sa[SATOT_BUF]; -+ char buf_s[SUBNETTOA_BUF]; -+ char buf_d[SUBNETTOA_BUF]; -+ size_t sa_len; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_spi_get_info: " -+ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", -+ buffer, -+ *start, -+ (int)offset, -+ length); -+ -+ spin_lock_bh(&tdb_lock); -+ -+ for (i = 0; i < SADB_HASHMOD; i++) { -+ for (sa_p = ipsec_sadb_hash[i]; -+ sa_p; -+ sa_p = sa_p->ips_hnext) { -+ atomic_inc(&sa_p->ips_refcount); -+ sa_len = satot(&sa_p->ips_said, 'x', sa, sizeof(sa)); -+ len += ipsec_snprintf(buffer+len, length-len, "%s ", -+ sa_len ? sa : " (error)"); -+ -+ len += ipsec_snprintf(buffer+len, length-len, "%s%s%s", -+ IPS_XFORM_NAME(sa_p)); -+ -+ len += ipsec_snprintf(buffer+len, length-len, ": dir=%s", -+ (sa_p->ips_flags & EMT_INBOUND) ? -+ "in " : "out"); -+ -+ if(sa_p->ips_addr_s) { -+ addrtoa(((struct sockaddr_in*)(sa_p->ips_addr_s))->sin_addr, -+ 0, buf_s, sizeof(buf_s)); -+ len += ipsec_snprintf(buffer+len, length-len, " src=%s", -+ buf_s); -+ } -+ -+ if((sa_p->ips_said.proto == IPPROTO_IPIP) -+ && (sa_p->ips_flags & SADB_X_SAFLAGS_INFLOW)) { -+ subnettoa(sa_p->ips_flow_s.u.v4.sin_addr, -+ sa_p->ips_mask_s.u.v4.sin_addr, -+ 0, -+ buf_s, -+ sizeof(buf_s)); -+ -+ subnettoa(sa_p->ips_flow_d.u.v4.sin_addr, -+ sa_p->ips_mask_d.u.v4.sin_addr, -+ 0, -+ buf_d, -+ sizeof(buf_d)); -+ -+ len += ipsec_snprintf(buffer+len, length-len, " policy=%s->%s", -+ buf_s, buf_d); -+ } -+ -+ if(sa_p->ips_iv_bits) { -+ int j; -+ len += ipsec_snprintf(buffer+len, length-len, " iv_bits=%dbits iv=0x", -+ sa_p->ips_iv_bits); -+ -+ for(j = 0; j < sa_p->ips_iv_bits / 8; j++) { -+ len += ipsec_snprintf(buffer+len, length-len, "%02x", -+ (__u32)((__u8*)(sa_p->ips_iv))[j]); -+ } -+ } -+ -+ if(sa_p->ips_encalg || sa_p->ips_authalg) { -+ if(sa_p->ips_replaywin) { -+ len += ipsec_snprintf(buffer+len, length-len, " ooowin=%d", -+ sa_p->ips_replaywin); -+ } -+ if(sa_p->ips_errs.ips_replaywin_errs) { -+ len += ipsec_snprintf(buffer+len, length-len, " ooo_errs=%d", -+ sa_p->ips_errs.ips_replaywin_errs); -+ } -+ if(sa_p->ips_replaywin_lastseq) { -+ len += ipsec_snprintf(buffer+len, length-len, " seq=%d", -+ sa_p->ips_replaywin_lastseq); -+ } -+ if(sa_p->ips_replaywin_bitmap) { -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) -+ len += ipsec_snprintf(buffer+len, length-len, " bit=0x%Lx", -+ sa_p->ips_replaywin_bitmap); -+#else -+ len += ipsec_snprintf(buffer+len, length-len, " bit=0x%x%08x", -+ (__u32)(sa_p->ips_replaywin_bitmap >> 32), -+ (__u32)sa_p->ips_replaywin_bitmap); -+#endif -+ } -+ if(sa_p->ips_replaywin_maxdiff) { -+ len += ipsec_snprintf(buffer+len, length-len, " max_seq_diff=%d", -+ sa_p->ips_replaywin_maxdiff); -+ } -+ } -+ if(sa_p->ips_flags & ~EMT_INBOUND) { -+ len += ipsec_snprintf(buffer+len, length-len, " flags=0x%x", -+ sa_p->ips_flags & ~EMT_INBOUND); -+ len += ipsec_snprintf(buffer+len, length-len, "<"); -+ /* flag printing goes here */ -+ len += ipsec_snprintf(buffer+len, length-len, ">"); -+ } -+ if(sa_p->ips_auth_bits) { -+ len += ipsec_snprintf(buffer+len, length-len, " alen=%d", -+ sa_p->ips_auth_bits); -+ } -+ if(sa_p->ips_key_bits_a) { -+ len += ipsec_snprintf(buffer+len, length-len, " aklen=%d", -+ sa_p->ips_key_bits_a); -+ } -+ if(sa_p->ips_errs.ips_auth_errs) { -+ len += ipsec_snprintf(buffer+len, length-len, " auth_errs=%d", -+ sa_p->ips_errs.ips_auth_errs); -+ } -+ if(sa_p->ips_key_bits_e) { -+ len += ipsec_snprintf(buffer+len, length-len, " eklen=%d", -+ sa_p->ips_key_bits_e); -+ } -+ if(sa_p->ips_errs.ips_encsize_errs) { -+ len += ipsec_snprintf(buffer+len, length-len, " encr_size_errs=%d", -+ sa_p->ips_errs.ips_encsize_errs); -+ } -+ if(sa_p->ips_errs.ips_encpad_errs) { -+ len += ipsec_snprintf(buffer+len, length-len, " encr_pad_errs=%d", -+ sa_p->ips_errs.ips_encpad_errs); -+ } -+ -+ len += ipsec_snprintf(buffer+len, length-len, " life(c,s,h)="); -+ -+ len += ipsec_lifetime_format(buffer + len, -+ length - len, -+ "alloc", -+ ipsec_life_countbased, -+ &sa_p->ips_life.ipl_allocations); -+ -+ len += ipsec_lifetime_format(buffer + len, -+ length - len, -+ "bytes", -+ ipsec_life_countbased, -+ &sa_p->ips_life.ipl_bytes); -+ -+ len += ipsec_lifetime_format(buffer + len, -+ length - len, -+ "addtime", -+ ipsec_life_timebased, -+ &sa_p->ips_life.ipl_addtime); -+ -+ len += ipsec_lifetime_format(buffer + len, -+ length - len, -+ "usetime", -+ ipsec_life_timebased, -+ &sa_p->ips_life.ipl_usetime); -+ -+ len += ipsec_lifetime_format(buffer + len, -+ length - len, -+ "packets", -+ ipsec_life_countbased, -+ &sa_p->ips_life.ipl_packets); -+ -+ if(sa_p->ips_life.ipl_usetime.ipl_last) { /* XXX-MCR should be last? */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) -+ len += ipsec_snprintf(buffer+len, length-len, " idle=%Ld", -+ jiffies / HZ - sa_p->ips_life.ipl_usetime.ipl_last); -+#else -+ len += ipsec_snprintf(buffer+len, length-len, " idle=%lu", -+ jiffies / HZ - (unsigned long)sa_p->ips_life.ipl_usetime.ipl_last); -+#endif -+ } -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+ if(sa_p->ips_said.proto == IPPROTO_COMP && -+ (sa_p->ips_comp_ratio_dbytes || -+ sa_p->ips_comp_ratio_cbytes)) { -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) -+ len += ipsec_snprintf(buffer+len, length-len, " ratio=%Ld:%Ld", -+ sa_p->ips_comp_ratio_dbytes, -+ sa_p->ips_comp_ratio_cbytes); -+#else -+ len += ipsec_snprintf(buffer+len, length-len, " ratio=%lu:%lu", -+ (unsigned long)sa_p->ips_comp_ratio_dbytes, -+ (unsigned long)sa_p->ips_comp_ratio_cbytes); -+#endif -+ } -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if(sa_p->ips_natt_type != 0) { -+ char *natttype_name; -+ -+ switch(sa_p->ips_natt_type) -+ { -+ case ESPINUDP_WITH_NON_IKE: -+ natttype_name="nonike"; -+ break; -+ case ESPINUDP_WITH_NON_ESP: -+ natttype_name="nonesp"; -+ break; -+ default: -+ natttype_name = "unknown"; -+ break; -+ } -+ -+ len += ipsec_snprintf(buffer + len, length-len, " natencap=%s", -+ natttype_name); -+ -+ len += ipsec_snprintf(buffer + len, length-len, " natsport=%d", -+ sa_p->ips_natt_sport); -+ -+ len += ipsec_snprintf(buffer + len,length-len, " natdport=%d", -+ sa_p->ips_natt_dport); -+ } -+#endif /* CONFIG_IPSEC_NAT_TRAVERSAL */ -+ -+ len += ipsec_snprintf(buffer + len,length-len, " refcount=%d", -+ atomic_read(&sa_p->ips_refcount)); -+ -+ len += ipsec_snprintf(buffer+len, length-len, " ref=%d", -+ sa_p->ips_ref); -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_xform) { -+ len += ipsec_snprintf(buffer+len, length-len, " reftable=%lu refentry=%lu", -+ (unsigned long)IPsecSAref2table(sa_p->ips_ref), -+ (unsigned long)IPsecSAref2entry(sa_p->ips_ref)); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ len += ipsec_snprintf(buffer+len, length-len, "\n"); -+ -+ atomic_dec(&sa_p->ips_refcount); -+ -+ if (len >= max_content) { -+ /* we've done all that can fit -- stop loops */ -+ len = max_content; /* truncate crap */ -+ goto done_spi_i; -+ } else { -+ const off_t pos = begin + len; /* file position of end of what we've generated */ -+ -+ if (pos <= offset) { -+ /* all is before first interesting character: -+ * discard, but note where we are. -+ */ -+ len = 0; -+ begin = pos; -+ } -+ } -+ } -+ } -+ -+done_spi_i: -+ spin_unlock_bh(&tdb_lock); -+ -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ return len - (offset - begin); -+} -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_spigrp_get_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length IPSEC_PROC_LAST_ARG) -+{ -+ /* Limit of useful snprintf output */ -+ const int max_content = length > 0? length-1 : 0; -+ -+ int len = 0; -+ off_t begin = 0; -+ int i; -+ struct ipsec_sa *sa_p, *sa_p2; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_spigrp_get_info: " -+ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", -+ buffer, -+ *start, -+ (int)offset, -+ length); -+ -+ spin_lock_bh(&tdb_lock); -+ -+ for (i = 0; i < SADB_HASHMOD; i++) { -+ for (sa_p = ipsec_sadb_hash[i]; -+ sa_p != NULL; -+ sa_p = sa_p->ips_hnext) -+ { -+ atomic_inc(&sa_p->ips_refcount); -+ if(sa_p->ips_inext == NULL) { -+ sa_p2 = sa_p; -+ while(sa_p2 != NULL) { -+ atomic_inc(&sa_p2->ips_refcount); -+ sa_len = satot(&sa_p2->ips_said, -+ 'x', sa, sizeof(sa)); -+ -+ len += ipsec_snprintf(buffer+len, length-len, "%s ", -+ sa_len ? sa : " (error)"); -+ atomic_dec(&sa_p2->ips_refcount); -+ sa_p2 = sa_p2->ips_onext; -+ } -+ len += ipsec_snprintf(buffer+len, length-len, "\n"); -+ } -+ -+ atomic_dec(&sa_p->ips_refcount); -+ -+ if (len >= max_content) { -+ /* we've done all that can fit -- stop loops */ -+ len = max_content; /* truncate crap */ -+ goto done_spigrp_i; -+ } else { -+ const off_t pos = begin + len; -+ -+ if (pos <= offset) { -+ /* all is before first interesting character: -+ * discard, but note where we are. -+ */ -+ len = 0; -+ begin = pos; -+ } -+ } -+ } -+ } -+ -+done_spigrp_i: -+ spin_unlock_bh(&tdb_lock); -+ -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ return len - (offset - begin); -+} -+ -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_tncfg_get_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length IPSEC_PROC_LAST_ARG) -+{ -+ /* limit of useful snprintf output */ -+ const int max_content = length > 0? length-1 : 0; -+ int len = 0; -+ off_t begin = 0; -+ int i; -+ char name[9]; -+ struct device *dev, *privdev; -+ struct ipsecpriv *priv; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_tncfg_get_info: " -+ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", -+ buffer, -+ *start, -+ (int)offset, -+ length); -+ -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ ipsec_snprintf(name, (ssize_t) sizeof(name), IPSEC_DEV_FORMAT, i); -+ dev = __ipsec_dev_get(name); -+ if(dev) { -+ priv = (struct ipsecpriv *)(dev->priv); -+ len += ipsec_snprintf(buffer+len, length-len, "%s", -+ dev->name); -+ if(priv) { -+ privdev = (struct device *)(priv->dev); -+ len += ipsec_snprintf(buffer+len, length-len, " -> %s", -+ privdev ? privdev->name : "NULL"); -+ len += ipsec_snprintf(buffer+len, length-len, " mtu=%d(%d) -> %d", -+ dev->mtu, -+ priv->mtu, -+ privdev ? privdev->mtu : 0); -+ } else { -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_tncfg_get_info: device '%s' has no private data space!\n", -+ dev->name); -+ } -+ len += ipsec_snprintf(buffer+len, length-len, "\n"); -+ -+ if (len >= max_content) { -+ /* we've done all that can fit -- stop loop */ -+ len = max_content; /* truncate crap */ -+ break; -+ } else { -+ const off_t pos = begin + len; -+ if (pos <= offset) { -+ len = 0; -+ begin = pos; -+ } -+ } -+ } -+ } -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ len -= (offset - begin); /* Start slop */ -+ if (len > length) -+ len = length; -+ return len; -+} -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_version_get_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length IPSEC_PROC_LAST_ARG) -+{ -+ int len = 0; -+ off_t begin = 0; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_version_get_info: " -+ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", -+ buffer, -+ *start, -+ (int)offset, -+ length); -+ -+ len += ipsec_snprintf(buffer + len,length-len, "Openswan version: %s\n", -+ ipsec_version_code()); -+#if 0 -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_version_get_info: " -+ "ipsec_init version: %s\n", -+ ipsec_init_c_version); -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_version_get_info: " -+ "ipsec_tunnel version: %s\n", -+ ipsec_tunnel_c_version); -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_version_get_info: " -+ "ipsec_netlink version: %s\n", -+ ipsec_netlink_c_version); -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_version_get_info: " -+ "radij_c_version: %s\n", -+ radij_c_version); -+#endif -+ -+ -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ len -= (offset - begin); /* Start slop */ -+ if (len > length) -+ len = length; -+ return len; -+} -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_birth_info(char *page, -+ char **start, -+ off_t offset, -+ int count, -+ int *eof, -+ void *data) -+{ -+ struct ipsec_birth_reply *ibr = (struct ipsec_birth_reply *)data; -+ int len; -+ -+ if(offset >= ibr->packet_template_len) { -+ if(eof) { -+ *eof=1; -+ } -+ return 0; -+ } -+ -+ len = ibr->packet_template_len; -+ len -= offset; -+ if (len > count) -+ len = count; -+ -+ memcpy(page + offset, ibr->packet_template+offset, len); -+ -+ return len; -+} -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_birth_set(struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ struct ipsec_birth_reply *ibr = (struct ipsec_birth_reply *)data; -+ int len; -+ -+ MOD_INC_USE_COUNT; -+ if(count > IPSEC_BIRTH_TEMPLATE_MAXLEN) { -+ len = IPSEC_BIRTH_TEMPLATE_MAXLEN; -+ } else { -+ len = count; -+ } -+ -+ if(copy_from_user(ibr->packet_template, buffer, len)) { -+ MOD_DEC_USE_COUNT; -+ return -EFAULT; -+ } -+ ibr->packet_template_len = len; -+ -+ MOD_DEC_USE_COUNT; -+ -+ return len; -+} -+ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_klipsdebug_get_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length IPSEC_PROC_LAST_ARG) -+{ -+ int len = 0; -+ off_t begin = 0; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_klipsdebug_get_info: " -+ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", -+ buffer, -+ *start, -+ (int)offset, -+ length); -+ -+ len += ipsec_snprintf(buffer+len, length-len, "debug_tunnel=%08x.\n", debug_tunnel); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_xform=%08x.\n", debug_xform); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_eroute=%08x.\n", debug_eroute); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_spi=%08x.\n", debug_spi); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_radij=%08x.\n", debug_radij); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_esp=%08x.\n", debug_esp); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_ah=%08x.\n", debug_ah); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_rcv=%08x.\n", debug_rcv); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_pfkey=%08x.\n", debug_pfkey); -+ -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ len -= (offset - begin); /* Start slop */ -+ if (len > length) -+ len = length; -+ return len; -+} -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_stats_get_int_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length, -+ int *eof, -+ void *data) -+{ -+ -+ const int max_content = length > 0? length-1 : 0; -+ int len = 0; -+ int *thing; -+ -+ thing = (int *)data; -+ -+ len = ipsec_snprintf(buffer+len, length-len, "%08x\n", *thing); -+ -+ if (len >= max_content) -+ len = max_content; /* truncate crap */ -+ -+ *start = buffer + offset; /* Start of wanted data */ -+ return len > offset? len - offset : 0; -+ -+} -+ -+#ifndef PROC_FS_2325 -+struct proc_dir_entry ipsec_eroute = -+{ -+ 0, -+ 12, "ipsec_eroute", -+ S_IFREG | S_IRUGO, 1, 0, 0, 0, -+ &proc_net_inode_operations, -+ ipsec_eroute_get_info, -+ NULL, NULL, NULL, NULL, NULL -+}; -+ -+struct proc_dir_entry ipsec_spi = -+{ -+ 0, -+ 9, "ipsec_spi", -+ S_IFREG | S_IRUGO, 1, 0, 0, 0, -+ &proc_net_inode_operations, -+ ipsec_spi_get_info, -+ NULL, NULL, NULL, NULL, NULL -+}; -+ -+struct proc_dir_entry ipsec_spigrp = -+{ -+ 0, -+ 12, "ipsec_spigrp", -+ S_IFREG | S_IRUGO, 1, 0, 0, 0, -+ &proc_net_inode_operations, -+ ipsec_spigrp_get_info, -+ NULL, NULL, NULL, NULL, NULL -+}; -+ -+struct proc_dir_entry ipsec_tncfg = -+{ -+ 0, -+ 11, "ipsec_tncfg", -+ S_IFREG | S_IRUGO, 1, 0, 0, 0, -+ &proc_net_inode_operations, -+ ipsec_tncfg_get_info, -+ NULL, NULL, NULL, NULL, NULL -+}; -+ -+struct proc_dir_entry ipsec_version = -+{ -+ 0, -+ 13, "ipsec_version", -+ S_IFREG | S_IRUGO, 1, 0, 0, 0, -+ &proc_net_inode_operations, -+ ipsec_version_get_info, -+ NULL, NULL, NULL, NULL, NULL -+}; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+struct proc_dir_entry ipsec_klipsdebug = -+{ -+ 0, -+ 16, "ipsec_klipsdebug", -+ S_IFREG | S_IRUGO, 1, 0, 0, 0, -+ &proc_net_inode_operations, -+ ipsec_klipsdebug_get_info, -+ NULL, NULL, NULL, NULL, NULL -+}; -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif /* !PROC_FS_2325 */ -+#endif /* CONFIG_PROC_FS */ -+ -+#if defined(PROC_FS_2325) -+struct ipsec_proc_list { -+ char *name; -+ struct proc_dir_entry **parent; -+ struct proc_dir_entry **dir; -+ read_proc_t *readthing; -+ write_proc_t *writething; -+ void *data; -+}; -+static struct ipsec_proc_list proc_items[]={ -+#ifdef CONFIG_IPSEC_DEBUG -+ {"klipsdebug", &proc_net_ipsec_dir, NULL, ipsec_klipsdebug_get_info, NULL, NULL}, -+#endif -+ {"eroute", &proc_net_ipsec_dir, &proc_eroute_dir, NULL, NULL, NULL}, -+ {"all", &proc_eroute_dir, NULL, ipsec_eroute_get_info, NULL, NULL}, -+ {"spi", &proc_net_ipsec_dir, &proc_spi_dir, NULL, NULL, NULL}, -+ {"all", &proc_spi_dir, NULL, ipsec_spi_get_info, NULL, NULL}, -+ {"spigrp", &proc_net_ipsec_dir, &proc_spigrp_dir, NULL, NULL, NULL}, -+ {"all", &proc_spigrp_dir, NULL, ipsec_spigrp_get_info, NULL, NULL}, -+ {"birth", &proc_net_ipsec_dir, &proc_birth_dir, NULL, NULL, NULL}, -+ {"ipv4", &proc_birth_dir, NULL, ipsec_birth_info, ipsec_birth_set, (void *)&ipsec_ipv4_birth_packet}, -+ {"ipv6", &proc_birth_dir, NULL, ipsec_birth_info, ipsec_birth_set, (void *)&ipsec_ipv6_birth_packet}, -+ {"tncfg", &proc_net_ipsec_dir, NULL, ipsec_tncfg_get_info, NULL, NULL}, -+ {"xforms", &proc_net_ipsec_dir, NULL, ipsec_xform_get_info, NULL, NULL}, -+ {"stats", &proc_net_ipsec_dir, &proc_stats_dir, NULL, NULL, NULL}, -+ {"trap_count", &proc_stats_dir, NULL, ipsec_stats_get_int_info, NULL, &ipsec_xmit_trap_count}, -+ {"trap_sendcount", &proc_stats_dir, NULL, ipsec_stats_get_int_info, NULL, &ipsec_xmit_trap_sendcount}, -+ {"version", &proc_net_ipsec_dir, NULL, ipsec_version_get_info, NULL, NULL}, -+ {NULL, NULL, NULL, NULL, NULL, NULL} -+}; -+#endif -+ -+int -+ipsec_proc_init() -+{ -+ int error = 0; -+#ifdef IPSEC_PROC_SUBDIRS -+ struct proc_dir_entry *item; -+#endif -+ -+ /* -+ * just complain because pluto won't run without /proc! -+ */ -+#ifndef CONFIG_PROC_FS -+#error You must have PROC_FS built in to use KLIPS -+#endif -+ -+ /* for 2.0 kernels */ -+#if !defined(PROC_FS_2325) && !defined(PROC_FS_21) -+ error |= proc_register_dynamic(&proc_net, &ipsec_eroute); -+ error |= proc_register_dynamic(&proc_net, &ipsec_spi); -+ error |= proc_register_dynamic(&proc_net, &ipsec_spigrp); -+ error |= proc_register_dynamic(&proc_net, &ipsec_tncfg); -+ error |= proc_register_dynamic(&proc_net, &ipsec_version); -+#ifdef CONFIG_IPSEC_DEBUG -+ error |= proc_register_dynamic(&proc_net, &ipsec_klipsdebug); -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif -+ -+ /* for 2.2 kernels */ -+#if !defined(PROC_FS_2325) && defined(PROC_FS_21) -+ error |= proc_register(proc_net, &ipsec_eroute); -+ error |= proc_register(proc_net, &ipsec_spi); -+ error |= proc_register(proc_net, &ipsec_spigrp); -+ error |= proc_register(proc_net, &ipsec_tncfg); -+ error |= proc_register(proc_net, &ipsec_version); -+#ifdef CONFIG_IPSEC_DEBUG -+ error |= proc_register(proc_net, &ipsec_klipsdebug); -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif -+ -+ /* for 2.4 kernels */ -+#if defined(PROC_FS_2325) -+ /* create /proc/net/ipsec */ -+ -+ /* zero these out before we initialize /proc/net/ipsec/birth/stuff */ -+ memset(&ipsec_ipv4_birth_packet, 0, sizeof(struct ipsec_birth_reply)); -+ memset(&ipsec_ipv6_birth_packet, 0, sizeof(struct ipsec_birth_reply)); -+ -+ proc_net_ipsec_dir = proc_mkdir("ipsec", proc_net); -+ if(proc_net_ipsec_dir == NULL) { -+ /* no point in continuing */ -+ return 1; -+ } -+ -+ { -+ struct ipsec_proc_list *it; -+ -+ it=proc_items; -+ while(it->name!=NULL) { -+ if(it->dir) { -+ /* make a dir instead */ -+ item = proc_mkdir(it->name, *it->parent); -+ *it->dir = item; -+ } else { -+ item = create_proc_entry(it->name, 0400, *it->parent); -+ } -+ if(item) { -+ item->read_proc = it->readthing; -+ item->write_proc = it->writething; -+ item->data = it->data; -+#ifdef MODULE -+ item->owner = THIS_MODULE; -+#endif -+ } else { -+ error |= 1; -+ } -+ it++; -+ } -+ } -+ -+ /* now create some symlinks to provide compatibility */ -+ proc_symlink("ipsec_eroute", proc_net, "ipsec/eroute/all"); -+ proc_symlink("ipsec_spi", proc_net, "ipsec/spi/all"); -+ proc_symlink("ipsec_spigrp", proc_net, "ipsec/spigrp/all"); -+ proc_symlink("ipsec_tncfg", proc_net, "ipsec/tncfg"); -+ proc_symlink("ipsec_version",proc_net, "ipsec/version"); -+ proc_symlink("ipsec_klipsdebug",proc_net,"ipsec/klipsdebug"); -+ -+#endif /* !PROC_FS_2325 */ -+ -+ return error; -+} -+ -+void -+ipsec_proc_cleanup() -+{ -+ -+ /* for 2.0 and 2.2 kernels */ -+#if !defined(PROC_FS_2325) -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (proc_net_unregister(ipsec_klipsdebug.low_ino) != 0) -+ printk("klips_debug:ipsec_cleanup: " -+ "cannot unregister /proc/net/ipsec_klipsdebug\n"); -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ if (proc_net_unregister(ipsec_version.low_ino) != 0) -+ printk("klips_debug:ipsec_cleanup: " -+ "cannot unregister /proc/net/ipsec_version\n"); -+ if (proc_net_unregister(ipsec_eroute.low_ino) != 0) -+ printk("klips_debug:ipsec_cleanup: " -+ "cannot unregister /proc/net/ipsec_eroute\n"); -+ if (proc_net_unregister(ipsec_spi.low_ino) != 0) -+ printk("klips_debug:ipsec_cleanup: " -+ "cannot unregister /proc/net/ipsec_spi\n"); -+ if (proc_net_unregister(ipsec_spigrp.low_ino) != 0) -+ printk("klips_debug:ipsec_cleanup: " -+ "cannot unregister /proc/net/ipsec_spigrp\n"); -+ if (proc_net_unregister(ipsec_tncfg.low_ino) != 0) -+ printk("klips_debug:ipsec_cleanup: " -+ "cannot unregister /proc/net/ipsec_tncfg\n"); -+#endif -+ -+ /* for 2.4 kernels */ -+#if defined(PROC_FS_2325) -+ { -+ struct ipsec_proc_list *it; -+ -+ /* find end of list */ -+ it=proc_items; -+ while(it->name!=NULL) { -+ it++; -+ } -+ it--; -+ -+ do { -+ remove_proc_entry(it->name, *it->parent); -+ it--; -+ } while(it > proc_items); -+ } -+ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ remove_proc_entry("ipsec_klipsdebug", proc_net); -+#endif /* CONFIG_IPSEC_DEBUG */ -+ remove_proc_entry("ipsec_eroute", proc_net); -+ remove_proc_entry("ipsec_spi", proc_net); -+ remove_proc_entry("ipsec_spigrp", proc_net); -+ remove_proc_entry("ipsec_tncfg", proc_net); -+ remove_proc_entry("ipsec_version", proc_net); -+ remove_proc_entry("ipsec", proc_net); -+#endif /* 2.4 kernel */ -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.30 2004/04/25 21:23:11 ken -+ * Pull in dhr's changes from FreeS/WAN 2.06 -+ * -+ * Revision 1.29 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.28 2004/03/28 20:29:58 paul -+ * ssize_t, not ssized_t -+ * -+ * Revision 1.27 2004/03/28 20:27:20 paul -+ * Included tested and confirmed fixes mcr made and dhr verified for -+ * snprint statements. Changed one other snprintf to use ipsec_snprintf -+ * so it wouldnt break compatibility with 2.0/2.2 kernels. Verified with -+ * dhr. (thanks dhr!) -+ * -+ * Revision 1.26 2004/02/09 22:07:06 mcr -+ * added information about nat-traversal setting to spi-output. -+ * -+ * Revision 1.25.4.1 2004/04/05 04:30:46 mcr -+ * patches for alg-branch to compile/work with 2.x openswan -+ * -+ * Revision 1.25 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.24.4.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.24 2003/06/20 01:42:21 mcr -+ * added counters to measure how many ACQUIREs we send to pluto, -+ * and how many are successfully sent. -+ * -+ * Revision 1.23 2003/04/03 17:38:09 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * -+ * Revision 1.22 2002/09/20 15:40:57 rgb -+ * Renamed saref macros for consistency and brevity. -+ * -+ * Revision 1.21 2002/09/20 05:01:35 rgb -+ * Print ref and reftable, refentry seperately. -+ * -+ * Revision 1.20 2002/09/19 02:35:39 mcr -+ * do not define structures needed by /proc/net/ipsec/ if we -+ * aren't going create that directory. -+ * -+ * Revision 1.19 2002/09/10 01:43:25 mcr -+ * fixed problem in /-* comment. -+ * -+ * Revision 1.18 2002/09/03 16:22:11 mcr -+ * fixed initialization of birth/stuff values - some simple -+ * screw ups in the code. -+ * removed debugging that was left in by mistake. -+ * -+ * Revision 1.17 2002/09/02 17:54:53 mcr -+ * changed how the table driven /proc entries are created so that -+ * making subdirs is now explicit rather than implicit. -+ * -+ * Revision 1.16 2002/08/30 01:23:37 mcr -+ * reorganized /proc creating code to clear up ifdefs, -+ * make the 2.4 code table driven, and put things into -+ * /proc/net/ipsec subdir. Symlinks are left for compatibility. -+ * -+ * Revision 1.15 2002/08/13 19:01:25 mcr -+ * patches from kenb to permit compilation of FreeSWAN on ia64. -+ * des library patched to use proper DES_LONG type for ia64. -+ * -+ * Revision 1.14 2002/07/26 08:48:31 rgb -+ * Added SA ref table code. -+ * -+ * Revision 1.13 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.12 2002/05/27 18:56:07 rgb -+ * Convert to dynamic ipsec device allocation. -+ * -+ * Revision 1.11 2002/05/23 07:14:50 rgb -+ * Added refcount code. -+ * Cleaned up %p variants to 0p%p for test suite cleanup. -+ * Convert "usecount" to "refcount" to remove ambiguity. -+ * -+ * Revision 1.10 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.9 2002/04/24 07:36:28 mcr -+ * Moved from ./klips/net/ipsec/ipsec_proc.c,v -+ * -+ * Revision 1.8 2002/01/29 17:17:55 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.7 2002/01/29 04:00:52 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.6 2002/01/29 02:13:17 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.5 2002/01/12 02:54:30 mcr -+ * beginnings of /proc/net/ipsec dir. -+ * -+ * Revision 1.4 2001/12/11 02:21:05 rgb -+ * Don't include module version here, fixing 2.2 compile bug. -+ * -+ * Revision 1.3 2001/12/05 07:19:44 rgb -+ * Fixed extraneous #include "version.c" bug causing modular KLIPS failure. -+ * -+ * Revision 1.2 2001/11/26 09:16:14 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.74 2001/11/22 05:44:11 henry -+ * new version stuff -+ * -+ * Revision 1.1.2.1 2001/09/25 02:19:40 mcr -+ * /proc manipulation code moved to new ipsec_proc.c -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_radij.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,869 @@ -+/* -+ * Interface between the IPSEC code and the radix (radij) tree code -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#include -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, struct net_device_stats and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* 23_SPINLOCK */ -+# include /* *lock* */ -+# endif /* 23_SPINLOCK */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+#endif -+#include -+#include -+ -+#include "openswan/ipsec_eroute.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_tunnel.h" /* struct ipsecpriv */ -+#include "openswan/ipsec_xform.h" -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_radij = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+struct radij_node_head *rnh = NULL; -+#ifdef SPINLOCK -+spinlock_t eroute_lock = SPIN_LOCK_UNLOCKED; -+#else /* SPINLOCK */ -+spinlock_t eroute_lock; -+#endif /* SPINLOCK */ -+ -+int -+ipsec_radijinit(void) -+{ -+ maj_keylen = sizeof (struct sockaddr_encap); -+ -+ rj_init(); -+ -+ if (rj_inithead((void **)&rnh, /*16*/offsetof(struct sockaddr_encap, sen_type) * sizeof(__u8)) == 0) /* 16 is bit offset of sen_type */ -+ return -1; -+ return 0; -+} -+ -+int -+ipsec_radijcleanup(void) -+{ -+ int error; -+ -+ spin_lock_bh(&eroute_lock); -+ -+ error = radijcleanup(); -+ -+ spin_unlock_bh(&eroute_lock); -+ -+ return error; -+} -+ -+int -+ipsec_cleareroutes(void) -+{ -+ int error; -+ -+ spin_lock_bh(&eroute_lock); -+ -+ error = radijcleartree(); -+ -+ spin_unlock_bh(&eroute_lock); -+ -+ return error; -+} -+ -+int -+ipsec_breakroute(struct sockaddr_encap *eaddr, -+ struct sockaddr_encap *emask, -+ struct sk_buff **first, -+ struct sk_buff **last) -+{ -+ struct eroute *ro; -+ struct radij_node *rn; -+ int error; -+#ifdef CONFIG_IPSEC_DEBUG -+ -+ if (debug_eroute) { -+ char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; -+ subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2)); -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_breakroute: " -+ "attempting to delete eroute for %s:%d->%s:%d %d\n", -+ buf1, ntohs(eaddr->sen_sport), -+ buf2, ntohs(eaddr->sen_dport), eaddr->sen_proto); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ spin_lock_bh(&eroute_lock); -+ -+ if ((error = rj_delete(eaddr, emask, rnh, &rn)) != 0) { -+ spin_unlock_bh(&eroute_lock); -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_breakroute: " -+ "node not found, eroute delete failed.\n"); -+ return error; -+ } -+ -+ spin_unlock_bh(&eroute_lock); -+ -+ ro = (struct eroute *)rn; -+ -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_breakroute: " -+ "deleted eroute=0p%p, ident=0p%p->0p%p, first=0p%p, last=0p%p\n", -+ ro, -+ ro->er_ident_s.data, -+ ro->er_ident_d.data, -+ ro->er_first, -+ ro->er_last); -+ -+ if (ro->er_ident_s.data != NULL) { -+ kfree(ro->er_ident_s.data); -+ } -+ if (ro->er_ident_d.data != NULL) { -+ kfree(ro->er_ident_d.data); -+ } -+ if (ro->er_first != NULL) { -+#if 0 -+ struct net_device_stats *stats = (struct net_device_stats *) &(((struct ipsecpriv *)(ro->er_first->dev->priv))->mystats); -+ stats->tx_dropped--; -+#endif -+ *first = ro->er_first; -+ } -+ if (ro->er_last != NULL) { -+#if 0 -+ struct net_device_stats *stats = (struct net_device_stats *) &(((struct ipsecpriv *)(ro->er_last->dev->priv))->mystats); -+ stats->tx_dropped--; -+#endif -+ *last = ro->er_last; -+ } -+ -+ if (rn->rj_flags & (RJF_ACTIVE | RJF_ROOT)) -+ panic ("ipsec_breakroute RMT_DELEROUTE root or active node\n"); -+ memset((caddr_t)rn, 0, sizeof (struct eroute)); -+ kfree(rn); -+ -+ return 0; -+} -+ -+int -+ipsec_makeroute(struct sockaddr_encap *eaddr, -+ struct sockaddr_encap *emask, -+ ip_said said, -+ uint32_t pid, -+ struct sk_buff *skb, -+ struct ident *ident_s, -+ struct ident *ident_d) -+{ -+ struct eroute *retrt; -+ int error; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ -+ if (debug_eroute) { -+ -+ { -+ char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; -+ -+ subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2)); -+ sa_len = satot(&said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_makeroute: " -+ "attempting to allocate %lu bytes to insert eroute for %s->%s, SA: %s, PID:%d, skb=0p%p, ident:%s->%s\n", -+ (unsigned long) sizeof(struct eroute), -+ buf1, -+ buf2, -+ sa_len ? sa : " (error)", -+ pid, -+ skb, -+ (ident_s ? (ident_s->data ? ident_s->data : "NULL") : "NULL"), -+ (ident_d ? (ident_d->data ? ident_d->data : "NULL") : "NULL")); -+ } -+ { -+ char buf1[sizeof(struct sockaddr_encap)*2 + 1], -+ buf2[sizeof(struct sockaddr_encap)*2 + 1]; -+ int i; -+ unsigned char *b1 = buf1, -+ *b2 = buf2, -+ *ea = (unsigned char *)eaddr, -+ *em = (unsigned char *)emask; -+ -+ -+ for (i=0; ier_eaddr = *eaddr; -+ retrt->er_emask = *emask; -+ retrt->er_said = said; -+ retrt->er_pid = pid; -+ retrt->er_count = 0; -+ retrt->er_lasttime = jiffies/HZ; -+ rd_key((&(retrt->er_rjt))) = &(retrt->er_eaddr); -+ -+ if (ident_s && ident_s->type != SADB_IDENTTYPE_RESERVED) { -+ int data_len = ident_s->len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); -+ -+ retrt->er_ident_s.type = ident_s->type; -+ retrt->er_ident_s.id = ident_s->id; -+ retrt->er_ident_s.len = ident_s->len; -+ if(data_len) { -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_makeroute: " -+ "attempting to allocate %u bytes for ident_s.\n", -+ data_len); -+ if(!(retrt->er_ident_s.data = kmalloc(data_len, GFP_KERNEL))) { -+ kfree(retrt); -+ printk("klips_error:ipsec_makeroute: not able to allocate kernel memory (%d)\n", data_len); -+ return ENOMEM; -+ } -+ memcpy(retrt->er_ident_s.data, ident_s->data, data_len); -+ } else { -+ retrt->er_ident_s.data = NULL; -+ } -+ } -+ -+ if (ident_d && ident_d->type != SADB_IDENTTYPE_RESERVED) { -+ int data_len = ident_d->len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); -+ -+ retrt->er_ident_d.type = ident_d->type; -+ retrt->er_ident_d.id = ident_d->id; -+ retrt->er_ident_d.len = ident_d->len; -+ if(data_len) { -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_makeroute: " -+ "attempting to allocate %u bytes for ident_d.\n", -+ data_len); -+ if(!(retrt->er_ident_d.data = kmalloc(data_len, GFP_KERNEL))) { -+ if (retrt->er_ident_s.data) -+ kfree(retrt->er_ident_s.data); -+ kfree(retrt); -+ printk("klips_error:ipsec_makeroute: not able to allocate kernel memory (%d)\n", data_len); -+ return ENOMEM; -+ } -+ memcpy(retrt->er_ident_d.data, ident_d->data, data_len); -+ } else { -+ retrt->er_ident_d.data = NULL; -+ } -+ } -+ retrt->er_first = skb; -+ retrt->er_last = NULL; -+ -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_makeroute: " -+ "calling rj_addroute now\n"); -+ -+ spin_lock_bh(&eroute_lock); -+ -+ error = rj_addroute(&(retrt->er_eaddr), &(retrt->er_emask), -+ rnh, retrt->er_rjt.rd_nodes); -+ -+ spin_unlock_bh(&eroute_lock); -+ -+ if(error) { -+ sa_len = satot(&said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_makeroute: " -+ "rj_addroute not able to insert eroute for SA:%s (error:%d)\n", -+ sa_len ? sa : " (error)", error); -+ if (retrt->er_ident_s.data) -+ kfree(retrt->er_ident_s.data); -+ if (retrt->er_ident_d.data) -+ kfree(retrt->er_ident_d.data); -+ -+ kfree(retrt); -+ -+ return error; -+ } -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_eroute) { -+ char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; -+/* -+ subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2)); -+*/ -+ subnettoa(rd_key((&(retrt->er_rjt)))->sen_ip_src, rd_mask((&(retrt->er_rjt)))->sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(rd_key((&(retrt->er_rjt)))->sen_ip_dst, rd_mask((&(retrt->er_rjt)))->sen_ip_dst, 0, buf2, sizeof(buf2)); -+ sa_len = satot(&retrt->er_said, 0, sa, sizeof(sa)); -+ -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_makeroute: " -+ "pid=%05d " -+ "count=%10d " -+ "lasttime=%6d " -+ "%-18s -> %-18s => %s\n", -+ retrt->er_pid, -+ retrt->er_count, -+ (int)(jiffies/HZ - retrt->er_lasttime), -+ buf1, -+ buf2, -+ sa_len ? sa : " (error)"); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_makeroute: " -+ "succeeded.\n"); -+ return 0; -+} -+ -+struct eroute * -+ipsec_findroute(struct sockaddr_encap *eaddr) -+{ -+ struct radij_node *rn; -+#ifdef CONFIG_IPSEC_DEBUG -+ char buf1[ADDRTOA_BUF], buf2[ADDRTOA_BUF]; -+ -+ if (debug_radij & DB_RJ_FINDROUTE) { -+ addrtoa(eaddr->sen_ip_src, 0, buf1, sizeof(buf1)); -+ addrtoa(eaddr->sen_ip_dst, 0, buf2, sizeof(buf2)); -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_findroute: " -+ "%s:%d->%s:%d %d\n", -+ buf1, ntohs(eaddr->sen_sport), -+ buf2, ntohs(eaddr->sen_dport), -+ eaddr->sen_proto); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ rn = rj_match((caddr_t)eaddr, rnh); -+ if(rn) { -+ KLIPS_PRINT(debug_eroute && sysctl_ipsec_debug_verbose, -+ "klips_debug:ipsec_findroute: " -+ "found, points to proto=%d, spi=%x, dst=%x.\n", -+ ((struct eroute*)rn)->er_said.proto, -+ ntohl(((struct eroute*)rn)->er_said.spi), -+ ntohl(((struct eroute*)rn)->er_said.dst.u.v4.sin_addr.s_addr)); -+ } -+ return (struct eroute *)rn; -+} -+ -+#ifdef CONFIG_PROC_FS -+/** ipsec_rj_walker_procprint: print one line of eroute table output. -+ * -+ * Theoretical BUG: if w->length is less than the length -+ * of some line we should produce, that line will never -+ * be finished. In effect, the "file" will stop part way -+ * through that line. -+ */ -+int -+ipsec_rj_walker_procprint(struct radij_node *rn, void *w0) -+{ -+ struct eroute *ro = (struct eroute *)rn; -+ struct rjtentry *rd = (struct rjtentry *)rn; -+ struct wsbuf *w = (struct wsbuf *)w0; -+ char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; -+ char buf3[16]; -+ char sa[SATOT_BUF]; -+ size_t sa_len, buf_len; -+ struct sockaddr_encap *key, *mask; -+ -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:ipsec_rj_walker_procprint: " -+ "rn=0p%p, w0=0p%p\n", -+ rn, -+ w0); -+ if (rn->rj_b >= 0) { -+ return 0; -+ } -+ -+ key = rd_key(rd); -+ mask = rd_mask(rd); -+ -+ if (key == NULL || mask == NULL) { -+ return 0; -+ } -+ -+ buf_len = subnettoa(key->sen_ip_src, mask->sen_ip_src, 0, buf1, sizeof(buf1)); -+ if(key->sen_sport != 0) { -+ sprintf(buf1+buf_len-1, ":%d", ntohs(key->sen_sport)); -+ } -+ -+ buf_len = subnettoa(key->sen_ip_dst, mask->sen_ip_dst, 0, buf2, sizeof(buf2)); -+ if(key->sen_dport != 0) { -+ sprintf(buf2+buf_len-1, ":%d", ntohs(key->sen_dport)); -+ } -+ -+ buf3[0]='\0'; -+ if(key->sen_proto != 0) { -+ sprintf(buf3, ":%d", key->sen_proto); -+ } -+ -+ sa_len = satot(&ro->er_said, 'x', sa, sizeof(sa)); -+ w->len += ipsec_snprintf(w->buffer + w->len, -+ w->length - w->len, -+ "%-10d " -+ "%-18s -> %-18s => %s%s\n", -+ ro->er_count, -+ buf1, -+ buf2, -+ sa_len ? sa : " (error)", -+ buf3); -+ -+ { -+ /* snprintf can only fill the last character with NUL -+ * so the maximum useful character is w->length-1. -+ * However, if w->length == 0, we cannot go back. -+ * (w->length surely cannot be negative.) -+ */ -+ int max_content = w->length > 0? w->length-1 : 0; -+ -+ if (w->len >= max_content) { -+ /* we've done all that can fit -- stop treewalking */ -+ w->len = max_content; /* truncate crap */ -+ return -ENOBUFS; -+ } else { -+ const off_t pos = w->begin + w->len; /* file position of end of what we've generated */ -+ -+ if (pos <= w->offset) { -+ /* all is before first interesting character: -+ * discard, but note where we are. -+ */ -+ w->len = 0; -+ w->begin = pos; -+ } -+ return 0; -+ } -+ } -+} -+#endif /* CONFIG_PROC_FS */ -+ -+int -+ipsec_rj_walker_delete(struct radij_node *rn, void *w0) -+{ -+ struct eroute *ro; -+ struct rjtentry *rd = (struct rjtentry *)rn; -+ struct radij_node *rn2; -+ int error; -+ struct sockaddr_encap *key, *mask; -+ -+ key = rd_key(rd); -+ mask = rd_mask(rd); -+ -+ if(!key || !mask) { -+ return -ENODATA; -+ } -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_radij) { -+ char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; -+ subnettoa(key->sen_ip_src, mask->sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(key->sen_ip_dst, mask->sen_ip_dst, 0, buf2, sizeof(buf2)); -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:ipsec_rj_walker_delete: " -+ "deleting: %s -> %s\n", -+ buf1, -+ buf2); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ if((error = rj_delete(key, mask, rnh, &rn2))) { -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:ipsec_rj_walker_delete: " -+ "rj_delete failed with error=%d.\n", error); -+ return error; -+ } -+ -+ if(rn2 != rn) { -+ printk("klips_debug:ipsec_rj_walker_delete: " -+ "tried to delete a different node?!? This should never happen!\n"); -+ } -+ -+ ro = (struct eroute *)rn; -+ -+ if (ro->er_ident_s.data) -+ kfree(ro->er_ident_s.data); -+ if (ro->er_ident_d.data) -+ kfree(ro->er_ident_d.data); -+ -+ memset((caddr_t)rn, 0, sizeof (struct eroute)); -+ kfree(rn); -+ -+ return 0; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.70 2004/04/25 21:10:52 ken -+ * Pull in dhr's changes from FreeS/WAN 2.06 -+ * -+ * Revision 1.69 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.68 2004/03/28 20:27:20 paul -+ * Included tested and confirmed fixes mcr made and dhr verified for -+ * snprint statements. Changed one other snprintf to use ipsec_snprintf -+ * so it wouldnt break compatibility with 2.0/2.2 kernels. Verified with -+ * dhr. (thanks dhr!) -+ * -+ * Revision 1.67.4.1 2004/04/05 04:30:46 mcr -+ * patches for alg-branch to compile/work with 2.x openswan -+ * -+ * Revision 1.67 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.66.24.2 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.66.24.1 2003/09/21 13:59:56 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.66 2002/10/12 23:11:53 dhr -+ * -+ * [KenB + DHR] more 64-bit cleanup -+ * -+ * Revision 1.65 2002/09/20 05:01:40 rgb -+ * Added memory allocation debugging. -+ * -+ * Revision 1.64 2002/05/31 01:46:05 mcr -+ * added && sysctl_ipsec_debug_verbose verbose to ipsec_findroute -+ * as requested in PR#14. -+ * -+ * Revision 1.63 2002/05/23 07:14:11 rgb -+ * Cleaned up %p variants to 0p%p for test suite cleanup. -+ * -+ * Revision 1.62 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.61 2002/04/24 07:36:29 mcr -+ * Moved from ./klips/net/ipsec/ipsec_radij.c,v -+ * -+ * Revision 1.60 2002/02/19 23:59:45 rgb -+ * Removed redundant compiler directives. -+ * -+ * Revision 1.59 2002/02/06 04:13:47 mcr -+ * missing #ifdef CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.58 2002/01/29 17:17:56 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.57 2002/01/29 04:00:52 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.56 2002/01/29 02:13:17 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.55 2001/11/26 09:23:48 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.53.2.1 2001/09/25 02:26:32 mcr -+ * headers adjusted for new usage. -+ * -+ * Revision 1.54 2001/10/18 04:45:20 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.53 2001/09/19 17:19:40 rgb -+ * Debug output bugfix for NetCelo's PF_KEY ident patch. -+ * -+ * Revision 1.52 2001/09/19 16:33:37 rgb -+ * Temporarily disable ident fields to /proc/net/ipsec_eroute. -+ * -+ * Revision 1.51 2001/09/15 16:24:04 rgb -+ * Re-inject first and last HOLD packet when an eroute REPLACE is done. -+ * -+ * Revision 1.50 2001/09/14 16:58:36 rgb -+ * Added support for storing the first and last packets through a HOLD. -+ * -+ * Revision 1.49 2001/09/08 21:13:32 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.48 2001/06/15 04:12:56 rgb -+ * Fixed kernel memory allocation error return code polarity bug. -+ * -+ * Revision 1.47 2001/06/14 19:35:09 rgb -+ * Update copyright date. -+ * -+ * Revision 1.46 2001/06/08 08:47:18 rgb -+ * Fixed for debug disabled. -+ * -+ * Revision 1.45 2001/05/27 06:12:11 rgb -+ * Added structures for pid, packet count and last access time to eroute. -+ * Added packet count to beginning of /proc/net/ipsec_eroute. -+ * -+ * Revision 1.44 2001/05/03 19:41:01 rgb -+ * Initialise error return variable. -+ * Use more appropriate return value for ipsec_rj_walker_delete(). -+ * -+ * Revision 1.43 2001/02/27 22:24:54 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.42 2001/02/27 06:21:57 rgb -+ * Added findroute success instrumentation. -+ * -+ * Revision 1.41 2000/11/06 04:32:08 rgb -+ * Ditched spin_lock_irqsave in favour of spin_lock_bh. -+ * -+ * Revision 1.40 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.39 2000/08/30 05:25:20 rgb -+ * Correct debug text in ipsec_breakroute() from incorrect -+ * "ipsec_callback". -+ * -+ * Revision 1.38 2000/07/28 14:58:31 rgb -+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. -+ * -+ * Revision 1.37 2000/03/16 14:02:50 rgb -+ * Fixed debug scope to enable compilation with debug off. -+ * -+ * Revision 1.36 2000/01/21 06:14:46 rgb -+ * Added debugging text to ipsec_rj_walker_delete(). -+ * Set return code to negative for consistency. -+ * -+ * Revision 1.35 1999/11/23 23:05:24 rgb -+ * Use provided macro ADDRTOA_BUF instead of hardcoded value. -+ * -+ * Revision 1.34 1999/11/18 04:13:56 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * Added CONFIG_PROC_FS compiler directives in case it is shut off. -+ * -+ * Revision 1.33 1999/11/17 15:53:39 rgb -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * -+ * Revision 1.32 1999/10/26 13:58:33 rgb -+ * Put spinlock flags variable declaration outside the debug compiler -+ * directive to enable compilation with debug shut off. -+ * -+ * Revision 1.31 1999/10/15 22:13:29 rgb -+ * Clean out cruft. -+ * Align /proc/net/ipsec_eroute output for easier readability. -+ * Fix double linefeed in radij debug output. -+ * Fix double locking bug that locks up 2.0.36 but not 2.0.38. -+ * -+ * Revision 1.30 1999/10/08 18:37:33 rgb -+ * Fix end-of-line spacing to sate whining PHMs. -+ * -+ * Revision 1.29 1999/10/03 18:52:45 rgb -+ * Spinlock support for 2.0.xx. -+ * Dumb return code spin_unlock fix. -+ * -+ * Revision 1.28 1999/10/01 16:22:24 rgb -+ * Switch from assignment init. to functional init. of spinlocks. -+ * -+ * Revision 1.27 1999/10/01 15:44:53 rgb -+ * Move spinlock header include to 2.1> scope. -+ * -+ * Revision 1.26 1999/10/01 00:01:23 rgb -+ * Added eroute structure locking. -+ * -+ * Revision 1.25 1999/06/10 16:07:30 rgb -+ * Silence delete eroute on no debug. -+ * -+ * Revision 1.24 1999/05/09 03:25:36 rgb -+ * Fix bug introduced by 2.2 quick-and-dirty patch. -+ * -+ * Revision 1.23 1999/05/05 22:02:31 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.22 1999/04/29 15:17:23 rgb -+ * Add return values to init and cleanup functions. -+ * Add sanity checking for null pointer arguments. -+ * -+ * Revision 1.21 1999/04/11 00:28:58 henry -+ * GPL boilerplate -+ * -+ * Revision 1.20 1999/04/06 04:54:26 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.19 1999/02/17 16:50:35 rgb -+ * Clean out unused cruft. -+ * Consolidate for space and speed efficiency. -+ * Convert DEBUG_IPSEC to KLIPS_PRINT -+ * -+ * Revision 1.18 1999/01/22 06:22:06 rgb -+ * Cruft clean-out. -+ * 64-bit clean-up. -+ * -+ * Revision 1.17 1998/12/02 03:09:39 rgb -+ * Clean up debug printing conditionals to compile with debugging off. -+ * -+ * Revision 1.16 1998/12/01 13:49:39 rgb -+ * Wrap version info printing in debug switches. -+ * -+ * Revision 1.15 1998/11/30 13:22:54 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.14 1998/10/31 06:48:17 rgb -+ * Fixed up comments in #endif directives. -+ * -+ * Revision 1.13 1998/10/27 13:48:09 rgb -+ * Cleaned up /proc/net/ipsec_* filesystem for easy parsing by scripts. -+ * Fixed less(1) truncated output bug. -+ * Code clean-up. -+ * -+ * Revision 1.12 1998/10/25 02:41:36 rgb -+ * Change return type on ipsec_breakroute and ipsec_makeroute and add an -+ * argument to be able to transmit more infomation about errors. -+ * Fix cut-and-paste debug statement identifier. -+ * -+ * Revision 1.11 1998/10/22 06:45:39 rgb -+ * Cleaned up cruft. -+ * Convert to use satoa for printk. -+ * -+ * Revision 1.10 1998/10/19 14:44:28 rgb -+ * Added inclusion of freeswan.h. -+ * sa_id structure implemented and used: now includes protocol. -+ * -+ * Revision 1.9 1998/10/09 04:30:52 rgb -+ * Added 'klips_debug' prefix to all klips printk debug statements. -+ * Deleted old commented out cruft. -+ * -+ * Revision 1.8 1998/08/06 17:24:23 rgb -+ * Fix addrtoa return code bug from stale manpage advice preventing packets -+ * from being erouted. -+ * -+ * Revision 1.7 1998/08/06 07:44:59 rgb -+ * Fixed /proc/net/ipsec_eroute subnettoa and addrtoa return value bug that -+ * ended up in nothing being printed. -+ * -+ * Revision 1.6 1998/08/05 22:16:41 rgb -+ * Cleanup to prevent cosmetic errors (ie. debug output) from being fatal. -+ * -+ * Revision 1.5 1998/07/29 20:38:44 rgb -+ * Debug and fix subnettoa and addrtoa output. -+ * -+ * Revision 1.4 1998/07/28 00:02:39 rgb -+ * Converting to exclusive use of addrtoa. -+ * Fix eroute delete. -+ * -+ * Revision 1.3 1998/07/14 18:21:26 rgb -+ * Add function to clear the eroute table. -+ * -+ * Revision 1.2 1998/06/23 02:59:14 rgb -+ * Added debugging output to eroute add/delete routines. -+ * -+ * Revision 1.9 1998/06/18 21:29:06 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid kernel -+ * build scripts happier in presence of symbolic links -+ * -+ * Revision 1.8 1998/06/05 02:32:26 rgb -+ * Fix spi ntoh kernel debug output. -+ * -+ * Revision 1.7 1998/05/25 20:30:37 rgb -+ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions. -+ * -+ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and -+ * add ipsec_rj_walker_delete. -+ * -+ * Revision 1.6 1998/05/21 13:08:57 rgb -+ * Rewrote procinfo subroutines to avoid *bad things* when more that 3k of -+ * information is available for printout. -+ * -+ * Revision 1.5 1998/05/18 21:35:55 rgb -+ * Clean up output for numerical consistency and readability. Zero freed -+ * eroute memory. -+ * -+ * Revision 1.4 1998/04/21 21:28:58 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.3 1998/04/14 17:30:39 rgb -+ * Fix up compiling errors for radij tree memory reclamation. -+ * -+ * Revision 1.2 1998/04/12 22:03:23 rgb -+ * Updated ESP-3DES-HMAC-MD5-96, -+ * ESP-DES-HMAC-MD5-96, -+ * AH-HMAC-MD5-96, -+ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository -+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts. -+ * -+ * Fixed eroute references in /proc/net/ipsec*. -+ * -+ * Started to patch module unloading memory leaks in ipsec_netlink and -+ * radij tree unloading. -+ * -+ * Revision 1.1 1998/04/09 03:06:10 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:03 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:39:04 ji -+ * Minor cleanups. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_rcv.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1922 @@ -+/* -+ * receive code -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998-2003 Richard Guy Briggs. -+ * Copyright (C) 2004 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_rcv_c_version[] = "RCSID $Id$"; -+ -+#include -+#include -+ -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define proto_priv cb -+#endif /* NET21 */ -+#include -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+ -+#include "openswan/ipsec_auth.h" -+ -+#include "openswan/ipsec_esp.h" -+ -+#ifdef CONFIG_IPSEC_AH -+#include "openswan/ipsec_ah.h" -+#endif /* CONFIG_IPSEC_AH */ -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+#include "openswan/ipsec_ipcomp.h" -+#endif /* CONFIG_IPSEC_COMP */ -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+#include "openswan/ipsec_alg.h" -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_rcv = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+int sysctl_ipsec_inbound_policy_check = 1; -+ -+/* This is a private use protocol, and AT&T should be ashamed. They should have -+ * used protocol # 59, which is "no next header" instead of 0xFE. -+ */ -+#ifndef IPPROTO_ATT_HEARTBEAT -+#define IPPROTO_ATT_HEARTBEAT 0xFE -+#endif -+ -+#ifdef CONFIG_IPSEC_DEBUG -+void -+ipsec_dmp(char *s, caddr_t bb, int len) -+{ -+ int i; -+ unsigned char *b = bb; -+ -+ -+ printk(KERN_INFO "klips_debug:ipsec_tunnel_:dmp: " -+ "at %s, len=%d:", -+ s, -+ len); -+ for (i=0; i < len; i++) { -+ if(!(i%16)){ -+ printk("\nklips_debug: "); -+ } -+ printk(" %02x", *b++); -+ } -+ printk("\n"); -+} -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+/* -+ * Check-replay-window routine, adapted from the original -+ * by J. Hughes, from draft-ietf-ipsec-esp-des-md5-03.txt -+ * -+ * This is a routine that implements a 64 packet window. This is intend- -+ * ed on being an implementation sample. -+ */ -+ -+DEBUG_NO_STATIC int -+ipsec_checkreplaywindow(struct ipsec_sa*ipsp, __u32 seq) -+{ -+ __u32 diff; -+ -+ if (ipsp->ips_replaywin == 0) /* replay shut off */ -+ return 1; -+ if (seq == 0) -+ return 0; /* first == 0 or wrapped */ -+ -+ /* new larger sequence number */ -+ if (seq > ipsp->ips_replaywin_lastseq) { -+ return 1; /* larger is good */ -+ } -+ diff = ipsp->ips_replaywin_lastseq - seq; -+ -+ /* too old or wrapped */ /* if wrapped, kill off SA? */ -+ if (diff >= ipsp->ips_replaywin) { -+ return 0; -+ } -+ /* this packet already seen */ -+ if (ipsp->ips_replaywin_bitmap & (1 << diff)) -+ return 0; -+ return 1; /* out of order but good */ -+} -+ -+DEBUG_NO_STATIC int -+ipsec_updatereplaywindow(struct ipsec_sa*ipsp, __u32 seq) -+{ -+ __u32 diff; -+ -+ if (ipsp->ips_replaywin == 0) /* replay shut off */ -+ return 1; -+ if (seq == 0) -+ return 0; /* first == 0 or wrapped */ -+ -+ /* new larger sequence number */ -+ if (seq > ipsp->ips_replaywin_lastseq) { -+ diff = seq - ipsp->ips_replaywin_lastseq; -+ -+ /* In win, set bit for this pkt */ -+ if (diff < ipsp->ips_replaywin) -+ ipsp->ips_replaywin_bitmap = -+ (ipsp->ips_replaywin_bitmap << diff) | 1; -+ else -+ /* This packet has way larger seq num */ -+ ipsp->ips_replaywin_bitmap = 1; -+ -+ if(seq - ipsp->ips_replaywin_lastseq - 1 > ipsp->ips_replaywin_maxdiff) { -+ ipsp->ips_replaywin_maxdiff = seq - ipsp->ips_replaywin_lastseq - 1; -+ } -+ ipsp->ips_replaywin_lastseq = seq; -+ return 1; /* larger is good */ -+ } -+ diff = ipsp->ips_replaywin_lastseq - seq; -+ -+ /* too old or wrapped */ /* if wrapped, kill off SA? */ -+ if (diff >= ipsp->ips_replaywin) { -+/* -+ if(seq < 0.25*max && ipsp->ips_replaywin_lastseq > 0.75*max) { -+ ipsec_sa_delchain(ipsp); -+ } -+*/ -+ return 0; -+ } -+ /* this packet already seen */ -+ if (ipsp->ips_replaywin_bitmap & (1 << diff)) -+ return 0; -+ ipsp->ips_replaywin_bitmap |= (1 << diff); /* mark as seen */ -+ return 1; /* out of order but good */ -+} -+ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+struct auth_alg ipsec_rcv_md5[]={ -+ {MD5Init, MD5Update, MD5Final, AHMD596_ALEN} -+}; -+ -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+struct auth_alg ipsec_rcv_sha1[]={ -+ {SHA1Init, SHA1Update, SHA1Final, AHSHA196_ALEN} -+}; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+ -+enum ipsec_rcv_value -+ipsec_rcv_decap_once(struct ipsec_rcv_state *irs, struct xform_functions *proto_funcs) -+{ -+ int iphlen; -+ unsigned char *dat; -+ __u8 proto; -+ struct in_addr ipsaddr; -+ struct in_addr ipdaddr; -+ int replay = 0; /* replay value in AH or ESP packet */ -+ struct ipsec_sa* ipsnext = NULL; /* next SA towards inside of packet */ -+ struct ipsec_sa *newipsp; -+ struct iphdr *ipp; -+ struct sk_buff *skb; -+#ifdef CONFIG_IPSEC_ALG -+ struct ipsec_alg_auth *ixt_a=NULL; -+#endif /* CONFIG_IPSEC_ALG */ -+ -+ skb = irs->skb; -+ irs->len = skb->len; -+ dat = skb->data; -+ ipp = irs->ipp; -+ proto = ipp->protocol; -+ ipsaddr.s_addr = ipp->saddr; -+ addrtoa(ipsaddr, 0, irs->ipsaddr_txt, sizeof(irs->ipsaddr_txt)); -+ ipdaddr.s_addr = ipp->daddr; -+ addrtoa(ipdaddr, 0, irs->ipdaddr_txt, sizeof(irs->ipdaddr_txt)); -+ -+ iphlen = ipp->ihl << 2; -+ irs->iphlen=iphlen; -+ ipp->check = 0; /* we know the sum is good */ -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv_decap_once: " -+ "decap (%d) from %s -> %s\n", -+ proto, irs->ipsaddr_txt, irs->ipdaddr_txt); -+ -+ /* -+ * Find tunnel control block and (indirectly) call the -+ * appropriate tranform routine. The resulting sk_buf -+ * is a valid IP packet ready to go through input processing. -+ */ -+ -+ irs->said.dst.u.v4.sin_addr.s_addr = ipp->daddr; -+ irs->said.dst.u.v4.sin_family = AF_INET; -+ -+ if(proto_funcs->rcv_checks) { -+ enum ipsec_rcv_value retval = -+ (*proto_funcs->rcv_checks)(irs, skb); -+ -+ if(retval < 0) { -+ return retval; -+ } -+ } -+ -+ irs->said.proto = proto; -+ irs->sa_len = satot(&irs->said, 0, irs->sa, sizeof(irs->sa)); -+ if(irs->sa_len == 0) { -+ strcpy(irs->sa, "(error)"); -+ } -+ -+ newipsp = ipsec_sa_getbyid(&irs->said); -+ if (newipsp == NULL) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "no ipsec_sa for SA:%s: incoming packet with no SA dropped\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_SAIDNOTFOUND; -+ } -+ -+ /* MCR - XXX this is bizarre. ipsec_sa_getbyid returned it, having incremented the refcount, -+ * why in the world would we decrement it here? -+ -+ ipsec_sa_put(irs->ipsp);*/ /* incomplete */ -+ -+ /* If it is in larval state, drop the packet, we cannot process yet. */ -+ if(newipsp->ips_state == SADB_SASTATE_LARVAL) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "ipsec_sa in larval state, cannot be used yet, dropping packet.\n"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ ipsec_sa_put(newipsp); -+ return IPSEC_RCV_SAIDNOTLIVE; -+ } -+ -+ if(newipsp->ips_state == SADB_SASTATE_DEAD) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "ipsec_sa in dead state, cannot be used any more, dropping packet.\n"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ ipsec_sa_put(newipsp); -+ return IPSEC_RCV_SAIDNOTLIVE; -+ } -+ -+ if(sysctl_ipsec_inbound_policy_check) { -+ if(irs->ipp->saddr != ((struct sockaddr_in*)(newipsp->ips_addr_s))->sin_addr.s_addr) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s, src=%s of pkt does not agree with expected SA source address policy.\n", -+ irs->sa_len ? irs->sa : " (error)", -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ ipsec_sa_put(newipsp); -+ return IPSEC_RCV_FAILEDINBOUND; -+ } -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s, src=%s of pkt agrees with expected SA source address policy.\n", -+ irs->sa_len ? irs->sa : " (error)", -+ irs->ipsaddr_txt); -+ -+ /* -+ * at this point, we have looked up a new SA, and we want to make sure that if this -+ * isn't the first SA in the list, that the previous SA actually points at this one. -+ */ -+ if(irs->ipsp) { -+ if(irs->ipsp->ips_inext != newipsp) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "unexpected SA:%s: does not agree with ips->inext policy, dropped\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ ipsec_sa_put(newipsp); -+ return IPSEC_RCV_FAILEDINBOUND; -+ } -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s grouping from previous SA is OK.\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ } else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s First SA in group.\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ } -+ -+ /* -+ * previously, at this point, we checked if the back pointer from the new SA that -+ * we just found matched the back pointer. But, we won't do this check anymore, -+ * because we want to be able to nest SAs -+ */ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "natt_type=%u tdbp->ips_natt_type=%u : %s\n", -+ irs->natt_type, newipsp->ips_natt_type, -+ (irs->natt_type==newipsp->ips_natt_type)?"ok":"bad"); -+ if (irs->natt_type != newipsp->ips_natt_type) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s does not agree with expected NAT-T policy.\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ ipsec_sa_put(newipsp); -+ return IPSEC_RCV_FAILEDINBOUND; -+ } -+#endif -+ } -+ -+ /* okay, SA checks out, so free any previous SA, and record a new one */ -+ -+ if(irs->ipsp) { -+ ipsec_sa_put(irs->ipsp); -+ } -+ irs->ipsp=newipsp; -+ -+ /* note that the outer code will free the irs->ipsp if there is an error */ -+ -+ -+ /* now check the lifetimes */ -+ if(ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_bytes, "bytes", -+ irs->sa, ipsec_life_countbased, ipsec_incoming, -+ irs->ipsp) == ipsec_life_harddied || -+ ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_addtime, "addtime", -+ irs->sa, ipsec_life_timebased, ipsec_incoming, -+ irs->ipsp) == ipsec_life_harddied || -+ ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_addtime, "usetime", -+ irs->sa, ipsec_life_timebased, ipsec_incoming, -+ irs->ipsp) == ipsec_life_harddied || -+ ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_packets, "packets", -+ irs->sa, ipsec_life_countbased, ipsec_incoming, -+ irs->ipsp) == ipsec_life_harddied) { -+ ipsec_sa_delchain(irs->ipsp); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv_decap_once: " -+ "decap (%d) failed lifetime check\n", -+ proto); -+ -+ return IPSEC_RCV_LIFETIMEFAILED; -+ } -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if ((irs->natt_type) && -+ ( (irs->ipp->saddr != (((struct sockaddr_in*)(newipsp->ips_addr_s))->sin_addr.s_addr)) || -+ (irs->natt_sport != newipsp->ips_natt_sport) -+ )) { -+ struct sockaddr sipaddr; -+ /** Advertise NAT-T addr change to pluto **/ -+ sipaddr.sa_family = AF_INET; -+ ((struct sockaddr_in*)&sipaddr)->sin_addr.s_addr = irs->ipp->saddr; -+ ((struct sockaddr_in*)&sipaddr)->sin_port = htons(irs->natt_sport); -+ pfkey_nat_t_new_mapping(newipsp, &sipaddr, irs->natt_sport); -+ /** -+ * Then allow or block packet depending on -+ * sysctl_ipsec_inbound_policy_check. -+ * -+ * In all cases, pluto will update SA if new mapping is -+ * accepted. -+ */ -+ if (sysctl_ipsec_inbound_policy_check) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s, src=%s:%u of pkt does not agree with expected " -+ "SA source address policy (pluto has been informed).\n", -+ irs->sa_len ? irs->sa : " (error)", -+ irs->ipsaddr_txt, irs->natt_sport); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ ipsec_sa_put(newipsp); -+ return IPSEC_RCV_FAILEDINBOUND; -+ } -+ } -+#endif -+ -+ irs->authfuncs=NULL; -+ /* authenticate, if required */ -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_a=irs->ipsp->ips_alg_auth)) { -+ irs->authlen = AHHMAC_HASHLEN; -+ irs->authfuncs = NULL; -+ irs->ictx = NULL; -+ irs->octx = NULL; -+ irs->ictx_len = 0; -+ irs->octx_len = 0; -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "authalg=%d authlen=%d\n", -+ irs->ipsp->ips_authalg, -+ irs->authlen); -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(irs->ipsp->ips_authalg) { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: -+ irs->authlen = AHHMAC_HASHLEN; -+ irs->authfuncs = ipsec_rcv_md5; -+ irs->ictx = (void *)&((struct md5_ctx*)(irs->ipsp->ips_key_a))->ictx; -+ irs->octx = (void *)&((struct md5_ctx*)(irs->ipsp->ips_key_a))->octx; -+ irs->ictx_len = sizeof(((struct md5_ctx*)(irs->ipsp->ips_key_a))->ictx); -+ irs->octx_len = sizeof(((struct md5_ctx*)(irs->ipsp->ips_key_a))->octx); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: -+ irs->authlen = AHHMAC_HASHLEN; -+ irs->authfuncs = ipsec_rcv_sha1; -+ irs->ictx = (void *)&((struct sha1_ctx*)(irs->ipsp->ips_key_a))->ictx; -+ irs->octx = (void *)&((struct sha1_ctx*)(irs->ipsp->ips_key_a))->octx; -+ irs->ictx_len = sizeof(((struct sha1_ctx*)(irs->ipsp->ips_key_a))->ictx); -+ irs->octx_len = sizeof(((struct sha1_ctx*)(irs->ipsp->ips_key_a))->octx); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ case AH_NONE: -+ irs->authlen = 0; -+ irs->authfuncs = NULL; -+ irs->ictx = NULL; -+ irs->octx = NULL; -+ irs->ictx_len = 0; -+ irs->octx_len = 0; -+ break; -+ default: -+ irs->ipsp->ips_errs.ips_alg_errs += 1; -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_BADAUTH; -+ } -+ -+ irs->ilen = irs->len - iphlen - irs->authlen; -+ if(irs->ilen <= 0) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "runt %s packet with no data, dropping.\n", -+ (proto == IPPROTO_ESP ? "esp" : "ah")); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_BADLEN; -+ } -+ -+#ifdef CONFIG_IPSEC_ALG -+ if(irs->authfuncs || ixt_a) { -+#else -+ if(irs->authfuncs) { -+#endif -+ unsigned char *authenticator = NULL; -+ -+ if(proto_funcs->rcv_setup_auth) { -+ enum ipsec_rcv_value retval -+ = (*proto_funcs->rcv_setup_auth)(irs, skb, -+ &replay, -+ &authenticator); -+ if(retval < 0) { -+ return retval; -+ } -+ } -+ -+ if(!authenticator) { -+ irs->ipsp->ips_errs.ips_auth_errs += 1; -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_BADAUTH; -+ } -+ -+ if(!ipsec_checkreplaywindow(irs->ipsp, replay)) { -+ irs->ipsp->ips_errs.ips_replaywin_errs += 1; -+ KLIPS_PRINT(debug_rcv & DB_RX_REPLAY, -+ "klips_debug:ipsec_rcv: " -+ "duplicate frame from %s, packet dropped\n", -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_REPLAYFAILED; -+ } -+ -+ /* -+ * verify authenticator -+ */ -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "encalg = %d, authalg = %d.\n", -+ irs->ipsp->ips_encalg, -+ irs->ipsp->ips_authalg); -+ -+ /* calculate authenticator */ -+ if(proto_funcs->rcv_calc_auth == NULL) { -+ return IPSEC_RCV_BADAUTH; -+ } -+ (*proto_funcs->rcv_calc_auth)(irs, skb); -+ -+ if (memcmp(irs->hash, authenticator, irs->authlen)) { -+ irs->ipsp->ips_errs.ips_auth_errs += 1; -+ KLIPS_PRINT(debug_rcv & DB_RX_INAU, -+ "klips_debug:ipsec_rcv: " -+ "auth failed on incoming packet from %s: hash=%08x%08x%08x auth=%08x%08x%08x, dropped\n", -+ irs->ipsaddr_txt, -+ ntohl(*(__u32*)&irs->hash[0]), -+ ntohl(*(__u32*)&irs->hash[4]), -+ ntohl(*(__u32*)&irs->hash[8]), -+ ntohl(*(__u32*)authenticator), -+ ntohl(*((__u32*)authenticator + 1)), -+ ntohl(*((__u32*)authenticator + 2))); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_AUTHFAILED; -+ } else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "authentication successful.\n"); -+ } -+ -+ /* Crypto hygiene: clear memory used to calculate autheticator. -+ * The length varies with the algorithm. -+ */ -+ memset(irs->hash, 0, irs->authlen); -+ -+ /* If the sequence number == 0, expire SA, it had rolled */ -+ if(irs->ipsp->ips_replaywin && !replay /* !irs->ipsp->ips_replaywin_lastseq */) { -+ ipsec_sa_delchain(irs->ipsp); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "replay window counter rolled, expiring SA.\n"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_REPLAYROLLED; -+ } -+ -+ /* now update the replay counter */ -+ if (!ipsec_updatereplaywindow(irs->ipsp, replay)) { -+ irs->ipsp->ips_errs.ips_replaywin_errs += 1; -+ KLIPS_PRINT(debug_rcv & DB_RX_REPLAY, -+ "klips_debug:ipsec_rcv: " -+ "duplicate frame from %s, packet dropped\n", -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_REPLAYROLLED; -+ } -+ } -+ -+ if(proto_funcs->rcv_decrypt) { -+ enum ipsec_rcv_value retval = -+ (*proto_funcs->rcv_decrypt)(irs); -+ -+ if(retval != IPSEC_RCV_OK) { -+ return retval; -+ } -+ } -+ -+ /* -+ * Adjust pointers -+ */ -+ skb = irs->skb; -+ irs->len = skb->len; -+ dat = skb->data; -+ -+#ifdef NET_21 -+/* skb->h.ipiph=(struct iphdr *)skb->data; */ -+ skb->nh.raw = skb->data; -+ skb->h.raw = skb->nh.raw + (skb->nh.iph->ihl << 2); -+ -+ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); -+#else /* NET_21 */ -+ skb->h.iph=(struct iphdr *)skb->data; -+ skb->ip_hdr=(struct iphdr *)skb->data; -+ memset(skb->proto_priv, 0, sizeof(struct options)); -+#endif /* NET_21 */ -+ -+ ipp = (struct iphdr *)dat; -+ ipsaddr.s_addr = ipp->saddr; -+ addrtoa(ipsaddr, 0, irs->ipsaddr_txt, sizeof(irs->ipsaddr_txt)); -+ ipdaddr.s_addr = ipp->daddr; -+ addrtoa(ipdaddr, 0, irs->ipdaddr_txt, sizeof(irs->ipdaddr_txt)); -+ /* -+ * Discard the original ESP/AH header -+ */ -+ ipp->protocol = irs->next_header; -+ -+ ipp->check = 0; /* NOTE: this will be included in checksum */ -+ ipp->check = ip_fast_csum((unsigned char *)dat, iphlen >> 2); -+ -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "after <%s%s%s>, SA:%s:\n", -+ IPS_XFORM_NAME(irs->ipsp), -+ irs->sa_len ? irs->sa : " (error)"); -+ KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp); -+ -+ skb->protocol = htons(ETH_P_IP); -+ skb->ip_summed = 0; -+ -+ ipsnext = irs->ipsp->ips_inext; -+ if(sysctl_ipsec_inbound_policy_check) { -+ if(ipsnext) { -+ if( -+ ipp->protocol != IPPROTO_AH -+ && ipp->protocol != IPPROTO_ESP -+#ifdef CONFIG_IPSEC_IPCOMP -+ && ipp->protocol != IPPROTO_COMP -+ && (ipsnext->ips_said.proto != IPPROTO_COMP -+ || ipsnext->ips_inext) -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ && ipp->protocol != IPPROTO_IPIP -+ && ipp->protocol != 0xFE /* added to support heartbeats to AT&T SIG/GIG */ -+ ) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "packet with incomplete policy dropped, last successful SA:%s.\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_FAILEDINBOUND; -+ } -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s, Another IPSEC header to process.\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ } else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "No ips_inext from this SA:%s.\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ } -+ } -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+ /* update ipcomp ratio counters, even if no ipcomp packet is present */ -+ if (ipsnext -+ && ipsnext->ips_said.proto == IPPROTO_COMP -+ && ipp->protocol != IPPROTO_COMP) { -+ ipsnext->ips_comp_ratio_cbytes += ntohs(ipp->tot_len); -+ ipsnext->ips_comp_ratio_dbytes += ntohs(ipp->tot_len); -+ } -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+ irs->ipsp->ips_life.ipl_bytes.ipl_count += irs->len; -+ irs->ipsp->ips_life.ipl_bytes.ipl_last = irs->len; -+ -+ if(!irs->ipsp->ips_life.ipl_usetime.ipl_count) { -+ irs->ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ; -+ } -+ irs->ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ; -+ irs->ipsp->ips_life.ipl_packets.ipl_count += 1; -+ -+#ifdef CONFIG_NETFILTER -+ if(proto == IPPROTO_ESP || proto == IPPROTO_AH) { -+ skb->nfmark = (skb->nfmark & (~(IPsecSAref2NFmark(IPSEC_SA_REF_MASK)))) -+ | IPsecSAref2NFmark(IPsecSA2SAref(irs->ipsp)); -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "%s SA sets skb->nfmark=0x%x.\n", -+ proto == IPPROTO_ESP ? "ESP" : "AH", -+ (unsigned)skb->nfmark); -+ } -+#endif /* CONFIG_NETFILTER */ -+ -+ return IPSEC_RCV_OK; -+} -+ -+ -+int -+#ifdef PROTO_HANDLER_SINGLE_PARM -+ipsec_rcv(struct sk_buff *skb) -+#else /* PROTO_HANDLER_SINGLE_PARM */ -+#ifdef NET_21 -+ipsec_rcv(struct sk_buff *skb, unsigned short xlen) -+#else /* NET_21 */ -+ipsec_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, -+ __u32 daddr_unused, unsigned short xlen, __u32 saddr, -+ int redo, struct inet_protocol *protocol) -+#endif /* NET_21 */ -+#endif /* PROTO_HANDLER_SINGLE_PARM */ -+{ -+#ifdef NET_21 -+#ifdef CONFIG_IPSEC_DEBUG -+ struct device *dev = skb->dev; -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif /* NET_21 */ -+ unsigned char protoc; -+ struct iphdr *ipp; -+ struct ipsec_sa *ipsp = NULL; -+ struct net_device_stats *stats = NULL; /* This device's statistics */ -+ struct device *ipsecdev = NULL, *prvdev; -+ struct ipsecpriv *prv; -+ char name[9]; -+ int i; -+ struct in_addr ipsaddr; -+ struct in_addr ipdaddr; -+ -+ struct ipsec_sa* ipsnext = NULL; /* next SA towards inside of packet */ -+ struct ipsec_rcv_state irs; -+ -+ /* Don't unlink in the middle of a turnaround */ -+ MOD_INC_USE_COUNT; -+ -+ memset(&irs, 0, sizeof(struct ipsec_rcv_state)); -+ -+ if (skb == NULL) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NULL skb passed in.\n"); -+ goto rcvleave; -+ } -+ -+ if (skb->data == NULL) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NULL skb->data passed in, packet is bogus, dropping.\n"); -+ goto rcvleave; -+ } -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if (skb->sk && skb->nh.iph && skb->nh.iph->protocol==IPPROTO_UDP) { -+ /** -+ * Packet comes from udp_queue_rcv_skb so it is already defrag, -+ * checksum verified, ... (ie safe to use) -+ * -+ * If the packet is not for us, return -1 and udp_queue_rcv_skb -+ * will continue to handle it (do not kfree skb !!). -+ */ -+#ifndef UDP_OPT_IN_SOCK -+ struct udp_opt { -+ __u32 esp_in_udp; -+ }; -+ struct udp_opt *tp = (struct udp_opt *)&(skb->sk->tp_pinfo.af_tcp); -+#else -+ struct udp_opt *tp = &(skb->sk->tp_pinfo.af_udp); -+#endif -+ struct iphdr *ip = (struct iphdr *)skb->nh.iph; -+ struct udphdr *udp = (struct udphdr *)((__u32 *)ip+ip->ihl); -+ __u8 *udpdata = (__u8 *)udp + sizeof(struct udphdr); -+ __u32 *udpdata32 = (__u32 *)udpdata; -+ -+ irs.natt_sport = ntohs(udp->source); -+ irs.natt_dport = ntohs(udp->dest); -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "suspected ESPinUDP packet (NAT-Traversal) [%d].\n", -+ tp->esp_in_udp); -+ KLIPS_IP_PRINT(debug_rcv, ip); -+ -+ if (udpdata < skb->tail) { -+ unsigned int len = skb->tail - udpdata; -+ if ((len==1) && (udpdata[0]==0xff)) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ /* not IPv6 compliant message */ -+ "NAT-keepalive from %d.%d.%d.%d.\n", NIPQUAD(ip->saddr)); -+ goto rcvleave; -+ } -+ else if ( (tp->esp_in_udp == ESPINUDP_WITH_NON_IKE) && -+ (len > (2*sizeof(__u32) + sizeof(struct esphdr))) && -+ (udpdata32[0]==0) && (udpdata32[1]==0) ) { -+ /* ESP Packet with Non-IKE header */ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "ESPinUDP pkt with Non-IKE - spi=0x%x\n", -+ ntohl(udpdata32[2])); -+ irs.natt_type = ESPINUDP_WITH_NON_IKE; -+ irs.natt_len = sizeof(struct udphdr)+(2*sizeof(__u32)); -+ } -+ else if ( (tp->esp_in_udp == ESPINUDP_WITH_NON_ESP) && -+ (len > sizeof(struct esphdr)) && -+ (udpdata32[0]!=0) ) { -+ /* ESP Packet without Non-ESP header */ -+ irs.natt_type = ESPINUDP_WITH_NON_ESP; -+ irs.natt_len = sizeof(struct udphdr); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "ESPinUDP pkt without Non-ESP - spi=0x%x\n", -+ ntohl(udpdata32[0])); -+ } -+ else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "IKE packet - not handled here\n"); -+ MOD_DEC_USE_COUNT; -+ return -1; -+ } -+ } -+ else { -+ MOD_DEC_USE_COUNT; -+ return -1; -+ } -+ } -+#endif -+ -+#ifdef IPH_is_SKB_PULLED -+ /* In Linux 2.4.4, the IP header has been skb_pull()ed before the -+ packet is passed to us. So we'll skb_push() to get back to it. */ -+ if (skb->data == skb->h.raw) { -+ skb_push(skb, skb->h.raw - skb->nh.raw); -+ } -+#endif /* IPH_is_SKB_PULLED */ -+ -+ /* dev->hard_header_len is unreliable and should not be used */ -+ irs.hard_header_len = skb->mac.raw ? (skb->data - skb->mac.raw) : 0; -+ if((irs.hard_header_len < 0) || (irs.hard_header_len > skb_headroom(skb))) -+ irs.hard_header_len = 0; -+ -+#ifdef NET_21 -+ /* if skb was cloned (most likely due to a packet sniffer such as -+ tcpdump being momentarily attached to the interface), make -+ a copy of our own to modify */ -+ if(skb_cloned(skb)) { -+ /* include any mac header while copying.. */ -+ if(skb_headroom(skb) < irs.hard_header_len) { -+ printk(KERN_WARNING "klips_error:ipsec_rcv: " -+ "tried to skb_push hhlen=%d, %d available. This should never happen, please report.\n", -+ irs.hard_header_len, -+ skb_headroom(skb)); -+ goto rcvleave; -+ } -+ skb_push(skb, irs.hard_header_len); -+ if -+#ifdef SKB_COW_NEW -+ (skb_cow(skb, skb_headroom(skb)) != 0) -+#else /* SKB_COW_NEW */ -+ ((skb = skb_cow(skb, skb_headroom(skb))) == NULL) -+#endif /* SKB_COW_NEW */ -+ { -+ goto rcvleave; -+ } -+ if(skb->len < irs.hard_header_len) { -+ printk(KERN_WARNING "klips_error:ipsec_rcv: " -+ "tried to skb_pull hhlen=%d, %d available. This should never happen, please report.\n", -+ irs.hard_header_len, -+ skb->len); -+ goto rcvleave; -+ } -+ skb_pull(skb, irs.hard_header_len); -+ } -+ -+#endif /* NET_21 */ -+ -+#if IP_FRAGMENT_LINEARIZE -+ /* In Linux 2.4.4, we may have to reassemble fragments. They are -+ not assembled automatically to save TCP from having to copy -+ twice. -+ */ -+ if (skb_is_nonlinear(skb)) { -+ if (skb_linearize(skb, GFP_ATOMIC) != 0) { -+ goto rcvleave; -+ } -+ } -+#endif /* IP_FRAGMENT_LINEARIZE */ -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if (irs.natt_len) { -+ /** -+ * Now, we are sure packet is ESPinUDP. Remove natt_len bytes from -+ * packet and modify protocol to ESP. -+ */ -+ if (((unsigned char *)skb->data > (unsigned char *)skb->nh.iph) && -+ ((unsigned char *)skb->nh.iph > (unsigned char *)skb->head)) { -+ unsigned int _len = (unsigned char *)skb->data - -+ (unsigned char *)skb->nh.iph; -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: adjusting skb: skb_push(%u)\n", -+ _len); -+ skb_push(skb, _len); -+ } -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "removing %d bytes from ESPinUDP packet\n", irs.natt_len); -+ ipp = (struct iphdr *)skb->data; -+ irs.iphlen = ipp->ihl << 2; -+ ipp->tot_len = htons(ntohs(ipp->tot_len) - irs.natt_len); -+ if (skb->len < irs.iphlen + irs.natt_len) { -+ printk(KERN_WARNING -+ "klips_error:ipsec_rcv: " -+ "ESPinUDP packet is too small (%d < %d+%d). " -+ "This should never happen, please report.\n", -+ (int)(skb->len), irs.iphlen, irs.natt_len); -+ goto rcvleave; -+ } -+ memmove(skb->data + irs.natt_len, skb->data, irs.iphlen); -+ skb_pull(skb, irs.natt_len); -+ -+ /* update nh.iph */ -+ ipp = skb->nh.iph = (struct iphdr *)skb->data; -+ -+ /* modify protocol */ -+ ipp->protocol = IPPROTO_ESP; -+ -+ skb->sk = NULL; -+ -+ KLIPS_IP_PRINT(debug_rcv, skb->nh.iph); -+ } -+#endif -+ -+ ipp = skb->nh.iph; -+ ipsaddr.s_addr = ipp->saddr; -+ addrtoa(ipsaddr, 0, irs.ipsaddr_txt, sizeof(irs.ipsaddr_txt)); -+ ipdaddr.s_addr = ipp->daddr; -+ addrtoa(ipdaddr, 0, irs.ipdaddr_txt, sizeof(irs.ipdaddr_txt)); -+ irs.iphlen = ipp->ihl << 2; -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "<<< Info -- "); -+ KLIPS_PRINTMORE(debug_rcv && skb->dev, "skb->dev=%s ", -+ skb->dev->name ? skb->dev->name : "NULL"); -+ KLIPS_PRINTMORE(debug_rcv && dev, "dev=%s ", -+ dev->name ? dev->name : "NULL"); -+ KLIPS_PRINTMORE(debug_rcv, "\n"); -+ -+ KLIPS_PRINT(debug_rcv && !(skb->dev && dev && (skb->dev == dev)), -+ "klips_debug:ipsec_rcv: " -+ "Informational -- **if this happens, find out why** skb->dev:%s is not equal to dev:%s\n", -+ skb->dev ? (skb->dev->name ? skb->dev->name : "NULL") : "NULL", -+ dev ? (dev->name ? dev->name : "NULL") : "NULL"); -+ -+ protoc = ipp->protocol; -+#ifndef NET_21 -+ if((!protocol) || (protocol->protocol != protoc)) { -+ KLIPS_PRINT(debug_rcv & DB_RX_IPSA, -+ "klips_debug:ipsec_rcv: " -+ "protocol arg is NULL or unequal to the packet contents, this is odd, using value in packet.\n"); -+ } -+#endif /* !NET_21 */ -+ -+ if( (protoc != IPPROTO_AH) && -+#ifdef CONFIG_IPSEC_IPCOMP_disabled_until_we_register_IPCOMP_HANDLER -+ (protoc != IPPROTO_COMP) && -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ (protoc != IPPROTO_ESP) ) { -+ KLIPS_PRINT(debug_rcv & DB_RX_IPSA, -+ "klips_debug:ipsec_rcv: Why the hell is someone " -+ "passing me a non-ipsec protocol = %d packet? -- dropped.\n", -+ protoc); -+ goto rcvleave; -+ } -+ -+ if(skb->dev) { -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ sprintf(name, IPSEC_DEV_FORMAT, i); -+ if(!strcmp(name, skb->dev->name)) { -+ prv = (struct ipsecpriv *)(skb->dev->priv); -+ if(prv) { -+ stats = (struct net_device_stats *) &(prv->mystats); -+ } -+ ipsecdev = skb->dev; -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "Info -- pkt already proc'ed a group of ipsec headers, processing next group of ipsec headers.\n"); -+ break; -+ } -+ if((ipsecdev = __ipsec_dev_get(name)) == NULL) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_error:ipsec_rcv: " -+ "device %s does not exist\n", -+ name); -+ } -+ prv = ipsecdev ? (struct ipsecpriv *)(ipsecdev->priv) : NULL; -+ prvdev = prv ? (struct device *)(prv->dev) : NULL; -+ -+#if 0 -+ KLIPS_PRINT(debug_rcv && prvdev, -+ "klips_debug:ipsec_rcv: " -+ "physical device for device %s is %s\n", -+ name, -+ prvdev->name); -+#endif -+ if(prvdev && skb->dev && -+ !strcmp(prvdev->name, skb->dev->name)) { -+ stats = prv ? ((struct net_device_stats *) &(prv->mystats)) : NULL; -+ skb->dev = ipsecdev; -+ KLIPS_PRINT(debug_rcv && prvdev, -+ "klips_debug:ipsec_rcv: " -+ "assigning packet ownership to virtual device %s from physical device %s.\n", -+ name, prvdev->name); -+ if(stats) { -+ stats->rx_packets++; -+ } -+ break; -+ } -+ } -+ } else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "device supplied with skb is NULL\n"); -+ } -+ -+ if(stats == NULL) { -+ KLIPS_PRINT((debug_rcv), -+ "klips_error:ipsec_rcv: " -+ "packet received from physical I/F (%s) not connected to ipsec I/F. Cannot record stats. May not have SA for decoding. Is IPSEC traffic expected on this I/F? Check routing.\n", -+ skb->dev ? (skb->dev->name ? skb->dev->name : "NULL") : "NULL"); -+ } -+ -+ KLIPS_IP_PRINT(debug_rcv, ipp); -+ -+ /* begin decapsulating loop here */ -+ -+ /* -+ The spinlock is to prevent any other process from -+ accessing or deleting the ipsec_sa hash table or any of the -+ ipsec_sa s while we are using and updating them. -+ -+ This is not optimal, but was relatively straightforward -+ at the time. A better way to do it has been planned for -+ more than a year, to lock the hash table and put reference -+ counts on each ipsec_sa instead. This is not likely to happen -+ in KLIPS1 unless a volunteer contributes it, but will be -+ designed into KLIPS2. -+ */ -+ spin_lock(&tdb_lock); -+ -+ /* set up for decap loop */ -+ irs.stats= stats; -+ irs.ipp = ipp; -+ irs.ipsp = NULL; -+ irs.ilen = 0; -+ irs.authlen=0; -+ irs.authfuncs=NULL; -+ irs.skb = skb; -+ -+ do { -+ int decap_stat; -+ struct xform_functions *proto_funcs; -+ -+ switch(irs.ipp->protocol) { -+ case IPPROTO_ESP: -+ proto_funcs = esp_xform_funcs; -+ break; -+ -+#ifdef CONFIG_IPSEC_AH -+ case IPPROTO_AH: -+ proto_funcs = ah_xform_funcs; -+ break; -+#endif /* !CONFIG_IPSEC_AH */ -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+ case IPPROTO_COMP: -+ proto_funcs = ipcomp_xform_funcs; -+ break; -+#endif /* !CONFIG_IPSEC_IPCOMP */ -+ default: -+ if(irs.stats) { -+ irs.stats->rx_errors++; -+ } -+ decap_stat = IPSEC_RCV_BADPROTO; -+ goto rcvleave; -+ } -+ -+ decap_stat = ipsec_rcv_decap_once(&irs, proto_funcs); -+ -+ if(decap_stat != IPSEC_RCV_OK) { -+ spin_unlock(&tdb_lock); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: decap_once failed: %d\n", -+ decap_stat); -+ -+ goto rcvleave; -+ } -+ /* end decapsulation loop here */ -+ } while( (irs.ipp->protocol == IPPROTO_ESP ) -+ || (irs.ipp->protocol == IPPROTO_AH ) -+#ifdef CONFIG_IPSEC_IPCOMP -+ || (irs.ipp->protocol == IPPROTO_COMP) -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ ); -+ -+ /* set up for decap loop */ -+ ipp =irs.ipp; -+ ipsp =irs.ipsp; -+ ipsnext = ipsp->ips_inext; -+ skb = irs.skb; -+ -+ /* if there is an IPCOMP, but we don't have an IPPROTO_COMP, -+ * then we can just skip it -+ */ -+#ifdef CONFIG_IPSEC_IPCOMP -+ if(ipsnext && ipsnext->ips_said.proto == IPPROTO_COMP) { -+ ipsp = ipsnext; -+ ipsnext = ipsp->ips_inext; -+ } -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if ((irs.natt_type) && (ipp->protocol != IPPROTO_IPIP)) { -+ /** -+ * NAT-Traversal and Transport Mode: -+ * we need to correct TCP/UDP checksum -+ * -+ * If we've got NAT-OA, we can fix checksum without recalculation. -+ */ -+ __u32 natt_oa = ipsp->ips_natt_oa ? -+ ((struct sockaddr_in*)(ipsp->ips_natt_oa))->sin_addr.s_addr : 0; -+ __u16 pkt_len = skb->tail - (unsigned char *)ipp; -+ __u16 data_len = pkt_len - (ipp->ihl << 2); -+ -+ switch (ipp->protocol) { -+ case IPPROTO_TCP: -+ if (data_len >= sizeof(struct tcphdr)) { -+ struct tcphdr *tcp = (struct tcphdr *)((__u32 *)ipp+ipp->ihl); -+ if (natt_oa) { -+ __u32 buff[2] = { ~natt_oa, ipp->saddr }; -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: " -+ "fix TCP checksum using NAT-OA\n"); -+ tcp->check = csum_fold( -+ csum_partial((unsigned char *)buff, sizeof(buff), -+ tcp->check^0xffff)); -+ } -+ else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: recalc TCP checksum\n"); -+ if (pkt_len > (ntohs(ipp->tot_len))) -+ data_len -= (pkt_len - ntohs(ipp->tot_len)); -+ tcp->check = 0; -+ tcp->check = csum_tcpudp_magic(ipp->saddr, ipp->daddr, -+ data_len, IPPROTO_TCP, -+ csum_partial((unsigned char *)tcp, data_len, 0)); -+ } -+ } -+ else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: can't fix TCP checksum\n"); -+ } -+ break; -+ case IPPROTO_UDP: -+ if (data_len >= sizeof(struct udphdr)) { -+ struct udphdr *udp = (struct udphdr *)((__u32 *)ipp+ipp->ihl); -+ if (udp->check == 0) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: UDP checksum already 0\n"); -+ } -+ else if (natt_oa) { -+ __u32 buff[2] = { ~natt_oa, ipp->saddr }; -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: " -+ "fix UDP checksum using NAT-OA\n"); -+ udp->check = csum_fold( -+ csum_partial((unsigned char *)buff, sizeof(buff), -+ udp->check^0xffff)); -+ } -+ else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: zero UDP checksum\n"); -+ udp->check = 0; -+ } -+ } -+ else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: can't fix UDP checksum\n"); -+ } -+ break; -+ default: -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: non TCP/UDP packet -- do nothing\n"); -+ break; -+ } -+ } -+#endif -+ -+ /* -+ * XXX this needs to be locked from when it was first looked -+ * up in the decapsulation loop. Perhaps it is better to put -+ * the IPIP decap inside the loop. -+ */ -+ if(ipsnext) { -+ ipsp = ipsnext; -+ irs.sa_len = satot(&irs.said, 0, irs.sa, sizeof(irs.sa)); -+ if((ipp->protocol != IPPROTO_IPIP) && -+ ( 0xFE != ipp->protocol)) { /* added to support AT&T heartbeats to SIG/GIG */ -+ spin_unlock(&tdb_lock); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s, Hey! How did this get through? Dropped.\n", -+ irs.sa_len ? irs.sa : " (error)"); -+ if(stats) { -+ stats->rx_dropped++; -+ } -+ goto rcvleave; -+ } -+ if(sysctl_ipsec_inbound_policy_check) { -+ if((ipsnext = ipsp->ips_inext)) { -+ char sa2[SATOT_BUF]; -+ size_t sa_len2; -+ sa_len2 = satot(&ipsnext->ips_said, 0, sa2, sizeof(sa2)); -+ spin_unlock(&tdb_lock); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "unexpected SA:%s after IPIP SA:%s\n", -+ sa_len2 ? sa2 : " (error)", -+ irs.sa_len ? irs.sa : " (error)"); -+ if(stats) { -+ stats->rx_dropped++; -+ } -+ goto rcvleave; -+ } -+ if(ipp->saddr != ((struct sockaddr_in*)(ipsp->ips_addr_s))->sin_addr.s_addr) { -+ spin_unlock(&tdb_lock); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s, src=%s of pkt does not agree with expected SA source address policy.\n", -+ irs.sa_len ? irs.sa : " (error)", -+ irs.ipsaddr_txt); -+ if(stats) { -+ stats->rx_dropped++; -+ } -+ goto rcvleave; -+ } -+ } -+ -+ if(ipp->protocol == IPPROTO_IPIP) /* added to support AT&T heartbeats to SIG/GIG */ -+ { -+ /* -+ * XXX this needs to be locked from when it was first looked -+ * up in the decapsulation loop. Perhaps it is better to put -+ * the IPIP decap inside the loop. -+ */ -+ ipsp->ips_life.ipl_bytes.ipl_count += skb->len; -+ ipsp->ips_life.ipl_bytes.ipl_last = skb->len; -+ -+ if(!ipsp->ips_life.ipl_usetime.ipl_count) { -+ ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ; -+ } -+ ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ; -+ ipsp->ips_life.ipl_packets.ipl_count += 1; -+ -+ if(skb->len < irs.iphlen) { -+ spin_unlock(&tdb_lock); -+ printk(KERN_WARNING "klips_debug:ipsec_rcv: " -+ "tried to skb_pull iphlen=%d, %d available. This should never happen, please report.\n", -+ irs.iphlen, -+ (int)(skb->len)); -+ -+ goto rcvleave; -+ } -+ skb_pull(skb, irs.iphlen); -+ -+#ifdef NET_21 -+ ipp = (struct iphdr *)skb->nh.raw = skb->data; -+ skb->h.raw = skb->nh.raw + (skb->nh.iph->ihl << 2); -+ -+ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); -+#else /* NET_21 */ -+ ipp = skb->ip_hdr = skb->h.iph = (struct iphdr *)skb->data; -+ -+ memset(skb->proto_priv, 0, sizeof(struct options)); -+#endif /* NET_21 */ -+ ipsaddr.s_addr = ipp->saddr; -+ addrtoa(ipsaddr, 0, irs.ipsaddr_txt, sizeof(irs.ipsaddr_txt)); -+ ipdaddr.s_addr = ipp->daddr; -+ addrtoa(ipdaddr, 0, irs.ipdaddr_txt, sizeof(irs.ipdaddr_txt)); -+ -+ skb->protocol = htons(ETH_P_IP); -+ skb->ip_summed = 0; -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "IPIP tunnel stripped.\n"); -+ KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp); -+ } -+ -+ if(sysctl_ipsec_inbound_policy_check -+ /* -+ Note: "xor" (^) logically replaces "not equal" -+ (!=) and "bitwise or" (|) logically replaces -+ "boolean or" (||). This is done to speed up -+ execution by doing only bitwise operations and -+ no branch operations -+ */ -+ && (((ipp->saddr & ipsp->ips_mask_s.u.v4.sin_addr.s_addr) -+ ^ ipsp->ips_flow_s.u.v4.sin_addr.s_addr) -+ | ((ipp->daddr & ipsp->ips_mask_d.u.v4.sin_addr.s_addr) -+ ^ ipsp->ips_flow_d.u.v4.sin_addr.s_addr)) ) -+ { -+ char sflow_txt[SUBNETTOA_BUF], dflow_txt[SUBNETTOA_BUF]; -+ -+ subnettoa(ipsp->ips_flow_s.u.v4.sin_addr, -+ ipsp->ips_mask_s.u.v4.sin_addr, -+ 0, sflow_txt, sizeof(sflow_txt)); -+ subnettoa(ipsp->ips_flow_d.u.v4.sin_addr, -+ ipsp->ips_mask_d.u.v4.sin_addr, -+ 0, dflow_txt, sizeof(dflow_txt)); -+ spin_unlock(&tdb_lock); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s, inner tunnel policy [%s -> %s] does not agree with pkt contents [%s -> %s].\n", -+ irs.sa_len ? irs.sa : " (error)", -+ sflow_txt, -+ dflow_txt, -+ irs.ipsaddr_txt, -+ irs.ipdaddr_txt); -+ if(stats) { -+ stats->rx_dropped++; -+ } -+ goto rcvleave; -+ } -+#ifdef CONFIG_NETFILTER -+ skb->nfmark = (skb->nfmark & (~(IPsecSAref2NFmark(IPSEC_SA_REF_TABLE_MASK)))) -+ | IPsecSAref2NFmark(IPsecSA2SAref(ipsp)); -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "IPIP SA sets skb->nfmark=0x%x.\n", -+ (unsigned)skb->nfmark); -+#endif /* CONFIG_NETFILTER */ -+ } -+ -+ spin_unlock(&tdb_lock); -+ -+#ifdef NET_21 -+ if(stats) { -+ stats->rx_bytes += skb->len; -+ } -+ if(skb->dst) { -+ dst_release(skb->dst); -+ skb->dst = NULL; -+ } -+ skb->pkt_type = PACKET_HOST; -+ if(irs.hard_header_len && -+ (skb->mac.raw != (skb->data - irs.hard_header_len)) && -+ (irs.hard_header_len <= skb_headroom(skb))) { -+ /* copy back original MAC header */ -+ memmove(skb->data - irs.hard_header_len, skb->mac.raw, irs.hard_header_len); -+ skb->mac.raw = skb->data - irs.hard_header_len; -+ } -+#endif /* NET_21 */ -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+ if(ipp->protocol == IPPROTO_COMP) { -+ unsigned int flags = 0; -+ -+ if(sysctl_ipsec_inbound_policy_check) { -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "inbound policy checking enabled, IPCOMP follows IPIP, dropped.\n"); -+ if (stats) { -+ stats->rx_errors++; -+ } -+ goto rcvleave; -+ } -+ /* -+ XXX need a ipsec_sa for updating ratio counters but it is not -+ following policy anyways so it is not a priority -+ */ -+ skb = skb_decompress(skb, NULL, &flags); -+ if (!skb || flags) { -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "skb_decompress() returned error flags: %d, dropped.\n", -+ flags); -+ if (stats) { -+ stats->rx_errors++; -+ } -+ goto rcvleave; -+ } -+ } -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#ifdef SKB_RESET_NFCT -+ nf_conntrack_put(skb->nfct); -+ skb->nfct = NULL; -+#ifdef CONFIG_NETFILTER_DEBUG -+ skb->nf_debug = 0; -+#endif /* CONFIG_NETFILTER_DEBUG */ -+#endif /* SKB_RESET_NFCT */ -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "netif_rx() called.\n"); -+ netif_rx(skb); -+ -+ MOD_DEC_USE_COUNT; -+ return(0); -+ -+ rcvleave: -+ if(skb) { -+ ipsec_kfree_skb(skb); -+ } -+ -+ MOD_DEC_USE_COUNT; -+ return(0); -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.143.4.2 2004/08/22 03:29:06 mcr -+ * include udp.h regardless of nat-t support. -+ * -+ * Revision 1.143.4.1 2004/08/21 02:14:58 ken -+ * Patch from Jochen Eisinger for AT&T MTS Heartbeat packet support -+ * -+ * Revision 1.143 2004/05/10 22:27:00 mcr -+ * fix for ESP-3DES-noauth test case. -+ * -+ * Revision 1.142 2004/05/10 22:25:57 mcr -+ * reformat of calls to ipsec_lifetime_check(). -+ * -+ * Revision 1.141 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.140 2004/02/03 03:12:53 mcr -+ * removed erroneously, double patched code. -+ * -+ * Revision 1.139 2004/01/05 23:21:29 mcr -+ * initialize sin_family in ipsec_rcv.c -+ * -+ * Revision 1.138 2003/12/24 19:46:52 mcr -+ * if sock.h patch has not been applied, then define appropriate -+ * structure so we can use it. This is serious inferior, and -+ * depends upon the concept that the structure in question is -+ * smaller than the other members of that union. -+ * getting rid of differing methods is a better solution. -+ * -+ * Revision 1.137 2003/12/22 19:40:57 mcr -+ * NAT-T patches 0.6c. -+ * -+ * Revision 1.136 2003/12/15 18:13:12 mcr -+ * when compiling with NAT traversal, don't assume that the -+ * kernel has been patched, unless CONFIG_IPSEC_NAT_NON_ESP -+ * is set. -+ * -+ * Revision 1.135 2003/12/13 19:10:21 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.134.2.1 2003/12/22 15:25:52 jjo -+ * Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.134 2003/12/10 01:14:27 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.133 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.132.2.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.132 2003/09/02 19:51:48 mcr -+ * fixes for PR#252. -+ * -+ * Revision 1.131 2003/07/31 22:47:16 mcr -+ * preliminary (untested by FS-team) 2.5 patches. -+ * -+ * Revision 1.130 2003/04/03 17:38:25 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * Clarified logic for non-connected devices. -+ * -+ * Revision 1.129 2003/02/06 02:21:34 rgb -+ * -+ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h . -+ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr". -+ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code. -+ * -+ * Revision 1.128 2002/12/13 20:58:03 rgb -+ * Relegated MCR's recent "_dmp" routine to debug_verbose. -+ * Cleaned up printing of source and destination addresses in debug output. -+ * -+ * Revision 1.127 2002/12/04 16:00:16 rgb -+ * -+ * Fixed AH decapsulation pointer update bug and added some comments and -+ * debugging. -+ * This bug was caught by west-ah-0[12]. -+ * -+ * Revision 1.126 2002/11/04 05:03:43 mcr -+ * fixes for IPCOMP. There were two problems: -+ * 1) the irs->ipp pointer was not being updated properly after -+ * the ESP descryption. The meant nothing for IPIP, as the -+ * later IP header overwrote the earlier one. -+ * 2) the more serious problem was that skb_decompress will -+ * usually allocate a new SKB, so we have to make sure that -+ * it doesn't get lost. -+ * #2 meant removing the skb argument from the ->decrypt routine -+ * and moving it to the irs->skb, so it could be value/result. -+ * -+ * Revision 1.125 2002/11/01 01:53:35 dhr -+ * -+ * fix typo -+ * -+ * Revision 1.124 2002/10/31 22:49:01 dhr -+ * -+ * - eliminate unused variable "hash" -+ * - reduce scope of variable "authenticator" -+ * - add comment on a couple of tricky bits -+ * -+ * Revision 1.123 2002/10/31 22:39:56 dhr -+ * -+ * use correct type for result of function calls -+ * -+ * Revision 1.122 2002/10/31 22:36:25 dhr -+ * -+ * simplify complex test -+ * -+ * Revision 1.121 2002/10/31 22:34:04 dhr -+ * -+ * ipsprev is never used: ditch it -+ * -+ * Revision 1.120 2002/10/31 22:30:21 dhr -+ * -+ * eliminate redundant assignments -+ * -+ * Revision 1.119 2002/10/31 22:27:43 dhr -+ * -+ * make whitespace canonical -+ * -+ * Revision 1.118 2002/10/30 05:47:17 rgb -+ * Fixed cut-and-paste error mis-identifying comp runt as ah. -+ * -+ * Revision 1.117 2002/10/17 16:37:45 rgb -+ * Remove compp intermediate variable and in-line its contents -+ * where used -+ * -+ * Revision 1.116 2002/10/12 23:11:53 dhr -+ * -+ * [KenB + DHR] more 64-bit cleanup -+ * -+ * Revision 1.115 2002/10/07 19:06:58 rgb -+ * Minor fixups and activation to west-rcv-nfmark-set-01 test to check for SA reference properly set on incoming. -+ * -+ * Revision 1.114 2002/10/07 18:31:31 rgb -+ * Set saref on incoming packets. -+ * -+ * Revision 1.113 2002/09/16 21:28:12 mcr -+ * adjust hash length for HMAC calculation - must look at whether -+ * it is MD5 or SHA1. -+ * -+ * Revision 1.112 2002/09/16 21:19:15 mcr -+ * fixes for west-ah-icmp-01 - length of AH header must be -+ * calculated properly, and next_header field properly copied. -+ * -+ * Revision 1.111 2002/09/10 02:45:56 mcr -+ * re-factored the ipsec_rcv function into several functions, -+ * ipsec_rcv_decap_once, and a set of functions for AH, ESP and IPCOMP. -+ * In addition, the MD5 and SHA1 functions are replaced with pointers. -+ * -+ * Revision 1.110 2002/08/30 06:34:33 rgb -+ * Fix scope of shift in AH header length check. -+ * -+ * Revision 1.109 2002/08/27 16:49:20 rgb -+ * Fixed ESP short packet DOS (and AH and IPCOMP). -+ * -+ * Revision 1.108 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.107 2002/05/27 18:58:18 rgb -+ * Convert to dynamic ipsec device allocation. -+ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT. -+ * -+ * Revision 1.106 2002/05/23 07:15:21 rgb -+ * Pointer clean-up. -+ * Added refcount code. -+ * -+ * Revision 1.105 2002/05/14 02:35:06 rgb -+ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips, -+ * ipsec_sa or ipsec_sa. -+ * Change references to _TDB to _IPSA. -+ * -+ * Revision 1.104 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.103 2002/04/24 07:36:30 mcr -+ * Moved from ./klips/net/ipsec/ipsec_rcv.c,v -+ * -+ * Revision 1.102 2002/01/29 17:17:56 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.101 2002/01/29 04:00:52 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.100 2002/01/29 02:13:17 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.99 2002/01/28 21:40:59 mcr -+ * should use #if to test boolean option rather than #ifdef. -+ * -+ * Revision 1.98 2002/01/20 20:19:36 mcr -+ * renamed option to IP_FRAGMENT_LINEARIZE. -+ * -+ * Revision 1.97 2002/01/12 02:55:36 mcr -+ * fix for post-2.4.4 to linearize skb's when ESP packet -+ * was assembled from fragments. -+ * -+ * Revision 1.96 2001/11/26 09:23:49 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.93.2.2 2001/10/22 20:54:07 mcr -+ * include des.h, removed phony prototypes and fixed calling -+ * conventions to match real prototypes. -+ * -+ * Revision 1.93.2.1 2001/09/25 02:22:22 mcr -+ * struct tdb -> struct ipsec_sa. -+ * lifetime checks moved to ipsec_life.c -+ * some sa(tdb) manipulation functions renamed. -+ * -+ * Revision 1.95 2001/11/06 19:49:07 rgb -+ * Added variable descriptions. -+ * Removed unauthenticated sequence==0 check to prevent DoS. -+ * -+ * Revision 1.94 2001/10/18 04:45:20 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.93 2001/09/07 22:17:24 rgb -+ * Fix for removal of transport layer protocol handler arg in 2.4.4. -+ * Fix to accomodate peer non-conformance to IPCOMP rfc2393. -+ * -+ * Revision 1.92 2001/08/27 19:44:41 rgb -+ * Fix error in comment. -+ * -+ * Revision 1.91 2001/07/20 19:31:48 dhr -+ * [DHR] fix source and destination subnets of policy in diagnostic -+ * -+ * Revision 1.90 2001/07/06 19:51:09 rgb -+ * Added inbound policy checking code for IPIP SAs. -+ * Renamed unused function argument for ease and intuitive naming. -+ * -+ * Revision 1.89 2001/06/22 19:35:23 rgb -+ * Disable ipcomp processing if we are handed a ipcomp packet with no esp -+ * or ah header. -+ * Print protocol if we are handed a non-ipsec packet. -+ * -+ * Revision 1.88 2001/06/20 06:30:47 rgb -+ * Fixed transport mode IPCOMP policy check bug. -+ * -+ * Revision 1.87 2001/06/13 20:58:40 rgb -+ * Added parentheses around assignment used as truth value to silence -+ * compiler. -+ * -+ * Revision 1.86 2001/06/07 22:25:23 rgb -+ * Added a source address policy check for tunnel mode. It still does -+ * not check client addresses and masks. -+ * Only decapsulate IPIP if it is expected. -+ * -+ * Revision 1.85 2001/05/30 08:14:02 rgb -+ * Removed vestiges of esp-null transforms. -+ * -+ * Revision 1.84 2001/05/27 06:12:11 rgb -+ * Added structures for pid, packet count and last access time to eroute. -+ * Added packet count to beginning of /proc/net/ipsec_eroute. -+ * -+ * Revision 1.83 2001/05/04 16:45:47 rgb -+ * Remove unneeded code. ipp is not used after this point. -+ * -+ * Revision 1.82 2001/05/04 16:36:00 rgb -+ * Fix skb_cow() call for 2.4.4. (SS) -+ * -+ * Revision 1.81 2001/05/02 14:46:53 rgb -+ * Fix typo for compiler directive to pull IPH back. -+ * -+ * Revision 1.80 2001/04/30 19:46:34 rgb -+ * Update for 2.4.4. We now receive the skb with skb->data pointing to -+ * h.raw. -+ * -+ * Revision 1.79 2001/04/23 15:01:15 rgb -+ * Added spin_lock() check to prevent double-locking for multiple -+ * transforms and hence kernel lock-ups with SMP kernels. -+ * Minor spin_unlock() adjustments to unlock before non-dependant prints -+ * and IPSEC device stats updates. -+ * -+ * Revision 1.78 2001/04/21 23:04:24 rgb -+ * Check if soft expire has already been sent before sending another to -+ * prevent ACQUIRE flooding. -+ * -+ * Revision 1.77 2001/03/16 07:35:20 rgb -+ * Ditch extra #if 1 around now permanent policy checking code. -+ * -+ * Revision 1.76 2001/02/27 22:24:54 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.75 2001/02/19 22:28:30 rgb -+ * Minor change to virtual device discovery code to assert which I/F has -+ * been found. -+ * -+ * Revision 1.74 2000/11/25 03:50:36 rgb -+ * Oops fix by minor re-arrangement of code to avoid accessing a freed tdb. -+ * -+ * Revision 1.73 2000/11/09 20:52:15 rgb -+ * More spinlock shuffling, locking earlier and unlocking later in rcv to -+ * include ipcomp and prevent races, renaming some tdb variables that got -+ * forgotten, moving some unlocks to include tdbs and adding a missing -+ * unlock. Thanks to Svenning for some of these. -+ * -+ * Revision 1.72 2000/11/09 20:11:22 rgb -+ * Minor shuffles to fix non-standard kernel config option selection. -+ * -+ * Revision 1.71 2000/11/06 04:36:18 rgb -+ * Ditched spin_lock_irqsave in favour of spin_lock. -+ * Minor initial protocol check rewrite. -+ * Clean up debug printing. -+ * Clean up tdb handling on ipcomp. -+ * Fixed transport mode null pointer de-reference without ipcomp. -+ * Add Svenning's adaptive content compression. -+ * Disabled registration of ipcomp handler. -+ * -+ * Revision 1.70 2000/10/30 23:41:43 henry -+ * Hans-Joerg Hoexer's null-pointer fix -+ * -+ * Revision 1.69 2000/10/10 18:54:16 rgb -+ * Added a fix for incoming policy check with ipcomp enabled but -+ * uncompressible. -+ * -+ * Revision 1.68 2000/09/22 17:53:12 rgb -+ * Fixed ipcomp tdb pointers update for policy checking. -+ * -+ * Revision 1.67 2000/09/21 03:40:58 rgb -+ * Added more debugging to try and track down the cpi outward copy problem. -+ * -+ * Revision 1.66 2000/09/20 04:00:10 rgb -+ * Changed static functions to DEBUG_NO_STATIC to reveal function names for -+ * debugging oopsen. -+ * -+ * Revision 1.65 2000/09/19 07:07:16 rgb -+ * Added debugging to inbound policy check for ipcomp. -+ * Added missing spin_unlocks (thanks Svenning!). -+ * Fixed misplaced tdbnext pointers causing mismatched ipip policy check. -+ * Protect ipcomp policy check following ipip decap with sysctl switch. -+ * -+ * Revision 1.64 2000/09/18 21:27:29 rgb -+ * 2.0 fixes. -+ * -+ * Revision 1.63 2000/09/18 02:35:50 rgb -+ * Added policy checking to ipcomp and re-enabled policy checking by -+ * default. -+ * Optimised satoa calls. -+ * -+ * Revision 1.62 2000/09/17 21:02:32 rgb -+ * Clean up debugging, removing slow timestamp debug code. -+ * -+ * Revision 1.61 2000/09/16 01:07:55 rgb -+ * Fixed erroneous ref from struct ipcomp to struct ipcomphdr. -+ * -+ * Revision 1.60 2000/09/15 11:37:01 rgb -+ * Merge in heavily modified Svenning Soerensen's -+ * IPCOMP zlib deflate code. -+ * -+ * Revision 1.59 2000/09/15 04:56:20 rgb -+ * Remove redundant satoa() call, reformat comment. -+ * -+ * Revision 1.58 2000/09/13 08:00:52 rgb -+ * Flick on inbound policy checking. -+ * -+ * Revision 1.57 2000/09/12 03:22:19 rgb -+ * Converted inbound_policy_check to sysctl. -+ * Re-enabled policy backcheck. -+ * Moved policy checks to top and within tdb lock. -+ * -+ * Revision 1.56 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.55 2000/08/28 18:15:46 rgb -+ * Added MB's nf-debug reset patch. -+ * -+ * Revision 1.54 2000/08/27 01:41:26 rgb -+ * More minor tweaks to the bad padding debug code. -+ * -+ * Revision 1.53 2000/08/24 16:54:16 rgb -+ * Added KLIPS_PRINTMORE macro to continue lines without KERN_INFO level -+ * info. -+ * Tidied up device reporting at the start of ipsec_rcv. -+ * Tidied up bad padding debugging and processing. -+ * -+ * Revision 1.52 2000/08/20 21:36:03 rgb -+ * Activated pfkey_expire() calls. -+ * Added a hard/soft expiry parameter to pfkey_expire(). -+ * Added sanity checking to avoid propagating zero or smaller-length skbs -+ * from a bogus decryption. -+ * Re-arranged the order of soft and hard expiry to conform to RFC2367. -+ * Clean up references to CONFIG_IPSEC_PFKEYv2. -+ * -+ * Revision 1.51 2000/08/18 21:23:30 rgb -+ * Improve bad padding warning so that the printk buffer doesn't get -+ * trampled. -+ * -+ * Revision 1.50 2000/08/01 14:51:51 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.49 2000/07/28 13:50:53 rgb -+ * Changed enet_statistics to net_device_stats and added back compatibility -+ * for pre-2.1.19. -+ * -+ * Revision 1.48 2000/05/10 19:14:40 rgb -+ * Only check usetime against soft and hard limits if the tdb has been -+ * used. -+ * Cast output of ntohl so that the broken prototype doesn't make our -+ * compile noisy. -+ * -+ * Revision 1.47 2000/05/09 17:45:43 rgb -+ * Fix replay bitmap corruption bug upon receipt of bogus packet -+ * with correct SPI. This was a DoS. -+ * -+ * Revision 1.46 2000/03/27 02:31:58 rgb -+ * Fixed authentication failure printout bug. -+ * -+ * Revision 1.45 2000/03/22 16:15:37 rgb -+ * Fixed renaming of dev_get (MB). -+ * -+ * Revision 1.44 2000/03/16 08:17:24 rgb -+ * Hardcode PF_KEYv2 support. -+ * Fixed minor bug checking AH header length. -+ * -+ * Revision 1.43 2000/03/14 12:26:59 rgb -+ * Added skb->nfct support for clearing netfilter conntrack bits (MB). -+ * -+ * Revision 1.42 2000/01/26 10:04:04 rgb -+ * Fixed inbound policy checking on transport mode bug. -+ * Fixed noisy 2.0 printk arguments. -+ * -+ * Revision 1.41 2000/01/24 20:58:02 rgb -+ * Improve debugging/reporting support for (disabled) inbound -+ * policy checking. -+ * -+ * Revision 1.40 2000/01/22 23:20:10 rgb -+ * Fixed up inboud policy checking code. -+ * Cleaned out unused crud. -+ * -+ * Revision 1.39 2000/01/21 06:15:29 rgb -+ * Added sanity checks on skb_push(), skb_pull() to prevent panics. -+ * Fixed cut-and-paste debug_tunnel to debug_rcv. -+ * Added inbound policy checking code, disabled. -+ * Simplified output code by updating ipp to post-IPIP decapsulation. -+ * -+ * elided pre-2000 comments. Use "cvs log" -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_sa.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1383 @@ -+/* -+ * Common routines for IPsec SA maintenance routines. -+ * -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ * This is the file formerly known as "ipsec_xform.h" -+ * -+ */ -+ -+#include -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* vmalloc() */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#ifdef SPINLOCK -+#ifdef SPINLOCK_23 -+#include /* *lock* */ -+#else /* SPINLOCK_23 */ -+#include /* *lock* */ -+#endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+#include -+#include -+#endif -+#include -+#include -+ -+#include "openswan/radij.h" -+ -+#include "openswan/ipsec_stats.h" -+#include "openswan/ipsec_life.h" -+#include "openswan/ipsec_sa.h" -+#include "openswan/ipsec_xform.h" -+ -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_ipe4.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+#include "openswan/ipsec_alg.h" -+ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_xform = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) -+ -+struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD]; -+#ifdef SPINLOCK -+spinlock_t tdb_lock = SPIN_LOCK_UNLOCKED; -+#else /* SPINLOCK */ -+spinlock_t tdb_lock; -+#endif /* SPINLOCK */ -+ -+struct ipsec_sadb ipsec_sadb; -+ -+#if IPSEC_SA_REF_CODE -+ -+/* the sub table must be narrower (or equal) in bits than the variable type -+ in the main table to count the number of unused entries in it. */ -+typedef struct { -+ int testSizeOf_refSubTable : -+ ((sizeof(IPsecRefTableUnusedCount) * 8) < IPSEC_SA_REF_SUBTABLE_IDX_WIDTH ? -1 : 1); -+} dummy; -+ -+ -+/* The field where the saref will be hosted in the skb must be wide enough to -+ accomodate the information it needs to store. */ -+typedef struct { -+ int testSizeOf_refField : -+ (IPSEC_SA_REF_HOST_FIELD_WIDTH < IPSEC_SA_REF_TABLE_IDX_WIDTH ? -1 : 1 ); -+} dummy2; -+ -+ -+#define IPS_HASH(said) (((said)->spi + (said)->dst.u.v4.sin_addr.s_addr + (said)->proto) % SADB_HASHMOD) -+ -+ -+void -+ipsec_SAtest(void) -+{ -+ IPsecSAref_t SAref = 258; -+ struct ipsec_sa ips; -+ ips.ips_ref = 772; -+ -+ printk("klips_debug:ipsec_SAtest: " -+ "IPSEC_SA_REF_SUBTABLE_IDX_WIDTH=%u\n" -+ "IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES=%u\n" -+ "IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES=%u\n" -+ "IPSEC_SA_REF_HOST_FIELD_WIDTH=%lu\n" -+ "IPSEC_SA_REF_TABLE_MASK=%x\n" -+ "IPSEC_SA_REF_ENTRY_MASK=%x\n" -+ "IPsecSAref2table(%d)=%u\n" -+ "IPsecSAref2entry(%d)=%u\n" -+ "IPsecSAref2NFmark(%d)=%u\n" -+ "IPsecSAref2SA(%d)=%p\n" -+ "IPsecSA2SAref(%p)=%d\n" -+ , -+ IPSEC_SA_REF_SUBTABLE_IDX_WIDTH, -+ IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES, -+ IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES, -+ (unsigned long) IPSEC_SA_REF_HOST_FIELD_WIDTH, -+ IPSEC_SA_REF_TABLE_MASK, -+ IPSEC_SA_REF_ENTRY_MASK, -+ SAref, IPsecSAref2table(SAref), -+ SAref, IPsecSAref2entry(SAref), -+ SAref, IPsecSAref2NFmark(SAref), -+ SAref, IPsecSAref2SA(SAref), -+ (&ips), IPsecSA2SAref((&ips)) -+ ); -+ return; -+} -+ -+int -+ipsec_SAref_recycle(void) -+{ -+ int table; -+ int entry; -+ int error = 0; -+ -+ ipsec_sadb.refFreeListHead = -1; -+ ipsec_sadb.refFreeListTail = -1; -+ -+ if(ipsec_sadb.refFreeListCont == IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES * IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_recycle: " -+ "end of table reached, continuing at start..\n"); -+ ipsec_sadb.refFreeListCont = 0; -+ } -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_recycle: " -+ "recycling, continuing from SAref=%d (0p%p), table=%d, entry=%d.\n", -+ ipsec_sadb.refFreeListCont, -+ (ipsec_sadb.refTable[IPsecSAref2table(ipsec_sadb.refFreeListCont)] != NULL) ? IPsecSAref2SA(ipsec_sadb.refFreeListCont) : NULL, -+ IPsecSAref2table(ipsec_sadb.refFreeListCont), -+ IPsecSAref2entry(ipsec_sadb.refFreeListCont)); -+ -+ for(table = IPsecSAref2table(ipsec_sadb.refFreeListCont); -+ table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; -+ table++) { -+ if(ipsec_sadb.refTable[table] == NULL) { -+ error = ipsec_SArefSubTable_alloc(table); -+ if(error) { -+ return error; -+ } -+ } -+ for(entry = IPsecSAref2entry(ipsec_sadb.refFreeListCont); -+ entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; -+ entry++) { -+ if(ipsec_sadb.refTable[table]->entry[entry] == NULL) { -+ ipsec_sadb.refFreeList[++ipsec_sadb.refFreeListTail] = IPsecSArefBuild(table, entry); -+ if(ipsec_sadb.refFreeListTail == (IPSEC_SA_REF_FREELIST_NUM_ENTRIES - 1)) { -+ ipsec_sadb.refFreeListHead = 0; -+ ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListTail] + 1; -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_recycle: " -+ "SArefFreeList refilled.\n"); -+ return 0; -+ } -+ } -+ } -+ } -+ -+ if(ipsec_sadb.refFreeListTail == -1) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_recycle: " -+ "out of room in the SArefTable.\n"); -+ -+ return(-ENOSPC); -+ } -+ -+ ipsec_sadb.refFreeListHead = 0; -+ ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListTail] + 1; -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_recycle: " -+ "SArefFreeList partly refilled to %d of %d.\n", -+ ipsec_sadb.refFreeListTail, -+ IPSEC_SA_REF_FREELIST_NUM_ENTRIES); -+ return 0; -+} -+ -+int -+ipsec_SArefSubTable_alloc(unsigned table) -+{ -+ unsigned entry; -+ struct IPsecSArefSubTable* SArefsub; -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SArefSubTable_alloc: " -+ "allocating %lu bytes for table %u of %u.\n", -+ (unsigned long) (IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES * sizeof(struct ipsec_sa *)), -+ table, -+ IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES); -+ -+ /* allocate another sub-table */ -+ SArefsub = vmalloc(IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES * sizeof(struct ipsec_sa *)); -+ if(SArefsub == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SArefSubTable_alloc: " -+ "error allocating memory for table %u of %u!\n", -+ table, -+ IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES); -+ return -ENOMEM; -+ } -+ -+ /* add this sub-table to the main table */ -+ ipsec_sadb.refTable[table] = SArefsub; -+ -+ /* initialise each element to NULL */ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SArefSubTable_alloc: " -+ "initialising %u elements (2 ^ %u) of table %u.\n", -+ IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES, -+ IPSEC_SA_REF_SUBTABLE_IDX_WIDTH, -+ table); -+ for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { -+ SArefsub->entry[entry] = NULL; -+ } -+ -+ return 0; -+} -+#endif /* IPSEC_SA_REF_CODE */ -+ -+int -+ipsec_saref_freelist_init(void) -+{ -+ int i; -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_saref_freelist_init: " -+ "initialising %u elements of FreeList.\n", -+ IPSEC_SA_REF_FREELIST_NUM_ENTRIES); -+ -+ for(i = 0; i < IPSEC_SA_REF_FREELIST_NUM_ENTRIES; i++) { -+ ipsec_sadb.refFreeList[i] = IPSEC_SAREF_NULL; -+ } -+ ipsec_sadb.refFreeListHead = -1; -+ ipsec_sadb.refFreeListCont = 0; -+ ipsec_sadb.refFreeListTail = -1; -+ -+ return 0; -+} -+ -+int -+ipsec_sadb_init(void) -+{ -+ int error = 0; -+ unsigned i; -+ -+ for(i = 0; i < SADB_HASHMOD; i++) { -+ ipsec_sadb_hash[i] = NULL; -+ } -+ /* parts above are for the old style SADB hash table */ -+ -+ -+#if IPSEC_SA_REF_CODE -+ /* initialise SA reference table */ -+ -+ /* initialise the main table */ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_init: " -+ "initialising main table of size %u (2 ^ %u).\n", -+ IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES, -+ IPSEC_SA_REF_MAINTABLE_IDX_WIDTH); -+ { -+ unsigned table; -+ for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { -+ ipsec_sadb.refTable[table] = NULL; -+ } -+ } -+ -+ /* allocate the first sub-table */ -+ error = ipsec_SArefSubTable_alloc(0); -+ if(error) { -+ return error; -+ } -+ -+ error = ipsec_saref_freelist_init(); -+#endif /* IPSEC_SA_REF_CODE */ -+ return error; -+} -+ -+#if IPSEC_SA_REF_CODE -+IPsecSAref_t -+ipsec_SAref_alloc(int*error) /* pass in error var by pointer */ -+{ -+ IPsecSAref_t SAref; -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_alloc: " -+ "SAref requested... head=%d, cont=%d, tail=%d, listsize=%d.\n", -+ ipsec_sadb.refFreeListHead, -+ ipsec_sadb.refFreeListCont, -+ ipsec_sadb.refFreeListTail, -+ IPSEC_SA_REF_FREELIST_NUM_ENTRIES); -+ -+ if(ipsec_sadb.refFreeListHead == -1) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_alloc: " -+ "FreeList empty, recycling...\n"); -+ *error = ipsec_SAref_recycle(); -+ if(*error) { -+ return IPSEC_SAREF_NULL; -+ } -+ } -+ -+ SAref = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListHead]; -+ if(SAref == IPSEC_SAREF_NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_alloc: " -+ "unexpected error, refFreeListHead = %d points to invalid entry.\n", -+ ipsec_sadb.refFreeListHead); -+ *error = -ESPIPE; -+ return IPSEC_SAREF_NULL; -+ } -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_alloc: " -+ "allocating SAref=%d, table=%u, entry=%u of %u.\n", -+ SAref, -+ IPsecSAref2table(SAref), -+ IPsecSAref2entry(SAref), -+ IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES * IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES); -+ -+ ipsec_sadb.refFreeList[ipsec_sadb.refFreeListHead] = IPSEC_SAREF_NULL; -+ ipsec_sadb.refFreeListHead++; -+ if(ipsec_sadb.refFreeListHead > ipsec_sadb.refFreeListTail) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_alloc: " -+ "last FreeList entry allocated, resetting list head to empty.\n"); -+ ipsec_sadb.refFreeListHead = -1; -+ } -+ -+ return SAref; -+} -+#endif /* IPSEC_SA_REF_CODE */ -+ -+int -+ipsec_sa_print(struct ipsec_sa *ips) -+{ -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ printk(KERN_INFO "klips_debug: SA:"); -+ if(ips == NULL) { -+ printk("NULL\n"); -+ return -ENOENT; -+ } -+ printk(" ref=%d", ips->ips_ref); -+ printk(" refcount=%d", atomic_read(&ips->ips_refcount)); -+ if(ips->ips_hnext != NULL) { -+ printk(" hnext=0p%p", ips->ips_hnext); -+ } -+ if(ips->ips_inext != NULL) { -+ printk(" inext=0p%p", ips->ips_inext); -+ } -+ if(ips->ips_onext != NULL) { -+ printk(" onext=0p%p", ips->ips_onext); -+ } -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ printk(" said=%s", sa_len ? sa : " (error)"); -+ if(ips->ips_seq) { -+ printk(" seq=%u", ips->ips_seq); -+ } -+ if(ips->ips_pid) { -+ printk(" pid=%u", ips->ips_pid); -+ } -+ if(ips->ips_authalg) { -+ printk(" authalg=%u", ips->ips_authalg); -+ } -+ if(ips->ips_encalg) { -+ printk(" encalg=%u", ips->ips_encalg); -+ } -+ printk(" XFORM=%s%s%s", IPS_XFORM_NAME(ips)); -+ if(ips->ips_replaywin) { -+ printk(" ooowin=%u", ips->ips_replaywin); -+ } -+ if(ips->ips_flags) { -+ printk(" flags=%u", ips->ips_flags); -+ } -+ if(ips->ips_addr_s) { -+ char buf[SUBNETTOA_BUF]; -+ addrtoa(((struct sockaddr_in*)(ips->ips_addr_s))->sin_addr, -+ 0, buf, sizeof(buf)); -+ printk(" src=%s", buf); -+ } -+ if(ips->ips_addr_d) { -+ char buf[SUBNETTOA_BUF]; -+ addrtoa(((struct sockaddr_in*)(ips->ips_addr_s))->sin_addr, -+ 0, buf, sizeof(buf)); -+ printk(" dst=%s", buf); -+ } -+ if(ips->ips_addr_p) { -+ char buf[SUBNETTOA_BUF]; -+ addrtoa(((struct sockaddr_in*)(ips->ips_addr_p))->sin_addr, -+ 0, buf, sizeof(buf)); -+ printk(" proxy=%s", buf); -+ } -+ if(ips->ips_key_bits_a) { -+ printk(" key_bits_a=%u", ips->ips_key_bits_a); -+ } -+ if(ips->ips_key_bits_e) { -+ printk(" key_bits_e=%u", ips->ips_key_bits_e); -+ } -+ -+ printk("\n"); -+ return 0; -+} -+ -+struct ipsec_sa* -+ipsec_sa_alloc(int*error) /* pass in error var by pointer */ -+{ -+ struct ipsec_sa* ips; -+ -+ if((ips = kmalloc(sizeof(*ips), GFP_ATOMIC) ) == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_alloc: " -+ "memory allocation error\n"); -+ *error = -ENOMEM; -+ return NULL; -+ } -+ memset((caddr_t)ips, 0, sizeof(*ips)); -+#if IPSEC_SA_REF_CODE -+ ips->ips_ref = ipsec_SAref_alloc(error); /* pass in error return by pointer */ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_alloc: " -+ "allocated %lu bytes for ipsec_sa struct=0p%p ref=%d.\n", -+ (unsigned long) sizeof(*ips), -+ ips, -+ ips->ips_ref); -+ if(ips->ips_ref == IPSEC_SAREF_NULL) { -+ kfree(ips); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_alloc: " -+ "SAref allocation error\n"); -+ return NULL; -+ } -+ -+ atomic_inc(&ips->ips_refcount); -+ IPsecSAref2SA(ips->ips_ref) = ips; -+#endif /* IPSEC_SA_REF_CODE */ -+ -+ *error = 0; -+ return(ips); -+} -+ -+int -+ipsec_sa_free(struct ipsec_sa* ips) -+{ -+ return ipsec_sa_wipe(ips); -+} -+ -+struct ipsec_sa * -+ipsec_sa_getbyid(ip_said *said) -+{ -+ int hashval; -+ struct ipsec_sa *ips; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ if(said == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_error:ipsec_sa_getbyid: " -+ "null pointer passed in!\n"); -+ return NULL; -+ } -+ -+ sa_len = satot(said, 0, sa, sizeof(sa)); -+ -+ hashval = IPS_HASH(said); -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_getbyid: " -+ "linked entry in ipsec_sa table for hash=%d of SA:%s requested.\n", -+ hashval, -+ sa_len ? sa : " (error)"); -+ -+ if((ips = ipsec_sadb_hash[hashval]) == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_getbyid: " -+ "no entries in ipsec_sa table for hash=%d of SA:%s.\n", -+ hashval, -+ sa_len ? sa : " (error)"); -+ return NULL; -+ } -+ -+ for (; ips; ips = ips->ips_hnext) { -+ if ((ips->ips_said.spi == said->spi) && -+ (ips->ips_said.dst.u.v4.sin_addr.s_addr == said->dst.u.v4.sin_addr.s_addr) && -+ (ips->ips_said.proto == said->proto)) { -+ atomic_inc(&ips->ips_refcount); -+ return ips; -+ } -+ } -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_getbyid: " -+ "no entry in linked list for hash=%d of SA:%s.\n", -+ hashval, -+ sa_len ? sa : " (error)"); -+ return NULL; -+} -+ -+int -+ipsec_sa_put(struct ipsec_sa *ips) -+{ -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ if(ips == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_error:ipsec_sa_put: " -+ "null pointer passed in!\n"); -+ return -1; -+ } -+ -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_put: " -+ "ipsec_sa SA:%s, ref:%d reference count decremented.\n", -+ sa_len ? sa : " (error)", -+ ips->ips_ref); -+ -+ atomic_dec(&ips->ips_refcount); -+ -+ return 0; -+} -+ -+/* -+ The ipsec_sa table better *NOT* be locked before it is handed in, or SMP locks will happen -+*/ -+int -+ipsec_sa_add(struct ipsec_sa *ips) -+{ -+ int error = 0; -+ unsigned int hashval; -+ -+ if(ips == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_error:ipsec_sa_add: " -+ "null pointer passed in!\n"); -+ return -ENODATA; -+ } -+ hashval = IPS_HASH(&ips->ips_said); -+ -+ atomic_inc(&ips->ips_refcount); -+ spin_lock_bh(&tdb_lock); -+ -+ ips->ips_hnext = ipsec_sadb_hash[hashval]; -+ ipsec_sadb_hash[hashval] = ips; -+ -+ spin_unlock_bh(&tdb_lock); -+ -+ return error; -+} -+ -+/* -+ The ipsec_sa table better be locked before it is handed in, or races might happen -+*/ -+int -+ipsec_sa_del(struct ipsec_sa *ips) -+{ -+ unsigned int hashval; -+ struct ipsec_sa *ipstp; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ if(ips == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_error:ipsec_sa_del: " -+ "null pointer passed in!\n"); -+ return -ENODATA; -+ } -+ -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ if(ips->ips_inext || ips->ips_onext) { -+ KLIPS_PRINT(debug_xform, -+ "klips_error:ipsec_sa_del: " -+ "SA:%s still linked!\n", -+ sa_len ? sa : " (error)"); -+ return -EMLINK; -+ } -+ -+ hashval = IPS_HASH(&ips->ips_said); -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_del: " -+ "deleting SA:%s, hashval=%d.\n", -+ sa_len ? sa : " (error)", -+ hashval); -+ if(ipsec_sadb_hash[hashval] == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_del: " -+ "no entries in ipsec_sa table for hash=%d of SA:%s.\n", -+ hashval, -+ sa_len ? sa : " (error)"); -+ return -ENOENT; -+ } -+ -+ if (ips == ipsec_sadb_hash[hashval]) { -+ ipsec_sadb_hash[hashval] = ipsec_sadb_hash[hashval]->ips_hnext; -+ ips->ips_hnext = NULL; -+ atomic_dec(&ips->ips_refcount); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_del: " -+ "successfully deleted first ipsec_sa in chain.\n"); -+ return 0; -+ } else { -+ for (ipstp = ipsec_sadb_hash[hashval]; -+ ipstp; -+ ipstp = ipstp->ips_hnext) { -+ if (ipstp->ips_hnext == ips) { -+ ipstp->ips_hnext = ips->ips_hnext; -+ ips->ips_hnext = NULL; -+ atomic_dec(&ips->ips_refcount); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_del: " -+ "successfully deleted link in ipsec_sa chain.\n"); -+ return 0; -+ } -+ } -+ } -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_del: " -+ "no entries in linked list for hash=%d of SA:%s.\n", -+ hashval, -+ sa_len ? sa : " (error)"); -+ return -ENOENT; -+} -+ -+/* -+ The ipsec_sa table better be locked before it is handed in, or races -+ might happen -+*/ -+int -+ipsec_sa_delchain(struct ipsec_sa *ips) -+{ -+ struct ipsec_sa *ipsdel; -+ int error = 0; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ if(ips == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_error:ipsec_sa_delchain: " -+ "null pointer passed in!\n"); -+ return -ENODATA; -+ } -+ -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_delchain: " -+ "passed SA:%s\n", -+ sa_len ? sa : " (error)"); -+ while(ips->ips_onext != NULL) { -+ ips = ips->ips_onext; -+ } -+ -+ while(ips) { -+ /* XXX send a pfkey message up to advise of deleted ipsec_sa */ -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_delchain: " -+ "unlinking and delting SA:%s", -+ sa_len ? sa : " (error)"); -+ ipsdel = ips; -+ ips = ips->ips_inext; -+ if(ips != NULL) { -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ ", inext=%s", -+ sa_len ? sa : " (error)"); -+ atomic_dec(&ipsdel->ips_refcount); -+ ipsdel->ips_inext = NULL; -+ atomic_dec(&ips->ips_refcount); -+ ips->ips_onext = NULL; -+ } -+ KLIPS_PRINT(debug_xform, -+ ".\n"); -+ if((error = ipsec_sa_del(ipsdel))) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_delchain: " -+ "ipsec_sa_del returned error %d.\n", -error); -+ return error; -+ } -+ if((error = ipsec_sa_wipe(ipsdel))) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_delchain: " -+ "ipsec_sa_wipe returned error %d.\n", -error); -+ return error; -+ } -+ } -+ return error; -+} -+ -+int -+ipsec_sadb_cleanup(__u8 proto) -+{ -+ unsigned i; -+ int error = 0; -+ struct ipsec_sa *ips, **ipsprev, *ipsdel; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_cleanup: " -+ "cleaning up proto=%d.\n", -+ proto); -+ -+ spin_lock_bh(&tdb_lock); -+ -+ for (i = 0; i < SADB_HASHMOD; i++) { -+ ipsprev = &(ipsec_sadb_hash[i]); -+ ips = ipsec_sadb_hash[i]; -+ if(ips != NULL) { -+ atomic_inc(&ips->ips_refcount); -+ } -+ for(; ips != NULL;) { -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_cleanup: " -+ "checking SA:%s, hash=%d, ref=%d", -+ sa_len ? sa : " (error)", -+ i, -+ ips->ips_ref); -+ ipsdel = ips; -+ ips = ipsdel->ips_hnext; -+ if(ips != NULL) { -+ atomic_inc(&ips->ips_refcount); -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ ", hnext=%s", -+ sa_len ? sa : " (error)"); -+ } -+ if(*ipsprev != NULL) { -+ sa_len = satot(&(*ipsprev)->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ ", *ipsprev=%s", -+ sa_len ? sa : " (error)"); -+ if((*ipsprev)->ips_hnext) { -+ sa_len = satot(&(*ipsprev)->ips_hnext->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ ", *ipsprev->ips_hnext=%s", -+ sa_len ? sa : " (error)"); -+ } -+ } -+ KLIPS_PRINT(debug_xform, -+ ".\n"); -+ if(proto == 0 || (proto == ipsdel->ips_said.proto)) { -+ sa_len = satot(&ipsdel->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_cleanup: " -+ "deleting SA chain:%s.\n", -+ sa_len ? sa : " (error)"); -+ if((error = ipsec_sa_delchain(ipsdel))) { -+ SENDERR(-error); -+ } -+ ipsprev = &(ipsec_sadb_hash[i]); -+ ips = ipsec_sadb_hash[i]; -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_cleanup: " -+ "deleted SA chain:%s", -+ sa_len ? sa : " (error)"); -+ if(ips != NULL) { -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ ", ipsec_sadb_hash[%d]=%s", -+ i, -+ sa_len ? sa : " (error)"); -+ } -+ if(*ipsprev != NULL) { -+ sa_len = satot(&(*ipsprev)->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ ", *ipsprev=%s", -+ sa_len ? sa : " (error)"); -+ if((*ipsprev)->ips_hnext != NULL) { -+ sa_len = satot(&(*ipsprev)->ips_hnext->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ ", *ipsprev->ips_hnext=%s", -+ sa_len ? sa : " (error)"); -+ } -+ } -+ KLIPS_PRINT(debug_xform, -+ ".\n"); -+ } else { -+ ipsprev = &ipsdel; -+ } -+ if(ipsdel != NULL) { -+ ipsec_sa_put(ipsdel); -+ } -+ } -+ } -+ errlab: -+ -+ spin_unlock_bh(&tdb_lock); -+ -+ -+#if IPSEC_SA_REF_CODE -+ /* clean up SA reference table */ -+ -+ /* go through the ref table and clean out all the SAs */ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_cleanup: " -+ "removing SAref entries and tables."); -+ { -+ unsigned table, entry; -+ for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_cleanup: " -+ "cleaning SAref table=%u.\n", -+ table); -+ if(ipsec_sadb.refTable[table] == NULL) { -+ printk("\n"); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_cleanup: " -+ "cleaned %u used refTables.\n", -+ table); -+ break; -+ } -+ for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { -+ if(ipsec_sadb.refTable[table]->entry[entry] != NULL) { -+ ipsec_sa_delchain(ipsec_sadb.refTable[table]->entry[entry]); -+ ipsec_sadb.refTable[table]->entry[entry] = NULL; -+ } -+ } -+ } -+ } -+#endif /* IPSEC_SA_REF_CODE */ -+ -+ return(error); -+} -+ -+int -+ipsec_sadb_free(void) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_free: " -+ "freeing SArefTable memory.\n"); -+ -+ /* clean up SA reference table */ -+ -+ /* go through the ref table and clean out all the SAs if any are -+ left and free table memory */ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_free: " -+ "removing SAref entries and tables.\n"); -+ { -+ unsigned table, entry; -+ for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_free: " -+ "removing SAref table=%u.\n", -+ table); -+ if(ipsec_sadb.refTable[table] == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_free: " -+ "removed %u used refTables.\n", -+ table); -+ break; -+ } -+ for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { -+ if(ipsec_sadb.refTable[table]->entry[entry] != NULL) { -+ ipsec_sa_delchain(ipsec_sadb.refTable[table]->entry[entry]); -+ ipsec_sadb.refTable[table]->entry[entry] = NULL; -+ } -+ } -+ vfree(ipsec_sadb.refTable[table]); -+ ipsec_sadb.refTable[table] = NULL; -+ } -+ } -+ -+ return(error); -+} -+ -+int -+ipsec_sa_wipe(struct ipsec_sa *ips) -+{ -+ if(ips == NULL) { -+ return -ENODATA; -+ } -+ -+ /* if(atomic_dec_and_test(ips)) { -+ }; */ -+ -+#if IPSEC_SA_REF_CODE -+ /* remove me from the SArefTable */ -+ { -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_wipe: " -+ "removing SA=%s(0p%p), SAref=%d, table=%d(0p%p), entry=%d from the refTable.\n", -+ sa_len ? sa : " (error)", -+ ips, -+ ips->ips_ref, -+ IPsecSAref2table(IPsecSA2SAref(ips)), -+ ipsec_sadb.refTable[IPsecSAref2table(IPsecSA2SAref(ips))], -+ IPsecSAref2entry(IPsecSA2SAref(ips))); -+ } -+ if(ips->ips_ref == IPSEC_SAREF_NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_wipe: " -+ "why does this SA not have a valid SAref?.\n"); -+ } -+ ipsec_sadb.refTable[IPsecSAref2table(IPsecSA2SAref(ips))]->entry[IPsecSAref2entry(IPsecSA2SAref(ips))] = NULL; -+ ips->ips_ref = IPSEC_SAREF_NULL; -+ ipsec_sa_put(ips); -+#endif /* IPSEC_SA_REF_CODE */ -+ -+ /* paranoid clean up */ -+ if(ips->ips_addr_s != NULL) { -+ memset((caddr_t)(ips->ips_addr_s), 0, ips->ips_addr_s_size); -+ kfree(ips->ips_addr_s); -+ } -+ ips->ips_addr_s = NULL; -+ -+ if(ips->ips_addr_d != NULL) { -+ memset((caddr_t)(ips->ips_addr_d), 0, ips->ips_addr_d_size); -+ kfree(ips->ips_addr_d); -+ } -+ ips->ips_addr_d = NULL; -+ -+ if(ips->ips_addr_p != NULL) { -+ memset((caddr_t)(ips->ips_addr_p), 0, ips->ips_addr_p_size); -+ kfree(ips->ips_addr_p); -+ } -+ ips->ips_addr_p = NULL; -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if(ips->ips_natt_oa) { -+ memset((caddr_t)(ips->ips_natt_oa), 0, ips->ips_natt_oa_size); -+ kfree(ips->ips_natt_oa); -+ } -+ ips->ips_natt_oa = NULL; -+#endif -+ -+ if(ips->ips_key_a != NULL) { -+ memset((caddr_t)(ips->ips_key_a), 0, ips->ips_key_a_size); -+ kfree(ips->ips_key_a); -+ } -+ ips->ips_key_a = NULL; -+ -+ if(ips->ips_key_e != NULL) { -+#ifdef CONFIG_IPSEC_ALG -+ if (ips->ips_alg_enc&&ips->ips_alg_enc->ixt_e_destroy_key) { -+ ips->ips_alg_enc->ixt_e_destroy_key(ips->ips_alg_enc, -+ ips->ips_key_e); -+ } else { -+#endif /* CONFIG_IPSEC_ALG */ -+ memset((caddr_t)(ips->ips_key_e), 0, ips->ips_key_e_size); -+ kfree(ips->ips_key_e); -+#ifdef CONFIG_IPSEC_ALG -+ } -+#endif /* CONFIG_IPSEC_ALG */ -+ } -+ ips->ips_key_e = NULL; -+ -+ if(ips->ips_iv != NULL) { -+ memset((caddr_t)(ips->ips_iv), 0, ips->ips_iv_size); -+ kfree(ips->ips_iv); -+ } -+ ips->ips_iv = NULL; -+ -+ if(ips->ips_ident_s.data != NULL) { -+ memset((caddr_t)(ips->ips_ident_s.data), -+ 0, -+ ips->ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); -+ kfree(ips->ips_ident_s.data); -+ } -+ ips->ips_ident_s.data = NULL; -+ -+ if(ips->ips_ident_d.data != NULL) { -+ memset((caddr_t)(ips->ips_ident_d.data), -+ 0, -+ ips->ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); -+ kfree(ips->ips_ident_d.data); -+ } -+ ips->ips_ident_d.data = NULL; -+ -+#ifdef CONFIG_IPSEC_ALG -+ if (ips->ips_alg_enc||ips->ips_alg_auth) { -+ ipsec_alg_sa_wipe(ips); -+ } -+#endif /* CONFIG_IPSEC_ALG */ -+ -+ memset((caddr_t)ips, 0, sizeof(*ips)); -+ kfree(ips); -+ ips = NULL; -+ -+ return 0; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.23 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.22.2.1 2003/12/22 15:25:52 jjo -+ * . Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.22 2003/12/10 01:14:27 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.21 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.20.4.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.20 2003/02/06 01:50:34 rgb -+ * Fixed initialisation bug for first sadb hash bucket that would only manifest itself on platforms where NULL != 0. -+ * -+ * Revision 1.19 2003/01/30 02:32:22 rgb -+ * -+ * Rename SAref table macro names for clarity. -+ * Transmit error code through to caller from callee for better diagnosis of problems. -+ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. -+ * -+ * Revision 1.18 2002/10/12 23:11:53 dhr -+ * -+ * [KenB + DHR] more 64-bit cleanup -+ * -+ * Revision 1.17 2002/10/07 18:31:43 rgb -+ * Move field width sanity checks to ipsec_sa.c -+ * -+ * Revision 1.16 2002/09/20 15:41:02 rgb -+ * Re-wrote most of the SAref code to eliminate Entry pointers. -+ * Added SAref code compiler directive switch. -+ * Added a saref test function for testing macros. -+ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc(). -+ * Split ipsec_sadb_cleanup from new funciton ipsec_sadb_free to avoid problem -+ * of freeing newly created structures when clearing the reftable upon startup -+ * to start from a known state. -+ * Place all ipsec sadb globals into one struct. -+ * Rework saref freelist. -+ * Added memory allocation debugging. -+ * -+ * Revision 1.15 2002/09/20 05:01:44 rgb -+ * Update copyright date. -+ * -+ * Revision 1.14 2002/08/13 19:01:25 mcr -+ * patches from kenb to permit compilation of FreeSWAN on ia64. -+ * des library patched to use proper DES_LONG type for ia64. -+ * -+ * Revision 1.13 2002/07/29 03:06:20 mcr -+ * get rid of variable not used warnings. -+ * -+ * Revision 1.12 2002/07/26 08:48:31 rgb -+ * Added SA ref table code. -+ * -+ * Revision 1.11 2002/06/04 16:48:49 rgb -+ * Tidied up pointer code for processor independance. -+ * -+ * Revision 1.10 2002/05/23 07:16:17 rgb -+ * Added ipsec_sa_put() for releasing an ipsec_sa refcount. -+ * Pointer clean-up. -+ * Added refcount code. -+ * Convert "usecount" to "refcount" to remove ambiguity. -+ * -+ * Revision 1.9 2002/05/14 02:34:49 rgb -+ * Converted reference from ipsec_sa_put to ipsec_sa_add to avoid confusion -+ * with "put" usage in the kernel. -+ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips, -+ * ipsec_sa or ipsec_sa. -+ * Added some preliminary refcount code. -+ * -+ * Revision 1.8 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.7 2002/04/24 07:36:30 mcr -+ * Moved from ./klips/net/ipsec/ipsec_sa.c,v -+ * -+ * Revision 1.6 2002/04/20 00:12:25 rgb -+ * Added esp IV CBC attack fix, disabled. -+ * -+ * Revision 1.5 2002/01/29 17:17:56 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.4 2002/01/29 04:00:52 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.3 2002/01/29 02:13:18 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.2 2001/11/26 09:16:15 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.2 2001/10/22 21:05:41 mcr -+ * removed phony prototype for des_set_key. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:24:57 mcr -+ * struct tdb -> struct ipsec_sa. -+ * sa(tdb) manipulation functions renamed and moved to ipsec_sa.c -+ * ipsec_xform.c removed. header file still contains useful things. -+ * -+ * -+ * -+ * CLONED from ipsec_xform.c: -+ * Revision 1.53 2001/09/08 21:13:34 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.52 2001/06/14 19:35:11 rgb -+ * Update copyright date. -+ * -+ * Revision 1.51 2001/05/30 08:14:03 rgb -+ * Removed vestiges of esp-null transforms. -+ * -+ * Revision 1.50 2001/05/03 19:43:18 rgb -+ * Initialise error return variable. -+ * Update SENDERR macro. -+ * Fix sign of error return code for ipsec_tdbcleanup(). -+ * Use more appropriate return code for ipsec_tdbwipe(). -+ * -+ * Revision 1.49 2001/04/19 18:56:17 rgb -+ * Fixed tdb table locking comments. -+ * -+ * Revision 1.48 2001/02/27 22:24:55 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.47 2000/11/06 04:32:08 rgb -+ * Ditched spin_lock_irqsave in favour of spin_lock_bh. -+ * -+ * Revision 1.46 2000/09/20 16:21:57 rgb -+ * Cleaned up ident string alloc/free. -+ * -+ * Revision 1.45 2000/09/08 19:16:51 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * Removed all references to CONFIG_IPSEC_PFKEYv2. -+ * -+ * Revision 1.44 2000/08/30 05:29:04 rgb -+ * Compiler-define out no longer used tdb_init() in ipsec_xform.c. -+ * -+ * Revision 1.43 2000/08/18 21:30:41 rgb -+ * Purged all tdb_spi, tdb_proto and tdb_dst macros. They are unclear. -+ * -+ * Revision 1.42 2000/08/01 14:51:51 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.41 2000/07/28 14:58:31 rgb -+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. -+ * -+ * Revision 1.40 2000/06/28 05:50:11 rgb -+ * Actually set iv_bits. -+ * -+ * Revision 1.39 2000/05/10 23:11:09 rgb -+ * Added netlink debugging output. -+ * Added a cast to quiet down the ntohl bug. -+ * -+ * Revision 1.38 2000/05/10 19:18:42 rgb -+ * Cast output of ntohl so that the broken prototype doesn't make our -+ * compile noisy. -+ * -+ * Revision 1.37 2000/03/16 14:04:59 rgb -+ * Hardwired CONFIG_IPSEC_PFKEYv2 on. -+ * -+ * Revision 1.36 2000/01/26 10:11:28 rgb -+ * Fixed spacing in error text causing run-in words. -+ * -+ * Revision 1.35 2000/01/21 06:17:16 rgb -+ * Tidied up compiler directive indentation for readability. -+ * Added ictx,octx vars for simplification.(kravietz) -+ * Added macros for HMAC padding magic numbers.(kravietz) -+ * Fixed missing key length reporting bug. -+ * Fixed bug in tdbwipe to return immediately on NULL tdbp passed in. -+ * -+ * Revision 1.34 1999/12/08 00:04:19 rgb -+ * Fixed SA direction overwriting bug for netlink users. -+ * -+ * Revision 1.33 1999/12/01 22:16:44 rgb -+ * Minor formatting changes in ESP MD5 initialisation. -+ * -+ * Revision 1.32 1999/11/25 09:06:36 rgb -+ * Fixed error return messages, should be returning negative numbers. -+ * Implemented SENDERR macro for propagating error codes. -+ * Added debug message and separate error code for algorithms not compiled -+ * in. -+ * -+ * Revision 1.31 1999/11/23 23:06:26 rgb -+ * Sort out pfkey and freeswan headers, putting them in a library path. -+ * -+ * Revision 1.30 1999/11/18 04:09:20 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.29 1999/11/17 15:53:40 rgb -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * -+ * Revision 1.28 1999/10/18 20:04:01 rgb -+ * Clean-out unused cruft. -+ * -+ * Revision 1.27 1999/10/03 19:01:03 rgb -+ * Spinlock support for 2.3.xx and 2.0.xx kernels. -+ * -+ * Revision 1.26 1999/10/01 16:22:24 rgb -+ * Switch from assignment init. to functional init. of spinlocks. -+ * -+ * Revision 1.25 1999/10/01 15:44:54 rgb -+ * Move spinlock header include to 2.1> scope. -+ * -+ * Revision 1.24 1999/10/01 00:03:46 rgb -+ * Added tdb structure locking. -+ * Minor formatting changes. -+ * Add function to initialize tdb hash table. -+ * -+ * Revision 1.23 1999/05/25 22:42:12 rgb -+ * Add deltdbchain() debugging. -+ * -+ * Revision 1.22 1999/05/25 21:24:31 rgb -+ * Add debugging statements to deltdbchain(). -+ * -+ * Revision 1.21 1999/05/25 03:51:48 rgb -+ * Refix error return code. -+ * -+ * Revision 1.20 1999/05/25 03:34:07 rgb -+ * Fix error return for flush. -+ * -+ * Revision 1.19 1999/05/09 03:25:37 rgb -+ * Fix bug introduced by 2.2 quick-and-dirty patch. -+ * -+ * Revision 1.18 1999/05/05 22:02:32 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.17 1999/04/29 15:20:16 rgb -+ * Change gettdb parameter to a pointer to reduce stack loading and -+ * facilitate parameter sanity checking. -+ * Add sanity checking for null pointer arguments. -+ * Add debugging instrumentation. -+ * Add function deltdbchain() which will take care of unlinking, -+ * zeroing and deleting a chain of tdbs. -+ * Add a parameter to tdbcleanup to be able to delete a class of SAs. -+ * tdbwipe now actually zeroes the tdb as well as any of its pointed -+ * structures. -+ * -+ * Revision 1.16 1999/04/16 15:36:29 rgb -+ * Fix cut-and-paste error causing a memory leak in IPIP TDB freeing. -+ * -+ * Revision 1.15 1999/04/11 00:29:01 henry -+ * GPL boilerplate -+ * -+ * Revision 1.14 1999/04/06 04:54:28 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.13 1999/02/19 18:23:01 rgb -+ * Nix debug off compile warning. -+ * -+ * Revision 1.12 1999/02/17 16:52:16 rgb -+ * Consolidate satoa()s for space and speed efficiency. -+ * Convert DEBUG_IPSEC to KLIPS_PRINT -+ * Clean out unused cruft. -+ * Ditch NET_IPIP dependancy. -+ * Loop for 3des key setting. -+ * -+ * Revision 1.11 1999/01/26 02:09:05 rgb -+ * Remove ah/esp/IPIP switching on include files. -+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro. -+ * Removed dead code. -+ * Clean up debug code when switched off. -+ * Remove references to INET_GET_PROTOCOL. -+ * Added code exclusion macros to reduce code from unused algorithms. -+ * -+ * Revision 1.10 1999/01/22 06:28:55 rgb -+ * Cruft clean-out. -+ * Put random IV generation in kernel. -+ * Added algorithm switch code. -+ * Enhanced debugging. -+ * 64-bit clean-up. -+ * -+ * Revision 1.9 1998/11/30 13:22:55 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.8 1998/11/25 04:59:06 rgb -+ * Add conditionals for no IPIP tunnel code. -+ * Delete commented out code. -+ * -+ * Revision 1.7 1998/10/31 06:50:41 rgb -+ * Convert xform ASCII names to no spaces. -+ * Fixed up comments in #endif directives. -+ * -+ * Revision 1.6 1998/10/19 14:44:28 rgb -+ * Added inclusion of freeswan.h. -+ * sa_id structure implemented and used: now includes protocol. -+ * -+ * Revision 1.5 1998/10/09 04:32:19 rgb -+ * Added 'klips_debug' prefix to all klips printk debug statements. -+ * -+ * Revision 1.4 1998/08/12 00:11:31 rgb -+ * Added new xform functions to the xform table. -+ * Fixed minor debug output spelling error. -+ * -+ * Revision 1.3 1998/07/09 17:45:31 rgb -+ * Clarify algorithm not available message. -+ * -+ * Revision 1.2 1998/06/23 03:00:51 rgb -+ * Check for presence of IPIP protocol if it is setup one way (we don't -+ * know what has been set up the other way and can only assume it will be -+ * symmetrical with the exception of keys). -+ * -+ * Revision 1.1 1998/06/18 21:27:51 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.3 1998/06/11 05:54:59 rgb -+ * Added transform version string pointer to xformsw initialisations. -+ * -+ * Revision 1.2 1998/04/21 21:28:57 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.1 1998/04/09 03:06:13 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:02 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.5 1997/06/03 04:24:48 ji -+ * Added ESP-3DES-MD5-96 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * Added new transforms. -+ * -+ * Revision 0.3 1996/11/20 14:39:04 ji -+ * Minor cleanups. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_sha1.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,219 @@ -+/* -+ * RCSID $Id$ -+ */ -+ -+/* -+ * The rest of the code is derived from sha1.c by Steve Reid, which is -+ * public domain. -+ * Minor cosmetic changes to accomodate it in the Linux kernel by ji. -+ */ -+ -+#include -+#include -+ -+#include "openswan/ipsec_sha1.h" -+ -+#if defined(rol) -+#undef rol -+#endif -+ -+#define SHA1HANDSOFF -+ -+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) -+ -+/* blk0() and blk() perform the initial expand. */ -+/* I got the idea of expanding during the round function from SSLeay */ -+#ifdef __LITTLE_ENDIAN -+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ -+ |(rol(block->l[i],8)&0x00FF00FF)) -+#else -+#define blk0(i) block->l[i] -+#endif -+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ -+ ^block->l[(i+2)&15]^block->l[i&15],1)) -+ -+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); -+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); -+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); -+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); -+ -+ -+/* Hash a single 512-bit block. This is the core of the algorithm. */ -+ -+void SHA1Transform(__u32 state[5], __u8 buffer[64]) -+{ -+__u32 a, b, c, d, e; -+typedef union { -+ unsigned char c[64]; -+ __u32 l[16]; -+} CHAR64LONG16; -+CHAR64LONG16* block; -+#ifdef SHA1HANDSOFF -+static unsigned char workspace[64]; -+ block = (CHAR64LONG16*)workspace; -+ memcpy(block, buffer, 64); -+#else -+ block = (CHAR64LONG16*)buffer; -+#endif -+ /* Copy context->state[] to working vars */ -+ a = state[0]; -+ b = state[1]; -+ c = state[2]; -+ d = state[3]; -+ e = state[4]; -+ /* 4 rounds of 20 operations each. Loop unrolled. */ -+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); -+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); -+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); -+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); -+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); -+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); -+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); -+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); -+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); -+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); -+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); -+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); -+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); -+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); -+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); -+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); -+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); -+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); -+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); -+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); -+ /* Add the working vars back into context.state[] */ -+ state[0] += a; -+ state[1] += b; -+ state[2] += c; -+ state[3] += d; -+ state[4] += e; -+ /* Wipe variables */ -+ a = b = c = d = e = 0; -+} -+ -+ -+/* SHA1Init - Initialize new context */ -+ -+void SHA1Init(void *vcontext) -+{ -+ SHA1_CTX* context = vcontext; -+ -+ /* SHA1 initialization constants */ -+ context->state[0] = 0x67452301; -+ context->state[1] = 0xEFCDAB89; -+ context->state[2] = 0x98BADCFE; -+ context->state[3] = 0x10325476; -+ context->state[4] = 0xC3D2E1F0; -+ context->count[0] = context->count[1] = 0; -+} -+ -+ -+/* Run your data through this. */ -+ -+void SHA1Update(void *vcontext, unsigned char* data, __u32 len) -+{ -+ SHA1_CTX* context = vcontext; -+ __u32 i, j; -+ -+ j = context->count[0]; -+ if ((context->count[0] += len << 3) < j) -+ context->count[1]++; -+ context->count[1] += (len>>29); -+ j = (j >> 3) & 63; -+ if ((j + len) > 63) { -+ memcpy(&context->buffer[j], data, (i = 64-j)); -+ SHA1Transform(context->state, context->buffer); -+ for ( ; i + 63 < len; i += 64) { -+ SHA1Transform(context->state, &data[i]); -+ } -+ j = 0; -+ } -+ else i = 0; -+ memcpy(&context->buffer[j], &data[i], len - i); -+} -+ -+ -+/* Add padding and return the message digest. */ -+ -+void SHA1Final(unsigned char digest[20], void *vcontext) -+{ -+ __u32 i, j; -+ unsigned char finalcount[8]; -+ SHA1_CTX* context = vcontext; -+ -+ for (i = 0; i < 8; i++) { -+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] -+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ -+ } -+ SHA1Update(context, (unsigned char *)"\200", 1); -+ while ((context->count[0] & 504) != 448) { -+ SHA1Update(context, (unsigned char *)"\0", 1); -+ } -+ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ -+ for (i = 0; i < 20; i++) { -+ digest[i] = (unsigned char) -+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); -+ } -+ /* Wipe variables */ -+ i = j = 0; -+ memset(context->buffer, 0, 64); -+ memset(context->state, 0, 20); -+ memset(context->count, 0, 8); -+ memset(&finalcount, 0, 8); -+#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */ -+ SHA1Transform(context->state, context->buffer); -+#endif -+} -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.9 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.8 2002/09/10 01:45:14 mcr -+ * changed type of MD5_CTX and SHA1_CTX to void * so that -+ * the function prototypes would match, and could be placed -+ * into a pointer to a function. -+ * -+ * Revision 1.7 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.6 2002/04/24 07:36:30 mcr -+ * Moved from ./klips/net/ipsec/ipsec_sha1.c,v -+ * -+ * Revision 1.5 1999/12/13 13:59:13 rgb -+ * Quick fix to argument size to Update bugs. -+ * -+ * Revision 1.4 1999/04/11 00:29:00 henry -+ * GPL boilerplate -+ * -+ * Revision 1.3 1999/04/06 04:54:27 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.2 1999/01/22 06:55:50 rgb -+ * 64-bit clean-up. -+ * -+ * Revision 1.1 1998/06/18 21:27:50 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.2 1998/04/23 20:54:04 rgb -+ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when -+ * verified. -+ * -+ * Revision 1.1 1998/04/09 03:06:11 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:05 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * New transform -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_tunnel.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,2645 @@ -+/* -+ * IPSEC Tunneling code. Heavily based on drivers/net/new_tunnel.c -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_tunnel_c_version[] = "RCSID $Id$"; -+ -+#define __NO_VERSION__ -+#include -+#include /* for CONFIG_IP_FORWARD */ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include /* struct tcphdr */ -+#include /* struct udphdr */ -+#include -+#include -+#ifdef NET_21 -+# include -+# include -+# define ip_chk_addr inet_addr_type -+# define IS_MYADDR RTN_LOCAL -+# include -+# undef dev_kfree_skb -+# define dev_kfree_skb(a,b) kfree_skb(a) -+# define PHYSDEV_TYPE -+#endif /* NET_21 */ -+#include -+#include /* icmp_send() */ -+#include -+#ifdef NETDEV_23 -+# include -+#endif /* NETDEV_23 */ -+ -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_life.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_eroute.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_sa.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_xmit.h" -+#include "openswan/ipsec_ipe4.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+#include -+#endif -+ -+static __u32 zeroes[64]; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_tunnel = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_open(struct device *dev) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ -+ /* -+ * Can't open until attached. -+ */ -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_open: " -+ "dev = %s, prv->dev = %s\n", -+ dev->name, prv->dev?prv->dev->name:"NONE"); -+ -+ if (prv->dev == NULL) -+ return -ENODEV; -+ -+ MOD_INC_USE_COUNT; -+ return 0; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_close(struct device *dev) -+{ -+ MOD_DEC_USE_COUNT; -+ return 0; -+} -+ -+#ifdef NETDEV_23 -+static inline int ipsec_tunnel_xmit2(struct sk_buff *skb) -+{ -+#ifdef NETDEV_25 /* 2.6 kernels */ -+ return dst_output(skb); -+#else -+ return ip_send(skb); -+#endif -+} -+#endif /* NETDEV_23 */ -+ -+enum ipsec_xmit_value -+ipsec_tunnel_strip_hard_header(struct ipsec_xmit_state *ixs) -+{ -+ /* ixs->physdev->hard_header_len is unreliable and should not be used */ -+ ixs->hard_header_len = (unsigned char *)(ixs->iph) - ixs->skb->data; -+ -+ if(ixs->hard_header_len < 0) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_error:ipsec_xmit_strip_hard_header: " -+ "Negative hard_header_len (%d)?!\n", ixs->hard_header_len); -+ ixs->stats->tx_dropped++; -+ return IPSEC_XMIT_BADHHLEN; -+ } -+ -+ /* while ixs->physdev->hard_header_len is unreliable and -+ * should not be trusted, it accurate and required for ATM, GRE and -+ * some other interfaces to work. Thanks to Willy Tarreau -+ * . -+ */ -+ if(ixs->hard_header_len == 0) { /* no hard header present */ -+ ixs->hard_header_stripped = 1; -+ ixs->hard_header_len = ixs->physdev->hard_header_len; -+ } -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_tunnel & DB_TN_XMIT) { -+ int i; -+ char c; -+ -+ printk(KERN_INFO "klips_debug:ipsec_xmit_strip_hard_header: " -+ ">>> skb->len=%ld hard_header_len:%d", -+ (unsigned long int)ixs->skb->len, ixs->hard_header_len); -+ c = ' '; -+ for (i=0; i < ixs->hard_header_len; i++) { -+ printk("%c%02x", c, ixs->skb->data[i]); -+ c = ':'; -+ } -+ printk(" \n"); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph); -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_strip_hard_header: " -+ "Original head,tailroom: %d,%d\n", -+ skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); -+ -+ return IPSEC_XMIT_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_tunnel_SAlookup(struct ipsec_xmit_state *ixs) -+{ -+ /* -+ * First things first -- look us up in the erouting tables. -+ */ -+ ixs->matcher.sen_len = sizeof (struct sockaddr_encap); -+ ixs->matcher.sen_family = AF_ENCAP; -+ ixs->matcher.sen_type = SENT_IP4; -+ ixs->matcher.sen_ip_src.s_addr = ixs->iph->saddr; -+ ixs->matcher.sen_ip_dst.s_addr = ixs->iph->daddr; -+ ixs->matcher.sen_proto = ixs->iph->protocol; -+ ipsec_extract_ports(ixs->iph, &ixs->matcher); -+ -+ /* -+ * The spinlock is to prevent any other process from accessing or deleting -+ * the eroute while we are using and updating it. -+ */ -+ spin_lock(&eroute_lock); -+ -+ ixs->eroute = ipsec_findroute(&ixs->matcher); -+ -+ if(ixs->iph->protocol == IPPROTO_UDP) { -+ if(ixs->skb->sk) { -+ ixs->sport=ntohs(ixs->skb->sk->sport); -+ ixs->dport=ntohs(ixs->skb->sk->dport); -+ } else if((ntohs(ixs->iph->frag_off) & IP_OFFSET) == 0 && -+ ((ixs->skb->len - ixs->hard_header_len) >= -+ ((ixs->iph->ihl << 2) + sizeof(struct udphdr)))) { -+ ixs->sport=ntohs(((struct udphdr*)((caddr_t)ixs->iph+(ixs->iph->ihl<<2)))->source); -+ ixs->dport=ntohs(((struct udphdr*)((caddr_t)ixs->iph + (ixs->iph->ihl<<2)))->dest); -+ } else { -+ ixs->sport=0; ixs->dport=0; -+ } -+ } -+ -+ /* default to a %drop eroute */ -+ ixs->outgoing_said.proto = IPPROTO_INT; -+ ixs->outgoing_said.spi = htonl(SPI_DROP); -+ ixs->outgoing_said.dst.u.v4.sin_addr.s_addr = INADDR_ANY; -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_SAlookup: " -+ "checking for local udp/500 IKE packet " -+ "saddr=%x, er=0p%p, daddr=%x, er_dst=%x, proto=%d sport=%d dport=%d\n", -+ ntohl((unsigned int)ixs->iph->saddr), -+ ixs->eroute, -+ ntohl((unsigned int)ixs->iph->daddr), -+ ixs->eroute ? ntohl((unsigned int)ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr) : 0, -+ ixs->iph->protocol, -+ ixs->sport, -+ ixs->dport); -+ -+ /* -+ * Quick cheat for now...are we udp/500? If so, let it through -+ * without interference since it is most likely an IKE packet. -+ */ -+ -+ if (ip_chk_addr((unsigned long)ixs->iph->saddr) == IS_MYADDR -+ && (!ixs->eroute -+ || ixs->iph->daddr == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr -+ || INADDR_ANY == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr) -+ -+ && ((ixs->sport == 500) || (ixs->sport == 4500))) { -+ /* Whatever the eroute, this is an IKE message -+ * from us (i.e. not being forwarded). -+ * Furthermore, if there is a tunnel eroute, -+ * the destination is the peer for this eroute. -+ * So %pass the packet: modify the default %drop. -+ */ -+ ixs->outgoing_said.spi = htonl(SPI_PASS); -+ if(!(ixs->skb->sk) && ((ntohs(ixs->iph->frag_off) & IP_MF) != 0)) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_SAlookup: " -+ "local UDP/500 (probably IKE) passthrough: base fragment, rest of fragments will probably get filtered.\n"); -+ } -+ } else if (ixs->eroute) { -+ ixs->eroute->er_count++; -+ ixs->eroute->er_lasttime = jiffies/HZ; -+ if(ixs->eroute->er_said.proto==IPPROTO_INT -+ && ixs->eroute->er_said.spi==htonl(SPI_HOLD)) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_SAlookup: " -+ "shunt SA of HOLD: skb stored in HOLD.\n"); -+ if(ixs->eroute->er_last != NULL) { -+ kfree_skb(ixs->eroute->er_last); -+ } -+ ixs->eroute->er_last = ixs->skb; -+ ixs->skb = NULL; -+ ixs->stats->tx_dropped++; -+ spin_unlock(&eroute_lock); -+ return IPSEC_XMIT_STOLEN; -+ } -+ ixs->outgoing_said = ixs->eroute->er_said; -+ ixs->eroute_pid = ixs->eroute->er_pid; -+ /* Copy of the ident for the TRAP/TRAPSUBNET eroutes */ -+ if(ixs->outgoing_said.proto==IPPROTO_INT -+ && (ixs->outgoing_said.spi==htonl(SPI_TRAP) -+ || (ixs->outgoing_said.spi==htonl(SPI_TRAPSUBNET)))) { -+ int len; -+ -+ ixs->ips.ips_ident_s.type = ixs->eroute->er_ident_s.type; -+ ixs->ips.ips_ident_s.id = ixs->eroute->er_ident_s.id; -+ ixs->ips.ips_ident_s.len = ixs->eroute->er_ident_s.len; -+ if (ixs->ips.ips_ident_s.len) { -+ len = ixs->ips.ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_SAlookup: " -+ "allocating %d bytes for ident_s shunt SA of HOLD: skb stored in HOLD.\n", -+ len); -+ if ((ixs->ips.ips_ident_s.data = kmalloc(len, GFP_ATOMIC)) == NULL) { -+ printk(KERN_WARNING "klips_debug:ipsec_xmit_SAlookup: " -+ "Failed, tried to allocate %d bytes for source ident.\n", -+ len); -+ ixs->stats->tx_dropped++; -+ spin_unlock(&eroute_lock); -+ return IPSEC_XMIT_ERRMEMALLOC; -+ } -+ memcpy(ixs->ips.ips_ident_s.data, ixs->eroute->er_ident_s.data, len); -+ } -+ ixs->ips.ips_ident_d.type = ixs->eroute->er_ident_d.type; -+ ixs->ips.ips_ident_d.id = ixs->eroute->er_ident_d.id; -+ ixs->ips.ips_ident_d.len = ixs->eroute->er_ident_d.len; -+ if (ixs->ips.ips_ident_d.len) { -+ len = ixs->ips.ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_SAlookup: " -+ "allocating %d bytes for ident_d shunt SA of HOLD: skb stored in HOLD.\n", -+ len); -+ if ((ixs->ips.ips_ident_d.data = kmalloc(len, GFP_ATOMIC)) == NULL) { -+ printk(KERN_WARNING "klips_debug:ipsec_xmit_SAlookup: " -+ "Failed, tried to allocate %d bytes for dest ident.\n", -+ len); -+ ixs->stats->tx_dropped++; -+ spin_unlock(&eroute_lock); -+ return IPSEC_XMIT_ERRMEMALLOC; -+ } -+ memcpy(ixs->ips.ips_ident_d.data, ixs->eroute->er_ident_d.data, len); -+ } -+ } -+ } -+ -+ spin_unlock(&eroute_lock); -+ return IPSEC_XMIT_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_tunnel_restore_hard_header(struct ipsec_xmit_state*ixs) -+{ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_restore_hard_header: " -+ "After recursive xforms -- head,tailroom: %d,%d\n", -+ skb_headroom(ixs->skb), -+ skb_tailroom(ixs->skb)); -+ -+ if(ixs->saved_header) { -+ if(skb_headroom(ixs->skb) < ixs->hard_header_len) { -+ printk(KERN_WARNING -+ "klips_error:ipsec_xmit_restore_hard_header: " -+ "tried to skb_push hhlen=%d, %d available. This should never happen, please report.\n", -+ ixs->hard_header_len, -+ skb_headroom(ixs->skb)); -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_PUSHPULLERR; -+ -+ } -+ skb_push(ixs->skb, ixs->hard_header_len); -+ { -+ int i; -+ for (i = 0; i < ixs->hard_header_len; i++) { -+ ixs->skb->data[i] = ixs->saved_header[i]; -+ } -+ } -+ } -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if (ixs->natt_type && ixs->natt_head) { -+ struct iphdr *ipp = ixs->skb->nh.iph; -+ struct udphdr *udp; -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "encapsuling packet into UDP (NAT-Traversal) (%d %d)\n", -+ ixs->natt_type, ixs->natt_head); -+ -+ ixs->iphlen = ipp->ihl << 2; -+ ipp->tot_len = -+ htons(ntohs(ipp->tot_len) + ixs->natt_head); -+ if(skb_tailroom(ixs->skb) < ixs->natt_head) { -+ printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: " -+ "tried to skb_put %d, %d available. " -+ "This should never happen, please report.\n", -+ ixs->natt_head, -+ skb_tailroom(ixs->skb)); -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESPUDP; -+ } -+ skb_put(ixs->skb, ixs->natt_head); -+ -+ udp = (struct udphdr *)((char *)ipp + ixs->iphlen); -+ -+ /* move ESP hdr after UDP hdr */ -+ memmove((void *)((char *)udp + ixs->natt_head), -+ (void *)(udp), -+ ntohs(ipp->tot_len) - ixs->iphlen - ixs->natt_head); -+ -+ /* clear UDP & Non-IKE Markers (if any) */ -+ memset(udp, 0, ixs->natt_head); -+ -+ /* fill UDP with usefull informations ;-) */ -+ udp->source = htons(ixs->natt_sport); -+ udp->dest = htons(ixs->natt_dport); -+ udp->len = htons(ntohs(ipp->tot_len) - ixs->iphlen); -+ -+ /* set protocol */ -+ ipp->protocol = IPPROTO_UDP; -+ -+ /* fix IP checksum */ -+ ipp->check = 0; -+ ipp->check = ip_fast_csum((unsigned char *)ipp, ipp->ihl); -+ } -+#endif -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_restore_hard_header: " -+ "With hard_header, final head,tailroom: %d,%d\n", -+ skb_headroom(ixs->skb), -+ skb_tailroom(ixs->skb)); -+ -+ return IPSEC_XMIT_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_tunnel_send(struct ipsec_xmit_state*ixs) -+{ -+#ifdef NETDEV_25 -+ struct flowi fl; -+#endif -+ -+#ifdef NET_21 /* 2.2 and 2.4 kernels */ -+ /* new route/dst cache code from James Morris */ -+ ixs->skb->dev = ixs->physdev; -+#ifdef NETDEV_25 -+ fl.oif = ixs->physdev->iflink; -+ fl.nl_u.ip4_u.daddr = ixs->skb->nh.iph->daddr; -+ fl.nl_u.ip4_u.saddr = ixs->pass ? 0 : ixs->skb->nh.iph->saddr; -+ fl.nl_u.ip4_u.tos = RT_TOS(ixs->skb->nh.iph->tos); -+ fl.proto = ixs->skb->nh.iph->protocol; -+ if ((ixs->error = ip_route_output_key(&ixs->route, &fl))) { -+#else -+ /*skb_orphan(ixs->skb);*/ -+ if((ixs->error = ip_route_output(&ixs->route, -+ ixs->skb->nh.iph->daddr, -+ ixs->pass ? 0 : ixs->skb->nh.iph->saddr, -+ RT_TOS(ixs->skb->nh.iph->tos), -+ /* mcr->rgb: should this be 0 instead? */ -+ ixs->physdev->iflink))) { -+#endif -+ ixs->stats->tx_errors++; -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_send: " -+ "ip_route_output failed with error code %d, rt->u.dst.dev=%s, dropped\n", -+ ixs->error, -+ ixs->route->u.dst.dev->name); -+ return IPSEC_XMIT_ROUTEERR; -+ } -+ if(ixs->dev == ixs->route->u.dst.dev) { -+ ip_rt_put(ixs->route); -+ /* This is recursion, drop it. */ -+ ixs->stats->tx_errors++; -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_send: " -+ "suspect recursion, dev=rt->u.dst.dev=%s, dropped\n", -+ ixs->dev->name); -+ return IPSEC_XMIT_RECURSDETECT; -+ } -+ dst_release(ixs->skb->dst); -+ ixs->skb->dst = &ixs->route->u.dst; -+ ixs->stats->tx_bytes += ixs->skb->len; -+ if(ixs->skb->len < ixs->skb->nh.raw - ixs->skb->data) { -+ ixs->stats->tx_errors++; -+ printk(KERN_WARNING -+ "klips_error:ipsec_xmit_send: " -+ "tried to __skb_pull nh-data=%ld, %d available. This should never happen, please report.\n", -+ (unsigned long)(ixs->skb->nh.raw - ixs->skb->data), -+ ixs->skb->len); -+ return IPSEC_XMIT_PUSHPULLERR; -+ } -+ __skb_pull(ixs->skb, ixs->skb->nh.raw - ixs->skb->data); -+#ifdef SKB_RESET_NFCT -+ if(!ixs->pass) { -+ nf_conntrack_put(ixs->skb->nfct); -+ ixs->skb->nfct = NULL; -+ } -+#ifdef CONFIG_NETFILTER_DEBUG -+ ixs->skb->nf_debug = 0; -+#endif /* CONFIG_NETFILTER_DEBUG */ -+#endif /* SKB_RESET_NFCT */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_send: " -+ "...done, calling ip_send() on device:%s\n", -+ ixs->skb->dev ? ixs->skb->dev->name : "NULL"); -+ KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->skb->nh.iph); -+#ifdef NETDEV_23 /* 2.4 kernels */ -+ { -+ int err; -+ -+ err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, ixs->skb, NULL, ixs->route->u.dst.dev, -+ ipsec_tunnel_xmit2); -+ if(err != NET_XMIT_SUCCESS && err != NET_XMIT_CN) { -+ if(net_ratelimit()) -+ printk(KERN_ERR -+ "klips_error:ipsec_xmit_send: " -+ "ip_send() failed, err=%d\n", -+ -err); -+ ixs->stats->tx_errors++; -+ ixs->stats->tx_aborted_errors++; -+ ixs->skb = NULL; -+ return IPSEC_XMIT_IPSENDFAILURE; -+ } -+ } -+#else /* NETDEV_23 */ /* 2.2 kernels */ -+ ip_send(ixs->skb); -+#endif /* NETDEV_23 */ -+#else /* NET_21 */ /* 2.0 kernels */ -+ ixs->skb->arp = 1; -+ /* ISDN/ASYNC PPP from Matjaz Godec. */ -+ /* skb->protocol = htons(ETH_P_IP); */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_send: " -+ "...done, calling dev_queue_xmit() or ip_fragment().\n"); -+ IP_SEND(ixs->skb, ixs->physdev); -+#endif /* NET_21 */ -+ ixs->stats->tx_packets++; -+ -+ ixs->skb = NULL; -+ -+ return IPSEC_XMIT_OK; -+} -+ -+void -+ipsec_tunnel_cleanup(struct ipsec_xmit_state*ixs) -+{ -+#if defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) -+ netif_wake_queue(ixs->dev); -+#else /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ -+ ixs->dev->tbusy = 0; -+#endif /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ -+ if(ixs->saved_header) { -+ kfree(ixs->saved_header); -+ } -+ if(ixs->skb) { -+ dev_kfree_skb(ixs->skb, FREE_WRITE); -+ } -+ if(ixs->oskb) { -+ dev_kfree_skb(ixs->oskb, FREE_WRITE); -+ } -+ if (ixs->ips.ips_ident_s.data) { -+ kfree(ixs->ips.ips_ident_s.data); -+ } -+ if (ixs->ips.ips_ident_d.data) { -+ kfree(ixs->ips.ips_ident_d.data); -+ } -+} -+ -+/* -+ * This function assumes it is being called from dev_queue_xmit() -+ * and that skb is filled properly by that function. -+ */ -+int -+ipsec_tunnel_start_xmit(struct sk_buff *skb, struct device *dev) -+{ -+ struct ipsec_xmit_state ixs_mem; -+ struct ipsec_xmit_state *ixs = &ixs_mem; -+ enum ipsec_xmit_value stat; -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ ixs->natt_type = 0, ixs->natt_head = 0; -+ ixs->natt_sport = 0, ixs->natt_dport = 0; -+#endif -+ -+ memset((caddr_t)ixs, 0, sizeof(*ixs)); -+ ixs->oskb = NULL; -+ ixs->saved_header = NULL; /* saved copy of the hard header */ -+ ixs->route = NULL; -+ memset((caddr_t)&(ixs->ips), 0, sizeof(ixs->ips)); -+ ixs->dev = dev; -+ ixs->skb = skb; -+ -+ stat = ipsec_xmit_sanity_check_dev(ixs); -+ if(stat != IPSEC_XMIT_OK) { -+ goto cleanup; -+ } -+ -+ stat = ipsec_xmit_sanity_check_skb(ixs); -+ if(stat != IPSEC_XMIT_OK) { -+ goto cleanup; -+ } -+ -+ stat = ipsec_tunnel_strip_hard_header(ixs); -+ if(stat != IPSEC_XMIT_OK) { -+ goto cleanup; -+ } -+ -+ stat = ipsec_tunnel_SAlookup(ixs); -+ if(stat != IPSEC_XMIT_OK) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_tunnel_start_xmit: SAlookup failed: %d\n", -+ stat); -+ goto cleanup; -+ } -+ -+ ixs->innersrc = ixs->iph->saddr; -+ /* start encapsulation loop here XXX */ -+ do { -+ stat = ipsec_xmit_encap_bundle(ixs); -+ if(stat != IPSEC_XMIT_OK) { -+ if(stat == IPSEC_XMIT_PASS) { -+ goto bypass; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_tunnel_start_xmit: encap_bundle failed: %d\n", -+ stat); -+ goto cleanup; -+ } -+ -+ ixs->matcher.sen_ip_src.s_addr = ixs->iph->saddr; -+ ixs->matcher.sen_ip_dst.s_addr = ixs->iph->daddr; -+ ixs->matcher.sen_proto = ixs->iph->protocol; -+ ipsec_extract_ports(ixs->iph, &ixs->matcher); -+ -+ spin_lock(&eroute_lock); -+ ixs->eroute = ipsec_findroute(&ixs->matcher); -+ if(ixs->eroute) { -+ ixs->outgoing_said = ixs->eroute->er_said; -+ ixs->eroute_pid = ixs->eroute->er_pid; -+ ixs->eroute->er_count++; -+ ixs->eroute->er_lasttime = jiffies/HZ; -+ } -+ spin_unlock(&eroute_lock); -+ -+ KLIPS_PRINT((debug_tunnel & DB_TN_XMIT) && -+ /* ((ixs->orgdst != ixs->newdst) || (ixs->orgsrc != ixs->newsrc)) */ -+ (ixs->orgedst != ixs->outgoing_said.dst.u.v4.sin_addr.s_addr) && -+ ixs->outgoing_said.dst.u.v4.sin_addr.s_addr && -+ ixs->eroute, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "We are recursing here.\n"); -+ -+ } while(/*((ixs->orgdst != ixs->newdst) || (ixs->orgsrc != ixs->newsrc))*/ -+ (ixs->orgedst != ixs->outgoing_said.dst.u.v4.sin_addr.s_addr) && -+ ixs->outgoing_said.dst.u.v4.sin_addr.s_addr && -+ ixs->eroute); -+ -+ stat = ipsec_tunnel_restore_hard_header(ixs); -+ if(stat != IPSEC_XMIT_OK) { -+ goto cleanup; -+ } -+ -+ bypass: -+ stat = ipsec_tunnel_send(ixs); -+ -+ cleanup: -+ ipsec_tunnel_cleanup(ixs); -+ -+ return 0; -+} -+ -+DEBUG_NO_STATIC struct net_device_stats * -+ipsec_tunnel_get_stats(struct device *dev) -+{ -+ return &(((struct ipsecpriv *)(dev->priv))->mystats); -+} -+ -+/* -+ * Revectored calls. -+ * For each of these calls, a field exists in our private structure. -+ */ -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_hard_header(struct sk_buff *skb, struct device *dev, -+ unsigned short type, void *daddr, void *saddr, unsigned len) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ struct device *tmp; -+ int ret; -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(skb == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "no skb...\n"); -+ return -ENODATA; -+ } -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "no device...\n"); -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "skb->dev=%s dev=%s.\n", -+ skb->dev ? skb->dev->name : "NULL", -+ dev->name); -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "no private space associated with dev=%s\n", -+ dev->name ? dev->name : "NULL"); -+ return -ENODEV; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "no physical device associated with dev=%s\n", -+ dev->name ? dev->name : "NULL"); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ /* check if we have to send a IPv6 packet. It might be a Router -+ Solicitation, where the building of the packet happens in -+ reverse order: -+ 1. ll hdr, -+ 2. IPv6 hdr, -+ 3. ICMPv6 hdr -+ -> skb->nh.raw is still uninitialized when this function is -+ called!! If this is no IPv6 packet, we can print debugging -+ messages, otherwise we skip all debugging messages and just -+ build the ll header */ -+ if(type != ETH_P_IPV6) { -+ /* execute this only, if we don't have to build the -+ header for a IPv6 packet */ -+ if(!prv->hard_header) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "physical device has been detached, packet dropped 0p%p->0p%p len=%d type=%d dev=%s->NULL ", -+ saddr, -+ daddr, -+ len, -+ type, -+ dev->name); -+#ifdef NET_21 -+ KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+#else /* NET_21 */ -+ KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->ip_hdr->saddr), -+ (__u32)ntohl(skb->ip_hdr->daddr) ); -+#endif /* NET_21 */ -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+#define da ((struct device *)(prv->dev))->dev_addr -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "Revectored 0p%p->0p%p len=%d type=%d dev=%s->%s dev_addr=%02x:%02x:%02x:%02x:%02x:%02x ", -+ saddr, -+ daddr, -+ len, -+ type, -+ dev->name, -+ prv->dev->name, -+ da[0], da[1], da[2], da[3], da[4], da[5]); -+#ifdef NET_21 -+ KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+#else /* NET_21 */ -+ KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->ip_hdr->saddr), -+ (__u32)ntohl(skb->ip_hdr->daddr) ); -+#endif /* NET_21 */ -+ } else { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n"); -+ } -+ tmp = skb->dev; -+ skb->dev = prv->dev; -+ ret = prv->hard_header(skb, prv->dev, type, (void *)daddr, (void *)saddr, len); -+ skb->dev = tmp; -+ return ret; -+} -+ -+DEBUG_NO_STATIC int -+#ifdef NET_21 -+ipsec_tunnel_rebuild_header(struct sk_buff *skb) -+#else /* NET_21 */ -+ipsec_tunnel_rebuild_header(void *buff, struct device *dev, -+ unsigned long raddr, struct sk_buff *skb) -+#endif /* NET_21 */ -+{ -+ struct ipsecpriv *prv = skb->dev->priv; -+ struct device *tmp; -+ int ret; -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(skb->dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_rebuild_header: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_rebuild_header: " -+ "no private space associated with dev=%s", -+ skb->dev->name ? skb->dev->name : "NULL"); -+ return -ENODEV; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_rebuild_header: " -+ "no physical device associated with dev=%s", -+ skb->dev->name ? skb->dev->name : "NULL"); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ if(!prv->rebuild_header) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_rebuild_header: " -+ "physical device has been detached, packet dropped skb->dev=%s->NULL ", -+ skb->dev->name); -+#ifdef NET_21 -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+#else /* NET_21 */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->ip_hdr->saddr), -+ (__u32)ntohl(skb->ip_hdr->daddr) ); -+#endif /* NET_21 */ -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel: " -+ "Revectored rebuild_header dev=%s->%s ", -+ skb->dev->name, prv->dev->name); -+#ifdef NET_21 -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+#else /* NET_21 */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->ip_hdr->saddr), -+ (__u32)ntohl(skb->ip_hdr->daddr) ); -+#endif /* NET_21 */ -+ tmp = skb->dev; -+ skb->dev = prv->dev; -+ -+#ifdef NET_21 -+ ret = prv->rebuild_header(skb); -+#else /* NET_21 */ -+ ret = prv->rebuild_header(buff, prv->dev, raddr, skb); -+#endif /* NET_21 */ -+ skb->dev = tmp; -+ return ret; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_set_mac_address(struct device *dev, void *addr) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_set_mac_address: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_set_mac_address: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return -ENODEV; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_set_mac_address: " -+ "no physical device associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ if(!prv->set_mac_address) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_set_mac_address: " -+ "physical device has been detached, cannot set - skb->dev=%s->NULL\n", -+ dev->name); -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_set_mac_address: " -+ "Revectored dev=%s->%s addr=0p%p\n", -+ dev->name, prv->dev->name, addr); -+ return prv->set_mac_address(prv->dev, addr); -+ -+} -+ -+#ifndef NET_21 -+DEBUG_NO_STATIC void -+ipsec_tunnel_cache_bind(struct hh_cache **hhp, struct device *dev, -+ unsigned short htype, __u32 daddr) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_bind: " -+ "no device..."); -+ return; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_bind: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_bind: " -+ "no physical device associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ stats->tx_dropped++; -+ return; -+ } -+ -+ if(!prv->header_cache_bind) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_bind: " -+ "physical device has been detached, cannot set - skb->dev=%s->NULL\n", -+ dev->name); -+ stats->tx_dropped++; -+ return; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_bind: " -+ "Revectored \n"); -+ prv->header_cache_bind(hhp, prv->dev, htype, daddr); -+ return; -+} -+#endif /* !NET_21 */ -+ -+ -+DEBUG_NO_STATIC void -+ipsec_tunnel_cache_update(struct hh_cache *hh, struct device *dev, unsigned char * haddr) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_update: " -+ "no device..."); -+ return; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_update: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_update: " -+ "no physical device associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ stats->tx_dropped++; -+ return; -+ } -+ -+ if(!prv->header_cache_update) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_update: " -+ "physical device has been detached, cannot set - skb->dev=%s->NULL\n", -+ dev->name); -+ return; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel: " -+ "Revectored cache_update\n"); -+ prv->header_cache_update(hh, prv->dev, haddr); -+ return; -+} -+ -+#ifdef NET_21 -+DEBUG_NO_STATIC int -+ipsec_tunnel_neigh_setup(struct neighbour *n) -+{ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_neigh_setup:\n"); -+ -+ if (n->nud_state == NUD_NONE) { -+ n->ops = &arp_broken_ops; -+ n->output = n->ops->output; -+ } -+ return 0; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_neigh_setup_dev(struct device *dev, struct neigh_parms *p) -+{ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_neigh_setup_dev: " -+ "setting up %s\n", -+ dev ? dev->name : "NULL"); -+ -+ if (p->tbl->family == AF_INET) { -+ p->neigh_setup = ipsec_tunnel_neigh_setup; -+ p->ucast_probes = 0; -+ p->mcast_probes = 0; -+ } -+ return 0; -+} -+#endif /* NET_21 */ -+ -+/* -+ * We call the attach routine to attach another device. -+ */ -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_attach(struct device *dev, struct device *physdev) -+{ -+ int i; -+ struct ipsecpriv *prv = dev->priv; -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_attach: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_attach: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return -ENODATA; -+ } -+ -+ prv->dev = physdev; -+ prv->hard_start_xmit = physdev->hard_start_xmit; -+ prv->get_stats = physdev->get_stats; -+ -+ if (physdev->hard_header) { -+ prv->hard_header = physdev->hard_header; -+ dev->hard_header = ipsec_tunnel_hard_header; -+ } else -+ dev->hard_header = NULL; -+ -+ if (physdev->rebuild_header) { -+ prv->rebuild_header = physdev->rebuild_header; -+ dev->rebuild_header = ipsec_tunnel_rebuild_header; -+ } else -+ dev->rebuild_header = NULL; -+ -+ if (physdev->set_mac_address) { -+ prv->set_mac_address = physdev->set_mac_address; -+ dev->set_mac_address = ipsec_tunnel_set_mac_address; -+ } else -+ dev->set_mac_address = NULL; -+ -+#ifndef NET_21 -+ if (physdev->header_cache_bind) { -+ prv->header_cache_bind = physdev->header_cache_bind; -+ dev->header_cache_bind = ipsec_tunnel_cache_bind; -+ } else -+ dev->header_cache_bind = NULL; -+#endif /* !NET_21 */ -+ -+ if (physdev->header_cache_update) { -+ prv->header_cache_update = physdev->header_cache_update; -+ dev->header_cache_update = ipsec_tunnel_cache_update; -+ } else -+ dev->header_cache_update = NULL; -+ -+ dev->hard_header_len = physdev->hard_header_len; -+ -+#ifdef NET_21 -+/* prv->neigh_setup = physdev->neigh_setup; */ -+ dev->neigh_setup = ipsec_tunnel_neigh_setup_dev; -+#endif /* NET_21 */ -+ dev->mtu = 16260; /* 0xfff0; */ /* dev->mtu; */ -+ prv->mtu = physdev->mtu; -+ -+#ifdef PHYSDEV_TYPE -+ dev->type = physdev->type; /* ARPHRD_TUNNEL; */ -+#endif /* PHYSDEV_TYPE */ -+ -+ dev->addr_len = physdev->addr_len; -+ for (i=0; iaddr_len; i++) { -+ dev->dev_addr[i] = physdev->dev_addr[i]; -+ } -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_tunnel & DB_TN_INIT) { -+ printk(KERN_INFO "klips_debug:ipsec_tunnel_attach: " -+ "physical device %s being attached has HW address: %2x", -+ physdev->name, physdev->dev_addr[0]); -+ for (i=1; i < physdev->addr_len; i++) { -+ printk(":%02x", physdev->dev_addr[i]); -+ } -+ printk("\n"); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ return 0; -+} -+ -+/* -+ * We call the detach routine to detach the ipsec tunnel from another device. -+ */ -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_detach(struct device *dev) -+{ -+ int i; -+ struct ipsecpriv *prv = dev->priv; -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_detach: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_detach: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return -ENODATA; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_detach: " -+ "physical device %s being detached from virtual device %s\n", -+ prv->dev ? prv->dev->name : "NULL", -+ dev->name); -+ -+ ipsec_dev_put(prv->dev); -+ prv->dev = NULL; -+ prv->hard_start_xmit = NULL; -+ prv->get_stats = NULL; -+ -+ prv->hard_header = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->hard_header = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+ prv->rebuild_header = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->rebuild_header = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+ prv->set_mac_address = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->set_mac_address = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+#ifndef NET_21 -+ prv->header_cache_bind = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->header_cache_bind = NULL; -+#endif /* DETACH_AND_DOWN */ -+#endif /* !NET_21 */ -+ -+ prv->header_cache_update = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->header_cache_update = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+#ifdef NET_21 -+/* prv->neigh_setup = NULL; */ -+#ifdef DETACH_AND_DOWN -+ dev->neigh_setup = NULL; -+#endif /* DETACH_AND_DOWN */ -+#endif /* NET_21 */ -+ dev->hard_header_len = 0; -+#ifdef DETACH_AND_DOWN -+ dev->mtu = 0; -+#endif /* DETACH_AND_DOWN */ -+ prv->mtu = 0; -+ for (i=0; idev_addr[i] = 0; -+ } -+ dev->addr_len = 0; -+#ifdef PHYSDEV_TYPE -+ dev->type = ARPHRD_VOID; /* ARPHRD_TUNNEL; */ -+#endif /* PHYSDEV_TYPE */ -+ -+ return 0; -+} -+ -+/* -+ * We call the clear routine to detach all ipsec tunnels from other devices. -+ */ -+DEBUG_NO_STATIC int -+ipsec_tunnel_clear(void) -+{ -+ int i; -+ struct device *ipsecdev = NULL, *prvdev; -+ struct ipsecpriv *prv; -+ char name[9]; -+ int ret; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_clear: .\n"); -+ -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ ipsecdev = ipsecdevices[i]; -+ if(ipsecdev != NULL) { -+ if((prv = (struct ipsecpriv *)(ipsecdev->priv))) { -+ prvdev = (struct device *)(prv->dev); -+ if(prvdev) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_clear: " -+ "physical device for device %s is %s\n", -+ name, prvdev->name); -+ if((ret = ipsec_tunnel_detach(ipsecdev))) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_clear: " -+ "error %d detatching device %s from device %s.\n", -+ ret, name, prvdev->name); -+ return ret; -+ } -+ } -+ } -+ } -+ } -+ return 0; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_ioctl(struct device *dev, struct ifreq *ifr, int cmd) -+{ -+ struct ipsectunnelconf *cf = (struct ipsectunnelconf *)&ifr->ifr_data; -+ struct ipsecpriv *prv = dev->priv; -+ struct device *them; /* physical device */ -+#ifdef CONFIG_IP_ALIAS -+ char *colon; -+ char realphysname[IFNAMSIZ]; -+#endif /* CONFIG_IP_ALIAS */ -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "device not supplied.\n"); -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "tncfg service call #%d for dev=%s\n", -+ cmd, -+ dev->name ? dev->name : "NULL"); -+ switch (cmd) { -+ /* attach a virtual ipsec? device to a physical device */ -+ case IPSEC_SET_DEV: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "calling ipsec_tunnel_attatch...\n"); -+#ifdef CONFIG_IP_ALIAS -+ /* If this is an IP alias interface, get its real physical name */ -+ strncpy(realphysname, cf->cf_name, IFNAMSIZ); -+ realphysname[IFNAMSIZ-1] = 0; -+ colon = strchr(realphysname, ':'); -+ if (colon) *colon = 0; -+ them = ipsec_dev_get(realphysname); -+#else /* CONFIG_IP_ALIAS */ -+ them = ipsec_dev_get(cf->cf_name); -+#endif /* CONFIG_IP_ALIAS */ -+ -+ if (them == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "physical device %s requested is null\n", -+ cf->cf_name); -+ ipsec_dev_put(them); -+ return -ENXIO; -+ } -+ -+#if 0 -+ if (them->flags & IFF_UP) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "physical device %s requested is not up.\n", -+ cf->cf_name); -+ ipsec_dev_put(them); -+ return -ENXIO; -+ } -+#endif -+ -+ if (prv && prv->dev) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "virtual device is already connected to %s.\n", -+ prv->dev->name ? prv->dev->name : "NULL"); -+ ipsec_dev_put(them); -+ return -EBUSY; -+ } -+ return ipsec_tunnel_attach(dev, them); -+ -+ case IPSEC_DEL_DEV: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "calling ipsec_tunnel_detatch.\n"); -+ if (! prv->dev) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "physical device not connected.\n"); -+ return -ENODEV; -+ } -+ return ipsec_tunnel_detach(dev); -+ -+ case IPSEC_CLR_DEV: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "calling ipsec_tunnel_clear.\n"); -+ return ipsec_tunnel_clear(); -+ -+ default: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "unknown command %d.\n", -+ cmd); -+ return -EOPNOTSUPP; -+ } -+} -+ -+int -+ipsec_device_event(struct notifier_block *unused, unsigned long event, void *ptr) -+{ -+ struct device *dev = ptr; -+ struct device *ipsec_dev; -+ struct ipsecpriv *priv; -+ int i; -+ -+ if (dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "dev=NULL for event type %ld.\n", -+ event); -+ return(NOTIFY_DONE); -+ } -+ -+ /* check for loopback devices */ -+ if (dev && (dev->flags & IFF_LOOPBACK)) { -+ return(NOTIFY_DONE); -+ } -+ -+ switch (event) { -+ case NETDEV_DOWN: -+ /* look very carefully at the scope of these compiler -+ directives before changing anything... -- RGB */ -+#ifdef NET_21 -+ case NETDEV_UNREGISTER: -+ switch (event) { -+ case NETDEV_DOWN: -+#endif /* NET_21 */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_DOWN dev=%s flags=%x\n", -+ dev->name, -+ dev->flags); -+ if(strncmp(dev->name, "ipsec", strlen("ipsec")) == 0) { -+ printk(KERN_CRIT "IPSEC EVENT: KLIPS device %s shut down.\n", -+ dev->name); -+ } -+#ifdef NET_21 -+ break; -+ case NETDEV_UNREGISTER: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_UNREGISTER dev=%s flags=%x\n", -+ dev->name, -+ dev->flags); -+ break; -+ } -+#endif /* NET_21 */ -+ -+ /* find the attached physical device and detach it. */ -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ ipsec_dev = ipsecdevices[i]; -+ -+ if(ipsec_dev) { -+ priv = (struct ipsecpriv *)(ipsec_dev->priv); -+ if(priv) { -+ ; -+ if(((struct device *)(priv->dev)) == dev) { -+ /* dev_close(ipsec_dev); */ -+ /* return */ ipsec_tunnel_detach(ipsec_dev); -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "device '%s' has been detached.\n", -+ ipsec_dev->name); -+ break; -+ } -+ } else { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "device '%s' has no private data space!\n", -+ ipsec_dev->name); -+ } -+ } -+ } -+ break; -+ case NETDEV_UP: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_UP dev=%s\n", -+ dev->name); -+ break; -+#ifdef NET_21 -+ case NETDEV_REBOOT: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_REBOOT dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_CHANGE: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_CHANGE dev=%s flags=%x\n", -+ dev->name, -+ dev->flags); -+ break; -+ case NETDEV_REGISTER: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_REGISTER dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_CHANGEMTU: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_CHANGEMTU dev=%s to mtu=%d\n", -+ dev->name, -+ dev->mtu); -+ break; -+ case NETDEV_CHANGEADDR: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_CHANGEADDR dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_GOING_DOWN: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_GOING_DOWN dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_CHANGENAME: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_CHANGENAME dev=%s\n", -+ dev->name); -+ break; -+#endif /* NET_21 */ -+ default: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "event type %ld unrecognised for dev=%s\n", -+ event, -+ dev->name); -+ break; -+ } -+ return NOTIFY_DONE; -+} -+ -+/* -+ * Called when an ipsec tunnel device is initialized. -+ * The ipsec tunnel device structure is passed to us. -+ */ -+ -+int -+ipsec_tunnel_init(struct device *dev) -+{ -+ int i; -+ -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_init: " -+ "allocating %lu bytes initialising device: %s\n", -+ (unsigned long) sizeof(struct ipsecpriv), -+ dev->name ? dev->name : "NULL"); -+ -+ /* Add our tunnel functions to the device */ -+ dev->open = ipsec_tunnel_open; -+ dev->stop = ipsec_tunnel_close; -+ dev->hard_start_xmit = ipsec_tunnel_start_xmit; -+ dev->get_stats = ipsec_tunnel_get_stats; -+ -+ dev->priv = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL); -+ if (dev->priv == NULL) -+ return -ENOMEM; -+ memset((caddr_t)(dev->priv), 0, sizeof(struct ipsecpriv)); -+ -+ for(i = 0; i < sizeof(zeroes); i++) { -+ ((__u8*)(zeroes))[i] = 0; -+ } -+ -+#ifndef NET_21 -+ /* Initialize the tunnel device structure */ -+ for (i = 0; i < DEV_NUMBUFFS; i++) -+ skb_queue_head_init(&dev->buffs[i]); -+#endif /* !NET_21 */ -+ -+ dev->set_multicast_list = NULL; -+ dev->do_ioctl = ipsec_tunnel_ioctl; -+ dev->hard_header = NULL; -+ dev->rebuild_header = NULL; -+ dev->set_mac_address = NULL; -+#ifndef NET_21 -+ dev->header_cache_bind = NULL; -+#endif /* !NET_21 */ -+ dev->header_cache_update= NULL; -+ -+#ifdef NET_21 -+/* prv->neigh_setup = NULL; */ -+ dev->neigh_setup = ipsec_tunnel_neigh_setup_dev; -+#endif /* NET_21 */ -+ dev->hard_header_len = 0; -+ dev->mtu = 0; -+ dev->addr_len = 0; -+ dev->type = ARPHRD_VOID; /* ARPHRD_TUNNEL; */ /* ARPHRD_ETHER; */ -+ dev->tx_queue_len = 10; /* Small queue */ -+ memset((caddr_t)(dev->broadcast),0xFF, ETH_ALEN); /* what if this is not attached to ethernet? */ -+ -+ /* New-style flags. */ -+ dev->flags = IFF_NOARP /* 0 */ /* Petr Novak */; -+#ifdef NET_21 -+ dev_init_buffers(dev); -+#else /* NET_21 */ -+ dev->family = AF_INET; -+ dev->pa_addr = 0; -+ dev->pa_brdaddr = 0; -+ dev->pa_mask = 0; -+ dev->pa_alen = 4; -+#endif /* NET_21 */ -+ -+ /* We're done. Have I forgotten anything? */ -+ return 0; -+} -+ -+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -+/* Module specific interface (but it links with the rest of IPSEC) */ -+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -+ -+int -+ipsec_tunnel_probe(struct device *dev) -+{ -+ ipsec_tunnel_init(dev); -+ return 0; -+} -+ -+struct device *ipsecdevices[IPSEC_NUM_IF]; -+ -+int -+ipsec_tunnel_init_devices(void) -+{ -+ int i; -+ char name[IFNAMSIZ]; -+ struct device *dev_ipsec; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_init_devices: " -+ "creating and registering IPSEC_NUM_IF=%u devices, allocating %lu per device, IFNAMSIZ=%u.\n", -+ IPSEC_NUM_IF, -+ (unsigned long) (sizeof(struct device) + IFNAMSIZ), -+ IFNAMSIZ); -+ -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ sprintf(name, IPSEC_DEV_FORMAT, i); -+ dev_ipsec = (struct device*)kmalloc(sizeof(struct device), GFP_KERNEL); -+ if (dev_ipsec == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_init_devices: " -+ "failed to allocate memory for device %s, quitting device init.\n", -+ name); -+ return -ENOMEM; -+ } -+ memset((caddr_t)dev_ipsec, 0, sizeof(struct device)); -+#ifdef NETDEV_23 -+ strncpy(dev_ipsec->name, name, sizeof(dev_ipsec->name)); -+#else /* NETDEV_23 */ -+ dev_ipsec->name = (char*)kmalloc(IFNAMSIZ, GFP_KERNEL); -+ if (dev_ipsec->name == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_init_devices: " -+ "failed to allocate memory for device %s name, quitting device init.\n", -+ name); -+ return -ENOMEM; -+ } -+ memset((caddr_t)dev_ipsec->name, 0, IFNAMSIZ); -+ strncpy(dev_ipsec->name, name, IFNAMSIZ); -+#endif /* NETDEV_23 */ -+ dev_ipsec->next = NULL; -+ dev_ipsec->init = &ipsec_tunnel_probe; -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_init_devices: " -+ "registering device %s\n", -+ dev_ipsec->name); -+ -+ /* reference and hold the device reference */ -+ dev_hold(dev_ipsec); -+ ipsecdevices[i]=dev_ipsec; -+ -+ if (register_netdev(dev_ipsec) != 0) { -+ KLIPS_PRINT(1 || debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_init_devices: " -+ "registering device %s failed, quitting device init.\n", -+ dev_ipsec->name); -+ return -EIO; -+ } else { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_init_devices: " -+ "registering device %s succeeded, continuing...\n", -+ dev_ipsec->name); -+ } -+ } -+ return 0; -+} -+ -+/* void */ -+int -+ipsec_tunnel_cleanup_devices(void) -+{ -+ int error = 0; -+ int i; -+ char name[32]; -+ struct device *dev_ipsec; -+ -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ dev_ipsec = ipsecdevices[i]; -+ if(dev_ipsec == NULL) { -+ continue; -+ } -+ -+ /* release reference */ -+ ipsecdevices[i]=NULL; -+ ipsec_dev_put(dev_ipsec); -+ -+ KLIPS_PRINT(debug_tunnel, "Unregistering %s (refcnt=%d)\n", -+ name, -+ atomic_read(&dev_ipsec->refcnt)); -+ unregister_netdev(dev_ipsec); -+ KLIPS_PRINT(debug_tunnel, "Unregisted %s\n", name); -+#ifndef NETDEV_23 -+ kfree(dev_ipsec->name); -+ dev_ipsec->name=NULL; -+#endif /* !NETDEV_23 */ -+ kfree(dev_ipsec->priv); -+ dev_ipsec->priv=NULL; -+ } -+ return error; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.220 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.219 2004/02/03 03:13:17 mcr -+ * minor edits for readability, and error reporting. -+ * -+ * Revision 1.218 2004/01/27 20:29:20 mcr -+ * fix for unregister_netdev() problem for underlying eth0. -+ * -+ * Revision 1.217 2003/12/10 01:14:27 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.216 2003/12/04 23:01:17 mcr -+ * removed ipsec_netlink.h -+ * -+ * Revision 1.215 2003/12/04 16:35:16 ken -+ * Fix for ATM devices where physdev->hard_header_len *is* correct -+ * -+ * Revision 1.214 2003/11/25 23:52:37 mcr -+ * fix typo in patch - ixs-> needed. -+ * -+ * Revision 1.213 2003/11/24 18:25:49 mcr -+ * patch from willy@w.ods.org to fix problems with ATM interfaces. -+ * -+ * Revision 1.212 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.211.2.2 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.211.2.1 2003/09/21 13:59:56 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.211 2003/09/10 16:46:30 mcr -+ * patches for 2.4 backport/2.6 existence. -+ * -+ * Revision 1.210 2003/07/31 22:47:16 mcr -+ * preliminary (untested by FS-team) 2.5 patches. -+ * -+ * Revision 1.209 2003/06/22 21:28:43 mcr -+ * inability to unload module was caused by calls to dev_get -+ * (ipsec_dev_get), to gather a device from a name. There is -+ * simply no reason to look the devices up - they should be kept -+ * in a nice array, ready for use. -+ * -+ * Revision 1.208 2003/06/22 21:25:07 mcr -+ * all staticly counted ipsecXXX device support removed. -+ * -+ * Revision 1.207 2003/04/02 20:15:37 mcr -+ * fix for PR#204 - do not clear connection tracking info if we -+ * the packet is being sent in the clear. -+ * -+ * Revision 1.206 2003/02/12 19:32:51 rgb -+ * Refactored file to: -+ * ipsec_xmit.c -+ * ipsec_xmit.h -+ * ipsec_mast.c -+ * -+ * Revision 1.205 2003/02/06 17:47:00 rgb -+ * -+ * Remove unused ipsec_tunnel_lock() and ipsec_tunnel_unlock() code. -+ * Refactor ipsec_tunnel_start_xmit() further into: -+ * ipsec_xmit_sanity_check_dev() -+ * ipsec_xmit_sanity_check_skb() -+ * ipsec_xmit_strip_hard_header() -+ * ipsec_xmit_restore_hard_header() -+ * ipsec_xmit_send() -+ * ipsec_xmit_cleanup() -+ * and start a skeletal ipsec_mast_start_xmit() . -+ * -+ * Revision 1.204 2003/02/06 06:43:46 rgb -+ * -+ * Refactor ipsec_tunnel_start_xmit, bringing out: -+ * ipsec_xmit_SAlookup -+ * ipsec_xmit_encap_once -+ * ipsec_xmit_encap_bundle -+ * -+ * Revision 1.203 2003/02/06 02:21:34 rgb -+ * -+ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h . -+ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr". -+ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code. -+ * -+ * Revision 1.202 2003/01/03 07:38:01 rgb -+ * -+ * Start to refactor ipsec_tunnel_start_xmit() by putting local variables -+ * into struct ipsec_xmit_state and renaming a few variables to give more -+ * unique or searchable names. -+ * -+ * Revision 1.201 2003/01/03 00:31:28 rgb -+ * -+ * Clean up memset usage, including fixing 2 places where keys were not -+ * properly wiped. -+ * -+ * Revision 1.200 2002/12/06 02:24:02 mcr -+ * patches for compiling against SUSE 8.1 kernels. Requires -+ * an additional -DSUSE_LINUX_2_4_19_IS_STUPID. -+ * -+ * Revision 1.199 2002/10/12 23:11:53 dhr -+ * -+ * [KenB + DHR] more 64-bit cleanup -+ * -+ * Revision 1.198 2002/10/05 05:02:58 dhr -+ * -+ * C labels go on statements -+ * -+ * Revision 1.197 2002/09/20 05:01:50 rgb -+ * Added compiler directive to switch on IP options and fix IP options bug. -+ * Make ip->ihl treatment consistent using shifts rather than multiplications. -+ * Check for large enough packet before accessing udp header for IKE bypass. -+ * Added memory allocation debugging. -+ * Fixed potential memory allocation failure-induced oops. -+ * -+ * Revision 1.196 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.195 2002/07/23 03:36:07 rgb -+ * Fixed 2.2 device initialisation hang. -+ * -+ * Revision 1.194 2002/05/27 21:40:34 rgb -+ * Set unused ipsec devices to ARPHRD_VOID to avoid confusing iproute2. -+ * Cleaned up intermediate step to dynamic device allocation. -+ * -+ * Revision 1.193 2002/05/27 19:31:36 rgb -+ * Convert to dynamic ipsec device allocation. -+ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT. -+ * -+ * Revision 1.192 2002/05/23 07:14:28 rgb -+ * Added refcount code. -+ * Cleaned up %p variants to 0p%p for test suite cleanup. -+ * -+ * Revision 1.191 2002/05/14 02:34:37 rgb -+ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips, -+ * ipsec_sa or ipsec_sa. -+ * -+ * Revision 1.190 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.189 2002/04/24 07:36:32 mcr -+ * Moved from ./klips/net/ipsec/ipsec_tunnel.c,v -+ * -+ * Revision 1.188 2002/04/20 00:12:25 rgb -+ * Added esp IV CBC attack fix, disabled. -+ * -+ * Revision 1.187 2002/03/23 19:55:17 rgb -+ * Fix for 2.2 local IKE fragmentation blackhole. Still won't work if -+ * iptraf or another pcap app is running. -+ * -+ * Revision 1.186 2002/03/19 03:26:22 rgb -+ * Applied DHR's tunnel patch to streamline IKE/specialSA processing. -+ * -+ * Revision 1.185 2002/02/20 04:13:05 rgb -+ * Send back ICMP_PKT_FILTERED upon %reject. -+ * -+ * Revision 1.184 2002/01/29 17:17:56 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.183 2002/01/29 04:00:53 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.182 2002/01/29 02:13:18 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.181 2002/01/07 20:00:33 rgb -+ * Added IKE destination port debugging. -+ * -+ * Revision 1.180 2001/12/21 21:49:54 rgb -+ * Fixed bug as a result of moving IKE bypass above %trap/%hold code. -+ * -+ * Revision 1.179 2001/12/19 21:08:14 rgb -+ * Added transport protocol ports to ipsec_print_ip(). -+ * Update eroute info for non-SA targets. -+ * Added obey DF code disabled. -+ * Fixed formatting bugs in ipsec_tunnel_hard_header(). -+ * -+ * Revision 1.178 2001/12/05 09:36:10 rgb -+ * Moved the UDP/500 IKE check just above the %hold/%trap checks to avoid -+ * IKE packets being stolen by the %hold (and returned to the sending KMd -+ * in an ACQUIRE, ironically ;-). -+ * -+ * Revision 1.177 2001/11/26 09:23:50 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.170.2.1 2001/09/25 02:28:27 mcr -+ * struct tdb -> struct ipsec_sa. -+ * lifetime checks moved to common routines. -+ * cleaned up includes. -+ * -+ * Revision 1.170.2.2 2001/10/22 21:08:01 mcr -+ * include des.h, removed phony prototypes and fixed calling -+ * conventions to match real prototypes. -+ * -+ * Revision 1.176 2001/11/09 18:32:31 rgb -+ * Added Hans Schultz' fragmented UDP/500 IKE socket port selector. -+ * -+ * Revision 1.175 2001/11/06 20:47:00 rgb -+ * Added Eric Espie's TRAPSUBNET fix, minus spin-lock-bh dabbling. -+ * -+ * Revision 1.174 2001/11/06 19:50:43 rgb -+ * Moved IP_SEND, ICMP_SEND, DEV_QUEUE_XMIT macros to ipsec_tunnel.h for -+ * use also by pfkey_v2_parser.c -+ * -+ * Revision 1.173 2001/10/29 21:53:44 henry -+ * tone down the device-down message slightly, until we can make it smarter -+ * -+ * Revision 1.172 2001/10/26 04:59:37 rgb -+ * Added a critical level syslog message if an ipsec device goes down. -+ * -+ * Revision 1.171 2001/10/18 04:45:21 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.170 2001/09/25 00:09:50 rgb -+ * Added NetCelo's TRAPSUBNET code to convert a new type TRAPSUBNET into a -+ * HOLD. -+ * -+ * Revision 1.169 2001/09/15 16:24:05 rgb -+ * Re-inject first and last HOLD packet when an eroute REPLACE is done. -+ * -+ * Revision 1.168 2001/09/14 16:58:37 rgb -+ * Added support for storing the first and last packets through a HOLD. -+ * -+ * Revision 1.167 2001/09/08 21:13:33 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.166 2001/08/27 19:47:59 rgb -+ * Clear tdb before usage. -+ * Added comment: clear IF before calling routing? -+ * -+ * Revision 1.165 2001/07/03 01:23:53 rgb -+ * Send back ICMP iff DF set, !ICMP, offset==0, sysctl_icmp, iph->tot_len > -+ * emtu, and don't drop. -+ * -+ * Revision 1.164 2001/06/14 19:35:10 rgb -+ * Update copyright date. -+ * -+ * Revision 1.163 2001/06/06 20:28:51 rgb -+ * Added sanity checks for NULL skbs and devices. -+ * Added more debugging output to various functions. -+ * Removed redundant dev->priv argument to ipsec_tunnel_{at,de}tach(). -+ * Renamed ipsec_tunnel_attach() virtual and physical device arguments. -+ * Corrected neigh_setup() device function assignment. -+ * Keep valid pointers to ipsec_tunnel_*() on detach. -+ * Set dev->type to the originally-initiallised value. -+ * -+ * Revision 1.162 2001/06/01 07:28:04 rgb -+ * Added sanity checks for detached devices. Don't down virtual devices -+ * to prevent packets going out in the clear if the detached device comes -+ * back up. -+ * -+ * Revision 1.161 2001/05/30 08:14:52 rgb -+ * Removed vestiges of esp-null transforms. -+ * NetDev Notifier instrumentation to track down disappearing devices. -+ * -+ * Revision 1.160 2001/05/29 05:15:12 rgb -+ * Added SS' PMTU patch which notifies sender if packet doesn't fit -+ * physical MTU (if it wasn't ICMP) and then drops it. -+ * -+ * Revision 1.159 2001/05/27 06:12:12 rgb -+ * Added structures for pid, packet count and last access time to eroute. -+ * Added packet count to beginning of /proc/net/ipsec_eroute. -+ * -+ * Revision 1.158 2001/05/24 05:39:33 rgb -+ * Applied source zeroing to 2.2 ip_route_output() call as well to enable -+ * PASS eroutes for opportunism. -+ * -+ * Revision 1.157 2001/05/23 22:35:28 rgb -+ * 2.4 source override simplification. -+ * -+ * Revision 1.156 2001/05/23 21:41:31 rgb -+ * Added error return code printing on ip_route_output(). -+ * -+ * Revision 1.155 2001/05/23 05:09:13 rgb -+ * Fixed incorrect ip_route_output() failure message. -+ * -+ * Revision 1.154 2001/05/21 14:53:31 rgb -+ * Added debug statement for case when ip_route_output() fails, causing -+ * packet to be dropped, but log looked ok. -+ * -+ * Revision 1.153 2001/05/19 02:37:54 rgb -+ * Fixed missing comment termination. -+ * -+ * Revision 1.152 2001/05/19 02:35:50 rgb -+ * Debug code optimisation for non-debug speed. -+ * Kernel version compiler define comments. -+ * 2.2 and 2.4 kernel ip_send device and ip debug output added. -+ * -+ * Revision 1.151 2001/05/18 16:17:35 rgb -+ * Changed reference from "magic" to "shunt" SAs. -+ * -+ * Revision 1.150 2001/05/18 16:12:19 rgb -+ * Changed UDP/500 bypass test from 3 nested ifs to one anded if. -+ * -+ * Revision 1.149 2001/05/16 04:39:33 rgb -+ * Add default == eroute.dest to IKE bypass conditions for magic eroutes. -+ * -+ * Revision 1.148 2001/05/05 03:31:41 rgb -+ * IP frag debugging updates and enhancements. -+ * -+ * Revision 1.147 2001/05/03 19:41:40 rgb -+ * Added SS' skb_cow fix for 2.4.4. -+ * -+ * Revision 1.146 2001/04/30 19:28:16 rgb -+ * Update for 2.4.4. ip_select_ident() now has 3 args. -+ * -+ * Revision 1.145 2001/04/23 14:56:10 rgb -+ * Added spin_lock() check to prevent double-locking for multiple -+ * transforms and hence kernel lock-ups with SMP kernels. -+ * -+ * Revision 1.144 2001/04/21 23:04:45 rgb -+ * Define out skb->used for 2.4 kernels. -+ * Check if soft expire has already been sent before sending another to -+ * prevent ACQUIRE flooding. -+ * -+ * Revision 1.143 2001/03/16 07:37:21 rgb -+ * Added comments to all #endifs. -+ * -+ * Revision 1.142 2001/02/28 05:03:27 rgb -+ * Clean up and rationalise startup messages. -+ * -+ * Revision 1.141 2001/02/27 22:24:54 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.140 2001/02/27 06:40:12 rgb -+ * Fixed TRAP->HOLD eroute byte order. -+ * -+ * Revision 1.139 2001/02/26 20:38:59 rgb -+ * Added compiler defines for 2.4.x-specific code. -+ * -+ * Revision 1.138 2001/02/26 19:57:27 rgb -+ * Implement magic SAs %drop, %reject, %trap, %hold, %pass as part -+ * of the new SPD and to support opportunistic. -+ * Drop sysctl_ipsec_{no_eroute_pass,opportunistic}, replaced by magic SAs. -+ * -+ * Revision 1.137 2001/02/19 22:29:49 rgb -+ * Fixes for presence of active ipv6 segments which share ipsec physical -+ * device (gg). -+ * -+ * Revision 1.136 2001/01/29 22:30:38 rgb -+ * Fixed minor acquire debug printing bug. -+ * -+ * Revision 1.135 2001/01/29 22:19:45 rgb -+ * Zero source address for 2.4 bypass route lookup. -+ * -+ * Revision 1.134 2001/01/23 20:19:49 rgb -+ * 2.4 fix to remove removed is_clone member. -+ * -+ * Revision 1.133 2000/12/09 22:08:35 rgb -+ * Fix NET_23 bug, should be NETDEV_23. -+ * -+ * Revision 1.132 2000/12/01 06:54:50 rgb -+ * Fix for new 2.4 IP TTL default variable name. -+ * -+ * Revision 1.131 2000/11/09 20:52:15 rgb -+ * More spinlock shuffling, locking earlier and unlocking later in rcv to -+ * include ipcomp and prevent races, renaming some tdb variables that got -+ * forgotten, moving some unlocks to include tdbs and adding a missing -+ * unlock. Thanks to Svenning for some of these. -+ * -+ * Revision 1.130 2000/11/09 20:11:22 rgb -+ * Minor shuffles to fix non-standard kernel config option selection. -+ * -+ * Revision 1.129 2000/11/06 04:32:49 rgb -+ * Clean up debug printing. -+ * Copy skb->protocol for all kernel versions. -+ * Ditched spin_lock_irqsave in favour of spin_lock. -+ * Disabled TTL decrement, done in ip_forward. -+ * Added debug printing before pfkey_acquire(). -+ * Fixed printk-deltdbchain-spin_lock races (Svenning). -+ * Use defaultTTL for 2.1+ kernels. -+ * Add Svenning's adaptive content compression. -+ * Fix up debug display arguments. -+ * -+ * Revision 1.128 2000/09/28 00:58:57 rgb -+ * Moved the IKE passthrough check after the eroute lookup so we can pass -+ * IKE through intermediate tunnels. -+ * -+ * Revision 1.127 2000/09/22 17:52:11 rgb -+ * Fixed misleading ipcomp debug output. -+ * -+ * Revision 1.126 2000/09/22 04:22:56 rgb -+ * Fixed dumb spi->cpi conversion error. -+ * -+ * Revision 1.125 2000/09/21 04:34:48 rgb -+ * A few debug-specific things should be hidden under -+ * CONFIG_IPSEC_DEBUG.(MB) -+ * Improved ip_send() error handling.(MB) -+ * -+ * Revision 1.124 2000/09/21 03:40:58 rgb -+ * Added more debugging to try and track down the cpi outward copy problem. -+ * -+ * Revision 1.123 2000/09/19 07:08:49 rgb -+ * Added debugging to outgoing compression report. -+ * -+ * Revision 1.122 2000/09/18 19:21:26 henry -+ * RGB-supplied fix for RH5.2 problem -+ * -+ * Revision 1.121 2000/09/17 21:05:09 rgb -+ * Added tdb to skb_compress call to write in cpi. -+ * -+ * Revision 1.120 2000/09/17 16:57:16 rgb -+ * Added Svenning's patch to remove restriction of ipcomp to innermost -+ * transform. -+ * -+ * Revision 1.119 2000/09/15 11:37:01 rgb -+ * Merge in heavily modified Svenning Soerensen's -+ * IPCOMP zlib deflate code. -+ * -+ * Revision 1.118 2000/09/15 04:57:16 rgb -+ * Moved debug output after sanity check. -+ * Added tos copy sysctl. -+ * -+ * Revision 1.117 2000/09/12 03:22:51 rgb -+ * Converted ipsec_icmp, no_eroute_pass, opportunistic and #if0 debugs to -+ * sysctl. -+ * -+ * Revision 1.116 2000/09/08 19:18:19 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * Added outgoing opportunistic hook, ifdef'ed out. -+ * -+ * Revision 1.115 2000/08/30 05:27:29 rgb -+ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst. -+ * Kill remainder of tdb_xform, tdb_xdata, xformsw. -+ * -+ * Revision 1.114 2000/08/28 18:15:46 rgb -+ * Added MB's nf-debug reset patch. -+ * -+ * Revision 1.113 2000/08/27 02:26:40 rgb -+ * Send all no-eroute-bypass, pluto-bypass and passthrough packets through -+ * fragmentation machinery for 2.0, 2.2 and 2.4 kernels. -+ * -+ * Revision 1.112 2000/08/20 21:37:33 rgb -+ * Activated pfkey_expire() calls. -+ * Added a hard/soft expiry parameter to pfkey_expire(). (Momchil) -+ * Re-arranged the order of soft and hard expiry to conform to RFC2367. -+ * Clean up references to CONFIG_IPSEC_PFKEYv2. -+ * -+ * Revision 1.111 2000/08/01 14:51:51 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.110 2000/07/28 14:58:31 rgb -+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. -+ * -+ * Revision 1.109 2000/07/28 13:50:54 rgb -+ * Changed enet_statistics to net_device_stats and added back compatibility -+ * for pre-2.1.19. -+ * -+ * Revision 1.108 2000/05/16 03:03:11 rgb -+ * Updates for 2.3.99pre8 from MB. -+ * -+ * Revision 1.107 2000/05/10 23:08:21 rgb -+ * Print a debug warning about bogus packets received by the outgoing -+ * processing machinery only when klipsdebug is not set to none. -+ * Comment out the device initialisation informational messages. -+ * -+ * Revision 1.106 2000/05/10 19:17:14 rgb -+ * Define an IP_SEND macro, intending to have all packet passthroughs -+ * use fragmentation. This didn't quite work, but is a step in the -+ * right direction. -+ * Added buffer allocation debugging statements. -+ * Added configure option to shut off no eroute passthrough. -+ * Only check usetime against soft and hard limits if the tdb has been -+ * used. -+ * Cast output of ntohl so that the broken prototype doesn't make our -+ * compile noisy. -+ * -+ * Revision 1.105 2000/03/22 16:15:37 rgb -+ * Fixed renaming of dev_get (MB). -+ * -+ * Revision 1.104 2000/03/16 14:04:15 rgb -+ * Indented headers for readability. -+ * Fixed debug scope to enable compilation with debug off. -+ * Added macros for ip_chk_addr and IS_MYADDR for identifying self. -+ * -+ * Revision 1.103 2000/03/16 07:11:07 rgb -+ * Hardcode PF_KEYv2 support. -+ * Fixed bug which allowed UDP/500 packet from another machine -+ * through in the clear. -+ * Added disabled skb->protocol fix for ISDN/ASYNC PPP from Matjaz Godec. -+ * -+ * Revision 1.102 2000/03/14 12:26:59 rgb -+ * Added skb->nfct support for clearing netfilter conntrack bits (MB). -+ * -+ * Revision 1.101 2000/02/14 21:05:22 rgb -+ * Added MB's netif_queue fix for kernels 2.3.43+. -+ * -+ * Revision 1.100 2000/01/26 10:04:57 rgb -+ * Fixed noisy 2.0 printk arguments. -+ * -+ * Revision 1.99 2000/01/21 06:16:25 rgb -+ * Added sanity checks on skb_push(), skb_pull() to prevent panics. -+ * Switched to AF_ENCAP macro. -+ * Shortened debug output per packet and re-arranging debug_tunnel -+ * bitmap flags, while retaining necessary information to avoid -+ * trampling the kernel print ring buffer. -+ * Reformatted recursion switch code. -+ * Changed all references to tdb_proto to tdb_said.proto for clarity. -+ * -+ * Revision 1.98 2000/01/13 08:09:31 rgb -+ * Shuffled debug_tunnel switches to focus output. -+ * Fixed outgoing recursion bug, limiting to recursing only if the remote -+ * SG changes and if it is valid, ie. not passthrough. -+ * Clarified a number of debug messages. -+ * -+ * Revision 1.97 2000/01/10 16:37:16 rgb -+ * MB support for new ip_select_ident() upon disappearance of -+ * ip_id_count in 2.3.36+. -+ * -+ * Revision 1.96 1999/12/31 14:59:08 rgb -+ * MB fix to use new skb_copy_expand in kernel 2.3.35. -+ * -+ * Revision 1.95 1999/12/29 21:15:44 rgb -+ * Fix tncfg to aliased device bug. -+ * -+ * Revision 1.94 1999/12/22 04:26:06 rgb -+ * Converted all 'static' functions to 'DEBUG_NO_STATIC' to enable -+ * debugging by providing external labels to all functions with debugging -+ * turned on. -+ * -+ * Revision 1.93 1999/12/13 13:30:14 rgb -+ * Changed MTU reports and HW address reporting back to debug only. -+ * -+ * Revision 1.92 1999/12/07 18:57:56 rgb -+ * Fix PFKEY symbol compile error (SADB_*) without pfkey enabled. -+ * -+ * Revision 1.91 1999/12/01 22:15:36 rgb -+ * Add checks for LARVAL and DEAD SAs. -+ * Change state of SA from MATURE to DYING when a soft lifetime is -+ * reached and print debug warning. -+ * -+ * Revision 1.90 1999/11/23 23:04:04 rgb -+ * Use provided macro ADDRTOA_BUF instead of hardcoded value. -+ * Sort out pfkey and freeswan headers, putting them in a library path. -+ * -+ * Revision 1.89 1999/11/18 18:50:59 rgb -+ * Changed all device registrations for static linking to -+ * dynamic to reduce the number and size of patches. -+ * -+ * Revision 1.88 1999/11/18 04:09:19 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.87 1999/11/17 15:53:40 rgb -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * -+ * Revision 1.86 1999/10/16 18:25:37 rgb -+ * Moved SA lifetime expiry checks before packet processing. -+ * Expire SA on replay counter rollover. -+ * -+ * Revision 1.85 1999/10/16 04:24:31 rgb -+ * Add stats for time since last packet. -+ * -+ * Revision 1.84 1999/10/16 00:30:47 rgb -+ * Added SA lifetime counting. -+ * -+ * Revision 1.83 1999/10/15 22:15:57 rgb -+ * Clean out cruft. -+ * Add debugging. -+ * -+ * Revision 1.82 1999/10/08 18:26:19 rgb -+ * Fix 2.0.3x outgoing fragmented packet memory leak. -+ * -+ * Revision 1.81 1999/10/05 02:38:54 rgb -+ * Lower the default mtu of virtual devices to 16260. -+ * -+ * Revision 1.80 1999/10/03 18:56:41 rgb -+ * Spinlock support for 2.3.xx. -+ * Don't forget to undo spinlocks on error! -+ * Check for valid eroute before copying the structure. -+ * -+ * Revision 1.79 1999/10/01 15:44:53 rgb -+ * Move spinlock header include to 2.1> scope. -+ * -+ * Revision 1.78 1999/10/01 00:02:43 rgb -+ * Added tdb structure locking. -+ * Added eroute structure locking. -+ * -+ * Revision 1.77 1999/09/30 02:52:29 rgb -+ * Add Marc Boucher's Copy-On-Write code (same as ipsec_rcv.c). -+ * -+ * Revision 1.76 1999/09/25 19:31:27 rgb -+ * Refine MSS hack to affect SYN, but not SYN+ACK packets. -+ * -+ * Revision 1.75 1999/09/24 22:52:38 rgb -+ * Fix two things broken in 2.0.38 by trying to fix network notifiers. -+ * -+ * Revision 1.74 1999/09/24 00:30:37 rgb -+ * Add test for changed source as well as destination to check for -+ * recursion. -+ * -+ * Revision 1.73 1999/09/23 20:52:24 rgb -+ * Add James Morris' MSS hack patch, disabled. -+ * -+ * Revision 1.72 1999/09/23 20:22:40 rgb -+ * Enable, tidy and fix network notifier code. -+ * -+ * Revision 1.71 1999/09/23 18:09:05 rgb -+ * Clean up 2.2.x fragmenting traces. -+ * Disable dev->type switching, forcing ARPHRD_TUNNEL. -+ * -+ * Revision 1.70 1999/09/22 14:14:24 rgb -+ * Add sanity checks for revectored calls to prevent calling a downed I/F. -+ * -+ * Revision 1.69 1999/09/21 15:00:57 rgb -+ * Add Marc Boucher's packet size check. -+ * Flesh out network device notifier code. -+ * -+ * Revision 1.68 1999/09/18 11:39:57 rgb -+ * Start to add (disabled) netdevice notifier code. -+ * -+ * Revision 1.67 1999/09/17 23:44:40 rgb -+ * Add a comment warning potential code hackers to stay away from mac.raw. -+ * -+ * Revision 1.66 1999/09/17 18:04:02 rgb -+ * Add fix for unpredictable hard_header_len for ISDN folks (thanks MB). -+ * Ditch TTL decrement in 2.2 (MB). -+ * -+ * Revision 1.65 1999/09/15 23:15:35 henry -+ * Marc Boucher's PPP fixes -+ * -+ * Revision 1.64 1999/09/07 13:40:53 rgb -+ * Ditch unreliable references to skb->mac.raw. -+ * -+ * Revision 1.63 1999/08/28 11:33:09 rgb -+ * Check for null skb->mac pointer. -+ * -+ * Revision 1.62 1999/08/28 02:02:30 rgb -+ * Add Marc Boucher's fix for properly dealing with skb->sk. -+ * -+ * Revision 1.61 1999/08/27 05:23:05 rgb -+ * Clean up skb->data/raw/nh/h manipulation. -+ * Add Marc Boucher's mods to aid tcpdump. -+ * Add sanity checks to skb->raw/nh/h pointer copies in skb_copy_expand. -+ * Re-order hard_header stripping -- might be able to remove it... -+ * -+ * Revision 1.60 1999/08/26 20:01:02 rgb -+ * Tidy up compiler directives and macros. -+ * Re-enable ICMP for tunnels where inner_dst != outer_dst. -+ * Remove unnecessary skb->dev = physdev assignment affecting 2.2.x. -+ * -+ * Revision 1.59 1999/08/25 15:44:41 rgb -+ * Clean up from 2.2.x instrumenting for compilation under 2.0.36. -+ * -+ * Revision 1.58 1999/08/25 15:00:54 rgb -+ * Add dst cache code for 2.2.xx. -+ * Add sanity check for skb packet header pointers. -+ * Add/modify debugging instrumentation to *_start_xmit, *_hard_header and -+ * *_rebuild_header. -+ * Add neigh_* cache code. -+ * Change dev->type back to ARPHRD_TUNNEL. -+ * -+ * Revision 1.57 1999/08/17 21:50:23 rgb -+ * Fixed minor debug output bugs. -+ * Regrouped error recovery exit code. -+ * Added compiler directives to remove unwanted code and symbols. -+ * Shut off ICMP messages: to be refined to only send ICMP to remote systems. -+ * Add debugging code for output function addresses. -+ * Fix minor bug in (possibly unused) header_cache_bind function. -+ * Add device neighbour caching code. -+ * Change dev->type from ARPHRD_TUNNEL to physdev->type. -+ * -+ * Revision 1.56 1999/08/03 17:22:56 rgb -+ * Debug output clarification using KERN_* macros. Other inactive changes -+ * added. -+ * -+ * Revision 1.55 1999/08/03 16:58:46 rgb -+ * Fix skb_copy_expand size bug. Was getting incorrect size. -+ * -+ * Revision 1.54 1999/07/14 19:32:38 rgb -+ * Fix oversize packet crash and ssh stalling in 2.2.x kernels. -+ * -+ * Revision 1.53 1999/06/10 15:44:02 rgb -+ * Minor reformatting and clean-up. -+ * -+ * Revision 1.52 1999/05/09 03:25:36 rgb -+ * Fix bug introduced by 2.2 quick-and-dirty patch. -+ * -+ * Revision 1.51 1999/05/08 21:24:59 rgb -+ * Add casting to silence the 2.2.x compile. -+ * -+ * Revision 1.50 1999/05/05 22:02:32 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.49 1999/04/29 15:18:52 rgb -+ * Change gettdb parameter to a pointer to reduce stack loading and -+ * facilitate parameter sanity checking. -+ * Fix undetected bug that might have tried to access a null pointer. -+ * Eliminate unnessessary usage of tdb_xform member to further switch -+ * away from the transform switch to the algorithm switch. -+ * Add return values to init and cleanup functions. -+ * -+ * Revision 1.48 1999/04/16 15:38:00 rgb -+ * Minor rearrangement of freeing code to avoid memory leaks with impossible or -+ * rare situations. -+ * -+ * Revision 1.47 1999/04/15 15:37:25 rgb -+ * Forward check changes from POST1_00 branch. -+ * -+ * Revision 1.32.2.4 1999/04/13 21:00:18 rgb -+ * Ditch 'things I wish I had known before...'. -+ * -+ * Revision 1.32.2.3 1999/04/13 20:34:38 rgb -+ * Free skb after fragmentation. -+ * Use stats more effectively. -+ * Add I/F to mtu notch-down reporting. -+ * -+ * Revision 1.32.2.2 1999/04/02 04:26:14 rgb -+ * Backcheck from HEAD, pre1.0. -+ * -+ * Revision 1.46 1999/04/11 00:29:00 henry -+ * GPL boilerplate -+ * -+ * Revision 1.45 1999/04/07 15:42:01 rgb -+ * Fix mtu/ping bug AGAIN! -+ * -+ * Revision 1.44 1999/04/06 04:54:27 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.43 1999/04/04 03:57:07 rgb -+ * ip_fragment() doesn't free the supplied skb. Freed. -+ * -+ * Revision 1.42 1999/04/01 23:27:15 rgb -+ * Preload size of virtual mtu. -+ * -+ * Revision 1.41 1999/04/01 09:31:23 rgb -+ * Invert meaning of ICMP PMTUD config option and clarify. -+ * Code clean-up. -+ * -+ * Revision 1.40 1999/04/01 04:37:17 rgb -+ * SSH stalling bug fix. -+ * -+ * Revision 1.39 1999/03/31 23:44:28 rgb -+ * Don't send ICMP on DF and frag_off. -+ * -+ * Revision 1.38 1999/03/31 15:20:10 rgb -+ * Quiet down debugging. -+ * -+ * Revision 1.37 1999/03/31 08:30:31 rgb -+ * Add switch to shut off ICMP PMTUD packets. -+ * -+ * Revision 1.36 1999/03/31 05:44:47 rgb -+ * Keep PMTU reduction private. -+ * -+ * Revision 1.35 1999/03/27 15:13:02 rgb -+ * PMTU/fragmentation bug fix. -+ * -+ * Revision 1.34 1999/03/17 21:19:26 rgb -+ * Fix kmalloc nonatomic bug. -+ * -+ * Revision 1.33 1999/03/17 15:38:42 rgb -+ * Code clean-up. -+ * ESP_NULL IV bug fix. -+ * -+ * Revision 1.32 1999/03/01 20:44:25 rgb -+ * Code clean-up. -+ * Memory leak bug fix. -+ * -+ * Revision 1.31 1999/02/27 00:02:09 rgb -+ * Tune to report the MTU reduction once, rather than after every recursion -+ * through the encapsulating code, preventing tcp stream stalling. -+ * -+ * Revision 1.30 1999/02/24 20:21:01 rgb -+ * Reformat debug printk's. -+ * Fix recursive encapsulation, dynamic MTU bugs and add debugging code. -+ * Clean-up. -+ * -+ * Revision 1.29 1999/02/22 17:08:14 rgb -+ * Fix recursive encapsulation code. -+ * -+ * Revision 1.28 1999/02/19 18:27:02 rgb -+ * Improve DF, fragmentation and PMTU behaviour and add dynamic MTU discovery. -+ * -+ * Revision 1.27 1999/02/17 16:51:37 rgb -+ * Clean out unused cruft. -+ * Temporarily tone down volume of debug output. -+ * Temporarily shut off fragment rejection. -+ * Disabled temporary failed recursive encapsulation loop. -+ * -+ * Revision 1.26 1999/02/12 21:21:26 rgb -+ * Move KLIPS_PRINT to ipsec_netlink.h for accessibility. -+ * -+ * Revision 1.25 1999/02/11 19:38:27 rgb -+ * More clean-up. -+ * Add sanity checking for skb_copy_expand() to prevent kernel panics on -+ * skb_put() values out of range. -+ * Fix head/tailroom calculation causing skb_put() out-of-range values. -+ * Fix return values to prevent 'nonatomic alloc_skb' warnings. -+ * Allocate new skb iff needed. -+ * Added more debug statements. -+ * Make headroom depend on structure, not hard-coded values. -+ * -+ * Revision 1.24 1999/02/10 23:20:33 rgb -+ * Shut up annoying 'statement has no effect' compiler warnings with -+ * debugging compiled out. -+ * -+ * Revision 1.23 1999/02/10 22:36:30 rgb -+ * Clean-up obsolete, unused and messy code. -+ * Converted most IPSEC_DEBUG statements to KLIPS_PRINT macros. -+ * Rename ipsec_tunnel_do_xmit to ipsec_tunnel_start_xmit and eliminated -+ * original ipsec_tunnel_start_xmit. -+ * Send all packet with different inner and outer destinations directly to -+ * the attached physical device, rather than back through ip_forward, -+ * preventing disappearing routes problems. -+ * Do sanity checking before investing too much CPU in allocating new -+ * structures. -+ * Fail on IP header options: We cannot process them yet. -+ * Add some helpful comments. -+ * Use virtual device for parameters instead of physical device. -+ * -+ * Revision 1.22 1999/02/10 03:03:02 rgb -+ * Duh. Fixed the TTL bug: forgot to update the checksum. -+ * -+ * Revision 1.21 1999/02/09 23:17:53 rgb -+ * Add structure members to ipsec_print_ip debug function. -+ * Temporarily fix TTL bug preventing tunnel mode from functioning. -+ * -+ * Revision 1.20 1999/02/09 00:14:25 rgb -+ * Add KLIPSPRINT macro. (Not used yet, though.) -+ * Delete old ip_tunnel code (BADCODE). -+ * Decrement TTL in outgoing packet. -+ * Set TTL on new IPIP_TUNNEL to default, not existing packet TTL. -+ * Delete ethernet only feature and fix hard-coded hard_header_len. -+ * -+ * Revision 1.19 1999/01/29 17:56:22 rgb -+ * 64-bit re-fix submitted by Peter Onion. -+ * -+ * Revision 1.18 1999/01/28 22:43:24 rgb -+ * Fixed bug in ipsec_print_ip that caused an OOPS, found by P.Onion. -+ * -+ * Revision 1.17 1999/01/26 02:08:16 rgb -+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro. -+ * Removed dead code. -+ * -+ * Revision 1.16 1999/01/22 06:25:26 rgb -+ * Cruft clean-out. -+ * Added algorithm switch code. -+ * 64-bit clean-up. -+ * Passthrough on IPIP protocol, spi 0x0 fix. -+ * Enhanced debugging. -+ * -+ * Revision 1.15 1998/12/01 13:22:04 rgb -+ * Added support for debug printing of version info. -+ * -+ * Revision 1.14 1998/11/30 13:22:55 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.13 1998/11/17 21:13:52 rgb -+ * Put IKE port bypass debug output in user-switched debug statements. -+ * -+ * Revision 1.12 1998/11/13 13:20:25 rgb -+ * Fixed ntohs bug in udp/500 hole for IKE. -+ * -+ * Revision 1.11 1998/11/10 08:01:19 rgb -+ * Kill tcp/500 hole, keep udp/500 hole. -+ * -+ * Revision 1.10 1998/11/09 21:29:26 rgb -+ * If no eroute is found, discard packet and incr. tx_error. -+ * -+ * Revision 1.9 1998/10/31 06:50:00 rgb -+ * Add tcp/udp/500 bypass. -+ * Fixed up comments in #endif directives. -+ * -+ * Revision 1.8 1998/10/27 00:34:31 rgb -+ * Reformat debug output of IP headers. -+ * Newlines added before calls to ipsec_print_ip. -+ * -+ * Revision 1.7 1998/10/19 14:44:28 rgb -+ * Added inclusion of freeswan.h. -+ * sa_id structure implemented and used: now includes protocol. -+ * -+ * Revision 1.6 1998/10/09 04:31:35 rgb -+ * Added 'klips_debug' prefix to all klips printk debug statements. -+ * -+ * Revision 1.5 1998/08/28 03:09:51 rgb -+ * Prevent kernel log spam with default route through ipsec. -+ * -+ * Revision 1.4 1998/08/05 22:23:09 rgb -+ * Change setdev return code to ENXIO for a non-existant physical device. -+ * -+ * Revision 1.3 1998/07/29 20:41:11 rgb -+ * Add ipsec_tunnel_clear to clear all tunnel attachments. -+ * -+ * Revision 1.2 1998/06/25 20:00:33 rgb -+ * Clean up #endif comments. -+ * Rename dev_ipsec to dev_ipsec0 for consistency. -+ * Document ipsec device fields. -+ * Make ipsec_tunnel_probe visible from rest of kernel for static linking. -+ * Get debugging report for *every* ipsec device initialisation. -+ * Comment out redundant code. -+ * -+ * Revision 1.1 1998/06/18 21:27:50 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.8 1998/06/14 23:49:40 rgb -+ * Clarify version reporting on module loading. -+ * -+ * Revision 1.7 1998/05/27 23:19:20 rgb -+ * Added version reporting. -+ * -+ * Revision 1.6 1998/05/18 21:56:23 rgb -+ * Clean up for numerical consistency of output and cleaning up debug code. -+ * -+ * Revision 1.5 1998/05/12 02:44:23 rgb -+ * Clarifying 'no e-route to host' message. -+ * -+ * Revision 1.4 1998/04/30 15:34:35 rgb -+ * Enclosed most remaining debugging statements in #ifdef's to make it quieter. -+ * -+ * Revision 1.3 1998/04/21 21:28:54 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.2 1998/04/12 22:03:24 rgb -+ * Updated ESP-3DES-HMAC-MD5-96, -+ * ESP-DES-HMAC-MD5-96, -+ * AH-HMAC-MD5-96, -+ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository -+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts. -+ * -+ * Fixed eroute references in /proc/net/ipsec*. -+ * -+ * Started to patch module unloading memory leaks in ipsec_netlink and -+ * radij tree unloading. -+ * -+ * Revision 1.1 1998/04/09 03:06:12 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:04 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.5 1997/06/03 04:24:48 ji -+ * Added transport mode. -+ * Changed the way routing is done. -+ * Lots of bug fixes. -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:39:04 ji -+ * Minor cleanups. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * Local Variables: -+ * c-style: linux -+ * End: -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_xform.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,351 @@ -+/* -+ * Common routines for IPSEC transformations. -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#include -+#include -+#include /* printk() */ -+ -+#include "freeswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include /* get_random_bytes() */ -+#include -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+#endif -+#include -+#include -+ -+#include "freeswan/radij.h" -+#include "freeswan/ipsec_encap.h" -+#include "freeswan/ipsec_radij.h" -+#include "freeswan/ipsec_xform.h" -+#include "freeswan/ipsec_ipe4.h" -+#include "freeswan/ipsec_ah.h" -+#include "freeswan/ipsec_esp.h" -+ -+#include -+#include -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_xform = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#ifdef SPINLOCK -+spinlock_t tdb_lock = SPIN_LOCK_UNLOCKED; -+#else /* SPINLOCK */ -+spinlock_t tdb_lock; -+#endif /* SPINLOCK */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.63 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.62.30.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.62 2002/05/14 02:34:21 rgb -+ * Delete stale code. -+ * -+ * Revision 1.61 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.60 2002/04/24 07:36:33 mcr -+ * Moved from ./klips/net/ipsec/ipsec_xform.c,v -+ * -+ * Revision 1.59 2002/03/29 15:01:36 rgb -+ * Delete decommissioned code. -+ * -+ * Revision 1.58 2002/01/29 17:17:57 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.57 2002/01/29 04:00:53 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.56 2001/11/27 05:17:22 mcr -+ * turn off the worst of the per-packet debugging. -+ * -+ * Revision 1.55 2001/11/26 09:23:50 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.54 2001/10/18 04:45:21 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.53 2001/09/08 21:13:34 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.52 2001/06/14 19:35:11 rgb -+ * Update copyright date. -+ * -+ * Revision 1.51 2001/05/30 08:14:03 rgb -+ * Removed vestiges of esp-null transforms. -+ * -+ * Revision 1.50 2001/05/03 19:43:18 rgb -+ * Initialise error return variable. -+ * Update SENDERR macro. -+ * Fix sign of error return code for ipsec_tdbcleanup(). -+ * Use more appropriate return code for ipsec_tdbwipe(). -+ * -+ * Revision 1.49 2001/04/19 18:56:17 rgb -+ * Fixed tdb table locking comments. -+ * -+ * Revision 1.48 2001/02/27 22:24:55 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.47 2000/11/06 04:32:08 rgb -+ * Ditched spin_lock_irqsave in favour of spin_lock_bh. -+ * -+ * Revision 1.46 2000/09/20 16:21:57 rgb -+ * Cleaned up ident string alloc/free. -+ * -+ * Revision 1.45 2000/09/08 19:16:51 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * Removed all references to CONFIG_IPSEC_PFKEYv2. -+ * -+ * Revision 1.44 2000/08/30 05:29:04 rgb -+ * Compiler-define out no longer used tdb_init() in ipsec_xform.c. -+ * -+ * Revision 1.43 2000/08/18 21:30:41 rgb -+ * Purged all tdb_spi, tdb_proto and tdb_dst macros. They are unclear. -+ * -+ * Revision 1.42 2000/08/01 14:51:51 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.41 2000/07/28 14:58:31 rgb -+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. -+ * -+ * Revision 1.40 2000/06/28 05:50:11 rgb -+ * Actually set iv_bits. -+ * -+ * Revision 1.39 2000/05/10 23:11:09 rgb -+ * Added netlink debugging output. -+ * Added a cast to quiet down the ntohl bug. -+ * -+ * Revision 1.38 2000/05/10 19:18:42 rgb -+ * Cast output of ntohl so that the broken prototype doesn't make our -+ * compile noisy. -+ * -+ * Revision 1.37 2000/03/16 14:04:59 rgb -+ * Hardwired CONFIG_IPSEC_PFKEYv2 on. -+ * -+ * Revision 1.36 2000/01/26 10:11:28 rgb -+ * Fixed spacing in error text causing run-in words. -+ * -+ * Revision 1.35 2000/01/21 06:17:16 rgb -+ * Tidied up compiler directive indentation for readability. -+ * Added ictx,octx vars for simplification.(kravietz) -+ * Added macros for HMAC padding magic numbers.(kravietz) -+ * Fixed missing key length reporting bug. -+ * Fixed bug in tdbwipe to return immediately on NULL tdbp passed in. -+ * -+ * Revision 1.34 1999/12/08 00:04:19 rgb -+ * Fixed SA direction overwriting bug for netlink users. -+ * -+ * Revision 1.33 1999/12/01 22:16:44 rgb -+ * Minor formatting changes in ESP MD5 initialisation. -+ * -+ * Revision 1.32 1999/11/25 09:06:36 rgb -+ * Fixed error return messages, should be returning negative numbers. -+ * Implemented SENDERR macro for propagating error codes. -+ * Added debug message and separate error code for algorithms not compiled -+ * in. -+ * -+ * Revision 1.31 1999/11/23 23:06:26 rgb -+ * Sort out pfkey and freeswan headers, putting them in a library path. -+ * -+ * Revision 1.30 1999/11/18 04:09:20 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.29 1999/11/17 15:53:40 rgb -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * -+ * Revision 1.28 1999/10/18 20:04:01 rgb -+ * Clean-out unused cruft. -+ * -+ * Revision 1.27 1999/10/03 19:01:03 rgb -+ * Spinlock support for 2.3.xx and 2.0.xx kernels. -+ * -+ * Revision 1.26 1999/10/01 16:22:24 rgb -+ * Switch from assignment init. to functional init. of spinlocks. -+ * -+ * Revision 1.25 1999/10/01 15:44:54 rgb -+ * Move spinlock header include to 2.1> scope. -+ * -+ * Revision 1.24 1999/10/01 00:03:46 rgb -+ * Added tdb structure locking. -+ * Minor formatting changes. -+ * Add function to initialize tdb hash table. -+ * -+ * Revision 1.23 1999/05/25 22:42:12 rgb -+ * Add deltdbchain() debugging. -+ * -+ * Revision 1.22 1999/05/25 21:24:31 rgb -+ * Add debugging statements to deltdbchain(). -+ * -+ * Revision 1.21 1999/05/25 03:51:48 rgb -+ * Refix error return code. -+ * -+ * Revision 1.20 1999/05/25 03:34:07 rgb -+ * Fix error return for flush. -+ * -+ * Revision 1.19 1999/05/09 03:25:37 rgb -+ * Fix bug introduced by 2.2 quick-and-dirty patch. -+ * -+ * Revision 1.18 1999/05/05 22:02:32 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.17 1999/04/29 15:20:16 rgb -+ * Change gettdb parameter to a pointer to reduce stack loading and -+ * facilitate parameter sanity checking. -+ * Add sanity checking for null pointer arguments. -+ * Add debugging instrumentation. -+ * Add function deltdbchain() which will take care of unlinking, -+ * zeroing and deleting a chain of tdbs. -+ * Add a parameter to tdbcleanup to be able to delete a class of SAs. -+ * tdbwipe now actually zeroes the tdb as well as any of its pointed -+ * structures. -+ * -+ * Revision 1.16 1999/04/16 15:36:29 rgb -+ * Fix cut-and-paste error causing a memory leak in IPIP TDB freeing. -+ * -+ * Revision 1.15 1999/04/11 00:29:01 henry -+ * GPL boilerplate -+ * -+ * Revision 1.14 1999/04/06 04:54:28 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.13 1999/02/19 18:23:01 rgb -+ * Nix debug off compile warning. -+ * -+ * Revision 1.12 1999/02/17 16:52:16 rgb -+ * Consolidate satoa()s for space and speed efficiency. -+ * Convert DEBUG_IPSEC to KLIPS_PRINT -+ * Clean out unused cruft. -+ * Ditch NET_IPIP dependancy. -+ * Loop for 3des key setting. -+ * -+ * Revision 1.11 1999/01/26 02:09:05 rgb -+ * Remove ah/esp/IPIP switching on include files. -+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro. -+ * Removed dead code. -+ * Clean up debug code when switched off. -+ * Remove references to INET_GET_PROTOCOL. -+ * Added code exclusion macros to reduce code from unused algorithms. -+ * -+ * Revision 1.10 1999/01/22 06:28:55 rgb -+ * Cruft clean-out. -+ * Put random IV generation in kernel. -+ * Added algorithm switch code. -+ * Enhanced debugging. -+ * 64-bit clean-up. -+ * -+ * Revision 1.9 1998/11/30 13:22:55 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.8 1998/11/25 04:59:06 rgb -+ * Add conditionals for no IPIP tunnel code. -+ * Delete commented out code. -+ * -+ * Revision 1.7 1998/10/31 06:50:41 rgb -+ * Convert xform ASCII names to no spaces. -+ * Fixed up comments in #endif directives. -+ * -+ * Revision 1.6 1998/10/19 14:44:28 rgb -+ * Added inclusion of freeswan.h. -+ * sa_id structure implemented and used: now includes protocol. -+ * -+ * Revision 1.5 1998/10/09 04:32:19 rgb -+ * Added 'klips_debug' prefix to all klips printk debug statements. -+ * -+ * Revision 1.4 1998/08/12 00:11:31 rgb -+ * Added new xform functions to the xform table. -+ * Fixed minor debug output spelling error. -+ * -+ * Revision 1.3 1998/07/09 17:45:31 rgb -+ * Clarify algorithm not available message. -+ * -+ * Revision 1.2 1998/06/23 03:00:51 rgb -+ * Check for presence of IPIP protocol if it is setup one way (we don't -+ * know what has been set up the other way and can only assume it will be -+ * symmetrical with the exception of keys). -+ * -+ * Revision 1.1 1998/06/18 21:27:51 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.3 1998/06/11 05:54:59 rgb -+ * Added transform version string pointer to xformsw initialisations. -+ * -+ * Revision 1.2 1998/04/21 21:28:57 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.1 1998/04/09 03:06:13 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:02 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.5 1997/06/03 04:24:48 ji -+ * Added ESP-3DES-MD5-96 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * Added new transforms. -+ * -+ * Revision 0.3 1996/11/20 14:39:04 ji -+ * Minor cleanups. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_xmit.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1869 @@ -+/* -+ * IPSEC Transmit code. -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998-2003 Richard Guy Briggs. -+ * Copyright (C) 2004 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_xmit_c_version[] = "RCSID $Id$"; -+ -+#define __NO_VERSION__ -+#include -+#include /* for CONFIG_IP_FORWARD */ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include /* struct tcphdr */ -+#include /* struct udphdr */ -+#include -+#include -+#ifdef NET_21 -+# define MSS_HACK_ /* experimental */ -+# include -+# include -+# include -+# define proto_priv cb -+#endif /* NET_21 */ -+#include -+#include /* icmp_send() */ -+#include -+#ifdef NETDEV_23 -+# include -+#endif /* NETDEV_23 */ -+ -+#include -+#ifdef MSS_HACK -+# include /* TCP options */ -+#endif /* MSS_HACK */ -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_life.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_eroute.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xmit.h" -+#include "openswan/ipsec_sa.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_ipe4.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+#include "openswan/ipcomp.h" -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+#include "openswan/ipsec_alg.h" -+ -+ -+/* -+ * Stupid kernel API differences in APIs. Not only do some -+ * kernels not have ip_select_ident, but some have differing APIs, -+ * and SuSE has one with one parameter, but no way of checking to -+ * see what is really what. -+ */ -+ -+#ifdef SUSE_LINUX_2_4_19_IS_STUPID -+#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph) -+#else -+ -+/* simplest case, nothing */ -+#if !defined(IP_SELECT_IDENT) -+#define KLIPS_IP_SELECT_IDENT(iph, skb) do { iph->id = htons(ip_id_count++); } while(0) -+#endif -+ -+/* kernels > 2.3.37-ish */ -+#if defined(IP_SELECT_IDENT) && !defined(IP_SELECT_IDENT_NEW) -+#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst) -+#endif -+ -+/* kernels > 2.4.2 */ -+#if defined(IP_SELECT_IDENT) && defined(IP_SELECT_IDENT_NEW) -+#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst, NULL) -+#endif -+ -+#endif /* SUSE_LINUX_2_4_19_IS_STUPID */ -+ -+ -+static __u32 zeroes[64]; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int sysctl_ipsec_debug_verbose = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+int ipsec_xmit_trap_count = 0; -+int ipsec_xmit_trap_sendcount = 0; -+ -+int sysctl_ipsec_icmp = 0; -+int sysctl_ipsec_tos = 0; -+ -+#ifdef CONFIG_IPSEC_DEBUG_ -+DEBUG_NO_STATIC void -+dmp(char *s, caddr_t bb, int len) -+{ -+ int i; -+ unsigned char *b = bb; -+ -+ if (debug_tunnel) { -+ printk(KERN_INFO "klips_debug:ipsec_tunnel_:dmp: " -+ "at %s, len=%d:", -+ s, -+ len); -+ for (i=0; i < len; i++) { -+ if(!(i%16)){ -+ printk("\nklips_debug: "); -+ } -+ printk(" %02x", *b++); -+ } -+ printk("\n"); -+ } -+} -+#else /* CONFIG_IPSEC_DEBUG */ -+#define dmp(_x, _y, _z) -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#ifndef SKB_COPY_EXPAND -+/* -+ * This is mostly skbuff.c:skb_copy(). -+ */ -+struct sk_buff * -+skb_copy_expand(struct sk_buff *skb, int headroom, int tailroom, int priority) -+{ -+ struct sk_buff *n; -+ unsigned long offset; -+ -+ /* -+ * Do sanity checking -+ */ -+ if((headroom < 0) || (tailroom < 0) || ((headroom+tailroom) < 0)) { -+ printk(KERN_WARNING -+ "klips_error:skb_copy_expand: " -+ "Illegal negative head,tailroom %d,%d\n", -+ headroom, -+ tailroom); -+ return NULL; -+ } -+ /* -+ * Allocate the copy buffer -+ */ -+ -+#ifndef NET_21 -+ IS_SKB(skb); -+#endif /* !NET_21 */ -+ -+ -+ n=alloc_skb(skb->end - skb->head + headroom + tailroom, priority); -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:skb_copy_expand: " -+ "allocating %d bytes, head=0p%p data=0p%p tail=0p%p end=0p%p end-head=%d tail-data=%d\n", -+ skb->end - skb->head + headroom + tailroom, -+ skb->head, -+ skb->data, -+ skb->tail, -+ skb->end, -+ skb->end - skb->head, -+ skb->tail - skb->data); -+ -+ if(n==NULL) -+ return NULL; -+ -+ /* -+ * Shift between the two data areas in bytes -+ */ -+ -+ /* Set the data pointer */ -+ skb_reserve(n,skb->data-skb->head+headroom); -+ /* Set the tail pointer and length */ -+ if(skb_tailroom(n) < skb->len) { -+ printk(KERN_WARNING "klips_error:skb_copy_expand: " -+ "tried to skb_put %ld, %d available. This should never happen, please report.\n", -+ (unsigned long int)skb->len, -+ skb_tailroom(n)); -+ ipsec_kfree_skb(n); -+ return NULL; -+ } -+ skb_put(n,skb->len); -+ -+ offset=n->head + headroom - skb->head; -+ -+ /* Copy the bytes */ -+ memcpy(n->head + headroom, skb->head,skb->end-skb->head); -+#ifdef NET_21 -+ n->csum=skb->csum; -+ n->priority=skb->priority; -+ n->dst=dst_clone(skb->dst); -+ if(skb->nh.raw) -+ n->nh.raw=skb->nh.raw+offset; -+#ifndef NETDEV_23 -+ n->is_clone=0; -+#endif /* NETDEV_23 */ -+ atomic_set(&n->users, 1); -+ n->destructor = NULL; -+ n->security=skb->security; -+#else /* NET_21 */ -+ n->link3=NULL; -+ n->when=skb->when; -+ if(skb->ip_hdr) -+ n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset); -+ n->saddr=skb->saddr; -+ n->daddr=skb->daddr; -+ n->raddr=skb->raddr; -+ n->seq=skb->seq; -+ n->end_seq=skb->end_seq; -+ n->ack_seq=skb->ack_seq; -+ n->acked=skb->acked; -+ n->free=1; -+ n->arp=skb->arp; -+ n->tries=0; -+ n->lock=0; -+ n->users=0; -+#endif /* NET_21 */ -+ n->protocol=skb->protocol; -+ n->list=NULL; -+ n->sk=NULL; -+ n->dev=skb->dev; -+ if(skb->h.raw) -+ n->h.raw=skb->h.raw+offset; -+ if(skb->mac.raw) -+ n->mac.raw=skb->mac.raw+offset; -+ memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv)); -+#ifndef NETDEV_23 -+ n->used=skb->used; -+#endif /* !NETDEV_23 */ -+ n->pkt_type=skb->pkt_type; -+ n->stamp=skb->stamp; -+ -+#ifndef NET_21 -+ IS_SKB(n); -+#endif /* !NET_21 */ -+ return n; -+} -+#endif /* !SKB_COPY_EXPAND */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+void -+ipsec_print_ip(struct iphdr *ip) -+{ -+ char buf[ADDRTOA_BUF]; -+ -+ printk(KERN_INFO "klips_debug: IP:"); -+ printk(" ihl:%d", ip->ihl << 2); -+ printk(" ver:%d", ip->version); -+ printk(" tos:%d", ip->tos); -+ printk(" tlen:%d", ntohs(ip->tot_len)); -+ printk(" id:%d", ntohs(ip->id)); -+ printk(" %s%s%sfrag_off:%d", -+ ip->frag_off & __constant_htons(IP_CE) ? "CE " : "", -+ ip->frag_off & __constant_htons(IP_DF) ? "DF " : "", -+ ip->frag_off & __constant_htons(IP_MF) ? "MF " : "", -+ (ntohs(ip->frag_off) & IP_OFFSET) << 3); -+ printk(" ttl:%d", ip->ttl); -+ printk(" proto:%d", ip->protocol); -+ if(ip->protocol == IPPROTO_UDP) -+ printk(" (UDP)"); -+ if(ip->protocol == IPPROTO_TCP) -+ printk(" (TCP)"); -+ if(ip->protocol == IPPROTO_ICMP) -+ printk(" (ICMP)"); -+ printk(" chk:%d", ntohs(ip->check)); -+ addrtoa(*((struct in_addr*)(&ip->saddr)), 0, buf, sizeof(buf)); -+ printk(" saddr:%s", buf); -+ if(ip->protocol == IPPROTO_UDP) -+ printk(":%d", -+ ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->source)); -+ if(ip->protocol == IPPROTO_TCP) -+ printk(":%d", -+ ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->source)); -+ addrtoa(*((struct in_addr*)(&ip->daddr)), 0, buf, sizeof(buf)); -+ printk(" daddr:%s", buf); -+ if(ip->protocol == IPPROTO_UDP) -+ printk(":%d", -+ ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest)); -+ if(ip->protocol == IPPROTO_TCP) -+ printk(":%d", -+ ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest)); -+ if(ip->protocol == IPPROTO_ICMP) -+ printk(" type:code=%d:%d", -+ ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->type, -+ ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->code); -+ printk("\n"); -+ -+ if(sysctl_ipsec_debug_verbose) { -+ __u8 *c; -+ int i; -+ -+ c = ((__u8*)ip) + ip->ihl*4; -+ for(i = 0; i < ntohs(ip->tot_len) - ip->ihl*4; i++ /*, c++*/) { -+ if(!(i % 16)) { -+ printk(KERN_INFO -+ "klips_debug: @%03x:", -+ i); -+ } -+ printk(" %02x", /***/c[i]); -+ if(!((i + 1) % 16)) { -+ printk("\n"); -+ } -+ } -+ if(i % 16) { -+ printk("\n"); -+ } -+ } -+} -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#ifdef MSS_HACK -+/* -+ * Issues: -+ * 1) Fragments arriving in the tunnel should probably be rejected. -+ * 2) How does this affect syncookies, mss_cache, dst cache ? -+ * 3) Path MTU discovery handling needs to be reviewed. For example, -+ * if we receive an ICMP 'packet too big' message from an intermediate -+ * router specifying it's next hop MTU, our stack may process this and -+ * adjust the MSS without taking our AH/ESP overheads into account. -+ */ -+ -+ -+/* -+ * Recaclulate checksum using differences between changed datum, -+ * borrowed from netfilter. -+ */ -+DEBUG_NO_STATIC u_int16_t -+ipsec_fast_csum(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck) -+{ -+ u_int32_t diffs[] = { oldvalinv, newval }; -+ return csum_fold(csum_partial((char *)diffs, sizeof(diffs), -+ oldcheck^0xFFFF)); -+} -+ -+/* -+ * Determine effective MSS. -+ * -+ * Note that we assume that there is always an MSS option for our own -+ * SYN segments, which is mentioned in tcp_syn_build_options(), kernel 2.2.x. -+ * This could change, and we should probably parse TCP options instead. -+ * -+ */ -+DEBUG_NO_STATIC u_int8_t -+ipsec_adjust_mss(struct sk_buff *skb, struct tcphdr *tcph, u_int16_t mtu) -+{ -+ u_int16_t oldmss, newmss; -+ u_int32_t *mssp; -+ struct sock *sk = skb->sk; -+ -+ newmss = tcp_sync_mss(sk, mtu); -+ printk(KERN_INFO "klips: setting mss to %u\n", newmss); -+ mssp = (u_int32_t *)tcph + sizeof(struct tcphdr) / sizeof(u_int32_t); -+ oldmss = ntohl(*mssp) & 0x0000FFFF; -+ *mssp = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | newmss); -+ tcph->check = ipsec_fast_csum(htons(~oldmss), -+ htons(newmss), tcph->check); -+ return 1; -+} -+#endif /* MSS_HACK */ -+ -+/* -+ * Sanity checks -+ */ -+enum ipsec_xmit_value -+ipsec_xmit_sanity_check_dev(struct ipsec_xmit_state *ixs) -+{ -+ -+ if (ixs->dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_error:ipsec_xmit_sanity_check_dev: " -+ "No device associated with skb!\n" ); -+ return IPSEC_XMIT_NODEV; -+ } -+ -+ ixs->prv = ixs->dev->priv; -+ if (ixs->prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_error:ipsec_xmit_sanity_check_dev: " -+ "Device has no private structure!\n" ); -+ return IPSEC_XMIT_NOPRIVDEV; -+ } -+ -+ ixs->physdev = ixs->prv->dev; -+ if (ixs->physdev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_error:ipsec_xmit_sanity_check_dev: " -+ "Device is not attached to physical device!\n" ); -+ return IPSEC_XMIT_NOPHYSDEV; -+ } -+ -+ ixs->physmtu = ixs->physdev->mtu; -+ -+ ixs->stats = (struct net_device_stats *) &(ixs->prv->mystats); -+ -+ return IPSEC_XMIT_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_xmit_sanity_check_skb(struct ipsec_xmit_state *ixs) -+{ -+ /* -+ * Return if there is nothing to do. (Does this ever happen?) XXX -+ */ -+ if (ixs->skb == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_error:ipsec_xmit_sanity_check_skb: " -+ "Nothing to do!\n" ); -+ return IPSEC_XMIT_NOSKB; -+ } -+#ifdef NET_21 -+ /* if skb was cloned (most likely due to a packet sniffer such as -+ tcpdump being momentarily attached to the interface), make -+ a copy of our own to modify */ -+ if(skb_cloned(ixs->skb)) { -+ if -+#ifdef SKB_COW_NEW -+ (skb_cow(ixs->skb, skb_headroom(ixs->skb)) != 0) -+#else /* SKB_COW_NEW */ -+ ((ixs->skb = skb_cow(ixs->skb, skb_headroom(ixs->skb))) == NULL) -+#endif /* SKB_COW_NEW */ -+ { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_error:ipsec_xmit_sanity_check_skb: " -+ "skb_cow failed to allocate buffer, dropping.\n" ); -+ ixs->stats->tx_dropped++; -+ return IPSEC_XMIT_ERRSKBALLOC; -+ } -+ } -+#endif /* NET_21 */ -+ -+#ifdef NET_21 -+ ixs->iph = ixs->skb->nh.iph; -+#else /* NET_21 */ -+ ixs->iph = ixs->skb->ip_hdr; -+#endif /* NET_21 */ -+ -+ /* sanity check for IP version as we can't handle IPv6 right now */ -+ if (ixs->iph->version != 4) { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_xmit_sanity_check_skb: " -+ "found IP Version %d but cannot process other IP versions than v4.\n", -+ ixs->iph->version); /* XXX */ -+ ixs->stats->tx_dropped++; -+ return IPSEC_XMIT_NOIPV6; -+ } -+ -+#if IPSEC_DISALLOW_IPOPTIONS -+ if ((ixs->iph->ihl << 2) != sizeof (struct iphdr)) { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_xmit_sanity_check_skb: " -+ "cannot process IP header options yet. May be mal-formed packet.\n"); /* XXX */ -+ ixs->stats->tx_dropped++; -+ return IPSEC_XMIT_NOIPOPTIONS; -+ } -+#endif /* IPSEC_DISALLOW_IPOPTIONS */ -+ -+#ifndef NET_21 -+ if (ixs->iph->ttl <= 0) { -+ /* Tell the sender its packet died... */ -+ ICMP_SEND(ixs->skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, ixs->physdev); -+ -+ KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_xmit_sanity_check_skb: " -+ "TTL=0, too many hops!\n"); -+ ixs->stats->tx_dropped++; -+ return IPSEC_XMIT_TTLEXPIRED; -+ } -+#endif /* !NET_21 */ -+ -+ return IPSEC_XMIT_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_xmit_encap_once(struct ipsec_xmit_state *ixs) -+{ -+#ifdef CONFIG_IPSEC_ESP -+ struct esphdr *espp; -+#ifdef CONFIG_IPSEC_ENC_3DES -+ __u32 iv[ESP_IV_MAXSZ_INT]; -+#endif /* !CONFIG_IPSEC_ENC_3DES */ -+ unsigned char *idat, *pad; -+ int authlen = 0, padlen = 0, i; -+#endif /* !CONFIG_IPSEC_ESP */ -+#ifdef CONFIG_IPSEC_AH -+ struct iphdr ipo; -+ struct ahhdr *ahp; -+#endif /* CONFIG_IPSEC_AH */ -+#if defined(CONFIG_IPSEC_AUTH_HMAC_MD5) || defined(CONFIG_IPSEC_AUTH_HMAC_SHA1) -+ union { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ MD5_CTX md5; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ SHA1_CTX sha1; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ } tctx; -+ __u8 hash[AH_AMAX]; -+#endif /* defined(CONFIG_IPSEC_AUTH_HMAC_MD5) || defined(CONFIG_IPSEC_AUTH_HMAC_SHA1) */ -+ int headroom = 0, tailroom = 0, ilen = 0, len = 0; -+ unsigned char *dat; -+ int blocksize = 8; /* XXX: should be inside ixs --jjo */ -+#ifdef CONFIG_IPSEC_ALG -+ struct ipsec_alg_enc *ixt_e = NULL; -+ struct ipsec_alg_auth *ixt_a = NULL; -+#endif /* CONFIG_IPSEC_ALG */ -+ -+ ixs->iphlen = ixs->iph->ihl << 2; -+ ixs->pyldsz = ntohs(ixs->iph->tot_len) - ixs->iphlen; -+ ixs->sa_len = satot(&ixs->ipsp->ips_said, 0, ixs->sa_txt, SATOT_BUF); -+ KLIPS_PRINT(debug_tunnel & DB_TN_OXFS, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "calling output for <%s%s%s>, SA:%s\n", -+ IPS_XFORM_NAME(ixs->ipsp), -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ -+ switch(ixs->ipsp->ips_said.proto) { -+#ifdef CONFIG_IPSEC_AH -+ case IPPROTO_AH: -+ headroom += sizeof(struct ahhdr); -+ break; -+#endif /* CONFIG_IPSEC_AH */ -+#ifdef CONFIG_IPSEC_ESP -+ case IPPROTO_ESP: -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_e=ixs->ipsp->ips_alg_enc)) { -+ blocksize = ixt_e->ixt_blocksize; -+ headroom += ESP_HEADER_LEN + ixt_e->ixt_ivlen/8; -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_encalg) { -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+ headroom += sizeof(struct esphdr); -+ break; -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_a=ixs->ipsp->ips_alg_auth)) { -+ tailroom += AHHMAC_HASHLEN; -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_authalg) { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: -+ authlen = AHHMAC_HASHLEN; -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: -+ authlen = AHHMAC_HASHLEN; -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ case AH_NONE: -+ break; -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+#ifdef CONFIG_IPSEC_ALG -+ tailroom += blocksize != 1 ? -+ ((blocksize - ((ixs->pyldsz + 2) % blocksize)) % blocksize) + 2 : -+ ((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2; -+#else -+ tailroom += ((8 - ((ixs->pyldsz + 2 * sizeof(unsigned char)) % 8)) % 8) + 2; -+#endif /* CONFIG_IPSEC_ALG */ -+ tailroom += authlen; -+ break; -+#endif /* !CONFIG_IPSEC_ESP */ -+#ifdef CONFIG_IPSEC_IPIP -+ case IPPROTO_IPIP: -+ headroom += sizeof(struct iphdr); -+ ixs->iphlen = sizeof(struct iphdr); -+ break; -+#endif /* !CONFIG_IPSEC_IPIP */ -+#ifdef CONFIG_IPSEC_IPCOMP -+ case IPPROTO_COMP: -+ break; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_BADPROTO; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "pushing %d bytes, putting %d, proto %d.\n", -+ headroom, tailroom, ixs->ipsp->ips_said.proto); -+ if(skb_headroom(ixs->skb) < headroom) { -+ printk(KERN_WARNING -+ "klips_error:ipsec_xmit_encap_once: " -+ "tried to skb_push headroom=%d, %d available. This should never happen, please report.\n", -+ headroom, skb_headroom(ixs->skb)); -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_PUSHPULLERR; -+ } -+ dat = skb_push(ixs->skb, headroom); -+ ilen = ixs->skb->len - tailroom; -+ if(skb_tailroom(ixs->skb) < tailroom) { -+ printk(KERN_WARNING -+ "klips_error:ipsec_xmit_encap_once: " -+ "tried to skb_put %d, %d available. This should never happen, please report.\n", -+ tailroom, skb_tailroom(ixs->skb)); -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_PUSHPULLERR; -+ } -+ skb_put(ixs->skb, tailroom); -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "head,tailroom: %d,%d before xform.\n", -+ skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); -+ len = ixs->skb->len; -+ if(len > 0xfff0) { -+ printk(KERN_WARNING "klips_error:ipsec_xmit_encap_once: " -+ "tot_len (%d) > 65520. This should never happen, please report.\n", -+ len); -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_BADLEN; -+ } -+ memmove((void *)dat, (void *)(dat + headroom), ixs->iphlen); -+ ixs->iph = (struct iphdr *)dat; -+ ixs->iph->tot_len = htons(ixs->skb->len); -+ -+ switch(ixs->ipsp->ips_said.proto) { -+#ifdef CONFIG_IPSEC_ESP -+ case IPPROTO_ESP: -+ espp = (struct esphdr *)(dat + ixs->iphlen); -+ espp->esp_spi = ixs->ipsp->ips_said.spi; -+ espp->esp_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); -+ -+#ifdef CONFIG_IPSEC_ALG -+ if (!ixt_e) -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_encalg) { -+#if defined(CONFIG_IPSEC_ENC_3DES) -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ iv[0] = *((__u32*)&(espp->esp_iv) ) = -+ ((__u32*)(ixs->ipsp->ips_iv))[0]; -+ iv[1] = *((__u32*)&(espp->esp_iv) + 1) = -+ ((__u32*)(ixs->ipsp->ips_iv))[1]; -+ break; -+#endif /* defined(CONFIG_IPSEC_ENC_3DES) */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+ -+ idat = dat + ixs->iphlen + headroom; -+ ilen = len - (ixs->iphlen + headroom + authlen); -+ -+ /* Self-describing padding */ -+ pad = &dat[len - tailroom]; -+ padlen = tailroom - 2 - authlen; -+ for (i = 0; i < padlen; i++) { -+ pad[i] = i + 1; -+ } -+ dat[len - authlen - 2] = padlen; -+ -+ dat[len - authlen - 1] = ixs->iph->protocol; -+ ixs->iph->protocol = IPPROTO_ESP; -+ -+#ifdef CONFIG_IPSEC_ALG -+ /* Do all operations here: -+ * copy IV->ESP, encrypt, update ips IV -+ */ -+ if (ixt_e) { -+ int ret; -+ memcpy(espp->esp_iv, -+ ixs->ipsp->ips_iv, -+ ixt_e->ixt_ivlen/8); -+ ret=ipsec_alg_esp_encrypt(ixs->ipsp, -+ idat, ilen, espp->esp_iv, -+ IPSEC_ALG_ENCRYPT); -+ memcpy(ixs->ipsp->ips_iv, -+ idat + ilen - ixt_e->ixt_ivlen/8, -+ ixt_e->ixt_ivlen/8); -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_encalg) { -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+ des_ede3_cbc_encrypt((des_cblock *)idat, -+ (des_cblock *)idat, -+ ilen, -+ ((struct des_eks *)(ixs->ipsp->ips_key_e))[0].ks, -+ ((struct des_eks *)(ixs->ipsp->ips_key_e))[1].ks, -+ ((struct des_eks *)(ixs->ipsp->ips_key_e))[2].ks, -+ (des_cblock *)iv, 1); -+ break; -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+ -+#ifdef CONFIG_IPSEC_ALG -+ if (!ixt_e) -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_encalg) { -+#if defined(CONFIG_IPSEC_ENC_3DES) -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ /* XXX update IV with the last 8 octets of the encryption */ -+#if KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK -+ ((__u32*)(ixs->ipsp->ips_iv))[0] = -+ ((__u32 *)(idat))[(ilen >> 2) - 2]; -+ ((__u32*)(ixs->ipsp->ips_iv))[1] = -+ ((__u32 *)(idat))[(ilen >> 2) - 1]; -+#else /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */ -+ prng_bytes(&ipsec_prng, (char *)ixs->ipsp->ips_iv, EMT_ESPDES_IV_SZ); -+#endif /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */ -+ break; -+#endif /* defined(CONFIG_IPSEC_ENC_3DES) */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+ -+#ifdef CONFIG_IPSEC_ALG -+ if (ixt_a) { -+ ipsec_alg_sa_esp_hash(ixs->ipsp, -+ (caddr_t)espp, len - ixs->iphlen - authlen, -+ &(dat[len - authlen]), authlen); -+ -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_authalg) { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: -+ dmp("espp", (char*)espp, len - ixs->iphlen - authlen); -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (caddr_t)espp, len - ixs->iphlen - authlen); -+ dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ dmp("ictx hash", (char*)&hash, sizeof(hash)); -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, hash, AHMD596_ALEN); -+ dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ dmp("octx hash", (char*)&hash, sizeof(hash)); -+ memcpy(&(dat[len - authlen]), hash, authlen); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ SHA1Update(&tctx.sha1, (caddr_t)espp, len - ixs->iphlen - authlen); -+ SHA1Final(hash, &tctx.sha1); -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); -+ SHA1Final(hash, &tctx.sha1); -+ memcpy(&(dat[len - authlen]), hash, authlen); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ case AH_NONE: -+ break; -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_AH_BADALG; -+ } -+#ifdef NET_21 -+ ixs->skb->h.raw = (unsigned char*)espp; -+#endif /* NET_21 */ -+ break; -+#endif /* !CONFIG_IPSEC_ESP */ -+#ifdef CONFIG_IPSEC_AH -+ case IPPROTO_AH: -+ ahp = (struct ahhdr *)(dat + ixs->iphlen); -+ ahp->ah_spi = ixs->ipsp->ips_said.spi; -+ ahp->ah_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); -+ ahp->ah_rv = 0; -+ ahp->ah_nh = ixs->iph->protocol; -+ ahp->ah_hl = (headroom >> 2) - sizeof(__u64)/sizeof(__u32); -+ ixs->iph->protocol = IPPROTO_AH; -+ dmp("ahp", (char*)ahp, sizeof(*ahp)); -+ -+ ipo = *ixs->iph; -+ ipo.tos = 0; -+ ipo.frag_off = 0; -+ ipo.ttl = 0; -+ ipo.check = 0; -+ dmp("ipo", (char*)&ipo, sizeof(ipo)); -+ -+ switch(ixs->ipsp->ips_authalg) { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr)); -+ dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data)); -+ dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN); -+ dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, dat + ixs->iphlen + headroom, len - ixs->iphlen - headroom); -+ dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ dmp("ictx hash", (char*)&hash, sizeof(hash)); -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, hash, AHMD596_ALEN); -+ dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ dmp("octx hash", (char*)&hash, sizeof(hash)); -+ -+ memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ SHA1Update(&tctx.sha1, (unsigned char *)&ipo, sizeof (struct iphdr)); -+ SHA1Update(&tctx.sha1, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data)); -+ SHA1Update(&tctx.sha1, (unsigned char *)zeroes, AHHMAC_HASHLEN); -+ SHA1Update(&tctx.sha1, dat + ixs->iphlen + headroom, len - ixs->iphlen - headroom); -+ SHA1Final(hash, &tctx.sha1); -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); -+ SHA1Final(hash, &tctx.sha1); -+ -+ memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_AH_BADALG; -+ } -+#ifdef NET_21 -+ ixs->skb->h.raw = (unsigned char*)ahp; -+#endif /* NET_21 */ -+ break; -+#endif /* CONFIG_IPSEC_AH */ -+#ifdef CONFIG_IPSEC_IPIP -+ case IPPROTO_IPIP: -+ ixs->iph->version = 4; -+ switch(sysctl_ipsec_tos) { -+ case 0: -+#ifdef NET_21 -+ ixs->iph->tos = ixs->skb->nh.iph->tos; -+#else /* NET_21 */ -+ ixs->iph->tos = ixs->skb->ip_hdr->tos; -+#endif /* NET_21 */ -+ break; -+ case 1: -+ ixs->iph->tos = 0; -+ break; -+ default: -+ break; -+ } -+#ifdef NET_21 -+#ifdef NETDEV_23 -+ ixs->iph->ttl = sysctl_ip_default_ttl; -+#else /* NETDEV_23 */ -+ ixs->iph->ttl = ip_statistics.IpDefaultTTL; -+#endif /* NETDEV_23 */ -+#else /* NET_21 */ -+ ixs->iph->ttl = 64; /* ip_statistics.IpDefaultTTL; */ -+#endif /* NET_21 */ -+ ixs->iph->frag_off = 0; -+ ixs->iph->saddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_s))->sin_addr.s_addr; -+ ixs->iph->daddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_d))->sin_addr.s_addr; -+ ixs->iph->protocol = IPPROTO_IPIP; -+ ixs->iph->ihl = sizeof(struct iphdr) >> 2; -+ -+ KLIPS_IP_SELECT_IDENT(ixs->iph, ixs->skb); -+ -+ ixs->newdst = (__u32)ixs->iph->daddr; -+ ixs->newsrc = (__u32)ixs->iph->saddr; -+ -+#ifdef NET_21 -+ ixs->skb->h.ipiph = ixs->skb->nh.iph; -+#endif /* NET_21 */ -+ break; -+#endif /* !CONFIG_IPSEC_IPIP */ -+#ifdef CONFIG_IPSEC_IPCOMP -+ case IPPROTO_COMP: -+ { -+ unsigned int flags = 0; -+#ifdef CONFIG_IPSEC_DEBUG -+ unsigned int old_tot_len = ntohs(ixs->iph->tot_len); -+#endif /* CONFIG_IPSEC_DEBUG */ -+ ixs->ipsp->ips_comp_ratio_dbytes += ntohs(ixs->iph->tot_len); -+ -+ ixs->skb = skb_compress(ixs->skb, ixs->ipsp, &flags); -+ -+#ifdef NET_21 -+ ixs->iph = ixs->skb->nh.iph; -+#else /* NET_21 */ -+ ixs->iph = ixs->skb->ip_hdr; -+#endif /* NET_21 */ -+ -+ ixs->ipsp->ips_comp_ratio_cbytes += ntohs(ixs->iph->tot_len); -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_tunnel & DB_TN_CROUT) -+ { -+ if (old_tot_len > ntohs(ixs->iph->tot_len)) -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "packet shrunk from %d to %d bytes after compression, cpi=%04x (should be from spi=%08x, spi&0xffff=%04x.\n", -+ old_tot_len, ntohs(ixs->iph->tot_len), -+ ntohs(((struct ipcomphdr*)(((char*)ixs->iph) + ((ixs->iph->ihl) << 2)))->ipcomp_cpi), -+ ntohl(ixs->ipsp->ips_said.spi), -+ (__u16)(ntohl(ixs->ipsp->ips_said.spi) & 0x0000ffff)); -+ else -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "packet did not compress (flags = %d).\n", -+ flags); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ } -+ break; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_BADPROTO; -+ } -+ -+#ifdef NET_21 -+ ixs->skb->nh.raw = ixs->skb->data; -+#else /* NET_21 */ -+ ixs->skb->ip_hdr = ixs->skb->h.iph = (struct iphdr *) ixs->skb->data; -+#endif /* NET_21 */ -+ ixs->iph->check = 0; -+ ixs->iph->check = ip_fast_csum((unsigned char *)ixs->iph, ixs->iph->ihl); -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "after <%s%s%s>, SA:%s:\n", -+ IPS_XFORM_NAME(ixs->ipsp), -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph); -+ -+ ixs->ipsp->ips_life.ipl_bytes.ipl_count += len; -+ ixs->ipsp->ips_life.ipl_bytes.ipl_last = len; -+ -+ if(!ixs->ipsp->ips_life.ipl_usetime.ipl_count) { -+ ixs->ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ; -+ } -+ ixs->ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ; -+ ixs->ipsp->ips_life.ipl_packets.ipl_count++; -+ -+ ixs->ipsp = ixs->ipsp->ips_onext; -+ -+ return IPSEC_XMIT_OK; -+} -+ -+/* -+ * If the IP packet (iph) is a carrying TCP/UDP, then set the encaps -+ * source and destination ports to those from the TCP/UDP header. -+ */ -+void ipsec_extract_ports(struct iphdr * iph, struct sockaddr_encap * er) -+{ -+ struct udphdr *udp; -+ -+ switch (iph->protocol) { -+ case IPPROTO_UDP: -+ case IPPROTO_TCP: -+ /* -+ * The ports are at the same offsets in a TCP and UDP -+ * header so hack it ... -+ */ -+ udp = (struct udphdr*)(((char*)iph)+(iph->ihl<<2)); -+ er->sen_sport = udp->source; -+ er->sen_dport = udp->dest; -+ break; -+ default: -+ er->sen_sport = 0; -+ er->sen_dport = 0; -+ break; -+ } -+} -+ -+/* -+ * A TRAP eroute is installed and we want to replace it with a HOLD -+ * eroute. -+ */ -+static int create_hold_eroute(struct eroute *origtrap, -+ struct sk_buff * skb, struct iphdr * iph, -+ uint32_t eroute_pid) -+{ -+ struct eroute hold_eroute; -+ ip_said hold_said; -+ struct sk_buff *first, *last; -+ int error; -+ -+ first = last = NULL; -+ memset((caddr_t)&hold_eroute, 0, sizeof(hold_eroute)); -+ memset((caddr_t)&hold_said, 0, sizeof(hold_said)); -+ -+ hold_said.proto = IPPROTO_INT; -+ hold_said.spi = htonl(SPI_HOLD); -+ hold_said.dst.u.v4.sin_addr.s_addr = INADDR_ANY; -+ -+ hold_eroute.er_eaddr.sen_len = sizeof(struct sockaddr_encap); -+ hold_eroute.er_emask.sen_len = sizeof(struct sockaddr_encap); -+ hold_eroute.er_eaddr.sen_family = AF_ENCAP; -+ hold_eroute.er_emask.sen_family = AF_ENCAP; -+ hold_eroute.er_eaddr.sen_type = SENT_IP4; -+ hold_eroute.er_emask.sen_type = 255; -+ -+ hold_eroute.er_eaddr.sen_ip_src.s_addr = iph->saddr; -+ hold_eroute.er_eaddr.sen_ip_dst.s_addr = iph->daddr; -+ hold_eroute.er_emask.sen_ip_src.s_addr = INADDR_BROADCAST; -+ hold_eroute.er_emask.sen_ip_dst.s_addr = INADDR_BROADCAST; -+ hold_eroute.er_emask.sen_sport = 0; -+ hold_eroute.er_emask.sen_dport = 0; -+ hold_eroute.er_pid = eroute_pid; -+ hold_eroute.er_count = 0; -+ hold_eroute.er_lasttime = jiffies/HZ; -+ -+ /* -+ * if it wasn't captured by a wildcard, then don't record it as -+ * a wildcard. -+ */ -+ if(origtrap->er_eaddr.sen_proto != 0) { -+ hold_eroute.er_eaddr.sen_proto = iph->protocol; -+ -+ if((iph->protocol == IPPROTO_TCP || -+ iph->protocol == IPPROTO_UDP) && -+ (origtrap->er_eaddr.sen_sport != 0 || -+ origtrap->er_eaddr.sen_dport != 0)) { -+ -+ if(origtrap->er_eaddr.sen_sport != 0) -+ hold_eroute.er_emask.sen_sport = ~0; -+ -+ if(origtrap->er_eaddr.sen_dport != 0) -+ hold_eroute.er_emask.sen_dport = ~0; -+ -+ ipsec_extract_ports(iph, &hold_eroute.er_eaddr); -+ } -+ } -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_pfkey) { -+ char buf1[64], buf2[64]; -+ subnettoa(hold_eroute.er_eaddr.sen_ip_src, -+ hold_eroute.er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(hold_eroute.er_eaddr.sen_ip_dst, -+ hold_eroute.er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "calling breakeroute and makeroute for %s:%d->%s:%d %d HOLD eroute.\n", -+ buf1, ntohs(hold_eroute.er_eaddr.sen_sport), -+ buf2, ntohs(hold_eroute.er_eaddr.sen_dport), -+ hold_eroute.er_eaddr.sen_proto); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ if (ipsec_breakroute(&(hold_eroute.er_eaddr), &(hold_eroute.er_emask), -+ &first, &last)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "HOLD breakeroute found nothing.\n"); -+ } else { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "HOLD breakroute deleted %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u %u\n", -+ NIPQUAD(hold_eroute.er_eaddr.sen_ip_src), -+ ntohs(hold_eroute.er_eaddr.sen_sport), -+ NIPQUAD(hold_eroute.er_eaddr.sen_ip_dst), -+ ntohs(hold_eroute.er_eaddr.sen_dport), -+ hold_eroute.er_eaddr.sen_proto); -+ } -+ if (first != NULL) -+ kfree_skb(first); -+ if (last != NULL) -+ kfree_skb(last); -+ -+ error = ipsec_makeroute(&(hold_eroute.er_eaddr), -+ &(hold_eroute.er_emask), -+ hold_said, eroute_pid, skb, NULL, NULL); -+ if (error) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "HOLD makeroute returned %d, failed.\n", error); -+ } else { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "HOLD makeroute call successful.\n"); -+ } -+ return (error == 0); -+} -+ -+enum ipsec_xmit_value -+ipsec_xmit_encap_bundle(struct ipsec_xmit_state *ixs) -+{ -+#ifdef CONFIG_IPSEC_ALG -+ struct ipsec_alg_enc *ixt_e = NULL; -+ struct ipsec_alg_auth *ixt_a = NULL; -+ int blocksize = 8; -+#endif /* CONFIG_IPSEC_ALG */ -+ enum ipsec_xmit_value bundle_stat = IPSEC_XMIT_OK; -+ -+ ixs->newdst = ixs->orgdst = ixs->iph->daddr; -+ ixs->newsrc = ixs->orgsrc = ixs->iph->saddr; -+ ixs->orgedst = ixs->outgoing_said.dst.u.v4.sin_addr.s_addr; -+ ixs->iphlen = ixs->iph->ihl << 2; -+ ixs->pyldsz = ntohs(ixs->iph->tot_len) - ixs->iphlen; -+ ixs->max_headroom = ixs->max_tailroom = 0; -+ -+ if (ixs->outgoing_said.proto == IPPROTO_INT) { -+ switch (ntohl(ixs->outgoing_said.spi)) { -+ case SPI_DROP: -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "shunt SA of DROP or no eroute: dropping.\n"); -+ ixs->stats->tx_dropped++; -+ break; -+ -+ case SPI_REJECT: -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "shunt SA of REJECT: notifying and dropping.\n"); -+ ICMP_SEND(ixs->skb, -+ ICMP_DEST_UNREACH, -+ ICMP_PKT_FILTERED, -+ 0, -+ ixs->physdev); -+ ixs->stats->tx_dropped++; -+ break; -+ -+ case SPI_PASS: -+#ifdef NET_21 -+ ixs->pass = 1; -+#endif /* NET_21 */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "PASS: calling dev_queue_xmit\n"); -+ return IPSEC_XMIT_PASS; -+ goto cleanup; -+ -+ case SPI_HOLD: -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "shunt SA of HOLD: this does not make sense here, dropping.\n"); -+ ixs->stats->tx_dropped++; -+ break; -+ -+ case SPI_TRAP: -+ case SPI_TRAPSUBNET: -+ { -+ struct sockaddr_in src, dst; -+#ifdef CONFIG_IPSEC_DEBUG -+ char bufsrc[ADDRTOA_BUF], bufdst[ADDRTOA_BUF]; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ /* Signal all listening KMds with a PF_KEY ACQUIRE */ -+ -+ src.sin_family = AF_INET; -+ dst.sin_family = AF_INET; -+ src.sin_addr.s_addr = ixs->iph->saddr; -+ dst.sin_addr.s_addr = ixs->iph->daddr; -+ -+ ixs->ips.ips_transport_protocol = 0; -+ src.sin_port = 0; -+ dst.sin_port = 0; -+ { -+ int i; -+ for(i = 0; -+ i < sizeof(struct sockaddr_in) -+ - offsetof(struct sockaddr_in, sin_zero); -+ i++) { -+ src.sin_zero[i] = 0; -+ dst.sin_zero[i] = 0; -+ } -+ } -+ -+ if(ixs->eroute->er_eaddr.sen_proto != 0) { -+ ixs->ips.ips_transport_protocol = ixs->iph->protocol; -+ -+ if(ixs->eroute->er_eaddr.sen_sport != 0) { -+ src.sin_port = -+ (ixs->iph->protocol == IPPROTO_UDP -+ ? ((struct udphdr*) (((caddr_t)ixs->iph) + (ixs->iph->ihl << 2)))->source -+ : (ixs->iph->protocol == IPPROTO_TCP -+ ? ((struct tcphdr*)((caddr_t)ixs->iph + (ixs->iph->ihl << 2)))->source -+ : 0)); -+ } -+ if(ixs->eroute->er_eaddr.sen_dport != 0) { -+ dst.sin_port = -+ (ixs->iph->protocol == IPPROTO_UDP -+ ? ((struct udphdr*) (((caddr_t)ixs->iph) + (ixs->iph->ihl << 2)))->dest -+ : (ixs->iph->protocol == IPPROTO_TCP -+ ? ((struct tcphdr*)((caddr_t)ixs->iph + (ixs->iph->ihl << 2)))->dest -+ : 0)); -+ } -+ } -+ -+ ixs->ips.ips_addr_s = (struct sockaddr*)(&src); -+ ixs->ips.ips_addr_d = (struct sockaddr*)(&dst); -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "SADB_ACQUIRE sent with src=%s:%d, dst=%s:%d, proto=%d.\n", -+ addrtoa(((struct sockaddr_in*)(ixs->ips.ips_addr_s))->sin_addr, 0, bufsrc, sizeof(bufsrc)) <= ADDRTOA_BUF ? bufsrc : "BAD_ADDR", -+ ntohs(((struct sockaddr_in*)(ixs->ips.ips_addr_s))->sin_port), -+ addrtoa(((struct sockaddr_in*)(ixs->ips.ips_addr_d))->sin_addr, 0, bufdst, sizeof(bufdst)) <= ADDRTOA_BUF ? bufdst : "BAD_ADDR", -+ ntohs(((struct sockaddr_in*)(ixs->ips.ips_addr_d))->sin_port), -+ ixs->ips.ips_said.proto); -+ -+ /* increment count of total traps needed */ -+ ipsec_xmit_trap_count++; -+ -+ if (pfkey_acquire(&ixs->ips) == 0) { -+ -+ /* note that we succeeded */ -+ ipsec_xmit_trap_sendcount++; -+ -+ if (ixs->outgoing_said.spi==htonl(SPI_TRAPSUBNET)) { -+ /* -+ * The spinlock is to prevent any other -+ * process from accessing or deleting -+ * the eroute while we are using and -+ * updating it. -+ */ -+ spin_lock(&eroute_lock); -+ ixs->eroute = ipsec_findroute(&ixs->matcher); -+ if(ixs->eroute) { -+ ixs->eroute->er_said.spi = htonl(SPI_HOLD); -+ ixs->eroute->er_first = ixs->skb; -+ ixs->skb = NULL; -+ } -+ spin_unlock(&eroute_lock); -+ } else if (create_hold_eroute(ixs->eroute, -+ ixs->skb, -+ ixs->iph, -+ ixs->eroute_pid)) { -+ ixs->skb = NULL; -+ } -+ /* whether or not the above succeeded, we continue */ -+ -+ } -+ ixs->stats->tx_dropped++; -+ } -+ default: -+ /* XXX what do we do with an unknown shunt spi? */ -+ break; -+ } /* switch (ntohl(ixs->outgoing_said.spi)) */ -+ return IPSEC_XMIT_STOLEN; -+ } /* if (ixs->outgoing_said.proto == IPPROTO_INT) */ -+ -+ /* -+ The spinlock is to prevent any other process from -+ accessing or deleting the ipsec_sa hash table or any of the -+ ipsec_sa s while we are using and updating them. -+ -+ This is not optimal, but was relatively straightforward -+ at the time. A better way to do it has been planned for -+ more than a year, to lock the hash table and put reference -+ counts on each ipsec_sa instead. This is not likely to happen -+ in KLIPS1 unless a volunteer contributes it, but will be -+ designed into KLIPS2. -+ */ -+ spin_lock(&tdb_lock); -+ -+ ixs->ipsp = ipsec_sa_getbyid(&ixs->outgoing_said); -+ ixs->sa_len = satot(&ixs->outgoing_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt)); -+ -+ if (ixs->ipsp == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "no ipsec_sa for SA%s: outgoing packet with no SA, dropped.\n", -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ ixs->stats->tx_dropped++; -+ bundle_stat = IPSEC_XMIT_SAIDNOTFOUND; -+ goto cleanup; -+ } -+ -+ ipsec_sa_put(ixs->ipsp); /* incomplete */ -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "found ipsec_sa -- SA:<%s%s%s> %s\n", -+ IPS_XFORM_NAME(ixs->ipsp), -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ -+ /* -+ * How much headroom do we need to be able to apply -+ * all the grouped transforms? -+ */ -+ ixs->ipsq = ixs->ipsp; /* save the head of the ipsec_sa chain */ -+ while (ixs->ipsp) { -+ ixs->sa_len = satot(&ixs->ipsp->ips_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt)); -+ if(ixs->sa_len == 0) { -+ strcpy(ixs->sa_txt, "(error)"); -+ } -+ -+ /* If it is in larval state, drop the packet, we cannot process yet. */ -+ if(ixs->ipsp->ips_state == SADB_SASTATE_LARVAL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "ipsec_sa in larval state for SA:<%s%s%s> %s, cannot be used yet, dropping packet.\n", -+ IPS_XFORM_NAME(ixs->ipsp), -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_SAIDNOTLIVE; -+ goto cleanup; -+ } -+ -+ if(ixs->ipsp->ips_state == SADB_SASTATE_DEAD) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "ipsec_sa in dead state for SA:<%s%s%s> %s, can no longer be used, dropping packet.\n", -+ IPS_XFORM_NAME(ixs->ipsp), -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_SAIDNOTLIVE; -+ goto cleanup; -+ } -+ -+ /* If the replay window counter == -1, expire SA, it will roll */ -+ if(ixs->ipsp->ips_replaywin && ixs->ipsp->ips_replaywin_lastseq == -1) { -+ pfkey_expire(ixs->ipsp, 1); -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "replay window counter rolled for SA:<%s%s%s> %s, packet dropped, expiring SA.\n", -+ IPS_XFORM_NAME(ixs->ipsp), -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ ipsec_sa_delchain(ixs->ipsp); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_REPLAYROLLED; -+ goto cleanup; -+ } -+ -+ /* -+ * if this is the first time we are using this SA, mark start time, -+ * and offset hard/soft counters by "now" for later checking. -+ */ -+#if 0 -+ if(ixs->ipsp->ips_life.ipl_usetime.count == 0) { -+ ixs->ipsp->ips_life.ipl_usetime.count = jiffies; -+ ixs->ipsp->ips_life.ipl_usetime.hard += jiffies; -+ ixs->ipsp->ips_life.ipl_usetime.soft += jiffies; -+ } -+#endif -+ -+ -+ if(ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_bytes, "bytes", ixs->sa_txt, -+ ipsec_life_countbased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied || -+ ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_addtime, "addtime",ixs->sa_txt, -+ ipsec_life_timebased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied || -+ ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_usetime, "usetime",ixs->sa_txt, -+ ipsec_life_timebased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied || -+ ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_packets, "packets",ixs->sa_txt, -+ ipsec_life_countbased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied) { -+ -+ ipsec_sa_delchain(ixs->ipsp); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_LIFETIMEFAILED; -+ goto cleanup; -+ } -+ -+ -+ ixs->headroom = ixs->tailroom = 0; -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "calling room for <%s%s%s>, SA:%s\n", -+ IPS_XFORM_NAME(ixs->ipsp), -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ switch(ixs->ipsp->ips_said.proto) { -+#ifdef CONFIG_IPSEC_AH -+ case IPPROTO_AH: -+ ixs->headroom += sizeof(struct ahhdr); -+ break; -+#endif /* CONFIG_IPSEC_AH */ -+#ifdef CONFIG_IPSEC_ESP -+ case IPPROTO_ESP: -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_e=ixs->ipsp->ips_alg_enc)) { -+ blocksize = ixt_e->ixt_blocksize; -+ ixs->headroom += ESP_HEADER_LEN + ixt_e->ixt_ivlen/8; -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_encalg) { -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+ ixs->headroom += sizeof(struct esphdr); -+ break; -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ default: -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_ESP_BADALG; -+ goto cleanup; -+ } -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_a=ixs->ipsp->ips_alg_auth)) { -+ ixs->tailroom += AHHMAC_HASHLEN; -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_authalg) { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: -+ ixs->tailroom += AHHMAC_HASHLEN; -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: -+ ixs->tailroom += AHHMAC_HASHLEN; -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ case AH_NONE: -+ break; -+ default: -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_AH_BADALG; -+ goto cleanup; -+ } -+#ifdef CONFIG_IPSEC_ALG -+ ixs->tailroom += blocksize != 1 ? -+ ((blocksize - ((ixs->pyldsz + 2) % blocksize)) % blocksize) + 2 : -+ ((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2; -+#else -+ ixs->tailroom += ((8 - ((ixs->pyldsz + 2 * sizeof(unsigned char)) % 8)) % 8) + 2; -+#endif /* CONFIG_IPSEC_ALG */ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if ((ixs->ipsp->ips_natt_type) && (!ixs->natt_type)) { -+ ixs->natt_type = ixs->ipsp->ips_natt_type; -+ ixs->natt_sport = ixs->ipsp->ips_natt_sport; -+ ixs->natt_dport = ixs->ipsp->ips_natt_dport; -+ switch (ixs->natt_type) { -+ case ESPINUDP_WITH_NON_IKE: -+ ixs->natt_head = sizeof(struct udphdr)+(2*sizeof(__u32)); -+ break; -+ -+ case ESPINUDP_WITH_NON_ESP: -+ ixs->natt_head = sizeof(struct udphdr); -+ break; -+ -+ default: -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT -+ , "klips_xmit: invalid nat-t type %d" -+ , ixs->natt_type); -+ bundle_stat = IPSEC_XMIT_ESPUDP_BADTYPE; -+ goto cleanup; -+ -+ break; -+ } -+ ixs->tailroom += ixs->natt_head; -+ } -+#endif -+ break; -+#endif /* !CONFIG_IPSEC_ESP */ -+#ifdef CONFIG_IPSEC_IPIP -+ case IPPROTO_IPIP: -+ ixs->headroom += sizeof(struct iphdr); -+ break; -+#endif /* !CONFIG_IPSEC_IPIP */ -+ case IPPROTO_COMP: -+#ifdef CONFIG_IPSEC_IPCOMP -+ /* -+ We can't predict how much the packet will -+ shrink without doing the actual compression. -+ We could do it here, if we were the first -+ encapsulation in the chain. That might save -+ us a skb_copy_expand, since we might fit -+ into the existing skb then. However, this -+ would be a bit unclean (and this hack has -+ bit us once), so we better not do it. After -+ all, the skb_copy_expand is cheap in -+ comparison to the actual compression. -+ At least we know the packet will not grow. -+ */ -+ break; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ default: -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_BADPROTO; -+ goto cleanup; -+ } -+ ixs->ipsp = ixs->ipsp->ips_onext; -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "Required head,tailroom: %d,%d\n", -+ ixs->headroom, ixs->tailroom); -+ ixs->max_headroom += ixs->headroom; -+ ixs->max_tailroom += ixs->tailroom; -+ ixs->pyldsz += (ixs->headroom + ixs->tailroom); -+ } -+ ixs->ipsp = ixs->ipsq; /* restore the head of the ipsec_sa chain */ -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "existing head,tailroom: %d,%d before applying xforms with head,tailroom: %d,%d .\n", -+ skb_headroom(ixs->skb), skb_tailroom(ixs->skb), -+ ixs->max_headroom, ixs->max_tailroom); -+ -+ ixs->tot_headroom += ixs->max_headroom; -+ ixs->tot_tailroom += ixs->max_tailroom; -+ -+ ixs->mtudiff = ixs->prv->mtu + ixs->tot_headroom + ixs->tot_tailroom - ixs->physmtu; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "mtu:%d physmtu:%d tothr:%d tottr:%d mtudiff:%d ippkttotlen:%d\n", -+ ixs->prv->mtu, ixs->physmtu, -+ ixs->tot_headroom, ixs->tot_tailroom, ixs->mtudiff, ntohs(ixs->iph->tot_len)); -+ if(ixs->mtudiff > 0) { -+ int newmtu = ixs->physmtu - (ixs->tot_headroom + ((ixs->tot_tailroom + 2) & ~7) + 5); -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_info:ipsec_xmit_encap_bundle: " -+ "dev %s mtu of %d decreased by %d to %d\n", -+ ixs->dev->name, -+ ixs->prv->mtu, -+ ixs->prv->mtu - newmtu, -+ newmtu); -+ ixs->prv->mtu = newmtu; -+#ifdef NET_21 -+#if 0 -+ ixs->skb->dst->pmtu = ixs->prv->mtu; /* RGB */ -+#endif /* 0 */ -+#else /* NET_21 */ -+#if 0 -+ ixs->dev->mtu = ixs->prv->mtu; /* RGB */ -+#endif /* 0 */ -+#endif /* NET_21 */ -+ } -+ -+ /* -+ If the sender is doing PMTU discovery, and the -+ packet doesn't fit within ixs->prv->mtu, notify him -+ (unless it was an ICMP packet, or it was not the -+ zero-offset packet) and send it anyways. -+ -+ Note: buggy firewall configuration may prevent the -+ ICMP packet from getting back. -+ */ -+ if(sysctl_ipsec_icmp -+ && ixs->prv->mtu < ntohs(ixs->iph->tot_len) -+ && (ixs->iph->frag_off & __constant_htons(IP_DF)) ) { -+ int notify = ixs->iph->protocol != IPPROTO_ICMP -+ && (ixs->iph->frag_off & __constant_htons(IP_OFFSET)) == 0; -+ -+#ifdef IPSEC_obey_DF -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "fragmentation needed and DF set; %sdropping packet\n", -+ notify ? "sending ICMP and " : ""); -+ if (notify) -+ ICMP_SEND(ixs->skb, -+ ICMP_DEST_UNREACH, -+ ICMP_FRAG_NEEDED, -+ ixs->prv->mtu, -+ ixs->physdev); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_CANNOTFRAG; -+ goto cleanup; -+#else /* IPSEC_obey_DF */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "fragmentation needed and DF set; %spassing packet\n", -+ notify ? "sending ICMP and " : ""); -+ if (notify) -+ ICMP_SEND(ixs->skb, -+ ICMP_DEST_UNREACH, -+ ICMP_FRAG_NEEDED, -+ ixs->prv->mtu, -+ ixs->physdev); -+#endif /* IPSEC_obey_DF */ -+ } -+ -+#ifdef MSS_HACK -+ /* -+ * If this is a transport mode TCP packet with -+ * SYN set, determine an effective MSS based on -+ * AH/ESP overheads determined above. -+ */ -+ if (ixs->iph->protocol == IPPROTO_TCP -+ && ixs->outgoing_said.proto != IPPROTO_IPIP) { -+ struct tcphdr *tcph = ixs->skb->h.th; -+ if (tcph->syn && !tcph->ack) { -+ if(!ipsec_adjust_mss(ixs->skb, tcph, ixs->prv->mtu)) { -+ printk(KERN_WARNING -+ "klips_warning:ipsec_xmit_encap_bundle: " -+ "ipsec_adjust_mss() failed\n"); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_MSSERR; -+ goto cleanup; -+ } -+ } -+ } -+#endif /* MSS_HACK */ -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if ((ixs->natt_type) && (ixs->outgoing_said.proto != IPPROTO_IPIP)) { -+ /** -+ * NAT-Traversal and Transport Mode: -+ * we need to correct TCP/UDP checksum -+ * -+ * If we've got NAT-OA, we can fix checksum without recalculation. -+ * If we don't we can zero udp checksum. -+ */ -+ __u32 natt_oa = ixs->ipsp->ips_natt_oa ? -+ ((struct sockaddr_in*)(ixs->ipsp->ips_natt_oa))->sin_addr.s_addr : 0; -+ __u16 pkt_len = ixs->skb->tail - (unsigned char *)ixs->iph; -+ __u16 data_len = pkt_len - (ixs->iph->ihl << 2); -+ switch (ixs->iph->protocol) { -+ case IPPROTO_TCP: -+ if (data_len >= sizeof(struct tcphdr)) { -+ struct tcphdr *tcp = (struct tcphdr *)((__u32 *)ixs->iph+ixs->iph->ihl); -+ if (natt_oa) { -+ __u32 buff[2] = { ~ixs->iph->daddr, natt_oa }; -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: " -+ "fix TCP checksum using NAT-OA\n"); -+ tcp->check = csum_fold( -+ csum_partial((unsigned char *)buff, sizeof(buff), -+ tcp->check^0xffff)); -+ } -+ else { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: do not recalc TCP checksum\n"); -+ } -+ } -+ else { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: can't fix TCP checksum\n"); -+ } -+ break; -+ case IPPROTO_UDP: -+ if (data_len >= sizeof(struct udphdr)) { -+ struct udphdr *udp = (struct udphdr *)((__u32 *)ixs->iph+ixs->iph->ihl); -+ if (udp->check == 0) { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: UDP checksum already 0\n"); -+ } -+ else if (natt_oa) { -+ __u32 buff[2] = { ~ixs->iph->daddr, natt_oa }; -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: " -+ "fix UDP checksum using NAT-OA\n"); -+ udp->check = csum_fold( -+ csum_partial((unsigned char *)buff, sizeof(buff), -+ udp->check^0xffff)); -+ } -+ else { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: zero UDP checksum\n"); -+ udp->check = 0; -+ } -+ } -+ else { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: can't fix UDP checksum\n"); -+ } -+ break; -+ default: -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: non TCP/UDP packet -- do nothing\n"); -+ break; -+ } -+ } -+#endif /* CONFIG_IPSEC_NAT_TRAVERSAL */ -+ -+ if(!ixs->hard_header_stripped) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "allocating %d bytes for hardheader.\n", -+ ixs->hard_header_len); -+ if((ixs->saved_header = kmalloc(ixs->hard_header_len, GFP_ATOMIC)) == NULL) { -+ printk(KERN_WARNING "klips_debug:ipsec_xmit_encap_bundle: " -+ "Failed, tried to allocate %d bytes for temp hard_header.\n", -+ ixs->hard_header_len); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_ERRMEMALLOC; -+ goto cleanup; -+ } -+ { -+ int i; -+ for (i = 0; i < ixs->hard_header_len; i++) { -+ ixs->saved_header[i] = ixs->skb->data[i]; -+ } -+ } -+ if(ixs->skb->len < ixs->hard_header_len) { -+ printk(KERN_WARNING "klips_error:ipsec_xmit_encap_bundle: " -+ "tried to skb_pull hhlen=%d, %d available. This should never happen, please report.\n", -+ ixs->hard_header_len, (int)(ixs->skb->len)); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_ESP_PUSHPULLERR; -+ goto cleanup; -+ } -+ skb_pull(ixs->skb, ixs->hard_header_len); -+ ixs->hard_header_stripped = 1; -+ -+/* ixs->iph = (struct iphdr *) (ixs->skb->data); */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "head,tailroom: %d,%d after hard_header stripped.\n", -+ skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); -+ KLIPS_IP_PRINT(debug_tunnel & DB_TN_CROUT, ixs->iph); -+ } else { -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "hard header already stripped.\n"); -+ } -+ -+ ixs->ll_headroom = (ixs->hard_header_len + 15) & ~15; -+ -+ if ((skb_headroom(ixs->skb) >= ixs->max_headroom + 2 * ixs->ll_headroom) && -+ (skb_tailroom(ixs->skb) >= ixs->max_tailroom) -+#ifndef NET_21 -+ && ixs->skb->free -+#endif /* !NET_21 */ -+ ) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "data fits in existing skb\n"); -+ } else { -+ struct sk_buff* tskb; -+ -+ if(!ixs->oskb) { -+ ixs->oskb = ixs->skb; -+ } -+ -+ tskb = skb_copy_expand(ixs->skb, -+ /* The need for 2 * link layer length here remains unexplained...RGB */ -+ ixs->max_headroom + 2 * ixs->ll_headroom, -+ ixs->max_tailroom, -+ GFP_ATOMIC); -+#ifdef NET_21 -+ if(tskb && ixs->skb->sk) { -+ skb_set_owner_w(tskb, ixs->skb->sk); -+ } -+#endif /* NET_21 */ -+ if(ixs->skb != ixs->oskb) { -+ ipsec_kfree_skb(ixs->skb); -+ } -+ ixs->skb = tskb; -+ if (!ixs->skb) { -+ printk(KERN_WARNING -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "Failed, tried to allocate %d head and %d tailroom\n", -+ ixs->max_headroom, ixs->max_tailroom); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_ERRSKBALLOC; -+ goto cleanup; -+ } -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "head,tailroom: %d,%d after allocation\n", -+ skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); -+ } -+ -+ /* -+ * Apply grouped transforms to packet -+ */ -+ while (ixs->ipsp) { -+ enum ipsec_xmit_value encap_stat = IPSEC_XMIT_OK; -+ -+ encap_stat = ipsec_xmit_encap_once(ixs); -+ if(encap_stat != IPSEC_XMIT_OK) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: encap_once failed: %d\n", -+ encap_stat); -+ -+ bundle_stat = IPSEC_XMIT_ENCAPFAIL; -+ goto cleanup; -+ } -+ } -+ /* end encapsulation loop here XXX */ -+ cleanup: -+ spin_unlock(&tdb_lock); -+ return bundle_stat; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.8 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.7 2004/02/03 03:13:41 mcr -+ * mark invalid encapsulation states. -+ * -+ * Revision 1.6.2.1 2003/12/22 15:25:52 jjo -+ * Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.6 2003/12/10 01:14:27 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.5 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.4.4.2 2003/10/29 01:37:39 mcr -+ * when creating %hold from %trap, only make the %hold as -+ * specific as the %trap was - so if the protocol and ports -+ * were wildcards, then the %hold will be too. -+ * -+ * Revision 1.4.4.1 2003/09/21 13:59:56 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.4 2003/06/20 02:28:10 mcr -+ * misstype of variable name, not detected by module build. -+ * -+ * Revision 1.3 2003/06/20 01:42:21 mcr -+ * added counters to measure how many ACQUIREs we send to pluto, -+ * and how many are successfully sent. -+ * -+ * Revision 1.2 2003/04/03 17:38:35 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * Normalised coding style. -+ * Simplified logic and reduced duplication of code. -+ * -+ * Revision 1.1 2003/02/12 19:31:23 rgb -+ * Refactored from ipsec_tunnel.c -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/pfkey_v2.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,2126 @@ -+/* -+ * @(#) RFC2367 PF_KEYv2 Key management API domain socket I/F -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* -+ * Template from /usr/src/linux-2.0.36/net/unix/af_unix.c. -+ * Hints from /usr/src/linux-2.0.36/net/ipv4/udp.c. -+ */ -+ -+#define __NO_VERSION__ -+#include -+#include -+#include -+#include -+ -+#include "openswan/ipsec_param.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* struct socket */ -+#include -+#include -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include -+#include -+#include -+#include /* struct sock */ -+/* #include */ -+#include -+#ifdef CONFIG_PROC_FS -+# include -+#endif /* CONFIG_PROC_FS */ -+ -+#include -+ -+#include -+#ifdef NET_21 -+# include -+# include -+#endif /* NET_21 */ -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_pfkey = 0; -+extern int sysctl_ipsec_debug_verbose; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) -+ -+#ifndef SOCKOPS_WRAPPED -+#define SOCKOPS_WRAPPED(name) name -+#endif /* SOCKOPS_WRAPPED */ -+ -+extern struct proto_ops pfkey_ops; -+struct sock *pfkey_sock_list = NULL; -+struct supported_list *pfkey_supported_list[SADB_SATYPE_MAX+1]; -+ -+struct socket_list *pfkey_open_sockets = NULL; -+struct socket_list *pfkey_registered_sockets[SADB_SATYPE_MAX+1]; -+ -+int pfkey_msg_interp(struct sock *, struct sadb_msg *, struct sadb_msg **); -+ -+int -+pfkey_list_remove_socket(struct socket *socketp, struct socket_list **sockets) -+{ -+ struct socket_list *socket_listp,*prev; -+ -+ if(!socketp) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_remove_socket: " -+ "NULL socketp handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ if(!sockets) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_remove_socket: " -+ "NULL sockets list handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ socket_listp = *sockets; -+ prev = NULL; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_remove_socket: " -+ "removing sock=0p%p\n", -+ socketp); -+ -+ while(socket_listp != NULL) { -+ if(socket_listp->socketp == socketp) { -+ if(prev != NULL) { -+ prev->next = socket_listp->next; -+ } else { -+ *sockets = socket_listp->next; -+ } -+ -+ kfree((void*)socket_listp); -+ -+ break; -+ } -+ prev = socket_listp; -+ socket_listp = socket_listp->next; -+ } -+ -+ return 0; -+} -+ -+int -+pfkey_list_insert_socket(struct socket *socketp, struct socket_list **sockets) -+{ -+ struct socket_list *socket_listp; -+ -+ if(!socketp) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_socket: " -+ "NULL socketp handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ if(!sockets) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_socket: " -+ "NULL sockets list handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_socket: " -+ "allocating %lu bytes for socketp=0p%p\n", -+ (unsigned long) sizeof(struct socket_list), -+ socketp); -+ -+ if((socket_listp = (struct socket_list *)kmalloc(sizeof(struct socket_list), GFP_KERNEL)) == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_socket: " -+ "memory allocation error.\n"); -+ return -ENOMEM; -+ } -+ -+ socket_listp->socketp = socketp; -+ socket_listp->next = *sockets; -+ *sockets = socket_listp; -+ -+ return 0; -+} -+ -+int -+pfkey_list_remove_supported(struct supported *supported, struct supported_list **supported_list) -+{ -+ struct supported_list *supported_listp = *supported_list, *prev = NULL; -+ -+ if(!supported) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_remove_supported: " -+ "NULL supported handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ if(!supported_list) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_remove_supported: " -+ "NULL supported_list handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_remove_supported: " -+ "removing supported=0p%p\n", -+ supported); -+ -+ while(supported_listp != NULL) { -+ if(supported_listp->supportedp == supported) { -+ if(prev != NULL) { -+ prev->next = supported_listp->next; -+ } else { -+ *supported_list = supported_listp->next; -+ } -+ -+ kfree((void*)supported_listp); -+ -+ break; -+ } -+ prev = supported_listp; -+ supported_listp = supported_listp->next; -+ } -+ -+ return 0; -+} -+ -+int -+pfkey_list_insert_supported(struct supported *supported, struct supported_list **supported_list) -+{ -+ struct supported_list *supported_listp; -+ -+ if(!supported) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_supported: " -+ "NULL supported handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ if(!supported_list) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_supported: " -+ "NULL supported_list handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_supported: " -+ "allocating %lu bytes for incoming, supported=0p%p, supported_list=0p%p\n", -+ (unsigned long) sizeof(struct supported_list), -+ supported, -+ supported_list); -+ -+ supported_listp = (struct supported_list *)kmalloc(sizeof(struct supported_list), GFP_KERNEL); -+ if(supported_listp == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_supported: " -+ "memory allocation error.\n"); -+ return -ENOMEM; -+ } -+ -+ supported_listp->supportedp = supported; -+ supported_listp->next = *supported_list; -+ *supported_list = supported_listp; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_supported: " -+ "outgoing, supported=0p%p, supported_list=0p%p\n", -+ supported, -+ supported_list); -+ -+ return 0; -+} -+ -+#ifndef NET_21 -+DEBUG_NO_STATIC void -+pfkey_state_change(struct sock *sk) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_state_change: .\n"); -+ if(!sk->dead) { -+ wake_up_interruptible(sk->sleep); -+ } -+} -+#endif /* !NET_21 */ -+ -+#ifndef NET_21 -+DEBUG_NO_STATIC void -+pfkey_data_ready(struct sock *sk, int len) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_data_ready: " -+ "sk=0p%p len=%d\n", -+ sk, -+ len); -+ if(!sk->dead) { -+ wake_up_interruptible(sk->sleep); -+ sock_wake_async(sk->socket, 1); -+ } -+} -+ -+DEBUG_NO_STATIC void -+pfkey_write_space(struct sock *sk) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_write_space: .\n"); -+ if(!sk->dead) { -+ wake_up_interruptible(sk->sleep); -+ sock_wake_async(sk->socket, 2); -+ } -+} -+#endif /* !NET_21 */ -+ -+DEBUG_NO_STATIC void -+pfkey_insert_socket(struct sock *sk) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_insert_socket: " -+ "sk=0p%p\n", -+ sk); -+ cli(); -+ sk->next=pfkey_sock_list; -+ pfkey_sock_list=sk; -+ sti(); -+} -+ -+DEBUG_NO_STATIC void -+pfkey_remove_socket(struct sock *sk) -+{ -+ struct sock **s; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_remove_socket: .\n"); -+ cli(); -+ s=&pfkey_sock_list; -+ -+ while(*s!=NULL) { -+ if(*s==sk) { -+ *s=sk->next; -+ sk->next=NULL; -+ sti(); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_remove_socket: " -+ "succeeded.\n"); -+ return; -+ } -+ s=&((*s)->next); -+ } -+ sti(); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_remove_socket: " -+ "not found.\n"); -+ return; -+} -+ -+DEBUG_NO_STATIC void -+pfkey_destroy_socket(struct sock *sk) -+{ -+ struct sk_buff *skb; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_destroy_socket: .\n"); -+ pfkey_remove_socket(sk); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_destroy_socket: " -+ "pfkey_remove_socket called.\n"); -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_destroy_socket: " -+ "sk(0p%p)->(&0p%p)receive_queue.{next=0p%p,prev=0p%p}.\n", -+ sk, -+ &(sk->receive_queue), -+ sk->receive_queue.next, -+ sk->receive_queue.prev); -+ while(sk && ((skb=skb_dequeue(&(sk->receive_queue)))!=NULL)) { -+#ifdef NET_21 -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_pfkey && sysctl_ipsec_debug_verbose) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_destroy_socket: " -+ "skb=0p%p dequeued.\n", skb); -+ printk(KERN_INFO "klips_debug:pfkey_destroy_socket: " -+ "pfkey_skb contents:"); -+ printk(" next:0p%p", skb->next); -+ printk(" prev:0p%p", skb->prev); -+ printk(" list:0p%p", skb->list); -+ printk(" sk:0p%p", skb->sk); -+ printk(" stamp:%ld.%ld", skb->stamp.tv_sec, skb->stamp.tv_usec); -+ printk(" dev:0p%p", skb->dev); -+ if(skb->dev) { -+ if(skb->dev->name) { -+ printk(" dev->name:%s", skb->dev->name); -+ } else { -+ printk(" dev->name:NULL?"); -+ } -+ } else { -+ printk(" dev:NULL"); -+ } -+ printk(" h:0p%p", skb->h.raw); -+ printk(" nh:0p%p", skb->nh.raw); -+ printk(" mac:0p%p", skb->mac.raw); -+ printk(" dst:0p%p", skb->dst); -+ if(sysctl_ipsec_debug_verbose) { -+ int i; -+ -+ printk(" cb"); -+ for(i=0; i<48; i++) { -+ printk(":%2x", skb->cb[i]); -+ } -+ } -+ printk(" len:%d", skb->len); -+ printk(" csum:%d", skb->csum); -+#ifndef NETDEV_23 -+ printk(" used:%d", skb->used); -+ printk(" is_clone:%d", skb->is_clone); -+#endif /* NETDEV_23 */ -+ printk(" cloned:%d", skb->cloned); -+ printk(" pkt_type:%d", skb->pkt_type); -+ printk(" ip_summed:%d", skb->ip_summed); -+ printk(" priority:%d", skb->priority); -+ printk(" protocol:%d", skb->protocol); -+ printk(" security:%d", skb->security); -+ printk(" truesize:%d", skb->truesize); -+ printk(" head:0p%p", skb->head); -+ printk(" data:0p%p", skb->data); -+ printk(" tail:0p%p", skb->tail); -+ printk(" end:0p%p", skb->end); -+ if(sysctl_ipsec_debug_verbose) { -+ unsigned char* i; -+ printk(" data"); -+ for(i = skb->head; i < skb->end; i++) { -+ printk(":%2x", (unsigned char)(*(i))); -+ } -+ } -+ printk(" destructor:0p%p", skb->destructor); -+ printk("\n"); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif /* NET_21 */ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_destroy_socket: " -+ "skb=0p%p freed.\n", -+ skb); -+ ipsec_kfree_skb(skb); -+ } -+ -+ sk->dead = 1; -+ sk_free(sk); -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_destroy_socket: destroyed.\n"); -+} -+ -+int -+pfkey_upmsg(struct socket *sock, struct sadb_msg *pfkey_msg) -+{ -+ int error = 0; -+ struct sk_buff * skb = NULL; -+ struct sock *sk; -+ -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_upmsg: " -+ "NULL socket passed in.\n"); -+ return -EINVAL; -+ } -+ -+ if(pfkey_msg == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_upmsg: " -+ "NULL pfkey_msg passed in.\n"); -+ return -EINVAL; -+ } -+ -+#ifdef NET_21 -+ sk = sock->sk; -+#else /* NET_21 */ -+ sk = sock->data; -+#endif /* NET_21 */ -+ -+ if(sk == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_upmsg: " -+ "NULL sock passed in.\n"); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_upmsg: " -+ "allocating %d bytes...\n", -+ (int)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)); -+ if(!(skb = alloc_skb(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN, GFP_ATOMIC) )) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_upmsg: " -+ "no buffers left to send up a message.\n"); -+ return -ENOBUFS; -+ } -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_upmsg: " -+ "...allocated at 0p%p.\n", -+ skb); -+ -+ skb->dev = NULL; -+ -+ if(skb_tailroom(skb) < pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) { -+ printk(KERN_WARNING "klips_error:pfkey_upmsg: " -+ "tried to skb_put %ld, %d available. This should never happen, please report.\n", -+ (unsigned long int)pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN, -+ skb_tailroom(skb)); -+ ipsec_kfree_skb(skb); -+ return -ENOBUFS; -+ } -+ skb->h.raw = skb_put(skb, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); -+ memcpy(skb->h.raw, pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); -+ -+#ifndef NET_21 -+ skb->free = 1; -+#endif /* !NET_21 */ -+ -+ if((error = sock_queue_rcv_skb(sk, skb)) < 0) { -+ skb->sk=NULL; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_upmsg: " -+ "error=%d calling sock_queue_rcv_skb with skb=0p%p.\n", -+ error, -+ skb); -+ ipsec_kfree_skb(skb); -+ return error; -+ } -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_create(struct socket *sock, int protocol) -+{ -+ struct sock *sk; -+ -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "socket NULL.\n"); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "sock=0p%p type:%d state:%d flags:%ld protocol:%d\n", -+ sock, -+ sock->type, -+ (unsigned int)(sock->state), -+ sock->flags, protocol); -+ -+ if(sock->type != SOCK_RAW) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "only SOCK_RAW supported.\n"); -+ return -ESOCKTNOSUPPORT; -+ } -+ -+ if(protocol != PF_KEY_V2) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "protocol not PF_KEY_V2.\n"); -+ return -EPROTONOSUPPORT; -+ } -+ -+ if((current->uid != 0)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "must be root to open pfkey sockets.\n"); -+ return -EACCES; -+ } -+ -+#ifdef NET_21 -+ sock->state = SS_UNCONNECTED; -+#endif /* NET_21 */ -+ MOD_INC_USE_COUNT; -+#ifdef NET_21 -+ if((sk=(struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, 1)) == NULL) -+#else /* NET_21 */ -+ if((sk=(struct sock *)sk_alloc(GFP_KERNEL)) == NULL) -+#endif /* NET_21 */ -+ { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "Out of memory trying to allocate.\n"); -+ MOD_DEC_USE_COUNT; -+ return -ENOMEM; -+ } -+ -+#ifndef NET_21 -+ memset(sk, 0, sizeof(*sk)); -+#endif /* !NET_21 */ -+ -+#ifdef NET_21 -+ sock_init_data(sock, sk); -+ -+ sk->destruct = NULL; -+ sk->reuse = 1; -+ sock->ops = &pfkey_ops; -+ -+ sk->zapped=0; -+ sk->family = PF_KEY; -+/* sk->num = protocol; */ -+ sk->protocol = protocol; -+ key_pid(sk) = current->pid; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "sock->fasync_list=0p%p sk->sleep=0p%p.\n", -+ sock->fasync_list, -+ sk->sleep); -+#else /* NET_21 */ -+ sk->type=sock->type; -+ init_timer(&sk->timer); -+ skb_queue_head_init(&sk->write_queue); -+ skb_queue_head_init(&sk->receive_queue); -+ skb_queue_head_init(&sk->back_log); -+ sk->rcvbuf=SK_RMEM_MAX; -+ sk->sndbuf=SK_WMEM_MAX; -+ sk->allocation=GFP_KERNEL; -+ sk->state=TCP_CLOSE; -+ sk->priority=SOPRI_NORMAL; -+ sk->state_change=pfkey_state_change; -+ sk->data_ready=pfkey_data_ready; -+ sk->write_space=pfkey_write_space; -+ sk->error_report=pfkey_state_change; -+ sk->mtu=4096; -+ sk->socket=sock; -+ sock->data=(void *)sk; -+ sk->sleep=sock->wait; -+#endif /* NET_21 */ -+ -+ pfkey_insert_socket(sk); -+ pfkey_list_insert_socket(sock, &pfkey_open_sockets); -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "Socket sock=0p%p sk=0p%p initialised.\n", sock, sk); -+ return 0; -+} -+ -+#ifndef NET_21 -+DEBUG_NO_STATIC int -+pfkey_dup(struct socket *newsock, struct socket *oldsock) -+{ -+ struct sock *sk; -+ -+ if(newsock==NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_dup: " -+ "No new socket attached.\n"); -+ return -EINVAL; -+ } -+ -+ if(oldsock==NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_dup: " -+ "No old socket attached.\n"); -+ return -EINVAL; -+ } -+ -+#ifdef NET_21 -+ sk=oldsock->sk; -+#else /* NET_21 */ -+ sk=oldsock->data; -+#endif /* NET_21 */ -+ -+ /* May not have data attached */ -+ if(sk==NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_dup: " -+ "No sock attached to old socket.\n"); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_dup: .\n"); -+ -+ return pfkey_create(newsock, sk->protocol); -+} -+#endif /* !NET_21 */ -+ -+DEBUG_NO_STATIC int -+#ifdef NETDEV_23 -+pfkey_release(struct socket *sock) -+#else /* NETDEV_23 */ -+pfkey_release(struct socket *sock, struct socket *peersock) -+#endif /* NETDEV_23 */ -+{ -+ struct sock *sk; -+ int i; -+ -+ if(sock==NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_release: " -+ "No socket attached.\n"); -+ return 0; /* -EINVAL; */ -+ } -+ -+#ifdef NET_21 -+ sk=sock->sk; -+#else /* NET_21 */ -+ sk=sock->data; -+#endif /* NET_21 */ -+ -+ /* May not have data attached */ -+ if(sk==NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_release: " -+ "No sk attached to sock=0p%p.\n", sock); -+ return 0; /* -EINVAL; */ -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_release: " -+ "sock=0p%p sk=0p%p\n", sock, sk); -+ -+#ifdef NET_21 -+ if(!sk->dead) -+#endif /* NET_21 */ -+ if(sk->state_change) { -+ sk->state_change(sk); -+ } -+ -+#ifdef NET_21 -+ sock->sk = NULL; -+#else /* NET_21 */ -+ sock->data = NULL; -+#endif /* NET_21 */ -+ -+ /* Try to flush out this socket. Throw out buffers at least */ -+ pfkey_destroy_socket(sk); -+ pfkey_list_remove_socket(sock, &pfkey_open_sockets); -+ for(i = SADB_SATYPE_UNSPEC; i <= SADB_SATYPE_MAX; i++) { -+ pfkey_list_remove_socket(sock, &(pfkey_registered_sockets[i])); -+ } -+ -+ MOD_DEC_USE_COUNT; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_release: " -+ "succeeded.\n"); -+ -+ return 0; -+} -+ -+#ifndef NET_21 -+DEBUG_NO_STATIC int -+pfkey_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_bind: " -+ "operation not supported.\n"); -+ return -EINVAL; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_connect: " -+ "operation not supported.\n"); -+ return -EINVAL; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_socketpair(struct socket *a, struct socket *b) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_socketpair: " -+ "operation not supported.\n"); -+ return -EINVAL; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_accept(struct socket *sock, struct socket *newsock, int flags) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_aaccept: " -+ "operation not supported.\n"); -+ return -EINVAL; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, -+ int peer) -+{ -+ struct sockaddr *ska = (struct sockaddr*)uaddr; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getname: .\n"); -+ ska->sa_family = PF_KEY; -+ *uaddr_len = sizeof(*ska); -+ return 0; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_select(struct socket *sock, int sel_type, select_table *wait) -+{ -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_select: " -+ ".sock=0p%p sk=0p%p sel_type=%d\n", -+ sock, -+ sock->data, -+ sel_type); -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_select: " -+ "Null socket passed in.\n"); -+ return -EINVAL; -+ } -+ return datagram_select(sock->data, sel_type, wait); -+} -+ -+DEBUG_NO_STATIC int -+pfkey_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ioctl: " -+ "not supported.\n"); -+ return -EINVAL; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_listen(struct socket *sock, int backlog) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_listen: " -+ "not supported.\n"); -+ return -EINVAL; -+} -+#endif /* !NET_21 */ -+ -+DEBUG_NO_STATIC int -+pfkey_shutdown(struct socket *sock, int mode) -+{ -+ struct sock *sk; -+ -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_shutdown: " -+ "NULL socket passed in.\n"); -+ return -EINVAL; -+ } -+ -+#ifdef NET_21 -+ sk=sock->sk; -+#else /* NET_21 */ -+ sk=sock->data; -+#endif /* NET_21 */ -+ -+ if(sk == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_shutdown: " -+ "No sock attached to socket.\n"); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_shutdown: " -+ "mode=%x.\n", mode); -+ mode++; -+ -+ if(mode&SEND_SHUTDOWN) { -+ sk->shutdown|=SEND_SHUTDOWN; -+ sk->state_change(sk); -+ } -+ -+ if(mode&RCV_SHUTDOWN) { -+ sk->shutdown|=RCV_SHUTDOWN; -+ sk->state_change(sk); -+ } -+ return 0; -+} -+ -+#ifndef NET_21 -+DEBUG_NO_STATIC int -+pfkey_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) -+{ -+#ifndef NET_21 -+ struct sock *sk; -+ -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_setsockopt: " -+ "Null socket passed in.\n"); -+ return -EINVAL; -+ } -+ -+ sk=sock->data; -+ -+ if(sk == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_setsockopt: " -+ "Null sock passed in.\n"); -+ return -EINVAL; -+ } -+#endif /* !NET_21 */ -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_setsockopt: .\n"); -+ if(level!=SOL_SOCKET) { -+ return -EOPNOTSUPP; -+ } -+#ifdef NET_21 -+ return sock_setsockopt(sock, level, optname, optval, optlen); -+#else /* NET_21 */ -+ return sock_setsockopt(sk, level, optname, optval, optlen); -+#endif /* NET_21 */ -+} -+ -+DEBUG_NO_STATIC int -+pfkey_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) -+{ -+#ifndef NET_21 -+ struct sock *sk; -+ -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_setsockopt: " -+ "Null socket passed in.\n"); -+ return -EINVAL; -+ } -+ -+ sk=sock->data; -+ -+ if(sk == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_setsockopt: " -+ "Null sock passed in.\n"); -+ return -EINVAL; -+ } -+#endif /* !NET_21 */ -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getsockopt: .\n"); -+ if(level!=SOL_SOCKET) { -+ return -EOPNOTSUPP; -+ } -+#ifdef NET_21 -+ return sock_getsockopt(sock, level, optname, optval, optlen); -+#else /* NET_21 */ -+ return sock_getsockopt(sk, level, optname, optval, optlen); -+#endif /* NET_21 */ -+} -+ -+DEBUG_NO_STATIC int -+pfkey_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_fcntl: " -+ "not supported.\n"); -+ return -EINVAL; -+} -+#endif /* !NET_21 */ -+ -+/* -+ * Send PF_KEY data down. -+ */ -+ -+DEBUG_NO_STATIC int -+#ifdef NET_21 -+pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) -+#else /* NET_21 */ -+pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nonblock, int flags) -+#endif /* NET_21 */ -+{ -+ struct sock *sk; -+ int error = 0; -+ struct sadb_msg *pfkey_msg = NULL, *pfkey_reply = NULL; -+ -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "Null socket passed in.\n"); -+ SENDERR(EINVAL); -+ } -+ -+#ifdef NET_21 -+ sk = sock->sk; -+#else /* NET_21 */ -+ sk = sock->data; -+#endif /* NET_21 */ -+ -+ if(sk == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "Null sock passed in.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(msg == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "Null msghdr passed in.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: .\n"); -+ if(sk->err) { -+ error = sock_error(sk); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "sk->err is non-zero, returns %d.\n", -+ error); -+ SENDERR(-error); -+ } -+ -+ if((current->uid != 0)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "must be root to send messages to pfkey sockets.\n"); -+ SENDERR(EACCES); -+ } -+ -+#ifdef NET_21 -+ if(msg->msg_control) -+#else /* NET_21 */ -+ if(flags || msg->msg_control) -+#endif /* NET_21 */ -+ { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "can't set flags or set msg_control.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(sk->shutdown & SEND_SHUTDOWN) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "shutdown.\n"); -+ send_sig(SIGPIPE, current, 0); -+ SENDERR(EPIPE); -+ } -+ -+ if(len < sizeof(struct sadb_msg)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "bogus msg len of %d, too small.\n", len); -+ SENDERR(EMSGSIZE); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "allocating %d bytes for downward message.\n", -+ len); -+ if((pfkey_msg = (struct sadb_msg*)kmalloc(len, GFP_KERNEL)) == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "memory allocation error.\n"); -+ SENDERR(ENOBUFS); -+ } -+ -+ memcpy_fromiovec((void *)pfkey_msg, msg->msg_iov, len); -+ -+ if(pfkey_msg->sadb_msg_version != PF_KEY_V2) { -+ KLIPS_PRINT(1 || debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "not PF_KEY_V2 msg, found %d, should be %d.\n", -+ pfkey_msg->sadb_msg_version, -+ PF_KEY_V2); -+ kfree((void*)pfkey_msg); -+ return -EINVAL; -+ } -+ -+ if(len != pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "bogus msg len of %d, not %d byte aligned.\n", -+ len, (int)IPSEC_PFKEYv2_ALIGN); -+ SENDERR(EMSGSIZE); -+ } -+ -+#if 0 -+ /* This check is questionable, since a downward message could be -+ the result of an ACQUIRE either from kernel (PID==0) or -+ userspace (some other PID). */ -+ /* check PID */ -+ if(pfkey_msg->sadb_msg_pid != current->pid) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "pid (%d) does not equal sending process pid (%d).\n", -+ pfkey_msg->sadb_msg_pid, current->pid); -+ SENDERR(EINVAL); -+ } -+#endif -+ -+ if(pfkey_msg->sadb_msg_reserved) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "reserved field must be zero, set to %d.\n", -+ pfkey_msg->sadb_msg_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ if((pfkey_msg->sadb_msg_type > SADB_MAX) || (!pfkey_msg->sadb_msg_type)){ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "msg type too large or small:%d.\n", -+ pfkey_msg->sadb_msg_type); -+ SENDERR(EINVAL); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "msg sent for parsing.\n"); -+ -+ if((error = pfkey_msg_interp(sk, pfkey_msg, &pfkey_reply))) { -+ struct socket_list *pfkey_socketsp; -+ -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " -+ "pfkey_msg_parse returns %d.\n", -+ error); -+ -+ if((pfkey_reply = (struct sadb_msg*)kmalloc(sizeof(struct sadb_msg), GFP_KERNEL)) == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "memory allocation error.\n"); -+ SENDERR(ENOBUFS); -+ } -+ memcpy((void*)pfkey_reply, (void*)pfkey_msg, sizeof(struct sadb_msg)); -+ pfkey_reply->sadb_msg_errno = -error; -+ pfkey_reply->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN; -+ -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ int error_upmsg = 0; -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " -+ "sending up error=%d message=0p%p to socket=0p%p.\n", -+ error, -+ pfkey_reply, -+ pfkey_socketsp->socketp); -+ if((error_upmsg = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " -+ "sending up error message to socket=0p%p failed with error=%d.\n", -+ pfkey_socketsp->socketp, -+ error_upmsg); -+ /* pfkey_msg_free(&pfkey_reply); */ -+ /* SENDERR(-error); */ -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " -+ "sending up error message to socket=0p%p succeeded.\n", -+ pfkey_socketsp->socketp); -+ } -+ -+ pfkey_msg_free(&pfkey_reply); -+ -+ SENDERR(-error); -+ } -+ -+ errlab: -+ if (pfkey_msg) { -+ kfree((void*)pfkey_msg); -+ } -+ -+ if(error) { -+ return error; -+ } else { -+ return len; -+ } -+} -+ -+/* -+ * Receive PF_KEY data up. -+ */ -+ -+DEBUG_NO_STATIC int -+#ifdef NET_21 -+pfkey_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm) -+#else /* NET_21 */ -+pfkey_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock, int flags, int *addr_len) -+#endif /* NET_21 */ -+{ -+ struct sock *sk; -+#ifdef NET_21 -+ int noblock = flags & MSG_DONTWAIT; -+#endif /* NET_21 */ -+ struct sk_buff *skb; -+ int error; -+ -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_recvmsg: " -+ "Null socket passed in.\n"); -+ return -EINVAL; -+ } -+ -+#ifdef NET_21 -+ sk = sock->sk; -+#else /* NET_21 */ -+ sk = sock->data; -+#endif /* NET_21 */ -+ -+ if(sk == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_recvmsg: " -+ "Null sock passed in for sock=0p%p.\n", sock); -+ return -EINVAL; -+ } -+ -+ if(msg == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_recvmsg: " -+ "Null msghdr passed in for sock=0p%p, sk=0p%p.\n", -+ sock, sk); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_recvmsg: sock=0p%p sk=0p%p msg=0p%p size=%d.\n", -+ sock, sk, msg, size); -+ if(flags & ~MSG_PEEK) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "flags (%d) other than MSG_PEEK not supported.\n", -+ flags); -+ return -EOPNOTSUPP; -+ } -+ -+#ifdef NET_21 -+ msg->msg_namelen = 0; /* sizeof(*ska); */ -+#else /* NET_21 */ -+ if(addr_len) { -+ *addr_len = 0; /* sizeof(*ska); */ -+ } -+#endif /* NET_21 */ -+ -+ if(sk->err) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "sk->err=%d.\n", sk->err); -+ return sock_error(sk); -+ } -+ -+ if((skb = skb_recv_datagram(sk, flags, noblock, &error) ) == NULL) { -+ return error; -+ } -+ -+ if(size > skb->len) { -+ size = skb->len; -+ } -+#ifdef NET_21 -+ else if(size len) { -+ msg->msg_flags |= MSG_TRUNC; -+ } -+#endif /* NET_21 */ -+ -+ skb_copy_datagram_iovec(skb, 0, msg->msg_iov, size); -+ sk->stamp=skb->stamp; -+ -+ skb_free_datagram(sk, skb); -+ return size; -+} -+ -+#ifdef NET_21 -+struct net_proto_family pfkey_family_ops = { -+ PF_KEY, -+ pfkey_create -+}; -+ -+struct proto_ops SOCKOPS_WRAPPED(pfkey_ops) = { -+#ifdef NETDEV_23 -+ family: PF_KEY, -+ release: pfkey_release, -+ bind: sock_no_bind, -+ connect: sock_no_connect, -+ socketpair: sock_no_socketpair, -+ accept: sock_no_accept, -+ getname: sock_no_getname, -+ poll: datagram_poll, -+ ioctl: sock_no_ioctl, -+ listen: sock_no_listen, -+ shutdown: pfkey_shutdown, -+ setsockopt: sock_no_setsockopt, -+ getsockopt: sock_no_getsockopt, -+ sendmsg: pfkey_sendmsg, -+ recvmsg: pfkey_recvmsg, -+ mmap: sock_no_mmap, -+#else /* NETDEV_23 */ -+ PF_KEY, -+ sock_no_dup, -+ pfkey_release, -+ sock_no_bind, -+ sock_no_connect, -+ sock_no_socketpair, -+ sock_no_accept, -+ sock_no_getname, -+ datagram_poll, -+ sock_no_ioctl, -+ sock_no_listen, -+ pfkey_shutdown, -+ sock_no_setsockopt, -+ sock_no_getsockopt, -+ sock_no_fcntl, -+ pfkey_sendmsg, -+ pfkey_recvmsg -+#endif /* NETDEV_23 */ -+}; -+ -+#ifdef NETDEV_23 -+#include -+SOCKOPS_WRAP(pfkey, PF_KEY); -+#endif /* NETDEV_23 */ -+ -+#else /* NET_21 */ -+struct proto_ops pfkey_proto_ops = { -+ PF_KEY, -+ pfkey_create, -+ pfkey_dup, -+ pfkey_release, -+ pfkey_bind, -+ pfkey_connect, -+ pfkey_socketpair, -+ pfkey_accept, -+ pfkey_getname, -+ pfkey_select, -+ pfkey_ioctl, -+ pfkey_listen, -+ pfkey_shutdown, -+ pfkey_setsockopt, -+ pfkey_getsockopt, -+ pfkey_fcntl, -+ pfkey_sendmsg, -+ pfkey_recvmsg -+}; -+#endif /* NET_21 */ -+ -+#ifdef CONFIG_PROC_FS -+#ifndef PROC_FS_2325 -+DEBUG_NO_STATIC -+#endif /* PROC_FS_2325 */ -+int -+pfkey_get_info(char *buffer, char **start, off_t offset, int length -+#ifndef PROC_NO_DUMMY -+, int dummy -+#endif /* !PROC_NO_DUMMY */ -+) -+{ -+ const int max_content = length > 0? length-1 : 0; -+ off_t begin=0; -+ int len=0; -+ struct sock *sk=pfkey_sock_list; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if(!sysctl_ipsec_debug_verbose) { -+#endif /* CONFIG_IPSEC_DEBUG */ -+ len+= snprintf(buffer,length, -+ " sock pid socket next prev e n p sndbf Flags Type St\n"); -+#ifdef CONFIG_IPSEC_DEBUG -+ } else { -+ len+= snprintf(buffer,length, -+ " sock pid d sleep socket next prev e r z n p sndbf stamp Flags Type St\n"); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ while(sk!=NULL) { -+#ifdef CONFIG_IPSEC_DEBUG -+ if(!sysctl_ipsec_debug_verbose) { -+#endif /* CONFIG_IPSEC_DEBUG */ -+ len += ipsec_snprintf(buffer+len, length-len, -+ "%8p %5d %8p %8p %8p %d %d %d %5d %08lX %8X %2X\n", -+ sk, -+ key_pid(sk), -+ sk->socket, -+ sk->next, -+ sk->prev, -+ sk->err, -+ sk->num, -+ sk->protocol, -+ sk->sndbuf, -+ sk->socket->flags, -+ sk->socket->type, -+ sk->socket->state); -+#ifdef CONFIG_IPSEC_DEBUG -+ } else { -+ len += ipsec_snprintf(buffer+len, length-len, -+ "%8p %5d %d %8p %8p %8p %8p %d %d %d %d %d %5d %d.%06d %08lX %8X %2X\n", -+ sk, -+ key_pid(sk), -+ sk->dead, -+ sk->sleep, -+ sk->socket, -+ sk->next, -+ sk->prev, -+ sk->err, -+ sk->reuse, -+ sk->zapped, -+ sk->num, -+ sk->protocol, -+ sk->sndbuf, -+ (unsigned int)sk->stamp.tv_sec, -+ (unsigned int)sk->stamp.tv_usec, -+ sk->socket->flags, -+ sk->socket->type, -+ sk->socket->state); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ if (len >= max_content) { -+ /* we've done all that can fit -- stop loop */ -+ len = max_content; /* truncate crap */ -+ break; -+ } else { -+ -+ const off_t pos = begin + len; /* file position of end of what we've generated */ -+ -+ if (pos <= offset) { -+ /* all is before first interesting character: -+ * discard, but note where we are. -+ */ -+ len = 0; -+ begin = pos; -+ } -+ } -+ sk=sk->next; -+ -+ } -+ -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ return len - (offset - begin); -+ -+} -+ -+#ifndef PROC_FS_2325 -+DEBUG_NO_STATIC -+#endif /* PROC_FS_2325 */ -+int -+pfkey_supported_get_info(char *buffer, char **start, off_t offset, int length -+#ifndef PROC_NO_DUMMY -+, int dummy -+#endif /* !PROC_NO_DUMMY */ -+) -+{ -+ const int max_content = length > 0? length-1 : 0; -+ off_t begin=0; -+ int len=0; -+ int satype; -+ struct supported_list *pfkey_supported_p; -+ -+ len += ipsec_snprintf(buffer, length, -+ "satype exttype alg_id ivlen minbits maxbits\n"); -+ -+ for(satype = SADB_SATYPE_UNSPEC; satype <= SADB_SATYPE_MAX; satype++) { -+ pfkey_supported_p = pfkey_supported_list[satype]; -+ while(pfkey_supported_p) { -+ len += ipsec_snprintf(buffer+len, length-len, -+ " %2d %2d %2d %3d %3d %3d\n", -+ satype, -+ pfkey_supported_p->supportedp->supported_alg_exttype, -+ pfkey_supported_p->supportedp->supported_alg_id, -+ pfkey_supported_p->supportedp->supported_alg_ivlen, -+ pfkey_supported_p->supportedp->supported_alg_minbits, -+ pfkey_supported_p->supportedp->supported_alg_maxbits); -+ -+ if (len >= max_content) { -+ /* we've done all that can fit -- stop loop */ -+ len = max_content; /* truncate crap */ -+ break; -+ } else { -+ const off_t pos = begin + len; /* file position of end of what we've generated */ -+ -+ if (pos <= offset) { -+ /* all is before first interesting character: -+ * discard, but note where we are. -+ */ -+ len = 0; -+ begin = pos; -+ } -+ } -+ -+ pfkey_supported_p = pfkey_supported_p->next; -+ } -+ } -+ -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ return len - (offset - begin); -+ -+} -+ -+#ifndef PROC_FS_2325 -+DEBUG_NO_STATIC -+#endif /* PROC_FS_2325 */ -+int -+pfkey_registered_get_info(char *buffer, char **start, off_t offset, int length -+#ifndef PROC_NO_DUMMY -+, int dummy -+#endif /* !PROC_NO_DUMMY */ -+) -+{ -+ const int max_content = length > 0? length-1 : 0; -+ off_t begin=0; -+ int len=0; -+ int satype; -+ struct socket_list *pfkey_sockets; -+ -+ len += ipsec_snprintf(buffer, length, -+ "satype socket pid sk\n"); -+ -+ for(satype = SADB_SATYPE_UNSPEC; satype <= SADB_SATYPE_MAX; satype++) { -+ pfkey_sockets = pfkey_registered_sockets[satype]; -+ while(pfkey_sockets) { -+#ifdef NET_21 -+ len += ipsec_snprintf(buffer+len, length-len, -+ " %2d %8p %5d %8p\n", -+ satype, -+ pfkey_sockets->socketp, -+ key_pid(pfkey_sockets->socketp->sk), -+ pfkey_sockets->socketp->sk); -+#else /* NET_21 */ -+ len += ipsec_snprintf(buffer+len, length-len, -+ " %2d %8p N/A %8p\n", -+ satype, -+ pfkey_sockets->socketp, -+#if 0 -+ key_pid((pfkey_sockets->socketp)->data), -+#endif -+ (pfkey_sockets->socketp)->data); -+#endif /* NET_21 */ -+ -+ if (len >= max_content) { -+ /* we've done all that can fit -- stop loop (could stop two) */ -+ len = max_content; /* truncate crap */ -+ break; -+ } else { -+ const off_t pos = begin + len; /* file position of end of what we've generated */ -+ -+ if (pos <= offset) { -+ /* all is before first interesting character: -+ * discard, but note where we are. -+ */ -+ len = 0; -+ begin = pos; -+ } -+ } -+ -+ -+ pfkey_sockets = pfkey_sockets->next; -+ } -+ } -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ return len - (offset - begin); -+} -+ -+#ifndef PROC_FS_2325 -+struct proc_dir_entry proc_net_pfkey = -+{ -+ 0, -+ 6, "pf_key", -+ S_IFREG | S_IRUGO, 1, 0, 0, -+ 0, &proc_net_inode_operations, -+ pfkey_get_info -+}; -+struct proc_dir_entry proc_net_pfkey_supported = -+{ -+ 0, -+ 16, "pf_key_supported", -+ S_IFREG | S_IRUGO, 1, 0, 0, -+ 0, &proc_net_inode_operations, -+ pfkey_supported_get_info -+}; -+struct proc_dir_entry proc_net_pfkey_registered = -+{ -+ 0, -+ 17, "pf_key_registered", -+ S_IFREG | S_IRUGO, 1, 0, 0, -+ 0, &proc_net_inode_operations, -+ pfkey_registered_get_info -+}; -+#endif /* !PROC_FS_2325 */ -+#endif /* CONFIG_PROC_FS */ -+ -+DEBUG_NO_STATIC int -+supported_add_all(int satype, struct supported supported[], int size) -+{ -+ int i; -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:init_pfkey: " -+ "sizeof(supported_init_)[%d]/sizeof(struct supported)[%d]=%d.\n", -+ satype, -+ size, -+ (int)sizeof(struct supported), -+ (int)(size/sizeof(struct supported))); -+ -+ for(i = 0; i < size / sizeof(struct supported); i++) { -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:init_pfkey: " -+ "i=%d inserting satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n", -+ i, -+ satype, -+ supported[i].supported_alg_exttype, -+ supported[i].supported_alg_id, -+ supported[i].supported_alg_ivlen, -+ supported[i].supported_alg_minbits, -+ supported[i].supported_alg_maxbits); -+ -+ error |= pfkey_list_insert_supported(&(supported[i]), -+ &(pfkey_supported_list[satype])); -+ } -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+supported_remove_all(int satype) -+{ -+ int error = 0; -+ struct supported*supportedp; -+ -+ while(pfkey_supported_list[satype]) { -+ supportedp = pfkey_supported_list[satype]->supportedp; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:init_pfkey: " -+ "removing satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n", -+ satype, -+ supportedp->supported_alg_exttype, -+ supportedp->supported_alg_id, -+ supportedp->supported_alg_ivlen, -+ supportedp->supported_alg_minbits, -+ supportedp->supported_alg_maxbits); -+ -+ error |= pfkey_list_remove_supported(supportedp, -+ &(pfkey_supported_list[satype])); -+ } -+ return error; -+} -+ -+int -+pfkey_init(void) -+{ -+ int error = 0; -+ int i; -+ -+ static struct supported supported_init_ah[] = { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_MD5HMAC, 0, 128, 128}, -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_SHA1HMAC, 0, 160, 160} -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ }; -+ static struct supported supported_init_esp[] = { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_MD5HMAC, 0, 128, 128}, -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_SHA1HMAC, 0, 160, 160}, -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+#ifdef CONFIG_IPSEC_ENC_3DES -+ {SADB_EXT_SUPPORTED_ENCRYPT, SADB_EALG_3DESCBC, 64, 168, 168}, -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ }; -+ static struct supported supported_init_ipip[] = { -+ {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv4_in_IPv4, 0, 32, 32} -+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+ , {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv6_in_IPv4, 0, 128, 32} -+ , {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv4_in_IPv6, 0, 32, 128} -+ , {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv6_in_IPv6, 0, 128, 128} -+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ -+ }; -+#ifdef CONFIG_IPSEC_IPCOMP -+ static struct supported supported_init_ipcomp[] = { -+ {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_CALG_DEFLATE, 0, 1, 1} -+ }; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#if 0 -+ printk(KERN_INFO -+ "klips_info:pfkey_init: " -+ "FreeS/WAN: initialising PF_KEYv2 domain sockets.\n"); -+#endif -+ -+ for(i = SADB_SATYPE_UNSPEC; i <= SADB_SATYPE_MAX; i++) { -+ pfkey_registered_sockets[i] = NULL; -+ pfkey_supported_list[i] = NULL; -+ } -+ -+ error |= supported_add_all(SADB_SATYPE_AH, supported_init_ah, sizeof(supported_init_ah)); -+ error |= supported_add_all(SADB_SATYPE_ESP, supported_init_esp, sizeof(supported_init_esp)); -+#ifdef CONFIG_IPSEC_IPCOMP -+ error |= supported_add_all(SADB_X_SATYPE_COMP, supported_init_ipcomp, sizeof(supported_init_ipcomp)); -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ error |= supported_add_all(SADB_X_SATYPE_IPIP, supported_init_ipip, sizeof(supported_init_ipip)); -+ -+#ifdef NET_21 -+ error |= sock_register(&pfkey_family_ops); -+#else /* NET_21 */ -+ error |= sock_register(pfkey_proto_ops.family, &pfkey_proto_ops); -+#endif /* NET_21 */ -+ -+#ifdef CONFIG_PROC_FS -+# ifndef PROC_FS_2325 -+# ifdef PROC_FS_21 -+ error |= proc_register(proc_net, &proc_net_pfkey); -+ error |= proc_register(proc_net, &proc_net_pfkey_supported); -+ error |= proc_register(proc_net, &proc_net_pfkey_registered); -+# else /* PROC_FS_21 */ -+ error |= proc_register_dynamic(&proc_net, &proc_net_pfkey); -+ error |= proc_register_dynamic(&proc_net, &proc_net_pfkey_supported); -+ error |= proc_register_dynamic(&proc_net, &proc_net_pfkey_registered); -+# endif /* PROC_FS_21 */ -+# else /* !PROC_FS_2325 */ -+ proc_net_create ("pf_key", 0, pfkey_get_info); -+ proc_net_create ("pf_key_supported", 0, pfkey_supported_get_info); -+ proc_net_create ("pf_key_registered", 0, pfkey_registered_get_info); -+# endif /* !PROC_FS_2325 */ -+#endif /* CONFIG_PROC_FS */ -+ -+ return error; -+} -+ -+int -+pfkey_cleanup(void) -+{ -+ int error = 0; -+ -+ printk(KERN_INFO "klips_info:pfkey_cleanup: " -+ "shutting down PF_KEY domain sockets.\n"); -+#ifdef NET_21 -+ error |= sock_unregister(PF_KEY); -+#else /* NET_21 */ -+ error |= sock_unregister(pfkey_proto_ops.family); -+#endif /* NET_21 */ -+ -+ error |= supported_remove_all(SADB_SATYPE_AH); -+ error |= supported_remove_all(SADB_SATYPE_ESP); -+#ifdef CONFIG_IPSEC_IPCOMP -+ error |= supported_remove_all(SADB_X_SATYPE_COMP); -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ error |= supported_remove_all(SADB_X_SATYPE_IPIP); -+ -+#ifdef CONFIG_PROC_FS -+# ifndef PROC_FS_2325 -+ if (proc_net_unregister(proc_net_pfkey.low_ino) != 0) -+ printk("klips_debug:pfkey_cleanup: " -+ "cannot unregister /proc/net/pf_key\n"); -+ if (proc_net_unregister(proc_net_pfkey_supported.low_ino) != 0) -+ printk("klips_debug:pfkey_cleanup: " -+ "cannot unregister /proc/net/pf_key_supported\n"); -+ if (proc_net_unregister(proc_net_pfkey_registered.low_ino) != 0) -+ printk("klips_debug:pfkey_cleanup: " -+ "cannot unregister /proc/net/pf_key_registered\n"); -+# else /* !PROC_FS_2325 */ -+ proc_net_remove ("pf_key"); -+ proc_net_remove ("pf_key_supported"); -+ proc_net_remove ("pf_key_registered"); -+# endif /* !PROC_FS_2325 */ -+#endif /* CONFIG_PROC_FS */ -+ -+ /* other module unloading cleanup happens here */ -+ return error; -+} -+ -+#ifdef MODULE -+#if 0 -+int -+init_module(void) -+{ -+ pfkey_init(); -+ return 0; -+} -+ -+void -+cleanup_module(void) -+{ -+ pfkey_cleanup(); -+} -+#endif /* 0 */ -+#else /* MODULE */ -+void -+pfkey_proto_init(struct net_proto *pro) -+{ -+ pfkey_init(); -+} -+#endif /* MODULE */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.81 2004/04/25 21:23:11 ken -+ * Pull in dhr's changes from FreeS/WAN 2.06 -+ * -+ * Revision 1.80 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.79.4.1 2003/12/22 15:25:52 jjo -+ * . Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.79 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.78.4.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.78 2003/04/03 17:38:09 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * -+ * Revision 1.77 2002/10/17 16:49:36 mcr -+ * sock->ops should reference the unwrapped options so that -+ * we get hacked in locking on SMP systems. -+ * -+ * Revision 1.76 2002/10/12 23:11:53 dhr -+ * -+ * [KenB + DHR] more 64-bit cleanup -+ * -+ * Revision 1.75 2002/09/20 05:01:57 rgb -+ * Added memory allocation debugging. -+ * -+ * Revision 1.74 2002/09/19 02:42:50 mcr -+ * do not define the pfkey_ops function for now. -+ * -+ * Revision 1.73 2002/09/17 17:29:23 mcr -+ * #if 0 out some dead code - pfkey_ops is never used as written. -+ * -+ * Revision 1.72 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.71 2002/05/23 07:14:11 rgb -+ * Cleaned up %p variants to 0p%p for test suite cleanup. -+ * -+ * Revision 1.70 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.69 2002/04/24 07:36:33 mcr -+ * Moved from ./klips/net/ipsec/pfkey_v2.c,v -+ * -+ * Revision 1.68 2002/03/08 01:15:17 mcr -+ * put some internal structure only debug messages behind -+ * && sysctl_ipsec_debug_verbose. -+ * -+ * Revision 1.67 2002/01/29 17:17:57 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.66 2002/01/29 04:00:54 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.65 2002/01/29 02:13:18 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.64 2001/11/26 09:23:51 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.61.2.1 2001/09/25 02:28:44 mcr -+ * cleaned up includes. -+ * -+ * Revision 1.63 2001/11/12 19:38:00 rgb -+ * Continue trying other sockets even if one fails and return only original -+ * error. -+ * -+ * Revision 1.62 2001/10/18 04:45:22 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.61 2001/09/20 15:32:59 rgb -+ * Min/max cleanup. -+ * -+ * Revision 1.60 2001/06/14 19:35:12 rgb -+ * Update copyright date. -+ * -+ * Revision 1.59 2001/06/13 15:35:48 rgb -+ * Fixed #endif comments. -+ * -+ * Revision 1.58 2001/05/04 16:37:24 rgb -+ * Remove erroneous checking of return codes for proc_net_* in 2.4. -+ * -+ * Revision 1.57 2001/05/03 19:43:36 rgb -+ * Initialise error return variable. -+ * Check error return codes in startup and shutdown. -+ * Standardise on SENDERR() macro. -+ * -+ * Revision 1.56 2001/04/21 23:05:07 rgb -+ * Define out skb->used for 2.4 kernels. -+ * -+ * Revision 1.55 2001/02/28 05:03:28 rgb -+ * Clean up and rationalise startup messages. -+ * -+ * Revision 1.54 2001/02/27 22:24:55 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.53 2001/02/27 06:48:18 rgb -+ * Fixed pfkey socket unregister log message to reflect type and function. -+ * -+ * Revision 1.52 2001/02/26 22:34:38 rgb -+ * Fix error return code that was getting overwritten by the error return -+ * code of an upmsg. -+ * -+ * Revision 1.51 2001/01/30 23:42:47 rgb -+ * Allow pfkey msgs from pid other than user context required for ACQUIRE -+ * and subsequent ADD or UDATE. -+ * -+ * Revision 1.50 2001/01/23 20:22:59 rgb -+ * 2.4 fix to remove removed is_clone member. -+ * -+ * Revision 1.49 2000/11/06 04:33:47 rgb -+ * Changed non-exported functions to DEBUG_NO_STATIC. -+ * -+ * Revision 1.48 2000/09/29 19:47:41 rgb -+ * Update copyright. -+ * -+ * Revision 1.47 2000/09/22 04:23:04 rgb -+ * Added more debugging to pfkey_upmsg() call from pfkey_sendmsg() error. -+ * -+ * Revision 1.46 2000/09/21 04:20:44 rgb -+ * Fixed array size off-by-one error. (Thanks Svenning!) -+ * -+ * Revision 1.45 2000/09/20 04:01:26 rgb -+ * Changed static functions to DEBUG_NO_STATIC for revealing function names -+ * in oopsen. -+ * -+ * Revision 1.44 2000/09/19 00:33:17 rgb -+ * 2.0 fixes. -+ * -+ * Revision 1.43 2000/09/16 01:28:13 rgb -+ * Fixed use of 0 in p format warning. -+ * -+ * Revision 1.42 2000/09/16 01:09:41 rgb -+ * Fixed debug format warning for pointers that was expecting ints. -+ * -+ * Revision 1.41 2000/09/13 15:54:00 rgb -+ * Rewrote pfkey_get_info(), added pfkey_{supported,registered}_get_info(). -+ * Moved supported algos add and remove to functions. -+ * -+ * Revision 1.40 2000/09/12 18:49:28 rgb -+ * Added IPIP tunnel and IPCOMP register support. -+ * -+ * Revision 1.39 2000/09/12 03:23:49 rgb -+ * Converted #if0 debugs to sysctl. -+ * Removed debug_pfkey initialisations that prevented no_debug loading or -+ * linking. -+ * -+ * Revision 1.38 2000/09/09 06:38:02 rgb -+ * Return positive errno in pfkey_reply error message. -+ * -+ * Revision 1.37 2000/09/08 19:19:09 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * Clean-up of long-unused crud... -+ * Create pfkey error message on on failure. -+ * Give pfkey_list_{insert,remove}_{socket,supported}() some error -+ * checking. -+ * -+ * Revision 1.36 2000/09/01 18:49:38 rgb -+ * Reap experimental NET_21_ bits. -+ * Turned registered sockets list into an array of one list per satype. -+ * Remove references to deprecated sklist_{insert,remove}_socket. -+ * Removed leaking socket debugging code. -+ * Removed duplicate pfkey_insert_socket in pfkey_create. -+ * Removed all references to pfkey msg->msg_name, since it is not used for -+ * pfkey. -+ * Added a supported algorithms array lists, one per satype and registered -+ * existing algorithms. -+ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to -+ * list. -+ * Only send pfkey_expire() messages to sockets registered for that satype. -+ * -+ * Revision 1.35 2000/08/24 17:03:00 rgb -+ * Corrected message size error return code for PF_KEYv2. -+ * Removed downward error prohibition. -+ * -+ * Revision 1.34 2000/08/21 16:32:26 rgb -+ * Re-formatted for cosmetic consistency and readability. -+ * -+ * Revision 1.33 2000/08/20 21:38:24 rgb -+ * Added a pfkey_reply parameter to pfkey_msg_interp(). (Momchil) -+ * Extended the upward message initiation of pfkey_sendmsg(). (Momchil) -+ * -+ * Revision 1.32 2000/07/28 14:58:31 rgb -+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. -+ * -+ * Revision 1.31 2000/05/16 03:04:00 rgb -+ * Updates for 2.3.99pre8 from MB. -+ * -+ * Revision 1.30 2000/05/10 19:22:21 rgb -+ * Use sklist private functions for 2.3.xx compatibility. -+ * -+ * Revision 1.29 2000/03/22 16:17:03 rgb -+ * Fixed SOCKOPS_WRAPPED macro for SMP (MB). -+ * -+ * Revision 1.28 2000/02/21 19:30:45 rgb -+ * Removed references to pkt_bridged for 2.3.47 compatibility. -+ * -+ * Revision 1.27 2000/02/14 21:07:00 rgb -+ * Fixed /proc/net/pf-key legend spacing. -+ * -+ * Revision 1.26 2000/01/22 03:46:59 rgb -+ * Fixed pfkey error return mechanism so that we are able to free the -+ * local copy of the pfkey_msg, plugging a memory leak and silencing -+ * the bad object free complaints. -+ * -+ * Revision 1.25 2000/01/21 06:19:44 rgb -+ * Moved pfkey_list_remove_socket() calls to before MOD_USE_DEC_COUNT. -+ * Added debugging to pfkey_upmsg. -+ * -+ * Revision 1.24 2000/01/10 16:38:23 rgb -+ * MB fixups for 2.3.x. -+ * -+ * Revision 1.23 1999/12/09 23:22:16 rgb -+ * Added more instrumentation for debugging 2.0 socket -+ * selection/reading. -+ * Removed erroneous 2.0 wait==NULL check bug in select. -+ * -+ * Revision 1.22 1999/12/08 20:32:16 rgb -+ * Tidied up 2.0.xx support, after major pfkey work, eliminating -+ * msg->msg_name twiddling in the process, since it is not defined -+ * for PF_KEYv2. -+ * -+ * Revision 1.21 1999/12/01 22:17:19 rgb -+ * Set skb->dev to zero on new skb in case it is a reused skb. -+ * Added check for skb_put overflow and freeing to avoid upmsg on error. -+ * Added check for wrong pfkey version and freeing to avoid upmsg on -+ * error. -+ * Shut off content dumping in pfkey_destroy. -+ * Added debugging message for size of buffer allocated for upmsg. -+ * -+ * Revision 1.20 1999/11/27 12:11:00 rgb -+ * Minor clean-up, enabling quiet operation of pfkey if desired. -+ * -+ * Revision 1.19 1999/11/25 19:04:21 rgb -+ * Update proc_fs code for pfkey to use dynamic registration. -+ * -+ * Revision 1.18 1999/11/25 09:07:17 rgb -+ * Implemented SENDERR macro for propagating error codes. -+ * Fixed error return code bug. -+ * -+ * Revision 1.17 1999/11/23 23:07:20 rgb -+ * Change name of pfkey_msg_parser to pfkey_msg_interp since it no longer -+ * parses. (PJO) -+ * Sort out pfkey and freeswan headers, putting them in a library path. -+ * -+ * Revision 1.16 1999/11/20 22:00:22 rgb -+ * Moved socketlist type declarations and prototypes for shared use. -+ * Renamed reformatted and generically extended for use by other socket -+ * lists pfkey_{del,add}_open_socket to pfkey_list_{remove,insert}_socket. -+ * -+ * Revision 1.15 1999/11/18 04:15:09 rgb -+ * Make pfkey_data_ready temporarily available for 2.2.x testing. -+ * Clean up pfkey_destroy_socket() debugging statements. -+ * Add Peter Onion's code to send messages up to all listening sockets. -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * Replaced all kernel version macros to shorter, readable form. -+ * Added CONFIG_PROC_FS compiler directives in case it is shut off. -+ * -+ * Revision 1.14 1999/11/17 16:01:00 rgb -+ * Make pfkey_data_ready temporarily available for 2.2.x testing. -+ * Clean up pfkey_destroy_socket() debugging statements. -+ * Add Peter Onion's code to send messages up to all listening sockets. -+ * Changed #include "../../../lib/freeswan.h" to #include -+ * which works due to -Ilibfreeswan in the klips/net/ipsec/Makefile. -+ * -+ * Revision 1.13 1999/10/27 19:59:51 rgb -+ * Removed af_unix comments that are no longer relevant. -+ * Added debug prink statements. -+ * Added to the /proc output in pfkey_get_info. -+ * Made most functions non-static to enable oops tracing. -+ * Re-enable skb dequeueing and freeing. -+ * Fix skb_alloc() and skb_put() size bug in pfkey_upmsg(). -+ * -+ * Revision 1.12 1999/10/26 17:05:42 rgb -+ * Complete re-ordering based on proto_ops structure order. -+ * Separated out proto_ops structures for 2.0.x and 2.2.x for clarity. -+ * Simplification to use built-in socket ops where possible for 2.2.x. -+ * Add shorter macros for compiler directives to visually clean-up. -+ * Add lots of sk skb dequeueing debugging statements. -+ * Added to the /proc output in pfkey_get_info. -+ * -+ * Revision 1.11 1999/09/30 02:55:10 rgb -+ * Bogus skb detection. -+ * Fix incorrect /proc/net/ipsec-eroute printk message. -+ * -+ * Revision 1.10 1999/09/21 15:22:13 rgb -+ * Temporary fix while I figure out the right way to destroy sockets. -+ * -+ * Revision 1.9 1999/07/08 19:19:44 rgb -+ * Fix pointer format warning. -+ * Fix missing member error under 2.0.xx kernels. -+ * -+ * Revision 1.8 1999/06/13 07:24:04 rgb -+ * Add more debugging. -+ * -+ * Revision 1.7 1999/06/10 05:24:17 rgb -+ * Clarified compiler directives. -+ * Renamed variables to reduce confusion. -+ * Used sklist_*_socket() kernel functions to simplify 2.2.x socket support. -+ * Added lots of sanity checking. -+ * -+ * Revision 1.6 1999/06/03 18:59:50 rgb -+ * More updates to 2.2.x socket support. Almost works, oops at end of call. -+ * -+ * Revision 1.5 1999/05/25 22:44:05 rgb -+ * Start fixing 2.2 sockets. -+ * -+ * Revision 1.4 1999/04/29 15:21:34 rgb -+ * Move log to the end of the file. -+ * Eliminate min/max redefinition in #include . -+ * Correct path for pfkey #includes -+ * Standardise an error return method. -+ * Add debugging instrumentation. -+ * Move message type checking to pfkey_msg_parse(). -+ * Add check for errno incorrectly set. -+ * Add check for valid PID. -+ * Add check for reserved illegally set. -+ * Add check for message out of bounds. -+ * -+ * Revision 1.3 1999/04/15 17:58:07 rgb -+ * Add RCSID labels. -+ * -+ * Revision 1.2 1999/04/15 15:37:26 rgb -+ * Forward check changes from POST1_00 branch. -+ * -+ * Revision 1.1.2.2 1999/04/13 20:37:12 rgb -+ * Header Title correction. -+ * -+ * Revision 1.1.2.1 1999/03/26 20:58:55 rgb -+ * Add pfkeyv2 support to KLIPS. -+ * -+ * -+ * RFC 2367 -+ * PF_KEY_v2 Key Management API -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/pfkey_v2_ext_process.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,922 @@ -+/* -+ * @(#) RFC2367 PF_KEYv2 Key management API message parser -+ * Copyright (C) 1998-2003 Richard Guy Briggs. -+ * Copyright (C) 2004 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* -+ * Template from klips/net/ipsec/ipsec/ipsec_netlink.c. -+ */ -+ -+char pfkey_v2_ext_process_c_version[] = "$Id$"; -+ -+#include -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+ -+#include -+ -+#include -+ -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define ip_chk_addr inet_addr_type -+# define IS_MYADDR RTN_LOCAL -+#endif -+#include -+#include -+#ifdef NETLINK_SOCK -+# include -+#else -+# include -+#endif -+ -+#include /* get_random_bytes() */ -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipcomp.h" -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+#include "openswan/ipsec_alg.h" -+ -+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) -+ -+int -+pfkey_sa_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext; -+ int error = 0; -+ struct ipsec_sa* ipsp; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sa_process: .\n"); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sa_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_ext->sadb_ext_type) { -+ case SADB_EXT_SA: -+ ipsp = extr->ips; -+ break; -+ case SADB_X_EXT_SA2: -+ if(extr->ips2 == NULL) { -+ extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */ -+ } -+ if(extr->ips2 == NULL) { -+ SENDERR(-error); -+ } -+ ipsp = extr->ips2; -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sa_process: " -+ "invalid exttype=%d.\n", -+ pfkey_ext->sadb_ext_type); -+ SENDERR(EINVAL); -+ } -+ -+ ipsp->ips_said.spi = pfkey_sa->sadb_sa_spi; -+ ipsp->ips_replaywin = pfkey_sa->sadb_sa_replay; -+ ipsp->ips_state = pfkey_sa->sadb_sa_state; -+ ipsp->ips_flags = pfkey_sa->sadb_sa_flags; -+ ipsp->ips_replaywin_lastseq = ipsp->ips_replaywin_bitmap = 0; -+ ipsp->ips_ref_rel = pfkey_sa->sadb_x_sa_ref; -+ -+ switch(ipsp->ips_said.proto) { -+ case IPPROTO_AH: -+ ipsp->ips_authalg = pfkey_sa->sadb_sa_auth; -+ ipsp->ips_encalg = SADB_EALG_NONE; -+ break; -+ case IPPROTO_ESP: -+ ipsp->ips_authalg = pfkey_sa->sadb_sa_auth; -+ ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt; -+#ifdef CONFIG_IPSEC_ALG -+ ipsec_alg_sa_init(ipsp); -+#endif /* CONFIG_IPSEC_ALG */ -+ break; -+ case IPPROTO_IPIP: -+ ipsp->ips_authalg = AH_NONE; -+ ipsp->ips_encalg = ESP_NONE; -+ break; -+#ifdef CONFIG_IPSEC_IPCOMP -+ case IPPROTO_COMP: -+ ipsp->ips_authalg = AH_NONE; -+ ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt; -+ break; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ case IPPROTO_INT: -+ ipsp->ips_authalg = AH_NONE; -+ ipsp->ips_encalg = ESP_NONE; -+ break; -+ case 0: -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sa_process: " -+ "unknown proto=%d.\n", -+ ipsp->ips_said.proto); -+ SENDERR(EINVAL); -+ } -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_lifetime_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_lifetime_process: .\n"); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_lifetime_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_lifetime->sadb_lifetime_exttype) { -+ case SADB_EXT_LIFETIME_CURRENT: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_lifetime_process: " -+ "lifetime_current not supported yet.\n"); -+ SENDERR(EINVAL); -+ break; -+ case SADB_EXT_LIFETIME_HARD: -+ ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_allocations, -+ pfkey_lifetime->sadb_lifetime_allocations); -+ -+ ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_bytes, -+ pfkey_lifetime->sadb_lifetime_bytes); -+ -+ ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_addtime, -+ pfkey_lifetime->sadb_lifetime_addtime); -+ -+ ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_usetime, -+ pfkey_lifetime->sadb_lifetime_usetime); -+ -+ break; -+ -+ case SADB_EXT_LIFETIME_SOFT: -+ ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_allocations, -+ pfkey_lifetime->sadb_lifetime_allocations); -+ -+ ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_bytes, -+ pfkey_lifetime->sadb_lifetime_bytes); -+ -+ ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_addtime, -+ pfkey_lifetime->sadb_lifetime_addtime); -+ -+ ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_usetime, -+ pfkey_lifetime->sadb_lifetime_usetime); -+ -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_lifetime_process: " -+ "invalid exttype=%d.\n", -+ pfkey_ext->sadb_ext_type); -+ SENDERR(EINVAL); -+ } -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_address_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ int saddr_len = 0; -+ char ipaddr_txt[ADDRTOA_BUF]; -+ unsigned char **sap; -+ unsigned short * portp = 0; -+ struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext; -+ struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address)); -+ struct ipsec_sa* ipsp; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process:\n"); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(s->sa_family) { -+ case AF_INET: -+ saddr_len = sizeof(struct sockaddr_in); -+ addrtoa(((struct sockaddr_in*)s)->sin_addr, 0, ipaddr_txt, sizeof(ipaddr_txt)); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found address family=%d, AF_INET, %s.\n", -+ s->sa_family, -+ ipaddr_txt); -+ break; -+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+ case AF_INET6: -+ saddr_len = sizeof(struct sockaddr_in6); -+ break; -+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "s->sa_family=%d not supported.\n", -+ s->sa_family); -+ SENDERR(EPFNOSUPPORT); -+ } -+ -+ switch(pfkey_address->sadb_address_exttype) { -+ case SADB_EXT_ADDRESS_SRC: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found src address.\n"); -+ sap = (unsigned char **)&(extr->ips->ips_addr_s); -+ extr->ips->ips_addr_s_size = saddr_len; -+ break; -+ case SADB_EXT_ADDRESS_DST: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found dst address.\n"); -+ sap = (unsigned char **)&(extr->ips->ips_addr_d); -+ extr->ips->ips_addr_d_size = saddr_len; -+ break; -+ case SADB_EXT_ADDRESS_PROXY: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found proxy address.\n"); -+ sap = (unsigned char **)&(extr->ips->ips_addr_p); -+ extr->ips->ips_addr_p_size = saddr_len; -+ break; -+ case SADB_X_EXT_ADDRESS_DST2: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found 2nd dst address.\n"); -+ if(extr->ips2 == NULL) { -+ extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */ -+ } -+ if(extr->ips2 == NULL) { -+ SENDERR(-error); -+ } -+ sap = (unsigned char **)&(extr->ips2->ips_addr_d); -+ extr->ips2->ips_addr_d_size = saddr_len; -+ break; -+ case SADB_X_EXT_ADDRESS_SRC_FLOW: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found src flow address.\n"); -+ if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { -+ SENDERR(ENOMEM); -+ } -+ sap = (unsigned char **)&(extr->eroute->er_eaddr.sen_ip_src); -+ portp = &(extr->eroute->er_eaddr.sen_sport); -+ break; -+ case SADB_X_EXT_ADDRESS_DST_FLOW: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found dst flow address.\n"); -+ if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { -+ SENDERR(ENOMEM); -+ } -+ sap = (unsigned char **)&(extr->eroute->er_eaddr.sen_ip_dst); -+ portp = &(extr->eroute->er_eaddr.sen_dport); -+ break; -+ case SADB_X_EXT_ADDRESS_SRC_MASK: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found src mask address.\n"); -+ if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { -+ SENDERR(ENOMEM); -+ } -+ sap = (unsigned char **)&(extr->eroute->er_emask.sen_ip_src); -+ portp = &(extr->eroute->er_emask.sen_sport); -+ break; -+ case SADB_X_EXT_ADDRESS_DST_MASK: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found dst mask address.\n"); -+ if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { -+ SENDERR(ENOMEM); -+ } -+ sap = (unsigned char **)&(extr->eroute->er_emask.sen_ip_dst); -+ portp = &(extr->eroute->er_emask.sen_dport); -+ break; -+#ifdef NAT_TRAVERSAL -+ case SADB_X_EXT_NAT_T_OA: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found NAT-OA address.\n"); -+ sap = (unsigned char **)&(extr->ips->ips_natt_oa); -+ extr->ips->ips_natt_oa_size = saddr_len; -+ break; -+#endif -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "unrecognised ext_type=%d.\n", -+ pfkey_address->sadb_address_exttype); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_address->sadb_address_exttype) { -+ case SADB_EXT_ADDRESS_SRC: -+ case SADB_EXT_ADDRESS_DST: -+ case SADB_EXT_ADDRESS_PROXY: -+ case SADB_X_EXT_ADDRESS_DST2: -+#ifdef NAT_TRAVERSAL -+ case SADB_X_EXT_NAT_T_OA: -+#endif -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "allocating %d bytes for saddr.\n", -+ saddr_len); -+ if(!(*sap = kmalloc(saddr_len, GFP_KERNEL))) { -+ SENDERR(ENOMEM); -+ } -+ memcpy(*sap, s, saddr_len); -+ break; -+ default: -+ if(s->sa_family != AF_INET) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "s->sa_family=%d not supported.\n", -+ s->sa_family); -+ SENDERR(EPFNOSUPPORT); -+ } -+ (unsigned long)(*sap) = ((struct sockaddr_in*)s)->sin_addr.s_addr; -+ if (portp != 0) -+ *portp = ((struct sockaddr_in*)s)->sin_port; -+#ifdef CONFIG_IPSEC_DEBUG -+ if(extr->eroute) { -+ char buf1[64], buf2[64]; -+ if (debug_pfkey) { -+ subnettoa(extr->eroute->er_eaddr.sen_ip_src, -+ extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(extr->eroute->er_eaddr.sen_ip_dst, -+ extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_parse: " -+ "extr->eroute set to %s:%d->%s:%d\n", -+ buf1, -+ ntohs(extr->eroute->er_eaddr.sen_sport), -+ buf2, -+ ntohs(extr->eroute->er_eaddr.sen_dport)); -+ } -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ } -+ -+ ipsp = extr->ips; -+ switch(pfkey_address->sadb_address_exttype) { -+ case SADB_X_EXT_ADDRESS_DST2: -+ ipsp = extr->ips2; -+ case SADB_EXT_ADDRESS_DST: -+ if(s->sa_family == AF_INET) { -+ ipsp->ips_said.dst.u.v4.sin_addr.s_addr = ((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr.s_addr; -+ ipsp->ips_said.dst.u.v4.sin_family = AF_INET; -+ addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr, -+ 0, -+ ipaddr_txt, -+ sizeof(ipaddr_txt)); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "ips_said.dst set to %s.\n", -+ ipaddr_txt); -+ } else { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "uh, ips_said.dst doesn't do address family=%d yet, said will be invalid.\n", -+ s->sa_family); -+ } -+ default: -+ break; -+ } -+ -+ /* XXX check if port!=0 */ -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: successful.\n"); -+ errlab: -+ return error; -+} -+ -+int -+pfkey_key_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct sadb_key *pfkey_key = (struct sadb_key *)pfkey_ext; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_key_process: .\n"); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_key_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_key->sadb_key_exttype) { -+ case SADB_EXT_KEY_AUTH: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_key_process: " -+ "allocating %d bytes for authkey.\n", -+ DIVUP(pfkey_key->sadb_key_bits, 8)); -+ if(!(extr->ips->ips_key_a = kmalloc(DIVUP(pfkey_key->sadb_key_bits, 8), GFP_KERNEL))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_key_process: " -+ "memory allocation error.\n"); -+ SENDERR(ENOMEM); -+ } -+ extr->ips->ips_key_bits_a = pfkey_key->sadb_key_bits; -+ extr->ips->ips_key_a_size = DIVUP(pfkey_key->sadb_key_bits, 8); -+ memcpy(extr->ips->ips_key_a, -+ (char*)pfkey_key + sizeof(struct sadb_key), -+ extr->ips->ips_key_a_size); -+ break; -+ case SADB_EXT_KEY_ENCRYPT: /* Key(s) */ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_key_process: " -+ "allocating %d bytes for enckey.\n", -+ DIVUP(pfkey_key->sadb_key_bits, 8)); -+ if(!(extr->ips->ips_key_e = kmalloc(DIVUP(pfkey_key->sadb_key_bits, 8), GFP_KERNEL))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_key_process: " -+ "memory allocation error.\n"); -+ SENDERR(ENOMEM); -+ } -+ extr->ips->ips_key_bits_e = pfkey_key->sadb_key_bits; -+ extr->ips->ips_key_e_size = DIVUP(pfkey_key->sadb_key_bits, 8); -+ memcpy(extr->ips->ips_key_e, -+ (char*)pfkey_key + sizeof(struct sadb_key), -+ extr->ips->ips_key_e_size); -+ break; -+ default: -+ SENDERR(EINVAL); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_key_process: " -+ "success.\n"); -+errlab: -+ return error; -+} -+ -+int -+pfkey_ident_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct sadb_ident *pfkey_ident = (struct sadb_ident *)pfkey_ext; -+ int data_len; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ident_process: .\n"); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ident_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_ident->sadb_ident_exttype) { -+ case SADB_EXT_IDENTITY_SRC: -+ data_len = pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); -+ -+ extr->ips->ips_ident_s.type = pfkey_ident->sadb_ident_type; -+ extr->ips->ips_ident_s.id = pfkey_ident->sadb_ident_id; -+ extr->ips->ips_ident_s.len = pfkey_ident->sadb_ident_len; -+ if(data_len) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ident_process: " -+ "allocating %d bytes for ident_s.\n", -+ data_len); -+ if(!(extr->ips->ips_ident_s.data -+ = kmalloc(data_len, GFP_KERNEL))) { -+ SENDERR(ENOMEM); -+ } -+ memcpy(extr->ips->ips_ident_s.data, -+ (char*)pfkey_ident + sizeof(struct sadb_ident), -+ data_len); -+ } else { -+ extr->ips->ips_ident_s.data = NULL; -+ } -+ break; -+ case SADB_EXT_IDENTITY_DST: /* Identity(ies) */ -+ data_len = pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); -+ -+ extr->ips->ips_ident_d.type = pfkey_ident->sadb_ident_type; -+ extr->ips->ips_ident_d.id = pfkey_ident->sadb_ident_id; -+ extr->ips->ips_ident_d.len = pfkey_ident->sadb_ident_len; -+ if(data_len) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ident_process: " -+ "allocating %d bytes for ident_d.\n", -+ data_len); -+ if(!(extr->ips->ips_ident_d.data -+ = kmalloc(data_len, GFP_KERNEL))) { -+ SENDERR(ENOMEM); -+ } -+ memcpy(extr->ips->ips_ident_d.data, -+ (char*)pfkey_ident + sizeof(struct sadb_ident), -+ data_len); -+ } else { -+ extr->ips->ips_ident_d.data = NULL; -+ } -+ break; -+ default: -+ SENDERR(EINVAL); -+ } -+errlab: -+ return error; -+} -+ -+int -+pfkey_sens_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sens_process: " -+ "Sorry, I can't process exttype=%d yet.\n", -+ pfkey_ext->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ errlab: -+ return error; -+} -+ -+int -+pfkey_prop_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_prop_process: " -+ "Sorry, I can't process exttype=%d yet.\n", -+ pfkey_ext->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ -+ errlab: -+ return error; -+} -+ -+int -+pfkey_supported_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_supported_process: " -+ "Sorry, I can't process exttype=%d yet.\n", -+ pfkey_ext->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_spirange_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_spirange_process: .\n"); -+/* errlab: */ -+ return error; -+} -+ -+int -+pfkey_x_kmprivate_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_kmprivate_process: " -+ "Sorry, I can't process exttype=%d yet.\n", -+ pfkey_ext->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_x_satype_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_satype_process: .\n"); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_satype_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(extr->ips2 == NULL) { -+ extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */ -+ } -+ if(extr->ips2 == NULL) { -+ SENDERR(-error); -+ } -+ if(!(extr->ips2->ips_said.proto = satype2proto(pfkey_x_satype->sadb_x_satype_satype))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_satype_process: " -+ "proto lookup from satype=%d failed.\n", -+ pfkey_x_satype->sadb_x_satype_satype); -+ SENDERR(EINVAL); -+ } -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_satype_process: " -+ "protocol==%d decoded from satype==%d(%s).\n", -+ extr->ips2->ips_said.proto, -+ pfkey_x_satype->sadb_x_satype_satype, -+ satype2name(pfkey_x_satype->sadb_x_satype_satype)); -+ -+errlab: -+ return error; -+} -+ -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+int -+pfkey_x_nat_t_type_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)pfkey_ext; -+ -+ if(!pfkey_x_nat_t_type) { -+ printk("klips_debug:pfkey_x_nat_t_type_process: " -+ "null pointer passed in\n"); -+ SENDERR(EINVAL); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_nat_t_type_process: %d.\n", -+ pfkey_x_nat_t_type->sadb_x_nat_t_type_type); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_nat_t_type_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_x_nat_t_type->sadb_x_nat_t_type_type) { -+ case ESPINUDP_WITH_NON_IKE: /* with Non-IKE (older version) */ -+ case ESPINUDP_WITH_NON_ESP: /* with Non-ESP */ -+ -+ extr->ips->ips_natt_type = pfkey_x_nat_t_type->sadb_x_nat_t_type_type; -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_nat_t_type_process: " -+ "unknown type %d.\n", -+ pfkey_x_nat_t_type->sadb_x_nat_t_type_type); -+ SENDERR(EINVAL); -+ break; -+ } -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_x_nat_t_port_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)pfkey_ext; -+ -+ if(!pfkey_x_nat_t_port) { -+ printk("klips_debug:pfkey_x_nat_t_port_process: " -+ "null pointer passed in\n"); -+ SENDERR(EINVAL); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_nat_t_port_process: %d/%d.\n", -+ pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype, -+ pfkey_x_nat_t_port->sadb_x_nat_t_port_port); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_nat_t_type_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype) { -+ case SADB_X_EXT_NAT_T_SPORT: -+ extr->ips->ips_natt_sport = pfkey_x_nat_t_port->sadb_x_nat_t_port_port; -+ break; -+ case SADB_X_EXT_NAT_T_DPORT: -+ extr->ips->ips_natt_dport = pfkey_x_nat_t_port->sadb_x_nat_t_port_port; -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_nat_t_port_process: " -+ "unknown exttype %d.\n", -+ pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype); -+ SENDERR(EINVAL); -+ break; -+ } -+ -+errlab: -+ return error; -+} -+#endif -+ -+int -+pfkey_x_debug_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)pfkey_ext; -+ -+ if(!pfkey_x_debug) { -+ printk("klips_debug:pfkey_x_debug_process: " -+ "null pointer passed in\n"); -+ SENDERR(EINVAL); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_debug_process: .\n"); -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if(pfkey_x_debug->sadb_x_debug_netlink >> -+ (sizeof(pfkey_x_debug->sadb_x_debug_netlink) * 8 - 1)) { -+ pfkey_x_debug->sadb_x_debug_netlink &= -+ ~(1 << (sizeof(pfkey_x_debug->sadb_x_debug_netlink) * 8 -1)); -+ debug_tunnel |= pfkey_x_debug->sadb_x_debug_tunnel; -+ debug_netlink |= pfkey_x_debug->sadb_x_debug_netlink; -+ debug_xform |= pfkey_x_debug->sadb_x_debug_xform; -+ debug_eroute |= pfkey_x_debug->sadb_x_debug_eroute; -+ debug_spi |= pfkey_x_debug->sadb_x_debug_spi; -+ debug_radij |= pfkey_x_debug->sadb_x_debug_radij; -+ debug_esp |= pfkey_x_debug->sadb_x_debug_esp; -+ debug_ah |= pfkey_x_debug->sadb_x_debug_ah; -+ debug_rcv |= pfkey_x_debug->sadb_x_debug_rcv; -+ debug_pfkey |= pfkey_x_debug->sadb_x_debug_pfkey; -+#ifdef CONFIG_IPSEC_IPCOMP -+ sysctl_ipsec_debug_ipcomp |= pfkey_x_debug->sadb_x_debug_ipcomp; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ sysctl_ipsec_debug_verbose |= pfkey_x_debug->sadb_x_debug_verbose; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_debug_process: " -+ "set\n"); -+ } else { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_debug_process: " -+ "unset\n"); -+ debug_tunnel &= pfkey_x_debug->sadb_x_debug_tunnel; -+ debug_netlink &= pfkey_x_debug->sadb_x_debug_netlink; -+ debug_xform &= pfkey_x_debug->sadb_x_debug_xform; -+ debug_eroute &= pfkey_x_debug->sadb_x_debug_eroute; -+ debug_spi &= pfkey_x_debug->sadb_x_debug_spi; -+ debug_radij &= pfkey_x_debug->sadb_x_debug_radij; -+ debug_esp &= pfkey_x_debug->sadb_x_debug_esp; -+ debug_ah &= pfkey_x_debug->sadb_x_debug_ah; -+ debug_rcv &= pfkey_x_debug->sadb_x_debug_rcv; -+ debug_pfkey &= pfkey_x_debug->sadb_x_debug_pfkey; -+#ifdef CONFIG_IPSEC_IPCOMP -+ sysctl_ipsec_debug_ipcomp &= pfkey_x_debug->sadb_x_debug_ipcomp; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ sysctl_ipsec_debug_verbose &= pfkey_x_debug->sadb_x_debug_verbose; -+ } -+#else /* CONFIG_IPSEC_DEBUG */ -+ printk("klips_debug:pfkey_x_debug_process: " -+ "debugging not enabled\n"); -+ SENDERR(EINVAL); -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+errlab: -+ return error; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.15 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.14 2004/02/03 03:13:59 mcr -+ * no longer #ifdef out NON_ESP mode. That was a mistake. -+ * -+ * Revision 1.13 2003/12/15 18:13:12 mcr -+ * when compiling with NAT traversal, don't assume that the -+ * kernel has been patched, unless CONFIG_IPSEC_NAT_NON_ESP -+ * is set. -+ * -+ * Revision 1.12.2.1 2003/12/22 15:25:52 jjo -+ * Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.12 2003/12/10 01:14:27 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.11 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.10.4.2 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.10.4.1 2003/09/21 13:59:56 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.10 2003/02/06 01:51:41 rgb -+ * Removed no longer relevant comment -+ * -+ * Revision 1.9 2003/01/30 02:32:44 rgb -+ * -+ * Transmit error code through to caller from callee for better diagnosis of problems. -+ * -+ * Revision 1.8 2002/12/13 22:42:22 mcr -+ * restored sa_ref code -+ * -+ * Revision 1.7 2002/12/13 22:40:48 mcr -+ * temporarily removed sadb_x_sa_ref reference for 2.xx -+ * -+ * Revision 1.6 2002/10/05 05:02:58 dhr -+ * -+ * C labels go on statements -+ * -+ * Revision 1.5 2002/09/20 15:41:08 rgb -+ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc(). -+ * Added sadb_x_sa_ref to struct sadb_sa. -+ * -+ * Revision 1.4 2002/09/20 05:02:02 rgb -+ * Added memory allocation debugging. -+ * -+ * Revision 1.3 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.2 2002/05/27 18:55:03 rgb -+ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT. -+ * -+ * Revision 1.1 2002/05/14 02:33:51 rgb -+ * Moved all the extension processing functions to pfkey_v2_ext_process.c. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/pfkey_v2_parser.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,4018 @@ -+/* -+ * @(#) RFC2367 PF_KEYv2 Key management API message parser -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* -+ * Template from klips/net/ipsec/ipsec/ipsec_netlink.c. -+ */ -+ -+char pfkey_v2_parser_c_version[] = "$Id$"; -+ -+#include -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+ -+#include -+ -+#include -+ -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define ip_chk_addr inet_addr_type -+# define IS_MYADDR RTN_LOCAL -+#endif -+#include -+#include -+#ifdef NETLINK_SOCK -+# include -+#else -+# include -+#endif -+ -+#include /* get_random_bytes() */ -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipcomp.h" -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+#include "openswan/ipsec_alg.h" -+ -+ -+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) -+ -+struct sklist_t { -+ struct socket *sk; -+ struct sklist_t* next; -+} pfkey_sklist_head, *pfkey_sklist, *pfkey_sklist_prev; -+ -+__u32 pfkey_msg_seq = 0; -+ -+ -+#if 0 -+#define DUMP_SAID dump_said(&extr->ips->ips_said, __LINE__) -+#define DUMP_SAID2 dump_said(&extr.ips->ips_said, __LINE__) -+static void dump_said(ip_said *s, int line) -+{ -+ char msa[SATOT_BUF]; -+ size_t msa_len; -+ -+ msa_len = satot(s, 0, msa, sizeof(msa)); -+ -+ printk("line: %d msa: %s\n", line, msa); -+} -+#endif -+ -+ -+int -+pfkey_alloc_eroute(struct eroute** eroute) -+{ -+ int error = 0; -+ if(*eroute) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_alloc_eroute: " -+ "eroute struct already allocated\n"); -+ SENDERR(EEXIST); -+ } -+ -+ if((*eroute = kmalloc(sizeof(**eroute), GFP_ATOMIC) ) == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_alloc_eroute: " -+ "memory allocation error\n"); -+ SENDERR(ENOMEM); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_alloc_eroute: " -+ "allocating %lu bytes for an eroute at 0p%p\n", -+ (unsigned long) sizeof(**eroute), *eroute); -+ -+ memset((caddr_t)*eroute, 0, sizeof(**eroute)); -+ (*eroute)->er_eaddr.sen_len = -+ (*eroute)->er_emask.sen_len = sizeof(struct sockaddr_encap); -+ (*eroute)->er_eaddr.sen_family = -+ (*eroute)->er_emask.sen_family = AF_ENCAP; -+ (*eroute)->er_eaddr.sen_type = SENT_IP4; -+ (*eroute)->er_emask.sen_type = 255; -+ (*eroute)->er_pid = 0; -+ (*eroute)->er_count = 0; -+ (*eroute)->er_lasttime = jiffies/HZ; -+ -+ errlab: -+ return(error); -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_protocol_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data *extr) -+{ -+ int error = 0; -+ struct sadb_protocol * p = (struct sadb_protocol *)pfkey_ext; -+ -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process: %p\n", extr); -+ -+ if (extr == 0) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_protocol_process:" -+ "extr is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ if (extr->eroute == 0) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_protocol_process:" -+ "extr->eroute is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ extr->eroute->er_eaddr.sen_proto = p->sadb_protocol_proto; -+ extr->eroute->er_emask.sen_proto = p->sadb_protocol_proto ? ~0:0; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_protocol_process: protocol = %d.\n", -+ p->sadb_protocol_proto); -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_ipsec_sa_init(struct ipsec_sa *ipsp, struct sadb_ext **extensions) -+{ -+ int i; -+ int error = 0; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ char ipaddr_txt[ADDRTOA_BUF]; -+ char ipaddr2_txt[ADDRTOA_BUF]; -+#if defined (CONFIG_IPSEC_AUTH_HMAC_MD5) || defined (CONFIG_IPSEC_AUTH_HMAC_SHA1) -+ unsigned char kb[AHMD596_BLKLEN]; -+#endif -+#ifdef CONFIG_IPSEC_ALG -+ struct ipsec_alg_enc *ixt_e = NULL; -+ struct ipsec_alg_auth *ixt_a = NULL; -+#endif /* CONFIG_IPSEC_ALG */ -+ -+ if(ipsp == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "ipsp is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ sa_len = satot(&ipsp->ips_said, 0, sa, sizeof(sa)); -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "(pfkey defined) called for SA:%s\n", -+ sa_len ? sa : " (error)"); -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "calling init routine of %s%s%s\n", -+ IPS_XFORM_NAME(ipsp)); -+ -+ switch(ipsp->ips_said.proto) { -+ -+#ifdef CONFIG_IPSEC_IPIP -+ case IPPROTO_IPIP: { -+ addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_s))->sin_addr, -+ 0, -+ ipaddr_txt, sizeof(ipaddr_txt)); -+ addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr, -+ 0, -+ ipaddr2_txt, sizeof(ipaddr_txt)); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "(pfkey defined) IPIP ipsec_sa set for %s->%s.\n", -+ ipaddr_txt, -+ ipaddr2_txt); -+ } -+ break; -+#endif /* !CONFIG_IPSEC_IPIP */ -+#ifdef CONFIG_IPSEC_AH -+ case IPPROTO_AH: -+ switch(ipsp->ips_authalg) { -+# ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: { -+ unsigned char *akp; -+ unsigned int aks; -+ MD5_CTX *ictx; -+ MD5_CTX *octx; -+ -+ if(ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, -+ ipsp->ips_key_bits_a, AHMD596_KLEN * 8); -+ SENDERR(EINVAL); -+ } -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "hmac md5-96 key is 0x%08x %08x %08x %08x\n", -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ -+ ipsp->ips_auth_bits = AHMD596_ALEN * 8; -+ -+ /* save the pointer to the key material */ -+ akp = ipsp->ips_key_a; -+ aks = ipsp->ips_key_a_size; -+ -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "allocating %lu bytes for md5_ctx.\n", -+ (unsigned long) sizeof(struct md5_ctx)); -+ if((ipsp->ips_key_a = (caddr_t) -+ kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { -+ ipsp->ips_key_a = akp; -+ SENDERR(ENOMEM); -+ } -+ ipsp->ips_key_a_size = sizeof(struct md5_ctx); -+ -+ for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { -+ kb[i] = akp[i] ^ HMAC_IPAD; -+ } -+ for (; i < AHMD596_BLKLEN; i++) { -+ kb[i] = HMAC_IPAD; -+ } -+ -+ ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx); -+ MD5Init(ictx); -+ MD5Update(ictx, kb, AHMD596_BLKLEN); -+ -+ for (i = 0; i < AHMD596_BLKLEN; i++) { -+ kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); -+ } -+ -+ octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx); -+ MD5Init(octx); -+ MD5Update(octx, kb, AHMD596_BLKLEN); -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", -+ ((__u32*)ictx)[0], -+ ((__u32*)ictx)[1], -+ ((__u32*)ictx)[2], -+ ((__u32*)ictx)[3], -+ ((__u32*)octx)[0], -+ ((__u32*)octx)[1], -+ ((__u32*)octx)[2], -+ ((__u32*)octx)[3] ); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ -+ /* zero key buffer -- paranoid */ -+ memset(akp, 0, aks); -+ kfree(akp); -+ } -+ break; -+# endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+# ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: { -+ unsigned char *akp; -+ unsigned int aks; -+ SHA1_CTX *ictx; -+ SHA1_CTX *octx; -+ -+ if(ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, -+ ipsp->ips_key_bits_a, AHSHA196_KLEN * 8); -+ SENDERR(EINVAL); -+ } -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ -+ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; -+ -+ /* save the pointer to the key material */ -+ akp = ipsp->ips_key_a; -+ aks = ipsp->ips_key_a_size; -+ -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "allocating %lu bytes for sha1_ctx.\n", -+ (unsigned long) sizeof(struct sha1_ctx)); -+ if((ipsp->ips_key_a = (caddr_t) -+ kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { -+ ipsp->ips_key_a = akp; -+ SENDERR(ENOMEM); -+ } -+ ipsp->ips_key_a_size = sizeof(struct sha1_ctx); -+ -+ for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { -+ kb[i] = akp[i] ^ HMAC_IPAD; -+ } -+ for (; i < AHMD596_BLKLEN; i++) { -+ kb[i] = HMAC_IPAD; -+ } -+ -+ ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx); -+ SHA1Init(ictx); -+ SHA1Update(ictx, kb, AHSHA196_BLKLEN); -+ -+ for (i = 0; i < AHSHA196_BLKLEN; i++) { -+ kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); -+ } -+ -+ octx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->octx); -+ SHA1Init(octx); -+ SHA1Update(octx, kb, AHSHA196_BLKLEN); -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", -+ ((__u32*)ictx)[0], -+ ((__u32*)ictx)[1], -+ ((__u32*)ictx)[2], -+ ((__u32*)ictx)[3], -+ ((__u32*)octx)[0], -+ ((__u32*)octx)[1], -+ ((__u32*)octx)[2], -+ ((__u32*)octx)[3] ); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ /* zero key buffer -- paranoid */ -+ memset(akp, 0, aks); -+ kfree(akp); -+ } -+ break; -+# endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "authalg=%d support not available in the kernel", -+ ipsp->ips_authalg); -+ SENDERR(EINVAL); -+ } -+ break; -+#endif /* CONFIG_IPSEC_AH */ -+#ifdef CONFIG_IPSEC_ESP -+ case IPPROTO_ESP: { -+#if defined (CONFIG_IPSEC_AUTH_HMAC_MD5) || defined (CONFIG_IPSEC_AUTH_HMAC_SHA1) -+ unsigned char *akp; -+ unsigned int aks; -+#endif -+#if defined (CONFIG_IPSEC_ENC_3DES) -+ unsigned char *ekp; -+ unsigned int eks; -+#endif -+ -+ ipsp->ips_iv_size = 0; -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_e=ipsp->ips_alg_enc)) { -+ ipsp->ips_iv_size = ixt_e->ixt_ivlen/8; -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ipsp->ips_encalg) { -+# ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+# endif /* CONFIG_IPSEC_ENC_3DES */ -+# if defined(CONFIG_IPSEC_ENC_3DES) -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "allocating %u bytes for iv.\n", -+ EMT_ESPDES_IV_SZ); -+ if((ipsp->ips_iv = (caddr_t) -+ kmalloc((ipsp->ips_iv_size = EMT_ESPDES_IV_SZ), GFP_ATOMIC)) == NULL) { -+ SENDERR(ENOMEM); -+ } -+ prng_bytes(&ipsec_prng, (char *)ipsp->ips_iv, EMT_ESPDES_IV_SZ); -+ ipsp->ips_iv_bits = ipsp->ips_iv_size * 8; -+ ipsp->ips_iv_size = EMT_ESPDES_IV_SZ; -+ break; -+# endif /* defined(CONFIG_IPSEC_ENC_3DES) */ -+ case ESP_NONE: -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "encalg=%d support not available in the kernel", -+ ipsp->ips_encalg); -+ SENDERR(EINVAL); -+ } -+ -+ /* Create IV */ -+ if (ipsp->ips_iv_size) { -+ if((ipsp->ips_iv = (caddr_t) -+ kmalloc(ipsp->ips_iv_size, GFP_ATOMIC)) == NULL) { -+ SENDERR(ENOMEM); -+ } -+ prng_bytes(&ipsec_prng, (char *)ipsp->ips_iv, ipsp->ips_iv_size); -+ ipsp->ips_iv_bits = ipsp->ips_iv_size * 8; -+ } -+ -+#ifdef CONFIG_IPSEC_ALG -+ if (ixt_e) { -+ if ((error=ipsec_alg_enc_key_create(ipsp)) < 0) -+ SENDERR(-error); -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ipsp->ips_encalg) { -+# ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+ if(ipsp->ips_key_bits_e != (EMT_ESP3DES_KEY_SZ * 8)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "incorrect encryption key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, -+ ipsp->ips_key_bits_e, EMT_ESP3DES_KEY_SZ * 8); -+ SENDERR(EINVAL); -+ } -+ -+ /* save encryption key pointer */ -+ ekp = ipsp->ips_key_e; -+ eks = ipsp->ips_key_e_size; -+ -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "allocating %lu bytes for 3des.\n", -+ (unsigned long) (3 * sizeof(struct des_eks))); -+ if((ipsp->ips_key_e = (caddr_t) -+ kmalloc(3 * sizeof(struct des_eks), GFP_ATOMIC)) == NULL) { -+ ipsp->ips_key_e = ekp; -+ SENDERR(ENOMEM); -+ } -+ ipsp->ips_key_e_size = 3 * sizeof(struct des_eks); -+ -+ for(i = 0; i < 3; i++) { -+#if KLIPS_DIVULGE_CYPHER_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "3des key %d/3 is 0x%08x%08x\n", -+ i + 1, -+ ntohl(*((__u32 *)ekp + i * 2)), -+ ntohl(*((__u32 *)ekp + i * 2 + 1))); -+# endif -+#if KLIPS_FIXES_DES_PARITY -+ /* force parity */ -+ des_set_odd_parity((des_cblock *)(ekp + EMT_ESPDES_KEY_SZ * i)); -+#endif -+ error = des_set_key((des_cblock *)(ekp + EMT_ESPDES_KEY_SZ * i), -+ ((struct des_eks *)(ipsp->ips_key_e))[i].ks); -+ if (error == -1) -+ printk("klips_debug:pfkey_ipsec_sa_init: " -+ "parity error in des key %d/3\n", -+ i + 1); -+ else if (error == -2) -+ printk("klips_debug:pfkey_ipsec_sa_init: " -+ "illegal weak des key %d/3\n", i + 1); -+ if (error) { -+ memset(ekp, 0, eks); -+ kfree(ekp); -+ SENDERR(EINVAL); -+ } -+ } -+ -+ /* paranoid */ -+ memset(ekp, 0, eks); -+ kfree(ekp); -+ break; -+# endif /* CONFIG_IPSEC_ENC_3DES */ -+ case ESP_NONE: -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "encalg=%d support not available in the kernel", -+ ipsp->ips_encalg); -+ SENDERR(EINVAL); -+ } -+ -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_a=ipsp->ips_alg_auth)) { -+ if ((error=ipsec_alg_auth_key_create(ipsp)) < 0) -+ SENDERR(-error); -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ -+ switch(ipsp->ips_authalg) { -+# ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: { -+ MD5_CTX *ictx; -+ MD5_CTX *octx; -+ -+ if(ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, -+ ipsp->ips_key_bits_a, -+ AHMD596_KLEN * 8); -+ SENDERR(EINVAL); -+ } -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "hmac md5-96 key is 0x%08x %08x %08x %08x\n", -+ ntohl(*(((__u32 *)(ipsp->ips_key_a))+0)), -+ ntohl(*(((__u32 *)(ipsp->ips_key_a))+1)), -+ ntohl(*(((__u32 *)(ipsp->ips_key_a))+2)), -+ ntohl(*(((__u32 *)(ipsp->ips_key_a))+3))); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ ipsp->ips_auth_bits = AHMD596_ALEN * 8; -+ -+ /* save the pointer to the key material */ -+ akp = ipsp->ips_key_a; -+ aks = ipsp->ips_key_a_size; -+ -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "allocating %lu bytes for md5_ctx.\n", -+ (unsigned long) sizeof(struct md5_ctx)); -+ if((ipsp->ips_key_a = (caddr_t) -+ kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { -+ ipsp->ips_key_a = akp; -+ SENDERR(ENOMEM); -+ } -+ ipsp->ips_key_a_size = sizeof(struct md5_ctx); -+ -+ for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { -+ kb[i] = akp[i] ^ HMAC_IPAD; -+ } -+ for (; i < AHMD596_BLKLEN; i++) { -+ kb[i] = HMAC_IPAD; -+ } -+ -+ ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx); -+ MD5Init(ictx); -+ MD5Update(ictx, kb, AHMD596_BLKLEN); -+ -+ for (i = 0; i < AHMD596_BLKLEN; i++) { -+ kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); -+ } -+ -+ octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx); -+ MD5Init(octx); -+ MD5Update(octx, kb, AHMD596_BLKLEN); -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", -+ ((__u32*)ictx)[0], -+ ((__u32*)ictx)[1], -+ ((__u32*)ictx)[2], -+ ((__u32*)ictx)[3], -+ ((__u32*)octx)[0], -+ ((__u32*)octx)[1], -+ ((__u32*)octx)[2], -+ ((__u32*)octx)[3] ); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ /* paranoid */ -+ memset(akp, 0, aks); -+ kfree(akp); -+ break; -+ } -+# endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+# ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: { -+ SHA1_CTX *ictx; -+ SHA1_CTX *octx; -+ -+ if(ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, -+ ipsp->ips_key_bits_a, -+ AHSHA196_KLEN * 8); -+ SENDERR(EINVAL); -+ } -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; -+ -+ /* save the pointer to the key material */ -+ akp = ipsp->ips_key_a; -+ aks = ipsp->ips_key_a_size; -+ -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "allocating %lu bytes for sha1_ctx.\n", -+ (unsigned long) sizeof(struct sha1_ctx)); -+ if((ipsp->ips_key_a = (caddr_t) -+ kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { -+ ipsp->ips_key_a = akp; -+ SENDERR(ENOMEM); -+ } -+ ipsp->ips_key_a_size = sizeof(struct sha1_ctx); -+ -+ for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { -+ kb[i] = akp[i] ^ HMAC_IPAD; -+ } -+ for (; i < AHMD596_BLKLEN; i++) { -+ kb[i] = HMAC_IPAD; -+ } -+ -+ ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx); -+ SHA1Init(ictx); -+ SHA1Update(ictx, kb, AHSHA196_BLKLEN); -+ -+ for (i = 0; i < AHSHA196_BLKLEN; i++) { -+ kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); -+ } -+ -+ octx = &((struct sha1_ctx*)(ipsp->ips_key_a))->octx; -+ SHA1Init(octx); -+ SHA1Update(octx, kb, AHSHA196_BLKLEN); -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", -+ ((__u32*)ictx)[0], -+ ((__u32*)ictx)[1], -+ ((__u32*)ictx)[2], -+ ((__u32*)ictx)[3], -+ ((__u32*)octx)[0], -+ ((__u32*)octx)[1], -+ ((__u32*)octx)[2], -+ ((__u32*)octx)[3] ); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ memset(akp, 0, aks); -+ kfree(akp); -+ break; -+ } -+# endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ case AH_NONE: -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "authalg=%d support not available in the kernel.\n", -+ ipsp->ips_authalg); -+ SENDERR(EINVAL); -+ } -+ } -+ break; -+#endif /* !CONFIG_IPSEC_ESP */ -+#ifdef CONFIG_IPSEC_IPCOMP -+ case IPPROTO_COMP: -+ ipsp->ips_comp_adapt_tries = 0; -+ ipsp->ips_comp_adapt_skip = 0; -+ ipsp->ips_comp_ratio_cbytes = 0; -+ ipsp->ips_comp_ratio_dbytes = 0; -+ break; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "proto=%d unknown.\n", -+ ipsp->ips_said.proto); -+ SENDERR(EINVAL); -+ } -+ -+ errlab: -+ return(error); -+} -+ -+ -+int -+pfkey_safe_build(int error, struct sadb_ext *extensions[SADB_MAX+1]) -+{ -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build: " -+ "error=%d\n", -+ error); -+ if (!error) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:" -+ "success.\n"); -+ return 1; -+ } else { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:" -+ "caught error %d\n", -+ error); -+ pfkey_extensions_free(extensions); -+ return 0; -+ } -+} -+ -+ -+DEBUG_NO_STATIC int -+pfkey_getspi_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ ipsec_spi_t minspi = htonl(256), maxspi = htonl(-1L); -+ int found_avail = 0; -+ struct ipsec_sa *ipsq; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getspi_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ if(extr == NULL || extr->ips == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getspi_parse: " -+ "error, extr or extr->ipsec_sa pointer NULL\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(extensions[SADB_EXT_SPIRANGE]) { -+ minspi = ((struct sadb_spirange *)extensions[SADB_EXT_SPIRANGE])->sadb_spirange_min; -+ maxspi = ((struct sadb_spirange *)extensions[SADB_EXT_SPIRANGE])->sadb_spirange_max; -+ } -+ -+ if(maxspi == minspi) { -+ extr->ips->ips_said.spi = maxspi; -+ ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if(ipsq != NULL) { -+ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); -+ ipsec_sa_put(ipsq); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getspi_parse: " -+ "EMT_GETSPI found an old ipsec_sa for SA: %s, delete it first.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(EEXIST); -+ } else { -+ found_avail = 1; -+ } -+ } else { -+ int i = 0; -+ __u32 rand_val; -+ __u32 spi_diff; -+ while( ( i < (spi_diff = (ntohl(maxspi) - ntohl(minspi)))) && !found_avail ) { -+ prng_bytes(&ipsec_prng, (char *) &(rand_val), -+ ( (spi_diff < (2^8)) ? 1 : -+ ( (spi_diff < (2^16)) ? 2 : -+ ( (spi_diff < (2^24)) ? 3 : -+ 4 ) ) ) ); -+ extr->ips->ips_said.spi = htonl(ntohl(minspi) + -+ (rand_val % -+ (spi_diff + 1))); -+ i++; -+ ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if(ipsq == NULL) { -+ found_avail = 1; -+ } else { -+ ipsec_sa_put(ipsq); -+ } -+ } -+ } -+ -+ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); -+ -+ if (!found_avail) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getspi_parse: " -+ "found an old ipsec_sa for SA: %s, delete it first.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(EEXIST); -+ } -+ -+ if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == IS_MYADDR) { -+ extr->ips->ips_flags |= EMT_INBOUND; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getspi_parse: " -+ "existing ipsec_sa not found (this is good) for SA: %s, %s-bound, allocating.\n", -+ sa_len ? sa : " (error)", -+ extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); -+ -+ /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ -+ extr->ips->ips_rcvif = NULL; -+ extr->ips->ips_life.ipl_addtime.ipl_count = jiffies/HZ; -+ -+ extr->ips->ips_state = SADB_SASTATE_LARVAL; -+ -+ if(!extr->ips->ips_life.ipl_allocations.ipl_count) { -+ extr->ips->ips_life.ipl_allocations.ipl_count += 1; -+ } -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_GETSPI, -+ satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ 0, -+ SADB_SASTATE_LARVAL, -+ 0, -+ 0, -+ 0, -+ extr->ips->ips_ref), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_s), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_d), -+ extensions_reply) )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " -+ "failed to build the getspi reply message extensions\n"); -+ goto errlab; -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " -+ "failed to build the getspi reply message\n"); -+ SENDERR(-error); -+ } -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " -+ "sending up getspi reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " -+ "sending up getspi reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ if((error = ipsec_sa_add(extr->ips))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " -+ "failed to add the larval SA=%s with error=%d.\n", -+ sa_len ? sa : " (error)", -+ error); -+ SENDERR(-error); -+ } -+ extr->ips = NULL; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getspi_parse: " -+ "successful for SA: %s\n", -+ sa_len ? sa : " (error)"); -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_update_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct ipsec_sa* ipsq; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ struct ipsec_sa *nat_t_ips_saved = NULL; -+#endif -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: " -+ "error, sa_state=%d must be MATURE=%d\n", -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state, -+ SADB_SASTATE_MATURE); -+ SENDERR(EINVAL); -+ } -+ -+ if(extr == NULL || extr->ips == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: " -+ "error, extr or extr->ips pointer NULL\n"); -+ SENDERR(EINVAL); -+ } -+ -+ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); -+ -+ spin_lock_bh(&tdb_lock); -+ -+ ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if (ipsq == NULL) { -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: " -+ "reserved ipsec_sa for SA: %s not found. Call SADB_GETSPI first or call SADB_ADD instead.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(ENOENT); -+ } -+ -+ if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == IS_MYADDR) { -+ extr->ips->ips_flags |= EMT_INBOUND; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: " -+ "existing ipsec_sa found (this is good) for SA: %s, %s-bound, updating.\n", -+ sa_len ? sa : " (error)", -+ extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if (extr->ips->ips_natt_sport || extr->ips->ips_natt_dport) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: only updating NAT-T ports " -+ "(%u:%u -> %u:%u)\n", -+ ipsq->ips_natt_sport, ipsq->ips_natt_dport, -+ extr->ips->ips_natt_sport, extr->ips->ips_natt_dport); -+ -+ if (extr->ips->ips_natt_sport) { -+ ipsq->ips_natt_sport = extr->ips->ips_natt_sport; -+ if (ipsq->ips_addr_s->sa_family == AF_INET) { -+ ((struct sockaddr_in *)(ipsq->ips_addr_s))->sin_port = htons(extr->ips->ips_natt_sport); -+ } -+ } -+ -+ if (extr->ips->ips_natt_dport) { -+ ipsq->ips_natt_dport = extr->ips->ips_natt_dport; -+ if (ipsq->ips_addr_d->sa_family == AF_INET) { -+ ((struct sockaddr_in *)(ipsq->ips_addr_d))->sin_port = htons(extr->ips->ips_natt_dport); -+ } -+ } -+ -+ nat_t_ips_saved = extr->ips; -+ extr->ips = ipsq; -+ } -+ else { -+#endif -+ -+ /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ -+ extr->ips->ips_rcvif = NULL; -+ if ((error = pfkey_ipsec_sa_init(extr->ips, extensions))) { -+ ipsec_sa_put(ipsq); -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: " -+ "not successful for SA: %s, deleting.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(-error); -+ } -+ -+ extr->ips->ips_life.ipl_addtime.ipl_count = ipsq->ips_life.ipl_addtime.ipl_count; -+ ipsec_sa_put(ipsq); -+ if((error = ipsec_sa_delchain(ipsq))) { -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: " -+ "error=%d, trouble deleting intermediate ipsec_sa for SA=%s.\n", -+ error, -+ sa_len ? sa : " (error)"); -+ SENDERR(-error); -+ } -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ } -+#endif -+ -+ spin_unlock_bh(&tdb_lock); -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_UPDATE, -+ satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ extr->ips->ips_replaywin, -+ extr->ips->ips_state, -+ extr->ips->ips_authalg, -+ extr->ips->ips_encalg, -+ extr->ips->ips_flags, -+ extr->ips->ips_ref), -+ extensions_reply) -+ /* The 3 lifetime extentions should only be sent if non-zero. */ -+ && (extensions[SADB_EXT_LIFETIME_HARD] -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD], -+ SADB_EXT_LIFETIME_HARD, -+ extr->ips->ips_life.ipl_allocations.ipl_hard, -+ extr->ips->ips_life.ipl_bytes.ipl_hard, -+ extr->ips->ips_life.ipl_addtime.ipl_hard, -+ extr->ips->ips_life.ipl_usetime.ipl_hard, -+ extr->ips->ips_life.ipl_packets.ipl_hard), -+ extensions_reply) : 1) -+ && (extensions[SADB_EXT_LIFETIME_SOFT] -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT], -+ SADB_EXT_LIFETIME_SOFT, -+ extr->ips->ips_life.ipl_allocations.ipl_count, -+ extr->ips->ips_life.ipl_bytes.ipl_count, -+ extr->ips->ips_life.ipl_addtime.ipl_count, -+ extr->ips->ips_life.ipl_usetime.ipl_count, -+ extr->ips->ips_life.ipl_packets.ipl_count), -+ extensions_reply) : 1) -+ && (extr->ips->ips_life.ipl_allocations.ipl_count -+ || extr->ips->ips_life.ipl_bytes.ipl_count -+ || extr->ips->ips_life.ipl_addtime.ipl_count -+ || extr->ips->ips_life.ipl_usetime.ipl_count -+ || extr->ips->ips_life.ipl_packets.ipl_count -+ -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_CURRENT], -+ SADB_EXT_LIFETIME_CURRENT, -+ extr->ips->ips_life.ipl_allocations.ipl_count, -+ extr->ips->ips_life.ipl_bytes.ipl_count, -+ extr->ips->ips_life.ipl_addtime.ipl_count, -+ extr->ips->ips_life.ipl_usetime.ipl_count, -+ extr->ips->ips_life.ipl_packets.ipl_count), -+ extensions_reply) : 1) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_s), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_d), -+ extensions_reply) -+ && (extr->ips->ips_ident_s.data -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC], -+ SADB_EXT_IDENTITY_SRC, -+ extr->ips->ips_ident_s.type, -+ extr->ips->ips_ident_s.id, -+ extr->ips->ips_ident_s.len, -+ extr->ips->ips_ident_s.data), -+ extensions_reply) : 1) -+ && (extr->ips->ips_ident_d.data -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST], -+ SADB_EXT_IDENTITY_DST, -+ extr->ips->ips_ident_d.type, -+ extr->ips->ips_ident_d.id, -+ extr->ips->ips_ident_d.len, -+ extr->ips->ips_ident_d.data), -+ extensions_reply) : 1) -+#if 0 -+ /* FIXME: This won't work yet because I have not finished -+ it. */ -+ && (extr->ips->ips_sens_ -+ ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY], -+ extr->ips->ips_sens_dpd, -+ extr->ips->ips_sens_sens_level, -+ extr->ips->ips_sens_sens_len, -+ extr->ips->ips_sens_sens_bitmap, -+ extr->ips->ips_sens_integ_level, -+ extr->ips->ips_sens_integ_len, -+ extr->ips->ips_sens_integ_bitmap), -+ extensions_reply) : 1) -+#endif -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " -+ "failed to build the update reply message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " -+ "failed to build the update reply message\n"); -+ SENDERR(-error); -+ } -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " -+ "sending up update reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " -+ "sending up update reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if (nat_t_ips_saved) { -+ /** -+ * As we _really_ update existing SA, we keep tdbq and need to delete -+ * parsed ips (nat_t_ips_saved, was extr->ips). -+ * -+ * goto errlab with extr->ips = nat_t_ips_saved will free it. -+ */ -+ -+ extr->ips = nat_t_ips_saved; -+ -+ error = 0; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse (NAT-T ports): " -+ "successful for SA: %s\n", -+ sa_len ? sa : " (error)"); -+ -+ goto errlab; -+ } -+#endif -+ -+ if((error = ipsec_sa_add(extr->ips))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " -+ "failed to update the mature SA=%s with error=%d.\n", -+ sa_len ? sa : " (error)", -+ error); -+ SENDERR(-error); -+ } -+ extr->ips = NULL; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: " -+ "successful for SA: %s\n", -+ sa_len ? sa : " (error)"); -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_add_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct ipsec_sa* ipsq; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_add_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_add_parse: " -+ "error, sa_state=%d must be MATURE=%d\n", -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state, -+ SADB_SASTATE_MATURE); -+ SENDERR(EINVAL); -+ } -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_add_parse: " -+ "extr or extr->ips pointer NULL\n"); -+ SENDERR(EINVAL); -+ } -+ -+ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); -+ -+ ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if(ipsq != NULL) { -+ ipsec_sa_put(ipsq); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_add_parse: " -+ "found an old ipsec_sa for SA%s, delete it first.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(EEXIST); -+ } -+ -+ if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == IS_MYADDR) { -+ extr->ips->ips_flags |= EMT_INBOUND; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_add_parse: " -+ "existing ipsec_sa not found (this is good) for SA%s, %s-bound, allocating.\n", -+ sa_len ? sa : " (error)", -+ extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); -+ -+ /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ -+ extr->ips->ips_rcvif = NULL; -+ -+ if ((error = pfkey_ipsec_sa_init(extr->ips, extensions))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_add_parse: " -+ "not successful for SA: %s, deleting.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(-error); -+ } -+ -+ extr->ips->ips_life.ipl_addtime.ipl_count = jiffies / HZ; -+ if(!extr->ips->ips_life.ipl_allocations.ipl_count) { -+ extr->ips->ips_life.ipl_allocations.ipl_count += 1; -+ } -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_ADD, -+ satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ extr->ips->ips_replaywin, -+ extr->ips->ips_state, -+ extr->ips->ips_authalg, -+ extr->ips->ips_encalg, -+ extr->ips->ips_flags, -+ extr->ips->ips_ref), -+ extensions_reply) -+ /* The 3 lifetime extentions should only be sent if non-zero. */ -+ && (extensions[SADB_EXT_LIFETIME_HARD] -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD], -+ SADB_EXT_LIFETIME_HARD, -+ extr->ips->ips_life.ipl_allocations.ipl_hard, -+ extr->ips->ips_life.ipl_bytes.ipl_hard, -+ extr->ips->ips_life.ipl_addtime.ipl_hard, -+ extr->ips->ips_life.ipl_usetime.ipl_hard, -+ extr->ips->ips_life.ipl_packets.ipl_hard), -+ extensions_reply) : 1) -+ && (extensions[SADB_EXT_LIFETIME_SOFT] -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT], -+ SADB_EXT_LIFETIME_SOFT, -+ extr->ips->ips_life.ipl_allocations.ipl_soft, -+ extr->ips->ips_life.ipl_bytes.ipl_soft, -+ extr->ips->ips_life.ipl_addtime.ipl_soft, -+ extr->ips->ips_life.ipl_usetime.ipl_soft, -+ extr->ips->ips_life.ipl_packets.ipl_soft), -+ extensions_reply) : 1) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_s), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_d), -+ extensions_reply) -+ && (extr->ips->ips_ident_s.data -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC], -+ SADB_EXT_IDENTITY_SRC, -+ extr->ips->ips_ident_s.type, -+ extr->ips->ips_ident_s.id, -+ extr->ips->ips_ident_s.len, -+ extr->ips->ips_ident_s.data), -+ extensions_reply) : 1) -+ && (extr->ips->ips_ident_d.data -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST], -+ SADB_EXT_IDENTITY_DST, -+ extr->ips->ips_ident_d.type, -+ extr->ips->ips_ident_d.id, -+ extr->ips->ips_ident_d.len, -+ extr->ips->ips_ident_d.data), -+ extensions_reply) : 1) -+#if 0 -+ /* FIXME: This won't work yet because I have not finished -+ it. */ -+ && (extr->ips->ips_sens_ -+ ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY], -+ extr->ips->ips_sens_dpd, -+ extr->ips->ips_sens_sens_level, -+ extr->ips->ips_sens_sens_len, -+ extr->ips->ips_sens_sens_bitmap, -+ extr->ips->ips_sens_integ_level, -+ extr->ips->ips_sens_integ_len, -+ extr->ips->ips_sens_integ_bitmap), -+ extensions_reply) : 1) -+#endif -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " -+ "failed to build the add reply message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " -+ "failed to build the add reply message\n"); -+ SENDERR(-error); -+ } -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " -+ "sending up add reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " -+ "sending up add reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ if((error = ipsec_sa_add(extr->ips))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " -+ "failed to add the mature SA=%s with error=%d.\n", -+ sa_len ? sa : " (error)", -+ error); -+ SENDERR(-error); -+ } -+ extr->ips = NULL; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_add_parse: " -+ "successful for SA: %s\n", -+ sa_len ? sa : " (error)"); -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_delete_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ struct ipsec_sa *ipsp; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ int error = 0; -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_delete_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_delete_parse: " -+ "extr or extr->ips pointer NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); -+ -+ spin_lock_bh(&tdb_lock); -+ -+ ipsp = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if (ipsp == NULL) { -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_delete_parse: " -+ "ipsec_sa not found for SA:%s, could not delete.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(ESRCH); -+ } -+ -+ ipsec_sa_put(ipsp); -+ if((error = ipsec_sa_delchain(ipsp))) { -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_delete_parse: " -+ "error=%d returned trying to delete ipsec_sa for SA:%s.\n", -+ error, -+ sa_len ? sa : " (error)"); -+ SENDERR(-error); -+ } -+ spin_unlock_bh(&tdb_lock); -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_DELETE, -+ satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ 0, -+ 0, -+ 0, -+ 0, -+ 0, -+ extr->ips->ips_ref), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_s), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_d), -+ extensions_reply) -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " -+ "failed to build the delete reply message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " -+ "failed to build the delete reply message\n"); -+ SENDERR(-error); -+ } -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " -+ "sending up delete reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " -+ "sending up delete reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_get_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct ipsec_sa *ipsp; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_get_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_get_parse: " -+ "extr or extr->ips pointer NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); -+ -+ spin_lock_bh(&tdb_lock); -+ -+ ipsp = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if (ipsp == NULL) { -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " -+ "ipsec_sa not found for SA=%s, could not get.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(ESRCH); -+ } -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_GET, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ extr->ips->ips_replaywin, -+ extr->ips->ips_state, -+ extr->ips->ips_authalg, -+ extr->ips->ips_encalg, -+ extr->ips->ips_flags, -+ extr->ips->ips_ref), -+ extensions_reply) -+ /* The 3 lifetime extentions should only be sent if non-zero. */ -+ && (ipsp->ips_life.ipl_allocations.ipl_count -+ || ipsp->ips_life.ipl_bytes.ipl_count -+ || ipsp->ips_life.ipl_addtime.ipl_count -+ || ipsp->ips_life.ipl_usetime.ipl_count -+ || ipsp->ips_life.ipl_packets.ipl_count -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_CURRENT], -+ SADB_EXT_LIFETIME_CURRENT, -+ ipsp->ips_life.ipl_allocations.ipl_count, -+ ipsp->ips_life.ipl_bytes.ipl_count, -+ ipsp->ips_life.ipl_addtime.ipl_count, -+ ipsp->ips_life.ipl_usetime.ipl_count, -+ ipsp->ips_life.ipl_packets.ipl_count), -+ extensions_reply) : 1) -+ && (ipsp->ips_life.ipl_allocations.ipl_hard -+ || ipsp->ips_life.ipl_bytes.ipl_hard -+ || ipsp->ips_life.ipl_addtime.ipl_hard -+ || ipsp->ips_life.ipl_usetime.ipl_hard -+ || ipsp->ips_life.ipl_packets.ipl_hard -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD], -+ SADB_EXT_LIFETIME_HARD, -+ ipsp->ips_life.ipl_allocations.ipl_hard, -+ ipsp->ips_life.ipl_bytes.ipl_hard, -+ ipsp->ips_life.ipl_addtime.ipl_hard, -+ ipsp->ips_life.ipl_usetime.ipl_hard, -+ ipsp->ips_life.ipl_packets.ipl_hard), -+ extensions_reply) : 1) -+ && (ipsp->ips_life.ipl_allocations.ipl_soft -+ || ipsp->ips_life.ipl_bytes.ipl_soft -+ || ipsp->ips_life.ipl_addtime.ipl_soft -+ || ipsp->ips_life.ipl_usetime.ipl_soft -+ || ipsp->ips_life.ipl_packets.ipl_soft -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT], -+ SADB_EXT_LIFETIME_SOFT, -+ ipsp->ips_life.ipl_allocations.ipl_soft, -+ ipsp->ips_life.ipl_bytes.ipl_soft, -+ ipsp->ips_life.ipl_addtime.ipl_soft, -+ ipsp->ips_life.ipl_usetime.ipl_soft, -+ ipsp->ips_life.ipl_packets.ipl_soft), -+ extensions_reply) : 1) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_s), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_d), -+ extensions_reply) -+ && (extr->ips->ips_addr_p -+ ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_PROXY], -+ SADB_EXT_ADDRESS_PROXY, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_p), -+ extensions_reply) : 1) -+#if 0 -+ /* FIXME: This won't work yet because the keys are not -+ stored directly in the ipsec_sa. They are stored as -+ contexts. */ -+ && (extr->ips->ips_key_a_size -+ ? pfkey_safe_build(error = pfkey_key_build(&extensions_reply[SADB_EXT_KEY_AUTH], -+ SADB_EXT_KEY_AUTH, -+ extr->ips->ips_key_a_size * 8, -+ extr->ips->ips_key_a), -+ extensions_reply) : 1) -+ /* FIXME: This won't work yet because the keys are not -+ stored directly in the ipsec_sa. They are stored as -+ key schedules. */ -+ && (extr->ips->ips_key_e_size -+ ? pfkey_safe_build(error = pfkey_key_build(&extensions_reply[SADB_EXT_KEY_ENCRYPT], -+ SADB_EXT_KEY_ENCRYPT, -+ extr->ips->ips_key_e_size * 8, -+ extr->ips->ips_key_e), -+ extensions_reply) : 1) -+#endif -+ && (extr->ips->ips_ident_s.data -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC], -+ SADB_EXT_IDENTITY_SRC, -+ extr->ips->ips_ident_s.type, -+ extr->ips->ips_ident_s.id, -+ extr->ips->ips_ident_s.len, -+ extr->ips->ips_ident_s.data), -+ extensions_reply) : 1) -+ && (extr->ips->ips_ident_d.data -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST], -+ SADB_EXT_IDENTITY_DST, -+ extr->ips->ips_ident_d.type, -+ extr->ips->ips_ident_d.id, -+ extr->ips->ips_ident_d.len, -+ extr->ips->ips_ident_d.data), -+ extensions_reply) : 1) -+#if 0 -+ /* FIXME: This won't work yet because I have not finished -+ it. */ -+ && (extr->ips->ips_sens_ -+ ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY], -+ extr->ips->ips_sens_dpd, -+ extr->ips->ips_sens_sens_level, -+ extr->ips->ips_sens_sens_len, -+ extr->ips->ips_sens_sens_bitmap, -+ extr->ips->ips_sens_integ_level, -+ extr->ips->ips_sens_integ_len, -+ extr->ips->ips_sens_integ_bitmap), -+ extensions_reply) : 1) -+#endif -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " -+ "failed to build the get reply message extensions\n"); -+ ipsec_sa_put(ipsp); -+ spin_unlock_bh(&tdb_lock); -+ SENDERR(-error); -+ } -+ -+ ipsec_sa_put(ipsp); -+ spin_unlock_bh(&tdb_lock); -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " -+ "failed to build the get reply message\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_upmsg(sk->socket, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " -+ "failed to send the get reply message\n"); -+ SENDERR(-error); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " -+ "succeeded in sending get reply message.\n"); -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_acquire_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_acquire_parse: .\n"); -+ -+ /* XXX I don't know if we want an upper bound, since userspace may -+ want to register itself for an satype > SADB_SATYPE_MAX. */ -+ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_acquire_parse: " -+ "SATYPE=%d invalid.\n", -+ satype); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(pfkey_registered_sockets[satype])) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " -+ "no sockets registered for SAtype=%d(%s).\n", -+ satype, -+ satype2name(satype)); -+ SENDERR(EPROTONOSUPPORT); -+ } -+ -+ for(pfkey_socketsp = pfkey_registered_sockets[satype]; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " -+ "sending up acquire reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " -+ "sending up acquire reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_register_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_parse: .\n"); -+ -+ /* XXX I don't know if we want an upper bound, since userspace may -+ want to register itself for an satype > SADB_SATYPE_MAX. */ -+ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_parse: " -+ "SATYPE=%d invalid.\n", -+ satype); -+ SENDERR(EINVAL); -+ } -+ -+ if(!pfkey_list_insert_socket(sk->socket, -+ &(pfkey_registered_sockets[satype]))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_parse: " -+ "SATYPE=%02d(%s) successfully registered by KMd (pid=%d).\n", -+ satype, -+ satype2name(satype), -+ key_pid(sk)); -+ }; -+ -+ /* send up register msg with supported SATYPE algos */ -+ -+ error=pfkey_register_reply(satype, (struct sadb_msg*)extensions[SADB_EXT_RESERVED]); -+ errlab: -+ return error; -+} -+ -+int -+pfkey_register_reply(int satype, struct sadb_msg *sadb_msg) -+{ -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ struct supported_list *pfkey_supported_listp; -+ unsigned int alg_num_a = 0, alg_num_e = 0; -+ struct sadb_alg *alg_a = NULL, *alg_e = NULL, *alg_ap = NULL, *alg_ep = NULL; -+ int error = 0; -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " -+ "SAtype=%d unspecified or unknown.\n", -+ satype); -+ SENDERR(EINVAL); -+ } -+ if(!(pfkey_registered_sockets[satype])) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " -+ "no sockets registered for SAtype=%d(%s).\n", -+ satype, -+ satype2name(satype)); -+ SENDERR(EPROTONOSUPPORT); -+ } -+ /* send up register msg with supported SATYPE algos */ -+ pfkey_supported_listp = pfkey_supported_list[satype]; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "pfkey_supported_list[%d]=0p%p\n", -+ satype, -+ pfkey_supported_list[satype]); -+ while(pfkey_supported_listp) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "checking supported=0p%p\n", -+ pfkey_supported_listp); -+ if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_AUTH) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "adding auth alg.\n"); -+ alg_num_a++; -+ } -+ if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_ENCRYPT) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "adding encrypt alg.\n"); -+ alg_num_e++; -+ } -+ pfkey_supported_listp = pfkey_supported_listp->next; -+ } -+ -+ if(alg_num_a) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "allocating %lu bytes for auth algs.\n", -+ (unsigned long) (alg_num_a * sizeof(struct sadb_alg))); -+ if((alg_a = kmalloc(alg_num_a * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "auth alg memory allocation error\n"); -+ SENDERR(ENOMEM); -+ } -+ alg_ap = alg_a; -+ } -+ -+ if(alg_num_e) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "allocating %lu bytes for enc algs.\n", -+ (unsigned long) (alg_num_e * sizeof(struct sadb_alg))); -+ if((alg_e = kmalloc(alg_num_e * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "enc alg memory allocation error\n"); -+ SENDERR(ENOMEM); -+ } -+ alg_ep = alg_e; -+ } -+ -+ pfkey_supported_listp = pfkey_supported_list[satype]; -+ while(pfkey_supported_listp) { -+ if(alg_num_a) { -+ if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_AUTH) { -+ alg_ap->sadb_alg_id = pfkey_supported_listp->supportedp->supported_alg_id; -+ alg_ap->sadb_alg_ivlen = pfkey_supported_listp->supportedp->supported_alg_ivlen; -+ alg_ap->sadb_alg_minbits = pfkey_supported_listp->supportedp->supported_alg_minbits; -+ alg_ap->sadb_alg_maxbits = pfkey_supported_listp->supportedp->supported_alg_maxbits; -+ alg_ap->sadb_alg_reserved = 0; -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_register_reply: " -+ "adding auth=0p%p\n", -+ alg_ap); -+ alg_ap++; -+ } -+ } -+ if(alg_num_e) { -+ if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_ENCRYPT) { -+ alg_ep->sadb_alg_id = pfkey_supported_listp->supportedp->supported_alg_id; -+ alg_ep->sadb_alg_ivlen = pfkey_supported_listp->supportedp->supported_alg_ivlen; -+ alg_ep->sadb_alg_minbits = pfkey_supported_listp->supportedp->supported_alg_minbits; -+ alg_ep->sadb_alg_maxbits = pfkey_supported_listp->supportedp->supported_alg_maxbits; -+ alg_ep->sadb_alg_reserved = 0; -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_register_reply: " -+ "adding encrypt=0p%p\n", -+ alg_ep); -+ alg_ep++; -+ } -+ } -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "found satype=%d(%s) exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_supported_listp->supportedp->supported_alg_exttype, -+ pfkey_supported_listp->supportedp->supported_alg_id, -+ pfkey_supported_listp->supportedp->supported_alg_ivlen, -+ pfkey_supported_listp->supportedp->supported_alg_minbits, -+ pfkey_supported_listp->supportedp->supported_alg_maxbits); -+ pfkey_supported_listp = pfkey_supported_listp->next; -+ } -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_REGISTER, -+ satype, -+ 0, -+ sadb_msg? sadb_msg->sadb_msg_seq : ++pfkey_msg_seq, -+ sadb_msg? sadb_msg->sadb_msg_pid: current->pid), -+ extensions_reply) && -+ (alg_num_a ? pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[SADB_EXT_SUPPORTED_AUTH], -+ SADB_EXT_SUPPORTED_AUTH, -+ alg_num_a, -+ alg_a), -+ extensions_reply) : 1) && -+ (alg_num_e ? pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[SADB_EXT_SUPPORTED_ENCRYPT], -+ SADB_EXT_SUPPORTED_ENCRYPT, -+ alg_num_e, -+ alg_e), -+ extensions_reply) : 1))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " -+ "failed to build the register message extensions_reply\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " -+ "failed to build the register message\n"); -+ SENDERR(-error); -+ } -+ /* this should go to all registered sockets for that satype only */ -+ for(pfkey_socketsp = pfkey_registered_sockets[satype]; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " -+ "sending up acquire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " -+ "sending up register message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ errlab: -+ if(alg_a) { -+ kfree(alg_a); -+ } -+ if(alg_e) { -+ kfree(alg_e); -+ } -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_expire_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct socket_list *pfkey_socketsp; -+#ifdef CONFIG_IPSEC_DEBUG -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_expire_parse: .\n"); -+ -+ if(pfkey_open_sockets) { -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: " -+ "sending up expire reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: " -+ "sending up expire reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ } -+ -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_flush_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ uint8_t proto = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_flush_parse: " -+ "flushing type %d SAs\n", -+ satype); -+ -+ if(satype && !(proto = satype2proto(satype))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_flush_parse: " -+ "satype %d lookup failed.\n", -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype); -+ SENDERR(EINVAL); -+ } -+ -+ if ((error = ipsec_sadb_cleanup(proto))) { -+ SENDERR(-error); -+ } -+ -+ if(pfkey_open_sockets) { -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: " -+ "sending up flush reply message for satype=%d(%s) (proto=%d) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ proto, -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: " -+ "sending up flush reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ } -+ -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_dump_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_dump_parse: .\n"); -+ -+ SENDERR(ENOSYS); -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_promisc_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_promisc_parse: .\n"); -+ -+ SENDERR(ENOSYS); -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_pchange_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_pchange_parse: .\n"); -+ -+ SENDERR(ENOSYS); -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_grpsa_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ struct ipsec_sa *ips1p, *ips2p, *ipsp; -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ char sa1[SATOT_BUF], sa2[SATOT_BUF]; -+ size_t sa_len1, sa_len2 = 0; -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ if(extr == NULL || extr->ips == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "extr or extr->ips is NULL, fatal.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ sa_len1 = satot(&extr->ips->ips_said, 0, sa1, sizeof(sa1)); -+ if(extr->ips2 != NULL) { -+ sa_len2 = satot(&extr->ips2->ips_said, 0, sa2, sizeof(sa2)); -+ } -+ -+ spin_lock_bh(&tdb_lock); -+ -+ ips1p = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if(ips1p == NULL) { -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "reserved ipsec_sa for SA1: %s not found. Call SADB_ADD/UPDATE first.\n", -+ sa_len1 ? sa1 : " (error)"); -+ SENDERR(ENOENT); -+ } -+ if(extr->ips2) { /* GRPSA */ -+ ips2p = ipsec_sa_getbyid(&(extr->ips2->ips_said)); -+ if(ips2p == NULL) { -+ ipsec_sa_put(ips1p); -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "reserved ipsec_sa for SA2: %s not found. Call SADB_ADD/UPDATE first.\n", -+ sa_len2 ? sa2 : " (error)"); -+ SENDERR(ENOENT); -+ } -+ -+ /* Is either one already linked? */ -+ if(ips1p->ips_onext) { -+ ipsec_sa_put(ips1p); -+ ipsec_sa_put(ips2p); -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "ipsec_sa for SA: %s is already linked.\n", -+ sa_len1 ? sa1 : " (error)"); -+ SENDERR(EEXIST); -+ } -+ if(ips2p->ips_inext) { -+ ipsec_sa_put(ips1p); -+ ipsec_sa_put(ips2p); -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "ipsec_sa for SA: %s is already linked.\n", -+ sa_len2 ? sa2 : " (error)"); -+ SENDERR(EEXIST); -+ } -+ -+ /* Is extr->ips already linked to extr->ips2? */ -+ ipsp = ips2p; -+ while(ipsp) { -+ if(ipsp == ips1p) { -+ ipsec_sa_put(ips1p); -+ ipsec_sa_put(ips2p); -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "ipsec_sa for SA: %s is already linked to %s.\n", -+ sa_len1 ? sa1 : " (error)", -+ sa_len2 ? sa2 : " (error)"); -+ SENDERR(EEXIST); -+ } -+ ipsp = ipsp->ips_onext; -+ } -+ -+ /* link 'em */ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "linking ipsec_sa SA: %s with %s.\n", -+ sa_len1 ? sa1 : " (error)", -+ sa_len2 ? sa2 : " (error)"); -+ ips1p->ips_onext = ips2p; -+ ips2p->ips_inext = ips1p; -+ } else { /* UNGRPSA */ -+ ipsec_sa_put(ips1p); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "unlinking ipsec_sa SA: %s.\n", -+ sa_len1 ? sa1 : " (error)"); -+ while(ips1p->ips_onext) { -+ ips1p = ips1p->ips_onext; -+ } -+ while(ips1p->ips_inext) { -+ ipsp = ips1p; -+ ips1p = ips1p->ips_inext; -+ ipsec_sa_put(ips1p); -+ ipsp->ips_inext = NULL; -+ ipsec_sa_put(ipsp); -+ ips1p->ips_onext = NULL; -+ } -+ } -+ -+ spin_unlock_bh(&tdb_lock); -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_X_GRPSA, -+ satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ extr->ips->ips_replaywin, -+ extr->ips->ips_state, -+ extr->ips->ips_authalg, -+ extr->ips->ips_encalg, -+ extr->ips->ips_flags, -+ extr->ips->ips_ref), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_d), -+ extensions_reply) -+ && (extr->ips2 -+ ? (pfkey_safe_build(error = pfkey_x_satype_build(&extensions_reply[SADB_X_EXT_SATYPE2], -+ ((struct sadb_x_satype*)extensions[SADB_X_EXT_SATYPE2])->sadb_x_satype_satype -+ /* proto2satype(extr->ips2->ips_said.proto) */), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_X_EXT_SA2], -+ SADB_X_EXT_SA2, -+ extr->ips2->ips_said.spi, -+ extr->ips2->ips_replaywin, -+ extr->ips2->ips_state, -+ extr->ips2->ips_authalg, -+ extr->ips2->ips_encalg, -+ extr->ips2->ips_flags, -+ extr->ips2->ips_ref), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST2], -+ SADB_X_EXT_ADDRESS_DST2, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips2->ips_addr_d), -+ extensions_reply) ) : 1 ) -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " -+ "failed to build the x_grpsa reply message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " -+ "failed to build the x_grpsa reply message\n"); -+ SENDERR(-error); -+ } -+ -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " -+ "sending up x_grpsa reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " -+ "sending up x_grpsa reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " -+ "succeeded in sending x_grpsa reply message.\n"); -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_addflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+#ifdef CONFIG_IPSEC_DEBUG -+ char buf1[64], buf2[64]; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ ip_address srcflow, dstflow, srcmask, dstmask; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ memset((caddr_t)&srcflow, 0, sizeof(srcflow)); -+ memset((caddr_t)&dstflow, 0, sizeof(dstflow)); -+ memset((caddr_t)&srcmask, 0, sizeof(srcmask)); -+ memset((caddr_t)&dstmask, 0, sizeof(dstmask)); -+ -+ if(!extr || !(extr->ips) || !(extr->eroute)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "missing extr, ipsec_sa or eroute data.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ srcflow.u.v4.sin_family = AF_INET; -+ dstflow.u.v4.sin_family = AF_INET; -+ srcmask.u.v4.sin_family = AF_INET; -+ dstmask.u.v4.sin_family = AF_INET; -+ srcflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_src; -+ dstflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_dst; -+ srcmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_src; -+ dstmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_dst; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_pfkey) { -+ subnettoa(extr->eroute->er_eaddr.sen_ip_src, -+ extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(extr->eroute->er_eaddr.sen_ip_dst, -+ extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "calling breakeroute and/or makeroute for %s->%s\n", -+ buf1, buf2); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ if(extr->ips->ips_flags & SADB_X_SAFLAGS_INFLOW) { -+/* if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == IS_MYADDR) */ -+ struct ipsec_sa *ipsp, *ipsq; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if(ipsq == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "ipsec_sa not found, cannot set incoming policy.\n"); -+ SENDERR(ENOENT); -+ } -+ -+ ipsp = ipsq; -+ while(ipsp && ipsp->ips_said.proto != IPPROTO_IPIP) { -+ ipsp = ipsp->ips_inext; -+ } -+ -+ if(ipsp == NULL) { -+ ipsec_sa_put(ipsq); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "SA chain does not have an IPIP SA, cannot set incoming policy.\n"); -+ SENDERR(ENOENT); -+ } -+ -+ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); -+ -+ ipsp->ips_flags |= SADB_X_SAFLAGS_INFLOW; -+ ipsp->ips_flow_s = srcflow; -+ ipsp->ips_flow_d = dstflow; -+ ipsp->ips_mask_s = srcmask; -+ ipsp->ips_mask_d = dstmask; -+ -+ ipsec_sa_put(ipsq); -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "inbound eroute, setting incoming policy information in IPIP ipsec_sa for SA: %s.\n", -+ sa_len ? sa : " (error)"); -+ } else { -+ struct sk_buff *first = NULL, *last = NULL; -+ -+ if(extr->ips->ips_flags & SADB_X_SAFLAGS_REPLACEFLOW) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "REPLACEFLOW flag set, calling breakeroute.\n"); -+ if ((error = ipsec_breakroute(&(extr->eroute->er_eaddr), -+ &(extr->eroute->er_emask), -+ &first, &last))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "breakeroute returned %d. first=0p%p, last=0p%p\n", -+ error, -+ first, -+ last); -+ if(first != NULL) { -+ ipsec_kfree_skb(first); -+ } -+ if(last != NULL) { -+ ipsec_kfree_skb(last); -+ } -+ SENDERR(-error); -+ } -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "calling makeroute.\n"); -+ -+ if ((error = ipsec_makeroute(&(extr->eroute->er_eaddr), -+ &(extr->eroute->er_emask), -+ extr->ips->ips_said, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid, -+ NULL, -+ &(extr->ips->ips_ident_s), -+ &(extr->ips->ips_ident_d)))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "makeroute returned %d.\n", error); -+ SENDERR(-error); -+ } -+ if(first != NULL) { -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "first=0p%p HOLD packet re-injected.\n", -+ first); -+ DEV_QUEUE_XMIT(first, first->dev, SOPRI_NORMAL); -+ } -+ if(last != NULL) { -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "last=0p%p HOLD packet re-injected.\n", -+ last); -+ DEV_QUEUE_XMIT(last, last->dev, SOPRI_NORMAL); -+ } -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "makeroute call successful.\n"); -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_X_ADDFLOW, -+ satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ extr->ips->ips_replaywin, -+ extr->ips->ips_state, -+ extr->ips->ips_authalg, -+ extr->ips->ips_encalg, -+ extr->ips->ips_flags, -+ extr->ips->ips_ref), -+ extensions_reply) -+ && (extensions[SADB_EXT_ADDRESS_SRC] -+ ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_s), -+ extensions_reply) : 1) -+ && (extensions[SADB_EXT_ADDRESS_DST] -+ ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_d), -+ extensions_reply) : 1) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_FLOW], -+ SADB_X_EXT_ADDRESS_SRC_FLOW, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&srcflow), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_FLOW], -+ SADB_X_EXT_ADDRESS_DST_FLOW, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&dstflow), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_MASK], -+ SADB_X_EXT_ADDRESS_SRC_MASK, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&srcmask), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_MASK], -+ SADB_X_EXT_ADDRESS_DST_MASK, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&dstmask), -+ extensions_reply) -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " -+ "failed to build the x_addflow reply message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " -+ "failed to build the x_addflow reply message\n"); -+ SENDERR(-error); -+ } -+ -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " -+ "sending up x_addflow reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " -+ "sending up x_addflow reply message for satype=%d(%s) (proto=%d) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ extr->ips->ips_said.proto, -+ pfkey_socketsp->socketp); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "extr->ips cleaned up and freed.\n"); -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_delflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+#ifdef CONFIG_IPSEC_DEBUG -+ char buf1[64], buf2[64]; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ ip_address srcflow, dstflow, srcmask, dstmask; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ memset((caddr_t)&srcflow, 0, sizeof(srcflow)); -+ memset((caddr_t)&dstflow, 0, sizeof(dstflow)); -+ memset((caddr_t)&srcmask, 0, sizeof(srcmask)); -+ memset((caddr_t)&dstmask, 0, sizeof(dstmask)); -+ -+ if(!extr || !(extr->ips)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: " -+ "extr, or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(extr->ips->ips_flags & SADB_X_SAFLAGS_CLEARFLOW) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: " -+ "CLEARFLOW flag set, calling cleareroutes.\n"); -+ if ((error = ipsec_cleareroutes())) -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: " -+ "cleareroutes returned %d.\n", error); -+ SENDERR(-error); -+ } else { -+ struct sk_buff *first = NULL, *last = NULL; -+ -+ if(!(extr->eroute)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: " -+ "extr->eroute is NULL, fatal.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ srcflow.u.v4.sin_family = AF_INET; -+ dstflow.u.v4.sin_family = AF_INET; -+ srcmask.u.v4.sin_family = AF_INET; -+ dstmask.u.v4.sin_family = AF_INET; -+ srcflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_src; -+ dstflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_dst; -+ srcmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_src; -+ dstmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_dst; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_pfkey) { -+ subnettoa(extr->eroute->er_eaddr.sen_ip_src, -+ extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(extr->eroute->er_eaddr.sen_ip_dst, -+ extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: " -+ "calling breakeroute for %s->%s\n", -+ buf1, buf2); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ error = ipsec_breakroute(&(extr->eroute->er_eaddr), -+ &(extr->eroute->er_emask), -+ &first, &last); -+ if(error) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: " -+ "breakeroute returned %d. first=0p%p, last=0p%p\n", -+ error, -+ first, -+ last); -+ } -+ if(first != NULL) { -+ ipsec_kfree_skb(first); -+ } -+ if(last != NULL) { -+ ipsec_kfree_skb(last); -+ } -+ if(error) { -+ SENDERR(-error); -+ } -+ } -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_X_DELFLOW, -+ satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ extr->ips->ips_replaywin, -+ extr->ips->ips_state, -+ extr->ips->ips_authalg, -+ extr->ips->ips_encalg, -+ extr->ips->ips_flags, -+ extr->ips->ips_ref), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_FLOW], -+ SADB_X_EXT_ADDRESS_SRC_FLOW, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&srcflow), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_FLOW], -+ SADB_X_EXT_ADDRESS_DST_FLOW, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&dstflow), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_MASK], -+ SADB_X_EXT_ADDRESS_SRC_MASK, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&srcmask), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_MASK], -+ SADB_X_EXT_ADDRESS_DST_MASK, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&dstmask), -+ extensions_reply) -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " -+ "failed to build the x_delflow reply message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " -+ "failed to build the x_delflow reply message\n"); -+ SENDERR(-error); -+ } -+ -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " -+ "sending up x_delflow reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " -+ "sending up x_delflow reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: " -+ "extr->ips cleaned up and freed.\n"); -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_msg_debug_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_msg_debug_parse: .\n"); -+ -+/* errlab:*/ -+ return error; -+} -+ -+/* pfkey_expire expects the ipsec_sa table to be locked before being called. */ -+int -+pfkey_expire(struct ipsec_sa *ipsp, int hard) -+{ -+ struct sadb_ext *extensions[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_msg = NULL; -+ struct socket_list *pfkey_socketsp; -+ int error = 0; -+ uint8_t satype; -+ -+ pfkey_extensions_init(extensions); -+ -+ if(!(satype = proto2satype(ipsp->ips_said.proto))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_expire: " -+ "satype lookup for protocol %d lookup failed.\n", -+ ipsp->ips_said.proto); -+ SENDERR(EINVAL); -+ } -+ -+ if(!pfkey_open_sockets) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " -+ "no sockets listening.\n"); -+ SENDERR(EPROTONOSUPPORT); -+ } -+ -+ if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions[0], -+ SADB_EXPIRE, -+ satype, -+ 0, -+ ++pfkey_msg_seq, -+ 0), -+ extensions) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions[SADB_EXT_SA], -+ SADB_EXT_SA, -+ ipsp->ips_said.spi, -+ ipsp->ips_replaywin, -+ ipsp->ips_state, -+ ipsp->ips_authalg, -+ ipsp->ips_encalg, -+ ipsp->ips_flags, -+ ipsp->ips_ref), -+ extensions) -+ && pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_CURRENT], -+ SADB_EXT_LIFETIME_CURRENT, -+ ipsp->ips_life.ipl_allocations.ipl_count, -+ ipsp->ips_life.ipl_bytes.ipl_count, -+ ipsp->ips_life.ipl_addtime.ipl_count, -+ ipsp->ips_life.ipl_usetime.ipl_count, -+ ipsp->ips_life.ipl_packets.ipl_count), -+ extensions) -+ && (hard ? -+ pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_HARD], -+ SADB_EXT_LIFETIME_HARD, -+ ipsp->ips_life.ipl_allocations.ipl_hard, -+ ipsp->ips_life.ipl_bytes.ipl_hard, -+ ipsp->ips_life.ipl_addtime.ipl_hard, -+ ipsp->ips_life.ipl_usetime.ipl_hard, -+ ipsp->ips_life.ipl_packets.ipl_hard), -+ extensions) -+ : pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_SOFT], -+ SADB_EXT_LIFETIME_SOFT, -+ ipsp->ips_life.ipl_allocations.ipl_soft, -+ ipsp->ips_life.ipl_bytes.ipl_soft, -+ ipsp->ips_life.ipl_addtime.ipl_soft, -+ ipsp->ips_life.ipl_usetime.ipl_soft, -+ ipsp->ips_life.ipl_packets.ipl_soft), -+ extensions)) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ 0, /* ipsp->ips_said.proto, */ -+ 0, -+ ipsp->ips_addr_s), -+ extensions) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /* ipsp->ips_said.proto, */ -+ 0, -+ ipsp->ips_addr_d), -+ extensions))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " -+ "failed to build the expire message extensions\n"); -+ spin_unlock(&tdb_lock); -+ goto errlab; -+ } -+ -+ if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " -+ "failed to build the expire message\n"); -+ SENDERR(-error); -+ } -+ -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " -+ "sending up expire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " -+ "sending up expire message for satype=%d(%s) (proto=%d) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ ipsp->ips_said.proto, -+ pfkey_socketsp->socketp); -+ } -+ -+ errlab: -+ if (pfkey_msg) { -+ pfkey_msg_free(&pfkey_msg); -+ } -+ pfkey_extensions_free(extensions); -+ return error; -+} -+ -+int -+pfkey_acquire(struct ipsec_sa *ipsp) -+{ -+ struct sadb_ext *extensions[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_msg = NULL; -+ struct socket_list *pfkey_socketsp; -+ int error = 0; -+ struct sadb_comb comb[] = { -+ /* auth; encrypt; flags; */ -+ /* auth_minbits; auth_maxbits; encrypt_minbits; encrypt_maxbits; */ -+ /* reserved; soft_allocations; hard_allocations; soft_bytes; hard_bytes; */ -+ /* soft_addtime; hard_addtime; soft_usetime; hard_usetime; */ -+ /* soft_packets; hard_packets; */ -+ { SADB_AALG_MD5HMAC, SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS, -+ 128, 128, 168, 168, -+ 0, 0, 0, 0, 0, -+ 57600, 86400, 57600, 86400, -+ 0, 0 }, -+ { SADB_AALG_SHA1HMAC, SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS, -+ 160, 160, 168, 168, -+ 0, 0, 0, 0, 0, -+ 57600, 86400, 57600, 86400, -+ 0, 0 } -+ }; -+ -+ /* XXX This should not be hard-coded. It should be taken from the spdb */ -+ uint8_t satype = SADB_SATYPE_ESP; -+ -+ pfkey_extensions_init(extensions); -+ -+ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: " -+ "SAtype=%d unspecified or unknown.\n", -+ satype); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(pfkey_registered_sockets[satype])) { -+ KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " -+ "no sockets registered for SAtype=%d(%s).\n", -+ satype, -+ satype2name(satype)); -+ SENDERR(EPROTONOSUPPORT); -+ } -+ -+ if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions[0], -+ SADB_ACQUIRE, -+ satype, -+ 0, -+ ++pfkey_msg_seq, -+ 0), -+ extensions) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ ipsp->ips_transport_protocol, -+ 0, -+ ipsp->ips_addr_s), -+ extensions) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ ipsp->ips_transport_protocol, -+ 0, -+ ipsp->ips_addr_d), -+ extensions) -+#if 0 -+ && (ipsp->ips_addr_p -+ ? pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_PROXY], -+ SADB_EXT_ADDRESS_PROXY, -+ ipsp->ips_transport_protocol, -+ 0, -+ ipsp->ips_addr_p), -+ extensions) : 1) -+#endif -+ && (ipsp->ips_ident_s.type != SADB_IDENTTYPE_RESERVED -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_SRC], -+ SADB_EXT_IDENTITY_SRC, -+ ipsp->ips_ident_s.type, -+ ipsp->ips_ident_s.id, -+ ipsp->ips_ident_s.len, -+ ipsp->ips_ident_s.data), -+ extensions) : 1) -+ -+ && (ipsp->ips_ident_d.type != SADB_IDENTTYPE_RESERVED -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_DST], -+ SADB_EXT_IDENTITY_DST, -+ ipsp->ips_ident_d.type, -+ ipsp->ips_ident_d.id, -+ ipsp->ips_ident_d.len, -+ ipsp->ips_ident_d.data), -+ extensions) : 1) -+#if 0 -+ /* FIXME: This won't work yet because I have not finished -+ it. */ -+ && (ipsp->ips_sens_ -+ ? pfkey_safe_build(error = pfkey_sens_build(&extensions[SADB_EXT_SENSITIVITY], -+ ipsp->ips_sens_dpd, -+ ipsp->ips_sens_sens_level, -+ ipsp->ips_sens_sens_len, -+ ipsp->ips_sens_sens_bitmap, -+ ipsp->ips_sens_integ_level, -+ ipsp->ips_sens_integ_len, -+ ipsp->ips_sens_integ_bitmap), -+ extensions) : 1) -+#endif -+ && pfkey_safe_build(error = pfkey_prop_build(&extensions[SADB_EXT_PROPOSAL], -+ 64, /* replay */ -+ sizeof(comb)/sizeof(struct sadb_comb), -+ &(comb[0])), -+ extensions) -+ )) { -+ KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " -+ "failed to build the acquire message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) { -+ KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " -+ "failed to build the acquire message\n"); -+ SENDERR(-error); -+ } -+ -+#if KLIPS_PFKEY_ACQUIRE_LOSSAGE > 0 -+ if(sysctl_ipsec_regress_pfkey_lossage) { -+ return(0); -+ } -+#endif -+ -+ /* this should go to all registered sockets for that satype only */ -+ for(pfkey_socketsp = pfkey_registered_sockets[satype]; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) { -+ KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " -+ "sending up acquire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: " -+ "sending up acquire message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ errlab: -+ if (pfkey_msg) { -+ pfkey_msg_free(&pfkey_msg); -+ } -+ pfkey_extensions_free(extensions); -+ return error; -+} -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+int -+pfkey_nat_t_new_mapping(struct ipsec_sa *ipsp, struct sockaddr *ipaddr, -+ __u16 sport) -+{ -+ struct sadb_ext *extensions[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_msg = NULL; -+ struct socket_list *pfkey_socketsp; -+ int error = 0; -+ uint8_t satype = (ipsp->ips_said.proto==IPPROTO_ESP) ? SADB_SATYPE_ESP : 0; -+ -+ /* Construct SADB_X_NAT_T_NEW_MAPPING message */ -+ -+ pfkey_extensions_init(extensions); -+ -+ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " -+ "SAtype=%d unspecified or unknown.\n", -+ satype); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(pfkey_registered_sockets[satype])) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " -+ "no sockets registered for SAtype=%d(%s).\n", -+ satype, -+ satype2name(satype)); -+ SENDERR(EPROTONOSUPPORT); -+ } -+ -+ if (!(pfkey_safe_build -+ (error = pfkey_msg_hdr_build(&extensions[0], SADB_X_NAT_T_NEW_MAPPING, -+ satype, 0, ++pfkey_msg_seq, 0), extensions) -+ /* SA */ -+ && pfkey_safe_build -+ (error = pfkey_sa_build(&extensions[SADB_EXT_SA], -+ SADB_EXT_SA, ipsp->ips_said.spi, 0, 0, 0, 0, 0), extensions) -+ /* ADDRESS_SRC = old addr */ -+ && pfkey_safe_build -+ (error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, ipsp->ips_said.proto, 0, ipsp->ips_addr_s), -+ extensions) -+ /* NAT_T_SPORT = old port */ -+ && pfkey_safe_build -+ (error = pfkey_x_nat_t_port_build(&extensions[SADB_X_EXT_NAT_T_SPORT], -+ SADB_X_EXT_NAT_T_SPORT, ipsp->ips_natt_sport), extensions) -+ /* ADDRESS_DST = new addr */ -+ && pfkey_safe_build -+ (error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, ipsp->ips_said.proto, 0, ipaddr), extensions) -+ /* NAT_T_DPORT = new port */ -+ && pfkey_safe_build -+ (error = pfkey_x_nat_t_port_build(&extensions[SADB_X_EXT_NAT_T_DPORT], -+ SADB_X_EXT_NAT_T_DPORT, sport), extensions) -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " -+ "failed to build the nat_t_new_mapping message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " -+ "failed to build the nat_t_new_mapping message\n"); -+ SENDERR(-error); -+ } -+ -+ /* this should go to all registered sockets for that satype only */ -+ for(pfkey_socketsp = pfkey_registered_sockets[satype]; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " -+ "sending up nat_t_new_mapping message for satype=%d(%s) to socket=%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " -+ "sending up nat_t_new_mapping message for satype=%d(%s) to socket=%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ errlab: -+ if (pfkey_msg) { -+ pfkey_msg_free(&pfkey_msg); -+ } -+ pfkey_extensions_free(extensions); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_nat_t_new_mapping_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ /* SADB_X_NAT_T_NEW_MAPPING not used in kernel */ -+ return -EINVAL; -+} -+#endif -+ -+DEBUG_NO_STATIC int (*ext_processors[SADB_EXT_MAX+1])(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) = -+{ -+ NULL, /* pfkey_msg_process, */ -+ pfkey_sa_process, -+ pfkey_lifetime_process, -+ pfkey_lifetime_process, -+ pfkey_lifetime_process, -+ pfkey_address_process, -+ pfkey_address_process, -+ pfkey_address_process, -+ pfkey_key_process, -+ pfkey_key_process, -+ pfkey_ident_process, -+ pfkey_ident_process, -+ pfkey_sens_process, -+ pfkey_prop_process, -+ pfkey_supported_process, -+ pfkey_supported_process, -+ pfkey_spirange_process, -+ pfkey_x_kmprivate_process, -+ pfkey_x_satype_process, -+ pfkey_sa_process, -+ pfkey_address_process, -+ pfkey_address_process, -+ pfkey_address_process, -+ pfkey_address_process, -+ pfkey_address_process, -+ pfkey_x_debug_process, -+ pfkey_x_protocol_process -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ , -+ pfkey_x_nat_t_type_process, -+ pfkey_x_nat_t_port_process, -+ pfkey_x_nat_t_port_process, -+ pfkey_address_process -+#endif -+}; -+ -+ -+DEBUG_NO_STATIC int (*msg_parsers[SADB_MAX +1])(struct sock *sk, struct sadb_ext *extensions[], struct pfkey_extracted_data* extr) -+ = -+{ -+ NULL, /* RESERVED */ -+ pfkey_getspi_parse, -+ pfkey_update_parse, -+ pfkey_add_parse, -+ pfkey_delete_parse, -+ pfkey_get_parse, -+ pfkey_acquire_parse, -+ pfkey_register_parse, -+ pfkey_expire_parse, -+ pfkey_flush_parse, -+ pfkey_dump_parse, -+ pfkey_x_promisc_parse, -+ pfkey_x_pchange_parse, -+ pfkey_x_grpsa_parse, -+ pfkey_x_addflow_parse, -+ pfkey_x_delflow_parse, -+ pfkey_x_msg_debug_parse -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ , pfkey_x_nat_t_new_mapping_parse -+#endif -+}; -+ -+int -+pfkey_build_reply(struct sadb_msg *pfkey_msg, struct pfkey_extracted_data *extr, -+ struct sadb_msg **pfkey_reply) -+{ -+ struct sadb_ext *extensions[SADB_EXT_MAX+1]; -+ int error = 0; -+ int msg_type = pfkey_msg->sadb_msg_type; -+ int seq = pfkey_msg->sadb_msg_seq; -+ -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " -+ "building reply with type: %d\n", -+ msg_type); -+ pfkey_extensions_init(extensions); -+ if (!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " -+ "bad ipsec_sa passed\n"); -+ return EINVAL; -+ } -+ error = pfkey_safe_build(pfkey_msg_hdr_build(&extensions[0], -+ msg_type, -+ proto2satype(extr->ips->ips_said.proto), -+ 0, -+ seq, -+ pfkey_msg->sadb_msg_pid), -+ extensions) && -+ (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & -+ 1 << SADB_EXT_SA) -+ || pfkey_safe_build(pfkey_sa_ref_build(&extensions[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ extr->ips->ips_replaywin, -+ extr->ips->ips_state, -+ extr->ips->ips_authalg, -+ extr->ips->ips_encalg, -+ extr->ips->ips_flags, -+ extr->ips->ips_ref), -+ extensions)) && -+ (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & -+ 1 << SADB_EXT_LIFETIME_CURRENT) -+ || pfkey_safe_build(pfkey_lifetime_build(&extensions -+ [SADB_EXT_LIFETIME_CURRENT], -+ SADB_EXT_LIFETIME_CURRENT, -+ extr->ips->ips_life.ipl_allocations.ipl_count, -+ extr->ips->ips_life.ipl_bytes.ipl_count, -+ extr->ips->ips_life.ipl_addtime.ipl_count, -+ extr->ips->ips_life.ipl_usetime.ipl_count, -+ extr->ips->ips_life.ipl_packets.ipl_count), -+ extensions)) && -+ (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & -+ 1 << SADB_EXT_ADDRESS_SRC) -+ || pfkey_safe_build(pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ extr->ips->ips_said.proto, -+ 0, -+ extr->ips->ips_addr_s), -+ extensions)) && -+ (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & -+ 1 << SADB_EXT_ADDRESS_DST) -+ || pfkey_safe_build(pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ extr->ips->ips_said.proto, -+ 0, -+ extr->ips->ips_addr_d), -+ extensions)); -+ -+ if (error == 0) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " -+ "building extensions failed\n"); -+ return EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_build_reply: " -+ "built extensions, proceed to build the message\n"); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_build_reply: " -+ "extensions[1]=0p%p\n", -+ extensions[1]); -+ error = pfkey_msg_build(pfkey_reply, extensions, EXT_BITS_OUT); -+ pfkey_extensions_free(extensions); -+ -+ return error; -+} -+ -+int -+pfkey_msg_interp(struct sock *sk, struct sadb_msg *pfkey_msg, -+ struct sadb_msg **pfkey_reply) -+{ -+ int error = 0; -+ int i; -+ struct sadb_ext *extensions[SADB_EXT_MAX+1]; -+ struct pfkey_extracted_data extr = {NULL, NULL, NULL}; -+ -+ pfkey_extensions_init(extensions); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "parsing message ver=%d, type=%d, errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n", -+ pfkey_msg->sadb_msg_version, -+ pfkey_msg->sadb_msg_type, -+ pfkey_msg->sadb_msg_errno, -+ pfkey_msg->sadb_msg_satype, -+ satype2name(pfkey_msg->sadb_msg_satype), -+ pfkey_msg->sadb_msg_len, -+ pfkey_msg->sadb_msg_reserved, -+ pfkey_msg->sadb_msg_seq, -+ pfkey_msg->sadb_msg_pid); -+ -+ extr.ips = ipsec_sa_alloc(&error); /* pass in error var by pointer */ -+ if(extr.ips == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "memory allocation error.\n"); -+ SENDERR(-error); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "allocated extr->ips=0p%p.\n", -+ extr.ips); -+ -+ if(pfkey_msg->sadb_msg_satype > SADB_SATYPE_MAX) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "satype %d > max %d\n", -+ pfkey_msg->sadb_msg_satype, -+ SADB_SATYPE_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_msg->sadb_msg_type) { -+ case SADB_GETSPI: -+ case SADB_UPDATE: -+ case SADB_ADD: -+ case SADB_DELETE: -+ case SADB_X_GRPSA: -+ case SADB_X_ADDFLOW: -+ -+ if(!(extr.ips->ips_said.proto = satype2proto(pfkey_msg->sadb_msg_satype))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "satype %d lookup failed.\n", -+ pfkey_msg->sadb_msg_satype); -+ SENDERR(EINVAL); -+ } else { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "satype %d lookups to proto=%d.\n", -+ pfkey_msg->sadb_msg_satype, -+ extr.ips->ips_said.proto); -+ } -+ break; -+ default: -+ break; -+ } -+ -+ /* The NULL below causes the default extension parsers to be used */ -+ /* Parse the extensions */ -+ if((error = pfkey_msg_parse(pfkey_msg, NULL, extensions, EXT_BITS_IN))) -+ { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "message parsing failed with error %d.\n", -+ error); -+ SENDERR(-error); -+ } -+ -+ /* Process the extensions */ -+ for(i=1; i <= SADB_EXT_MAX;i++) { -+ if(extensions[i] != NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "processing ext %d 0p%p with processor 0p%p.\n", -+ i, extensions[i], ext_processors[i]); -+ if((error = ext_processors[i](extensions[i], &extr))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "extension processing for type %d failed with error %d.\n", -+ i, -+ error); -+ SENDERR(-error); -+ } -+ -+ } -+ -+ } -+ -+ /* Parse the message types */ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "parsing message type %d(%s) with msg_parser 0p%p.\n", -+ pfkey_msg->sadb_msg_type, -+ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type), -+ msg_parsers[pfkey_msg->sadb_msg_type]); -+ if((error = msg_parsers[pfkey_msg->sadb_msg_type](sk, extensions, &extr))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "message parsing failed with error %d.\n", -+ error); -+ SENDERR(-error); -+ } -+ -+#if 0 -+ error = pfkey_build_reply(pfkey_msg, &extr, pfkey_reply); -+ if (error) { -+ *pfkey_reply = NULL; -+ } -+#endif -+ errlab: -+ if(extr.ips != NULL) { -+ ipsec_sa_wipe(extr.ips); -+ } -+ if(extr.ips2 != NULL) { -+ ipsec_sa_wipe(extr.ips2); -+ } -+ if (extr.eroute != NULL) { -+ kfree(extr.eroute); -+ } -+ return(error); -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.123 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.122.2.2 2004/04/05 04:30:46 mcr -+ * patches for alg-branch to compile/work with 2.x openswan -+ * -+ * Revision 1.122.2.1 2003/12/22 15:25:52 jjo -+ * . Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.122 2003/12/10 01:14:27 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.121 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.120.4.2 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.120.4.1 2003/09/21 13:59:56 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.120 2003/04/03 17:38:09 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * -+ * Revision 1.119 2003/02/06 01:52:37 rgb -+ * Removed no longer relevant comment -+ * -+ * Revision 1.118 2003/01/30 02:32:44 rgb -+ * -+ * Transmit error code through to caller from callee for better diagnosis of problems. -+ * -+ * Revision 1.117 2003/01/16 18:48:13 rgb -+ * -+ * Fixed sign bug in error return from an sa allocation call in -+ * pfkey_msg_interp. -+ * -+ * Revision 1.116 2002/10/17 16:38:01 rgb -+ * Change pfkey_alloc_eroute() to never static since its consumers -+ * have been moved outside the file. -+ * -+ * Revision 1.115 2002/10/12 23:11:53 dhr -+ * -+ * [KenB + DHR] more 64-bit cleanup -+ * -+ * Revision 1.114 2002/10/05 05:02:58 dhr -+ * -+ * C labels go on statements -+ * -+ * Revision 1.113 2002/09/30 19:11:22 rgb -+ * Turn on debugging for upgoing acquire messages to test for reliability. -+ * -+ * Revision 1.112 2002/09/20 15:41:16 rgb -+ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc(). -+ * Added sadb_x_sa_ref to struct sadb_sa. -+ * Added ref parameter to pfkey_sa_build(). -+ * -+ * Revision 1.111 2002/09/20 05:02:08 rgb -+ * Added memory allocation debugging. -+ * Convert to switch to divulge hmac keys for debugging. -+ * Added text labels to elucidate numeric values presented. -+ * -+ * Revision 1.110 2002/08/03 18:03:05 mcr -+ * loop that checks for SPI's to have been already linked -+ * fails to actually step to next pointer, but continuously -+ * resets to head of list. Wrong pointer used. -+ * test east-icmp-02 revealed this. -+ * -+ * Revision 1.109 2002/07/26 08:48:31 rgb -+ * Added SA ref table code. -+ * -+ * Revision 1.108 2002/05/27 18:55:03 rgb -+ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT. -+ * -+ * Revision 1.107 2002/05/23 07:16:08 rgb -+ * Added ipsec_sa_put() for releasing an ipsec_sa refcount. -+ * Pointer clean-up. -+ * Added refcount code. -+ * -+ * Revision 1.106 2002/05/14 02:34:13 rgb -+ * Converted reference from ipsec_sa_put to ipsec_sa_add to avoid confusion -+ * with "put" usage in the kernel. -+ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips, -+ * ipsec_sa or ipsec_sa. -+ * Moved all the extension parsing functions to pfkey_v2_ext_process.c. -+ * -+ * Revision 1.105 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.104 2002/04/24 07:36:34 mcr -+ * Moved from ./klips/net/ipsec/pfkey_v2_parser.c,v -+ * -+ * Revision 1.103 2002/04/20 00:12:25 rgb -+ * Added esp IV CBC attack fix, disabled. -+ * -+ * Revision 1.102 2002/03/08 01:15:17 mcr -+ * put some internal structure only debug messages behind -+ * && sysctl_ipsec_debug_verbose. -+ * -+ * Revision 1.101 2002/01/29 17:17:57 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.100 2002/01/29 04:00:54 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.99 2002/01/29 02:13:19 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.98 2002/01/12 02:57:57 mcr -+ * first regression test causes acquire messages to be lost -+ * 100% of the time. This is to help testing of pluto. -+ * -+ * Revision 1.97 2001/11/26 09:23:52 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.93.2.4 2001/10/23 04:20:27 mcr -+ * parity was forced on wrong structure! prototypes help here. -+ * -+ * Revision 1.93.2.3 2001/10/22 21:14:59 mcr -+ * include des.h, removed phony prototypes and fixed calling -+ * conventions to match real prototypes. -+ * -+ * Revision 1.93.2.2 2001/10/15 05:39:03 mcr -+ * %08lx is not the right format for u32. Use %08x. 64-bit safe? ha. -+ * -+ * Revision 1.93.2.1 2001/09/25 02:30:14 mcr -+ * struct tdb -> struct ipsec_sa. -+ * use new lifetime structure. common format routines for debug. -+ * -+ * Revision 1.96 2001/11/06 20:47:54 rgb -+ * Fixed user context call to ipsec_dev_start_xmit() bug. Call -+ * dev_queue_xmit() instead. -+ * -+ * Revision 1.95 2001/11/06 19:47:46 rgb -+ * Added packet parameter to lifetime and comb structures. -+ * -+ * Revision 1.94 2001/10/18 04:45:23 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.93 2001/09/20 15:32:59 rgb -+ * Min/max cleanup. -+ * -+ * Revision 1.92 2001/09/19 16:35:48 rgb -+ * PF_KEY ident fix for getspi from NetCelo (puttdb duplication). -+ * -+ * Revision 1.91 2001/09/15 16:24:06 rgb -+ * Re-inject first and last HOLD packet when an eroute REPLACE is done. -+ * -+ * Revision 1.90 2001/09/14 16:58:38 rgb -+ * Added support for storing the first and last packets through a HOLD. -+ * -+ * Revision 1.89 2001/09/08 21:14:07 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * Better state coherency (error management) between pf_key and IKE daemon. -+ * (NetCelo) -+ * -+ * Revision 1.88 2001/08/27 19:42:44 rgb -+ * Fix memory leak of encrypt and auth structs in pfkey register. -+ * -+ * Revision 1.87 2001/07/06 19:50:46 rgb -+ * Removed unused debugging code. -+ * Added inbound policy checking code for IPIP SAs. -+ * -+ * Revision 1.86 2001/06/20 06:26:04 rgb -+ * Changed missing SA errors from EEXIST to ENOENT and added debug output -+ * for already linked SAs. -+ * -+ * Revision 1.85 2001/06/15 04:57:02 rgb -+ * Remove single error return condition check and check for all errors in -+ * the case of a replace eroute delete operation. This means that -+ * applications must expect to be deleting something before replacing it -+ * and if nothing is found, complain. -+ * -+ * Revision 1.84 2001/06/14 19:35:12 rgb -+ * Update copyright date. -+ * -+ * Revision 1.83 2001/06/12 00:03:19 rgb -+ * Silence debug set/unset under normal conditions. -+ * -+ * Revision 1.82 2001/05/30 08:14:04 rgb -+ * Removed vestiges of esp-null transforms. -+ * -+ * Revision 1.81 2001/05/27 06:12:12 rgb -+ * Added structures for pid, packet count and last access time to eroute. -+ * Added packet count to beginning of /proc/net/ipsec_eroute. -+ * -+ * Revision 1.80 2001/05/03 19:43:59 rgb -+ * Check error return codes for all build function calls. -+ * Standardise on SENDERR() macro. -+ * -+ * Revision 1.79 2001/04/20 21:09:16 rgb -+ * Cleaned up fixed tdbwipes. -+ * Free pfkey_reply and clean up extensions_reply for grpsa, addflow and -+ * delflow (Per Cederqvist) plugging memleaks. -+ * -+ * Revision 1.78 2001/04/19 19:02:39 rgb -+ * Fixed extr.tdb freeing, stealing it for getspi, update and add. -+ * Refined a couple of spinlocks, fixed the one in update. -+ * -+ * Revision 1.77 2001/04/18 20:26:16 rgb -+ * Wipe/free eroute and both tdbs from extr at end of pfkey_msg_interp() -+ * instead of inside each message type parser. This fixes two memleaks. -+ * -+ * Revision 1.76 2001/04/17 23:51:18 rgb -+ * Quiet down pfkey_x_debug_process(). -+ * -+ * Revision 1.75 2001/03/29 01:55:05 rgb -+ * Fixed pfkey key init memleak. -+ * Fixed pfkey encryption key debug output. -+ * -+ * Revision 1.74 2001/03/27 05:29:14 rgb -+ * Debug output cleanup/silencing. -+ * -+ * Revision 1.73 2001/02/28 05:03:28 rgb -+ * Clean up and rationalise startup messages. -+ * -+ * Revision 1.72 2001/02/27 22:24:56 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.71 2001/02/27 06:59:30 rgb -+ * Added satype2name() conversions most places satype is debug printed. -+ * -+ * Revision 1.70 2001/02/26 22:37:08 rgb -+ * Fixed 'unknown proto' INT bug in new code. -+ * Added satype to protocol debugging instrumentation. -+ * -+ * Revision 1.69 2001/02/26 19:57:51 rgb -+ * Re-formatted debug output (split lines, consistent spacing). -+ * Fixed as yet undetected FLUSH bug which called ipsec_tdbcleanup() -+ * with an satype instead of proto. -+ * Checked for satype consistency and fixed minor bugs. -+ * Fixed undetected ungrpspi bug that tried to upmsg a second tdb. -+ * Check for satype sanity in pfkey_expire(). -+ * Added satype sanity check to addflow. -+ * -+ * Revision 1.68 2001/02/12 23:14:40 rgb -+ * Remove double spin lock in pfkey_expire(). -+ * -+ * Revision 1.67 2001/01/31 19:23:40 rgb -+ * Fixed double-unlock bug introduced by grpsa upmsg (found by Lars Heete). -+ * -+ * Revision 1.66 2001/01/29 22:20:04 rgb -+ * Fix minor add upmsg lifetime bug. -+ * -+ * Revision 1.65 2001/01/24 06:12:33 rgb -+ * Fixed address extension compile bugs just introduced. -+ * -+ * Revision 1.64 2001/01/24 00:31:15 rgb -+ * Added upmsg for addflow/delflow. -+ * -+ * Revision 1.63 2001/01/23 22:02:55 rgb -+ * Added upmsg to x_grpsa. -+ * Fixed lifetimes extentions to add/update/get upmsg. -+ * -+ * Revision 1.62 2000/11/30 21:47:51 rgb -+ * Fix error return bug after returning from pfkey_tdb_init(). -+ * -+ * Revision 1.61 2000/11/17 18:10:29 rgb -+ * Fixed bugs mostly relating to spirange, to treat all spi variables as -+ * network byte order since this is the way PF_KEYv2 stored spis. -+ * -+ * Revision 1.60 2000/11/06 04:34:53 rgb -+ * Changed non-exported functions to DEBUG_NO_STATIC. -+ * Add Svenning's adaptive content compression. -+ * Ditched spin_lock_irqsave in favour of spin_lock/_bh. -+ * Fixed double unlock bug (Svenning). -+ * Fixed pfkey_msg uninitialized bug in pfkey_{expire,acquire}(). -+ * Fixed incorrect extension type (prop) in pfkey)acquire(). -+ * -+ * Revision 1.59 2000/10/11 15:25:12 rgb -+ * Fixed IPCOMP disabled compile bug. -+ * -+ * Revision 1.58 2000/10/11 14:54:03 rgb -+ * Fixed pfkey_acquire() satype to SADB_SATYPE_ESP and removed pfkey -+ * protocol violations of setting pfkey_address_build() protocol parameter -+ * to non-zero except in the case of pfkey_acquire(). -+ * -+ * Revision 1.57 2000/10/10 20:10:18 rgb -+ * Added support for debug_ipcomp and debug_verbose to klipsdebug. -+ * -+ * Revision 1.56 2000/10/06 20:24:36 rgb -+ * Fixes to pfkey_acquire to initialize extensions[] and use correct -+ * ipproto. -+ * -+ * Revision 1.55 2000/10/03 03:20:57 rgb -+ * Added brackets to get a?b:c scope right for pfkey_register reply. -+ * -+ * Revision 1.54 2000/09/29 19:49:30 rgb -+ * As-yet-unused-bits cleanup. -+ * -+ * Revision 1.53 2000/09/28 00:35:45 rgb -+ * Padded SATYPE printout in pfkey_register for vertical alignment. -+ * -+ * Revision 1.52 2000/09/20 16:21:58 rgb -+ * Cleaned up ident string alloc/free. -+ * -+ * Revision 1.51 2000/09/20 04:04:20 rgb -+ * Changed static functions to DEBUG_NO_STATIC to reveal function names in -+ * oopsen. -+ * -+ * Revision 1.50 2000/09/16 01:10:53 rgb -+ * Fixed unused var warning with debug off. -+ * -+ * Revision 1.49 2000/09/15 11:37:02 rgb -+ * Merge in heavily modified Svenning Soerensen's -+ * IPCOMP zlib deflate code. -+ * -+ * Revision 1.48 2000/09/15 04:57:57 rgb -+ * Cleaned up existing IPCOMP code before svenning addition. -+ * Initialize pfkey_reply and extensions_reply in case of early error in -+ * message parsing functions (thanks Kai!). -+ * -+ * Revision 1.47 2000/09/13 08:02:56 rgb -+ * Added KMd registration notification. -+ * -+ * Revision 1.46 2000/09/12 22:35:36 rgb -+ * Restructured to remove unused extensions from CLEARFLOW messages. -+ * -+ * Revision 1.45 2000/09/12 03:24:23 rgb -+ * Converted #if0 debugs to sysctl. -+ * -+ * Revision 1.44 2000/09/09 06:38:39 rgb -+ * Correct SADB message type for update, add and delete. -+ * -+ * Revision 1.43 2000/09/08 19:19:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * Removed all references to CONFIG_IPSEC_PFKEYv2. -+ * Put in sanity checks in most msg type parsers to catch invalid satypes -+ * and empty socket lists. -+ * Moved spin-locks in pfkey_get_parse() to simplify. -+ * Added pfkey_acquire(). -+ * Added upwards messages to update, add, delete, acquire_parse, -+ * expire_parse and flush. -+ * Fix pfkey_prop_build() parameter to be only single indirection. -+ * Changed all replies to use pfkey_reply. -+ * Check return code on puttdb() and deltdbchain() in getspi, update, -+ * add, delete. -+ * Fixed up all pfkey replies to open and registered sockets. -+ * -+ * Revision 1.42 2000/09/01 18:50:26 rgb -+ * Added a supported algorithms array lists, one per satype and registered -+ * existing algorithms. -+ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to -+ * list. -+ * Only send pfkey_expire() messages to sockets registered for that satype. -+ * Added reply to pfkey_getspi_parse(). -+ * Added reply to pfkey_get_parse(). -+ * Fixed debug output label bug in pfkey_lifetime_process(). -+ * Cleaned up pfkey_sa_process a little. -+ * Moved pfkey_safe_build() above message type parsers to make it available -+ * for creating replies. -+ * Added comments for future work in pfkey_acquire_parse(). -+ * Fleshed out guts of pfkey_register_parse(). -+ * -+ * Revision 1.41 2000/08/24 16:58:11 rgb -+ * Fixed key debugging variables. -+ * Fixed error return code for a failed search. -+ * Changed order of pfkey_get operations. -+ * -+ * Revision 1.40 2000/08/21 16:32:27 rgb -+ * Re-formatted for cosmetic consistency and readability. -+ * -+ * Revision 1.39 2000/08/20 21:38:57 rgb -+ * Bugfixes to as-yet-unused pfkey_update_parse() and -+ * pfkey_register_parse(). (Momchil) -+ * Added functions pfkey_safe_build(), pfkey_expire() and -+ * pfkey_build_reply(). (Momchil) -+ * Added a pfkey_reply parameter to pfkey_msg_interp(). (Momchil) -+ * -+ * Revision 1.38 2000/08/18 21:30:41 rgb -+ * Purged all tdb_spi, tdb_proto and tdb_dst macros. They are unclear. -+ * -+ * Revision 1.37 2000/08/18 18:18:02 rgb -+ * Cosmetic and descriptive changes made to debug test. -+ * getspi and update fixes from Momchil. -+ * -+ * Revision 1.36 2000/08/15 15:41:55 rgb -+ * Fixed the (as yet unused and untested) pfkey_getspi() routine. -+ * -+ * Revision 1.35 2000/08/01 14:51:52 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.34 2000/07/28 14:58:32 rgb -+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. -+ * -+ * Revision 1.33 2000/06/28 05:50:11 rgb -+ * Actually set iv_bits. -+ * -+ * Revision 1.32 2000/05/30 18:36:56 rgb -+ * Fix AH auth hash setup bug. This breaks interop with previous PF_KEY -+ * FreeS/WAN, but fixes interop with other implementations. -+ * -+ * Revision 1.31 2000/03/16 14:05:48 rgb -+ * Fixed brace scope preventing non-debug compile. -+ * Added null parameter check for pfkey_x_debug(). -+ * -+ * Revision 1.30 2000/01/22 23:21:13 rgb -+ * Use new function satype2proto(). -+ * -+ * Revision 1.29 2000/01/22 08:40:21 rgb -+ * Invert condition to known value to avoid AF_INET6 in 2.0.36. -+ * -+ * Revision 1.28 2000/01/22 07:58:57 rgb -+ * Fixed REPLACEFLOW bug, missing braces around KLIPS_PRINT *and* SENDERR. -+ * -+ * Revision 1.27 2000/01/22 03:48:01 rgb -+ * Added extr pointer component debugging. -+ * -+ * Revision 1.26 2000/01/21 09:41:25 rgb -+ * Changed a (void*) to (char*) cast to do proper pointer math. -+ * Don't call tdbwipe if tdb2 is NULL. -+ * -+ * Revision 1.25 2000/01/21 06:21:01 rgb -+ * Added address cases for eroute flows. -+ * Tidied up compiler directive indentation for readability. -+ * Added ictx,octx vars for simplification. -+ * Added macros for HMAC padding magic numbers. -+ * Converted from double tdb arguments to one structure (extr) -+ * containing pointers to all temporary information structures -+ * and checking for valid arguments to all ext processors and -+ * msg type parsers. -+ * Added spiungrp'ing. -+ * Added klipsdebug switching capability. -+ * Removed sa_process() check for zero protocol. -+ * Added address case for DST2 for grouping. -+ * Added/changed minor debugging instrumentation. -+ * Fixed spigrp for single said, ungrouping case. -+ * Added code to parse addflow and delflow messages. -+ * Removed redundant statements duplicating tdbwipe() functionality -+ * and causing double kfrees. -+ * Permit addflow to have a protocol of 0. -+ * -+ * Revision 1.24 1999/12/09 23:23:00 rgb -+ * Added check to pfkey_sa_process() to do eroutes. -+ * Converted to DIVUP() macro. -+ * Converted if() to switch() in pfkey_register_parse(). -+ * Use new pfkey_extensions_init() instead of memset(). -+ * -+ * Revision 1.23 1999/12/01 22:18:13 rgb -+ * Preset minspi and maxspi values in case and spirange extension is not -+ * included and check for the presence of an spirange extension before -+ * using it. Initialise tdb_sastate to LARVAL. -+ * Fixed debugging output typo. -+ * Fixed authentication context initialisation bugs (4 places). -+ * -+ * Revision 1.22 1999/11/27 11:53:08 rgb -+ * Moved pfkey_msg_parse prototype to pfkey.h -+ * Moved exts_permitted/required prototype to pfkey.h. -+ * Moved sadb_satype2proto protocol lookup table to lib/pfkey_v2_parse.c. -+ * Deleted SADB_X_EXT_SA2 code from pfkey_sa_process() since it will never -+ * be called. -+ * Moved protocol/algorithm checks to lib/pfkey_v2_parse.c -+ * Debugging error messages added. -+ * Enable lifetime_current checking. -+ * Remove illegal requirement for SA extension to be present in an -+ * originating GETSPI call. -+ * Re-instate requirement for UPDATE or ADD message to be MATURE. -+ * Add argument to pfkey_msg_parse() for direction. -+ * Fixed IPIP dst address bug and purged redundant, leaky code. -+ * -+ * Revision 1.21 1999/11/24 05:24:20 rgb -+ * hanged 'void*extensions' to 'struct sadb_ext*extensions'. -+ * Fixed indention. -+ * Ditched redundant replay check. -+ * Fixed debug message text from 'parse' to 'process'. -+ * Added more debug output. -+ * Forgot to zero extensions array causing bug, fixed. -+ * -+ * Revision 1.20 1999/11/23 23:08:13 rgb -+ * Move all common parsing code to lib/pfkey_v2_parse.c and rename -+ * remaining bits to *_process. (PJO) -+ * Add macros for dealing with alignment and rounding up more opaquely. -+ * Use provided macro ADDRTOA_BUF instead of hardcoded value. -+ * Sort out pfkey and freeswan headers, putting them in a library path. -+ * Corrected a couple of bugs in as-yet-inactive code. -+ * -+ * Revision 1.19 1999/11/20 22:01:10 rgb -+ * Add more descriptive error messages for non-zero reserved fields. -+ * Add more descriptive error message for spirange parsing. -+ * Start on supported extension parsing. -+ * Start on register and get message parsing. -+ * -+ * Revision 1.18 1999/11/18 04:09:20 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.17 1999/11/17 15:53:41 rgb -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * -+ * Revision 1.16 1999/10/26 16:57:43 rgb -+ * Add shorter macros for compiler directives to visually clean-up. -+ * Give ipv6 code meaningful compiler directive. -+ * Add comments to other #if 0 debug code. -+ * Remove unused *_bh_atomic() calls. -+ * Fix mis-placed spinlock. -+ * -+ * Revision 1.15 1999/10/16 18:27:10 rgb -+ * Clean-up unused cruft. -+ * Fix-up lifetime_allocations_c and lifetime_addtime_c initialisations. -+ * -+ * Revision 1.14 1999/10/08 18:37:34 rgb -+ * Fix end-of-line spacing to sate whining PHMs. -+ * -+ * Revision 1.13 1999/10/03 18:49:12 rgb -+ * Spinlock fixes for 2.0.xx and 2.3.xx. -+ * -+ * Revision 1.12 1999/10/01 15:44:54 rgb -+ * Move spinlock header include to 2.1> scope. -+ * -+ * Revision 1.11 1999/10/01 00:05:45 rgb -+ * Added tdb structure locking. -+ * Use 'jiffies' instead of do_get_timeofday(). -+ * Fix lifetime assignments. -+ * -+ * Revision 1.10 1999/09/21 15:24:45 rgb -+ * Rework spirange code to save entropy and prevent endless loops. -+ * -+ * Revision 1.9 1999/09/16 12:10:21 rgb -+ * Minor fixes to random spi selection for correctness and entropy conservation. -+ * -+ * Revision 1.8 1999/05/25 22:54:46 rgb -+ * Fix comparison that should be an assignment in an if. -+ * -+ * Revision 1.7 1999/05/09 03:25:37 rgb -+ * Fix bug introduced by 2.2 quick-and-dirty patch. -+ * -+ * Revision 1.6 1999/05/08 21:32:30 rgb -+ * Fix error return reporting. -+ * -+ * Revision 1.5 1999/05/05 22:02:33 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.4 1999/04/29 15:22:40 rgb -+ * Standardise an error return method. -+ * Add debugging instrumentation. -+ * Add check for existence of macros min/max. -+ * Add extensions permitted/required in/out filters. -+ * Add satype-to-protocol table. -+ * Add a second tdb pointer to each parser to accomodate GRPSA. -+ * Move AH & no_algo_set to GETSPI, UPDATE and ADD. -+ * Add OOO window check. -+ * Add support for IPPROTO_IPIP and hooks for IPPROTO_COMP. -+ * Add timestamp to lifetime parse. -+ * Fix address structure length checking bug. -+ * Fix address structure allocation bug (forgot to kmalloc!). -+ * Add checks for extension lengths. -+ * Add checks for extension reserved illegal values. -+ * Add check for spirange legal values. -+ * Add an extension type for parsing a second satype, SA and -+ * DST_ADDRESS. -+ * Make changes to tdb_init() template to get pfkey_tdb_init(), -+ * eliminating any mention of xformsw. -+ * Implement getspi, update and grpsa (not tested). -+ * Add stubs for as yet unimplemented message types. -+ * Add table of message parsers to substitute for msg_parse switch. -+ * -+ * Revision 1.3 1999/04/15 17:58:07 rgb -+ * Add RCSID labels. -+ * -+ * Revision 1.2 1999/04/15 15:37:26 rgb -+ * Forward check changes from POST1_00 branch. -+ * -+ * Revision 1.1.2.1 1999/03/26 20:58:56 rgb -+ * Add pfkeyv2 support to KLIPS. -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/radij.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1225 @@ -+char radij_c_version[] = "RCSID $Id$"; -+ -+/* -+ * This file is defived from ${SRC}/sys/net/radix.c of BSD 4.4lite -+ * -+ * Variable and procedure names have been modified so that they don't -+ * conflict with the original BSD code, as a small number of modifications -+ * have been introduced and we may want to reuse this code in BSD. -+ * -+ * The `j' in `radij' is pronounced as a voiceless guttural (like a Greek -+ * chi or a German ch sound (as `doch', not as in `milch'), or even a -+ * spanish j as in Juan. It is not as far back in the throat like -+ * the corresponding Hebrew sound, nor is it a soft breath like the English h. -+ * It has nothing to do with the Dutch ij sound. -+ * -+ * Here is the appropriate copyright notice: -+ */ -+ -+/* -+ * Copyright (c) 1988, 1989, 1993 -+ * The Regents of the University of California. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * This product includes software developed by the University of -+ * California, Berkeley and its contributors. -+ * 4. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * @(#)radix.c 8.2 (Berkeley) 1/4/94 -+ */ -+ -+/* -+ * Routines to build and maintain radix trees for routing lookups. -+ */ -+ -+#include -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#ifdef NET_21 -+# include -+# include -+#endif /* NET_21 */ -+#include -+#include -+ -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+ -+int maj_keylen; -+struct radij_mask *rj_mkfreelist; -+struct radij_node_head *mask_rjhead; -+static int gotOddMasks; -+static char *maskedKey; -+static char *rj_zeroes, *rj_ones; -+ -+#define rj_masktop (mask_rjhead->rnh_treetop) -+#ifdef Bcmp -+# undef Bcmp -+#endif /* Bcmp */ -+#define Bcmp(a, b, l) (l == 0 ? 0 : memcmp((caddr_t)(b), (caddr_t)(a), (size_t)l)) -+/* -+ * The data structure for the keys is a radix tree with one way -+ * branching removed. The index rj_b at an internal node n represents a bit -+ * position to be tested. The tree is arranged so that all descendants -+ * of a node n have keys whose bits all agree up to position rj_b - 1. -+ * (We say the index of n is rj_b.) -+ * -+ * There is at least one descendant which has a one bit at position rj_b, -+ * and at least one with a zero there. -+ * -+ * A route is determined by a pair of key and mask. We require that the -+ * bit-wise logical and of the key and mask to be the key. -+ * We define the index of a route to associated with the mask to be -+ * the first bit number in the mask where 0 occurs (with bit number 0 -+ * representing the highest order bit). -+ * -+ * We say a mask is normal if every bit is 0, past the index of the mask. -+ * If a node n has a descendant (k, m) with index(m) == index(n) == rj_b, -+ * and m is a normal mask, then the route applies to every descendant of n. -+ * If the index(m) < rj_b, this implies the trailing last few bits of k -+ * before bit b are all 0, (and hence consequently true of every descendant -+ * of n), so the route applies to all descendants of the node as well. -+ * -+ * The present version of the code makes no use of normal routes, -+ * but similar logic shows that a non-normal mask m such that -+ * index(m) <= index(n) could potentially apply to many children of n. -+ * Thus, for each non-host route, we attach its mask to a list at an internal -+ * node as high in the tree as we can go. -+ */ -+ -+struct radij_node * -+rj_search(v_arg, head) -+ void *v_arg; -+ struct radij_node *head; -+{ -+ register struct radij_node *x; -+ register caddr_t v; -+ -+ for (x = head, v = v_arg; x->rj_b >= 0;) { -+ if (x->rj_bmask & v[x->rj_off]) -+ x = x->rj_r; -+ else -+ x = x->rj_l; -+ } -+ return (x); -+}; -+ -+struct radij_node * -+rj_search_m(v_arg, head, m_arg) -+ struct radij_node *head; -+ void *v_arg, *m_arg; -+{ -+ register struct radij_node *x; -+ register caddr_t v = v_arg, m = m_arg; -+ -+ for (x = head; x->rj_b >= 0;) { -+ if ((x->rj_bmask & m[x->rj_off]) && -+ (x->rj_bmask & v[x->rj_off])) -+ x = x->rj_r; -+ else -+ x = x->rj_l; -+ } -+ return x; -+}; -+ -+int -+rj_refines(m_arg, n_arg) -+ void *m_arg, *n_arg; -+{ -+ register caddr_t m = m_arg, n = n_arg; -+ register caddr_t lim, lim2 = lim = n + *(u_char *)n; -+ int longer = (*(u_char *)n++) - (int)(*(u_char *)m++); -+ int masks_are_equal = 1; -+ -+ if (longer > 0) -+ lim -= longer; -+ while (n < lim) { -+ if (*n & ~(*m)) -+ return 0; -+ if (*n++ != *m++) -+ masks_are_equal = 0; -+ -+ } -+ while (n < lim2) -+ if (*n++) -+ return 0; -+ if (masks_are_equal && (longer < 0)) -+ for (lim2 = m - longer; m < lim2; ) -+ if (*m++) -+ return 1; -+ return (!masks_are_equal); -+} -+ -+ -+struct radij_node * -+rj_match(v_arg, head) -+ void *v_arg; -+ struct radij_node_head *head; -+{ -+ caddr_t v = v_arg; -+ register struct radij_node *t = head->rnh_treetop, *x; -+ register caddr_t cp = v, cp2, cp3; -+ caddr_t cplim, mstart; -+ struct radij_node *saved_t, *top = t; -+ int off = t->rj_off, vlen = *(u_char *)cp, matched_off; -+ -+ /* -+ * Open code rj_search(v, top) to avoid overhead of extra -+ * subroutine call. -+ */ -+ for (; t->rj_b >= 0; ) { -+ if (t->rj_bmask & cp[t->rj_off]) -+ t = t->rj_r; -+ else -+ t = t->rj_l; -+ } -+ /* -+ * See if we match exactly as a host destination -+ */ -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:rj_match: " -+ "* See if we match exactly as a host destination\n"); -+ -+ cp += off; cp2 = t->rj_key + off; cplim = v + vlen; -+ for (; cp < cplim; cp++, cp2++) -+ if (*cp != *cp2) -+ goto on1; -+ /* -+ * This extra grot is in case we are explicitly asked -+ * to look up the default. Ugh! -+ */ -+ if ((t->rj_flags & RJF_ROOT) && t->rj_dupedkey) -+ t = t->rj_dupedkey; -+ return t; -+on1: -+ matched_off = cp - v; -+ saved_t = t; -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:rj_match: " -+ "** try to match a leaf, t=0p%p\n", t); -+ do { -+ if (t->rj_mask) { -+ /* -+ * Even if we don't match exactly as a hosts; -+ * we may match if the leaf we wound up at is -+ * a route to a net. -+ */ -+ cp3 = matched_off + t->rj_mask; -+ cp2 = matched_off + t->rj_key; -+ for (; cp < cplim; cp++) -+ if ((*cp2++ ^ *cp) & *cp3++) -+ break; -+ if (cp == cplim) -+ return t; -+ cp = matched_off + v; -+ } -+ } while ((t = t->rj_dupedkey)); -+ t = saved_t; -+ /* start searching up the tree */ -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:rj_match: " -+ "*** start searching up the tree, t=0p%p\n", -+ t); -+ do { -+ register struct radij_mask *m; -+ -+ t = t->rj_p; -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:rj_match: " -+ "**** t=0p%p\n", -+ t); -+ if ((m = t->rj_mklist)) { -+ /* -+ * After doing measurements here, it may -+ * turn out to be faster to open code -+ * rj_search_m here instead of always -+ * copying and masking. -+ */ -+ /* off = min(t->rj_off, matched_off); */ -+ off = t->rj_off; -+ if (matched_off < off) -+ off = matched_off; -+ mstart = maskedKey + off; -+ do { -+ cp2 = mstart; -+ cp3 = m->rm_mask + off; -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:rj_match: " -+ "***** cp2=0p%p cp3=0p%p\n", -+ cp2, cp3); -+ for (cp = v + off; cp < cplim;) -+ *cp2++ = *cp++ & *cp3++; -+ x = rj_search(maskedKey, t); -+ while (x && x->rj_mask != m->rm_mask) -+ x = x->rj_dupedkey; -+ if (x && -+ (Bcmp(mstart, x->rj_key + off, -+ vlen - off) == 0)) -+ return x; -+ } while ((m = m->rm_mklist)); -+ } -+ } while (t != top); -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:rj_match: " -+ "***** not found.\n"); -+ return 0; -+}; -+ -+#ifdef RJ_DEBUG -+int rj_nodenum; -+struct radij_node *rj_clist; -+int rj_saveinfo; -+DEBUG_NO_STATIC void traverse(struct radij_node *); -+#ifdef RJ_DEBUG2 -+int rj_debug = 1; -+#else -+int rj_debug = 0; -+#endif /* RJ_DEBUG2 */ -+#endif /* RJ_DEBUG */ -+ -+struct radij_node * -+rj_newpair(v, b, nodes) -+ void *v; -+ int b; -+ struct radij_node nodes[2]; -+{ -+ register struct radij_node *tt = nodes, *t = tt + 1; -+ t->rj_b = b; t->rj_bmask = 0x80 >> (b & 7); -+ t->rj_l = tt; t->rj_off = b >> 3; -+ tt->rj_b = -1; tt->rj_key = (caddr_t)v; tt->rj_p = t; -+ tt->rj_flags = t->rj_flags = RJF_ACTIVE; -+#ifdef RJ_DEBUG -+ tt->rj_info = rj_nodenum++; t->rj_info = rj_nodenum++; -+ tt->rj_twin = t; tt->rj_ybro = rj_clist; rj_clist = tt; -+#endif /* RJ_DEBUG */ -+ return t; -+} -+ -+struct radij_node * -+rj_insert(v_arg, head, dupentry, nodes) -+ void *v_arg; -+ struct radij_node_head *head; -+ int *dupentry; -+ struct radij_node nodes[2]; -+{ -+ caddr_t v = v_arg; -+ struct radij_node *top = head->rnh_treetop; -+ int head_off = top->rj_off, vlen = (int)*((u_char *)v); -+ register struct radij_node *t = rj_search(v_arg, top); -+ register caddr_t cp = v + head_off; -+ register int b; -+ struct radij_node *tt; -+ /* -+ *find first bit at which v and t->rj_key differ -+ */ -+ { -+ register caddr_t cp2 = t->rj_key + head_off; -+ register int cmp_res; -+ caddr_t cplim = v + vlen; -+ -+ while (cp < cplim) -+ if (*cp2++ != *cp++) -+ goto on1; -+ *dupentry = 1; -+ return t; -+on1: -+ *dupentry = 0; -+ cmp_res = (cp[-1] ^ cp2[-1]) & 0xff; -+ for (b = (cp - v) << 3; cmp_res; b--) -+ cmp_res >>= 1; -+ } -+ { -+ register struct radij_node *p, *x = top; -+ cp = v; -+ do { -+ p = x; -+ if (cp[x->rj_off] & x->rj_bmask) -+ x = x->rj_r; -+ else x = x->rj_l; -+ } while (b > (unsigned) x->rj_b); /* x->rj_b < b && x->rj_b >= 0 */ -+#ifdef RJ_DEBUG -+ if (rj_debug) -+ printk("klips_debug:rj_insert: Going In:\n"), traverse(p); -+#endif /* RJ_DEBUG */ -+ t = rj_newpair(v_arg, b, nodes); tt = t->rj_l; -+ if ((cp[p->rj_off] & p->rj_bmask) == 0) -+ p->rj_l = t; -+ else -+ p->rj_r = t; -+ x->rj_p = t; t->rj_p = p; /* frees x, p as temp vars below */ -+ if ((cp[t->rj_off] & t->rj_bmask) == 0) { -+ t->rj_r = x; -+ } else { -+ t->rj_r = tt; t->rj_l = x; -+ } -+#ifdef RJ_DEBUG -+ if (rj_debug) -+ printk("klips_debug:rj_insert: Coming out:\n"), traverse(p); -+#endif /* RJ_DEBUG */ -+ } -+ return (tt); -+} -+ -+struct radij_node * -+rj_addmask(n_arg, search, skip) -+ int search, skip; -+ void *n_arg; -+{ -+ caddr_t netmask = (caddr_t)n_arg; -+ register struct radij_node *x; -+ register caddr_t cp, cplim; -+ register int b, mlen, j; -+ int maskduplicated; -+ -+ mlen = *(u_char *)netmask; -+ if (search) { -+ x = rj_search(netmask, rj_masktop); -+ mlen = *(u_char *)netmask; -+ if (Bcmp(netmask, x->rj_key, mlen) == 0) -+ return (x); -+ } -+ R_Malloc(x, struct radij_node *, maj_keylen + 2 * sizeof (*x)); -+ if (x == 0) -+ return (0); -+ Bzero(x, maj_keylen + 2 * sizeof (*x)); -+ cp = (caddr_t)(x + 2); -+ Bcopy(netmask, cp, mlen); -+ netmask = cp; -+ x = rj_insert(netmask, mask_rjhead, &maskduplicated, x); -+ /* -+ * Calculate index of mask. -+ */ -+ cplim = netmask + mlen; -+ for (cp = netmask + skip; cp < cplim; cp++) -+ if (*(u_char *)cp != 0xff) -+ break; -+ b = (cp - netmask) << 3; -+ if (cp != cplim) { -+ if (*cp != 0) { -+ gotOddMasks = 1; -+ for (j = 0x80; j; b++, j >>= 1) -+ if ((j & *cp) == 0) -+ break; -+ } -+ } -+ x->rj_b = -1 - b; -+ return (x); -+} -+ -+#if 0 -+struct radij_node * -+#endif -+int -+rj_addroute(v_arg, n_arg, head, treenodes) -+ void *v_arg, *n_arg; -+ struct radij_node_head *head; -+ struct radij_node treenodes[2]; -+{ -+ caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg; -+ register struct radij_node *t, *x=NULL, *tt; -+ struct radij_node *saved_tt, *top = head->rnh_treetop; -+ short b = 0, b_leaf; -+ int mlen, keyduplicated; -+ caddr_t cplim; -+ struct radij_mask *m, **mp; -+ -+ /* -+ * In dealing with non-contiguous masks, there may be -+ * many different routes which have the same mask. -+ * We will find it useful to have a unique pointer to -+ * the mask to speed avoiding duplicate references at -+ * nodes and possibly save time in calculating indices. -+ */ -+ if (netmask) { -+ x = rj_search(netmask, rj_masktop); -+ mlen = *(u_char *)netmask; -+ if (Bcmp(netmask, x->rj_key, mlen) != 0) { -+ x = rj_addmask(netmask, 0, top->rj_off); -+ if (x == 0) -+ return -ENOMEM; /* (0) rgb */ -+ } -+ netmask = x->rj_key; -+ b = -1 - x->rj_b; -+ } -+ /* -+ * Deal with duplicated keys: attach node to previous instance -+ */ -+ saved_tt = tt = rj_insert(v, head, &keyduplicated, treenodes); -+#ifdef RJ_DEBUG -+ printk("addkey: duplicated: %d\n", keyduplicated); -+#endif -+ if (keyduplicated) { -+ do { -+ if (tt->rj_mask == netmask) -+ return -EEXIST; /* -ENXIO; (0) rgb */ -+ t = tt; -+ if (netmask == 0 || -+ (tt->rj_mask && rj_refines(netmask, tt->rj_mask))) -+ break; -+ } while ((tt = tt->rj_dupedkey)); -+ /* -+ * If the mask is not duplicated, we wouldn't -+ * find it among possible duplicate key entries -+ * anyway, so the above test doesn't hurt. -+ * -+ * We sort the masks for a duplicated key the same way as -+ * in a masklist -- most specific to least specific. -+ * This may require the unfortunate nuisance of relocating -+ * the head of the list. -+ */ -+ if (tt && t == saved_tt) { -+ struct radij_node *xx = x; -+ /* link in at head of list */ -+ (tt = treenodes)->rj_dupedkey = t; -+ tt->rj_flags = t->rj_flags; -+ tt->rj_p = x = t->rj_p; -+ if (x->rj_l == t) x->rj_l = tt; else x->rj_r = tt; -+ saved_tt = tt; x = xx; -+ } else { -+ (tt = treenodes)->rj_dupedkey = t->rj_dupedkey; -+ t->rj_dupedkey = tt; -+ } -+#ifdef RJ_DEBUG -+ t=tt+1; tt->rj_info = rj_nodenum++; t->rj_info = rj_nodenum++; -+ tt->rj_twin = t; tt->rj_ybro = rj_clist; rj_clist = tt; -+#endif /* RJ_DEBUG */ -+ t = saved_tt; -+ tt->rj_key = (caddr_t) v; -+ tt->rj_b = -1; -+ tt->rj_flags = t->rj_flags & ~RJF_ROOT; -+ } -+ /* -+ * Put mask in tree. -+ */ -+ if (netmask) { -+ tt->rj_mask = netmask; -+ tt->rj_b = x->rj_b; -+ } -+ t = saved_tt->rj_p; -+ b_leaf = -1 - t->rj_b; -+ if (t->rj_r == saved_tt) x = t->rj_l; else x = t->rj_r; -+ /* Promote general routes from below */ -+ if (x->rj_b < 0) { -+ if (x->rj_mask && (x->rj_b >= b_leaf) && x->rj_mklist == 0) { -+ MKGet(m); -+ if (m) { -+ Bzero(m, sizeof *m); -+ m->rm_b = x->rj_b; -+ m->rm_mask = x->rj_mask; -+ x->rj_mklist = t->rj_mklist = m; -+ } -+ } -+ } else if (x->rj_mklist) { -+ /* -+ * Skip over masks whose index is > that of new node -+ */ -+ for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist) -+ if (m->rm_b >= b_leaf) -+ break; -+ t->rj_mklist = m; *mp = 0; -+ } -+ /* Add new route to highest possible ancestor's list */ -+ if ((netmask == 0) || (b > t->rj_b )) { -+#ifdef RJ_DEBUG -+ printk("klips:radij.c: netmask = %p or b(%d)>t->rjb(%d)\n", netmask, b, t->rj_b); -+#endif -+ return 0; /* tt rgb */ /* can't lift at all */ -+ } -+ b_leaf = tt->rj_b; -+ do { -+ x = t; -+ t = t->rj_p; -+ } while (b <= t->rj_b && x != top); -+ /* -+ * Search through routes associated with node to -+ * insert new route according to index. -+ * For nodes of equal index, place more specific -+ * masks first. -+ */ -+ cplim = netmask + mlen; -+ for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist) { -+ if (m->rm_b < b_leaf) -+ continue; -+ if (m->rm_b > b_leaf) -+ break; -+ if (m->rm_mask == netmask) { -+ m->rm_refs++; -+ tt->rj_mklist = m; -+#ifdef RJ_DEBUG -+ printk("klips:radij.c: m->rm_mask %p == netmask\n", netmask); -+#endif -+ return 0; /* tt rgb */ -+ } -+ if (rj_refines(netmask, m->rm_mask)) -+ break; -+ } -+ MKGet(m); -+ if (m == 0) { -+ printk("klips_debug:rj_addroute: " -+ "Mask for route not entered\n"); -+ return 0; /* (tt) rgb */ -+ } -+ Bzero(m, sizeof *m); -+ m->rm_b = b_leaf; -+ m->rm_mask = netmask; -+ m->rm_mklist = *mp; -+ *mp = m; -+ tt->rj_mklist = m; -+#ifdef RJ_DEBUG -+ printk("klips:radij.c: addroute done\n"); -+#endif -+ return 0; /* tt rgb */ -+} -+ -+int -+rj_delete(v_arg, netmask_arg, head, node) -+ void *v_arg, *netmask_arg; -+ struct radij_node_head *head; -+ struct radij_node **node; -+{ -+ register struct radij_node *t, *p, *x, *tt; -+ struct radij_mask *m, *saved_m, **mp; -+ struct radij_node *dupedkey, *saved_tt, *top; -+ caddr_t v, netmask; -+ int b, head_off, vlen; -+ -+ v = v_arg; -+ netmask = netmask_arg; -+ x = head->rnh_treetop; -+ tt = rj_search(v, x); -+ head_off = x->rj_off; -+ vlen = *(u_char *)v; -+ saved_tt = tt; -+ top = x; -+ if (tt == 0 || -+ Bcmp(v + head_off, tt->rj_key + head_off, vlen - head_off)) -+ return -EFAULT; /* (0) rgb */ -+ /* -+ * Delete our route from mask lists. -+ */ -+ if ((dupedkey = tt->rj_dupedkey)) { -+ if (netmask) -+ netmask = rj_search(netmask, rj_masktop)->rj_key; -+ while (tt->rj_mask != netmask) -+ if ((tt = tt->rj_dupedkey) == 0) -+ return -ENOENT; /* -ENXIO; (0) rgb */ -+ } -+ if (tt->rj_mask == 0 || (saved_m = m = tt->rj_mklist) == 0) -+ goto on1; -+ if (m->rm_mask != tt->rj_mask) { -+ printk("klips_debug:rj_delete: " -+ "inconsistent annotation\n"); -+ goto on1; -+ } -+ if (--m->rm_refs >= 0) -+ goto on1; -+ b = -1 - tt->rj_b; -+ t = saved_tt->rj_p; -+ if (b > t->rj_b) -+ goto on1; /* Wasn't lifted at all */ -+ do { -+ x = t; -+ t = t->rj_p; -+ } while (b <= t->rj_b && x != top); -+ for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist) -+ if (m == saved_m) { -+ *mp = m->rm_mklist; -+ MKFree(m); -+ break; -+ } -+ if (m == 0) -+ printk("klips_debug:rj_delete: " -+ "couldn't find our annotation\n"); -+on1: -+ /* -+ * Eliminate us from tree -+ */ -+ if (tt->rj_flags & RJF_ROOT) -+ return -EFAULT; /* (0) rgb */ -+#ifdef RJ_DEBUG -+ /* Get us out of the creation list */ -+ for (t = rj_clist; t && t->rj_ybro != tt; t = t->rj_ybro) {} -+ if (t) t->rj_ybro = tt->rj_ybro; -+#endif /* RJ_DEBUG */ -+ t = tt->rj_p; -+ if (dupedkey) { -+ if (tt == saved_tt) { -+ x = dupedkey; x->rj_p = t; -+ if (t->rj_l == tt) t->rj_l = x; else t->rj_r = x; -+ } else { -+ for (x = p = saved_tt; p && p->rj_dupedkey != tt;) -+ p = p->rj_dupedkey; -+ if (p) p->rj_dupedkey = tt->rj_dupedkey; -+ else printk("klips_debug:rj_delete: " -+ "couldn't find node that we started with\n"); -+ } -+ t = tt + 1; -+ if (t->rj_flags & RJF_ACTIVE) { -+#ifndef RJ_DEBUG -+ *++x = *t; p = t->rj_p; -+#else -+ b = t->rj_info; *++x = *t; t->rj_info = b; p = t->rj_p; -+#endif /* RJ_DEBUG */ -+ if (p->rj_l == t) p->rj_l = x; else p->rj_r = x; -+ x->rj_l->rj_p = x; x->rj_r->rj_p = x; -+ } -+ goto out; -+ } -+ if (t->rj_l == tt) x = t->rj_r; else x = t->rj_l; -+ p = t->rj_p; -+ if (p->rj_r == t) p->rj_r = x; else p->rj_l = x; -+ x->rj_p = p; -+ /* -+ * Demote routes attached to us. -+ */ -+ if (t->rj_mklist) { -+ if (x->rj_b >= 0) { -+ for (mp = &x->rj_mklist; (m = *mp);) -+ mp = &m->rm_mklist; -+ *mp = t->rj_mklist; -+ } else { -+ for (m = t->rj_mklist; m;) { -+ struct radij_mask *mm = m->rm_mklist; -+ if (m == x->rj_mklist && (--(m->rm_refs) < 0)) { -+ x->rj_mklist = 0; -+ MKFree(m); -+ } else -+ printk("klips_debug:rj_delete: " -+ "Orphaned Mask 0p%p at 0p%p\n", m, x); -+ m = mm; -+ } -+ } -+ } -+ /* -+ * We may be holding an active internal node in the tree. -+ */ -+ x = tt + 1; -+ if (t != x) { -+#ifndef RJ_DEBUG -+ *t = *x; -+#else -+ b = t->rj_info; *t = *x; t->rj_info = b; -+#endif /* RJ_DEBUG */ -+ t->rj_l->rj_p = t; t->rj_r->rj_p = t; -+ p = x->rj_p; -+ if (p->rj_l == x) p->rj_l = t; else p->rj_r = t; -+ } -+out: -+ tt->rj_flags &= ~RJF_ACTIVE; -+ tt[1].rj_flags &= ~RJF_ACTIVE; -+ *node = tt; -+ return 0; /* (tt) rgb */ -+} -+ -+int -+rj_walktree(h, f, w) -+ struct radij_node_head *h; -+ register int (*f)(struct radij_node *,void *); -+ void *w; -+{ -+ int error; -+ struct radij_node *base, *next; -+ register struct radij_node *rn; -+ -+ if(!h || !f /* || !w */) { -+ return -ENODATA; -+ } -+ -+ rn = h->rnh_treetop; -+ /* -+ * This gets complicated because we may delete the node -+ * while applying the function f to it, so we need to calculate -+ * the successor node in advance. -+ */ -+ /* First time through node, go left */ -+ while (rn->rj_b >= 0) -+ rn = rn->rj_l; -+ for (;;) { -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_radij) { -+ printk("klips_debug:rj_walktree: " -+ "for: rn=0p%p rj_b=%d rj_flags=%x", -+ rn, -+ rn->rj_b, -+ rn->rj_flags); -+ rn->rj_b >= 0 ? -+ printk(" node off=%x\n", -+ rn->rj_off) : -+ printk(" leaf key = %08x->%08x\n", -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr), -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr)) -+ ; -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ base = rn; -+ /* If at right child go back up, otherwise, go right */ -+ while (rn->rj_p->rj_r == rn && (rn->rj_flags & RJF_ROOT) == 0) -+ rn = rn->rj_p; -+ /* Find the next *leaf* since next node might vanish, too */ -+ for (rn = rn->rj_p->rj_r; rn->rj_b >= 0;) -+ rn = rn->rj_l; -+ next = rn; -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_radij) { -+ printk("klips_debug:rj_walktree: " -+ "processing leaves, rn=0p%p rj_b=%d rj_flags=%x", -+ rn, -+ rn->rj_b, -+ rn->rj_flags); -+ rn->rj_b >= 0 ? -+ printk(" node off=%x\n", -+ rn->rj_off) : -+ printk(" leaf key = %08x->%08x\n", -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr), -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr)) -+ ; -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ /* Process leaves */ -+ while ((rn = base)) { -+ base = rn->rj_dupedkey; -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_radij) { -+ printk("klips_debug:rj_walktree: " -+ "while: base=0p%p rn=0p%p rj_b=%d rj_flags=%x", -+ base, -+ rn, -+ rn->rj_b, -+ rn->rj_flags); -+ rn->rj_b >= 0 ? -+ printk(" node off=%x\n", -+ rn->rj_off) : -+ printk(" leaf key = %08x->%08x\n", -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr), -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr)) -+ ; -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ if (!(rn->rj_flags & RJF_ROOT) && (error = (*f)(rn, w))) -+ return (-error); -+ } -+ rn = next; -+ if (rn->rj_flags & RJF_ROOT) -+ return (0); -+ } -+ /* NOTREACHED */ -+} -+ -+int -+rj_inithead(head, off) -+ void **head; -+ int off; -+{ -+ register struct radij_node_head *rnh; -+ register struct radij_node *t, *tt, *ttt; -+ if (*head) -+ return (1); -+ R_Malloc(rnh, struct radij_node_head *, sizeof (*rnh)); -+ if (rnh == NULL) -+ return (0); -+ Bzero(rnh, sizeof (*rnh)); -+ *head = rnh; -+ t = rj_newpair(rj_zeroes, off, rnh->rnh_nodes); -+ ttt = rnh->rnh_nodes + 2; -+ t->rj_r = ttt; -+ t->rj_p = t; -+ tt = t->rj_l; -+ tt->rj_flags = t->rj_flags = RJF_ROOT | RJF_ACTIVE; -+ tt->rj_b = -1 - off; -+ *ttt = *tt; -+ ttt->rj_key = rj_ones; -+ rnh->rnh_addaddr = rj_addroute; -+ rnh->rnh_deladdr = rj_delete; -+ rnh->rnh_matchaddr = rj_match; -+ rnh->rnh_walktree = rj_walktree; -+ rnh->rnh_treetop = t; -+ return (1); -+} -+ -+void -+rj_init() -+{ -+ char *cp, *cplim; -+ -+ if (maj_keylen == 0) { -+ printk("klips_debug:rj_init: " -+ "radij functions require maj_keylen be set\n"); -+ return; -+ } -+ R_Malloc(rj_zeroes, char *, 3 * maj_keylen); -+ if (rj_zeroes == NULL) -+ panic("rj_init"); -+ Bzero(rj_zeroes, 3 * maj_keylen); -+ rj_ones = cp = rj_zeroes + maj_keylen; -+ maskedKey = cplim = rj_ones + maj_keylen; -+ while (cp < cplim) -+ *cp++ = -1; -+ if (rj_inithead((void **)&mask_rjhead, 0) == 0) -+ panic("rj_init 2"); -+} -+ -+void -+rj_preorder(struct radij_node *rn, int l) -+{ -+ int i; -+ -+ if (rn == NULL){ -+ printk("klips_debug:rj_preorder: " -+ "NULL pointer\n"); -+ return; -+ } -+ -+ if (rn->rj_b >= 0){ -+ rj_preorder(rn->rj_l, l+1); -+ rj_preorder(rn->rj_r, l+1); -+ printk("klips_debug:"); -+ for (i=0; irj_off); -+ } else { -+ printk("klips_debug:"); -+ for (i=0; irj_flags); -+ if (rn->rj_flags & RJF_ACTIVE) { -+ printk(" @key=0p%p", -+ rn->rj_key); -+ printk(" key = %08x->%08x", -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr), -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr)); -+ printk(" @mask=0p%p", -+ rn->rj_mask); -+ if (rn->rj_mask) -+ printk(" mask = %08x->%08x", -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_mask)->sen_ip_src.s_addr), -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_mask)->sen_ip_dst.s_addr)); -+ if (rn->rj_dupedkey) -+ printk(" dupedkey = 0p%p", -+ rn->rj_dupedkey); -+ } -+ printk("\n"); -+ } -+} -+ -+#ifdef RJ_DEBUG -+DEBUG_NO_STATIC void traverse(struct radij_node *p) -+{ -+ rj_preorder(p, 0); -+} -+#endif /* RJ_DEBUG */ -+ -+void -+rj_dumptrees(void) -+{ -+ rj_preorder(rnh->rnh_treetop, 0); -+} -+ -+void -+rj_free_mkfreelist(void) -+{ -+ struct radij_mask *mknp, *mknp2; -+ -+ mknp = rj_mkfreelist; -+ while(mknp) -+ { -+ mknp2 = mknp; -+ mknp = mknp->rm_mklist; -+ kfree(mknp2); -+ } -+} -+ -+int -+radijcleartree(void) -+{ -+ return rj_walktree(rnh, ipsec_rj_walker_delete, NULL); -+} -+ -+int -+radijcleanup(void) -+{ -+ int error = 0; -+ -+ error = radijcleartree(); -+ -+ rj_free_mkfreelist(); -+ -+/* rj_walktree(mask_rjhead, ipsec_rj_walker_delete, NULL); */ -+ if(mask_rjhead) { -+ kfree(mask_rjhead); -+ } -+ -+ if(rj_zeroes) { -+ kfree(rj_zeroes); -+ } -+ -+ if(rnh) { -+ kfree(rnh); -+ } -+ -+ return error; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.46 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.45 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.44.30.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.44 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.43 2002/05/23 07:14:11 rgb -+ * Cleaned up %p variants to 0p%p for test suite cleanup. -+ * -+ * Revision 1.42 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.41 2002/04/24 07:36:35 mcr -+ * Moved from ./klips/net/ipsec/radij.c,v -+ * -+ * Revision 1.40 2002/01/29 17:17:58 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.39 2002/01/29 04:00:55 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.38 2002/01/29 02:13:19 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.37 2001/10/18 04:45:23 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.36 2001/08/22 13:43:51 henry -+ * eliminate the single use of min() to avoid problems with Linus changing it -+ * -+ * Revision 1.35 2001/06/15 04:57:29 rgb -+ * Clarified error return codes. -+ * Changed mask add already exists to EEXIST. -+ * Changed mask delete did not exist to ENOENT. -+ * -+ * Revision 1.34 2001/05/03 19:44:26 rgb -+ * Fix sign of error return codes for rj_addroute(). -+ * -+ * Revision 1.33 2001/02/27 22:24:56 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.32 2001/02/27 06:23:15 rgb -+ * Debug line splitting. -+ * -+ * Revision 1.31 2000/11/06 04:35:21 rgb -+ * Clear table *before* releasing other items in radijcleanup. -+ * -+ * Revision 1.30 2000/09/20 04:07:40 rgb -+ * Changed static functions to DEBUG_NO_STATIC to reveal function names in -+ * oopsen. -+ * -+ * Revision 1.29 2000/09/12 03:25:02 rgb -+ * Moved radij_c_version printing to ipsec_version_get_info(). -+ * -+ * Revision 1.28 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.27 2000/07/28 14:58:32 rgb -+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. -+ * -+ * Revision 1.26 2000/05/10 23:11:37 rgb -+ * Comment out most of the startup version information. -+ * -+ * Revision 1.25 2000/01/21 06:21:47 rgb -+ * Change return codes to negative on error. -+ * -+ * Revision 1.24 1999/11/18 04:09:20 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.23 1999/11/17 15:53:41 rgb -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * -+ * Revision 1.22 1999/10/15 22:17:28 rgb -+ * Modify radijcleanup() to call radijcleartree(). -+ * -+ * Revision 1.21 1999/10/08 18:37:34 rgb -+ * Fix end-of-line spacing to sate whining PHMs. -+ * -+ * Revision 1.20 1999/10/01 15:44:54 rgb -+ * Move spinlock header include to 2.1> scope. -+ * -+ * Revision 1.19 1999/10/01 08:35:52 rgb -+ * Add spinlock include to shut up compiler for 2.0.38. -+ * -+ * Revision 1.18 1999/09/23 18:02:52 rgb -+ * De-alarm the search failure message so it doesn't sound so grave. -+ * -+ * Revision 1.17 1999/05/25 21:26:01 rgb -+ * Fix rj_walktree() sanity checking bug. -+ * -+ * Revision 1.16 1999/05/09 03:25:38 rgb -+ * Fix bug introduced by 2.2 quick-and-dirty patch. -+ * -+ * Revision 1.15 1999/05/05 22:02:33 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.14 1999/04/29 15:24:15 rgb -+ * Add sanity checking for null pointer arguments. -+ * Standardise an error return method. -+ * -+ * Revision 1.13 1999/04/11 00:29:02 henry -+ * GPL boilerplate -+ * -+ * Revision 1.12 1999/04/06 04:54:28 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.11 1999/02/17 16:52:53 rgb -+ * Convert DEBUG_IPSEC to KLIPS_PRINT -+ * Clean out unused cruft. -+ * -+ * Revision 1.10 1999/01/22 06:30:05 rgb -+ * Cruft clean-out. -+ * 64-bit clean-up. -+ * -+ * Revision 1.9 1998/12/01 13:22:04 rgb -+ * Added support for debug printing of version info. -+ * -+ * Revision 1.8 1998/11/30 13:22:55 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.7 1998/10/25 02:43:26 rgb -+ * Change return type on rj_addroute and rj_delete and add and argument -+ * to the latter to be able to transmit more infomation about errors. -+ * -+ * Revision 1.6 1998/10/19 14:30:06 rgb -+ * Added inclusion of freeswan.h. -+ * -+ * Revision 1.5 1998/10/09 04:33:27 rgb -+ * Added 'klips_debug' prefix to all klips printk debug statements. -+ * Fixed output formatting slightly. -+ * -+ * Revision 1.4 1998/07/28 00:06:59 rgb -+ * Add debug detail to tree traversing. -+ * -+ * Revision 1.3 1998/07/14 18:07:58 rgb -+ * Add a routine to clear the eroute tree. -+ * -+ * Revision 1.2 1998/06/25 20:03:22 rgb -+ * Cleanup #endif comments. Debug output for rj_init. -+ * -+ * Revision 1.1 1998/06/18 21:30:22 henry -+ * move sources from klips/src to klips/net/ipsec to keep stupid kernel -+ * build scripts happier about symlinks -+ * -+ * Revision 1.8 1998/05/25 20:34:15 rgb -+ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions. -+ * -+ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and -+ * add ipsec_rj_walker_delete. -+ * -+ * Recover memory for eroute table on unload of module. -+ * -+ * Revision 1.7 1998/05/21 12:58:58 rgb -+ * Moved 'extern' definitions to ipsec_radij.h to support /proc 3k limit fix. -+ * -+ * Revision 1.6 1998/04/23 20:57:29 rgb -+ * Cleaned up compiler warnings for unused debugging functions. -+ * -+ * Revision 1.5 1998/04/22 16:51:38 rgb -+ * Tidy up radij debug code from recent rash of modifications to debug code. -+ * -+ * Revision 1.4 1998/04/21 21:28:56 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.3 1998/04/14 17:30:37 rgb -+ * Fix up compiling errors for radij tree memory reclamation. -+ * -+ * Revision 1.2 1998/04/12 22:03:25 rgb -+ * Updated ESP-3DES-HMAC-MD5-96, -+ * ESP-DES-HMAC-MD5-96, -+ * AH-HMAC-MD5-96, -+ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository -+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts. -+ * -+ * Fixed eroute references in /proc/net/ipsec*. -+ * -+ * Started to patch module unloading memory leaks in ipsec_netlink and -+ * radij tree unloading. -+ * -+ * Revision 1.1 1998/04/09 03:06:15 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:03 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:39:04 ji -+ * Minor cleanups. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/sysctl_net_ipsec.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,196 @@ -+/* -+ * sysctl interface to net IPSEC subsystem. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* -*- linux-c -*- -+ * -+ * Initiated April 3, 1998, Richard Guy Briggs -+ */ -+ -+#include -+#include -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef CONFIG_SYSCTL -+ -+#define NET_IPSEC 2112 /* Random number */ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int debug_ah; -+extern int debug_esp; -+extern int debug_tunnel; -+extern int debug_eroute; -+extern int debug_spi; -+extern int debug_radij; -+extern int debug_netlink; -+extern int debug_xform; -+extern int debug_rcv; -+extern int debug_pfkey; -+extern int sysctl_ipsec_debug_verbose; -+#ifdef CONFIG_IPSEC_IPCOMP -+extern int sysctl_ipsec_debug_ipcomp; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+extern int sysctl_ipsec_icmp; -+extern int sysctl_ipsec_inbound_policy_check; -+extern int sysctl_ipsec_tos; -+int sysctl_ipsec_regress_pfkey_lossage; -+ -+enum { -+#ifdef CONFIG_IPSEC_DEBUG -+ NET_IPSEC_DEBUG_AH=1, -+ NET_IPSEC_DEBUG_ESP=2, -+ NET_IPSEC_DEBUG_TUNNEL=3, -+ NET_IPSEC_DEBUG_EROUTE=4, -+ NET_IPSEC_DEBUG_SPI=5, -+ NET_IPSEC_DEBUG_RADIJ=6, -+ NET_IPSEC_DEBUG_NETLINK=7, -+ NET_IPSEC_DEBUG_XFORM=8, -+ NET_IPSEC_DEBUG_RCV=9, -+ NET_IPSEC_DEBUG_PFKEY=10, -+ NET_IPSEC_DEBUG_VERBOSE=11, -+ NET_IPSEC_DEBUG_IPCOMP=12, -+#endif /* CONFIG_IPSEC_DEBUG */ -+ NET_IPSEC_ICMP=13, -+ NET_IPSEC_INBOUND_POLICY_CHECK=14, -+ NET_IPSEC_TOS=15, -+ NET_IPSEC_REGRESS_PFKEY_LOSSAGE=16, -+}; -+ -+static ctl_table ipsec_table[] = { -+#ifdef CONFIG_IPSEC_DEBUG -+ { NET_IPSEC_DEBUG_AH, "debug_ah", &debug_ah, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_ESP, "debug_esp", &debug_esp, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_TUNNEL, "debug_tunnel", &debug_tunnel, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_EROUTE, "debug_eroute", &debug_eroute, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_SPI, "debug_spi", &debug_spi, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_RADIJ, "debug_radij", &debug_radij, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_NETLINK, "debug_netlink", &debug_netlink, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_XFORM, "debug_xform", &debug_xform, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_RCV, "debug_rcv", &debug_rcv, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_PFKEY, "debug_pfkey", &debug_pfkey, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_VERBOSE, "debug_verbose",&sysctl_ipsec_debug_verbose, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+#ifdef CONFIG_IPSEC_IPCOMP -+ { NET_IPSEC_DEBUG_IPCOMP, "debug_ipcomp", &sysctl_ipsec_debug_ipcomp, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#ifdef CONFIG_IPSEC_REGRESS -+ { NET_IPSEC_REGRESS_PFKEY_LOSSAGE, "pfkey_lossage", -+ &sysctl_ipsec_regress_pfkey_lossage, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+#endif /* CONFIG_IPSEC_REGRESS */ -+ -+#endif /* CONFIG_IPSEC_DEBUG */ -+ { NET_IPSEC_ICMP, "icmp", &sysctl_ipsec_icmp, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_INBOUND_POLICY_CHECK, "inbound_policy_check", &sysctl_ipsec_inbound_policy_check, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_TOS, "tos", &sysctl_ipsec_tos, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ {0} -+}; -+ -+static ctl_table ipsec_net_table[] = { -+ { NET_IPSEC, "ipsec", NULL, 0, 0555, ipsec_table }, -+ { 0 } -+}; -+ -+static ctl_table ipsec_root_table[] = { -+ { CTL_NET, "net", NULL, 0, 0555, ipsec_net_table }, -+ { 0 } -+}; -+ -+static struct ctl_table_header *ipsec_table_header; -+ -+int ipsec_sysctl_register(void) -+{ -+ ipsec_table_header = register_sysctl_table(ipsec_root_table, 0); -+ if (!ipsec_table_header) { -+ return -ENOMEM; -+ } -+ return 0; -+} -+ -+void ipsec_sysctl_unregister(void) -+{ -+ unregister_sysctl_table(ipsec_table_header); -+} -+ -+#endif /* CONFIG_SYSCTL */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.16 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.15 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.14 2002/04/24 07:36:35 mcr -+ * Moved from ./klips/net/ipsec/sysctl_net_ipsec.c,v -+ * -+ * Revision 1.13 2002/01/12 02:58:32 mcr -+ * first regression test causes acquire messages to be lost -+ * 100% of the time. This is to help testing of pluto. -+ * -+ * Revision 1.12 2001/06/14 19:35:13 rgb -+ * Update copyright date. -+ * -+ * Revision 1.11 2001/02/26 19:58:13 rgb -+ * Drop sysctl_ipsec_{no_eroute_pass,opportunistic}, replaced by magic SAs. -+ * -+ * Revision 1.10 2000/09/16 01:50:15 rgb -+ * Protect sysctl_ipsec_debug_ipcomp with compiler defines too so that the -+ * linker won't blame rj_delete() for missing symbols. ;-> Damn statics... -+ * -+ * Revision 1.9 2000/09/15 23:17:51 rgb -+ * Moved stuff around to compile with debug off. -+ * -+ * Revision 1.8 2000/09/15 11:37:02 rgb -+ * Merge in heavily modified Svenning Soerensen's -+ * IPCOMP zlib deflate code. -+ * -+ * Revision 1.7 2000/09/15 07:37:15 rgb -+ * Munged silly log comment that was causing a warning. -+ * -+ * Revision 1.6 2000/09/15 04:58:23 rgb -+ * Added tos runtime switch. -+ * Removed 'sysctl_ipsec_' prefix from /proc/sys/net/ipsec/ filenames. -+ * -+ * Revision 1.5 2000/09/12 03:25:28 rgb -+ * Filled in and implemented sysctl. -+ * -+ * Revision 1.4 1999/04/11 00:29:03 henry -+ * GPL boilerplate -+ * -+ * Revision 1.3 1999/04/06 04:54:29 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/version.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,44 @@ -+/* -+ * return IPsec version information -+ * Copyright (C) 2001 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifdef __KERNEL__ -+#include -+#endif -+ -+#include "openswan.h" -+ -+#define V "cvs2002Mar12_01:19:03" /* substituted in by Makefile */ -+static const char openswan_number[] = V; -+static const char openswan_string[] = "Openswan " V; -+ -+/* -+ - ipsec_version_code - return IPsec version number/code, as string -+ */ -+const char * -+ipsec_version_code() -+{ -+ return openswan_number; -+} -+ -+/* -+ - ipsec_version_string - return full version string -+ */ -+const char * -+ipsec_version_string() -+{ -+ return openswan_string; -+} -RCSID $Id$ ---- ./net/ipv4/af_inet.c.preipsec Wed Apr 26 15:13:17 2000 -+++ ./net/ipv4/af_inet.c Fri Jun 30 15:01:27 2000 -@@ -1019,6 +1019,17 @@ - ip_mr_init(); - #endif - -+#if defined(CONFIG_IPSEC) -+ { -+ extern /* void */ int ipsec_init(void); -+ /* -+ * Initialise AF_INET ESP and AH protocol support including -+ * e-routing and SA tables -+ */ -+ ipsec_init(); -+ } -+#endif /* CONFIG_IPSEC */ -+ - /* - * Create all the /proc entries. - */ ---- /dev/null Fri May 10 13:59:54 2002 -+++ linux/net/ipsec/Makefile.ver Sun Jul 28 22:10:40 2002 -@@ -0,0 +1 @@ -+IPSECVERSION=cvs2002Mar12_01:19:03 -make[1]: Leaving directory `/data/mtx/oe/tmp/work/openswan-2.2.0-r0/openswan-2.2.0' diff --git a/linux/linux-mtx-1-2.4.24/14-au1000-eth-vlan.diff b/linux/linux-mtx-1-2.4.24/14-au1000-eth-vlan.diff deleted file mode 100644 index a4fa3169cc..0000000000 --- a/linux/linux-mtx-1-2.4.24/14-au1000-eth-vlan.diff +++ /dev/null @@ -1,10 +0,0 @@ ---- linux/drivers/net/au1000_eth.c.orig 2004-11-18 13:44:52.163605416 +0100 -+++ linux/drivers/net/au1000_eth.c 2004-11-18 13:51:42.096286176 +0100 -@@ -1384,6 +1384,7 @@ - control |= MAC_FULL_DUPLEX; - } - aup->mac->control = control; -+ aup->mac->vlan1_tag = 0x8100; /* activate vlan support */ - au_sync(); - - spin_unlock_irqrestore(&aup->lock, flags); diff --git a/linux/linux-mtx-1-2.4.24/15-mtd-proc-partition-rw.diff b/linux/linux-mtx-1-2.4.24/15-mtd-proc-partition-rw.diff deleted file mode 100644 index 54ba5fff98..0000000000 --- a/linux/linux-mtx-1-2.4.24/15-mtd-proc-partition-rw.diff +++ /dev/null @@ -1,173 +0,0 @@ -diff -Nurb linux/drivers/mtd/mtdcore.c linux-mtd-rw/drivers/mtd/mtdcore.c ---- linux/drivers/mtd/mtdcore.c 2004-11-18 13:16:00.000000000 +0100 -+++ linux-mtd-rw/drivers/mtd/mtdcore.c 2004-11-18 15:27:13.130036616 +0100 -@@ -25,6 +25,10 @@ - - #include - -+/* this symbol is exported by the procfs. */ -+extern struct proc_dir_entry *proc_sys_root; -+ -+ - /* These are exported solely for the purpose of mtd_blkdevs.c. You - should not use them for _anything_ else */ - DECLARE_MUTEX(mtd_table_mutex); -@@ -336,8 +340,83 @@ - - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) - static struct proc_dir_entry *proc_mtd; -+ -+static struct proc_dir_entry *proc_sys_mtd; -+static struct proc_dir_entry *proc_sys_mtd_partition[MAX_MTD_DEVICES]; -+static struct proc_dir_entry *proc_sys_mtd_partition_rw[MAX_MTD_DEVICES]; - #endif - -+/*===================================0 -+ * mtdproc_read_partition_access -+ */ -+static int mtdproc_read_partition_access ( char *page, char **start, off_t off,int count, -+ int *eof, void *data -+ ) -+{ -+ int partid = (unsigned int)data; -+ int len = 0; -+ -+ // NO RETURN FROM HERE UNTIL "up(&mtd_table_mutex)". -+ down(&mtd_table_mutex); -+ -+ if (partid < MAX_MTD_DEVICES) -+ { -+ struct mtd_info *this = mtd_table[partid]; -+ if (this) -+ { -+ page[len] = (this->flags & MTD_WRITEABLE) ? '1' : '0'; -+ len++; -+ } -+ } -+ -+ up(&mtd_table_mutex); -+ -+ if (off >= len) -+ return 0; -+ *start = page + off; -+ return ((count < len-off) ? count : len-off); -+} -+ -+ -+static int mtdproc_write_partition_access (struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ int partid = (unsigned int)data; -+ int len = 0; -+ -+ // NO RETURN FROM HERE UNTIL "up(&mtd_table_mutex)". -+ down(&mtd_table_mutex); -+ -+ if (partid < MAX_MTD_DEVICES) -+ { -+ struct mtd_info *this = mtd_table[partid]; -+ if (this && count > 0) -+ { -+ switch (*buffer) -+ { -+ case '0': -+ this->flags &= ~(this->master_flags & MTD_WRITEABLE); -+ break; -+ -+ case '1': -+ this->flags |= ~(this->master_flags & MTD_WRITEABLE); -+ break; -+ -+ default: -+ break; -+ } -+ } -+ } -+ -+ up(&mtd_table_mutex); -+ -+ return count; -+} -+ -+ -+ -+ -+ - static inline int mtd_proc_info (char *buf, int i) - { - struct mtd_info *this = mtd_table[i]; -@@ -349,6 +428,7 @@ - this->erasesize, this->name); - } - -+ - static int mtd_read_proc ( char *page, char **start, off_t off,int count - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) - ,int *eof, void *data_unused -@@ -404,12 +484,31 @@ - /*====================================================================*/ - /* Init code */ - -+ - int __init init_mtd(void) - { - #ifdef CONFIG_PROC_FS - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) -+ int i; -+ - if ((proc_mtd = create_proc_entry( "mtd", 0, 0 ))) - proc_mtd->read_proc = mtd_read_proc; -+ -+ proc_sys_mtd = proc_mkdir("mtd", proc_sys_root); -+ for (i=0; iread_proc = mtdproc_read_partition_access; -+ proc_sys_mtd_partition_rw[i]->write_proc = mtdproc_write_partition_access; -+ proc_sys_mtd_partition_rw[i]->data = (void *)i; -+ } -+ } - #else - proc_register_dynamic(&proc_root,&mtd_proc_entry); - #endif -@@ -425,6 +524,8 @@ - return 0; - } - -+ -+ - static void __exit cleanup_mtd(void) - { - #ifdef CONFIG_PM -diff -Nurb linux/drivers/mtd/mtdpart.c linux-mtd-rw/drivers/mtd/mtdpart.c ---- linux/drivers/mtd/mtdpart.c 2004-11-18 13:16:00.000000000 +0100 -+++ linux-mtd-rw/drivers/mtd/mtdpart.c 2004-11-18 15:27:13.131036464 +0100 -@@ -341,6 +341,9 @@ - /* set up the MTD object for this partition */ - slave->mtd.type = master->type; - slave->mtd.flags = master->flags & ~parts[i].mask_flags; -+ slave->mtd.master_flags = master->flags; -+ slave->mtd.mask_flags = parts[i].mask_flags; -+ - slave->mtd.size = parts[i].size; - slave->mtd.oobblock = master->oobblock; - slave->mtd.oobsize = master->oobsize; -diff -Nurb linux/include/linux/mtd/mtd.h linux-mtd-rw/include/linux/mtd/mtd.h ---- linux/include/linux/mtd/mtd.h 2004-11-18 13:16:31.000000000 +0100 -+++ linux-mtd-rw/include/linux/mtd/mtd.h 2004-11-18 15:27:13.000000000 +0100 -@@ -232,6 +232,9 @@ - - struct module *owner; - int usecount; -+ -+ u_int32_t master_flags; -+ u_int32_t mask_flags; - }; - - diff --git a/linux/linux-mtx-1-2.4.24/defconfig-mtx-1 b/linux/linux-mtx-1-2.4.24/defconfig-mtx-1 deleted file mode 100644 index 711356c1a9..0000000000 --- a/linux/linux-mtx-1-2.4.24/defconfig-mtx-1 +++ /dev/null @@ -1,1176 +0,0 @@ -# -# Automatically generated by make menuconfig: don't edit -# -CONFIG_MIPS=y -CONFIG_MIPS32=y -# CONFIG_MIPS64 is not set - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_MIPS_BOSPORUS is not set -# CONFIG_MIPS_MIRAGE is not set -# CONFIG_MIPS_DB1000 is not set -# CONFIG_MIPS_DB1100 is not set -# CONFIG_MIPS_DB1500 is not set -# CONFIG_MIPS_PB1000 is not set -# CONFIG_MIPS_PB1100 is not set -# CONFIG_MIPS_PB1500 is not set -# CONFIG_MIPS_HYDROGEN3 is not set -# CONFIG_MIPS_PB1550 is not set -# CONFIG_MIPS_XXS1500 is not set -CONFIG_MIPS_MTX1=y -# CONFIG_COGENT_CSB250 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_LASAT is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_MOMENCO_JAGUAR_ATX is not set -# CONFIG_PMC_YOSEMITE is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_NINO is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP27 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -# CONFIG_HIGHMEM is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -CONFIG_SOC_AU1X00=y -CONFIG_SOC_AU1500=y -CONFIG_NEW_TIME_C=y -CONFIG_PCI=y -CONFIG_NEW_PCI=y -CONFIG_PCI_AUTO=y -CONFIG_NONCOHERENT_IO=y -# CONFIG_MIPS_AU1000 is not set - -# -# CPU selection -# -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_RM9000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_PAGE_SIZE_4KB=y -# CONFIG_PAGE_SIZE_16KB is not set -# CONFIG_PAGE_SIZE_64KB is not set -CONFIG_CPU_HAS_PREFETCH=y -# CONFIG_VTAG_ICACHE is not set -CONFIG_64BIT_PHYS_ADDR=y -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -# CONFIG_CPU_HAS_LLDSCD is not set -# CONFIG_CPU_HAS_WB is not set -CONFIG_CPU_HAS_SYNC=y - -# -# General setup -# -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_NET=y -CONFIG_PCI_NAMES=y -# CONFIG_ISA is not set -# CONFIG_TC is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set - -# -# PCI Hotplug Support -# -# CONFIG_HOTPLUG_PCI is not set -# CONFIG_HOTPLUG_PCI_COMPAQ is not set -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_ELF=y -# CONFIG_MIPS32_COMPAT is not set -# CONFIG_MIPS32_O32 is not set -# CONFIG_MIPS32_N32 is not set -# CONFIG_BINFMT_ELF32 is not set -# CONFIG_BINFMT_MISC is not set -# CONFIG_OOM_KILLER is not set -# CONFIG_PM is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_CMDLINE_PARTS is not set -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_CFI_AMDSTD_RETRY=y -CONFIG_MTD_CFI_AMDSTD_RETRY_MAX=5 -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set -# CONFIG_MTD_JEDEC is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_DB1X00 is not set -CONFIG_MTD_MTX1=y -# CONFIG_MTD_CSTM_MIPS_IXX is not set -# CONFIG_MTD_OCELOT is not set -# CONFIG_MTD_LASAT is not set -# CONFIG_MTD_PCI is not set -# CONFIG_MTD_PCMCIA is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -# CONFIG_MTD_DOCPROBE is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_CISS_MONITOR_THREAD is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=m -CONFIG_BLK_DEV_RAM_SIZE=4096 -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_BLK_STATS is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -# CONFIG_BLK_DEV_LVM is not set - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=m -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_IP_PIMSM_V2=y -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -CONFIG_SYN_COOKIES=y - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m -# CONFIG_IP_NF_NAT_LOCAL is not set -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m -# CONFIG_IP_NF_COMPAT_IPCHAINS is not set -# CONFIG_IP_NF_COMPAT_IPFWADM is not set - -# -# IP: Virtual Server Configuration -# -# CONFIG_IP_VS is not set -CONFIG_IPV6=m - -# -# IPv6: Netfilter Configuration -# -CONFIG_IP6_NF_QUEUE=m -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -# CONFIG_KHTTPD is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=m -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -CONFIG_VLAN_8021Q=m -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m -CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_RED=m -CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_TEQL=m -CONFIG_NET_SCH_TBF=m -CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DSMARK=m -CONFIG_NET_SCH_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -CONFIG_NET_CLS_TCINDEX=m -CONFIG_NET_CLS_ROUTE4=m -CONFIG_NET_CLS_ROUTE=y -CONFIG_NET_CLS_FW=m -CONFIG_NET_CLS_U32=m -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -CONFIG_NET_PKTGEN=m -CONFIG_IPSEC_NAT_TRAVERSAL=y -CONFIG_IPSEC=m -CONFIG_IPSEC_IPIP=y -CONFIG_IPSEC_AH=y -CONFIG_IPSEC_AUTH_HMAC_MD5=y -CONFIG_IPSEC_AUTH_HMAC_SHA1=y -CONFIG_IPSEC_ESP=y -CONFIG_IPSEC_ENC_3DES=y -CONFIG_IPSEC_ENC_AES=y -CONFIG_IPSEC_ALG=y -CONFIG_IPSEC_ALG_AES=m -CONFIG_IPSEC_ALG_CRYPTOAPI=m -CONFIG_IPSEC_ALG_NON_LIBRE=y -CONFIG_IPSEC_IPCOMP=y -CONFIG_IPSEC_DEBUG=y - -# -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI support -# -CONFIG_SCSI=m -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=40 -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 -# CONFIG_CHR_DEV_SG is not set -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_MEGARAID2 is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_NCR53C8XX is not set -# CONFIG_SCSI_SYM53C8XX is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set -# CONFIG_FUSION_BOOT is not set -# CONFIG_FUSION_ISENSE is not set -# CONFIG_FUSION_CTL is not set -# CONFIG_FUSION_LAN is not set - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -CONFIG_MIPS_AU1X00_ENET=y -# CONFIG_BCM5222_DUAL_PHY is not set -# CONFIG_SUNLANCE is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -# CONFIG_STRIP is not set -# CONFIG_WAVELAN is not set -# CONFIG_ARLAN is not set -CONFIG_AIRONET4500=m -CONFIG_AIRONET4500_NONCS=m -# CONFIG_AIRONET4500_PNP is not set -CONFIG_AIRONET4500_PCI=y -# CONFIG_AIRONET4500_ISA is not set -# CONFIG_AIRONET4500_I365 is not set -CONFIG_AIRONET4500_PROC=m -CONFIG_AIRO=m -# CONFIG_HERMES is not set -# CONFIG_PLX_HERMES is not set -# CONFIG_TMD_HERMES is not set -# CONFIG_PCI_HERMES is not set -CONFIG_NET_WIRELESS=y - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -CONFIG_SHAPER=m - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input core support -# -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_UINPUT is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -CONFIG_SERIAL_NONSTANDARD=y -# CONFIG_COMPUTONE is not set -# CONFIG_ROCKETPORT is not set -# CONFIG_CYCLADES is not set -# CONFIG_DIGIEPCA is not set -# CONFIG_DIGI is not set -# CONFIG_ESPSERIAL is not set -# CONFIG_MOXA_INTELLIO is not set -# CONFIG_MOXA_SMARTIO is not set -# CONFIG_ISI is not set -# CONFIG_SYNCLINK is not set -# CONFIG_SYNCLINKMP is not set -# CONFIG_N_HDLC is not set -# CONFIG_RISCOM8 is not set -# CONFIG_SPECIALIX is not set -# CONFIG_SX is not set -# CONFIG_RIO is not set -# CONFIG_STALDRV is not set -# CONFIG_SERIAL_TX3912 is not set -# CONFIG_SERIAL_TX3912_CONSOLE is not set -# CONFIG_SERIAL_TXX9 is not set -# CONFIG_SERIAL_TXX9_CONSOLE is not set -CONFIG_AU1X00_UART=y -CONFIG_AU1X00_SERIAL_CONSOLE=y -# CONFIG_AU1X00_USB_TTY is not set -# CONFIG_AU1X00_USB_RAW is not set -# CONFIG_TXX927_SERIAL is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_QIC02_TAPE is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_DEVICE_INTERFACE is not set -# CONFIG_IPMI_KCS is not set -# CONFIG_IPMI_WATCHDOG is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_SCx200_GPIO is not set -# CONFIG_AMD_PM768 is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -CONFIG_MIPS_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set - -# -# Direct Rendering Manager (XFree86 DRI support) -# -# CONFIG_DRM is not set -CONFIG_AU1X00_GPIO=m -# CONFIG_TS_AU1X00_ADS7846 is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_QFMT_V2 is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BEFS_DEBUG is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -# CONFIG_UMSDOS_FS is not set -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_CRAMFS is not set -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -# CONFIG_JFS_FS is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set -CONFIG_NTFS_FS=m -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=m -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set -# CONFIG_XFS_FS is not set -# CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_RT is not set -# CONFIG_XFS_TRACE is not set -# CONFIG_XFS_DEBUG is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_DIRECTIO is not set -CONFIG_ROOT_NFS=y -CONFIG_NFSD=y -CONFIG_NFSD_V3=y -# CONFIG_NFSD_TCP is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -CONFIG_ZISOFS_FS=m - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-15" -CONFIG_NLS_CODEPAGE_437=m -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -CONFIG_NLS_CODEPAGE_850=m -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -CONFIG_NLS_ISO8859_1=m -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -CONFIG_NLS_ISO8859_15=m -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -CONFIG_NLS_UTF8=m - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -# CONFIG_I2C_PARPORT is not set -# CONFIG_VIDEO_BT848 is not set -# CONFIG_VIDEO_PMS is not set -CONFIG_VIDEO_CPIA=m -# CONFIG_VIDEO_CPIA_PP is not set -CONFIG_VIDEO_CPIA_USB=m -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_ZORAN_BUZ is not set -# CONFIG_VIDEO_ZORAN_DC10 is not set -# CONFIG_VIDEO_ZORAN_LML33 is not set -# CONFIG_VIDEO_ZR36120 is not set -# CONFIG_VIDEO_MEYE is not set - -# -# Radio Adapters -# -# CONFIG_RADIO_GEMTEK_PCI is not set -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_MAESTRO is not set -# CONFIG_RADIO_MIROPCM20 is not set - -# -# Sound -# -CONFIG_SOUND=m -# CONFIG_SOUND_ALI5455 is not set -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_MIDI_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_MAESTRO3 is not set -# CONFIG_SOUND_FORTE is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_RME96XX is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_AU1X00 is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -# CONFIG_MIDI_VIA82CXXX is not set -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -# CONFIG_SOUND_DMAP is not set -# CONFIG_SOUND_AD1816 is not set -# CONFIG_SOUND_AD1889 is not set -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_ADLIB is not set -# CONFIG_SOUND_ACI_MIXER is not set -# CONFIG_SOUND_CS4232 is not set -# CONFIG_SOUND_SSCAPE is not set -# CONFIG_SOUND_GUS is not set -# CONFIG_SOUND_VMIDI is not set -# CONFIG_SOUND_TRIX is not set -# CONFIG_SOUND_MSS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_NM256 is not set -# CONFIG_SOUND_MAD16 is not set -# CONFIG_SOUND_PAS is not set -# CONFIG_PAS_JOYSTICK is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_SB is not set -# CONFIG_SOUND_AWE32_SYNTH is not set -# CONFIG_SOUND_KAHLUA is not set -# CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_OPL3SA2 is not set -# CONFIG_SOUND_YMFPCI is not set -# CONFIG_SOUND_YMFPCI_LEGACY is not set -# CONFIG_SOUND_UART6850 is not set -# CONFIG_SOUND_AEDSP16 is not set -# CONFIG_SOUND_TVMIXER is not set -# CONFIG_SOUND_AD1980 is not set -# CONFIG_SOUND_WM97XX is not set - -# -# USB support -# -CONFIG_USB=y -# CONFIG_USB_DEBUG is not set -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -CONFIG_USB_OHCI=y -CONFIG_USB_NON_PCI_OHCI=y -CONFIG_USB_AUDIO=m -CONFIG_USB_EMI26=m -CONFIG_USB_MIDI=m -CONFIG_USB_STORAGE=m -CONFIG_USB_STORAGE_DEBUG=y -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -# CONFIG_USB_STORAGE_ISD200 is not set -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m -# CONFIG_USB_HID is not set -# CONFIG_USB_HIDINPUT is not set -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -CONFIG_USB_DC2XX=m -CONFIG_USB_MDC800=m -CONFIG_USB_SCANNER=m -CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -# CONFIG_USB_W9968CF is not set -CONFIG_USB_VICAM=m -CONFIG_USB_DSBR=m -CONFIG_USB_DABUSB=m -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_KAWETH=m -CONFIG_USB_CATC=m -CONFIG_USB_AX8817X=m -CONFIG_USB_CDCETHER=m -CONFIG_USB_USBNET=m -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_DEBUG is not set -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=m -CONFIG_USB_SERIAL_VISOR=m -CONFIG_USB_SERIAL_IPAQ=m -CONFIG_USB_SERIAL_IR=m -CONFIG_USB_SERIAL_EDGEPORT=m -CONFIG_USB_SERIAL_EDGEPORT_TI=m -CONFIG_USB_SERIAL_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -CONFIG_USB_SERIAL_KEYSPAN_USA28=y -CONFIG_USB_SERIAL_KEYSPAN_USA28X=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -CONFIG_USB_SERIAL_KEYSPAN_USA19=y -CONFIG_USB_SERIAL_KEYSPAN_USA18X=y -CONFIG_USB_SERIAL_KEYSPAN_USA19W=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -CONFIG_USB_SERIAL_KEYSPAN_MPR=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_RIO500=m -CONFIG_USB_AUERSWALD=m -CONFIG_USB_TIGL=m -CONFIG_USB_BRLVGER=m -CONFIG_USB_LCD=m - -# -# Support for USB gadgets -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -CONFIG_BLUEZ_HCIUSB=m -CONFIG_BLUEZ_HCIUSB_SCO=y -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y -CONFIG_BLUEZ_HCIBFUSB=m -# CONFIG_BLUEZ_HCIDTL1 is not set -# CONFIG_BLUEZ_HCIBT3C is not set -# CONFIG_BLUEZ_HCIBLUECARD is not set -# CONFIG_BLUEZ_HCIBTUART is not set -CONFIG_BLUEZ_HCIVHCI=m - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_RUNTIME_DEBUG is not set -# CONFIG_KGDB is not set -# CONFIG_GDB_CONSOLE is not set -# CONFIG_DEBUG_INFO is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MIPS_UNCACHED is not set -CONFIG_LOG_BUF_SHIFT=0 - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=m -CONFIG_CRYPTO_SHA1=m -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_DES=m -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_DEFLATE=m -CONFIG_CRYPTO_TEST=m - -# -# Library routines -# -CONFIG_CRC32=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_FW_LOADER=m diff --git a/linux/linux-mtx-1-2.4.27/01-mtd-2004-01-27.diff b/linux/linux-mtx-1-2.4.27/01-mtd-2004-01-27.diff deleted file mode 100644 index 74e6375385..0000000000 --- a/linux/linux-mtx-1-2.4.27/01-mtd-2004-01-27.diff +++ /dev/null @@ -1,51503 +0,0 @@ -diff -Nurb linux-mips-2.4.27/drivers/mtd/Config.in linux/drivers/mtd/Config.in ---- linux-mips-2.4.27/drivers/mtd/Config.in 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/Config.in 2004-11-19 10:25:11.607244176 +0100 -@@ -1,5 +1,5 @@ - --# $Id$ -+# $Id$ - - mainmenu_option next_comment - comment 'Memory Technology Devices (MTD)' -@@ -30,6 +30,7 @@ - if [ "$CONFIG_NFTL" = "y" -o "$CONFIG_NFTL" = "m" ]; then - bool ' Write support for NFTL (BETA)' CONFIG_NFTL_RW - fi -+ dep_tristate ' INFTL (Inverse NAND Flash Translation Layer) support' CONFIG_INFTL $CONFIG_MTD - - source drivers/mtd/chips/Config.in - -diff -Nurb linux-mips-2.4.27/drivers/mtd/Makefile linux/drivers/mtd/Makefile ---- linux-mips-2.4.27/drivers/mtd/Makefile 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/Makefile 2004-11-19 10:25:11.608244024 +0100 -@@ -1,30 +1,7 @@ - # - # Makefile for the memory technology device drivers. - # --# Note! Dependencies are done automagically by 'make dep', which also --# removes any old dependencies. DON'T put your own dependencies here --# unless it's something special (ie not a .c file). --# --# Note 2! The CFLAGS definitions are now inherited from the --# parent makes.. --# --# $Id$ -- -- --obj-y += chips/chipslink.o maps/mapslink.o \ -- devices/devlink.o nand/nandlink.o --obj-m := --obj-n := --obj- := -- --O_TARGET := mtdlink.o -- --export-objs := mtdcore.o mtdpart.o redboot.o cmdlinepart.o afs.o mtdconcat.o --list-multi := nftl.o -- --mod-subdirs := --subdir-y := chips maps devices nand --subdir-m := $(subdir-y) -+# $Id$ - - # *** BIG UGLY NOTE *** - # -@@ -52,15 +29,44 @@ - - # 'Users' - code which presents functionality to userspace. - obj-$(CONFIG_MTD_CHAR) += mtdchar.o --obj-$(CONFIG_MTD_BLOCK) += mtdblock.o --obj-$(CONFIG_MTD_BLOCK_RO) += mtdblock_ro.o --obj-$(CONFIG_FTL) += ftl.o --obj-$(CONFIG_NFTL) += nftl.o -+obj-$(CONFIG_MTD_BLOCK) += mtdblock.o mtd_blkdevs.o -+obj-$(CONFIG_MTD_BLOCK_RO) += mtdblock_ro.o mtd_blkdevs.o -+obj-$(CONFIG_FTL) += ftl.o mtd_blkdevs.o -+obj-$(CONFIG_NFTL) += nftl.o mtd_blkdevs.o -+obj-$(CONFIG_INFTL) += inftl.o mtd_blkdevs.o - - nftl-objs := nftlcore.o nftlmount.o -+inftl-objs := inftlcore.o inftlmount.o -+ -+ifeq ($(PATCHLEVEL),4) -+ -+export-objs := mtdcore.o mtdpart.o redboot.o cmdlinepart.o afs.o \ -+ mtdconcat.o mtd_blkdevs-24.o -+ -+mtd_blkdevs-objs := mtd_blkdevs-24.o -+ -+obj-y += chips/chipslink.o maps/mapslink.o \ -+ devices/devlink.o nand/nandlink.o -+ -+O_TARGET := mtdlink.o -+ -+list-multi := nftl.o inftl.o mtd_blkdevs.o -+ -+mod-subdirs := -+subdir-y := chips maps devices nand -+subdir-m := $(subdir-y) - - include $(TOPDIR)/Rules.make - - nftl.o: $(nftl-objs) - $(LD) -r -o $@ $(nftl-objs) - -+inftl.o: $(inftl-objs) -+ $(LD) -r -o $@ $(inftl-objs) -+ -+mtd_blkdevs.o: $(mtd_blkdevs-objs) -+ $(LD) -r -o $@ $(mtd_blkdevs-objs) -+ -+else -+obj-y += chips/ maps/ devices/ nand/ -+endif -diff -Nurb linux-mips-2.4.27/drivers/mtd/afs.c linux/drivers/mtd/afs.c ---- linux-mips-2.4.27/drivers/mtd/afs.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/afs.c 2004-11-19 10:25:11.610243720 +0100 -@@ -21,7 +21,7 @@ - This is access code for flashes using ARM's flash partitioning - standards. - -- $Id$ -+ $Id$ - - ======================================================================*/ - -@@ -76,17 +76,19 @@ - return ret; - } - -+ ret = 1; -+ - /* - * Does it contain the magic number? - */ - if (fs.signature != 0xa0ffff9f) -- ret = 1; -+ ret = 0; - - /* - * Don't touch the SIB. - */ - if (fs.type == 2) -- ret = 1; -+ ret = 0; - - *iis_start = fs.image_info_base & mask; - *img_start = fs.image_start & mask; -@@ -96,14 +98,14 @@ - * be located after the footer structure. - */ - if (*iis_start >= ptr) -- ret = 1; -+ ret = 0; - - /* - * Check the start of this image. The image - * data can not be located after this block. - */ - if (*img_start > off) -- ret = 1; -+ ret = 0; - - return ret; - } -@@ -125,7 +127,9 @@ - return ret; - } - --int parse_afs_partitions(struct mtd_info *mtd, struct mtd_partition **pparts) -+static int parse_afs_partitions(struct mtd_info *mtd, -+ struct mtd_partition **pparts, -+ unsigned long origin) - { - struct mtd_partition *parts; - u_int mask, off, idx, sz; -@@ -150,7 +154,7 @@ - ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask); - if (ret < 0) - break; -- if (ret == 1) -+ if (ret == 0) - continue; - - ret = afs_read_iis(mtd, &iis, iis_ptr); -@@ -183,7 +187,7 @@ - ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask); - if (ret < 0) - break; -- if (ret == 1) -+ if (ret == 0) - continue; - - /* Read the image info block */ -@@ -227,7 +231,25 @@ - return idx ? idx : ret; - } - --EXPORT_SYMBOL(parse_afs_partitions); -+static struct mtd_part_parser afs_parser = { -+ .owner = THIS_MODULE, -+ .parse_fn = parse_afs_partitions, -+ .name = "afs", -+}; -+ -+static int __init afs_parser_init(void) -+{ -+ return register_mtd_parser(&afs_parser); -+} -+ -+static void __exit afs_parser_exit(void) -+{ -+ deregister_mtd_parser(&afs_parser); -+} -+ -+module_init(afs_parser_init); -+module_exit(afs_parser_exit); -+ - - MODULE_AUTHOR("ARM Ltd"); - MODULE_DESCRIPTION("ARM Firmware Suite partition parser"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/Config.in linux/drivers/mtd/chips/Config.in ---- linux-mips-2.4.27/drivers/mtd/chips/Config.in 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/chips/Config.in 2004-11-19 10:25:11.712228216 +0100 -@@ -1,6 +1,6 @@ - # drivers/mtd/chips/Config.in - --# $Id$ -+# $Id$ - - mainmenu_option next_comment - -@@ -11,13 +11,12 @@ - - if [ "$CONFIG_MTD_CFI" = "y" -o "$CONFIG_MTD_JEDECPROBE" = "y" ]; then - define_bool CONFIG_MTD_GEN_PROBE y --else -- if [ "$CONFIG_MTD_CFI" = "m" -o "$CONFIG_MTD_JEDECPROBE" = "m" ]; then -+elif [ "$CONFIG_MTD_CFI" = "m" -o "$CONFIG_MTD_JEDECPROBE" = "m" ]; then - define_bool CONFIG_MTD_GEN_PROBE m -- else -+else - define_bool CONFIG_MTD_GEN_PROBE n -- fi - fi -+ - if [ "$CONFIG_MTD_GEN_PROBE" = "y" -o "$CONFIG_MTD_GEN_PROBE" = "m" ]; then - bool ' Flash chip driver advanced configuration options' CONFIG_MTD_CFI_ADV_OPTIONS - if [ "$CONFIG_MTD_CFI_ADV_OPTIONS" = "y" ]; then -@@ -44,8 +43,27 @@ - fi - dep_tristate ' Support for Intel/Sharp flash chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_GEN_PROBE - dep_tristate ' Support for AMD/Fujitsu flash chips' CONFIG_MTD_CFI_AMDSTD $CONFIG_MTD_GEN_PROBE -+if [ "$CONFIG_MTD_CFI_AMDSTD" = "y" -o "$CONFIG_MTD_CFI_AMDSTD" = "m" ]; then -+ bool ' Retry failed commands (erase/program)' CONFIG_MTD_CFI_AMDSTD_RETRY n -+ if [ "$CONFIG_MTD_CFI_AMDSTD_RETRY" = "y" ]; then -+ int ' Max retries of failed commands (erase/program)' CONFIG_MTD_CFI_AMDSTD_RETRY_MAX 0 -+ fi -+fi -+ - dep_tristate ' Support for ST (Advanced Architecture) flash chips' CONFIG_MTD_CFI_STAA $CONFIG_MTD_GEN_PROBE - -+if [ "$CONFIG_MTD_CFI_INTELEXT" = "y" \ -+ -o "$CONFIG_MTD_CFI_AMDSTD" = "y" \ -+ -o "$CONFIG_MTD_CFI_STAA" = "y" ]; then -+ define_bool CONFIG_MTD_CFI_UTIL y -+elif [ "$CONFIG_MTD_CFI_INTELEXT" = "m" \ -+ -o "$CONFIG_MTD_CFI_AMDSTD" = "m" \ -+ -o "$CONFIG_MTD_CFI_STAA" = "m" ]; then -+ define_bool CONFIG_MTD_CFI_UTIL m -+else -+ define_bool CONFIG_MTD_CFI_UTIL n -+fi -+ - dep_tristate ' Support for RAM chips in bus mapping' CONFIG_MTD_RAM $CONFIG_MTD - dep_tristate ' Support for ROM chips in bus mapping' CONFIG_MTD_ROM $CONFIG_MTD - dep_tristate ' Support for absent chips in bus mapping' CONFIG_MTD_ABSENT $CONFIG_MTD -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/Makefile linux/drivers/mtd/chips/Makefile ---- linux-mips-2.4.27/drivers/mtd/chips/Makefile 2003-07-05 05:23:38.000000000 +0200 -+++ linux/drivers/mtd/chips/Makefile 2004-11-19 10:25:11.714227912 +0100 -@@ -1,11 +1,12 @@ - # - # linux/drivers/chips/Makefile - # --# $Id$ -+# $Id$ - -+ifeq ($(PATCHLEVEL),4) - O_TARGET := chipslink.o -- --export-objs := chipreg.o gen_probe.o -+export-objs := chipreg.o gen_probe.o cfi_util.o -+endif - - # *** BIG UGLY NOTE *** - # -@@ -17,6 +18,7 @@ - obj-$(CONFIG_MTD) += chipreg.o - obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o - obj-$(CONFIG_MTD_CFI) += cfi_probe.o -+obj-$(CONFIG_MTD_CFI_UTIL) += cfi_util.o - obj-$(CONFIG_MTD_CFI_STAA) += cfi_cmdset_0020.o - obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o - obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o -@@ -28,4 +30,4 @@ - obj-$(CONFIG_MTD_SHARP) += sharp.o - obj-$(CONFIG_MTD_ABSENT) += map_absent.o - --include $(TOPDIR)/Rules.make -+-include $(TOPDIR)/Rules.make -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/amd_flash.c linux/drivers/mtd/chips/amd_flash.c ---- linux-mips-2.4.27/drivers/mtd/chips/amd_flash.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/chips/amd_flash.c 2004-11-19 10:25:11.722226696 +0100 -@@ -3,7 +3,7 @@ - * - * Author: Jonas Holmberg - * -- * $Id$ -+ * $Id$ - * - * Copyright (c) 2001 Axis Communications AB - * -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -125,10 +126,10 @@ - - - static struct mtd_chip_driver amd_flash_chipdrv = { -- probe: amd_flash_probe, -- destroy: amd_flash_destroy, -- name: "amd_flash", -- module: THIS_MODULE -+ .probe = amd_flash_probe, -+ .destroy = amd_flash_destroy, -+ .name = "amd_flash", -+ .module = THIS_MODULE - }; - - -@@ -140,11 +141,11 @@ - static inline __u32 wide_read(struct map_info *map, __u32 addr) - { - if (map->buswidth == 1) { -- return map->read8(map, addr); -+ return map_read8(map, addr); - } else if (map->buswidth == 2) { -- return map->read16(map, addr); -+ return map_read16(map, addr); - } else if (map->buswidth == 4) { -- return map->read32(map, addr); -+ return map_read32(map, addr); - } - - return 0; -@@ -153,11 +154,11 @@ - static inline void wide_write(struct map_info *map, __u32 val, __u32 addr) - { - if (map->buswidth == 1) { -- map->write8(map, val, addr); -+ map_write8(map, val, addr); - } else if (map->buswidth == 2) { -- map->write16(map, val, addr); -+ map_write16(map, val, addr); - } else if (map->buswidth == 4) { -- map->write32(map, val, addr); -+ map_write32(map, val, addr); - } - } - -@@ -424,231 +425,228 @@ - - static struct mtd_info *amd_flash_probe(struct map_info *map) - { -- /* Keep this table on the stack so that it gets deallocated after the -- * probe is done. -- */ -- const struct amd_flash_info table[] = { -+ static const struct amd_flash_info table[] = { - { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV160DT, -- name: "AMD AM29LV160DT", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, -- { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV160DT, -+ .name = "AMD AM29LV160DT", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, -+ { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV160DB, -- name: "AMD AM29LV160DB", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, -- { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV160DB, -+ .name = "AMD AM29LV160DB", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, -+ { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVT160, -- name: "Toshiba TC58FVT160", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, -- { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVT160, -+ .name = "Toshiba TC58FVT160", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, -+ { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV160TE, -- name: "Fujitsu MBM29LV160TE", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, -- { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV160TE, -+ .name = "Fujitsu MBM29LV160TE", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, -+ { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVB160, -- name: "Toshiba TC58FVB160", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, -- { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVB160, -+ .name = "Toshiba TC58FVB160", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, -+ { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV160BE, -- name: "Fujitsu MBM29LV160BE", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, -- { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV160BE, -+ .name = "Fujitsu MBM29LV160BE", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, -+ { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV800BB, -- name: "AMD AM29LV800BB", -- size: 0x00100000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, -- { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 15 } -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV800BB, -+ .name = "AMD AM29LV800BB", -+ .size = 0x00100000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, -+ { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 } - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F800BB, -- name: "AMD AM29F800BB", -- size: 0x00100000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, -- { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 15 } -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F800BB, -+ .name = "AMD AM29F800BB", -+ .size = 0x00100000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, -+ { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 } - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV800BT, -- name: "AMD AM29LV800BT", -- size: 0x00100000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, -- { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV800BT, -+ .name = "AMD AM29LV800BT", -+ .size = 0x00100000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, -+ { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F800BT, -- name: "AMD AM29F800BT", -- size: 0x00100000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, -- { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F800BT, -+ .name = "AMD AM29F800BT", -+ .size = 0x00100000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, -+ { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV800BB, -- name: "AMD AM29LV800BB", -- size: 0x00100000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, -- { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV800BB, -+ .name = "AMD AM29LV800BB", -+ .size = 0x00100000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, -+ { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV800BB, -- name: "Fujitsu MBM29LV800BB", -- size: 0x00100000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, -- { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 15 } -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV800BB, -+ .name = "Fujitsu MBM29LV800BB", -+ .size = 0x00100000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, -+ { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 } - } - }, { -- mfr_id: MANUFACTURER_ST, -- dev_id: M29W800T, -- name: "ST M29W800T", -- size: 0x00100000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, -- { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_ST, -+ .dev_id = M29W800T, -+ .name = "ST M29W800T", -+ .size = 0x00100000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, -+ { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_ST, -- dev_id: M29W160DT, -- name: "ST M29W160DT", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, -- { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } -+ .mfr_id = MANUFACTURER_ST, -+ .dev_id = M29W160DT, -+ .name = "ST M29W160DT", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, -+ { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } - } - }, { -- mfr_id: MANUFACTURER_ST, -- dev_id: M29W160DB, -- name: "ST M29W160DB", -- size: 0x00200000, -- numeraseregions: 4, -- regions: { -- { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, -- { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, -- { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } -+ .mfr_id = MANUFACTURER_ST, -+ .dev_id = M29W160DB, -+ .name = "ST M29W160DB", -+ .size = 0x00200000, -+ .numeraseregions = 4, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, -+ { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, -+ { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29BDS323D, -- name: "AMD AM29BDS323D", -- size: 0x00400000, -- numeraseregions: 3, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 48 }, -- { offset: 0x300000, erasesize: 0x10000, numblocks: 15 }, -- { offset: 0x3f0000, erasesize: 0x02000, numblocks: 8 }, -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29BDS323D, -+ .name = "AMD AM29BDS323D", -+ .size = 0x00400000, -+ .numeraseregions = 3, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 48 }, -+ { .offset = 0x300000, .erasesize = 0x10000, .numblocks = 15 }, -+ { .offset = 0x3f0000, .erasesize = 0x02000, .numblocks = 8 }, - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29BDS643D, -- name: "AMD AM29BDS643D", -- size: 0x00800000, -- numeraseregions: 3, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 96 }, -- { offset: 0x600000, erasesize: 0x10000, numblocks: 31 }, -- { offset: 0x7f0000, erasesize: 0x02000, numblocks: 8 }, -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29BDS643D, -+ .name = "AMD AM29BDS643D", -+ .size = 0x00800000, -+ .numeraseregions = 3, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 96 }, -+ { .offset = 0x600000, .erasesize = 0x10000, .numblocks = 31 }, -+ { .offset = 0x7f0000, .erasesize = 0x02000, .numblocks = 8 }, - } - }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT49xV16x, -- name: "Atmel AT49xV16x", -- size: 0x00200000, -- numeraseregions: 2, -- regions: { -- { offset: 0x000000, erasesize: 0x02000, numblocks: 8 }, -- { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT49xV16x, -+ .name = "Atmel AT49xV16x", -+ .size = 0x00200000, -+ .numeraseregions = 2, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x02000, .numblocks = 8 }, -+ { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } - } - }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT49xV16xT, -- name: "Atmel AT49xV16xT", -- size: 0x00200000, -- numeraseregions: 2, -- regions: { -- { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, -- { offset: 0x1F0000, erasesize: 0x02000, numblocks: 8 } -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT49xV16xT, -+ .name = "Atmel AT49xV16xT", -+ .size = 0x00200000, -+ .numeraseregions = 2, -+ .regions = { -+ { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, -+ { .offset = 0x1F0000, .erasesize = 0x02000, .numblocks = 8 } - } - } - }; -@@ -822,7 +820,7 @@ - - chip->state = FL_READY; - -- map->copy_from(map, buf, adr, len); -+ map_copy_from(map, buf, adr, len); - - wake_up(&chip->wq); - spin_unlock_bh(chip->mutex); -@@ -984,7 +982,7 @@ - u_char tmp_buf[4]; - __u32 datum; - -- map->copy_from(map, tmp_buf, -+ map_copy_from(map, tmp_buf, - bus_ofs + private->chips[chipnum].start, - map->buswidth); - while (len && i < map->buswidth) -@@ -1057,7 +1055,7 @@ - u_char tmp_buf[2]; - __u32 datum; - -- map->copy_from(map, tmp_buf, -+ map_copy_from(map, tmp_buf, - ofs + private->chips[chipnum].start, - map->buswidth); - while (len--) { -@@ -1178,7 +1176,7 @@ - __u8 verify; - - for (address = adr; address < (adr + size); address++) { -- if ((verify = map->read8(map, address)) != 0xFF) { -+ if ((verify = map_read8(map, address)) != 0xFF) { - error = 1; - break; - } -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/cfi_cmdset_0001.c linux/drivers/mtd/chips/cfi_cmdset_0001.c ---- linux-mips-2.4.27/drivers/mtd/chips/cfi_cmdset_0001.c 2003-07-05 05:23:38.000000000 +0200 -+++ linux/drivers/mtd/chips/cfi_cmdset_0001.c 2004-11-19 10:25:11.733225024 +0100 -@@ -4,7 +4,7 @@ - * - * (C) 2000 Red Hat. GPL'd - * -- * $Id$ -+ * $Id$ - * - * - * 10/10/2000 Nicolas Pitre -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -29,10 +30,14 @@ - #include - #include - #include --#include -+#include - #include -+#include -+ -+/* #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE */ - --// debugging, turns off buffer write mode #define FORCE_WORD_WRITE -+// debugging, turns off buffer write mode if set to 1 -+#define FORCE_WORD_WRITE 0 - - static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); - static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); -@@ -52,16 +57,21 @@ - - static struct mtd_info *cfi_intelext_setup (struct map_info *); - --static int do_point (struct mtd_info *mtd, loff_t from, size_t len, -+static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char **mtdbuf); --static void do_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, -+static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, - size_t len); - -+ -+/* -+ * *********** SETUP AND PROBE BITS *********** -+ */ -+ - static struct mtd_chip_driver cfi_intelext_chipdrv = { -- probe: NULL, /* Not usable directly */ -- destroy: cfi_intelext_destroy, -- name: "cfi_cmdset_0001", -- module: THIS_MODULE -+ .probe = NULL, /* Not usable directly */ -+ .destroy = cfi_intelext_destroy, -+ .name = "cfi_cmdset_0001", -+ .module = THIS_MODULE - }; - - /* #define DEBUG_LOCK_BITS */ -@@ -102,13 +112,63 @@ - } - - printk(" Vcc Logic Supply Optimum Program/Erase Voltage: %d.%d V\n", -- extp->VccOptimal >> 8, extp->VccOptimal & 0xf); -+ extp->VccOptimal >> 4, extp->VccOptimal & 0xf); - if (extp->VppOptimal) - printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n", -- extp->VppOptimal >> 8, extp->VppOptimal & 0xf); -+ extp->VppOptimal >> 4, extp->VppOptimal & 0xf); - } - #endif - -+#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE -+/* Some Intel Strata Flash prior to FPO revision C has bugs in this area */ -+static void fixup_intel_strataflash(struct map_info *map, void* param) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ struct cfi_pri_amdstd *extp = cfi->cmdset_priv; -+ -+ printk(KERN_WARNING "cfi_cmdset_0001: Suspend " -+ "erase on write disabled.\n"); -+ extp->SuspendCmdSupport &= ~1; -+} -+#endif -+ -+static void fixup_st_m28w320ct(struct map_info *map, void* param) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ -+ cfi->cfiq->BufWriteTimeoutTyp = 0; /* Not supported */ -+ cfi->cfiq->BufWriteTimeoutMax = 0; /* Not supported */ -+} -+ -+static void fixup_st_m28w320cb(struct map_info *map, void* param) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ -+ /* Note this is done after the region info is endian swapped */ -+ cfi->cfiq->EraseRegionInfo[1] = -+ (cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e; -+}; -+ -+static struct cfi_fixup fixup_table[] = { -+#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE -+ { -+ CFI_MFR_ANY, CFI_ID_ANY, -+ fixup_intel_strataflash, NULL -+ }, -+#endif -+ { -+ 0x0020, /* STMicroelectronics */ -+ 0x00ba, /* M28W320CT */ -+ fixup_st_m28w320ct, NULL -+ }, { -+ 0x0020, /* STMicroelectronics */ -+ 0x00bb, /* M28W320CB */ -+ fixup_st_m28w320cb, NULL -+ }, { -+ 0, 0, NULL, NULL -+ } -+}; -+ - /* This routine is made available to other mtd code via - * inter_module_register. It must only be accessed through - * inter_module_get which will bump the use count of this module. The -@@ -120,7 +180,6 @@ - { - struct cfi_private *cfi = map->fldrv_priv; - int i; -- __u32 base = cfi->chips[0].start; - - if (cfi->cfi_mode == CFI_MODE_CFI) { - /* -@@ -130,59 +189,29 @@ - */ - __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; - struct cfi_pri_intelext *extp; -- int ofs_factor = cfi->interleave * cfi->device_type; -- -- //printk(" Intel/Sharp Extended Query Table at 0x%4.4X\n", adr); -- if (!adr) -- return NULL; - -- /* Switch it into Query Mode */ -- cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); -- -- extp = kmalloc(sizeof(*extp), GFP_KERNEL); -- if (!extp) { -- printk(KERN_ERR "Failed to allocate memory\n"); -+ extp = (struct cfi_pri_intelext*)cfi_read_pri(map, adr, sizeof(*extp), "Intel/Sharp"); -+ if (!extp) - return NULL; -- } -- -- /* Read in the Extended Query Table */ -- for (i=0; iMajorVersion != '1' || -- (extp->MinorVersion < '0' || extp->MinorVersion > '3')) { -- printk(KERN_WARNING " Unknown IntelExt Extended Query " -- "version %c.%c.\n", extp->MajorVersion, -- extp->MinorVersion); -- kfree(extp); -- return NULL; -- } - - /* Do some byteswapping if necessary */ - extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport); - extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask); - extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr); - -+ /* Install our own private info structure */ -+ cfi->cmdset_priv = extp; -+ -+ cfi_fixup(map, fixup_table); -+ - #ifdef DEBUG_CFI_FEATURES - /* Tell the user about it in lots of lovely detail */ - cfi_tell_features(extp); - #endif - - if(extp->SuspendCmdSupport & 1) { --//#define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE --#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE --/* Some Intel Strata Flash prior to FPO revision C has bugs in this area */ -- printk(KERN_WARNING "cfi_cmdset_0001: Suspend " -- "erase on write disabled.\n"); -- extp->SuspendCmdSupport &= ~1; --#else - printk(KERN_NOTICE "cfi_cmdset_0001: Erase suspend on write enabled\n"); --#endif - } -- /* Install our own private info structure */ -- cfi->cmdset_priv = extp; - } - - for (i=0; i< cfi->numchips; i++) { -@@ -194,8 +223,6 @@ - - map->fldrv = &cfi_intelext_chipdrv; - -- /* Make sure it's in read mode */ -- cfi_send_gen_cmd(0xff, 0x55, base, map, cfi, cfi->device_type, NULL); - return cfi_intelext_setup(map); - } - -@@ -261,20 +288,16 @@ - mtd->erase = cfi_intelext_erase_varsize; - mtd->read = cfi_intelext_read; - -- if(map->point && map->unpoint){ -- mtd->point = do_point; -- mtd->unpoint = do_unpoint; -+ if (map_is_linear(map)) { -+ mtd->point = cfi_intelext_point; -+ mtd->unpoint = cfi_intelext_unpoint; - } - --#ifndef FORCE_WORD_WRITE -- if ( cfi->cfiq->BufWriteTimeoutTyp ) { -- printk("Using buffer write method\n" ); -+ if ( cfi->cfiq->BufWriteTimeoutTyp && !FORCE_WORD_WRITE) { -+ printk(KERN_INFO "Using buffer write method\n" ); - mtd->write = cfi_intelext_write_buffers; - } else { --#else -- { --#endif -- printk("Using word write method\n" ); -+ printk(KERN_INFO "Using word write method\n" ); - mtd->write = cfi_intelext_write_words; - } - mtd->read_user_prot_reg = cfi_intelext_read_user_prot_reg; -@@ -286,8 +309,8 @@ - mtd->resume = cfi_intelext_resume; - mtd->flags = MTD_CAP_NORFLASH; - map->fldrv = &cfi_intelext_chipdrv; -- MOD_INC_USE_COUNT; - mtd->name = map->name; -+ __module_get(THIS_MODULE); - return mtd; - - setup_err: -@@ -301,78 +324,170 @@ - return NULL; - } - --static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) -+/* -+ * *********** CHIP ACCESS FUNCTIONS *********** -+ */ -+ -+static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode) - { -- cfi_word status, status_OK; -- unsigned long timeo; - DECLARE_WAITQUEUE(wait, current); -- unsigned long cmd_addr; - struct cfi_private *cfi = map->fldrv_priv; -+ cfi_word status, status_OK = CMD(0x80); -+ unsigned long timeo; -+ struct cfi_pri_intelext *cfip = (struct cfi_pri_intelext *)cfi->cmdset_priv; - -- adr += chip->start; -- -- /* Ensure cmd read/writes are aligned. */ -- cmd_addr = adr & ~(CFIDEV_BUSWIDTH-1); -- -- /* Let's determine this according to the interleave only once */ -- status_OK = CMD(0x80); -- -+ resettime: - timeo = jiffies + HZ; - retry: -- spin_lock(chip->mutex); -- -- /* Check that the chip's ready to talk to us. -- * If it's in FL_ERASING state, suspend it and make it talk now. -- */ - switch (chip->state) { - -- case FL_READY: -- case FL_POINT: -+ case FL_STATUS: -+ for (;;) { -+ status = cfi_read(map, adr); -+ if ((status & status_OK) == status_OK) - break; - -+ if (time_after(jiffies, timeo)) { -+ printk(KERN_ERR "Waiting for chip to be ready timed out. Status %llx\n", -+ (long long)status); -+ spin_unlock(chip->mutex); -+ return -EIO; -+ } -+ spin_unlock(chip->mutex); -+ cfi_udelay(1); -+ spin_lock(chip->mutex); -+ /* Someone else might have been playing with it. */ -+ goto retry; -+ } -+ -+ case FL_READY: - case FL_CFI_QUERY: - case FL_JEDEC_QUERY: -- cfi_write(map, CMD(0x70), cmd_addr); -- chip->state = FL_STATUS; -+ return 0; - -- case FL_STATUS: -- status = cfi_read(map, cmd_addr); -- if ((status & status_OK) == status_OK) { -- cfi_write(map, CMD(0xff), cmd_addr); -- chip->state = FL_READY; -+ case FL_ERASING: -+ if (!(cfip->FeatureSupport & 2) || -+ !(mode == FL_READY || mode == FL_POINT || -+ (mode == FL_WRITING && (cfip->SuspendCmdSupport & 1)))) -+ goto sleep; -+ -+ -+ /* Erase suspend */ -+ cfi_write(map, CMD(0xB0), adr); -+ -+ /* If the flash has finished erasing, then 'erase suspend' -+ * appears to make some (28F320) flash devices switch to -+ * 'read' mode. Make sure that we switch to 'read status' -+ * mode so we get the right data. --rmk -+ */ -+ cfi_write(map, CMD(0x70), adr); -+ chip->oldstate = FL_ERASING; -+ chip->state = FL_ERASE_SUSPENDING; -+ chip->erase_suspended = 1; -+ for (;;) { -+ status = cfi_read(map, adr); -+ if ((status & status_OK) == status_OK) - break; -- } - -- /* Urgh. Chip not yet ready to talk to us. */ - if (time_after(jiffies, timeo)) { -- spin_unlock(chip->mutex); -- printk(KERN_ERR "waiting for chip to be ready timed out in read. WSM status = %llx\n", (__u64)status); -+ /* Urgh. Resume and pretend we weren't here. */ -+ cfi_write(map, CMD(0xd0), adr); -+ /* Make sure we're in 'read status' mode if it had finished */ -+ cfi_write(map, CMD(0x70), adr); -+ chip->state = FL_ERASING; -+ chip->oldstate = FL_READY; -+ printk(KERN_ERR "Chip not ready after erase " -+ "suspended: status = 0x%x\n", status); - return -EIO; - } - -- /* Latency issues. Drop the lock, wait a while and retry */ - spin_unlock(chip->mutex); - cfi_udelay(1); -- goto retry; -+ spin_lock(chip->mutex); -+ /* Nobody will touch it while it's in state FL_ERASE_SUSPENDING. -+ So we can just loop here. */ -+ } -+ chip->state = FL_STATUS; -+ return 0; -+ -+ case FL_POINT: -+ /* Only if there's no operation suspended... */ -+ if (mode == FL_READY && chip->oldstate == FL_READY) -+ return 0; - - default: -- /* Stick ourselves on a wait queue to be woken when -- someone changes the status */ -+ sleep: - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); -- timeo = jiffies + HZ; -- goto retry; -+ spin_lock(chip->mutex); -+ goto resettime; - } -+} -+ -+static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ -+ switch(chip->oldstate) { -+ case FL_ERASING: -+ chip->state = chip->oldstate; -+ /* What if one interleaved chip has finished and the -+ other hasn't? The old code would leave the finished -+ one in READY mode. That's bad, and caused -EROFS -+ errors to be returned from do_erase_oneblock because -+ that's the only bit it checked for at the time. -+ As the state machine appears to explicitly allow -+ sending the 0x70 (Read Status) command to an erasing -+ chip and expecting it to be ignored, that's what we -+ do. */ -+ cfi_write(map, CMD(0xd0), adr); -+ cfi_write(map, CMD(0x70), adr); -+ chip->oldstate = FL_READY; -+ chip->state = FL_ERASING; -+ break; -+ -+ case FL_READY: -+ case FL_STATUS: -+ /* We should really make set_vpp() count, rather than doing this */ -+ DISABLE_VPP(map); -+ break; -+ default: -+ printk(KERN_ERR "put_chip() called with oldstate %d!!\n", chip->oldstate); -+ } -+ wake_up(&chip->wq); -+} -+ -+static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) -+{ -+ unsigned long cmd_addr; -+ struct cfi_private *cfi = map->fldrv_priv; -+ int ret = 0; -+ -+ adr += chip->start; -+ -+ /* Ensure cmd read/writes are aligned. */ -+ cmd_addr = adr & ~(CFIDEV_BUSWIDTH-1); -+ -+ spin_lock(chip->mutex); -+ -+ ret = get_chip(map, chip, cmd_addr, FL_POINT); -+ -+ if (!ret) { -+ if (chip->state != FL_POINT && chip->state != FL_READY) -+ cfi_write(map, CMD(0xff), cmd_addr); - - chip->state = FL_POINT; - chip->ref_point_counter++; -+ } - spin_unlock(chip->mutex); -- return 0; -+ -+ return ret; - } --static int do_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) -+ -+static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) - { - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; -@@ -380,12 +495,10 @@ - int chipnum; - int ret = 0; - -- if (from + len > mtd->size) -+ if (!map->virt || (from + len > mtd->size)) - return -EINVAL; - -- *mtdbuf = map->point(map, from, len); -- if(*mtdbuf == NULL) -- return -EINVAL; /* can not point this region */ -+ *mtdbuf = (void *)map->virt + from; - *retlen = 0; - - /* Now lock the chip(s) to POINT state */ -@@ -418,14 +531,13 @@ - return 0; - } - --static void do_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) -+static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) - { - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - unsigned long ofs; - int chipnum; - -- map->unpoint(map, addr, from, len); - /* Now unlock the chip(s) POINT state */ - - /* ofs: offset within the first chip that the first read should start */ -@@ -446,13 +558,14 @@ - thislen = len; - - spin_lock(chip->mutex); -- if(chip->state == FL_POINT){ -+ if (chip->state == FL_POINT) { - chip->ref_point_counter--; - if(chip->ref_point_counter == 0) - chip->state = FL_READY; - } else -- printk("Warning: unpoint called on non pointed region\n"); /* Should this give an error? */ -- wake_up(&chip->wq); -+ printk(KERN_ERR "Warning: unpoint called on non pointed region\n"); /* Should this give an error? */ -+ -+ put_chip(map, chip, chip->start); - spin_unlock(chip->mutex); - - len -= thislen; -@@ -463,136 +576,32 @@ - - static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) - { -- cfi_word status, status_OK; -- unsigned long timeo; -- DECLARE_WAITQUEUE(wait, current); -- int suspended = 0; - unsigned long cmd_addr; - struct cfi_private *cfi = map->fldrv_priv; -+ int ret; - - adr += chip->start; - - /* Ensure cmd read/writes are aligned. */ - cmd_addr = adr & ~(CFIDEV_BUSWIDTH-1); - -- /* Let's determine this according to the interleave only once */ -- status_OK = CMD(0x80); -- -- timeo = jiffies + HZ; -- retry: - spin_lock(chip->mutex); -- -- /* Check that the chip's ready to talk to us. -- * If it's in FL_ERASING state, suspend it and make it talk now. -- */ -- switch (chip->state) { -- case FL_ERASING: -- if (!cfi->cmdset_priv || -- !(((struct cfi_pri_intelext *)cfi->cmdset_priv)->FeatureSupport & 2)) -- goto sleep; /* We don't support erase suspend */ -- -- cfi_write (map, CMD(0xb0), cmd_addr); -- /* If the flash has finished erasing, then 'erase suspend' -- * appears to make some (28F320) flash devices switch to -- * 'read' mode. Make sure that we switch to 'read status' -- * mode so we get the right data. --rmk -- */ -- cfi_write(map, CMD(0x70), cmd_addr); -- chip->oldstate = FL_ERASING; -- chip->state = FL_ERASE_SUSPENDING; -- // printk("Erase suspending at 0x%lx\n", cmd_addr); -- for (;;) { -- status = cfi_read(map, cmd_addr); -- if ((status & status_OK) == status_OK) -- break; -- -- if (time_after(jiffies, timeo)) { -- /* Urgh */ -- cfi_write(map, CMD(0xd0), cmd_addr); -- /* make sure we're in 'read status' mode */ -- cfi_write(map, CMD(0x70), cmd_addr); -- chip->state = FL_ERASING; -- spin_unlock(chip->mutex); -- printk(KERN_ERR "Chip not ready after erase " -- "suspended: status = 0x%llx\n", (__u64)status); -- return -EIO; -- } -- -+ ret = get_chip(map, chip, cmd_addr, FL_READY); -+ if (ret) { - spin_unlock(chip->mutex); -- cfi_udelay(1); -- spin_lock(chip->mutex); -+ return ret; - } - -- suspended = 1; -+ if (chip->state != FL_POINT && chip->state != FL_READY) { - cfi_write(map, CMD(0xff), cmd_addr); -- chip->state = FL_READY; -- break; -- --#if 0 -- case FL_WRITING: -- /* Not quite yet */ --#endif -- -- case FL_READY: -- case FL_POINT: -- break; -- -- case FL_CFI_QUERY: -- case FL_JEDEC_QUERY: -- cfi_write(map, CMD(0x70), cmd_addr); -- chip->state = FL_STATUS; - -- case FL_STATUS: -- status = cfi_read(map, cmd_addr); -- if ((status & status_OK) == status_OK) { -- cfi_write(map, CMD(0xff), cmd_addr); - chip->state = FL_READY; -- break; - } - -- /* Urgh. Chip not yet ready to talk to us. */ -- if (time_after(jiffies, timeo)) { -- spin_unlock(chip->mutex); -- printk(KERN_ERR "waiting for chip to be ready timed out in read. WSM status = %llx\n", (__u64)status); -- return -EIO; -- } -+ map_copy_from(map, buf, adr, len); - -- /* Latency issues. Drop the lock, wait a while and retry */ -- spin_unlock(chip->mutex); -- cfi_udelay(1); -- goto retry; -+ put_chip(map, chip, cmd_addr); - -- default: -- sleep: -- /* Stick ourselves on a wait queue to be woken when -- someone changes the status */ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -- spin_unlock(chip->mutex); -- schedule(); -- remove_wait_queue(&chip->wq, &wait); -- timeo = jiffies + HZ; -- goto retry; -- } -- -- map->copy_from(map, buf, adr, len); -- -- if (suspended) { -- chip->state = chip->oldstate; -- /* What if one interleaved chip has finished and the -- other hasn't? The old code would leave the finished -- one in READY mode. That's bad, and caused -EROFS -- errors to be returned from do_erase_oneblock because -- that's the only bit it checked for at the time. -- As the state machine appears to explicitly allow -- sending the 0x70 (Read Status) command to an erasing -- chip and expecting it to be ignored, that's what we -- do. */ -- cfi_write(map, CMD(0xd0), cmd_addr); -- cfi_write(map, CMD(0x70), cmd_addr); -- } -- -- wake_up(&chip->wq); - spin_unlock(chip->mutex); - return 0; - } -@@ -640,70 +649,52 @@ - { - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; -- struct cfi_pri_intelext *extp=cfi->cmdset_priv; -- int ofs_factor = cfi->interleave * cfi->device_type; -- int count=len; -+ struct cfi_pri_intelext *extp = cfi->cmdset_priv; - struct flchip *chip; -- int chip_num,offst; -- unsigned long timeo; -- DECLARE_WAITQUEUE(wait, current); -+ int ofs_factor = cfi->interleave * cfi->device_type; -+ int count = len; -+ int chip_num, offst; -+ int ret; - -- chip=0; -- /* Calculate which chip & protection register offset we need */ -- chip_num=((unsigned int)from/reg_sz); -- offst=from-(reg_sz*chip_num)+base_offst; -+ chip_num = ((unsigned int)from/reg_sz); -+ offst = from - (reg_sz*chip_num)+base_offst; - -- while(count){ -+ while (count) { -+ /* Calculate which chip & protection register offset we need */ - -- if(chip_num>=cfi->numchips) -+ if (chip_num >= cfi->numchips) - goto out; - -- /* Make sure that the chip is in the right state */ -+ chip = &cfi->chips[chip_num]; - -- timeo = jiffies + HZ; -- chip=&cfi->chips[chip_num]; -- retry: - spin_lock(chip->mutex); -- -- switch (chip->state) { -- case FL_READY: -- case FL_STATUS: -- case FL_CFI_QUERY: -- case FL_JEDEC_QUERY: -- break; -- -- default: -- /* Stick ourselves on a wait queue to be woken when -- someone changes the status */ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ ret = get_chip(map, chip, chip->start, FL_JEDEC_QUERY); -+ if (ret) { - spin_unlock(chip->mutex); -- schedule(); -- remove_wait_queue(&chip->wq, &wait); -- timeo = jiffies + HZ; -- goto retry; -+ return (len-count)?:ret; - } - -- /* Now read the data required from this flash */ -+ if (chip->state != FL_JEDEC_QUERY) { -+ cfi_write(map, CMD(0x90), chip->start); -+ chip->state = FL_JEDEC_QUERY; -+ } - -- cfi_send_gen_cmd(0x90, 0x55,chip->start, map, cfi, cfi->device_type, NULL); -- while(count && ((offst-base_offst)read8(map,(chip->start+((extp->ProtRegAddr+1)*ofs_factor)+offst)); -+ while (count && ((offst-base_offst) < reg_sz)) { -+ *buf = map_read8(map,(chip->start+((extp->ProtRegAddr+1)*ofs_factor)+offst)); - buf++; - offst++; - count--; - } - -- chip->state=FL_CFI_QUERY; -+ put_chip(map, chip, chip->start); - spin_unlock(chip->mutex); -+ - /* Move on to the next chip */ - chip_num++; -- offst=base_offst; -- -+ offst = base_offst; - } - - out: -- wake_up(&chip->wq); - return len-count; - } - -@@ -749,103 +740,20 @@ - static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, cfi_word datum) - { - struct cfi_private *cfi = map->fldrv_priv; -- struct cfi_pri_intelext *extp = cfi->cmdset_priv; -- cfi_word status, status_OK; -- unsigned long timeo; -- DECLARE_WAITQUEUE(wait, current); -- int z, suspended=0, ret=0; -- -- adr += chip->start; -- -- /* Let's determine this according to the interleave only once */ -- status_OK = CMD(0x80); -- -- timeo = jiffies + HZ; -- retry: -- spin_lock(chip->mutex); -- -- /* Check that the chip's ready to talk to us. -- * Later, we can actually think about interrupting it -- * if it's in FL_ERASING state. -- * Not just yet, though. -- */ -- switch (chip->state) { -- case FL_READY: -- break; -- -- case FL_CFI_QUERY: -- case FL_JEDEC_QUERY: -- cfi_write(map, CMD(0x70), adr); -- chip->state = FL_STATUS; -- -- case FL_STATUS: -- status = cfi_read(map, adr); -- if ((status & status_OK) == status_OK) -- break; -- -- /* Urgh. Chip not yet ready to talk to us. */ -- if (time_after(jiffies, timeo)) { -- spin_unlock(chip->mutex); -- printk(KERN_ERR "waiting for chip to be ready timed out in read\n"); -- return -EIO; -- } -- -- /* Latency issues. Drop the lock, wait a while and retry */ -- spin_unlock(chip->mutex); -- cfi_udelay(1); -- goto retry; -- -- case FL_ERASING: -- if (!extp || -- !((extp->FeatureSupport & 2) && (extp->SuspendCmdSupport & 1))) -- goto sleep; /* We don't support erase suspend */ -- -- cfi_write (map, CMD(0xb0), adr); -- -- /* If the flash has finished erasing, then 'erase suspend' -- * appears to make some (28F320) flash devices switch to -- * 'read' mode. Make sure that we switch to 'read status' -- * mode so we get the right data. --rmk -- */ -- cfi_write(map, CMD(0x70), adr); -- chip->oldstate = FL_ERASING; -- chip->state = FL_ERASE_SUSPENDING; -- for (;;) { -- status = cfi_read(map, adr); -- if ((status & status_OK) == status_OK) -- break; -+ cfi_word status, status_OK; -+ unsigned long timeo; -+ int z, ret=0; - -- if (time_after(jiffies, timeo)) { -- /* Urgh */ -- cfi_write(map, CMD(0xd0), adr); -- /* make sure we're in 'read status' mode */ -- cfi_write(map, CMD(0x70), adr); -- chip->state = FL_ERASING; -- spin_unlock(chip->mutex); -- printk(KERN_ERR "Chip not ready after erase " -- "suspended: status = 0x%x\n", status); -- return -EIO; -- } -+ adr += chip->start; - -- spin_unlock(chip->mutex); -- cfi_udelay(1); -- spin_lock(chip->mutex); -- } -- suspended = 1; -- chip->state = FL_STATUS; -- break; -+ /* Let's determine this according to the interleave only once */ -+ status_OK = CMD(0x80); - -- default: -- sleep: -- /* Stick ourselves on a wait queue to be woken when -- someone changes the status */ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ spin_lock(chip->mutex); -+ ret = get_chip(map, chip, adr, FL_WRITING); -+ if (ret) { - spin_unlock(chip->mutex); -- schedule(); -- remove_wait_queue(&chip->wq, &wait); -- timeo = jiffies + HZ; -- goto retry; -+ return ret; - } - - ENABLE_VPP(map); -@@ -862,6 +770,8 @@ - for (;;) { - if (chip->state != FL_WRITING) { - /* Someone's suspended the write. Sleep */ -+ DECLARE_WAITQUEUE(wait, current); -+ - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - spin_unlock(chip->mutex); -@@ -879,7 +789,6 @@ - /* OK Still waiting */ - if (time_after(jiffies, timeo)) { - chip->state = FL_STATUS; -- DISABLE_VPP(map); - printk(KERN_ERR "waiting for chip to be ready timed out in word write\n"); - ret = -EIO; - goto out; -@@ -908,27 +817,11 @@ - /* put back into read status register mode */ - cfi_write(map, CMD(0x70), adr); - ret = -EROFS; -- goto out; - } - out: -- if (suspended) { -- chip->state = chip->oldstate; -- /* What if one interleaved chip has finished and the -- other hasn't? The old code would leave the finished -- one in READY mode. That's bad, and caused -EROFS -- errors to be returned from do_erase_oneblock because -- that's the only bit it checked for at the time. -- As the state machine appears to explicitly allow -- sending the 0x70 (Read Status) command to an erasing -- chip and expecting it to be ignored, that's what we -- do. */ -- cfi_write(map, CMD(0xd0), adr); -- cfi_write(map, CMD(0x70), adr); -- } else -- DISABLE_VPP(map); /* must not clear the VPP if there is a suspended erase to be resumed */ -- -- wake_up(&chip->wq); -+ put_chip(map, chip, adr); - spin_unlock(chip->mutex); -+ - return ret; - } - -@@ -1059,11 +952,9 @@ - unsigned long adr, const u_char *buf, int len) - { - struct cfi_private *cfi = map->fldrv_priv; -- struct cfi_pri_intelext *extp = cfi->cmdset_priv; - cfi_word status, status_OK; - unsigned long cmd_adr, timeo; -- DECLARE_WAITQUEUE(wait, current); -- int wbufsize, z, suspended=0, ret=0; -+ int wbufsize, z, ret=0, bytes, words; - - wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize; - adr += chip->start; -@@ -1072,91 +963,18 @@ - /* Let's determine this according to the interleave only once */ - status_OK = CMD(0x80); - -- timeo = jiffies + HZ; -- retry: - spin_lock(chip->mutex); -- -- /* Check that the chip's ready to talk to us. -- * Later, we can actually think about interrupting it -- * if it's in FL_ERASING state. -- * Not just yet, though. -- */ -- switch (chip->state) { -- case FL_READY: -- case FL_CFI_QUERY: -- case FL_JEDEC_QUERY: -- cfi_write(map, CMD(0x70), cmd_adr); -- chip->state = FL_STATUS; -- -- case FL_STATUS: -- status = cfi_read(map, cmd_adr); -- if ((status & status_OK) == status_OK) -- break; -- /* Urgh. Chip not yet ready to talk to us. */ -- if (time_after(jiffies, timeo)) { -+ ret = get_chip(map, chip, cmd_adr, FL_WRITING); -+ if (ret) { - spin_unlock(chip->mutex); -- printk(KERN_ERR "waiting for chip to be ready timed out in buffer write\n"); -- return -EIO; -+ return ret; - } - -- /* Latency issues. Drop the lock, wait a while and retry */ -- spin_unlock(chip->mutex); -- cfi_udelay(1); -- goto retry; -- -- case FL_ERASING: -- if (!extp || -- !((extp->FeatureSupport & 2) && (extp->SuspendCmdSupport & 1))) -- goto sleep; /* We don't support erase suspend */ -- -- cfi_write (map, CMD(0xb0), adr); -- -- /* If the flash has finished erasing, then 'erase suspend' -- * appears to make some (28F320) flash devices switch to -- * 'read' mode. Make sure that we switch to 'read status' -- * mode so we get the right data. --rmk -- */ -- cfi_write(map, CMD(0x70), adr); -- chip->oldstate = FL_ERASING; -- chip->state = FL_ERASE_SUSPENDING; -- for (;;) { -- status = cfi_read(map, adr); -- if ((status & status_OK) == status_OK) -- break; -- -- if (time_after(jiffies, timeo)) { -- /* Urgh */ -- cfi_write(map, CMD(0xd0), adr); -- /* make sure we're in 'read status' mode */ -- cfi_write(map, CMD(0x70), adr); -- chip->state = FL_ERASING; -- spin_unlock(chip->mutex); -- printk(KERN_ERR "Chip not ready after erase " -- "suspended: status = 0x%x\n", status); -- return -EIO; -- } -+ if (chip->state != FL_STATUS) -+ cfi_write(map, CMD(0x70), cmd_adr); - -- spin_unlock(chip->mutex); -- cfi_udelay(1); -- spin_lock(chip->mutex); -- } -- suspended = 1; -- chip->state = FL_STATUS; -- break; -+ status = cfi_read(map, cmd_adr); - -- default: -- sleep: -- /* Stick ourselves on a wait queue to be woken when -- someone changes the status */ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -- spin_unlock(chip->mutex); -- schedule(); -- remove_wait_queue(&chip->wq, &wait); -- timeo = jiffies + HZ; -- goto retry; -- } -- /* We know we're now in FL_STATUS mode, and 'status' is current */ - /* §4.8 of the 28FxxxJ3A datasheet says "Any time SR.4 and/or SR.5 is set - [...], the device will not accept any more Write to Buffer commands". - So we must check here and reset those bits if they're set. Otherwise -@@ -1185,7 +1003,6 @@ - /* Argh. Not ready for write to buffer */ - cfi_write(map, CMD(0x70), cmd_adr); - chip->state = FL_STATUS; -- DISABLE_VPP(map); - printk(KERN_ERR "Chip not ready for buffer write. Xstatus = %llx, status = %llx\n", (__u64)status, (__u64)cfi_read(map, cmd_adr)); - /* Odd. Clear status bits */ - cfi_write(map, CMD(0x50), cmd_adr); -@@ -1196,20 +1013,42 @@ - } - - /* Write length of data to come */ -- cfi_write(map, CMD(len/CFIDEV_BUSWIDTH-1), cmd_adr ); -+ bytes = len & (CFIDEV_BUSWIDTH-1); -+ words = len / CFIDEV_BUSWIDTH; -+ cfi_write(map, CMD(words - !bytes), cmd_adr ); - - /* Write data */ -- for (z = 0; z < len; z += CFIDEV_BUSWIDTH) { -+ z = 0; -+ while(z < words * CFIDEV_BUSWIDTH) { - if (cfi_buswidth_is_1()) { -- map->write8 (map, *((__u8*)buf)++, adr+z); -+ map_write8 (map, *((__u8*)buf)++, adr+z); - } else if (cfi_buswidth_is_2()) { -- map->write16 (map, *((__u16*)buf)++, adr+z); -+ map_write16 (map, *((__u16*)buf)++, adr+z); - } else if (cfi_buswidth_is_4()) { -- map->write32 (map, *((__u32*)buf)++, adr+z); -+ map_write32 (map, *((__u32*)buf)++, adr+z); - } else if (cfi_buswidth_is_8()) { -- map->write64 (map, *((__u64*)buf)++, adr+z); -+ map_write64 (map, *((__u64*)buf)++, adr+z); -+ } else { -+ ret = -EINVAL; -+ goto out; -+ } -+ z += CFIDEV_BUSWIDTH; -+ } -+ if (bytes) { -+ int i = 0, n = 0; -+ u_char tmp_buf[8], *tmp_p = tmp_buf; -+ -+ while (bytes--) -+ tmp_buf[i++] = buf[n++]; -+ while (i < CFIDEV_BUSWIDTH) -+ tmp_buf[i++] = 0xff; -+ if (cfi_buswidth_is_2()) { -+ map_write16 (map, *((__u16*)tmp_p)++, adr+z); -+ } else if (cfi_buswidth_is_4()) { -+ map_write32 (map, *((__u32*)tmp_p)++, adr+z); -+ } else if (cfi_buswidth_is_8()) { -+ map_write64 (map, *((__u64*)tmp_p)++, adr+z); - } else { -- DISABLE_VPP(map); - ret = -EINVAL; - goto out; - } -@@ -1227,6 +1066,7 @@ - for (;;) { - if (chip->state != FL_WRITING) { - /* Someone's suspended the write. Sleep */ -+ DECLARE_WAITQUEUE(wait, current); - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - spin_unlock(chip->mutex); -@@ -1244,7 +1084,6 @@ - /* OK Still waiting */ - if (time_after(jiffies, timeo)) { - chip->state = FL_STATUS; -- DISABLE_VPP(map); - printk(KERN_ERR "waiting for chip to be ready timed out in bufwrite\n"); - ret = -EIO; - goto out; -@@ -1266,6 +1105,7 @@ - - /* Done and happy. */ - chip->state = FL_STATUS; -+ - /* check for lock bit */ - if (status & CMD(0x02)) { - /* clear status */ -@@ -1273,26 +1113,10 @@ - /* put back into read status register mode */ - cfi_write(map, CMD(0x70), adr); - ret = -EROFS; -- goto out; - } -- out: -- if (suspended) { -- chip->state = chip->oldstate; -- /* What if one interleaved chip has finished and the -- other hasn't? The old code would leave the finished -- one in READY mode. That's bad, and caused -EROFS -- errors to be returned from do_erase_oneblock because -- that's the only bit it checked for at the time. -- As the state machine appears to explicitly allow -- sending the 0x70 (Read Status) command to an erasing -- chip and expecting it to be ignored, that's what we -- do. */ -- cfi_write(map, CMD(0xd0), adr); -- cfi_write(map, CMD(0x70), adr); -- } else -- DISABLE_VPP(map); /* must not clear the VPP if there is a suspended erase to be resumed */ - -- wake_up(&chip->wq); -+ out: -+ put_chip(map, chip, cmd_adr); - spin_unlock(chip->mutex); - return ret; - } -@@ -1336,12 +1160,12 @@ - } - - /* Write buffer is worth it only if more than one word to write... */ -- while(len > CFIDEV_BUSWIDTH) { -+ while(len) { - /* We must not cross write block boundaries */ - int size = wbufsize - (ofs & (wbufsize-1)); - - if (size > len) -- size = len & ~(CFIDEV_BUSWIDTH-1); -+ size = len; - ret = do_write_buffer(map, &cfi->chips[chipnum], - ofs, buf, size); - if (ret) -@@ -1359,17 +1183,6 @@ - return 0; - } - } -- -- /* ... and write the remaining bytes */ -- if (len > 0) { -- size_t local_retlen; -- ret = cfi_intelext_write_words(mtd, ofs + (chipnum << cfi->chipshift), -- len, &local_retlen, buf); -- if (ret) -- return ret; -- (*retlen) += local_retlen; -- } -- - return 0; - } - -@@ -1479,45 +1292,12 @@ - /* Let's determine this according to the interleave only once */ - status_OK = CMD(0x80); - -- timeo = jiffies + HZ; --retry: -+ retry: - spin_lock(chip->mutex); -- -- /* Check that the chip's ready to talk to us. */ -- switch (chip->state) { -- case FL_CFI_QUERY: -- case FL_JEDEC_QUERY: -- case FL_READY: -- cfi_write(map, CMD(0x70), adr); -- chip->state = FL_STATUS; -- -- case FL_STATUS: -- status = cfi_read(map, adr); -- if ((status & status_OK) == status_OK) -- break; -- -- /* Urgh. Chip not yet ready to talk to us. */ -- if (time_after(jiffies, timeo)) { -- spin_unlock(chip->mutex); -- printk(KERN_ERR "waiting for chip to be ready timed out in erase\n"); -- return -EIO; -- } -- -- /* Latency issues. Drop the lock, wait a while and retry */ -- spin_unlock(chip->mutex); -- cfi_udelay(1); -- goto retry; -- -- default: -- /* Stick ourselves on a wait queue to be woken when -- someone changes the status */ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ ret = get_chip(map, chip, adr, FL_ERASING); -+ if (ret) { - spin_unlock(chip->mutex); -- schedule(); -- remove_wait_queue(&chip->wq, &wait); -- timeo = jiffies + HZ; -- goto retry; -+ return ret; - } - - ENABLE_VPP(map); -@@ -1528,7 +1308,7 @@ - cfi_write(map, CMD(0x20), adr); - cfi_write(map, CMD(0xD0), adr); - chip->state = FL_ERASING; -- chip->oldstate = 0; -+ chip->erase_suspended = 0; - - spin_unlock(chip->mutex); - set_current_state(TASK_UNINTERRUPTIBLE); -@@ -1550,11 +1330,11 @@ - spin_lock(chip->mutex); - continue; - } -- if (chip->oldstate) { -+ if (chip->erase_suspended) { - /* This erase was suspended and resumed. - Adjust the timeout */ - timeo = jiffies + (HZ*20); /* FIXME */ -- chip->oldstate = 0; -+ chip->erase_suspended = 0; - } - - status = cfi_read(map, adr); -@@ -1658,39 +1438,22 @@ - int i; - struct flchip *chip; - int ret = 0; -- DECLARE_WAITQUEUE(wait, current); - - for (i=0; !ret && inumchips; i++) { - chip = &cfi->chips[i]; - -- retry: - spin_lock(chip->mutex); -+ ret = get_chip(map, chip, chip->start, FL_SYNCING); - -- switch(chip->state) { -- case FL_READY: -- case FL_STATUS: -- case FL_CFI_QUERY: -- case FL_JEDEC_QUERY: -+ if (!ret) { - chip->oldstate = chip->state; - chip->state = FL_SYNCING; - /* No need to wake_up() on this state change - - * as the whole point is that nobody can do anything - * with the chip now anyway. - */ -- case FL_SYNCING: -- spin_unlock(chip->mutex); -- break; -- -- default: -- /* Not an idle state */ -- add_wait_queue(&chip->wq, &wait); -- -- spin_unlock(chip->mutex); -- schedule(); -- remove_wait_queue(&chip->wq, &wait); -- -- goto retry; - } -+ spin_unlock(chip->mutex); - } - - /* Unlock the chips again */ -@@ -1731,52 +1494,18 @@ - struct cfi_private *cfi = map->fldrv_priv; - cfi_word status, status_OK; - unsigned long timeo = jiffies + HZ; -- DECLARE_WAITQUEUE(wait, current); -+ int ret; - - adr += chip->start; - - /* Let's determine this according to the interleave only once */ - status_OK = CMD(0x80); - -- timeo = jiffies + HZ; --retry: - spin_lock(chip->mutex); -- -- /* Check that the chip's ready to talk to us. */ -- switch (chip->state) { -- case FL_CFI_QUERY: -- case FL_JEDEC_QUERY: -- case FL_READY: -- cfi_write(map, CMD(0x70), adr); -- chip->state = FL_STATUS; -- -- case FL_STATUS: -- status = cfi_read(map, adr); -- if ((status & status_OK) == status_OK) -- break; -- -- /* Urgh. Chip not yet ready to talk to us. */ -- if (time_after(jiffies, timeo)) { -- spin_unlock(chip->mutex); -- printk(KERN_ERR "%s: waiting for chip to be ready timed out\n", __FUNCTION__); -- return -EIO; -- } -- -- /* Latency issues. Drop the lock, wait a while and retry */ -- spin_unlock(chip->mutex); -- cfi_udelay(1); -- goto retry; -- -- default: -- /* Stick ourselves on a wait queue to be woken when -- someone changes the status */ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ ret = get_chip(map, chip, adr, FL_LOCKING); -+ if (ret) { - spin_unlock(chip->mutex); -- schedule(); -- remove_wait_queue(&chip->wq, &wait); -- timeo = jiffies + HZ; -- goto retry; -+ return ret; - } - - ENABLE_VPP(map); -@@ -1823,8 +1552,7 @@ - - /* Done and happy. */ - chip->state = FL_STATUS; -- DISABLE_VPP(map); -- wake_up(&chip->wq); -+ put_chip(map, chip, adr); - spin_unlock(chip->mutex); - return 0; - } -@@ -1889,22 +1617,23 @@ - - spin_lock(chip->mutex); - -- switch(chip->state) { -+ switch (chip->state) { - case FL_READY: - case FL_STATUS: - case FL_CFI_QUERY: - case FL_JEDEC_QUERY: -+ if (chip->oldstate == FL_READY) { - chip->oldstate = chip->state; - chip->state = FL_PM_SUSPENDED; - /* No need to wake_up() on this state change - - * as the whole point is that nobody can do anything - * with the chip now anyway. - */ -- case FL_PM_SUSPENDED: -+ } - break; -- - default: - ret = -EAGAIN; -+ case FL_PM_SUSPENDED: - break; - } - spin_unlock(chip->mutex); -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/cfi_cmdset_0002.c linux/drivers/mtd/chips/cfi_cmdset_0002.c ---- linux-mips-2.4.27/drivers/mtd/chips/cfi_cmdset_0002.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/chips/cfi_cmdset_0002.c 2004-11-19 10:25:11.745223200 +0100 -@@ -6,16 +6,22 @@ - * - * 2_by_8 routines added by Simon Munton - * -+ * 4_by_16 work by Carolyn J. Smith -+ * -+ * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com -+ * - * This code is GPL - * -- * $Id$ -+ * $Id$ - * - */ - -+#include - #include - #include - #include - #include -+#include - #include - #include - -@@ -23,16 +29,50 @@ - #include - #include - #include -+#include - #include -+#include - #include - - #define AMD_BOOTLOC_BUG -+#define FORCE_WORD_WRITE 0 -+ -+ -+/* -+ * This is an attempt to coalesce the retry logic in one place - that way -+ * there aren't #ifdefs scattered throughout. -+ */ -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+ -+#ifndef CONFIG_MTD_CFI_AMDSTD_RETRY_MAX -+#define CONFIG_MTD_CFI_AMDSTD_RETRY_MAX 0 -+#endif -+ -+#define RETRY_CMD_LABEL retry_cmd: do {} while (0) -+#define HANDLE_WACKY_STATE() handle_wacky_state(__func__, retry_cmd_cnt, adr, datum, prev_oldstatus, prev_status, oldstatus, status) -+static int retry_cmd_max = CONFIG_MTD_CFI_AMDSTD_RETRY_MAX; -+#define DECLARE_RETRY_CMD_CNT() int retry_cmd_cnt = 0 -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+#define CHECK_RETRIES() do { if (++retry_cmd_cnt <= retry_cmd_max) goto retry_cmd; } while (0) -+#endif -+ -+#else -+ -+#define RETRY_CMD_LABEL do {} while (0) -+#define HANDLE_WACKY_STATE() handle_wacky_state(__func__, adr, datum, prev_oldstatus, prev_status, oldstatus, status) -+#define DECLARE_RETRY_CMD_CNT() -+#define CHECK_RETRIES() -+ -+#endif /* !defined(CONFIG_MTD_CFI_AMDSTD_RETRY) */ -+ - - static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); --static int cfi_amdstd_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -+static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -+static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); - static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *); --static int cfi_amdstd_erase_onesize(struct mtd_info *, struct erase_info *); - static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *); -+static int cfi_amdstd_lock_varsize(struct mtd_info *, loff_t, size_t); -+static int cfi_amdstd_unlock_varsize(struct mtd_info *, loff_t, size_t); - static void cfi_amdstd_sync (struct mtd_info *); - static int cfi_amdstd_suspend (struct mtd_info *); - static void cfi_amdstd_resume (struct mtd_info *); -@@ -45,55 +85,136 @@ - - - static struct mtd_chip_driver cfi_amdstd_chipdrv = { -- probe: NULL, /* Not usable directly */ -- destroy: cfi_amdstd_destroy, -- name: "cfi_cmdset_0002", -- module: THIS_MODULE -+ .probe = NULL, /* Not usable directly */ -+ .destroy = cfi_amdstd_destroy, -+ .name = "cfi_cmdset_0002", -+ .module = THIS_MODULE - }; - --struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) -+ -+/* #define DEBUG_LOCK_BITS */ -+/* #define DEBUG_CFI_FEATURES */ -+ -+ -+#ifdef DEBUG_CFI_FEATURES -+static void cfi_tell_features(struct cfi_pri_amdstd *extp) - { -- struct cfi_private *cfi = map->fldrv_priv; -- unsigned char bootloc; -- int ofs_factor = cfi->interleave * cfi->device_type; -- int i; -- __u8 major, minor; -- __u32 base = cfi->chips[0].start; -+ const char* erase_suspend[3] = { -+ "Not supported", "Read only", "Read/write" -+ }; -+ const char* top_bottom[6] = { -+ "No WP", "8x8KiB sectors at top & bottom, no WP", -+ "Bottom boot", "Top boot", -+ "Uniform, Bottom WP", "Uniform, Top WP" -+ }; -+ -+ printk(" Silicon revision: %d\n", extp->SiliconRevision >> 1); -+ printk(" Address sensitive unlock: %s\n", -+ (extp->SiliconRevision & 1) ? "Not required" : "Required"); - -- if (cfi->cfi_mode==CFI_MODE_CFI){ -- __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; -+ if (extp->EraseSuspend < ARRAY_SIZE(erase_suspend)) -+ printk(" Erase Suspend: %s\n", erase_suspend[extp->EraseSuspend]); -+ else -+ printk(" Erase Suspend: Unknown value %d\n", extp->EraseSuspend); - -- cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); -+ if (extp->BlkProt == 0) -+ printk(" Block protection: Not supported\n"); -+ else -+ printk(" Block protection: %d sectors per group\n", extp->BlkProt); -+ -+ -+ printk(" Temporary block unprotect: %s\n", -+ extp->TmpBlkUnprotect ? "Supported" : "Not supported"); -+ printk(" Block protect/unprotect scheme: %d\n", extp->BlkProtUnprot); -+ printk(" Number of simultaneous operations: %d\n", extp->SimultaneousOps); -+ printk(" Burst mode: %s\n", -+ extp->BurstMode ? "Supported" : "Not supported"); -+ if (extp->PageMode == 0) -+ printk(" Page mode: Not supported\n"); -+ else -+ printk(" Page mode: %d word page\n", extp->PageMode << 2); - -- major = cfi_read_query(map, base + (adr+3)*ofs_factor); -- minor = cfi_read_query(map, base + (adr+4)*ofs_factor); -+ printk(" Vpp Supply Minimum Program/Erase Voltage: %d.%d V\n", -+ extp->VppMin >> 4, extp->VppMin & 0xf); -+ printk(" Vpp Supply Maximum Program/Erase Voltage: %d.%d V\n", -+ extp->VppMax >> 4, extp->VppMax & 0xf); - -- printk(KERN_NOTICE " Amd/Fujitsu Extended Query Table v%c.%c at 0x%4.4X\n", -- major, minor, adr); -- cfi_send_gen_cmd(0xf0, 0x55, base, map, cfi, cfi->device_type, NULL); -- -- cfi_send_gen_cmd(0xaa, 0x555, base, map, cfi, cfi->device_type, NULL); -- cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL); -- cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL); -- cfi->mfr = cfi_read_query(map, base); -- cfi->id = cfi_read_query(map, base + ofs_factor); -+ if (extp->TopBottom < ARRAY_SIZE(top_bottom)) -+ printk(" Top/Bottom Boot Block: %s\n", top_bottom[extp->TopBottom]); -+ else -+ printk(" Top/Bottom Boot Block: Unknown value %d\n", extp->TopBottom); -+} -+#endif - -- /* Wheee. Bring me the head of someone at AMD. */ - #ifdef AMD_BOOTLOC_BUG -+/* Wheee. Bring me the head of someone at AMD. */ -+static void fixup_amd_bootblock(struct map_info *map, void* param) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ struct cfi_pri_amdstd *extp = cfi->cmdset_priv; -+ __u8 major = extp->MajorVersion; -+ __u8 minor = extp->MinorVersion; -+ - if (((major << 8) | minor) < 0x3131) { - /* CFI version 1.0 => don't trust bootloc */ - if (cfi->id & 0x80) { - printk(KERN_WARNING "%s: JEDEC Device ID is 0x%02X. Assuming broken CFI table.\n", map->name, cfi->id); -- bootloc = 3; /* top boot */ -+ extp->TopBottom = 3; /* top boot */ - } else { -- bootloc = 2; /* bottom boot */ -+ extp->TopBottom = 2; /* bottom boot */ - } -- } else -+ } -+} - #endif -+ -+static struct cfi_fixup fixup_table[] = { -+#ifdef AMD_BOOTLOC_BUG - { -- cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); -- bootloc = cfi_read_query(map, base + (adr+15)*ofs_factor); -+ 0x0001, /* AMD */ -+ CFI_ID_ANY, -+ fixup_amd_bootblock, NULL -+ }, -+#endif -+ { 0, 0, NULL, NULL } -+}; -+ -+ -+struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ unsigned char bootloc; -+ int i; -+ -+ if (cfi->cfi_mode==CFI_MODE_CFI){ -+ /* -+ * It's a real CFI chip, not one for which the probe -+ * routine faked a CFI structure. So we read the feature -+ * table from it. -+ */ -+ __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; -+ struct cfi_pri_amdstd *extp; -+ -+ extp = (struct cfi_pri_amdstd*)cfi_read_pri(map, adr, sizeof(*extp), "Amd/Fujitsu"); -+ if (!extp) -+ return NULL; -+ -+ /* Install our own private info structure */ -+ cfi->cmdset_priv = extp; -+ -+ cfi_fixup(map, fixup_table); -+ -+#ifdef DEBUG_CFI_FEATURES -+ /* Tell the user about it in lots of lovely detail */ -+ cfi_tell_features(extp); -+#endif -+ -+ bootloc = extp->TopBottom; -+ if ((bootloc != 2) && (bootloc != 3)) { -+ printk(KERN_WARNING "%s: CFI does not contain boot " -+ "bank location. Assuming top.\n", map->name); -+ bootloc = 2; - } -+ - if (bootloc == 3 && cfi->cfiq->NumEraseRegions > 1) { - printk(KERN_WARNING "%s: Swapping erase regions for broken CFI table.\n", map->name); - -@@ -106,6 +227,11 @@ - cfi->cfiq->EraseRegionInfo[j] = swap; - } - } -+ /* -+ * These might already be setup (more correctly) by -+ * jedec_probe.c - still need it for cfi_probe.c path. -+ */ -+ if ( ! (cfi->addr_unlock1 && cfi->addr_unlock2) ) { - switch (cfi->device_type) { - case CFI_DEVICETYPE_X8: - cfi->addr_unlock1 = 0x555; -@@ -125,9 +251,13 @@ - cfi->addr_unlock2 = 0xaaa; - break; - default: -- printk(KERN_NOTICE "Eep. Unknown cfi_cmdset_0002 device type %d\n", cfi->device_type); -+ printk(KERN_WARNING -+ "MTD %s(): Unsupported device type %d\n", -+ __func__, cfi->device_type); - return NULL; - } -+ } -+ - } /* CFI mode */ - - for (i=0; i< cfi->numchips; i++) { -@@ -138,15 +268,17 @@ - - map->fldrv = &cfi_amdstd_chipdrv; - -- cfi_send_gen_cmd(0xf0, 0x55, base, map, cfi, cfi->device_type, NULL); - return cfi_amdstd_setup(map); - } - -+ - static struct mtd_info *cfi_amdstd_setup(struct map_info *map) - { - struct cfi_private *cfi = map->fldrv_priv; - struct mtd_info *mtd; - unsigned long devsize = (1<cfiq->DevSize) * cfi->interleave; -+ unsigned long offset = 0; -+ int i,j; - - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); - printk(KERN_NOTICE "number of %s chips: %d\n", -@@ -163,15 +295,9 @@ - /* Also select the correct geometry setup too */ - mtd->size = devsize * cfi->numchips; - -- if (cfi->cfiq->NumEraseRegions == 1) { -- /* No need to muck about with multiple erase sizes */ -- mtd->erasesize = ((cfi->cfiq->EraseRegionInfo[0] >> 8) & ~0xff) * cfi->interleave; -- } else { -- unsigned long offset = 0; -- int i,j; -- - mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; -- mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL); -+ mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) -+ * mtd->numeraseregions, GFP_KERNEL); - if (!mtd->eraseregions) { - printk(KERN_WARNING "Failed to allocate memory for MTD erase region info\n"); - goto setup_err; -@@ -206,39 +332,52 @@ - mtd->eraseregions[i].numblocks); - } - #endif -- } - - switch (CFIDEV_BUSWIDTH) - { - case 1: - case 2: - case 4: --#if 1 -- if (mtd->numeraseregions > 1) -- mtd->erase = cfi_amdstd_erase_varsize; -- else -+#ifdef CFI_WORD_64 -+ case 8: - #endif -- if (((cfi->cfiq->EraseRegionInfo[0] & 0xffff) + 1) == 1) -+ if (mtd->numeraseregions == 1 -+ && ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) + 1) == 1) { - mtd->erase = cfi_amdstd_erase_chip; -- else -- mtd->erase = cfi_amdstd_erase_onesize; -+ } else { -+ mtd->erase = cfi_amdstd_erase_varsize; -+ mtd->lock = cfi_amdstd_lock_varsize; -+ mtd->unlock = cfi_amdstd_unlock_varsize; -+ } -+ -+ if ( cfi->cfiq->BufWriteTimeoutTyp && !FORCE_WORD_WRITE) { -+ DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" ); -+ mtd->write = cfi_amdstd_write_buffers; -+ } else { -+ DEBUG(MTD_DEBUG_LEVEL1, "Using word write method\n" ); -+ mtd->write = cfi_amdstd_write_words; -+ } -+ - mtd->read = cfi_amdstd_read; -- mtd->write = cfi_amdstd_write; - break; - - default: -- printk(KERN_WARNING "Unsupported buswidth\n"); -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); - goto setup_err; - break; - } - if (cfi->fast_prog) { -- /* In cfi_amdstd_write() we frob the protection stuff -+ /* In cfi_amdstd_write_words() we frob the protection stuff - without paying any attention to the state machine. - This upsets in-progress erases. So we turn this flag - off for now till the code gets fixed. */ - printk(KERN_NOTICE "cfi_cmdset_0002: Disabling fast programming due to code brokenness.\n"); - cfi->fast_prog = 0; - } -+ /* FIXME: erase-suspend-program is broken. See -+ http://lists.infradead.org/pipermail/linux-mtd/2003-December/009001.html */ -+ printk(KERN_NOTICE "cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.\n"); - - - /* does this chip have a secsi area? */ -@@ -266,7 +405,7 @@ - mtd->flags = MTD_CAP_NORFLASH; - map->fldrv = &cfi_amdstd_chipdrv; - mtd->name = map->name; -- MOD_INC_USE_COUNT; -+ __module_get(THIS_MODULE); - return mtd; - - setup_err: -@@ -280,46 +419,210 @@ - return NULL; - } - --static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) -+ -+/* This is more work to coalesce the retry #ifdefs in one location */ -+static inline void handle_wacky_state(const char *func, -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+ int retry_cmd_cnt, -+#endif -+ unsigned long adr, -+ cfi_word datum, -+ cfi_word prev_oldstatus, -+ cfi_word prev_status, -+ cfi_word oldstatus, -+ cfi_word status) -+{ -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+ if ( retry_cmd_cnt == retry_cmd_max ) { -+#endif -+ printk(KERN_WARNING -+ "MTD %s(): Wacky! Unable to decode failure status\n" -+ "Possible buggy device - try " -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+ "increasing retry_cmd_max from %d\n" -+#else -+ "enabling CONFIG_MTD_CFI_AMDSTD_RETRY\n" -+ "in your kernel config and setting driver retry_cmd_max\n" -+#endif -+ , func -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+ , retry_cmd_max -+#endif -+ ); -+ -+ printk(KERN_WARNING -+ "MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", -+ func, adr, datum, -+ prev_oldstatus, prev_status, -+ oldstatus, status); -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+ } -+#endif -+} -+ -+ -+static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode) - { - DECLARE_WAITQUEUE(wait, current); -- unsigned long timeo = jiffies + HZ; -+ struct cfi_private *cfi = map->fldrv_priv; -+ cfi_word status, oldstatus; -+ cfi_word dq6 = CMD(1<<6); -+ cfi_word dq2 = CMD(1<<2); -+ unsigned long timeo; -+ struct cfi_pri_amdstd *cfip = (struct cfi_pri_amdstd *)cfi->cmdset_priv; - -+ resettime: -+ timeo = jiffies + HZ; - retry: -+ switch (chip->state) { -+ -+ case FL_STATUS: -+ for (;;) { -+ oldstatus = cfi_read(map, adr); -+ status = cfi_read(map, adr); -+ if (((oldstatus ^ status) & (dq6 | dq2)) == 0) -+ break; -+ -+ if (time_after(jiffies, timeo)) { -+ printk(KERN_ERR "Waiting for chip to be ready timed out. Status %llx\n", -+ (long long)status); -+ cfi_spin_unlock(chip->mutex); -+ return -EIO; -+ } -+ cfi_spin_unlock(chip->mutex); -+ cfi_udelay(1); - cfi_spin_lock(chip->mutex); -+ /* Someone else might have been playing with it. */ -+ goto retry; -+ } - -- if (chip->state != FL_READY){ --#if 0 -- printk(KERN_DEBUG "Waiting for chip to read, status = %d\n", chip->state); --#endif -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ case FL_READY: -+ case FL_CFI_QUERY: -+ case FL_JEDEC_QUERY: -+ return 0; -+ -+ case FL_ERASING: -+ if (mode == FL_WRITING) /* FIXME: Erase-suspend-program appears broken. */ -+ goto sleep; -+ -+ if (!(mode == FL_READY || mode == FL_POINT -+ || (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)) -+ || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1)))) -+ goto sleep; -+ -+ oldstatus = cfi_read(map, adr); -+ status = cfi_read(map, adr); -+ if ((oldstatus ^ status) & dq2) { -+ printk(KERN_ERR "Can't suspend erase -- block in progress\n"); -+ goto sleep; -+ } -+ -+ /* Erase suspend */ -+ /* FIXME - is there a way to verify suspend? */ -+ cfi_write(map, CMD(0xB0), chip->in_progress_block_addr); -+ chip->oldstate = FL_ERASING; -+ chip->state = FL_ERASE_SUSPENDING; -+ chip->erase_suspended = 1; -+ for (;;) { -+ oldstatus = cfi_read(map, chip->in_progress_block_addr); -+ status = cfi_read(map, chip->in_progress_block_addr); -+ if (((oldstatus ^ status) & dq6) == 0) -+ break; -+ -+ if (time_after(jiffies, timeo)) { -+ /* Urgh. Resume and pretend we weren't here. */ -+ /* FIXME - is there a way to verify resume? */ -+ cfi_write(map, CMD(0x30), chip->in_progress_block_addr); -+ chip->state = FL_ERASING; -+ chip->oldstate = FL_READY; -+ printk(KERN_ERR "Chip not ready after erase " -+ "suspended: status = 0x%x\n", status); -+ return -EIO; -+ } - - cfi_spin_unlock(chip->mutex); -+ cfi_udelay(1); -+ cfi_spin_lock(chip->mutex); -+ /* Nobody will touch it while it's in state FL_ERASE_SUSPENDING. -+ So we can just loop here. */ -+ } -+ chip->state = FL_READY; -+ return 0; -+ -+ case FL_POINT: -+ /* Only if there's no operation suspended... */ -+ if (mode == FL_READY && chip->oldstate == FL_READY) -+ return 0; - -+ default: -+ sleep: -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ add_wait_queue(&chip->wq, &wait); -+ cfi_spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); --#if 0 -- if(signal_pending(current)) -- return -EINTR; --#endif -- timeo = jiffies + HZ; -+ cfi_spin_lock(chip->mutex); -+ goto resettime; -+ } -+} - -- goto retry; -+ -+static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ -+ switch(chip->oldstate) { -+ case FL_ERASING: -+ chip->state = chip->oldstate; -+ cfi_write(map, CMD(0x30), chip->in_progress_block_addr); -+ chip->oldstate = FL_READY; -+ chip->state = FL_ERASING; -+ break; -+ -+ case FL_READY: -+ case FL_STATUS: -+ /* We should really make set_vpp() count, rather than doing this */ -+ DISABLE_VPP(map); -+ break; -+ default: -+ printk(KERN_ERR "MTD: put_chip() called with oldstate %d!!\n", chip->oldstate); - } -+ wake_up(&chip->wq); -+} -+ -+ -+static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) -+{ -+ unsigned long cmd_addr; -+ struct cfi_private *cfi = map->fldrv_priv; -+ int ret; - - adr += chip->start; - -+ /* Ensure cmd read/writes are aligned. */ -+ cmd_addr = adr & ~(CFIDEV_BUSWIDTH-1); -+ -+ cfi_spin_lock(chip->mutex); -+ ret = get_chip(map, chip, cmd_addr, FL_READY); -+ if (ret) { -+ cfi_spin_unlock(chip->mutex); -+ return ret; -+ } -+ -+ if (chip->state != FL_POINT && chip->state != FL_READY) { -+ cfi_write(map, CMD(0xf0), cmd_addr); - chip->state = FL_READY; -+ } - -- map->copy_from(map, buf, adr, len); -+ map_copy_from(map, buf, adr, len); - -- wake_up(&chip->wq); -- cfi_spin_unlock(chip->mutex); -+ put_chip(map, chip, cmd_addr); - -+ cfi_spin_unlock(chip->mutex); - return 0; - } - -+ - static int cfi_amdstd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) - { - struct map_info *map = mtd->priv; -@@ -361,6 +664,7 @@ - return ret; - } - -+ - static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) - { - DECLARE_WAITQUEUE(wait, current); -@@ -394,12 +698,14 @@ - - chip->state = FL_READY; - -+ /* should these be CFI_DEVICETYPE_X8 instead of cfi->device_type? */ - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); - cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); - -- map->copy_from(map, buf, adr, len); -+ map_copy_from(map, buf, adr, len); - -+ /* should these be CFI_DEVICETYPE_X8 instead of cfi->device_type? */ - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); - cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); -@@ -454,125 +760,241 @@ - return ret; - } - --static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum, int fast) -+ -+static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, cfi_word datum, int fast) - { -- unsigned long timeo = jiffies + HZ; -- unsigned int oldstatus, status; -- unsigned int dq6, dq5; - struct cfi_private *cfi = map->fldrv_priv; -- DECLARE_WAITQUEUE(wait, current); -+ unsigned long timeo = jiffies + HZ; -+ cfi_word oldstatus, status, prev_oldstatus, prev_status; -+ cfi_word dq6 = CMD(1<<6); -+ /* -+ * We use a 1ms + 1 jiffies generic timeout for writes (most devices -+ * have a max write time of a few hundreds usec). However, we should -+ * use the maximum timeout value given by the chip at probe time -+ * instead. Unfortunately, struct flchip does have a field for -+ * maximum timeout, only for typical which can be far too short -+ * depending of the conditions. The ' + 1' is to avoid having a -+ * timeout of 0 jiffies if HZ is smaller than 1000. -+ */ -+ unsigned long uWriteTimeout = ( HZ / 1000 ) + 1; - int ret = 0; -+ int ta = 0; -+ DECLARE_RETRY_CMD_CNT(); - -- retry: -- cfi_spin_lock(chip->mutex); -- -- if (chip->state != FL_READY) { --#if 0 -- printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", chip->state); --#endif -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ adr += chip->start; - -+ cfi_spin_lock(chip->mutex); -+ ret = get_chip(map, chip, adr, FL_WRITING); -+ if (ret) { - cfi_spin_unlock(chip->mutex); -- -- schedule(); -- remove_wait_queue(&chip->wq, &wait); --#if 0 -- printk(KERN_DEBUG "Wake up to write:\n"); -- if(signal_pending(current)) -- return -EINTR; --#endif -- timeo = jiffies + HZ; -- -- goto retry; -+ return ret; - } - -- chip->state = FL_WRITING; -+ RETRY_CMD_LABEL; -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8x)\n", -+ __func__, adr, datum ); -+ -+ /* -+ * Check for a NOP for the case when the datum to write is already -+ * present - it saves time and works around buggy chips that corrupt -+ * data at other locations when 0xff is written to a location that -+ * already contains 0xff. -+ */ -+ status = cfi_read(map, adr); -+ if (status == datum) { -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): NOP 0x%.8x == 0x%.8x\n", -+ __func__, status, datum ); -+ goto op_done; -+ } - -- adr += chip->start; - ENABLE_VPP(map); - if (fast) { /* Unlock bypass */ - cfi_send_gen_cmd(0xA0, 0, chip->start, map, cfi, cfi->device_type, NULL); -- } -- else { -+ } else { -+ /* -+ * The CFI_DEVICETYPE_X8 argument is needed even when -+ * cfi->device_type != CFI_DEVICETYPE_X8. The addresses for -+ * command sequences don't scale even when the device is -+ * wider. This is the case for many of the cfi_send_gen_cmd() -+ * below. I'm not sure, however, why some use -+ * cfi->device_type. -+ */ - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - } -- - cfi_write(map, datum, adr); -+ chip->state = FL_WRITING; - - cfi_spin_unlock(chip->mutex); - cfi_udelay(chip->word_write_time); - cfi_spin_lock(chip->mutex); - -- /* Polling toggle bits instead of reading back many times -- This ensures that write operation is really completed, -- or tells us why it failed. */ -- dq6 = CMD(1<<6); -- dq5 = CMD(1<<5); -- timeo = jiffies + (HZ/1000); /* setting timeout to 1ms for now */ -+ /* -+ * Polling toggle bits instead of reading back many times This ensures -+ * that write operation is really completed, or tells us why it -+ * failed. -+ * -+ * It may appear that the polling and decoding of error state might be -+ * simplified. Don't do it unless you really know what you are doing. -+ * -+ * You must remember that JESD21-C 3.5.3 states that the status must -+ * be read back an _additional_ two times before a failure is -+ * determined. This is because these devices have internal state -+ * machines that are asynchronous to the external data bus. During an -+ * erase or write the read-back status of the polling bits might be -+ * transitioning internaly when the external read-back occurs. This -+ * means that the bits aren't in the final state and they might appear -+ * to report an error as they are in a transient state: dq7 is -+ * asynchronous with dq6 and other status bits. -+ * -+ * This asynchronous behaviour can cause infrequent errors that will -+ * usually disappear the next time an erase or write happens (Try -+ * tracking those errors down!). To ensure that the bits are not in -+ * transition, the location must be read-back two more times and -+ * compared against what was written - BOTH reads MUST match what was -+ * written. Don't think this can be simplified to only the last read -+ * matching the datum written: status bits *can* match the datum -+ * written. -+ * -+ * If the final comparison fails, error state can *then* be decoded. -+ * -+ * - Thayne Harbaugh -+ */ -+ /* See comment above for timeout value. */ -+ timeo = jiffies + uWriteTimeout; -+ for (;;) { -+ if (chip->state != FL_WRITING) { -+ /* Someone's suspended the write. Sleep */ -+ DECLARE_WAITQUEUE(wait, current); -+ -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ add_wait_queue(&chip->wq, &wait); -+ cfi_spin_unlock(chip->mutex); -+ schedule(); -+ remove_wait_queue(&chip->wq, &wait); -+ timeo = jiffies + (HZ / 2); /* FIXME */ -+ cfi_spin_lock(chip->mutex); -+ continue; -+ } - - oldstatus = cfi_read(map, adr); - status = cfi_read(map, adr); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); - -- while( (status & dq6) != (oldstatus & dq6) && -- (status & dq5) != dq5 && -- !time_after(jiffies, timeo) ) { -+ /* -+ * This only checks if dq6 is still toggling and that our -+ * timer hasn't expired. We purposefully ignore the chip's -+ * internal timer that will assert dq5 and leave dq6 toggling. -+ * This is done for a variety of reasons: -+ * -+ * 1) Not all chips support dq5. -+ * -+ * 2) Dealing with asynchronous status bit and data updates -+ * and reading a device two more times creates _messy_ logic -+ * when trying to deal with interleaved devices - some may be -+ * changing while others are still busy. -+ * -+ * 3) Checking dq5 only helps to optimize an error case that -+ * should at worst be infrequent and at best non-existent. -+ * -+ * If our timeout occurs _then_ we will check dq5 to see if -+ * the device also had an internal timeout. -+ */ -+ if ( (((status ^ oldstatus) & dq6) == 0) -+ || ( ta = time_after(jiffies, timeo)) ) -+ break; - -- if (need_resched()) { -+ /* Latency issues. Drop the lock, wait a while and retry */ - cfi_spin_unlock(chip->mutex); -- yield(); -+ cfi_udelay(1); - cfi_spin_lock(chip->mutex); -- } else -- udelay(1); -- -- oldstatus = cfi_read( map, adr ); -- status = cfi_read( map, adr ); - } - -- if( (status & dq6) != (oldstatus & dq6) ) { -- /* The erasing didn't stop?? */ -- if( (status & dq5) == dq5 ) { -- /* When DQ5 raises, we must check once again -- if DQ6 is toggling. If not, the erase has been -- completed OK. If not, reset chip. */ -+ /* -+ * Something kicked us out of the read-back loop. We'll check success -+ * befor checking failure. Even though dq6 might be true data, it is -+ * unkown if all of the other bits have changed to true data due to -+ * the asynchronous nature of the internal state machine. We will -+ * read two more times and use this to either verify that the write -+ * completed successfully or that something really went wrong. BOTH -+ * reads must match what was written - this certifies that bits aren't -+ * still changing and that the status bits erroneously match the datum -+ * that was written. -+ */ -+ prev_oldstatus = oldstatus; -+ prev_status = status; - oldstatus = cfi_read(map, adr); - status = cfi_read(map, adr); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); - -- if ( (oldstatus & 0x00FF) == (status & 0x00FF) ) { -- printk(KERN_WARNING "Warning: DQ5 raised while program operation was in progress, however operation completed OK\n" ); -+ if ( oldstatus == datum && status == datum ) { -+ /* success - do nothing */ -+ goto op_done; -+ } -+ -+ if ( ta ) { -+ /* Only check dq5 on the chips that are still toggling. */ -+ cfi_word dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1; -+ if ( status & dq5mask ) { -+ /* dq5 asserted - decode interleave chips */ -+ printk( KERN_WARNING -+ "MTD %s(): FLASH internal timeout: 0x%.8x 0x%.8x 0x%8x\n", -+ __func__, -+ status & dq5mask, status, datum ); - } else { -- /* DQ5 is active so we can do a reset and stop the erase */ -- cfi_write(map, CMD(0xF0), chip->start); -- printk(KERN_WARNING "Internal flash device timeout occurred or write operation was performed while flash was programming.\n" ); -+ printk( KERN_WARNING -+ "MTD %s(): Software timed out during write.\n", -+ __func__ ); -+ } -+ goto op_failed; - } -- } else { -- printk(KERN_WARNING "Waiting for write to complete timed out in do_write_oneword."); - -+ /* -+ * If we get to here then it means that something -+ * is wrong and it's not a timeout. Something -+ * is seriously wacky! Dump some debug info. -+ */ -+ /* -+ * Found a clue about the chips that reach this state. -+ * Some flash chips (SST >cough<) -+ * are horribly broken. They do not ignore traffic that is -+ * destined to other devices. This happens because some solutions -+ * are on shared busses, the erase and program sequences have -+ * have multiple commands, and the sequence is interspersed with -+ * commands destined to other devices. A good flash chip will -+ * examine the command and destination address and will ignore -+ * commands that are for other devices. -+ */ -+ HANDLE_WACKY_STATE(); -+ -+ op_failed: -+ /* reset on all failures. */ -+ cfi_write( map, CMD(0xF0), chip->start ); -+ /* FIXME - should have reset delay before continuing */ -+ CHECK_RETRIES(); -+ ret = -EIO; -+ -+ op_done: - chip->state = FL_READY; -- wake_up(&chip->wq); -- cfi_spin_unlock(chip->mutex); -- DISABLE_VPP(map); -- ret = -EIO; -- } -- } -- -- DISABLE_VPP(map); -- chip->state = FL_READY; -- wake_up(&chip->wq); -+ put_chip(map, chip, adr); - cfi_spin_unlock(chip->mutex); - - return ret; - } - --static int cfi_amdstd_write (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf) -+ -+static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) - { - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - int ret = 0; - int chipnum; - unsigned long ofs, chipstart; -+ DECLARE_WAITQUEUE(wait, current); - - *retlen = 0; - if (!len) -@@ -587,19 +1009,52 @@ - unsigned long bus_ofs = ofs & ~(CFIDEV_BUSWIDTH-1); - int i = ofs - bus_ofs; - int n = 0; -- u_char tmp_buf[4]; -- __u32 datum; -+ u_char tmp_buf[8]; -+ cfi_word datum; -+ -+ retry: -+ cfi_spin_lock(cfi->chips[chipnum].mutex); -+ -+ if (cfi->chips[chipnum].state != FL_READY) { -+#if 0 -+ printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state); -+#endif -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ add_wait_queue(&cfi->chips[chipnum].wq, &wait); -+ -+ cfi_spin_unlock(cfi->chips[chipnum].mutex); -+ -+ schedule(); -+ remove_wait_queue(&cfi->chips[chipnum].wq, &wait); -+#if 0 -+ if(signal_pending(current)) -+ return -EINTR; -+#endif -+ goto retry; -+ } -+ -+ map_copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); - -- map->copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); -- while (len && i < CFIDEV_BUSWIDTH) -- tmp_buf[i++] = buf[n++], len--; -+ cfi_spin_unlock(cfi->chips[chipnum].mutex); -+ -+ while (len && i < CFIDEV_BUSWIDTH) { -+ tmp_buf[i++] = buf[n++]; -+ len--; -+ } - -+ /* already know that buswidth > 1 */ - if (cfi_buswidth_is_2()) { - datum = *(__u16*)tmp_buf; - } else if (cfi_buswidth_is_4()) { - datum = *(__u32*)tmp_buf; -+#ifdef CFI_WORD_64 -+ } else if (cfi_buswidth_is_8()) { -+ datum = *(__u64*)tmp_buf; -+#endif - } else { -- return -EINVAL; /* should never happen, but be safe */ -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); -+ return -EINVAL; - } - - ret = do_write_oneword(map, &cfi->chips[chipnum], -@@ -628,7 +1083,7 @@ - - /* We are now aligned, write as much as possible */ - while(len >= CFIDEV_BUSWIDTH) { -- __u32 datum; -+ cfi_word datum; - - if (cfi_buswidth_is_1()) { - datum = *(__u8*)buf; -@@ -636,7 +1091,13 @@ - datum = *(__u16*)buf; - } else if (cfi_buswidth_is_4()) { - datum = *(__u32*)buf; -+#ifdef CFI_WORD_64 -+ } else if (cfi_buswidth_is_8()) { -+ datum = *(__u64*)buf; -+#endif - } else { -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); - return -EINVAL; - } - ret = do_write_oneword(map, &cfi->chips[chipnum], -@@ -685,10 +1146,34 @@ - /* Write the trailing bytes if any */ - if (len & (CFIDEV_BUSWIDTH-1)) { - int i = 0, n = 0; -- u_char tmp_buf[4]; -- __u32 datum; -+ u_char tmp_buf[8]; -+ cfi_word datum; -+ -+ retry1: -+ cfi_spin_lock(cfi->chips[chipnum].mutex); -+ -+ if (cfi->chips[chipnum].state != FL_READY) { -+#if 0 -+ printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state); -+#endif -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ add_wait_queue(&cfi->chips[chipnum].wq, &wait); -+ -+ cfi_spin_unlock(cfi->chips[chipnum].mutex); -+ -+ schedule(); -+ remove_wait_queue(&cfi->chips[chipnum].wq, &wait); -+#if 0 -+ if(signal_pending(current)) -+ return -EINTR; -+#endif -+ goto retry1; -+ } -+ -+ map_copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); -+ -+ cfi_spin_unlock(cfi->chips[chipnum].mutex); - -- map->copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); - while (len--) - tmp_buf[i++] = buf[n++]; - -@@ -696,8 +1181,14 @@ - datum = *(__u16*)tmp_buf; - } else if (cfi_buswidth_is_4()) { - datum = *(__u32*)tmp_buf; -+#ifdef CFI_WORD_64 -+ } else if (cfi_buswidth_is_8()) { -+ datum = *(__u64*)tmp_buf; -+#endif - } else { -- return -EINVAL; /* should never happen, but be safe */ -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); -+ return -EINVAL; - } - - ret = do_write_oneword(map, &cfi->chips[chipnum], -@@ -711,289 +1202,446 @@ - return 0; - } - --static inline int do_erase_chip(struct map_info *map, struct flchip *chip) -+ -+/* -+ * FIXME: interleaved mode not tested, and probably not supported! -+ */ -+static inline int do_write_buffer(struct map_info *map, struct flchip *chip, -+ unsigned long adr, const u_char *buf, int len) - { -- unsigned int oldstatus, status; -- unsigned int dq6, dq5; -- unsigned long timeo = jiffies + HZ; -- unsigned int adr; - struct cfi_private *cfi = map->fldrv_priv; -- DECLARE_WAITQUEUE(wait, current); -- -- retry: -- cfi_spin_lock(chip->mutex); -+ unsigned long timeo = jiffies + HZ; -+ cfi_word oldstatus, status, prev_oldstatus, prev_status; -+ cfi_word dq6 = CMD(1<<6); -+ /* see comments in do_write_oneword() regarding uWriteTimeo. */ -+ static unsigned long uWriteTimeout = ( HZ / 1000 ) + 1; -+ int ret = -EIO; -+ int ta = 0; -+ unsigned long cmd_adr; -+ int z, bytes, words; -+ cfi_word datum; -+ DECLARE_RETRY_CMD_CNT(); - -- if (chip->state != FL_READY){ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ adr += chip->start; -+ cmd_adr = adr; - -+ cfi_spin_lock(chip->mutex); -+ ret = get_chip(map, chip, adr, FL_WRITING); -+ if (ret) { - cfi_spin_unlock(chip->mutex); -+ return ret; -+ } - -- schedule(); -- remove_wait_queue(&chip->wq, &wait); --#if 0 -- if(signal_pending(current)) -- return -EINTR; -+ if (cfi_buswidth_is_1()) { -+ datum = *(__u8*)buf; -+ } else if (cfi_buswidth_is_2()) { -+ datum = *(__u16*)buf; -+ } else if (cfi_buswidth_is_4()) { -+ datum = *(__u32*)buf; -+#ifdef CFI_WORD_64 -+ } else if (cfi_buswidth_is_8()) { -+ datum = *(__u64*)buf; - #endif -- timeo = jiffies + HZ; -- -- goto retry; -+ } else { -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); -+ return -EINVAL; - } - -- chip->state = FL_ERASING; -+ RETRY_CMD_LABEL; -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8x)\n", -+ __func__, adr, datum ); - -- /* Handle devices with one erase region, that only implement -- * the chip erase command. -- */ - ENABLE_VPP(map); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -- cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -- cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -- cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -- cfi_send_gen_cmd(0x10, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -- timeo = jiffies + (HZ*20); -- adr = cfi->addr_unlock1; -+ //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - -- /* Wait for the end of programing/erasure by using the toggle method. -- * As long as there is a programming procedure going on, bit 6 of the last -- * written byte is toggling it's state with each consectuve read. -- * The toggling stops as soon as the procedure is completed. -- * -- * If the process has gone on for too long on the chip bit 5 gets. -- * After bit5 is set you can kill the operation by sending a reset -- * command to the chip. -- */ -- dq6 = CMD(1<<6); -- dq5 = CMD(1<<5); -+ /* Write Buffer Load */ -+ cfi_write(map, CMD(0x25), cmd_adr); - -- oldstatus = cfi_read(map, adr); -- status = cfi_read(map, adr); -- while( ((status & dq6) != (oldstatus & dq6)) && -- ((status & dq5) != dq5) && -- !time_after(jiffies, timeo)) { -- int wait_reps; -+ chip->state = FL_WRITING_TO_BUFFER; -+ -+ /* Write length of data to come */ -+ bytes = len & (CFIDEV_BUSWIDTH-1); -+ words = len / CFIDEV_BUSWIDTH; -+ cfi_write(map, CMD(words - !bytes), cmd_adr ); -+ /* Write data */ -+ z = 0; -+ while(z < words * CFIDEV_BUSWIDTH) { -+ if (cfi_buswidth_is_1()) { -+ datum = *((__u8*)buf); -+ map_write8 (map, *((__u8*)buf)++, adr+z); -+ } else if (cfi_buswidth_is_2()) { -+ datum = *((__u16*)buf); -+ map_write16 (map, *((__u16*)buf)++, adr+z); -+ } else if (cfi_buswidth_is_4()) { -+ datum = *((__u32*)buf); -+ map_write32 (map, *((__u32*)buf)++, adr+z); -+#ifdef CFI_WORD_64 -+ } else if (cfi_buswidth_is_8()) { -+ datum = *((__u64*)buf); -+ map_write64 (map, *((__u64*)buf)++, adr+z); -+#endif -+ } else { -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); -+ ret = -EINVAL; -+ goto op_failed; -+ } -+ z += CFIDEV_BUSWIDTH; -+ } -+ if (bytes) { -+ int i = 0, n = 0; -+ u_char tmp_buf[8], *tmp_p = tmp_buf; -+ -+ while (bytes--) -+ tmp_buf[i++] = buf[n++]; -+ while (i < CFIDEV_BUSWIDTH) -+ tmp_buf[i++] = 0xff; -+ if (cfi_buswidth_is_2()) { -+ datum = *((__u16*)tmp_p); -+ map_write16 (map, *((__u16*)tmp_p)++, adr+z); -+ } else if (cfi_buswidth_is_4()) { -+ datum = *((__u32*)tmp_p); -+ map_write32 (map, *((__u32*)tmp_p)++, adr+z); -+#ifdef CFI_WORD_64 -+ } else if (cfi_buswidth_is_8()) { -+ datum = *((__u64*)tmp_p); -+ map_write64 (map, *((__u64*)tmp_p)++, adr+z); -+#endif -+ } else { -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); -+ ret = -EINVAL; -+ goto op_failed; -+ } -+ } else if (words > 0) { -+ z -= CFIDEV_BUSWIDTH; -+ } -+ -+ adr += z; -+ -+ /* Write Buffer Program Confirm: GO GO GO */ -+ cfi_write(map, CMD(0x29), cmd_adr); -+ chip->state = FL_WRITING; - -- /* an initial short sleep */ - cfi_spin_unlock(chip->mutex); -- schedule_timeout(HZ/100); -+ cfi_udelay(chip->buffer_write_time); - cfi_spin_lock(chip->mutex); - -- if (chip->state != FL_ERASING) { -- /* Someone's suspended the erase. Sleep */ -+ timeo = jiffies + uWriteTimeout; -+ -+ for (;;) { -+ if (chip->state != FL_WRITING) { -+ /* Someone's suspended the write. Sleep */ -+ DECLARE_WAITQUEUE(wait, current); -+ - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); -- - cfi_spin_unlock(chip->mutex); -- printk("erase suspended. Sleeping\n"); -- - schedule(); - remove_wait_queue(&chip->wq, &wait); --#if 0 -- if (signal_pending(current)) -- return -EINTR; --#endif -- timeo = jiffies + (HZ*2); /* FIXME */ -+ timeo = jiffies + (HZ / 2); /* FIXME */ - cfi_spin_lock(chip->mutex); - continue; - } - -- /* Busy wait for 1/10 of a milisecond */ -- for(wait_reps = 0; -- (wait_reps < 100) && -- ((status & dq6) != (oldstatus & dq6)) && -- ((status & dq5) != dq5); -- wait_reps++) { -+ oldstatus = cfi_read(map, adr); -+ status = cfi_read(map, adr); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); -+ -+ /* See comments in do_write_oneword() about checking status */ -+ if ( (((status ^ oldstatus) & dq6) == 0) -+ || ( ta = time_after(jiffies, timeo)) ) { -+ break; -+ } - - /* Latency issues. Drop the lock, wait a while and retry */ - cfi_spin_unlock(chip->mutex); -- - cfi_udelay(1); -- - cfi_spin_lock(chip->mutex); -- oldstatus = cfi_read(map, adr); -- status = cfi_read(map, adr); - } -+ -+ /* See comments in do_write_oneword() about "two more checks" */ -+ prev_oldstatus = oldstatus; -+ prev_status = status; - oldstatus = cfi_read(map, adr); - status = cfi_read(map, adr); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); -+ -+ if ( oldstatus == datum && status == datum ) { -+ /* success - do nothing */ -+ goto op_done; -+ } -+ -+ if ( ta ) { -+ /* Only check dq5 on the chips that are still toggling. */ -+ cfi_word dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1; -+ if ( status & dq5mask ) { -+ /* dq5 asserted - decode interleave chips */ -+ printk( KERN_WARNING -+ "MTD %s(): FLASH internal timeout: 0x%.8x 0x%.8x 0x%8x\n", -+ __func__, -+ status & dq5mask, status, datum ); -+ } else { -+ printk( KERN_WARNING -+ "MTD %s(): Software timed out during write.\n", -+ __func__ ); - } -- if ((status & dq6) != (oldstatus & dq6)) { -- /* The erasing didn't stop?? */ -- if ((status & dq5) == dq5) { -- /* dq5 is active so we can do a reset and stop the erase */ -- cfi_write(map, CMD(0xF0), chip->start); -+ goto op_failed; - } -+ -+ HANDLE_WACKY_STATE(); -+ -+ op_failed: -+ /* reset on all failures. */ -+ cfi_write( map, CMD(0xF0), chip->start ); -+ /* FIXME - should have reset delay before continuing */ -+ CHECK_RETRIES(); -+ ret = -EIO; -+ -+ op_done: - chip->state = FL_READY; -- wake_up(&chip->wq); -+ put_chip(map, chip, adr); - cfi_spin_unlock(chip->mutex); -- printk("waiting for erase to complete timed out."); -- DISABLE_VPP(map); -- return -EIO; -+ -+ return ret; -+} -+ -+ -+static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ struct map_info *map = mtd->priv; -+ struct cfi_private *cfi = map->fldrv_priv; -+ int wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize; -+ int ret = 0; -+ int chipnum; -+ unsigned long ofs; -+ -+ *retlen = 0; -+ if (!len) -+ return 0; -+ -+ chipnum = to >> cfi->chipshift; -+ ofs = to - (chipnum << cfi->chipshift); -+ -+ /* If it's not bus-aligned, do the first word write */ -+ if (ofs & (CFIDEV_BUSWIDTH-1)) { -+ size_t local_len = (-ofs)&(CFIDEV_BUSWIDTH-1); -+ if (local_len > len) -+ local_len = len; -+ ret = cfi_amdstd_write_words(mtd, to, local_len, -+ retlen, buf); -+ if (ret) -+ return ret; -+ ofs += local_len; -+ buf += local_len; -+ len -= local_len; -+ -+ if (ofs >> cfi->chipshift) { -+ chipnum ++; -+ ofs = 0; -+ if (chipnum == cfi->numchips) -+ return 0; -+ } -+ } -+ -+ /* Write buffer is worth it only if more than one word to write... */ -+ while (len) { -+ /* We must not cross write block boundaries */ -+ int size = wbufsize - (ofs & (wbufsize-1)); -+ -+ if (size > len) -+ size = len; -+ ret = do_write_buffer(map, &cfi->chips[chipnum], -+ ofs, buf, size); -+ if (ret) -+ return ret; -+ -+ ofs += size; -+ buf += size; -+ (*retlen) += size; -+ len -= size; -+ -+ if (ofs >> cfi->chipshift) { -+ chipnum ++; -+ ofs = 0; -+ if (chipnum == cfi->numchips) -+ return 0; -+ } - } -- DISABLE_VPP(map); -- chip->state = FL_READY; -- wake_up(&chip->wq); -- cfi_spin_unlock(chip->mutex); - - return 0; - } - --static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) -+ -+/* -+ * Handle devices with one erase region, that only implement -+ * the chip erase command. -+ */ -+static inline int do_erase_chip(struct map_info *map, struct flchip *chip) - { -- unsigned int oldstatus, status; -- unsigned int dq6, dq5; -- unsigned long timeo = jiffies + HZ; - struct cfi_private *cfi = map->fldrv_priv; -+ cfi_word oldstatus, status, prev_oldstatus, prev_status; -+ cfi_word dq6 = CMD(1<<6); -+ unsigned long timeo = jiffies + HZ; -+ unsigned long int adr; - DECLARE_WAITQUEUE(wait, current); -+ int ret = 0; -+ int ta = 0; -+ cfi_word datum = 0; -+ DECLARE_RETRY_CMD_CNT(); - -- retry: -- cfi_spin_lock(chip->mutex); -- -- if (chip->state != FL_READY){ -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -+ adr = cfi->addr_unlock1; - -+ cfi_spin_lock(chip->mutex); -+ ret = get_chip(map, chip, adr, FL_WRITING); -+ if (ret) { - cfi_spin_unlock(chip->mutex); -- -- schedule(); -- remove_wait_queue(&chip->wq, &wait); --#if 0 -- if(signal_pending(current)) -- return -EINTR; --#endif -- timeo = jiffies + HZ; -- -- goto retry; -+ return ret; - } - -- chip->state = FL_ERASING; -+ RETRY_CMD_LABEL; -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n", -+ __func__, chip->start ); - -- adr += chip->start; - ENABLE_VPP(map); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -- cfi_write(map, CMD(0x30), adr); -- -- timeo = jiffies + (HZ*20); -- -- /* Wait for the end of programing/erasure by using the toggle method. -- * As long as there is a programming procedure going on, bit 6 of the last -- * written byte is toggling it's state with each consectuve read. -- * The toggling stops as soon as the procedure is completed. -- * -- * If the process has gone on for too long on the chip bit 5 gets. -- * After bit5 is set you can kill the operation by sending a reset -- * command to the chip. -- */ -- dq6 = CMD(1<<6); -- dq5 = CMD(1<<5); -+ cfi_send_gen_cmd(0x10, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - -- oldstatus = cfi_read(map, adr); -- status = cfi_read(map, adr); -- while( ((status & dq6) != (oldstatus & dq6)) && -- ((status & dq5) != dq5) && -- !time_after(jiffies, timeo)) { -- int wait_reps; -+ chip->state = FL_ERASING; -+ chip->erase_suspended = 0; -+ chip->in_progress_block_addr = adr; - -- /* an initial short sleep */ - cfi_spin_unlock(chip->mutex); -- schedule_timeout(HZ/100); -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ schedule_timeout((chip->erase_time*HZ)/(2*1000)); - cfi_spin_lock(chip->mutex); - -+ timeo = jiffies + (HZ*20); -+ -+ for (;;) { - if (chip->state != FL_ERASING) { - /* Someone's suspended the erase. Sleep */ - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); -- - cfi_spin_unlock(chip->mutex); -- printk(KERN_DEBUG "erase suspended. Sleeping\n"); -- - schedule(); - remove_wait_queue(&chip->wq, &wait); --#if 0 -- if (signal_pending(current)) -- return -EINTR; --#endif -- timeo = jiffies + (HZ*2); /* FIXME */ - cfi_spin_lock(chip->mutex); - continue; - } -+ if (chip->erase_suspended) { -+ /* This erase was suspended and resumed. -+ Adjust the timeout */ -+ timeo = jiffies + (HZ*20); /* FIXME */ -+ chip->erase_suspended = 0; -+ } - -- /* Busy wait for 1/10 of a milisecond */ -- for(wait_reps = 0; -- (wait_reps < 100) && -- ((status & dq6) != (oldstatus & dq6)) && -- ((status & dq5) != dq5); -- wait_reps++) { -+ oldstatus = cfi_read(map, adr); -+ status = cfi_read(map, adr); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); -+ if ( (((status ^ oldstatus) & dq6) == 0) -+ || ( ta = time_after(jiffies, timeo)) ) -+ break; - - /* Latency issues. Drop the lock, wait a while and retry */ - cfi_spin_unlock(chip->mutex); -- -- cfi_udelay(1); -- -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ schedule_timeout(1); - cfi_spin_lock(chip->mutex); -- oldstatus = cfi_read(map, adr); -- status = cfi_read(map, adr); - } -+ -+ prev_oldstatus = oldstatus; -+ prev_status = status; - oldstatus = cfi_read(map, adr); - status = cfi_read(map, adr); -- } -- if( (status & dq6) != (oldstatus & dq6) ) -- { -- /* The erasing didn't stop?? */ -- if( ( status & dq5 ) == dq5 ) -- { -- /* When DQ5 raises, we must check once again if DQ6 is toggling. -- If not, the erase has been completed OK. If not, reset chip. */ -- oldstatus = cfi_read( map, adr ); -- status = cfi_read( map, adr ); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); - -- if( ( oldstatus & 0x00FF ) == ( status & 0x00FF ) ) -- { -- printk( "Warning: DQ5 raised while erase operation was in progress, but erase completed OK\n" ); -- } -- else -- { -- /* DQ5 is active so we can do a reset and stop the erase */ -- cfi_write(map, CMD(0xF0), chip->start); -- printk( KERN_WARNING "Internal flash device timeout occured or write operation was performed while flash was erasing\n" ); -+ if ( cfi_buswidth_is_1() ) { -+ datum = (__u8)~0; -+ } else if ( cfi_buswidth_is_2() ) { -+ datum = (__u16)~0; -+ } else if ( cfi_buswidth_is_4() ) { -+ datum = (__u32)~0; -+#ifdef CFI_WORD_64 -+ } else if ( cfi_buswidth_is_8() ) { -+ datum = (__u64)~0; -+#endif -+ } else { -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); -+ goto op_failed; -+ } -+ -+ if ( oldstatus == datum && status == datum ) { -+ /* success - do nothing */ -+ goto op_done; -+ } -+ -+ if ( ta ) { -+ /* Only check dq5 on the chips that are still toggling. */ -+ cfi_word dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1; -+ if ( status & dq5mask ) { -+ /* dq5 asserted - decode interleave chips */ -+ printk( KERN_WARNING -+ "MTD %s(): FLASH internal timeout: 0x%.8x\n", -+ __func__, -+ status & dq5mask ); -+ } else { -+ printk( KERN_WARNING -+ "MTD %s(): Software timed out during write.\n", -+ __func__ ); - } -+ goto op_failed; - } -- else -- { -- printk( "Waiting for erase to complete timed out in do_erase_oneblock."); - -- chip->state = FL_READY; -- wake_up(&chip->wq); -- cfi_spin_unlock(chip->mutex); -- DISABLE_VPP(map); -- return -EIO; -- } -- } -+ HANDLE_WACKY_STATE(); - -- DISABLE_VPP(map); -+ op_failed: -+ /* reset on all failures. */ -+ cfi_write( map, CMD(0xF0), chip->start ); -+ /* FIXME - should have reset delay before continuing */ -+ CHECK_RETRIES(); -+ ret = -EIO; -+ -+ op_done: - chip->state = FL_READY; -- wake_up(&chip->wq); -+ put_chip(map, chip, adr); - cfi_spin_unlock(chip->mutex); -- return 0; -+ -+ return ret; - } - --static int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) -+ -+typedef int (*frob_t)(struct map_info *map, struct flchip *chip, -+ unsigned long adr, void *thunk); -+ -+ -+static int cfi_amdstd_varsize_frob(struct mtd_info *mtd, frob_t frob, -+ loff_t ofs, size_t len, void *thunk) - { - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; -- unsigned long adr, len; -+ unsigned long adr; - int chipnum, ret = 0; - int i, first; - struct mtd_erase_region_info *regions = mtd->eraseregions; - -- if (instr->addr > mtd->size) -+ if (ofs > mtd->size) - return -EINVAL; - -- if ((instr->len + instr->addr) > mtd->size) -+ if ((len + ofs) > mtd->size) - return -EINVAL; - - /* Check that both start and end of the requested erase are -@@ -1008,7 +1656,7 @@ - start of the requested erase, and then go back one. - */ - -- while (i < mtd->numeraseregions && instr->addr >= regions[i].offset) -+ while (i < mtd->numeraseregions && ofs >= regions[i].offset) - i++; - i--; - -@@ -1018,7 +1666,7 @@ - effect here. - */ - -- if (instr->addr & (regions[i].erasesize-1)) -+ if (ofs & (regions[i].erasesize-1)) - return -EINVAL; - - /* Remember the erase region we start on */ -@@ -1028,7 +1676,7 @@ - * with the erase region at that address. - */ - -- while (inumeraseregions && (instr->addr + instr->len) >= regions[i].offset) -+ while (inumeraseregions && (ofs + len) >= regions[i].offset) - i++; - - /* As before, drop back one to point at the region in which -@@ -1036,17 +1684,16 @@ - */ - i--; - -- if ((instr->addr + instr->len) & (regions[i].erasesize-1)) -+ if ((ofs + len) & (regions[i].erasesize-1)) - return -EINVAL; - -- chipnum = instr->addr >> cfi->chipshift; -- adr = instr->addr - (chipnum << cfi->chipshift); -- len = instr->len; -+ chipnum = ofs >> cfi->chipshift; -+ adr = ofs - (chipnum << cfi->chipshift); - - i=first; - -- while(len) { -- ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr); -+ while (len) { -+ ret = (*frob)(map, &cfi->chips[chipnum], adr, thunk); - - if (ret) - return ret; -@@ -1066,50 +1713,171 @@ - } - } - -- instr->state = MTD_ERASE_DONE; -- if (instr->callback) -- instr->callback(instr); -- - return 0; - } - --static int cfi_amdstd_erase_onesize(struct mtd_info *mtd, struct erase_info *instr) -+ -+static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, void *thunk) - { -- struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; -- unsigned long adr, len; -- int chipnum, ret = 0; -+ cfi_word oldstatus, status, prev_oldstatus, prev_status; -+ cfi_word dq6 = CMD(1<<6); -+ unsigned long timeo = jiffies + HZ; -+ DECLARE_WAITQUEUE(wait, current); -+ int ret = 0; -+ int ta = 0; -+ cfi_word datum = 0; -+ DECLARE_RETRY_CMD_CNT(); - -- if (instr->addr & (mtd->erasesize - 1)) -- return -EINVAL; -+ adr += chip->start; - -- if (instr->len & (mtd->erasesize -1)) -- return -EINVAL; -+ cfi_spin_lock(chip->mutex); -+ ret = get_chip(map, chip, adr, FL_ERASING); -+ if (ret) { -+ cfi_spin_unlock(chip->mutex); -+ return ret; -+ } - -- if ((instr->len + instr->addr) > mtd->size) -- return -EINVAL; -+ RETRY_CMD_LABEL; -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n", -+ __func__, adr ); - -- chipnum = instr->addr >> cfi->chipshift; -- adr = instr->addr - (chipnum << cfi->chipshift); -- len = instr->len; -+ ENABLE_VPP(map); -+ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ cfi_write(map, CMD(0x30), adr); - -- while(len) { -- ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr); -+ chip->state = FL_ERASING; -+ chip->erase_suspended = 0; -+ chip->in_progress_block_addr = adr; - -- if (ret) -- return ret; -+ cfi_spin_unlock(chip->mutex); -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ schedule_timeout((chip->erase_time*HZ)/(2*1000)); -+ cfi_spin_lock(chip->mutex); - -- adr += mtd->erasesize; -- len -= mtd->erasesize; -+ timeo = jiffies + (HZ*20); - -- if (adr >> cfi->chipshift) { -- adr = 0; -- chipnum++; -+ /* Wait for the end of programing/erasure by using the toggle method. -+ * As long as there is a programming procedure going on, bit 6 is -+ * toggling its state with each consecutive read. The toggling stops -+ * as soon as the procedure is completed. -+ * -+ * If the process has gone on for too long on the chip, bit 5 gets -+ * set. After bit5 is set you can kill the operation by sending a -+ * reset command to the chip. -+ */ -+ /* See comments in do_write_oneword(). */ - -- if (chipnum >= cfi->numchips) -+ for (;;) { -+ if (chip->state != FL_ERASING) { -+ /* Someone's suspended the erase. Sleep */ -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ add_wait_queue(&chip->wq, &wait); -+ cfi_spin_unlock(chip->mutex); -+ schedule(); -+ remove_wait_queue(&chip->wq, &wait); -+ cfi_spin_lock(chip->mutex); -+ continue; -+ } -+ if (chip->erase_suspended) { -+ /* This erase was suspended and resumed. -+ Adjust the timeout */ -+ timeo = jiffies + (HZ*20); /* FIXME */ -+ chip->erase_suspended = 0; -+ } -+ -+ oldstatus = cfi_read(map, adr); -+ status = cfi_read(map, adr); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); -+ if ( (((status ^ oldstatus) & dq6) == 0) -+ || ( ta = time_after(jiffies, timeo)) ) - break; -+ -+ /* Latency issues. Drop the lock, wait a while and retry */ -+ cfi_spin_unlock(chip->mutex); -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ schedule_timeout(1); -+ cfi_spin_lock(chip->mutex); - } -+ -+ prev_oldstatus = oldstatus; -+ prev_status = status; -+ oldstatus = cfi_read(map, adr); -+ status = cfi_read(map, adr); -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n", -+ __func__, oldstatus, status ); -+ -+ if ( cfi_buswidth_is_1() ) { -+ datum = (__u8)~0; -+ } else if ( cfi_buswidth_is_2() ) { -+ datum = (__u16)~0; -+ } else if ( cfi_buswidth_is_4() ) { -+ datum = (__u32)~0; -+#ifdef CFI_WORD_64 -+ } else if ( cfi_buswidth_is_8() ) { -+ datum = (__u64)~0; -+#endif -+ } else { -+ printk(KERN_WARNING "MTD %s(): Unsupported buswidth %d\n", -+ __func__, CFIDEV_BUSWIDTH); -+ goto op_failed; -+ } -+ -+ if ( oldstatus == datum && status == datum ) { -+ /* success - do nothing */ -+ goto op_done; -+ } -+ -+ if ( ta ) { -+ /* Only check dq5 on the chips that are still toggling. */ -+ cfi_word dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1; -+ if ( status & dq5mask ) { -+ /* dq5 asserted - decode interleave chips */ -+ printk( KERN_WARNING -+ "MTD %s(): FLASH internal timeout: 0x%.8x\n", -+ __func__, -+ status & dq5mask ); -+ } else { -+ printk( KERN_WARNING -+ "MTD %s(): Software timed out during write.\n", -+ __func__ ); - } -+ goto op_failed; -+ } -+ -+ HANDLE_WACKY_STATE(); -+ -+ op_failed: -+ /* reset on all failures. */ -+ cfi_write( map, CMD(0xF0), chip->start ); -+ /* FIXME - should have reset delay before continuing */ -+ CHECK_RETRIES(); -+ ret = -EIO; -+ -+ op_done: -+ chip->state = FL_READY; -+ put_chip(map, chip, adr); -+ cfi_spin_unlock(chip->mutex); -+ return ret; -+} -+ -+ -+int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ unsigned long ofs, len; -+ int ret; -+ -+ ofs = instr->addr; -+ len = instr->len; -+ -+ ret = cfi_amdstd_varsize_frob(mtd, do_erase_oneblock, ofs, len, 0); -+ if (ret) -+ return ret; - - instr->state = MTD_ERASE_DONE; - if (instr->callback) -@@ -1118,6 +1886,7 @@ - return 0; - } - -+ - static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr) - { - struct map_info *map = mtd->priv; -@@ -1141,6 +1910,7 @@ - return 0; - } - -+ - static void cfi_amdstd_sync (struct mtd_info *mtd) - { - struct map_info *map = mtd->priv; -@@ -1254,6 +2024,7 @@ - return ret; - } - -+ - static void cfi_amdstd_resume(struct mtd_info *mtd) - { - struct map_info *map = mtd->priv; -@@ -1279,6 +2050,137 @@ - } - } - -+ -+#ifdef DEBUG_LOCK_BITS -+ -+static int do_printlockstatus_oneblock(struct map_info *map, -+ struct flchip *chip, -+ unsigned long adr, -+ void *thunk) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ int ofs_factor = cfi->interleave * cfi->device_type; -+ -+ cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL); -+ printk(KERN_DEBUG "block status register for 0x%08lx is %x\n", -+ adr, cfi_read_query(map, adr+(2*ofs_factor))); -+ cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL); -+ -+ return 0; -+} -+ -+ -+#define debug_dump_locks(mtd, frob, ofs, len, thunk) \ -+ cfi_amdstd_varsize_frob((mtd), (frob), (ofs), (len), (thunk)) -+ -+#else -+ -+#define debug_dump_locks(...) -+ -+#endif /* DEBUG_LOCK_BITS */ -+ -+ -+struct xxlock_thunk { -+ cfi_word val; -+ flstate_t state; -+}; -+ -+ -+#define DO_XXLOCK_ONEBLOCK_LOCK ((struct xxlock_thunk){0x01, FL_LOCKING}) -+#define DO_XXLOCK_ONEBLOCK_UNLOCK ((struct xxlock_thunk){0x00, FL_UNLOCKING}) -+ -+ -+/* -+ * FIXME - this is *very* specific to a particular chip. It likely won't -+ * work for all chips that require unlock. It also hasn't been tested -+ * with interleaved chips. -+ */ -+static int do_xxlock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, void *thunk) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ struct xxlock_thunk *xxlt = (struct xxlock_thunk *)thunk; -+ int ret; -+ -+ /* -+ * This is easy because these are writes to registers and not writes -+ * to flash memory - that means that we don't have to check status -+ * and timeout. -+ */ -+ -+ adr += chip->start; -+ /* -+ * lock block registers: -+ * - on 64k boundariesand -+ * - bit 1 set high -+ * - block lock registers are 4MiB lower - overflow subtract (danger) -+ */ -+ adr = ((adr & ~0xffff) | 0x2) + ~0x3fffff; -+ -+ cfi_spin_lock(chip->mutex); -+ ret = get_chip(map, chip, adr, FL_LOCKING); -+ if (ret) { -+ cfi_spin_unlock(chip->mutex); -+ return ret; -+ } -+ -+ chip->state = xxlt->state; -+ cfi_write(map, CMD(xxlt->val), adr); -+ -+ /* Done and happy. */ -+ chip->state = FL_READY; -+ put_chip(map, chip, adr); -+ cfi_spin_unlock(chip->mutex); -+ return 0; -+} -+ -+ -+static int cfi_amdstd_lock_varsize(struct mtd_info *mtd, -+ loff_t ofs, -+ size_t len) -+{ -+ int ret; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, -+ "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", -+ __func__, ofs, len); -+ debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); -+ -+ ret = cfi_amdstd_varsize_frob(mtd, do_xxlock_oneblock, ofs, len, -+ (void *)&DO_XXLOCK_ONEBLOCK_LOCK); -+ -+ DEBUG(MTD_DEBUG_LEVEL3, -+ "%s: lock status after, ret=%d\n", -+ __func__, ret); -+ -+ debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); -+ -+ return ret; -+} -+ -+ -+static int cfi_amdstd_unlock_varsize(struct mtd_info *mtd, -+ loff_t ofs, -+ size_t len) -+{ -+ int ret; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, -+ "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", -+ __func__, ofs, len); -+ debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); -+ -+ ret = cfi_amdstd_varsize_frob(mtd, do_xxlock_oneblock, ofs, len, -+ (void *)&DO_XXLOCK_ONEBLOCK_UNLOCK); -+ -+ DEBUG(MTD_DEBUG_LEVEL3, -+ "%s: lock status after, ret=%d\n", -+ __func__, ret); -+ debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); -+ -+ return ret; -+} -+ -+ - static void cfi_amdstd_destroy(struct mtd_info *mtd) - { - struct map_info *map = mtd->priv; -@@ -1291,17 +2193,20 @@ - - static char im_name[]="cfi_cmdset_0002"; - -+ - int __init cfi_amdstd_init(void) - { - inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0002); - return 0; - } - -+ - static void __exit cfi_amdstd_exit(void) - { - inter_module_unregister(im_name); - } - -+ - module_init(cfi_amdstd_init); - module_exit(cfi_amdstd_exit); - -@@ -1309,3 +2214,7 @@ - MODULE_AUTHOR("Crossnet Co. et al."); - MODULE_DESCRIPTION("MTD chip driver for AMD/Fujitsu flash chips"); - -+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY -+MODULE_PARM(retry_cmd_max, "i"); -+MODULE_PARM_DESC(retry_cmd_max, "Number of times to retry an erase or program command if it fails - should only be needed by buggy hardware: default 0"); -+#endif -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/cfi_cmdset_0020.c linux/drivers/mtd/chips/cfi_cmdset_0020.c ---- linux-mips-2.4.27/drivers/mtd/chips/cfi_cmdset_0020.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/chips/cfi_cmdset_0020.c 2004-11-19 10:25:11.747222896 +0100 -@@ -21,16 +21,19 @@ - #include - #include - #include -+#include - #include - #include - - #include -+#include - #include - #include - #include -+#include - #include - #include --#include -+#include - - - static int cfi_staa_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); -@@ -51,10 +54,10 @@ - static struct mtd_info *cfi_staa_setup (struct map_info *); - - static struct mtd_chip_driver cfi_staa_chipdrv = { -- probe: NULL, /* Not usable directly */ -- destroy: cfi_staa_destroy, -- name: "cfi_cmdset_0020", -- module: THIS_MODULE -+ .probe = NULL, /* Not usable directly */ -+ .destroy = cfi_staa_destroy, -+ .name = "cfi_cmdset_0020", -+ .module = THIS_MODULE - }; - - /* #define DEBUG_LOCK_BITS */ -@@ -113,7 +116,6 @@ - { - struct cfi_private *cfi = map->fldrv_priv; - int i; -- __u32 base = cfi->chips[0].start; - - if (cfi->cfi_mode) { - /* -@@ -123,35 +125,10 @@ - */ - __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; - struct cfi_pri_intelext *extp; -- int ofs_factor = cfi->interleave * cfi->device_type; -- -- printk(" ST Microelectronics Extended Query Table at 0x%4.4X\n", adr); -- if (!adr) -- return NULL; -- -- /* Switch it into Query Mode */ -- cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); -- -- extp = kmalloc(sizeof(*extp), GFP_KERNEL); -- if (!extp) { -- printk(KERN_ERR "Failed to allocate memory\n"); -- return NULL; -- } -- -- /* Read in the Extended Query Table */ -- for (i=0; iMajorVersion != '1' || -- (extp->MinorVersion < '0' || extp->MinorVersion > '2')) { -- printk(KERN_WARNING " Unknown staa Extended Query " -- "version %c.%c.\n", extp->MajorVersion, -- extp->MinorVersion); -- kfree(extp); -+ extp = (struct cfi_pri_intelext*)cfi_read_pri(map, adr, sizeof(*extp), "ST Microelectronics"); -+ if (!extp) - return NULL; -- } - - /* Do some byteswapping if necessary */ - extp->FeatureSupport = cfi32_to_cpu(extp->FeatureSupport); -@@ -172,11 +149,6 @@ - cfi->chips[i].erase_time = 1024; - } - -- map->fldrv = &cfi_staa_chipdrv; -- MOD_INC_USE_COUNT; -- -- /* Make sure it's in read mode */ -- cfi_send_gen_cmd(0xff, 0x55, base, map, cfi, cfi->device_type, NULL); - return cfi_staa_setup(map); - } - -@@ -208,6 +180,7 @@ - if (!mtd->eraseregions) { - printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n"); - kfree(cfi->cmdset_priv); -+ kfree(mtd); - return NULL; - } - -@@ -232,6 +205,7 @@ - printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize); - kfree(mtd->eraseregions); - kfree(cfi->cmdset_priv); -+ kfree(mtd); - return NULL; - } - -@@ -256,7 +230,7 @@ - mtd->flags |= MTD_ECC; /* FIXME: Not all STMicro flashes have this */ - mtd->eccsize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */ - map->fldrv = &cfi_staa_chipdrv; -- MOD_INC_USE_COUNT; -+ __module_get(THIS_MODULE); - mtd->name = map->name; - return mtd; - } -@@ -288,7 +262,7 @@ - */ - switch (chip->state) { - case FL_ERASING: -- if (!((struct cfi_pri_intelext *)cfi->cmdset_priv)->FeatureSupport & 2) -+ if (!(((struct cfi_pri_intelext *)cfi->cmdset_priv)->FeatureSupport & 2)) - goto sleep; /* We don't support erase suspend */ - - cfi_write (map, CMD(0xb0), cmd_addr); -@@ -374,7 +348,7 @@ - goto retry; - } - -- map->copy_from(map, buf, adr, len); -+ map_copy_from(map, buf, adr, len); - - if (suspended) { - chip->state = chip->oldstate; -@@ -540,11 +514,11 @@ - /* Write data */ - for (z = 0; z < len; z += CFIDEV_BUSWIDTH) { - if (cfi_buswidth_is_1()) { -- map->write8 (map, *((__u8*)buf)++, adr+z); -+ map_write8 (map, *((__u8*)buf)++, adr+z); - } else if (cfi_buswidth_is_2()) { -- map->write16 (map, *((__u16*)buf)++, adr+z); -+ map_write16 (map, *((__u16*)buf)++, adr+z); - } else if (cfi_buswidth_is_4()) { -- map->write32 (map, *((__u32*)buf)++, adr+z); -+ map_write32 (map, *((__u32*)buf)++, adr+z); - } else { - DISABLE_VPP(map); - return -EINVAL; -@@ -1436,13 +1410,13 @@ - - static char im_name[]="cfi_cmdset_0020"; - --mod_init_t cfi_staa_init(void) -+int __init cfi_staa_init(void) - { - inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0020); - return 0; - } - --mod_exit_t cfi_staa_exit(void) -+static void __exit cfi_staa_exit(void) - { - inter_module_unregister(im_name); - } -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/cfi_probe.c linux/drivers/mtd/chips/cfi_probe.c ---- linux-mips-2.4.27/drivers/mtd/chips/cfi_probe.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/chips/cfi_probe.c 2004-11-19 10:25:11.766220008 +0100 -@@ -1,13 +1,14 @@ - /* - Common Flash Interface probe code. - (C) 2000 Red Hat. GPL'd. -- $Id$ -+ $Id$ - */ - - #include - #include - #include - #include -+#include - #include - #include - #include -@@ -25,7 +26,7 @@ - #endif - - static int cfi_probe_chip(struct map_info *map, __u32 base, -- struct flchip *chips, struct cfi_private *cfi); -+ unsigned long *chip_map, struct cfi_private *cfi); - static int cfi_chip_setup(struct map_info *map, struct cfi_private *cfi); - - struct mtd_info *cfi_probe(struct map_info *map); -@@ -48,7 +49,7 @@ - } - - static int cfi_probe_chip(struct map_info *map, __u32 base, -- struct flchip *chips, struct cfi_private *cfi) -+ unsigned long *chip_map, struct cfi_private *cfi) - { - int i; - -@@ -77,18 +78,24 @@ - } - - /* Check each previous chip to see if it's an alias */ -- for (i=0; inumchips; i++) { -+ for (i=0; i < (base >> cfi->chipshift); i++) { -+ unsigned long start; -+ if(!test_bit(i, chip_map)) { -+ /* Skip location; no valid chip at this address */ -+ continue; -+ } -+ start = i << cfi->chipshift; - /* This chip should be in read mode if it's one - we've already touched. */ -- if (qry_present(map,chips[i].start,cfi)) { -+ if (qry_present(map, start, cfi)) { - /* Eep. This chip also had the QRY marker. - * Is it an alias for the new one? */ -- cfi_send_gen_cmd(0xF0, 0, chips[i].start, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0xF0, 0, start, map, cfi, cfi->device_type, NULL); - - /* If the QRY marker goes away, it's an alias */ -- if (!qry_present(map, chips[i].start, cfi)) { -+ if (!qry_present(map, start, cfi)) { - printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", -- map->name, base, chips[i].start); -+ map->name, base, start); - return 0; - } - /* Yes, it's actually got QRY for data. Most -@@ -99,7 +106,7 @@ - - if (qry_present(map, base, cfi)) { - printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", -- map->name, base, chips[i].start); -+ map->name, base, start); - return 0; - } - } -@@ -107,13 +114,7 @@ - - /* OK, if we got to here, then none of the previous chips appear to - be aliases for the current one. */ -- if (cfi->numchips == MAX_CFI_CHIPS) { -- printk(KERN_WARNING"%s: Too many flash chips detected. Increase MAX_CFI_CHIPS from %d.\n", map->name, MAX_CFI_CHIPS); -- /* Doesn't matter about resetting it to Read Mode - we're not going to talk to it anyway */ -- return -1; -- } -- chips[cfi->numchips].start = base; -- chips[cfi->numchips].state = FL_READY; -+ set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */ - cfi->numchips++; - - /* Put it back into Read Mode */ -@@ -179,9 +180,28 @@ - (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1); - #endif - } -+ -+ /* Note we put the device back into Read Mode BEFORE going into Auto -+ * Select Mode, as some devices support nesting of modes, others -+ * don't. This way should always work. -+ * On cmdset 0001 the writes of 0xaa and 0x55 are not needed, and -+ * so should be treated as nops or illegal (and so put the device -+ * back into Read Mode, which is a nop in this case). -+ */ -+ cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0xaa, 0x555, base, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL); -+ cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL); -+ cfi->mfr = cfi_read_query(map, base); -+ cfi->id = cfi_read_query(map, base + ofs_factor); -+ - /* Put it back into Read Mode */ - cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); - -+ printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit mode\n", -+ map->name, cfi->interleave, cfi->device_type*8, base, -+ map->buswidth*8); -+ - return 1; - } - -@@ -240,11 +260,11 @@ - printk("No Alternate Algorithm Table\n"); - - -- printk("Vcc Minimum: %x.%x V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf); -- printk("Vcc Maximum: %x.%x V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf); -+ printk("Vcc Minimum: %2d.%d V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf); -+ printk("Vcc Maximum: %2d.%d V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf); - if (cfip->VppMin) { -- printk("Vpp Minimum: %x.%x V\n", cfip->VppMin >> 4, cfip->VppMin & 0xf); -- printk("Vpp Maximum: %x.%x V\n", cfip->VppMax >> 4, cfip->VppMax & 0xf); -+ printk("Vpp Minimum: %2d.%d V\n", cfip->VppMin >> 4, cfip->VppMin & 0xf); -+ printk("Vpp Maximum: %2d.%d V\n", cfip->VppMax >> 4, cfip->VppMax & 0xf); - } - else - printk("No Vpp line\n"); -@@ -303,8 +323,8 @@ - #endif /* DEBUG_CFI */ - - static struct chip_probe cfi_chip_probe = { -- name: "CFI", -- probe_chip: cfi_probe_chip -+ .name = "CFI", -+ .probe_chip = cfi_probe_chip - }; - - struct mtd_info *cfi_probe(struct map_info *map) -@@ -317,9 +337,9 @@ - } - - static struct mtd_chip_driver cfi_chipdrv = { -- probe: cfi_probe, -- name: "cfi_probe", -- module: THIS_MODULE -+ .probe = cfi_probe, -+ .name = "cfi_probe", -+ .module = THIS_MODULE - }; - - int __init cfi_probe_init(void) -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/cfi_util.c linux/drivers/mtd/chips/cfi_util.c ---- linux-mips-2.4.27/drivers/mtd/chips/cfi_util.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/chips/cfi_util.c 2004-11-19 10:25:11.767219856 +0100 -@@ -0,0 +1,91 @@ -+/* -+ * Common Flash Interface support: -+ * Generic utility functions not dependant on command set -+ * -+ * Copyright (C) 2002 Red Hat -+ * Copyright (C) 2003 STMicroelectronics Limited -+ * -+ * This code is covered by the GPL. -+ * -+ * $Id$ -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct cfi_extquery * -+cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ __u32 base = 0; // cfi->chips[0].start; -+ int ofs_factor = cfi->interleave * cfi->device_type; -+ int i; -+ struct cfi_extquery *extp = NULL; -+ -+ printk(" %s Extended Query Table at 0x%4.4X\n", name, adr); -+ if (!adr) -+ goto out; -+ -+ /* Switch it into Query Mode */ -+ cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); -+ -+ extp = kmalloc(size, GFP_KERNEL); -+ if (!extp) { -+ printk(KERN_ERR "Failed to allocate memory\n"); -+ goto out; -+ } -+ -+ /* Read in the Extended Query Table */ -+ for (i=0; iMajorVersion != '1' || -+ (extp->MinorVersion < '0' || extp->MinorVersion > '3')) { -+ printk(KERN_WARNING " Unknown %s Extended Query " -+ "version %c.%c.\n", name, extp->MajorVersion, -+ extp->MinorVersion); -+ kfree(extp); -+ extp = NULL; -+ goto out; -+ } -+ -+out: -+ /* Make sure it's in read mode */ -+ cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL); -+ -+ return extp; -+} -+ -+EXPORT_SYMBOL(cfi_read_pri); -+ -+void cfi_fixup(struct map_info *map, struct cfi_fixup* fixups) -+{ -+ struct cfi_private *cfi = map->fldrv_priv; -+ struct cfi_fixup *f; -+ -+ for (f=fixups; f->fixup; f++) { -+ if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi->mfr)) && -+ ((f->id == CFI_ID_ANY) || (f->id == cfi->id))) { -+ f->fixup(map, f->param); -+ } -+ } -+} -+ -+EXPORT_SYMBOL(cfi_fixup); -+ -+MODULE_LICENSE("GPL"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/chipreg.c linux/drivers/mtd/chips/chipreg.c ---- linux-mips-2.4.27/drivers/mtd/chips/chipreg.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/chips/chipreg.c 2004-11-19 10:25:11.769219552 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Registration for chip drivers - * -@@ -7,10 +7,13 @@ - - #include - #include -+#include - #include - #include --#include -+#include - #include -+#include -+#include - - spinlock_t chip_drvs_lock = SPIN_LOCK_UNLOCKED; - static LIST_HEAD(chip_drvs_list); -@@ -44,10 +47,8 @@ - break; - } - } -- if (ret && !try_inc_mod_count(ret->module)) { -- /* Eep. Failed. */ -+ if (ret && !try_module_get(ret->module)) - ret = NULL; -- } - - spin_unlock(&chip_drvs_lock); - -@@ -64,32 +65,46 @@ - - drv = get_mtd_chip_driver(name); - -- if (!drv && !request_module(name)) -+ if (!drv && !request_module("%s", name)) - drv = get_mtd_chip_driver(name); - - if (!drv) - return NULL; - - ret = drv->probe(map); --#ifdef CONFIG_MODULES -+ - /* We decrease the use count here. It may have been a - probe-only module, which is no longer required from this - point, having given us a handle on (and increased the use - count of) the actual driver code. - */ -- if(drv->module) -- __MOD_DEC_USE_COUNT(drv->module); --#endif -+ module_put(drv->module); - - if (ret) - return ret; - - return NULL; - } -+/* -+ * Destroy an MTD device which was created for a map device. -+ * Make sure the MTD device is already unregistered before calling this -+ */ -+void map_destroy(struct mtd_info *mtd) -+{ -+ struct map_info *map = mtd->priv; -+ -+ if (map->fldrv->destroy) -+ map->fldrv->destroy(mtd); -+ -+ module_put(map->fldrv->module); -+ -+ kfree(mtd); -+} - - EXPORT_SYMBOL(register_mtd_chip_driver); - EXPORT_SYMBOL(unregister_mtd_chip_driver); - EXPORT_SYMBOL(do_map_probe); -+EXPORT_SYMBOL(map_destroy); - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("David Woodhouse "); -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/gen_probe.c linux/drivers/mtd/chips/gen_probe.c ---- linux-mips-2.4.27/drivers/mtd/chips/gen_probe.c 2003-08-13 19:19:18.000000000 +0200 -+++ linux/drivers/mtd/chips/gen_probe.c 2004-11-19 10:25:11.770219400 +0100 -@@ -1,14 +1,17 @@ - /* - * Routines common to all CFI-type probes. -- * (C) 2001, 2001 Red Hat, Inc. -+ * (C) 2001-2003 Red Hat, Inc. - * GPL'd -- * $Id$ -+ * $Id$ - */ - - #include -+#include -+#include - #include - #include - #include -+#include - #include - - static struct mtd_info *check_cmd_set(struct map_info *, int); -@@ -50,11 +53,11 @@ - - struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp) - { -- unsigned long base=0; - struct cfi_private cfi; - struct cfi_private *retcfi; -- struct flchip chip[MAX_CFI_CHIPS]; -- int i; -+ unsigned long *chip_map; -+ int i, j; -+ int max_chips; - - memset(&cfi, 0, sizeof(cfi)); - -@@ -77,8 +80,6 @@ - return NULL; - } - #endif -- chip[0].start = 0; -- chip[0].state = FL_READY; - cfi.chipshift = cfi.cfiq->DevSize; - - switch(cfi.interleave) { -@@ -103,20 +104,28 @@ - cfi.numchips = 1; - - /* -+ * Allocate memory for bitmap of valid chips. -+ * Align bitmap storage size to full byte. -+ */ -+ max_chips = map->size >> cfi.chipshift; -+ chip_map = kmalloc((max_chips / 8) + ((max_chips % 8) ? 1 : 0), GFP_KERNEL); -+ if (!chip_map) { -+ printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name); -+ kfree(cfi.cfiq); -+ return NULL; -+ } -+ -+ set_bit(0, chip_map); /* Mark first chip valid */ -+ -+ /* - * Now probe for other chips, checking sensibly for aliases while - * we're at it. The new_chip probe above should have let the first - * chip in read mode. -- * -- * NOTE: Here, we're checking if there is room for another chip -- * the same size within the mapping. Therefore, -- * base + chipsize <= map->size is the correct thing to do, -- * because, base + chipsize would be the _first_ byte of the -- * next chip, not the one we're currently pondering. - */ - -- for (base = (1<size; -- base += (1<probe_chip(map, base, &chip[0], &cfi); -+ for (i = 1; i < max_chips; i++) { -+ cp->probe_chip(map, i << cfi.chipshift, chip_map, &cfi); -+ } - - /* - * Now allocate the space for the structures we need to return to -@@ -128,19 +137,26 @@ - if (!retcfi) { - printk(KERN_WARNING "%s: kmalloc failed for CFI private structure\n", map->name); - kfree(cfi.cfiq); -+ kfree(chip_map); - return NULL; - } - - memcpy(retcfi, &cfi, sizeof(cfi)); -- memcpy(&retcfi->chips[0], chip, sizeof(struct flchip) * cfi.numchips); -+ memset(&retcfi->chips[0], 0, sizeof(struct flchip) * cfi.numchips); - -- /* Fix up the stuff that breaks when you move it */ -- for (i=0; i< retcfi->numchips; i++) { -- init_waitqueue_head(&retcfi->chips[i].wq); -- spin_lock_init(&retcfi->chips[i]._spinlock); -- retcfi->chips[i].mutex = &retcfi->chips[i]._spinlock; -+ for (i = 0, j = 0; (j < cfi.numchips) && (i < max_chips); i++) { -+ if(test_bit(i, chip_map)) { -+ struct flchip *pchip = &retcfi->chips[j++]; -+ -+ pchip->start = (i << cfi.chipshift); -+ pchip->state = FL_READY; -+ init_waitqueue_head(&pchip->wq); -+ spin_lock_init(&pchip->_spinlock); -+ pchip->mutex = &pchip->_spinlock; -+ } - } - -+ kfree(chip_map); - return retcfi; - } - -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/jedec.c linux/drivers/mtd/chips/jedec.c ---- linux-mips-2.4.27/drivers/mtd/chips/jedec.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/chips/jedec.c 2004-11-19 10:25:11.772219096 +0100 -@@ -11,10 +11,16 @@ - * not going to guess how to send commands to them, plus I expect they will - * all speak CFI.. - * -- * $Id$ -+ * $Id$ - */ - -+#include -+#include -+#include - #include -+#include -+#include -+#include - - static struct mtd_info *jedec_probe(struct map_info *); - static int jedec_probe8(struct map_info *map,unsigned long base, -@@ -33,14 +39,51 @@ - - /* Listing of parts and sizes. We need this table to learn the sector - size of the chip and the total length */ --static const struct JEDECTable JEDEC_table[] = -- {{0x013D,"AMD Am29F017D",2*1024*1024,64*1024,MTD_CAP_NORFLASH}, -- {0x01AD,"AMD Am29F016",2*1024*1024,64*1024,MTD_CAP_NORFLASH}, -- {0x01D5,"AMD Am29F080",1*1024*1024,64*1024,MTD_CAP_NORFLASH}, -- {0x01A4,"AMD Am29F040",512*1024,64*1024,MTD_CAP_NORFLASH}, -- {0x20E3,"AMD Am29W040B",512*1024,64*1024,MTD_CAP_NORFLASH}, -- {0xC2AD,"Macronix MX29F016",2*1024*1024,64*1024,MTD_CAP_NORFLASH}, -- {}}; -+static const struct JEDECTable JEDEC_table[] = { -+ { -+ .jedec = 0x013D, -+ .name = "AMD Am29F017D", -+ .size = 2*1024*1024, -+ .sectorsize = 64*1024, -+ .capabilities = MTD_CAP_NORFLASH -+ }, -+ { -+ .jedec = 0x01AD, -+ .name = "AMD Am29F016", -+ .size = 2*1024*1024, -+ .sectorsize = 64*1024, -+ .capabilities = MTD_CAP_NORFLASH -+ }, -+ { -+ .jedec = 0x01D5, -+ .name = "AMD Am29F080", -+ .size = 1*1024*1024, -+ .sectorsize = 64*1024, -+ .capabilities = MTD_CAP_NORFLASH -+ }, -+ { -+ .jedec = 0x01A4, -+ .name = "AMD Am29F040", -+ .size = 512*1024, -+ .sectorsize = 64*1024, -+ .capabilities = MTD_CAP_NORFLASH -+ }, -+ { -+ .jedec = 0x20E3, -+ .name = "AMD Am29W040B", -+ .size = 512*1024, -+ .sectorsize = 64*1024, -+ .capabilities = MTD_CAP_NORFLASH -+ }, -+ { -+ .jedec = 0xC2AD, -+ .name = "Macronix MX29F016", -+ .size = 2*1024*1024, -+ .sectorsize = 64*1024, -+ .capabilities = MTD_CAP_NORFLASH -+ }, -+ { .jedec = 0x0 } -+}; - - static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id); - static void jedec_sync(struct mtd_info *mtd) {}; -@@ -54,9 +97,9 @@ - - - static struct mtd_chip_driver jedec_chipdrv = { -- probe: jedec_probe, -- name: "jedec", -- module: THIS_MODULE -+ .probe = jedec_probe, -+ .name = "jedec", -+ .module = THIS_MODULE - }; - - /* Probe entry point */ -@@ -131,8 +174,7 @@ - /* Generate a part name that includes the number of different chips and - other configuration information */ - count = 1; -- strncpy(Part,map->name,sizeof(Part)-10); -- Part[sizeof(Part)-11] = 0; -+ strlcpy(Part,map->name,sizeof(Part)-10); - strcat(Part," "); - Uniq = 0; - for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) -@@ -209,8 +251,7 @@ - // printk("Part: '%s'\n",Part); - - memset(MTD,0,sizeof(*MTD)); -- // strncpy(MTD->name,Part,sizeof(MTD->name)); -- // MTD->name[sizeof(MTD->name)-1] = 0; -+ // strlcpy(MTD->name,Part,sizeof(MTD->name)); - MTD->name = map->name; - MTD->type = MTD_NORFLASH; - MTD->flags = MTD_CAP_NORFLASH; -@@ -229,7 +270,7 @@ - MTD->priv = map; - map->fldrv_priv = priv; - map->fldrv = &jedec_chipdrv; -- MOD_INC_USE_COUNT; -+ __module_get(THIS_MODULE); - return MTD; - } - -@@ -351,8 +392,8 @@ - static int jedec_probe8(struct map_info *map,unsigned long base, - struct jedec_private *priv) - { -- #define flread(x) map->read8(map,base+x) -- #define flwrite(v,x) map->write8(map,v,base+x) -+ #define flread(x) map_read8(map,base+x) -+ #define flwrite(v,x) map_write8(map,v,base+x) - - const unsigned long AutoSel1 = 0xAA; - const unsigned long AutoSel2 = 0x55; -@@ -411,8 +452,8 @@ - static int jedec_probe32(struct map_info *map,unsigned long base, - struct jedec_private *priv) - { -- #define flread(x) map->read32(map,base+((x)<<2)) -- #define flwrite(v,x) map->write32(map,v,base+((x)<<2)) -+ #define flread(x) map_read32(map,base+((x)<<2)) -+ #define flwrite(v,x) map_write32(map,v,base+((x)<<2)) - - const unsigned long AutoSel1 = 0xAAAAAAAA; - const unsigned long AutoSel2 = 0x55555555; -@@ -490,7 +531,7 @@ - { - struct map_info *map = (struct map_info *)mtd->priv; - -- map->copy_from(map, buf, from, len); -+ map_copy_from(map, buf, from, len); - *retlen = len; - return 0; - } -@@ -514,7 +555,7 @@ - get = priv->bank_fill[0] - offset; - - bank /= priv->bank_fill[0]; -- map->copy_from(map,buf + *retlen,bank*my_bank_size + offset,get); -+ map_copy_from(map,buf + *retlen,bank*my_bank_size + offset,get); - - len -= get; - *retlen += get; -@@ -545,8 +586,8 @@ - static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) - { - // Does IO to the currently selected chip -- #define flread(x) map->read8(map,chip->base+((x)<addrshift)) -- #define flwrite(v,x) map->write8(map,v,chip->base+((x)<addrshift)) -+ #define flread(x) map_read8(map,chip->base+((x)<addrshift)) -+ #define flwrite(v,x) map_write8(map,v,chip->base+((x)<addrshift)) - - unsigned long Time = 0; - unsigned long NoTime = 0; -@@ -608,7 +649,7 @@ - - /* Poll the flash for erasure completion, specs say this can take as long - as 480 seconds to do all the sectors (for a 2 meg flash). -- Erasure time is dependant on chip age, temp and wear.. */ -+ Erasure time is dependent on chip age, temp and wear.. */ - - /* This being a generic routine assumes a 32 bit bus. It does read32s - and bundles interleved chips into the same grouping. This will work -@@ -651,19 +692,19 @@ - or this is not really flash ;> */ - switch (map->buswidth) { - case 1: -- Last[0] = map->read8(map,(chip->base >> chip->addrshift) + chip->start + off); -- Last[1] = map->read8(map,(chip->base >> chip->addrshift) + chip->start + off); -- Last[2] = map->read8(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[0] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[1] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[2] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); - break; - case 2: -- Last[0] = map->read16(map,(chip->base >> chip->addrshift) + chip->start + off); -- Last[1] = map->read16(map,(chip->base >> chip->addrshift) + chip->start + off); -- Last[2] = map->read16(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[0] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[1] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[2] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); - break; - case 3: -- Last[0] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); -- Last[1] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); -- Last[2] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[0] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[1] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[2] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); - break; - } - Count = 3; -@@ -699,13 +740,13 @@ - - switch (map->buswidth) { - case 1: -- Last[Count % 4] = map->read8(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[Count % 4] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); - break; - case 2: -- Last[Count % 4] = map->read16(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[Count % 4] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); - break; - case 4: -- Last[Count % 4] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); -+ Last[Count % 4] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); - break; - } - Count++; -@@ -755,10 +796,10 @@ - size_t *retlen, const u_char *buf) - { - /* Does IO to the currently selected chip. It takes the bank addressing -- base (which is divisable by the chip size) adds the necesary lower bits -- of addrshift (interleve index) and then adds the control register index. */ -- #define flread(x) map->read8(map,base+(off&((1<addrshift)-1))+((x)<addrshift)) -- #define flwrite(v,x) map->write8(map,v,base+(off&((1<addrshift)-1))+((x)<addrshift)) -+ base (which is divisible by the chip size) adds the necessary lower bits -+ of addrshift (interleave index) and then adds the control register index. */ -+ #define flread(x) map_read8(map,base+(off&((1<addrshift)-1))+((x)<addrshift)) -+ #define flwrite(v,x) map_write8(map,v,base+(off&((1<addrshift)-1))+((x)<addrshift)) - - struct map_info *map = (struct map_info *)mtd->priv; - struct jedec_private *priv = (struct jedec_private *)map->fldrv_priv; -@@ -794,7 +835,7 @@ - // Loop over this page - for (; off != (chip->size << chip->addrshift) && len != 0; start++, len--, off++,buf++) - { -- unsigned char oldbyte = map->read8(map,base+off); -+ unsigned char oldbyte = map_read8(map,base+off); - unsigned char Last[4]; - unsigned long Count = 0; - -@@ -809,10 +850,10 @@ - flwrite(0xAA,0x555); - flwrite(0x55,0x2AA); - flwrite(0xA0,0x555); -- map->write8(map,*buf,base + off); -- Last[0] = map->read8(map,base + off); -- Last[1] = map->read8(map,base + off); -- Last[2] = map->read8(map,base + off); -+ map_write8(map,*buf,base + off); -+ Last[0] = map_read8(map,base + off); -+ Last[1] = map_read8(map,base + off); -+ Last[2] = map_read8(map,base + off); - - /* Wait for the flash to finish the operation. We store the last 4 - status bytes that have been retrieved so we can determine why -@@ -820,7 +861,7 @@ - failure */ - for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && - Count < 10000; Count++) -- Last[Count % 4] = map->read8(map,base + off); -+ Last[Count % 4] = map_read8(map,base + off); - if (Last[(Count - 1) % 4] != *buf) - { - jedec_flash_failed(Last[(Count - 3) % 4]); -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/jedec_probe.c linux/drivers/mtd/chips/jedec_probe.c ---- linux-mips-2.4.27/drivers/mtd/chips/jedec_probe.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/chips/jedec_probe.c 2004-11-19 10:25:11.774218792 +0100 -@@ -1,9 +1,11 @@ - /* - Common Flash Interface probe code. - (C) 2000 Red Hat. GPL'd. -- $Id$ -+ $Id$ - See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5) - for the standard this probe goes back to. -+ -+ Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com - */ - - #include -@@ -15,7 +17,9 @@ - #include - #include - #include -+#include - -+#include - #include - #include - #include -@@ -26,20 +30,24 @@ - #define MANUFACTURER_FUJITSU 0x0004 - #define MANUFACTURER_INTEL 0x0089 - #define MANUFACTURER_MACRONIX 0x00C2 --#define MANUFACTURER_ST 0x0020 -+#define MANUFACTURER_PMC 0x009D - #define MANUFACTURER_SST 0x00BF -+#define MANUFACTURER_ST 0x0020 - #define MANUFACTURER_TOSHIBA 0x0098 -+#define MANUFACTURER_WINBOND 0x00da - - - /* AMD */ - #define AM29F800BB 0x2258 - #define AM29F800BT 0x22D6 -+#define AM29LV400BB 0x22BA -+#define AM29LV400BT 0x22B9 - #define AM29LV800BB 0x225B - #define AM29LV800BT 0x22DA - #define AM29LV160DT 0x22C4 - #define AM29LV160DB 0x2249 - #define AM29F017D 0x003D --#define AM29F016 0x00AD -+#define AM29F016D 0x00AD - #define AM29F080 0x00D5 - #define AM29F040 0x00A4 - #define AM29LV040B 0x004F -@@ -54,6 +62,7 @@ - #define AT49BV32XT 0x00C9 - - /* Fujitsu */ -+#define MBM29F040C 0x00A4 - #define MBM29LV650UE 0x22D7 - #define MBM29LV320TE 0x22F6 - #define MBM29LV320BE 0x22F9 -@@ -61,6 +70,9 @@ - #define MBM29LV160BE 0x2249 - #define MBM29LV800BA 0x225B - #define MBM29LV800TA 0x22DA -+#define MBM29LV400TC 0x22B9 -+#define MBM29LV400BC 0x22BA -+ - - /* Intel */ - #define I28F004B3T 0x00d4 -@@ -93,8 +105,14 @@ - #define MX29F004T 0x0045 - #define MX29F004B 0x0046 - -+/* PMC */ -+#define PM49FL002 0x006D -+#define PM49FL004 0x006E -+#define PM49FL008 0x006A -+ - /* ST - www.st.com */ --#define M29W800T 0x00D7 -+#define M29W800DT 0x00D7 -+#define M29W800DB 0x005B - #define M29W160DT 0x22C4 - #define M29W160DB 0x2249 - #define M29W040B 0x00E3 -@@ -110,6 +128,7 @@ - #define SST39LF040 0x00D7 - #define SST39SF010A 0x00B5 - #define SST39SF020A 0x00B6 -+#define SST49LF004B 0x0060 - #define SST49LF030A 0x001C - #define SST49LF040A 0x0051 - #define SST49LF080A 0x005B -@@ -122,15 +141,87 @@ - #define TC58FVT641 0x0093 - #define TC58FVB641 0x0095 - -+/* Winbond */ -+#define W49V002A 0x00b0 -+ -+ -+/* -+ * Unlock address sets for AMD command sets. -+ * Intel command sets use the MTD_UADDR_UNNECESSARY. -+ * Each identifier, except MTD_UADDR_UNNECESSARY, and -+ * MTD_UADDR_NO_SUPPORT must be defined below in unlock_addrs[]. -+ * MTD_UADDR_NOT_SUPPORTED must be 0 so that structure -+ * initialization need not require initializing all of the -+ * unlock addresses for all bit widths. -+ */ -+enum uaddr { -+ MTD_UADDR_NOT_SUPPORTED = 0, /* data width not supported */ -+ MTD_UADDR_0x0555_0x02AA, -+ MTD_UADDR_0x0555_0x0AAA, -+ MTD_UADDR_0x5555_0x2AAA, -+ MTD_UADDR_0x0AAA_0x0555, -+ MTD_UADDR_DONT_CARE, /* Requires an arbitrary address */ -+ MTD_UADDR_UNNECESSARY, /* Does not require any address */ -+}; -+ -+ -+struct unlock_addr { -+ int addr1; -+ int addr2; -+}; -+ -+ -+/* -+ * I don't like the fact that the first entry in unlock_addrs[] -+ * exists, but is for MTD_UADDR_NOT_SUPPORTED - and, therefore, -+ * should not be used. The problem is that structures with -+ * initializers have extra fields initialized to 0. It is _very_ -+ * desireable to have the unlock address entries for unsupported -+ * data widths automatically initialized - that means that -+ * MTD_UADDR_NOT_SUPPORTED must be 0 and the first entry here -+ * must go unused. -+ */ -+static const struct unlock_addr unlock_addrs[] = { -+ [MTD_UADDR_NOT_SUPPORTED] = { -+ .addr1 = 0xffff, -+ .addr2 = 0xffff -+ }, -+ -+ [MTD_UADDR_0x0555_0x02AA] = { -+ .addr1 = 0x0555, -+ .addr2 = 0x02aa -+ }, -+ -+ [MTD_UADDR_0x0555_0x0AAA] = { -+ .addr1 = 0x0555, -+ .addr2 = 0x0aaa -+ }, -+ -+ [MTD_UADDR_0x5555_0x2AAA] = { -+ .addr1 = 0x5555, -+ .addr2 = 0x2aaa -+ }, -+ -+ [MTD_UADDR_0x0AAA_0x0555] = { -+ .addr1 = 0x0AAA, -+ .addr2 = 0x0555 -+ }, -+ -+ [MTD_UADDR_DONT_CARE] = { -+ .addr1 = 0x0000, /* Doesn't matter which address */ -+ .addr2 = 0x0000 /* is used - must be last entry */ -+ } -+}; -+ - - struct amd_flash_info { - const __u16 mfr_id; - const __u16 dev_id; - const char *name; - const int DevSize; -- const int InterfaceDesc; - const int NumEraseRegions; - const int CmdSet; -+ const __u8 uaddr[4]; /* unlock addrs for 8, 16, 32, 64 */ - const ulong regions[4]; - }; - -@@ -145,760 +236,1214 @@ - #define SIZE_4MiB 22 - #define SIZE_8MiB 23 - -+ -+/* -+ * Please keep this list ordered by manufacturer! -+ * Fortunately, the list isn't searched often and so a -+ * slow, linear search isn't so bad. -+ */ - static const struct amd_flash_info jedec_table[] = { - { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F032B, -- name: "AMD AM29F032B", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,64) -- } -- }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV160DT, -- name: "AMD AM29LV160DT", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,31), -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F032B, -+ .name = "AMD AM29F032B", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,64) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV160DT, -+ .name = "AMD AM29LV160DT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,31), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV160DB, -- name: "AMD AM29LV160DB", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV160DB, -+ .name = "AMD AM29LV160DB", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x08000,1), - ERASEINFO(0x10000,31) - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVT160, -- name: "Toshiba TC58FVT160", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,31), -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV400BB, -+ .name = "AMD AM29LV400BB", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x10000,7) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV400BT, -+ .name = "AMD AM29LV400BT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,7), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVB160, -- name: "Toshiba TC58FVB160", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV800BB, -+ .name = "AMD AM29LV800BB", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x08000,1), -- ERASEINFO(0x10000,31) -+ ERASEINFO(0x10000,15), - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVB321, -- name: "Toshiba TC58FVB321", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x02000,8), -- ERASEINFO(0x10000,63) -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F800BB, -+ .name = "AMD AM29F800BB", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x10000,15), - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVT321, -- name: "Toshiba TC58FVT321", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x10000,63), -- ERASEINFO(0x02000,8) -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV800BT, -+ .name = "AMD AM29LV800BT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,15), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVB641, -- name: "Toshiba TC58FVB641", -- DevSize: SIZE_8MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x02000,8), -- ERASEINFO(0x10000,127) -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F800BT, -+ .name = "AMD AM29F800BT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,15), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_TOSHIBA, -- dev_id: TC58FVT641, -- name: "Toshiba TC58FVT641", -- DevSize: SIZE_8MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x10000,127), -- ERASEINFO(0x02000,8) -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F017D, -+ .name = "AMD AM29F017D", -+ .uaddr = { -+ [0] = MTD_UADDR_DONT_CARE /* x8 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,32), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F016D, -+ .name = "AMD AM29F016D", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,32), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F080, -+ .name = "AMD AM29F080", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,16), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29F040, -+ .name = "AMD AM29F040", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,8), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_AMD, -+ .dev_id = AM29LV040B, -+ .name = "AMD AM29LV040B", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,8), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT49BV512, -+ .name = "Atmel AT49BV512", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_64KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,1) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT29LV512, -+ .name = "Atmel AT29LV512", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_64KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x80,256), -+ ERASEINFO(0x80,256) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT49BV16X, -+ .name = "Atmel AT49BV16X", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x0AAA, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x0AAA /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x02000,8), -+ ERASEINFO(0x10000,31) - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV650UE, -- name: "Fujitsu MBM29LV650UE", -- DevSize: SIZE_8MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,128) -- } -- }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV320TE, -- name: "Fujitsu MBM29LV320TE", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x10000,63), -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT49BV16XT, -+ .name = "Atmel AT49BV16XT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x0AAA, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x0AAA /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x10000,31), - ERASEINFO(0x02000,8) - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV320BE, -- name: "Fujitsu MBM29LV320BE", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x02000,8), -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT49BV32X, -+ .name = "Atmel AT49BV32X", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x0AAA, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x0AAA /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x02000,8), - ERASEINFO(0x10000,63) - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV160TE, -- name: "Fujitsu MBM29LV160TE", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,31), -- ERASEINFO(0x08000,1), -- ERASEINFO(0x02000,2), -- ERASEINFO(0x04000,1) -+ .mfr_id = MANUFACTURER_ATMEL, -+ .dev_id = AT49BV32XT, -+ .name = "Atmel AT49BV32XT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x0AAA, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x0AAA /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x10000,63), -+ ERASEINFO(0x02000,8) - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV160BE, -- name: "Fujitsu MBM29LV160BE", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -- ERASEINFO(0x02000,2), -- ERASEINFO(0x08000,1), -- ERASEINFO(0x10000,31) -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29F040C, -+ .name = "Fujitsu MBM29F040C", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,8) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV650UE, -+ .name = "Fujitsu MBM29LV650UE", -+ .uaddr = { -+ [0] = MTD_UADDR_DONT_CARE /* x16 */ -+ }, -+ .DevSize = SIZE_8MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,128) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV320TE, -+ .name = "Fujitsu MBM29LV320TE", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x10000,63), -+ ERASEINFO(0x02000,8) - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV800BA, -- name: "Fujitsu MBM29LV800BA", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -- ERASEINFO(0x02000,2), -- ERASEINFO(0x08000,1), -- ERASEINFO(0x10000,15) -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV320BE, -+ .name = "Fujitsu MBM29LV320BE", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x02000,8), -+ ERASEINFO(0x10000,63) - } - }, { -- mfr_id: MANUFACTURER_FUJITSU, -- dev_id: MBM29LV800TA, -- name: "Fujitsu MBM29LV800TA", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,15), -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV160TE, -+ .name = "Fujitsu MBM29LV160TE", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,31), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV800BB, -- name: "AMD AM29LV800BB", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV160BE, -+ .name = "Fujitsu MBM29LV160BE", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x08000,1), -- ERASEINFO(0x10000,15), -+ ERASEINFO(0x10000,31) - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F800BB, -- name: "AMD AM29F800BB", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV800BA, -+ .name = "Fujitsu MBM29LV800BA", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x08000,1), -- ERASEINFO(0x10000,15), -+ ERASEINFO(0x10000,15) - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV800BT, -- name: "AMD AM29LV800BT", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,15), -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV800TA, -+ .name = "Fujitsu MBM29LV800TA", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,15), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F800BT, -- name: "AMD AM29F800BT", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,15), -- ERASEINFO(0x08000,1), -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV400BC, -+ .name = "Fujitsu MBM29LV400BC", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), -- ERASEINFO(0x04000,1) -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x10000,7) - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV800BB, -- name: "AMD AM29LV800BB", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,15), -+ .mfr_id = MANUFACTURER_FUJITSU, -+ .dev_id = MBM29LV400TC, -+ .name = "Fujitsu MBM29LV400TC", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,7), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F004B3B, -- name: "Intel 28F004B3B", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F004B3B, -+ .name = "Intel 28F004B3B", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 7), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F004B3T, -- name: "Intel 28F004B3T", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F004B3T, -+ .name = "Intel 28F004B3T", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 7), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F400B3B, -- name: "Intel 28F400B3B", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F400B3B, -+ .name = "Intel 28F400B3B", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 7), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F400B3T, -- name: "Intel 28F400B3T", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F400B3T, -+ .name = "Intel 28F400B3T", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 7), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F008B3B, -- name: "Intel 28F008B3B", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F008B3B, -+ .name = "Intel 28F008B3B", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 15), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F008B3T, -- name: "Intel 28F008B3T", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F008B3T, -+ .name = "Intel 28F008B3T", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 15), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F008S5, -- name: "Intel 28F008S5", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_INTEL_EXT, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,16), -- } -- }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F016S5, -- name: "Intel 28F016S5", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_INTEL_EXT, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,32), -- } -- }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F008SA, -- name: "Intel 28F008SA", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 1, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F008S5, -+ .name = "Intel 28F008S5", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_INTEL_EXT, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,16), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F016S5, -+ .name = "Intel 28F016S5", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_INTEL_EXT, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,32), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F008SA, -+ .name = "Intel 28F008SA", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 1, -+ .regions = { - ERASEINFO(0x10000, 16), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F800B3B, -- name: "Intel 28F800B3B", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F800B3B, -+ .name = "Intel 28F800B3B", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 15), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F800B3T, -- name: "Intel 28F800B3T", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F800B3T, -+ .name = "Intel 28F800B3T", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 15), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F016B3B, -- name: "Intel 28F016B3B", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F016B3B, -+ .name = "Intel 28F016B3B", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 31), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F016S3, -- name: "Intel I28F016S3", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 1, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F016S3, -+ .name = "Intel I28F016S3", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 1, -+ .regions = { - ERASEINFO(0x10000, 32), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F016B3T, -- name: "Intel 28F016B3T", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F016B3T, -+ .name = "Intel 28F016B3T", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 31), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F160B3B, -- name: "Intel 28F160B3B", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F160B3B, -+ .name = "Intel 28F160B3B", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 31), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F160B3T, -- name: "Intel 28F160B3T", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F160B3T, -+ .name = "Intel 28F160B3T", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 31), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F320B3B, -- name: "Intel 28F320B3B", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F320B3B, -+ .name = "Intel 28F320B3B", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 63), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F320B3T, -- name: "Intel 28F320B3T", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F320B3T, -+ .name = "Intel 28F320B3T", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 63), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F640B3B, -- name: "Intel 28F640B3B", -- DevSize: SIZE_8MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F640B3B, -+ .name = "Intel 28F640B3B", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_8MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x02000, 8), - ERASEINFO(0x10000, 127), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I28F640B3T, -- name: "Intel 28F640B3T", -- DevSize: SIZE_8MiB, -- CmdSet: P_ID_INTEL_STD, -- NumEraseRegions: 2, -- regions: { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I28F640B3T, -+ .name = "Intel 28F640B3T", -+ .uaddr = { -+ [1] = MTD_UADDR_UNNECESSARY, /* x16 */ -+ }, -+ .DevSize = SIZE_8MiB, -+ .CmdSet = P_ID_INTEL_STD, -+ .NumEraseRegions= 2, -+ .regions = { - ERASEINFO(0x10000, 127), - ERASEINFO(0x02000, 8), - } - }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I82802AB, -- name: "Intel 82802AB", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_INTEL_EXT, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,8), -- } -- }, { -- mfr_id: MANUFACTURER_INTEL, -- dev_id: I82802AC, -- name: "Intel 82802AC", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_INTEL_EXT, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,16), -- } -- }, { -- mfr_id: MANUFACTURER_ST, -- dev_id: M29W800T, -- name: "ST M29W800T", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,15), -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I82802AB, -+ .name = "Intel 82802AB", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_INTEL_EXT, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,8), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_INTEL, -+ .dev_id = I82802AC, -+ .name = "Intel 82802AC", -+ .uaddr = { -+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_INTEL_EXT, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,16), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_MACRONIX, -+ .dev_id = MX29LV160T, -+ .name = "MXIC MX29LV160T", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,31), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_ST, -- dev_id: M29W160DT, -- name: "ST M29W160DT", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,31), -- ERASEINFO(0x08000,1), -- ERASEINFO(0x02000,2), -- ERASEINFO(0x04000,1) -- } -- }, { -- mfr_id: MANUFACTURER_ST, -- dev_id: M29W160DB, -- name: "ST M29W160DB", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -+ .mfr_id = MANUFACTURER_MACRONIX, -+ .dev_id = MX29LV160B, -+ .name = "MXIC MX29LV160B", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x08000,1), - ERASEINFO(0x10000,31) - } - }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT49BV512, -- name: "Atmel AT49BV512", -- DevSize: SIZE_64KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,1) -- } -- }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT29LV512, -- name: "Atmel AT29LV512", -- DevSize: SIZE_64KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: { -- ERASEINFO(0x80,256), -- ERASEINFO(0x80,256) -- } -- }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT49BV16X, -- name: "Atmel AT49BV16X", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x02000,8), -- ERASEINFO(0x10000,31) -+ .mfr_id = MANUFACTURER_MACRONIX, -+ .dev_id = MX29F016, -+ .name = "Macronix MX29F016", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,32), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_MACRONIX, -+ .dev_id = MX29F004T, -+ .name = "Macronix MX29F004T", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,7), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x04000,1), - } - }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT49BV16XT, -- name: "Atmel AT49BV16XT", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x10000,31), -- ERASEINFO(0x02000,8) -+ .mfr_id = MANUFACTURER_MACRONIX, -+ .dev_id = MX29F004B, -+ .name = "Macronix MX29F004B", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x10000,7), - } - }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT49BV32X, -- name: "Atmel AT49BV32X", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x02000,8), -- ERASEINFO(0x10000,63) -+ .mfr_id = MANUFACTURER_PMC, -+ .dev_id = PM49FL002, -+ .name = "PMC Pm49FL002", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_256KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO( 0x01000, 64 ) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_PMC, -+ .dev_id = PM49FL004, -+ .name = "PMC Pm49FL004", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO( 0x01000, 128 ) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_PMC, -+ .dev_id = PM49FL008, -+ .name = "PMC Pm49FL008", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO( 0x01000, 256 ) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST39LF512, -+ .name = "SST 39LF512", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_64KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,16), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST39LF010, -+ .name = "SST 39LF010", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_128KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,32), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST39LF020, -+ .name = "SST 39LF020", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_256KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,64), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST39LF040, -+ .name = "SST 39LF040", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,128), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST39SF010A, -+ .name = "SST 39SF010A", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_128KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,32), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST39SF020A, -+ .name = "SST 39SF020A", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_256KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,64), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST49LF004B, -+ .name = "SST 49LF004B", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,128), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST49LF030A, -+ .name = "SST 49LF030A", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,96), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST49LF040A, -+ .name = "SST 49LF040A", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,128), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_SST, -+ .dev_id = SST49LF080A, -+ .name = "SST 49LF080A", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x01000,256), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */ -+ .dev_id = M29W800DT, -+ .name = "ST M29W800DT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA, /* x8 */ -+ [1] = MTD_UADDR_0x5555_0x2AAA /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,15), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_ATMEL, -- dev_id: AT49BV32XT, -- name: "Atmel AT49BV32XT", -- DevSize: SIZE_4MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 2, -- regions: {ERASEINFO(0x10000,63), -- ERASEINFO(0x02000,8) -+ .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */ -+ .dev_id = M29W800DB, -+ .name = "ST M29W800DB", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA, /* x8 */ -+ [1] = MTD_UADDR_0x5555_0x2AAA /* x16 */ -+ }, -+ .DevSize = SIZE_1MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), -+ ERASEINFO(0x02000,2), -+ ERASEINFO(0x08000,1), -+ ERASEINFO(0x10000,15) - } - }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F017D, -- name: "AMD AM29F017D", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,32), -- } -- }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F016, -- name: "AMD AM29F016", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,32), -- } -- }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F080, -- name: "AMD AM29F080", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,16), -- } -- }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29F040, -- name: "AMD AM29F040", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,8), -- } -- }, { -- mfr_id: MANUFACTURER_AMD, -- dev_id: AM29LV040B, -- name: "AMD AM29LV040B", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,8), -- } -- }, { -- mfr_id: MANUFACTURER_ST, -- dev_id: M29W040B, -- name: "ST M29W040B", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,8), -- } -- }, { -- mfr_id: MANUFACTURER_MACRONIX, -- dev_id: MX29LV160T, -- name: "MXIC MX29LV160T", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,31), -+ .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */ -+ .dev_id = M29W160DT, -+ .name = "ST M29W160DT", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,31), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_MACRONIX, -- dev_id: MX29LV160B, -- name: "MXIC MX29LV160B", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -+ .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */ -+ .dev_id = M29W160DB, -+ .name = "ST M29W160DB", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x08000,1), - ERASEINFO(0x10000,31) - } - }, { -- mfr_id: MANUFACTURER_MACRONIX, -- dev_id: MX29F016, -- name: "Macronix MX29F016", -- DevSize: SIZE_2MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x10000,32), -- } -- }, { -- mfr_id: MANUFACTURER_MACRONIX, -- dev_id: MX29F004T, -- name: "Macronix MX29F004T", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x10000,7), -+ .mfr_id = MANUFACTURER_ST, -+ .dev_id = M29W040B, -+ .name = "ST M29W040B", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ -+ }, -+ .DevSize = SIZE_512KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 1, -+ .regions = { -+ ERASEINFO(0x10000,8), -+ } -+ }, { -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVT160, -+ .name = "Toshiba TC58FVT160", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000,31), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), -- ERASEINFO(0x04000,1), -+ ERASEINFO(0x04000,1) - } - }, { -- mfr_id: MANUFACTURER_MACRONIX, -- dev_id: MX29F004B, -- name: "Macronix MX29F004B", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 4, -- regions: {ERASEINFO(0x04000,1), -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVB160, -+ .name = "Toshiba TC58FVB160", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */ -+ }, -+ .DevSize = SIZE_2MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x04000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x08000,1), -- ERASEINFO(0x10000,7), -+ ERASEINFO(0x10000,31) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVB321, -+ .name = "Toshiba TC58FVB321", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x02000,8), -+ ERASEINFO(0x10000,63) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVT321, -+ .name = "Toshiba TC58FVT321", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */ -+ }, -+ .DevSize = SIZE_4MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x10000,63), -+ ERASEINFO(0x02000,8) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVB641, -+ .name = "Toshiba TC58FVB641", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_8MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x02000,8), -+ ERASEINFO(0x10000,127) -+ } -+ }, { -+ .mfr_id = MANUFACTURER_TOSHIBA, -+ .dev_id = TC58FVT641, -+ .name = "Toshiba TC58FVT641", -+ .uaddr = { -+ [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */ -+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */ -+ }, -+ .DevSize = SIZE_8MiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 2, -+ .regions = { -+ ERASEINFO(0x10000,127), -+ ERASEINFO(0x02000,8) - } - }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST39LF512, -- name: "SST 39LF512", -- DevSize: SIZE_64KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,16), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST39LF010, -- name: "SST 39LF010", -- DevSize: SIZE_128KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,32), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST39LF020, -- name: "SST 39LF020", -- DevSize: SIZE_256KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,64), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST39LF040, -- name: "SST 39LF040", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,128), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST39SF010A, -- name: "SST 39SF010A", -- DevSize: SIZE_128KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,32), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST39SF020A, -- name: "SST 39SF020A", -- DevSize: SIZE_256KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,64), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST49LF030A, -- name: "SST 49LF030A", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,96), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST49LF040A, -- name: "SST 49LF040A", -- DevSize: SIZE_512KiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,128), -- } -- }, { -- mfr_id: MANUFACTURER_SST, -- dev_id: SST49LF080A, -- name: "SST 49LF080A", -- DevSize: SIZE_1MiB, -- CmdSet: P_ID_AMD_STD, -- NumEraseRegions: 1, -- regions: {ERASEINFO(0x01000,256), -+ .mfr_id = MANUFACTURER_WINBOND, -+ .dev_id = W49V002A, -+ .name = "Winbond W49V002A", -+ .uaddr = { -+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ -+ }, -+ .DevSize = SIZE_256KiB, -+ .CmdSet = P_ID_AMD_STD, -+ .NumEraseRegions= 4, -+ .regions = { -+ ERASEINFO(0x10000, 3), -+ ERASEINFO(0x08000, 1), -+ ERASEINFO(0x02000, 2), -+ ERASEINFO(0x04000, 1), - } - } - }; -@@ -907,7 +1452,7 @@ - static int cfi_jedec_setup(struct cfi_private *p_cfi, int index); - - static int jedec_probe_chip(struct map_info *map, __u32 base, -- struct flchip *chips, struct cfi_private *cfi); -+ unsigned long *chip_map, struct cfi_private *cfi); - - struct mtd_info *jedec_probe(struct map_info *map); - -@@ -944,11 +1489,43 @@ - * this should be safe. - */ - cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); -+ /* FIXME - should have reset delay before continuing */ -+} - -+ -+static inline __u8 finfo_uaddr(const struct amd_flash_info *finfo, int device_type) -+{ -+ int uaddr_idx; -+ __u8 uaddr = MTD_UADDR_NOT_SUPPORTED; -+ -+ switch ( device_type ) { -+ case CFI_DEVICETYPE_X8: uaddr_idx = 0; break; -+ case CFI_DEVICETYPE_X16: uaddr_idx = 1; break; -+ case CFI_DEVICETYPE_X32: uaddr_idx = 2; break; -+ default: -+ printk(KERN_NOTICE "MTD: %s(): unknown device_type %d\n", -+ __func__, device_type); -+ goto uaddr_done; -+ } -+ -+ uaddr = finfo->uaddr[uaddr_idx]; -+ -+ if (uaddr != MTD_UADDR_NOT_SUPPORTED ) { -+ /* ASSERT("The unlock addresses for non-8-bit mode -+ are bollocks. We don't really need an array."); */ -+ uaddr = finfo->uaddr[0]; -+ } -+ -+ uaddr_done: -+ return uaddr; - } -+ -+ - static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) - { - int i,num_erase_regions; -+ unsigned long mask; -+ __u8 uaddr; - - printk("Found: %s\n",jedec_table[index].name); - -@@ -971,41 +1548,170 @@ - p_cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i]; - } - p_cfi->cmdset_priv = 0; -+ -+ /* This may be redundant for some cases, but it doesn't hurt */ -+ p_cfi->mfr = jedec_table[index].mfr_id; -+ p_cfi->id = jedec_table[index].dev_id; -+ -+ uaddr = finfo_uaddr(&jedec_table[index], p_cfi->device_type); -+ if ( uaddr == MTD_UADDR_NOT_SUPPORTED ) { -+ kfree( p_cfi->cfiq ); -+ return 0; -+ } -+ -+ /* Mask out address bits which are smaller than the device type */ -+ mask = ~(p_cfi->device_type-1); -+ p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 & mask; -+ p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 & mask; -+ - return 1; /* ok */ - } - --static int jedec_probe_chip(struct map_info *map, __u32 base, -- struct flchip *chips, struct cfi_private *cfi) -+ -+/* -+ * There is a BIG problem properly ID'ing the JEDEC devic and guaranteeing -+ * the mapped address, unlock addresses, and proper chip ID. This function -+ * attempts to minimize errors. It is doubtfull that this probe will ever -+ * be perfect - consequently there should be some module parameters that -+ * could be manually specified to force the chip info. -+ */ -+static inline int jedec_match( __u32 base, -+ struct map_info *map, -+ struct cfi_private *cfi, -+ const struct amd_flash_info *finfo ) - { -- int i; -- int unlockpass = 0; -+ int rc = 0; /* failure until all tests pass */ -+ u32 mfr, id; -+ __u8 uaddr; -+ unsigned long mask; - -- if (!cfi->numchips) { -+ /* -+ * The IDs must match. For X16 and X32 devices operating in -+ * a lower width ( X8 or X16 ), the device ID's are usually just -+ * the lower byte(s) of the larger device ID for wider mode. If -+ * a part is found that doesn't fit this assumption (device id for -+ * smaller width mode is completely unrealated to full-width mode) -+ * then the jedec_table[] will have to be augmented with the IDs -+ * for different widths. -+ */ - switch (cfi->device_type) { - case CFI_DEVICETYPE_X8: -- cfi->addr_unlock1 = 0x555; -- cfi->addr_unlock2 = 0x2aa; -+ mfr = (__u8)finfo->mfr_id; -+ id = (__u8)finfo->dev_id; - break; - case CFI_DEVICETYPE_X16: -- cfi->addr_unlock1 = 0xaaa; -- if (map->buswidth == cfi->interleave) { -- /* X16 chip(s) in X8 mode */ -- cfi->addr_unlock2 = 0x555; -- } else { -- cfi->addr_unlock2 = 0x554; -- } -+ mfr = (__u16)finfo->mfr_id; -+ id = (__u16)finfo->dev_id; - break; - case CFI_DEVICETYPE_X32: -- cfi->addr_unlock1 = 0x1555; -- cfi->addr_unlock2 = 0xaaa; -+ mfr = (__u16)finfo->mfr_id; -+ id = (__u32)finfo->dev_id; - break; - default: -- printk(KERN_NOTICE "Eep. Unknown jedec_probe device type %d\n", cfi->device_type); -- return 0; -+ printk(KERN_WARNING -+ "MTD %s(): Unsupported device type %d\n", -+ __func__, cfi->device_type); -+ goto match_done; -+ } -+ if ( cfi->mfr != mfr || cfi->id != id ) { -+ goto match_done; -+ } -+ -+ /* the part size must fit in the memory window */ -+ DEBUG( MTD_DEBUG_LEVEL3, -+ "MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n", -+ __func__, base, 1 << finfo->DevSize, base + (1 << finfo->DevSize) ); -+ if ( base + cfi->interleave * ( 1 << finfo->DevSize ) > map->size ) { -+ DEBUG( MTD_DEBUG_LEVEL3, -+ "MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n", -+ __func__, finfo->mfr_id, finfo->dev_id, -+ 1 << finfo->DevSize ); -+ goto match_done; -+ } -+ -+ uaddr = finfo_uaddr(finfo, cfi->device_type); -+ if ( uaddr == MTD_UADDR_NOT_SUPPORTED ) { -+ goto match_done; -+ } -+ -+ mask = ~(cfi->device_type-1); -+ -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n", -+ __func__, cfi->addr_unlock1, cfi->addr_unlock2 ); -+ if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr -+ && ( (unlock_addrs[uaddr].addr1 & mask) != cfi->addr_unlock1 || -+ (unlock_addrs[uaddr].addr2 & mask) != cfi->addr_unlock2 ) ) { -+ DEBUG( MTD_DEBUG_LEVEL3, -+ "MTD %s(): 0x%.4x 0x%.4x did not match\n", -+ __func__, -+ unlock_addrs[uaddr].addr1 & mask, -+ unlock_addrs[uaddr].addr2 & mask); -+ goto match_done; - } -+ -+ /* -+ * Make sure the ID's dissappear when the device is taken out of -+ * ID mode. The only time this should fail when it should succeed -+ * is when the ID's are written as data to the same -+ * addresses. For this rare and unfortunate case the chip -+ * cannot be probed correctly. -+ * FIXME - write a driver that takes all of the chip info as -+ * module parameters, doesn't probe but forces a load. -+ */ -+ DEBUG( MTD_DEBUG_LEVEL3, -+ "MTD %s(): check ID's disappear when not in ID mode\n", -+ __func__ ); -+ jedec_reset( base, map, cfi ); -+ mfr = jedec_read_mfr( map, base, cfi ); -+ id = jedec_read_id( map, base, cfi ); -+ if ( mfr == cfi->mfr && id == cfi->id ) { -+ DEBUG( MTD_DEBUG_LEVEL3, -+ "MTD %s(): ID 0x%.2x:0x%.2x did not change after reset:\n" -+ "You might need to manually specify JEDEC parameters.\n", -+ __func__, cfi->mfr, cfi->id ); -+ goto match_done; -+ } -+ -+ /* all tests passed - mark as success */ -+ rc = 1; -+ -+ /* -+ * Put the device back in ID mode - only need to do this if we -+ * were truly frobbing a real device. -+ */ -+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): return to ID mode\n", __func__ ); -+ if(cfi->addr_unlock1) { -+ cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL); - } -+ cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ /* FIXME - should have a delay before continuing */ -+ -+ match_done: -+ return rc; -+} -+ -+ -+static int jedec_probe_chip(struct map_info *map, __u32 base, -+ unsigned long *chip_map, struct cfi_private *cfi) -+{ -+ int i; -+ enum uaddr uaddr_idx = MTD_UADDR_NOT_SUPPORTED; - - retry: -+ if (!cfi->numchips) { -+ unsigned long mask = ~(cfi->device_type-1); -+ -+ uaddr_idx++; -+ -+ if (MTD_UADDR_UNNECESSARY == uaddr_idx) -+ return 0; -+ -+ /* Mask out address bits which are smaller than the device type */ -+ cfi->addr_unlock1 = unlock_addrs[uaddr_idx].addr1 & mask; -+ cfi->addr_unlock2 = unlock_addrs[uaddr_idx].addr2 & mask; -+ } -+ - /* Make certain we aren't probing past the end of map */ - if (base >= map->size) { - printk(KERN_NOTICE -@@ -1038,6 +1744,7 @@ - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL); - } - cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); -+ /* FIXME - should have a delay before continuing */ - - if (!cfi->numchips) { - /* This is the first time we're called. Set up the CFI -@@ -1045,26 +1752,21 @@ - - cfi->mfr = jedec_read_mfr(map, base, cfi); - cfi->id = jedec_read_id(map, base, cfi); -- printk(KERN_INFO "Search for id:(%02x %02x) interleave(%d) type(%d)\n", -+ DEBUG(MTD_DEBUG_LEVEL3, -+ "Search for id:(%02x %02x) interleave(%d) type(%d)\n", - cfi->mfr, cfi->id, cfi->interleave, cfi->device_type); - for (i=0; imfr == jedec_table[i].mfr_id && -- cfi->id == jedec_table[i].dev_id) { -+ if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) { -+ DEBUG( MTD_DEBUG_LEVEL3, -+ "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n", -+ __func__, cfi->mfr, cfi->id, -+ cfi->addr_unlock1, cfi->addr_unlock2 ); - if (!cfi_jedec_setup(cfi, i)) - return 0; - goto ok_out; - } - } -- switch(unlockpass++) { -- case 0: -- cfi->addr_unlock1 |= cfi->addr_unlock1 << 4; -- cfi->addr_unlock2 |= cfi->addr_unlock2 << 4; -- goto retry; -- case 1: -- cfi->addr_unlock1 = cfi->addr_unlock2 = 0; - goto retry; -- } -- return 0; - } else { - __u16 mfr; - __u16 id; -@@ -1081,21 +1783,24 @@ - } - } - -- /* Check each previous chip to see if it's an alias */ -- for (i=0; inumchips; i++) { -- /* This chip should be in read mode if it's one -- we've already touched. */ -- if (jedec_read_mfr(map, chips[i].start, cfi) == cfi->mfr && -- jedec_read_id(map, chips[i].start, cfi) == cfi->id) { -+ /* Check each previous chip locations to see if it's an alias */ -+ for (i=0; i < (base >> cfi->chipshift); i++) { -+ unsigned long start; -+ if(!test_bit(i, chip_map)) { -+ continue; /* Skip location; no valid chip at this address */ -+ } -+ start = i << cfi->chipshift; -+ if (jedec_read_mfr(map, start, cfi) == cfi->mfr && -+ jedec_read_id(map, start, cfi) == cfi->id) { - /* Eep. This chip also looks like it's in autoselect mode. - Is it an alias for the new one? */ -- jedec_reset(chips[i].start, map, cfi); -+ jedec_reset(start, map, cfi); - - /* If the device IDs go away, it's an alias */ - if (jedec_read_mfr(map, base, cfi) != cfi->mfr || - jedec_read_id(map, base, cfi) != cfi->id) { - printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", -- map->name, base, chips[i].start); -+ map->name, base, start); - return 0; - } - -@@ -1107,7 +1812,7 @@ - if (jedec_read_mfr(map, base, cfi) == cfi->mfr && - jedec_read_id(map, base, cfi) == cfi->id) { - printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", -- map->name, base, chips[i].start); -+ map->name, base, start); - return 0; - } - } -@@ -1115,13 +1820,7 @@ - - /* OK, if we got to here, then none of the previous chips appear to - be aliases for the current one. */ -- if (cfi->numchips == MAX_CFI_CHIPS) { -- printk(KERN_WARNING"%s: Too many flash chips detected. Increase MAX_CFI_CHIPS from %d.\n", map->name, MAX_CFI_CHIPS); -- /* Doesn't matter about resetting it to Read Mode - we're not going to talk to it anyway */ -- return -1; -- } -- chips[cfi->numchips].start = base; -- chips[cfi->numchips].state = FL_READY; -+ set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */ - cfi->numchips++; - - ok_out: -@@ -1136,8 +1835,8 @@ - } - - static struct chip_probe jedec_chip_probe = { -- name: "JEDEC", -- probe_chip: jedec_probe_chip -+ .name = "JEDEC", -+ .probe_chip = jedec_probe_chip - }; - - struct mtd_info *jedec_probe(struct map_info *map) -@@ -1150,9 +1849,9 @@ - } - - static struct mtd_chip_driver jedec_chipdrv = { -- probe: jedec_probe, -- name: "jedec_probe", -- module: THIS_MODULE -+ .probe = jedec_probe, -+ .name = "jedec_probe", -+ .module = THIS_MODULE - }; - - int __init jedec_probe_init(void) -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/map_absent.c linux/drivers/mtd/chips/map_absent.c ---- linux-mips-2.4.27/drivers/mtd/chips/map_absent.c 2001-11-05 21:15:51.000000000 +0100 -+++ linux/drivers/mtd/chips/map_absent.c 2004-11-19 10:25:11.776218488 +0100 -@@ -1,7 +1,7 @@ - /* - * Common code to handle absent "placeholder" devices - * Copyright 2001 Resilience Corporation -- * $Id$ -+ * $Id$ - * - * This map driver is used to allocate "placeholder" MTD - * devices on systems that have socketed/removable media. -@@ -23,9 +23,10 @@ - #include - #include - #include -- -+#include -+#include - #include -- -+#include - - static int map_absent_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); - static int map_absent_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -@@ -36,10 +37,10 @@ - - - static struct mtd_chip_driver map_absent_chipdrv = { -- probe: map_absent_probe, -- destroy: map_absent_destroy, -- name: "map_absent", -- module: THIS_MODULE -+ .probe = map_absent_probe, -+ .destroy = map_absent_destroy, -+ .name = "map_absent", -+ .module = THIS_MODULE - }; - - static struct mtd_info *map_absent_probe(struct map_info *map) -@@ -65,7 +66,7 @@ - mtd->flags = 0; - mtd->erasesize = PAGE_SIZE; - -- MOD_INC_USE_COUNT; -+ __module_get(THIS_MODULE); - return mtd; - } - -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/map_ram.c linux/drivers/mtd/chips/map_ram.c ---- linux-mips-2.4.27/drivers/mtd/chips/map_ram.c 2001-11-05 21:15:51.000000000 +0100 -+++ linux/drivers/mtd/chips/map_ram.c 2004-11-19 10:25:11.777218336 +0100 -@@ -1,7 +1,7 @@ - /* - * Common code to handle map devices which are simple RAM - * (C) 2000 Red Hat. GPL'd. -- * $Id$ -+ * $Id$ - */ - - #include -@@ -11,8 +11,10 @@ - #include - #include - #include -- -+#include -+#include - #include -+#include - - - static int mapram_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); -@@ -23,9 +25,9 @@ - - - static struct mtd_chip_driver mapram_chipdrv = { -- probe: map_ram_probe, -- name: "map_ram", -- module: THIS_MODULE -+ .probe = map_ram_probe, -+ .name = "map_ram", -+ .module = THIS_MODULE - }; - - static struct mtd_info *map_ram_probe(struct map_info *map) -@@ -34,21 +36,21 @@ - - /* Check the first byte is RAM */ - #if 0 -- map->write8(map, 0x55, 0); -- if (map->read8(map, 0) != 0x55) -+ map_write8(map, 0x55, 0); -+ if (map_read8(map, 0) != 0x55) - return NULL; - -- map->write8(map, 0xAA, 0); -- if (map->read8(map, 0) != 0xAA) -+ map_write8(map, 0xAA, 0); -+ if (map_read8(map, 0) != 0xAA) - return NULL; - - /* Check the last byte is RAM */ -- map->write8(map, 0x55, map->size-1); -- if (map->read8(map, map->size-1) != 0x55) -+ map_write8(map, 0x55, map->size-1); -+ if (map_read8(map, map->size-1) != 0x55) - return NULL; - -- map->write8(map, 0xAA, map->size-1); -- if (map->read8(map, map->size-1) != 0xAA) -+ map_write8(map, 0xAA, map->size-1); -+ if (map_read8(map, map->size-1) != 0xAA) - return NULL; - #endif - /* OK. It seems to be RAM. */ -@@ -74,7 +76,7 @@ - while(mtd->size & (mtd->erasesize - 1)) - mtd->erasesize >>= 1; - -- MOD_INC_USE_COUNT; -+ __module_get(THIS_MODULE); - return mtd; - } - -@@ -83,7 +85,7 @@ - { - struct map_info *map = (struct map_info *)mtd->priv; - -- map->copy_from(map, buf, from, len); -+ map_copy_from(map, buf, from, len); - *retlen = len; - return 0; - } -@@ -92,7 +94,7 @@ - { - struct map_info *map = (struct map_info *)mtd->priv; - -- map->copy_to(map, to, buf, len); -+ map_copy_to(map, to, buf, len); - *retlen = len; - return 0; - } -@@ -105,7 +107,7 @@ - unsigned long i; - - for (i=0; ilen; i++) -- map->write8(map, 0xFF, instr->addr + i); -+ map_write8(map, 0xFF, instr->addr + i); - - if (instr->callback) - instr->callback(instr); -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/map_rom.c linux/drivers/mtd/chips/map_rom.c ---- linux-mips-2.4.27/drivers/mtd/chips/map_rom.c 2001-11-05 21:15:52.000000000 +0100 -+++ linux/drivers/mtd/chips/map_rom.c 2004-11-19 10:25:11.778218184 +0100 -@@ -1,7 +1,7 @@ - /* - * Common code to handle map devices which are simple ROM - * (C) 2000 Red Hat. GPL'd. -- * $Id$ -+ * $Id$ - */ - - #include -@@ -12,8 +12,10 @@ - #include - #include - #include -- -+#include -+#include - #include -+#include - - static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); - static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -@@ -21,9 +23,9 @@ - struct mtd_info *map_rom_probe(struct map_info *map); - - static struct mtd_chip_driver maprom_chipdrv = { -- probe: map_rom_probe, -- name: "map_rom", -- module: THIS_MODULE -+ .probe = map_rom_probe, -+ .name = "map_rom", -+ .module = THIS_MODULE - }; - - struct mtd_info *map_rom_probe(struct map_info *map) -@@ -49,7 +51,7 @@ - while(mtd->size & (mtd->erasesize - 1)) - mtd->erasesize >>= 1; - -- MOD_INC_USE_COUNT; -+ __module_get(THIS_MODULE); - return mtd; - } - -@@ -58,7 +60,7 @@ - { - struct map_info *map = (struct map_info *)mtd->priv; - -- map->copy_from(map, buf, from, len); -+ map_copy_from(map, buf, from, len); - *retlen = len; - return 0; - } -diff -Nurb linux-mips-2.4.27/drivers/mtd/chips/sharp.c linux/drivers/mtd/chips/sharp.c ---- linux-mips-2.4.27/drivers/mtd/chips/sharp.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/chips/sharp.c 2004-11-19 10:25:11.792216056 +0100 -@@ -4,7 +4,7 @@ - * Copyright 2000,2001 David A. Schleef - * 2000,2001 Lineo, Inc. - * -- * $Id$ -+ * $Id$ - * - * Devices supported: - * LH28F016SCT Symmetrical block flash memory, 2Mx8 -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -98,10 +99,10 @@ - static void sharp_destroy(struct mtd_info *mtd); - - static struct mtd_chip_driver sharp_chipdrv = { -- probe: sharp_probe, -- destroy: sharp_destroy, -- name: "sharp", -- module: THIS_MODULE -+ .probe = sharp_probe, -+ .destroy = sharp_destroy, -+ .name = "sharp", -+ .module = THIS_MODULE - }; - - -@@ -116,8 +117,10 @@ - return NULL; - - sharp = kmalloc(sizeof(*sharp), GFP_KERNEL); -- if(!sharp) -+ if(!sharp) { -+ kfree(mtd); - return NULL; -+ } - - memset(mtd, 0, sizeof(*mtd)); - -@@ -163,12 +166,12 @@ - u32 read0, read4; - int width = 4; - -- tmp = map->read32(map, base+0); -+ tmp = map_read32(map, base+0); - -- map->write32(map, CMD_READ_ID, base+0); -+ map_write32(map, CMD_READ_ID, base+0); - -- read0=map->read32(map, base+0); -- read4=map->read32(map, base+4); -+ read0=map_read32(map, base+0); -+ read4=map_read32(map, base+4); - if(read0 == 0x89898989){ - printk("Looks like sharp flash\n"); - switch(read4){ -@@ -196,10 +199,10 @@ - printk("Sort-of looks like sharp flash, 0x%08x 0x%08x\n", - read0,read4); - } -- }else if((map->read32(map, base+0) == CMD_READ_ID)){ -+ }else if((map_read32(map, base+0) == CMD_READ_ID)){ - /* RAM, probably */ - printk("Looks like RAM\n"); -- map->write32(map, tmp, base+0); -+ map_write32(map, tmp, base+0); - }else{ - printk("Doesn't look like sharp flash, 0x%08x 0x%08x\n", - read0,read4); -@@ -221,10 +224,10 @@ - - switch(chip->state){ - case FL_READY: -- map->write32(map,CMD_READ_STATUS,adr); -+ map_write32(map,CMD_READ_STATUS,adr); - chip->state = FL_STATUS; - case FL_STATUS: -- status = map->read32(map,adr); -+ status = map_read32(map,adr); - //printk("status=%08x\n",status); - - udelay(100); -@@ -252,7 +255,7 @@ - goto retry; - } - -- map->write32(map,CMD_RESET, adr); -+ map_write32(map,CMD_RESET, adr); - - chip->state = FL_READY; - -@@ -293,7 +296,7 @@ - if(ret<0) - break; - -- map->copy_from(map,buf,ofs,thislen); -+ map_copy_from(map,buf,ofs,thislen); - - sharp_release(&sharp->chips[chipnum]); - -@@ -354,17 +357,17 @@ - ret = sharp_wait(map,chip); - - for(try=0;try<10;try++){ -- map->write32(map,CMD_BYTE_WRITE,adr); -+ map_write32(map,CMD_BYTE_WRITE,adr); - /* cpu_to_le32 -> hack to fix the writel be->le conversion */ -- map->write32(map,cpu_to_le32(datum),adr); -+ map_write32(map,cpu_to_le32(datum),adr); - - chip->state = FL_WRITING; - - timeo = jiffies + (HZ/2); - -- map->write32(map,CMD_READ_STATUS,adr); -+ map_write32(map,CMD_READ_STATUS,adr); - for(i=0;i<100;i++){ -- status = map->read32(map,adr); -+ status = map_read32(map,adr); - if((status & SR_READY)==SR_READY) - break; - } -@@ -377,9 +380,9 @@ - - printk("sharp: error writing byte at addr=%08lx status=%08x\n",adr,status); - -- map->write32(map,CMD_CLEAR_STATUS,adr); -+ map_write32(map,CMD_CLEAR_STATUS,adr); - } -- map->write32(map,CMD_RESET,adr); -+ map_write32(map,CMD_RESET,adr); - chip->state = FL_READY; - - wake_up(&chip->wq); -@@ -436,14 +439,14 @@ - int status; - DECLARE_WAITQUEUE(wait, current); - -- map->write32(map,CMD_READ_STATUS,adr); -- status = map->read32(map,adr); -+ map_write32(map,CMD_READ_STATUS,adr); -+ status = map_read32(map,adr); - - timeo = jiffies + HZ; - - while(time_before(jiffies, timeo)){ -- map->write32(map,CMD_READ_STATUS,adr); -- status = map->read32(map,adr); -+ map_write32(map,CMD_READ_STATUS,adr); -+ status = map_read32(map,adr); - if((status & SR_READY)==SR_READY){ - ret = 0; - goto out; -@@ -485,26 +488,26 @@ - sharp_unlock_oneblock(map,chip,adr); - #endif - -- map->write32(map,CMD_BLOCK_ERASE_1,adr); -- map->write32(map,CMD_BLOCK_ERASE_2,adr); -+ map_write32(map,CMD_BLOCK_ERASE_1,adr); -+ map_write32(map,CMD_BLOCK_ERASE_2,adr); - - chip->state = FL_ERASING; - - ret = sharp_do_wait_for_ready(map,chip,adr); - if(ret<0)return ret; - -- map->write32(map,CMD_READ_STATUS,adr); -- status = map->read32(map,adr); -+ map_write32(map,CMD_READ_STATUS,adr); -+ status = map_read32(map,adr); - - if(!(status&SR_ERRORS)){ -- map->write32(map,CMD_RESET,adr); -+ map_write32(map,CMD_RESET,adr); - chip->state = FL_READY; - //spin_unlock_bh(chip->mutex); - return 0; - } - - printk("sharp: error erasing block at addr=%08lx status=%08x\n",adr,status); -- map->write32(map,CMD_CLEAR_STATUS,adr); -+ map_write32(map,CMD_CLEAR_STATUS,adr); - - //spin_unlock_bh(chip->mutex); - -@@ -518,17 +521,17 @@ - int i; - int status; - -- map->write32(map,CMD_CLEAR_BLOCK_LOCKS_1,adr); -- map->write32(map,CMD_CLEAR_BLOCK_LOCKS_2,adr); -+ map_write32(map,CMD_CLEAR_BLOCK_LOCKS_1,adr); -+ map_write32(map,CMD_CLEAR_BLOCK_LOCKS_2,adr); - - udelay(100); - -- status = map->read32(map,adr); -+ status = map_read32(map,adr); - printk("status=%08x\n",status); - - for(i=0;i<1000;i++){ -- //map->write32(map,CMD_READ_STATUS,adr); -- status = map->read32(map,adr); -+ //map_write32(map,CMD_READ_STATUS,adr); -+ status = map_read32(map,adr); - if((status & SR_READY)==SR_READY) - break; - udelay(100); -@@ -538,13 +541,13 @@ - } - - if(!(status&SR_ERRORS)){ -- map->write32(map,CMD_RESET,adr); -+ map_write32(map,CMD_RESET,adr); - chip->state = FL_READY; - return; - } - - printk("sharp: error unlocking block at addr=%08lx status=%08x\n",adr,status); -- map->write32(map,CMD_CLEAR_STATUS,adr); -+ map_write32(map,CMD_CLEAR_STATUS,adr); - } - #endif - -diff -Nurb linux-mips-2.4.27/drivers/mtd/cmdlinepart.c linux/drivers/mtd/cmdlinepart.c ---- linux-mips-2.4.27/drivers/mtd/cmdlinepart.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/cmdlinepart.c 2004-11-19 10:25:11.628240984 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Read flash partition table from command line - * -@@ -28,7 +28,7 @@ - - #include - #include --#include -+#include - #include - - /* error message prefix */ -@@ -178,8 +178,7 @@ - parts[this_part].mask_flags = mask_flags; - if (name) - { -- strncpy(extra_mem, name, name_len); -- extra_mem[name_len] = 0; -+ strlcpy(extra_mem, name, name_len + 1); - } - else - { -@@ -258,8 +257,7 @@ - this_mtd->parts = parts; - this_mtd->num_parts = num_parts; - this_mtd->mtd_id = (char*)(this_mtd + 1); -- strncpy(this_mtd->mtd_id, mtd_id, mtd_id_len); -- this_mtd->mtd_id[mtd_id_len] = 0; -+ strlcpy(this_mtd->mtd_id, mtd_id, mtd_id_len + 1); - - /* link into chain */ - this_mtd->next = partitions; -@@ -291,13 +289,14 @@ - * information. It returns partitions for the requested mtd device, or - * the first one in the chain if a NULL mtd_id is passed in. - */ --int parse_cmdline_partitions(struct mtd_info *master, -+static int parse_cmdline_partitions(struct mtd_info *master, - struct mtd_partition **pparts, -- const char *mtd_id) -+ unsigned long origin) - { - unsigned long offset; - int i; - struct cmdline_mtd_partition *part; -+ char *mtd_id = master->name; - - if(!cmdline) - return -EINVAL; -@@ -349,7 +348,25 @@ - - __setup("mtdparts=", mtdpart_setup); - --EXPORT_SYMBOL(parse_cmdline_partitions); -+static struct mtd_part_parser cmdline_parser = { -+ .owner = THIS_MODULE, -+ .parse_fn = parse_cmdline_partitions, -+ .name = "cmdlinepart", -+}; -+ -+static int __init cmdline_parser_init(void) -+{ -+ return register_mtd_parser(&cmdline_parser); -+} -+ -+static void __exit cmdline_parser_exit(void) -+{ -+ deregister_mtd_parser(&cmdline_parser); -+} -+ -+module_init(cmdline_parser_init); -+module_exit(cmdline_parser_exit); -+ - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Marius Groeger "); -diff -Nurb linux-mips-2.4.27/drivers/mtd/devices/Config.in linux/drivers/mtd/devices/Config.in ---- linux-mips-2.4.27/drivers/mtd/devices/Config.in 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/devices/Config.in 2004-11-19 10:25:11.811213168 +0100 -@@ -1,6 +1,6 @@ --# drivers/mtd/maps/Config.in -+# drivers/mtd/devices/Config.in - --# $Id$ -+# $Id$ - - mainmenu_option next_comment - -@@ -28,13 +28,13 @@ - dep_tristate ' MTD emulation using block device' CONFIG_MTD_BLKMTD $CONFIG_MTD - - comment 'Disk-On-Chip Device Drivers' -- dep_tristate ' M-Systems Disk-On-Chip 1000' CONFIG_MTD_DOC1000 $CONFIG_MTD - dep_tristate ' M-Systems Disk-On-Chip 2000 and Millennium' CONFIG_MTD_DOC2000 $CONFIG_MTD - dep_tristate ' M-Systems Disk-On-Chip Millennium-only alternative driver (see help)' CONFIG_MTD_DOC2001 $CONFIG_MTD -- if [ "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" ]; then -+ dep_tristate ' M-Systems Disk-On-Chip Millennium Plus driver (see help)' CONFIG_MTD_DOC2001PLUS $CONFIG_MTD -+ if [ "$CONFIG_MTD_DOC2001PLUS" = "y" -o "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" ]; then - define_bool CONFIG_MTD_DOCPROBE y - else -- if [ "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" ]; then -+ if [ "$CONFIG_MTD_DOC2001PLUS" = "m" -o "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" ]; then - define_bool CONFIG_MTD_DOCPROBE m - else - define_bool CONFIG_MTD_DOCPROBE n -diff -Nurb linux-mips-2.4.27/drivers/mtd/devices/Makefile linux/drivers/mtd/devices/Makefile ---- linux-mips-2.4.27/drivers/mtd/devices/Makefile 2002-03-30 09:15:50.000000000 +0100 -+++ linux/drivers/mtd/devices/Makefile 2004-11-19 10:25:11.813212864 +0100 -@@ -1,9 +1,12 @@ - # - # linux/drivers/devices/Makefile - # --# $Id$ -+# $Id$ - -+ifeq ($(PATCHLEVEL),4) - O_TARGET := devlink.o -+export-objs := docecc.o -+endif - - # *** BIG UGLY NOTE *** - # -@@ -12,15 +15,16 @@ - # here where previously there was none. We now have to ensure that - # doc200[01].o are linked before docprobe.o - --obj-$(CONFIG_MTD_DOC1000) += doc1000.o - obj-$(CONFIG_MTD_DOC2000) += doc2000.o - obj-$(CONFIG_MTD_DOC2001) += doc2001.o -+obj-$(CONFIG_MTD_DOC2001PLUS) += doc2001plus.o - obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o docecc.o - obj-$(CONFIG_MTD_SLRAM) += slram.o -+obj-$(CONFIG_MTD_PHRAM) += phram.o - obj-$(CONFIG_MTD_PMC551) += pmc551.o - obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o - obj-$(CONFIG_MTD_MTDRAM) += mtdram.o - obj-$(CONFIG_MTD_LART) += lart.o - obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o - --include $(TOPDIR)/Rules.make -+-include $(TOPDIR)/Rules.make -diff -Nurb linux-mips-2.4.27/drivers/mtd/devices/blkmtd-25.c linux/drivers/mtd/devices/blkmtd-25.c ---- linux-mips-2.4.27/drivers/mtd/devices/blkmtd-25.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/devices/blkmtd-25.c 2004-11-19 10:25:11.814212712 +0100 -@@ -0,0 +1,827 @@ -+/* -+ * $Id$ -+ * -+ * blkmtd.c - use a block device as a fake MTD -+ * -+ * Author: Simon Evans -+ * -+ * Copyright (C) 2001,2002 Simon Evans -+ * -+ * Licence: GPL -+ * -+ * How it works: -+ * The driver uses raw/io to read/write the device and the page -+ * cache to cache access. Writes update the page cache with the -+ * new data and mark it dirty and add the page into a BIO which -+ * is then written out. -+ * -+ * It can be loaded Read-Only to prevent erases and writes to the -+ * medium. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#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) -+#define warn(format, arg...) printk(KERN_WARNING "blkmtd: " format "\n" , ## arg) -+#define crit(format, arg...) printk(KERN_CRIT "blkmtd: " format "\n" , ## arg) -+ -+ -+/* Default erase size in K, always make it a multiple of PAGE_SIZE */ -+#define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10) /* 128KiB */ -+#define VERSION "$Revision$" -+ -+/* Info for the block device */ -+struct blkmtd_dev { -+ struct list_head list; -+ struct block_device *blkdev; -+ struct mtd_info mtd_info; -+ struct semaphore wrbuf_mutex; -+}; -+ -+ -+/* Static info about the MTD, used in cleanup_module */ -+static LIST_HEAD(blkmtd_device_list); -+ -+ -+static void blkmtd_sync(struct mtd_info *mtd); -+ -+#define MAX_DEVICES 4 -+ -+/* Module parameters passed by insmod/modprobe */ -+char *device[MAX_DEVICES]; /* the block device to use */ -+int erasesz[MAX_DEVICES]; /* optional default erase size */ -+int ro[MAX_DEVICES]; /* optional read only flag */ -+int sync; -+ -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Simon Evans "); -+MODULE_DESCRIPTION("Emulate an MTD using a block device"); -+MODULE_PARM(device, "1-4s"); -+MODULE_PARM_DESC(device, "block device to use"); -+MODULE_PARM(erasesz, "1-4i"); -+MODULE_PARM_DESC(erasesz, "optional erase size to use in KiB. eg 4=4KiB."); -+MODULE_PARM(ro, "1-4i"); -+MODULE_PARM_DESC(ro, "1=Read only, writes and erases cause errors"); -+MODULE_PARM(sync, "i"); -+MODULE_PARM_DESC(sync, "1=Synchronous writes"); -+ -+ -+/* completion handler for BIO reads */ -+static int bi_read_complete(struct bio *bio, unsigned int bytes_done, int error) -+{ -+ if (bio->bi_size) -+ return 1; -+ -+ complete((struct completion*)bio->bi_private); -+ return 0; -+} -+ -+ -+/* completion handler for BIO writes */ -+static int bi_write_complete(struct bio *bio, unsigned int bytes_done, int error) -+{ -+ const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); -+ struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; -+ -+ if (bio->bi_size) -+ return 1; -+ -+ if(!uptodate) -+ err("bi_write_complete: not uptodate\n"); -+ -+ do { -+ struct page *page = bvec->bv_page; -+ DEBUG(3, "Cleaning up page %ld\n", page->index); -+ if (--bvec >= bio->bi_io_vec) -+ prefetchw(&bvec->bv_page->flags); -+ -+ if (uptodate) { -+ SetPageUptodate(page); -+ } else { -+ ClearPageUptodate(page); -+ SetPageError(page); -+ } -+ ClearPageDirty(page); -+ unlock_page(page); -+ page_cache_release(page); -+ } while (bvec >= bio->bi_io_vec); -+ -+ complete((struct completion*)bio->bi_private); -+ return 0; -+} -+ -+ -+/* read one page from the block device */ -+static int blkmtd_readpage(struct blkmtd_dev *dev, struct page *page) -+{ -+ struct bio *bio; -+ struct completion event; -+ int err = -ENOMEM; -+ -+ if(PageUptodate(page)) { -+ DEBUG(2, "blkmtd: readpage page %ld is already upto date\n", page->index); -+ unlock_page(page); -+ return 0; -+ } -+ -+ ClearPageUptodate(page); -+ ClearPageError(page); -+ -+ bio = bio_alloc(GFP_KERNEL, 1); -+ if(bio) { -+ init_completion(&event); -+ bio->bi_bdev = dev->blkdev; -+ bio->bi_sector = page->index << (PAGE_SHIFT-9); -+ bio->bi_private = &event; -+ bio->bi_end_io = bi_read_complete; -+ if(bio_add_page(bio, page, PAGE_SIZE, 0) == PAGE_SIZE) { -+ submit_bio(READ, bio); -+ blk_run_queues(); -+ wait_for_completion(&event); -+ err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO; -+ bio_put(bio); -+ } -+ } -+ -+ if(err) -+ SetPageError(page); -+ else -+ SetPageUptodate(page); -+ flush_dcache_page(page); -+ unlock_page(page); -+ return err; -+} -+ -+ -+/* write out the current BIO and wait for it to finish */ -+static int blkmtd_write_out(struct bio *bio) -+{ -+ struct completion event; -+ int err; -+ -+ if(!bio->bi_vcnt) { -+ bio_put(bio); -+ return 0; -+ } -+ -+ init_completion(&event); -+ bio->bi_private = &event; -+ bio->bi_end_io = bi_write_complete; -+ submit_bio(WRITE, bio); -+ blk_run_queues(); -+ wait_for_completion(&event); -+ DEBUG(3, "submit_bio completed, bi_vcnt = %d\n", bio->bi_vcnt); -+ err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO; -+ bio_put(bio); -+ return err; -+} -+ -+ -+/** -+ * blkmtd_add_page - add a page to the current BIO -+ * @bio: bio to add to (NULL to alloc initial bio) -+ * @blkdev: block device -+ * @page: page to add -+ * @pagecnt: pages left to add -+ * -+ * Adds a page to the current bio, allocating it if necessary. If it cannot be -+ * added, the current bio is written out and a new one is allocated. Returns -+ * the new bio to add or NULL on error -+ */ -+static struct bio *blkmtd_add_page(struct bio *bio, struct block_device *blkdev, -+ struct page *page, int pagecnt) -+{ -+ -+ retry: -+ if(!bio) { -+ bio = bio_alloc(GFP_KERNEL, pagecnt); -+ if(!bio) -+ return NULL; -+ bio->bi_sector = page->index << (PAGE_SHIFT-9); -+ bio->bi_bdev = blkdev; -+ } -+ -+ if(bio_add_page(bio, page, PAGE_SIZE, 0) != PAGE_SIZE) { -+ blkmtd_write_out(bio); -+ bio = NULL; -+ goto retry; -+ } -+ return bio; -+} -+ -+ -+/** -+ * write_pages - write block of data to device via the page cache -+ * @dev: device to write to -+ * @buf: data source or NULL if erase (output is set to 0xff) -+ * @to: offset into output device -+ * @len: amount to data to write -+ * @retlen: amount of data written -+ * -+ * Grab pages from the page cache and fill them with the source data. -+ * Non page aligned start and end result in a readin of the page and -+ * part of the page being modified. Pages are added to the bio and then written -+ * out. -+ */ -+static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to, -+ size_t len, size_t *retlen) -+{ -+ int pagenr, offset; -+ size_t start_len = 0, end_len; -+ int pagecnt = 0; -+ int err = 0; -+ struct bio *bio = NULL; -+ size_t thislen = 0; -+ -+ pagenr = to >> PAGE_SHIFT; -+ offset = to & ~PAGE_MASK; -+ -+ DEBUG(2, "blkmtd: write_pages: buf = %p to = %ld len = %d pagenr = %d offset = %d\n", -+ buf, (long)to, len, pagenr, offset); -+ -+ /* see if we have to do a partial write at the start */ -+ if(offset) { -+ start_len = ((offset + len) > PAGE_SIZE) ? PAGE_SIZE - offset : len; -+ len -= start_len; -+ } -+ -+ /* calculate the length of the other two regions */ -+ end_len = len & ~PAGE_MASK; -+ len -= end_len; -+ -+ if(start_len) -+ pagecnt++; -+ -+ if(len) -+ pagecnt += len >> PAGE_SHIFT; -+ -+ if(end_len) -+ pagecnt++; -+ -+ down(&dev->wrbuf_mutex); -+ -+ DEBUG(3, "blkmtd: write: start_len = %d len = %d end_len = %d pagecnt = %d\n", -+ start_len, len, end_len, pagecnt); -+ -+ if(start_len) { -+ /* do partial start region */ -+ struct page *page; -+ -+ DEBUG(3, "blkmtd: write: doing partial start, page = %d len = %d offset = %d\n", -+ pagenr, start_len, offset); -+ -+ BUG_ON(!buf); -+ page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev); -+ lock_page(page); -+ if(PageDirty(page)) { -+ err("to = %lld start_len = %d len = %d end_len = %d pagenr = %d\n", -+ to, start_len, len, end_len, pagenr); -+ BUG(); -+ } -+ memcpy(page_address(page)+offset, buf, start_len); -+ SetPageDirty(page); -+ SetPageUptodate(page); -+ buf += start_len; -+ thislen = start_len; -+ bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt); -+ if(!bio) { -+ err = -ENOMEM; -+ err("bio_add_page failed\n"); -+ goto write_err; -+ } -+ pagecnt--; -+ pagenr++; -+ } -+ -+ /* Now do the main loop to a page aligned, n page sized output */ -+ if(len) { -+ int pagesc = len >> PAGE_SHIFT; -+ DEBUG(3, "blkmtd: write: whole pages start = %d, count = %d\n", -+ pagenr, pagesc); -+ while(pagesc) { -+ struct page *page; -+ -+ /* see if page is in the page cache */ -+ DEBUG(3, "blkmtd: write: grabbing page %d from page cache\n", pagenr); -+ page = grab_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr); -+ if(PageDirty(page)) { -+ BUG(); -+ } -+ if(!page) { -+ warn("write: cannot grab cache page %d", pagenr); -+ err = -ENOMEM; -+ goto write_err; -+ } -+ if(!buf) { -+ memset(page_address(page), 0xff, PAGE_SIZE); -+ } else { -+ memcpy(page_address(page), buf, PAGE_SIZE); -+ buf += PAGE_SIZE; -+ } -+ bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt); -+ if(!bio) { -+ err = -ENOMEM; -+ err("bio_add_page failed\n"); -+ goto write_err; -+ } -+ pagenr++; -+ pagecnt--; -+ SetPageDirty(page); -+ SetPageUptodate(page); -+ pagesc--; -+ thislen += PAGE_SIZE; -+ } -+ } -+ -+ if(end_len) { -+ /* do the third region */ -+ struct page *page; -+ DEBUG(3, "blkmtd: write: doing partial end, page = %d len = %d\n", -+ pagenr, end_len); -+ BUG_ON(!buf); -+ page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev); -+ lock_page(page); -+ if(PageDirty(page)) { -+ err("to = %lld start_len = %d len = %d end_len = %d pagenr = %d\n", -+ to, start_len, len, end_len, pagenr); -+ BUG(); -+ } -+ memcpy(page_address(page), buf, end_len); -+ SetPageDirty(page); -+ SetPageUptodate(page); -+ DEBUG(3, "blkmtd: write: writing out partial end\n"); -+ thislen += end_len; -+ bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt); -+ if(!bio) { -+ err = -ENOMEM; -+ err("bio_add_page failed\n"); -+ goto write_err; -+ } -+ pagenr++; -+ } -+ -+ DEBUG(3, "blkmtd: write: got %d vectors to write\n", bio->bi_vcnt); -+ write_err: -+ if(bio) -+ blkmtd_write_out(bio); -+ -+ DEBUG(2, "blkmtd: write: end, retlen = %d, err = %d\n", *retlen, err); -+ up(&dev->wrbuf_mutex); -+ -+ if(retlen) -+ *retlen = thislen; -+ return err; -+} -+ -+ -+/* erase a specified part of the device */ -+static int blkmtd_erase(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ struct blkmtd_dev *dev = mtd->priv; -+ struct mtd_erase_region_info *einfo = mtd->eraseregions; -+ int numregions = mtd->numeraseregions; -+ size_t from; -+ u_long len; -+ int err = -EIO; -+ int retlen; -+ -+ instr->state = MTD_ERASING; -+ from = instr->addr; -+ len = instr->len; -+ -+ /* check erase region has valid start and length */ -+ DEBUG(2, "blkmtd: erase: dev = `%s' from = 0x%x len = 0x%lx\n", -+ mtd->name+9, from, len); -+ while(numregions) { -+ DEBUG(3, "blkmtd: checking erase region = 0x%08X size = 0x%X num = 0x%x\n", -+ einfo->offset, einfo->erasesize, einfo->numblocks); -+ if(from >= einfo->offset -+ && from < einfo->offset + (einfo->erasesize * einfo->numblocks)) { -+ if(len == einfo->erasesize -+ && ( (from - einfo->offset) % einfo->erasesize == 0)) -+ break; -+ } -+ numregions--; -+ einfo++; -+ } -+ -+ if(!numregions) { -+ /* Not a valid erase block */ -+ err("erase: invalid erase request 0x%lX @ 0x%08X", len, from); -+ instr->state = MTD_ERASE_FAILED; -+ err = -EIO; -+ } -+ -+ if(instr->state != MTD_ERASE_FAILED) { -+ /* do the erase */ -+ DEBUG(3, "Doing erase from = %d len = %ld\n", from, len); -+ err = write_pages(dev, NULL, from, len, &retlen); -+ if(err || retlen != len) { -+ err("erase failed err = %d", err); -+ instr->state = MTD_ERASE_FAILED; -+ } else { -+ instr->state = MTD_ERASE_DONE; -+ } -+ } -+ -+ DEBUG(3, "blkmtd: erase: checking callback\n"); -+ if (instr->callback) { -+ (*(instr->callback))(instr); -+ } -+ DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err); -+ return err; -+} -+ -+ -+/* read a range of the data via the page cache */ -+static int blkmtd_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ struct blkmtd_dev *dev = mtd->priv; -+ int err = 0; -+ int offset; -+ int pagenr, pages; -+ size_t thislen = 0; -+ -+ DEBUG(2, "blkmtd: read: dev = `%s' from = %ld len = %d buf = %p\n", -+ mtd->name+9, (long int)from, len, buf); -+ -+ if(from > mtd->size) -+ return -EINVAL; -+ if(from + len > mtd->size) -+ len = mtd->size - from; -+ -+ pagenr = from >> PAGE_SHIFT; -+ offset = from - (pagenr << PAGE_SHIFT); -+ -+ pages = (offset+len+PAGE_SIZE-1) >> PAGE_SHIFT; -+ DEBUG(3, "blkmtd: read: pagenr = %d offset = %d, pages = %d\n", -+ pagenr, offset, pages); -+ -+ while(pages) { -+ struct page *page; -+ int cpylen; -+ -+ DEBUG(3, "blkmtd: read: looking for page: %d\n", pagenr); -+ page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev); -+ if(IS_ERR(page)) { -+ err = -EIO; -+ goto readerr; -+ } -+ -+ cpylen = (PAGE_SIZE > len) ? len : PAGE_SIZE; -+ if(offset+cpylen > PAGE_SIZE) -+ cpylen = PAGE_SIZE-offset; -+ -+ memcpy(buf + thislen, page_address(page) + offset, cpylen); -+ offset = 0; -+ len -= cpylen; -+ thislen += cpylen; -+ pagenr++; -+ pages--; -+ if(!PageDirty(page)) -+ page_cache_release(page); -+ } -+ -+ readerr: -+ if(retlen) -+ *retlen = thislen; -+ DEBUG(2, "blkmtd: end read: retlen = %d, err = %d\n", thislen, err); -+ return err; -+} -+ -+ -+/* write data to the underlying device */ -+static int blkmtd_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ struct blkmtd_dev *dev = mtd->priv; -+ int err; -+ -+ if(!len) -+ return 0; -+ -+ DEBUG(2, "blkmtd: write: dev = `%s' to = %ld len = %d buf = %p\n", -+ mtd->name+9, (long int)to, len, buf); -+ -+ if(to >= mtd->size) { -+ return -ENOSPC; -+ } -+ -+ if(to + len > mtd->size) { -+ len = mtd->size - to; -+ } -+ -+ err = write_pages(dev, buf, to, len, retlen); -+ if(err > 0) -+ err = 0; -+ DEBUG(2, "blkmtd: write: end, err = %d\n", err); -+ return err; -+} -+ -+ -+/* sync the device - wait until the write queue is empty */ -+static void blkmtd_sync(struct mtd_info *mtd) -+{ -+ /* Currently all writes are synchronous */ -+} -+ -+ -+static void free_device(struct blkmtd_dev *dev) -+{ -+ DEBUG(2, "blkmtd: free_device() dev = %p\n", dev); -+ if(dev) { -+ if(dev->mtd_info.eraseregions) -+ kfree(dev->mtd_info.eraseregions); -+ if(dev->mtd_info.name) -+ kfree(dev->mtd_info.name); -+ -+ if(dev->blkdev) { -+ invalidate_inode_pages(dev->blkdev->bd_inode->i_mapping); -+ close_bdev_excl(dev->blkdev, BDEV_RAW); -+ } -+ kfree(dev); -+ } -+} -+ -+ -+/* For a given size and initial erase size, calculate the number -+ * and size of each erase region. Goes round the loop twice, -+ * once to find out how many regions, then allocates space, -+ * then round the loop again to fill it in. -+ */ -+static struct mtd_erase_region_info *calc_erase_regions( -+ size_t erase_size, size_t total_size, int *regions) -+{ -+ struct mtd_erase_region_info *info = NULL; -+ -+ DEBUG(2, "calc_erase_regions, es = %d size = %d regions = %d\n", -+ erase_size, total_size, *regions); -+ /* Make any user specified erasesize be a power of 2 -+ and at least PAGE_SIZE */ -+ if(erase_size) { -+ int es = erase_size; -+ erase_size = 1; -+ while(es != 1) { -+ es >>= 1; -+ erase_size <<= 1; -+ } -+ if(erase_size < PAGE_SIZE) -+ erase_size = PAGE_SIZE; -+ } else { -+ erase_size = CONFIG_MTD_BLKDEV_ERASESIZE; -+ } -+ -+ *regions = 0; -+ -+ do { -+ int tot_size = total_size; -+ int er_size = erase_size; -+ int count = 0, offset = 0, regcnt = 0; -+ -+ while(tot_size) { -+ count = tot_size / er_size; -+ if(count) { -+ tot_size = tot_size % er_size; -+ if(info) { -+ DEBUG(2, "adding to erase info off=%d er=%d cnt=%d\n", -+ offset, er_size, count); -+ (info+regcnt)->offset = offset; -+ (info+regcnt)->erasesize = er_size; -+ (info+regcnt)->numblocks = count; -+ (*regions)++; -+ } -+ regcnt++; -+ offset += (count * er_size); -+ } -+ while(er_size > tot_size) -+ er_size >>= 1; -+ } -+ if(info == NULL) { -+ info = kmalloc(regcnt * sizeof(struct mtd_erase_region_info), GFP_KERNEL); -+ if(!info) -+ break; -+ } -+ } while(!(*regions)); -+ DEBUG(2, "calc_erase_regions done, es = %d size = %d regions = %d\n", -+ erase_size, total_size, *regions); -+ return info; -+} -+ -+ -+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; -+ int mode; -+ struct blkmtd_dev *dev; -+ -+ if(!devname) -+ return NULL; -+ -+ /* Get a handle on the device */ -+ -+ -+#ifdef MODULE -+ mode = (readonly) ? O_RDONLY : O_RDWR; -+ bdev = open_bdev_excl(devname, mode, BDEV_RAW, NULL); -+#else -+ mode = (readonly) ? FMODE_READ : FMODE_WRITE; -+ bdev = open_by_devnum(name_to_dev_t(devname), mode, BDEV_RAW); -+#endif -+ if(IS_ERR(bdev)) { -+ err("error: cannot open device %s", devname); -+ DEBUG(2, "blkmtd: opening bdev returned %ld\n", PTR_ERR(bdev)); -+ return NULL; -+ } -+ -+ DEBUG(1, "blkmtd: found a block device major = %d, minor = %d\n", -+ MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev)); -+ -+ if(MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { -+ err("attempting to use an MTD device as a block device"); -+ blkdev_put(bdev, BDEV_RAW); -+ return NULL; -+ } -+ -+ dev = kmalloc(sizeof(struct blkmtd_dev), GFP_KERNEL); -+ if(dev == NULL) { -+ blkdev_put(bdev, BDEV_RAW); -+ return NULL; -+ } -+ -+ memset(dev, 0, sizeof(struct blkmtd_dev)); -+ if(!readonly) { -+ init_MUTEX(&dev->wrbuf_mutex); -+ } -+ -+ dev->blkdev = bdev; -+ dev->mtd_info.size = dev->blkdev->bd_inode->i_size & PAGE_MASK; -+ -+ /* Setup the MTD structure */ -+ /* make the name contain the block device in */ -+ dev->mtd_info.name = kmalloc(sizeof("blkmtd: ") + strlen(devname), GFP_KERNEL); -+ if(dev->mtd_info.name == NULL) -+ goto devinit_err; -+ -+ sprintf(dev->mtd_info.name, "blkmtd: %s", devname); -+ dev->mtd_info.eraseregions = calc_erase_regions(erase_size, dev->mtd_info.size, -+ &dev->mtd_info.numeraseregions); -+ if(dev->mtd_info.eraseregions == NULL) -+ goto devinit_err; -+ -+ dev->mtd_info.erasesize = dev->mtd_info.eraseregions->erasesize; -+ DEBUG(1, "blkmtd: init: found %d erase regions\n", -+ dev->mtd_info.numeraseregions); -+ -+ if(readonly) { -+ dev->mtd_info.type = MTD_ROM; -+ dev->mtd_info.flags = MTD_CAP_ROM; -+ } else { -+ dev->mtd_info.type = MTD_RAM; -+ dev->mtd_info.flags = MTD_CAP_RAM; -+ dev->mtd_info.erase = blkmtd_erase; -+ dev->mtd_info.write = blkmtd_write; -+ dev->mtd_info.writev = default_mtd_writev; -+ dev->mtd_info.sync = blkmtd_sync; -+ } -+ dev->mtd_info.read = blkmtd_read; -+ dev->mtd_info.readv = default_mtd_readv; -+ dev->mtd_info.priv = dev; -+ dev->mtd_info.owner = THIS_MODULE; -+ -+ list_add(&dev->list, &blkmtd_device_list); -+ if (add_mtd_device(&dev->mtd_info)) { -+ /* Device didnt get added, so free the entry */ -+ list_del(&dev->list); -+ goto devinit_err; -+ } else { -+ info("mtd%d: [%s] erase_size = %dKiB %s", -+ dev->mtd_info.index, dev->mtd_info.name + strlen("blkmtd: "), -+ dev->mtd_info.erasesize >> 10, -+ readonly ? "(read-only)" : ""); -+ } -+ -+ return dev; -+ -+ devinit_err: -+ free_device(dev); -+ return NULL; -+} -+ -+ -+/* Cleanup and exit - sync the device and kill of the kernel thread */ -+static void __devexit cleanup_blkmtd(void) -+{ -+ struct list_head *temp1, *temp2; -+ -+ /* Remove the MTD devices */ -+ list_for_each_safe(temp1, temp2, &blkmtd_device_list) { -+ struct blkmtd_dev *dev = list_entry(temp1, struct blkmtd_dev, -+ list); -+ blkmtd_sync(&dev->mtd_info); -+ del_mtd_device(&dev->mtd_info); -+ info("mtd%d: [%s] removed", dev->mtd_info.index, -+ dev->mtd_info.name + strlen("blkmtd: ")); -+ list_del(&dev->list); -+ free_device(dev); -+ } -+} -+ -+#ifndef MODULE -+ -+/* Handle kernel boot params */ -+ -+ -+static int __init param_blkmtd_device(char *str) -+{ -+ int i; -+ -+ for(i = 0; i < MAX_DEVICES; i++) { -+ device[i] = str; -+ DEBUG(2, "blkmtd: device setup: %d = %s\n", i, device[i]); -+ strsep(&str, ","); -+ } -+ return 1; -+} -+ -+ -+static int __init param_blkmtd_erasesz(char *str) -+{ -+ int i; -+ for(i = 0; i < MAX_DEVICES; i++) { -+ char *val = strsep(&str, ","); -+ if(val) -+ erasesz[i] = simple_strtoul(val, NULL, 0); -+ DEBUG(2, "blkmtd: erasesz setup: %d = %d\n", i, erasesz[i]); -+ } -+ -+ return 1; -+} -+ -+ -+static int __init param_blkmtd_ro(char *str) -+{ -+ int i; -+ for(i = 0; i < MAX_DEVICES; i++) { -+ char *val = strsep(&str, ","); -+ if(val) -+ ro[i] = simple_strtoul(val, NULL, 0); -+ DEBUG(2, "blkmtd: ro setup: %d = %d\n", i, ro[i]); -+ } -+ -+ return 1; -+} -+ -+ -+static int __init param_blkmtd_sync(char *str) -+{ -+ if(str[0] == '1') -+ sync = 1; -+ return 1; -+} -+ -+__setup("blkmtd_device=", param_blkmtd_device); -+__setup("blkmtd_erasesz=", param_blkmtd_erasesz); -+__setup("blkmtd_ro=", param_blkmtd_ro); -+__setup("blkmtd_sync=", param_blkmtd_sync); -+ -+#endif -+ -+ -+/* Startup */ -+static int __init init_blkmtd(void) -+{ -+ int i; -+ -+ info("version " VERSION); -+ /* Check args - device[0] is the bare minimum*/ -+ if(!device[0]) { -+ err("error: missing `device' name\n"); -+ return -EINVAL; -+ } -+ -+ for(i = 0; i < MAX_DEVICES; i++) -+ add_device(device[i], ro[i], erasesz[i] << 10); -+ -+ if(list_empty(&blkmtd_device_list)) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+module_init(init_blkmtd); -+module_exit(cleanup_blkmtd); -diff -Nurb linux-mips-2.4.27/drivers/mtd/devices/blkmtd.c linux/drivers/mtd/devices/blkmtd.c ---- linux-mips-2.4.27/drivers/mtd/devices/blkmtd.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/devices/blkmtd.c 2004-11-19 10:25:11.816212408 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * blkmtd.c - use a block device as a fake MTD - * -@@ -143,7 +143,7 @@ - for(cnt = 0; cnt < pages; cnt++) { - page = grab_cache_page(dev->binding->bd_inode->i_mapping, pagenrs[cnt]); - pagelst[cnt] = page; -- if(!PageUptodate(page)) { -+ if(!Page_Uptodate(page)) { - iobuf->blocks[iobuf->nr_pages] = pagenrs[cnt]; - iobuf->maplist[iobuf->nr_pages++] = page; - } -@@ -912,7 +912,7 @@ - dev->mtd_info.point = 0; - dev->mtd_info.unpoint = 0; - dev->mtd_info.priv = dev; -- dev->mtd_info.module = THIS_MODULE; -+ dev->mtd_info.owner = THIS_MODULE; - - list_add(&dev->list, &blkmtd_device_list); - if (add_mtd_device(&dev->mtd_info)) { -diff -Nurb linux-mips-2.4.27/drivers/mtd/devices/doc2000.c linux/drivers/mtd/devices/doc2000.c ---- linux-mips-2.4.27/drivers/mtd/devices/doc2000.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/devices/doc2000.c 2004-11-19 10:25:11.818212104 +0100 -@@ -4,7 +4,7 @@ - * (c) 1999 Machine Vision Holdings, Inc. - * (c) 1999, 2000 David Woodhouse - * -- * $Id$ -+ * $Id$ - */ - - #include -@@ -25,6 +25,7 @@ - #include - - #define DOC_SUPPORT_2000 -+#define DOC_SUPPORT_2000TSOP - #define DOC_SUPPORT_MILLENNIUM - - #ifdef DOC_SUPPORT_2000 -@@ -33,7 +34,7 @@ - #define DoC_is_2000(doc) (0) - #endif - --#ifdef DOC_SUPPORT_MILLENNIUM -+#if defined(DOC_SUPPORT_2000TSOP) || defined(DOC_SUPPORT_MILLENNIUM) - #define DoC_is_Millennium(doc) (doc->ChipID == DOC_ChipID_DocMil) - #else - #define DoC_is_Millennium(doc) (0) -@@ -56,6 +57,9 @@ - size_t *retlen, u_char *buf, u_char *eccbuf, int oobsel); - static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf, u_char *eccbuf, int oobsel); -+static int doc_writev_ecc(struct mtd_info *mtd, const struct iovec *vecs, -+ unsigned long count, loff_t to, size_t *retlen, -+ u_char *eccbuf, struct nand_oobinfo *oobsel); - static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, u_char *buf); - static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, -@@ -92,6 +96,10 @@ - - /* Out-of-line routine to wait for chip response */ - while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { -+ /* issue 2 read from NOP register after reading from CDSNControl register -+ see Software Requirement 11.4 item 2. */ -+ DoC_Delay(doc, 2); -+ - if (time_after(jiffies, timeo)) { - DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); - return -EIO; -@@ -145,6 +153,8 @@ - - /* Send the command */ - WriteDOC_(command, docptr, doc->ioreg); -+ if (DoC_is_Millennium(doc)) -+ WriteDOC(command, docptr, WritePipeTerm); - - /* Lower the CLE line */ - WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl); -@@ -206,6 +216,9 @@ - } - } - -+ if (DoC_is_Millennium(doc)) -+ WriteDOC(ofs & 0xff, docptr, WritePipeTerm); -+ - DoC_Delay(doc, 2); /* Needed for some slow flash chips. mf. */ - - /* FIXME: The SlowIO's for millennium could be replaced by -@@ -344,15 +357,25 @@ - - /* Read the manufacturer and device id codes from the device */ - -- /* CDSN Slow IO register see Software Requirement 11.4 item 5. */ -+ if (DoC_is_Millennium(doc)) { -+ DoC_Delay(doc, 2); -+ dummy = ReadDOC(doc->virtadr, ReadPipeInit); -+ mfr = ReadDOC(doc->virtadr, LastDataRead); -+ -+ DoC_Delay(doc, 2); -+ dummy = ReadDOC(doc->virtadr, ReadPipeInit); -+ id = ReadDOC(doc->virtadr, LastDataRead); -+ } else { -+ /* CDSN Slow IO register see Software Req 11.4 item 5. */ - dummy = ReadDOC(doc->virtadr, CDSNSlowIO); - DoC_Delay(doc, 2); - mfr = ReadDOC_(doc->virtadr, doc->ioreg); - -- /* CDSN Slow IO register see Software Requirement 11.4 item 5. */ -+ /* CDSN Slow IO register see Software Req 11.4 item 5. */ - dummy = ReadDOC(doc->virtadr, CDSNSlowIO); - DoC_Delay(doc, 2); - id = ReadDOC_(doc->virtadr, doc->ioreg); -+ } - - /* No response - return failure */ - if (mfr == 0xff || mfr == 0) -@@ -410,20 +433,16 @@ - - /* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */ - --static void DoC_ScanChips(struct DiskOnChip *this) -+static void DoC_ScanChips(struct DiskOnChip *this, int maxchips) - { - int floor, chip; - int numchips[MAX_FLOORS]; -- int maxchips = MAX_CHIPS; - int ret = 1; - - this->numchips = 0; - this->mfr = 0; - this->id = 0; - -- if (DoC_is_Millennium(this)) -- maxchips = MAX_CHIPS_MIL; -- - /* For each floor, find the number of valid chips it contains */ - for (floor = 0; floor < MAX_FLOORS; floor++) { - ret = 1; -@@ -515,6 +534,7 @@ - { - struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; - struct DiskOnChip *old = NULL; -+ int maxchips; - - /* We must avoid being called twice for the same device. */ - -@@ -538,14 +558,28 @@ - - - switch (this->ChipID) { -+ case DOC_ChipID_Doc2kTSOP: -+ mtd->name = "DiskOnChip 2000 TSOP"; -+ this->ioreg = DoC_Mil_CDSN_IO; -+ /* Pretend it's a Millennium */ -+ this->ChipID = DOC_ChipID_DocMil; -+ maxchips = MAX_CHIPS; -+ break; - case DOC_ChipID_Doc2k: - mtd->name = "DiskOnChip 2000"; - this->ioreg = DoC_2k_CDSN_IO; -+ maxchips = MAX_CHIPS; - break; - case DOC_ChipID_DocMil: - mtd->name = "DiskOnChip Millennium"; - this->ioreg = DoC_Mil_CDSN_IO; -+ maxchips = MAX_CHIPS_MIL; - break; -+ default: -+ printk("Unknown ChipID 0x%02x\n", this->ChipID); -+ kfree(mtd); -+ iounmap((void *) this->virtadr); -+ return; - } - - printk(KERN_NOTICE "%s found at address 0x%lX\n", mtd->name, -@@ -553,11 +587,12 @@ - - mtd->type = MTD_NANDFLASH; - mtd->flags = MTD_CAP_NANDFLASH; -+ mtd->ecctype = MTD_ECC_RS_DiskOnChip; - mtd->size = 0; - mtd->erasesize = 0; - mtd->oobblock = 512; - mtd->oobsize = 16; -- mtd->module = THIS_MODULE; -+ mtd->owner = THIS_MODULE; - mtd->erase = doc_erase; - mtd->point = NULL; - mtd->unpoint = NULL; -@@ -565,6 +600,7 @@ - mtd->write = doc_write; - mtd->read_ecc = doc_read_ecc; - mtd->write_ecc = doc_write_ecc; -+ mtd->writev_ecc = doc_writev_ecc; - mtd->read_oob = doc_read_oob; - mtd->write_oob = doc_write_oob; - mtd->sync = NULL; -@@ -577,7 +613,7 @@ - init_MUTEX(&this->lock); - - /* Ident all the chips present. */ -- DoC_ScanChips(this); -+ DoC_ScanChips(this, maxchips); - - if (!this->totlen) { - kfree(mtd); -@@ -608,6 +644,7 @@ - unsigned char syndrome[6]; - volatile char dummy; - int i, len256 = 0, ret=0; -+ size_t left = len; - - docptr = this->virtadr; - -@@ -617,6 +654,10 @@ - - down(&this->lock); - -+ *retlen = 0; -+ while (left) { -+ len = left; -+ - /* Don't allow a single read to cross a 512-byte block boundary */ - if (from + len > ((from | 0x1ff) + 1)) - len = ((from | 0x1ff) + 1) - from; -@@ -673,7 +714,7 @@ - DoC_ReadBuf(this, &buf[len256], len - len256); - - /* Let the caller know we completed it */ -- *retlen = len; -+ *retlen += len; - - if (eccbuf) { - /* Read the ECC data through the DiskOnChip ECC logic */ -@@ -730,11 +771,16 @@ - - /* according to 11.4.1, we need to wait for the busy line - * drop if we read to the end of the page. */ -- if(0 == ((from + *retlen) & 0x1ff)) -+ if(0 == ((from + len) & 0x1ff)) - { - DoC_WaitReady(this); - } - -+ from += len; -+ left -= len; -+ buf += len; -+ } -+ - up(&this->lock); - - return ret; -@@ -757,6 +803,8 @@ - volatile char dummy; - int len256 = 0; - struct Nand *mychip; -+ size_t left = len; -+ int status; - - docptr = this->virtadr; - -@@ -766,15 +814,21 @@ - - down(&this->lock); - -+ *retlen = 0; -+ while (left) { -+ len = left; -+ - /* Don't allow a single write to cross a 512-byte block boundary */ - if (to + len > ((to | 0x1ff) + 1)) - len = ((to | 0x1ff) + 1) - to; - - /* The ECC will not be calculated correctly if less than 512 is written */ -+/* DBB- - if (len != 0x200 && eccbuf) - printk(KERN_WARNING - "ECC needs a full sector write (adr: %lx size %lx)\n", - (long) to, (long) len); -+ -DBB */ - - /* printk("DoC_Write (adr: %lx size %lx)\n", (long) to, (long) len); */ - -@@ -853,6 +907,9 @@ - WriteDOC_(0, docptr, this->ioreg); - } - -+ WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_FLASH_IO | CDSN_CTRL_CE, docptr, -+ CDSNControl); -+ - /* Read the ECC data through the DiskOnChip ECC logic */ - for (di = 0; di < 6; di++) { - eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di); -@@ -874,10 +931,16 @@ - DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); - /* There's an implicit DoC_WaitReady() in DoC_Command */ - -+ if (DoC_is_Millennium(this)) { -+ ReadDOC(docptr, ReadPipeInit); -+ status = ReadDOC(docptr, LastDataRead); -+ } else { - dummy = ReadDOC(docptr, CDSNSlowIO); - DoC_Delay(this, 2); -+ status = ReadDOC_(docptr, this->ioreg); -+ } - -- if (ReadDOC_(docptr, this->ioreg) & 1) { -+ if (status & 1) { - printk(KERN_ERR "Error programming flash\n"); - /* Error in programming */ - *retlen = 0; -@@ -886,7 +949,7 @@ - } - - /* Let the caller know we completed it */ -- *retlen = len; -+ *retlen += len; - - if (eccbuf) { - unsigned char x[8]; -@@ -901,13 +964,81 @@ - x[7]=0x55; - - ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x); -+ if (ret) { - up(&this->lock); - return ret; - } -+ } -+ -+ to += len; -+ left -= len; -+ buf += len; -+ } -+ - up(&this->lock); - return 0; - } - -+static int doc_writev_ecc(struct mtd_info *mtd, const struct iovec *vecs, -+ unsigned long count, loff_t to, size_t *retlen, -+ u_char *eccbuf, struct nand_oobinfo *oobsel) -+{ -+ static char static_buf[512]; -+ static DECLARE_MUTEX(writev_buf_sem); -+ -+ size_t totretlen = 0; -+ size_t thisvecofs = 0; -+ int ret= 0; -+ -+ down(&writev_buf_sem); -+ -+ while(count) { -+ size_t thislen, thisretlen; -+ unsigned char *buf; -+ -+ buf = vecs->iov_base + thisvecofs; -+ thislen = vecs->iov_len - thisvecofs; -+ -+ -+ if (thislen >= 512) { -+ thislen = thislen & ~(512-1); -+ thisvecofs += thislen; -+ } else { -+ /* Not enough to fill a page. Copy into buf */ -+ memcpy(static_buf, buf, thislen); -+ buf = &static_buf[thislen]; -+ -+ while(count && thislen < 512) { -+ vecs++; -+ count--; -+ thisvecofs = min((512-thislen), vecs->iov_len); -+ memcpy(buf, vecs->iov_base, thisvecofs); -+ thislen += thisvecofs; -+ buf += thisvecofs; -+ } -+ buf = static_buf; -+ } -+ if (count && thisvecofs == vecs->iov_len) { -+ thisvecofs = 0; -+ vecs++; -+ count--; -+ } -+ ret = doc_write_ecc(mtd, to, thislen, &thisretlen, buf, eccbuf, oobsel); -+ -+ totretlen += thisretlen; -+ -+ if (ret || thisretlen != thislen) -+ break; -+ -+ to += thislen; -+ } -+ -+ up(&writev_buf_sem); -+ *retlen = totretlen; -+ return ret; -+} -+ -+ - static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t * retlen, u_char * buf) - { -@@ -977,6 +1108,7 @@ - unsigned long docptr = this->virtadr; - struct Nand *mychip = &this->chips[ofs >> this->chipshift]; - volatile int dummy; -+ int status; - - // printk("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",(long)ofs, len, - // buf[0], buf[1], buf[2], buf[3], buf[8], buf[9], buf[14],buf[15]); -@@ -1025,10 +1157,16 @@ - DoC_Command(this, NAND_CMD_STATUS, 0); - /* DoC_WaitReady() is implicit in DoC_Command */ - -+ if (DoC_is_Millennium(this)) { -+ ReadDOC(docptr, ReadPipeInit); -+ status = ReadDOC(docptr, LastDataRead); -+ } else { - dummy = ReadDOC(docptr, CDSNSlowIO); - DoC_Delay(this, 2); -+ status = ReadDOC_(docptr, this->ioreg); -+ } - -- if (ReadDOC_(docptr, this->ioreg) & 1) { -+ if (status & 1) { - printk(KERN_ERR "Error programming oob data\n"); - /* There was an error */ - *retlen = 0; -@@ -1044,10 +1182,16 @@ - DoC_Command(this, NAND_CMD_STATUS, 0); - /* DoC_WaitReady() is implicit in DoC_Command */ - -+ if (DoC_is_Millennium(this)) { -+ ReadDOC(docptr, ReadPipeInit); -+ status = ReadDOC(docptr, LastDataRead); -+ } else { - dummy = ReadDOC(docptr, CDSNSlowIO); - DoC_Delay(this, 2); -+ status = ReadDOC_(docptr, this->ioreg); -+ } - -- if (ReadDOC_(docptr, this->ioreg) & 1) { -+ if (status & 1) { - printk(KERN_ERR "Error programming oob data\n"); - /* There was an error */ - *retlen = 0; -@@ -1080,6 +1224,7 @@ - volatile int dummy; - unsigned long docptr; - struct Nand *mychip; -+ int status; - - down(&this->lock); - -@@ -1111,10 +1256,16 @@ - - DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); - -+ if (DoC_is_Millennium(this)) { -+ ReadDOC(docptr, ReadPipeInit); -+ status = ReadDOC(docptr, LastDataRead); -+ } else { - dummy = ReadDOC(docptr, CDSNSlowIO); - DoC_Delay(this, 2); -+ status = ReadDOC_(docptr, this->ioreg); -+ } - -- if (ReadDOC_(docptr, this->ioreg) & 1) { -+ if (status & 1) { - printk(KERN_ERR "Error erasing at 0x%x\n", ofs); - /* There was an error */ - instr->state = MTD_ERASE_FAILED; -diff -Nurb linux-mips-2.4.27/drivers/mtd/devices/doc2001.c linux/drivers/mtd/devices/doc2001.c ---- linux-mips-2.4.27/drivers/mtd/devices/doc2001.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/devices/doc2001.c 2004-11-19 10:25:11.835209520 +0100 -@@ -4,7 +4,7 @@ - * (c) 1999 Machine Vision Holdings, Inc. - * (c) 1999, 2000 David Woodhouse - * -- * $Id$ -+ * $Id$ - */ - - #include -@@ -359,14 +359,15 @@ - - mtd->type = MTD_NANDFLASH; - mtd->flags = MTD_CAP_NANDFLASH; -+ mtd->ecctype = MTD_ECC_RS_DiskOnChip; - mtd->size = 0; - -- /* FIXME: erase size is not always 8kB */ -+ /* FIXME: erase size is not always 8KiB */ - mtd->erasesize = 0x2000; - - mtd->oobblock = 512; - mtd->oobsize = 16; -- mtd->module = THIS_MODULE; -+ mtd->owner = THIS_MODULE; - mtd->erase = doc_erase; - mtd->point = NULL; - mtd->unpoint = NULL; -diff -Nurb linux-mips-2.4.27/drivers/mtd/devices/doc2001plus.c linux/drivers/mtd/devices/doc2001plus.c ---- linux-mips-2.4.27/drivers/mtd/devices/doc2001plus.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/devices/doc2001plus.c 2004-11-19 10:25:11.837209216 +0100 -@@ -0,0 +1,1154 @@ -+/* -+ * Linux driver for Disk-On-Chip Millennium Plus -+ * -+ * (c) 2002-2003 Greg Ungerer -+ * (c) 2002-2003 SnapGear Inc -+ * (c) 1999 Machine Vision Holdings, Inc. -+ * (c) 1999, 2000 David Woodhouse -+ * -+ * $Id$ -+ * -+ * Released under GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+/* #define ECC_DEBUG */ -+ -+/* I have no idea why some DoC chips can not use memcop_form|to_io(). -+ * This may be due to the different revisions of the ASIC controller built-in or -+ * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment -+ * this:*/ -+#undef USE_MEMCPY -+ -+static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf); -+static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf); -+static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf, u_char *eccbuf, -+ struct nand_oobinfo *oobsel); -+static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf, u_char *eccbuf, -+ struct nand_oobinfo *oobsel); -+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, -+ size_t *retlen, u_char *buf); -+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, -+ size_t *retlen, const u_char *buf); -+static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); -+ -+static struct mtd_info *docmilpluslist = NULL; -+ -+ -+/* Perform the required delay cycles by writing to the NOP register */ -+static void DoC_Delay(unsigned long docptr, int cycles) -+{ -+ int i; -+ -+ for (i = 0; (i < cycles); i++) -+ WriteDOC(0, docptr, Mplus_NOP); -+} -+ -+#define CDSN_CTRL_FR_B_MASK (CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1) -+ -+/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ -+static int _DoC_WaitReady(unsigned long docptr) -+{ -+ unsigned int c = 0xffff; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, -+ "_DoC_WaitReady called for out-of-line wait\n"); -+ -+ /* Out-of-line routine to wait for chip response */ -+ while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c) -+ ; -+ -+ if (c == 0) -+ DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); -+ -+ return (c == 0); -+} -+ -+static inline int DoC_WaitReady(unsigned long docptr) -+{ -+ /* This is inline, to optimise the common case, where it's ready instantly */ -+ int ret = 0; -+ -+ /* read form NOP register should be issued prior to the read from CDSNControl -+ see Software Requirement 11.4 item 2. */ -+ DoC_Delay(docptr, 4); -+ -+ if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) -+ /* Call the out-of-line routine to wait */ -+ ret = _DoC_WaitReady(docptr); -+ -+ return ret; -+} -+ -+/* For some reason the Millennium Plus seems to occassionally put itself -+ * into reset mode. For me this happens randomly, with no pattern that I -+ * can detect. M-systems suggest always check this on any block level -+ * operation and setting to normal mode if in reset mode. -+ */ -+static inline void DoC_CheckASIC(unsigned long docptr) -+{ -+ /* Make sure the DoC is in normal mode */ -+ if ((ReadDOC(docptr, Mplus_DOCControl) & DOC_MODE_NORMAL) == 0) { -+ WriteDOC((DOC_MODE_NORMAL | DOC_MODE_MDWREN), docptr, Mplus_DOCControl); -+ WriteDOC(~(DOC_MODE_NORMAL | DOC_MODE_MDWREN), docptr, Mplus_CtrlConfirm); -+ } -+} -+ -+/* DoC_Command: Send a flash command to the flash chip through the Flash -+ * command register. Need 2 Write Pipeline Terminates to complete send. -+ */ -+static inline void DoC_Command(unsigned long docptr, unsigned char command, -+ unsigned char xtraflags) -+{ -+ WriteDOC(command, docptr, Mplus_FlashCmd); -+ WriteDOC(command, docptr, Mplus_WritePipeTerm); -+ WriteDOC(command, docptr, Mplus_WritePipeTerm); -+} -+ -+/* DoC_Address: Set the current address for the flash chip through the Flash -+ * Address register. Need 2 Write Pipeline Terminates to complete send. -+ */ -+static inline void DoC_Address(struct DiskOnChip *doc, int numbytes, -+ unsigned long ofs, unsigned char xtraflags1, -+ unsigned char xtraflags2) -+{ -+ unsigned long docptr = doc->virtadr; -+ -+ /* Allow for possible Mill Plus internal flash interleaving */ -+ ofs >>= doc->interleave; -+ -+ switch (numbytes) { -+ case 1: -+ /* Send single byte, bits 0-7. */ -+ WriteDOC(ofs & 0xff, docptr, Mplus_FlashAddress); -+ break; -+ case 2: -+ /* Send bits 9-16 followed by 17-23 */ -+ WriteDOC((ofs >> 9) & 0xff, docptr, Mplus_FlashAddress); -+ WriteDOC((ofs >> 17) & 0xff, docptr, Mplus_FlashAddress); -+ break; -+ case 3: -+ /* Send 0-7, 9-16, then 17-23 */ -+ WriteDOC(ofs & 0xff, docptr, Mplus_FlashAddress); -+ WriteDOC((ofs >> 9) & 0xff, docptr, Mplus_FlashAddress); -+ WriteDOC((ofs >> 17) & 0xff, docptr, Mplus_FlashAddress); -+ break; -+ default: -+ return; -+ } -+ -+ WriteDOC(0x00, docptr, Mplus_WritePipeTerm); -+ WriteDOC(0x00, docptr, Mplus_WritePipeTerm); -+} -+ -+/* DoC_SelectChip: Select a given flash chip within the current floor */ -+static int DoC_SelectChip(unsigned long docptr, int chip) -+{ -+ /* No choice for flash chip on Millennium Plus */ -+ return 0; -+} -+ -+/* DoC_SelectFloor: Select a given floor (bank of flash chips) */ -+static int DoC_SelectFloor(unsigned long docptr, int floor) -+{ -+ WriteDOC((floor & 0x3), docptr, Mplus_DeviceSelect); -+ return 0; -+} -+ -+/* -+ * Translate the given offset into the appropriate command and offset. -+ * This does the mapping using the 16bit interleave layout defined by -+ * M-Systems, and looks like this for a sector pair: -+ * +-----------+-------+-------+-------+--------------+---------+-----------+ -+ * | 0 --- 511 |512-517|518-519|520-521| 522 --- 1033 |1034-1039|1040 - 1055| -+ * +-----------+-------+-------+-------+--------------+---------+-----------+ -+ * | Data 0 | ECC 0 |Flags0 |Flags1 | Data 1 |ECC 1 | OOB 1 + 2 | -+ * +-----------+-------+-------+-------+--------------+---------+-----------+ -+ */ -+/* FIXME: This lives in INFTL not here. Other users of flash devices -+ may not want it */ -+static unsigned int DoC_GetDataOffset(struct mtd_info *mtd, loff_t *from) -+{ -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ -+ if (this->interleave) { -+ unsigned int ofs = *from & 0x3ff; -+ unsigned int cmd; -+ -+ if (ofs < 512) { -+ cmd = NAND_CMD_READ0; -+ ofs &= 0x1ff; -+ } else if (ofs < 1014) { -+ cmd = NAND_CMD_READ1; -+ ofs = (ofs & 0x1ff) + 10; -+ } else { -+ cmd = NAND_CMD_READOOB; -+ ofs = ofs - 1014; -+ } -+ -+ *from = (*from & ~0x3ff) | ofs; -+ return cmd; -+ } else { -+ /* No interleave */ -+ if ((*from) & 0x100) -+ return NAND_CMD_READ1; -+ return NAND_CMD_READ0; -+ } -+} -+ -+static unsigned int DoC_GetECCOffset(struct mtd_info *mtd, loff_t *from) -+{ -+ unsigned int ofs, cmd; -+ -+ if (*from & 0x200) { -+ cmd = NAND_CMD_READOOB; -+ ofs = 10 + (*from & 0xf); -+ } else { -+ cmd = NAND_CMD_READ1; -+ ofs = (*from & 0xf); -+ } -+ -+ *from = (*from & ~0x3ff) | ofs; -+ return cmd; -+} -+ -+static unsigned int DoC_GetFlagsOffset(struct mtd_info *mtd, loff_t *from) -+{ -+ unsigned int ofs, cmd; -+ -+ cmd = NAND_CMD_READ1; -+ ofs = (*from & 0x200) ? 8 : 6; -+ *from = (*from & ~0x3ff) | ofs; -+ return cmd; -+} -+ -+static unsigned int DoC_GetHdrOffset(struct mtd_info *mtd, loff_t *from) -+{ -+ unsigned int ofs, cmd; -+ -+ cmd = NAND_CMD_READOOB; -+ ofs = (*from & 0x200) ? 24 : 16; -+ *from = (*from & ~0x3ff) | ofs; -+ return cmd; -+} -+ -+static inline void MemReadDOC(unsigned long docptr, unsigned char *buf, int len) -+{ -+#ifndef USE_MEMCPY -+ int i; -+ for (i = 0; i < len; i++) -+ buf[i] = ReadDOC(docptr, Mil_CDSN_IO + i); -+#else -+ memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len); -+#endif -+} -+ -+static inline void MemWriteDOC(unsigned long docptr, unsigned char *buf, int len) -+{ -+#ifndef USE_MEMCPY -+ int i; -+ for (i = 0; i < len; i++) -+ WriteDOC(buf[i], docptr, Mil_CDSN_IO + i); -+#else -+ memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len); -+#endif -+} -+ -+/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */ -+static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) -+{ -+ int mfr, id, i, j; -+ volatile char dummy; -+ unsigned long docptr = doc->virtadr; -+ -+ /* Page in the required floor/chip */ -+ DoC_SelectFloor(docptr, floor); -+ DoC_SelectChip(docptr, chip); -+ -+ /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ -+ WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect); -+ -+ /* Reset the chip, see Software Requirement 11.4 item 1. */ -+ DoC_Command(docptr, NAND_CMD_RESET, 0); -+ DoC_WaitReady(docptr); -+ -+ /* Read the NAND chip ID: 1. Send ReadID command */ -+ DoC_Command(docptr, NAND_CMD_READID, 0); -+ -+ /* Read the NAND chip ID: 2. Send address byte zero */ -+ DoC_Address(doc, 1, 0x00, 0, 0x00); -+ -+ WriteDOC(0, docptr, Mplus_FlashControl); -+ DoC_WaitReady(docptr); -+ -+ /* Read the manufacturer and device id codes of the flash device through -+ CDSN IO register see Software Requirement 11.4 item 5.*/ -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ -+ mfr = ReadDOC(docptr, Mil_CDSN_IO); -+ if (doc->interleave) -+ dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */ -+ -+ id = ReadDOC(docptr, Mil_CDSN_IO); -+ if (doc->interleave) -+ dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */ -+ -+ dummy = ReadDOC(docptr, Mplus_LastDataRead); -+ dummy = ReadDOC(docptr, Mplus_LastDataRead); -+ -+ /* Disable flash internally */ -+ WriteDOC(0, docptr, Mplus_FlashSelect); -+ -+ /* No response - return failure */ -+ if (mfr == 0xff || mfr == 0) -+ return 0; -+ -+ for (i = 0; nand_flash_ids[i].name != NULL; i++) { -+ if (id == nand_flash_ids[i].id) { -+ /* Try to identify manufacturer */ -+ for (j = 0; nand_manuf_ids[j].id != 0x0; j++) { -+ if (nand_manuf_ids[j].id == mfr) -+ break; -+ } -+ printk(KERN_INFO "Flash chip found: Manufacturer ID: %2.2X, " -+ "Chip ID: %2.2X (%s:%s)\n", mfr, id, -+ nand_manuf_ids[j].name, nand_flash_ids[i].name); -+ doc->mfr = mfr; -+ doc->id = id; -+ doc->chipshift = nand_flash_ids[i].chipshift; -+ doc->erasesize = nand_flash_ids[i].erasesize << doc->interleave; -+ break; -+ } -+ } -+ -+ if (nand_flash_ids[i].name == NULL) -+ return 0; -+ return 1; -+} -+ -+/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */ -+static void DoC_ScanChips(struct DiskOnChip *this) -+{ -+ int floor, chip; -+ int numchips[MAX_FLOORS_MPLUS]; -+ int ret; -+ -+ this->numchips = 0; -+ this->mfr = 0; -+ this->id = 0; -+ -+ /* Work out the intended interleave setting */ -+ this->interleave = 0; -+ if (this->ChipID == DOC_ChipID_DocMilPlus32) -+ this->interleave = 1; -+ -+ /* Check the ASIC agrees */ -+ if ( (this->interleave << 2) != -+ (ReadDOC(this->virtadr, Mplus_Configuration) & 4)) { -+ u_char conf = ReadDOC(this->virtadr, Mplus_Configuration); -+ printk(KERN_NOTICE "Setting DiskOnChip Millennium Plus interleave to %s\n", -+ this->interleave?"on (16-bit)":"off (8-bit)"); -+ conf ^= 4; -+ WriteDOC(this->virtadr, conf, Mplus_Configuration); -+ } -+ -+ /* For each floor, find the number of valid chips it contains */ -+ for (floor = 0,ret = 1; floor < MAX_FLOORS_MPLUS; floor++) { -+ numchips[floor] = 0; -+ for (chip = 0; chip < MAX_CHIPS_MPLUS && ret != 0; chip++) { -+ ret = DoC_IdentChip(this, floor, chip); -+ if (ret) { -+ numchips[floor]++; -+ this->numchips++; -+ } -+ } -+ } -+ /* If there are none at all that we recognise, bail */ -+ if (!this->numchips) { -+ printk("No flash chips recognised.\n"); -+ return; -+ } -+ -+ /* Allocate an array to hold the information for each chip */ -+ this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL); -+ if (!this->chips){ -+ printk("MTD: No memory for allocating chip info structures\n"); -+ return; -+ } -+ -+ /* Fill out the chip array with {floor, chipno} for each -+ * detected chip in the device. */ -+ for (floor = 0, ret = 0; floor < MAX_FLOORS_MPLUS; floor++) { -+ for (chip = 0 ; chip < numchips[floor] ; chip++) { -+ this->chips[ret].floor = floor; -+ this->chips[ret].chip = chip; -+ this->chips[ret].curadr = 0; -+ this->chips[ret].curmode = 0x50; -+ ret++; -+ } -+ } -+ -+ /* Calculate and print the total size of the device */ -+ this->totlen = this->numchips * (1 << this->chipshift); -+ printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld MiB\n", -+ this->numchips ,this->totlen >> 20); -+} -+ -+static int DoCMilPlus_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2) -+{ -+ int tmp1, tmp2, retval; -+ -+ if (doc1->physadr == doc2->physadr) -+ return 1; -+ -+ /* Use the alias resolution register which was set aside for this -+ * purpose. If it's value is the same on both chips, they might -+ * be the same chip, and we write to one and check for a change in -+ * the other. It's unclear if this register is usuable in the -+ * DoC 2000 (it's in the Millennium docs), but it seems to work. */ -+ tmp1 = ReadDOC(doc1->virtadr, Mplus_AliasResolution); -+ tmp2 = ReadDOC(doc2->virtadr, Mplus_AliasResolution); -+ if (tmp1 != tmp2) -+ return 0; -+ -+ WriteDOC((tmp1+1) % 0xff, doc1->virtadr, Mplus_AliasResolution); -+ tmp2 = ReadDOC(doc2->virtadr, Mplus_AliasResolution); -+ if (tmp2 == (tmp1+1) % 0xff) -+ retval = 1; -+ else -+ retval = 0; -+ -+ /* Restore register contents. May not be necessary, but do it just to -+ * be safe. */ -+ WriteDOC(tmp1, doc1->virtadr, Mplus_AliasResolution); -+ -+ return retval; -+} -+ -+static const char im_name[] = "DoCMilPlus_init"; -+ -+/* This routine is made available to other mtd code via -+ * inter_module_register. It must only be accessed through -+ * inter_module_get which will bump the use count of this module. The -+ * addresses passed back in mtd are valid as long as the use count of -+ * this module is non-zero, i.e. between inter_module_get and -+ * inter_module_put. Keith Owens 29 Oct 2000. -+ */ -+static void DoCMilPlus_init(struct mtd_info *mtd) -+{ -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ struct DiskOnChip *old = NULL; -+ -+ /* We must avoid being called twice for the same device. */ -+ if (docmilpluslist) -+ old = (struct DiskOnChip *)docmilpluslist->priv; -+ -+ while (old) { -+ if (DoCMilPlus_is_alias(this, old)) { -+ printk(KERN_NOTICE "Ignoring DiskOnChip Millennium " -+ "Plus at 0x%lX - already configured\n", -+ this->physadr); -+ iounmap((void *)this->virtadr); -+ kfree(mtd); -+ return; -+ } -+ if (old->nextdoc) -+ old = (struct DiskOnChip *)old->nextdoc->priv; -+ else -+ old = NULL; -+ } -+ -+ mtd->name = "DiskOnChip Millennium Plus"; -+ printk(KERN_NOTICE "DiskOnChip Millennium Plus found at " -+ "address 0x%lX\n", this->physadr); -+ -+ mtd->type = MTD_NANDFLASH; -+ mtd->flags = MTD_CAP_NANDFLASH; -+ mtd->ecctype = MTD_ECC_RS_DiskOnChip; -+ mtd->size = 0; -+ -+ mtd->erasesize = 0; -+ mtd->oobblock = 512; -+ mtd->oobsize = 16; -+ mtd->owner = THIS_MODULE; -+ mtd->erase = doc_erase; -+ mtd->point = NULL; -+ mtd->unpoint = NULL; -+ mtd->read = doc_read; -+ mtd->write = doc_write; -+ mtd->read_ecc = doc_read_ecc; -+ mtd->write_ecc = doc_write_ecc; -+ mtd->read_oob = doc_read_oob; -+ mtd->write_oob = doc_write_oob; -+ mtd->sync = NULL; -+ -+ this->totlen = 0; -+ this->numchips = 0; -+ this->curfloor = -1; -+ this->curchip = -1; -+ -+ /* Ident all the chips present. */ -+ DoC_ScanChips(this); -+ -+ if (!this->totlen) { -+ kfree(mtd); -+ iounmap((void *)this->virtadr); -+ } else { -+ this->nextdoc = docmilpluslist; -+ docmilpluslist = mtd; -+ mtd->size = this->totlen; -+ mtd->erasesize = this->erasesize; -+ add_mtd_device(mtd); -+ return; -+ } -+} -+ -+#if 0 -+static int doc_dumpblk(struct mtd_info *mtd, loff_t from) -+{ -+ int i; -+ loff_t fofs; -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ unsigned long docptr = this->virtadr; -+ struct Nand *mychip = &this->chips[from >> (this->chipshift)]; -+ unsigned char *bp, buf[1056]; -+ char c[32]; -+ -+ from &= ~0x3ff; -+ -+ /* Don't allow read past end of device */ -+ if (from >= this->totlen) -+ return -EINVAL; -+ -+ DoC_CheckASIC(docptr); -+ -+ /* Find the chip which is to be used and select it */ -+ if (this->curfloor != mychip->floor) { -+ DoC_SelectFloor(docptr, mychip->floor); -+ DoC_SelectChip(docptr, mychip->chip); -+ } else if (this->curchip != mychip->chip) { -+ DoC_SelectChip(docptr, mychip->chip); -+ } -+ this->curfloor = mychip->floor; -+ this->curchip = mychip->chip; -+ -+ /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ -+ WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect); -+ -+ /* Reset the chip, see Software Requirement 11.4 item 1. */ -+ DoC_Command(docptr, NAND_CMD_RESET, 0); -+ DoC_WaitReady(docptr); -+ -+ fofs = from; -+ DoC_Command(docptr, DoC_GetDataOffset(mtd, &fofs), 0); -+ DoC_Address(this, 3, fofs, 0, 0x00); -+ WriteDOC(0, docptr, Mplus_FlashControl); -+ DoC_WaitReady(docptr); -+ -+ /* disable the ECC engine */ -+ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); -+ -+ ReadDOC(docptr, Mplus_ReadPipeInit); -+ ReadDOC(docptr, Mplus_ReadPipeInit); -+ -+ /* Read the data via the internal pipeline through CDSN IO -+ register, see Pipelined Read Operations 11.3 */ -+ MemReadDOC(docptr, buf, 1054); -+ buf[1054] = ReadDOC(docptr, Mplus_LastDataRead); -+ buf[1055] = ReadDOC(docptr, Mplus_LastDataRead); -+ -+ memset(&c[0], 0, sizeof(c)); -+ printk("DUMP OFFSET=%x:\n", (int)from); -+ -+ for (i = 0, bp = &buf[0]; (i < 1056); i++) { -+ if ((i % 16) == 0) -+ printk("%08x: ", i); -+ printk(" %02x", *bp); -+ c[(i & 0xf)] = ((*bp >= 0x20) && (*bp <= 0x7f)) ? *bp : '.'; -+ bp++; -+ if (((i + 1) % 16) == 0) -+ printk(" %s\n", c); -+ } -+ printk("\n"); -+ -+ /* Disable flash internally */ -+ WriteDOC(0, docptr, Mplus_FlashSelect); -+ -+ return 0; -+} -+#endif -+ -+static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ /* Just a special case of doc_read_ecc */ -+ return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL); -+} -+ -+static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf, u_char *eccbuf, -+ struct nand_oobinfo *oobsel) -+{ -+ int ret, i; -+ volatile char dummy; -+ loff_t fofs; -+ unsigned char syndrome[6]; -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ unsigned long docptr = this->virtadr; -+ struct Nand *mychip = &this->chips[from >> (this->chipshift)]; -+ -+ /* Don't allow read past end of device */ -+ if (from >= this->totlen) -+ return -EINVAL; -+ -+ /* Don't allow a single read to cross a 512-byte block boundary */ -+ if (from + len > ((from | 0x1ff) + 1)) -+ len = ((from | 0x1ff) + 1) - from; -+ -+ DoC_CheckASIC(docptr); -+ -+ /* Find the chip which is to be used and select it */ -+ if (this->curfloor != mychip->floor) { -+ DoC_SelectFloor(docptr, mychip->floor); -+ DoC_SelectChip(docptr, mychip->chip); -+ } else if (this->curchip != mychip->chip) { -+ DoC_SelectChip(docptr, mychip->chip); -+ } -+ this->curfloor = mychip->floor; -+ this->curchip = mychip->chip; -+ -+ /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ -+ WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect); -+ -+ /* Reset the chip, see Software Requirement 11.4 item 1. */ -+ DoC_Command(docptr, NAND_CMD_RESET, 0); -+ DoC_WaitReady(docptr); -+ -+ fofs = from; -+ DoC_Command(docptr, DoC_GetDataOffset(mtd, &fofs), 0); -+ DoC_Address(this, 3, fofs, 0, 0x00); -+ WriteDOC(0, docptr, Mplus_FlashControl); -+ DoC_WaitReady(docptr); -+ -+ if (eccbuf) { -+ /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ -+ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); -+ WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf); -+ } else { -+ /* disable the ECC engine */ -+ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); -+ } -+ -+ /* Let the caller know we completed it */ -+ *retlen = len; -+ ret = 0; -+ -+ ReadDOC(docptr, Mplus_ReadPipeInit); -+ ReadDOC(docptr, Mplus_ReadPipeInit); -+ -+ if (eccbuf) { -+ /* Read the data via the internal pipeline through CDSN IO -+ register, see Pipelined Read Operations 11.3 */ -+ MemReadDOC(docptr, buf, len); -+ -+ /* Read the ECC data following raw data */ -+ MemReadDOC(docptr, eccbuf, 4); -+ eccbuf[4] = ReadDOC(docptr, Mplus_LastDataRead); -+ eccbuf[5] = ReadDOC(docptr, Mplus_LastDataRead); -+ -+ /* Flush the pipeline */ -+ dummy = ReadDOC(docptr, Mplus_ECCConf); -+ dummy = ReadDOC(docptr, Mplus_ECCConf); -+ -+ /* Check the ECC Status */ -+ if (ReadDOC(docptr, Mplus_ECCConf) & 0x80) { -+ int nb_errors; -+ /* There was an ECC error */ -+#ifdef ECC_DEBUG -+ printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); -+#endif -+ /* Read the ECC syndrom through the DiskOnChip ECC logic. -+ These syndrome will be all ZERO when there is no error */ -+ for (i = 0; i < 6; i++) -+ syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); -+ -+ nb_errors = doc_decode_ecc(buf, syndrome); -+#ifdef ECC_DEBUG -+ printk("ECC Errors corrected: %x\n", nb_errors); -+#endif -+ if (nb_errors < 0) { -+ /* We return error, but have actually done the read. Not that -+ this can be told to user-space, via sys_read(), but at least -+ MTD-aware stuff can know about it by checking *retlen */ -+#ifdef ECC_DEBUG -+ printk("%s(%d): Millennium Plus ECC error (from=0x%x:\n", -+ __FILE__, __LINE__, (int)from); -+ printk(" syndrome= %02x:%02x:%02x:%02x:%02x:" -+ "%02x\n", -+ syndrome[0], syndrome[1], syndrome[2], -+ syndrome[3], syndrome[4], syndrome[5]); -+ printk(" eccbuf= %02x:%02x:%02x:%02x:%02x:" -+ "%02x\n", -+ eccbuf[0], eccbuf[1], eccbuf[2], -+ eccbuf[3], eccbuf[4], eccbuf[5]); -+#endif -+ ret = -EIO; -+ } -+ } -+ -+#ifdef PSYCHO_DEBUG -+ printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", -+ (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], -+ eccbuf[4], eccbuf[5]); -+#endif -+ -+ /* disable the ECC engine */ -+ WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf); -+ } else { -+ /* Read the data via the internal pipeline through CDSN IO -+ register, see Pipelined Read Operations 11.3 */ -+ MemReadDOC(docptr, buf, len-2); -+ buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead); -+ buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead); -+ } -+ -+ /* Disable flash internally */ -+ WriteDOC(0, docptr, Mplus_FlashSelect); -+ -+ return ret; -+} -+ -+static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ char eccbuf[6]; -+ return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL); -+} -+ -+static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf, u_char *eccbuf, -+ struct nand_oobinfo *oobsel) -+{ -+ int i, before, ret = 0; -+ loff_t fto; -+ volatile char dummy; -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ unsigned long docptr = this->virtadr; -+ struct Nand *mychip = &this->chips[to >> (this->chipshift)]; -+ -+ /* Don't allow write past end of device */ -+ if (to >= this->totlen) -+ return -EINVAL; -+ -+ /* Don't allow writes which aren't exactly one block (512 bytes) */ -+ if ((to & 0x1ff) || (len != 0x200)) -+ return -EINVAL; -+ -+ /* Determine position of OOB flags, before or after data */ -+ before = (this->interleave && (to & 0x200)); -+ -+ DoC_CheckASIC(docptr); -+ -+ /* Find the chip which is to be used and select it */ -+ if (this->curfloor != mychip->floor) { -+ DoC_SelectFloor(docptr, mychip->floor); -+ DoC_SelectChip(docptr, mychip->chip); -+ } else if (this->curchip != mychip->chip) { -+ DoC_SelectChip(docptr, mychip->chip); -+ } -+ this->curfloor = mychip->floor; -+ this->curchip = mychip->chip; -+ -+ /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ -+ WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect); -+ -+ /* Reset the chip, see Software Requirement 11.4 item 1. */ -+ DoC_Command(docptr, NAND_CMD_RESET, 0); -+ DoC_WaitReady(docptr); -+ -+ /* Set device to appropriate plane of flash */ -+ fto = to; -+ WriteDOC(DoC_GetDataOffset(mtd, &fto), docptr, Mplus_FlashCmd); -+ -+ /* On interleaved devices the flags for 2nd half 512 are before data */ -+ if (eccbuf && before) -+ fto -= 2; -+ -+ /* issue the Serial Data In command to initial the Page Program process */ -+ DoC_Command(docptr, NAND_CMD_SEQIN, 0x00); -+ DoC_Address(this, 3, fto, 0x00, 0x00); -+ -+ /* Disable the ECC engine */ -+ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); -+ -+ if (eccbuf) { -+ if (before) { -+ /* Write the block status BLOCK_USED (0x5555) */ -+ WriteDOC(0x55, docptr, Mil_CDSN_IO); -+ WriteDOC(0x55, docptr, Mil_CDSN_IO); -+ } -+ -+ /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ -+ WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf); -+ } -+ -+ MemWriteDOC(docptr, (unsigned char *) buf, len); -+ -+ if (eccbuf) { -+ /* Write ECC data to flash, the ECC info is generated by -+ the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */ -+ DoC_Delay(docptr, 3); -+ -+ /* Read the ECC data through the DiskOnChip ECC logic */ -+ for (i = 0; i < 6; i++) -+ eccbuf[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); -+ -+ /* disable the ECC engine */ -+ WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); -+ -+ /* Write the ECC data to flash */ -+ MemWriteDOC(docptr, eccbuf, 6); -+ -+ if (!before) { -+ /* Write the block status BLOCK_USED (0x5555) */ -+ WriteDOC(0x55, docptr, Mil_CDSN_IO+6); -+ WriteDOC(0x55, docptr, Mil_CDSN_IO+7); -+ } -+ -+#ifdef PSYCHO_DEBUG -+ printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", -+ (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], -+ eccbuf[4], eccbuf[5]); -+#endif -+ } -+ -+ WriteDOC(0x00, docptr, Mplus_WritePipeTerm); -+ WriteDOC(0x00, docptr, Mplus_WritePipeTerm); -+ -+ /* Commit the Page Program command and wait for ready -+ see Software Requirement 11.4 item 1.*/ -+ DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00); -+ DoC_WaitReady(docptr); -+ -+ /* Read the status of the flash device through CDSN IO register -+ see Software Requirement 11.4 item 5.*/ -+ DoC_Command(docptr, NAND_CMD_STATUS, 0); -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ DoC_Delay(docptr, 2); -+ if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) { -+ printk("MTD: Error 0x%x programming at 0x%x\n", dummy, (int)to); -+ /* Error in programming -+ FIXME: implement Bad Block Replacement (in nftl.c ??) */ -+ *retlen = 0; -+ ret = -EIO; -+ } -+ dummy = ReadDOC(docptr, Mplus_LastDataRead); -+ -+ /* Disable flash internally */ -+ WriteDOC(0, docptr, Mplus_FlashSelect); -+ -+ /* Let the caller know we completed it */ -+ *retlen = len; -+ -+ return ret; -+} -+ -+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ loff_t fofs, base; -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ unsigned long docptr = this->virtadr; -+ struct Nand *mychip = &this->chips[ofs >> this->chipshift]; -+ size_t i, size, got, want; -+ -+ DoC_CheckASIC(docptr); -+ -+ /* Find the chip which is to be used and select it */ -+ if (this->curfloor != mychip->floor) { -+ DoC_SelectFloor(docptr, mychip->floor); -+ DoC_SelectChip(docptr, mychip->chip); -+ } else if (this->curchip != mychip->chip) { -+ DoC_SelectChip(docptr, mychip->chip); -+ } -+ this->curfloor = mychip->floor; -+ this->curchip = mychip->chip; -+ -+ /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ -+ WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect); -+ -+ /* disable the ECC engine */ -+ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); -+ DoC_WaitReady(docptr); -+ -+ /* Maximum of 16 bytes in the OOB region, so limit read to that */ -+ if (len > 16) -+ len = 16; -+ got = 0; -+ want = len; -+ -+ for (i = 0; ((i < 3) && (want > 0)); i++) { -+ /* Figure out which region we are accessing... */ -+ fofs = ofs; -+ base = ofs & 0xf; -+ if (!this->interleave) { -+ DoC_Command(docptr, NAND_CMD_READOOB, 0); -+ size = 16 - base; -+ } else if (base < 6) { -+ DoC_Command(docptr, DoC_GetECCOffset(mtd, &fofs), 0); -+ size = 6 - base; -+ } else if (base < 8) { -+ DoC_Command(docptr, DoC_GetFlagsOffset(mtd, &fofs), 0); -+ size = 8 - base; -+ } else { -+ DoC_Command(docptr, DoC_GetHdrOffset(mtd, &fofs), 0); -+ size = 16 - base; -+ } -+ if (size > want) -+ size = want; -+ -+ /* Issue read command */ -+ DoC_Address(this, 3, fofs, 0, 0x00); -+ WriteDOC(0, docptr, Mplus_FlashControl); -+ DoC_WaitReady(docptr); -+ -+ ReadDOC(docptr, Mplus_ReadPipeInit); -+ ReadDOC(docptr, Mplus_ReadPipeInit); -+ MemReadDOC(docptr, &buf[got], size - 2); -+ buf[got + size - 2] = ReadDOC(docptr, Mplus_LastDataRead); -+ buf[got + size - 1] = ReadDOC(docptr, Mplus_LastDataRead); -+ -+ ofs += size; -+ got += size; -+ want -= size; -+ } -+ -+ /* Disable flash internally */ -+ WriteDOC(0, docptr, Mplus_FlashSelect); -+ -+ *retlen = len; -+ return 0; -+} -+ -+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ volatile char dummy; -+ loff_t fofs, base; -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ unsigned long docptr = this->virtadr; -+ struct Nand *mychip = &this->chips[ofs >> this->chipshift]; -+ size_t i, size, got, want; -+ int ret = 0; -+ -+ DoC_CheckASIC(docptr); -+ -+ /* Find the chip which is to be used and select it */ -+ if (this->curfloor != mychip->floor) { -+ DoC_SelectFloor(docptr, mychip->floor); -+ DoC_SelectChip(docptr, mychip->chip); -+ } else if (this->curchip != mychip->chip) { -+ DoC_SelectChip(docptr, mychip->chip); -+ } -+ this->curfloor = mychip->floor; -+ this->curchip = mychip->chip; -+ -+ /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ -+ WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect); -+ -+ -+ /* Maximum of 16 bytes in the OOB region, so limit write to that */ -+ if (len > 16) -+ len = 16; -+ got = 0; -+ want = len; -+ -+ for (i = 0; ((i < 3) && (want > 0)); i++) { -+ /* Reset the chip, see Software Requirement 11.4 item 1. */ -+ DoC_Command(docptr, NAND_CMD_RESET, 0); -+ DoC_WaitReady(docptr); -+ -+ /* Figure out which region we are accessing... */ -+ fofs = ofs; -+ base = ofs & 0x0f; -+ if (!this->interleave) { -+ WriteDOC(NAND_CMD_READOOB, docptr, Mplus_FlashCmd); -+ size = 16 - base; -+ } else if (base < 6) { -+ WriteDOC(DoC_GetECCOffset(mtd, &fofs), docptr, Mplus_FlashCmd); -+ size = 6 - base; -+ } else if (base < 8) { -+ WriteDOC(DoC_GetFlagsOffset(mtd, &fofs), docptr, Mplus_FlashCmd); -+ size = 8 - base; -+ } else { -+ WriteDOC(DoC_GetHdrOffset(mtd, &fofs), docptr, Mplus_FlashCmd); -+ size = 16 - base; -+ } -+ if (size > want) -+ size = want; -+ -+ /* Issue the Serial Data In command to initial the Page Program process */ -+ DoC_Command(docptr, NAND_CMD_SEQIN, 0x00); -+ DoC_Address(this, 3, fofs, 0, 0x00); -+ -+ /* Disable the ECC engine */ -+ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); -+ -+ /* Write the data via the internal pipeline through CDSN IO -+ register, see Pipelined Write Operations 11.2 */ -+ MemWriteDOC(docptr, (unsigned char *) &buf[got], size); -+ WriteDOC(0x00, docptr, Mplus_WritePipeTerm); -+ WriteDOC(0x00, docptr, Mplus_WritePipeTerm); -+ -+ /* Commit the Page Program command and wait for ready -+ see Software Requirement 11.4 item 1.*/ -+ DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00); -+ DoC_WaitReady(docptr); -+ -+ /* Read the status of the flash device through CDSN IO register -+ see Software Requirement 11.4 item 5.*/ -+ DoC_Command(docptr, NAND_CMD_STATUS, 0x00); -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ DoC_Delay(docptr, 2); -+ if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) { -+ printk("MTD: Error 0x%x programming oob at 0x%x\n", -+ dummy, (int)ofs); -+ /* FIXME: implement Bad Block Replacement */ -+ *retlen = 0; -+ ret = -EIO; -+ } -+ dummy = ReadDOC(docptr, Mplus_LastDataRead); -+ -+ ofs += size; -+ got += size; -+ want -= size; -+ } -+ -+ /* Disable flash internally */ -+ WriteDOC(0, docptr, Mplus_FlashSelect); -+ -+ *retlen = len; -+ return ret; -+} -+ -+int doc_erase(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ volatile char dummy; -+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; -+ __u32 ofs = instr->addr; -+ __u32 len = instr->len; -+ unsigned long docptr = this->virtadr; -+ struct Nand *mychip = &this->chips[ofs >> this->chipshift]; -+ -+ DoC_CheckASIC(docptr); -+ -+ if (len != mtd->erasesize) -+ printk(KERN_WARNING "MTD: Erase not right size (%x != %x)n", -+ len, mtd->erasesize); -+ -+ /* Find the chip which is to be used and select it */ -+ if (this->curfloor != mychip->floor) { -+ DoC_SelectFloor(docptr, mychip->floor); -+ DoC_SelectChip(docptr, mychip->chip); -+ } else if (this->curchip != mychip->chip) { -+ DoC_SelectChip(docptr, mychip->chip); -+ } -+ this->curfloor = mychip->floor; -+ this->curchip = mychip->chip; -+ -+ instr->state = MTD_ERASE_PENDING; -+ -+ /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */ -+ WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect); -+ -+ DoC_Command(docptr, NAND_CMD_RESET, 0x00); -+ DoC_WaitReady(docptr); -+ -+ DoC_Command(docptr, NAND_CMD_ERASE1, 0); -+ DoC_Address(this, 2, ofs, 0, 0x00); -+ DoC_Command(docptr, NAND_CMD_ERASE2, 0); -+ DoC_WaitReady(docptr); -+ instr->state = MTD_ERASING; -+ -+ /* Read the status of the flash device through CDSN IO register -+ see Software Requirement 11.4 item 5. */ -+ DoC_Command(docptr, NAND_CMD_STATUS, 0); -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ dummy = ReadDOC(docptr, Mplus_ReadPipeInit); -+ if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) { -+ printk("MTD: Error 0x%x erasing at 0x%x\n", dummy, ofs); -+ /* FIXME: implement Bad Block Replacement (in nftl.c ??) */ -+ instr->state = MTD_ERASE_FAILED; -+ } else { -+ instr->state = MTD_ERASE_DONE; -+ } -+ dummy = ReadDOC(docptr, Mplus_LastDataRead); -+ -+ /* Disable flash internally */ -+ WriteDOC(0, docptr, Mplus_FlashSelect); -+ -+ if (instr->callback) -+ instr->callback(instr); -+ -+ return 0; -+} -+ -+/**************************************************************************** -+ * -+ * Module stuff -+ * -+ ****************************************************************************/ -+ -+int __init init_doc2001plus(void) -+{ -+ inter_module_register(im_name, THIS_MODULE, &DoCMilPlus_init); -+ return 0; -+} -+ -+static void __exit cleanup_doc2001plus(void) -+{ -+ struct mtd_info *mtd; -+ struct DiskOnChip *this; -+ -+ while ((mtd=docmilpluslist)) { -+ this = (struct DiskOnChip *)mtd->priv; -+ docmilpluslist = this->nextdoc; -+ -+ del_mtd_device(mtd); -+ -+ iounmap((void *)this->virtadr); -+ kfree(this->chips); -+ kfree(mtd); -+ } -+ inter_module_unregister(im_name); -+} -+ -+module_exit(cleanup_doc2001plus); -+module_init(init_doc2001plus); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Greg Ungerer et al."); -+MODULE_DESCRIPTION("Driver for DiskOnChip Millennium Plus"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/devices/docecc.c linux/drivers/mtd/devices/docecc.c ---- linux-mips-2.4.27/drivers/mtd/devices/docecc.c 2001-11-05 21:15:52.000000000 +0100 -+++ linux/drivers/mtd/devices/docecc.c 2004-11-19 10:25:11.851207088 +0100 -@@ -7,7 +7,7 @@ - * Author: Fabrice Bellard (fabrice.bellard@netgem.com) - * Copyright (C) 2000 Netgem S.A. - * -- * $Id$ -+ * $Id$ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -519,6 +519,8 @@ - return nb_errors; - } - -+EXPORT_SYMBOL_GPL(doc_decode_ecc); -+ - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Fabrice Bellard "); - MODULE_DESCRIPTION("ECC code for correcting errors detected by DiskOnChip 2000 and Millennium ECC hardware"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/devices/docprobe.c linux/drivers/mtd/devices/docprobe.c ---- linux-mips-2.4.27/drivers/mtd/devices/docprobe.c 2003-06-16 01:42:21.000000000 +0200 -+++ linux/drivers/mtd/devices/docprobe.c 2004-11-19 10:25:11.853206784 +0100 -@@ -4,7 +4,7 @@ - /* (C) 1999 Machine Vision Holdings, Inc. */ - /* (C) 1999-2003 David Woodhouse */ - --/* $Id$ */ -+/* $Id$ */ - - - -@@ -31,14 +31,12 @@ - /* DOC_SINGLE_DRIVER: - Millennium driver has been merged into DOC2000 driver. - -- The newly-merged driver doesn't appear to work for writing. It's the -- same with the DiskOnChip 2000 and the Millennium. If you have a -- Millennium and you want write support to work, remove the definition -- of DOC_SINGLE_DRIVER below to use the old doc2001-specific driver. -- -- Otherwise, it's left on in the hope that it'll annoy someone with -- a Millennium enough that they go through and work out what the -- difference is :) -+ The old Millennium-only driver has been retained just in case there -+ are problems with the new code. If the combined driver doesn't work -+ for you, you can try the old one by undefining DOC_SINGLE_DRIVER -+ below and also enabling it in your configuration. If this fixes the -+ problems, please send a report to the MTD mailing list at -+ . - */ - #define DOC_SINGLE_DRIVER - -@@ -47,18 +45,15 @@ - #include - #include - #include --#include --#include --#include - #include - #include --#include - #include - #include - - #include - #include - #include -+#include - - /* Where to look for the devices? */ - #ifndef CONFIG_MTD_DOCPROBE_ADDRESS -@@ -92,17 +87,17 @@ - 0xff000000, - #elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C) - 0xff000000, --#else -+##else - #warning Unknown architecture for DiskOnChip. No default probe locations defined - #endif -- 0 }; -+ 0xffffffff }; - - /* doccheck: Probe a given memory window to see if there's a DiskOnChip present */ - - static inline int __init doccheck(unsigned long potential, unsigned long physadr) - { - unsigned long window=potential; -- unsigned char tmp, ChipID; -+ unsigned char tmp, tmpb, tmpc, ChipID; - #ifndef DOC_PASSIVE_PROBE - unsigned char tmp2; - #endif -@@ -140,26 +135,80 @@ - window, DOCControl); - #endif /* !DOC_PASSIVE_PROBE */ - -+ /* We need to read the ChipID register four times. For some -+ newer DiskOnChip 2000 units, the first three reads will -+ return the DiskOnChip Millennium ident. Don't ask. */ - ChipID = ReadDOC(window, ChipID); - - switch (ChipID) { - case DOC_ChipID_Doc2k: - /* Check the TOGGLE bit in the ECC register */ - tmp = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT; -- if ((ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT) != tmp) -+ tmpb = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT; -+ tmpc = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT; -+ if (tmp != tmpb && tmp == tmpc) - return ChipID; - break; - - case DOC_ChipID_DocMil: -+ /* Check for the new 2000 with Millennium ASIC */ -+ ReadDOC(window, ChipID); -+ ReadDOC(window, ChipID); -+ if (ReadDOC(window, ChipID) != DOC_ChipID_DocMil) -+ ChipID = DOC_ChipID_Doc2kTSOP; -+ - /* Check the TOGGLE bit in the ECC register */ - tmp = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT; -- if ((ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT) != tmp) -+ tmpb = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT; -+ tmpc = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT; -+ if (tmp != tmpb && tmp == tmpc) -+ return ChipID; -+ break; -+ -+ case DOC_ChipID_DocMilPlus16: -+ case DOC_ChipID_DocMilPlus32: -+ case 0: -+ /* Possible Millennium+, need to do more checks */ -+#ifndef DOC_PASSIVE_PROBE -+ /* Possibly release from power down mode */ -+ for (tmp = 0; (tmp < 4); tmp++) -+ ReadDOC(window, Mplus_Power); -+ -+ /* Reset the DiskOnChip ASIC */ -+ tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | -+ DOC_MODE_BDECT; -+ WriteDOC(tmp, window, Mplus_DOCControl); -+ WriteDOC(~tmp, window, Mplus_CtrlConfirm); -+ -+ mdelay(1); -+ /* Enable the DiskOnChip ASIC */ -+ tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | -+ DOC_MODE_BDECT; -+ WriteDOC(tmp, window, Mplus_DOCControl); -+ WriteDOC(~tmp, window, Mplus_CtrlConfirm); -+ mdelay(1); -+#endif /* !DOC_PASSIVE_PROBE */ -+ -+ ChipID = ReadDOC(window, ChipID); -+ -+ switch (ChipID) { -+ case DOC_ChipID_DocMilPlus16: -+ case DOC_ChipID_DocMilPlus32: -+ /* Check the TOGGLE bit in the toggle register */ -+ tmp = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT; -+ tmpb = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT; -+ tmpc = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT; -+ if (tmp != tmpb && tmp == tmpc) - return ChipID; -+ default: - break; -+ } -+ /* FALL TRHU */ - - default: --#ifndef CONFIG_MTD_DOCPROBE_55AA -- printk(KERN_WARNING "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n", -+ -+#ifdef CONFIG_MTD_DOCPROBE_55AA -+ printk(KERN_DEBUG "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n", - ChipID, physadr); - #endif - #ifndef DOC_PASSIVE_PROBE -@@ -200,6 +249,12 @@ - return; - - if ((ChipID = doccheck(docptr, physadr))) { -+ if (ChipID == DOC_ChipID_Doc2kTSOP) { -+ /* Remove this at your own peril. The hardware driver works but nothing prevents you from erasing bad blocks */ -+ printk(KERN_NOTICE "Refusing to drive DiskOnChip 2000 TSOP until Bad Block Table is correctly supported by INFTL\n"); -+ iounmap((void *)docptr); -+ return; -+ } - docfound = 1; - mtd = kmalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL); - -@@ -221,6 +276,12 @@ - sprintf(namebuf, "with ChipID %2.2X", ChipID); - - switch(ChipID) { -+ case DOC_ChipID_Doc2kTSOP: -+ name="2000 TSOP"; -+ im_funcname = "DoC2k_init"; -+ im_modname = "doc2000"; -+ break; -+ - case DOC_ChipID_Doc2k: - name="2000"; - im_funcname = "DoC2k_init"; -@@ -237,6 +298,13 @@ - im_modname = "doc2001"; - #endif /* DOC_SINGLE_DRIVER */ - break; -+ -+ case DOC_ChipID_DocMilPlus16: -+ case DOC_ChipID_DocMilPlus32: -+ name="MillenniumPlus"; -+ im_funcname = "DoCMilPlus_init"; -+ im_modname = "doc2001plus"; -+ break; - } - - if (im_funcname) -@@ -248,6 +316,7 @@ - return; - } - printk(KERN_NOTICE "Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr); -+ kfree(mtd); - } - iounmap((void *)docptr); - } -@@ -267,7 +336,7 @@ - printk(KERN_INFO "Using configured DiskOnChip probe address 0x%lx\n", doc_config_location); - DoC_Probe(doc_config_location); - } else { -- for (i=0; doc_locations[i]; i++) { -+ for (i=0; (doc_locations[i] != 0xffffffff); i++) { - DoC_Probe(doc_locations[i]); - } - } -@@ -275,11 +344,7 @@ - found, so the user knows we at least tried. */ - if (!docfound) - printk(KERN_INFO "No recognised DiskOnChip devices found\n"); -- /* So it looks like we've been used and we get unloaded */ -- MOD_INC_USE_COUNT; -- MOD_DEC_USE_COUNT; -- return 0; -- -+ return -EAGAIN; - } - - module_init(init_doc); -diff -Nurb linux-mips-2.4.27/drivers/mtd/devices/lart.c linux/drivers/mtd/devices/lart.c ---- linux-mips-2.4.27/drivers/mtd/devices/lart.c 2001-11-05 21:15:52.000000000 +0100 -+++ linux/drivers/mtd/devices/lart.c 2004-11-19 10:25:11.854206632 +0100 -@@ -2,7 +2,7 @@ - /* - * MTD driver for the 28F160F3 Flash Memory (non-CFI) on LART. - * -- * $Id$ -+ * $Id$ - * - * Author: Abraham vd Merwe - * -@@ -584,45 +584,40 @@ - - static struct mtd_info mtd; - --static struct mtd_erase_region_info erase_regions[] = --{ -+static struct mtd_erase_region_info erase_regions[] = { - /* parameter blocks */ - { -- offset: 0x00000000, -- erasesize: FLASH_BLOCKSIZE_PARAM, -- numblocks: FLASH_NUMBLOCKS_16m_PARAM -+ .offset = 0x00000000, -+ .erasesize = FLASH_BLOCKSIZE_PARAM, -+ .numblocks = FLASH_NUMBLOCKS_16m_PARAM, - }, - /* main blocks */ - { -- offset: FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM, -- erasesize: FLASH_BLOCKSIZE_MAIN, -- numblocks: FLASH_NUMBLOCKS_16m_MAIN -+ .offset = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM, -+ .erasesize = FLASH_BLOCKSIZE_MAIN, -+ .numblocks = FLASH_NUMBLOCKS_16m_MAIN, - } - }; - - #ifdef HAVE_PARTITIONS --static struct mtd_partition lart_partitions[] = --{ -+static struct mtd_partition lart_partitions[] = { - /* blob */ - { -- name: "blob", -- offset: BLOB_START, -- size: BLOB_LEN, -- mask_flags: 0 -+ .name = "blob", -+ .offset = BLOB_START, -+ .size = BLOB_LEN, - }, - /* kernel */ - { -- name: "kernel", -- offset: KERNEL_START, /* MTDPART_OFS_APPEND */ -- size: KERNEL_LEN, -- mask_flags: 0 -+ .name = "kernel", -+ .offset = KERNEL_START, /* MTDPART_OFS_APPEND */ -+ .size = KERNEL_LEN, - }, - /* initial ramdisk / file system */ - { -- name: "file system", -- offset: INITRD_START, /* MTDPART_OFS_APPEND */ -- size: INITRD_LEN, /* MTDPART_SIZ_FULL */ -- mask_flags: 0 -+ .name = "file system", -+ .offset = INITRD_START, /* MTDPART_OFS_APPEND */ -+ .size = INITRD_LEN, /* MTDPART_SIZ_FULL */ - } - }; - #endif -@@ -646,10 +641,10 @@ - mtd.erasesize = FLASH_BLOCKSIZE_MAIN; - mtd.numeraseregions = NB_OF (erase_regions); - mtd.eraseregions = erase_regions; -- mtd.module = THIS_MODULE; - mtd.erase = flash_erase; - mtd.read = flash_read; - mtd.write = flash_write; -+ mtd.owner = THIS_MODULE; - - #ifdef LART_DEBUG - printk (KERN_DEBUG -diff -Nurb linux-mips-2.4.27/drivers/mtd/devices/ms02-nv.c linux/drivers/mtd/devices/ms02-nv.c ---- linux-mips-2.4.27/drivers/mtd/devices/ms02-nv.c 2004-07-30 12:22:40.000000000 +0200 -+++ linux/drivers/mtd/devices/ms02-nv.c 2004-11-19 10:25:11.856206328 +0100 -@@ -6,7 +6,7 @@ - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * -- * $Id$ -+ * $Id$ - */ - - #include -@@ -31,7 +31,7 @@ - static char version[] __initdata = - "ms02-nv.c: v.1.0.0 13 Aug 2001 Maciej W. Rozycki.\n"; - --MODULE_AUTHOR("Maciej W. Rozycki "); -+MODULE_AUTHOR("Maciej W. Rozycki "); - MODULE_DESCRIPTION("DEC MS02-NV NVRAM module driver"); - MODULE_LICENSE("GPL"); - -@@ -222,7 +222,7 @@ - mtd->flags = MTD_CAP_RAM | MTD_XIP; - mtd->size = fixsize; - mtd->name = (char *)ms02nv_name; -- mtd->module = THIS_MODULE; -+ mtd->owner = THIS_MODULE; - mtd->read = ms02nv_read; - mtd->write = ms02nv_write; - -diff -Nurb linux-mips-2.4.27/drivers/mtd/devices/mtdram.c linux/drivers/mtd/devices/mtdram.c ---- linux-mips-2.4.27/drivers/mtd/devices/mtdram.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/devices/mtdram.c 2004-11-19 10:25:11.859205872 +0100 -@@ -1,6 +1,6 @@ - /* - * mtdram - a test mtd device -- * $Id$ -+ * $Id$ - * Author: Alexander Larsson - * - * Copyright (c) 1999 Alexander Larsson -@@ -13,6 +13,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - -@@ -136,7 +138,7 @@ - mtd->erasesize = MTDRAM_ERASE_SIZE; - mtd->priv = mapped_address; - -- mtd->module = THIS_MODULE; -+ mtd->owner = THIS_MODULE; - mtd->erase = ram_erase; - mtd->point = ram_point; - mtd->unpoint = ram_unpoint; -diff -Nurb linux-mips-2.4.27/drivers/mtd/devices/phram.c linux/drivers/mtd/devices/phram.c ---- linux-mips-2.4.27/drivers/mtd/devices/phram.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/devices/phram.c 2004-11-19 10:25:11.860205720 +0100 -@@ -0,0 +1,362 @@ -+/** -+ * -+ * $Id$ -+ * -+ * Copyright (c) Jochen Schaeuble -+ * 07/2003 rewritten by Joern Engel -+ * -+ * DISCLAIMER: This driver makes use of Rusty's excellent module code, -+ * so it will not work for 2.4 without changes and it wont work for 2.4 -+ * as a module without major changes. Oh well! -+ * -+ * Usage: -+ * -+ * one commend line parameter per device, each in the form: -+ * phram=,, -+ * may be up to 63 characters. -+ * and can be octal, decimal or hexadecimal. If followed -+ * by "k", "M" or "G", the numbers will be interpreted as kilo, mega or -+ * gigabytes. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define ERROR(fmt, args...) printk(KERN_ERR "phram: " fmt , ## args) -+ -+struct phram_mtd_list { -+ struct list_head list; -+ struct mtd_info *mtdinfo; -+}; -+ -+static LIST_HEAD(phram_list); -+ -+ -+ -+int phram_erase(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ u_char *start = (u_char *)mtd->priv; -+ -+ if (instr->addr + instr->len > mtd->size) -+ return -EINVAL; -+ -+ memset(start + instr->addr, 0xff, instr->len); -+ -+ /* This'll catch a few races. Free the thing before returning :) -+ * I don't feel at all ashamed. This kind of thing is possible anyway -+ * with flash, but unlikely. -+ */ -+ -+ instr->state = MTD_ERASE_DONE; -+ -+ if (instr->callback) -+ (*(instr->callback))(instr); -+ else -+ kfree(instr); -+ -+ return 0; -+} -+ -+int phram_point(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char **mtdbuf) -+{ -+ u_char *start = (u_char *)mtd->priv; -+ -+ if (from + len > mtd->size) -+ return -EINVAL; -+ -+ *mtdbuf = start + from; -+ *retlen = len; -+ return 0; -+} -+ -+void phram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) -+{ -+} -+ -+int phram_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ u_char *start = (u_char *)mtd->priv; -+ -+ if (from + len > mtd->size) -+ return -EINVAL; -+ -+ memcpy(buf, start + from, len); -+ -+ *retlen = len; -+ return 0; -+} -+ -+int phram_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ u_char *start = (u_char *)mtd->priv; -+ -+ if (to + len > mtd->size) -+ return -EINVAL; -+ -+ memcpy(start + to, buf, len); -+ -+ *retlen = len; -+ return 0; -+} -+ -+ -+ -+static void unregister_devices(void) -+{ -+ struct phram_mtd_list *this; -+ -+ list_for_each_entry(this, &phram_list, list) { -+ del_mtd_device(this->mtdinfo); -+ iounmap(this->mtdinfo->priv); -+ kfree(this->mtdinfo); -+ kfree(this); -+ } -+} -+ -+static int register_device(char *name, unsigned long start, unsigned long len) -+{ -+ struct phram_mtd_list *new; -+ int ret = -ENOMEM; -+ -+ new = kmalloc(sizeof(*new), GFP_KERNEL); -+ if (!new) -+ goto out0; -+ -+ new->mtdinfo = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); -+ if (!new->mtdinfo) -+ goto out1; -+ -+ memset(new->mtdinfo, 0, sizeof(struct mtd_info)); -+ -+ ret = -EIO; -+ new->mtdinfo->priv = ioremap(start, len); -+ if (!new->mtdinfo->priv) { -+ ERROR("ioremap failed\n"); -+ goto out2; -+ } -+ -+ -+ new->mtdinfo->name = name; -+ new->mtdinfo->size = len; -+ new->mtdinfo->flags = MTD_CAP_RAM | MTD_ERASEABLE | MTD_VOLATILE; -+ new->mtdinfo->erase = phram_erase; -+ new->mtdinfo->point = phram_point; -+ new->mtdinfo->unpoint = phram_unpoint; -+ new->mtdinfo->read = phram_read; -+ new->mtdinfo->write = phram_write; -+ new->mtdinfo->owner = THIS_MODULE; -+ new->mtdinfo->type = MTD_RAM; -+ new->mtdinfo->erasesize = 0x0; -+ -+ ret = -EAGAIN; -+ if (add_mtd_device(new->mtdinfo)) { -+ ERROR("Failed to register new device\n"); -+ goto out3; -+ } -+ -+ list_add_tail(&new->list, &phram_list); -+ return 0; -+ -+out3: -+ iounmap(new->mtdinfo->priv); -+out2: -+ kfree(new->mtdinfo); -+out1: -+ kfree(new); -+out0: -+ return ret; -+} -+ -+static int ustrtoul(const char *cp, char **endp, unsigned int base) -+{ -+ unsigned long result = simple_strtoul(cp, endp, base); -+ -+ switch (**endp) { -+ case 'G': -+ result *= 1024; -+ case 'M': -+ result *= 1024; -+ case 'k': -+ result *= 1024; -+ endp++; -+ } -+ return result; -+} -+ -+static int parse_num32(uint32_t *num32, const char *token) -+{ -+ char *endp; -+ unsigned long n; -+ -+ n = ustrtoul(token, &endp, 0); -+ if (*endp) -+ return -EINVAL; -+ -+ *num32 = n; -+ return 0; -+} -+ -+static int parse_name(char **pname, const char *token) -+{ -+ size_t len; -+ char *name; -+ -+ len = strlen(token) + 1; -+ if (len > 64) -+ return -ENOSPC; -+ -+ name = kmalloc(len, GFP_KERNEL); -+ if (!name) -+ return -ENOMEM; -+ -+ strcpy(name, token); -+ -+ *pname = name; -+ return 0; -+} -+ -+#define parse_err(fmt, args...) do { \ -+ ERROR(fmt , ## args); \ -+ return 0; \ -+} while (0) -+ -+static int phram_setup(const char *val, struct kernel_param *kp) -+{ -+ char buf[64+12+12], *str = buf; -+ char *token[3]; -+ char *name; -+ uint32_t start; -+ uint32_t len; -+ int i, ret; -+ -+ if (strnlen(val, sizeof(str)) >= sizeof(str)) -+ parse_err("parameter too long\n"); -+ -+ strcpy(str, val); -+ -+ for (i=0; i<3; i++) -+ token[i] = strsep(&str, ","); -+ -+ if (str) -+ parse_err("too many arguments\n"); -+ -+ if (!token[2]) -+ parse_err("not enough arguments\n"); -+ -+ ret = parse_name(&name, token[0]); -+ if (ret == -ENOMEM) -+ parse_err("out of memory\n"); -+ if (ret == -ENOSPC) -+ parse_err("name too long\n"); -+ if (ret) -+ return 0; -+ -+ ret = parse_num32(&start, token[1]); -+ if (ret) -+ parse_err("illegal start address\n"); -+ -+ ret = parse_num32(&len, token[2]); -+ if (ret) -+ parse_err("illegal device length\n"); -+ -+ register_device(name, start, len); -+ -+ return 0; -+} -+ -+module_param_call(phram, phram_setup, NULL, NULL, 000); -+MODULE_PARM_DESC(phram, "Memory region to map. \"map=,\""); -+ -+/* -+ * Just for compatibility with slram, this is horrible and should go someday. -+ */ -+static int __init slram_setup(const char *val, struct kernel_param *kp) -+{ -+ char buf[256], *str = buf; -+ -+ if (!val || !val[0]) -+ parse_err("no arguments to \"slram=\"\n"); -+ -+ if (strnlen(val, sizeof(str)) >= sizeof(str)) -+ parse_err("parameter too long\n"); -+ -+ strcpy(str, val); -+ -+ while (str) { -+ char *token[3]; -+ char *name; -+ uint32_t start; -+ uint32_t len; -+ int i, ret; -+ -+ for (i=0; i<3; i++) { -+ token[i] = strsep(&str, ","); -+ if (token[i]) -+ continue; -+ parse_err("wrong number of arguments to \"slram=\"\n"); -+ } -+ -+ /* name */ -+ ret = parse_name(&name, token[0]); -+ if (ret == -ENOMEM) -+ parse_err("of memory\n"); -+ if (ret == -ENOSPC) -+ parse_err("too long\n"); -+ if (ret) -+ return 1; -+ -+ /* start */ -+ ret = parse_num32(&start, token[1]); -+ if (ret) -+ parse_err("illegal start address\n"); -+ -+ /* len */ -+ if (token[2][0] == '+') -+ ret = parse_num32(&len, token[2] + 1); -+ else -+ ret = parse_num32(&len, token[2]); -+ -+ if (ret) -+ parse_err("illegal device length\n"); -+ -+ if (token[2][0] != '+') { -+ if (len < start) -+ parse_err("end < start\n"); -+ len -= start; -+ } -+ -+ register_device(name, start, len); -+ } -+ return 1; -+} -+ -+module_param_call(slram, slram_setup, NULL, NULL, 000); -+MODULE_PARM_DESC(slram, "List of memory regions to map. \"map=,\""); -+ -+ -+int __init init_phram(void) -+{ -+ printk(KERN_ERR "phram loaded\n"); -+ return 0; -+} -+ -+static void __exit cleanup_phram(void) -+{ -+ unregister_devices(); -+} -+ -+module_init(init_phram); -+module_exit(cleanup_phram); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jörn Engel "); -+MODULE_DESCRIPTION("MTD driver for physical RAM"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/devices/pmc551.c linux/drivers/mtd/devices/pmc551.c ---- linux-mips-2.4.27/drivers/mtd/devices/pmc551.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/devices/pmc551.c 2004-11-19 10:25:11.862205416 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * PMC551 PCI Mezzanine Ram Device - * -@@ -681,11 +681,6 @@ - - printk(KERN_INFO PMC551_VERSION); - -- if(!pci_present()) { -- printk(KERN_NOTICE "pmc551: PCI not enabled.\n"); -- return -ENODEV; -- } -- - /* - * PCU-bus chipset probe. - */ -@@ -787,10 +782,10 @@ - mtd->write = pmc551_write; - mtd->point = pmc551_point; - mtd->unpoint = pmc551_unpoint; -- mtd->module = THIS_MODULE; - mtd->type = MTD_RAM; - mtd->name = "PMC551 RAM board"; - mtd->erasesize = 0x10000; -+ mtd->owner = THIS_MODULE; - - if (add_mtd_device(mtd)) { - printk(KERN_NOTICE "pmc551: Failed to register new device\n"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/devices/slram.c linux/drivers/mtd/devices/slram.c ---- linux-mips-2.4.27/drivers/mtd/devices/slram.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/devices/slram.c 2004-11-19 10:25:11.863205264 +0100 -@@ -1,6 +1,6 @@ - /*====================================================================== - -- $Id$ -+ $Id$ - - This driver provides a method to access memory not used by the kernel - itself (i.e. if the kernel commandline mem=xxx is used). To actually -@@ -199,7 +199,7 @@ - (*curmtd)->mtdinfo->unpoint = slram_unpoint; - (*curmtd)->mtdinfo->read = slram_read; - (*curmtd)->mtdinfo->write = slram_write; -- (*curmtd)->mtdinfo->module = THIS_MODULE; -+ (*curmtd)->mtdinfo->owner = THIS_MODULE; - (*curmtd)->mtdinfo->type = MTD_RAM; - (*curmtd)->mtdinfo->erasesize = 0x0; - -diff -Nurb linux-mips-2.4.27/drivers/mtd/ftl.c linux/drivers/mtd/ftl.c ---- linux-mips-2.4.27/drivers/mtd/ftl.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/ftl.c 2004-11-19 10:25:11.630240680 +0100 -@@ -1,5 +1,5 @@ - /* This version ported to the Linux-MTD system by dwmw2@infradead.org -- * $Id$ -+ * $Id$ - * - * Fixes: Arnaldo Carvalho de Melo - * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups -@@ -55,8 +55,8 @@ - contact M-Systems (http://www.m-sys.com) directly. - - ======================================================================*/ -+#include - #include --#include - #include - /*#define PSYCHO_DEBUG */ - -@@ -68,43 +68,13 @@ - #include - #include - #include --#include -+#include - #include -- --#if (LINUX_VERSION_CODE >= 0x20100) - #include --#endif --#if (LINUX_VERSION_CODE >= 0x20303) - #include --#endif -+#include - - #include --/*====================================================================*/ --/* Stuff which really ought to be in compatmac.h */ -- --#if (LINUX_VERSION_CODE < 0x20328) --#define register_disk(dev, drive, minors, ops, size) \ -- do { (dev)->part[(drive)*(minors)].nr_sects = size; \ -- if (size == 0) (dev)->part[(drive)*(minors)].start_sect = -1; \ -- resetup_one_dev(dev, drive); } while (0) --#endif -- --#if (LINUX_VERSION_CODE < 0x20320) --#define BLK_DEFAULT_QUEUE(n) blk_dev[n].request_fn --#define blk_init_queue(q, req) q = (req) --#define blk_cleanup_queue(q) q = NULL --#define request_arg_t void --#else --#define request_arg_t request_queue_t *q --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14) --#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT --#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT --#else --#define BLK_INC_USE_COUNT do {} while(0) --#define BLK_DEC_USE_COUNT do {} while(0) --#endif - - /*====================================================================*/ - -@@ -119,19 +89,6 @@ - #define FTL_MAJOR 44 - #endif - --/* Funky stuff for setting up a block device */ --#define MAJOR_NR FTL_MAJOR --#define DEVICE_NAME "ftl" --#define DEVICE_REQUEST do_ftl_request --#define DEVICE_ON(device) --#define DEVICE_OFF(device) -- --#define DEVICE_NR(minor) ((minor)>>5) --#define REGION_NR(minor) (((minor)>>3)&3) --#define PART_NR(minor) ((minor)&7) --#define MINOR_NR(dev,reg,part) (((dev)<<5)+((reg)<<3)+(part)) -- --#include - - /*====================================================================*/ - -@@ -142,8 +99,7 @@ - #define MAX_REGION 4 - - /* Maximum number of partitions in an FTL region */ --#define PART_BITS 3 --#define MAX_PART 8 -+#define PART_BITS 4 - - /* Maximum number of outstanding erase requests per socket */ - #define MAX_ERASE 8 -@@ -154,7 +110,7 @@ - - /* Each memory region corresponds to a minor device */ - typedef struct partition_t { -- struct mtd_info *mtd; -+ struct mtd_blktrans_dev mbd; - u_int32_t state; - u_int32_t *VirtualBlockMap; - u_int32_t *VirtualPageMap; -@@ -179,21 +135,10 @@ - region_info_t region; - memory_handle_t handle; - #endif -- atomic_t open; - } partition_t; - --partition_t *myparts[MAX_MTD_DEVICES]; -- --static void ftl_notify_add(struct mtd_info *mtd); --static void ftl_notify_remove(struct mtd_info *mtd); -- - void ftl_freepart(partition_t *part); - --static struct mtd_notifier ftl_notifier = { -- add: ftl_notify_add, -- remove: ftl_notify_remove, --}; -- - /* Partition state flags */ - #define FTL_FORMATTED 0x01 - -@@ -204,51 +149,11 @@ - #define XFER_PREPARED 0x03 - #define XFER_FAILED 0x04 - --static struct hd_struct ftl_hd[MINOR_NR(MAX_DEV, 0, 0)]; --static int ftl_sizes[MINOR_NR(MAX_DEV, 0, 0)]; --static int ftl_blocksizes[MINOR_NR(MAX_DEV, 0, 0)]; -- --static struct gendisk ftl_gendisk = { -- major: FTL_MAJOR, -- major_name: "ftl", -- minor_shift: PART_BITS, -- max_p: MAX_PART, --#if (LINUX_VERSION_CODE < 0x20328) -- max_nr: MAX_DEV*MAX_PART, --#endif -- part: ftl_hd, -- sizes: ftl_sizes, --}; -- - /*====================================================================*/ - --static int ftl_ioctl(struct inode *inode, struct file *file, -- u_int cmd, u_long arg); --static int ftl_open(struct inode *inode, struct file *file); --static release_t ftl_close(struct inode *inode, struct file *file); --static int ftl_reread_partitions(int minor); - - static void ftl_erase_callback(struct erase_info *done); - --#if LINUX_VERSION_CODE < 0x20326 --static struct file_operations ftl_blk_fops = { -- open: ftl_open, -- release: ftl_close, -- ioctl: ftl_ioctl, -- read: block_read, -- write: block_write, -- fsync: block_fsync --}; --#else --static struct block_device_operations ftl_blk_fops = { --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14) -- owner: THIS_MODULE, --#endif -- open: ftl_open, -- release: ftl_close, -- ioctl: ftl_ioctl, --}; --#endif - - /*====================================================================== - -@@ -264,13 +169,13 @@ - loff_t offset, max_offset; - int ret; - part->header.FormattedSize = 0; -- max_offset = (0x100000mtd->size)?0x100000:part->mtd->size; -+ max_offset = (0x100000mbd.mtd->size)?0x100000:part->mbd.mtd->size; - /* Search first megabyte for a valid FTL header */ - for (offset = 0; - (offset + sizeof(header)) < max_offset; -- offset += part->mtd->erasesize ? : 0x2000) { -+ offset += part->mbd.mtd->erasesize ? : 0x2000) { - -- ret = part->mtd->read(part->mtd, offset, sizeof(header), &ret, -+ ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &ret, - (unsigned char *)&header); - - if (ret) -@@ -283,15 +188,15 @@ - printk(KERN_NOTICE "ftl_cs: FTL header not found.\n"); - return -ENOENT; - } -- if ((le16_to_cpu(header.NumEraseUnits) > 65536) || header.BlockSize != 9 || -+ if (header.BlockSize != 9 || - (header.EraseUnitSize < 10) || (header.EraseUnitSize > 31) || - (header.NumTransferUnits >= le16_to_cpu(header.NumEraseUnits))) { - printk(KERN_NOTICE "ftl_cs: FTL header corrupt!\n"); - return -1; - } -- if ((1 << header.EraseUnitSize) != part->mtd->erasesize) { -+ if ((1 << header.EraseUnitSize) != part->mbd.mtd->erasesize) { - printk(KERN_NOTICE "ftl: FTL EraseUnitSize %x != MTD erasesize %x\n", -- 1 << header.EraseUnitSize,part->mtd->erasesize); -+ 1 << header.EraseUnitSize,part->mbd.mtd->erasesize); - return -1; - } - part->header = header; -@@ -326,7 +231,7 @@ - for (i = 0; i < le16_to_cpu(part->header.NumEraseUnits); i++) { - offset = ((i + le16_to_cpu(part->header.FirstPhysicalEUN)) - << part->header.EraseUnitSize); -- ret = part->mtd->read(part->mtd, offset, sizeof(header), &retval, -+ ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &retval, - (unsigned char *)&header); - - if (ret) -@@ -391,7 +296,7 @@ - part->EUNInfo[i].Deleted = 0; - offset = part->EUNInfo[i].Offset + le32_to_cpu(header.BAMOffset); - -- ret = part->mtd->read(part->mtd, offset, -+ ret = part->mbd.mtd->read(part->mbd.mtd, offset, - part->BlocksPerUnit * sizeof(u_int32_t), &retval, - (unsigned char *)part->bam_cache); - -@@ -456,7 +361,7 @@ - erase->len = 1 << part->header.EraseUnitSize; - erase->priv = (u_long)part; - -- ret = part->mtd->erase(part->mtd, erase); -+ ret = part->mbd.mtd->erase(part->mbd.mtd, erase); - - if (!ret) - xfer->EraseCount++; -@@ -523,7 +428,7 @@ - header.LogicalEUN = cpu_to_le16(0xffff); - header.EraseCount = cpu_to_le32(xfer->EraseCount); - -- ret = part->mtd->write(part->mtd, xfer->Offset, sizeof(header), -+ ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset, sizeof(header), - &retlen, (u_char *)&header); - - if (ret) { -@@ -539,7 +444,7 @@ - - for (i = 0; i < nbam; i++, offset += sizeof(u_int32_t)) { - -- ret = part->mtd->write(part->mtd, offset, sizeof(u_int32_t), -+ ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t), - &retlen, (u_char *)&ctl); - - if (ret) -@@ -586,7 +491,7 @@ - - offset = eun->Offset + le32_to_cpu(part->header.BAMOffset); - -- ret = part->mtd->read(part->mtd, offset, -+ ret = part->mbd.mtd->read(part->mbd.mtd, offset, - part->BlocksPerUnit * sizeof(u_int32_t), - &retlen, (u_char *) (part->bam_cache)); - -@@ -604,7 +509,7 @@ - offset = xfer->Offset + 20; /* Bad! */ - unit = cpu_to_le16(0x7fff); - -- ret = part->mtd->write(part->mtd, offset, sizeof(u_int16_t), -+ ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int16_t), - &retlen, (u_char *) &unit); - - if (ret) { -@@ -624,7 +529,7 @@ - break; - case BLOCK_DATA: - case BLOCK_REPLACEMENT: -- ret = part->mtd->read(part->mtd, src, SECTOR_SIZE, -+ ret = part->mbd.mtd->read(part->mbd.mtd, src, SECTOR_SIZE, - &retlen, (u_char *) buf); - if (ret) { - printk(KERN_WARNING "ftl: Error reading old xfer unit in copy_erase_unit\n"); -@@ -632,7 +537,7 @@ - } - - -- ret = part->mtd->write(part->mtd, dest, SECTOR_SIZE, -+ ret = part->mbd.mtd->write(part->mbd.mtd, dest, SECTOR_SIZE, - &retlen, (u_char *) buf); - if (ret) { - printk(KERN_WARNING "ftl: Error writing new xfer unit in copy_erase_unit\n"); -@@ -651,7 +556,7 @@ - } - - /* Write the BAM to the transfer unit */ -- ret = part->mtd->write(part->mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset), -+ ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset), - part->BlocksPerUnit * sizeof(int32_t), &retlen, - (u_char *)part->bam_cache); - if (ret) { -@@ -661,7 +566,7 @@ - - - /* All clear? Then update the LogicalEUN again */ -- ret = part->mtd->write(part->mtd, xfer->Offset + 20, sizeof(u_int16_t), -+ ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + 20, sizeof(u_int16_t), - &retlen, (u_char *)&srcunitswap); - - if (ret) { -@@ -749,8 +654,8 @@ - if (queued) { - DEBUG(1, "ftl_cs: waiting for transfer " - "unit to be prepared...\n"); -- if (part->mtd->sync) -- part->mtd->sync(part->mtd); -+ if (part->mbd.mtd->sync) -+ part->mbd.mtd->sync(part->mbd.mtd); - } else { - static int ne = 0; - if (++ne < 5) -@@ -848,7 +753,7 @@ - /* Invalidate cache */ - part->bam_index = 0xffff; - -- ret = part->mtd->read(part->mtd, -+ ret = part->mbd.mtd->read(part->mbd.mtd, - part->EUNInfo[eun].Offset + le32_to_cpu(part->header.BAMOffset), - part->BlocksPerUnit * sizeof(u_int32_t), - &retlen, (u_char *) (part->bam_cache)); -@@ -877,78 +782,6 @@ - - } /* find_free */ - --/*====================================================================== -- -- This gets a memory handle for the region corresponding to the -- minor device number. -- --======================================================================*/ -- --static int ftl_open(struct inode *inode, struct file *file) --{ -- int minor = MINOR(inode->i_rdev); -- partition_t *partition; -- -- if (minor>>4 >= MAX_MTD_DEVICES) -- return -ENODEV; -- -- partition = myparts[minor>>4]; -- -- if (!partition) -- return -ENODEV; -- -- if (partition->state != FTL_FORMATTED) -- return -ENXIO; -- -- if (ftl_gendisk.part[minor].nr_sects == 0) -- return -ENXIO; -- -- BLK_INC_USE_COUNT; -- -- if (!get_mtd_device(partition->mtd, -1)) { -- BLK_DEC_USE_COUNT; -- return -ENXIO; -- } -- -- if ((file->f_mode & 2) && !(partition->mtd->flags & MTD_CLEAR_BITS) ) { -- put_mtd_device(partition->mtd); -- BLK_DEC_USE_COUNT; -- return -EROFS; -- } -- -- DEBUG(0, "ftl_cs: ftl_open(%d)\n", minor); -- -- atomic_inc(&partition->open); -- -- return 0; --} -- --/*====================================================================*/ -- --static release_t ftl_close(struct inode *inode, struct file *file) --{ -- int minor = MINOR(inode->i_rdev); -- partition_t *part = myparts[minor >> 4]; -- int i; -- -- DEBUG(0, "ftl_cs: ftl_close(%d)\n", minor); -- -- /* Wait for any pending erase operations to complete */ -- if (part->mtd->sync) -- part->mtd->sync(part->mtd); -- -- for (i = 0; i < part->header.NumTransferUnits; i++) { -- if (part->XferInfo[i].state == XFER_ERASED) -- prepare_xfer(part, i); -- } -- -- atomic_dec(&part->open); -- -- put_mtd_device(part->mtd); -- BLK_DEC_USE_COUNT; -- release_return(0); --} /* ftl_close */ -- - - /*====================================================================== - -@@ -983,7 +816,7 @@ - else { - offset = (part->EUNInfo[log_addr / bsize].Offset - + (log_addr % bsize)); -- ret = part->mtd->read(part->mtd, offset, SECTOR_SIZE, -+ ret = part->mbd.mtd->read(part->mbd.mtd, offset, SECTOR_SIZE, - &retlen, (u_char *) buffer); - - if (ret) { -@@ -1022,7 +855,7 @@ - le32_to_cpu(part->header.BAMOffset)); - - #ifdef PSYCHO_DEBUG -- ret = part->mtd->read(part->mtd, offset, sizeof(u_int32_t), -+ ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(u_int32_t), - &retlen, (u_char *)&old_addr); - if (ret) { - printk(KERN_WARNING"ftl: Error reading old_addr in set_bam_entry: %d\n",ret); -@@ -1059,7 +892,7 @@ - #endif - part->bam_cache[blk] = le_virt_addr; - } -- ret = part->mtd->write(part->mtd, offset, sizeof(u_int32_t), -+ ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t), - &retlen, (u_char *)&le_virt_addr); - - if (ret) { -@@ -1119,7 +952,7 @@ - part->EUNInfo[part->bam_index].Deleted++; - offset = (part->EUNInfo[part->bam_index].Offset + - blk * SECTOR_SIZE); -- ret = part->mtd->write(part->mtd, offset, SECTOR_SIZE, &retlen, -+ ret = part->mbd.mtd->write(part->mbd.mtd, offset, SECTOR_SIZE, &retlen, - buffer); - - if (ret) { -@@ -1151,164 +984,32 @@ - return 0; - } /* ftl_write */ - --/*====================================================================== -- -- IOCTL calls for getting device parameters. -- --======================================================================*/ -- --static int ftl_ioctl(struct inode *inode, struct file *file, -- u_int cmd, u_long arg) -+static int ftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) - { -- struct hd_geometry *geo = (struct hd_geometry *)arg; -- int ret = 0, minor = MINOR(inode->i_rdev); -- partition_t *part= myparts[minor >> 4]; -+ partition_t *part = (void *)dev; - u_long sect; - -- if (!part) -- return -ENODEV; /* How? */ -- -- switch (cmd) { -- case HDIO_GETGEO: -- ret = verify_area(VERIFY_WRITE, (long *)arg, sizeof(*geo)); -- if (ret) return ret; -- /* Sort of arbitrary: round size down to 4K boundary */ -+ /* Sort of arbitrary: round size down to 4KiB boundary */ - sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE; -- put_user(1, (char *)&geo->heads); -- put_user(8, (char *)&geo->sectors); -- put_user((sect>>3), (short *)&geo->cylinders); -- put_user(ftl_hd[minor].start_sect, (u_long *)&geo->start); -- break; -- case BLKGETSIZE: -- ret = put_user(ftl_hd[minor].nr_sects, (unsigned long *)arg); -- break; --#ifdef BLKGETSIZE64 -- case BLKGETSIZE64: -- ret = put_user((u64)ftl_hd[minor].nr_sects << 9, (u64 *)arg); -- break; --#endif -- case BLKRRPART: -- ret = ftl_reread_partitions(minor); -- break; --#if (LINUX_VERSION_CODE < 0x20303) -- case BLKFLSBUF: --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) -- if (!capable(CAP_SYS_ADMIN)) return -EACCES; --#endif -- fsync_dev(inode->i_rdev); -- invalidate_buffers(inode->i_rdev); -- break; -- RO_IOCTLS(inode->i_rdev, arg); --#else -- case BLKROSET: -- case BLKROGET: -- case BLKFLSBUF: -- ret = blk_ioctl(inode->i_rdev, cmd, arg); -- break; --#endif -- default: -- ret = -EINVAL; -- } -- -- return ret; --} /* ftl_ioctl */ -- --/*====================================================================== - -- Handler for block device requests -+ geo->heads = 1; -+ geo->sectors = 8; -+ geo->cylinders = sect >> 3; - --======================================================================*/ -- --static int ftl_reread_partitions(int minor) --{ -- partition_t *part = myparts[minor >> 4]; -- int i, whole; -- -- DEBUG(0, "ftl_cs: ftl_reread_partition(%d)\n", minor); -- if ((atomic_read(&part->open) > 1)) { -- return -EBUSY; -- } -- whole = minor & ~(MAX_PART-1); -- -- i = MAX_PART - 1; -- while (i-- > 0) { -- if (ftl_hd[whole+i].nr_sects > 0) { -- kdev_t rdev = MKDEV(FTL_MAJOR, whole+i); -- -- invalidate_device(rdev, 1); -- } -- ftl_hd[whole+i].start_sect = 0; -- ftl_hd[whole+i].nr_sects = 0; -- } -- -- scan_header(part); -- -- register_disk(&ftl_gendisk, whole >> PART_BITS, MAX_PART, -- &ftl_blk_fops, le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE); -- --#ifdef PCMCIA_DEBUG -- for (i = 0; i < MAX_PART; i++) { -- if (ftl_hd[whole+i].nr_sects > 0) -- printk(KERN_INFO " %d: start %ld size %ld\n", i, -- ftl_hd[whole+i].start_sect, -- ftl_hd[whole+i].nr_sects); -- } --#endif - return 0; - } - --/*====================================================================== -- -- Handler for block device requests -- --======================================================================*/ -- --static void do_ftl_request(request_arg_t) -+static int ftl_readsect(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buf) - { -- int ret, minor; -- partition_t *part; -- -- do { -- // sti(); -- INIT_REQUEST; -- -- minor = MINOR(CURRENT->rq_dev); -- -- part = myparts[minor >> 4]; -- if (part) { -- ret = 0; -- -- switch (CURRENT->cmd) { -- case READ: -- ret = ftl_read(part, CURRENT->buffer, -- CURRENT->sector+ftl_hd[minor].start_sect, -- CURRENT->current_nr_sectors); -- if (ret) printk("ftl_read returned %d\n", ret); -- break; -- -- case WRITE: -- ret = ftl_write(part, CURRENT->buffer, -- CURRENT->sector+ftl_hd[minor].start_sect, -- CURRENT->current_nr_sectors); -- if (ret) printk("ftl_write returned %d\n", ret); -- break; -- -- default: -- panic("ftl_cs: unknown block command!\n"); -- -- } -- } else { -- ret = 1; -- printk("NULL part in ftl_request\n"); -- } -- -- if (!ret) { -- CURRENT->sector += CURRENT->current_nr_sectors; -- } -+ return ftl_read((void *)dev, buf, block, 1); -+} - -- end_request((ret == 0) ? 1 : 0); -- } while (1); --} /* do_ftl_request */ -+static int ftl_writesect(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buf) -+{ -+ return ftl_write((void *)dev, buf, block, 1); -+} - - /*====================================================================*/ - -@@ -1337,19 +1038,9 @@ - - } /* ftl_freepart */ - --static void ftl_notify_add(struct mtd_info *mtd) -+static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) - { - partition_t *partition; -- int device; -- -- for (device=0; device < MAX_MTD_DEVICES && myparts[device]; device++) -- ; -- -- if (device == MAX_MTD_DEVICES) { -- printk(KERN_NOTICE "Maximum number of FTL partitions reached\n" -- "Not scanning <%s>\n", mtd->name); -- return; -- } - - partition = kmalloc(sizeof(partition_t), GFP_KERNEL); - -@@ -1361,92 +1052,55 @@ - - memset(partition, 0, sizeof(partition_t)); - -- partition->mtd = mtd; -+ partition->mbd.mtd = mtd; - - if ((scan_header(partition) == 0) && - (build_maps(partition) == 0)) { - - partition->state = FTL_FORMATTED; -- atomic_set(&partition->open, 0); -- myparts[device] = partition; -- ftl_reread_partitions(device << 4); - #ifdef PCMCIA_DEBUG -- printk(KERN_INFO "ftl_cs: opening %d kb FTL partition\n", -+ printk(KERN_INFO "ftl_cs: opening %d KiB FTL partition\n", - le32_to_cpu(partition->header.FormattedSize) >> 10); - #endif -+ partition->mbd.size = le32_to_cpu(partition->header.FormattedSize) >> 9; -+ partition->mbd.blksize = SECTOR_SIZE; -+ partition->mbd.tr = tr; -+ partition->mbd.devnum = -1; -+ if (add_mtd_blktrans_dev((void *)partition)) -+ kfree(partition); -+ - } else - kfree(partition); - } - --static void ftl_notify_remove(struct mtd_info *mtd) -+static void ftl_remove_dev(struct mtd_blktrans_dev *dev) - { -- int i,j; -- -- /* Q: What happens if you try to remove a device which has -- * a currently-open FTL partition on it? -- * -- * A: You don't. The ftl_open routine is responsible for -- * increasing the use count of the driver module which -- * it uses. -- */ -- -- /* That's the theory, anyway :) */ -- -- for (i=0; i< MAX_MTD_DEVICES; i++) -- if (myparts[i] && myparts[i]->mtd == mtd) { -- -- if (myparts[i]->state == FTL_FORMATTED) -- ftl_freepart(myparts[i]); -- -- myparts[i]->state = 0; -- for (j=0; j<16; j++) { -- ftl_gendisk.part[j].nr_sects=0; -- ftl_gendisk.part[j].start_sect=0; -- } -- kfree(myparts[i]); -- myparts[i] = NULL; -- } -+ del_mtd_blktrans_dev(dev); -+ kfree(dev); - } - -+struct mtd_blktrans_ops ftl_tr = { -+ .name = "ftl", -+ .major = FTL_MAJOR, -+ .part_bits = PART_BITS, -+ .readsect = ftl_readsect, -+ .writesect = ftl_writesect, -+ .getgeo = ftl_getgeo, -+ .add_mtd = ftl_add_mtd, -+ .remove_dev = ftl_remove_dev, -+ .owner = THIS_MODULE, -+}; -+ - int init_ftl(void) - { -- int i; -- -- memset(myparts, 0, sizeof(myparts)); -+ DEBUG(0, "$Id$\n"); - -- DEBUG(0, "$Id$\n"); -- -- if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) { -- printk(KERN_NOTICE "ftl_cs: unable to grab major " -- "device number!\n"); -- return -EAGAIN; -- } -- -- for (i = 0; i < MINOR_NR(MAX_DEV, 0, 0); i++) -- ftl_blocksizes[i] = 1024; -- for (i = 0; i < MAX_DEV*MAX_PART; i++) { -- ftl_hd[i].nr_sects = 0; -- ftl_hd[i].start_sect = 0; -- } -- blksize_size[FTL_MAJOR] = ftl_blocksizes; -- ftl_gendisk.major = FTL_MAJOR; -- blk_init_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR), &do_ftl_request); -- add_gendisk(&ftl_gendisk); -- -- register_mtd_user(&ftl_notifier); -- -- return 0; -+ return register_mtd_blktrans(&ftl_tr); - } - - static void __exit cleanup_ftl(void) - { -- unregister_mtd_user(&ftl_notifier); -- -- unregister_blkdev(FTL_MAJOR, "ftl"); -- blk_cleanup_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR)); -- blksize_size[FTL_MAJOR] = NULL; -- -- del_gendisk(&ftl_gendisk); -+ deregister_mtd_blktrans(&ftl_tr); - } - - module_init(init_ftl); -diff -Nurb linux-mips-2.4.27/drivers/mtd/inftlcore.c linux/drivers/mtd/inftlcore.c ---- linux-mips-2.4.27/drivers/mtd/inftlcore.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/inftlcore.c 2004-11-19 10:25:11.632240376 +0100 -@@ -0,0 +1,900 @@ -+/* -+ * inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL) -+ * -+ * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) -+ * -+ * Based heavily on the nftlcore.c code which is: -+ * (c) 1999 Machine Vision Holdings, Inc. -+ * Author: David Woodhouse -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the 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 -+ -+/* -+ * Maximum number of loops while examining next block, to have a -+ * chance to detect consistency problems (they should never happen -+ * because of the checks done in the mounting. -+ */ -+#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; -+ unsigned long temp; -+ -+ if (mtd->ecctype != MTD_ECC_RS_DiskOnChip) -+ return; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name); -+ -+ inftl = kmalloc(sizeof(*inftl), GFP_KERNEL); -+ -+ if (!inftl) { -+ printk(KERN_WARNING "INFTL: Out of memory for data structures\n"); -+ return; -+ } -+ memset(inftl, 0, sizeof(*inftl)); -+ -+ inftl->mbd.mtd = mtd; -+ inftl->mbd.devnum = -1; -+ inftl->mbd.blksize = 512; -+ inftl->mbd.tr = tr; -+ -+ if (INFTL_mount(inftl) < 0) { -+ printk(KERN_WARNING "INFTL: could not mount device\n"); -+ kfree(inftl); -+ return; -+ } -+ -+ /* OK, it's a new one. Set up all the data structures. */ -+ -+ /* Calculate geometry */ -+ inftl->cylinders = 1024; -+ inftl->heads = 16; -+ -+ temp = inftl->cylinders * inftl->heads; -+ inftl->sectors = inftl->mbd.size / temp; -+ if (inftl->mbd.size % temp) { -+ inftl->sectors++; -+ temp = inftl->cylinders * inftl->sectors; -+ inftl->heads = inftl->mbd.size / temp; -+ -+ if (inftl->mbd.size % temp) { -+ inftl->heads++; -+ temp = inftl->heads * inftl->sectors; -+ inftl->cylinders = inftl->mbd.size / temp; -+ } -+ } -+ -+ if (inftl->mbd.size != inftl->heads * inftl->cylinders * inftl->sectors) { -+ /* -+ Oh no we don't have -+ mbd.size == heads * cylinders * sectors -+ */ -+ printk(KERN_WARNING "INFTL: cannot calculate a geometry to " -+ "match size of 0x%lx.\n", inftl->mbd.size); -+ printk(KERN_WARNING "INFTL: using C:%d H:%d S:%d " -+ "(== 0x%lx sects)\n", -+ inftl->cylinders, inftl->heads , inftl->sectors, -+ (long)inftl->cylinders * (long)inftl->heads * -+ (long)inftl->sectors ); -+ } -+ -+ if (add_mtd_blktrans_dev(&inftl->mbd)) { -+ if (inftl->PUtable) -+ kfree(inftl->PUtable); -+ if (inftl->VUtable) -+ kfree(inftl->VUtable); -+ kfree(inftl); -+ return; -+ } -+#ifdef PSYCHO_DEBUG -+ printk(KERN_INFO "INFTL: Found new nftl%c\n", nftl->mbd.devnum + 'a'); -+#endif -+ return; -+} -+ -+static void inftl_remove_dev(struct mtd_blktrans_dev *dev) -+{ -+ struct INFTLrecord *inftl = (void *)dev; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: remove_dev (i=%d)\n", dev->devnum); -+ -+ del_mtd_blktrans_dev(dev); -+ -+ if (inftl->PUtable) -+ kfree(inftl->PUtable); -+ if (inftl->VUtable) -+ kfree(inftl->VUtable); -+ kfree(inftl); -+} -+ -+/* -+ * Actual INFTL access routines. -+ */ -+ -+/* -+ * INFTL_findfreeblock: Find a free Erase Unit on the INFTL partition. -+ * This function is used when the give Virtual Unit Chain. -+ */ -+static u16 INFTL_findfreeblock(struct INFTLrecord *inftl, int desperate) -+{ -+ u16 pot = inftl->LastFreeEUN; -+ int silly = inftl->nb_blocks; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findfreeblock(inftl=0x%x," -+ "desperate=%d)\n", (int)inftl, desperate); -+ -+ /* -+ * Normally, we force a fold to happen before we run out of free -+ * blocks completely. -+ */ -+ if (!desperate && inftl->numfreeEUNs < 2) { -+ DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free " -+ "EUNs (%d)\n", inftl->numfreeEUNs); -+ return 0xffff; -+ } -+ -+ /* Scan for a free block */ -+ do { -+ if (inftl->PUtable[pot] == BLOCK_FREE) { -+ inftl->LastFreeEUN = pot; -+ return pot; -+ } -+ -+ if (++pot > inftl->lastEUN) -+ pot = 0; -+ -+ if (!silly--) { -+ printk(KERN_WARNING "INFTL: no free blocks found! " -+ "EUN range = %d - %d\n", 0, inftl->LastFreeEUN); -+ return BLOCK_NIL; -+ } -+ } while (pot != inftl->LastFreeEUN); -+ -+ return BLOCK_NIL; -+} -+ -+static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned pendingblock) -+{ -+ u16 BlockMap[MAX_SECTORS_PER_UNIT]; -+ unsigned char BlockDeleted[MAX_SECTORS_PER_UNIT]; -+ unsigned int thisEUN, prevEUN, status; -+ int block, silly; -+ unsigned int targetEUN; -+ struct inftl_oob oob; -+ size_t retlen; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_foldchain(inftl=0x%x,thisVUC=%d," -+ "pending=%d)\n", (int)inftl, thisVUC, pendingblock); -+ -+ memset(BlockMap, 0xff, sizeof(BlockMap)); -+ memset(BlockDeleted, 0, sizeof(BlockDeleted)); -+ -+ thisEUN = targetEUN = inftl->VUtable[thisVUC]; -+ -+ if (thisEUN == BLOCK_NIL) { -+ printk(KERN_WARNING "INFTL: trying to fold non-existent " -+ "Virtual Unit Chain %d!\n", thisVUC); -+ return BLOCK_NIL; -+ } -+ -+ /* -+ * Scan to find the Erase Unit which holds the actual data for each -+ * 512-byte block within the Chain. -+ */ -+ silly = MAX_LOOPS; -+ while (thisEUN < inftl->nb_blocks) { -+ for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) { -+ if ((BlockMap[block] != 0xffff) || BlockDeleted[block]) -+ continue; -+ -+ if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) -+ + (block * SECTORSIZE), 16 , &retlen, -+ (char *)&oob) < 0) -+ status = SECTOR_IGNORE; -+ else -+ status = oob.b.Status | oob.b.Status1; -+ -+ switch(status) { -+ case SECTOR_FREE: -+ case SECTOR_IGNORE: -+ break; -+ case SECTOR_USED: -+ BlockMap[block] = thisEUN; -+ continue; -+ case SECTOR_DELETED: -+ BlockDeleted[block] = 1; -+ continue; -+ default: -+ printk(KERN_WARNING "INFTL: unknown status " -+ "for block %d in EUN %d: %x\n", -+ block, thisEUN, status); -+ break; -+ } -+ } -+ -+ if (!silly--) { -+ printk(KERN_WARNING "INFTL: infinite loop in Virtual " -+ "Unit Chain 0x%x\n", thisVUC); -+ return BLOCK_NIL; -+ } -+ -+ thisEUN = inftl->PUtable[thisEUN]; -+ } -+ -+ /* -+ * OK. We now know the location of every block in the Virtual Unit -+ * Chain, and the Erase Unit into which we are supposed to be copying. -+ * Go for it. -+ */ -+ DEBUG(MTD_DEBUG_LEVEL1, "INFTL: folding chain %d into unit %d\n", -+ thisVUC, targetEUN); -+ -+ for (block = 0; block < inftl->EraseSize/SECTORSIZE ; block++) { -+ unsigned char movebuf[SECTORSIZE]; -+ int ret; -+ -+ /* -+ * If it's in the target EUN already, or if it's pending write, -+ * do nothing. -+ */ -+ if (BlockMap[block] == targetEUN || (pendingblock == -+ (thisVUC * (inftl->EraseSize / SECTORSIZE) + block))) { -+ continue; -+ } -+ -+ /* -+ * Copy only in non free block (free blocks can only -+ * happen in case of media errors or deleted blocks). -+ */ -+ if (BlockMap[block] == BLOCK_NIL) -+ continue; -+ -+ ret = MTD_READECC(inftl->mbd.mtd, (inftl->EraseSize * -+ BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE, -+ &retlen, movebuf, (char *)&oob, NULL); -+ if (ret < 0) { -+ ret = MTD_READECC(inftl->mbd.mtd, (inftl->EraseSize * -+ BlockMap[block]) + (block * SECTORSIZE), -+ SECTORSIZE, &retlen, movebuf, (char *)&oob, -+ NULL); -+ if (ret != -EIO) -+ DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went " -+ "away on retry?\n"); -+ } -+ MTD_WRITEECC(inftl->mbd.mtd, (inftl->EraseSize * targetEUN) + -+ (block * SECTORSIZE), SECTORSIZE, &retlen, -+ movebuf, (char *)&oob, NULL); -+ } -+ -+ /* -+ * Newest unit in chain now contains data from _all_ older units. -+ * So go through and erase each unit in chain, oldest first. (This -+ * is important, by doing oldest first if we crash/reboot then it -+ * it is relatively simple to clean up the mess). -+ */ -+ DEBUG(MTD_DEBUG_LEVEL1, "INFTL: want to erase virtual chain %d\n", -+ thisVUC); -+ -+ for (;;) { -+ /* Find oldest unit in chain. */ -+ thisEUN = inftl->VUtable[thisVUC]; -+ prevEUN = BLOCK_NIL; -+ while (inftl->PUtable[thisEUN] != BLOCK_NIL) { -+ prevEUN = thisEUN; -+ thisEUN = inftl->PUtable[thisEUN]; -+ } -+ -+ /* Check if we are all done */ -+ if (thisEUN == targetEUN) -+ break; -+ -+ if (INFTL_formatblock(inftl, thisEUN) < 0) { -+ /* -+ * Could not erase : mark block as reserved. -+ * FixMe: Update Bad Unit Table on disk. -+ */ -+ inftl->PUtable[thisEUN] = BLOCK_RESERVED; -+ } else { -+ /* Correctly erased : mark it as free */ -+ inftl->PUtable[thisEUN] = BLOCK_FREE; -+ inftl->PUtable[prevEUN] = BLOCK_NIL; -+ inftl->numfreeEUNs++; -+ } -+ } -+ -+ return targetEUN; -+} -+ -+u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock) -+{ -+ /* -+ * This is the part that needs some cleverness applied. -+ * For now, I'm doing the minimum applicable to actually -+ * get the thing to work. -+ * Wear-levelling and other clever stuff needs to be implemented -+ * and we also need to do some assessment of the results when -+ * the system loses power half-way through the routine. -+ */ -+ u16 LongestChain = 0; -+ u16 ChainLength = 0, thislen; -+ u16 chain, EUN; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_makefreeblock(inftl=0x%x," -+ "pending=%d)\n", (int)inftl, pendingblock); -+ -+ for (chain = 0; chain < inftl->nb_blocks; chain++) { -+ EUN = inftl->VUtable[chain]; -+ thislen = 0; -+ -+ while (EUN <= inftl->lastEUN) { -+ thislen++; -+ EUN = inftl->PUtable[EUN]; -+ if (thislen > 0xff00) { -+ printk(KERN_WARNING "INFTL: endless loop in " -+ "Virtual Chain %d: Unit %x\n", -+ chain, EUN); -+ /* -+ * Actually, don't return failure. -+ * Just ignore this chain and get on with it. -+ */ -+ thislen = 0; -+ break; -+ } -+ } -+ -+ if (thislen > ChainLength) { -+ ChainLength = thislen; -+ LongestChain = chain; -+ } -+ } -+ -+ if (ChainLength < 2) { -+ printk(KERN_WARNING "INFTL: no Virtual Unit Chains available " -+ "for folding. Failing request\n"); -+ return BLOCK_NIL; -+ } -+ -+ return INFTL_foldchain(inftl, LongestChain, pendingblock); -+} -+ -+static int nrbits(unsigned int val, int bitcount) -+{ -+ int i, total = 0; -+ -+ for (i = 0; (i < bitcount); i++) -+ total += (((0x1 << i) & val) ? 1 : 0); -+ return total; -+} -+ -+/* -+ * INFTL_findwriteunit: Return the unit number into which we can write -+ * for this block. Make it available if it isn't already. -+ */ -+static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) -+{ -+ unsigned int thisVUC = block / (inftl->EraseSize / SECTORSIZE); -+ unsigned int thisEUN, writeEUN, prev_block, status; -+ unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize -1); -+ struct inftl_oob oob; -+ struct inftl_bci bci; -+ unsigned char anac, nacs, parity; -+ size_t retlen; -+ int silly, silly2 = 3; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findwriteunit(inftl=0x%x," -+ "block=%d)\n", (int)inftl, block); -+ -+ do { -+ /* -+ * Scan the media to find a unit in the VUC which has -+ * a free space for the block in question. -+ */ -+ writeEUN = BLOCK_NIL; -+ thisEUN = inftl->VUtable[thisVUC]; -+ silly = MAX_LOOPS; -+ -+ while (thisEUN <= inftl->lastEUN) { -+ MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) + -+ blockofs, 8, &retlen, (char *)&bci); -+ -+ status = bci.Status | bci.Status1; -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: status of block %d in " -+ "EUN %d is %x\n", block , writeEUN, status); -+ -+ switch(status) { -+ case SECTOR_FREE: -+ writeEUN = thisEUN; -+ break; -+ case SECTOR_DELETED: -+ case SECTOR_USED: -+ /* Can't go any further */ -+ goto hitused; -+ case SECTOR_IGNORE: -+ break; -+ default: -+ /* -+ * Invalid block. Don't use it any more. -+ * Must implement. -+ */ -+ break; -+ } -+ -+ if (!silly--) { -+ printk(KERN_WARNING "INFTL: infinite loop in " -+ "Virtual Unit Chain 0x%x\n", thisVUC); -+ return 0xffff; -+ } -+ -+ /* Skip to next block in chain */ -+ thisEUN = inftl->PUtable[thisEUN]; -+ } -+ -+hitused: -+ if (writeEUN != BLOCK_NIL) -+ return writeEUN; -+ -+ -+ /* -+ * OK. We didn't find one in the existing chain, or there -+ * is no existing chain. Allocate a new one. -+ */ -+ writeEUN = INFTL_findfreeblock(inftl, 0); -+ -+ if (writeEUN == BLOCK_NIL) { -+ /* -+ * That didn't work - there were no free blocks just -+ * waiting to be picked up. We're going to have to fold -+ * a chain to make room. -+ */ -+ thisEUN = INFTL_makefreeblock(inftl, 0xffff); -+ -+ /* -+ * Hopefully we free something, lets try again. -+ * This time we are desperate... -+ */ -+ DEBUG(MTD_DEBUG_LEVEL1, "INFTL: using desperate==1 " -+ "to find free EUN to accommodate write to " -+ "VUC %d\n", thisVUC); -+ writeEUN = INFTL_findfreeblock(inftl, 1); -+ if (writeEUN == BLOCK_NIL) { -+ /* -+ * Ouch. This should never happen - we should -+ * always be able to make some room somehow. -+ * If we get here, we've allocated more storage -+ * space than actual media, or our makefreeblock -+ * routine is missing something. -+ */ -+ printk(KERN_WARNING "INFTL: cannot make free " -+ "space.\n"); -+#ifdef DEBUG -+ INFTL_dumptables(inftl); -+ INFTL_dumpVUchains(inftl); -+#endif -+ return BLOCK_NIL; -+ } -+ } -+ -+ /* -+ * Insert new block into virtual chain. Firstly update the -+ * block headers in flash... -+ */ -+ anac = 0; -+ nacs = 0; -+ thisEUN = inftl->VUtable[thisVUC]; -+ if (thisEUN != BLOCK_NIL) { -+ MTD_READOOB(inftl->mbd.mtd, thisEUN * inftl->EraseSize -+ + 8, 8, &retlen, (char *)&oob.u); -+ anac = oob.u.a.ANAC + 1; -+ nacs = oob.u.a.NACs + 1; -+ } -+ -+ prev_block = inftl->VUtable[thisVUC]; -+ if (prev_block < inftl->nb_blocks) -+ prev_block -= inftl->firstEUN; -+ -+ parity = (nrbits(thisVUC, 16) & 0x1) ? 0x1 : 0; -+ parity |= (nrbits(prev_block, 16) & 0x1) ? 0x2 : 0; -+ parity |= (nrbits(anac, 8) & 0x1) ? 0x4 : 0; -+ parity |= (nrbits(nacs, 8) & 0x1) ? 0x8 : 0; -+ -+ oob.u.a.virtualUnitNo = cpu_to_le16(thisVUC); -+ oob.u.a.prevUnitNo = cpu_to_le16(prev_block); -+ oob.u.a.ANAC = anac; -+ oob.u.a.NACs = nacs; -+ oob.u.a.parityPerField = parity; -+ oob.u.a.discarded = 0xaa; -+ -+ MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize + 8, 8, -+ &retlen, (char *)&oob.u); -+ -+ /* Also back up header... */ -+ oob.u.b.virtualUnitNo = cpu_to_le16(thisVUC); -+ oob.u.b.prevUnitNo = cpu_to_le16(prev_block); -+ oob.u.b.ANAC = anac; -+ oob.u.b.NACs = nacs; -+ oob.u.b.parityPerField = parity; -+ oob.u.b.discarded = 0xaa; -+ -+ MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize + -+ SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u); -+ -+ inftl->PUtable[writeEUN] = inftl->VUtable[thisVUC]; -+ inftl->VUtable[thisVUC] = writeEUN; -+ -+ inftl->numfreeEUNs--; -+ return writeEUN; -+ -+ } while (silly2--); -+ -+ printk(KERN_WARNING "INFTL: error folding to make room for Virtual " -+ "Unit Chain 0x%x\n", thisVUC); -+ return 0xffff; -+} -+ -+/* -+ * Given a Virtual Unit Chain, see if it can be deleted, and if so do it. -+ */ -+static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC) -+{ -+ unsigned char BlockUsed[MAX_SECTORS_PER_UNIT]; -+ unsigned char BlockDeleted[MAX_SECTORS_PER_UNIT]; -+ unsigned int thisEUN, status; -+ int block, silly; -+ struct inftl_bci bci; -+ size_t retlen; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_trydeletechain(inftl=0x%x," -+ "thisVUC=%d)\n", (int)inftl, thisVUC); -+ -+ memset(BlockUsed, 0, sizeof(BlockUsed)); -+ memset(BlockDeleted, 0, sizeof(BlockDeleted)); -+ -+ thisEUN = inftl->VUtable[thisVUC]; -+ if (thisEUN == BLOCK_NIL) { -+ printk(KERN_WARNING "INFTL: trying to delete non-existent " -+ "Virtual Unit Chain %d!\n", thisVUC); -+ return; -+ } -+ -+ /* -+ * Scan through the Erase Units to determine whether any data is in -+ * each of the 512-byte blocks within the Chain. -+ */ -+ silly = MAX_LOOPS; -+ while (thisEUN < inftl->nb_blocks) { -+ for (block = 0; block < inftl->EraseSize/SECTORSIZE; block++) { -+ if (BlockUsed[block] || BlockDeleted[block]) -+ continue; -+ -+ if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) -+ + (block * SECTORSIZE), 8 , &retlen, -+ (char *)&bci) < 0) -+ status = SECTOR_IGNORE; -+ else -+ status = bci.Status | bci.Status1; -+ -+ switch(status) { -+ case SECTOR_FREE: -+ case SECTOR_IGNORE: -+ break; -+ case SECTOR_USED: -+ BlockUsed[block] = 1; -+ continue; -+ case SECTOR_DELETED: -+ BlockDeleted[block] = 1; -+ continue; -+ default: -+ printk(KERN_WARNING "INFTL: unknown status " -+ "for block %d in EUN %d: 0x%x\n", -+ block, thisEUN, status); -+ } -+ } -+ -+ if (!silly--) { -+ printk(KERN_WARNING "INFTL: infinite loop in Virtual " -+ "Unit Chain 0x%x\n", thisVUC); -+ return; -+ } -+ -+ thisEUN = inftl->PUtable[thisEUN]; -+ } -+ -+ for (block = 0; block < inftl->EraseSize/SECTORSIZE; block++) -+ if (BlockUsed[block]) -+ return; -+ -+ /* -+ * For each block in the chain free it and make it available -+ * for future use. Erase from the oldest unit first. -+ */ -+ DEBUG(MTD_DEBUG_LEVEL1, "INFTL: deleting empty VUC %d\n", thisVUC); -+ -+ for (;;) { -+ u16 *prevEUN = &inftl->VUtable[thisVUC]; -+ thisEUN = *prevEUN; -+ -+ /* If the chain is all gone already, we're done */ -+ if (thisEUN == BLOCK_NIL) { -+ DEBUG(MTD_DEBUG_LEVEL2, "INFTL: Empty VUC %d for deletion was already absent\n", thisEUN); -+ return; -+ } -+ -+ /* Find oldest unit in chain. */ -+ while (inftl->PUtable[thisEUN] != BLOCK_NIL) { -+ BUG_ON(thisEUN >= inftl->nb_blocks); -+ -+ prevEUN = &inftl->PUtable[thisEUN]; -+ thisEUN = *prevEUN; -+ } -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "Deleting EUN %d from VUC %d\n", -+ thisEUN, thisVUC); -+ -+ if (INFTL_formatblock(inftl, thisEUN) < 0) { -+ /* -+ * Could not erase : mark block as reserved. -+ * FixMe: Update Bad Unit Table on medium. -+ */ -+ inftl->PUtable[thisEUN] = BLOCK_RESERVED; -+ } else { -+ /* Correctly erased : mark it as free */ -+ inftl->PUtable[thisEUN] = BLOCK_FREE; -+ inftl->numfreeEUNs++; -+ } -+ -+ /* Now sort out whatever was pointing to it... */ -+ *prevEUN = BLOCK_NIL; -+ -+ /* Ideally we'd actually be responsive to new -+ requests while we're doing this -- if there's -+ free space why should others be made to wait? */ -+ cond_resched(); -+ } -+ -+ inftl->VUtable[thisVUC] = BLOCK_NIL; -+} -+ -+static int INFTL_deleteblock(struct INFTLrecord *inftl, unsigned block) -+{ -+ unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)]; -+ unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1); -+ unsigned int status; -+ int silly = MAX_LOOPS; -+ size_t retlen; -+ struct inftl_bci bci; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_deleteblock(inftl=0x%x," -+ "block=%d)\n", (int)inftl, block); -+ -+ while (thisEUN < inftl->nb_blocks) { -+ if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) + -+ blockofs, 8, &retlen, (char *)&bci) < 0) -+ status = SECTOR_IGNORE; -+ else -+ status = bci.Status | bci.Status1; -+ -+ switch (status) { -+ case SECTOR_FREE: -+ case SECTOR_IGNORE: -+ break; -+ case SECTOR_DELETED: -+ thisEUN = BLOCK_NIL; -+ goto foundit; -+ case SECTOR_USED: -+ goto foundit; -+ default: -+ printk(KERN_WARNING "INFTL: unknown status for " -+ "block %d in EUN %d: 0x%x\n", -+ block, thisEUN, status); -+ break; -+ } -+ -+ if (!silly--) { -+ printk(KERN_WARNING "INFTL: infinite loop in Virtual " -+ "Unit Chain 0x%x\n", -+ block / (inftl->EraseSize / SECTORSIZE)); -+ return 1; -+ } -+ thisEUN = inftl->PUtable[thisEUN]; -+ } -+ -+foundit: -+ if (thisEUN != BLOCK_NIL) { -+ loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs; -+ -+ if (MTD_READOOB(inftl->mbd.mtd, ptr, 8, &retlen, (char *)&bci) < 0) -+ return -EIO; -+ bci.Status = bci.Status1 = SECTOR_DELETED; -+ if (MTD_WRITEOOB(inftl->mbd.mtd, ptr, 8, &retlen, (char *)&bci) < 0) -+ return -EIO; -+ INFTL_trydeletechain(inftl, block / (inftl->EraseSize / SECTORSIZE)); -+ } -+ return 0; -+} -+ -+static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, -+ char *buffer) -+{ -+ struct INFTLrecord *inftl = (void *)mbd; -+ unsigned int writeEUN; -+ unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1); -+ size_t retlen; -+ u8 eccbuf[6]; -+ char *p, *pend; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_writeblock(inftl=0x%x,block=%d," -+ "buffer=0x%x)\n", (int)inftl, block, (int)buffer); -+ -+ /* Is block all zero? */ -+ pend = buffer + SECTORSIZE; -+ for (p = buffer; p < pend && !*p; p++) -+ ; -+ -+ if (p < pend) { -+ writeEUN = INFTL_findwriteunit(inftl, block); -+ -+ if (writeEUN == BLOCK_NIL) { -+ printk(KERN_WARNING "inftl_writeblock(): cannot find " -+ "block to write to\n"); -+ /* -+ * If we _still_ haven't got a block to use, -+ * we're screwed. -+ */ -+ return 1; -+ } -+ -+ MTD_WRITEECC(inftl->mbd.mtd, (writeEUN * inftl->EraseSize) + -+ blockofs, SECTORSIZE, &retlen, (char *)buffer, -+ (char *)eccbuf, NULL); -+ /* -+ * No need to write SECTOR_USED flags since they are written -+ * in mtd_writeecc -+ */ -+ } else { -+ INFTL_deleteblock(inftl, block); -+ } -+ -+ return 0; -+} -+ -+static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block, -+ char *buffer) -+{ -+ struct INFTLrecord *inftl = (void *)mbd; -+ unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)]; -+ unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1); -+ unsigned int status; -+ int silly = MAX_LOOPS; -+ struct inftl_bci bci; -+ size_t retlen; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=0x%x,block=%d," -+ "buffer=0x%x)\n", (int)inftl, block, (int)buffer); -+ -+ while (thisEUN < inftl->nb_blocks) { -+ if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) + -+ blockofs, 8, &retlen, (char *)&bci) < 0) -+ status = SECTOR_IGNORE; -+ else -+ status = bci.Status | bci.Status1; -+ -+ switch (status) { -+ case SECTOR_DELETED: -+ thisEUN = BLOCK_NIL; -+ goto foundit; -+ case SECTOR_USED: -+ goto foundit; -+ case SECTOR_FREE: -+ case SECTOR_IGNORE: -+ break; -+ default: -+ printk(KERN_WARNING "INFTL: unknown status for " -+ "block %ld in EUN %d: 0x%04x\n", -+ block, thisEUN, status); -+ break; -+ } -+ -+ if (!silly--) { -+ printk(KERN_WARNING "INFTL: infinite loop in " -+ "Virtual Unit Chain 0x%lx\n", -+ block / (inftl->EraseSize / SECTORSIZE)); -+ return 1; -+ } -+ -+ thisEUN = inftl->PUtable[thisEUN]; -+ } -+ -+foundit: -+ if (thisEUN == BLOCK_NIL) { -+ /* The requested block is not on the media, return all 0x00 */ -+ memset(buffer, 0, SECTORSIZE); -+ } else { -+ size_t retlen; -+ loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs; -+ u_char eccbuf[6]; -+ if (MTD_READECC(inftl->mbd.mtd, ptr, SECTORSIZE, &retlen, -+ buffer, eccbuf, NULL)) -+ return -EIO; -+ } -+ return 0; -+} -+ -+static int inftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) -+{ -+ struct INFTLrecord *inftl = (void *)dev; -+ -+ geo->heads = inftl->heads; -+ geo->sectors = inftl->sectors; -+ geo->cylinders = inftl->cylinders; -+ -+ return 0; -+} -+ -+struct mtd_blktrans_ops inftl_tr = { -+ .name = "inftl", -+ .major = INFTL_MAJOR, -+ .part_bits = INFTL_PARTN_BITS, -+ .getgeo = inftl_getgeo, -+ .readsect = inftl_readblock, -+ .writesect = inftl_writeblock, -+ .add_mtd = inftl_add_mtd, -+ .remove_dev = inftl_remove_dev, -+ .owner = THIS_MODULE, -+}; -+ -+extern char inftlmountrev[]; -+ -+int __init init_inftl(void) -+{ -+ printk(KERN_INFO "INFTL: inftlcore.c $Revision$, " -+ "inftlmount.c %s\n", inftlmountrev); -+ -+ return register_mtd_blktrans(&inftl_tr); -+} -+ -+static void __exit cleanup_inftl(void) -+{ -+ deregister_mtd_blktrans(&inftl_tr); -+} -+ -+module_init(init_inftl); -+module_exit(cleanup_inftl); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Greg Ungerer , David Woodhouse , Fabrice Bellard et al."); -+MODULE_DESCRIPTION("Support code for Inverse Flash Translation Layer, used on M-Systems DiskOnChip 2000, Millennium and Millennium Plus"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/inftlmount.c linux/drivers/mtd/inftlmount.c ---- linux-mips-2.4.27/drivers/mtd/inftlmount.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/inftlmount.c 2004-11-19 10:25:11.633240224 +0100 -@@ -0,0 +1,817 @@ -+/* -+ * inftlmount.c -- INFTL mount code with extensive checks. -+ * -+ * Author: Greg Ungerer (gerg@snapgear.com) -+ * (C) Copyright 2002-2003, Greg Ungerer (gerg@snapgear.com) -+ * -+ * Based heavily on the nftlmount.c code which is: -+ * Author: Fabrice Bellard (fabrice.bellard@netgem.com) -+ * Copyright (C) 2000 Netgem S.A. -+ * -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the 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 -+ -+char inftlmountrev[]="$Revision$"; -+ -+/* -+ * find_boot_record: Find the INFTL Media Header and its Spare copy which -+ * contains the various device information of the INFTL partition and -+ * Bad Unit Table. Update the PUtable[] table according to the Bad -+ * Unit Table. PUtable[] is used for management of Erase Unit in -+ * other routines in inftlcore.c and inftlmount.c. -+ */ -+static int find_boot_record(struct INFTLrecord *inftl) -+{ -+ struct inftl_unittail h1; -+ //struct inftl_oob oob; -+ unsigned int i, block, boot_record_count = 0; -+ u8 buf[SECTORSIZE]; -+ struct INFTLMediaHeader *mh = &inftl->MediaHdr; -+ struct INFTLPartition *ip; -+ int retlen; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: find_boot_record(inftl=0x%x)\n", -+ (int)inftl); -+ -+ /* -+ * Assume logical EraseSize == physical erasesize for starting the -+ * scan. We'll sort it out later if we find a MediaHeader which says -+ * otherwise. -+ */ -+ inftl->EraseSize = inftl->mbd.mtd->erasesize; -+ inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize; -+ -+ inftl->MediaUnit = BLOCK_NIL; -+ inftl->SpareMediaUnit = BLOCK_NIL; -+ -+ /* Search for a valid boot record */ -+ for (block = 0; block < inftl->nb_blocks; block++) { -+ int ret; -+ -+ /* -+ * Check for BNAND header first. Then whinge if it's found -+ * but later checks fail. -+ */ -+ if ((ret = MTD_READ(inftl->mbd.mtd, block * inftl->EraseSize, -+ SECTORSIZE, &retlen, buf))) { -+ static int warncount = 5; -+ -+ if (warncount) { -+ printk(KERN_WARNING "INFTL: block read at 0x%x " -+ "of mtd%d failed: %d\n", -+ block * inftl->EraseSize, -+ inftl->mbd.mtd->index, ret); -+ if (!--warncount) -+ printk(KERN_WARNING "INFTL: further " -+ "failures for this block will " -+ "not be printed\n"); -+ } -+ continue; -+ } -+ -+ if (retlen < 6 || memcmp(buf, "BNAND", 6)) { -+ /* BNAND\0 not found. Continue */ -+ continue; -+ } -+ -+ /* To be safer with BIOS, also use erase mark as discriminant */ -+ if ((ret = MTD_READOOB(inftl->mbd.mtd, block * inftl->EraseSize + -+ SECTORSIZE + 8, 8, &retlen, (char *)&h1) < 0)) { -+ printk(KERN_WARNING "INFTL: ANAND header found at " -+ "0x%x in mtd%d, but OOB data read failed " -+ "(err %d)\n", block * inftl->EraseSize, -+ inftl->mbd.mtd->index, ret); -+ continue; -+ } -+ -+ if (boot_record_count) { -+ /* -+ * We've already processed one. So we just check if -+ * this one is the same as the first one we found. -+ */ -+ if (memcmp(mh, buf, sizeof(struct INFTLMediaHeader))) { -+ printk(KERN_WARNING "INFTL: Media Headers at " -+ "0x%x and 0x%x disagree.\n", -+ inftl->MediaUnit * inftl->EraseSize, -+ block * inftl->EraseSize); -+ return -1; -+ } -+ if (boot_record_count == 1) -+ inftl->SpareMediaUnit = block; -+ -+ /* -+ * Mark this boot record (INFTL MediaHeader) block as -+ * reserved. -+ */ -+ inftl->PUtable[block] = BLOCK_RESERVED; -+ -+ boot_record_count++; -+ continue; -+ } -+ -+ /* -+ * This is the first we've seen. -+ * Copy the media header structure into place. -+ */ -+ memcpy(mh, buf, sizeof(struct INFTLMediaHeader)); -+ mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks); -+ mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions); -+ mh->NoOfBDTLPartitions = le32_to_cpu(mh->NoOfBDTLPartitions); -+ mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits); -+ mh->FormatFlags = le32_to_cpu(mh->FormatFlags); -+ mh->PercentUsed = le32_to_cpu(mh->PercentUsed); -+ -+#ifdef CONFIG_MTD_DEBUG_VERBOSE -+ if (CONFIG_MTD_DEBUG_VERBOSE >= 2) { -+ printk("INFTL: Media Header ->\n" -+ " bootRecordID = %s\n" -+ " NoOfBootImageBlocks = %d\n" -+ " NoOfBinaryPartitions = %d\n" -+ " NoOfBDTLPartitions = %d\n" -+ " BlockMultiplerBits = %d\n" -+ " FormatFlgs = %d\n" -+ " OsakVersion = 0x%x\n" -+ " PercentUsed = %d\n", -+ mh->bootRecordID, mh->NoOfBootImageBlocks, -+ mh->NoOfBinaryPartitions, -+ mh->NoOfBDTLPartitions, -+ mh->BlockMultiplierBits, mh->FormatFlags, -+ mh->OsakVersion, mh->PercentUsed); -+ } -+#endif -+ -+ if (mh->NoOfBDTLPartitions == 0) { -+ printk(KERN_WARNING "INFTL: Media Header sanity check " -+ "failed: NoOfBDTLPartitions (%d) == 0, " -+ "must be at least 1\n", mh->NoOfBDTLPartitions); -+ return -1; -+ } -+ -+ if ((mh->NoOfBDTLPartitions + mh->NoOfBinaryPartitions) > 4) { -+ printk(KERN_WARNING "INFTL: Media Header sanity check " -+ "failed: Total Partitions (%d) > 4, " -+ "BDTL=%d Binary=%d\n", mh->NoOfBDTLPartitions + -+ mh->NoOfBinaryPartitions, -+ mh->NoOfBDTLPartitions, -+ mh->NoOfBinaryPartitions); -+ return -1; -+ } -+ -+ if (mh->BlockMultiplierBits > 1) { -+ printk(KERN_WARNING "INFTL: sorry, we don't support " -+ "UnitSizeFactor 0x%02x\n", -+ mh->BlockMultiplierBits); -+ return -1; -+ } else if (mh->BlockMultiplierBits == 1) { -+ printk(KERN_WARNING "INFTL: support for INFTL with " -+ "UnitSizeFactor 0x%02x is experimental\n", -+ mh->BlockMultiplierBits); -+ inftl->EraseSize = inftl->mbd.mtd->erasesize << -+ (0xff - mh->BlockMultiplierBits); -+ inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize; -+ } -+ -+ /* Scan the partitions */ -+ for (i = 0; (i < 4); i++) { -+ ip = &mh->Partitions[i]; -+ ip->virtualUnits = le32_to_cpu(ip->virtualUnits); -+ ip->firstUnit = le32_to_cpu(ip->firstUnit); -+ ip->lastUnit = le32_to_cpu(ip->lastUnit); -+ ip->flags = le32_to_cpu(ip->flags); -+ ip->spareUnits = le32_to_cpu(ip->spareUnits); -+ ip->Reserved0 = le32_to_cpu(ip->Reserved0); -+ -+#ifdef CONFIG_MTD_DEBUG_VERBOSE -+ if (CONFIG_MTD_DEBUG_VERBOSE >= 2) { -+ printk(" PARTITION[%d] ->\n" -+ " virtualUnits = %d\n" -+ " firstUnit = %d\n" -+ " lastUnit = %d\n" -+ " flags = 0x%x\n" -+ " spareUnits = %d\n", -+ i, ip->virtualUnits, ip->firstUnit, -+ ip->lastUnit, ip->flags, -+ ip->spareUnits); -+ } -+#endif -+ -+ if (ip->Reserved0 != ip->firstUnit) { -+ struct erase_info *instr = &inftl->instr; -+ -+ /* -+ * Most likely this is using the -+ * undocumented qiuck mount feature. -+ * We don't support that, we will need -+ * to erase the hidden block for full -+ * compatibility. -+ */ -+ instr->addr = ip->Reserved0 * inftl->EraseSize; -+ instr->len = inftl->EraseSize; -+ MTD_ERASE(inftl->mbd.mtd, instr); -+ } -+ if ((ip->lastUnit - ip->firstUnit + 1) < ip->virtualUnits) { -+ printk(KERN_WARNING "INFTL: Media Header " -+ "Partition %d sanity check failed\n" -+ " firstUnit %d : lastUnit %d > " -+ "virtualUnits %d\n", i, ip->lastUnit, -+ ip->firstUnit, ip->Reserved0); -+ return -1; -+ } -+ if (ip->Reserved1 != 0) { -+ printk(KERN_WARNING "INFTL: Media Header " -+ "Partition %d sanity check failed: " -+ "Reserved1 %d != 0\n", -+ i, ip->Reserved1); -+ return -1; -+ } -+ -+ if (ip->flags & INFTL_BDTL) -+ break; -+ } -+ -+ if (i >= 4) { -+ printk(KERN_WARNING "INFTL: Media Header Partition " -+ "sanity check failed:\n No partition " -+ "marked as Disk Partition\n"); -+ return -1; -+ } -+ -+ inftl->nb_boot_blocks = ip->firstUnit; -+ inftl->numvunits = ip->virtualUnits; -+ if (inftl->numvunits > (inftl->nb_blocks - -+ inftl->nb_boot_blocks - 2)) { -+ printk(KERN_WARNING "INFTL: Media Header sanity check " -+ "failed:\n numvunits (%d) > nb_blocks " -+ "(%d) - nb_boot_blocks(%d) - 2\n", -+ inftl->numvunits, inftl->nb_blocks, -+ inftl->nb_boot_blocks); -+ return -1; -+ } -+ -+ inftl->mbd.size = inftl->numvunits * -+ (inftl->EraseSize / SECTORSIZE); -+ -+ /* -+ * Block count is set to last used EUN (we won't need to keep -+ * any meta-data past that point). -+ */ -+ inftl->firstEUN = ip->firstUnit; -+ inftl->lastEUN = ip->lastUnit; -+ inftl->nb_blocks = ip->lastUnit + 1; -+ -+ /* Memory alloc */ -+ inftl->PUtable = kmalloc(inftl->nb_blocks * sizeof(u16), GFP_KERNEL); -+ if (!inftl->PUtable) { -+ printk(KERN_WARNING "INFTL: allocation of PUtable " -+ "failed (%d bytes)\n", -+ inftl->nb_blocks * sizeof(u16)); -+ return -ENOMEM; -+ } -+ -+ inftl->VUtable = kmalloc(inftl->nb_blocks * sizeof(u16), GFP_KERNEL); -+ if (!inftl->VUtable) { -+ kfree(inftl->PUtable); -+ printk(KERN_WARNING "INFTL: allocation of VUtable " -+ "failed (%d bytes)\n", -+ inftl->nb_blocks * sizeof(u16)); -+ return -ENOMEM; -+ } -+ -+ /* Mark the blocks before INFTL MediaHeader as reserved */ -+ for (i = 0; i < inftl->nb_boot_blocks; i++) -+ inftl->PUtable[i] = BLOCK_RESERVED; -+ /* Mark all remaining blocks as potentially containing data */ -+ for (; i < inftl->nb_blocks; i++) -+ inftl->PUtable[i] = BLOCK_NOTEXPLORED; -+ -+ /* Mark this boot record (NFTL MediaHeader) block as reserved */ -+ inftl->PUtable[block] = BLOCK_RESERVED; -+ -+#if 0 -+ /* Read Bad Erase Unit Table and modify PUtable[] accordingly */ -+ for (i = 0; i < inftl->nb_blocks; i++) { -+ if ((i & (SECTORSIZE - 1)) == 0) { -+ /* read one sector for every SECTORSIZE of blocks */ -+ if ((ret = MTD_READECC(inftl->mbd.mtd, -+ block * inftl->EraseSize + i + SECTORSIZE, -+ SECTORSIZE, &retlen, buf, -+ (char *)&oob, NULL)) < 0) { -+ printk(KERN_WARNING "INFTL: read of " -+ "bad sector table failed " -+ "(err %d)\n", ret); -+ kfree(inftl->VUtable); -+ kfree(inftl->PUtable); -+ return -1; -+ } -+ } -+ /* Mark the Bad Erase Unit as RESERVED in PUtable */ -+ if (buf[i & (SECTORSIZE - 1)] != 0xff) -+ inftl->PUtable[i] = BLOCK_RESERVED; -+ } -+#endif -+ -+ inftl->MediaUnit = block; -+ boot_record_count++; -+ } -+ -+ return boot_record_count ? 0 : -1; -+} -+ -+static int memcmpb(void *a, int c, int n) -+{ -+ int i; -+ for (i = 0; i < n; i++) { -+ if (c != ((unsigned char *)a)[i]) -+ return 1; -+ } -+ return 0; -+} -+ -+/* -+ * check_free_sector: check if a free sector is actually FREE, -+ * i.e. All 0xff in data and oob area. -+ */ -+static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address, -+ int len, int check_oob) -+{ -+ int i, retlen; -+ u8 buf[SECTORSIZE]; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: check_free_sectors(inftl=0x%x," -+ "address=0x%x,len=%d,check_oob=%d)\n", (int)inftl, -+ address, len, check_oob); -+ -+ for (i = 0; i < len; i += SECTORSIZE) { -+ /* -+ * We want to read the sector without ECC check here since a -+ * free sector does not have ECC syndrome on it yet. -+ */ -+ if (MTD_READ(inftl->mbd.mtd, address, SECTORSIZE, &retlen, buf) < 0) -+ return -1; -+ if (memcmpb(buf, 0xff, SECTORSIZE) != 0) -+ return -1; -+ -+ if (check_oob) { -+ if (MTD_READOOB(inftl->mbd.mtd, address, -+ inftl->mbd.mtd->oobsize, &retlen, buf) < 0) -+ return -1; -+ if (memcmpb(buf, 0xff, inftl->mbd.mtd->oobsize) != 0) -+ return -1; -+ } -+ address += SECTORSIZE; -+ } -+ -+ return 0; -+} -+ -+/* -+ * INFTL_format: format a Erase Unit by erasing ALL Erase Zones in the Erase -+ * Unit and Update INFTL metadata. Each erase operation is -+ * checked with check_free_sectors. -+ * -+ * Return: 0 when succeed, -1 on error. -+ * -+ * ToDo: 1. Is it neceressary to check_free_sector after erasing ?? -+ * 2. UnitSizeFactor != 0xFF -+ */ -+int INFTL_formatblock(struct INFTLrecord *inftl, int block) -+{ -+ int retlen; -+ struct inftl_unittail uci; -+ struct erase_info *instr = &inftl->instr; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=0x%x," -+ "block=%d)\n", (int)inftl, block); -+ -+ memset(instr, 0, sizeof(struct erase_info)); -+ -+ /* FIXME: Shouldn't we be setting the 'discarded' flag to zero -+ _first_? */ -+ -+ /* Use async erase interface, test return code */ -+ instr->addr = block * inftl->EraseSize; -+ instr->len = inftl->EraseSize; -+ MTD_ERASE(inftl->mbd.mtd, instr); -+ -+ if (instr->state == MTD_ERASE_FAILED) { -+ /* -+ * Could not format, FixMe: We should update the BadUnitTable -+ * both in memory and on disk. -+ */ -+ printk(KERN_WARNING "INFTL: error while formatting block %d\n", -+ block); -+ return -1; -+ } -+ -+ /* -+ * Check the "freeness" of Erase Unit before updating metadata. -+ * FixMe: is this check really necessary? Since we have check the -+ * return code after the erase operation. -+ */ -+ if (check_free_sectors(inftl, instr->addr, inftl->EraseSize, 1) != 0) -+ return -1; -+ -+ uci.EraseMark = cpu_to_le16(ERASE_MARK); -+ uci.EraseMark1 = cpu_to_le16(ERASE_MARK); -+ uci.Reserved[0] = 0; -+ uci.Reserved[1] = 0; -+ uci.Reserved[2] = 0; -+ uci.Reserved[3] = 0; -+ if (MTD_WRITEOOB(inftl->mbd.mtd, block * inftl->EraseSize + SECTORSIZE * 2 + -+ 8, 8, &retlen, (char *)&uci) < 0) -+ return -1; -+ return 0; -+} -+ -+/* -+ * format_chain: Format an invalid Virtual Unit chain. It frees all the Erase -+ * Units in a Virtual Unit Chain, i.e. all the units are disconnected. -+ * -+ * Since the chain is invalid then we will have to erase it from its -+ * head (normally for INFTL we go from the oldest). But if it has a -+ * loop then there is no oldest... -+ */ -+static void format_chain(struct INFTLrecord *inftl, unsigned int first_block) -+{ -+ unsigned int block = first_block, block1; -+ -+ printk(KERN_WARNING "INFTL: formatting chain at block %d\n", -+ first_block); -+ -+ for (;;) { -+ block1 = inftl->PUtable[block]; -+ -+ printk(KERN_WARNING "INFTL: formatting block %d\n", block); -+ if (INFTL_formatblock(inftl, block) < 0) { -+ /* -+ * Cannot format !!!! Mark it as Bad Unit, -+ * FixMe: update the BadUnitTable on disk. -+ */ -+ inftl->PUtable[block] = BLOCK_RESERVED; -+ } else { -+ inftl->PUtable[block] = BLOCK_FREE; -+ } -+ -+ /* Goto next block on the chain */ -+ block = block1; -+ -+ if (block == BLOCK_NIL || block >= inftl->lastEUN) -+ break; -+ } -+} -+ -+void INFTL_dumptables(struct INFTLrecord *s) -+{ -+ int i; -+ -+ printk("-------------------------------------------" -+ "----------------------------------\n"); -+ -+ printk("VUtable[%d] ->", s->nb_blocks); -+ for (i = 0; i < s->nb_blocks; i++) { -+ if ((i % 8) == 0) -+ printk("\n%04x: ", i); -+ printk("%04x ", s->VUtable[i]); -+ } -+ -+ printk("\n-------------------------------------------" -+ "----------------------------------\n"); -+ -+ printk("PUtable[%d-%d=%d] ->", s->firstEUN, s->lastEUN, s->nb_blocks); -+ for (i = 0; i <= s->lastEUN; i++) { -+ if ((i % 8) == 0) -+ printk("\n%04x: ", i); -+ printk("%04x ", s->PUtable[i]); -+ } -+ -+ printk("\n-------------------------------------------" -+ "----------------------------------\n"); -+ -+ printk("INFTL ->\n" -+ " EraseSize = %d\n" -+ " h/s/c = %d/%d/%d\n" -+ " numvunits = %d\n" -+ " firstEUN = %d\n" -+ " lastEUN = %d\n" -+ " numfreeEUNs = %d\n" -+ " LastFreeEUN = %d\n" -+ " nb_blocks = %d\n" -+ " nb_boot_blocks = %d", -+ s->EraseSize, s->heads, s->sectors, s->cylinders, -+ s->numvunits, s->firstEUN, s->lastEUN, s->numfreeEUNs, -+ s->LastFreeEUN, s->nb_blocks, s->nb_boot_blocks); -+ -+ printk("\n-------------------------------------------" -+ "----------------------------------\n"); -+} -+ -+void INFTL_dumpVUchains(struct INFTLrecord *s) -+{ -+ int logical, block, i; -+ -+ printk("-------------------------------------------" -+ "----------------------------------\n"); -+ -+ printk("INFTL Virtual Unit Chains:\n"); -+ for (logical = 0; logical < s->nb_blocks; logical++) { -+ block = s->VUtable[logical]; -+ if (block > s->nb_blocks) -+ continue; -+ printk(" LOGICAL %d --> %d ", logical, block); -+ for (i = 0; i < s->nb_blocks; i++) { -+ if (s->PUtable[block] == BLOCK_NIL) -+ break; -+ block = s->PUtable[block]; -+ printk("%d ", block); -+ } -+ printk("\n"); -+ } -+ -+ printk("-------------------------------------------" -+ "----------------------------------\n"); -+} -+ -+int INFTL_mount(struct INFTLrecord *s) -+{ -+ unsigned int block, first_block, prev_block, last_block; -+ unsigned int first_logical_block, logical_block, erase_mark; -+ int chain_length, do_format_chain; -+ struct inftl_unithead1 h0; -+ struct inftl_unittail h1; -+ int i, retlen; -+ u8 *ANACtable, ANAC; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_mount(inftl=0x%x)\n", (int)s); -+ -+ /* Search for INFTL MediaHeader and Spare INFTL Media Header */ -+ if (find_boot_record(s) < 0) { -+ printk(KERN_WARNING "INFTL: could not find valid boot record?\n"); -+ return -1; -+ } -+ -+ /* Init the logical to physical table */ -+ for (i = 0; i < s->nb_blocks; i++) -+ s->VUtable[i] = BLOCK_NIL; -+ -+ logical_block = block = BLOCK_NIL; -+ -+ /* Temporary buffer to store ANAC numbers. */ -+ ANACtable = kmalloc(s->nb_blocks * sizeof(u8), GFP_KERNEL); -+ memset(ANACtable, 0, s->nb_blocks); -+ -+ /* -+ * First pass is to explore each physical unit, and construct the -+ * virtual chains that exist (newest physical unit goes into VUtable). -+ * Any block that is in any way invalid will be left in the -+ * NOTEXPLORED state. Then at the end we will try to format it and -+ * mark it as free. -+ */ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 1, explore each unit\n"); -+ for (first_block = s->firstEUN; first_block <= s->lastEUN; first_block++) { -+ if (s->PUtable[first_block] != BLOCK_NOTEXPLORED) -+ continue; -+ -+ do_format_chain = 0; -+ first_logical_block = BLOCK_NIL; -+ last_block = BLOCK_NIL; -+ block = first_block; -+ -+ for (chain_length = 0; ; chain_length++) { -+ -+ if ((chain_length == 0) && -+ (s->PUtable[block] != BLOCK_NOTEXPLORED)) { -+ /* Nothing to do here, onto next block */ -+ break; -+ } -+ -+ if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, -+ 8, &retlen, (char *)&h0) < 0 || -+ MTD_READOOB(s->mbd.mtd, block * s->EraseSize + -+ 2 * SECTORSIZE + 8, 8, &retlen, (char *)&h1) < 0) { -+ /* Should never happen? */ -+ do_format_chain++; -+ break; -+ } -+ -+ logical_block = le16_to_cpu(h0.virtualUnitNo); -+ prev_block = le16_to_cpu(h0.prevUnitNo); -+ erase_mark = le16_to_cpu((h1.EraseMark | h1.EraseMark1)); -+ ANACtable[block] = h0.ANAC; -+ -+ /* Previous block is relative to start of Partition */ -+ if (prev_block < s->nb_blocks) -+ prev_block += s->firstEUN; -+ -+ /* Already explored partial chain? */ -+ if (s->PUtable[block] != BLOCK_NOTEXPLORED) { -+ /* Check if chain for this logical */ -+ if (logical_block == first_logical_block) { -+ if (last_block != BLOCK_NIL) -+ s->PUtable[last_block] = block; -+ } -+ break; -+ } -+ -+ /* Check for invalid block */ -+ if (erase_mark != ERASE_MARK) { -+ printk(KERN_WARNING "INFTL: corrupt block %d " -+ "in chain %d, chain length %d, erase " -+ "mark 0x%x?\n", block, first_block, -+ chain_length, erase_mark); -+ /* -+ * Assume end of chain, probably incomplete -+ * fold/erase... -+ */ -+ if (chain_length == 0) -+ do_format_chain++; -+ break; -+ } -+ -+ /* Check for it being free already then... */ -+ if ((logical_block == BLOCK_FREE) || -+ (logical_block == BLOCK_NIL)) { -+ s->PUtable[block] = BLOCK_FREE; -+ break; -+ } -+ -+ /* Sanity checks on block numbers */ -+ if ((logical_block >= s->nb_blocks) || -+ ((prev_block >= s->nb_blocks) && -+ (prev_block != BLOCK_NIL))) { -+ if (chain_length > 0) { -+ printk(KERN_WARNING "INFTL: corrupt " -+ "block %d in chain %d?\n", -+ block, first_block); -+ do_format_chain++; -+ } -+ break; -+ } -+ -+ if (first_logical_block == BLOCK_NIL) { -+ first_logical_block = logical_block; -+ } else { -+ if (first_logical_block != logical_block) { -+ /* Normal for folded chain... */ -+ break; -+ } -+ } -+ -+ /* -+ * Current block is valid, so if we followed a virtual -+ * chain to get here then we can set the previous -+ * block pointer in our PUtable now. Then move onto -+ * the previous block in the chain. -+ */ -+ s->PUtable[block] = BLOCK_NIL; -+ if (last_block != BLOCK_NIL) -+ s->PUtable[last_block] = block; -+ last_block = block; -+ block = prev_block; -+ -+ /* Check for end of chain */ -+ if (block == BLOCK_NIL) -+ break; -+ -+ /* Validate next block before following it... */ -+ if (block > s->lastEUN) { -+ printk(KERN_WARNING "INFTL: invalid previous " -+ "block %d in chain %d?\n", block, -+ first_block); -+ do_format_chain++; -+ break; -+ } -+ } -+ -+ if (do_format_chain) { -+ format_chain(s, first_block); -+ continue; -+ } -+ -+ /* -+ * Looks like a valid chain then. It may not really be the -+ * newest block in the chain, but it is the newest we have -+ * found so far. We might update it in later iterations of -+ * this loop if we find something newer. -+ */ -+ s->VUtable[first_logical_block] = first_block; -+ logical_block = BLOCK_NIL; -+ } -+ -+#ifdef CONFIG_MTD_DEBUG_VERBOSE -+ if (CONFIG_MTD_DEBUG_VERBOSE >= 2) -+ INFTL_dumptables(s); -+#endif -+ -+ /* -+ * Second pass, check for infinite loops in chains. These are -+ * possible because we don't update the previous pointers when -+ * we fold chains. No big deal, just fix them up in PUtable. -+ */ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 2, validate virtual chains\n"); -+ for (logical_block = 0; logical_block < s->numvunits; logical_block++) { -+ block = s->VUtable[logical_block]; -+ last_block = BLOCK_NIL; -+ -+ /* Check for free/reserved/nil */ -+ if (block >= BLOCK_RESERVED) -+ continue; -+ -+ ANAC = ANACtable[block]; -+ for (i = 0; i < s->numvunits; i++) { -+ if (s->PUtable[block] == BLOCK_NIL) -+ break; -+ if (s->PUtable[block] > s->lastEUN) { -+ printk(KERN_WARNING "INFTL: invalid prev %d, " -+ "in virtual chain %d\n", -+ s->PUtable[block], logical_block); -+ s->PUtable[block] = BLOCK_NIL; -+ -+ } -+ if (ANACtable[block] != ANAC) { -+ /* -+ * Chain must point back to itself. This is ok, -+ * but we will need adjust the tables with this -+ * newest block and oldest block. -+ */ -+ s->VUtable[logical_block] = block; -+ s->PUtable[last_block] = BLOCK_NIL; -+ break; -+ } -+ -+ ANAC--; -+ last_block = block; -+ block = s->PUtable[block]; -+ } -+ -+ if (i >= s->nb_blocks) { -+ /* -+ * Uhoo, infinite chain with valid ANACS! -+ * Format whole chain... -+ */ -+ format_chain(s, first_block); -+ } -+ } -+ -+#ifdef CONFIG_MTD_DEBUG_VERBOSE -+ if (CONFIG_MTD_DEBUG_VERBOSE >= 2) -+ INFTL_dumptables(s); -+ if (CONFIG_MTD_DEBUG_VERBOSE >= 2) -+ INFTL_dumpVUchains(s); -+#endif -+ -+ /* -+ * Third pass, format unreferenced blocks and init free block count. -+ */ -+ s->numfreeEUNs = 0; -+ s->LastFreeEUN = BLOCK_NIL; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 3, format unused blocks\n"); -+ for (block = s->firstEUN; block <= s->lastEUN; block++) { -+ if (s->PUtable[block] == BLOCK_NOTEXPLORED) { -+ printk("INFTL: unreferenced block %d, formatting it\n", -+ block); -+ if (INFTL_formatblock(s, block) < 0) -+ s->PUtable[block] = BLOCK_RESERVED; -+ else -+ s->PUtable[block] = BLOCK_FREE; -+ } -+ if (s->PUtable[block] == BLOCK_FREE) { -+ s->numfreeEUNs++; -+ if (s->LastFreeEUN == BLOCK_NIL) -+ s->LastFreeEUN = block; -+ } -+ } -+ -+ kfree(ANACtable); -+ return 0; -+} -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/Config.in linux/drivers/mtd/maps/Config.in ---- linux-mips-2.4.27/drivers/mtd/maps/Config.in 2004-02-26 01:46:35.000000000 +0100 -+++ linux/drivers/mtd/maps/Config.in 2004-11-19 10:25:11.888201464 +0100 -@@ -1,17 +1,14 @@ - # drivers/mtd/maps/Config.in - --# $Id$ -+# $Id$ - - mainmenu_option next_comment - - comment 'Mapping drivers for chip access' - --dep_tristate ' CFI Flash device in physical memory map' CONFIG_MTD_PHYSMAP $CONFIG_MTD_GEN_PROBE --if [ "$CONFIG_MTD_PHYSMAP" = "y" -o "$CONFIG_MTD_PHYSMAP" = "m" ]; then -- hex ' Physical start address of flash mapping' CONFIG_MTD_PHYSMAP_START 0x8000000 -- hex ' Physical length of flash mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000 -- int ' Bus width in octets' CONFIG_MTD_PHYSMAP_BUSWIDTH 2 --fi -+bool ' Support for non-linear mappings of flash chips' CONFIG_MTD_COMPLEX_MAPPINGS -+ -+bool ' CFI Flash device in physical memory map' CONFIG_MTD_PHYSMAP $CONFIG_MTD_GEN_PROBE - - if [ "$CONFIG_SPARC" = "y" -o "$CONFIG_SPARC64" = "y" ]; then - dep_tristate ' Sun Microsystems userflash support' CONFIG_MTD_SUN_UFLASH $CONFIG_MTD_CFI -@@ -21,56 +18,68 @@ - dep_tristate ' CFI Flash device mapped on Photron PNC-2000' CONFIG_MTD_PNC2000 $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS - dep_tristate ' CFI Flash device mapped on AMD SC520 CDP' CONFIG_MTD_SC520CDP $CONFIG_MTD_CFI - dep_tristate ' CFI Flash device mapped on AMD NetSc520' CONFIG_MTD_NETSC520 $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS -- dep_tristate ' CFI Flash device mapped on Arcom SBC-GXx boards' CONFIG_MTD_SBC_GXX $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_PARTITIONS -- dep_tristate ' CFI Flash device mapped on Arcom ELAN-104NC' CONFIG_MTD_ELAN_104NC $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_PARTITIONS -+ dep_tristate ' CFI Flash device mapped on Arcom SBC-GXx boards' CONFIG_MTD_SBC_GXX $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_PARTITIONS $CONFIG_MTD_COMPLEX_MAPPINGS -+ dep_tristate ' CFI Flash device mapped on Arcom ELAN-104NC' CONFIG_MTD_ELAN_104NC $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_PARTITIONS $CONFIG_MTD_COMPLEX_MAPPINGS - dep_tristate ' CFI Flash device mapped on DIL/Net PC' CONFIG_MTD_DILNETPC $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_PARTITIONS $CONFIG_MTD_CONCAT - if [ "$CONFIG_MTD_DILNETPC" = "y" -o "$CONFIG_MTD_DILNETPC" = "m" ]; then - hex ' Size of boot partition' CONFIG_MTD_DILNETPC_BOOTSIZE 0x80000 - fi -- dep_tristate ' JEDEC Flash device mapped on Mixcom piggyback card' CONFIG_MTD_MIXMEM $CONFIG_MTD_JEDEC -- dep_tristate ' JEDEC Flash device mapped on Octagon 5066 SBC' CONFIG_MTD_OCTAGON $CONFIG_MTD_JEDEC -- dep_tristate ' JEDEC Flash device mapped on Tempustech VMAX SBC301' CONFIG_MTD_VMAX $CONFIG_MTD_JEDEC -+ dep_tristate ' JEDEC Flash device mapped on Octagon 5066 SBC' CONFIG_MTD_OCTAGON $CONFIG_MTD_JEDEC $CONFIG_MTD_COMPLEX_MAPPINGS -+ dep_tristate ' JEDEC Flash device mapped on Tempustech VMAX SBC301' CONFIG_MTD_VMAX $CONFIG_MTD_JEDEC $CONFIG_MTD_COMPLEX_MAPPINGS - dep_tristate ' Flash device mapped with DOCCS on NatSemi SCx200' CONFIG_MTD_SCx200_DOCFLASH $CONFIG_MTD_CFI - dep_tristate ' BIOS flash chip on Intel L440GX boards' CONFIG_MTD_L440GX $CONFIG_MTD_JEDECPROBE - dep_tristate ' ROM connected to AMD76X southbridge' CONFIG_MTD_AMD76XROM $CONFIG_MTD_GEN_PROBE -- dep_tristate ' ROM connected to Intel Hub Controller 2' CONFIG_MTD_ICH2ROM $CONFIG_MTD_JEDECPROBE -+ dep_tristate ' ROM connected to Intel Hub Controller 2/3/4/5' CONFIG_MTD_ICHXROM $CONFIG_MTD_JEDECPROBE $CONFIG_MTD_COMPLEX_MAPPINGS - dep_tristate ' CFI Flash device mapped on SnapGear/SecureEdge' CONFIG_MTD_NETtel $CONFIG_MTD_PARTITIONS - dep_tristate ' BIOS flash chip on Intel SCB2 boards' CONFIG_MTD_SCB2_FLASH $CONFIG_MTD_GEN_PROBE - fi - --if [ "$CONFIG_PPC" = "y" ]; then -- dep_tristate ' CFI Flash device mapped on TQM8XXL' CONFIG_MTD_TQM8XXL $CONFIG_MTD_CFI $CONFIG_TQM8xxL -+if [ "$CONFIG_PPC32" = "y" ]; then -+ if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "y" ]; then -+ dep_tristate ' Flash device on SBC8240' CONFIG_MTD_SBC8240 $CONFIG_MTD_JEDECPROBE -+ fi -+ if [ "$CONFIG_8xx" = "y" ]; then -+ if [ "$CONFIG_TQM8xxL" = "y" ]; then -+ dep_tristate ' CFI Flash device mapped on TQM8XXL' CONFIG_MTD_TQM8XXL $CONFIG_MTD_CFI -+ fi -+ if [ "$CONFIG_RPXLITE" = "y" -o "$CONFIG_RPXCLASSIC" = "y" ]; then - dep_tristate ' CFI Flash device mapped on RPX Lite or CLLF' CONFIG_MTD_RPXLITE $CONFIG_MTD_CFI -+ fi -+ if [ "$CONFIG_MBX" = "y" ]; then - dep_tristate ' System flash on MBX860 board' CONFIG_MTD_MBX860 $CONFIG_MTD_CFI -+ fi -+ if [ "$CONFIG_DBOX2" = "y" ]; then - dep_tristate ' CFI Flash device mapped on D-Box2' CONFIG_MTD_DBOX2 $CONFIG_MTD_CFI -+ fi - dep_tristate ' CFI Flash device mapping on FlagaDM' CONFIG_MTD_CFI_FLAGADM $CONFIG_MTD_CFI -- dep_tristate ' CFI Flash device mapped on IBM Redwood-4/5' CONFIG_MTD_REDWOOD $CONFIG_MTD_CFI -+ fi -+ if [ "$CONFIG_4xx" = "y" ]; then -+ if [ "$CONFIG_40x" = "y" ]; then -+ if [ "$CONFIG_REDWOOD_4" = "y" -o "$CONFIG_REDWOOD_5" = "y" -o "$CONFIG_REDWOOD_6" = "y" ]; then -+ dep_tristate ' CFI Flash device mapped on IBM Redwood' CONFIG_MTD_REDWOOD $CONFIG_MTD_CFI -+ fi -+ dep_tristate ' CFI Flash device mapped on IBM Beech' CONFIG_MTD_BEECH $CONFIG_MTD_CFI $CONFIG_BEECH -+ dep_tristate ' CFI Flash device mapped on IBM Arctic' CONFIG_MTD_ARCTIC $CONFIG_MTD_CFI $CONFIG_ARCTIC2 -+ fi -+ if [ "$CONFIG_440" = "y" ]; then -+ dep_tristate ' Flash devices mapped on IBM Ebony' CONFIG_MTD_EBONY $CONFIG_MTD_CFI $CONFIG_EBONY -+ fi -+ fi - fi - --if [ "$CONFIG_MIPS" = "y" ]; then -- dep_tristate ' Pb1000 MTD support' CONFIG_MTD_PB1000 $CONFIG_MIPS_PB1000 -- dep_tristate ' Pb1500 MTD support' CONFIG_MTD_PB1500 $CONFIG_MIPS_PB1500 -- dep_tristate ' Pb1100 MTD support' CONFIG_MTD_PB1100 $CONFIG_MIPS_PB1100 -- dep_tristate ' Bosporus MTD support' CONFIG_MTD_BOSPORUS $CONFIG_MIPS_BOSPORUS -- dep_tristate ' XXS1500 boot flash device' CONFIG_MTD_XXS1500 $CONFIG_MIPS_XXS1500 -- dep_tristate ' MTX-1 flash device' CONFIG_MTD_MTX1 $CONFIG_MIPS_MTX1 -- if [ "$CONFIG_MTD_PB1500" = "y" -o "$CONFIG_MTD_PB1500" = "m" \ -- -o "$CONFIG_MTD_PB1100" = "y" -o "$CONFIG_MTD_PB1100" = "m" ]; then -- bool ' Pb[15]00 boot flash device' CONFIG_MTD_PB1500_BOOT -- bool ' Pb[15]00 user flash device (2nd 32MiB bank)' CONFIG_MTD_PB1500_USER -+if [ "$CONFIG_MIPS" = "y" -o "$CONFIG_MIPS64" = "y" ]; then -+ if [ "$CONFIG_MIPS_PB1000" = "y" -o "$CONFIG_MIPS_PB1100" = "y" -o "$CONFIG_MIPS_PB1500" = "y" ]; then -+ tristate ' Pb1x00 MTD support' CONFIG_MTD_PB1XXX -+ if [ "$CONFIG_MIPS_PB1500" = "y" -o "$CONFIG_MIPS_PB1100" = "m" ]; then -+ bool ' Pb1x00 boot flash device' CONFIG_MTD_PB1500_BOOT -+ bool ' Pb1x00 user flash device (2nd 32MiB bank)' CONFIG_MTD_PB1500_USER -+ fi - fi - tristate ' Db1x00 MTD support' CONFIG_MTD_DB1X00 - if [ "$CONFIG_MTD_DB1X00" = "y" -o "$CONFIG_MTD_DB1X00" = "m" ]; then - bool ' Db1x00 boot flash device' CONFIG_MTD_DB1X00_BOOT - bool ' Db1x00 user flash device (2nd bank)' CONFIG_MTD_DB1X00_USER - fi -- tristate ' Pb1550 MTD support' CONFIG_MTD_PB1550 -- if [ "$CONFIG_MTD_PB1550" = "y" -o "$CONFIG_MTD_PB1550" = "m" ]; then -- bool ' Pb1550 Boot Flash' CONFIG_MTD_PB1550_BOOT -- bool ' Pb1550 User Parameter Flash' CONFIG_MTD_PB1550_USER -- fi -- dep_tristate ' Hydrogen 3 MTD support' CONFIG_MTD_HYDROGEN3 $CONFIG_MIPS_HYDROGEN3 -- dep_tristate ' Mirage MTD support' CONFIG_MTD_MIRAGE $CONFIG_MIPS_MIRAGE - dep_tristate ' Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board' CONFIG_MTD_CSTM_MIPS_IXX $CONFIG_MTD_CFI $CONFIG_MTD_JEDEC $CONFIG_MTD_PARTITIONS - if [ "$CONFIG_MTD_CSTM_MIPS_IXX" = "y" -o "$CONFIG_MTD_CSTM_MIPS_IXX" = "m" ]; then - hex ' Physical start address of flash mapping' CONFIG_MTD_CSTM_MIPS_IXX_START 0x8000000 -@@ -78,7 +87,7 @@ - int ' Bus width in octets' CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH 2 - fi - dep_tristate ' Momenco Ocelot boot flash device' CONFIG_MTD_OCELOT $CONFIG_MOMENCO_OCELOT -- dep_tristate ' LASAT flash device' CONFIG_MTD_LASAT $CONFIG_MTD_CFI $CONFIG_LASAT -+ dep_tristate ' LASAT flash device' CONFIG_MTD_LASAT $CONFIG_LASAT - fi - - if [ "$CONFIG_SUPERH" = "y" ]; then -@@ -90,21 +99,24 @@ - fi - - if [ "$CONFIG_ARM" = "y" ]; then -- dep_tristate ' CFI Flash device mapped on Nora' CONFIG_MTD_NORA $CONFIG_MTD_CFI - dep_tristate ' CFI Flash device mapped on ARM Integrator/P720T' CONFIG_MTD_ARM_INTEGRATOR $CONFIG_MTD_CFI - dep_tristate ' Cirrus CDB89712 evaluation board mappings' CONFIG_MTD_CDB89712 $CONFIG_MTD_CFI $CONFIG_ARCH_CDB89712 - dep_tristate ' CFI Flash device mapped on StrongARM SA11x0' CONFIG_MTD_SA1100 $CONFIG_MTD_CFI $CONFIG_ARCH_SA1100 $CONFIG_MTD_PARTITIONS -- dep_tristate ' CFI Flash device mapped on DC21285 Footbridge' CONFIG_MTD_DC21285 $CONFIG_MTD_CFI $CONFIG_ARCH_FOOTBRIDGE -+ dep_tristate ' CFI Flash device mapped on DC21285 Footbridge' CONFIG_MTD_DC21285 $CONFIG_MTD_CFI $CONFIG_ARCH_FOOTBRIDGE $CONFIG_MTD_COMPLEX_MAPPINGS - dep_tristate ' CFI Flash device mapped on the XScale IQ80310 board' CONFIG_MTD_IQ80310 $CONFIG_MTD_CFI $CONFIG_ARCH_IQ80310 -+ dep_tristate ' CFI Flash device mapped on the XScale Lubbock board' CONFIG_MTD_LUBBOCK $CONFIG_MTD_CFI $CONFIG_ARCH_LUBBOCK -+ dep_tristate ' CFI Flash device mapped on XScale IXP425 systems' CONFIG_MTD_IXP425 $CONFIG_MTD_CFI $CONFIG_MTD_COMPLEX_MAPPINGS - dep_tristate ' CFI Flash device mapped on Epxa10db' CONFIG_MTD_EPXA10DB $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_CAMELOT - dep_tristate ' CFI Flash device mapped on the FortuNet board' CONFIG_MTD_FORTUNET $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_SA1100_FORTUNET - dep_tristate ' NV-RAM mapping AUTCPU12 board' CONFIG_MTD_AUTCPU12 $CONFIG_ARCH_AUTCPU12 - dep_tristate ' CFI Flash device mapped on EDB7312' CONFIG_MTD_EDB7312 $CONFIG_MTD_CFI -+ dep_tristate ' CFI Flash device mapped on Hynix evaluation boards' CONFIG_MTD_H720X $CONFIG_MTD_CFI - dep_tristate ' JEDEC Flash device mapped on impA7' CONFIG_MTD_IMPA7 $CONFIG_MTD_JEDECPROBE - dep_tristate ' JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame' CONFIG_MTD_CEIVA $CONFIG_MTD_JEDECPROBE $CONFIG_ARCH_CEIVA -+ dep_tristate ' NOR Flash device on TOTO board' CONFIG_MTD_NOR_TOTO $CONFIG_MTD $CONFIG_OMAP_TOTO - fi - if [ "$CONFIG_ALPHA" = "y" ]; then -- dep_tristate ' Flash chip mapping on TSUNAMI' CONFIG_MTD_TSUNAMI $CONFIG_MTD_GENPROBE -+ dep_tristate ' Flash chip mapping on TSUNAMI' CONFIG_MTD_TSUNAMI $CONFIG_MTD_GENPROBE $CONFIG_MTD_COMPLEX_MAPPINGS - fi - - if [ "$CONFIG_UCLINUX" = "y" ]; then -@@ -112,7 +124,7 @@ - fi - - # This needs CFI or JEDEC, depending on the cards found. --dep_tristate ' PCI MTD driver' CONFIG_MTD_PCI $CONFIG_MTD $CONFIG_PCI --dep_tristate ' PCMCIA MTD driver' CONFIG_MTD_PCMCIA $CONFIG_MTD $CONFIG_PCMCIA -+dep_tristate ' PCI MTD driver' CONFIG_MTD_PCI $CONFIG_MTD $CONFIG_PCI $CONFIG_MTD_COMPLEX_MAPPINGS -+dep_tristate ' PCMCIA MTD driver' CONFIG_MTD_PCMCIA $CONFIG_MTD $CONFIG_PCMCIA $CONFIG_MTD_COMPLEX_MAPPINGS - - endmenu -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/Makefile linux/drivers/mtd/maps/Makefile ---- linux-mips-2.4.27/drivers/mtd/maps/Makefile 2004-02-26 01:46:35.000000000 +0100 -+++ linux/drivers/mtd/maps/Makefile 2004-11-19 10:25:11.890201160 +0100 -@@ -1,12 +1,16 @@ - # - # linux/drivers/maps/Makefile - # --# $Id$ -+# $Id$ - --BELOW25 := $(shell echo $(PATCHLEVEL) | sed s/[1234]/y/) -- --ifeq ($(BELOW25),y) -+ifeq ($(PATCHLEVEL),4) - O_TARGET := mapslink.o -+export-objs := map_funcs.o -+endif -+ -+ -+ifeq ($(CONFIG_MTD_COMPLEX_MAPPINGS),y) -+obj-$(CONFIG_MTD) += map_funcs.o - endif - - # Chip mappings -@@ -21,19 +25,13 @@ - obj-$(CONFIG_MTD_IQ80310) += iq80310.o - obj-$(CONFIG_MTD_L440GX) += l440gx.o - obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o --obj-$(CONFIG_MTD_ICH2ROM) += ich2rom.o -+obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o - obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o -+obj-$(CONFIG_MTD_LUBBOCK) += lubbock-flash.o - obj-$(CONFIG_MTD_MBX860) += mbx860.o --obj-$(CONFIG_MTD_NORA) += nora.o - obj-$(CONFIG_MTD_CEIVA) += ceiva.o - obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o --ifneq ($(CONFIG_MTD_PHYSMAP),n) -- ifeq ($(CONFIG_MTD_PHYSMAP_BUSWIDTH),8) -- obj-$(CONFIG_MTD_PHYSMAP) += physmap64.o -- else -- obj-$(CONFIG_MTD_PHYSMAP) += physmap.o -- endif --endif -+obj-$(CONFIG_MTD_PHYSMAP) += physmap.o - obj-$(CONFIG_MTD_PNC2000) += pnc2000.o - obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o - obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o -@@ -49,16 +47,9 @@ - obj-$(CONFIG_MTD_OCELOT) += ocelot.o - obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o - obj-$(CONFIG_MTD_PCI) += pci.o --obj-$(CONFIG_MTD_PB1000) += pb1xxx-flash.o --obj-$(CONFIG_MTD_PB1100) += pb1xxx-flash.o --obj-$(CONFIG_MTD_PB1500) += pb1xxx-flash.o --obj-$(CONFIG_MTD_XXS1500) += xxs1500.o --obj-$(CONFIG_MTD_MTX1) += mtx-1.o --obj-$(CONFIG_MTD_LASAT) += lasat.o -+obj-$(CONFIG_MTD_PB1XXX) += pb1xxx-flash.o - obj-$(CONFIG_MTD_DB1X00) += db1x00-flash.o --obj-$(CONFIG_MTD_PB1550) += pb1550-flash.o --obj-$(CONFIG_MTD_HYDROGEN3) += hydrogen3-flash.o --obj-$(CONFIG_MTD_BOSPORUS) += pb1xxx-flash.o -+obj-$(CONFIG_MTD_LASAT) += lasat.o - obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o - obj-$(CONFIG_MTD_EDB7312) += edb7312.o - obj-$(CONFIG_MTD_IMPA7) += impa7.o -@@ -67,6 +58,13 @@ - obj-$(CONFIG_MTD_UCLINUX) += uclinux.o - obj-$(CONFIG_MTD_NETtel) += nettel.o - obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o --obj-$(CONFIG_MTD_MIRAGE) += mirage-flash.o -+obj-$(CONFIG_MTD_EBONY) += ebony.o -+obj-$(CONFIG_MTD_BEECH) += beech-mtd.o -+obj-$(CONFIG_MTD_ARCTIC) += arctic-mtd.o -+obj-$(CONFIG_MTD_H720X) += h720x-flash.o -+obj-$(CONFIG_MTD_SBC8240) += sbc8240.o -+obj-$(CONFIG_MTD_NOR_TOTO) += omap-toto-flash.o -+obj-$(CONFIG_MTD_MPC1211) += mpc1211.o -+obj-$(CONFIG_MTD_IXP425) += ixp425.o - --include $(TOPDIR)/Rules.make -+-include $(TOPDIR)/Rules.make -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/amd76xrom.c linux/drivers/mtd/maps/amd76xrom.c ---- linux-mips-2.4.27/drivers/mtd/maps/amd76xrom.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/maps/amd76xrom.c 2004-11-19 10:25:11.891201008 +0100 -@@ -2,12 +2,13 @@ - * amd76xrom.c - * - * Normal mappings of chips in physical memory -- * $Id$ -+ * $Id$ - */ - - #include - #include - #include -+#include - #include - #include - #include -@@ -16,77 +17,59 @@ - #include - - -+#define xstr(s) str(s) -+#define str(s) #s -+#define MOD_NAME xstr(KBUILD_BASENAME) -+ -+#define MTD_DEV_NAME_LENGTH 16 -+ - struct amd76xrom_map_info { - struct map_info map; - struct mtd_info *mtd; - unsigned long window_addr; - u32 window_start, window_size; - struct pci_dev *pdev; -+ struct resource window_rsrc; -+ struct resource rom_rsrc; -+ char mtd_name[MTD_DEV_NAME_LENGTH]; - }; - --static __u8 amd76xrom_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --static __u16 amd76xrom_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} - --static __u32 amd76xrom_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -+static struct amd76xrom_map_info amd76xrom_map = { -+ .map = { -+ .name = MOD_NAME, -+ .size = 0, -+ .buswidth = 1, -+ } -+ /* remaining fields of structure are initialized to 0 */ -+}; - --static void amd76xrom_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} - --static void amd76xrom_write8(struct map_info *map, __u8 d, unsigned long adr) -+static void amd76xrom_cleanup(struct amd76xrom_map_info *info) - { -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -+ u8 byte; - --static void amd76xrom_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -+ /* Disable writes through the rom window */ -+ pci_read_config_byte(info->pdev, 0x40, &byte); -+ pci_write_config_byte(info->pdev, 0x40, byte & ~1); - --static void amd76xrom_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -+ if (info->mtd) { -+ del_mtd_device(info->mtd); -+ map_destroy(info->mtd); -+ info->mtd = NULL; -+ info->map.virt = 0; -+ } -+ if (info->rom_rsrc.parent) -+ release_resource(&info->rom_rsrc); -+ if (info->window_rsrc.parent) -+ release_resource(&info->window_rsrc); - --static void amd76xrom_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); -+ if (info->window_addr) { -+ iounmap((void *)(info->window_addr)); -+ info->window_addr = 0; -+ } - } - --static struct amd76xrom_map_info amd76xrom_map = { -- map: { -- name: "AMD76X rom", -- size: 0, -- buswidth: 1, -- read8: amd76xrom_read8, -- read16: amd76xrom_read16, -- read32: amd76xrom_read32, -- copy_from: amd76xrom_copy_from, -- write8: amd76xrom_write8, -- write16: amd76xrom_write16, -- write32: amd76xrom_write32, -- copy_to: amd76xrom_copy_to, -- /* The standard rom socket is for single power supply chips -- * that don't have an extra vpp. -- */ -- }, -- mtd: 0, -- window_addr: 0, --}; - - static int __devinit amd76xrom_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) -@@ -97,6 +80,10 @@ - u8 segen_bits; - }; - static struct rom_window rom_window[] = { -+ /* -+ * Need the 5MiB window for chips that have block lock/unlock -+ * registers located below 4MiB window. -+ */ - { 0xffb00000, 5*1024*1024, (1<<7) | (1<<6), }, - { 0xffc00000, 4*1024*1024, (1<<7), }, - { 0xffff0000, 64*1024, 0 }, -@@ -112,19 +99,29 @@ - int i; - u32 rom_size; - -+ info->pdev = pdev; - window = &rom_window[0]; --#if 0 -- while(window->size) { -- if (request_mem_region(window->start, window->size, "amd76xrom")) { -- break; -- } -- window++; -- } -- if (!window->size) { -- printk(KERN_ERR "amd76xrom: cannot reserve rom window\n"); -- goto err_out_none; -+ -+ while (window->size) { -+ /* -+ * Try to reserve the window mem region. If this fails then -+ * it is likely due to a fragment of the window being -+ * "reseved" by the BIOS. In the case that the -+ * request_mem_region() fails then once the rom size is -+ * discovered we will try to reserve the unreserved fragment. -+ */ -+ info->window_rsrc.name = MOD_NAME; -+ info->window_rsrc.start = window->start; -+ info->window_rsrc.end = window->start + window->size - 1; -+ info->window_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; -+ if (request_resource(&iomem_resource, &info->window_rsrc)) { -+ info->window_rsrc.parent = NULL; -+ printk(KERN_ERR MOD_NAME -+ " %s(): Unable to register resource" -+ " 0x%.08lx-0x%.08lx - kernel bug?\n", -+ __func__, -+ info->window_rsrc.start, info->window_rsrc.end); - } --#endif - - /* Enable the selected rom window */ - pci_read_config_byte(pdev, 0x43, &byte); -@@ -136,49 +133,94 @@ - - /* FIXME handle registers 0x80 - 0x8C the bios region locks */ - -- printk(KERN_NOTICE "amd76xrom window : %x at %x\n", -+ printk(KERN_NOTICE MOD_NAME " window : %x at %x\n", - window->size, window->start); - /* For write accesses caches are useless */ -- info->window_addr = (unsigned long)ioremap_nocache(window->start, window->size); -+ info->window_addr = -+ (unsigned long)ioremap_nocache(window->start, -+ window->size); - - if (!info->window_addr) { - printk(KERN_ERR "Failed to ioremap\n"); -- goto err_out_free_mmio_region; -+ continue; - } -- info->mtd = 0; -+ -+ info->mtd = NULL; -+ - for(i = 0; (rom_size = rom_probe_sizes[i]); i++) { - char **chip_type; - if (rom_size > window->size) { - continue; - } -- info->map.map_priv_1 = -+ info->map.phys = window->start + window->size - rom_size; -+ info->map.virt = - info->window_addr + window->size - rom_size; - info->map.size = rom_size; -+ simple_map_init(&info->map); - chip_type = rom_probe_types; - for(; !info->mtd && *chip_type; chip_type++) { - info->mtd = do_map_probe(*chip_type, &amd76xrom_map.map); - } -- if (info->mtd) { -- break; -- } -+ if (info->mtd) goto found_mtd; - } -- if (!info->mtd) { -- goto err_out_iounmap; -+ iounmap((void *)(info->window_addr)); -+ info->window_addr = 0; -+ -+ /* Disable writes through the rom window */ -+ pci_read_config_byte(pdev, 0x40, &byte); -+ pci_write_config_byte(pdev, 0x40, byte & ~1); -+ -+ window++; - } -- printk(KERN_NOTICE "amd76xrom chip at offset: %x\n", -+ goto failed; -+ -+ found_mtd: -+ printk(KERN_NOTICE MOD_NAME " chip at offset: 0x%x\n", - window->size - rom_size); - -- info->mtd->module = THIS_MODULE; -+ info->mtd->owner = THIS_MODULE; -+ -+ if (!info->window_rsrc.parent) { -+ /* failed to reserve entire window - try fragments */ -+ info->window_rsrc.name = MOD_NAME; -+ info->window_rsrc.start = window->start; -+ info->window_rsrc.end = window->start + window->size - rom_size - 1; -+ info->window_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; -+ if (request_resource(&iomem_resource, &info->window_rsrc)) { -+ printk(KERN_ERR MOD_NAME -+ ": cannot reserve window resource fragment\n"); -+ goto failed; -+ } -+ } -+ - add_mtd_device(info->mtd); - info->window_start = window->start; - info->window_size = window->size; -+ -+ if (info->window_rsrc.parent) { -+ /* -+ * Registering the MTD device in iomem may not be possible -+ * if there is a BIOS "reserved" and BUSY range. If this -+ * fails then continue anyway. -+ */ -+ snprintf(info->mtd_name, MTD_DEV_NAME_LENGTH, -+ "mtd%d", info->mtd->index); -+ -+ info->rom_rsrc.name = info->mtd_name; -+ info->rom_rsrc.start = window->start + window->size - rom_size; -+ info->rom_rsrc.end = window->start + window->size - 1; -+ info->rom_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; -+ if (request_resource(&info->window_rsrc, &info->rom_rsrc)) { -+ printk(KERN_ERR MOD_NAME -+ ": cannot reserve MTD resource\n"); -+ info->rom_rsrc.parent = NULL; -+ } -+ } -+ - return 0; - --err_out_iounmap: -- iounmap((void *)(info->window_addr)); --err_out_free_mmio_region: -- release_mem_region(window->start, window->size); --err_out_none: -+ failed: -+ amd76xrom_cleanup(info); - return -ENODEV; - } - -@@ -186,21 +228,8 @@ - static void __devexit amd76xrom_remove_one (struct pci_dev *pdev) - { - struct amd76xrom_map_info *info = &amd76xrom_map; -- u8 byte; -- -- del_mtd_device(info->mtd); -- map_destroy(info->mtd); -- info->mtd = 0; -- info->map.map_priv_1 = 0; -- -- iounmap((void *)(info->window_addr)); -- info->window_addr = 0; -- -- /* Disable writes through the rom window */ -- pci_read_config_byte(pdev, 0x40, &byte); -- pci_write_config_byte(pdev, 0x40, byte & ~1); - -- release_mem_region(info->window_start, info->window_size); -+ amd76xrom_cleanup(info); - } - - static struct pci_device_id amd76xrom_pci_tbl[] __devinitdata = { -@@ -208,6 +237,7 @@ - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7440, - PCI_ANY_ID, PCI_ANY_ID, }, -+ { PCI_VENDOR_ID_AMD, 0x7468 }, /* amd8111 support */ - { 0, } - }; - -@@ -215,10 +245,10 @@ - - #if 0 - static struct pci_driver amd76xrom_driver = { -- name: "amd76xrom", -- id_table: amd76xrom_pci_tbl, -- probe: amd76xrom_init_one, -- remove: amd76xrom_remove_one, -+ .name = MOD_NAME, -+ .id_table = amd76xrom_pci_tbl, -+ .probe = amd76xrom_init_one, -+ .remove = amd76xrom_remove_one, - }; - #endif - -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/arctic-mtd.c linux/drivers/mtd/maps/arctic-mtd.c ---- linux-mips-2.4.27/drivers/mtd/maps/arctic-mtd.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/arctic-mtd.c 2004-11-19 10:25:11.893200704 +0100 -@@ -0,0 +1,135 @@ -+/* -+ * $Id$ -+ * -+ * drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for -+ * IBM 405LP Arctic boards. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the 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 -+ * -+ * Copyright (C) 2002, International Business Machines Corporation -+ * All Rights Reserved. -+ * -+ * Bishop Brock -+ * IBM Research, Austin Center for Low-Power Computing -+ * bcbrock@us.ibm.com -+ * March 2002 -+ * -+ * modified for Arctic by, -+ * David Gibson -+ * IBM OzLabs, Canberra, Australia -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* -+ * 0 : 0xFE00 0000 - 0xFEFF FFFF : Filesystem 1 (16MiB) -+ * 1 : 0xFF00 0000 - 0xFF4F FFFF : kernel (5.12MiB) -+ * 2 : 0xFF50 0000 - 0xFFF5 FFFF : Filesystem 2 (10.624MiB) (if non-XIP) -+ * 3 : 0xFFF6 0000 - 0xFFFF FFFF : PIBS Firmware (640KiB) -+ */ -+ -+#define FFS1_SIZE 0x01000000 /* 16MiB */ -+#define KERNEL_SIZE 0x00500000 /* 5.12MiB */ -+#define FFS2_SIZE 0x00a60000 /* 10.624MiB */ -+#define FIRMWARE_SIZE 0x000a0000 /* 640KiB */ -+ -+ -+#define NAME "Arctic Linux Flash" -+#define PADDR SUBZERO_BOOTFLASH_PADDR -+#define BUSWIDTH 2 -+#define SIZE SUBZERO_BOOTFLASH_SIZE -+#define PARTITIONS 4 -+ -+/* Flash memories on these boards are memory resources, accessed big-endian. */ -+ -+{ -+ /* do nothing for now */ -+} -+ -+static struct map_info arctic_mtd_map = { -+ .name = NAME, -+ .size = SIZE, -+ .buswidth = BUSWIDTH, -+ .phys = PADDR, -+}; -+ -+static struct mtd_info *arctic_mtd; -+ -+static struct mtd_partition arctic_partitions[PARTITIONS] = { -+ { .name = "Filesystem", -+ .size = FFS1_SIZE, -+ .offset = 0,}, -+ { .name = "Kernel", -+ .size = KERNEL_SIZE, -+ .offset = FFS1_SIZE,}, -+ { .name = "Filesystem", -+ .size = FFS2_SIZE, -+ .offset = FFS1_SIZE + KERNEL_SIZE,}, -+ { .name = "Firmware", -+ .size = FIRMWARE_SIZE, -+ .offset = SUBZERO_BOOTFLASH_SIZE - FIRMWARE_SIZE,}, -+}; -+ -+static int __init -+init_arctic_mtd(void) -+{ -+ printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); -+ -+ arctic_mtd_map.virt = (unsigned long) ioremap(PADDR, SIZE); -+ -+ if (!arctic_mtd_map.virt) { -+ printk("%s: failed to ioremap 0x%x\n", NAME, PADDR); -+ return -EIO; -+ } -+ simple_map_init(&arctic_mtd_map); -+ -+ printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8); -+ arctic_mtd = do_map_probe("cfi_probe", &arctic_mtd_map); -+ -+ if (!arctic_mtd) -+ return -ENXIO; -+ -+ arctic_mtd->owner = THIS_MODULE; -+ -+ return add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS); -+} -+ -+static void __exit -+cleanup_arctic_mtd(void) -+{ -+ if (arctic_mtd) { -+ del_mtd_partitions(arctic_mtd); -+ map_destroy(arctic_mtd); -+ iounmap((void *) arctic_mtd_map.virt); -+ } -+} -+ -+module_init(init_arctic_mtd); -+module_exit(cleanup_arctic_mtd); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("David Gibson "); -+MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Arctic boards"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/autcpu12-nvram.c linux/drivers/mtd/maps/autcpu12-nvram.c ---- linux-mips-2.4.27/drivers/mtd/maps/autcpu12-nvram.c 2002-06-27 00:35:50.000000000 +0200 -+++ linux/drivers/mtd/maps/autcpu12-nvram.c 2004-11-19 10:25:11.894200552 +0100 -@@ -2,7 +2,7 @@ - * NV-RAM memory access on autcpu12 - * (C) 2002 Thomas Gleixner (gleixner@autronix.de) - * -- * $Id$ -+ * $Id$ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -32,80 +33,27 @@ - #include - #include - --__u8 autcpu12_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 autcpu12_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 autcpu12_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void autcpu12_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void autcpu12_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void autcpu12_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void autcpu12_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void autcpu12_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- while(len) { -- __raw_writeb(*(unsigned char *) from, map->map_priv_1 + to); -- from++; -- to++; -- len--; -- } --} - - static struct mtd_info *sram_mtd; - - struct map_info autcpu12_sram_map = { -- name: "SRAM", -- size: 32768, -- buswidth: 8, -- read8: autcpu12_read8, -- read16: autcpu12_read16, -- read32: autcpu12_read32, -- copy_from: autcpu12_copy_from, -- write8: autcpu12_write8, -- write16: autcpu12_write16, -- write32: autcpu12_write32, -- copy_to: autcpu12_copy_to -+ .name = "SRAM", -+ .size = 32768, -+ .buswidth = 4, -+ .phys = 0x12000000, - }; - - static int __init init_autcpu12_sram (void) - { - int err, save0, save1; - -- autcpu12_sram_map.map_priv_1 = (unsigned long)ioremap(0x12000000, SZ_128K); -- if (!autcpu12_sram_map.map_priv_1) { -+ autcpu12_sram_map.virt = (unsigned long)ioremap(0x12000000, SZ_128K); -+ if (!autcpu12_sram_map.virt) { - printk("Failed to ioremap autcpu12 NV-RAM space\n"); - err = -EIO; - goto out; - } -+ simple_map_init(&autcpu_sram_map); - - /* - * Check for 32K/128K -@@ -115,20 +63,20 @@ - * Read and check result on ofs 0x0 - * Restore contents - */ -- save0 = autcpu12_read32(&autcpu12_sram_map,0); -- save1 = autcpu12_read32(&autcpu12_sram_map,0x10000); -- autcpu12_write32(&autcpu12_sram_map,~save0,0x10000); -+ save0 = map_read32(&autcpu12_sram_map,0); -+ save1 = map_read32(&autcpu12_sram_map,0x10000); -+ map_write32(&autcpu12_sram_map,~save0,0x10000); - /* if we find this pattern on 0x0, we have 32K size - * restore contents and exit - */ -- if ( autcpu12_read32(&autcpu12_sram_map,0) != save0) { -- autcpu12_write32(&autcpu12_sram_map,save0,0x0); -+ if ( map_read32(&autcpu12_sram_map,0) != save0) { -+ map_write32(&autcpu12_sram_map,save0,0x0); - goto map; - } - /* We have a 128K found, restore 0x10000 and set size - * to 128K - */ -- autcpu12_write32(&autcpu12_sram_map,save1,0x10000); -+ ma[_write32(&autcpu12_sram_map,save1,0x10000); - autcpu12_sram_map.size = SZ_128K; - - map: -@@ -139,7 +87,7 @@ - goto out_ioremap; - } - -- sram_mtd->module = THIS_MODULE; -+ sram_mtd->owner = THIS_MODULE; - sram_mtd->erasesize = 16; - - if (add_mtd_device(sram_mtd)) { -@@ -148,7 +96,7 @@ - goto out_probe; - } - -- printk("NV-RAM device size %ldK registered on AUTCPU12\n",autcpu12_sram_map.size/SZ_1K); -+ printk("NV-RAM device size %ldKiB registered on AUTCPU12\n",autcpu12_sram_map.size/SZ_1K); - - return 0; - -@@ -157,7 +105,7 @@ - sram_mtd = 0; - - out_ioremap: -- iounmap((void *)autcpu12_sram_map.map_priv_1); -+ iounmap((void *)autcpu12_sram_map.virt); - out: - return err; - } -@@ -167,7 +115,7 @@ - if (sram_mtd) { - del_mtd_device(sram_mtd); - map_destroy(sram_mtd); -- iounmap((void *)autcpu12_sram_map.map_priv_1); -+ iounmap((void *)autcpu12_sram_map.virt); - } - } - -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/beech-mtd.c linux/drivers/mtd/maps/beech-mtd.c ---- linux-mips-2.4.27/drivers/mtd/maps/beech-mtd.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/beech-mtd.c 2004-11-19 10:25:11.895200400 +0100 -@@ -0,0 +1,112 @@ -+/* -+ * $Id$ -+ * -+ * drivers/mtd/maps/beech-mtd.c MTD mappings and partition tables for -+ * IBM 405LP Beech boards. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the 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 -+ * -+ * Copyright (C) 2002, International Business Machines Corporation -+ * All Rights Reserved. -+ * -+ * Bishop Brock -+ * IBM Research, Austin Center for Low-Power Computing -+ * bcbrock@us.ibm.com -+ * March 2002 -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#define NAME "Beech Linux Flash" -+#define PADDR BEECH_BIGFLASH_PADDR -+#define SIZE BEECH_BIGFLASH_SIZE -+#define BUSWIDTH 1 -+ -+/* Flash memories on these boards are memory resources, accessed big-endian. */ -+ -+ -+static struct map_info beech_mtd_map = { -+ .name = NAME, -+ .size = SIZE, -+ .buswidth = BUSWIDTH, -+ .phys = PADDR -+}; -+ -+static struct mtd_info *beech_mtd; -+ -+static struct mtd_partition beech_partitions[2] = { -+ { -+ .name = "Linux Kernel", -+ .size = BEECH_KERNEL_SIZE, -+ .offset = BEECH_KERNEL_OFFSET -+ }, { -+ .name = "Free Area", -+ .size = BEECH_FREE_AREA_SIZE, -+ .offset = BEECH_FREE_AREA_OFFSET -+ } -+}; -+ -+static int __init -+init_beech_mtd(void) -+{ -+ printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); -+ -+ beech_mtd_map.virt = (unsigned long) ioremap(PADDR, SIZE); -+ -+ if (!beech_mtd_map.virt) { -+ printk("%s: failed to ioremap 0x%x\n", NAME, PADDR); -+ return -EIO; -+ } -+ -+ simple_map_init(&beech_mtd_map); -+ -+ printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8); -+ beech_mtd = do_map_probe("cfi_probe", &beech_mtd_map); -+ -+ if (!beech_mtd) -+ return -ENXIO; -+ -+ beech_mtd->owner = THIS_MODULE; -+ -+ return add_mtd_partitions(beech_mtd, beech_partitions, 2); -+} -+ -+static void __exit -+cleanup_beech_mtd(void) -+{ -+ if (beech_mtd) { -+ del_mtd_partitions(beech_mtd); -+ map_destroy(beech_mtd); -+ iounmap((void *) beech_mtd_map.virt); -+ } -+} -+ -+module_init(init_beech_mtd); -+module_exit(cleanup_beech_mtd); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Bishop Brock "); -+MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Beech boards"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/cdb89712.c linux/drivers/mtd/maps/cdb89712.c ---- linux-mips-2.4.27/drivers/mtd/maps/cdb89712.c 2001-11-05 21:15:52.000000000 +0100 -+++ linux/drivers/mtd/maps/cdb89712.c 2004-11-19 10:25:11.897200096 +0100 -@@ -1,13 +1,14 @@ - /* - * Flash on Cirrus CDB89712 - * -- * $Id$ -+ * $Id$ - */ - - #include - #include - #include - #include -+#include - #include - #include - #include -@@ -16,77 +17,21 @@ - - - --__u8 cdb89712_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 cdb89712_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 cdb89712_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void cdb89712_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void cdb89712_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void cdb89712_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void cdb89712_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- // printk ("cdb89712_copy_from: 0x%x@0x%x -> 0x%x\n", len, from, to); -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void cdb89712_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- while(len) { -- __raw_writeb(*(unsigned char *) from, map->map_priv_1 + to); -- from++; -- to++; -- len--; -- } --} -- - - static struct mtd_info *flash_mtd; - - struct map_info cdb89712_flash_map = { -- name: "flash", -- size: FLASH_SIZE, -- buswidth: FLASH_WIDTH, -- read8: cdb89712_read8, -- read16: cdb89712_read16, -- read32: cdb89712_read32, -- copy_from: cdb89712_copy_from, -- write8: cdb89712_write8, -- write16: cdb89712_write16, -- write32: cdb89712_write32, -- copy_to: cdb89712_copy_to -+ .name = "flash", -+ .size = FLASH_SIZE, -+ .buswidth = FLASH_WIDTH, -+ .phys = FLASH_START, - }; - - struct resource cdb89712_flash_resource = { -- name: "Flash", -- start: FLASH_START, -- end: FLASH_START + FLASH_SIZE - 1, -- flags: IORESOURCE_IO | IORESOURCE_BUSY, -+ .name = "Flash", -+ .start = FLASH_START, -+ .end = FLASH_START + FLASH_SIZE - 1, -+ .flags = IORESOURCE_IO | IORESOURCE_BUSY, - }; - - static int __init init_cdb89712_flash (void) -@@ -99,13 +44,13 @@ - goto out; - } - -- cdb89712_flash_map.map_priv_1 = (unsigned long)ioremap(FLASH_START, FLASH_SIZE); -- if (!cdb89712_flash_map.map_priv_1) { -+ cdb89712_flash_map.virt = (unsigned long)ioremap(FLASH_START, FLASH_SIZE); -+ if (!cdb89712_flash_map.virt) { - printk(KERN_NOTICE "Failed to ioremap Cdb89712 FLASH space\n"); - err = -EIO; - goto out_resource; - } -- -+ simple_map_init(&cdb89712_flash_map); - flash_mtd = do_map_probe("cfi_probe", &cdb89712_flash_map); - if (!flash_mtd) { - flash_mtd = do_map_probe("map_rom", &cdb89712_flash_map); -@@ -118,7 +63,7 @@ - goto out_ioremap; - } - -- flash_mtd->module = THIS_MODULE; -+ flash_mtd->owner = THIS_MODULE; - - if (add_mtd_device(flash_mtd)) { - printk("FLASH device addition failed\n"); -@@ -132,7 +77,7 @@ - map_destroy(flash_mtd); - flash_mtd = 0; - out_ioremap: -- iounmap((void *)cdb89712_flash_map.map_priv_1); -+ iounmap((void *)cdb89712_flash_map.virt); - out_resource: - release_resource (&cdb89712_flash_resource); - out: -@@ -146,24 +91,17 @@ - static struct mtd_info *sram_mtd; - - struct map_info cdb89712_sram_map = { -- name: "SRAM", -- size: SRAM_SIZE, -- buswidth: SRAM_WIDTH, -- read8: cdb89712_read8, -- read16: cdb89712_read16, -- read32: cdb89712_read32, -- copy_from: cdb89712_copy_from, -- write8: cdb89712_write8, -- write16: cdb89712_write16, -- write32: cdb89712_write32, -- copy_to: cdb89712_copy_to -+ .name = "SRAM", -+ .size = SRAM_SIZE, -+ .buswidth = SRAM_WIDTH, -+ .phys = SRAM_START, - }; - - struct resource cdb89712_sram_resource = { -- name: "SRAM", -- start: SRAM_START, -- end: SRAM_START + SRAM_SIZE - 1, -- flags: IORESOURCE_IO | IORESOURCE_BUSY, -+ .name = "SRAM", -+ .start = SRAM_START, -+ .end = SRAM_START + SRAM_SIZE - 1, -+ .flags = IORESOURCE_IO | IORESOURCE_BUSY, - }; - - static int __init init_cdb89712_sram (void) -@@ -176,13 +114,13 @@ - goto out; - } - -- cdb89712_sram_map.map_priv_1 = (unsigned long)ioremap(SRAM_START, SRAM_SIZE); -- if (!cdb89712_sram_map.map_priv_1) { -+ cdb89712_sram_map.virt = (unsigned long)ioremap(SRAM_START, SRAM_SIZE); -+ if (!cdb89712_sram_map.virt) { - printk(KERN_NOTICE "Failed to ioremap Cdb89712 SRAM space\n"); - err = -EIO; - goto out_resource; - } -- -+ simple_map_init(&cdb89712_sram_map); - sram_mtd = do_map_probe("map_ram", &cdb89712_sram_map); - if (!sram_mtd) { - printk("SRAM probe failed\n"); -@@ -190,7 +128,7 @@ - goto out_ioremap; - } - -- sram_mtd->module = THIS_MODULE; -+ sram_mtd->owner = THIS_MODULE; - sram_mtd->erasesize = 16; - - if (add_mtd_device(sram_mtd)) { -@@ -205,7 +143,7 @@ - map_destroy(sram_mtd); - sram_mtd = 0; - out_ioremap: -- iounmap((void *)cdb89712_sram_map.map_priv_1); -+ iounmap((void *)cdb89712_sram_map.virt); - out_resource: - release_resource (&cdb89712_sram_resource); - out: -@@ -221,20 +159,17 @@ - static struct mtd_info *bootrom_mtd; - - struct map_info cdb89712_bootrom_map = { -- name: "BootROM", -- size: BOOTROM_SIZE, -- buswidth: BOOTROM_WIDTH, -- read8: cdb89712_read8, -- read16: cdb89712_read16, -- read32: cdb89712_read32, -- copy_from: cdb89712_copy_from, -+ .name = "BootROM", -+ .size = BOOTROM_SIZE, -+ .buswidth = BOOTROM_WIDTH, -+ .phys = BOOTROM_START, - }; - - struct resource cdb89712_bootrom_resource = { -- name: "BootROM", -- start: BOOTROM_START, -- end: BOOTROM_START + BOOTROM_SIZE - 1, -- flags: IORESOURCE_IO | IORESOURCE_BUSY, -+ .name = "BootROM", -+ .start = BOOTROM_START, -+ .end = BOOTROM_START + BOOTROM_SIZE - 1, -+ .flags = IORESOURCE_IO | IORESOURCE_BUSY, - }; - - static int __init init_cdb89712_bootrom (void) -@@ -247,13 +182,13 @@ - goto out; - } - -- cdb89712_bootrom_map.map_priv_1 = (unsigned long)ioremap(BOOTROM_START, BOOTROM_SIZE); -- if (!cdb89712_bootrom_map.map_priv_1) { -+ cdb89712_bootrom_map.virt = (unsigned long)ioremap(BOOTROM_START, BOOTROM_SIZE); -+ if (!cdb89712_bootrom_map.virt) { - printk(KERN_NOTICE "Failed to ioremap Cdb89712 BootROM space\n"); - err = -EIO; - goto out_resource; - } -- -+ simple_map_init(&cdb89712_bootrom_map); - bootrom_mtd = do_map_probe("map_rom", &cdb89712_bootrom_map); - if (!bootrom_mtd) { - printk("BootROM probe failed\n"); -@@ -261,7 +196,7 @@ - goto out_ioremap; - } - -- bootrom_mtd->module = THIS_MODULE; -+ bootrom_mtd->owner = THIS_MODULE; - bootrom_mtd->erasesize = 0x10000; - - if (add_mtd_device(bootrom_mtd)) { -@@ -276,7 +211,7 @@ - map_destroy(bootrom_mtd); - bootrom_mtd = 0; - out_ioremap: -- iounmap((void *)cdb89712_bootrom_map.map_priv_1); -+ iounmap((void *)cdb89712_bootrom_map.virt); - out_resource: - release_resource (&cdb89712_bootrom_resource); - out: -@@ -306,21 +241,21 @@ - if (sram_mtd) { - del_mtd_device(sram_mtd); - map_destroy(sram_mtd); -- iounmap((void *)cdb89712_sram_map.map_priv_1); -+ iounmap((void *)cdb89712_sram_map.virt); - release_resource (&cdb89712_sram_resource); - } - - if (flash_mtd) { - del_mtd_device(flash_mtd); - map_destroy(flash_mtd); -- iounmap((void *)cdb89712_flash_map.map_priv_1); -+ iounmap((void *)cdb89712_flash_map.virt); - release_resource (&cdb89712_flash_resource); - } - - if (bootrom_mtd) { - del_mtd_device(bootrom_mtd); - map_destroy(bootrom_mtd); -- iounmap((void *)cdb89712_bootrom_map.map_priv_1); -+ iounmap((void *)cdb89712_bootrom_map.virt); - release_resource (&cdb89712_bootrom_resource); - } - } -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/ceiva.c linux/drivers/mtd/maps/ceiva.c ---- linux-mips-2.4.27/drivers/mtd/maps/ceiva.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/maps/ceiva.c 2004-11-19 10:25:11.898199944 +0100 -@@ -11,7 +11,7 @@ - * - * (C) 2000 Nicolas Pitre - * -- * $Id$ -+ * $Id$ - */ - - #include -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -31,62 +32,10 @@ - #include - - /* -- * This isnt complete yet, so... -+ * This isn't complete yet, so... - */ - #define CONFIG_MTD_CEIVA_STATICMAP - --static __u8 clps_read8(struct map_info *map, unsigned long ofs) --{ -- return readb(map->map_priv_1 + ofs); --} -- --static __u16 clps_read16(struct map_info *map, unsigned long ofs) --{ -- return readw(map->map_priv_1 + ofs); --} -- --static __u32 clps_read32(struct map_info *map, unsigned long ofs) --{ -- return readl(map->map_priv_1 + ofs); --} -- --static void clps_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy(to, (void *)(map->map_priv_1 + from), len); --} -- --static void clps_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, map->map_priv_1 + adr); --} -- --static void clps_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, map->map_priv_1 + adr); --} -- --static void clps_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- writel(d, map->map_priv_1 + adr); --} -- --static void clps_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy((void *)(map->map_priv_1 + to), from, len); --} -- --static struct map_info clps_map __initdata = { -- name: "clps flash", -- read8: clps_read8, -- read16: clps_read16, -- read32: clps_read32, -- copy_from: clps_copy_from, -- write8: clps_write8, -- write16: clps_write16, -- write32: clps_write32, -- copy_to: clps_copy_to, --}; -- - #ifdef CONFIG_MTD_CEIVA_STATICMAP - /* - * See include/linux/mtd/partitions.h for definition of the mtd_partition -@@ -176,7 +125,7 @@ - maps = kmalloc(sizeof(struct map_info) * nr, GFP_KERNEL); - if (!maps) - return -ENOMEM; -- -+ memset(maps, 0, sizeof(struct map_info) * nr); - /* - * Claim and then map the memory regions. - */ -@@ -191,7 +140,9 @@ - } - - clps[i].map = maps + i; -- memcpy(clps[i].map, &clps_map, sizeof(struct map_info)); -+ -+ clps[i].map->name = "clps flash"; -+ clps[i].map->phys = clps[i].base; - - clps[i].vbase = ioremap(clps[i].base, clps[i].size); - if (!clps[i].vbase) { -@@ -199,16 +150,18 @@ - break; - } - -- clps[i].map->map_priv_1 = (unsigned long)clps[i].vbase; -+ clps[i].map->virt = (unsigned long)clps[i].vbase; - clps[i].map->buswidth = clps[i].width; - clps[i].map->size = clps[i].size; - -+ simple_map_init(&clps[i].map); -+ - clps[i].mtd = do_map_probe("jedec_probe", clps[i].map); - if (clps[i].mtd == NULL) { - ret = -ENXIO; - break; - } -- clps[i].mtd->module = THIS_MODULE; -+ clps[i].mtd->owner = THIS_MODULE; - subdev[i] = clps[i].mtd; - - printk(KERN_INFO "clps flash: JEDEC device at 0x%08lx, %dMiB, " -@@ -318,10 +271,8 @@ - return nr; - } - --extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts); --extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, char *); -- - static struct mtd_partition *parsed_parts; -+static const char *probes[] = { "cmdlinepart", "RedBoot", NULL }; - - static void __init clps_locate_partitions(struct mtd_info *mtd) - { -@@ -331,20 +282,11 @@ - /* - * Partition selection stuff. - */ --#ifdef CONFIG_MTD_CMDLINE_PARTS -- nr_parts = parse_cmdline_partitions(mtd, &parsed_parts, "clps"); -+ nr_parts = parse_mtd_partitions(mtd, probes, &parsed_parts, 0); - if (nr_parts > 0) { - part_type = "command line"; - break; - } --#endif --#ifdef CONFIG_MTD_REDBOOT_PARTS -- nr_parts = parse_redboot_partitions(mtd, &parsed_parts); -- if (nr_parts > 0) { -- part_type = "RedBoot"; -- break; -- } --#endif - #ifdef CONFIG_MTD_CEIVA_STATICMAP - nr_parts = clps_static_partitions(&parsed_parts); - if (nr_parts > 0) { -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/cfi_flagadm.c linux/drivers/mtd/maps/cfi_flagadm.c ---- linux-mips-2.4.27/drivers/mtd/maps/cfi_flagadm.c 2001-11-05 21:15:52.000000000 +0100 -+++ linux/drivers/mtd/maps/cfi_flagadm.c 2004-11-19 10:25:11.900199640 +0100 -@@ -1,7 +1,7 @@ - /* - * Copyright © 2001 Flaga hf. Medical Devices, Kári Davíðsson - * -- * $Id$ -+ * $Id$ - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -55,83 +56,33 @@ - #define FLASH_PARTITION3_ADDR 0x00240000 - #define FLASH_PARTITION3_SIZE 0x001C0000 - --__u8 flagadm_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 flagadm_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 flagadm_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void flagadm_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void flagadm_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void flagadm_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void flagadm_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void flagadm_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - struct map_info flagadm_map = { -- name: "FlagaDM flash device", -- size: FLASH_SIZE, -- buswidth: 2, -- read8: flagadm_read8, -- read16: flagadm_read16, -- read32: flagadm_read32, -- copy_from: flagadm_copy_from, -- write8: flagadm_write8, -- write16: flagadm_write16, -- write32: flagadm_write32, -- copy_to: flagadm_copy_to -+ .name = "FlagaDM flash device", -+ .size = FLASH_SIZE, -+ .buswidth = 2, - }; - - struct mtd_partition flagadm_parts[] = { - { -- name : "Bootloader", -- offset : FLASH_PARTITION0_ADDR, -- size : FLASH_PARTITION0_SIZE -+ .name = "Bootloader", -+ .offset = FLASH_PARTITION0_ADDR, -+ .size = FLASH_PARTITION0_SIZE - }, - { -- name : "Kernel image", -- offset : FLASH_PARTITION1_ADDR, -- size : FLASH_PARTITION1_SIZE -+ .name = "Kernel image", -+ .offset = FLASH_PARTITION1_ADDR, -+ .size = FLASH_PARTITION1_SIZE - }, - { -- name : "Initial ramdisk image", -- offset : FLASH_PARTITION2_ADDR, -- size : FLASH_PARTITION2_SIZE -+ .name = "Initial ramdisk image", -+ .offset = FLASH_PARTITION2_ADDR, -+ .size = FLASH_PARTITION2_SIZE - }, - { -- name : "Persistant storage", -- offset : FLASH_PARTITION3_ADDR, -- size : FLASH_PARTITION3_SIZE -+ .name = "Persistant storage", -+ .offset = FLASH_PARTITION3_ADDR, -+ .size = FLASH_PARTITION3_SIZE - } - }; - -@@ -144,22 +95,26 @@ - printk(KERN_NOTICE "FlagaDM flash device: %x at %x\n", - FLASH_SIZE, FLASH_PHYS_ADDR); - -- flagadm_map.map_priv_1 = (unsigned long)ioremap(FLASH_PHYS_ADDR, -+ flagadm_map.phys = FLASH_PHYS_ADDR; -+ flagadm_map.virt = (unsigned long)ioremap(FLASH_PHYS_ADDR, - FLASH_SIZE); - -- if (!flagadm_map.map_priv_1) { -+ if (!flagadm_map.virt) { - printk("Failed to ioremap\n"); - return -EIO; - } -+ -+ simple_map_init(&flagadm_map); -+ - mymtd = do_map_probe("cfi_probe", &flagadm_map); - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - add_mtd_partitions(mymtd, flagadm_parts, PARTITION_COUNT); - printk(KERN_NOTICE "FlagaDM flash device initialized\n"); - return 0; - } - -- iounmap((void *)flagadm_map.map_priv_1); -+ iounmap((void *)flagadm_map.virt); - return -ENXIO; - } - -@@ -169,9 +124,9 @@ - del_mtd_partitions(mymtd); - map_destroy(mymtd); - } -- if (flagadm_map.map_priv_1) { -- iounmap((void *)flagadm_map.map_priv_1); -- flagadm_map.map_priv_1 = 0; -+ if (flagadm_map.virt) { -+ iounmap((void *)flagadm_map.virt); -+ flagadm_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/cstm_mips_ixx.c linux/drivers/mtd/maps/cstm_mips_ixx.c ---- linux-mips-2.4.27/drivers/mtd/maps/cstm_mips_ixx.c 2001-11-05 21:15:52.000000000 +0100 -+++ linux/drivers/mtd/maps/cstm_mips_ixx.c 2004-11-19 10:25:11.901199488 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions. - * Config with both CFI and JEDEC device support. -@@ -33,55 +33,13 @@ - #include - #include - #include -+#include - #include - #include - #include - #include - #include -- --#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) - #include --#endif -- --__u8 cstm_mips_ixx_read8(struct map_info *map, unsigned long ofs) --{ -- return *(__u8 *)(map->map_priv_1 + ofs); --} -- --__u16 cstm_mips_ixx_read16(struct map_info *map, unsigned long ofs) --{ -- return *(__u16 *)(map->map_priv_1 + ofs); --} -- --__u32 cstm_mips_ixx_read32(struct map_info *map, unsigned long ofs) --{ -- return *(__u32 *)(map->map_priv_1 + ofs); --} -- --void cstm_mips_ixx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void cstm_mips_ixx_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- *(__u8 *)(map->map_priv_1 + adr) = d; --} -- --void cstm_mips_ixx_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- *(__u16 *)(map->map_priv_1 + adr) = d; --} -- --void cstm_mips_ixx_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- *(__u32 *)(map->map_priv_1 + adr) = d; --} -- --void cstm_mips_ixx_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) - #define CC_GCR 0xB4013818 -@@ -97,10 +55,17 @@ - #define CC_GPAICR 0xB4013804 - #endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ - -+#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) - void cstm_mips_ixx_set_vpp(struct map_info *map,int vpp) - { -+ static spinlock_t vpp_lock = SPIN_LOCK_UNLOCKED; -+ static int vpp_count = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&vpp_lock, flags); -+ - if (vpp) { --#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) -+ if (!vpp_count++) { - __u16 data; - __u8 data1; - static u8 first = 1; -@@ -116,10 +81,9 @@ - enabling vpp after powerup */ - udelay(40); - } --#endif /* CONFIG_MIPS_ITE8172 */ - } -- else { --#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) -+ } else { -+ if (!--vpp_count) { - __u16 data; - - // Set GPIO port B pin3 to high -@@ -127,26 +91,11 @@ - data = (data & 0xff3f) | 0x0040; - *(__u16 *)CC_GPBCR = data; - *(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) & 0xf7; --#endif /* CONFIG_MIPS_ITE8172 */ - } -+ } -+ spin_unlock_irqrestore(&vpp_lock, flags); - } -- --const struct map_info basic_cstm_mips_ixx_map = { -- NULL, -- 0, -- 0, -- cstm_mips_ixx_read8, -- cstm_mips_ixx_read16, -- cstm_mips_ixx_read32, -- cstm_mips_ixx_copy_from, -- cstm_mips_ixx_write8, -- cstm_mips_ixx_write16, -- cstm_mips_ixx_write32, -- cstm_mips_ixx_copy_to, -- cstm_mips_ixx_set_vpp, -- 0, -- 0 --}; -+#endif - - /* board and partition description */ - -@@ -175,9 +124,9 @@ - static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = { - { // 28F128J3A in 2x16 configuration - { -- name: "main partition ", -- size: 0x02000000, // 128 x 2 x 128k byte sectors -- offset: 0, -+ .name = "main partition ", -+ .size = 0x02000000, // 128 x 2 x 128k byte sectors -+ .offset = 0, - }, - }, - }; -@@ -197,9 +146,9 @@ - static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = { - { - { -- name: "main partition", -- size: CONFIG_MTD_CSTM_MIPS_IXX_LEN, -- offset: 0, -+ .name = "main partition", -+ .size = CONFIG_MTD_CSTM_MIPS_IXX_LEN, -+ .offset = 0, - }, - }, - }; -@@ -216,17 +165,24 @@ - - /* Initialize mapping */ - for (i=0;imodule = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - cstm_mips_ixx_map[i].map_priv_2 = (unsigned long)mymtd; - add_mtd_partitions(mymtd, parts, cstm_mips_ixx_board_desc[i].num_partitions); -@@ -266,9 +222,9 @@ - del_mtd_partitions(mymtd); - map_destroy(mymtd); - } -- if (cstm_mips_ixx_map[i].map_priv_1) { -- iounmap((void *)cstm_mips_ixx_map[i].map_priv_1); -- cstm_mips_ixx_map[i].map_priv_1 = 0; -+ if (cstm_mips_ixx_map[i].virt) { -+ iounmap((void *)cstm_mips_ixx_map[i].virt); -+ cstm_mips_ixx_map[i].virt = 0; - } - } - } -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/db1x00-flash.c linux/drivers/mtd/maps/db1x00-flash.c ---- linux-mips-2.4.27/drivers/mtd/maps/db1x00-flash.c 2003-02-16 07:25:24.000000000 +0100 -+++ linux/drivers/mtd/maps/db1x00-flash.c 2004-11-19 10:25:11.903199184 +0100 -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -29,76 +30,6 @@ - static unsigned long flash_size; - - static BCSR * const bcsr = (BCSR *)0xAE000000; -- --__u8 physmap_read8(struct map_info *map, unsigned long ofs) --{ -- __u8 ret; -- ret = __raw_readb(map->map_priv_1 + ofs); -- DBG("read8 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --__u16 physmap_read16(struct map_info *map, unsigned long ofs) --{ -- __u16 ret; -- ret = __raw_readw(map->map_priv_1 + ofs); -- DBG("read16 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --__u32 physmap_read32(struct map_info *map, unsigned long ofs) --{ -- __u32 ret; -- ret = __raw_readl(map->map_priv_1 + ofs); -- DBG("read32 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- DBG("physmap_copy from %x to %x\n", (unsigned)from, (unsigned)to); -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void physmap_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- DBG("write8 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- DBG("write16 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- DBG("write32 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- DBG("physmap_copy_to %x from %x\n", (unsigned)to, (unsigned)from); -- memcpy_toio(map->map_priv_1 + to, from, len); --} -- --static struct map_info db1x00_map = { -- name: "Db1x00 flash", -- read8: physmap_read8, -- read16: physmap_read16, -- read32: physmap_read32, -- copy_from: physmap_copy_from, -- write8: physmap_write8, -- write16: physmap_write16, -- write32: physmap_write32, -- copy_to: physmap_copy_to, --}; -- - static unsigned char flash_buswidth = 4; - - /* -@@ -115,58 +46,62 @@ - */ - static struct mtd_partition db1x00_partitions[] = { - { -- name: "User FS", -- size: 0x1c00000, -- offset: 0x0000000 -+ .name = "User FS", -+ .size = 0x1c00000, -+ .offset = 0x0000000 - },{ -- name: "yamon", -- size: 0x0100000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE -+ .name = "yamon", -+ .size = 0x0100000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE - },{ -- name: "raw kernel", -- size: (0x300000-0x40000), /* last 256KB is yamon env */ -- offset: MTDPART_OFS_APPEND, -+ .name = "raw kernel", -+ .size = (0x300000-0x40000), /* last 256KB is env */ -+ .offset = MTDPART_OFS_APPEND, - } - }; - #elif defined(DB1X00_BOOT_ONLY) - static struct mtd_partition db1x00_partitions[] = { - { -- name: "User FS", -- size: 0x00c00000, -- offset: 0x0000000 -+ .name = "User FS", -+ .size = 0x00c00000, -+ .offset = 0x0000000 - },{ -- name: "yamon", -- size: 0x0100000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE -+ .name = "yamon", -+ .size = 0x0100000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE - },{ -- name: "raw kernel", -- size: (0x300000-0x40000), /* last 256KB is yamon env */ -- offset: MTDPART_OFS_APPEND, -+ .name = "raw kernel", -+ .size = (0x300000-0x40000), /* last 256KB is env */ -+ .offset = MTDPART_OFS_APPEND, - } - }; - #elif defined(DB1X00_USER_ONLY) - static struct mtd_partition db1x00_partitions[] = { - { -- name: "User FS", -- size: 0x0e00000, -- offset: 0x0000000 -+ .name = "User FS", -+ .size = 0x0e00000, -+ .offset = 0x0000000 - },{ -- name: "raw kernel", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .name = "raw kernel", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #else - #error MTD_DB1X00 define combo error /* should never happen */ - #endif -+#define NB_OF(x) (sizeof(x)/sizeof(x[0])) - -+#define NAME "Db1x00 Linux Flash" - --#define NB_OF(x) (sizeof(x)/sizeof(x[0])) -+static struct map_info db1xxx_mtd_map = { -+ .name = NAME, -+}; - - static struct mtd_partition *parsed_parts; --static struct mtd_info *mymtd; -+static struct mtd_info *db1xxx_mtd; - - /* - * Probe the flash density and setup window address and size -@@ -174,7 +109,7 @@ - * want the MTD driver to be probing the boot or user flash, - * so having the option to enable only one bank is important. - */ --int setup_flash_params() -+int setup_flash_params(void) - { - switch ((bcsr->status >> 14) & 0x3) { - case 0: /* 64Mbit devices */ -@@ -228,6 +163,10 @@ - default: - return 1; - } -+ db1xxx_mtd_map.size = window_size; -+ db1xxx_mtd_map.buswidth = flash_buswidth; -+ db1xxx_mtd_map.phys = window_addr; -+ db1xxx_mtd_map.buswidth = flash_buswidth; - return 0; - } - -@@ -235,10 +174,6 @@ - { - struct mtd_partition *parts; - int nb_parts = 0; -- char *part_type; -- -- /* Default flash buswidth */ -- db1x00_map.buswidth = flash_buswidth; - - if (setup_flash_params()) - return -ENXIO; -@@ -246,32 +181,29 @@ - /* - * Static partition definition selection - */ -- part_type = "static"; - parts = db1x00_partitions; - nb_parts = NB_OF(db1x00_partitions); -- db1x00_map.size = window_size; - - /* - * Now let's probe for the actual flash. Do it here since - * specific machine settings might have been set above. - */ - printk(KERN_NOTICE "Db1xxx flash: probing %d-bit flash bus\n", -- db1x00_map.buswidth*8); -- db1x00_map.map_priv_1 = -- (unsigned long)ioremap(window_addr, window_size); -- mymtd = do_map_probe("cfi_probe", &db1x00_map); -- if (!mymtd) return -ENXIO; -- mymtd->module = THIS_MODULE; -+ db1xxx_mtd_map.buswidth*8); -+ db1xxx_mtd_map.virt = (unsigned long)ioremap(window_addr, window_size); -+ db1xxx_mtd = do_map_probe("cfi_probe", &db1xxx_mtd_map); -+ if (!db1xxx_mtd) return -ENXIO; -+ db1xxx_mtd->owner = THIS_MODULE; - -- add_mtd_partitions(mymtd, parts, nb_parts); -+ add_mtd_partitions(db1xxx_mtd, parts, nb_parts); - return 0; - } - - static void __exit db1x00_mtd_cleanup(void) - { -- if (mymtd) { -- del_mtd_partitions(mymtd); -- map_destroy(mymtd); -+ if (db1xxx_mtd) { -+ del_mtd_partitions(db1xxx_mtd); -+ map_destroy(db1xxx_mtd); - if (parsed_parts) - kfree(parsed_parts); - } -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/dbox2-flash.c linux/drivers/mtd/maps/dbox2-flash.c ---- linux-mips-2.4.27/drivers/mtd/maps/dbox2-flash.c 2001-11-05 21:15:52.000000000 +0100 -+++ linux/drivers/mtd/maps/dbox2-flash.c 2004-11-19 10:25:11.904199032 +0100 -@@ -1,12 +1,13 @@ - /* -- * $Id$ -+ * $Id$ - * -- * Nokia / Sagem D-Box 2 flash driver -+ * D-Box 2 flash driver - */ - - #include - #include - #include -+#include - #include - #include - #include -@@ -16,22 +17,44 @@ - /* partition_info gives details on the logical partitions that the split the - * single flash device into. If the size if zero we use up to the end of the - * device. */ --static struct mtd_partition partition_info[]= {{name: "BR bootloader", // raw -- size: 128 * 1024, -- offset: 0, -- mask_flags: MTD_WRITEABLE}, -- {name: "PPC bootloader", // flfs -- size: 128 * 1024, -- offset: MTDPART_OFS_APPEND, -- mask_flags: 0}, -- {name: "Kernel", // idxfs -- size: 768 * 1024, -- offset: MTDPART_OFS_APPEND, -- mask_flags: 0}, -- {name: "System", // jffs -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -- mask_flags: 0}}; -+static struct mtd_partition partition_info[]= { -+ { -+ .name = "BR bootloader", -+ .size = 128 * 1024, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE -+ }, -+ { -+ .name = "flfs (ppcboot)", -+ .size = 128 * 1024, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = 0 -+ }, -+ { -+ .name = "root (cramfs)", -+ .size = 7040 * 1024, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = 0 -+ }, -+ { -+ .name = "var (jffs2)", -+ .size = 896 * 1024, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = 0 -+ }, -+ { -+ .name = "flash without bootloader", -+ .size = MTDPART_SIZ_FULL, -+ .offset = 128 * 1024, -+ .mask_flags = 0 -+ }, -+ { -+ .name = "complete flash", -+ .size = MTDPART_SIZ_FULL, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE -+ } -+}; - - #define NUM_PARTITIONS (sizeof(partition_info) / sizeof(partition_info[0])) - -@@ -40,72 +63,24 @@ - - static struct mtd_info *mymtd; - --__u8 dbox2_flash_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 dbox2_flash_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 dbox2_flash_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void dbox2_flash_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void dbox2_flash_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void dbox2_flash_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void dbox2_flash_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void dbox2_flash_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - struct map_info dbox2_flash_map = { -- name: "D-Box 2 flash memory", -- size: WINDOW_SIZE, -- buswidth: 4, -- read8: dbox2_flash_read8, -- read16: dbox2_flash_read16, -- read32: dbox2_flash_read32, -- copy_from: dbox2_flash_copy_from, -- write8: dbox2_flash_write8, -- write16: dbox2_flash_write16, -- write32: dbox2_flash_write32, -- copy_to: dbox2_flash_copy_to -+ .name = "D-Box 2 flash memory", -+ .size = WINDOW_SIZE, -+ .buswidth = 4, -+ .phys = WINDOW_ADDR, - }; - - int __init init_dbox2_flash(void) - { - printk(KERN_NOTICE "D-Box 2 flash driver (size->0x%X mem->0x%X)\n", WINDOW_SIZE, WINDOW_ADDR); -- dbox2_flash_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); -+ dbox2_flash_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); - -- if (!dbox2_flash_map.map_priv_1) { -+ if (!dbox2_flash_map.virt) { - printk("Failed to ioremap\n"); - return -EIO; - } -+ simple_map_init(&dbox2_flash_map); - - // Probe for dual Intel 28F320 or dual AMD - mymtd = do_map_probe("cfi_probe", &dbox2_flash_map); -@@ -117,7 +92,7 @@ - } - - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - /* Create MTD devices for each partition. */ - add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS); -@@ -125,7 +100,7 @@ - return 0; - } - -- iounmap((void *)dbox2_flash_map.map_priv_1); -+ iounmap((void *)dbox2_flash_map.virt); - return -ENXIO; - } - -@@ -135,9 +110,9 @@ - del_mtd_partitions(mymtd); - map_destroy(mymtd); - } -- if (dbox2_flash_map.map_priv_1) { -- iounmap((void *)dbox2_flash_map.map_priv_1); -- dbox2_flash_map.map_priv_1 = 0; -+ if (dbox2_flash_map.virt) { -+ iounmap((void *)dbox2_flash_map.virt); -+ dbox2_flash_map.virt = 0; - } - } - -@@ -146,5 +121,5 @@ - - - MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Kári Davíðsson "); --MODULE_DESCRIPTION("MTD map driver for Nokia/Sagem D-Box 2 board"); -+MODULE_AUTHOR("Kári Davíðsson , Bastian Blank , Alexander Wild "); -+MODULE_DESCRIPTION("MTD map driver for D-Box 2 board"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/dc21285.c linux/drivers/mtd/maps/dc21285.c ---- linux-mips-2.4.27/drivers/mtd/maps/dc21285.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/maps/dc21285.c 2004-11-19 10:25:11.906198728 +0100 -@@ -5,12 +5,13 @@ - * - * This code is GPL - * -- * $Id$ -+ * $Id$ - */ - #include - #include - #include - #include -+#include - - #include - #include -@@ -92,26 +93,42 @@ - } - - struct map_info dc21285_map = { -- name: "DC21285 flash", -- size: 16*1024*1024, -- read8: dc21285_read8, -- read16: dc21285_read16, -- read32: dc21285_read32, -- copy_from: dc21285_copy_from, -- write8: dc21285_write8, -- write16: dc21285_write16, -- write32: dc21285_write32, -- copy_to: dc21285_copy_to -+ .name = "DC21285 flash", -+ .phys = NO_XIP, -+ .size = 16*1024*1024, -+ .read8 = dc21285_read8, -+ .read16 = dc21285_read16, -+ .read32 = dc21285_read32, -+ .copy_from = dc21285_copy_from, -+ .write8 = dc21285_write8, -+ .write16 = dc21285_write16, -+ .write32 = dc21285_write32, -+ .copy_to = dc21285_copy_to - }; - - - /* Partition stuff */ - static struct mtd_partition *dc21285_parts; -- --extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **); -+#ifdef CONFIG_MTD_PARTITIONS -+static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; -+#endif - - int __init init_dc21285(void) - { -+ -+ /* -+ * Flash timing is determined with bits 19-16 of the -+ * CSR_SA110_CNTL. The value is the number of wait cycles, or -+ * 0 for 16 cycles (the default). Cycles are 20 ns. -+ * Here we use 7 for 140 ns flash chips. -+ */ -+ /* access time */ -+ *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x000f0000) | (7 << 16)); -+ /* burst time */ -+ *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20)); -+ /* tristate time */ -+ *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24)); -+ - /* Determine buswidth */ - switch (*CSR_SA110_CNTL & (3<<14)) { - case SA110_CNTL_ROMWIDTH_8: -@@ -141,33 +158,18 @@ - if (mymtd) { - int nrparts = 0; - -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - /* partition fixup */ - --#ifdef CONFIG_MTD_REDBOOT_PARTS -- nrparts = parse_redboot_partitions(mymtd, &dc21285_parts); --#endif -+#ifdef CONFIG_MTD_PARTITIONS -+ nrparts = parse_mtd_partitions(mymtd, probes, &dc21285_parts, (void *)0); - if (nrparts > 0) { - add_mtd_partitions(mymtd, dc21285_parts, nrparts); -- } else if (nrparts == 0) { -- printk(KERN_NOTICE "RedBoot partition table failed\n"); -- add_mtd_device(mymtd); -+ return 0; - } -- -- /* -- * Flash timing is determined with bits 19-16 of the -- * CSR_SA110_CNTL. The value is the number of wait cycles, or -- * 0 for 16 cycles (the default). Cycles are 20 ns. -- * Here we use 7 for 140 ns flash chips. -- */ -- /* access time */ -- *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x000f0000) | (7 << 16)); -- /* burst time */ -- *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20)); -- /* tristate time */ -- *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24)); -- -+#endif -+ add_mtd_device(mymtd); - return 0; - } - -@@ -177,17 +179,16 @@ - - static void __exit cleanup_dc21285(void) - { -- if (mymtd) { -+#ifdef CONFIG_MTD_PARTITIONS -+ if (dc21285_parts) { -+ del_mtd_partitions(mymtd); -+ kfree(dc21285_parts); -+ } else -+#endif - del_mtd_device(mymtd); -+ - map_destroy(mymtd); -- mymtd = NULL; -- } -- if (dc21285_map.map_priv_1) { - iounmap((void *)dc21285_map.map_priv_1); -- dc21285_map.map_priv_1 = 0; -- } -- if(dc21285_parts) -- kfree(dc21285_parts); - } - - module_init(init_dc21285); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/dilnetpc.c linux/drivers/mtd/maps/dilnetpc.c ---- linux-mips-2.4.27/drivers/mtd/maps/dilnetpc.c 2002-06-27 00:35:50.000000000 +0200 -+++ linux/drivers/mtd/maps/dilnetpc.c 2004-11-19 10:25:11.907198576 +0100 -@@ -14,7 +14,7 @@ - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * -- * $Id$ -+ * $Id$ - * - * The DIL/Net PC is a tiny embedded PC board made by SSV Embedded Systems - * featuring the AMD Elan SC410 processor. There are two variants of this -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -36,7 +37,7 @@ - #include - - /* --** The DIL/NetPC keeps it's BIOS in two distinct flash blocks. -+** The DIL/NetPC keeps its BIOS in two distinct flash blocks. - ** Destroying any of these blocks transforms the DNPC into - ** a paperweight (albeit not a very useful one, considering - ** it only weighs a few grams). -@@ -189,45 +190,6 @@ - } - - --static __u8 dnpc_read8(struct map_info *map, unsigned long ofs) --{ -- return readb(map->map_priv_1 + ofs); --} -- --static __u16 dnpc_read16(struct map_info *map, unsigned long ofs) --{ -- return readw(map->map_priv_1 + ofs); --} -- --static __u32 dnpc_read32(struct map_info *map, unsigned long ofs) --{ -- return readl(map->map_priv_1 + ofs); --} -- --static void dnpc_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); --} -- --static void dnpc_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, map->map_priv_1 + adr); --} -- --static void dnpc_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, map->map_priv_1 + adr); --} -- --static void dnpc_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- writel(d, map->map_priv_1 + adr); --} -- --static void dnpc_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio((void *)(map->map_priv_1 + to), from, len); --} - - /* - ************************************************************ -@@ -288,19 +250,11 @@ - #define WINDOW_ADDR FLASH_BASE - - static struct map_info dnpc_map = { -- name: "ADNP Flash Bank", -- size: ADNP_WINDOW_SIZE, -- buswidth: 1, -- read8: dnpc_read8, -- read16: dnpc_read16, -- read32: dnpc_read32, -- copy_from: dnpc_copy_from, -- write8: dnpc_write8, -- write16: dnpc_write16, -- write32: dnpc_write32, -- copy_to: dnpc_copy_to, -- set_vpp: adnp_set_vpp, -- map_priv_2: WINDOW_ADDR -+ .name = "ADNP Flash Bank", -+ .size = ADNP_WINDOW_SIZE, -+ .buswidth = 1, -+ .set_vpp = adnp_set_vpp, -+ .phys = WINDOW_ADDR - }; - - /* -@@ -316,29 +270,29 @@ - static struct mtd_partition partition_info[]= - { - { -- name: "ADNP boot", -- offset: 0, -- size: 0xf0000, -+ .name = "ADNP boot", -+ .offset = 0, -+ .size = 0xf0000, - }, - { -- name: "ADNP system BIOS", -- offset: MTDPART_OFS_NXTBLK, -- size: 0x10000, -+ .name = "ADNP system BIOS", -+ .offset = MTDPART_OFS_NXTBLK, -+ .size = 0x10000, - #ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED -- mask_flags: MTD_WRITEABLE, -+ .mask_flags = MTD_WRITEABLE, - #endif - }, - { -- name: "ADNP file system", -- offset: MTDPART_OFS_NXTBLK, -- size: 0x2f0000, -+ .name = "ADNP file system", -+ .offset = MTDPART_OFS_NXTBLK, -+ .size = 0x2f0000, - }, - { -- name: "ADNP system BIOS entry", -- offset: MTDPART_OFS_NXTBLK, -- size: MTDPART_SIZ_FULL, -+ .name = "ADNP system BIOS entry", -+ .offset = MTDPART_OFS_NXTBLK, -+ .size = MTDPART_SIZ_FULL, - #ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED -- mask_flags: MTD_WRITEABLE, -+ .mask_flags = MTD_WRITEABLE, - #endif - }, - }; -@@ -369,21 +323,21 @@ - static struct mtd_partition higlvl_partition_info[]= - { - { -- name: "ADNP boot block", -- offset: 0, -- size: CONFIG_MTD_DILNETPC_BOOTSIZE, -+ .name = "ADNP boot block", -+ .offset = 0, -+ .size = CONFIG_MTD_DILNETPC_BOOTSIZE, - }, - { -- name: "ADNP file system space", -- offset: MTDPART_OFS_NXTBLK, -- size: ADNP_WINDOW_SIZE-CONFIG_MTD_DILNETPC_BOOTSIZE-0x20000, -+ .name = "ADNP file system space", -+ .offset = MTDPART_OFS_NXTBLK, -+ .size = ADNP_WINDOW_SIZE-CONFIG_MTD_DILNETPC_BOOTSIZE-0x20000, - }, - { -- name: "ADNP system BIOS + BIOS Entry", -- offset: MTDPART_OFS_NXTBLK, -- size: MTDPART_SIZ_FULL, -+ .name = "ADNP system BIOS + BIOS Entry", -+ .offset = MTDPART_OFS_NXTBLK, -+ .size = MTDPART_SIZ_FULL, - #ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED -- mask_flags: MTD_WRITEABLE, -+ .mask_flags = MTD_WRITEABLE, - #endif - }, - }; -@@ -447,18 +401,19 @@ - } - - printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%lx\n", -- is_dnp ? "DNPC" : "ADNP", dnpc_map.size, dnpc_map.map_priv_2); -+ is_dnp ? "DNPC" : "ADNP", dnpc_map.size, dnpc_map.phys); - -- dnpc_map.map_priv_1 = (unsigned long)ioremap_nocache(dnpc_map.map_priv_2, dnpc_map.size); -+ dnpc_map.virt = (unsigned long)ioremap_nocache(dnpc_map.phys, dnpc_map.size); - -- dnpc_map_flash(dnpc_map.map_priv_2, dnpc_map.size); -+ dnpc_map_flash(dnpc_map.phys, dnpc_map.size); - -- if (!dnpc_map.map_priv_1) { -+ if (!dnpc_map.virt) { - printk("Failed to ioremap_nocache\n"); - return -EIO; - } -+ simple_map_init(&dnpc_map); - -- printk("FLASH virtual address: 0x%lx\n", dnpc_map.map_priv_1); -+ printk("FLASH virtual address: 0x%lx\n", dnpc_map.virt); - - mymtd = do_map_probe("jedec_probe", &dnpc_map); - -@@ -475,11 +430,11 @@ - mymtd->erasesize = 0x10000; - - if (!mymtd) { -- iounmap((void *)dnpc_map.map_priv_1); -+ iounmap((void *)dnpc_map.virt); - return -ENXIO; - } - -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - /* - ** Supply pointers to lowlvl_parts[] array to add_mtd_partitions() -@@ -525,10 +480,10 @@ - del_mtd_partitions(mymtd); - map_destroy(mymtd); - } -- if (dnpc_map.map_priv_1) { -- iounmap((void *)dnpc_map.map_priv_1); -+ if (dnpc_map.virt) { -+ iounmap((void *)dnpc_map.virt); - dnpc_unmap_flash(); -- dnpc_map.map_priv_1 = 0; -+ dnpc_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/ebony.c linux/drivers/mtd/maps/ebony.c ---- linux-mips-2.4.27/drivers/mtd/maps/ebony.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/ebony.c 2004-11-19 10:25:11.909198272 +0100 -@@ -0,0 +1,164 @@ -+/* -+ * $Id$ -+ * -+ * Mapping for Ebony user flash -+ * -+ * Matt Porter -+ * -+ * Copyright 2002 MontaVista Software Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static struct mtd_info *flash; -+ -+static struct map_info ebony_small_map = { -+ .name = "Ebony small flash", -+ .size = EBONY_SMALL_FLASH_SIZE, -+ .buswidth = 1, -+}; -+ -+static struct map_info ebony_large_map = { -+ .name = "Ebony large flash", -+ .size = EBONY_LARGE_FLASH_SIZE, -+ .buswidth = 1, -+}; -+ -+static struct mtd_partition ebony_small_partitions[] = { -+ { -+ .name = "OpenBIOS", -+ .offset = 0x0, -+ .size = 0x80000, -+ } -+}; -+ -+static struct mtd_partition ebony_large_partitions[] = { -+ { -+ .name = "fs", -+ .offset = 0, -+ .size = 0x380000, -+ }, -+ { -+ .name = "firmware", -+ .offset = 0x380000, -+ .size = 0x80000, -+ } -+}; -+ -+int __init init_ebony(void) -+{ -+ u8 fpga0_reg; -+ unsigned long fpga0_adr; -+ unsigned long long small_flash_base, large_flash_base; -+ -+ fpga0_adr = ioremap64(EBONY_FPGA_ADDR, 16); -+ if (!fpga0_adr) -+ return -ENOMEM; -+ -+ fpga0_reg = readb(fpga0_adr); -+ iounmap64(fpga0_adr); -+ -+ if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) && -+ !EBONY_FLASH_SEL(fpga0_reg)) -+ small_flash_base = EBONY_SMALL_FLASH_HIGH2; -+ else if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) && -+ EBONY_FLASH_SEL(fpga0_reg)) -+ small_flash_base = EBONY_SMALL_FLASH_HIGH1; -+ else if (!EBONY_BOOT_SMALL_FLASH(fpga0_reg) && -+ !EBONY_FLASH_SEL(fpga0_reg)) -+ small_flash_base = EBONY_SMALL_FLASH_LOW2; -+ else -+ small_flash_base = EBONY_SMALL_FLASH_LOW1; -+ -+ if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) && -+ !EBONY_ONBRD_FLASH_EN(fpga0_reg)) -+ large_flash_base = EBONY_LARGE_FLASH_LOW; -+ else -+ large_flash_base = EBONY_LARGE_FLASH_HIGH; -+ -+ ebony_small_map.phys = small_flash_base; -+ ebony_small_map.virt = -+ (unsigned long)ioremap64(small_flash_base, -+ ebony_small_map.size); -+ -+ if (!ebony_small_map.virt) { -+ printk("Failed to ioremap flash\n"); -+ return -EIO; -+ } -+ -+ simple_map_init(&ebony_small_map); -+ -+ flash = do_map_probe("map_rom", &ebony_small_map); -+ if (flash) { -+ flash->owner = THIS_MODULE; -+ add_mtd_partitions(flash, ebony_small_partitions, -+ ARRAY_SIZE(ebony_small_partitions)); -+ } else { -+ printk("map probe failed for flash\n"); -+ return -ENXIO; -+ } -+ -+ ebony_large_map.phys = large_flash_base; -+ ebony_large_map.virt = -+ (unsigned long)ioremap64(large_flash_base, -+ ebony_large_map.size); -+ -+ if (!ebony_large_map.virt) { -+ printk("Failed to ioremap flash\n"); -+ return -EIO; -+ } -+ -+ simple_map_init(&ebony_large_map); -+ -+ flash = do_map_probe("cfi_probe", &ebony_large_map); -+ if (flash) { -+ flash->owner = THIS_MODULE; -+ add_mtd_partitions(flash, ebony_large_partitions, -+ ARRAY_SIZE(ebony_large_partitions)); -+ } else { -+ printk("map probe failed for flash\n"); -+ return -ENXIO; -+ } -+ -+ return 0; -+} -+ -+static void __exit cleanup_ebony(void) -+{ -+ if (flash) { -+ del_mtd_partitions(flash); -+ map_destroy(flash); -+ } -+ -+ if (ebony_small_map.virt) { -+ iounmap((void *)ebony_small_map.virt); -+ ebony_small_map.virt = 0; -+ } -+ -+ if (ebony_large_map.virt) { -+ iounmap((void *)ebony_large_map.virt); -+ ebony_large_map.virt = 0; -+ } -+} -+ -+module_init(init_ebony); -+module_exit(cleanup_ebony); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Matt Porter "); -+MODULE_DESCRIPTION("MTD map and partitions for IBM 440GP Ebony boards"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/edb7312.c linux/drivers/mtd/maps/edb7312.c ---- linux-mips-2.4.27/drivers/mtd/maps/edb7312.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/maps/edb7312.c 2004-11-19 10:25:11.910198120 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Handle mapping of the NOR flash on Cogent EDB7312 boards - * -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -35,61 +36,11 @@ - - static struct mtd_info *mymtd; - --__u8 edb7312nor_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 edb7312nor_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 edb7312nor_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void edb7312nor_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void edb7312nor_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void edb7312nor_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void edb7312nor_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void edb7312nor_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} -- - struct map_info edb7312nor_map = { -- name: "NOR flash on EDB7312", -- size: WINDOW_SIZE, -- buswidth: BUSWIDTH, -- read8: edb7312nor_read8, -- read16: edb7312nor_read16, -- read32: edb7312nor_read32, -- copy_from: edb7312nor_copy_from, -- write8: edb7312nor_write8, -- write16: edb7312nor_write16, -- write32: edb7312nor_write32, -- copy_to: edb7312nor_copy_to -+ .name = "NOR flash on EDB7312", -+ .size = WINDOW_SIZE, -+ .buswidth = BUSWIDTH, -+ .phys = WINDOW_ADDR, - }; - - #ifdef CONFIG_MTD_PARTITIONS -@@ -100,29 +51,23 @@ - static struct mtd_partition static_partitions[3] = - { - { -- name: "ARMboot", -- size: 0x40000, -- offset: 0 -+ .name = "ARMboot", -+ .size = 0x40000, -+ .offset = 0 - }, - { -- name: "Kernel", -- size: 0x200000, -- offset: 0x40000 -+ .name = "Kernel", -+ .size = 0x200000, -+ .offset = 0x40000 - }, - { -- name: "RootFS", -- size: 0xDC0000, -- offset: 0x240000 -+ .name = "RootFS", -+ .size = 0xDC0000, -+ .offset = 0x240000 - }, - }; - --#define NB_OF(x) (sizeof (x) / sizeof (x[0])) -- --#ifdef CONFIG_MTD_CMDLINE_PARTS --int parse_cmdline_partitions(struct mtd_info *master, -- struct mtd_partition **pparts, -- const char *mtd_id); --#endif -+static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; - - #endif - -@@ -137,32 +82,33 @@ - - printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n", - WINDOW_SIZE, WINDOW_ADDR); -- edb7312nor_map.map_priv_1 = (unsigned long) -+ edb7312nor_map.virt = (unsigned long) - ioremap(WINDOW_ADDR, WINDOW_SIZE); - -- if (!edb7312nor_map.map_priv_1) { -+ if (!edb7312nor_map.virt) { - printk(MSG_PREFIX "failed to ioremap\n"); - return -EIO; - } - -+ simple_map_init(&edb7312nor_map); -+ - mymtd = 0; - type = rom_probe_types; - for(; !mymtd && *type; type++) { - mymtd = do_map_probe(*type, &edb7312nor_map); - } - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - #ifdef CONFIG_MTD_PARTITIONS --#ifdef CONFIG_MTD_CMDLINE_PARTS -- mtd_parts_nb = parse_cmdline_partitions(mymtd, &mtd_parts, MTDID); -+ mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, MTDID); - if (mtd_parts_nb > 0) -- part_type = "command line"; --#endif -+ part_type = "detected"; -+ - if (mtd_parts_nb == 0) - { - mtd_parts = static_partitions; -- mtd_parts_nb = NB_OF(static_partitions); -+ mtd_parts_nb = ARRAY_SIZE(static_partitions); - part_type = "static"; - } - #endif -@@ -178,7 +124,7 @@ - return 0; - } - -- iounmap((void *)edb7312nor_map.map_priv_1); -+ iounmap((void *)edb7312nor_map.virt); - return -ENXIO; - } - -@@ -188,9 +134,9 @@ - del_mtd_device(mymtd); - map_destroy(mymtd); - } -- if (edb7312nor_map.map_priv_1) { -- iounmap((void *)edb7312nor_map.map_priv_1); -- edb7312nor_map.map_priv_1 = 0; -+ if (edb7312nor_map.virt) { -+ iounmap((void *)edb7312nor_map.virt); -+ edb7312nor_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/elan-104nc.c linux/drivers/mtd/maps/elan-104nc.c ---- linux-mips-2.4.27/drivers/mtd/maps/elan-104nc.c 2002-06-27 00:35:50.000000000 +0200 -+++ linux/drivers/mtd/maps/elan-104nc.c 2004-11-19 10:25:11.912197816 +0100 -@@ -16,7 +16,7 @@ - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - -- $Id$ -+ $Id$ - - The ELAN-104NC has up to 8 Mibyte of Intel StrataFlash (28F320/28F640) in x16 - mode. This drivers uses the CFI probe and Intel Extended Command Set drivers. -@@ -40,6 +40,7 @@ - #include - - #include -+#include - #include - - #define WINDOW_START 0xb0000 -@@ -59,14 +60,14 @@ - * single flash device into. If the size if zero we use up to the end of the - * device. */ - static struct mtd_partition partition_info[]={ -- { name: "ELAN-104NC flash boot partition", -- offset: 0, -- size: 640*1024 }, -- { name: "ELAN-104NC flash partition 1", -- offset: 640*1024, -- size: 896*1024 }, -- { name: "ELAN-104NC flash partition 2", -- offset: (640+896)*1024 } -+ { .name = "ELAN-104NC flash boot partition", -+ .offset = 0, -+ .size = 640*1024 }, -+ { .name = "ELAN-104NC flash partition 1", -+ .offset = 640*1024, -+ .size = 896*1024 }, -+ { .name = "ELAN-104NC flash partition 2", -+ .offset = (640+896)*1024 } - }; - #define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0])) - -@@ -195,19 +196,20 @@ - } - - static struct map_info elan_104nc_map = { -- name: "ELAN-104NC flash", -- size: 8*1024*1024, /* this must be set to a maximum possible amount -+ .name = "ELAN-104NC flash", -+ .phys = NO_XIP, -+ .size = 8*1024*1024, /* this must be set to a maximum possible amount - of flash so the cfi probe routines find all - the chips */ -- buswidth: 2, -- read8: elan_104nc_read8, -- read16: elan_104nc_read16, -- read32: elan_104nc_read32, -- copy_from: elan_104nc_copy_from, -- write8: elan_104nc_write8, -- write16: elan_104nc_write16, -- write32: elan_104nc_write32, -- copy_to: elan_104nc_copy_to -+ .buswidth = 2, -+ .read8 = elan_104nc_read8, -+ .read16 = elan_104nc_read16, -+ .read32 = elan_104nc_read32, -+ .copy_from = elan_104nc_copy_from, -+ .write8 = elan_104nc_write8, -+ .write16 = elan_104nc_write16, -+ .write32 = elan_104nc_write32, -+ .copy_to = elan_104nc_copy_to - }; - - /* MTD device for all of the flash. */ -@@ -221,20 +223,13 @@ - } - - iounmap((void *)iomapadr); -- release_region(PAGE_IO,PAGE_IO_SIZE); - } - - int __init init_elan_104nc(void) - { -- /* Urg! We use I/O port 0x22 without request_region()ing it */ -- /* -- if (check_region(PAGE_IO,PAGE_IO_SIZE) != 0) { -- printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n", -- elan_104nc_map.name, -- PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 ); -- return -EAGAIN; -- } -- */ -+ /* Urg! We use I/O port 0x22 without request_region()ing it, -+ because it's already allocated to the PIC. */ -+ - iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); - if (!iomapadr) { - printk( KERN_ERR"%s: failed to ioremap memory region\n", -@@ -242,10 +237,6 @@ - return -EIO; - } - -- /* -- request_region( PAGE_IO, PAGE_IO_SIZE, "ELAN-104NC flash" ); -- */ -- - printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n", - elan_104nc_map.name, - PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1, -@@ -260,7 +251,7 @@ - return -ENXIO; - } - -- all_mtd->module=THIS_MODULE; -+ all_mtd->owner = THIS_MODULE; - - /* Create MTD devices for each partition. */ - add_mtd_partitions( all_mtd, partition_info, NUM_PARTITIONS ); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/epxa10db-flash.c linux/drivers/mtd/maps/epxa10db-flash.c ---- linux-mips-2.4.27/drivers/mtd/maps/epxa10db-flash.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/maps/epxa10db-flash.c 2004-11-19 10:25:11.913197664 +0100 -@@ -5,7 +5,7 @@ - * Copyright (C) 2001 Altera Corporation - * Copyright (C) 2001 Red Hat, Inc. - * -- * $Id$ -+ * $Id$ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -43,87 +44,38 @@ - - static struct mtd_info *mymtd; - --extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **); - static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts); - --static __u8 epxa_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --static __u16 epxa_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --static __u32 epxa_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --static void epxa_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); --} -- --static void epxa_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --static void epxa_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --static void epxa_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --static void epxa_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio((void *)(map->map_priv_1 + to), from, len); --} -- -- - - static struct map_info epxa_map = { -- name: "EPXA flash", -- size: FLASH_SIZE, -- buswidth: 2, -- read8: epxa_read8, -- read16: epxa_read16, -- read32: epxa_read32, -- copy_from: epxa_copy_from, -- write8: epxa_write8, -- write16: epxa_write16, -- write32: epxa_write32, -- copy_to: epxa_copy_to -+ .name = "EPXA flash", -+ .size = FLASH_SIZE, -+ .buswidth = 2, -+ .phys = FLASH_START, - }; - -+static const char *probes[] = { "RedBoot", "afs", NULL }; - - static int __init epxa_mtd_init(void) - { - int i; - -- printk(KERN_NOTICE "%s flash device: %x at %x\n", BOARD_NAME, FLASH_SIZE, FLASH_START); -- epxa_map.map_priv_1 = (unsigned long)ioremap(FLASH_START, FLASH_SIZE); -- if (!epxa_map.map_priv_1) { -+ printk(KERN_NOTICE "%s flash device: 0x%x at 0x%x\n", BOARD_NAME, FLASH_SIZE, FLASH_START); -+ -+ epxa_map.virt = (unsigned long)ioremap(FLASH_START, FLASH_SIZE); -+ if (!epxa_map.virt) { - printk("Failed to ioremap %s flash\n",BOARD_NAME); - return -EIO; - } -+ simple_map_init(&epxa_map); - - mymtd = do_map_probe("cfi_probe", &epxa_map); - if (!mymtd) { -- iounmap((void *)epxa_map.map_priv_1); -+ iounmap((void *)epxa_map.virt); - return -ENXIO; - } - -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - /* Unlock the flash device. */ - if(mymtd->unlock){ -@@ -135,23 +87,14 @@ - } - } - --#ifdef CONFIG_MTD_REDBOOT_PARTS -- nr_parts = parse_redboot_partitions(mymtd, &parts); -- -- if (nr_parts > 0) { -- add_mtd_partitions(mymtd, parts, nr_parts); -- return 0; -- } --#endif --#ifdef CONFIG_MTD_AFS_PARTS -- nr_parts = parse_afs_partitions(mymtd, &parts); -+#ifdef CONFIG_MTD_PARTITIONS -+ nr_parts = parse_mtd_partitions(mymtd, probes, &parts, 0); - - if (nr_parts > 0) { - add_mtd_partitions(mymtd, parts, nr_parts); - return 0; - } - #endif -- - /* No recognised partitioning schemes found - use defaults */ - nr_parts = epxa_default_partitions(mymtd, &parts); - if (nr_parts > 0) { -@@ -173,9 +116,9 @@ - del_mtd_device(mymtd); - map_destroy(mymtd); - } -- if (epxa_map.map_priv_1) { -- iounmap((void *)epxa_map.map_priv_1); -- epxa_map.map_priv_1 = 0; -+ if (epxa_map.virt) { -+ iounmap((void *)epxa_map.virt); -+ epxa_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/fortunet.c linux/drivers/mtd/maps/fortunet.c ---- linux-mips-2.4.27/drivers/mtd/maps/fortunet.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/maps/fortunet.c 2004-11-19 10:25:11.915197360 +0100 -@@ -1,11 +1,12 @@ - /* fortunet.c memory map - * -- * $Id$ -+ * $Id$ - */ - - #include - #include - #include -+#include - #include - #include - #include -@@ -23,7 +24,7 @@ - - struct map_region - { -- int window_addr_phyical; -+ int window_addr_physical; - int altbuswidth; - struct map_info map_info; - struct mtd_info *mymtd; -@@ -37,57 +38,10 @@ - static int map_regions_parts[MAX_NUM_REGIONS] = {0,0,0,0}; - - --__u8 fortunet_read8(struct map_info *map, unsigned long ofs) --{ -- return *(__u8 *)(map->map_priv_1 + ofs); --} -- --__u16 fortunet_read16(struct map_info *map, unsigned long ofs) --{ -- return *(__u16 *)(map->map_priv_1 + ofs); --} -- --__u32 fortunet_read32(struct map_info *map, unsigned long ofs) --{ -- return *(__u32 *)(map->map_priv_1 + ofs); --} -- --void fortunet_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy(to, (void *)(map->map_priv_1 + from), len); --} -- --void fortunet_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- *(__u8 *)(map->map_priv_1 + adr) = d; --} -- --void fortunet_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- *(__u16 *)(map->map_priv_1 + adr) = d; --} -- --void fortunet_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- *(__u32 *)(map->map_priv_1 + adr) = d; --} -- --void fortunet_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy((void *)(map->map_priv_1 + to), from, len); --} - - struct map_info default_map = { -- size: DEF_WINDOW_SIZE, -- buswidth: 4, -- read8: fortunet_read8, -- read16: fortunet_read16, -- read32: fortunet_read32, -- copy_from: fortunet_copy_from, -- write8: fortunet_write8, -- write16: fortunet_write16, -- write32: fortunet_write32, -- copy_to: fortunet_copy_to -+ .size = DEF_WINDOW_SIZE, -+ .buswidth = 4, - }; - - static char * __init get_string_option(char *dest,int dest_size,char *sor) -@@ -147,7 +101,7 @@ - get_options (get_string_option(string,sizeof(string),line),6,params); - if(params[0]<1) - { -- printk(MTD_FORTUNET_PK "Bad paramters for MTD Region " -+ printk(MTD_FORTUNET_PK "Bad parameters for MTD Region " - " name,region-number[,base,size,buswidth,altbuswidth]\n"); - return 1; - } -@@ -161,14 +115,14 @@ - memcpy(&map_regions[params[1]].map_info, - &default_map,sizeof(map_regions[params[1]].map_info)); - map_regions_set[params[1]] = 1; -- map_regions[params[1]].window_addr_phyical = DEF_WINDOW_ADDR_PHY; -+ map_regions[params[1]].window_addr_physical = DEF_WINDOW_ADDR_PHY; - map_regions[params[1]].altbuswidth = 2; - map_regions[params[1]].mymtd = NULL; - map_regions[params[1]].map_info.name = map_regions[params[1]].map_name; - strcpy(map_regions[params[1]].map_info.name,string); - if(params[0]>1) - { -- map_regions[params[1]].window_addr_phyical = params[2]; -+ map_regions[params[1]].window_addr_physical = params[2]; - } - if(params[0]>2) - { -@@ -185,14 +139,14 @@ - return 1; - } - --static int __init MTD_New_Partion(char *line) -+static int __init MTD_New_Partition(char *line) - { - char string[MAX_NAME_SIZE]; - int params[4]; - get_options (get_string_option(string,sizeof(string),line),4,params); - if(params[0]<3) - { -- printk(MTD_FORTUNET_PK "Bad paramters for MTD Partion " -+ printk(MTD_FORTUNET_PK "Bad parameters for MTD Partition " - " name,region-number,size,offset\n"); - return 1; - } -@@ -204,7 +158,7 @@ - } - if(map_regions_parts[params[1]]>=MAX_NUM_PARTITIONS) - { -- printk(MTD_FORTUNET_PK "Out of space for partion in this region\n"); -+ printk(MTD_FORTUNET_PK "Out of space for partition in this region\n"); - return 1; - } - map_regions[params[1]].parts[map_regions_parts[params[1]]].name = -@@ -220,7 +174,10 @@ - } - - __setup("MTD_Region=", MTD_New_Region); --__setup("MTD_Partion=", MTD_New_Partion); -+__setup("MTD_Partition=", MTD_New_Partition); -+ -+/* Backwards-spelling-compatibility */ -+__setup("MTD_Partion=", MTD_New_Partition); - - int __init init_fortunet(void) - { -@@ -229,13 +186,13 @@ - { - if(map_regions_parts[ix]&&(!map_regions_set[ix])) - { -- printk(MTD_FORTUNET_PK "Region %d is not setup (Seting to default)\n", -+ printk(MTD_FORTUNET_PK "Region %d is not setup (Setting to default)\n", - ix); - memset(&map_regions[ix],0,sizeof(map_regions[ix])); - memcpy(&map_regions[ix].map_info,&default_map, - sizeof(map_regions[ix].map_info)); - map_regions_set[ix] = 1; -- map_regions[ix].window_addr_phyical = DEF_WINDOW_ADDR_PHY; -+ map_regions[ix].window_addr_physical = DEF_WINDOW_ADDR_PHY; - map_regions[ix].altbuswidth = 2; - map_regions[ix].mymtd = NULL; - map_regions[ix].map_info.name = map_regions[ix].map_name; -@@ -244,30 +201,35 @@ - if(map_regions_set[ix]) - { - iy++; -- printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash device at phyicaly " -+ printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash device at physically " - " address %x size %x\n", - map_regions[ix].map_info.name, -- map_regions[ix].window_addr_phyical, -+ map_regions[ix].window_addr_physical, - map_regions[ix].map_info.size); -- map_regions[ix].map_info.map_priv_1 = -+ -+ map_regions[ix].map_info.phys = map_regions[ix].window_addr_physical, -+ -+ map_regions[ix].map_info.virt = - (int)ioremap_nocache( -- map_regions[ix].window_addr_phyical, -+ map_regions[ix].window_addr_physical, - map_regions[ix].map_info.size); -- if(!map_regions[ix].map_info.map_priv_1) -+ if(!map_regions[ix].map_info.virt) - { - printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n", - map_regions[ix].map_info.name); - return -ENXIO; - } -- printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash is veritualy at: %x\n", -+ simple_map_init(&map_regions[ix].map_info); -+ -+ printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash is virtually at: %x\n", - map_regions[ix].map_info.name, -- map_regions[ix].map_info.map_priv_1); -+ map_regions[ix].map_info.virt); - map_regions[ix].mymtd = do_map_probe("cfi_probe", - &map_regions[ix].map_info); - if((!map_regions[ix].mymtd)&&( - map_regions[ix].altbuswidth!=map_regions[ix].map_info.buswidth)) - { -- printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternet buswidth " -+ printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternate buswidth " - "for %s flash.\n", - map_regions[ix].map_info.name); - map_regions[ix].map_info.buswidth = -@@ -275,7 +237,7 @@ - map_regions[ix].mymtd = do_map_probe("cfi_probe", - &map_regions[ix].map_info); - } -- map_regions[ix].mymtd->module = THIS_MODULE; -+ map_regions[ix].mymtd->owner = THIS_MODULE; - add_mtd_partitions(map_regions[ix].mymtd, - map_regions[ix].parts,map_regions_parts[ix]); - } -@@ -297,7 +259,7 @@ - del_mtd_partitions( map_regions[ix].mymtd ); - map_destroy( map_regions[ix].mymtd ); - } -- iounmap((void *)map_regions[ix].map_info.map_priv_1); -+ iounmap((void *)map_regions[ix].map_info.virt); - } - } - } -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/h720x-flash.c linux/drivers/mtd/maps/h720x-flash.c ---- linux-mips-2.4.27/drivers/mtd/maps/h720x-flash.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/h720x-flash.c 2004-11-19 10:25:11.917197056 +0100 -@@ -0,0 +1,142 @@ -+/* -+ * Flash memory access on Hynix GMS30C7201/HMS30C7202 based -+ * evaluation boards -+ * -+ * (C) 2002 Jungjun Kim -+ * 2003 Thomas Gleixner -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static struct mtd_info *mymtd; -+ -+static struct map_info h720x_map = { -+ .name = "H720X", -+ .buswidth = 4, -+ .size = FLASH_SIZE, -+ .phys = FLASH_PHYS, -+}; -+ -+static struct mtd_partition h720x_partitions[] = { -+ { -+ .name = "ArMon", -+ .size = 0x00080000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE -+ },{ -+ .name = "Env", -+ .size = 0x00040000, -+ .offset = 0x00080000, -+ .mask_flags = MTD_WRITEABLE -+ },{ -+ .name = "Kernel", -+ .size = 0x00180000, -+ .offset = 0x000c0000, -+ .mask_flags = MTD_WRITEABLE -+ },{ -+ .name = "Ramdisk", -+ .size = 0x00400000, -+ .offset = 0x00240000, -+ .mask_flags = MTD_WRITEABLE -+ },{ -+ .name = "jffs2", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND -+ } -+}; -+ -+#define NUM_PARTITIONS (sizeof(h720x_partitions)/sizeof(h720x_partitions[0])) -+ -+static int nr_mtd_parts; -+static struct mtd_partition *mtd_parts; -+static const char *probes[] = { "cmdlinepart", NULL }; -+ -+/* -+ * Initialize FLASH support -+ */ -+int __init h720x_mtd_init(void) -+{ -+ -+ char *part_type = NULL; -+ -+ h720x_map.virt = (unsigned long)ioremap(FLASH_PHYS, FLASH_SIZE); -+ -+ if (!h720x_map.virt) { -+ printk(KERN_ERR "H720x-MTD: ioremap failed\n"); -+ return -EIO; -+ } -+ -+ simple_map_init(&h720x_map); -+ -+ // Probe for flash buswidth 4 -+ printk (KERN_INFO "H720x-MTD probing 32bit FLASH\n"); -+ mymtd = do_map_probe("cfi_probe", &h720x_map); -+ if (!mymtd) { -+ printk (KERN_INFO "H720x-MTD probing 16bit FLASH\n"); -+ // Probe for buswidth 2 -+ h720x_map.buswidth = 2; -+ mymtd = do_map_probe("cfi_probe", &h720x_map); -+ } -+ -+ if (mymtd) { -+ mymtd->owner = THIS_MODULE; -+ -+#ifdef CONFIG_MTD_PARTITIONS -+ nr_mtd_parts = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0); -+ if (nr_mtd_parts > 0) -+ part_type = "command line"; -+#endif -+ if (nr_mtd_parts <= 0) { -+ mtd_parts = h720x_partitions; -+ nr_mtd_parts = NUM_PARTITIONS; -+ part_type = "builtin"; -+ } -+ printk(KERN_INFO "Using %s partition table\n", part_type); -+ add_mtd_partitions(mymtd, mtd_parts, nr_mtd_parts); -+ return 0; -+ } -+ -+ iounmap((void *)h720x_map.virt); -+ return -ENXIO; -+} -+ -+/* -+ * Cleanup -+ */ -+static void __exit h720x_mtd_cleanup(void) -+{ -+ -+ if (mymtd) { -+ del_mtd_partitions(mymtd); -+ map_destroy(mymtd); -+ } -+ -+ /* Free partition info, if commandline partition was used */ -+ if (mtd_parts && (mtd_parts != h720x_partitions)) -+ kfree (mtd_parts); -+ -+ if (h720x_map.virt) { -+ iounmap((void *)h720x_map.virt); -+ h720x_map.virt = 0; -+ } -+} -+ -+ -+module_init(h720x_mtd_init); -+module_exit(h720x_mtd_cleanup); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Thomas Gleixner "); -+MODULE_DESCRIPTION("MTD map driver for Hynix evaluation boards"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/ichxrom.c linux/drivers/mtd/maps/ichxrom.c ---- linux-mips-2.4.27/drivers/mtd/maps/ichxrom.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/ichxrom.c 2004-11-19 10:25:11.918196904 +0100 -@@ -0,0 +1,380 @@ -+/* -+ * ichxrom.c -+ * -+ * Normal mappings of chips in physical memory -+ * $Id$ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define xstr(s) str(s) -+#define str(s) #s -+#define MOD_NAME xstr(KBUILD_BASENAME) -+ -+#define MTD_DEV_NAME_LENGTH 16 -+ -+#define RESERVE_MEM_REGION 0 -+ -+#define ICHX_FWH_REGION_START 0xFF000000UL -+#define ICHX_FWH_REGION_SIZE 0x01000000UL -+#define BIOS_CNTL 0x4e -+#define FWH_DEC_EN1 0xE3 -+#define FWH_DEC_EN2 0xF0 -+#define FWH_SEL1 0xE8 -+#define FWH_SEL2 0xEE -+ -+struct ichxrom_map_info { -+ struct map_info map; -+ struct mtd_info *mtd; -+ unsigned long window_addr; -+ struct pci_dev *pdev; -+ struct resource window_rsrc; -+ struct resource rom_rsrc; -+ char mtd_name[MTD_DEV_NAME_LENGTH]; -+}; -+ -+static inline unsigned long addr(struct map_info *map, unsigned long ofs) -+{ -+ unsigned long offset; -+ offset = ((8*1024*1024) - map->size) + ofs; -+ if (offset >= (4*1024*1024)) { -+ offset += 0x400000; -+ } -+ return map->map_priv_1 + 0x400000 + offset; -+} -+ -+static inline unsigned long dbg_addr(struct map_info *map, unsigned long addr) -+{ -+ return addr - map->map_priv_1 + ICHX_FWH_REGION_START; -+} -+ -+static __u8 ichxrom_read8(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readb(addr(map, ofs)); -+} -+ -+static __u16 ichxrom_read16(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readw(addr(map, ofs)); -+} -+ -+static __u32 ichxrom_read32(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readl(addr(map, ofs)); -+} -+ -+static void ichxrom_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -+{ -+ memcpy_fromio(to, addr(map, from), len); -+} -+ -+static void ichxrom_write8(struct map_info *map, __u8 d, unsigned long ofs) -+{ -+ __raw_writeb(d, addr(map,ofs)); -+ mb(); -+} -+ -+static void ichxrom_write16(struct map_info *map, __u16 d, unsigned long ofs) -+{ -+ __raw_writew(d, addr(map, ofs)); -+ mb(); -+} -+ -+static void ichxrom_write32(struct map_info *map, __u32 d, unsigned long ofs) -+{ -+ __raw_writel(d, addr(map, ofs)); -+ mb(); -+} -+ -+static void ichxrom_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -+{ -+ memcpy_toio(addr(map, to), from, len); -+} -+ -+static struct ichxrom_map_info ichxrom_map = { -+ .map = { -+ .name = MOD_NAME, -+ .phys = NO_XIP, -+ .size = 0, -+ .buswidth = 1, -+ .read8 = ichxrom_read8, -+ .read16 = ichxrom_read16, -+ .read32 = ichxrom_read32, -+ .copy_from = ichxrom_copy_from, -+ .write8 = ichxrom_write8, -+ .write16 = ichxrom_write16, -+ .write32 = ichxrom_write32, -+ .copy_to = ichxrom_copy_to, -+ /* Firmware hubs only use vpp when being programmed -+ * in a factory setting. So in-place programming -+ * needs to use a different method. -+ */ -+ }, -+ /* remaining fields of structure are initialized to 0 */ -+}; -+ -+enum fwh_lock_state { -+ FWH_DENY_WRITE = 1, -+ FWH_IMMUTABLE = 2, -+ FWH_DENY_READ = 4, -+}; -+ -+static void ichxrom_cleanup(struct ichxrom_map_info *info) -+{ -+ u16 word; -+ -+ /* Disable writes through the rom window */ -+ pci_read_config_word(info->pdev, BIOS_CNTL, &word); -+ pci_write_config_word(info->pdev, BIOS_CNTL, word & ~1); -+ -+ if (info->mtd) { -+ del_mtd_device(info->mtd); -+ map_destroy(info->mtd); -+ info->mtd = NULL; -+ info->map.virt = 0; -+ } -+ if (info->rom_rsrc.parent) -+ release_resource(&info->rom_rsrc); -+ if (info->window_rsrc.parent) -+ release_resource(&info->window_rsrc); -+ -+ if (info->window_addr) { -+ iounmap((void *)(info->window_addr)); -+ info->window_addr = 0; -+ } -+} -+ -+ -+static int ichxrom_set_lock_state(struct mtd_info *mtd, loff_t ofs, size_t len, -+ enum fwh_lock_state state) -+{ -+ struct map_info *map = mtd->priv; -+ unsigned long start = ofs; -+ unsigned long end = start + len -1; -+ -+ /* FIXME do I need to guard against concurrency here? */ -+ /* round down to 64K boundaries */ -+ start = start & ~0xFFFF; -+ end = end & ~0xFFFF; -+ while (start <= end) { -+ unsigned long ctrl_addr; -+ ctrl_addr = addr(map, start) - 0x400000 + 2; -+ writeb(state, ctrl_addr); -+ start = start + 0x10000; -+ } -+ return 0; -+} -+ -+static int ichxrom_lock(struct mtd_info *mtd, loff_t ofs, size_t len) -+{ -+ return ichxrom_set_lock_state(mtd, ofs, len, FWH_DENY_WRITE); -+} -+ -+static int ichxrom_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) -+{ -+ return ichxrom_set_lock_state(mtd, ofs, len, 0); -+} -+ -+static int __devinit ichxrom_init_one (struct pci_dev *pdev, -+ const struct pci_device_id *ent) -+{ -+ u16 word; -+ struct ichxrom_map_info *info = &ichxrom_map; -+ unsigned long map_size; -+ -+ /* For now I just handle the ichx and I assume there -+ * are not a lot of resources up at the top of the address -+ * space. It is possible to handle other devices in the -+ * top 16MB but it is very painful. Also since -+ * you can only really attach a FWH to an ICHX there -+ * a number of simplifications you can make. -+ * -+ * Also you can page firmware hubs if an 8MB window isn't enough -+ * but don't currently handle that case either. -+ */ -+ -+ info->pdev = pdev; -+ -+ /* -+ * Try to reserve the window mem region. If this fails then -+ * it is likely due to the window being "reseved" by the BIOS. -+ */ -+ info->window_rsrc.name = MOD_NAME; -+ info->window_rsrc.start = ICHX_FWH_REGION_START; -+ info->window_rsrc.end = ICHX_FWH_REGION_START + ICHX_FWH_REGION_SIZE - 1; -+ info->window_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; -+ if (request_resource(&iomem_resource, &info->window_rsrc)) { -+ info->window_rsrc.parent = NULL; -+ printk(KERN_ERR MOD_NAME -+ " %s(): Unable to register resource" -+ " 0x%.08lx-0x%.08lx - kernel bug?\n", -+ __func__, -+ info->window_rsrc.start, info->window_rsrc.end); -+ } -+ -+ /* Enable writes through the rom window */ -+ pci_read_config_word(pdev, BIOS_CNTL, &word); -+ if (!(word & 1) && (word & (1<<1))) { -+ /* The BIOS will generate an error if I enable -+ * this device, so don't even try. -+ */ -+ printk(KERN_ERR MOD_NAME ": firmware access control, I can't enable writes\n"); -+ goto failed; -+ } -+ pci_write_config_word(pdev, BIOS_CNTL, word | 1); -+ -+ -+ /* Map the firmware hub into my address space. */ -+ /* Does this use too much virtual address space? */ -+ info->window_addr = (unsigned long)ioremap( -+ ICHX_FWH_REGION_START, ICHX_FWH_REGION_SIZE); -+ if (!info->window_addr) { -+ printk(KERN_ERR "Failed to ioremap\n"); -+ goto failed; -+ } -+ -+ /* For now assume the firmware has setup all relevant firmware -+ * windows. We don't have enough information to handle this case -+ * intelligently. -+ */ -+ -+ /* FIXME select the firmware hub and enable a window to it. */ -+ -+ info->mtd = 0; -+ info->map.map_priv_1 = info->window_addr; -+ -+ map_size = ICHX_FWH_REGION_SIZE; -+ while(!info->mtd && (map_size > 0)) { -+ info->map.size = map_size; -+ info->mtd = do_map_probe("jedec_probe", &ichxrom_map.map); -+ map_size -= 512*1024; -+ } -+ if (!info->mtd) { -+ goto failed; -+ } -+ /* I know I can only be a firmware hub here so put -+ * in the special lock and unlock routines. -+ */ -+ info->mtd->lock = ichxrom_lock; -+ info->mtd->unlock = ichxrom_unlock; -+ -+ info->mtd->owner = THIS_MODULE; -+ add_mtd_device(info->mtd); -+ -+ if (info->window_rsrc.parent) { -+ /* -+ * Registering the MTD device in iomem may not be possible -+ * if there is a BIOS "reserved" and BUSY range. If this -+ * fails then continue anyway. -+ */ -+ snprintf(info->mtd_name, MTD_DEV_NAME_LENGTH, -+ "mtd%d", info->mtd->index); -+ -+ info->rom_rsrc.name = info->mtd_name; -+ info->rom_rsrc.start = ICHX_FWH_REGION_START -+ + ICHX_FWH_REGION_SIZE - map_size; -+ info->rom_rsrc.end = ICHX_FWH_REGION_START -+ + ICHX_FWH_REGION_SIZE; -+ info->rom_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; -+ if (request_resource(&info->window_rsrc, &info->rom_rsrc)) { -+ printk(KERN_ERR MOD_NAME -+ ": cannot reserve MTD resource\n"); -+ info->rom_rsrc.parent = NULL; -+ } -+ } -+ -+ return 0; -+ -+ failed: -+ ichxrom_cleanup(info); -+ return -ENODEV; -+} -+ -+ -+static void __devexit ichxrom_remove_one (struct pci_dev *pdev) -+{ -+ struct ichxrom_map_info *info = &ichxrom_map; -+ u16 word; -+ -+ del_mtd_device(info->mtd); -+ map_destroy(info->mtd); -+ info->mtd = 0; -+ info->map.map_priv_1 = 0; -+ -+ iounmap((void *)(info->window_addr)); -+ info->window_addr = 0; -+ -+ /* Disable writes through the rom window */ -+ pci_read_config_word(pdev, BIOS_CNTL, &word); -+ pci_write_config_word(pdev, BIOS_CNTL, word & ~1); -+ -+#if RESERVE_MEM_REGION -+ release_mem_region(ICHX_FWH_REGION_START, ICHX_FWH_REGION_SIZE); -+#endif -+} -+ -+static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = { -+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, -+ PCI_ANY_ID, PCI_ANY_ID, }, -+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, -+ PCI_ANY_ID, PCI_ANY_ID, }, -+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, -+ PCI_ANY_ID, PCI_ANY_ID, }, -+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, -+ PCI_ANY_ID, PCI_ANY_ID, }, -+ { 0, }, -+}; -+ -+MODULE_DEVICE_TABLE(pci, ichxrom_pci_tbl); -+ -+#if 0 -+static struct pci_driver ichxrom_driver = { -+ .name = MOD_NAME, -+ .id_table = ichxrom_pci_tbl, -+ .probe = ichxrom_init_one, -+ .remove = ichxrom_remove_one, -+}; -+#endif -+ -+static struct pci_dev *mydev; -+int __init init_ichxrom(void) -+{ -+ struct pci_dev *pdev; -+ struct pci_device_id *id; -+ pdev = 0; -+ for(id = ichxrom_pci_tbl; id->vendor; id++) { -+ pdev = pci_find_device(id->vendor, id->device, 0); -+ if (pdev) { -+ break; -+ } -+ } -+ if (pdev) { -+ mydev = pdev; -+ return ichxrom_init_one(pdev, &ichxrom_pci_tbl[0]); -+ } -+ return -ENXIO; -+#if 0 -+ return pci_module_init(&ichxrom_driver); -+#endif -+} -+ -+static void __exit cleanup_ichxrom(void) -+{ -+ ichxrom_remove_one(mydev); -+} -+ -+module_init(init_ichxrom); -+module_exit(cleanup_ichxrom); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Eric Biederman "); -+MODULE_DESCRIPTION("MTD map driver for BIOS chips on the ICHX southbridge"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/impa7.c linux/drivers/mtd/maps/impa7.c ---- linux-mips-2.4.27/drivers/mtd/maps/impa7.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/maps/impa7.c 2004-11-19 10:25:11.920196600 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Handle mapping of the NOR flash on implementa A7 boards - * -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -37,75 +38,17 @@ - - static struct mtd_info *impa7_mtd[NUM_FLASHBANKS] = { 0 }; - --__u8 impa7_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 impa7_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 impa7_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void impa7_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void impa7_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void impa7_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void impa7_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void impa7_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - static struct map_info impa7_map[NUM_FLASHBANKS] = { - { -- name: "impA7 NOR Flash Bank #0", -- size: WINDOW_SIZE0, -- buswidth: BUSWIDTH, -- read8: impa7_read8, -- read16: impa7_read16, -- read32: impa7_read32, -- copy_from: impa7_copy_from, -- write8: impa7_write8, -- write16: impa7_write16, -- write32: impa7_write32, -- copy_to: impa7_copy_to -+ .name = "impA7 NOR Flash Bank #0", -+ .size = WINDOW_SIZE0, -+ .buswidth = BUSWIDTH, - }, - { -- name: "impA7 NOR Flash Bank #1", -- size: WINDOW_SIZE1, -- buswidth: BUSWIDTH, -- read8: impa7_read8, -- read16: impa7_read16, -- read32: impa7_read32, -- copy_from: impa7_copy_from, -- write8: impa7_write8, -- write16: impa7_write16, -- write32: impa7_write32, -- copy_to: impa7_copy_to -+ .name = "impA7 NOR Flash Bank #1", -+ .size = WINDOW_SIZE1, -+ .buswidth = BUSWIDTH, - }, - }; - -@@ -117,24 +60,18 @@ - static struct mtd_partition static_partitions[] = - { - { -- name: "FileSystem", -- size: 0x800000, -- offset: 0x00000000 -+ .name = "FileSystem", -+ .size = 0x800000, -+ .offset = 0x00000000 - }, - }; - --#define NB_OF(x) (sizeof (x) / sizeof (x[0])) -+static int mtd_parts_nb[NUM_FLASHBANKS]; -+static struct mtd_partition *mtd_parts[NUM_FLASHBANKS]; - --#ifdef CONFIG_MTD_CMDLINE_PARTS --int parse_cmdline_partitions(struct mtd_info *master, -- struct mtd_partition **pparts, -- const char *mtd_id); - #endif - --#endif -- --static int mtd_parts_nb = 0; --static struct mtd_partition *mtd_parts = 0; -+static const char *probes[] = { "cmdlinepart", NULL }; - - int __init init_impa7(void) - { -@@ -146,20 +83,21 @@ - { WINDOW_ADDR0, WINDOW_SIZE0 }, - { WINDOW_ADDR1, WINDOW_SIZE1 }, - }; -- char mtdid[10]; - int devicesfound = 0; - - for(i=0; imodule = THIS_MODULE; -- add_mtd_device(impa7_mtd[i]); -+ if (impa7_mtd[i]) { -+ impa7_mtd[i]->owner = THIS_MODULE; - devicesfound++; - #ifdef CONFIG_MTD_PARTITIONS --#ifdef CONFIG_MTD_CMDLINE_PARTS -- sprintf(mtdid, MTDID, i); -- mtd_parts_nb = parse_cmdline_partitions(impa7_mtd[i], -- &mtd_parts, -- mtdid); -- if (mtd_parts_nb > 0) -+ mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i], -+ probes, -+ &mtd_parts[i], -+ 0); -+ if (mtd_parts_nb[i] > 0) { - part_type = "command line"; --#endif -- if (mtd_parts_nb <= 0) -- { -- mtd_parts = static_partitions; -- mtd_parts_nb = NB_OF(static_partitions); -+ } else { -+ mtd_parts[i] = static_partitions; -+ mtd_parts_nb[i] = ARRAY_SIZE(static_partitions); - part_type = "static"; - } -- if (mtd_parts_nb <= 0) -- { -- printk(KERN_NOTICE MSG_PREFIX -- "no partition info available\n"); -- } -- else -- { -+ - printk(KERN_NOTICE MSG_PREFIX - "using %s partition definition\n", - part_type); - add_mtd_partitions(impa7_mtd[i], -- mtd_parts, mtd_parts_nb); -- } -+ mtd_parts[i], mtd_parts_nb[i]); -+#else -+ add_mtd_device(impa7_mtd[i]); -+ - #endif - } - else -- iounmap((void *)impa7_map[i].map_priv_1); -+ iounmap((void *)impa7_map[i].virt); - } - return devicesfound == 0 ? -ENXIO : 0; - } -@@ -211,17 +140,16 @@ - static void __exit cleanup_impa7(void) - { - int i; -- for (i=0; i -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+// board specific stuff - sorry, it should be in arch/arm/mach-*. -+#ifdef CONFIG_ARCH_INTEGRATOR -+ -+#define FLASH_BASE INTEGRATOR_FLASH_BASE -+#define FLASH_SIZE INTEGRATOR_FLASH_SIZE -+ -+#define FLASH_PART_SIZE 0x400000 -+ -+#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET) -+#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET) -+#define EBI_CSR1 (IO_ADDRESS(INTEGRATOR_EBI_BASE) + INTEGRATOR_EBI_CSR1_OFFSET) -+#define EBI_LOCK (IO_ADDRESS(INTEGRATOR_EBI_BASE) + INTEGRATOR_EBI_LOCK_OFFSET) -+ -+/* -+ * Initialise the flash access systems: -+ * - Disable VPP -+ * - Assert WP -+ * - Set write enable bit in EBI reg -+ */ -+static void armflash_flash_init(void) -+{ -+ unsigned int tmp; -+ -+ __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC); -+ -+ tmp = __raw_readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE; -+ __raw_writel(tmp, EBI_CSR1); -+ -+ if (!(__raw_readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) { -+ __raw_writel(0xa05f, EBI_LOCK); -+ __raw_writel(tmp, EBI_CSR1); -+ __raw_writel(0, EBI_LOCK); -+ } -+} -+ -+/* -+ * Shutdown the flash access systems: -+ * - Disable VPP -+ * - Assert WP -+ * - Clear write enable bit in EBI reg -+ */ -+static void armflash_flash_exit(void) -+{ -+ unsigned int tmp; -+ -+ __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC); -+ -+ /* -+ * Clear the write enable bit in system controller EBI register. -+ */ -+ tmp = __raw_readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE; -+ __raw_writel(tmp, EBI_CSR1); -+ -+ if (__raw_readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) { -+ __raw_writel(0xa05f, EBI_LOCK); -+ __raw_writel(tmp, EBI_CSR1); -+ __raw_writel(0, EBI_LOCK); -+ } -+} -+ -+static void armflash_flash_wp(int on) -+{ -+ unsigned int reg; -+ -+ if (on) -+ reg = SC_CTRLC; -+ else -+ reg = SC_CTRLS; -+ -+ __raw_writel(INTEGRATOR_SC_CTRL_nFLWP, reg); -+} -+ -+static void armflash_set_vpp(struct map_info *map, int on) -+{ -+ unsigned int reg; -+ -+ if (on) -+ reg = SC_CTRLS; -+ else -+ reg = SC_CTRLC; -+ -+ __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg); -+} -+#endif -+ -+#ifdef CONFIG_ARCH_P720T -+ -+#define FLASH_BASE (0x04000000) -+#define FLASH_SIZE (64*1024*1024) -+ -+#define FLASH_PART_SIZE (4*1024*1024) -+#define FLASH_BLOCK_SIZE (128*1024) -+ -+static void armflash_flash_init(void) -+{ -+} -+ -+static void armflash_flash_exit(void) -+{ -+} -+ -+static void armflash_flash_wp(int on) -+{ -+} -+ -+static void armflash_set_vpp(struct map_info *map, int on) -+{ -+} -+#endif -+ -+ -+static struct map_info armflash_map = -+{ -+ .name = "AFS", -+ .set_vpp = armflash_set_vpp, -+ .phys = FLASH_BASE, -+}; -+ -+static struct mtd_info *mtd; -+static struct mtd_partition *parts; -+static const char *probes[] = { "RedBoot", "afs", NULL }; -+ -+static int __init armflash_cfi_init(void *base, u_int size) -+{ -+ int ret; -+ -+ armflash_flash_init(); -+ armflash_flash_wp(1); -+ -+ /* -+ * look for CFI based flash parts fitted to this board -+ */ -+ armflash_map.size = size; -+ armflash_map.buswidth = 4; -+ armflash_map.virt = (unsigned long) base; -+ -+ simple_map_init(&armflash_map); -+ -+ /* -+ * Also, the CFI layer automatically works out what size -+ * of chips we have, and does the necessary identification -+ * for us automatically. -+ */ -+ mtd = do_map_probe("cfi_probe", &armflash_map); -+ if (!mtd) -+ return -ENXIO; -+ -+ mtd->owner = THIS_MODULE; -+ -+ ret = parse_mtd_partitions(mtd, probes, &parts, (void *)0); -+ if (ret > 0) { -+ ret = add_mtd_partitions(mtd, parts, ret); -+ if (ret) -+ printk(KERN_ERR "mtd partition registration " -+ "failed: %d\n", ret); -+ } -+ -+ /* -+ * If we got an error, free all resources. -+ */ -+ if (ret < 0) { -+ del_mtd_partitions(mtd); -+ map_destroy(mtd); -+ } -+ -+ return ret; -+} -+ -+static void armflash_cfi_exit(void) -+{ -+ if (mtd) { -+ del_mtd_partitions(mtd); -+ map_destroy(mtd); -+ } -+ if (parts) -+ kfree(parts); -+} -+ -+static int __init armflash_init(void) -+{ -+ int err = -EBUSY; -+ void *base; -+ -+ if (request_mem_region(FLASH_BASE, FLASH_SIZE, "flash") == NULL) -+ goto out; -+ -+ base = ioremap(FLASH_BASE, FLASH_SIZE); -+ err = -ENOMEM; -+ if (base == NULL) -+ goto release; -+ -+ err = armflash_cfi_init(base, FLASH_SIZE); -+ if (err) { -+ iounmap(base); -+release: -+ release_mem_region(FLASH_BASE, FLASH_SIZE); -+ } -+out: -+ return err; -+} -+ -+static void __exit armflash_exit(void) -+{ -+ armflash_cfi_exit(); -+ iounmap((void *)armflash_map.virt); -+ release_mem_region(FLASH_BASE, FLASH_SIZE); -+ armflash_flash_exit(); -+} -+ -+module_init(armflash_init); -+module_exit(armflash_exit); -+ -+MODULE_AUTHOR("ARM Ltd"); -+MODULE_DESCRIPTION("ARM Integrator CFI map driver"); -+MODULE_LICENSE("GPL"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/integrator-flash.c linux/drivers/mtd/maps/integrator-flash.c ---- linux-mips-2.4.27/drivers/mtd/maps/integrator-flash.c 2002-06-27 00:35:50.000000000 +0200 -+++ linux/drivers/mtd/maps/integrator-flash.c 2004-11-19 10:25:11.923196144 +0100 -@@ -1,8 +1,9 @@ - /*====================================================================== - -- drivers/mtd/maps/armflash.c: ARM Flash Layout/Partitioning -+ drivers/mtd/maps/integrator-flash.c: ARM Integrator flash map driver - - Copyright (C) 2000 ARM Limited -+ Copyright (C) 2003 Deep Blue Solutions 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 -@@ -21,7 +22,7 @@ - This is access code for flashes using ARM's flash partitioning - standards. - -- $Id$ -+ $Id$ - - ======================================================================*/ - -@@ -31,268 +32,181 @@ - #include - #include - #include -+#include - #include - - #include - #include - #include - -+#include - #include - #include - #include - --extern int parse_afs_partitions(struct mtd_info *, struct mtd_partition **); -- --// board specific stuff - sorry, it should be in arch/arm/mach-*. --#ifdef CONFIG_ARCH_INTEGRATOR -- --#define FLASH_BASE INTEGRATOR_FLASH_BASE --#define FLASH_SIZE INTEGRATOR_FLASH_SIZE -- --#define FLASH_PART_SIZE 0x400000 -- --#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET) --#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET) --#define EBI_CSR1 (IO_ADDRESS(INTEGRATOR_EBI_BASE) + INTEGRATOR_EBI_CSR1_OFFSET) --#define EBI_LOCK (IO_ADDRESS(INTEGRATOR_EBI_BASE) + INTEGRATOR_EBI_LOCK_OFFSET) -- --/* -- * Initialise the flash access systems: -- * - Disable VPP -- * - Assert WP -- * - Set write enable bit in EBI reg -- */ --static void armflash_flash_init(void) --{ -- unsigned int tmp; -- -- __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC); -- -- tmp = __raw_readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE; -- __raw_writel(tmp, EBI_CSR1); -- -- if (!(__raw_readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) { -- __raw_writel(0xa05f, EBI_LOCK); -- __raw_writel(tmp, EBI_CSR1); -- __raw_writel(0, EBI_LOCK); -- } --} -- --/* -- * Shutdown the flash access systems: -- * - Disable VPP -- * - Assert WP -- * - Clear write enable bit in EBI reg -- */ --static void armflash_flash_exit(void) --{ -- unsigned int tmp; -- -- __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC); -- -- /* -- * Clear the write enable bit in system controller EBI register. -- */ -- tmp = __raw_readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE; -- __raw_writel(tmp, EBI_CSR1); -- -- if (__raw_readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) { -- __raw_writel(0xa05f, EBI_LOCK); -- __raw_writel(tmp, EBI_CSR1); -- __raw_writel(0, EBI_LOCK); -- } --} -- --static void armflash_flash_wp(int on) --{ -- unsigned int reg; -- -- if (on) -- reg = SC_CTRLC; -- else -- reg = SC_CTRLS; -- -- __raw_writel(INTEGRATOR_SC_CTRL_nFLWP, reg); --} -- --static void armflash_set_vpp(struct map_info *map, int on) --{ -- unsigned int reg; -- -- if (on) -- reg = SC_CTRLS; -- else -- reg = SC_CTRLC; -- -- __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg); --} --#endif -- - #ifdef CONFIG_ARCH_P720T -- - #define FLASH_BASE (0x04000000) - #define FLASH_SIZE (64*1024*1024) -- --#define FLASH_PART_SIZE (4*1024*1024) --#define FLASH_BLOCK_SIZE (128*1024) -- --static void armflash_flash_init(void) --{ --} -- --static void armflash_flash_exit(void) --{ --} -- --static void armflash_flash_wp(int on) --{ --} -- --static void armflash_set_vpp(struct map_info *map, int on) --{ --} - #endif - --static __u8 armflash_read8(struct map_info *map, unsigned long ofs) --{ -- return readb(ofs + map->map_priv_2); --} -- --static __u16 armflash_read16(struct map_info *map, unsigned long ofs) --{ -- return readw(ofs + map->map_priv_2); --} -+struct armflash_info { -+ struct flash_platform_data *plat; -+ struct resource *res; -+ struct mtd_partition *parts; -+ struct mtd_info *mtd; -+ struct map_info map; -+}; - --static __u32 armflash_read32(struct map_info *map, unsigned long ofs) -+static void armflash_set_vpp(struct map_info *map, int on) - { -- return readl(ofs + map->map_priv_2); --} -+ struct armflash_info *info = container_of(map, struct armflash_info, map); - --static void armflash_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy(to, (void *) (from + map->map_priv_2), len); -+ if (info->plat && info->plat->set_vpp) -+ info->plat->set_vpp(on); - } - --static void armflash_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, adr + map->map_priv_2); --} -- --static void armflash_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, adr + map->map_priv_2); --} -+static const char *probes[] = { "RedBoot", "afs", NULL }; - --static void armflash_write32(struct map_info *map, __u32 d, unsigned long adr) -+static int armflash_probe(struct device *_dev) - { -- writel(d, adr + map->map_priv_2); --} -+ struct platform_device *dev = to_platform_device(_dev); -+ struct flash_platform_data *plat = dev->dev.platform_data; -+ struct resource *res = dev->resource; -+ unsigned int size = res->end - res->start + 1; -+ struct armflash_info *info; -+ int err; -+ void *base; - --static void armflash_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy((void *) (to + map->map_priv_2), from, len); --} -+ info = kmalloc(sizeof(struct armflash_info), GFP_KERNEL); -+ if (!info) { -+ err = -ENOMEM; -+ goto out; -+ } - --static struct map_info armflash_map = --{ -- name: "AFS", -- read8: armflash_read8, -- read16: armflash_read16, -- read32: armflash_read32, -- copy_from: armflash_copy_from, -- write8: armflash_write8, -- write16: armflash_write16, -- write32: armflash_write32, -- copy_to: armflash_copy_to, -- set_vpp: armflash_set_vpp, --}; -+ memset(info, 0, sizeof(struct armflash_info)); - --static struct mtd_info *mtd; --static struct mtd_partition *parts; -+ info->plat = plat; -+ if (plat && plat->init) { -+ err = plat->init(); -+ if (err) -+ goto no_resource; -+ } - --static int __init armflash_cfi_init(void *base, u_int size) --{ -- int ret; -+ info->res = request_mem_region(res->start, size, "armflash"); -+ if (!info->res) { -+ err = -EBUSY; -+ goto no_resource; -+ } - -- armflash_flash_init(); -- armflash_flash_wp(1); -+ base = ioremap(res->start, size); -+ if (!base) { -+ err = -ENOMEM; -+ goto no_mem; -+ } - - /* - * look for CFI based flash parts fitted to this board - */ -- armflash_map.size = size; -- armflash_map.buswidth = 4; -- armflash_map.map_priv_2 = (unsigned long) base; -+ info->map.size = size; -+ info->map.buswidth = plat->width; -+ info->map.phys = res->start; -+ info->map.virt = (unsigned long) base; -+ info->map.name = dev->dev.bus_id; -+ info->map.set_vpp = armflash_set_vpp; -+ -+ simple_map_init(&info->map); - - /* - * Also, the CFI layer automatically works out what size - * of chips we have, and does the necessary identification - * for us automatically. - */ -- mtd = do_map_probe("cfi_probe", &armflash_map); -- if (!mtd) -- return -ENXIO; -- -- mtd->module = THIS_MODULE; -- -- ret = parse_afs_partitions(mtd, &parts); -- if (ret > 0) { -- ret = add_mtd_partitions(mtd, parts, ret); -- if (ret) -- printk(KERN_ERR "mtd partition registration " -- "failed: %d\n", ret); -+ info->mtd = do_map_probe(plat->map_name, &info->map); -+ if (!info->mtd) { -+ err = -ENXIO; -+ goto no_device; - } - -+ info->mtd->owner = THIS_MODULE; -+ -+ err = parse_mtd_partitions(info->mtd, probes, &info->parts, 0); -+ if (err > 0) { -+ err = add_mtd_partitions(info->mtd, info->parts, err); -+ if (err) -+ printk(KERN_ERR -+ "mtd partition registration failed: %d\n", err); -+ } -+ -+ if (err == 0) -+ dev_set_drvdata(&dev->dev, info); -+ - /* - * If we got an error, free all resources. - */ -- if (ret < 0) { -- del_mtd_partitions(mtd); -- map_destroy(mtd); -+ if (err < 0) { -+ if (info->mtd) { -+ del_mtd_partitions(info->mtd); -+ map_destroy(info->mtd); - } -+ if (info->parts) -+ kfree(info->parts); - -- return ret; --} -- --static void armflash_cfi_exit(void) --{ -- if (mtd) { -- del_mtd_partitions(mtd); -- map_destroy(mtd); -+ no_device: -+ iounmap(base); -+ no_mem: -+ release_mem_region(res->start, size); -+ no_resource: -+ if (plat && plat->exit) -+ plat->exit(); -+ kfree(info); - } -- if (parts) -- kfree(parts); -+ out: -+ return err; - } - --static int __init armflash_init(void) -+static int armflash_remove(struct device *_dev) - { -- int err = -EBUSY; -- void *base; -+ struct platform_device *dev = to_platform_device(_dev); -+ struct armflash_info *info = dev_get_drvdata(&dev->dev); - -- if (request_mem_region(FLASH_BASE, FLASH_SIZE, "flash") == NULL) -- goto out; -+ dev_set_drvdata(&dev->dev, NULL); - -- base = ioremap(FLASH_BASE, FLASH_SIZE); -- err = -ENOMEM; -- if (base == NULL) -- goto release; -+ if (info) { -+ if (info->mtd) { -+ del_mtd_partitions(info->mtd); -+ map_destroy(info->mtd); -+ } -+ if (info->parts) -+ kfree(info->parts); - -- err = armflash_cfi_init(base, FLASH_SIZE); -- if (err) { -- iounmap(base); --release: -- release_mem_region(FLASH_BASE, FLASH_SIZE); -+ iounmap((void *)info->map.virt); -+ release_resource(info->res); -+ kfree(info->res); -+ -+ if (info->plat && info->plat->exit) -+ info->plat->exit(); -+ -+ kfree(info); - } --out: -- return err; -+ -+ return 0; -+} -+ -+static struct device_driver armflash_driver = { -+ .name = "armflash", -+ .bus = &platform_bus_type, -+ .probe = armflash_probe, -+ .remove = armflash_remove, -+}; -+ -+static int __init armflash_init(void) -+{ -+ return driver_register(&armflash_driver); - } - - static void __exit armflash_exit(void) - { -- armflash_cfi_exit(); -- iounmap((void *)armflash_map.map_priv_2); -- release_mem_region(FLASH_BASE, FLASH_SIZE); -- armflash_flash_exit(); -+ driver_unregister(&armflash_driver); - } - - module_init(armflash_init); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/iq80310.c linux/drivers/mtd/maps/iq80310.c ---- linux-mips-2.4.27/drivers/mtd/maps/iq80310.c 2002-06-27 00:35:50.000000000 +0200 -+++ linux/drivers/mtd/maps/iq80310.c 2004-11-19 10:25:11.924195992 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Mapping for the Intel XScale IQ80310 evaluation board - * -@@ -14,6 +14,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -26,127 +28,72 @@ - - static struct mtd_info *mymtd; - --static __u8 iq80310_read8(struct map_info *map, unsigned long ofs) --{ -- return *(__u8 *)(map->map_priv_1 + ofs); --} -- --static __u16 iq80310_read16(struct map_info *map, unsigned long ofs) --{ -- return *(__u16 *)(map->map_priv_1 + ofs); --} -- --static __u32 iq80310_read32(struct map_info *map, unsigned long ofs) --{ -- return *(__u32 *)(map->map_priv_1 + ofs); --} -- --static void iq80310_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy(to, (void *)(map->map_priv_1 + from), len); --} -- --static void iq80310_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- *(__u8 *)(map->map_priv_1 + adr) = d; --} -- --static void iq80310_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- *(__u16 *)(map->map_priv_1 + adr) = d; --} -- --static void iq80310_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- *(__u32 *)(map->map_priv_1 + adr) = d; --} -- --static void iq80310_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy((void *)(map->map_priv_1 + to), from, len); --} -- - static struct map_info iq80310_map = { -- name: "IQ80310 flash", -- size: WINDOW_SIZE, -- buswidth: BUSWIDTH, -- read8: iq80310_read8, -- read16: iq80310_read16, -- read32: iq80310_read32, -- copy_from: iq80310_copy_from, -- write8: iq80310_write8, -- write16: iq80310_write16, -- write32: iq80310_write32, -- copy_to: iq80310_copy_to -+ .name = "IQ80310 flash", -+ .size = WINDOW_SIZE, -+ .buswidth = BUSWIDTH, -+ .phys = WINDOW_ADDR - }; - - static struct mtd_partition iq80310_partitions[4] = { - { -- name: "Firmware", -- size: 0x00080000, -- offset: 0, -- mask_flags: MTD_WRITEABLE /* force read-only */ -+ .name = "Firmware", -+ .size = 0x00080000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ - },{ -- name: "Kernel", -- size: 0x000a0000, -- offset: 0x00080000, -+ .name = "Kernel", -+ .size = 0x000a0000, -+ .offset = 0x00080000, - },{ -- name: "Filesystem", -- size: 0x00600000, -- offset: 0x00120000 -+ .name = "Filesystem", -+ .size = 0x00600000, -+ .offset = 0x00120000 - },{ -- name: "RedBoot", -- size: 0x000e0000, -- offset: 0x00720000, -- mask_flags: MTD_WRITEABLE -+ .name = "RedBoot", -+ .size = 0x000e0000, -+ .offset = 0x00720000, -+ .mask_flags = MTD_WRITEABLE - } - }; - --#define NB_OF(x) (sizeof(x)/sizeof(x[0])) -- - static struct mtd_info *mymtd; - static struct mtd_partition *parsed_parts; -- --extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts); -+static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; - - static int __init init_iq80310(void) - { - struct mtd_partition *parts; - int nb_parts = 0; - int parsed_nr_parts = 0; -- char *part_type = "static"; -+ int ret; - -- iq80310_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); -- if (!iq80310_map.map_priv_1) { -+ iq80310_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); -+ if (!iq80310_map.virt) { - printk("Failed to ioremap\n"); - return -EIO; - } -+ simple_map_init(&iq80310_map); -+ - mymtd = do_map_probe("cfi_probe", &iq80310_map); - if (!mymtd) { -- iounmap((void *)iq80310_map.map_priv_1); -+ iounmap((void *)iq80310_map.virt); - return -ENXIO; - } -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - --#ifdef CONFIG_MTD_REDBOOT_PARTS -- if (parsed_nr_parts == 0) { -- int ret = parse_redboot_partitions(mymtd, &parsed_parts); -+ ret = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0); - -- if (ret > 0) { -- part_type = "RedBoot"; -+ if (ret > 0) - parsed_nr_parts = ret; -- } -- } --#endif - - if (parsed_nr_parts > 0) { - parts = parsed_parts; - nb_parts = parsed_nr_parts; - } else { - parts = iq80310_partitions; -- nb_parts = NB_OF(iq80310_partitions); -+ nb_parts = ARRAY_SIZE(iq80310_partitions); - } -- printk(KERN_NOTICE "Using %s partition definition\n", part_type); - add_mtd_partitions(mymtd, parts, nb_parts); - return 0; - } -@@ -159,8 +106,8 @@ - if (parsed_parts) - kfree(parsed_parts); - } -- if (iq80310_map.map_priv_1) -- iounmap((void *)iq80310_map.map_priv_1); -+ if (iq80310_map.virt) -+ iounmap((void *)iq80310_map.virt); - } - - module_init(init_iq80310); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/ixp425.c linux/drivers/mtd/maps/ixp425.c ---- linux-mips-2.4.27/drivers/mtd/maps/ixp425.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/ixp425.c 2004-11-19 10:25:11.925195840 +0100 -@@ -0,0 +1,220 @@ -+/* -+ * $Id$ -+ * -+ * drivers/mtd/maps/ixp425.c -+ * -+ * MTD Map file for IXP425 based systems. Please do not make per-board -+ * map driver as the code will be 90% identical. For now just add -+ * if(machine_is_XXX()) checks to the code. I'll clean this stuff to -+ * use platform_data in the the future so we can get rid of that too. -+ * -+ * Original Author: Intel Corporation -+ * Maintainer: Deepak Saxena -+ * -+ * Copyright (C) 2002 Intel Corporation -+ * Copyright (C) 2003 MontaVista Software, Inc. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define WINDOW_ADDR 0x50000000 -+#define BUSWIDTH 2 -+ -+#ifndef __ARMEB__ -+#define BYTE0(h) ((h) & 0xFF) -+#define BYTE1(h) (((h) >> 8) & 0xFF) -+#else -+#define BYTE0(h) (((h) >> 8) & 0xFF) -+#define BYTE1(h) ((h) & 0xFF) -+#endif -+ -+static __u16 -+ixp425_read16(struct map_info *map, unsigned long ofs) -+{ -+ return *(__u16 *) (map->map_priv_1 + ofs); -+} -+ -+/* -+ * The IXP425 expansion bus only allows 16-bit wide acceses -+ * when attached to a 16-bit wide device (such as the 28F128J3A), -+ * so we can't just memcpy_fromio(). -+ */ -+static void -+ixp425_copy_from(struct map_info *map, void *to, -+ unsigned long from, ssize_t len) -+{ -+ int i; -+ u8 *dest = (u8 *) to; -+ u16 *src = (u16 *) (map->map_priv_1 + from); -+ u16 data; -+ -+ for (i = 0; i < (len / 2); i++) { -+ data = src[i]; -+ dest[i * 2] = BYTE0(data); -+ dest[i * 2 + 1] = BYTE1(data); -+ } -+ -+ if (len & 1) -+ dest[len - 1] = BYTE0(src[i]); -+} -+ -+static void -+ixp425_write16(struct map_info *map, __u16 d, unsigned long adr) -+{ -+ *(__u16 *) (map->map_priv_1 + adr) = d; -+} -+ -+static struct map_info ixp425_map = { -+ .name = "IXP425 Flash", -+ .buswidth = BUSWIDTH, -+ .read16 = ixp425_read16, -+ .copy_from = ixp425_copy_from, -+ .write16 = ixp425_write16, -+}; -+ -+/* -+ * Put flash back in read mode so RedBoot can boot properly. -+ */ -+int ixp425_mtd_reboot(struct notifier_block *n, unsigned long code, void *p) -+{ -+ if (code != SYS_RESTART) -+ return NOTIFY_DONE; -+ -+ ixp425_write16(&ixp425_map, 0xff, 0x55 * 0x2); -+ return NOTIFY_DONE; -+} -+ -+static struct notifier_block ixp425_mtd_notifier = { -+ notifier_call:ixp425_mtd_reboot, -+ next:NULL, -+ priority:0 -+}; -+ -+static struct mtd_partition *parsed_parts; -+static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; -+ -+static struct mtd_partition ixp425_partitions[] = { -+ { -+ .name = "image", -+ .offset = 0x00040000, -+ .size = 0x00400000, -+ }, { -+ .name = "user", -+ .offset = 0x00440000, -+ .size = MTDPART_SIZ_FULL -+ } -+}; -+ -+#define NB_OF(x) (sizeof(x)/sizeof(x[0])) -+ -+static struct mtd_info *ixp425_mtd; -+static struct resource *mtd_resource; -+ -+static void -+ixp425_exit(void) -+{ -+ if (ixp425_mtd) { -+ del_mtd_partitions(ixp425_mtd); -+ map_destroy(ixp425_mtd); -+ } -+ if (ixp425_map.map_priv_1) -+ iounmap((void *) ixp425_map.map_priv_1); -+ if (mtd_resource) -+ release_mem_region(WINDOW_ADDR, ixp425_map.size); -+ -+ if (parsed_parts) -+ kfree(parsed_parts); -+ -+ unregister_reboot_notifier(&ixp425_mtd_notifier); -+ -+ /* Disable flash write */ -+ *IXP425_EXP_CS0 &= ~IXP425_FLASH_WRITABLE; -+ -+ if(machine_is_adi_coyote()) -+ *IXP425_EXP_CS1 &= ~IXP425_FLASH_WRITABLE; -+} -+ -+static int __init -+ixp425_init(void) -+{ -+ int res = -1, npart; -+ -+ /* Enable flash write */ -+ *IXP425_EXP_CS0 |= IXP425_FLASH_WRITABLE; -+ -+ /* -+ * Coyote requires CS1 write to be enabled and has 32MB flash. -+ * This will move to the platform init code in 2.6 -+ */ -+ if(machine_is_adi_coyote()) { -+ *IXP425_EXP_CS1 |= IXP425_FLASH_WRITABLE; -+ ixp425_map.size = 0x02000000; -+ } else -+ ixp425_map.size = 0x01000000; -+ -+ ixp425_map.map_priv_1 = 0; -+ mtd_resource = -+ request_mem_region(WINDOW_ADDR, ixp425_map.size, "IXP425 Flash"); -+ if (!mtd_resource) { -+ printk(KERN_ERR -+ "ixp425 flash: Could not request mem region.\n"); -+ res = -ENOMEM; -+ goto Error; -+ } -+ -+ ixp425_map.map_priv_1 = -+ (unsigned long) ioremap(WINDOW_ADDR, ixp425_map.size); -+ if (!ixp425_map.map_priv_1) { -+ printk("ixp425 Flash: Failed to map IO region. (ioremap)\n"); -+ res = -EIO; -+ goto Error; -+ } -+ -+ ixp425_mtd = do_map_probe("cfi_probe", &ixp425_map); -+ if (!ixp425_mtd) { -+ res = -ENXIO; -+ goto Error; -+ } -+ ixp425_mtd->owner = THIS_MODULE; -+ -+ /* Try to parse RedBoot partitions */ -+ npart = parse_mtd_partitions(ixp425_mtd, probes, &parsed_parts, 0); -+ if (npart > 0) -+ res = add_mtd_partitions(ixp425_mtd, parsed_parts, npart); -+ else { -+ printk("IXP425 Flash: Using static MTD partitions.\n"); -+ res = add_mtd_partitions(ixp425_mtd, ixp425_partitions, -+ NB_OF(ixp425_partitions)); -+ } -+ -+ if (res) -+ goto Error; -+ -+ register_reboot_notifier(&ixp425_mtd_notifier); -+ -+ return res; -+ -+Error: -+ ixp425_exit(); -+ return res; -+} -+ -+module_init(ixp425_init); -+module_exit(ixp425_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("MTD map driver for ixp425 evaluation board"); -+MODULE_AUTHOR("Deepak Saxena"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/l440gx.c linux/drivers/mtd/maps/l440gx.c ---- linux-mips-2.4.27/drivers/mtd/maps/l440gx.c 2002-06-27 00:35:50.000000000 +0200 -+++ linux/drivers/mtd/maps/l440gx.c 2004-11-19 10:25:11.927195536 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * BIOS Flash chip on Intel 440GX board. - * -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -27,48 +28,6 @@ - - static struct mtd_info *mymtd; - --__u8 l440gx_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 l440gx_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 l440gx_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void l440gx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void l440gx_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void l440gx_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void l440gx_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void l440gx_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - /* Is this really the vpp port? */ - void l440gx_set_vpp(struct map_info *map, int vpp) -@@ -85,22 +44,15 @@ - } - - struct map_info l440gx_map = { -- name: "L440GX BIOS", -- size: WINDOW_SIZE, -- buswidth: BUSWIDTH, -- read8: l440gx_read8, -- read16: l440gx_read16, -- read32: l440gx_read32, -- copy_from: l440gx_copy_from, -- write8: l440gx_write8, -- write16: l440gx_write16, -- write32: l440gx_write32, -- copy_to: l440gx_copy_to, -+ .name = "L440GX BIOS", -+ .size = WINDOW_SIZE, -+ .buswidth = BUSWIDTH, -+ .phys = WINDOW_ADDR, - #if 0 - /* FIXME verify that this is the - * appripriate code for vpp enable/disable - */ -- set_vpp: l440gx_set_vpp -+ .set_vpp = l440gx_set_vpp - #endif - }; - -@@ -113,7 +65,6 @@ - dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_0, NULL); - -- - pm_dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_3, NULL); - -@@ -122,15 +73,14 @@ - return -ENODEV; - } - -+ l440gx_map.virt = (unsigned long)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE); - -- l440gx_map.map_priv_1 = (unsigned long)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE); -- -- if (!l440gx_map.map_priv_1) { -+ if (!l440gx_map.virt) { - printk(KERN_WARNING "Failed to ioremap L440GX flash region\n"); - return -ENOMEM; - } -- -- printk(KERN_NOTICE "window_addr = 0x%08lx\n", (unsigned long)l440gx_map.map_priv_1); -+ simple_map_init(&l440gx_map); -+ printk(KERN_NOTICE "window_addr = 0x%08lx\n", (unsigned long)l440gx_map.virt); - - /* Setup the pm iobase resource - * This code should move into some kind of generic bridge -@@ -153,7 +103,7 @@ - /* Allocate the resource region */ - if (pci_assign_resource(pm_dev, PIIXE_IOBASE_RESOURCE) != 0) { - printk(KERN_WARNING "Could not allocate pm iobase resource\n"); -- iounmap((void *)l440gx_map.map_priv_1); -+ iounmap((void *)l440gx_map.virt); - return -ENXIO; - } - } -@@ -181,13 +131,13 @@ - mymtd = do_map_probe("map_rom", &l440gx_map); - } - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - add_mtd_device(mymtd); - return 0; - } - -- iounmap((void *)l440gx_map.map_priv_1); -+ iounmap((void *)l440gx_map.virt); - return -ENXIO; - } - -@@ -196,7 +146,7 @@ - del_mtd_device(mymtd); - map_destroy(mymtd); - -- iounmap((void *)l440gx_map.map_priv_1); -+ iounmap((void *)l440gx_map.virt); - } - - module_init(init_l440gx); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/lasat.c linux/drivers/mtd/maps/lasat.c ---- linux-mips-2.4.27/drivers/mtd/maps/lasat.c 2003-08-18 04:59:02.000000000 +0200 -+++ linux/drivers/mtd/maps/lasat.c 2004-11-19 10:25:11.928195384 +0100 -@@ -1,11 +1,20 @@ - /* -- * Flash device on lasat 100 and 200 boards -+ * Flash device on Lasat 100 and 200 boards -+ * -+ * (C) 2002 Brian Murphy -+ * -+ * 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. -+ * -+ * $Id$ - * - */ - - #include - #include - #include -+#include - #include - #include - #include -@@ -13,123 +22,80 @@ - #include - #include - --static struct mtd_info *mymtd; -- --static __u8 sp_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --static __u16 sp_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --static __u32 sp_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --static void sp_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -+static struct mtd_info *lasat_mtd; - --static void sp_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --static void sp_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --static void sp_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -+static struct mtd_partition partition_info[LASAT_MTD_LAST]; -+static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Filesystem", "Config"}; - --static void sp_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -+static void lasat_set_vpp(struct map_info *map, int vpp) - { -- memcpy_toio(map->map_priv_1 + to, from, len); -+ if (vpp) -+ *lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit; -+ else -+ *lasat_misc->flash_wp_reg &= ~(1 << lasat_misc->flash_wp_bit); - } - --static struct map_info sp_map = { -- name: "SP flash", -- buswidth: 4, -- read8: sp_read8, -- read16: sp_read16, -- read32: sp_read32, -- copy_from: sp_copy_from, -- write8: sp_write8, -- write16: sp_write16, -- write32: sp_write32, -- copy_to: sp_copy_to -+static struct map_info lasat_map = { -+ .name = "LASAT flash", -+ .buswidth = 4, -+ .set_vpp = lasat_set_vpp - }; - --static struct mtd_partition partition_info[LASAT_MTD_LAST]; --static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Config", "Filesystem"}; -- --static int __init init_sp(void) -+static int __init init_lasat(void) - { - int i; -- int nparts = 0; -- /* this does not play well with the old flash code which -- * protects and uprotects the flash when necessary */ -+ /* since we use AMD chips and set_vpp is not implimented -+ * for these (yet) we still have to permanently enable flash write */ - printk(KERN_NOTICE "Unprotecting flash\n"); -- *lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit; -+ ENABLE_VPP((&lasat_map)); - -- sp_map.map_priv_1 = ioremap_nocache( -- lasat_flash_partition_start(LASAT_MTD_BOOTLOADER), -- lasat_board_info.li_flash_size); -- sp_map.size = lasat_board_info.li_flash_size; -+ lasat_map.phys = lasat_flash_partition_start(LASAT_MTD_BOOTLOADER); -+ lasat_map.virt = (unsigned long)ioremap_nocache( -+ lasat_map.phys, lasat_board_info.li_flash_size); -+ lasat_map.size = lasat_board_info.li_flash_size; - -- printk(KERN_NOTICE "sp flash device: %lx at %lx\n", -- sp_map.size, sp_map.map_priv_1); -+ simple_map_init(&lasat_map); - - for (i=0; i < LASAT_MTD_LAST; i++) - partition_info[i].name = lasat_mtd_partnames[i]; - -- mymtd = do_map_probe("cfi_probe", &sp_map); -- if (mymtd) { -+ lasat_mtd = do_map_probe("cfi_probe", &lasat_map); -+ -+ if (!lasat_mtd) -+ lasat_mtd = do_map_probe("jedec_probe", &lasat_map); -+ -+ if (lasat_mtd) { - u32 size, offset = 0; - -- mymtd->module = THIS_MODULE; -+ lasat_mtd->owner = THIS_MODULE; - - for (i=0; i < LASAT_MTD_LAST; i++) { - size = lasat_flash_partition_size(i); -- if (size != 0) { -- nparts++; - partition_info[i].size = size; - partition_info[i].offset = offset; - offset += size; - } -- } - -- add_mtd_partitions( mymtd, partition_info, nparts ); -+ add_mtd_partitions( lasat_mtd, partition_info, LASAT_MTD_LAST ); - return 0; - } - - return -ENXIO; - } - --static void __exit cleanup_sp(void) -+static void __exit cleanup_lasat(void) - { -- if (mymtd) { -- del_mtd_partitions(mymtd); -- map_destroy(mymtd); -+ if (lasat_mtd) { -+ del_mtd_partitions(lasat_mtd); -+ map_destroy(lasat_mtd); - } -- if (sp_map.map_priv_1) { -- sp_map.map_priv_1 = 0; -+ if (lasat_map.virt) { -+ lasat_map.virt = 0; - } - } - --module_init(init_sp); --module_exit(cleanup_sp); -+module_init(init_lasat); -+module_exit(cleanup_lasat); - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Brian Murphy "); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/lubbock-flash.c linux/drivers/mtd/maps/lubbock-flash.c ---- linux-mips-2.4.27/drivers/mtd/maps/lubbock-flash.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/lubbock-flash.c 2004-11-19 10:25:11.930195080 +0100 -@@ -0,0 +1,151 @@ -+/* -+ * $Id$ -+ * -+ * Map driver for the Lubbock developer platform. -+ * -+ * Author: Nicolas Pitre -+ * Copyright: (C) 2001 MontaVista Software Inc. -+ * -+ * 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 -+ -+ -+#define ROM_ADDR 0x00000000 -+#define FLASH_ADDR 0x04000000 -+ -+#define WINDOW_SIZE 64*1024*1024 -+ -+static struct map_info lubbock_maps[2] = { { -+ .size = WINDOW_SIZE, -+ .phys = 0x00000000, -+}, { -+ .size = WINDOW_SIZE, -+ .phys = 0x04000000, -+} }; -+ -+static struct mtd_partition lubbock_partitions[] = { -+ { -+ .name = "Bootloader", -+ .size = 0x00040000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ -+ },{ -+ .name = "Kernel", -+ .size = 0x00100000, -+ .offset = 0x00040000, -+ },{ -+ .name = "Filesystem", -+ .size = MTDPART_SIZ_FULL, -+ .offset = 0x00140000 -+ } -+}; -+ -+static struct mtd_info *mymtds[2]; -+static struct mtd_partition *parsed_parts[2]; -+static int nr_parsed_parts[2]; -+ -+static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; -+ -+static int __init init_lubbock(void) -+{ -+ int flashboot = (CONF_SWITCHES & 1); -+ int ret = 0, i; -+ -+ lubbock_maps[0].buswidth = lubbock_maps[1].buswidth = -+ (BOOT_DEF & 1) ? 2 : 4; -+ -+ /* Compensate for the nROMBT switch which swaps the flash banks */ -+ printk(KERN_NOTICE "Lubbock configured to boot from %s (bank %d)\n", -+ flashboot?"Flash":"ROM", flashboot); -+ -+ lubbock_maps[flashboot^1].name = "Lubbock Application Flash"; -+ lubbock_maps[flashboot].name = "Lubbock Boot ROM"; -+ -+ for (i = 0; i < 2; i++) { -+ lubbock_maps[i].virt = (unsigned long)__ioremap(lubbock_maps[i].phys, WINDOW_SIZE, 0); -+ if (!lubbock_maps[i].virt) { -+ printk(KERN_WARNING "Failed to ioremap %s\n", lubbock_maps[i].name); -+ if (!ret) -+ ret = -ENOMEM; -+ continue; -+ } -+ simple_map_init(&lubbock_maps[i]); -+ -+ printk(KERN_NOTICE "Probing %s at physical address 0x%08lx (%d-bit buswidth)\n", -+ lubbock_maps[i].name, lubbock_maps[i].phys, -+ lubbock_maps[i].buswidth * 8); -+ -+ mymtds[i] = do_map_probe("cfi_probe", &lubbock_maps[i]); -+ -+ if (!mymtds[i]) { -+ iounmap((void *)lubbock_maps[i].virt); -+ if (!ret) -+ ret = -EIO; -+ continue; -+ } -+ mymtds[i]->owner = THIS_MODULE; -+ -+ int ret = parse_mtd_partitions(mymtds[i], probes, -+ &parsed_parts[i], 0); -+ -+ if (ret > 0) -+ nr_parsed_parts[i] = ret; -+ } -+ -+ if (!mymtds[0] && !mymtds[1]) -+ return ret; -+ -+ for (i = 0; i < 2; i++) { -+ if (!mymtds[i]) { -+ printk(KERN_WARNING "%s is absent. Skipping\n", lubbock_maps[i].name); -+ } else if (nr_parsed_parts[i]) { -+ add_mtd_partitions(mymtds[i], parsed_parts[i], nr_parsed_parts[i]); -+ } else if (!i) { -+ printk("Using static partitions on %s\n", lubbock_maps[i].name); -+ add_mtd_partitions(mymtds[i], lubbock_partitions, ARRAY_SIZE(lubbock_partitions)); -+ } else { -+ printk("Registering %s as whole device\n", lubbock_maps[i].name); -+ add_mtd_device(mymtds[i]); -+ } -+ } -+ return 0; -+} -+ -+static void __exit cleanup_lubbock(void) -+{ -+ int i; -+ for (i = 0; i < 2; i++) { -+ if (!mymtds[i]) -+ continue; -+ -+ if (nr_parsed_parts[i] || !i) -+ del_mtd_partitions(mymtds[i]); -+ else -+ del_mtd_device(mymtds[i]); -+ -+ map_destroy(mymtds[i]); -+ iounmap((void *)lubbock_maps[i].virt); -+ -+ if (parsed_parts[i]) -+ kfree(parsed_parts[i]); -+ } -+} -+ -+module_init(init_lubbock); -+module_exit(cleanup_lubbock); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Nicolas Pitre "); -+MODULE_DESCRIPTION("MTD map driver for Intel Lubbock"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/map_funcs.c linux/drivers/mtd/maps/map_funcs.c ---- linux-mips-2.4.27/drivers/mtd/maps/map_funcs.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/map_funcs.c 2004-11-19 10:25:11.931194928 +0100 -@@ -0,0 +1,96 @@ -+/* -+ * $Id$ -+ * -+ * Out-of-line map I/O functions for simple maps when CONFIG_COMPLEX_MAPPINGS -+ * is enabled. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+static u8 simple_map_read8(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readb(map->virt + ofs); -+} -+ -+static u16 simple_map_read16(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readw(map->virt + ofs); -+} -+ -+static u32 simple_map_read32(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readl(map->virt + ofs); -+} -+ -+static u64 simple_map_read64(struct map_info *map, unsigned long ofs) -+{ -+#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */ -+ BUG(); -+ return 0; -+#else -+ return __raw_readll(map->virt + ofs); -+#endif -+} -+ -+static void simple_map_write8(struct map_info *map, u8 datum, unsigned long ofs) -+{ -+ __raw_writeb(datum, map->virt + ofs); -+ mb(); -+} -+ -+static void simple_map_write16(struct map_info *map, u16 datum, unsigned long ofs) -+{ -+ __raw_writew(datum, map->virt + ofs); -+ mb(); -+} -+ -+static void simple_map_write32(struct map_info *map, u32 datum, unsigned long ofs) -+{ -+ __raw_writel(datum, map->virt + ofs); -+ mb(); -+} -+ -+static void simple_map_write64(struct map_info *map, u64 datum, unsigned long ofs) -+{ -+#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */ -+ BUG(); -+#else -+ __raw_writell(datum, map->virt + ofs); -+ mb(); -+#endif /* CFI_B8 */ -+} -+ -+static void simple_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -+{ -+ memcpy_fromio(to, map->virt + from, len); -+} -+ -+static void simple_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -+{ -+ memcpy_toio(map->virt + to, from, len); -+} -+ -+void simple_map_init(struct map_info *map) -+{ -+ map->read8 = simple_map_read8; -+ map->read16 = simple_map_read16; -+ map->read32 = simple_map_read32; -+ map->read64 = simple_map_read64; -+ map->write8 = simple_map_write8; -+ map->write16 = simple_map_write16; -+ map->write32 = simple_map_write32; -+ map->write64 = simple_map_write64; -+ map->copy_from = simple_map_copy_from; -+ map->copy_to = simple_map_copy_to; -+} -+ -+EXPORT_SYMBOL(simple_map_init); -+ -+MODULE_LICENSE("GPL"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/mbx860.c linux/drivers/mtd/maps/mbx860.c ---- linux-mips-2.4.27/drivers/mtd/maps/mbx860.c 2002-06-27 00:35:50.000000000 +0200 -+++ linux/drivers/mtd/maps/mbx860.c 2004-11-19 10:25:11.933194624 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Handle mapping of the flash on MBX860 boards - * -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -36,91 +37,46 @@ - * single flash device into. If the size if zero we use up to the end of the - * device. */ - static struct mtd_partition partition_info[]={ -- { name: "MBX flash BOOT partition", -- offset: 0, -- size: BOOT_PARTITION_SIZE_KiB*1024 }, -- { name: "MBX flash DATA partition", -- offset: BOOT_PARTITION_SIZE_KiB*1024, -- size: (KERNEL_PARTITION_SIZE_KiB)*1024 }, -- { name: "MBX flash APPLICATION partition", -- offset: (BOOT_PARTITION_SIZE_KiB+KERNEL_PARTITION_SIZE_KiB)*1024 } -+ { .name = "MBX flash BOOT partition", -+ .offset = 0, -+ .size = BOOT_PARTITION_SIZE_KiB*1024 }, -+ { .name = "MBX flash DATA partition", -+ .offset = BOOT_PARTITION_SIZE_KiB*1024, -+ .size = (KERNEL_PARTITION_SIZE_KiB)*1024 }, -+ { .name = "MBX flash APPLICATION partition", -+ .offset = (BOOT_PARTITION_SIZE_KiB+KERNEL_PARTITION_SIZE_KiB)*1024 } - }; - - - static struct mtd_info *mymtd; - --__u8 mbx_read8(struct map_info *map, unsigned long ofs) --{ -- return readb(map->map_priv_1 + ofs); --} -- --__u16 mbx_read16(struct map_info *map, unsigned long ofs) --{ -- return readw(map->map_priv_1 + ofs); --} -- --__u32 mbx_read32(struct map_info *map, unsigned long ofs) --{ -- return readl(map->map_priv_1 + ofs); --} -- --void mbx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); --} -- --void mbx_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, map->map_priv_1 + adr); --} -- --void mbx_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, map->map_priv_1 + adr); --} -- --void mbx_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- writel(d, map->map_priv_1 + adr); --} -- --void mbx_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio((void *)(map->map_priv_1 + to), from, len); --} -- - struct map_info mbx_map = { -- name: "MBX flash", -- size: WINDOW_SIZE, -- buswidth: 4, -- read8: mbx_read8, -- read16: mbx_read16, -- read32: mbx_read32, -- copy_from: mbx_copy_from, -- write8: mbx_write8, -- write16: mbx_write16, -- write32: mbx_write32, -- copy_to: mbx_copy_to -+ .name = "MBX flash", -+ .size = WINDOW_SIZE, -+ .phys = WINDOW_ADDR, -+ .buswidth = 4, - }; - - int __init init_mbx(void) - { -- printk(KERN_NOTICE "Motorola MBX flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR); -- mbx_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); -+ printk(KERN_NOTICE "Motorola MBX flash device: 0x%x at 0x%x\n", WINDOW_SIZE*4, WINDOW_ADDR); -+ mbx_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); - -- if (!mbx_map.map_priv_1) { -+ if (!mbx_map.virt) { - printk("Failed to ioremap\n"); - return -EIO; - } -+ simple_map_init(&mbx_map); -+ - mymtd = do_map_probe("jedec_probe", &mbx_map); - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - add_mtd_device(mymtd); - add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS); - return 0; - } - -- iounmap((void *)mbx_map.map_priv_1); -+ iounmap((void *)mbx_map.virt); - return -ENXIO; - } - -@@ -130,9 +86,9 @@ - del_mtd_device(mymtd); - map_destroy(mymtd); - } -- if (mbx_map.map_priv_1) { -- iounmap((void *)mbx_map.map_priv_1); -- mbx_map.map_priv_1 = 0; -+ if (mbx_map.virt) { -+ iounmap((void *)mbx_map.virt); -+ mbx_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/mpc1211.c linux/drivers/mtd/maps/mpc1211.c ---- linux-mips-2.4.27/drivers/mtd/maps/mpc1211.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/mpc1211.c 2004-11-19 10:25:11.934194472 +0100 -@@ -0,0 +1,79 @@ -+/* -+ * Flash on MPC-1211 -+ * -+ * (C) 2002 Interface, Saito.K & Jeanne -+ * -+ * GPL'd -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static struct mtd_info *flash_mtd; -+static struct mtd_partition *parsed_parts; -+ -+struct map_info mpc1211_flash_map = { -+ .name = "MPC-1211 FLASH", -+ .size = 0x80000, -+ .buswidth = 1, -+}; -+ -+static struct mtd_partition mpc1211_partitions[] = { -+ { -+ .name = "IPL & ETH-BOOT", -+ .offset = 0x00000000, -+ .size = 0x10000, -+ }, -+ { -+ .name = "Flash FS", -+ .offset = 0x00010000, -+ .size = MTDPART_SIZ_FULL, -+ } -+}; -+ -+static int __init init_mpc1211_maps(void) -+{ -+ int nr_parts; -+ -+ mpc1211_flash_map.phys = 0; -+ mpc1211_flash_map.virt = P2SEGADDR(0); -+ -+ simple_map_init(&mpc1211_flash_map); -+ -+ printk(KERN_NOTICE "Probing for flash chips at 0x00000000:\n"); -+ flash_mtd = do_map_probe("jedec_probe", &mpc1211_flash_map); -+ if (!flash_mtd) { -+ printk(KERN_NOTICE "Flash chips not detected at either possible location.\n"); -+ return -ENXIO; -+ } -+ printk(KERN_NOTICE "MPC-1211: Flash at 0x%08lx\n", mpc1211_flash_map.virt & 0x1fffffff); -+ flash_mtd->module = THIS_MODULE; -+ -+ parsed_parts = mpc1211_partitions; -+ nr_parts = ARRAY_SIZE(mpc1211_partitions); -+ -+ add_mtd_partitions(flash_mtd, parsed_parts, nr_parts); -+ return 0; -+} -+ -+static void __exit cleanup_mpc1211_maps(void) -+{ -+ if (parsed_parts) -+ del_mtd_partitions(flash_mtd); -+ else -+ del_mtd_device(flash_mtd); -+ map_destroy(flash_mtd); -+} -+ -+module_init(init_mpc1211_maps); -+module_exit(cleanup_mpc1211_maps); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Saito.K & Jeanne "); -+MODULE_DESCRIPTION("MTD map driver for MPC-1211 boards. Interface"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/netsc520.c linux/drivers/mtd/maps/netsc520.c ---- linux-mips-2.4.27/drivers/mtd/maps/netsc520.c 2001-11-05 21:15:52.000000000 +0100 -+++ linux/drivers/mtd/maps/netsc520.c 2004-11-19 10:25:11.935194320 +0100 -@@ -3,7 +3,7 @@ - * Copyright (C) 2001 Mark Langsdorf (mark.langsdorf@amd.com) - * based on sc520cdp.c by Sysgo Real-Time Solutions GmbH - * -- * $Id$ -+ * $Id$ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -50,95 +51,41 @@ - ** recoverable afterwards. - */ - --static __u8 netsc520_read8(struct map_info *map, unsigned long ofs) --{ -- return readb(map->map_priv_1 + ofs); --} -- --static __u16 netsc520_read16(struct map_info *map, unsigned long ofs) --{ -- return readw(map->map_priv_1 + ofs); --} -- --static __u32 netsc520_read32(struct map_info *map, unsigned long ofs) --{ -- return readl(map->map_priv_1 + ofs); --} -- --static void netsc520_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); --} -- --static void netsc520_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, map->map_priv_1 + adr); --} -- --static void netsc520_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, map->map_priv_1 + adr); --} -- --static void netsc520_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- writel(d, map->map_priv_1 + adr); --} -- --static void netsc520_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio((void *)(map->map_priv_1 + to), from, len); --} -- - /* partition_info gives details on the logical partitions that the split the - * single flash device into. If the size if zero we use up to the end of the - * device. */ - static struct mtd_partition partition_info[]={ - { -- name: "NetSc520 boot kernel", -- offset: 0, -- size: 0xc0000 -+ .name = "NetSc520 boot kernel", -+ .offset = 0, -+ .size = 0xc0000 - }, - { -- name: "NetSc520 Low BIOS", -- offset: 0xc0000, -- size: 0x40000 -+ .name = "NetSc520 Low BIOS", -+ .offset = 0xc0000, -+ .size = 0x40000 - }, - { -- name: "NetSc520 file system", -- offset: 0x100000, -- size: 0xe80000 -+ .name = "NetSc520 file system", -+ .offset = 0x100000, -+ .size = 0xe80000 - }, - { -- name: "NetSc520 High BIOS", -- offset: 0xf80000, -- size: 0x80000 -+ .name = "NetSc520 High BIOS", -+ .offset = 0xf80000, -+ .size = 0x80000 - }, - }; - #define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0])) - --/* -- * If no idea what is going on here. This is taken from the FlashFX stuff. -- */ --#define ROMCS 1 -- -- - #define WINDOW_SIZE 0x00100000 - #define WINDOW_ADDR 0x00200000 - - static struct map_info netsc520_map = { -- name: "netsc520 Flash Bank", -- size: WINDOW_SIZE, -- buswidth: 4, -- read8: netsc520_read8, -- read16: netsc520_read16, -- read32: netsc520_read32, -- copy_from: netsc520_copy_from, -- write8: netsc520_write8, -- write16: netsc520_write16, -- write32: netsc520_write32, -- copy_to: netsc520_copy_to, -- map_priv_2: WINDOW_ADDR -+ .name = "netsc520 Flash Bank", -+ .size = WINDOW_SIZE, -+ .buswidth = 4, -+ .phys = WINDOW_ADDR, - }; - - #define NUM_FLASH_BANKS (sizeof(netsc520_map)/sizeof(struct map_info)) -@@ -147,13 +94,16 @@ - - static int __init init_netsc520(void) - { -- printk(KERN_NOTICE "NetSc520 flash device: %lx at %lx\n", netsc520_map.size, netsc520_map.map_priv_2); -- netsc520_map.map_priv_1 = (unsigned long)ioremap_nocache(netsc520_map.map_priv_2, netsc520_map.size); -+ printk(KERN_NOTICE "NetSc520 flash device: 0x%lx at 0x%lx\n", netsc520_map.size, netsc520_map.phys); -+ netsc520_map.virt = (unsigned long)ioremap_nocache(netsc520_map.phys, netsc520_map.size); - -- if (!netsc520_map.map_priv_1) { -+ if (!netsc520_map.virt) { - printk("Failed to ioremap_nocache\n"); - return -EIO; - } -+ -+ simple_map_init(&netsc520_map); -+ - mymtd = do_map_probe("cfi_probe", &netsc520_map); - if(!mymtd) - mymtd = do_map_probe("map_ram", &netsc520_map); -@@ -161,11 +111,11 @@ - mymtd = do_map_probe("map_rom", &netsc520_map); - - if (!mymtd) { -- iounmap((void *)netsc520_map.map_priv_1); -+ iounmap((void *)netsc520_map.virt); - return -ENXIO; - } - -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - add_mtd_partitions( mymtd, partition_info, NUM_PARTITIONS ); - return 0; - } -@@ -176,9 +126,9 @@ - del_mtd_partitions(mymtd); - map_destroy(mymtd); - } -- if (netsc520_map.map_priv_1) { -- iounmap((void *)netsc520_map.map_priv_1); -- netsc520_map.map_priv_1 = 0; -+ if (netsc520_map.virt) { -+ iounmap((void *)netsc520_map.virt); -+ netsc520_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/nettel.c linux/drivers/mtd/maps/nettel.c ---- linux-mips-2.4.27/drivers/mtd/maps/nettel.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/maps/nettel.c 2004-11-19 10:25:11.937194016 +0100 -@@ -6,7 +6,7 @@ - * (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com) - * (C) Copyright 2001-2002, SnapGear (www.snapgear.com) - * -- * $Id$ -+ * $Id$ - */ - - /****************************************************************************/ -@@ -59,128 +59,72 @@ - - /****************************************************************************/ - --static __u8 nettel_read8(struct map_info *map, unsigned long ofs) --{ -- return(readb(map->map_priv_1 + ofs)); --} -- --static __u16 nettel_read16(struct map_info *map, unsigned long ofs) --{ -- return(readw(map->map_priv_1 + ofs)); --} -- --static __u32 nettel_read32(struct map_info *map, unsigned long ofs) --{ -- return(readl(map->map_priv_1 + ofs)); --} -- --static void nettel_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --static void nettel_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, map->map_priv_1 + adr); --} -- --static void nettel_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, map->map_priv_1 + adr); --} -- --static void nettel_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- writel(d, map->map_priv_1 + adr); --} -- --static void nettel_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} -- - /****************************************************************************/ - - #ifdef CONFIG_MTD_CFI_INTELEXT - static struct map_info nettel_intel_map = { -- name: "SnapGear Intel", -- size: 0, -- buswidth: INTEL_BUSWIDTH, -- read8: nettel_read8, -- read16: nettel_read16, -- read32: nettel_read32, -- copy_from: nettel_copy_from, -- write8: nettel_write8, -- write16: nettel_write16, -- write32: nettel_write32, -- copy_to: nettel_copy_to -+ .name = "SnapGear Intel", -+ .size = 0, -+ .buswidth = INTEL_BUSWIDTH, - }; - - static struct mtd_partition nettel_intel_partitions[] = { - { -- name: "SnapGear kernel", -- offset: 0, -- size: 0x000e0000 -+ .name = "SnapGear kernel", -+ .offset = 0, -+ .size = 0x000e0000 - }, - { -- name: "SnapGear filesystem", -- offset: 0x00100000, -+ .name = "SnapGear filesystem", -+ .offset = 0x00100000, - }, - { -- name: "SnapGear config", -- offset: 0x000e0000, -- size: 0x00020000 -+ .name = "SnapGear config", -+ .offset = 0x000e0000, -+ .size = 0x00020000 - }, - { -- name: "SnapGear Intel", -- offset: 0 -+ .name = "SnapGear Intel", -+ .offset = 0 - }, - { -- name: "SnapGear BIOS Config", -- offset: 0x007e0000, -- size: 0x00020000 -+ .name = "SnapGear BIOS Config", -+ .offset = 0x007e0000, -+ .size = 0x00020000 - }, - { -- name: "SnapGear BIOS", -- offset: 0x007e0000, -- size: 0x00020000 -+ .name = "SnapGear BIOS", -+ .offset = 0x007e0000, -+ .size = 0x00020000 - }, - }; - #endif - - static struct map_info nettel_amd_map = { -- name: "SnapGear AMD", -- size: AMD_WINDOW_MAXSIZE, -- buswidth: AMD_BUSWIDTH, -- read8: nettel_read8, -- read16: nettel_read16, -- read32: nettel_read32, -- copy_from: nettel_copy_from, -- write8: nettel_write8, -- write16: nettel_write16, -- write32: nettel_write32, -- copy_to: nettel_copy_to -+ .name = "SnapGear AMD", -+ .size = AMD_WINDOW_MAXSIZE, -+ .buswidth = AMD_BUSWIDTH, - }; - - static struct mtd_partition nettel_amd_partitions[] = { - { -- name: "SnapGear BIOS config", -- offset: 0x000e0000, -- size: 0x00010000 -+ .name = "SnapGear BIOS config", -+ .offset = 0x000e0000, -+ .size = 0x00010000 - }, - { -- name: "SnapGear BIOS", -- offset: 0x000f0000, -- size: 0x00010000 -+ .name = "SnapGear BIOS", -+ .offset = 0x000f0000, -+ .size = 0x00010000 - }, - { -- name: "SnapGear AMD", -- offset: 0 -+ .name = "SnapGear AMD", -+ .offset = 0 - }, - { -- name: "SnapGear high BIOS", -- offset: 0x001f0000, -- size: 0x00010000 -+ .name = "SnapGear high BIOS", -+ .offset = 0x001f0000, -+ .size = 0x00010000 - } - }; - -@@ -328,18 +272,20 @@ - *amdpar = SC520_PAR(SC520_PAR_BOOTCS, amdaddr, maxsize); - __asm__ ("wbinvd"); - -- nettel_amd_map.map_priv_1 = (unsigned long) -+ nettel_amd_map.phys = amdaddr; -+ nettel_amd_map.virt = (unsigned long) - ioremap_nocache(amdaddr, maxsize); -- if (!nettel_amd_map.map_priv_1) { -+ if (!nettel_amd_map.virt) { - printk("SNAPGEAR: failed to ioremap() BOOTCS\n"); - return(-EIO); - } -+ simple_map_init(&nettel_amd_map); - - if ((amd_mtd = do_map_probe("jedec_probe", &nettel_amd_map))) { - printk(KERN_NOTICE "SNAPGEAR: AMD flash device size = %dK\n", - amd_mtd->size>>10); - -- amd_mtd->module = THIS_MODULE; -+ amd_mtd->owner = THIS_MODULE; - - /* The high BIOS partition is only present for 2MB units */ - num_amd_partitions = NUM_AMD_PARTITIONS; -@@ -387,8 +333,8 @@ - - /* Destroy useless AMD MTD mapping */ - amd_mtd = NULL; -- iounmap((void *) nettel_amd_map.map_priv_1); -- nettel_amd_map.map_priv_1 = (unsigned long) NULL; -+ iounmap((void *) nettel_amd_map.virt); -+ nettel_amd_map.virt = (unsigned long) NULL; - #else - /* Only AMD flash supported */ - return(-ENXIO); -@@ -411,16 +357,18 @@ - - /* Probe for the the size of the first Intel flash */ - nettel_intel_map.size = maxsize; -- nettel_intel_map.map_priv_1 = (unsigned long) -+ nettel_intel_map.phys = intel0addr; -+ nettel_intel_map.virt = (unsigned long) - ioremap_nocache(intel0addr, maxsize); -- if (!nettel_intel_map.map_priv_1) { -+ if (!nettel_intel_map.virt) { - printk("SNAPGEAR: failed to ioremap() ROMCS1\n"); - return(-EIO); - } -+ simple_map_init(&nettel_intel_map); - - intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); - if (! intel_mtd) { -- iounmap((void *) nettel_intel_map.map_priv_1); -+ iounmap((void *) nettel_intel_map.virt); - return(-ENXIO); - } - -@@ -441,19 +389,19 @@ - /* Delete the old map and probe again to do both chips */ - map_destroy(intel_mtd); - intel_mtd = NULL; -- iounmap((void *) nettel_intel_map.map_priv_1); -+ iounmap((void *) nettel_intel_map.virt); - - nettel_intel_map.size = maxsize; -- nettel_intel_map.map_priv_1 = (unsigned long) -+ nettel_intel_map.virt = (unsigned long) - ioremap_nocache(intel0addr, maxsize); -- if (!nettel_intel_map.map_priv_1) { -+ if (!nettel_intel_map.virt) { - printk("SNAPGEAR: failed to ioremap() ROMCS1/2\n"); - return(-EIO); - } - - intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); - if (! intel_mtd) { -- iounmap((void *) nettel_intel_map.map_priv_1); -+ iounmap((void *) nettel_intel_map.virt); - return(-ENXIO); - } - -@@ -468,7 +416,7 @@ - printk(KERN_NOTICE "SNAPGEAR: Intel flash device size = %dK\n", - (intel_mtd->size >> 10)); - -- intel_mtd->module = THIS_MODULE; -+ intel_mtd->owner = THIS_MODULE; - - #ifndef CONFIG_BLK_DEV_INITRD - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 1); -@@ -523,18 +471,18 @@ - del_mtd_partitions(amd_mtd); - map_destroy(amd_mtd); - } -- if (nettel_amd_map.map_priv_1) { -- iounmap((void *)nettel_amd_map.map_priv_1); -- nettel_amd_map.map_priv_1 = 0; -+ if (nettel_amd_map.virt) { -+ iounmap((void *)nettel_amd_map.virt); -+ nettel_amd_map.virt = 0; - } - #ifdef CONFIG_MTD_CFI_INTELEXT - if (intel_mtd) { - del_mtd_partitions(intel_mtd); - map_destroy(intel_mtd); - } -- if (nettel_intel_map.map_priv_1) { -- iounmap((void *)nettel_intel_map.map_priv_1); -- nettel_intel_map.map_priv_1 = 0; -+ if (nettel_intel_map.virt) { -+ iounmap((void *)nettel_intel_map.virt); -+ nettel_intel_map.virt = 0; - } - #endif - } -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/ocelot.c linux/drivers/mtd/maps/ocelot.c ---- linux-mips-2.4.27/drivers/mtd/maps/ocelot.c 2001-11-05 21:15:52.000000000 +0100 -+++ linux/drivers/mtd/maps/ocelot.c 2004-11-19 10:25:11.938193864 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Flash on Momenco Ocelot - */ -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -20,47 +21,23 @@ - #define NVRAM_WINDOW_SIZE 0x00007FF0 - #define NVRAM_BUSWIDTH 1 - --extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts); -- - static unsigned int cacheflush = 0; - - static struct mtd_info *flash_mtd; - static struct mtd_info *nvram_mtd; - --__u8 ocelot_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --void ocelot_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- cacheflush = 1; -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void ocelot_copy_from_cache(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- if (cacheflush) { -- dma_cache_inv(map->map_priv_2, map->size); -- cacheflush = 0; -- } -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void ocelot_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -+static void ocelot_ram_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) - { -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -+ struct map_info *map = (struct map_info *)mtd->priv; -+ size_t done = 0; - --void ocelot_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ - /* If we use memcpy, it does word-wide writes. Even though we told the - GT64120A that it's an 8-bit wide region, word-wide writes don't work. - We end up just writing the first byte of the four to all four bytes. - So we have this loop instead */ -+ *retlen = len; - while(len) { -- __raw_writeb(*(unsigned char *) from, map->map_priv_1 + to); -+ __raw_writeb(*(unsigned char *) from, map->virt + to); - from++; - to++; - len--; -@@ -70,24 +47,21 @@ - static struct mtd_partition *parsed_parts; - - struct map_info ocelot_flash_map = { -- name: "Ocelot boot flash", -- size: FLASH_WINDOW_SIZE, -- buswidth: FLASH_BUSWIDTH, -- read8: ocelot_read8, -- copy_from: ocelot_copy_from_cache, -- write8: ocelot_write8, -+ .name = "Ocelot boot flash", -+ .size = FLASH_WINDOW_SIZE, -+ .buswidth = FLASH_BUSWIDTH, -+ .phys = FLASH_WINDOW_ADDR, - }; - - struct map_info ocelot_nvram_map = { -- name: "Ocelot NVRAM", -- size: NVRAM_WINDOW_SIZE, -- buswidth: NVRAM_BUSWIDTH, -- read8: ocelot_read8, -- copy_from: ocelot_copy_from, -- write8: ocelot_write8, -- copy_to: ocelot_copy_to -+ .name = "Ocelot NVRAM", -+ .size = NVRAM_WINDOW_SIZE, -+ .buswidth = NVRAM_BUSWIDTH, -+ .phys = NVRAM_WINDOW_ADDR, - }; - -+static const char *probes[] = { "RedBoot", NULL }; -+ - static int __init init_ocelot_maps(void) - { - void *pld; -@@ -107,12 +81,13 @@ - iounmap(pld); - - /* Now ioremap the NVRAM space */ -- ocelot_nvram_map.map_priv_1 = (unsigned long)ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE); -- if (!ocelot_nvram_map.map_priv_1) { -+ ocelot_nvram_map.virt = (unsigned long)ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE); -+ if (!ocelot_nvram_map.virt) { - printk(KERN_NOTICE "Failed to ioremap Ocelot NVRAM space\n"); - return -EIO; - } -- // ocelot_nvram_map.map_priv_2 = ocelot_nvram_map.map_priv_1; -+ -+ simple_map_init(&ocelot_nvram_map); - - /* And do the RAM probe on it to get an MTD device */ - nvram_mtd = do_map_probe("map_ram", &ocelot_nvram_map); -@@ -120,22 +95,21 @@ - printk("NVRAM probe failed\n"); - goto fail_1; - } -- nvram_mtd->module = THIS_MODULE; -+ nvram_mtd->owner = THIS_MODULE; - nvram_mtd->erasesize = 16; -+ /* Override the write() method */ -+ nvram_mtd->write = ocelot_ram_write; - - /* Now map the flash space */ -- ocelot_flash_map.map_priv_1 = (unsigned long)ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE); -- if (!ocelot_flash_map.map_priv_1) { -+ ocelot_flash_map.virt = (unsigned long)ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE); -+ if (!ocelot_flash_map.virt) { - printk(KERN_NOTICE "Failed to ioremap Ocelot flash space\n"); - goto fail_2; - } - /* Now the cached version */ -- ocelot_flash_map.map_priv_2 = (unsigned long)__ioremap(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE, 0); -+ ocelot_flash_map.cached = (unsigned long)__ioremap(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE, 0); - -- if (!ocelot_flash_map.map_priv_2) { -- /* Doesn't matter if it failed. Just use the uncached version */ -- ocelot_flash_map.map_priv_2 = ocelot_flash_map.map_priv_1; -- } -+ simple_map_init(&ocelot_flash_map); - - /* Only probe for flash if the write jumper is present */ - if (brd_status & 0x40) { -@@ -155,10 +129,10 @@ - - add_mtd_device(nvram_mtd); - -- flash_mtd->module = THIS_MODULE; -- nr_parts = parse_redboot_partitions(flash_mtd, &parsed_parts); -+ flash_mtd->owner = THIS_MODULE; -+ nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0); - -- if (nr_parts) -+ if (nr_parts > 0) - add_mtd_partitions(flash_mtd, parsed_parts, nr_parts); - else - add_mtd_device(flash_mtd); -@@ -166,14 +140,13 @@ - return 0; - - fail3: -- iounmap((void *)ocelot_flash_map.map_priv_1); -- if (ocelot_flash_map.map_priv_2 && -- ocelot_flash_map.map_priv_2 != ocelot_flash_map.map_priv_1) -- iounmap((void *)ocelot_flash_map.map_priv_2); -+ iounmap((void *)ocelot_flash_map.virt); -+ if (ocelot_flash_map.cached) -+ iounmap((void *)ocelot_flash_map.cached); - fail_2: - map_destroy(nvram_mtd); - fail_1: -- iounmap((void *)ocelot_nvram_map.map_priv_1); -+ iounmap((void *)ocelot_nvram_map.virt); - - return -ENXIO; - } -@@ -182,16 +155,16 @@ - { - del_mtd_device(nvram_mtd); - map_destroy(nvram_mtd); -- iounmap((void *)ocelot_nvram_map.map_priv_1); -+ iounmap((void *)ocelot_nvram_map.virt); - - if (parsed_parts) - del_mtd_partitions(flash_mtd); - else - del_mtd_device(flash_mtd); - map_destroy(flash_mtd); -- iounmap((void *)ocelot_flash_map.map_priv_1); -- if (ocelot_flash_map.map_priv_2 != ocelot_flash_map.map_priv_1) -- iounmap((void *)ocelot_flash_map.map_priv_2); -+ iounmap((void *)ocelot_flash_map.virt); -+ if (ocelot_flash_map.cached) -+ iounmap((void *)ocelot_flash_map.cached); - } - - module_init(init_ocelot_maps); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/octagon-5066.c linux/drivers/mtd/maps/octagon-5066.c ---- linux-mips-2.4.27/drivers/mtd/maps/octagon-5066.c 2003-08-13 19:19:18.000000000 +0200 -+++ linux/drivers/mtd/maps/octagon-5066.c 2004-11-19 10:25:11.940193560 +0100 -@@ -1,4 +1,4 @@ --// $Id$ -+// $Id$ - /* ###################################################################### - - Octagon 5066 MTD Driver. -@@ -31,6 +31,7 @@ - #include - - #include -+#include - - #define WINDOW_START 0xe8000 - #define WINDOW_LENGTH 0x8000 -@@ -151,32 +152,34 @@ - - static struct map_info oct5066_map[2] = { - { -- name: "Octagon 5066 Socket", -- size: 512 * 1024, -- buswidth: 1, -- read8: oct5066_read8, -- read16: oct5066_read16, -- read32: oct5066_read32, -- copy_from: oct5066_copy_from, -- write8: oct5066_write8, -- write16: oct5066_write16, -- write32: oct5066_write32, -- copy_to: oct5066_copy_to, -- map_priv_1: 1<<6 -+ .name = "Octagon 5066 Socket", -+ .phys = NO_XIP, -+ .size = 512 * 1024, -+ .buswidth = 1, -+ .read8 = oct5066_read8, -+ .read16 = oct5066_read16, -+ .read32 = oct5066_read32, -+ .copy_from = oct5066_copy_from, -+ .write8 = oct5066_write8, -+ .write16 = oct5066_write16, -+ .write32 = oct5066_write32, -+ .copy_to = oct5066_copy_to, -+ .map_priv_1 = 1<<6 - }, - { -- name: "Octagon 5066 Internal Flash", -- size: 2 * 1024 * 1024, -- buswidth: 1, -- read8: oct5066_read8, -- read16: oct5066_read16, -- read32: oct5066_read32, -- copy_from: oct5066_copy_from, -- write8: oct5066_write8, -- write16: oct5066_write16, -- write32: oct5066_write32, -- copy_to: oct5066_copy_to, -- map_priv_1: 2<<6 -+ .name = "Octagon 5066 Internal Flash", -+ .phys = NO_XIP, -+ .size = 2 * 1024 * 1024, -+ .buswidth = 1, -+ .read8 = oct5066_read8, -+ .read16 = oct5066_read16, -+ .read32 = oct5066_read32, -+ .copy_from = oct5066_copy_from, -+ .write8 = oct5066_write8, -+ .write16 = oct5066_write16, -+ .write32 = oct5066_write32, -+ .copy_to = oct5066_copy_to, -+ .map_priv_1 = 2<<6 - } - }; - -@@ -244,6 +247,7 @@ - } - if (OctProbe() != 0) { - printk(KERN_NOTICE "5066: Octagon Probe Failed, is this an Octagon 5066 SBC?\n"); -+ iounmap((void *)iomapadr); - ret = -EAGAIN; - goto out_unmap; - } -@@ -261,7 +265,7 @@ - if (!oct5066_mtd[i]) - oct5066_mtd[i] = do_map_probe("map_rom", &oct5066_map[i]); - if (oct5066_mtd[i]) { -- oct5066_mtd[i]->module = THIS_MODULE; -+ oct5066_mtd[i]->owner = THIS_MODULE; - add_mtd_device(oct5066_mtd[i]); - } - } -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/omap-toto-flash.c linux/drivers/mtd/maps/omap-toto-flash.c ---- linux-mips-2.4.27/drivers/mtd/maps/omap-toto-flash.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/omap-toto-flash.c 2004-11-19 10:25:11.941193408 +0100 -@@ -0,0 +1,137 @@ -+/* -+ * NOR Flash memory access on TI Toto board -+ * -+ * jzhang@ti.com (C) 2003 Texas Instruments. -+ * -+ * (C) 2002 MontVista Software, Inc. -+ * -+ * $Id$ -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+ -+#ifndef CONFIG_ARCH_OMAP -+#error This is for OMAP architecture only -+#endif -+ -+//these lines need be moved to a hardware header file -+#define OMAP_TOTO_FLASH_BASE 0xd8000000 -+#define OMAP_TOTO_FLASH_SIZE 0x80000 -+ -+static struct map_info omap_toto_map_flash = { -+ .name = "OMAP Toto flash", -+ .buswidth = 2, -+ .virt = OMAP_TOTO_FLASH_BASE, -+}; -+ -+ -+static struct mtd_partition toto_flash_partitions[] = { -+ { -+ .name = "BootLoader", -+ .size = 0x00040000, /* hopefully u-boot will stay 128k + 128*/ -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "ReservedSpace", -+ .size = 0x00030000, -+ .offset = MTDPART_OFS_APPEND, -+ //mask_flags: MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "EnvArea", /* bottom 64KiB for env vars */ -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, -+ } -+}; -+ -+static struct mtd_partition *parsed_parts; -+ -+static struct mtd_info *flash_mtd; -+ -+static int __init init_flash (void) -+{ -+ -+ struct mtd_partition *parts; -+ int nb_parts = 0; -+ int parsed_nr_parts = 0; -+ const char *part_type; -+ -+ /* -+ * Static partition definition selection -+ */ -+ part_type = "static"; -+ -+ parts = toto_flash_partitions; -+ nb_parts = ARRAY_SIZE(toto_flash_partitions); -+ omap_toto_map_flash.size = OMAP_TOTO_FLASH_SIZE; -+ omap_toto_map_flash.phys = virt_to_phys(OMAP_TOTO_FLASH_BASE); -+ -+ simple_map_init(&omap_toto_map_flash); -+ /* -+ * Now let's probe for the actual flash. Do it here since -+ * specific machine settings might have been set above. -+ */ -+ printk(KERN_NOTICE "OMAP toto flash: probing %d-bit flash bus\n", -+ omap_toto_map_flash.buswidth*8); -+ flash_mtd = do_map_probe("jedec_probe", &omap_toto_map_flash); -+ if (!flash_mtd) -+ return -ENXIO; -+ -+ if (parsed_nr_parts > 0) { -+ parts = parsed_parts; -+ nb_parts = parsed_nr_parts; -+ } -+ -+ if (nb_parts == 0) { -+ printk(KERN_NOTICE "OMAP toto flash: no partition info available," -+ "registering whole flash at once\n"); -+ if (add_mtd_device(flash_mtd)){ -+ return -ENXIO; -+ } -+ } else { -+ printk(KERN_NOTICE "Using %s partition definition\n", -+ part_type); -+ return add_mtd_partitions(flash_mtd, parts, nb_parts); -+ } -+ return 0; -+} -+ -+int __init omap_toto_mtd_init(void) -+{ -+ int status; -+ -+ if (status = init_flash()) { -+ printk(KERN_ERR "OMAP Toto Flash: unable to init map for toto flash\n"); -+ } -+ return status; -+} -+ -+static void __exit omap_toto_mtd_cleanup(void) -+{ -+ if (flash_mtd) { -+ del_mtd_partitions(flash_mtd); -+ map_destroy(flash_mtd); -+ if (parsed_parts) -+ kfree(parsed_parts); -+ } -+} -+ -+module_init(omap_toto_mtd_init); -+module_exit(omap_toto_mtd_cleanup); -+ -+MODULE_AUTHOR("Jian Zhang"); -+MODULE_DESCRIPTION("OMAP Toto board map driver"); -+MODULE_LICENSE("GPL"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/pb1xxx-flash.c linux/drivers/mtd/maps/pb1xxx-flash.c ---- linux-mips-2.4.27/drivers/mtd/maps/pb1xxx-flash.c 2003-05-19 08:27:22.000000000 +0200 -+++ linux/drivers/mtd/maps/pb1xxx-flash.c 2004-11-19 10:25:11.943193104 +0100 -@@ -3,12 +3,13 @@ - * - * (C) 2001 Pete Popov - * -- * $Id$ -+ * $Id$ - */ - - #include - #include - #include -+#include - #include - - #include -@@ -25,210 +26,110 @@ - #endif - - #ifdef CONFIG_MIPS_PB1000 -+ - #define WINDOW_ADDR 0x1F800000 - #define WINDOW_SIZE 0x800000 --#endif -- --__u8 physmap_read8(struct map_info *map, unsigned long ofs) --{ -- __u8 ret; -- ret = __raw_readb(map->map_priv_1 + ofs); -- DBG("read8 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --__u16 physmap_read16(struct map_info *map, unsigned long ofs) --{ -- __u16 ret; -- ret = __raw_readw(map->map_priv_1 + ofs); -- DBG("read16 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --__u32 physmap_read32(struct map_info *map, unsigned long ofs) --{ -- __u32 ret; -- ret = __raw_readl(map->map_priv_1 + ofs); -- DBG("read32 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- DBG("physmap_copy from %x to %x\n", (unsigned)from, (unsigned)to); -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void physmap_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- DBG("write8 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- DBG("write16 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- DBG("write32 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- DBG("physmap_copy_to %x from %x\n", (unsigned)to, (unsigned)from); -- memcpy_toio(map->map_priv_1 + to, from, len); --} -- -- -- --static struct map_info pb1xxx_map = { -- name: "Pb1xxx flash", -- read8: physmap_read8, -- read16: physmap_read16, -- read32: physmap_read32, -- copy_from: physmap_copy_from, -- write8: physmap_write8, -- write16: physmap_write16, -- write32: physmap_write32, -- copy_to: physmap_copy_to, --}; - -- --#ifdef CONFIG_MIPS_PB1000 -- --static unsigned long flash_size = 0x00800000; --static unsigned char flash_buswidth = 4; - static struct mtd_partition pb1xxx_partitions[] = { - { -- name: "yamon env", -- size: 0x00020000, -- offset: 0, -- mask_flags: MTD_WRITEABLE -- },{ -- name: "User FS", -- size: 0x003e0000, -- offset: 0x20000, -- },{ -- name: "boot code", -- size: 0x100000, -- offset: 0x400000, -- mask_flags: MTD_WRITEABLE -- },{ -- name: "raw/kernel", -- size: 0x300000, -- offset: 0x500000 -- } -+ .name = "yamon env", -+ .size = 0x00020000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE}, -+ { -+ .name = "User FS", -+ .size = 0x003e0000, -+ .offset = 0x20000,}, -+ { -+ .name = "boot code", -+ .size = 0x100000, -+ .offset = 0x400000, -+ .mask_flags = MTD_WRITEABLE}, -+ { -+ .name = "raw/kernel", -+ .size = 0x300000, -+ .offset = 0x500000} - }; - - #elif defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) - --static unsigned char flash_buswidth = 4; - #if defined(CONFIG_MTD_PB1500_BOOT) && defined(CONFIG_MTD_PB1500_USER) --/* both 32MiB banks will be used. Combine the first 32MiB bank and the -- * first 28MiB of the second bank together into a single jffs/jffs2 -+/* both 32MB banks will be used. Combine the first 32MB bank and the -+ * first 28MB of the second bank together into a single jffs/jffs2 - * partition. - */ --static unsigned long flash_size = 0x04000000; - #define WINDOW_ADDR 0x1C000000 - #define WINDOW_SIZE 0x4000000 - static struct mtd_partition pb1xxx_partitions[] = { - { -- name: "User FS", -- size: 0x3c00000, -- offset: 0x0000000 -- },{ -- name: "yamon", -- size: 0x0100000, -- offset: 0x3c00000, -- mask_flags: MTD_WRITEABLE -- },{ -- name: "raw kernel", -- size: 0x02c0000, -- offset: 0x3d00000 -+ .name = "User FS", -+ .size = 0x3c00000, -+ .offset = 0x0000000 -+ },{ -+ .name = "yamon", -+ .size = 0x0100000, -+ .offset = 0x3c00000, -+ .mask_flags = MTD_WRITEABLE -+ },{ -+ .name = "raw kernel", -+ .size = 0x02c0000, -+ .offset = 0x3d00000 - } - }; - #elif defined(CONFIG_MTD_PB1500_BOOT) && !defined(CONFIG_MTD_PB1500_USER) --static unsigned long flash_size = 0x02000000; - #define WINDOW_ADDR 0x1E000000 - #define WINDOW_SIZE 0x2000000 - static struct mtd_partition pb1xxx_partitions[] = { - { -- name: "User FS", -- size: 0x1c00000, -- offset: 0x0000000 -- },{ -- name: "yamon", -- size: 0x0100000, -- offset: 0x1c00000, -- mask_flags: MTD_WRITEABLE -- },{ -- name: "raw kernel", -- size: 0x02c0000, -- offset: 0x1d00000 -+ .name = "User FS", -+ .size = 0x1c00000, -+ .offset = 0x0000000 -+ },{ -+ .name = "yamon", -+ .size = 0x0100000, -+ .offset = 0x1c00000, -+ .mask_flags = MTD_WRITEABLE -+ },{ -+ .name = "raw kernel", -+ .size = 0x02c0000, -+ .offset = 0x1d00000 - } - }; - #elif !defined(CONFIG_MTD_PB1500_BOOT) && defined(CONFIG_MTD_PB1500_USER) --static unsigned long flash_size = 0x02000000; - #define WINDOW_ADDR 0x1C000000 - #define WINDOW_SIZE 0x2000000 - static struct mtd_partition pb1xxx_partitions[] = { - { -- name: "User FS", -- size: 0x1e00000, -- offset: 0x0000000 -- },{ -- name: "raw kernel", -- size: 0x0200000, -- offset: 0x1e00000, -+ .name = "User FS", -+ .size = 0x1e00000, -+ .offset = 0x0000000 -+ },{ -+ .name = "raw kernel", -+ .size = 0x0200000, -+ .offset = 0x1e00000, - } - }; - #else - #error MTD_PB1500 define combo error /* should never happen */ - #endif --#elif defined(CONFIG_MTD_BOSPORUS) --static unsigned char flash_buswidth = 2; --static unsigned long flash_size = 0x02000000; --#define WINDOW_ADDR 0x1F000000 --#define WINDOW_SIZE 0x2000000 --static struct mtd_partition pb1xxx_partitions[] = { -- { -- name: "User FS", -- size: 0x00400000, -- offset: 0x00000000, -- },{ -- name: "Yamon-2", -- size: 0x00100000, -- offset: 0x00400000, -- },{ -- name: "Root FS", -- size: 0x00700000, -- offset: 0x00500000, -- },{ -- name: "Yamon-1", -- size: 0x00100000, -- offset: 0x00C00000, -- },{ -- name: "Kernel", -- size: 0x00300000, -- offset: 0x00D00000, -- } --}; - #else - #error Unsupported board - #endif - -+#define NAME "Pb1x00 Linux Flash" -+#define PADDR WINDOW_ADDR -+#define BUSWIDTH 4 -+#define SIZE WINDOW_SIZE -+#define PARTITIONS 4 -+ -+static struct map_info pb1xxx_mtd_map = { -+ .name = NAME, -+ .size = SIZE, -+ .buswidth = BUSWIDTH, -+ .phys = PADDR, -+}; - --#define NB_OF(x) (sizeof(x)/sizeof(x[0])) -- --static struct mtd_partition *parsed_parts; --static struct mtd_info *mymtd; -+static struct mtd_info *pb1xxx_mtd; - - int __init pb1xxx_mtd_init(void) - { -@@ -236,40 +137,37 @@ - int nb_parts = 0; - char *part_type; - -- /* Default flash buswidth */ -- pb1xxx_map.buswidth = flash_buswidth; -- - /* - * Static partition definition selection - */ - part_type = "static"; - parts = pb1xxx_partitions; -- nb_parts = NB_OF(pb1xxx_partitions); -- pb1xxx_map.size = flash_size; -+ nb_parts = ARRAY_SIZE(pb1xxx_partitions); - - /* - * Now let's probe for the actual flash. Do it here since - * specific machine settings might have been set above. - */ - printk(KERN_NOTICE "Pb1xxx flash: probing %d-bit flash bus\n", -- pb1xxx_map.buswidth*8); -- pb1xxx_map.map_priv_1 = -- (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); -- mymtd = do_map_probe("cfi_probe", &pb1xxx_map); -- if (!mymtd) return -ENXIO; -- mymtd->module = THIS_MODULE; -+ BUSWIDTH*8); -+ pb1xxx_mtd_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); -+ -+ simple_map_init(&pb1xxx_mtd_map); -+ -+ pb1xxx_mtd = do_map_probe("cfi_probe", &pb1xxx_mtd_map); -+ if (!pb1xxx_mtd) return -ENXIO; -+ pb1xxx_mtd->owner = THIS_MODULE; - -- add_mtd_partitions(mymtd, parts, nb_parts); -+ add_mtd_partitions(pb1xxx_mtd, parts, nb_parts); - return 0; - } - - static void __exit pb1xxx_mtd_cleanup(void) - { -- if (mymtd) { -- del_mtd_partitions(mymtd); -- map_destroy(mymtd); -- if (parsed_parts) -- kfree(parsed_parts); -+ if (pb1xxx_mtd) { -+ del_mtd_partitions(pb1xxx_mtd); -+ map_destroy(pb1xxx_mtd); -+ iounmap((void *) pb1xxx_mtd_map.virt); - } - } - -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/pci.c linux/drivers/mtd/maps/pci.c ---- linux-mips-2.4.27/drivers/mtd/maps/pci.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/maps/pci.c 2004-11-19 10:25:11.944192952 +0100 -@@ -7,7 +7,7 @@ - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * -- * $Id$ -+ * $Id$ - * - * Generic PCI memory map driver. We support the following boards: - * - Intel IQ80310 ATU. -@@ -98,10 +98,10 @@ - } - - static struct mtd_pci_info intel_iq80310_info = { -- init: intel_iq80310_init, -- exit: intel_iq80310_exit, -- translate: intel_iq80310_translate, -- map_name: "cfi_probe", -+ .init = intel_iq80310_init, -+ .exit = intel_iq80310_exit, -+ .translate = intel_iq80310_translate, -+ .map_name = "cfi_probe", - }; - - /* -@@ -181,10 +181,10 @@ - } - - static struct mtd_pci_info intel_dc21285_info = { -- init: intel_dc21285_init, -- exit: intel_dc21285_exit, -- translate: intel_dc21285_translate, -- map_name: "jedec_probe", -+ .init = intel_dc21285_init, -+ .exit = intel_dc21285_exit, -+ .translate = intel_dc21285_translate, -+ .map_name = "jedec_probe", - }; - - /* -@@ -193,22 +193,20 @@ - - static struct pci_device_id mtd_pci_ids[] __devinitdata = { - { -- vendor: PCI_VENDOR_ID_INTEL, -- device: 0x530d, -- subvendor: PCI_ANY_ID, -- subdevice: PCI_ANY_ID, -- class: PCI_CLASS_MEMORY_OTHER << 8, -- class_mask: 0xffff00, -- driver_data: (unsigned long)&intel_iq80310_info, -+ .vendor = PCI_VENDOR_ID_INTEL, -+ .device = 0x530d, -+ .subvendor = PCI_ANY_ID, -+ .subdevice = PCI_ANY_ID, -+ .class = PCI_CLASS_MEMORY_OTHER << 8, -+ .class_mask = 0xffff00, -+ .driver_data = (unsigned long)&intel_iq80310_info, - }, - { -- vendor: PCI_VENDOR_ID_DEC, -- device: PCI_DEVICE_ID_DEC_21285, -- subvendor: 0, /* DC21285 defaults to 0 on reset */ -- subdevice: 0, /* DC21285 defaults to 0 on reset */ -- class: 0, -- class_mask: 0, -- driver_data: (unsigned long)&intel_dc21285_info, -+ .vendor = PCI_VENDOR_ID_DEC, -+ .device = PCI_DEVICE_ID_DEC_21285, -+ .subvendor = 0, /* DC21285 defaults to 0 on reset */ -+ .subdevice = 0, /* DC21285 defaults to 0 on reset */ -+ .driver_data = (unsigned long)&intel_dc21285_info, - }, - { 0, } - }; -@@ -275,14 +273,15 @@ - } - - static struct map_info mtd_pci_map = { -- read8: mtd_pci_read8, -- read16: mtd_pci_read16, -- read32: mtd_pci_read32, -- copy_from: mtd_pci_copyfrom, -- write8: mtd_pci_write8, -- write16: mtd_pci_write16, -- write32: mtd_pci_write32, -- copy_to: mtd_pci_copyto, -+ .phys = NO_XIP, -+ .read8 = mtd_pci_read8, -+ .read16 = mtd_pci_read16, -+ .read32 = mtd_pci_read32, -+ .copy_from = mtd_pci_copyfrom, -+ .write8 = mtd_pci_write8, -+ .write16 = mtd_pci_write16, -+ .write32 = mtd_pci_write32, -+ .copy_to = mtd_pci_copyto, - }; - - static int __devinit -@@ -322,7 +321,7 @@ - if (!mtd) - goto release; - -- mtd->module = THIS_MODULE; -+ mtd->owner = THIS_MODULE; - add_mtd_device(mtd); - - pci_set_drvdata(dev, mtd); -@@ -359,10 +358,10 @@ - } - - static struct pci_driver mtd_pci_driver = { -- name: "MTD PCI", -- probe: mtd_pci_probe, -- remove: __devexit_p(mtd_pci_remove), -- id_table: mtd_pci_ids, -+ .name = "MTD PCI", -+ .probe = mtd_pci_probe, -+ .remove = __devexit_p(mtd_pci_remove), -+ .id_table = mtd_pci_ids, - }; - - static int __init mtd_pci_maps_init(void) -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/pcmciamtd.c linux/drivers/mtd/maps/pcmciamtd.c ---- linux-mips-2.4.27/drivers/mtd/maps/pcmciamtd.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/maps/pcmciamtd.c 2004-11-19 10:25:11.946192648 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * pcmciamtd.c - MTD driver for PCMCIA flash memory cards - * -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -24,6 +25,7 @@ - #include - - #include -+#include - - #ifdef CONFIG_MTD_DEBUG - static int debug = CONFIG_MTD_DEBUG_VERBOSE; -@@ -47,7 +49,7 @@ - - - #define DRIVER_DESC "PCMCIA Flash memory card driver" --#define DRIVER_VERSION "$Revision$" -+#define DRIVER_VERSION "$Revision$" - - /* Size of the PCMCIA address space: 26 bits = 64 MB */ - #define MAX_PCMCIA_ADDR 0x4000000 -@@ -96,7 +98,7 @@ - MODULE_PARM(mem_speed, "i"); - MODULE_PARM_DESC(mem_speed, "Set memory access speed in ns"); - MODULE_PARM(force_size, "i"); --MODULE_PARM_DESC(force_size, "Force size of card in MB (1-64)"); -+MODULE_PARM_DESC(force_size, "Force size of card in MiB (1-64)"); - MODULE_PARM(setvpp, "i"); - MODULE_PARM_DESC(setvpp, "Set Vpp (0=Never, 1=On writes, 2=Always on, default=0)"); - MODULE_PARM(vpp, "i"); -@@ -106,11 +108,13 @@ - - - -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69) - static inline void cs_error(client_handle_t handle, int func, int ret) - { - error_info_t err = { func, ret }; - CardServices(ReportError, handle, &err); - } -+#endif - - - /* read/write{8,16} copy_{from,to} routines with window remapping to access whole card */ -@@ -529,6 +533,7 @@ - - card_settings(dev, link, &new_name); - -+ dev->pcmcia_map.phys = NO_XIP; - dev->pcmcia_map.read8 = pcmcia_read8_remap; - dev->pcmcia_map.read16 = pcmcia_read16_remap; - dev->pcmcia_map.copy_from = pcmcia_copy_from_remap; -@@ -539,7 +544,7 @@ - dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp; - - /* Request a memory window for PCMCIA. Some architeures can map windows upto the maximum -- that PCMCIA can support (64Mb) - this is ideal and we aim for a window the size of the -+ that PCMCIA can support (64MiB) - this is ideal and we aim for a window the size of the - whole card - otherwise we try smaller windows until we succeed */ - - req.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE; -@@ -552,7 +557,7 @@ - - do { - int ret; -- DEBUG(2, "requesting window with size = %dKB memspeed = %d", -+ DEBUG(2, "requesting window with size = %dKiB memspeed = %d", - req.Size >> 10, req.AccessSpeed); - link->win = (window_handle_t)link->handle; - ret = CardServices(RequestWindow, &link->win, &req); -@@ -560,7 +565,7 @@ - if(ret) { - req.Size >>= 1; - } else { -- DEBUG(2, "Got window of size %dKB", req.Size >> 10); -+ DEBUG(2, "Got window of size %dKiB", req.Size >> 10); - dev->win_size = req.Size; - break; - } -@@ -573,7 +578,7 @@ - pcmciamtd_release((u_long)link); - return; - } -- DEBUG(1, "Allocated a window of %dKB", dev->win_size >> 10); -+ DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10); - - /* Get write protect status */ - CS_CHECK(GetStatus, link->handle, &status); -@@ -642,21 +647,21 @@ - } - - dev->mtd_info = mtd; -- mtd->module = THIS_MODULE; -+ mtd->owner = THIS_MODULE; - - if(new_name) { - int size = 0; - char unit = ' '; - /* Since we are using a default name, make it better by adding in the - size */ -- if(mtd->size < 1048576) { /* <1MB in size, show size in K */ -+ if(mtd->size < 1048576) { /* <1MiB in size, show size in KiB */ - size = mtd->size >> 10; - unit = 'K'; - } else { - size = mtd->size >> 20; - unit = 'M'; - } -- snprintf(dev->mtd_name, sizeof(dev->mtd_name), "%d%cB %s", size, unit, "PCMCIA Memory card"); -+ snprintf(dev->mtd_name, sizeof(dev->mtd_name), "%d%ciB %s", size, unit, "PCMCIA Memory card"); - } - - /* If the memory found is fits completely into the mapped PCMCIA window, -@@ -828,16 +833,20 @@ - } - - -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,68) -+static struct pcmcia_driver pcmciamtd_driver = { -+ .drv = { -+ .name = "pcmciamtd" -+ }, -+ .attach = pcmciamtd_attach, -+ .detach = pcmciamtd_detach, -+ .owner = THIS_MODULE -+}; -+#endif -+ -+ - static int __init init_pcmciamtd(void) - { -- servinfo_t serv; -- -- info(DRIVER_DESC " " DRIVER_VERSION); -- CardServices(GetCardServicesInfo, &serv); -- if (serv.Revision != CS_RELEASE_CODE) { -- err("Card Services release does not match!"); -- return -1; -- } - - if(buswidth && buswidth != 1 && buswidth != 2) { - info("bad buswidth (%d), using default", buswidth); -@@ -851,15 +860,24 @@ - info("bad mem_type (%d), using default", mem_type); - mem_type = 0; - } -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,68) -+ return pcmcia_register_driver(&pcmciamtd_driver); -+#else - register_pccard_driver(&dev_info, &pcmciamtd_attach, &pcmciamtd_detach); - return 0; -+#endif - } - - - static void __exit exit_pcmciamtd(void) - { - DEBUG(1, DRIVER_DESC " unloading"); -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,68) -+ pcmcia_unregister_driver(&pcmciamtd_driver); -+#else - unregister_pccard_driver(&dev_info); -+#endif - - while(dev_list) { - dev_link_t *link = dev_list; -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/physmap.c linux/drivers/mtd/maps/physmap.c ---- linux-mips-2.4.27/drivers/mtd/maps/physmap.c 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/maps/physmap.c 2004-11-19 10:25:11.947192496 +0100 -@@ -1,179 +1,114 @@ - /* -- * $Id$ -+ * $Id$ - * - * Normal mappings of chips in physical memory -+ * -+ * Copyright (C) 2003 MontaVista Software Inc. -+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net -+ * -+ * 031022 - [jsun] add run-time configure and partition setup - */ - - #include - #include - #include -+#include -+#include - #include - #include - #include - #include -- --#ifdef CONFIG_MTD_PARTITIONS - #include --#endif -- --#define WINDOW_ADDR CONFIG_MTD_PHYSMAP_START --#define WINDOW_SIZE CONFIG_MTD_PHYSMAP_LEN --#define BUSWIDTH CONFIG_MTD_PHYSMAP_BUSWIDTH - - static struct mtd_info *mymtd; - --__u8 physmap_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 physmap_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 physmap_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -+struct map_info physmap_map = {.name = "phys_mapped_flash"}; - --void physmap_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -+#ifdef CONFIG_MTD_PARTITIONS -+static struct mtd_partition *mtd_parts; -+static int mtd_parts_nb; - --void physmap_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -+static int num_physmap_partitions; -+static struct mtd_partition *physmap_partitions; - --void physmap_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -+char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL}; - --void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -+void physmap_set_partitions(struct mtd_partition *parts, int num_parts) - { -- memcpy_toio(map->map_priv_1 + to, from, len); -+ physmap_partitions=parts; -+ num_physmap_partitions=num_parts; - } -- --struct map_info physmap_map = { -- name: "Physically mapped flash", -- size: WINDOW_SIZE, -- buswidth: BUSWIDTH, -- read8: physmap_read8, -- read16: physmap_read16, -- read32: physmap_read32, -- copy_from: physmap_copy_from, -- write8: physmap_write8, -- write16: physmap_write16, -- write32: physmap_write32, -- copy_to: physmap_copy_to --}; -- --#ifdef CONFIG_MTD_PARTITIONS --#ifdef CONFIG_MTD_CMDLINE_PARTS --static struct mtd_partition *mtd_parts = 0; --static int mtd_parts_nb = 0; --#else --static struct mtd_partition physmap_partitions[] = { --/* Put your own partition definitions here */ --#if 0 -- { -- name: "bootROM", -- size: 0x80000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "zImage", -- size: 0x100000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "ramdisk.gz", -- size: 0x300000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "User FS", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -- } --#endif --}; -- --#define NUM_PARTITIONS (sizeof(physmap_partitions)/sizeof(struct mtd_partition)) -- --#endif --#endif -+#endif /* CONFIG_MTD_PARTITIONS */ - - int __init init_physmap(void) - { - static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", 0 }; - const char **type; - -- printk(KERN_NOTICE "physmap flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); -- physmap_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); -+ printk(KERN_NOTICE "physmap flash device: %lx at %lx\n", physmap_map.size, physmap_map.phys); -+ physmap_map.virt = (unsigned long)ioremap(physmap_map.phys, physmap_map.size); - -- if (!physmap_map.map_priv_1) { -+ if (!physmap_map.virt) { - printk("Failed to ioremap\n"); - return -EIO; - } - -+ simple_map_init(&physmap_map); -+ - mymtd = 0; - type = rom_probe_types; - for(; !mymtd && *type; type++) { - mymtd = do_map_probe(*type, &physmap_map); - } - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - -- add_mtd_device(mymtd); - #ifdef CONFIG_MTD_PARTITIONS --#ifdef CONFIG_MTD_CMDLINE_PARTS -- mtd_parts_nb = parse_cmdline_partitions(mymtd, &mtd_parts, -- "phys"); -+ mtd_parts_nb = parse_mtd_partitions(mymtd, part_probes, -+ &mtd_parts, 0); -+ - if (mtd_parts_nb > 0) - { -- printk(KERN_NOTICE -- "Using command line partition definition\n"); - add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb); -+ return 0; - } --#else -- if (NUM_PARTITIONS != 0) -+ -+ if (num_physmap_partitions != 0) - { - printk(KERN_NOTICE - "Using physmap partition definition\n"); -- add_mtd_partitions (mymtd, physmap_partitions, NUM_PARTITIONS); -+ add_mtd_partitions (mymtd, physmap_partitions, num_physmap_partitions); -+ return 0; - } - - #endif --#endif -+ add_mtd_device(mymtd); -+ - return 0; - } - -- iounmap((void *)physmap_map.map_priv_1); -+ iounmap((void *)physmap_map.virt); - return -ENXIO; - } - - static void __exit cleanup_physmap(void) - { -- if (mymtd) { -+#ifdef CONFIG_MTD_PARTITIONS -+ if (mtd_parts_nb) { -+ del_mtd_partitions(mymtd); -+ kfree(mtd_parts); -+ } else if (num_physmap_partitions) { -+ del_mtd_partitions(mymtd); -+ } else { - del_mtd_device(mymtd); -- map_destroy(mymtd); -- } -- if (physmap_map.map_priv_1) { -- iounmap((void *)physmap_map.map_priv_1); -- physmap_map.map_priv_1 = 0; - } -+#else -+ del_mtd_device(mymtd); -+#endif -+ map_destroy(mymtd); -+ -+ iounmap((void *)physmap_map.virt); -+ physmap_map.virt = 0; - } - - module_init(init_physmap); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/pnc2000.c linux/drivers/mtd/maps/pnc2000.c ---- linux-mips-2.4.27/drivers/mtd/maps/pnc2000.c 2001-11-05 21:15:52.000000000 +0100 -+++ linux/drivers/mtd/maps/pnc2000.c 2004-11-19 10:25:11.949192192 +0100 -@@ -5,12 +5,13 @@ - * - * This code is GPL - * -- * $Id$ -+ * $Id$ - */ - - #include - #include - #include -+#include - - #include - #include -@@ -24,58 +25,13 @@ - * MAP DRIVER STUFF - */ - --__u8 pnc_read8(struct map_info *map, unsigned long ofs) --{ -- return *(__u8 *)(WINDOW_ADDR + ofs); --} -- --__u16 pnc_read16(struct map_info *map, unsigned long ofs) --{ -- return *(__u16 *)(WINDOW_ADDR + ofs); --} -- --__u32 pnc_read32(struct map_info *map, unsigned long ofs) --{ -- return *(volatile unsigned int *)(WINDOW_ADDR + ofs); --} -- --void pnc_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy(to, (void *)(WINDOW_ADDR + from), len); --} -- --void pnc_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- *(__u8 *)(WINDOW_ADDR + adr) = d; --} -- --void pnc_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- *(__u16 *)(WINDOW_ADDR + adr) = d; --} -- --void pnc_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- *(__u32 *)(WINDOW_ADDR + adr) = d; --} -- --void pnc_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy((void *)(WINDOW_ADDR + to), from, len); --} - - struct map_info pnc_map = { -- name: "PNC-2000", -- size: WINDOW_SIZE, -- buswidth: 4, -- read8: pnc_read8, -- read16: pnc_read16, -- read32: pnc_read32, -- copy_from: pnc_copy_from, -- write8: pnc_write8, -- write16: pnc_write16, -- write32: pnc_write32, -- copy_to: pnc_copy_to -+ .name = "PNC-2000", -+ .size = WINDOW_SIZE, -+ .buswidth = 4, -+ .phys = 0xFFFFFFFF, -+ .virt = WINDOW_ADDR, - }; - - -@@ -84,19 +40,19 @@ - */ - static struct mtd_partition pnc_partitions[3] = { - { -- name: "PNC-2000 boot firmware", -- size: 0x20000, -- offset: 0 -+ .name = "PNC-2000 boot firmware", -+ .size = 0x20000, -+ .offset = 0 - }, - { -- name: "PNC-2000 kernel", -- size: 0x1a0000, -- offset: 0x20000 -+ .name = "PNC-2000 kernel", -+ .size = 0x1a0000, -+ .offset = 0x20000 - }, - { -- name: "PNC-2000 filesystem", -- size: 0x240000, -- offset: 0x1c0000 -+ .name = "PNC-2000 filesystem", -+ .size = 0x240000, -+ .offset = 0x1c0000 - } - }; - -@@ -110,9 +66,11 @@ - { - printk(KERN_NOTICE "Photron PNC-2000 flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); - -+ simple_map_init(&pnc_map); -+ - mymtd = do_map_probe("cfi_probe", &pnc_map); - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - return add_mtd_partitions(mymtd, pnc_partitions, 3); - } - -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/redwood.c linux/drivers/mtd/maps/redwood.c ---- linux-mips-2.4.27/drivers/mtd/maps/redwood.c 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/maps/redwood.c 2004-11-19 10:25:11.962190216 +0100 -@@ -1,38 +1,23 @@ - /* -- * $Id: -+ * $Id$ - * -- * redwood.c - mapper for IBM Redwood-4/5 board. -+ * drivers/mtd/maps/redwood.c - * -- * Copyright 2001 MontaVista Softare Inc. -+ * FLASH map for the IBM Redwood 4/5/6 boards. - * -- * This program is free software; you can redistribute it and/or modify it -- * under the terms of the 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. -- * -- * History: 12/17/2001 - Armin -- * migrated to use do_map_probe -+ * Author: MontaVista Software, Inc. - * -+ * 2001-2003 (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. - */ - -+#include - #include - #include - #include -+#include - - #include - #include -@@ -40,96 +25,102 @@ - - #include - -+#if !defined (CONFIG_REDWOOD_6) -+ - #define WINDOW_ADDR 0xffc00000 - #define WINDOW_SIZE 0x00400000 - --__u8 redwood_flash_read8(struct map_info *map, unsigned long ofs) --{ -- return *(__u8 *)(map->map_priv_1 + ofs); --} -- --__u16 redwood_flash_read16(struct map_info *map, unsigned long ofs) --{ -- return *(__u16 *)(map->map_priv_1 + ofs); --} -- --__u32 redwood_flash_read32(struct map_info *map, unsigned long ofs) --{ -- return *(volatile unsigned int *)(map->map_priv_1 + ofs); --} -- --void redwood_flash_copy_from(struct map_info *map, void *to, -- unsigned long from, ssize_t len) --{ -- memcpy(to, (void *)(map->map_priv_1 + from), len); --} -- --void redwood_flash_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- *(__u8 *)(map->map_priv_1 + adr) = d; --} -- --void redwood_flash_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- *(__u16 *)(map->map_priv_1 + adr) = d; --} -- --void redwood_flash_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- *(__u32 *)(map->map_priv_1 + adr) = d; --} -- --void redwood_flash_copy_to(struct map_info *map, unsigned long to, -- const void *from, ssize_t len) --{ -- memcpy((void *)(map->map_priv_1 + to), from, len); --} -+#define RW_PART0_OF 0 -+#define RW_PART0_SZ 0x10000 -+#define RW_PART1_OF RW_PART0_SZ -+#define RW_PART1_SZ 0x200000 - 0x10000 -+#define RW_PART2_OF 0x200000 -+#define RW_PART2_SZ 0x10000 -+#define RW_PART3_OF 0x210000 -+#define RW_PART3_SZ 0x200000 - (0x10000 + 0x20000) -+#define RW_PART4_OF 0x3e0000 -+#define RW_PART4_SZ 0x20000 - --struct map_info redwood_flash_map = { -- name: "IBM Redwood", -- size: WINDOW_SIZE, -- buswidth: 2, -- read8: redwood_flash_read8, -- read16: redwood_flash_read16, -- read32: redwood_flash_read32, -- copy_from: redwood_flash_copy_from, -- write8: redwood_flash_write8, -- write16: redwood_flash_write16, -- write32: redwood_flash_write32, -- copy_to: redwood_flash_copy_to -+static struct mtd_partition redwood_flash_partitions[] = { -+ { -+ .name = "Redwood OpenBIOS Vital Product Data", -+ .offset = RW_PART0_OF, -+ .size = RW_PART0_SZ, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ -+ }, -+ { -+ .name = "Redwood kernel", -+ .offset = RW_PART1_OF, -+ .size = RW_PART1_SZ -+ }, -+ { -+ .name = "Redwood OpenBIOS non-volatile storage", -+ .offset = RW_PART2_OF, -+ .size = RW_PART2_SZ, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ -+ }, -+ { -+ .name = "Redwood filesystem", -+ .offset = RW_PART3_OF, -+ .size = RW_PART3_SZ -+ }, -+ { -+ .name = "Redwood OpenBIOS", -+ .offset = RW_PART4_OF, -+ .size = RW_PART4_SZ, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ -+ } - }; - -+#else /* CONFIG_REDWOOD_6 */ -+/* FIXME: the window is bigger - armin */ -+#define WINDOW_ADDR 0xff800000 -+#define WINDOW_SIZE 0x00800000 -+ -+#define RW_PART0_OF 0 -+#define RW_PART0_SZ 0x400000 /* 4 MiB data */ -+#define RW_PART1_OF RW_PART0_OF + RW_PART0_SZ -+#define RW_PART1_SZ 0x10000 /* 64K VPD */ -+#define RW_PART2_OF RW_PART1_OF + RW_PART1_SZ -+#define RW_PART2_SZ 0x400000 - (0x10000 + 0x20000) -+#define RW_PART3_OF RW_PART2_OF + RW_PART2_SZ -+#define RW_PART3_SZ 0x20000 - - static struct mtd_partition redwood_flash_partitions[] = { - { -- name: "Redwood OpenBIOS Vital Product Data", -- offset: 0, -- size: 0x10000, -- mask_flags: MTD_WRITEABLE /* force read-only */ -+ .name = "Redwood filesystem", -+ .offset = RW_PART0_OF, -+ .size = RW_PART0_SZ - }, - { -- name: "Redwood kernel", -- offset: 0x10000, -- size: 0x200000 - 0x10000 -+ .name = "Redwood OpenBIOS Vital Product Data", -+ .offset = RW_PART1_OF, -+ .size = RW_PART1_SZ, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ - }, - { -- name: "Redwood OpenBIOS non-volatile storage", -- offset: 0x200000, -- size: 0x10000, -- mask_flags: MTD_WRITEABLE /* force read-only */ -+ .name = "Redwood kernel", -+ .offset = RW_PART2_OF, -+ .size = RW_PART2_SZ - }, - { -- name: "Redwood filesystem", -- offset: 0x210000, -- size: 0x200000 - (0x10000 + 0x20000) -- }, -- { -- name: "Redwood OpenBIOS", -- offset: 0x3e0000, -- size: 0x20000, -- mask_flags: MTD_WRITEABLE /* force read-only */ -+ .name = "Redwood OpenBIOS", -+ .offset = RW_PART3_OF, -+ .size = RW_PART3_SZ, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ - } - }; -+ -+#endif /* CONFIG_REDWOOD_6 */ -+ -+struct map_info redwood_flash_map = { -+ .name = "IBM Redwood", -+ .size = WINDOW_SIZE, -+ .buswidth = 2, -+ .phys = WINDOW_ADDR, -+}; -+ -+ - #define NUM_REDWOOD_FLASH_PARTITIONS \ - (sizeof(redwood_flash_partitions)/sizeof(redwood_flash_partitions[0])) - -@@ -140,18 +131,19 @@ - printk(KERN_NOTICE "redwood: flash mapping: %x at %x\n", - WINDOW_SIZE, WINDOW_ADDR); - -- redwood_flash_map.map_priv_1 = -+ redwood_flash_map.virt = - (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); - -- if (!redwood_flash_map.map_priv_1) { -+ if (!redwood_flash_map.virt) { - printk("init_redwood_flash: failed to ioremap\n"); - return -EIO; - } -+ simple_map_init(&redwood_flash_map); - - redwood_mtd = do_map_probe("cfi_probe",&redwood_flash_map); - - if (redwood_mtd) { -- redwood_mtd->module = THIS_MODULE; -+ redwood_mtd->owner = THIS_MODULE; - return add_mtd_partitions(redwood_mtd, - redwood_flash_partitions, - NUM_REDWOOD_FLASH_PARTITIONS); -@@ -164,10 +156,15 @@ - { - if (redwood_mtd) { - del_mtd_partitions(redwood_mtd); -- iounmap((void *)redwood_flash_map.map_priv_1); -+ /* moved iounmap after map_destroy - armin */ - map_destroy(redwood_mtd); -+ iounmap((void *)redwood_flash_map.virt); - } - } - - module_init(init_redwood_flash); - module_exit(cleanup_redwood_flash); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("MontaVista Software "); -+MODULE_DESCRIPTION("MTD map driver for the IBM Redwood reference boards"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/rpxlite.c linux/drivers/mtd/maps/rpxlite.c ---- linux-mips-2.4.27/drivers/mtd/maps/rpxlite.c 2001-11-05 21:15:52.000000000 +0100 -+++ linux/drivers/mtd/maps/rpxlite.c 2004-11-19 10:25:11.963190064 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Handle mapping of the flash on the RPX Lite and CLLF boards - */ -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -17,80 +18,31 @@ - - static struct mtd_info *mymtd; - --__u8 rpxlite_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --__u16 rpxlite_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --__u32 rpxlite_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void rpxlite_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); --} -- --void rpxlite_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void rpxlite_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void rpxlite_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void rpxlite_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio((void *)(map->map_priv_1 + to), from, len); --} -- --struct map_info rpxlite_map = { -- name: "RPX", -- size: WINDOW_SIZE, -- buswidth: 4, -- read8: rpxlite_read8, -- read16: rpxlite_read16, -- read32: rpxlite_read32, -- copy_from: rpxlite_copy_from, -- write8: rpxlite_write8, -- write16: rpxlite_write16, -- write32: rpxlite_write32, -- copy_to: rpxlite_copy_to -+static struct map_info rpxlite_map = { -+ .name = "RPX", -+ .size = WINDOW_SIZE, -+ .buswidth = 4, -+ .phys = WINDOW_ADDR, - }; - - int __init init_rpxlite(void) - { - printk(KERN_NOTICE "RPX Lite or CLLF flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR); -- rpxlite_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); -+ rpxlite_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); - -- if (!rpxlite_map.map_priv_1) { -+ if (!rpxlite_map.virt) { - printk("Failed to ioremap\n"); - return -EIO; - } -+ simple_map_init(&rpxlite_map); - mymtd = do_map_probe("cfi_probe", &rpxlite_map); - if (mymtd) { -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - add_mtd_device(mymtd); - return 0; - } - -- iounmap((void *)rpxlite_map.map_priv_1); -+ iounmap((void *)rpxlite_map.virt); - return -ENXIO; - } - -@@ -100,9 +52,9 @@ - del_mtd_device(mymtd); - map_destroy(mymtd); - } -- if (rpxlite_map.map_priv_1) { -- iounmap((void *)rpxlite_map.map_priv_1); -- rpxlite_map.map_priv_1 = 0; -+ if (rpxlite_map.virt) { -+ iounmap((void *)rpxlite_map.virt); -+ rpxlite_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/sa1100-flash.c linux/drivers/mtd/maps/sa1100-flash.c ---- linux-mips-2.4.27/drivers/mtd/maps/sa1100-flash.c 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/maps/sa1100-flash.c 2004-11-19 10:25:11.966189608 +0100 -@@ -3,7 +3,7 @@ - * - * (C) 2000 Nicolas Pitre - * -- * $Id$ -+ * $Id$ - */ - - #include -@@ -11,278 +11,212 @@ - #include - #include - #include -+#include -+#include -+#include - - #include - #include - #include -+#include - - #include -+#include - #include -+#include - -+#include - - #ifndef CONFIG_ARCH_SA1100 - #error This is for SA1100 architecture only - #endif - -+/* -+ * This isnt complete yet, so... -+ */ -+#define CONFIG_MTD_SA1100_STATICMAP 1 - --#define WINDOW_ADDR 0xe8000000 -- --static __u8 sa1100_read8(struct map_info *map, unsigned long ofs) --{ -- return readb(map->map_priv_1 + ofs); --} -- --static __u16 sa1100_read16(struct map_info *map, unsigned long ofs) --{ -- return readw(map->map_priv_1 + ofs); --} -- --static __u32 sa1100_read32(struct map_info *map, unsigned long ofs) --{ -- return readl(map->map_priv_1 + ofs); --} -- --static void sa1100_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy(to, (void *)(map->map_priv_1 + from), len); --} -- --static void sa1100_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, map->map_priv_1 + adr); --} -- --static void sa1100_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, map->map_priv_1 + adr); --} -- --static void sa1100_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- writel(d, map->map_priv_1 + adr); --} -- --static void sa1100_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy((void *)(map->map_priv_1 + to), from, len); --} -- --static struct map_info sa1100_map = { -- name: "SA1100 flash", -- read8: sa1100_read8, -- read16: sa1100_read16, -- read32: sa1100_read32, -- copy_from: sa1100_copy_from, -- write8: sa1100_write8, -- write16: sa1100_write16, -- write32: sa1100_write32, -- copy_to: sa1100_copy_to, -- -- map_priv_1: WINDOW_ADDR, -- map_priv_2: -1, --}; -- -- -+#ifdef CONFIG_MTD_SA1100_STATICMAP - /* - * Here are partition information for all known SA1100-based devices. - * See include/linux/mtd/partitions.h for definition of the mtd_partition - * structure. - * -- * The *_max_flash_size is the maximum possible mapped flash size which -- * is not necessarily the actual flash size. It must be no more than -- * the value specified in the "struct map_desc *_io_desc" mapping -- * definition for the corresponding machine. -+ * Please note: -+ * 1. We no longer support static flash mappings via the machine io_desc -+ * structure. -+ * 2. The flash size given should be the largest flash size that can -+ * be accommodated. -+ * -+ * The MTD layer will detect flash chip aliasing and reduce the size of -+ * the map accordingly. - * - * Please keep these in alphabetical order, and formatted as per existing - * entries. Thanks. - */ - - #ifdef CONFIG_SA1100_ADSBITSY --#define ADSBITSY_FLASH_SIZE 0x02000000 - static struct mtd_partition adsbitsy_partitions[] = { - { -- name: "bootROM", -- size: 0x80000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "zImage", -- size: 0x100000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "ramdisk.gz", -- size: 0x300000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "User FS", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .name = "bootROM", -+ .size = 0x80000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "zImage", -+ .size = 0x100000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "ramdisk.gz", -+ .size = 0x300000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "User FS", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #endif - - #ifdef CONFIG_SA1100_ASSABET - /* Phase 4 Assabet has two 28F160B3 flash parts in bank 0: */ --#define ASSABET4_FLASH_SIZE 0x00400000 - static struct mtd_partition assabet4_partitions[] = { - { -- name: "bootloader", -- size: 0x00020000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "bootloader params", -- size: 0x00020000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "jffs", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .name = "bootloader", -+ .size = 0x00020000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "bootloader params", -+ .size = 0x00020000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "jffs", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - - /* Phase 5 Assabet has two 28F128J3A flash parts in bank 0: */ --#define ASSABET5_FLASH_SIZE 0x02000000 - static struct mtd_partition assabet5_partitions[] = { - { -- name: "bootloader", -- size: 0x00040000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "bootloader params", -- size: 0x00040000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "jffs", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .name = "bootloader", -+ .size = 0x00040000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "bootloader params", -+ .size = 0x00040000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "jffs", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - --#define ASSABET_FLASH_SIZE ASSABET5_FLASH_SIZE - #define assabet_partitions assabet5_partitions - #endif - - #ifdef CONFIG_SA1100_BADGE4 -- - /* -- * 1 x Intel 28F320C3BA100 Advanced+ Boot Block Flash (32 Mi bit) -+ * 1 x Intel 28F320C3 Advanced+ Boot Block Flash (32 Mi bit) - * Eight 4 KiW Parameter Bottom Blocks (64 KiB) - * Sixty-three 32 KiW Main Blocks (4032 Ki b) -+ * -+ * -+ * -+ * 1 x Intel 28F640C3 Advanced+ Boot Block Flash (64 Mi bit) -+ * Eight 4 KiW Parameter Bottom Blocks (64 KiB) -+ * One-hundred-twenty-seven 32 KiW Main Blocks (8128 Ki b) - */ --#define BADGE4_FLASH_SIZE 0x00400000 - static struct mtd_partition badge4_partitions[] = { - { -- name: "BLOB boot loader", -- offset: 0, -- size: 0x0000A000 -- }, { -- name: "params", -- offset: MTDPART_OFS_APPEND, -- size: 0x00006000 -- }, { -- name: "kernel", -- offset: MTDPART_OFS_APPEND, -- size: 0x00100000 -- }, { -- name: "root", -- offset: MTDPART_OFS_APPEND, -- size: MTDPART_SIZ_FULL -+ .name = "BLOB boot loader", -+ .offset = 0, -+ .size = 0x0000A000 -+ }, { -+ .name = "params", -+ .offset = MTDPART_OFS_APPEND, -+ .size = 0x00006000 -+ }, { -+ .name = "root", -+ .offset = MTDPART_OFS_APPEND, -+ .size = MTDPART_SIZ_FULL - } - }; -- - #endif - - - #ifdef CONFIG_SA1100_CERF - #ifdef CONFIG_SA1100_CERF_FLASH_32MB --#define CERF_FLASH_SIZE 0x02000000 --static struct mtd_partition cerf_partitions[] = { -- { -- name: "firmware", -- size: 0x00040000, -- offset: 0, -- }, { -- name: "params", -- size: 0x00040000, -- offset: 0x00040000, -- }, { -- name: "kernel", -- size: 0x00100000, -- offset: 0x00080000, -- }, { -- name: "rootdisk", -- size: 0x01E80000, -- offset: 0x00180000, -- } --}; -+# define CERF_FLASH_SIZE 0x02000000 - #elif defined CONFIG_SA1100_CERF_FLASH_16MB --#define CERF_FLASH_SIZE 0x01000000 -+# define CERF_FLASH_SIZE 0x01000000 -+#elif defined CONFIG_SA1100_CERF_FLASH_8MB -+# define CERF_FLASH_SIZE 0x00800000 -+#else -+# error "Undefined flash size for CERF in sa1100-flash.c" -+#endif -+ - static struct mtd_partition cerf_partitions[] = { - { -- name: "firmware", -- size: 0x00020000, -- offset: 0, -- }, { -- name: "params", -- size: 0x00020000, -- offset: 0x00020000, -- }, { -- name: "kernel", -- size: 0x00100000, -- offset: 0x00040000, -- }, { -- name: "rootdisk", -- size: 0x00EC0000, -- offset: 0x00140000, -+ .name = "Bootloader", -+ .size = 0x00020000, -+ .offset = 0x00000000, -+ }, { -+ .name = "Params", -+ .size = 0x00040000, -+ .offset = 0x00020000, -+ }, { -+ .name = "Kernel", -+ .size = 0x00100000, -+ .offset = 0x00060000, -+ }, { -+ .name = "Filesystem", -+ .size = CERF_FLASH_SIZE-0x00160000, -+ .offset = 0x00160000, - } - }; --#elif defined CONFIG_SA1100_CERF_FLASH_8MB --# error "Unwritten type definition" --#else --# error "Undefined memory orientation for CERF in sa1100-flash.c" --#endif - #endif - - #ifdef CONFIG_SA1100_CONSUS --#define CONSUS_FLASH_SIZE 0x02000000 - static struct mtd_partition consus_partitions[] = { - { -- name: "Consus boot firmware", -- offset: 0, -- size: 0x00040000, -- mask_flags: MTD_WRITABLE, /* force read-only */ -- }, { -- name: "Consus kernel", -- offset: 0x00040000, -- size: 0x00100000, -- mask_flags: 0, -+ .name = "Consus boot firmware", -+ .offset = 0, -+ .size = 0x00040000, -+ .mask_flags = MTD_WRITABLE, /* force read-only */ -+ }, { -+ .name = "Consus kernel", -+ .offset = 0x00040000, -+ .size = 0x00100000, -+ .mask_flags = 0, - }, { -- name: "Consus disk", -- offset: 0x00140000, -+ .name = "Consus disk", -+ .offset = 0x00140000, - /* The rest (up to 16M) for jffs. We could put 0 and - make it find the size automatically, but right now - i have 32 megs. jffs will use all 32 megs if given - the chance, and this leads to horrible problems - when you try to re-flash the image because blob - won't erase the whole partition. */ -- size: 0x01000000 - 0x00140000, -- mask_flags: 0, -+ .size = 0x01000000 - 0x00140000, -+ .mask_flags = 0, - }, { - /* this disk is a secondary disk, which can be used as - needed, for simplicity, make it the size of the other - consus partition, although realistically it could be - the remainder of the disk (depending on the file - system used) */ -- name: "Consus disk2", -- offset: 0x01000000, -- size: 0x01000000 - 0x00140000, -- mask_flags: 0, -+ .name = "Consus disk2", -+ .offset = 0x01000000, -+ .size = 0x01000000 - 0x00140000, -+ .mask_flags = 0, - } - }; - #endif -@@ -292,96 +226,95 @@ - #define FLEXANET_FLASH_SIZE 0x02000000 - static struct mtd_partition flexanet_partitions[] = { - { -- name: "bootloader", -- size: 0x00040000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "bootloader params", -- size: 0x00040000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "kernel", -- size: 0x000C0000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "altkernel", -- size: 0x000C0000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "root", -- size: 0x00400000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "free1", -- size: 0x00300000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "free2", -- size: 0x00300000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -- }, { -- name: "free3", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, -+ .name = "bootloader", -+ .size = 0x00040000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "bootloader params", -+ .size = 0x00040000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "kernel", -+ .size = 0x000C0000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "altkernel", -+ .size = 0x000C0000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "root", -+ .size = 0x00400000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "free1", -+ .size = 0x00300000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "free2", -+ .size = 0x00300000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, -+ }, { -+ .name = "free3", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, - } - }; - #endif - - #ifdef CONFIG_SA1100_FREEBIRD --#define FREEBIRD_FLASH_SIZE 0x02000000 - static struct mtd_partition freebird_partitions[] = { --#if CONFIG_SA1100_FREEBIRD_NEW -+#ifdef CONFIG_SA1100_FREEBIRD_NEW - { -- name: "firmware", -- size: 0x00040000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "kernel", -- size: 0x00080000, -- offset: 0x00040000, -- }, { -- name: "params", -- size: 0x00040000, -- offset: 0x000C0000, -- }, { -- name: "initrd", -- size: 0x00100000, -- offset: 0x00100000, -- }, { -- name: "root cramfs", -- size: 0x00300000, -- offset: 0x00200000, -- }, { -- name: "usr cramfs", -- size: 0x00C00000, -- offset: 0x00500000, -- }, { -- name: "local", -- size: MTDPART_SIZ_FULL, -- offset: 0x01100000, -+ .name = "firmware", -+ .size = 0x00040000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "kernel", -+ .size = 0x00080000, -+ .offset = 0x00040000, -+ }, { -+ .name = "params", -+ .size = 0x00040000, -+ .offset = 0x000C0000, -+ }, { -+ .name = "initrd", -+ .size = 0x00100000, -+ .offset = 0x00100000, -+ }, { -+ .name = "root cramfs", -+ .size = 0x00300000, -+ .offset = 0x00200000, -+ }, { -+ .name = "usr cramfs", -+ .size = 0x00C00000, -+ .offset = 0x00500000, -+ }, { -+ .name = "local", -+ .size = MTDPART_SIZ_FULL, -+ .offset = 0x01100000, - } - #else - { -- size: 0x00040000, -- offset: 0, -+ .size = 0x00040000, -+ .offset = 0, - }, { -- size: 0x000c0000, -- offset: MTDPART_OFS_APPEND, -+ .size = 0x000c0000, -+ .offset = MTDPART_OFS_APPEND, - }, { -- size: 0x00400000, -- offset: MTDPART_OFS_APPEND, -+ .size = 0x00400000, -+ .offset = MTDPART_OFS_APPEND, - }, { -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - #endif - }; -@@ -389,178 +322,215 @@ - - #ifdef CONFIG_SA1100_FRODO - /* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */ --#define FRODO_FLASH_SIZE 0x02000000 - static struct mtd_partition frodo_partitions[] = - { - { -- name: "Boot Loader", -- size: 0x00040000, -- offset: 0x00000000 -- }, { -- name: "Parameter Block", -- size: 0x00040000, -- offset: MTDPART_OFS_APPEND -- }, { -- name: "Linux Kernel", -- size: 0x00100000, -- offset: MTDPART_OFS_APPEND -- }, { -- name: "Ramdisk", -- size: 0x00680000, -- offset: MTDPART_OFS_APPEND -- }, { -- name: "Flash File System", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND -+ .name = "bootloader", -+ .size = 0x00040000, -+ .offset = 0x00000000, -+ .mask_flags = MTD_WRITEABLE -+ }, { -+ .name = "bootloader params", -+ .size = 0x00040000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE -+ }, { -+ .name = "kernel", -+ .size = 0x00100000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE -+ }, { -+ .name = "ramdisk", -+ .size = 0x00400000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE -+ }, { -+ .name = "file system", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND - } - }; - #endif - - #ifdef CONFIG_SA1100_GRAPHICSCLIENT --#define GRAPHICSCLIENT_FLASH_SIZE 0x02000000 - static struct mtd_partition graphicsclient_partitions[] = { - { -- name: "zImage", -- size: 0x100000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "ramdisk.gz", -- size: 0x300000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "User FS", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .name = "zImage", -+ .size = 0x100000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "ramdisk.gz", -+ .size = 0x300000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "User FS", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #endif - - #ifdef CONFIG_SA1100_GRAPHICSMASTER --#define GRAPHICSMASTER_FLASH_SIZE 0x01000000 - static struct mtd_partition graphicsmaster_partitions[] = { - { -- name: "zImage", -- size: 0x100000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -+ .name = "zImage", -+ .size = 0x100000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, - { -- name: "ramdisk.gz", -- size: 0x300000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -+ .name = "ramdisk.gz", -+ .size = 0x300000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, - { -- name: "User FS", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .name = "User FS", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #endif - --#ifdef CONFIG_SA1100_H3600 --#define H3600_FLASH_SIZE 0x02000000 --static struct mtd_partition h3600_partitions[] = { -+#ifdef CONFIG_SA1100_H3XXX -+static struct mtd_partition h3xxx_partitions[] = { - { -- name: "H3600 boot firmware", -- size: 0x00040000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "H3600 kernel", -- size: 0x00080000, -- offset: 0x00040000, -+ .name = "H3XXX boot firmware", -+ .size = 0x00040000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { -- name: "H3600 params", -- size: 0x00040000, -- offset: 0x000C0000, -+#ifdef CONFIG_MTD_2PARTS_IPAQ -+ .name = "H3XXX root jffs2", -+ .size = MTDPART_SIZ_FULL, -+ .offset = 0x00040000, -+#else -+ .name = "H3XXX kernel", -+ .size = 0x00080000, -+ .offset = 0x00040000, -+ }, { -+ .name = "H3XXX params", -+ .size = 0x00040000, -+ .offset = 0x000C0000, - }, { - #ifdef CONFIG_JFFS2_FS -- name: "H3600 root jffs2", -- size: MTDPART_SIZ_FULL, -- offset: 0x00100000, -+ .name = "H3XXX root jffs2", -+ .size = MTDPART_SIZ_FULL, -+ .offset = 0x00100000, - #else -- name: "H3600 initrd", -- size: 0x00100000, -- offset: 0x00100000, -+ .name = "H3XXX initrd", -+ .size = 0x00100000, -+ .offset = 0x00100000, - }, { -- name: "H3600 root cramfs", -- size: 0x00300000, -- offset: 0x00200000, -+ .name = "H3XXX root cramfs", -+ .size = 0x00300000, -+ .offset = 0x00200000, - }, { -- name: "H3600 usr cramfs", -- size: 0x00800000, -- offset: 0x00500000, -+ .name = "H3XXX usr cramfs", -+ .size = 0x00800000, -+ .offset = 0x00500000, - }, { -- name: "H3600 usr local", -- size: MTDPART_SIZ_FULL, -- offset: 0x00d00000, -+ .name = "H3XXX usr local", -+ .size = MTDPART_SIZ_FULL, -+ .offset = 0x00d00000, -+#endif - #endif - } - }; - --static void h3600_set_vpp(struct map_info *map, int vpp) -+static void h3xxx_set_vpp(struct map_info *map, int vpp) - { - assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, vpp); - } -+#else -+#define h3xxx_set_vpp NULL -+#endif -+ -+#ifdef CONFIG_SA1100_HACKKIT -+static struct mtd_partition hackkit_partitions[] = { -+ { -+ .name = "BLOB", -+ .size = 0x00040000, -+ .offset = 0x00000000, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "config", -+ .size = 0x00040000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+ .name = "kernel", -+ .size = 0x00100000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+ .name = "initrd", -+ .size = 0x00180000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+ .name = "rootfs", -+ .size = 0x700000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+ .name = "data", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, -+ } -+}; - #endif - - #ifdef CONFIG_SA1100_HUW_WEBPANEL --#define HUW_WEBPANEL_FLASH_SIZE 0x01000000 - static struct mtd_partition huw_webpanel_partitions[] = { - { -- name: "Loader", -- size: 0x00040000, -- offset: 0, -- }, { -- name: "Sector 1", -- size: 0x00040000, -- offset: MTDPART_OFS_APPEND, -+ .name = "Loader", -+ .size = 0x00040000, -+ .offset = 0, -+ }, { -+ .name = "Sector 1", -+ .size = 0x00040000, -+ .offset = MTDPART_OFS_APPEND, - }, { -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #endif - - #ifdef CONFIG_SA1100_JORNADA720 --#define JORNADA720_FLASH_SIZE 0x02000000 - static struct mtd_partition jornada720_partitions[] = { - { -- name: "JORNADA720 boot firmware", -- size: 0x00040000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -+ .name = "JORNADA720 boot firmware", -+ .size = 0x00040000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { -- name: "JORNADA720 kernel", -- size: 0x000c0000, -- offset: 0x00040000, -+ .name = "JORNADA720 kernel", -+ .size = 0x000c0000, -+ .offset = 0x00040000, - }, { -- name: "JORNADA720 params", -- size: 0x00040000, -- offset: 0x00100000, -+ .name = "JORNADA720 params", -+ .size = 0x00040000, -+ .offset = 0x00100000, - }, { -- name: "JORNADA720 initrd", -- size: 0x00100000, -- offset: 0x00140000, -+ .name = "JORNADA720 initrd", -+ .size = 0x00100000, -+ .offset = 0x00140000, - }, { -- name: "JORNADA720 root cramfs", -- size: 0x00300000, -- offset: 0x00240000, -+ .name = "JORNADA720 root cramfs", -+ .size = 0x00300000, -+ .offset = 0x00240000, - }, { -- name: "JORNADA720 usr cramfs", -- size: 0x00800000, -- offset: 0x00540000, -+ .name = "JORNADA720 usr cramfs", -+ .size = 0x00800000, -+ .offset = 0x00540000, - }, { -- name: "JORNADA720 usr local", -- size: 0 /* will expand to the end of the flash */ -- offset: 0x00d00000, -+ .name = "JORNADA720 usr local", -+ .size = 0, /* will expand to the end of the flash */ -+ .offset = 0x00d00000, - } - }; - --static void jornada720_set_vpp(int vpp) -+static void jornada720_set_vpp(struct map_info *map, int vpp) - { - if (vpp) - PPSR |= 0x80; -@@ -568,454 +538,811 @@ - PPSR &= ~0x80; - PPDR |= 0x80; - } -- -+#else -+#define jornada720_set_vpp NULL - #endif - - #ifdef CONFIG_SA1100_PANGOLIN --#define PANGOLIN_FLASH_SIZE 0x04000000 - static struct mtd_partition pangolin_partitions[] = { - { -- name: "boot firmware", -- size: 0x00080000, -- offset: 0x00000000, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "kernel", -- size: 0x00100000, -- offset: 0x00080000, -- }, { -- name: "initrd", -- size: 0x00280000, -- offset: 0x00180000, -- }, { -- name: "initrd-test", -- size: 0x03C00000, -- offset: 0x00400000, -+ .name = "boot firmware", -+ .size = 0x00080000, -+ .offset = 0x00000000, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "kernel", -+ .size = 0x00100000, -+ .offset = 0x00080000, -+ }, { -+ .name = "initrd", -+ .size = 0x00280000, -+ .offset = 0x00180000, -+ }, { -+ .name = "initrd-test", -+ .size = 0x03C00000, -+ .offset = 0x00400000, - } - }; - #endif - - #ifdef CONFIG_SA1100_PT_SYSTEM3 - /* erase size is 0x40000 == 256k partitions have to have this boundary */ --#define SYSTEM3_FLASH_SIZE 0x01000000 - static struct mtd_partition system3_partitions[] = { - { -- name: "BLOB", -- size: 0x00040000, -- offset: 0x00000000, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "config", -- size: 0x00040000, -- offset: MTDPART_OFS_APPEND, -- }, { -- name: "kernel", -- size: 0x00100000, -- offset: MTDPART_OFS_APPEND, -- }, { -- name: "root", -- size: MTDPART_SIZ_FULL, -- offset: MTDPART_OFS_APPEND, -+ .name = "BLOB", -+ .size = 0x00040000, -+ .offset = 0x00000000, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "config", -+ .size = 0x00040000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+ .name = "kernel", -+ .size = 0x00100000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+ .name = "root", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #endif - - #ifdef CONFIG_SA1100_SHANNON --#define SHANNON_FLASH_SIZE 0x00400000 - static struct mtd_partition shannon_partitions[] = { - { -- name: "BLOB boot loader", -- offset: 0, -- size: 0x20000 -+ .name = "BLOB boot loader", -+ .offset = 0, -+ .size = 0x20000 - }, - { -- name: "kernel", -- offset: MTDPART_OFS_APPEND, -- size: 0xe0000 -+ .name = "kernel", -+ .offset = MTDPART_OFS_APPEND, -+ .size = 0xe0000 - }, - { -- name: "initrd", -- offset: MTDPART_OFS_APPEND, -- size: MTDPART_SIZ_FULL -+ .name = "initrd", -+ .offset = MTDPART_OFS_APPEND, -+ .size = MTDPART_SIZ_FULL - } - }; - - #endif - - #ifdef CONFIG_SA1100_SHERMAN --#define SHERMAN_FLASH_SIZE 0x02000000 - static struct mtd_partition sherman_partitions[] = { - { -- size: 0x50000, -- offset: 0, -+ .size = 0x50000, -+ .offset = 0, - }, { -- size: 0x70000, -- offset: MTDPART_OFS_APPEND, -+ .size = 0x70000, -+ .offset = MTDPART_OFS_APPEND, - }, { -- size: 0x600000, -- offset: MTDPART_OFS_APPEND, -+ .size = 0x600000, -+ .offset = MTDPART_OFS_APPEND, - }, { -- size: 0xA0000, -- offset: MTDPART_OFS_APPEND, -+ .size = 0xA0000, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #endif - - #ifdef CONFIG_SA1100_SIMPAD --#define SIMPAD_FLASH_SIZE 0x02000000 - static struct mtd_partition simpad_partitions[] = { - { -- name: "SIMpad boot firmware", -- size: 0x00080000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "SIMpad kernel", -- size: 0x00100000, -- offset: 0x00080000, -- }, { --#ifdef CONFIG_JFFS2_FS -- name: "SIMpad root jffs2", -- size: MTDPART_SIZ_FULL, -- offset: 0x00180000, -+ .name = "SIMpad boot firmware", -+ .size = 0x00080000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "SIMpad kernel", -+ .size = 0x00100000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+#ifdef CONFIG_ROOT_CRAMFS -+ .name = "SIMpad root cramfs", -+ .size =0x00D80000, -+ .offset = MTDPART_OFS_APPEND -+ -+ }, { -+ .name = "SIMpad local jffs2", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND - #else -- name: "SIMpad initrd", -- size: 0x00300000, -- offset: 0x00180000, -- }, { -- name: "SIMpad root cramfs", -- size: 0x00300000, -- offset: 0x00480000, -- }, { -- name: "SIMpad usr cramfs", -- size: 0x005c0000, -- offset: 0x00780000, -- }, { -- name: "SIMpad usr local", -- size: MTDPART_SIZ_FULL, -- offset: 0x00d40000, -+ .name = "SIMpad root jffs2", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND - #endif - } - }; - #endif /* CONFIG_SA1100_SIMPAD */ - - #ifdef CONFIG_SA1100_STORK --#define STORK_FLASH_SIZE 0x02000000 - static struct mtd_partition stork_partitions[] = { - { -- name: "STORK boot firmware", -- size: 0x00040000, -- offset: 0, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -- }, { -- name: "STORK params", -- size: 0x00040000, -- offset: 0x00040000, -- }, { -- name: "STORK kernel", -- size: 0x00100000, -- offset: 0x00080000, -+ .name = "STORK boot firmware", -+ .size = 0x00040000, -+ .offset = 0, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, { -+ .name = "STORK params", -+ .size = 0x00040000, -+ .offset = 0x00040000, -+ }, { -+ .name = "STORK kernel", -+ .size = 0x00100000, -+ .offset = 0x00080000, - }, { - #ifdef CONFIG_JFFS2_FS -- name: "STORK root jffs2", -- offset: 0x00180000, -- size: MTDPART_SIZ_FULL, -+ .name = "STORK root jffs2", -+ .offset = 0x00180000, -+ .size = MTDPART_SIZ_FULL, - #else -- name: "STORK initrd", -- size: 0x00100000, -- offset: 0x00180000, -- }, { -- name: "STORK root cramfs", -- size: 0x00300000, -- offset: 0x00280000, -- }, { -- name: "STORK usr cramfs", -- size: 0x00800000, -- offset: 0x00580000, -- }, { -- name: "STORK usr local", -- offset: 0x00d80000, -- size: MTDPART_SIZ_FULL, -+ .name = "STORK initrd", -+ .size = 0x00100000, -+ .offset = 0x00180000, -+ }, { -+ .name = "STORK root cramfs", -+ .size = 0x00300000, -+ .offset = 0x00280000, -+ }, { -+ .name = "STORK usr cramfs", -+ .size = 0x00800000, -+ .offset = 0x00580000, -+ }, { -+ .name = "STORK usr local", -+ .offset = 0x00d80000, -+ .size = MTDPART_SIZ_FULL, -+#endif -+ } -+}; - #endif -+ -+#ifdef CONFIG_SA1100_TRIZEPS -+static struct mtd_partition trizeps_partitions[] = { -+ { -+ .name = "Bootloader", -+ .size = 0x00100000, -+ .offset = 0, -+ }, { -+ .name = "Kernel", -+ .size = 0x00100000, -+ .offset = MTDPART_OFS_APPEND, -+ }, { -+ .name = "root", -+ .size = MTDPART_SIZ_FULL, -+ .offset = MTDPART_OFS_APPEND, - } - }; - #endif - - #ifdef CONFIG_SA1100_YOPY --#define YOPY_FLASH_SIZE 0x08000000 - static struct mtd_partition yopy_partitions[] = { - { -- name: "boot firmware", -- size: 0x00040000, -- offset: 0x00000000, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -+ .name = "boot firmware", -+ .size = 0x00040000, -+ .offset = 0x00000000, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { -- name: "kernel", -- size: 0x00080000, -- offset: 0x00080000, -+ .name = "kernel", -+ .size = 0x00080000, -+ .offset = 0x00080000, - }, { -- name: "initrd", -- size: 0x00300000, -- offset: 0x00100000, -+ .name = "initrd", -+ .size = 0x00300000, -+ .offset = 0x00100000, - }, { -- name: "root", -- size: 0x01000000, -- offset: 0x00400000, -+ .name = "root", -+ .size = 0x01000000, -+ .offset = 0x00400000, - } - }; - #endif - --extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts); --extern int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts); -- --static struct mtd_partition *parsed_parts; --static struct mtd_info *mymtd; -- --int __init sa1100_mtd_init(void) -+static int __init sa1100_static_partitions(struct mtd_partition **parts) - { -- struct mtd_partition *parts; -- int nb_parts = 0, ret; -- int parsed_nr_parts = 0; -- const char *part_type; -- unsigned long base = -1UL; -- -- /* Default flash buswidth */ -- sa1100_map.buswidth = (MSC0 & MSC_RBW) ? 2 : 4; -- -- /* -- * Static partition definition selection -- */ -- part_type = "static"; -+ int nb_parts = 0; - - #ifdef CONFIG_SA1100_ADSBITSY - if (machine_is_adsbitsy()) { -- parts = adsbitsy_partitions; -+ *parts = adsbitsy_partitions; - nb_parts = ARRAY_SIZE(adsbitsy_partitions); -- sa1100_map.size = ADSBITSY_FLASH_SIZE; -- sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4; - } - #endif - #ifdef CONFIG_SA1100_ASSABET - if (machine_is_assabet()) { -- parts = assabet_partitions; -+ *parts = assabet_partitions; - nb_parts = ARRAY_SIZE(assabet_partitions); -- sa1100_map.size = ASSABET_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_BADGE4 - if (machine_is_badge4()) { -- parts = badge4_partitions; -+ *parts = badge4_partitions; - nb_parts = ARRAY_SIZE(badge4_partitions); -- sa1100_map.size = BADGE4_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_CERF - if (machine_is_cerf()) { -- parts = cerf_partitions; -+ *parts = cerf_partitions; - nb_parts = ARRAY_SIZE(cerf_partitions); -- sa1100_map.size = CERF_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_CONSUS - if (machine_is_consus()) { -- parts = consus_partitions; -+ *parts = consus_partitions; - nb_parts = ARRAY_SIZE(consus_partitions); -- sa1100_map.size = CONSUS_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_FLEXANET - if (machine_is_flexanet()) { -- parts = flexanet_partitions; -+ *parts = flexanet_partitions; - nb_parts = ARRAY_SIZE(flexanet_partitions); -- sa1100_map.size = FLEXANET_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_FREEBIRD - if (machine_is_freebird()) { -- parts = freebird_partitions; -+ *parts = freebird_partitions; - nb_parts = ARRAY_SIZE(freebird_partitions); -- sa1100_map.size = FREEBIRD_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_FRODO - if (machine_is_frodo()) { -- parts = frodo_partitions; -+ *parts = frodo_partitions; - nb_parts = ARRAY_SIZE(frodo_partitions); -- sa1100_map.size = FRODO_FLASH_SIZE; -- base = 0x00000000; - } - #endif - #ifdef CONFIG_SA1100_GRAPHICSCLIENT - if (machine_is_graphicsclient()) { -- parts = graphicsclient_partitions; -+ *parts = graphicsclient_partitions; - nb_parts = ARRAY_SIZE(graphicsclient_partitions); -- sa1100_map.size = GRAPHICSCLIENT_FLASH_SIZE; -- sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2:4; - } - #endif - #ifdef CONFIG_SA1100_GRAPHICSMASTER - if (machine_is_graphicsmaster()) { -- parts = graphicsmaster_partitions; -+ *parts = graphicsmaster_partitions; - nb_parts = ARRAY_SIZE(graphicsmaster_partitions); -- sa1100_map.size = GRAPHICSMASTER_FLASH_SIZE; -- sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2:4; - } - #endif --#ifdef CONFIG_SA1100_H3600 -- if (machine_is_h3600()) { -- parts = h3600_partitions; -- nb_parts = ARRAY_SIZE(h3600_partitions); -- sa1100_map.size = H3600_FLASH_SIZE; -- sa1100_map.set_vpp = h3600_set_vpp; -+#ifdef CONFIG_SA1100_H3XXX -+ if (machine_is_h3xxx()) { -+ *parts = h3xxx_partitions; -+ nb_parts = ARRAY_SIZE(h3xxx_partitions); -+ } -+#endif -+#ifdef CONFIG_SA1100_HACKKIT -+ if (machine_is_hackkit()) { -+ *parts = hackkit_partitions; -+ nb_parts = ARRAY_SIZE(hackkit_partitions); - } - #endif - #ifdef CONFIG_SA1100_HUW_WEBPANEL - if (machine_is_huw_webpanel()) { -- parts = huw_webpanel_partitions; -+ *parts = huw_webpanel_partitions; - nb_parts = ARRAY_SIZE(huw_webpanel_partitions); -- sa1100_map.size = HUW_WEBPANEL_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_JORNADA720 - if (machine_is_jornada720()) { -- parts = jornada720_partitions; -+ *parts = jornada720_partitions; - nb_parts = ARRAY_SIZE(jornada720_partitions); -- sa1100_map.size = JORNADA720_FLASH_SIZE; -- sa1100_map.set_vpp = jornada720_set_vpp; - } - #endif - #ifdef CONFIG_SA1100_PANGOLIN - if (machine_is_pangolin()) { -- parts = pangolin_partitions; -+ *parts = pangolin_partitions; - nb_parts = ARRAY_SIZE(pangolin_partitions); -- sa1100_map.size = PANGOLIN_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_PT_SYSTEM3 - if (machine_is_pt_system3()) { -- parts = system3_partitions; -+ *parts = system3_partitions; - nb_parts = ARRAY_SIZE(system3_partitions); -- sa1100_map.size = SYSTEM3_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_SHANNON - if (machine_is_shannon()) { -- parts = shannon_partitions; -+ *parts = shannon_partitions; - nb_parts = ARRAY_SIZE(shannon_partitions); -- sa1100_map.size = SHANNON_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_SHERMAN - if (machine_is_sherman()) { -- parts = sherman_partitions; -+ *parts = sherman_partitions; - nb_parts = ARRAY_SIZE(sherman_partitions); -- sa1100_map.size = SHERMAN_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_SIMPAD - if (machine_is_simpad()) { -- parts = simpad_partitions; -+ *parts = simpad_partitions; - nb_parts = ARRAY_SIZE(simpad_partitions); -- sa1100_map.size = SIMPAD_FLASH_SIZE; - } - #endif - #ifdef CONFIG_SA1100_STORK - if (machine_is_stork()) { -- parts = stork_partitions; -+ *parts = stork_partitions; - nb_parts = ARRAY_SIZE(stork_partitions); -- sa1100_map.size = STORK_FLASH_SIZE; -+ } -+#endif -+#ifdef CONFIG_SA1100_TRIZEPS -+ if (machine_is_trizeps()) { -+ *parts = trizeps_partitions; -+ nb_parts = ARRAY_SIZE(trizeps_partitions); - } - #endif - #ifdef CONFIG_SA1100_YOPY - if (machine_is_yopy()) { -- parts = yopy_partitions; -+ *parts = yopy_partitions; - nb_parts = ARRAY_SIZE(yopy_partitions); -- sa1100_map.size = YOPY_FLASH_SIZE; - } - #endif - -+ return nb_parts; -+} -+#endif -+ -+struct sa_info { -+ unsigned long base; -+ unsigned long size; -+ int width; -+ void *vbase; -+ void (*set_vpp)(struct map_info *, int); -+ struct map_info *map; -+ struct mtd_info *mtd; -+ struct resource *res; -+}; -+ -+#define NR_SUBMTD 4 -+ -+static struct sa_info info[NR_SUBMTD]; -+ -+static int __init sa1100_setup_mtd(struct sa_info *sa, int nr, struct mtd_info **rmtd) -+{ -+ struct mtd_info *subdev[nr]; -+ struct map_info *maps; -+ int i, found = 0, ret = 0; -+ - /* -- * For simple flash devices, use ioremap to map the flash. -+ * Allocate the map_info structs in one go. - */ -- if (base != (unsigned long)-1) { -- if (!request_mem_region(base, sa1100_map.size, "flash")) -- return -EBUSY; -- sa1100_map.map_priv_2 = base; -- sa1100_map.map_priv_1 = (unsigned long) -- ioremap(base, sa1100_map.size); -+ maps = kmalloc(sizeof(struct map_info) * nr, GFP_KERNEL); -+ if (!maps) -+ return -ENOMEM; -+ -+ memset(maps, 0, sizeof(struct map_info) * nr); -+ -+ /* -+ * Claim and then map the memory regions. -+ */ -+ for (i = 0; i < nr; i++) { -+ if (sa[i].base == (unsigned long)-1) -+ break; -+ -+ sa[i].res = request_mem_region(sa[i].base, sa[i].size, "sa1100 flash"); -+ if (!sa[i].res) { -+ ret = -EBUSY; -+ break; -+ } -+ -+ sa[i].map = maps + i; -+ -+ sa[i].vbase = ioremap(sa[i].base, sa[i].size); -+ if (!sa[i].vbase) { - ret = -ENOMEM; -- if (!sa1100_map.map_priv_1) -- goto out_err; -+ break; - } - -+ sa[i].map->virt = (unsigned long)sa[i].vbase; -+ sa[i].map->phys = sa[i].base; -+ sa[i].map->set_vpp = sa[i].set_vpp; -+ sa[i].map->buswidth = sa[i].width; -+ sa[i].map->size = sa[i].size; -+ -+ simple_map_init(sa[i].map); -+ - /* - * Now let's probe for the actual flash. Do it here since - * specific machine settings might have been set above. - */ -- printk(KERN_NOTICE "SA1100 flash: probing %d-bit flash bus\n", sa1100_map.buswidth*8); -- mymtd = do_map_probe("cfi_probe", &sa1100_map); -+ sa[i].mtd = do_map_probe("cfi_probe", sa[i].map); -+ if (sa[i].mtd == NULL) { - ret = -ENXIO; -- if (!mymtd) -- goto out_err; -- mymtd->module = THIS_MODULE; -+ break; -+ } -+ sa[i].mtd->owner = THIS_MODULE; -+ subdev[i] = sa[i].mtd; -+ -+ printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, " -+ "%d-bit\n", sa[i].base, sa[i].mtd->size >> 20, -+ sa[i].width * 8); -+ found += 1; -+ } - - /* -- * Dynamic partition selection stuff (might override the static ones) -+ * ENXIO is special. It means we didn't find a chip when -+ * we probed. We need to tear down the mapping, free the -+ * resource and mark it as such. - */ --#ifdef CONFIG_MTD_REDBOOT_PARTS -- if (parsed_nr_parts == 0) { -- int ret = parse_redboot_partitions(mymtd, &parsed_parts); -+ if (ret == -ENXIO) { -+ iounmap(sa[i].vbase); -+ sa[i].vbase = NULL; -+ release_resource(sa[i].res); -+ sa[i].res = NULL; -+ } - -- if (ret > 0) { -- part_type = "RedBoot"; -- parsed_nr_parts = ret; -+ /* -+ * If we found one device, don't bother with concat support. -+ * If we found multiple devices, use concat if we have it -+ * available, otherwise fail. -+ */ -+ if (ret == 0 || ret == -ENXIO) { -+ if (found == 1) { -+ *rmtd = subdev[0]; -+ ret = 0; -+ } else if (found > 1) { -+ /* -+ * We detected multiple devices. Concatenate -+ * them together. -+ */ -+#ifdef CONFIG_MTD_CONCAT -+ *rmtd = mtd_concat_create(subdev, found, -+ "sa1100 flash"); -+ if (*rmtd == NULL) -+ ret = -ENXIO; -+#else -+ printk(KERN_ERR "SA1100 flash: multiple devices " -+ "found but MTD concat support disabled.\n"); -+ ret = -ENXIO; -+#endif - } - } -+ -+ /* -+ * If we failed, clean up. -+ */ -+ if (ret) { -+ do { -+ if (sa[i].mtd) -+ map_destroy(sa[i].mtd); -+ if (sa[i].vbase) -+ iounmap(sa[i].vbase); -+ if (sa[i].res) -+ release_resource(sa[i].res); -+ } while (i--); -+ -+ kfree(maps); -+ } -+ -+ return ret; -+} -+ -+static void __exit sa1100_destroy_mtd(struct sa_info *sa, struct mtd_info *mtd) -+{ -+ int i; -+ -+ del_mtd_partitions(mtd); -+ -+#ifdef CONFIG_MTD_CONCAT -+ if (mtd != sa[0].mtd) -+ mtd_concat_destroy(mtd); - #endif --#ifdef CONFIG_MTD_CMDLINE_PARTS -- if (parsed_nr_parts == 0) { -- int ret = parse_cmdline_partitions(mymtd, &parsed_parts, "sa1100"); -- if (ret > 0) { -- part_type = "Command Line"; -- parsed_nr_parts = ret; -+ -+ for (i = NR_SUBMTD; i >= 0; i--) { -+ if (sa[i].mtd) -+ map_destroy(sa[i].mtd); -+ if (sa[i].vbase) -+ iounmap(sa[i].vbase); -+ if (sa[i].res) -+ release_resource(sa[i].res); - } -+ kfree(sa[0].map); -+} -+ -+/* -+ * A Thought: can we automatically detect the flash? -+ * - Check to see if the region is busy (yes -> failure) -+ * - Is the MSC setup for flash (no -> failure) -+ * - Probe for flash -+ */ -+ -+static struct map_info sa1100_probe_map __initdata = { -+ .name = "SA1100-flash", -+}; -+ -+static void __init sa1100_probe_one_cs(unsigned int msc, unsigned long phys) -+{ -+ struct mtd_info *mtd; -+ -+ printk(KERN_INFO "* Probing 0x%08lx: MSC = 0x%04x %d bit ", -+ phys, msc & 0xffff, msc & MSC_RBW ? 16 : 32); -+ -+ if (check_mem_region(phys, 0x08000000)) { -+ printk("busy\n"); -+ return; - } --#endif - -- if (parsed_nr_parts > 0) { -- parts = parsed_parts; -- nb_parts = parsed_nr_parts; -+ if ((msc & 3) == 1) { -+ printk("wrong type\n"); -+ return; - } - -- if (nb_parts == 0) { -- printk(KERN_NOTICE "SA1100 flash: no partition info available, registering whole flash at once\n"); -- add_mtd_device(mymtd); -- } else { -- printk(KERN_NOTICE "Using %s partition definition\n", part_type); -- add_mtd_partitions(mymtd, parts, nb_parts); -+ sa1100_probe_map.buswidth = msc & MSC_RBW ? 2 : 4; -+ sa1100_probe_map.size = SZ_1M; -+ sa1100_probe_map.phys = phys; -+ sa1100_probe_map.virt = (unsigned long)ioremap(phys, SZ_1M); -+ if (sa1100_probe_map.virt == 0) -+ goto fail; -+ simple_map_init(&sa1100_probe_map); -+ -+ /* Shame cfi_probe blurts out kernel messages... */ -+ mtd = do_map_probe("cfi_probe", &sa1100_probe_map); -+ if (mtd) -+ map_destroy(mtd); -+ iounmap((void *)sa1100_probe_map.virt); -+ -+ if (!mtd) -+ goto fail; -+ -+ printk("pass\n"); -+ return; -+ -+ fail: -+ printk("failed\n"); -+} -+ -+static void __init sa1100_probe_flash(void) -+{ -+ printk(KERN_INFO "-- SA11xx Flash probe. Please report results.\n"); -+ sa1100_probe_one_cs(MSC0, SA1100_CS0_PHYS); -+ sa1100_probe_one_cs(MSC0 >> 16, SA1100_CS1_PHYS); -+ sa1100_probe_one_cs(MSC1, SA1100_CS2_PHYS); -+ sa1100_probe_one_cs(MSC1 >> 16, SA1100_CS3_PHYS); -+ sa1100_probe_one_cs(MSC2, SA1100_CS4_PHYS); -+ sa1100_probe_one_cs(MSC2 >> 16, SA1100_CS5_PHYS); -+ printk(KERN_INFO "-- SA11xx Flash probe complete.\n"); -+} -+ -+static int __init sa1100_locate_flash(void) -+{ -+ int i, nr = -ENODEV; -+ -+ sa1100_probe_flash(); -+ -+ if (machine_is_adsbitsy()) { -+ info[0].base = SA1100_CS1_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_assabet()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ info[1].base = SA1100_CS1_PHYS; /* neponset */ -+ info[1].size = SZ_32M; -+ nr = 2; -+ } -+ if (machine_is_badge4()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_64M; -+ nr = 1; -+ } -+ if (machine_is_cerf()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_consus()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_flexanet()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_freebird()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_frodo()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_graphicsclient()) { -+ info[0].base = SA1100_CS1_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; - } -- return 0; -+ if (machine_is_graphicsmaster()) { -+ info[0].base = SA1100_CS1_PHYS; -+ info[0].size = SZ_16M; -+ nr = 1; -+ } -+ if (machine_is_h3xxx()) { -+ info[0].set_vpp = h3xxx_set_vpp; -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_huw_webpanel()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_16M; -+ nr = 1; -+ } -+ if (machine_is_itsy()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_jornada720()) { -+ info[0].set_vpp = jornada720_set_vpp; -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_nanoengine()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[1].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_pangolin()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_64M; -+ nr = 1; -+ } -+ if (machine_is_pfs168()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_pleb()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_4M; -+ info[1].base = SA1100_CS1_PHYS; -+ info[1].size = SZ_4M; -+ nr = 2; -+ } -+ if (machine_is_pt_system3()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_16M; -+ nr = 1; -+ } -+ if (machine_is_shannon()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_4M; -+ nr = 1; -+ } -+ if (machine_is_sherman()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_simpad()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_16M; -+ info[1].base = SA1100_CS1_PHYS; -+ info[1].size = SZ_16M; -+ nr = 2; -+ } -+ if (machine_is_stork()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_32M; -+ nr = 1; -+ } -+ if (machine_is_trizeps()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_16M; -+ nr = 1; -+ } -+ if (machine_is_victor()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_2M; -+ nr = 1; -+ } -+ if (machine_is_yopy()) { -+ info[0].base = SA1100_CS0_PHYS; -+ info[0].size = SZ_64M; -+ info[1].base = SA1100_CS1_PHYS; -+ info[1].size = SZ_64M; -+ nr = 2; -+ } -+ -+ if (nr < 0) -+ return nr; - -- out_err: -- if (sa1100_map.map_priv_2 != -1) { -- iounmap((void *)sa1100_map.map_priv_1); -- release_mem_region(sa1100_map.map_priv_2, sa1100_map.size); -+ /* -+ * Retrieve the buswidth from the MSC registers. -+ * We currently only implement CS0 and CS1 here. -+ */ -+ for (i = 0; i < nr; i++) { -+ switch (info[i].base) { -+ default: -+ printk(KERN_WARNING "SA1100 flash: unknown base address " -+ "0x%08lx, assuming CS0\n", info[i].base); -+ case SA1100_CS0_PHYS: -+ info[i].width = (MSC0 & MSC_RBW) ? 2 : 4; -+ break; -+ -+ case SA1100_CS1_PHYS: -+ info[i].width = ((MSC0 >> 16) & MSC_RBW) ? 2 : 4; -+ break; - } -- return ret; -+ } -+ -+ return nr; - } - --static void __exit sa1100_mtd_cleanup(void) -+static struct mtd_partition *parsed_parts; -+const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; -+ -+static void __init sa1100_locate_partitions(struct mtd_info *mtd) - { -- if (mymtd) { -- del_mtd_partitions(mymtd); -- map_destroy(mymtd); -- if (parsed_parts) -- kfree(parsed_parts); -+ const char *part_type = NULL; -+ int nr_parts = 0; -+ -+ do { -+ /* -+ * Partition selection stuff. -+ */ -+#ifdef CONFIG_MTD_PARTITIONS -+ nr_parts = parse_mtd_partitions(mtd, part_probes, &parsed_parts, 0); -+ if (nr_parts > 0) { -+ part_type = "dynamic"; -+ break; - } -- if (sa1100_map.map_priv_2 != -1) { -- iounmap((void *)sa1100_map.map_priv_1); -- release_mem_region(sa1100_map.map_priv_2, sa1100_map.size); -+#endif -+#ifdef CONFIG_MTD_SA1100_STATICMAP -+ nr_parts = sa1100_static_partitions(&parsed_parts); -+ if (nr_parts > 0) { -+ part_type = "static"; -+ break; - } -+#endif -+ } while (0); -+ -+ if (nr_parts == 0) { -+ printk(KERN_NOTICE "SA1100 flash: no partition info " -+ "available, registering whole flash\n"); -+ add_mtd_device(mtd); -+ } else { -+ printk(KERN_NOTICE "SA1100 flash: using %s partition " -+ "definition\n", part_type); -+ add_mtd_partitions(mtd, parsed_parts, nr_parts); -+ } -+ -+ /* Always succeeds. */ -+} -+ -+static void __exit sa1100_destroy_partitions(void) -+{ -+ if (parsed_parts) -+ kfree(parsed_parts); -+} -+ -+static struct mtd_info *mymtd; -+ -+static int __init sa1100_mtd_init(void) -+{ -+ int ret; -+ int nr; -+ -+ nr = sa1100_locate_flash(); -+ if (nr < 0) -+ return nr; -+ -+ ret = sa1100_setup_mtd(info, nr, &mymtd); -+ if (ret == 0) -+ sa1100_locate_partitions(mymtd); -+ -+ return ret; -+} -+ -+static void __exit sa1100_mtd_cleanup(void) -+{ -+ sa1100_destroy_mtd(info, mymtd); -+ sa1100_destroy_partitions(); - } - - module_init(sa1100_mtd_init); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/sbc8240.c linux/drivers/mtd/maps/sbc8240.c ---- linux-mips-2.4.27/drivers/mtd/maps/sbc8240.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/maps/sbc8240.c 2004-11-19 10:25:11.967189456 +0100 -@@ -0,0 +1,417 @@ -+/* -+ * Handle mapping of the flash memory access routines on the SBC8240 board. -+ * -+ * Carolyn Smith, Tektronix, Inc. -+ * -+ * This code is GPLed -+ * -+ * $Id$ -+ * -+ */ -+ -+/* -+ * The SBC8240 has 2 flash banks. -+ * Bank 0 is a 512 KiB AMD AM29F040B; 8 x 64 KiB sectors. -+ * It contains the U-Boot code (7 sectors) and the environment (1 sector). -+ * Bank 1 is 4 x 1 MiB AMD AM29LV800BT; 15 x 64 KiB sectors, 1 x 32 KiB sector, -+ * 2 x 8 KiB sectors, 1 x 16 KiB sectors. -+ * Both parts are JEDEC compatible. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#ifdef CONFIG_MTD_PARTITIONS -+#include -+#endif -+ -+#define DEBUG -+ -+#ifdef DEBUG -+# define debugk(fmt,args...) printk(fmt ,##args) -+#else -+# define debugk(fmt,args...) -+#endif -+ -+ -+#define WINDOW_ADDR0 0xFFF00000 /* 512 KiB */ -+#define WINDOW_SIZE0 0x00080000 -+#define BUSWIDTH0 1 -+ -+#define WINDOW_ADDR1 0xFF000000 /* 4 MiB */ -+#define WINDOW_SIZE1 0x00400000 -+#define BUSWIDTH1 8 -+ -+#define MSG_PREFIX "sbc8240:" /* prefix for our printk()'s */ -+#define MTDID "sbc8240-%d" /* for mtdparts= partitioning */ -+ -+ -+static __u8 sbc8240_read8 (struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readb(map->map_priv_1 + ofs); -+} -+ -+static __u16 sbc8240_read16 (struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readw(map->map_priv_1 + ofs); -+} -+ -+static __u32 sbc8240_read32 (struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readl(map->map_priv_1 + ofs); -+} -+ -+unsigned long long result64; -+ -+static __u64 sbc8240_read64 (struct map_info *map, unsigned long ofs) -+{ -+ unsigned long flags, msr, saved_msr; -+ volatile long saved_fr[2]; -+ volatile unsigned long long result; -+ volatile unsigned long *p; -+ -+ save_flags(flags); -+ cli(); -+ -+ /* turn off floating point unavailable exceptions */ -+ -+ __asm__ __volatile__ ( -+ "mfmsr %0" -+ : "=r" (msr) :); -+ -+ saved_msr = msr; -+ msr |= MSR_FP; -+ msr &= ~(MSR_FE0 | MSR_FE1); -+ -+ __asm__ __volatile__ ( -+ "mtmsr %0\n" -+ "isync\n" -+ : : "r" (msr)); -+ -+ /* read the data via a floating point register */ -+ -+ ofs = map->map_priv_1 + ofs; -+ p = (unsigned long *) &result64; -+ -+ __asm__ __volatile__ ( -+ "lfd 1,0(%1)\n" -+ "stfd 1,0(%0)\n" -+ : : "r" (p), "r" (ofs) -+ ); -+ -+ /* restore state */ -+ -+ __asm__ __volatile__ ( -+ "mtmsr %0\n" -+ "isync\n" -+ : : "r" (saved_msr)); -+ -+ restore_flags(flags); -+ -+ p = (unsigned long *) &result64; -+ debugk("sbc8240_read64 ofs 0x%x result 0x%08x%08x\n", ofs, *p, *(p+1)); -+ -+ return result64; -+} -+ -+static void sbc8240_copy_from (struct map_info *map, -+ void *to, unsigned long from, ssize_t len) -+{ -+ memcpy_fromio (to, (void *) (map->map_priv_1 + from), len); -+} -+ -+static void sbc8240_write8 (struct map_info *map, __u8 d, unsigned long adr) -+{ -+ __raw_writeb(d, map->map_priv_1 + adr); -+ mb(); -+} -+ -+static void sbc8240_write16 (struct map_info *map, __u16 d, -+ unsigned long adr) -+{ -+ __raw_writew(d, map->map_priv_1 + adr); -+ mb(); -+} -+ -+static void sbc8240_write32 (struct map_info *map, __u32 d, -+ unsigned long adr) -+{ -+ __raw_writel(d, map->map_priv_1 + adr); -+ mb(); -+} -+ -+static void sbc8240_write64 (struct map_info *map, __u64 data, -+ unsigned long adr) -+{ -+ unsigned long long tmp; -+ unsigned long flags, msr, saved_msr, *p; -+ volatile long saved_fr[2]; -+ -+ save_flags(flags); -+ cli(); -+ -+ /* turn off floating point unavailable exceptions */ -+ -+ __asm__ __volatile__ ( -+ "mfmsr %0" -+ : "=r" (msr) :); -+ -+ saved_msr = msr; -+ msr |= MSR_FP; -+ msr &= ~(MSR_FE0 | MSR_FE1); -+ -+ __asm__ __volatile__ ( -+ "mtmsr %0\n" -+ "isync\n" -+ : : "r" (msr)); -+ -+ -+ /* write the data via a floating point register */ -+ -+ tmp = data; -+ p = (unsigned long *) &tmp; -+ adr = map->map_priv_1 + adr; -+ debugk("sbc8240_write64 adr 0x%x data 0x%08x%08x\n", adr, *p, *(p+1)); -+ -+ __asm__ __volatile__ ( -+ "stfd 1,0(%2)\n" -+ "lfd 1,0(%0)\n" -+ "stfd 1,0(%1)\n" -+ "lfd 1,0(%2)\n" -+ : : "r" (p), "r" (adr), "b" (saved_fr) -+ ); -+ -+ /* restore state */ -+ -+ __asm__ __volatile__ ( -+ "mtmsr %0\n" -+ "isync\n" -+ : : "r" (saved_msr)); -+ -+ restore_flags(flags); -+} -+ -+static void sbc8240_copy_to (struct map_info *map, -+ unsigned long to, const void *from, ssize_t len) -+{ -+ memcpy_toio ((void *) (map->map_priv_1 + to), from, len); -+} -+ -+static struct map_info sbc8240_map[2] = { -+ { -+ .name = "sbc8240 Flash Bank #0", -+ .size = WINDOW_SIZE0, -+ .buswidth = BUSWIDTH0, -+ .read8 = sbc8240_read8, -+ .read16 = sbc8240_read16, -+ .read32 = sbc8240_read32, -+ .read64 = sbc8240_read64, -+ .copy_from = sbc8240_copy_from, -+ .write8 = sbc8240_write8, -+ .write16 = sbc8240_write16, -+ .write32 = sbc8240_write32, -+ .write64 = sbc8240_write64, -+ .copy_to = sbc8240_copy_to -+ }, -+ { -+ .name = "sbc8240 Flash Bank #1", -+ .size = WINDOW_SIZE1, -+ .buswidth = BUSWIDTH1, -+ .read8 = sbc8240_read8, -+ .read16 = sbc8240_read16, -+ .read32 = sbc8240_read32, -+ .read64 = sbc8240_read64, -+ .copy_from = sbc8240_copy_from, -+ .write8 = sbc8240_write8, -+ .write16 = sbc8240_write16, -+ .write32 = sbc8240_write32, -+ .write64 = sbc8240_write64, -+ .copy_to = sbc8240_copy_to -+ } -+}; -+ -+#define NUM_FLASH_BANKS (sizeof(sbc8240_map) / sizeof(struct map_info)) -+ -+/* -+ * The following defines the partition layout of SBC8240 boards. -+ * -+ * See include/linux/mtd/partitions.h for definition of the -+ * mtd_partition structure. -+ * -+ * The *_max_flash_size is the maximum possible mapped flash size -+ * which is not necessarily the actual flash size. It must correspond -+ * to the value specified in the mapping definition defined by the -+ * "struct map_desc *_io_desc" for the corresponding machine. -+ */ -+ -+#ifdef CONFIG_MTD_PARTITIONS -+ -+static struct mtd_partition sbc8240_uboot_partitions [] = { -+ /* Bank 0 */ -+ { -+ .name = "U-boot", /* U-Boot Firmware */ -+ .offset = 0, -+ .size = 0x00070000, /* 7 x 64 KiB sectors */ -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ -+ }, -+ { -+ .name = "environment", /* U-Boot environment */ -+ .offset = 0x00070000, -+ .size = 0x00010000, /* 1 x 64 KiB sector */ -+ }, -+}; -+ -+static struct mtd_partition sbc8240_fs_partitions [] = { -+ { -+ .name = "jffs", /* JFFS filesystem */ -+ .offset = 0, -+ .size = 0x003C0000, /* 4 * 15 * 64KiB */ -+ }, -+ { -+ .name = "tmp32", -+ .offset = 0x003C0000, -+ .size = 0x00020000, /* 4 * 32KiB */ -+ }, -+ { -+ .name = "tmp8a", -+ .offset = 0x003E0000, -+ .size = 0x00008000, /* 4 * 8KiB */ -+ }, -+ { -+ .name = "tmp8b", -+ .offset = 0x003E8000, -+ .size = 0x00008000, /* 4 * 8KiB */ -+ }, -+ { -+ .name = "tmp16", -+ .offset = 0x003F0000, -+ .size = 0x00010000, /* 4 * 16KiB */ -+ } -+}; -+ -+#define NB_OF(x) (sizeof (x) / sizeof (x[0])) -+ -+/* trivial struct to describe partition information */ -+struct mtd_part_def -+{ -+ int nums; -+ unsigned char *type; -+ struct mtd_partition* mtd_part; -+}; -+ -+static struct mtd_info *sbc8240_mtd[NUM_FLASH_BANKS]; -+static struct mtd_part_def sbc8240_part_banks[NUM_FLASH_BANKS]; -+ -+ -+#endif /* CONFIG_MTD_PARTITIONS */ -+ -+ -+int __init init_sbc8240_mtd (void) -+{ -+ static struct _cjs { -+ u_long addr; -+ u_long size; -+ } pt[NUM_FLASH_BANKS] = { -+ { -+ .addr = WINDOW_ADDR0, -+ .size = WINDOW_SIZE0 -+ }, -+ { -+ .addr = WINDOW_ADDR1, -+ .size = WINDOW_SIZE1 -+ }, -+ }; -+ -+ int devicesfound = 0; -+ int i; -+ -+ for (i = 0; i < NUM_FLASH_BANKS; i++) { -+ printk (KERN_NOTICE MSG_PREFIX -+ "Probing 0x%08lx at 0x%08lx\n", pt[i].size, pt[i].addr); -+ -+ sbc8240_map[i].map_priv_1 = -+ (unsigned long) ioremap (pt[i].addr, pt[i].size); -+ if (!sbc8240_map[i].map_priv_1) { -+ printk (MSG_PREFIX "failed to ioremap\n"); -+ return -EIO; -+ } -+ -+ sbc8240_mtd[i] = do_map_probe("jedec_probe", &sbc8240_map[i]); -+ -+ if (sbc8240_mtd[i]) { -+ sbc8240_mtd[i]->module = THIS_MODULE; -+ devicesfound++; -+ } -+ } -+ -+ if (!devicesfound) { -+ printk(KERN_NOTICE MSG_PREFIX -+ "No suppported flash chips found!\n"); -+ return -ENXIO; -+ } -+ -+#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[1].mtd_part = sbc8240_fs_partitions; -+ sbc8240_part_banks[1].type = "static file system"; -+ sbc8240_part_banks[1].nums = NB_OF(sbc8240_fs_partitions); -+ -+ for (i = 0; i < NUM_FLASH_BANKS; i++) { -+ -+ if (!sbc8240_mtd[i]) continue; -+ if (sbc8240_part_banks[i].nums == 0) { -+ printk (KERN_NOTICE MSG_PREFIX -+ "No partition info available, registering whole device\n"); -+ add_mtd_device(sbc8240_mtd[i]); -+ } else { -+ printk (KERN_NOTICE MSG_PREFIX -+ "Using %s partition definition\n", sbc8240_part_banks[i].mtd_part->name); -+ add_mtd_partitions (sbc8240_mtd[i], -+ sbc8240_part_banks[i].mtd_part, -+ sbc8240_part_banks[i].nums); -+ } -+ } -+#else -+ printk(KERN_NOTICE MSG_PREFIX -+ "Registering %d flash banks at once\n", devicesfound); -+ -+ for (i = 0; i < devicesfound; i++) { -+ add_mtd_device(sbc8240_mtd[i]); -+ } -+#endif /* CONFIG_MTD_PARTITIONS */ -+ -+ return devicesfound == 0 ? -ENXIO : 0; -+} -+ -+static void __exit cleanup_sbc8240_mtd (void) -+{ -+ int i; -+ -+ for (i = 0; i < NUM_FLASH_BANKS; i++) { -+ if (sbc8240_mtd[i]) { -+ del_mtd_device (sbc8240_mtd[i]); -+ map_destroy (sbc8240_mtd[i]); -+ } -+ if (sbc8240_map[i].map_priv_1) { -+ iounmap ((void *) sbc8240_map[i].map_priv_1); -+ sbc8240_map[i].map_priv_1 = 0; -+ } -+ } -+} -+ -+module_init (init_sbc8240_mtd); -+module_exit (cleanup_sbc8240_mtd); -+ -+MODULE_LICENSE ("GPL"); -+MODULE_AUTHOR ("Carolyn Smith "); -+MODULE_DESCRIPTION ("MTD map driver for SBC8240 boards"); -+ -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/sbc_gxx.c linux/drivers/mtd/maps/sbc_gxx.c ---- linux-mips-2.4.27/drivers/mtd/maps/sbc_gxx.c 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/maps/sbc_gxx.c 2004-11-19 10:25:11.969189152 +0100 -@@ -17,7 +17,7 @@ - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - -- $Id$ -+ $Id$ - - The SBC-MediaGX / SBC-GXx has up to 16 MiB of - Intel StrataFlash (28F320/28F640) in x8 mode. -@@ -91,14 +91,14 @@ - * single flash device into. If the size if zero we use up to the end of the - * device. */ - static struct mtd_partition partition_info[]={ -- { name: "SBC-GXx flash boot partition", -- offset: 0, -- size: BOOT_PARTITION_SIZE_KiB*1024 }, -- { name: "SBC-GXx flash data partition", -- offset: BOOT_PARTITION_SIZE_KiB*1024, -- size: (DATA_PARTITION_SIZE_KiB)*1024 }, -- { name: "SBC-GXx flash application partition", -- offset: (BOOT_PARTITION_SIZE_KiB+DATA_PARTITION_SIZE_KiB)*1024 } -+ { .name = "SBC-GXx flash boot partition", -+ .offset = 0, -+ .size = BOOT_PARTITION_SIZE_KiB*1024 }, -+ { .name = "SBC-GXx flash data partition", -+ .offset = BOOT_PARTITION_SIZE_KiB*1024, -+ .size = (DATA_PARTITION_SIZE_KiB)*1024 }, -+ { .name = "SBC-GXx flash application partition", -+ .offset = (BOOT_PARTITION_SIZE_KiB+DATA_PARTITION_SIZE_KiB)*1024 } - }; - - #define NUM_PARTITIONS 3 -@@ -203,19 +203,20 @@ - } - - static struct map_info sbc_gxx_map = { -- name: "SBC-GXx flash", -- size: MAX_SIZE_KiB*1024, /* this must be set to a maximum possible amount -+ .name = "SBC-GXx flash", -+ .phys = NO_XIP, -+ .size = MAX_SIZE_KiB*1024, /* this must be set to a maximum possible amount - of flash so the cfi probe routines find all - the chips */ -- buswidth: 1, -- read8: sbc_gxx_read8, -- read16: sbc_gxx_read16, -- read32: sbc_gxx_read32, -- copy_from: sbc_gxx_copy_from, -- write8: sbc_gxx_write8, -- write16: sbc_gxx_write16, -- write32: sbc_gxx_write32, -- copy_to: sbc_gxx_copy_to -+ .buswidth = 1, -+ .read8 = sbc_gxx_read8, -+ .read16 = sbc_gxx_read16, -+ .read32 = sbc_gxx_read32, -+ .copy_from = sbc_gxx_copy_from, -+ .write8 = sbc_gxx_write8, -+ .write16 = sbc_gxx_write16, -+ .write32 = sbc_gxx_write32, -+ .copy_to = sbc_gxx_copy_to - }; - - /* MTD device for all of the flash. */ -@@ -234,12 +235,6 @@ - - int __init init_sbc_gxx(void) - { -- if (check_region(PAGE_IO,PAGE_IO_SIZE) != 0) { -- printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n", -- sbc_gxx_map.name, -- PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 ); -- return -EAGAIN; -- } - iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); - if (!iomapadr) { - printk( KERN_ERR"%s: failed to ioremap memory region\n", -@@ -247,7 +242,14 @@ - return -EIO; - } - -- request_region( PAGE_IO, PAGE_IO_SIZE, "SBC-GXx flash" ); -+ if (!request_region( PAGE_IO, PAGE_IO_SIZE, "SBC-GXx flash")) { -+ printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n", -+ sbc_gxx_map.name, -+ PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 ); -+ iounmap((void *)iomapadr); -+ return -EAGAIN; -+ } -+ - - printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n", - sbc_gxx_map.name, -@@ -261,7 +263,7 @@ - return -ENXIO; - } - -- all_mtd->module=THIS_MODULE; -+ all_mtd->owner = THIS_MODULE; - - /* Create MTD devices for each partition. */ - add_mtd_partitions(all_mtd, partition_info, NUM_PARTITIONS ); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/sc520cdp.c linux/drivers/mtd/maps/sc520cdp.c ---- linux-mips-2.4.27/drivers/mtd/maps/sc520cdp.c 2002-06-27 00:35:50.000000000 +0200 -+++ linux/drivers/mtd/maps/sc520cdp.c 2004-11-19 10:25:11.970189000 +0100 -@@ -16,7 +16,7 @@ - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * -- * $Id$ -+ * $Id$ - * - * - * The SC520CDP is an evaluation board for the Elan SC520 processor available -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -84,88 +85,25 @@ - #define WINDOW_SIZE_1 0x00800000 - #define WINDOW_SIZE_2 0x00080000 - --static __u8 sc520cdp_read8(struct map_info *map, unsigned long ofs) --{ -- return readb(map->map_priv_1 + ofs); --} -- --static __u16 sc520cdp_read16(struct map_info *map, unsigned long ofs) --{ -- return readw(map->map_priv_1 + ofs); --} -- --static __u32 sc520cdp_read32(struct map_info *map, unsigned long ofs) --{ -- return readl(map->map_priv_1 + ofs); --} -- --static void sc520cdp_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); --} -- --static void sc520cdp_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- writeb(d, map->map_priv_1 + adr); --} -- --static void sc520cdp_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- writew(d, map->map_priv_1 + adr); --} -- --static void sc520cdp_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- writel(d, map->map_priv_1 + adr); --} -- --static void sc520cdp_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio((void *)(map->map_priv_1 + to), from, len); --} - - static struct map_info sc520cdp_map[] = { - { -- name: "SC520CDP Flash Bank #0", -- size: WINDOW_SIZE_0, -- buswidth: 4, -- read8: sc520cdp_read8, -- read16: sc520cdp_read16, -- read32: sc520cdp_read32, -- copy_from: sc520cdp_copy_from, -- write8: sc520cdp_write8, -- write16: sc520cdp_write16, -- write32: sc520cdp_write32, -- copy_to: sc520cdp_copy_to, -- map_priv_2: WINDOW_ADDR_0 -+ .name = "SC520CDP Flash Bank #0", -+ .size = WINDOW_SIZE_0, -+ .buswidth = 4, -+ .phys = WINDOW_ADDR_0 - }, - { -- name: "SC520CDP Flash Bank #1", -- size: WINDOW_SIZE_1, -- buswidth: 4, -- read8: sc520cdp_read8, -- read16: sc520cdp_read16, -- read32: sc520cdp_read32, -- copy_from: sc520cdp_copy_from, -- write8: sc520cdp_write8, -- write16: sc520cdp_write16, -- write32: sc520cdp_write32, -- copy_to: sc520cdp_copy_to, -- map_priv_2: WINDOW_ADDR_1 -+ .name = "SC520CDP Flash Bank #1", -+ .size = WINDOW_SIZE_1, -+ .buswidth = 4, -+ .phys = WINDOW_ADDR_1 - }, - { -- name: "SC520CDP DIL Flash", -- size: WINDOW_SIZE_2, -- buswidth: 1, -- read8: sc520cdp_read8, -- read16: sc520cdp_read16, -- read32: sc520cdp_read32, -- copy_from: sc520cdp_copy_from, -- write8: sc520cdp_write8, -- write16: sc520cdp_write16, -- write32: sc520cdp_write32, -- copy_to: sc520cdp_copy_to, -- map_priv_2: WINDOW_ADDR_2 -+ .name = "SC520CDP DIL Flash", -+ .size = WINDOW_SIZE_2, -+ .buswidth = 1, -+ .phys = WINDOW_ADDR_2 - }, - }; - -@@ -255,9 +193,9 @@ - /* map in SC520's MMCR area */ - mmcr = (unsigned long *)ioremap_nocache(SC520_MMCR_BASE, SC520_MMCR_EXTENT); - if(!mmcr) { /* ioremap_nocache failed: skip the PAR reprogramming */ -- /* force map_priv_2 fields to BIOS defaults: */ -+ /* force physical address fields to BIOS defaults: */ - for(i = 0; i < NUM_FLASH_BANKS; i++) -- sc520cdp_map[i].map_priv_2 = par_table[i].default_address; -+ sc520cdp_map[i].phys = par_table[i].default_address; - return; - } - -@@ -282,7 +220,7 @@ - sc520cdp_map[i].name); - printk(KERN_NOTICE "Trying default address 0x%lx\n", - par_table[i].default_address); -- sc520cdp_map[i].map_priv_2 = par_table[i].default_address; -+ sc520cdp_map[i].phys = par_table[i].default_address; - } - } - iounmap((void *)mmcr); -@@ -300,13 +238,18 @@ - #endif - - for (i = 0; i < NUM_FLASH_BANKS; i++) { -- printk(KERN_NOTICE "SC520 CDP flash device: %lx at %lx\n", sc520cdp_map[i].size, sc520cdp_map[i].map_priv_2); -- sc520cdp_map[i].map_priv_1 = (unsigned long)ioremap_nocache(sc520cdp_map[i].map_priv_2, sc520cdp_map[i].size); -+ printk(KERN_NOTICE "SC520 CDP flash device: 0x%lx at 0x%lx\n", -+ sc520cdp_map[i].size, sc520cdp_map[i].phys); - -- if (!sc520cdp_map[i].map_priv_1) { -+ sc520cdp_map[i].virt = (unsigned long)ioremap_nocache(sc520cdp_map[i].phys, sc520cdp_map[i].size); -+ -+ if (!sc520cdp_map[i].virt) { - printk("Failed to ioremap_nocache\n"); - return -EIO; - } -+ -+ simple_map_init(&sc520cdp_map[i]); -+ - mymtd[i] = do_map_probe("cfi_probe", &sc520cdp_map[i]); - if(!mymtd[i]) - mymtd[i] = do_map_probe("jedec_probe", &sc520cdp_map[i]); -@@ -314,11 +257,11 @@ - mymtd[i] = do_map_probe("map_rom", &sc520cdp_map[i]); - - if (mymtd[i]) { -- mymtd[i]->module = THIS_MODULE; -+ mymtd[i]->owner = THIS_MODULE; - ++devices_found; - } - else { -- iounmap((void *)sc520cdp_map[i].map_priv_1); -+ iounmap((void *)sc520cdp_map[i].virt); - } - } - if(devices_found >= 2) { -@@ -346,9 +289,9 @@ - for (i = 0; i < NUM_FLASH_BANKS; i++) { - if (mymtd[i]) - map_destroy(mymtd[i]); -- if (sc520cdp_map[i].map_priv_1) { -- iounmap((void *)sc520cdp_map[i].map_priv_1); -- sc520cdp_map[i].map_priv_1 = 0; -+ if (sc520cdp_map[i].virt) { -+ iounmap((void *)sc520cdp_map[i].virt); -+ sc520cdp_map[i].virt = 0; - } - } - } -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/scb2_flash.c linux/drivers/mtd/maps/scb2_flash.c ---- linux-mips-2.4.27/drivers/mtd/maps/scb2_flash.c 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/maps/scb2_flash.c 2004-11-19 10:25:11.972188696 +0100 -@@ -1,6 +1,6 @@ - /* - * MTD map driver for BIOS Flash on Intel SCB2 boards -- * $Id$ -+ * $Id$ - * Copyright (C) 2002 Sun Microsystems, Inc. - * Tim Hockin - * -@@ -14,7 +14,7 @@ - * try to request it here, but if it fails, we carry on anyway. - * - * This is how the chip is attached, so said the schematic: -- * * a 4 MiB (32 Mb) 16 bit chip -+ * * a 4 MiB (32 Mib) 16 bit chip - * * a 1 MiB memory region - * * A20 and A21 pulled up - * * D8-D15 ignored -@@ -48,6 +48,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -60,65 +61,13 @@ - #define SCB2_ADDR 0xfff00000 - #define SCB2_WINDOW 0x00100000 - --static __u8 scb2_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --static __u16 scb2_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --static __u32 scb2_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --static void scb2_copy_from(struct map_info *map, void *to, -- unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --static void scb2_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --static void scb2_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --static void scb2_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --static void scb2_copy_to(struct map_info *map, unsigned long to, -- const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - static void *scb2_ioaddr; - static struct mtd_info *scb2_mtd; - struct map_info scb2_map = { -- name: "SCB2 BIOS Flash", -- size: 0, -- buswidth: 1, -- read8: scb2_read8, -- read16: scb2_read16, -- read32: scb2_read32, -- copy_from: scb2_copy_from, -- write8: scb2_write8, -- write16: scb2_write16, -- write32: scb2_write32, -- copy_to: scb2_copy_to, -+ .name = "SCB2 BIOS Flash", -+ .size = 0, -+ .buswidth = 1, - }; - static int region_fail; - -@@ -137,6 +86,8 @@ - return -1; - } - -+ /* I wasn't here. I didn't see. dwmw2. */ -+ - /* the chip is sometimes bigger than the map - what a waste */ - mtd->size = map->size; - -@@ -211,9 +162,12 @@ - return -ENOMEM; - } - -- scb2_map.map_priv_1 = (unsigned long)scb2_ioaddr; -+ scb2_map.phys = SCB2_ADDR; -+ scb2_map.virt = (unsigned long)scb2_ioaddr; - scb2_map.size = SCB2_WINDOW; - -+ simple_map_init(&scb2_map); -+ - /* try to find a chip */ - scb2_mtd = do_map_probe("cfi_probe", &scb2_map); - -@@ -225,7 +179,7 @@ - return -ENODEV; - } - -- scb2_mtd->module = THIS_MODULE; -+ scb2_mtd->owner = THIS_MODULE; - if (scb2_fixup_mtd(scb2_mtd) < 0) { - del_mtd_device(scb2_mtd); - map_destroy(scb2_mtd); -@@ -235,7 +189,7 @@ - return -ENODEV; - } - -- printk(KERN_NOTICE MODNAME ": chip size %x at offset %x\n", -+ printk(KERN_NOTICE MODNAME ": chip size 0x%x at offset 0x%x\n", - scb2_mtd->size, SCB2_WINDOW - scb2_mtd->size); - - add_mtd_device(scb2_mtd); -@@ -266,19 +220,19 @@ - - static struct pci_device_id scb2_flash_pci_ids[] __devinitdata = { - { -- vendor: PCI_VENDOR_ID_SERVERWORKS, -- device: PCI_DEVICE_ID_SERVERWORKS_CSB5, -- subvendor: PCI_ANY_ID, -- subdevice: PCI_ANY_ID -+ .vendor = PCI_VENDOR_ID_SERVERWORKS, -+ .device = PCI_DEVICE_ID_SERVERWORKS_CSB5, -+ .subvendor = PCI_ANY_ID, -+ .subdevice = PCI_ANY_ID - }, - { 0, } - }; - - static struct pci_driver scb2_flash_driver = { -- name: "Intel SCB2 BIOS Flash", -- id_table: scb2_flash_pci_ids, -- probe: scb2_flash_probe, -- remove: __devexit_p(scb2_flash_remove), -+ .name = "Intel SCB2 BIOS Flash", -+ .id_table = scb2_flash_pci_ids, -+ .probe = scb2_flash_probe, -+ .remove = __devexit_p(scb2_flash_remove), - }; - - static int __init -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/scx200_docflash.c linux/drivers/mtd/maps/scx200_docflash.c ---- linux-mips-2.4.27/drivers/mtd/maps/scx200_docflash.c 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/maps/scx200_docflash.c 2004-11-19 10:25:11.973188544 +0100 -@@ -2,7 +2,7 @@ - - Copyright (c) 2001,2002 Christer Weinigel - -- $Id$ -+ $Id$ - - National Semiconductor SCx200 flash mapped with DOCCS - */ -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -75,46 +76,9 @@ - #define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0])) - #endif - --static __u8 scx200_docflash_read8(struct map_info *map, unsigned long ofs) --{ -- return __raw_readb(map->map_priv_1 + ofs); --} -- --static __u16 scx200_docflash_read16(struct map_info *map, unsigned long ofs) --{ -- return __raw_readw(map->map_priv_1 + ofs); --} -- --static void scx200_docflash_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --static void scx200_docflash_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --static void scx200_docflash_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --static void scx200_docflash_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - static struct map_info scx200_docflash_map = { - .name = "NatSemi SCx200 DOCCS Flash", -- .read8 = scx200_docflash_read8, -- .read16 = scx200_docflash_read16, -- .copy_from = scx200_docflash_copy_from, -- .write8 = scx200_docflash_write8, -- .write16 = scx200_docflash_write16, -- .copy_to = scx200_docflash_copy_to - }; - - int __init init_scx200_docflash(void) -@@ -213,8 +177,11 @@ - else - scx200_docflash_map.buswidth = 2; - -- scx200_docflash_map.map_priv_1 = (unsigned long)ioremap(docmem.start, scx200_docflash_map.size); -- if (!scx200_docflash_map.map_priv_1) { -+ simple_map_init(&scx200_docflash_map); -+ -+ scx200_docflash_map.phys = docmem.start; -+ scx200_docflash_map.virt = (unsigned long)ioremap(docmem.start, scx200_docflash_map.size); -+ if (!scx200_docflash_map.virt) { - printk(KERN_ERR NAME ": failed to ioremap the flash\n"); - release_resource(&docmem); - return -EIO; -@@ -223,7 +190,7 @@ - mymtd = do_map_probe(flashtype, &scx200_docflash_map); - if (!mymtd) { - printk(KERN_ERR NAME ": unable to detect flash\n"); -- iounmap((void *)scx200_docflash_map.map_priv_1); -+ iounmap((void *)scx200_docflash_map.virt); - release_resource(&docmem); - return -ENXIO; - } -@@ -231,7 +198,7 @@ - if (size < mymtd->size) - printk(KERN_WARNING NAME ": warning, flash mapping is smaller than flash size\n"); - -- mymtd->module = THIS_MODULE; -+ mymtd->owner = THIS_MODULE; - - #if PARTITION - partition_info[3].offset = mymtd->size-partition_info[3].size; -@@ -253,8 +220,8 @@ - #endif - map_destroy(mymtd); - } -- if (scx200_docflash_map.map_priv_1) { -- iounmap((void *)scx200_docflash_map.map_priv_1); -+ if (scx200_docflash_map.virt) { -+ iounmap((void *)scx200_docflash_map.virt); - release_resource(&docmem); - } - } -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/solutionengine.c linux/drivers/mtd/maps/solutionengine.c ---- linux-mips-2.4.27/drivers/mtd/maps/solutionengine.c 2002-06-27 00:35:50.000000000 +0200 -+++ linux/drivers/mtd/maps/solutionengine.c 2004-11-19 10:25:11.975188240 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Flash and EPROM on Hitachi Solution Engine and similar boards. - * -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -18,60 +19,39 @@ - #include - - --extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts); -- --__u32 soleng_read32(struct map_info *map, unsigned long ofs) --{ -- return __raw_readl(map->map_priv_1 + ofs); --} -- --void soleng_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void soleng_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- -- - static struct mtd_info *flash_mtd; - static struct mtd_info *eprom_mtd; - - static struct mtd_partition *parsed_parts; - - struct map_info soleng_eprom_map = { -- name: "Solution Engine EPROM", -- size: 0x400000, -- buswidth: 4, -- copy_from: soleng_copy_from, -+ .name = "Solution Engine EPROM", -+ .size = 0x400000, -+ .buswidth = 4, - }; - - struct map_info soleng_flash_map = { -- name: "Solution Engine FLASH", -- size: 0x400000, -- buswidth: 4, -- read32: soleng_read32, -- copy_from: soleng_copy_from, -- write32: soleng_write32, -+ .name = "Solution Engine FLASH", -+ .size = 0x400000, -+ .buswidth = 4, - }; - -+static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; -+ - #ifdef CONFIG_MTD_SUPERH_RESERVE - static struct mtd_partition superh_se_partitions[] = { - /* Reserved for boot code, read-only */ - { -- name: "flash_boot", -- offset: 0x00000000, -- size: CONFIG_MTD_SUPERH_RESERVE, -- mask_flags: MTD_WRITEABLE, -+ .name = "flash_boot", -+ .offset = 0x00000000, -+ .size = CONFIG_MTD_SUPERH_RESERVE, -+ .mask_flags = MTD_WRITEABLE, - }, - /* All else is writable (e.g. JFFS) */ - { -- name: "Flash FS", -- offset: MTDPART_OFS_NXTBLK, -- size: MTDPART_SIZ_FULL, -+ .name = "Flash FS", -+ .offset = MTDPART_OFS_NXTBLK, -+ .size = MTDPART_SIZ_FULL, - } - }; - #endif /* CONFIG_MTD_SUPERH_RESERVE */ -@@ -81,16 +61,22 @@ - int nr_parts = 0; - - /* First probe at offset 0 */ -- soleng_flash_map.map_priv_1 = P2SEGADDR(0); -- soleng_eprom_map.map_priv_1 = P1SEGADDR(0x01000000); -+ soleng_flash_map.phys = 0; -+ soleng_flash_map.virt = P2SEGADDR(0); -+ soleng_eprom_map.phys = 0x01000000; -+ soleng_eprom_map.virt = P1SEGADDR(0x01000000); -+ simple_map_init(&soleng_eprom_map); -+ simple_map_init(&soleng_flash_map); - - printk(KERN_NOTICE "Probing for flash chips at 0x00000000:\n"); - flash_mtd = do_map_probe("cfi_probe", &soleng_flash_map); - if (!flash_mtd) { - /* Not there. Try swapping */ - printk(KERN_NOTICE "Probing for flash chips at 0x01000000:\n"); -- soleng_flash_map.map_priv_1 = P2SEGADDR(0x01000000); -- soleng_eprom_map.map_priv_1 = P1SEGADDR(0); -+ soleng_flash_map.phys = 0x01000000; -+ soleng_flash_map.virt = P2SEGADDR(0x01000000); -+ soleng_eprom_map.phys = 0; -+ soleng_eprom_map.virt = P1SEGADDR(0); - flash_mtd = do_map_probe("cfi_probe", &soleng_flash_map); - if (!flash_mtd) { - /* Eep. */ -@@ -99,25 +85,20 @@ - } - } - printk(KERN_NOTICE "Solution Engine: Flash at 0x%08lx, EPROM at 0x%08lx\n", -- soleng_flash_map.map_priv_1 & 0x1fffffff, -- soleng_eprom_map.map_priv_1 & 0x1fffffff); -- flash_mtd->module = THIS_MODULE; -+ soleng_flash_map.phys & 0x1fffffff, -+ soleng_eprom_map.phys & 0x1fffffff); -+ flash_mtd->owner = THIS_MODULE; - - eprom_mtd = do_map_probe("map_rom", &soleng_eprom_map); - if (eprom_mtd) { -- eprom_mtd->module = THIS_MODULE; -+ eprom_mtd->owner = THIS_MODULE; - add_mtd_device(eprom_mtd); - } - --#ifdef CONFIG_MTD_REDBOOT_PARTS -- nr_parts = parse_redboot_partitions(flash_mtd, &parsed_parts); -- if (nr_parts > 0) -- printk(KERN_NOTICE "Found RedBoot partition table.\n"); -- else if (nr_parts < 0) -- printk(KERN_NOTICE "Error looking for RedBoot partitions.\n"); --#endif /* CONFIG_MTD_REDBOOT_PARTS */ -+ nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0); -+ - #if CONFIG_MTD_SUPERH_RESERVE -- if (nr_parts == 0) { -+ if (nr_parts <= 0) { - printk(KERN_NOTICE "Using configured partition at 0x%08x.\n", - CONFIG_MTD_SUPERH_RESERVE); - parsed_parts = superh_se_partitions; -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/sun_uflash.c linux/drivers/mtd/maps/sun_uflash.c ---- linux-mips-2.4.27/drivers/mtd/maps/sun_uflash.c 2001-11-05 21:15:52.000000000 +0100 -+++ linux/drivers/mtd/maps/sun_uflash.c 2004-11-19 10:25:11.976188088 +0100 -@@ -1,4 +1,4 @@ --/* $Id$ -+/* $Id$ - * - * sun_uflash - Driver implementation for user-programmable flash - * present on many Sun Microsystems SME boardsets. -@@ -48,60 +48,11 @@ - struct list_head list; - }; - --__u8 uflash_read8(struct map_info *map, unsigned long ofs) --{ -- return(__raw_readb(map->map_priv_1 + ofs)); --} -- --__u16 uflash_read16(struct map_info *map, unsigned long ofs) --{ -- return(__raw_readw(map->map_priv_1 + ofs)); --} -- --__u32 uflash_read32(struct map_info *map, unsigned long ofs) --{ -- return(__raw_readl(map->map_priv_1 + ofs)); --} -- --void uflash_copy_from(struct map_info *map, void *to, unsigned long from, -- ssize_t len) --{ -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void uflash_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- __raw_writeb(d, map->map_priv_1 + adr); --} -- --void uflash_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- __raw_writew(d, map->map_priv_1 + adr); --} -- --void uflash_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- __raw_writel(d, map->map_priv_1 + adr); --} -- --void uflash_copy_to(struct map_info *map, unsigned long to, const void *from, -- ssize_t len) --{ -- memcpy_toio(map->map_priv_1 + to, from, len); --} - - struct map_info uflash_map_templ = { -- name: "SUNW,???-????", -- size: UFLASH_WINDOW_SIZE, -- buswidth: UFLASH_BUSWIDTH, -- read8: uflash_read8, -- read16: uflash_read16, -- read32: uflash_read32, -- copy_from: uflash_copy_from, -- write8: uflash_write8, -- write16: uflash_write16, -- write32: uflash_write32, -- copy_to: uflash_copy_to -+ .name = "SUNW,???-????", -+ .size = UFLASH_WINDOW_SIZE, -+ .buswidth = UFLASH_BUSWIDTH, - }; - - int uflash_devinit(struct linux_ebus_device* edev) -@@ -145,20 +96,22 @@ - if(0 != pdev->name && 0 < strlen(pdev->name)) { - pdev->map.name = pdev->name; - } -- -- pdev->map.map_priv_1 = -+ pdev->phys = edev->resource[0].start; -+ pdev->virt = - (unsigned long)ioremap_nocache(edev->resource[0].start, pdev->map.size); -- if(0 == pdev->map.map_priv_1) { -+ if(0 == pdev->map.virt) { - printk("%s: failed to map device\n", __FUNCTION__); - kfree(pdev->name); - kfree(pdev); - return(-1); - } - -+ simple_map_init(&pdev->map); -+ - /* MTD registration */ - pdev->mtd = do_map_probe("cfi_probe", &pdev->map); - if(0 == pdev->mtd) { -- iounmap((void *)pdev->map.map_priv_1); -+ iounmap((void *)pdev->map.virt); - kfree(pdev->name); - kfree(pdev); - return(-ENXIO); -@@ -166,7 +119,7 @@ - - list_add(&pdev->list, &device_list); - -- pdev->mtd->module = THIS_MODULE; -+ pdev->mtd->owner = THIS_MODULE; - - add_mtd_device(pdev->mtd); - return(0); -@@ -211,9 +164,9 @@ - del_mtd_device(udev->mtd); - map_destroy(udev->mtd); - } -- if(0 != udev->map.map_priv_1) { -- iounmap((void*)udev->map.map_priv_1); -- udev->map.map_priv_1 = 0; -+ if(0 != udev->map.virt) { -+ iounmap((void*)udev->map.virt); -+ udev->map.virt = 0; - } - if(0 != udev->name) { - kfree(udev->name); -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/tqm8xxl.c linux/drivers/mtd/maps/tqm8xxl.c ---- linux-mips-2.4.27/drivers/mtd/maps/tqm8xxl.c 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/maps/tqm8xxl.c 2004-11-19 10:25:11.978187784 +0100 -@@ -2,7 +2,7 @@ - * Handle mapping of the flash memory access routines - * on TQM8xxL based devices. - * -- * $Id$ -+ * $Id$ - * - * based on rpxlite.c - * -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -51,46 +52,6 @@ - static unsigned long num_banks; - static unsigned long start_scan_addr; - --__u8 tqm8xxl_read8(struct map_info *map, unsigned long ofs) --{ -- return *((__u8 *)(map->map_priv_1 + ofs)); --} -- --__u16 tqm8xxl_read16(struct map_info *map, unsigned long ofs) --{ -- return *((__u16 *)(map->map_priv_1 + ofs)); --} -- --__u32 tqm8xxl_read32(struct map_info *map, unsigned long ofs) --{ -- return *((__u32 *)(map->map_priv_1 + ofs)); --} -- --void tqm8xxl_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); --} -- --void tqm8xxl_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- *((__u8 *)(map->map_priv_1 + adr)) = d; --} -- --void tqm8xxl_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- *((__u16 *)( map->map_priv_1 + adr)) = d; --} -- --void tqm8xxl_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- *((__u32 *)(map->map_priv_1 + adr)) = d; --} -- --void tqm8xxl_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy_toio((void *)(map->map_priv_1 + to), from, len); --} -- - /* - * Here are partition information for all known TQM8xxL series devices. - * See include/linux/mtd/partitions.h for definition of the mtd_partition -@@ -107,50 +68,48 @@ - static unsigned long tqm8xxl_max_flash_size = 0x00800000; - - /* partition definition for first flash bank -- * also ref. to "drivers\char\flash_config.c" -+ * (cf. "drivers/char/flash_config.c") - */ - static struct mtd_partition tqm8xxl_partitions[] = { - { -- name: "ppcboot", -- offset: 0x00000000, -- size: 0x00020000, /* 128KB */ -- mask_flags: MTD_WRITEABLE, /* force read-only */ -+ .name = "ppcboot", -+ .offset = 0x00000000, -+ .size = 0x00020000, /* 128KB */ -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, - { -- name: "kernel", /* default kernel image */ -- offset: 0x00020000, -- size: 0x000e0000, -- mask_flags: MTD_WRITEABLE, /* force read-only */ -+ .name = "kernel", /* default kernel image */ -+ .offset = 0x00020000, -+ .size = 0x000e0000, -+ .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, - { -- name: "user", -- offset: 0x00100000, -- size: 0x00100000, -+ .name = "user", -+ .offset = 0x00100000, -+ .size = 0x00100000, - }, - { -- name: "initrd", -- offset: 0x00200000, -- size: 0x00200000, -+ .name = "initrd", -+ .offset = 0x00200000, -+ .size = 0x00200000, - } - }; --/* partition definition for second flahs bank */ -+/* partition definition for second flash bank */ - static struct mtd_partition tqm8xxl_fs_partitions[] = { - { -- name: "cramfs", -- offset: 0x00000000, -- size: 0x00200000, -+ .name = "cramfs", -+ .offset = 0x00000000, -+ .size = 0x00200000, - }, - { -- name: "jffs", -- offset: 0x00200000, -- size: 0x00200000, -- //size: MTDPART_SIZ_FULL, -+ .name = "jffs", -+ .offset = 0x00200000, -+ .size = 0x00200000, -+ .//size = MTDPART_SIZ_FULL, - } - }; - #endif - --#define NB_OF(x) (sizeof(x)/sizeof(x[0])) -- - int __init init_tqm_mtd(void) - { - int idx = 0, ret = 0; -@@ -160,67 +119,73 @@ - - flash_addr = bd->bi_flashstart; - flash_size = bd->bi_flashsize; -- //request maximum flash size address spzce -+ -+ //request maximum flash size address space - start_scan_addr = (unsigned long)ioremap(flash_addr, flash_size); - if (!start_scan_addr) { -- //printk("%s:Failed to ioremap address:0x%x\n", __FUNCTION__, FLASH_ADDR); -- printk("%s:Failed to ioremap address:0x%x\n", __FUNCTION__, flash_addr); -+ printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __FUNCTION__, flash_addr); - return -EIO; - } -- for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) -- { -+ -+ for (idx = 0 ; idx < FLASH_BANK_MAX ; idx++) { - if(mtd_size >= flash_size) - break; - -- printk("%s: chip probing count %d\n", __FUNCTION__, idx); -+ printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx); - - map_banks[idx] = (struct map_info *)kmalloc(sizeof(struct map_info), GFP_KERNEL); -- if(map_banks[idx] == NULL) -- { -- //return -ENOMEM; -+ if(map_banks[idx] == NULL) { - ret = -ENOMEM; -+ /* FIXME: What if some MTD devices were probed already? */ - goto error_mem; - } -+ - memset((void *)map_banks[idx], 0, sizeof(struct map_info)); - map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL); -- if(map_banks[idx]->name == NULL) -- { -- //return -ENOMEM; -+ -+ if (!map_banks[idx]->name) { - ret = -ENOMEM; -+ /* FIXME: What if some MTD devices were probed already? */ - goto error_mem; - } -- memset((void *)map_banks[idx]->name, 0, 16); -- - sprintf(map_banks[idx]->name, "TQM8xxL%d", idx); -+ - map_banks[idx]->size = flash_size; - map_banks[idx]->buswidth = 4; -- map_banks[idx]->read8 = tqm8xxl_read8; -- map_banks[idx]->read16 = tqm8xxl_read16; -- map_banks[idx]->read32 = tqm8xxl_read32; -- map_banks[idx]->copy_from = tqm8xxl_copy_from; -- map_banks[idx]->write8 = tqm8xxl_write8; -- map_banks[idx]->write16 = tqm8xxl_write16; -- map_banks[idx]->write32 = tqm8xxl_write32; -- map_banks[idx]->copy_to = tqm8xxl_copy_to; -+ -+ simple_map_init(map_banks[idx]); -+ -+ map_banks[idx]->virt = start_scan_addr; -+ map_banks[idx]->phys = flash_addr; -+ /* FIXME: This looks utterly bogus, but I'm trying to -+ preserve the behaviour of the original (shown here)... -+ - map_banks[idx]->map_priv_1 = - start_scan_addr + ((idx > 0) ? - (mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0); -+ */ -+ -+ if (idx && mtd_banks[idx-1]) { -+ map_banks[idx]->virt += mtd_banks[idx-1]->size; -+ map_banks[idx]->phys += mtd_banks[idx-1]->size; -+ } -+ - //start to probe flash chips - mtd_banks[idx] = do_map_probe("cfi_probe", map_banks[idx]); -- if(mtd_banks[idx]) -- { -- mtd_banks[idx]->module = THIS_MODULE; -+ -+ if (mtd_banks[idx]) { -+ mtd_banks[idx]->owner = THIS_MODULE; - mtd_size += mtd_banks[idx]->size; - num_banks++; -- printk("%s: bank%d, name:%s, size:%dbytes \n", __FUNCTION__, num_banks, -+ -+ printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __FUNCTION__, num_banks, - mtd_banks[idx]->name, mtd_banks[idx]->size); - } - } - - /* no supported flash chips found */ -- if(!num_banks) -- { -- printk("TQM8xxL: No support flash chips found!\n"); -+ if (!num_banks) { -+ printk(KERN_NOTICE "TQM8xxL: No support flash chips found!\n"); - ret = -ENXIO; - goto error_mem; - } -@@ -231,12 +196,13 @@ - */ - part_banks[0].mtd_part = tqm8xxl_partitions; - part_banks[0].type = "Static image"; -- part_banks[0].nums = NB_OF(tqm8xxl_partitions); -+ part_banks[0].nums = ARRAY_SIZE(tqm8xxl_partitions); -+ - part_banks[1].mtd_part = tqm8xxl_fs_partitions; - part_banks[1].type = "Static file system"; -- part_banks[1].nums = NB_OF(tqm8xxl_fs_partitions); -- for(idx = 0; idx < num_banks ; idx++) -- { -+ part_banks[1].nums = ARRAY_SIZE(tqm8xxl_fs_partitions); -+ -+ for(idx = 0; idx < num_banks ; idx++) { - if (part_banks[idx].nums == 0) { - printk(KERN_NOTICE "TQM flash%d: no partition info available, registering whole flash at once\n", idx); - add_mtd_device(mtd_banks[idx]); -@@ -254,12 +220,9 @@ - #endif - return 0; - error_mem: -- for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) -- { -- if(map_banks[idx] != NULL) -- { -- if(map_banks[idx]->name != NULL) -- { -+ for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) { -+ if(map_banks[idx] != NULL) { -+ if(map_banks[idx]->name != NULL) { - kfree(map_banks[idx]->name); - map_banks[idx]->name = NULL; - } -@@ -267,18 +230,15 @@ - map_banks[idx] = NULL; - } - } -- //return -ENOMEM; - error: - iounmap((void *)start_scan_addr); -- //return -ENXIO; - return ret; - } - - static void __exit cleanup_tqm_mtd(void) - { - unsigned int idx = 0; -- for(idx = 0 ; idx < num_banks ; idx++) -- { -+ for(idx = 0 ; idx < num_banks ; idx++) { - /* destroy mtd_info previously allocated */ - if (mtd_banks[idx]) { - del_mtd_partitions(mtd_banks[idx]); -@@ -288,6 +248,7 @@ - kfree(map_banks[idx]->name); - kfree(map_banks[idx]); - } -+ - if (start_scan_addr) { - iounmap((void *)start_scan_addr); - start_scan_addr = 0; -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/tsunami_flash.c linux/drivers/mtd/maps/tsunami_flash.c ---- linux-mips-2.4.27/drivers/mtd/maps/tsunami_flash.c 2002-06-27 00:35:50.000000000 +0200 -+++ linux/drivers/mtd/maps/tsunami_flash.c 2004-11-19 10:25:11.979187632 +0100 -@@ -2,11 +2,13 @@ - * tsunami_flash.c - * - * flash chip on alpha ds10... -- * $Id$ -+ * $Id$ - */ - #include - #include -+#include - #include -+#include - - #define FLASH_ENABLE_PORT 0x00C00001 - #define FLASH_ENABLE_BYTE 0x01 -@@ -58,18 +60,12 @@ - static struct map_info tsunami_flash_map = { - .name = "flash chip on the Tsunami TIG bus", - .size = MAX_TIG_FLASH_SIZE, -+ .phys = NO_XIP; - .buswidth = 1, - .read8 = tsunami_flash_read8, -- .read16 = 0, -- .read32 = 0, - .copy_from = tsunami_flash_copy_from, - .write8 = tsunami_flash_write8, -- .write16 = 0, -- .write32 = 0, - .copy_to = tsunami_flash_copy_to, -- .set_vpp = 0, -- .map_priv_1 = 0, -- - }; - - static struct mtd_info *tsunami_flash_mtd; -@@ -99,7 +95,7 @@ - tsunami_flash_mtd = do_map_probe(*type, &tsunami_flash_map); - } - if (tsunami_flash_mtd) { -- tsunami_flash_mtd->module = THIS_MODULE; -+ tsunami_flash_mtd->owner = THIS_MODULE; - add_mtd_device(tsunami_flash_mtd); - return 0; - } -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/uclinux.c linux/drivers/mtd/maps/uclinux.c ---- linux-mips-2.4.27/drivers/mtd/maps/uclinux.c 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/maps/uclinux.c 2004-11-19 10:25:11.980187480 +0100 -@@ -5,7 +5,7 @@ - * - * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) - * -- * $Id$ -+ * $Id$ - */ - - /****************************************************************************/ -@@ -24,58 +24,11 @@ - - /****************************************************************************/ - --__u8 uclinux_read8(struct map_info *map, unsigned long ofs) --{ -- return(*((__u8 *) (map->map_priv_1 + ofs))); --} -- --__u16 uclinux_read16(struct map_info *map, unsigned long ofs) --{ -- return(*((__u16 *) (map->map_priv_1 + ofs))); --} -- --__u32 uclinux_read32(struct map_info *map, unsigned long ofs) --{ -- return(*((__u32 *) (map->map_priv_1 + ofs))); --} -- --void uclinux_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- memcpy(to, (void *)(map->map_priv_1 + from), len); --} -- --void uclinux_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- *((__u8 *) (map->map_priv_1 + adr)) = d; --} -- --void uclinux_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- *((__u16 *) (map->map_priv_1 + adr)) = d; --} -- --void uclinux_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- *((__u32 *) (map->map_priv_1 + adr)) = d; --} -- --void uclinux_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- memcpy((void *) (map->map_priv_1 + to), from, len); --} - - /****************************************************************************/ - - struct map_info uclinux_ram_map = { -- name: "RAM", -- read8: uclinux_read8, -- read16: uclinux_read16, -- read32: uclinux_read32, -- copy_from: uclinux_copy_from, -- write8: uclinux_write8, -- write16: uclinux_write16, -- write32: uclinux_write32, -- copy_to: uclinux_copy_to, -+ .name = "RAM", - }; - - struct mtd_info *uclinux_ram_mtdinfo; -@@ -83,7 +36,7 @@ - /****************************************************************************/ - - struct mtd_partition uclinux_romfs[] = { -- { name: "ROMfs", offset: 0 } -+ { .name = "ROMfs" } - }; - - #define NUM_PARTITIONS (sizeof(uclinux_romfs) / sizeof(uclinux_romfs[0])) -@@ -94,7 +47,7 @@ - size_t *retlen, u_char **mtdbuf) - { - struct map_info *map = (struct map_info *) mtd->priv; -- *mtdbuf = (u_char *) (map->map_priv_1 + ((int) from)); -+ *mtdbuf = (u_char *) (map->virt + ((int) from)); - *retlen = len; - return(0); - } -@@ -108,29 +61,31 @@ - extern char _ebss; - - mapp = &uclinux_ram_map; -- mapp->map_priv_2 = (unsigned long) &_ebss; -+ mapp->phys = (unsigned long) &_ebss; - mapp->size = PAGE_ALIGN(*((unsigned long *)((&_ebss) + 8))); - mapp->buswidth = 4; - - printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n", - (int) mapp->map_priv_2, (int) mapp->size); - -- mapp->map_priv_1 = (unsigned long) -- ioremap_nocache(mapp->map_priv_2, mapp->size); -+ mapp->virt = (unsigned long) -+ ioremap_nocache(mapp->phys, mapp->size); - -- if (mapp->map_priv_1 == 0) { -+ if (mapp->virt == 0) { - printk("uclinux[mtd]: ioremap_nocache() failed\n"); - return(-EIO); - } - -+ simple_map_init(mapp); -+ - mtd = do_map_probe("map_ram", mapp); - if (!mtd) { - printk("uclinux[mtd]: failed to find a mapping?\n"); -- iounmap((void *) mapp->map_priv_1); -+ iounmap((void *) mapp->virt); - return(-ENXIO); - } - -- mtd->module = THIS_MODULE; -+ mtd->owner = THIS_MODULE; - mtd->point = uclinux_point; - mtd->priv = mapp; - -@@ -155,8 +110,8 @@ - uclinux_ram_mtdinfo = NULL; - } - if (uclinux_ram_map.map_priv_1) { -- iounmap((void *) uclinux_ram_map.map_priv_1); -- uclinux_ram_map.map_priv_1 = 0; -+ iounmap((void *) uclinux_ram_map.virt); -+ uclinux_ram_map.virt = 0; - } - } - -diff -Nurb linux-mips-2.4.27/drivers/mtd/maps/vmax301.c linux/drivers/mtd/maps/vmax301.c ---- linux-mips-2.4.27/drivers/mtd/maps/vmax301.c 2001-11-05 21:15:52.000000000 +0100 -+++ linux/drivers/mtd/maps/vmax301.c 2004-11-19 10:25:11.982187176 +0100 -@@ -1,4 +1,4 @@ --// $Id$ -+// $Id$ - /* ###################################################################### - - Tempustech VMAX SBC301 MTD Driver. -@@ -24,6 +24,7 @@ - #include - - #include -+#include - - - #define WINDOW_START 0xd8000 -@@ -142,34 +143,36 @@ - - static struct map_info vmax_map[2] = { - { -- name: "VMAX301 Internal Flash", -- size: 3*2*1024*1024, -- buswidth: 1, -- read8: vmax301_read8, -- read16: vmax301_read16, -- read32: vmax301_read32, -- copy_from: vmax301_copy_from, -- write8: vmax301_write8, -- write16: vmax301_write16, -- write32: vmax301_write32, -- copy_to: vmax301_copy_to, -- map_priv_1: WINDOW_START + WINDOW_LENGTH, -- map_priv_2: 0xFFFFFFFF -+ .name = "VMAX301 Internal Flash", -+ .phys = NO_XIP, -+ .size = 3*2*1024*1024, -+ .buswidth = 1, -+ .read8 = vmax301_read8, -+ .read16 = vmax301_read16, -+ .read32 = vmax301_read32, -+ .copy_from = vmax301_copy_from, -+ .write8 = vmax301_write8, -+ .write16 = vmax301_write16, -+ .write32 = vmax301_write32, -+ .copy_to = vmax301_copy_to, -+ .map_priv_1 = WINDOW_START + WINDOW_LENGTH, -+ .map_priv_2 = 0xFFFFFFFF - }, - { -- name: "VMAX301 Socket", -- size: 0, -- buswidth: 1, -- read8: vmax301_read8, -- read16: vmax301_read16, -- read32: vmax301_read32, -- copy_from: vmax301_copy_from, -- write8: vmax301_write8, -- write16: vmax301_write16, -- write32: vmax301_write32, -- copy_to: vmax301_copy_to, -- map_priv_1: WINDOW_START + (3*WINDOW_LENGTH), -- map_priv_2: 0xFFFFFFFF -+ .name = "VMAX301 Socket", -+ .phys = NO_XIP, -+ .size = 0, -+ .buswidth = 1, -+ .read8 = vmax301_read8, -+ .read16 = vmax301_read16, -+ .read32 = vmax301_read32, -+ .copy_from = vmax301_copy_from, -+ .write8 = vmax301_write8, -+ .write16 = vmax301_write16, -+ .write32 = vmax301_write32, -+ .copy_to = vmax301_copy_to, -+ .map_priv_1 = WINDOW_START + (3*WINDOW_LENGTH), -+ .map_priv_2 = 0xFFFFFFFF - } - }; - -@@ -206,8 +209,8 @@ - address of the first half, because it's used more - often. - */ -- vmax_map[0].map_priv_1 = iomapadr + WINDOW_START; -- vmax_map[1].map_priv_1 = iomapadr + (3*WINDOW_START); -+ vmax_map[0].map_priv_2 = iomapadr + WINDOW_START; -+ vmax_map[1].map_priv_2 = iomapadr + (3*WINDOW_START); - - for (i=0; i<2; i++) { - vmax_mtd[i] = do_map_probe("cfi_probe", &vmax_map[i]); -@@ -218,7 +221,7 @@ - if (!vmax_mtd[i]) - vmax_mtd[i] = do_map_probe("map_rom", &vmax_map[i]); - if (vmax_mtd[i]) { -- vmax_mtd[i]->module = THIS_MODULE; -+ vmax_mtd[i]->owner = THIS_MODULE; - add_mtd_device(vmax_mtd[i]); - } - } -diff -Nurb linux-mips-2.4.27/drivers/mtd/mtd_blkdevs-24.c linux/drivers/mtd/mtd_blkdevs-24.c ---- linux-mips-2.4.27/drivers/mtd/mtd_blkdevs-24.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/mtd_blkdevs-24.c 2004-11-19 10:25:11.640239160 +0100 -@@ -0,0 +1,699 @@ -+/* -+ * $Id$ -+ * -+ * (C) 2003 David Woodhouse -+ * -+ * Interface to Linux 2.4 block layer for MTD 'translation layers'. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static LIST_HEAD(blktrans_majors); -+ -+extern struct semaphore mtd_table_mutex; -+extern struct mtd_info *mtd_table[]; -+ -+struct mtd_blkcore_priv { -+ devfs_handle_t devfs_dir_handle; -+ int blksizes[256]; -+ int sizes[256]; -+ struct hd_struct part_table[256]; -+ struct gendisk gd; -+ spinlock_t devs_lock; /* See comment in _request function */ -+ struct completion thread_dead; -+ int exiting; -+ wait_queue_head_t thread_wq; -+}; -+ -+static inline struct mtd_blktrans_dev *tr_get_dev(struct mtd_blktrans_ops *tr, -+ int devnum) -+{ -+ struct list_head *this; -+ struct mtd_blktrans_dev *d; -+ -+ list_for_each(this, &tr->devs) { -+ d = list_entry(this, struct mtd_blktrans_dev, list); -+ -+ if (d->devnum == devnum) -+ return d; -+ } -+ return NULL; -+} -+ -+static inline struct mtd_blktrans_ops *get_tr(int major) -+{ -+ struct list_head *this; -+ struct mtd_blktrans_ops *t; -+ -+ list_for_each(this, &blktrans_majors) { -+ t = list_entry(this, struct mtd_blktrans_ops, list); -+ -+ if (t->major == major) -+ return t; -+ } -+ return NULL; -+} -+ -+static int do_blktrans_request(struct mtd_blktrans_ops *tr, -+ struct mtd_blktrans_dev *dev, -+ struct request *req) -+{ -+ unsigned long block, nsect; -+ char *buf; -+ int minor; -+ -+ minor = MINOR(req->rq_dev); -+ block = req->sector; -+ nsect = req->current_nr_sectors; -+ buf = req->buffer; -+ -+ if (block + nsect > tr->blkcore_priv->part_table[minor].nr_sects) { -+ printk(KERN_WARNING "Access beyond end of device.\n"); -+ return 0; -+ } -+ block += tr->blkcore_priv->part_table[minor].start_sect; -+ -+ switch(req->cmd) { -+ case READ: -+ for (; nsect > 0; nsect--, block++, buf += 512) -+ if (tr->readsect(dev, block, buf)) -+ return 0; -+ return 1; -+ -+ case WRITE: -+ if (!tr->writesect) -+ return 0; -+ -+ for (; nsect > 0; nsect--, block++, buf += 512) -+ if (tr->writesect(dev, block, buf)) -+ return 0; -+ return 1; -+ -+ default: -+ printk(KERN_NOTICE "Unknown request cmd %d\n", req->cmd); -+ return 0; -+ } -+} -+ -+static int mtd_blktrans_thread(void *arg) -+{ -+ struct mtd_blktrans_ops *tr = arg; -+ struct request_queue *rq = BLK_DEFAULT_QUEUE(tr->major); -+ -+ /* we might get involved when memory gets low, so use PF_MEMALLOC */ -+ current->flags |= PF_MEMALLOC; -+ -+ snprintf(current->comm, sizeof(current->comm), "%sd", tr->name); -+ -+ /* daemonize() doesn't do this for us since some kernel threads -+ actually want to deal with signals. We can't just call -+ exit_sighand() since that'll cause an oops when we finally -+ do exit. */ -+ -+#ifndef __rh_config_h__ /* HAVE_NPTL */ -+ spin_lock_irq(¤t->sigmask_lock); -+ sigfillset(¤t->blocked); -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+#else -+ spin_lock_irq(¤t->sighand->siglock); -+ sigfillset(¤t->blocked); -+ recalc_sigpending(); -+ spin_unlock_irq(¤t->sighand->siglock); -+#endif -+ daemonize(); -+ -+ while (!tr->blkcore_priv->exiting) { -+ struct request *req; -+ struct mtd_blktrans_dev *dev; -+ int devnum; -+ int res = 0; -+ DECLARE_WAITQUEUE(wait, current); -+ -+ spin_lock_irq(&io_request_lock); -+ -+ if (list_empty(&rq->queue_head)) { -+ -+ add_wait_queue(&tr->blkcore_priv->thread_wq, &wait); -+ set_current_state(TASK_INTERRUPTIBLE); -+ -+ spin_unlock_irq(&io_request_lock); -+ -+ schedule(); -+ remove_wait_queue(&tr->blkcore_priv->thread_wq, &wait); -+ -+ continue; -+ } -+ -+ req = blkdev_entry_next_request(&rq->queue_head); -+ -+ devnum = MINOR(req->rq_dev) >> tr->part_bits; -+ -+ /* The ll_rw_blk code knows not to touch the request -+ at the head of the queue */ -+ spin_unlock_irq(&io_request_lock); -+ -+ /* FIXME: Where can we store the dev, on which -+ we already have a refcount anyway? We need to -+ lock against concurrent addition/removal of devices, -+ but if we use the mtd_table_mutex we deadlock when -+ grok_partitions is called from the registration -+ callbacks. */ -+ spin_lock(&tr->blkcore_priv->devs_lock); -+ dev = tr_get_dev(tr, devnum); -+ spin_unlock(&tr->blkcore_priv->devs_lock); -+ -+ BUG_ON(!dev); -+ -+ /* Ensure serialisation of requests */ -+ down(&dev->sem); -+ -+ res = do_blktrans_request(tr, dev, req); -+ up(&dev->sem); -+ -+ if (!end_that_request_first(req, res, tr->name)) { -+ spin_lock_irq(&io_request_lock); -+ blkdev_dequeue_request(req); -+ end_that_request_last(req); -+ spin_unlock_irq(&io_request_lock); -+ } -+ } -+ complete_and_exit(&tr->blkcore_priv->thread_dead, 0); -+} -+ -+static void mtd_blktrans_request(struct request_queue *rq) -+{ -+ struct mtd_blktrans_ops *tr = rq->queuedata; -+ wake_up(&tr->blkcore_priv->thread_wq); -+} -+ -+int blktrans_open(struct inode *i, struct file *f) -+{ -+ struct mtd_blktrans_ops *tr = NULL; -+ struct mtd_blktrans_dev *dev = NULL; -+ int major_nr = MAJOR(i->i_rdev); -+ int minor_nr = MINOR(i->i_rdev); -+ int devnum; -+ int ret = -ENODEV; -+ -+ if (is_read_only(i->i_rdev) && (f->f_mode & FMODE_WRITE)) -+ return -EROFS; -+ -+ down(&mtd_table_mutex); -+ -+ tr = get_tr(major_nr); -+ -+ if (!tr) -+ goto out; -+ -+ devnum = minor_nr >> tr->part_bits; -+ -+ dev = tr_get_dev(tr, devnum); -+ -+ if (!dev) -+ goto out; -+ -+ if (!tr->blkcore_priv->part_table[minor_nr].nr_sects) { -+ ret = -ENODEV; -+ goto out; -+ } -+ -+ if (!try_inc_mod_count(dev->mtd->owner)) -+ goto out; -+ -+ if (!try_inc_mod_count(tr->owner)) -+ goto out_tr; -+ -+ dev->mtd->usecount++; -+ -+ ret = 0; -+ if (tr->open && (ret = tr->open(dev))) { -+ dev->mtd->usecount--; -+ if (dev->mtd->owner) -+ __MOD_DEC_USE_COUNT(dev->mtd->owner); -+ out_tr: -+ if (tr->owner) -+ __MOD_DEC_USE_COUNT(tr->owner); -+ } -+ out: -+ up(&mtd_table_mutex); -+ -+ return ret; -+} -+ -+int blktrans_release(struct inode *i, struct file *f) -+{ -+ struct mtd_blktrans_dev *dev; -+ struct mtd_blktrans_ops *tr; -+ int ret = 0; -+ int devnum; -+ -+ down(&mtd_table_mutex); -+ -+ tr = get_tr(MAJOR(i->i_rdev)); -+ if (!tr) { -+ up(&mtd_table_mutex); -+ return -ENODEV; -+ } -+ -+ devnum = MINOR(i->i_rdev) >> tr->part_bits; -+ dev = tr_get_dev(tr, devnum); -+ -+ if (!dev) { -+ up(&mtd_table_mutex); -+ return -ENODEV; -+ } -+ -+ if (tr->release) -+ ret = tr->release(dev); -+ -+ if (!ret) { -+ dev->mtd->usecount--; -+ if (dev->mtd->owner) -+ __MOD_DEC_USE_COUNT(dev->mtd->owner); -+ if (tr->owner) -+ __MOD_DEC_USE_COUNT(tr->owner); -+ } -+ -+ up(&mtd_table_mutex); -+ -+ return ret; -+} -+ -+static int mtd_blktrans_rrpart(kdev_t rdev, struct mtd_blktrans_ops *tr, -+ struct mtd_blktrans_dev *dev) -+{ -+ struct gendisk *gd = &(tr->blkcore_priv->gd); -+ int i; -+ int minor = MINOR(rdev); -+ -+ if (minor & ((1<part_bits)-1) || !tr->part_bits) { -+ /* BLKRRPART on a partition. Go away. */ -+ return -ENOTTY; -+ } -+ -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EACCES; -+ -+ /* We are required to prevent simultaneous open() ourselves. -+ The core doesn't do that for us. Did I ever mention how -+ much the Linux block layer sucks? Sledgehammer approach... */ -+ down(&mtd_table_mutex); -+ -+ for (i=0; i < (1<part_bits); i++) { -+ invalidate_device(MKDEV(tr->major, minor+i), 1); -+ gd->part[minor + i].start_sect = 0; -+ gd->part[minor + i].nr_sects = 0; -+ } -+ -+ grok_partitions(gd, minor, 1 << tr->part_bits, -+ tr->blkcore_priv->sizes[minor]); -+ up(&mtd_table_mutex); -+ -+ return 0; -+} -+ -+static int blktrans_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct mtd_blktrans_dev *dev; -+ struct mtd_blktrans_ops *tr; -+ int devnum; -+ -+ switch(cmd) { -+ case BLKGETSIZE: -+ case BLKGETSIZE64: -+ case BLKBSZSET: -+ case BLKBSZGET: -+ case BLKROSET: -+ case BLKROGET: -+ case BLKRASET: -+ case BLKRAGET: -+ case BLKPG: -+ case BLKELVGET: -+ case BLKELVSET: -+ return blk_ioctl(inode->i_rdev, cmd, arg); -+ } -+ -+ down(&mtd_table_mutex); -+ -+ tr = get_tr(MAJOR(inode->i_rdev)); -+ if (!tr) { -+ up(&mtd_table_mutex); -+ return -ENODEV; -+ } -+ -+ devnum = MINOR(inode->i_rdev) >> tr->part_bits; -+ dev = tr_get_dev(tr, devnum); -+ -+ up(&mtd_table_mutex); -+ -+ if (!dev) -+ return -ENODEV; -+ -+ switch(cmd) { -+ case BLKRRPART: -+ return mtd_blktrans_rrpart(inode->i_rdev, tr, dev); -+ -+ case BLKFLSBUF: -+ blk_ioctl(inode->i_rdev, cmd, arg); -+ if (tr->flush) -+ return tr->flush(dev); -+ /* The core code did the work, we had nothing to do. */ -+ return 0; -+ -+ case HDIO_GETGEO: -+ if (tr->getgeo) { -+ struct hd_geometry g; -+ struct gendisk *gd = &(tr->blkcore_priv->gd); -+ int ret; -+ -+ memset(&g, 0, sizeof(g)); -+ ret = tr->getgeo(dev, &g); -+ if (ret) -+ return ret; -+ -+ g.start = gd->part[MINOR(inode->i_rdev)].start_sect; -+ if (copy_to_user((void *)arg, &g, sizeof(g))) -+ return -EFAULT; -+ return 0; -+ } /* else */ -+ default: -+ return -ENOTTY; -+ } -+} -+ -+struct block_device_operations mtd_blktrans_ops = { -+ .owner = THIS_MODULE, -+ .open = blktrans_open, -+ .release = blktrans_release, -+ .ioctl = blktrans_ioctl, -+}; -+ -+int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) -+{ -+ struct mtd_blktrans_ops *tr = new->tr; -+ struct list_head *this; -+ int last_devnum = -1; -+ int i; -+ -+ if (!down_trylock(&mtd_table_mutex)) { -+ up(&mtd_table_mutex); -+ BUG(); -+ } -+ -+ spin_lock(&tr->blkcore_priv->devs_lock); -+ -+ list_for_each(this, &tr->devs) { -+ struct mtd_blktrans_dev *d = list_entry(this, struct mtd_blktrans_dev, list); -+ if (new->devnum == -1) { -+ /* Use first free number */ -+ if (d->devnum != last_devnum+1) { -+ /* Found a free devnum. Plug it in here */ -+ new->devnum = last_devnum+1; -+ list_add_tail(&new->list, &d->list); -+ goto added; -+ } -+ } else if (d->devnum == new->devnum) { -+ /* Required number taken */ -+ spin_unlock(&tr->blkcore_priv->devs_lock); -+ return -EBUSY; -+ } else if (d->devnum > new->devnum) { -+ /* Required number was free */ -+ list_add_tail(&new->list, &d->list); -+ goto added; -+ } -+ last_devnum = d->devnum; -+ } -+ if (new->devnum == -1) -+ new->devnum = last_devnum+1; -+ -+ if ((new->devnum << tr->part_bits) > 256) { -+ spin_unlock(&tr->blkcore_priv->devs_lock); -+ return -EBUSY; -+ } -+ -+ init_MUTEX(&new->sem); -+ list_add_tail(&new->list, &tr->devs); -+ added: -+ spin_unlock(&tr->blkcore_priv->devs_lock); -+ -+ if (!tr->writesect) -+ new->readonly = 1; -+ -+ for (i = new->devnum << tr->part_bits; -+ i < (new->devnum+1) << tr->part_bits; -+ i++) { -+ set_device_ro(MKDEV(tr->major, i), new->readonly); -+ tr->blkcore_priv->blksizes[i] = new->blksize; -+ tr->blkcore_priv->sizes[i] = 0; -+ tr->blkcore_priv->part_table[i].nr_sects = 0; -+ tr->blkcore_priv->part_table[i].start_sect = 0; -+ } -+ -+ /* -+ dwmw2: BLOCK_SIZE_BITS has nothing to do with block devices -+ dwmw2: any code which sets blk_size[][] should be -+ size >> 10 /+ 2.4 and its dumb units */ -+ -+ tr->blkcore_priv->sizes[new->devnum << tr->part_bits] = -+ (new->size * new->blksize) >> 10; /* 2.4 and its dumb units */ -+ -+ /* But this is still in device's sectors? $DEITY knows */ -+ tr->blkcore_priv->part_table[new->devnum << tr->part_bits].nr_sects = new->size; -+ -+ if (tr->part_bits) { -+ grok_partitions(&tr->blkcore_priv->gd, new->devnum, -+ 1 << tr->part_bits, new->size); -+ } -+#ifdef CONFIG_DEVFS_FS -+ if (!tr->part_bits) { -+ char name[2]; -+ -+ name[0] = '0' + new->devnum; -+ name[1] = 0; -+ -+ new->blkcore_priv = -+ devfs_register(tr->blkcore_priv->devfs_dir_handle, -+ name, DEVFS_FL_DEFAULT, tr->major, -+ new->devnum, S_IFBLK|S_IRUGO|S_IWUGO, -+ &mtd_blktrans_ops, NULL); -+ } -+#endif -+ return 0; -+} -+ -+int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) -+{ -+ struct mtd_blktrans_ops *tr = old->tr; -+ int i; -+ -+ if (!down_trylock(&mtd_table_mutex)) { -+ up(&mtd_table_mutex); -+ BUG(); -+ } -+ -+#ifdef CONFIG_DEVFS_FS -+ if (!tr->part_bits) { -+ devfs_unregister(old->blkcore_priv); -+ old->blkcore_priv = NULL; -+ } else { -+ devfs_register_partitions(&tr->blkcore_priv->gd, -+ old->devnum << tr->part_bits, 1); -+ } -+#endif -+ spin_lock(&tr->blkcore_priv->devs_lock); -+ list_del(&old->list); -+ spin_unlock(&tr->blkcore_priv->devs_lock); -+ -+ for (i = (old->devnum << tr->part_bits); -+ i < ((old->devnum+1) << tr->part_bits); i++) { -+ tr->blkcore_priv->sizes[i] = 0; -+ tr->blkcore_priv->part_table[i].nr_sects = 0; -+ tr->blkcore_priv->part_table[i].start_sect = 0; -+ } -+ -+ return 0; -+} -+ -+void blktrans_notify_remove(struct mtd_info *mtd) -+{ -+ struct list_head *this, *this2, *next; -+ -+ list_for_each(this, &blktrans_majors) { -+ struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list); -+ -+ list_for_each_safe(this2, next, &tr->devs) { -+ struct mtd_blktrans_dev *dev = list_entry(this2, struct mtd_blktrans_dev, list); -+ -+ if (dev->mtd == mtd) -+ tr->remove_dev(dev); -+ } -+ } -+} -+ -+void blktrans_notify_add(struct mtd_info *mtd) -+{ -+ struct list_head *this; -+ -+ if (mtd->type == MTD_ABSENT) -+ return; -+ -+ list_for_each(this, &blktrans_majors) { -+ struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list); -+ -+ tr->add_mtd(tr, mtd); -+ } -+ -+} -+ -+static struct mtd_notifier blktrans_notifier = { -+ .add = blktrans_notify_add, -+ .remove = blktrans_notify_remove, -+}; -+ -+int register_mtd_blktrans(struct mtd_blktrans_ops *tr) -+{ -+ int ret, i; -+ -+ /* Register the notifier if/when the first device type is -+ registered, to prevent the link/init ordering from fucking -+ us over. */ -+ if (!blktrans_notifier.list.next) -+ register_mtd_user(&blktrans_notifier); -+ -+ tr->blkcore_priv = kmalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL); -+ if (!tr->blkcore_priv) -+ return -ENOMEM; -+ -+ memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv)); -+ -+ down(&mtd_table_mutex); -+ -+ ret = devfs_register_blkdev(tr->major, tr->name, &mtd_blktrans_ops); -+ 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); -+ return ret; -+ } -+ -+ blk_init_queue(BLK_DEFAULT_QUEUE(tr->major), &mtd_blktrans_request); -+ (BLK_DEFAULT_QUEUE(tr->major))->queuedata = tr; -+ -+ init_completion(&tr->blkcore_priv->thread_dead); -+ init_waitqueue_head(&tr->blkcore_priv->thread_wq); -+ -+ ret = kernel_thread(mtd_blktrans_thread, tr, -+ CLONE_FS|CLONE_FILES|CLONE_SIGHAND); -+ if (ret < 0) { -+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(tr->major)); -+ devfs_unregister_blkdev(tr->major, tr->name); -+ kfree(tr->blkcore_priv); -+ up(&mtd_table_mutex); -+ return ret; -+ } -+ -+ tr->blkcore_priv->devfs_dir_handle = -+ devfs_mk_dir(NULL, tr->name, NULL); -+ -+ blksize_size[tr->major] = tr->blkcore_priv->blksizes; -+ blk_size[tr->major] = tr->blkcore_priv->sizes; -+ -+ tr->blkcore_priv->gd.major = tr->major; -+ tr->blkcore_priv->gd.major_name = tr->name; -+ tr->blkcore_priv->gd.minor_shift = tr->part_bits; -+ tr->blkcore_priv->gd.max_p = (1<part_bits) - 1; -+ tr->blkcore_priv->gd.part = tr->blkcore_priv->part_table; -+ tr->blkcore_priv->gd.sizes = tr->blkcore_priv->sizes; -+ tr->blkcore_priv->gd.nr_real = 256 >> tr->part_bits; -+ -+ spin_lock_init(&tr->blkcore_priv->devs_lock); -+ -+ add_gendisk(&tr->blkcore_priv->gd); -+ -+ INIT_LIST_HEAD(&tr->devs); -+ list_add(&tr->list, &blktrans_majors); -+ -+ for (i=0; itype != MTD_ABSENT) -+ tr->add_mtd(tr, mtd_table[i]); -+ } -+ up(&mtd_table_mutex); -+ -+ return 0; -+} -+ -+int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) -+{ -+ struct list_head *this, *next; -+ -+ down(&mtd_table_mutex); -+ -+ /* Clean up the kernel thread */ -+ tr->blkcore_priv->exiting = 1; -+ wake_up(&tr->blkcore_priv->thread_wq); -+ wait_for_completion(&tr->blkcore_priv->thread_dead); -+ -+ /* Remove it from the list of active majors */ -+ list_del(&tr->list); -+ -+ /* Remove each of its devices */ -+ list_for_each_safe(this, next, &tr->devs) { -+ struct mtd_blktrans_dev *dev = list_entry(this, struct mtd_blktrans_dev, list); -+ tr->remove_dev(dev); -+ } -+ -+ blksize_size[tr->major] = NULL; -+ blk_size[tr->major] = NULL; -+ -+ del_gendisk(&tr->blkcore_priv->gd); -+ -+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(tr->major)); -+ devfs_unregister_blkdev(tr->major, tr->name); -+ -+ devfs_unregister(tr->blkcore_priv->devfs_dir_handle); -+ -+ up(&mtd_table_mutex); -+ -+ kfree(tr->blkcore_priv); -+ -+ if (!list_empty(&tr->devs)) -+ BUG(); -+ return 0; -+} -+ -+static void __exit mtd_blktrans_exit(void) -+{ -+ /* No race here -- if someone's currently in register_mtd_blktrans -+ we're screwed anyway. */ -+ if (blktrans_notifier.list.next) -+ unregister_mtd_user(&blktrans_notifier); -+} -+ -+module_exit(mtd_blktrans_exit); -+ -+EXPORT_SYMBOL_GPL(register_mtd_blktrans); -+EXPORT_SYMBOL_GPL(deregister_mtd_blktrans); -+EXPORT_SYMBOL_GPL(add_mtd_blktrans_dev); -+EXPORT_SYMBOL_GPL(del_mtd_blktrans_dev); -+ -+MODULE_AUTHOR("David Woodhouse "); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Common interface to block layer for MTD 'translation layers'"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/mtd_blkdevs.c linux/drivers/mtd/mtd_blkdevs.c ---- linux-mips-2.4.27/drivers/mtd/mtd_blkdevs.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/mtd_blkdevs.c 2004-11-19 10:25:11.642238856 +0100 -@@ -0,0 +1,479 @@ -+/* -+ * $Id$ -+ * -+ * (C) 2003 David Woodhouse -+ * -+ * Interface to Linux 2.5 block layer for MTD 'translation layers'. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static LIST_HEAD(blktrans_majors); -+ -+extern struct semaphore mtd_table_mutex; -+extern struct mtd_info *mtd_table[]; -+ -+struct mtd_blkcore_priv { -+ struct completion thread_dead; -+ int exiting; -+ wait_queue_head_t thread_wq; -+ struct request_queue *rq; -+ spinlock_t queue_lock; -+}; -+ -+static int do_blktrans_request(struct mtd_blktrans_ops *tr, -+ struct mtd_blktrans_dev *dev, -+ struct request *req) -+{ -+ unsigned long block, nsect; -+ char *buf; -+ -+ block = req->sector; -+ nsect = req->current_nr_sectors; -+ buf = req->buffer; -+ -+ if (!(req->flags & REQ_CMD)) -+ return 0; -+ -+ if (block + nsect > get_capacity(req->rq_disk)) -+ return 0; -+ -+ switch(rq_data_dir(req)) { -+ case READ: -+ for (; nsect > 0; nsect--, block++, buf += 512) -+ if (tr->readsect(dev, block, buf)) -+ return 0; -+ return 1; -+ -+ case WRITE: -+ if (!tr->writesect) -+ return 0; -+ -+ for (; nsect > 0; nsect--, block++, buf += 512) -+ if (tr->writesect(dev, block, buf)) -+ return 0; -+ return 1; -+ -+ default: -+ printk(KERN_NOTICE "Unknown request %ld\n", rq_data_dir(req)); -+ return 0; -+ } -+} -+ -+static int mtd_blktrans_thread(void *arg) -+{ -+ struct mtd_blktrans_ops *tr = arg; -+ struct request_queue *rq = tr->blkcore_priv->rq; -+ -+ /* we might get involved when memory gets low, so use PF_MEMALLOC */ -+ current->flags |= PF_MEMALLOC; -+ -+ daemonize("%sd", tr->name); -+ -+ /* daemonize() doesn't do this for us since some kernel threads -+ actually want to deal with signals. We can't just call -+ exit_sighand() since that'll cause an oops when we finally -+ do exit. */ -+ spin_lock_irq(¤t->sighand->siglock); -+ sigfillset(¤t->blocked); -+ recalc_sigpending(); -+ spin_unlock_irq(¤t->sighand->siglock); -+ -+ spin_lock_irq(rq->queue_lock); -+ -+ while (!tr->blkcore_priv->exiting) { -+ struct request *req; -+ struct mtd_blktrans_dev *dev; -+ int res = 0; -+ DECLARE_WAITQUEUE(wait, current); -+ -+ req = elv_next_request(rq); -+ -+ if (!req) { -+ add_wait_queue(&tr->blkcore_priv->thread_wq, &wait); -+ set_current_state(TASK_INTERRUPTIBLE); -+ -+ spin_unlock_irq(rq->queue_lock); -+ -+ schedule(); -+ remove_wait_queue(&tr->blkcore_priv->thread_wq, &wait); -+ -+ spin_lock_irq(rq->queue_lock); -+ -+ continue; -+ } -+ -+ dev = req->rq_disk->private_data; -+ tr = dev->tr; -+ -+ spin_unlock_irq(rq->queue_lock); -+ -+ down(&dev->sem); -+ res = do_blktrans_request(tr, dev, req); -+ up(&dev->sem); -+ -+ spin_lock_irq(rq->queue_lock); -+ -+ end_request(req, res); -+ } -+ complete_and_exit(&tr->blkcore_priv->thread_dead, 0); -+} -+ -+static void mtd_blktrans_request(struct request_queue *rq) -+{ -+ struct mtd_blktrans_ops *tr = rq->queuedata; -+ wake_up(&tr->blkcore_priv->thread_wq); -+} -+ -+ -+int blktrans_open(struct inode *i, struct file *f) -+{ -+ struct mtd_blktrans_dev *dev; -+ struct mtd_blktrans_ops *tr; -+ int ret = -ENODEV; -+ -+ dev = i->i_bdev->bd_disk->private_data; -+ tr = dev->tr; -+ -+ if (!try_module_get(dev->mtd->owner)) -+ goto out; -+ -+ if (!try_module_get(tr->owner)) -+ goto out_tr; -+ -+ /* FIXME: Locking. A hot pluggable device can go away -+ (del_mtd_device can be called for it) without its module -+ being unloaded. */ -+ dev->mtd->usecount++; -+ -+ ret = 0; -+ if (tr->open && (ret = tr->open(dev))) { -+ dev->mtd->usecount--; -+ module_put(dev->mtd->owner); -+ out_tr: -+ module_put(tr->owner); -+ } -+ out: -+ return ret; -+} -+ -+int blktrans_release(struct inode *i, struct file *f) -+{ -+ struct mtd_blktrans_dev *dev; -+ struct mtd_blktrans_ops *tr; -+ int ret = 0; -+ -+ dev = i->i_bdev->bd_disk->private_data; -+ tr = dev->tr; -+ -+ if (tr->release) -+ ret = tr->release(dev); -+ -+ if (!ret) { -+ dev->mtd->usecount--; -+ module_put(dev->mtd->owner); -+ module_put(tr->owner); -+ } -+ -+ return ret; -+} -+ -+ -+static int blktrans_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct mtd_blktrans_dev *dev = inode->i_bdev->bd_disk->private_data; -+ struct mtd_blktrans_ops *tr = dev->tr; -+ -+ switch (cmd) { -+ case BLKFLSBUF: -+ if (tr->flush) -+ return tr->flush(dev); -+ /* The core code did the work, we had nothing to do. */ -+ return 0; -+ -+ case HDIO_GETGEO: -+ if (tr->getgeo) { -+ struct hd_geometry g; -+ int ret; -+ -+ memset(&g, 0, sizeof(g)); -+ ret = tr->getgeo(dev, &g); -+ -+ if (ret) -+ return ret; -+ -+ g.start = get_start_sect(inode->i_bdev); -+ if (copy_to_user((void *)arg, &g, sizeof(g))) -+ return -EFAULT; -+ return 0; -+ } /* else */ -+ default: -+ return -ENOTTY; -+ } -+} -+ -+struct block_device_operations mtd_blktrans_ops = { -+ .owner = THIS_MODULE, -+ .open = blktrans_open, -+ .release = blktrans_release, -+ .ioctl = blktrans_ioctl, -+}; -+ -+int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) -+{ -+ struct mtd_blktrans_ops *tr = new->tr; -+ struct list_head *this; -+ int last_devnum = -1; -+ struct gendisk *gd; -+ -+ if (!down_trylock(&mtd_table_mutex)) { -+ up(&mtd_table_mutex); -+ BUG(); -+ } -+ -+ list_for_each(this, &tr->devs) { -+ struct mtd_blktrans_dev *d = list_entry(this, struct mtd_blktrans_dev, list); -+ if (new->devnum == -1) { -+ /* Use first free number */ -+ if (d->devnum != last_devnum+1) { -+ /* Found a free devnum. Plug it in here */ -+ new->devnum = last_devnum+1; -+ list_add_tail(&new->list, &d->list); -+ goto added; -+ } -+ } else if (d->devnum == new->devnum) { -+ /* Required number taken */ -+ return -EBUSY; -+ } else if (d->devnum > new->devnum) { -+ /* Required number was free */ -+ list_add_tail(&new->list, &d->list); -+ goto added; -+ } -+ last_devnum = d->devnum; -+ } -+ if (new->devnum == -1) -+ new->devnum = last_devnum+1; -+ -+ if ((new->devnum << tr->part_bits) > 256) { -+ return -EBUSY; -+ } -+ -+ init_MUTEX(&new->sem); -+ list_add_tail(&new->list, &tr->devs); -+ added: -+ if (!tr->writesect) -+ new->readonly = 1; -+ -+ gd = alloc_disk(1 << tr->part_bits); -+ if (!gd) { -+ list_del(&new->list); -+ return -ENOMEM; -+ } -+ gd->major = tr->major; -+ gd->first_minor = (new->devnum) << tr->part_bits; -+ gd->fops = &mtd_blktrans_ops; -+ -+ snprintf(gd->disk_name, sizeof(gd->disk_name), -+ "%s%c", tr->name, (tr->part_bits?'a':'0') + new->devnum); -+ snprintf(gd->devfs_name, sizeof(gd->devfs_name), -+ "%s/%c", tr->name, (tr->part_bits?'a':'0') + new->devnum); -+ -+ /* 2.5 has capacity in units of 512 bytes while still -+ having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */ -+ set_capacity(gd, (new->size * new->blksize) >> 9); -+ -+ gd->private_data = new; -+ new->blkcore_priv = gd; -+ gd->queue = tr->blkcore_priv->rq; -+ -+ if (new->readonly) -+ set_disk_ro(gd, 1); -+ -+ add_disk(gd); -+ -+ return 0; -+} -+ -+int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) -+{ -+ if (!down_trylock(&mtd_table_mutex)) { -+ up(&mtd_table_mutex); -+ BUG(); -+ } -+ -+ list_del(&old->list); -+ -+ del_gendisk(old->blkcore_priv); -+ put_disk(old->blkcore_priv); -+ -+ return 0; -+} -+ -+void blktrans_notify_remove(struct mtd_info *mtd) -+{ -+ struct list_head *this, *this2, *next; -+ -+ list_for_each(this, &blktrans_majors) { -+ struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list); -+ -+ list_for_each_safe(this2, next, &tr->devs) { -+ struct mtd_blktrans_dev *dev = list_entry(this2, struct mtd_blktrans_dev, list); -+ -+ if (dev->mtd == mtd) -+ tr->remove_dev(dev); -+ } -+ } -+} -+ -+void blktrans_notify_add(struct mtd_info *mtd) -+{ -+ struct list_head *this; -+ -+ if (mtd->type == MTD_ABSENT) -+ return; -+ -+ list_for_each(this, &blktrans_majors) { -+ struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list); -+ -+ tr->add_mtd(tr, mtd); -+ } -+ -+} -+ -+static struct mtd_notifier blktrans_notifier = { -+ .add = blktrans_notify_add, -+ .remove = blktrans_notify_remove, -+}; -+ -+int register_mtd_blktrans(struct mtd_blktrans_ops *tr) -+{ -+ int ret, i; -+ -+ /* Register the notifier if/when the first device type is -+ registered, to prevent the link/init ordering from fucking -+ us over. */ -+ if (!blktrans_notifier.list.next) -+ register_mtd_user(&blktrans_notifier); -+ -+ tr->blkcore_priv = kmalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL); -+ if (!tr->blkcore_priv) -+ return -ENOMEM; -+ -+ memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv)); -+ -+ down(&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); -+ return ret; -+ } -+ spin_lock_init(&tr->blkcore_priv->queue_lock); -+ init_completion(&tr->blkcore_priv->thread_dead); -+ init_waitqueue_head(&tr->blkcore_priv->thread_wq); -+ -+ tr->blkcore_priv->rq = blk_init_queue(mtd_blktrans_request, &tr->blkcore_priv->queue_lock); -+ if (!tr->blkcore_priv->rq) { -+ unregister_blkdev(tr->major, tr->name); -+ kfree(tr->blkcore_priv); -+ up(&mtd_table_mutex); -+ return -ENOMEM; -+ } -+ -+ tr->blkcore_priv->rq->queuedata = tr; -+ -+ ret = kernel_thread(mtd_blktrans_thread, tr, -+ CLONE_FS|CLONE_FILES|CLONE_SIGHAND); -+ if (ret < 0) { -+ blk_cleanup_queue(tr->blkcore_priv->rq); -+ unregister_blkdev(tr->major, tr->name); -+ kfree(tr->blkcore_priv); -+ up(&mtd_table_mutex); -+ return ret; -+ } -+ -+ devfs_mk_dir(tr->name); -+ -+ INIT_LIST_HEAD(&tr->devs); -+ list_add(&tr->list, &blktrans_majors); -+ -+ for (i=0; itype != MTD_ABSENT) -+ tr->add_mtd(tr, mtd_table[i]); -+ } -+ -+ up(&mtd_table_mutex); -+ -+ return 0; -+} -+ -+int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) -+{ -+ struct list_head *this, *next; -+ -+ down(&mtd_table_mutex); -+ -+ /* Clean up the kernel thread */ -+ tr->blkcore_priv->exiting = 1; -+ wake_up(&tr->blkcore_priv->thread_wq); -+ wait_for_completion(&tr->blkcore_priv->thread_dead); -+ -+ /* Remove it from the list of active majors */ -+ list_del(&tr->list); -+ -+ list_for_each_safe(this, next, &tr->devs) { -+ struct mtd_blktrans_dev *dev = list_entry(this, struct mtd_blktrans_dev, list); -+ tr->remove_dev(dev); -+ } -+ -+ devfs_remove(tr->name); -+ blk_cleanup_queue(tr->blkcore_priv->rq); -+ unregister_blkdev(tr->major, tr->name); -+ -+ up(&mtd_table_mutex); -+ -+ kfree(tr->blkcore_priv); -+ -+ if (!list_empty(&tr->devs)) -+ BUG(); -+ return 0; -+} -+ -+static void __exit mtd_blktrans_exit(void) -+{ -+ /* No race here -- if someone's currently in register_mtd_blktrans -+ we're screwed anyway. */ -+ if (blktrans_notifier.list.next) -+ unregister_mtd_user(&blktrans_notifier); -+} -+ -+module_exit(mtd_blktrans_exit); -+ -+EXPORT_SYMBOL_GPL(register_mtd_blktrans); -+EXPORT_SYMBOL_GPL(deregister_mtd_blktrans); -+EXPORT_SYMBOL_GPL(add_mtd_blktrans_dev); -+EXPORT_SYMBOL_GPL(del_mtd_blktrans_dev); -+ -+MODULE_AUTHOR("David Woodhouse "); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Common interface to block layer for MTD 'translation layers'"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/mtdblock.c linux/drivers/mtd/mtdblock.c ---- linux-mips-2.4.27/drivers/mtd/mtdblock.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/mtdblock.c 2004-11-19 10:25:11.643238704 +0100 -@@ -1,52 +1,25 @@ - /* - * Direct MTD block device access - * -- * $Id$ -+ * $Id$ - * -- * 02-nov-2000 Nicolas Pitre Added read-modify-write with cache -+ * (C) 2000-2003 Nicolas Pitre -+ * (C) 1999-2003 David Woodhouse - */ - - #include - #include - #include - #include -+#include -+#include - #include -+#include - #include --#include -- --#define MAJOR_NR MTD_BLOCK_MAJOR --#define DEVICE_NAME "mtdblock" --#define DEVICE_REQUEST mtdblock_request --#define DEVICE_NR(device) (device) --#define DEVICE_ON(device) --#define DEVICE_OFF(device) --#define DEVICE_NO_RANDOM --#include --/* for old kernels... */ --#ifndef QUEUE_EMPTY --#define QUEUE_EMPTY (!CURRENT) --#endif --#if LINUX_VERSION_CODE < 0x20300 --#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].plug_tq.sync) --#else --#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].request_queue.plugged) --#endif -- --#ifdef CONFIG_DEVFS_FS --#include --static void mtd_notify_add(struct mtd_info* mtd); --static void mtd_notify_remove(struct mtd_info* mtd); --static struct mtd_notifier notifier = { -- mtd_notify_add, -- mtd_notify_remove, -- NULL --}; --static devfs_handle_t devfs_dir_handle = NULL; --static devfs_handle_t devfs_rw_handle[MAX_MTD_DEVICES]; --#endif -+#include - - static struct mtdblk_dev { -- struct mtd_info *mtd; /* Locked */ -+ struct mtd_info *mtd; - int count; - struct semaphore cache_sem; - unsigned char *cache_data; -@@ -55,19 +28,6 @@ - enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; - } *mtdblks[MAX_MTD_DEVICES]; - --static spinlock_t mtdblks_lock; -- --static int mtd_sizes[MAX_MTD_DEVICES]; --static int mtd_blksizes[MAX_MTD_DEVICES]; -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14) --#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT --#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT --#else --#define BLK_INC_USE_COUNT do {} while(0) --#define BLK_DEC_USE_COUNT do {} while(0) --#endif -- - /* - * Cache stuff... - * -@@ -151,7 +111,7 @@ - return ret; - - /* -- * Here we could argably set the cache state to STATE_CLEAN. -+ * Here we could argubly set the cache state to STATE_CLEAN. - * However this could lead to inconsistency since we will not - * be notified if this content is altered on the flash by other - * means. Let's declare it empty and leave buffering tasks to -@@ -277,57 +237,47 @@ - return 0; - } - -+static int mtdblock_readsect(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buf) -+{ -+ struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; -+ return do_cached_read(mtdblk, block<<9, 512, buf); -+} - -+static int mtdblock_writesect(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buf) -+{ -+ struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; -+ if (unlikely(!mtdblk->cache_data)) { -+ mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize); -+ if (!mtdblk->cache_data) -+ return -EINTR; -+ /* -EINTR is not really correct, but it is the best match -+ * documented in man 2 write for all cases. We could also -+ * return -EAGAIN sometimes, but why bother? -+ */ -+ } -+ return do_cached_write(mtdblk, block<<9, 512, buf); -+} - --static int mtdblock_open(struct inode *inode, struct file *file) -+static int mtdblock_open(struct mtd_blktrans_dev *mbd) - { - struct mtdblk_dev *mtdblk; -- struct mtd_info *mtd; -- int dev; -+ struct mtd_info *mtd = mbd->mtd; -+ int dev = mbd->devnum; - - DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n"); - -- if (!inode) -- return -EINVAL; -- -- dev = MINOR(inode->i_rdev); -- if (dev >= MAX_MTD_DEVICES) -- return -EINVAL; -- -- BLK_INC_USE_COUNT; -- -- mtd = get_mtd_device(NULL, dev); -- if (!mtd) -- return -ENODEV; -- if (MTD_ABSENT == mtd->type) { -- put_mtd_device(mtd); -- BLK_DEC_USE_COUNT; -- return -ENODEV; -- } -- -- spin_lock(&mtdblks_lock); -- -- /* If it's already open, no need to piss about. */ - if (mtdblks[dev]) { - mtdblks[dev]->count++; -- spin_unlock(&mtdblks_lock); -- put_mtd_device(mtd); - return 0; - } - -- /* OK, it's not open. Try to find it */ -- -- /* First we have to drop the lock, because we have to -- to things which might sleep. -- */ -- spin_unlock(&mtdblks_lock); -- -+ /* OK, it's not open. Create cache info for it */ - mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); -- if (!mtdblk) { -- put_mtd_device(mtd); -- BLK_DEC_USE_COUNT; -+ if (!mtdblk) - return -ENOMEM; -- } -+ - memset(mtdblk, 0, sizeof(*mtdblk)); - mtdblk->count = 1; - mtdblk->mtd = mtd; -@@ -337,336 +287,102 @@ - if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM && - mtdblk->mtd->erasesize) { - mtdblk->cache_size = mtdblk->mtd->erasesize; -- mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize); -- if (!mtdblk->cache_data) { -- put_mtd_device(mtdblk->mtd); -- kfree(mtdblk); -- BLK_DEC_USE_COUNT; -- return -ENOMEM; -- } -- } -- -- /* OK, we've created a new one. Add it to the list. */ -- -- spin_lock(&mtdblks_lock); -- -- if (mtdblks[dev]) { -- /* Another CPU made one at the same time as us. */ -- mtdblks[dev]->count++; -- spin_unlock(&mtdblks_lock); -- put_mtd_device(mtdblk->mtd); -- vfree(mtdblk->cache_data); -- kfree(mtdblk); -- return 0; -+ mtdblk->cache_data = NULL; - } - - mtdblks[dev] = mtdblk; -- mtd_sizes[dev] = mtdblk->mtd->size/1024; -- if (mtdblk->mtd->erasesize) -- mtd_blksizes[dev] = mtdblk->mtd->erasesize; -- if (mtd_blksizes[dev] > PAGE_SIZE) -- mtd_blksizes[dev] = PAGE_SIZE; -- set_device_ro (inode->i_rdev, !(mtdblk->mtd->flags & MTD_WRITEABLE)); -- -- spin_unlock(&mtdblks_lock); - - DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); - - return 0; - } - --static release_t mtdblock_release(struct inode *inode, struct file *file) -+static int mtdblock_release(struct mtd_blktrans_dev *mbd) - { -- int dev; -- struct mtdblk_dev *mtdblk; -- DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); -+ int dev = mbd->devnum; -+ struct mtdblk_dev *mtdblk = mtdblks[dev]; - -- if (inode == NULL) -- release_return(-ENODEV); -- -- dev = MINOR(inode->i_rdev); -- mtdblk = mtdblks[dev]; -+ DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); - - down(&mtdblk->cache_sem); - write_cached_data(mtdblk); - up(&mtdblk->cache_sem); - -- spin_lock(&mtdblks_lock); - if (!--mtdblk->count) { - /* It was the last usage. Free the device */ - mtdblks[dev] = NULL; -- spin_unlock(&mtdblks_lock); - if (mtdblk->mtd->sync) - mtdblk->mtd->sync(mtdblk->mtd); -- put_mtd_device(mtdblk->mtd); - vfree(mtdblk->cache_data); - kfree(mtdblk); -- } else { -- spin_unlock(&mtdblks_lock); - } -- - DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); - -- BLK_DEC_USE_COUNT; -- release_return(0); --} -- -- --/* -- * This is a special request_fn because it is executed in a process context -- * to be able to sleep independently of the caller. The io_request_lock -- * is held upon entry and exit. -- * The head of our request queue is considered active so there is no need -- * to dequeue requests before we are done. -- */ --static void handle_mtdblock_request(void) --{ -- struct request *req; -- struct mtdblk_dev *mtdblk; -- unsigned int res; -- -- for (;;) { -- INIT_REQUEST; -- req = CURRENT; -- spin_unlock_irq(&io_request_lock); -- mtdblk = mtdblks[MINOR(req->rq_dev)]; -- res = 0; -- -- if (MINOR(req->rq_dev) >= MAX_MTD_DEVICES) -- panic("%s: minor out of bounds", __FUNCTION__); -- -- if ((req->sector + req->current_nr_sectors) > (mtdblk->mtd->size >> 9)) -- goto end_req; -- -- // Handle the request -- switch (req->cmd) -- { -- int err; -- -- case READ: -- down(&mtdblk->cache_sem); -- err = do_cached_read (mtdblk, req->sector << 9, -- req->current_nr_sectors << 9, -- req->buffer); -- up(&mtdblk->cache_sem); -- if (!err) -- res = 1; -- break; -- -- case WRITE: -- // Read only device -- if ( !(mtdblk->mtd->flags & MTD_WRITEABLE) ) -- break; -- -- // Do the write -- down(&mtdblk->cache_sem); -- err = do_cached_write (mtdblk, req->sector << 9, -- req->current_nr_sectors << 9, -- req->buffer); -- up(&mtdblk->cache_sem); -- if (!err) -- res = 1; -- break; -- } -- --end_req: -- spin_lock_irq(&io_request_lock); -- end_request(res); -- } --} -- --static volatile int leaving = 0; --static DECLARE_MUTEX_LOCKED(thread_sem); --static DECLARE_WAIT_QUEUE_HEAD(thr_wq); -- --int mtdblock_thread(void *dummy) --{ -- struct task_struct *tsk = current; -- DECLARE_WAITQUEUE(wait, tsk); -- -- /* we might get involved when memory gets low, so use PF_MEMALLOC */ -- tsk->flags |= PF_MEMALLOC; -- strcpy(tsk->comm, "mtdblockd"); -- spin_lock_irq(&tsk->sigmask_lock); -- sigfillset(&tsk->blocked); -- recalc_sigpending(tsk); -- spin_unlock_irq(&tsk->sigmask_lock); -- daemonize(); -- -- while (!leaving) { -- add_wait_queue(&thr_wq, &wait); -- set_current_state(TASK_INTERRUPTIBLE); -- spin_lock_irq(&io_request_lock); -- if (QUEUE_EMPTY || QUEUE_PLUGGED) { -- spin_unlock_irq(&io_request_lock); -- schedule(); -- remove_wait_queue(&thr_wq, &wait); -- } else { -- remove_wait_queue(&thr_wq, &wait); -- set_current_state(TASK_RUNNING); -- handle_mtdblock_request(); -- spin_unlock_irq(&io_request_lock); -- } -- } -- -- up(&thread_sem); - return 0; - } - --#if LINUX_VERSION_CODE < 0x20300 --#define RQFUNC_ARG void --#else --#define RQFUNC_ARG request_queue_t *q --#endif -- --static void mtdblock_request(RQFUNC_ARG) -+static int mtdblock_flush(struct mtd_blktrans_dev *dev) - { -- /* Don't do anything, except wake the thread if necessary */ -- wake_up(&thr_wq); --} -+ struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; - -- --static int mtdblock_ioctl(struct inode * inode, struct file * file, -- unsigned int cmd, unsigned long arg) --{ -- struct mtdblk_dev *mtdblk; -- -- mtdblk = mtdblks[MINOR(inode->i_rdev)]; -- --#ifdef PARANOIA -- if (!mtdblk) -- BUG(); --#endif -- -- switch (cmd) { -- case BLKGETSIZE: /* Return device size */ -- return put_user((mtdblk->mtd->size >> 9), (unsigned long *) arg); -- --#ifdef BLKGETSIZE64 -- case BLKGETSIZE64: -- return put_user((u64)mtdblk->mtd->size, (u64 *)arg); --#endif -- -- case BLKFLSBUF: --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) -- if(!capable(CAP_SYS_ADMIN)) -- return -EACCES; --#endif -- fsync_dev(inode->i_rdev); -- invalidate_buffers(inode->i_rdev); - down(&mtdblk->cache_sem); - write_cached_data(mtdblk); - up(&mtdblk->cache_sem); -+ - if (mtdblk->mtd->sync) - mtdblk->mtd->sync(mtdblk->mtd); - return 0; -- -- default: -- return -EINVAL; -- } - } - --#if LINUX_VERSION_CODE < 0x20326 --static struct file_operations mtd_fops = -+static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) - { -- open: mtdblock_open, -- ioctl: mtdblock_ioctl, -- release: mtdblock_release, -- read: block_read, -- write: block_write --}; --#else --static struct block_device_operations mtd_fops = --{ --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14) -- owner: THIS_MODULE, --#endif -- open: mtdblock_open, -- release: mtdblock_release, -- ioctl: mtdblock_ioctl --}; --#endif -+ struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL); - --#ifdef CONFIG_DEVFS_FS --/* Notification that a new device has been added. Create the devfs entry for -- * it. */ -- --static void mtd_notify_add(struct mtd_info* mtd) --{ -- char name[8]; -- -- if (!mtd || mtd->type == MTD_ABSENT) -+ if (!dev) - return; - -- sprintf(name, "%d", mtd->index); -- devfs_rw_handle[mtd->index] = devfs_register(devfs_dir_handle, name, -- DEVFS_FL_DEFAULT, MTD_BLOCK_MAJOR, mtd->index, -- S_IFBLK | S_IRUGO | S_IWUGO, -- &mtd_fops, NULL); --} -- --static void mtd_notify_remove(struct mtd_info* mtd) --{ -- if (!mtd || mtd->type == MTD_ABSENT) -- return; -+ memset(dev, 0, sizeof(*dev)); - -- devfs_unregister(devfs_rw_handle[mtd->index]); --} --#endif -+ dev->mtd = mtd; -+ dev->devnum = mtd->index; -+ dev->blksize = 512; -+ dev->size = mtd->size >> 9; -+ dev->tr = tr; -+ -+ if (!(mtd->flags & MTD_WRITEABLE)) -+ dev->readonly = 1; -+ -+ add_mtd_blktrans_dev(dev); -+} -+ -+static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev) -+{ -+ del_mtd_blktrans_dev(dev); -+ kfree(dev); -+} -+ -+struct mtd_blktrans_ops mtdblock_tr = { -+ .name = "mtdblock", -+ .major = 31, -+ .part_bits = 0, -+ .open = mtdblock_open, -+ .flush = mtdblock_flush, -+ .release = mtdblock_release, -+ .readsect = mtdblock_readsect, -+ .writesect = mtdblock_writesect, -+ .add_mtd = mtdblock_add_mtd, -+ .remove_dev = mtdblock_remove_dev, -+ .owner = THIS_MODULE, -+}; - - int __init init_mtdblock(void) - { -- int i; -- -- spin_lock_init(&mtdblks_lock); --#ifdef CONFIG_DEVFS_FS -- if (devfs_register_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME, &mtd_fops)) -- { -- printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", -- MTD_BLOCK_MAJOR); -- return -EAGAIN; -- } -- -- devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL); -- register_mtd_user(¬ifier); --#else -- if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { -- printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", -- MTD_BLOCK_MAJOR); -- return -EAGAIN; -- } --#endif -- -- /* We fill it in at open() time. */ -- for (i=0; i< MAX_MTD_DEVICES; i++) { -- mtd_sizes[i] = 0; -- mtd_blksizes[i] = BLOCK_SIZE; -- } -- init_waitqueue_head(&thr_wq); -- /* Allow the block size to default to BLOCK_SIZE. */ -- blksize_size[MAJOR_NR] = mtd_blksizes; -- blk_size[MAJOR_NR] = mtd_sizes; -- -- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request); -- kernel_thread (mtdblock_thread, NULL, CLONE_FS|CLONE_FILES|CLONE_SIGHAND); -- return 0; -+ return register_mtd_blktrans(&mtdblock_tr); - } - - static void __exit cleanup_mtdblock(void) - { -- leaving = 1; -- wake_up(&thr_wq); -- down(&thread_sem); --#ifdef CONFIG_DEVFS_FS -- unregister_mtd_user(¬ifier); -- devfs_unregister(devfs_dir_handle); -- devfs_unregister_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME); --#else -- unregister_blkdev(MAJOR_NR,DEVICE_NAME); --#endif -- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); -- blksize_size[MAJOR_NR] = NULL; -- blk_size[MAJOR_NR] = NULL; -+ deregister_mtd_blktrans(&mtdblock_tr); - } - - module_init(init_mtdblock); -diff -Nurb linux-mips-2.4.27/drivers/mtd/mtdblock_ro.c linux/drivers/mtd/mtdblock_ro.c ---- linux-mips-2.4.27/drivers/mtd/mtdblock_ro.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/mtdblock_ro.c 2004-11-19 10:25:11.645238400 +0100 -@@ -1,301 +1,87 @@ - /* -- * $Id$ -+ * $Id$ - * -- * Read-only version of the mtdblock device, without the -- * read/erase/modify/writeback stuff -+ * (C) 2003 David Woodhouse -+ * -+ * Simple read-only (writable only for RAM) mtdblock driver - */ - --#ifdef MTDBLOCK_DEBUG --#define DEBUGLVL debug --#endif -- -- --#include --#include -- -+#include -+#include - #include --#include -- --#define MAJOR_NR MTD_BLOCK_MAJOR --#define DEVICE_NAME "mtdblock" --#define DEVICE_REQUEST mtdblock_request --#define DEVICE_NR(device) (device) --#define DEVICE_ON(device) --#define DEVICE_OFF(device) --#define DEVICE_NO_RANDOM --#include -- --#if LINUX_VERSION_CODE < 0x20300 --#define RQFUNC_ARG void --#define blkdev_dequeue_request(req) do {CURRENT = req->next;} while (0) --#else --#define RQFUNC_ARG request_queue_t *q --#endif -- --#ifdef MTDBLOCK_DEBUG --static int debug = MTDBLOCK_DEBUG; --MODULE_PARM(debug, "i"); --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14) --#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT --#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT --#else --#define BLK_INC_USE_COUNT do {} while(0) --#define BLK_DEC_USE_COUNT do {} while(0) --#endif -- --static int mtd_sizes[MAX_MTD_DEVICES]; -+#include - -- --static int mtdblock_open(struct inode *inode, struct file *file) -+static int mtdblock_readsect(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buf) - { -- struct mtd_info *mtd = NULL; -- -- int dev; -- -- DEBUG(1,"mtdblock_open\n"); -- -- if (inode == 0) -- return -EINVAL; -- -- dev = MINOR(inode->i_rdev); -- -- mtd = get_mtd_device(NULL, dev); -- if (!mtd) -- return -EINVAL; -- if (MTD_ABSENT == mtd->type) { -- put_mtd_device(mtd); -- return -EINVAL; -- } -- -- BLK_INC_USE_COUNT; -- -- mtd_sizes[dev] = mtd->size>>9; -- -- DEBUG(1, "ok\n"); -+ size_t retlen; - -+ if (dev->mtd->read(dev->mtd, (block * 512), 512, &retlen, buf)) -+ return 1; - return 0; - } - --static release_t mtdblock_release(struct inode *inode, struct file *file) -+static int mtdblock_writesect(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buf) - { -- int dev; -- struct mtd_info *mtd; -- -- DEBUG(1, "mtdblock_release\n"); -- -- if (inode == NULL) -- release_return(-ENODEV); -- -- dev = MINOR(inode->i_rdev); -- mtd = __get_mtd_device(NULL, dev); -- -- if (!mtd) { -- printk(KERN_WARNING "MTD device is absent on mtd_release!\n"); -- BLK_DEC_USE_COUNT; -- release_return(-ENODEV); -- } -- -- if (mtd->sync) -- mtd->sync(mtd); -- -- put_mtd_device(mtd); -- -- DEBUG(1, "ok\n"); -+ size_t retlen; - -- BLK_DEC_USE_COUNT; -- release_return(0); -+ if (dev->mtd->write(dev->mtd, (block * 512), 512, &retlen, buf)) -+ return 1; -+ return 0; - } - -- --static void mtdblock_request(RQFUNC_ARG) -+static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) - { -- struct request *current_request; -- unsigned int res = 0; -- struct mtd_info *mtd; -- -- while (1) -- { -- /* Grab the Request and unlink it from the request list, INIT_REQUEST -- will execute a return if we are done. */ -- INIT_REQUEST; -- current_request = CURRENT; -- -- if (MINOR(current_request->rq_dev) >= MAX_MTD_DEVICES) -- { -- printk("mtd: Unsupported device!\n"); -- end_request(0); -- continue; -- } -- -- // Grab our MTD structure -- -- mtd = __get_mtd_device(NULL, MINOR(current_request->rq_dev)); -- if (!mtd) { -- printk("MTD device %d doesn't appear to exist any more\n", CURRENT_DEV); -- end_request(0); -- } -- -- if (current_request->sector << 9 > mtd->size || -- (current_request->sector + current_request->current_nr_sectors) << 9 > mtd->size) -- { -- printk("mtd: Attempt to read past end of device!\n"); -- printk("size: %x, sector: %lx, nr_sectors %lx\n", mtd->size, -- current_request->sector, current_request->current_nr_sectors); -- end_request(0); -- continue; -- } -- -- /* Remove the request we are handling from the request list so nobody messes -- with it */ --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) -- /* Now drop the lock that the ll_rw_blk functions grabbed for us -- and process the request. This is necessary due to the extreme time -- we spend processing it. */ -- spin_unlock_irq(&io_request_lock); --#endif -- -- // Handle the request -- switch (current_request->cmd) -- { -- size_t retlen; -+ struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL); - -- case READ: -- if (MTD_READ(mtd,current_request->sector<<9, -- current_request->current_nr_sectors << 9, -- &retlen, current_request->buffer) == 0) -- res = 1; -- else -- res = 0; -- break; -+ if (!dev) -+ return; - -- case WRITE: -+ memset(dev, 0, sizeof(*dev)); - -- /* printk("mtdblock_request WRITE sector=%d(%d)\n",current_request->sector, -- current_request->current_nr_sectors); -- */ -+ dev->mtd = mtd; -+ dev->devnum = mtd->index; -+ dev->blksize = 512; -+ dev->size = mtd->size >> 9; -+ dev->tr = tr; -+ if ((mtd->flags & (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEABLE)) != -+ (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEABLE)) -+ dev->readonly = 1; - -- // Read only device -- if ((mtd->flags & MTD_CAP_RAM) == 0) -- { -- res = 0; -- break; -- } -- -- // Do the write -- if (MTD_WRITE(mtd,current_request->sector<<9, -- current_request->current_nr_sectors << 9, -- &retlen, current_request->buffer) == 0) -- res = 1; -- else -- res = 0; -- break; -- -- // Shouldn't happen -- default: -- printk("mtd: unknown request\n"); -- break; -- } -- -- // Grab the lock and re-thread the item onto the linked list --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) -- spin_lock_irq(&io_request_lock); --#endif -- end_request(res); -- } -+ add_mtd_blktrans_dev(dev); - } - -- -- --static int mtdblock_ioctl(struct inode * inode, struct file * file, -- unsigned int cmd, unsigned long arg) -+static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev) - { -- struct mtd_info *mtd; -- -- mtd = __get_mtd_device(NULL, MINOR(inode->i_rdev)); -- -- if (!mtd) return -EINVAL; -- -- switch (cmd) { -- case BLKGETSIZE: /* Return device size */ -- return put_user((mtd->size >> 9), (unsigned long *) arg); -- --#ifdef BLKGETSIZE64 -- case BLKGETSIZE64: -- return put_user((u64)mtd->size, (u64 *)arg); --#endif -- -- case BLKFLSBUF: --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) -- if(!capable(CAP_SYS_ADMIN)) return -EACCES; --#endif -- fsync_dev(inode->i_rdev); -- invalidate_buffers(inode->i_rdev); -- if (mtd->sync) -- mtd->sync(mtd); -- return 0; -- -- default: -- return -ENOTTY; -- } -+ del_mtd_blktrans_dev(dev); -+ kfree(dev); - } - --#if LINUX_VERSION_CODE < 0x20326 --static struct file_operations mtd_fops = --{ -- open: mtdblock_open, -- ioctl: mtdblock_ioctl, -- release: mtdblock_release, -- read: block_read, -- write: block_write --}; --#else --static struct block_device_operations mtd_fops = --{ --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14) -- owner: THIS_MODULE, --#endif -- open: mtdblock_open, -- release: mtdblock_release, -- ioctl: mtdblock_ioctl -+struct mtd_blktrans_ops mtdblock_tr = { -+ .name = "mtdblock", -+ .major = 31, -+ .part_bits = 0, -+ .readsect = mtdblock_readsect, -+ .writesect = mtdblock_writesect, -+ .add_mtd = mtdblock_add_mtd, -+ .remove_dev = mtdblock_remove_dev, -+ .owner = THIS_MODULE, - }; --#endif - --int __init init_mtdblock(void) -+static int __init mtdblock_init(void) - { -- int i; -- -- if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { -- printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", -- MTD_BLOCK_MAJOR); -- return -EAGAIN; -- } -- -- /* We fill it in at open() time. */ -- for (i=0; i< MAX_MTD_DEVICES; i++) { -- mtd_sizes[i] = 0; -- } -- -- /* Allow the block size to default to BLOCK_SIZE. */ -- blksize_size[MAJOR_NR] = NULL; -- blk_size[MAJOR_NR] = mtd_sizes; -- -- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request); -- return 0; -+ return register_mtd_blktrans(&mtdblock_tr); - } - --static void __exit cleanup_mtdblock(void) -+static void __exit mtdblock_exit(void) - { -- unregister_blkdev(MAJOR_NR,DEVICE_NAME); -- blk_size[MAJOR_NR] = NULL; -- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); -+ deregister_mtd_blktrans(&mtdblock_tr); - } - --module_init(init_mtdblock); --module_exit(cleanup_mtdblock); -- -+module_init(mtdblock_init); -+module_exit(mtdblock_exit); - - MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Erwin Authried et al."); -+MODULE_AUTHOR("David Woodhouse "); - MODULE_DESCRIPTION("Simple read-only block device emulation access to MTD devices"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/mtdchar.c linux/drivers/mtd/mtdchar.c ---- linux-mips-2.4.27/drivers/mtd/mtdchar.c 2004-08-14 20:38:51.000000000 +0200 -+++ linux/drivers/mtd/mtdchar.c 2004-11-19 10:25:11.647238096 +0100 -@@ -1,8 +1,7 @@ - /* -- * $Id$ -+ * $Id$ - * - * Character-device access to raw MTD devices. -- * Pure 2.4 version - compatibility cruft removed to mtdchar-compat.c - * - */ - -@@ -10,7 +9,11 @@ - #include - #include - #include -+#include - #include -+#include -+#include -+#include - - #ifdef CONFIG_DEVFS_FS - #include -@@ -18,8 +21,8 @@ - static void mtd_notify_remove(struct mtd_info* mtd); - - static struct mtd_notifier notifier = { -- add: mtd_notify_add, -- remove: mtd_notify_remove, -+ .add = mtd_notify_add, -+ .remove = mtd_notify_remove, - }; - - static devfs_handle_t devfs_dir_handle; -@@ -60,7 +63,7 @@ - - static int mtd_open(struct inode *inode, struct file *file) - { -- int minor = minor(inode->i_rdev); -+ int minor = iminor(inode); - int devnum = minor >> 1; - struct mtd_info *mtd; - -@@ -125,15 +128,11 @@ - int ret=0; - int len; - char *kbuf; -- loff_t pos = *ppos; - - DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n"); - -- if (pos < 0 || pos > mtd->size) -- return 0; -- -- if (count > mtd->size - pos) -- count = mtd->size - pos; -+ if (*ppos + count > mtd->size) -+ count = mtd->size - *ppos; - - if (!count) - return 0; -@@ -150,9 +149,9 @@ - if (!kbuf) - return -ENOMEM; - -- ret = MTD_READ(mtd, pos, len, &retlen, kbuf); -+ ret = MTD_READ(mtd, *ppos, len, &retlen, kbuf); - if (!ret) { -- pos += retlen; -+ *ppos += retlen; - if (copy_to_user(buf, kbuf, retlen)) { - kfree(kbuf); - return -EFAULT; -@@ -171,8 +170,6 @@ - kfree(kbuf); - } - -- *ppos = pos; -- - return total_retlen; - } /* mtd_read */ - -@@ -182,17 +179,16 @@ - char *kbuf; - size_t retlen; - size_t total_retlen=0; -- loff_t pos = *ppos; - int ret=0; - int len; - - DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n"); - -- if (pos < 0 || pos >= mtd->size) -+ if (*ppos == mtd->size) - return -ENOSPC; - -- if (count > mtd->size - pos) -- count = mtd->size - pos; -+ if (*ppos + count > mtd->size) -+ count = mtd->size - *ppos; - - if (!count) - return 0; -@@ -214,9 +210,9 @@ - return -EFAULT; - } - -- ret = (*(mtd->write))(mtd, pos, len, &retlen, kbuf); -+ ret = (*(mtd->write))(mtd, *ppos, len, &retlen, kbuf); - if (!ret) { -- pos += retlen; -+ *ppos += retlen; - total_retlen += retlen; - count -= retlen; - buf += retlen; -@@ -228,7 +224,6 @@ - - kfree(kbuf); - } -- *ppos = pos; - - return total_retlen; - } /* mtd_write */ -@@ -450,81 +445,13 @@ - break; - } - -- case MEMWRITEDATA: -- { -- struct mtd_oob_buf buf; -- void *databuf; -- ssize_t retlen; -- -- if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf))) -- return -EFAULT; -- -- if (buf.length > 0x4096) -- return -EINVAL; -- -- if (!mtd->write_ecc) -- ret = -EOPNOTSUPP; -- else -- ret = verify_area(VERIFY_READ, (char *)buf.ptr, buf.length); -- -- if (ret) -- return ret; -- -- databuf = kmalloc(buf.length, GFP_KERNEL); -- if (!databuf) -- return -ENOMEM; -- -- if (copy_from_user(databuf, buf.ptr, buf.length)) { -- kfree(databuf); -- return -EFAULT; -- } -- -- ret = (mtd->write_ecc)(mtd, buf.start, buf.length, &retlen, databuf, NULL, 0); -- -- if (copy_to_user((void *)arg + sizeof(u_int32_t), &retlen, sizeof(u_int32_t))) -- ret = -EFAULT; -- -- kfree(databuf); -- break; -- -- } -- -- case MEMREADDATA: -+ case MEMSETOOBSEL: - { -- struct mtd_oob_buf buf; -- void *databuf; -- ssize_t retlen = 0; -- -- if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf))) -+ if (copy_from_user(&mtd->oobinfo ,(void *)arg, sizeof(struct nand_oobinfo))) - return -EFAULT; -- -- if (buf.length > 0x4096) -- return -EINVAL; -- -- if (!mtd->read_ecc) -- ret = -EOPNOTSUPP; -- else -- ret = verify_area(VERIFY_WRITE, (char *)buf.ptr, buf.length); -- -- if (ret) -- return ret; -- -- databuf = kmalloc(buf.length, GFP_KERNEL); -- if (!databuf) -- return -ENOMEM; -- -- ret = (mtd->read_ecc)(mtd, buf.start, buf.length, &retlen, databuf, NULL, 0); -- -- if (copy_to_user((void *)arg + sizeof(u_int32_t), &retlen, sizeof(u_int32_t))) -- ret = -EFAULT; -- else if (retlen && copy_to_user(buf.ptr, databuf, retlen)) -- ret = -EFAULT; -- -- kfree(databuf); - break; - } - -- - default: - DEBUG(MTD_DEBUG_LEVEL0, "Invalid ioctl %x (MEMGETINFO = %x)\n", cmd, MEMGETINFO); - ret = -ENOTTY; -@@ -534,13 +461,13 @@ - } /* memory_ioctl */ - - static struct file_operations mtd_fops = { -- owner: THIS_MODULE, -- llseek: mtd_lseek, /* lseek */ -- read: mtd_read, /* read */ -- write: mtd_write, /* write */ -- ioctl: mtd_ioctl, /* ioctl */ -- open: mtd_open, /* open */ -- release: mtd_close, /* release */ -+ .owner = THIS_MODULE, -+ .llseek = mtd_lseek, -+ .read = mtd_read, -+ .write = mtd_write, -+ .ioctl = mtd_ioctl, -+ .open = mtd_open, -+ .release = mtd_close, - }; - - -@@ -580,26 +507,18 @@ - - static int __init init_mtdchar(void) - { --#ifdef CONFIG_DEVFS_FS -- if (devfs_register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) -+ if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) - { - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", - MTD_CHAR_MAJOR); - return -EAGAIN; - } - -+#ifdef CONFIG_DEVFS_FS - devfs_dir_handle = devfs_mk_dir(NULL, "mtd", NULL); - - register_mtd_user(¬ifier); --#else -- if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) -- { -- printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", -- MTD_CHAR_MAJOR); -- return -EAGAIN; -- } - #endif -- - return 0; - } - -@@ -608,10 +527,8 @@ - #ifdef CONFIG_DEVFS_FS - unregister_mtd_user(¬ifier); - devfs_unregister(devfs_dir_handle); -- devfs_unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); --#else -- unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); - #endif -+ unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); - } - - module_init(init_mtdchar); -diff -Nurb linux-mips-2.4.27/drivers/mtd/mtdconcat.c linux/drivers/mtd/mtdconcat.c ---- linux-mips-2.4.27/drivers/mtd/mtdconcat.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/mtdconcat.c 2004-11-19 10:25:11.649237792 +0100 -@@ -3,9 +3,11 @@ - * - * (C) 2002 Robert Kaiser - * -+ * NAND support by Christian Gan -+ * - * This code is GPL - * -- * $Id$ -+ * $Id$ - */ - - #include -@@ -35,21 +37,20 @@ - #define SIZEOF_STRUCT_MTD_CONCAT(num_subdev) \ - ((sizeof(struct mtd_concat) + (num_subdev) * sizeof(struct mtd_info *))) - -- - /* - * Given a pointer to the MTD object in the mtd_concat structure, - * we can retrieve the pointer to that structure with this macro. - */ - #define CONCAT(x) ((struct mtd_concat *)(x)) - -- - /* - * MTD methods which look up the relevant subdevice, translate the - * effective address and pass through to the subdevice. - */ - --static int concat_read (struct mtd_info *mtd, loff_t from, size_t len, -- size_t *retlen, u_char *buf) -+static int -+concat_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t * retlen, u_char * buf) - { - struct mtd_concat *concat = CONCAT(mtd); - int err = -EINVAL; -@@ -57,43 +58,43 @@ - - *retlen = 0; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size, retsize; - -- if (from >= subdev->size) -- { -+ if (from >= subdev->size) { -+ /* Not destined for this subdev */ - size = 0; - from -= subdev->size; -+ continue; - } -- else -- { - if (from + len > subdev->size) -+ /* First part goes into this subdev */ - size = subdev->size - from; - else -+ /* Entire transaction goes into this subdev */ - size = len; - - err = subdev->read(subdev, from, size, &retsize, buf); - -- if(err) -+ if (err) - break; - - *retlen += retsize; - len -= size; -- if(len == 0) -+ if (len == 0) - break; - - err = -EINVAL; - buf += size; - from = 0; - } -- } - return err; - } - --static int concat_write (struct mtd_info *mtd, loff_t to, size_t len, -- size_t *retlen, const u_char *buf) -+static int -+concat_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t * retlen, const u_char * buf) - { - struct mtd_concat *concat = CONCAT(mtd); - int err = -EINVAL; -@@ -104,18 +105,15 @@ - - *retlen = 0; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size, retsize; - -- if (to >= subdev->size) -- { -+ if (to >= subdev->size) { - size = 0; - to -= subdev->size; -+ continue; - } -- else -- { - if (to + len > subdev->size) - size = subdev->size - to; - else -@@ -126,25 +124,232 @@ - else - err = subdev->write(subdev, to, size, &retsize, buf); - -- if(err) -+ if (err) - break; - - *retlen += retsize; - len -= size; -- if(len == 0) -+ if (len == 0) - break; - - err = -EINVAL; - buf += size; - to = 0; - } -+ return err; -+} -+ -+static int -+concat_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t * retlen, u_char * buf, u_char * eccbuf, -+ struct nand_oobinfo *oobsel) -+{ -+ struct mtd_concat *concat = CONCAT(mtd); -+ int err = -EINVAL; -+ int i; -+ -+ *retlen = 0; -+ -+ for (i = 0; i < concat->num_subdev; i++) { -+ struct mtd_info *subdev = concat->subdev[i]; -+ size_t size, retsize; -+ -+ if (from >= subdev->size) { -+ /* Not destined for this subdev */ -+ size = 0; -+ from -= subdev->size; -+ continue; -+ } -+ -+ if (from + len > subdev->size) -+ /* First part goes into this subdev */ -+ size = subdev->size - from; -+ else -+ /* Entire transaction goes into this subdev */ -+ size = len; -+ -+ if (subdev->read_ecc) -+ err = subdev->read_ecc(subdev, from, size, -+ &retsize, buf, eccbuf, oobsel); -+ else -+ err = -EINVAL; -+ -+ if (err) -+ break; -+ -+ *retlen += retsize; -+ len -= size; -+ if (len == 0) -+ break; -+ -+ err = -EINVAL; -+ buf += size; -+ if (eccbuf) { -+ eccbuf += subdev->oobsize; -+ /* in nand.c at least, eccbufs are -+ tagged with 2 (int)eccstatus'; we -+ must account for these */ -+ eccbuf += 2 * (sizeof (int)); -+ } -+ from = 0; - } - return err; - } - --static void concat_erase_callback (struct erase_info *instr) -+static int -+concat_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t * retlen, const u_char * buf, u_char * eccbuf, -+ struct nand_oobinfo *oobsel) - { -- wake_up((wait_queue_head_t *)instr->priv); -+ struct mtd_concat *concat = CONCAT(mtd); -+ int err = -EINVAL; -+ int i; -+ -+ if (!(mtd->flags & MTD_WRITEABLE)) -+ return -EROFS; -+ -+ *retlen = 0; -+ -+ for (i = 0; i < concat->num_subdev; i++) { -+ struct mtd_info *subdev = concat->subdev[i]; -+ size_t size, retsize; -+ -+ if (to >= subdev->size) { -+ size = 0; -+ to -= subdev->size; -+ continue; -+ } -+ if (to + len > subdev->size) -+ size = subdev->size - to; -+ else -+ size = len; -+ -+ if (!(subdev->flags & MTD_WRITEABLE)) -+ err = -EROFS; -+ else if (subdev->write_ecc) -+ err = subdev->write_ecc(subdev, to, size, -+ &retsize, buf, eccbuf, oobsel); -+ else -+ err = -EINVAL; -+ -+ if (err) -+ break; -+ -+ *retlen += retsize; -+ len -= size; -+ if (len == 0) -+ break; -+ -+ err = -EINVAL; -+ buf += size; -+ if (eccbuf) -+ eccbuf += subdev->oobsize; -+ to = 0; -+ } -+ return err; -+} -+ -+static int -+concat_read_oob(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t * retlen, u_char * buf) -+{ -+ struct mtd_concat *concat = CONCAT(mtd); -+ int err = -EINVAL; -+ int i; -+ -+ *retlen = 0; -+ -+ for (i = 0; i < concat->num_subdev; i++) { -+ struct mtd_info *subdev = concat->subdev[i]; -+ size_t size, retsize; -+ -+ if (from >= subdev->size) { -+ /* Not destined for this subdev */ -+ size = 0; -+ from -= subdev->size; -+ continue; -+ } -+ if (from + len > subdev->size) -+ /* First part goes into this subdev */ -+ size = subdev->size - from; -+ else -+ /* Entire transaction goes into this subdev */ -+ size = len; -+ -+ if (subdev->read_oob) -+ err = subdev->read_oob(subdev, from, size, -+ &retsize, buf); -+ else -+ err = -EINVAL; -+ -+ if (err) -+ break; -+ -+ *retlen += retsize; -+ len -= size; -+ if (len == 0) -+ break; -+ -+ err = -EINVAL; -+ buf += size; -+ from = 0; -+ } -+ return err; -+} -+ -+static int -+concat_write_oob(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t * retlen, const u_char * buf) -+{ -+ struct mtd_concat *concat = CONCAT(mtd); -+ int err = -EINVAL; -+ int i; -+ -+ if (!(mtd->flags & MTD_WRITEABLE)) -+ return -EROFS; -+ -+ *retlen = 0; -+ -+ for (i = 0; i < concat->num_subdev; i++) { -+ struct mtd_info *subdev = concat->subdev[i]; -+ size_t size, retsize; -+ -+ if (to >= subdev->size) { -+ size = 0; -+ to -= subdev->size; -+ continue; -+ } -+ if (to + len > subdev->size) -+ size = subdev->size - to; -+ else -+ size = len; -+ -+ if (!(subdev->flags & MTD_WRITEABLE)) -+ err = -EROFS; -+ else if (subdev->write_oob) -+ err = subdev->write_oob(subdev, to, size, &retsize, -+ buf); -+ else -+ err = -EINVAL; -+ -+ if (err) -+ break; -+ -+ *retlen += retsize; -+ len -= size; -+ if (len == 0) -+ break; -+ -+ err = -EINVAL; -+ buf += size; -+ to = 0; -+ } -+ return err; -+} -+ -+static void concat_erase_callback(struct erase_info *instr) -+{ -+ wake_up((wait_queue_head_t *) instr->priv); - } - - static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase) -@@ -160,18 +365,18 @@ - - erase->mtd = mtd; - erase->callback = concat_erase_callback; -- erase->priv = (unsigned long)&waitq; -+ erase->priv = (unsigned long) &waitq; - - /* - * FIXME: Allow INTERRUPTIBLE. Which means - * not having the wait_queue head on the stack. - */ - err = mtd->erase(mtd, erase); -- if (!err) -- { -+ if (!err) { - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&waitq, &wait); -- if (erase->state != MTD_ERASE_DONE && erase->state != MTD_ERASE_FAILED) -+ if (erase->state != MTD_ERASE_DONE -+ && erase->state != MTD_ERASE_FAILED) - schedule(); - remove_wait_queue(&waitq, &wait); - set_current_state(TASK_RUNNING); -@@ -181,7 +386,7 @@ - return err; - } - --static int concat_erase (struct mtd_info *mtd, struct erase_info *instr) -+static int concat_erase(struct mtd_info *mtd, struct erase_info *instr) - { - struct mtd_concat *concat = CONCAT(mtd); - struct mtd_info *subdev; -@@ -192,10 +397,10 @@ - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; - -- if(instr->addr > concat->mtd.size) -+ if (instr->addr > concat->mtd.size) - return -EINVAL; - -- if(instr->len + instr->addr > concat->mtd.size) -+ if (instr->len + instr->addr > concat->mtd.size) - return -EINVAL; - - /* -@@ -204,23 +409,22 @@ - * region info rather than looking at each particular sub-device - * in turn. - */ -- if (!concat->mtd.numeraseregions) -- { /* the easy case: device has uniform erase block size */ -- if(instr->addr & (concat->mtd.erasesize - 1)) -+ if (!concat->mtd.numeraseregions) { -+ /* the easy case: device has uniform erase block size */ -+ if (instr->addr & (concat->mtd.erasesize - 1)) - return -EINVAL; -- if(instr->len & (concat->mtd.erasesize - 1)) -+ if (instr->len & (concat->mtd.erasesize - 1)) - return -EINVAL; -- } -- else -- { /* device has variable erase size */ -- struct mtd_erase_region_info *erase_regions = concat->mtd.eraseregions; -+ } else { -+ /* device has variable erase size */ -+ struct mtd_erase_region_info *erase_regions = -+ concat->mtd.eraseregions; - - /* - * Find the erase region where the to-be-erased area begins: - */ -- for(i = 0; i < concat->mtd.numeraseregions && -- instr->addr >= erase_regions[i].offset; i++) -- ; -+ for (i = 0; i < concat->mtd.numeraseregions && -+ instr->addr >= erase_regions[i].offset; i++) ; - --i; - - /* -@@ -228,25 +432,26 @@ - * to-be-erased area begins. Verify that the starting - * offset is aligned to this region's erase size: - */ -- if (instr->addr & (erase_regions[i].erasesize-1)) -+ if (instr->addr & (erase_regions[i].erasesize - 1)) - return -EINVAL; - - /* - * now find the erase region where the to-be-erased area ends: - */ -- for(; i < concat->mtd.numeraseregions && -- (instr->addr + instr->len) >= erase_regions[i].offset ; ++i) -- ; -+ for (; i < concat->mtd.numeraseregions && -+ (instr->addr + instr->len) >= erase_regions[i].offset; -+ ++i) ; - --i; - /* - * check if the ending offset is aligned to this region's erase size - */ -- if ((instr->addr + instr->len) & (erase_regions[i].erasesize-1)) -+ if ((instr->addr + instr->len) & (erase_regions[i].erasesize - -+ 1)) - return -EINVAL; - } - - /* make a local copy of instr to avoid modifying the caller's struct */ -- erase = kmalloc(sizeof(struct erase_info),GFP_KERNEL); -+ erase = kmalloc(sizeof (struct erase_info), GFP_KERNEL); - - if (!erase) - return -ENOMEM; -@@ -258,39 +463,40 @@ - * find the subdevice where the to-be-erased area begins, adjust - * starting offset to be relative to the subdevice start - */ -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - subdev = concat->subdev[i]; -- if(subdev->size <= erase->addr) -+ if (subdev->size <= erase->addr) - erase->addr -= subdev->size; - else - break; - } -- if(i >= concat->num_subdev) /* must never happen since size */ -- BUG(); /* limit has been verified above */ -+ -+ /* must never happen since size limit has been verified above */ -+ if (i >= concat->num_subdev) -+ BUG(); - - /* now do the erase: */ - err = 0; -- for(;length > 0; i++) /* loop for all subevices affected by this request */ -- { -+ for (; length > 0; i++) { -+ /* loop for all subdevices affected by this request */ - subdev = concat->subdev[i]; /* get current subdevice */ - - /* limit length to subdevice's size: */ -- if(erase->addr + length > subdev->size) -+ if (erase->addr + length > subdev->size) - erase->len = subdev->size - erase->addr; - else - erase->len = length; - -- if (!(subdev->flags & MTD_WRITEABLE)) -- { -+ if (!(subdev->flags & MTD_WRITEABLE)) { - err = -EROFS; - break; - } - length -= erase->len; -- if ((err = concat_dev_erase(subdev, erase))) -- { -- if(err == -EINVAL) /* sanity check: must never happen since */ -- BUG(); /* block alignment has been checked above */ -+ if ((err = concat_dev_erase(subdev, erase))) { -+ /* sanity check: should never happen since -+ * block alignment has been checked above */ -+ if (err == -EINVAL) -+ BUG(); - break; - } - /* -@@ -313,7 +519,7 @@ - return 0; - } - --static int concat_lock (struct mtd_info *mtd, loff_t ofs, size_t len) -+static int concat_lock(struct mtd_info *mtd, loff_t ofs, size_t len) - { - struct mtd_concat *concat = CONCAT(mtd); - int i, err = -EINVAL; -@@ -321,18 +527,15 @@ - if ((len + ofs) > mtd->size) - return -EINVAL; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size; - -- if (ofs >= subdev->size) -- { -+ if (ofs >= subdev->size) { - size = 0; - ofs -= subdev->size; -+ continue; - } -- else -- { - if (ofs + len > subdev->size) - size = subdev->size - ofs; - else -@@ -340,21 +543,21 @@ - - err = subdev->lock(subdev, ofs, size); - -- if(err) -+ if (err) - break; - - len -= size; -- if(len == 0) -+ if (len == 0) - break; - - err = -EINVAL; - ofs = 0; - } -- } -+ - return err; - } - --static int concat_unlock (struct mtd_info *mtd, loff_t ofs, size_t len) -+static int concat_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) - { - struct mtd_concat *concat = CONCAT(mtd); - int i, err = 0; -@@ -362,18 +565,15 @@ - if ((len + ofs) > mtd->size) - return -EINVAL; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size; - -- if (ofs >= subdev->size) -- { -+ if (ofs >= subdev->size) { - size = 0; - ofs -= subdev->size; -+ continue; - } -- else -- { - if (ofs + len > subdev->size) - size = subdev->size - ofs; - else -@@ -381,17 +581,17 @@ - - err = subdev->unlock(subdev, ofs, size); - -- if(err) -+ if (err) - break; - - len -= size; -- if(len == 0) -+ if (len == 0) - break; - - err = -EINVAL; - ofs = 0; - } -- } -+ - return err; - } - -@@ -400,8 +600,7 @@ - struct mtd_concat *concat = CONCAT(mtd); - int i; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - subdev->sync(subdev); - } -@@ -412,10 +611,9 @@ - struct mtd_concat *concat = CONCAT(mtd); - int i, rc = 0; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; -- if((rc = subdev->suspend(subdev)) < 0) -+ if ((rc = subdev->suspend(subdev)) < 0) - return rc; - } - return rc; -@@ -426,8 +624,7 @@ - struct mtd_concat *concat = CONCAT(mtd); - int i; - -- for(i = 0; i < concat->num_subdev; i++) -- { -+ for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - subdev->resume(subdev); - } -@@ -439,11 +636,10 @@ - * stored to *new_dev upon success. This function does _not_ - * register any devices: this is the caller's responsibility. - */ --struct mtd_info *mtd_concat_create( -- struct mtd_info *subdev[], /* subdevices to concatenate */ -+struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to concatenate */ - int num_devs, /* number of subdevices */ -- char *name) /* name for the new device */ --{ -+ char *name) -+{ /* name for the new device */ - int i; - size_t size; - struct mtd_concat *concat; -@@ -451,21 +647,21 @@ - int num_erase_region; - - printk(KERN_NOTICE "Concatenating MTD devices:\n"); -- for(i = 0; i < num_devs; i++) -+ for (i = 0; i < num_devs; i++) - printk(KERN_NOTICE "(%d): \"%s\"\n", i, subdev[i]->name); - printk(KERN_NOTICE "into device \"%s\"\n", name); - - /* allocate the device structure */ - size = SIZEOF_STRUCT_MTD_CONCAT(num_devs); -- concat = kmalloc (size, GFP_KERNEL); -- if(!concat) -- { -- printk ("memory allocation error while creating concatenated device \"%s\"\n", -+ concat = kmalloc(size, GFP_KERNEL); -+ if (!concat) { -+ printk -+ ("memory allocation error while creating concatenated device \"%s\"\n", - name); - return NULL; - } - memset(concat, 0, size); -- concat->subdev = (struct mtd_info **)(concat + 1); -+ concat->subdev = (struct mtd_info **) (concat + 1); - - /* - * Set up the new "super" device's MTD object structure, check for -@@ -479,39 +675,53 @@ - concat->mtd.oobsize = subdev[0]->oobsize; - concat->mtd.ecctype = subdev[0]->ecctype; - concat->mtd.eccsize = subdev[0]->eccsize; -+ if (subdev[0]->read_ecc) -+ concat->mtd.read_ecc = concat_read_ecc; -+ if (subdev[0]->write_ecc) -+ concat->mtd.write_ecc = concat_write_ecc; -+ if (subdev[0]->read_oob) -+ concat->mtd.read_oob = concat_read_oob; -+ if (subdev[0]->write_oob) -+ concat->mtd.write_oob = concat_write_oob; - - concat->subdev[0] = subdev[0]; - -- for(i = 1; i < num_devs; i++) -- { -- if(concat->mtd.type != subdev[i]->type) -- { -+ for (i = 1; i < num_devs; i++) { -+ if (concat->mtd.type != subdev[i]->type) { - kfree(concat); -- printk ("Incompatible device type on \"%s\"\n", subdev[i]->name); -+ printk("Incompatible device type on \"%s\"\n", -+ subdev[i]->name); - return NULL; - } -- if(concat->mtd.flags != subdev[i]->flags) -- { /* -- * Expect all flags except MTD_WRITEABLE to be equal on -- * all subdevices. -+ if (concat->mtd.flags != subdev[i]->flags) { -+ /* -+ * Expect all flags except MTD_WRITEABLE to be -+ * equal on all subdevices. - */ -- if((concat->mtd.flags ^ subdev[i]->flags) & ~MTD_WRITEABLE) -- { -+ if ((concat->mtd.flags ^ subdev[i]-> -+ flags) & ~MTD_WRITEABLE) { - kfree(concat); -- printk ("Incompatible device flags on \"%s\"\n", subdev[i]->name); -+ printk("Incompatible device flags on \"%s\"\n", -+ subdev[i]->name); - return NULL; -- } -- else /* if writeable attribute differs, make super device writeable */ -- concat->mtd.flags |= subdev[i]->flags & MTD_WRITEABLE; -+ } else -+ /* if writeable attribute differs, -+ make super device writeable */ -+ concat->mtd.flags |= -+ subdev[i]->flags & MTD_WRITEABLE; - } - concat->mtd.size += subdev[i]->size; -- if(concat->mtd.oobblock != subdev[i]->oobblock || -+ if (concat->mtd.oobblock != subdev[i]->oobblock || - concat->mtd.oobsize != subdev[i]->oobsize || - concat->mtd.ecctype != subdev[i]->ecctype || -- concat->mtd.eccsize != subdev[i]->eccsize) -- { -+ concat->mtd.eccsize != subdev[i]->eccsize || -+ !concat->mtd.read_ecc != !subdev[i]->read_ecc || -+ !concat->mtd.write_ecc != !subdev[i]->write_ecc || -+ !concat->mtd.read_oob != !subdev[i]->read_oob || -+ !concat->mtd.write_oob != !subdev[i]->write_oob) { - kfree(concat); -- printk ("Incompatible OOB or ECC data on \"%s\"\n", subdev[i]->name); -+ printk("Incompatible OOB or ECC data on \"%s\"\n", -+ subdev[i]->name); - return NULL; - } - concat->subdev[i] = subdev[i]; -@@ -535,7 +745,6 @@ - concat->mtd.suspend = concat_suspend; - concat->mtd.resume = concat_resume; - -- - /* - * Combine the erase block size info of the subdevices: - * -@@ -544,44 +753,44 @@ - */ - max_erasesize = curr_erasesize = subdev[0]->erasesize; - num_erase_region = 1; -- for(i = 0; i < num_devs; i++) -- { -- if(subdev[i]->numeraseregions == 0) -- { /* current subdevice has uniform erase size */ -- if(subdev[i]->erasesize != curr_erasesize) -- { /* if it differs from the last subdevice's erase size, count it */ -+ for (i = 0; i < num_devs; i++) { -+ if (subdev[i]->numeraseregions == 0) { -+ /* current subdevice has uniform erase size */ -+ if (subdev[i]->erasesize != curr_erasesize) { -+ /* if it differs from the last subdevice's erase size, count it */ - ++num_erase_region; - curr_erasesize = subdev[i]->erasesize; -- if(curr_erasesize > max_erasesize) -+ if (curr_erasesize > max_erasesize) - max_erasesize = curr_erasesize; - } -- } -- else -- { /* current subdevice has variable erase size */ -+ } else { -+ /* current subdevice has variable erase size */ - int j; -- for(j = 0; j < subdev[i]->numeraseregions; j++) -- { /* walk the list of erase regions, count any changes */ -- if(subdev[i]->eraseregions[j].erasesize != curr_erasesize) -- { -+ for (j = 0; j < subdev[i]->numeraseregions; j++) { -+ -+ /* walk the list of erase regions, count any changes */ -+ if (subdev[i]->eraseregions[j].erasesize != -+ curr_erasesize) { - ++num_erase_region; -- curr_erasesize = subdev[i]->eraseregions[j].erasesize; -- if(curr_erasesize > max_erasesize) -+ curr_erasesize = -+ subdev[i]->eraseregions[j]. -+ erasesize; -+ if (curr_erasesize > max_erasesize) - max_erasesize = curr_erasesize; - } - } - } - } - -- if(num_erase_region == 1) -- { /* -+ if (num_erase_region == 1) { -+ /* - * All subdevices have the same uniform erase size. - * This is easy: - */ - concat->mtd.erasesize = curr_erasesize; - concat->mtd.numeraseregions = 0; -- } -- else -- { /* -+ } else { -+ /* - * erase block size varies across the subdevices: allocate - * space to store the data describing the variable erase regions - */ -@@ -590,12 +799,13 @@ - - concat->mtd.erasesize = max_erasesize; - concat->mtd.numeraseregions = num_erase_region; -- concat->mtd.eraseregions = erase_region_p = kmalloc ( -- num_erase_region * sizeof(struct mtd_erase_region_info), GFP_KERNEL); -- if(!erase_region_p) -- { -+ concat->mtd.eraseregions = erase_region_p = -+ kmalloc(num_erase_region * -+ sizeof (struct mtd_erase_region_info), GFP_KERNEL); -+ if (!erase_region_p) { - kfree(concat); -- printk ("memory allocation error while creating erase region list" -+ printk -+ ("memory allocation error while creating erase region list" - " for device \"%s\"\n", name); - return NULL; - } -@@ -606,41 +816,48 @@ - */ - curr_erasesize = subdev[0]->erasesize; - begin = position = 0; -- for(i = 0; i < num_devs; i++) -- { -- if(subdev[i]->numeraseregions == 0) -- { /* current subdevice has uniform erase size */ -- if(subdev[i]->erasesize != curr_erasesize) -- { /* -+ for (i = 0; i < num_devs; i++) { -+ if (subdev[i]->numeraseregions == 0) { -+ /* current subdevice has uniform erase size */ -+ if (subdev[i]->erasesize != curr_erasesize) { -+ /* - * fill in an mtd_erase_region_info structure for the area - * we have walked so far: - */ - erase_region_p->offset = begin; -- erase_region_p->erasesize = curr_erasesize; -- erase_region_p->numblocks = (position - begin) / curr_erasesize; -+ erase_region_p->erasesize = -+ curr_erasesize; -+ erase_region_p->numblocks = -+ (position - begin) / curr_erasesize; - begin = position; - - curr_erasesize = subdev[i]->erasesize; - ++erase_region_p; - } - position += subdev[i]->size; -- } -- else -- { /* current subdevice has variable erase size */ -+ } else { -+ /* current subdevice has variable erase size */ - int j; -- for(j = 0; j < subdev[i]->numeraseregions; j++) -- { /* walk the list of erase regions, count any changes */ -- if(subdev[i]->eraseregions[j].erasesize != curr_erasesize) -- { -+ for (j = 0; j < subdev[i]->numeraseregions; j++) { -+ /* walk the list of erase regions, count any changes */ -+ if (subdev[i]->eraseregions[j]. -+ erasesize != curr_erasesize) { - erase_region_p->offset = begin; -- erase_region_p->erasesize = curr_erasesize; -- erase_region_p->numblocks = (position - begin) / curr_erasesize; -+ erase_region_p->erasesize = -+ curr_erasesize; -+ erase_region_p->numblocks = -+ (position - -+ begin) / curr_erasesize; - begin = position; - -- curr_erasesize = subdev[i]->eraseregions[j].erasesize; -+ curr_erasesize = -+ subdev[i]->eraseregions[j]. -+ erasesize; - ++erase_region_p; - } -- position += subdev[i]->eraseregions[j].numblocks * curr_erasesize; -+ position += -+ subdev[i]->eraseregions[j]. -+ numblocks * curr_erasesize; - } - } - } -@@ -660,16 +877,14 @@ - void mtd_concat_destroy(struct mtd_info *mtd) - { - struct mtd_concat *concat = CONCAT(mtd); -- if(concat->mtd.numeraseregions) -+ if (concat->mtd.numeraseregions) - kfree(concat->mtd.eraseregions); - kfree(concat); - } - -- - EXPORT_SYMBOL(mtd_concat_create); - EXPORT_SYMBOL(mtd_concat_destroy); - -- - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Robert Kaiser "); - MODULE_DESCRIPTION("Generic support for concatenating of MTD devices"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/mtdcore.c linux/drivers/mtd/mtdcore.c ---- linux-mips-2.4.27/drivers/mtd/mtdcore.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/mtdcore.c 2004-11-19 10:25:11.650237640 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Core registration and callback routines for MTD - * drivers and users. -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include - #ifdef CONFIG_PROC_FS - #include -@@ -24,9 +25,15 @@ - - #include - --static DECLARE_MUTEX(mtd_table_mutex); --static struct mtd_info *mtd_table[MAX_MTD_DEVICES]; --static struct mtd_notifier *mtd_notifiers = NULL; -+/* These are exported solely for the purpose of mtd_blkdevs.c. You -+ should not use them for _anything_ else */ -+DECLARE_MUTEX(mtd_table_mutex); -+struct mtd_info *mtd_table[MAX_MTD_DEVICES]; -+ -+EXPORT_SYMBOL_GPL(mtd_table_mutex); -+EXPORT_SYMBOL_GPL(mtd_table); -+ -+static LIST_HEAD(mtd_notifiers); - - /** - * add_mtd_device - register an MTD device -@@ -44,21 +51,28 @@ - - down(&mtd_table_mutex); - -- for (i=0; i< MAX_MTD_DEVICES; i++) -- if (!mtd_table[i]) -- { -- struct mtd_notifier *not=mtd_notifiers; -+ for (i=0; i < MAX_MTD_DEVICES; i++) -+ if (!mtd_table[i]) { -+ struct list_head *this; - - mtd_table[i] = mtd; - mtd->index = i; -+ mtd->usecount = 0; -+ - DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name); -- while (not) -- { -- (*(not->add))(mtd); -- not = not->next; -+ /* No need to get a refcount on the module containing -+ the notifier, since we hold the mtd_table_mutex */ -+ list_for_each(this, &mtd_notifiers) { -+ struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list); -+ not->add(mtd); - } -+ - up(&mtd_table_mutex); -- MOD_INC_USE_COUNT; -+ /* 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 -+ either. :) */ -+ __module_get(THIS_MODULE); - return 0; - } - -@@ -78,29 +92,34 @@ - - int del_mtd_device (struct mtd_info *mtd) - { -- struct mtd_notifier *not=mtd_notifiers; -- int i; -+ int ret; - - down(&mtd_table_mutex); - -- for (i=0; i < MAX_MTD_DEVICES; i++) -- { -- if (mtd_table[i] == mtd) -- { -- while (not) -- { -- (*(not->remove))(mtd); -- not = not->next; -- } -- mtd_table[i] = NULL; -- up (&mtd_table_mutex); -- MOD_DEC_USE_COUNT; -- return 0; -+ if (mtd_table[mtd->index] != mtd) { -+ ret = -ENODEV; -+ } else if (mtd->usecount) { -+ printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n", -+ mtd->index, mtd->name, mtd->usecount); -+ ret = -EBUSY; -+ } else { -+ struct list_head *this; -+ -+ /* No need to get a refcount on the module containing -+ the notifier, since we hold the mtd_table_mutex */ -+ list_for_each(this, &mtd_notifiers) { -+ struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list); -+ not->remove(mtd); - } -+ -+ mtd_table[mtd->index] = NULL; -+ -+ module_put(THIS_MODULE); -+ ret = 0; - } - - up(&mtd_table_mutex); -- return 1; -+ return ret; - } - - /** -@@ -118,10 +137,9 @@ - - down(&mtd_table_mutex); - -- new->next = mtd_notifiers; -- mtd_notifiers = new; -+ list_add(&new->list, &mtd_notifiers); - -- MOD_INC_USE_COUNT; -+ __module_get(THIS_MODULE); - - for (i=0; i< MAX_MTD_DEVICES; i++) - if (mtd_table[i]) -@@ -142,34 +160,24 @@ - - int unregister_mtd_user (struct mtd_notifier *old) - { -- struct mtd_notifier **prev = &mtd_notifiers; -- struct mtd_notifier *cur; - int i; - - down(&mtd_table_mutex); - -- while ((cur = *prev)) { -- if (cur == old) { -- *prev = cur->next; -- -- MOD_DEC_USE_COUNT; -+ module_put(THIS_MODULE); - - for (i=0; i< MAX_MTD_DEVICES; i++) - if (mtd_table[i]) - old->remove(mtd_table[i]); - -+ list_del(&old->list); - up(&mtd_table_mutex); - return 0; -- } -- prev = &cur->next; -- } -- up(&mtd_table_mutex); -- return 1; - } - - - /** -- * __get_mtd_device - obtain a validated handle for an MTD device -+ * get_mtd_device - obtain a validated handle for an MTD device - * @mtd: last known address of the required MTD device - * @num: internal device number of the required MTD device - * -@@ -177,11 +185,10 @@ - * table, if any. Given an address and num == -1, search the device table - * for a device with that address and return if it's still present. Given - * both, return the num'th driver only if its address matches. Return NULL -- * if not. get_mtd_device() increases the use count, but -- * __get_mtd_device() doesn't - you should generally use get_mtd_device(). -+ * if not. - */ - --struct mtd_info *__get_mtd_device(struct mtd_info *mtd, int num) -+struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) - { - struct mtd_info *ret = NULL; - int i; -@@ -198,10 +205,27 @@ - ret = NULL; - } - -+ if (ret && !try_module_get(ret->owner)) -+ ret = NULL; -+ -+ if (ret) -+ ret->usecount++; -+ - up(&mtd_table_mutex); - return ret; - } - -+void put_mtd_device(struct mtd_info *mtd) -+{ -+ int c; -+ -+ down(&mtd_table_mutex); -+ c = --mtd->usecount; -+ up(&mtd_table_mutex); -+ BUG_ON(c < 0); -+ -+ module_put(mtd->owner); -+} - - /* default_mtd_writev - default mtd writev method for MTD devices that - * dont implement their own -@@ -265,7 +289,8 @@ - - EXPORT_SYMBOL(add_mtd_device); - EXPORT_SYMBOL(del_mtd_device); --EXPORT_SYMBOL(__get_mtd_device); -+EXPORT_SYMBOL(get_mtd_device); -+EXPORT_SYMBOL(put_mtd_device); - EXPORT_SYMBOL(register_mtd_user); - EXPORT_SYMBOL(unregister_mtd_user); - EXPORT_SYMBOL(default_mtd_writev); -diff -Nurb linux-mips-2.4.27/drivers/mtd/mtdpart.c linux/drivers/mtd/mtdpart.c ---- linux-mips-2.4.27/drivers/mtd/mtdpart.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/mtdpart.c 2004-11-19 10:25:11.652237336 +0100 -@@ -5,7 +5,7 @@ - * - * This code is GPL - * -- * $Id$ -+ * $Id$ - * - * 02-21-2002 Thomas Gleixner - * added support for read_oob, write_oob -@@ -16,10 +16,11 @@ - #include - #include - #include -- -+#include -+#include - #include - #include -- -+#include - - /* Our partition linked list */ - static LIST_HEAD(mtd_partitions); -@@ -54,8 +55,12 @@ - len = 0; - else if (from + len > mtd->size) - len = mtd->size - from; -+ if (part->master->read_ecc == NULL) - return part->master->read (part->master, from + part->offset, - len, retlen, buf); -+ else -+ return part->master->read_ecc (part->master, from + part->offset, -+ len, retlen, buf, NULL, &mtd->oobinfo); - } - - static int part_point (struct mtd_info *mtd, loff_t from, size_t len, -@@ -78,9 +83,11 @@ - - - static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, -- size_t *retlen, u_char *buf, u_char *eccbuf, int oobsel) -+ size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel) - { - struct mtd_part *part = PART(mtd); -+ if (oobsel == NULL) -+ oobsel = &mtd->oobinfo; - if (from >= mtd->size) - len = 0; - else if (from + len > mtd->size) -@@ -113,7 +120,7 @@ - size_t *retlen, u_char *buf) - { - struct mtd_part *part = PART(mtd); -- return part->master->read_user_prot_reg (part->master, from, -+ return part->master->read_fact_prot_reg (part->master, from, - len, retlen, buf); - } - -@@ -127,17 +134,24 @@ - len = 0; - else if (to + len > mtd->size) - len = mtd->size - to; -+ if (part->master->write_ecc == NULL) - return part->master->write (part->master, to + part->offset, - len, retlen, buf); -+ else -+ return part->master->write_ecc (part->master, to + part->offset, -+ len, retlen, buf, NULL, &mtd->oobinfo); -+ - } - - static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf, -- u_char *eccbuf, int oobsel) -+ u_char *eccbuf, struct nand_oobinfo *oobsel) - { - struct mtd_part *part = PART(mtd); - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; -+ if (oobsel == NULL) -+ oobsel = &mtd->oobinfo; - if (to >= mtd->size) - len = 0; - else if (to + len > mtd->size) -@@ -174,25 +188,37 @@ - struct mtd_part *part = PART(mtd); - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; -+ if (part->master->writev_ecc == NULL) - return part->master->writev (part->master, vecs, count, - to + part->offset, retlen); -+ else -+ return part->master->writev_ecc (part->master, vecs, count, -+ to + part->offset, retlen, -+ NULL, &mtd->oobinfo); - } - - static int part_readv (struct mtd_info *mtd, struct iovec *vecs, - unsigned long count, loff_t from, size_t *retlen) - { - struct mtd_part *part = PART(mtd); -+ if (part->master->readv_ecc == NULL) - return part->master->readv (part->master, vecs, count, - from + part->offset, retlen); -+ else -+ return part->master->readv_ecc (part->master, vecs, count, -+ from + part->offset, retlen, -+ NULL, &mtd->oobinfo); - } - - static int part_writev_ecc (struct mtd_info *mtd, const struct iovec *vecs, - unsigned long count, loff_t to, size_t *retlen, -- u_char *eccbuf, int oobsel) -+ u_char *eccbuf, struct nand_oobinfo *oobsel) - { - struct mtd_part *part = PART(mtd); - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; -+ if (oobsel == NULL) -+ oobsel = &mtd->oobinfo; - return part->master->writev_ecc (part->master, vecs, count, - to + part->offset, retlen, - eccbuf, oobsel); -@@ -200,9 +226,11 @@ - - static int part_readv_ecc (struct mtd_info *mtd, struct iovec *vecs, - unsigned long count, loff_t from, size_t *retlen, -- u_char *eccbuf, int oobsel) -+ u_char *eccbuf, struct nand_oobinfo *oobsel) - { - struct mtd_part *part = PART(mtd); -+ if (oobsel == NULL) -+ oobsel = &mtd->oobinfo; - return part->master->readv_ecc (part->master, vecs, count, - from + part->offset, retlen, - eccbuf, oobsel); -@@ -288,7 +316,7 @@ - */ - - int add_mtd_partitions(struct mtd_info *master, -- struct mtd_partition *parts, -+ const struct mtd_partition *parts, - int nbparts) - { - struct mtd_part *slave; -@@ -321,7 +349,7 @@ - - slave->mtd.name = parts[i].name; - slave->mtd.bank_size = master->bank_size; -- slave->mtd.module = master->module; -+ slave->mtd.owner = master->owner; - - slave->mtd.read = part_read; - slave->mtd.write = part_write; -@@ -452,6 +480,75 @@ - EXPORT_SYMBOL(add_mtd_partitions); - EXPORT_SYMBOL(del_mtd_partitions); - -+static spinlock_t part_parser_lock = SPIN_LOCK_UNLOCKED; -+static LIST_HEAD(part_parsers); -+ -+struct mtd_part_parser *get_partition_parser(const char *name) -+{ -+ struct list_head *this; -+ void *ret = NULL; -+ spin_lock(&part_parser_lock); -+ -+ list_for_each(this, &part_parsers) { -+ struct mtd_part_parser *p = list_entry(this, struct mtd_part_parser, list); -+ -+ if (!strcmp(p->name, name) && try_module_get(p->owner)) { -+ ret = p; -+ break; -+ } -+ } -+ spin_unlock(&part_parser_lock); -+ -+ return ret; -+} -+ -+int register_mtd_parser(struct mtd_part_parser *p) -+{ -+ spin_lock(&part_parser_lock); -+ list_add(&p->list, &part_parsers); -+ spin_unlock(&part_parser_lock); -+ -+ return 0; -+} -+ -+int deregister_mtd_parser(struct mtd_part_parser *p) -+{ -+ spin_lock(&part_parser_lock); -+ list_del(&p->list); -+ spin_unlock(&part_parser_lock); -+ return 0; -+} -+ -+int parse_mtd_partitions(struct mtd_info *master, const char **types, -+ struct mtd_partition **pparts, unsigned long origin) -+{ -+ struct mtd_part_parser *parser; -+ int ret = 0; -+ -+ for ( ; ret <= 0 && *types; types++) { -+ parser = get_partition_parser(*types); -+#ifdef CONFIG_KMOD -+ if (!parser && !request_module("%s", *types)) -+ parser = get_partition_parser(*types); -+#endif -+ if (!parser) { -+ printk(KERN_NOTICE "%s partition parsing not available\n", -+ *types); -+ continue; -+ } -+ ret = (*parser->parse_fn)(master, pparts, origin); -+ if (ret > 0) { -+ printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", -+ ret, parser->name, master->name); -+ } -+ put_partition_parser(parser); -+ } -+ return ret; -+} -+ -+EXPORT_SYMBOL_GPL(parse_mtd_partitions); -+EXPORT_SYMBOL_GPL(register_mtd_parser); -+EXPORT_SYMBOL_GPL(deregister_mtd_parser); - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Nicolas Pitre "); -diff -Nurb linux-mips-2.4.27/drivers/mtd/nand/Config.in linux/drivers/mtd/nand/Config.in ---- linux-mips-2.4.27/drivers/mtd/nand/Config.in 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/nand/Config.in 2004-11-19 10:25:11.987186416 +0100 -@@ -1,6 +1,6 @@ - # drivers/mtd/nand/Config.in - --# $Id$ -+# $Id$ - - mainmenu_option next_comment - -@@ -11,26 +11,27 @@ - bool ' Verify NAND page writes' CONFIG_MTD_NAND_VERIFY_WRITE - fi - --if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_P720T" = "y" ]; then -- dep_tristate ' NAND Flash device on SPIA board' CONFIG_MTD_NAND_SPIA $CONFIG_MTD_NAND -+if [ "$CONFIG_ARM" = "y" ]; then -+ dep_tristate ' NAND Flash device on SPIA board' CONFIG_MTD_NAND_SPIA $CONFIG_MTD_NAND $CONFIG_ARCH_P720T -+ dep_tristate ' NAND Flash device on TOTO board' CONFIG_MTD_NAND_TOTO $CONFIG_MTD_NAND $CONFIG_ARCH_OMAP -+ dep_tristate ' SmartMedia Card on AUTCPU12 board' CONFIG_MTD_NAND_AUTCPU12 $CONFIG_MTD_NAND $CONFIG_ARCH_AUTCPU12 -+ dep_tristate ' NAND Flash device on EDP7312 board' CONFIG_MTD_NAND_EDB7312 $CONFIG_MTD_NAND $CONFIG_ARCH_EDB7312 - fi - --if [ "$CONFIG_ARCH_AUTCPU12" = "y" ]; then -- dep_tristate ' SmartMedia Card on AUTCPU12 board' CONFIG_MTD_NAND_AUTCPU12 $CONFIG_MTD_NAND --fi -- --if [ "$CONFIG_ARCH_EDB7312" = "y" ]; then -- dep_tristate ' NAND Flash device on EDP7312 board' CONFIG_MTD_NAND_EDB7312 $CONFIG_MTD_NAND --fi -- --if [ "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" -o "$CONFIG_MTD_NAND" = "y" ]; then -+if [ "$CONFIG_MTD_DOC2001PLUS" = "y" -o "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" -o "$CONFIG_MTD_NAND" = "y" ]; then - define_bool CONFIG_MTD_NAND_IDS y -+else -+ if [ "$CONFIG_MTD_DOC2001PLUS" = "m" -o "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" -o "$CONFIG_MTD_NAND" = "m" ]; then -+ define_bool CONFIG_MTD_NAND_IDS m -+ fi - fi - --if [ "$CONFIG_MTD_NAND_IDS" != "y" ]; then --if [ "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" -o "$CONFIG_MTD_NAND" = "m" ]; then -- define_bool CONFIG_MTD_NAND_IDS m -+if [ "$CONFIG_TOSHIBA_RBTX4925" = "y" ]; then -+ dep_tristate ' SmartMedia Card on Toshiba RBTX4925 reference board' CONFIG_MTD_NAND_TX4925NDFMC $CONFIG_MTD_NAND $CONFIG_TOSHIBA_RBTX4925_MPLEX_NAND - fi -+ -+if [ "$CONFIG_TOSHIBA_RBTX4938" = "y" ]; then -+ dep_tristate ' NAND Flash device on Toshiba RBTX4938 reference board' CONFIG_MTD_NAND_TX4938NDFMC $CONFIG_MTD_NAND $CONFIG_TOSHIBA_RBTX4938_MPLEX_NAND - fi - - endmenu -diff -Nurb linux-mips-2.4.27/drivers/mtd/nand/Makefile linux/drivers/mtd/nand/Makefile ---- linux-mips-2.4.27/drivers/mtd/nand/Makefile 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/nand/Makefile 2004-11-19 10:25:11.989186112 +0100 -@@ -1,16 +1,20 @@ - # - # linux/drivers/nand/Makefile - # --# $Id$ -+# $Id$ - -+ifeq ($(PATCHLEVEL),4) - O_TARGET := nandlink.o -- - export-objs := nand.o nand_ecc.o nand_ids.o -+endif - - obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o - obj-$(CONFIG_MTD_NAND_SPIA) += spia.o -+obj-$(CONFIG_MTD_NAND_TOTO) += toto.o - obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o - obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o -+obj-$(CONFIG_MTD_NAND_TX4925NDFMC) += tx4925ndfmc.o -+obj-$(CONFIG_MTD_NAND_TX4938NDFMC) += tx4938ndfmc.o - obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o - --include $(TOPDIR)/Rules.make -+-include $(TOPDIR)/Rules.make -diff -Nurb linux-mips-2.4.27/drivers/mtd/nand/autcpu12.c linux/drivers/mtd/nand/autcpu12.c ---- linux-mips-2.4.27/drivers/mtd/nand/autcpu12.c 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/nand/autcpu12.c 2004-11-19 10:25:11.990185960 +0100 -@@ -4,9 +4,9 @@ - * Copyright (c) 2002 Thomas Gleixner - * - * Derived from drivers/mtd/spia.c -- * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) -+ * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) - * -- * $Id$ -+ * $Id$ - * - * 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 -@@ -25,10 +25,10 @@ - * added page_cache - * - * 10-06-2002 TG 128K card support added -- * - */ - - #include -+#include - #include - #include - #include -@@ -70,6 +70,7 @@ - /* - * Define partitions for flash devices - */ -+extern struct nand_oobinfo jffs2_oobinfo; - - static struct mtd_partition partition_info16k[] = { - { name: "AUTCPU12 flash partition 1", -@@ -95,7 +96,7 @@ - size: 16 * SZ_1M }, - { name: "AUTCPU12 flash partition 2", - offset: 16 * SZ_1M, -- size: 48 * SZ_1M}, -+ size: 48 * SZ_1M }, - }; - - static struct mtd_partition partition_info128k[] = { -@@ -104,7 +105,7 @@ - size: 16 * SZ_1M }, - { name: "AUTCPU12 flash partition 2", - offset: 16 * SZ_1M, -- size: 112 * SZ_1M}, -+ size: 112 * SZ_1M }, - }; - - #define NUM_PARTITIONS16K 2 -@@ -114,7 +115,7 @@ - /* - * hardware specific access to control-lines - */ --void autcpu12_hwcontrol(int cmd) -+static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd) - { - - switch(cmd){ -@@ -133,7 +134,7 @@ - /* - * read device ready pin - */ --int autcpu12_device_ready(void) -+int autcpu12_device_ready(struct mtd_info *mtd) - { - - return ( (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) & AUTCPU12_SMC_RDY) ? 1 : 0; -@@ -184,7 +185,7 @@ - this->eccmode = NAND_ECC_SOFT; - - /* Scan to find existance of the device */ -- if (nand_scan (autcpu12_mtd)) { -+ if (nand_scan (autcpu12_mtd, 1)) { - err = -ENXIO; - goto out_ior; - } -@@ -197,15 +198,6 @@ - goto out_ior; - } - -- /* Allocate memory for internal data buffer */ -- this->data_cache = kmalloc (sizeof(u_char) * (autcpu12_mtd->oobblock + autcpu12_mtd->oobsize), GFP_KERNEL); -- if (!this->data_cache) { -- printk ("Unable to allocate NAND data cache for AUTCPU12.\n"); -- err = -ENOMEM; -- goto out_buf; -- } -- this->cache_page = -1; -- - /* Register the partitions */ - switch(autcpu12_mtd->size){ - case SZ_16M: add_mtd_partitions(autcpu12_mtd, partition_info16k, NUM_PARTITIONS16K); break; -@@ -215,13 +207,11 @@ - default: { - printk ("Unsupported SmartMedia device\n"); - err = -ENXIO; -- goto out_cac; -+ goto out_buf; - } - } - goto out; - --out_cac: -- kfree (this->data_cache); - out_buf: - kfree (this->data_buf); - out_ior: -@@ -250,7 +240,6 @@ - - /* Free internal data buffers */ - kfree (this->data_buf); -- kfree (this->data_cache); - - /* unmap physical adress */ - iounmap((void *)autcpu12_fio_base); -diff -Nurb linux-mips-2.4.27/drivers/mtd/nand/diskonchip.c linux/drivers/mtd/nand/diskonchip.c ---- linux-mips-2.4.27/drivers/mtd/nand/diskonchip.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/nand/diskonchip.c 2004-11-19 10:25:11.992185656 +0100 -@@ -0,0 +1,534 @@ -+/* -+ * drivers/mtd/nand/diskonchip.c -+ * -+ * (C) 2003 Red Hat, Inc. -+ * -+ * Author: David Woodhouse -+ * -+ * Interface to generic NAND code for M-Systems DiskOnChip devices -+ * -+ * $Id$ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+struct doc_priv { -+ unsigned long virtadr; -+ unsigned long physadr; -+ u_char ChipID; -+ u_char CDSNControl; -+ int chips_per_floor; /* The number of chips detected on each floor */ -+ int curfloor; -+ int curchip; -+}; -+ -+#define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil) -+#define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k) -+ -+static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd); -+static void doc200x_select_chip(struct mtd_info *mtd, int chip); -+ -+static int debug=0; -+MODULE_PARM(debug, "i"); -+ -+static int try_dword=1; -+MODULE_PARM(try_dword, "i"); -+ -+static void DoC_Delay(struct doc_priv *doc, unsigned short cycles) -+{ -+ volatile char dummy; -+ int i; -+ -+ for (i = 0; i < cycles; i++) { -+ if (DoC_is_Millennium(doc)) -+ dummy = ReadDOC(doc->virtadr, NOP); -+ else -+ dummy = ReadDOC(doc->virtadr, DOCStatus); -+ } -+ -+} -+/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ -+static int _DoC_WaitReady(struct doc_priv *doc) -+{ -+ unsigned long docptr = doc->virtadr; -+ unsigned long timeo = jiffies + (HZ * 10); -+ -+ if(debug) printk("_DoC_WaitReady...\n"); -+ /* Out-of-line routine to wait for chip response */ -+ while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { -+ if (time_after(jiffies, timeo)) { -+ printk("_DoC_WaitReady timed out.\n"); -+ return -EIO; -+ } -+ udelay(1); -+ cond_resched(); -+ } -+ -+ return 0; -+} -+ -+static inline int DoC_WaitReady(struct doc_priv *doc) -+{ -+ unsigned long docptr = doc->virtadr; -+ int ret = 0; -+ -+ DoC_Delay(doc, 4); -+ -+ if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) -+ /* Call the out-of-line routine to wait */ -+ ret = _DoC_WaitReady(doc); -+ -+ DoC_Delay(doc, 2); -+ if(debug) printk("DoC_WaitReady OK\n"); -+ return ret; -+} -+ -+static void doc2000_write_byte(struct mtd_info *mtd, u_char datum) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ -+ if(debug)printk("write_byte %02x\n", datum); -+ WriteDOC(datum, docptr, CDSNSlowIO); -+ WriteDOC(datum, docptr, 2k_CDSN_IO); -+} -+ -+static u_char doc2000_read_byte(struct mtd_info *mtd) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ -+ ReadDOC(docptr, CDSNSlowIO); -+ u_char ret = ReadDOC(docptr, 2k_CDSN_IO); -+ if (debug) printk("read_byte returns %02x\n", ret); -+ return ret; -+} -+static void doc2000_writebuf(struct mtd_info *mtd, -+ const u_char *buf, int len) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int i; -+ if (debug)printk("writebuf of %d bytes: ", len); -+ for (i=0; i < len; i++) { -+ WriteDOC_(buf[i], docptr, DoC_2k_CDSN_IO + i); -+ if (debug && i < 16) -+ printk("%02x ", buf[i]); -+ } -+ if (debug) printk("\n"); -+} -+ -+static void doc2000_readbuf(struct mtd_info *mtd, -+ u_char *buf, int len) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int i; -+ -+ if (debug)printk("readbuf of %d bytes: ", len); -+ -+ for (i=0; i < len; i++) { -+ buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i); -+ } -+} -+ -+static void doc2000_readbuf_dword(struct mtd_info *mtd, -+ u_char *buf, int len) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int i; -+ -+ if (debug) printk("readbuf_dword of %d bytes: ", len); -+ -+ if (unlikely((((unsigned long)buf)|len) & 3)) { -+ for (i=0; i < len; i++) { -+ *(uint8_t *)(&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i); -+ } -+ } else { -+ for (i=0; i < len; i+=4) { -+ *(uint32_t*)(&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i); -+ } -+ } -+} -+ -+static int doc2000_verifybuf(struct mtd_info *mtd, -+ const u_char *buf, int len) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int i; -+ -+ for (i=0; i < len; i++) -+ if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO)) -+ return i; -+ return 0; -+} -+ -+static uint16_t doc200x_ident_chip(struct mtd_info *mtd, int nr) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ uint16_t ret; -+ -+ doc200x_select_chip(mtd, nr); -+ doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); -+ this->write_byte(mtd, NAND_CMD_READID); -+ doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); -+ doc200x_hwcontrol(mtd, NAND_CTL_SETALE); -+ this->write_byte(mtd, 0); -+ doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); -+ -+ ret = this->read_byte(mtd) << 8; -+ ret |= this->read_byte(mtd); -+ -+ if (doc->ChipID == DOC_ChipID_Doc2k && try_dword && !nr) { -+ /* First chip probe. See if we get same results by 32-bit access */ -+ union { -+ uint32_t dword; -+ uint8_t byte[4]; -+ } ident; -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ -+ doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); -+ doc2000_write_byte(mtd, NAND_CMD_READID); -+ doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); -+ doc200x_hwcontrol(mtd, NAND_CTL_SETALE); -+ doc2000_write_byte(mtd, 0); -+ doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); -+ -+ ident.dword = readl(docptr + DoC_2k_CDSN_IO); -+ if (((ident.byte[0] << 8) | ident.byte[1]) == ret) { -+ printk(KERN_INFO "DiskOnChip 2000 responds to DWORD access\n"); -+ this->read_buf = &doc2000_readbuf_dword; -+ } -+ } -+ -+ return ret; -+} -+ -+static void doc2000_count_chips(struct mtd_info *mtd) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ uint16_t mfrid; -+ int i; -+ -+ /* Max 4 chips per floor on DiskOnChip 2000 */ -+ doc->chips_per_floor = 4; -+ -+ /* Find out what the first chip is */ -+ mfrid = doc200x_ident_chip(mtd, 0); -+ -+ /* Find how many chips in each floor. */ -+ for (i = 1; i < 4; i++) { -+ if (doc200x_ident_chip(mtd, i) != mfrid) -+ break; -+ } -+ doc->chips_per_floor = i; -+} -+ -+static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state) -+{ -+ struct doc_priv *doc = (void *)this->priv; -+ -+ int status; -+ -+ DoC_WaitReady(doc); -+ this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); -+ DoC_WaitReady(doc); -+ status = (int)this->read_byte(mtd); -+ -+ return status; -+} -+ -+static void doc2001_write_byte(struct mtd_info *mtd, u_char datum) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ -+ WriteDOC(datum, docptr, CDSNSlowIO); -+ WriteDOC(datum, docptr, Mil_CDSN_IO); -+ WriteDOC(datum, docptr, WritePipeTerm); -+} -+ -+static u_char doc2001_read_byte(struct mtd_info *mtd) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ -+ ReadDOC(docptr, CDSNSlowIO); -+ /* 11.4.5 -- delay twice to allow extended length cycle */ -+ DoC_Delay(doc, 2); -+ ReadDOC(docptr, ReadPipeInit); -+ return ReadDOC(docptr, Mil_CDSN_IO); -+} -+ -+static void doc2001_writebuf(struct mtd_info *mtd, -+ const u_char *buf, int len) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int i; -+ -+ for (i=0; i < len; i++) -+ WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); -+ /* Terminate write pipeline */ -+ WriteDOC(0x00, docptr, WritePipeTerm); -+} -+ -+static void doc2001_readbuf(struct mtd_info *mtd, -+ u_char *buf, int len) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int i; -+ -+ /* Start read pipeline */ -+ ReadDOC(docptr, ReadPipeInit); -+ -+ for (i=0; i < len-1; i++) -+ buf[i] = ReadDOC(docptr, Mil_CDSN_IO); -+ -+ /* Terminate read pipeline */ -+ buf[i] = ReadDOC(docptr, LastDataRead); -+} -+static int doc2001_verifybuf(struct mtd_info *mtd, -+ const u_char *buf, int len) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int i; -+ -+ /* Start read pipeline */ -+ ReadDOC(docptr, ReadPipeInit); -+ -+ for (i=0; i < len-1; i++) -+ if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { -+ ReadDOC(docptr, LastDataRead); -+ return i; -+ } -+ if (buf[i] != ReadDOC(docptr, LastDataRead)) -+ return i; -+ return 0; -+} -+ -+static void doc200x_select_chip(struct mtd_info *mtd, int chip) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ int floor = 0; -+ -+ /* 11.4.4 -- deassert CE before changing chip */ -+ doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE); -+ -+ if(debug)printk("select chip (%d)\n", chip); -+ -+ if (chip == -1) -+ return; -+ -+ floor = chip / doc->chips_per_floor; -+ chip -= (floor * doc->chips_per_floor); -+ -+ WriteDOC(floor, docptr, FloorSelect); -+ WriteDOC(chip, docptr, CDSNDeviceSelect); -+ -+ doc200x_hwcontrol(mtd, NAND_CTL_SETNCE); -+ -+ doc->curchip = chip; -+ doc->curfloor = floor; -+} -+ -+static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ -+ switch(cmd) { -+ case NAND_CTL_SETNCE: -+ doc->CDSNControl |= CDSN_CTRL_CE; -+ break; -+ case NAND_CTL_CLRNCE: -+ doc->CDSNControl &= ~CDSN_CTRL_CE; -+ break; -+ case NAND_CTL_SETCLE: -+ doc->CDSNControl |= CDSN_CTRL_CLE; -+ break; -+ case NAND_CTL_CLRCLE: -+ doc->CDSNControl &= ~CDSN_CTRL_CLE; -+ break; -+ case NAND_CTL_SETALE: -+ doc->CDSNControl |= CDSN_CTRL_ALE; -+ break; -+ case NAND_CTL_CLRALE: -+ doc->CDSNControl &= ~CDSN_CTRL_ALE; -+ break; -+ case NAND_CTL_SETWP: -+ doc->CDSNControl |= CDSN_CTRL_WP; -+ break; -+ case NAND_CTL_CLRWP: -+ doc->CDSNControl &= ~CDSN_CTRL_WP; -+ break; -+ } -+ if (debug)printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl); -+ WriteDOC(doc->CDSNControl, docptr, CDSNControl); -+ /* 11.4.3 -- 4 NOPs after CSDNControl write */ -+ DoC_Delay(doc, 4); -+} -+ -+static int doc200x_dev_ready(struct mtd_info *mtd) -+{ -+ struct nand_chip *this = mtd->priv; -+ struct doc_priv *doc = (void *)this->priv; -+ unsigned long docptr = doc->virtadr; -+ -+ /* 11.4.2 -- must NOP four times before checking FR/B# */ -+ DoC_Delay(doc, 4); -+ if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { -+ if(debug) -+ printk("not ready\n"); -+ return 0; -+ } -+ /* 11.4.2 -- Must NOP twice if it's ready */ -+ DoC_Delay(doc, 2); -+ if (debug)printk("was ready\n"); -+ return 1; -+} -+ -+static int doc200x_block_bad(struct mtd_info *mtd, unsigned long block) -+{ -+ /* FIXME: Look it up in the BBT */ -+ return 0; -+} -+ -+struct doc_priv mydoc = { -+ .physadr = 0xd4000, -+ .curfloor = -1, -+ .curchip = -1, -+}; -+ -+u_char mydatabuf[528]; -+ -+struct nand_chip mynand = { -+ .priv = (void *)&mydoc, -+ .select_chip = doc200x_select_chip, -+ .hwcontrol = doc200x_hwcontrol, -+ .dev_ready = doc200x_dev_ready, -+ .waitfunc = doc200x_wait, -+ .block_bad = doc200x_block_bad, -+ .eccmode = NAND_ECC_SOFT, -+ .data_buf = mydatabuf, -+}; -+ -+struct mtd_info mymtd = { -+ .priv = (void *)&mynand, -+ .owner = THIS_MODULE, -+}; -+ -+int __init init_nanddoc(void) -+{ -+ mydoc.virtadr = (unsigned long)ioremap(mydoc.physadr, DOC_IOREMAP_LEN); -+ int nrchips = 1; -+ char *name; -+ -+ WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, -+ mydoc.virtadr, DOCControl); -+ WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, -+ mydoc.virtadr, DOCControl); -+ -+ WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, -+ mydoc.virtadr, DOCControl); -+ WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, -+ mydoc.virtadr, DOCControl); -+ -+ mydoc.ChipID = ReadDOC(mydoc.virtadr, ChipID); -+ -+ switch(mydoc.ChipID) { -+ case DOC_ChipID_DocMil: -+ mynand.write_byte = doc2001_write_byte; -+ mynand.read_byte = doc2001_read_byte; -+ mynand.write_buf = doc2001_writebuf; -+ mynand.read_buf = doc2001_readbuf; -+ mynand.verify_buf = doc2001_verifybuf; -+ -+ ReadDOC(mydoc.virtadr, ChipID); -+ ReadDOC(mydoc.virtadr, ChipID); -+ if (ReadDOC(mydoc.virtadr, ChipID) != DOC_ChipID_DocMil) { -+ /* It's not a Millennium; it's one of the newer -+ DiskOnChip 2000 units with a similar ASIC. -+ Treat it like a Millennium, except that it -+ can have multiple chips. */ -+ doc2000_count_chips(&mymtd); -+ nrchips = 4 * mydoc.chips_per_floor; -+ name = "DiskOnChip 2000 (INFTL Model)"; -+ } else { -+ /* Bog-standard Millennium */ -+ mydoc.chips_per_floor = 1; -+ nrchips = 1; -+ name = "DiskOnChip Millennium"; -+ } -+ break; -+ -+ case DOC_ChipID_Doc2k: -+ mynand.write_byte = doc2000_write_byte; -+ mynand.read_byte = doc2000_read_byte; -+ mynand.write_buf = doc2000_writebuf; -+ mynand.read_buf = doc2000_readbuf; -+ mynand.verify_buf = doc2000_verifybuf; -+ -+ doc2000_count_chips(&mymtd); -+ nrchips = 4 * mydoc.chips_per_floor; -+ name = "DiskOnChip 2000 (NFTL Model)"; -+ mydoc.CDSNControl |= CDSN_CTRL_FLASH_IO; -+ -+ break; -+ -+ default: -+ return -EIO; -+ } -+ if (nand_scan(&mymtd, nrchips)) { -+ iounmap((void *)mydoc.virtadr); -+ return -EIO; -+ } -+ mymtd.name = name; -+ add_mtd_device(&mymtd); -+ -+ return 0; -+} -+ -+void __exit cleanup_nanddoc(void) -+{ -+ del_mtd_device(&mymtd); -+ iounmap((void *)mydoc.virtadr); -+} -+ -+module_init(init_nanddoc); -+module_exit(cleanup_nanddoc); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("David Woodhouse "); -+MODULE_DESCRIPTION("M-Systems DiskOnChip 2000 and Millennium device driver\n"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/nand/edb7312.c linux/drivers/mtd/nand/edb7312.c ---- linux-mips-2.4.27/drivers/mtd/nand/edb7312.c 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/nand/edb7312.c 2004-11-19 10:25:11.997184896 +0100 -@@ -6,7 +6,7 @@ - * Derived from drivers/mtd/nand/autcpu12.c - * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) - * -- * $Id$ -+ * $Id$ - * - * 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 -@@ -20,6 +20,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -77,16 +78,13 @@ - }; - #define NUM_PARTITIONS 1 - --extern int parse_cmdline_partitions(struct mtd_info *master, -- struct mtd_partition **pparts, -- const char *mtd_id); - #endif - - - /* - * hardware specific access to control-lines - */ --static void ep7312_hwcontrol(int cmd) -+static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd) - { - switch(cmd) { - -@@ -116,10 +114,13 @@ - /* - * read device ready pin - */ --static int ep7312_device_ready(void) -+static int ep7312_device_ready(struct mtd_info *mtd) - { - return 1; - } -+#ifdef CONFIG_MTD_PARTITIONS -+const char *part_probes[] = { "cmdlinepart", NULL }; -+#endif - - /* - * Main initialization routine -@@ -174,7 +175,7 @@ - this->chip_delay = 15; - - /* Scan to find existence of the device */ -- if (nand_scan (ep7312_mtd)) { -+ if (nand_scan (ep7312_mtd, 1)) { - iounmap((void *)ep7312_fio_base); - kfree (ep7312_mtd); - return -ENXIO; -@@ -189,27 +190,16 @@ - return -ENOMEM; - } - -- /* Allocate memory for internal data buffer */ -- this->data_cache = kmalloc (sizeof(u_char) * (ep7312_mtd->oobblock + ep7312_mtd->oobsize), GFP_KERNEL); -- if (!this->data_cache) { -- printk("Unable to allocate NAND data cache for EDB7312.\n"); -- kfree (this->data_buf); -- iounmap((void *)ep7312_fio_base); -- kfree (ep7312_mtd); -- return -ENOMEM; -- } -- this->cache_page = -1; -- --#ifdef CONFIG_MTD_CMDLINE_PARTS -- mtd_parts_nb = parse_cmdline_partitions(ep7312_mtd, &mtd_parts, -- "edb7312-nand"); -+#ifdef CONFIG_PARTITIONS -+ ep7312_mtd->name = "edb7312-nand"; -+ mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, -+ &mtd_parts, 0); - if (mtd_parts_nb > 0) - part_type = "command line"; - else - mtd_parts_nb = 0; - #endif -- if (mtd_parts_nb == 0) -- { -+ if (mtd_parts_nb == 0) { - mtd_parts = partition_info; - mtd_parts_nb = NUM_PARTITIONS; - part_type = "static"; -@@ -236,7 +226,6 @@ - - /* Free internal data buffer */ - kfree (this->data_buf); -- kfree (this->data_cache); - - /* Free the MTD device structure */ - kfree (ep7312_mtd); -diff -Nurb linux-mips-2.4.27/drivers/mtd/nand/nand.c linux/drivers/mtd/nand/nand.c ---- linux-mips-2.4.27/drivers/mtd/nand/nand.c 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/nand/nand.c 2004-11-19 10:25:12.010182920 +0100 -@@ -8,7 +8,7 @@ - * Additional technical information is available on - * http://www.linux-mtd.infradead.org/tech/nand.html - * -- * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) -+ * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) - * 2002 Thomas Gleixner (tglx@linutronix.de) - * - * 10-29-2001 Thomas Gleixner (tglx@linutronix.de) -@@ -112,10 +112,27 @@ - * for mtd->read_ecc / mtd->write_ecc - * some minor cleanups - * -- * 12-05-2000 tglx: Dave Ellis (DGE@sixnetio) provided the fix for -+ * 12-05-2002 tglx: Dave Ellis (DGE@sixnetio) provided the fix for - * WRITE_VERIFY long time ago. Thanks for remembering me. - * -- * $Id$ -+ * 02-14-2003 tglx: Reject non page aligned writes -+ * Fixed ecc select in nand_write_page to match semantics. -+ * -+ * 02-18-2003 tglx: Changed oobsel to pointer. Added a default oob-selector -+ * -+ * 02-18-2003 tglx: Implemented oobsel again. Now it uses a pointer to -+ + a structure, which will be supplied by a filesystem driver -+ * If NULL is given, then the defaults (none or defaults -+ * supplied by ioctl (MEMSETOOBSEL) are used. -+ * For partitions the partition defaults are used (mtdpart.c) -+ * -+ * 06-04-2003 tglx: fix compile errors and fix write verify problem for -+ * some chips, which need either a delay between the readback -+ * and the next write command or have the CE removed. The -+ * CE disable/enable is much faster than a 20us delay and -+ * it should work on all available chips. -+ * -+ * $Id$ - * - * 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 -@@ -130,102 +147,151 @@ - #include - #include - #include -+#include - #include - #include - - /* -- * Macros for low-level register control -- */ --#define nand_select() this->hwcontrol(NAND_CTL_SETNCE); -- --#define nand_deselect() this->hwcontrol(NAND_CTL_CLRNCE); -- --/* -- * out of band configuration for different filesystems -- */ --static int oobconfigs[][6] = { -- { 0,0,0,0,0,0}, -- -- { NAND_JFFS2_OOB_ECCPOS0, NAND_JFFS2_OOB_ECCPOS1, NAND_JFFS2_OOB_ECCPOS2, -- NAND_JFFS2_OOB_ECCPOS3, NAND_JFFS2_OOB_ECCPOS4, NAND_JFFS2_OOB_ECCPOS5 }, -- -- { NAND_YAFFS_OOB_ECCPOS0, NAND_YAFFS_OOB_ECCPOS1, NAND_YAFFS_OOB_ECCPOS2, -- NAND_YAFFS_OOB_ECCPOS3, NAND_YAFFS_OOB_ECCPOS4, NAND_YAFFS_OOB_ECCPOS5 } --}; -- --/* - * NAND low-level MTD interface functions - */ -+static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len); -+static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len); -+static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len); -+ - static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf); - static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, -- size_t * retlen, u_char * buf, u_char * eccbuf, int oobsel); -+ size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel); - static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf); - static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf); - static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, -- size_t * retlen, const u_char * buf, u_char * eccbuf, int oobsel); -+ size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel); - static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char *buf); - static int nand_writev (struct mtd_info *mtd, const struct iovec *vecs, - unsigned long count, loff_t to, size_t * retlen); - static int nand_writev_ecc (struct mtd_info *mtd, const struct iovec *vecs, -- unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, int oobsel); -+ unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); - static int nand_erase (struct mtd_info *mtd, struct erase_info *instr); - static void nand_sync (struct mtd_info *mtd); --static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, int col, -- int last, u_char *oob_buf, int oobsel); -+static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf, struct nand_oobinfo *oobsel); -+ -+static u_char nand_read_byte(struct mtd_info *mtd) -+{ -+ struct nand_chip *this = mtd->priv; -+ return readb(this->IO_ADDR_R); -+} -+ -+static void nand_write_byte(struct mtd_info *mtd, u_char byte) -+{ -+ struct nand_chip *this = mtd->priv; -+ writeb(byte, this->IO_ADDR_W); -+} -+ -+static void nand_select_chip(struct mtd_info *mtd, int chip) -+{ -+ struct nand_chip *this = mtd->priv; -+ switch(chip) { -+ case -1: -+ this->hwcontrol(mtd, NAND_CTL_CLRNCE); -+ break; -+ case 0: -+ this->hwcontrol(mtd, NAND_CTL_SETNCE); -+ break; -+ -+ default: -+ BUG(); -+ } -+} -+ -+static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_W); -+} -+ -+static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_R); -+} -+ -+static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_R)) -+ return i; -+ -+ return 0; -+} -+ -+/* Appropriate chip should already be selected */ -+static int nand_block_bad(struct mtd_info *mtd, unsigned long page) -+{ -+ struct nand_chip *this = mtd->priv; -+ -+ this->cmdfunc (mtd, NAND_CMD_READOOB, NAND_BADBLOCK_POS, page); -+ if (this->read_byte(mtd) != 0xff) -+ return 1; -+ -+ return 0; -+} -+ - /* - * Send command to NAND device - */ - static void nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) - { - register struct nand_chip *this = mtd->priv; -- register unsigned long NAND_IO_ADDR = this->IO_ADDR_W; - - /* Begin command latch cycle */ -- this->hwcontrol (NAND_CTL_SETCLE); -+ this->hwcontrol(mtd, NAND_CTL_SETCLE); - /* - * Write out the command to the device. - */ -- if (command != NAND_CMD_SEQIN) -- writeb (command, NAND_IO_ADDR); -- else { -- if (mtd->oobblock == 256 && column >= 256) { -- column -= 256; -- writeb (NAND_CMD_READOOB, NAND_IO_ADDR); -- writeb (NAND_CMD_SEQIN, NAND_IO_ADDR); -- } else if (mtd->oobblock == 512 && column >= 256) { -- if (column < 512) { -- column -= 256; -- writeb (NAND_CMD_READ1, NAND_IO_ADDR); -- writeb (NAND_CMD_SEQIN, NAND_IO_ADDR); -- } else { -- column -= 512; -- writeb (NAND_CMD_READOOB, NAND_IO_ADDR); -- writeb (NAND_CMD_SEQIN, NAND_IO_ADDR); -- } -+ if (command == NAND_CMD_SEQIN) { -+ int readcmd; -+ -+ if (column >= mtd->oobblock) { -+ /* OOB area */ -+ column -= mtd->oobblock; -+ readcmd = NAND_CMD_READOOB; -+ } else if (column < 256) { -+ /* First 256 bytes --> READ0 */ -+ readcmd = NAND_CMD_READ0; - } else { -- writeb (NAND_CMD_READ0, NAND_IO_ADDR); -- writeb (NAND_CMD_SEQIN, NAND_IO_ADDR); -+ column -= 256; -+ readcmd = NAND_CMD_READ1; - } -+ this->write_byte(mtd, readcmd); - } -+ this->write_byte(mtd, command); - - /* Set ALE and clear CLE to start address cycle */ -- this->hwcontrol (NAND_CTL_CLRCLE); -+ this->hwcontrol(mtd, NAND_CTL_CLRCLE); - - if (column != -1 || page_addr != -1) { -- this->hwcontrol (NAND_CTL_SETALE); -+ this->hwcontrol(mtd, NAND_CTL_SETALE); - - /* Serially input address */ - if (column != -1) -- writeb (column, NAND_IO_ADDR); -+ this->write_byte(mtd, column); - if (page_addr != -1) { -- writeb ((unsigned char) (page_addr & 0xff), NAND_IO_ADDR); -- writeb ((unsigned char) ((page_addr >> 8) & 0xff), NAND_IO_ADDR); -+ this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); -+ this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); - /* One more address cycle for higher density devices */ - if (mtd->size & 0x0c000000) -- writeb ((unsigned char) ((page_addr >> 16) & 0x0f), NAND_IO_ADDR); -+ this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f)); - } - /* Latch in address */ -- this->hwcontrol (NAND_CTL_CLRALE); -+ this->hwcontrol(mtd, NAND_CTL_CLRALE); - } - - /* -@@ -244,10 +310,11 @@ - case NAND_CMD_RESET: - if (this->dev_ready) - break; -- this->hwcontrol (NAND_CTL_SETCLE); -- writeb (NAND_CMD_STATUS, NAND_IO_ADDR); -- this->hwcontrol (NAND_CTL_CLRCLE); -- while ( !(readb (this->IO_ADDR_R) & 0x40)); -+ udelay(this->chip_delay); -+ this->hwcontrol(mtd, NAND_CTL_SETCLE); -+ this->write_byte(mtd, NAND_CMD_STATUS); -+ this->hwcontrol(mtd, NAND_CTL_CLRCLE); -+ while ( !(this->read_byte(mtd) & 0x40)); - return; - - /* This applies to read commands */ -@@ -263,7 +330,7 @@ - } - - /* wait until command is processed */ -- while (!this->dev_ready()); -+ while (!this->dev_ready(mtd)); - } - - /* -@@ -288,17 +355,17 @@ - spin_unlock_bh (&this->chip_lock); - return; - } -- -+#if 0 /* This was broken. And of dubious utility */ - if (this->state == FL_ERASING) { - if (new_state != FL_ERASING) { - this->state = new_state; - spin_unlock_bh (&this->chip_lock); -- nand_select (); /* select in any case */ -+ this->select_chip(mtd, 0); /* select in any case */ - this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); - return; - } - } -- -+#endif - set_current_state (TASK_UNINTERRUPTIBLE); - add_wait_queue (&this->wq, &wait); - spin_unlock_bh (&this->chip_lock); -@@ -334,17 +401,17 @@ - return 0; - } - if (this->dev_ready) { -- if (this->dev_ready ()) -+ if (this->dev_ready(mtd)) - break; - } -- if (readb (this->IO_ADDR_R) & 0x40) -+ if (this->read_byte(mtd) & 0x40) - break; - - spin_unlock_bh (&this->chip_lock); - yield (); - spin_lock_bh (&this->chip_lock); - } -- status = (int) readb (this->IO_ADDR_R); -+ status = (int) this->read_byte(mtd); - spin_unlock_bh (&this->chip_lock); - - return status; -@@ -352,14 +419,15 @@ - - /* - * Nand_page_program function is used for write and writev ! -+ * This function will always program a full page of data -+ * If you call it with a non page aligned buffer, you're lost :) - */ --static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, -- int page, int col, int last, u_char *oob_buf, int oobsel) -+static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf, struct nand_oobinfo *oobsel) - { - int i, status; - u_char ecc_code[6], *oob_data; -- int eccmode = oobsel ? this->eccmode : NAND_ECC_NONE; -- int *oob_config = oobconfigs[oobsel]; -+ int eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; -+ int *oob_config = oobsel->eccpos; - - /* pad oob area, if we have no oob buffer from fs-driver */ - if (!oob_buf) { -@@ -369,66 +437,42 @@ - } else - oob_data = oob_buf; - -- /* software ecc 3 Bytes ECC / 256 Byte Data ? */ -- if (eccmode == NAND_ECC_SOFT) { -- /* Read back previous written data, if col > 0 */ -- if (col) { -- this->cmdfunc (mtd, NAND_CMD_READ0, 0, page); -- for (i = 0; i < col; i++) -- this->data_poi[i] = readb (this->IO_ADDR_R); -- } -- if ((col < this->eccsize) && (last >= this->eccsize)) { -- this->calculate_ecc (&this->data_poi[0], &(ecc_code[0])); -- for (i = 0; i < 3; i++) -- oob_data[oob_config[i]] = ecc_code[i]; -- } -- /* Calculate and write the second ECC if we have enough data */ -- if ((mtd->oobblock == 512) && (last == 512)) { -- this->calculate_ecc (&this->data_poi[256], &(ecc_code[3])); -- for (i = 3; i < 6; i++) -- oob_data[oob_config[i]] = ecc_code[i]; -- } -- } else { -- /* For hardware ECC skip ECC, if we have no full page write */ -- if (eccmode != NAND_ECC_NONE && (col || last != mtd->oobblock)) -- eccmode = NAND_ECC_NONE; -- } -- -- /* Prepad for partial page programming !!! */ -- for (i = 0; i < col; i++) -- this->data_poi[i] = 0xff; -- -- /* Postpad for partial page programming !!! oob is already padded */ -- for (i = last; i < mtd->oobblock; i++) -- this->data_poi[i] = 0xff; -- - /* Send command to begin auto page programming */ - this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page); - - /* Write out complete page of data, take care of eccmode */ -- switch (this->eccmode) { -+ switch (eccmode) { - /* No ecc and software ecc 3/256, write all */ - case NAND_ECC_NONE: -+ printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n"); -+ this->write_buf(mtd, this->data_poi, mtd->oobblock); -+ break; - case NAND_ECC_SOFT: -- for (i = 0; i < mtd->oobblock; i++) -- writeb ( this->data_poi[i] , this->IO_ADDR_W); -+ this->calculate_ecc(mtd, &this->data_poi[0], &(ecc_code[0])); -+ for (i = 0; i < 3; i++) -+ oob_data[oob_config[i]] = ecc_code[i]; -+ /* Calculate and write the second ECC for 512 Byte page size */ -+ if (mtd->oobblock == 512) { -+ this->calculate_ecc(mtd, &this->data_poi[256], &(ecc_code[3])); -+ for (i = 3; i < 6; i++) -+ oob_data[oob_config[i]] = ecc_code[i]; -+ } -+ this->write_buf(mtd, this->data_poi, mtd->oobblock); - break; - - /* Hardware ecc 3 byte / 256 data, write first half, get ecc, then second, if 512 byte pagesize */ - case NAND_ECC_HW3_256: -- this->enable_hwecc (NAND_ECC_WRITE); /* enable hardware ecc logic for write */ -- for (i = 0; i < mtd->eccsize; i++) -- writeb ( this->data_poi[i] , this->IO_ADDR_W); -+ this->enable_hwecc(mtd, NAND_ECC_WRITE); /* enable hardware ecc logic for write */ -+ this->write_buf(mtd, this->data_poi, mtd->eccsize); - -- this->calculate_ecc (NULL, &(ecc_code[0])); -+ this->calculate_ecc(mtd, NULL, &(ecc_code[0])); - for (i = 0; i < 3; i++) - oob_data[oob_config[i]] = ecc_code[i]; - - if (mtd->oobblock == 512) { -- this->enable_hwecc (NAND_ECC_WRITE); /* enable hardware ecc logic for write*/ -- for (i = mtd->eccsize; i < mtd->oobblock; i++) -- writeb ( this->data_poi[i] , this->IO_ADDR_W); -- this->calculate_ecc (NULL, &(ecc_code[3])); -+ this->enable_hwecc(mtd, NAND_ECC_WRITE); /* enable hardware ecc logic for write*/ -+ this->write_buf(mtd, &this->data_poi[mtd->eccsize], mtd->oobblock - mtd->eccsize); -+ this->calculate_ecc(mtd, NULL, &(ecc_code[3])); - for (i = 3; i < 6; i++) - oob_data[oob_config[i]] = ecc_code[i]; - } -@@ -436,20 +480,18 @@ - - /* Hardware ecc 3 byte / 512 byte data, write full page */ - case NAND_ECC_HW3_512: -- this->enable_hwecc (NAND_ECC_WRITE); /* enable hardware ecc logic */ -- for (i = 0; i < mtd->oobblock; i++) -- writeb ( this->data_poi[i] , this->IO_ADDR_W); -- this->calculate_ecc (NULL, &(ecc_code[0])); -+ this->enable_hwecc(mtd, NAND_ECC_WRITE); /* enable hardware ecc logic */ -+ this->write_buf(mtd, this->data_poi, mtd->oobblock); -+ this->calculate_ecc(mtd, NULL, &(ecc_code[0])); - for (i = 0; i < 3; i++) - oob_data[oob_config[i]] = ecc_code[i]; - break; - - /* Hardware ecc 6 byte / 512 byte data, write full page */ - case NAND_ECC_HW6_512: -- this->enable_hwecc (NAND_ECC_WRITE); /* enable hardware ecc logic */ -- for (i = 0; i < mtd->oobblock; i++) -- writeb ( this->data_poi[i] , this->IO_ADDR_W); -- this->calculate_ecc (NULL, &(ecc_code[0])); -+ this->enable_hwecc(mtd, NAND_ECC_WRITE); /* enable hardware ecc logic */ -+ this->write_buf(mtd, this->data_poi, mtd->oobblock); -+ this->calculate_ecc(mtd, NULL, &(ecc_code[0])); - for (i = 0; i < 6; i++) - oob_data[oob_config[i]] = ecc_code[i]; - break; -@@ -460,8 +502,7 @@ - } - - /* Write out OOB data */ -- for (i = 0; i < mtd->oobsize; i++) -- writeb ( oob_data[i] , this->IO_ADDR_W); -+ this->write_buf(mtd, oob_data, mtd->oobsize); - - /* Send command to actually program the data */ - this->cmdfunc (mtd, NAND_CMD_PAGEPROG, -1, -1); -@@ -490,25 +531,21 @@ - */ - - /* Send command to read back the page */ -- this->cmdfunc (mtd, NAND_CMD_READ0, col, page); -+ this->cmdfunc (mtd, NAND_CMD_READ0, 0, page); - /* Loop through and verify the data */ -- for (i = col; i < last; i++) { -- if (this->data_poi[i] != readb (this->IO_ADDR_R)) { -+ if (this->verify_buf(mtd, this->data_poi, mtd->oobblock)) { - DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); - return -EIO; - } -- } - - /* check, if we have a fs-supplied oob-buffer */ - if (oob_buf) { -- for (i = 0; i < mtd->oobsize; i++) { -- if (oob_data[i] != readb (this->IO_ADDR_R)) { -+ if (this->verify_buf(mtd, oob_data, mtd->oobsize)) { - DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); - return -EIO; - } -- } - } else { -- if (eccmode != NAND_ECC_NONE && !col && last == mtd->oobblock) { -+ if (eccmode != NAND_ECC_NONE) { - int ecc_bytes = 0; - - switch (this->eccmode) { -@@ -518,8 +555,7 @@ - case NAND_ECC_HW6_512: ecc_bytes = 6; break; - } - -- for (i = 0; i < mtd->oobsize; i++) -- oob_data[i] = readb (this->IO_ADDR_R); -+ this->read_buf(mtd, oob_data, mtd->oobsize); - - for (i = 0; i < ecc_bytes; i++) { - if (oob_data[oob_config[i]] != ecc_code[i]) { -@@ -531,6 +567,13 @@ - } - } - } -+ /* -+ * Terminate the read command. This is faster than sending a reset command or -+ * applying a 20us delay before issuing the next programm sequence. -+ * This is not a problem for all chips, but I have found a bunch of them. -+ */ -+ this->select_chip(mtd, -1); -+ this->select_chip(mtd, 0); - #endif - return 0; - } -@@ -540,7 +583,7 @@ - */ - static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf) - { -- return (nand_read_ecc (mtd, from, len, retlen, buf, NULL, 0)); -+ return nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL); - } - - -@@ -548,7 +591,7 @@ - * NAND read with ECC - */ - static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, -- size_t * retlen, u_char * buf, u_char * oob_buf, int oobsel) -+ size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel) - { - int j, col, page, end, ecc; - int erase_state = 0; -@@ -557,9 +600,15 @@ - u_char *data_poi, *oob_data = oob_buf; - u_char ecc_calc[6]; - u_char ecc_code[6]; -- int eccmode = oobsel ? this->eccmode : NAND_ECC_NONE; -+ int eccmode; -+ int *oob_config; -+ -+ // use chip default if zero -+ if (oobsel == NULL) -+ oobsel = &mtd->oobinfo; - -- int *oob_config = oobconfigs[oobsel]; -+ eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; -+ oob_config = oobsel->eccpos; - - DEBUG (MTD_DEBUG_LEVEL3, "nand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); - -@@ -574,7 +623,7 @@ - nand_get_chip (this, mtd ,FL_READING, &erase_state); - - /* Select the NAND device */ -- nand_select (); -+ this->select_chip(mtd, 0); - - /* First we calculate the starting page */ - page = from >> this->page_shift; -@@ -596,7 +645,7 @@ - if (!this->dev_ready) - udelay (this->chip_delay); - else -- while (!this->dev_ready()); -+ while (!this->dev_ready(mtd)); - } - - /* -@@ -616,39 +665,40 @@ - - j = 0; - switch (eccmode) { -- case NAND_ECC_NONE: /* No ECC, Read in a page */ -- while (j < end) -- data_poi[j++] = readb (this->IO_ADDR_R); -+ case NAND_ECC_NONE: { /* No ECC, Read in a page */ -+ static unsigned long lastwhinge = 0; -+ if ((lastwhinge / HZ) != (jiffies / HZ)) { -+ printk (KERN_WARNING "Reading data from NAND FLASH without ECC is not recommended\n"); -+ lastwhinge = jiffies; -+ } -+ this->read_buf(mtd, data_poi, end); - break; -+ } - - case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */ -- while (j < end) -- data_poi[j++] = readb (this->IO_ADDR_R); -- this->calculate_ecc (&data_poi[0], &ecc_calc[0]); -+ this->read_buf(mtd, data_poi, end); -+ this->calculate_ecc(mtd, &data_poi[0], &ecc_calc[0]); - if (mtd->oobblock == 512) -- this->calculate_ecc (&data_poi[256], &ecc_calc[3]); -+ this->calculate_ecc(mtd, &data_poi[256], &ecc_calc[3]); - break; - - case NAND_ECC_HW3_256: /* Hardware ECC 3 byte /256 byte data: Read in first 256 byte, get ecc, */ -- this->enable_hwecc (NAND_ECC_READ); -- while (j < ecc) -- data_poi[j++] = readb (this->IO_ADDR_R); -- this->calculate_ecc (&data_poi[0], &ecc_calc[0]); /* read from hardware */ -+ this->enable_hwecc(mtd, NAND_ECC_READ); -+ this->read_buf(mtd, data_poi, ecc); -+ this->calculate_ecc(mtd, &data_poi[0], &ecc_calc[0]); /* read from hardware */ - - if (mtd->oobblock == 512) { /* read second, if pagesize = 512 */ -- this->enable_hwecc (NAND_ECC_READ); -- while (j < end) -- data_poi[j++] = readb (this->IO_ADDR_R); -- this->calculate_ecc (&data_poi[256], &ecc_calc[3]); /* read from hardware */ -+ this->enable_hwecc(mtd, NAND_ECC_READ); -+ this->read_buf(mtd, &data_poi[ecc], end-ecc); -+ this->calculate_ecc(mtd, &data_poi[256], &ecc_calc[3]); /* read from hardware */ - } - break; - - case NAND_ECC_HW3_512: - case NAND_ECC_HW6_512: /* Hardware ECC 3/6 byte / 512 byte data : Read in a page */ -- this->enable_hwecc (NAND_ECC_READ); -- while (j < end) -- data_poi[j++] = readb (this->IO_ADDR_R); -- this->calculate_ecc (&data_poi[0], &ecc_calc[0]); /* read from hardware */ -+ this->enable_hwecc(mtd, NAND_ECC_READ); -+ this->read_buf(mtd, data_poi, end); -+ this->calculate_ecc(mtd, &data_poi[0], &ecc_calc[0]); /* read from hardware */ - break; - - default: -@@ -658,7 +708,7 @@ - - /* read oobdata */ - for (j = 0; j < mtd->oobsize; j++) -- oob_data[oob + j] = readb (this->IO_ADDR_R); -+ oob_data[oob + j] = this->read_byte(mtd); - - /* Skip ECC, if not active */ - if (eccmode == NAND_ECC_NONE) -@@ -669,7 +719,7 @@ - ecc_code[j] = oob_data[oob + oob_config[j]]; - - /* correct data, if neccecary */ -- ecc_status = this->correct_data (&data_poi[0], &ecc_code[0], &ecc_calc[0]); -+ ecc_status = this->correct_data(mtd, &data_poi[0], &ecc_code[0], &ecc_calc[0]); - /* check, if we have a fs supplied oob-buffer */ - if (oob_buf) { - oob += mtd->oobsize; -@@ -682,7 +732,7 @@ - } - - if (mtd->oobblock == 512 && eccmode != NAND_ECC_HW3_512) { -- ecc_status = this->correct_data (&data_poi[256], &ecc_code[3], &ecc_calc[3]); -+ ecc_status = this->correct_data(mtd, &data_poi[256], &ecc_code[3], &ecc_calc[3]); - if (oob_buf) { - *((int *)&oob_data[oob]) = ecc_status; - oob += sizeof(int); -@@ -705,7 +755,7 @@ - } - - /* De-select the NAND device */ -- nand_deselect (); -+ this->select_chip(mtd, -1); - - /* Wake up anyone waiting on the device */ - spin_lock_bh (&this->chip_lock); -@@ -753,7 +803,7 @@ - nand_get_chip (this, mtd , FL_READING, &erase_state); - - /* Select the NAND device */ -- nand_select (); -+ this->select_chip(mtd, 0); - - /* Send the read command */ - this->cmdfunc (mtd, NAND_CMD_READOOB, col, page); -@@ -761,13 +811,20 @@ - * Read the data, if we read more than one page - * oob data, let the device transfer the data ! - */ -- for (i = 0; i < len; i++) { -- buf[i] = readb (this->IO_ADDR_R); -- if ((col++ & (mtd->oobsize - 1)) == (mtd->oobsize - 1)) -+ i = 0; -+ while (i < len) { -+ int thislen = (mtd->oobsize - col) & (mtd->oobsize - 1); -+ if (!thislen) -+ thislen = mtd->oobsize; -+ thislen = min_t(int, thislen, len); -+ this->read_buf(mtd, &buf[i], thislen); -+ i += thislen; -+ col += thislen; -+ /* Delay between pages */ - udelay (this->chip_delay); - } - /* De-select the NAND device */ -- nand_deselect (); -+ this->select_chip(mtd, -1); - - /* Wake up anyone waiting on the device */ - spin_lock_bh (&this->chip_lock); -@@ -780,45 +837,54 @@ - return 0; - } - -+#define NOTALIGNED(x) (x & (mtd->oobblock-1)) != 0 -+ - /* - * Use NAND write ECC - */ - static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf) - { -- return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, 0)); -+ return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL)); - } - /* - * NAND write with ECC - */ - static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, -- size_t * retlen, const u_char * buf, u_char * eccbuf, int oobsel) -+ size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel) - { -- int i, page, col, cnt, ret = 0, oob = 0, written = 0; -+ int page, ret = 0, oob = 0, written = 0; - struct nand_chip *this = mtd->priv; - - DEBUG (MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); - - /* Do not allow write past end of device */ - if ((to + len) > mtd->size) { -- DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n"); -+ DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n"); -+ return -EINVAL; -+ } -+ -+ /* reject writes, which are not page aligned */ -+ if (NOTALIGNED (to) || NOTALIGNED(len)) { -+ printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); - return -EINVAL; - } - -+ // if oobsel is NULL, use chip defaults -+ if (oobsel == NULL) -+ oobsel = &mtd->oobinfo; -+ - /* Shift to get page */ - page = ((int) to) >> this->page_shift; - -- /* Get the starting column */ -- col = to & (mtd->oobblock - 1); -- - /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd, FL_WRITING, NULL); - - /* Select the NAND device */ -- nand_select (); -+ this->select_chip(mtd, 0); - - /* Check the WP bit */ - this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); -- if (!(readb (this->IO_ADDR_R) & 0x80)) { -+ if (!(this->read_byte(mtd) & 0x80)) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Device is write protected!!!\n"); - ret = -EIO; - goto out; -@@ -826,42 +892,27 @@ - - /* Loop until all data is written */ - while (written < len) { -- /* -- * Check, if we have a full page write, then we can -- * use the given buffer, else we have to copy -- */ -- if (!col && (len - written) >= mtd->oobblock) { -+ int cnt = mtd->oobblock; - this->data_poi = (u_char*) &buf[written]; -- cnt = mtd->oobblock; -- } else { -- cnt = 0; -- for (i = col; i < len && i < mtd->oobblock; i++) { -- this->data_buf[i] = buf[written + i]; -- cnt++; -- } -- this->data_poi = this->data_buf; -- } -- /* We use the same function for write and writev !) */ -+ /* We use the same function for write and writev */ - if (eccbuf) { -- ret = nand_write_page (mtd, this, page, col, cnt ,&eccbuf[oob], oobsel); -+ ret = nand_write_page (mtd, this, page, &eccbuf[oob], oobsel); - oob += mtd->oobsize; - } else -- ret = nand_write_page (mtd, this, page, col, cnt, NULL, oobsel); -+ ret = nand_write_page (mtd, this, page, NULL, oobsel); - - if (ret) - goto out; - - /* Update written bytes count */ - written += cnt; -- /* Next write is aligned */ -- col = 0; - /* Increment page address */ - page++; - } - - out: - /* De-select the NAND device */ -- nand_deselect (); -+ this->select_chip(mtd, -1); - - /* Wake up anyone waiting on the device */ - spin_lock_bh (&this->chip_lock); -@@ -873,13 +924,21 @@ - return ret; - } - -+static u_char ffchars[] = { -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -+}; -+ - /* - * NAND write out-of-band - */ - static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf) - { -- int i, column, page, status, ret = 0; -+ int column, page, status, ret = 0; - struct nand_chip *this = mtd->priv; -+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE -+ int i; -+#endif - - DEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); - -@@ -902,27 +961,31 @@ - nand_get_chip (this, mtd, FL_WRITING, NULL); - - /* Select the NAND device */ -- nand_select (); -+ this->select_chip(mtd, 0); -+ -+ /* Reset the chip. Some chips (like the Toshiba TC5832DC found -+ in one of my DiskOnChip 2000 test units) will clear the whole -+ data page too if we don't do this. I have no clue why, but -+ I seem to have 'fixed' it in the doc2000 driver in -+ August 1999. dwmw2. */ -+ this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); - - /* Check the WP bit */ - this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); -- if (!(readb (this->IO_ADDR_R) & 0x80)) { -+ if (!(this->read_byte(mtd) & 0x80)) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Device is write protected!!!\n"); - ret = -EIO; - goto out; - } -- - /* Write out desired data */ - this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock, page); -+ - /* prepad 0xff for partial programming */ -- for (i = 0; i < column; i++) -- writeb (0xff, this->IO_ADDR_W); -+ this->write_buf(mtd, ffchars, column); - /* write data */ -- for (i = 0; i < len; i++) -- writeb (buf[i], this->IO_ADDR_W); -+ this->write_buf(mtd, buf, len); - /* postpad 0xff for partial programming */ -- for (i = len + column; i < mtd->oobsize; i++) -- writeb (0xff, this->IO_ADDR_W); -+ this->write_buf(mtd, ffchars, mtd->oobsize - (len+column)); - - /* Send command to program the OOB data */ - this->cmdfunc (mtd, NAND_CMD_PAGEPROG, -1, -1); -@@ -944,7 +1007,7 @@ - - /* Loop through and verify the data */ - for (i = 0; i < len; i++) { -- if (buf[i] != readb (this->IO_ADDR_R)) { -+ if (buf[i] != this->read_byte(mtd)) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page); - ret = -EIO; - goto out; -@@ -954,7 +1017,7 @@ - - out: - /* De-select the NAND device */ -- nand_deselect (); -+ this->select_chip(mtd, -1); - - /* Wake up anyone waiting on the device */ - spin_lock_bh (&this->chip_lock); -@@ -976,9 +1039,9 @@ - } - - static int nand_writev_ecc (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, -- loff_t to, size_t * retlen, u_char *eccbuf, int oobsel) -+ loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel) - { -- int i, page, col, cnt, len, total_len, ret = 0, written = 0; -+ int i, page, len, total_len, ret = 0, written = 0; - struct nand_chip *this = mtd->priv; - - /* Calculate total length of data */ -@@ -995,39 +1058,42 @@ - return -EINVAL; - } - -+ /* reject writes, which are not page aligned */ -+ if (NOTALIGNED (to) || NOTALIGNED(total_len)) { -+ printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); -+ return -EINVAL; -+ } -+ -+ // if oobsel is NULL, use chip defaults -+ if (oobsel == NULL) -+ oobsel = &mtd->oobinfo; -+ - /* Shift to get page */ - page = ((int) to) >> this->page_shift; - -- /* Get the starting column */ -- col = to & (mtd->oobblock - 1); -- - /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd, FL_WRITING, NULL); - - /* Select the NAND device */ -- nand_select (); -+ this->select_chip(mtd, 0); - - /* Check the WP bit */ - this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); -- if (!(readb (this->IO_ADDR_R) & 0x80)) { -+ if (!(this->read_byte(mtd) & 0x80)) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_writev: Device is write protected!!!\n"); - ret = -EIO; - goto out; - } - - /* Loop until all iovecs' data has been written */ -- cnt = col; - len = 0; -- - while (count) { - /* -- * Check, if we write from offset 0 and if the tuple -- * gives us not enough data for a full page write. Then we -- * can use the iov direct, else we have to copy into -- * data_buf. -+ * Check, if the tuple gives us not enough data for a -+ * full page write. Then we can use the iov direct, -+ * else we have to copy into data_buf. - */ -- if (!cnt && (vecs->iov_len - len) >= mtd->oobblock) { -- cnt = mtd->oobblock; -+ if ((vecs->iov_len - len) >= mtd->oobblock) { - this->data_poi = (u_char *) vecs->iov_base; - this->data_poi += len; - len += mtd->oobblock; -@@ -1042,6 +1108,7 @@ - * Read data out of each tuple until we have a full page - * to write or we've read all the tuples. - */ -+ int cnt = 0; - while ((cnt < mtd->oobblock) && count) { - if (vecs->iov_base != NULL && vecs->iov_len) { - this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++]; -@@ -1057,15 +1124,12 @@ - } - - /* We use the same function for write and writev !) */ -- ret = nand_write_page (mtd, this, page, col, cnt, NULL, oobsel); -+ ret = nand_write_page (mtd, this, page, NULL, oobsel); - if (ret) - goto out; - - /* Update written bytes count */ -- written += (cnt - col); -- -- /* Reset written byte counter and column */ -- col = cnt = 0; -+ written += mtd->oobblock;; - - /* Increment page address */ - page++; -@@ -1073,7 +1137,7 @@ - - out: - /* De-select the NAND device */ -- nand_deselect (); -+ this->select_chip(mtd, -1); - - /* Wake up anyone waiting on the device */ - spin_lock_bh (&this->chip_lock); -@@ -1125,11 +1189,11 @@ - pages_per_block = mtd->erasesize / mtd->oobblock; - - /* Select the NAND device */ -- nand_select (); -+ this->select_chip(mtd, 0); - - /* Check the WP bit */ - this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); -- if (!(readb (this->IO_ADDR_R) & 0x80)) { -+ if (!(this->read_byte(mtd) & 0x80)) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Device is write protected!!!\n"); - instr->state = MTD_ERASE_FAILED; - goto erase_exit; -@@ -1142,8 +1206,7 @@ - - while (len) { - /* Check if we have a bad block, we do not erase bad blocks ! */ -- this->cmdfunc (mtd, NAND_CMD_READOOB, NAND_BADBLOCK_POS, page); -- if (readb (this->IO_ADDR_R) != 0xff) { -+ if (this->block_bad(mtd, page)) { - printk (KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page); - instr->state = MTD_ERASE_FAILED; - goto erase_exit; -@@ -1179,7 +1242,7 @@ - if (this->state == FL_ERASING || this->state == FL_READY) { - /* Select the NAND device again, if we were interrupted */ - this->state = FL_ERASING; -- nand_select (); -+ this->select_chip(mtd, 0); - continue; - } else { - set_current_state (TASK_UNINTERRUPTIBLE); -@@ -1194,7 +1257,7 @@ - - erase_exit: - /* De-select the NAND device */ -- nand_deselect (); -+ this->select_chip(mtd, -1); - spin_unlock_bh (&this->chip_lock); - - ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;; -@@ -1205,6 +1268,7 @@ - /* The device is ready */ - spin_lock_bh (&this->chip_lock); - this->state = FL_READY; -+ wake_up (&this->wq); - spin_unlock_bh (&this->chip_lock); - - /* Return more or less happy */ -@@ -1259,7 +1323,7 @@ - /* - * Scan for the NAND device - */ --int nand_scan (struct mtd_info *mtd) -+int nand_scan (struct mtd_info *mtd, int maxchips) - { - int i, nand_maf_id, nand_dev_id; - struct nand_chip *this = mtd->priv; -@@ -1276,23 +1340,38 @@ - if (this->waitfunc == NULL) - this->waitfunc = nand_wait; - -+ if (!this->block_bad) -+ this->block_bad = nand_block_bad; -+ if (!this->select_chip) -+ this->select_chip = nand_select_chip; -+ if (!this->write_byte) -+ this->write_byte = nand_write_byte; -+ if (!this->read_byte) -+ this->read_byte = nand_read_byte; -+ if (!this->write_buf) -+ this->write_buf = nand_write_buf; -+ if (!this->read_buf) -+ this->read_buf = nand_read_buf; -+ if (!this->verify_buf) -+ this->verify_buf = nand_verify_buf; -+ - /* Select the device */ -- nand_select (); -+ this->select_chip(mtd, 0); - - /* Send the command for reading device ID */ - this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1); - - /* Read manufacturer and device IDs */ -- nand_maf_id = readb (this->IO_ADDR_R); -- nand_dev_id = readb (this->IO_ADDR_R); -+ nand_maf_id = this->read_byte(mtd); -+ nand_dev_id = this->read_byte(mtd); - - /* Print and store flash device information */ - for (i = 0; nand_flash_ids[i].name != NULL; i++) { - if (nand_dev_id == nand_flash_ids[i].id && !mtd->size) { - mtd->name = nand_flash_ids[i].name; - mtd->erasesize = nand_flash_ids[i].erasesize; -- mtd->size = (1 << nand_flash_ids[i].chipshift); - mtd->eccsize = 256; -+ this->chipshift = nand_flash_ids[i].chipshift; - if (nand_flash_ids[i].page256) { - mtd->oobblock = 256; - mtd->oobsize = 8; -@@ -1307,13 +1386,34 @@ - if (nand_manuf_ids[i].id == nand_maf_id) - break; - } -- printk (KERN_INFO "NAND device: Manufacture ID:" -+ printk (KERN_INFO "NAND device: Manufacturer ID:" - " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, - nand_manuf_ids[i].name , mtd->name); - break; - } - } - -+ if (!mtd->name) { -+ printk (KERN_WARNING "No NAND device found!!!\n"); -+ return 1; -+ } -+ -+ for (i=1; i < maxchips; i++) { -+ this->select_chip(mtd, i); -+ -+ /* Send the command for reading device ID */ -+ this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1); -+ -+ /* Read manufacturer and device IDs */ -+ if (nand_maf_id != this->read_byte(mtd) || -+ nand_dev_id != this->read_byte(mtd)) -+ break; -+ } -+ if (i > 1) -+ printk(KERN_INFO "%d NAND chips detected\n", i); -+ -+ mtd->size = (1 << this->chipshift) /* * i when we fix the rest of the code */; -+ - /* - * check ECC mode, default to software - * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize -@@ -1324,6 +1424,7 @@ - switch (this->eccmode) { - - case NAND_ECC_HW3_512: -+ case NAND_ECC_HW6_512: - if (mtd->oobblock == 256) { - printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n"); - this->eccmode = NAND_ECC_SOFT; -@@ -1340,6 +1441,7 @@ - BUG(); - - case NAND_ECC_NONE: -+ printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n"); - this->eccmode = NAND_ECC_NONE; - break; - -@@ -1359,18 +1461,11 @@ - spin_lock_init (&this->chip_lock); - - /* De-select the device */ -- nand_deselect (); -- -- /* Print warning message for no device */ -- if (!mtd->size) { -- printk (KERN_WARNING "No NAND device found!!!\n"); -- return 1; -- } -+ this->select_chip(mtd, -1); - - /* Fill in remaining MTD driver data */ - mtd->type = MTD_NANDFLASH; - mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC; -- mtd->module = THIS_MODULE; - mtd->ecctype = MTD_ECC_SW; - mtd->erase = nand_erase; - mtd->point = NULL; -@@ -1389,6 +1484,7 @@ - mtd->unlock = NULL; - mtd->suspend = NULL; - mtd->resume = NULL; -+ mtd->owner = THIS_MODULE; - - /* Return happy */ - return 0; -@@ -1397,5 +1493,5 @@ - EXPORT_SYMBOL (nand_scan); - - MODULE_LICENSE ("GPL"); --MODULE_AUTHOR ("Steven J. Hill , Thomas Gleixner "); -+MODULE_AUTHOR ("Steven J. Hill , Thomas Gleixner "); - MODULE_DESCRIPTION ("Generic NAND flash driver code"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/nand/nand_ecc.c linux/drivers/mtd/nand/nand_ecc.c ---- linux-mips-2.4.27/drivers/mtd/nand/nand_ecc.c 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/nand/nand_ecc.c 2004-11-19 10:25:12.011182768 +0100 -@@ -1,10 +1,10 @@ - /* - * drivers/mtd/nand_ecc.c - * -- * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) -+ * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) - * Toshiba America Electronics Components, Inc. - * -- * $Id$ -+ * $Id$ - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - /* - * Pre-calculated 256-way 1 byte column parity -@@ -84,7 +85,7 @@ - /* - * Calculate 3 byte ECC code for 256 byte block - */ --void nand_calculate_ecc (const u_char *dat, u_char *ecc_code) -+void nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) - { - u_char idx, reg1, reg2, reg3; - int j; -@@ -119,7 +120,7 @@ - /* - * Detect and correct a 1 bit error for 256 byte block - */ --int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc) -+int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) - { - u_char a, b, c, d1, d2, d3, add, bit, i; - -@@ -209,5 +210,5 @@ - EXPORT_SYMBOL(nand_correct_data); - - MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Steven J. Hill "); -+MODULE_AUTHOR("Steven J. Hill "); - MODULE_DESCRIPTION("Generic NAND ECC support"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/nand/nand_ids.c linux/drivers/mtd/nand/nand_ids.c ---- linux-mips-2.4.27/drivers/mtd/nand/nand_ids.c 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/nand/nand_ids.c 2004-11-19 10:25:12.013182464 +0100 -@@ -4,7 +4,7 @@ - * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de) - * - * -- * $Id$ -+ * $Id$ - * - * 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 -@@ -18,21 +18,21 @@ - * Chip ID list - */ - struct nand_flash_dev nand_flash_ids[] = { -- {"NAND 1MB 5V", 0x6e, 20, 0x1000, 1}, // 1Mb 5V -- {"NAND 2MB 5V", 0x64, 21, 0x1000, 1}, // 2Mb 5V -- {"NAND 4MB 5V", 0x6b, 22, 0x2000, 0}, // 4Mb 5V -- {"NAND 1MB 3,3V", 0xe8, 20, 0x1000, 1}, // 1Mb 3.3V -- {"NAND 1MB 3,3V", 0xec, 20, 0x1000, 1}, // 1Mb 3.3V -- {"NAND 2MB 3,3V", 0xea, 21, 0x1000, 1}, // 2Mb 3.3V -- {"NAND 4MB 3,3V", 0xd5, 22, 0x2000, 0}, // 4Mb 3.3V -- {"NAND 4MB 3,3V", 0xe3, 22, 0x2000, 0}, // 4Mb 3.3V -- {"NAND 4MB 3,3V", 0xe5, 22, 0x2000, 0}, // 4Mb 3.3V -- {"NAND 8MB 3,3V", 0xd6, 23, 0x2000, 0}, // 8Mb 3.3V -- {"NAND 8MB 3,3V", 0xe6, 23, 0x2000, 0}, // 8Mb 3.3V -- {"NAND 16MB 3,3V", 0x73, 24, 0x4000, 0},// 16Mb 3,3V -- {"NAND 32MB 3,3V", 0x75, 25, 0x4000, 0}, // 32Mb 3,3V -- {"NAND 64MB 3,3V", 0x76, 26, 0x4000, 0}, // 64Mb 3,3V -- {"NAND 128MB 3,3V", 0x79, 27, 0x4000, 0}, // 128Mb 3,3V -+ {"NAND 1MiB 5V", 0x6e, 20, 0x1000, 1}, -+ {"NAND 2MiB 5V", 0x64, 21, 0x1000, 1}, -+ {"NAND 4MiB 5V", 0x6b, 22, 0x2000, 0}, -+ {"NAND 1MiB 3,3V", 0xe8, 20, 0x1000, 1}, -+ {"NAND 1MiB 3,3V", 0xec, 20, 0x1000, 1}, -+ {"NAND 2MiB 3,3V", 0xea, 21, 0x1000, 1}, -+ {"NAND 4MiB 3,3V", 0xd5, 22, 0x2000, 0}, -+ {"NAND 4MiB 3,3V", 0xe3, 22, 0x2000, 0}, -+ {"NAND 4MiB 3,3V", 0xe5, 22, 0x2000, 0}, -+ {"NAND 8MiB 3,3V", 0xd6, 23, 0x2000, 0}, -+ {"NAND 8MiB 3,3V", 0xe6, 23, 0x2000, 0}, -+ {"NAND 16MiB 3,3V", 0x73, 24, 0x4000, 0}, -+ {"NAND 32MiB 3,3V", 0x75, 25, 0x4000, 0}, -+ {"NAND 64MiB 3,3V", 0x76, 26, 0x4000, 0}, -+ {"NAND 128MiB 3,3V", 0x79, 27, 0x4000, 0}, - {NULL,} - }; - -diff -Nurb linux-mips-2.4.27/drivers/mtd/nand/spia.c linux/drivers/mtd/nand/spia.c ---- linux-mips-2.4.27/drivers/mtd/nand/spia.c 2003-02-26 01:53:50.000000000 +0100 -+++ linux/drivers/mtd/nand/spia.c 2004-11-19 10:25:12.014182312 +0100 -@@ -1,14 +1,14 @@ - /* - * drivers/mtd/nand/spia.c - * -- * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) -+ * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) - * - * - * 10-29-2001 TG change to support hardwarespecific access - * to controllines (due to change in nand.c) - * page_cache added - * -- * $Id$ -+ * $Id$ - * - * 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 -@@ -20,6 +20,8 @@ - * a 64Mibit (8MiB x 8 bits) NAND flash device. - */ - -+#include -+#include - #include - #include - #include -@@ -35,14 +37,14 @@ - /* - * Values specific to the SPIA board (used with EP7212 processor) - */ --#define SPIA_IO_ADDR = 0xd0000000 /* Start of EP7212 IO address space */ --#define SPIA_FIO_ADDR = 0xf0000000 /* Address where flash is mapped */ --#define SPIA_PEDR = 0x0080 /* -+#define SPIA_IO_BASE 0xd0000000 /* Start of EP7212 IO address space */ -+#define SPIA_FIO_BASE 0xf0000000 /* Address where flash is mapped */ -+#define SPIA_PEDR 0x0080 /* - * IO offset to Port E data register - * where the CLE, ALE and NCE pins - * are wired to. - */ --#define SPIA_PEDDR = 0x00c0 /* -+#define SPIA_PEDDR 0x00c0 /* - * IO offset to Port E data direction - * register so we can control the IO - * lines. -@@ -62,21 +64,20 @@ - MODULE_PARM(spia_pedr, "i"); - MODULE_PARM(spia_peddr, "i"); - --__setup("spia_io_base=",spia_io_base); --__setup("spia_fio_base=",spia_fio_base); --__setup("spia_pedr=",spia_pedr); --__setup("spia_peddr=",spia_peddr); -- - /* - * Define partitions for flash device - */ - const static struct mtd_partition partition_info[] = { -- { name: "SPIA flash partition 1", -- offset: 0, -- size: 2*1024*1024 }, -- { name: "SPIA flash partition 2", -- offset: 2*1024*1024, -- size: 6*1024*1024 } -+ { -+ .name = "SPIA flash partition 1", -+ .offset = 0, -+ .size = 2*1024*1024 -+ }, -+ { -+ .name = "SPIA flash partition 2", -+ .offset = 2*1024*1024, -+ .size = 6*1024*1024 -+ } - }; - #define NUM_PARTITIONS 2 - -@@ -84,7 +85,7 @@ - /* - * hardware specific access to control-lines - */ --void spia_hwcontrol(int cmd){ -+static void spia_hwcontrol(struct mtd_info *mtd, int cmd){ - - switch(cmd){ - -@@ -139,7 +140,7 @@ - this->chip_delay = 15; - - /* Scan to find existence of the device */ -- if (nand_scan (spia_mtd)) { -+ if (nand_scan (spia_mtd, 1)) { - kfree (spia_mtd); - return -ENXIO; - } -@@ -152,16 +153,6 @@ - return -ENOMEM; - } - -- /* Allocate memory for internal data buffer */ -- this->data_cache = kmalloc (sizeof(u_char) * (spia_mtd->oobblock + spia_mtd->oobsize), GFP_KERNEL); -- if (!this->data_cache) { -- printk ("Unable to allocate NAND data cache for SPIA.\n"); -- kfree (this->data_buf); -- kfree (spia_mtd); -- return = -ENOMEM; -- } -- this->cache_page = -1; -- - /* Register the partitions */ - add_mtd_partitions(spia_mtd, partition_info, NUM_PARTITIONS); - -@@ -183,7 +174,6 @@ - - /* Free internal data buffer */ - kfree (this->data_buf); -- kfree (this->page_cache); - - /* Free the MTD device structure */ - kfree (spia_mtd); -@@ -192,5 +182,5 @@ - #endif - - MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Steven J. Hill -+ * -+ * 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. -+ * -+ * Overview: -+ * This is a device driver for the NAND flash device found on the -+ * TI fido board. It supports 32MiB and 64MiB cards -+ * -+ * $Id$ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * MTD structure for TOTO board -+ */ -+static struct mtd_info *toto_mtd = NULL; -+ -+static int toto_io_base = OMAP_FLASH_1_BASE; -+ -+#define CONFIG_NAND_WORKAROUND 1 -+ -+#define NAND_NCE 0x4000 -+#define NAND_CLE 0x1000 -+#define NAND_ALE 0x0002 -+#define NAND_MASK (NAND_CLE | NAND_ALE | NAND_NCE) -+ -+#define T_NAND_CTL_CLRALE(iob) gpiosetout(NAND_ALE, 0) -+#define T_NAND_CTL_SETALE(iob) gpiosetout(NAND_ALE, NAND_ALE) -+#ifdef CONFIG_NAND_WORKAROUND /* "some" dev boards busted, blue wired to rts2 :( */ -+#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0); rts2setout(2, 2) -+#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE); rts2setout(2, 0) -+#else -+#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0) -+#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE) -+#endif -+#define T_NAND_CTL_SETNCE(iob) gpiosetout(NAND_NCE, 0) -+#define T_NAND_CTL_CLRNCE(iob) gpiosetout(NAND_NCE, NAND_NCE) -+ -+/* -+ * Define partitions for flash devices -+ */ -+ -+static struct mtd_partition partition_info64M[] = { -+ { .name = "toto kernel partition 1", -+ .offset = 0, -+ .size = 2 * SZ_1M }, -+ { .name = "toto file sys partition 2", -+ .offset = 2 * SZ_1M, -+ .size = 14 * SZ_1M }, -+ { .name = "toto user partition 3", -+ .offset = 16 * SZ_1M, -+ .size = 16 * SZ_1M }, -+ { .name = "toto devboard extra partition 4", -+ .offset = 32 * SZ_1M, -+ .size = 32 * SZ_1M }, -+}; -+ -+static struct mtd_partition partition_info32M[] = { -+ { .name = "toto kernel partition 1", -+ .offset = 0, -+ .size = 2 * SZ_1M }, -+ { .name = "toto file sys partition 2", -+ .offset = 2 * SZ_1M, -+ .size = 14 * SZ_1M }, -+ { .name = "toto user partition 3", -+ .offset = 16 * SZ_1M, -+ .size = 16 * SZ_1M }, -+}; -+ -+#define NUM_PARTITIONS32M 3 -+#define NUM_PARTITIONS64M 4 -+/* -+ * hardware specific access to control-lines -+*/ -+ -+static void toto_hwcontrol(struct mtd_info *mtd, int cmd) -+{ -+ -+ udelay(1); /* hopefully enough time for tc make proceding write to clear */ -+ switch(cmd){ -+ -+ case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break; -+ case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break; -+ -+ case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break; -+ case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break; -+ -+ case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break; -+ case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break; -+ } -+ udelay(1); /* allow time to ensure gpio state to over take memory write */ -+} -+ -+/* -+ * Main initialization routine -+ */ -+int __init toto_init (void) -+{ -+ struct nand_chip *this; -+ int err = 0; -+ -+ /* Allocate memory for MTD device structure and private data */ -+ toto_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), -+ GFP_KERNEL); -+ if (!toto_mtd) { -+ printk (KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n"); -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ /* Get pointer to private data */ -+ this = (struct nand_chip *) (&toto_mtd[1]); -+ -+ /* Initialize structures */ -+ memset((char *) toto_mtd, 0, sizeof(struct mtd_info)); -+ memset((char *) this, 0, sizeof(struct nand_chip)); -+ -+ /* Link the private data with the MTD structure */ -+ toto_mtd->priv = this; -+ -+ /* Set address of NAND IO lines */ -+ this->IO_ADDR_R = toto_io_base; -+ this->IO_ADDR_W = toto_io_base; -+ this->hwcontrol = toto_hwcontrol; -+ this->dev_ready = NULL; -+ /* 25 us command delay time */ -+ this->chip_delay = 30; -+ this->eccmode = NAND_ECC_SOFT; -+ -+ /* Scan to find existance of the device */ -+ if (nand_scan (toto_mtd, 1)) { -+ err = -ENXIO; -+ goto out_mtd; -+ } -+ -+ /* Allocate memory for internal data buffer */ -+ this->data_buf = kmalloc (sizeof(u_char) * (toto_mtd->oobblock + toto_mtd->oobsize), GFP_KERNEL); -+ if (!this->data_buf) { -+ printk (KERN_WARNING "Unable to allocate NAND data buffer for toto.\n"); -+ err = -ENOMEM; -+ goto out_mtd; -+ } -+ -+ /* Register the partitions */ -+ switch(toto_mtd->size){ -+ case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break; -+ case SZ_32M: add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M); break; -+ default: { -+ printk (KERN_WARNING "Unsupported Nand device\n"); -+ err = -ENXIO; -+ goto out_buf; -+ } -+ } -+ -+ gpioreserve(NAND_MASK); /* claim our gpios */ -+ archflashwp(0,0); /* open up flash for writing */ -+ -+ goto out; -+ -+out_buf: -+ kfree (this->data_buf); -+out_mtd: -+ kfree (toto_mtd); -+out: -+ return err; -+} -+ -+module_init(toto_init); -+ -+/* -+ * Clean up routine -+ */ -+static void __exit toto_cleanup (void) -+{ -+ struct nand_chip *this = (struct nand_chip *) &toto_mtd[1]; -+ -+ /* Unregister partitions */ -+ del_mtd_partitions(toto_mtd); -+ -+ /* Unregister the device */ -+ del_mtd_device (toto_mtd); -+ -+ /* Free internal data buffers */ -+ kfree (this->data_buf); -+ -+ /* Free the MTD device structure */ -+ kfree (toto_mtd); -+ -+ /* stop flash writes */ -+ archflashwp(0,1); -+ -+ /* release gpios to system */ -+ gpiorelease(NAND_MASK); -+} -+module_exit(toto_cleanup); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Richard Woodruff "); -+MODULE_DESCRIPTION("Glue layer for NAND flash on toto board"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/nand/tx4925ndfmc.c linux/drivers/mtd/nand/tx4925ndfmc.c ---- linux-mips-2.4.27/drivers/mtd/nand/tx4925ndfmc.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/nand/tx4925ndfmc.c 2004-11-19 10:25:12.017181856 +0100 -@@ -0,0 +1,442 @@ -+/* -+ * drivers/mtd/tx4925ndfmc.c -+ * -+ * Overview: -+ * This is a device driver for the NAND flash device found on the -+ * Toshiba RBTX4925 reference board, which is a SmartMediaCard. It supports -+ * 16MiB, 32MiB and 64MiB cards. -+ * -+ * Author: MontaVista Software, Inc. source@mvista.com -+ * -+ * Derived from drivers/mtd/autcpu12.c -+ * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) -+ * -+ * $Id$ -+ * -+ * Copyright (C) 2001 Toshiba Corporation -+ * -+ * 2003 (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. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+extern struct nand_oobinfo jffs2_oobinfo; -+ -+/* -+ * MTD structure for RBTX4925 board -+ */ -+static struct mtd_info *tx4925ndfmc_mtd = NULL; -+ -+/* -+ * Module stuff -+ */ -+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -+#define tx4925ndfmc_init init_module -+#define tx4925ndfmc_cleanup cleanup_module -+#endif -+ -+/* -+ * Define partitions for flash devices -+ */ -+ -+static struct mtd_partition partition_info16k[] = { -+ { .name = "RBTX4925 flash partition 1", -+ .offset = 0, -+ .size = 8 * 0x00100000 }, -+ { .name = "RBTX4925 flash partition 2", -+ .offset = 8 * 0x00100000, -+ .size = 8 * 0x00100000 }, -+}; -+ -+static struct mtd_partition partition_info32k[] = { -+ { .name = "RBTX4925 flash partition 1", -+ .offset = 0, -+ .size = 8 * 0x00100000 }, -+ { .name = "RBTX4925 flash partition 2", -+ .offset = 8 * 0x00100000, -+ .size = 24 * 0x00100000 }, -+}; -+ -+static struct mtd_partition partition_info64k[] = { -+ { .name = "User FS", -+ .offset = 0, -+ .size = 16 * 0x00100000 }, -+ { .name = "RBTX4925 flash partition 2", -+ .offset = 16 * 0x00100000, -+ .size = 48 * 0x00100000}, -+}; -+ -+static struct mtd_partition partition_info128k[] = { -+ { .name = "Skip bad section", -+ .offset = 0, -+ .size = 16 * 0x00100000 }, -+ { .name = "User FS", -+ .offset = 16 * 0x00100000, -+ .size = 112 * 0x00100000 }, -+}; -+#define NUM_PARTITIONS16K 2 -+#define NUM_PARTITIONS32K 2 -+#define NUM_PARTITIONS64K 2 -+#define NUM_PARTITIONS128K 2 -+ -+/* -+ * hardware specific access to control-lines -+*/ -+static void tx4925ndfmc_hwcontrol(struct mtd_info *mtd, int cmd) -+{ -+ -+ switch(cmd){ -+ -+ case NAND_CTL_SETCLE: -+ tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_CLE; -+ break; -+ case NAND_CTL_CLRCLE: -+ tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_CLE; -+ break; -+ case NAND_CTL_SETALE: -+ tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ALE; -+ break; -+ case NAND_CTL_CLRALE: -+ tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ALE; -+ break; -+ case NAND_CTL_SETNCE: -+ tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_CE; -+ break; -+ case NAND_CTL_CLRNCE: -+ tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_CE; -+ break; -+ case NAND_CTL_SETWP: -+ tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_WE; -+ break; -+ case NAND_CTL_CLRWP: -+ tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_WE; -+ break; -+ } -+} -+ -+/* -+* read device ready pin -+*/ -+static int tx4925ndfmc_device_ready(struct mtd_info *mtd) -+{ -+ int ready; -+ ready = (tx4925_ndfmcptr->sr & TX4925_NDSFR_BUSY) ? 0 : 1; -+ return ready; -+} -+void tx4925ndfmc_enable_hwecc(struct mtd_info *mtd, int mode) -+{ -+ /* reset first */ -+ tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_MASK; -+ tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK; -+ tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_ENAB; -+} -+static void tx4925ndfmc_disable_ecc(void) -+{ -+ tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK; -+} -+static void tx4925ndfmc_enable_read_ecc(void) -+{ -+ tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK; -+ tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_READ; -+} -+void tx4925ndfmc_readecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code){ -+ int i; -+ u_char *ecc = ecc_code; -+ tx4925ndfmc_enable_read_ecc(); -+ for (i = 0;i < 6;i++,ecc++) -+ *ecc = tx4925_read_nfmc(&(tx4925_ndfmcptr->dtr)); -+ tx4925ndfmc_disable_ecc(); -+} -+void tx4925ndfmc_device_setup(void) -+{ -+ -+ *(unsigned char *)0xbb005000 &= ~0x08; -+ -+ /* reset NDFMC */ -+ tx4925_ndfmcptr->rstr |= TX4925_NDFRSTR_RST; -+ while (tx4925_ndfmcptr->rstr & TX4925_NDFRSTR_RST); -+ -+ /* setup BusSeparete, Hold Time, Strobe Pulse Width */ -+ tx4925_ndfmcptr->mcr = TX4925_BSPRT ? TX4925_NDFMCR_BSPRT : 0; -+ tx4925_ndfmcptr->spr = TX4925_HOLD << 4 | TX4925_SPW; -+} -+static u_char tx4925ndfmc_nand_read_byte(struct mtd_info *mtd) -+{ -+ struct nand_chip *this = mtd->priv; -+ return tx4925_read_nfmc(this->IO_ADDR_R); -+} -+ -+static void tx4925ndfmc_nand_write_byte(struct mtd_info *mtd, u_char byte) -+{ -+ struct nand_chip *this = mtd->priv; -+ tx4925_write_nfmc(byte, this->IO_ADDR_W); -+} -+ -+static void tx4925ndfmc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_W); -+} -+ -+static void tx4925ndfmc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_R); -+} -+ -+static int tx4925ndfmc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_R)) -+ return i; -+ -+ return 0; -+} -+ -+/* -+ * Send command to NAND device -+ */ -+static void tx4925ndfmc_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) -+{ -+ register struct nand_chip *this = mtd->priv; -+ -+ /* Begin command latch cycle */ -+ this->hwcontrol(mtd, NAND_CTL_SETCLE); -+ /* -+ * Write out the command to the device. -+ */ -+ if (command == NAND_CMD_SEQIN) { -+ int readcmd; -+ -+ if (column >= mtd->oobblock) { -+ /* OOB area */ -+ column -= mtd->oobblock; -+ readcmd = NAND_CMD_READOOB; -+ } else if (column < 256) { -+ /* First 256 bytes --> READ0 */ -+ readcmd = NAND_CMD_READ0; -+ } else { -+ column -= 256; -+ readcmd = NAND_CMD_READ1; -+ } -+ this->write_byte(mtd, readcmd); -+ } -+ this->write_byte(mtd, command); -+ -+ /* Set ALE and clear CLE to start address cycle */ -+ this->hwcontrol(mtd, NAND_CTL_CLRCLE); -+ -+ if (column != -1 || page_addr != -1) { -+ this->hwcontrol(mtd, NAND_CTL_SETALE); -+ -+ /* Serially input address */ -+ if (column != -1) -+ this->write_byte(mtd, column); -+ if (page_addr != -1) { -+ this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); -+ this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); -+ /* One more address cycle for higher density devices */ -+ if (mtd->size & 0x0c000000) -+ this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f)); -+ } -+ /* Latch in address */ -+ this->hwcontrol(mtd, NAND_CTL_CLRALE); -+ } -+ -+ /* -+ * program and erase have their own busy handlers -+ * status and sequential in needs no delay -+ */ -+ switch (command) { -+ -+ case NAND_CMD_PAGEPROG: -+ /* Turn off WE */ -+ this->hwcontrol (mtd, NAND_CTL_CLRWP); -+ return; -+ -+ case NAND_CMD_SEQIN: -+ /* Turn on WE */ -+ this->hwcontrol (mtd, NAND_CTL_SETWP); -+ return; -+ -+ case NAND_CMD_ERASE1: -+ case NAND_CMD_ERASE2: -+ case NAND_CMD_STATUS: -+ return; -+ -+ case NAND_CMD_RESET: -+ if (this->dev_ready) -+ break; -+ this->hwcontrol(mtd, NAND_CTL_SETCLE); -+ this->write_byte(mtd, NAND_CMD_STATUS); -+ this->hwcontrol(mtd, NAND_CTL_CLRCLE); -+ while ( !(this->read_byte(mtd) & 0x40)); -+ return; -+ -+ /* This applies to read commands */ -+ default: -+ /* -+ * If we don't have access to the busy pin, we apply the given -+ * command delay -+ */ -+ if (!this->dev_ready) { -+ udelay (this->chip_delay); -+ return; -+ } -+ } -+ -+ /* wait until command is processed */ -+ while (!this->dev_ready(mtd)); -+} -+ -+#ifdef CONFIG_MTD_CMDLINE_PARTS -+extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partitio -+n **pparts, char *); -+#endif -+ -+/* -+ * Main initialization routine -+ */ -+extern int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc); -+int __init tx4925ndfmc_init (void) -+{ -+ struct nand_chip *this; -+ int err = 0; -+ -+ /* Allocate memory for MTD device structure and private data */ -+ tx4925ndfmc_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), -+ GFP_KERNEL); -+ if (!tx4925ndfmc_mtd) { -+ printk ("Unable to allocate RBTX4925 NAND MTD device structure.\n"); -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ tx4925ndfmc_device_setup(); -+ -+ /* io is indirect via a register so don't need to ioremap address */ -+ -+ /* Get pointer to private data */ -+ this = (struct nand_chip *) (&tx4925ndfmc_mtd[1]); -+ -+ /* Initialize structures */ -+ memset((char *) tx4925ndfmc_mtd, 0, sizeof(struct mtd_info)); -+ memset((char *) this, 0, sizeof(struct nand_chip)); -+ -+ /* Link the private data with the MTD structure */ -+ tx4925ndfmc_mtd->priv = this; -+ -+ /* Set address of NAND IO lines */ -+ this->IO_ADDR_R = (unsigned long)&(tx4925_ndfmcptr->dtr); -+ this->IO_ADDR_W = (unsigned long)&(tx4925_ndfmcptr->dtr); -+ this->hwcontrol = tx4925ndfmc_hwcontrol; -+ this->enable_hwecc = tx4925ndfmc_enable_hwecc; -+ this->calculate_ecc = tx4925ndfmc_readecc; -+ this->correct_data = nand_correct_data; -+ this->eccmode = NAND_ECC_HW6_512; -+ this->dev_ready = tx4925ndfmc_device_ready; -+ /* 20 us command delay time */ -+ this->chip_delay = 20; -+ this->read_byte = tx4925ndfmc_nand_read_byte; -+ this->write_byte = tx4925ndfmc_nand_write_byte; -+ this->cmdfunc = tx4925ndfmc_nand_command; -+ this->write_buf = tx4925ndfmc_nand_write_buf; -+ this->read_buf = tx4925ndfmc_nand_read_buf; -+ this->verify_buf = tx4925ndfmc_nand_verify_buf; -+ -+ /* Scan to find existance of the device */ -+ if (nand_scan (tx4925ndfmc_mtd, 1)) { -+ err = -ENXIO; -+ goto out_ior; -+ } -+ -+ /* Allocate memory for internal data buffer */ -+ this->data_buf = kmalloc (sizeof(u_char) * (tx4925ndfmc_mtd->oobblock + tx4925ndfmc_mtd->oobsize), GFP_KERNEL); -+ if (!this->data_buf) { -+ printk ("Unable to allocate NAND data buffer for RBTX4925.\n"); -+ err = -ENOMEM; -+ goto out_ior; -+ } -+ -+ /* Register the partitions */ -+#ifdef CONFIG_MTD_CMDLINE_PARTS -+ { -+ int mtd_parts_nb = 0; -+ struct mtd_partition *mtd_parts = 0; -+ mtd_parts_nb = parse_cmdline_partitions(tx4925ndfmc_mtd, &mtd_parts, "tx4925ndfmc"); -+ if (mtd_parts_nb > 0) -+ add_mtd_partitions(tx4925ndfmc_mtd, mtd_parts, mtd_parts_nb); -+ else -+ add_mtd_device(tx4925ndfmc_mtd); -+ } -+#else /* ifdef CONFIG_MTD_CMDLINE_PARTS */ -+ switch(tx4925ndfmc_mtd->size){ -+ case 0x01000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info16k, NUM_PARTITIONS16K); break; -+ case 0x02000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info32k, NUM_PARTITIONS32K); break; -+ case 0x04000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info64k, NUM_PARTITIONS64K); break; -+ case 0x08000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info128k, NUM_PARTITIONS128K); break; -+ default: { -+ printk ("Unsupported SmartMedia device\n"); -+ err = -ENXIO; -+ goto out_buf; -+ } -+ } -+#endif /* ifdef CONFIG_MTD_CMDLINE_PARTS */ -+ goto out; -+ -+out_buf: -+ kfree (this->data_buf); -+out_ior: -+out: -+ return err; -+} -+ -+module_init(tx4925ndfmc_init); -+ -+/* -+ * Clean up routine -+ */ -+#ifdef MODULE -+static void __exit tx4925ndfmc_cleanup (void) -+{ -+ struct nand_chip *this = (struct nand_chip *) &tx4925ndfmc_mtd[1]; -+ -+ /* Unregister partitions */ -+ del_mtd_partitions(tx4925ndfmc_mtd); -+ -+ /* Unregister the device */ -+ del_mtd_device (tx4925ndfmc_mtd); -+ -+ /* Free internal data buffers */ -+ kfree (this->data_buf); -+ -+ /* Free the MTD device structure */ -+ kfree (tx4925ndfmc_mtd); -+} -+module_exit(tx4925ndfmc_cleanup); -+#endif -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Alice Hennessy "); -+MODULE_DESCRIPTION("Glue layer for SmartMediaCard on Toshiba RBTX4925"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/nand/tx4938ndfmc.c linux/drivers/mtd/nand/tx4938ndfmc.c ---- linux-mips-2.4.27/drivers/mtd/nand/tx4938ndfmc.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/mtd/nand/tx4938ndfmc.c 2004-11-19 10:25:12.019181552 +0100 -@@ -0,0 +1,422 @@ -+/* -+ * drivers/mtd/nand/tx4938ndfmc.c -+ * -+ * Overview: -+ * This is a device driver for the NAND flash device connected to -+ * TX4938 internal NAND Memory Controller. -+ * TX4938 NDFMC is almost same as TX4925 NDFMC, but register size are 64 bit. -+ * -+ * Author: source@mvista.com -+ * -+ * Based on spia.c by Steven J. Hill -+ * -+ * $Id$ -+ * -+ * Copyright (C) 2000-2001 Toshiba Corporation -+ * -+ * 2003 (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. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+extern struct nand_oobinfo jffs2_oobinfo; -+ -+/* -+ * MTD structure for TX4938 NDFMC -+ */ -+static struct mtd_info *tx4938ndfmc_mtd; -+ -+/* -+ * Define partitions for flash device -+ */ -+#define flush_wb() (void)tx4938_ndfmcptr->mcr; -+ -+#define NUM_PARTITIONS 3 -+#define NUMBER_OF_CIS_BLOCKS 24 -+#define SIZE_OF_BLOCK 0x00004000 -+#define NUMBER_OF_BLOCK_PER_ZONE 1024 -+#define SIZE_OF_ZONE (NUMBER_OF_BLOCK_PER_ZONE * SIZE_OF_BLOCK) -+#ifndef CONFIG_MTD_CMDLINE_PARTS -+/* -+ * You can use the following sample of MTD partitions -+ * on the NAND Flash Memory 32MB or more. -+ * -+ * The following figure shows the image of the sample partition on -+ * the 32MB NAND Flash Memory. -+ * -+ * Block No. -+ * 0 +-----------------------------+ ------ -+ * | CIS | ^ -+ * 24 +-----------------------------+ | -+ * | kernel image | | Zone 0 -+ * | | | -+ * +-----------------------------+ | -+ * 1023 | unused area | v -+ * +-----------------------------+ ------ -+ * 1024 | JFFS2 | ^ -+ * | | | -+ * | | | Zone 1 -+ * | | | -+ * | | | -+ * | | v -+ * 2047 +-----------------------------+ ------ -+ * -+ */ -+static struct mtd_partition partition_info[NUM_PARTITIONS] = { -+ { -+ .name = "RBTX4938 CIS Area", -+ .offset = 0, -+ .size = (NUMBER_OF_CIS_BLOCKS * SIZE_OF_BLOCK), -+ .mask_flags = MTD_WRITEABLE /* This partition is NOT writable */ -+ }, -+ { -+ .name = "RBTX4938 kernel image", -+ .offset = MTDPART_OFS_APPEND, -+ .size = 8 * 0x00100000, /* 8MB (Depends on size of kernel image) */ -+ .mask_flags = MTD_WRITEABLE /* This partition is NOT writable */ -+ }, -+ { -+ .name = "Root FS (JFFS2)", -+ .offset = (0 + SIZE_OF_ZONE), /* start address of next zone */ -+ .size = MTDPART_SIZ_FULL -+ }, -+}; -+#endif -+ -+static void tx4938ndfmc_hwcontrol(struct mtd_info *mtd, int cmd) -+{ -+ switch (cmd) { -+ case NAND_CTL_SETCLE: -+ tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_CLE; -+ break; -+ case NAND_CTL_CLRCLE: -+ tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_CLE; -+ break; -+ case NAND_CTL_SETALE: -+ tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_ALE; -+ break; -+ case NAND_CTL_CLRALE: -+ tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_ALE; -+ break; -+ /* TX4938_NDFMCR_CE bit is 0:high 1:low */ -+ case NAND_CTL_SETNCE: -+ tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_CE; -+ break; -+ case NAND_CTL_CLRNCE: -+ tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_CE; -+ break; -+ case NAND_CTL_SETWP: -+ tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_WE; -+ break; -+ case NAND_CTL_CLRWP: -+ tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_WE; -+ break; -+ } -+} -+static int tx4938ndfmc_dev_ready(struct mtd_info *mtd) -+{ -+ flush_wb(); -+ return !(tx4938_ndfmcptr->sr & TX4938_NDFSR_BUSY); -+} -+static void tx4938ndfmc_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) -+{ -+ u32 mcr = tx4938_ndfmcptr->mcr; -+ mcr &= ~TX4938_NDFMCR_ECC_ALL; -+ tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF; -+ tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_READ; -+ ecc_code[1] = tx4938_ndfmcptr->dtr; -+ ecc_code[0] = tx4938_ndfmcptr->dtr; -+ ecc_code[2] = tx4938_ndfmcptr->dtr; -+ tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF; -+} -+static void tx4938ndfmc_enable_hwecc(struct mtd_info *mtd, int mode) -+{ -+ u32 mcr = tx4938_ndfmcptr->mcr; -+ mcr &= ~TX4938_NDFMCR_ECC_ALL; -+ tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_RESET; -+ tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF; -+ tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_ON; -+} -+ -+static u_char tx4938ndfmc_nand_read_byte(struct mtd_info *mtd) -+{ -+ struct nand_chip *this = mtd->priv; -+ return tx4938_read_nfmc(this->IO_ADDR_R); -+} -+ -+static void tx4938ndfmc_nand_write_byte(struct mtd_info *mtd, u_char byte) -+{ -+ struct nand_chip *this = mtd->priv; -+ tx4938_write_nfmc(byte, this->IO_ADDR_W); -+} -+ -+static void tx4938ndfmc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_W); -+} -+ -+static void tx4938ndfmc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_R); -+} -+ -+static int tx4938ndfmc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ int i; -+ struct nand_chip *this = mtd->priv; -+ -+ for (i=0; iIO_ADDR_R)) -+ return i; -+ -+ return 0; -+} -+ -+/* -+ * Send command to NAND device -+ */ -+static void tx4938ndfmc_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) -+{ -+ register struct nand_chip *this = mtd->priv; -+ -+ /* Begin command latch cycle */ -+ this->hwcontrol(mtd, NAND_CTL_SETCLE); -+ /* -+ * Write out the command to the device. -+ */ -+ if (command == NAND_CMD_SEQIN) { -+ int readcmd; -+ -+ if (column >= mtd->oobblock) { -+ /* OOB area */ -+ column -= mtd->oobblock; -+ readcmd = NAND_CMD_READOOB; -+ } else if (column < 256) { -+ /* First 256 bytes --> READ0 */ -+ readcmd = NAND_CMD_READ0; -+ } else { -+ column -= 256; -+ readcmd = NAND_CMD_READ1; -+ } -+ this->write_byte(mtd, readcmd); -+ } -+ this->write_byte(mtd, command); -+ -+ /* Set ALE and clear CLE to start address cycle */ -+ this->hwcontrol(mtd, NAND_CTL_CLRCLE); -+ -+ if (column != -1 || page_addr != -1) { -+ this->hwcontrol(mtd, NAND_CTL_SETALE); -+ -+ /* Serially input address */ -+ if (column != -1) -+ this->write_byte(mtd, column); -+ if (page_addr != -1) { -+ this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); -+ this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); -+ /* One more address cycle for higher density devices */ -+ if (mtd->size & 0x0c000000) -+ this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f)); -+ } -+ /* Latch in address */ -+ this->hwcontrol(mtd, NAND_CTL_CLRALE); -+ } -+ -+ /* -+ * program and erase have their own busy handlers -+ * status and sequential in needs no delay -+ */ -+ switch (command) { -+ -+ case NAND_CMD_PAGEPROG: -+ /* Turn off WE */ -+ this->hwcontrol (mtd, NAND_CTL_CLRWP); -+ return; -+ -+ case NAND_CMD_SEQIN: -+ /* Turn on WE */ -+ this->hwcontrol (mtd, NAND_CTL_SETWP); -+ return; -+ -+ case NAND_CMD_ERASE1: -+ case NAND_CMD_ERASE2: -+ case NAND_CMD_STATUS: -+ return; -+ -+ case NAND_CMD_RESET: -+ if (this->dev_ready) -+ break; -+ this->hwcontrol(mtd, NAND_CTL_SETCLE); -+ this->write_byte(mtd, NAND_CMD_STATUS); -+ this->hwcontrol(mtd, NAND_CTL_CLRCLE); -+ while ( !(this->read_byte(mtd) & 0x40)); -+ return; -+ -+ /* This applies to read commands */ -+ default: -+ /* -+ * If we don't have access to the busy pin, we apply the given -+ * command delay -+ */ -+ if (!this->dev_ready) { -+ udelay (this->chip_delay); -+ return; -+ } -+ } -+ -+ /* wait until command is processed */ -+ while (!this->dev_ready(mtd)); -+} -+ -+#ifdef CONFIG_MTD_CMDLINE_PARTS -+extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, char *); -+#endif -+/* -+ * Main initialization routine -+ */ -+int __init tx4938ndfmc_init (void) -+{ -+ struct nand_chip *this; -+ int bsprt = 0, hold = 0xf, spw = 0xf; -+ int protected = 0; -+ -+ if ((*rbtx4938_piosel_ptr & 0x0c) != 0x08) { -+ printk("TX4938 NDFMC: disabled by IOC PIOSEL\n"); -+ return -ENODEV; -+ } -+ bsprt = 1; -+ hold = 2; -+ spw = 9 - 1; /* 8 GBUSCLK = 80ns (@ GBUSCLK 100MHz) */ -+ -+ if ((tx4938_ccfgptr->pcfg & -+ (TX4938_PCFG_ATA_SEL|TX4938_PCFG_ISA_SEL|TX4938_PCFG_NDF_SEL)) -+ != TX4938_PCFG_NDF_SEL) { -+ printk("TX4938 NDFMC: disabled by PCFG.\n"); -+ return -ENODEV; -+ } -+ -+ /* reset NDFMC */ -+ tx4938_ndfmcptr->rstr |= TX4938_NDFRSTR_RST; -+ while (tx4938_ndfmcptr->rstr & TX4938_NDFRSTR_RST) -+ ; -+ /* setup BusSeparete, Hold Time, Strobe Pulse Width */ -+ tx4938_ndfmcptr->mcr = bsprt ? TX4938_NDFMCR_BSPRT : 0; -+ tx4938_ndfmcptr->spr = hold << 4 | spw; -+ -+ /* Allocate memory for MTD device structure and private data */ -+ tx4938ndfmc_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), -+ GFP_KERNEL); -+ if (!tx4938ndfmc_mtd) { -+ printk ("Unable to allocate TX4938 NDFMC MTD device structure.\n"); -+ return -ENOMEM; -+ } -+ -+ /* Get pointer to private data */ -+ this = (struct nand_chip *) (&tx4938ndfmc_mtd[1]); -+ -+ /* Initialize structures */ -+ memset((char *) tx4938ndfmc_mtd, 0, sizeof(struct mtd_info)); -+ memset((char *) this, 0, sizeof(struct nand_chip)); -+ -+ /* Link the private data with the MTD structure */ -+ tx4938ndfmc_mtd->priv = this; -+ -+ /* Set address of NAND IO lines */ -+ this->IO_ADDR_R = (unsigned long)&tx4938_ndfmcptr->dtr; -+ this->IO_ADDR_W = (unsigned long)&tx4938_ndfmcptr->dtr; -+ this->hwcontrol = tx4938ndfmc_hwcontrol; -+ this->dev_ready = tx4938ndfmc_dev_ready; -+ this->calculate_ecc = tx4938ndfmc_calculate_ecc; -+ this->correct_data = nand_correct_data; -+ this->enable_hwecc = tx4938ndfmc_enable_hwecc; -+ this->eccmode = NAND_ECC_HW3_256; -+ this->chip_delay = 100; -+ this->read_byte = tx4938ndfmc_nand_read_byte; -+ this->write_byte = tx4938ndfmc_nand_write_byte; -+ this->cmdfunc = tx4938ndfmc_nand_command; -+ this->write_buf = tx4938ndfmc_nand_write_buf; -+ this->read_buf = tx4938ndfmc_nand_read_buf; -+ this->verify_buf = tx4938ndfmc_nand_verify_buf; -+ -+ /* Scan to find existance of the device */ -+ if (nand_scan (tx4938ndfmc_mtd, 1)) { -+ kfree (tx4938ndfmc_mtd); -+ return -ENXIO; -+ } -+ -+ /* Allocate memory for internal data buffer */ -+ this->data_buf = kmalloc (sizeof(u_char) * (tx4938ndfmc_mtd->oobblock + tx4938ndfmc_mtd->oobsize), GFP_KERNEL); -+ if (!this->data_buf) { -+ printk ("Unable to allocate NAND data buffer for TX4938.\n"); -+ kfree (tx4938ndfmc_mtd); -+ return -ENOMEM; -+ } -+ -+ if (protected) { -+ printk(KERN_INFO "TX4938 NDFMC: write protected.\n"); -+ tx4938ndfmc_mtd->flags &= ~(MTD_WRITEABLE | MTD_ERASEABLE); -+ } -+ -+#ifdef CONFIG_MTD_CMDLINE_PARTS -+ { -+ int mtd_parts_nb = 0; -+ struct mtd_partition *mtd_parts = 0; -+ mtd_parts_nb = parse_cmdline_partitions(tx4938ndfmc_mtd, &mtd_parts, "tx4938ndfmc"); -+ if (mtd_parts_nb > 0) -+ add_mtd_partitions(tx4938ndfmc_mtd, mtd_parts, mtd_parts_nb); -+ else -+ add_mtd_device(tx4938ndfmc_mtd); -+ } -+#else -+ add_mtd_partitions(tx4938ndfmc_mtd, partition_info, NUM_PARTITIONS ); -+#endif -+ -+ return 0; -+} -+module_init(tx4938ndfmc_init); -+ -+/* -+ * Clean up routine -+ */ -+static void __exit tx4938ndfmc_cleanup (void) -+{ -+ struct nand_chip *this = (struct nand_chip *) tx4938ndfmc_mtd->priv; -+ -+ /* Unregister the device */ -+#ifdef CONFIG_MTD_CMDLINE_PARTS -+ del_mtd_partitions(tx4938ndfmc_mtd); -+#endif -+ del_mtd_device (tx4938ndfmc_mtd); -+ -+ /* Free the MTD device structure */ -+ kfree (tx4938ndfmc_mtd); -+ -+ /* Free internal data buffer */ -+ kfree (this->data_buf); -+} -+module_exit(tx4938ndfmc_cleanup); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Alice Hennessy "); -+MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on TX4938 NDFMC"); -diff -Nurb linux-mips-2.4.27/drivers/mtd/nftlcore.c linux/drivers/mtd/nftlcore.c ---- linux-mips-2.4.27/drivers/mtd/nftlcore.c 2003-02-26 01:53:49.000000000 +0100 -+++ linux/drivers/mtd/nftlcore.c 2004-11-19 10:25:11.653237184 +0100 -@@ -1,7 +1,7 @@ - /* Linux driver for NAND Flash Translation Layer */ - /* (c) 1999 Machine Vision Holdings, Inc. */ - /* Author: David Woodhouse */ --/* $Id$ */ -+/* $Id$ */ - - /* - The contents of this file are distributed under the GNU General -@@ -23,15 +23,13 @@ - #include - #include - #include --#include -+#include - --#ifdef CONFIG_KMOD - #include --#endif - #include - #include - #include --#include -+#include - - /* maximum number of loops while examining next block, to have a - chance to detect consistency problems (they should never happen -@@ -39,187 +37,95 @@ - - #define MAX_LOOPS 10000 - --/* NFTL block device stuff */ --#define MAJOR_NR NFTL_MAJOR --#define DEVICE_REQUEST nftl_request --#define DEVICE_OFF(device) -- -- --#include --#include -- --/* Linux-specific block device functions */ -- --/* I _HATE_ the Linux block device setup more than anything else I've ever -- * encountered, except ... -- */ -- --static int nftl_sizes[256]; --static int nftl_blocksizes[256]; -- --/* .. for the Linux partition table handling. */ --struct hd_struct part_table[256]; -- --#if LINUX_VERSION_CODE < 0x20328 --static void dummy_init (struct gendisk *crap) --{} --#endif -- --static struct gendisk nftl_gendisk = { -- major: MAJOR_NR, -- major_name: "nftl", -- minor_shift: NFTL_PARTN_BITS, /* Bits to shift to get real from partition */ -- max_p: (1<mtd == mtd) { -- /* This is a Spare Media Header for an NFTL we've already found */ -- DEBUG(MTD_DEBUG_LEVEL1, "MTD already mounted as NFTL\n"); -+ if (mtd->ecctype != MTD_ECC_RS_DiskOnChip) - return; -- } -- } -- if (firstfree == -1) { -- printk(KERN_WARNING "No more NFTL slot available\n"); -- return; -- } -+ -+ DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name); - - nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); -+ - if (!nftl) { -- printk(KERN_WARNING "Out of memory for NFTL data structures\n"); -+ printk(KERN_WARNING "NFTL: out of memory for data structures\n"); - return; - } -+ memset(nftl, 0, sizeof(*nftl)); - -- init_MUTEX(&nftl->mutex); -- -- nftl->mtd = mtd; -+ nftl->mbd.mtd = mtd; -+ nftl->mbd.devnum = -1; -+ nftl->mbd.blksize = 512; -+ nftl->mbd.tr = tr; - - if (NFTL_mount(nftl) < 0) { -- printk(KERN_WARNING "Could not mount NFTL device\n"); -+ printk(KERN_WARNING "NFTL: could not mount device\n"); - kfree(nftl); - return; - } - - /* OK, it's a new one. Set up all the data structures. */ --#ifdef PSYCHO_DEBUG -- printk("Found new NFTL nftl%c\n", firstfree + 'a'); --#endif - -- /* linux stuff */ -- nftl->usecount = 0; -+ /* Calculate geometry */ - nftl->cylinders = 1024; - nftl->heads = 16; - - temp = nftl->cylinders * nftl->heads; -- nftl->sectors = nftl->nr_sects / temp; -- if (nftl->nr_sects % temp) { -+ nftl->sectors = nftl->mbd.size / temp; -+ if (nftl->mbd.size % temp) { - nftl->sectors++; - temp = nftl->cylinders * nftl->sectors; -- nftl->heads = nftl->nr_sects / temp; -+ nftl->heads = nftl->mbd.size / temp; - -- if (nftl->nr_sects % temp) { -+ if (nftl->mbd.size % temp) { - nftl->heads++; - temp = nftl->heads * nftl->sectors; -- nftl->cylinders = nftl->nr_sects / temp; -+ nftl->cylinders = nftl->mbd.size / temp; - } - } - -- if (nftl->nr_sects != nftl->heads * nftl->cylinders * nftl->sectors) { -- printk(KERN_WARNING "Cannot calculate an NFTL geometry to " -- "match size of 0x%x.\n", nftl->nr_sects); -- printk(KERN_WARNING "Using C:%d H:%d S:%d (== 0x%lx sects)\n", -+ if (nftl->mbd.size != nftl->heads * nftl->cylinders * nftl->sectors) { -+ /* -+ Oh no we don't have -+ mbd.size == heads * cylinders * sectors -+ */ -+ printk(KERN_WARNING "NFTL: cannot calculate a geometry to " -+ "match size of 0x%lx.\n", nftl->mbd.size); -+ printk(KERN_WARNING "NFTL: using C:%d H:%d S:%d " -+ "(== 0x%lx sects)\n", - nftl->cylinders, nftl->heads , nftl->sectors, -- (long)nftl->cylinders * (long)nftl->heads * (long)nftl->sectors ); -- -- /* Oh no we don't have nftl->nr_sects = nftl->heads * nftl->cylinders * nftl->sectors; */ -+ (long)nftl->cylinders * (long)nftl->heads * -+ (long)nftl->sectors ); - } -- NFTLs[firstfree] = nftl; -- /* Finally, set up the block device sizes */ -- nftl_sizes[firstfree * 16] = nftl->nr_sects; -- //nftl_blocksizes[firstfree*16] = 512; -- part_table[firstfree * 16].nr_sects = nftl->nr_sects; -- -- nftl_gendisk.nr_real++; -- -- /* partition check ... */ --#if LINUX_VERSION_CODE < 0x20328 -- resetup_one_dev(&nftl_gendisk, firstfree); --#else -- grok_partitions(&nftl_gendisk, firstfree, 1<nr_sects); --#endif --} -- --static void NFTL_unsetup(int i) --{ -- struct NFTLrecord *nftl = NFTLs[i]; -- -- DEBUG(MTD_DEBUG_LEVEL1, "NFTL_unsetup %d\n", i); -- -- NFTLs[i] = NULL; - -+ if (add_mtd_blktrans_dev(&nftl->mbd)) { - if (nftl->ReplUnitTable) - kfree(nftl->ReplUnitTable); - if (nftl->EUNtable) - kfree(nftl->EUNtable); -- -- nftl_gendisk.nr_real--; - kfree(nftl); --} -- --/* Search the MTD device for NFTL partitions */ --static void NFTL_notify_add(struct mtd_info *mtd) --{ -- DEBUG(MTD_DEBUG_LEVEL1, "NFTL_notify_add for %s\n", mtd->name); -- -- if (mtd) { -- if (!mtd->read_oob) { -- /* If this MTD doesn't have out-of-band data, -- then there's no point continuing */ -- DEBUG(MTD_DEBUG_LEVEL1, "No OOB data, quitting\n"); - return; - } -- DEBUG(MTD_DEBUG_LEVEL3, "mtd->read = %p, size = %d, erasesize = %d\n", -- mtd->read, mtd->size, mtd->erasesize); -- -- NFTL_setup(mtd); -- } -+#ifdef PSYCHO_DEBUG -+ printk(KERN_INFO "NFTL: Found new nftl%c\n", nftl->mbd.devnum + 'a'); -+#endif - } - --static void NFTL_notify_remove(struct mtd_info *mtd) -+static void nftl_remove_dev(struct mtd_blktrans_dev *dev) - { -- int i; -+ struct NFTLrecord *nftl = (void *)dev; - -- for (i = 0; i < MAX_NFTLS; i++) { -- if (NFTLs[i] && NFTLs[i]->mtd == mtd) -- NFTL_unsetup(i); -- } -+ DEBUG(MTD_DEBUG_LEVEL1, "NFTL: remove_dev (i=%d)\n", dev->devnum); -+ -+ del_mtd_blktrans_dev(dev); -+ if (nftl->ReplUnitTable) -+ kfree(nftl->ReplUnitTable); -+ if (nftl->EUNtable) -+ kfree(nftl->EUNtable); -+ kfree(nftl); - } - - #ifdef CONFIG_NFTL_RW -@@ -303,7 +209,7 @@ - - targetEUN = thisEUN; - for (block = 0; block < nftl->EraseSize / 512; block ++) { -- MTD_READOOB(nftl->mtd, -+ MTD_READOOB(nftl->mbd.mtd, - (thisEUN * nftl->EraseSize) + (block * 512), - 16 , &retlen, (char *)&oob); - if (block == 2) { -@@ -420,7 +326,7 @@ - chain by selecting the longer one */ - oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS); - oob.u.c.unused = 0xffffffff; -- MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, -+ MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, - 8, &retlen, (char *)&oob.u); - } - -@@ -444,16 +350,16 @@ - if (BlockMap[block] == BLOCK_NIL) - continue; - -- ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512), -+ ret = MTD_READECC(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512), - 512, &retlen, movebuf, (char *)&oob, NAND_ECC_DISKONCHIP); - if (ret < 0) { -- ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block]) -+ ret = MTD_READECC(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) - + (block * 512), 512, &retlen, - movebuf, (char *)&oob, NAND_ECC_DISKONCHIP); - if (ret != -EIO) - printk("Error went away on retry.\n"); - } -- MTD_WRITEECC(nftl->mtd, (nftl->EraseSize * targetEUN) + (block * 512), -+ MTD_WRITEECC(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + (block * 512), - 512, &retlen, movebuf, (char *)&oob, NAND_ECC_DISKONCHIP); - } - -@@ -462,7 +368,7 @@ - = cpu_to_le16(thisVUC); - oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; - -- MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 8, -+ MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 8, - 8, &retlen, (char *)&oob.u); - - /* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */ -@@ -582,7 +488,7 @@ - - lastEUN = writeEUN; - -- MTD_READOOB(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs, -+ MTD_READOOB(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs, - 8, &retlen, (char *)&bci); - - DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n", -@@ -670,12 +576,12 @@ - nftl->ReplUnitTable[writeEUN] = BLOCK_NIL; - - /* ... and on the flash itself */ -- MTD_READOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8, -+ MTD_READOOB(nftl->mbd.mtd, writeEUN * nftl->EraseSize + 8, 8, - &retlen, (char *)&oob.u); - - oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); - -- MTD_WRITEOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8, -+ MTD_WRITEOOB(nftl->mbd.mtd, writeEUN * nftl->EraseSize + 8, 8, - &retlen, (char *)&oob.u); - - /* we link the new block to the chain only after the -@@ -685,13 +591,13 @@ - /* Both in our cache... */ - nftl->ReplUnitTable[lastEUN] = writeEUN; - /* ... and on the flash itself */ -- MTD_READOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8, -+ MTD_READOOB(nftl->mbd.mtd, (lastEUN * nftl->EraseSize) + 8, - 8, &retlen, (char *)&oob.u); - - oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum - = cpu_to_le16(writeEUN); - -- MTD_WRITEOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8, -+ MTD_WRITEOOB(nftl->mbd.mtd, (lastEUN * nftl->EraseSize) + 8, - 8, &retlen, (char *)&oob.u); - } - -@@ -704,8 +610,10 @@ - return 0xffff; - } - --static int NFTL_writeblock(struct NFTLrecord *nftl, unsigned block, char *buffer) -+static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, -+ char *buffer) - { -+ struct NFTLrecord *nftl = (void *)mbd; - u16 writeEUN; - unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1); - size_t retlen; -@@ -720,7 +628,7 @@ - return 1; - } - -- MTD_WRITEECC(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs, -+ MTD_WRITEECC(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs, - 512, &retlen, (char *)buffer, (char *)eccbuf, NAND_ECC_DISKONCHIP); - /* no need to write SECTOR_USED flags since they are written in mtd_writeecc */ - -@@ -728,8 +636,10 @@ - } - #endif /* CONFIG_NFTL_RW */ - --static int NFTL_readblock(struct NFTLrecord *nftl, unsigned block, char *buffer) -+static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block, -+ char *buffer) - { -+ struct NFTLrecord *nftl = (void *)mbd; - u16 lastgoodEUN; - u16 thisEUN = nftl->EUNtable[block / (nftl->EraseSize / 512)]; - unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1); -@@ -742,7 +652,7 @@ - - if (thisEUN != BLOCK_NIL) { - while (thisEUN < nftl->nb_blocks) { -- if (MTD_READOOB(nftl->mtd, (thisEUN * nftl->EraseSize) + blockofs, -+ if (MTD_READOOB(nftl->mbd.mtd, (thisEUN * nftl->EraseSize) + blockofs, - 8, &retlen, (char *)&bci) < 0) - status = SECTOR_IGNORE; - else -@@ -761,13 +671,13 @@ - case SECTOR_IGNORE: - break; - default: -- printk("Unknown status for block %d in EUN %d: %x\n", -+ printk("Unknown status for block %ld in EUN %d: %x\n", - block, thisEUN, status); - break; - } - - if (!silly--) { -- printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", -+ printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%lx\n", - block / (nftl->EraseSize / 512)); - return 1; - } -@@ -783,264 +693,22 @@ - loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs; - size_t retlen; - u_char eccbuf[6]; -- if (MTD_READECC(nftl->mtd, ptr, 512, &retlen, buffer, eccbuf, NAND_ECC_DISKONCHIP)) -+ if (MTD_READECC(nftl->mbd.mtd, ptr, 512, &retlen, buffer, eccbuf, NAND_ECC_DISKONCHIP)) - return -EIO; - } - return 0; - } - --static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) --{ -- struct NFTLrecord *nftl; -- int p; -- -- nftl = NFTLs[MINOR(inode->i_rdev) >> NFTL_PARTN_BITS]; -- -- if (!nftl) return -EINVAL; -- -- switch (cmd) { -- case HDIO_GETGEO: { -- struct hd_geometry g; -- -- g.heads = nftl->heads; -- g.sectors = nftl->sectors; -- g.cylinders = nftl->cylinders; -- g.start = part_table[MINOR(inode->i_rdev)].start_sect; -- return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0; -- } -- case BLKGETSIZE: /* Return device size */ -- return put_user(part_table[MINOR(inode->i_rdev)].nr_sects, -- (unsigned long *) arg); -- --#ifdef BLKGETSIZE64 -- case BLKGETSIZE64: -- return put_user((u64)part_table[MINOR(inode->i_rdev)].nr_sects << 9, -- (u64 *)arg); --#endif -- -- case BLKFLSBUF: -- if (!capable(CAP_SYS_ADMIN)) return -EACCES; -- fsync_dev(inode->i_rdev); -- invalidate_buffers(inode->i_rdev); -- if (nftl->mtd->sync) -- nftl->mtd->sync(nftl->mtd); -- return 0; -- -- case BLKRRPART: -- if (!capable(CAP_SYS_ADMIN)) return -EACCES; -- if (nftl->usecount > 1) return -EBUSY; -- /* -- * We have to flush all buffers and invalidate caches, -- * or we won't be able to re-use the partitions, -- * if there was a change and we don't want to reboot -- */ -- p = (1< 0) { -- kdev_t devp = MKDEV(MAJOR(inode->i_dev), MINOR(inode->i_dev)+p); -- if (part_table[p].nr_sects > 0) -- invalidate_device (devp, 1); -- -- part_table[MINOR(inode->i_dev)+p].start_sect = 0; -- part_table[MINOR(inode->i_dev)+p].nr_sects = 0; -- } -- --#if LINUX_VERSION_CODE < 0x20328 -- resetup_one_dev(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS); --#else -- grok_partitions(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS, -- 1<nr_sects); --#endif -- return 0; -- --#if (LINUX_VERSION_CODE < 0x20303) -- RO_IOCTLS(inode->i_rdev, arg); /* ref. linux/blk.h */ --#else -- case BLKROSET: -- case BLKROGET: -- case BLKSSZGET: -- return blk_ioctl(inode->i_rdev, cmd, arg); --#endif -- -- default: -- return -EINVAL; -- } --} -- --void nftl_request(RQFUNC_ARG) --{ -- unsigned int dev, block, nsect; -- struct NFTLrecord *nftl; -- char *buffer; -- struct request *req; -- int res; -- -- while (1) { -- INIT_REQUEST; /* blk.h */ -- req = CURRENT; -- -- /* We can do this because the generic code knows not to -- touch the request at the head of the queue */ -- spin_unlock_irq(&io_request_lock); -- -- DEBUG(MTD_DEBUG_LEVEL2, "NFTL_request\n"); -- DEBUG(MTD_DEBUG_LEVEL3, "NFTL %s request, from sector 0x%04lx for 0x%04lx sectors\n", -- (req->cmd == READ) ? "Read " : "Write", -- req->sector, req->current_nr_sectors); -- -- dev = MINOR(req->rq_dev); -- block = req->sector; -- nsect = req->current_nr_sectors; -- buffer = req->buffer; -- res = 1; /* succeed */ -- -- if (dev >= MAX_NFTLS * (1<rq_dev)); -- res = 0; /* fail */ -- goto repeat; -- } -- -- nftl = NFTLs[dev / (1<mutex); -- DEBUG(MTD_DEBUG_LEVEL3, "Got mutex\n"); -- -- if (block + nsect > part_table[dev].nr_sects) { -- /* access past the end of device */ -- printk("nftl%c%d: bad access: block = %d, count = %d\n", -- (MINOR(req->rq_dev)>>6)+'a', dev & 0xf, block, nsect); -- up(&nftl->mutex); -- res = 0; /* fail */ -- goto repeat; -- } -- -- block += part_table[dev].start_sect; -- -- if (req->cmd == READ) { -- DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request of 0x%x sectors @ %x " -- "(req->nr_sectors == %lx)\n", nsect, block, req->nr_sectors); -- -- for ( ; nsect > 0; nsect-- , block++, buffer += 512) { -- /* Read a single sector to req->buffer + (512 * i) */ -- if (NFTL_readblock(nftl, block, buffer)) { -- DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request failed\n"); -- up(&nftl->mutex); -- res = 0; -- goto repeat; -- } -- } -- -- DEBUG(MTD_DEBUG_LEVEL2,"NFTL read request completed OK\n"); -- up(&nftl->mutex); -- goto repeat; -- } else if (req->cmd == WRITE) { -- DEBUG(MTD_DEBUG_LEVEL2, "NFTL write request of 0x%x sectors @ %x " -- "(req->nr_sectors == %lx)\n", nsect, block, -- req->nr_sectors); --#ifdef CONFIG_NFTL_RW -- for ( ; nsect > 0; nsect-- , block++, buffer += 512) { -- /* Read a single sector to req->buffer + (512 * i) */ -- if (NFTL_writeblock(nftl, block, buffer)) { -- DEBUG(MTD_DEBUG_LEVEL1,"NFTL write request failed\n"); -- up(&nftl->mutex); -- res = 0; -- goto repeat; -- } -- } -- DEBUG(MTD_DEBUG_LEVEL2,"NFTL write request completed OK\n"); --#else -- res = 0; /* Writes always fail */ --#endif /* CONFIG_NFTL_RW */ -- up(&nftl->mutex); -- goto repeat; -- } else { -- DEBUG(MTD_DEBUG_LEVEL0, "NFTL unknown request\n"); -- up(&nftl->mutex); -- res = 0; -- goto repeat; -- } -- repeat: -- DEBUG(MTD_DEBUG_LEVEL3, "end_request(%d)\n", res); -- spin_lock_irq(&io_request_lock); -- end_request(res); -- } --} -- --static int nftl_open(struct inode *ip, struct file *fp) --{ -- int nftlnum = MINOR(ip->i_rdev) >> NFTL_PARTN_BITS; -- struct NFTLrecord *thisNFTL; -- thisNFTL = NFTLs[nftlnum]; -- -- DEBUG(MTD_DEBUG_LEVEL2,"NFTL_open\n"); -- --#ifdef CONFIG_KMOD -- if (!thisNFTL && nftlnum == 0) { -- request_module("docprobe"); -- thisNFTL = NFTLs[nftlnum]; -- } --#endif -- if (!thisNFTL) { -- DEBUG(MTD_DEBUG_LEVEL2,"ENODEV: thisNFTL = %d, minor = %d, ip = %p, fp = %p\n", -- nftlnum, ip->i_rdev, ip, fp); -- return -ENODEV; -- } -- --#ifndef CONFIG_NFTL_RW -- if (fp->f_mode & FMODE_WRITE) -- return -EROFS; --#endif /* !CONFIG_NFTL_RW */ -- -- thisNFTL->usecount++; -- BLK_INC_USE_COUNT; -- if (!get_mtd_device(thisNFTL->mtd, -1)) { -- BLK_DEC_USE_COUNT; -- return -ENXIO; -- } -- -- return 0; --} -- --static int nftl_release(struct inode *inode, struct file *fp) -+static int nftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) - { -- struct NFTLrecord *thisNFTL; -- -- thisNFTL = NFTLs[MINOR(inode->i_rdev) / 16]; -- -- DEBUG(MTD_DEBUG_LEVEL2, "NFTL_release\n"); -- -- if (thisNFTL->mtd->sync) -- thisNFTL->mtd->sync(thisNFTL->mtd); -- thisNFTL->usecount--; -- BLK_DEC_USE_COUNT; -+ struct NFTLrecord *nftl = (void *)dev; - -- put_mtd_device(thisNFTL->mtd); -+ geo->heads = nftl->heads; -+ geo->sectors = nftl->sectors; -+ geo->cylinders = nftl->cylinders; - - return 0; - } --#if LINUX_VERSION_CODE < 0x20326 --static struct file_operations nftl_fops = { -- read: block_read, -- write: block_write, -- ioctl: nftl_ioctl, -- open: nftl_open, -- release: nftl_release, -- fsync: block_fsync, --}; --#else --static struct block_device_operations nftl_fops = --{ --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14) -- owner: THIS_MODULE, --#endif -- open: nftl_open, -- release: nftl_release, -- ioctl: nftl_ioctl --}; --#endif -- -- - - /**************************************************************************** - * -@@ -1048,49 +716,33 @@ - * - ****************************************************************************/ - --static struct mtd_notifier nftl_notifier = { -- add: NFTL_notify_add, -- remove: NFTL_notify_remove -+ -+struct mtd_blktrans_ops nftl_tr = { -+ .name = "nftl", -+ .major = NFTL_MAJOR, -+ .part_bits = NFTL_PARTN_BITS, -+ .getgeo = nftl_getgeo, -+ .readsect = nftl_readblock, -+#ifdef CONFIG_NFTL_RW -+ .writesect = nftl_writeblock, -+#endif -+ .add_mtd = nftl_add_mtd, -+ .remove_dev = nftl_remove_dev, -+ .owner = THIS_MODULE, - }; - - extern char nftlmountrev[]; - - int __init init_nftl(void) - { -- int i; -- --#ifdef PRERELEASE -- printk(KERN_INFO "NFTL driver: nftlcore.c $Revision$, nftlmount.c %s\n", nftlmountrev); --#endif -- -- if (register_blkdev(MAJOR_NR, "nftl", &nftl_fops)){ -- printk("unable to register NFTL block device on major %d\n", MAJOR_NR); -- return -EBUSY; -- } else { -- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &nftl_request); -+ printk(KERN_INFO "NFTL driver: nftlcore.c $Revision$, nftlmount.c %s\n", nftlmountrev); - -- /* set block size to 1kB each */ -- for (i = 0; i < 256; i++) { -- nftl_blocksizes[i] = 1024; -- } -- blksize_size[MAJOR_NR] = nftl_blocksizes; -- -- add_gendisk(&nftl_gendisk); -- } -- -- register_mtd_user(&nftl_notifier); -- -- return 0; -+ return register_mtd_blktrans(&nftl_tr); - } - - static void __exit cleanup_nftl(void) - { -- unregister_mtd_user(&nftl_notifier); -- unregister_blkdev(MAJOR_NR, "nftl"); -- -- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); -- -- del_gendisk(&nftl_gendisk); -+ deregister_mtd_blktrans(&nftl_tr); - } - - module_init(init_nftl); -diff -Nurb linux-mips-2.4.27/drivers/mtd/nftlmount.c linux/drivers/mtd/nftlmount.c ---- linux-mips-2.4.27/drivers/mtd/nftlmount.c 2003-07-05 05:23:38.000000000 +0200 -+++ linux/drivers/mtd/nftlmount.c 2004-11-19 10:25:11.655236880 +0100 -@@ -4,7 +4,7 @@ - * Author: Fabrice Bellard (fabrice.bellard@netgem.com) - * Copyright (C) 2000 Netgem S.A. - * -- * $Id$ -+ * $Id$ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -21,26 +21,17 @@ - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - --#define __NO_VERSION__ - #include --#include - #include --#include --#include --#include --#include - #include - #include --#include --#include - #include - #include - #include --#include - - #define SECTORSIZE 512 - --char nftlmountrev[]="$Revision$"; -+char nftlmountrev[]="$Revision$"; - - /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the - * various device information of the NFTL partition and Bad Unit Table. Update -@@ -59,8 +50,8 @@ - - /* Assume logical EraseSize == physical erasesize for starting the scan. - We'll sort it out later if we find a MediaHeader which says otherwise */ -- nftl->EraseSize = nftl->mtd->erasesize; -- nftl->nb_blocks = nftl->mtd->size / nftl->EraseSize; -+ nftl->EraseSize = nftl->mbd.mtd->erasesize; -+ nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize; - - nftl->MediaUnit = BLOCK_NIL; - nftl->SpareMediaUnit = BLOCK_NIL; -@@ -71,12 +62,12 @@ - - /* Check for ANAND header first. Then can whinge if it's found but later - checks fail */ -- if ((ret = MTD_READ(nftl->mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf))) { -+ if ((ret = MTD_READ(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf))) { - static int warncount = 5; - - if (warncount) { - printk(KERN_WARNING "Block read at 0x%x of mtd%d failed: %d\n", -- block * nftl->EraseSize, nftl->mtd->index, ret); -+ block * nftl->EraseSize, nftl->mbd.mtd->index, ret); - if (!--warncount) - printk(KERN_WARNING "Further failures for this block will not be printed\n"); - } -@@ -87,16 +78,16 @@ - /* ANAND\0 not found. Continue */ - #if 0 - printk(KERN_DEBUG "ANAND header not found at 0x%x in mtd%d\n", -- block * nftl->EraseSize, nftl->mtd->index); -+ block * nftl->EraseSize, nftl->mbd.mtd->index); - #endif - continue; - } - - /* To be safer with BIOS, also use erase mark as discriminant */ -- if ((ret = MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, -- 8, &retlen, (char *)&h1)) < 0) { -+ if ((ret = MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, -+ 8, &retlen, (char *)&h1) < 0)) { - printk(KERN_WARNING "ANAND header found at 0x%x in mtd%d, but OOB data read failed (err %d)\n", -- block * nftl->EraseSize, nftl->mtd->index, ret); -+ block * nftl->EraseSize, nftl->mbd.mtd->index, ret); - continue; - } - -@@ -106,23 +97,23 @@ - */ - if (le16_to_cpu(h1.EraseMark | h1.EraseMark1) != ERASE_MARK) { - printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but erase mark not present (0x%04x,0x%04x instead)\n", -- block * nftl->EraseSize, nftl->mtd->index, -+ block * nftl->EraseSize, nftl->mbd.mtd->index, - le16_to_cpu(h1.EraseMark), le16_to_cpu(h1.EraseMark1)); - continue; - } - - /* Finally reread to check ECC */ -- if ((ret = MTD_READECC(nftl->mtd, block * nftl->EraseSize, SECTORSIZE, -- &retlen, buf, (char *)&oob, NAND_ECC_DISKONCHIP)) < 0) { -+ if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, -+ &retlen, buf, (char *)&oob, NAND_ECC_DISKONCHIP) < 0)) { - printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n", -- block * nftl->EraseSize, nftl->mtd->index, ret); -+ block * nftl->EraseSize, nftl->mbd.mtd->index, ret); - continue; - } - - /* Paranoia. Check the ANAND header is still there after the ECC read */ - if (memcmp(buf, "ANAND", 6)) { - printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but went away on reread!\n", -- block * nftl->EraseSize, nftl->mtd->index); -+ block * nftl->EraseSize, nftl->mbd.mtd->index); - printk(KERN_NOTICE "New data are: %02x %02x %02x %02x %02x %02x\n", - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); - continue; -@@ -137,8 +128,12 @@ - printk(KERN_NOTICE "NFTL Media Headers at 0x%x and 0x%x disagree.\n", - nftl->MediaUnit * nftl->EraseSize, block * nftl->EraseSize); - /* if (debug) Print both side by side */ -+ if (boot_record_count < 2) { -+ /* We haven't yet seen two real ones */ - return -1; - } -+ continue; -+ } - if (boot_record_count == 1) - nftl->SpareMediaUnit = block; - -@@ -163,8 +158,8 @@ - } else if (mh->UnitSizeFactor != 0xff) { - printk(KERN_NOTICE "WARNING: Support for NFTL with UnitSizeFactor 0x%02x is experimental\n", - mh->UnitSizeFactor); -- nftl->EraseSize = nftl->mtd->erasesize << (0xff - mh->UnitSizeFactor); -- nftl->nb_blocks = nftl->mtd->size / nftl->EraseSize; -+ nftl->EraseSize = nftl->mbd.mtd->erasesize << (0xff - mh->UnitSizeFactor); -+ nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize; - } - nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN); - if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) { -@@ -182,7 +177,7 @@ - return -1; - } - -- nftl->nr_sects = nftl->numvunits * (nftl->EraseSize / SECTORSIZE); -+ nftl->mbd.size = nftl->numvunits * (nftl->EraseSize / SECTORSIZE); - - /* If we're not using the last sectors in the device for some reason, - reduce nb_blocks accordingly so we forget they're there */ -@@ -220,7 +215,7 @@ - for (i = 0; i < nftl->nb_blocks; i++) { - if ((i & (SECTORSIZE - 1)) == 0) { - /* read one sector for every SECTORSIZE of blocks */ -- if ((ret = MTD_READECC(nftl->mtd, block * nftl->EraseSize + -+ if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize + - i + SECTORSIZE, SECTORSIZE, &retlen, buf, - (char *)&oob, NAND_ECC_DISKONCHIP)) < 0) { - printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n", -@@ -263,16 +258,16 @@ - for (i = 0; i < len; i += SECTORSIZE) { - /* we want to read the sector without ECC check here since a free - sector does not have ECC syndrome on it yet */ -- if (MTD_READ(nftl->mtd, address, SECTORSIZE, &retlen, buf) < 0) -+ if (MTD_READ(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf) < 0) - return -1; - if (memcmpb(buf, 0xff, SECTORSIZE) != 0) - return -1; - - if (check_oob) { -- if (MTD_READOOB(nftl->mtd, address, nftl->mtd->oobsize, -+ if (MTD_READOOB(nftl->mbd.mtd, address, nftl->mbd.mtd->oobsize, - &retlen, buf) < 0) - return -1; -- if (memcmpb(buf, 0xff, nftl->mtd->oobsize) != 0) -+ if (memcmpb(buf, 0xff, nftl->mbd.mtd->oobsize) != 0) - return -1; - } - address += SECTORSIZE; -@@ -297,7 +292,7 @@ - struct erase_info *instr = &nftl->instr; - - /* Read the Unit Control Information #1 for Wear-Leveling */ -- if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, -+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, - 8, &retlen, (char *)&uci) < 0) - goto default_uci1; - -@@ -314,7 +309,7 @@ - /* XXX: use async erase interface, XXX: test return code */ - instr->addr = block * nftl->EraseSize; - instr->len = nftl->EraseSize; -- MTD_ERASE(nftl->mtd, instr); -+ MTD_ERASE(nftl->mbd.mtd, instr); - - if (instr->state == MTD_ERASE_FAILED) { - /* could not format, FixMe: We should update the BadUnitTable -@@ -337,7 +332,7 @@ - return -1; - - uci.WearInfo = le32_to_cpu(nb_erases); -- if (MTD_WRITEOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, -+ if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, - &retlen, (char *)&uci) < 0) - return -1; - return 0; -@@ -363,7 +358,7 @@ - block = first_block; - for (;;) { - for (i = 0; i < sectors_per_block; i++) { -- if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + i * SECTORSIZE, -+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i * SECTORSIZE, - 8, &retlen, (char *)&bci) < 0) - status = SECTOR_IGNORE; - else -@@ -383,7 +378,7 @@ - /* sector not free actually : mark it as SECTOR_IGNORE */ - bci.Status = SECTOR_IGNORE; - bci.Status1 = SECTOR_IGNORE; -- MTD_WRITEOOB(nftl->mtd, -+ MTD_WRITEOOB(nftl->mbd.mtd, - block * nftl->EraseSize + i * SECTORSIZE, - 8, &retlen, (char *)&bci); - } -@@ -476,7 +471,7 @@ - size_t retlen; - - /* check erase mark. */ -- if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, -+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, - &retlen, (char *)&h1) < 0) - return -1; - -@@ -491,7 +486,7 @@ - h1.EraseMark = cpu_to_le16(ERASE_MARK); - h1.EraseMark1 = cpu_to_le16(ERASE_MARK); - h1.WearInfo = cpu_to_le32(0); -- if (MTD_WRITEOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, -+ if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, - &retlen, (char *)&h1) < 0) - return -1; - } else { -@@ -503,7 +498,7 @@ - SECTORSIZE, 0) != 0) - return -1; - -- if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + i, -+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i, - 16, &retlen, buf) < 0) - return -1; - if (i == SECTORSIZE) { -@@ -533,7 +528,7 @@ - struct nftl_uci2 uci; - size_t retlen; - -- if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8, -+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8, - 8, &retlen, (char *)&uci) < 0) - return 0; - -@@ -572,9 +567,9 @@ - - for (;;) { - /* read the block header. If error, we format the chain */ -- if (MTD_READOOB(s->mtd, block * s->EraseSize + 8, 8, -+ if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8, - &retlen, (char *)&h0) < 0 || -- MTD_READOOB(s->mtd, block * s->EraseSize + SECTORSIZE + 8, 8, -+ MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8, - &retlen, (char *)&h1) < 0) { - s->ReplUnitTable[block] = BLOCK_NIL; - do_format_chain = 1; -diff -Nurb linux-mips-2.4.27/drivers/mtd/redboot.c linux/drivers/mtd/redboot.c ---- linux-mips-2.4.27/drivers/mtd/redboot.c 2001-12-02 12:34:42.000000000 +0100 -+++ linux/drivers/mtd/redboot.c 2004-11-19 10:25:11.656236728 +0100 -@@ -1,5 +1,5 @@ - /* -- * $Id$ -+ * $Id$ - * - * Parse RedBoot-style Flash Image System (FIS) tables and - * produce a Linux partition array to match. -@@ -7,6 +7,7 @@ - - #include - #include -+#include - - #include - #include -@@ -34,7 +35,9 @@ - return 1; - } - --int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts) -+static int parse_redboot_partitions(struct mtd_info *master, -+ struct mtd_partition **pparts, -+ unsigned long fis_origin) - { - int nrparts = 0; - struct fis_image_desc *buf; -@@ -43,7 +46,9 @@ - int ret, i; - size_t retlen; - char *names; -+ char *nullname; - int namelen = 0; -+ static char nullstring[] = "unallocated"; - - buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - -@@ -90,7 +95,11 @@ - goto out; - } - new_fl->img = &buf[i]; -+ if (fis_origin) { -+ buf[i].flash_base -= fis_origin; -+ } else { - buf[i].flash_base &= master->size-1; -+ } - - /* I'm sure the JFFS2 code has done me permanent damage. - * I now think the following is _normal_ -@@ -110,18 +119,24 @@ - if (tmp_fl->img->flash_base + tmp_fl->img->size + master->erasesize < tmp_fl->next->img->flash_base) - nrparts++; - } -- parts = kmalloc(sizeof(*parts)*nrparts + namelen, GFP_KERNEL); -+ parts = kmalloc(sizeof(*parts)*nrparts + sizeof(nullstring) + namelen, GFP_KERNEL); - - if (!parts) { - ret = -ENOMEM; - goto out; - } -- names = (char *)&parts[nrparts]; -+ - memset(parts, 0, sizeof(*parts)*nrparts + namelen); -+ -+ /* FIXME: Include nullname only if it's used */ -+ nullname = (char *)&parts[nrparts]; -+ sprintf(nullname, nullstring); -+ names = nullname + sizeof(nullstring); -+ - i=0; - - if (fl->img->flash_base) { -- parts[0].name = "unallocated space"; -+ parts[0].name = nullname; - parts[0].size = fl->img->flash_base; - parts[0].offset = 0; - } -@@ -133,11 +148,11 @@ - strcpy(names, fl->img->name); - names += strlen(names)+1; - -- if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize < fl->next->img->flash_base) { -+ if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) { - i++; - parts[i].offset = parts[i-1].size + parts[i-1].offset; - parts[i].size = fl->next->img->flash_base - parts[i].offset; -- parts[i].name = "unallocated space"; -+ parts[i].name = nullname; - } - tmp_fl = fl; - fl = fl->next; -@@ -155,7 +170,24 @@ - return ret; - } - --EXPORT_SYMBOL(parse_redboot_partitions); -+static struct mtd_part_parser redboot_parser = { -+ .owner = THIS_MODULE, -+ .parse_fn = parse_redboot_partitions, -+ .name = "RedBoot", -+}; -+ -+static int __init redboot_parser_init(void) -+{ -+ return register_mtd_parser(&redboot_parser); -+} -+ -+static void __exit redboot_parser_exit(void) -+{ -+ deregister_mtd_parser(&redboot_parser); -+} -+ -+module_init(redboot_parser_init); -+module_exit(redboot_parser_exit); - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Red Hat, Inc. - David Woodhouse "); -diff -Nurb linux-mips-2.4.27/fs/Config.in linux/fs/Config.in ---- linux-mips-2.4.27/fs/Config.in 2004-02-20 02:22:19.000000000 +0100 -+++ linux/fs/Config.in 2004-11-19 10:25:12.229149632 +0100 -@@ -49,6 +49,7 @@ - dep_tristate 'Journalling Flash File System v2 (JFFS2) support' CONFIG_JFFS2_FS $CONFIG_MTD - if [ "$CONFIG_JFFS2_FS" = "y" -o "$CONFIG_JFFS2_FS" = "m" ] ; then - int 'JFFS2 debugging verbosity (0 = quiet, 2 = noisy)' CONFIG_JFFS2_FS_DEBUG 0 -+ bool 'JFFS2 support for NAND chips' CONFIG_JFFS2_FS_NAND - fi - tristate 'Compressed ROM file system support' CONFIG_CRAMFS - bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS -diff -Nurb linux-mips-2.4.27/fs/jffs2/Makefile linux/fs/jffs2/Makefile ---- linux-mips-2.4.27/fs/jffs2/Makefile 2003-08-13 19:19:25.000000000 +0200 -+++ linux/fs/jffs2/Makefile 2004-11-19 10:25:12.071173648 +0100 -@@ -1,7 +1,7 @@ - # - # Makefile for the linux Journalling Flash FileSystem (JFFS) routines. - # --# $Id$ -+# $Id$ - # - # Note! Dependencies are done automagically by 'make dep', which also - # removes any old dependencies. DON'T put your own dependencies here -@@ -10,16 +10,31 @@ - # Note 2! The CFLAGS definitions are now in the main makefile... - - --COMPR_OBJS := compr.o compr_rubin.o compr_rtime.o pushpull.o \ -- compr_zlib.o -+obj-$(CONFIG_JFFS2_FS) := jffs2.o -+ -+COMPR_OBJS := compr.o compr_rubin.o compr_rtime.o compr_zlib.o - JFFS2_OBJS := dir.o file.o ioctl.o nodelist.o malloc.o \ -- read.o nodemgmt.o readinode.o super.o write.o scan.o gc.o \ -- symlink.o build.o erase.o background.o -+ read.o nodemgmt.o readinode.o write.o scan.o gc.o \ -+ symlink.o build.o erase.o background.o fs.o writev.o - --O_TARGET := jffs2.o -+BELOW25 := $(shell echo $(PATCHLEVEL) | sed s/[1234]/y/) -+ -+ifeq ($(BELOW25),y) -+LINUX_OBJS := super-v24.o crc32.o rbtree.o -+else -+LINUX_OBJS := super.o -+endif - --obj-y := $(COMPR_OBJS) $(JFFS2_OBJS) --obj-m := $(O_TARGET) -+NAND_OBJS-$(CONFIG_JFFS2_FS_NAND) := wbuf.o - -+jffs2-objs := $(COMPR_OBJS) $(JFFS2_OBJS) $(VERS_OBJS) $(NAND_OBJS-y) \ -+ $(LINUX_OBJS) -+ -+ -+# 2.4 build compatibility -+ifeq ($(BELOW25),y) -+obj-y := $(jffs2-objs) -+O_TARGET := jffs2.o - include $(TOPDIR)/Rules.make -+endif - -diff -Nurb linux-mips-2.4.27/fs/jffs2/background.c linux/fs/jffs2/background.c ---- linux-mips-2.4.27/fs/jffs2/background.c 2001-11-06 08:56:10.000000000 +0100 -+++ linux/fs/jffs2/background.c 2004-11-19 10:25:12.072173496 +0100 -@@ -1,61 +1,36 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #define __KERNEL_SYSCALLS__ - - #include --#include --#include - #include - #include --#include - #include -+#include -+#include -+#include - #include "nodelist.h" - - - static int jffs2_garbage_collect_thread(void *); --static int thread_should_wake(struct jffs2_sb_info *c); - - void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c) - { -- spin_lock_bh(&c->erase_completion_lock); -- if (c->gc_task && thread_should_wake(c)) -+ spin_lock(&c->erase_completion_lock); -+ if (c->gc_task && jffs2_thread_should_wake(c)) - send_sig(SIGHUP, c->gc_task, 1); -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - } - - /* This must only ever be called when no GC thread is currently running */ -@@ -86,12 +61,12 @@ - - void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c) - { -- spin_lock_bh(&c->erase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - if (c->gc_task) { - D1(printk(KERN_DEBUG "jffs2: Killing GC task %d\n", c->gc_task->pid)); - send_sig(SIGKILL, c->gc_task, 1); - } -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - wait_for_completion(&c->gc_thread_exit); - } - -@@ -99,34 +74,37 @@ - { - struct jffs2_sb_info *c = _c; - -- daemonize(); -- current->tty = NULL; -+ daemonize("jffs2_gcd_mtd%d", c->mtd->index); -+ allow_signal(SIGKILL); -+ allow_signal(SIGSTOP); -+ allow_signal(SIGCONT); -+ - c->gc_task = current; - up(&c->gc_thread_start); - -- sprintf(current->comm, "jffs2_gcd_mtd%d", c->mtd->index); -- -- /* FIXME in the 2.2 backport */ -- current->nice = 10; -+ set_user_nice(current, 10); - - for (;;) { -- spin_lock_irq(¤t->sigmask_lock); -- siginitsetinv (¤t->blocked, sigmask(SIGHUP) | sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT)); -- recalc_sigpending(current); -- spin_unlock_irq(¤t->sigmask_lock); -+ allow_signal(SIGHUP); - -- if (!thread_should_wake(c)) { -+ if (!jffs2_thread_should_wake(c)) { - set_current_state (TASK_INTERRUPTIBLE); - D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n")); -- /* Yes, there's a race here; we checked thread_should_wake() before -- setting current->state to TASK_INTERRUPTIBLE. But it doesn't -+ /* Yes, there's a race here; we checked jffs2_thread_should_wake() -+ before setting current->state to TASK_INTERRUPTIBLE. But it doesn't - matter - We don't care if we miss a wakeup, because the GC thread - is only an optimisation anyway. */ - schedule(); - } - -- if (current->need_resched) -- schedule(); -+ if (current->flags & PF_FREEZE) { -+ refrigerator(0); -+ /* refrigerator() should recalc sigpending for us -+ but doesn't. No matter - allow_signal() will. */ -+ continue; -+ } -+ -+ cond_resched(); - - /* Put_super will send a SIGKILL and then wait on the sem. - */ -@@ -134,9 +112,7 @@ - siginfo_t info; - unsigned long signr; - -- spin_lock_irq(¤t->sigmask_lock); -- signr = dequeue_signal(¤t->blocked, &info); -- spin_unlock_irq(¤t->sigmask_lock); -+ signr = dequeue_signal_lock(current, ¤t->blocked, &info); - - switch(signr) { - case SIGSTOP: -@@ -147,9 +123,10 @@ - - case SIGKILL: - D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGKILL received.\n")); -- spin_lock_bh(&c->erase_completion_lock); -+ die: -+ spin_lock(&c->erase_completion_lock); - c->gc_task = NULL; -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - complete_and_exit(&c->gc_thread_exit, 0); - - case SIGHUP: -@@ -157,27 +134,15 @@ - break; - default: - D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): signal %ld received\n", signr)); -- - } - } - /* We don't want SIGHUP to interrupt us. STOP and KILL are OK though. */ -- spin_lock_irq(¤t->sigmask_lock); -- siginitsetinv (¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT)); -- recalc_sigpending(current); -- spin_unlock_irq(¤t->sigmask_lock); -+ disallow_signal(SIGHUP); - - D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): pass\n")); -- jffs2_garbage_collect_pass(c); -+ if (jffs2_garbage_collect_pass(c) == -ENOSPC) { -+ printk(KERN_NOTICE "No space for garbage collection. Aborting GC thread\n"); -+ goto die; -+ } - } --} -- --static int thread_should_wake(struct jffs2_sb_info *c) --{ -- D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x\n", -- c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size)); -- if (c->nr_free_blocks + c->nr_erasing_blocks < JFFS2_RESERVED_BLOCKS_GCTRIGGER && -- c->dirty_size > c->sector_size) -- return 1; -- else -- return 0; - } -diff -Nurb linux-mips-2.4.27/fs/jffs2/build.c linux/fs/jffs2/build.c ---- linux-mips-2.4.27/fs/jffs2/build.c 2003-07-05 05:23:44.000000000 +0200 -+++ linux/fs/jffs2/build.c 2004-11-19 10:25:12.073173344 +0100 -@@ -1,47 +1,22 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include --#include -+#include - #include - #include "nodelist.h" - --int jffs2_build_inode_pass1(struct jffs2_sb_info *, struct jffs2_inode_cache *); --int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, struct jffs2_inode_cache *); -+static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, struct jffs2_inode_cache *, struct jffs2_full_dirent **); - - static inline struct jffs2_inode_cache * - first_inode_chain(int *i, struct jffs2_sb_info *c) -@@ -68,16 +43,52 @@ - ic; \ - ic = next_inode(&i, ic, (c))) - -+ -+static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) -+{ -+ struct jffs2_full_dirent *fd; -+ -+ D1(printk(KERN_DEBUG "jffs2_build_inode building directory inode #%u\n", ic->ino)); -+ -+ /* For each child, increase nlink */ -+ for(fd = ic->scan_dents; fd; fd = fd->next) { -+ struct jffs2_inode_cache *child_ic; -+ if (!fd->ino) -+ continue; -+ -+ /* XXX: Can get high latency here with huge directories */ -+ -+ child_ic = jffs2_get_ino_cache(c, fd->ino); -+ if (!child_ic) { -+ printk(KERN_NOTICE "Eep. Child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n", -+ fd->name, fd->ino, ic->ino); -+ continue; -+ } -+ -+ if (child_ic->nlink++ && fd->type == DT_DIR) { -+ printk(KERN_NOTICE "Child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", fd->name, fd->ino, ic->ino); -+ if (fd->ino == 1 && ic->ino == 1) { -+ printk(KERN_NOTICE "This is mostly harmless, and probably caused by creating a JFFS2 image\n"); -+ printk(KERN_NOTICE "using a buggy version of mkfs.jffs2. Use at least v1.17.\n"); -+ } -+ /* What do we do about it? */ -+ } -+ D1(printk(KERN_DEBUG "Increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino)); -+ /* Can't free them. We might need them in pass 2 */ -+ } -+} -+ - /* Scan plan: - - Scan physical nodes. Build map of inodes/dirents. Allocate inocaches as we go - - Scan directory tree from top down, setting nlink in inocaches - - Scan inocaches for inodes with nlink==0 - */ --int jffs2_build_filesystem(struct jffs2_sb_info *c) -+static int jffs2_build_filesystem(struct jffs2_sb_info *c) - { - int ret; - int i; - struct jffs2_inode_cache *ic; -+ struct jffs2_full_dirent *dead_fds = NULL; - - /* First, scan the medium and build all the inode caches with - lists of physical nodes */ -@@ -90,14 +101,17 @@ - return ret; - - D1(printk(KERN_DEBUG "Scanned flash completely\n")); -- /* Now build the data map for each inode, marking obsoleted nodes -- as such, and also increase nlink of any children. */ -+ D1(jffs2_dump_block_lists(c)); -+ -+ /* Now scan the directory tree, increasing nlink according to every dirent found. */ - for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 1: ino #%u\n", ic->ino)); -- ret = jffs2_build_inode_pass1(c, ic); -- if (ret) { -- D1(printk(KERN_WARNING "Eep. jffs2_build_inode_pass1 for ino %d returned %d\n", ic->ino, ret)); -- return ret; -+ -+ D1(BUG_ON(ic->ino > c->highest_ino)); -+ -+ if (ic->scan_dents) { -+ jffs2_build_inode_pass1(c, ic); -+ cond_resched(); - } - } - D1(printk(KERN_DEBUG "Pass 1 complete\n")); -@@ -107,181 +121,226 @@ - children too, and repeat the scan. As that's going to be - a fairly uncommon occurrence, it's not so evil to do it this - way. Recursion bad. */ -- do { -- D1(printk(KERN_DEBUG "Pass 2 (re)starting\n")); -- ret = 0; -+ D1(printk(KERN_DEBUG "Pass 2 starting\n")); -+ - for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 2: ino #%u, nlink %d, ic %p, nodes %p\n", ic->ino, ic->nlink, ic, ic->nodes)); - if (ic->nlink) - continue; - -- ret = jffs2_build_remove_unlinked_inode(c, ic); -- if (ret) -- break; -- /* -EAGAIN means the inode's nlink was zero, so we deleted it, -- and furthermore that it had children and their nlink has now -- gone to zero too. So we have to restart the scan. */ -+ jffs2_build_remove_unlinked_inode(c, ic, &dead_fds); -+ cond_resched(); -+ } -+ -+ D1(printk(KERN_DEBUG "Pass 2a starting\n")); -+ -+ while (dead_fds) { -+ struct jffs2_inode_cache *ic; -+ struct jffs2_full_dirent *fd = dead_fds; -+ -+ dead_fds = fd->next; -+ -+ ic = jffs2_get_ino_cache(c, fd->ino); -+ D1(printk(KERN_DEBUG "Removing dead_fd ino #%u (\"%s\"), ic at %p\n", fd->ino, fd->name, ic)); -+ -+ if (ic) -+ jffs2_build_remove_unlinked_inode(c, ic, &dead_fds); -+ jffs2_free_full_dirent(fd); - } -- } while(ret == -EAGAIN); - - D1(printk(KERN_DEBUG "Pass 2 complete\n")); - -- /* Finally, we can scan again and free the dirent nodes and scan_info structs */ -+ /* Finally, we can scan again and free the dirent structs */ - for_each_inode(i, c, ic) { -- struct jffs2_scan_info *scan = ic->scan; - struct jffs2_full_dirent *fd; - D1(printk(KERN_DEBUG "Pass 3: ino #%u, ic %p, nodes %p\n", ic->ino, ic, ic->nodes)); -- if (!scan) { -- if (ic->nlink) { -- D1(printk(KERN_WARNING "Why no scan struct for ino #%u which has nlink %d?\n", ic->ino, ic->nlink)); -- } -- continue; -- } -- ic->scan = NULL; -- while(scan->dents) { -- fd = scan->dents; -- scan->dents = fd->next; -+ -+ while(ic->scan_dents) { -+ fd = ic->scan_dents; -+ ic->scan_dents = fd->next; - jffs2_free_full_dirent(fd); - } -- kfree(scan); -+ ic->scan_dents = NULL; -+ cond_resched(); - } - D1(printk(KERN_DEBUG "Pass 3 complete\n")); -+ D1(jffs2_dump_block_lists(c)); -+ -+ /* Rotate the lists by some number to ensure wear levelling */ -+ jffs2_rotate_lists(c); - - return ret; - } - --int jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) -+static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, struct jffs2_full_dirent **dead_fds) - { -- struct jffs2_tmp_dnode_info *tn; -+ struct jffs2_raw_node_ref *raw; - struct jffs2_full_dirent *fd; -- struct jffs2_node_frag *fraglist = NULL; -- struct jffs2_tmp_dnode_info *metadata = NULL; -- -- D1(printk(KERN_DEBUG "jffs2_build_inode building inode #%u\n", ic->ino)); -- if (ic->ino > c->highest_ino) -- c->highest_ino = ic->ino; - -- if (!ic->scan->tmpnodes && ic->ino != 1) { -- D1(printk(KERN_DEBUG "jffs2_build_inode: ino #%u has no data nodes!\n", ic->ino)); -- } -- /* Build the list to make sure any obsolete nodes are marked as such */ -- while(ic->scan->tmpnodes) { -- tn = ic->scan->tmpnodes; -- ic->scan->tmpnodes = tn->next; -- -- if (metadata && tn->version > metadata->version) { -- D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 ignoring old metadata at 0x%08x\n", -- metadata->fn->raw->flash_offset &~3)); -+ D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino)); - -- jffs2_free_full_dnode(metadata->fn); -- jffs2_free_tmp_dnode_info(metadata); -- metadata = NULL; -+ for (raw = ic->nodes; raw != (void *)ic; raw = raw->next_in_ino) { -+ D1(printk(KERN_DEBUG "obsoleting node at 0x%08x\n", ref_offset(raw))); -+ jffs2_mark_node_obsolete(c, raw); - } - -- if (tn->fn->size) { -- jffs2_add_full_dnode_to_fraglist (c, &fraglist, tn->fn); -- jffs2_free_tmp_dnode_info(tn); -- } else { -- if (!metadata) { -- metadata = tn; -- } else { -- D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 ignoring new metadata at 0x%08x\n", -- tn->fn->raw->flash_offset &~3)); -- -- jffs2_free_full_dnode(tn->fn); -- jffs2_free_tmp_dnode_info(tn); -- } -- } -- } -+ if (ic->scan_dents) { -+ int whinged = 0; -+ D1(printk(KERN_DEBUG "Inode #%u was a directory which may have children...\n", ic->ino)); - -- /* OK. Now clear up */ -- if (metadata) { -- jffs2_free_full_dnode(metadata->fn); -- jffs2_free_tmp_dnode_info(metadata); -- } -- metadata = NULL; -+ while(ic->scan_dents) { -+ struct jffs2_inode_cache *child_ic; - -- while (fraglist) { -- struct jffs2_node_frag *frag; -- frag = fraglist; -- fraglist = fraglist->next; -+ fd = ic->scan_dents; -+ ic->scan_dents = fd->next; - -- if (frag->node && !(--frag->node->frags)) { -- jffs2_free_full_dnode(frag->node); -+ if (!fd->ino) { -+ /* It's a deletion dirent. Ignore it */ -+ D1(printk(KERN_DEBUG "Child \"%s\" is a deletion dirent, skipping...\n", fd->name)); -+ jffs2_free_full_dirent(fd); -+ continue; - } -- jffs2_free_node_frag(frag); -+ if (!whinged) { -+ whinged = 1; -+ printk(KERN_NOTICE "Inode #%u was a directory with children - removing those too...\n", ic->ino); - } - -- /* Now for each child, increase nlink */ -- for(fd=ic->scan->dents; fd; fd = fd->next) { -- struct jffs2_inode_cache *child_ic; -- if (!fd->ino) -- continue; -+ D1(printk(KERN_DEBUG "Removing child \"%s\", ino #%u\n", -+ fd->name, fd->ino)); - - child_ic = jffs2_get_ino_cache(c, fd->ino); - if (!child_ic) { -- printk(KERN_NOTICE "Eep. Child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n", -- fd->name, fd->ino, ic->ino); -+ printk(KERN_NOTICE "Cannot remove child \"%s\", ino #%u, because it doesn't exist\n", fd->name, fd->ino); -+ jffs2_free_full_dirent(fd); - continue; - } - -- if (child_ic->nlink++ && fd->type == DT_DIR) { -- printk(KERN_NOTICE "Child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", fd->name, fd->ino, ic->ino); -- if (fd->ino == 1 && ic->ino == 1) { -- printk(KERN_NOTICE "This is mostly harmless, and probably caused by creating a JFFS2 image\n"); -- printk(KERN_NOTICE "using a buggy version of mkfs.jffs2. Use at least v1.17.\n"); -+ /* Reduce nlink of the child. If it's now zero, stick it on the -+ dead_fds list to be cleaned up later. Else just free the fd */ -+ -+ child_ic->nlink--; -+ -+ if (!child_ic->nlink) { -+ D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got zero nlink. Adding to dead_fds list.\n", -+ fd->ino, fd->name)); -+ fd->next = *dead_fds; -+ *dead_fds = fd; -+ } else { -+ D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got nlink %d. Ignoring.\n", -+ fd->ino, fd->name, child_ic->nlink)); -+ jffs2_free_full_dirent(fd); - } -- /* What do we do about it? */ - } -- D1(printk(KERN_DEBUG "Increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino)); -- /* Can't free them. We might need them in pass 2 */ - } -- return 0; -+ -+ /* -+ We don't delete the inocache from the hash list and free it yet. -+ The erase code will do that, when all the nodes are completely gone. -+ */ - } - --int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) -+static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) - { -- struct jffs2_raw_node_ref *raw; -- struct jffs2_full_dirent *fd; -- int ret = 0; -+ uint32_t size; - -- if(!ic->scan) { -- D1(printk(KERN_DEBUG "ino #%u was already removed\n", ic->ino)); -- return 0; -- } -+ /* Deletion should almost _always_ be allowed. We're fairly -+ buggered once we stop allowing people to delete stuff -+ because there's not enough free space... */ -+ c->resv_blocks_deletion = 2; -+ -+ /* Be conservative about how much space we need before we allow writes. -+ On top of that which is required for deletia, require an extra 2% -+ of the medium to be available, for overhead caused by nodes being -+ split across blocks, etc. */ -+ -+ size = c->flash_size / 50; /* 2% of flash size */ -+ size += c->nr_blocks * 100; /* And 100 bytes per eraseblock */ -+ size += c->sector_size - 1; /* ... and round up */ -+ -+ c->resv_blocks_write = c->resv_blocks_deletion + (size / c->sector_size); -+ -+ /* When do we let the GC thread run in the background */ -+ -+ c->resv_blocks_gctrigger = c->resv_blocks_write + 1; -+ -+ /* When do we allow garbage collection to merge nodes to make -+ long-term progress at the expense of short-term space exhaustion? */ -+ c->resv_blocks_gcmerge = c->resv_blocks_deletion + 1; -+ -+ /* When do we allow garbage collection to eat from bad blocks rather -+ than actually making progress? */ -+ c->resv_blocks_gcbad = 0;//c->resv_blocks_deletion + 2; -+ -+ /* If there's less than this amount of dirty space, don't bother -+ trying to GC to make more space. It'll be a fruitless task */ -+ c->nospc_dirty_size = c->sector_size + (c->flash_size / 100); -+ -+ D1(printk(KERN_DEBUG "JFFS2 trigger levels (size %d KiB, block size %d KiB, %d blocks)\n", -+ c->flash_size / 1024, c->sector_size / 1024, c->nr_blocks)); -+ D1(printk(KERN_DEBUG "Blocks required to allow deletion: %d (%d KiB)\n", -+ c->resv_blocks_deletion, c->resv_blocks_deletion*c->sector_size/1024)); -+ D1(printk(KERN_DEBUG "Blocks required to allow writes: %d (%d KiB)\n", -+ c->resv_blocks_write, c->resv_blocks_write*c->sector_size/1024)); -+ D1(printk(KERN_DEBUG "Blocks required to quiesce GC thread: %d (%d KiB)\n", -+ c->resv_blocks_gctrigger, c->resv_blocks_gctrigger*c->sector_size/1024)); -+ D1(printk(KERN_DEBUG "Blocks required to allow GC merges: %d (%d KiB)\n", -+ c->resv_blocks_gcmerge, c->resv_blocks_gcmerge*c->sector_size/1024)); -+ D1(printk(KERN_DEBUG "Blocks required to GC bad blocks: %d (%d KiB)\n", -+ c->resv_blocks_gcbad, c->resv_blocks_gcbad*c->sector_size/1024)); -+ D1(printk(KERN_DEBUG "Amount of dirty space required to GC: %d bytes\n", -+ c->nospc_dirty_size)); -+} - -- D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino)); -+int jffs2_do_mount_fs(struct jffs2_sb_info *c) -+{ -+ int i; - -- for (raw = ic->nodes; raw != (void *)ic; raw = raw->next_in_ino) { -- D1(printk(KERN_DEBUG "obsoleting node at 0x%08x\n", raw->flash_offset&~3)); -- jffs2_mark_node_obsolete(c, raw); -+ c->free_size = c->flash_size; -+ c->nr_blocks = c->flash_size / c->sector_size; -+ c->blocks = kmalloc(sizeof(struct jffs2_eraseblock) * c->nr_blocks, GFP_KERNEL); -+ if (!c->blocks) -+ return -ENOMEM; -+ for (i=0; inr_blocks; i++) { -+ INIT_LIST_HEAD(&c->blocks[i].list); -+ c->blocks[i].offset = i * c->sector_size; -+ c->blocks[i].free_size = c->sector_size; -+ c->blocks[i].dirty_size = 0; -+ c->blocks[i].wasted_size = 0; -+ c->blocks[i].unchecked_size = 0; -+ c->blocks[i].used_size = 0; -+ c->blocks[i].first_node = NULL; -+ c->blocks[i].last_node = NULL; -+ } -+ -+ init_MUTEX(&c->alloc_sem); -+ init_MUTEX(&c->erase_free_sem); -+ init_waitqueue_head(&c->erase_wait); -+ init_waitqueue_head(&c->inocache_wq); -+ spin_lock_init(&c->erase_completion_lock); -+ spin_lock_init(&c->inocache_lock); -+ -+ INIT_LIST_HEAD(&c->clean_list); -+ INIT_LIST_HEAD(&c->very_dirty_list); -+ INIT_LIST_HEAD(&c->dirty_list); -+ INIT_LIST_HEAD(&c->erasable_list); -+ INIT_LIST_HEAD(&c->erasing_list); -+ INIT_LIST_HEAD(&c->erase_pending_list); -+ INIT_LIST_HEAD(&c->erasable_pending_wbuf_list); -+ INIT_LIST_HEAD(&c->erase_complete_list); -+ INIT_LIST_HEAD(&c->free_list); -+ INIT_LIST_HEAD(&c->bad_list); -+ INIT_LIST_HEAD(&c->bad_used_list); -+ c->highest_ino = 1; -+ -+ if (jffs2_build_filesystem(c)) { -+ D1(printk(KERN_DEBUG "build_fs failed\n")); -+ jffs2_free_ino_caches(c); -+ jffs2_free_raw_node_refs(c); -+ kfree(c->blocks); -+ return -EIO; - } - -- if (ic->scan->dents) { -- printk(KERN_NOTICE "Inode #%u was a directory with children - removing those too...\n", ic->ino); -- -- while(ic->scan->dents) { -- struct jffs2_inode_cache *child_ic; -+ jffs2_calc_trigger_levels(c); - -- fd = ic->scan->dents; -- ic->scan->dents = fd->next; -- -- D1(printk(KERN_DEBUG "Removing child \"%s\", ino #%u\n", -- fd->name, fd->ino)); -- -- child_ic = jffs2_get_ino_cache(c, fd->ino); -- if (!child_ic) { -- printk(KERN_NOTICE "Cannot remove child \"%s\", ino #%u, because it doesn't exist\n", fd->name, fd->ino); -- continue; -- } -- jffs2_free_full_dirent(fd); -- child_ic->nlink--; -- } -- ret = -EAGAIN; -- } -- kfree(ic->scan); -- ic->scan = NULL; -- // jffs2_del_ino_cache(c, ic); -- // jffs2_free_inode_cache(ic); -- return ret; -+ return 0; - } -diff -Nurb linux-mips-2.4.27/fs/jffs2/compr.c linux/fs/jffs2/compr.c ---- linux-mips-2.4.27/fs/jffs2/compr.c 2001-11-05 21:16:18.000000000 +0100 -+++ linux/fs/jffs2/compr.c 2004-11-19 10:25:12.085171520 +0100 -@@ -1,59 +1,37 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by Arjan van de Ven - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include - #include --#include - #include -+#include -+#include - #include -+#include "nodelist.h" - --int zlib_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 *sourcelen, __u32 *dstlen); --void zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, __u32 srclen, __u32 destlen); --int rtime_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 *sourcelen, __u32 *dstlen); --void rtime_decompress(unsigned char *data_in, unsigned char *cpage_out, __u32 srclen, __u32 destlen); --int rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 *sourcelen, __u32 *dstlen); --void rubinmips_decompress(unsigned char *data_in, unsigned char *cpage_out, __u32 srclen, __u32 destlen); --int dynrubin_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 *sourcelen, __u32 *dstlen); --void dynrubin_decompress(unsigned char *data_in, unsigned char *cpage_out, __u32 srclen, __u32 destlen); -+int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen); -+void jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, uint32_t srclen, uint32_t destlen); -+int jffs2_rtime_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen); -+void jffs2_rtime_decompress(unsigned char *data_in, unsigned char *cpage_out, uint32_t srclen, uint32_t destlen); -+int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen); -+void jffs2_rubinmips_decompress(unsigned char *data_in, unsigned char *cpage_out, uint32_t srclen, uint32_t destlen); -+int jffs2_dynrubin_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen); -+void jffs2_dynrubin_decompress(unsigned char *data_in, unsigned char *cpage_out, uint32_t srclen, uint32_t destlen); - - - /* jffs2_compress: - * @data: Pointer to uncompressed data -- * @cdata: Pointer to buffer for compressed data -+ * @cdata: Pointer to returned pointer to buffer for compressed data - * @datalen: On entry, holds the amount of data available for compression. - * On exit, expected to hold the amount of data actually compressed. - * @cdatalen: On entry, holds the amount of space available for compressed -@@ -68,47 +46,59 @@ - * jffs2_compress should compress as much as will fit, and should set - * *datalen accordingly to show the amount of data which were compressed. - */ --unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 *datalen, __u32 *cdatalen) -+unsigned char jffs2_compress(unsigned char *data_in, unsigned char **cpage_out, -+ uint32_t *datalen, uint32_t *cdatalen) - { -+#ifdef JFFS2_COMPRESSION - int ret; - -- ret = zlib_compress(data_in, cpage_out, datalen, cdatalen); -+ *cpage_out = kmalloc(*cdatalen, GFP_KERNEL); -+ if (!*cpage_out) { -+ printk(KERN_WARNING "No memory for compressor allocation. Compression failed\n"); -+ goto out; -+ } -+ -+#ifdef JFFS2_USE_ZLIB -+ ret = jffs2_zlib_compress(data_in, *cpage_out, datalen, cdatalen); - if (!ret) { - return JFFS2_COMPR_ZLIB; - } --#if 0 /* Disabled 23/9/1. With zlib it hardly ever gets a look in */ -- ret = dynrubin_compress(data_in, cpage_out, datalen, cdatalen); -+#endif -+#ifdef JFFS2_USE_DYNRUBIN -+ ret = jffs2_dynrubin_compress(data_in, *cpage_out, datalen, cdatalen); - if (!ret) { - return JFFS2_COMPR_DYNRUBIN; - } - #endif --#if 0 /* Disabled 26/2/1. Obsoleted by dynrubin */ -- ret = rubinmips_compress(data_in, cpage_out, datalen, cdatalen); -+#ifdef JFFS2_USE_RUBINMIPS -+ ret = jffs2_rubinmips_compress(data_in, *cpage_out, datalen, cdatalen); - if (!ret) { - return JFFS2_COMPR_RUBINMIPS; - } - #endif -+#ifdef JFFS2_USE_RTIME - /* rtime does manage to recompress already-compressed data */ -- ret = rtime_compress(data_in, cpage_out, datalen, cdatalen); -+ ret = jffs2_rtime_compress(data_in, *cpage_out, datalen, cdatalen); - if (!ret) { - return JFFS2_COMPR_RTIME; - } --#if 0 -- /* We don't need to copy. Let the caller special-case the COMPR_NONE case. */ -- /* If we get here, no compression is going to work */ -- /* But we might want to use the fragmentation part -- Arjan */ -- memcpy(cpage_out,data_in,min(*datalen,*cdatalen)); -- if (*datalen > *cdatalen) -- *datalen = *cdatalen; - #endif -+ kfree(*cpage_out); -+#endif /* Compression */ -+ out: -+ *cpage_out = data_in; -+ *datalen = *cdatalen; - return JFFS2_COMPR_NONE; /* We failed to compress */ -- - } - -+void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig) -+{ -+ if (orig != comprbuf) -+ kfree(comprbuf); -+} - - int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, -- unsigned char *data_out, __u32 cdatalen, __u32 datalen) -+ unsigned char *data_out, uint32_t cdatalen, uint32_t datalen) - { - switch (comprtype) { - case JFFS2_COMPR_NONE: -@@ -119,30 +109,27 @@ - case JFFS2_COMPR_ZERO: - memset(data_out, 0, datalen); - break; -- -+#ifdef JFFS2_USE_ZLIB - case JFFS2_COMPR_ZLIB: -- zlib_decompress(cdata_in, data_out, cdatalen, datalen); -+ jffs2_zlib_decompress(cdata_in, data_out, cdatalen, datalen); - break; -- -+#endif -+#ifdef JFFS2_USE_RTIME - case JFFS2_COMPR_RTIME: -- rtime_decompress(cdata_in, data_out, cdatalen, datalen); -+ jffs2_rtime_decompress(cdata_in, data_out, cdatalen, datalen); - break; -- -- case JFFS2_COMPR_RUBINMIPS: --#if 0 /* Disabled 23/9/1 */ -- rubinmips_decompress(cdata_in, data_out, cdatalen, datalen); --#else -- printk(KERN_WARNING "JFFS2: Rubinmips compression encountered but support not compiled in!\n"); - #endif -+#ifdef JFFS2_USE_RUBINMIPS -+ case JFFS2_COMPR_RUBINMIPS: -+ jffs2_rubinmips_decompress(cdata_in, data_out, cdatalen, datalen); - break; -- case JFFS2_COMPR_DYNRUBIN: --#if 1 /* Phase this one out */ -- dynrubin_decompress(cdata_in, data_out, cdatalen, datalen); --#else -- printk(KERN_WARNING "JFFS2: Dynrubin compression encountered but support not compiled in!\n"); - #endif -- break; -+#ifdef JFFS2_USE_DYNRUBIN -+ case JFFS2_COMPR_DYNRUBIN: - -+ jffs2_dynrubin_decompress(cdata_in, data_out, cdatalen, datalen); -+ break; -+#endif - default: - printk(KERN_NOTICE "Unknown JFFS2 compression type 0x%02x\n", comprtype); - return -EIO; -diff -Nurb linux-mips-2.4.27/fs/jffs2/compr_rtime.c linux/fs/jffs2/compr_rtime.c ---- linux-mips-2.4.27/fs/jffs2/compr_rtime.c 2001-10-19 03:24:56.000000000 +0200 -+++ linux/fs/jffs2/compr_rtime.c 2004-11-19 10:25:12.087171216 +0100 -@@ -1,43 +1,19 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by Arjan van de Ven - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - * - * Very simple lz77-ish encoder. - * - * Theory of operation: Both encoder and decoder have a list of "last -- * occurances" for every possible source-value; after sending the -+ * occurrences" for every possible source-value; after sending the - * first source-byte, the second byte indicated the "run" length of - * matches - * -@@ -51,10 +27,10 @@ - #include - - /* _compress returns the compressed size, -1 if bigger */ --int rtime_compress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 *sourcelen, __u32 *dstlen) -+int jffs2_rtime_compress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t *sourcelen, uint32_t *dstlen) - { -- int positions[256]; -+ short positions[256]; - int outpos = 0; - int pos=0; - -@@ -91,10 +67,10 @@ - } - - --void rtime_decompress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 srclen, __u32 destlen) -+void jffs2_rtime_decompress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t srclen, uint32_t destlen) - { -- int positions[256]; -+ short positions[256]; - int outpos = 0; - int pos=0; - -diff -Nurb linux-mips-2.4.27/fs/jffs2/compr_rubin.c linux/fs/jffs2/compr_rubin.c ---- linux-mips-2.4.27/fs/jffs2/compr_rubin.c 2001-11-05 21:16:18.000000000 +0100 -+++ linux/fs/jffs2/compr_rubin.c 2004-11-19 10:25:12.088171064 +0100 -@@ -1,37 +1,13 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001, 2002 Red Hat, Inc. - * - * Created by Arjan van de Ven - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - -@@ -43,7 +19,7 @@ - - - --void init_rubin(struct rubin_state *rs, int div, int *bits) -+static void init_rubin(struct rubin_state *rs, int div, int *bits) - { - int c; - -@@ -56,7 +32,7 @@ - } - - --int encode(struct rubin_state *rs, long A, long B, int symbol) -+static int encode(struct rubin_state *rs, long A, long B, int symbol) - { - - long i0, i1; -@@ -91,7 +67,7 @@ - } - - --void end_rubin(struct rubin_state *rs) -+static void end_rubin(struct rubin_state *rs) - { - - int i; -@@ -104,7 +80,7 @@ - } - - --void init_decode(struct rubin_state *rs, int div, int *bits) -+static void init_decode(struct rubin_state *rs, int div, int *bits) - { - init_rubin(rs, div, bits); - -@@ -151,7 +127,7 @@ - rs->rec_q = rec_q; - } - --int decode(struct rubin_state *rs, long A, long B) -+static int decode(struct rubin_state *rs, long A, long B) - { - unsigned long p = rs->p, q = rs->q; - long i0, threshold; -@@ -212,8 +188,8 @@ - - - --int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, -- unsigned char *cpage_out, __u32 *sourcelen, __u32 *dstlen) -+static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, -+ unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen) - { - int outpos = 0; - int pos=0; -@@ -246,20 +222,20 @@ - } - #if 0 - /* _compress returns the compressed size, -1 if bigger */ --int rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 *sourcelen, __u32 *dstlen) -+int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t *sourcelen, uint32_t *dstlen) - { - return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen); - } - #endif --int dynrubin_compress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 *sourcelen, __u32 *dstlen) -+int jffs2_dynrubin_compress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t *sourcelen, uint32_t *dstlen) - { - int bits[8]; - unsigned char histo[256]; - int i; - int ret; -- __u32 mysrclen, mydstlen; -+ uint32_t mysrclen, mydstlen; - - mysrclen = *sourcelen; - mydstlen = *dstlen - 8; -@@ -315,8 +291,8 @@ - return 0; - } - --void rubin_do_decompress(int bit_divider, int *bits, unsigned char *cdata_in, -- unsigned char *page_out, __u32 srclen, __u32 destlen) -+static void rubin_do_decompress(int bit_divider, int *bits, unsigned char *cdata_in, -+ unsigned char *page_out, uint32_t srclen, uint32_t destlen) - { - int outpos = 0; - struct rubin_state rs; -@@ -330,14 +306,14 @@ - } - - --void rubinmips_decompress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 sourcelen, __u32 dstlen) -+void jffs2_rubinmips_decompress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t sourcelen, uint32_t dstlen) - { - rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen); - } - --void dynrubin_decompress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 sourcelen, __u32 dstlen) -+void jffs2_dynrubin_decompress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t sourcelen, uint32_t dstlen) - { - int bits[8]; - int c; -diff -Nurb linux-mips-2.4.27/fs/jffs2/compr_rubin.h linux/fs/jffs2/compr_rubin.h ---- linux-mips-2.4.27/fs/jffs2/compr_rubin.h 2001-10-19 03:24:56.000000000 +0200 -+++ linux/fs/jffs2/compr_rubin.h 2004-11-19 10:25:12.090170760 +0100 -@@ -1,7 +1,7 @@ - /* Rubin encoder/decoder header */ - /* work started at : aug 3, 1994 */ - /* last modification : aug 15, 1994 */ --/* $Id$ */ -+/* $Id$ */ - - #include "pushpull.h" - -@@ -19,10 +19,3 @@ - int bit_divider; - int bits[8]; - }; -- -- --void init_rubin (struct rubin_state *rs, int div, int *bits); --int encode (struct rubin_state *, long, long, int); --void end_rubin (struct rubin_state *); --void init_decode (struct rubin_state *, int div, int *bits); --int decode (struct rubin_state *, long, long); -diff -Nurb linux-mips-2.4.27/fs/jffs2/compr_zlib.c linux/fs/jffs2/compr_zlib.c ---- linux-mips-2.4.27/fs/jffs2/compr_zlib.c 2003-01-11 18:53:17.000000000 +0100 -+++ linux/fs/jffs2/compr_zlib.c 2004-11-19 10:25:12.091170608 +0100 -@@ -1,50 +1,26 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001, 2002 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - --#ifndef __KERNEL__ -+#if !defined(__KERNEL__) && !defined(__ECOS) - #error "The userspace support got too messy and was removed. Update your mkfs.jffs2" - #endif - - #include - #include --#include /* for min() */ - #include --#include - #include -+#include -+#include - #include "nodelist.h" - - /* Plan: call deflate() with avail_in == *sourcelen, -@@ -58,21 +34,24 @@ - - static DECLARE_MUTEX(deflate_sem); - static DECLARE_MUTEX(inflate_sem); --static void *deflate_workspace; --static void *inflate_workspace; -+static z_stream inf_strm, def_strm; -+ -+#ifdef __KERNEL__ /* Linux-only */ -+#include -+#include - - int __init jffs2_zlib_init(void) - { -- deflate_workspace = vmalloc(zlib_deflate_workspacesize()); -- if (!deflate_workspace) { -+ def_strm.workspace = vmalloc(zlib_deflate_workspacesize()); -+ if (!def_strm.workspace) { - printk(KERN_WARNING "Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize()); - return -ENOMEM; - } - D1(printk(KERN_DEBUG "Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize())); -- inflate_workspace = vmalloc(zlib_inflate_workspacesize()); -- if (!inflate_workspace) { -+ inf_strm.workspace = vmalloc(zlib_inflate_workspacesize()); -+ if (!inf_strm.workspace) { - printk(KERN_WARNING "Failed to allocate %d bytes for inflate workspace\n", zlib_inflate_workspacesize()); -- vfree(deflate_workspace); -+ vfree(def_strm.workspace); - return -ENOMEM; - } - D1(printk(KERN_DEBUG "Allocated %d bytes for inflate workspace\n", zlib_inflate_workspacesize())); -@@ -81,97 +60,120 @@ - - void jffs2_zlib_exit(void) - { -- vfree(deflate_workspace); -- vfree(inflate_workspace); -+ vfree(def_strm.workspace); -+ vfree(inf_strm.workspace); - } -+#endif /* __KERNEL__ */ - --int zlib_compress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 *sourcelen, __u32 *dstlen) -+int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t *sourcelen, uint32_t *dstlen) - { -- z_stream strm; - int ret; - - if (*dstlen <= STREAM_END_SPACE) - return -1; - - down(&deflate_sem); -- strm.workspace = deflate_workspace; - -- if (Z_OK != zlib_deflateInit(&strm, 3)) { -+ if (Z_OK != zlib_deflateInit(&def_strm, 3)) { - printk(KERN_WARNING "deflateInit failed\n"); - up(&deflate_sem); - return -1; - } - -- strm.next_in = data_in; -- strm.total_in = 0; -+ def_strm.next_in = data_in; -+ def_strm.total_in = 0; - -- strm.next_out = cpage_out; -- strm.total_out = 0; -+ def_strm.next_out = cpage_out; -+ def_strm.total_out = 0; - -- while (strm.total_out < *dstlen - STREAM_END_SPACE && strm.total_in < *sourcelen) { -- strm.avail_out = *dstlen - (strm.total_out + STREAM_END_SPACE); -- strm.avail_in = min((unsigned)(*sourcelen-strm.total_in), strm.avail_out); -+ while (def_strm.total_out < *dstlen - STREAM_END_SPACE && def_strm.total_in < *sourcelen) { -+ def_strm.avail_out = *dstlen - (def_strm.total_out + STREAM_END_SPACE); -+ def_strm.avail_in = min((unsigned)(*sourcelen-def_strm.total_in), def_strm.avail_out); - D1(printk(KERN_DEBUG "calling deflate with avail_in %d, avail_out %d\n", -- strm.avail_in, strm.avail_out)); -- ret = zlib_deflate(&strm, Z_PARTIAL_FLUSH); -+ def_strm.avail_in, def_strm.avail_out)); -+ ret = zlib_deflate(&def_strm, Z_PARTIAL_FLUSH); - D1(printk(KERN_DEBUG "deflate returned with avail_in %d, avail_out %d, total_in %ld, total_out %ld\n", -- strm.avail_in, strm.avail_out, strm.total_in, strm.total_out)); -+ def_strm.avail_in, def_strm.avail_out, def_strm.total_in, def_strm.total_out)); - if (ret != Z_OK) { - D1(printk(KERN_DEBUG "deflate in loop returned %d\n", ret)); -- zlib_deflateEnd(&strm); -+ zlib_deflateEnd(&def_strm); - up(&deflate_sem); - return -1; - } - } -- strm.avail_out += STREAM_END_SPACE; -- strm.avail_in = 0; -- ret = zlib_deflate(&strm, Z_FINISH); -- zlib_deflateEnd(&strm); -- up(&deflate_sem); -+ def_strm.avail_out += STREAM_END_SPACE; -+ def_strm.avail_in = 0; -+ ret = zlib_deflate(&def_strm, Z_FINISH); -+ zlib_deflateEnd(&def_strm); -+ - if (ret != Z_STREAM_END) { - D1(printk(KERN_DEBUG "final deflate returned %d\n", ret)); -- return -1; -+ ret = -1; -+ goto out; - } - -- D1(printk(KERN_DEBUG "zlib compressed %ld bytes into %ld\n", -- strm.total_in, strm.total_out)); -+ if (def_strm.total_out >= def_strm.total_in) { -+ D1(printk(KERN_DEBUG "zlib compressed %ld bytes into %ld; failing\n", -+ def_strm.total_in, def_strm.total_out)); -+ ret = -1; -+ goto out; -+ } - -- if (strm.total_out >= strm.total_in) -- return -1; -+ D1(printk(KERN_DEBUG "zlib compressed %ld bytes into %ld\n", -+ def_strm.total_in, def_strm.total_out)); - -- *dstlen = strm.total_out; -- *sourcelen = strm.total_in; -- return 0; -+ *dstlen = def_strm.total_out; -+ *sourcelen = def_strm.total_in; -+ ret = 0; -+ out: -+ up(&deflate_sem); -+ return ret; - } - --void zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 srclen, __u32 destlen) -+void jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, -+ uint32_t srclen, uint32_t destlen) - { -- z_stream strm; - int ret; -+ int wbits = MAX_WBITS; - - down(&inflate_sem); -- strm.workspace = inflate_workspace; - -- if (Z_OK != zlib_inflateInit(&strm)) { -+ inf_strm.next_in = data_in; -+ inf_strm.avail_in = srclen; -+ inf_strm.total_in = 0; -+ -+ inf_strm.next_out = cpage_out; -+ inf_strm.avail_out = destlen; -+ inf_strm.total_out = 0; -+ -+ /* If it's deflate, and it's got no preset dictionary, then -+ we can tell zlib to skip the adler32 check. */ -+ if (srclen > 2 && !(data_in[1] & PRESET_DICT) && -+ ((data_in[0] & 0x0f) == Z_DEFLATED) && -+ !(((data_in[0]<<8) + data_in[1]) % 31)) { -+ -+ D2(printk(KERN_DEBUG "inflate skipping adler32\n")); -+ wbits = -((data_in[0] >> 4) + 8); -+ inf_strm.next_in += 2; -+ inf_strm.avail_in -= 2; -+ } else { -+ /* Let this remain D1 for now -- it should never happen */ -+ D1(printk(KERN_DEBUG "inflate not skipping adler32\n")); -+ } -+ -+ -+ if (Z_OK != zlib_inflateInit2(&inf_strm, wbits)) { - printk(KERN_WARNING "inflateInit failed\n"); - up(&inflate_sem); - return; - } -- strm.next_in = data_in; -- strm.avail_in = srclen; -- strm.total_in = 0; -- -- strm.next_out = cpage_out; -- strm.avail_out = destlen; -- strm.total_out = 0; - -- while((ret = zlib_inflate(&strm, Z_FINISH)) == Z_OK) -+ while((ret = zlib_inflate(&inf_strm, Z_FINISH)) == Z_OK) - ; - if (ret != Z_STREAM_END) { - printk(KERN_NOTICE "inflate returned %d\n", ret); - } -- zlib_inflateEnd(&strm); -+ zlib_inflateEnd(&inf_strm); - up(&inflate_sem); - } -diff -Nurb linux-mips-2.4.27/fs/jffs2/comprtest.c linux/fs/jffs2/comprtest.c ---- linux-mips-2.4.27/fs/jffs2/comprtest.c 2001-10-19 03:24:56.000000000 +0200 -+++ linux/fs/jffs2/comprtest.c 2004-11-19 10:25:12.093170304 +0100 -@@ -1,4 +1,4 @@ --/* $Id$ */ -+/* $Id$ */ - - #include - #include -@@ -266,13 +266,13 @@ - static unsigned char decomprbuf[TESTDATA_LEN]; - - int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, -- unsigned char *data_out, __u32 cdatalen, __u32 datalen); -+ unsigned char *data_out, uint32_t cdatalen, uint32_t datalen); - unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 *datalen, __u32 *cdatalen); -+ uint32_t *datalen, uint32_t *cdatalen); - - int init_module(void ) { - unsigned char comprtype; -- __u32 c, d; -+ uint32_t c, d; - int ret; - - printk("Original data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -diff -Nurb linux-mips-2.4.27/fs/jffs2/crc32.c linux/fs/jffs2/crc32.c ---- linux-mips-2.4.27/fs/jffs2/crc32.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/crc32.c 2004-11-19 10:25:12.095170000 +0100 -@@ -0,0 +1,97 @@ -+/* -+ * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or -+ * code or tables extracted from it, as desired without restriction. -+ * -+ * First, the polynomial itself and its table of feedback terms. The -+ * polynomial is -+ * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 -+ * -+ * Note that we take it "backwards" and put the highest-order term in -+ * the lowest-order bit. The X^32 term is "implied"; the LSB is the -+ * X^31 term, etc. The X^0 term (usually shown as "+1") results in -+ * the MSB being 1 -+ * -+ * Note that the usual hardware shift register implementation, which -+ * is what we're using (we're merely optimizing it by doing eight-bit -+ * chunks at a time) shifts bits into the lowest-order term. In our -+ * implementation, that means shifting towards the right. Why do we -+ * do it this way? Because the calculated CRC must be transmitted in -+ * order from highest-order term to lowest-order term. UARTs transmit -+ * characters in order from LSB to MSB. By storing the CRC this way -+ * we hand it to the UART in the order low-byte to high-byte; the UART -+ * sends each low-bit to hight-bit; and the result is transmission bit -+ * by bit from highest- to lowest-order term without requiring any bit -+ * shuffling on our part. Reception works similarly -+ * -+ * The feedback terms table consists of 256, 32-bit entries. Notes -+ * -+ * The table can be generated at runtime if desired; code to do so -+ * is shown later. It might not be obvious, but the feedback -+ * terms simply represent the results of eight shift/xor opera -+ * tions for all combinations of data and CRC register values -+ * -+ * The values must be right-shifted by eight bits by the "updcrc -+ * logic; the shift must be unsigned (bring in zeroes). On some -+ * hardware you could probably optimize the shift in assembler by -+ * using byte-swap instructions -+ * polynomial $edb88320 -+ */ -+ -+/* $Id$ */ -+ -+#include "crc32.h" -+ -+const uint32_t crc32_table[256] = { -+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, -+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, -+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, -+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, -+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, -+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, -+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, -+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, -+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, -+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, -+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, -+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, -+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, -+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, -+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, -+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, -+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, -+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, -+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, -+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, -+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, -+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, -+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, -+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, -+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, -+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, -+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, -+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, -+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, -+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, -+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, -+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, -+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, -+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, -+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, -+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, -+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, -+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, -+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, -+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, -+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, -+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, -+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, -+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, -+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, -+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, -+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, -+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, -+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, -+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, -+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, -+ 0x2d02ef8dL -+}; -diff -Nurb linux-mips-2.4.27/fs/jffs2/crc32.h linux/fs/jffs2/crc32.h ---- linux-mips-2.4.27/fs/jffs2/crc32.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/crc32.h 2004-11-19 10:25:12.096169848 +0100 -@@ -0,0 +1,21 @@ -+#ifndef CRC32_H -+#define CRC32_H -+ -+/* $Id$ */ -+ -+#include -+ -+extern const uint32_t crc32_table[256]; -+ -+/* Return a 32-bit CRC of the contents of the buffer. */ -+ -+static inline uint32_t -+crc32(uint32_t val, const void *ss, int len) -+{ -+ const unsigned char *s = ss; -+ while (--len >= 0) -+ val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8); -+ return val; -+} -+ -+#endif -diff -Nurb linux-mips-2.4.27/fs/jffs2/dir.c linux/fs/jffs2/dir.c ---- linux-mips-2.4.27/fs/jffs2/dir.c 2003-11-17 02:07:44.000000000 +0100 -+++ linux/fs/jffs2/dir.c 2004-11-19 10:25:12.097169696 +0100 -@@ -1,84 +1,73 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include - #include -+#include - #include --#include /* For completion */ -+#include - #include - #include - #include -+#include - #include "nodelist.h" --#include -+ -+/* Urgh. Please tell me there's a nicer way of doing these. */ -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,48) -+typedef int mknod_arg_t; -+#define NAMEI_COMPAT(x) ((void *)x) -+#else -+typedef dev_t mknod_arg_t; -+#define NAMEI_COMPAT(x) (x) -+#endif - - static int jffs2_readdir (struct file *, void *, filldir_t); - --static int jffs2_create (struct inode *,struct dentry *,int); --static struct dentry *jffs2_lookup (struct inode *,struct dentry *); -+static int jffs2_create (struct inode *,struct dentry *,int, -+ struct nameidata *); -+static struct dentry *jffs2_lookup (struct inode *,struct dentry *, -+ struct nameidata *); - static int jffs2_link (struct dentry *,struct inode *,struct dentry *); - static int jffs2_unlink (struct inode *,struct dentry *); - static int jffs2_symlink (struct inode *,struct dentry *,const char *); - static int jffs2_mkdir (struct inode *,struct dentry *,int); - static int jffs2_rmdir (struct inode *,struct dentry *); --static int jffs2_mknod (struct inode *,struct dentry *,int,int); -+static int jffs2_mknod (struct inode *,struct dentry *,int,mknod_arg_t); - static int jffs2_rename (struct inode *, struct dentry *, - struct inode *, struct dentry *); - - struct file_operations jffs2_dir_operations = - { -- read: generic_read_dir, -- readdir: jffs2_readdir, -- ioctl: jffs2_ioctl, -- fsync: jffs2_null_fsync -+ .read = generic_read_dir, -+ .readdir = jffs2_readdir, -+ .ioctl = jffs2_ioctl, -+ .fsync = jffs2_fsync - }; - - - struct inode_operations jffs2_dir_inode_operations = - { -- create: jffs2_create, -- lookup: jffs2_lookup, -- link: jffs2_link, -- unlink: jffs2_unlink, -- symlink: jffs2_symlink, -- mkdir: jffs2_mkdir, -- rmdir: jffs2_rmdir, -- mknod: jffs2_mknod, -- rename: jffs2_rename, -- setattr: jffs2_setattr, -+ .create = NAMEI_COMPAT(jffs2_create), -+ .lookup = NAMEI_COMPAT(jffs2_lookup), -+ .link = jffs2_link, -+ .unlink = jffs2_unlink, -+ .symlink = jffs2_symlink, -+ .mkdir = jffs2_mkdir, -+ .rmdir = jffs2_rmdir, -+ .mknod = jffs2_mknod, -+ .rename = jffs2_rename, -+ .setattr = jffs2_setattr, - }; - - /***********************************************************************/ -@@ -88,12 +77,13 @@ - and we use the same hash function as the dentries. Makes this - nice and simple - */ --static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target) -+static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, -+ struct nameidata *nd) - { - struct jffs2_inode_info *dir_f; - struct jffs2_sb_info *c; - struct jffs2_full_dirent *fd = NULL, *fd_list; -- __u32 ino = 0; -+ uint32_t ino = 0; - struct inode *inode = NULL; - - D1(printk(KERN_DEBUG "jffs2_lookup()\n")); -@@ -153,8 +143,9 @@ - offset++; - } - if (offset == 1) { -- D1(printk(KERN_DEBUG "Dirent 1: \"..\", ino #%lu\n", filp->f_dentry->d_parent->d_inode->i_ino)); -- if (filldir(dirent, "..", 2, 1, filp->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) -+ unsigned long pino = parent_ino(filp->f_dentry); -+ D1(printk(KERN_DEBUG "Dirent 1: \"..\", ino #%lu\n", pino)); -+ if (filldir(dirent, "..", 2, 1, pino, DT_DIR) < 0) - goto out; - offset++; - } -@@ -188,18 +179,14 @@ - - /***********************************************************************/ - --static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode) -+ -+static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, -+ struct nameidata *nd) - { -+ struct jffs2_raw_inode *ri; - struct jffs2_inode_info *f, *dir_f; - struct jffs2_sb_info *c; - struct inode *inode; -- struct jffs2_raw_inode *ri; -- struct jffs2_raw_dirent *rd; -- struct jffs2_full_dnode *fn; -- struct jffs2_full_dirent *fd; -- int namelen; -- __u32 alloclen, phys_ofs; -- __u32 writtenlen; - int ret; - - ri = jffs2_alloc_raw_inode(); -@@ -210,23 +197,11 @@ - - D1(printk(KERN_DEBUG "jffs2_create()\n")); - -- /* Try to reserve enough space for both node and dirent. -- * Just the node will do for now, though -- */ -- namelen = dentry->d_name.len; -- ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); -- D1(printk(KERN_DEBUG "jffs2_create(): reserved 0x%x bytes\n", alloclen)); -- if (ret) { -- jffs2_free_raw_inode(ri); -- return ret; -- } -- - inode = jffs2_new_inode(dir_i, mode, ri); - - if (IS_ERR(inode)) { - D1(printk(KERN_DEBUG "jffs2_new_inode() failed\n")); - jffs2_free_raw_inode(ri); -- jffs2_complete_reservation(c); - return PTR_ERR(inode); - } - -@@ -236,93 +211,22 @@ - inode->i_mapping->nrpages = 0; - - f = JFFS2_INODE_INFO(inode); -+ dir_f = JFFS2_INODE_INFO(dir_i); - -- ri->data_crc = 0; -- ri->node_crc = crc32(0, ri, sizeof(*ri)-8); -- -- fn = jffs2_write_dnode(inode, ri, NULL, 0, phys_ofs, &writtenlen); -- D1(printk(KERN_DEBUG "jffs2_create created file with mode 0x%x\n", ri->mode)); -- jffs2_free_raw_inode(ri); -- -- if (IS_ERR(fn)) { -- D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n")); -- /* Eeek. Wave bye bye */ -- up(&f->sem); -- jffs2_complete_reservation(c); -- jffs2_clear_inode(inode); -- return PTR_ERR(fn); -- } -- /* No data here. Only a metadata node, which will be -- obsoleted by the first data write -- */ -- f->metadata = fn; -- -- /* Work out where to put the dirent node now. */ -- writtenlen = PAD(writtenlen); -- phys_ofs += writtenlen; -- alloclen -= writtenlen; -- up(&f->sem); -- -- if (alloclen < sizeof(*rd)+namelen) { -- /* Not enough space left in this chunk. Get some more */ -- jffs2_complete_reservation(c); -- ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); -+ ret = jffs2_do_create(c, dir_f, f, ri, -+ dentry->d_name.name, dentry->d_name.len); - - if (ret) { -- /* Eep. */ -- D1(printk(KERN_DEBUG "jffs2_reserve_space() for dirent failed\n")); - jffs2_clear_inode(inode); -+ make_bad_inode(inode); -+ iput(inode); -+ jffs2_free_raw_inode(ri); - return ret; - } -- } - -- rd = jffs2_alloc_raw_dirent(); -- if (!rd) { -- /* Argh. Now we treat it like a normal delete */ -- jffs2_complete_reservation(c); -- jffs2_clear_inode(inode); -- return -ENOMEM; -- } -- -- dir_f = JFFS2_INODE_INFO(dir_i); -- down(&dir_f->sem); -- -- rd->magic = JFFS2_MAGIC_BITMASK; -- rd->nodetype = JFFS2_NODETYPE_DIRENT; -- rd->totlen = sizeof(*rd) + namelen; -- rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); -- -- rd->pino = dir_i->i_ino; -- rd->version = ++dir_f->highest_version; -- rd->ino = inode->i_ino; -- rd->mctime = CURRENT_TIME; -- rd->nsize = namelen; -- rd->type = DT_REG; -- rd->node_crc = crc32(0, rd, sizeof(*rd)-8); -- rd->name_crc = crc32(0, dentry->d_name.name, namelen); -- -- fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); -- -- jffs2_complete_reservation(c); -- -- if (IS_ERR(fd)) { -- /* dirent failed to write. Delete the inode normally -- as if it were the final unlink() */ -- jffs2_free_raw_dirent(rd); -- up(&dir_f->sem); -- jffs2_clear_inode(inode); -- return PTR_ERR(fd); -- } -- -- dir_i->i_mtime = dir_i->i_ctime = rd->mctime; -- -- jffs2_free_raw_dirent(rd); -- -- /* Link the fd into the inode's list, obsoleting an old -- one if necessary. */ -- jffs2_add_fd_to_list(c, fd, &dir_f->dents); -- up(&dir_f->sem); -+ dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime)); - -+ jffs2_free_raw_inode(ri); - d_instantiate(dentry, inode); - - D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n", -@@ -332,173 +236,48 @@ - - /***********************************************************************/ - --static int jffs2_do_unlink(struct inode *dir_i, struct dentry *dentry, int rename) --{ -- struct jffs2_inode_info *dir_f, *f; -- struct jffs2_sb_info *c; -- struct jffs2_raw_dirent *rd; -- struct jffs2_full_dirent *fd; -- __u32 alloclen, phys_ofs; -- int ret; -- -- c = JFFS2_SB_INFO(dir_i->i_sb); -- -- rd = jffs2_alloc_raw_dirent(); -- if (!rd) -- return -ENOMEM; -- -- ret = jffs2_reserve_space(c, sizeof(*rd)+dentry->d_name.len, &phys_ofs, &alloclen, ALLOC_DELETION); -- if (ret) { -- jffs2_free_raw_dirent(rd); -- return ret; -- } -- -- dir_f = JFFS2_INODE_INFO(dir_i); -- down(&dir_f->sem); -- -- /* Build a deletion node */ -- rd->magic = JFFS2_MAGIC_BITMASK; -- rd->nodetype = JFFS2_NODETYPE_DIRENT; -- rd->totlen = sizeof(*rd) + dentry->d_name.len; -- rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); -- -- rd->pino = dir_i->i_ino; -- rd->version = ++dir_f->highest_version; -- rd->ino = 0; -- rd->mctime = CURRENT_TIME; -- rd->nsize = dentry->d_name.len; -- rd->type = DT_UNKNOWN; -- rd->node_crc = crc32(0, rd, sizeof(*rd)-8); -- rd->name_crc = crc32(0, dentry->d_name.name, dentry->d_name.len); -- -- fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, dentry->d_name.len, phys_ofs, NULL); -- -- jffs2_complete_reservation(c); -- jffs2_free_raw_dirent(rd); -- -- if (IS_ERR(fd)) { -- up(&dir_f->sem); -- return PTR_ERR(fd); -- } -- -- /* File it. This will mark the old one obsolete. */ -- jffs2_add_fd_to_list(c, fd, &dir_f->dents); -- up(&dir_f->sem); -- -- if (!rename) { -- f = JFFS2_INODE_INFO(dentry->d_inode); -- down(&f->sem); -- -- while (f->dents) { -- /* There can be only deleted ones */ -- fd = f->dents; -- -- f->dents = fd->next; -- -- if (fd->ino) { -- printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n", -- f->inocache->ino, fd->name, fd->ino); -- } else { -- D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n", fd->name, f->inocache->ino)); -- } -- jffs2_mark_node_obsolete(c, fd->raw); -- jffs2_free_full_dirent(fd); -- } -- /* Don't oops on unlinking a bad inode */ -- if (f->inocache) -- f->inocache->nlink--; -- dentry->d_inode->i_nlink--; -- up(&f->sem); -- } -- -- return 0; --} - - static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry) - { -- return jffs2_do_unlink(dir_i, dentry, 0); --} --/***********************************************************************/ -- --static int jffs2_do_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry, int rename) --{ -- struct jffs2_inode_info *dir_f, *f; -- struct jffs2_sb_info *c; -- struct jffs2_raw_dirent *rd; -- struct jffs2_full_dirent *fd; -- __u32 alloclen, phys_ofs; -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb); -+ struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); -+ struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(dentry->d_inode); - int ret; - -- c = JFFS2_SB_INFO(dir_i->i_sb); -- -- rd = jffs2_alloc_raw_dirent(); -- if (!rd) -- return -ENOMEM; -- -- ret = jffs2_reserve_space(c, sizeof(*rd)+dentry->d_name.len, &phys_ofs, &alloclen, ALLOC_NORMAL); -- if (ret) { -- jffs2_free_raw_dirent(rd); -+ ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, -+ dentry->d_name.len, dead_f); -+ if (dead_f->inocache) -+ dentry->d_inode->i_nlink = dead_f->inocache->nlink; - return ret; -- } -- -- dir_f = JFFS2_INODE_INFO(dir_i); -- down(&dir_f->sem); -- -- /* Build a deletion node */ -- rd->magic = JFFS2_MAGIC_BITMASK; -- rd->nodetype = JFFS2_NODETYPE_DIRENT; -- rd->totlen = sizeof(*rd) + dentry->d_name.len; -- rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); -- -- rd->pino = dir_i->i_ino; -- rd->version = ++dir_f->highest_version; -- rd->ino = old_dentry->d_inode->i_ino; -- rd->mctime = CURRENT_TIME; -- rd->nsize = dentry->d_name.len; -- -- /* XXX: This is ugly. */ -- rd->type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; -- if (!rd->type) rd->type = DT_REG; -- -- rd->node_crc = crc32(0, rd, sizeof(*rd)-8); -- rd->name_crc = crc32(0, dentry->d_name.name, dentry->d_name.len); -- -- fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, dentry->d_name.len, phys_ofs, NULL); -- -- jffs2_complete_reservation(c); -- jffs2_free_raw_dirent(rd); -- -- if (IS_ERR(fd)) { -- up(&dir_f->sem); -- return PTR_ERR(fd); -- } -- -- /* File it. This will mark the old one obsolete. */ -- jffs2_add_fd_to_list(c, fd, &dir_f->dents); -- up(&dir_f->sem); -- -- if (!rename) { -- f = JFFS2_INODE_INFO(old_dentry->d_inode); -- down(&f->sem); -- old_dentry->d_inode->i_nlink = ++f->inocache->nlink; -- up(&f->sem); -- } -- return 0; - } -+/***********************************************************************/ -+ - - static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry) - { -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dentry->d_inode->i_sb); -+ struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); -+ struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); - int ret; -+ uint8_t type; - -- /* Can't link a bad inode. */ -- if (!JFFS2_INODE_INFO(old_dentry->d_inode)->inocache) -+ /* Don't let people make hard links to bad inodes. */ -+ if (!f->inocache) - return -EIO; - - if (S_ISDIR(old_dentry->d_inode->i_mode)) - return -EPERM; - -- ret = jffs2_do_link(old_dentry, dir_i, dentry, 0); -+ /* XXX: This is ugly */ -+ type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; -+ if (!type) type = DT_REG; -+ -+ ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len); -+ - if (!ret) { -+ down(&f->sem); -+ old_dentry->d_inode->i_nlink = ++f->inocache->nlink; -+ up(&f->sem); - d_instantiate(dentry, old_dentry->d_inode); - atomic_inc(&old_dentry->d_inode->i_count); - } -@@ -517,8 +296,7 @@ - struct jffs2_full_dnode *fn; - struct jffs2_full_dirent *fd; - int namelen; -- __u32 alloclen, phys_ofs; -- __u32 writtenlen; -+ uint32_t alloclen, phys_ofs; - int ret; - - /* FIXME: If you care. We'd need to use frags for the target -@@ -556,15 +334,16 @@ - - f = JFFS2_INODE_INFO(inode); - -- inode->i_size = ri->isize = ri->dsize = ri->csize = strlen(target); -- ri->totlen = sizeof(*ri) + ri->dsize; -- ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); -+ inode->i_size = strlen(target); -+ ri->isize = ri->dsize = ri->csize = cpu_to_je32(inode->i_size); -+ ri->totlen = cpu_to_je32(sizeof(*ri) + inode->i_size); -+ ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); - - ri->compr = JFFS2_COMPR_NONE; -- ri->data_crc = crc32(0, target, strlen(target)); -- ri->node_crc = crc32(0, ri, sizeof(*ri)-8); -+ ri->data_crc = cpu_to_je32(crc32(0, target, strlen(target))); -+ ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - -- fn = jffs2_write_dnode(inode, ri, target, strlen(target), phys_ofs, &writtenlen); -+ fn = jffs2_write_dnode(c, f, ri, target, strlen(target), phys_ofs, ALLOC_NORMAL); - - jffs2_free_raw_inode(ri); - -@@ -581,13 +360,6 @@ - f->metadata = fn; - up(&f->sem); - -- /* Work out where to put the dirent node now. */ -- writtenlen = (writtenlen+3)&~3; -- phys_ofs += writtenlen; -- alloclen -= writtenlen; -- -- if (alloclen < sizeof(*rd)+namelen) { -- /* Not enough space left in this chunk. Get some more */ - jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); - if (ret) { -@@ -595,7 +367,6 @@ - jffs2_clear_inode(inode); - return ret; - } -- } - - rd = jffs2_alloc_raw_dirent(); - if (!rd) { -@@ -608,41 +379,42 @@ - dir_f = JFFS2_INODE_INFO(dir_i); - down(&dir_f->sem); - -- rd->magic = JFFS2_MAGIC_BITMASK; -- rd->nodetype = JFFS2_NODETYPE_DIRENT; -- rd->totlen = sizeof(*rd) + namelen; -- rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); -- -- rd->pino = dir_i->i_ino; -- rd->version = ++dir_f->highest_version; -- rd->ino = inode->i_ino; -- rd->mctime = CURRENT_TIME; -+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); -+ rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); -+ rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); -+ -+ rd->pino = cpu_to_je32(dir_i->i_ino); -+ rd->version = cpu_to_je32(++dir_f->highest_version); -+ rd->ino = cpu_to_je32(inode->i_ino); -+ rd->mctime = cpu_to_je32(get_seconds()); - rd->nsize = namelen; - rd->type = DT_LNK; -- rd->node_crc = crc32(0, rd, sizeof(*rd)-8); -- rd->name_crc = crc32(0, dentry->d_name.name, namelen); -+ rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); -+ rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); - -- fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); -- -- jffs2_complete_reservation(c); -+ fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); - - if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally - as if it were the final unlink() */ -+ jffs2_complete_reservation(c); - jffs2_free_raw_dirent(rd); - up(&dir_f->sem); - jffs2_clear_inode(inode); - return PTR_ERR(fd); - } - -- dir_i->i_mtime = dir_i->i_ctime = rd->mctime; -+ dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); - - jffs2_free_raw_dirent(rd); - - /* Link the fd into the inode's list, obsoleting an old - one if necessary. */ - jffs2_add_fd_to_list(c, fd, &dir_f->dents); -+ - up(&dir_f->sem); -+ jffs2_complete_reservation(c); - - d_instantiate(dentry, inode); - return 0; -@@ -659,8 +431,7 @@ - struct jffs2_full_dnode *fn; - struct jffs2_full_dirent *fd; - int namelen; -- __u32 alloclen, phys_ofs; -- __u32 writtenlen; -+ uint32_t alloclen, phys_ofs; - int ret; - - mode |= S_IFDIR; -@@ -692,13 +463,15 @@ - - inode->i_op = &jffs2_dir_inode_operations; - inode->i_fop = &jffs2_dir_operations; -+ /* Directories get nlink 2 at start */ -+ inode->i_nlink = 2; - - f = JFFS2_INODE_INFO(inode); - -- ri->data_crc = 0; -- ri->node_crc = crc32(0, ri, sizeof(*ri)-8); -+ ri->data_crc = cpu_to_je32(0); -+ ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - -- fn = jffs2_write_dnode(inode, ri, NULL, 0, phys_ofs, &writtenlen); -+ fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); - - jffs2_free_raw_inode(ri); - -@@ -715,13 +488,6 @@ - f->metadata = fn; - up(&f->sem); - -- /* Work out where to put the dirent node now. */ -- writtenlen = PAD(writtenlen); -- phys_ofs += writtenlen; -- alloclen -= writtenlen; -- -- if (alloclen < sizeof(*rd)+namelen) { -- /* Not enough space left in this chunk. Get some more */ - jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); - if (ret) { -@@ -729,7 +495,6 @@ - jffs2_clear_inode(inode); - return ret; - } -- } - - rd = jffs2_alloc_raw_dirent(); - if (!rd) { -@@ -742,41 +507,43 @@ - dir_f = JFFS2_INODE_INFO(dir_i); - down(&dir_f->sem); - -- rd->magic = JFFS2_MAGIC_BITMASK; -- rd->nodetype = JFFS2_NODETYPE_DIRENT; -- rd->totlen = sizeof(*rd) + namelen; -- rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); -- -- rd->pino = dir_i->i_ino; -- rd->version = ++dir_f->highest_version; -- rd->ino = inode->i_ino; -- rd->mctime = CURRENT_TIME; -+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); -+ rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); -+ rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); -+ -+ rd->pino = cpu_to_je32(dir_i->i_ino); -+ rd->version = cpu_to_je32(++dir_f->highest_version); -+ rd->ino = cpu_to_je32(inode->i_ino); -+ rd->mctime = cpu_to_je32(get_seconds()); - rd->nsize = namelen; - rd->type = DT_DIR; -- rd->node_crc = crc32(0, rd, sizeof(*rd)-8); -- rd->name_crc = crc32(0, dentry->d_name.name, namelen); -+ rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); -+ rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); - -- fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); -- -- jffs2_complete_reservation(c); -+ fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); - - if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally - as if it were the final unlink() */ -+ jffs2_complete_reservation(c); - jffs2_free_raw_dirent(rd); - up(&dir_f->sem); - jffs2_clear_inode(inode); - return PTR_ERR(fd); - } - -- dir_i->i_mtime = dir_i->i_ctime = rd->mctime; -+ dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); -+ dir_i->i_nlink++; - - jffs2_free_raw_dirent(rd); - - /* Link the fd into the inode's list, obsoleting an old - one if necessary. */ - jffs2_add_fd_to_list(c, fd, &dir_f->dents); -+ - up(&dir_f->sem); -+ jffs2_complete_reservation(c); - - d_instantiate(dentry, inode); - return 0; -@@ -786,15 +553,19 @@ - { - struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); - struct jffs2_full_dirent *fd; -+ int ret; - - for (fd = f->dents ; fd; fd = fd->next) { - if (fd->ino) - return -ENOTEMPTY; - } -- return jffs2_unlink(dir_i, dentry); -+ ret = jffs2_unlink(dir_i, dentry); -+ if (!ret) -+ dir_i->i_nlink--; -+ return ret; - } - --static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, int rdev) -+static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, mknod_arg_t rdev) - { - struct jffs2_inode_info *f, *dir_f; - struct jffs2_sb_info *c; -@@ -804,12 +575,14 @@ - struct jffs2_full_dnode *fn; - struct jffs2_full_dirent *fd; - int namelen; -- unsigned short dev; -+ jint16_t dev; - int devlen = 0; -- __u32 alloclen, phys_ofs; -- __u32 writtenlen; -+ uint32_t alloclen, phys_ofs; - int ret; - -+ if (!old_valid_dev(rdev)) -+ return -EINVAL; -+ - ri = jffs2_alloc_raw_inode(); - if (!ri) - return -ENOMEM; -@@ -817,7 +590,7 @@ - c = JFFS2_SB_INFO(dir_i->i_sb); - - if (S_ISBLK(mode) || S_ISCHR(mode)) { -- dev = (MAJOR(to_kdev_t(rdev)) << 8) | MINOR(to_kdev_t(rdev)); -+ dev = cpu_to_je16(old_encode_dev(rdev)); - devlen = sizeof(dev); - } - -@@ -844,15 +617,15 @@ - - f = JFFS2_INODE_INFO(inode); - -- ri->dsize = ri->csize = devlen; -- ri->totlen = sizeof(*ri) + ri->csize; -- ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); -+ ri->dsize = ri->csize = cpu_to_je32(devlen); -+ ri->totlen = cpu_to_je32(sizeof(*ri) + devlen); -+ ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); - - ri->compr = JFFS2_COMPR_NONE; -- ri->data_crc = crc32(0, &dev, devlen); -- ri->node_crc = crc32(0, ri, sizeof(*ri)-8); -+ ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen)); -+ ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - -- fn = jffs2_write_dnode(inode, ri, (char *)&dev, devlen, phys_ofs, &writtenlen); -+ fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, phys_ofs, ALLOC_NORMAL); - - jffs2_free_raw_inode(ri); - -@@ -869,13 +642,6 @@ - f->metadata = fn; - up(&f->sem); - -- /* Work out where to put the dirent node now. */ -- writtenlen = (writtenlen+3)&~3; -- phys_ofs += writtenlen; -- alloclen -= writtenlen; -- -- if (alloclen < sizeof(*rd)+namelen) { -- /* Not enough space left in this chunk. Get some more */ - jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); - if (ret) { -@@ -883,7 +649,6 @@ - jffs2_clear_inode(inode); - return ret; - } -- } - - rd = jffs2_alloc_raw_dirent(); - if (!rd) { -@@ -896,44 +661,45 @@ - dir_f = JFFS2_INODE_INFO(dir_i); - down(&dir_f->sem); - -- rd->magic = JFFS2_MAGIC_BITMASK; -- rd->nodetype = JFFS2_NODETYPE_DIRENT; -- rd->totlen = sizeof(*rd) + namelen; -- rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); -- -- rd->pino = dir_i->i_ino; -- rd->version = ++dir_f->highest_version; -- rd->ino = inode->i_ino; -- rd->mctime = CURRENT_TIME; -+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); -+ rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); -+ rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); -+ -+ rd->pino = cpu_to_je32(dir_i->i_ino); -+ rd->version = cpu_to_je32(++dir_f->highest_version); -+ rd->ino = cpu_to_je32(inode->i_ino); -+ rd->mctime = cpu_to_je32(get_seconds()); - rd->nsize = namelen; - - /* XXX: This is ugly. */ - rd->type = (mode & S_IFMT) >> 12; - -- rd->node_crc = crc32(0, rd, sizeof(*rd)-8); -- rd->name_crc = crc32(0, dentry->d_name.name, namelen); -- -- fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); -+ rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); -+ rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); - -- jffs2_complete_reservation(c); -+ fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); - - if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally - as if it were the final unlink() */ -+ jffs2_complete_reservation(c); - jffs2_free_raw_dirent(rd); - up(&dir_f->sem); - jffs2_clear_inode(inode); - return PTR_ERR(fd); - } - -- dir_i->i_mtime = dir_i->i_ctime = rd->mctime; -+ dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); - - jffs2_free_raw_dirent(rd); - - /* Link the fd into the inode's list, obsoleting an old - one if necessary. */ - jffs2_add_fd_to_list(c, fd, &dir_f->dents); -+ - up(&dir_f->sem); -+ jffs2_complete_reservation(c); - - d_instantiate(dentry, inode); - -@@ -944,7 +710,9 @@ - struct inode *new_dir_i, struct dentry *new_dentry) - { - int ret; -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); - struct jffs2_inode_info *victim_f = NULL; -+ uint8_t type; - - /* The VFS will check for us and prevent trying to rename a - * file over a directory and vice versa, but if it's a directory, -@@ -973,7 +741,15 @@ - */ - - /* Make a hard link */ -- ret = jffs2_do_link(old_dentry, new_dir_i, new_dentry, 1); -+ -+ /* XXX: This is ugly */ -+ type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; -+ if (!type) type = DT_REG; -+ -+ ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), -+ old_dentry->d_inode->i_ino, type, -+ new_dentry->d_name.name, new_dentry->d_name.len); -+ - if (ret) - return ret; - -@@ -989,22 +765,36 @@ - } - } - -+ /* If it was a directory we moved, and there was no victim, -+ increase i_nlink on its new parent */ -+ if (S_ISDIR(old_dentry->d_inode->i_mode) && !victim_f) -+ new_dir_i->i_nlink++; -+ - /* Unlink the original */ -- ret = jffs2_do_unlink(old_dir_i, old_dentry, 1); -+ ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), -+ old_dentry->d_name.name, old_dentry->d_name.len, NULL); -+ -+ /* We don't touch inode->i_nlink */ - - if (ret) { - /* Oh shit. We really ought to make a single node which can do both atomically */ - struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); - down(&f->sem); -+ old_dentry->d_inode->i_nlink++; - if (f->inocache) -- old_dentry->d_inode->i_nlink = f->inocache->nlink++; -+ f->inocache->nlink++; - up(&f->sem); - - printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret); - /* Might as well let the VFS know */ - d_instantiate(new_dentry, old_dentry->d_inode); - atomic_inc(&old_dentry->d_inode->i_count); -- } - return ret; -+ } -+ -+ if (S_ISDIR(old_dentry->d_inode->i_mode)) -+ old_dir_i->i_nlink--; -+ -+ return 0; - } - -diff -Nurb linux-mips-2.4.27/fs/jffs2/erase.c linux/fs/jffs2/erase.c ---- linux-mips-2.4.27/fs/jffs2/erase.c 2003-11-17 02:07:44.000000000 +0100 -+++ linux/fs/jffs2/erase.c 2004-11-19 10:25:12.099169392 +0100 -@@ -1,68 +1,60 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ -+ - #include - #include - #include --#include --#include --#include "nodelist.h" -+#include - #include -+#include -+#include -+#include "nodelist.h" - - struct erase_priv_struct { - struct jffs2_eraseblock *jeb; - struct jffs2_sb_info *c; - }; - -+#ifndef __ECOS - static void jffs2_erase_callback(struct erase_info *); -+#endif -+static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); - static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); - - void jffs2_erase_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) - { -- struct erase_info *instr; - int ret; -+#ifdef __ECOS -+ ret = jffs2_flash_erase(c, jeb); -+ if (!ret) { -+ jffs2_erase_succeeded(c, jeb); -+ return; -+ } -+#else /* Linux */ -+ struct erase_info *instr; - - instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL); - if (!instr) { - printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n"); -- spin_lock_bh(&c->erase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - list_del(&jeb->list); - list_add(&jeb->list, &c->erase_pending_list); - c->erasing_size -= c->sector_size; -- spin_unlock_bh(&c->erase_completion_lock); -+ c->dirty_size += c->sector_size; -+ jeb->dirty_size = c->sector_size; -+ spin_unlock(&c->erase_completion_lock); - return; - } - -@@ -77,19 +69,27 @@ - ((struct erase_priv_struct *)instr->priv)->jeb = jeb; - ((struct erase_priv_struct *)instr->priv)->c = c; - -+ /* NAND , read out the fail counter, if possible */ -+ if (!jffs2_can_mark_obsolete(c)) -+ jffs2_nand_read_failcnt(c,jeb); -+ - ret = c->mtd->erase(c->mtd, instr); -- if (!ret) { -+ if (!ret) - return; -- } -+ -+ kfree(instr); -+#endif /* __ECOS */ -+ - if (ret == -ENOMEM || ret == -EAGAIN) { - /* Erase failed immediately. Refile it on the list */ - D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret)); -- spin_lock_bh(&c->erase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - list_del(&jeb->list); - list_add(&jeb->list, &c->erase_pending_list); - c->erasing_size -= c->sector_size; -- spin_unlock_bh(&c->erase_completion_lock); -- kfree(instr); -+ c->dirty_size += c->sector_size; -+ jeb->dirty_size = c->sector_size; -+ spin_unlock(&c->erase_completion_lock); - return; - } - -@@ -97,74 +97,101 @@ - printk(KERN_WARNING "Erase at 0x%08x failed immediately: -EROFS. Is the sector locked?\n", jeb->offset); - else - printk(KERN_WARNING "Erase at 0x%08x failed immediately: errno %d\n", jeb->offset, ret); -- spin_lock_bh(&c->erase_completion_lock); -- list_del(&jeb->list); -- list_add(&jeb->list, &c->bad_list); -- c->nr_erasing_blocks--; -- c->bad_size += c->sector_size; -- c->erasing_size -= c->sector_size; -- spin_unlock_bh(&c->erase_completion_lock); -- wake_up(&c->erase_wait); -- kfree(instr); -+ -+ jffs2_erase_failed(c, jeb); - } - --void jffs2_erase_pending_blocks(struct jffs2_sb_info *c) -+void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) - { - struct jffs2_eraseblock *jeb; - -- spin_lock_bh(&c->erase_completion_lock); -- while (!list_empty(&c->erase_pending_list)) { -+ down(&c->erase_free_sem); - -- jeb = list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list); -+ spin_lock(&c->erase_completion_lock); - -- D1(printk(KERN_DEBUG "Starting erase of pending block 0x%08x\n", jeb->offset)); -+ while (!list_empty(&c->erase_complete_list) || -+ !list_empty(&c->erase_pending_list)) { - -+ if (!list_empty(&c->erase_complete_list)) { -+ jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list); -+ list_del(&jeb->list); -+ spin_unlock(&c->erase_completion_lock); -+ jffs2_mark_erased_block(c, jeb); -+ -+ if (!--count) { -+ D1(printk(KERN_DEBUG "Count reached. jffs2_erase_pending_blocks leaving\n")); -+ goto done; -+ } -+ -+ } else if (!list_empty(&c->erase_pending_list)) { -+ jeb = list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list); -+ D1(printk(KERN_DEBUG "Starting erase of pending block 0x%08x\n", jeb->offset)); - list_del(&jeb->list); - c->erasing_size += c->sector_size; -+ c->wasted_size -= jeb->wasted_size; - c->free_size -= jeb->free_size; - c->used_size -= jeb->used_size; - c->dirty_size -= jeb->dirty_size; -- jeb->used_size = jeb->dirty_size = jeb->free_size = 0; -+ jeb->wasted_size = jeb->used_size = jeb->dirty_size = jeb->free_size = 0; - jffs2_free_all_node_refs(c, jeb); - list_add(&jeb->list, &c->erasing_list); -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - - jffs2_erase_block(c, jeb); -+ -+ } else { -+ BUG(); -+ } -+ - /* Be nice */ -- if (current->need_resched) -- schedule(); -- spin_lock_bh(&c->erase_completion_lock); -+ cond_resched(); -+ spin_lock(&c->erase_completion_lock); - } -- spin_unlock_bh(&c->erase_completion_lock); -+ -+ spin_unlock(&c->erase_completion_lock); -+ done: - D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n")); -+ -+ up(&c->erase_free_sem); -+} -+ -+static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) -+{ -+ D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset)); -+ spin_lock(&c->erase_completion_lock); -+ list_del(&jeb->list); -+ list_add_tail(&jeb->list, &c->erase_complete_list); -+ spin_unlock(&c->erase_completion_lock); -+ /* Ensure that kupdated calls us again to mark them clean */ -+ jffs2_erase_pending_trigger(c); - } - -+static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) -+{ -+ spin_lock(&c->erase_completion_lock); -+ c->erasing_size -= c->sector_size; -+ c->bad_size += c->sector_size; -+ list_del(&jeb->list); -+ list_add(&jeb->list, &c->bad_list); -+ c->nr_erasing_blocks--; -+ spin_unlock(&c->erase_completion_lock); -+ wake_up(&c->erase_wait); -+} - -+#ifndef __ECOS - static void jffs2_erase_callback(struct erase_info *instr) - { - struct erase_priv_struct *priv = (void *)instr->priv; - - if(instr->state != MTD_ERASE_DONE) { - printk(KERN_WARNING "Erase at 0x%08x finished, but state != MTD_ERASE_DONE. State is 0x%x instead.\n", instr->addr, instr->state); -- spin_lock(&priv->c->erase_completion_lock); -- priv->c->erasing_size -= priv->c->sector_size; -- priv->c->bad_size += priv->c->sector_size; -- list_del(&priv->jeb->list); -- list_add(&priv->jeb->list, &priv->c->bad_list); -- priv->c->nr_erasing_blocks--; -- spin_unlock(&priv->c->erase_completion_lock); -- wake_up(&priv->c->erase_wait); -+ jffs2_erase_failed(priv->c, priv->jeb); - } else { -- D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", instr->addr)); -- spin_lock(&priv->c->erase_completion_lock); -- list_del(&priv->jeb->list); -- list_add_tail(&priv->jeb->list, &priv->c->erase_complete_list); -- spin_unlock(&priv->c->erase_completion_lock); -+ jffs2_erase_succeeded(priv->c, priv->jeb); - } -- /* Make sure someone picks up the block off the erase_complete list */ -- OFNI_BS_2SFFJ(priv->c)->s_dirt = 1; - kfree(instr); - } -+#endif /* !__ECOS */ - - /* Hmmm. Maybe we should accept the extra space it takes and make - this a standard doubly-linked list? */ -@@ -221,7 +248,7 @@ - this = ic->nodes; - - while(this) { -- printk( "0x%08x(%d)->", this->flash_offset & ~3, this->flash_offset &3); -+ printk( "0x%08x(%d)->", ref_offset(this), ref_flags(this)); - if (++i == 5) { - printk("\n" KERN_DEBUG); - i=0; -@@ -256,54 +283,43 @@ - jeb->last_node = NULL; - } - --void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) -+static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) - { -- OFNI_BS_2SFFJ(c)->s_dirt = 1; --} -- --void jffs2_mark_erased_blocks(struct jffs2_sb_info *c) --{ -- static struct jffs2_unknown_node marker = {JFFS2_MAGIC_BITMASK, JFFS2_NODETYPE_CLEANMARKER, sizeof(struct jffs2_unknown_node)}; -- struct jffs2_eraseblock *jeb; -- struct jffs2_raw_node_ref *marker_ref; -+ struct jffs2_raw_node_ref *marker_ref = NULL; - unsigned char *ebuf; -- ssize_t retlen; -+ size_t retlen; - int ret; - -- marker.hdr_crc = crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4); -- -- spin_lock_bh(&c->erase_completion_lock); -- while (!list_empty(&c->erase_complete_list)) { -- jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list); -- list_del(&jeb->list); -- spin_unlock_bh(&c->erase_completion_lock); -- -+ if (!jffs2_cleanmarker_oob(c)) { - marker_ref = jffs2_alloc_raw_node_ref(); - if (!marker_ref) { - printk(KERN_WARNING "Failed to allocate raw node ref for clean marker\n"); -- /* Come back later */ -+ /* Stick it back on the list from whence it came and come back later */ - jffs2_erase_pending_trigger(c); -+ spin_lock(&c->erase_completion_lock); -+ list_add(&jeb->list, &c->erase_complete_list); -+ spin_unlock(&c->erase_completion_lock); - return; - } -- -+ } - ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!ebuf) { - printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Assuming it worked\n", jeb->offset); - } else { -- __u32 ofs = jeb->offset; -+ uint32_t ofs = jeb->offset; - - D1(printk(KERN_DEBUG "Verifying erase at 0x%08x\n", jeb->offset)); - while(ofs < jeb->offset + c->sector_size) { -- __u32 readlen = min((__u32)PAGE_SIZE, jeb->offset + c->sector_size - ofs); -+ uint32_t readlen = min((uint32_t)PAGE_SIZE, jeb->offset + c->sector_size - ofs); - int i; - -- ret = c->mtd->read(c->mtd, ofs, readlen, &retlen, ebuf); -- if (ret < 0) { -+ ret = jffs2_flash_read(c, ofs, readlen, &retlen, ebuf); -+ if (ret) { - printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret); - goto bad; - } - if (retlen != readlen) { -- printk(KERN_WARNING "Short read from newly-erased block at 0x%08x. Wanted %d, got %d\n", ofs, readlen, retlen); -+ printk(KERN_WARNING "Short read from newly-erased block at 0x%08x. Wanted %d, got %zd\n", ofs, readlen, retlen); - goto bad; - } - for (i=0; ierase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - c->erasing_size -= c->sector_size; - c->bad_size += c->sector_size; - - list_add_tail(&jeb->list, &c->bad_list); - c->nr_erasing_blocks--; -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - wake_up(&c->erase_wait); - return; - } - } - ofs += readlen; -+ cond_resched(); - } - kfree(ebuf); - } - - /* Write the erase complete marker */ - D1(printk(KERN_DEBUG "Writing erased marker to block at 0x%08x\n", jeb->offset)); -- ret = c->mtd->write(c->mtd, jeb->offset, sizeof(marker), &retlen, (char *)&marker); -+ if (jffs2_cleanmarker_oob(c)) { -+ -+ if (jffs2_write_nand_cleanmarker(c, jeb)) -+ goto bad2; -+ -+ jeb->first_node = jeb->last_node = NULL; -+ -+ jeb->free_size = c->sector_size; -+ jeb->used_size = 0; -+ jeb->dirty_size = 0; -+ jeb->wasted_size = 0; -+ } else { -+ struct jffs2_unknown_node marker = { -+ .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK), -+ .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), -+ .totlen = cpu_to_je32(c->cleanmarker_size) -+ }; -+ -+ marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4)); -+ -+ /* We only write the header; the rest was noise or padding anyway */ -+ ret = jffs2_flash_write(c, jeb->offset, sizeof(marker), &retlen, (char *)&marker); - if (ret) { - printk(KERN_WARNING "Write clean marker to block at 0x%08x failed: %d\n", - jeb->offset, ret); - goto bad2; - } - if (retlen != sizeof(marker)) { -- printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %d, got %d\n", -+ printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %d, got %zd\n", - jeb->offset, sizeof(marker), retlen); - goto bad2; - } - - marker_ref->next_in_ino = NULL; - marker_ref->next_phys = NULL; -- marker_ref->flash_offset = jeb->offset; -- marker_ref->totlen = PAD(sizeof(marker)); -+ marker_ref->flash_offset = jeb->offset | REF_NORMAL; -+ marker_ref->__totlen = c->cleanmarker_size; - - jeb->first_node = jeb->last_node = marker_ref; - -- jeb->free_size = c->sector_size - marker_ref->totlen; -- jeb->used_size = marker_ref->totlen; -+ jeb->free_size = c->sector_size - c->cleanmarker_size; -+ jeb->used_size = c->cleanmarker_size; - jeb->dirty_size = 0; -+ jeb->wasted_size = 0; -+ } - -- spin_lock_bh(&c->erase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - c->erasing_size -= c->sector_size; - c->free_size += jeb->free_size; - c->used_size += jeb->used_size; - - ACCT_SANITY_CHECK(c,jeb); -- ACCT_PARANOIA_CHECK(jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); - - list_add_tail(&jeb->list, &c->free_list); - c->nr_erasing_blocks--; - c->nr_free_blocks++; -+ spin_unlock(&c->erase_completion_lock); - wake_up(&c->erase_wait); -- } -- spin_unlock_bh(&c->erase_completion_lock); - } -+ -diff -Nurb linux-mips-2.4.27/fs/jffs2/file.c linux/fs/jffs2/file.c ---- linux-mips-2.4.27/fs/jffs2/file.c 2003-11-17 02:07:44.000000000 +0100 -+++ linux/fs/jffs2/file.c 2004-11-19 10:25:12.101169088 +0100 -@@ -1,319 +1,106 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - -+#include - #include --#include /* for min() */ - #include - #include -+#include - #include -+#include -+#include - #include - #include "nodelist.h" --#include - - extern int generic_file_open(struct inode *, struct file *) __attribute__((weak)); - extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) __attribute__((weak)); - - --int jffs2_null_fsync(struct file *filp, struct dentry *dentry, int datasync) -+int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync) - { -- /* Move along. Nothing to see here */ -+ struct inode *inode = dentry->d_inode; -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -+ -+ /* Trigger GC to flush any pending writes for this inode */ -+ jffs2_flush_wbuf_gc(c, inode->i_ino); -+ - return 0; - } - - struct file_operations jffs2_file_operations = - { -- llseek: generic_file_llseek, -- open: generic_file_open, -- read: generic_file_read, -- write: generic_file_write, -- ioctl: jffs2_ioctl, -- mmap: generic_file_mmap, -- fsync: jffs2_null_fsync -+ .llseek = generic_file_llseek, -+ .open = generic_file_open, -+ .read = generic_file_read, -+ .write = generic_file_write, -+ .ioctl = jffs2_ioctl, -+ .mmap = generic_file_readonly_mmap, -+ .fsync = jffs2_fsync, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,29) -+ .sendfile = generic_file_sendfile -+#endif - }; - - /* jffs2_file_inode_operations */ - - struct inode_operations jffs2_file_inode_operations = - { -- setattr: jffs2_setattr -+ .setattr = jffs2_setattr - }; - - struct address_space_operations jffs2_file_address_operations = - { -- readpage: jffs2_readpage, -- prepare_write: jffs2_prepare_write, -- commit_write: jffs2_commit_write -+ .readpage = jffs2_readpage, -+ .prepare_write =jffs2_prepare_write, -+ .commit_write = jffs2_commit_write - }; - --int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) --{ -- struct jffs2_full_dnode *old_metadata, *new_metadata; -- struct inode *inode = dentry->d_inode; -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); -- struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -- struct jffs2_raw_inode *ri; -- unsigned short dev; -- unsigned char *mdata = NULL; -- int mdatalen = 0; -- unsigned int ivalid; -- __u32 phys_ofs, alloclen; -- int ret; -- D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); -- ret = inode_change_ok(inode, iattr); -- if (ret) -- return ret; -- -- /* Special cases - we don't want more than one data node -- for these types on the medium at any time. So setattr -- must read the original data associated with the node -- (i.e. the device numbers or the target name) and write -- it out again with the appropriate data attached */ -- if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { -- /* For these, we don't actually need to read the old node */ -- dev = (MAJOR(to_kdev_t(dentry->d_inode->i_rdev)) << 8) | -- MINOR(to_kdev_t(dentry->d_inode->i_rdev)); -- mdata = (char *)&dev; -- mdatalen = sizeof(dev); -- D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen)); -- } else if (S_ISLNK(inode->i_mode)) { -- mdatalen = f->metadata->size; -- mdata = kmalloc(f->metadata->size, GFP_USER); -- if (!mdata) -- return -ENOMEM; -- ret = jffs2_read_dnode(c, f->metadata, mdata, 0, mdatalen); -- if (ret) { -- kfree(mdata); -- return ret; -- } -- D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen)); -- } -- -- ri = jffs2_alloc_raw_inode(); -- if (!ri) { -- if (S_ISLNK(inode->i_mode)) -- kfree(mdata); -- return -ENOMEM; -- } -- -- ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL); -- if (ret) { -- jffs2_free_raw_inode(ri); -- if (S_ISLNK(inode->i_mode)) -- kfree(mdata); -- return ret; -- } -- down(&f->sem); -- ivalid = iattr->ia_valid; -- -- ri->magic = JFFS2_MAGIC_BITMASK; -- ri->nodetype = JFFS2_NODETYPE_INODE; -- ri->totlen = sizeof(*ri) + mdatalen; -- ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); -- -- ri->ino = inode->i_ino; -- ri->version = ++f->highest_version; -- -- ri->mode = (ivalid & ATTR_MODE)?iattr->ia_mode:inode->i_mode; -- ri->uid = (ivalid & ATTR_UID)?iattr->ia_uid:inode->i_uid; -- ri->gid = (ivalid & ATTR_GID)?iattr->ia_gid:inode->i_gid; -- -- if (ivalid & ATTR_MODE && ri->mode & S_ISGID && -- !in_group_p(ri->gid) && !capable(CAP_FSETID)) -- ri->mode &= ~S_ISGID; -- -- ri->isize = (ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size; -- ri->atime = (ivalid & ATTR_ATIME)?iattr->ia_atime:inode->i_atime; -- ri->mtime = (ivalid & ATTR_MTIME)?iattr->ia_mtime:inode->i_mtime; -- ri->ctime = (ivalid & ATTR_CTIME)?iattr->ia_ctime:inode->i_ctime; -- -- ri->offset = 0; -- ri->csize = ri->dsize = mdatalen; -- ri->compr = JFFS2_COMPR_NONE; -- if (inode->i_size < ri->isize) { -- /* It's an extension. Make it a hole node */ -- ri->compr = JFFS2_COMPR_ZERO; -- ri->dsize = ri->isize - inode->i_size; -- ri->offset = inode->i_size; -- } -- ri->node_crc = crc32(0, ri, sizeof(*ri)-8); -- if (mdatalen) -- ri->data_crc = crc32(0, mdata, mdatalen); -- else -- ri->data_crc = 0; -- -- new_metadata = jffs2_write_dnode(inode, ri, mdata, mdatalen, phys_ofs, NULL); -- if (S_ISLNK(inode->i_mode)) -- kfree(mdata); -- -- jffs2_complete_reservation(c); -- -- if (IS_ERR(new_metadata)) { -- jffs2_free_raw_inode(ri); -- up(&f->sem); -- return PTR_ERR(new_metadata); -- } -- /* It worked. Update the inode */ -- inode->i_atime = ri->atime; -- inode->i_ctime = ri->ctime; -- inode->i_mtime = ri->mtime; -- inode->i_mode = ri->mode; -- inode->i_uid = ri->uid; -- inode->i_gid = ri->gid; -- -- -- old_metadata = f->metadata; -- -- if (inode->i_size > ri->isize) { -- vmtruncate(inode, ri->isize); -- jffs2_truncate_fraglist (c, &f->fraglist, ri->isize); -- } -- -- if (inode->i_size < ri->isize) { -- jffs2_add_full_dnode_to_inode(c, f, new_metadata); -- inode->i_size = ri->isize; -- f->metadata = NULL; -- } else { -- f->metadata = new_metadata; -- } -- if (old_metadata) { -- jffs2_mark_node_obsolete(c, old_metadata->raw); -- jffs2_free_full_dnode(old_metadata); -- } -- jffs2_free_raw_inode(ri); -- up(&f->sem); -- return 0; --} -- - int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg) - { - struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -- struct jffs2_node_frag *frag = f->fraglist; -- __u32 offset = pg->index << PAGE_CACHE_SHIFT; -- __u32 end = offset + PAGE_CACHE_SIZE; - unsigned char *pg_buf; - int ret; - -- D1(printk(KERN_DEBUG "jffs2_do_readpage_nolock(): ino #%lu, page at offset 0x%x\n", inode->i_ino, offset)); -+ D2(printk(KERN_DEBUG "jffs2_do_readpage_nolock(): ino #%lu, page at offset 0x%lx\n", inode->i_ino, pg->index << PAGE_CACHE_SHIFT)); - - if (!PageLocked(pg)) - PAGE_BUG(pg); - -- while(frag && frag->ofs + frag->size <= offset) { -- // D1(printk(KERN_DEBUG "skipping frag %d-%d; before the region we care about\n", frag->ofs, frag->ofs + frag->size)); -- frag = frag->next; -- } -- - pg_buf = kmap(pg); -+ /* FIXME: Can kmap fail? */ - -- /* XXX FIXME: Where a single physical node actually shows up in two -- frags, we read it twice. Don't do that. */ -- /* Now we're pointing at the first frag which overlaps our page */ -- while(offset < end) { -- D2(printk(KERN_DEBUG "jffs2_readpage: offset %d, end %d\n", offset, end)); -- if (!frag || frag->ofs > offset) { -- __u32 holesize = end - offset; -- if (frag) { -- D1(printk(KERN_NOTICE "Eep. Hole in ino %ld fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n", inode->i_ino, frag->ofs, offset)); -- holesize = min(holesize, frag->ofs - offset); -- D1(jffs2_print_frag_list(f)); -- } -- D1(printk(KERN_DEBUG "Filling non-frag hole from %d-%d\n", offset, offset+holesize)); -- memset(pg_buf, 0, holesize); -- pg_buf += holesize; -- offset += holesize; -- continue; -- } else if (frag->ofs < offset && (offset & (PAGE_CACHE_SIZE-1)) != 0) { -- D1(printk(KERN_NOTICE "Eep. Overlap in ino #%ld fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n", -- inode->i_ino, frag->ofs, offset)); -- D1(jffs2_print_frag_list(f)); -- memset(pg_buf, 0, end - offset); -- ClearPageUptodate(pg); -- SetPageError(pg); -- kunmap(pg); -- return -EIO; -- } else if (!frag->node) { -- __u32 holeend = min(end, frag->ofs + frag->size); -- D1(printk(KERN_DEBUG "Filling frag hole from %d-%d (frag 0x%x 0x%x)\n", offset, holeend, frag->ofs, frag->ofs + frag->size)); -- memset(pg_buf, 0, holeend - offset); -- pg_buf += holeend - offset; -- offset = holeend; -- frag = frag->next; -- continue; -- } else { -- __u32 readlen; -- __u32 fragofs; /* offset within the frag to start reading */ -+ ret = jffs2_read_inode_range(c, f, pg_buf, pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE); - -- fragofs = offset - frag->ofs; -- readlen = min(frag->size - fragofs, end - offset); -- D1(printk(KERN_DEBUG "Reading %d-%d from node at 0x%x\n", frag->ofs+fragofs, -- fragofs+frag->ofs+readlen, frag->node->raw->flash_offset & ~3)); -- ret = jffs2_read_dnode(c, frag->node, pg_buf, fragofs + frag->ofs - frag->node->ofs, readlen); -- D2(printk(KERN_DEBUG "node read done\n")); - if (ret) { -- D1(printk(KERN_DEBUG"jffs2_readpage error %d\n",ret)); -- memset(pg_buf, 0, readlen); - ClearPageUptodate(pg); - SetPageError(pg); -- kunmap(pg); -- return ret; -- } -- -- pg_buf += readlen; -- offset += readlen; -- frag = frag->next; -- D2(printk(KERN_DEBUG "node read was OK. Looping\n")); -- } -- } -- D2(printk(KERN_DEBUG "readpage finishing\n")); -+ } else { - SetPageUptodate(pg); - ClearPageError(pg); -+ } - - flush_dcache_page(pg); -- - kunmap(pg); -- D1(printk(KERN_DEBUG "readpage finished\n")); -+ -+ D2(printk(KERN_DEBUG "readpage finished\n")); - return 0; - } - - int jffs2_do_readpage_unlock(struct inode *inode, struct page *pg) - { - int ret = jffs2_do_readpage_nolock(inode, pg); -- UnlockPage(pg); -+ unlock_page(pg); - return ret; - } - -@@ -333,17 +120,17 @@ - { - struct inode *inode = pg->mapping->host; - struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); -- __u32 pageofs = pg->index << PAGE_CACHE_SHIFT; -+ uint32_t pageofs = pg->index << PAGE_CACHE_SHIFT; - int ret = 0; - -- D1(printk(KERN_DEBUG "jffs2_prepare_write() nrpages %ld\n", inode->i_mapping->nrpages)); -+ D1(printk(KERN_DEBUG "jffs2_prepare_write()\n")); - - if (pageofs > inode->i_size) { - /* Make new hole frag from old EOF to new page */ - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); - struct jffs2_raw_inode ri; - struct jffs2_full_dnode *fn; -- __u32 phys_ofs, alloc_len; -+ uint32_t phys_ofs, alloc_len; - - D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", - (unsigned int)inode->i_size, pageofs)); -@@ -355,29 +142,30 @@ - down(&f->sem); - memset(&ri, 0, sizeof(ri)); - -- ri.magic = JFFS2_MAGIC_BITMASK; -- ri.nodetype = JFFS2_NODETYPE_INODE; -- ri.totlen = sizeof(ri); -- ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4); -- -- ri.ino = f->inocache->ino; -- ri.version = ++f->highest_version; -- ri.mode = inode->i_mode; -- ri.uid = inode->i_uid; -- ri.gid = inode->i_gid; -- ri.isize = max((__u32)inode->i_size, pageofs); -- ri.atime = ri.ctime = ri.mtime = CURRENT_TIME; -- ri.offset = inode->i_size; -- ri.dsize = pageofs - inode->i_size; -- ri.csize = 0; -+ ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -+ ri.totlen = cpu_to_je32(sizeof(ri)); -+ ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); -+ -+ ri.ino = cpu_to_je32(f->inocache->ino); -+ ri.version = cpu_to_je32(++f->highest_version); -+ ri.mode = cpu_to_jemode(inode->i_mode); -+ ri.uid = cpu_to_je16(inode->i_uid); -+ ri.gid = cpu_to_je16(inode->i_gid); -+ ri.isize = cpu_to_je32(max((uint32_t)inode->i_size, pageofs)); -+ ri.atime = ri.ctime = ri.mtime = cpu_to_je32(get_seconds()); -+ ri.offset = cpu_to_je32(inode->i_size); -+ ri.dsize = cpu_to_je32(pageofs - inode->i_size); -+ ri.csize = cpu_to_je32(0); - ri.compr = JFFS2_COMPR_ZERO; -- ri.node_crc = crc32(0, &ri, sizeof(ri)-8); -- ri.data_crc = 0; -+ ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); -+ ri.data_crc = cpu_to_je32(0); -+ -+ fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_NORMAL); - -- fn = jffs2_write_dnode(inode, &ri, NULL, 0, phys_ofs, NULL); -- jffs2_complete_reservation(c); - if (IS_ERR(fn)) { - ret = PTR_ERR(fn); -+ jffs2_complete_reservation(c); - up(&f->sem); - return ret; - } -@@ -391,16 +179,17 @@ - D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in prepare_write, returned %d\n", ret)); - jffs2_mark_node_obsolete(c, fn->raw); - jffs2_free_full_dnode(fn); -+ jffs2_complete_reservation(c); - up(&f->sem); - return ret; - } -+ jffs2_complete_reservation(c); - inode->i_size = pageofs; - up(&f->sem); - } - -- - /* Read in the page if it wasn't already present, unless it's a whole page */ -- if (!Page_Uptodate(pg) && (start || end < PAGE_CACHE_SIZE)) { -+ if (!PageUptodate(pg) && (start || end < PAGE_CACHE_SIZE)) { - down(&f->sem); - ret = jffs2_do_readpage_nolock(inode, pg); - up(&f->sem); -@@ -417,14 +206,12 @@ - struct inode *inode = pg->mapping->host; - struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -- __u32 newsize = max_t(__u32, filp->f_dentry->d_inode->i_size, (pg->index << PAGE_CACHE_SHIFT) + end); -- __u32 file_ofs = (pg->index << PAGE_CACHE_SHIFT); -- __u32 writelen = min((__u32)PAGE_CACHE_SIZE, newsize - file_ofs); - struct jffs2_raw_inode *ri; - int ret = 0; -- ssize_t writtenlen = 0; -+ uint32_t writtenlen = 0; - -- D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n", inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags)); -+ D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n", -+ inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags)); - - if (!start && end == PAGE_CACHE_SIZE) { - /* We need to avoid deadlock with page_cache_read() in -@@ -435,109 +222,47 @@ - } - - ri = jffs2_alloc_raw_inode(); -- if (!ri) -- return -ENOMEM; -- -- while(writelen) { -- struct jffs2_full_dnode *fn; -- unsigned char *comprbuf = NULL; -- unsigned char comprtype = JFFS2_COMPR_NONE; -- __u32 phys_ofs, alloclen; -- __u32 datalen, cdatalen; - -- D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, file_ofs)); -- -- ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen, ALLOC_NORMAL); -- if (ret) { -- SetPageError(pg); -- D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); -- break; -+ if (!ri) { -+ D1(printk(KERN_DEBUG "jffs2_commit_write(): Allocation of raw inode failed\n")); -+ return -ENOMEM; - } -- down(&f->sem); -- datalen = writelen; -- cdatalen = min(alloclen - sizeof(*ri), writelen); -- -- comprbuf = kmalloc(cdatalen, GFP_KERNEL); -- if (comprbuf) { -- comprtype = jffs2_compress(page_address(pg)+ (file_ofs & (PAGE_CACHE_SIZE-1)), comprbuf, &datalen, &cdatalen); -- } -- if (comprtype == JFFS2_COMPR_NONE) { -- /* Either compression failed, or the allocation of comprbuf failed */ -- if (comprbuf) -- kfree(comprbuf); -- comprbuf = page_address(pg) + (file_ofs & (PAGE_CACHE_SIZE -1)); -- datalen = cdatalen; -- } -- /* Now comprbuf points to the data to be written, be it compressed or not. -- comprtype holds the compression type, and comprtype == JFFS2_COMPR_NONE means -- that the comprbuf doesn't need to be kfree()d. -- */ -- -- ri->magic = JFFS2_MAGIC_BITMASK; -- ri->nodetype = JFFS2_NODETYPE_INODE; -- ri->totlen = sizeof(*ri) + cdatalen; -- ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); -- -- ri->ino = inode->i_ino; -- ri->version = ++f->highest_version; -- ri->mode = inode->i_mode; -- ri->uid = inode->i_uid; -- ri->gid = inode->i_gid; -- ri->isize = max((__u32)inode->i_size, file_ofs + datalen); -- ri->atime = ri->ctime = ri->mtime = CURRENT_TIME; -- ri->offset = file_ofs; -- ri->csize = cdatalen; -- ri->dsize = datalen; -- ri->compr = comprtype; -- ri->node_crc = crc32(0, ri, sizeof(*ri)-8); -- ri->data_crc = crc32(0, comprbuf, cdatalen); -- -- fn = jffs2_write_dnode(inode, ri, comprbuf, cdatalen, phys_ofs, NULL); - -- jffs2_complete_reservation(c); -+ /* Set the fields that the generic jffs2_write_inode_range() code can't find */ -+ ri->ino = cpu_to_je32(inode->i_ino); -+ ri->mode = cpu_to_jemode(inode->i_mode); -+ ri->uid = cpu_to_je16(inode->i_uid); -+ ri->gid = cpu_to_je16(inode->i_gid); -+ ri->isize = cpu_to_je32((uint32_t)inode->i_size); -+ ri->atime = ri->ctime = ri->mtime = cpu_to_je32(get_seconds()); -+ -+ /* In 2.4, it was already kmapped by generic_file_write(). Doesn't -+ hurt to do it again. The alternative is ifdefs, which are ugly. */ -+ kmap(pg); -+ -+ ret = jffs2_write_inode_range(c, f, ri, page_address(pg) + start, -+ (pg->index << PAGE_CACHE_SHIFT) + start, -+ end - start, &writtenlen); - -- if (comprtype != JFFS2_COMPR_NONE) -- kfree(comprbuf); -+ kunmap(pg); - -- if (IS_ERR(fn)) { -- ret = PTR_ERR(fn); -- up(&f->sem); -- SetPageError(pg); -- break; -- } -- ret = jffs2_add_full_dnode_to_inode(c, f, fn); -- if (f->metadata) { -- jffs2_mark_node_obsolete(c, f->metadata->raw); -- jffs2_free_full_dnode(f->metadata); -- f->metadata = NULL; -- } -- up(&f->sem); - if (ret) { -- /* Eep */ -- D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in commit_write, returned %d\n", ret)); -- jffs2_mark_node_obsolete(c, fn->raw); -- jffs2_free_full_dnode(fn); -+ /* There was an error writing. */ - SetPageError(pg); -- break; - } -- inode->i_size = ri->isize; -+ -+ if (writtenlen) { -+ if (inode->i_size < (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen) { -+ inode->i_size = (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen; - inode->i_blocks = (inode->i_size + 511) >> 9; -- inode->i_ctime = inode->i_mtime = ri->ctime; -- if (!datalen) { -- printk(KERN_WARNING "Eep. We didn't actually write any bloody data\n"); -- ret = -EIO; -- SetPageError(pg); -- break; -+ -+ inode->i_ctime = inode->i_mtime = ITIME(je32_to_cpu(ri->ctime)); - } -- D1(printk(KERN_DEBUG "increasing writtenlen by %d\n", datalen)); -- writtenlen += datalen; -- file_ofs += datalen; -- writelen -= datalen; - } - - jffs2_free_raw_inode(ri); - -- if (writtenlen < end) { -+ if (start+writtenlen < end) { - /* generic_file_write has written more to the page cache than we've - actually written to the medium. Mark the page !Uptodate so that - it gets reread */ -@@ -545,13 +270,7 @@ - SetPageError(pg); - ClearPageUptodate(pg); - } -- if (writtenlen <= start) { -- /* We didn't even get to the start of the affected part */ -- ret = ret?ret:-ENOSPC; -- D1(printk(KERN_DEBUG "jffs2_commit_write(): Only %x bytes written to page. start (%x) not reached, returning %d\n", writtenlen, start, ret)); -- } -- writtenlen = min(end-start, writtenlen-start); - -- D1(printk(KERN_DEBUG "jffs2_commit_write() returning %d. nrpages is %ld\n",writtenlen?writtenlen:ret, inode->i_mapping->nrpages)); -+ D1(printk(KERN_DEBUG "jffs2_commit_write() returning %d\n",writtenlen?writtenlen:ret)); - return writtenlen?writtenlen:ret; - } -diff -Nurb linux-mips-2.4.27/fs/jffs2/fs.c linux/fs/jffs2/fs.c ---- linux-mips-2.4.27/fs/jffs2/fs.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/fs.c 2004-11-19 10:25:12.102168936 +0100 -@@ -0,0 +1,618 @@ -+/* -+ * JFFS2 -- Journalling Flash File System, Version 2. -+ * -+ * Copyright (C) 2001-2003 Red Hat, Inc. -+ * -+ * Created by David Woodhouse -+ * -+ * For licensing information, see the file 'LICENCE' in this directory. -+ * -+ * $Id$ -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "nodelist.h" -+ -+ -+static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) -+{ -+ struct jffs2_full_dnode *old_metadata, *new_metadata; -+ struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -+ struct jffs2_raw_inode *ri; -+ unsigned short dev; -+ unsigned char *mdata = NULL; -+ int mdatalen = 0; -+ unsigned int ivalid; -+ uint32_t phys_ofs, alloclen; -+ int ret; -+ D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); -+ ret = inode_change_ok(inode, iattr); -+ if (ret) -+ return ret; -+ -+ /* Special cases - we don't want more than one data node -+ for these types on the medium at any time. So setattr -+ must read the original data associated with the node -+ (i.e. the device numbers or the target name) and write -+ it out again with the appropriate data attached */ -+ if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { -+ /* For these, we don't actually need to read the old node */ -+ dev = old_encode_dev(inode->i_rdev); -+ mdata = (char *)&dev; -+ mdatalen = sizeof(dev); -+ D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen)); -+ } else if (S_ISLNK(inode->i_mode)) { -+ mdatalen = f->metadata->size; -+ mdata = kmalloc(f->metadata->size, GFP_USER); -+ if (!mdata) -+ return -ENOMEM; -+ ret = jffs2_read_dnode(c, f->metadata, mdata, 0, mdatalen); -+ if (ret) { -+ kfree(mdata); -+ return ret; -+ } -+ D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen)); -+ } -+ -+ ri = jffs2_alloc_raw_inode(); -+ if (!ri) { -+ if (S_ISLNK(inode->i_mode)) -+ kfree(mdata); -+ return -ENOMEM; -+ } -+ -+ ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL); -+ if (ret) { -+ jffs2_free_raw_inode(ri); -+ if (S_ISLNK(inode->i_mode & S_IFMT)) -+ kfree(mdata); -+ return ret; -+ } -+ down(&f->sem); -+ ivalid = iattr->ia_valid; -+ -+ ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -+ ri->totlen = cpu_to_je32(sizeof(*ri) + mdatalen); -+ ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); -+ -+ ri->ino = cpu_to_je32(inode->i_ino); -+ ri->version = cpu_to_je32(++f->highest_version); -+ -+ ri->uid = cpu_to_je16((ivalid & ATTR_UID)?iattr->ia_uid:inode->i_uid); -+ ri->gid = cpu_to_je16((ivalid & ATTR_GID)?iattr->ia_gid:inode->i_gid); -+ -+ if (ivalid & ATTR_MODE) -+ if (iattr->ia_mode & S_ISGID && -+ !in_group_p(je16_to_cpu(ri->gid)) && !capable(CAP_FSETID)) -+ ri->mode = cpu_to_jemode(iattr->ia_mode & ~S_ISGID); -+ else -+ ri->mode = cpu_to_jemode(iattr->ia_mode); -+ else -+ ri->mode = cpu_to_jemode(inode->i_mode); -+ -+ -+ ri->isize = cpu_to_je32((ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size); -+ ri->atime = cpu_to_je32(I_SEC((ivalid & ATTR_ATIME)?iattr->ia_atime:inode->i_atime)); -+ ri->mtime = cpu_to_je32(I_SEC((ivalid & ATTR_MTIME)?iattr->ia_mtime:inode->i_mtime)); -+ ri->ctime = cpu_to_je32(I_SEC((ivalid & ATTR_CTIME)?iattr->ia_ctime:inode->i_ctime)); -+ -+ ri->offset = cpu_to_je32(0); -+ ri->csize = ri->dsize = cpu_to_je32(mdatalen); -+ ri->compr = JFFS2_COMPR_NONE; -+ if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { -+ /* It's an extension. Make it a hole node */ -+ ri->compr = JFFS2_COMPR_ZERO; -+ ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size); -+ ri->offset = cpu_to_je32(inode->i_size); -+ } -+ ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); -+ if (mdatalen) -+ ri->data_crc = cpu_to_je32(crc32(0, mdata, mdatalen)); -+ else -+ ri->data_crc = cpu_to_je32(0); -+ -+ new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, phys_ofs, ALLOC_NORMAL); -+ if (S_ISLNK(inode->i_mode)) -+ kfree(mdata); -+ -+ if (IS_ERR(new_metadata)) { -+ jffs2_complete_reservation(c); -+ jffs2_free_raw_inode(ri); -+ up(&f->sem); -+ return PTR_ERR(new_metadata); -+ } -+ /* It worked. Update the inode */ -+ inode->i_atime = ITIME(je32_to_cpu(ri->atime)); -+ inode->i_ctime = ITIME(je32_to_cpu(ri->ctime)); -+ inode->i_mtime = ITIME(je32_to_cpu(ri->mtime)); -+ inode->i_mode = jemode_to_cpu(ri->mode); -+ inode->i_uid = je16_to_cpu(ri->uid); -+ inode->i_gid = je16_to_cpu(ri->gid); -+ -+ -+ old_metadata = f->metadata; -+ -+ if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) -+ jffs2_truncate_fraglist (c, &f->fragtree, iattr->ia_size); -+ -+ if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { -+ jffs2_add_full_dnode_to_inode(c, f, new_metadata); -+ inode->i_size = iattr->ia_size; -+ f->metadata = NULL; -+ } else { -+ f->metadata = new_metadata; -+ } -+ if (old_metadata) { -+ jffs2_mark_node_obsolete(c, old_metadata->raw); -+ jffs2_free_full_dnode(old_metadata); -+ } -+ jffs2_free_raw_inode(ri); -+ -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ -+ /* We have to do the vmtruncate() without f->sem held, since -+ some pages may be locked and waiting for it in readpage(). -+ We are protected from a simultaneous write() extending i_size -+ back past iattr->ia_size, because do_truncate() holds the -+ generic inode semaphore. */ -+ if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) -+ vmtruncate(inode, iattr->ia_size); -+ -+ return 0; -+} -+ -+int jffs2_setattr(struct dentry *dentry, struct iattr *iattr) -+{ -+ return jffs2_do_setattr(dentry->d_inode, iattr); -+} -+ -+int jffs2_statfs(struct super_block *sb, struct kstatfs *buf) -+{ -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); -+ unsigned long avail; -+ -+ buf->f_type = JFFS2_SUPER_MAGIC; -+ buf->f_bsize = 1 << PAGE_SHIFT; -+ buf->f_blocks = c->flash_size >> PAGE_SHIFT; -+ buf->f_files = 0; -+ buf->f_ffree = 0; -+ buf->f_namelen = JFFS2_MAX_NAME_LEN; -+ -+ spin_lock(&c->erase_completion_lock); -+ -+ avail = c->dirty_size + c->free_size; -+ if (avail > c->sector_size * c->resv_blocks_write) -+ avail -= c->sector_size * c->resv_blocks_write; -+ else -+ avail = 0; -+ -+ buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT; -+ -+ D1(jffs2_dump_block_lists(c)); -+ -+ spin_unlock(&c->erase_completion_lock); -+ -+ return 0; -+} -+ -+ -+void jffs2_clear_inode (struct inode *inode) -+{ -+ /* We can forget about this inode for now - drop all -+ * the nodelists associated with it, etc. -+ */ -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -+ struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); -+ -+ D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); -+ -+ jffs2_do_clear_inode(c, f); -+} -+ -+void jffs2_read_inode (struct inode *inode) -+{ -+ struct jffs2_inode_info *f; -+ struct jffs2_sb_info *c; -+ struct jffs2_raw_inode latest_node; -+ int ret; -+ -+ D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino)); -+ -+ f = JFFS2_INODE_INFO(inode); -+ c = JFFS2_SB_INFO(inode->i_sb); -+ -+ jffs2_init_inode_info(f); -+ -+ ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); -+ -+ if (ret) { -+ make_bad_inode(inode); -+ up(&f->sem); -+ return; -+ } -+ inode->i_mode = jemode_to_cpu(latest_node.mode); -+ inode->i_uid = je16_to_cpu(latest_node.uid); -+ inode->i_gid = je16_to_cpu(latest_node.gid); -+ inode->i_size = je32_to_cpu(latest_node.isize); -+ inode->i_atime = ITIME(je32_to_cpu(latest_node.atime)); -+ inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime)); -+ inode->i_ctime = ITIME(je32_to_cpu(latest_node.ctime)); -+ -+ inode->i_nlink = f->inocache->nlink; -+ -+ inode->i_blksize = PAGE_SIZE; -+ inode->i_blocks = (inode->i_size + 511) >> 9; -+ -+ switch (inode->i_mode & S_IFMT) { -+ jint16_t rdev; -+ -+ case S_IFLNK: -+ inode->i_op = &jffs2_symlink_inode_operations; -+ break; -+ -+ case S_IFDIR: -+ { -+ struct jffs2_full_dirent *fd; -+ -+ for (fd=f->dents; fd; fd = fd->next) { -+ if (fd->type == DT_DIR && fd->ino) -+ inode->i_nlink++; -+ } -+ /* and '..' */ -+ inode->i_nlink++; -+ /* Root dir gets i_nlink 3 for some reason */ -+ if (inode->i_ino == 1) -+ inode->i_nlink++; -+ -+ inode->i_op = &jffs2_dir_inode_operations; -+ inode->i_fop = &jffs2_dir_operations; -+ break; -+ } -+ case S_IFREG: -+ inode->i_op = &jffs2_file_inode_operations; -+ inode->i_fop = &jffs2_file_operations; -+ inode->i_mapping->a_ops = &jffs2_file_address_operations; -+ inode->i_mapping->nrpages = 0; -+ break; -+ -+ case S_IFBLK: -+ case S_IFCHR: -+ /* Read the device numbers from the media */ -+ D1(printk(KERN_DEBUG "Reading device numbers from flash\n")); -+ if (jffs2_read_dnode(c, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) { -+ /* Eep */ -+ printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino); -+ up(&f->sem); -+ jffs2_do_clear_inode(c, f); -+ make_bad_inode(inode); -+ return; -+ } -+ -+ case S_IFSOCK: -+ case S_IFIFO: -+ inode->i_op = &jffs2_file_inode_operations; -+ init_special_inode(inode, inode->i_mode, -+ old_decode_dev((je16_to_cpu(rdev)))); -+ break; -+ -+ default: -+ printk(KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu\n", inode->i_mode, (unsigned long)inode->i_ino); -+ } -+ -+ up(&f->sem); -+ -+ D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n")); -+} -+ -+void jffs2_dirty_inode(struct inode *inode) -+{ -+ struct iattr iattr; -+ -+ if (!(inode->i_state & I_DIRTY_DATASYNC)) { -+ D2(printk(KERN_DEBUG "jffs2_dirty_inode() not calling setattr() for ino #%lu\n", inode->i_ino)); -+ return; -+ } -+ -+ D1(printk(KERN_DEBUG "jffs2_dirty_inode() calling setattr() for ino #%lu\n", inode->i_ino)); -+ -+ iattr.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_MTIME|ATTR_CTIME; -+ iattr.ia_mode = inode->i_mode; -+ iattr.ia_uid = inode->i_uid; -+ iattr.ia_gid = inode->i_gid; -+ iattr.ia_atime = inode->i_atime; -+ iattr.ia_mtime = inode->i_mtime; -+ iattr.ia_ctime = inode->i_ctime; -+ -+ jffs2_do_setattr(inode, &iattr); -+} -+ -+int jffs2_remount_fs (struct super_block *sb, int *flags, char *data) -+{ -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); -+ -+ if (c->flags & JFFS2_SB_FLAG_RO && !(sb->s_flags & MS_RDONLY)) -+ return -EROFS; -+ -+ /* We stop if it was running, then restart if it needs to. -+ This also catches the case where it was stopped and this -+ is just a remount to restart it */ -+ if (!(sb->s_flags & MS_RDONLY)) -+ jffs2_stop_garbage_collect_thread(c); -+ -+ if (!(*flags & MS_RDONLY)) -+ jffs2_start_garbage_collect_thread(c); -+ -+ sb->s_flags = (sb->s_flags & ~MS_RDONLY)|(*flags & MS_RDONLY); -+ -+ return 0; -+} -+ -+void jffs2_write_super (struct super_block *sb) -+{ -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); -+ sb->s_dirt = 0; -+ -+ if (sb->s_flags & MS_RDONLY) -+ return; -+ -+ D1(printk(KERN_DEBUG "jffs2_write_super()\n")); -+ jffs2_garbage_collect_trigger(c); -+ jffs2_erase_pending_blocks(c, 0); -+ jffs2_flush_wbuf_gc(c, 0); -+} -+ -+ -+/* jffs2_new_inode: allocate a new inode and inocache, add it to the hash, -+ fill in the raw_inode while you're at it. */ -+struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri) -+{ -+ struct inode *inode; -+ struct super_block *sb = dir_i->i_sb; -+ struct jffs2_sb_info *c; -+ struct jffs2_inode_info *f; -+ int ret; -+ -+ D1(printk(KERN_DEBUG "jffs2_new_inode(): dir_i %ld, mode 0x%x\n", dir_i->i_ino, mode)); -+ -+ c = JFFS2_SB_INFO(sb); -+ -+ inode = new_inode(sb); -+ -+ if (!inode) -+ return ERR_PTR(-ENOMEM); -+ -+ f = JFFS2_INODE_INFO(inode); -+ jffs2_init_inode_info(f); -+ -+ memset(ri, 0, sizeof(*ri)); -+ /* Set OS-specific defaults for new inodes */ -+ ri->uid = cpu_to_je16(current->fsuid); -+ -+ if (dir_i->i_mode & S_ISGID) { -+ ri->gid = cpu_to_je16(dir_i->i_gid); -+ if (S_ISDIR(mode)) -+ mode |= S_ISGID; -+ } else { -+ ri->gid = cpu_to_je16(current->fsgid); -+ } -+ ri->mode = cpu_to_jemode(mode); -+ ret = jffs2_do_new_inode (c, f, mode, ri); -+ if (ret) { -+ make_bad_inode(inode); -+ iput(inode); -+ return ERR_PTR(ret); -+ } -+ inode->i_nlink = 1; -+ inode->i_ino = je32_to_cpu(ri->ino); -+ inode->i_mode = jemode_to_cpu(ri->mode); -+ inode->i_gid = je16_to_cpu(ri->gid); -+ inode->i_uid = je16_to_cpu(ri->uid); -+ inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME; -+ ri->atime = ri->mtime = ri->ctime = cpu_to_je32(I_SEC(inode->i_mtime)); -+ -+ inode->i_blksize = PAGE_SIZE; -+ inode->i_blocks = 0; -+ inode->i_size = 0; -+ -+ insert_inode_hash(inode); -+ -+ return inode; -+} -+ -+ -+int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) -+{ -+ struct jffs2_sb_info *c; -+ struct inode *root_i; -+ int ret; -+ size_t blocks; -+ -+ c = JFFS2_SB_INFO(sb); -+ -+ c->flash_size = c->mtd->size; -+ -+ /* -+ * Check, if we have to concatenate physical blocks to larger virtual blocks -+ * to reduce the memorysize for c->blocks. (kmalloc allows max. 128K allocation) -+ */ -+ blocks = c->flash_size / c->mtd->erasesize; -+ while ((blocks * sizeof (struct jffs2_eraseblock)) > (128 * 1024)) -+ blocks >>= 1; -+ -+ c->sector_size = c->flash_size / blocks; -+ if (c->sector_size != c->mtd->erasesize) -+ printk(KERN_INFO "jffs2: Erase block size too small (%dKiB). Using virtual blocks size (%dKiB) instead\n", -+ c->mtd->erasesize / 1024, c->sector_size / 1024); -+ -+ if (c->flash_size < 5*c->sector_size) { -+ printk(KERN_ERR "jffs2: Too few erase blocks (%d)\n", c->flash_size / c->sector_size); -+ return -EINVAL; -+ } -+ -+ c->cleanmarker_size = sizeof(struct jffs2_unknown_node); -+ /* Joern -- stick alignment for weird 8-byte-page flash here */ -+ -+ if (jffs2_cleanmarker_oob(c)) { -+ /* NAND (or other bizarre) flash... do setup accordingly */ -+ ret = jffs2_nand_flash_setup(c); -+ if (ret) -+ return ret; -+ } -+ -+ c->inocache_list = kmalloc(INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *), GFP_KERNEL); -+ if (!c->inocache_list) { -+ ret = -ENOMEM; -+ goto out_wbuf; -+ } -+ memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *)); -+ -+ if ((ret = jffs2_do_mount_fs(c))) -+ goto out_inohash; -+ -+ ret = -EINVAL; -+ -+ D1(printk(KERN_DEBUG "jffs2_do_fill_super(): Getting root inode\n")); -+ root_i = iget(sb, 1); -+ if (is_bad_inode(root_i)) { -+ D1(printk(KERN_WARNING "get root inode failed\n")); -+ goto out_nodes; -+ } -+ -+ D1(printk(KERN_DEBUG "jffs2_do_fill_super(): d_alloc_root()\n")); -+ sb->s_root = d_alloc_root(root_i); -+ if (!sb->s_root) -+ goto out_root_i; -+ -+#if LINUX_VERSION_CODE >= 0x20403 -+ sb->s_maxbytes = 0xFFFFFFFF; -+#endif -+ sb->s_blocksize = PAGE_CACHE_SIZE; -+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT; -+ sb->s_magic = JFFS2_SUPER_MAGIC; -+ if (!(sb->s_flags & MS_RDONLY)) -+ jffs2_start_garbage_collect_thread(c); -+ return 0; -+ -+ out_root_i: -+ iput(root_i); -+ out_nodes: -+ jffs2_free_ino_caches(c); -+ jffs2_free_raw_node_refs(c); -+ kfree(c->blocks); -+ out_inohash: -+ kfree(c->inocache_list); -+ out_wbuf: -+ jffs2_nand_flash_cleanup(c); -+ -+ return ret; -+} -+ -+void jffs2_gc_release_inode(struct jffs2_sb_info *c, -+ struct jffs2_inode_info *f) -+{ -+ iput(OFNI_EDONI_2SFFJ(f)); -+} -+ -+struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, -+ int inum, int nlink) -+{ -+ struct inode *inode; -+ struct jffs2_inode_cache *ic; -+ if (!nlink) { -+ /* The inode has zero nlink but its nodes weren't yet marked -+ obsolete. This has to be because we're still waiting for -+ the final (close() and) iput() to happen. -+ -+ There's a possibility that the final iput() could have -+ happened while we were contemplating. In order to ensure -+ that we don't cause a new read_inode() (which would fail) -+ for the inode in question, we use ilookup() in this case -+ instead of iget(). -+ -+ The nlink can't _become_ zero at this point because we're -+ holding the alloc_sem, and jffs2_do_unlink() would also -+ need that while decrementing nlink on any inode. -+ */ -+ inode = ilookup(OFNI_BS_2SFFJ(c), inum); -+ if (!inode) { -+ D1(printk(KERN_DEBUG "ilookup() failed for ino #%u; inode is probably deleted.\n", -+ inum)); -+ -+ spin_lock(&c->inocache_lock); -+ ic = jffs2_get_ino_cache(c, inum); -+ if (!ic) { -+ D1(printk(KERN_DEBUG "Inode cache for ino #%u is gone.\n", inum)); -+ spin_unlock(&c->inocache_lock); -+ return NULL; -+ } -+ if (ic->state != INO_STATE_CHECKEDABSENT) { -+ /* Wait for progress. Don't just loop */ -+ D1(printk(KERN_DEBUG "Waiting for ino #%u in state %d\n", -+ ic->ino, ic->state)); -+ sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); -+ } else { -+ spin_unlock(&c->inocache_lock); -+ } -+ -+ return NULL; -+ } -+ } else { -+ /* Inode has links to it still; they're not going away because -+ jffs2_do_unlink() would need the alloc_sem and we have it. -+ Just iget() it, and if read_inode() is necessary that's OK. -+ */ -+ inode = iget(OFNI_BS_2SFFJ(c), inum); -+ if (!inode) -+ return ERR_PTR(-ENOMEM); -+ } -+ if (is_bad_inode(inode)) { -+ printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u. nlink %d\n", -+ inum, nlink); -+ /* NB. This will happen again. We need to do something appropriate here. */ -+ iput(inode); -+ return ERR_PTR(-EIO); -+ } -+ -+ return JFFS2_INODE_INFO(inode); -+} -+ -+unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, -+ struct jffs2_inode_info *f, -+ unsigned long offset, -+ unsigned long *priv) -+{ -+ struct inode *inode = OFNI_EDONI_2SFFJ(f); -+ struct page *pg; -+ -+ pg = read_cache_page(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, -+ (void *)jffs2_do_readpage_unlock, inode); -+ if (IS_ERR(pg)) -+ return (void *)pg; -+ -+ *priv = (unsigned long)pg; -+ return kmap(pg); -+} -+ -+void jffs2_gc_release_page(struct jffs2_sb_info *c, -+ unsigned char *ptr, -+ unsigned long *priv) -+{ -+ struct page *pg = (void *)*priv; -+ -+ kunmap(pg); -+ page_cache_release(pg); -+} -diff -Nurb linux-mips-2.4.27/fs/jffs2/gc.c linux/fs/jffs2/gc.c ---- linux-mips-2.4.27/fs/jffs2/gc.c 2003-11-17 02:07:44.000000000 +0100 -+++ linux/fs/jffs2/gc.c 2004-11-19 10:25:12.104168632 +0100 -@@ -1,76 +1,67 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include - #include - #include --#include --#include --#include - #include --#include "nodelist.h" - #include -+#include -+#include -+#include "nodelist.h" - -+static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, -+ struct jffs2_inode_cache *ic, -+ struct jffs2_raw_node_ref *raw); - static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dnode *fd); -+ struct jffs2_inode_info *f, struct jffs2_full_dnode *fd); - static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dirent *fd); -+ struct jffs2_inode_info *f, struct jffs2_full_dirent *fd); - static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dirent *fd); -+ struct jffs2_inode_info *f, struct jffs2_full_dirent *fd); - static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *indeo, struct jffs2_full_dnode *fn, -- __u32 start, __u32 end); -+ struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, -+ uint32_t start, uint32_t end); - static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dnode *fn, -- __u32 start, __u32 end); -+ struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, -+ uint32_t start, uint32_t end); -+static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_node_ref *raw, struct jffs2_inode_info *f); - - /* Called with erase_completion_lock held */ - static struct jffs2_eraseblock *jffs2_find_gc_block(struct jffs2_sb_info *c) - { - struct jffs2_eraseblock *ret; - struct list_head *nextlist = NULL; -+ int n = jiffies % 128; - - /* Pick an eraseblock to garbage collect next. This is where we'll - put the clever wear-levelling algorithms. Eventually. */ -- if (!list_empty(&c->bad_used_list) && c->nr_free_blocks > JFFS2_RESERVED_BLOCKS_GCBAD) { -+ /* We possibly want to favour the dirtier blocks more when the -+ number of free blocks is low. */ -+ if (!list_empty(&c->bad_used_list) && c->nr_free_blocks > c->resv_blocks_gcbad) { - D1(printk(KERN_DEBUG "Picking block from bad_used_list to GC next\n")); - nextlist = &c->bad_used_list; -- } else if (jiffies % 100 && !list_empty(&c->dirty_list)) { -- /* Most of the time, pick one off the dirty list */ -+ } else if (n < 50 && !list_empty(&c->erasable_list)) { -+ /* Note that most of them will have gone directly to be erased. -+ So don't favour the erasable_list _too_ much. */ -+ D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next\n")); -+ nextlist = &c->erasable_list; -+ } else if (n < 110 && !list_empty(&c->very_dirty_list)) { -+ /* Most of the time, pick one off the very_dirty list */ -+ D1(printk(KERN_DEBUG "Picking block from very_dirty_list to GC next\n")); -+ nextlist = &c->very_dirty_list; -+ } else if (n < 126 && !list_empty(&c->dirty_list)) { - D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next\n")); - nextlist = &c->dirty_list; - } else if (!list_empty(&c->clean_list)) { -@@ -80,9 +71,16 @@ - D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next (clean_list was empty)\n")); - - nextlist = &c->dirty_list; -+ } else if (!list_empty(&c->very_dirty_list)) { -+ D1(printk(KERN_DEBUG "Picking block from very_dirty_list to GC next (clean_list and dirty_list were empty)\n")); -+ nextlist = &c->very_dirty_list; -+ } else if (!list_empty(&c->erasable_list)) { -+ D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next (clean_list and {very_,}dirty_list were empty)\n")); -+ -+ nextlist = &c->erasable_list; - } else { -- /* Eep. Both were empty */ -- printk(KERN_NOTICE "jffs2: No clean _or_ dirty blocks to GC from! Where are they all?\n"); -+ /* Eep. All were empty */ -+ printk(KERN_NOTICE "jffs2: No clean, dirty _or_ erasable blocks to GC from! Where are they all?\n"); - return NULL; - } - -@@ -94,6 +92,17 @@ - printk(KERN_WARNING "Eep. ret->gc_node for block at 0x%08x is NULL\n", ret->offset); - BUG(); - } -+ -+ /* Have we accidentally picked a clean block with wasted space ? */ -+ if (ret->wasted_size) { -+ D1(printk(KERN_DEBUG "Converting wasted_size %08x to dirty_size\n", ret->wasted_size)); -+ ret->dirty_size += ret->wasted_size; -+ c->wasted_size -= ret->wasted_size; -+ c->dirty_size += ret->wasted_size; -+ ret->wasted_size = 0; -+ } -+ -+ D1(jffs2_dump_block_lists(c)); - return ret; - } - -@@ -103,21 +112,90 @@ - */ - int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) - { -- struct jffs2_eraseblock *jeb; - struct jffs2_inode_info *f; -- struct jffs2_raw_node_ref *raw; -- struct jffs2_node_frag *frag; -- struct jffs2_full_dnode *fn = NULL; -- struct jffs2_full_dirent *fd; - struct jffs2_inode_cache *ic; -- __u32 start = 0, end = 0, nrfrags = 0; -- struct inode *inode; -- int ret = 0; -+ struct jffs2_eraseblock *jeb; -+ struct jffs2_raw_node_ref *raw; -+ int ret = 0, inum, nlink; - - if (down_interruptible(&c->alloc_sem)) - return -EINTR; - -- spin_lock_bh(&c->erase_completion_lock); -+ for (;;) { -+ spin_lock(&c->erase_completion_lock); -+ if (!c->unchecked_size) -+ break; -+ -+ /* We can't start doing GC yet. We haven't finished checking -+ the node CRCs etc. Do it now. */ -+ -+ /* checked_ino is protected by the alloc_sem */ -+ if (c->checked_ino > c->highest_ino) { -+ printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", -+ c->unchecked_size); -+ D1(jffs2_dump_block_lists(c)); -+ spin_unlock(&c->erase_completion_lock); -+ BUG(); -+ } -+ -+ spin_unlock(&c->erase_completion_lock); -+ -+ spin_lock(&c->inocache_lock); -+ -+ ic = jffs2_get_ino_cache(c, c->checked_ino++); -+ -+ if (!ic) { -+ spin_unlock(&c->inocache_lock); -+ continue; -+ } -+ -+ if (!ic->nlink) { -+ D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n", -+ ic->ino)); -+ spin_unlock(&c->inocache_lock); -+ continue; -+ } -+ switch(ic->state) { -+ case INO_STATE_CHECKEDABSENT: -+ case INO_STATE_PRESENT: -+ D1(printk(KERN_DEBUG "Skipping ino #%u already checked\n", ic->ino)); -+ spin_unlock(&c->inocache_lock); -+ continue; -+ -+ case INO_STATE_GC: -+ case INO_STATE_CHECKING: -+ printk(KERN_WARNING "Inode #%u is in state %d during CRC check phase!\n", ic->ino, ic->state); -+ spin_unlock(&c->inocache_lock); -+ BUG(); -+ -+ case INO_STATE_READING: -+ /* We need to wait for it to finish, lest we move on -+ and trigger the BUG() above while we haven't yet -+ finished checking all its nodes */ -+ D1(printk(KERN_DEBUG "Waiting for ino #%u to finish reading\n", ic->ino)); -+ up(&c->alloc_sem); -+ sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); -+ return 0; -+ -+ default: -+ BUG(); -+ -+ case INO_STATE_UNCHECKED: -+ ; -+ } -+ ic->state = INO_STATE_CHECKING; -+ spin_unlock(&c->inocache_lock); -+ -+ D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() triggering inode scan of ino#%u\n", ic->ino)); -+ -+ ret = jffs2_do_crccheck_inode(c, ic); -+ if (ret) -+ printk(KERN_WARNING "Returned error for crccheck of ino #%u. Expect badness...\n", ic->ino); -+ -+ jffs2_set_inocache_state(c, ic, INO_STATE_CHECKEDABSENT); -+ up(&c->alloc_sem); -+ return ret; -+ } - - /* First, work out which block we're garbage-collecting */ - jeb = c->gcblock; -@@ -127,12 +205,14 @@ - - if (!jeb) { - printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n"); -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - up(&c->alloc_sem); - return -EIO; - } - -- D1(printk(KERN_DEBUG "garbage collect from block at phys 0x%08x\n", jeb->offset)); -+ D1(printk(KERN_DEBUG "GC from block %08x, used_size %08x, dirty_size %08x, free_size %08x\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size)); -+ D1(if (c->nextblock) -+ printk(KERN_DEBUG "Nextblock at %08x, used_size %08x, dirty_size %08x, wasted_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->free_size)); - - if (!jeb->used_size) { - up(&c->alloc_sem); -@@ -141,92 +221,211 @@ - - raw = jeb->gc_node; - -- while(raw->flash_offset & 1) { -- D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", raw->flash_offset &~3)); -- jeb->gc_node = raw = raw->next_phys; -- if (!raw) { -+ while(ref_obsolete(raw)) { -+ D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw))); -+ raw = raw->next_phys; -+ if (unlikely(!raw)) { - printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n"); - printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size); -- spin_unlock_bh(&c->erase_completion_lock); -+ jeb->gc_node = raw; -+ spin_unlock(&c->erase_completion_lock); - up(&c->alloc_sem); - BUG(); - } - } -- D1(printk(KERN_DEBUG "Going to garbage collect node at 0x%08x\n", raw->flash_offset &~3)); -+ jeb->gc_node = raw; -+ -+ D1(printk(KERN_DEBUG "Going to garbage collect node at 0x%08x\n", ref_offset(raw))); -+ - if (!raw->next_in_ino) { - /* Inode-less node. Clean marker, snapshot or something like that */ -- spin_unlock_bh(&c->erase_completion_lock); -+ /* FIXME: If it's something that needs to be copied, including something -+ we don't grok that has JFFS2_NODETYPE_RWCOMPAT_COPY, we should do so */ -+ spin_unlock(&c->erase_completion_lock); - jffs2_mark_node_obsolete(c, raw); - up(&c->alloc_sem); - goto eraseit_lock; - } - - ic = jffs2_raw_ref_to_ic(raw); -- D1(printk(KERN_DEBUG "Inode number is #%u\n", ic->ino)); -- -- spin_unlock_bh(&c->erase_completion_lock); - -- D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass collecting from block @0x%08x. Node @0x%08x, ino #%u\n", jeb->offset, raw->flash_offset&~3, ic->ino)); -- if (!ic->nlink) { -- /* The inode has zero nlink but its nodes weren't yet marked -- obsolete. This has to be because we're still waiting for -- the final (close() and) iput() to happen. -- -- There's a possibility that the final iput() could have -- happened while we were contemplating. In order to ensure -- that we don't cause a new read_inode() (which would fail) -- for the inode in question, we use ilookup() in this case -- instead of iget(). -- -- The nlink can't _become_ zero at this point because we're -- holding the alloc_sem, and jffs2_do_unlink() would also -- need that while decrementing nlink on any inode. -+ /* We need to hold the inocache. Either the erase_completion_lock or -+ the inocache_lock are sufficient; we trade down since the inocache_lock -+ causes less contention. */ -+ spin_lock(&c->inocache_lock); -+ -+ spin_unlock(&c->erase_completion_lock); -+ -+ D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass collecting from block @0x%08x. Node @0x%08x(%d), ino #%u\n", jeb->offset, ref_offset(raw), ref_flags(raw), ic->ino)); -+ -+ /* Three possibilities: -+ 1. Inode is already in-core. We must iget it and do proper -+ updating to its fragtree, etc. -+ 2. Inode is not in-core, node is REF_PRISTINE. We lock the -+ inocache to prevent a read_inode(), copy the node intact. -+ 3. Inode is not in-core, node is not pristine. We must iget() -+ and take the slow path. - */ -- inode = ilookup(OFNI_BS_2SFFJ(c), ic->ino); -- if (!inode) { -- D1(printk(KERN_DEBUG "ilookup() failed for ino #%u; inode is probably deleted.\n", -+ -+ switch(ic->state) { -+ case INO_STATE_CHECKEDABSENT: -+ /* It's been checked, but it's not currently in-core. -+ We can just copy any pristine nodes, but have -+ to prevent anyone else from doing read_inode() while -+ we're at it, so we set the state accordingly */ -+ if (ref_flags(raw) == REF_PRISTINE) -+ ic->state = INO_STATE_GC; -+ else { -+ D1(printk(KERN_DEBUG "Ino #%u is absent but node not REF_PRISTINE. Reading.\n", - ic->ino)); -- up(&c->alloc_sem); -- return 0; - } -- } else { -- /* Inode has links to it still; they're not going away because -- jffs2_do_unlink() would need the alloc_sem and we have it. -- Just iget() it, and if read_inode() is necessary that's OK. -+ break; -+ -+ case INO_STATE_PRESENT: -+ /* It's in-core. GC must iget() it. */ -+ break; -+ -+ case INO_STATE_UNCHECKED: -+ case INO_STATE_CHECKING: -+ case INO_STATE_GC: -+ /* Should never happen. We should have finished checking -+ by the time we actually start doing any GC, and since -+ we're holding the alloc_sem, no other garbage collection -+ can happen. - */ -- inode = iget(OFNI_BS_2SFFJ(c), ic->ino); -- if (!inode) { -+ printk(KERN_CRIT "Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n", -+ ic->ino, ic->state); - up(&c->alloc_sem); -- return -ENOMEM; -+ spin_unlock(&c->inocache_lock); -+ BUG(); -+ -+ case INO_STATE_READING: -+ /* Someone's currently trying to read it. We must wait for -+ them to finish and then go through the full iget() route -+ to do the GC. However, sometimes read_inode() needs to get -+ the alloc_sem() (for marking nodes invalid) so we must -+ drop the alloc_sem before sleeping. */ -+ -+ up(&c->alloc_sem); -+ D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() waiting for ino #%u in state %d\n", -+ ic->ino, ic->state)); -+ sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); -+ /* And because we dropped the alloc_sem we must start again from the -+ beginning. Ponder chance of livelock here -- we're returning success -+ without actually making any progress. -+ -+ Q: What are the chances that the inode is back in INO_STATE_READING -+ again by the time we next enter this function? And that this happens -+ enough times to cause a real delay? -+ -+ A: Small enough that I don't care :) -+ */ -+ return 0; - } -+ -+ /* OK. Now if the inode is in state INO_STATE_GC, we are going to copy the -+ node intact, and we don't have to muck about with the fragtree etc. -+ because we know it's not in-core. If it _was_ in-core, we go through -+ all the iget() crap anyway */ -+ -+ if (ic->state == INO_STATE_GC) { -+ spin_unlock(&c->inocache_lock); -+ -+ ret = jffs2_garbage_collect_pristine(c, ic, raw); -+ -+ spin_lock(&c->inocache_lock); -+ ic->state = INO_STATE_CHECKEDABSENT; -+ wake_up(&c->inocache_wq); -+ -+ if (ret != -EBADFD) { -+ spin_unlock(&c->inocache_lock); -+ goto release_sem; - } -- if (is_bad_inode(inode)) { -- printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u\n", ic->ino); -- /* NB. This will happen again. We need to do something appropriate here. */ -+ -+ /* Fall through if it wanted us to, with inocache_lock held */ -+ } -+ -+ /* Prevent the fairly unlikely race where the gcblock is -+ entirely obsoleted by the final close of a file which had -+ the only valid nodes in the block, followed by erasure, -+ followed by freeing of the ic because the erased block(s) -+ held _all_ the nodes of that inode.... never been seen but -+ it's vaguely possible. */ -+ -+ inum = ic->ino; -+ nlink = ic->nlink; -+ spin_unlock(&c->inocache_lock); -+ -+ f = jffs2_gc_fetch_inode(c, inum, nlink); -+ if (IS_ERR(f)) -+ return PTR_ERR(f); -+ if (!f) -+ return 0; -+ -+ ret = jffs2_garbage_collect_live(c, jeb, raw, f); -+ -+ jffs2_gc_release_inode(c, f); -+ -+ release_sem: - up(&c->alloc_sem); -- iput(inode); -- return -EIO; -+ -+ eraseit_lock: -+ /* If we've finished this block, start it erasing */ -+ spin_lock(&c->erase_completion_lock); -+ -+ eraseit: -+ if (c->gcblock && !c->gcblock->used_size) { -+ D1(printk(KERN_DEBUG "Block at 0x%08x completely obsoleted by GC. Moving to erase_pending_list\n", c->gcblock->offset)); -+ /* We're GC'ing an empty block? */ -+ list_add_tail(&c->gcblock->list, &c->erase_pending_list); -+ c->gcblock = NULL; -+ c->nr_erasing_blocks++; -+ jffs2_erase_pending_trigger(c); - } -+ spin_unlock(&c->erase_completion_lock); -+ -+ return ret; -+} -+ -+static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_node_ref *raw, struct jffs2_inode_info *f) -+{ -+ struct jffs2_node_frag *frag; -+ struct jffs2_full_dnode *fn = NULL; -+ struct jffs2_full_dirent *fd; -+ uint32_t start = 0, end = 0, nrfrags = 0; -+ int ret = 0; - -- f = JFFS2_INODE_INFO(inode); - down(&f->sem); -+ - /* Now we have the lock for this inode. Check that it's still the one at the head - of the list. */ - -- if (raw->flash_offset & 1) { -+ spin_lock(&c->erase_completion_lock); -+ -+ if (c->gcblock != jeb) { -+ spin_unlock(&c->erase_completion_lock); -+ D1(printk(KERN_DEBUG "GC block is no longer gcblock. Restart\n")); -+ goto upnout; -+ } -+ if (ref_obsolete(raw)) { -+ spin_unlock(&c->erase_completion_lock); - D1(printk(KERN_DEBUG "node to be GC'd was obsoleted in the meantime.\n")); - /* They'll call again */ - goto upnout; - } -+ spin_unlock(&c->erase_completion_lock); -+ - /* OK. Looks safe. And nobody can get us now because we have the semaphore. Move the block */ - if (f->metadata && f->metadata->raw == raw) { - fn = f->metadata; -- ret = jffs2_garbage_collect_metadata(c, jeb, inode, fn); -+ ret = jffs2_garbage_collect_metadata(c, jeb, f, fn); - goto upnout; - } - -- for (frag = f->fraglist; frag; frag = frag->next) { -+ /* FIXME. Read node and do lookup? */ -+ for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) { - if (frag->node && frag->node->raw == raw) { - fn = frag->node; - end = frag->ofs + frag->size; -@@ -237,13 +436,22 @@ - } - } - if (fn) { -+ if (ref_flags(raw) == REF_PRISTINE) { -+ ret = jffs2_garbage_collect_pristine(c, f->inocache, raw); -+ if (!ret) { -+ /* Urgh. Return it sensibly. */ -+ frag->node->raw = f->inocache->nodes; -+ } -+ if (ret != -EBADFD) -+ goto upnout; -+ } - /* We found a datanode. Do the GC */ - if((start >> PAGE_CACHE_SHIFT) < ((end-1) >> PAGE_CACHE_SHIFT)) { - /* It crosses a page boundary. Therefore, it must be a hole. */ -- ret = jffs2_garbage_collect_hole(c, jeb, inode, fn, start, end); -+ ret = jffs2_garbage_collect_hole(c, jeb, f, fn, start, end); - } else { - /* It could still be a hole. But we GC the page this way anyway */ -- ret = jffs2_garbage_collect_dnode(c, jeb, inode, fn, start, end); -+ ret = jffs2_garbage_collect_dnode(c, jeb, f, fn, start, end); - } - goto upnout; - } -@@ -255,12 +463,13 @@ - } - - if (fd && fd->ino) { -- ret = jffs2_garbage_collect_dirent(c, jeb, inode, fd); -+ ret = jffs2_garbage_collect_dirent(c, jeb, f, fd); - } else if (fd) { -- ret = jffs2_garbage_collect_deletion_dirent(c, jeb, inode, fd); -+ ret = jffs2_garbage_collect_deletion_dirent(c, jeb, f, fd); - } else { -- printk(KERN_WARNING "Raw node at 0x%08x wasn't in node lists for ino #%lu\n", raw->flash_offset&~3, inode->i_ino); -- if (raw->flash_offset & 1) { -+ printk(KERN_WARNING "Raw node at 0x%08x wasn't in node lists for ino #%u\n", -+ ref_offset(raw), f->inocache->ino); -+ if (ref_obsolete(raw)) { - printk(KERN_WARNING "But it's obsolete so we don't mind too much\n"); - } else { - ret = -EIO; -@@ -268,46 +477,197 @@ - } - upnout: - up(&f->sem); -- up(&c->alloc_sem); -- iput(inode); - -- eraseit_lock: -- /* If we've finished this block, start it erasing */ -- spin_lock_bh(&c->erase_completion_lock); -+ return ret; -+} - -- eraseit: -- if (c->gcblock && !c->gcblock->used_size) { -- D1(printk(KERN_DEBUG "Block at 0x%08x completely obsoleted by GC. Moving to erase_pending_list\n", c->gcblock->offset)); -- /* We're GC'ing an empty block? */ -- list_add_tail(&c->gcblock->list, &c->erase_pending_list); -- c->gcblock = NULL; -- c->nr_erasing_blocks++; -- jffs2_erase_pending_trigger(c); -+static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, -+ struct jffs2_inode_cache *ic, -+ struct jffs2_raw_node_ref *raw) -+{ -+ union jffs2_node_union *node; -+ struct jffs2_raw_node_ref *nraw; -+ size_t retlen; -+ int ret; -+ uint32_t phys_ofs, alloclen; -+ uint32_t crc, rawlen; -+ int retried = 0; -+ -+ D1(printk(KERN_DEBUG "Going to GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw))); -+ -+ rawlen = ref_totlen(c, c->gcblock, raw); -+ -+ /* Ask for a small amount of space (or the totlen if smaller) because we -+ don't want to force wastage of the end of a block if splitting would -+ work. */ -+ ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN, -+ rawlen), &phys_ofs, &alloclen); -+ if (ret) -+ return ret; -+ -+ if (alloclen < rawlen) { -+ /* Doesn't fit untouched. We'll go the old route and split it */ -+ return -EBADFD; -+ } -+ -+ node = kmalloc(rawlen, GFP_KERNEL); -+ if (!node) -+ return -ENOMEM; -+ -+ ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)node); -+ if (!ret && retlen != rawlen) -+ ret = -EIO; -+ if (ret) -+ goto out_node; -+ -+ crc = crc32(0, node, sizeof(struct jffs2_unknown_node)-4); -+ if (je32_to_cpu(node->u.hdr_crc) != crc) { -+ printk(KERN_WARNING "Header CRC failed on REF_PRISTINE node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ref_offset(raw), je32_to_cpu(node->u.hdr_crc), crc); -+ goto bail; -+ } -+ -+ switch(je16_to_cpu(node->u.nodetype)) { -+ case JFFS2_NODETYPE_INODE: -+ crc = crc32(0, node, sizeof(node->i)-8); -+ if (je32_to_cpu(node->i.node_crc) != crc) { -+ printk(KERN_WARNING "Node CRC failed on REF_PRISTINE data node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ref_offset(raw), je32_to_cpu(node->i.node_crc), crc); -+ goto bail; -+ } -+ -+ if (je32_to_cpu(node->i.dsize)) { -+ crc = crc32(0, node->i.data, je32_to_cpu(node->i.csize)); -+ if (je32_to_cpu(node->i.data_crc) != crc) { -+ printk(KERN_WARNING "Data CRC failed on REF_PRISTINE data node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ref_offset(raw), je32_to_cpu(node->i.data_crc), crc); -+ goto bail; - } -- spin_unlock_bh(&c->erase_completion_lock); -+ } -+ break; -+ -+ case JFFS2_NODETYPE_DIRENT: -+ crc = crc32(0, node, sizeof(node->d)-8); -+ if (je32_to_cpu(node->d.node_crc) != crc) { -+ printk(KERN_WARNING "Node CRC failed on REF_PRISTINE dirent node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ref_offset(raw), je32_to_cpu(node->d.node_crc), crc); -+ goto bail; -+ } -+ -+ if (node->d.nsize) { -+ crc = crc32(0, node->d.name, node->d.nsize); -+ if (je32_to_cpu(node->d.name_crc) != crc) { -+ printk(KERN_WARNING "Name CRC failed on REF_PRISTINE dirent ode at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ref_offset(raw), je32_to_cpu(node->d.name_crc), crc); -+ goto bail; -+ } -+ } -+ break; -+ default: -+ printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", -+ ref_offset(raw), je16_to_cpu(node->u.nodetype)); -+ goto bail; -+ } -+ -+ nraw = jffs2_alloc_raw_node_ref(); -+ if (!nraw) { -+ ret = -ENOMEM; -+ goto out_node; -+ } -+ -+ /* OK, all the CRCs are good; this node can just be copied as-is. */ -+ retry: -+ nraw->flash_offset = phys_ofs; -+ nraw->__totlen = rawlen; -+ nraw->next_phys = NULL; -+ -+ ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node); -+ -+ if (ret || (retlen != rawlen)) { -+ printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n", -+ rawlen, phys_ofs, ret, retlen); -+ if (retlen) { -+ /* Doesn't belong to any inode */ -+ nraw->next_in_ino = NULL; -+ -+ nraw->flash_offset |= REF_OBSOLETE; -+ jffs2_add_physical_node_ref(c, nraw); -+ jffs2_mark_node_obsolete(c, nraw); -+ } else { -+ printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset); -+ jffs2_free_raw_node_ref(nraw); -+ } -+ if (!retried && (nraw == jffs2_alloc_raw_node_ref())) { -+ /* Try to reallocate space and retry */ -+ uint32_t dummy; -+ struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size]; -+ -+ retried = 1; -+ -+ D1(printk(KERN_DEBUG "Retrying failed write of REF_PRISTINE node.\n")); -+ -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ ret = jffs2_reserve_space_gc(c, rawlen, &phys_ofs, &dummy); -+ -+ if (!ret) { -+ D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", phys_ofs)); - -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ goto retry; -+ } -+ D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); -+ jffs2_free_raw_node_ref(nraw); -+ } -+ -+ if (!ret) -+ ret = -EIO; -+ goto out_node; -+ } -+ nraw->flash_offset |= REF_PRISTINE; -+ jffs2_add_physical_node_ref(c, nraw); -+ -+ /* Link into per-inode list. This is safe because of the ic -+ state being INO_STATE_GC. Note that if we're doing this -+ for an inode which is in-code, the 'nraw' pointer is then -+ going to be fetched from ic->nodes by our caller. */ -+ nraw->next_in_ino = ic->nodes; -+ ic->nodes = nraw; -+ -+ jffs2_mark_node_obsolete(c, raw); -+ D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw))); -+ -+ out_node: -+ kfree(node); - return ret; -+ bail: -+ ret = -EBADFD; -+ goto out_node; - } - - static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dnode *fn) -+ struct jffs2_inode_info *f, struct jffs2_full_dnode *fn) - { -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_full_dnode *new_fn; - struct jffs2_raw_inode ri; -- unsigned short dev; -+ jint16_t dev; - char *mdata = NULL, mdatalen = 0; -- __u32 alloclen, phys_ofs; -+ uint32_t alloclen, phys_ofs; - int ret; - -- if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { -+ if (S_ISBLK(JFFS2_F_I_MODE(f)) || -+ S_ISCHR(JFFS2_F_I_MODE(f)) ) { - /* For these, we don't actually need to read the old node */ -- dev = (MAJOR(to_kdev_t(inode->i_rdev)) << 8) | -- MINOR(to_kdev_t(inode->i_rdev)); -+ /* FIXME: for minor or major > 255. */ -+ dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) | -+ JFFS2_F_I_RDEV_MIN(f))); - mdata = (char *)&dev; - mdatalen = sizeof(dev); - D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen)); -- } else if (S_ISLNK(inode->i_mode)) { -+ } else if (S_ISLNK(JFFS2_F_I_MODE(f))) { - mdatalen = fn->size; - mdata = kmalloc(fn->size, GFP_KERNEL); - if (!mdata) { -@@ -326,34 +686,34 @@ - - ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen); - if (ret) { -- printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_metadata failed: %d\n", -+ printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_metadata failed: %d\n", - sizeof(ri)+ mdatalen, ret); - goto out; - } - - memset(&ri, 0, sizeof(ri)); -- ri.magic = JFFS2_MAGIC_BITMASK; -- ri.nodetype = JFFS2_NODETYPE_INODE; -- ri.totlen = sizeof(ri) + mdatalen; -- ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4); -- -- ri.ino = inode->i_ino; -- ri.version = ++f->highest_version; -- ri.mode = inode->i_mode; -- ri.uid = inode->i_uid; -- ri.gid = inode->i_gid; -- ri.isize = inode->i_size; -- ri.atime = inode->i_atime; -- ri.ctime = inode->i_ctime; -- ri.mtime = inode->i_mtime; -- ri.offset = 0; -- ri.csize = mdatalen; -- ri.dsize = mdatalen; -+ ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -+ ri.totlen = cpu_to_je32(sizeof(ri) + mdatalen); -+ ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); -+ -+ ri.ino = cpu_to_je32(f->inocache->ino); -+ ri.version = cpu_to_je32(++f->highest_version); -+ ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f)); -+ ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); -+ ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); -+ ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f)); -+ ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); -+ ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); -+ ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); -+ ri.offset = cpu_to_je32(0); -+ ri.csize = cpu_to_je32(mdatalen); -+ ri.dsize = cpu_to_je32(mdatalen); - ri.compr = JFFS2_COMPR_NONE; -- ri.node_crc = crc32(0, &ri, sizeof(ri)-8); -- ri.data_crc = crc32(0, mdata, mdatalen); -+ ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); -+ ri.data_crc = cpu_to_je32(crc32(0, mdata, mdatalen)); - -- new_fn = jffs2_write_dnode(inode, &ri, mdata, mdatalen, phys_ofs, NULL); -+ new_fn = jffs2_write_dnode(c, f, &ri, mdata, mdatalen, phys_ofs, ALLOC_GC); - - if (IS_ERR(new_fn)) { - printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn)); -@@ -364,41 +724,40 @@ - jffs2_free_full_dnode(fn); - f->metadata = new_fn; - out: -- if (S_ISLNK(inode->i_mode)) -+ if (S_ISLNK(JFFS2_F_I_MODE(f))) - kfree(mdata); - return ret; - } - - static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dirent *fd) -+ struct jffs2_inode_info *f, struct jffs2_full_dirent *fd) - { -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_full_dirent *new_fd; - struct jffs2_raw_dirent rd; -- __u32 alloclen, phys_ofs; -+ uint32_t alloclen, phys_ofs; - int ret; - -- rd.magic = JFFS2_MAGIC_BITMASK; -- rd.nodetype = JFFS2_NODETYPE_DIRENT; -+ rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ rd.nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); - rd.nsize = strlen(fd->name); -- rd.totlen = sizeof(rd) + rd.nsize; -- rd.hdr_crc = crc32(0, &rd, sizeof(struct jffs2_unknown_node)-4); -+ rd.totlen = cpu_to_je32(sizeof(rd) + rd.nsize); -+ rd.hdr_crc = cpu_to_je32(crc32(0, &rd, sizeof(struct jffs2_unknown_node)-4)); - -- rd.pino = inode->i_ino; -- rd.version = ++f->highest_version; -- rd.ino = fd->ino; -- rd.mctime = max(inode->i_mtime, inode->i_ctime); -+ rd.pino = cpu_to_je32(f->inocache->ino); -+ rd.version = cpu_to_je32(++f->highest_version); -+ rd.ino = cpu_to_je32(fd->ino); -+ rd.mctime = cpu_to_je32(max(JFFS2_F_I_MTIME(f), JFFS2_F_I_CTIME(f))); - rd.type = fd->type; -- rd.node_crc = crc32(0, &rd, sizeof(rd)-8); -- rd.name_crc = crc32(0, fd->name, rd.nsize); -+ rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); -+ rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); - - ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen); - if (ret) { -- printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_dirent failed: %d\n", -+ printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dirent failed: %d\n", - sizeof(rd)+rd.nsize, ret); - return ret; - } -- new_fd = jffs2_write_dirent(inode, &rd, fd->name, rd.nsize, phys_ofs, NULL); -+ new_fd = jffs2_write_dirent(c, f, &rd, fd->name, rd.nsize, phys_ofs, ALLOC_GC); - - if (IS_ERR(new_fd)) { - printk(KERN_WARNING "jffs2_write_dirent in garbage_collect_dirent failed: %ld\n", PTR_ERR(new_fd)); -@@ -409,19 +768,98 @@ - } - - static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dirent *fd) -+ struct jffs2_inode_info *f, struct jffs2_full_dirent *fd) - { -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_full_dirent **fdp = &f->dents; - int found = 0; - -- /* FIXME: When we run on NAND flash, we need to work out whether -- this deletion dirent is still needed to actively delete a -- 'real' dirent with the same name that's still somewhere else -- on the flash. For now, we know that we've actually obliterated -- all the older dirents when they became obsolete, so we didn't -- really need to write the deletion to flash in the first place. -- */ -+ /* On a medium where we can't actually mark nodes obsolete -+ pernamently, such as NAND flash, we need to work out -+ whether this deletion dirent is still needed to actively -+ delete a 'real' dirent with the same name that's still -+ somewhere else on the flash. */ -+ if (!jffs2_can_mark_obsolete(c)) { -+ struct jffs2_raw_dirent *rd; -+ struct jffs2_raw_node_ref *raw; -+ int ret; -+ size_t retlen; -+ int name_len = strlen(fd->name); -+ uint32_t name_crc = crc32(0, fd->name, name_len); -+ uint32_t rawlen = ref_totlen(c, jeb, fd->raw); -+ -+ rd = kmalloc(rawlen, GFP_KERNEL); -+ if (!rd) -+ return -ENOMEM; -+ -+ /* Prevent the erase code from nicking the obsolete node refs while -+ we're looking at them. I really don't like this extra lock but -+ can't see any alternative. Suggestions on a postcard to... */ -+ down(&c->erase_free_sem); -+ -+ for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) { -+ -+ /* We only care about obsolete ones */ -+ if (!(ref_obsolete(raw))) -+ continue; -+ -+ /* Any dirent with the same name is going to have the same length... */ -+ if (ref_totlen(c, NULL, raw) != rawlen) -+ continue; -+ -+ /* Doesn't matter if there's one in the same erase block. We're going to -+ delete it too at the same time. */ -+ if ((raw->flash_offset & ~(c->sector_size-1)) == -+ (fd->raw->flash_offset & ~(c->sector_size-1))) -+ continue; -+ -+ D1(printk(KERN_DEBUG "Check potential deletion dirent at %08x\n", ref_offset(raw))); -+ -+ /* This is an obsolete node belonging to the same directory, and it's of the right -+ length. We need to take a closer look...*/ -+ ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)rd); -+ if (ret) { -+ printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading obsolete node at %08x\n", ret, ref_offset(raw)); -+ /* If we can't read it, we don't need to continue to obsolete it. Continue */ -+ continue; -+ } -+ if (retlen != rawlen) { -+ printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Short read (%zd not %zd) reading header from obsolete node at %08x\n", -+ retlen, rawlen, ref_offset(raw)); -+ continue; -+ } -+ -+ if (je16_to_cpu(rd->nodetype) != JFFS2_NODETYPE_DIRENT) -+ continue; -+ -+ /* If the name CRC doesn't match, skip */ -+ if (je32_to_cpu(rd->name_crc) != name_crc) -+ continue; -+ -+ /* If the name length doesn't match, or it's another deletion dirent, skip */ -+ if (rd->nsize != name_len || !je32_to_cpu(rd->ino)) -+ continue; -+ -+ /* OK, check the actual name now */ -+ if (memcmp(rd->name, fd->name, name_len)) -+ continue; -+ -+ /* OK. The name really does match. There really is still an older node on -+ the flash which our deletion dirent obsoletes. So we have to write out -+ a new deletion dirent to replace it */ -+ up(&c->erase_free_sem); -+ -+ D1(printk(KERN_DEBUG "Deletion dirent at %08x still obsoletes real dirent \"%s\" at %08x for ino #%u\n", -+ ref_offset(fd->raw), fd->name, ref_offset(raw), je32_to_cpu(rd->ino))); -+ kfree(rd); -+ -+ return jffs2_garbage_collect_dirent(c, jeb, f, fd); -+ } -+ -+ up(&c->erase_free_sem); -+ kfree(rd); -+ } -+ -+ /* No need for it any more. Just mark it obsolete and remove it from the list */ - while (*fdp) { - if ((*fdp) == fd) { - found = 1; -@@ -431,7 +869,7 @@ - fdp = &(*fdp)->next; - } - if (!found) { -- printk(KERN_WARNING "Deletion dirent \"%s\" not found in list for ino #%lu\n", fd->name, inode->i_ino); -+ printk(KERN_WARNING "Deletion dirent \"%s\" not found in list for ino #%u\n", fd->name, f->inocache->ino); - } - jffs2_mark_node_obsolete(c, fd->raw); - jffs2_free_full_dirent(fd); -@@ -439,93 +877,95 @@ - } - - static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dnode *fn, -- __u32 start, __u32 end) -+ struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, -+ uint32_t start, uint32_t end) - { -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_raw_inode ri; - struct jffs2_node_frag *frag; - struct jffs2_full_dnode *new_fn; -- __u32 alloclen, phys_ofs; -+ uint32_t alloclen, phys_ofs; - int ret; - -- D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%lu from offset 0x%x to 0x%x\n", -- inode->i_ino, start, end)); -+ D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n", -+ f->inocache->ino, start, end)); - - memset(&ri, 0, sizeof(ri)); - - if(fn->frags > 1) { - size_t readlen; -- __u32 crc; -+ uint32_t crc; - /* It's partially obsoleted by a later write. So we have to - write it out again with the _same_ version as before */ -- ret = c->mtd->read(c->mtd, fn->raw->flash_offset & ~3, sizeof(ri), &readlen, (char *)&ri); -+ ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(ri), &readlen, (char *)&ri); - if (readlen != sizeof(ri) || ret) { -- printk(KERN_WARNING "Node read failed in jffs2_garbage_collect_hole. Ret %d, retlen %d. Data will be lost by writing new hold node\n", ret, readlen); -+ printk(KERN_WARNING "Node read failed in jffs2_garbage_collect_hole. Ret %d, retlen %zd. Data will be lost by writing new hole node\n", ret, readlen); - goto fill; - } -- if (ri.nodetype != JFFS2_NODETYPE_INODE) { -+ if (je16_to_cpu(ri.nodetype) != JFFS2_NODETYPE_INODE) { - printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had node type 0x%04x instead of JFFS2_NODETYPE_INODE(0x%04x)\n", -- fn->raw->flash_offset & ~3, ri.nodetype, JFFS2_NODETYPE_INODE); -+ ref_offset(fn->raw), -+ je16_to_cpu(ri.nodetype), JFFS2_NODETYPE_INODE); - return -EIO; - } -- if (ri.totlen != sizeof(ri)) { -- printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had totlen 0x%x instead of expected 0x%x\n", -- fn->raw->flash_offset & ~3, ri.totlen, sizeof(ri)); -+ if (je32_to_cpu(ri.totlen) != sizeof(ri)) { -+ printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had totlen 0x%x instead of expected 0x%zx\n", -+ ref_offset(fn->raw), -+ je32_to_cpu(ri.totlen), sizeof(ri)); - return -EIO; - } - crc = crc32(0, &ri, sizeof(ri)-8); -- if (crc != ri.node_crc) { -+ if (crc != je32_to_cpu(ri.node_crc)) { - printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had CRC 0x%08x which doesn't match calculated CRC 0x%08x\n", -- fn->raw->flash_offset & ~3, ri.node_crc, crc); -+ ref_offset(fn->raw), -+ je32_to_cpu(ri.node_crc), crc); - /* FIXME: We could possibly deal with this by writing new holes for each frag */ -- printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%lu will be lost\n", -- start, end, inode->i_ino); -+ printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", -+ start, end, f->inocache->ino); - goto fill; - } - if (ri.compr != JFFS2_COMPR_ZERO) { -- printk(KERN_WARNING "jffs2_garbage_collect_hole: Node 0x%08x wasn't a hole node!\n", fn->raw->flash_offset & ~3); -- printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%lu will be lost\n", -- start, end, inode->i_ino); -+ printk(KERN_WARNING "jffs2_garbage_collect_hole: Node 0x%08x wasn't a hole node!\n", ref_offset(fn->raw)); -+ printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", -+ start, end, f->inocache->ino); - goto fill; - } - } else { - fill: -- ri.magic = JFFS2_MAGIC_BITMASK; -- ri.nodetype = JFFS2_NODETYPE_INODE; -- ri.totlen = sizeof(ri); -- ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4); -- -- ri.ino = inode->i_ino; -- ri.version = ++f->highest_version; -- ri.offset = start; -- ri.dsize = end - start; -- ri.csize = 0; -+ ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -+ ri.totlen = cpu_to_je32(sizeof(ri)); -+ ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); -+ -+ ri.ino = cpu_to_je32(f->inocache->ino); -+ ri.version = cpu_to_je32(++f->highest_version); -+ ri.offset = cpu_to_je32(start); -+ ri.dsize = cpu_to_je32(end - start); -+ ri.csize = cpu_to_je32(0); - ri.compr = JFFS2_COMPR_ZERO; - } -- ri.mode = inode->i_mode; -- ri.uid = inode->i_uid; -- ri.gid = inode->i_gid; -- ri.isize = inode->i_size; -- ri.atime = inode->i_atime; -- ri.ctime = inode->i_ctime; -- ri.mtime = inode->i_mtime; -- ri.data_crc = 0; -- ri.node_crc = crc32(0, &ri, sizeof(ri)-8); -+ ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f)); -+ ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); -+ ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); -+ ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f)); -+ ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); -+ ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); -+ ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); -+ ri.data_crc = cpu_to_je32(0); -+ ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); - - ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen); - if (ret) { -- printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_hole failed: %d\n", -+ printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_hole failed: %d\n", - sizeof(ri), ret); - return ret; - } -- new_fn = jffs2_write_dnode(inode, &ri, NULL, 0, phys_ofs, NULL); -+ new_fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_GC); - - if (IS_ERR(new_fn)) { - printk(KERN_WARNING "Error writing new hole node: %ld\n", PTR_ERR(new_fn)); - return PTR_ERR(new_fn); - } -- if (ri.version == f->highest_version) { -+ if (je32_to_cpu(ri.version) == f->highest_version) { - jffs2_add_full_dnode_to_inode(c, f, new_fn); - if (f->metadata) { - jffs2_mark_node_obsolete(c, f->metadata->raw); -@@ -541,12 +981,17 @@ - * number as before. (Except in case of error -- see 'goto fill;' - * above.) - */ -- D1(if(fn->frags <= 1) { -+ D1(if(unlikely(fn->frags <= 1)) { - printk(KERN_WARNING "jffs2_garbage_collect_hole: Replacing fn with %d frag(s) but new ver %d != highest_version %d of ino #%d\n", -- fn->frags, ri.version, f->highest_version, ri.ino); -+ fn->frags, je32_to_cpu(ri.version), f->highest_version, -+ je32_to_cpu(ri.ino)); - }); - -- for (frag = f->fraglist; frag; frag = frag->next) { -+ /* This is a partially-overlapped hole node. Mark it REF_NORMAL not REF_PRISTINE */ -+ mark_ref_normal(new_fn->raw); -+ -+ for (frag = jffs2_lookup_node_frag(&f->fragtree, fn->ofs); -+ frag; frag = frag_next(frag)) { - if (frag->ofs > fn->size + fn->ofs) - break; - if (frag->node == fn) { -@@ -571,49 +1016,146 @@ - } - - static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -- struct inode *inode, struct jffs2_full_dnode *fn, -- __u32 start, __u32 end) -+ struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, -+ uint32_t start, uint32_t end) - { -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_full_dnode *new_fn; - struct jffs2_raw_inode ri; -- __u32 alloclen, phys_ofs, offset, orig_end; -+ uint32_t alloclen, phys_ofs, offset, orig_end, orig_start; - int ret = 0; - unsigned char *comprbuf = NULL, *writebuf; -- struct page *pg; -+ unsigned long pg; - unsigned char *pg_ptr; - -- - memset(&ri, 0, sizeof(ri)); - -- D1(printk(KERN_DEBUG "Writing replacement dnode for ino #%lu from offset 0x%x to 0x%x\n", -- inode->i_ino, start, end)); -+ D1(printk(KERN_DEBUG "Writing replacement dnode for ino #%u from offset 0x%x to 0x%x\n", -+ f->inocache->ino, start, end)); - - orig_end = end; -+ orig_start = start; - -+ if (c->nr_free_blocks + c->nr_erasing_blocks > c->resv_blocks_gcmerge) { -+ /* Attempt to do some merging. But only expand to cover logically -+ adjacent frags if the block containing them is already considered -+ to be dirty. Otherwise we end up with GC just going round in -+ circles dirtying the nodes it already wrote out, especially -+ on NAND where we have small eraseblocks and hence a much higher -+ chance of nodes having to be split to cross boundaries. */ - -- /* If we're looking at the last node in the block we're -- garbage-collecting, we allow ourselves to merge as if the -- block was already erasing. We're likely to be GC'ing a -- partial page, and the next block we GC is likely to have -- the other half of this page right at the beginning, which -- means we'd expand it _then_, as nr_erasing_blocks would have -- increased since we checked, and in doing so would obsolete -- the partial node which we'd have written here. Meaning that -- the GC would churn and churn, and just leave dirty blocks in -- it's wake. -- */ -- if(c->nr_free_blocks + c->nr_erasing_blocks > JFFS2_RESERVED_BLOCKS_GCMERGE - (fn->raw->next_phys?0:1)) { -- /* Shitloads of space */ -- /* FIXME: Integrate this properly with GC calculations */ -- start &= ~(PAGE_CACHE_SIZE-1); -- end = min_t(__u32, start + PAGE_CACHE_SIZE, inode->i_size); -- D1(printk(KERN_DEBUG "Plenty of free space, so expanding to write from offset 0x%x to 0x%x\n", -- start, end)); -- if (end < orig_end) { -- printk(KERN_WARNING "Eep. jffs2_garbage_collect_dnode extended node to write, but it got smaller: start 0x%x, orig_end 0x%x, end 0x%x\n", start, orig_end, end); -- end = orig_end; -+ struct jffs2_node_frag *frag; -+ uint32_t min, max; -+ -+ min = start & ~(PAGE_CACHE_SIZE-1); -+ max = min + PAGE_CACHE_SIZE; -+ -+ frag = jffs2_lookup_node_frag(&f->fragtree, start); -+ -+ /* BUG_ON(!frag) but that'll happen anyway... */ -+ -+ BUG_ON(frag->ofs != start); -+ -+ /* First grow down... */ -+ while((frag = frag_prev(frag)) && frag->ofs >= min) { -+ -+ /* If the previous frag doesn't even reach the beginning, there's -+ excessive fragmentation. Just merge. */ -+ if (frag->ofs > min) { -+ D1(printk(KERN_DEBUG "Expanding down to cover partial frag (0x%x-0x%x)\n", -+ frag->ofs, frag->ofs+frag->size)); -+ start = frag->ofs; -+ continue; -+ } -+ /* OK. This frag holds the first byte of the page. */ -+ if (!frag->node || !frag->node->raw) { -+ D1(printk(KERN_DEBUG "First frag in page is hole (0x%x-0x%x). Not expanding down.\n", -+ frag->ofs, frag->ofs+frag->size)); -+ break; -+ } else { -+ -+ /* OK, it's a frag which extends to the beginning of the page. Does it live -+ in a block which is still considered clean? If so, don't obsolete it. -+ If not, cover it anyway. */ -+ -+ struct jffs2_raw_node_ref *raw = frag->node->raw; -+ struct jffs2_eraseblock *jeb; -+ -+ jeb = &c->blocks[raw->flash_offset / c->sector_size]; -+ -+ if (jeb == c->gcblock) { -+ D1(printk(KERN_DEBUG "Expanding down to cover frag (0x%x-0x%x) in gcblock at %08x\n", -+ frag->ofs, frag->ofs+frag->size, ref_offset(raw))); -+ start = frag->ofs; -+ break; - } -+ if (!ISDIRTY(jeb->dirty_size + jeb->wasted_size)) { -+ D1(printk(KERN_DEBUG "Not expanding down to cover frag (0x%x-0x%x) in clean block %08x\n", -+ frag->ofs, frag->ofs+frag->size, jeb->offset)); -+ break; -+ } -+ -+ D1(printk(KERN_DEBUG "Expanding down to cover frag (0x%x-0x%x) in dirty block %08x\n", -+ frag->ofs, frag->ofs+frag->size, jeb->offset)); -+ start = frag->ofs; -+ break; -+ } -+ } -+ -+ /* ... then up */ -+ -+ /* Find last frag which is actually part of the node we're to GC. */ -+ frag = jffs2_lookup_node_frag(&f->fragtree, end-1); -+ -+ while((frag = frag_next(frag)) && frag->ofs+frag->size <= max) { -+ -+ /* If the previous frag doesn't even reach the beginning, there's lots -+ of fragmentation. Just merge. */ -+ if (frag->ofs+frag->size < max) { -+ D1(printk(KERN_DEBUG "Expanding up to cover partial frag (0x%x-0x%x)\n", -+ frag->ofs, frag->ofs+frag->size)); -+ end = frag->ofs + frag->size; -+ continue; -+ } -+ -+ if (!frag->node || !frag->node->raw) { -+ D1(printk(KERN_DEBUG "Last frag in page is hole (0x%x-0x%x). Not expanding up.\n", -+ frag->ofs, frag->ofs+frag->size)); -+ break; -+ } else { -+ -+ /* OK, it's a frag which extends to the beginning of the page. Does it live -+ in a block which is still considered clean? If so, don't obsolete it. -+ If not, cover it anyway. */ -+ -+ struct jffs2_raw_node_ref *raw = frag->node->raw; -+ struct jffs2_eraseblock *jeb; -+ -+ jeb = &c->blocks[raw->flash_offset / c->sector_size]; -+ -+ if (jeb == c->gcblock) { -+ D1(printk(KERN_DEBUG "Expanding up to cover frag (0x%x-0x%x) in gcblock at %08x\n", -+ frag->ofs, frag->ofs+frag->size, ref_offset(raw))); -+ end = frag->ofs + frag->size; -+ break; -+ } -+ if (!ISDIRTY(jeb->dirty_size + jeb->wasted_size)) { -+ D1(printk(KERN_DEBUG "Not expanding up to cover frag (0x%x-0x%x) in clean block %08x\n", -+ frag->ofs, frag->ofs+frag->size, jeb->offset)); -+ break; -+ } -+ -+ D1(printk(KERN_DEBUG "Expanding up to cover frag (0x%x-0x%x) in dirty block %08x\n", -+ frag->ofs, frag->ofs+frag->size, jeb->offset)); -+ end = frag->ofs + frag->size; -+ break; -+ } -+ } -+ D1(printk(KERN_DEBUG "Expanded dnode to write from (0x%x-0x%x) to (0x%x-0x%x)\n", -+ orig_start, orig_end, start, end)); -+ -+ BUG_ON(end > JFFS2_F_I_SIZE(f)); -+ BUG_ON(end < orig_end); -+ BUG_ON(start > orig_start); - } - - /* First, use readpage() to read the appropriate page into the page cache */ -@@ -623,63 +1165,57 @@ - * page OK. We'll actually write it out again in commit_write, which is a little - * suboptimal, but at least we're correct. - */ -- pg = read_cache_page(inode->i_mapping, start >> PAGE_CACHE_SHIFT, (void *)jffs2_do_readpage_unlock, inode); -+ pg_ptr = jffs2_gc_fetch_page(c, f, start, &pg); - -- if (IS_ERR(pg)) { -- printk(KERN_WARNING "read_cache_page() returned error: %ld\n", PTR_ERR(pg)); -- return PTR_ERR(pg); -+ if (IS_ERR(pg_ptr)) { -+ printk(KERN_WARNING "read_cache_page() returned error: %ld\n", PTR_ERR(pg_ptr)); -+ return PTR_ERR(pg_ptr); - } -- pg_ptr = (char *)kmap(pg); -- comprbuf = kmalloc(end - start, GFP_KERNEL); - - offset = start; - while(offset < orig_end) { -- __u32 datalen; -- __u32 cdatalen; -+ uint32_t datalen; -+ uint32_t cdatalen; - char comprtype = JFFS2_COMPR_NONE; - - ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen); - - if (ret) { -- printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_dnode failed: %d\n", -+ printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dnode failed: %d\n", - sizeof(ri)+ JFFS2_MIN_DATA_LEN, ret); - break; - } -- cdatalen = min(alloclen - sizeof(ri), end - offset); -+ cdatalen = min_t(uint32_t, alloclen - sizeof(ri), end - offset); - datalen = end - offset; - - writebuf = pg_ptr + (offset & (PAGE_CACHE_SIZE -1)); - -- if (comprbuf) { -- comprtype = jffs2_compress(writebuf, comprbuf, &datalen, &cdatalen); -- } -- if (comprtype) { -- writebuf = comprbuf; -- } else { -- datalen = cdatalen; -- } -- ri.magic = JFFS2_MAGIC_BITMASK; -- ri.nodetype = JFFS2_NODETYPE_INODE; -- ri.totlen = sizeof(ri) + cdatalen; -- ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4); -- -- ri.ino = inode->i_ino; -- ri.version = ++f->highest_version; -- ri.mode = inode->i_mode; -- ri.uid = inode->i_uid; -- ri.gid = inode->i_gid; -- ri.isize = inode->i_size; -- ri.atime = inode->i_atime; -- ri.ctime = inode->i_ctime; -- ri.mtime = inode->i_mtime; -- ri.offset = offset; -- ri.csize = cdatalen; -- ri.dsize = datalen; -+ comprtype = jffs2_compress(writebuf, &comprbuf, &datalen, &cdatalen); -+ -+ ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -+ ri.totlen = cpu_to_je32(sizeof(ri) + cdatalen); -+ ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); -+ -+ ri.ino = cpu_to_je32(f->inocache->ino); -+ ri.version = cpu_to_je32(++f->highest_version); -+ ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f)); -+ ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); -+ ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); -+ ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f)); -+ ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); -+ ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); -+ ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); -+ ri.offset = cpu_to_je32(offset); -+ ri.csize = cpu_to_je32(cdatalen); -+ ri.dsize = cpu_to_je32(datalen); - ri.compr = comprtype; -- ri.node_crc = crc32(0, &ri, sizeof(ri)-8); -- ri.data_crc = crc32(0, writebuf, cdatalen); -+ ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); -+ ri.data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); -+ -+ new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, phys_ofs, ALLOC_GC); - -- new_fn = jffs2_write_dnode(inode, &ri, writebuf, cdatalen, phys_ofs, NULL); -+ jffs2_free_comprbuf(comprbuf, writebuf); - - if (IS_ERR(new_fn)) { - printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn)); -@@ -694,12 +1230,8 @@ - f->metadata = NULL; - } - } -- if (comprbuf) kfree(comprbuf); - -- kunmap(pg); -- /* XXX: Does the page get freed automatically? */ -- /* AAA: Judging by the unmount getting stuck in __wait_on_page, nope. */ -- page_cache_release(pg); -+ jffs2_gc_release_page(c, pg_ptr, &pg); - return ret; - } - -diff -Nurb linux-mips-2.4.27/fs/jffs2/ioctl.c linux/fs/jffs2/ioctl.c ---- linux-mips-2.4.27/fs/jffs2/ioctl.c 2001-10-19 03:24:56.000000000 +0200 -+++ linux/fs/jffs2/ioctl.c 2004-11-19 10:25:12.108168024 +0100 -@@ -1,37 +1,13 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - -@@ -42,6 +18,6 @@ - { - /* Later, this will provide for lsattr.jffs2 and chattr.jffs2, which - will include compression support etc. */ -- return -EINVAL; -+ return -ENOTTY; - } - -diff -Nurb linux-mips-2.4.27/fs/jffs2/malloc.c linux/fs/jffs2/malloc.c ---- linux-mips-2.4.27/fs/jffs2/malloc.c 2001-10-19 03:24:56.000000000 +0200 -+++ linux/fs/jffs2/malloc.c 2004-11-19 10:25:12.110167720 +0100 -@@ -1,37 +1,13 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - -@@ -47,6 +23,9 @@ - #define JFFS2_SLAB_POISON 0 - #endif - -+// replace this by #define D3 (x) x for cache debugging -+#define D3(x) -+ - /* These are initialised to NULL in the kernel startup code. - If you're porting to other operating systems, beware */ - static kmem_cache_t *full_dnode_slab; -@@ -57,57 +36,47 @@ - static kmem_cache_t *node_frag_slab; - static kmem_cache_t *inode_cache_slab; - --void jffs2_free_tmp_dnode_info_list(struct jffs2_tmp_dnode_info *tn) --{ -- struct jffs2_tmp_dnode_info *next; -- -- while (tn) { -- next = tn; -- tn = tn->next; -- jffs2_free_full_dnode(next->fn); -- jffs2_free_tmp_dnode_info(next); -- } --} -- --void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd) --{ -- struct jffs2_full_dirent *next; -- -- while (fd) { -- next = fd->next; -- jffs2_free_full_dirent(fd); -- fd = next; -- } --} -- - int __init jffs2_create_slab_caches(void) - { -- full_dnode_slab = kmem_cache_create("jffs2_full_dnode", sizeof(struct jffs2_full_dnode), 0, JFFS2_SLAB_POISON, NULL, NULL); -+ full_dnode_slab = kmem_cache_create("jffs2_full_dnode", -+ sizeof(struct jffs2_full_dnode), -+ 0, JFFS2_SLAB_POISON, NULL, NULL); - if (!full_dnode_slab) - goto err; - -- raw_dirent_slab = kmem_cache_create("jffs2_raw_dirent", sizeof(struct jffs2_raw_dirent), 0, JFFS2_SLAB_POISON, NULL, NULL); -+ raw_dirent_slab = kmem_cache_create("jffs2_raw_dirent", -+ sizeof(struct jffs2_raw_dirent), -+ 0, JFFS2_SLAB_POISON, NULL, NULL); - if (!raw_dirent_slab) - goto err; - -- raw_inode_slab = kmem_cache_create("jffs2_raw_inode", sizeof(struct jffs2_raw_inode), 0, JFFS2_SLAB_POISON, NULL, NULL); -+ raw_inode_slab = kmem_cache_create("jffs2_raw_inode", -+ sizeof(struct jffs2_raw_inode), -+ 0, JFFS2_SLAB_POISON, NULL, NULL); - if (!raw_inode_slab) - goto err; - -- tmp_dnode_info_slab = kmem_cache_create("jffs2_tmp_dnode", sizeof(struct jffs2_tmp_dnode_info), 0, JFFS2_SLAB_POISON, NULL, NULL); -+ tmp_dnode_info_slab = kmem_cache_create("jffs2_tmp_dnode", -+ sizeof(struct jffs2_tmp_dnode_info), -+ 0, JFFS2_SLAB_POISON, NULL, NULL); - if (!tmp_dnode_info_slab) - goto err; - -- raw_node_ref_slab = kmem_cache_create("jffs2_raw_node_ref", sizeof(struct jffs2_raw_node_ref), 0, JFFS2_SLAB_POISON, NULL, NULL); -+ raw_node_ref_slab = kmem_cache_create("jffs2_raw_node_ref", -+ sizeof(struct jffs2_raw_node_ref), -+ 0, JFFS2_SLAB_POISON, NULL, NULL); - if (!raw_node_ref_slab) - goto err; - -- node_frag_slab = kmem_cache_create("jffs2_node_frag", sizeof(struct jffs2_node_frag), 0, JFFS2_SLAB_POISON, NULL, NULL); -+ node_frag_slab = kmem_cache_create("jffs2_node_frag", -+ sizeof(struct jffs2_node_frag), -+ 0, JFFS2_SLAB_POISON, NULL, NULL); - if (!node_frag_slab) - goto err; - -- inode_cache_slab = kmem_cache_create("jffs2_inode_cache", sizeof(struct jffs2_inode_cache), 0, JFFS2_SLAB_POISON, NULL, NULL); -- -+ inode_cache_slab = kmem_cache_create("jffs2_inode_cache", -+ sizeof(struct jffs2_inode_cache), -+ 0, JFFS2_SLAB_POISON, NULL, NULL); - if (inode_cache_slab) - return 0; - err: -@@ -131,7 +100,6 @@ - kmem_cache_destroy(node_frag_slab); - if(inode_cache_slab) - kmem_cache_destroy(inode_cache_slab); -- - } - - struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize) -@@ -146,75 +114,92 @@ - - struct jffs2_full_dnode *jffs2_alloc_full_dnode(void) - { -- void *ret = kmem_cache_alloc(full_dnode_slab, GFP_KERNEL); -+ struct jffs2_full_dnode *ret = kmem_cache_alloc(full_dnode_slab, GFP_KERNEL); -+ D3 (printk (KERN_DEBUG "alloc_full_dnode at %p\n", ret)); - return ret; - } - - void jffs2_free_full_dnode(struct jffs2_full_dnode *x) - { -+ D3 (printk (KERN_DEBUG "free full_dnode at %p\n", x)); - kmem_cache_free(full_dnode_slab, x); - } - - struct jffs2_raw_dirent *jffs2_alloc_raw_dirent(void) - { -- return kmem_cache_alloc(raw_dirent_slab, GFP_KERNEL); -+ struct jffs2_raw_dirent *ret = kmem_cache_alloc(raw_dirent_slab, GFP_KERNEL); -+ D3 (printk (KERN_DEBUG "alloc_raw_dirent\n", ret)); -+ return ret; - } - - void jffs2_free_raw_dirent(struct jffs2_raw_dirent *x) - { -+ D3 (printk (KERN_DEBUG "free_raw_dirent at %p\n", x)); - kmem_cache_free(raw_dirent_slab, x); - } - - struct jffs2_raw_inode *jffs2_alloc_raw_inode(void) - { -- return kmem_cache_alloc(raw_inode_slab, GFP_KERNEL); -+ struct jffs2_raw_inode *ret = kmem_cache_alloc(raw_inode_slab, GFP_KERNEL); -+ D3 (printk (KERN_DEBUG "alloc_raw_inode at %p\n", ret)); -+ return ret; - } - - void jffs2_free_raw_inode(struct jffs2_raw_inode *x) - { -+ D3 (printk (KERN_DEBUG "free_raw_inode at %p\n", x)); - kmem_cache_free(raw_inode_slab, x); - } - - struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void) - { -- return kmem_cache_alloc(tmp_dnode_info_slab, GFP_KERNEL); -+ struct jffs2_tmp_dnode_info *ret = kmem_cache_alloc(tmp_dnode_info_slab, GFP_KERNEL); -+ D3 (printk (KERN_DEBUG "alloc_tmp_dnode_info at %p\n", ret)); -+ return ret; - } - - void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x) - { -+ D3 (printk (KERN_DEBUG "free_tmp_dnode_info at %p\n", x)); - kmem_cache_free(tmp_dnode_info_slab, x); - } - - struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) - { -- return kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); -+ struct jffs2_raw_node_ref *ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); -+ D3 (printk (KERN_DEBUG "alloc_raw_node_ref at %p\n", ret)); -+ return ret; - } - - void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) - { -+ D3 (printk (KERN_DEBUG "free_raw_node_ref at %p\n", x)); - kmem_cache_free(raw_node_ref_slab, x); - } - - struct jffs2_node_frag *jffs2_alloc_node_frag(void) - { -- return kmem_cache_alloc(node_frag_slab, GFP_KERNEL); -+ struct jffs2_node_frag *ret = kmem_cache_alloc(node_frag_slab, GFP_KERNEL); -+ D3 (printk (KERN_DEBUG "alloc_node_frag at %p\n", ret)); -+ return ret; - } - - void jffs2_free_node_frag(struct jffs2_node_frag *x) - { -+ D3 (printk (KERN_DEBUG "free_node_frag at %p\n", x)); - kmem_cache_free(node_frag_slab, x); - } - - struct jffs2_inode_cache *jffs2_alloc_inode_cache(void) - { - struct jffs2_inode_cache *ret = kmem_cache_alloc(inode_cache_slab, GFP_KERNEL); -- D1(printk(KERN_DEBUG "Allocated inocache at %p\n", ret)); -+ D3 (printk(KERN_DEBUG "Allocated inocache at %p\n", ret)); - return ret; - } - - void jffs2_free_inode_cache(struct jffs2_inode_cache *x) - { -- D1(printk(KERN_DEBUG "Freeing inocache at %p\n", x)); -+ D3 (printk(KERN_DEBUG "Freeing inocache at %p\n", x)); - kmem_cache_free(inode_cache_slab, x); - } - -diff -Nurb linux-mips-2.4.27/fs/jffs2/nodelist.c linux/fs/jffs2/nodelist.c ---- linux-mips-2.4.27/fs/jffs2/nodelist.c 2003-07-05 05:23:44.000000000 +0200 -+++ linux/fs/jffs2/nodelist.c 2004-11-19 10:25:12.112167416 +0100 -@@ -1,44 +1,24 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001, 2002 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include --#include -+#include - #include - #include -+#include -+#include -+#include -+#include - #include "nodelist.h" - - void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list) -@@ -78,7 +58,7 @@ - /* Put a new tmp_dnode_info into the list, keeping the list in - order of increasing version - */ --void jffs2_add_tn_to_list(struct jffs2_tmp_dnode_info *tn, struct jffs2_tmp_dnode_info **list) -+static void jffs2_add_tn_to_list(struct jffs2_tmp_dnode_info *tn, struct jffs2_tmp_dnode_info **list) - { - struct jffs2_tmp_dnode_info **prev = list; - -@@ -89,13 +69,37 @@ - *prev = tn; - } - -+static void jffs2_free_tmp_dnode_info_list(struct jffs2_tmp_dnode_info *tn) -+{ -+ struct jffs2_tmp_dnode_info *next; -+ -+ while (tn) { -+ next = tn; -+ tn = tn->next; -+ jffs2_free_full_dnode(next->fn); -+ jffs2_free_tmp_dnode_info(next); -+ } -+} -+ -+static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd) -+{ -+ struct jffs2_full_dirent *next; -+ -+ while (fd) { -+ next = fd->next; -+ jffs2_free_full_dirent(fd); -+ fd = next; -+ } -+} -+ -+ - /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated - with this ino, returning the former in order of version */ - - int jffs2_get_inode_nodes(struct jffs2_sb_info *c, ino_t ino, struct jffs2_inode_info *f, - struct jffs2_tmp_dnode_info **tnp, struct jffs2_full_dirent **fdp, -- __u32 *highest_version, __u32 *latest_mctime, -- __u32 *mctime_ver) -+ uint32_t *highest_version, uint32_t *latest_mctime, -+ uint32_t *mctime_ver) - { - struct jffs2_raw_node_ref *ref = f->inocache->nodes; - struct jffs2_tmp_dnode_info *tn, *ret_tn = NULL; -@@ -109,43 +113,71 @@ - - D1(printk(KERN_DEBUG "jffs2_get_inode_nodes(): ino #%lu\n", ino)); - if (!f->inocache->nodes) { -- printk(KERN_WARNING "Eep. no nodes for ino #%lu\n", ino); -+ printk(KERN_WARNING "Eep. no nodes for ino #%lu\n", (unsigned long)ino); - } -+ -+ spin_lock(&c->erase_completion_lock); -+ - for (ref = f->inocache->nodes; ref && ref->next_in_ino; ref = ref->next_in_ino) { - /* Work out whether it's a data node or a dirent node */ -- if (ref->flash_offset & 1) { -+ if (ref_obsolete(ref)) { - /* FIXME: On NAND flash we may need to read these */ -- D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref->flash_offset &~3)); -+ D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref))); - continue; - } -- err = c->mtd->read(c->mtd, (ref->flash_offset & ~3), min(ref->totlen, sizeof(node)), &retlen, (void *)&node); -+ /* We can hold a pointer to a non-obsolete node without the spinlock, -+ but _obsolete_ nodes may disappear at any time, if the block -+ they're in gets erased */ -+ spin_unlock(&c->erase_completion_lock); -+ -+ cond_resched(); -+ -+ /* FIXME: point() */ -+ err = jffs2_flash_read(c, (ref_offset(ref)), -+ min_t(uint32_t, ref_totlen(c, NULL, ref), sizeof(node)), -+ &retlen, (void *)&node); - if (err) { -- printk(KERN_WARNING "error %d reading node at 0x%08x in get_inode_nodes()\n", err, (ref->flash_offset) & ~3); -+ printk(KERN_WARNING "error %d reading node at 0x%08x in get_inode_nodes()\n", err, ref_offset(ref)); - goto free_out; - } - - - /* Check we've managed to read at least the common node header */ -- if (retlen < min(ref->totlen, sizeof(node.u))) { -+ if (retlen < min_t(uint32_t, ref_totlen(c, NULL, ref), sizeof(node.u))) { - printk(KERN_WARNING "short read in get_inode_nodes()\n"); - err = -EIO; - goto free_out; - } - -- switch (node.u.nodetype) { -+ switch (je16_to_cpu(node.u.nodetype)) { - case JFFS2_NODETYPE_DIRENT: -- D1(printk(KERN_DEBUG "Node at %08x is a dirent node\n", ref->flash_offset &~3)); -+ D1(printk(KERN_DEBUG "Node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref))); -+ if (ref_flags(ref) == REF_UNCHECKED) { -+ printk(KERN_WARNING "BUG: Dirent node at 0x%08x never got checked? How?\n", ref_offset(ref)); -+ BUG(); -+ } - if (retlen < sizeof(node.d)) { - printk(KERN_WARNING "short read in get_inode_nodes()\n"); - err = -EIO; - goto free_out; - } -- if (node.d.version > *highest_version) -- *highest_version = node.d.version; -- if (ref->flash_offset & 1) { -- /* Obsoleted */ -+ /* sanity check */ -+ if (PAD((node.d.nsize + sizeof (node.d))) != PAD(je32_to_cpu (node.d.totlen))) { -+ printk(KERN_NOTICE "jffs2_get_inode_nodes(): Illegal nsize in node at 0x%08x: nsize 0x%02x, totlen %04x\n", -+ ref_offset(ref), node.d.nsize, je32_to_cpu(node.d.totlen)); -+ jffs2_mark_node_obsolete(c, ref); -+ spin_lock(&c->erase_completion_lock); - continue; - } -+ if (je32_to_cpu(node.d.version) > *highest_version) -+ *highest_version = je32_to_cpu(node.d.version); -+ if (ref_obsolete(ref)) { -+ /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ -+ printk(KERN_ERR "Dirent node at 0x%08x became obsolete while we weren't looking\n", -+ ref_offset(ref)); -+ BUG(); -+ } -+ - fd = jffs2_alloc_full_dirent(node.d.nsize+1); - if (!fd) { - err = -ENOMEM; -@@ -153,29 +185,30 @@ - } - memset(fd,0,sizeof(struct jffs2_full_dirent) + node.d.nsize+1); - fd->raw = ref; -- fd->version = node.d.version; -- fd->ino = node.d.ino; -+ fd->version = je32_to_cpu(node.d.version); -+ fd->ino = je32_to_cpu(node.d.ino); - fd->type = node.d.type; - - /* Pick out the mctime of the latest dirent */ - if(fd->version > *mctime_ver) { - *mctime_ver = fd->version; -- *latest_mctime = node.d.mctime; -+ *latest_mctime = je32_to_cpu(node.d.mctime); - } - - /* memcpy as much of the name as possible from the raw - dirent we've already read from the flash - */ - if (retlen > sizeof(struct jffs2_raw_dirent)) -- memcpy(&fd->name[0], &node.d.name[0], min((__u32)node.d.nsize, (retlen-sizeof(struct jffs2_raw_dirent)))); -+ memcpy(&fd->name[0], &node.d.name[0], min_t(uint32_t, node.d.nsize, (retlen-sizeof(struct jffs2_raw_dirent)))); - - /* Do we need to copy any more of the name directly - from the flash? - */ - if (node.d.nsize + sizeof(struct jffs2_raw_dirent) > retlen) { -+ /* FIXME: point() */ - int already = retlen - sizeof(struct jffs2_raw_dirent); - -- err = c->mtd->read(c->mtd, (ref->flash_offset & ~3) + retlen, -+ err = jffs2_flash_read(c, (ref_offset(ref)) + retlen, - node.d.nsize - already, &retlen, &fd->name[already]); - if (!err && retlen != node.d.nsize - already) - err = -EIO; -@@ -196,21 +229,126 @@ - break; - - case JFFS2_NODETYPE_INODE: -- D1(printk(KERN_DEBUG "Node at %08x is a data node\n", ref->flash_offset &~3)); -+ D1(printk(KERN_DEBUG "Node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref))); - if (retlen < sizeof(node.i)) { - printk(KERN_WARNING "read too short for dnode\n"); - err = -EIO; - goto free_out; - } -- if (node.i.version > *highest_version) -- *highest_version = node.i.version; -- D1(printk(KERN_DEBUG "version %d, highest_version now %d\n", node.i.version, *highest_version)); -- -- if (ref->flash_offset & 1) { -- D1(printk(KERN_DEBUG "obsoleted\n")); -- /* Obsoleted */ -+ if (je32_to_cpu(node.i.version) > *highest_version) -+ *highest_version = je32_to_cpu(node.i.version); -+ D1(printk(KERN_DEBUG "version %d, highest_version now %d\n", je32_to_cpu(node.i.version), *highest_version)); -+ -+ if (ref_obsolete(ref)) { -+ /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ -+ printk(KERN_ERR "Inode node at 0x%08x became obsolete while we weren't looking\n", -+ ref_offset(ref)); -+ BUG(); -+ } -+ -+ /* If we've never checked the CRCs on this node, check them now. */ -+ if (ref_flags(ref) == REF_UNCHECKED) { -+ uint32_t crc, len; -+ struct jffs2_eraseblock *jeb; -+ -+ crc = crc32(0, &node, sizeof(node.i)-8); -+ if (crc != je32_to_cpu(node.i.node_crc)) { -+ printk(KERN_NOTICE "jffs2_get_inode_nodes(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ref_offset(ref), je32_to_cpu(node.i.node_crc), crc); -+ jffs2_mark_node_obsolete(c, ref); -+ spin_lock(&c->erase_completion_lock); - continue; - } -+ -+ /* sanity checks */ -+ if ( je32_to_cpu(node.i.offset) > je32_to_cpu(node.i.isize) || -+ PAD(je32_to_cpu(node.i.csize) + sizeof (node.i)) != PAD(je32_to_cpu(node.i.totlen))) { -+ printk(KERN_NOTICE "jffs2_get_inode_nodes(): Inode corrupted at 0x%08x, totlen %d, #ino %d, version %d, isize %d, csize %d, dsize %d \n", -+ ref_offset(ref), je32_to_cpu(node.i.totlen), je32_to_cpu(node.i.ino), -+ je32_to_cpu(node.i.version), je32_to_cpu(node.i.isize), -+ je32_to_cpu(node.i.csize), je32_to_cpu(node.i.dsize)); -+ jffs2_mark_node_obsolete(c, ref); -+ spin_lock(&c->erase_completion_lock); -+ continue; -+ } -+ -+ if (node.i.compr != JFFS2_COMPR_ZERO && je32_to_cpu(node.i.csize)) { -+ unsigned char *buf=NULL; -+ uint32_t pointed = 0; -+#ifndef __ECOS -+ if (c->mtd->point) { -+ err = c->mtd->point (c->mtd, ref_offset(ref) + sizeof(node.i), je32_to_cpu(node.i.csize), -+ &retlen, &buf); -+ if (!err && retlen < je32_to_cpu(node.i.csize)) { -+ D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen)); -+ c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(node.i), je32_to_cpu(node.i.csize)); -+ } else if (err){ -+ D1(printk(KERN_DEBUG "MTD point failed %d\n", err)); -+ } else -+ pointed = 1; /* succefully pointed to device */ -+ } -+#endif -+ if(!pointed){ -+ buf = kmalloc(je32_to_cpu(node.i.csize), GFP_KERNEL); -+ if (!buf) -+ return -ENOMEM; -+ -+ err = jffs2_flash_read(c, ref_offset(ref) + sizeof(node.i), je32_to_cpu(node.i.csize), -+ &retlen, buf); -+ if (!err && retlen != je32_to_cpu(node.i.csize)) -+ err = -EIO; -+ if (err) { -+ kfree(buf); -+ return err; -+ } -+ } -+ crc = crc32(0, buf, je32_to_cpu(node.i.csize)); -+ if(!pointed) -+ kfree(buf); -+#ifndef __ECOS -+ else -+ c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(node.i), je32_to_cpu(node.i.csize)); -+#endif -+ -+ if (crc != je32_to_cpu(node.i.data_crc)) { -+ printk(KERN_NOTICE "jffs2_get_inode_nodes(): Data CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ref_offset(ref), je32_to_cpu(node.i.data_crc), crc); -+ jffs2_mark_node_obsolete(c, ref); -+ spin_lock(&c->erase_completion_lock); -+ continue; -+ } -+ -+ } -+ -+ /* Mark the node as having been checked and fix the accounting accordingly */ -+ spin_lock(&c->erase_completion_lock); -+ jeb = &c->blocks[ref->flash_offset / c->sector_size]; -+ len = ref_totlen(c, jeb, ref); -+ -+ jeb->used_size += len; -+ jeb->unchecked_size -= len; -+ c->used_size += len; -+ c->unchecked_size -= len; -+ -+ /* If node covers at least a whole page, or if it starts at the -+ beginning of a page and runs to the end of the file, or if -+ it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. -+ -+ If it's actually overlapped, it'll get made NORMAL (or OBSOLETE) -+ when the overlapping node(s) get added to the tree anyway. -+ */ -+ if ((je32_to_cpu(node.i.dsize) >= PAGE_CACHE_SIZE) || -+ ( ((je32_to_cpu(node.i.offset)&(PAGE_CACHE_SIZE-1))==0) && -+ (je32_to_cpu(node.i.dsize)+je32_to_cpu(node.i.offset) == je32_to_cpu(node.i.isize)))) { -+ D1(printk(KERN_DEBUG "Marking node at 0x%08x REF_PRISTINE\n", ref_offset(ref))); -+ ref->flash_offset = ref_offset(ref) | REF_PRISTINE; -+ } else { -+ D1(printk(KERN_DEBUG "Marking node at 0x%08x REF_NORMAL\n", ref_offset(ref))); -+ ref->flash_offset = ref_offset(ref) | REF_NORMAL; -+ } -+ spin_unlock(&c->erase_completion_lock); -+ } -+ - tn = jffs2_alloc_tmp_dnode_info(); - if (!tn) { - D1(printk(KERN_DEBUG "alloc tn failed\n")); -@@ -225,36 +363,76 @@ - jffs2_free_tmp_dnode_info(tn); - goto free_out; - } -- tn->version = node.i.version; -- tn->fn->ofs = node.i.offset; -+ tn->version = je32_to_cpu(node.i.version); -+ tn->fn->ofs = je32_to_cpu(node.i.offset); - /* There was a bug where we wrote hole nodes out with - csize/dsize swapped. Deal with it */ -- if (node.i.compr == JFFS2_COMPR_ZERO && !node.i.dsize && node.i.csize) -- tn->fn->size = node.i.csize; -+ if (node.i.compr == JFFS2_COMPR_ZERO && !je32_to_cpu(node.i.dsize) && je32_to_cpu(node.i.csize)) -+ tn->fn->size = je32_to_cpu(node.i.csize); - else // normal case... -- tn->fn->size = node.i.dsize; -+ tn->fn->size = je32_to_cpu(node.i.dsize); - tn->fn->raw = ref; -- D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %04x, dsize %04x\n", ref->flash_offset &~3, node.i.version, node.i.offset, node.i.dsize)); -+ D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %04x, dsize %04x\n", -+ ref_offset(ref), je32_to_cpu(node.i.version), -+ je32_to_cpu(node.i.offset), je32_to_cpu(node.i.dsize))); - jffs2_add_tn_to_list(tn, &ret_tn); - break; - - default: -- switch(node.u.nodetype & JFFS2_COMPAT_MASK) { -+ if (ref_flags(ref) == REF_UNCHECKED) { -+ struct jffs2_eraseblock *jeb; -+ uint32_t len; -+ -+ printk(KERN_ERR "Eep. Unknown node type %04x at %08x was marked REF_UNCHECKED\n", -+ je16_to_cpu(node.u.nodetype), ref_offset(ref)); -+ -+ /* Mark the node as having been checked and fix the accounting accordingly */ -+ spin_lock(&c->erase_completion_lock); -+ jeb = &c->blocks[ref->flash_offset / c->sector_size]; -+ len = ref_totlen(c, jeb, ref); -+ -+ jeb->used_size += len; -+ jeb->unchecked_size -= len; -+ c->used_size += len; -+ c->unchecked_size -= len; -+ -+ mark_ref_normal(ref); -+ spin_unlock(&c->erase_completion_lock); -+ } -+ node.u.nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(node.u.nodetype)); -+ if (crc32(0, &node, sizeof(struct jffs2_unknown_node)-4) != je32_to_cpu(node.u.hdr_crc)) { -+ /* Hmmm. This should have been caught at scan time. */ -+ printk(KERN_ERR "Node header CRC failed at %08x. But it must have been OK earlier.\n", -+ ref_offset(ref)); -+ printk(KERN_ERR "Node was: { %04x, %04x, %08x, %08x }\n", -+ je16_to_cpu(node.u.magic), je16_to_cpu(node.u.nodetype), je32_to_cpu(node.u.totlen), -+ je32_to_cpu(node.u.hdr_crc)); -+ jffs2_mark_node_obsolete(c, ref); -+ } else switch(je16_to_cpu(node.u.nodetype) & JFFS2_COMPAT_MASK) { - case JFFS2_FEATURE_INCOMPAT: -- printk(KERN_NOTICE "Unknown INCOMPAT nodetype %04X at %08X\n", node.u.nodetype, ref->flash_offset & ~3); -+ printk(KERN_NOTICE "Unknown INCOMPAT nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); -+ /* EEP */ -+ BUG(); - break; - case JFFS2_FEATURE_ROCOMPAT: -- printk(KERN_NOTICE "Unknown ROCOMPAT nodetype %04X at %08X\n", node.u.nodetype, ref->flash_offset & ~3); -+ printk(KERN_NOTICE "Unknown ROCOMPAT nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); -+ if (!(c->flags & JFFS2_SB_FLAG_RO)) -+ BUG(); - break; - case JFFS2_FEATURE_RWCOMPAT_COPY: -- printk(KERN_NOTICE "Unknown RWCOMPAT_COPY nodetype %04X at %08X\n", node.u.nodetype, ref->flash_offset & ~3); -+ printk(KERN_NOTICE "Unknown RWCOMPAT_COPY nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); - break; - case JFFS2_FEATURE_RWCOMPAT_DELETE: -- printk(KERN_NOTICE "Unknown RWCOMPAT_DELETE nodetype %04X at %08X\n", node.u.nodetype, ref->flash_offset & ~3); -+ printk(KERN_NOTICE "Unknown RWCOMPAT_DELETE nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); -+ jffs2_mark_node_obsolete(c, ref); - break; - } -+ - } -+ spin_lock(&c->erase_completion_lock); -+ - } -+ spin_unlock(&c->erase_completion_lock); - *tnp = ret_tn; - *fdp = ret_fd; - -@@ -266,19 +444,30 @@ - return err; - } - -+void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state) -+{ -+ spin_lock(&c->inocache_lock); -+ ic->state = state; -+ wake_up(&c->inocache_wq); -+ spin_unlock(&c->inocache_lock); -+} -+ -+/* During mount, this needs no locking. During normal operation, its -+ callers want to do other stuff while still holding the inocache_lock. -+ Rather than introducing special case get_ino_cache functions or -+ callbacks, we just let the caller do the locking itself. */ -+ - struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t ino) - { - struct jffs2_inode_cache *ret; - - D2(printk(KERN_DEBUG "jffs2_get_ino_cache(): ino %u\n", ino)); -- spin_lock (&c->inocache_lock); -+ - ret = c->inocache_list[ino % INOCACHE_HASHSIZE]; - while (ret && ret->ino < ino) { - ret = ret->next; - } - -- spin_unlock(&c->inocache_lock); -- - if (ret && ret->ino != ino) - ret = NULL; - -@@ -299,6 +488,7 @@ - } - new->next = *prev; - *prev = new; -+ - spin_unlock(&c->inocache_lock); - } - -@@ -316,6 +506,7 @@ - if ((*prev) == old) { - *prev = old->next; - } -+ - spin_unlock(&c->inocache_lock); - } - -@@ -352,3 +543,128 @@ - } - } - -+struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset) -+{ -+ /* The common case in lookup is that there will be a node -+ which precisely matches. So we go looking for that first */ -+ struct rb_node *next; -+ struct jffs2_node_frag *prev = NULL; -+ struct jffs2_node_frag *frag = NULL; -+ -+ D2(printk(KERN_DEBUG "jffs2_lookup_node_frag(%p, %d)\n", fragtree, offset)); -+ -+ next = fragtree->rb_node; -+ -+ while(next) { -+ frag = rb_entry(next, struct jffs2_node_frag, rb); -+ -+ D2(printk(KERN_DEBUG "Considering frag %d-%d (%p). left %p, right %p\n", -+ frag->ofs, frag->ofs+frag->size, frag, frag->rb.rb_left, frag->rb.rb_right)); -+ if (frag->ofs + frag->size <= offset) { -+ D2(printk(KERN_DEBUG "Going right from frag %d-%d, before the region we care about\n", -+ frag->ofs, frag->ofs+frag->size)); -+ /* Remember the closest smaller match on the way down */ -+ if (!prev || frag->ofs > prev->ofs) -+ prev = frag; -+ next = frag->rb.rb_right; -+ } else if (frag->ofs > offset) { -+ D2(printk(KERN_DEBUG "Going left from frag %d-%d, after the region we care about\n", -+ frag->ofs, frag->ofs+frag->size)); -+ next = frag->rb.rb_left; -+ } else { -+ D2(printk(KERN_DEBUG "Returning frag %d,%d, matched\n", -+ frag->ofs, frag->ofs+frag->size)); -+ return frag; -+ } -+ } -+ -+ /* Exact match not found. Go back up looking at each parent, -+ and return the closest smaller one */ -+ -+ if (prev) -+ D2(printk(KERN_DEBUG "No match. Returning frag %d,%d, closest previous\n", -+ prev->ofs, prev->ofs+prev->size)); -+ else -+ D2(printk(KERN_DEBUG "Returning NULL, empty fragtree\n")); -+ -+ return prev; -+} -+ -+/* Pass 'c' argument to indicate that nodes should be marked obsolete as -+ they're killed. */ -+void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) -+{ -+ struct jffs2_node_frag *frag; -+ struct jffs2_node_frag *parent; -+ -+ if (!root->rb_node) -+ return; -+ -+ frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb)); -+ -+ while(frag) { -+ if (frag->rb.rb_left) { -+ D2(printk(KERN_DEBUG "Going left from frag (%p) %d-%d\n", -+ frag, frag->ofs, frag->ofs+frag->size)); -+ frag = frag_left(frag); -+ continue; -+ } -+ if (frag->rb.rb_right) { -+ D2(printk(KERN_DEBUG "Going right from frag (%p) %d-%d\n", -+ frag, frag->ofs, frag->ofs+frag->size)); -+ frag = frag_right(frag); -+ continue; -+ } -+ -+ D2(printk(KERN_DEBUG "jffs2_kill_fragtree: frag at 0x%x-0x%x: node %p, frags %d--\n", -+ frag->ofs, frag->ofs+frag->size, frag->node, -+ frag->node?frag->node->frags:0)); -+ -+ if (frag->node && !(--frag->node->frags)) { -+ /* Not a hole, and it's the final remaining frag -+ of this node. Free the node */ -+ if (c) -+ jffs2_mark_node_obsolete(c, frag->node->raw); -+ -+ jffs2_free_full_dnode(frag->node); -+ } -+ parent = frag_parent(frag); -+ if (parent) { -+ if (frag_left(parent) == frag) -+ parent->rb.rb_left = NULL; -+ else -+ parent->rb.rb_right = NULL; -+ } -+ -+ jffs2_free_node_frag(frag); -+ frag = parent; -+ -+ cond_resched(); -+ } -+} -+ -+void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base) -+{ -+ struct rb_node *parent = &base->rb; -+ struct rb_node **link = &parent; -+ -+ D2(printk(KERN_DEBUG "jffs2_fragtree_insert(%p; %d-%d, %p)\n", newfrag, -+ newfrag->ofs, newfrag->ofs+newfrag->size, base)); -+ -+ while (*link) { -+ parent = *link; -+ base = rb_entry(parent, struct jffs2_node_frag, rb); -+ -+ D2(printk(KERN_DEBUG "fragtree_insert considering frag at 0x%x\n", base->ofs)); -+ if (newfrag->ofs > base->ofs) -+ link = &base->rb.rb_right; -+ else if (newfrag->ofs < base->ofs) -+ link = &base->rb.rb_left; -+ else { -+ printk(KERN_CRIT "Duplicate frag at %08x (%p,%p)\n", newfrag->ofs, newfrag, base); -+ BUG(); -+ } -+ } -+ -+ rb_link_node(&newfrag->rb, &base->rb, link); -+} -diff -Nurb linux-mips-2.4.27/fs/jffs2/nodelist.h linux/fs/jffs2/nodelist.h ---- linux-mips-2.4.27/fs/jffs2/nodelist.h 2003-11-17 02:07:44.000000000 +0100 -+++ linux/fs/jffs2/nodelist.h 2004-11-19 10:25:12.113167264 +0100 -@@ -1,48 +1,35 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - -+#ifndef __JFFS2_NODELIST_H__ -+#define __JFFS2_NODELIST_H__ -+ - #include - #include -- -+#include -+#include - #include - #include - -+#ifdef __ECOS -+#include "os-ecos.h" -+#else -+#include /* For min/max in older kernels */ -+#include "os-linux.h" -+#endif -+ - #ifndef CONFIG_JFFS2_FS_DEBUG --#define CONFIG_JFFS2_FS_DEBUG 2 -+#define CONFIG_JFFS2_FS_DEBUG 1 - #endif - - #if CONFIG_JFFS2_FS_DEBUG > 0 -@@ -71,17 +58,21 @@ - for this inode instead. The inode_cache will have NULL in the first - word so you know when you've got there :) */ - struct jffs2_raw_node_ref *next_phys; -- // __u32 ino; -- __u32 flash_offset; -- __u32 totlen; --// __u16 nodetype; -+ uint32_t flash_offset; -+ uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */ -+}; - - /* flash_offset & 3 always has to be zero, because nodes are - always aligned at 4 bytes. So we have a couple of extra bits -- to play with. So we set the least significant bit to 1 to -- signify that the node is obsoleted by later nodes. -- */ --}; -+ to play with, which indicate the node's status; see below: */ -+#define REF_UNCHECKED 0 /* We haven't yet checked the CRC or built its inode */ -+#define REF_OBSOLETE 1 /* Obsolete, can be completely ignored */ -+#define REF_PRISTINE 2 /* Completely clean. GC without looking */ -+#define REF_NORMAL 3 /* Possibly overlapped. Read the page and write again on GC */ -+#define ref_flags(ref) ((ref)->flash_offset & 3) -+#define ref_offset(ref) ((ref)->flash_offset & ~3) -+#define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE) -+#define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0) - - /* - Used for keeping track of deletion nodes &c, which can only be marked -@@ -101,19 +92,35 @@ - a pointer to the first physical node which is part of this inode, too. - */ - struct jffs2_inode_cache { -- struct jffs2_scan_info *scan; /* Used during scan to hold -- temporary lists of nodes, and later must be set to -+ struct jffs2_full_dirent *scan_dents; /* Used during scan to hold -+ temporary lists of dirents, and later must be set to - NULL to mark the end of the raw_node_ref->next_in_ino - chain. */ - struct jffs2_inode_cache *next; - struct jffs2_raw_node_ref *nodes; -- __u32 ino; -+ uint32_t ino; - int nlink; -+ int state; - }; - -+/* Inode states for 'state' above. We need the 'GC' state to prevent -+ someone from doing a read_inode() while we're moving a 'REF_PRISTINE' -+ node without going through all the iget() nonsense */ -+#define INO_STATE_UNCHECKED 0 /* CRC checks not yet done */ -+#define INO_STATE_CHECKING 1 /* CRC checks in progress */ -+#define INO_STATE_PRESENT 2 /* In core */ -+#define INO_STATE_CHECKEDABSENT 3 /* Checked, cleared again */ -+#define INO_STATE_GC 4 /* GCing a 'pristine' node */ -+#define INO_STATE_READING 5 /* In read_inode() */ -+ -+#define INOCACHE_HASHSIZE 128 -+ - struct jffs2_scan_info { - struct jffs2_full_dirent *dents; - struct jffs2_tmp_dnode_info *tmpnodes; -+ /* Latest i_size info */ -+ uint32_t version; -+ uint32_t isize; - }; - /* - Larger representation of a raw node, kept in-core only when the -@@ -123,9 +130,9 @@ - struct jffs2_full_dnode - { - struct jffs2_raw_node_ref *raw; -- __u32 ofs; /* Don't really need this, but optimisation */ -- __u32 size; -- __u32 frags; /* Number of fragments which currently refer -+ uint32_t ofs; /* Don't really need this, but optimisation */ -+ uint32_t size; -+ uint32_t frags; /* Number of fragments which currently refer - to this node. When this reaches zero, - the node is obsolete. - */ -@@ -140,15 +147,15 @@ - { - struct jffs2_tmp_dnode_info *next; - struct jffs2_full_dnode *fn; -- __u32 version; -+ uint32_t version; - }; - - struct jffs2_full_dirent - { - struct jffs2_raw_node_ref *raw; - struct jffs2_full_dirent *next; -- __u32 version; -- __u32 ino; /* == zero for unlink */ -+ uint32_t version; -+ uint32_t ino; /* == zero for unlink */ - unsigned int nhash; - unsigned char type; - unsigned char name[0]; -@@ -159,21 +166,23 @@ - */ - struct jffs2_node_frag - { -- struct jffs2_node_frag *next; -+ struct rb_node rb; - struct jffs2_full_dnode *node; /* NULL for holes */ -- __u32 size; -- __u32 ofs; /* Don't really need this, but optimisation */ -+ uint32_t size; -+ uint32_t ofs; /* Don't really need this, but optimisation */ - }; - - struct jffs2_eraseblock - { - struct list_head list; - int bad_count; -- __u32 offset; /* of this block in the MTD */ -+ uint32_t offset; /* of this block in the MTD */ - -- __u32 used_size; -- __u32 dirty_size; -- __u32 free_size; /* Note that sector_size - free_size -+ uint32_t unchecked_size; -+ uint32_t used_size; -+ uint32_t dirty_size; -+ uint32_t wasted_size; -+ uint32_t free_size; /* Note that sector_size - free_size - is the address of the first free space */ - struct jffs2_raw_node_ref *first_node; - struct jffs2_raw_node_ref *last_node; -@@ -190,45 +199,134 @@ - }; - - #define ACCT_SANITY_CHECK(c, jeb) do { \ -- if (jeb->used_size + jeb->dirty_size + jeb->free_size != c->sector_size) { \ -- printk(KERN_NOTICE "Eeep. Space accounting for block at 0x%08x is screwed\n", jeb->offset); \ -- printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x != total %08x\n", \ -- jeb->free_size, jeb->dirty_size, jeb->used_size, c->sector_size); \ -+ struct jffs2_eraseblock *___j = jeb; \ -+ if ((___j) && ___j->used_size + ___j->dirty_size + ___j->free_size + ___j->wasted_size + ___j->unchecked_size != c->sector_size) { \ -+ printk(KERN_NOTICE "Eeep. Space accounting for block at 0x%08x is screwed\n", ___j->offset); \ -+ printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + wasted %08x + unchecked %08x != total %08x\n", \ -+ ___j->free_size, ___j->dirty_size, ___j->used_size, ___j->wasted_size, ___j->unchecked_size, c->sector_size); \ - BUG(); \ - } \ -- if (c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size != c->flash_size) { \ -+ if (c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size + c->wasted_size + c->unchecked_size != c->flash_size) { \ - printk(KERN_NOTICE "Eeep. Space accounting superblock info is screwed\n"); \ -- printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + erasing %08x + bad %08x != total %08x\n", \ -- c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, c->flash_size); \ -+ printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + erasing %08x + bad %08x + wasted %08x + unchecked %08x != total %08x\n", \ -+ c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, c->wasted_size, c->unchecked_size, c->flash_size); \ - BUG(); \ - } \ - } while(0) - -+static inline void paranoia_failed_dump(struct jffs2_eraseblock *jeb) -+{ -+ struct jffs2_raw_node_ref *ref; -+ int i=0; -+ -+ printk(KERN_NOTICE); -+ for (ref = jeb->first_node; ref; ref = ref->next_phys) { -+ printk("%08x->", ref_offset(ref)); -+ if (++i == 8) { -+ i = 0; -+ printk("\n" KERN_NOTICE); -+ } -+ } -+ printk("\n"); -+} -+ -+ - #define ACCT_PARANOIA_CHECK(jeb) do { \ -- __u32 my_used_size = 0; \ -+ uint32_t my_used_size = 0; \ -+ uint32_t my_unchecked_size = 0; \ - struct jffs2_raw_node_ref *ref2 = jeb->first_node; \ - while (ref2) { \ -- if (!(ref2->flash_offset & 1)) \ -- my_used_size += ref2->totlen; \ -+ if (unlikely(ref2->flash_offset < jeb->offset || \ -+ ref2->flash_offset > jeb->offset + c->sector_size)) { \ -+ printk(KERN_NOTICE "Node %08x shouldn't be in block at %08x!\n", \ -+ ref_offset(ref2), jeb->offset); \ -+ paranoia_failed_dump(jeb); \ -+ BUG(); \ -+ } \ -+ if (ref_flags(ref2) == REF_UNCHECKED) \ -+ my_unchecked_size += ref_totlen(c, jeb, ref2); \ -+ else if (!ref_obsolete(ref2)) \ -+ my_used_size += ref_totlen(c, jeb, ref2); \ -+ if (unlikely((!ref2->next_phys) != (ref2 == jeb->last_node))) { \ -+ printk("ref for node at %p (phys %08x) has next_phys->%p (%08x), last_node->%p (phys %08x)\n", \ -+ ref2, ref_offset(ref2), ref2->next_phys, ref_offset(ref2->next_phys), \ -+ jeb->last_node, ref_offset(jeb->last_node)); \ -+ paranoia_failed_dump(jeb); \ -+ BUG(); \ -+ } \ - ref2 = ref2->next_phys; \ - } \ - if (my_used_size != jeb->used_size) { \ - printk(KERN_NOTICE "Calculated used size %08x != stored used size %08x\n", my_used_size, jeb->used_size); \ - BUG(); \ - } \ -+ if (my_unchecked_size != jeb->unchecked_size) { \ -+ printk(KERN_NOTICE "Calculated unchecked size %08x != stored unchecked size %08x\n", my_unchecked_size, jeb->unchecked_size); \ -+ BUG(); \ -+ } \ - } while(0) - -+/* Calculate totlen from surrounding nodes or eraseblock */ -+static inline uint32_t __ref_totlen(struct jffs2_sb_info *c, -+ struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_node_ref *ref) -+{ -+ uint32_t ref_end; -+ -+ if (ref->next_phys) -+ ref_end = ref_offset(ref->next_phys); -+ else { -+ if (!jeb) -+ jeb = &c->blocks[ref->flash_offset / c->sector_size]; -+ -+ /* Last node in block. Use free_space */ -+ BUG_ON(ref != jeb->last_node); -+ ref_end = jeb->offset + c->sector_size - jeb->free_size; -+ } -+ return ref_end - ref_offset(ref); -+} -+ -+static inline uint32_t ref_totlen(struct jffs2_sb_info *c, -+ struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_node_ref *ref) -+{ -+ uint32_t ret; -+ -+ D1(if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) { -+ printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n", -+ jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref)); -+ BUG(); -+ }) -+ -+#if 1 -+ ret = ref->__totlen; -+#else -+ /* This doesn't actually work yet */ -+ ret = __ref_totlen(c, jeb, ref); -+ if (ret != ref->__totlen) { -+ printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n", -+ ref, ref_offset(ref), ref_offset(ref)+ref->__totlen, -+ ret, ref->__totlen); -+ if (!jeb) -+ jeb = &c->blocks[ref->flash_offset / c->sector_size]; -+ paranoia_failed_dump(jeb); -+ BUG(); -+ } -+#endif -+ return ret; -+} -+ -+ - #define ALLOC_NORMAL 0 /* Normal allocation */ - #define ALLOC_DELETION 1 /* Deletion node. Best to allow it */ - #define ALLOC_GC 2 /* Space requested for GC. Give it or die */ -+#define ALLOC_NORETRY 3 /* For jffs2_write_dnode: On failure, return -EAGAIN instead of retrying */ - --#define JFFS2_RESERVED_BLOCKS_BASE 3 /* Number of free blocks there must be before we... */ --#define JFFS2_RESERVED_BLOCKS_WRITE (JFFS2_RESERVED_BLOCKS_BASE + 2) /* ... allow a normal filesystem write */ --#define JFFS2_RESERVED_BLOCKS_DELETION (JFFS2_RESERVED_BLOCKS_BASE + 1) /* ... allow a normal filesystem deletion */ --#define JFFS2_RESERVED_BLOCKS_GCTRIGGER (JFFS2_RESERVED_BLOCKS_BASE + 3) /* ... wake up the GC thread */ --#define JFFS2_RESERVED_BLOCKS_GCBAD (JFFS2_RESERVED_BLOCKS_BASE + 1) /* ... pick a block from the bad_list to GC */ --#define JFFS2_RESERVED_BLOCKS_GCMERGE (JFFS2_RESERVED_BLOCKS_BASE) /* ... merge pages when garbage collecting */ -+/* How much dirty space before it goes on the very_dirty_list */ -+#define VERYDIRTY(c, size) ((size) >= ((c)->sector_size / 2)) - -+/* check if dirty space is more than 255 Byte */ -+#define ISDIRTY(size) ((size) > sizeof (struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN) - - #define PAD(x) (((x)+3)&~3) - -@@ -241,43 +339,75 @@ - return ((struct jffs2_inode_cache *)raw); - } - -+static inline struct jffs2_node_frag *frag_first(struct rb_root *root) -+{ -+ struct rb_node *node = root->rb_node; -+ -+ if (!node) -+ return NULL; -+ while(node->rb_left) -+ node = node->rb_left; -+ return rb_entry(node, struct jffs2_node_frag, rb); -+} -+#define rb_parent(rb) ((rb)->rb_parent) -+#define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb) -+#define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb) -+#define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb) -+#define frag_left(frag) rb_entry((frag)->rb.rb_left, struct jffs2_node_frag, rb) -+#define frag_right(frag) rb_entry((frag)->rb.rb_right, struct jffs2_node_frag, rb) -+#define frag_erase(frag, list) rb_erase(&frag->rb, list); -+ - /* nodelist.c */ - D1(void jffs2_print_frag_list(struct jffs2_inode_info *f)); - void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list); --void jffs2_add_tn_to_list(struct jffs2_tmp_dnode_info *tn, struct jffs2_tmp_dnode_info **list); - int jffs2_get_inode_nodes(struct jffs2_sb_info *c, ino_t ino, struct jffs2_inode_info *f, - struct jffs2_tmp_dnode_info **tnp, struct jffs2_full_dirent **fdp, -- __u32 *highest_version, __u32 *latest_mctime, -- __u32 *mctime_ver); -+ uint32_t *highest_version, uint32_t *latest_mctime, -+ uint32_t *mctime_ver); -+void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state); - struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t ino); - void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new); - void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old); - void jffs2_free_ino_caches(struct jffs2_sb_info *c); - void jffs2_free_raw_node_refs(struct jffs2_sb_info *c); -+struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset); -+void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c_delete); -+void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base); -+struct rb_node *rb_next(struct rb_node *); -+struct rb_node *rb_prev(struct rb_node *); -+void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); - - /* nodemgmt.c */ --int jffs2_reserve_space(struct jffs2_sb_info *c, __u32 minsize, __u32 *ofs, __u32 *len, int prio); --int jffs2_reserve_space_gc(struct jffs2_sb_info *c, __u32 minsize, __u32 *ofs, __u32 *len); --int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, __u32 len, int dirty); -+int jffs2_thread_should_wake(struct jffs2_sb_info *c); -+int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio); -+int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len); -+int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new); - void jffs2_complete_reservation(struct jffs2_sb_info *c); - void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); -+void jffs2_dump_block_lists(struct jffs2_sb_info *c); - - /* write.c */ --struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri); --struct jffs2_full_dnode *jffs2_write_dnode(struct inode *inode, struct jffs2_raw_inode *ri, const unsigned char *data, __u32 datalen, __u32 flash_ofs, __u32 *writelen); --struct jffs2_full_dirent *jffs2_write_dirent(struct inode *inode, struct jffs2_raw_dirent *rd, const unsigned char *name, __u32 namelen, __u32 flash_ofs, __u32 *writelen); -+int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri); -+ -+struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode); -+struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode); -+int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, -+ struct jffs2_raw_inode *ri, unsigned char *buf, -+ uint32_t offset, uint32_t writelen, uint32_t *retlen); -+int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen); -+int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f); -+int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen); -+ - - /* readinode.c */ --void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct jffs2_node_frag **list, __u32 size); --int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct jffs2_node_frag **list, struct jffs2_full_dnode *fn); -+void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); - int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); --void jffs2_read_inode (struct inode *); --void jffs2_clear_inode (struct inode *); -+int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, -+ uint32_t ino, struct jffs2_raw_inode *latest_node); -+int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); -+void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f); - - /* malloc.c */ --void jffs2_free_tmp_dnode_info_list(struct jffs2_tmp_dnode_info *tn); --void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd); -- - int jffs2_create_slab_caches(void); - void jffs2_destroy_slab_caches(void); - -@@ -301,54 +431,41 @@ - /* gc.c */ - int jffs2_garbage_collect_pass(struct jffs2_sb_info *c); - --/* background.c */ --int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c); --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 struct inode_operations jffs2_dir_inode_operations; -- --/* file.c */ --extern 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_null_fsync(struct file *, struct dentry *, int); --int jffs2_setattr (struct dentry *dentry, struct iattr *iattr); --int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg); --int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg); --int jffs2_readpage (struct file *, struct page *); --int jffs2_prepare_write (struct file *, struct page *, unsigned, unsigned); --int jffs2_commit_write (struct file *, struct page *, unsigned, unsigned); -- --/* ioctl.c */ --int jffs2_ioctl(struct inode *, struct file *, unsigned int, unsigned long); -- - /* read.c */ - int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsigned char *buf, int ofs, int len); -+int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, -+ unsigned char *buf, uint32_t offset, uint32_t len); -+char *jffs2_getlink(struct jffs2_sb_info *c, struct jffs2_inode_info *f); - - /* compr.c */ --unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, -- __u32 *datalen, __u32 *cdatalen); -+unsigned char jffs2_compress(unsigned char *data_in, unsigned char **cpage_out, -+ uint32_t *datalen, uint32_t *cdatalen); -+void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig); - int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, -- unsigned char *data_out, __u32 cdatalen, __u32 datalen); -+ unsigned char *data_out, uint32_t cdatalen, uint32_t datalen); - - /* scan.c */ - int jffs2_scan_medium(struct jffs2_sb_info *c); -+void jffs2_rotate_lists(struct jffs2_sb_info *c); - - /* build.c */ --int jffs2_build_filesystem(struct jffs2_sb_info *c); -- --/* symlink.c */ --extern struct inode_operations jffs2_symlink_inode_operations; -+int jffs2_do_mount_fs(struct jffs2_sb_info *c); - - /* erase.c */ - void jffs2_erase_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); --void jffs2_erase_pending_blocks(struct jffs2_sb_info *c); --void jffs2_mark_erased_blocks(struct jffs2_sb_info *c); --void jffs2_erase_pending_trigger(struct jffs2_sb_info *c); -+void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count); -+ -+#ifdef CONFIG_JFFS2_FS_NAND -+/* wbuf.c */ -+int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino); -+int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c); -+int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+int jffs2_nand_read_failcnt(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+#endif - - /* compr_zlib.c */ - int jffs2_zlib_init(void); - void jffs2_zlib_exit(void); -+ -+#endif /* __JFFS2_NODELIST_H__ */ -diff -Nurb linux-mips-2.4.27/fs/jffs2/nodemgmt.c linux/fs/jffs2/nodemgmt.c ---- linux-mips-2.4.27/fs/jffs2/nodemgmt.c 2002-06-27 00:36:20.000000000 +0200 -+++ linux/fs/jffs2/nodemgmt.c 2004-11-19 10:25:12.115166960 +0100 -@@ -1,45 +1,21 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include - #include --#include - #include --#include -+#include -+#include /* For cond_resched() */ - #include "nodelist.h" - - /** -@@ -62,53 +38,95 @@ - * for the requested allocation. - */ - --static int jffs2_do_reserve_space(struct jffs2_sb_info *c, __u32 minsize, __u32 *ofs, __u32 *len); -+static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len); - --int jffs2_reserve_space(struct jffs2_sb_info *c, __u32 minsize, __u32 *ofs, __u32 *len, int prio) -+int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio) - { - int ret = -EAGAIN; -- int blocksneeded = JFFS2_RESERVED_BLOCKS_WRITE; -+ int blocksneeded = c->resv_blocks_write; - /* align it */ - minsize = PAD(minsize); - -- if (prio == ALLOC_DELETION) -- blocksneeded = JFFS2_RESERVED_BLOCKS_DELETION; -- - D1(printk(KERN_DEBUG "jffs2_reserve_space(): Requested 0x%x bytes\n", minsize)); - down(&c->alloc_sem); - - D1(printk(KERN_DEBUG "jffs2_reserve_space(): alloc sem got\n")); - -- spin_lock_bh(&c->erase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - -- /* this needs a little more thought */ -+ /* this needs a little more thought (true :)) */ - while(ret == -EAGAIN) { - while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) { - int ret; -+ uint32_t dirty, avail; -+ -+ /* calculate real dirty size -+ * dirty_size contains blocks on erase_pending_list -+ * those blocks are counted in c->nr_erasing_blocks. -+ * If one block is actually erased, it is not longer counted as dirty_space -+ * but it is counted in c->nr_erasing_blocks, so we add it and subtract it -+ * with c->nr_erasing_blocks * c->sector_size again. -+ * Blocks on erasable_list are counted as dirty_size, but not in c->nr_erasing_blocks -+ * This helps us to force gc and pick eventually a clean block to spread the load. -+ * We add unchecked_size here, as we hopefully will find some space to use. -+ * This will affect the sum only once, as gc first finishes checking -+ * of nodes. -+ */ -+ dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size + c->unchecked_size; -+ if (dirty < c->nospc_dirty_size) { -+ if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) { -+ printk(KERN_NOTICE "jffs2_reserve_space(): Low on dirty space to GC, but it's a deletion. Allowing...\n"); -+ break; -+ } -+ D1(printk(KERN_DEBUG "dirty size 0x%08x + unchecked_size 0x%08x < nospc_dirty_size 0x%08x, returning -ENOSPC\n", -+ dirty, c->unchecked_size, c->sector_size)); -+ -+ spin_unlock(&c->erase_completion_lock); -+ up(&c->alloc_sem); -+ return -ENOSPC; -+ } - -+ /* Calc possibly available space. Possibly available means that we -+ * don't know, if unchecked size contains obsoleted nodes, which could give us some -+ * more usable space. This will affect the sum only once, as gc first finishes checking -+ * of nodes. -+ + Return -ENOSPC, if the maximum possibly available space is less or equal than -+ * blocksneeded * sector_size. -+ * This blocks endless gc looping on a filesystem, which is nearly full, even if -+ * the check above passes. -+ */ -+ avail = c->free_size + c->dirty_size + c->erasing_size + c->unchecked_size; -+ if ( (avail / c->sector_size) <= blocksneeded) { -+ if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) { -+ printk(KERN_NOTICE "jffs2_reserve_space(): Low on possibly available space, but it's a deletion. Allowing...\n"); -+ break; -+ } -+ -+ D1(printk(KERN_DEBUG "max. available size 0x%08x < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n", -+ avail, blocksneeded * c->sector_size)); -+ spin_unlock(&c->erase_completion_lock); - up(&c->alloc_sem); -- if (c->dirty_size < c->sector_size) { -- D1(printk(KERN_DEBUG "Short on space, but total dirty size 0x%08x < sector size 0x%08x, so -ENOSPC\n", c->dirty_size, c->sector_size)); -- spin_unlock_bh(&c->erase_completion_lock); - return -ENOSPC; - } -- D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n", -- c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, -- c->free_size + c->dirty_size + c->used_size + c->erasing_size + c->bad_size, c->flash_size)); -- spin_unlock_bh(&c->erase_completion_lock); -+ -+ up(&c->alloc_sem); -+ -+ D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, wasted_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n", -+ c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->wasted_size, c->used_size, c->erasing_size, c->bad_size, -+ c->free_size + c->dirty_size + c->wasted_size + c->used_size + c->erasing_size + c->bad_size, c->flash_size)); -+ spin_unlock(&c->erase_completion_lock); - - ret = jffs2_garbage_collect_pass(c); - if (ret) - return ret; - -- if (current->need_resched) -- schedule(); -+ cond_resched(); - - if (signal_pending(current)) - return -EINTR; - - down(&c->alloc_sem); -- spin_lock_bh(&c->erase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - } - - ret = jffs2_do_reserve_space(c, minsize, ofs, len); -@@ -116,45 +134,72 @@ - D1(printk(KERN_DEBUG "jffs2_reserve_space: ret is %d\n", ret)); - } - } -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - if (ret) - up(&c->alloc_sem); - return ret; - } - --int jffs2_reserve_space_gc(struct jffs2_sb_info *c, __u32 minsize, __u32 *ofs, __u32 *len) -+int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len) - { - int ret = -EAGAIN; - minsize = PAD(minsize); - - D1(printk(KERN_DEBUG "jffs2_reserve_space_gc(): Requested 0x%x bytes\n", minsize)); - -- spin_lock_bh(&c->erase_completion_lock); -+ spin_lock(&c->erase_completion_lock); - while(ret == -EAGAIN) { - ret = jffs2_do_reserve_space(c, minsize, ofs, len); - if (ret) { - D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret)); - } - } -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - return ret; - } - - /* Called with alloc sem _and_ erase_completion_lock */ --static int jffs2_do_reserve_space(struct jffs2_sb_info *c, __u32 minsize, __u32 *ofs, __u32 *len) -+static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len) - { - struct jffs2_eraseblock *jeb = c->nextblock; - - restart: - if (jeb && minsize > jeb->free_size) { - /* Skip the end of this block and file it as having some dirty space */ -- c->dirty_size += jeb->free_size; -+ /* If there's a pending write to it, flush now */ -+ if (jffs2_wbuf_dirty(c)) { -+ spin_unlock(&c->erase_completion_lock); -+ D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Flushing write buffer\n")); -+ jffs2_flush_wbuf_pad(c); -+ spin_lock(&c->erase_completion_lock); -+ jeb = c->nextblock; -+ goto restart; -+ } -+ c->wasted_size += jeb->free_size; - c->free_size -= jeb->free_size; -- jeb->dirty_size += jeb->free_size; -+ jeb->wasted_size += jeb->free_size; - jeb->free_size = 0; -+ -+ /* Check, if we have a dirty block now, or if it was dirty already */ -+ if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) { -+ c->dirty_size += jeb->wasted_size; -+ c->wasted_size -= jeb->wasted_size; -+ jeb->dirty_size += jeb->wasted_size; -+ jeb->wasted_size = 0; -+ if (VERYDIRTY(c, jeb->dirty_size)) { -+ D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", -+ jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); -+ list_add_tail(&jeb->list, &c->very_dirty_list); -+ } else { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->dirty_list); -+ } -+ } else { -+ D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", -+ jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); -+ list_add_tail(&jeb->list, &c->clean_list); -+ } - c->nextblock = jeb = NULL; - } - -@@ -164,33 +209,44 @@ - - if (list_empty(&c->free_list)) { - -- DECLARE_WAITQUEUE(wait, current); -+ if (!c->nr_erasing_blocks && -+ !list_empty(&c->erasable_list)) { -+ struct jffs2_eraseblock *ejeb; -+ -+ ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list); -+ list_del(&ejeb->list); -+ list_add_tail(&ejeb->list, &c->erase_pending_list); -+ c->nr_erasing_blocks++; -+ jffs2_erase_pending_trigger(c); -+ D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Triggering erase of erasable block at 0x%08x\n", -+ ejeb->offset)); -+ } -+ -+ if (!c->nr_erasing_blocks && -+ !list_empty(&c->erasable_pending_wbuf_list)) { -+ D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Flushing write buffer\n")); -+ /* c->nextblock is NULL, no update to c->nextblock allowed */ -+ spin_unlock(&c->erase_completion_lock); -+ jffs2_flush_wbuf_pad(c); -+ spin_lock(&c->erase_completion_lock); -+ /* Have another go. It'll be on the erasable_list now */ -+ return -EAGAIN; -+ } - - if (!c->nr_erasing_blocks) { --// if (list_empty(&c->erasing_list) && list_empty(&c->erase_pending_list) && list_empty(c->erase_complete_list)) { - /* Ouch. We're in GC, or we wouldn't have got here. - And there's no space left. At all. */ -- printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasingempty: %s, erasependingempty: %s)\n", -- c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no"); -+ printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", -+ c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasable_list)?"yes":"no", -+ list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no"); - return -ENOSPC; - } -- /* Make sure this can't deadlock. Someone has to start the erases -- of erase_pending blocks */ -- set_current_state(TASK_INTERRUPTIBLE); -- add_wait_queue(&c->erase_wait, &wait); -- D1(printk(KERN_DEBUG "Waiting for erases to complete. erasing_blocks is %d. (erasingempty: %s, erasependingempty: %s)\n", -- c->nr_erasing_blocks, list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no")); -- if (!list_empty(&c->erase_pending_list)) { -- D1(printk(KERN_DEBUG "Triggering pending erases\n")); -- jffs2_erase_pending_trigger(c); -- } -- spin_unlock_bh(&c->erase_completion_lock); -- schedule(); -- remove_wait_queue(&c->erase_wait, &wait); -- spin_lock_bh(&c->erase_completion_lock); -- if (signal_pending(current)) { -- return -EINTR; -- } -+ -+ spin_unlock(&c->erase_completion_lock); -+ /* Don't wait for it; just erase one right now */ -+ jffs2_erase_pending_blocks(c, 1); -+ spin_lock(&c->erase_completion_lock); -+ - /* An erase may have failed, decreasing the - amount of free space available. So we must - restart from the beginning */ -@@ -201,7 +257,8 @@ - list_del(next); - c->nextblock = jeb = list_entry(next, struct jffs2_eraseblock, list); - c->nr_free_blocks--; -- if (jeb->free_size != c->sector_size - sizeof(struct jffs2_unknown_node)) { -+ -+ if (jeb->free_size != c->sector_size - c->cleanmarker_size) { - printk(KERN_WARNING "Eep. Block 0x%08x taken from free_list had free_size of 0x%08x!!\n", jeb->offset, jeb->free_size); - goto restart; - } -@@ -210,6 +267,20 @@ - enough space */ - *ofs = jeb->offset + (c->sector_size - jeb->free_size); - *len = jeb->free_size; -+ -+ if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size && -+ !jeb->first_node->next_in_ino) { -+ /* Only node in it beforehand was a CLEANMARKER node (we think). -+ So mark it obsolete now that there's going to be another node -+ in the block. This will reduce used_size to zero but We've -+ already set c->nextblock so that jffs2_mark_node_obsolete() -+ won't try to refile it to the dirty_list. -+ */ -+ spin_unlock(&c->erase_completion_lock); -+ jffs2_mark_node_obsolete(c, jeb->first_node); -+ spin_lock(&c->erase_completion_lock); -+ } -+ - D1(printk(KERN_DEBUG "jffs2_do_reserve_space(): Giving 0x%x bytes at 0x%x\n", *len, *ofs)); - return 0; - } -@@ -217,9 +288,9 @@ - /** - * jffs2_add_physical_node_ref - add a physical node reference to the list - * @c: superblock info -- * @ofs: physical location of this physical node -+ * @new: new node reference to add - * @len: length of this physical node -- * @ino: inode number with which this physical node is associated -+ * @dirty: dirty flag for new node - * - * Should only be used to report nodes for which space has been allocated - * by jffs2_reserve_space. -@@ -227,47 +298,58 @@ - * Must be called with the alloc_sem held. - */ - --int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, __u32 len, int dirty) -+int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new) - { - struct jffs2_eraseblock *jeb; -+ uint32_t len; -+ -+ jeb = &c->blocks[new->flash_offset / c->sector_size]; -+ len = ref_totlen(c, jeb, new); - -- len = PAD(len); -- jeb = &c->blocks[(new->flash_offset & ~3) / c->sector_size]; -- D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x, size 0x%x\n", new->flash_offset & ~3, len)); -+ D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len)); - #if 1 -- if (jeb != c->nextblock || (new->flash_offset & ~3) != jeb->offset + (c->sector_size - jeb->free_size)) { -+ if (jeb != c->nextblock || (ref_offset(new)) != jeb->offset + (c->sector_size - jeb->free_size)) { - printk(KERN_WARNING "argh. node added in wrong place\n"); - jffs2_free_raw_node_ref(new); - return -EINVAL; - } - #endif -+ spin_lock(&c->erase_completion_lock); -+ - if (!jeb->first_node) - jeb->first_node = new; - if (jeb->last_node) - jeb->last_node->next_phys = new; - jeb->last_node = new; - -- spin_lock_bh(&c->erase_completion_lock); - jeb->free_size -= len; - c->free_size -= len; -- if (dirty) { -- new->flash_offset |= 1; -+ if (ref_obsolete(new)) { - jeb->dirty_size += len; - c->dirty_size += len; - } else { - jeb->used_size += len; - c->used_size += len; - } -- spin_unlock_bh(&c->erase_completion_lock); -+ - if (!jeb->free_size && !jeb->dirty_size) { - /* If it lives on the dirty_list, jffs2_reserve_space will put it there */ - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); -+ if (jffs2_wbuf_dirty(c)) { -+ /* Flush the last write in the block if it's outstanding */ -+ spin_unlock(&c->erase_completion_lock); -+ jffs2_flush_wbuf_pad(c); -+ spin_lock(&c->erase_completion_lock); -+ } -+ - list_add_tail(&jeb->list, &c->clean_list); - c->nextblock = NULL; - } - ACCT_SANITY_CHECK(c,jeb); -- ACCT_PARANOIA_CHECK(jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ spin_unlock(&c->erase_completion_lock); - - return 0; - } -@@ -280,20 +362,34 @@ - up(&c->alloc_sem); - } - -+static inline int on_list(struct list_head *obj, struct list_head *head) -+{ -+ struct list_head *this; -+ -+ list_for_each(this, head) { -+ if (this == obj) { -+ D1(printk("%p is on list at %p\n", obj, head)); -+ return 1; -+ -+ } -+ } -+ return 0; -+} -+ - void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref) - { - struct jffs2_eraseblock *jeb; - int blocknr; - struct jffs2_unknown_node n; -- int ret; -- ssize_t retlen; -+ int ret, addedsize; -+ size_t retlen; - - if(!ref) { - printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n"); - return; - } -- if (ref->flash_offset & 1) { -- D1(printk(KERN_DEBUG "jffs2_mark_node_obsolete called with already obsolete node at 0x%08x\n", ref->flash_offset &~3)); -+ if (ref_obsolete(ref)) { -+ D1(printk(KERN_DEBUG "jffs2_mark_node_obsolete called with already obsolete node at 0x%08x\n", ref_offset(ref))); - return; - } - blocknr = ref->flash_offset / c->sector_size; -@@ -302,22 +398,63 @@ - BUG(); - } - jeb = &c->blocks[blocknr]; -- if (jeb->used_size < ref->totlen) { -+ -+ spin_lock(&c->erase_completion_lock); -+ -+ if (ref_flags(ref) == REF_UNCHECKED) { -+ D1(if (unlikely(jeb->unchecked_size < ref_totlen(c, jeb, ref))) { -+ printk(KERN_NOTICE "raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n", -+ ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size); -+ BUG(); -+ }) -+ D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); -+ jeb->unchecked_size -= ref_totlen(c, jeb, ref); -+ c->unchecked_size -= ref_totlen(c, jeb, ref); -+ } else { -+ D1(if (unlikely(jeb->used_size < ref_totlen(c, jeb, ref))) { - printk(KERN_NOTICE "raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n", -- ref->totlen, blocknr, ref->flash_offset, jeb->used_size); -+ ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size); - BUG(); -+ }) -+ D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); -+ jeb->used_size -= ref_totlen(c, jeb, ref); -+ c->used_size -= ref_totlen(c, jeb, ref); -+ } -+ -+ // Take care, that wasted size is taken into concern -+ if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + ref_totlen(c, jeb, ref))) && jeb != c->nextblock) { -+ D1(printk("Dirtying\n")); -+ addedsize = ref_totlen(c, jeb, ref); -+ jeb->dirty_size += ref_totlen(c, jeb, ref); -+ c->dirty_size += ref_totlen(c, jeb, ref); -+ -+ /* Convert wasted space to dirty, if not a bad block */ -+ if (jeb->wasted_size) { -+ if (on_list(&jeb->list, &c->bad_used_list)) { -+ D1(printk(KERN_DEBUG "Leaving block at %08x on the bad_used_list\n", -+ jeb->offset)); -+ addedsize = 0; /* To fool the refiling code later */ -+ } else { -+ D1(printk(KERN_DEBUG "Converting %d bytes of wasted space to dirty in block at %08x\n", -+ jeb->wasted_size, jeb->offset)); -+ addedsize += jeb->wasted_size; -+ jeb->dirty_size += jeb->wasted_size; -+ c->dirty_size += jeb->wasted_size; -+ c->wasted_size -= jeb->wasted_size; -+ jeb->wasted_size = 0; - } -- -- spin_lock_bh(&c->erase_completion_lock); -- jeb->used_size -= ref->totlen; -- jeb->dirty_size += ref->totlen; -- c->used_size -= ref->totlen; -- c->dirty_size += ref->totlen; -- ref->flash_offset |= 1; -+ } -+ } else { -+ D1(printk("Wasting\n")); -+ addedsize = 0; -+ jeb->wasted_size += ref_totlen(c, jeb, ref); -+ c->wasted_size += ref_totlen(c, jeb, ref); -+ } -+ ref->flash_offset = ref_offset(ref) | REF_OBSOLETE; - - ACCT_SANITY_CHECK(c, jeb); - -- ACCT_PARANOIA_CHECK(jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); - - if (c->flags & JFFS2_SB_FLAG_MOUNTING) { - /* Mount in progress. Don't muck about with the block -@@ -325,68 +462,280 @@ - obliterate nodes that look obsolete. If they weren't - marked obsolete on the flash at the time they _became_ - obsolete, there was probably a reason for that. */ -- spin_unlock_bh(&c->erase_completion_lock); -+ spin_unlock(&c->erase_completion_lock); - return; - } -+ - if (jeb == c->nextblock) { - D2(printk(KERN_DEBUG "Not moving nextblock 0x%08x to dirty/erase_pending list\n", jeb->offset)); -- } else if (jeb == c->gcblock) { -- D2(printk(KERN_DEBUG "Not moving gcblock 0x%08x to dirty/erase_pending list\n", jeb->offset)); --#if 0 /* We no longer do this here. It can screw the wear levelling. If you have a lot of static -- data and a few blocks free, and you just create new files and keep deleting/overwriting -- them, then you'd keep erasing and reusing those blocks without ever moving stuff around. -- So we leave completely obsoleted blocks on the dirty_list and let the GC delete them -- when it finds them there. That way, we still get the 'once in a while, take a clean block' -- to spread out the flash usage */ -- } else if (!jeb->used_size) { -+ } else if (!jeb->used_size && !jeb->unchecked_size) { -+ if (jeb == c->gcblock) { -+ D1(printk(KERN_DEBUG "gcblock at 0x%08x completely dirtied. Clearing gcblock...\n", jeb->offset)); -+ c->gcblock = NULL; -+ } else { - D1(printk(KERN_DEBUG "Eraseblock at 0x%08x completely dirtied. Removing from (dirty?) list...\n", jeb->offset)); - list_del(&jeb->list); -+ } -+ if (jffs2_wbuf_dirty(c)) { -+ D1(printk(KERN_DEBUG "...and adding to erasable_pending_wbuf_list\n")); -+ list_add_tail(&jeb->list, &c->erasable_pending_wbuf_list); -+ } else { -+ if (jiffies & 127) { -+ /* Most of the time, we just erase it immediately. Otherwise we -+ spend ages scanning it on mount, etc. */ - D1(printk(KERN_DEBUG "...and adding to erase_pending_list\n")); - list_add_tail(&jeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; - jffs2_erase_pending_trigger(c); -- // OFNI_BS_2SFFJ(c)->s_dirt = 1; -+ } else { -+ /* Sometimes, however, we leave it elsewhere so it doesn't get -+ immediately reused, and we spread the load a bit. */ -+ D1(printk(KERN_DEBUG "...and adding to erasable_list\n")); -+ list_add_tail(&jeb->list, &c->erasable_list); -+ } -+ } - D1(printk(KERN_DEBUG "Done OK\n")); --#endif -- } else if (jeb->dirty_size == ref->totlen) { -+ } else if (jeb == c->gcblock) { -+ D2(printk(KERN_DEBUG "Not moving gcblock 0x%08x to dirty_list\n", jeb->offset)); -+ } else if (ISDIRTY(jeb->dirty_size) && !ISDIRTY(jeb->dirty_size - addedsize)) { - D1(printk(KERN_DEBUG "Eraseblock at 0x%08x is freshly dirtied. Removing from clean list...\n", jeb->offset)); - list_del(&jeb->list); - D1(printk(KERN_DEBUG "...and adding to dirty_list\n")); - list_add_tail(&jeb->list, &c->dirty_list); -+ } else if (VERYDIRTY(c, jeb->dirty_size) && -+ !VERYDIRTY(c, jeb->dirty_size - addedsize)) { -+ D1(printk(KERN_DEBUG "Eraseblock at 0x%08x is now very dirty. Removing from dirty list...\n", jeb->offset)); -+ list_del(&jeb->list); -+ D1(printk(KERN_DEBUG "...and adding to very_dirty_list\n")); -+ list_add_tail(&jeb->list, &c->very_dirty_list); -+ } else { -+ D1(printk(KERN_DEBUG "Eraseblock at 0x%08x not moved anywhere. (free 0x%08x, dirty 0x%08x, used 0x%08x)\n", -+ jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - } -- spin_unlock_bh(&c->erase_completion_lock); - -- if (c->mtd->type != MTD_NORFLASH && c->mtd->type != MTD_RAM) -+ spin_unlock(&c->erase_completion_lock); -+ -+ if (!jffs2_can_mark_obsolete(c)) - return; -- if (OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY) -+ if (jffs2_is_readonly(c)) - return; - -- D1(printk(KERN_DEBUG "obliterating obsoleted node at 0x%08x\n", ref->flash_offset &~3)); -- ret = c->mtd->read(c->mtd, ref->flash_offset &~3, sizeof(n), &retlen, (char *)&n); -+ D1(printk(KERN_DEBUG "obliterating obsoleted node at 0x%08x\n", ref_offset(ref))); -+ ret = jffs2_flash_read(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n); - if (ret) { -- printk(KERN_WARNING "Read error reading from obsoleted node at 0x%08x: %d\n", ref->flash_offset &~3, ret); -+ printk(KERN_WARNING "Read error reading from obsoleted node at 0x%08x: %d\n", ref_offset(ref), ret); - return; - } - if (retlen != sizeof(n)) { -- printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %d\n", ref->flash_offset &~3, retlen); -+ printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen); - return; - } -- if (PAD(n.totlen) != PAD(ref->totlen)) { -- printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen in node ref (0x%08x)\n", n.totlen, ref->totlen); -+ if (PAD(je32_to_cpu(n.totlen)) != PAD(ref_totlen(c, jeb, ref))) { -+ printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n", je32_to_cpu(n.totlen), ref_totlen(c, jeb, ref)); - return; - } -- if (!(n.nodetype & JFFS2_NODE_ACCURATE)) { -- D1(printk(KERN_DEBUG "Node at 0x%08x was already marked obsolete (nodetype 0x%04x\n", ref->flash_offset &~3, n.nodetype)); -+ if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) { -+ D1(printk(KERN_DEBUG "Node at 0x%08x was already marked obsolete (nodetype 0x%04x)\n", ref_offset(ref), je16_to_cpu(n.nodetype))); - return; - } -- n.nodetype &= ~JFFS2_NODE_ACCURATE; -- ret = c->mtd->write(c->mtd, ref->flash_offset&~3, sizeof(n), &retlen, (char *)&n); -+ /* XXX FIXME: This is ugly now */ -+ n.nodetype = cpu_to_je16(je16_to_cpu(n.nodetype) & ~JFFS2_NODE_ACCURATE); -+ ret = jffs2_flash_write(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n); - if (ret) { -- printk(KERN_WARNING "Write error in obliterating obsoleted node at 0x%08x: %d\n", ref->flash_offset &~3, ret); -+ printk(KERN_WARNING "Write error in obliterating obsoleted node at 0x%08x: %d\n", ref_offset(ref), ret); - return; - } - if (retlen != sizeof(n)) { -- printk(KERN_WARNING "Short write in obliterating obsoleted node at 0x%08x: %d\n", ref->flash_offset &~3, retlen); -+ printk(KERN_WARNING "Short write in obliterating obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen); - return; - } - } -+ -+#if CONFIG_JFFS2_FS_DEBUG > 0 -+void jffs2_dump_block_lists(struct jffs2_sb_info *c) -+{ -+ -+ -+ printk(KERN_DEBUG "jffs2_dump_block_lists:\n"); -+ printk(KERN_DEBUG "flash_size: %08x\n", c->flash_size); -+ printk(KERN_DEBUG "used_size: %08x\n", c->used_size); -+ printk(KERN_DEBUG "dirty_size: %08x\n", c->dirty_size); -+ printk(KERN_DEBUG "wasted_size: %08x\n", c->wasted_size); -+ printk(KERN_DEBUG "unchecked_size: %08x\n", c->unchecked_size); -+ printk(KERN_DEBUG "free_size: %08x\n", c->free_size); -+ printk(KERN_DEBUG "erasing_size: %08x\n", c->erasing_size); -+ printk(KERN_DEBUG "bad_size: %08x\n", c->bad_size); -+ printk(KERN_DEBUG "sector_size: %08x\n", c->sector_size); -+ printk(KERN_DEBUG "jffs2_reserved_blocks size: %08x\n",c->sector_size * c->resv_blocks_write); -+ -+ if (c->nextblock) { -+ printk(KERN_DEBUG "nextblock: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->unchecked_size, c->nextblock->free_size); -+ } else { -+ printk(KERN_DEBUG "nextblock: NULL\n"); -+ } -+ if (c->gcblock) { -+ printk(KERN_DEBUG "gcblock: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size); -+ } else { -+ printk(KERN_DEBUG "gcblock: NULL\n"); -+ } -+ if (list_empty(&c->clean_list)) { -+ printk(KERN_DEBUG "clean_list: empty\n"); -+ } else { -+ struct list_head *this; -+ int numblocks = 0; -+ uint32_t dirty = 0; -+ -+ list_for_each(this, &c->clean_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ numblocks ++; -+ dirty += jeb->wasted_size; -+ printk(KERN_DEBUG "clean_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ printk (KERN_DEBUG "Contains %d blocks with total wasted size %u, average wasted size: %u\n", numblocks, dirty, dirty / numblocks); -+ } -+ if (list_empty(&c->very_dirty_list)) { -+ printk(KERN_DEBUG "very_dirty_list: empty\n"); -+ } else { -+ struct list_head *this; -+ int numblocks = 0; -+ uint32_t dirty = 0; -+ -+ list_for_each(this, &c->very_dirty_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ numblocks ++; -+ dirty += jeb->dirty_size; -+ printk(KERN_DEBUG "very_dirty_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", -+ numblocks, dirty, dirty / numblocks); -+ } -+ if (list_empty(&c->dirty_list)) { -+ printk(KERN_DEBUG "dirty_list: empty\n"); -+ } else { -+ struct list_head *this; -+ int numblocks = 0; -+ uint32_t dirty = 0; -+ -+ list_for_each(this, &c->dirty_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ numblocks ++; -+ dirty += jeb->dirty_size; -+ printk(KERN_DEBUG "dirty_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", -+ numblocks, dirty, dirty / numblocks); -+ } -+ if (list_empty(&c->erasable_list)) { -+ printk(KERN_DEBUG "erasable_list: empty\n"); -+ } else { -+ struct list_head *this; -+ -+ list_for_each(this, &c->erasable_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ printk(KERN_DEBUG "erasable_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ } -+ if (list_empty(&c->erasing_list)) { -+ printk(KERN_DEBUG "erasing_list: empty\n"); -+ } else { -+ struct list_head *this; -+ -+ list_for_each(this, &c->erasing_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ printk(KERN_DEBUG "erasing_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ } -+ if (list_empty(&c->erase_pending_list)) { -+ printk(KERN_DEBUG "erase_pending_list: empty\n"); -+ } else { -+ struct list_head *this; -+ -+ list_for_each(this, &c->erase_pending_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ printk(KERN_DEBUG "erase_pending_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ } -+ if (list_empty(&c->erasable_pending_wbuf_list)) { -+ printk(KERN_DEBUG "erasable_pending_wbuf_list: empty\n"); -+ } else { -+ struct list_head *this; -+ -+ list_for_each(this, &c->erasable_pending_wbuf_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ printk(KERN_DEBUG "erasable_pending_wbuf_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ } -+ if (list_empty(&c->free_list)) { -+ printk(KERN_DEBUG "free_list: empty\n"); -+ } else { -+ struct list_head *this; -+ -+ list_for_each(this, &c->free_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ printk(KERN_DEBUG "free_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ } -+ if (list_empty(&c->bad_list)) { -+ printk(KERN_DEBUG "bad_list: empty\n"); -+ } else { -+ struct list_head *this; -+ -+ list_for_each(this, &c->bad_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ printk(KERN_DEBUG "bad_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ } -+ if (list_empty(&c->bad_used_list)) { -+ printk(KERN_DEBUG "bad_used_list: empty\n"); -+ } else { -+ struct list_head *this; -+ -+ list_for_each(this, &c->bad_used_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ printk(KERN_DEBUG "bad_used_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", -+ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); -+ } -+ } -+} -+#endif /* CONFIG_JFFS2_FS_DEBUG */ -+ -+int jffs2_thread_should_wake(struct jffs2_sb_info *c) -+{ -+ int ret = 0; -+ uint32_t dirty; -+ -+ if (c->unchecked_size) { -+ D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): unchecked_size %d, checked_ino #%d\n", -+ c->unchecked_size, c->checked_ino)); -+ return 1; -+ } -+ -+ /* dirty_size contains blocks on erase_pending_list -+ * those blocks are counted in c->nr_erasing_blocks. -+ * If one block is actually erased, it is not longer counted as dirty_space -+ * but it is counted in c->nr_erasing_blocks, so we add it and subtract it -+ * with c->nr_erasing_blocks * c->sector_size again. -+ * Blocks on erasable_list are counted as dirty_size, but not in c->nr_erasing_blocks -+ * This helps us to force gc and pick eventually a clean block to spread the load. -+ */ -+ dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size; -+ -+ if (c->nr_free_blocks + c->nr_erasing_blocks < c->resv_blocks_gctrigger && -+ (dirty > c->nospc_dirty_size)) -+ ret = 1; -+ -+ D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x: %s\n", -+ c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, ret?"yes":"no")); -+ -+ return ret; -+} -diff -Nurb linux-mips-2.4.27/fs/jffs2/os-linux.h linux/fs/jffs2/os-linux.h ---- linux-mips-2.4.27/fs/jffs2/os-linux.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/os-linux.h 2004-11-19 10:25:12.116166808 +0100 -@@ -0,0 +1,212 @@ -+/* -+ * JFFS2 -- Journalling Flash File System, Version 2. -+ * -+ * Copyright (C) 2002-2003 Red Hat, Inc. -+ * -+ * Created by David Woodhouse -+ * -+ * For licensing information, see the file 'LICENCE' in this directory. -+ * -+ * $Id$ -+ * -+ */ -+ -+#ifndef __JFFS2_OS_LINUX_H__ -+#define __JFFS2_OS_LINUX_H__ -+#include -+ -+/* JFFS2 uses Linux mode bits natively -- no need for conversion */ -+#define os_to_jffs2_mode(x) (x) -+#define jffs2_to_os_mode(x) (x) -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,73) -+#define kstatfs statfs -+#endif -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2) -+#define JFFS2_INODE_INFO(i) (list_entry(i, struct jffs2_inode_info, vfs_inode)) -+#define OFNI_EDONI_2SFFJ(f) (&(f)->vfs_inode) -+#define JFFS2_SB_INFO(sb) (sb->s_fs_info) -+#define OFNI_BS_2SFFJ(c) ((struct super_block *)c->os_priv) -+#elif defined(JFFS2_OUT_OF_KERNEL) -+#define JFFS2_INODE_INFO(i) ((struct jffs2_inode_info *) &(i)->u) -+#define OFNI_EDONI_2SFFJ(f) ((struct inode *) ( ((char *)f) - ((char *)(&((struct inode *)NULL)->u)) ) ) -+#define JFFS2_SB_INFO(sb) ((struct jffs2_sb_info *) &(sb)->u) -+#define OFNI_BS_2SFFJ(c) ((struct super_block *) ( ((char *)c) - ((char *)(&((struct super_block *)NULL)->u)) ) ) -+#else -+#define JFFS2_INODE_INFO(i) (&i->u.jffs2_i) -+#define OFNI_EDONI_2SFFJ(f) ((struct inode *) ( ((char *)f) - ((char *)(&((struct inode *)NULL)->u)) ) ) -+#define JFFS2_SB_INFO(sb) (&sb->u.jffs2_sb) -+#define OFNI_BS_2SFFJ(c) ((struct super_block *) ( ((char *)c) - ((char *)(&((struct super_block *)NULL)->u)) ) ) -+#endif -+ -+ -+#define JFFS2_F_I_SIZE(f) (OFNI_EDONI_2SFFJ(f)->i_size) -+#define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode) -+#define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid) -+#define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid) -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,1) -+#define JFFS2_F_I_RDEV_MIN(f) (iminor(OFNI_EDONI_2SFFJ(f))) -+#define JFFS2_F_I_RDEV_MAJ(f) (imajor(OFNI_EDONI_2SFFJ(f))) -+#else -+#define JFFS2_F_I_RDEV_MIN(f) (MINOR(to_kdev_t(OFNI_EDONI_2SFFJ(f)->i_rdev))) -+#define JFFS2_F_I_RDEV_MAJ(f) (MAJOR(to_kdev_t(OFNI_EDONI_2SFFJ(f)->i_rdev))) -+#endif -+ -+/* Urgh. The things we do to keep the 2.4 build working */ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,47) -+#define ITIME(sec) ((struct timespec){sec, 0}) -+#define I_SEC(tv) ((tv).tv_sec) -+#define JFFS2_F_I_CTIME(f) (OFNI_EDONI_2SFFJ(f)->i_ctime.tv_sec) -+#define JFFS2_F_I_MTIME(f) (OFNI_EDONI_2SFFJ(f)->i_mtime.tv_sec) -+#define JFFS2_F_I_ATIME(f) (OFNI_EDONI_2SFFJ(f)->i_atime.tv_sec) -+#else -+#define ITIME(x) (x) -+#define I_SEC(x) (x) -+#define JFFS2_F_I_CTIME(f) (OFNI_EDONI_2SFFJ(f)->i_ctime) -+#define JFFS2_F_I_MTIME(f) (OFNI_EDONI_2SFFJ(f)->i_mtime) -+#define JFFS2_F_I_ATIME(f) (OFNI_EDONI_2SFFJ(f)->i_atime) -+#endif -+ -+#define sleep_on_spinunlock(wq, s) \ -+ do { \ -+ DECLARE_WAITQUEUE(__wait, current); \ -+ add_wait_queue((wq), &__wait); \ -+ set_current_state(TASK_UNINTERRUPTIBLE); \ -+ spin_unlock(s); \ -+ schedule(); \ -+ remove_wait_queue((wq), &__wait); \ -+ } while(0) -+ -+static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) -+{ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2) -+ f->highest_version = 0; -+ f->fragtree = RB_ROOT; -+ f->metadata = NULL; -+ f->dents = NULL; -+ f->flags = 0; -+ f->usercompr = 0; -+#else -+ memset(f, 0, sizeof(*f)); -+ init_MUTEX_LOCKED(&f->sem); -+#endif -+} -+ -+#define jffs2_is_readonly(c) (OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY) -+ -+#ifndef CONFIG_JFFS2_FS_NAND -+#define jffs2_can_mark_obsolete(c) (1) -+#define jffs2_cleanmarker_oob(c) (0) -+#define jffs2_write_nand_cleanmarker(c,jeb) (-EIO) -+ -+#define jffs2_flash_write(c, ofs, len, retlen, buf) ((c)->mtd->write((c)->mtd, ofs, len, retlen, buf)) -+#define jffs2_flash_read(c, ofs, len, retlen, buf) ((c)->mtd->read((c)->mtd, ofs, len, retlen, buf)) -+#define jffs2_flush_wbuf_pad(c) ({ (void)(c), 0; }) -+#define jffs2_flush_wbuf_gc(c, i) ({ (void)(c), (void) i, 0; }) -+#define jffs2_nand_read_failcnt(c,jeb) do { ; } while(0) -+#define jffs2_write_nand_badblock(c,jeb) do { ; } while(0) -+#define jffs2_nand_flash_setup(c) (0) -+#define jffs2_nand_flash_cleanup(c) do {} while(0) -+#define jffs2_wbuf_dirty(c) (0) -+#define jffs2_flash_writev(a,b,c,d,e,f) jffs2_flash_direct_writev(a,b,c,d,e) -+#define jffs2_wbuf_timeout NULL -+#define jffs2_wbuf_process NULL -+ -+#else /* NAND support present */ -+ -+#define jffs2_can_mark_obsolete(c) (c->mtd->type == MTD_NORFLASH || c->mtd->type == MTD_RAM) -+#define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH) -+ -+#define jffs2_flash_write_oob(c, ofs, len, retlen, buf) ((c)->mtd->write_oob((c)->mtd, ofs, len, retlen, buf)) -+#define jffs2_flash_read_oob(c, ofs, len, retlen, buf) ((c)->mtd->read_oob((c)->mtd, ofs, len, retlen, buf)) -+#define jffs2_wbuf_dirty(c) (!!(c)->wbuf_len) -+struct kstatfs; -+ -+/* wbuf.c */ -+int jffs2_flash_writev(struct jffs2_sb_info *c, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino); -+int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf); -+int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, u_char *buf); -+int jffs2_check_oob_empty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,int mode); -+int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+void jffs2_wbuf_timeout(unsigned long data); -+void jffs2_wbuf_process(void *data); -+int jffs2_nand_flash_setup(struct jffs2_sb_info *c); -+void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c); -+#endif /* NAND */ -+ -+/* erase.c */ -+static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) -+{ -+ OFNI_BS_2SFFJ(c)->s_dirt = 1; -+} -+ -+/* background.c */ -+int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c); -+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 struct inode_operations jffs2_dir_inode_operations; -+ -+/* file.c */ -+extern 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); -+int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg); -+int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg); -+int jffs2_readpage (struct file *, struct page *); -+int jffs2_prepare_write (struct file *, struct page *, unsigned, unsigned); -+int jffs2_commit_write (struct file *, struct page *, unsigned, unsigned); -+ -+/* ioctl.c */ -+int jffs2_ioctl(struct inode *, struct file *, unsigned int, unsigned long); -+ -+/* symlink.c */ -+extern struct inode_operations jffs2_symlink_inode_operations; -+ -+/* fs.c */ -+int jffs2_setattr (struct dentry *, struct iattr *); -+void jffs2_read_inode (struct inode *); -+void jffs2_clear_inode (struct inode *); -+void jffs2_dirty_inode(struct inode *inode); -+struct inode *jffs2_new_inode (struct inode *dir_i, int mode, -+ struct jffs2_raw_inode *ri); -+int jffs2_statfs (struct super_block *, struct kstatfs *); -+void jffs2_write_super (struct super_block *); -+int jffs2_remount_fs (struct super_block *, int *, char *); -+int jffs2_do_fill_super(struct super_block *sb, void *data, int silent); -+void jffs2_gc_release_inode(struct jffs2_sb_info *c, -+ struct jffs2_inode_info *f); -+struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, -+ int inum, int nlink); -+ -+unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, -+ struct jffs2_inode_info *f, -+ unsigned long offset, -+ unsigned long *priv); -+void jffs2_gc_release_page(struct jffs2_sb_info *c, -+ unsigned char *pg, -+ unsigned long *priv); -+ -+ -+/* writev.c */ -+int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs, -+ unsigned long count, loff_t to, size_t *retlen); -+ -+/* Compression config */ -+#define JFFS2_COMPRESSION -+#undef JFFS2_USE_DYNRUBIN /* Disabled 23/9/1. With zlib it hardly ever gets a look in */ -+#undef JFFS2_USE_RUBINMIPS /* Disabled 26/2/1. Obsoleted by dynrubin */ -+#define JFFS2_USE_ZLIB -+#define JFFS2_USE_RTIME /* rtime does manage to recompress already-compressed data */ -+ -+ -+#endif /* __JFFS2_OS_LINUX_H__ */ -+ -+ -diff -Nurb linux-mips-2.4.27/fs/jffs2/pushpull.h linux/fs/jffs2/pushpull.h ---- linux-mips-2.4.27/fs/jffs2/pushpull.h 2001-11-05 21:16:19.000000000 +0100 -+++ linux/fs/jffs2/pushpull.h 2004-11-19 10:25:12.118166504 +0100 -@@ -1,42 +1,21 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001, 2002 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #ifndef __PUSHPULL_H__ - #define __PUSHPULL_H__ -+ -+#include -+ - struct pushpull { - unsigned char *buf; - unsigned int buflen; -@@ -44,9 +23,36 @@ - unsigned int reserve; - }; - --void init_pushpull(struct pushpull *, char *, unsigned, unsigned, unsigned); --int pushbit(struct pushpull *pp, int bit, int use_reserved); --int pushedbits(struct pushpull *pp); -+ -+static inline void init_pushpull(struct pushpull *pp, char *buf, unsigned buflen, unsigned ofs, unsigned reserve) -+{ -+ pp->buf = buf; -+ pp->buflen = buflen; -+ pp->ofs = ofs; -+ pp->reserve = reserve; -+} -+ -+static inline int pushbit(struct pushpull *pp, int bit, int use_reserved) -+{ -+ if (pp->ofs >= pp->buflen - (use_reserved?0:pp->reserve)) { -+ return -ENOSPC; -+ } -+ -+ if (bit) { -+ pp->buf[pp->ofs >> 3] |= (1<<(7-(pp->ofs &7))); -+ } -+ else { -+ pp->buf[pp->ofs >> 3] &= ~(1<<(7-(pp->ofs &7))); -+ } -+ pp->ofs++; -+ -+ return 0; -+} -+ -+static inline int pushedbits(struct pushpull *pp) -+{ -+ return pp->ofs; -+} - - static inline int pullbit(struct pushpull *pp) - { -diff -Nurb linux-mips-2.4.27/fs/jffs2/rbtree.c linux/fs/jffs2/rbtree.c ---- linux-mips-2.4.27/fs/jffs2/rbtree.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/rbtree.c 2004-11-19 10:25:12.120166200 +0100 -@@ -0,0 +1,363 @@ -+/* -+ Red Black Trees -+ (C) 1999 Andrea Arcangeli -+ (C) 2002 David Woodhouse -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the 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 -+ -+ $Id$ -+*/ -+ -+#ifdef __ECOS /* This file is _not_ under the eCos licence; it is pure GPL. */ -+#error "Licence problem. eCos has its own rbtree code." -+#endif -+ -+#include -+#include -+ -+/* This wasn't present till 2.4.11, wasn't exported till 2.4.19 */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,11) || \ -+ (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19) && defined(MODULE)) -+static void __rb_rotate_left(struct rb_node * node, struct rb_root * root) -+{ -+ struct rb_node * right = node->rb_right; -+ -+ if ((node->rb_right = right->rb_left)) -+ right->rb_left->rb_parent = node; -+ right->rb_left = node; -+ -+ if ((right->rb_parent = node->rb_parent)) -+ { -+ if (node == node->rb_parent->rb_left) -+ node->rb_parent->rb_left = right; -+ else -+ node->rb_parent->rb_right = right; -+ } -+ else -+ root->rb_node = right; -+ node->rb_parent = right; -+} -+ -+static void __rb_rotate_right(struct rb_node * node, struct rb_root * root) -+{ -+ struct rb_node * left = node->rb_left; -+ -+ if ((node->rb_left = left->rb_right)) -+ left->rb_right->rb_parent = node; -+ left->rb_right = node; -+ -+ if ((left->rb_parent = node->rb_parent)) -+ { -+ if (node == node->rb_parent->rb_right) -+ node->rb_parent->rb_right = left; -+ else -+ node->rb_parent->rb_left = left; -+ } -+ else -+ root->rb_node = left; -+ node->rb_parent = left; -+} -+ -+void rb_insert_color(struct rb_node * node, struct rb_root * root) -+{ -+ struct rb_node * parent, * gparent; -+ -+ while ((parent = node->rb_parent) && parent->rb_color == RB_RED) -+ { -+ gparent = parent->rb_parent; -+ -+ if (parent == gparent->rb_left) -+ { -+ { -+ register struct rb_node * uncle = gparent->rb_right; -+ if (uncle && uncle->rb_color == RB_RED) -+ { -+ uncle->rb_color = RB_BLACK; -+ parent->rb_color = RB_BLACK; -+ gparent->rb_color = RB_RED; -+ node = gparent; -+ continue; -+ } -+ } -+ -+ if (parent->rb_right == node) -+ { -+ register struct rb_node * tmp; -+ __rb_rotate_left(parent, root); -+ tmp = parent; -+ parent = node; -+ node = tmp; -+ } -+ -+ parent->rb_color = RB_BLACK; -+ gparent->rb_color = RB_RED; -+ __rb_rotate_right(gparent, root); -+ } else { -+ { -+ register struct rb_node * uncle = gparent->rb_left; -+ if (uncle && uncle->rb_color == RB_RED) -+ { -+ uncle->rb_color = RB_BLACK; -+ parent->rb_color = RB_BLACK; -+ gparent->rb_color = RB_RED; -+ node = gparent; -+ continue; -+ } -+ } -+ -+ if (parent->rb_left == node) -+ { -+ register struct rb_node * tmp; -+ __rb_rotate_right(parent, root); -+ tmp = parent; -+ parent = node; -+ node = tmp; -+ } -+ -+ parent->rb_color = RB_BLACK; -+ gparent->rb_color = RB_RED; -+ __rb_rotate_left(gparent, root); -+ } -+ } -+ -+ root->rb_node->rb_color = RB_BLACK; -+} -+ -+static void __rb_erase_color(struct rb_node * node, struct rb_node * parent, -+ struct rb_root * root) -+{ -+ struct rb_node * other; -+ -+ while ((!node || node->rb_color == RB_BLACK) && node != root->rb_node) -+ { -+ if (parent->rb_left == node) -+ { -+ other = parent->rb_right; -+ if (other->rb_color == RB_RED) -+ { -+ other->rb_color = RB_BLACK; -+ parent->rb_color = RB_RED; -+ __rb_rotate_left(parent, root); -+ other = parent->rb_right; -+ } -+ if ((!other->rb_left || -+ other->rb_left->rb_color == RB_BLACK) -+ && (!other->rb_right || -+ other->rb_right->rb_color == RB_BLACK)) -+ { -+ other->rb_color = RB_RED; -+ node = parent; -+ parent = node->rb_parent; -+ } -+ else -+ { -+ if (!other->rb_right || -+ other->rb_right->rb_color == RB_BLACK) -+ { -+ register struct rb_node * o_left; -+ if ((o_left = other->rb_left)) -+ o_left->rb_color = RB_BLACK; -+ other->rb_color = RB_RED; -+ __rb_rotate_right(other, root); -+ other = parent->rb_right; -+ } -+ other->rb_color = parent->rb_color; -+ parent->rb_color = RB_BLACK; -+ if (other->rb_right) -+ other->rb_right->rb_color = RB_BLACK; -+ __rb_rotate_left(parent, root); -+ node = root->rb_node; -+ break; -+ } -+ } -+ else -+ { -+ other = parent->rb_left; -+ if (other->rb_color == RB_RED) -+ { -+ other->rb_color = RB_BLACK; -+ parent->rb_color = RB_RED; -+ __rb_rotate_right(parent, root); -+ other = parent->rb_left; -+ } -+ if ((!other->rb_left || -+ other->rb_left->rb_color == RB_BLACK) -+ && (!other->rb_right || -+ other->rb_right->rb_color == RB_BLACK)) -+ { -+ other->rb_color = RB_RED; -+ node = parent; -+ parent = node->rb_parent; -+ } -+ else -+ { -+ if (!other->rb_left || -+ other->rb_left->rb_color == RB_BLACK) -+ { -+ register struct rb_node * o_right; -+ if ((o_right = other->rb_right)) -+ o_right->rb_color = RB_BLACK; -+ other->rb_color = RB_RED; -+ __rb_rotate_left(other, root); -+ other = parent->rb_left; -+ } -+ other->rb_color = parent->rb_color; -+ parent->rb_color = RB_BLACK; -+ if (other->rb_left) -+ other->rb_left->rb_color = RB_BLACK; -+ __rb_rotate_right(parent, root); -+ node = root->rb_node; -+ break; -+ } -+ } -+ } -+ if (node) -+ node->rb_color = RB_BLACK; -+} -+ -+void rb_erase(struct rb_node * node, struct rb_root * root) -+{ -+ struct rb_node * child, * parent; -+ int color; -+ -+ if (!node->rb_left) -+ child = node->rb_right; -+ else if (!node->rb_right) -+ child = node->rb_left; -+ else -+ { -+ struct rb_node * old = node, * left; -+ -+ node = node->rb_right; -+ while ((left = node->rb_left)) -+ node = left; -+ child = node->rb_right; -+ parent = node->rb_parent; -+ color = node->rb_color; -+ -+ if (child) -+ child->rb_parent = parent; -+ if (parent) -+ { -+ if (parent->rb_left == node) -+ parent->rb_left = child; -+ else -+ parent->rb_right = child; -+ } -+ else -+ root->rb_node = child; -+ -+ if (node->rb_parent == old) -+ parent = node; -+ node->rb_parent = old->rb_parent; -+ node->rb_color = old->rb_color; -+ node->rb_right = old->rb_right; -+ node->rb_left = old->rb_left; -+ -+ if (old->rb_parent) -+ { -+ if (old->rb_parent->rb_left == old) -+ old->rb_parent->rb_left = node; -+ else -+ old->rb_parent->rb_right = node; -+ } else -+ root->rb_node = node; -+ -+ old->rb_left->rb_parent = node; -+ if (old->rb_right) -+ old->rb_right->rb_parent = node; -+ goto color; -+ } -+ -+ parent = node->rb_parent; -+ color = node->rb_color; -+ -+ if (child) -+ child->rb_parent = parent; -+ if (parent) -+ { -+ if (parent->rb_left == node) -+ parent->rb_left = child; -+ else -+ parent->rb_right = child; -+ } -+ else -+ root->rb_node = child; -+ -+ color: -+ if (color == RB_BLACK) -+ __rb_erase_color(child, parent, root); -+} -+#endif /* Before 2.4.11 */ -+ -+ /* These routines haven't made it into 2.4 (yet) */ -+struct rb_node *rb_next(struct rb_node *node) -+{ -+ /* If we have a right-hand child, go down and then left as far -+ as we can. */ -+ if (node->rb_right) { -+ node = node->rb_right; -+ while (node->rb_left) -+ node=node->rb_left; -+ return node; -+ } -+ -+ /* No right-hand children. Everything down and left is -+ smaller than us, so any 'next' node must be in the general -+ direction of our parent. Go up the tree; any time the -+ ancestor is a right-hand child of its parent, keep going -+ up. First time it's a left-hand child of its parent, said -+ parent is our 'next' node. */ -+ while (node->rb_parent && node == node->rb_parent->rb_right) -+ node = node->rb_parent; -+ -+ return node->rb_parent; -+} -+ -+struct rb_node *rb_prev(struct rb_node *node) -+{ -+ if (node->rb_left) { -+ node = node->rb_left; -+ while (node->rb_right) -+ node=node->rb_right; -+ return node; -+ } -+ while (node->rb_parent && node == node->rb_parent->rb_left) -+ node = node->rb_parent; -+ -+ return node->rb_parent; -+} -+ -+void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root) -+{ -+ struct rb_node *parent = victim->rb_parent; -+ -+ /* Set the surrounding nodes to point to the replacement */ -+ if (parent) { -+ if (victim == parent->rb_left) -+ parent->rb_left = new; -+ else -+ parent->rb_right = new; -+ } else { -+ root->rb_node = new; -+ } -+ if (victim->rb_left) -+ victim->rb_left->rb_parent = new; -+ if (victim->rb_right) -+ victim->rb_right->rb_parent = new; -+ -+ /* Copy the pointers/colour from the victim to the replacement */ -+ *new = *victim; -+} -diff -Nurb linux-mips-2.4.27/fs/jffs2/read.c linux/fs/jffs2/read.c ---- linux-mips-2.4.27/fs/jffs2/read.c 2003-11-17 02:07:44.000000000 +0100 -+++ linux/fs/jffs2/read.c 2004-11-19 10:25:12.121166048 +0100 -@@ -1,52 +1,29 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include - #include --#include -+#include -+#include - #include -+#include - #include "nodelist.h" --#include - - int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsigned char *buf, int ofs, int len) - { - struct jffs2_raw_inode *ri; - size_t readlen; -- __u32 crc; -+ uint32_t crc; - unsigned char *decomprbuf = NULL; - unsigned char *readbuf = NULL; - int ret = 0; -@@ -55,35 +32,41 @@ - if (!ri) - return -ENOMEM; - -- ret = c->mtd->read(c->mtd, fd->raw->flash_offset & ~3, sizeof(*ri), &readlen, (char *)ri); -+ ret = jffs2_flash_read(c, ref_offset(fd->raw), sizeof(*ri), &readlen, (char *)ri); - if (ret) { - jffs2_free_raw_inode(ri); -- printk(KERN_WARNING "Error reading node from 0x%08x: %d\n", fd->raw->flash_offset & ~3, ret); -+ printk(KERN_WARNING "Error reading node from 0x%08x: %d\n", ref_offset(fd->raw), ret); - return ret; - } - if (readlen != sizeof(*ri)) { - jffs2_free_raw_inode(ri); -- printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%x bytes, got 0x%x\n", -- fd->raw->flash_offset & ~3, sizeof(*ri), readlen); -+ printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%zx bytes, got 0x%zx\n", -+ ref_offset(fd->raw), sizeof(*ri), readlen); - return -EIO; - } - crc = crc32(0, ri, sizeof(*ri)-8); - -- D1(printk(KERN_DEBUG "Node read from %08x: node_crc %08x, calculated CRC %08x. dsize %x, csize %x, offset %x, buf %p\n", fd->raw->flash_offset & ~3, ri->node_crc, crc, ri->dsize, ri->csize, ri->offset, buf)); -- if (crc != ri->node_crc) { -- printk(KERN_WARNING "Node CRC %08x != calculated CRC %08x for node at %08x\n", ri->node_crc, crc, fd->raw->flash_offset & ~3); -+ D1(printk(KERN_DEBUG "Node read from %08x: node_crc %08x, calculated CRC %08x. dsize %x, csize %x, offset %x, buf %p\n", -+ ref_offset(fd->raw), je32_to_cpu(ri->node_crc), -+ crc, je32_to_cpu(ri->dsize), je32_to_cpu(ri->csize), -+ je32_to_cpu(ri->offset), buf)); -+ if (crc != je32_to_cpu(ri->node_crc)) { -+ printk(KERN_WARNING "Node CRC %08x != calculated CRC %08x for node at %08x\n", -+ je32_to_cpu(ri->node_crc), crc, ref_offset(fd->raw)); - ret = -EIO; - goto out_ri; - } - /* There was a bug where we wrote hole nodes out with csize/dsize - swapped. Deal with it */ -- if (ri->compr == JFFS2_COMPR_ZERO && !ri->dsize && ri->csize) { -+ if (ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) && -+ je32_to_cpu(ri->csize)) { - ri->dsize = ri->csize; -- ri->csize = 0; -+ ri->csize = cpu_to_je32(0); - } - -- D1(if(ofs + len > ri->dsize) { -- printk(KERN_WARNING "jffs2_read_dnode() asked for %d bytes at %d from %d-byte node\n", len, ofs, ri->dsize); -+ D1(if(ofs + len > je32_to_cpu(ri->dsize)) { -+ printk(KERN_WARNING "jffs2_read_dnode() asked for %d bytes at %d from %d-byte node\n", -+ len, ofs, je32_to_cpu(ri->dsize)); - ret = -EINVAL; - goto out_ri; - }); -@@ -100,18 +83,18 @@ - Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy - Reading partial node and it's compressed - read into readbuf, check checksum, decompress to decomprbuf and copy - */ -- if (ri->compr == JFFS2_COMPR_NONE && len == ri->dsize) { -+ if (ri->compr == JFFS2_COMPR_NONE && len == je32_to_cpu(ri->dsize)) { - readbuf = buf; - } else { -- readbuf = kmalloc(ri->csize, GFP_KERNEL); -+ readbuf = kmalloc(je32_to_cpu(ri->csize), GFP_KERNEL); - if (!readbuf) { - ret = -ENOMEM; - goto out_ri; - } - } - if (ri->compr != JFFS2_COMPR_NONE) { -- if (len < ri->dsize) { -- decomprbuf = kmalloc(ri->dsize, GFP_KERNEL); -+ if (len < je32_to_cpu(ri->dsize)) { -+ decomprbuf = kmalloc(je32_to_cpu(ri->dsize), GFP_KERNEL); - if (!decomprbuf) { - ret = -ENOMEM; - goto out_readbuf; -@@ -123,31 +106,35 @@ - decomprbuf = readbuf; - } - -- D2(printk(KERN_DEBUG "Read %d bytes to %p\n", ri->csize, readbuf)); -- ret = c->mtd->read(c->mtd, (fd->raw->flash_offset &~3) + sizeof(*ri), ri->csize, &readlen, readbuf); -+ D2(printk(KERN_DEBUG "Read %d bytes to %p\n", je32_to_cpu(ri->csize), -+ readbuf)); -+ ret = jffs2_flash_read(c, (ref_offset(fd->raw)) + sizeof(*ri), -+ je32_to_cpu(ri->csize), &readlen, readbuf); - -- if (!ret && readlen != ri->csize) -+ if (!ret && readlen != je32_to_cpu(ri->csize)) - ret = -EIO; - if (ret) - goto out_decomprbuf; - -- crc = crc32(0, readbuf, ri->csize); -- if (crc != ri->data_crc) { -- printk(KERN_WARNING "Data CRC %08x != calculated CRC %08x for node at %08x\n", ri->data_crc, crc, fd->raw->flash_offset & ~3); -+ crc = crc32(0, readbuf, je32_to_cpu(ri->csize)); -+ if (crc != je32_to_cpu(ri->data_crc)) { -+ printk(KERN_WARNING "Data CRC %08x != calculated CRC %08x for node at %08x\n", -+ je32_to_cpu(ri->data_crc), crc, ref_offset(fd->raw)); - ret = -EIO; - goto out_decomprbuf; - } - D2(printk(KERN_DEBUG "Data CRC matches calculated CRC %08x\n", crc)); - if (ri->compr != JFFS2_COMPR_NONE) { -- D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n", ri->csize, readbuf, ri->dsize, decomprbuf)); -- ret = jffs2_decompress(ri->compr, readbuf, decomprbuf, ri->csize, ri->dsize); -+ D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n", -+ je32_to_cpu(ri->csize), readbuf, je32_to_cpu(ri->dsize), decomprbuf)); -+ ret = jffs2_decompress(ri->compr, readbuf, decomprbuf, je32_to_cpu(ri->csize), je32_to_cpu(ri->dsize)); - if (ret) { - printk(KERN_WARNING "Error: jffs2_decompress returned %d\n", ret); - goto out_decomprbuf; - } - } - -- if (len < ri->dsize) { -+ if (len < je32_to_cpu(ri->dsize)) { - memcpy(buf, decomprbuf+ofs, len); - } - out_decomprbuf: -@@ -161,3 +148,96 @@ - - return ret; - } -+ -+int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, -+ unsigned char *buf, uint32_t offset, uint32_t len) -+{ -+ uint32_t end = offset + len; -+ struct jffs2_node_frag *frag; -+ int ret; -+ -+ D1(printk(KERN_DEBUG "jffs2_read_inode_range: ino #%u, range 0x%08x-0x%08x\n", -+ f->inocache->ino, offset, offset+len)); -+ -+ frag = jffs2_lookup_node_frag(&f->fragtree, offset); -+ -+ /* XXX FIXME: Where a single physical node actually shows up in two -+ frags, we read it twice. Don't do that. */ -+ /* Now we're pointing at the first frag which overlaps our page */ -+ while(offset < end) { -+ D2(printk(KERN_DEBUG "jffs2_read_inode_range: offset %d, end %d\n", offset, end)); -+ if (unlikely(!frag || frag->ofs > offset)) { -+ uint32_t holesize = end - offset; -+ if (frag) { -+ D1(printk(KERN_NOTICE "Eep. Hole in ino #%u fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n", f->inocache->ino, frag->ofs, offset)); -+ holesize = min(holesize, frag->ofs - offset); -+ D1(jffs2_print_frag_list(f)); -+ } -+ D1(printk(KERN_DEBUG "Filling non-frag hole from %d-%d\n", offset, offset+holesize)); -+ memset(buf, 0, holesize); -+ buf += holesize; -+ offset += holesize; -+ continue; -+ } else if (unlikely(!frag->node)) { -+ uint32_t holeend = min(end, frag->ofs + frag->size); -+ D1(printk(KERN_DEBUG "Filling frag hole from %d-%d (frag 0x%x 0x%x)\n", offset, holeend, frag->ofs, frag->ofs + frag->size)); -+ memset(buf, 0, holeend - offset); -+ buf += holeend - offset; -+ offset = holeend; -+ frag = frag_next(frag); -+ continue; -+ } else { -+ uint32_t readlen; -+ uint32_t fragofs; /* offset within the frag to start reading */ -+ -+ fragofs = offset - frag->ofs; -+ readlen = min(frag->size - fragofs, end - offset); -+ D1(printk(KERN_DEBUG "Reading %d-%d from node at 0x%08x (%d)\n", -+ frag->ofs+fragofs, frag->ofs+fragofs+readlen, -+ ref_offset(frag->node->raw), ref_flags(frag->node->raw))); -+ ret = jffs2_read_dnode(c, frag->node, buf, fragofs + frag->ofs - frag->node->ofs, readlen); -+ D2(printk(KERN_DEBUG "node read done\n")); -+ if (ret) { -+ D1(printk(KERN_DEBUG"jffs2_read_inode_range error %d\n",ret)); -+ memset(buf, 0, readlen); -+ return ret; -+ } -+ buf += readlen; -+ offset += readlen; -+ frag = frag_next(frag); -+ D2(printk(KERN_DEBUG "node read was OK. Looping\n")); -+ } -+ } -+ return 0; -+} -+ -+/* Core function to read symlink target. */ -+char *jffs2_getlink(struct jffs2_sb_info *c, struct jffs2_inode_info *f) -+{ -+ char *buf; -+ int ret; -+ -+ down(&f->sem); -+ -+ if (!f->metadata) { -+ printk(KERN_NOTICE "No metadata for symlink inode #%u\n", f->inocache->ino); -+ up(&f->sem); -+ return ERR_PTR(-EINVAL); -+ } -+ buf = kmalloc(f->metadata->size+1, GFP_USER); -+ if (!buf) { -+ up(&f->sem); -+ return ERR_PTR(-ENOMEM); -+ } -+ buf[f->metadata->size]=0; -+ -+ ret = jffs2_read_dnode(c, f->metadata, buf, 0, f->metadata->size); -+ -+ up(&f->sem); -+ -+ if (ret) { -+ kfree(buf); -+ return ERR_PTR(ret); -+ } -+ return buf; -+} -diff -Nurb linux-mips-2.4.27/fs/jffs2/readinode.c linux/fs/jffs2/readinode.c ---- linux-mips-2.4.27/fs/jffs2/readinode.c 2003-11-17 02:07:44.000000000 +0100 -+++ linux/fs/jffs2/readinode.c 2004-11-19 10:25:12.123165744 +0100 -@@ -1,79 +1,122 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - --/* Given an inode, probably with existing list of fragments, add the new node -- * to the fragment list. -- */ - #include - #include - #include -+#include -+#include - #include --#include -+#include - #include "nodelist.h" --#include - -+static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag); - --D1(void jffs2_print_frag_list(struct jffs2_inode_info *f) -+#if CONFIG_JFFS2_FS_DEBUG >= 1 -+static void jffs2_print_fragtree(struct rb_root *list, int permitbug) - { -- struct jffs2_node_frag *this = f->fraglist; -+ struct jffs2_node_frag *this = frag_first(list); -+ uint32_t lastofs = 0; -+ int buggy = 0; - - while(this) { - if (this->node) -- printk(KERN_DEBUG "frag %04x-%04x: 0x%08x on flash (*%p->%p)\n", this->ofs, this->ofs+this->size, this->node->raw->flash_offset &~3, this, this->next); -+ printk(KERN_DEBUG "frag %04x-%04x: 0x%08x(%d) on flash (*%p). left (%p), right (%p), parent (%p)\n", -+ this->ofs, this->ofs+this->size, ref_offset(this->node->raw), ref_flags(this->node->raw), -+ this, frag_left(this), frag_right(this), frag_parent(this)); - else -- printk(KERN_DEBUG "frag %04x-%04x: hole (*%p->%p)\n", this->ofs, this->ofs+this->size, this, this->next); -- this = this->next; -+ printk(KERN_DEBUG "frag %04x-%04x: hole (*%p). left (%p} right (%p), parent (%p)\n", this->ofs, -+ this->ofs+this->size, this, frag_left(this), frag_right(this), frag_parent(this)); -+ if (this->ofs != lastofs) -+ buggy = 1; -+ lastofs = this->ofs+this->size; -+ this = frag_next(this); -+ } -+ if (buggy && !permitbug) { -+ printk(KERN_CRIT "Frag tree got a hole in it\n"); -+ BUG(); - } -+} -+ -+void jffs2_print_frag_list(struct jffs2_inode_info *f) -+{ -+ jffs2_print_fragtree(&f->fragtree, 0); -+ - if (f->metadata) { -- printk(KERN_DEBUG "metadata at 0x%08x\n", f->metadata->raw->flash_offset &~3); -+ printk(KERN_DEBUG "metadata at 0x%08x\n", ref_offset(f->metadata->raw)); - } --}) -- -+} - --int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn) -+static int jffs2_sanitycheck_fragtree(struct jffs2_inode_info *f) - { -- int ret; -- D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)\n", f->inocache->ino, f, fn)); -+ struct jffs2_node_frag *frag; -+ int bitched = 0; - -- ret = jffs2_add_full_dnode_to_fraglist(c, &f->fraglist, fn); -+ for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) { - -- D2(jffs2_print_frag_list(f)); -- return ret; -+ struct jffs2_full_dnode *fn = frag->node; -+ if (!fn || !fn->raw) -+ continue; -+ -+ if (ref_flags(fn->raw) == REF_PRISTINE) { -+ -+ if (fn->frags > 1) { -+ printk(KERN_WARNING "REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2\n", ref_offset(fn->raw), fn->frags); -+ bitched = 1; -+ } -+ /* A hole node which isn't multi-page should be garbage-collected -+ and merged anyway, so we just check for the frag size here, -+ rather than mucking around with actually reading the node -+ and checking the compression type, which is the real way -+ to tell a hole node. */ -+ if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag) && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) { -+ printk(KERN_WARNING "REF_PRISTINE node at 0x%08x had a previous non-hole frag in the same page. Tell dwmw2\n", -+ ref_offset(fn->raw)); -+ bitched = 1; -+ } -+ -+ if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag) && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) { -+ printk(KERN_WARNING "REF_PRISTINE node at 0x%08x (%08x-%08x) had a following non-hole frag in the same page. Tell dwmw2\n", -+ ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size); -+ bitched = 1; -+ } -+ } -+ } -+ -+ if (bitched) { -+ struct jffs2_node_frag *thisfrag; -+ -+ printk(KERN_WARNING "Inode is #%u\n", f->inocache->ino); -+ thisfrag = frag_first(&f->fragtree); -+ while (thisfrag) { -+ if (!thisfrag->node) { -+ printk("Frag @0x%x-0x%x; node-less hole\n", -+ thisfrag->ofs, thisfrag->size + thisfrag->ofs); -+ } else if (!thisfrag->node->raw) { -+ printk("Frag @0x%x-0x%x; raw-less hole\n", -+ thisfrag->ofs, thisfrag->size + thisfrag->ofs); -+ } else { -+ printk("Frag @0x%x-0x%x; raw at 0x%08x(%d) (0x%x-0x%x)\n", -+ thisfrag->ofs, thisfrag->size + thisfrag->ofs, -+ ref_offset(thisfrag->node->raw), ref_flags(thisfrag->node->raw), -+ thisfrag->node->ofs, thisfrag->node->ofs+thisfrag->node->size); -+ } -+ thisfrag = frag_next(thisfrag); -+ } -+ } -+ return bitched; - } -+#endif /* D1 */ - - static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this) - { -@@ -82,42 +125,38 @@ - if (!this->node->frags) { - /* The node has no valid frags left. It's totally obsoleted */ - D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) obsolete\n", -- this->node->raw->flash_offset &~3, this->node->ofs, this->node->ofs+this->node->size)); -+ ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size)); - jffs2_mark_node_obsolete(c, this->node->raw); - jffs2_free_full_dnode(this->node); - } else { -- D2(printk(KERN_DEBUG "Not marking old node @0x%08x (0x%04x-0x%04x) obsolete. frags is %d\n", -- this->node->raw->flash_offset &~3, this->node->ofs, this->node->ofs+this->node->size, -+ D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n", -+ ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size, - this->node->frags)); -+ mark_ref_normal(this->node->raw); - } - - } - jffs2_free_node_frag(this); - } - --/* Doesn't set inode->i_size */ --int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct jffs2_node_frag **list, struct jffs2_full_dnode *fn) -+/* Given an inode, probably with existing list of fragments, add the new node -+ * to the fragment list. -+ */ -+int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn) - { -+ int ret; -+ struct jffs2_node_frag *newfrag; - -- struct jffs2_node_frag *this, **prev, *old; -- struct jffs2_node_frag *newfrag, *newfrag2; -- __u32 lastend = 0; -- -+ D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)\n", f->inocache->ino, f, fn)); - - newfrag = jffs2_alloc_node_frag(); -- if (!newfrag) { -+ if (unlikely(!newfrag)) - return -ENOMEM; -- } -- -- D2(if (fn->raw) -- printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, fn->raw->flash_offset &~3, newfrag); -- else -- printk(KERN_DEBUG "adding hole node %04x-%04x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, newfrag)); - -- prev = list; -- this = *list; -+ D2(printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n", -+ fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag)); - -- if (!fn->size) { -+ if (unlikely(!fn->size)) { - jffs2_free_node_frag(newfrag); - return 0; - } -@@ -126,176 +165,358 @@ - newfrag->size = fn->size; - newfrag->node = fn; - newfrag->node->frags = 1; -- newfrag->next = (void *)0xdeadbeef; -+ -+ ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag); -+ if (ret) -+ return ret; -+ -+ /* If we now share a page with other nodes, mark either previous -+ or next node REF_NORMAL, as appropriate. */ -+ if (newfrag->ofs & (PAGE_CACHE_SIZE-1)) { -+ struct jffs2_node_frag *prev = frag_prev(newfrag); -+ -+ mark_ref_normal(fn->raw); -+ /* If we don't start at zero there's _always_ a previous */ -+ if (prev->node) -+ mark_ref_normal(prev->node->raw); -+ } -+ -+ if ((newfrag->ofs+newfrag->size) & (PAGE_CACHE_SIZE-1)) { -+ struct jffs2_node_frag *next = frag_next(newfrag); -+ -+ if (next) { -+ mark_ref_normal(fn->raw); -+ if (next->node) -+ mark_ref_normal(next->node->raw); -+ } -+ } -+ D2(if (jffs2_sanitycheck_fragtree(f)) { -+ printk(KERN_WARNING "Just added node %04x-%04x @0x%08x on flash, newfrag *%p\n", -+ fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag); -+ return 0; -+ }) -+ D2(jffs2_print_frag_list(f)); -+ return 0; -+} -+ -+/* Doesn't set inode->i_size */ -+static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag) -+{ -+ struct jffs2_node_frag *this; -+ uint32_t lastend; - - /* Skip all the nodes which are completed before this one starts */ -- while(this && fn->ofs >= this->ofs+this->size) { -- lastend = this->ofs + this->size; -+ this = jffs2_lookup_node_frag(list, newfrag->node->ofs); - -- D2(printk(KERN_DEBUG "j_a_f_d_t_f: skipping frag 0x%04x-0x%04x; phys 0x%08x (*%p->%p)\n", -- this->ofs, this->ofs+this->size, this->node?(this->node->raw->flash_offset &~3):0xffffffff, this, this->next)); -- prev = &this->next; -- this = this->next; -+ if (this) { -+ D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", -+ this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this)); -+ lastend = this->ofs + this->size; -+ } else { -+ D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave no frag\n")); -+ lastend = 0; - } - - /* See if we ran off the end of the list */ -- if (!this) { -+ if (lastend <= newfrag->ofs) { - /* We did */ -- if (lastend < fn->ofs) { -+ -+ /* Check if 'this' node was on the same page as the new node. -+ If so, both 'this' and the new node get marked REF_NORMAL so -+ the GC can take a look. -+ */ -+ if ((lastend-1) >> PAGE_CACHE_SHIFT == newfrag->ofs >> PAGE_CACHE_SHIFT) { -+ if (this->node) -+ mark_ref_normal(this->node->raw); -+ mark_ref_normal(newfrag->node->raw); -+ } -+ -+ if (lastend < newfrag->node->ofs) { - /* ... and we need to put a hole in before the new node */ - struct jffs2_node_frag *holefrag = jffs2_alloc_node_frag(); -- if (!holefrag) -+ if (!holefrag) { -+ jffs2_free_node_frag(newfrag); - return -ENOMEM; -+ } - holefrag->ofs = lastend; -- holefrag->size = fn->ofs - lastend; -- holefrag->next = NULL; -+ holefrag->size = newfrag->node->ofs - lastend; - holefrag->node = NULL; -- *prev = holefrag; -- prev = &holefrag->next; -+ if (this) { -+ /* By definition, the 'this' node has no right-hand child, -+ because there are no frags with offset greater than it. -+ So that's where we want to put the hole */ -+ D2(printk(KERN_DEBUG "Adding hole frag (%p) on right of node at (%p)\n", holefrag, this)); -+ rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right); -+ } else { -+ D2(printk(KERN_DEBUG "Adding hole frag (%p) at root of tree\n", holefrag)); -+ rb_link_node(&holefrag->rb, NULL, &list->rb_node); -+ } -+ rb_insert_color(&holefrag->rb, list); -+ this = holefrag; - } -- newfrag->next = NULL; -- *prev = newfrag; -+ if (this) { -+ /* By definition, the 'this' node has no right-hand child, -+ because there are no frags with offset greater than it. -+ So that's where we want to put the hole */ -+ D2(printk(KERN_DEBUG "Adding new frag (%p) on right of node at (%p)\n", newfrag, this)); -+ rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); -+ } else { -+ D2(printk(KERN_DEBUG "Adding new frag (%p) at root of tree\n", newfrag)); -+ rb_link_node(&newfrag->rb, NULL, &list->rb_node); -+ } -+ rb_insert_color(&newfrag->rb, list); - return 0; - } - -- D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p->%p)\n", -- this->ofs, this->ofs+this->size, this->node?(this->node->raw->flash_offset &~3):0xffffffff, this, this->next)); -+ D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", -+ this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this)); - -- /* OK. 'this' is pointing at the first frag that fn->ofs at least partially obsoletes, -- * - i.e. fn->ofs < this->ofs+this->size && fn->ofs >= this->ofs -+ /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes, -+ * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs - */ -- if (fn->ofs > this->ofs) { -+ if (newfrag->ofs > this->ofs) { - /* This node isn't completely obsoleted. The start of it remains valid */ -- if (this->ofs + this->size > fn->ofs + fn->size) { -+ -+ /* Mark the new node and the partially covered node REF_NORMAL -- let -+ the GC take a look at them */ -+ mark_ref_normal(newfrag->node->raw); -+ if (this->node) -+ mark_ref_normal(this->node->raw); -+ -+ if (this->ofs + this->size > newfrag->ofs + newfrag->size) { - /* The new node splits 'this' frag into two */ -- newfrag2 = jffs2_alloc_node_frag(); -+ struct jffs2_node_frag *newfrag2 = jffs2_alloc_node_frag(); - if (!newfrag2) { - jffs2_free_node_frag(newfrag); - return -ENOMEM; - } -- D1(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size); -+ D2(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size); - if (this->node) -- printk("phys 0x%08x\n", this->node->raw->flash_offset &~3); -+ printk("phys 0x%08x\n", ref_offset(this->node->raw)); - else - printk("hole\n"); - ) -- newfrag2->ofs = fn->ofs + fn->size; -+ -+ /* New second frag pointing to this's node */ -+ newfrag2->ofs = newfrag->ofs + newfrag->size; - newfrag2->size = (this->ofs+this->size) - newfrag2->ofs; -- newfrag2->next = this->next; - newfrag2->node = this->node; - if (this->node) - this->node->frags++; -- newfrag->next = newfrag2; -- this->next = newfrag; -+ -+ /* Adjust size of original 'this' */ - this->size = newfrag->ofs - this->ofs; -+ -+ /* Now, we know there's no node with offset -+ greater than this->ofs but smaller than -+ newfrag2->ofs or newfrag->ofs, for obvious -+ reasons. So we can do a tree insert from -+ 'this' to insert newfrag, and a tree insert -+ from newfrag to insert newfrag2. */ -+ jffs2_fragtree_insert(newfrag, this); -+ rb_insert_color(&newfrag->rb, list); -+ -+ jffs2_fragtree_insert(newfrag2, newfrag); -+ rb_insert_color(&newfrag2->rb, list); -+ - return 0; - } - /* New node just reduces 'this' frag in size, doesn't split it */ -- this->size = fn->ofs - this->ofs; -- newfrag->next = this->next; -- this->next = newfrag; -- this = newfrag->next; -+ this->size = newfrag->ofs - this->ofs; -+ -+ /* Again, we know it lives down here in the tree */ -+ jffs2_fragtree_insert(newfrag, this); -+ rb_insert_color(&newfrag->rb, list); - } else { -- D2(printk(KERN_DEBUG "Inserting newfrag (*%p) in before 'this' (*%p)\n", newfrag, this)); -- *prev = newfrag; -- newfrag->next = this; -+ /* New frag starts at the same point as 'this' used to. Replace -+ it in the tree without doing a delete and insertion */ -+ D2(printk(KERN_DEBUG "Inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", -+ newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, -+ this, this->ofs, this->ofs+this->size)); -+ -+ rb_replace_node(&this->rb, &newfrag->rb, list); -+ -+ if (newfrag->ofs + newfrag->size >= this->ofs+this->size) { -+ D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size)); -+ jffs2_obsolete_node_frag(c, this); -+ } else { -+ this->ofs += newfrag->size; -+ this->size -= newfrag->size; -+ -+ jffs2_fragtree_insert(this, newfrag); -+ rb_insert_color(&this->rb, list); -+ return 0; - } -- /* OK, now we have newfrag added in the correct place in the list, but -- newfrag->next points to a fragment which may be overlapping it -+ } -+ /* OK, now we have newfrag added in the correct place in the tree, but -+ frag_next(newfrag) may be a fragment which is overlapped by it - */ -- while (this && newfrag->ofs + newfrag->size >= this->ofs + this->size) { -- /* 'this' frag is obsoleted. */ -- old = this; -- this = old->next; -- jffs2_obsolete_node_frag(c, old); -+ while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) { -+ /* 'this' frag is obsoleted completely. */ -+ D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x) and removing from tree\n", this, this->ofs, this->ofs+this->size)); -+ rb_erase(&this->rb, list); -+ jffs2_obsolete_node_frag(c, this); - } - /* Now we're pointing at the first frag which isn't totally obsoleted by - the new frag */ -- newfrag->next = this; - - if (!this || newfrag->ofs + newfrag->size == this->ofs) { - return 0; - } -- /* Still some overlap */ -+ /* Still some overlap but we don't need to move it in the tree */ - this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size); - this->ofs = newfrag->ofs + newfrag->size; -+ -+ /* And mark them REF_NORMAL so the GC takes a look at them */ -+ if (this->node) -+ mark_ref_normal(this->node->raw); -+ mark_ref_normal(newfrag->node->raw); -+ - return 0; - } - --void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct jffs2_node_frag **list, __u32 size) -+void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) - { -+ struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); -+ - D1(printk(KERN_DEBUG "Truncating fraglist to 0x%08x bytes\n", size)); - -- while (*list) { -- if ((*list)->ofs >= size) { -- struct jffs2_node_frag *this = *list; -- *list = this->next; -- D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", this->ofs, this->ofs+this->size)); -- jffs2_obsolete_node_frag(c, this); -- continue; -- } else if ((*list)->ofs + (*list)->size > size) { -- D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", (*list)->ofs, (*list)->ofs + (*list)->size)); -- (*list)->size = size - (*list)->ofs; -- } -- list = &(*list)->next; -+ /* We know frag->ofs <= size. That's what lookup does for us */ -+ if (frag && frag->ofs != size) { -+ if (frag->ofs+frag->size >= size) { -+ D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size)); -+ frag->size = size - frag->ofs; -+ } -+ frag = frag_next(frag); -+ } -+ while (frag && frag->ofs >= size) { -+ struct jffs2_node_frag *next = frag_next(frag); -+ -+ D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size)); -+ frag_erase(frag, list); -+ jffs2_obsolete_node_frag(c, frag); -+ frag = next; - } - } - - /* Scan the list of all nodes present for this ino, build map of versions, etc. */ - --void jffs2_read_inode (struct inode *inode) -+static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, -+ struct jffs2_inode_info *f, -+ struct jffs2_raw_inode *latest_node); -+ -+int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, -+ uint32_t ino, struct jffs2_raw_inode *latest_node) - { -- struct jffs2_tmp_dnode_info *tn_list, *tn; -- struct jffs2_full_dirent *fd_list; -- struct jffs2_inode_info *f; -- struct jffs2_full_dnode *fn = NULL; -- struct jffs2_sb_info *c; -- struct jffs2_raw_inode latest_node; -- __u32 latest_mctime, mctime_ver; -- __u32 mdata_ver = 0; -- int ret; -- ssize_t retlen; -+ D2(printk(KERN_DEBUG "jffs2_do_read_inode(): getting inocache\n")); - -- D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino)); -+ retry_inocache: -+ spin_lock(&c->inocache_lock); -+ f->inocache = jffs2_get_ino_cache(c, ino); -+ -+ D2(printk(KERN_DEBUG "jffs2_do_read_inode(): Got inocache at %p\n", f->inocache)); -+ -+ if (f->inocache) { -+ /* Check its state. We may need to wait before we can use it */ -+ switch(f->inocache->state) { -+ case INO_STATE_UNCHECKED: -+ case INO_STATE_CHECKEDABSENT: -+ f->inocache->state = INO_STATE_READING; -+ break; - -- f = JFFS2_INODE_INFO(inode); -- c = JFFS2_SB_INFO(inode->i_sb); -+ case INO_STATE_CHECKING: -+ case INO_STATE_GC: -+ /* If it's in either of these states, we need -+ to wait for whoever's got it to finish and -+ put it back. */ -+ D1(printk(KERN_DEBUG "jffs2_get_ino_cache_read waiting for ino #%u in state %d\n", -+ ino, f->inocache->state)); -+ sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); -+ goto retry_inocache; -+ -+ case INO_STATE_READING: -+ case INO_STATE_PRESENT: -+ /* Eep. This should never happen. It can -+ happen if Linux calls read_inode() again -+ before clear_inode() has finished though. */ -+ printk(KERN_WARNING "Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state); -+ /* Fail. That's probably better than allowing it to succeed */ -+ f->inocache = NULL; -+ break; - -- memset(f, 0, sizeof(*f)); -- D2(printk(KERN_DEBUG "getting inocache\n")); -- init_MUTEX(&f->sem); -- f->inocache = jffs2_get_ino_cache(c, inode->i_ino); -- D2(printk(KERN_DEBUG "jffs2_read_inode(): Got inocache at %p\n", f->inocache)); -+ default: -+ BUG(); -+ } -+ } -+ spin_unlock(&c->inocache_lock); - -- if (!f->inocache && inode->i_ino == 1) { -+ if (!f->inocache && ino == 1) { - /* Special case - no root inode on medium */ - f->inocache = jffs2_alloc_inode_cache(); - if (!f->inocache) { -- printk(KERN_CRIT "jffs2_read_inode(): Cannot allocate inocache for root inode\n"); -- make_bad_inode(inode); -- return; -+ printk(KERN_CRIT "jffs2_do_read_inode(): Cannot allocate inocache for root inode\n"); -+ return -ENOMEM; - } -- D1(printk(KERN_DEBUG "jffs2_read_inode(): Creating inocache for root inode\n")); -+ D1(printk(KERN_DEBUG "jffs2_do_read_inode(): Creating inocache for root inode\n")); - memset(f->inocache, 0, sizeof(struct jffs2_inode_cache)); - f->inocache->ino = f->inocache->nlink = 1; - f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; -+ f->inocache->state = INO_STATE_READING; - jffs2_add_ino_cache(c, f->inocache); - } - if (!f->inocache) { -- printk(KERN_WARNING "jffs2_read_inode() on nonexistent ino %lu\n", (unsigned long)inode->i_ino); -- make_bad_inode(inode); -- return; -+ printk(KERN_WARNING "jffs2_do_read_inode() on nonexistent ino %u\n", ino); -+ return -ENOENT; - } -- D1(printk(KERN_DEBUG "jffs2_read_inode(): ino #%lu nlink is %d\n", (unsigned long)inode->i_ino, f->inocache->nlink)); -- inode->i_nlink = f->inocache->nlink; -+ -+ return jffs2_do_read_inode_internal(c, f, latest_node); -+} -+ -+int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) -+{ -+ struct jffs2_raw_inode n; -+ struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL); -+ int ret; -+ -+ if (!f) -+ return -ENOMEM; -+ -+ memset(f, 0, sizeof(*f)); -+ init_MUTEX_LOCKED(&f->sem); -+ f->inocache = ic; -+ -+ ret = jffs2_do_read_inode_internal(c, f, &n); -+ if (!ret) { -+ up(&f->sem); -+ jffs2_do_clear_inode(c, f); -+ } -+ kfree (f); -+ return ret; -+} -+ -+static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, -+ struct jffs2_inode_info *f, -+ struct jffs2_raw_inode *latest_node) -+{ -+ struct jffs2_tmp_dnode_info *tn_list, *tn; -+ struct jffs2_full_dirent *fd_list; -+ struct jffs2_full_dnode *fn = NULL; -+ uint32_t crc; -+ uint32_t latest_mctime, mctime_ver; -+ uint32_t mdata_ver = 0; -+ size_t retlen; -+ int ret; -+ -+ D1(printk(KERN_DEBUG "jffs2_do_read_inode_internal(): ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink)); - - /* Grab all nodes relevant to this ino */ -- ret = jffs2_get_inode_nodes(c, inode->i_ino, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); -+ ret = jffs2_get_inode_nodes(c, f->inocache->ino, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); - - if (ret) { -- printk(KERN_CRIT "jffs2_get_inode_nodes() for ino %lu returned %d\n", inode->i_ino, ret); -- make_bad_inode(inode); -- return; -+ printk(KERN_CRIT "jffs2_get_inode_nodes() for ino %u returned %d\n", f->inocache->ino, ret); -+ if (f->inocache->state == INO_STATE_READING) -+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); -+ return ret; - } - f->dents = fd_list; - -@@ -304,205 +525,169 @@ - - fn = tn->fn; - -- if (f->metadata && tn->version > mdata_ver) { -- D1(printk(KERN_DEBUG "Obsoleting old metadata at 0x%08x\n", f->metadata->raw->flash_offset &~3)); -+ if (f->metadata) { -+ if (likely(tn->version >= mdata_ver)) { -+ D1(printk(KERN_DEBUG "Obsoleting old metadata at 0x%08x\n", ref_offset(f->metadata->raw))); - jffs2_mark_node_obsolete(c, f->metadata->raw); - jffs2_free_full_dnode(f->metadata); - f->metadata = NULL; - - mdata_ver = 0; -+ } else { -+ /* This should never happen. */ -+ printk(KERN_WARNING "Er. New metadata at 0x%08x with ver %d is actually older than previous ver %d at 0x%08x\n", -+ ref_offset(fn->raw), tn->version, mdata_ver, ref_offset(f->metadata->raw)); -+ jffs2_mark_node_obsolete(c, fn->raw); -+ jffs2_free_full_dnode(fn); -+ /* Fill in latest_node from the metadata, not this one we're about to free... */ -+ fn = f->metadata; -+ goto next_tn; -+ } - } - - if (fn->size) { - jffs2_add_full_dnode_to_inode(c, f, fn); - } else { - /* Zero-sized node at end of version list. Just a metadata update */ -- D1(printk(KERN_DEBUG "metadata @%08x: ver %d\n", fn->raw->flash_offset &~3, tn->version)); -+ D1(printk(KERN_DEBUG "metadata @%08x: ver %d\n", ref_offset(fn->raw), tn->version)); - f->metadata = fn; - mdata_ver = tn->version; - } -+ next_tn: - tn_list = tn->next; - jffs2_free_tmp_dnode_info(tn); - } -+ D1(jffs2_sanitycheck_fragtree(f)); -+ - if (!fn) { - /* No data nodes for this inode. */ -- if (inode->i_ino != 1) { -- printk(KERN_WARNING "jffs2_read_inode(): No data nodes found for ino #%lu\n", inode->i_ino); -+ if (f->inocache->ino != 1) { -+ printk(KERN_WARNING "jffs2_do_read_inode(): No data nodes found for ino #%u\n", f->inocache->ino); - if (!fd_list) { -- make_bad_inode(inode); -- return; -- } -- printk(KERN_WARNING "jffs2_read_inode(): But it has children so we fake some modes for it\n"); -+ if (f->inocache->state == INO_STATE_READING) -+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); -+ return -EIO; -+ } -+ printk(KERN_WARNING "jffs2_do_read_inode(): But it has children so we fake some modes for it\n"); -+ } -+ latest_node->mode = cpu_to_jemode(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO); -+ latest_node->version = cpu_to_je32(0); -+ latest_node->atime = latest_node->ctime = latest_node->mtime = cpu_to_je32(0); -+ latest_node->isize = cpu_to_je32(0); -+ latest_node->gid = cpu_to_je16(0); -+ latest_node->uid = cpu_to_je16(0); -+ if (f->inocache->state == INO_STATE_READING) -+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT); -+ return 0; - } -- inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO; -- latest_node.version = 0; -- inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME; -- inode->i_nlink = f->inocache->nlink; -- inode->i_size = 0; -- } else { -- __u32 crc; - -- ret = c->mtd->read(c->mtd, fn->raw->flash_offset & ~3, sizeof(latest_node), &retlen, (void *)&latest_node); -- if (ret || retlen != sizeof(latest_node)) { -- printk(KERN_NOTICE "MTD read in jffs2_read_inode() failed: Returned %d, %ld of %d bytes read\n", -- ret, (long)retlen, sizeof(latest_node)); -- jffs2_clear_inode(inode); -- make_bad_inode(inode); -- return; -- } -- -- crc = crc32(0, &latest_node, sizeof(latest_node)-8); -- if (crc != latest_node.node_crc) { -- printk(KERN_NOTICE "CRC failed for read_inode of inode %ld at physical location 0x%x\n", inode->i_ino, fn->raw->flash_offset & ~3); -- jffs2_clear_inode(inode); -- make_bad_inode(inode); -- return; -- } -- -- inode->i_mode = latest_node.mode; -- inode->i_uid = latest_node.uid; -- inode->i_gid = latest_node.gid; -- inode->i_size = latest_node.isize; -- if (S_ISREG(inode->i_mode)) -- jffs2_truncate_fraglist(c, &f->fraglist, latest_node.isize); -- inode->i_atime = latest_node.atime; -- inode->i_mtime = latest_node.mtime; -- inode->i_ctime = latest_node.ctime; -- } -- -- /* OK, now the special cases. Certain inode types should -- have only one data node, and it's kept as the metadata -- node */ -- if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode) || -- S_ISLNK(inode->i_mode)) { -- if (f->metadata) { -- printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o had metadata node\n", inode->i_ino, inode->i_mode); -- jffs2_clear_inode(inode); -- make_bad_inode(inode); -- return; -- } -- if (!f->fraglist) { -- printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o has no fragments\n", inode->i_ino, inode->i_mode); -- jffs2_clear_inode(inode); -- make_bad_inode(inode); -- return; -- } -- /* ASSERT: f->fraglist != NULL */ -- if (f->fraglist->next) { -- printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o had more than one node\n", inode->i_ino, inode->i_mode); -- /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ -- jffs2_clear_inode(inode); -- make_bad_inode(inode); -- return; -- } -- /* OK. We're happy */ -- f->metadata = f->fraglist->node; -- jffs2_free_node_frag(f->fraglist); -- f->fraglist = NULL; -+ ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node); -+ if (ret || retlen != sizeof(*latest_node)) { -+ printk(KERN_NOTICE "MTD read in jffs2_do_read_inode() failed: Returned %d, %zd of %zd bytes read\n", -+ ret, retlen, sizeof(*latest_node)); -+ /* FIXME: If this fails, there seems to be a memory leak. Find it. */ -+ up(&f->sem); -+ jffs2_do_clear_inode(c, f); -+ return ret?ret:-EIO; - } - -- inode->i_blksize = PAGE_SIZE; -- inode->i_blocks = (inode->i_size + 511) >> 9; -- -- switch (inode->i_mode & S_IFMT) { -- unsigned short rdev; -- -- case S_IFLNK: -- inode->i_op = &jffs2_symlink_inode_operations; -- /* Hack to work around broken isize in old symlink code. -- Remove this when dwmw2 comes to his senses and stops -- symlinks from being an entirely gratuitous special -- case. */ -- if (!inode->i_size) -- inode->i_size = latest_node.dsize; -- break; -+ crc = crc32(0, latest_node, sizeof(*latest_node)-8); -+ if (crc != je32_to_cpu(latest_node->node_crc)) { -+ printk(KERN_NOTICE "CRC failed for read_inode of inode %u at physical location 0x%x\n", f->inocache->ino, ref_offset(fn->raw)); -+ up(&f->sem); -+ jffs2_do_clear_inode(c, f); -+ return -EIO; -+ } - -+ switch(jemode_to_cpu(latest_node->mode) & S_IFMT) { - case S_IFDIR: -- if (mctime_ver > latest_node.version) { -+ if (mctime_ver > je32_to_cpu(latest_node->version)) { - /* The times in the latest_node are actually older than - mctime in the latest dirent. Cheat. */ -- inode->i_mtime = inode->i_ctime = inode->i_atime = -- latest_mctime; -+ latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime); - } -- inode->i_op = &jffs2_dir_inode_operations; -- inode->i_fop = &jffs2_dir_operations; - break; - -+ - case S_IFREG: -- inode->i_op = &jffs2_file_inode_operations; -- inode->i_fop = &jffs2_file_operations; -- inode->i_mapping->a_ops = &jffs2_file_address_operations; -- inode->i_mapping->nrpages = 0; -+ /* If it was a regular file, truncate it to the latest node's isize */ -+ jffs2_truncate_fraglist(c, &f->fragtree, je32_to_cpu(latest_node->isize)); - break; - -+ case S_IFLNK: -+ /* Hack to work around broken isize in old symlink code. -+ Remove this when dwmw2 comes to his senses and stops -+ symlinks from being an entirely gratuitous special -+ case. */ -+ if (!je32_to_cpu(latest_node->isize)) -+ latest_node->isize = latest_node->dsize; -+ /* fall through... */ -+ - case S_IFBLK: - case S_IFCHR: -- /* Read the device numbers from the media */ -- D1(printk(KERN_DEBUG "Reading device numbers from flash\n")); -- if (jffs2_read_dnode(c, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) { -- /* Eep */ -- printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino); -- jffs2_clear_inode(inode); -- make_bad_inode(inode); -- return; -+ /* Certain inode types should have only one data node, and it's -+ kept as the metadata node */ -+ if (f->metadata) { -+ printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had metadata node\n", -+ f->inocache->ino, jemode_to_cpu(latest_node->mode)); -+ up(&f->sem); -+ jffs2_do_clear_inode(c, f); -+ return -EIO; - } -- -- case S_IFSOCK: -- case S_IFIFO: -- inode->i_op = &jffs2_file_inode_operations; -- init_special_inode(inode, inode->i_mode, kdev_t_to_nr(MKDEV(rdev>>8, rdev&0xff))); -+ if (!frag_first(&f->fragtree)) { -+ printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o has no fragments\n", -+ f->inocache->ino, jemode_to_cpu(latest_node->mode)); -+ up(&f->sem); -+ jffs2_do_clear_inode(c, f); -+ return -EIO; -+ } -+ /* ASSERT: f->fraglist != NULL */ -+ if (frag_next(frag_first(&f->fragtree))) { -+ printk(KERN_WARNING "Argh. Special inode #%u with mode 0x%x had more than one node\n", -+ f->inocache->ino, jemode_to_cpu(latest_node->mode)); -+ /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ -+ up(&f->sem); -+ jffs2_do_clear_inode(c, f); -+ return -EIO; -+ } -+ /* OK. We're happy */ -+ f->metadata = frag_first(&f->fragtree)->node; -+ jffs2_free_node_frag(frag_first(&f->fragtree)); -+ f->fragtree = RB_ROOT; - break; -- -- default: -- printk(KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu", inode->i_mode, (unsigned long)inode->i_ino); - } -- D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n")); -+ if (f->inocache->state == INO_STATE_READING) -+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT); -+ -+ return 0; - } - --void jffs2_clear_inode (struct inode *inode) -+void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) - { -- /* We can forget about this inode for now - drop all -- * the nodelists associated with it, etc. -- */ -- struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -- struct jffs2_node_frag *frag, *frags; - struct jffs2_full_dirent *fd, *fds; -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - int deleted; - -- D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); -- - down(&f->sem); - deleted = f->inocache && !f->inocache->nlink; - -- frags = f->fraglist; -- fds = f->dents; - if (f->metadata) { - if (deleted) - jffs2_mark_node_obsolete(c, f->metadata->raw); - jffs2_free_full_dnode(f->metadata); - } - -- while (frags) { -- frag = frags; -- frags = frag->next; -- D2(printk(KERN_DEBUG "jffs2_clear_inode: frag at 0x%x-0x%x: node %p, frags %d--\n", frag->ofs, frag->ofs+frag->size, frag->node, frag->node?frag->node->frags:0)); -+ jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL); - -- if (frag->node && !(--frag->node->frags)) { -- /* Not a hole, and it's the final remaining frag of this node. Free the node */ -- if (deleted) -- jffs2_mark_node_obsolete(c, frag->node->raw); -+ fds = f->dents; - -- jffs2_free_full_dnode(frag->node); -- } -- jffs2_free_node_frag(frag); -- } - while(fds) { - fd = fds; - fds = fd->next; - jffs2_free_full_dirent(fd); - } - -- up(&f->sem); --}; -+ if (f->inocache && f->inocache->state != INO_STATE_CHECKING) -+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); - -+ up(&f->sem); -+} -diff -Nurb linux-mips-2.4.27/fs/jffs2/scan.c linux/fs/jffs2/scan.c ---- linux-mips-2.4.27/fs/jffs2/scan.c 2003-11-17 02:07:44.000000000 +0100 -+++ linux/fs/jffs2/scan.c 2004-11-19 10:25:12.124165592 +0100 -@@ -1,47 +1,25 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - #include -+#include - #include --#include - #include - #include --#include "nodelist.h" - #include -+#include -+#include "nodelist.h" - -+#define EMPTY_SCAN_SIZE 1024 - - #define DIRTY_SPACE(x) do { typeof(x) _x = (x); \ - c->free_size -= _x; c->dirty_size += _x; \ -@@ -51,6 +29,10 @@ - c->free_size -= _x; c->used_size += _x; \ - jeb->free_size -= _x ; jeb->used_size += _x; \ - }while(0) -+#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \ -+ c->free_size -= _x; c->unchecked_size += _x; \ -+ jeb->free_size -= _x ; jeb->unchecked_size += _x; \ -+ }while(0) - - #define noisy_printk(noise, args...) do { \ - if (*(noise)) { \ -@@ -63,39 +45,84 @@ - } while(0) - - static uint32_t pseudo_random; --static void jffs2_rotate_lists(struct jffs2_sb_info *c); - --static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -+static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ unsigned char *buf, uint32_t buf_size); - - /* These helper functions _must_ increase ofs and also do the dirty/used space accounting. - * Returning an error will abort the mount - bad checksums etc. should just mark the space - * as dirty. - */ --static int jffs2_scan_empty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, __u32 *ofs, int *noise); --static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, __u32 *ofs); --static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, __u32 *ofs); -+static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_inode *ri, uint32_t ofs); -+static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_dirent *rd, uint32_t ofs); -+ -+#define BLK_STATE_ALLFF 0 -+#define BLK_STATE_CLEAN 1 -+#define BLK_STATE_PARTDIRTY 2 -+#define BLK_STATE_CLEANMARKER 3 -+#define BLK_STATE_ALLDIRTY 4 -+#define BLK_STATE_BADBLOCK 5 - -+static inline int min_free(struct jffs2_sb_info *c) -+{ -+ uint32_t min = 2 * sizeof(struct jffs2_raw_inode); -+#ifdef CONFIG_JFFS2_FS_NAND -+ if (!jffs2_can_mark_obsolete(c) && min < c->wbuf_pagesize) -+ return c->wbuf_pagesize; -+#endif -+ return min; - -+} - int jffs2_scan_medium(struct jffs2_sb_info *c) - { - int i, ret; -- __u32 empty_blocks = 0; -- -- if (!c->blocks) { -- printk(KERN_WARNING "EEEK! c->blocks is NULL!\n"); -- return -EINVAL; -+ uint32_t empty_blocks = 0, bad_blocks = 0; -+ unsigned char *flashbuf = NULL; -+ uint32_t buf_size = 0; -+#ifndef __ECOS -+ size_t pointlen; -+ -+ if (c->mtd->point) { -+ ret = c->mtd->point (c->mtd, 0, c->mtd->size, &pointlen, &flashbuf); -+ if (!ret && pointlen < c->mtd->size) { -+ /* Don't muck about if it won't let us point to the whole flash */ -+ D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", pointlen)); -+ c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size); -+ flashbuf = NULL; -+ } -+ if (ret) -+ D1(printk(KERN_DEBUG "MTD point failed %d\n", ret)); -+ } -+#endif -+ if (!flashbuf) { -+ /* For NAND it's quicker to read a whole eraseblock at a time, -+ apparently */ -+ if (jffs2_cleanmarker_oob(c)) -+ buf_size = c->sector_size; -+ else -+ buf_size = PAGE_SIZE; -+ -+ D1(printk(KERN_DEBUG "Allocating readbuf of %d bytes\n", buf_size)); -+ flashbuf = kmalloc(buf_size, GFP_KERNEL); -+ if (!flashbuf) -+ return -ENOMEM; - } -+ - for (i=0; inr_blocks; i++) { - struct jffs2_eraseblock *jeb = &c->blocks[i]; - -- ret = jffs2_scan_eraseblock(c, jeb); -+ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), buf_size); -+ - if (ret < 0) -- return ret; -+ goto out; - - ACCT_PARANOIA_CHECK(jeb); - - /* Now decide which list to put it on */ -- if (ret == 1) { -+ switch(ret) { -+ case BLK_STATE_ALLFF: - /* - * Empty block. Since we can't be sure it - * was entirely erased, we just queue it for erase -@@ -103,10 +130,12 @@ - * is complete. Meanwhile we still count it as empty - * for later checks. - */ -- list_add(&jeb->list, &c->erase_pending_list); - empty_blocks++; -+ list_add(&jeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; -- } else if (jeb->used_size == PAD(sizeof(struct jffs2_unknown_node)) && !jeb->first_node->next_in_ino) { -+ break; -+ -+ case BLK_STATE_CLEANMARKER: - /* Only a CLEANMARKER node is valid */ - if (!jeb->dirty_size) { - /* It's actually free */ -@@ -118,74 +147,227 @@ - list_add(&jeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; - } -- } else if (jeb->used_size > c->sector_size - (2*sizeof(struct jffs2_raw_inode))) { -+ break; -+ -+ case BLK_STATE_CLEAN: - /* Full (or almost full) of clean data. Clean list */ - list_add(&jeb->list, &c->clean_list); -- } else if (jeb->used_size) { -+ break; -+ -+ case BLK_STATE_PARTDIRTY: - /* Some data, but not full. Dirty list. */ - /* Except that we want to remember the block with most free space, - and stick it in the 'nextblock' position to start writing to it. - Later when we do snapshots, this must be the most recent block, - not the one with most free space. - */ -- if (jeb->free_size > 2*sizeof(struct jffs2_raw_inode) && -+ if (jeb->free_size > min_free(c) && - (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { - /* Better candidate for the next writes to go to */ -- if (c->nextblock) -+ if (c->nextblock) { -+ c->nextblock->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; -+ c->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; -+ c->free_size -= c->nextblock->free_size; -+ c->wasted_size -= c->nextblock->wasted_size; -+ c->nextblock->free_size = c->nextblock->wasted_size = 0; -+ if (VERYDIRTY(c, c->nextblock->dirty_size)) { -+ list_add(&c->nextblock->list, &c->very_dirty_list); -+ } else { - list_add(&c->nextblock->list, &c->dirty_list); -+ } -+ } - c->nextblock = jeb; - } else { -+ jeb->dirty_size += jeb->free_size + jeb->wasted_size; -+ c->dirty_size += jeb->free_size + jeb->wasted_size; -+ c->free_size -= jeb->free_size; -+ c->wasted_size -= jeb->wasted_size; -+ jeb->free_size = jeb->wasted_size = 0; -+ if (VERYDIRTY(c, jeb->dirty_size)) { -+ list_add(&jeb->list, &c->very_dirty_list); -+ } else { - list_add(&jeb->list, &c->dirty_list); - } -- } else { -+ } -+ break; -+ -+ case BLK_STATE_ALLDIRTY: - /* Nothing valid - not even a clean marker. Needs erasing. */ - /* For now we just put it on the erasing list. We'll start the erases later */ -- printk(KERN_NOTICE "JFFS2: Erase block at 0x%08x is not formatted. It will be erased\n", jeb->offset); -+ D1(printk(KERN_NOTICE "JFFS2: Erase block at 0x%08x is not formatted. It will be erased\n", jeb->offset)); - list_add(&jeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; -+ break; -+ -+ case BLK_STATE_BADBLOCK: -+ D1(printk(KERN_NOTICE "JFFS2: Block at 0x%08x is bad\n", jeb->offset)); -+ list_add(&jeb->list, &c->bad_list); -+ c->bad_size += c->sector_size; -+ c->free_size -= c->sector_size; -+ bad_blocks++; -+ break; -+ default: -+ printk(KERN_WARNING "jffs2_scan_medium(): unknown block state\n"); -+ BUG(); - } - } -- /* Rotate the lists by some number to ensure wear levelling */ -- jffs2_rotate_lists(c); - -+ /* Nextblock dirty is always seen as wasted, because we cannot recycle it now */ -+ if (c->nextblock && (c->nextblock->dirty_size)) { -+ c->nextblock->wasted_size += c->nextblock->dirty_size; -+ c->wasted_size += c->nextblock->dirty_size; -+ c->dirty_size -= c->nextblock->dirty_size; -+ c->nextblock->dirty_size = 0; -+ } -+#ifdef CONFIG_JFFS2_FS_NAND -+ if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) { -+ /* If we're going to start writing into a block which already -+ contains data, and the end of the data isn't page-aligned, -+ skip a little and align it. */ -+ -+ uint32_t skip = c->nextblock->free_size & (c->wbuf_pagesize-1); -+ -+ D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n", -+ skip)); -+ c->nextblock->wasted_size += skip; -+ c->wasted_size += skip; -+ -+ c->nextblock->free_size -= skip; -+ c->free_size -= skip; -+ } -+#endif - if (c->nr_erasing_blocks) { -- if (!c->used_size && empty_blocks != c->nr_blocks) { -+ if ( !c->used_size && ((empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) { - printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n"); -- return -EIO; -+ printk(KERN_NOTICE "empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",empty_blocks,bad_blocks,c->nr_blocks); -+ ret = -EIO; -+ goto out; - } - jffs2_erase_pending_trigger(c); - } -+ ret = 0; -+ out: -+ if (buf_size) -+ kfree(flashbuf); -+#ifndef __ECOS -+ else -+ c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size); -+#endif -+ return ret; -+} -+ -+static int jffs2_fill_scan_buf (struct jffs2_sb_info *c, unsigned char *buf, -+ uint32_t ofs, uint32_t len) -+{ -+ int ret; -+ size_t retlen; -+ -+ ret = jffs2_flash_read(c, ofs, len, &retlen, buf); -+ if (ret) { -+ D1(printk(KERN_WARNING "mtd->read(0x%x bytes from 0x%x) returned %d\n", len, ofs, ret)); -+ return ret; -+ } -+ if (retlen < len) { -+ D1(printk(KERN_WARNING "Read at 0x%x gave only 0x%zx bytes\n", ofs, retlen)); -+ return -EIO; -+ } -+ D2(printk(KERN_DEBUG "Read 0x%x bytes from 0x%08x into buf\n", len, ofs)); -+ D2(printk(KERN_DEBUG "000: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15])); - return 0; - } - --static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) { -- struct jffs2_unknown_node node; -- __u32 ofs, prevofs; -- __u32 hdr_crc, nodetype; -+static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ unsigned char *buf, uint32_t buf_size) { -+ struct jffs2_unknown_node *node; -+ struct jffs2_unknown_node crcnode; -+ uint32_t ofs, prevofs; -+ uint32_t hdr_crc, buf_ofs, buf_len; - int err; - int noise = 0; -+ int wasempty = 0; -+ uint32_t empty_start = 0; -+#ifdef CONFIG_JFFS2_FS_NAND -+ int cleanmarkerfound = 0; -+#endif - - ofs = jeb->offset; - prevofs = jeb->offset - 1; - - D1(printk(KERN_DEBUG "jffs2_scan_eraseblock(): Scanning block at 0x%x\n", ofs)); - -- err = jffs2_scan_empty(c, jeb, &ofs, &noise); -- if (err) return err; -- if (ofs == jeb->offset + c->sector_size) { -+#ifdef CONFIG_JFFS2_FS_NAND -+ if (jffs2_cleanmarker_oob(c)) { -+ int ret = jffs2_check_nand_cleanmarker(c, jeb); -+ D2(printk(KERN_NOTICE "jffs_check_nand_cleanmarker returned %d\n",ret)); -+ /* Even if it's not found, we still scan to see -+ if the block is empty. We use this information -+ to decide whether to erase it or not. */ -+ switch (ret) { -+ case 0: cleanmarkerfound = 1; break; -+ case 1: break; -+ case 2: return BLK_STATE_BADBLOCK; -+ case 3: return BLK_STATE_ALLDIRTY; /* Block has failed to erase min. once */ -+ default: return ret; -+ } -+ } -+#endif -+ buf_ofs = jeb->offset; -+ -+ if (!buf_size) { -+ buf_len = c->sector_size; -+ } else { -+ buf_len = EMPTY_SCAN_SIZE; -+ err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); -+ if (err) -+ return err; -+ } -+ -+ /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ -+ ofs = 0; -+ -+ /* Scan only 4KiB of 0xFF before declaring it's empty */ -+ while(ofs < EMPTY_SCAN_SIZE && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF) -+ ofs += 4; -+ -+ if (ofs == EMPTY_SCAN_SIZE) { -+#ifdef CONFIG_JFFS2_FS_NAND -+ if (jffs2_cleanmarker_oob(c)) { -+ /* scan oob, take care of cleanmarker */ -+ int ret = jffs2_check_oob_empty(c, jeb, cleanmarkerfound); -+ D2(printk(KERN_NOTICE "jffs2_check_oob_empty returned %d\n",ret)); -+ switch (ret) { -+ case 0: return cleanmarkerfound ? BLK_STATE_CLEANMARKER : BLK_STATE_ALLFF; -+ case 1: return BLK_STATE_ALLDIRTY; -+ case 2: return BLK_STATE_BADBLOCK; /* case 2/3 are paranoia checks */ -+ case 3: return BLK_STATE_ALLDIRTY; /* Block has failed to erase min. once */ -+ default: return ret; -+ } -+ } -+#endif - D1(printk(KERN_DEBUG "Block at 0x%08x is empty (erased)\n", jeb->offset)); -- return 1; /* special return code */ -+ return BLK_STATE_ALLFF; /* OK to erase if all blocks are like this */ -+ } -+ if (ofs) { -+ D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset, -+ jeb->offset + ofs)); -+ DIRTY_SPACE(ofs); - } - -+ /* Now ofs is a complete physical flash offset as it always was... */ -+ ofs += jeb->offset; -+ - noise = 10; - - while(ofs < jeb->offset + c->sector_size) { -- ssize_t retlen; -- ACCT_PARANOIA_CHECK(jeb); -+ -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ cond_resched(); - - if (ofs & 3) { - printk(KERN_WARNING "Eep. ofs 0x%08x not word-aligned!\n", ofs); -- ofs = (ofs+3)&~3; -+ ofs = PAD(ofs); - continue; - } - if (ofs == prevofs) { -@@ -196,102 +378,173 @@ - } - prevofs = ofs; - -- if (jeb->offset + c->sector_size < ofs + sizeof(node)) { -- D1(printk(KERN_DEBUG "Fewer than %d bytes left to end of block. Not reading\n", sizeof(struct jffs2_unknown_node))); -+ if (jeb->offset + c->sector_size < ofs + sizeof(*node)) { -+ D1(printk(KERN_DEBUG "Fewer than %zd bytes left to end of block. (%x+%x<%x+%zx) Not reading\n", sizeof(struct jffs2_unknown_node), -+ jeb->offset, c->sector_size, ofs, sizeof(*node))); - DIRTY_SPACE((jeb->offset + c->sector_size)-ofs); - break; - } - -- err = c->mtd->read(c->mtd, ofs, sizeof(node), &retlen, (char *)&node); -- -- if (err) { -- D1(printk(KERN_WARNING "mtd->read(0x%x bytes from 0x%x) returned %d\n", sizeof(node), ofs, err)); -+ if (buf_ofs + buf_len < ofs + sizeof(*node)) { -+ buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); -+ D1(printk(KERN_DEBUG "Fewer than %zd bytes (node header) left to end of buf. Reading 0x%x at 0x%08x\n", -+ sizeof(struct jffs2_unknown_node), buf_len, ofs)); -+ err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); -+ if (err) - return err; -+ buf_ofs = ofs; - } -- if (retlen < sizeof(node)) { -- D1(printk(KERN_WARNING "Read at 0x%x gave only 0x%x bytes\n", ofs, retlen)); -- DIRTY_SPACE(retlen); -- ofs += retlen; -- continue; -+ -+ node = (struct jffs2_unknown_node *)&buf[ofs-buf_ofs]; -+ -+ if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) { -+ uint32_t inbuf_ofs = ofs - buf_ofs + 4; -+ uint32_t scanend; -+ -+ empty_start = ofs; -+ ofs += 4; -+ -+ /* If scanning empty space after only a cleanmarker, don't -+ bother scanning the whole block */ -+ if (unlikely(empty_start == jeb->offset + c->cleanmarker_size && -+ jeb->offset + EMPTY_SCAN_SIZE < buf_ofs + buf_len)) -+ scanend = jeb->offset + EMPTY_SCAN_SIZE - buf_ofs; -+ else -+ scanend = buf_len; -+ -+ D1(printk(KERN_DEBUG "Found empty flash at 0x%08x\n", ofs)); -+ while (inbuf_ofs < scanend) { -+ if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) -+ goto emptyends; -+ -+ inbuf_ofs+=4; -+ ofs += 4; - } -+ /* Ran off end. */ -+ D1(printk(KERN_DEBUG "Empty flash ends normally at 0x%08x\n", ofs)); - -- if (node.magic == JFFS2_EMPTY_BITMASK && node.nodetype == JFFS2_EMPTY_BITMASK) { -- D1(printk(KERN_DEBUG "Found empty flash at 0x%x\n", ofs)); -- err = jffs2_scan_empty(c, jeb, &ofs, &noise); -- if (err) return err; -+ if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && -+ c->cleanmarker_size && !jeb->first_node->next_in_ino && !jeb->dirty_size) -+ return BLK_STATE_CLEANMARKER; -+ wasempty = 1; -+ continue; -+ } else if (wasempty) { -+ emptyends: -+ printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n", empty_start, ofs); -+ DIRTY_SPACE(ofs-empty_start); -+ wasempty = 0; - continue; - } - -- if (ofs == jeb->offset && node.magic == KSAMTIB_CIGAM_2SFFJ) { -+ if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) { - printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?\n", ofs); - DIRTY_SPACE(4); - ofs += 4; - continue; - } -- if (node.magic == JFFS2_DIRTY_BITMASK) { -- D1(printk(KERN_DEBUG "Empty bitmask at 0x%08x\n", ofs)); -+ if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) { -+ D1(printk(KERN_DEBUG "Dirty bitmask at 0x%08x\n", ofs)); - DIRTY_SPACE(4); - ofs += 4; - continue; - } -- if (node.magic == JFFS2_OLD_MAGIC_BITMASK) { -+ if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) { - printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs); - printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n"); - DIRTY_SPACE(4); - ofs += 4; - continue; - } -- if (node.magic != JFFS2_MAGIC_BITMASK) { -+ if (je16_to_cpu(node->magic) != JFFS2_MAGIC_BITMASK) { - /* OK. We're out of possibilities. Whinge and move on */ -- noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", JFFS2_MAGIC_BITMASK, ofs, node.magic); -+ noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", -+ JFFS2_MAGIC_BITMASK, ofs, -+ je16_to_cpu(node->magic)); - DIRTY_SPACE(4); - ofs += 4; - continue; - } - /* We seem to have a node of sorts. Check the CRC */ -- nodetype = node.nodetype; -- node.nodetype |= JFFS2_NODE_ACCURATE; -- hdr_crc = crc32(0, &node, sizeof(node)-4); -- node.nodetype = nodetype; -- if (hdr_crc != node.hdr_crc) { -+ crcnode.magic = node->magic; -+ crcnode.nodetype = cpu_to_je16( je16_to_cpu(node->nodetype) | JFFS2_NODE_ACCURATE); -+ crcnode.totlen = node->totlen; -+ hdr_crc = crc32(0, &crcnode, sizeof(crcnode)-4); -+ -+ if (hdr_crc != je32_to_cpu(node->hdr_crc)) { - noisy_printk(&noise, "jffs2_scan_eraseblock(): Node at 0x%08x {0x%04x, 0x%04x, 0x%08x) has invalid CRC 0x%08x (calculated 0x%08x)\n", -- ofs, node.magic, node.nodetype, node.totlen, node.hdr_crc, hdr_crc); -+ ofs, je16_to_cpu(node->magic), -+ je16_to_cpu(node->nodetype), -+ je32_to_cpu(node->totlen), -+ je32_to_cpu(node->hdr_crc), -+ hdr_crc); - DIRTY_SPACE(4); - ofs += 4; - continue; - } - -- if (ofs + node.totlen > jeb->offset + c->sector_size) { -+ if (ofs + je32_to_cpu(node->totlen) > -+ jeb->offset + c->sector_size) { - /* Eep. Node goes over the end of the erase block. */ - printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n", -- ofs, node.totlen); -+ ofs, je32_to_cpu(node->totlen)); - printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n"); - DIRTY_SPACE(4); - ofs += 4; - continue; - } - -- switch(node.nodetype | JFFS2_NODE_ACCURATE) { -+ if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) { -+ /* Wheee. This is an obsoleted node */ -+ D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs)); -+ DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); -+ ofs += PAD(je32_to_cpu(node->totlen)); -+ continue; -+ } -+ -+ switch(je16_to_cpu(node->nodetype)) { - case JFFS2_NODETYPE_INODE: -- err = jffs2_scan_inode_node(c, jeb, &ofs); -+ if (buf_ofs + buf_len < ofs + sizeof(struct jffs2_raw_inode)) { -+ buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); -+ D1(printk(KERN_DEBUG "Fewer than %zd bytes (inode node) left to end of buf. Reading 0x%x at 0x%08x\n", -+ sizeof(struct jffs2_raw_inode), buf_len, ofs)); -+ err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); -+ if (err) -+ return err; -+ buf_ofs = ofs; -+ node = (void *)buf; -+ } -+ err = jffs2_scan_inode_node(c, jeb, (void *)node, ofs); - if (err) return err; -+ ofs += PAD(je32_to_cpu(node->totlen)); - break; - - case JFFS2_NODETYPE_DIRENT: -- err = jffs2_scan_dirent_node(c, jeb, &ofs); -+ if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) { -+ buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); -+ D1(printk(KERN_DEBUG "Fewer than %d bytes (dirent node) left to end of buf. Reading 0x%x at 0x%08x\n", -+ je32_to_cpu(node->totlen), buf_len, ofs)); -+ err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); -+ if (err) -+ return err; -+ buf_ofs = ofs; -+ node = (void *)buf; -+ } -+ err = jffs2_scan_dirent_node(c, jeb, (void *)node, ofs); - if (err) return err; -+ ofs += PAD(je32_to_cpu(node->totlen)); - break; - - case JFFS2_NODETYPE_CLEANMARKER: -- if (node.totlen != sizeof(struct jffs2_unknown_node)) { -+ D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs)); -+ if (je32_to_cpu(node->totlen) != c->cleanmarker_size) { - printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", -- ofs, node.totlen, sizeof(struct jffs2_unknown_node)); -+ ofs, je32_to_cpu(node->totlen), c->cleanmarker_size); - DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); -+ ofs += PAD(sizeof(struct jffs2_unknown_node)); - } else if (jeb->first_node) { - printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset); - DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); - ofs += PAD(sizeof(struct jffs2_unknown_node)); -- continue; - } else { - struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); - if (!marker_ref) { -@@ -300,98 +553,80 @@ - } - marker_ref->next_in_ino = NULL; - marker_ref->next_phys = NULL; -- marker_ref->flash_offset = ofs; -- marker_ref->totlen = sizeof(struct jffs2_unknown_node); -+ marker_ref->flash_offset = ofs | REF_NORMAL; -+ marker_ref->__totlen = c->cleanmarker_size; - jeb->first_node = jeb->last_node = marker_ref; - -- USED_SPACE(PAD(sizeof(struct jffs2_unknown_node))); -+ USED_SPACE(PAD(c->cleanmarker_size)); -+ ofs += PAD(c->cleanmarker_size); - } -- ofs += PAD(sizeof(struct jffs2_unknown_node)); -+ break; -+ -+ case JFFS2_NODETYPE_PADDING: -+ DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); -+ ofs += PAD(je32_to_cpu(node->totlen)); - break; - - default: -- switch (node.nodetype & JFFS2_COMPAT_MASK) { -+ switch (je16_to_cpu(node->nodetype) & JFFS2_COMPAT_MASK) { - case JFFS2_FEATURE_ROCOMPAT: -- printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs); -+ printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs); - c->flags |= JFFS2_SB_FLAG_RO; -- if (!(OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY)) -+ if (!(jffs2_is_readonly(c))) - return -EROFS; -- DIRTY_SPACE(PAD(node.totlen)); -- ofs += PAD(node.totlen); -- continue; -+ DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); -+ ofs += PAD(je32_to_cpu(node->totlen)); -+ break; - - case JFFS2_FEATURE_INCOMPAT: -- printk(KERN_NOTICE "Incompatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs); -+ printk(KERN_NOTICE "Incompatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs); - return -EINVAL; - - case JFFS2_FEATURE_RWCOMPAT_DELETE: -- printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs); -- DIRTY_SPACE(PAD(node.totlen)); -- ofs += PAD(node.totlen); -+ D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); -+ DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); -+ ofs += PAD(je32_to_cpu(node->totlen)); - break; - - case JFFS2_FEATURE_RWCOMPAT_COPY: -- printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs); -- USED_SPACE(PAD(node.totlen)); -- ofs += PAD(node.totlen); -+ D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); -+ USED_SPACE(PAD(je32_to_cpu(node->totlen))); -+ ofs += PAD(je32_to_cpu(node->totlen)); - break; - } - } - } -- D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, used 0x%08x\n", jeb->offset, -- jeb->free_size, jeb->dirty_size, jeb->used_size)); -- return 0; --} - --/* We're pointing at the first empty word on the flash. Scan and account for the whole dirty region */ --static int jffs2_scan_empty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, __u32 *startofs, int *noise) --{ -- __u32 *buf; -- __u32 scanlen = (jeb->offset + c->sector_size) - *startofs; -- __u32 curofs = *startofs; -- -- buf = kmalloc(min((__u32)PAGE_SIZE, scanlen), GFP_KERNEL); -- if (!buf) { -- printk(KERN_WARNING "Scan buffer allocation failed\n"); -- return -ENOMEM; -- } -- while(scanlen) { -- ssize_t retlen; -- int ret, i; -- -- ret = c->mtd->read(c->mtd, curofs, min((__u32)PAGE_SIZE, scanlen), &retlen, (char *)buf); -- if(ret) { -- D1(printk(KERN_WARNING "jffs2_scan_empty(): Read 0x%x bytes at 0x%08x returned %d\n", min((__u32)PAGE_SIZE, scanlen), curofs, ret)); -- kfree(buf); -- return ret; -- } -- if (retlen < 4) { -- D1(printk(KERN_WARNING "Eep. too few bytes read in scan_empty()\n")); -- kfree(buf); -- return -EIO; -- } -- for (i=0; i<(retlen / 4); i++) { -- if (buf[i] != 0xffffffff) { -- curofs += i*4; -- -- noisy_printk(noise, "jffs2_scan_empty(): Empty block at 0x%08x ends at 0x%08x (with 0x%08x)! Marking dirty\n", *startofs, curofs, buf[i]); -- DIRTY_SPACE(curofs - (*startofs)); -- *startofs = curofs; -- kfree(buf); -- return 0; -- } -- } -- scanlen -= retlen&~3; -- curofs += retlen&~3; -- } - -- D1(printk(KERN_DEBUG "Empty flash detected from 0x%08x to 0x%08x\n", *startofs, curofs)); -- kfree(buf); -- *startofs = curofs; -- return 0; -+ D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, -+ jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size)); -+ -+ /* mark_node_obsolete can add to wasted !! */ -+ if (jeb->wasted_size) { -+ jeb->dirty_size += jeb->wasted_size; -+ c->dirty_size += jeb->wasted_size; -+ c->wasted_size -= jeb->wasted_size; -+ jeb->wasted_size = 0; -+ } -+ -+ if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size -+ && (!jeb->first_node || jeb->first_node->next_in_ino) ) -+ return BLK_STATE_CLEANMARKER; -+ -+ /* move blocks with max 4 byte dirty space to cleanlist */ -+ else if (!ISDIRTY(c->sector_size - (jeb->used_size + jeb->unchecked_size))) { -+ c->dirty_size -= jeb->dirty_size; -+ c->wasted_size += jeb->dirty_size; -+ jeb->wasted_size += jeb->dirty_size; -+ jeb->dirty_size = 0; -+ return BLK_STATE_CLEAN; -+ } else if (jeb->used_size || jeb->unchecked_size) -+ return BLK_STATE_PARTDIRTY; -+ else -+ return BLK_STATE_ALLDIRTY; - } - --static struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, __u32 ino) -+static struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino) - { - struct jffs2_inode_cache *ic; - -@@ -399,137 +634,77 @@ - if (ic) - return ic; - -+ if (ino > c->highest_ino) -+ c->highest_ino = ino; -+ - ic = jffs2_alloc_inode_cache(); - if (!ic) { - printk(KERN_NOTICE "jffs2_scan_make_inode_cache(): allocation of inode cache failed\n"); - return NULL; - } - memset(ic, 0, sizeof(*ic)); -- ic->scan = kmalloc(sizeof(struct jffs2_scan_info), GFP_KERNEL); -- if (!ic->scan) { -- printk(KERN_NOTICE "jffs2_scan_make_inode_cache(): allocation of scan info for inode cache failed\n"); -- jffs2_free_inode_cache(ic); -- return NULL; -- } -- memset(ic->scan, 0, sizeof(*ic->scan)); -+ - ic->ino = ino; - ic->nodes = (void *)ic; - jffs2_add_ino_cache(c, ic); - if (ino == 1) -- ic->nlink=1; -+ ic->nlink = 1; - return ic; - } - --static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, __u32 *ofs) -+static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_inode *ri, uint32_t ofs) - { - struct jffs2_raw_node_ref *raw; -- struct jffs2_full_dnode *fn; -- struct jffs2_tmp_dnode_info *tn, **tn_list; - struct jffs2_inode_cache *ic; -- struct jffs2_raw_inode ri; -- __u32 crc; -- __u16 oldnodetype; -- int ret; -- ssize_t retlen; -- -- D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", *ofs)); -- -- ret = c->mtd->read(c->mtd, *ofs, sizeof(ri), &retlen, (char *)&ri); -- if (ret) { -- printk(KERN_NOTICE "jffs2_scan_inode_node(): Read error at 0x%08x: %d\n", *ofs, ret); -- return ret; -- } -- if (retlen != sizeof(ri)) { -- printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", -- retlen, *ofs, sizeof(ri)); -- return -EIO; -- } -+ uint32_t ino = je32_to_cpu(ri->ino); - -- /* We sort of assume that the node was accurate when it was -- first written to the medium :) */ -- oldnodetype = ri.nodetype; -- ri.nodetype |= JFFS2_NODE_ACCURATE; -- crc = crc32(0, &ri, sizeof(ri)-8); -- ri.nodetype = oldnodetype; -+ D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs)); - -- if(crc != ri.node_crc) { -- printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -- *ofs, ri.node_crc, crc); -- /* FIXME: Why do we believe totlen? */ -- DIRTY_SPACE(4); -- *ofs += 4; -- return 0; -- } -- /* There was a bug where we wrote hole nodes out with csize/dsize -- swapped. Deal with it */ -- if (ri.compr == JFFS2_COMPR_ZERO && !ri.dsize && ri.csize) { -- ri.dsize = ri.csize; -- ri.csize = 0; -- } -+ /* We do very little here now. Just check the ino# to which we should attribute -+ this node; we can do all the CRC checking etc. later. There's a tradeoff here -- -+ we used to scan the flash once only, reading everything we want from it into -+ memory, then building all our in-core data structures and freeing the extra -+ information. Now we allow the first part of the mount to complete a lot quicker, -+ but we have to go _back_ to the flash in order to finish the CRC checking, etc. -+ Which means that the _full_ amount of time to get to proper write mode with GC -+ operational may actually be _longer_ than before. Sucks to be me. */ - -- if (ri.csize) { -- /* Check data CRC too */ -- unsigned char *dbuf; -- __u32 crc; -- -- dbuf = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL); -- if (!dbuf) { -- printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of temporary data buffer for CRC check failed\n"); -- return -ENOMEM; -- } -- ret = c->mtd->read(c->mtd, *ofs+sizeof(ri), ri.csize, &retlen, dbuf); -- if (ret) { -- printk(KERN_NOTICE "jffs2_scan_inode_node(): Read error at 0x%08x: %d\n", *ofs+sizeof(ri), ret); -- kfree(dbuf); -- return ret; -- } -- if (retlen != ri.csize) { -- printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", -- retlen, *ofs+ sizeof(ri), ri.csize); -- kfree(dbuf); -- return -EIO; -- } -- crc = crc32(0, dbuf, ri.csize); -- kfree(dbuf); -- if (crc != ri.data_crc) { -- printk(KERN_NOTICE "jffs2_scan_inode_node(): Data CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -- *ofs, ri.data_crc, crc); -- DIRTY_SPACE(PAD(ri.totlen)); -- *ofs += PAD(ri.totlen); -- return 0; -- } -- } -- -- /* Wheee. It worked */ - raw = jffs2_alloc_raw_node_ref(); - if (!raw) { - printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n"); - return -ENOMEM; - } -- tn = jffs2_alloc_tmp_dnode_info(); -- if (!tn) { -- jffs2_free_raw_node_ref(raw); -- return -ENOMEM; -- } -- fn = jffs2_alloc_full_dnode(); -- if (!fn) { -- jffs2_free_tmp_dnode_info(tn); -+ -+ ic = jffs2_get_ino_cache(c, ino); -+ if (!ic) { -+ /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the -+ first node we found for this inode. Do a CRC check to protect against the former -+ case */ -+ uint32_t crc = crc32(0, ri, sizeof(*ri)-8); -+ -+ if (crc != je32_to_cpu(ri->node_crc)) { -+ printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -+ ofs, je32_to_cpu(ri->node_crc), crc); -+ /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ -+ DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen))); - jffs2_free_raw_node_ref(raw); -- return -ENOMEM; -+ return 0; - } -- ic = jffs2_scan_make_ino_cache(c, ri.ino); -+ ic = jffs2_scan_make_ino_cache(c, ino); - if (!ic) { -- jffs2_free_full_dnode(fn); -- jffs2_free_tmp_dnode_info(tn); - jffs2_free_raw_node_ref(raw); - return -ENOMEM; - } -+ } - -- /* Build the data structures and file them for later */ -- raw->flash_offset = *ofs; -- raw->totlen = PAD(ri.totlen); -+ /* Wheee. It worked */ -+ -+ raw->flash_offset = ofs | REF_UNCHECKED; -+ raw->__totlen = PAD(je32_to_cpu(ri->totlen)); - raw->next_phys = NULL; - raw->next_in_ino = ic->nodes; -+ - ic->nodes = raw; - if (!jeb->first_node) - jeb->first_node = raw; -@@ -538,134 +713,56 @@ - jeb->last_node = raw; - - D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", -- ri.ino, ri.version, ri.offset, ri.offset+ri.dsize)); -- -- pseudo_random += ri.version; -- -- for (tn_list = &ic->scan->tmpnodes; *tn_list; tn_list = &((*tn_list)->next)) { -- if ((*tn_list)->version < ri.version) -- continue; -- if ((*tn_list)->version > ri.version) -- break; -- /* Wheee. We've found another instance of the same version number. -- We should obsolete one of them. -- */ -- D1(printk(KERN_DEBUG "Duplicate version %d found in ino #%u. Previous one is at 0x%08x\n", ri.version, ic->ino, (*tn_list)->fn->raw->flash_offset &~3)); -- if (!jeb->used_size) { -- D1(printk(KERN_DEBUG "No valid nodes yet found in this eraseblock 0x%08x, so obsoleting the new instance at 0x%08x\n", -- jeb->offset, raw->flash_offset & ~3)); -- ri.nodetype &= ~JFFS2_NODE_ACCURATE; -- /* Perhaps we could also mark it as such on the medium. Maybe later */ -- } -- break; -- } -- -- if (ri.nodetype & JFFS2_NODE_ACCURATE) { -- memset(fn,0,sizeof(*fn)); -- -- fn->ofs = ri.offset; -- fn->size = ri.dsize; -- fn->frags = 0; -- fn->raw = raw; -- -- tn->next = NULL; -- tn->fn = fn; -- tn->version = ri.version; -+ je32_to_cpu(ri->ino), je32_to_cpu(ri->version), -+ je32_to_cpu(ri->offset), -+ je32_to_cpu(ri->offset)+je32_to_cpu(ri->dsize))); - -- USED_SPACE(PAD(ri.totlen)); -- jffs2_add_tn_to_list(tn, &ic->scan->tmpnodes); -- /* Make sure the one we just added is the _last_ in the list -- with this version number, so the older ones get obsoleted */ -- while (tn->next && tn->next->version == tn->version) { -+ pseudo_random += je32_to_cpu(ri->version); - -- D1(printk(KERN_DEBUG "Shifting new node at 0x%08x after other node at 0x%08x for version %d in list\n", -- fn->raw->flash_offset&~3, tn->next->fn->raw->flash_offset &~3, ri.version)); -- -- if(tn->fn != fn) -- BUG(); -- tn->fn = tn->next->fn; -- tn->next->fn = fn; -- tn = tn->next; -- } -- } else { -- jffs2_free_full_dnode(fn); -- jffs2_free_tmp_dnode_info(tn); -- raw->flash_offset |= 1; -- DIRTY_SPACE(PAD(ri.totlen)); -- } -- *ofs += PAD(ri.totlen); -+ UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen))); - return 0; - } - --static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, __u32 *ofs) -+static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, -+ struct jffs2_raw_dirent *rd, uint32_t ofs) - { - struct jffs2_raw_node_ref *raw; - struct jffs2_full_dirent *fd; - struct jffs2_inode_cache *ic; -- struct jffs2_raw_dirent rd; -- __u16 oldnodetype; -- int ret; -- __u32 crc; -- ssize_t retlen; -- -- D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", *ofs)); -+ uint32_t crc; - -- ret = c->mtd->read(c->mtd, *ofs, sizeof(rd), &retlen, (char *)&rd); -- if (ret) { -- printk(KERN_NOTICE "jffs2_scan_dirent_node(): Read error at 0x%08x: %d\n", *ofs, ret); -- return ret; -- } -- if (retlen != sizeof(rd)) { -- printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", -- retlen, *ofs, sizeof(rd)); -- return -EIO; -- } -+ D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", ofs)); - -- /* We sort of assume that the node was accurate when it was -- first written to the medium :) */ -- oldnodetype = rd.nodetype; -- rd.nodetype |= JFFS2_NODE_ACCURATE; -- crc = crc32(0, &rd, sizeof(rd)-8); -- rd.nodetype = oldnodetype; -+ /* We don't get here unless the node is still valid, so we don't have to -+ mask in the ACCURATE bit any more. */ -+ crc = crc32(0, rd, sizeof(*rd)-8); - -- if (crc != rd.node_crc) { -+ if (crc != je32_to_cpu(rd->node_crc)) { - printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -- *ofs, rd.node_crc, crc); -- /* FIXME: Why do we believe totlen? */ -- DIRTY_SPACE(4); -- *ofs += 4; -+ ofs, je32_to_cpu(rd->node_crc), crc); -+ /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ -+ DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen))); - return 0; - } - -- pseudo_random += rd.version; -+ pseudo_random += je32_to_cpu(rd->version); - -- fd = jffs2_alloc_full_dirent(rd.nsize+1); -+ fd = jffs2_alloc_full_dirent(rd->nsize+1); - if (!fd) { - return -ENOMEM; --} -- ret = c->mtd->read(c->mtd, *ofs + sizeof(rd), rd.nsize, &retlen, &fd->name[0]); -- if (ret) { -- jffs2_free_full_dirent(fd); -- printk(KERN_NOTICE "jffs2_scan_dirent_node(): Read error at 0x%08x: %d\n", -- *ofs + sizeof(rd), ret); -- return ret; -- } -- if (retlen != rd.nsize) { -- jffs2_free_full_dirent(fd); -- printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", -- retlen, *ofs + sizeof(rd), rd.nsize); -- return -EIO; - } -- crc = crc32(0, fd->name, rd.nsize); -- if (crc != rd.name_crc) { -+ memcpy(&fd->name, rd->name, rd->nsize); -+ fd->name[rd->nsize] = 0; -+ -+ crc = crc32(0, fd->name, rd->nsize); -+ if (crc != je32_to_cpu(rd->name_crc)) { - printk(KERN_NOTICE "jffs2_scan_dirent_node(): Name CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", -- *ofs, rd.name_crc, crc); -- fd->name[rd.nsize]=0; -- D1(printk(KERN_NOTICE "Name for which CRC failed is (now) '%s', ino #%d\n", fd->name, rd.ino)); -+ ofs, je32_to_cpu(rd->name_crc), crc); -+ D1(printk(KERN_NOTICE "Name for which CRC failed is (now) '%s', ino #%d\n", fd->name, je32_to_cpu(rd->ino))); - jffs2_free_full_dirent(fd); - /* FIXME: Why do we believe totlen? */ -- DIRTY_SPACE(PAD(rd.totlen)); -- *ofs += PAD(rd.totlen); -+ /* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */ -+ DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen))); - return 0; - } - raw = jffs2_alloc_raw_node_ref(); -@@ -674,15 +771,15 @@ - printk(KERN_NOTICE "jffs2_scan_dirent_node(): allocation of node reference failed\n"); - return -ENOMEM; - } -- ic = jffs2_scan_make_ino_cache(c, rd.pino); -+ ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino)); - if (!ic) { - jffs2_free_full_dirent(fd); - jffs2_free_raw_node_ref(raw); - return -ENOMEM; - } - -- raw->totlen = PAD(rd.totlen); -- raw->flash_offset = *ofs; -+ raw->__totlen = PAD(je32_to_cpu(rd->totlen)); -+ raw->flash_offset = ofs | REF_PRISTINE; - raw->next_phys = NULL; - raw->next_in_ino = ic->nodes; - ic->nodes = raw; -@@ -692,24 +789,15 @@ - jeb->last_node->next_phys = raw; - jeb->last_node = raw; - -- if (rd.nodetype & JFFS2_NODE_ACCURATE) { - fd->raw = raw; - fd->next = NULL; -- fd->version = rd.version; -- fd->ino = rd.ino; -- fd->name[rd.nsize]=0; -- fd->nhash = full_name_hash(fd->name, rd.nsize); -- fd->type = rd.type; -- -- USED_SPACE(PAD(rd.totlen)); -- jffs2_add_fd_to_list(c, fd, &ic->scan->dents); -- } else { -- raw->flash_offset |= 1; -- jffs2_free_full_dirent(fd); -+ fd->version = je32_to_cpu(rd->version); -+ fd->ino = je32_to_cpu(rd->ino); -+ fd->nhash = full_name_hash(fd->name, rd->nsize); -+ fd->type = rd->type; -+ USED_SPACE(PAD(je32_to_cpu(rd->totlen))); -+ jffs2_add_fd_to_list(c, fd, &ic->scan_dents); - -- DIRTY_SPACE(PAD(rd.totlen)); -- } -- *ofs += PAD(rd.totlen); - return 0; - } - -@@ -731,26 +819,90 @@ - struct list_head *n = head->next; - - list_del(head); -- while(count--) -+ while(count--) { - n = n->next; -+ } - list_add(head, n); - } - --static void jffs2_rotate_lists(struct jffs2_sb_info *c) -+void jffs2_rotate_lists(struct jffs2_sb_info *c) - { - uint32_t x; -+ uint32_t rotateby; - - x = count_list(&c->clean_list); -- if (x) -- rotate_list((&c->clean_list), pseudo_random % x); -+ if (x) { -+ rotateby = pseudo_random % x; -+ D1(printk(KERN_DEBUG "Rotating clean_list by %d\n", rotateby)); -+ -+ rotate_list((&c->clean_list), rotateby); -+ -+ D1(printk(KERN_DEBUG "Erase block at front of clean_list is at %08x\n", -+ list_entry(c->clean_list.next, struct jffs2_eraseblock, list)->offset)); -+ } else { -+ D1(printk(KERN_DEBUG "Not rotating empty clean_list\n")); -+ } -+ -+ x = count_list(&c->very_dirty_list); -+ if (x) { -+ rotateby = pseudo_random % x; -+ D1(printk(KERN_DEBUG "Rotating very_dirty_list by %d\n", rotateby)); -+ -+ rotate_list((&c->very_dirty_list), rotateby); -+ -+ D1(printk(KERN_DEBUG "Erase block at front of very_dirty_list is at %08x\n", -+ list_entry(c->very_dirty_list.next, struct jffs2_eraseblock, list)->offset)); -+ } else { -+ D1(printk(KERN_DEBUG "Not rotating empty very_dirty_list\n")); -+ } - - x = count_list(&c->dirty_list); -- if (x) -- rotate_list((&c->dirty_list), pseudo_random % x); -+ if (x) { -+ rotateby = pseudo_random % x; -+ D1(printk(KERN_DEBUG "Rotating dirty_list by %d\n", rotateby)); -+ -+ rotate_list((&c->dirty_list), rotateby); -+ -+ D1(printk(KERN_DEBUG "Erase block at front of dirty_list is at %08x\n", -+ list_entry(c->dirty_list.next, struct jffs2_eraseblock, list)->offset)); -+ } else { -+ D1(printk(KERN_DEBUG "Not rotating empty dirty_list\n")); -+ } -+ -+ x = count_list(&c->erasable_list); -+ if (x) { -+ rotateby = pseudo_random % x; -+ D1(printk(KERN_DEBUG "Rotating erasable_list by %d\n", rotateby)); - -- if (c->nr_erasing_blocks) -- rotate_list((&c->erase_pending_list), pseudo_random % c->nr_erasing_blocks); -+ rotate_list((&c->erasable_list), rotateby); - -- if (c->nr_free_blocks) /* Not that it should ever be zero */ -- rotate_list((&c->free_list), pseudo_random % c->nr_free_blocks); -+ D1(printk(KERN_DEBUG "Erase block at front of erasable_list is at %08x\n", -+ list_entry(c->erasable_list.next, struct jffs2_eraseblock, list)->offset)); -+ } else { -+ D1(printk(KERN_DEBUG "Not rotating empty erasable_list\n")); -+ } -+ -+ if (c->nr_erasing_blocks) { -+ rotateby = pseudo_random % c->nr_erasing_blocks; -+ D1(printk(KERN_DEBUG "Rotating erase_pending_list by %d\n", rotateby)); -+ -+ rotate_list((&c->erase_pending_list), rotateby); -+ -+ D1(printk(KERN_DEBUG "Erase block at front of erase_pending_list is at %08x\n", -+ list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list)->offset)); -+ } else { -+ D1(printk(KERN_DEBUG "Not rotating empty erase_pending_list\n")); -+ } -+ -+ if (c->nr_free_blocks) { -+ rotateby = pseudo_random % c->nr_free_blocks; -+ D1(printk(KERN_DEBUG "Rotating free_list by %d\n", rotateby)); -+ -+ rotate_list((&c->free_list), rotateby); -+ -+ D1(printk(KERN_DEBUG "Erase block at front of free_list is at %08x\n", -+ list_entry(c->free_list.next, struct jffs2_eraseblock, list)->offset)); -+ } else { -+ D1(printk(KERN_DEBUG "Not rotating empty free_list\n")); -+ } - } -diff -Nurb linux-mips-2.4.27/fs/jffs2/super-v24.c linux/fs/jffs2/super-v24.c ---- linux-mips-2.4.27/fs/jffs2/super-v24.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/super-v24.c 2004-11-19 10:25:12.126165288 +0100 -@@ -0,0 +1,167 @@ -+/* -+ * JFFS2 -- Journalling Flash File System, Version 2. -+ * -+ * Copyright (C) 2001-2003 Red Hat, Inc. -+ * -+ * Created by David Woodhouse -+ * -+ * For licensing information, see the file 'LICENCE' in this directory. -+ * -+ * $Id$ -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "nodelist.h" -+ -+#ifndef MTD_BLOCK_MAJOR -+#define MTD_BLOCK_MAJOR 31 -+#endif -+ -+static void jffs2_put_super (struct super_block *); -+ -+static struct super_operations jffs2_super_operations = -+{ -+ .read_inode = jffs2_read_inode, -+ .put_super = jffs2_put_super, -+ .write_super = jffs2_write_super, -+ .statfs = jffs2_statfs, -+ .remount_fs = jffs2_remount_fs, -+ .clear_inode = jffs2_clear_inode, -+ .dirty_inode = jffs2_dirty_inode, -+}; -+ -+ -+static struct super_block *jffs2_read_super(struct super_block *sb, void *data, int silent) -+{ -+ struct jffs2_sb_info *c; -+ int ret; -+ -+ D1(printk(KERN_DEBUG "jffs2: read_super for device %s\n", kdevname(sb->s_dev))); -+ -+ if (major(sb->s_dev) != MTD_BLOCK_MAJOR) { -+ if (!silent) -+ printk(KERN_DEBUG "jffs2: attempt to mount non-MTD device %s\n", kdevname(sb->s_dev)); -+ return NULL; -+ } -+ -+ c = JFFS2_SB_INFO(sb); -+ memset(c, 0, sizeof(*c)); -+ -+ sb->s_op = &jffs2_super_operations; -+ -+ c->mtd = get_mtd_device(NULL, minor(sb->s_dev)); -+ if (!c->mtd) { -+ D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", minor(sb->s_dev))); -+ return NULL; -+ } -+ -+ ret = jffs2_do_fill_super(sb, data, silent); -+ if (ret) { -+ put_mtd_device(c->mtd); -+ return NULL; -+ } -+ -+ return sb; -+} -+ -+static void jffs2_put_super (struct super_block *sb) -+{ -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); -+ -+ D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n")); -+ -+ -+ if (!(sb->s_flags & MS_RDONLY)) -+ jffs2_stop_garbage_collect_thread(c); -+ down(&c->alloc_sem); -+ jffs2_flush_wbuf_pad(c); -+ up(&c->alloc_sem); -+ jffs2_free_ino_caches(c); -+ jffs2_free_raw_node_refs(c); -+ kfree(c->blocks); -+ jffs2_nand_flash_cleanup(c); -+ kfree(c->inocache_list); -+ if (c->mtd->sync) -+ c->mtd->sync(c->mtd); -+ put_mtd_device(c->mtd); -+ -+ D1(printk(KERN_DEBUG "jffs2_put_super returning\n")); -+} -+ -+static DECLARE_FSTYPE_DEV(jffs2_fs_type, "jffs2", jffs2_read_super); -+ -+static int __init init_jffs2_fs(void) -+{ -+ int ret; -+ -+ printk(KERN_INFO "JFFS2 version 2.2." -+#ifdef CONFIG_FS_JFFS2_NAND -+ " (NAND)" -+#endif -+ " (C) 2001-2003 Red Hat, Inc.\n"); -+ -+#ifdef JFFS2_OUT_OF_KERNEL -+ /* sanity checks. Could we do these at compile time? */ -+ if (sizeof(struct jffs2_sb_info) > sizeof (((struct super_block *)NULL)->u)) { -+ printk(KERN_ERR "JFFS2 error: struct jffs2_sb_info (%d bytes) doesn't fit in the super_block union (%d bytes)\n", -+ sizeof(struct jffs2_sb_info), sizeof (((struct super_block *)NULL)->u)); -+ return -EIO; -+ } -+ -+ if (sizeof(struct jffs2_inode_info) > sizeof (((struct inode *)NULL)->u)) { -+ printk(KERN_ERR "JFFS2 error: struct jffs2_inode_info (%d bytes) doesn't fit in the inode union (%d bytes)\n", -+ sizeof(struct jffs2_inode_info), sizeof (((struct inode *)NULL)->u)); -+ return -EIO; -+ } -+#endif -+ ret = jffs2_zlib_init(); -+ if (ret) { -+ printk(KERN_ERR "JFFS2 error: Failed to initialise zlib workspaces\n"); -+ goto out; -+ } -+ ret = jffs2_create_slab_caches(); -+ if (ret) { -+ printk(KERN_ERR "JFFS2 error: Failed to initialise slab caches\n"); -+ goto out_zlib; -+ } -+ ret = register_filesystem(&jffs2_fs_type); -+ if (ret) { -+ printk(KERN_ERR "JFFS2 error: Failed to register filesystem\n"); -+ goto out_slab; -+ } -+ return 0; -+ -+ out_slab: -+ jffs2_destroy_slab_caches(); -+ out_zlib: -+ jffs2_zlib_exit(); -+ out: -+ -+ return ret; -+} -+ -+static void __exit exit_jffs2_fs(void) -+{ -+ jffs2_destroy_slab_caches(); -+ jffs2_zlib_exit(); -+ unregister_filesystem(&jffs2_fs_type); -+} -+ -+module_init(init_jffs2_fs); -+module_exit(exit_jffs2_fs); -+ -+MODULE_DESCRIPTION("The Journalling Flash File System, v2"); -+MODULE_AUTHOR("Red Hat, Inc."); -+MODULE_LICENSE("GPL"); // Actually dual-licensed, but it doesn't matter for -+ // the sake of this tag. It's Free Software. -diff -Nurb linux-mips-2.4.27/fs/jffs2/super.c linux/fs/jffs2/super.c ---- linux-mips-2.4.27/fs/jffs2/super.c 2003-01-11 18:53:17.000000000 +0100 -+++ linux/fs/jffs2/super.c 2004-11-19 10:25:12.127165136 +0100 -@@ -1,291 +1,257 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include - #include - #include --#include - #include - #include - #include - #include -+#include - #include - #include - #include --#include -+#include -+#include - #include "nodelist.h" - --#ifndef MTD_BLOCK_MAJOR --#define MTD_BLOCK_MAJOR 31 --#endif -+static void jffs2_put_super(struct super_block *); -+ -+static kmem_cache_t *jffs2_inode_cachep; -+ -+static struct inode *jffs2_alloc_inode(struct super_block *sb) -+{ -+ struct jffs2_inode_info *ei; -+ ei = (struct jffs2_inode_info *)kmem_cache_alloc(jffs2_inode_cachep, SLAB_KERNEL); -+ if (!ei) -+ return NULL; -+ return &ei->vfs_inode; -+} -+ -+static void jffs2_destroy_inode(struct inode *inode) -+{ -+ kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode)); -+} -+ -+static void jffs2_i_init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) -+{ -+ struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo; - --extern void jffs2_read_inode (struct inode *); --void jffs2_put_super (struct super_block *); --void jffs2_write_super (struct super_block *); --static int jffs2_statfs (struct super_block *, struct statfs *); --int jffs2_remount_fs (struct super_block *, int *, char *); --extern void jffs2_clear_inode (struct inode *); -+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == -+ SLAB_CTOR_CONSTRUCTOR) { -+ init_MUTEX_LOCKED(&ei->sem); -+ inode_init_once(&ei->vfs_inode); -+ } -+} - - static struct super_operations jffs2_super_operations = - { -- read_inode: jffs2_read_inode, --// delete_inode: jffs2_delete_inode, -- put_super: jffs2_put_super, -- write_super: jffs2_write_super, -- statfs: jffs2_statfs, -- remount_fs: jffs2_remount_fs, -- clear_inode: jffs2_clear_inode -+ .alloc_inode = jffs2_alloc_inode, -+ .destroy_inode =jffs2_destroy_inode, -+ .read_inode = jffs2_read_inode, -+ .put_super = jffs2_put_super, -+ .write_super = jffs2_write_super, -+ .statfs = jffs2_statfs, -+ .remount_fs = jffs2_remount_fs, -+ .clear_inode = jffs2_clear_inode, -+ .dirty_inode = jffs2_dirty_inode, - }; - --static int jffs2_statfs(struct super_block *sb, struct statfs *buf) -+static int jffs2_sb_compare(struct super_block *sb, void *data) - { -+ struct jffs2_sb_info *p = data; - struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); -- unsigned long avail; - -- buf->f_type = JFFS2_SUPER_MAGIC; -- buf->f_bsize = 1 << PAGE_SHIFT; -- buf->f_blocks = c->flash_size >> PAGE_SHIFT; -- buf->f_files = 0; -- buf->f_ffree = 0; -- buf->f_namelen = JFFS2_MAX_NAME_LEN; -- -- spin_lock_bh(&c->erase_completion_lock); -- -- avail = c->dirty_size + c->free_size; -- if (avail > c->sector_size * JFFS2_RESERVED_BLOCKS_WRITE) -- avail -= c->sector_size * JFFS2_RESERVED_BLOCKS_WRITE; -- else -- avail = 0; -- -- buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT; -- --#if CONFIG_JFFS2_FS_DEBUG > 0 -- printk(KERN_DEBUG "STATFS:\n"); -- printk(KERN_DEBUG "flash_size: %08x\n", c->flash_size); -- printk(KERN_DEBUG "used_size: %08x\n", c->used_size); -- printk(KERN_DEBUG "dirty_size: %08x\n", c->dirty_size); -- printk(KERN_DEBUG "free_size: %08x\n", c->free_size); -- printk(KERN_DEBUG "erasing_size: %08x\n", c->erasing_size); -- printk(KERN_DEBUG "bad_size: %08x\n", c->bad_size); -- printk(KERN_DEBUG "sector_size: %08x\n", c->sector_size); -- -- if (c->nextblock) { -- printk(KERN_DEBUG "nextblock: 0x%08x\n", c->nextblock->offset); -- } else { -- printk(KERN_DEBUG "nextblock: NULL\n"); -- } -- if (c->gcblock) { -- printk(KERN_DEBUG "gcblock: 0x%08x\n", c->gcblock->offset); -+ /* The superblocks are considered to be equivalent if the underlying MTD -+ device is the same one */ -+ if (c->mtd == p->mtd) { -+ D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", p->mtd->index, p->mtd->name)); -+ return 1; - } else { -- printk(KERN_DEBUG "gcblock: NULL\n"); -+ D1(printk(KERN_DEBUG "jffs2_sb_compare: No match, device %d (\"%s\"), device %d (\"%s\")\n", -+ c->mtd->index, c->mtd->name, p->mtd->index, p->mtd->name)); -+ return 0; - } -- if (list_empty(&c->clean_list)) { -- printk(KERN_DEBUG "clean_list: empty\n"); -- } else { -- struct list_head *this; -+} - -- list_for_each(this, &c->clean_list) { -- struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -- printk(KERN_DEBUG "clean_list: %08x\n", jeb->offset); -- } -- } -- if (list_empty(&c->dirty_list)) { -- printk(KERN_DEBUG "dirty_list: empty\n"); -- } else { -- struct list_head *this; -+static int jffs2_sb_set(struct super_block *sb, void *data) -+{ -+ struct jffs2_sb_info *p = data; - -- list_for_each(this, &c->dirty_list) { -- struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -- printk(KERN_DEBUG "dirty_list: %08x\n", jeb->offset); -- } -- } -- if (list_empty(&c->erasing_list)) { -- printk(KERN_DEBUG "erasing_list: empty\n"); -- } else { -- struct list_head *this; -+ /* For persistence of NFS exports etc. we use the same s_dev -+ each time we mount the device, don't just use an anonymous -+ device */ -+ sb->s_fs_info = p; -+ p->os_priv = sb; -+ sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, p->mtd->index); - -- list_for_each(this, &c->erasing_list) { -- struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -- printk(KERN_DEBUG "erasing_list: %08x\n", jeb->offset); -- } -- } -- if (list_empty(&c->erase_pending_list)) { -- printk(KERN_DEBUG "erase_pending_list: empty\n"); -- } else { -- struct list_head *this; -+ return 0; -+} - -- list_for_each(this, &c->erase_pending_list) { -- struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -- printk(KERN_DEBUG "erase_pending_list: %08x\n", jeb->offset); -- } -- } -- if (list_empty(&c->free_list)) { -- printk(KERN_DEBUG "free_list: empty\n"); -- } else { -- struct list_head *this; -+static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, -+ int flags, const char *dev_name, -+ void *data, struct mtd_info *mtd) -+{ -+ struct super_block *sb; -+ struct jffs2_sb_info *c; -+ int ret; - -- list_for_each(this, &c->free_list) { -- struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -- printk(KERN_DEBUG "free_list: %08x\n", jeb->offset); -- } -- } -- if (list_empty(&c->bad_list)) { -- printk(KERN_DEBUG "bad_list: empty\n"); -- } else { -- struct list_head *this; -+ c = kmalloc(sizeof(*c), GFP_KERNEL); -+ if (!c) -+ return ERR_PTR(-ENOMEM); -+ memset(c, 0, sizeof(*c)); -+ c->mtd = mtd; - -- list_for_each(this, &c->bad_list) { -- struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -- printk(KERN_DEBUG "bad_list: %08x\n", jeb->offset); -- } -- } -- if (list_empty(&c->bad_used_list)) { -- printk(KERN_DEBUG "bad_used_list: empty\n"); -- } else { -- struct list_head *this; -+ sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c); -+ -+ if (IS_ERR(sb)) -+ goto out_put; - -- list_for_each(this, &c->bad_used_list) { -- struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -- printk(KERN_DEBUG "bad_used_list: %08x\n", jeb->offset); -+ if (sb->s_root) { -+ /* New mountpoint for JFFS2 which is already mounted */ -+ D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n", -+ mtd->index, mtd->name)); -+ goto out_put; - } -+ -+ D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): New superblock for device %d (\"%s\")\n", -+ mtd->index, mtd->name)); -+ -+ sb->s_op = &jffs2_super_operations; -+ -+ ret = jffs2_do_fill_super(sb, data, (flags&MS_VERBOSE)?1:0); -+ -+ if (ret) { -+ /* Failure case... */ -+ up_write(&sb->s_umount); -+ deactivate_super(sb); -+ return ERR_PTR(ret); - } --#endif /* CONFIG_JFFS2_FS_DEBUG */ - -- spin_unlock_bh(&c->erase_completion_lock); -+ sb->s_flags |= MS_ACTIVE; -+ return sb; - -+ out_put: -+ kfree(c); -+ put_mtd_device(mtd); - -- return 0; -+ return sb; - } - --static struct super_block *jffs2_read_super(struct super_block *sb, void *data, int silent) -+static struct super_block *jffs2_get_sb_mtdnr(struct file_system_type *fs_type, -+ int flags, const char *dev_name, -+ void *data, int mtdnr) - { -- struct jffs2_sb_info *c; -- struct inode *root_i; -- int i; -- -- D1(printk(KERN_DEBUG "jffs2: read_super for device %s\n", kdevname(sb->s_dev))); -+ struct mtd_info *mtd; - -- if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) { -- if (!silent) -- printk(KERN_DEBUG "jffs2: attempt to mount non-MTD device %s\n", kdevname(sb->s_dev)); -- return NULL; -+ mtd = get_mtd_device(NULL, mtdnr); -+ if (!mtd) { -+ D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr)); -+ return ERR_PTR(-EINVAL); - } - -- c = JFFS2_SB_INFO(sb); -- memset(c, 0, sizeof(*c)); -+ return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); -+} - -- c->mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); -- if (!c->mtd) { -- D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", MINOR(sb->s_dev))); -- return NULL; -+static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, -+ int flags, const char *dev_name, -+ void *data) -+{ -+ int err; -+ struct nameidata nd; -+ int mtdnr; -+ -+ if (!dev_name) -+ return ERR_PTR(-EINVAL); -+ -+ D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name)); -+ -+ /* The preferred way of mounting in future; especially when -+ CONFIG_BLK_DEV is implemented - we specify the underlying -+ MTD device by number or by name, so that we don't require -+ block device support to be present in the kernel. */ -+ -+ /* FIXME: How to do the root fs this way? */ -+ -+ if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') { -+ /* Probably mounting without the blkdev crap */ -+ if (dev_name[3] == ':') { -+ struct mtd_info *mtd; -+ -+ /* Mount by MTD device name */ -+ D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4)); -+ for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) { -+ mtd = get_mtd_device(NULL, mtdnr); -+ if (mtd) { -+ if (!strcmp(mtd->name, dev_name+4)) -+ return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); -+ put_mtd_device(mtd); - } -- c->sector_size = c->mtd->erasesize; -- c->free_size = c->flash_size = c->mtd->size; -- c->nr_blocks = c->mtd->size / c->mtd->erasesize; -- c->blocks = kmalloc(sizeof(struct jffs2_eraseblock) * c->nr_blocks, GFP_KERNEL); -- if (!c->blocks) -- goto out_mtd; -- for (i=0; inr_blocks; i++) { -- INIT_LIST_HEAD(&c->blocks[i].list); -- c->blocks[i].offset = i * c->sector_size; -- c->blocks[i].free_size = c->sector_size; -- c->blocks[i].dirty_size = 0; -- c->blocks[i].used_size = 0; -- c->blocks[i].first_node = NULL; -- c->blocks[i].last_node = NULL; -- } -- -- spin_lock_init(&c->nodelist_lock); -- init_MUTEX(&c->alloc_sem); -- init_waitqueue_head(&c->erase_wait); -- spin_lock_init(&c->erase_completion_lock); -- spin_lock_init(&c->inocache_lock); -- -- INIT_LIST_HEAD(&c->clean_list); -- INIT_LIST_HEAD(&c->dirty_list); -- INIT_LIST_HEAD(&c->erasing_list); -- INIT_LIST_HEAD(&c->erase_pending_list); -- INIT_LIST_HEAD(&c->erase_complete_list); -- INIT_LIST_HEAD(&c->free_list); -- INIT_LIST_HEAD(&c->bad_list); -- INIT_LIST_HEAD(&c->bad_used_list); -- c->highest_ino = 1; -- -- if (jffs2_build_filesystem(c)) { -- D1(printk(KERN_DEBUG "build_fs failed\n")); -- goto out_nodes; - } -+ printk(KERN_NOTICE "jffs2_get_sb(): MTD device with name \"%s\" not found.\n", dev_name+4); -+ } else if (isdigit(dev_name[3])) { -+ /* Mount by MTD device number name */ -+ char *endptr; - -- sb->s_op = &jffs2_super_operations; -+ mtdnr = simple_strtoul(dev_name+3, &endptr, 0); -+ if (!*endptr) { -+ /* It was a valid number */ -+ D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr)); -+ return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); -+ } -+ } -+ } - -- D1(printk(KERN_DEBUG "jffs2_read_super(): Getting root inode\n")); -- root_i = iget(sb, 1); -- if (is_bad_inode(root_i)) { -- D1(printk(KERN_WARNING "get root inode failed\n")); -- goto out_nodes; -+ /* Try the old way - the hack where we allowed users to mount -+ /dev/mtdblock$(n) but didn't actually _use_ the blkdev */ -+ -+ err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); -+ -+ D1(printk(KERN_DEBUG "jffs2_get_sb(): path_lookup() returned %d, inode %p\n", -+ err, nd.dentry->d_inode)); -+ -+ if (err) -+ return ERR_PTR(err); -+ -+ err = -EINVAL; -+ -+ if (!S_ISBLK(nd.dentry->d_inode->i_mode)) -+ goto out; -+ -+ if (nd.mnt->mnt_flags & MNT_NODEV) { -+ err = -EACCES; -+ goto out; - } - -- D1(printk(KERN_DEBUG "jffs2_read_super(): d_alloc_root()\n")); -- sb->s_root = d_alloc_root(root_i); -- if (!sb->s_root) -- goto out_root_i; -+ if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) { -+ if (!(flags & MS_VERBOSE)) /* Yes I mean this. Strangely */ -+ printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n", -+ dev_name); -+ goto out; -+ } - --#if LINUX_VERSION_CODE >= 0x20403 -- sb->s_maxbytes = 0xFFFFFFFF; --#endif -- sb->s_blocksize = PAGE_CACHE_SIZE; -- sb->s_blocksize_bits = PAGE_CACHE_SHIFT; -- sb->s_magic = JFFS2_SUPER_MAGIC; -- if (!(sb->s_flags & MS_RDONLY)) -- jffs2_start_garbage_collect_thread(c); -- return sb; -+ mtdnr = iminor(nd.dentry->d_inode); -+ path_release(&nd); - -- out_root_i: -- iput(root_i); -- out_nodes: -- jffs2_free_ino_caches(c); -- jffs2_free_raw_node_refs(c); -- kfree(c->blocks); -- out_mtd: -- put_mtd_device(c->mtd); -- return NULL; -+ return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); -+ -+out: -+ path_release(&nd); -+ return ERR_PTR(err); - } - --void jffs2_put_super (struct super_block *sb) -+static void jffs2_put_super (struct super_block *sb) - { - struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); - -@@ -293,74 +259,53 @@ - - if (!(sb->s_flags & MS_RDONLY)) - jffs2_stop_garbage_collect_thread(c); -+ down(&c->alloc_sem); -+ jffs2_flush_wbuf_pad(c); -+ up(&c->alloc_sem); - jffs2_free_ino_caches(c); - jffs2_free_raw_node_refs(c); - kfree(c->blocks); -+ jffs2_nand_flash_cleanup(c); -+ kfree(c->inocache_list); - if (c->mtd->sync) - c->mtd->sync(c->mtd); -- put_mtd_device(c->mtd); - - D1(printk(KERN_DEBUG "jffs2_put_super returning\n")); - } - --int jffs2_remount_fs (struct super_block *sb, int *flags, char *data) -+static void jffs2_kill_sb(struct super_block *sb) - { - struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); -- -- if (c->flags & JFFS2_SB_FLAG_RO && !(sb->s_flags & MS_RDONLY)) -- return -EROFS; -- -- /* We stop if it was running, then restart if it needs to. -- This also catches the case where it was stopped and this -- is just a remount to restart it */ -- if (!(sb->s_flags & MS_RDONLY)) -- jffs2_stop_garbage_collect_thread(c); -- -- if (!(*flags & MS_RDONLY)) -- jffs2_start_garbage_collect_thread(c); -- -- sb->s_flags = (sb->s_flags & ~MS_RDONLY)|(*flags & MS_RDONLY); -- -- return 0; --} -- --void jffs2_write_super (struct super_block *sb) --{ -- struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); -- sb->s_dirt = 0; -- -- if (sb->s_flags & MS_RDONLY) -- return; -- -- jffs2_garbage_collect_trigger(c); -- jffs2_erase_pending_blocks(c); -- jffs2_mark_erased_blocks(c); -+ generic_shutdown_super(sb); -+ put_mtd_device(c->mtd); -+ kfree(c); - } - -- --static DECLARE_FSTYPE_DEV(jffs2_fs_type, "jffs2", jffs2_read_super); -+static struct file_system_type jffs2_fs_type = { -+ .owner = THIS_MODULE, -+ .name = "jffs2", -+ .get_sb = jffs2_get_sb, -+ .kill_sb = jffs2_kill_sb, -+}; - - static int __init init_jffs2_fs(void) - { - int ret; - -- printk(KERN_NOTICE "JFFS2 version 2.1. (C) 2001 Red Hat, Inc., designed by Axis Communications AB.\n"); -- --#ifdef JFFS2_OUT_OF_KERNEL -- /* sanity checks. Could we do these at compile time? */ -- if (sizeof(struct jffs2_sb_info) > sizeof (((struct super_block *)NULL)->u)) { -- printk(KERN_ERR "JFFS2 error: struct jffs2_sb_info (%d bytes) doesn't fit in the super_block union (%d bytes)\n", -- sizeof(struct jffs2_sb_info), sizeof (((struct super_block *)NULL)->u)); -- return -EIO; -- } -- -- if (sizeof(struct jffs2_inode_info) > sizeof (((struct inode *)NULL)->u)) { -- printk(KERN_ERR "JFFS2 error: struct jffs2_inode_info (%d bytes) doesn't fit in the inode union (%d bytes)\n", -- sizeof(struct jffs2_inode_info), sizeof (((struct inode *)NULL)->u)); -- return -EIO; -- } -+ printk(KERN_INFO "JFFS2 version 2.2." -+#ifdef CONFIG_FS_JFFS2_NAND -+ " (NAND)" - #endif -+ " (C) 2001-2003 Red Hat, Inc.\n"); - -+ jffs2_inode_cachep = kmem_cache_create("jffs2_i", -+ sizeof(struct jffs2_inode_info), -+ 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, -+ jffs2_i_init_once, NULL); -+ if (!jffs2_inode_cachep) { -+ printk(KERN_ERR "JFFS2 error: Failed to initialise inode cache\n"); -+ return -ENOMEM; -+ } - ret = jffs2_zlib_init(); - if (ret) { - printk(KERN_ERR "JFFS2 error: Failed to initialise zlib workspaces\n"); -@@ -388,9 +333,10 @@ - - static void __exit exit_jffs2_fs(void) - { -+ unregister_filesystem(&jffs2_fs_type); - jffs2_destroy_slab_caches(); - jffs2_zlib_exit(); -- unregister_filesystem(&jffs2_fs_type); -+ kmem_cache_destroy(jffs2_inode_cachep); - } - - module_init(init_jffs2_fs); -diff -Nurb linux-mips-2.4.27/fs/jffs2/symlink.c linux/fs/jffs2/symlink.c ---- linux-mips-2.4.27/fs/jffs2/symlink.c 2002-06-27 00:36:20.000000000 +0200 -+++ linux/fs/jffs2/symlink.c 2004-11-19 10:25:12.129164832 +0100 -@@ -3,35 +3,11 @@ - * - * Copyright (C) 2001, 2002 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - -@@ -39,7 +15,6 @@ - #include - #include - #include --#include - #include "nodelist.h" - - int jffs2_readlink(struct dentry *dentry, char *buffer, int buflen); -@@ -47,45 +22,17 @@ - - struct inode_operations jffs2_symlink_inode_operations = - { -- readlink: jffs2_readlink, -- follow_link: jffs2_follow_link, -- setattr: jffs2_setattr -+ .readlink = jffs2_readlink, -+ .follow_link = jffs2_follow_link, -+ .setattr = jffs2_setattr - }; - --static char *jffs2_getlink(struct dentry *dentry) --{ -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); -- char *buf; -- int ret; -- -- down(&f->sem); -- if (!f->metadata) { -- up(&f->sem); -- printk(KERN_NOTICE "No metadata for symlink inode #%lu\n", dentry->d_inode->i_ino); -- return ERR_PTR(-EINVAL); -- } -- buf = kmalloc(f->metadata->size+1, GFP_USER); -- if (!buf) { -- up(&f->sem); -- return ERR_PTR(-ENOMEM); -- } -- buf[f->metadata->size]=0; -- -- ret = jffs2_read_dnode(JFFS2_SB_INFO(dentry->d_inode->i_sb), f->metadata, buf, 0, f->metadata->size); -- up(&f->sem); -- if (ret) { -- kfree(buf); -- return ERR_PTR(ret); -- } -- return buf; -- --} - int jffs2_readlink(struct dentry *dentry, char *buffer, int buflen) - { - unsigned char *kbuf; - int ret; - -- kbuf = jffs2_getlink(dentry); -+ kbuf = jffs2_getlink(JFFS2_SB_INFO(dentry->d_inode->i_sb), JFFS2_INODE_INFO(dentry->d_inode)); - if (IS_ERR(kbuf)) - return PTR_ERR(kbuf); - -@@ -99,7 +46,7 @@ - unsigned char *buf; - int ret; - -- buf = jffs2_getlink(dentry); -+ buf = jffs2_getlink(JFFS2_SB_INFO(dentry->d_inode->i_sb), JFFS2_INODE_INFO(dentry->d_inode)); - - if (IS_ERR(buf)) - return PTR_ERR(buf); -diff -Nurb linux-mips-2.4.27/fs/jffs2/wbuf.c linux/fs/jffs2/wbuf.c ---- linux-mips-2.4.27/fs/jffs2/wbuf.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/wbuf.c 2004-11-19 10:25:12.131164528 +0100 -@@ -0,0 +1,1156 @@ -+/* -+ * JFFS2 -- Journalling Flash File System, Version 2. -+ * -+ * Copyright (C) 2001-2003 Red Hat, Inc. -+ * -+ * Created by David Woodhouse -+ * -+ * For licensing information, see the file 'LICENCE' in this directory. -+ * -+ * $Id$ -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "nodelist.h" -+ -+/* For testing write failures */ -+#undef BREAKME -+#undef BREAKMEHEADER -+ -+#ifdef BREAKME -+static unsigned char *brokenbuf; -+#endif -+ -+/* max. erase failures before we mark a block bad */ -+#define MAX_ERASE_FAILURES 5 -+ -+/* two seconds timeout for timed wbuf-flushing */ -+#define WBUF_FLUSH_TIMEOUT 2 * HZ -+ -+struct jffs2_inodirty { -+ uint32_t ino; -+ struct jffs2_inodirty *next; -+}; -+ -+static struct jffs2_inodirty inodirty_nomem; -+ -+static int jffs2_wbuf_pending_for_ino(struct jffs2_sb_info *c, uint32_t ino) -+{ -+ struct jffs2_inodirty *this = c->wbuf_inodes; -+ -+ /* If a malloc failed, consider _everything_ dirty */ -+ if (this == &inodirty_nomem) -+ return 1; -+ -+ /* If ino == 0, _any_ non-GC writes mean 'yes' */ -+ if (this && !ino) -+ return 1; -+ -+ /* Look to see if the inode in question is pending in the wbuf */ -+ while (this) { -+ if (this->ino == ino) -+ return 1; -+ this = this->next; -+ } -+ return 0; -+} -+ -+static void jffs2_clear_wbuf_ino_list(struct jffs2_sb_info *c) -+{ -+ struct jffs2_inodirty *this; -+ -+ this = c->wbuf_inodes; -+ -+ if (this != &inodirty_nomem) { -+ while (this) { -+ struct jffs2_inodirty *next = this->next; -+ kfree(this); -+ this = next; -+ } -+ } -+ c->wbuf_inodes = NULL; -+} -+ -+static void jffs2_wbuf_dirties_inode(struct jffs2_sb_info *c, uint32_t ino) -+{ -+ struct jffs2_inodirty *new; -+ -+ /* Mark the superblock dirty so that kupdated will flush... */ -+ OFNI_BS_2SFFJ(c)->s_dirt = 1; -+ -+ if (jffs2_wbuf_pending_for_ino(c, ino)) -+ return; -+ -+ new = kmalloc(sizeof(*new), GFP_KERNEL); -+ if (!new) { -+ D1(printk(KERN_DEBUG "No memory to allocate inodirty. Fallback to all considered dirty\n")); -+ jffs2_clear_wbuf_ino_list(c); -+ c->wbuf_inodes = &inodirty_nomem; -+ return; -+ } -+ new->ino = ino; -+ new->next = c->wbuf_inodes; -+ c->wbuf_inodes = new; -+ return; -+} -+ -+static inline void jffs2_refile_wbuf_blocks(struct jffs2_sb_info *c) -+{ -+ struct list_head *this, *next; -+ static int n; -+ -+ if (list_empty(&c->erasable_pending_wbuf_list)) -+ return; -+ -+ list_for_each_safe(this, next, &c->erasable_pending_wbuf_list) { -+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); -+ -+ D1(printk(KERN_DEBUG "Removing eraseblock at 0x%08x from erasable_pending_wbuf_list...\n", jeb->offset)); -+ list_del(this); -+ if ((jiffies + (n++)) & 127) { -+ /* Most of the time, we just erase it immediately. Otherwise we -+ spend ages scanning it on mount, etc. */ -+ D1(printk(KERN_DEBUG "...and adding to erase_pending_list\n")); -+ list_add_tail(&jeb->list, &c->erase_pending_list); -+ c->nr_erasing_blocks++; -+ jffs2_erase_pending_trigger(c); -+ } else { -+ /* Sometimes, however, we leave it elsewhere so it doesn't get -+ immediately reused, and we spread the load a bit. */ -+ D1(printk(KERN_DEBUG "...and adding to erasable_list\n")); -+ list_add_tail(&jeb->list, &c->erasable_list); -+ } -+ } -+} -+ -+/* Recover from failure to write wbuf. Recover the nodes up to the -+ * wbuf, not the one which we were starting to try to write. */ -+ -+static void jffs2_wbuf_recover(struct jffs2_sb_info *c) -+{ -+ struct jffs2_eraseblock *jeb, *new_jeb; -+ struct jffs2_raw_node_ref **first_raw, **raw; -+ size_t retlen; -+ int ret; -+ unsigned char *buf; -+ uint32_t start, end, ofs, len; -+ -+ spin_lock(&c->erase_completion_lock); -+ -+ jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; -+ -+ D1(printk("About to refile bad block at %08x\n", jeb->offset)); -+ -+ D2(jffs2_dump_block_lists(c)); -+ /* File the existing block on the bad_used_list.... */ -+ if (c->nextblock == jeb) -+ c->nextblock = NULL; -+ else /* Not sure this should ever happen... need more coffee */ -+ list_del(&jeb->list); -+ if (jeb->first_node) { -+ D1(printk("Refiling block at %08x to bad_used_list\n", jeb->offset)); -+ list_add(&jeb->list, &c->bad_used_list); -+ } else { -+ BUG(); -+ /* It has to have had some nodes or we couldn't be here */ -+ D1(printk("Refiling block at %08x to erase_pending_list\n", jeb->offset)); -+ list_add(&jeb->list, &c->erase_pending_list); -+ c->nr_erasing_blocks++; -+ jffs2_erase_pending_trigger(c); -+ } -+ D2(jffs2_dump_block_lists(c)); -+ -+ /* Adjust its size counts accordingly */ -+ c->wasted_size += jeb->free_size; -+ c->free_size -= jeb->free_size; -+ jeb->wasted_size += jeb->free_size; -+ jeb->free_size = 0; -+ -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ /* Find the first node to be recovered, by skipping over every -+ node which ends before the wbuf starts, or which is obsolete. */ -+ first_raw = &jeb->first_node; -+ while (*first_raw && -+ (ref_obsolete(*first_raw) || -+ (ref_offset(*first_raw)+ref_totlen(c, jeb, *first_raw)) < c->wbuf_ofs)) { -+ D1(printk(KERN_DEBUG "Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n", -+ ref_offset(*first_raw), ref_flags(*first_raw), -+ (ref_offset(*first_raw) + ref_totlen(c, jeb, *first_raw)), -+ c->wbuf_ofs)); -+ first_raw = &(*first_raw)->next_phys; -+ } -+ -+ if (!*first_raw) { -+ /* All nodes were obsolete. Nothing to recover. */ -+ D1(printk(KERN_DEBUG "No non-obsolete nodes to be recovered. Just filing block bad\n")); -+ spin_unlock(&c->erase_completion_lock); -+ return; -+ } -+ -+ start = ref_offset(*first_raw); -+ end = ref_offset(*first_raw) + ref_totlen(c, jeb, *first_raw); -+ -+ /* Find the last node to be recovered */ -+ raw = first_raw; -+ while ((*raw)) { -+ if (!ref_obsolete(*raw)) -+ end = ref_offset(*raw) + ref_totlen(c, jeb, *raw); -+ -+ raw = &(*raw)->next_phys; -+ } -+ spin_unlock(&c->erase_completion_lock); -+ -+ D1(printk(KERN_DEBUG "wbuf recover %08x-%08x\n", start, end)); -+ -+ buf = NULL; -+ if (start < c->wbuf_ofs) { -+ /* First affected node was already partially written. -+ * Attempt to reread the old data into our buffer. */ -+ -+ buf = kmalloc(end - start, GFP_KERNEL); -+ if (!buf) { -+ printk(KERN_CRIT "Malloc failure in wbuf recovery. Data loss ensues.\n"); -+ -+ goto read_failed; -+ } -+ -+ /* Do the read... */ -+ ret = c->mtd->read_ecc(c->mtd, start, c->wbuf_ofs - start, &retlen, buf, NULL, c->oobinfo); -+ if (ret == -EIO && retlen == c->wbuf_ofs - start) { -+ /* ECC recovered */ -+ ret = 0; -+ } -+ if (ret || retlen != c->wbuf_ofs - start) { -+ printk(KERN_CRIT "Old data are already lost in wbuf recovery. Data loss ensues.\n"); -+ -+ kfree(buf); -+ buf = NULL; -+ read_failed: -+ first_raw = &(*first_raw)->next_phys; -+ /* If this was the only node to be recovered, give up */ -+ if (!(*first_raw)) -+ return; -+ -+ /* It wasn't. Go on and try to recover nodes complete in the wbuf */ -+ start = ref_offset(*first_raw); -+ } else { -+ /* Read succeeded. Copy the remaining data from the wbuf */ -+ memcpy(buf + (c->wbuf_ofs - start), c->wbuf, end - c->wbuf_ofs); -+ } -+ } -+ /* OK... we're to rewrite (end-start) bytes of data from first_raw onwards. -+ Either 'buf' contains the data, or we find it in the wbuf */ -+ -+ -+ /* ... and get an allocation of space from a shiny new block instead */ -+ ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len); -+ if (ret) { -+ printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n"); -+ if (buf) -+ kfree(buf); -+ return; -+ } -+ if (end-start >= c->wbuf_pagesize) { -+ /* Need to do another write immediately. This, btw, -+ means that we'll be writing from 'buf' and not from -+ the wbuf. Since if we're writing from the wbuf there -+ won't be more than a wbuf full of data, now will -+ there? :) */ -+ -+ uint32_t towrite = (end-start) - ((end-start)%c->wbuf_pagesize); -+ -+ D1(printk(KERN_DEBUG "Write 0x%x bytes at 0x%08x in wbuf recover\n", -+ towrite, ofs)); -+ -+#ifdef BREAKMEHEADER -+ static int breakme; -+ if (breakme++ == 20) { -+ printk(KERN_NOTICE "Faking write error at 0x%08x\n", ofs); -+ breakme = 0; -+ c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen, -+ brokenbuf, NULL, c->oobinfo); -+ ret = -EIO; -+ } else -+#endif -+ ret = c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen, -+ buf, NULL, c->oobinfo); -+ -+ if (ret || retlen != towrite) { -+ /* Argh. We tried. Really we did. */ -+ printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n"); -+ kfree(buf); -+ -+ if (retlen) { -+ struct jffs2_raw_node_ref *raw2; -+ -+ raw2 = jffs2_alloc_raw_node_ref(); -+ if (!raw2) -+ return; -+ -+ raw2->flash_offset = ofs | REF_OBSOLETE; -+ raw2->__totlen = ref_totlen(c, jeb, *first_raw); -+ raw2->next_phys = NULL; -+ raw2->next_in_ino = NULL; -+ -+ jffs2_add_physical_node_ref(c, raw2); -+ } -+ return; -+ } -+ printk(KERN_NOTICE "Recovery of wbuf succeeded to %08x\n", ofs); -+ -+ c->wbuf_len = (end - start) - towrite; -+ c->wbuf_ofs = ofs + towrite; -+ memcpy(c->wbuf, buf + towrite, c->wbuf_len); -+ /* Don't muck about with c->wbuf_inodes. False positives are harmless. */ -+ -+ kfree(buf); -+ } else { -+ /* OK, now we're left with the dregs in whichever buffer we're using */ -+ if (buf) { -+ memcpy(c->wbuf, buf, end-start); -+ kfree(buf); -+ } else { -+ memmove(c->wbuf, c->wbuf + (start - c->wbuf_ofs), end - start); -+ } -+ c->wbuf_ofs = ofs; -+ c->wbuf_len = end - start; -+ } -+ -+ /* Now sort out the jffs2_raw_node_refs, moving them from the old to the next block */ -+ new_jeb = &c->blocks[ofs / c->sector_size]; -+ -+ spin_lock(&c->erase_completion_lock); -+ if (new_jeb->first_node) { -+ /* Odd, but possible with ST flash later maybe */ -+ new_jeb->last_node->next_phys = *first_raw; -+ } else { -+ new_jeb->first_node = *first_raw; -+ } -+ -+ raw = first_raw; -+ while (*raw) { -+ uint32_t rawlen = ref_totlen(c, jeb, *raw); -+ -+ D1(printk(KERN_DEBUG "Refiling block of %08x at %08x(%d) to %08x\n", -+ rawlen, ref_offset(*raw), ref_flags(*raw), ofs)); -+ -+ if (ref_obsolete(*raw)) { -+ /* Shouldn't really happen much */ -+ new_jeb->dirty_size += rawlen; -+ new_jeb->free_size -= rawlen; -+ c->dirty_size += rawlen; -+ } else { -+ new_jeb->used_size += rawlen; -+ new_jeb->free_size -= rawlen; -+ jeb->dirty_size += rawlen; -+ jeb->used_size -= rawlen; -+ c->dirty_size += rawlen; -+ } -+ c->free_size -= rawlen; -+ (*raw)->flash_offset = ofs | ref_flags(*raw); -+ ofs += rawlen; -+ new_jeb->last_node = *raw; -+ -+ raw = &(*raw)->next_phys; -+ } -+ -+ /* Fix up the original jeb now it's on the bad_list */ -+ *first_raw = NULL; -+ if (first_raw == &jeb->first_node) { -+ jeb->last_node = NULL; -+ D1(printk(KERN_DEBUG "Failing block at %08x is now empty. Moving to erase_pending_list\n", jeb->offset)); -+ list_del(&jeb->list); -+ list_add(&jeb->list, &c->erase_pending_list); -+ c->nr_erasing_blocks++; -+ jffs2_erase_pending_trigger(c); -+ } -+ else -+ jeb->last_node = container_of(first_raw, struct jffs2_raw_node_ref, next_phys); -+ -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ ACCT_SANITY_CHECK(c,new_jeb); -+ D1(ACCT_PARANOIA_CHECK(new_jeb)); -+ -+ spin_unlock(&c->erase_completion_lock); -+ -+ D1(printk(KERN_DEBUG "wbuf recovery completed OK\n")); -+} -+ -+/* Meaning of pad argument: -+ 0: Do not pad. Probably pointless - we only ever use this when we can't pad anyway. -+ 1: Pad, do not adjust nextblock free_size -+ 2: Pad, adjust nextblock free_size -+*/ -+static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) -+{ -+ int ret; -+ size_t retlen; -+ -+ /* Nothing to do if not NAND flash. In particular, we shouldn't -+ del_timer() the timer we never initialised. */ -+ if (jffs2_can_mark_obsolete(c)) -+ return 0; -+ -+ if (!down_trylock(&c->alloc_sem)) { -+ up(&c->alloc_sem); -+ printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n"); -+ BUG(); -+ } -+ -+ if(!c->wbuf || !c->wbuf_len) -+ return 0; -+ -+ /* claim remaining space on the page -+ this happens, if we have a change to a new block, -+ or if fsync forces us to flush the writebuffer. -+ if we have a switch to next page, we will not have -+ enough remaining space for this. -+ */ -+ if (pad) { -+ c->wbuf_len = PAD(c->wbuf_len); -+ -+ if ( c->wbuf_len + sizeof(struct jffs2_unknown_node) < c->wbuf_pagesize) { -+ struct jffs2_unknown_node *padnode = (void *)(c->wbuf + c->wbuf_len); -+ padnode->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ padnode->nodetype = cpu_to_je16(JFFS2_NODETYPE_PADDING); -+ padnode->totlen = cpu_to_je32(c->wbuf_pagesize - c->wbuf_len); -+ padnode->hdr_crc = cpu_to_je32(crc32(0, padnode, sizeof(*padnode)-4)); -+ } -+ } -+ /* else jffs2_flash_writev has actually filled in the rest of the -+ buffer for us, and will deal with the node refs etc. later. */ -+ -+#ifdef BREAKME -+ static int breakme; -+ if (breakme++ == 20) { -+ printk(KERN_NOTICE "Faking write error at 0x%08x\n", c->wbuf_ofs); -+ breakme = 0; -+ c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, -+ &retlen, brokenbuf, NULL, c->oobinfo); -+ ret = -EIO; -+ } else -+#endif -+ ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo); -+ -+ -+ if (ret || retlen != c->wbuf_pagesize) { -+ if (ret) -+ printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n",ret); -+ else { -+ printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n", -+ retlen, c->wbuf_pagesize); -+ ret = -EIO; -+ } -+ -+ jffs2_wbuf_recover(c); -+ -+ return ret; -+ } -+ -+ /* Adjusting free size of next block only, if it's called from fsync ! */ -+ if (pad == 2) { -+ D1(printk(KERN_DEBUG "jffs2_flush_wbuf() adjusting free_size of c->nextblock\n")); -+ spin_lock(&c->erase_completion_lock); -+ if (!c->nextblock) -+ BUG(); -+ /* wbuf_pagesize - wbuf_len is the amount of space that's to be -+ padded. If there is less free space in the block than that, -+ something screwed up */ -+ if (c->nextblock->free_size < (c->wbuf_pagesize - c->wbuf_len)) { -+ printk(KERN_CRIT "jffs2_flush_wbuf(): Accounting error. wbuf at 0x%08x has 0x%03x bytes, 0x%03x left.\n", -+ c->wbuf_ofs, c->wbuf_len, c->wbuf_pagesize-c->wbuf_len); -+ printk(KERN_CRIT "jffs2_flush_wbuf(): But free_size for block at 0x%08x is only 0x%08x\n", -+ c->nextblock->offset, c->nextblock->free_size); -+ BUG(); -+ } -+ c->nextblock->free_size -= (c->wbuf_pagesize - c->wbuf_len); -+ c->free_size -= (c->wbuf_pagesize - c->wbuf_len); -+ c->nextblock->wasted_size += (c->wbuf_pagesize - c->wbuf_len); -+ c->wasted_size += (c->wbuf_pagesize - c->wbuf_len); -+ spin_unlock(&c->erase_completion_lock); -+ } -+ -+ /* Stick any now-obsoleted blocks on the erase_pending_list */ -+ spin_lock(&c->erase_completion_lock); -+ jffs2_refile_wbuf_blocks(c); -+ jffs2_clear_wbuf_ino_list(c); -+ spin_unlock(&c->erase_completion_lock); -+ -+ memset(c->wbuf,0xff,c->wbuf_pagesize); -+ /* adjust write buffer offset, else we get a non contiguous write bug */ -+ c->wbuf_ofs += c->wbuf_pagesize; -+ c->wbuf_len = 0; -+ return 0; -+} -+ -+/* Trigger garbage collection to flush the write-buffer. -+ If ino arg is zero, do it if _any_ real (i.e. not GC) writes are -+ outstanding. If ino arg non-zero, do it only if a write for the -+ given inode is outstanding. */ -+int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino) -+{ -+ uint32_t old_wbuf_ofs; -+ uint32_t old_wbuf_len; -+ int ret = 0; -+ -+ D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() called for ino #%u...\n", ino)); -+ -+ down(&c->alloc_sem); -+ if (!jffs2_wbuf_pending_for_ino(c, ino)) { -+ D1(printk(KERN_DEBUG "Ino #%d not pending in wbuf. Returning\n", ino)); -+ up(&c->alloc_sem); -+ return 0; -+ } -+ -+ old_wbuf_ofs = c->wbuf_ofs; -+ old_wbuf_len = c->wbuf_len; -+ -+ if (c->unchecked_size) { -+ /* GC won't make any progress for a while */ -+ D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() padding. Not finished checking\n")); -+ ret = __jffs2_flush_wbuf(c, 2); -+ } else while (old_wbuf_len && -+ old_wbuf_ofs == c->wbuf_ofs) { -+ -+ up(&c->alloc_sem); -+ -+ D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() calls gc pass\n")); -+ -+ ret = jffs2_garbage_collect_pass(c); -+ if (ret) { -+ /* GC failed. Flush it with padding instead */ -+ down(&c->alloc_sem); -+ ret = __jffs2_flush_wbuf(c, 2); -+ break; -+ } -+ down(&c->alloc_sem); -+ } -+ -+ D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() ends...\n")); -+ -+ up(&c->alloc_sem); -+ return ret; -+} -+ -+/* Pad write-buffer to end and write it, wasting space. */ -+int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c) -+{ -+ return __jffs2_flush_wbuf(c, 1); -+} -+ -+ -+#define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) ) -+#define PAGE_MOD(x) ( (x) & (c->wbuf_pagesize - 1) ) -+int jffs2_flash_writev(struct jffs2_sb_info *c, const struct iovec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino) -+{ -+ struct iovec outvecs[3]; -+ uint32_t totlen = 0; -+ uint32_t split_ofs = 0; -+ uint32_t old_totlen; -+ int ret, splitvec = -1; -+ int invec, outvec; -+ size_t wbuf_retlen; -+ unsigned char *wbuf_ptr; -+ size_t donelen = 0; -+ uint32_t outvec_to = to; -+ -+ /* If not NAND flash, don't bother */ -+ if (!c->wbuf) -+ return jffs2_flash_direct_writev(c, invecs, count, to, retlen); -+ -+ /* If wbuf_ofs is not initialized, set it to target address */ -+ if (c->wbuf_ofs == 0xFFFFFFFF) { -+ c->wbuf_ofs = PAGE_DIV(to); -+ c->wbuf_len = PAGE_MOD(to); -+ memset(c->wbuf,0xff,c->wbuf_pagesize); -+ } -+ -+ /* Sanity checks on target address. -+ It's permitted to write at PAD(c->wbuf_len+c->wbuf_ofs), -+ and it's permitted to write at the beginning of a new -+ erase block. Anything else, and you die. -+ New block starts at xxx000c (0-b = block header) -+ */ -+ if ( (to & ~(c->sector_size-1)) != (c->wbuf_ofs & ~(c->sector_size-1)) ) { -+ /* It's a write to a new block */ -+ if (c->wbuf_len) { -+ D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx causes flush of wbuf at 0x%08x\n", (unsigned long)to, c->wbuf_ofs)); -+ ret = jffs2_flush_wbuf_pad(c); -+ if (ret) { -+ /* the underlying layer has to check wbuf_len to do the cleanup */ -+ D1(printk(KERN_WARNING "jffs2_flush_wbuf() called from jffs2_flash_writev() failed %d\n", ret)); -+ *retlen = 0; -+ return ret; -+ } -+ } -+ /* set pointer to new block */ -+ c->wbuf_ofs = PAGE_DIV(to); -+ c->wbuf_len = PAGE_MOD(to); -+ } -+ -+ if (to != PAD(c->wbuf_ofs + c->wbuf_len)) { -+ /* We're not writing immediately after the writebuffer. Bad. */ -+ printk(KERN_CRIT "jffs2_flash_writev(): Non-contiguous write to %08lx\n", (unsigned long)to); -+ if (c->wbuf_len) -+ printk(KERN_CRIT "wbuf was previously %08x-%08x\n", -+ c->wbuf_ofs, c->wbuf_ofs+c->wbuf_len); -+ BUG(); -+ } -+ -+ /* Note outvecs[3] above. We know count is never greater than 2 */ -+ if (count > 2) { -+ printk(KERN_CRIT "jffs2_flash_writev(): count is %ld\n", count); -+ BUG(); -+ } -+ -+ invec = 0; -+ outvec = 0; -+ -+ -+ /* Fill writebuffer first, if already in use */ -+ if (c->wbuf_len) { -+ uint32_t invec_ofs = 0; -+ -+ /* adjust alignment offset */ -+ if (c->wbuf_len != PAGE_MOD(to)) { -+ c->wbuf_len = PAGE_MOD(to); -+ /* take care of alignment to next page */ -+ if (!c->wbuf_len) -+ c->wbuf_len = c->wbuf_pagesize; -+ } -+ -+ while(c->wbuf_len < c->wbuf_pagesize) { -+ uint32_t thislen; -+ -+ if (invec == count) -+ goto alldone; -+ -+ thislen = c->wbuf_pagesize - c->wbuf_len; -+ -+ if (thislen >= invecs[invec].iov_len) -+ thislen = invecs[invec].iov_len; -+ -+ invec_ofs = thislen; -+ -+ memcpy(c->wbuf + c->wbuf_len, invecs[invec].iov_base, thislen); -+ c->wbuf_len += thislen; -+ donelen += thislen; -+ /* Get next invec, if actual did not fill the buffer */ -+ if (c->wbuf_len < c->wbuf_pagesize) -+ invec++; -+ } -+ -+ /* write buffer is full, flush buffer */ -+ ret = __jffs2_flush_wbuf(c, 0); -+ if (ret) { -+ /* the underlying layer has to check wbuf_len to do the cleanup */ -+ D1(printk(KERN_WARNING "jffs2_flush_wbuf() called from jffs2_flash_writev() failed %d\n", ret)); -+ /* Retlen zero to make sure our caller doesn't mark the space dirty. -+ We've already done everything that's necessary */ -+ *retlen = 0; -+ return ret; -+ } -+ outvec_to += donelen; -+ c->wbuf_ofs = outvec_to; -+ -+ /* All invecs done ? */ -+ if (invec == count) -+ goto alldone; -+ -+ /* Set up the first outvec, containing the remainder of the -+ invec we partially used */ -+ if (invecs[invec].iov_len > invec_ofs) { -+ outvecs[0].iov_base = invecs[invec].iov_base+invec_ofs; -+ totlen = outvecs[0].iov_len = invecs[invec].iov_len-invec_ofs; -+ if (totlen > c->wbuf_pagesize) { -+ splitvec = outvec; -+ split_ofs = outvecs[0].iov_len - PAGE_MOD(totlen); -+ } -+ outvec++; -+ } -+ invec++; -+ } -+ -+ /* OK, now we've flushed the wbuf and the start of the bits -+ we have been asked to write, now to write the rest.... */ -+ -+ /* totlen holds the amount of data still to be written */ -+ old_totlen = totlen; -+ for ( ; invec < count; invec++,outvec++ ) { -+ outvecs[outvec].iov_base = invecs[invec].iov_base; -+ totlen += outvecs[outvec].iov_len = invecs[invec].iov_len; -+ if (PAGE_DIV(totlen) != PAGE_DIV(old_totlen)) { -+ splitvec = outvec; -+ split_ofs = outvecs[outvec].iov_len - PAGE_MOD(totlen); -+ old_totlen = totlen; -+ } -+ } -+ -+ /* Now the outvecs array holds all the remaining data to write */ -+ /* Up to splitvec,split_ofs is to be written immediately. The rest -+ goes into the (now-empty) wbuf */ -+ -+ if (splitvec != -1) { -+ uint32_t remainder; -+ int ret; -+ -+ remainder = outvecs[splitvec].iov_len - split_ofs; -+ outvecs[splitvec].iov_len = split_ofs; -+ -+ /* We did cross a page boundary, so we write some now */ -+ ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo); -+ if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) { -+ /* At this point we have no problem, -+ c->wbuf is empty. -+ */ -+ *retlen = donelen; -+ return ret; -+ } -+ -+ donelen += wbuf_retlen; -+ c->wbuf_ofs = PAGE_DIV(outvec_to) + PAGE_DIV(totlen); -+ -+ if (remainder) { -+ outvecs[splitvec].iov_base += split_ofs; -+ outvecs[splitvec].iov_len = remainder; -+ } else { -+ splitvec++; -+ } -+ -+ } else { -+ splitvec = 0; -+ } -+ -+ /* Now splitvec points to the start of the bits we have to copy -+ into the wbuf */ -+ wbuf_ptr = c->wbuf; -+ -+ for ( ; splitvec < outvec; splitvec++) { -+ /* Don't copy the wbuf into itself */ -+ if (outvecs[splitvec].iov_base == c->wbuf) -+ continue; -+ memcpy(wbuf_ptr, outvecs[splitvec].iov_base, outvecs[splitvec].iov_len); -+ wbuf_ptr += outvecs[splitvec].iov_len; -+ donelen += outvecs[splitvec].iov_len; -+ } -+ c->wbuf_len = wbuf_ptr - c->wbuf; -+ -+ /* If there's a remainder in the wbuf and it's a non-GC write, -+ remember that the wbuf affects this ino */ -+alldone: -+ *retlen = donelen; -+ -+ if (c->wbuf_len && ino) -+ jffs2_wbuf_dirties_inode(c, ino); -+ -+ return 0; -+} -+ -+/* -+ * This is the entry for flash write. -+ * Check, if we work on NAND FLASH, if so build an iovec and write it via vritev -+*/ -+int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf) -+{ -+ struct iovec vecs[1]; -+ -+ if (jffs2_can_mark_obsolete(c)) -+ return c->mtd->write(c->mtd, ofs, len, retlen, buf); -+ -+ vecs[0].iov_base = (unsigned char *) buf; -+ vecs[0].iov_len = len; -+ return jffs2_flash_writev(c, vecs, 1, ofs, retlen, 0); -+} -+ -+/* -+ Handle readback from writebuffer and ECC failure return -+*/ -+int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, u_char *buf) -+{ -+ loff_t orbf = 0, owbf = 0, lwbf = 0; -+ int ret; -+ -+ /* Read flash */ -+ if (!jffs2_can_mark_obsolete(c)) { -+ ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo); -+ -+ if ( (ret == -EIO) && (*retlen == len) ) { -+ printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n", -+ len, ofs); -+ /* -+ * We have the raw data without ECC correction in the buffer, maybe -+ * we are lucky and all data or parts are correct. We check the node. -+ * If data are corrupted node check will sort it out. -+ * We keep this block, it will fail on write or erase and the we -+ * mark it bad. Or should we do that now? But we should give him a chance. -+ * Maybe we had a system crash or power loss before the ecc write or -+ * a erase was completed. -+ * So we return success. :) -+ */ -+ ret = 0; -+ } -+ } else -+ return c->mtd->read(c->mtd, ofs, len, retlen, buf); -+ -+ /* if no writebuffer available or write buffer empty, return */ -+ if (!c->wbuf_pagesize || !c->wbuf_len) -+ return ret; -+ -+ /* if we read in a different block, return */ -+ if ( (ofs & ~(c->sector_size-1)) != (c->wbuf_ofs & ~(c->sector_size-1)) ) -+ return ret; -+ -+ if (ofs >= c->wbuf_ofs) { -+ owbf = (ofs - c->wbuf_ofs); /* offset in write buffer */ -+ if (owbf > c->wbuf_len) /* is read beyond write buffer ? */ -+ return ret; -+ lwbf = c->wbuf_len - owbf; /* number of bytes to copy */ -+ if (lwbf > len) -+ lwbf = len; -+ } else { -+ orbf = (c->wbuf_ofs - ofs); /* offset in read buffer */ -+ if (orbf > len) /* is write beyond write buffer ? */ -+ return ret; -+ lwbf = len - orbf; /* number of bytes to copy */ -+ if (lwbf > c->wbuf_len) -+ lwbf = c->wbuf_len; -+ } -+ if (lwbf > 0) -+ memcpy(buf+orbf,c->wbuf+owbf,lwbf); -+ -+ return ret; -+} -+ -+/* -+ * Check, if the out of band area is empty -+ */ -+int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, int mode) -+{ -+ unsigned char *buf; -+ int ret = 0; -+ int i,len,page; -+ size_t retlen; -+ int oob_size; -+ -+ oob_size = c->mtd->oobsize; -+ -+ /* allocate a buffer for all oob data in this sector */ -+ len = 4 * oob_size; -+ buf = kmalloc(len, GFP_KERNEL); -+ if (!buf) { -+ printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n"); -+ return -ENOMEM; -+ } -+ /* -+ * if mode = 0, we scan for a total empty oob area, else we have -+ * to take care of the cleanmarker in the first page of the block -+ */ -+ ret = jffs2_flash_read_oob(c, jeb->offset, len , &retlen, buf); -+ if (ret) { -+ D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB failed %d for block at %08x\n", ret, jeb->offset)); -+ goto out; -+ } -+ -+ if (retlen < len) { -+ D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB return short read " -+ "(%zd bytes not %d) for block at %08x\n", retlen, len, jeb->offset)); -+ ret = -EIO; -+ goto out; -+ } -+ -+ /* Special check for first two pages */ -+ for (page = 0; page < 2 * oob_size; page += oob_size) { -+ /* Check for bad block marker */ -+ if (buf[page+c->badblock_pos] != 0xff) { -+ D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Bad or failed block at %08x\n",jeb->offset)); -+ /* Return 2 for bad and 3 for failed block -+ bad goes to list_bad and failed to list_erase */ -+ ret = (!page) ? 2 : 3; -+ goto out; -+ } -+ for(i = 0; i < oob_size ; i++) { -+ /* Yeah, we know about the cleanmarker. */ -+ if (mode && i >= c->fsdata_pos && -+ i < c->fsdata_pos+c->fsdata_len) -+ continue; -+ -+ if (buf[page+i] != 0xFF) { -+ D2(printk(KERN_DEBUG "Found %02x at %x in OOB for %08x\n", -+ buf[page+i], page+i, jeb->offset)); -+ ret = 1; -+ goto out; -+ } -+ } -+ /* only the first page can contain a cleanmarker !*/ -+ mode = 0; -+ } -+ -+ /* we know, we are aligned :) */ -+ for (; page < len; page += sizeof(long)) { -+ unsigned long dat = *(unsigned long *)(&buf[page]); -+ if(dat != -1) { -+ ret = 1; -+ goto out; -+ } -+ } -+ -+out: -+ kfree(buf); -+ -+ return ret; -+} -+ -+/* -+* Scan for a valid cleanmarker and for bad blocks -+* For virtual blocks (concatenated physical blocks) check the cleanmarker -+* only in the first page of the first physical block, but scan for bad blocks in all -+* physical blocks -+*/ -+int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) -+{ -+ struct jffs2_unknown_node n; -+ unsigned char buf[32]; -+ unsigned char *p; -+ int ret, i, cnt, retval = 0; -+ size_t retlen, offset; -+ int oob_size; -+ -+ offset = jeb->offset; -+ oob_size = c->mtd->oobsize; -+ -+ /* Loop through the physical blocks */ -+ for (cnt = 0; cnt < (c->sector_size / c->mtd->erasesize); cnt++) { -+ /* -+ * We read oob data from page 0 and 1 of the block. -+ * page 0 contains cleanmarker and badblock info -+ * page 1 contains failure count of this block -+ */ -+ ret = c->mtd->read_oob (c->mtd, offset, oob_size << 1, &retlen, buf); -+ -+ if (ret) { -+ D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB failed %d for block at %08x\n", ret, jeb->offset)); -+ return ret; -+ } -+ if (retlen < (oob_size << 1)) { -+ D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB return short read (%zd bytes not %d) for block at %08x\n", retlen, oob_size << 1, jeb->offset)); -+ return -EIO; -+ } -+ -+ /* Check for bad block marker */ -+ if (buf[c->badblock_pos] != 0xff) { -+ D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Bad block at %08x (has %02x %02x in badblock_pos %d\n", -+ jeb->offset, buf[c->badblock_pos], buf[c->badblock_pos + oob_size], c->badblock_pos)); -+ return 2; -+ } -+ -+ /* Check for failure counter in the second page */ -+ if (buf[c->badblock_pos + oob_size] != 0xff) { -+ D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Block marked as failed at %08x, fail count:%d\n", jeb->offset, buf[c->badblock_pos + oob_size])); -+ return 3; -+ } -+ -+ /* Check cleanmarker only on the first physical block */ -+ if (!cnt) { -+ n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK); -+ n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER); -+ n.totlen = cpu_to_je32 (8); -+ p = (unsigned char *) &n; -+ -+ for (i = 0; i < c->fsdata_len; i++) { -+ if (buf[c->fsdata_pos + i] != p[i]) { -+ retval = 1; -+ } -+ } -+ D1(if (retval == 1) { -+ printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): Cleanmarker node not detected in block at %08x\n", jeb->offset); -+ printk(KERN_WARNING "OOB at %08x was ", offset); -+ for (i=0; i < oob_size; i++) { -+ printk("%02x ", buf[i]); -+ } -+ printk("\n"); -+ }) -+ } -+ offset += c->mtd->erasesize; -+ } -+ return retval; -+} -+ -+int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) -+{ -+ struct jffs2_unknown_node n; -+ int ret; -+ size_t retlen; -+ -+ n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); -+ n.totlen = cpu_to_je32(8); -+ -+ ret = jffs2_flash_write_oob(c, jeb->offset + c->fsdata_pos, c->fsdata_len, &retlen, (unsigned char *)&n); -+ -+ if (ret) { -+ D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); -+ return ret; -+ } -+ if (retlen != c->fsdata_len) { -+ D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Short write for block at %08x: %zd not %d\n", jeb->offset, retlen, c->fsdata_len)); -+ return ret; -+ } -+ return 0; -+} -+ -+/* -+ * We try to get the failure count of this block. -+ */ -+int jffs2_nand_read_failcnt(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) { -+ -+ unsigned char buf[16]; -+ int ret; -+ size_t retlen; -+ int oob_size; -+ -+ oob_size = c->mtd->oobsize; -+ -+ ret = c->mtd->read_oob(c->mtd, jeb->offset + c->mtd->oobblock, oob_size , &retlen, buf); -+ -+ if (ret) { -+ D1(printk(KERN_WARNING "jffs2_nand_read_failcnt(): Read OOB failed %d for block at %08x\n", ret, jeb->offset)); -+ return ret; -+ } -+ -+ if (retlen < oob_size) { -+ D1(printk(KERN_WARNING "jffs2_nand_read_failcnt(): Read OOB return short read (%zd bytes not %d) for block at %08x\n", retlen, oob_size, jeb->offset)); -+ return -EIO; -+ } -+ -+ jeb->bad_count = buf[c->badblock_pos]; -+ return 0; -+} -+ -+/* -+ * On NAND we try to mark this block bad. We try to write how often -+ * the block was erased and mark it finaly bad, if the count -+ * is > MAX_ERASE_FAILURES. We read this information on mount ! -+ * jeb->bad_count contains the count before this erase. -+ * Don't care about failures. This block remains on the erase-pending -+ * or badblock list as long as nobody manipulates the flash with -+ * a bootloader or something like that. -+ */ -+ -+int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) -+{ -+ unsigned char buf = 0x0; -+ int ret; -+ size_t retlen; -+ -+ /* if the count is < max, we try to write the counter to the 2nd page oob area */ -+ if( ++jeb->bad_count < MAX_ERASE_FAILURES) { -+ buf = (unsigned char)jeb->bad_count; -+ c->badblock_pos += c->mtd->oobblock; -+ } -+ -+ ret = jffs2_flash_write_oob(c, jeb->offset + c->badblock_pos, 1, &retlen, &buf); -+ -+ if (ret) { -+ D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); -+ return ret; -+ } -+ if (retlen != 1) { -+ D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Short write for block at %08x: %zd not 1\n", jeb->offset, retlen)); -+ return ret; -+ } -+ return 0; -+} -+ -+#define JFFS2_OOB_ECCPOS0 0 -+#define JFFS2_OOB_ECCPOS1 1 -+#define JFFS2_OOB_ECCPOS2 2 -+#define JFFS2_OOB_ECCPOS3 3 -+#define JFFS2_OOB_ECCPOS4 6 -+#define JFFS2_OOB_ECCPOS5 7 -+ -+#define NAND_JFFS2_OOB8_FSDAPOS 6 -+#define NAND_JFFS2_OOB16_FSDAPOS 8 -+#define NAND_JFFS2_OOB8_FSDALEN 2 -+#define NAND_JFFS2_OOB16_FSDALEN 8 -+ -+static struct nand_oobinfo jffs2_oobinfo_swecc = { -+ .useecc = 1, -+ .eccpos = {JFFS2_OOB_ECCPOS0, JFFS2_OOB_ECCPOS1, JFFS2_OOB_ECCPOS2, -+ JFFS2_OOB_ECCPOS3, JFFS2_OOB_ECCPOS4, JFFS2_OOB_ECCPOS5} -+}; -+ -+static struct nand_oobinfo jffs2_oobinfo_docecc = { -+ .useecc = 1, -+ .eccpos = {0,1,2,3,4,5} -+}; -+ -+ -+ -+int jffs2_nand_flash_setup(struct jffs2_sb_info *c) -+{ -+ /* Cleanmarker is out-of-band, so inline size zero */ -+ c->cleanmarker_size = 0; -+ -+ /* Initialise write buffer */ -+ c->wbuf_pagesize = c->mtd->oobblock; -+ c->wbuf_ofs = 0xFFFFFFFF; -+ -+ /* FIXME: If we had a generic way of describing the hardware's -+ use of OOB area, we could perhaps make this generic too. */ -+ switch(c->mtd->ecctype) { -+ case MTD_ECC_SW: -+ D1(printk(KERN_DEBUG "JFFS2 using software ECC\n")); -+ c->oobinfo = &jffs2_oobinfo_swecc; -+ if (c->mtd->oobsize == 8) { -+ c->fsdata_pos = NAND_JFFS2_OOB8_FSDAPOS; -+ c->fsdata_len = NAND_JFFS2_OOB8_FSDALEN; -+ } else { -+ c->fsdata_pos = NAND_JFFS2_OOB16_FSDAPOS; -+ c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN; -+ } -+ c->badblock_pos = NAND_BADBLOCK_POS; -+ break; -+ -+ case MTD_ECC_RS_DiskOnChip: -+ D1(printk(KERN_DEBUG "JFFS2 using DiskOnChip hardware ECC\n")); -+ c->oobinfo = &jffs2_oobinfo_docecc; -+ c->fsdata_pos = 6; -+ c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN; -+ c->badblock_pos = 15; -+ break; -+ -+ default: -+ printk("JFFS2 doesn't yet know how to handle ECC type %d\n", -+ c->mtd->ecctype); -+ return -EINVAL; -+ } -+ -+ c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); -+ if (!c->wbuf) -+ return -ENOMEM; -+ -+#ifdef BREAKME -+ if (!brokenbuf) -+ brokenbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); -+ if (!brokenbuf) { -+ kfree(c->wbuf); -+ return -ENOMEM; -+ } -+ memset(brokenbuf, 0xdb, c->wbuf_pagesize); -+#endif -+ return 0; -+} -+ -+void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c) -+{ -+ kfree(c->wbuf); -+} -diff -Nurb linux-mips-2.4.27/fs/jffs2/write.c linux/fs/jffs2/write.c ---- linux-mips-2.4.27/fs/jffs2/write.c 2003-11-17 02:07:44.000000000 +0100 -+++ linux/fs/jffs2/write.c 2004-11-19 10:25:12.132164376 +0100 -@@ -1,154 +1,70 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in this directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #include - #include --#include -+#include -+#include -+#include - #include - #include "nodelist.h" --#include - --/* jffs2_new_inode: allocate a new inode and inocache, add it to the hash, -- fill in the raw_inode while you're at it. */ --struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri) -+ -+int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri) - { -- struct inode *inode; -- struct super_block *sb = dir_i->i_sb; - struct jffs2_inode_cache *ic; -- struct jffs2_sb_info *c; -- struct jffs2_inode_info *f; -- -- D1(printk(KERN_DEBUG "jffs2_new_inode(): dir_i %ld, mode 0x%x\n", dir_i->i_ino, mode)); -- -- c = JFFS2_SB_INFO(sb); -- memset(ri, 0, sizeof(*ri)); - - ic = jffs2_alloc_inode_cache(); - if (!ic) { -- return ERR_PTR(-ENOMEM); -+ return -ENOMEM; - } -- memset(ic, 0, sizeof(*ic)); -- -- inode = new_inode(sb); - -- if (!inode) { -- jffs2_free_inode_cache(ic); -- return ERR_PTR(-ENOMEM); -- } -- -- /* Alloc jffs2_inode_info when that's split in 2.5 */ -+ memset(ic, 0, sizeof(*ic)); - -- f = JFFS2_INODE_INFO(inode); -- memset(f, 0, sizeof(*f)); - init_MUTEX_LOCKED(&f->sem); - f->inocache = ic; -- inode->i_nlink = f->inocache->nlink = 1; -+ f->inocache->nlink = 1; - f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; -- f->inocache->ino = ri->ino = inode->i_ino = ++c->highest_ino; -- D1(printk(KERN_DEBUG "jffs2_new_inode(): Assigned ino# %d\n", ri->ino)); -- jffs2_add_ino_cache(c, f->inocache); -+ f->inocache->ino = ++c->highest_ino; -+ f->inocache->state = INO_STATE_PRESENT; - -- ri->magic = JFFS2_MAGIC_BITMASK; -- ri->nodetype = JFFS2_NODETYPE_INODE; -- ri->totlen = PAD(sizeof(*ri)); -- ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); -- ri->mode = mode; -- f->highest_version = ri->version = 1; -- ri->uid = current->fsuid; -- if (dir_i->i_mode & S_ISGID) { -- ri->gid = dir_i->i_gid; -- if (S_ISDIR(mode)) -- ri->mode |= S_ISGID; -- } else { -- ri->gid = current->fsgid; -- } -- inode->i_mode = ri->mode; -- inode->i_gid = ri->gid; -- inode->i_uid = ri->uid; -- inode->i_atime = inode->i_ctime = inode->i_mtime = -- ri->atime = ri->mtime = ri->ctime = CURRENT_TIME; -- inode->i_blksize = PAGE_SIZE; -- inode->i_blocks = 0; -- inode->i_size = 0; -+ ri->ino = cpu_to_je32(f->inocache->ino); - -- insert_inode_hash(inode); -+ D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino)); -+ jffs2_add_ino_cache(c, f->inocache); - -- return inode; --} -+ ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -+ ri->totlen = cpu_to_je32(PAD(sizeof(*ri))); -+ ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); -+ ri->mode = cpu_to_jemode(mode); - --/* This ought to be in core MTD code. All registered MTD devices -- without writev should have this put in place. Bug the MTD -- maintainer */ --static int mtd_fake_writev(struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen) --{ -- unsigned long i; -- size_t totlen = 0, thislen; -- int ret = 0; -+ f->highest_version = 1; -+ ri->version = cpu_to_je32(f->highest_version); - -- for (i=0; iwrite(mtd, to, vecs[i].iov_len, &thislen, vecs[i].iov_base); -- totlen += thislen; -- if (ret || thislen != vecs[i].iov_len) -- break; -- to += vecs[i].iov_len; -- } -- if (retlen) -- *retlen = totlen; -- return ret; --} -- -- --static inline int mtd_writev(struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen) --{ -- if (mtd->writev) -- return mtd->writev(mtd,vecs,count,to,retlen); -- else -- return mtd_fake_writev(mtd, vecs, count, to, retlen); -+ return 0; - } - --static void writecheck(struct mtd_info *mtd, __u32 ofs) -+#if CONFIG_JFFS2_FS_DEBUG > 0 -+static void writecheck(struct jffs2_sb_info *c, uint32_t ofs) - { - unsigned char buf[16]; -- ssize_t retlen; -+ size_t retlen; - int ret, i; - -- ret = mtd->read(mtd, ofs, 16, &retlen, buf); -- if (ret && retlen != 16) { -- D1(printk(KERN_DEBUG "read failed or short in writecheck(). ret %d, retlen %d\n", ret, retlen)); -+ ret = jffs2_flash_read(c, ofs, 16, &retlen, buf); -+ if (ret || (retlen != 16)) { -+ D1(printk(KERN_DEBUG "read failed or short in writecheck(). ret %d, retlen %zd\n", ret, retlen)); - return; - } - ret = 0; -@@ -157,32 +73,31 @@ - ret = 1; - } - if (ret) { -- printk(KERN_WARNING "ARGH. About to write node to 0x%08x on flash, but there's data already there:\n", ofs); -+ printk(KERN_WARNING "ARGH. About to write node to 0x%08x on flash, but there are data already there:\n", ofs); - printk(KERN_WARNING "0x%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - ofs, - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], - buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]); - } - } -- -- -+#endif - - - /* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, - write it to the flash, link it into the existing inode/fragment list */ - --struct jffs2_full_dnode *jffs2_write_dnode(struct inode *inode, struct jffs2_raw_inode *ri, const unsigned char *data, __u32 datalen, __u32 flash_ofs, __u32 *writelen) -+struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode) - - { -- struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_raw_node_ref *raw; - struct jffs2_full_dnode *fn; -- ssize_t retlen; -+ size_t retlen; - struct iovec vecs[2]; - int ret; -+ int retried = 0; -+ unsigned long cnt = 2; - -- D1(if(ri->hdr_crc != crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)) { -+ D1(if(je32_to_cpu(ri->hdr_crc) != crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)) { - printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dnode()\n"); - BUG(); - } -@@ -192,10 +107,10 @@ - vecs[1].iov_base = (unsigned char *)data; - vecs[1].iov_len = datalen; - -- writecheck(c->mtd, flash_ofs); -+ D1(writecheck(c, flash_ofs)); - -- if (ri->totlen != sizeof(*ri) + datalen) { -- printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08x) + datalen (0x%08x)\n", ri->totlen, sizeof(*ri), datalen); -+ if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { -+ printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); - } - raw = jffs2_alloc_raw_node_ref(); - if (!raw) -@@ -206,19 +121,28 @@ - jffs2_free_raw_node_ref(raw); - return ERR_PTR(-ENOMEM); - } -- raw->flash_offset = flash_ofs; -- raw->totlen = PAD(ri->totlen); -- raw->next_phys = NULL; - -- fn->ofs = ri->offset; -- fn->size = ri->dsize; -+ fn->ofs = je32_to_cpu(ri->offset); -+ fn->size = je32_to_cpu(ri->dsize); - fn->frags = 0; -+ -+ /* check number of valid vecs */ -+ if (!datalen || !data) -+ cnt = 1; -+ retry: - fn->raw = raw; - -- ret = mtd_writev(c->mtd, vecs, 2, flash_ofs, &retlen); -+ raw->flash_offset = flash_ofs; -+ raw->__totlen = PAD(sizeof(*ri)+datalen); -+ raw->next_phys = NULL; -+ -+ ret = jffs2_flash_writev(c, vecs, cnt, flash_ofs, &retlen, -+ (alloc_mode==ALLOC_GC)?0:f->inocache->ino); -+ - if (ret || (retlen != sizeof(*ri) + datalen)) { -- printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %d\n", -+ printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", - sizeof(*ri)+datalen, flash_ofs, ret, retlen); -+ - /* Mark the space as dirtied */ - if (retlen) { - /* Doesn't belong to any inode */ -@@ -229,48 +153,96 @@ - seem corrupted, in which case the scan would skip over - any node we write before the original intended end of - this node */ -- jffs2_add_physical_node_ref(c, raw, sizeof(*ri)+datalen, 1); -+ raw->flash_offset |= REF_OBSOLETE; -+ jffs2_add_physical_node_ref(c, raw); - jffs2_mark_node_obsolete(c, raw); - } else { - printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); - jffs2_free_raw_node_ref(raw); - } -+ if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) { -+ /* Try to reallocate space and retry */ -+ uint32_t dummy; -+ struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; -+ -+ retried = 1; -+ -+ D1(printk(KERN_DEBUG "Retrying failed write.\n")); -+ -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ if (alloc_mode == ALLOC_GC) { -+ ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, &dummy); -+ } else { -+ /* Locking pain */ -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ -+ ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, &dummy, alloc_mode); -+ down(&f->sem); -+ } -+ -+ if (!ret) { -+ D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); -+ -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); - -+ goto retry; -+ } -+ D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); -+ jffs2_free_raw_node_ref(raw); -+ } - /* Release the full_dnode which is now useless, and return */ - jffs2_free_full_dnode(fn); -- if (writelen) -- *writelen = retlen; - return ERR_PTR(ret?ret:-EIO); - } - /* Mark the space used */ -- jffs2_add_physical_node_ref(c, raw, retlen, 0); -+ /* If node covers at least a whole page, or if it starts at the -+ beginning of a page and runs to the end of the file, or if -+ it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. -+ */ -+ if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || -+ ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && -+ (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) { -+ raw->flash_offset |= REF_PRISTINE; -+ } else { -+ raw->flash_offset |= REF_NORMAL; -+ } -+ jffs2_add_physical_node_ref(c, raw); - - /* Link into per-inode list */ - raw->next_in_ino = f->inocache->nodes; - f->inocache->nodes = raw; - -- D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", flash_ofs, ri->dsize, ri->csize, ri->node_crc, ri->data_crc, ri->totlen)); -- if (writelen) -- *writelen = retlen; -+ D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", -+ flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), -+ je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), -+ je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); -+ -+ if (retried) { -+ ACCT_SANITY_CHECK(c,NULL); -+ } - -- f->inocache->nodes = raw; - return fn; - } - --struct jffs2_full_dirent *jffs2_write_dirent(struct inode *inode, struct jffs2_raw_dirent *rd, const unsigned char *name, __u32 namelen, __u32 flash_ofs, __u32 *writelen) -+struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode) - { -- struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); -- struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_raw_node_ref *raw; - struct jffs2_full_dirent *fd; -- ssize_t retlen; -+ size_t retlen; - struct iovec vecs[2]; -+ int retried = 0; - int ret; - -- D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", rd->pino, name, name, rd->ino, rd->name_crc)); -- writecheck(c->mtd, flash_ofs); -+ D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", -+ je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino), -+ je32_to_cpu(rd->name_crc))); -+ D1(writecheck(c, flash_ofs)); - -- D1(if(rd->hdr_crc != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { -+ D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { - printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); - BUG(); - } -@@ -291,44 +263,414 @@ - jffs2_free_raw_node_ref(raw); - return ERR_PTR(-ENOMEM); - } -- raw->flash_offset = flash_ofs; -- raw->totlen = PAD(rd->totlen); -- raw->next_in_ino = f->inocache->nodes; -- f->inocache->nodes = raw; -- raw->next_phys = NULL; - -- fd->version = rd->version; -- fd->ino = rd->ino; -+ fd->version = je32_to_cpu(rd->version); -+ fd->ino = je32_to_cpu(rd->ino); - fd->nhash = full_name_hash(name, strlen(name)); - fd->type = rd->type; - memcpy(fd->name, name, namelen); - fd->name[namelen]=0; -+ -+ retry: - fd->raw = raw; - -- ret = mtd_writev(c->mtd, vecs, 2, flash_ofs, &retlen); -+ raw->flash_offset = flash_ofs; -+ raw->__totlen = PAD(sizeof(*rd)+namelen); -+ raw->next_phys = NULL; -+ -+ ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen, -+ (alloc_mode==ALLOC_GC)?0:je32_to_cpu(rd->pino)); - if (ret || (retlen != sizeof(*rd) + namelen)) { -- printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %d\n", -+ printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", - sizeof(*rd)+namelen, flash_ofs, ret, retlen); - /* Mark the space as dirtied */ - if (retlen) { -- jffs2_add_physical_node_ref(c, raw, sizeof(*rd)+namelen, 1); -+ raw->next_in_ino = NULL; -+ raw->flash_offset |= REF_OBSOLETE; -+ jffs2_add_physical_node_ref(c, raw); - jffs2_mark_node_obsolete(c, raw); - } else { - printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); - jffs2_free_raw_node_ref(raw); - } -+ if (!retried && (raw = jffs2_alloc_raw_node_ref())) { -+ /* Try to reallocate space and retry */ -+ uint32_t dummy; -+ struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; -+ -+ retried = 1; -+ -+ D1(printk(KERN_DEBUG "Retrying failed write.\n")); -+ -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ -+ if (alloc_mode == ALLOC_GC) { -+ ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, &dummy); -+ } else { -+ /* Locking pain */ -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ -+ ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, &dummy, alloc_mode); -+ down(&f->sem); -+ } - -+ if (!ret) { -+ D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); -+ ACCT_SANITY_CHECK(c,jeb); -+ D1(ACCT_PARANOIA_CHECK(jeb)); -+ goto retry; -+ } -+ D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); -+ jffs2_free_raw_node_ref(raw); -+ } - /* Release the full_dnode which is now useless, and return */ - jffs2_free_full_dirent(fd); -- if (writelen) -- *writelen = retlen; - return ERR_PTR(ret?ret:-EIO); - } - /* Mark the space used */ -- jffs2_add_physical_node_ref(c, raw, retlen, 0); -- if (writelen) -- *writelen = retlen; -+ raw->flash_offset |= REF_PRISTINE; -+ jffs2_add_physical_node_ref(c, raw); - -+ raw->next_in_ino = f->inocache->nodes; - f->inocache->nodes = raw; -+ -+ if (retried) { -+ ACCT_SANITY_CHECK(c,NULL); -+ } -+ - return fd; - } -+ -+/* The OS-specific code fills in the metadata in the jffs2_raw_inode for us, so that -+ we don't have to go digging in struct inode or its equivalent. It should set: -+ mode, uid, gid, (starting)isize, atime, ctime, mtime */ -+int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, -+ struct jffs2_raw_inode *ri, unsigned char *buf, -+ uint32_t offset, uint32_t writelen, uint32_t *retlen) -+{ -+ int ret = 0; -+ uint32_t writtenlen = 0; -+ -+ D1(printk(KERN_DEBUG "jffs2_write_inode_range(): Ino #%u, ofs 0x%x, len 0x%x\n", -+ f->inocache->ino, offset, writelen)); -+ -+ while(writelen) { -+ struct jffs2_full_dnode *fn; -+ unsigned char *comprbuf = NULL; -+ unsigned char comprtype = JFFS2_COMPR_NONE; -+ uint32_t phys_ofs, alloclen; -+ uint32_t datalen, cdatalen; -+ int retried = 0; -+ -+ retry: -+ D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset)); -+ -+ ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen, ALLOC_NORMAL); -+ if (ret) { -+ D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); -+ break; -+ } -+ down(&f->sem); -+ datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1))); -+ cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen); -+ -+ comprtype = jffs2_compress(buf, &comprbuf, &datalen, &cdatalen); -+ -+ ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -+ ri->totlen = cpu_to_je32(sizeof(*ri) + cdatalen); -+ ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); -+ -+ ri->ino = cpu_to_je32(f->inocache->ino); -+ ri->version = cpu_to_je32(++f->highest_version); -+ ri->isize = cpu_to_je32(max(je32_to_cpu(ri->isize), offset + datalen)); -+ ri->offset = cpu_to_je32(offset); -+ ri->csize = cpu_to_je32(cdatalen); -+ ri->dsize = cpu_to_je32(datalen); -+ ri->compr = comprtype; -+ ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); -+ ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); -+ -+ fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, phys_ofs, ALLOC_NORETRY); -+ -+ jffs2_free_comprbuf(comprbuf, buf); -+ -+ if (IS_ERR(fn)) { -+ ret = PTR_ERR(fn); -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ if (!retried) { -+ /* Write error to be retried */ -+ retried = 1; -+ D1(printk(KERN_DEBUG "Retrying node write in jffs2_write_inode_range()\n")); -+ goto retry; -+ } -+ break; -+ } -+ ret = jffs2_add_full_dnode_to_inode(c, f, fn); -+ if (f->metadata) { -+ jffs2_mark_node_obsolete(c, f->metadata->raw); -+ jffs2_free_full_dnode(f->metadata); -+ f->metadata = NULL; -+ } -+ if (ret) { -+ /* Eep */ -+ D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in commit_write, returned %d\n", ret)); -+ jffs2_mark_node_obsolete(c, fn->raw); -+ jffs2_free_full_dnode(fn); -+ -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ break; -+ } -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ if (!datalen) { -+ printk(KERN_WARNING "Eep. We didn't actually write any data in jffs2_write_inode_range()\n"); -+ ret = -EIO; -+ break; -+ } -+ D1(printk(KERN_DEBUG "increasing writtenlen by %d\n", datalen)); -+ writtenlen += datalen; -+ offset += datalen; -+ writelen -= datalen; -+ buf += datalen; -+ } -+ *retlen = writtenlen; -+ return ret; -+} -+ -+int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen) -+{ -+ struct jffs2_raw_dirent *rd; -+ struct jffs2_full_dnode *fn; -+ struct jffs2_full_dirent *fd; -+ uint32_t alloclen, phys_ofs; -+ int ret; -+ -+ /* Try to reserve enough space for both node and dirent. -+ * Just the node will do for now, though -+ */ -+ ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); -+ D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); -+ if (ret) { -+ up(&f->sem); -+ return ret; -+ } -+ -+ ri->data_crc = cpu_to_je32(0); -+ ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); -+ -+ fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); -+ -+ D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n", -+ jemode_to_cpu(ri->mode))); -+ -+ if (IS_ERR(fn)) { -+ D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n")); -+ /* Eeek. Wave bye bye */ -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ return PTR_ERR(fn); -+ } -+ /* No data here. Only a metadata node, which will be -+ obsoleted by the first data write -+ */ -+ f->metadata = fn; -+ -+ up(&f->sem); -+ jffs2_complete_reservation(c); -+ ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); -+ -+ if (ret) { -+ /* Eep. */ -+ D1(printk(KERN_DEBUG "jffs2_reserve_space() for dirent failed\n")); -+ return ret; -+ } -+ -+ rd = jffs2_alloc_raw_dirent(); -+ if (!rd) { -+ /* Argh. Now we treat it like a normal delete */ -+ jffs2_complete_reservation(c); -+ return -ENOMEM; -+ } -+ -+ down(&dir_f->sem); -+ -+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); -+ rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); -+ rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); -+ -+ rd->pino = cpu_to_je32(dir_f->inocache->ino); -+ rd->version = cpu_to_je32(++dir_f->highest_version); -+ rd->ino = ri->ino; -+ rd->mctime = ri->ctime; -+ rd->nsize = namelen; -+ rd->type = DT_REG; -+ rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); -+ rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); -+ -+ fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); -+ -+ jffs2_free_raw_dirent(rd); -+ -+ if (IS_ERR(fd)) { -+ /* dirent failed to write. Delete the inode normally -+ as if it were the final unlink() */ -+ jffs2_complete_reservation(c); -+ up(&dir_f->sem); -+ return PTR_ERR(fd); -+ } -+ -+ /* Link the fd into the inode's list, obsoleting an old -+ one if necessary. */ -+ jffs2_add_fd_to_list(c, fd, &dir_f->dents); -+ -+ jffs2_complete_reservation(c); -+ up(&dir_f->sem); -+ -+ return 0; -+} -+ -+ -+int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, -+ const char *name, int namelen, struct jffs2_inode_info *dead_f) -+{ -+ struct jffs2_raw_dirent *rd; -+ struct jffs2_full_dirent *fd; -+ uint32_t alloclen, phys_ofs; -+ int ret; -+ -+ rd = jffs2_alloc_raw_dirent(); -+ if (!rd) -+ return -ENOMEM; -+ -+ ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_DELETION); -+ if (ret) { -+ jffs2_free_raw_dirent(rd); -+ return ret; -+ } -+ -+ down(&dir_f->sem); -+ -+ /* Build a deletion node */ -+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); -+ rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); -+ rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); -+ -+ rd->pino = cpu_to_je32(dir_f->inocache->ino); -+ rd->version = cpu_to_je32(++dir_f->highest_version); -+ rd->ino = cpu_to_je32(0); -+ rd->mctime = cpu_to_je32(get_seconds()); -+ rd->nsize = namelen; -+ rd->type = DT_UNKNOWN; -+ rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); -+ rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); -+ -+ fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION); -+ -+ jffs2_free_raw_dirent(rd); -+ -+ if (IS_ERR(fd)) { -+ jffs2_complete_reservation(c); -+ up(&dir_f->sem); -+ return PTR_ERR(fd); -+ } -+ -+ /* File it. This will mark the old one obsolete. */ -+ jffs2_add_fd_to_list(c, fd, &dir_f->dents); -+ -+ up(&dir_f->sem); -+ -+ /* dead_f is NULL if this was a rename not a real unlink */ -+ /* Also catch the !f->inocache case, where there was a dirent -+ pointing to an inode which didn't exist. */ -+ if (dead_f && dead_f->inocache) { -+ -+ down(&dead_f->sem); -+ -+ while (dead_f->dents) { -+ /* There can be only deleted ones */ -+ fd = dead_f->dents; -+ -+ dead_f->dents = fd->next; -+ -+ if (fd->ino) { -+ printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n", -+ dead_f->inocache->ino, fd->name, fd->ino); -+ } else { -+ D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n", fd->name, dead_f->inocache->ino)); -+ } -+ jffs2_mark_node_obsolete(c, fd->raw); -+ jffs2_free_full_dirent(fd); -+ } -+ -+ dead_f->inocache->nlink--; -+ /* NB: Caller must set inode nlink if appropriate */ -+ up(&dead_f->sem); -+ } -+ -+ jffs2_complete_reservation(c); -+ -+ return 0; -+} -+ -+ -+int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen) -+{ -+ struct jffs2_raw_dirent *rd; -+ struct jffs2_full_dirent *fd; -+ uint32_t alloclen, phys_ofs; -+ int ret; -+ -+ rd = jffs2_alloc_raw_dirent(); -+ if (!rd) -+ return -ENOMEM; -+ -+ ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); -+ if (ret) { -+ jffs2_free_raw_dirent(rd); -+ return ret; -+ } -+ -+ down(&dir_f->sem); -+ -+ /* Build a deletion node */ -+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); -+ rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); -+ rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); -+ -+ rd->pino = cpu_to_je32(dir_f->inocache->ino); -+ rd->version = cpu_to_je32(++dir_f->highest_version); -+ rd->ino = cpu_to_je32(ino); -+ rd->mctime = cpu_to_je32(get_seconds()); -+ rd->nsize = namelen; -+ -+ rd->type = type; -+ -+ rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); -+ rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); -+ -+ fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); -+ -+ jffs2_free_raw_dirent(rd); -+ -+ if (IS_ERR(fd)) { -+ jffs2_complete_reservation(c); -+ up(&dir_f->sem); -+ return PTR_ERR(fd); -+ } -+ -+ /* File it. This will mark the old one obsolete. */ -+ jffs2_add_fd_to_list(c, fd, &dir_f->dents); -+ -+ jffs2_complete_reservation(c); -+ up(&dir_f->sem); -+ -+ return 0; -+} -diff -Nurb linux-mips-2.4.27/fs/jffs2/writev.c linux/fs/jffs2/writev.c ---- linux-mips-2.4.27/fs/jffs2/writev.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/jffs2/writev.c 2004-11-19 10:25:12.134164072 +0100 -@@ -0,0 +1,50 @@ -+/* -+ * JFFS2 -- Journalling Flash File System, Version 2. -+ * -+ * Copyright (C) 2001, 2002 Red Hat, Inc. -+ * -+ * Created by David Woodhouse -+ * -+ * For licensing information, see the file 'LICENCE' in this directory. -+ * -+ * $Id$ -+ * -+ */ -+ -+#include -+#include -+#include "nodelist.h" -+ -+/* This ought to be in core MTD code. All registered MTD devices -+ without writev should have this put in place. Bug the MTD -+ maintainer */ -+static inline int mtd_fake_writev(struct mtd_info *mtd, const struct iovec *vecs, -+ unsigned long count, loff_t to, size_t *retlen) -+{ -+ unsigned long i; -+ size_t totlen = 0, thislen; -+ int ret = 0; -+ -+ for (i=0; iwrite(mtd, to, vecs[i].iov_len, &thislen, vecs[i].iov_base); -+ totlen += thislen; -+ if (ret || thislen != vecs[i].iov_len) -+ break; -+ to += vecs[i].iov_len; -+ } -+ if (retlen) -+ *retlen = totlen; -+ return ret; -+} -+ -+int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs, -+ unsigned long count, loff_t to, size_t *retlen) -+{ -+ if (c->mtd->writev) -+ return c->mtd->writev(c->mtd, vecs, count, to, retlen); -+ else -+ return mtd_fake_writev(c->mtd, vecs, count, to, retlen); -+} -+ -diff -Nurb linux-mips-2.4.27/include/linux/jffs2.h linux/include/linux/jffs2.h ---- linux-mips-2.4.27/include/linux/jffs2.h 2002-06-27 00:36:46.000000000 +0200 -+++ linux/include/linux/jffs2.h 2004-11-19 10:25:12.139163312 +0100 -@@ -1,50 +1,30 @@ - /* - * JFFS2 -- Journalling Flash File System, Version 2. - * -- * Copyright (C) 2001 Red Hat, Inc. -+ * Copyright (C) 2001-2003 Red Hat, Inc. - * -- * Created by David Woodhouse -+ * Created by David Woodhouse - * -- * The original JFFS, from which the design for JFFS2 was derived, -- * was designed and implemented by Axis Communications AB. -+ * For licensing information, see the file 'LICENCE' in the -+ * jffs2 directory. - * -- * The contents of this file are subject to the Red Hat eCos Public -- * License Version 1.1 (the "Licence"); you may not use this file -- * except in compliance with the Licence. You may obtain a copy of -- * the Licence at http://www.redhat.com/ -- * -- * Software distributed under the Licence is distributed on an "AS IS" -- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -- * See the Licence for the specific language governing rights and -- * limitations under the Licence. -- * -- * The Original Code is JFFS2 - Journalling Flash File System, version 2 -- * -- * Alternatively, the contents of this file may be used under the -- * terms of the GNU General Public License version 2 (the "GPL"), in -- * which case the provisions of the GPL are applicable instead of the -- * above. If you wish to allow the use of your version of this file -- * only under the terms of the GPL and not to allow others to use your -- * version of this file under the RHEPL, indicate your decision by -- * deleting the provisions above and replace them with the notice and -- * other provisions required by the GPL. If you do not delete the -- * provisions above, a recipient may use your version of this file -- * under either the RHEPL or the GPL. -- * -- * $Id$ -+ * $Id$ - * - */ - - #ifndef __LINUX_JFFS2_H__ - #define __LINUX_JFFS2_H__ - --#include -+/* You must include something which defines the C99 uintXX_t types. -+ We don't do it from here because this file is used in too many -+ different environments. */ -+ - #define JFFS2_SUPER_MAGIC 0x72b6 - - /* Values we may expect to find in the 'magic' field */ - #define JFFS2_OLD_MAGIC_BITMASK 0x1984 - #define JFFS2_MAGIC_BITMASK 0x1985 --#define KSAMTIB_CIGAM_2SFFJ 0x5981 /* For detecting wrong-endian fs */ -+#define KSAMTIB_CIGAM_2SFFJ 0x8519 /* For detecting wrong-endian fs */ - #define JFFS2_EMPTY_BITMASK 0xffff - #define JFFS2_DIRTY_BITMASK 0x0000 - -@@ -78,16 +58,12 @@ - #define JFFS2_NODETYPE_DIRENT (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 1) - #define JFFS2_NODETYPE_INODE (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 2) - #define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) -+#define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4) - - // Maybe later... - //#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) - //#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4) - --/* Same as the non_ECC versions, but with extra space for real -- * ECC instead of just the checksum. For use on NAND flash -- */ --//#define JFFS2_NODETYPE_DIRENT_ECC (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 5) --//#define JFFS2_NODETYPE_INODE_ECC (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 6) - - #define JFFS2_INO_FLAG_PREREAD 1 /* Do read_inode() for this one at - mount time, don't wait for it to -@@ -96,31 +72,79 @@ - compression type */ - - -+/* These can go once we've made sure we've caught all uses without -+ byteswapping */ -+ -+typedef struct { -+ uint32_t v32; -+} __attribute__((packed)) jint32_t; -+ -+typedef struct { -+ uint32_t m; -+} __attribute__((packed)) jmode_t; -+ -+typedef struct { -+ uint16_t v16; -+} __attribute__((packed)) jint16_t; -+ -+#define JFFS2_NATIVE_ENDIAN -+ -+/* Note we handle mode bits conversion from JFFS2 (i.e. Linux) to/from -+ whatever OS we're actually running on here too. */ -+ -+#if defined(JFFS2_NATIVE_ENDIAN) -+#define cpu_to_je16(x) ((jint16_t){x}) -+#define cpu_to_je32(x) ((jint32_t){x}) -+#define cpu_to_jemode(x) ((jmode_t){os_to_jffs2_mode(x)}) -+ -+#define je16_to_cpu(x) ((x).v16) -+#define je32_to_cpu(x) ((x).v32) -+#define jemode_to_cpu(x) (jffs2_to_os_mode((x).m)) -+#elif defined(JFFS2_BIG_ENDIAN) -+#define cpu_to_je16(x) ((jint16_t){cpu_to_be16(x)}) -+#define cpu_to_je32(x) ((jint32_t){cpu_to_be32(x)}) -+#define cpu_to_jemode(x) ((jmode_t){cpu_to_be32(os_to_jffs2_mode(x))}) -+ -+#define je16_to_cpu(x) (be16_to_cpu(x.v16)) -+#define je32_to_cpu(x) (be32_to_cpu(x.v32)) -+#define jemode_to_cpu(x) (be32_to_cpu(jffs2_to_os_mode((x).m))) -+#elif defined(JFFS2_LITTLE_ENDIAN) -+#define cpu_to_je16(x) ((jint16_t){cpu_to_le16(x)}) -+#define cpu_to_je32(x) ((jint32_t){cpu_to_le32(x)}) -+#define cpu_to_jemode(x) ((jmode_t){cpu_to_le32(os_to_jffs2_mode(x))}) -+ -+#define je16_to_cpu(x) (le16_to_cpu(x.v16)) -+#define je32_to_cpu(x) (le32_to_cpu(x.v32)) -+#define jemode_to_cpu(x) (le32_to_cpu(jffs2_to_os_mode((x).m))) -+#else -+#error wibble -+#endif -+ - struct jffs2_unknown_node - { - /* All start like this */ -- __u16 magic; -- __u16 nodetype; -- __u32 totlen; /* So we can skip over nodes we don't grok */ -- __u32 hdr_crc; -+ jint16_t magic; -+ jint16_t nodetype; -+ jint32_t totlen; /* So we can skip over nodes we don't grok */ -+ jint32_t hdr_crc; - } __attribute__((packed)); - - struct jffs2_raw_dirent - { -- __u16 magic; -- __u16 nodetype; /* == JFFS_NODETYPE_DIRENT */ -- __u32 totlen; -- __u32 hdr_crc; -- __u32 pino; -- __u32 version; -- __u32 ino; /* == zero for unlink */ -- __u32 mctime; -- __u8 nsize; -- __u8 type; -- __u8 unused[2]; -- __u32 node_crc; -- __u32 name_crc; -- __u8 name[0]; -+ jint16_t magic; -+ jint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ -+ jint32_t totlen; -+ jint32_t hdr_crc; -+ jint32_t pino; -+ jint32_t version; -+ jint32_t ino; /* == zero for unlink */ -+ jint32_t mctime; -+ uint8_t nsize; -+ uint8_t type; -+ uint8_t unused[2]; -+ jint32_t node_crc; -+ jint32_t name_crc; -+ uint8_t name[0]; - } __attribute__((packed)); - - /* The JFFS2 raw inode structure: Used for storage on physical media. */ -@@ -131,28 +155,28 @@ - */ - struct jffs2_raw_inode - { -- __u16 magic; /* A constant magic number. */ -- __u16 nodetype; /* == JFFS_NODETYPE_INODE */ -- __u32 totlen; /* Total length of this node (inc data, etc.) */ -- __u32 hdr_crc; -- __u32 ino; /* Inode number. */ -- __u32 version; /* Version number. */ -- __u32 mode; /* The file's type or mode. */ -- __u16 uid; /* The file's owner. */ -- __u16 gid; /* The file's group. */ -- __u32 isize; /* Total resultant size of this inode (used for truncations) */ -- __u32 atime; /* Last access time. */ -- __u32 mtime; /* Last modification time. */ -- __u32 ctime; /* Change time. */ -- __u32 offset; /* Where to begin to write. */ -- __u32 csize; /* (Compressed) data size */ -- __u32 dsize; /* Size of the node's data. (after decompression) */ -- __u8 compr; /* Compression algorithm used */ -- __u8 usercompr; /* Compression algorithm requested by the user */ -- __u16 flags; /* See JFFS2_INO_FLAG_* */ -- __u32 data_crc; /* CRC for the (compressed) data. */ -- __u32 node_crc; /* CRC for the raw inode (excluding data) */ --// __u8 data[dsize]; -+ jint16_t magic; /* A constant magic number. */ -+ jint16_t nodetype; /* == JFFS_NODETYPE_INODE */ -+ jint32_t totlen; /* Total length of this node (inc data, etc.) */ -+ jint32_t hdr_crc; -+ jint32_t ino; /* Inode number. */ -+ jint32_t version; /* Version number. */ -+ jmode_t mode; /* The file's type or mode. */ -+ jint16_t uid; /* The file's owner. */ -+ jint16_t gid; /* The file's group. */ -+ jint32_t isize; /* Total resultant size of this inode (used for truncations) */ -+ jint32_t atime; /* Last access time. */ -+ jint32_t mtime; /* Last modification time. */ -+ jint32_t ctime; /* Change time. */ -+ jint32_t offset; /* Where to begin to write. */ -+ jint32_t csize; /* (Compressed) data size */ -+ jint32_t dsize; /* Size of the node's data. (after decompression) */ -+ uint8_t compr; /* Compression algorithm used */ -+ uint8_t usercompr; /* Compression algorithm requested by the user */ -+ jint16_t flags; /* See JFFS2_INO_FLAG_* */ -+ jint32_t data_crc; /* CRC for the (compressed) data. */ -+ jint32_t node_crc; /* CRC for the raw inode (excluding data) */ -+ uint8_t data[0]; - } __attribute__((packed)); - - union jffs2_node_union { -diff -Nurb linux-mips-2.4.27/include/linux/jffs2_fs_i.h linux/include/linux/jffs2_fs_i.h ---- linux-mips-2.4.27/include/linux/jffs2_fs_i.h 2001-10-19 03:25:03.000000000 +0200 -+++ linux/include/linux/jffs2_fs_i.h 2004-11-19 10:25:12.141163008 +0100 -@@ -1,22 +1,12 @@ --/* $Id$ */ -+/* $Id$ */ - - #ifndef _JFFS2_FS_I - #define _JFFS2_FS_I - --/* Include the pipe_inode_info at the beginning so that we can still -- use the storage space in the inode when we have a pipe inode. -- This sucks. --*/ -- --#undef THISSUCKS /* Only for 2.2 */ --#ifdef THISSUCKS --#include --#endif -+#include -+#include - - struct jffs2_inode_info { --#ifdef THISSUCKS -- struct pipe_inode_info pipecrap; --#endif - /* We need an internal semaphore similar to inode->i_sem. - Unfortunately, we can't used the existing one, because - either the GC would deadlock, or we'd have to release it -@@ -26,10 +16,10 @@ - struct semaphore sem; - - /* The highest (datanode) version number used for this ino */ -- __u32 highest_version; -+ uint32_t highest_version; - - /* List of data fragments which make up the file */ -- struct jffs2_node_frag *fraglist; -+ struct rb_root fragtree; - - /* There may be one datanode which isn't referenced by any of the - above fragments, if it contains a metadata update but no actual -@@ -44,19 +34,13 @@ - /* Some stuff we just have to keep in-core at all times, for each inode. */ - struct jffs2_inode_cache *inocache; - -- /* Keep a pointer to the last physical node in the list. We don't -- use the doubly-linked lists because we don't want to increase -- the memory usage that much. This is simpler */ -- // struct jffs2_raw_node_ref *lastnode; -- __u16 flags; -- __u8 usercompr; --}; -- --#ifdef JFFS2_OUT_OF_KERNEL --#define JFFS2_INODE_INFO(i) ((struct jffs2_inode_info *) &(i)->u) --#else --#define JFFS2_INODE_INFO(i) (&i->u.jffs2_i) -+ uint16_t flags; -+ uint8_t usercompr; -+#if !defined (__ECOS) -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2) -+ struct inode vfs_inode; - #endif -+#endif -+}; - - #endif /* _JFFS2_FS_I */ -- -diff -Nurb linux-mips-2.4.27/include/linux/jffs2_fs_sb.h linux/include/linux/jffs2_fs_sb.h ---- linux-mips-2.4.27/include/linux/jffs2_fs_sb.h 2002-06-27 00:36:46.000000000 +0200 -+++ linux/include/linux/jffs2_fs_sb.h 2004-11-19 10:25:12.142162856 +0100 -@@ -1,19 +1,22 @@ --/* $Id$ */ -+/* $Id$ */ - - #ifndef _JFFS2_FS_SB - #define _JFFS2_FS_SB - - #include - #include -+#include - #include - #include -+#include -+#include - #include - --#define INOCACHE_HASHSIZE 1 -- - #define JFFS2_SB_FLAG_RO 1 - #define JFFS2_SB_FLAG_MOUNTING 2 - -+struct jffs2_inodirty; -+ - /* A struct for the overall file system control. Pointers to - jffs2_sb_info structs are named `c' in the source code. - Nee jffs_control -@@ -21,36 +24,46 @@ - struct jffs2_sb_info { - struct mtd_info *mtd; - -- __u32 highest_ino; -+ uint32_t highest_ino; -+ uint32_t checked_ino; -+ - unsigned int flags; -- spinlock_t nodelist_lock; - -- // pid_t thread_pid; /* GC thread's PID */ - struct task_struct *gc_task; /* GC task struct */ - struct semaphore gc_thread_start; /* GC thread start mutex */ - struct completion gc_thread_exit; /* GC thread exit completion port */ -- // __u32 gc_minfree_threshold; /* GC trigger thresholds */ -- // __u32 gc_maxdirty_threshold; - - struct semaphore alloc_sem; /* Used to protect all the following - fields, and also to protect against - out-of-order writing of nodes. - And GC. - */ -- __u32 flash_size; -- __u32 used_size; -- __u32 dirty_size; -- __u32 free_size; -- __u32 erasing_size; -- __u32 bad_size; -- __u32 sector_size; -- // __u32 min_free_size; -- // __u32 max_chunk_size; -+ uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER -+ (i.e. zero for OOB CLEANMARKER */ -+ -+ uint32_t flash_size; -+ uint32_t used_size; -+ uint32_t dirty_size; -+ uint32_t wasted_size; -+ uint32_t free_size; -+ uint32_t erasing_size; -+ uint32_t bad_size; -+ uint32_t sector_size; -+ uint32_t unchecked_size; -+ -+ uint32_t nr_free_blocks; -+ uint32_t nr_erasing_blocks; -+ -+ /* Number of free blocks there must be before we... */ -+ uint8_t resv_blocks_write; /* ... allow a normal filesystem write */ -+ uint8_t resv_blocks_deletion; /* ... allow a normal filesystem deletion */ -+ uint8_t resv_blocks_gctrigger; /* ... wake up the GC thread */ -+ uint8_t resv_blocks_gcbad; /* ... pick a block from the bad_list to GC */ -+ uint8_t resv_blocks_gcmerge; /* ... merge pages when garbage collecting */ - -- __u32 nr_free_blocks; -- __u32 nr_erasing_blocks; -+ uint32_t nospc_dirty_size; - -- __u32 nr_blocks; -+ uint32_t nr_blocks; - struct jffs2_eraseblock *blocks; /* The whole array of blocks. Used for getting blocks - * from the offset (blocks[ofs / sector_size]) */ - struct jffs2_eraseblock *nextblock; /* The block we're currently filling */ -@@ -58,9 +71,12 @@ - struct jffs2_eraseblock *gcblock; /* The block we're currently garbage-collecting */ - - struct list_head clean_list; /* Blocks 100% full of clean data */ -+ struct list_head very_dirty_list; /* Blocks with lots of dirty space */ - struct list_head dirty_list; /* Blocks with some dirty space */ -+ struct list_head erasable_list; /* Blocks which are completely dirty, and need erasing */ -+ struct list_head erasable_pending_wbuf_list; /* Blocks which need erasing but only after the current wbuf is flushed */ - struct list_head erasing_list; /* Blocks which are currently erasing */ -- struct list_head erase_pending_list; /* Blocks which need erasing */ -+ struct list_head erase_pending_list; /* Blocks which need erasing now */ - struct list_head erase_complete_list; /* Blocks which are erased and need the clean marker written to them */ - struct list_head free_list; /* Blocks which are free and ready to be used */ - struct list_head bad_list; /* Bad blocks. */ -@@ -69,16 +85,33 @@ - spinlock_t erase_completion_lock; /* Protect free_list and erasing_list - against erase completion handler */ - wait_queue_head_t erase_wait; /* For waiting for erases to complete */ -- struct jffs2_inode_cache *inocache_list[INOCACHE_HASHSIZE]; -+ -+ wait_queue_head_t inocache_wq; -+ struct jffs2_inode_cache **inocache_list; - spinlock_t inocache_lock; --}; - --#ifdef JFFS2_OUT_OF_KERNEL --#define JFFS2_SB_INFO(sb) ((struct jffs2_sb_info *) &(sb)->u) --#else --#define JFFS2_SB_INFO(sb) (&sb->u.jffs2_sb) -+ /* Sem to allow jffs2_garbage_collect_deletion_dirent to -+ drop the erase_completion_lock while it's holding a pointer -+ to an obsoleted node. I don't like this. Alternatives welcomed. */ -+ struct semaphore erase_free_sem; -+ -+#ifdef CONFIG_JFFS2_FS_NAND -+ /* Write-behind buffer for NAND flash */ -+ unsigned char *wbuf; -+ uint32_t wbuf_ofs; -+ uint32_t wbuf_len; -+ uint32_t wbuf_pagesize; -+ struct jffs2_inodirty *wbuf_inodes; -+ -+ /* Information about out-of-band area usage... */ -+ struct nand_oobinfo *oobinfo; -+ uint32_t badblock_pos; -+ uint32_t fsdata_pos; -+ uint32_t fsdata_len; - #endif - --#define OFNI_BS_2SFFJ(c) ((struct super_block *) ( ((char *)c) - ((char *)(&((struct super_block *)NULL)->u)) ) ) -+ /* OS-private pointer for getting back to master superblock info */ -+ void *os_priv; -+}; - - #endif /* _JFFS2_FB_SB */ -diff -Nurb linux-mips-2.4.27/include/linux/mtd/blktrans.h linux/include/linux/mtd/blktrans.h ---- linux-mips-2.4.27/include/linux/mtd/blktrans.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/include/linux/mtd/blktrans.h 2004-11-19 10:25:12.037178816 +0100 -@@ -0,0 +1,72 @@ -+/* -+ * $Id$ -+ * -+ * (C) 2003 David Woodhouse -+ * -+ * Interface to Linux block layer for MTD 'translation layers'. -+ * -+ */ -+ -+#ifndef __MTD_TRANS_H__ -+#define __MTD_TRANS_H__ -+ -+#include -+ -+struct hd_geometry; -+struct mtd_info; -+struct mtd_blktrans_ops; -+struct file; -+struct inode; -+ -+struct mtd_blktrans_dev { -+ struct mtd_blktrans_ops *tr; -+ struct list_head list; -+ struct mtd_info *mtd; -+ struct semaphore sem; -+ int devnum; -+ int blksize; -+ unsigned long size; -+ int readonly; -+ void *blkcore_priv; /* gendisk in 2.5, devfs_handle in 2.4 */ -+}; -+ -+struct blkcore_priv; /* Differs for 2.4 and 2.5 kernels; private */ -+ -+struct mtd_blktrans_ops { -+ char *name; -+ int major; -+ int part_bits; -+ -+ /* Access functions */ -+ int (*readsect)(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buffer); -+ int (*writesect)(struct mtd_blktrans_dev *dev, -+ unsigned long block, char *buffer); -+ -+ /* Block layer ioctls */ -+ int (*getgeo)(struct mtd_blktrans_dev *dev, struct hd_geometry *geo); -+ int (*flush)(struct mtd_blktrans_dev *dev); -+ -+ /* Called with mtd_table_mutex held; no race with add/remove */ -+ int (*open)(struct mtd_blktrans_dev *dev); -+ int (*release)(struct mtd_blktrans_dev *dev); -+ -+ /* Called on {de,}registration and on subsequent addition/removal -+ of devices, with mtd_table_mutex held. */ -+ void (*add_mtd)(struct mtd_blktrans_ops *tr, struct mtd_info *mtd); -+ void (*remove_dev)(struct mtd_blktrans_dev *dev); -+ -+ struct list_head devs; -+ struct list_head list; -+ struct module *owner; -+ -+ struct mtd_blkcore_priv *blkcore_priv; -+}; -+ -+extern int register_mtd_blktrans(struct mtd_blktrans_ops *tr); -+extern int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr); -+extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); -+extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); -+ -+ -+#endif /* __MTD_TRANS_H__ */ -diff -Nurb linux-mips-2.4.27/include/linux/mtd/cfi.h linux/include/linux/mtd/cfi.h ---- linux-mips-2.4.27/include/linux/mtd/cfi.h 2003-02-26 01:53:51.000000000 +0100 -+++ linux/include/linux/mtd/cfi.h 2004-11-19 10:25:12.038178664 +0100 -@@ -1,13 +1,14 @@ - - /* Common Flash Interface structures - * See http://support.intel.com/design/flash/technote/index.htm -- * $Id$ -+ * $Id$ - */ - - #ifndef __MTD_CFI_H__ - #define __MTD_CFI_H__ - - #include -+#include - #include - #include - #include -@@ -260,7 +261,8 @@ - __u8 pri[3]; - __u8 MajorVersion; - __u8 MinorVersion; -- __u32 FeatureSupport; -+ __u32 FeatureSupport; /* if bit 31 is set then an additional __u32 feature -+ block follows - FIXME - not currently supported */ - __u8 SuspendCmdSupport; - __u16 BlkStatusRegMask; - __u8 VccOptimal; -@@ -271,6 +273,25 @@ - __u8 UserProtRegSize; - } __attribute__((packed)); - -+/* Vendor-Specific PRI for AMD/Fujitsu Extended Command Set (0x0002) */ -+ -+struct cfi_pri_amdstd { -+ __u8 pri[3]; -+ __u8 MajorVersion; -+ __u8 MinorVersion; -+ __u8 SiliconRevision; /* bits 1-0: Address Sensitive Unlock */ -+ __u8 EraseSuspend; -+ __u8 BlkProt; -+ __u8 TmpBlkUnprotect; -+ __u8 BlkProtUnprot; -+ __u8 SimultaneousOps; -+ __u8 BurstMode; -+ __u8 PageMode; -+ __u8 VppMin; -+ __u8 VppMax; -+ __u8 TopBottom; -+} __attribute__((packed)); -+ - struct cfi_pri_query { - __u8 NumFields; - __u32 ProtField[1]; /* Not host ordered */ -@@ -314,8 +335,6 @@ - struct flchip chips[0]; /* per-chip data structure for each chip */ - }; - --#define MAX_CFI_CHIPS 8 /* Entirely arbitrary to avoid realloc() */ -- - /* - * Returns the command address according to the given geometry. - */ -@@ -387,13 +406,13 @@ - static inline cfi_word cfi_read(struct map_info *map, __u32 addr) - { - if (cfi_buswidth_is_1()) { -- return map->read8(map, addr); -+ return map_read8(map, addr); - } else if (cfi_buswidth_is_2()) { -- return map->read16(map, addr); -+ return map_read16(map, addr); - } else if (cfi_buswidth_is_4()) { -- return map->read32(map, addr); -+ return map_read32(map, addr); - } else if (cfi_buswidth_is_8()) { -- return map->read64(map, addr); -+ return map_read64(map, addr); - } else { - return 0; - } -@@ -406,13 +425,13 @@ - static inline void cfi_write(struct map_info *map, cfi_word val, __u32 addr) - { - if (cfi_buswidth_is_1()) { -- map->write8(map, val, addr); -+ map_write8(map, val, addr); - } else if (cfi_buswidth_is_2()) { -- map->write16(map, val, addr); -+ map_write16(map, val, addr); - } else if (cfi_buswidth_is_4()) { -- map->write32(map, val, addr); -+ map_write32(map, val, addr); - } else if (cfi_buswidth_is_8()) { -- map->write64(map, val, addr); -+ map_write64(map, val, addr); - } - } - -@@ -443,13 +462,13 @@ - static inline __u8 cfi_read_query(struct map_info *map, __u32 addr) - { - if (cfi_buswidth_is_1()) { -- return map->read8(map, addr); -+ return map_read8(map, addr); - } else if (cfi_buswidth_is_2()) { -- return cfi16_to_cpu(map->read16(map, addr)); -+ return cfi16_to_cpu(map_read16(map, addr)); - } else if (cfi_buswidth_is_4()) { -- return cfi32_to_cpu(map->read32(map, addr)); -+ return cfi32_to_cpu(map_read32(map, addr)); - } else if (cfi_buswidth_is_8()) { -- return cfi64_to_cpu(map->read64(map, addr)); -+ return cfi64_to_cpu(map_read64(map, addr)); - } else { - return 0; - } -@@ -479,5 +498,19 @@ - spin_unlock_bh(mutex); - } - -+struct cfi_extquery *cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, -+ const char* name); -+ -+struct cfi_fixup { -+ __u16 mfr; -+ __u16 id; -+ void (*fixup)(struct map_info *map, void* param); -+ void* param; -+}; -+ -+#define CFI_MFR_ANY 0xffff -+#define CFI_ID_ANY 0xffff -+ -+void cfi_fixup(struct map_info *map, struct cfi_fixup* fixups); - - #endif /* __MTD_CFI_H__ */ -diff -Nurb linux-mips-2.4.27/include/linux/mtd/compatmac.h linux/include/linux/mtd/compatmac.h ---- linux-mips-2.4.27/include/linux/mtd/compatmac.h 2003-02-26 01:53:51.000000000 +0100 -+++ linux/include/linux/mtd/compatmac.h 2004-11-19 10:25:12.041178208 +0100 -@@ -1,573 +1,152 @@ -- - /* -- * mtd/include/compatmac.h -- * -- * $Id$ -+ * $Id$ - * - * Extensions and omissions from the normal 'linux/compatmac.h' - * files. hopefully this will end up empty as the 'real' one - * becomes fully-featured. - */ - -- --/* First, include the parts which the kernel is good enough to provide -- * to us -- */ -- - #ifndef __LINUX_MTD_COMPATMAC_H__ - #define __LINUX_MTD_COMPATMAC_H__ - --#include --#include --#ifndef LINUX_VERSION_CODE - #include --#endif -- --#ifndef VERSION_CODE --# define VERSION_CODE(vers,rel,seq) ( ((vers)<<16) | ((rel)<<8) | (seq) ) --#endif --#ifndef KERNEL_VERSION --# define KERNEL_VERSION(a,b,c) VERSION_CODE(a,b,c) --#endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,0,0) --# error "This kernel is too old: not supported by this file" --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) --#include /* used later in this header */ -- --#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) --#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) -- --typedef struct wait_queue * wait_queue_head_t; -- --#define DECLARE_WAITQUEUE(x,y) struct wait_queue x = {y,NULL} --#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue *x = NULL --#define init_waitqueue_head init_waitqueue --#define DECLARE_MUTEX(x) struct semaphore x = MUTEX --#define DECLARE_MUTEX_LOCKED(x) struct semaphore x = MUTEX_LOCKED -- --/* from sysdep-2.1.h */ --# include --# define access_ok(t,a,sz) (verify_area((t),(a),(sz)) ? 0 : 1) --# define verify_area_20 verify_area --# define copy_to_user(t,f,n) (memcpy_tofs(t,f,n), 0) --# define __copy_to_user(t,f,n) copy_to_user((t),(f),(n)) --# define copy_to_user_ret(t,f,n,r) copy_to_user((t),(f),(n)) --# define copy_from_user(t,f,n) (memcpy_fromfs((t),(f),(n)), 0) --# define __copy_from_user(t,f,n) copy_from_user((t),(f),(n)) --# define copy_from_user_ret(t,f,n,r) copy_from_user((t),(f),(n)) --//xxx # define PUT_USER(val,add) (put_user((val),(add)), 0) --# define Put_user(val,add) (put_user((val),(add)), 0) --# define __PUT_USER(val,add) PUT_USER((val),(add)) --# define PUT_USER_RET(val,add,ret) PUT_USER((val),(add)) --# define GET_USER(dest,add) ((dest)=get_user((add)), 0) --# define __GET_USER(dest,add) GET_USER((dest),(add)) --# define GET_USER_RET(dest,add,ret) GET_USER((dest),(add)) -- --#define ioremap(offset,size) vremap(offset,size) --#define iounmap(adr) /* */ -- --#define EXPORT_SYMBOL(s) /* */ --#define EXPORT_SYMBOL_NOVERS(s) /* */ -- --/* 2.1.10 and 2.1.43 introduced new functions. They are worth using */ -- --#if LINUX_VERSION_CODE < VERSION_CODE(2,1,10) -- --# include --# ifdef __LITTLE_ENDIAN --# define cpu_to_le16(x) (x) --# define cpu_to_le32(x) (x) --# define cpu_to_be16(x) htons((x)) --# define cpu_to_be32(x) htonl((x)) --# else --# define cpu_to_be16(x) (x) --# define cpu_to_be32(x) (x) -- extern inline __u16 cpu_to_le16(__u16 x) { return (x<<8) | (x>>8);} -- extern inline __u32 cpu_to_le32(__u32 x) { return((x>>24) | -- ((x>>8)&0xff00) | ((x<<8)&0xff0000) | (x<<24));} --# endif -- --# define le16_to_cpu(x) cpu_to_le16(x) --# define le32_to_cpu(x) cpu_to_le32(x) --# define be16_to_cpu(x) cpu_to_be16(x) --# define be32_to_cpu(x) cpu_to_be32(x) -- --#endif -- --#if LINUX_VERSION_CODE < VERSION_CODE(2,1,43) --# define cpu_to_le16p(addr) (cpu_to_le16(*(addr))) --# define cpu_to_le32p(addr) (cpu_to_le32(*(addr))) --# define cpu_to_be16p(addr) (cpu_to_be16(*(addr))) --# define cpu_to_be32p(addr) (cpu_to_be32(*(addr))) -- -- extern inline void cpu_to_le16s(__u16 *a) {*a = cpu_to_le16(*a);} -- extern inline void cpu_to_le32s(__u16 *a) {*a = cpu_to_le32(*a);} -- extern inline void cpu_to_be16s(__u16 *a) {*a = cpu_to_be16(*a);} -- extern inline void cpu_to_be32s(__u16 *a) {*a = cpu_to_be32(*a);} -- --# define le16_to_cpup(x) cpu_to_le16p(x) --# define le32_to_cpup(x) cpu_to_le32p(x) --# define be16_to_cpup(x) cpu_to_be16p(x) --# define be32_to_cpup(x) cpu_to_be32p(x) -- --# define le16_to_cpus(x) cpu_to_le16s(x) --# define le32_to_cpus(x) cpu_to_le32s(x) --# define be16_to_cpus(x) cpu_to_be16s(x) --# define be32_to_cpus(x) cpu_to_be32s(x) --#endif -- --// from 2.2, linux/types.h --#ifndef __BIT_TYPES_DEFINED__ --#define __BIT_TYPES_DEFINED__ -- --typedef __u8 u_int8_t; --typedef __s8 int8_t; --typedef __u16 u_int16_t; --typedef __s16 int16_t; --typedef __u32 u_int32_t; --typedef __s32 int32_t; -- --#endif /* !(__BIT_TYPES_DEFINED__) */ -- --#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) -- typedef struct { } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { } --#else -- typedef struct { int gcc_is_buggy; } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } --#endif -- --#define spin_lock_init(lock) do { } while(0) --#define spin_lock(lock) (void)(lock) /* Not "unused variable". */ --#define spin_trylock(lock) (1) --#define spin_unlock_wait(lock) do { } while(0) --#define spin_unlock(lock) do { } while(0) --#define spin_lock_irq(lock) cli() --#define spin_unlock_irq(lock) sti() -- --#define spin_lock_irqsave(lock, flags) \ -- do { save_flags(flags); cli(); } while (0) --#define spin_unlock_irqrestore(lock, flags) \ -- restore_flags(flags) -- --// Doesn't work when tqueue.h is included. --// #define queue_task queue_task_irq_off --#define tty_flip_buffer_push(tty) queue_task_irq_off(&tty->flip.tqueue, &tq_timer) --#define signal_pending(current) (current->signal & ~current->blocked) --#define schedule_timeout(to) do {current->timeout = jiffies + (to);schedule ();} while (0) --#define time_after(t1,t2) (((long)t1-t2) > 0) -- --#else -- #include --#endif // LINUX_VERSION_CODE < 0x020100 -- -- --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) --#include --#endif -- --/* Modularization issues */ --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,18) --# define __USE_OLD_SYMTAB__ --# define EXPORT_NO_SYMBOLS register_symtab(NULL); --# define REGISTER_SYMTAB(tab) register_symtab(tab) --#else --# define REGISTER_SYMTAB(tab) /* nothing */ --#endif -- --#ifdef __USE_OLD_SYMTAB__ --# define __MODULE_STRING(s) /* nothing */ --# define MODULE_PARM(v,t) /* nothing */ --# define MODULE_PARM_DESC(v,t) /* nothing */ --# define MODULE_AUTHOR(n) /* nothing */ --# define MODULE_DESCRIPTION(d) /* nothing */ --# define MODULE_SUPPORTED_DEVICE(n) /* nothing */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) -+#error "This kernel is too old: not supported by this file" - #endif - --/* -- * "select" changed in 2.1.23. The implementation is twin, but this -- * header is new -- */ --#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,22) --# include --#else --# define __USE_OLD_SELECT__ --#endif -+ /* O(1) scheduler stuff. */ - --/* Other change in the fops are solved using pseudo-types */ --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) --# define lseek_t long long --# define lseek_off_t long long --#else --# define lseek_t int --# define lseek_off_t off_t --#endif -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,5) && !defined(__rh_config_h__) -+#include -+static inline void __recalc_sigpending(void) -+{ -+ recalc_sigpending(current); -+} -+#undef recalc_sigpending -+#define recalc_sigpending() __recalc_sigpending () - --/* changed the prototype of read/write */ -+#define set_user_nice(tsk, n) do { (tsk)->nice = n; } while(0) - --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) || defined(__alpha__) --# define count_t unsigned long --# define read_write_t long --#else --# define count_t int --# define read_write_t int - #endif - - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,31) --# define release_t void --# define release_return(x) return --#else --# define release_t int --# define release_return(x) return (x) --#endif -- --#if LINUX_VERSION_CODE < 0x20300 --#define __exit --#endif --#if LINUX_VERSION_CODE < 0x20200 --#define __init --#else --#include --#endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) --#define init_MUTEX(x) do {*(x) = MUTEX;} while (0) --#define init_MUTEX_LOCKED(x) do {*(x) = MUTEX_LOCKED;} while (0) --#endif -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20) - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) --#define RQFUNC_ARG void --#define blkdev_dequeue_request(req) do {CURRENT = req->next;} while (0) --#else --#define RQFUNC_ARG request_queue_t *q -+#ifndef yield -+#define yield() do { set_current_state(TASK_RUNNING); schedule(); } while(0) - #endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,32) --#define blk_cleanup_queue(nr) do {blk_dev[nr].request_fn = 0;} while(0) --#define BLK_DEFAULT_QUEUE(nr) (blk_dev[nr].request_fn) --#define blk_init_queue(q, rq) do {q = rq;} while(0) -+#ifndef minor -+#define major(d) (MAJOR(to_kdev_t(d))) -+#define minor(d) (MINOR(to_kdev_t(d))) - #endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0) --#ifdef CONFIG_MODULES --#define __MOD_INC_USE_COUNT(mod) \ -- (atomic_inc(&(mod)->uc.usecount), (mod)->flags |= MOD_VISITED|MOD_USED_ONCE) --#define __MOD_DEC_USE_COUNT(mod) \ -- (atomic_dec(&(mod)->uc.usecount), (mod)->flags |= MOD_VISITED) --#else --#define __MOD_INC_USE_COUNT(mod) --#define __MOD_DEC_USE_COUNT(mod) --#endif -+#ifndef mk_kdev -+#define mk_kdev(ma,mi) MKDEV(ma,mi) -+#define kdev_t_to_nr(x) (x) - #endif - -+#define need_resched() (current->need_resched) -+#define cond_resched() do { if need_resched() { yield(); } } while(0) - --#ifndef HAVE_INTER_MODULE --static inline void *inter_module_get(char *x) {return NULL;} --static inline void *inter_module_get_request(char *x, char *y) {return NULL;} --static inline void inter_module_put(const char *x) {} --static inline void inter_module_register(const char *x, struct module *y, const void *z) {} --static inline void inter_module_unregister(const char *x) {} -+#endif /* < 2.4.20 */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,73) -+#define iminor(i) minor((i)->i_rdev) -+#define imajor(i) major((i)->i_rdev) -+#define old_encode_dev(d) ( (major(d)<<8) | minor(d) ) -+#define old_decode_dev(rdev) (kdev_t_to_nr(mk_kdev((rdev)>>8, (rdev)&0xff))) -+#define old_valid_dev(d) (1) - #endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,61) - --#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue *x = NULL --#define init_waitqueue_head init_waitqueue -+#include - -+#ifdef __rh_config_h__ -+#define sigmask_lock sighand->siglock -+#define sig sighand - #endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -- --static inline int try_inc_mod_count(struct module *mod) -+static inline void __daemonize_modvers(void) - { --#ifdef CONFIG_MODULES -- if (mod) -- __MOD_INC_USE_COUNT(mod); --#endif -- return 1; --} --#endif -+ daemonize(); - -+ spin_lock_irq(¤t->sigmask_lock); -+ sigfillset(¤t->blocked); -+ recalc_sigpending(); -+ spin_unlock_irq(¤t->sigmask_lock); -+} -+#undef daemonize -+#define daemonize(fmt, ...) do { \ -+ snprintf(current->comm, sizeof(current->comm), fmt ,##__VA_ARGS__); \ -+ __daemonize_modvers(); \ -+ } while(0) - --/* Yes, I'm aware that it's a fairly ugly hack. -- Until the __constant_* macros appear in Linus' own kernels, this is -- the way it has to be done. -- DW 19/1/00 -- */ -- --#include -- --#ifndef __constant_cpu_to_le16 -- --#ifdef __BIG_ENDIAN --#define __constant_cpu_to_le64(x) ___swab64((x)) --#define __constant_le64_to_cpu(x) ___swab64((x)) --#define __constant_cpu_to_le32(x) ___swab32((x)) --#define __constant_le32_to_cpu(x) ___swab32((x)) --#define __constant_cpu_to_le16(x) ___swab16((x)) --#define __constant_le16_to_cpu(x) ___swab16((x)) --#define __constant_cpu_to_be64(x) ((__u64)(x)) --#define __constant_be64_to_cpu(x) ((__u64)(x)) --#define __constant_cpu_to_be32(x) ((__u32)(x)) --#define __constant_be32_to_cpu(x) ((__u32)(x)) --#define __constant_cpu_to_be16(x) ((__u16)(x)) --#define __constant_be16_to_cpu(x) ((__u16)(x)) --#else --#ifdef __LITTLE_ENDIAN --#define __constant_cpu_to_le64(x) ((__u64)(x)) --#define __constant_le64_to_cpu(x) ((__u64)(x)) --#define __constant_cpu_to_le32(x) ((__u32)(x)) --#define __constant_le32_to_cpu(x) ((__u32)(x)) --#define __constant_cpu_to_le16(x) ((__u16)(x)) --#define __constant_le16_to_cpu(x) ((__u16)(x)) --#define __constant_cpu_to_be64(x) ___swab64((x)) --#define __constant_be64_to_cpu(x) ___swab64((x)) --#define __constant_cpu_to_be32(x) ___swab32((x)) --#define __constant_be32_to_cpu(x) ___swab32((x)) --#define __constant_cpu_to_be16(x) ___swab16((x)) --#define __constant_be16_to_cpu(x) ___swab16((x)) --#else --#error No (recognised) endianness defined (unless it,s PDP) --#endif /* __LITTLE_ENDIAN */ --#endif /* __BIG_ENDIAN */ -- --#endif /* ifndef __constant_cpu_to_le16 */ -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -- #define mod_init_t int __init -- #define mod_exit_t void --#else -- #define mod_init_t static int __init -- #define mod_exit_t static void __exit --#endif -- --#ifndef THIS_MODULE --#ifdef MODULE --#define THIS_MODULE (&__this_module) --#else --#define THIS_MODULE (NULL) --#endif --#endif -- --#if LINUX_VERSION_CODE < 0x20300 --#include --#define spin_lock_bh(lock) do {start_bh_atomic();spin_lock(lock);}while(0) --#define spin_unlock_bh(lock) do {spin_unlock(lock);end_bh_atomic();}while(0) --#else --#include --#include --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) --#define set_current_state(state_value) \ -- do { current->state = (state_value); } while (0) --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0) --static inline int invalidate_device(kdev_t dev, int do_sync) { -+static inline int dequeue_signal_lock(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) -+{ -+ unsigned long flags; -+ unsigned long ret; - -- if (do_sync) -- fsync_dev(dev); -+ spin_lock_irqsave(¤t->sigmask_lock, flags); -+ ret = dequeue_signal(mask, info); -+ spin_unlock_irqrestore(¤t->sigmask_lock, flags); - -- invalidate_buffers(dev); -- return 0; -+ return ret; - } --#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,4,5) --static inline int invalidate_device(kdev_t dev, int do_sync) { -- struct super_block *sb = get_super(dev); -- int res = 0; - -- if (do_sync) -- fsync_dev(dev); -- -- if (sb) -- res = invalidate_inodes(sb); -+static inline int allow_signal(int sig) -+{ -+ if (sig < 1 || sig > _NSIG) -+ return -EINVAL; - -- invalidate_buffers(dev); -- return res; -+ spin_lock_irq(¤t->sigmask_lock); -+ sigdelset(¤t->blocked, sig); -+ recalc_sigpending(); -+ /* Make sure the kernel neither eats it now converts to SIGKILL */ -+ current->sig->action[sig-1].sa.sa_handler = (void *)2; -+ spin_unlock_irq(¤t->sigmask_lock); -+ return 0; - } --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) --#undef min --#undef max --#undef min_t --#undef max_t --/* -- * min()/max() macros that also do -- * strict type-checking.. See the -- * "unnecessary" pointer comparison. -- */ --#define min(x,y) ({ \ -- const typeof(x) _x = (x); \ -- const typeof(y) _y = (y); \ -- (void) (&_x == &_y); \ -- _x < _y ? _x : _y; }) -- --#define max(x,y) ({ \ -- const typeof(x) _x = (x); \ -- const typeof(y) _y = (y); \ -- (void) (&_x == &_y); \ -- _x > _y ? _x : _y; }) -- --/* -- * ..and if you can't take the strict -- * types, you can specify one yourself. -- * -- * Or not use min/max at all, of course. -- */ --#define min_t(type,x,y) \ -- ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) --#define max_t(type,x,y) \ -- ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,7) --struct completion { -- struct semaphore s; --}; -- --#define complete(c) up(&(c)->s) --#define wait_for_completion(c) down(&(c)->s) --#define init_completion(c) init_MUTEX_LOCKED(&(c)->s); -- --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9) --/* This came later */ --#define complete_and_exit(c, r) do { complete(c); do_exit(r); } while(0) --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9) || \ -- (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) && !defined(__rh_config_h__)) -+static inline int disallow_signal(int sig) -+{ -+ if (sig < 1 || sig > _NSIG) -+ return -EINVAL; - --#include -+ spin_lock_irq(¤t->sigmask_lock); -+ sigaddset(¤t->blocked, sig); -+ recalc_sigpending(); - --static inline void add_gendisk(struct gendisk *gp) --{ -- gp->next = gendisk_head; -- gendisk_head = gp; -+ current->sig->action[sig-1].sa.sa_handler = SIG_DFL; -+ spin_unlock_irq(¤t->sigmask_lock); -+ return 0; - } - --static inline void del_gendisk(struct gendisk *gp) --{ -- struct gendisk *gd, **gdp; -+#undef sighand -+#undef sigmask_lock - -- for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) -- if (*gdp == gp) { -- gd = *gdp; *gdp = gd->next; -- break; -- } --} -+#define PF_FREEZE 0 -+#define refrigerator(x) do { ; } while(0) - #endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) && defined(MODULE) -+ /* Module bits */ - --#define module_init(func) \ --mod_init_t init_module(void) { \ -- return func(); \ --} - --#define module_exit(func) \ --mod_exit_t cleanup_module(void) { \ -- return func(); \ --} -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60) -+#define try_module_get(m) try_inc_mod_count(m) -+#define __module_get(m) do { if (!try_inc_mod_count(m)) BUG(); } while(0) -+#define module_put(m) do { if (m) __MOD_DEC_USE_COUNT((struct module *)(m)); } while(0) -+#define set_module_owner(x) do { x->owner = THIS_MODULE; } while(0) - #endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9) || \ -- (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) && !defined(__rh_config_h__)) --#define MODULE_LICENSE(x) /* */ --#endif - --/* Removed for 2.4.21 kernel. This really should have been renamed -- when it was changed -- this is a PITA */ --#if 0 && LINUX_VERSION_CODE < KERNEL_VERSION(2,5,5) --#include --static inline void __recalc_sigpending(void) --{ -- recalc_sigpending(current); --} --#undef recalc_sigpending --#define recalc_sigpending() __recalc_sigpending () --#endif -+ /* Random filesystem stuff, only for JFFS2 really */ - - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,5) - #define parent_ino(d) ((d)->d_parent->d_inode->i_ino) - #endif - --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,3) --#define need_resched() (current->need_resched) --#define cond_resched() do { if need_resched() schedule(); } while(0) --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19) --#ifndef yield --#define yield() do { set_current_state(TASK_RUNNING); schedule(); } while(0) --#endif --#ifndef minor --#define major(d) (MAJOR(to_kdev_t(d))) --#define minor(d) (MINOR(to_kdev_t(d))) --#endif --#ifndef mk_kdev --#define mk_kdev(ma,mi) MKDEV(ma,mi) --#define kdev_t_to_nr(x) (x) --#endif --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -- /* Is this right? */ --#define set_user_nice(tsk, n) do { (tsk)->priority = 20-(n); } while(0) --#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,4,21) && !defined(RED_HAT_LINUX_KERNEL) --#define set_user_nice(tsk, n) do { (tsk)->nice = n; } while(0) --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,21) --#define rq_data_dir(x) ((x)->cmd) --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -- --#define IS_REQ_CMD(req) (1) -- --#define QUEUE_LOCK(q) (&io_request_lock) -- --#define BLK_INIT_QUEUE(q, req, lock) blk_init_queue((q), (req)) -- --#else /* > 2.5.0 */ -- --#define IS_REQ_CMD(req) ((req)->flags & REQ_CMD) -- --#define QUEUE_LOCK(q) ((q)->queue_lock) -- --#define BLK_INIT_QUEUE(q, req, lock) blk_init_queue((q), (req), (lock)) -- --#endif -- --/* Removed cos it broke stuff. Where is this required anyway? -- * #ifndef QUEUE_EMPTY -- * #define QUEUE_EMPTY (!CURRENT) -- * #endif -- */ --#if LINUX_VERSION_CODE < 0x20300 --#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].plug_tq.sync) --#elif LINUX_VERSION_CODE < 0x20500 //FIXME (Si) --#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].request_queue.plugged) --#else --#define QUEUE_PLUGGED (blk_queue_plugged(QUEUE)) --#endif -- --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14) --#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT --#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT --#else --#define BLK_INC_USE_COUNT do {} while(0) --#define BLK_DEC_USE_COUNT do {} while(0) --#endif -- - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,12) - #define PageUptodate(x) Page_Uptodate(x) - #endif -@@ -580,4 +159,31 @@ - #define generic_file_readonly_mmap generic_file_mmap - #endif - -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,70) -+ -+#include -+#include -+ -+static inline char *strlcpy(char *dest, const char *src, int len) -+{ -+ dest[len-1] = 0; -+ return strncpy(dest, src, len-1); -+} -+ -+static inline int do_old_request_module(const char *mod) -+{ -+ return request_module(mod); -+} -+#undef request_module -+#define request_module(fmt, ...) \ -+ ({ char modname[32]; snprintf(modname, 31, fmt ,##__VA_ARGS__); do_old_request_module(modname); }) -+ -+#endif /* 2.5.70 */ -+ -+#ifndef container_of -+#define container_of(ptr, type, member) ({ \ -+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ -+ (type *)( (char *)__mptr - offsetof(type,member) );}) -+#endif -+ - #endif /* __LINUX_MTD_COMPATMAC_H__ */ -diff -Nurb linux-mips-2.4.27/include/linux/mtd/doc2000.h linux/include/linux/mtd/doc2000.h ---- linux-mips-2.4.27/include/linux/mtd/doc2000.h 2001-11-05 21:16:30.000000000 +0100 -+++ linux/include/linux/mtd/doc2000.h 2004-11-19 10:25:12.044177752 +0100 -@@ -1,13 +1,21 @@ -- --/* Linux driver for Disk-On-Chip 2000 */ --/* (c) 1999 Machine Vision Holdings, Inc. */ --/* Author: David Woodhouse */ --/* $Id$ */ -+/* -+ * Linux driver for Disk-On-Chip devices -+ * -+ * Copyright (C) 1999 Machine Vision Holdings, Inc. -+ * Copyright (C) 2001-2003 David Woodhouse -+ * Copyright (C) 2002-2003 Greg Ungerer -+ * Copyright (C) 2002-2003 SnapGear Inc -+ * -+ * $Id$ -+ * -+ * Released under GPL -+ */ - - #ifndef __MTD_DOC2000_H__ - #define __MTD_DOC2000_H__ - - #include -+#include - - #define DoC_Sig1 0 - #define DoC_Sig2 1 -@@ -38,18 +46,47 @@ - #define DoC_Mil_CDSN_IO 0x0800 - #define DoC_2k_CDSN_IO 0x1800 - -+#define DoC_Mplus_NOP 0x1002 -+#define DoC_Mplus_AliasResolution 0x1004 -+#define DoC_Mplus_DOCControl 0x1006 -+#define DoC_Mplus_AccessStatus 0x1008 -+#define DoC_Mplus_DeviceSelect 0x1008 -+#define DoC_Mplus_Configuration 0x100a -+#define DoC_Mplus_OutputControl 0x100c -+#define DoC_Mplus_FlashControl 0x1020 -+#define DoC_Mplus_FlashSelect 0x1022 -+#define DoC_Mplus_FlashCmd 0x1024 -+#define DoC_Mplus_FlashAddress 0x1026 -+#define DoC_Mplus_FlashData0 0x1028 -+#define DoC_Mplus_FlashData1 0x1029 -+#define DoC_Mplus_ReadPipeInit 0x102a -+#define DoC_Mplus_LastDataRead 0x102c -+#define DoC_Mplus_LastDataRead1 0x102d -+#define DoC_Mplus_WritePipeTerm 0x102e -+#define DoC_Mplus_ECCSyndrome0 0x1040 -+#define DoC_Mplus_ECCSyndrome1 0x1041 -+#define DoC_Mplus_ECCSyndrome2 0x1042 -+#define DoC_Mplus_ECCSyndrome3 0x1043 -+#define DoC_Mplus_ECCSyndrome4 0x1044 -+#define DoC_Mplus_ECCSyndrome5 0x1045 -+#define DoC_Mplus_ECCConf 0x1046 -+#define DoC_Mplus_Toggle 0x1046 -+#define DoC_Mplus_DownloadStatus 0x1074 -+#define DoC_Mplus_CtrlConfirm 0x1076 -+#define DoC_Mplus_Power 0x1fff -+ - /* How to access the device? - * On ARM, it'll be mmap'd directly with 32-bit wide accesses. - * On PPC, it's mmap'd and 16-bit wide. - * Others use readb/writeb - */ - #if defined(__arm__) --#define ReadDOC_(adr, reg) ((unsigned char)(*(__u32 *)(((unsigned long)adr)+((reg)<<2)))) --#define WriteDOC_(d, adr, reg) do{ *(__u32 *)(((unsigned long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0) -+#define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)))) -+#define WriteDOC_(d, adr, reg) do{ *(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0) - #define DOC_IOREMAP_LEN 0x8000 - #elif defined(__ppc__) --#define ReadDOC_(adr, reg) ((unsigned char)(*(__u16 *)(((unsigned long)adr)+((reg)<<1)))) --#define WriteDOC_(d, adr, reg) do{ *(__u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0) -+#define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u16 *)(((unsigned long)adr)+((reg)<<1)))) -+#define WriteDOC_(d, adr, reg) do{ *(volatile __u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0) - #define DOC_IOREMAP_LEN 0x4000 - #else - #define ReadDOC_(adr, reg) readb(((unsigned long)adr) + (reg)) -@@ -71,13 +108,21 @@ - #define DOC_MODE_RESERVED1 2 - #define DOC_MODE_RESERVED2 3 - --#define DOC_MODE_MDWREN 4 - #define DOC_MODE_CLR_ERR 0x80 -+#define DOC_MODE_RST_LAT 0x10 -+#define DOC_MODE_BDECT 0x08 -+#define DOC_MODE_MDWREN 0x04 - - #define DOC_ChipID_Doc2k 0x20 -+#define DOC_ChipID_Doc2kTSOP 0x21 /* internal number for MTD */ - #define DOC_ChipID_DocMil 0x30 -+#define DOC_ChipID_DocMilPlus32 0x40 -+#define DOC_ChipID_DocMilPlus16 0x41 - - #define CDSN_CTRL_FR_B 0x80 -+#define CDSN_CTRL_FR_B0 0x40 -+#define CDSN_CTRL_FR_B1 0x80 -+ - #define CDSN_CTRL_ECC_IO 0x20 - #define CDSN_CTRL_FLASH_IO 0x10 - #define CDSN_CTRL_WP 0x08 -@@ -93,6 +138,10 @@ - #define DOC_ECC_RESV 0x02 - #define DOC_ECC_IGNORE 0x01 - -+#define DOC_FLASH_CE 0x80 -+#define DOC_FLASH_WP 0x40 -+#define DOC_FLASH_BANK 0x02 -+ - /* We have to also set the reserved bit 1 for enable */ - #define DOC_ECC_EN (DOC_ECC__EN | DOC_ECC_RESV) - #define DOC_ECC_DIS (DOC_ECC_RESV) -@@ -107,9 +156,12 @@ - #define MAX_FLOORS 4 - #define MAX_CHIPS 4 - --#define MAX_FLOORS_MIL 4 -+#define MAX_FLOORS_MIL 1 - #define MAX_CHIPS_MIL 1 - -+#define MAX_FLOORS_MPLUS 2 -+#define MAX_CHIPS_MPLUS 1 -+ - #define ADDR_COLUMN 1 - #define ADDR_PAGE 2 - #define ADDR_COLUMN_PAGE 3 -@@ -118,7 +170,7 @@ - unsigned long physadr; - unsigned long virtadr; - unsigned long totlen; -- char ChipID; /* Type of DiskOnChip */ -+ unsigned char ChipID; /* Type of DiskOnChip */ - int ioreg; - - unsigned long mfr; /* Flash IDs - only one type of flash per device */ -@@ -126,6 +178,7 @@ - int chipshift; - char page256; - char pageadrlen; -+ char interleave; /* Internal interleaving - Millennium Plus style */ - unsigned long erasesize; - - int curfloor; -diff -Nurb linux-mips-2.4.27/include/linux/mtd/flashchip.h linux/include/linux/mtd/flashchip.h ---- linux-mips-2.4.27/include/linux/mtd/flashchip.h 2003-02-26 01:53:51.000000000 +0100 -+++ linux/include/linux/mtd/flashchip.h 2004-11-19 10:25:12.045177600 +0100 -@@ -6,7 +6,7 @@ - * - * (C) 2000 Red Hat. GPLd. - * -- * $Id$ -+ * $Id$ - * - */ - -@@ -58,6 +58,11 @@ - int ref_point_counter; - flstate_t state; - flstate_t oldstate; -+ -+ int write_suspended:1; -+ int erase_suspended:1; -+ unsigned long in_progress_block_addr; -+ - spinlock_t *mutex; - spinlock_t _spinlock; /* We do it like this because sometimes they'll be shared. */ - wait_queue_head_t wq; /* Wait on here when we're waiting for the chip -diff -Nurb linux-mips-2.4.27/include/linux/mtd/gen_probe.h linux/include/linux/mtd/gen_probe.h ---- linux-mips-2.4.27/include/linux/mtd/gen_probe.h 2001-11-05 21:16:30.000000000 +0100 -+++ linux/include/linux/mtd/gen_probe.h 2004-11-19 10:25:12.048177144 +0100 -@@ -1,7 +1,7 @@ - /* - * (C) 2001, 2001 Red Hat, Inc. - * GPL'd -- * $Id$ -+ * $Id$ - */ - - #ifndef __LINUX_MTD_GEN_PROBE_H__ -@@ -10,12 +10,12 @@ - #include - #include - #include -+#include - - struct chip_probe { - char *name; - int (*probe_chip)(struct map_info *map, __u32 base, -- struct flchip *chips, struct cfi_private *cfi); -- -+ unsigned long *chip_map, struct cfi_private *cfi); - }; - - struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp); -diff -Nurb linux-mips-2.4.27/include/linux/mtd/inftl.h linux/include/linux/mtd/inftl.h ---- linux-mips-2.4.27/include/linux/mtd/inftl.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/include/linux/mtd/inftl.h 2004-11-19 10:25:12.051176688 +0100 -@@ -0,0 +1,129 @@ -+/* -+ * inftl.h -- defines to support the Inverse NAND Flash Translation Layer -+ * -+ * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) -+ * -+ * $Id$ -+ */ -+ -+#ifndef __MTD_INFTL_H__ -+#define __MTD_INFTL_H__ -+ -+#include -+#include -+#include -+ -+#define OSAK_VERSION 0x5120 -+#define PERCENTUSED 98 -+ -+#define SECTORSIZE 512 -+ -+#ifndef INFTL_MAJOR -+#define INFTL_MAJOR 94 -+#endif -+#define INFTL_PARTN_BITS 4 -+ -+/* Block Control Information */ -+ -+struct inftl_bci { -+ __u8 ECCsig[6]; -+ __u8 Status; -+ __u8 Status1; -+} __attribute__((packed)); -+ -+struct inftl_unithead1 { -+ __u16 virtualUnitNo; -+ __u16 prevUnitNo; -+ __u8 ANAC; -+ __u8 NACs; -+ __u8 parityPerField; -+ __u8 discarded; -+} __attribute__((packed)); -+ -+struct inftl_unithead2 { -+ __u8 parityPerField; -+ __u8 ANAC; -+ __u16 prevUnitNo; -+ __u16 virtualUnitNo; -+ __u8 NACs; -+ __u8 discarded; -+} __attribute__((packed)); -+ -+struct inftl_unittail { -+ __u8 Reserved[4]; -+ __u16 EraseMark; -+ __u16 EraseMark1; -+} __attribute__((packed)); -+ -+union inftl_uci { -+ struct inftl_unithead1 a; -+ struct inftl_unithead2 b; -+ struct inftl_unittail c; -+}; -+ -+struct inftl_oob { -+ struct inftl_bci b; -+ union inftl_uci u; -+}; -+ -+ -+/* INFTL Media Header */ -+ -+struct INFTLPartition { -+ __u32 virtualUnits; -+ __u32 firstUnit; -+ __u32 lastUnit; -+ __u32 flags; -+ __u32 spareUnits; -+ __u32 Reserved0; -+ __u32 Reserved1; -+} __attribute__((packed)); -+ -+struct INFTLMediaHeader { -+ char bootRecordID[8]; -+ __u32 NoOfBootImageBlocks; -+ __u32 NoOfBinaryPartitions; -+ __u32 NoOfBDTLPartitions; -+ __u32 BlockMultiplierBits; -+ __u32 FormatFlags; -+ __u32 OsakVersion; -+ __u32 PercentUsed; -+ struct INFTLPartition Partitions[4]; -+} __attribute__((packed)); -+ -+/* Partition flag types */ -+#define INFTL_BINARY 0x20000000 -+#define INFTL_BDTL 0x40000000 -+#define INFTL_LAST 0x80000000 -+ -+ -+#ifdef __KERNEL__ -+ -+struct INFTLrecord { -+ struct mtd_blktrans_dev mbd; -+ __u16 MediaUnit, SpareMediaUnit; -+ __u32 EraseSize; -+ struct INFTLMediaHeader MediaHdr; -+ int usecount; -+ unsigned char heads; -+ unsigned char sectors; -+ unsigned short cylinders; -+ __u16 numvunits; -+ __u16 firstEUN; -+ __u16 lastEUN; -+ __u16 numfreeEUNs; -+ __u16 LastFreeEUN; /* To speed up finding a free EUN */ -+ int head,sect,cyl; -+ __u16 *PUtable; /* Physical Unit Table */ -+ __u16 *VUtable; /* Virtual Unit Table */ -+ unsigned int nb_blocks; /* number of physical blocks */ -+ unsigned int nb_boot_blocks; /* number of blocks used by the bios */ -+ struct erase_info instr; -+}; -+ -+int INFTL_mount(struct INFTLrecord *s); -+int INFTL_formatblock(struct INFTLrecord *s, int block); -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* __MTD_INFTL_H__ */ -diff -Nurb linux-mips-2.4.27/include/linux/mtd/jedec.h linux/include/linux/mtd/jedec.h ---- linux-mips-2.4.27/include/linux/mtd/jedec.h 2001-12-02 12:35:00.000000000 +0100 -+++ linux/include/linux/mtd/jedec.h 2004-11-19 10:25:12.052176536 +0100 -@@ -7,14 +7,13 @@ - * - * See the AMD flash databook for information on how to operate the interface. - * -- * $Id$ -+ * $Id$ - */ - - #ifndef __LINUX_MTD_JEDEC_H__ - #define __LINUX_MTD_JEDEC_H__ - - #include --#include - - #define MAX_JEDEC_CHIPS 16 - -diff -Nurb linux-mips-2.4.27/include/linux/mtd/map.h linux/include/linux/mtd/map.h ---- linux-mips-2.4.27/include/linux/mtd/map.h 2003-02-26 01:53:51.000000000 +0100 -+++ linux/include/linux/mtd/map.h 2004-11-19 10:25:12.054176232 +0100 -@@ -1,14 +1,15 @@ - - /* Overhauled routines for dealing with different mmap regions of flash */ --/* $Id$ */ -+/* $Id$ */ - - #ifndef __LINUX_MTD_MAP_H__ - #define __LINUX_MTD_MAP_H__ - - #include - #include --#include --#include -+#include -+#include -+#include - - /* The map stuff is very simple. You fill in your struct map_info with - a handful of routines for accessing the device, making sure they handle -@@ -29,39 +30,44 @@ - struct map_info { - char *name; - unsigned long size; -+ unsigned long phys; -+#define NO_XIP (-1UL) -+ -+ unsigned long virt; -+ void *cached; -+ - int buswidth; /* in octets */ -- __u8 (*read8)(struct map_info *, unsigned long); -- __u16 (*read16)(struct map_info *, unsigned long); -- __u32 (*read32)(struct map_info *, unsigned long); -- __u64 (*read64)(struct map_info *, unsigned long); -+ -+#ifdef CONFIG_MTD_COMPLEX_MAPPINGS -+ u8 (*read8)(struct map_info *, unsigned long); -+ u16 (*read16)(struct map_info *, unsigned long); -+ u32 (*read32)(struct map_info *, unsigned long); -+ u64 (*read64)(struct map_info *, unsigned long); - /* If it returned a 'long' I'd call it readl. - * It doesn't. - * I won't. - * dwmw2 */ - - void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t); -- void (*write8)(struct map_info *, __u8, unsigned long); -- void (*write16)(struct map_info *, __u16, unsigned long); -- void (*write32)(struct map_info *, __u32, unsigned long); -- void (*write64)(struct map_info *, __u64, unsigned long); -+ void (*write8)(struct map_info *, u8, unsigned long); -+ void (*write16)(struct map_info *, u16, unsigned long); -+ void (*write32)(struct map_info *, u32, unsigned long); -+ void (*write64)(struct map_info *, u64, unsigned long); - void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t); - -- u_char * (*point) (struct map_info *, loff_t, size_t); -- void (*unpoint) (struct map_info *, u_char *, loff_t, size_t); -- -+ /* We can perhaps put in 'point' and 'unpoint' methods, if we really -+ want to enable XIP for non-linear mappings. Not yet though. */ -+#endif -+ /* set_vpp() must handle being reentered -- enable, enable, disable -+ must leave it enabled. */ - void (*set_vpp)(struct map_info *, int); -- /* We put these two here rather than a single void *map_priv, -- because we want mappers to be able to have quickly-accessible -- cache for the 'currently-mapped page' without the _extra_ -- redirection that would be necessary. If you need more than -- two longs, turn the second into a pointer. dwmw2 */ -+ - unsigned long map_priv_1; - unsigned long map_priv_2; - void *fldrv_priv; - struct mtd_chip_driver *fldrv; - }; - -- - struct mtd_chip_driver { - struct mtd_info *(*probe)(struct map_info *map); - void (*destroy)(struct mtd_info *); -@@ -74,26 +80,93 @@ - void unregister_mtd_chip_driver(struct mtd_chip_driver *); - - struct mtd_info *do_map_probe(const char *name, struct map_info *map); -+void map_destroy(struct mtd_info *mtd); -+ -+#define ENABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 1); } while(0) -+#define DISABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 0); } while(0) -+ -+#ifdef CONFIG_MTD_COMPLEX_MAPPINGS -+#define map_read8(map, ofs) (map)->read8(map, ofs) -+#define map_read16(map, ofs) (map)->read16(map, ofs) -+#define map_read32(map, ofs) (map)->read32(map, ofs) -+#define map_read64(map, ofs) (map)->read64(map, ofs) -+#define map_copy_from(map, to, from, len) (map)->copy_from(map, to, from, len) -+#define map_write8(map, datum, ofs) (map)->write8(map, datum, ofs) -+#define map_write16(map, datum, ofs) (map)->write16(map, datum, ofs) -+#define map_write32(map, datum, ofs) (map)->write32(map, datum, ofs) -+#define map_write64(map, datum, ofs) (map)->write64(map, datum, ofs) -+#define map_copy_to(map, to, from, len) (map)->copy_to(map, to, from, len) - -+extern void simple_map_init(struct map_info *); -+#define map_is_linear(map) (map->phys != NO_XIP) - --/* -- * Destroy an MTD device which was created for a map device. -- * Make sure the MTD device is already unregistered before calling this -- */ --static inline void map_destroy(struct mtd_info *mtd) --{ -- struct map_info *map = mtd->priv; -- -- if (map->fldrv->destroy) -- map->fldrv->destroy(mtd); --#ifdef CONFIG_MODULES -- if (map->fldrv->module) -- __MOD_DEC_USE_COUNT(map->fldrv->module); -+#else -+static inline u8 map_read8(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readb(map->virt + ofs); -+} -+ -+static inline u16 map_read16(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readw(map->virt + ofs); -+} -+ -+static inline u32 map_read32(struct map_info *map, unsigned long ofs) -+{ -+ return __raw_readl(map->virt + ofs); -+} -+ -+static inline u64 map_read64(struct map_info *map, unsigned long ofs) -+{ -+#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */ -+ BUG(); -+ return 0; -+#else -+ return __raw_readll(map->virt + ofs); - #endif -- kfree(mtd); - } - --#define ENABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 1); } while(0) --#define DISABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 0); } while(0) -+static inline void map_write8(struct map_info *map, u8 datum, unsigned long ofs) -+{ -+ __raw_writeb(datum, map->virt + ofs); -+ mb(); -+} -+ -+static inline void map_write16(struct map_info *map, u16 datum, unsigned long ofs) -+{ -+ __raw_writew(datum, map->virt + ofs); -+ mb(); -+} -+ -+static inline void map_write32(struct map_info *map, u32 datum, unsigned long ofs) -+{ -+ __raw_writel(datum, map->virt + ofs); -+ mb(); -+} -+ -+static inline void map_write64(struct map_info *map, u64 datum, unsigned long ofs) -+{ -+#ifndef CONFIG_MTD_CFI_B8 /* 64-bit mappings */ -+ BUG(); -+#else -+ __raw_writell(datum, map->virt + ofs); -+ mb(); -+#endif /* CFI_B8 */ -+} -+ -+static inline void map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -+{ -+ memcpy_fromio(to, map->virt + from, len); -+} -+ -+static inline void map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -+{ -+ memcpy_toio(map->virt + to, from, len); -+} -+ -+#define simple_map_init(map) do { } while (0) -+#define map_is_linear(map) (1) -+ -+#endif /* !CONFIG_MTD_COMPLEX_MAPPINGS */ - - #endif /* __LINUX_MTD_MAP_H__ */ -diff -Nurb linux-mips-2.4.27/include/linux/mtd/mtd.h linux/include/linux/mtd/mtd.h ---- linux-mips-2.4.27/include/linux/mtd/mtd.h 2003-08-13 19:19:29.000000000 +0200 -+++ linux/include/linux/mtd/mtd.h 2004-11-19 10:25:12.055176080 +0100 -@@ -1,5 +1,10 @@ -- --/* $Id$ */ -+/* -+ * $Id$ -+ * -+ * Copyright (C) 1999-2003 David Woodhouse et al. -+ * -+ * Released under GPL -+ */ - - #ifndef __MTD_MTD_H__ - #define __MTD_MTD_H__ -@@ -9,7 +14,6 @@ - #include - #include - #include --#include - #include - #include - -@@ -26,7 +30,6 @@ - unsigned char *ptr; - }; - -- - #define MTD_CHAR_MAJOR 90 - #define MTD_BLOCK_MAJOR 31 - #define MAX_MTD_DEVICES 16 -@@ -93,18 +96,23 @@ - #define MEMUNLOCK _IOW('M', 6, struct erase_info_user) - #define MEMGETREGIONCOUNT _IOR('M', 7, int) - #define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user) --#define MEMREADDATA _IOWR('M', 9, struct mtd_oob_buf) --#define MEMWRITEDATA _IOWR('M', 10, struct mtd_oob_buf) -+#define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo) -+ -+struct nand_oobinfo { -+ int useecc; -+ int eccpos[6]; -+}; -+ - - #ifndef __KERNEL__ - - typedef struct mtd_info_user mtd_info_t; - typedef struct erase_info_user erase_info_t; - typedef struct region_info_user region_info_t; -+typedef struct nand_oobinfo nand_oobinfo_t; - - /* User-space ioctl definitions */ - -- - #else /* __KERNEL__ */ - - -@@ -150,10 +158,14 @@ - u_int32_t ecctype; - u_int32_t eccsize; - -+ - // Kernel-only stuff starts here. - char *name; - int index; - -+ // oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO) -+ struct nand_oobinfo oobinfo; -+ - /* Data for variable erase regions. If numeraseregions is zero, - * it means that the whole device has erasesize as given above. - */ -@@ -163,7 +175,6 @@ - /* This really shouldn't be here. It can go away in 2.5 */ - u_int32_t bank_size; - -- struct module *module; - int (*erase) (struct mtd_info *mtd, struct erase_info *instr); - - /* This stuff for eXecute-In-Place */ -@@ -176,8 +187,8 @@ - int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); - int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); - -- int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, int oobsel); -- int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, int oobsel); -+ int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); -+ int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); - - int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); - int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); -@@ -201,10 +212,10 @@ - */ - int (*readv) (struct mtd_info *mtd, struct iovec *vecs, unsigned long count, loff_t from, size_t *retlen); - int (*readv_ecc) (struct mtd_info *mtd, struct iovec *vecs, unsigned long count, loff_t from, -- size_t *retlen, u_char *eccbuf, int oobsel); -+ size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); - int (*writev) (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen); - int (*writev_ecc) (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, -- size_t *retlen, u_char *eccbuf, int oobsel); -+ size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); - - /* Sync */ - void (*sync) (struct mtd_info *mtd); -@@ -218,6 +229,9 @@ - void (*resume) (struct mtd_info *mtd); - - void *priv; -+ -+ struct module *owner; -+ int usecount; - }; - - -@@ -226,31 +240,15 @@ - extern int add_mtd_device(struct mtd_info *mtd); - extern int del_mtd_device (struct mtd_info *mtd); - --extern struct mtd_info *__get_mtd_device(struct mtd_info *mtd, int num); -- --static inline struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) --{ -- struct mtd_info *ret; -+extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); - -- ret = __get_mtd_device(mtd, num); -- -- if (ret && ret->module && !try_inc_mod_count(ret->module)) -- return NULL; -- -- return ret; --} -- --static inline void put_mtd_device(struct mtd_info *mtd) --{ -- if (mtd->module) -- __MOD_DEC_USE_COUNT(mtd->module); --} -+extern void put_mtd_device(struct mtd_info *mtd); - - - struct mtd_notifier { - void (*add)(struct mtd_info *mtd); - void (*remove)(struct mtd_info *mtd); -- struct mtd_notifier *next; -+ struct list_head list; - }; - - -@@ -263,7 +261,6 @@ - int default_mtd_readv(struct mtd_info *mtd, struct iovec *vecs, - unsigned long count, loff_t from, size_t *retlen); - --#ifndef MTDC - #define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args) - #define MTD_POINT(mtd, a,b,c,d) (*(mtd->point))(mtd, a,b,c, (u_char **)(d)) - #define MTD_UNPOINT(mtd, arg) (*(mtd->unpoint))(mtd, (u_char *)arg) -@@ -276,7 +273,6 @@ - #define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args) - #define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args) - #define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0) --#endif /* MTDC */ - - /* - * Debugging macro and defines -@@ -293,7 +289,8 @@ - printk(KERN_INFO args); \ - } while(0) - #else /* CONFIG_MTD_DEBUG */ --#define DEBUG(n, args...) -+#define DEBUG(n, args...) do { } while(0) -+ - #endif /* CONFIG_MTD_DEBUG */ - - #endif /* __KERNEL__ */ -diff -Nurb linux-mips-2.4.27/include/linux/mtd/nand.h linux/include/linux/mtd/nand.h ---- linux-mips-2.4.27/include/linux/mtd/nand.h 2003-02-26 01:53:51.000000000 +0100 -+++ linux/include/linux/mtd/nand.h 2004-11-19 10:25:12.057175776 +0100 -@@ -2,10 +2,10 @@ - * linux/include/linux/mtd/nand.h - * - * Copyright (c) 2000 David Woodhouse -- * Steven J. Hill -+ * Steven J. Hill - * Thomas Gleixner - * -- * $Id$ -+ * $Id$ - * - * 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 -@@ -49,12 +49,14 @@ - #define __LINUX_MTD_NAND_H - - #include --#include -+#include -+#include - -+struct mtd_info; - /* - * Searches for a NAND device - */ --extern int nand_scan (struct mtd_info *mtd); -+extern int nand_scan (struct mtd_info *mtd, int max_chips); - - /* - * Constants for hardware specific CLE/ALE/NCE function -@@ -65,6 +67,8 @@ - #define NAND_CTL_CLRCLE 4 - #define NAND_CTL_SETALE 5 - #define NAND_CTL_CLRALE 6 -+#define NAND_CTL_SETWP 7 -+#define NAND_CTL_CLRWP 8 - - /* - * Standard NAND flash commands -@@ -160,24 +164,33 @@ - struct nand_chip { - unsigned long IO_ADDR_R; - unsigned long IO_ADDR_W; -- void (*hwcontrol)(int cmd); -- int (*dev_ready)(void); -+ -+ u_char (*read_byte)(struct mtd_info *mtd); -+ void (*write_byte)(struct mtd_info *mtd, u_char byte); -+ -+ void (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len); -+ void (*read_buf)(struct mtd_info *mtd, u_char *buf, int len); -+ int (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len); -+ void (*select_chip)(struct mtd_info *mtd, int chip); -+ int (*block_bad)(struct mtd_info *mtd, unsigned long pos); -+ void (*hwcontrol)(struct mtd_info *mtd, int cmd); -+ int (*dev_ready)(struct mtd_info *mtd); - void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr); - int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state); -- void (*calculate_ecc)(const u_char *dat, u_char *ecc_code); -- int (*correct_data)(u_char *dat, u_char *read_ecc, u_char *calc_ecc); -- void (*enable_hwecc)(int mode); -+ void (*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code); -+ int (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc); -+ void (*enable_hwecc)(struct mtd_info *mtd, int mode); - int eccmode; - int eccsize; - int chip_delay; -+ int chipshift; - spinlock_t chip_lock; - wait_queue_head_t wq; - nand_state_t state; - int page_shift; - u_char *data_buf; - u_char *data_poi; -- u_char *data_cache; -- int cache_page; -+ void *priv; - }; - - /* -@@ -241,34 +254,4 @@ - */ - #define NAND_BADBLOCK_POS 5 - --#define NAND_NONE_OOB 0 --#define NAND_JFFS2_OOB 1 --#define NAND_YAFFS_OOB 2 -- --#define NAND_NOOB_ECCPOS0 0 --#define NAND_NOOB_ECCPOS1 1 --#define NAND_NOOB_ECCPOS2 2 --#define NAND_NOOB_ECCPOS3 3 --#define NAND_NOOB_ECCPOS4 6 --#define NAND_NOOB_ECCPOS5 7 -- --#define NAND_JFFS2_OOB_ECCPOS0 0 --#define NAND_JFFS2_OOB_ECCPOS1 1 --#define NAND_JFFS2_OOB_ECCPOS2 2 --#define NAND_JFFS2_OOB_ECCPOS3 3 --#define NAND_JFFS2_OOB_ECCPOS4 6 --#define NAND_JFFS2_OOB_ECCPOS5 7 -- --#define NAND_YAFFS_OOB_ECCPOS0 8 --#define NAND_YAFFS_OOB_ECCPOS1 9 --#define NAND_YAFFS_OOB_ECCPOS2 10 --#define NAND_YAFFS_OOB_ECCPOS3 13 --#define NAND_YAFFS_OOB_ECCPOS4 14 --#define NAND_YAFFS_OOB_ECCPOS5 15 -- --#define NAND_JFFS2_OOB8_FSDAPOS 6 --#define NAND_JFFS2_OOB16_FSDAPOS 8 --#define NAND_JFFS2_OOB8_FSDALEN 2 --#define NAND_JFFS2_OOB16_FSDALEN 8 -- - #endif /* __LINUX_MTD_NAND_H */ -diff -Nurb linux-mips-2.4.27/include/linux/mtd/nand_ecc.h linux/include/linux/mtd/nand_ecc.h ---- linux-mips-2.4.27/include/linux/mtd/nand_ecc.h 2001-08-22 05:25:12.000000000 +0200 -+++ linux/include/linux/mtd/nand_ecc.h 2004-11-19 10:25:12.058175624 +0100 -@@ -1,9 +1,9 @@ - /* - * drivers/mtd/nand_ecc.h - * -- * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) -+ * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) - * -- * $Id$ -+ * $Id$ - * - * 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 -@@ -12,17 +12,19 @@ - * This file is the header for the ECC algorithm. - */ - --/* -- * Creates non-inverted ECC code from line parity -- */ --void nand_trans_result(u_char reg2, u_char reg3, u_char *ecc_code); -+#ifndef __MTD_NAND_ECC_H__ -+#define __MTD_NAND_ECC_H__ -+ -+struct mtd_info; - - /* - * Calculate 3 byte ECC code for 256 byte block - */ --void nand_calculate_ecc (const u_char *dat, u_char *ecc_code); -+void nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code); - - /* - * Detect and correct a 1 bit error for 256 byte block - */ --int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc); -+int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc); -+ -+#endif /* __MTD_NAND_ECC_H__ */ -diff -Nurb linux-mips-2.4.27/include/linux/mtd/nftl.h linux/include/linux/mtd/nftl.h ---- linux-mips-2.4.27/include/linux/mtd/nftl.h 2003-02-26 01:53:51.000000000 +0100 -+++ linux/include/linux/mtd/nftl.h 2004-11-19 10:25:12.060175320 +0100 -@@ -1,15 +1,14 @@ -- --/* Defines for NAND Flash Translation Layer */ --/* (c) 1999 Machine Vision Holdings, Inc. */ --/* Author: David Woodhouse */ --/* $Id$ */ -+/* -+ * $Id$ -+ * -+ * (C) 1999-2003 David Woodhouse -+ */ - - #ifndef __MTD_NFTL_H__ - #define __MTD_NFTL_H__ - --#ifndef __BOOT__ - #include --#endif -+#include - - /* Block Control Information */ - -@@ -84,8 +83,7 @@ - #define BLOCK_RESERVED 0xfffc /* bios block or bad block */ - - struct NFTLrecord { -- struct mtd_info *mtd; -- struct semaphore mutex; -+ struct mtd_blktrans_dev mbd; - __u16 MediaUnit, SpareMediaUnit; - __u32 EraseSize; - struct NFTLMediaHeader MediaHdr; -@@ -97,7 +95,6 @@ - __u16 lastEUN; /* should be suppressed */ - __u16 numfreeEUNs; - __u16 LastFreeEUN; /* To speed up finding a free EUN */ -- __u32 nr_sects; - int head,sect,cyl; - __u16 *EUNtable; /* [numvunits]: First EUN for each virtual unit */ - __u16 *ReplUnitTable; /* [numEUNs]: ReplUnitNumber for each */ -@@ -114,7 +111,7 @@ - #endif - - #define MAX_NFTLS 16 --#define MAX_SECTORS_PER_UNIT 32 -+#define MAX_SECTORS_PER_UNIT 64 - #define NFTL_PARTN_BITS 4 - - #endif /* __KERNEL__ */ -diff -Nurb linux-mips-2.4.27/include/linux/mtd/partitions.h linux/include/linux/mtd/partitions.h ---- linux-mips-2.4.27/include/linux/mtd/partitions.h 2002-06-27 00:36:47.000000000 +0200 -+++ linux/include/linux/mtd/partitions.h 2004-11-19 10:25:12.061175168 +0100 -@@ -5,7 +5,7 @@ - * - * This code is GPL - * -- * $Id$ -+ * $Id$ - */ - - #ifndef MTD_PARTITIONS_H -@@ -41,6 +41,7 @@ - u_int32_t size; /* partition size */ - u_int32_t offset; /* offset within the master MTD space */ - u_int32_t mask_flags; /* master MTD flags to mask out for this partition */ -+ struct nand_oobinfo *oobsel; /* out of band layout for this partition (NAND only)*/ - struct mtd_info **mtdp; /* pointer to store the MTD object */ - }; - -@@ -49,8 +50,27 @@ - #define MTDPART_SIZ_FULL (0) - - --int add_mtd_partitions(struct mtd_info *, struct mtd_partition *, int); -+int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); - int del_mtd_partitions(struct mtd_info *); - -+/* -+ * Functions dealing with the various ways of partitioning the space -+ */ -+ -+struct mtd_part_parser { -+ struct list_head list; -+ struct module *owner; -+ const char *name; -+ int (*parse_fn)(struct mtd_info *, struct mtd_partition **, unsigned long); -+}; -+ -+extern struct mtd_part_parser *get_partition_parser(const char *name); -+extern int register_mtd_parser(struct mtd_part_parser *parser); -+extern int deregister_mtd_parser(struct mtd_part_parser *parser); -+extern int parse_mtd_partitions(struct mtd_info *master, const char **types, -+ struct mtd_partition **pparts, unsigned long origin); -+ -+#define put_partition_parser(p) do { module_put((p)->owner); } while(0) -+ - #endif - -diff -Nurb linux-mips-2.4.27/include/linux/mtd/physmap.h linux/include/linux/mtd/physmap.h ---- linux-mips-2.4.27/include/linux/mtd/physmap.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/include/linux/mtd/physmap.h 2004-11-19 10:25:12.062175016 +0100 -@@ -0,0 +1,59 @@ -+/* -+ * For boards with physically mapped flash and using -+ * drivers/mtd/maps/physmap.c mapping driver. -+ * -+ * Copyright (C) 2003 MontaVista Software Inc. -+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the 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_MTD_PHYSMAP__ -+ -+#include -+ -+#if defined(CONFIG_MTD_PHYSMAP) -+ -+#include -+#include -+#include -+ -+/* -+ * The map_info for physmap. Board can override size, buswidth, phys, -+ * (*set_vpp)(), etc in their initial setup routine. -+ */ -+extern struct map_info physmap_map; -+ -+/* -+ * Board needs to specify the exact mapping during their setup time. -+ */ -+static inline void physmap_configure(unsigned long addr, unsigned long size, int buswidth, void (*set_vpp)(struct map_info *, int) ) -+{ -+ physmap_map.phys = addr; -+ physmap_map.size = size; -+ physmap_map.buswidth = buswidth; -+ physmap_map.set_vpp = set_vpp; -+} -+ -+#if defined(CONFIG_MTD_PARTITIONS) -+ -+/* -+ * Machines that wish to do flash partition may want to call this function in -+ * their setup routine. -+ * -+ * physmap_set_partitions(mypartitions, num_parts); -+ * -+ * Note that one can always override this hard-coded partition with -+ * command line partition (you need to enable CONFIG_MTD_CMDLINE_PARTS). -+ */ -+void physmap_set_partitions(struct mtd_partition *parts, int num_parts); -+ -+#endif /* defined(CONFIG_MTD_PARTITIONS) */ -+#endif /* defined(CONFIG_MTD) */ -+ -+#endif /* __LINUX_MTD_PHYSMAP__ */ -+ -diff -Nurb linux-mips-2.4.27/include/linux/rbtree-24.h linux/include/linux/rbtree-24.h ---- linux-mips-2.4.27/include/linux/rbtree-24.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/include/linux/rbtree-24.h 2004-11-19 10:25:12.143162704 +0100 -@@ -0,0 +1,133 @@ -+/* -+ Red Black Trees -+ (C) 1999 Andrea Arcangeli -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the 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 -+ -+ linux/include/linux/rbtree.h -+ -+ To use rbtrees you'll have to implement your own insert and search cores. -+ This will avoid us to use callbacks and to drop drammatically performances. -+ I know it's not the cleaner way, but in C (not in C++) to get -+ performances and genericity... -+ -+ Some example of insert and search follows here. The search is a plain -+ normal search over an ordered tree. The insert instead must be implemented -+ int two steps: as first thing the code must insert the element in -+ order as a red leaf in the tree, then the support library function -+ rb_insert_color() must be called. Such function will do the -+ not trivial work to rebalance the rbtree if necessary. -+ -+----------------------------------------------------------------------- -+static inline struct page * rb_search_page_cache(struct inode * inode, -+ unsigned long offset) -+{ -+ rb_node_t * n = inode->i_rb_page_cache.rb_node; -+ struct page * page; -+ -+ while (n) -+ { -+ page = rb_entry(n, struct page, rb_page_cache); -+ -+ if (offset < page->offset) -+ n = n->rb_left; -+ else if (offset > page->offset) -+ n = n->rb_right; -+ else -+ return page; -+ } -+ return NULL; -+} -+ -+static inline struct page * __rb_insert_page_cache(struct inode * inode, -+ unsigned long offset, -+ rb_node_t * node) -+{ -+ rb_node_t ** p = &inode->i_rb_page_cache.rb_node; -+ rb_node_t * parent = NULL; -+ struct page * page; -+ -+ while (*p) -+ { -+ parent = *p; -+ page = rb_entry(parent, struct page, rb_page_cache); -+ -+ if (offset < page->offset) -+ p = &(*p)->rb_left; -+ else if (offset > page->offset) -+ p = &(*p)->rb_right; -+ else -+ return page; -+ } -+ -+ rb_link_node(node, parent, p); -+ -+ return NULL; -+} -+ -+static inline struct page * rb_insert_page_cache(struct inode * inode, -+ unsigned long offset, -+ rb_node_t * node) -+{ -+ struct page * ret; -+ if ((ret = __rb_insert_page_cache(inode, offset, node))) -+ goto out; -+ rb_insert_color(node, &inode->i_rb_page_cache); -+ out: -+ return ret; -+} -+----------------------------------------------------------------------- -+*/ -+ -+#ifndef _LINUX_RBTREE_H -+#define _LINUX_RBTREE_H -+ -+#include -+#include -+ -+typedef struct rb_node_s -+{ -+ struct rb_node_s * rb_parent; -+ int rb_color; -+#define RB_RED 0 -+#define RB_BLACK 1 -+ struct rb_node_s * rb_right; -+ struct rb_node_s * rb_left; -+} -+rb_node_t; -+ -+typedef struct rb_root_s -+{ -+ struct rb_node_s * rb_node; -+} -+rb_root_t; -+ -+#define RB_ROOT (rb_root_t) { NULL, } -+#define rb_entry(ptr, type, member) \ -+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) -+ -+extern void rb_insert_color(rb_node_t *, rb_root_t *); -+extern void rb_erase(rb_node_t *, rb_root_t *); -+ -+static inline void rb_link_node(rb_node_t * node, rb_node_t * parent, rb_node_t ** rb_link) -+{ -+ node->rb_parent = parent; -+ node->rb_color = RB_RED; -+ node->rb_left = node->rb_right = NULL; -+ -+ *rb_link = node; -+} -+ -+#endif /* _LINUX_RBTREE_H */ -diff -Nurb linux-mips-2.4.27/include/linux/rbtree.h linux/include/linux/rbtree.h ---- linux-mips-2.4.27/include/linux/rbtree.h 2001-10-19 03:25:03.000000000 +0200 -+++ linux/include/linux/rbtree.h 2004-11-19 10:25:12.148161944 +0100 -@@ -1,133 +1,25 @@ - /* -- Red Black Trees -- (C) 1999 Andrea Arcangeli -+ * 2.5 compatibility -+ * $Id$ -+ */ -+ -+#ifndef __MTD_COMPAT_RBTREE_H__ -+#define __MTD_COMPAT_RBTREE_H__ -+ -+#include -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,40) -+#include_next -+#else -+#define rb_node_s rb_node -+#define rb_root_s rb_root -+ -+#include -+ -+/* Find logical next and previous nodes in a tree */ -+extern struct rb_node *rb_next(struct rb_node *); -+extern struct rb_node *rb_prev(struct rb_node *); -+extern struct rb_node *rb_first(struct rb_root *); -+#endif - -- This program is free software; you can redistribute it and/or modify -- it under the terms of the 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 -- -- linux/include/linux/rbtree.h -- -- To use rbtrees you'll have to implement your own insert and search cores. -- This will avoid us to use callbacks and to drop drammatically performances. -- I know it's not the cleaner way, but in C (not in C++) to get -- performances and genericity... -- -- Some example of insert and search follows here. The search is a plain -- normal search over an ordered tree. The insert instead must be implemented -- int two steps: as first thing the code must insert the element in -- order as a red leaf in the tree, then the support library function -- rb_insert_color() must be called. Such function will do the -- not trivial work to rebalance the rbtree if necessary. -- ------------------------------------------------------------------------- --static inline struct page * rb_search_page_cache(struct inode * inode, -- unsigned long offset) --{ -- rb_node_t * n = inode->i_rb_page_cache.rb_node; -- struct page * page; -- -- while (n) -- { -- page = rb_entry(n, struct page, rb_page_cache); -- -- if (offset < page->offset) -- n = n->rb_left; -- else if (offset > page->offset) -- n = n->rb_right; -- else -- return page; -- } -- return NULL; --} -- --static inline struct page * __rb_insert_page_cache(struct inode * inode, -- unsigned long offset, -- rb_node_t * node) --{ -- rb_node_t ** p = &inode->i_rb_page_cache.rb_node; -- rb_node_t * parent = NULL; -- struct page * page; -- -- while (*p) -- { -- parent = *p; -- page = rb_entry(parent, struct page, rb_page_cache); -- -- if (offset < page->offset) -- p = &(*p)->rb_left; -- else if (offset > page->offset) -- p = &(*p)->rb_right; -- else -- return page; -- } -- -- rb_link_node(node, parent, p); -- -- return NULL; --} -- --static inline struct page * rb_insert_page_cache(struct inode * inode, -- unsigned long offset, -- rb_node_t * node) --{ -- struct page * ret; -- if ((ret = __rb_insert_page_cache(inode, offset, node))) -- goto out; -- rb_insert_color(node, &inode->i_rb_page_cache); -- out: -- return ret; --} ------------------------------------------------------------------------- --*/ -- --#ifndef _LINUX_RBTREE_H --#define _LINUX_RBTREE_H -- --#include --#include -- --typedef struct rb_node_s --{ -- struct rb_node_s * rb_parent; -- int rb_color; --#define RB_RED 0 --#define RB_BLACK 1 -- struct rb_node_s * rb_right; -- struct rb_node_s * rb_left; --} --rb_node_t; -- --typedef struct rb_root_s --{ -- struct rb_node_s * rb_node; --} --rb_root_t; -- --#define RB_ROOT (rb_root_t) { NULL, } --#define rb_entry(ptr, type, member) \ -- ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) -- --extern void rb_insert_color(rb_node_t *, rb_root_t *); --extern void rb_erase(rb_node_t *, rb_root_t *); -- --static inline void rb_link_node(rb_node_t * node, rb_node_t * parent, rb_node_t ** rb_link) --{ -- node->rb_parent = parent; -- node->rb_color = RB_RED; -- node->rb_left = node->rb_right = NULL; -- -- *rb_link = node; --} -- --#endif /* _LINUX_RBTREE_H */ -+#endif /* __MTD_COMPAT_RBTREE_H__ */ -diff -Nurb linux-mips-2.4.27/include/linux/suspend.h linux/include/linux/suspend.h ---- linux-mips-2.4.27/include/linux/suspend.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/include/linux/suspend.h 2004-11-19 10:25:12.150161640 +0100 -@@ -0,0 +1,10 @@ -+/* $Id$ */ -+ -+#ifndef __MTD_COMPAT_VERSION_H__ -+#include -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+#include_next -+#endif -+ -+#endif /* __MTD_COMPAT_VERSION_H__ */ -diff -Nurb linux-mips-2.4.27/include/linux/workqueue.h linux/include/linux/workqueue.h ---- linux-mips-2.4.27/include/linux/workqueue.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/include/linux/workqueue.h 2004-11-19 10:25:12.152161336 +0100 -@@ -0,0 +1,21 @@ -+/* -+ * 2.5 compatibility -+ * $Id$ -+ */ -+ -+#ifndef __MTD_COMPAT_WORKQUEUE_H__ -+#define __MTD_COMPAT_WORKQUEUE_H__ -+ -+#include -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,40) -+#include_next -+#else -+#include -+#define work_struct tq_struct -+#define schedule_work(x) schedule_task(x) -+#define flush_scheduled_work flush_scheduled_tasks -+#define INIT_WORK(x,y,z) INIT_TQUEUE(x,y,z) -+#endif -+ -+#endif /* __MTD_COMPAT_WORKQUEUE_H__ */ diff --git a/linux/linux-mtx-1-2.4.27/02-mtd-mtx-1-map.diff b/linux/linux-mtx-1-2.4.27/02-mtd-mtx-1-map.diff deleted file mode 100644 index ba24bb1381..0000000000 --- a/linux/linux-mtx-1-2.4.27/02-mtd-mtx-1-map.diff +++ /dev/null @@ -1,248 +0,0 @@ -diff -Nurb linux/drivers/mtd/maps/Config.in linux-mips-2.4.24-pre2+mtd-2004-01-27+mtx-map/drivers/mtd/maps/Config.in ---- linux/drivers/mtd/maps/Config.in 2004-11-17 18:17:59.049312400 +0100 -+++ linux-mips-2.4.24-pre2+mtd-2004-01-27+mtx-map/drivers/mtd/maps/Config.in 2004-11-17 18:12:26.000000000 +0100 -@@ -80,6 +80,7 @@ - bool ' Db1x00 boot flash device' CONFIG_MTD_DB1X00_BOOT - bool ' Db1x00 user flash device (2nd bank)' CONFIG_MTD_DB1X00_USER - fi -+ dep_tristate ' MTX-1 flash device' CONFIG_MTD_MTX1 $CONFIG_MIPS_MTX1 - dep_tristate ' Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board' CONFIG_MTD_CSTM_MIPS_IXX $CONFIG_MTD_CFI $CONFIG_MTD_JEDEC $CONFIG_MTD_PARTITIONS - if [ "$CONFIG_MTD_CSTM_MIPS_IXX" = "y" -o "$CONFIG_MTD_CSTM_MIPS_IXX" = "m" ]; then - hex ' Physical start address of flash mapping' CONFIG_MTD_CSTM_MIPS_IXX_START 0x8000000 -diff -Nurb linux/drivers/mtd/maps/Makefile linux-mips-2.4.24-pre2+mtd-2004-01-27+mtx-map/drivers/mtd/maps/Makefile ---- linux/drivers/mtd/maps/Makefile 2004-11-17 18:17:59.051312096 +0100 -+++ linux-mips-2.4.24-pre2+mtd-2004-01-27+mtx-map/drivers/mtd/maps/Makefile 2004-11-17 18:12:26.000000000 +0100 -@@ -49,6 +49,7 @@ - obj-$(CONFIG_MTD_PCI) += pci.o - obj-$(CONFIG_MTD_PB1XXX) += pb1xxx-flash.o - obj-$(CONFIG_MTD_DB1X00) += db1x00-flash.o -+obj-$(CONFIG_MTD_MTX1) += mtx-1.o - obj-$(CONFIG_MTD_LASAT) += lasat.o - obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o - obj-$(CONFIG_MTD_EDB7312) += edb7312.o -diff -Nurb linux/drivers/mtd/maps/mtx-1.c linux-mips-2.4.24-pre2+mtd-2004-01-27+mtx-map/drivers/mtd/maps/mtx-1.c ---- linux/drivers/mtd/maps/mtx-1.c 2004-11-17 18:17:02.689880336 +0100 -+++ linux-mips-2.4.24-pre2+mtd-2004-01-27+mtx-map/drivers/mtd/maps/mtx-1.c 2004-11-17 18:12:26.000000000 +0100 -@@ -1,166 +1,78 @@ - /* - * Flash memory access on 4G Systems MTX-1 board - * -- * (C) 2003 Pete Popov -- * Bruno Randolf -+ * (C) Bruno Randolf (4G Systeme GmbH) - */ - - #include - #include - #include - #include -+#include - - #include - #include - #include - - #include --#include - --#ifdef DEBUG_RW --#define DBG(x...) printk(x) --#else --#define DBG(x...) --#endif -- --#ifdef CONFIG_MIPS_MTX1 - #define WINDOW_ADDR 0x1E000000 - #define WINDOW_SIZE 0x2000000 --#endif -- --__u8 physmap_read8(struct map_info *map, unsigned long ofs) --{ -- __u8 ret; -- ret = __raw_readb(map->map_priv_1 + ofs); -- DBG("read8 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --__u16 physmap_read16(struct map_info *map, unsigned long ofs) --{ -- __u16 ret; -- ret = __raw_readw(map->map_priv_1 + ofs); -- DBG("read16 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --__u32 physmap_read32(struct map_info *map, unsigned long ofs) --{ -- __u32 ret; -- ret = __raw_readl(map->map_priv_1 + ofs); -- DBG("read32 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); -- return ret; --} -- --void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) --{ -- DBG("physmap_copy from %x to %x\n", (unsigned)from, (unsigned)to); -- memcpy_fromio(to, map->map_priv_1 + from, len); --} -- --void physmap_write8(struct map_info *map, __u8 d, unsigned long adr) --{ -- DBG("write8 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writeb(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_write16(struct map_info *map, __u16 d, unsigned long adr) --{ -- DBG("write16 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writew(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_write32(struct map_info *map, __u32 d, unsigned long adr) --{ -- DBG("write32 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); -- __raw_writel(d, map->map_priv_1 + adr); -- mb(); --} -- --void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) --{ -- DBG("physmap_copy_to %x from %x\n", (unsigned)to, (unsigned)from); -- memcpy_toio(map->map_priv_1 + to, from, len); --} -- -- -+#define BUSWIDTH 4 - - static struct map_info mtx1_map = { -- name: "MTX-1 flash", -- read8: physmap_read8, -- read16: physmap_read16, -- read32: physmap_read32, -- copy_from: physmap_copy_from, -- write8: physmap_write8, -- write16: physmap_write16, -- write32: physmap_write32, -- copy_to: physmap_copy_to, -+ .name = "MTX-1 flash", -+ .size = WINDOW_SIZE, -+ .buswidth = BUSWIDTH, -+ .phys = WINDOW_ADDR - }; - -- --static unsigned long flash_size = 0x01000000; --static unsigned char flash_buswidth = 4; - static struct mtd_partition mtx1_partitions[] = { - { -- name: "user fs", -- size: 0x1c00000, -- offset: 0, -+ .name = "user fs", -+ .size = 0x1c00000, -+ .offset = 0, - },{ -- name: "yamon", -- size: 0x0100000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE -+ .name = "yamon", -+ .size = 0x0100000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ - },{ -- name: "raw kernel", -- size: 0x02c0000, -- offset: MTDPART_OFS_APPEND, -+ .name = "raw kernel", -+ .size = 0x02c0000, -+ .offset = MTDPART_OFS_APPEND, - },{ -- name: "yamon env vars", -- size: 0x0040000, -- offset: MTDPART_OFS_APPEND, -- mask_flags: MTD_WRITEABLE -+ .name = "yamon environment", -+ .size = 0x0040000, -+ .offset = MTDPART_OFS_APPEND, -+ .mask_flags = MTD_WRITEABLE /* force read-only */ - } - }; - -- --#define NB_OF(x) (sizeof(x)/sizeof(x[0])) -- --static struct mtd_partition *parsed_parts; - static struct mtd_info *mymtd; - - int __init mtx1_mtd_init(void) - { -- struct mtd_partition *parts; -- int nb_parts = 0; -- char *part_type; -+ printk(KERN_NOTICE "MTX-1 flash: probing %d-bit flash bus at %x\n", -+ mtx1_map.buswidth*8, WINDOW_ADDR); - -- /* Default flash buswidth */ -- mtx1_map.buswidth = flash_buswidth; -+ mtx1_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); -+ if (!mtx1_map.virt) { -+ printk("mtx_mtd_init: failed to ioremap\n"); -+ return -EIO; -+ } -+ -+ simple_map_init(&mtx1_map); - -- /* -- * Static partition definition selection -- */ -- part_type = "static"; -- parts = mtx1_partitions; -- nb_parts = NB_OF(mtx1_partitions); -- mtx1_map.size = flash_size; -- -- /* -- * Now let's probe for the actual flash. Do it here since -- * specific machine settings might have been set above. -- */ -- printk(KERN_NOTICE "MTX-1 flash: probing %d-bit flash bus\n", -- mtx1_map.buswidth*8); -- mtx1_map.map_priv_1 = -- (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); - mymtd = do_map_probe("cfi_probe", &mtx1_map); -- if (!mymtd) return -ENXIO; -- mymtd->module = THIS_MODULE; -+ if (!mymtd) { -+ iounmap(mtx1_map.virt); -+ return -ENXIO; -+ } -+ -+ mymtd->owner = THIS_MODULE; - -- add_mtd_partitions(mymtd, parts, nb_parts); -- return 0; -+ return add_mtd_partitions(mymtd, mtx1_partitions, ARRAY_SIZE(mtx1_partitions)); - } - - static void __exit mtx1_mtd_cleanup(void) -@@ -168,14 +80,14 @@ - if (mymtd) { - del_mtd_partitions(mymtd); - map_destroy(mymtd); -- if (parsed_parts) -- kfree(parsed_parts); - } -+ if (mtx1_map.virt) -+ iounmap(mtx1_map.virt); - } - - module_init(mtx1_mtd_init); - module_exit(mtx1_mtd_cleanup); - --MODULE_AUTHOR("Pete Popov"); -+MODULE_AUTHOR("Bruno Randolf "); - MODULE_DESCRIPTION("MTX-1 CFI map driver"); - MODULE_LICENSE("GPL"); - diff --git a/linux/linux-mtx-1-2.4.27/03-mtd-erase-compiler-bug.diff b/linux/linux-mtx-1-2.4.27/03-mtd-erase-compiler-bug.diff deleted file mode 100644 index 9e310bf327..0000000000 --- a/linux/linux-mtx-1-2.4.27/03-mtd-erase-compiler-bug.diff +++ /dev/null @@ -1,21 +0,0 @@ ---- linux-mips-2.4.24-pre2+mtd-2004-01-27/fs/jffs2/erase.c 2004-11-17 18:17:59.000000000 +0100 -+++ linux/fs/jffs2/erase.c 2004-11-17 18:44:52.260067088 +0100 -@@ -365,11 +365,13 @@ - jeb->dirty_size = 0; - jeb->wasted_size = 0; - } else { -- struct jffs2_unknown_node marker = { -- .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK), -- .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), -- .totlen = cpu_to_je32(c->cleanmarker_size) -- }; -+ /* compiler workaround, structure was not initialized before -+ on mipsel cross compilers -+ fix by Eugene.Wisor@flukenetworks.com */ -+ struct jffs2_unknown_node marker; -+ marker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -+ marker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); -+ marker.totlen = cpu_to_je32(c->cleanmarker_size); - - marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4)); - diff --git a/linux/linux-mtx-1-2.4.27/04-mtx-1-board-reset.diff b/linux/linux-mtx-1-2.4.27/04-mtx-1-board-reset.diff deleted file mode 100644 index 9a13c2a403..0000000000 --- a/linux/linux-mtx-1-2.4.27/04-mtx-1-board-reset.diff +++ /dev/null @@ -1,15 +0,0 @@ ---- linux/arch/mips/au1000/mtx-1/board_setup.c.orig 2004-10-13 19:05:15.340583632 +0200 -+++ linux/arch/mips/au1000/mtx-1/board_setup.c 2004-10-13 19:01:03.402883984 +0200 -@@ -48,6 +48,12 @@ - - extern struct rtc_ops no_rtc_ops; - -+void board_reset (void) -+{ -+ /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ -+ au_writel(0x00000000, 0xAE00001C); -+} -+ - void __init board_setup(void) - { - rtc_ops = &no_rtc_ops; diff --git a/linux/linux-mtx-1-2.4.27/05-mtx-1-pci-irq.diff b/linux/linux-mtx-1-2.4.27/05-mtx-1-pci-irq.diff deleted file mode 100644 index 4fc6b9e667..0000000000 --- a/linux/linux-mtx-1-2.4.27/05-mtx-1-pci-irq.diff +++ /dev/null @@ -1,18 +0,0 @@ -diff -Nurb linux-mips-2.4.27/arch/mips/au1000/mtx-1/irqmap.c linux/arch/mips/au1000/mtx-1/irqmap.c ---- linux-mips-2.4.27/arch/mips/au1000/mtx-1/irqmap.c 2004-04-02 11:04:00.000000000 +0200 -+++ linux/arch/mips/au1000/mtx-1/irqmap.c 2004-11-22 14:15:56.000000000 +0100 -@@ -72,10 +72,10 @@ - * A B C D - */ - { -- {INTA, INTB, INTC, INTD}, /* IDSEL 0 */ -- {INTA, INTB, INTC, INTD}, /* IDSEL 1 */ -- {INTA, INTB, INTC, INTD}, /* IDSEL 2 */ -- {INTA, INTB, INTC, INTD}, /* IDSEL 3 */ -+ {INTA, INTB, INTX, INTX}, /* IDSEL 0 */ -+ {INTB, INTA, INTX, INTX}, /* IDSEL 1 */ -+ {INTC, INTD, INTX, INTX}, /* IDSEL 2 */ -+ {INTD, INTC, INTX, INTX}, /* IDSEL 3 */ - }; - const long min_idsel = 0, max_idsel = 3, irqs_per_slot = 4; - return PCI_IRQ_TABLE_LOOKUP; diff --git a/linux/linux-mtx-1-2.4.27/06-zboot-2.4.26.patch b/linux/linux-mtx-1-2.4.27/06-zboot-2.4.26.patch deleted file mode 100644 index 573aa7f0cf..0000000000 --- a/linux/linux-mtx-1-2.4.27/06-zboot-2.4.26.patch +++ /dev/null @@ -1,5308 +0,0 @@ -diff -Naru linux/arch/mips/Makefile linux.spi/arch/mips/Makefile ---- linux/arch/mips/Makefile 2004-05-06 15:23:41.000000000 -0400 -+++ linux.spi/arch/mips/Makefile 2004-05-11 23:19:24.000000000 -0400 -@@ -29,6 +29,8 @@ - endif - - MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot -+MAKEZBOOT = $(MAKE) -C arch/$(ARCH)/zboot -+BOOT_TARGETS = zImage zImage.initrd zImage.flash - - check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi) - -@@ -757,12 +749,16 @@ - - vmlinux.ecoff: vmlinux - @$(MAKEBOOT) $@ -+ -+$(BOOT_TARGETS): vmlinux -+ @$(MAKEZBOOT) $@ - - vmlinux.srec: vmlinux - @$(MAKEBOOT) $@ - - archclean: - @$(MAKEBOOT) clean -+ @$(MAKEZBOOT) clean - rm -f arch/$(ARCH)/ld.script - $(MAKE) -C arch/$(ARCH)/tools clean - $(MAKE) -C arch/mips/baget clean -diff -Naru linux/arch/mips/zboot/common/au1k_uart.c linux.spi/arch/mips/zboot/common/au1k_uart.c ---- linux/arch/mips/zboot/common/au1k_uart.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/common/au1k_uart.c 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,103 @@ -+/* -+ * BRIEF MODULE DESCRIPTION -+ * Simple Au1000 uart routines. -+ * -+ * Copyright 2001 MontaVista Software Inc. -+ * Author: MontaVista Software, Inc. -+ * ppopov@mvista.com or source@mvista.com -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * THIS 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 "ns16550.h" -+ -+typedef unsigned char uint8; -+typedef unsigned int uint32; -+ -+#define UART16550_BAUD_2400 2400 -+#define UART16550_BAUD_4800 4800 -+#define UART16550_BAUD_9600 9600 -+#define UART16550_BAUD_19200 19200 -+#define UART16550_BAUD_38400 38400 -+#define UART16550_BAUD_57600 57600 -+#define UART16550_BAUD_115200 115200 -+ -+#define UART16550_PARITY_NONE 0 -+#define UART16550_PARITY_ODD 0x08 -+#define UART16550_PARITY_EVEN 0x18 -+#define UART16550_PARITY_MARK 0x28 -+#define UART16550_PARITY_SPACE 0x38 -+ -+#define UART16550_DATA_5BIT 0x0 -+#define UART16550_DATA_6BIT 0x1 -+#define UART16550_DATA_7BIT 0x2 -+#define UART16550_DATA_8BIT 0x3 -+ -+#define UART16550_STOP_1BIT 0x0 -+#define UART16550_STOP_2BIT 0x4 -+ -+/* It would be nice if we had a better way to do this. -+ * It could be a variable defined in one of the board specific files. -+ */ -+#undef UART_BASE -+#ifdef CONFIG_COGENT_CSB250 -+#define UART_BASE UART3_ADDR -+#else -+#define UART_BASE UART0_ADDR -+#endif -+ -+/* memory-mapped read/write of the port */ -+#define UART16550_READ(y) (readl(UART_BASE + y) & 0xff) -+#define UART16550_WRITE(y,z) (writel(z&0xff, UART_BASE + y)) -+ -+/* -+ * We use uart 0, which is already initialized by -+ * yamon. -+ */ -+volatile struct NS16550 * -+serial_init(int chan) -+{ -+ volatile struct NS16550 *com_port; -+ com_port = (struct NS16550 *) UART_BASE; -+ return (com_port); -+} -+ -+void -+serial_putc(volatile struct NS16550 *com_port, unsigned char c) -+{ -+ while ((UART16550_READ(UART_LSR)&0x40) == 0); -+ UART16550_WRITE(UART_TX, c); -+} -+ -+unsigned char -+serial_getc(volatile struct NS16550 *com_port) -+{ -+ while((UART16550_READ(UART_LSR) & 0x1) == 0); -+ return UART16550_READ(UART_RX); -+} -+ -+int -+serial_tstc(volatile struct NS16550 *com_port) -+{ -+ return((UART16550_READ(UART_LSR) & LSR_DR) != 0); -+} -diff -Naru linux/arch/mips/zboot/common/ctype.c linux.spi/arch/mips/zboot/common/ctype.c ---- linux/arch/mips/zboot/common/ctype.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/common/ctype.c 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,35 @@ -+/* -+ * linux/lib/ctype.c -+ * -+ * Copyright (C) 1991, 1992 Linus Torvalds -+ */ -+ -+#include -+ -+unsigned char _ctype[] = { -+_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ -+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ -+_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ -+_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ -+_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ -+_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ -+_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ -+_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ -+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ -+_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ -+_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ -+_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ -+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ -+_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ -+_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ -+_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ -+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ -+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ -+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ -+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ -+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ -+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ -+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ -+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ -+ -+ -diff -Naru linux/arch/mips/zboot/common/dummy.c linux.spi/arch/mips/zboot/common/dummy.c ---- linux/arch/mips/zboot/common/dummy.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/common/dummy.c 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,4 @@ -+int main(void) -+{ -+ return 0; -+} -diff -Naru linux/arch/mips/zboot/common/Makefile linux.spi/arch/mips/zboot/common/Makefile ---- linux/arch/mips/zboot/common/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/common/Makefile 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,27 @@ -+# -+# arch/mips/zboot/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. -+# -+# Tom Rini January 2001 -+# -+ -+.c.s: -+ $(CC) $(CFLAGS) -S -o $*.s $< -+.s.o: -+ $(AS) -o $*.o $< -+.c.o: -+ $(CC) $(CFLAGS) -c -o $*.o $< -+.S.s: -+ $(CPP) $(AFLAGS) -o $*.o $< -+.S.o: -+ $(CC) $(AFLAGS) -c -o $*.o $< -+ -+clean: -+ rm -rf *.o -+ -+OBJCOPY_ARGS = -O elf32-tradlittlemips -+ -+include $(TOPDIR)/Rules.make -diff -Naru linux/arch/mips/zboot/common/misc-common.c linux.spi/arch/mips/zboot/common/misc-common.c ---- linux/arch/mips/zboot/common/misc-common.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/common/misc-common.c 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,437 @@ -+/* -+ * arch/mips/zboot/common/misc-common.c -+ * -+ * Misc. bootloader code (almost) all platforms can use -+ * -+ * Author: Johnnie Peters -+ * Editor: Tom Rini -+ * -+ * Derived from arch/ppc/boot/prep/misc.c -+ * -+ * Ported by Pete Popov to -+ * support mips board(s). I also got rid of the vga console -+ * code. -+ * -+ * Copyright 2000-2001 MontaVista Software Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * THIS 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 "zlib.h" -+#include -+ -+extern char *avail_ram; -+extern char *end_avail; -+extern char _end[]; -+ -+void puts(const char *); -+void putc(const char c); -+void puthex(unsigned long val); -+void _bcopy(char *src, char *dst, int len); -+void gunzip(void *, int, unsigned char *, int *); -+static int _cvt(unsigned long val, char *buf, long radix, char *digits); -+ -+void _vprintk(void(*)(const char), const char *, va_list ap); -+ -+struct NS16550 *com_port; -+ -+int serial_tstc(volatile struct NS16550 *); -+unsigned char serial_getc(volatile struct NS16550 *); -+void serial_putc(volatile struct NS16550 *, unsigned char); -+ -+void pause(void) -+{ -+ puts("pause\n"); -+} -+ -+void exit(void) -+{ -+ puts("exit\n"); -+ while(1); -+} -+ -+int tstc(void) -+{ -+ return (serial_tstc(com_port)); -+} -+ -+int getc(void) -+{ -+ while (1) { -+ if (serial_tstc(com_port)) -+ return (serial_getc(com_port)); -+ } -+} -+ -+void -+putc(const char c) -+{ -+ int x,y; -+ -+ serial_putc(com_port, c); -+ if ( c == '\n' ) -+ serial_putc(com_port, '\r'); -+} -+ -+void puts(const char *s) -+{ -+ char c; -+ while ( ( c = *s++ ) != '\0' ) { -+ serial_putc(com_port, c); -+ if ( c == '\n' ) serial_putc(com_port, '\r'); -+ } -+} -+ -+void error(char *x) -+{ -+ puts("\n\n"); -+ puts(x); -+ puts("\n\n -- System halted"); -+ -+ while(1); /* Halt */ -+} -+ -+void *zalloc(void *x, unsigned items, unsigned size) -+{ -+ void *p = avail_ram; -+ -+ size *= items; -+ size = (size + 7) & -8; -+ avail_ram += size; -+ if (avail_ram > end_avail) { -+ puts("oops... out of memory\n"); -+ pause(); -+ } -+ return p; -+} -+ -+void zfree(void *x, void *addr, unsigned nb) -+{ -+} -+ -+#define HEAD_CRC 2 -+#define EXTRA_FIELD 4 -+#define ORIG_NAME 8 -+#define COMMENT 0x10 -+#define RESERVED 0xe0 -+ -+#define DEFLATED 8 -+ -+void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) -+{ -+ z_stream s; -+ int r, i, flags; -+ -+ /* skip header */ -+ i = 10; -+ flags = src[3]; -+ if (src[2] != DEFLATED || (flags & RESERVED) != 0) { -+ puts("bad gzipped data\n"); -+ exit(); -+ } -+ if ((flags & EXTRA_FIELD) != 0) -+ i = 12 + src[10] + (src[11] << 8); -+ if ((flags & ORIG_NAME) != 0) -+ while (src[i++] != 0) -+ ; -+ if ((flags & COMMENT) != 0) -+ while (src[i++] != 0) -+ ; -+ if ((flags & HEAD_CRC) != 0) -+ i += 2; -+ if (i >= *lenp) { -+ puts("gunzip: ran out of data in header\n"); -+ exit(); -+ } -+ -+ s.zalloc = zalloc; -+ s.zfree = zfree; -+ r = inflateInit2(&s, -MAX_WBITS); -+ if (r != Z_OK) { -+ puts("inflateInit2 returned %d\n"); -+ exit(); -+ } -+ s.next_in = src + i; -+ s.avail_in = *lenp - i; -+ s.next_out = dst; -+ s.avail_out = dstlen; -+ r = inflate(&s, Z_FINISH); -+ if (r != Z_OK && r != Z_STREAM_END) { -+ puts("inflate returned %d\n"); -+ exit(); -+ } -+ *lenp = s.next_out - (unsigned char *) dst; -+ inflateEnd(&s); -+} -+ -+void -+puthex(unsigned long val) -+{ -+ -+ unsigned char buf[10]; -+ int i; -+ for (i = 7; i >= 0; i--) -+ { -+ buf[i] = "0123456789ABCDEF"[val & 0x0F]; -+ val >>= 4; -+ } -+ buf[8] = '\0'; -+ puts(buf); -+} -+ -+#define FALSE 0 -+#define TRUE 1 -+ -+void -+_printk(char const *fmt, ...) -+{ -+ va_list ap; -+ -+ va_start(ap, fmt); -+ _vprintk(putc, fmt, ap); -+ va_end(ap); -+ return; -+} -+ -+#define is_digit(c) ((c >= '0') && (c <= '9')) -+ -+void -+_vprintk(void(*putc)(const char), const char *fmt0, va_list ap) -+{ -+ char c, sign, *cp = 0; -+ int left_prec, right_prec, zero_fill, length = 0, pad, pad_on_right; -+ char buf[32]; -+ long val; -+ while ((c = *fmt0++)) -+ { -+ if (c == '%') -+ { -+ c = *fmt0++; -+ left_prec = right_prec = pad_on_right = 0; -+ if (c == '-') -+ { -+ c = *fmt0++; -+ pad_on_right++; -+ } -+ if (c == '0') -+ { -+ zero_fill = TRUE; -+ c = *fmt0++; -+ } else -+ { -+ zero_fill = FALSE; -+ } -+ while (is_digit(c)) -+ { -+ left_prec = (left_prec * 10) + (c - '0'); -+ c = *fmt0++; -+ } -+ if (c == '.') -+ { -+ c = *fmt0++; -+ zero_fill++; -+ while (is_digit(c)) -+ { -+ right_prec = (right_prec * 10) + (c - '0'); -+ c = *fmt0++; -+ } -+ } else -+ { -+ right_prec = left_prec; -+ } -+ sign = '\0'; -+ switch (c) -+ { -+ case 'd': -+ case 'x': -+ case 'X': -+ val = va_arg(ap, long); -+ switch (c) -+ { -+ case 'd': -+ if (val < 0) -+ { -+ sign = '-'; -+ val = -val; -+ } -+ length = _cvt(val, buf, 10, "0123456789"); -+ break; -+ case 'x': -+ length = _cvt(val, buf, 16, "0123456789abcdef"); -+ break; -+ case 'X': -+ length = _cvt(val, buf, 16, "0123456789ABCDEF"); -+ break; -+ } -+ cp = buf; -+ break; -+ case 's': -+ cp = va_arg(ap, char *); -+ length = strlen(cp); -+ break; -+ case 'c': -+ c = va_arg(ap, long /*char*/); -+ (*putc)(c); -+ continue; -+ default: -+ (*putc)('?'); -+ } -+ pad = left_prec - length; -+ if (sign != '\0') -+ { -+ pad--; -+ } -+ if (zero_fill) -+ { -+ c = '0'; -+ if (sign != '\0') -+ { -+ (*putc)(sign); -+ sign = '\0'; -+ } -+ } else -+ { -+ c = ' '; -+ } -+ if (!pad_on_right) -+ { -+ while (pad-- > 0) -+ { -+ (*putc)(c); -+ } -+ } -+ if (sign != '\0') -+ { -+ (*putc)(sign); -+ } -+ while (length-- > 0) -+ { -+ (*putc)(c = *cp++); -+ if (c == '\n') -+ { -+ (*putc)('\r'); -+ } -+ } -+ if (pad_on_right) -+ { -+ while (pad-- > 0) -+ { -+ (*putc)(c); -+ } -+ } -+ } else -+ { -+ (*putc)(c); -+ if (c == '\n') -+ { -+ (*putc)('\r'); -+ } -+ } -+ } -+} -+ -+int -+_cvt(unsigned long val, char *buf, long radix, char *digits) -+{ -+ char temp[80]; -+ char *cp = temp; -+ int length = 0; -+ if (val == 0) -+ { /* Special case */ -+ *cp++ = '0'; -+ } else -+ while (val) -+ { -+ *cp++ = digits[val % radix]; -+ val /= radix; -+ } -+ while (cp != temp) -+ { -+ *buf++ = *--cp; -+ length++; -+ } -+ *buf = '\0'; -+ return (length); -+} -+ -+void -+_dump_buf_with_offset(unsigned char *p, int s, unsigned char *base) -+{ -+ int i, c; -+ if ((unsigned int)s > (unsigned int)p) -+ { -+ s = (unsigned int)s - (unsigned int)p; -+ } -+ while (s > 0) -+ { -+ if (base) -+ { -+ _printk("%06X: ", (int)p - (int)base); -+ } else -+ { -+ _printk("%06X: ", p); -+ } -+ for (i = 0; i < 16; i++) -+ { -+ if (i < s) -+ { -+ _printk("%02X", p[i] & 0xFF); -+ } else -+ { -+ _printk(" "); -+ } -+ if ((i % 2) == 1) _printk(" "); -+ if ((i % 8) == 7) _printk(" "); -+ } -+ _printk(" |"); -+ for (i = 0; i < 16; i++) -+ { -+ if (i < s) -+ { -+ c = p[i] & 0xFF; -+ if ((c < 0x20) || (c >= 0x7F)) c = '.'; -+ } else -+ { -+ c = ' '; -+ } -+ _printk("%c", c); -+ } -+ _printk("|\n"); -+ s -= 16; -+ p += 16; -+ } -+} -+ -+void -+_dump_buf(unsigned char *p, int s) -+{ -+ _printk("\n"); -+ _dump_buf_with_offset(p, s, 0); -+} -+ -+/* -+ * Local variables: -+ * c-indent-level: 8 -+ * c-basic-offset: 8 -+ * tab-width: 8 -+ * End: -+ */ -diff -Naru linux/arch/mips/zboot/common/misc-simple.c linux.spi/arch/mips/zboot/common/misc-simple.c ---- linux/arch/mips/zboot/common/misc-simple.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/common/misc-simple.c 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,127 @@ -+/* -+ * arch/mips/zboot/common/misc-simple.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 -+ * your serial console. If a machine meets these requirements, it can quite -+ * likely use this code during boot. -+ * -+ * Author: Matt Porter -+ * Derived from arch/ppc/boot/prep/misc.c -+ * -+ * Copyright 2001 MontaVista Software 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 "zlib.h" -+ -+extern struct NS16550 *com_port; -+ -+char *avail_ram; -+char *end_avail; -+extern char _end[]; -+char *zimage_start; -+ -+#ifdef CONFIG_CMDLINE -+#define CMDLINE CONFIG_CMDLINE -+#else -+#define CMDLINE "" -+#endif -+char cmd_preset[] = CMDLINE; -+char cmd_buf[256]; -+char *cmd_line = cmd_buf; -+ -+/* The linker tells us where the image is. -+*/ -+extern unsigned char __image_begin, __image_end; -+extern unsigned char __ramdisk_begin, __ramdisk_end; -+unsigned long initrd_size; -+ -+extern void puts(const char *); -+extern void putc(const char c); -+extern void puthex(unsigned long val); -+extern void *memcpy(void * __dest, __const void * __src, -+ __kernel_size_t __n); -+extern void gunzip(void *, int, unsigned char *, int *); -+extern void udelay(long delay); -+extern int tstc(void); -+extern int getc(void); -+extern volatile struct NS16550 *serial_init(int chan); -+ -+void -+decompress_kernel(unsigned long load_addr, int num_words, -+ unsigned long cksum, unsigned long *sp) -+{ -+ int timer = 0; -+ extern unsigned long start; -+ char *cp, ch; -+ int i; -+ int zimage_size; -+ -+ com_port = (struct NS16550 *)serial_init(0); -+ -+ initrd_size = (unsigned long)(&__ramdisk_end) - -+ (unsigned long)(&__ramdisk_begin); -+ -+ /* -+ * Reveal where we were loaded at and where we -+ * were relocated to. -+ */ -+ puts("loaded at: "); puthex(load_addr); -+ puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n"); -+ if ( (unsigned long)load_addr != (unsigned long)&start ) -+ { -+ puts("relocated to: "); puthex((unsigned long)&start); -+ puts(" "); -+ puthex((unsigned long)((unsigned long)&start + (4*num_words))); -+ puts("\n"); -+ } -+ -+ /* -+ * We link ourself to an arbitrary low address. When we run, we -+ * relocate outself to that address. __image_being points to -+ * the part of the image where the zImage is. -- Tom -+ */ -+ zimage_start = (char *)(unsigned long)(&__image_begin); -+ zimage_size = (unsigned long)(&__image_end) - -+ (unsigned long)(&__image_begin); -+ -+ /* -+ * The zImage and initrd will be between start and _end, so they've -+ * already been moved once. We're good to go now. -- Tom -+ */ -+ puts("zimage at: "); puthex((unsigned long)zimage_start); -+ puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); -+ puts("\n"); -+ -+ if ( initrd_size ) { -+ puts("initrd at: "); -+ puthex((unsigned long)(&__ramdisk_begin)); -+ puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n"); -+ } -+ -+ /* assume the chunk below 8M is free */ -+ avail_ram = (char *)AVAIL_RAM_START; -+ end_avail = (char *)AVAIL_RAM_END; -+ -+ /* Display standard Linux/MIPS boot prompt for kernel args */ -+ puts("Uncompressing Linux at load address "); -+ puthex(LOADADDR); -+ puts("\n"); -+ /* I don't like this hard coded gunzip size (fixme) */ -+ gunzip((void *)LOADADDR, 0x400000, zimage_start, &zimage_size); -+ puts("Now booting the kernel\n"); -+} -diff -Naru linux/arch/mips/zboot/common/no_initrd.c linux.spi/arch/mips/zboot/common/no_initrd.c ---- linux/arch/mips/zboot/common/no_initrd.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/common/no_initrd.c 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,2 @@ -+char initrd_data[1]; -+int initrd_len = 0; -diff -Naru linux/arch/mips/zboot/common/ns16550.c linux.spi/arch/mips/zboot/common/ns16550.c ---- linux/arch/mips/zboot/common/ns16550.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/common/ns16550.c 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,57 @@ -+/* -+ * NS16550 support -+ */ -+ -+#include -+#include -+#include "ns16550.h" -+ -+typedef struct NS16550 *NS16550_t; -+ -+const NS16550_t COM_PORTS[] = { (NS16550_t) COM1, -+ (NS16550_t) COM2, -+ (NS16550_t) COM3, -+ (NS16550_t) COM4 }; -+ -+volatile struct NS16550 * -+serial_init(int chan) -+{ -+ volatile struct NS16550 *com_port; -+ com_port = (struct NS16550 *) COM_PORTS[chan]; -+ /* See if port is present */ -+ com_port->lcr = 0x00; -+ com_port->ier = 0xFF; -+#if 0 -+ if (com_port->ier != 0x0F) return ((struct NS16550 *)0); -+#endif -+ com_port->ier = 0x00; -+ com_port->lcr = 0x80; /* Access baud rate */ -+#ifdef CONFIG_SERIAL_CONSOLE_NONSTD -+ com_port->dll = (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD); -+ com_port->dlm = (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD) >> 8; -+#endif -+ com_port->lcr = 0x03; /* 8 data, 1 stop, no parity */ -+ com_port->mcr = 0x03; /* RTS/DTR */ -+ com_port->fcr = 0x07; /* Clear & enable FIFOs */ -+ return (com_port); -+} -+ -+void -+serial_putc(volatile struct NS16550 *com_port, unsigned char c) -+{ -+ while ((com_port->lsr & LSR_THRE) == 0) ; -+ com_port->thr = c; -+} -+ -+unsigned char -+serial_getc(volatile struct NS16550 *com_port) -+{ -+ while ((com_port->lsr & LSR_DR) == 0) ; -+ return (com_port->rbr); -+} -+ -+int -+serial_tstc(volatile struct NS16550 *com_port) -+{ -+ return ((com_port->lsr & LSR_DR) != 0); -+} -diff -Naru linux/arch/mips/zboot/common/string.c linux.spi/arch/mips/zboot/common/string.c ---- linux/arch/mips/zboot/common/string.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/common/string.c 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,497 @@ -+/* -+ * linux/lib/string.c -+ * -+ * Copyright (C) 1991, 1992 Linus Torvalds -+ */ -+ -+/* -+ * stupid library routines.. The optimized versions should generally be found -+ * as inline code in -+ * -+ * These are buggy as well.. -+ * -+ * * Fri Jun 25 1999, Ingo Oeser -+ * - Added strsep() which will replace strtok() soon (because strsep() is -+ * reentrant and should be faster). Use only strsep() in new code, please. -+ */ -+ -+#include -+#include -+#include -+ -+/** -+ * strnicmp - Case insensitive, length-limited string comparison -+ * @s1: One string -+ * @s2: The other string -+ * @len: the maximum number of characters to compare -+ */ -+int strnicmp(const char *s1, const char *s2, size_t len) -+{ -+ /* Yes, Virginia, it had better be unsigned */ -+ unsigned char c1, c2; -+ -+ c1 = 0; c2 = 0; -+ if (len) { -+ do { -+ c1 = *s1; c2 = *s2; -+ s1++; s2++; -+ if (!c1) -+ break; -+ if (!c2) -+ break; -+ if (c1 == c2) -+ continue; -+ c1 = tolower(c1); -+ c2 = tolower(c2); -+ if (c1 != c2) -+ break; -+ } while (--len); -+ } -+ return (int)c1 - (int)c2; -+} -+ -+char * ___strtok; -+ -+#ifndef __HAVE_ARCH_STRCPY -+/** -+ * strcpy - Copy a %NUL terminated string -+ * @dest: Where to copy the string to -+ * @src: Where to copy the string from -+ */ -+char * strcpy(char * dest,const char *src) -+{ -+ char *tmp = dest; -+ -+ while ((*dest++ = *src++) != '\0') -+ /* nothing */; -+ return tmp; -+} -+#endif -+ -+#ifndef __HAVE_ARCH_STRNCPY -+/** -+ * strncpy - Copy a length-limited, %NUL-terminated string -+ * @dest: Where to copy the string to -+ * @src: Where to copy the string from -+ * @count: The maximum number of bytes to copy -+ * -+ * Note that unlike userspace strncpy, this does not %NUL-pad the buffer. -+ * However, the result is not %NUL-terminated if the source exceeds -+ * @count bytes. -+ */ -+char * strncpy(char * dest,const char *src,size_t count) -+{ -+ char *tmp = dest; -+ -+ while (count-- && (*dest++ = *src++) != '\0') -+ /* nothing */; -+ -+ return tmp; -+} -+#endif -+ -+/** -+ * strcat - Append one %NUL-terminated string to another -+ * @dest: The string to be appended to -+ * @src: The string to append to it -+ */ -+char * strcat(char * dest, const char * src) -+{ -+ char *tmp = dest; -+ -+ while (*dest) -+ dest++; -+ while ((*dest++ = *src++) != '\0') -+ ; -+ -+ return tmp; -+} -+ -+/** -+ * strncat - Append a length-limited, %NUL-terminated string to another -+ * @dest: The string to be appended to -+ * @src: The string to append to it -+ * @count: The maximum numbers of bytes to copy -+ * -+ * Note that in contrast to strncpy, strncat ensures the result is -+ * terminated. -+ */ -+char * strncat(char *dest, const char *src, size_t count) -+{ -+ char *tmp = dest; -+ -+ if (count) { -+ while (*dest) -+ dest++; -+ while ((*dest++ = *src++)) { -+ if (--count == 0) { -+ *dest = '\0'; -+ break; -+ } -+ } -+ } -+ -+ return tmp; -+} -+ -+#ifndef __HAVE_ARCH_STRCMP -+/** -+ * strcmp - Compare two strings -+ * @cs: One string -+ * @ct: Another string -+ */ -+int strcmp(const char * cs,const char * ct) -+{ -+ register signed char __res; -+ -+ while (1) { -+ if ((__res = *cs - *ct++) != 0 || !*cs++) -+ break; -+ } -+ -+ return __res; -+} -+#endif -+ -+#ifndef __HAVE_ARCH_STRNCMP -+/** -+ * strncmp - Compare two length-limited strings -+ * @cs: One string -+ * @ct: Another string -+ * @count: The maximum number of bytes to compare -+ */ -+int strncmp(const char * cs,const char * ct,size_t count) -+{ -+ register signed char __res = 0; -+ -+ while (count) { -+ if ((__res = *cs - *ct++) != 0 || !*cs++) -+ break; -+ count--; -+ } -+ -+ return __res; -+} -+#endif -+ -+/** -+ * strchr - Find the first occurrence of a character in a string -+ * @s: The string to be searched -+ * @c: The character to search for -+ */ -+char * strchr(const char * s, int c) -+{ -+ for(; *s != (char) c; ++s) -+ if (*s == '\0') -+ return NULL; -+ return (char *) s; -+} -+ -+/** -+ * strrchr - Find the last occurrence of a character in a string -+ * @s: The string to be searched -+ * @c: The character to search for -+ */ -+char * strrchr(const char * s, int c) -+{ -+ const char *p = s + strlen(s); -+ do { -+ if (*p == (char)c) -+ return (char *)p; -+ } while (--p >= s); -+ return NULL; -+} -+ -+/** -+ * strlen - Find the length of a string -+ * @s: The string to be sized -+ */ -+size_t strlen(const char * s) -+{ -+ const char *sc; -+ -+ for (sc = s; *sc != '\0'; ++sc) -+ /* nothing */; -+ return sc - s; -+} -+ -+/** -+ * strnlen - Find the length of a length-limited string -+ * @s: The string to be sized -+ * @count: The maximum number of bytes to search -+ */ -+size_t strnlen(const char * s, size_t count) -+{ -+ const char *sc; -+ -+ for (sc = s; count-- && *sc != '\0'; ++sc) -+ /* nothing */; -+ return sc - s; -+} -+ -+/** -+ * strspn - Calculate the length of the initial substring of @s which only -+ * contain letters in @accept -+ * @s: The string to be searched -+ * @accept: The string to search for -+ */ -+size_t strspn(const char *s, const char *accept) -+{ -+ const char *p; -+ const char *a; -+ size_t count = 0; -+ -+ for (p = s; *p != '\0'; ++p) { -+ for (a = accept; *a != '\0'; ++a) { -+ if (*p == *a) -+ break; -+ } -+ if (*a == '\0') -+ return count; -+ ++count; -+ } -+ -+ return count; -+} -+ -+/** -+ * strpbrk - Find the first occurrence of a set of characters -+ * @cs: The string to be searched -+ * @ct: The characters to search for -+ */ -+char * strpbrk(const char * cs,const char * ct) -+{ -+ const char *sc1,*sc2; -+ -+ for( sc1 = cs; *sc1 != '\0'; ++sc1) { -+ for( sc2 = ct; *sc2 != '\0'; ++sc2) { -+ if (*sc1 == *sc2) -+ return (char *) sc1; -+ } -+ } -+ return NULL; -+} -+ -+/** -+ * strtok - Split a string into tokens -+ * @s: The string to be searched -+ * @ct: The characters to search for -+ * -+ * WARNING: strtok is deprecated, use strsep instead. -+ */ -+char * strtok(char * s,const char * ct) -+{ -+ char *sbegin, *send; -+ -+ sbegin = s ? s : ___strtok; -+ if (!sbegin) { -+ return NULL; -+ } -+ sbegin += strspn(sbegin,ct); -+ if (*sbegin == '\0') { -+ ___strtok = NULL; -+ return( NULL ); -+ } -+ send = strpbrk( sbegin, ct); -+ if (send && *send != '\0') -+ *send++ = '\0'; -+ ___strtok = send; -+ return (sbegin); -+} -+ -+/** -+ * strsep - Split a string into tokens -+ * @s: The string to be searched -+ * @ct: The characters to search for -+ * -+ * strsep() updates @s to point after the token, ready for the next call. -+ * -+ * It returns empty tokens, too, behaving exactly like the libc function -+ * of that name. In fact, it was stolen from glibc2 and de-fancy-fied. -+ * Same semantics, slimmer shape. ;) -+ */ -+char * strsep(char **s, const char *ct) -+{ -+ char *sbegin = *s, *end; -+ -+ if (sbegin == NULL) -+ return NULL; -+ -+ end = strpbrk(sbegin, ct); -+ if (end) -+ *end++ = '\0'; -+ *s = end; -+ -+ return sbegin; -+} -+ -+/** -+ * memset - Fill a region of memory with the given value -+ * @s: Pointer to the start of the area. -+ * @c: The byte to fill the area with -+ * @count: The size of the area. -+ * -+ * Do not use memset() to access IO space, use memset_io() instead. -+ */ -+void * memset(void * s,int c, size_t count) -+{ -+ char *xs = (char *) s; -+ -+ while (count--) -+ *xs++ = c; -+ -+ return s; -+} -+ -+/** -+ * bcopy - Copy one area of memory to another -+ * @src: Where to copy from -+ * @dest: Where to copy to -+ * @count: The size of the area. -+ * -+ * Note that this is the same as memcpy(), with the arguments reversed. -+ * memcpy() is the standard, bcopy() is a legacy BSD function. -+ * -+ * You should not use this function to access IO space, use memcpy_toio() -+ * or memcpy_fromio() instead. -+ */ -+char * bcopy(const char * src, char * dest, int count) -+{ -+ char *tmp = dest; -+ -+ while (count--) -+ *tmp++ = *src++; -+ -+ return dest; -+} -+ -+/** -+ * memcpy - Copy one area of memory to another -+ * @dest: Where to copy to -+ * @src: Where to copy from -+ * @count: The size of the area. -+ * -+ * You should not use this function to access IO space, use memcpy_toio() -+ * or memcpy_fromio() instead. -+ */ -+void * memcpy(void * dest,const void *src,size_t count) -+{ -+ char *tmp = (char *) dest, *s = (char *) src; -+ -+ while (count--) -+ *tmp++ = *s++; -+ -+ return dest; -+} -+ -+/** -+ * memmove - Copy one area of memory to another -+ * @dest: Where to copy to -+ * @src: Where to copy from -+ * @count: The size of the area. -+ * -+ * Unlike memcpy(), memmove() copes with overlapping areas. -+ */ -+void * memmove(void * dest,const void *src,size_t count) -+{ -+ char *tmp, *s; -+ -+ if (dest <= src) { -+ tmp = (char *) dest; -+ s = (char *) src; -+ while (count--) -+ *tmp++ = *s++; -+ } -+ else { -+ tmp = (char *) dest + count; -+ s = (char *) src + count; -+ while (count--) -+ *--tmp = *--s; -+ } -+ -+ return dest; -+} -+ -+/** -+ * memcmp - Compare two areas of memory -+ * @cs: One area of memory -+ * @ct: Another area of memory -+ * @count: The size of the area. -+ */ -+int memcmp(const void * cs,const void * ct,size_t count) -+{ -+ const unsigned char *su1, *su2; -+ signed char res = 0; -+ -+ for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) -+ if ((res = *su1 - *su2) != 0) -+ break; -+ return res; -+} -+ -+#ifndef __HAVE_ARCH_MEMSCAN -+/** -+ * memscan - Find a character in an area of memory. -+ * @addr: The memory area -+ * @c: The byte to search for -+ * @size: The size of the area. -+ * -+ * returns the address of the first occurrence of @c, or 1 byte past -+ * the area if @c is not found -+ */ -+void * memscan(void * addr, int c, size_t size) -+{ -+ unsigned char * p = (unsigned char *) addr; -+ unsigned char * e = p + size; -+ -+ while (p != e) { -+ if (*p == c) -+ return (void *) p; -+ p++; -+ } -+ -+ return (void *) p; -+} -+#endif -+ -+/** -+ * strstr - Find the first substring in a %NUL terminated string -+ * @s1: The string to be searched -+ * @s2: The string to search for -+ */ -+char * strstr(const char * s1,const char * s2) -+{ -+ int l1, l2; -+ -+ l2 = strlen(s2); -+ if (!l2) -+ return (char *) s1; -+ l1 = strlen(s1); -+ while (l1 >= l2) { -+ l1--; -+ if (!memcmp(s1,s2,l2)) -+ return (char *) s1; -+ s1++; -+ } -+ return NULL; -+} -+ -+/** -+ * memchr - Find a character in an area of memory. -+ * @s: The memory area -+ * @c: The byte to search for -+ * @n: The size of the area. -+ * -+ * returns the address of the first occurrence of @c, or %NULL -+ * if @c is not found -+ */ -+void *memchr(const void *s, int c, size_t n) -+{ -+ const unsigned char *p = s; -+ while (n-- != 0) { -+ if ((unsigned char)c == *p++) { -+ return (void *)(p-1); -+ } -+ } -+ return NULL; -+} -diff -Naru linux/arch/mips/zboot/csb250/head.S linux.spi/arch/mips/zboot/csb250/head.S ---- linux/arch/mips/zboot/csb250/head.S 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/csb250/head.S 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,157 @@ -+/* -+ * arch/mips/kernel/head.S -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 1994, 1995 Waldorf Electronics -+ * Written by Ralf Baechle and Andreas Busse -+ * Copyright (C) 1995 - 1999 Ralf Baechle -+ * Copyright (C) 1996 Paul M. Antoine -+ * Modified for DECStation and hence R3000 support by Paul M. Antoine -+ * Further modifications by David S. Miller and Harald Koerfgen -+ * Copyright (C) 1999 Silicon Graphics, Inc. -+ * -+ * Head.S contains the MIPS exception handler and startup code. -+ * -+ ************************************************************************** -+ * 9 Nov, 2000. -+ * Added Cache Error exception handler and SBDDP EJTAG debug exception. -+ * -+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com -+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. -+ ************************************************************************** -+ */ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define IndexInvalidate_I 0x00 -+#define IndexWriteBack_D 0x01 -+ -+ .set noreorder -+ .cprestore -+ LEAF(start) -+start: -+ bal locate -+ nop -+ -+ .globl asize /* Someday we'll put the initrd info here. */ -+asize: .word 0 -+ .word 0 -+ .word 0 -+ .word 0 -+ -+locate: -+ subu s8, ra, 8 /* Where we were loaded */ -+ la sp, (.stack + 8192) -+ -+ move s0, a0 /* Save boot rom start args */ -+ move s1, a1 -+ move s2, a2 -+ move s3, a3 -+ -+ la a0, start /* Where we were linked to run */ -+ -+ move a1, s8 -+ la a2, _edata -+ subu t1, a2, a0 -+ srl t1, t1, 2 -+ -+ /* copy text section */ -+ li t0, 0 -+1: lw v0, 0(a1) -+ nop -+ sw v0, 0(a0) -+ xor t0, t0, v0 -+ addu a0, 4 -+ bne a2, a0, 1b -+ addu a1, 4 -+ -+ /* Clear BSS */ -+ la a0, _edata -+ la a2, _end -+2: sw zero, 0(a0) -+ bne a2, a0, 2b -+ addu a0, 4 -+ -+ /* push the D-Cache and invalidate I-Cache */ -+ li k0, 0x80000000 # start address -+ li k1, 0x80004000 # end address (16KB I-Cache) -+ subu k1, 128 -+ -+1: -+ .set mips3 -+ cache IndexWriteBack_D, 0(k0) -+ cache IndexWriteBack_D, 32(k0) -+ cache IndexWriteBack_D, 64(k0) -+ cache IndexWriteBack_D, 96(k0) -+ cache IndexInvalidate_I, 0(k0) -+ cache IndexInvalidate_I, 32(k0) -+ cache IndexInvalidate_I, 64(k0) -+ cache IndexInvalidate_I, 96(k0) -+ .set mips0 -+ -+ bne k0, k1, 1b -+ addu k0, k0, 128 -+ /* done */ -+ -+/* move a0, s8 /* load address */ -+ subu a0, s8, 0x1000 /* load address */ -+ move a1, t1 /* length in words */ -+ move a2, t0 /* checksum */ -+ move a3, sp -+ -+ la ra, 1f -+ la k0, decompress_kernel -+ jr k0 -+ nop -+1: -+ -+ la a2, __ramdisk_begin -+ la a3, initrd_size -+ lw a0, 0(a2) -+ lw a1, 0(a3) -+ li k0, KERNEL_ENTRY -+ jr k0 -+ nop -+3: -+ b 3b -+ END(start) -+ -+ LEAF(udelay) -+udelay: -+ END(udelay) -+ -+ -+ LEAF(FlushCache) -+ li k0, 0x80000000 # start address -+ li k1, 0x80004000 # end address (16KB I-Cache) -+ subu k1, 128 -+ -+1: -+ .set mips3 -+ cache IndexWriteBack_D, 0(k0) -+ cache IndexWriteBack_D, 32(k0) -+ cache IndexWriteBack_D, 64(k0) -+ cache IndexWriteBack_D, 96(k0) -+ cache IndexInvalidate_I, 0(k0) -+ cache IndexInvalidate_I, 32(k0) -+ cache IndexInvalidate_I, 64(k0) -+ cache IndexInvalidate_I, 96(k0) -+ .set mips0 -+ -+ bne k0, k1, 1b -+ addu k0, k0, 128 -+ jr ra -+ nop -+ END(FlushCache) -+ -+ .comm .stack,4096*2,4 -diff -Naru linux/arch/mips/zboot/csb250/Makefile linux.spi/arch/mips/zboot/csb250/Makefile ---- linux/arch/mips/zboot/csb250/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/csb250/Makefile 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,90 @@ -+# arch/mips/zboot/pb1xxx/Makefile -+# -+# Makefile for Cogent CSB250 Au1500 board. -+# All of the boot loader code was derived from the ppc -+# boot code. -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by the -+# Free Software Foundation; either version 2 of the License, or (at your -+# option) any later version. -+ -+.c.s: -+ $(CC) $(CFLAGS) -S -o $*.s $< -+.s.o: -+ $(AS) -o $*.o $< -+.c.o: -+ $(CC) $(CFLAGS) -D__BOOTER__ -c -o $*.o $< -+.S.s: -+ $(CPP) $(AFLAGS) -o $*.o $< -+.S.o: -+ $(CC) $(AFLAGS) -c -o $*.o $< -+ -+######################################################################### -+# START BOARD SPECIFIC VARIABLES -+BNAME=csb250 -+ -+# These two variables control where the zImage is stored -+# in flash and loaded in memory. It only controls how the srec -+# file is generated, the code is the same. -+RAM_RUN_ADDR = 0x80a00000 -+FLASH_LOAD_ADDR = 0xBFD00000 -+ -+# These two variables specify the free ram region -+# that can be used for temporary malloc area -+AVAIL_RAM_START=0x80400000 -+AVAIL_RAM_END=0x80800000 -+ -+# This one must match the LOADADDR in arch/mips/Makefile! -+LOADADDR=0x80100000 -+# END BOARD SPECIFIC VARIABLES -+######################################################################### -+ -+OBJECTS := head.o ../common/misc-common.o ../common/misc-simple.o \ -+ ../common/au1k_uart.o ../common/string.o ../common/ctype.o -+LIBS := ../lib/zlib.a -+ -+ENTRY := ../utils/entry -+OFFSET := ../utils/offset -+SIZE := ../utils/size -+ -+LD_ARGS := -T ../ld.script -Ttext $(RAM_RUN_ADDR) -Bstatic -+OBJCOPY_ARGS = -O elf32-tradbigmips -+ -+all: zImage -+ -+clean: -+ rm -rf *.o vmlinux* zvmlinux.* ../images/*.srec -+ -+head.o: head.S $(TOPDIR)/vmlinux -+ $(CC) $(AFLAGS) \ -+ -DKERNEL_ENTRY=$(shell sh $(ENTRY) $(NM) $(TOPDIR)/vmlinux ) \ -+ -c -o $*.o $< -+ -+../common/misc-simple.o: -+ $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \ -+ -DAVAIL_RAM_START=$(AVAIL_RAM_START) \ -+ -DAVAIL_RAM_END=$(AVAIL_RAM_END) \ -+ -DLOADADDR=$(LOADADDR) \ -+ -DZIMAGE_SIZE=0 -c -o $@ $*.c -+ -+zvmlinux: $(OBJECTS) $(LIBS) ../ld.script ../images/vmlinux.gz ../common/dummy.o -+ $(OBJCOPY) \ -+ --add-section=.image=../images/vmlinux.gz \ -+ --set-section-flags=.image=contents,alloc,load,readonly,data \ -+ ../common/dummy.o image.o -+ $(LD) $(LD_ARGS) -o $@ $(OBJECTS) image.o $(LIBS) -+ $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr \ -+ -R .initrd -R .sysmap -+ -+# Here we manipulate the image in order to get it the necessary -+# srecord file we need. -+zImage: zvmlinux -+ mv zvmlinux ../images/zImage.$(BNAME) -+ $(OBJCOPY) -O binary ../images/zImage.$(BNAME) ../images/$(BNAME).bin -+ -+zImage.flash: zImage -+ $(OBJCOPY) -O srec --adjust-vma 0x3ed00000 \ -+ ../images/zImage.$(BNAME) ../images/$(BNAME).flash.srec -+ -+include $(TOPDIR)/Rules.make -diff -Naru linux/arch/mips/zboot/images/Makefile linux.spi/arch/mips/zboot/images/Makefile ---- linux/arch/mips/zboot/images/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/images/Makefile 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,10 @@ -+ -+include $(TOPDIR)/Rules.make -+ -+vmlinux.gz: $(TOPDIR)/vmlinux -+ $(OBJCOPY) -S -O binary $(TOPDIR)/vmlinux vmlinux -+ gzip -vf vmlinux -+ -+clean: -+ rm -f vmlinux.* zImage.* -+ -diff -Naru linux/arch/mips/zboot/include/nonstdio.h linux.spi/arch/mips/zboot/include/nonstdio.h ---- linux/arch/mips/zboot/include/nonstdio.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/include/nonstdio.h 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,18 @@ -+/* -+ * Copyright (C) Paul Mackerras 1997. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+typedef int FILE; -+extern FILE *stdin, *stdout; -+#define NULL ((void *)0) -+#define EOF (-1) -+#define fopen(n, m) NULL -+#define fflush(f) 0 -+#define fclose(f) 0 -+extern char *fgets(); -+ -+#define perror(s) printf("%s: no files!\n", (s)) -diff -Naru linux/arch/mips/zboot/include/ns16550.h linux.spi/arch/mips/zboot/include/ns16550.h ---- linux/arch/mips/zboot/include/ns16550.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/include/ns16550.h 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,49 @@ -+/* -+ * NS16550 Serial Port -+ */ -+ -+/* -+ * Figure out which file will have the definitons of COMx -+ */ -+#if !defined(CONFIG_AU1X00_UART) -+#error no serial.h -+#endif -+ -+/* Some machines have their uart registers 16 bytes apart. Most don't. -+ * TODO: Make this work like drivers/char/serial does - Tom */ -+#if !defined(UART_REG_PAD) -+#define UART_REG_PAD(x) -+#endif -+ -+struct NS16550 -+ { -+ unsigned char rbr; /* 0 */ -+ UART_REG_PAD(rbr) -+ unsigned char ier; /* 1 */ -+ UART_REG_PAD(ier) -+ unsigned char fcr; /* 2 */ -+ UART_REG_PAD(fcr) -+ unsigned char lcr; /* 3 */ -+ UART_REG_PAD(lcr) -+ unsigned char mcr; /* 4 */ -+ UART_REG_PAD(mcr) -+ unsigned char lsr; /* 5 */ -+ UART_REG_PAD(lsr) -+ unsigned char msr; /* 6 */ -+ UART_REG_PAD(msr) -+ unsigned char scr; /* 7 */ -+ }; -+ -+#define thr rbr -+#define iir fcr -+#define dll rbr -+#define dlm ier -+ -+#define LSR_DR 0x01 /* Data ready */ -+#define LSR_OE 0x02 /* Overrun */ -+#define LSR_PE 0x04 /* Parity error */ -+#define LSR_FE 0x08 /* Framing error */ -+#define LSR_BI 0x10 /* Break */ -+#define LSR_THRE 0x20 /* Xmit holding register empty */ -+#define LSR_TEMT 0x40 /* Xmitter empty */ -+#define LSR_ERR 0x80 /* Error */ -diff -Naru linux/arch/mips/zboot/include/pb1000_serial.h linux.spi/arch/mips/zboot/include/pb1000_serial.h ---- linux/arch/mips/zboot/include/pb1000_serial.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/include/pb1000_serial.h 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,20 @@ -+/* -+ * arch/ppc/boot/include/sandpoint_serial.h -+ * -+ * Location of the COM ports on Motorola SPS Sandpoint machines -+ * -+ * Author: Mark A. Greer -+ * mgreer@mvista.com -+ * -+ * Copyright 2001 MontaVista Software 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. -+ */ -+ -+#define COM1 0xfe0003f8 -+#define COM2 0xfe0002f8 -+#define COM3 0x00000000 /* No COM3 */ -+#define COM4 0x00000000 /* No COM4 */ -diff -Naru linux/arch/mips/zboot/include/zlib.h linux.spi/arch/mips/zboot/include/zlib.h ---- linux/arch/mips/zboot/include/zlib.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/include/zlib.h 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,432 @@ -+/* $Id$ */ -+ -+/* -+ * This file is derived from zlib.h and zconf.h from the zlib-0.95 -+ * distribution by Jean-loup Gailly and Mark Adler, with some additions -+ * by Paul Mackerras to aid in implementing Deflate compression and -+ * decompression for PPP packets. -+ */ -+ -+/* -+ * ==FILEVERSION 960122== -+ * -+ * This marker is used by the Linux installation script to determine -+ * whether an up-to-date version of this file is already installed. -+ */ -+ -+/* zlib.h -- interface of the 'zlib' general purpose compression library -+ version 0.95, Aug 16th, 1995. -+ -+ Copyright (C) 1995 Jean-loup Gailly and Mark Adler -+ -+ This software is provided 'as-is', without any express or implied -+ warranty. In no event will the authors be held liable for any damages -+ arising from the use of this software. -+ -+ Permission is granted to anyone to use this software for any purpose, -+ including commercial applications, and to alter it and redistribute it -+ freely, subject to the following restrictions: -+ -+ 1. The origin of this software must not be misrepresented; you must not -+ claim that you wrote the original software. If you use this software -+ in a product, an acknowledgment in the product documentation would be -+ appreciated but is not required. -+ 2. Altered source versions must be plainly marked as such, and must not be -+ misrepresented as being the original software. -+ 3. This notice may not be removed or altered from any source distribution. -+ -+ Jean-loup Gailly Mark Adler -+ gzip@prep.ai.mit.edu madler@alumni.caltech.edu -+ */ -+ -+#ifndef _ZLIB_H -+#define _ZLIB_H -+ -+/* #include "zconf.h" */ /* included directly here */ -+ -+/* zconf.h -- configuration of the zlib compression library -+ * Copyright (C) 1995 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */ -+ -+/* -+ The library does not install any signal handler. It is recommended to -+ add at least a handler for SIGSEGV when decompressing; the library checks -+ the consistency of the input data whenever possible but may go nuts -+ for some forms of corrupted input. -+ */ -+ -+/* -+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more -+ * than 64k bytes at a time (needed on systems with 16-bit int). -+ * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints -+ * at addresses which are not a multiple of their size. -+ * Under DOS, -DFAR=far or -DFAR=__far may be needed. -+ */ -+ -+#ifndef STDC -+# if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus) -+# define STDC -+# endif -+#endif -+ -+#ifdef __MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */ -+# include -+#endif -+ -+/* Maximum value for memLevel in deflateInit2 */ -+#ifndef MAX_MEM_LEVEL -+# ifdef MAXSEG_64K -+# define MAX_MEM_LEVEL 8 -+# else -+# define MAX_MEM_LEVEL 9 -+# endif -+#endif -+ -+#ifndef FAR -+# define FAR -+#endif -+ -+/* Maximum value for windowBits in deflateInit2 and inflateInit2 */ -+#ifndef MAX_WBITS -+# define MAX_WBITS 15 /* 32K LZ77 window */ -+#endif -+ -+/* The memory requirements for deflate are (in bytes): -+ 1 << (windowBits+2) + 1 << (memLevel+9) -+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) -+ plus a few kilobytes for small objects. For example, if you want to reduce -+ the default memory requirements from 256K to 128K, compile with -+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" -+ Of course this will generally degrade compression (there's no free lunch). -+ -+ The memory requirements for inflate are (in bytes) 1 << windowBits -+ that is, 32K for windowBits=15 (default value) plus a few kilobytes -+ for small objects. -+*/ -+ -+ /* Type declarations */ -+ -+#ifndef OF /* function prototypes */ -+# ifdef STDC -+# define OF(args) args -+# else -+# define OF(args) () -+# endif -+#endif -+ -+typedef unsigned char Byte; /* 8 bits */ -+typedef unsigned int uInt; /* 16 bits or more */ -+typedef unsigned long uLong; /* 32 bits or more */ -+ -+typedef Byte FAR Bytef; -+typedef char FAR charf; -+typedef int FAR intf; -+typedef uInt FAR uIntf; -+typedef uLong FAR uLongf; -+ -+#ifdef STDC -+ typedef void FAR *voidpf; -+ typedef void *voidp; -+#else -+ typedef Byte FAR *voidpf; -+ typedef Byte *voidp; -+#endif -+ -+/* end of original zconf.h */ -+ -+#define ZLIB_VERSION "0.95P" -+ -+/* -+ The 'zlib' compression library provides in-memory compression and -+ decompression functions, including integrity checks of the uncompressed -+ data. This version of the library supports only one compression method -+ (deflation) but other algorithms may be added later and will have the same -+ stream interface. -+ -+ For compression the application must provide the output buffer and -+ may optionally provide the input buffer for optimization. For decompression, -+ the application must provide the input buffer and may optionally provide -+ the output buffer for optimization. -+ -+ Compression can be done in a single step if the buffers are large -+ enough (for example if an input file is mmap'ed), or can be done by -+ repeated calls of the compression function. In the latter case, the -+ application must provide more input and/or consume the output -+ (providing more output space) before each call. -+*/ -+ -+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -+typedef void (*free_func) OF((voidpf opaque, voidpf address, uInt nbytes)); -+ -+struct internal_state; -+ -+typedef struct z_stream_s { -+ Bytef *next_in; /* next input byte */ -+ uInt avail_in; /* number of bytes available at next_in */ -+ uLong total_in; /* total nb of input bytes read so far */ -+ -+ Bytef *next_out; /* next output byte should be put there */ -+ uInt avail_out; /* remaining free space at next_out */ -+ uLong total_out; /* total nb of bytes output so far */ -+ -+ char *msg; /* last error message, NULL if no error */ -+ struct internal_state FAR *state; /* not visible by applications */ -+ -+ alloc_func zalloc; /* used to allocate the internal state */ -+ free_func zfree; /* used to free the internal state */ -+ voidp opaque; /* private data object passed to zalloc and zfree */ -+ -+ Byte data_type; /* best guess about the data type: ascii or binary */ -+ -+} z_stream; -+ -+/* -+ The application must update next_in and avail_in when avail_in has -+ dropped to zero. It must update next_out and avail_out when avail_out -+ has dropped to zero. The application must initialize zalloc, zfree and -+ opaque before calling the init function. All other fields are set by the -+ compression library and must not be updated by the application. -+ -+ The opaque value provided by the application will be passed as the first -+ parameter for calls of zalloc and zfree. This can be useful for custom -+ memory management. The compression library attaches no meaning to the -+ opaque value. -+ -+ zalloc must return Z_NULL if there is not enough memory for the object. -+ On 16-bit systems, the functions zalloc and zfree must be able to allocate -+ exactly 65536 bytes, but will not be required to allocate more than this -+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, -+ pointers returned by zalloc for objects of exactly 65536 bytes *must* -+ have their offset normalized to zero. The default allocation function -+ provided by this library ensures this (see zutil.c). To reduce memory -+ requirements and avoid any allocation of 64K objects, at the expense of -+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). -+ -+ The fields total_in and total_out can be used for statistics or -+ progress reports. After compression, total_in holds the total size of -+ the uncompressed data and may be saved for use in the decompressor -+ (particularly if the decompressor wants to decompress everything in -+ a single step). -+*/ -+ -+ /* constants */ -+ -+#define Z_NO_FLUSH 0 -+#define Z_PARTIAL_FLUSH 1 -+#define Z_FULL_FLUSH 2 -+#define Z_SYNC_FLUSH 3 /* experimental: partial_flush + byte align */ -+#define Z_FINISH 4 -+#define Z_PACKET_FLUSH 5 -+/* See deflate() below for the usage of these constants */ -+ -+#define Z_OK 0 -+#define Z_STREAM_END 1 -+#define Z_ERRNO (-1) -+#define Z_STREAM_ERROR (-2) -+#define Z_DATA_ERROR (-3) -+#define Z_MEM_ERROR (-4) -+#define Z_BUF_ERROR (-5) -+/* error codes for the compression/decompression functions */ -+ -+#define Z_BEST_SPEED 1 -+#define Z_BEST_COMPRESSION 9 -+#define Z_DEFAULT_COMPRESSION (-1) -+/* compression levels */ -+ -+#define Z_FILTERED 1 -+#define Z_HUFFMAN_ONLY 2 -+#define Z_DEFAULT_STRATEGY 0 -+ -+#define Z_BINARY 0 -+#define Z_ASCII 1 -+#define Z_UNKNOWN 2 -+/* Used to set the data_type field */ -+ -+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ -+ -+extern char *zlib_version; -+/* The application can compare zlib_version and ZLIB_VERSION for consistency. -+ If the first character differs, the library code actually used is -+ not compatible with the zlib.h header file used by the application. -+ */ -+ -+ /* basic functions */ -+ -+extern int inflateInit OF((z_stream *strm)); -+/* -+ Initializes the internal stream state for decompression. The fields -+ zalloc and zfree must be initialized before by the caller. If zalloc and -+ zfree are set to Z_NULL, inflateInit updates them to use default allocation -+ functions. -+ -+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory. msg is set to null if there is no error message. -+ inflateInit does not perform any decompression: this will be done by -+ inflate(). -+*/ -+ -+ -+extern int inflate OF((z_stream *strm, int flush)); -+/* -+ Performs one or both of the following actions: -+ -+ - Decompress more input starting at next_in and update next_in and avail_in -+ accordingly. If not all input can be processed (because there is not -+ enough room in the output buffer), next_in is updated and processing -+ will resume at this point for the next call of inflate(). -+ -+ - Provide more output starting at next_out and update next_out and avail_out -+ accordingly. inflate() always provides as much output as possible -+ (until there is no more input data or no more space in the output buffer). -+ -+ Before the call of inflate(), the application should ensure that at least -+ one of the actions is possible, by providing more input and/or consuming -+ more output, and updating the next_* and avail_* values accordingly. -+ The application can consume the uncompressed output when it wants, for -+ example when the output buffer is full (avail_out == 0), or after each -+ call of inflate(). -+ -+ If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH, -+ inflate flushes as much output as possible to the output buffer. The -+ flushing behavior of inflate is not specified for values of the flush -+ parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the -+ current implementation actually flushes as much output as possible -+ anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data -+ has been consumed, it is expecting to see the length field of a stored -+ block; if not, it returns Z_DATA_ERROR. -+ -+ inflate() should normally be called until it returns Z_STREAM_END or an -+ error. However if all decompression is to be performed in a single step -+ (a single call of inflate), the parameter flush should be set to -+ Z_FINISH. In this case all pending input is processed and all pending -+ output is flushed; avail_out must be large enough to hold all the -+ uncompressed data. (The size of the uncompressed data may have been saved -+ by the compressor for this purpose.) The next operation on this stream must -+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH -+ is never required, but can be used to inform inflate that a faster routine -+ may be used for the single inflate() call. -+ -+ inflate() returns Z_OK if some progress has been made (more input -+ processed or more output produced), Z_STREAM_END if the end of the -+ compressed data has been reached and all uncompressed output has been -+ produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if -+ the stream structure was inconsistent (for example if next_in or next_out -+ was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no -+ progress is possible or if there was not enough room in the output buffer -+ when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then -+ call inflateSync to look for a good compression block. */ -+ -+ -+extern int inflateEnd OF((z_stream *strm)); -+/* -+ All dynamically allocated data structures for this stream are freed. -+ This function discards any unprocessed input and does not flush any -+ pending output. -+ -+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state -+ was inconsistent. In the error case, msg may be set but then points to a -+ static string (which must not be deallocated). -+*/ -+ -+ /* advanced functions */ -+ -+extern int inflateInit2 OF((z_stream *strm, -+ int windowBits)); -+/* -+ This is another version of inflateInit with more compression options. The -+ fields next_out, zalloc and zfree must be initialized before by the caller. -+ -+ The windowBits parameter is the base two logarithm of the maximum window -+ size (the size of the history buffer). It should be in the range 8..15 for -+ this version of the library (the value 16 will be allowed soon). The -+ default value is 15 if inflateInit is used instead. If a compressed stream -+ with a larger window size is given as input, inflate() will return with -+ the error code Z_DATA_ERROR instead of trying to allocate a larger window. -+ -+ If next_out is not null, the library will use this buffer for the history -+ buffer; the buffer must either be large enough to hold the entire output -+ data, or have at least 1<msg=z_errmsg[1-err], err) -+/* To be used only when the state is known to be valid */ -+ -+#ifndef NULL -+#define NULL ((void *) 0) -+#endif -+ -+ /* common constants */ -+ -+#define DEFLATED 8 -+ -+#ifndef DEF_WBITS -+# define DEF_WBITS MAX_WBITS -+#endif -+/* default windowBits for decompression. MAX_WBITS is for compression only */ -+ -+#if MAX_MEM_LEVEL >= 8 -+# define DEF_MEM_LEVEL 8 -+#else -+# define DEF_MEM_LEVEL MAX_MEM_LEVEL -+#endif -+/* default memLevel */ -+ -+#define STORED_BLOCK 0 -+#define STATIC_TREES 1 -+#define DYN_TREES 2 -+/* The three kinds of block type */ -+ -+#define MIN_MATCH 3 -+#define MAX_MATCH 258 -+/* The minimum and maximum match lengths */ -+ -+ /* functions */ -+ -+#include -+#define zmemcpy memcpy -+#define zmemzero(dest, len) memset(dest, 0, len) -+ -+/* Diagnostic functions */ -+#ifdef DEBUG_ZLIB -+# include -+# ifndef verbose -+# define verbose 0 -+# endif -+# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -+# define Trace(x) fprintf x -+# define Tracev(x) {if (verbose) fprintf x ;} -+# define Tracevv(x) {if (verbose>1) fprintf x ;} -+# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -+# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} -+#else -+# define Assert(cond,msg) -+# define Trace(x) -+# define Tracev(x) -+# define Tracevv(x) -+# define Tracec(c,x) -+# define Tracecv(c,x) -+#endif -+ -+ -+typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len)); -+ -+/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */ -+/* void zcfree OF((voidpf opaque, voidpf ptr)); */ -+ -+#define ZALLOC(strm, items, size) \ -+ (*((strm)->zalloc))((strm)->opaque, (items), (size)) -+#define ZFREE(strm, addr, size) \ -+ (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size)) -+#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);} -+ -+/* deflate.h -- internal compression state -+ * Copyright (C) 1995 Jean-loup Gailly -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+/*+++++*/ -+/* infblock.h -- header to use infblock.c -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+struct inflate_blocks_state; -+typedef struct inflate_blocks_state FAR inflate_blocks_statef; -+ -+local inflate_blocks_statef * inflate_blocks_new OF(( -+ z_stream *z, -+ check_func c, /* check function */ -+ uInt w)); /* window size */ -+ -+local int inflate_blocks OF(( -+ inflate_blocks_statef *, -+ z_stream *, -+ int)); /* initial return code */ -+ -+local void inflate_blocks_reset OF(( -+ inflate_blocks_statef *, -+ z_stream *, -+ uLongf *)); /* check value on output */ -+ -+local int inflate_blocks_free OF(( -+ inflate_blocks_statef *, -+ z_stream *, -+ uLongf *)); /* check value on output */ -+ -+local int inflate_addhistory OF(( -+ inflate_blocks_statef *, -+ z_stream *)); -+ -+local int inflate_packet_flush OF(( -+ inflate_blocks_statef *)); -+ -+/*+++++*/ -+/* inftrees.h -- header to use inftrees.c -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+/* Huffman code lookup table entry--this entry is four bytes for machines -+ that have 16-bit pointers (e.g. PC's in the small or medium model). */ -+ -+typedef struct inflate_huft_s FAR inflate_huft; -+ -+struct inflate_huft_s { -+ union { -+ struct { -+ Byte Exop; /* number of extra bits or operation */ -+ Byte Bits; /* number of bits in this code or subcode */ -+ } what; -+ uInt Nalloc; /* number of these allocated here */ -+ Bytef *pad; /* pad structure to a power of 2 (4 bytes for */ -+ } word; /* 16-bit, 8 bytes for 32-bit machines) */ -+ union { -+ uInt Base; /* literal, length base, or distance base */ -+ inflate_huft *Next; /* pointer to next level of table */ -+ } more; -+}; -+ -+#ifdef DEBUG_ZLIB -+ local uInt inflate_hufts; -+#endif -+ -+local int inflate_trees_bits OF(( -+ uIntf *, /* 19 code lengths */ -+ uIntf *, /* bits tree desired/actual depth */ -+ inflate_huft * FAR *, /* bits tree result */ -+ z_stream *)); /* for zalloc, zfree functions */ -+ -+local int inflate_trees_dynamic OF(( -+ uInt, /* number of literal/length codes */ -+ uInt, /* number of distance codes */ -+ uIntf *, /* that many (total) code lengths */ -+ uIntf *, /* literal desired/actual bit depth */ -+ uIntf *, /* distance desired/actual bit depth */ -+ inflate_huft * FAR *, /* literal/length tree result */ -+ inflate_huft * FAR *, /* distance tree result */ -+ z_stream *)); /* for zalloc, zfree functions */ -+ -+local int inflate_trees_fixed OF(( -+ uIntf *, /* literal desired/actual bit depth */ -+ uIntf *, /* distance desired/actual bit depth */ -+ inflate_huft * FAR *, /* literal/length tree result */ -+ inflate_huft * FAR *)); /* distance tree result */ -+ -+local int inflate_trees_free OF(( -+ inflate_huft *, /* tables to free */ -+ z_stream *)); /* for zfree function */ -+ -+ -+/*+++++*/ -+/* infcodes.h -- header to use infcodes.c -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+struct inflate_codes_state; -+typedef struct inflate_codes_state FAR inflate_codes_statef; -+ -+local inflate_codes_statef *inflate_codes_new OF(( -+ uInt, uInt, -+ inflate_huft *, inflate_huft *, -+ z_stream *)); -+ -+local int inflate_codes OF(( -+ inflate_blocks_statef *, -+ z_stream *, -+ int)); -+ -+local void inflate_codes_free OF(( -+ inflate_codes_statef *, -+ z_stream *)); -+ -+ -+/*+++++*/ -+/* inflate.c -- zlib interface to inflate modules -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* inflate private state */ -+struct internal_state { -+ -+ /* mode */ -+ enum { -+ METHOD, /* waiting for method byte */ -+ FLAG, /* waiting for flag byte */ -+ BLOCKS, /* decompressing blocks */ -+ CHECK4, /* four check bytes to go */ -+ CHECK3, /* three check bytes to go */ -+ CHECK2, /* two check bytes to go */ -+ CHECK1, /* one check byte to go */ -+ DONE, /* finished check, done */ -+ BAD} /* got an error--stay here */ -+ mode; /* current inflate mode */ -+ -+ /* mode dependent information */ -+ union { -+ uInt method; /* if FLAGS, method byte */ -+ struct { -+ uLong was; /* computed check value */ -+ uLong need; /* stream check value */ -+ } check; /* if CHECK, check values to compare */ -+ uInt marker; /* if BAD, inflateSync's marker bytes count */ -+ } sub; /* submode */ -+ -+ /* mode independent information */ -+ int nowrap; /* flag for no wrapper */ -+ uInt wbits; /* log2(window size) (8..15, defaults to 15) */ -+ inflate_blocks_statef -+ *blocks; /* current inflate_blocks state */ -+ -+}; -+ -+ -+int inflateReset(z) -+z_stream *z; -+{ -+ uLong c; -+ -+ if (z == Z_NULL || z->state == Z_NULL) -+ return Z_STREAM_ERROR; -+ z->total_in = z->total_out = 0; -+ z->msg = Z_NULL; -+ z->state->mode = z->state->nowrap ? BLOCKS : METHOD; -+ inflate_blocks_reset(z->state->blocks, z, &c); -+ Trace((stderr, "inflate: reset\n")); -+ return Z_OK; -+} -+ -+ -+int inflateEnd(z) -+z_stream *z; -+{ -+ uLong c; -+ -+ if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) -+ return Z_STREAM_ERROR; -+ if (z->state->blocks != Z_NULL) -+ inflate_blocks_free(z->state->blocks, z, &c); -+ ZFREE(z, z->state, sizeof(struct internal_state)); -+ z->state = Z_NULL; -+ Trace((stderr, "inflate: end\n")); -+ return Z_OK; -+} -+ -+ -+int inflateInit2(z, w) -+z_stream *z; -+int w; -+{ -+ /* initialize state */ -+ if (z == Z_NULL) -+ return Z_STREAM_ERROR; -+/* if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */ -+/* if (z->zfree == Z_NULL) z->zfree = zcfree; */ -+ if ((z->state = (struct internal_state FAR *) -+ ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) -+ return Z_MEM_ERROR; -+ z->state->blocks = Z_NULL; -+ -+ /* handle undocumented nowrap option (no zlib header or check) */ -+ z->state->nowrap = 0; -+ if (w < 0) -+ { -+ w = - w; -+ z->state->nowrap = 1; -+ } -+ -+ /* set window size */ -+ if (w < 8 || w > 15) -+ { -+ inflateEnd(z); -+ return Z_STREAM_ERROR; -+ } -+ z->state->wbits = (uInt)w; -+ -+ /* create inflate_blocks state */ -+ if ((z->state->blocks = -+ inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w)) -+ == Z_NULL) -+ { -+ inflateEnd(z); -+ return Z_MEM_ERROR; -+ } -+ Trace((stderr, "inflate: allocated\n")); -+ -+ /* reset state */ -+ inflateReset(z); -+ return Z_OK; -+} -+ -+ -+int inflateInit(z) -+z_stream *z; -+{ -+ return inflateInit2(z, DEF_WBITS); -+} -+ -+ -+#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;} -+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) -+ -+int inflate(z, f) -+z_stream *z; -+int f; -+{ -+ int r; -+ uInt b; -+ -+ if (z == Z_NULL || z->next_in == Z_NULL) -+ return Z_STREAM_ERROR; -+ r = Z_BUF_ERROR; -+ while (1) switch (z->state->mode) -+ { -+ case METHOD: -+ NEEDBYTE -+ if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED) -+ { -+ z->state->mode = BAD; -+ z->msg = "unknown compression method"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ if ((z->state->sub.method >> 4) + 8 > z->state->wbits) -+ { -+ z->state->mode = BAD; -+ z->msg = "invalid window size"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ z->state->mode = FLAG; -+ case FLAG: -+ NEEDBYTE -+ if ((b = NEXTBYTE) & 0x20) -+ { -+ z->state->mode = BAD; -+ z->msg = "invalid reserved bit"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ if (((z->state->sub.method << 8) + b) % 31) -+ { -+ z->state->mode = BAD; -+ z->msg = "incorrect header check"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ Trace((stderr, "inflate: zlib header ok\n")); -+ z->state->mode = BLOCKS; -+ case BLOCKS: -+ r = inflate_blocks(z->state->blocks, z, r); -+ if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0) -+ r = inflate_packet_flush(z->state->blocks); -+ if (r == Z_DATA_ERROR) -+ { -+ z->state->mode = BAD; -+ z->state->sub.marker = 0; /* can try inflateSync */ -+ break; -+ } -+ if (r != Z_STREAM_END) -+ return r; -+ r = Z_OK; -+ inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); -+ if (z->state->nowrap) -+ { -+ z->state->mode = DONE; -+ break; -+ } -+ z->state->mode = CHECK4; -+ case CHECK4: -+ NEEDBYTE -+ z->state->sub.check.need = (uLong)NEXTBYTE << 24; -+ z->state->mode = CHECK3; -+ case CHECK3: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE << 16; -+ z->state->mode = CHECK2; -+ case CHECK2: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE << 8; -+ z->state->mode = CHECK1; -+ case CHECK1: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE; -+ -+ if (z->state->sub.check.was != z->state->sub.check.need) -+ { -+ z->state->mode = BAD; -+ z->msg = "incorrect data check"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ Trace((stderr, "inflate: zlib check ok\n")); -+ z->state->mode = DONE; -+ case DONE: -+ return Z_STREAM_END; -+ case BAD: -+ return Z_DATA_ERROR; -+ default: -+ return Z_STREAM_ERROR; -+ } -+ -+ empty: -+ if (f != Z_PACKET_FLUSH) -+ return r; -+ z->state->mode = BAD; -+ z->state->sub.marker = 0; /* can try inflateSync */ -+ return Z_DATA_ERROR; -+} -+ -+/* -+ * This subroutine adds the data at next_in/avail_in to the output history -+ * without performing any output. The output buffer must be "caught up"; -+ * i.e. no pending output (hence s->read equals s->write), and the state must -+ * be BLOCKS (i.e. we should be willing to see the start of a series of -+ * BLOCKS). On exit, the output will also be caught up, and the checksum -+ * will have been updated if need be. -+ */ -+ -+int inflateIncomp(z) -+z_stream *z; -+{ -+ if (z->state->mode != BLOCKS) -+ return Z_DATA_ERROR; -+ return inflate_addhistory(z->state->blocks, z); -+} -+ -+ -+int inflateSync(z) -+z_stream *z; -+{ -+ uInt n; /* number of bytes to look at */ -+ Bytef *p; /* pointer to bytes */ -+ uInt m; /* number of marker bytes found in a row */ -+ uLong r, w; /* temporaries to save total_in and total_out */ -+ -+ /* set up */ -+ if (z == Z_NULL || z->state == Z_NULL) -+ return Z_STREAM_ERROR; -+ if (z->state->mode != BAD) -+ { -+ z->state->mode = BAD; -+ z->state->sub.marker = 0; -+ } -+ if ((n = z->avail_in) == 0) -+ return Z_BUF_ERROR; -+ p = z->next_in; -+ m = z->state->sub.marker; -+ -+ /* search */ -+ while (n && m < 4) -+ { -+ if (*p == (Byte)(m < 2 ? 0 : 0xff)) -+ m++; -+ else if (*p) -+ m = 0; -+ else -+ m = 4 - m; -+ p++, n--; -+ } -+ -+ /* restore */ -+ z->total_in += p - z->next_in; -+ z->next_in = p; -+ z->avail_in = n; -+ z->state->sub.marker = m; -+ -+ /* return no joy or set up to restart on a new block */ -+ if (m != 4) -+ return Z_DATA_ERROR; -+ r = z->total_in; w = z->total_out; -+ inflateReset(z); -+ z->total_in = r; z->total_out = w; -+ z->state->mode = BLOCKS; -+ return Z_OK; -+} -+ -+#undef NEEDBYTE -+#undef NEXTBYTE -+ -+/*+++++*/ -+/* infutil.h -- types and macros common to blocks and codes -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+/* inflate blocks semi-private state */ -+struct inflate_blocks_state { -+ -+ /* mode */ -+ enum { -+ TYPE, /* get type bits (3, including end bit) */ -+ LENS, /* get lengths for stored */ -+ STORED, /* processing stored block */ -+ TABLE, /* get table lengths */ -+ BTREE, /* get bit lengths tree for a dynamic block */ -+ DTREE, /* get length, distance trees for a dynamic block */ -+ CODES, /* processing fixed or dynamic block */ -+ DRY, /* output remaining window bytes */ -+ DONEB, /* finished last block, done */ -+ BADB} /* got a data error--stuck here */ -+ mode; /* current inflate_block mode */ -+ -+ /* mode dependent information */ -+ union { -+ uInt left; /* if STORED, bytes left to copy */ -+ struct { -+ uInt table; /* table lengths (14 bits) */ -+ uInt index; /* index into blens (or border) */ -+ uIntf *blens; /* bit lengths of codes */ -+ uInt bb; /* bit length tree depth */ -+ inflate_huft *tb; /* bit length decoding tree */ -+ int nblens; /* # elements allocated at blens */ -+ } trees; /* if DTREE, decoding info for trees */ -+ struct { -+ inflate_huft *tl, *td; /* trees to free */ -+ inflate_codes_statef -+ *codes; -+ } decode; /* if CODES, current state */ -+ } sub; /* submode */ -+ uInt last; /* true if this block is the last block */ -+ -+ /* mode independent information */ -+ uInt bitk; /* bits in bit buffer */ -+ uLong bitb; /* bit buffer */ -+ Bytef *window; /* sliding window */ -+ Bytef *end; /* one byte after sliding window */ -+ Bytef *read; /* window read pointer */ -+ Bytef *write; /* window write pointer */ -+ check_func checkfn; /* check function */ -+ uLong check; /* check on output */ -+ -+}; -+ -+ -+/* defines for inflate input/output */ -+/* update pointers and return */ -+#define UPDBITS {s->bitb=b;s->bitk=k;} -+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} -+#define UPDOUT {s->write=q;} -+#define UPDATE {UPDBITS UPDIN UPDOUT} -+#define LEAVE {UPDATE return inflate_flush(s,z,r);} -+/* get bytes and bits */ -+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} -+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} -+#define NEXTBYTE (n--,*p++) -+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} -+/* output bytes */ -+#define WAVAIL (qread?s->read-q-1:s->end-q) -+#define LOADOUT {q=s->write;m=WAVAIL;} -+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}} -+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} -+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} -+#define OUTBYTE(a) {*q++=(Byte)(a);m--;} -+/* load local pointers */ -+#define LOAD {LOADIN LOADOUT} -+ -+/* -+ * The IBM 150 firmware munges the data right after _etext[]. This -+ * protects it. -- Cort -+ */ -+local uInt protect_mask[] = {0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0}; -+/* And'ing with mask[n] masks the lower n bits */ -+local uInt inflate_mask[] = { -+ 0x0000, -+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, -+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -+}; -+ -+/* copy as much as possible from the sliding window to the output area */ -+local int inflate_flush OF(( -+ inflate_blocks_statef *, -+ z_stream *, -+ int)); -+ -+/*+++++*/ -+/* inffast.h -- header to use inffast.c -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+local int inflate_fast OF(( -+ uInt, -+ uInt, -+ inflate_huft *, -+ inflate_huft *, -+ inflate_blocks_statef *, -+ z_stream *)); -+ -+ -+/*+++++*/ -+/* infblock.c -- interpret and process block types to last block -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* Table for deflate from PKZIP's appnote.txt. */ -+local uInt border[] = { /* Order of the bit length code lengths */ -+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; -+ -+/* -+ Notes beyond the 1.93a appnote.txt: -+ -+ 1. Distance pointers never point before the beginning of the output -+ stream. -+ 2. Distance pointers can point back across blocks, up to 32k away. -+ 3. There is an implied maximum of 7 bits for the bit length table and -+ 15 bits for the actual data. -+ 4. If only one code exists, then it is encoded using one bit. (Zero -+ would be more efficient, but perhaps a little confusing.) If two -+ codes exist, they are coded using one bit each (0 and 1). -+ 5. There is no way of sending zero distance codes--a dummy must be -+ sent if there are none. (History: a pre 2.0 version of PKZIP would -+ store blocks with no distance codes, but this was discovered to be -+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow -+ zero distance codes, which is sent as one code of zero bits in -+ length. -+ 6. There are up to 286 literal/length codes. Code 256 represents the -+ end-of-block. Note however that the static length tree defines -+ 288 codes just to fill out the Huffman codes. Codes 286 and 287 -+ cannot be used though, since there is no length base or extra bits -+ defined for them. Similarily, there are up to 30 distance codes. -+ However, static trees define 32 codes (all 5 bits) to fill out the -+ Huffman codes, but the last two had better not show up in the data. -+ 7. Unzip can check dynamic Huffman blocks for complete code sets. -+ The exception is that a single code would not be complete (see #4). -+ 8. The five bits following the block type is really the number of -+ literal codes sent minus 257. -+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits -+ (1+6+6). Therefore, to output three times the length, you output -+ three codes (1+1+1), whereas to output four times the same length, -+ you only need two codes (1+3). Hmm. -+ 10. In the tree reconstruction algorithm, Code = Code + Increment -+ only if BitLength(i) is not zero. (Pretty obvious.) -+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) -+ 12. Note: length code 284 can represent 227-258, but length code 285 -+ really is 258. The last length deserves its own, short code -+ since it gets used a lot in very redundant files. The length -+ 258 is special since 258 - 3 (the min match length) is 255. -+ 13. The literal/length and distance code bit lengths are read as a -+ single stream of lengths. It is possible (and advantageous) for -+ a repeat code (16, 17, or 18) to go across the boundary between -+ the two sets of lengths. -+ */ -+ -+ -+local void inflate_blocks_reset(s, z, c) -+inflate_blocks_statef *s; -+z_stream *z; -+uLongf *c; -+{ -+ if (s->checkfn != Z_NULL) -+ *c = s->check; -+ if (s->mode == BTREE || s->mode == DTREE) -+ ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt)); -+ if (s->mode == CODES) -+ { -+ inflate_codes_free(s->sub.decode.codes, z); -+ inflate_trees_free(s->sub.decode.td, z); -+ inflate_trees_free(s->sub.decode.tl, z); -+ } -+ s->mode = TYPE; -+ s->bitk = 0; -+ s->bitb = 0; -+ s->read = s->write = s->window; -+ if (s->checkfn != Z_NULL) -+ s->check = (*s->checkfn)(0L, Z_NULL, 0); -+ Trace((stderr, "inflate: blocks reset\n")); -+} -+ -+ -+local inflate_blocks_statef *inflate_blocks_new(z, c, w) -+z_stream *z; -+check_func c; -+uInt w; -+{ -+ inflate_blocks_statef *s; -+ -+ if ((s = (inflate_blocks_statef *)ZALLOC -+ (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) -+ return s; -+ if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) -+ { -+ ZFREE(z, s, sizeof(struct inflate_blocks_state)); -+ return Z_NULL; -+ } -+ s->end = s->window + w; -+ s->checkfn = c; -+ s->mode = TYPE; -+ Trace((stderr, "inflate: blocks allocated\n")); -+ inflate_blocks_reset(s, z, &s->check); -+ return s; -+} -+ -+ -+local int inflate_blocks(s, z, r) -+inflate_blocks_statef *s; -+z_stream *z; -+int r; -+{ -+ uInt t; /* temporary storage */ -+ uLong b; /* bit buffer */ -+ uInt k; /* bits in bit buffer */ -+ Bytef *p; /* input data pointer */ -+ uInt n; /* bytes available there */ -+ Bytef *q; /* output window write pointer */ -+ uInt m; /* bytes to end of window or read pointer */ -+ -+ /* copy input/output information to locals (UPDATE macro restores) */ -+ LOAD -+ -+ /* process input based on current state */ -+ while (1) switch (s->mode) -+ { -+ case TYPE: -+ NEEDBITS(3) -+ t = (uInt)b & 7; -+ s->last = t & 1; -+ switch (t >> 1) -+ { -+ case 0: /* stored */ -+ Trace((stderr, "inflate: stored block%s\n", -+ s->last ? " (last)" : "")); -+ DUMPBITS(3) -+ t = k & 7; /* go to byte boundary */ -+ DUMPBITS(t) -+ s->mode = LENS; /* get length of stored block */ -+ break; -+ case 1: /* fixed */ -+ Trace((stderr, "inflate: fixed codes block%s\n", -+ s->last ? " (last)" : "")); -+ { -+ uInt bl, bd; -+ inflate_huft *tl, *td; -+ -+ inflate_trees_fixed(&bl, &bd, &tl, &td); -+ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); -+ if (s->sub.decode.codes == Z_NULL) -+ { -+ r = Z_MEM_ERROR; -+ LEAVE -+ } -+ s->sub.decode.tl = Z_NULL; /* don't try to free these */ -+ s->sub.decode.td = Z_NULL; -+ } -+ DUMPBITS(3) -+ s->mode = CODES; -+ break; -+ case 2: /* dynamic */ -+ Trace((stderr, "inflate: dynamic codes block%s\n", -+ s->last ? " (last)" : "")); -+ DUMPBITS(3) -+ s->mode = TABLE; -+ break; -+ case 3: /* illegal */ -+ DUMPBITS(3) -+ s->mode = BADB; -+ z->msg = "invalid block type"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+ break; -+ case LENS: -+ NEEDBITS(32) -+ if (((~b) >> 16) != (b & 0xffff)) -+ { -+ s->mode = BADB; -+ z->msg = "invalid stored block lengths"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+ s->sub.left = (uInt)b & 0xffff; -+ b = k = 0; /* dump bits */ -+ Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); -+ s->mode = s->sub.left ? STORED : TYPE; -+ break; -+ case STORED: -+ if (n == 0) -+ LEAVE -+ NEEDOUT -+ t = s->sub.left; -+ if (t > n) t = n; -+ if (t > m) t = m; -+ zmemcpy(q, p, t); -+ p += t; n -= t; -+ q += t; m -= t; -+ if ((s->sub.left -= t) != 0) -+ break; -+ Tracev((stderr, "inflate: stored end, %lu total out\n", -+ z->total_out + (q >= s->read ? q - s->read : -+ (s->end - s->read) + (q - s->window)))); -+ s->mode = s->last ? DRY : TYPE; -+ break; -+ case TABLE: -+ NEEDBITS(14) -+ s->sub.trees.table = t = (uInt)b & 0x3fff; -+#ifndef PKZIP_BUG_WORKAROUND -+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) -+ { -+ s->mode = BADB; -+ z->msg = "too many length or distance symbols"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+#endif -+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); -+ if (t < 19) -+ t = 19; -+ if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) -+ { -+ r = Z_MEM_ERROR; -+ LEAVE -+ } -+ s->sub.trees.nblens = t; -+ DUMPBITS(14) -+ s->sub.trees.index = 0; -+ Tracev((stderr, "inflate: table sizes ok\n")); -+ s->mode = BTREE; -+ case BTREE: -+ while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) -+ { -+ NEEDBITS(3) -+ s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; -+ DUMPBITS(3) -+ } -+ while (s->sub.trees.index < 19) -+ s->sub.trees.blens[border[s->sub.trees.index++]] = 0; -+ s->sub.trees.bb = 7; -+ t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, -+ &s->sub.trees.tb, z); -+ if (t != Z_OK) -+ { -+ r = t; -+ if (r == Z_DATA_ERROR) -+ s->mode = BADB; -+ LEAVE -+ } -+ s->sub.trees.index = 0; -+ Tracev((stderr, "inflate: bits tree ok\n")); -+ s->mode = DTREE; -+ case DTREE: -+ while (t = s->sub.trees.table, -+ s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) -+ { -+ inflate_huft *h; -+ uInt i, j, c; -+ -+ t = s->sub.trees.bb; -+ NEEDBITS(t) -+ h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); -+ t = h->word.what.Bits; -+ c = h->more.Base; -+ if (c < 16) -+ { -+ DUMPBITS(t) -+ s->sub.trees.blens[s->sub.trees.index++] = c; -+ } -+ else /* c == 16..18 */ -+ { -+ i = c == 18 ? 7 : c - 14; -+ j = c == 18 ? 11 : 3; -+ NEEDBITS(t + i) -+ DUMPBITS(t) -+ j += (uInt)b & inflate_mask[i]; -+ DUMPBITS(i) -+ i = s->sub.trees.index; -+ t = s->sub.trees.table; -+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || -+ (c == 16 && i < 1)) -+ { -+ s->mode = BADB; -+ z->msg = "invalid bit length repeat"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+ c = c == 16 ? s->sub.trees.blens[i - 1] : 0; -+ do { -+ s->sub.trees.blens[i++] = c; -+ } while (--j); -+ s->sub.trees.index = i; -+ } -+ } -+ inflate_trees_free(s->sub.trees.tb, z); -+ s->sub.trees.tb = Z_NULL; -+ { -+ uInt bl, bd; -+ inflate_huft *tl, *td; -+ inflate_codes_statef *c; -+ -+ bl = 9; /* must be <= 9 for lookahead assumptions */ -+ bd = 6; /* must be <= 9 for lookahead assumptions */ -+ t = s->sub.trees.table; -+ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), -+ s->sub.trees.blens, &bl, &bd, &tl, &td, z); -+ if (t != Z_OK) -+ { -+ if (t == (uInt)Z_DATA_ERROR) -+ s->mode = BADB; -+ r = t; -+ LEAVE -+ } -+ Tracev((stderr, "inflate: trees ok\n")); -+ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) -+ { -+ inflate_trees_free(td, z); -+ inflate_trees_free(tl, z); -+ r = Z_MEM_ERROR; -+ LEAVE -+ } -+ ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt)); -+ s->sub.decode.codes = c; -+ s->sub.decode.tl = tl; -+ s->sub.decode.td = td; -+ } -+ s->mode = CODES; -+ case CODES: -+ UPDATE -+ if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) -+ return inflate_flush(s, z, r); -+ r = Z_OK; -+ inflate_codes_free(s->sub.decode.codes, z); -+ inflate_trees_free(s->sub.decode.td, z); -+ inflate_trees_free(s->sub.decode.tl, z); -+ LOAD -+ Tracev((stderr, "inflate: codes end, %lu total out\n", -+ z->total_out + (q >= s->read ? q - s->read : -+ (s->end - s->read) + (q - s->window)))); -+ if (!s->last) -+ { -+ s->mode = TYPE; -+ break; -+ } -+ if (k > 7) /* return unused byte, if any */ -+ { -+ Assert(k < 16, "inflate_codes grabbed too many bytes") -+ k -= 8; -+ n++; -+ p--; /* can always return one */ -+ } -+ s->mode = DRY; -+ case DRY: -+ FLUSH -+ if (s->read != s->write) -+ LEAVE -+ s->mode = DONEB; -+ case DONEB: -+ r = Z_STREAM_END; -+ LEAVE -+ case BADB: -+ r = Z_DATA_ERROR; -+ LEAVE -+ default: -+ r = Z_STREAM_ERROR; -+ LEAVE -+ } -+} -+ -+ -+local int inflate_blocks_free(s, z, c) -+inflate_blocks_statef *s; -+z_stream *z; -+uLongf *c; -+{ -+ inflate_blocks_reset(s, z, c); -+ ZFREE(z, s->window, s->end - s->window); -+ ZFREE(z, s, sizeof(struct inflate_blocks_state)); -+ Trace((stderr, "inflate: blocks freed\n")); -+ return Z_OK; -+} -+ -+/* -+ * This subroutine adds the data at next_in/avail_in to the output history -+ * without performing any output. The output buffer must be "caught up"; -+ * i.e. no pending output (hence s->read equals s->write), and the state must -+ * be BLOCKS (i.e. we should be willing to see the start of a series of -+ * BLOCKS). On exit, the output will also be caught up, and the checksum -+ * will have been updated if need be. -+ */ -+local int inflate_addhistory(s, z) -+inflate_blocks_statef *s; -+z_stream *z; -+{ -+ uLong b; /* bit buffer */ /* NOT USED HERE */ -+ uInt k; /* bits in bit buffer */ /* NOT USED HERE */ -+ uInt t; /* temporary storage */ -+ Bytef *p; /* input data pointer */ -+ uInt n; /* bytes available there */ -+ Bytef *q; /* output window write pointer */ -+ uInt m; /* bytes to end of window or read pointer */ -+ -+ if (s->read != s->write) -+ return Z_STREAM_ERROR; -+ if (s->mode != TYPE) -+ return Z_DATA_ERROR; -+ -+ /* we're ready to rock */ -+ LOAD -+ /* while there is input ready, copy to output buffer, moving -+ * pointers as needed. -+ */ -+ while (n) { -+ t = n; /* how many to do */ -+ /* is there room until end of buffer? */ -+ if (t > m) t = m; -+ /* update check information */ -+ if (s->checkfn != Z_NULL) -+ s->check = (*s->checkfn)(s->check, q, t); -+ zmemcpy(q, p, t); -+ q += t; -+ p += t; -+ n -= t; -+ z->total_out += t; -+ s->read = q; /* drag read pointer forward */ -+/* WRAP */ /* expand WRAP macro by hand to handle s->read */ -+ if (q == s->end) { -+ s->read = q = s->window; -+ m = WAVAIL; -+ } -+ } -+ UPDATE -+ return Z_OK; -+} -+ -+ -+/* -+ * At the end of a Deflate-compressed PPP packet, we expect to have seen -+ * a `stored' block type value but not the (zero) length bytes. -+ */ -+local int inflate_packet_flush(s) -+ inflate_blocks_statef *s; -+{ -+ if (s->mode != LENS) -+ return Z_DATA_ERROR; -+ s->mode = TYPE; -+ return Z_OK; -+} -+ -+ -+/*+++++*/ -+/* inftrees.c -- generate Huffman trees for efficient decoding -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* simplify the use of the inflate_huft type with some defines */ -+#define base more.Base -+#define next more.Next -+#define exop word.what.Exop -+#define bits word.what.Bits -+ -+ -+local int huft_build OF(( -+ uIntf *, /* code lengths in bits */ -+ uInt, /* number of codes */ -+ uInt, /* number of "simple" codes */ -+ uIntf *, /* list of base values for non-simple codes */ -+ uIntf *, /* list of extra bits for non-simple codes */ -+ inflate_huft * FAR*,/* result: starting table */ -+ uIntf *, /* maximum lookup bits (returns actual) */ -+ z_stream *)); /* for zalloc function */ -+ -+local voidpf falloc OF(( -+ voidpf, /* opaque pointer (not used) */ -+ uInt, /* number of items */ -+ uInt)); /* size of item */ -+ -+local void ffree OF(( -+ voidpf q, /* opaque pointer (not used) */ -+ voidpf p, /* what to free (not used) */ -+ uInt n)); /* number of bytes (not used) */ -+ -+/* Tables for deflate from PKZIP's appnote.txt. */ -+local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */ -+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, -+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; -+ /* actually lengths - 2; also see note #13 above about 258 */ -+local uInt cplext[] = { /* Extra bits for literal codes 257..285 */ -+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, -+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */ -+local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */ -+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, -+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, -+ 8193, 12289, 16385, 24577}; -+local uInt cpdext[] = { /* Extra bits for distance codes */ -+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, -+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, -+ 12, 12, 13, 13}; -+ -+/* -+ Huffman code decoding is performed using a multi-level table lookup. -+ The fastest way to decode is to simply build a lookup table whose -+ size is determined by the longest code. However, the time it takes -+ to build this table can also be a factor if the data being decoded -+ is not very long. The most common codes are necessarily the -+ shortest codes, so those codes dominate the decoding time, and hence -+ the speed. The idea is you can have a shorter table that decodes the -+ shorter, more probable codes, and then point to subsidiary tables for -+ the longer codes. The time it costs to decode the longer codes is -+ then traded against the time it takes to make longer tables. -+ -+ This results of this trade are in the variables lbits and dbits -+ below. lbits is the number of bits the first level table for literal/ -+ length codes can decode in one step, and dbits is the same thing for -+ the distance codes. Subsequent tables are also less than or equal to -+ those sizes. These values may be adjusted either when all of the -+ codes are shorter than that, in which case the longest code length in -+ bits is used, or when the shortest code is *longer* than the requested -+ table size, in which case the length of the shortest code in bits is -+ used. -+ -+ There are two different values for the two tables, since they code a -+ different number of possibilities each. The literal/length table -+ codes 286 possible values, or in a flat code, a little over eight -+ bits. The distance table codes 30 possible values, or a little less -+ than five bits, flat. The optimum values for speed end up being -+ about one bit more than those, so lbits is 8+1 and dbits is 5+1. -+ The optimum values may differ though from machine to machine, and -+ possibly even between compilers. Your mileage may vary. -+ */ -+ -+ -+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ -+#define BMAX 15 /* maximum bit length of any code */ -+#define N_MAX 288 /* maximum number of codes in any set */ -+ -+#ifdef DEBUG_ZLIB -+ uInt inflate_hufts; -+#endif -+ -+local int huft_build(b, n, s, d, e, t, m, zs) -+uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ -+uInt n; /* number of codes (assumed <= N_MAX) */ -+uInt s; /* number of simple-valued codes (0..s-1) */ -+uIntf *d; /* list of base values for non-simple codes */ -+uIntf *e; /* list of extra bits for non-simple codes */ -+inflate_huft * FAR *t; /* result: starting table */ -+uIntf *m; /* maximum lookup bits, returns actual */ -+z_stream *zs; /* for zalloc function */ -+/* Given a list of code lengths and a maximum table size, make a set of -+ tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR -+ if the given code set is incomplete (the tables are still built in this -+ case), Z_DATA_ERROR if the input is invalid (all zero length codes or an -+ over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */ -+{ -+ -+ uInt a; /* counter for codes of length k */ -+ uInt c[BMAX+1]; /* bit length count table */ -+ uInt f; /* i repeats in table every f entries */ -+ int g; /* maximum code length */ -+ int h; /* table level */ -+ register uInt i; /* counter, current code */ -+ register uInt j; /* counter */ -+ register int k; /* number of bits in current code */ -+ int l; /* bits per table (returned in m) */ -+ register uIntf *p; /* pointer into c[], b[], or v[] */ -+ inflate_huft *q; /* points to current table */ -+ struct inflate_huft_s r; /* table entry for structure assignment */ -+ inflate_huft *u[BMAX]; /* table stack */ -+ uInt v[N_MAX]; /* values in order of bit length */ -+ register int w; /* bits before this table == (l * h) */ -+ uInt x[BMAX+1]; /* bit offsets, then code stack */ -+ uIntf *xp; /* pointer into x */ -+ int y; /* number of dummy codes added */ -+ uInt z; /* number of entries in current table */ -+ -+ -+ /* Generate counts for each bit length */ -+ p = c; -+#define C0 *p++ = 0; -+#define C2 C0 C0 C0 C0 -+#define C4 C2 C2 C2 C2 -+ C4 /* clear c[]--assume BMAX+1 is 16 */ -+ p = b; i = n; -+ do { -+ c[*p++]++; /* assume all entries <= BMAX */ -+ } while (--i); -+ if (c[0] == n) /* null input--all zero length codes */ -+ { -+ *t = (inflate_huft *)Z_NULL; -+ *m = 0; -+ return Z_OK; -+ } -+ -+ -+ /* Find minimum and maximum length, bound *m by those */ -+ l = *m; -+ for (j = 1; j <= BMAX; j++) -+ if (c[j]) -+ break; -+ k = j; /* minimum code length */ -+ if ((uInt)l < j) -+ l = j; -+ for (i = BMAX; i; i--) -+ if (c[i]) -+ break; -+ g = i; /* maximum code length */ -+ if ((uInt)l > i) -+ l = i; -+ *m = l; -+ -+ -+ /* Adjust last length count to fill out codes, if needed */ -+ for (y = 1 << j; j < i; j++, y <<= 1) -+ if ((y -= c[j]) < 0) -+ return Z_DATA_ERROR; -+ if ((y -= c[i]) < 0) -+ return Z_DATA_ERROR; -+ c[i] += y; -+ -+ -+ /* Generate starting offsets into the value table for each length */ -+ x[1] = j = 0; -+ p = c + 1; xp = x + 2; -+ while (--i) { /* note that i == g from above */ -+ *xp++ = (j += *p++); -+ } -+ -+ -+ /* Make a table of values in order of bit lengths */ -+ p = b; i = 0; -+ do { -+ if ((j = *p++) != 0) -+ v[x[j]++] = i; -+ } while (++i < n); -+ -+ -+ /* Generate the Huffman codes and for each, make the table entries */ -+ x[0] = i = 0; /* first Huffman code is zero */ -+ p = v; /* grab values in bit order */ -+ h = -1; /* no tables yet--level -1 */ -+ w = -l; /* bits decoded == (l * h) */ -+ u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ -+ q = (inflate_huft *)Z_NULL; /* ditto */ -+ z = 0; /* ditto */ -+ -+ /* go through the bit lengths (k already is bits in shortest code) */ -+ for (; k <= g; k++) -+ { -+ a = c[k]; -+ while (a--) -+ { -+ /* here i is the Huffman code of length k bits for value *p */ -+ /* make tables up to required level */ -+ while (k > w + l) -+ { -+ h++; -+ w += l; /* previous table always l bits */ -+ -+ /* compute minimum size table less than or equal to l bits */ -+ z = (z = g - w) > (uInt)l ? l : z; /* table size upper limit */ -+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ -+ { /* too few codes for k-w bit table */ -+ f -= a + 1; /* deduct codes from patterns left */ -+ xp = c + k; -+ if (j < z) -+ while (++j < z) /* try smaller tables up to z bits */ -+ { -+ if ((f <<= 1) <= *++xp) -+ break; /* enough codes to use up j bits */ -+ f -= *xp; /* else deduct codes from patterns */ -+ } -+ } -+ z = 1 << j; /* table entries for j-bit table */ -+ -+ /* allocate and link in new table */ -+ if ((q = (inflate_huft *)ZALLOC -+ (zs,z + 1,sizeof(inflate_huft))) == Z_NULL) -+ { -+ if (h) -+ inflate_trees_free(u[0], zs); -+ return Z_MEM_ERROR; /* not enough memory */ -+ } -+ q->word.Nalloc = z + 1; -+#ifdef DEBUG_ZLIB -+ inflate_hufts += z + 1; -+#endif -+ *t = q + 1; /* link to list for huft_free() */ -+ *(t = &(q->next)) = Z_NULL; -+ u[h] = ++q; /* table starts after link */ -+ -+ /* connect to last table, if there is one */ -+ if (h) -+ { -+ x[h] = i; /* save pattern for backing up */ -+ r.bits = (Byte)l; /* bits to dump before this table */ -+ r.exop = (Byte)j; /* bits in this table */ -+ r.next = q; /* pointer to this table */ -+ j = i >> (w - l); /* (get around Turbo C bug) */ -+ u[h-1][j] = r; /* connect to last table */ -+ } -+ } -+ -+ /* set up table entry in r */ -+ r.bits = (Byte)(k - w); -+ if (p >= v + n) -+ r.exop = 128 + 64; /* out of values--invalid code */ -+ else if (*p < s) -+ { -+ r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ -+ r.base = *p++; /* simple code is just the value */ -+ } -+ else -+ { -+ r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */ -+ r.base = d[*p++ - s]; -+ } -+ -+ /* fill code-like entries with r */ -+ f = 1 << (k - w); -+ for (j = i >> w; j < z; j += f) -+ q[j] = r; -+ -+ /* backwards increment the k-bit code i */ -+ for (j = 1 << (k - 1); i & j; j >>= 1) -+ i ^= j; -+ i ^= j; -+ -+ /* backup over finished tables */ -+ while ((i & ((1 << w) - 1)) != x[h]) -+ { -+ h--; /* don't need to update q */ -+ w -= l; -+ } -+ } -+ } -+ -+ -+ /* Return Z_BUF_ERROR if we were given an incomplete table */ -+ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; -+} -+ -+ -+local int inflate_trees_bits(c, bb, tb, z) -+uIntf *c; /* 19 code lengths */ -+uIntf *bb; /* bits tree desired/actual depth */ -+inflate_huft * FAR *tb; /* bits tree result */ -+z_stream *z; /* for zfree function */ -+{ -+ int r; -+ -+ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z); -+ if (r == Z_DATA_ERROR) -+ z->msg = "oversubscribed dynamic bit lengths tree"; -+ else if (r == Z_BUF_ERROR) -+ { -+ inflate_trees_free(*tb, z); -+ z->msg = "incomplete dynamic bit lengths tree"; -+ r = Z_DATA_ERROR; -+ } -+ return r; -+} -+ -+ -+local int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z) -+uInt nl; /* number of literal/length codes */ -+uInt nd; /* number of distance codes */ -+uIntf *c; /* that many (total) code lengths */ -+uIntf *bl; /* literal desired/actual bit depth */ -+uIntf *bd; /* distance desired/actual bit depth */ -+inflate_huft * FAR *tl; /* literal/length tree result */ -+inflate_huft * FAR *td; /* distance tree result */ -+z_stream *z; /* for zfree function */ -+{ -+ int r; -+ -+ /* build literal/length tree */ -+ if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK) -+ { -+ if (r == Z_DATA_ERROR) -+ z->msg = "oversubscribed literal/length tree"; -+ else if (r == Z_BUF_ERROR) -+ { -+ inflate_trees_free(*tl, z); -+ z->msg = "incomplete literal/length tree"; -+ r = Z_DATA_ERROR; -+ } -+ return r; -+ } -+ -+ /* build distance tree */ -+ if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK) -+ { -+ if (r == Z_DATA_ERROR) -+ z->msg = "oversubscribed literal/length tree"; -+ else if (r == Z_BUF_ERROR) { -+#ifdef PKZIP_BUG_WORKAROUND -+ r = Z_OK; -+ } -+#else -+ inflate_trees_free(*td, z); -+ z->msg = "incomplete literal/length tree"; -+ r = Z_DATA_ERROR; -+ } -+ inflate_trees_free(*tl, z); -+ return r; -+#endif -+ } -+ -+ /* done */ -+ return Z_OK; -+} -+ -+ -+/* build fixed tables only once--keep them here */ -+local int fixed_lock = 0; -+local int fixed_built = 0; -+#define FIXEDH 530 /* number of hufts used by fixed tables */ -+local uInt fixed_left = FIXEDH; -+local inflate_huft fixed_mem[FIXEDH]; -+local uInt fixed_bl; -+local uInt fixed_bd; -+local inflate_huft *fixed_tl; -+local inflate_huft *fixed_td; -+ -+ -+local voidpf falloc(q, n, s) -+voidpf q; /* opaque pointer (not used) */ -+uInt n; /* number of items */ -+uInt s; /* size of item */ -+{ -+ Assert(s == sizeof(inflate_huft) && n <= fixed_left, -+ "inflate_trees falloc overflow"); -+ if (q) s++; /* to make some compilers happy */ -+ fixed_left -= n; -+ return (voidpf)(fixed_mem + fixed_left); -+} -+ -+ -+local void ffree(q, p, n) -+voidpf q; -+voidpf p; -+uInt n; -+{ -+ Assert(0, "inflate_trees ffree called!"); -+ if (q) q = p; /* to make some compilers happy */ -+} -+ -+ -+local int inflate_trees_fixed(bl, bd, tl, td) -+uIntf *bl; /* literal desired/actual bit depth */ -+uIntf *bd; /* distance desired/actual bit depth */ -+inflate_huft * FAR *tl; /* literal/length tree result */ -+inflate_huft * FAR *td; /* distance tree result */ -+{ -+ /* build fixed tables if not built already--lock out other instances */ -+ while (++fixed_lock > 1) -+ fixed_lock--; -+ if (!fixed_built) -+ { -+ int k; /* temporary variable */ -+ unsigned c[288]; /* length list for huft_build */ -+ z_stream z; /* for falloc function */ -+ -+ /* set up fake z_stream for memory routines */ -+ z.zalloc = falloc; -+ z.zfree = ffree; -+ z.opaque = Z_NULL; -+ -+ /* literal table */ -+ for (k = 0; k < 144; k++) -+ c[k] = 8; -+ for (; k < 256; k++) -+ c[k] = 9; -+ for (; k < 280; k++) -+ c[k] = 7; -+ for (; k < 288; k++) -+ c[k] = 8; -+ fixed_bl = 7; -+ huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z); -+ -+ /* distance table */ -+ for (k = 0; k < 30; k++) -+ c[k] = 5; -+ fixed_bd = 5; -+ huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z); -+ -+ /* done */ -+ fixed_built = 1; -+ } -+ fixed_lock--; -+ *bl = fixed_bl; -+ *bd = fixed_bd; -+ *tl = fixed_tl; -+ *td = fixed_td; -+ return Z_OK; -+} -+ -+ -+local int inflate_trees_free(t, z) -+inflate_huft *t; /* table to free */ -+z_stream *z; /* for zfree function */ -+/* Free the malloc'ed tables built by huft_build(), which makes a linked -+ list of the tables it made, with the links in a dummy first entry of -+ each table. */ -+{ -+ register inflate_huft *p, *q; -+ -+ /* Go through linked list, freeing from the malloced (t[-1]) address. */ -+ p = t; -+ while (p != Z_NULL) -+ { -+ q = (--p)->next; -+ ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft)); -+ p = q; -+ } -+ return Z_OK; -+} -+ -+/*+++++*/ -+/* infcodes.c -- process literals and length/distance pairs -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* simplify the use of the inflate_huft type with some defines */ -+#define base more.Base -+#define next more.Next -+#define exop word.what.Exop -+#define bits word.what.Bits -+ -+/* inflate codes private state */ -+struct inflate_codes_state { -+ -+ /* mode */ -+ enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ -+ START, /* x: set up for LEN */ -+ LEN, /* i: get length/literal/eob next */ -+ LENEXT, /* i: getting length extra (have base) */ -+ DIST, /* i: get distance next */ -+ DISTEXT, /* i: getting distance extra */ -+ COPY, /* o: copying bytes in window, waiting for space */ -+ LIT, /* o: got literal, waiting for output space */ -+ WASH, /* o: got eob, possibly still output waiting */ -+ END, /* x: got eob and all data flushed */ -+ BADCODE} /* x: got error */ -+ mode; /* current inflate_codes mode */ -+ -+ /* mode dependent information */ -+ uInt len; -+ union { -+ struct { -+ inflate_huft *tree; /* pointer into tree */ -+ uInt need; /* bits needed */ -+ } code; /* if LEN or DIST, where in tree */ -+ uInt lit; /* if LIT, literal */ -+ struct { -+ uInt get; /* bits to get for extra */ -+ uInt dist; /* distance back to copy from */ -+ } copy; /* if EXT or COPY, where and how much */ -+ } sub; /* submode */ -+ -+ /* mode independent information */ -+ Byte lbits; /* ltree bits decoded per branch */ -+ Byte dbits; /* dtree bits decoder per branch */ -+ inflate_huft *ltree; /* literal/length/eob tree */ -+ inflate_huft *dtree; /* distance tree */ -+ -+}; -+ -+ -+local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) -+uInt bl, bd; -+inflate_huft *tl, *td; -+z_stream *z; -+{ -+ inflate_codes_statef *c; -+ -+ if ((c = (inflate_codes_statef *) -+ ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) -+ { -+ c->mode = START; -+ c->lbits = (Byte)bl; -+ c->dbits = (Byte)bd; -+ c->ltree = tl; -+ c->dtree = td; -+ Tracev((stderr, "inflate: codes new\n")); -+ } -+ return c; -+} -+ -+ -+local int inflate_codes(s, z, r) -+inflate_blocks_statef *s; -+z_stream *z; -+int r; -+{ -+ uInt j; /* temporary storage */ -+ inflate_huft *t; /* temporary pointer */ -+ uInt e; /* extra bits or operation */ -+ uLong b; /* bit buffer */ -+ uInt k; /* bits in bit buffer */ -+ Bytef *p; /* input data pointer */ -+ uInt n; /* bytes available there */ -+ Bytef *q; /* output window write pointer */ -+ uInt m; /* bytes to end of window or read pointer */ -+ Bytef *f; /* pointer to copy strings from */ -+ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ -+ -+ /* copy input/output information to locals (UPDATE macro restores) */ -+ LOAD -+ -+ /* process input and output based on current state */ -+ while (1) switch (c->mode) -+ { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ -+ case START: /* x: set up for LEN */ -+#ifndef SLOW -+ if (m >= 258 && n >= 10) -+ { -+ UPDATE -+ r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); -+ LOAD -+ if (r != Z_OK) -+ { -+ c->mode = r == Z_STREAM_END ? WASH : BADCODE; -+ break; -+ } -+ } -+#endif /* !SLOW */ -+ c->sub.code.need = c->lbits; -+ c->sub.code.tree = c->ltree; -+ c->mode = LEN; -+ case LEN: /* i: get length/literal/eob next */ -+ j = c->sub.code.need; -+ NEEDBITS(j) -+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); -+ DUMPBITS(t->bits) -+ e = (uInt)(t->exop); -+ if (e == 0) /* literal */ -+ { -+ c->sub.lit = t->base; -+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? -+ "inflate: literal '%c'\n" : -+ "inflate: literal 0x%02x\n", t->base)); -+ c->mode = LIT; -+ break; -+ } -+ if (e & 16) /* length */ -+ { -+ c->sub.copy.get = e & 15; -+ c->len = t->base; -+ c->mode = LENEXT; -+ break; -+ } -+ if ((e & 64) == 0) /* next table */ -+ { -+ c->sub.code.need = e; -+ c->sub.code.tree = t->next; -+ break; -+ } -+ if (e & 32) /* end of block */ -+ { -+ Tracevv((stderr, "inflate: end of block\n")); -+ c->mode = WASH; -+ break; -+ } -+ c->mode = BADCODE; /* invalid code */ -+ z->msg = "invalid literal/length code"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ case LENEXT: /* i: getting length extra (have base) */ -+ j = c->sub.copy.get; -+ NEEDBITS(j) -+ c->len += (uInt)b & inflate_mask[j]; -+ DUMPBITS(j) -+ c->sub.code.need = c->dbits; -+ c->sub.code.tree = c->dtree; -+ Tracevv((stderr, "inflate: length %u\n", c->len)); -+ c->mode = DIST; -+ case DIST: /* i: get distance next */ -+ j = c->sub.code.need; -+ NEEDBITS(j) -+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); -+ DUMPBITS(t->bits) -+ e = (uInt)(t->exop); -+ if (e & 16) /* distance */ -+ { -+ c->sub.copy.get = e & 15; -+ c->sub.copy.dist = t->base; -+ c->mode = DISTEXT; -+ break; -+ } -+ if ((e & 64) == 0) /* next table */ -+ { -+ c->sub.code.need = e; -+ c->sub.code.tree = t->next; -+ break; -+ } -+ c->mode = BADCODE; /* invalid code */ -+ z->msg = "invalid distance code"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ case DISTEXT: /* i: getting distance extra */ -+ j = c->sub.copy.get; -+ NEEDBITS(j) -+ c->sub.copy.dist += (uInt)b & inflate_mask[j]; -+ DUMPBITS(j) -+ Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); -+ c->mode = COPY; -+ case COPY: /* o: copying bytes in window, waiting for space */ -+#ifndef __TURBOC__ /* Turbo C bug for following expression */ -+ f = (uInt)(q - s->window) < c->sub.copy.dist ? -+ s->end - (c->sub.copy.dist - (q - s->window)) : -+ q - c->sub.copy.dist; -+#else -+ f = q - c->sub.copy.dist; -+ if ((uInt)(q - s->window) < c->sub.copy.dist) -+ f = s->end - (c->sub.copy.dist - (q - s->window)); -+#endif -+ while (c->len) -+ { -+ NEEDOUT -+ OUTBYTE(*f++) -+ if (f == s->end) -+ f = s->window; -+ c->len--; -+ } -+ c->mode = START; -+ break; -+ case LIT: /* o: got literal, waiting for output space */ -+ NEEDOUT -+ OUTBYTE(c->sub.lit) -+ c->mode = START; -+ break; -+ case WASH: /* o: got eob, possibly more output */ -+ FLUSH -+ if (s->read != s->write) -+ LEAVE -+ c->mode = END; -+ case END: -+ r = Z_STREAM_END; -+ LEAVE -+ case BADCODE: /* x: got error */ -+ r = Z_DATA_ERROR; -+ LEAVE -+ default: -+ r = Z_STREAM_ERROR; -+ LEAVE -+ } -+} -+ -+ -+local void inflate_codes_free(c, z) -+inflate_codes_statef *c; -+z_stream *z; -+{ -+ ZFREE(z, c, sizeof(struct inflate_codes_state)); -+ Tracev((stderr, "inflate: codes free\n")); -+} -+ -+/*+++++*/ -+/* inflate_util.c -- data and routines common to blocks and codes -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* copy as much as possible from the sliding window to the output area */ -+local int inflate_flush(s, z, r) -+inflate_blocks_statef *s; -+z_stream *z; -+int r; -+{ -+ uInt n; -+ Bytef *p, *q; -+ -+ /* local copies of source and destination pointers */ -+ p = z->next_out; -+ q = s->read; -+ -+ /* compute number of bytes to copy as far as end of window */ -+ n = (uInt)((q <= s->write ? s->write : s->end) - q); -+ if (n > z->avail_out) n = z->avail_out; -+ if (n && r == Z_BUF_ERROR) r = Z_OK; -+ -+ /* update counters */ -+ z->avail_out -= n; -+ z->total_out += n; -+ -+ /* update check information */ -+ if (s->checkfn != Z_NULL) -+ s->check = (*s->checkfn)(s->check, q, n); -+ -+ /* copy as far as end of window */ -+ zmemcpy(p, q, n); -+ p += n; -+ q += n; -+ -+ /* see if more to copy at beginning of window */ -+ if (q == s->end) -+ { -+ /* wrap pointers */ -+ q = s->window; -+ if (s->write == s->end) -+ s->write = s->window; -+ -+ /* compute bytes to copy */ -+ n = (uInt)(s->write - q); -+ if (n > z->avail_out) n = z->avail_out; -+ if (n && r == Z_BUF_ERROR) r = Z_OK; -+ -+ /* update counters */ -+ z->avail_out -= n; -+ z->total_out += n; -+ -+ /* update check information */ -+ if (s->checkfn != Z_NULL) -+ s->check = (*s->checkfn)(s->check, q, n); -+ -+ /* copy */ -+ zmemcpy(p, q, n); -+ p += n; -+ q += n; -+ } -+ -+ /* update pointers */ -+ z->next_out = p; -+ s->read = q; -+ -+ /* done */ -+ return r; -+} -+ -+ -+/*+++++*/ -+/* inffast.c -- process literals and length/distance pairs fast -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* simplify the use of the inflate_huft type with some defines */ -+#define base more.Base -+#define next more.Next -+#define exop word.what.Exop -+#define bits word.what.Bits -+ -+/* macros for bit input with no checking and for returning unused bytes */ -+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<>3);p-=c;k&=7;} -+ -+/* Called with number of bytes left to write in window at least 258 -+ (the maximum string length) and number of input bytes available -+ at least ten. The ten bytes are six bytes for the longest length/ -+ distance pair plus four bytes for overloading the bit buffer. */ -+ -+local int inflate_fast(bl, bd, tl, td, s, z) -+uInt bl, bd; -+inflate_huft *tl, *td; -+inflate_blocks_statef *s; -+z_stream *z; -+{ -+ inflate_huft *t; /* temporary pointer */ -+ uInt e; /* extra bits or operation */ -+ uLong b; /* bit buffer */ -+ uInt k; /* bits in bit buffer */ -+ Bytef *p; /* input data pointer */ -+ uInt n; /* bytes available there */ -+ Bytef *q; /* output window write pointer */ -+ uInt m; /* bytes to end of window or read pointer */ -+ uInt ml; /* mask for literal/length tree */ -+ uInt md; /* mask for distance tree */ -+ uInt c; /* bytes to copy */ -+ uInt d; /* distance back to copy from */ -+ Bytef *r; /* copy source pointer */ -+ -+ /* load input, output, bit values */ -+ LOAD -+ -+ /* initialize masks */ -+ ml = inflate_mask[bl]; -+ md = inflate_mask[bd]; -+ -+ /* do until not enough input or output space for fast loop */ -+ do { /* assume called with m >= 258 && n >= 10 */ -+ /* get literal/length code */ -+ GRABBITS(20) /* max bits for literal/length code */ -+ if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) -+ { -+ DUMPBITS(t->bits) -+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? -+ "inflate: * literal '%c'\n" : -+ "inflate: * literal 0x%02x\n", t->base)); -+ *q++ = (Byte)t->base; -+ m--; -+ continue; -+ } -+ do { -+ DUMPBITS(t->bits) -+ if (e & 16) -+ { -+ /* get extra bits for length */ -+ e &= 15; -+ c = t->base + ((uInt)b & inflate_mask[e]); -+ DUMPBITS(e) -+ Tracevv((stderr, "inflate: * length %u\n", c)); -+ -+ /* decode distance base of block to copy */ -+ GRABBITS(15); /* max bits for distance code */ -+ e = (t = td + ((uInt)b & md))->exop; -+ do { -+ DUMPBITS(t->bits) -+ if (e & 16) -+ { -+ /* get extra bits to add to distance base */ -+ e &= 15; -+ GRABBITS(e) /* get extra bits (up to 13) */ -+ d = t->base + ((uInt)b & inflate_mask[e]); -+ DUMPBITS(e) -+ Tracevv((stderr, "inflate: * distance %u\n", d)); -+ -+ /* do the copy */ -+ m -= c; -+ if ((uInt)(q - s->window) >= d) /* offset before dest */ -+ { /* just copy */ -+ r = q - d; -+ *q++ = *r++; c--; /* minimum count is three, */ -+ *q++ = *r++; c--; /* so unroll loop a little */ -+ } -+ else /* else offset after destination */ -+ { -+ e = d - (q - s->window); /* bytes from offset to end */ -+ r = s->end - e; /* pointer to offset */ -+ if (c > e) /* if source crosses, */ -+ { -+ c -= e; /* copy to end of window */ -+ do { -+ *q++ = *r++; -+ } while (--e); -+ r = s->window; /* copy rest from start of window */ -+ } -+ } -+ do { /* copy all or what's left */ -+ *q++ = *r++; -+ } while (--c); -+ break; -+ } -+ else if ((e & 64) == 0) -+ e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop; -+ else -+ { -+ z->msg = "invalid distance code"; -+ UNGRAB -+ UPDATE -+ return Z_DATA_ERROR; -+ } -+ } while (1); -+ break; -+ } -+ if ((e & 64) == 0) -+ { -+ if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0) -+ { -+ DUMPBITS(t->bits) -+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? -+ "inflate: * literal '%c'\n" : -+ "inflate: * literal 0x%02x\n", t->base)); -+ *q++ = (Byte)t->base; -+ m--; -+ break; -+ } -+ } -+ else if (e & 32) -+ { -+ Tracevv((stderr, "inflate: * end of block\n")); -+ UNGRAB -+ UPDATE -+ return Z_STREAM_END; -+ } -+ else -+ { -+ z->msg = "invalid literal/length code"; -+ UNGRAB -+ UPDATE -+ return Z_DATA_ERROR; -+ } -+ } while (1); -+ } while (m >= 258 && n >= 10); -+ -+ /* not enough input or output--restore pointers and return */ -+ UNGRAB -+ UPDATE -+ return Z_OK; -+} -+ -+ -+/*+++++*/ -+/* zutil.c -- target dependent utility functions for the compression library -+ * Copyright (C) 1995 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */ -+ -+char *zlib_version = ZLIB_VERSION; -+ -+char *z_errmsg[] = { -+"stream end", /* Z_STREAM_END 1 */ -+"", /* Z_OK 0 */ -+"file error", /* Z_ERRNO (-1) */ -+"stream error", /* Z_STREAM_ERROR (-2) */ -+"data error", /* Z_DATA_ERROR (-3) */ -+"insufficient memory", /* Z_MEM_ERROR (-4) */ -+"buffer error", /* Z_BUF_ERROR (-5) */ -+""}; -+ -+ -+/*+++++*/ -+/* adler32.c -- compute the Adler-32 checksum of a data stream -+ * Copyright (C) 1995 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */ -+ -+#define BASE 65521L /* largest prime smaller than 65536 */ -+#define NMAX 5552 -+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ -+ -+#define DO1(buf) {s1 += *buf++; s2 += s1;} -+#define DO2(buf) DO1(buf); DO1(buf); -+#define DO4(buf) DO2(buf); DO2(buf); -+#define DO8(buf) DO4(buf); DO4(buf); -+#define DO16(buf) DO8(buf); DO8(buf); -+ -+/* ========================================================================= */ -+uLong adler32(adler, buf, len) -+ uLong adler; -+ Bytef *buf; -+ uInt len; -+{ -+ unsigned long s1 = adler & 0xffff; -+ unsigned long s2 = (adler >> 16) & 0xffff; -+ int k; -+ -+ if (buf == Z_NULL) return 1L; -+ -+ while (len > 0) { -+ k = len < NMAX ? len : NMAX; -+ len -= k; -+ while (k >= 16) { -+ DO16(buf); -+ k -= 16; -+ } -+ if (k != 0) do { -+ DO1(buf); -+ } while (--k); -+ s1 %= BASE; -+ s2 %= BASE; -+ } -+ return (s2 << 16) | s1; -+} -diff -Naru linux/arch/mips/zboot/Makefile linux.spi/arch/mips/zboot/Makefile ---- linux/arch/mips/zboot/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/Makefile 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,84 @@ -+# -+# arch/mips/zboot/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. -+ -+# Adapted for MIPS Pete Popov, Dan Malek -+# -+# Copyright (C) 1994 by Linus Torvalds -+# Adapted for PowerPC by Gary Thomas -+# modified by Cort (cort@cs.nmt.edu) -+# -+ -+.c.s: -+ $(CC) $(CFLAGS) -S -o $*.s $< -+.s.o: -+ $(AS) -o $*.o $< -+.c.o: -+ $(CC) $(CFLAGS) -c -o $*.o $< -+.S.s: -+ $(CPP) $(AFLAGS) -o $*.o $< -+.S.o: -+ $(CC) $(AFLAGS) -c -o $*.o $< -+ -+GZIP_FLAGS = -v9f -+ -+CFLAGS += -D__BOOTER__ -I$(TOPDIR)/arch/$(ARCH)/zboot/include -+AFLAGS += -D__BOOTER__ -+ -+BOOT_TARGETS = zImage zImage.initrd zImage.flash zImage.initrd.flash -+ -+lib/zlib.a: -+ $(MAKE) -C lib -+ -+images/vmlinux.gz: $(TOPDIR)/vmlinux -+ $(MAKE) -C images vmlinux.gz -+ -+$(BOOT_TARGETS): lib/zlib.a images/vmlinux.gz -+ifdef CONFIG_MIPS_PB1000 -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_MIPS_PB1500 -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_MIPS_PB1100 -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_MIPS_PB1550 -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_MIPS_DB1000 -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_MIPS_DB1100 -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_MIPS_DB1500 -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_MIPS_BOSPORUS -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_MIPS_MIRAGE -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_MIPS_MTX1 -+ $(MAKE) -C pb1xxx $@ -+endif -+ifdef CONFIG_COGENT_CSB250 -+ $(MAKE) -C csb250 $@ -+endif -+ifdef CONFIG_MIPS_XXS1500 -+BOOT_DIR = xxs1500 -+endif -+ -+# Do the dirs -+clean: -+ $(MAKE) -C common clean -+ $(MAKE) -C images clean -+ $(MAKE) -C pb1xxx clean -+ $(MAKE) -C xxs1500 clean -+ -+include $(TOPDIR)/Rules.make -diff -Naru linux/arch/mips/zboot/pb1xxx/head.S linux.spi/arch/mips/zboot/pb1xxx/head.S ---- linux/arch/mips/zboot/pb1xxx/head.S 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/pb1xxx/head.S 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,149 @@ -+/* -+ * arch/mips/kernel/head.S -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 1994, 1995 Waldorf Electronics -+ * Written by Ralf Baechle and Andreas Busse -+ * Copyright (C) 1995 - 1999 Ralf Baechle -+ * Copyright (C) 1996 Paul M. Antoine -+ * Modified for DECStation and hence R3000 support by Paul M. Antoine -+ * Further modifications by David S. Miller and Harald Koerfgen -+ * Copyright (C) 1999 Silicon Graphics, Inc. -+ * -+ * Head.S contains the MIPS exception handler and startup code. -+ * -+ ************************************************************************** -+ * 9 Nov, 2000. -+ * Added Cache Error exception handler and SBDDP EJTAG debug exception. -+ * -+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com -+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. -+ ************************************************************************** -+ */ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define IndexInvalidate_I 0x00 -+#define IndexWriteBack_D 0x01 -+ -+ .set noreorder -+ .cprestore -+ LEAF(start) -+start: -+ bal locate -+ nop -+locate: -+ subu s8, ra, 8 /* Where we were loaded */ -+ la sp, (.stack + 8192) -+ -+ move s0, a0 /* Save boot rom start args */ -+ move s1, a1 -+ move s2, a2 -+ move s3, a3 -+ -+ la a0, start /* Where we were linked to run */ -+ -+ move a1, s8 -+ la a2, _edata -+ subu t1, a2, a0 -+ srl t1, t1, 2 -+ -+ /* copy text section */ -+ li t0, 0 -+1: lw v0, 0(a1) -+ nop -+ sw v0, 0(a0) -+ xor t0, t0, v0 -+ addu a0, 4 -+ bne a2, a0, 1b -+ addu a1, 4 -+ -+ /* Clear BSS */ -+ la a0, _edata -+ la a2, _end -+2: sw zero, 0(a0) -+ bne a2, a0, 2b -+ addu a0, 4 -+ -+ /* push the D-Cache and invalidate I-Cache */ -+ li k0, 0x80000000 # start address -+ li k1, 0x80004000 # end address (16KB I-Cache) -+ subu k1, 128 -+ -+1: -+ .set mips3 -+ cache IndexWriteBack_D, 0(k0) -+ cache IndexWriteBack_D, 32(k0) -+ cache IndexWriteBack_D, 64(k0) -+ cache IndexWriteBack_D, 96(k0) -+ cache IndexInvalidate_I, 0(k0) -+ cache IndexInvalidate_I, 32(k0) -+ cache IndexInvalidate_I, 64(k0) -+ cache IndexInvalidate_I, 96(k0) -+ .set mips0 -+ -+ bne k0, k1, 1b -+ addu k0, k0, 128 -+ /* done */ -+ -+ move a0, s8 /* load address */ -+ move a1, t1 /* length in words */ -+ move a2, t0 /* checksum */ -+ move a3, sp -+ -+ la ra, 1f -+ la k0, decompress_kernel -+ jr k0 -+ nop -+1: -+ -+ move a0, s0 -+ move a1, s1 -+ move a2, s2 -+ move a3, s3 -+ li k0, KERNEL_ENTRY -+ jr k0 -+ nop -+3: -+ b 3b -+ END(start) -+ -+ LEAF(udelay) -+udelay: -+ END(udelay) -+ -+ -+ LEAF(FlushCache) -+ li k0, 0x80000000 # start address -+ li k1, 0x80004000 # end address (16KB I-Cache) -+ subu k1, 128 -+ -+1: -+ .set mips3 -+ cache IndexWriteBack_D, 0(k0) -+ cache IndexWriteBack_D, 32(k0) -+ cache IndexWriteBack_D, 64(k0) -+ cache IndexWriteBack_D, 96(k0) -+ cache IndexInvalidate_I, 0(k0) -+ cache IndexInvalidate_I, 32(k0) -+ cache IndexInvalidate_I, 64(k0) -+ cache IndexInvalidate_I, 96(k0) -+ .set mips0 -+ -+ bne k0, k1, 1b -+ addu k0, k0, 128 -+ jr ra -+ nop -+ END(FlushCache) -+ -+ .comm .stack,4096*2,4 -diff -Naru linux/arch/mips/zboot/pb1xxx/Makefile linux.spi/arch/mips/zboot/pb1xxx/Makefile ---- linux/arch/mips/zboot/pb1xxx/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/pb1xxx/Makefile 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,135 @@ -+# arch/mips/zboot/pb1xxx/Makefile -+# -+# Makefile for Alchemy Semiconductor Pb1[015]00 boards. -+# All of the boot loader code was derived from the ppc -+# boot code. -+# -+# Copyright 2001,2002 MontaVista Software Inc. -+# -+# Author: Mark A. Greer -+# mgreer@mvista.com -+# Ported and modified for mips support by -+# Pete Popov -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by the -+# Free Software Foundation; either version 2 of the License, or (at your -+# option) any later version. -+ -+.c.s: -+ $(CC) $(CFLAGS) -S -o $*.s $< -+.s.o: -+ $(AS) -o $*.o $< -+.c.o: -+ $(CC) $(CFLAGS) -D__BOOTER__ -c -o $*.o $< -+.S.s: -+ $(CPP) $(AFLAGS) -o $*.o $< -+.S.o: -+ $(CC) $(AFLAGS) -c -o $*.o $< -+ -+######################################################################### -+# START BOARD SPECIFIC VARIABLES -+ifdef CONFIG_MIPS_PB1000 -+BNAME=pb1000 -+endif -+ -+ifdef CONFIG_MIPS_PB1100 -+BNAME=pb1100 -+endif -+ -+ifdef CONFIG_MIPS_PB1500 -+BNAME=pb1500 -+endif -+ -+ifdef CONFIG_MIPS_PB1550 -+BNAME=pb1550 -+endif -+ -+ifdef CONFIG_MIPS_DB1000 -+BNAME=db1000 -+endif -+ -+ifdef CONFIG_MIPS_DB1100 -+BNAME=db1100 -+endif -+ -+ifdef CONFIG_MIPS_DB1500 -+BNAME=db1500 -+endif -+ -+ifdef CONFIG_MIPS_BOSPORUS -+BNAME=bosporus -+endif -+ -+ifdef CONFIG_MIPS_MIRAGE -+BNAME=mirage -+endif -+ -+ifdef CONFIG_MIPS_MTX1 -+BNAME=mtx-1 -+endif -+ -+# These two variables control where the zImage is stored -+# in flash and loaded in memory. It only controls how the srec -+# file is generated, the code is the same. -+RAM_RUN_ADDR = 0x81000000 -+FLASH_LOAD_ADDR = 0xBFD00000 -+ -+# These two variables specify the free ram region -+# that can be used for temporary malloc area -+AVAIL_RAM_START=0x80400000 -+AVAIL_RAM_END=0x80800000 -+ -+# This one must match the LOADADDR in arch/mips/Makefile! -+LOADADDR=0x80100000 -+# END BOARD SPECIFIC VARIABLES -+######################################################################### -+ -+OBJECTS := head.o ../common/misc-common.o ../common/misc-simple.o \ -+ ../common/au1k_uart.o ../common/string.o ../common/ctype.o -+LIBS := ../lib/zlib.a -+ -+ENTRY := ../utils/entry -+OFFSET := ../utils/offset -+SIZE := ../utils/size -+ -+LD_ARGS := -T ../ld.script -Ttext $(RAM_RUN_ADDR) -Bstatic -+OBJCOPY_ARGS = -O elf32-tradlittlemips -+ -+all: zImage -+ -+clean: -+ rm -rf *.o vmlinux* zvmlinux.* ../images/*.srec -+ -+head.o: head.S $(TOPDIR)/vmlinux -+ $(CC) $(AFLAGS) \ -+ -DKERNEL_ENTRY=$(shell sh $(ENTRY) $(NM) $(TOPDIR)/vmlinux ) \ -+ -c -o $*.o $< -+ -+../common/misc-simple.o: -+ $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \ -+ -DAVAIL_RAM_START=$(AVAIL_RAM_START) \ -+ -DAVAIL_RAM_END=$(AVAIL_RAM_END) \ -+ -DLOADADDR=$(LOADADDR) \ -+ -DZIMAGE_SIZE=0 -c -o $@ $*.c -+ -+zvmlinux: $(OBJECTS) $(LIBS) ../ld.script ../images/vmlinux.gz ../common/dummy.o -+ $(OBJCOPY) \ -+ --add-section=.image=../images/vmlinux.gz \ -+ --set-section-flags=.image=contents,alloc,load,readonly,data \ -+ ../common/dummy.o image.o -+ $(LD) $(LD_ARGS) -o $@ $(OBJECTS) image.o $(LIBS) -+ $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr \ -+ -R .initrd -R .sysmap -+ -+# Here we manipulate the image in order to get it the necessary -+# srecord file we need. -+zImage: zvmlinux -+ mv zvmlinux ../images/zImage.$(BNAME) -+ $(OBJCOPY) -O srec ../images/zImage.$(BNAME) ../images/$(BNAME).srec -+ -+zImage.flash: zImage -+ $(OBJCOPY) -O srec --adjust-vma 0x3ed00000 \ -+ ../images/zImage.$(BNAME) ../images/$(BNAME).flash.srec -+ -+include $(TOPDIR)/Rules.make -diff -Naru linux/arch/mips/zboot/utils/entry linux.spi/arch/mips/zboot/utils/entry ---- linux/arch/mips/zboot/utils/entry 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/utils/entry 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,12 @@ -+#!/bin/sh -+ -+# grab the kernel_entry address from the vmlinux elf image -+entry=`$1 $2 | grep kernel_entry` -+ -+fs=`echo $entry | grep ffffffff` # check toolchain output -+ -+if [ -n "$fs" ]; then -+ echo "0x"`$1 $2 | grep kernel_entry | cut -c9- | awk '{print $1}'` -+else -+ echo "0x"`$1 $2 | grep kernel_entry | cut -c1- | awk '{print $1}'` -+fi -diff -Naru linux/arch/mips/zboot/utils/offset linux.spi/arch/mips/zboot/utils/offset ---- linux/arch/mips/zboot/utils/offset 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/utils/offset 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,3 @@ -+#!/bin/sh -+ -+echo "0x"`$1 -h $2 | grep $3 | grep -v zvmlinux| awk '{print $6}'` -diff -Naru linux/arch/mips/zboot/utils/size linux.spi/arch/mips/zboot/utils/size ---- linux/arch/mips/zboot/utils/size 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/utils/size 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,4 @@ -+#!/bin/sh -+ -+OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux | awk '{print $3}'` -+echo "0x"$OFFSET -diff -Naru linux/arch/mips/zboot/xxs1500/head.S linux.spi/arch/mips/zboot/xxs1500/head.S ---- linux/arch/mips/zboot/xxs1500/head.S 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/xxs1500/head.S 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,137 @@ -+/* -+ * arch/mips/kernel/head.S -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 1994, 1995 Waldorf Electronics -+ * Written by Ralf Baechle and Andreas Busse -+ * Copyright (C) 1995 - 1999 Ralf Baechle -+ * Copyright (C) 1996 Paul M. Antoine -+ * Modified for DECStation and hence R3000 support by Paul M. Antoine -+ * Further modifications by David S. Miller and Harald Koerfgen -+ * Copyright (C) 1999 Silicon Graphics, Inc. -+ * -+ * Head.S contains the MIPS exception handler and startup code. -+ * -+ ************************************************************************** -+ * 9 Nov, 2000. -+ * Added Cache Error exception handler and SBDDP EJTAG debug exception. -+ * -+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com -+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. -+ ************************************************************************** -+ */ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define IndexInvalidate_I 0x00 -+ -+ .set noreorder -+ .cprestore -+ LEAF(start) -+start: -+ -+locate: -+ la sp, .stack -+ move s0, a0 -+ move s1, a1 -+ move s2, a2 -+ move s3, a3 -+ -+ la a0, start -+ -+ li a1, FLASH_LOAD_ADDR -+ la a2, _edata -+ subu t1, a2, a0 -+ srl t1, t1, 2 -+ -+ /* copy text section */ -+ li t0, 0 -+1: lw v0, 0(a1) -+ nop -+ sw v0, 0(a0) -+ xor t0, t0, v0 -+ addu a0, 4 -+ bne a2, a0, 1b -+ addu a1, 4 -+ -+ /* Clear BSS */ -+ la a0, _edata -+ la a2, _end -+2: sw zero, 0(a0) -+ bne a2, a0, 2b -+ addu a0, 4 -+ -+ /* flush the I-Cache */ -+ li k0, 0x80000000 # start address -+ li k1, 0x80004000 # end address (16KB I-Cache) -+ subu k1, 128 -+ -+1: -+ .set mips3 -+ cache IndexInvalidate_I, 0(k0) -+ cache IndexInvalidate_I, 32(k0) -+ cache IndexInvalidate_I, 64(k0) -+ cache IndexInvalidate_I, 96(k0) -+ .set mips0 -+ -+ bne k0, k1, 1b -+ addu k0, k0, 128 -+ /* done */ -+ -+ li a0, FLASH_LOAD_ADDR /* load address */ -+ move a1, t1 /* length in words */ -+ move a2, t0 /* checksum */ -+ move a3, sp -+ -+ la ra, 1f -+ la k0, decompress_kernel -+ jr k0 -+ nop -+1: -+ -+ move a0, s0 -+ move a1, s1 -+ move a2, s2 -+ move a3, s3 -+ li k0, KERNEL_ENTRY -+ jr k0 -+ nop -+3: -+ b 3b -+ END(start) -+ -+ LEAF(udelay) -+udelay: -+ END(udelay) -+ -+ -+ LEAF(FlushCache) -+ li k0, 0x80000000 # start address -+ li k1, 0x80004000 # end address (16KB I-Cache) -+ subu k1, 128 -+ -+1: -+ .set mips3 -+ cache IndexInvalidate_I, 0(k0) -+ cache IndexInvalidate_I, 32(k0) -+ cache IndexInvalidate_I, 64(k0) -+ cache IndexInvalidate_I, 96(k0) -+ .set mips0 -+ -+ bne k0, k1, 1b -+ addu k0, k0, 128 -+ jr ra -+ nop -+ END(FlushCache) -+ -+ .comm .stack,4096*2,4 -diff -Naru linux/arch/mips/zboot/xxs1500/ld.script linux.spi/arch/mips/zboot/xxs1500/ld.script ---- linux/arch/mips/zboot/xxs1500/ld.script 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/xxs1500/ld.script 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,147 @@ -+OUTPUT_ARCH(mips) -+ENTRY(start) -+SECTIONS -+{ -+ /* Read-only sections, merged into text segment: */ -+ /* . = 0x81000000; */ -+ .init : { *(.init) } =0 -+ .text : -+ { -+ _ftext = . ; -+ *(.text) -+ *(.rodata) -+ *(.rodata1) -+ /* .gnu.warning sections are handled specially by elf32.em. */ -+ *(.gnu.warning) -+ } =0 -+ .kstrtab : { *(.kstrtab) } -+ -+ . = ALIGN(16); /* Exception table */ -+ __start___ex_table = .; -+ __ex_table : { *(__ex_table) } -+ __stop___ex_table = .; -+ -+ __start___dbe_table = .; /* Exception table for data bus errors */ -+ __dbe_table : { *(__dbe_table) } -+ __stop___dbe_table = .; -+ -+ __start___ksymtab = .; /* Kernel symbol table */ -+ __ksymtab : { *(__ksymtab) } -+ __stop___ksymtab = .; -+ -+ _etext = .; -+ -+ . = ALIGN(8192); -+ .data.init_task : { *(.data.init_task) } -+ -+ /* Startup code */ -+ . = ALIGN(4096); -+ __init_begin = .; -+ .text.init : { *(.text.init) } -+ .data.init : { *(.data.init) } -+ . = ALIGN(16); -+ __setup_start = .; -+ .setup.init : { *(.setup.init) } -+ __setup_end = .; -+ __initcall_start = .; -+ .initcall.init : { *(.initcall.init) } -+ __initcall_end = .; -+ . = ALIGN(4096); /* Align double page for init_task_union */ -+ __init_end = .; -+ -+ . = ALIGN(4096); -+ .data.page_aligned : { *(.data.idt) } -+ -+ . = ALIGN(32); -+ .data.cacheline_aligned : { *(.data.cacheline_aligned) } -+ -+ .fini : { *(.fini) } =0 -+ .reginfo : { *(.reginfo) } -+ /* Adjust the address for the data segment. We want to adjust up to -+ the same address within the page on the next page up. It would -+ be more correct to do this: -+ . = .; -+ The current expression does not correctly handle the case of a -+ text segment ending precisely at the end of a page; it causes the -+ data segment to skip a page. The above expression does not have -+ this problem, but it will currently (2/95) cause BFD to allocate -+ a single segment, combining both text and data, for this case. -+ This will prevent the text segment from being shared among -+ multiple executions of the program; I think that is more -+ important than losing a page of the virtual address space (note -+ that no actual memory is lost; the page which is skipped can not -+ be referenced). */ -+ . = .; -+ .data : -+ { -+ _fdata = . ; -+ *(.data) -+ -+ /* Align the initial ramdisk image (INITRD) on page boundaries. */ -+ . = ALIGN(4096); -+ __rd_start = .; -+ *(.initrd) -+ __rd_end = .; -+ . = ALIGN(4096); -+ -+ CONSTRUCTORS -+ } -+ .data1 : { *(.data1) } -+ _gp = . + 0x8000; -+ .lit8 : { *(.lit8) } -+ .lit4 : { *(.lit4) } -+ .ctors : { *(.ctors) } -+ .dtors : { *(.dtors) } -+ .got : { *(.got.plt) *(.got) } -+ .dynamic : { *(.dynamic) } -+ /* We want the small data sections together, so single-instruction offsets -+ can access them all, and initialized data all before uninitialized, so -+ we can shorten the on-disk segment size. */ -+ .sdata : { *(.sdata) } -+ . = ALIGN(4); -+ _edata = .; -+ PROVIDE (edata = .); -+ -+ __bss_start = .; -+ _fbss = .; -+ .sbss : { *(.sbss) *(.scommon) } -+ .bss : -+ { -+ *(.dynbss) -+ *(.bss) -+ *(COMMON) -+ . = ALIGN(4); -+ _end = . ; -+ PROVIDE (end = .); -+ } -+ -+ /* Sections to be discarded */ -+ /DISCARD/ : -+ { -+ *(.text.exit) -+ *(.data.exit) -+ *(.exitcall.exit) -+ } -+ -+ /* This is the MIPS specific mdebug section. */ -+ .mdebug : { *(.mdebug) } -+ /* These are needed for ELF backends which have not yet been -+ converted to the new style linker. */ -+ .stab 0 : { *(.stab) } -+ .stabstr 0 : { *(.stabstr) } -+ /* DWARF debug sections. -+ Symbols in the .debug DWARF section are relative to the beginning of the -+ section so we begin .debug at 0. It's not clear yet what needs to happen -+ for the others. */ -+ .debug 0 : { *(.debug) } -+ .debug_srcinfo 0 : { *(.debug_srcinfo) } -+ .debug_aranges 0 : { *(.debug_aranges) } -+ .debug_pubnames 0 : { *(.debug_pubnames) } -+ .debug_sfnames 0 : { *(.debug_sfnames) } -+ .line 0 : { *(.line) } -+ /* These must appear regardless of . */ -+ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } -+ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } -+ .comment : { *(.comment) } -+ .note : { *(.note) } -+} -diff -Naru linux/arch/mips/zboot/xxs1500/Makefile linux.spi/arch/mips/zboot/xxs1500/Makefile ---- linux/arch/mips/zboot/xxs1500/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ linux.spi/arch/mips/zboot/xxs1500/Makefile 2004-05-11 23:19:24.000000000 -0400 -@@ -0,0 +1,123 @@ -+# arch/mips/compressed/alchemy/Makefile -+# -+# Makefile for Alchemy Semiconductor Pb1[015]00 boards. -+# All of the boot loader code was derived from the ppc -+# boot code. -+# -+# Copyright 2001,2002 MontaVista Software Inc. -+# -+# Author: Mark A. Greer -+# mgreer@mvista.com -+# Ported and modified for mips support by -+# Pete Popov -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by the -+# Free Software Foundation; either version 2 of the License, or (at your -+# option) any later version. -+ -+.c.s: -+ $(CC) $(CFLAGS) -S -o $*.s $< -+.s.o: -+ $(AS) -o $*.o $< -+.c.o: -+ $(CC) $(CFLAGS) -D__BOOTER__ -c -o $*.o $< -+.S.s: -+ $(CPP) $(AFLAGS) -o $*.o $< -+.S.o: -+ $(CC) $(AFLAGS) -c -o $*.o $< -+ -+######################################################################### -+# START BOARD SPECIFIC VARIABLES -+BNAME=xxs1500 -+ -+ -+# These two variables control where the zImage is stored -+# in flash and loaded in memory. If you change either one, -+# be sure to make the appropriate change to the zImage -+# rule. -+RAM_LOAD_ADDR = 0x81000000 -+FLASH_LOAD_ADDR = 0xBF000000 -+ -+# These two variables specify the free ram region -+# that can be used for temporary malloc area -+AVAIL_RAM_START=0x80400000 -+AVAIL_RAM_END=0x80800000 -+ -+# This one must match the LOADADDR in arch/mips/Makefile! -+LOADADDR=0x80100000 -+# END BOARD SPECIFIC VARIABLES -+######################################################################### -+ -+ZLINKFLAGS = -T ld.script -Ttext $(RAM_LOAD_ADDR) -+ -+OBJECTS := head.o ../common/misc-common.o ../common/misc-simple.o \ -+ ../common/au1k_uart.o ../common/string.o ../common/ctype.o -+LIBS := ../lib/zlib.a -+ -+ENTRY := ../utils/entry -+OFFSET := ../utils/offset -+SIZE := ../utils/size -+ -+all: zImage -+ -+clean: -+ rm -rf *.o vmlinux* zvmlinux.* -+ -+head.o: head.S $(TOPDIR)/vmlinux -+ $(CC) -DFLASH_LOAD_ADDR=$(FLASH_LOAD_ADDR) $(AFLAGS) \ -+ -DKERNEL_ENTRY=$(shell sh $(ENTRY) $(NM) $(TOPDIR)/vmlinux ) \ -+ -c -o $*.o $< -+ -+../common/misc-simple.o: -+ $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \ -+ -DAVAIL_RAM_START=$(AVAIL_RAM_START) \ -+ -DAVAIL_RAM_END=$(AVAIL_RAM_END) \ -+ -DLOADADDR=$(LOADADDR) \ -+ -DZIMAGE_SIZE=0 -c -o $@ $*.c -+ -+# This is the first pass at building the boot loader image, -+# without knowing the file offset where the vmlinuz.gz -+# kernel will end up. We build this image, check the offset, -+# and then rebuild it with the correct offset and size -+# passed to mips-simple.c -+zvmlinux.no: $(OBJECTS) $(LIBS) ../images/vmlinux.gz -+ $(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS) -+ $(OBJCOPY) -R .comment \ -+ --add-section=image=../images/vmlinux.gz \ -+ $@.tmp $@ -+ # rm -f $@.tmp -+ -+ -+# This is the final image we build, now that we know what -+# the vmlinuz.gz offset is. -+zvmlinux: $(OBJECTS) $(LIBS) ../images/vmlinux.gz zvmlinux.no -+ $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \ -+ -DZIMAGE_OFFSET=$(shell sh $(OFFSET) $(OBJDUMP) $@.no image) \ -+ -DZIMAGE_SIZE=$(shell sh $(SIZE) $(OBJDUMP) $@.no image) \ -+ -D__BOOTER__ \ -+ -DAVAIL_RAM_START=$(AVAIL_RAM_START) \ -+ -DAVAIL_RAM_END=$(AVAIL_RAM_END) \ -+ -DLOADADDR=$(LOADADDR) \ -+ -c -o ../common/misc-simple.o ../common/misc-simple.c -+ $(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS) -+ $(OBJCOPY) -R .comment \ -+ --add-section=image=../images/vmlinux.gz \ -+ $@.tmp $@ -+ $(OBJCOPY) --adjust-section-vma=image+$(RAM_LOAD_ADDR) $@ -+ $(OBJCOPY) --adjust-section-vma=image+$(shell sh $(OFFSET) \ -+ $(OBJDUMP) $@.no image ) $@ -+ # rm -f $@.tmp -+ # rm -f $@.no -+ -+ -+# Here we manipulate the image in order to get it the necessary -+# srecord file we need. -+zImage: zvmlinux -+ mv zvmlinux ../images/$@.$(BNAME) -+ $(OBJCOPY) --set-section-flags=image=alloc,load,code ../images/$@.$(BNAME) -+ $(OBJCOPY) -O srec --adjust-vma 0x3e000000 \ -+ ../images/$@.$(BNAME) ../images/$@.$(BNAME).srec -+ # rm ../images/vmlinux.gz -+ -+include $(TOPDIR)/Rules.make diff --git a/linux/linux-mtx-1-2.4.27/07-zboot-zimage-flash-bin.diff b/linux/linux-mtx-1-2.4.27/07-zboot-zimage-flash-bin.diff deleted file mode 100644 index dca79a3000..0000000000 --- a/linux/linux-mtx-1-2.4.27/07-zboot-zimage-flash-bin.diff +++ /dev/null @@ -1,11 +0,0 @@ -diff -Nurb oe/tmp/work/linux-mtx-1-2.4.27-r0/linux/arch/mips/zboot/pb1xxx/Makefile linux.m/arch/mips/zboot/pb1xxx/Makefile ---- oe/tmp/work/linux-mtx-1-2.4.27-r0/linux/arch/mips/zboot/pb1xxx/Makefile 2004-10-13 21:08:49.840408328 +0200 -+++ linux.m/arch/mips/zboot/pb1xxx/Makefile 2004-10-13 21:08:29.736464592 +0200 -@@ -131,5 +131,7 @@ - zImage.flash: zImage - $(OBJCOPY) -O srec --adjust-vma 0x3ed00000 \ - ../images/zImage.$(BNAME) ../images/$(BNAME).flash.srec -+ $(OBJCOPY) -O binary --adjust-vma 0x3ed00000 \ -+ ../images/zImage.$(BNAME) ../images/$(BNAME).flash.bin - - include $(TOPDIR)/Rules.make diff --git a/linux/linux-mtx-1-2.4.27/08-usb-nonpci-2.4.24.patch b/linux/linux-mtx-1-2.4.27/08-usb-nonpci-2.4.24.patch deleted file mode 100644 index ca093e1a67..0000000000 --- a/linux/linux-mtx-1-2.4.27/08-usb-nonpci-2.4.24.patch +++ /dev/null @@ -1,3185 +0,0 @@ -diff -Nurb linux-mips-2.4.27/drivers/usb/host/Config.in linux/drivers/usb/host/Config.in ---- linux-mips-2.4.27/drivers/usb/host/Config.in 2003-11-17 02:07:42.000000000 +0100 -+++ linux/drivers/usb/host/Config.in 2004-11-23 11:24:10.599627448 +0100 -@@ -17,3 +17,4 @@ - dep_tristate ' SL811HS Alternate (x86, StrongARM, isosynchronous mode)' CONFIG_USB_SL811HS_ALT $CONFIG_USB $CONFIG_EXPERIMENTAL - dep_tristate ' SL811HS (x86, StrongARM) support, old driver' CONFIG_USB_SL811HS $CONFIG_USB $CONFIG_EXPERIMENTAL - fi -+dep_tristate ' Non-PCI OHCI support' CONFIG_USB_NON_PCI_OHCI $CONFIG_USB_OHCI -diff -Nurb linux-mips-2.4.27/drivers/usb/host/usb-ohci.c linux/drivers/usb/host/usb-ohci.c ---- linux-mips-2.4.27/drivers/usb/host/usb-ohci.c 2004-04-16 05:14:18.000000000 +0200 -+++ linux/drivers/usb/host/usb-ohci.c 2004-11-23 11:24:10.602626992 +0100 -@@ -2564,6 +2564,7 @@ - hc_release_ohci (ohci); - return ret; - } -+#ifndef CONFIG_USB_NON_PCI_OHCI - ohci->flags = id->driver_data; - - /* Check for NSC87560. We have to look at the bridge (fn1) to identify -@@ -2582,6 +2583,7 @@ - printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n"); - if (ohci->flags & OHCI_QUIRK_AMD756) - printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n"); -+#endif - - if (hc_reset (ohci) < 0) { - hc_release_ohci (ohci); -@@ -2627,8 +2629,10 @@ - int temp; - int i; - -+#ifndef CONFIG_USB_NON_PCI_OHCI - if (ohci->pci_latency) - pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency); -+#endif - - ohci->disabled = 1; - ohci->sleeping = 0; -@@ -2658,6 +2662,7 @@ - - /*-------------------------------------------------------------------------*/ - -+#ifndef CONFIG_USB_NON_PCI_OHCI - /* configured so that an OHCI device is always provided */ - /* always called with process context; sleeping is OK */ - -@@ -2705,6 +2710,88 @@ - } - return status; - } -+#else /* CONFIG_USB_NON_PCI_OHCI */ -+ -+// Boot options -+static int ohci_base=0, ohci_len=0; -+static int ohci_irq=-1; -+ -+MODULE_PARM(ohci_base, "i"); -+MODULE_PARM(ohci_len, "i"); -+MODULE_PARM(ohci_irq, "i"); -+MODULE_PARM_DESC(ohci_base, "IO Base address of OHCI Oper. registers"); -+MODULE_PARM_DESC(ohci_len, "IO length of OHCI Oper. registers"); -+MODULE_PARM_DESC(ohci_irq, "IRQ for OHCI interrupts"); -+ -+// bogus pci_dev -+static struct pci_dev bogus_pcidev; -+ -+static struct pci_driver ohci_pci_driver = { -+ name: "usb-ohci", -+}; -+ -+static int __devinit -+ohci_non_pci_init (void) -+{ -+ void *mem_base; -+ -+ if (!ohci_base || !ohci_len || (ohci_irq < 0)) -+ return -ENODEV; -+ -+ if (!request_mem_region (ohci_base, ohci_len, ohci_pci_driver.name)) { -+ dbg ("controller already in use"); -+ return -EBUSY; -+ } -+ -+ mem_base = ioremap_nocache (ohci_base, ohci_len); -+ if (!mem_base) { -+ err("Error mapping OHCI memory"); -+ return -EFAULT; -+ } -+ -+ /* -+ * Fill in the bogus pci_dev. Only those members actually -+ * dereferenced in this driver are initialized. -+ */ -+ memset(&bogus_pcidev, 0, sizeof(struct pci_dev)); -+ strcpy(bogus_pcidev.name, "non-PCI OHCI"); -+ strcpy(bogus_pcidev.slot_name, "builtin"); -+ bogus_pcidev.resource[0].name = "OHCI Operational Registers"; -+ bogus_pcidev.resource[0].start = ohci_base; -+ bogus_pcidev.resource[0].end = ohci_base + ohci_len; -+ bogus_pcidev.resource[0].flags = 0; -+ bogus_pcidev.irq = ohci_irq; -+ -+ return hc_found_ohci (&bogus_pcidev, bogus_pcidev.irq, mem_base, NULL); -+} -+ -+#ifndef MODULE -+ -+static int __init -+ohci_setup (char* options) -+{ -+ char* this_opt; -+ -+ if (!options || !*options) -+ return 0; -+ -+ for(this_opt=strtok(options,",");this_opt;this_opt=strtok(NULL,",")) { -+ if (!strncmp(this_opt, "base:", 5)) { -+ ohci_base = simple_strtoul(this_opt+5, NULL, 0); -+ } else if (!strncmp(this_opt, "len:", 4)) { -+ ohci_len = simple_strtoul(this_opt+4, NULL, 0); -+ } else if (!strncmp(this_opt, "irq:", 4)) { -+ ohci_irq = simple_strtoul(this_opt+4, NULL, 0); -+ } -+ } -+ return 0; -+} -+ -+__setup("usb_ohci=", ohci_setup); -+ -+#endif /* !MODULE */ -+ -+#endif /* CONFIG_USB_NON_PCI_OHCI */ - - /*-------------------------------------------------------------------------*/ - -@@ -2745,6 +2832,7 @@ - } - - -+#ifndef CONFIG_USB_NON_PCI_OHCI - #ifdef CONFIG_PM - - /*-------------------------------------------------------------------------*/ -@@ -2983,20 +3071,29 @@ - resume: ohci_pci_resume, - #endif /* PM */ - }; -+#endif /* CONFIG_USB_NON_PCI_OHCI */ - - - /*-------------------------------------------------------------------------*/ - - static int __init ohci_hcd_init (void) - { -+#ifndef CONFIG_USB_NON_PCI_OHCI - return pci_module_init (&ohci_pci_driver); -+#else -+ return ohci_non_pci_init(); -+#endif - } - - /*-------------------------------------------------------------------------*/ - - static void __exit ohci_hcd_cleanup (void) - { -+#ifndef CONFIG_USB_NON_PCI_OHCI - pci_unregister_driver (&ohci_pci_driver); -+#else -+ ohci_pci_remove(&bogus_pcidev); -+#endif - } - - module_init (ohci_hcd_init); -diff -Nurb linux-mips-2.4.27/drivers/usb/host/usb-ohci.c.orig linux/drivers/usb/host/usb-ohci.c.orig ---- linux-mips-2.4.27/drivers/usb/host/usb-ohci.c.orig 1970-01-01 01:00:00.000000000 +0100 -+++ linux/drivers/usb/host/usb-ohci.c.orig 2004-11-23 11:21:54.984244120 +0100 -@@ -0,0 +1,3008 @@ -+/* -+ * URB OHCI HCD (Host Controller Driver) for USB. -+ * -+ * (C) Copyright 1999 Roman Weissgaerber -+ * (C) Copyright 2000-2001 David Brownell -+ * -+ * [ Initialisation is based on Linus' ] -+ * [ uhci code and gregs ohci fragments ] -+ * [ (C) Copyright 1999 Linus Torvalds ] -+ * [ (C) Copyright 1999 Gregory P. Smith] -+ * -+ * -+ * History: -+ * -+ * 2002/10/22 OHCI_USB_OPER for ALi lockup in IBM i1200 (ALEX ) -+ * 2002/03/08 interrupt unlink fix (Matt Hughes), better cleanup on -+ * load failure (Matthew Frederickson) -+ * 2002/01/20 async unlink fixes: return -EINPROGRESS (per spec) and -+ * make interrupt unlink-in-completion work (db) -+ * 2001/09/19 USB_ZERO_PACKET support (Jean Tourrilhes) -+ * 2001/07/17 power management and pmac cleanup (Benjamin Herrenschmidt) -+ * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam); -+ pci_map_single (db) -+ * 2001/03/21 td and dev/ed allocation uses new pci_pool API (db) -+ * 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam) -+ * -+ * 2000/09/26 fixed races in removing the private portion of the urb -+ * 2000/09/07 disable bulk and control lists when unlinking the last -+ * endpoint descriptor in order to avoid unrecoverable errors on -+ * the Lucent chips. (rwc@sgi) -+ * 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some -+ * urb unlink probs, indentation fixes -+ * 2000/08/11 various oops fixes mostly affecting iso and cleanup from -+ * device unplugs. -+ * 2000/06/28 use PCI hotplug framework, for better power management -+ * and for Cardbus support (David Brownell) -+ * 2000/earlier: fixes for NEC/Lucent chips; suspend/resume handling -+ * when the controller loses power; handle UE; cleanup; ... -+ * -+ * v5.2 1999/12/07 URB 3rd preview, -+ * v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi) -+ * v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume -+ * i386: HUB, Keyboard, Mouse, Printer -+ * -+ * v4.3 1999/10/27 multiple HCs, bulk_request -+ * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes -+ * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl. -+ * v4.0 1999/08/18 -+ * v3.0 1999/06/25 -+ * v2.1 1999/05/09 code clean up -+ * v2.0 1999/05/04 -+ * v1.0 1999/04/27 initial release -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* for in_interrupt() */ -+#undef DEBUG -+#include -+ -+#include -+#include -+#include -+#include -+ -+#define OHCI_USE_NPS // force NoPowerSwitching mode -+// #define OHCI_VERBOSE_DEBUG /* not always helpful */ -+ -+#include "usb-ohci.h" -+ -+#include "../hcd.h" -+ -+#ifdef CONFIG_PMAC_PBOOK -+#include -+#include -+#include -+#ifndef CONFIG_PM -+#define CONFIG_PM -+#endif -+#endif -+ -+ -+/* -+ * Version Information -+ */ -+#define DRIVER_VERSION "v5.3" -+#define DRIVER_AUTHOR "Roman Weissgaerber , David Brownell" -+#define DRIVER_DESC "USB OHCI Host Controller Driver" -+ -+/* For initializing controller (mask in an HCFS mode too) */ -+#define OHCI_CONTROL_INIT \ -+ (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE -+ -+#define OHCI_UNLINK_TIMEOUT (HZ / 10) -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* AMD-756 (D2 rev) reports corrupt register contents in some cases. -+ * The erratum (#4) description is incorrect. AMD's workaround waits -+ * till some bits (mostly reserved) are clear; ok for all revs. -+ */ -+#define read_roothub(hc, register, mask) ({ \ -+ u32 temp = readl (&hc->regs->roothub.register); \ -+ if (hc->flags & OHCI_QUIRK_AMD756) \ -+ while (temp & mask) \ -+ temp = readl (&hc->regs->roothub.register); \ -+ temp; }) -+ -+static u32 roothub_a (struct ohci *hc) -+ { return read_roothub (hc, a, 0xfc0fe000); } -+static inline u32 roothub_b (struct ohci *hc) -+ { return readl (&hc->regs->roothub.b); } -+static inline u32 roothub_status (struct ohci *hc) -+ { return readl (&hc->regs->roothub.status); } -+static u32 roothub_portstatus (struct ohci *hc, int i) -+ { return read_roothub (hc, portstatus [i], 0xffe0fce0); } -+ -+ -+/*-------------------------------------------------------------------------* -+ * URB support functions -+ *-------------------------------------------------------------------------*/ -+ -+static void ohci_complete_add(struct ohci *ohci, struct urb *urb) -+{ -+ -+ if (urb->hcpriv != NULL) { -+ printk("completing with non-null priv!\n"); -+ return; -+ } -+ -+ if (ohci->complete_tail == NULL) { -+ ohci->complete_head = urb; -+ ohci->complete_tail = urb; -+ } else { -+ ohci->complete_head->hcpriv = urb; -+ ohci->complete_tail = urb; -+ } -+} -+ -+static inline struct urb *ohci_complete_get(struct ohci *ohci) -+{ -+ struct urb *urb; -+ -+ if ((urb = ohci->complete_head) == NULL) -+ return NULL; -+ if (urb == ohci->complete_tail) { -+ ohci->complete_tail = NULL; -+ ohci->complete_head = NULL; -+ } else { -+ ohci->complete_head = urb->hcpriv; -+ } -+ urb->hcpriv = NULL; -+ return urb; -+} -+ -+static inline void ohci_complete(struct ohci *ohci) -+{ -+ struct urb *urb; -+ -+ spin_lock(&ohci->ohci_lock); -+ while ((urb = ohci_complete_get(ohci)) != NULL) { -+ spin_unlock(&ohci->ohci_lock); -+ if (urb->dev) { -+ usb_dec_dev_use (urb->dev); -+ urb->dev = NULL; -+ } -+ if (urb->complete) -+ (*urb->complete)(urb); -+ spin_lock(&ohci->ohci_lock); -+ } -+ spin_unlock(&ohci->ohci_lock); -+} -+ -+/* free HCD-private data associated with this URB */ -+ -+static void urb_free_priv (struct ohci *hc, urb_priv_t * urb_priv) -+{ -+ int i; -+ int last = urb_priv->length - 1; -+ int len; -+ int dir; -+ struct td *td; -+ -+ if (last >= 0) { -+ -+ /* ISOC, BULK, INTR data buffer starts at td 0 -+ * CTRL setup starts at td 0 */ -+ td = urb_priv->td [0]; -+ -+ len = td->urb->transfer_buffer_length, -+ dir = usb_pipeout (td->urb->pipe) -+ ? PCI_DMA_TODEVICE -+ : PCI_DMA_FROMDEVICE; -+ -+ /* unmap CTRL URB setup */ -+ if (usb_pipecontrol (td->urb->pipe)) { -+ pci_unmap_single (hc->ohci_dev, -+ td->data_dma, 8, PCI_DMA_TODEVICE); -+ -+ /* CTRL data buffer starts at td 1 if len > 0 */ -+ if (len && last > 0) -+ td = urb_priv->td [1]; -+ } -+ -+ /* unmap data buffer */ -+ if (len && td->data_dma) -+ pci_unmap_single (hc->ohci_dev, td->data_dma, len, dir); -+ -+ for (i = 0; i <= last; i++) { -+ td = urb_priv->td [i]; -+ if (td) -+ td_free (hc, td); -+ } -+ } -+ -+ kfree (urb_priv); -+} -+ -+static void urb_rm_priv_locked (struct urb * urb) -+{ -+ urb_priv_t * urb_priv = urb->hcpriv; -+ -+ if (urb_priv) { -+ urb->hcpriv = NULL; -+ -+#ifdef DO_TIMEOUTS -+ if (urb->timeout) { -+ list_del (&urb->urb_list); -+ urb->timeout -= jiffies; -+ } -+#endif -+ -+ /* Release int/iso bandwidth */ -+ if (urb->bandwidth) { -+ switch (usb_pipetype(urb->pipe)) { -+ case PIPE_INTERRUPT: -+ usb_release_bandwidth (urb->dev, urb, 0); -+ break; -+ case PIPE_ISOCHRONOUS: -+ usb_release_bandwidth (urb->dev, urb, 1); -+ break; -+ default: -+ break; -+ } -+ } -+ -+ urb_free_priv ((struct ohci *)urb->dev->bus->hcpriv, urb_priv); -+ } else { -+ if (urb->dev != NULL) { -+ err ("Non-null dev at rm_priv time"); -+ // urb->dev = NULL; -+ } -+ } -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+#ifdef DEBUG -+static int sohci_get_current_frame_number (struct usb_device * dev); -+ -+/* debug| print the main components of an URB -+ * small: 0) header + data packets 1) just header */ -+ -+static void urb_print (struct urb * urb, char * str, int small) -+{ -+ unsigned int pipe= urb->pipe; -+ -+ if (!urb->dev || !urb->dev->bus) { -+ dbg("%s URB: no dev", str); -+ return; -+ } -+ -+#ifndef OHCI_VERBOSE_DEBUG -+ if (urb->status != 0) -+#endif -+ dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,flags:%4x,len:%d/%d,stat:%d(%x)", -+ str, -+ sohci_get_current_frame_number (urb->dev), -+ usb_pipedevice (pipe), -+ usb_pipeendpoint (pipe), -+ usb_pipeout (pipe)? 'O': 'I', -+ usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"): -+ (usb_pipecontrol (pipe)? "CTRL": "BULK"), -+ urb->transfer_flags, -+ urb->actual_length, -+ urb->transfer_buffer_length, -+ urb->status, urb->status); -+#ifdef OHCI_VERBOSE_DEBUG -+ if (!small) { -+ int i, len; -+ -+ if (usb_pipecontrol (pipe)) { -+ printk (KERN_DEBUG __FILE__ ": cmd(8):"); -+ for (i = 0; i < 8 ; i++) -+ printk (" %02x", ((__u8 *) urb->setup_packet) [i]); -+ printk ("\n"); -+ } -+ if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) { -+ printk (KERN_DEBUG __FILE__ ": data(%d/%d):", -+ urb->actual_length, -+ urb->transfer_buffer_length); -+ len = usb_pipeout (pipe)? -+ urb->transfer_buffer_length: urb->actual_length; -+ for (i = 0; i < 16 && i < len; i++) -+ printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]); -+ printk ("%s stat:%d\n", i < len? "...": "", urb->status); -+ } -+ } -+#endif -+} -+ -+/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/ -+void ep_print_int_eds (ohci_t * ohci, char * str) { -+ int i, j; -+ __u32 * ed_p; -+ for (i= 0; i < 32; i++) { -+ j = 5; -+ ed_p = &(ohci->hcca->int_table [i]); -+ if (*ed_p == 0) -+ continue; -+ printk (KERN_DEBUG __FILE__ ": %s branch int %2d(%2x):", str, i, i); -+ while (*ed_p != 0 && j--) { -+ ed_t *ed = dma_to_ed (ohci, le32_to_cpup(ed_p)); -+ printk (" ed: %4x;", ed->hwINFO); -+ ed_p = &ed->hwNextED; -+ } -+ printk ("\n"); -+ } -+} -+ -+ -+static void ohci_dump_intr_mask (char *label, __u32 mask) -+{ -+ dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s", -+ label, -+ mask, -+ (mask & OHCI_INTR_MIE) ? " MIE" : "", -+ (mask & OHCI_INTR_OC) ? " OC" : "", -+ (mask & OHCI_INTR_RHSC) ? " RHSC" : "", -+ (mask & OHCI_INTR_FNO) ? " FNO" : "", -+ (mask & OHCI_INTR_UE) ? " UE" : "", -+ (mask & OHCI_INTR_RD) ? " RD" : "", -+ (mask & OHCI_INTR_SF) ? " SF" : "", -+ (mask & OHCI_INTR_WDH) ? " WDH" : "", -+ (mask & OHCI_INTR_SO) ? " SO" : "" -+ ); -+} -+ -+static void maybe_print_eds (char *label, __u32 value) -+{ -+ if (value) -+ dbg ("%s %08x", label, value); -+} -+ -+static char *hcfs2string (int state) -+{ -+ switch (state) { -+ case OHCI_USB_RESET: return "reset"; -+ case OHCI_USB_RESUME: return "resume"; -+ case OHCI_USB_OPER: return "operational"; -+ case OHCI_USB_SUSPEND: return "suspend"; -+ } -+ return "?"; -+} -+ -+// dump control and status registers -+static void ohci_dump_status (ohci_t *controller) -+{ -+ struct ohci_regs *regs = controller->regs; -+ __u32 temp; -+ -+ temp = readl (®s->revision) & 0xff; -+ if (temp != 0x10) -+ dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f)); -+ -+ temp = readl (®s->control); -+ dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, -+ (temp & OHCI_CTRL_RWE) ? " RWE" : "", -+ (temp & OHCI_CTRL_RWC) ? " RWC" : "", -+ (temp & OHCI_CTRL_IR) ? " IR" : "", -+ hcfs2string (temp & OHCI_CTRL_HCFS), -+ (temp & OHCI_CTRL_BLE) ? " BLE" : "", -+ (temp & OHCI_CTRL_CLE) ? " CLE" : "", -+ (temp & OHCI_CTRL_IE) ? " IE" : "", -+ (temp & OHCI_CTRL_PLE) ? " PLE" : "", -+ temp & OHCI_CTRL_CBSR -+ ); -+ -+ temp = readl (®s->cmdstatus); -+ dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, -+ (temp & OHCI_SOC) >> 16, -+ (temp & OHCI_OCR) ? " OCR" : "", -+ (temp & OHCI_BLF) ? " BLF" : "", -+ (temp & OHCI_CLF) ? " CLF" : "", -+ (temp & OHCI_HCR) ? " HCR" : "" -+ ); -+ -+ ohci_dump_intr_mask ("intrstatus", readl (®s->intrstatus)); -+ ohci_dump_intr_mask ("intrenable", readl (®s->intrenable)); -+ // intrdisable always same as intrenable -+ // ohci_dump_intr_mask ("intrdisable", readl (®s->intrdisable)); -+ -+ maybe_print_eds ("ed_periodcurrent", readl (®s->ed_periodcurrent)); -+ -+ maybe_print_eds ("ed_controlhead", readl (®s->ed_controlhead)); -+ maybe_print_eds ("ed_controlcurrent", readl (®s->ed_controlcurrent)); -+ -+ maybe_print_eds ("ed_bulkhead", readl (®s->ed_bulkhead)); -+ maybe_print_eds ("ed_bulkcurrent", readl (®s->ed_bulkcurrent)); -+ -+ maybe_print_eds ("donehead", readl (®s->donehead)); -+} -+ -+static void ohci_dump_roothub (ohci_t *controller, int verbose) -+{ -+ __u32 temp, ndp, i; -+ -+ temp = roothub_a (controller); -+ if (temp == ~(u32)0) -+ return; -+ ndp = (temp & RH_A_NDP); -+ -+ if (verbose) { -+ dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, -+ ((temp & RH_A_POTPGT) >> 24) & 0xff, -+ (temp & RH_A_NOCP) ? " NOCP" : "", -+ (temp & RH_A_OCPM) ? " OCPM" : "", -+ (temp & RH_A_DT) ? " DT" : "", -+ (temp & RH_A_NPS) ? " NPS" : "", -+ (temp & RH_A_PSM) ? " PSM" : "", -+ ndp -+ ); -+ temp = roothub_b (controller); -+ dbg ("roothub.b: %08x PPCM=%04x DR=%04x", -+ temp, -+ (temp & RH_B_PPCM) >> 16, -+ (temp & RH_B_DR) -+ ); -+ temp = roothub_status (controller); -+ dbg ("roothub.status: %08x%s%s%s%s%s%s", -+ temp, -+ (temp & RH_HS_CRWE) ? " CRWE" : "", -+ (temp & RH_HS_OCIC) ? " OCIC" : "", -+ (temp & RH_HS_LPSC) ? " LPSC" : "", -+ (temp & RH_HS_DRWE) ? " DRWE" : "", -+ (temp & RH_HS_OCI) ? " OCI" : "", -+ (temp & RH_HS_LPS) ? " LPS" : "" -+ ); -+ } -+ -+ for (i = 0; i < ndp; i++) { -+ temp = roothub_portstatus (controller, i); -+ dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", -+ i, -+ temp, -+ (temp & RH_PS_PRSC) ? " PRSC" : "", -+ (temp & RH_PS_OCIC) ? " OCIC" : "", -+ (temp & RH_PS_PSSC) ? " PSSC" : "", -+ (temp & RH_PS_PESC) ? " PESC" : "", -+ (temp & RH_PS_CSC) ? " CSC" : "", -+ -+ (temp & RH_PS_LSDA) ? " LSDA" : "", -+ (temp & RH_PS_PPS) ? " PPS" : "", -+ (temp & RH_PS_PRS) ? " PRS" : "", -+ (temp & RH_PS_POCI) ? " POCI" : "", -+ (temp & RH_PS_PSS) ? " PSS" : "", -+ -+ (temp & RH_PS_PES) ? " PES" : "", -+ (temp & RH_PS_CCS) ? " CCS" : "" -+ ); -+ } -+} -+ -+static void ohci_dump (ohci_t *controller, int verbose) -+{ -+ dbg ("OHCI controller usb-%s state", controller->ohci_dev->slot_name); -+ -+ // dumps some of the state we know about -+ ohci_dump_status (controller); -+ if (verbose) -+ ep_print_int_eds (controller, "hcca"); -+ dbg ("hcca frame #%04x", controller->hcca->frame_no); -+ ohci_dump_roothub (controller, 1); -+} -+ -+ -+#endif -+ -+/*-------------------------------------------------------------------------* -+ * Interface functions (URB) -+ *-------------------------------------------------------------------------*/ -+ -+/* return a request to the completion handler */ -+ -+static int sohci_return_urb (struct ohci *hc, struct urb * urb) -+{ -+ urb_priv_t * urb_priv = urb->hcpriv; -+ struct urb * urbt; -+ int i; -+ -+ if (!urb_priv) -+ return -1; /* urb already unlinked */ -+ -+ /* just to be sure */ -+ if (!urb->complete) { -+ urb_rm_priv_locked (urb); -+ ohci_complete_add(hc, urb); /* Just usb_dec_dev_use */ -+ return -1; -+ } -+ -+#ifdef DEBUG -+ urb_print (urb, "RET", usb_pipeout (urb->pipe)); -+#endif -+ -+ switch (usb_pipetype (urb->pipe)) { -+ case PIPE_INTERRUPT: -+ pci_unmap_single (hc->ohci_dev, -+ urb_priv->td [0]->data_dma, -+ urb->transfer_buffer_length, -+ usb_pipeout (urb->pipe) -+ ? PCI_DMA_TODEVICE -+ : PCI_DMA_FROMDEVICE); -+ if (urb->interval) { -+ urb->complete (urb); -+ -+ /* implicitly requeued */ -+ urb->actual_length = 0; -+ urb->status = -EINPROGRESS; -+ td_submit_urb (urb); -+ } else { -+ urb_rm_priv_locked (urb); -+ ohci_complete_add(hc, urb); -+ } -+ break; -+ -+ case PIPE_ISOCHRONOUS: -+ for (urbt = urb->next; urbt && (urbt != urb); urbt = urbt->next); -+ if (urbt) { /* send the reply and requeue URB */ -+ pci_unmap_single (hc->ohci_dev, -+ urb_priv->td [0]->data_dma, -+ urb->transfer_buffer_length, -+ usb_pipeout (urb->pipe) -+ ? PCI_DMA_TODEVICE -+ : PCI_DMA_FROMDEVICE); -+ urb->complete (urb); -+ urb->actual_length = 0; -+ urb->status = USB_ST_URB_PENDING; -+ urb->start_frame = urb_priv->ed->last_iso + 1; -+ if (urb_priv->state != URB_DEL) { -+ for (i = 0; i < urb->number_of_packets; i++) { -+ urb->iso_frame_desc[i].actual_length = 0; -+ urb->iso_frame_desc[i].status = -EXDEV; -+ } -+ td_submit_urb (urb); -+ } -+ -+ } else { /* unlink URB, call complete */ -+ urb_rm_priv_locked (urb); -+ ohci_complete_add(hc, urb); -+ } -+ break; -+ -+ case PIPE_BULK: -+ case PIPE_CONTROL: /* unlink URB, call complete */ -+ urb_rm_priv_locked (urb); -+ ohci_complete_add(hc, urb); -+ break; -+ } -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* get a transfer request */ -+ -+static int sohci_submit_urb (struct urb * urb) -+{ -+ ohci_t * ohci; -+ ed_t * ed; -+ urb_priv_t * urb_priv; -+ unsigned int pipe = urb->pipe; -+ int maxps = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)); -+ int i, size = 0; -+ unsigned long flags; -+ int bustime = 0; -+ int mem_flags = GFP_ATOMIC; -+ -+ if (!urb->dev || !urb->dev->bus) -+ return -ENODEV; -+ -+ if (urb->hcpriv) /* urb already in use */ -+ return -EINVAL; -+ -+// if(usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) -+// return -EPIPE; -+ -+ usb_inc_dev_use (urb->dev); -+ ohci = (ohci_t *) urb->dev->bus->hcpriv; -+ -+#ifdef DEBUG -+ urb_print (urb, "SUB", usb_pipein (pipe)); -+#endif -+ -+ /* handle a request to the virtual root hub */ -+ if (usb_pipedevice (pipe) == ohci->rh.devnum) -+ return rh_submit_urb (urb); -+ -+ spin_lock_irqsave(&ohci->ohci_lock, flags); -+ -+ /* when controller's hung, permit only roothub cleanup attempts -+ * such as powering down ports */ -+ if (ohci->disabled) { -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ usb_dec_dev_use (urb->dev); -+ return -ESHUTDOWN; -+ } -+ -+ /* every endpoint has a ed, locate and fill it */ -+ if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) { -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ usb_dec_dev_use (urb->dev); -+ return -ENOMEM; -+ } -+ -+ /* for the private part of the URB we need the number of TDs (size) */ -+ switch (usb_pipetype (pipe)) { -+ case PIPE_BULK: /* one TD for every 4096 Byte */ -+ size = (urb->transfer_buffer_length - 1) / 4096 + 1; -+ -+ /* If the transfer size is multiple of the pipe mtu, -+ * we may need an extra TD to create a empty frame -+ * Jean II */ -+ if ((urb->transfer_flags & USB_ZERO_PACKET) && -+ usb_pipeout (pipe) && -+ (urb->transfer_buffer_length != 0) && -+ ((urb->transfer_buffer_length % maxps) == 0)) -+ size++; -+ break; -+ case PIPE_ISOCHRONOUS: /* number of packets from URB */ -+ size = urb->number_of_packets; -+ if (size <= 0) { -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ usb_dec_dev_use (urb->dev); -+ return -EINVAL; -+ } -+ for (i = 0; i < urb->number_of_packets; i++) { -+ urb->iso_frame_desc[i].actual_length = 0; -+ urb->iso_frame_desc[i].status = -EXDEV; -+ } -+ break; -+ case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ -+ size = (urb->transfer_buffer_length == 0)? 2: -+ (urb->transfer_buffer_length - 1) / 4096 + 3; -+ break; -+ case PIPE_INTERRUPT: /* one TD */ -+ size = 1; -+ break; -+ } -+ -+ /* allocate the private part of the URB */ -+ urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *), -+ GFP_ATOMIC); -+ if (!urb_priv) { -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ usb_dec_dev_use (urb->dev); -+ return -ENOMEM; -+ } -+ memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (td_t *)); -+ -+ /* fill the private part of the URB */ -+ urb_priv->length = size; -+ urb_priv->ed = ed; -+ -+ /* allocate the TDs (updating hash chains) */ -+ for (i = 0; i < size; i++) { -+ urb_priv->td[i] = td_alloc (ohci, SLAB_ATOMIC); -+ if (!urb_priv->td[i]) { -+ urb_priv->length = i; -+ urb_free_priv (ohci, urb_priv); -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ usb_dec_dev_use (urb->dev); -+ return -ENOMEM; -+ } -+ } -+ -+ if (ed->state == ED_NEW || (ed->state & ED_DEL)) { -+ urb_free_priv (ohci, urb_priv); -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ usb_dec_dev_use (urb->dev); -+ return -EINVAL; -+ } -+ -+ /* allocate and claim bandwidth if needed; ISO -+ * needs start frame index if it was't provided. -+ */ -+ switch (usb_pipetype (pipe)) { -+ case PIPE_ISOCHRONOUS: -+ if (urb->transfer_flags & USB_ISO_ASAP) { -+ urb->start_frame = ((ed->state == ED_OPER) -+ ? (ed->last_iso + 1) -+ : (le16_to_cpu (ohci->hcca->frame_no) + 10)) & 0xffff; -+ } -+ /* FALLTHROUGH */ -+ case PIPE_INTERRUPT: -+ if (urb->bandwidth == 0) { -+ bustime = usb_check_bandwidth (urb->dev, urb); -+ } -+ if (bustime < 0) { -+ urb_free_priv (ohci, urb_priv); -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ usb_dec_dev_use (urb->dev); -+ return bustime; -+ } -+ usb_claim_bandwidth (urb->dev, urb, bustime, usb_pipeisoc (urb->pipe)); -+#ifdef DO_TIMEOUTS -+ urb->timeout = 0; -+#endif -+ } -+ -+ urb->actual_length = 0; -+ urb->hcpriv = urb_priv; -+ urb->status = USB_ST_URB_PENDING; -+ -+ /* link the ed into a chain if is not already */ -+ if (ed->state != ED_OPER) -+ ep_link (ohci, ed); -+ -+ /* fill the TDs and link it to the ed */ -+ td_submit_urb (urb); -+ -+#ifdef DO_TIMEOUTS -+ /* maybe add to ordered list of timeouts */ -+ if (urb->timeout) { -+ struct list_head *entry; -+ -+ urb->timeout += jiffies; -+ -+ list_for_each (entry, &ohci->timeout_list) { -+ struct urb *next_urb; -+ -+ next_urb = list_entry (entry, struct urb, urb_list); -+ if (time_after_eq (urb->timeout, next_urb->timeout)) -+ break; -+ } -+ list_add (&urb->urb_list, entry); -+ -+ /* drive timeouts by SF (messy, but works) */ -+ writel (OHCI_INTR_SF, &ohci->regs->intrenable); -+ (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ -+ } -+#endif -+ -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* deactivate all TDs and remove the private part of the URB */ -+/* interrupt callers must use async unlink mode */ -+ -+static int sohci_unlink_urb (struct urb * urb) -+{ -+ unsigned long flags; -+ ohci_t * ohci; -+ -+ if (!urb) /* just to be sure */ -+ return -EINVAL; -+ -+ if (!urb->dev || !urb->dev->bus) -+ return -ENODEV; -+ -+ ohci = (ohci_t *) urb->dev->bus->hcpriv; -+ -+#ifdef DEBUG -+ urb_print (urb, "UNLINK", 1); -+#endif -+ -+ /* handle a request to the virtual root hub */ -+ if (usb_pipedevice (urb->pipe) == ohci->rh.devnum) -+ return rh_unlink_urb (urb); -+ -+ spin_lock_irqsave(&ohci->ohci_lock, flags); -+ if (urb->hcpriv && (urb->status == USB_ST_URB_PENDING)) { -+ if (!ohci->disabled) { -+ urb_priv_t * urb_priv; -+ -+ /* interrupt code may not sleep; it must use -+ * async status return to unlink pending urbs. -+ */ -+ if (!(urb->transfer_flags & USB_ASYNC_UNLINK) -+ && in_interrupt ()) { -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ err ("bug in call from %p; use async!", -+ __builtin_return_address(0)); -+ return -EWOULDBLOCK; -+ } -+ -+ /* flag the urb and its TDs for deletion in some -+ * upcoming SF interrupt delete list processing -+ */ -+ urb_priv = urb->hcpriv; -+ -+ if (!urb_priv || (urb_priv->state == URB_DEL)) { -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ return 0; -+ } -+ -+ urb_priv->state = URB_DEL; -+ ep_rm_ed (urb->dev, urb_priv->ed); -+ urb_priv->ed->state |= ED_URB_DEL; -+ -+ if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) { -+ DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); -+ DECLARE_WAITQUEUE (wait, current); -+ int timeout = OHCI_UNLINK_TIMEOUT; -+ -+ add_wait_queue (&unlink_wakeup, &wait); -+ urb_priv->wait = &unlink_wakeup; -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ -+ /* wait until all TDs are deleted */ -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ while (timeout && (urb->status == USB_ST_URB_PENDING)) { -+ timeout = schedule_timeout (timeout); -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ } -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue (&unlink_wakeup, &wait); -+ if (urb->status == USB_ST_URB_PENDING) { -+ err ("unlink URB timeout"); -+ return -ETIMEDOUT; -+ } -+ -+ usb_dec_dev_use (urb->dev); -+ urb->dev = NULL; -+ if (urb->complete) -+ urb->complete (urb); -+ } else { -+ /* usb_dec_dev_use done in dl_del_list() */ -+ urb->status = -EINPROGRESS; -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ return -EINPROGRESS; -+ } -+ } else { -+ urb_rm_priv_locked (urb); -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ usb_dec_dev_use (urb->dev); -+ urb->dev = NULL; -+ if (urb->transfer_flags & USB_ASYNC_UNLINK) { -+ urb->status = -ECONNRESET; -+ if (urb->complete) -+ urb->complete (urb); -+ } else -+ urb->status = -ENOENT; -+ } -+ } else { -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ } -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* allocate private data space for a usb device */ -+ -+static int sohci_alloc_dev (struct usb_device *usb_dev) -+{ -+ struct ohci_device * dev; -+ -+ dev = dev_alloc ((struct ohci *) usb_dev->bus->hcpriv, ALLOC_FLAGS); -+ if (!dev) -+ return -ENOMEM; -+ -+ usb_dev->hcpriv = dev; -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* may be called from interrupt context */ -+/* frees private data space of usb device */ -+ -+static int sohci_free_dev (struct usb_device * usb_dev) -+{ -+ unsigned long flags; -+ int i, cnt = 0; -+ ed_t * ed; -+ struct ohci_device * dev = usb_to_ohci (usb_dev); -+ ohci_t * ohci = usb_dev->bus->hcpriv; -+ -+ if (!dev) -+ return 0; -+ -+ if (usb_dev->devnum >= 0) { -+ -+ /* driver disconnects should have unlinked all urbs -+ * (freeing all the TDs, unlinking EDs) but we need -+ * to defend against bugs that prevent that. -+ */ -+ spin_lock_irqsave(&ohci->ohci_lock, flags); -+ for(i = 0; i < NUM_EDS; i++) { -+ ed = &(dev->ed[i]); -+ if (ed->state != ED_NEW) { -+ if (ed->state == ED_OPER) { -+ /* driver on that interface didn't unlink an urb */ -+ dbg ("driver usb-%s dev %d ed 0x%x unfreed URB", -+ ohci->ohci_dev->slot_name, usb_dev->devnum, i); -+ ep_unlink (ohci, ed); -+ } -+ ep_rm_ed (usb_dev, ed); -+ ed->state = ED_DEL; -+ cnt++; -+ } -+ } -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ -+ /* if the controller is running, tds for those unlinked -+ * urbs get freed by dl_del_list at the next SF interrupt -+ */ -+ if (cnt > 0) { -+ -+ if (ohci->disabled) { -+ /* FIXME: Something like this should kick in, -+ * though it's currently an exotic case ... -+ * the controller won't ever be touching -+ * these lists again!! -+ dl_del_list (ohci, -+ le16_to_cpu (ohci->hcca->frame_no) & 1); -+ */ -+ warn ("TD leak, %d", cnt); -+ -+ } else if (!in_interrupt ()) { -+ DECLARE_WAIT_QUEUE_HEAD (freedev_wakeup); -+ DECLARE_WAITQUEUE (wait, current); -+ int timeout = OHCI_UNLINK_TIMEOUT; -+ -+ /* SF interrupt handler calls dl_del_list */ -+ add_wait_queue (&freedev_wakeup, &wait); -+ dev->wait = &freedev_wakeup; -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ while (timeout && dev->ed_cnt) -+ timeout = schedule_timeout (timeout); -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue (&freedev_wakeup, &wait); -+ if (dev->ed_cnt) { -+ err ("free device %d timeout", usb_dev->devnum); -+ return -ETIMEDOUT; -+ } -+ } else { -+ /* likely some interface's driver has a refcount bug */ -+ err ("bus %s devnum %d deletion in interrupt", -+ ohci->ohci_dev->slot_name, usb_dev->devnum); -+ BUG (); -+ } -+ } -+ } -+ -+ /* free device, and associated EDs */ -+ dev_free (ohci, dev); -+ -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* tell us the current USB frame number */ -+ -+static int sohci_get_current_frame_number (struct usb_device *usb_dev) -+{ -+ ohci_t * ohci = usb_dev->bus->hcpriv; -+ -+ return le16_to_cpu (ohci->hcca->frame_no); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+struct usb_operations sohci_device_operations = { -+ sohci_alloc_dev, -+ sohci_free_dev, -+ sohci_get_current_frame_number, -+ sohci_submit_urb, -+ sohci_unlink_urb -+}; -+ -+/*-------------------------------------------------------------------------* -+ * ED handling functions -+ *-------------------------------------------------------------------------*/ -+ -+/* search for the right branch to insert an interrupt ed into the int tree -+ * do some load ballancing; -+ * returns the branch and -+ * sets the interval to interval = 2^integer (ld (interval)) */ -+ -+static int ep_int_ballance (ohci_t * ohci, int interval, int load) -+{ -+ int i, branch = 0; -+ -+ /* search for the least loaded interrupt endpoint branch of all 32 branches */ -+ for (i = 0; i < 32; i++) -+ if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i]) branch = i; -+ -+ branch = branch % interval; -+ for (i = branch; i < 32; i += interval) ohci->ohci_int_load [i] += load; -+ -+ return branch; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* 2^int( ld (inter)) */ -+ -+static int ep_2_n_interval (int inter) -+{ -+ int i; -+ for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++); -+ return 1 << i; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* the int tree is a binary tree -+ * in order to process it sequentially the indexes of the branches have to be mapped -+ * the mapping reverses the bits of a word of num_bits length */ -+ -+static int ep_rev (int num_bits, int word) -+{ -+ int i, wout = 0; -+ -+ for (i = 0; i < num_bits; i++) wout |= (((word >> i) & 1) << (num_bits - i - 1)); -+ return wout; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* link an ed into one of the HC chains */ -+ -+static int ep_link (ohci_t * ohci, ed_t * edi) -+{ -+ int int_branch; -+ int i; -+ int inter; -+ int interval; -+ int load; -+ __u32 * ed_p; -+ volatile ed_t * ed = edi; -+ -+ ed->state = ED_OPER; -+ -+ switch (ed->type) { -+ case PIPE_CONTROL: -+ ed->hwNextED = 0; -+ if (ohci->ed_controltail == NULL) { -+ writel (ed->dma, &ohci->regs->ed_controlhead); -+ } else { -+ ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma); -+ } -+ ed->ed_prev = ohci->ed_controltail; -+ if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && -+ !ohci->ed_rm_list[1] && !ohci->sleeping) { -+ ohci->hc_control |= OHCI_CTRL_CLE; -+ writel (ohci->hc_control, &ohci->regs->control); -+ } -+ ohci->ed_controltail = edi; -+ break; -+ -+ case PIPE_BULK: -+ ed->hwNextED = 0; -+ if (ohci->ed_bulktail == NULL) { -+ writel (ed->dma, &ohci->regs->ed_bulkhead); -+ } else { -+ ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma); -+ } -+ ed->ed_prev = ohci->ed_bulktail; -+ if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && -+ !ohci->ed_rm_list[1] && !ohci->sleeping) { -+ ohci->hc_control |= OHCI_CTRL_BLE; -+ writel (ohci->hc_control, &ohci->regs->control); -+ } -+ ohci->ed_bulktail = edi; -+ break; -+ -+ case PIPE_INTERRUPT: -+ load = ed->int_load; -+ interval = ep_2_n_interval (ed->int_period); -+ ed->int_interval = interval; -+ int_branch = ep_int_ballance (ohci, interval, load); -+ ed->int_branch = int_branch; -+ -+ for (i = 0; i < ep_rev (6, interval); i += inter) { -+ inter = 1; -+ for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i) + int_branch]); -+ (*ed_p != 0) && ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval >= interval); -+ ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) -+ inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval); -+ ed->hwNextED = *ed_p; -+ *ed_p = cpu_to_le32 (ed->dma); -+ } -+#ifdef DEBUG -+ ep_print_int_eds (ohci, "LINK_INT"); -+#endif -+ break; -+ -+ case PIPE_ISOCHRONOUS: -+ ed->hwNextED = 0; -+ ed->int_interval = 1; -+ if (ohci->ed_isotail != NULL) { -+ ohci->ed_isotail->hwNextED = cpu_to_le32 (ed->dma); -+ ed->ed_prev = ohci->ed_isotail; -+ } else { -+ for ( i = 0; i < 32; i += inter) { -+ inter = 1; -+ for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i)]); -+ *ed_p != 0; -+ ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) -+ inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval); -+ *ed_p = cpu_to_le32 (ed->dma); -+ } -+ ed->ed_prev = NULL; -+ } -+ ohci->ed_isotail = edi; -+#ifdef DEBUG -+ ep_print_int_eds (ohci, "LINK_ISO"); -+#endif -+ break; -+ } -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* scan the periodic table to find and unlink this ED */ -+static void periodic_unlink ( -+ struct ohci *ohci, -+ struct ed *ed, -+ unsigned index, -+ unsigned period -+) { -+ for (; index < NUM_INTS; index += period) { -+ __u32 *ed_p = &ohci->hcca->int_table [index]; -+ -+ /* ED might have been unlinked through another path */ -+ while (*ed_p != 0) { -+ if ((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) { -+ *ed_p = ed->hwNextED; -+ break; -+ } -+ ed_p = & ((dma_to_ed (ohci, -+ le32_to_cpup (ed_p)))->hwNextED); -+ } -+ } -+} -+ -+/* unlink an ed from one of the HC chains. -+ * just the link to the ed is unlinked. -+ * the link from the ed still points to another operational ed or 0 -+ * so the HC can eventually finish the processing of the unlinked ed */ -+ -+static int ep_unlink (ohci_t * ohci, ed_t * ed) -+{ -+ int i; -+ -+ ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP); -+ -+ switch (ed->type) { -+ case PIPE_CONTROL: -+ if (ed->ed_prev == NULL) { -+ if (!ed->hwNextED) { -+ ohci->hc_control &= ~OHCI_CTRL_CLE; -+ writel (ohci->hc_control, &ohci->regs->control); -+ } -+ writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_controlhead); -+ } else { -+ ed->ed_prev->hwNextED = ed->hwNextED; -+ } -+ if (ohci->ed_controltail == ed) { -+ ohci->ed_controltail = ed->ed_prev; -+ } else { -+ (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev; -+ } -+ break; -+ -+ case PIPE_BULK: -+ if (ed->ed_prev == NULL) { -+ if (!ed->hwNextED) { -+ ohci->hc_control &= ~OHCI_CTRL_BLE; -+ writel (ohci->hc_control, &ohci->regs->control); -+ } -+ writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_bulkhead); -+ } else { -+ ed->ed_prev->hwNextED = ed->hwNextED; -+ } -+ if (ohci->ed_bulktail == ed) { -+ ohci->ed_bulktail = ed->ed_prev; -+ } else { -+ (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev; -+ } -+ break; -+ -+ case PIPE_INTERRUPT: -+ periodic_unlink (ohci, ed, 0, 1); -+ for (i = ed->int_branch; i < 32; i += ed->int_interval) -+ ohci->ohci_int_load[i] -= ed->int_load; -+#ifdef DEBUG -+ ep_print_int_eds (ohci, "UNLINK_INT"); -+#endif -+ break; -+ -+ case PIPE_ISOCHRONOUS: -+ if (ohci->ed_isotail == ed) -+ ohci->ed_isotail = ed->ed_prev; -+ if (ed->hwNextED != 0) -+ (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED))) -+ ->ed_prev = ed->ed_prev; -+ -+ if (ed->ed_prev != NULL) -+ ed->ed_prev->hwNextED = ed->hwNextED; -+ else -+ periodic_unlink (ohci, ed, 0, 1); -+#ifdef DEBUG -+ ep_print_int_eds (ohci, "UNLINK_ISO"); -+#endif -+ break; -+ } -+ ed->state = ED_UNLINK; -+ return 0; -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* add/reinit an endpoint; this should be done once at the usb_set_configuration command, -+ * but the USB stack is a little bit stateless so we do it at every transaction -+ * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK -+ * in all other cases the state is left unchanged -+ * the ed info fields are setted anyway even though most of them should not change */ -+ -+static ed_t * ep_add_ed ( -+ struct usb_device * usb_dev, -+ unsigned int pipe, -+ int interval, -+ int load, -+ int mem_flags -+) -+{ -+ ohci_t * ohci = usb_dev->bus->hcpriv; -+ td_t * td; -+ ed_t * ed_ret; -+ volatile ed_t * ed; -+ -+ ed = ed_ret = &(usb_to_ohci (usb_dev)->ed[(usb_pipeendpoint (pipe) << 1) | -+ (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]); -+ -+ if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { -+ /* pending delete request */ -+ return NULL; -+ } -+ -+ if (ed->state == ED_NEW) { -+ ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */ -+ /* dummy td; end of td list for ed */ -+ td = td_alloc (ohci, SLAB_ATOMIC); -+ /* hash the ed for later reverse mapping */ -+ if (!td || !hash_add_ed (ohci, (ed_t *)ed)) { -+ /* out of memory */ -+ if (td) -+ td_free(ohci, td); -+ return NULL; -+ } -+ ed->hwTailP = cpu_to_le32 (td->td_dma); -+ ed->hwHeadP = ed->hwTailP; -+ ed->state = ED_UNLINK; -+ ed->type = usb_pipetype (pipe); -+ usb_to_ohci (usb_dev)->ed_cnt++; -+ } -+ -+ ohci->dev[usb_pipedevice (pipe)] = usb_dev; -+ -+ ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe) -+ | usb_pipeendpoint (pipe) << 7 -+ | (usb_pipeisoc (pipe)? 0x8000: 0) -+ | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) -+ | usb_pipeslow (pipe) << 13 -+ | usb_maxpacket (usb_dev, pipe, usb_pipeout (pipe)) << 16); -+ -+ if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) { -+ ed->int_period = interval; -+ ed->int_load = load; -+ } -+ -+ return ed_ret; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* request the removal of an endpoint -+ * put the ep on the rm_list and request a stop of the bulk or ctrl list -+ * real removal is done at the next start frame (SF) hardware interrupt */ -+ -+static void ep_rm_ed (struct usb_device * usb_dev, ed_t * ed) -+{ -+ unsigned int frame; -+ ohci_t * ohci = usb_dev->bus->hcpriv; -+ -+ if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) -+ return; -+ -+ ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP); -+ -+ if (!ohci->disabled) { -+ switch (ed->type) { -+ case PIPE_CONTROL: /* stop control list */ -+ ohci->hc_control &= ~OHCI_CTRL_CLE; -+ writel (ohci->hc_control, &ohci->regs->control); -+ break; -+ case PIPE_BULK: /* stop bulk list */ -+ ohci->hc_control &= ~OHCI_CTRL_BLE; -+ writel (ohci->hc_control, &ohci->regs->control); -+ break; -+ } -+ } -+ -+ frame = le16_to_cpu (ohci->hcca->frame_no) & 0x1; -+ ed->ed_rm_list = ohci->ed_rm_list[frame]; -+ ohci->ed_rm_list[frame] = ed; -+ -+ if (!ohci->disabled && !ohci->sleeping) { -+ /* enable SOF interrupt */ -+ writel (OHCI_INTR_SF, &ohci->regs->intrstatus); -+ writel (OHCI_INTR_SF, &ohci->regs->intrenable); -+ (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ -+ } -+} -+ -+/*-------------------------------------------------------------------------* -+ * TD handling functions -+ *-------------------------------------------------------------------------*/ -+ -+/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ -+ -+static void -+td_fill (ohci_t * ohci, unsigned int info, -+ dma_addr_t data, int len, -+ struct urb * urb, int index) -+{ -+ volatile td_t * td, * td_pt; -+ urb_priv_t * urb_priv = urb->hcpriv; -+ -+ if (index >= urb_priv->length) { -+ err("internal OHCI error: TD index > length"); -+ return; -+ } -+ -+ /* use this td as the next dummy */ -+ td_pt = urb_priv->td [index]; -+ td_pt->hwNextTD = 0; -+ -+ /* fill the old dummy TD */ -+ td = urb_priv->td [index] = dma_to_td (ohci, -+ le32_to_cpup (&urb_priv->ed->hwTailP) & ~0xf); -+ -+ td->ed = urb_priv->ed; -+ td->next_dl_td = NULL; -+ td->index = index; -+ td->urb = urb; -+ td->data_dma = data; -+ if (!len) -+ data = 0; -+ -+ td->hwINFO = cpu_to_le32 (info); -+ if ((td->ed->type) == PIPE_ISOCHRONOUS) { -+ td->hwCBP = cpu_to_le32 (data & 0xFFFFF000); -+ td->ed->last_iso = info & 0xffff; -+ } else { -+ td->hwCBP = cpu_to_le32 (data); -+ } -+ if (data) -+ td->hwBE = cpu_to_le32 (data + len - 1); -+ else -+ td->hwBE = 0; -+ td->hwNextTD = cpu_to_le32 (td_pt->td_dma); -+ td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000); -+ -+ /* append to queue */ -+ wmb(); -+ td->ed->hwTailP = td->hwNextTD; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* prepare all TDs of a transfer */ -+ -+static void td_submit_urb (struct urb * urb) -+{ -+ urb_priv_t * urb_priv = urb->hcpriv; -+ ohci_t * ohci = (ohci_t *) urb->dev->bus->hcpriv; -+ dma_addr_t data; -+ int data_len = urb->transfer_buffer_length; -+ int maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe)); -+ int cnt = 0; -+ __u32 info = 0; -+ unsigned int toggle = 0; -+ -+ /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */ -+ if(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) { -+ toggle = TD_T_TOGGLE; -+ } else { -+ toggle = TD_T_DATA0; -+ usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 1); -+ } -+ -+ urb_priv->td_cnt = 0; -+ -+ if (data_len) { -+ data = pci_map_single (ohci->ohci_dev, -+ urb->transfer_buffer, data_len, -+ usb_pipeout (urb->pipe) -+ ? PCI_DMA_TODEVICE -+ : PCI_DMA_FROMDEVICE -+ ); -+ } else -+ data = 0; -+ -+ switch (usb_pipetype (urb->pipe)) { -+ case PIPE_BULK: -+ info = usb_pipeout (urb->pipe)? -+ TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; -+ while(data_len > 4096) { -+ td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, urb, cnt); -+ data += 4096; data_len -= 4096; cnt++; -+ } -+ info = usb_pipeout (urb->pipe)? -+ TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; -+ td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, cnt); -+ cnt++; -+ -+ /* If the transfer size is multiple of the pipe mtu, -+ * we may need an extra TD to create a empty frame -+ * Note : another way to check this condition is -+ * to test if(urb_priv->length > cnt) - Jean II */ -+ if ((urb->transfer_flags & USB_ZERO_PACKET) && -+ usb_pipeout (urb->pipe) && -+ (urb->transfer_buffer_length != 0) && -+ ((urb->transfer_buffer_length % maxps) == 0)) { -+ td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), 0, 0, urb, cnt); -+ cnt++; -+ } -+ -+ if (!ohci->sleeping) { -+ wmb(); -+ writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ -+ (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ -+ } -+ break; -+ -+ case PIPE_INTERRUPT: -+ info = usb_pipeout (urb->pipe)? -+ TD_CC | TD_DP_OUT | toggle: TD_CC | TD_R | TD_DP_IN | toggle; -+ td_fill (ohci, info, data, data_len, urb, cnt++); -+ break; -+ -+ case PIPE_CONTROL: -+ info = TD_CC | TD_DP_SETUP | TD_T_DATA0; -+ td_fill (ohci, info, -+ pci_map_single (ohci->ohci_dev, -+ urb->setup_packet, 8, -+ PCI_DMA_TODEVICE), -+ 8, urb, cnt++); -+ if (data_len > 0) { -+ info = usb_pipeout (urb->pipe)? -+ TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; -+ /* NOTE: mishandles transfers >8K, some >4K */ -+ td_fill (ohci, info, data, data_len, urb, cnt++); -+ } -+ info = usb_pipeout (urb->pipe)? -+ TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; -+ td_fill (ohci, info, data, 0, urb, cnt++); -+ if (!ohci->sleeping) { -+ wmb(); -+ writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ -+ (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ -+ } -+ break; -+ -+ case PIPE_ISOCHRONOUS: -+ for (cnt = 0; cnt < urb->number_of_packets; cnt++) { -+ td_fill (ohci, TD_CC|TD_ISO | ((urb->start_frame + cnt) & 0xffff), -+ data + urb->iso_frame_desc[cnt].offset, -+ urb->iso_frame_desc[cnt].length, urb, cnt); -+ } -+ break; -+ } -+ if (urb_priv->length != cnt) -+ dbg("TD LENGTH %d != CNT %d", urb_priv->length, cnt); -+} -+ -+/*-------------------------------------------------------------------------* -+ * Done List handling functions -+ *-------------------------------------------------------------------------*/ -+ -+ -+/* calculate the transfer length and update the urb */ -+ -+static void dl_transfer_length(td_t * td) -+{ -+ __u32 tdINFO, tdBE, tdCBP; -+ __u16 tdPSW; -+ struct urb * urb = td->urb; -+ urb_priv_t * urb_priv = urb->hcpriv; -+ int dlen = 0; -+ int cc = 0; -+ -+ tdINFO = le32_to_cpup (&td->hwINFO); -+ tdBE = le32_to_cpup (&td->hwBE); -+ tdCBP = le32_to_cpup (&td->hwCBP); -+ -+ -+ if (tdINFO & TD_ISO) { -+ tdPSW = le16_to_cpu (td->hwPSW[0]); -+ cc = (tdPSW >> 12) & 0xF; -+ if (cc < 0xE) { -+ if (usb_pipeout(urb->pipe)) { -+ dlen = urb->iso_frame_desc[td->index].length; -+ } else { -+ dlen = tdPSW & 0x3ff; -+ } -+ urb->actual_length += dlen; -+ urb->iso_frame_desc[td->index].actual_length = dlen; -+ if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN)) -+ cc = TD_CC_NOERROR; -+ -+ urb->iso_frame_desc[td->index].status = cc_to_error[cc]; -+ } -+ } else { /* BULK, INT, CONTROL DATA */ -+ if (!(usb_pipetype (urb->pipe) == PIPE_CONTROL && -+ ((td->index == 0) || (td->index == urb_priv->length - 1)))) { -+ if (tdBE != 0) { -+ if (td->hwCBP == 0) -+ urb->actual_length += tdBE - td->data_dma + 1; -+ else -+ urb->actual_length += tdCBP - td->data_dma; -+ } -+ } -+ } -+} -+ -+/* handle an urb that is being unlinked */ -+ -+static void dl_del_urb (ohci_t *ohci, struct urb * urb) -+{ -+ wait_queue_head_t * wait_head = ((urb_priv_t *)(urb->hcpriv))->wait; -+ -+ urb_rm_priv_locked (urb); -+ -+ if (urb->transfer_flags & USB_ASYNC_UNLINK) { -+ urb->status = -ECONNRESET; -+ ohci_complete_add(ohci, urb); -+ } else { -+ urb->status = -ENOENT; -+ -+ /* unblock sohci_unlink_urb */ -+ if (wait_head) -+ wake_up (wait_head); -+ } -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* replies to the request have to be on a FIFO basis so -+ * we reverse the reversed done-list */ -+ -+static td_t * dl_reverse_done_list (ohci_t * ohci) -+{ -+ __u32 td_list_hc; -+ td_t * td_rev = NULL; -+ td_t * td_list = NULL; -+ urb_priv_t * urb_priv = NULL; -+ -+ td_list_hc = le32_to_cpup (&ohci->hcca->done_head) & 0xfffffff0; -+ ohci->hcca->done_head = 0; -+ -+ while (td_list_hc) { -+ td_list = dma_to_td (ohci, td_list_hc); -+ -+ if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) { -+ urb_priv = (urb_priv_t *) td_list->urb->hcpriv; -+ dbg(" USB-error/status: %x : %p", -+ TD_CC_GET (le32_to_cpup (&td_list->hwINFO)), td_list); -+ if (td_list->ed->hwHeadP & cpu_to_le32 (0x1)) { -+ if (urb_priv && ((td_list->index + 1) < urb_priv->length)) { -+ td_list->ed->hwHeadP = -+ (urb_priv->td[urb_priv->length - 1]->hwNextTD & cpu_to_le32 (0xfffffff0)) | -+ (td_list->ed->hwHeadP & cpu_to_le32 (0x2)); -+ urb_priv->td_cnt += urb_priv->length - td_list->index - 1; -+ } else -+ td_list->ed->hwHeadP &= cpu_to_le32 (0xfffffff2); -+ } -+ } -+ -+ td_list->next_dl_td = td_rev; -+ td_rev = td_list; -+ td_list_hc = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0; -+ } -+ return td_list; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* there are some pending requests to remove -+ * - some of the eds (if ed->state & ED_DEL (set by sohci_free_dev) -+ * - some URBs/TDs if urb_priv->state == URB_DEL */ -+ -+static void dl_del_list (ohci_t * ohci, unsigned int frame) -+{ -+ ed_t * ed; -+ __u32 edINFO; -+ __u32 tdINFO; -+ td_t * td = NULL, * td_next = NULL, * tdHeadP = NULL, * tdTailP; -+ __u32 * td_p; -+ int ctrl = 0, bulk = 0; -+ -+ for (ed = ohci->ed_rm_list[frame]; ed != NULL; ed = ed->ed_rm_list) { -+ -+ tdTailP = dma_to_td (ohci, le32_to_cpup (&ed->hwTailP) & 0xfffffff0); -+ tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP) & 0xfffffff0); -+ edINFO = le32_to_cpup (&ed->hwINFO); -+ td_p = &ed->hwHeadP; -+ -+ for (td = tdHeadP; td != tdTailP; td = td_next) { -+ struct urb * urb = td->urb; -+ urb_priv_t * urb_priv = td->urb->hcpriv; -+ -+ td_next = dma_to_td (ohci, le32_to_cpup (&td->hwNextTD) & 0xfffffff0); -+ if ((urb_priv->state == URB_DEL) || (ed->state & ED_DEL)) { -+ tdINFO = le32_to_cpup (&td->hwINFO); -+ if (TD_CC_GET (tdINFO) < 0xE) -+ dl_transfer_length (td); -+ *td_p = td->hwNextTD | (*td_p & cpu_to_le32 (0x3)); -+ -+ /* URB is done; clean up */ -+ if (++(urb_priv->td_cnt) == urb_priv->length) -+ dl_del_urb (ohci, urb); -+ } else { -+ td_p = &td->hwNextTD; -+ } -+ } -+ -+ if (ed->state & ED_DEL) { /* set by sohci_free_dev */ -+ struct ohci_device * dev = usb_to_ohci (ohci->dev[edINFO & 0x7F]); -+ td_free (ohci, tdTailP); /* free dummy td */ -+ ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); -+ ed->state = ED_NEW; -+ hash_free_ed(ohci, ed); -+ /* if all eds are removed wake up sohci_free_dev */ -+ if (!--dev->ed_cnt) { -+ wait_queue_head_t *wait_head = dev->wait; -+ -+ dev->wait = 0; -+ if (wait_head) -+ wake_up (wait_head); -+ } -+ } else { -+ ed->state &= ~ED_URB_DEL; -+ tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP) & 0xfffffff0); -+ -+ if (tdHeadP == tdTailP) { -+ if (ed->state == ED_OPER) -+ ep_unlink(ohci, ed); -+ } else -+ ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP); -+ } -+ -+ switch (ed->type) { -+ case PIPE_CONTROL: -+ ctrl = 1; -+ break; -+ case PIPE_BULK: -+ bulk = 1; -+ break; -+ } -+ } -+ -+ /* maybe reenable control and bulk lists */ -+ if (!ohci->disabled) { -+ if (ctrl) /* reset control list */ -+ writel (0, &ohci->regs->ed_controlcurrent); -+ if (bulk) /* reset bulk list */ -+ writel (0, &ohci->regs->ed_bulkcurrent); -+ if (!ohci->ed_rm_list[!frame] && !ohci->sleeping) { -+ if (ohci->ed_controltail) -+ ohci->hc_control |= OHCI_CTRL_CLE; -+ if (ohci->ed_bulktail) -+ ohci->hc_control |= OHCI_CTRL_BLE; -+ writel (ohci->hc_control, &ohci->regs->control); -+ } -+ } -+ -+ ohci->ed_rm_list[frame] = NULL; -+} -+ -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* td done list */ -+ -+static void dl_done_list (ohci_t * ohci, td_t * td_list) -+{ -+ td_t * td_list_next = NULL; -+ ed_t * ed; -+ int cc = 0; -+ struct urb * urb; -+ urb_priv_t * urb_priv; -+ __u32 tdINFO, edHeadP, edTailP; -+ -+ while (td_list) { -+ td_list_next = td_list->next_dl_td; -+ -+ urb = td_list->urb; -+ urb_priv = urb->hcpriv; -+ tdINFO = le32_to_cpup (&td_list->hwINFO); -+ -+ ed = td_list->ed; -+ -+ dl_transfer_length(td_list); -+ -+ /* error code of transfer */ -+ cc = TD_CC_GET (tdINFO); -+ if (cc == TD_CC_STALL) -+ usb_endpoint_halt(urb->dev, -+ usb_pipeendpoint(urb->pipe), -+ usb_pipeout(urb->pipe)); -+ -+ if (!(urb->transfer_flags & USB_DISABLE_SPD) -+ && (cc == TD_DATAUNDERRUN)) -+ cc = TD_CC_NOERROR; -+ -+ if (++(urb_priv->td_cnt) == urb_priv->length) { -+ if ((ed->state & (ED_OPER | ED_UNLINK)) -+ && (urb_priv->state != URB_DEL)) { -+ urb->status = cc_to_error[cc]; -+ sohci_return_urb (ohci, urb); -+ } else { -+ dl_del_urb (ohci, urb); -+ } -+ } -+ -+ if (ed->state != ED_NEW) { -+ edHeadP = le32_to_cpup (&ed->hwHeadP) & 0xfffffff0; -+ edTailP = le32_to_cpup (&ed->hwTailP); -+ -+ /* unlink eds if they are not busy */ -+ if ((edHeadP == edTailP) && (ed->state == ED_OPER)) -+ ep_unlink (ohci, ed); -+ } -+ -+ td_list = td_list_next; -+ } -+} -+ -+ -+ -+ -+/*-------------------------------------------------------------------------* -+ * Virtual Root Hub -+ *-------------------------------------------------------------------------*/ -+ -+/* Device descriptor */ -+static __u8 root_hub_dev_des[] = -+{ -+ 0x12, /* __u8 bLength; */ -+ 0x01, /* __u8 bDescriptorType; Device */ -+ 0x10, /* __u16 bcdUSB; v1.1 */ -+ 0x01, -+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ -+ 0x00, /* __u8 bDeviceSubClass; */ -+ 0x00, /* __u8 bDeviceProtocol; */ -+ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ -+ 0x00, /* __u16 idVendor; */ -+ 0x00, -+ 0x00, /* __u16 idProduct; */ -+ 0x00, -+ 0x00, /* __u16 bcdDevice; */ -+ 0x00, -+ 0x00, /* __u8 iManufacturer; */ -+ 0x02, /* __u8 iProduct; */ -+ 0x01, /* __u8 iSerialNumber; */ -+ 0x01 /* __u8 bNumConfigurations; */ -+}; -+ -+ -+/* Configuration descriptor */ -+static __u8 root_hub_config_des[] = -+{ -+ 0x09, /* __u8 bLength; */ -+ 0x02, /* __u8 bDescriptorType; Configuration */ -+ 0x19, /* __u16 wTotalLength; */ -+ 0x00, -+ 0x01, /* __u8 bNumInterfaces; */ -+ 0x01, /* __u8 bConfigurationValue; */ -+ 0x00, /* __u8 iConfiguration; */ -+ 0x40, /* __u8 bmAttributes; -+ Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ -+ 0x00, /* __u8 MaxPower; */ -+ -+ /* interface */ -+ 0x09, /* __u8 if_bLength; */ -+ 0x04, /* __u8 if_bDescriptorType; Interface */ -+ 0x00, /* __u8 if_bInterfaceNumber; */ -+ 0x00, /* __u8 if_bAlternateSetting; */ -+ 0x01, /* __u8 if_bNumEndpoints; */ -+ 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ -+ 0x00, /* __u8 if_bInterfaceSubClass; */ -+ 0x00, /* __u8 if_bInterfaceProtocol; */ -+ 0x00, /* __u8 if_iInterface; */ -+ -+ /* endpoint */ -+ 0x07, /* __u8 ep_bLength; */ -+ 0x05, /* __u8 ep_bDescriptorType; Endpoint */ -+ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ -+ 0x03, /* __u8 ep_bmAttributes; Interrupt */ -+ 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ -+ 0x00, -+ 0xff /* __u8 ep_bInterval; 255 ms */ -+}; -+ -+/* Hub class-specific descriptor is constructed dynamically */ -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* prepare Interrupt pipe data; HUB INTERRUPT ENDPOINT */ -+ -+static int rh_send_irq (ohci_t * ohci, void * rh_data, int rh_len) -+{ -+ int num_ports; -+ int i; -+ int ret; -+ int len; -+ -+ __u8 data[8]; -+ -+ num_ports = roothub_a (ohci) & RH_A_NDP; -+ if (num_ports > MAX_ROOT_PORTS) { -+ err ("bogus NDP=%d for OHCI usb-%s", num_ports, -+ ohci->ohci_dev->slot_name); -+ err ("rereads as NDP=%d", -+ readl (&ohci->regs->roothub.a) & RH_A_NDP); -+ /* retry later; "should not happen" */ -+ return 0; -+ } -+ *(__u8 *) data = (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC)) -+ ? 1: 0; -+ ret = *(__u8 *) data; -+ -+ for ( i = 0; i < num_ports; i++) { -+ *(__u8 *) (data + (i + 1) / 8) |= -+ ((roothub_portstatus (ohci, i) & -+ (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC | RH_PS_PRSC)) -+ ? 1: 0) << ((i + 1) % 8); -+ ret += *(__u8 *) (data + (i + 1) / 8); -+ } -+ len = i/8 + 1; -+ -+ if (ret > 0) { -+ memcpy(rh_data, data, -+ min_t(unsigned int, len, -+ min_t(unsigned int, rh_len, sizeof(data)))); -+ return len; -+ } -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* Virtual Root Hub INTs are polled by this timer every "interval" ms */ -+ -+static void rh_int_timer_do (unsigned long ptr) -+{ -+ int len; -+ -+ struct urb * urb = (struct urb *) ptr; -+ ohci_t * ohci = urb->dev->bus->hcpriv; -+ -+ if (ohci->disabled) -+ return; -+ -+ /* ignore timers firing during PM suspend, etc */ -+ if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) -+ goto out; -+ -+ if(ohci->rh.send) { -+ len = rh_send_irq (ohci, urb->transfer_buffer, urb->transfer_buffer_length); -+ if (len > 0) { -+ urb->actual_length = len; -+#ifdef DEBUG -+ urb_print (urb, "RET-t(rh)", usb_pipeout (urb->pipe)); -+#endif -+ if (urb->complete) -+ urb->complete (urb); -+ } -+ } -+ out: -+ rh_init_int_timer (urb); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* Root Hub INTs are polled by this timer */ -+ -+static int rh_init_int_timer (struct urb * urb) -+{ -+ ohci_t * ohci = urb->dev->bus->hcpriv; -+ -+ ohci->rh.interval = urb->interval; -+ init_timer (&ohci->rh.rh_int_timer); -+ ohci->rh.rh_int_timer.function = rh_int_timer_do; -+ ohci->rh.rh_int_timer.data = (unsigned long) urb; -+ ohci->rh.rh_int_timer.expires = -+ jiffies + (HZ * (urb->interval < 30? 30: urb->interval)) / 1000; -+ add_timer (&ohci->rh.rh_int_timer); -+ -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+#define OK(x) len = (x); break -+#define WR_RH_STAT(x) writel((x), &ohci->regs->roothub.status) -+#define WR_RH_PORTSTAT(x) writel((x), &ohci->regs->roothub.portstatus[wIndex-1]) -+#define RD_RH_STAT roothub_status(ohci) -+#define RD_RH_PORTSTAT roothub_portstatus(ohci,wIndex-1) -+ -+/* request to virtual root hub */ -+ -+static int rh_submit_urb (struct urb * urb) -+{ -+ struct usb_device * usb_dev = urb->dev; -+ ohci_t * ohci = usb_dev->bus->hcpriv; -+ unsigned int pipe = urb->pipe; -+ struct usb_ctrlrequest * cmd = (struct usb_ctrlrequest *) urb->setup_packet; -+ void * data = urb->transfer_buffer; -+ int leni = urb->transfer_buffer_length; -+ int len = 0; -+ int status = TD_CC_NOERROR; -+ unsigned long flags; -+ -+ __u32 datab[4]; -+ __u8 * data_buf = (__u8 *) datab; -+ -+ __u16 bmRType_bReq; -+ __u16 wValue; -+ __u16 wIndex; -+ __u16 wLength; -+ -+ spin_lock_irqsave(&ohci->ohci_lock, flags); -+ -+ if (usb_pipeint(pipe)) { -+ ohci->rh.urb = urb; -+ ohci->rh.send = 1; -+ ohci->rh.interval = urb->interval; -+ rh_init_int_timer(urb); -+ urb->status = cc_to_error [TD_CC_NOERROR]; -+ -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ return 0; -+ } -+ -+ bmRType_bReq = cmd->bRequestType | (cmd->bRequest << 8); -+ wValue = le16_to_cpu (cmd->wValue); -+ wIndex = le16_to_cpu (cmd->wIndex); -+ wLength = le16_to_cpu (cmd->wLength); -+ -+ switch (bmRType_bReq) { -+ /* Request Destination: -+ without flags: Device, -+ RH_INTERFACE: interface, -+ RH_ENDPOINT: endpoint, -+ RH_CLASS means HUB here, -+ RH_OTHER | RH_CLASS almost ever means HUB_PORT here -+ */ -+ -+ case RH_GET_STATUS: -+ *(__u16 *) data_buf = cpu_to_le16 (1); OK (2); -+ case RH_GET_STATUS | RH_INTERFACE: -+ *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); -+ case RH_GET_STATUS | RH_ENDPOINT: -+ *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); -+ case RH_GET_STATUS | RH_CLASS: -+ *(__u32 *) data_buf = cpu_to_le32 ( -+ RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); -+ OK (4); -+ case RH_GET_STATUS | RH_OTHER | RH_CLASS: -+ *(__u32 *) data_buf = cpu_to_le32 (RD_RH_PORTSTAT); OK (4); -+ -+ case RH_CLEAR_FEATURE | RH_ENDPOINT: -+ switch (wValue) { -+ case (RH_ENDPOINT_STALL): OK (0); -+ } -+ break; -+ -+ case RH_CLEAR_FEATURE | RH_CLASS: -+ switch (wValue) { -+ case RH_C_HUB_LOCAL_POWER: -+ OK(0); -+ case (RH_C_HUB_OVER_CURRENT): -+ WR_RH_STAT(RH_HS_OCIC); OK (0); -+ } -+ break; -+ -+ case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: -+ switch (wValue) { -+ case (RH_PORT_ENABLE): -+ WR_RH_PORTSTAT (RH_PS_CCS ); OK (0); -+ case (RH_PORT_SUSPEND): -+ WR_RH_PORTSTAT (RH_PS_POCI); OK (0); -+ case (RH_PORT_POWER): -+ WR_RH_PORTSTAT (RH_PS_LSDA); OK (0); -+ case (RH_C_PORT_CONNECTION): -+ WR_RH_PORTSTAT (RH_PS_CSC ); OK (0); -+ case (RH_C_PORT_ENABLE): -+ WR_RH_PORTSTAT (RH_PS_PESC); OK (0); -+ case (RH_C_PORT_SUSPEND): -+ WR_RH_PORTSTAT (RH_PS_PSSC); OK (0); -+ case (RH_C_PORT_OVER_CURRENT): -+ WR_RH_PORTSTAT (RH_PS_OCIC); OK (0); -+ case (RH_C_PORT_RESET): -+ WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); -+ } -+ break; -+ -+ case RH_SET_FEATURE | RH_OTHER | RH_CLASS: -+ switch (wValue) { -+ case (RH_PORT_SUSPEND): -+ WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); -+ case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ -+ if (RD_RH_PORTSTAT & RH_PS_CCS) -+ WR_RH_PORTSTAT (RH_PS_PRS); -+ OK (0); -+ case (RH_PORT_POWER): -+ WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); -+ case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ -+ if (RD_RH_PORTSTAT & RH_PS_CCS) -+ WR_RH_PORTSTAT (RH_PS_PES ); -+ OK (0); -+ } -+ break; -+ -+ case RH_SET_ADDRESS: ohci->rh.devnum = wValue; OK(0); -+ -+ case RH_GET_DESCRIPTOR: -+ switch ((wValue & 0xff00) >> 8) { -+ case (0x01): /* device descriptor */ -+ len = min_t(unsigned int, -+ leni, -+ min_t(unsigned int, -+ sizeof (root_hub_dev_des), -+ wLength)); -+ data_buf = root_hub_dev_des; OK(len); -+ case (0x02): /* configuration descriptor */ -+ len = min_t(unsigned int, -+ leni, -+ min_t(unsigned int, -+ sizeof (root_hub_config_des), -+ wLength)); -+ data_buf = root_hub_config_des; OK(len); -+ case (0x03): /* string descriptors */ -+ len = usb_root_hub_string (wValue & 0xff, -+ (int)(long) ohci->regs, "OHCI", -+ data, wLength); -+ if (len > 0) { -+ data_buf = data; -+ OK(min_t(int, leni, len)); -+ } -+ // else fallthrough -+ default: -+ status = TD_CC_STALL; -+ } -+ break; -+ -+ case RH_GET_DESCRIPTOR | RH_CLASS: -+ { -+ __u32 temp = roothub_a (ohci); -+ -+ data_buf [0] = 9; // min length; -+ data_buf [1] = 0x29; -+ data_buf [2] = temp & RH_A_NDP; -+ data_buf [3] = 0; -+ if (temp & RH_A_PSM) /* per-port power switching? */ -+ data_buf [3] |= 0x1; -+ if (temp & RH_A_NOCP) /* no overcurrent reporting? */ -+ data_buf [3] |= 0x10; -+ else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */ -+ data_buf [3] |= 0x8; -+ -+ datab [1] = 0; -+ data_buf [5] = (temp & RH_A_POTPGT) >> 24; -+ temp = roothub_b (ohci); -+ data_buf [7] = temp & RH_B_DR; -+ if (data_buf [2] < 7) { -+ data_buf [8] = 0xff; -+ } else { -+ data_buf [0] += 2; -+ data_buf [8] = (temp & RH_B_DR) >> 8; -+ data_buf [10] = data_buf [9] = 0xff; -+ } -+ -+ len = min_t(unsigned int, leni, -+ min_t(unsigned int, data_buf [0], wLength)); -+ OK (len); -+ } -+ -+ case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1); -+ -+ case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0); -+ -+ default: -+ dbg ("unsupported root hub command"); -+ status = TD_CC_STALL; -+ } -+ -+#ifdef DEBUG -+ // ohci_dump_roothub (ohci, 0); -+#endif -+ -+ len = min_t(int, len, leni); -+ if (data != data_buf) -+ memcpy (data, data_buf, len); -+ urb->actual_length = len; -+ urb->status = cc_to_error [status]; -+ -+#ifdef DEBUG -+ urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe)); -+#endif -+ -+ urb->hcpriv = NULL; -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ usb_dec_dev_use (usb_dev); -+ urb->dev = NULL; -+ if (urb->complete) -+ urb->complete (urb); -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int rh_unlink_urb (struct urb * urb) -+{ -+ ohci_t * ohci = urb->dev->bus->hcpriv; -+ unsigned int flags; -+ -+ spin_lock_irqsave(&ohci->ohci_lock, flags); -+ if (ohci->rh.urb == urb) { -+ ohci->rh.send = 0; -+ del_timer (&ohci->rh.rh_int_timer); -+ ohci->rh.urb = NULL; -+ -+ urb->hcpriv = NULL; -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ usb_dec_dev_use(urb->dev); -+ urb->dev = NULL; -+ if (urb->transfer_flags & USB_ASYNC_UNLINK) { -+ urb->status = -ECONNRESET; -+ if (urb->complete) -+ urb->complete (urb); -+ } else -+ urb->status = -ENOENT; -+ } else { -+ spin_unlock_irqrestore(&ohci->ohci_lock, flags); -+ } -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------* -+ * HC functions -+ *-------------------------------------------------------------------------*/ -+ -+/* reset the HC and BUS */ -+ -+static int hc_reset (ohci_t * ohci) -+{ -+ int timeout = 30; -+ int smm_timeout = 50; /* 0,5 sec */ -+ -+#ifndef __hppa__ -+ /* PA-RISC doesn't have SMM, but PDC might leave IR set */ -+ if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */ -+ writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */ -+ dbg("USB HC TakeOver from SMM"); -+ while (readl (&ohci->regs->control) & OHCI_CTRL_IR) { -+ wait_ms (10); -+ if (--smm_timeout == 0) { -+ err("USB HC TakeOver failed!"); -+ return -1; -+ } -+ } -+ } -+#endif -+ -+ /* Disable HC interrupts */ -+ writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); -+ -+ dbg("USB HC reset_hc usb-%s: ctrl = 0x%x ;", -+ ohci->ohci_dev->slot_name, -+ readl (&ohci->regs->control)); -+ -+ /* Reset USB (needed by some controllers) */ -+ writel (0, &ohci->regs->control); -+ -+ /* Force a state change from USBRESET to USBOPERATIONAL for ALi */ -+ (void) readl (&ohci->regs->control); /* PCI posting */ -+ writel (ohci->hc_control = OHCI_USB_OPER, &ohci->regs->control); -+ -+ /* HC Reset requires max 10 ms delay */ -+ writel (OHCI_HCR, &ohci->regs->cmdstatus); -+ while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { -+ if (--timeout == 0) { -+ err("USB HC reset timed out!"); -+ return -1; -+ } -+ udelay (1); -+ } -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* Start an OHCI controller, set the BUS operational -+ * enable interrupts -+ * connect the virtual root hub */ -+ -+static int hc_start (ohci_t * ohci) -+{ -+ __u32 mask; -+ unsigned int fminterval; -+ struct usb_device * usb_dev; -+ struct ohci_device * dev; -+ -+ ohci->disabled = 1; -+ -+ /* Tell the controller where the control and bulk lists are -+ * The lists are empty now. */ -+ -+ writel (0, &ohci->regs->ed_controlhead); -+ writel (0, &ohci->regs->ed_bulkhead); -+ -+ writel (ohci->hcca_dma, &ohci->regs->hcca); /* a reset clears this */ -+ -+ fminterval = 0x2edf; -+ writel ((fminterval * 9) / 10, &ohci->regs->periodicstart); -+ fminterval |= ((((fminterval - 210) * 6) / 7) << 16); -+ writel (fminterval, &ohci->regs->fminterval); -+ writel (0x628, &ohci->regs->lsthresh); -+ -+ /* start controller operations */ -+ ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; -+ ohci->disabled = 0; -+ writel (ohci->hc_control, &ohci->regs->control); -+ -+ /* Choose the interrupts we care about now, others later on demand */ -+ mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; -+ writel (mask, &ohci->regs->intrenable); -+ writel (mask, &ohci->regs->intrstatus); -+ -+#ifdef OHCI_USE_NPS -+ if(ohci->flags & OHCI_QUIRK_SUCKYIO) -+ { -+ /* NSC 87560 at least requires different setup .. */ -+ writel ((roothub_a (ohci) | RH_A_NOCP) & -+ ~(RH_A_OCPM | RH_A_POTPGT | RH_A_PSM | RH_A_NPS), -+ &ohci->regs->roothub.a); -+ } -+ else -+ { -+ /* required for AMD-756 and some Mac platforms */ -+ writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM, -+ &ohci->regs->roothub.a); -+ } -+ writel (RH_HS_LPSC, &ohci->regs->roothub.status); -+#endif /* OHCI_USE_NPS */ -+ -+ (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ -+ -+ // POTPGT delay is bits 24-31, in 2 ms units. -+ mdelay ((roothub_a (ohci) >> 23) & 0x1fe); -+ -+ /* connect the virtual root hub */ -+ ohci->rh.devnum = 0; -+ usb_dev = usb_alloc_dev (NULL, ohci->bus); -+ if (!usb_dev) { -+ ohci->disabled = 1; -+ return -ENOMEM; -+ } -+ -+ dev = usb_to_ohci (usb_dev); -+ ohci->bus->root_hub = usb_dev; -+ usb_connect (usb_dev); -+ if (usb_new_device (usb_dev) != 0) { -+ usb_free_dev (usb_dev); -+ ohci->disabled = 1; -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* called only from interrupt handler */ -+ -+static void check_timeouts (struct ohci *ohci) -+{ -+ spin_lock (&ohci->ohci_lock); -+ while (!list_empty (&ohci->timeout_list)) { -+ struct urb *urb; -+ -+ urb = list_entry (ohci->timeout_list.next, struct urb, urb_list); -+ if (time_after (jiffies, urb->timeout)) -+ break; -+ -+ list_del_init (&urb->urb_list); -+ if (urb->status != -EINPROGRESS) -+ continue; -+ -+ urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK; -+ spin_unlock (&ohci->ohci_lock); -+ -+ // outside the interrupt handler (in a timer...) -+ // this reference would race interrupts -+ sohci_unlink_urb (urb); -+ -+ spin_lock (&ohci->ohci_lock); -+ } -+ spin_unlock (&ohci->ohci_lock); -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* an interrupt happens */ -+ -+static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r) -+{ -+ ohci_t * ohci = __ohci; -+ struct ohci_regs * regs = ohci->regs; -+ int ints; -+ -+ spin_lock (&ohci->ohci_lock); -+ -+ /* avoid (slow) readl if only WDH happened */ -+ if ((ohci->hcca->done_head != 0) -+ && !(le32_to_cpup (&ohci->hcca->done_head) & 0x01)) { -+ ints = OHCI_INTR_WDH; -+ -+ /* cardbus/... hardware gone before remove() */ -+ } else if ((ints = readl (®s->intrstatus)) == ~(u32)0) { -+ ohci->disabled++; -+ spin_unlock (&ohci->ohci_lock); -+ err ("%s device removed!", ohci->ohci_dev->slot_name); -+ return; -+ -+ /* interrupt for some other device? */ -+ } else if ((ints &= readl (®s->intrenable)) == 0) { -+ spin_unlock (&ohci->ohci_lock); -+ return; -+ } -+ -+ // dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); -+ -+ if (ints & OHCI_INTR_UE) { -+ ohci->disabled++; -+ err ("OHCI Unrecoverable Error, controller usb-%s disabled", -+ ohci->ohci_dev->slot_name); -+ // e.g. due to PCI Master/Target Abort -+ -+#ifdef DEBUG -+ ohci_dump (ohci, 1); -+#else -+ // FIXME: be optimistic, hope that bug won't repeat often. -+ // Make some non-interrupt context restart the controller. -+ // Count and limit the retries though; either hardware or -+ // software errors can go forever... -+#endif -+ hc_reset (ohci); -+ } -+ -+ if (ints & OHCI_INTR_WDH) { -+ writel (OHCI_INTR_WDH, ®s->intrdisable); -+ (void)readl (®s->intrdisable); /* PCI posting flush */ -+ dl_done_list (ohci, dl_reverse_done_list (ohci)); -+ writel (OHCI_INTR_WDH, ®s->intrenable); -+ (void)readl (®s->intrdisable); /* PCI posting flush */ -+ } -+ -+ if (ints & OHCI_INTR_SO) { -+ dbg("USB Schedule overrun"); -+ writel (OHCI_INTR_SO, ®s->intrenable); -+ (void)readl (®s->intrdisable); /* PCI posting flush */ -+ } -+ -+ // FIXME: this assumes SOF (1/ms) interrupts don't get lost... -+ if (ints & OHCI_INTR_SF) { -+ unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1; -+ writel (OHCI_INTR_SF, ®s->intrdisable); -+ (void)readl (®s->intrdisable); /* PCI posting flush */ -+ if (ohci->ed_rm_list[!frame] != NULL) { -+ dl_del_list (ohci, !frame); -+ } -+ if (ohci->ed_rm_list[frame] != NULL) { -+ writel (OHCI_INTR_SF, ®s->intrenable); -+ (void)readl (®s->intrdisable); /* PCI posting flush */ -+ } -+ } -+ -+ /* -+ * Finally, we are done with trashing about our hardware lists -+ * and other CPUs are allowed in. The festive flipping of the lock -+ * ensues as we struggle with the check_timeouts disaster. -+ */ -+ spin_unlock (&ohci->ohci_lock); -+ -+ if (!list_empty (&ohci->timeout_list)) { -+ check_timeouts (ohci); -+// FIXME: enable SF as needed in a timer; -+// don't make lots of 1ms interrupts -+// On unloaded USB, think 4k ~= 4-5msec -+ if (!list_empty (&ohci->timeout_list)) -+ writel (OHCI_INTR_SF, ®s->intrenable); -+ } -+ -+ writel (ints, ®s->intrstatus); -+ writel (OHCI_INTR_MIE, ®s->intrenable); -+ (void)readl (®s->intrdisable); /* PCI posting flush */ -+ -+ ohci_complete(ohci); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* allocate OHCI */ -+ -+static ohci_t * __devinit hc_alloc_ohci (struct pci_dev *dev, void * mem_base) -+{ -+ ohci_t * ohci; -+ -+ ohci = (ohci_t *) kmalloc (sizeof *ohci, GFP_KERNEL); -+ if (!ohci) -+ return NULL; -+ -+ memset (ohci, 0, sizeof (ohci_t)); -+ -+ ohci->hcca = pci_alloc_consistent (dev, sizeof *ohci->hcca, -+ &ohci->hcca_dma); -+ if (!ohci->hcca) { -+ kfree (ohci); -+ return NULL; -+ } -+ memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); -+ -+ ohci->disabled = 1; -+ ohci->sleeping = 0; -+ ohci->irq = -1; -+ ohci->regs = mem_base; -+ -+ ohci->ohci_dev = dev; -+ pci_set_drvdata(dev, ohci); -+ -+ INIT_LIST_HEAD (&ohci->timeout_list); -+ spin_lock_init(&ohci->ohci_lock); -+ -+ ohci->bus = usb_alloc_bus (&sohci_device_operations); -+ if (!ohci->bus) { -+ pci_set_drvdata (dev, NULL); -+ pci_free_consistent (ohci->ohci_dev, sizeof *ohci->hcca, -+ ohci->hcca, ohci->hcca_dma); -+ kfree (ohci); -+ return NULL; -+ } -+ ohci->bus->bus_name = dev->slot_name; -+ ohci->bus->hcpriv = (void *) ohci; -+ -+ return ohci; -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* De-allocate all resources.. */ -+ -+static void hc_release_ohci (ohci_t * ohci) -+{ -+ dbg ("USB HC release ohci usb-%s", ohci->ohci_dev->slot_name); -+ -+ /* disconnect all devices */ -+ if (ohci->bus->root_hub) -+ usb_disconnect (&ohci->bus->root_hub); -+ -+ if (!ohci->disabled) -+ hc_reset (ohci); -+ -+ if (ohci->irq >= 0) { -+ free_irq (ohci->irq, ohci); -+ ohci->irq = -1; -+ } -+ pci_set_drvdata(ohci->ohci_dev, NULL); -+ if (ohci->bus) { -+ if (ohci->bus->busnum != -1) -+ usb_deregister_bus (ohci->bus); -+ -+ usb_free_bus (ohci->bus); -+ } -+ -+ ohci_mem_cleanup (ohci); -+ -+ /* unmap the IO address space */ -+ iounmap (ohci->regs); -+ -+ pci_free_consistent (ohci->ohci_dev, sizeof *ohci->hcca, -+ ohci->hcca, ohci->hcca_dma); -+ kfree (ohci); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* Increment the module usage count, start the control thread and -+ * return success. */ -+ -+static struct pci_driver ohci_pci_driver; -+ -+static int __devinit -+hc_found_ohci (struct pci_dev *dev, int irq, -+ void *mem_base, const struct pci_device_id *id) -+{ -+ ohci_t * ohci; -+ char buf[8], *bufp = buf; -+ int ret; -+ -+#ifndef __sparc__ -+ sprintf(buf, "%d", irq); -+#else -+ bufp = __irq_itoa(irq); -+#endif -+ printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n", -+ (unsigned long) mem_base, bufp); -+ printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name); -+ -+ ohci = hc_alloc_ohci (dev, mem_base); -+ if (!ohci) { -+ return -ENOMEM; -+ } -+ if ((ret = ohci_mem_init (ohci)) < 0) { -+ hc_release_ohci (ohci); -+ return ret; -+ } -+ ohci->flags = id->driver_data; -+ -+ /* Check for NSC87560. We have to look at the bridge (fn1) to identify -+ the USB (fn2). This quirk might apply to more or even all NSC stuff -+ I don't know.. */ -+ -+ if(dev->vendor == PCI_VENDOR_ID_NS) -+ { -+ struct pci_dev *fn1 = pci_find_slot(dev->bus->number, PCI_DEVFN(PCI_SLOT(dev->devfn), 1)); -+ if(fn1 && fn1->vendor == PCI_VENDOR_ID_NS && fn1->device == PCI_DEVICE_ID_NS_87560_LIO) -+ ohci->flags |= OHCI_QUIRK_SUCKYIO; -+ -+ } -+ -+ if (ohci->flags & OHCI_QUIRK_SUCKYIO) -+ printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n"); -+ if (ohci->flags & OHCI_QUIRK_AMD756) -+ printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n"); -+ -+ if (hc_reset (ohci) < 0) { -+ hc_release_ohci (ohci); -+ return -ENODEV; -+ } -+ -+ /* FIXME this is a second HC reset; why?? */ -+ writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control); -+ (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ -+ wait_ms (10); -+ -+ usb_register_bus (ohci->bus); -+ -+ if (request_irq (irq, hc_interrupt, SA_SHIRQ, -+ ohci_pci_driver.name, ohci) != 0) { -+ err ("request interrupt %s failed", bufp); -+ hc_release_ohci (ohci); -+ return -EBUSY; -+ } -+ ohci->irq = irq; -+ -+ if (hc_start (ohci) < 0) { -+ err ("can't start usb-%s", dev->slot_name); -+ hc_release_ohci (ohci); -+ return -EBUSY; -+ } -+ -+#ifdef DEBUG -+ ohci_dump (ohci, 1); -+#endif -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+#ifdef CONFIG_PM -+ -+/* controller died; cleanup debris, then restart */ -+/* must not be called from interrupt context */ -+ -+static void hc_restart (ohci_t *ohci) -+{ -+ int temp; -+ int i; -+ -+ if (ohci->pci_latency) -+ pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency); -+ -+ ohci->disabled = 1; -+ ohci->sleeping = 0; -+ if (ohci->bus->root_hub) -+ usb_disconnect (&ohci->bus->root_hub); -+ -+ /* empty the interrupt branches */ -+ for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0; -+ for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0; -+ -+ /* no EDs to remove */ -+ ohci->ed_rm_list [0] = NULL; -+ ohci->ed_rm_list [1] = NULL; -+ -+ /* empty control and bulk lists */ -+ ohci->ed_isotail = NULL; -+ ohci->ed_controltail = NULL; -+ ohci->ed_bulktail = NULL; -+ -+ if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) { -+ err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp); -+ } else -+ dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name); -+} -+ -+#endif /* CONFIG_PM */ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* configured so that an OHCI device is always provided */ -+/* always called with process context; sleeping is OK */ -+ -+static int __devinit -+ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ unsigned long mem_resource, mem_len; -+ void *mem_base; -+ int status; -+ -+ if (pci_enable_device(dev) < 0) -+ return -ENODEV; -+ -+ if (!dev->irq) { -+ err("found OHCI device with no IRQ assigned. check BIOS settings!"); -+ pci_disable_device (dev); -+ return -ENODEV; -+ } -+ -+ /* we read its hardware registers as memory */ -+ mem_resource = pci_resource_start(dev, 0); -+ mem_len = pci_resource_len(dev, 0); -+ if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) { -+ dbg ("controller already in use"); -+ pci_disable_device (dev); -+ return -EBUSY; -+ } -+ -+ mem_base = ioremap_nocache (mem_resource, mem_len); -+ if (!mem_base) { -+ err("Error mapping OHCI memory"); -+ release_mem_region (mem_resource, mem_len); -+ pci_disable_device (dev); -+ return -EFAULT; -+ } -+ -+ /* controller writes into our memory */ -+ pci_set_master (dev); -+ -+ status = hc_found_ohci (dev, dev->irq, mem_base, id); -+ if (status < 0) { -+ iounmap (mem_base); -+ release_mem_region (mem_resource, mem_len); -+ pci_disable_device (dev); -+ } -+ return status; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* may be called from interrupt context [interface spec] */ -+/* may be called without controller present */ -+/* may be called with controller, bus, and devices active */ -+ -+static void __devexit -+ohci_pci_remove (struct pci_dev *dev) -+{ -+ ohci_t *ohci = pci_get_drvdata(dev); -+ -+ dbg ("remove %s controller usb-%s%s%s", -+ hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), -+ dev->slot_name, -+ ohci->disabled ? " (disabled)" : "", -+ in_interrupt () ? " in interrupt" : "" -+ ); -+#ifdef DEBUG -+ ohci_dump (ohci, 1); -+#endif -+ -+ /* don't wake up sleeping controllers, or block in interrupt context */ -+ if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER || in_interrupt ()) { -+ dbg ("controller being disabled"); -+ ohci->disabled = 1; -+ } -+ -+ /* on return, USB will always be reset (if present) */ -+ if (ohci->disabled) -+ writel (ohci->hc_control = OHCI_USB_RESET, -+ &ohci->regs->control); -+ -+ hc_release_ohci (ohci); -+ -+ release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0)); -+ pci_disable_device (dev); -+} -+ -+ -+#ifdef CONFIG_PM -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int -+ohci_pci_suspend (struct pci_dev *dev, u32 state) -+{ -+ ohci_t *ohci = pci_get_drvdata(dev); -+ unsigned long flags; -+ u16 cmd; -+ -+ if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) { -+ dbg ("can't suspend usb-%s (state is %s)", dev->slot_name, -+ hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS)); -+ return -EIO; -+ } -+ -+ /* act as if usb suspend can always be used */ -+ info ("USB suspend: usb-%s", dev->slot_name); -+ ohci->sleeping = 1; -+ -+ /* First stop processing */ -+ spin_lock_irqsave (&ohci->ohci_lock, flags); -+ ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); -+ writel (ohci->hc_control, &ohci->regs->control); -+ writel (OHCI_INTR_SF, &ohci->regs->intrstatus); -+ (void) readl (&ohci->regs->intrstatus); -+ spin_unlock_irqrestore (&ohci->ohci_lock, flags); -+ -+ /* Wait a frame or two */ -+ mdelay(1); -+ if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) -+ mdelay (1); -+ -+#ifdef CONFIG_PMAC_PBOOK -+ if (_machine == _MACH_Pmac) -+ disable_irq (ohci->irq); -+ /* else, 2.4 assumes shared irqs -- don't disable */ -+#endif -+ /* Enable remote wakeup */ -+ writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable); -+ -+ /* Suspend chip and let things settle down a bit */ -+ ohci->hc_control = OHCI_USB_SUSPEND; -+ writel (ohci->hc_control, &ohci->regs->control); -+ (void) readl (&ohci->regs->control); -+ mdelay (500); /* No schedule here ! */ -+ switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) { -+ case OHCI_USB_RESET: -+ dbg("Bus in reset phase ???"); -+ break; -+ case OHCI_USB_RESUME: -+ dbg("Bus in resume phase ???"); -+ break; -+ case OHCI_USB_OPER: -+ dbg("Bus in operational phase ???"); -+ break; -+ case OHCI_USB_SUSPEND: -+ dbg("Bus suspended"); -+ break; -+ } -+ /* In some rare situations, Apple's OHCI have happily trashed -+ * memory during sleep. We disable it's bus master bit during -+ * suspend -+ */ -+ pci_read_config_word (dev, PCI_COMMAND, &cmd); -+ cmd &= ~PCI_COMMAND_MASTER; -+ pci_write_config_word (dev, PCI_COMMAND, cmd); -+#ifdef CONFIG_PMAC_PBOOK -+ { -+ struct device_node *of_node; -+ -+ /* Disable USB PAD & cell clock */ -+ of_node = pci_device_to_OF_node (ohci->ohci_dev); -+ if (of_node) -+ pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); -+ } -+#endif -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int -+ohci_pci_resume (struct pci_dev *dev) -+{ -+ ohci_t *ohci = pci_get_drvdata(dev); -+ int temp; -+ unsigned long flags; -+ -+ /* guard against multiple resumes */ -+ atomic_inc (&ohci->resume_count); -+ if (atomic_read (&ohci->resume_count) != 1) { -+ err ("concurrent PCI resumes for usb-%s", dev->slot_name); -+ atomic_dec (&ohci->resume_count); -+ return 0; -+ } -+ -+#ifdef CONFIG_PMAC_PBOOK -+ { -+ struct device_node *of_node; -+ -+ /* Re-enable USB PAD & cell clock */ -+ of_node = pci_device_to_OF_node (ohci->ohci_dev); -+ if (of_node) -+ pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 1); -+ } -+#endif -+ -+ /* did we suspend, or were we powered off? */ -+ ohci->hc_control = readl (&ohci->regs->control); -+ temp = ohci->hc_control & OHCI_CTRL_HCFS; -+ -+#ifdef DEBUG -+ /* the registers may look crazy here */ -+ ohci_dump_status (ohci); -+#endif -+ -+ /* Re-enable bus mastering */ -+ pci_set_master(ohci->ohci_dev); -+ -+ switch (temp) { -+ -+ case OHCI_USB_RESET: // lost power -+ info ("USB restart: usb-%s", dev->slot_name); -+ hc_restart (ohci); -+ break; -+ -+ case OHCI_USB_SUSPEND: // host wakeup -+ case OHCI_USB_RESUME: // remote wakeup -+ info ("USB continue: usb-%s from %s wakeup", dev->slot_name, -+ (temp == OHCI_USB_SUSPEND) -+ ? "host" : "remote"); -+ ohci->hc_control = OHCI_USB_RESUME; -+ writel (ohci->hc_control, &ohci->regs->control); -+ (void) readl (&ohci->regs->control); -+ mdelay (20); /* no schedule here ! */ -+ /* Some controllers (lucent) need a longer delay here */ -+ mdelay (15); -+ temp = readl (&ohci->regs->control); -+ temp = ohci->hc_control & OHCI_CTRL_HCFS; -+ if (temp != OHCI_USB_RESUME) { -+ err ("controller usb-%s won't resume", dev->slot_name); -+ ohci->disabled = 1; -+ return -EIO; -+ } -+ -+ /* Some chips likes being resumed first */ -+ writel (OHCI_USB_OPER, &ohci->regs->control); -+ (void) readl (&ohci->regs->control); -+ mdelay (3); -+ -+ /* Then re-enable operations */ -+ spin_lock_irqsave (&ohci->ohci_lock, flags); -+ ohci->disabled = 0; -+ ohci->sleeping = 0; -+ ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; -+ if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) { -+ if (ohci->ed_controltail) -+ ohci->hc_control |= OHCI_CTRL_CLE; -+ if (ohci->ed_bulktail) -+ ohci->hc_control |= OHCI_CTRL_BLE; -+ } -+ writel (ohci->hc_control, &ohci->regs->control); -+ writel (OHCI_INTR_SF, &ohci->regs->intrstatus); -+ writel (OHCI_INTR_SF, &ohci->regs->intrenable); -+ /* Check for a pending done list */ -+ writel (OHCI_INTR_WDH, &ohci->regs->intrdisable); -+ (void) readl (&ohci->regs->intrdisable); -+#ifdef CONFIG_PMAC_PBOOK -+ if (_machine == _MACH_Pmac) -+ enable_irq (ohci->irq); -+#endif -+ if (ohci->hcca->done_head) -+ dl_done_list (ohci, dl_reverse_done_list (ohci)); -+ writel (OHCI_INTR_WDH, &ohci->regs->intrenable); -+ writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ -+ writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ -+ spin_unlock_irqrestore (&ohci->ohci_lock, flags); -+ break; -+ -+ default: -+ warn ("odd PCI resume for usb-%s", dev->slot_name); -+ } -+ -+ /* controller is operational, extra resumes are harmless */ -+ atomic_dec (&ohci->resume_count); -+ -+ return 0; -+} -+ -+#endif /* CONFIG_PM */ -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static const struct pci_device_id __devinitdata ohci_pci_ids [] = { { -+ -+ /* -+ * AMD-756 [Viper] USB has a serious erratum when used with -+ * lowspeed devices like mice. -+ */ -+ vendor: 0x1022, -+ device: 0x740c, -+ subvendor: PCI_ANY_ID, -+ subdevice: PCI_ANY_ID, -+ -+ driver_data: OHCI_QUIRK_AMD756, -+ -+} , { -+ -+ /* handle any USB OHCI controller */ -+ class: ((PCI_CLASS_SERIAL_USB << 8) | 0x10), -+ class_mask: ~0, -+ -+ /* no matter who makes it */ -+ vendor: PCI_ANY_ID, -+ device: PCI_ANY_ID, -+ subvendor: PCI_ANY_ID, -+ subdevice: PCI_ANY_ID, -+ -+ }, { /* end: all zeroes */ } -+}; -+ -+MODULE_DEVICE_TABLE (pci, ohci_pci_ids); -+ -+static struct pci_driver ohci_pci_driver = { -+ name: "usb-ohci", -+ id_table: &ohci_pci_ids [0], -+ -+ probe: ohci_pci_probe, -+ remove: __devexit_p(ohci_pci_remove), -+ -+#ifdef CONFIG_PM -+ suspend: ohci_pci_suspend, -+ resume: ohci_pci_resume, -+#endif /* PM */ -+}; -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int __init ohci_hcd_init (void) -+{ -+ return pci_module_init (&ohci_pci_driver); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void __exit ohci_hcd_cleanup (void) -+{ -+ pci_unregister_driver (&ohci_pci_driver); -+} -+ -+module_init (ohci_hcd_init); -+module_exit (ohci_hcd_cleanup); -+ -+ -+MODULE_AUTHOR( DRIVER_AUTHOR ); -+MODULE_DESCRIPTION( DRIVER_DESC ); -+MODULE_LICENSE("GPL"); diff --git a/linux/linux-mtx-1-2.4.27/09-au1000-eth-vlan.diff b/linux/linux-mtx-1-2.4.27/09-au1000-eth-vlan.diff deleted file mode 100644 index 2f09c02d5a..0000000000 --- a/linux/linux-mtx-1-2.4.27/09-au1000-eth-vlan.diff +++ /dev/null @@ -1,10 +0,0 @@ ---- linux/drivers/net/au1000_eth.c.orig 2004-11-18 13:44:52.163605416 +0100 -+++ linux/drivers/net/au1000_eth.c 2004-11-18 13:51:42.096286176 +0100 -@@ -1389,6 +1389,7 @@ - control |= MAC_FULL_DUPLEX; - } - aup->mac->control = control; -+ aup->mac->vlan1_tag = 0x8100; /* activate vlan support */ - au_sync(); - - spin_unlock_irqrestore(&aup->lock, flags); diff --git a/linux/linux-mtx-1-2.4.27/10-iw-max-spy-32.diff b/linux/linux-mtx-1-2.4.27/10-iw-max-spy-32.diff deleted file mode 100644 index e782d3d3dc..0000000000 --- a/linux/linux-mtx-1-2.4.27/10-iw-max-spy-32.diff +++ /dev/null @@ -1,11 +0,0 @@ ---- linux-mips-2.4.24-pre2/include/linux/wireless.h 2004-11-17 18:05:09.000000000 +0100 -+++ linux/include/linux/wireless.h 2004-11-17 19:02:44.370081592 +0100 -@@ -334,7 +334,7 @@ - * a few of them in the struct iw_range. */ - - /* Maximum of address that you may set with SPY */ --#define IW_MAX_SPY 8 -+#define IW_MAX_SPY 32 - - /* Maximum of address that you may get in the - list of access points in range */ diff --git a/linux/linux-mtx-1-2.4.27/11-mtd-proc-partition-rw.diff b/linux/linux-mtx-1-2.4.27/11-mtd-proc-partition-rw.diff deleted file mode 100644 index 54ba5fff98..0000000000 --- a/linux/linux-mtx-1-2.4.27/11-mtd-proc-partition-rw.diff +++ /dev/null @@ -1,173 +0,0 @@ -diff -Nurb linux/drivers/mtd/mtdcore.c linux-mtd-rw/drivers/mtd/mtdcore.c ---- linux/drivers/mtd/mtdcore.c 2004-11-18 13:16:00.000000000 +0100 -+++ linux-mtd-rw/drivers/mtd/mtdcore.c 2004-11-18 15:27:13.130036616 +0100 -@@ -25,6 +25,10 @@ - - #include - -+/* this symbol is exported by the procfs. */ -+extern struct proc_dir_entry *proc_sys_root; -+ -+ - /* These are exported solely for the purpose of mtd_blkdevs.c. You - should not use them for _anything_ else */ - DECLARE_MUTEX(mtd_table_mutex); -@@ -336,8 +340,83 @@ - - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) - static struct proc_dir_entry *proc_mtd; -+ -+static struct proc_dir_entry *proc_sys_mtd; -+static struct proc_dir_entry *proc_sys_mtd_partition[MAX_MTD_DEVICES]; -+static struct proc_dir_entry *proc_sys_mtd_partition_rw[MAX_MTD_DEVICES]; - #endif - -+/*===================================0 -+ * mtdproc_read_partition_access -+ */ -+static int mtdproc_read_partition_access ( char *page, char **start, off_t off,int count, -+ int *eof, void *data -+ ) -+{ -+ int partid = (unsigned int)data; -+ int len = 0; -+ -+ // NO RETURN FROM HERE UNTIL "up(&mtd_table_mutex)". -+ down(&mtd_table_mutex); -+ -+ if (partid < MAX_MTD_DEVICES) -+ { -+ struct mtd_info *this = mtd_table[partid]; -+ if (this) -+ { -+ page[len] = (this->flags & MTD_WRITEABLE) ? '1' : '0'; -+ len++; -+ } -+ } -+ -+ up(&mtd_table_mutex); -+ -+ if (off >= len) -+ return 0; -+ *start = page + off; -+ return ((count < len-off) ? count : len-off); -+} -+ -+ -+static int mtdproc_write_partition_access (struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ int partid = (unsigned int)data; -+ int len = 0; -+ -+ // NO RETURN FROM HERE UNTIL "up(&mtd_table_mutex)". -+ down(&mtd_table_mutex); -+ -+ if (partid < MAX_MTD_DEVICES) -+ { -+ struct mtd_info *this = mtd_table[partid]; -+ if (this && count > 0) -+ { -+ switch (*buffer) -+ { -+ case '0': -+ this->flags &= ~(this->master_flags & MTD_WRITEABLE); -+ break; -+ -+ case '1': -+ this->flags |= ~(this->master_flags & MTD_WRITEABLE); -+ break; -+ -+ default: -+ break; -+ } -+ } -+ } -+ -+ up(&mtd_table_mutex); -+ -+ return count; -+} -+ -+ -+ -+ -+ - static inline int mtd_proc_info (char *buf, int i) - { - struct mtd_info *this = mtd_table[i]; -@@ -349,6 +428,7 @@ - this->erasesize, this->name); - } - -+ - static int mtd_read_proc ( char *page, char **start, off_t off,int count - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) - ,int *eof, void *data_unused -@@ -404,12 +484,31 @@ - /*====================================================================*/ - /* Init code */ - -+ - int __init init_mtd(void) - { - #ifdef CONFIG_PROC_FS - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) -+ int i; -+ - if ((proc_mtd = create_proc_entry( "mtd", 0, 0 ))) - proc_mtd->read_proc = mtd_read_proc; -+ -+ proc_sys_mtd = proc_mkdir("mtd", proc_sys_root); -+ for (i=0; iread_proc = mtdproc_read_partition_access; -+ proc_sys_mtd_partition_rw[i]->write_proc = mtdproc_write_partition_access; -+ proc_sys_mtd_partition_rw[i]->data = (void *)i; -+ } -+ } - #else - proc_register_dynamic(&proc_root,&mtd_proc_entry); - #endif -@@ -425,6 +524,8 @@ - return 0; - } - -+ -+ - static void __exit cleanup_mtd(void) - { - #ifdef CONFIG_PM -diff -Nurb linux/drivers/mtd/mtdpart.c linux-mtd-rw/drivers/mtd/mtdpart.c ---- linux/drivers/mtd/mtdpart.c 2004-11-18 13:16:00.000000000 +0100 -+++ linux-mtd-rw/drivers/mtd/mtdpart.c 2004-11-18 15:27:13.131036464 +0100 -@@ -341,6 +341,9 @@ - /* set up the MTD object for this partition */ - slave->mtd.type = master->type; - slave->mtd.flags = master->flags & ~parts[i].mask_flags; -+ slave->mtd.master_flags = master->flags; -+ slave->mtd.mask_flags = parts[i].mask_flags; -+ - slave->mtd.size = parts[i].size; - slave->mtd.oobblock = master->oobblock; - slave->mtd.oobsize = master->oobsize; -diff -Nurb linux/include/linux/mtd/mtd.h linux-mtd-rw/include/linux/mtd/mtd.h ---- linux/include/linux/mtd/mtd.h 2004-11-18 13:16:31.000000000 +0100 -+++ linux-mtd-rw/include/linux/mtd/mtd.h 2004-11-18 15:27:13.000000000 +0100 -@@ -232,6 +232,9 @@ - - struct module *owner; - int usecount; -+ -+ u_int32_t master_flags; -+ u_int32_t mask_flags; - }; - - diff --git a/linux/linux-mtx-1-2.4.27/12-openswan-2.2.0-nat-t.diff b/linux/linux-mtx-1-2.4.27/12-openswan-2.2.0-nat-t.diff deleted file mode 100644 index 2a18d605bf..0000000000 --- a/linux/linux-mtx-1-2.4.27/12-openswan-2.2.0-nat-t.diff +++ /dev/null @@ -1,143 +0,0 @@ -diff -Nurb linux-08/include/net/sock.h linux/include/net/sock.h ---- linux-08/include/net/sock.h 2004-11-19 11:37:23.376715120 +0100 -+++ linux/include/net/sock.h 2004-11-19 11:39:29.874484536 +0100 -@@ -256,6 +256,13 @@ - __u32 end_seq; - }; - -+#if 1 -+#define UDP_OPT_IN_SOCK 1 -+struct udp_opt { -+ __u32 esp_in_udp; -+}; -+#endif -+ - struct tcp_opt { - int tcp_header_len; /* Bytes of tcp header to send */ - -@@ -648,6 +655,9 @@ - #if defined(CONFIG_SPX) || defined (CONFIG_SPX_MODULE) - struct spx_opt af_spx; - #endif /* CONFIG_SPX */ -+#if 1 -+ struct udp_opt af_udp; -+#endif - - } tp_pinfo; - -diff -Nurb linux-08/net/Config.in linux/net/Config.in ---- linux-08/net/Config.in 2004-11-19 11:37:23.770655232 +0100 -+++ linux/net/Config.in 2004-11-19 11:39:29.874484536 +0100 -@@ -102,4 +102,6 @@ - dep_tristate 'Packet Generator (USE WITH CAUTION)' CONFIG_NET_PKTGEN $CONFIG_PROC_FS - endmenu - -+bool 'IPSEC NAT-Traversal' CONFIG_IPSEC_NAT_TRAVERSAL -+ - endmenu -diff -Nurb linux-08/net/ipv4/udp.c linux/net/ipv4/udp.c ---- linux-08/net/ipv4/udp.c 2004-11-19 11:37:23.897635928 +0100 -+++ linux/net/ipv4/udp.c 2004-11-19 11:39:29.875484384 +0100 -@@ -810,6 +810,9 @@ - - static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) - { -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ struct udp_opt *tp = &(sk->tp_pinfo.af_udp); -+#endif - /* - * Charge it to the socket, dropping if the queue is full. - */ -@@ -827,6 +830,40 @@ - } - #endif - -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if (tp->esp_in_udp) { -+ /* -+ * Set skb->sk and xmit packet to ipsec_rcv. -+ * -+ * If ret != 0, ipsec_rcv refused the packet (not ESPinUDP), -+ * restore skb->sk and fall back to sock_queue_rcv_skb -+ */ -+ struct inet_protocol *esp = NULL; -+ -+#if defined(CONFIG_IPSEC) && !defined(CONFIG_IPSEC_MODULE) -+ /* optomize only when we know it is statically linked */ -+ extern struct inet_protocol esp_protocol; -+ esp = &esp_protocol; -+#else -+ for (esp = (struct inet_protocol *)inet_protos[IPPROTO_ESP & (MAX_INET_PROTOS - 1)]; -+ (esp) && (esp->protocol != IPPROTO_ESP); -+ esp = esp->next); -+#endif -+ -+ if (esp && esp->handler) { -+ struct sock *sav_sk = skb->sk; -+ skb->sk = sk; -+ if (esp->handler(skb) == 0) { -+ skb->sk = sav_sk; -+ /*not sure we might count ESPinUDP as UDP...*/ -+ UDP_INC_STATS_BH(UdpInDatagrams); -+ return 0; -+ } -+ skb->sk = sav_sk; -+ } -+ } -+#endif -+ - if (sock_queue_rcv_skb(sk,skb)<0) { - UDP_INC_STATS_BH(UdpInErrors); - IP_INC_STATS_BH(IpInDiscards); -@@ -1050,13 +1087,49 @@ - return len; - } - -+static int udp_setsockopt(struct sock *sk, int level, int optname, -+ char *optval, int optlen) -+{ -+ struct udp_opt *tp = &(sk->tp_pinfo.af_udp); -+ int val; -+ int err = 0; -+ -+ if (level != SOL_UDP) -+ return ip_setsockopt(sk, level, optname, optval, optlen); -+ -+ if(optlenesp_in_udp = val; -+ break; -+#endif -+ default: -+ err = -ENOPROTOOPT; -+ break; -+ } -+ -+ release_sock(sk); -+ return err; -+} -+ - struct proto udp_prot = { - name: "UDP", - close: udp_close, - connect: udp_connect, - disconnect: udp_disconnect, - ioctl: udp_ioctl, -- setsockopt: ip_setsockopt, -+ setsockopt: udp_setsockopt, - getsockopt: ip_getsockopt, - sendmsg: udp_sendmsg, - recvmsg: udp_recvmsg, - diff --git a/linux/linux-mtx-1-2.4.27/13-openswan-2.2.0.patch b/linux/linux-mtx-1-2.4.27/13-openswan-2.2.0.patch deleted file mode 100644 index db64219eda..0000000000 --- a/linux/linux-mtx-1-2.4.27/13-openswan-2.2.0.patch +++ /dev/null @@ -1,61573 +0,0 @@ -make[1]: Entering directory `/data/mtx/oe/tmp/work/openswan-2.2.0-r0/openswan-2.2.0' -packaging/utils/kernelpatch 2.4 ---- linux/Documentation/Configure.help.orig Fri Dec 21 12:41:53 2001 -+++ linux/Documentation/Configure.help Mon Jul 29 16:35:32 2002 -@@ -24237,5 +24237,65 @@ - --# -+IP Security Protocol (IPSEC) (EXPERIMENTAL) -+CONFIG_IPSEC -+ This unit is experimental code. -+ Pick 'y' for static linking, 'm' for module support or 'n' for none. -+ This option adds support for network layer packet encryption and/or -+ authentication with participating hosts. The standards start with: -+ RFCs 2411, 2407 and 2401. Others are mentioned where they refer to -+ specific features below. There are more pending which can be found -+ at: ftp://ftp.ietf.org/internet-drafts/draft-ietf-ipsec-*. -+ A description of each document can also be found at: -+ http://ietf.org/ids.by.wg/ipsec.html. -+ Their charter can be found at: -+ http://www.ietf.org/html.charters/ipsec-charter.html -+ Snapshots and releases of the current work can be found at: -+ http://www.freeswan.org/ -+ -+IPSEC: IP-in-IP encapsulation -+CONFIG_IPSEC_IPIP -+ This option provides support for tunnel mode IPSEC. It is recommended -+ to enable this. -+ -+IPSEC: Authentication Header -+CONFIG_IPSEC_AH -+ This option provides support for the IPSEC Authentication Header -+ (IP protocol 51) which provides packet layer sender and content -+ authentication. It is recommended to enable this. RFC2402 -+ -+HMAC-MD5 algorithm -+CONFIG_IPSEC_AUTH_HMAC_MD5 -+ Provides support for authentication using the HMAC MD5 -+ algorithm with 96 bits of hash used as the authenticator. RFC2403 -+ -+HMAC-SHA1 algorithm -+CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ Provides support for Authentication Header using the HMAC SHA1 -+ algorithm with 96 bits of hash used as the authenticator. RFC2404 -+ -+IPSEC: Encapsulating Security Payload -+CONFIG_IPSEC_ESP -+ This option provides support for the IPSEC Encapsulation Security -+ Payload (IP protocol 50) which provides packet layer content -+ hiding. It is recommended to enable this. RFC2406 -+ -+3DES algorithm -+CONFIG_IPSEC_ENC_3DES -+ Provides support for Encapsulation Security Payload protocol, using -+ the triple DES encryption algorithm. RFC2451 -+ -+IPSEC Debugging Option -+CONFIG_IPSEC_DEBUG -+ Enables IPSEC kernel debugging. It is further controlled by the -+ user space utility 'klipsdebug'. -+ -+IPSEC Regression Testing option -+CONFIG_IPSEC_REGRESS -+ Enables IPSEC regression testing. Creates a number of switches in -+ /proc/sys/net/ipsec which cause various failure modes in KLIPS. -+ For more details see FreeSWAN source under -+ testing/doc/regression_options.txt. -+ -+# - # A couple of things I keep forgetting: - # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, - # Intel, IRQ, ISDN, Linux, MSDOS, NetWare, NetWinder, ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/README.openswan-2 Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,112 @@ -+* -+* RCSID $Id$ -+* -+ -+ **************************************** -+ * IPSEC for Linux, Release 2.xx series * -+ **************************************** -+ -+ -+ -+1. Files -+ -+The contents of linux/net/ipsec/ (see below) join the linux kernel source tree. -+as provided for higher up. -+ -+The programs/ directory contains the user-level utilities which you need -+to run IPSEC. See the top-level top/INSTALL to compile and install them. -+ -+The testing/ directory contains test scripts. -+ -+The doc/ directory contains -- what else -- documentation. -+ -+1.1. Kernel files -+ -+The following are found in net/ipsec/: -+ -+Makefile The Makefile -+Config.in The configuration script for make menuconfig -+defconfig Configuration defaults for first time. -+ -+radij.c General-purpose radix-tree operations -+ -+ipsec_ipcomp.c IPCOMP encapsulate/decapsulate code. -+ipsec_ah.c Authentication Header (AH) encapsulate/decapsulate code. -+ipsec_esp.c Encapsulated Security Payload (ESP) encap/decap code. -+ -+pfkey_v2.c PF_KEYv2 socket interface code. -+pfkey_v2_parser.c PF_KEYv2 message parsing and processing code. -+ -+ipsec_init.c Initialization code, /proc interface. -+ipsec_radij.c Interface with the radix tree code. -+ipsec_netlink.c Interface with the netlink code. -+ipsec_xform.c Routines and structures common to transforms. -+ipsec_tunnel.c The outgoing packet processing code. -+ipsec_rcv.c The incoming packet processing code. -+ipsec_md5c.c Somewhat modified RSADSI MD5 C code. -+ipsec_sha1.c Somewhat modified Steve Reid SHA-1 C code. -+ -+sysctl_net_ipsec.c /proc/sys/net/ipsec/* variable definitions. -+ -+version.c symbolic link to project version. -+ -+radij.h Headers for radij.c -+ -+ipcomp.h Headers used by IPCOMP code. -+ -+ipsec_radij.h Interface with the radix tree code. -+ipsec_netlink.h Headers used by the netlink interface. -+ipsec_encap.h Headers defining encapsulation structures. -+ipsec_xform.h Transform headers. -+ipsec_tunnel.h Headers used by tunneling code. -+ipsec_ipe4.h Headers for the IP-in-IP code. -+ipsec_ah.h Headers common to AH transforms. -+ipsec_md5h.h RSADSI MD5 headers. -+ipsec_sha1.h SHA-1 headers. -+ipsec_esp.h Headers common to ESP transfroms. -+ipsec_rcv.h Headers for incoming packet processing code. -+ -+1.2. User-level files. -+ -+The following are found in utils/: -+ -+eroute.c Create an "extended route" source code -+spi.c Set up Security Associations source code -+spigrp.c Link SPIs together source code. -+tncfg.c Configure the tunneling features of the virtual interface -+ source code -+klipsdebug.c Set/reset klips debugging features source code. -+version.c symbolic link to project version. -+ -+eroute.8 Create an "extended route" manual page -+spi.8 Set up Security Associations manual page -+spigrp.8 Link SPIs together manual page -+tncfg.8 Configure the tunneling features of the virtual interface -+ manual page -+klipsdebug.8 Set/reset klips debugging features manual page -+ -+eroute.5 /proc/net/ipsec_eroute format manual page -+spi.5 /proc/net/ipsec_spi format manual page -+spigrp.5 /proc/net/ipsec_spigrp format manual page -+tncfg.5 /proc/net/ipsec_tncfg format manual page -+klipsdebug.5 /proc/net/ipsec_klipsdebug format manual page -+version.5 /proc/net/ipsec_version format manual page -+pf_key.5 /proc/net/pf_key format manual page -+ -+Makefile Utilities makefile. -+ -+*.8 Manpages for the respective utils. -+ -+ -+1.3. Test files -+ -+The test scripts are locate in testing/ and and documentation is found -+at doc/src/umltesting.html. Automated testing via "make check" is available -+provided that the User-Mode-Linux patches are available. -+ -+* -+* $Log$ -+* Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+* Turn off EOLN_NATIVE flag -+* -+* (Logical change 1.5010) -+* -+* Revision 1.1 2003/12/10 01:07:49 mcr -+* documentation for additions. -+* -+* ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/aes/Makefile.objs Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,13 @@ -+ -+ASM-$(ARCH_ASM):=1 -+ASM_X86:=$(ASM-i586)$(ASM-i686) -+ -+ifneq ($(strip $(ASM_X86)),) -+obj-$(CONFIG_IPSEC_ENC_AES) += aes-i586.o -+else -+obj-$(CONFIG_IPSEC_ENC_AES) += aes.o -+endif -+ -+obj-$(CONFIG_IPSEC_ENC_AES) += aes_cbc.o -+obj-$(CONFIG_IPSEC_ENC_AES) += aes_xcbc_mac.o -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/aes/aes-i586.S Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,892 @@ -+// -+// Copyright (c) 2001, Dr Brian Gladman , Worcester, UK. -+// All rights reserved. -+// -+// TERMS -+// -+// Redistribution and use in source and binary forms, with or without -+// modification, are permitted subject to the following conditions: -+// -+// 1. Redistributions of source code must retain the above copyright -+// notice, this list of conditions and the following disclaimer. -+// -+// 2. Redistributions in binary form must reproduce the above copyright -+// notice, this list of conditions and the following disclaimer in the -+// documentation and/or other materials provided with the distribution. -+// -+// 3. The copyright holder's name must not be used to endorse or promote -+// any products derived from this software without his specific prior -+// written permission. -+// -+// This software is provided 'as is' with no express or implied warranties -+// of correctness or fitness for purpose. -+ -+// Modified by Jari Ruusu, December 24 2001 -+// - Converted syntax to GNU CPP/assembler syntax -+// - C programming interface converted back to "old" API -+// - Minor portability cleanups and speed optimizations -+ -+// An AES (Rijndael) implementation for the Pentium. This version only -+// implements the standard AES block length (128 bits, 16 bytes). This code -+// does not preserve the eax, ecx or edx registers or the artihmetic status -+// flags. However, the ebx, esi, edi, and ebp registers are preserved across -+// calls. -+ -+// void aes_set_key(aes_context *cx, const unsigned char key[], const int key_len, const int f) -+// void aes_encrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) -+// void aes_decrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) -+ -+#if defined(USE_UNDERLINE) -+# define aes_set_key _aes_set_key -+# define aes_encrypt _aes_encrypt -+# define aes_decrypt _aes_decrypt -+#endif -+#if !defined(ALIGN32BYTES) -+# define ALIGN32BYTES 32 -+#endif -+ -+ .file "aes-i586.S" -+ .globl aes_set_key -+ .globl aes_encrypt -+ .globl aes_decrypt -+ -+#define tlen 1024 // length of each of 4 'xor' arrays (256 32-bit words) -+ -+// offsets to parameters with one register pushed onto stack -+ -+#define ctx 8 // AES context structure -+#define in_blk 12 // input byte array address parameter -+#define out_blk 16 // output byte array address parameter -+ -+// offsets in context structure -+ -+#define nkey 0 // key length, size 4 -+#define nrnd 4 // number of rounds, size 4 -+#define ekey 8 // encryption key schedule base address, size 256 -+#define dkey 264 // decryption key schedule base address, size 256 -+ -+// This macro performs a forward encryption cycle. It is entered with -+// the first previous round column values in %eax, %ebx, %esi and %edi and -+// exits with the final values in the same registers. -+ -+#define fwd_rnd(p1,p2) \ -+ mov %ebx,(%esp) ;\ -+ movzbl %al,%edx ;\ -+ mov %eax,%ecx ;\ -+ mov p2(%ebp),%eax ;\ -+ mov %edi,4(%esp) ;\ -+ mov p2+12(%ebp),%edi ;\ -+ xor p1(,%edx,4),%eax ;\ -+ movzbl %ch,%edx ;\ -+ shr $16,%ecx ;\ -+ mov p2+4(%ebp),%ebx ;\ -+ xor p1+tlen(,%edx,4),%edi ;\ -+ movzbl %cl,%edx ;\ -+ movzbl %ch,%ecx ;\ -+ xor p1+3*tlen(,%ecx,4),%ebx ;\ -+ mov %esi,%ecx ;\ -+ mov p1+2*tlen(,%edx,4),%esi ;\ -+ movzbl %cl,%edx ;\ -+ xor p1(,%edx,4),%esi ;\ -+ movzbl %ch,%edx ;\ -+ shr $16,%ecx ;\ -+ xor p1+tlen(,%edx,4),%ebx ;\ -+ movzbl %cl,%edx ;\ -+ movzbl %ch,%ecx ;\ -+ xor p1+2*tlen(,%edx,4),%eax ;\ -+ mov (%esp),%edx ;\ -+ xor p1+3*tlen(,%ecx,4),%edi ;\ -+ movzbl %dl,%ecx ;\ -+ xor p2+8(%ebp),%esi ;\ -+ xor p1(,%ecx,4),%ebx ;\ -+ movzbl %dh,%ecx ;\ -+ shr $16,%edx ;\ -+ xor p1+tlen(,%ecx,4),%eax ;\ -+ movzbl %dl,%ecx ;\ -+ movzbl %dh,%edx ;\ -+ xor p1+2*tlen(,%ecx,4),%edi ;\ -+ mov 4(%esp),%ecx ;\ -+ xor p1+3*tlen(,%edx,4),%esi ;\ -+ movzbl %cl,%edx ;\ -+ xor p1(,%edx,4),%edi ;\ -+ movzbl %ch,%edx ;\ -+ shr $16,%ecx ;\ -+ xor p1+tlen(,%edx,4),%esi ;\ -+ movzbl %cl,%edx ;\ -+ movzbl %ch,%ecx ;\ -+ xor p1+2*tlen(,%edx,4),%ebx ;\ -+ xor p1+3*tlen(,%ecx,4),%eax -+ -+// This macro performs an inverse encryption cycle. It is entered with -+// the first previous round column values in %eax, %ebx, %esi and %edi and -+// exits with the final values in the same registers. -+ -+#define inv_rnd(p1,p2) \ -+ movzbl %al,%edx ;\ -+ mov %ebx,(%esp) ;\ -+ mov %eax,%ecx ;\ -+ mov p2(%ebp),%eax ;\ -+ mov %edi,4(%esp) ;\ -+ mov p2+4(%ebp),%ebx ;\ -+ xor p1(,%edx,4),%eax ;\ -+ movzbl %ch,%edx ;\ -+ shr $16,%ecx ;\ -+ mov p2+12(%ebp),%edi ;\ -+ xor p1+tlen(,%edx,4),%ebx ;\ -+ movzbl %cl,%edx ;\ -+ movzbl %ch,%ecx ;\ -+ xor p1+3*tlen(,%ecx,4),%edi ;\ -+ mov %esi,%ecx ;\ -+ mov p1+2*tlen(,%edx,4),%esi ;\ -+ movzbl %cl,%edx ;\ -+ xor p1(,%edx,4),%esi ;\ -+ movzbl %ch,%edx ;\ -+ shr $16,%ecx ;\ -+ xor p1+tlen(,%edx,4),%edi ;\ -+ movzbl %cl,%edx ;\ -+ movzbl %ch,%ecx ;\ -+ xor p1+2*tlen(,%edx,4),%eax ;\ -+ mov (%esp),%edx ;\ -+ xor p1+3*tlen(,%ecx,4),%ebx ;\ -+ movzbl %dl,%ecx ;\ -+ xor p2+8(%ebp),%esi ;\ -+ xor p1(,%ecx,4),%ebx ;\ -+ movzbl %dh,%ecx ;\ -+ shr $16,%edx ;\ -+ xor p1+tlen(,%ecx,4),%esi ;\ -+ movzbl %dl,%ecx ;\ -+ movzbl %dh,%edx ;\ -+ xor p1+2*tlen(,%ecx,4),%edi ;\ -+ mov 4(%esp),%ecx ;\ -+ xor p1+3*tlen(,%edx,4),%eax ;\ -+ movzbl %cl,%edx ;\ -+ xor p1(,%edx,4),%edi ;\ -+ movzbl %ch,%edx ;\ -+ shr $16,%ecx ;\ -+ xor p1+tlen(,%edx,4),%eax ;\ -+ movzbl %cl,%edx ;\ -+ movzbl %ch,%ecx ;\ -+ xor p1+2*tlen(,%edx,4),%ebx ;\ -+ xor p1+3*tlen(,%ecx,4),%esi -+ -+// AES (Rijndael) Encryption Subroutine -+ -+ .text -+ .align ALIGN32BYTES -+aes_encrypt: -+ push %ebp -+ mov ctx(%esp),%ebp // pointer to context -+ mov in_blk(%esp),%ecx -+ push %ebx -+ push %esi -+ push %edi -+ mov nrnd(%ebp),%edx // number of rounds -+ lea ekey+16(%ebp),%ebp // key pointer -+ -+// input four columns and xor in first round key -+ -+ mov (%ecx),%eax -+ mov 4(%ecx),%ebx -+ mov 8(%ecx),%esi -+ mov 12(%ecx),%edi -+ xor -16(%ebp),%eax -+ xor -12(%ebp),%ebx -+ xor -8(%ebp),%esi -+ xor -4(%ebp),%edi -+ -+ sub $8,%esp // space for register saves on stack -+ -+ sub $10,%edx -+ je aes_15 -+ add $32,%ebp -+ sub $2,%edx -+ je aes_13 -+ add $32,%ebp -+ -+ fwd_rnd(aes_ft_tab,-64) // 14 rounds for 256-bit key -+ fwd_rnd(aes_ft_tab,-48) -+aes_13: fwd_rnd(aes_ft_tab,-32) // 12 rounds for 192-bit key -+ fwd_rnd(aes_ft_tab,-16) -+aes_15: fwd_rnd(aes_ft_tab,0) // 10 rounds for 128-bit key -+ fwd_rnd(aes_ft_tab,16) -+ fwd_rnd(aes_ft_tab,32) -+ fwd_rnd(aes_ft_tab,48) -+ fwd_rnd(aes_ft_tab,64) -+ fwd_rnd(aes_ft_tab,80) -+ fwd_rnd(aes_ft_tab,96) -+ fwd_rnd(aes_ft_tab,112) -+ fwd_rnd(aes_ft_tab,128) -+ fwd_rnd(aes_fl_tab,144) // last round uses a different table -+ -+// move final values to the output array. -+ -+ mov out_blk+20(%esp),%ebp -+ add $8,%esp -+ mov %eax,(%ebp) -+ mov %ebx,4(%ebp) -+ mov %esi,8(%ebp) -+ mov %edi,12(%ebp) -+ pop %edi -+ pop %esi -+ pop %ebx -+ pop %ebp -+ ret -+ -+ -+// AES (Rijndael) Decryption Subroutine -+ -+ .align ALIGN32BYTES -+aes_decrypt: -+ push %ebp -+ mov ctx(%esp),%ebp // pointer to context -+ mov in_blk(%esp),%ecx -+ push %ebx -+ push %esi -+ push %edi -+ mov nrnd(%ebp),%edx // number of rounds -+ lea dkey+16(%ebp),%ebp // key pointer -+ -+// input four columns and xor in first round key -+ -+ mov (%ecx),%eax -+ mov 4(%ecx),%ebx -+ mov 8(%ecx),%esi -+ mov 12(%ecx),%edi -+ xor -16(%ebp),%eax -+ xor -12(%ebp),%ebx -+ xor -8(%ebp),%esi -+ xor -4(%ebp),%edi -+ -+ sub $8,%esp // space for register saves on stack -+ -+ sub $10,%edx -+ je aes_25 -+ add $32,%ebp -+ sub $2,%edx -+ je aes_23 -+ add $32,%ebp -+ -+ inv_rnd(aes_it_tab,-64) // 14 rounds for 256-bit key -+ inv_rnd(aes_it_tab,-48) -+aes_23: inv_rnd(aes_it_tab,-32) // 12 rounds for 192-bit key -+ inv_rnd(aes_it_tab,-16) -+aes_25: inv_rnd(aes_it_tab,0) // 10 rounds for 128-bit key -+ inv_rnd(aes_it_tab,16) -+ inv_rnd(aes_it_tab,32) -+ inv_rnd(aes_it_tab,48) -+ inv_rnd(aes_it_tab,64) -+ inv_rnd(aes_it_tab,80) -+ inv_rnd(aes_it_tab,96) -+ inv_rnd(aes_it_tab,112) -+ inv_rnd(aes_it_tab,128) -+ inv_rnd(aes_il_tab,144) // last round uses a different table -+ -+// move final values to the output array. -+ -+ mov out_blk+20(%esp),%ebp -+ add $8,%esp -+ mov %eax,(%ebp) -+ mov %ebx,4(%ebp) -+ mov %esi,8(%ebp) -+ mov %edi,12(%ebp) -+ pop %edi -+ pop %esi -+ pop %ebx -+ pop %ebp -+ ret -+ -+// AES (Rijndael) Key Schedule Subroutine -+ -+// input/output parameters -+ -+#define aes_cx 12 // AES context -+#define in_key 16 // key input array address -+#define key_ln 20 // key length, bytes (16,24,32) or bits (128,192,256) -+#define ed_flg 24 // 0=create both encr/decr keys, 1=create encr key only -+ -+// offsets for locals -+ -+#define cnt -4 -+#define kpf -8 -+#define slen 8 -+ -+// This macro performs a column mixing operation on an input 32-bit -+// word to give a 32-bit result. It uses each of the 4 bytes in the -+// the input column to index 4 different tables of 256 32-bit words -+// that are xored together to form the output value. -+ -+#define mix_col(p1) \ -+ movzbl %bl,%ecx ;\ -+ mov p1(,%ecx,4),%eax ;\ -+ movzbl %bh,%ecx ;\ -+ ror $16,%ebx ;\ -+ xor p1+tlen(,%ecx,4),%eax ;\ -+ movzbl %bl,%ecx ;\ -+ xor p1+2*tlen(,%ecx,4),%eax ;\ -+ movzbl %bh,%ecx ;\ -+ xor p1+3*tlen(,%ecx,4),%eax -+ -+// Key Schedule Macros -+ -+#define ksc4(p1) \ -+ rol $24,%ebx ;\ -+ mix_col(aes_fl_tab) ;\ -+ ror $8,%ebx ;\ -+ xor 4*p1+aes_rcon_tab,%eax ;\ -+ xor %eax,%esi ;\ -+ xor %esi,%ebp ;\ -+ mov %esi,16*p1(%edi) ;\ -+ mov %ebp,16*p1+4(%edi) ;\ -+ xor %ebp,%edx ;\ -+ xor %edx,%ebx ;\ -+ mov %edx,16*p1+8(%edi) ;\ -+ mov %ebx,16*p1+12(%edi) -+ -+#define ksc6(p1) \ -+ rol $24,%ebx ;\ -+ mix_col(aes_fl_tab) ;\ -+ ror $8,%ebx ;\ -+ xor 4*p1+aes_rcon_tab,%eax ;\ -+ xor 24*p1-24(%edi),%eax ;\ -+ mov %eax,24*p1(%edi) ;\ -+ xor 24*p1-20(%edi),%eax ;\ -+ mov %eax,24*p1+4(%edi) ;\ -+ xor %eax,%esi ;\ -+ xor %esi,%ebp ;\ -+ mov %esi,24*p1+8(%edi) ;\ -+ mov %ebp,24*p1+12(%edi) ;\ -+ xor %ebp,%edx ;\ -+ xor %edx,%ebx ;\ -+ mov %edx,24*p1+16(%edi) ;\ -+ mov %ebx,24*p1+20(%edi) -+ -+#define ksc8(p1) \ -+ rol $24,%ebx ;\ -+ mix_col(aes_fl_tab) ;\ -+ ror $8,%ebx ;\ -+ xor 4*p1+aes_rcon_tab,%eax ;\ -+ xor 32*p1-32(%edi),%eax ;\ -+ mov %eax,32*p1(%edi) ;\ -+ xor 32*p1-28(%edi),%eax ;\ -+ mov %eax,32*p1+4(%edi) ;\ -+ xor 32*p1-24(%edi),%eax ;\ -+ mov %eax,32*p1+8(%edi) ;\ -+ xor 32*p1-20(%edi),%eax ;\ -+ mov %eax,32*p1+12(%edi) ;\ -+ push %ebx ;\ -+ mov %eax,%ebx ;\ -+ mix_col(aes_fl_tab) ;\ -+ pop %ebx ;\ -+ xor %eax,%esi ;\ -+ xor %esi,%ebp ;\ -+ mov %esi,32*p1+16(%edi) ;\ -+ mov %ebp,32*p1+20(%edi) ;\ -+ xor %ebp,%edx ;\ -+ xor %edx,%ebx ;\ -+ mov %edx,32*p1+24(%edi) ;\ -+ mov %ebx,32*p1+28(%edi) -+ -+ .align ALIGN32BYTES -+aes_set_key: -+ pushfl -+ push %ebp -+ mov %esp,%ebp -+ sub $slen,%esp -+ push %ebx -+ push %esi -+ push %edi -+ -+ mov aes_cx(%ebp),%edx // edx -> AES context -+ -+ mov key_ln(%ebp),%ecx // key length -+ cmpl $128,%ecx -+ jb aes_30 -+ shr $3,%ecx -+aes_30: cmpl $32,%ecx -+ je aes_32 -+ cmpl $24,%ecx -+ je aes_32 -+ mov $16,%ecx -+aes_32: shr $2,%ecx -+ mov %ecx,nkey(%edx) -+ -+ lea 6(%ecx),%eax // 10/12/14 for 4/6/8 32-bit key length -+ mov %eax,nrnd(%edx) -+ -+ mov in_key(%ebp),%esi // key input array -+ lea ekey(%edx),%edi // key position in AES context -+ cld -+ push %ebp -+ mov %ecx,%eax // save key length in eax -+ rep ; movsl // words in the key schedule -+ mov -4(%esi),%ebx // put some values in registers -+ mov -8(%esi),%edx // to allow faster code -+ mov -12(%esi),%ebp -+ mov -16(%esi),%esi -+ -+ cmpl $4,%eax // jump on key size -+ je aes_36 -+ cmpl $6,%eax -+ je aes_35 -+ -+ ksc8(0) -+ ksc8(1) -+ ksc8(2) -+ ksc8(3) -+ ksc8(4) -+ ksc8(5) -+ ksc8(6) -+ jmp aes_37 -+aes_35: ksc6(0) -+ ksc6(1) -+ ksc6(2) -+ ksc6(3) -+ ksc6(4) -+ ksc6(5) -+ ksc6(6) -+ ksc6(7) -+ jmp aes_37 -+aes_36: ksc4(0) -+ ksc4(1) -+ ksc4(2) -+ ksc4(3) -+ ksc4(4) -+ ksc4(5) -+ ksc4(6) -+ ksc4(7) -+ ksc4(8) -+ ksc4(9) -+aes_37: pop %ebp -+ mov aes_cx(%ebp),%edx // edx -> AES context -+ cmpl $0,ed_flg(%ebp) -+ jne aes_39 -+ -+// compile decryption key schedule from encryption schedule - reverse -+// order and do mix_column operation on round keys except first and last -+ -+ mov nrnd(%edx),%eax // kt = cx->d_key + nc * cx->Nrnd -+ shl $2,%eax -+ lea dkey(%edx,%eax,4),%edi -+ lea ekey(%edx),%esi // kf = cx->e_key -+ -+ movsl // copy first round key (unmodified) -+ movsl -+ movsl -+ movsl -+ sub $32,%edi -+ movl $1,cnt(%ebp) -+aes_38: // do mix column on each column of -+ lodsl // each round key -+ mov %eax,%ebx -+ mix_col(aes_im_tab) -+ stosl -+ lodsl -+ mov %eax,%ebx -+ mix_col(aes_im_tab) -+ stosl -+ lodsl -+ mov %eax,%ebx -+ mix_col(aes_im_tab) -+ stosl -+ lodsl -+ mov %eax,%ebx -+ mix_col(aes_im_tab) -+ stosl -+ sub $32,%edi -+ -+ incl cnt(%ebp) -+ mov cnt(%ebp),%eax -+ cmp nrnd(%edx),%eax -+ jb aes_38 -+ -+ movsl // copy last round key (unmodified) -+ movsl -+ movsl -+ movsl -+aes_39: pop %edi -+ pop %esi -+ pop %ebx -+ mov %ebp,%esp -+ pop %ebp -+ popfl -+ ret -+ -+ -+// finite field multiplies by {02}, {04} and {08} -+ -+#define f2(x) ((x<<1)^(((x>>7)&1)*0x11b)) -+#define f4(x) ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b)) -+#define f8(x) ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b)) -+ -+// finite field multiplies required in table generation -+ -+#define f3(x) (f2(x) ^ x) -+#define f9(x) (f8(x) ^ x) -+#define fb(x) (f8(x) ^ f2(x) ^ x) -+#define fd(x) (f8(x) ^ f4(x) ^ x) -+#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) -+ -+// These defines generate the forward table entries -+ -+#define u0(x) ((f3(x) << 24) | (x << 16) | (x << 8) | f2(x)) -+#define u1(x) ((x << 24) | (x << 16) | (f2(x) << 8) | f3(x)) -+#define u2(x) ((x << 24) | (f2(x) << 16) | (f3(x) << 8) | x) -+#define u3(x) ((f2(x) << 24) | (f3(x) << 16) | (x << 8) | x) -+ -+// These defines generate the inverse table entries -+ -+#define v0(x) ((fb(x) << 24) | (fd(x) << 16) | (f9(x) << 8) | fe(x)) -+#define v1(x) ((fd(x) << 24) | (f9(x) << 16) | (fe(x) << 8) | fb(x)) -+#define v2(x) ((f9(x) << 24) | (fe(x) << 16) | (fb(x) << 8) | fd(x)) -+#define v3(x) ((fe(x) << 24) | (fb(x) << 16) | (fd(x) << 8) | f9(x)) -+ -+// These defines generate entries for the last round tables -+ -+#define w0(x) (x) -+#define w1(x) (x << 8) -+#define w2(x) (x << 16) -+#define w3(x) (x << 24) -+ -+// macro to generate inverse mix column tables (needed for the key schedule) -+ -+#define im_data0(p1) \ -+ .long p1(0x00),p1(0x01),p1(0x02),p1(0x03),p1(0x04),p1(0x05),p1(0x06),p1(0x07) ;\ -+ .long p1(0x08),p1(0x09),p1(0x0a),p1(0x0b),p1(0x0c),p1(0x0d),p1(0x0e),p1(0x0f) ;\ -+ .long p1(0x10),p1(0x11),p1(0x12),p1(0x13),p1(0x14),p1(0x15),p1(0x16),p1(0x17) ;\ -+ .long p1(0x18),p1(0x19),p1(0x1a),p1(0x1b),p1(0x1c),p1(0x1d),p1(0x1e),p1(0x1f) -+#define im_data1(p1) \ -+ .long p1(0x20),p1(0x21),p1(0x22),p1(0x23),p1(0x24),p1(0x25),p1(0x26),p1(0x27) ;\ -+ .long p1(0x28),p1(0x29),p1(0x2a),p1(0x2b),p1(0x2c),p1(0x2d),p1(0x2e),p1(0x2f) ;\ -+ .long p1(0x30),p1(0x31),p1(0x32),p1(0x33),p1(0x34),p1(0x35),p1(0x36),p1(0x37) ;\ -+ .long p1(0x38),p1(0x39),p1(0x3a),p1(0x3b),p1(0x3c),p1(0x3d),p1(0x3e),p1(0x3f) -+#define im_data2(p1) \ -+ .long p1(0x40),p1(0x41),p1(0x42),p1(0x43),p1(0x44),p1(0x45),p1(0x46),p1(0x47) ;\ -+ .long p1(0x48),p1(0x49),p1(0x4a),p1(0x4b),p1(0x4c),p1(0x4d),p1(0x4e),p1(0x4f) ;\ -+ .long p1(0x50),p1(0x51),p1(0x52),p1(0x53),p1(0x54),p1(0x55),p1(0x56),p1(0x57) ;\ -+ .long p1(0x58),p1(0x59),p1(0x5a),p1(0x5b),p1(0x5c),p1(0x5d),p1(0x5e),p1(0x5f) -+#define im_data3(p1) \ -+ .long p1(0x60),p1(0x61),p1(0x62),p1(0x63),p1(0x64),p1(0x65),p1(0x66),p1(0x67) ;\ -+ .long p1(0x68),p1(0x69),p1(0x6a),p1(0x6b),p1(0x6c),p1(0x6d),p1(0x6e),p1(0x6f) ;\ -+ .long p1(0x70),p1(0x71),p1(0x72),p1(0x73),p1(0x74),p1(0x75),p1(0x76),p1(0x77) ;\ -+ .long p1(0x78),p1(0x79),p1(0x7a),p1(0x7b),p1(0x7c),p1(0x7d),p1(0x7e),p1(0x7f) -+#define im_data4(p1) \ -+ .long p1(0x80),p1(0x81),p1(0x82),p1(0x83),p1(0x84),p1(0x85),p1(0x86),p1(0x87) ;\ -+ .long p1(0x88),p1(0x89),p1(0x8a),p1(0x8b),p1(0x8c),p1(0x8d),p1(0x8e),p1(0x8f) ;\ -+ .long p1(0x90),p1(0x91),p1(0x92),p1(0x93),p1(0x94),p1(0x95),p1(0x96),p1(0x97) ;\ -+ .long p1(0x98),p1(0x99),p1(0x9a),p1(0x9b),p1(0x9c),p1(0x9d),p1(0x9e),p1(0x9f) -+#define im_data5(p1) \ -+ .long p1(0xa0),p1(0xa1),p1(0xa2),p1(0xa3),p1(0xa4),p1(0xa5),p1(0xa6),p1(0xa7) ;\ -+ .long p1(0xa8),p1(0xa9),p1(0xaa),p1(0xab),p1(0xac),p1(0xad),p1(0xae),p1(0xaf) ;\ -+ .long p1(0xb0),p1(0xb1),p1(0xb2),p1(0xb3),p1(0xb4),p1(0xb5),p1(0xb6),p1(0xb7) ;\ -+ .long p1(0xb8),p1(0xb9),p1(0xba),p1(0xbb),p1(0xbc),p1(0xbd),p1(0xbe),p1(0xbf) -+#define im_data6(p1) \ -+ .long p1(0xc0),p1(0xc1),p1(0xc2),p1(0xc3),p1(0xc4),p1(0xc5),p1(0xc6),p1(0xc7) ;\ -+ .long p1(0xc8),p1(0xc9),p1(0xca),p1(0xcb),p1(0xcc),p1(0xcd),p1(0xce),p1(0xcf) ;\ -+ .long p1(0xd0),p1(0xd1),p1(0xd2),p1(0xd3),p1(0xd4),p1(0xd5),p1(0xd6),p1(0xd7) ;\ -+ .long p1(0xd8),p1(0xd9),p1(0xda),p1(0xdb),p1(0xdc),p1(0xdd),p1(0xde),p1(0xdf) -+#define im_data7(p1) \ -+ .long p1(0xe0),p1(0xe1),p1(0xe2),p1(0xe3),p1(0xe4),p1(0xe5),p1(0xe6),p1(0xe7) ;\ -+ .long p1(0xe8),p1(0xe9),p1(0xea),p1(0xeb),p1(0xec),p1(0xed),p1(0xee),p1(0xef) ;\ -+ .long p1(0xf0),p1(0xf1),p1(0xf2),p1(0xf3),p1(0xf4),p1(0xf5),p1(0xf6),p1(0xf7) ;\ -+ .long p1(0xf8),p1(0xf9),p1(0xfa),p1(0xfb),p1(0xfc),p1(0xfd),p1(0xfe),p1(0xff) -+ -+// S-box data - 256 entries -+ -+#define sb_data0(p1) \ -+ .long p1(0x63),p1(0x7c),p1(0x77),p1(0x7b),p1(0xf2),p1(0x6b),p1(0x6f),p1(0xc5) ;\ -+ .long p1(0x30),p1(0x01),p1(0x67),p1(0x2b),p1(0xfe),p1(0xd7),p1(0xab),p1(0x76) ;\ -+ .long p1(0xca),p1(0x82),p1(0xc9),p1(0x7d),p1(0xfa),p1(0x59),p1(0x47),p1(0xf0) ;\ -+ .long p1(0xad),p1(0xd4),p1(0xa2),p1(0xaf),p1(0x9c),p1(0xa4),p1(0x72),p1(0xc0) -+#define sb_data1(p1) \ -+ .long p1(0xb7),p1(0xfd),p1(0x93),p1(0x26),p1(0x36),p1(0x3f),p1(0xf7),p1(0xcc) ;\ -+ .long p1(0x34),p1(0xa5),p1(0xe5),p1(0xf1),p1(0x71),p1(0xd8),p1(0x31),p1(0x15) ;\ -+ .long p1(0x04),p1(0xc7),p1(0x23),p1(0xc3),p1(0x18),p1(0x96),p1(0x05),p1(0x9a) ;\ -+ .long p1(0x07),p1(0x12),p1(0x80),p1(0xe2),p1(0xeb),p1(0x27),p1(0xb2),p1(0x75) -+#define sb_data2(p1) \ -+ .long p1(0x09),p1(0x83),p1(0x2c),p1(0x1a),p1(0x1b),p1(0x6e),p1(0x5a),p1(0xa0) ;\ -+ .long p1(0x52),p1(0x3b),p1(0xd6),p1(0xb3),p1(0x29),p1(0xe3),p1(0x2f),p1(0x84) ;\ -+ .long p1(0x53),p1(0xd1),p1(0x00),p1(0xed),p1(0x20),p1(0xfc),p1(0xb1),p1(0x5b) ;\ -+ .long p1(0x6a),p1(0xcb),p1(0xbe),p1(0x39),p1(0x4a),p1(0x4c),p1(0x58),p1(0xcf) -+#define sb_data3(p1) \ -+ .long p1(0xd0),p1(0xef),p1(0xaa),p1(0xfb),p1(0x43),p1(0x4d),p1(0x33),p1(0x85) ;\ -+ .long p1(0x45),p1(0xf9),p1(0x02),p1(0x7f),p1(0x50),p1(0x3c),p1(0x9f),p1(0xa8) ;\ -+ .long p1(0x51),p1(0xa3),p1(0x40),p1(0x8f),p1(0x92),p1(0x9d),p1(0x38),p1(0xf5) ;\ -+ .long p1(0xbc),p1(0xb6),p1(0xda),p1(0x21),p1(0x10),p1(0xff),p1(0xf3),p1(0xd2) -+#define sb_data4(p1) \ -+ .long p1(0xcd),p1(0x0c),p1(0x13),p1(0xec),p1(0x5f),p1(0x97),p1(0x44),p1(0x17) ;\ -+ .long p1(0xc4),p1(0xa7),p1(0x7e),p1(0x3d),p1(0x64),p1(0x5d),p1(0x19),p1(0x73) ;\ -+ .long p1(0x60),p1(0x81),p1(0x4f),p1(0xdc),p1(0x22),p1(0x2a),p1(0x90),p1(0x88) ;\ -+ .long p1(0x46),p1(0xee),p1(0xb8),p1(0x14),p1(0xde),p1(0x5e),p1(0x0b),p1(0xdb) -+#define sb_data5(p1) \ -+ .long p1(0xe0),p1(0x32),p1(0x3a),p1(0x0a),p1(0x49),p1(0x06),p1(0x24),p1(0x5c) ;\ -+ .long p1(0xc2),p1(0xd3),p1(0xac),p1(0x62),p1(0x91),p1(0x95),p1(0xe4),p1(0x79) ;\ -+ .long p1(0xe7),p1(0xc8),p1(0x37),p1(0x6d),p1(0x8d),p1(0xd5),p1(0x4e),p1(0xa9) ;\ -+ .long p1(0x6c),p1(0x56),p1(0xf4),p1(0xea),p1(0x65),p1(0x7a),p1(0xae),p1(0x08) -+#define sb_data6(p1) \ -+ .long p1(0xba),p1(0x78),p1(0x25),p1(0x2e),p1(0x1c),p1(0xa6),p1(0xb4),p1(0xc6) ;\ -+ .long p1(0xe8),p1(0xdd),p1(0x74),p1(0x1f),p1(0x4b),p1(0xbd),p1(0x8b),p1(0x8a) ;\ -+ .long p1(0x70),p1(0x3e),p1(0xb5),p1(0x66),p1(0x48),p1(0x03),p1(0xf6),p1(0x0e) ;\ -+ .long p1(0x61),p1(0x35),p1(0x57),p1(0xb9),p1(0x86),p1(0xc1),p1(0x1d),p1(0x9e) -+#define sb_data7(p1) \ -+ .long p1(0xe1),p1(0xf8),p1(0x98),p1(0x11),p1(0x69),p1(0xd9),p1(0x8e),p1(0x94) ;\ -+ .long p1(0x9b),p1(0x1e),p1(0x87),p1(0xe9),p1(0xce),p1(0x55),p1(0x28),p1(0xdf) ;\ -+ .long p1(0x8c),p1(0xa1),p1(0x89),p1(0x0d),p1(0xbf),p1(0xe6),p1(0x42),p1(0x68) ;\ -+ .long p1(0x41),p1(0x99),p1(0x2d),p1(0x0f),p1(0xb0),p1(0x54),p1(0xbb),p1(0x16) -+ -+// Inverse S-box data - 256 entries -+ -+#define ib_data0(p1) \ -+ .long p1(0x52),p1(0x09),p1(0x6a),p1(0xd5),p1(0x30),p1(0x36),p1(0xa5),p1(0x38) ;\ -+ .long p1(0xbf),p1(0x40),p1(0xa3),p1(0x9e),p1(0x81),p1(0xf3),p1(0xd7),p1(0xfb) ;\ -+ .long p1(0x7c),p1(0xe3),p1(0x39),p1(0x82),p1(0x9b),p1(0x2f),p1(0xff),p1(0x87) ;\ -+ .long p1(0x34),p1(0x8e),p1(0x43),p1(0x44),p1(0xc4),p1(0xde),p1(0xe9),p1(0xcb) -+#define ib_data1(p1) \ -+ .long p1(0x54),p1(0x7b),p1(0x94),p1(0x32),p1(0xa6),p1(0xc2),p1(0x23),p1(0x3d) ;\ -+ .long p1(0xee),p1(0x4c),p1(0x95),p1(0x0b),p1(0x42),p1(0xfa),p1(0xc3),p1(0x4e) ;\ -+ .long p1(0x08),p1(0x2e),p1(0xa1),p1(0x66),p1(0x28),p1(0xd9),p1(0x24),p1(0xb2) ;\ -+ .long p1(0x76),p1(0x5b),p1(0xa2),p1(0x49),p1(0x6d),p1(0x8b),p1(0xd1),p1(0x25) -+#define ib_data2(p1) \ -+ .long p1(0x72),p1(0xf8),p1(0xf6),p1(0x64),p1(0x86),p1(0x68),p1(0x98),p1(0x16) ;\ -+ .long p1(0xd4),p1(0xa4),p1(0x5c),p1(0xcc),p1(0x5d),p1(0x65),p1(0xb6),p1(0x92) ;\ -+ .long p1(0x6c),p1(0x70),p1(0x48),p1(0x50),p1(0xfd),p1(0xed),p1(0xb9),p1(0xda) ;\ -+ .long p1(0x5e),p1(0x15),p1(0x46),p1(0x57),p1(0xa7),p1(0x8d),p1(0x9d),p1(0x84) -+#define ib_data3(p1) \ -+ .long p1(0x90),p1(0xd8),p1(0xab),p1(0x00),p1(0x8c),p1(0xbc),p1(0xd3),p1(0x0a) ;\ -+ .long p1(0xf7),p1(0xe4),p1(0x58),p1(0x05),p1(0xb8),p1(0xb3),p1(0x45),p1(0x06) ;\ -+ .long p1(0xd0),p1(0x2c),p1(0x1e),p1(0x8f),p1(0xca),p1(0x3f),p1(0x0f),p1(0x02) ;\ -+ .long p1(0xc1),p1(0xaf),p1(0xbd),p1(0x03),p1(0x01),p1(0x13),p1(0x8a),p1(0x6b) -+#define ib_data4(p1) \ -+ .long p1(0x3a),p1(0x91),p1(0x11),p1(0x41),p1(0x4f),p1(0x67),p1(0xdc),p1(0xea) ;\ -+ .long p1(0x97),p1(0xf2),p1(0xcf),p1(0xce),p1(0xf0),p1(0xb4),p1(0xe6),p1(0x73) ;\ -+ .long p1(0x96),p1(0xac),p1(0x74),p1(0x22),p1(0xe7),p1(0xad),p1(0x35),p1(0x85) ;\ -+ .long p1(0xe2),p1(0xf9),p1(0x37),p1(0xe8),p1(0x1c),p1(0x75),p1(0xdf),p1(0x6e) -+#define ib_data5(p1) \ -+ .long p1(0x47),p1(0xf1),p1(0x1a),p1(0x71),p1(0x1d),p1(0x29),p1(0xc5),p1(0x89) ;\ -+ .long p1(0x6f),p1(0xb7),p1(0x62),p1(0x0e),p1(0xaa),p1(0x18),p1(0xbe),p1(0x1b) ;\ -+ .long p1(0xfc),p1(0x56),p1(0x3e),p1(0x4b),p1(0xc6),p1(0xd2),p1(0x79),p1(0x20) ;\ -+ .long p1(0x9a),p1(0xdb),p1(0xc0),p1(0xfe),p1(0x78),p1(0xcd),p1(0x5a),p1(0xf4) -+#define ib_data6(p1) \ -+ .long p1(0x1f),p1(0xdd),p1(0xa8),p1(0x33),p1(0x88),p1(0x07),p1(0xc7),p1(0x31) ;\ -+ .long p1(0xb1),p1(0x12),p1(0x10),p1(0x59),p1(0x27),p1(0x80),p1(0xec),p1(0x5f) ;\ -+ .long p1(0x60),p1(0x51),p1(0x7f),p1(0xa9),p1(0x19),p1(0xb5),p1(0x4a),p1(0x0d) ;\ -+ .long p1(0x2d),p1(0xe5),p1(0x7a),p1(0x9f),p1(0x93),p1(0xc9),p1(0x9c),p1(0xef) -+#define ib_data7(p1) \ -+ .long p1(0xa0),p1(0xe0),p1(0x3b),p1(0x4d),p1(0xae),p1(0x2a),p1(0xf5),p1(0xb0) ;\ -+ .long p1(0xc8),p1(0xeb),p1(0xbb),p1(0x3c),p1(0x83),p1(0x53),p1(0x99),p1(0x61) ;\ -+ .long p1(0x17),p1(0x2b),p1(0x04),p1(0x7e),p1(0xba),p1(0x77),p1(0xd6),p1(0x26) ;\ -+ .long p1(0xe1),p1(0x69),p1(0x14),p1(0x63),p1(0x55),p1(0x21),p1(0x0c),p1(0x7d) -+ -+// The rcon_table (needed for the key schedule) -+// -+// Here is original Dr Brian Gladman's source code: -+// _rcon_tab: -+// %assign x 1 -+// %rep 29 -+// dd x -+// %assign x f2(x) -+// %endrep -+// -+// Here is precomputed output (it's more portable this way): -+ -+ .align ALIGN32BYTES -+aes_rcon_tab: -+ .long 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 -+ .long 0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f -+ .long 0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4 -+ .long 0xb3,0x7d,0xfa,0xef,0xc5 -+ -+// The forward xor tables -+ -+ .align ALIGN32BYTES -+aes_ft_tab: -+ sb_data0(u0) -+ sb_data1(u0) -+ sb_data2(u0) -+ sb_data3(u0) -+ sb_data4(u0) -+ sb_data5(u0) -+ sb_data6(u0) -+ sb_data7(u0) -+ -+ sb_data0(u1) -+ sb_data1(u1) -+ sb_data2(u1) -+ sb_data3(u1) -+ sb_data4(u1) -+ sb_data5(u1) -+ sb_data6(u1) -+ sb_data7(u1) -+ -+ sb_data0(u2) -+ sb_data1(u2) -+ sb_data2(u2) -+ sb_data3(u2) -+ sb_data4(u2) -+ sb_data5(u2) -+ sb_data6(u2) -+ sb_data7(u2) -+ -+ sb_data0(u3) -+ sb_data1(u3) -+ sb_data2(u3) -+ sb_data3(u3) -+ sb_data4(u3) -+ sb_data5(u3) -+ sb_data6(u3) -+ sb_data7(u3) -+ -+ .align ALIGN32BYTES -+aes_fl_tab: -+ sb_data0(w0) -+ sb_data1(w0) -+ sb_data2(w0) -+ sb_data3(w0) -+ sb_data4(w0) -+ sb_data5(w0) -+ sb_data6(w0) -+ sb_data7(w0) -+ -+ sb_data0(w1) -+ sb_data1(w1) -+ sb_data2(w1) -+ sb_data3(w1) -+ sb_data4(w1) -+ sb_data5(w1) -+ sb_data6(w1) -+ sb_data7(w1) -+ -+ sb_data0(w2) -+ sb_data1(w2) -+ sb_data2(w2) -+ sb_data3(w2) -+ sb_data4(w2) -+ sb_data5(w2) -+ sb_data6(w2) -+ sb_data7(w2) -+ -+ sb_data0(w3) -+ sb_data1(w3) -+ sb_data2(w3) -+ sb_data3(w3) -+ sb_data4(w3) -+ sb_data5(w3) -+ sb_data6(w3) -+ sb_data7(w3) -+ -+// The inverse xor tables -+ -+ .align ALIGN32BYTES -+aes_it_tab: -+ ib_data0(v0) -+ ib_data1(v0) -+ ib_data2(v0) -+ ib_data3(v0) -+ ib_data4(v0) -+ ib_data5(v0) -+ ib_data6(v0) -+ ib_data7(v0) -+ -+ ib_data0(v1) -+ ib_data1(v1) -+ ib_data2(v1) -+ ib_data3(v1) -+ ib_data4(v1) -+ ib_data5(v1) -+ ib_data6(v1) -+ ib_data7(v1) -+ -+ ib_data0(v2) -+ ib_data1(v2) -+ ib_data2(v2) -+ ib_data3(v2) -+ ib_data4(v2) -+ ib_data5(v2) -+ ib_data6(v2) -+ ib_data7(v2) -+ -+ ib_data0(v3) -+ ib_data1(v3) -+ ib_data2(v3) -+ ib_data3(v3) -+ ib_data4(v3) -+ ib_data5(v3) -+ ib_data6(v3) -+ ib_data7(v3) -+ -+ .align ALIGN32BYTES -+aes_il_tab: -+ ib_data0(w0) -+ ib_data1(w0) -+ ib_data2(w0) -+ ib_data3(w0) -+ ib_data4(w0) -+ ib_data5(w0) -+ ib_data6(w0) -+ ib_data7(w0) -+ -+ ib_data0(w1) -+ ib_data1(w1) -+ ib_data2(w1) -+ ib_data3(w1) -+ ib_data4(w1) -+ ib_data5(w1) -+ ib_data6(w1) -+ ib_data7(w1) -+ -+ ib_data0(w2) -+ ib_data1(w2) -+ ib_data2(w2) -+ ib_data3(w2) -+ ib_data4(w2) -+ ib_data5(w2) -+ ib_data6(w2) -+ ib_data7(w2) -+ -+ ib_data0(w3) -+ ib_data1(w3) -+ ib_data2(w3) -+ ib_data3(w3) -+ ib_data4(w3) -+ ib_data5(w3) -+ ib_data6(w3) -+ ib_data7(w3) -+ -+// The inverse mix column tables -+ -+ .align ALIGN32BYTES -+aes_im_tab: -+ im_data0(v0) -+ im_data1(v0) -+ im_data2(v0) -+ im_data3(v0) -+ im_data4(v0) -+ im_data5(v0) -+ im_data6(v0) -+ im_data7(v0) -+ -+ im_data0(v1) -+ im_data1(v1) -+ im_data2(v1) -+ im_data3(v1) -+ im_data4(v1) -+ im_data5(v1) -+ im_data6(v1) -+ im_data7(v1) -+ -+ im_data0(v2) -+ im_data1(v2) -+ im_data2(v2) -+ im_data3(v2) -+ im_data4(v2) -+ im_data5(v2) -+ im_data6(v2) -+ im_data7(v2) -+ -+ im_data0(v3) -+ im_data1(v3) -+ im_data2(v3) -+ im_data3(v3) -+ im_data4(v3) -+ im_data5(v3) -+ im_data6(v3) -+ im_data7(v3) ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/aes/aes.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1415 @@ -+// I retain copyright in this code but I encourage its free use provided -+// that I don't carry any responsibility for the results. I am especially -+// happy to see it used in free and open source software. If you do use -+// it I would appreciate an acknowledgement of its origin in the code or -+// the product that results and I would also appreciate knowing a little -+// about the use to which it is being put. I am grateful to Frank Yellin -+// for some ideas that are used in this implementation. -+// -+// Dr B. R. Gladman 6th April 2001. -+// -+// This is an implementation of the AES encryption algorithm (Rijndael) -+// designed by Joan Daemen and Vincent Rijmen. This version is designed -+// to provide both fixed and dynamic block and key lengths and can also -+// run with either big or little endian internal byte order (see aes.h). -+// It inputs block and key lengths in bytes with the legal values being -+// 16, 24 and 32. -+ -+/* -+ * Modified by Jari Ruusu, May 1 2001 -+ * - Fixed some compile warnings, code was ok but gcc warned anyway. -+ * - Changed basic types: byte -> unsigned char, word -> u_int32_t -+ * - Major name space cleanup: Names visible to outside now begin -+ * with "aes_" or "AES_". A lot of stuff moved from aes.h to aes.c -+ * - Removed C++ and DLL support as part of name space cleanup. -+ * - Eliminated unnecessary recomputation of tables. (actual bug fix) -+ * - Merged precomputed constant tables to aes.c file. -+ * - Removed data alignment restrictions for portability reasons. -+ * - Made block and key lengths accept bit count (128/192/256) -+ * as well byte count (16/24/32). -+ * - Removed all error checks. This change also eliminated the need -+ * to preinitialize the context struct to zero. -+ * - Removed some totally unused constants. -+ */ -+ -+#include "crypto/aes.h" -+ -+// CONFIGURATION OPTIONS (see also aes.h) -+// -+// 1. Define UNROLL for full loop unrolling in encryption and decryption. -+// 2. Define PARTIAL_UNROLL to unroll two loops in encryption and decryption. -+// 3. Define FIXED_TABLES for compiled rather than dynamic tables. -+// 4. Define FF_TABLES to use tables for field multiplies and inverses. -+// Do not enable this without understanding stack space requirements. -+// 5. Define ARRAYS to use arrays to hold the local state block. If this -+// is not defined, individually declared 32-bit words are used. -+// 6. Define FAST_VARIABLE if a high speed variable block implementation -+// is needed (essentially three separate fixed block size code sequences) -+// 7. Define either ONE_TABLE or FOUR_TABLES for a fast table driven -+// version using 1 table (2 kbytes of table space) or 4 tables (8 -+// kbytes of table space) for higher speed. -+// 8. Define either ONE_LR_TABLE or FOUR_LR_TABLES for a further speed -+// increase by using tables for the last rounds but with more table -+// space (2 or 8 kbytes extra). -+// 9. If neither ONE_TABLE nor FOUR_TABLES is defined, a compact but -+// slower version is provided. -+// 10. If fast decryption key scheduling is needed define ONE_IM_TABLE -+// or FOUR_IM_TABLES for higher speed (2 or 8 kbytes extra). -+ -+#define UNROLL -+//#define PARTIAL_UNROLL -+ -+#define FIXED_TABLES -+//#define FF_TABLES -+//#define ARRAYS -+#define FAST_VARIABLE -+ -+//#define ONE_TABLE -+#define FOUR_TABLES -+ -+//#define ONE_LR_TABLE -+#define FOUR_LR_TABLES -+ -+//#define ONE_IM_TABLE -+#define FOUR_IM_TABLES -+ -+#if defined(UNROLL) && defined (PARTIAL_UNROLL) -+#error both UNROLL and PARTIAL_UNROLL are defined -+#endif -+ -+#if defined(ONE_TABLE) && defined (FOUR_TABLES) -+#error both ONE_TABLE and FOUR_TABLES are defined -+#endif -+ -+#if defined(ONE_LR_TABLE) && defined (FOUR_LR_TABLES) -+#error both ONE_LR_TABLE and FOUR_LR_TABLES are defined -+#endif -+ -+#if defined(ONE_IM_TABLE) && defined (FOUR_IM_TABLES) -+#error both ONE_IM_TABLE and FOUR_IM_TABLES are defined -+#endif -+ -+#if defined(AES_BLOCK_SIZE) && AES_BLOCK_SIZE != 16 && AES_BLOCK_SIZE != 24 && AES_BLOCK_SIZE != 32 -+#error an illegal block size has been specified -+#endif -+ -+// upr(x,n): rotates bytes within words by n positions, moving bytes -+// to higher index positions with wrap around into low positions -+// ups(x,n): moves bytes by n positions to higher index positions in -+// words but without wrap around -+// bval(x,n): extracts a byte from a word -+ -+#define upr(x,n) (((x) << 8 * (n)) | ((x) >> (32 - 8 * (n)))) -+#define ups(x,n) ((x) << 8 * (n)) -+#define bval(x,n) ((unsigned char)((x) >> 8 * (n))) -+#define bytes2word(b0, b1, b2, b3) \ -+ ((u_int32_t)(b3) << 24 | (u_int32_t)(b2) << 16 | (u_int32_t)(b1) << 8 | (b0)) -+ -+ -+/* little endian processor without data alignment restrictions: AES_LE_OK */ -+/* original code: i386 */ -+#if defined(i386) || defined(_I386) || defined(__i386__) || defined(__i386) -+#define AES_LE_OK 1 -+/* added (tested): alpha --jjo */ -+#elif defined(__alpha__)|| defined (__alpha) -+#define AES_LE_OK 1 -+/* added (tested): ia64 --jjo */ -+#elif defined(__ia64__)|| defined (__ia64) -+#define AES_LE_OK 1 -+#endif -+ -+#ifdef AES_LE_OK -+/* little endian processor without data alignment restrictions */ -+#define word_in(x) *(u_int32_t*)(x) -+#define const_word_in(x) *(const u_int32_t*)(x) -+#define word_out(x,v) *(u_int32_t*)(x) = (v) -+#define const_word_out(x,v) *(const u_int32_t*)(x) = (v) -+#else -+/* slower but generic big endian or with data alignment restrictions */ -+/* some additional "const" touches to stop "gcc -Wcast-qual" complains --jjo */ -+#define word_in(x) ((u_int32_t)(((unsigned char *)(x))[0])|((u_int32_t)(((unsigned char *)(x))[1])<<8)|((u_int32_t)(((unsigned char *)(x))[2])<<16)|((u_int32_t)(((unsigned char *)(x))[3])<<24)) -+#define const_word_in(x) ((const u_int32_t)(((const unsigned char *)(x))[0])|((const u_int32_t)(((const unsigned char *)(x))[1])<<8)|((const u_int32_t)(((const unsigned char *)(x))[2])<<16)|((const u_int32_t)(((const unsigned char *)(x))[3])<<24)) -+#define word_out(x,v) ((unsigned char *)(x))[0]=(v),((unsigned char *)(x))[1]=((v)>>8),((unsigned char *)(x))[2]=((v)>>16),((unsigned char *)(x))[3]=((v)>>24) -+#define const_word_out(x,v) ((const unsigned char *)(x))[0]=(v),((const unsigned char *)(x))[1]=((v)>>8),((const unsigned char *)(x))[2]=((v)>>16),((const unsigned char *)(x))[3]=((v)>>24) -+#endif -+ -+// Disable at least some poor combinations of options -+ -+#if !defined(ONE_TABLE) && !defined(FOUR_TABLES) -+#define FIXED_TABLES -+#undef UNROLL -+#undef ONE_LR_TABLE -+#undef FOUR_LR_TABLES -+#undef ONE_IM_TABLE -+#undef FOUR_IM_TABLES -+#elif !defined(FOUR_TABLES) -+#ifdef FOUR_LR_TABLES -+#undef FOUR_LR_TABLES -+#define ONE_LR_TABLE -+#endif -+#ifdef FOUR_IM_TABLES -+#undef FOUR_IM_TABLES -+#define ONE_IM_TABLE -+#endif -+#elif !defined(AES_BLOCK_SIZE) -+#if defined(UNROLL) -+#define PARTIAL_UNROLL -+#undef UNROLL -+#endif -+#endif -+ -+// the finite field modular polynomial and elements -+ -+#define ff_poly 0x011b -+#define ff_hi 0x80 -+ -+// multiply four bytes in GF(2^8) by 'x' {02} in parallel -+ -+#define m1 0x80808080 -+#define m2 0x7f7f7f7f -+#define m3 0x0000001b -+#define FFmulX(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * m3)) -+ -+// The following defines provide alternative definitions of FFmulX that might -+// give improved performance if a fast 32-bit multiply is not available. Note -+// that a temporary variable u needs to be defined where FFmulX is used. -+ -+// #define FFmulX(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) -+// #define m4 0x1b1b1b1b -+// #define FFmulX(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) -+ -+// perform column mix operation on four bytes in parallel -+ -+#define fwd_mcol(x) (f2 = FFmulX(x), f2 ^ upr(x ^ f2,3) ^ upr(x,2) ^ upr(x,1)) -+ -+#if defined(FIXED_TABLES) -+ -+// the S-Box table -+ -+static const unsigned char s_box[256] = -+{ -+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, -+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, -+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, -+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, -+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, -+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, -+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, -+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, -+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, -+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, -+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, -+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, -+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, -+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, -+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, -+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, -+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, -+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, -+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, -+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, -+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, -+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, -+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, -+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, -+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, -+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, -+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, -+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, -+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, -+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, -+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, -+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 -+}; -+ -+// the inverse S-Box table -+ -+static const unsigned char inv_s_box[256] = -+{ -+ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, -+ 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, -+ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, -+ 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, -+ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, -+ 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, -+ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, -+ 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, -+ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, -+ 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, -+ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, -+ 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, -+ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, -+ 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, -+ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, -+ 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, -+ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, -+ 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, -+ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, -+ 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, -+ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, -+ 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, -+ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, -+ 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, -+ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, -+ 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, -+ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, -+ 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, -+ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, -+ 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, -+ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, -+ 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d -+}; -+ -+#define w0(p) 0x000000##p -+ -+// Number of elements required in this table for different -+// block and key lengths is: -+// -+// Nk = 4 6 8 -+// ---------- -+// Nb = 4 | 10 8 7 -+// 6 | 19 12 11 -+// 8 | 29 19 14 -+// -+// this table can be a table of bytes if the key schedule -+// code is adjusted accordingly -+ -+static const u_int32_t rcon_tab[29] = -+{ -+ w0(01), w0(02), w0(04), w0(08), -+ w0(10), w0(20), w0(40), w0(80), -+ w0(1b), w0(36), w0(6c), w0(d8), -+ w0(ab), w0(4d), w0(9a), w0(2f), -+ w0(5e), w0(bc), w0(63), w0(c6), -+ w0(97), w0(35), w0(6a), w0(d4), -+ w0(b3), w0(7d), w0(fa), w0(ef), -+ w0(c5) -+}; -+ -+#undef w0 -+ -+#define r0(p,q,r,s) 0x##p##q##r##s -+#define r1(p,q,r,s) 0x##q##r##s##p -+#define r2(p,q,r,s) 0x##r##s##p##q -+#define r3(p,q,r,s) 0x##s##p##q##r -+#define w0(p) 0x000000##p -+#define w1(p) 0x0000##p##00 -+#define w2(p) 0x00##p##0000 -+#define w3(p) 0x##p##000000 -+ -+#if defined(FIXED_TABLES) && (defined(ONE_TABLE) || defined(FOUR_TABLES)) -+ -+// data for forward tables (other than last round) -+ -+#define f_table \ -+ r(a5,63,63,c6), r(84,7c,7c,f8), r(99,77,77,ee), r(8d,7b,7b,f6),\ -+ r(0d,f2,f2,ff), r(bd,6b,6b,d6), r(b1,6f,6f,de), r(54,c5,c5,91),\ -+ r(50,30,30,60), r(03,01,01,02), r(a9,67,67,ce), r(7d,2b,2b,56),\ -+ r(19,fe,fe,e7), r(62,d7,d7,b5), r(e6,ab,ab,4d), r(9a,76,76,ec),\ -+ r(45,ca,ca,8f), r(9d,82,82,1f), r(40,c9,c9,89), r(87,7d,7d,fa),\ -+ r(15,fa,fa,ef), r(eb,59,59,b2), r(c9,47,47,8e), r(0b,f0,f0,fb),\ -+ r(ec,ad,ad,41), r(67,d4,d4,b3), r(fd,a2,a2,5f), r(ea,af,af,45),\ -+ r(bf,9c,9c,23), r(f7,a4,a4,53), r(96,72,72,e4), r(5b,c0,c0,9b),\ -+ r(c2,b7,b7,75), r(1c,fd,fd,e1), r(ae,93,93,3d), r(6a,26,26,4c),\ -+ r(5a,36,36,6c), r(41,3f,3f,7e), r(02,f7,f7,f5), r(4f,cc,cc,83),\ -+ r(5c,34,34,68), r(f4,a5,a5,51), r(34,e5,e5,d1), r(08,f1,f1,f9),\ -+ r(93,71,71,e2), r(73,d8,d8,ab), r(53,31,31,62), r(3f,15,15,2a),\ -+ r(0c,04,04,08), r(52,c7,c7,95), r(65,23,23,46), r(5e,c3,c3,9d),\ -+ r(28,18,18,30), r(a1,96,96,37), r(0f,05,05,0a), r(b5,9a,9a,2f),\ -+ r(09,07,07,0e), r(36,12,12,24), r(9b,80,80,1b), r(3d,e2,e2,df),\ -+ r(26,eb,eb,cd), r(69,27,27,4e), r(cd,b2,b2,7f), r(9f,75,75,ea),\ -+ r(1b,09,09,12), r(9e,83,83,1d), r(74,2c,2c,58), r(2e,1a,1a,34),\ -+ r(2d,1b,1b,36), r(b2,6e,6e,dc), r(ee,5a,5a,b4), r(fb,a0,a0,5b),\ -+ r(f6,52,52,a4), r(4d,3b,3b,76), r(61,d6,d6,b7), r(ce,b3,b3,7d),\ -+ r(7b,29,29,52), r(3e,e3,e3,dd), r(71,2f,2f,5e), r(97,84,84,13),\ -+ r(f5,53,53,a6), r(68,d1,d1,b9), r(00,00,00,00), r(2c,ed,ed,c1),\ -+ r(60,20,20,40), r(1f,fc,fc,e3), r(c8,b1,b1,79), r(ed,5b,5b,b6),\ -+ r(be,6a,6a,d4), r(46,cb,cb,8d), r(d9,be,be,67), r(4b,39,39,72),\ -+ r(de,4a,4a,94), r(d4,4c,4c,98), r(e8,58,58,b0), r(4a,cf,cf,85),\ -+ r(6b,d0,d0,bb), r(2a,ef,ef,c5), r(e5,aa,aa,4f), r(16,fb,fb,ed),\ -+ r(c5,43,43,86), r(d7,4d,4d,9a), r(55,33,33,66), r(94,85,85,11),\ -+ r(cf,45,45,8a), r(10,f9,f9,e9), r(06,02,02,04), r(81,7f,7f,fe),\ -+ r(f0,50,50,a0), r(44,3c,3c,78), r(ba,9f,9f,25), r(e3,a8,a8,4b),\ -+ r(f3,51,51,a2), r(fe,a3,a3,5d), r(c0,40,40,80), r(8a,8f,8f,05),\ -+ r(ad,92,92,3f), r(bc,9d,9d,21), r(48,38,38,70), r(04,f5,f5,f1),\ -+ r(df,bc,bc,63), r(c1,b6,b6,77), r(75,da,da,af), r(63,21,21,42),\ -+ r(30,10,10,20), r(1a,ff,ff,e5), r(0e,f3,f3,fd), r(6d,d2,d2,bf),\ -+ r(4c,cd,cd,81), r(14,0c,0c,18), r(35,13,13,26), r(2f,ec,ec,c3),\ -+ r(e1,5f,5f,be), r(a2,97,97,35), r(cc,44,44,88), r(39,17,17,2e),\ -+ r(57,c4,c4,93), r(f2,a7,a7,55), r(82,7e,7e,fc), r(47,3d,3d,7a),\ -+ r(ac,64,64,c8), r(e7,5d,5d,ba), r(2b,19,19,32), r(95,73,73,e6),\ -+ r(a0,60,60,c0), r(98,81,81,19), r(d1,4f,4f,9e), r(7f,dc,dc,a3),\ -+ r(66,22,22,44), r(7e,2a,2a,54), r(ab,90,90,3b), r(83,88,88,0b),\ -+ r(ca,46,46,8c), r(29,ee,ee,c7), r(d3,b8,b8,6b), r(3c,14,14,28),\ -+ r(79,de,de,a7), r(e2,5e,5e,bc), r(1d,0b,0b,16), r(76,db,db,ad),\ -+ r(3b,e0,e0,db), r(56,32,32,64), r(4e,3a,3a,74), r(1e,0a,0a,14),\ -+ r(db,49,49,92), r(0a,06,06,0c), r(6c,24,24,48), r(e4,5c,5c,b8),\ -+ r(5d,c2,c2,9f), r(6e,d3,d3,bd), r(ef,ac,ac,43), r(a6,62,62,c4),\ -+ r(a8,91,91,39), r(a4,95,95,31), r(37,e4,e4,d3), r(8b,79,79,f2),\ -+ r(32,e7,e7,d5), r(43,c8,c8,8b), r(59,37,37,6e), r(b7,6d,6d,da),\ -+ r(8c,8d,8d,01), r(64,d5,d5,b1), r(d2,4e,4e,9c), r(e0,a9,a9,49),\ -+ r(b4,6c,6c,d8), r(fa,56,56,ac), r(07,f4,f4,f3), r(25,ea,ea,cf),\ -+ r(af,65,65,ca), r(8e,7a,7a,f4), r(e9,ae,ae,47), r(18,08,08,10),\ -+ r(d5,ba,ba,6f), r(88,78,78,f0), r(6f,25,25,4a), r(72,2e,2e,5c),\ -+ r(24,1c,1c,38), r(f1,a6,a6,57), r(c7,b4,b4,73), r(51,c6,c6,97),\ -+ r(23,e8,e8,cb), r(7c,dd,dd,a1), r(9c,74,74,e8), r(21,1f,1f,3e),\ -+ r(dd,4b,4b,96), r(dc,bd,bd,61), r(86,8b,8b,0d), r(85,8a,8a,0f),\ -+ r(90,70,70,e0), r(42,3e,3e,7c), r(c4,b5,b5,71), r(aa,66,66,cc),\ -+ r(d8,48,48,90), r(05,03,03,06), r(01,f6,f6,f7), r(12,0e,0e,1c),\ -+ r(a3,61,61,c2), r(5f,35,35,6a), r(f9,57,57,ae), r(d0,b9,b9,69),\ -+ r(91,86,86,17), r(58,c1,c1,99), r(27,1d,1d,3a), r(b9,9e,9e,27),\ -+ r(38,e1,e1,d9), r(13,f8,f8,eb), r(b3,98,98,2b), r(33,11,11,22),\ -+ r(bb,69,69,d2), r(70,d9,d9,a9), r(89,8e,8e,07), r(a7,94,94,33),\ -+ r(b6,9b,9b,2d), r(22,1e,1e,3c), r(92,87,87,15), r(20,e9,e9,c9),\ -+ r(49,ce,ce,87), r(ff,55,55,aa), r(78,28,28,50), r(7a,df,df,a5),\ -+ r(8f,8c,8c,03), r(f8,a1,a1,59), r(80,89,89,09), r(17,0d,0d,1a),\ -+ r(da,bf,bf,65), r(31,e6,e6,d7), r(c6,42,42,84), r(b8,68,68,d0),\ -+ r(c3,41,41,82), r(b0,99,99,29), r(77,2d,2d,5a), r(11,0f,0f,1e),\ -+ r(cb,b0,b0,7b), r(fc,54,54,a8), r(d6,bb,bb,6d), r(3a,16,16,2c) -+ -+// data for inverse tables (other than last round) -+ -+#define i_table \ -+ r(50,a7,f4,51), r(53,65,41,7e), r(c3,a4,17,1a), r(96,5e,27,3a),\ -+ r(cb,6b,ab,3b), r(f1,45,9d,1f), r(ab,58,fa,ac), r(93,03,e3,4b),\ -+ r(55,fa,30,20), r(f6,6d,76,ad), r(91,76,cc,88), r(25,4c,02,f5),\ -+ r(fc,d7,e5,4f), r(d7,cb,2a,c5), r(80,44,35,26), r(8f,a3,62,b5),\ -+ r(49,5a,b1,de), r(67,1b,ba,25), r(98,0e,ea,45), r(e1,c0,fe,5d),\ -+ r(02,75,2f,c3), r(12,f0,4c,81), r(a3,97,46,8d), r(c6,f9,d3,6b),\ -+ r(e7,5f,8f,03), r(95,9c,92,15), r(eb,7a,6d,bf), r(da,59,52,95),\ -+ r(2d,83,be,d4), r(d3,21,74,58), r(29,69,e0,49), r(44,c8,c9,8e),\ -+ r(6a,89,c2,75), r(78,79,8e,f4), r(6b,3e,58,99), r(dd,71,b9,27),\ -+ r(b6,4f,e1,be), r(17,ad,88,f0), r(66,ac,20,c9), r(b4,3a,ce,7d),\ -+ r(18,4a,df,63), r(82,31,1a,e5), r(60,33,51,97), r(45,7f,53,62),\ -+ r(e0,77,64,b1), r(84,ae,6b,bb), r(1c,a0,81,fe), r(94,2b,08,f9),\ -+ r(58,68,48,70), r(19,fd,45,8f), r(87,6c,de,94), r(b7,f8,7b,52),\ -+ r(23,d3,73,ab), r(e2,02,4b,72), r(57,8f,1f,e3), r(2a,ab,55,66),\ -+ r(07,28,eb,b2), r(03,c2,b5,2f), r(9a,7b,c5,86), r(a5,08,37,d3),\ -+ r(f2,87,28,30), r(b2,a5,bf,23), r(ba,6a,03,02), r(5c,82,16,ed),\ -+ r(2b,1c,cf,8a), r(92,b4,79,a7), r(f0,f2,07,f3), r(a1,e2,69,4e),\ -+ r(cd,f4,da,65), r(d5,be,05,06), r(1f,62,34,d1), r(8a,fe,a6,c4),\ -+ r(9d,53,2e,34), r(a0,55,f3,a2), r(32,e1,8a,05), r(75,eb,f6,a4),\ -+ r(39,ec,83,0b), r(aa,ef,60,40), r(06,9f,71,5e), r(51,10,6e,bd),\ -+ r(f9,8a,21,3e), r(3d,06,dd,96), r(ae,05,3e,dd), r(46,bd,e6,4d),\ -+ r(b5,8d,54,91), r(05,5d,c4,71), r(6f,d4,06,04), r(ff,15,50,60),\ -+ r(24,fb,98,19), r(97,e9,bd,d6), r(cc,43,40,89), r(77,9e,d9,67),\ -+ r(bd,42,e8,b0), r(88,8b,89,07), r(38,5b,19,e7), r(db,ee,c8,79),\ -+ r(47,0a,7c,a1), r(e9,0f,42,7c), r(c9,1e,84,f8), r(00,00,00,00),\ -+ r(83,86,80,09), r(48,ed,2b,32), r(ac,70,11,1e), r(4e,72,5a,6c),\ -+ r(fb,ff,0e,fd), r(56,38,85,0f), r(1e,d5,ae,3d), r(27,39,2d,36),\ -+ r(64,d9,0f,0a), r(21,a6,5c,68), r(d1,54,5b,9b), r(3a,2e,36,24),\ -+ r(b1,67,0a,0c), r(0f,e7,57,93), r(d2,96,ee,b4), r(9e,91,9b,1b),\ -+ r(4f,c5,c0,80), r(a2,20,dc,61), r(69,4b,77,5a), r(16,1a,12,1c),\ -+ r(0a,ba,93,e2), r(e5,2a,a0,c0), r(43,e0,22,3c), r(1d,17,1b,12),\ -+ r(0b,0d,09,0e), r(ad,c7,8b,f2), r(b9,a8,b6,2d), r(c8,a9,1e,14),\ -+ r(85,19,f1,57), r(4c,07,75,af), r(bb,dd,99,ee), r(fd,60,7f,a3),\ -+ r(9f,26,01,f7), r(bc,f5,72,5c), r(c5,3b,66,44), r(34,7e,fb,5b),\ -+ r(76,29,43,8b), r(dc,c6,23,cb), r(68,fc,ed,b6), r(63,f1,e4,b8),\ -+ r(ca,dc,31,d7), r(10,85,63,42), r(40,22,97,13), r(20,11,c6,84),\ -+ r(7d,24,4a,85), r(f8,3d,bb,d2), r(11,32,f9,ae), r(6d,a1,29,c7),\ -+ r(4b,2f,9e,1d), r(f3,30,b2,dc), r(ec,52,86,0d), r(d0,e3,c1,77),\ -+ r(6c,16,b3,2b), r(99,b9,70,a9), r(fa,48,94,11), r(22,64,e9,47),\ -+ r(c4,8c,fc,a8), r(1a,3f,f0,a0), r(d8,2c,7d,56), r(ef,90,33,22),\ -+ r(c7,4e,49,87), r(c1,d1,38,d9), r(fe,a2,ca,8c), r(36,0b,d4,98),\ -+ r(cf,81,f5,a6), r(28,de,7a,a5), r(26,8e,b7,da), r(a4,bf,ad,3f),\ -+ r(e4,9d,3a,2c), r(0d,92,78,50), r(9b,cc,5f,6a), r(62,46,7e,54),\ -+ r(c2,13,8d,f6), r(e8,b8,d8,90), r(5e,f7,39,2e), r(f5,af,c3,82),\ -+ r(be,80,5d,9f), r(7c,93,d0,69), r(a9,2d,d5,6f), r(b3,12,25,cf),\ -+ r(3b,99,ac,c8), r(a7,7d,18,10), r(6e,63,9c,e8), r(7b,bb,3b,db),\ -+ r(09,78,26,cd), r(f4,18,59,6e), r(01,b7,9a,ec), r(a8,9a,4f,83),\ -+ r(65,6e,95,e6), r(7e,e6,ff,aa), r(08,cf,bc,21), r(e6,e8,15,ef),\ -+ r(d9,9b,e7,ba), r(ce,36,6f,4a), r(d4,09,9f,ea), r(d6,7c,b0,29),\ -+ r(af,b2,a4,31), r(31,23,3f,2a), r(30,94,a5,c6), r(c0,66,a2,35),\ -+ r(37,bc,4e,74), r(a6,ca,82,fc), r(b0,d0,90,e0), r(15,d8,a7,33),\ -+ r(4a,98,04,f1), r(f7,da,ec,41), r(0e,50,cd,7f), r(2f,f6,91,17),\ -+ r(8d,d6,4d,76), r(4d,b0,ef,43), r(54,4d,aa,cc), r(df,04,96,e4),\ -+ r(e3,b5,d1,9e), r(1b,88,6a,4c), r(b8,1f,2c,c1), r(7f,51,65,46),\ -+ r(04,ea,5e,9d), r(5d,35,8c,01), r(73,74,87,fa), r(2e,41,0b,fb),\ -+ r(5a,1d,67,b3), r(52,d2,db,92), r(33,56,10,e9), r(13,47,d6,6d),\ -+ r(8c,61,d7,9a), r(7a,0c,a1,37), r(8e,14,f8,59), r(89,3c,13,eb),\ -+ r(ee,27,a9,ce), r(35,c9,61,b7), r(ed,e5,1c,e1), r(3c,b1,47,7a),\ -+ r(59,df,d2,9c), r(3f,73,f2,55), r(79,ce,14,18), r(bf,37,c7,73),\ -+ r(ea,cd,f7,53), r(5b,aa,fd,5f), r(14,6f,3d,df), r(86,db,44,78),\ -+ r(81,f3,af,ca), r(3e,c4,68,b9), r(2c,34,24,38), r(5f,40,a3,c2),\ -+ r(72,c3,1d,16), r(0c,25,e2,bc), r(8b,49,3c,28), r(41,95,0d,ff),\ -+ r(71,01,a8,39), r(de,b3,0c,08), r(9c,e4,b4,d8), r(90,c1,56,64),\ -+ r(61,84,cb,7b), r(70,b6,32,d5), r(74,5c,6c,48), r(42,57,b8,d0) -+ -+// generate the required tables in the desired endian format -+ -+#undef r -+#define r r0 -+ -+#if defined(ONE_TABLE) -+static const u_int32_t ft_tab[256] = -+ { f_table }; -+#elif defined(FOUR_TABLES) -+static const u_int32_t ft_tab[4][256] = -+{ { f_table }, -+#undef r -+#define r r1 -+ { f_table }, -+#undef r -+#define r r2 -+ { f_table }, -+#undef r -+#define r r3 -+ { f_table } -+}; -+#endif -+ -+#undef r -+#define r r0 -+#if defined(ONE_TABLE) -+static const u_int32_t it_tab[256] = -+ { i_table }; -+#elif defined(FOUR_TABLES) -+static const u_int32_t it_tab[4][256] = -+{ { i_table }, -+#undef r -+#define r r1 -+ { i_table }, -+#undef r -+#define r r2 -+ { i_table }, -+#undef r -+#define r r3 -+ { i_table } -+}; -+#endif -+ -+#endif -+ -+#if defined(FIXED_TABLES) && (defined(ONE_LR_TABLE) || defined(FOUR_LR_TABLES)) -+ -+// data for inverse tables (last round) -+ -+#define li_table \ -+ w(52), w(09), w(6a), w(d5), w(30), w(36), w(a5), w(38),\ -+ w(bf), w(40), w(a3), w(9e), w(81), w(f3), w(d7), w(fb),\ -+ w(7c), w(e3), w(39), w(82), w(9b), w(2f), w(ff), w(87),\ -+ w(34), w(8e), w(43), w(44), w(c4), w(de), w(e9), w(cb),\ -+ w(54), w(7b), w(94), w(32), w(a6), w(c2), w(23), w(3d),\ -+ w(ee), w(4c), w(95), w(0b), w(42), w(fa), w(c3), w(4e),\ -+ w(08), w(2e), w(a1), w(66), w(28), w(d9), w(24), w(b2),\ -+ w(76), w(5b), w(a2), w(49), w(6d), w(8b), w(d1), w(25),\ -+ w(72), w(f8), w(f6), w(64), w(86), w(68), w(98), w(16),\ -+ w(d4), w(a4), w(5c), w(cc), w(5d), w(65), w(b6), w(92),\ -+ w(6c), w(70), w(48), w(50), w(fd), w(ed), w(b9), w(da),\ -+ w(5e), w(15), w(46), w(57), w(a7), w(8d), w(9d), w(84),\ -+ w(90), w(d8), w(ab), w(00), w(8c), w(bc), w(d3), w(0a),\ -+ w(f7), w(e4), w(58), w(05), w(b8), w(b3), w(45), w(06),\ -+ w(d0), w(2c), w(1e), w(8f), w(ca), w(3f), w(0f), w(02),\ -+ w(c1), w(af), w(bd), w(03), w(01), w(13), w(8a), w(6b),\ -+ w(3a), w(91), w(11), w(41), w(4f), w(67), w(dc), w(ea),\ -+ w(97), w(f2), w(cf), w(ce), w(f0), w(b4), w(e6), w(73),\ -+ w(96), w(ac), w(74), w(22), w(e7), w(ad), w(35), w(85),\ -+ w(e2), w(f9), w(37), w(e8), w(1c), w(75), w(df), w(6e),\ -+ w(47), w(f1), w(1a), w(71), w(1d), w(29), w(c5), w(89),\ -+ w(6f), w(b7), w(62), w(0e), w(aa), w(18), w(be), w(1b),\ -+ w(fc), w(56), w(3e), w(4b), w(c6), w(d2), w(79), w(20),\ -+ w(9a), w(db), w(c0), w(fe), w(78), w(cd), w(5a), w(f4),\ -+ w(1f), w(dd), w(a8), w(33), w(88), w(07), w(c7), w(31),\ -+ w(b1), w(12), w(10), w(59), w(27), w(80), w(ec), w(5f),\ -+ w(60), w(51), w(7f), w(a9), w(19), w(b5), w(4a), w(0d),\ -+ w(2d), w(e5), w(7a), w(9f), w(93), w(c9), w(9c), w(ef),\ -+ w(a0), w(e0), w(3b), w(4d), w(ae), w(2a), w(f5), w(b0),\ -+ w(c8), w(eb), w(bb), w(3c), w(83), w(53), w(99), w(61),\ -+ w(17), w(2b), w(04), w(7e), w(ba), w(77), w(d6), w(26),\ -+ w(e1), w(69), w(14), w(63), w(55), w(21), w(0c), w(7d), -+ -+// generate the required tables in the desired endian format -+ -+#undef r -+#define r(p,q,r,s) w0(q) -+#if defined(ONE_LR_TABLE) -+static const u_int32_t fl_tab[256] = -+ { f_table }; -+#elif defined(FOUR_LR_TABLES) -+static const u_int32_t fl_tab[4][256] = -+{ { f_table }, -+#undef r -+#define r(p,q,r,s) w1(q) -+ { f_table }, -+#undef r -+#define r(p,q,r,s) w2(q) -+ { f_table }, -+#undef r -+#define r(p,q,r,s) w3(q) -+ { f_table } -+}; -+#endif -+ -+#undef w -+#define w w0 -+#if defined(ONE_LR_TABLE) -+static const u_int32_t il_tab[256] = -+ { li_table }; -+#elif defined(FOUR_LR_TABLES) -+static const u_int32_t il_tab[4][256] = -+{ { li_table }, -+#undef w -+#define w w1 -+ { li_table }, -+#undef w -+#define w w2 -+ { li_table }, -+#undef w -+#define w w3 -+ { li_table } -+}; -+#endif -+ -+#endif -+ -+#if defined(FIXED_TABLES) && (defined(ONE_IM_TABLE) || defined(FOUR_IM_TABLES)) -+ -+#define m_table \ -+ r(00,00,00,00), r(0b,0d,09,0e), r(16,1a,12,1c), r(1d,17,1b,12),\ -+ r(2c,34,24,38), r(27,39,2d,36), r(3a,2e,36,24), r(31,23,3f,2a),\ -+ r(58,68,48,70), r(53,65,41,7e), r(4e,72,5a,6c), r(45,7f,53,62),\ -+ r(74,5c,6c,48), r(7f,51,65,46), r(62,46,7e,54), r(69,4b,77,5a),\ -+ r(b0,d0,90,e0), r(bb,dd,99,ee), r(a6,ca,82,fc), r(ad,c7,8b,f2),\ -+ r(9c,e4,b4,d8), r(97,e9,bd,d6), r(8a,fe,a6,c4), r(81,f3,af,ca),\ -+ r(e8,b8,d8,90), r(e3,b5,d1,9e), r(fe,a2,ca,8c), r(f5,af,c3,82),\ -+ r(c4,8c,fc,a8), r(cf,81,f5,a6), r(d2,96,ee,b4), r(d9,9b,e7,ba),\ -+ r(7b,bb,3b,db), r(70,b6,32,d5), r(6d,a1,29,c7), r(66,ac,20,c9),\ -+ r(57,8f,1f,e3), r(5c,82,16,ed), r(41,95,0d,ff), r(4a,98,04,f1),\ -+ r(23,d3,73,ab), r(28,de,7a,a5), r(35,c9,61,b7), r(3e,c4,68,b9),\ -+ r(0f,e7,57,93), r(04,ea,5e,9d), r(19,fd,45,8f), r(12,f0,4c,81),\ -+ r(cb,6b,ab,3b), r(c0,66,a2,35), r(dd,71,b9,27), r(d6,7c,b0,29),\ -+ r(e7,5f,8f,03), r(ec,52,86,0d), r(f1,45,9d,1f), r(fa,48,94,11),\ -+ r(93,03,e3,4b), r(98,0e,ea,45), r(85,19,f1,57), r(8e,14,f8,59),\ -+ r(bf,37,c7,73), r(b4,3a,ce,7d), r(a9,2d,d5,6f), r(a2,20,dc,61),\ -+ r(f6,6d,76,ad), r(fd,60,7f,a3), r(e0,77,64,b1), r(eb,7a,6d,bf),\ -+ r(da,59,52,95), r(d1,54,5b,9b), r(cc,43,40,89), r(c7,4e,49,87),\ -+ r(ae,05,3e,dd), r(a5,08,37,d3), r(b8,1f,2c,c1), r(b3,12,25,cf),\ -+ r(82,31,1a,e5), r(89,3c,13,eb), r(94,2b,08,f9), r(9f,26,01,f7),\ -+ r(46,bd,e6,4d), r(4d,b0,ef,43), r(50,a7,f4,51), r(5b,aa,fd,5f),\ -+ r(6a,89,c2,75), r(61,84,cb,7b), r(7c,93,d0,69), r(77,9e,d9,67),\ -+ r(1e,d5,ae,3d), r(15,d8,a7,33), r(08,cf,bc,21), r(03,c2,b5,2f),\ -+ r(32,e1,8a,05), r(39,ec,83,0b), r(24,fb,98,19), r(2f,f6,91,17),\ -+ r(8d,d6,4d,76), r(86,db,44,78), r(9b,cc,5f,6a), r(90,c1,56,64),\ -+ r(a1,e2,69,4e), r(aa,ef,60,40), r(b7,f8,7b,52), r(bc,f5,72,5c),\ -+ r(d5,be,05,06), r(de,b3,0c,08), r(c3,a4,17,1a), r(c8,a9,1e,14),\ -+ r(f9,8a,21,3e), r(f2,87,28,30), r(ef,90,33,22), r(e4,9d,3a,2c),\ -+ r(3d,06,dd,96), r(36,0b,d4,98), r(2b,1c,cf,8a), r(20,11,c6,84),\ -+ r(11,32,f9,ae), r(1a,3f,f0,a0), r(07,28,eb,b2), r(0c,25,e2,bc),\ -+ r(65,6e,95,e6), r(6e,63,9c,e8), r(73,74,87,fa), r(78,79,8e,f4),\ -+ r(49,5a,b1,de), r(42,57,b8,d0), r(5f,40,a3,c2), r(54,4d,aa,cc),\ -+ r(f7,da,ec,41), r(fc,d7,e5,4f), r(e1,c0,fe,5d), r(ea,cd,f7,53),\ -+ r(db,ee,c8,79), r(d0,e3,c1,77), r(cd,f4,da,65), r(c6,f9,d3,6b),\ -+ r(af,b2,a4,31), r(a4,bf,ad,3f), r(b9,a8,b6,2d), r(b2,a5,bf,23),\ -+ r(83,86,80,09), r(88,8b,89,07), r(95,9c,92,15), r(9e,91,9b,1b),\ -+ r(47,0a,7c,a1), r(4c,07,75,af), r(51,10,6e,bd), r(5a,1d,67,b3),\ -+ r(6b,3e,58,99), r(60,33,51,97), r(7d,24,4a,85), r(76,29,43,8b),\ -+ r(1f,62,34,d1), r(14,6f,3d,df), r(09,78,26,cd), r(02,75,2f,c3),\ -+ r(33,56,10,e9), r(38,5b,19,e7), r(25,4c,02,f5), r(2e,41,0b,fb),\ -+ r(8c,61,d7,9a), r(87,6c,de,94), r(9a,7b,c5,86), r(91,76,cc,88),\ -+ r(a0,55,f3,a2), r(ab,58,fa,ac), r(b6,4f,e1,be), r(bd,42,e8,b0),\ -+ r(d4,09,9f,ea), r(df,04,96,e4), r(c2,13,8d,f6), r(c9,1e,84,f8),\ -+ r(f8,3d,bb,d2), r(f3,30,b2,dc), r(ee,27,a9,ce), r(e5,2a,a0,c0),\ -+ r(3c,b1,47,7a), r(37,bc,4e,74), r(2a,ab,55,66), r(21,a6,5c,68),\ -+ r(10,85,63,42), r(1b,88,6a,4c), r(06,9f,71,5e), r(0d,92,78,50),\ -+ r(64,d9,0f,0a), r(6f,d4,06,04), r(72,c3,1d,16), r(79,ce,14,18),\ -+ r(48,ed,2b,32), r(43,e0,22,3c), r(5e,f7,39,2e), r(55,fa,30,20),\ -+ r(01,b7,9a,ec), r(0a,ba,93,e2), r(17,ad,88,f0), r(1c,a0,81,fe),\ -+ r(2d,83,be,d4), r(26,8e,b7,da), r(3b,99,ac,c8), r(30,94,a5,c6),\ -+ r(59,df,d2,9c), r(52,d2,db,92), r(4f,c5,c0,80), r(44,c8,c9,8e),\ -+ r(75,eb,f6,a4), r(7e,e6,ff,aa), r(63,f1,e4,b8), r(68,fc,ed,b6),\ -+ r(b1,67,0a,0c), r(ba,6a,03,02), r(a7,7d,18,10), r(ac,70,11,1e),\ -+ r(9d,53,2e,34), r(96,5e,27,3a), r(8b,49,3c,28), r(80,44,35,26),\ -+ r(e9,0f,42,7c), r(e2,02,4b,72), r(ff,15,50,60), r(f4,18,59,6e),\ -+ r(c5,3b,66,44), r(ce,36,6f,4a), r(d3,21,74,58), r(d8,2c,7d,56),\ -+ r(7a,0c,a1,37), r(71,01,a8,39), r(6c,16,b3,2b), r(67,1b,ba,25),\ -+ r(56,38,85,0f), r(5d,35,8c,01), r(40,22,97,13), r(4b,2f,9e,1d),\ -+ r(22,64,e9,47), r(29,69,e0,49), r(34,7e,fb,5b), r(3f,73,f2,55),\ -+ r(0e,50,cd,7f), r(05,5d,c4,71), r(18,4a,df,63), r(13,47,d6,6d),\ -+ r(ca,dc,31,d7), r(c1,d1,38,d9), r(dc,c6,23,cb), r(d7,cb,2a,c5),\ -+ r(e6,e8,15,ef), r(ed,e5,1c,e1), r(f0,f2,07,f3), r(fb,ff,0e,fd),\ -+ r(92,b4,79,a7), r(99,b9,70,a9), r(84,ae,6b,bb), r(8f,a3,62,b5),\ -+ r(be,80,5d,9f), r(b5,8d,54,91), r(a8,9a,4f,83), r(a3,97,46,8d) -+ -+#undef r -+#define r r0 -+ -+#if defined(ONE_IM_TABLE) -+static const u_int32_t im_tab[256] = -+ { m_table }; -+#elif defined(FOUR_IM_TABLES) -+static const u_int32_t im_tab[4][256] = -+{ { m_table }, -+#undef r -+#define r r1 -+ { m_table }, -+#undef r -+#define r r2 -+ { m_table }, -+#undef r -+#define r r3 -+ { m_table } -+}; -+#endif -+ -+#endif -+ -+#else -+ -+static int tab_gen = 0; -+ -+static unsigned char s_box[256]; // the S box -+static unsigned char inv_s_box[256]; // the inverse S box -+static u_int32_t rcon_tab[AES_RC_LENGTH]; // table of round constants -+ -+#if defined(ONE_TABLE) -+static u_int32_t ft_tab[256]; -+static u_int32_t it_tab[256]; -+#elif defined(FOUR_TABLES) -+static u_int32_t ft_tab[4][256]; -+static u_int32_t it_tab[4][256]; -+#endif -+ -+#if defined(ONE_LR_TABLE) -+static u_int32_t fl_tab[256]; -+static u_int32_t il_tab[256]; -+#elif defined(FOUR_LR_TABLES) -+static u_int32_t fl_tab[4][256]; -+static u_int32_t il_tab[4][256]; -+#endif -+ -+#if defined(ONE_IM_TABLE) -+static u_int32_t im_tab[256]; -+#elif defined(FOUR_IM_TABLES) -+static u_int32_t im_tab[4][256]; -+#endif -+ -+// Generate the tables for the dynamic table option -+ -+#if !defined(FF_TABLES) -+ -+// It will generally be sensible to use tables to compute finite -+// field multiplies and inverses but where memory is scarse this -+// code might sometimes be better. -+ -+// return 2 ^ (n - 1) where n is the bit number of the highest bit -+// set in x with x in the range 1 < x < 0x00000200. This form is -+// used so that locals within FFinv can be bytes rather than words -+ -+static unsigned char hibit(const u_int32_t x) -+{ unsigned char r = (unsigned char)((x >> 1) | (x >> 2)); -+ -+ r |= (r >> 2); -+ r |= (r >> 4); -+ return (r + 1) >> 1; -+} -+ -+// return the inverse of the finite field element x -+ -+static unsigned char FFinv(const unsigned char x) -+{ unsigned char p1 = x, p2 = 0x1b, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; -+ -+ if(x < 2) return x; -+ -+ for(;;) -+ { -+ if(!n1) return v1; -+ -+ while(n2 >= n1) -+ { -+ n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2); -+ } -+ -+ if(!n2) return v2; -+ -+ while(n1 >= n2) -+ { -+ n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1); -+ } -+ } -+} -+ -+// define the finite field multiplies required for Rijndael -+ -+#define FFmul02(x) ((((x) & 0x7f) << 1) ^ ((x) & 0x80 ? 0x1b : 0)) -+#define FFmul03(x) ((x) ^ FFmul02(x)) -+#define FFmul09(x) ((x) ^ FFmul02(FFmul02(FFmul02(x)))) -+#define FFmul0b(x) ((x) ^ FFmul02((x) ^ FFmul02(FFmul02(x)))) -+#define FFmul0d(x) ((x) ^ FFmul02(FFmul02((x) ^ FFmul02(x)))) -+#define FFmul0e(x) FFmul02((x) ^ FFmul02((x) ^ FFmul02(x))) -+ -+#else -+ -+#define FFinv(x) ((x) ? pow[255 - log[x]]: 0) -+ -+#define FFmul02(x) (x ? pow[log[x] + 0x19] : 0) -+#define FFmul03(x) (x ? pow[log[x] + 0x01] : 0) -+#define FFmul09(x) (x ? pow[log[x] + 0xc7] : 0) -+#define FFmul0b(x) (x ? pow[log[x] + 0x68] : 0) -+#define FFmul0d(x) (x ? pow[log[x] + 0xee] : 0) -+#define FFmul0e(x) (x ? pow[log[x] + 0xdf] : 0) -+ -+#endif -+ -+// The forward and inverse affine transformations used in the S-box -+ -+#define fwd_affine(x) \ -+ (w = (u_int32_t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(unsigned char)(w^(w>>8))) -+ -+#define inv_affine(x) \ -+ (w = (u_int32_t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(unsigned char)(w^(w>>8))) -+ -+static void gen_tabs(void) -+{ u_int32_t i, w; -+ -+#if defined(FF_TABLES) -+ -+ unsigned char pow[512], log[256]; -+ -+ // log and power tables for GF(2^8) finite field with -+ // 0x011b as modular polynomial - the simplest primitive -+ // root is 0x03, used here to generate the tables -+ -+ i = 0; w = 1; -+ do -+ { -+ pow[i] = (unsigned char)w; -+ pow[i + 255] = (unsigned char)w; -+ log[w] = (unsigned char)i++; -+ w ^= (w << 1) ^ (w & ff_hi ? ff_poly : 0); -+ } -+ while (w != 1); -+ -+#endif -+ -+ for(i = 0, w = 1; i < AES_RC_LENGTH; ++i) -+ { -+ rcon_tab[i] = bytes2word(w, 0, 0, 0); -+ w = (w << 1) ^ (w & ff_hi ? ff_poly : 0); -+ } -+ -+ for(i = 0; i < 256; ++i) -+ { unsigned char b; -+ -+ s_box[i] = b = fwd_affine(FFinv((unsigned char)i)); -+ -+ w = bytes2word(b, 0, 0, 0); -+#if defined(ONE_LR_TABLE) -+ fl_tab[i] = w; -+#elif defined(FOUR_LR_TABLES) -+ fl_tab[0][i] = w; -+ fl_tab[1][i] = upr(w,1); -+ fl_tab[2][i] = upr(w,2); -+ fl_tab[3][i] = upr(w,3); -+#endif -+ w = bytes2word(FFmul02(b), b, b, FFmul03(b)); -+#if defined(ONE_TABLE) -+ ft_tab[i] = w; -+#elif defined(FOUR_TABLES) -+ ft_tab[0][i] = w; -+ ft_tab[1][i] = upr(w,1); -+ ft_tab[2][i] = upr(w,2); -+ ft_tab[3][i] = upr(w,3); -+#endif -+ inv_s_box[i] = b = FFinv(inv_affine((unsigned char)i)); -+ -+ w = bytes2word(b, 0, 0, 0); -+#if defined(ONE_LR_TABLE) -+ il_tab[i] = w; -+#elif defined(FOUR_LR_TABLES) -+ il_tab[0][i] = w; -+ il_tab[1][i] = upr(w,1); -+ il_tab[2][i] = upr(w,2); -+ il_tab[3][i] = upr(w,3); -+#endif -+ w = bytes2word(FFmul0e(b), FFmul09(b), FFmul0d(b), FFmul0b(b)); -+#if defined(ONE_TABLE) -+ it_tab[i] = w; -+#elif defined(FOUR_TABLES) -+ it_tab[0][i] = w; -+ it_tab[1][i] = upr(w,1); -+ it_tab[2][i] = upr(w,2); -+ it_tab[3][i] = upr(w,3); -+#endif -+#if defined(ONE_IM_TABLE) -+ im_tab[b] = w; -+#elif defined(FOUR_IM_TABLES) -+ im_tab[0][b] = w; -+ im_tab[1][b] = upr(w,1); -+ im_tab[2][b] = upr(w,2); -+ im_tab[3][b] = upr(w,3); -+#endif -+ -+ } -+} -+ -+#endif -+ -+#define no_table(x,box,vf,rf,c) bytes2word( \ -+ box[bval(vf(x,0,c),rf(0,c))], \ -+ box[bval(vf(x,1,c),rf(1,c))], \ -+ box[bval(vf(x,2,c),rf(2,c))], \ -+ box[bval(vf(x,3,c),rf(3,c))]) -+ -+#define one_table(x,op,tab,vf,rf,c) \ -+ ( tab[bval(vf(x,0,c),rf(0,c))] \ -+ ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \ -+ ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \ -+ ^ op(tab[bval(vf(x,3,c),rf(3,c))],3)) -+ -+#define four_tables(x,tab,vf,rf,c) \ -+ ( tab[0][bval(vf(x,0,c),rf(0,c))] \ -+ ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ -+ ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ -+ ^ tab[3][bval(vf(x,3,c),rf(3,c))]) -+ -+#define vf1(x,r,c) (x) -+#define rf1(r,c) (r) -+#define rf2(r,c) ((r-c)&3) -+ -+#if defined(FOUR_LR_TABLES) -+#define ls_box(x,c) four_tables(x,fl_tab,vf1,rf2,c) -+#elif defined(ONE_LR_TABLE) -+#define ls_box(x,c) one_table(x,upr,fl_tab,vf1,rf2,c) -+#else -+#define ls_box(x,c) no_table(x,s_box,vf1,rf2,c) -+#endif -+ -+#if defined(FOUR_IM_TABLES) -+#define inv_mcol(x) four_tables(x,im_tab,vf1,rf1,0) -+#elif defined(ONE_IM_TABLE) -+#define inv_mcol(x) one_table(x,upr,im_tab,vf1,rf1,0) -+#else -+#define inv_mcol(x) \ -+ (f9 = (x),f2 = FFmulX(f9), f4 = FFmulX(f2), f8 = FFmulX(f4), f9 ^= f8, \ -+ f2 ^= f4 ^ f8 ^ upr(f2 ^ f9,3) ^ upr(f4 ^ f9,2) ^ upr(f9,1)) -+#endif -+ -+// Subroutine to set the block size (if variable) in bytes, legal -+// values being 16, 24 and 32. -+ -+#if defined(AES_BLOCK_SIZE) -+#define nc (AES_BLOCK_SIZE / 4) -+#else -+#define nc (cx->aes_Ncol) -+ -+void aes_set_blk(aes_context *cx, int n_bytes) -+{ -+#if !defined(FIXED_TABLES) -+ if(!tab_gen) { gen_tabs(); tab_gen = 1; } -+#endif -+ -+ switch(n_bytes) { -+ case 32: /* bytes */ -+ case 256: /* bits */ -+ nc = 8; -+ break; -+ case 24: /* bytes */ -+ case 192: /* bits */ -+ nc = 6; -+ break; -+ case 16: /* bytes */ -+ case 128: /* bits */ -+ default: -+ nc = 4; -+ break; -+ } -+} -+ -+#endif -+ -+// Initialise the key schedule from the user supplied key. The key -+// length is now specified in bytes - 16, 24 or 32 as appropriate. -+// This corresponds to bit lengths of 128, 192 and 256 bits, and -+// to Nk values of 4, 6 and 8 respectively. -+ -+#define mx(t,f) (*t++ = inv_mcol(*f),f++) -+#define cp(t,f) *t++ = *f++ -+ -+#if AES_BLOCK_SIZE == 16 -+#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s) -+#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s) -+#elif AES_BLOCK_SIZE == 24 -+#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ -+ cp(d,s); cp(d,s) -+#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ -+ mx(d,s); mx(d,s) -+#elif AES_BLOCK_SIZE == 32 -+#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ -+ cp(d,s); cp(d,s); cp(d,s); cp(d,s) -+#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ -+ mx(d,s); mx(d,s); mx(d,s); mx(d,s) -+#else -+ -+#define cpy(d,s) \ -+switch(nc) \ -+{ case 8: cp(d,s); cp(d,s); \ -+ case 6: cp(d,s); cp(d,s); \ -+ case 4: cp(d,s); cp(d,s); \ -+ cp(d,s); cp(d,s); \ -+} -+ -+#define mix(d,s) \ -+switch(nc) \ -+{ case 8: mx(d,s); mx(d,s); \ -+ case 6: mx(d,s); mx(d,s); \ -+ case 4: mx(d,s); mx(d,s); \ -+ mx(d,s); mx(d,s); \ -+} -+ -+#endif -+ -+void aes_set_key(aes_context *cx, const unsigned char in_key[], int n_bytes, const int f) -+{ u_int32_t *kf, *kt, rci; -+ -+#if !defined(FIXED_TABLES) -+ if(!tab_gen) { gen_tabs(); tab_gen = 1; } -+#endif -+ -+ switch(n_bytes) { -+ case 32: /* bytes */ -+ case 256: /* bits */ -+ cx->aes_Nkey = 8; -+ break; -+ case 24: /* bytes */ -+ case 192: /* bits */ -+ cx->aes_Nkey = 6; -+ break; -+ case 16: /* bytes */ -+ case 128: /* bits */ -+ default: -+ cx->aes_Nkey = 4; -+ break; -+ } -+ -+ cx->aes_Nrnd = (cx->aes_Nkey > nc ? cx->aes_Nkey : nc) + 6; -+ -+ cx->aes_e_key[0] = const_word_in(in_key ); -+ cx->aes_e_key[1] = const_word_in(in_key + 4); -+ cx->aes_e_key[2] = const_word_in(in_key + 8); -+ cx->aes_e_key[3] = const_word_in(in_key + 12); -+ -+ kf = cx->aes_e_key; -+ kt = kf + nc * (cx->aes_Nrnd + 1) - cx->aes_Nkey; -+ rci = 0; -+ -+ switch(cx->aes_Nkey) -+ { -+ case 4: do -+ { kf[4] = kf[0] ^ ls_box(kf[3],3) ^ rcon_tab[rci++]; -+ kf[5] = kf[1] ^ kf[4]; -+ kf[6] = kf[2] ^ kf[5]; -+ kf[7] = kf[3] ^ kf[6]; -+ kf += 4; -+ } -+ while(kf < kt); -+ break; -+ -+ case 6: cx->aes_e_key[4] = const_word_in(in_key + 16); -+ cx->aes_e_key[5] = const_word_in(in_key + 20); -+ do -+ { kf[ 6] = kf[0] ^ ls_box(kf[5],3) ^ rcon_tab[rci++]; -+ kf[ 7] = kf[1] ^ kf[ 6]; -+ kf[ 8] = kf[2] ^ kf[ 7]; -+ kf[ 9] = kf[3] ^ kf[ 8]; -+ kf[10] = kf[4] ^ kf[ 9]; -+ kf[11] = kf[5] ^ kf[10]; -+ kf += 6; -+ } -+ while(kf < kt); -+ break; -+ -+ case 8: cx->aes_e_key[4] = const_word_in(in_key + 16); -+ cx->aes_e_key[5] = const_word_in(in_key + 20); -+ cx->aes_e_key[6] = const_word_in(in_key + 24); -+ cx->aes_e_key[7] = const_word_in(in_key + 28); -+ do -+ { kf[ 8] = kf[0] ^ ls_box(kf[7],3) ^ rcon_tab[rci++]; -+ kf[ 9] = kf[1] ^ kf[ 8]; -+ kf[10] = kf[2] ^ kf[ 9]; -+ kf[11] = kf[3] ^ kf[10]; -+ kf[12] = kf[4] ^ ls_box(kf[11],0); -+ kf[13] = kf[5] ^ kf[12]; -+ kf[14] = kf[6] ^ kf[13]; -+ kf[15] = kf[7] ^ kf[14]; -+ kf += 8; -+ } -+ while (kf < kt); -+ break; -+ } -+ -+ if(!f) -+ { u_int32_t i; -+ -+ kt = cx->aes_d_key + nc * cx->aes_Nrnd; -+ kf = cx->aes_e_key; -+ -+ cpy(kt, kf); kt -= 2 * nc; -+ -+ for(i = 1; i < cx->aes_Nrnd; ++i) -+ { -+#if defined(ONE_TABLE) || defined(FOUR_TABLES) -+#if !defined(ONE_IM_TABLE) && !defined(FOUR_IM_TABLES) -+ u_int32_t f2, f4, f8, f9; -+#endif -+ mix(kt, kf); -+#else -+ cpy(kt, kf); -+#endif -+ kt -= 2 * nc; -+ } -+ -+ cpy(kt, kf); -+ } -+} -+ -+// y = output word, x = input word, r = row, c = column -+// for r = 0, 1, 2 and 3 = column accessed for row r -+ -+#if defined(ARRAYS) -+#define s(x,c) x[c] -+#else -+#define s(x,c) x##c -+#endif -+ -+// I am grateful to Frank Yellin for the following constructions -+// which, given the column (c) of the output state variable that -+// is being computed, return the input state variables which are -+// needed for each row (r) of the state -+ -+// For the fixed block size options, compilers reduce these two -+// expressions to fixed variable references. For variable block -+// size code conditional clauses will sometimes be returned -+ -+#define unused 77 // Sunset Strip -+ -+#define fwd_var(x,r,c) \ -+ ( r==0 ? \ -+ ( c==0 ? s(x,0) \ -+ : c==1 ? s(x,1) \ -+ : c==2 ? s(x,2) \ -+ : c==3 ? s(x,3) \ -+ : c==4 ? s(x,4) \ -+ : c==5 ? s(x,5) \ -+ : c==6 ? s(x,6) \ -+ : s(x,7)) \ -+ : r==1 ? \ -+ ( c==0 ? s(x,1) \ -+ : c==1 ? s(x,2) \ -+ : c==2 ? s(x,3) \ -+ : c==3 ? nc==4 ? s(x,0) : s(x,4) \ -+ : c==4 ? s(x,5) \ -+ : c==5 ? nc==8 ? s(x,6) : s(x,0) \ -+ : c==6 ? s(x,7) \ -+ : s(x,0)) \ -+ : r==2 ? \ -+ ( c==0 ? nc==8 ? s(x,3) : s(x,2) \ -+ : c==1 ? nc==8 ? s(x,4) : s(x,3) \ -+ : c==2 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \ -+ : c==3 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \ -+ : c==4 ? nc==8 ? s(x,7) : s(x,0) \ -+ : c==5 ? nc==8 ? s(x,0) : s(x,1) \ -+ : c==6 ? s(x,1) \ -+ : s(x,2)) \ -+ : \ -+ ( c==0 ? nc==8 ? s(x,4) : s(x,3) \ -+ : c==1 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \ -+ : c==2 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \ -+ : c==3 ? nc==4 ? s(x,2) : nc==8 ? s(x,7) : s(x,0) \ -+ : c==4 ? nc==8 ? s(x,0) : s(x,1) \ -+ : c==5 ? nc==8 ? s(x,1) : s(x,2) \ -+ : c==6 ? s(x,2) \ -+ : s(x,3))) -+ -+#define inv_var(x,r,c) \ -+ ( r==0 ? \ -+ ( c==0 ? s(x,0) \ -+ : c==1 ? s(x,1) \ -+ : c==2 ? s(x,2) \ -+ : c==3 ? s(x,3) \ -+ : c==4 ? s(x,4) \ -+ : c==5 ? s(x,5) \ -+ : c==6 ? s(x,6) \ -+ : s(x,7)) \ -+ : r==1 ? \ -+ ( c==0 ? nc==4 ? s(x,3) : nc==8 ? s(x,7) : s(x,5) \ -+ : c==1 ? s(x,0) \ -+ : c==2 ? s(x,1) \ -+ : c==3 ? s(x,2) \ -+ : c==4 ? s(x,3) \ -+ : c==5 ? s(x,4) \ -+ : c==6 ? s(x,5) \ -+ : s(x,6)) \ -+ : r==2 ? \ -+ ( c==0 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \ -+ : c==1 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \ -+ : c==2 ? nc==8 ? s(x,7) : s(x,0) \ -+ : c==3 ? nc==8 ? s(x,0) : s(x,1) \ -+ : c==4 ? nc==8 ? s(x,1) : s(x,2) \ -+ : c==5 ? nc==8 ? s(x,2) : s(x,3) \ -+ : c==6 ? s(x,3) \ -+ : s(x,4)) \ -+ : \ -+ ( c==0 ? nc==4 ? s(x,1) : nc==8 ? s(x,4) : s(x,3) \ -+ : c==1 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \ -+ : c==2 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \ -+ : c==3 ? nc==8 ? s(x,7) : s(x,0) \ -+ : c==4 ? nc==8 ? s(x,0) : s(x,1) \ -+ : c==5 ? nc==8 ? s(x,1) : s(x,2) \ -+ : c==6 ? s(x,2) \ -+ : s(x,3))) -+ -+#define si(y,x,k,c) s(y,c) = const_word_in(x + 4 * c) ^ k[c] -+#define so(y,x,c) word_out(y + 4 * c, s(x,c)) -+ -+#if defined(FOUR_TABLES) -+#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,ft_tab,fwd_var,rf1,c) -+#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,it_tab,inv_var,rf1,c) -+#elif defined(ONE_TABLE) -+#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,ft_tab,fwd_var,rf1,c) -+#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,it_tab,inv_var,rf1,c) -+#else -+#define fwd_rnd(y,x,k,c) s(y,c) = fwd_mcol(no_table(x,s_box,fwd_var,rf1,c)) ^ (k)[c] -+#define inv_rnd(y,x,k,c) s(y,c) = inv_mcol(no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c]) -+#endif -+ -+#if defined(FOUR_LR_TABLES) -+#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,fl_tab,fwd_var,rf1,c) -+#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,il_tab,inv_var,rf1,c) -+#elif defined(ONE_LR_TABLE) -+#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,fl_tab,fwd_var,rf1,c) -+#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,il_tab,inv_var,rf1,c) -+#else -+#define fwd_lrnd(y,x,k,c) s(y,c) = no_table(x,s_box,fwd_var,rf1,c) ^ (k)[c] -+#define inv_lrnd(y,x,k,c) s(y,c) = no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c] -+#endif -+ -+#if AES_BLOCK_SIZE == 16 -+ -+#if defined(ARRAYS) -+#define locals(y,x) x[4],y[4] -+#else -+#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 -+// the following defines prevent the compiler requiring the declaration -+// of generated but unused variables in the fwd_var and inv_var macros -+#define b04 unused -+#define b05 unused -+#define b06 unused -+#define b07 unused -+#define b14 unused -+#define b15 unused -+#define b16 unused -+#define b17 unused -+#endif -+#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ -+ s(y,2) = s(x,2); s(y,3) = s(x,3); -+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) -+#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) -+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) -+ -+#elif AES_BLOCK_SIZE == 24 -+ -+#if defined(ARRAYS) -+#define locals(y,x) x[6],y[6] -+#else -+#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5, \ -+ y##0,y##1,y##2,y##3,y##4,y##5 -+#define b06 unused -+#define b07 unused -+#define b16 unused -+#define b17 unused -+#endif -+#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ -+ s(y,2) = s(x,2); s(y,3) = s(x,3); \ -+ s(y,4) = s(x,4); s(y,5) = s(x,5); -+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \ -+ si(y,x,k,3); si(y,x,k,4); si(y,x,k,5) -+#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); \ -+ so(y,x,3); so(y,x,4); so(y,x,5) -+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \ -+ rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5) -+#else -+ -+#if defined(ARRAYS) -+#define locals(y,x) x[8],y[8] -+#else -+#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5,x##6,x##7, \ -+ y##0,y##1,y##2,y##3,y##4,y##5,y##6,y##7 -+#endif -+#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ -+ s(y,2) = s(x,2); s(y,3) = s(x,3); \ -+ s(y,4) = s(x,4); s(y,5) = s(x,5); \ -+ s(y,6) = s(x,6); s(y,7) = s(x,7); -+ -+#if AES_BLOCK_SIZE == 32 -+ -+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); \ -+ si(y,x,k,4); si(y,x,k,5); si(y,x,k,6); si(y,x,k,7) -+#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); \ -+ so(y,x,4); so(y,x,5); so(y,x,6); so(y,x,7) -+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \ -+ rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7) -+#else -+ -+#define state_in(y,x,k) \ -+switch(nc) \ -+{ case 8: si(y,x,k,7); si(y,x,k,6); \ -+ case 6: si(y,x,k,5); si(y,x,k,4); \ -+ case 4: si(y,x,k,3); si(y,x,k,2); \ -+ si(y,x,k,1); si(y,x,k,0); \ -+} -+ -+#define state_out(y,x) \ -+switch(nc) \ -+{ case 8: so(y,x,7); so(y,x,6); \ -+ case 6: so(y,x,5); so(y,x,4); \ -+ case 4: so(y,x,3); so(y,x,2); \ -+ so(y,x,1); so(y,x,0); \ -+} -+ -+#if defined(FAST_VARIABLE) -+ -+#define round(rm,y,x,k) \ -+switch(nc) \ -+{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ -+ rm(y,x,k,5); rm(y,x,k,4); \ -+ rm(y,x,k,3); rm(y,x,k,2); \ -+ rm(y,x,k,1); rm(y,x,k,0); \ -+ break; \ -+ case 6: rm(y,x,k,5); rm(y,x,k,4); \ -+ rm(y,x,k,3); rm(y,x,k,2); \ -+ rm(y,x,k,1); rm(y,x,k,0); \ -+ break; \ -+ case 4: rm(y,x,k,3); rm(y,x,k,2); \ -+ rm(y,x,k,1); rm(y,x,k,0); \ -+ break; \ -+} -+#else -+ -+#define round(rm,y,x,k) \ -+switch(nc) \ -+{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ -+ case 6: rm(y,x,k,5); rm(y,x,k,4); \ -+ case 4: rm(y,x,k,3); rm(y,x,k,2); \ -+ rm(y,x,k,1); rm(y,x,k,0); \ -+} -+ -+#endif -+ -+#endif -+#endif -+ -+void aes_encrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) -+{ u_int32_t locals(b0, b1); -+ const u_int32_t *kp = cx->aes_e_key; -+ -+#if !defined(ONE_TABLE) && !defined(FOUR_TABLES) -+ u_int32_t f2; -+#endif -+ -+ state_in(b0, in_blk, kp); kp += nc; -+ -+#if defined(UNROLL) -+ -+ switch(cx->aes_Nrnd) -+ { -+ case 14: round(fwd_rnd, b1, b0, kp ); -+ round(fwd_rnd, b0, b1, kp + nc ); kp += 2 * nc; -+ case 12: round(fwd_rnd, b1, b0, kp ); -+ round(fwd_rnd, b0, b1, kp + nc ); kp += 2 * nc; -+ case 10: round(fwd_rnd, b1, b0, kp ); -+ round(fwd_rnd, b0, b1, kp + nc); -+ round(fwd_rnd, b1, b0, kp + 2 * nc); -+ round(fwd_rnd, b0, b1, kp + 3 * nc); -+ round(fwd_rnd, b1, b0, kp + 4 * nc); -+ round(fwd_rnd, b0, b1, kp + 5 * nc); -+ round(fwd_rnd, b1, b0, kp + 6 * nc); -+ round(fwd_rnd, b0, b1, kp + 7 * nc); -+ round(fwd_rnd, b1, b0, kp + 8 * nc); -+ round(fwd_lrnd, b0, b1, kp + 9 * nc); -+ } -+ -+#elif defined(PARTIAL_UNROLL) -+ { u_int32_t rnd; -+ -+ for(rnd = 0; rnd < (cx->aes_Nrnd >> 1) - 1; ++rnd) -+ { -+ round(fwd_rnd, b1, b0, kp); -+ round(fwd_rnd, b0, b1, kp + nc); kp += 2 * nc; -+ } -+ -+ round(fwd_rnd, b1, b0, kp); -+ round(fwd_lrnd, b0, b1, kp + nc); -+ } -+#else -+ { u_int32_t rnd; -+ -+ for(rnd = 0; rnd < cx->aes_Nrnd - 1; ++rnd) -+ { -+ round(fwd_rnd, b1, b0, kp); -+ l_copy(b0, b1); kp += nc; -+ } -+ -+ round(fwd_lrnd, b0, b1, kp); -+ } -+#endif -+ -+ state_out(out_blk, b0); -+} -+ -+void aes_decrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) -+{ u_int32_t locals(b0, b1); -+ const u_int32_t *kp = cx->aes_d_key; -+ -+#if !defined(ONE_TABLE) && !defined(FOUR_TABLES) -+ u_int32_t f2, f4, f8, f9; -+#endif -+ -+ state_in(b0, in_blk, kp); kp += nc; -+ -+#if defined(UNROLL) -+ -+ switch(cx->aes_Nrnd) -+ { -+ case 14: round(inv_rnd, b1, b0, kp ); -+ round(inv_rnd, b0, b1, kp + nc ); kp += 2 * nc; -+ case 12: round(inv_rnd, b1, b0, kp ); -+ round(inv_rnd, b0, b1, kp + nc ); kp += 2 * nc; -+ case 10: round(inv_rnd, b1, b0, kp ); -+ round(inv_rnd, b0, b1, kp + nc); -+ round(inv_rnd, b1, b0, kp + 2 * nc); -+ round(inv_rnd, b0, b1, kp + 3 * nc); -+ round(inv_rnd, b1, b0, kp + 4 * nc); -+ round(inv_rnd, b0, b1, kp + 5 * nc); -+ round(inv_rnd, b1, b0, kp + 6 * nc); -+ round(inv_rnd, b0, b1, kp + 7 * nc); -+ round(inv_rnd, b1, b0, kp + 8 * nc); -+ round(inv_lrnd, b0, b1, kp + 9 * nc); -+ } -+ -+#elif defined(PARTIAL_UNROLL) -+ { u_int32_t rnd; -+ -+ for(rnd = 0; rnd < (cx->aes_Nrnd >> 1) - 1; ++rnd) -+ { -+ round(inv_rnd, b1, b0, kp); -+ round(inv_rnd, b0, b1, kp + nc); kp += 2 * nc; -+ } -+ -+ round(inv_rnd, b1, b0, kp); -+ round(inv_lrnd, b0, b1, kp + nc); -+ } -+#else -+ { u_int32_t rnd; -+ -+ for(rnd = 0; rnd < cx->aes_Nrnd - 1; ++rnd) -+ { -+ round(inv_rnd, b1, b0, kp); -+ l_copy(b0, b1); kp += nc; -+ } -+ -+ round(inv_lrnd, b0, b1, kp); -+ } -+#endif -+ -+ state_out(out_blk, b0); -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/aes/aes_cbc.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,43 @@ -+/* -+// I retain copyright in this code but I encourage its free use provided -+// that I don't carry any responsibility for the results. I am especially -+// happy to see it used in free and open source software. If you do use -+// it I would appreciate an acknowledgement of its origin in the code or -+// the product that results and I would also appreciate knowing a little -+// about the use to which it is being put. I am grateful to Frank Yellin -+// for some ideas that are used in this implementation. -+// -+// Dr B. R. Gladman 6th April 2001. -+// -+// This is an implementation of the AES encryption algorithm (Rijndael) -+// designed by Joan Daemen and Vincent Rijmen. This version is designed -+// to provide both fixed and dynamic block and key lengths and can also -+// run with either big or little endian internal byte order (see aes.h). -+// It inputs block and key lengths in bytes with the legal values being -+// 16, 24 and 32. -+* -+*/ -+ -+#ifdef __KERNEL__ -+#include -+#else -+#include -+#endif -+#include "crypto/aes_cbc.h" -+#include "crypto/cbc_generic.h" -+ -+/* returns bool success */ -+int AES_set_key(aes_context *aes_ctx, const u_int8_t *key, int keysize) { -+ aes_set_key(aes_ctx, key, keysize, 0); -+ return 1; -+} -+CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, u_int8_t *, aes_encrypt, aes_decrypt); -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.1 2004/04/06 02:48:12 mcr -+ * pullup of AES cipher from alg-branch. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/aes/aes_xcbc_mac.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,67 @@ -+#ifdef __KERNEL__ -+#include -+#include -+#define DEBUG(x) -+#else -+#include -+#include -+#define DEBUG(x) x -+#endif -+ -+#include "crypto/aes.h" -+#include "crypto/aes_xcbc_mac.h" -+ -+int AES_xcbc_mac_set_key(aes_context_mac *ctxm, const u_int8_t *key, int keylen) -+{ -+ int ret=1; -+ aes_block kn[3] = { -+ { 0x01010101, 0x01010101, 0x01010101, 0x01010101 }, -+ { 0x02020202, 0x02020202, 0x02020202, 0x02020202 }, -+ { 0x03030303, 0x03030303, 0x03030303, 0x03030303 }, -+ }; -+ aes_set_key(&ctxm->ctx_k1, key, keylen, 0); -+ aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[0], (u_int8_t *) kn[0]); -+ aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[1], (u_int8_t *) ctxm->k2); -+ aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[2], (u_int8_t *) ctxm->k3); -+ aes_set_key(&ctxm->ctx_k1, (u_int8_t *) kn[0], 16, 0); -+ return ret; -+} -+static void do_pad_xor(u_int8_t *out, const u_int8_t *in, int len) { -+ int pos=0; -+ for (pos=1; pos <= 16; pos++, in++, out++) { -+ if (pos <= len) -+ *out ^= *in; -+ if (pos > len) { -+ DEBUG(printf("put 0x80 at pos=%d\n", pos)); -+ *out ^= 0x80; -+ break; -+ } -+ } -+} -+static void xor_block(aes_block res, const aes_block op) { -+ res[0] ^= op[0]; -+ res[1] ^= op[1]; -+ res[2] ^= op[2]; -+ res[3] ^= op[3]; -+} -+int AES_xcbc_mac_hash(const aes_context_mac *ctxm, const u_int8_t * in, int ilen, u_int8_t hash[16]) { -+ int ret=ilen; -+ u_int32_t out[4] = { 0, 0, 0, 0 }; -+ for (; ilen > 16 ; ilen-=16) { -+ xor_block(out, (const u_int32_t*) &in[0]); -+ aes_encrypt(&ctxm->ctx_k1, in, (u_int8_t *)&out[0]); -+ in+=16; -+ } -+ do_pad_xor((u_int8_t *)&out, in, ilen); -+ if (ilen==16) { -+ DEBUG(printf("using k3\n")); -+ xor_block(out, ctxm->k3); -+ } -+ else -+ { -+ DEBUG(printf("using k2\n")); -+ xor_block(out, ctxm->k2); -+ } -+ aes_encrypt(&ctxm->ctx_k1, (u_int8_t *)out, hash); -+ return ret; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/aes/test_main.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,41 @@ -+#include -+#include -+#include -+#include "aes_cbc.h" -+#define AES_BLOCK_SIZE 16 -+#define KEY_SIZE 128 /* bits */ -+#define KEY "1234567890123456" -+#define STR "hola guaso como estaisss ... 012" -+#define STRSZ (sizeof(STR)-1) -+ -+#define EMT_AESCBC_BLKLEN AES_BLOCK_SIZE -+#define AES_CONTEXT_T aes_context -+#define EMT_ESPAES_KEY_SZ 16 -+int pretty_print(const unsigned char *buf, int count) { -+ int i=0; -+ for (;i -+#include -+#include -+#include "aes.h" -+#include "aes_xcbc_mac.h" -+#define STR "Hola guasssso c|mo estais ...012" -+void print_hash(const __u8 *hash) { -+ printf("%08x %08x %08x %08x\n", -+ *(__u32*)(&hash[0]), -+ *(__u32*)(&hash[4]), -+ *(__u32*)(&hash[8]), -+ *(__u32*)(&hash[12])); -+} -+int main(int argc, char *argv[]) { -+ aes_block key= { 0xdeadbeef, 0xceedcaca, 0xcafebabe, 0xff010204 }; -+ __u8 hash[16]; -+ char *str = argv[1]; -+ aes_context_mac ctx; -+ if (str==NULL) { -+ fprintf(stderr, "pasame el str\n"); -+ return 255; -+ } -+ AES_xcbc_mac_set_key(&ctx, (__u8 *)&key, sizeof(key)); -+ AES_xcbc_mac_hash(&ctx, str, strlen(str), hash); -+ print_hash(hash); -+ str[2]='x'; -+ AES_xcbc_mac_hash(&ctx, str, strlen(str), hash); -+ print_hash(hash); -+ return 0; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/COPYRIGHT Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,50 @@ -+Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+All rights reserved. -+ -+This package is an DES implementation written by Eric Young (eay@cryptsoft.com). -+The implementation was written so as to conform with MIT's libdes. -+ -+This library is free for commercial and non-commercial use as long as -+the following conditions are aheared to. The following conditions -+apply to all code found in this distribution. -+ -+Copyright remains Eric Young's, and as such any Copyright notices in -+the code are not to be removed. -+If this package is used in a product, Eric Young should be given attribution -+as the author of that the SSL library. This can be in the form of a textual -+message at program startup or in documentation (online or textual) provided -+with the package. -+ -+Redistribution and use in source and binary forms, with or without -+modification, are permitted provided that the following conditions -+are met: -+1. Redistributions of source code must retain the copyright -+ notice, this list of conditions and the following disclaimer. -+2. Redistributions in binary form must reproduce the above copyright -+ notice, this list of conditions and the following disclaimer in the -+ documentation and/or other materials provided with the distribution. -+3. All advertising materials mentioning features or use of this software -+ must display the following acknowledgement: -+ This product includes software developed by Eric Young (eay@cryptsoft.com) -+ -+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+SUCH DAMAGE. -+ -+The license and distribution terms for any publically available version or -+derivative of this code cannot be changed. i.e. this code cannot simply be -+copied and put under another distrubution license -+[including the GNU Public License.] -+ -+The reason behind this being stated in this direct manner is past -+experience in code simply being copied and the attribution removed -+from it and then being distributed as part of other packages. This -+implementation was a non-trivial and unpaid effort. ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/INSTALL Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,69 @@ -+Check the CC and CFLAGS lines in the makefile -+ -+If your C library does not support the times(3) function, change the -+#define TIMES to -+#undef TIMES in speed.c -+If it does, check the HZ value for the times(3) function. -+If your system does not define CLK_TCK it will be assumed to -+be 100.0. -+ -+If possible use gcc v 2.7.? -+Turn on the maximum optimising (normally '-O3 -fomit-frame-pointer' for gcc) -+In recent times, some system compilers give better performace. -+ -+type 'make' -+ -+run './destest' to check things are ok. -+run './rpw' to check the tty code for reading passwords works. -+run './speed' to see how fast those optimisations make the library run :-) -+run './des_opts' to determin the best compile time options. -+ -+The output from des_opts should be put in the makefile options and des_enc.c -+should be rebuilt. For 64 bit computers, do not use the DES_PTR option. -+For the DEC Alpha, edit des.h and change DES_LONG to 'unsigned int' -+and then you can use the 'DES_PTR' option. -+ -+The file options.txt has the options listed for best speed on quite a -+few systems. Look and the options (UNROLL, PTR, RISC2 etc) and then -+turn on the relevent option in the Makefile -+ -+There are some special Makefile targets that make life easier. -+make cc - standard cc build -+make gcc - standard gcc build -+make x86-elf - x86 assembler (elf), linux-elf. -+make x86-out - x86 assembler (a.out), FreeBSD -+make x86-solaris- x86 assembler -+make x86-bsdi - x86 assembler (a.out with primative assembler). -+ -+If at all possible use the assembler (for Windows NT/95, use -+asm/win32.obj to link with). The x86 assembler is very very fast. -+ -+A make install will by default install -+libdes.a in /usr/local/lib/libdes.a -+des in /usr/local/bin/des -+des_crypt.man in /usr/local/man/man3/des_crypt.3 -+des.man in /usr/local/man/man1/des.1 -+des.h in /usr/include/des.h -+ -+des(1) should be compatible with sunOS's but I have been unable to -+test it. -+ -+These routines should compile on MSDOS, most 32bit and 64bit version -+of Unix (BSD and SYSV) and VMS, without modification. -+The only problems should be #include files that are in the wrong places. -+ -+These routines can be compiled under MSDOS. -+I have successfully encrypted files using des(1) under MSDOS and then -+decrypted the files on a SparcStation. -+I have been able to compile and test the routines with -+Microsoft C v 5.1 and Turbo C v 2.0. -+The code in this library is in no way optimised for the 16bit -+operation of MSDOS. -+ -+When building for glibc, ignore all of the above and just unpack into -+glibc-1.??/des and then gmake as per normal. -+ -+As a final note on performace. Certain CPUs like sparcs and Alpha often give -+a %10 speed difference depending on the link order. It is rather anoying -+when one program reports 'x' DES encrypts a second and another reports -+'x*0.9' the speed. ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/Makefile.objs Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,20 @@ -+obj-$(CONFIG_IPSEC_ENC_3DES) += cbc_enc.o -+#obj-$(CONFIG_IPSEC_ENC_3DES) += des_opts.o -+obj-$(CONFIG_IPSEC_ENC_3DES) += ecb_enc.o -+#obj-$(CONFIG_IPSEC_ENC_3DES) += fcrypt.o -+obj-$(CONFIG_IPSEC_ENC_3DES) += set_key.o -+ -+ifeq ($(strip ${SUBARCH}),) -+SUBARCH:=${ARCH} -+endif -+ -+ifeq (${SUBARCH},i386) -+obj-$(CONFIG_IPSEC_ENC_3DES) += dx86unix.o -+else -+obj-$(CONFIG_IPSEC_ENC_3DES) += des_enc.o -+endif -+ -+ -+ -+ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/README Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,54 @@ -+ -+ libdes, Version 4.01 10-Jan-97 -+ -+ Copyright (c) 1997, Eric Young -+ All rights reserved. -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms specified in COPYRIGHT. -+ -+-- -+The primary ftp site for this library is -+ftp://ftp.psy.uq.oz.au/pub/Crypto/DES/libdes-x.xx.tar.gz -+libdes is now also shipped with SSLeay. Primary ftp site of -+ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL/SSLeay-x.x.x.tar.gz -+ -+The best way to build this library is to build it as part of SSLeay. -+ -+This kit builds a DES encryption library and a DES encryption program. -+It supports ecb, cbc, ofb, cfb, triple ecb, triple cbc, triple ofb, -+triple cfb, desx, and MIT's pcbc encryption modes and also has a fast -+implementation of crypt(3). -+It contains support routines to read keys from a terminal, -+generate a random key, generate a key from an arbitrary length string, -+read/write encrypted data from/to a file descriptor. -+ -+The implementation was written so as to conform with the manual entry -+for the des_crypt(3) library routines from MIT's project Athena. -+ -+destest should be run after compilation to test the des routines. -+rpw should be run after compilation to test the read password routines. -+The des program is a replacement for the sun des command. I believe it -+conforms to the sun version. -+ -+The Imakefile is setup for use in the kerberos distribution. -+ -+These routines are best compiled with gcc or any other good -+optimising compiler. -+Just turn you optimiser up to the highest settings and run destest -+after the build to make sure everything works. -+ -+I believe these routines are close to the fastest and most portable DES -+routines that use small lookup tables (4.5k) that are publicly available. -+The fcrypt routine is faster than ufc's fcrypt (when compiling with -+gcc2 -O2) on the sparc 2 (1410 vs 1270) but is not so good on other machines -+(on a sun3/260 168 vs 336). It is a function of CPU on chip cache size. -+[ 10-Jan-97 and a function of an incorrect speed testing program in -+ ufc which gave much better test figures that reality ]. -+ -+It is worth noting that on sparc and Alpha CPUs, performance of the DES -+library can vary by upto %10 due to the positioning of files after application -+linkage. -+ -+Eric Young (eay@cryptsoft.com) -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/README.freeswan Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,33 @@ -+The only changes the FreeS/WAN project has made to libdes-lite 4.04b are: -+ -+We #ifdef-ed the declaration of DES_LONG in des.h, so it's more efficient -+on the Alpha, instead of just noting the issue in a comment. -+ -+We #ifdef-ed out the des_options() function in ecb_enc.c, because we don't -+use it, and its call to sprintf() can cause subtle difficulties when KLIPS -+is built as a module (depending on details of Linux configuration options). -+ -+We changed some instances of CC=$(CC) in the Makefile to CC='$(CC)' to make -+it cope better with Linux kernel Makefile stupidities, and took out an -+explicit CC=gcc (unwise on systems with strange compilers). -+ -+We deleted some references to and , and a declaration -+of one function found only in the full libdes (not in libdes-lite), to -+avoid dragging in bits of stdio/stdlib unnecessarily. (Our thanks to Hans -+Schultz for spotting this and pointing out the fixes.) -+ -+We deleted a couple of .obj files in the asm subdirectory, which appear to -+have been included in the original library by accident. -+ -+We have added an include of our Makefile.inc file, to permit overriding -+things like choice of compiler (although the libdes Makefile would -+probably need some work to make this effective). -+ -+ -+ -+Note that Eric Young is no longer at the email address listed in these -+files, and is (alas) no longer working on free crypto software. -+ -+ -+ -+This file is RCSID $Id$ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/VERSION Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,406 @@ -+Version 4.04 -+ Fixed a few tests in destest. Also added x86 assember for -+ des_ncbc_encrypt() which is the standard cbc mode function. -+ This makes a very very large performace difference. -+ Ariel Glenn ariel@columbia.edu reports that the terminal -+ 'turn echo off' can return (errno == EINVAL) under solaris -+ when redirection is used. So I now catch that as well as ENOTTY. -+ -+ -+Version 4.03 -+ Left a static out of enc_write.c, which caused to buffer to be -+ continiously malloc()ed. Does anyone use these functions? I keep -+ on feeling like removing them since I only had these in there -+ for a version of kerberised login. Anyway, this was pointed out -+ by Theo de Raadt -+ The 'n' bit ofb code was wrong, it was not shifting the shift -+ register. It worked correctly for n == 64. Thanks to -+ Gigi Ankeny for pointing this one out. -+ -+Version 4.02 -+ I was doing 'if (memcmp(weak_keys[i],key,sizeof(key)) == 0)' -+ when checking for weak keys which is wrong :-(, pointed out by -+ Markus F.X.J. Oberhumer . -+ -+Version 4.01 -+ Even faster inner loop in the DES assembler for x86 and a modification -+ for IP/FP which is faster on x86. Both of these changes are -+ from Svend Olaf Mikkelsen . His -+ changes make the assembler run %40 faster on a pentium. This is just -+ a case of getting the instruction sequence 'just right'. -+ All credit to 'Svend' :-) -+ Quite a few special x86 'make' targets. -+ A libdes-l (lite) distribution. -+ -+Version 4.00 -+ After a bit of a pause, I'll up the major version number since this -+ is mostly a performace release. I've added x86 assembler and -+ added more options for performance. A %28 speedup for gcc -+ on a pentium and the assembler is a %50 speedup. -+ MIPS CPU's, sparc and Alpha are the main CPU's with speedups. -+ Run des_opts to work out which options should be used. -+ DES_RISC1/DES_RISC2 use alternative inner loops which use -+ more registers but should give speedups on any CPU that does -+ dual issue (pentium). DES_UNROLL unrolls the inner loop, -+ which costs in code size. -+ -+Version 3.26 -+ I've finally removed one of the shifts in D_ENCRYPT. This -+ meant I've changed the des_SPtrans table (spr.h), the set_key() -+ function and some things in des_enc.c. This has definitly -+ made things faster :-). I've known about this one for some -+ time but I've been too lazy to follow it up :-). -+ Noticed that in the D_ENCRYPT() macro, we can just do L^=(..)^(..)^.. -+ instead of L^=((..)|(..)|(..).. This should save a register at -+ least. -+ Assember for x86. The file to replace is des_enc.c, which is replaced -+ by one of the assembler files found in asm. Look at des/asm/readme -+ for more info. -+ -+ /* Modification to fcrypt so it can be compiled to support -+ HPUX 10.x's long password format, define -DLONGCRYPT to use this. -+ Thanks to Jens Kupferschmidt . */ -+ -+ SIGWINCH case put in des_read_passwd() so the function does not -+ 'exit' if this function is recieved. -+ -+Version 3.25 17/07/96 -+ Modified read_pwd.c so that stdin can be read if not a tty. -+ Thanks to Jeff Barber for the patches. -+ des_init_random_number_generator() shortened due to VMS linker -+ limits. -+ Added RSA's DESX cbc mode. It is a form of cbc encryption, with 2 -+ 8 byte quantites xored before and after encryption. -+ des_xcbc_encryption() - the name is funny to preserve the des_ -+ prefix on all functions. -+ -+Version 3.24 20/04/96 -+ The DES_PTR macro option checked and used by SSLeay configuration -+ -+Version 3.23 11/04/96 -+ Added DES_LONG. If defined to 'unsigned int' on the DEC Alpha, -+ it gives a %20 speedup :-) -+ Fixed the problem with des.pl under perl5. The patches were -+ sent by Ed Kubaitis (ejk@uiuc.edu). -+ if fcrypt.c, changed values to handle illegal salt values the way -+ normal crypt() implementations do. Some programs apparently use -+ them :-(. The patch was sent by Bjorn Gronvall -+ -+Version 3.22 29/11/95 -+ Bug in des(1), an error with the uuencoding stuff when the -+ 'data' is small, thanks to Geoff Keating -+ for the patch. -+ -+Version 3.21 22/11/95 -+ After some emailing back and forth with -+ Colin Plumb , I've tweaked a few things -+ and in a future version I will probably put in some of the -+ optimisation he suggested for use with the DES_USE_PTR option. -+ Extra routines from Mark Murray for use in -+ freeBSD. They mostly involve random number generation for use -+ with kerberos. They involve evil machine specific system calls -+ etc so I would normally suggest pushing this stuff into the -+ application and/or using RAND_seed()/RAND_bytes() if you are -+ using this DES library as part of SSLeay. -+ Redone the read_pw() function so that it is cleaner and -+ supports termios, thanks to Sameer Parekh -+ for the initial patches for this. -+ Renamed 3ecb_encrypt() to ecb3_encrypt(). This has been -+ done just to make things more consistent. -+ I have also now added triple DES versions of cfb and ofb. -+ -+Version 3.20 -+ Damn, Damn, Damn, as pointed out by Mike_Spreitzer.PARC@xerox.com, -+ my des_random_seed() function was only copying 4 bytes of the -+ passed seed into the init structure. It is now fixed to copy 8. -+ My own suggestion is to used something like MD5 :-) -+ -+Version 3.19 -+ While looking at my code one day, I though, why do I keep on -+ calling des_encrypt(in,out,ks,enc) when every function that -+ calls it has in and out the same. So I dropped the 'out' -+ parameter, people should not be using this function. -+ -+Version 3.18 30/08/95 -+ Fixed a few bit with the distribution and the filenames. -+ 3.17 had been munged via a move to DOS and back again. -+ NO CODE CHANGES -+ -+Version 3.17 14/07/95 -+ Fixed ede3 cbc which I had broken in 3.16. I have also -+ removed some unneeded variables in 7-8 of the routines. -+ -+Version 3.16 26/06/95 -+ Added des_encrypt2() which does not use IP/FP, used by triple -+ des routines. Tweaked things a bit elsewhere. %13 speedup on -+ sparc and %6 on a R4400 for ede3 cbc mode. -+ -+Version 3.15 06/06/95 -+ Added des_ncbc_encrypt(), it is des_cbc mode except that it is -+ 'normal' and copies the new iv value back over the top of the -+ passed parameter. -+ CHANGED des_ede3_cbc_encrypt() so that it too now overwrites -+ the iv. THIS WILL BREAK EXISTING CODE, but since this function -+ only new, I feel I can change it, not so with des_cbc_encrypt :-(. -+ I need to update the documentation. -+ -+Version 3.14 31/05/95 -+ New release upon the world, as part of my SSL implementation. -+ New copyright and usage stuff. Basically free for all to use -+ as long as you say it came from me :-) -+ -+Version 3.13 31/05/95 -+ A fix in speed.c, if HZ is not defined, I set it to 100.0 -+ which is reasonable for most unixes except SunOS 4.x. -+ I now have a #ifdef sun but timing for SunOS 4.x looked very -+ good :-(. At my last job where I used SunOS 4.x, it was -+ defined to be 60.0 (look at the old INSTALL documentation), at -+ the last release had it changed to 100.0 since I now work with -+ Solaris2 and SVR4 boxes. -+ Thanks to Rory Chisholm for pointing this -+ one out. -+ -+Version 3.12 08/05/95 -+ As pointed out by The Crypt Keeper , -+ my D_ENCRYPT macro in crypt() had an un-necessary variable. -+ It has been removed. -+ -+Version 3.11 03/05/95 -+ Added des_ede3_cbc_encrypt() which is cbc mode des with 3 keys -+ and one iv. It is a standard and I needed it for my SSL code. -+ It makes more sense to use this for triple DES than -+ 3cbc_encrypt(). I have also added (or should I say tested :-) -+ cfb64_encrypt() which is cfb64 but it will encrypt a partial -+ number of bytes - 3 bytes in 3 bytes out. Again this is for -+ my SSL library, as a form of encryption to use with SSL -+ telnet. -+ -+Version 3.10 22/03/95 -+ Fixed a bug in 3cbc_encrypt() :-(. When making repeated calls -+ to cbc3_encrypt, the 2 iv values that were being returned to -+ be used in the next call were reversed :-(. -+ Many thanks to Bill Wade for pointing out -+ this error. -+ -+Version 3.09 01/02/95 -+ Fixed des_random_key to far more random, it was rather feeble -+ with regards to picking the initial seed. The problem was -+ pointed out by Olaf Kirch . -+ -+Version 3.08 14/12/94 -+ Added Makefile.PL so libdes can be built into perl5. -+ Changed des_locl.h so RAND is always defined. -+ -+Version 3.07 05/12/94 -+ Added GNUmake and stuff so the library can be build with -+ glibc. -+ -+Version 3.06 30/08/94 -+ Added rpc_enc.c which contains _des_crypt. This is for use in -+ secure_rpc v 4.0 -+ Finally fixed the cfb_enc problems. -+ Fixed a few parameter parsing bugs in des (-3 and -b), thanks -+ to Rob McMillan -+ -+Version 3.05 21/04/94 -+ for unsigned long l; gcc does not produce ((l>>34) == 0) -+ This causes bugs in cfb_enc. -+ Thanks to Hadmut Danisch -+ -+Version 3.04 20/04/94 -+ Added a version number to des.c and libdes.a -+ -+Version 3.03 12/01/94 -+ Fixed a bug in non zero iv in 3cbc_enc. -+ -+Version 3.02 29/10/93 -+ I now work in a place where there are 6+ architectures and 14+ -+ OS versions :-). -+ Fixed TERMIO definition so the most sys V boxes will work :-) -+ -+Release upon comp.sources.misc -+Version 3.01 08/10/93 -+ Added des_3cbc_encrypt() -+ -+Version 3.00 07/10/93 -+ Fixed up documentation. -+ quad_cksum definitely compatible with MIT's now. -+ -+Version 2.30 24/08/93 -+ Triple DES now defaults to triple cbc but can do triple ecb -+ with the -b flag. -+ Fixed some MSDOS uuen/uudecoding problems, thanks to -+ Added prototypes. -+ -+Version 2.22 29/06/93 -+ Fixed a bug in des_is_weak_key() which stopped it working :-( -+ thanks to engineering@MorningStar.Com. -+ -+Version 2.21 03/06/93 -+ des(1) with no arguments gives quite a bit of help. -+ Added -c (generate ckecksum) flag to des(1). -+ Added -3 (triple DES) flag to des(1). -+ Added cfb and ofb routines to the library. -+ -+Version 2.20 11/03/93 -+ Added -u (uuencode) flag to des(1). -+ I have been playing with byte order in quad_cksum to make it -+ compatible with MIT's version. All I can say is avid this -+ function if possible since MIT's output is endian dependent. -+ -+Version 2.12 14/10/92 -+ Added MSDOS specific macro in ecb_encrypt which gives a %70 -+ speed up when the code is compiled with turbo C. -+ -+Version 2.11 12/10/92 -+ Speedup in set_key (recoding of PC-1) -+ I now do it in 47 simple operations, down from 60. -+ Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) -+ for motivating me to look for a faster system :-) -+ The speedup is probably less that 1% but it is still 13 -+ instructions less :-). -+ -+Version 2.10 06/10/92 -+ The code now works on the 64bit ETA10 and CRAY without modifications or -+ #defines. I believe the code should work on any machine that -+ defines long, int or short to be 8 bytes long. -+ Thanks to Shabbir J. Safdar (shabby@mentor.cc.purdue.edu) -+ for helping me fix the code to run on 64bit machines (he had -+ access to an ETA10). -+ Thanks also to John Fletcher -+ for testing the routines on a CRAY. -+ read_password.c has been renamed to read_passwd.c -+ string_to_key.c has been renamed to string2key.c -+ -+Version 2.00 14/09/92 -+ Made mods so that the library should work on 64bit CPU's. -+ Removed all my uchar and ulong defs. To many different -+ versions of unix define them in their header files in too many -+ different combinations :-) -+ IRIX - Sillicon Graphics mods (mostly in read_password.c). -+ Thanks to Andrew Daviel (advax@erich.triumf.ca) -+ -+Version 1.99 26/08/92 -+ Fixed a bug or 2 in enc_read.c -+ Fixed a bug in enc_write.c -+ Fixed a pseudo bug in fcrypt.c (very obscure). -+ -+Version 1.98 31/07/92 -+ Support for the ETA10. This is a strange machine that defines -+ longs and ints as 8 bytes and shorts as 4 bytes. -+ Since I do evil things with long * that assume that they are 4 -+ bytes. Look in the Makefile for the option to compile for -+ this machine. quad_cksum appears to have problems but I -+ will don't have the time to fix it right now, and this is not -+ a function that uses DES and so will not effect the main uses -+ of the library. -+ -+Version 1.97 20/05/92 eay -+ Fixed the Imakefile and made some changes to des.h to fix some -+ problems when building this package with Kerberos v 4. -+ -+Version 1.96 18/05/92 eay -+ Fixed a small bug in string_to_key() where problems could -+ occur if des_check_key was set to true and the string -+ generated a weak key. -+ -+Patch2 posted to comp.sources.misc -+Version 1.95 13/05/92 eay -+ Added an alternative version of the D_ENCRYPT macro in -+ ecb_encrypt and fcrypt. Depending on the compiler, one version or the -+ other will be faster. This was inspired by -+ Dana How , and her pointers about doing the -+ *(ulong *)((uchar *)ptr+(value&0xfc)) -+ vs -+ ptr[value&0x3f] -+ to stop the C compiler doing a <<2 to convert the long array index. -+ -+Version 1.94 05/05/92 eay -+ Fixed an incompatibility between my string_to_key and the MIT -+ version. When the key is longer than 8 chars, I was wrapping -+ with a different method. To use the old version, define -+ OLD_STR_TO_KEY in the makefile. Thanks to -+ viktor@newsu.shearson.com (Viktor Dukhovni). -+ -+Version 1.93 28/04/92 eay -+ Fixed the VMS mods so that echo is now turned off in -+ read_password. Thanks again to brennan@coco.cchs.su.oz.AU. -+ MSDOS support added. The routines can be compiled with -+ Turbo C (v2.0) and MSC (v5.1). Make sure MSDOS is defined. -+ -+Patch1 posted to comp.sources.misc -+Version 1.92 13/04/92 eay -+ Changed D_ENCRYPT so that the rotation of R occurs outside of -+ the loop. This required rotating all the longs in sp.h (now -+ called spr.h). Thanks to Richard Outerbridge <71755.204@CompuServe.COM> -+ speed.c has been changed so it will work without SIGALRM. If -+ times(3) is not present it will try to use ftime() instead. -+ -+Version 1.91 08/04/92 eay -+ Added -E/-D options to des(1) so it can use string_to_key. -+ Added SVR4 mods suggested by witr@rwwa.COM -+ Added VMS mods suggested by brennan@coco.cchs.su.oz.AU. If -+ anyone knows how to turn of tty echo in VMS please tell me or -+ implement it yourself :-). -+ Changed FILE *IN/*OUT to *DES_IN/*DES_OUT since it appears VMS -+ does not like IN/OUT being used. -+ -+Libdes posted to comp.sources.misc -+Version 1.9 24/03/92 eay -+ Now contains a fast small crypt replacement. -+ Added des(1) command. -+ Added des_rw_mode so people can use cbc encryption with -+ enc_read and enc_write. -+ -+Version 1.8 15/10/91 eay -+ Bug in cbc_cksum. -+ Many thanks to Keith Reynolds (keithr@sco.COM) for pointing this -+ one out. -+ -+Version 1.7 24/09/91 eay -+ Fixed set_key :-) -+ set_key is 4 times faster and takes less space. -+ There are a few minor changes that could be made. -+ -+Version 1.6 19/09/1991 eay -+ Finally go IP and FP finished. -+ Now I need to fix set_key. -+ This version is quite a bit faster that 1.51 -+ -+Version 1.52 15/06/1991 eay -+ 20% speedup in ecb_encrypt by changing the E bit selection -+ to use 2 32bit words. This also required modification of the -+ sp table. There is still a way to speedup the IP and IP-1 -+ (hints from outer@sq.com) still working on this one :-(. -+ -+Version 1.51 07/06/1991 eay -+ Faster des_encrypt by loop unrolling -+ Fixed bug in quad_cksum.c (thanks to hughes@logos.ucs.indiana.edu) -+ -+Version 1.50 28/05/1991 eay -+ Optimised the code a bit more for the sparc. I have improved the -+ speed of the inner des_encrypt by speeding up the initial and -+ final permutations. -+ -+Version 1.40 23/10/1990 eay -+ Fixed des_random_key, it did not produce a random key :-( -+ -+Version 1.30 2/10/1990 eay -+ Have made des_quad_cksum the same as MIT's, the full package -+ should be compatible with MIT's -+ Have tested on a DECstation 3100 -+ Still need to fix des_set_key (make it faster). -+ Does des_cbc_encrypts at 70.5k/sec on a 3100. -+ -+Version 1.20 18/09/1990 eay -+ Fixed byte order dependencies. -+ Fixed (I hope) all the word alignment problems. -+ Speedup in des_ecb_encrypt. -+ -+Version 1.10 11/09/1990 eay -+ Added des_enc_read and des_enc_write. -+ Still need to fix des_quad_cksum. -+ Still need to document des_enc_read and des_enc_write. -+ -+Version 1.00 27/08/1990 eay -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/crypt586.pl Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,204 @@ -+#!/usr/bin/perl -+# -+# The inner loop instruction sequence and the IP/FP modifications are from -+# Svend Olaf Mikkelsen -+# I've added the stuff needed for crypt() but I've not worried about making -+# things perfect. -+# -+ -+push(@INC,"perlasm","../../perlasm"); -+require "x86asm.pl"; -+ -+&asm_init($ARGV[0],"crypt586.pl"); -+ -+$L="edi"; -+$R="esi"; -+ -+&external_label("des_SPtrans"); -+&fcrypt_body("fcrypt_body"); -+&asm_finish(); -+ -+sub fcrypt_body -+ { -+ local($name,$do_ip)=@_; -+ -+ &function_begin($name,"EXTRN _des_SPtrans:DWORD"); -+ -+ &comment(""); -+ &comment("Load the 2 words"); -+ $ks="ebp"; -+ -+ &xor( $L, $L); -+ &xor( $R, $R); -+ &mov($ks,&wparam(1)); -+ -+ &push(25); # add a variable -+ -+ &set_label("start"); -+ for ($i=0; $i<16; $i+=2) -+ { -+ &comment(""); -+ &comment("Round $i"); -+ &D_ENCRYPT($i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); -+ -+ &comment(""); -+ &comment("Round ".sprintf("%d",$i+1)); -+ &D_ENCRYPT($i+1,$R,$L,($i+1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); -+ } -+ &mov("ebx", &swtmp(0)); -+ &mov("eax", $L); -+ &dec("ebx"); -+ &mov($L, $R); -+ &mov($R, "eax"); -+ &mov(&swtmp(0), "ebx"); -+ &jnz(&label("start")); -+ -+ &comment(""); -+ &comment("FP"); -+ &mov("edx",&wparam(0)); -+ -+ &FP_new($R,$L,"eax",3); -+ &mov(&DWP(0,"edx","",0),"eax"); -+ &mov(&DWP(4,"edx","",0),$L); -+ -+ &pop("ecx"); # remove variable -+ -+ &function_end($name); -+ } -+ -+sub D_ENCRYPT -+ { -+ local($r,$L,$R,$S,$ks,$desSP,$u,$tmp1,$tmp2,$t)=@_; -+ -+ &mov( $u, &wparam(2)); # 2 -+ &mov( $t, $R); -+ &shr( $t, 16); # 1 -+ &mov( $tmp2, &wparam(3)); # 2 -+ &xor( $t, $R); # 1 -+ -+ &and( $u, $t); # 2 -+ &and( $t, $tmp2); # 2 -+ -+ &mov( $tmp1, $u); -+ &shl( $tmp1, 16); # 1 -+ &mov( $tmp2, $t); -+ &shl( $tmp2, 16); # 1 -+ &xor( $u, $tmp1); # 2 -+ &xor( $t, $tmp2); # 2 -+ &mov( $tmp1, &DWP(&n2a($S*4),$ks,"",0)); # 2 -+ &xor( $u, $tmp1); -+ &mov( $tmp2, &DWP(&n2a(($S+1)*4),$ks,"",0)); # 2 -+ &xor( $u, $R); -+ &xor( $t, $R); -+ &xor( $t, $tmp2); -+ -+ &and( $u, "0xfcfcfcfc" ); # 2 -+ &xor( $tmp1, $tmp1); # 1 -+ &and( $t, "0xcfcfcfcf" ); # 2 -+ &xor( $tmp2, $tmp2); -+ &movb( &LB($tmp1), &LB($u) ); -+ &movb( &LB($tmp2), &HB($u) ); -+ &rotr( $t, 4 ); -+ &mov( $ks, &DWP(" $desSP",$tmp1,"",0)); -+ &movb( &LB($tmp1), &LB($t) ); -+ &xor( $L, $ks); -+ &mov( $ks, &DWP("0x200+$desSP",$tmp2,"",0)); -+ &xor( $L, $ks); -+ &movb( &LB($tmp2), &HB($t) ); -+ &shr( $u, 16); -+ &mov( $ks, &DWP("0x100+$desSP",$tmp1,"",0)); -+ &xor( $L, $ks); -+ &movb( &LB($tmp1), &HB($u) ); -+ &shr( $t, 16); -+ &mov( $ks, &DWP("0x300+$desSP",$tmp2,"",0)); -+ &xor( $L, $ks); -+ &mov( $ks, &wparam(1)); -+ &movb( &LB($tmp2), &HB($t) ); -+ &and( $u, "0xff" ); -+ &and( $t, "0xff" ); -+ &mov( $tmp1, &DWP("0x600+$desSP",$tmp1,"",0)); -+ &xor( $L, $tmp1); -+ &mov( $tmp1, &DWP("0x700+$desSP",$tmp2,"",0)); -+ &xor( $L, $tmp1); -+ &mov( $tmp1, &DWP("0x400+$desSP",$u,"",0)); -+ &xor( $L, $tmp1); -+ &mov( $tmp1, &DWP("0x500+$desSP",$t,"",0)); -+ &xor( $L, $tmp1); -+ } -+ -+sub n2a -+ { -+ sprintf("%d",$_[0]); -+ } -+ -+# now has a side affect of rotating $a by $shift -+sub R_PERM_OP -+ { -+ local($a,$b,$tt,$shift,$mask,$last)=@_; -+ -+ &rotl( $a, $shift ) if ($shift != 0); -+ &mov( $tt, $a ); -+ &xor( $a, $b ); -+ &and( $a, $mask ); -+ if ($notlast eq $b) -+ { -+ &xor( $b, $a ); -+ &xor( $tt, $a ); -+ } -+ else -+ { -+ &xor( $tt, $a ); -+ &xor( $b, $a ); -+ } -+ &comment(""); -+ } -+ -+sub IP_new -+ { -+ local($l,$r,$tt,$lr)=@_; -+ -+ &R_PERM_OP($l,$r,$tt, 4,"0xf0f0f0f0",$l); -+ &R_PERM_OP($r,$tt,$l,20,"0xfff0000f",$l); -+ &R_PERM_OP($l,$tt,$r,14,"0x33333333",$r); -+ &R_PERM_OP($tt,$r,$l,22,"0x03fc03fc",$r); -+ &R_PERM_OP($l,$r,$tt, 9,"0xaaaaaaaa",$r); -+ -+ if ($lr != 3) -+ { -+ if (($lr-3) < 0) -+ { &rotr($tt, 3-$lr); } -+ else { &rotl($tt, $lr-3); } -+ } -+ if ($lr != 2) -+ { -+ if (($lr-2) < 0) -+ { &rotr($r, 2-$lr); } -+ else { &rotl($r, $lr-2); } -+ } -+ } -+ -+sub FP_new -+ { -+ local($l,$r,$tt,$lr)=@_; -+ -+ if ($lr != 2) -+ { -+ if (($lr-2) < 0) -+ { &rotl($r, 2-$lr); } -+ else { &rotr($r, $lr-2); } -+ } -+ if ($lr != 3) -+ { -+ if (($lr-3) < 0) -+ { &rotl($l, 3-$lr); } -+ else { &rotr($l, $lr-3); } -+ } -+ -+ &R_PERM_OP($l,$r,$tt, 0,"0xaaaaaaaa",$r); -+ &R_PERM_OP($tt,$r,$l,23,"0x03fc03fc",$r); -+ &R_PERM_OP($l,$r,$tt,10,"0x33333333",$l); -+ &R_PERM_OP($r,$tt,$l,18,"0xfff0000f",$l); -+ &R_PERM_OP($l,$tt,$r,12,"0xf0f0f0f0",$r); -+ &rotr($tt , 4); -+ } -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/des-586.pl Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,251 @@ -+#!/usr/bin/perl -+# -+# The inner loop instruction sequence and the IP/FP modifications are from -+# Svend Olaf Mikkelsen -+# -+ -+push(@INC,"perlasm","../../perlasm"); -+require "x86asm.pl"; -+require "cbc.pl"; -+require "desboth.pl"; -+ -+# base code is in microsft -+# op dest, source -+# format. -+# -+ -+&asm_init($ARGV[0],"des-586.pl"); -+ -+$L="edi"; -+$R="esi"; -+ -+&external_label("des_SPtrans"); -+&des_encrypt("des_encrypt",1); -+&des_encrypt("des_encrypt2",0); -+&des_encrypt3("des_encrypt3",1); -+&des_encrypt3("des_decrypt3",0); -+&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1); -+&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5); -+ -+&asm_finish(); -+ -+sub des_encrypt -+ { -+ local($name,$do_ip)=@_; -+ -+ &function_begin_B($name,"EXTRN _des_SPtrans:DWORD"); -+ -+ &push("esi"); -+ &push("edi"); -+ -+ &comment(""); -+ &comment("Load the 2 words"); -+ $ks="ebp"; -+ -+ if ($do_ip) -+ { -+ &mov($R,&wparam(0)); -+ &xor( "ecx", "ecx" ); -+ -+ &push("ebx"); -+ &push("ebp"); -+ -+ &mov("eax",&DWP(0,$R,"",0)); -+ &mov("ebx",&wparam(2)); # get encrypt flag -+ &mov($L,&DWP(4,$R,"",0)); -+ &comment(""); -+ &comment("IP"); -+ &IP_new("eax",$L,$R,3); -+ } -+ else -+ { -+ &mov("eax",&wparam(0)); -+ &xor( "ecx", "ecx" ); -+ -+ &push("ebx"); -+ &push("ebp"); -+ -+ &mov($R,&DWP(0,"eax","",0)); -+ &mov("ebx",&wparam(2)); # get encrypt flag -+ &rotl($R,3); -+ &mov($L,&DWP(4,"eax","",0)); -+ &rotl($L,3); -+ } -+ -+ &mov( $ks, &wparam(1) ); -+ &cmp("ebx","0"); -+ &je(&label("start_decrypt")); -+ -+ for ($i=0; $i<16; $i+=2) -+ { -+ &comment(""); -+ &comment("Round $i"); -+ &D_ENCRYPT($i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); -+ -+ &comment(""); -+ &comment("Round ".sprintf("%d",$i+1)); -+ &D_ENCRYPT($i+1,$R,$L,($i+1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); -+ } -+ &jmp(&label("end")); -+ -+ &set_label("start_decrypt"); -+ -+ for ($i=15; $i>0; $i-=2) -+ { -+ &comment(""); -+ &comment("Round $i"); -+ &D_ENCRYPT(15-$i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); -+ &comment(""); -+ &comment("Round ".sprintf("%d",$i-1)); -+ &D_ENCRYPT(15-$i+1,$R,$L,($i-1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); -+ } -+ -+ &set_label("end"); -+ -+ if ($do_ip) -+ { -+ &comment(""); -+ &comment("FP"); -+ &mov("edx",&wparam(0)); -+ &FP_new($L,$R,"eax",3); -+ -+ &mov(&DWP(0,"edx","",0),"eax"); -+ &mov(&DWP(4,"edx","",0),$R); -+ } -+ else -+ { -+ &comment(""); -+ &comment("Fixup"); -+ &rotr($L,3); # r -+ &mov("eax",&wparam(0)); -+ &rotr($R,3); # l -+ &mov(&DWP(0,"eax","",0),$L); -+ &mov(&DWP(4,"eax","",0),$R); -+ } -+ -+ &pop("ebp"); -+ &pop("ebx"); -+ &pop("edi"); -+ &pop("esi"); -+ &ret(); -+ -+ &function_end_B($name); -+ } -+ -+sub D_ENCRYPT -+ { -+ local($r,$L,$R,$S,$ks,$desSP,$u,$tmp1,$tmp2,$t)=@_; -+ -+ &mov( $u, &DWP(&n2a($S*4),$ks,"",0)); -+ &xor( $tmp1, $tmp1); -+ &mov( $t, &DWP(&n2a(($S+1)*4),$ks,"",0)); -+ &xor( $u, $R); -+ &xor( $t, $R); -+ &and( $u, "0xfcfcfcfc" ); -+ &and( $t, "0xcfcfcfcf" ); -+ &movb( &LB($tmp1), &LB($u) ); -+ &movb( &LB($tmp2), &HB($u) ); -+ &rotr( $t, 4 ); -+ &mov( $ks, &DWP(" $desSP",$tmp1,"",0)); -+ &movb( &LB($tmp1), &LB($t) ); -+ &xor( $L, $ks); -+ &mov( $ks, &DWP("0x200+$desSP",$tmp2,"",0)); -+ &xor( $L, $ks); ###### -+ &movb( &LB($tmp2), &HB($t) ); -+ &shr( $u, 16); -+ &mov( $ks, &DWP("0x100+$desSP",$tmp1,"",0)); -+ &xor( $L, $ks); ###### -+ &movb( &LB($tmp1), &HB($u) ); -+ &shr( $t, 16); -+ &mov( $ks, &DWP("0x300+$desSP",$tmp2,"",0)); -+ &xor( $L, $ks); -+ &mov( $ks, &wparam(1) ); -+ &movb( &LB($tmp2), &HB($t) ); -+ &and( $u, "0xff" ); -+ &and( $t, "0xff" ); -+ &mov( $tmp1, &DWP("0x600+$desSP",$tmp1,"",0)); -+ &xor( $L, $tmp1); -+ &mov( $tmp1, &DWP("0x700+$desSP",$tmp2,"",0)); -+ &xor( $L, $tmp1); -+ &mov( $tmp1, &DWP("0x400+$desSP",$u,"",0)); -+ &xor( $L, $tmp1); -+ &mov( $tmp1, &DWP("0x500+$desSP",$t,"",0)); -+ &xor( $L, $tmp1); -+ } -+ -+sub n2a -+ { -+ sprintf("%d",$_[0]); -+ } -+ -+# now has a side affect of rotating $a by $shift -+sub R_PERM_OP -+ { -+ local($a,$b,$tt,$shift,$mask,$last)=@_; -+ -+ &rotl( $a, $shift ) if ($shift != 0); -+ &mov( $tt, $a ); -+ &xor( $a, $b ); -+ &and( $a, $mask ); -+ if (!$last eq $b) -+ { -+ &xor( $b, $a ); -+ &xor( $tt, $a ); -+ } -+ else -+ { -+ &xor( $tt, $a ); -+ &xor( $b, $a ); -+ } -+ &comment(""); -+ } -+ -+sub IP_new -+ { -+ local($l,$r,$tt,$lr)=@_; -+ -+ &R_PERM_OP($l,$r,$tt, 4,"0xf0f0f0f0",$l); -+ &R_PERM_OP($r,$tt,$l,20,"0xfff0000f",$l); -+ &R_PERM_OP($l,$tt,$r,14,"0x33333333",$r); -+ &R_PERM_OP($tt,$r,$l,22,"0x03fc03fc",$r); -+ &R_PERM_OP($l,$r,$tt, 9,"0xaaaaaaaa",$r); -+ -+ if ($lr != 3) -+ { -+ if (($lr-3) < 0) -+ { &rotr($tt, 3-$lr); } -+ else { &rotl($tt, $lr-3); } -+ } -+ if ($lr != 2) -+ { -+ if (($lr-2) < 0) -+ { &rotr($r, 2-$lr); } -+ else { &rotl($r, $lr-2); } -+ } -+ } -+ -+sub FP_new -+ { -+ local($l,$r,$tt,$lr)=@_; -+ -+ if ($lr != 2) -+ { -+ if (($lr-2) < 0) -+ { &rotl($r, 2-$lr); } -+ else { &rotr($r, $lr-2); } -+ } -+ if ($lr != 3) -+ { -+ if (($lr-3) < 0) -+ { &rotl($l, 3-$lr); } -+ else { &rotr($l, $lr-3); } -+ } -+ -+ &R_PERM_OP($l,$r,$tt, 0,"0xaaaaaaaa",$r); -+ &R_PERM_OP($tt,$r,$l,23,"0x03fc03fc",$r); -+ &R_PERM_OP($l,$r,$tt,10,"0x33333333",$l); -+ &R_PERM_OP($r,$tt,$l,18,"0xfff0000f",$l); -+ &R_PERM_OP($l,$tt,$r,12,"0xf0f0f0f0",$r); -+ &rotr($tt , 4); -+ } -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/des686.pl Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,230 @@ -+#!/usr/bin/perl -+ -+$prog="des686.pl"; -+ -+# base code is in microsft -+# op dest, source -+# format. -+# -+ -+# WILL NOT WORK ANYMORE WITH desboth.pl -+require "desboth.pl"; -+ -+if ( ($ARGV[0] eq "elf")) -+ { require "x86unix.pl"; } -+elsif ( ($ARGV[0] eq "a.out")) -+ { $aout=1; require "x86unix.pl"; } -+elsif ( ($ARGV[0] eq "sol")) -+ { $sol=1; require "x86unix.pl"; } -+elsif ( ($ARGV[0] eq "cpp")) -+ { $cpp=1; require "x86unix.pl"; } -+elsif ( ($ARGV[0] eq "win32")) -+ { require "x86ms.pl"; } -+else -+ { -+ print STDERR <<"EOF"; -+Pick one target type from -+ elf - linux, FreeBSD etc -+ a.out - old linux -+ sol - x86 solaris -+ cpp - format so x86unix.cpp can be used -+ win32 - Windows 95/Windows NT -+EOF -+ exit(1); -+ } -+ -+&comment("Don't even think of reading this code"); -+&comment("It was automatically generated by $prog"); -+&comment("Which is a perl program used to generate the x86 assember for"); -+&comment("any of elf, a.out, Win32, or Solaris"); -+&comment("It can be found in SSLeay 0.6.5+ or in libdes 3.26+"); -+&comment("eric "); -+&comment(""); -+ -+&file("dx86xxxx"); -+ -+$L="edi"; -+$R="esi"; -+ -+&des_encrypt("des_encrypt",1); -+&des_encrypt("des_encrypt2",0); -+ -+&des_encrypt3("des_encrypt3",1); -+&des_encrypt3("des_decrypt3",0); -+ -+&file_end(); -+ -+sub des_encrypt -+ { -+ local($name,$do_ip)=@_; -+ -+ &function_begin($name,"EXTRN _des_SPtrans:DWORD"); -+ -+ &comment(""); -+ &comment("Load the 2 words"); -+ &mov("eax",&wparam(0)); -+ &mov($L,&DWP(0,"eax","",0)); -+ &mov($R,&DWP(4,"eax","",0)); -+ -+ $ksp=&wparam(1); -+ -+ if ($do_ip) -+ { -+ &comment(""); -+ &comment("IP"); -+ &IP_new($L,$R,"eax"); -+ } -+ -+ &comment(""); -+ &comment("fixup rotate"); -+ &rotl($R,3); -+ &rotl($L,3); -+ &exch($L,$R); -+ -+ &comment(""); -+ &comment("load counter, key_schedule and enc flag"); -+ &mov("eax",&wparam(2)); # get encrypt flag -+ &mov("ebp",&wparam(1)); # get ks -+ &cmp("eax","0"); -+ &je(&label("start_decrypt")); -+ -+ # encrypting part -+ -+ for ($i=0; $i<16; $i+=2) -+ { -+ &comment(""); -+ &comment("Round $i"); -+ &D_ENCRYPT($L,$R,$i*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); -+ -+ &comment(""); -+ &comment("Round ".sprintf("%d",$i+1)); -+ &D_ENCRYPT($R,$L,($i+1)*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); -+ } -+ &jmp(&label("end")); -+ -+ &set_label("start_decrypt"); -+ -+ for ($i=15; $i>0; $i-=2) -+ { -+ &comment(""); -+ &comment("Round $i"); -+ &D_ENCRYPT($L,$R,$i*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); -+ &comment(""); -+ &comment("Round ".sprintf("%d",$i-1)); -+ &D_ENCRYPT($R,$L,($i-1)*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); -+ } -+ -+ &set_label("end"); -+ -+ &comment(""); -+ &comment("Fixup"); -+ &rotr($L,3); # r -+ &rotr($R,3); # l -+ -+ if ($do_ip) -+ { -+ &comment(""); -+ &comment("FP"); -+ &FP_new($R,$L,"eax"); -+ } -+ -+ &mov("eax",&wparam(0)); -+ &mov(&DWP(0,"eax","",0),$L); -+ &mov(&DWP(4,"eax","",0),$R); -+ -+ &function_end($name); -+ } -+ -+ -+# The logic is to load R into 2 registers and operate on both at the same time. -+# We also load the 2 R's into 2 more registers so we can do the 'move word down a byte' -+# while also masking the other copy and doing a lookup. We then also accumulate the -+# L value in 2 registers then combine them at the end. -+sub D_ENCRYPT -+ { -+ local($L,$R,$S,$ks,$desSP,$u,$t,$tmp1,$tmp2,$tmp3)=@_; -+ -+ &mov( $u, &DWP(&n2a($S*4),$ks,"",0)); -+ &mov( $t, &DWP(&n2a(($S+1)*4),$ks,"",0)); -+ &xor( $u, $R ); -+ &xor( $t, $R ); -+ &rotr( $t, 4 ); -+ -+ # the numbers at the end of the line are origional instruction order -+ &mov( $tmp2, $u ); # 1 2 -+ &mov( $tmp1, $t ); # 1 1 -+ &and( $tmp2, "0xfc" ); # 1 4 -+ &and( $tmp1, "0xfc" ); # 1 3 -+ &shr( $t, 8 ); # 1 5 -+ &xor( $L, &DWP("0x100+$desSP",$tmp1,"",0)); # 1 7 -+ &shr( $u, 8 ); # 1 6 -+ &mov( $tmp1, &DWP(" $desSP",$tmp2,"",0)); # 1 8 -+ -+ &mov( $tmp2, $u ); # 2 2 -+ &xor( $L, $tmp1 ); # 1 9 -+ &and( $tmp2, "0xfc" ); # 2 4 -+ &mov( $tmp1, $t ); # 2 1 -+ &and( $tmp1, "0xfc" ); # 2 3 -+ &shr( $t, 8 ); # 2 5 -+ &xor( $L, &DWP("0x300+$desSP",$tmp1,"",0)); # 2 7 -+ &shr( $u, 8 ); # 2 6 -+ &mov( $tmp1, &DWP("0x200+$desSP",$tmp2,"",0)); # 2 8 -+ &mov( $tmp2, $u ); # 3 2 -+ -+ &xor( $L, $tmp1 ); # 2 9 -+ &and( $tmp2, "0xfc" ); # 3 4 -+ -+ &mov( $tmp1, $t ); # 3 1 -+ &shr( $u, 8 ); # 3 6 -+ &and( $tmp1, "0xfc" ); # 3 3 -+ &shr( $t, 8 ); # 3 5 -+ &xor( $L, &DWP("0x500+$desSP",$tmp1,"",0)); # 3 7 -+ &mov( $tmp1, &DWP("0x400+$desSP",$tmp2,"",0)); # 3 8 -+ -+ &and( $t, "0xfc" ); # 4 1 -+ &xor( $L, $tmp1 ); # 3 9 -+ -+ &and( $u, "0xfc" ); # 4 2 -+ &xor( $L, &DWP("0x700+$desSP",$t,"",0)); # 4 3 -+ &xor( $L, &DWP("0x600+$desSP",$u,"",0)); # 4 4 -+ } -+ -+sub PERM_OP -+ { -+ local($a,$b,$tt,$shift,$mask)=@_; -+ -+ &mov( $tt, $a ); -+ &shr( $tt, $shift ); -+ &xor( $tt, $b ); -+ &and( $tt, $mask ); -+ &xor( $b, $tt ); -+ &shl( $tt, $shift ); -+ &xor( $a, $tt ); -+ } -+ -+sub IP_new -+ { -+ local($l,$r,$tt)=@_; -+ -+ &PERM_OP($r,$l,$tt, 4,"0x0f0f0f0f"); -+ &PERM_OP($l,$r,$tt,16,"0x0000ffff"); -+ &PERM_OP($r,$l,$tt, 2,"0x33333333"); -+ &PERM_OP($l,$r,$tt, 8,"0x00ff00ff"); -+ &PERM_OP($r,$l,$tt, 1,"0x55555555"); -+ } -+ -+sub FP_new -+ { -+ local($l,$r,$tt)=@_; -+ -+ &PERM_OP($l,$r,$tt, 1,"0x55555555"); -+ &PERM_OP($r,$l,$tt, 8,"0x00ff00ff"); -+ &PERM_OP($l,$r,$tt, 2,"0x33333333"); -+ &PERM_OP($r,$l,$tt,16,"0x0000ffff"); -+ &PERM_OP($l,$r,$tt, 4,"0x0f0f0f0f"); -+ } -+ -+sub n2a -+ { -+ sprintf("%d",$_[0]); -+ } ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/desboth.pl Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,79 @@ -+#!/usr/bin/perl -+ -+$L="edi"; -+$R="esi"; -+ -+sub des_encrypt3 -+ { -+ local($name,$enc)=@_; -+ -+ &function_begin_B($name,""); -+ &push("ebx"); -+ &mov("ebx",&wparam(0)); -+ -+ &push("ebp"); -+ &push("esi"); -+ -+ &push("edi"); -+ -+ &comment(""); -+ &comment("Load the data words"); -+ &mov($L,&DWP(0,"ebx","",0)); -+ &mov($R,&DWP(4,"ebx","",0)); -+ &stack_push(3); -+ -+ &comment(""); -+ &comment("IP"); -+ &IP_new($L,$R,"edx",0); -+ -+ # put them back -+ -+ if ($enc) -+ { -+ &mov(&DWP(4,"ebx","",0),$R); -+ &mov("eax",&wparam(1)); -+ &mov(&DWP(0,"ebx","",0),"edx"); -+ &mov("edi",&wparam(2)); -+ &mov("esi",&wparam(3)); -+ } -+ else -+ { -+ &mov(&DWP(4,"ebx","",0),$R); -+ &mov("esi",&wparam(1)); -+ &mov(&DWP(0,"ebx","",0),"edx"); -+ &mov("edi",&wparam(2)); -+ &mov("eax",&wparam(3)); -+ } -+ &mov(&swtmp(2), (($enc)?"1":"0")); -+ &mov(&swtmp(1), "eax"); -+ &mov(&swtmp(0), "ebx"); -+ &call("des_encrypt2"); -+ &mov(&swtmp(2), (($enc)?"0":"1")); -+ &mov(&swtmp(1), "edi"); -+ &mov(&swtmp(0), "ebx"); -+ &call("des_encrypt2"); -+ &mov(&swtmp(2), (($enc)?"1":"0")); -+ &mov(&swtmp(1), "esi"); -+ &mov(&swtmp(0), "ebx"); -+ &call("des_encrypt2"); -+ -+ &stack_pop(3); -+ &mov($L,&DWP(0,"ebx","",0)); -+ &mov($R,&DWP(4,"ebx","",0)); -+ -+ &comment(""); -+ &comment("FP"); -+ &FP_new($L,$R,"eax",0); -+ -+ &mov(&DWP(0,"ebx","",0),"eax"); -+ &mov(&DWP(4,"ebx","",0),$R); -+ -+ &pop("edi"); -+ &pop("esi"); -+ &pop("ebp"); -+ &pop("ebx"); -+ &ret(); -+ &function_end_B($name); -+ } -+ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/perlasm/cbc.pl Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,342 @@ -+#!/usr/bin/perl -+ -+# void des_ncbc_encrypt(input, output, length, schedule, ivec, enc) -+# des_cblock (*input); -+# des_cblock (*output); -+# long length; -+# des_key_schedule schedule; -+# des_cblock (*ivec); -+# int enc; -+# -+# calls -+# des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); -+# -+ -+#&cbc("des_ncbc_encrypt","des_encrypt",0); -+#&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt", -+# 1,4,5,3,5,-1); -+#&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt", -+# 0,4,5,3,5,-1); -+#&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3", -+# 0,6,7,3,4,5); -+# -+# When doing a cipher that needs bigendian order, -+# for encrypt, the iv is kept in bigendian form, -+# while for decrypt, it is kept in little endian. -+sub cbc -+ { -+ local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_; -+ # name is the function name -+ # enc_func and dec_func and the functions to call for encrypt/decrypt -+ # swap is true if byte order needs to be reversed -+ # iv_off is parameter number for the iv -+ # enc_off is parameter number for the encrypt/decrypt flag -+ # p1,p2,p3 are the offsets for parameters to be passed to the -+ # underlying calls. -+ -+ &function_begin_B($name,""); -+ &comment(""); -+ -+ $in="esi"; -+ $out="edi"; -+ $count="ebp"; -+ -+ &push("ebp"); -+ &push("ebx"); -+ &push("esi"); -+ &push("edi"); -+ -+ $data_off=4; -+ $data_off+=4 if ($p1 > 0); -+ $data_off+=4 if ($p2 > 0); -+ $data_off+=4 if ($p3 > 0); -+ -+ &mov($count, &wparam(2)); # length -+ -+ &comment("getting iv ptr from parameter $iv_off"); -+ &mov("ebx", &wparam($iv_off)); # Get iv ptr -+ -+ &mov($in, &DWP(0,"ebx","",0));# iv[0] -+ &mov($out, &DWP(4,"ebx","",0));# iv[1] -+ -+ &push($out); -+ &push($in); -+ &push($out); # used in decrypt for iv[1] -+ &push($in); # used in decrypt for iv[0] -+ -+ &mov("ebx", "esp"); # This is the address of tin[2] -+ -+ &mov($in, &wparam(0)); # in -+ &mov($out, &wparam(1)); # out -+ -+ # We have loaded them all, how lets push things -+ &comment("getting encrypt flag from parameter $enc_off"); -+ &mov("ecx", &wparam($enc_off)); # Get enc flag -+ if ($p3 > 0) -+ { -+ &comment("get and push parameter $p3"); -+ if ($enc_off != $p3) -+ { &mov("eax", &wparam($p3)); &push("eax"); } -+ else { &push("ecx"); } -+ } -+ if ($p2 > 0) -+ { -+ &comment("get and push parameter $p2"); -+ if ($enc_off != $p2) -+ { &mov("eax", &wparam($p2)); &push("eax"); } -+ else { &push("ecx"); } -+ } -+ if ($p1 > 0) -+ { -+ &comment("get and push parameter $p1"); -+ if ($enc_off != $p1) -+ { &mov("eax", &wparam($p1)); &push("eax"); } -+ else { &push("ecx"); } -+ } -+ &push("ebx"); # push data/iv -+ -+ &cmp("ecx",0); -+ &jz(&label("decrypt")); -+ -+ &and($count,0xfffffff8); -+ &mov("eax", &DWP($data_off,"esp","",0)); # load iv[0] -+ &mov("ebx", &DWP($data_off+4,"esp","",0)); # load iv[1] -+ -+ &jz(&label("encrypt_finish")); -+ -+ ############################################################# -+ -+ &set_label("encrypt_loop"); -+ # encrypt start -+ # "eax" and "ebx" hold iv (or the last cipher text) -+ -+ &mov("ecx", &DWP(0,$in,"",0)); # load first 4 bytes -+ &mov("edx", &DWP(4,$in,"",0)); # second 4 bytes -+ -+ &xor("eax", "ecx"); -+ &xor("ebx", "edx"); -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call -+ &mov(&DWP($data_off+4,"esp","",0), "ebx"); # -+ -+ &call($enc_func); -+ -+ &mov("eax", &DWP($data_off,"esp","",0)); -+ &mov("ebx", &DWP($data_off+4,"esp","",0)); -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov(&DWP(0,$out,"",0),"eax"); -+ &mov(&DWP(4,$out,"",0),"ebx"); -+ -+ # eax and ebx are the next iv. -+ -+ &add($in, 8); -+ &add($out, 8); -+ -+ &sub($count, 8); -+ &jnz(&label("encrypt_loop")); -+ -+###################################################################3 -+ &set_label("encrypt_finish"); -+ &mov($count, &wparam(2)); # length -+ &and($count, 7); -+ &jz(&label("finish")); -+ &xor("ecx","ecx"); -+ &xor("edx","edx"); -+ &mov($count,&DWP(&label("cbc_enc_jmp_table"),"",$count,4)); -+ &jmp_ptr($count); -+ -+&set_label("ej7"); -+ &xor("edx", "edx") if $ppro; # ppro friendly -+ &movb(&HB("edx"), &BP(6,$in,"",0)); -+ &shl("edx",8); -+&set_label("ej6"); -+ &movb(&HB("edx"), &BP(5,$in,"",0)); -+&set_label("ej5"); -+ &movb(&LB("edx"), &BP(4,$in,"",0)); -+&set_label("ej4"); -+ &mov("ecx", &DWP(0,$in,"",0)); -+ &jmp(&label("ejend")); -+&set_label("ej3"); -+ &movb(&HB("ecx"), &BP(2,$in,"",0)); -+ &xor("ecx", "ecx") if $ppro; # ppro friendly -+ &shl("ecx",8); -+&set_label("ej2"); -+ &movb(&HB("ecx"), &BP(1,$in,"",0)); -+&set_label("ej1"); -+ &movb(&LB("ecx"), &BP(0,$in,"",0)); -+&set_label("ejend"); -+ -+ &xor("eax", "ecx"); -+ &xor("ebx", "edx"); -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call -+ &mov(&DWP($data_off+4,"esp","",0), "ebx"); # -+ -+ &call($enc_func); -+ -+ &mov("eax", &DWP($data_off,"esp","",0)); -+ &mov("ebx", &DWP($data_off+4,"esp","",0)); -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov(&DWP(0,$out,"",0),"eax"); -+ &mov(&DWP(4,$out,"",0),"ebx"); -+ -+ &jmp(&label("finish")); -+ -+ ############################################################# -+ ############################################################# -+ &set_label("decrypt",1); -+ # decrypt start -+ &and($count,0xfffffff8); -+ # The next 2 instructions are only for if the jz is taken -+ &mov("eax", &DWP($data_off+8,"esp","",0)); # get iv[0] -+ &mov("ebx", &DWP($data_off+12,"esp","",0)); # get iv[1] -+ &jz(&label("decrypt_finish")); -+ -+ &set_label("decrypt_loop"); -+ &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes -+ &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov(&DWP($data_off,"esp","",0), "eax"); # put back -+ &mov(&DWP($data_off+4,"esp","",0), "ebx"); # -+ -+ &call($dec_func); -+ -+ &mov("eax", &DWP($data_off,"esp","",0)); # get return -+ &mov("ebx", &DWP($data_off+4,"esp","",0)); # -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] -+ &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] -+ -+ &xor("ecx", "eax"); -+ &xor("edx", "ebx"); -+ -+ &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, -+ &mov("ebx", &DWP(4,$in,"",0)); # next iv actually -+ -+ &mov(&DWP(0,$out,"",0),"ecx"); -+ &mov(&DWP(4,$out,"",0),"edx"); -+ -+ &mov(&DWP($data_off+8,"esp","",0), "eax"); # save iv -+ &mov(&DWP($data_off+12,"esp","",0), "ebx"); # -+ -+ &add($in, 8); -+ &add($out, 8); -+ -+ &sub($count, 8); -+ &jnz(&label("decrypt_loop")); -+############################ ENDIT #######################3 -+ &set_label("decrypt_finish"); -+ &mov($count, &wparam(2)); # length -+ &and($count, 7); -+ &jz(&label("finish")); -+ -+ &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes -+ &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov(&DWP($data_off,"esp","",0), "eax"); # put back -+ &mov(&DWP($data_off+4,"esp","",0), "ebx"); # -+ -+ &call($dec_func); -+ -+ &mov("eax", &DWP($data_off,"esp","",0)); # get return -+ &mov("ebx", &DWP($data_off+4,"esp","",0)); # -+ -+ &bswap("eax") if $swap; -+ &bswap("ebx") if $swap; -+ -+ &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] -+ &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] -+ -+ &xor("ecx", "eax"); -+ &xor("edx", "ebx"); -+ -+ # this is for when we exit -+ &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, -+ &mov("ebx", &DWP(4,$in,"",0)); # next iv actually -+ -+&set_label("dj7"); -+ &rotr("edx", 16); -+ &movb(&BP(6,$out,"",0), &LB("edx")); -+ &shr("edx",16); -+&set_label("dj6"); -+ &movb(&BP(5,$out,"",0), &HB("edx")); -+&set_label("dj5"); -+ &movb(&BP(4,$out,"",0), &LB("edx")); -+&set_label("dj4"); -+ &mov(&DWP(0,$out,"",0), "ecx"); -+ &jmp(&label("djend")); -+&set_label("dj3"); -+ &rotr("ecx", 16); -+ &movb(&BP(2,$out,"",0), &LB("ecx")); -+ &shl("ecx",16); -+&set_label("dj2"); -+ &movb(&BP(1,$in,"",0), &HB("ecx")); -+&set_label("dj1"); -+ &movb(&BP(0,$in,"",0), &LB("ecx")); -+&set_label("djend"); -+ -+ # final iv is still in eax:ebx -+ &jmp(&label("finish")); -+ -+ -+############################ FINISH #######################3 -+ &set_label("finish",1); -+ &mov("ecx", &wparam($iv_off)); # Get iv ptr -+ -+ ################################################# -+ $total=16+4; -+ $total+=4 if ($p1 > 0); -+ $total+=4 if ($p2 > 0); -+ $total+=4 if ($p3 > 0); -+ &add("esp",$total); -+ -+ &mov(&DWP(0,"ecx","",0), "eax"); # save iv -+ &mov(&DWP(4,"ecx","",0), "ebx"); # save iv -+ -+ &function_end_A($name); -+ -+ &set_label("cbc_enc_jmp_table",1); -+ &data_word("0"); -+ &data_word(&label("ej1")); -+ &data_word(&label("ej2")); -+ &data_word(&label("ej3")); -+ &data_word(&label("ej4")); -+ &data_word(&label("ej5")); -+ &data_word(&label("ej6")); -+ &data_word(&label("ej7")); -+ &set_label("cbc_dec_jmp_table",1); -+ &data_word("0"); -+ &data_word(&label("dj1")); -+ &data_word(&label("dj2")); -+ &data_word(&label("dj3")); -+ &data_word(&label("dj4")); -+ &data_word(&label("dj5")); -+ &data_word(&label("dj6")); -+ &data_word(&label("dj7")); -+ -+ &function_end_B($name); -+ -+ } -+ -+1; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/perlasm/readme Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,124 @@ -+The perl scripts in this directory are my 'hack' to generate -+multiple different assembler formats via the one origional script. -+ -+The way to use this library is to start with adding the path to this directory -+and then include it. -+ -+push(@INC,"perlasm","../../perlasm"); -+require "x86asm.pl"; -+ -+The first thing we do is setup the file and type of assember -+ -+&asm_init($ARGV[0],$0); -+ -+The first argument is the 'type'. Currently -+'cpp', 'sol', 'a.out', 'elf' or 'win32'. -+Argument 2 is the file name. -+ -+The reciprocal function is -+&asm_finish() which should be called at the end. -+ -+There are 2 main 'packages'. x86ms.pl, which is the microsoft assembler, -+and x86unix.pl which is the unix (gas) version. -+ -+Functions of interest are: -+&external_label("des_SPtrans"); declare and external variable -+&LB(reg); Low byte for a register -+&HB(reg); High byte for a register -+&BP(off,base,index,scale) Byte pointer addressing -+&DWP(off,base,index,scale) Word pointer addressing -+&stack_push(num) Basically a 'sub esp, num*4' with extra -+&stack_pop(num) inverse of stack_push -+&function_begin(name,extra) Start a function with pushing of -+ edi, esi, ebx and ebp. extra is extra win32 -+ external info that may be required. -+&function_begin_B(name,extra) Same as norma function_begin but no pushing. -+&function_end(name) Call at end of function. -+&function_end_A(name) Standard pop and ret, for use inside functions -+&function_end_B(name) Call at end but with poping or 'ret'. -+&swtmp(num) Address on stack temp word. -+&wparam(num) Parameter number num, that was push -+ in C convention. This all works over pushes -+ and pops. -+&comment("hello there") Put in a comment. -+&label("loop") Refer to a label, normally a jmp target. -+&set_label("loop") Set a label at this point. -+&data_word(word) Put in a word of data. -+ -+So how does this all hold together? Given -+ -+int calc(int len, int *data) -+ { -+ int i,j=0; -+ -+ for (i=0; i"); -+&comment(""); -+ -+ $filename =~ s/\.pl$//; -+ &file($filename); -+ } -+ -+sub asm_finish_cpp -+ { -+ return unless $cpp; -+ -+ local($tmp,$i); -+ foreach $i (&get_labels()) -+ { -+ $tmp.="#define $i _$i\n"; -+ } -+ print <<"EOF"; -+/* Run the C pre-processor over this file with one of the following defined -+ * ELF - elf object files, -+ * OUT - a.out object files, -+ * BSDI - BSDI style a.out object files -+ * SOL - Solaris style elf -+ */ -+ -+#define TYPE(a,b) .type a,b -+#define SIZE(a,b) .size a,b -+ -+#if defined(OUT) || defined(BSDI) -+$tmp -+#endif -+ -+#ifdef OUT -+#define OK 1 -+#define ALIGN 4 -+#endif -+ -+#ifdef BSDI -+#define OK 1 -+#define ALIGN 4 -+#undef SIZE -+#undef TYPE -+#endif -+ -+#if defined(ELF) || defined(SOL) -+#define OK 1 -+#define ALIGN 16 -+#endif -+ -+#ifndef OK -+You need to define one of -+ELF - elf systems - linux-elf, NetBSD and DG-UX -+OUT - a.out systems - linux-a.out and FreeBSD -+SOL - solaris systems, which are elf with strange comment lines -+BSDI - a.out with a very primative version of as. -+#endif -+ -+/* Let the Assembler begin :-) */ -+EOF -+ } -+ -+1; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/perlasm/x86ms.pl Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,345 @@ -+#!/usr/bin/perl -+ -+package x86ms; -+ -+$label="L000"; -+ -+%lb=( 'eax', 'al', -+ 'ebx', 'bl', -+ 'ecx', 'cl', -+ 'edx', 'dl', -+ 'ax', 'al', -+ 'bx', 'bl', -+ 'cx', 'cl', -+ 'dx', 'dl', -+ ); -+ -+%hb=( 'eax', 'ah', -+ 'ebx', 'bh', -+ 'ecx', 'ch', -+ 'edx', 'dh', -+ 'ax', 'ah', -+ 'bx', 'bh', -+ 'cx', 'ch', -+ 'dx', 'dh', -+ ); -+ -+sub main'asm_init_output { @out=(); } -+sub main'asm_get_output { return(@out); } -+sub main'get_labels { return(@labels); } -+sub main'external_label { push(@labels,@_); } -+ -+sub main'LB -+ { -+ (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n"; -+ return($lb{$_[0]}); -+ } -+ -+sub main'HB -+ { -+ (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n"; -+ return($hb{$_[0]}); -+ } -+ -+sub main'BP -+ { -+ &get_mem("BYTE",@_); -+ } -+ -+sub main'DWP -+ { -+ &get_mem("DWORD",@_); -+ } -+ -+sub main'stack_push -+ { -+ local($num)=@_; -+ $stack+=$num*4; -+ &main'sub("esp",$num*4); -+ } -+ -+sub main'stack_pop -+ { -+ local($num)=@_; -+ $stack-=$num*4; -+ &main'add("esp",$num*4); -+ } -+ -+sub get_mem -+ { -+ local($size,$addr,$reg1,$reg2,$idx)=@_; -+ local($t,$post); -+ local($ret)="$size PTR "; -+ -+ $addr =~ s/^\s+//; -+ if ($addr =~ /^(.+)\+(.+)$/) -+ { -+ $reg2=&conv($1); -+ $addr="_$2"; -+ } -+ elsif ($addr =~ /^[_a-zA-Z]/) -+ { -+ $addr="_$addr"; -+ } -+ -+ $reg1="$regs{$reg1}" if defined($regs{$reg1}); -+ $reg2="$regs{$reg2}" if defined($regs{$reg2}); -+ if (($addr ne "") && ($addr ne 0)) -+ { -+ if ($addr !~ /^-/) -+ { $ret.=$addr; } -+ else { $post=$addr; } -+ } -+ if ($reg2 ne "") -+ { -+ $t=""; -+ $t="*$idx" if ($idx != 0); -+ $reg1="+".$reg1 if ("$reg1$post" ne ""); -+ $ret.="[$reg2$t$reg1$post]"; -+ } -+ else -+ { -+ $ret.="[$reg1$post]" -+ } -+ return($ret); -+ } -+ -+sub main'mov { &out2("mov",@_); } -+sub main'movb { &out2("mov",@_); } -+sub main'and { &out2("and",@_); } -+sub main'or { &out2("or",@_); } -+sub main'shl { &out2("shl",@_); } -+sub main'shr { &out2("shr",@_); } -+sub main'xor { &out2("xor",@_); } -+sub main'xorb { &out2("xor",@_); } -+sub main'add { &out2("add",@_); } -+sub main'adc { &out2("adc",@_); } -+sub main'sub { &out2("sub",@_); } -+sub main'rotl { &out2("rol",@_); } -+sub main'rotr { &out2("ror",@_); } -+sub main'exch { &out2("xchg",@_); } -+sub main'cmp { &out2("cmp",@_); } -+sub main'lea { &out2("lea",@_); } -+sub main'mul { &out1("mul",@_); } -+sub main'div { &out1("div",@_); } -+sub main'dec { &out1("dec",@_); } -+sub main'inc { &out1("inc",@_); } -+sub main'jmp { &out1("jmp",@_); } -+sub main'jmp_ptr { &out1p("jmp",@_); } -+sub main'je { &out1("je",@_); } -+sub main'jle { &out1("jle",@_); } -+sub main'jz { &out1("jz",@_); } -+sub main'jge { &out1("jge",@_); } -+sub main'jl { &out1("jl",@_); } -+sub main'jb { &out1("jb",@_); } -+sub main'jnz { &out1("jnz",@_); } -+sub main'jne { &out1("jne",@_); } -+sub main'push { &out1("push",@_); $stack+=4; } -+sub main'pop { &out1("pop",@_); $stack-=4; } -+sub main'bswap { &out1("bswap",@_); &using486(); } -+sub main'not { &out1("not",@_); } -+sub main'call { &out1("call",'_'.$_[0]); } -+sub main'ret { &out0("ret"); } -+sub main'nop { &out0("nop"); } -+ -+sub out2 -+ { -+ local($name,$p1,$p2)=@_; -+ local($l,$t); -+ -+ push(@out,"\t$name\t"); -+ $t=&conv($p1).","; -+ $l=length($t); -+ push(@out,$t); -+ $l=4-($l+9)/8; -+ push(@out,"\t" x $l); -+ push(@out,&conv($p2)); -+ push(@out,"\n"); -+ } -+ -+sub out0 -+ { -+ local($name)=@_; -+ -+ push(@out,"\t$name\n"); -+ } -+ -+sub out1 -+ { -+ local($name,$p1)=@_; -+ local($l,$t); -+ -+ push(@out,"\t$name\t".&conv($p1)."\n"); -+ } -+ -+sub conv -+ { -+ local($p)=@_; -+ -+ $p =~ s/0x([0-9A-Fa-f]+)/0$1h/; -+ return $p; -+ } -+ -+sub using486 -+ { -+ return if $using486; -+ $using486++; -+ grep(s/\.386/\.486/,@out); -+ } -+ -+sub main'file -+ { -+ local($file)=@_; -+ -+ local($tmp)=<<"EOF"; -+ TITLE $file.asm -+ .386 -+.model FLAT -+EOF -+ push(@out,$tmp); -+ } -+ -+sub main'function_begin -+ { -+ local($func,$extra)=@_; -+ -+ push(@labels,$func); -+ -+ local($tmp)=<<"EOF"; -+_TEXT SEGMENT -+PUBLIC _$func -+$extra -+_$func PROC NEAR -+ push ebp -+ push ebx -+ push esi -+ push edi -+EOF -+ push(@out,$tmp); -+ $stack=20; -+ } -+ -+sub main'function_begin_B -+ { -+ local($func,$extra)=@_; -+ -+ local($tmp)=<<"EOF"; -+_TEXT SEGMENT -+PUBLIC _$func -+$extra -+_$func PROC NEAR -+EOF -+ push(@out,$tmp); -+ $stack=4; -+ } -+ -+sub main'function_end -+ { -+ local($func)=@_; -+ -+ local($tmp)=<<"EOF"; -+ pop edi -+ pop esi -+ pop ebx -+ pop ebp -+ ret -+_$func ENDP -+_TEXT ENDS -+EOF -+ push(@out,$tmp); -+ $stack=0; -+ %label=(); -+ } -+ -+sub main'function_end_B -+ { -+ local($func)=@_; -+ -+ local($tmp)=<<"EOF"; -+_$func ENDP -+_TEXT ENDS -+EOF -+ push(@out,$tmp); -+ $stack=0; -+ %label=(); -+ } -+ -+sub main'function_end_A -+ { -+ local($func)=@_; -+ -+ local($tmp)=<<"EOF"; -+ pop edi -+ pop esi -+ pop ebx -+ pop ebp -+ ret -+EOF -+ push(@out,$tmp); -+ } -+ -+sub main'file_end -+ { -+ push(@out,"END\n"); -+ } -+ -+sub main'wparam -+ { -+ local($num)=@_; -+ -+ return(&main'DWP($stack+$num*4,"esp","",0)); -+ } -+ -+sub main'swtmp -+ { -+ return(&main'DWP($_[0]*4,"esp","",0)); -+ } -+ -+# Should use swtmp, which is above esp. Linix can trash the stack above esp -+#sub main'wtmp -+# { -+# local($num)=@_; -+# -+# return(&main'DWP(-(($num+1)*4),"esp","",0)); -+# } -+ -+sub main'comment -+ { -+ foreach (@_) -+ { -+ push(@out,"\t; $_\n"); -+ } -+ } -+ -+sub main'label -+ { -+ if (!defined($label{$_[0]})) -+ { -+ $label{$_[0]}="\$${label}${_[0]}"; -+ $label++; -+ } -+ return($label{$_[0]}); -+ } -+ -+sub main'set_label -+ { -+ if (!defined($label{$_[0]})) -+ { -+ $label{$_[0]}="${label}${_[0]}"; -+ $label++; -+ } -+ push(@out,"$label{$_[0]}:\n"); -+ } -+ -+sub main'data_word -+ { -+ push(@out,"\tDD\t$_[0]\n"); -+ } -+ -+sub out1p -+ { -+ local($name,$p1)=@_; -+ local($l,$t); -+ -+ push(@out,"\t$name\t ".&conv($p1)."\n"); -+ } ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/perlasm/x86unix.pl Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,403 @@ -+#!/usr/bin/perl -+ -+package x86unix; -+ -+$label="L000"; -+ -+$align=($main'aout)?"4":"16"; -+$under=($main'aout)?"_":""; -+$com_start=($main'sol)?"/":"#"; -+ -+sub main'asm_init_output { @out=(); } -+sub main'asm_get_output { return(@out); } -+sub main'get_labels { return(@labels); } -+sub main'external_label { push(@labels,@_); } -+ -+if ($main'cpp) -+ { -+ $align="ALIGN"; -+ $under=""; -+ $com_start='/*'; -+ $com_end='*/'; -+ } -+ -+%lb=( 'eax', '%al', -+ 'ebx', '%bl', -+ 'ecx', '%cl', -+ 'edx', '%dl', -+ 'ax', '%al', -+ 'bx', '%bl', -+ 'cx', '%cl', -+ 'dx', '%dl', -+ ); -+ -+%hb=( 'eax', '%ah', -+ 'ebx', '%bh', -+ 'ecx', '%ch', -+ 'edx', '%dh', -+ 'ax', '%ah', -+ 'bx', '%bh', -+ 'cx', '%ch', -+ 'dx', '%dh', -+ ); -+ -+%regs=( 'eax', '%eax', -+ 'ebx', '%ebx', -+ 'ecx', '%ecx', -+ 'edx', '%edx', -+ 'esi', '%esi', -+ 'edi', '%edi', -+ 'ebp', '%ebp', -+ 'esp', '%esp', -+ ); -+ -+%reg_val=( -+ 'eax', 0x00, -+ 'ebx', 0x03, -+ 'ecx', 0x01, -+ 'edx', 0x02, -+ 'esi', 0x06, -+ 'edi', 0x07, -+ 'ebp', 0x05, -+ 'esp', 0x04, -+ ); -+ -+sub main'LB -+ { -+ (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n"; -+ return($lb{$_[0]}); -+ } -+ -+sub main'HB -+ { -+ (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n"; -+ return($hb{$_[0]}); -+ } -+ -+sub main'DWP -+ { -+ local($addr,$reg1,$reg2,$idx)=@_; -+ -+ $ret=""; -+ $addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/; -+ $reg1="$regs{$reg1}" if defined($regs{$reg1}); -+ $reg2="$regs{$reg2}" if defined($regs{$reg2}); -+ $ret.=$addr if ($addr ne "") && ($addr ne 0); -+ if ($reg2 ne "") -+ { $ret.="($reg1,$reg2,$idx)"; } -+ else -+ { $ret.="($reg1)" } -+ return($ret); -+ } -+ -+sub main'BP -+ { -+ return(&main'DWP(@_)); -+ } -+ -+#sub main'BP -+# { -+# local($addr,$reg1,$reg2,$idx)=@_; -+# -+# $ret=""; -+# -+# $addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/; -+# $reg1="$regs{$reg1}" if defined($regs{$reg1}); -+# $reg2="$regs{$reg2}" if defined($regs{$reg2}); -+# $ret.=$addr if ($addr ne "") && ($addr ne 0); -+# if ($reg2 ne "") -+# { $ret.="($reg1,$reg2,$idx)"; } -+# else -+# { $ret.="($reg1)" } -+# return($ret); -+# } -+ -+sub main'mov { &out2("movl",@_); } -+sub main'movb { &out2("movb",@_); } -+sub main'and { &out2("andl",@_); } -+sub main'or { &out2("orl",@_); } -+sub main'shl { &out2("sall",@_); } -+sub main'shr { &out2("shrl",@_); } -+sub main'xor { &out2("xorl",@_); } -+sub main'xorb { &out2("xorb",@_); } -+sub main'add { &out2("addl",@_); } -+sub main'adc { &out2("adcl",@_); } -+sub main'sub { &out2("subl",@_); } -+sub main'rotl { &out2("roll",@_); } -+sub main'rotr { &out2("rorl",@_); } -+sub main'exch { &out2("xchg",@_); } -+sub main'cmp { &out2("cmpl",@_); } -+sub main'lea { &out2("leal",@_); } -+sub main'mul { &out1("mull",@_); } -+sub main'div { &out1("divl",@_); } -+sub main'jmp { &out1("jmp",@_); } -+sub main'jmp_ptr { &out1p("jmp",@_); } -+sub main'je { &out1("je",@_); } -+sub main'jle { &out1("jle",@_); } -+sub main'jne { &out1("jne",@_); } -+sub main'jnz { &out1("jnz",@_); } -+sub main'jz { &out1("jz",@_); } -+sub main'jge { &out1("jge",@_); } -+sub main'jl { &out1("jl",@_); } -+sub main'jb { &out1("jb",@_); } -+sub main'dec { &out1("decl",@_); } -+sub main'inc { &out1("incl",@_); } -+sub main'push { &out1("pushl",@_); $stack+=4; } -+sub main'pop { &out1("popl",@_); $stack-=4; } -+sub main'bswap { &out1("bswapl",@_); } -+sub main'not { &out1("notl",@_); } -+sub main'call { &out1("call",$under.$_[0]); } -+sub main'ret { &out0("ret"); } -+sub main'nop { &out0("nop"); } -+ -+sub out2 -+ { -+ local($name,$p1,$p2)=@_; -+ local($l,$ll,$t); -+ local(%special)=( "roll",0xD1C0,"rorl",0xD1C8, -+ "rcll",0xD1D0,"rcrl",0xD1D8, -+ "shll",0xD1E0,"shrl",0xD1E8, -+ "sarl",0xD1F8); -+ -+ if ((defined($special{$name})) && defined($regs{$p1}) && ($p2 == 1)) -+ { -+ $op=$special{$name}|$reg_val{$p1}; -+ $tmp1=sprintf ".byte %d\n",($op>>8)&0xff; -+ $tmp2=sprintf ".byte %d\t",$op &0xff; -+ push(@out,$tmp1); -+ push(@out,$tmp2); -+ -+ $p2=&conv($p2); -+ $p1=&conv($p1); -+ &main'comment("$name $p2 $p1"); -+ return; -+ } -+ -+ push(@out,"\t$name\t"); -+ $t=&conv($p2).","; -+ $l=length($t); -+ push(@out,$t); -+ $ll=4-($l+9)/8; -+ $tmp1=sprintf "\t" x $ll; -+ push(@out,$tmp1); -+ push(@out,&conv($p1)."\n"); -+ } -+ -+sub out1 -+ { -+ local($name,$p1)=@_; -+ local($l,$t); -+ -+ push(@out,"\t$name\t".&conv($p1)."\n"); -+ } -+ -+sub out1p -+ { -+ local($name,$p1)=@_; -+ local($l,$t); -+ -+ push(@out,"\t$name\t*".&conv($p1)."\n"); -+ } -+ -+sub out0 -+ { -+ push(@out,"\t$_[0]\n"); -+ } -+ -+sub conv -+ { -+ local($p)=@_; -+ -+# $p =~ s/0x([0-9A-Fa-f]+)/0$1h/; -+ -+ $p=$regs{$p} if (defined($regs{$p})); -+ -+ $p =~ s/^(-{0,1}[0-9A-Fa-f]+)$/\$$1/; -+ $p =~ s/^(0x[0-9A-Fa-f]+)$/\$$1/; -+ return $p; -+ } -+ -+sub main'file -+ { -+ local($file)=@_; -+ -+ local($tmp)=<<"EOF"; -+ .file "$file.s" -+ .version "01.01" -+gcc2_compiled.: -+EOF -+ push(@out,$tmp); -+ } -+ -+sub main'function_begin -+ { -+ local($func)=@_; -+ -+ $func=$under.$func; -+ -+ local($tmp)=<<"EOF"; -+.text -+ .align $align -+.globl $func -+EOF -+ push(@out,$tmp); -+ if ($main'cpp) -+ { $tmp=push(@out,"\tTYPE($func,\@function)\n"); } -+ else { $tmp=push(@out,"\t.type\t$func,\@function\n"); } -+ push(@out,"$func:\n"); -+ $tmp=<<"EOF"; -+ pushl %ebp -+ pushl %ebx -+ pushl %esi -+ pushl %edi -+ -+EOF -+ push(@out,$tmp); -+ $stack=20; -+ } -+ -+sub main'function_begin_B -+ { -+ local($func,$extra)=@_; -+ -+ $func=$under.$func; -+ -+ local($tmp)=<<"EOF"; -+.text -+ .align $align -+.globl $func -+EOF -+ push(@out,$tmp); -+ if ($main'cpp) -+ { push(@out,"\tTYPE($func,\@function)\n"); } -+ else { push(@out,"\t.type $func,\@function\n"); } -+ push(@out,"$func:\n"); -+ $stack=4; -+ } -+ -+sub main'function_end -+ { -+ local($func)=@_; -+ -+ $func=$under.$func; -+ -+ local($tmp)=<<"EOF"; -+ popl %edi -+ popl %esi -+ popl %ebx -+ popl %ebp -+ ret -+.${func}_end: -+EOF -+ push(@out,$tmp); -+ if ($main'cpp) -+ { push(@out,"\tSIZE($func,.${func}_end-$func)\n"); } -+ else { push(@out,"\t.size\t$func,.${func}_end-$func\n"); } -+ push(@out,".ident \"$func\"\n"); -+ $stack=0; -+ %label=(); -+ } -+ -+sub main'function_end_A -+ { -+ local($func)=@_; -+ -+ local($tmp)=<<"EOF"; -+ popl %edi -+ popl %esi -+ popl %ebx -+ popl %ebp -+ ret -+EOF -+ push(@out,$tmp); -+ } -+ -+sub main'function_end_B -+ { -+ local($func)=@_; -+ -+ $func=$under.$func; -+ -+ push(@out,".${func}_end:\n"); -+ if ($main'cpp) -+ { push(@out,"\tSIZE($func,.${func}_end-$func)\n"); } -+ else { push(@out,"\t.size\t$func,.${func}_end-$func\n"); } -+ push(@out,".ident \"desasm.pl\"\n"); -+ $stack=0; -+ %label=(); -+ } -+ -+sub main'wparam -+ { -+ local($num)=@_; -+ -+ return(&main'DWP($stack+$num*4,"esp","",0)); -+ } -+ -+sub main'stack_push -+ { -+ local($num)=@_; -+ $stack+=$num*4; -+ &main'sub("esp",$num*4); -+ } -+ -+sub main'stack_pop -+ { -+ local($num)=@_; -+ $stack-=$num*4; -+ &main'add("esp",$num*4); -+ } -+ -+sub main'swtmp -+ { -+ return(&main'DWP($_[0]*4,"esp","",0)); -+ } -+ -+# Should use swtmp, which is above esp. Linix can trash the stack above esp -+#sub main'wtmp -+# { -+# local($num)=@_; -+# -+# return(&main'DWP(-($num+1)*4,"esp","",0)); -+# } -+ -+sub main'comment -+ { -+ foreach (@_) -+ { -+ if (/^\s*$/) -+ { push(@out,"\n"); } -+ else -+ { push(@out,"\t$com_start $_ $com_end\n"); } -+ } -+ } -+ -+sub main'label -+ { -+ if (!defined($label{$_[0]})) -+ { -+ $label{$_[0]}=".${label}${_[0]}"; -+ $label++; -+ } -+ return($label{$_[0]}); -+ } -+ -+sub main'set_label -+ { -+ if (!defined($label{$_[0]})) -+ { -+ $label{$_[0]}=".${label}${_[0]}"; -+ $label++; -+ } -+ push(@out,".align $align\n") if ($_[1] != 0); -+ push(@out,"$label{$_[0]}:\n"); -+ } -+ -+sub main'file_end -+ { -+ } -+ -+sub main'data_word -+ { -+ push(@out,"\t.long $_[0]\n"); -+ } ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/asm/readme Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,131 @@ -+First up, let me say I don't like writing in assembler. It is not portable, -+dependant on the particular CPU architecture release and is generally a pig -+to debug and get right. Having said that, the x86 architecture is probably -+the most important for speed due to number of boxes and since -+it appears to be the worst architecture to to get -+good C compilers for. So due to this, I have lowered myself to do -+assembler for the inner DES routines in libdes :-). -+ -+The file to implement in assembler is des_enc.c. Replace the following -+4 functions -+des_encrypt(DES_LONG data[2],des_key_schedule ks, int encrypt); -+des_encrypt2(DES_LONG data[2],des_key_schedule ks, int encrypt); -+des_encrypt3(DES_LONG data[2],des_key_schedule ks1,ks2,ks3); -+des_decrypt3(DES_LONG data[2],des_key_schedule ks1,ks2,ks3); -+ -+They encrypt/decrypt the 64 bits held in 'data' using -+the 'ks' key schedules. The only difference between the 4 functions is that -+des_encrypt2() does not perform IP() or FP() on the data (this is an -+optimization for when doing triple DES and des_encrypt3() and des_decrypt3() -+perform triple des. The triple DES routines are in here because it does -+make a big difference to have them located near the des_encrypt2 function -+at link time.. -+ -+Now as we all know, there are lots of different operating systems running on -+x86 boxes, and unfortunately they normally try to make sure their assembler -+formating is not the same as the other peoples. -+The 4 main formats I know of are -+Microsoft Windows 95/Windows NT -+Elf Includes Linux and FreeBSD(?). -+a.out The older Linux. -+Solaris Same as Elf but different comments :-(. -+ -+Now I was not overly keen to write 4 different copies of the same code, -+so I wrote a few perl routines to output the correct assembler, given -+a target assembler type. This code is ugly and is just a hack. -+The libraries are x86unix.pl and x86ms.pl. -+des586.pl, des686.pl and des-som[23].pl are the programs to actually -+generate the assembler. -+ -+So to generate elf assembler -+perl des-som3.pl elf >dx86-elf.s -+For Windows 95/NT -+perl des-som2.pl win32 >win32.asm -+ -+[ update 4 Jan 1996 ] -+I have added another way to do things. -+perl des-som3.pl cpp >dx86-cpp.s -+generates a file that will be included by dx86unix.cpp when it is compiled. -+To build for elf, a.out, solaris, bsdi etc, -+cc -E -DELF asm/dx86unix.cpp | as -o asm/dx86-elf.o -+cc -E -DSOL asm/dx86unix.cpp | as -o asm/dx86-sol.o -+cc -E -DOUT asm/dx86unix.cpp | as -o asm/dx86-out.o -+cc -E -DBSDI asm/dx86unix.cpp | as -o asm/dx86bsdi.o -+This was done to cut down the number of files in the distribution. -+ -+Now the ugly part. I acquired my copy of Intels -+"Optimization's For Intel's 32-Bit Processors" and found a few interesting -+things. First, the aim of the exersize is to 'extract' one byte at a time -+from a word and do an array lookup. This involves getting the byte from -+the 4 locations in the word and moving it to a new word and doing the lookup. -+The most obvious way to do this is -+xor eax, eax # clear word -+movb al, cl # get low byte -+xor edi DWORD PTR 0x100+des_SP[eax] # xor in word -+movb al, ch # get next byte -+xor edi DWORD PTR 0x300+des_SP[eax] # xor in word -+shr ecx 16 -+which seems ok. For the pentium, this system appears to be the best. -+One has to do instruction interleaving to keep both functional units -+operating, but it is basically very efficient. -+ -+Now the crunch. When a full register is used after a partial write, eg. -+mov al, cl -+xor edi, DWORD PTR 0x100+des_SP[eax] -+386 - 1 cycle stall -+486 - 1 cycle stall -+586 - 0 cycle stall -+686 - at least 7 cycle stall (page 22 of the above mentioned document). -+ -+So the technique that produces the best results on a pentium, according to -+the documentation, will produce hideous results on a pentium pro. -+ -+To get around this, des686.pl will generate code that is not as fast on -+a pentium, should be very good on a pentium pro. -+mov eax, ecx # copy word -+shr ecx, 8 # line up next byte -+and eax, 0fch # mask byte -+xor edi DWORD PTR 0x100+des_SP[eax] # xor in array lookup -+mov eax, ecx # get word -+shr ecx 8 # line up next byte -+and eax, 0fch # mask byte -+xor edi DWORD PTR 0x300+des_SP[eax] # xor in array lookup -+ -+Due to the execution units in the pentium, this actually works quite well. -+For a pentium pro it should be very good. This is the type of output -+Visual C++ generates. -+ -+There is a third option. instead of using -+mov al, ch -+which is bad on the pentium pro, one may be able to use -+movzx eax, ch -+which may not incur the partial write penalty. On the pentium, -+this instruction takes 4 cycles so is not worth using but on the -+pentium pro it appears it may be worth while. I need access to one to -+experiment :-). -+ -+eric (20 Oct 1996) -+ -+22 Nov 1996 - I have asked people to run the 2 different version on pentium -+pros and it appears that the intel documentation is wrong. The -+mov al,bh is still faster on a pentium pro, so just use the des586.pl -+install des686.pl -+ -+3 Dec 1996 - I added des_encrypt3/des_decrypt3 because I have moved these -+functions into des_enc.c because it does make a massive performance -+difference on some boxes to have the functions code located close to -+the des_encrypt2() function. -+ -+9 Jan 1997 - des-som2.pl is now the correct perl script to use for -+pentiums. It contains an inner loop from -+Svend Olaf Mikkelsen which does raw ecb DES calls at -+273,000 per second. He had a previous version at 250,000 and the best -+I was able to get was 203,000. The content has not changed, this is all -+due to instruction sequencing (and actual instructions choice) which is able -+to keep both functional units of the pentium going. -+We may have lost the ugly register usage restrictions when x86 went 32 bit -+but for the pentium it has been replaced by evil instruction ordering tricks. -+ -+13 Jan 1997 - des-som3.pl, more optimizations from Svend Olaf. -+raw DES at 281,000 per second on a pentium 100. -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/cbc_enc.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,135 @@ -+/* crypto/des/cbc_enc.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+#include "des_locl.h" -+ -+void des_cbc_encrypt(input, output, length, schedule, ivec, enc) -+des_cblock (*input); -+des_cblock (*output); -+long length; -+des_key_schedule schedule; -+des_cblock (*ivec); -+int enc; -+ { -+ register DES_LONG tin0,tin1; -+ register DES_LONG tout0,tout1,xor0,xor1; -+ register unsigned char *in,*out; -+ register long l=length; -+ DES_LONG tin[2]; -+ unsigned char *iv; -+ -+ in=(unsigned char *)input; -+ out=(unsigned char *)output; -+ iv=(unsigned char *)ivec; -+ -+ if (enc) -+ { -+ c2l(iv,tout0); -+ c2l(iv,tout1); -+ for (l-=8; l>=0; l-=8) -+ { -+ c2l(in,tin0); -+ c2l(in,tin1); -+ tin0^=tout0; tin[0]=tin0; -+ tin1^=tout1; tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); -+ tout0=tin[0]; l2c(tout0,out); -+ tout1=tin[1]; l2c(tout1,out); -+ } -+ if (l != -8) -+ { -+ c2ln(in,tin0,tin1,l+8); -+ tin0^=tout0; tin[0]=tin0; -+ tin1^=tout1; tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); -+ tout0=tin[0]; l2c(tout0,out); -+ tout1=tin[1]; l2c(tout1,out); -+ } -+ } -+ else -+ { -+ c2l(iv,xor0); -+ c2l(iv,xor1); -+ for (l-=8; l>=0; l-=8) -+ { -+ c2l(in,tin0); tin[0]=tin0; -+ c2l(in,tin1); tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); -+ tout0=tin[0]^xor0; -+ tout1=tin[1]^xor1; -+ l2c(tout0,out); -+ l2c(tout1,out); -+ xor0=tin0; -+ xor1=tin1; -+ } -+ if (l != -8) -+ { -+ c2l(in,tin0); tin[0]=tin0; -+ c2l(in,tin1); tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); -+ tout0=tin[0]^xor0; -+ tout1=tin[1]^xor1; -+ l2cn(tout0,tout1,out,l+8); -+ /* xor0=tin0; -+ xor1=tin1; */ -+ } -+ } -+ tin0=tin1=tout0=tout1=xor0=xor1=0; -+ tin[0]=tin[1]=0; -+ } -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/des.doc Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,505 @@ -+The DES library. -+ -+Please note that this library was originally written to operate with -+eBones, a version of Kerberos that had had encryption removed when it left -+the USA and then put back in. As such there are some routines that I will -+advise not using but they are still in the library for historical reasons. -+For all calls that have an 'input' and 'output' variables, they can be the -+same. -+ -+This library requires the inclusion of 'des.h'. -+ -+All of the encryption functions take what is called a des_key_schedule as an -+argument. A des_key_schedule is an expanded form of the des key. -+A des_key is 8 bytes of odd parity, the type used to hold the key is a -+des_cblock. A des_cblock is an array of 8 bytes, often in this library -+description I will refer to input bytes when the function specifies -+des_cblock's as input or output, this just means that the variable should -+be a multiple of 8 bytes. -+ -+The define DES_ENCRYPT is passed to specify encryption, DES_DECRYPT to -+specify decryption. The functions and global variable are as follows: -+ -+int des_check_key; -+ DES keys are supposed to be odd parity. If this variable is set to -+ a non-zero value, des_set_key() will check that the key has odd -+ parity and is not one of the known weak DES keys. By default this -+ variable is turned off; -+ -+void des_set_odd_parity( -+des_cblock *key ); -+ This function takes a DES key (8 bytes) and sets the parity to odd. -+ -+int des_is_weak_key( -+des_cblock *key ); -+ This function returns a non-zero value if the DES key passed is a -+ weak, DES key. If it is a weak key, don't use it, try a different -+ one. If you are using 'random' keys, the chances of hitting a weak -+ key are 1/2^52 so it is probably not worth checking for them. -+ -+int des_set_key( -+des_cblock *key, -+des_key_schedule schedule); -+ Des_set_key converts an 8 byte DES key into a des_key_schedule. -+ A des_key_schedule is an expanded form of the key which is used to -+ perform actual encryption. It can be regenerated from the DES key -+ so it only needs to be kept when encryption or decryption is about -+ to occur. Don't save or pass around des_key_schedule's since they -+ are CPU architecture dependent, DES keys are not. If des_check_key -+ is non zero, zero is returned if the key has the wrong parity or -+ the key is a weak key, else 1 is returned. -+ -+int des_key_sched( -+des_cblock *key, -+des_key_schedule schedule); -+ An alternative name for des_set_key(). -+ -+int des_rw_mode; /* defaults to DES_PCBC_MODE */ -+ This flag holds either DES_CBC_MODE or DES_PCBC_MODE (default). -+ This specifies the function to use in the enc_read() and enc_write() -+ functions. -+ -+void des_encrypt( -+unsigned long *data, -+des_key_schedule ks, -+int enc); -+ This is the DES encryption function that gets called by just about -+ every other DES routine in the library. You should not use this -+ function except to implement 'modes' of DES. I say this because the -+ functions that call this routine do the conversion from 'char *' to -+ long, and this needs to be done to make sure 'non-aligned' memory -+ access do not occur. The characters are loaded 'little endian', -+ have a look at my source code for more details on how I use this -+ function. -+ Data is a pointer to 2 unsigned long's and ks is the -+ des_key_schedule to use. enc, is non zero specifies encryption, -+ zero if decryption. -+ -+void des_encrypt2( -+unsigned long *data, -+des_key_schedule ks, -+int enc); -+ This functions is the same as des_encrypt() except that the DES -+ initial permutation (IP) and final permutation (FP) have been left -+ out. As for des_encrypt(), you should not use this function. -+ It is used by the routines in my library that implement triple DES. -+ IP() des_encrypt2() des_encrypt2() des_encrypt2() FP() is the same -+ as des_encrypt() des_encrypt() des_encrypt() except faster :-). -+ -+void des_ecb_encrypt( -+des_cblock *input, -+des_cblock *output, -+des_key_schedule ks, -+int enc); -+ This is the basic Electronic Code Book form of DES, the most basic -+ form. Input is encrypted into output using the key represented by -+ ks. If enc is non zero (DES_ENCRYPT), encryption occurs, otherwise -+ decryption occurs. Input is 8 bytes long and output is 8 bytes. -+ (the des_cblock structure is 8 chars). -+ -+void des_ecb3_encrypt( -+des_cblock *input, -+des_cblock *output, -+des_key_schedule ks1, -+des_key_schedule ks2, -+des_key_schedule ks3, -+int enc); -+ This is the 3 key EDE mode of ECB DES. What this means is that -+ the 8 bytes of input is encrypted with ks1, decrypted with ks2 and -+ then encrypted again with ks3, before being put into output; -+ C=E(ks3,D(ks2,E(ks1,M))). There is a macro, des_ecb2_encrypt() -+ that only takes 2 des_key_schedules that implements, -+ C=E(ks1,D(ks2,E(ks1,M))) in that the final encrypt is done with ks1. -+ -+void des_cbc_encrypt( -+des_cblock *input, -+des_cblock *output, -+long length, -+des_key_schedule ks, -+des_cblock *ivec, -+int enc); -+ This routine implements DES in Cipher Block Chaining mode. -+ Input, which should be a multiple of 8 bytes is encrypted -+ (or decrypted) to output which will also be a multiple of 8 bytes. -+ The number of bytes is in length (and from what I've said above, -+ should be a multiple of 8). If length is not a multiple of 8, I'm -+ not being held responsible :-). ivec is the initialisation vector. -+ This function does not modify this variable. To correctly implement -+ cbc mode, you need to do one of 2 things; copy the last 8 bytes of -+ cipher text for use as the next ivec in your application, -+ or use des_ncbc_encrypt(). -+ Only this routine has this problem with updating the ivec, all -+ other routines that are implementing cbc mode update ivec. -+ -+void des_ncbc_encrypt( -+des_cblock *input, -+des_cblock *output, -+long length, -+des_key_schedule sk, -+des_cblock *ivec, -+int enc); -+ For historical reasons, des_cbc_encrypt() did not update the -+ ivec with the value requires so that subsequent calls to -+ des_cbc_encrypt() would 'chain'. This was needed so that the same -+ 'length' values would not need to be used when decrypting. -+ des_ncbc_encrypt() does the right thing. It is the same as -+ des_cbc_encrypt accept that ivec is updates with the correct value -+ to pass in subsequent calls to des_ncbc_encrypt(). I advise using -+ des_ncbc_encrypt() instead of des_cbc_encrypt(); -+ -+void des_xcbc_encrypt( -+des_cblock *input, -+des_cblock *output, -+long length, -+des_key_schedule sk, -+des_cblock *ivec, -+des_cblock *inw, -+des_cblock *outw, -+int enc); -+ This is RSA's DESX mode of DES. It uses inw and outw to -+ 'whiten' the encryption. inw and outw are secret (unlike the iv) -+ and are as such, part of the key. So the key is sort of 24 bytes. -+ This is much better than cbc des. -+ -+void des_3cbc_encrypt( -+des_cblock *input, -+des_cblock *output, -+long length, -+des_key_schedule sk1, -+des_key_schedule sk2, -+des_cblock *ivec1, -+des_cblock *ivec2, -+int enc); -+ This function is flawed, do not use it. I have left it in the -+ library because it is used in my des(1) program and will function -+ correctly when used by des(1). If I removed the function, people -+ could end up unable to decrypt files. -+ This routine implements outer triple cbc encryption using 2 ks and -+ 2 ivec's. Use des_ede2_cbc_encrypt() instead. -+ -+void des_ede3_cbc_encrypt( -+des_cblock *input, -+des_cblock *output, -+long length, -+des_key_schedule ks1, -+des_key_schedule ks2, -+des_key_schedule ks3, -+des_cblock *ivec, -+int enc); -+ This function implements inner triple CBC DES encryption with 3 -+ keys. What this means is that each 'DES' operation -+ inside the cbc mode is really an C=E(ks3,D(ks2,E(ks1,M))). -+ Again, this is cbc mode so an ivec is requires. -+ This mode is used by SSL. -+ There is also a des_ede2_cbc_encrypt() that only uses 2 -+ des_key_schedule's, the first being reused for the final -+ encryption. C=E(ks1,D(ks2,E(ks1,M))). This form of triple DES -+ is used by the RSAref library. -+ -+void des_pcbc_encrypt( -+des_cblock *input, -+des_cblock *output, -+long length, -+des_key_schedule ks, -+des_cblock *ivec, -+int enc); -+ This is Propagating Cipher Block Chaining mode of DES. It is used -+ by Kerberos v4. It's parameters are the same as des_ncbc_encrypt(). -+ -+void des_cfb_encrypt( -+unsigned char *in, -+unsigned char *out, -+int numbits, -+long length, -+des_key_schedule ks, -+des_cblock *ivec, -+int enc); -+ Cipher Feedback Back mode of DES. This implementation 'feeds back' -+ in numbit blocks. The input (and output) is in multiples of numbits -+ bits. numbits should to be a multiple of 8 bits. Length is the -+ number of bytes input. If numbits is not a multiple of 8 bits, -+ the extra bits in the bytes will be considered padding. So if -+ numbits is 12, for each 2 input bytes, the 4 high bits of the -+ second byte will be ignored. So to encode 72 bits when using -+ a numbits of 12 take 12 bytes. To encode 72 bits when using -+ numbits of 9 will take 16 bytes. To encode 80 bits when using -+ numbits of 16 will take 10 bytes. etc, etc. This padding will -+ apply to both input and output. -+ -+ -+void des_cfb64_encrypt( -+unsigned char *in, -+unsigned char *out, -+long length, -+des_key_schedule ks, -+des_cblock *ivec, -+int *num, -+int enc); -+ This is one of the more useful functions in this DES library, it -+ implements CFB mode of DES with 64bit feedback. Why is this -+ useful you ask? Because this routine will allow you to encrypt an -+ arbitrary number of bytes, no 8 byte padding. Each call to this -+ routine will encrypt the input bytes to output and then update ivec -+ and num. num contains 'how far' we are though ivec. If this does -+ not make much sense, read more about cfb mode of DES :-). -+ -+void des_ede3_cfb64_encrypt( -+unsigned char *in, -+unsigned char *out, -+long length, -+des_key_schedule ks1, -+des_key_schedule ks2, -+des_key_schedule ks3, -+des_cblock *ivec, -+int *num, -+int enc); -+ Same as des_cfb64_encrypt() accept that the DES operation is -+ triple DES. As usual, there is a macro for -+ des_ede2_cfb64_encrypt() which reuses ks1. -+ -+void des_ofb_encrypt( -+unsigned char *in, -+unsigned char *out, -+int numbits, -+long length, -+des_key_schedule ks, -+des_cblock *ivec); -+ This is a implementation of Output Feed Back mode of DES. It is -+ the same as des_cfb_encrypt() in that numbits is the size of the -+ units dealt with during input and output (in bits). -+ -+void des_ofb64_encrypt( -+unsigned char *in, -+unsigned char *out, -+long length, -+des_key_schedule ks, -+des_cblock *ivec, -+int *num); -+ The same as des_cfb64_encrypt() except that it is Output Feed Back -+ mode. -+ -+void des_ede3_ofb64_encrypt( -+unsigned char *in, -+unsigned char *out, -+long length, -+des_key_schedule ks1, -+des_key_schedule ks2, -+des_key_schedule ks3, -+des_cblock *ivec, -+int *num); -+ Same as des_ofb64_encrypt() accept that the DES operation is -+ triple DES. As usual, there is a macro for -+ des_ede2_ofb64_encrypt() which reuses ks1. -+ -+int des_read_pw_string( -+char *buf, -+int length, -+char *prompt, -+int verify); -+ This routine is used to get a password from the terminal with echo -+ turned off. Buf is where the string will end up and length is the -+ size of buf. Prompt is a string presented to the 'user' and if -+ verify is set, the key is asked for twice and unless the 2 copies -+ match, an error is returned. A return code of -1 indicates a -+ system error, 1 failure due to use interaction, and 0 is success. -+ -+unsigned long des_cbc_cksum( -+des_cblock *input, -+des_cblock *output, -+long length, -+des_key_schedule ks, -+des_cblock *ivec); -+ This function produces an 8 byte checksum from input that it puts in -+ output and returns the last 4 bytes as a long. The checksum is -+ generated via cbc mode of DES in which only the last 8 byes are -+ kept. I would recommend not using this function but instead using -+ the EVP_Digest routines, or at least using MD5 or SHA. This -+ function is used by Kerberos v4 so that is why it stays in the -+ library. -+ -+char *des_fcrypt( -+const char *buf, -+const char *salt -+char *ret); -+ This is my fast version of the unix crypt(3) function. This version -+ takes only a small amount of space relative to other fast -+ crypt() implementations. This is different to the normal crypt -+ in that the third parameter is the buffer that the return value -+ is written into. It needs to be at least 14 bytes long. This -+ function is thread safe, unlike the normal crypt. -+ -+char *crypt( -+const char *buf, -+const char *salt); -+ This function calls des_fcrypt() with a static array passed as the -+ third parameter. This emulates the normal non-thread safe semantics -+ of crypt(3). -+ -+void des_string_to_key( -+char *str, -+des_cblock *key); -+ This function takes str and converts it into a DES key. I would -+ recommend using MD5 instead and use the first 8 bytes of output. -+ When I wrote the first version of these routines back in 1990, MD5 -+ did not exist but I feel these routines are still sound. This -+ routines is compatible with the one in MIT's libdes. -+ -+void des_string_to_2keys( -+char *str, -+des_cblock *key1, -+des_cblock *key2); -+ This function takes str and converts it into 2 DES keys. -+ I would recommend using MD5 and using the 16 bytes as the 2 keys. -+ I have nothing against these 2 'string_to_key' routines, it's just -+ that if you say that your encryption key is generated by using the -+ 16 bytes of an MD5 hash, every-one knows how you generated your -+ keys. -+ -+int des_read_password( -+des_cblock *key, -+char *prompt, -+int verify); -+ This routine combines des_read_pw_string() with des_string_to_key(). -+ -+int des_read_2passwords( -+des_cblock *key1, -+des_cblock *key2, -+char *prompt, -+int verify); -+ This routine combines des_read_pw_string() with des_string_to_2key(). -+ -+void des_random_seed( -+des_cblock key); -+ This routine sets a starting point for des_random_key(). -+ -+void des_random_key( -+des_cblock ret); -+ This function return a random key. Make sure to 'seed' the random -+ number generator (with des_random_seed()) before using this function. -+ I personally now use a MD5 based random number system. -+ -+int des_enc_read( -+int fd, -+char *buf, -+int len, -+des_key_schedule ks, -+des_cblock *iv); -+ This function will write to a file descriptor the encrypted data -+ from buf. This data will be preceded by a 4 byte 'byte count' and -+ will be padded out to 8 bytes. The encryption is either CBC of -+ PCBC depending on the value of des_rw_mode. If it is DES_PCBC_MODE, -+ pcbc is used, if DES_CBC_MODE, cbc is used. The default is to use -+ DES_PCBC_MODE. -+ -+int des_enc_write( -+int fd, -+char *buf, -+int len, -+des_key_schedule ks, -+des_cblock *iv); -+ This routines read stuff written by des_enc_read() and decrypts it. -+ I have used these routines quite a lot but I don't believe they are -+ suitable for non-blocking io. If you are after a full -+ authentication/encryption over networks, have a look at SSL instead. -+ -+unsigned long des_quad_cksum( -+des_cblock *input, -+des_cblock *output, -+long length, -+int out_count, -+des_cblock *seed); -+ This is a function from Kerberos v4 that is not anything to do with -+ DES but was needed. It is a cksum that is quicker to generate than -+ des_cbc_cksum(); I personally would use MD5 routines now. -+===== -+Modes of DES -+Quite a bit of the following information has been taken from -+ AS 2805.5.2 -+ Australian Standard -+ Electronic funds transfer - Requirements for interfaces, -+ Part 5.2: Modes of operation for an n-bit block cipher algorithm -+ Appendix A -+ -+There are several different modes in which DES can be used, they are -+as follows. -+ -+Electronic Codebook Mode (ECB) (des_ecb_encrypt()) -+- 64 bits are enciphered at a time. -+- The order of the blocks can be rearranged without detection. -+- The same plaintext block always produces the same ciphertext block -+ (for the same key) making it vulnerable to a 'dictionary attack'. -+- An error will only affect one ciphertext block. -+ -+Cipher Block Chaining Mode (CBC) (des_cbc_encrypt()) -+- a multiple of 64 bits are enciphered at a time. -+- The CBC mode produces the same ciphertext whenever the same -+ plaintext is encrypted using the same key and starting variable. -+- The chaining operation makes the ciphertext blocks dependent on the -+ current and all preceding plaintext blocks and therefore blocks can not -+ be rearranged. -+- The use of different starting variables prevents the same plaintext -+ enciphering to the same ciphertext. -+- An error will affect the current and the following ciphertext blocks. -+ -+Cipher Feedback Mode (CFB) (des_cfb_encrypt()) -+- a number of bits (j) <= 64 are enciphered at a time. -+- The CFB mode produces the same ciphertext whenever the same -+ plaintext is encrypted using the same key and starting variable. -+- The chaining operation makes the ciphertext variables dependent on the -+ current and all preceding variables and therefore j-bit variables are -+ chained together and can not be rearranged. -+- The use of different starting variables prevents the same plaintext -+ enciphering to the same ciphertext. -+- The strength of the CFB mode depends on the size of k (maximal if -+ j == k). In my implementation this is always the case. -+- Selection of a small value for j will require more cycles through -+ the encipherment algorithm per unit of plaintext and thus cause -+ greater processing overheads. -+- Only multiples of j bits can be enciphered. -+- An error will affect the current and the following ciphertext variables. -+ -+Output Feedback Mode (OFB) (des_ofb_encrypt()) -+- a number of bits (j) <= 64 are enciphered at a time. -+- The OFB mode produces the same ciphertext whenever the same -+ plaintext enciphered using the same key and starting variable. More -+ over, in the OFB mode the same key stream is produced when the same -+ key and start variable are used. Consequently, for security reasons -+ a specific start variable should be used only once for a given key. -+- The absence of chaining makes the OFB more vulnerable to specific attacks. -+- The use of different start variables values prevents the same -+ plaintext enciphering to the same ciphertext, by producing different -+ key streams. -+- Selection of a small value for j will require more cycles through -+ the encipherment algorithm per unit of plaintext and thus cause -+ greater processing overheads. -+- Only multiples of j bits can be enciphered. -+- OFB mode of operation does not extend ciphertext errors in the -+ resultant plaintext output. Every bit error in the ciphertext causes -+ only one bit to be in error in the deciphered plaintext. -+- OFB mode is not self-synchronising. If the two operation of -+ encipherment and decipherment get out of synchronism, the system needs -+ to be re-initialised. -+- Each re-initialisation should use a value of the start variable -+ different from the start variable values used before with the same -+ key. The reason for this is that an identical bit stream would be -+ produced each time from the same parameters. This would be -+ susceptible to a ' known plaintext' attack. -+ -+Triple ECB Mode (des_ecb3_encrypt()) -+- Encrypt with key1, decrypt with key2 and encrypt with key3 again. -+- As for ECB encryption but increases the key length to 168 bits. -+ There are theoretic attacks that can be used that make the effective -+ key length 112 bits, but this attack also requires 2^56 blocks of -+ memory, not very likely, even for the NSA. -+- If both keys are the same it is equivalent to encrypting once with -+ just one key. -+- If the first and last key are the same, the key length is 112 bits. -+ There are attacks that could reduce the key space to 55 bit's but it -+ requires 2^56 blocks of memory. -+- If all 3 keys are the same, this is effectively the same as normal -+ ecb mode. -+ -+Triple CBC Mode (des_ede3_cbc_encrypt()) -+- Encrypt with key1, decrypt with key2 and then encrypt with key3. -+- As for CBC encryption but increases the key length to 168 bits with -+ the same restrictions as for triple ecb mode. ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/des_crypt.man Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,508 @@ -+.TH DES_CRYPT 3 -+.SH NAME -+des_read_password, des_read_2password, -+des_string_to_key, des_string_to_2key, des_read_pw_string, -+des_random_key, des_set_key, -+des_key_sched, des_ecb_encrypt, des_ecb3_encrypt, des_cbc_encrypt, -+des_3cbc_encrypt, -+des_pcbc_encrypt, des_cfb_encrypt, des_ofb_encrypt, -+des_cbc_cksum, des_quad_cksum, -+des_enc_read, des_enc_write, des_set_odd_parity, -+des_is_weak_key, crypt \- (non USA) DES encryption -+.SH SYNOPSIS -+.nf -+.nj -+.ft B -+#include -+.PP -+.B int des_read_password(key,prompt,verify) -+des_cblock *key; -+char *prompt; -+int verify; -+.PP -+.B int des_read_2password(key1,key2,prompt,verify) -+des_cblock *key1,*key2; -+char *prompt; -+int verify; -+.PP -+.B int des_string_to_key(str,key) -+char *str; -+des_cblock *key; -+.PP -+.B int des_string_to_2keys(str,key1,key2) -+char *str; -+des_cblock *key1,*key2; -+.PP -+.B int des_read_pw_string(buf,length,prompt,verify) -+char *buf; -+int length; -+char *prompt; -+int verify; -+.PP -+.B int des_random_key(key) -+des_cblock *key; -+.PP -+.B int des_set_key(key,schedule) -+des_cblock *key; -+des_key_schedule schedule; -+.PP -+.B int des_key_sched(key,schedule) -+des_cblock *key; -+des_key_schedule schedule; -+.PP -+.B int des_ecb_encrypt(input,output,schedule,encrypt) -+des_cblock *input; -+des_cblock *output; -+des_key_schedule schedule; -+int encrypt; -+.PP -+.B int des_ecb3_encrypt(input,output,ks1,ks2,encrypt) -+des_cblock *input; -+des_cblock *output; -+des_key_schedule ks1,ks2; -+int encrypt; -+.PP -+.B int des_cbc_encrypt(input,output,length,schedule,ivec,encrypt) -+des_cblock *input; -+des_cblock *output; -+long length; -+des_key_schedule schedule; -+des_cblock *ivec; -+int encrypt; -+.PP -+.B int des_3cbc_encrypt(input,output,length,sk1,sk2,ivec1,ivec2,encrypt) -+des_cblock *input; -+des_cblock *output; -+long length; -+des_key_schedule sk1; -+des_key_schedule sk2; -+des_cblock *ivec1; -+des_cblock *ivec2; -+int encrypt; -+.PP -+.B int des_pcbc_encrypt(input,output,length,schedule,ivec,encrypt) -+des_cblock *input; -+des_cblock *output; -+long length; -+des_key_schedule schedule; -+des_cblock *ivec; -+int encrypt; -+.PP -+.B int des_cfb_encrypt(input,output,numbits,length,schedule,ivec,encrypt) -+unsigned char *input; -+unsigned char *output; -+int numbits; -+long length; -+des_key_schedule schedule; -+des_cblock *ivec; -+int encrypt; -+.PP -+.B int des_ofb_encrypt(input,output,numbits,length,schedule,ivec) -+unsigned char *input,*output; -+int numbits; -+long length; -+des_key_schedule schedule; -+des_cblock *ivec; -+.PP -+.B unsigned long des_cbc_cksum(input,output,length,schedule,ivec) -+des_cblock *input; -+des_cblock *output; -+long length; -+des_key_schedule schedule; -+des_cblock *ivec; -+.PP -+.B unsigned long des_quad_cksum(input,output,length,out_count,seed) -+des_cblock *input; -+des_cblock *output; -+long length; -+int out_count; -+des_cblock *seed; -+.PP -+.B int des_check_key; -+.PP -+.B int des_enc_read(fd,buf,len,sched,iv) -+int fd; -+char *buf; -+int len; -+des_key_schedule sched; -+des_cblock *iv; -+.PP -+.B int des_enc_write(fd,buf,len,sched,iv) -+int fd; -+char *buf; -+int len; -+des_key_schedule sched; -+des_cblock *iv; -+.PP -+.B extern int des_rw_mode; -+.PP -+.B void des_set_odd_parity(key) -+des_cblock *key; -+.PP -+.B int des_is_weak_key(key) -+des_cblock *key; -+.PP -+.B char *crypt(passwd,salt) -+char *passwd; -+char *salt; -+.PP -+.fi -+.SH DESCRIPTION -+This library contains a fast implementation of the DES encryption -+algorithm. -+.PP -+There are two phases to the use of DES encryption. -+The first is the generation of a -+.I des_key_schedule -+from a key, -+the second is the actual encryption. -+A des key is of type -+.I des_cblock. -+This type is made from 8 characters with odd parity. -+The least significant bit in the character is the parity bit. -+The key schedule is an expanded form of the key; it is used to speed the -+encryption process. -+.PP -+.I des_read_password -+writes the string specified by prompt to the standard output, -+turns off echo and reads an input string from standard input -+until terminated with a newline. -+If verify is non-zero, it prompts and reads the input again and verifies -+that both entered passwords are the same. -+The entered string is converted into a des key by using the -+.I des_string_to_key -+routine. -+The new key is placed in the -+.I des_cblock -+that was passed (by reference) to the routine. -+If there were no errors, -+.I des_read_password -+returns 0, -+-1 is returned if there was a terminal error and 1 is returned for -+any other error. -+.PP -+.I des_read_2password -+operates in the same way as -+.I des_read_password -+except that it generates 2 keys by using the -+.I des_string_to_2key -+function. -+.PP -+.I des_read_pw_string -+is called by -+.I des_read_password -+to read and verify a string from a terminal device. -+The string is returned in -+.I buf. -+The size of -+.I buf -+is passed to the routine via the -+.I length -+parameter. -+.PP -+.I des_string_to_key -+converts a string into a valid des key. -+.PP -+.I des_string_to_2key -+converts a string into 2 valid des keys. -+This routine is best suited for used to generate keys for use with -+.I des_ecb3_encrypt. -+.PP -+.I des_random_key -+returns a random key that is made of a combination of process id, -+time and an increasing counter. -+.PP -+Before a des key can be used it is converted into a -+.I des_key_schedule -+via the -+.I des_set_key -+routine. -+If the -+.I des_check_key -+flag is non-zero, -+.I des_set_key -+will check that the key passed is of odd parity and is not a week or -+semi-weak key. -+If the parity is wrong, -+then -1 is returned. -+If the key is a weak key, -+then -2 is returned. -+If an error is returned, -+the key schedule is not generated. -+.PP -+.I des_key_sched -+is another name for the -+.I des_set_key -+function. -+.PP -+The following routines mostly operate on an input and output stream of -+.I des_cblock's. -+.PP -+.I des_ecb_encrypt -+is the basic DES encryption routine that encrypts or decrypts a single 8-byte -+.I des_cblock -+in -+.I electronic code book -+mode. -+It always transforms the input data, pointed to by -+.I input, -+into the output data, -+pointed to by the -+.I output -+argument. -+If the -+.I encrypt -+argument is non-zero (DES_ENCRYPT), -+the -+.I input -+(cleartext) is encrypted in to the -+.I output -+(ciphertext) using the key_schedule specified by the -+.I schedule -+argument, -+previously set via -+.I des_set_key. -+If -+.I encrypt -+is zero (DES_DECRYPT), -+the -+.I input -+(now ciphertext) -+is decrypted into the -+.I output -+(now cleartext). -+Input and output may overlap. -+No meaningful value is returned. -+.PP -+.I des_ecb3_encrypt -+encrypts/decrypts the -+.I input -+block by using triple ecb DES encryption. -+This involves encrypting the input with -+.I ks1, -+decryption with the key schedule -+.I ks2, -+and then encryption with the first again. -+This routine greatly reduces the chances of brute force breaking of -+DES and has the advantage of if -+.I ks1 -+and -+.I ks2 -+are the same, it is equivalent to just encryption using ecb mode and -+.I ks1 -+as the key. -+.PP -+.I des_cbc_encrypt -+encrypts/decrypts using the -+.I cipher-block-chaining -+mode of DES. -+If the -+.I encrypt -+argument is non-zero, -+the routine cipher-block-chain encrypts the cleartext data pointed to by the -+.I input -+argument into the ciphertext pointed to by the -+.I output -+argument, -+using the key schedule provided by the -+.I schedule -+argument, -+and initialisation vector provided by the -+.I ivec -+argument. -+If the -+.I length -+argument is not an integral multiple of eight bytes, -+the last block is copied to a temporary area and zero filled. -+The output is always -+an integral multiple of eight bytes. -+To make multiple cbc encrypt calls on a large amount of data appear to -+be one -+.I des_cbc_encrypt -+call, the -+.I ivec -+of subsequent calls should be the last 8 bytes of the output. -+.PP -+.I des_3cbc_encrypt -+encrypts/decrypts the -+.I input -+block by using triple cbc DES encryption. -+This involves encrypting the input with key schedule -+.I ks1, -+decryption with the key schedule -+.I ks2, -+and then encryption with the first again. -+2 initialisation vectors are required, -+.I ivec1 -+and -+.I ivec2. -+Unlike -+.I des_cbc_encrypt, -+these initialisation vectors are modified by the subroutine. -+This routine greatly reduces the chances of brute force breaking of -+DES and has the advantage of if -+.I ks1 -+and -+.I ks2 -+are the same, it is equivalent to just encryption using cbc mode and -+.I ks1 -+as the key. -+.PP -+.I des_pcbc_encrypt -+encrypt/decrypts using a modified block chaining mode. -+It provides better error propagation characteristics than cbc -+encryption. -+.PP -+.I des_cfb_encrypt -+encrypt/decrypts using cipher feedback mode. This method takes an -+array of characters as input and outputs and array of characters. It -+does not require any padding to 8 character groups. Note: the ivec -+variable is changed and the new changed value needs to be passed to -+the next call to this function. Since this function runs a complete -+DES ecb encryption per numbits, this function is only suggested for -+use when sending small numbers of characters. -+.PP -+.I des_ofb_encrypt -+encrypt using output feedback mode. This method takes an -+array of characters as input and outputs and array of characters. It -+does not require any padding to 8 character groups. Note: the ivec -+variable is changed and the new changed value needs to be passed to -+the next call to this function. Since this function runs a complete -+DES ecb encryption per numbits, this function is only suggested for -+use when sending small numbers of characters. -+.PP -+.I des_cbc_cksum -+produces an 8 byte checksum based on the input stream (via cbc encryption). -+The last 4 bytes of the checksum is returned and the complete 8 bytes is -+placed in -+.I output. -+.PP -+.I des_quad_cksum -+returns a 4 byte checksum from the input bytes. -+The algorithm can be iterated over the input, -+depending on -+.I out_count, -+1, 2, 3 or 4 times. -+If -+.I output -+is non-NULL, -+the 8 bytes generated by each pass are written into -+.I output. -+.PP -+.I des_enc_write -+is used to write -+.I len -+bytes -+to file descriptor -+.I fd -+from buffer -+.I buf. -+The data is encrypted via -+.I pcbc_encrypt -+(default) using -+.I sched -+for the key and -+.I iv -+as a starting vector. -+The actual data send down -+.I fd -+consists of 4 bytes (in network byte order) containing the length of the -+following encrypted data. The encrypted data then follows, padded with random -+data out to a multiple of 8 bytes. -+.PP -+.I des_enc_read -+is used to read -+.I len -+bytes -+from file descriptor -+.I fd -+into buffer -+.I buf. -+The data being read from -+.I fd -+is assumed to have come from -+.I des_enc_write -+and is decrypted using -+.I sched -+for the key schedule and -+.I iv -+for the initial vector. -+The -+.I des_enc_read/des_enc_write -+pair can be used to read/write to files, pipes and sockets. -+I have used them in implementing a version of rlogin in which all -+data is encrypted. -+.PP -+.I des_rw_mode -+is used to specify the encryption mode to use with -+.I des_enc_read -+and -+.I des_end_write. -+If set to -+.I DES_PCBC_MODE -+(the default), des_pcbc_encrypt is used. -+If set to -+.I DES_CBC_MODE -+des_cbc_encrypt is used. -+These two routines and the variable are not part of the normal MIT library. -+.PP -+.I des_set_odd_parity -+sets the parity of the passed -+.I key -+to odd. This routine is not part of the standard MIT library. -+.PP -+.I des_is_weak_key -+returns 1 is the passed key is a weak key (pick again :-), -+0 if it is ok. -+This routine is not part of the standard MIT library. -+.PP -+.I crypt -+is a replacement for the normal system crypt. -+It is much faster than the system crypt. -+.PP -+.SH FILES -+/usr/include/des.h -+.br -+/usr/lib/libdes.a -+.PP -+The encryption routines have been tested on 16bit, 32bit and 64bit -+machines of various endian and even works under VMS. -+.PP -+.SH BUGS -+.PP -+If you think this manual is sparse, -+read the des_crypt(3) manual from the MIT kerberos (or bones outside -+of the USA) distribution. -+.PP -+.I des_cfb_encrypt -+and -+.I des_ofb_encrypt -+operates on input of 8 bits. What this means is that if you set -+numbits to 12, and length to 2, the first 12 bits will come from the 1st -+input byte and the low half of the second input byte. The second 12 -+bits will have the low 8 bits taken from the 3rd input byte and the -+top 4 bits taken from the 4th input byte. The same holds for output. -+This function has been implemented this way because most people will -+be using a multiple of 8 and because once you get into pulling bytes input -+bytes apart things get ugly! -+.PP -+.I des_read_pw_string -+is the most machine/OS dependent function and normally generates the -+most problems when porting this code. -+.PP -+.I des_string_to_key -+is probably different from the MIT version since there are lots -+of fun ways to implement one-way encryption of a text string. -+.PP -+The routines are optimised for 32 bit machines and so are not efficient -+on IBM PCs. -+.PP -+NOTE: extensive work has been done on this library since this document -+was origionally written. Please try to read des.doc from the libdes -+distribution since it is far more upto date and documents more of the -+functions. Libdes is now also being shipped as part of SSLeay, a -+general cryptographic library that amonst other things implements -+netscapes SSL protocoll. The most recent version can be found in -+SSLeay distributions. -+.SH AUTHOR -+Eric Young (eay@cryptsoft.com) ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/des_enc.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,502 @@ -+/* crypto/des/des_enc.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+#include "des_locl.h" -+ -+void des_encrypt(data, ks, enc) -+DES_LONG *data; -+des_key_schedule ks; -+int enc; -+ { -+ register DES_LONG l,r,t,u; -+#ifdef DES_PTR -+ register unsigned char *des_SP=(unsigned char *)des_SPtrans; -+#endif -+#ifndef DES_UNROLL -+ register int i; -+#endif -+ register DES_LONG *s; -+ -+ r=data[0]; -+ l=data[1]; -+ -+ IP(r,l); -+ /* Things have been modified so that the initial rotate is -+ * done outside the loop. This required the -+ * des_SPtrans values in sp.h to be rotated 1 bit to the right. -+ * One perl script later and things have a 5% speed up on a sparc2. -+ * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> -+ * for pointing this out. */ -+ /* clear the top bits on machines with 8byte longs */ -+ /* shift left by 2 */ -+ r=ROTATE(r,29)&0xffffffffL; -+ l=ROTATE(l,29)&0xffffffffL; -+ -+ s=(DES_LONG *)ks; -+ /* I don't know if it is worth the effort of loop unrolling the -+ * inner loop */ -+ if (enc) -+ { -+#ifdef DES_UNROLL -+ D_ENCRYPT(l,r, 0); /* 1 */ -+ D_ENCRYPT(r,l, 2); /* 2 */ -+ D_ENCRYPT(l,r, 4); /* 3 */ -+ D_ENCRYPT(r,l, 6); /* 4 */ -+ D_ENCRYPT(l,r, 8); /* 5 */ -+ D_ENCRYPT(r,l,10); /* 6 */ -+ D_ENCRYPT(l,r,12); /* 7 */ -+ D_ENCRYPT(r,l,14); /* 8 */ -+ D_ENCRYPT(l,r,16); /* 9 */ -+ D_ENCRYPT(r,l,18); /* 10 */ -+ D_ENCRYPT(l,r,20); /* 11 */ -+ D_ENCRYPT(r,l,22); /* 12 */ -+ D_ENCRYPT(l,r,24); /* 13 */ -+ D_ENCRYPT(r,l,26); /* 14 */ -+ D_ENCRYPT(l,r,28); /* 15 */ -+ D_ENCRYPT(r,l,30); /* 16 */ -+#else -+ for (i=0; i<32; i+=8) -+ { -+ D_ENCRYPT(l,r,i+0); /* 1 */ -+ D_ENCRYPT(r,l,i+2); /* 2 */ -+ D_ENCRYPT(l,r,i+4); /* 3 */ -+ D_ENCRYPT(r,l,i+6); /* 4 */ -+ } -+#endif -+ } -+ else -+ { -+#ifdef DES_UNROLL -+ D_ENCRYPT(l,r,30); /* 16 */ -+ D_ENCRYPT(r,l,28); /* 15 */ -+ D_ENCRYPT(l,r,26); /* 14 */ -+ D_ENCRYPT(r,l,24); /* 13 */ -+ D_ENCRYPT(l,r,22); /* 12 */ -+ D_ENCRYPT(r,l,20); /* 11 */ -+ D_ENCRYPT(l,r,18); /* 10 */ -+ D_ENCRYPT(r,l,16); /* 9 */ -+ D_ENCRYPT(l,r,14); /* 8 */ -+ D_ENCRYPT(r,l,12); /* 7 */ -+ D_ENCRYPT(l,r,10); /* 6 */ -+ D_ENCRYPT(r,l, 8); /* 5 */ -+ D_ENCRYPT(l,r, 6); /* 4 */ -+ D_ENCRYPT(r,l, 4); /* 3 */ -+ D_ENCRYPT(l,r, 2); /* 2 */ -+ D_ENCRYPT(r,l, 0); /* 1 */ -+#else -+ for (i=30; i>0; i-=8) -+ { -+ D_ENCRYPT(l,r,i-0); /* 16 */ -+ D_ENCRYPT(r,l,i-2); /* 15 */ -+ D_ENCRYPT(l,r,i-4); /* 14 */ -+ D_ENCRYPT(r,l,i-6); /* 13 */ -+ } -+#endif -+ } -+ -+ /* rotate and clear the top bits on machines with 8byte longs */ -+ l=ROTATE(l,3)&0xffffffffL; -+ r=ROTATE(r,3)&0xffffffffL; -+ -+ FP(r,l); -+ data[0]=l; -+ data[1]=r; -+ l=r=t=u=0; -+ } -+ -+void des_encrypt2(data, ks, enc) -+DES_LONG *data; -+des_key_schedule ks; -+int enc; -+ { -+ register DES_LONG l,r,t,u; -+#ifdef DES_PTR -+ register unsigned char *des_SP=(unsigned char *)des_SPtrans; -+#endif -+#ifndef DES_UNROLL -+ register int i; -+#endif -+ register DES_LONG *s; -+ -+ r=data[0]; -+ l=data[1]; -+ -+ /* Things have been modified so that the initial rotate is -+ * done outside the loop. This required the -+ * des_SPtrans values in sp.h to be rotated 1 bit to the right. -+ * One perl script later and things have a 5% speed up on a sparc2. -+ * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> -+ * for pointing this out. */ -+ /* clear the top bits on machines with 8byte longs */ -+ r=ROTATE(r,29)&0xffffffffL; -+ l=ROTATE(l,29)&0xffffffffL; -+ -+ s=(DES_LONG *)ks; -+ /* I don't know if it is worth the effort of loop unrolling the -+ * inner loop */ -+ if (enc) -+ { -+#ifdef DES_UNROLL -+ D_ENCRYPT(l,r, 0); /* 1 */ -+ D_ENCRYPT(r,l, 2); /* 2 */ -+ D_ENCRYPT(l,r, 4); /* 3 */ -+ D_ENCRYPT(r,l, 6); /* 4 */ -+ D_ENCRYPT(l,r, 8); /* 5 */ -+ D_ENCRYPT(r,l,10); /* 6 */ -+ D_ENCRYPT(l,r,12); /* 7 */ -+ D_ENCRYPT(r,l,14); /* 8 */ -+ D_ENCRYPT(l,r,16); /* 9 */ -+ D_ENCRYPT(r,l,18); /* 10 */ -+ D_ENCRYPT(l,r,20); /* 11 */ -+ D_ENCRYPT(r,l,22); /* 12 */ -+ D_ENCRYPT(l,r,24); /* 13 */ -+ D_ENCRYPT(r,l,26); /* 14 */ -+ D_ENCRYPT(l,r,28); /* 15 */ -+ D_ENCRYPT(r,l,30); /* 16 */ -+#else -+ for (i=0; i<32; i+=8) -+ { -+ D_ENCRYPT(l,r,i+0); /* 1 */ -+ D_ENCRYPT(r,l,i+2); /* 2 */ -+ D_ENCRYPT(l,r,i+4); /* 3 */ -+ D_ENCRYPT(r,l,i+6); /* 4 */ -+ } -+#endif -+ } -+ else -+ { -+#ifdef DES_UNROLL -+ D_ENCRYPT(l,r,30); /* 16 */ -+ D_ENCRYPT(r,l,28); /* 15 */ -+ D_ENCRYPT(l,r,26); /* 14 */ -+ D_ENCRYPT(r,l,24); /* 13 */ -+ D_ENCRYPT(l,r,22); /* 12 */ -+ D_ENCRYPT(r,l,20); /* 11 */ -+ D_ENCRYPT(l,r,18); /* 10 */ -+ D_ENCRYPT(r,l,16); /* 9 */ -+ D_ENCRYPT(l,r,14); /* 8 */ -+ D_ENCRYPT(r,l,12); /* 7 */ -+ D_ENCRYPT(l,r,10); /* 6 */ -+ D_ENCRYPT(r,l, 8); /* 5 */ -+ D_ENCRYPT(l,r, 6); /* 4 */ -+ D_ENCRYPT(r,l, 4); /* 3 */ -+ D_ENCRYPT(l,r, 2); /* 2 */ -+ D_ENCRYPT(r,l, 0); /* 1 */ -+#else -+ for (i=30; i>0; i-=8) -+ { -+ D_ENCRYPT(l,r,i-0); /* 16 */ -+ D_ENCRYPT(r,l,i-2); /* 15 */ -+ D_ENCRYPT(l,r,i-4); /* 14 */ -+ D_ENCRYPT(r,l,i-6); /* 13 */ -+ } -+#endif -+ } -+ /* rotate and clear the top bits on machines with 8byte longs */ -+ data[0]=ROTATE(l,3)&0xffffffffL; -+ data[1]=ROTATE(r,3)&0xffffffffL; -+ l=r=t=u=0; -+ } -+ -+void des_encrypt3(data,ks1,ks2,ks3) -+DES_LONG *data; -+des_key_schedule ks1; -+des_key_schedule ks2; -+des_key_schedule ks3; -+ { -+ register DES_LONG l,r; -+ -+ l=data[0]; -+ r=data[1]; -+ IP(l,r); -+ data[0]=l; -+ data[1]=r; -+ des_encrypt2((DES_LONG *)data,ks1,DES_ENCRYPT); -+ des_encrypt2((DES_LONG *)data,ks2,DES_DECRYPT); -+ des_encrypt2((DES_LONG *)data,ks3,DES_ENCRYPT); -+ l=data[0]; -+ r=data[1]; -+ FP(r,l); -+ data[0]=l; -+ data[1]=r; -+ } -+ -+void des_decrypt3(data,ks1,ks2,ks3) -+DES_LONG *data; -+des_key_schedule ks1; -+des_key_schedule ks2; -+des_key_schedule ks3; -+ { -+ register DES_LONG l,r; -+ -+ l=data[0]; -+ r=data[1]; -+ IP(l,r); -+ data[0]=l; -+ data[1]=r; -+ des_encrypt2((DES_LONG *)data,ks3,DES_DECRYPT); -+ des_encrypt2((DES_LONG *)data,ks2,DES_ENCRYPT); -+ des_encrypt2((DES_LONG *)data,ks1,DES_DECRYPT); -+ l=data[0]; -+ r=data[1]; -+ FP(r,l); -+ data[0]=l; -+ data[1]=r; -+ } -+ -+#ifndef DES_DEFAULT_OPTIONS -+ -+void des_ncbc_encrypt(input, output, length, schedule, ivec, enc) -+des_cblock (*input); -+des_cblock (*output); -+long length; -+des_key_schedule schedule; -+des_cblock (*ivec); -+int enc; -+ { -+ register DES_LONG tin0,tin1; -+ register DES_LONG tout0,tout1,xor0,xor1; -+ register unsigned char *in,*out; -+ register long l=length; -+ DES_LONG tin[2]; -+ unsigned char *iv; -+ -+ in=(unsigned char *)input; -+ out=(unsigned char *)output; -+ iv=(unsigned char *)ivec; -+ -+ if (enc) -+ { -+ c2l(iv,tout0); -+ c2l(iv,tout1); -+ for (l-=8; l>=0; l-=8) -+ { -+ c2l(in,tin0); -+ c2l(in,tin1); -+ tin0^=tout0; tin[0]=tin0; -+ tin1^=tout1; tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); -+ tout0=tin[0]; l2c(tout0,out); -+ tout1=tin[1]; l2c(tout1,out); -+ } -+ if (l != -8) -+ { -+ c2ln(in,tin0,tin1,l+8); -+ tin0^=tout0; tin[0]=tin0; -+ tin1^=tout1; tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); -+ tout0=tin[0]; l2c(tout0,out); -+ tout1=tin[1]; l2c(tout1,out); -+ } -+ iv=(unsigned char *)ivec; -+ l2c(tout0,iv); -+ l2c(tout1,iv); -+ } -+ else -+ { -+ c2l(iv,xor0); -+ c2l(iv,xor1); -+ for (l-=8; l>=0; l-=8) -+ { -+ c2l(in,tin0); tin[0]=tin0; -+ c2l(in,tin1); tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); -+ tout0=tin[0]^xor0; -+ tout1=tin[1]^xor1; -+ l2c(tout0,out); -+ l2c(tout1,out); -+ xor0=tin0; -+ xor1=tin1; -+ } -+ if (l != -8) -+ { -+ c2l(in,tin0); tin[0]=tin0; -+ c2l(in,tin1); tin[1]=tin1; -+ des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); -+ tout0=tin[0]^xor0; -+ tout1=tin[1]^xor1; -+ l2cn(tout0,tout1,out,l+8); -+ xor0=tin0; -+ xor1=tin1; -+ } -+ -+ iv=(unsigned char *)ivec; -+ l2c(xor0,iv); -+ l2c(xor1,iv); -+ } -+ tin0=tin1=tout0=tout1=xor0=xor1=0; -+ tin[0]=tin[1]=0; -+ } -+ -+void des_ede3_cbc_encrypt(input, output, length, ks1, ks2, ks3, ivec, enc) -+des_cblock (*input); -+des_cblock (*output); -+long length; -+des_key_schedule ks1; -+des_key_schedule ks2; -+des_key_schedule ks3; -+des_cblock (*ivec); -+int enc; -+ { -+ register DES_LONG tin0,tin1; -+ register DES_LONG tout0,tout1,xor0,xor1; -+ register unsigned char *in,*out; -+ register long l=length; -+ DES_LONG tin[2]; -+ unsigned char *iv; -+ -+ in=(unsigned char *)input; -+ out=(unsigned char *)output; -+ iv=(unsigned char *)ivec; -+ -+ if (enc) -+ { -+ c2l(iv,tout0); -+ c2l(iv,tout1); -+ for (l-=8; l>=0; l-=8) -+ { -+ c2l(in,tin0); -+ c2l(in,tin1); -+ tin0^=tout0; -+ tin1^=tout1; -+ -+ tin[0]=tin0; -+ tin[1]=tin1; -+ des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); -+ tout0=tin[0]; -+ tout1=tin[1]; -+ -+ l2c(tout0,out); -+ l2c(tout1,out); -+ } -+ if (l != -8) -+ { -+ c2ln(in,tin0,tin1,l+8); -+ tin0^=tout0; -+ tin1^=tout1; -+ -+ tin[0]=tin0; -+ tin[1]=tin1; -+ des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); -+ tout0=tin[0]; -+ tout1=tin[1]; -+ -+ l2c(tout0,out); -+ l2c(tout1,out); -+ } -+ iv=(unsigned char *)ivec; -+ l2c(tout0,iv); -+ l2c(tout1,iv); -+ } -+ else -+ { -+ register DES_LONG t0,t1; -+ -+ c2l(iv,xor0); -+ c2l(iv,xor1); -+ for (l-=8; l>=0; l-=8) -+ { -+ c2l(in,tin0); -+ c2l(in,tin1); -+ -+ t0=tin0; -+ t1=tin1; -+ -+ tin[0]=tin0; -+ tin[1]=tin1; -+ des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); -+ tout0=tin[0]; -+ tout1=tin[1]; -+ -+ tout0^=xor0; -+ tout1^=xor1; -+ l2c(tout0,out); -+ l2c(tout1,out); -+ xor0=t0; -+ xor1=t1; -+ } -+ if (l != -8) -+ { -+ c2l(in,tin0); -+ c2l(in,tin1); -+ -+ t0=tin0; -+ t1=tin1; -+ -+ tin[0]=tin0; -+ tin[1]=tin1; -+ des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); -+ tout0=tin[0]; -+ tout1=tin[1]; -+ -+ tout0^=xor0; -+ tout1^=xor1; -+ l2cn(tout0,tout1,out,l+8); -+ xor0=t0; -+ xor1=t1; -+ } -+ -+ iv=(unsigned char *)ivec; -+ l2c(xor0,iv); -+ l2c(xor1,iv); -+ } -+ tin0=tin1=tout0=tout1=xor0=xor1=0; -+ tin[0]=tin[1]=0; -+ } -+ -+#endif /* DES_DEFAULT_OPTIONS */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/des_locl.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,515 @@ -+/* crypto/des/des_locl.org */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING -+ * -+ * Always modify des_locl.org since des_locl.h is automatically generated from -+ * it during SSLeay configuration. -+ * -+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING -+ */ -+ -+#ifndef HEADER_DES_LOCL_H -+#define HEADER_DES_LOCL_H -+ -+#if defined(WIN32) || defined(WIN16) -+#ifndef MSDOS -+#define MSDOS -+#endif -+#endif -+ -+#include "crypto/des.h" -+ -+#ifndef DES_DEFAULT_OPTIONS -+/* the following is tweaked from a config script, that is why it is a -+ * protected undef/define */ -+#ifndef DES_PTR -+#define DES_PTR -+#endif -+ -+/* This helps C compiler generate the correct code for multiple functional -+ * units. It reduces register dependancies at the expense of 2 more -+ * registers */ -+#ifndef DES_RISC1 -+#define DES_RISC1 -+#endif -+ -+#ifndef DES_RISC2 -+#undef DES_RISC2 -+#endif -+ -+#if defined(DES_RISC1) && defined(DES_RISC2) -+YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! -+#endif -+ -+/* Unroll the inner loop, this sometimes helps, sometimes hinders. -+ * Very mucy CPU dependant */ -+#ifndef DES_UNROLL -+#define DES_UNROLL -+#endif -+ -+/* These default values were supplied by -+ * Peter Gutman -+ * They are only used if nothing else has been defined */ -+#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) -+/* Special defines which change the way the code is built depending on the -+ CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find -+ even newer MIPS CPU's, but at the moment one size fits all for -+ optimization options. Older Sparc's work better with only UNROLL, but -+ there's no way to tell at compile time what it is you're running on */ -+ -+#if defined( sun ) /* Newer Sparc's */ -+ #define DES_PTR -+ #define DES_RISC1 -+ #define DES_UNROLL -+#elif defined( __ultrix ) /* Older MIPS */ -+ #define DES_PTR -+ #define DES_RISC2 -+ #define DES_UNROLL -+#elif defined( __osf1__ ) /* Alpha */ -+ #define DES_PTR -+ #define DES_RISC2 -+#elif defined ( _AIX ) /* RS6000 */ -+ /* Unknown */ -+#elif defined( __hpux ) /* HP-PA */ -+ /* Unknown */ -+#elif defined( __aux ) /* 68K */ -+ /* Unknown */ -+#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ -+ #define DES_UNROLL -+#elif defined( __sgi ) /* Newer MIPS */ -+ #define DES_PTR -+ #define DES_RISC2 -+ #define DES_UNROLL -+#elif defined( i386 ) /* x86 boxes, should be gcc */ -+ #define DES_PTR -+ #define DES_RISC1 -+ #define DES_UNROLL -+#endif /* Systems-specific speed defines */ -+#endif -+ -+#endif /* DES_DEFAULT_OPTIONS */ -+ -+#ifdef MSDOS /* Visual C++ 2.1 (Windows NT/95) */ -+#include -+#include -+#include -+#include -+#ifndef RAND -+#define RAND -+#endif -+#undef NOPROTO -+#endif -+ -+#if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS) -+#ifndef __KERNEL__ -+#include -+#else -+#include -+#endif -+#endif -+ -+#ifndef RAND -+#define RAND -+#endif -+ -+#ifdef linux -+#undef RAND -+#endif -+ -+#ifdef MSDOS -+#define getpid() 2 -+#define RAND -+#undef NOPROTO -+#endif -+ -+#if defined(NOCONST) -+#define const -+#endif -+ -+#ifdef __STDC__ -+#undef NOPROTO -+#endif -+ -+#ifdef RAND -+#define srandom(s) srand(s) -+#define random rand -+#endif -+ -+#define ITERATIONS 16 -+#define HALF_ITERATIONS 8 -+ -+/* used in des_read and des_write */ -+#define MAXWRITE (1024*16) -+#define BSIZE (MAXWRITE+4) -+ -+#define c2l(c,l) (l =((DES_LONG)(*((c)++))) , \ -+ l|=((DES_LONG)(*((c)++)))<< 8L, \ -+ l|=((DES_LONG)(*((c)++)))<<16L, \ -+ l|=((DES_LONG)(*((c)++)))<<24L) -+ -+/* NOTE - c is not incremented as per c2l */ -+#define c2ln(c,l1,l2,n) { \ -+ c+=n; \ -+ l1=l2=0; \ -+ switch (n) { \ -+ case 8: l2 =((DES_LONG)(*(--(c))))<<24L; \ -+ case 7: l2|=((DES_LONG)(*(--(c))))<<16L; \ -+ case 6: l2|=((DES_LONG)(*(--(c))))<< 8L; \ -+ case 5: l2|=((DES_LONG)(*(--(c)))); \ -+ case 4: l1 =((DES_LONG)(*(--(c))))<<24L; \ -+ case 3: l1|=((DES_LONG)(*(--(c))))<<16L; \ -+ case 2: l1|=((DES_LONG)(*(--(c))))<< 8L; \ -+ case 1: l1|=((DES_LONG)(*(--(c)))); \ -+ } \ -+ } -+ -+#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ -+ *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ -+ *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ -+ *((c)++)=(unsigned char)(((l)>>24L)&0xff)) -+ -+/* replacements for htonl and ntohl since I have no idea what to do -+ * when faced with machines with 8 byte longs. */ -+#define HDRSIZE 4 -+ -+#define n2l(c,l) (l =((DES_LONG)(*((c)++)))<<24L, \ -+ l|=((DES_LONG)(*((c)++)))<<16L, \ -+ l|=((DES_LONG)(*((c)++)))<< 8L, \ -+ l|=((DES_LONG)(*((c)++)))) -+ -+#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ -+ *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ -+ *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ -+ *((c)++)=(unsigned char)(((l) )&0xff)) -+ -+/* NOTE - c is not incremented as per l2c */ -+#define l2cn(l1,l2,c,n) { \ -+ c+=n; \ -+ switch (n) { \ -+ case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ -+ case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ -+ case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ -+ case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ -+ case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ -+ case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ -+ case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ -+ case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ -+ } \ -+ } -+ -+#if defined(WIN32) -+#define ROTATE(a,n) (_lrotr(a,n)) -+#else -+#define ROTATE(a,n) (((a)>>(n))+((a)<<(32-(n)))) -+#endif -+ -+/* Don't worry about the LOAD_DATA() stuff, that is used by -+ * fcrypt() to add it's little bit to the front */ -+ -+#ifdef DES_FCRYPT -+ -+#define LOAD_DATA_tmp(R,S,u,t,E0,E1) \ -+ { DES_LONG tmp; LOAD_DATA(R,S,u,t,E0,E1,tmp); } -+ -+#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ -+ t=R^(R>>16L); \ -+ u=t&E0; t&=E1; \ -+ tmp=(u<<16); u^=R^s[S ]; u^=tmp; \ -+ tmp=(t<<16); t^=R^s[S+1]; t^=tmp -+#else -+#define LOAD_DATA_tmp(a,b,c,d,e,f) LOAD_DATA(a,b,c,d,e,f,g) -+#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ -+ u=R^s[S ]; \ -+ t=R^s[S+1] -+#endif -+ -+/* The changes to this macro may help or hinder, depending on the -+ * compiler and the achitecture. gcc2 always seems to do well :-). -+ * Inspired by Dana How -+ * DO NOT use the alternative version on machines with 8 byte longs. -+ * It does not seem to work on the Alpha, even when DES_LONG is 4 -+ * bytes, probably an issue of accessing non-word aligned objects :-( */ -+#ifdef DES_PTR -+ -+/* It recently occured to me that 0^0^0^0^0^0^0 == 0, so there -+ * is no reason to not xor all the sub items together. This potentially -+ * saves a register since things can be xored directly into L */ -+ -+#if defined(DES_RISC1) || defined(DES_RISC2) -+#ifdef DES_RISC1 -+#define D_ENCRYPT(LL,R,S) { \ -+ unsigned int u1,u2,u3; \ -+ LOAD_DATA(R,S,u,t,E0,E1,u1); \ -+ u2=(int)u>>8L; \ -+ u1=(int)u&0xfc; \ -+ u2&=0xfc; \ -+ t=ROTATE(t,4); \ -+ u>>=16L; \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP +u1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \ -+ u3=(int)(u>>8L); \ -+ u1=(int)u&0xfc; \ -+ u3&=0xfc; \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+u1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+u3); \ -+ u2=(int)t>>8L; \ -+ u1=(int)t&0xfc; \ -+ u2&=0xfc; \ -+ t>>=16L; \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \ -+ u3=(int)t>>8L; \ -+ u1=(int)t&0xfc; \ -+ u3&=0xfc; \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+u1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+u3); } -+#endif -+#ifdef DES_RISC2 -+#define D_ENCRYPT(LL,R,S) { \ -+ unsigned int u1,u2,s1,s2; \ -+ LOAD_DATA(R,S,u,t,E0,E1,u1); \ -+ u2=(int)u>>8L; \ -+ u1=(int)u&0xfc; \ -+ u2&=0xfc; \ -+ t=ROTATE(t,4); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP +u1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \ -+ s1=(int)(u>>16L); \ -+ s2=(int)(u>>24L); \ -+ s1&=0xfc; \ -+ s2&=0xfc; \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+s1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+s2); \ -+ u2=(int)t>>8L; \ -+ u1=(int)t&0xfc; \ -+ u2&=0xfc; \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \ -+ s1=(int)(t>>16L); \ -+ s2=(int)(t>>24L); \ -+ s1&=0xfc; \ -+ s2&=0xfc; \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+s1); \ -+ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+s2); } -+#endif -+#else -+#define D_ENCRYPT(LL,R,S) { \ -+ LOAD_DATA_tmp(R,S,u,t,E0,E1); \ -+ t=ROTATE(t,4); \ -+ LL^= \ -+ *(DES_LONG *)((unsigned char *)des_SP +((u )&0xfc))^ \ -+ *(DES_LONG *)((unsigned char *)des_SP+0x200+((u>> 8L)&0xfc))^ \ -+ *(DES_LONG *)((unsigned char *)des_SP+0x400+((u>>16L)&0xfc))^ \ -+ *(DES_LONG *)((unsigned char *)des_SP+0x600+((u>>24L)&0xfc))^ \ -+ *(DES_LONG *)((unsigned char *)des_SP+0x100+((t )&0xfc))^ \ -+ *(DES_LONG *)((unsigned char *)des_SP+0x300+((t>> 8L)&0xfc))^ \ -+ *(DES_LONG *)((unsigned char *)des_SP+0x500+((t>>16L)&0xfc))^ \ -+ *(DES_LONG *)((unsigned char *)des_SP+0x700+((t>>24L)&0xfc)); } -+#endif -+ -+#else /* original version */ -+ -+#if defined(DES_RISC1) || defined(DES_RISC2) -+#ifdef DES_RISC1 -+#define D_ENCRYPT(LL,R,S) {\ -+ unsigned int u1,u2,u3; \ -+ LOAD_DATA(R,S,u,t,E0,E1,u1); \ -+ u>>=2L; \ -+ t=ROTATE(t,6); \ -+ u2=(int)u>>8L; \ -+ u1=(int)u&0x3f; \ -+ u2&=0x3f; \ -+ u>>=16L; \ -+ LL^=des_SPtrans[0][u1]; \ -+ LL^=des_SPtrans[2][u2]; \ -+ u3=(int)u>>8L; \ -+ u1=(int)u&0x3f; \ -+ u3&=0x3f; \ -+ LL^=des_SPtrans[4][u1]; \ -+ LL^=des_SPtrans[6][u3]; \ -+ u2=(int)t>>8L; \ -+ u1=(int)t&0x3f; \ -+ u2&=0x3f; \ -+ t>>=16L; \ -+ LL^=des_SPtrans[1][u1]; \ -+ LL^=des_SPtrans[3][u2]; \ -+ u3=(int)t>>8L; \ -+ u1=(int)t&0x3f; \ -+ u3&=0x3f; \ -+ LL^=des_SPtrans[5][u1]; \ -+ LL^=des_SPtrans[7][u3]; } -+#endif -+#ifdef DES_RISC2 -+#define D_ENCRYPT(LL,R,S) {\ -+ unsigned int u1,u2,s1,s2; \ -+ LOAD_DATA(R,S,u,t,E0,E1,u1); \ -+ u>>=2L; \ -+ t=ROTATE(t,6); \ -+ u2=(int)u>>8L; \ -+ u1=(int)u&0x3f; \ -+ u2&=0x3f; \ -+ LL^=des_SPtrans[0][u1]; \ -+ LL^=des_SPtrans[2][u2]; \ -+ s1=(int)u>>16L; \ -+ s2=(int)u>>24L; \ -+ s1&=0x3f; \ -+ s2&=0x3f; \ -+ LL^=des_SPtrans[4][s1]; \ -+ LL^=des_SPtrans[6][s2]; \ -+ u2=(int)t>>8L; \ -+ u1=(int)t&0x3f; \ -+ u2&=0x3f; \ -+ LL^=des_SPtrans[1][u1]; \ -+ LL^=des_SPtrans[3][u2]; \ -+ s1=(int)t>>16; \ -+ s2=(int)t>>24L; \ -+ s1&=0x3f; \ -+ s2&=0x3f; \ -+ LL^=des_SPtrans[5][s1]; \ -+ LL^=des_SPtrans[7][s2]; } -+#endif -+ -+#else -+ -+#define D_ENCRYPT(LL,R,S) {\ -+ LOAD_DATA_tmp(R,S,u,t,E0,E1); \ -+ t=ROTATE(t,4); \ -+ LL^=\ -+ des_SPtrans[0][(u>> 2L)&0x3f]^ \ -+ des_SPtrans[2][(u>>10L)&0x3f]^ \ -+ des_SPtrans[4][(u>>18L)&0x3f]^ \ -+ des_SPtrans[6][(u>>26L)&0x3f]^ \ -+ des_SPtrans[1][(t>> 2L)&0x3f]^ \ -+ des_SPtrans[3][(t>>10L)&0x3f]^ \ -+ des_SPtrans[5][(t>>18L)&0x3f]^ \ -+ des_SPtrans[7][(t>>26L)&0x3f]; } -+#endif -+#endif -+ -+ /* IP and FP -+ * The problem is more of a geometric problem that random bit fiddling. -+ 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 -+ 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 -+ 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 -+ 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 -+ -+ 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 -+ 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 -+ 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 -+ 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 -+ -+ The output has been subject to swaps of the form -+ 0 1 -> 3 1 but the odd and even bits have been put into -+ 2 3 2 0 -+ different words. The main trick is to remember that -+ t=((l>>size)^r)&(mask); -+ r^=t; -+ l^=(t<>(n))^(b))&(m)),\ -+ (b)^=(t),\ -+ (a)^=((t)<<(n))) -+ -+#define IP(l,r) \ -+ { \ -+ register DES_LONG tt; \ -+ PERM_OP(r,l,tt, 4,0x0f0f0f0fL); \ -+ PERM_OP(l,r,tt,16,0x0000ffffL); \ -+ PERM_OP(r,l,tt, 2,0x33333333L); \ -+ PERM_OP(l,r,tt, 8,0x00ff00ffL); \ -+ PERM_OP(r,l,tt, 1,0x55555555L); \ -+ } -+ -+#define FP(l,r) \ -+ { \ -+ register DES_LONG tt; \ -+ PERM_OP(l,r,tt, 1,0x55555555L); \ -+ PERM_OP(r,l,tt, 8,0x00ff00ffL); \ -+ PERM_OP(l,r,tt, 2,0x33333333L); \ -+ PERM_OP(r,l,tt,16,0x0000ffffL); \ -+ PERM_OP(l,r,tt, 4,0x0f0f0f0fL); \ -+ } -+ -+extern const DES_LONG des_SPtrans[8][64]; -+ -+#ifndef NOPROTO -+void fcrypt_body(DES_LONG *out,des_key_schedule ks, -+ DES_LONG Eswap0, DES_LONG Eswap1); -+#else -+void fcrypt_body(); -+#endif -+ -+#endif ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/des_opts.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,620 @@ -+/* crypto/des/des_opts.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+/* define PART1, PART2, PART3 or PART4 to build only with a few of the options. -+ * This is for machines with 64k code segment size restrictions. */ -+ -+#ifndef MSDOS -+#define TIMES -+#endif -+ -+#include -+#ifndef MSDOS -+#include -+#else -+#include -+extern void exit(); -+#endif -+#include -+#ifndef VMS -+#ifndef _IRIX -+#include -+#endif -+#ifdef TIMES -+#include -+#include -+#endif -+#else /* VMS */ -+#include -+struct tms { -+ time_t tms_utime; -+ time_t tms_stime; -+ time_t tms_uchild; /* I dunno... */ -+ time_t tms_uchildsys; /* so these names are a guess :-) */ -+ } -+#endif -+#ifndef TIMES -+#include -+#endif -+ -+#ifdef sun -+#include -+#include -+#endif -+ -+#include "des_locl.h" -+#include "spr.h" -+ -+#define DES_DEFAULT_OPTIONS -+ -+#if !defined(PART1) && !defined(PART2) && !defined(PART3) && !defined(PART4) -+#define PART1 -+#define PART2 -+#define PART3 -+#define PART4 -+#endif -+ -+#ifdef PART1 -+ -+#undef DES_UNROLL -+#undef DES_RISC1 -+#undef DES_RISC2 -+#undef DES_PTR -+#undef D_ENCRYPT -+#define des_encrypt des_encrypt_u4_cisc_idx -+#define des_encrypt2 des_encrypt2_u4_cisc_idx -+#define des_encrypt3 des_encrypt3_u4_cisc_idx -+#define des_decrypt3 des_decrypt3_u4_cisc_idx -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#define DES_UNROLL -+#undef DES_RISC1 -+#undef DES_RISC2 -+#undef DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u16_cisc_idx -+#define des_encrypt2 des_encrypt2_u16_cisc_idx -+#define des_encrypt3 des_encrypt3_u16_cisc_idx -+#define des_decrypt3 des_decrypt3_u16_cisc_idx -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#undef DES_UNROLL -+#define DES_RISC1 -+#undef DES_RISC2 -+#undef DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u4_risc1_idx -+#define des_encrypt2 des_encrypt2_u4_risc1_idx -+#define des_encrypt3 des_encrypt3_u4_risc1_idx -+#define des_decrypt3 des_decrypt3_u4_risc1_idx -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#endif -+ -+#ifdef PART2 -+ -+#undef DES_UNROLL -+#undef DES_RISC1 -+#define DES_RISC2 -+#undef DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u4_risc2_idx -+#define des_encrypt2 des_encrypt2_u4_risc2_idx -+#define des_encrypt3 des_encrypt3_u4_risc2_idx -+#define des_decrypt3 des_decrypt3_u4_risc2_idx -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#define DES_UNROLL -+#define DES_RISC1 -+#undef DES_RISC2 -+#undef DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u16_risc1_idx -+#define des_encrypt2 des_encrypt2_u16_risc1_idx -+#define des_encrypt3 des_encrypt3_u16_risc1_idx -+#define des_decrypt3 des_decrypt3_u16_risc1_idx -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#define DES_UNROLL -+#undef DES_RISC1 -+#define DES_RISC2 -+#undef DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u16_risc2_idx -+#define des_encrypt2 des_encrypt2_u16_risc2_idx -+#define des_encrypt3 des_encrypt3_u16_risc2_idx -+#define des_decrypt3 des_decrypt3_u16_risc2_idx -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#endif -+ -+#ifdef PART3 -+ -+#undef DES_UNROLL -+#undef DES_RISC1 -+#undef DES_RISC2 -+#define DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u4_cisc_ptr -+#define des_encrypt2 des_encrypt2_u4_cisc_ptr -+#define des_encrypt3 des_encrypt3_u4_cisc_ptr -+#define des_decrypt3 des_decrypt3_u4_cisc_ptr -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#define DES_UNROLL -+#undef DES_RISC1 -+#undef DES_RISC2 -+#define DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u16_cisc_ptr -+#define des_encrypt2 des_encrypt2_u16_cisc_ptr -+#define des_encrypt3 des_encrypt3_u16_cisc_ptr -+#define des_decrypt3 des_decrypt3_u16_cisc_ptr -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#undef DES_UNROLL -+#define DES_RISC1 -+#undef DES_RISC2 -+#define DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u4_risc1_ptr -+#define des_encrypt2 des_encrypt2_u4_risc1_ptr -+#define des_encrypt3 des_encrypt3_u4_risc1_ptr -+#define des_decrypt3 des_decrypt3_u4_risc1_ptr -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#endif -+ -+#ifdef PART4 -+ -+#undef DES_UNROLL -+#undef DES_RISC1 -+#define DES_RISC2 -+#define DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u4_risc2_ptr -+#define des_encrypt2 des_encrypt2_u4_risc2_ptr -+#define des_encrypt3 des_encrypt3_u4_risc2_ptr -+#define des_decrypt3 des_decrypt3_u4_risc2_ptr -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#define DES_UNROLL -+#define DES_RISC1 -+#undef DES_RISC2 -+#define DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u16_risc1_ptr -+#define des_encrypt2 des_encrypt2_u16_risc1_ptr -+#define des_encrypt3 des_encrypt3_u16_risc1_ptr -+#define des_decrypt3 des_decrypt3_u16_risc1_ptr -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#define DES_UNROLL -+#undef DES_RISC1 -+#define DES_RISC2 -+#define DES_PTR -+#undef D_ENCRYPT -+#undef des_encrypt -+#undef des_encrypt2 -+#undef des_encrypt3 -+#undef des_decrypt3 -+#define des_encrypt des_encrypt_u16_risc2_ptr -+#define des_encrypt2 des_encrypt2_u16_risc2_ptr -+#define des_encrypt3 des_encrypt3_u16_risc2_ptr -+#define des_decrypt3 des_decrypt3_u16_risc2_ptr -+#undef HEADER_DES_LOCL_H -+#include "des_enc.c" -+ -+#endif -+ -+/* The following if from times(3) man page. It may need to be changed */ -+#ifndef HZ -+# ifndef CLK_TCK -+# ifndef _BSD_CLK_TCK_ /* FreeBSD fix */ -+# ifndef VMS -+# define HZ 100.0 -+# else /* VMS */ -+# define HZ 100.0 -+# endif -+# else /* _BSD_CLK_TCK_ */ -+# define HZ ((double)_BSD_CLK_TCK_) -+# endif -+# else /* CLK_TCK */ -+# define HZ ((double)CLK_TCK) -+# endif -+#endif -+ -+#define BUFSIZE ((long)1024) -+long run=0; -+ -+#ifndef NOPROTO -+double Time_F(int s); -+#else -+double Time_F(); -+#endif -+ -+#ifdef SIGALRM -+#if defined(__STDC__) || defined(sgi) -+#define SIGRETTYPE void -+#else -+#define SIGRETTYPE int -+#endif -+ -+#ifndef NOPROTO -+SIGRETTYPE sig_done(int sig); -+#else -+SIGRETTYPE sig_done(); -+#endif -+ -+SIGRETTYPE sig_done(sig) -+int sig; -+ { -+ signal(SIGALRM,sig_done); -+ run=0; -+#ifdef LINT -+ sig=sig; -+#endif -+ } -+#endif -+ -+#define START 0 -+#define STOP 1 -+ -+double Time_F(s) -+int s; -+ { -+ double ret; -+#ifdef TIMES -+ static struct tms tstart,tend; -+ -+ if (s == START) -+ { -+ times(&tstart); -+ return(0); -+ } -+ else -+ { -+ times(&tend); -+ ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ; -+ return((ret == 0.0)?1e-6:ret); -+ } -+#else /* !times() */ -+ static struct timeb tstart,tend; -+ long i; -+ -+ if (s == START) -+ { -+ ftime(&tstart); -+ return(0); -+ } -+ else -+ { -+ ftime(&tend); -+ i=(long)tend.millitm-(long)tstart.millitm; -+ ret=((double)(tend.time-tstart.time))+((double)i)/1000.0; -+ return((ret == 0.0)?1e-6:ret); -+ } -+#endif -+ } -+ -+#ifdef SIGALRM -+#define print_name(name) fprintf(stderr,"Doing %s's for 10 seconds\n",name); alarm(10); -+#else -+#define print_name(name) fprintf(stderr,"Doing %s %ld times\n",name,cb); -+#endif -+ -+#define time_it(func,name,index) \ -+ print_name(name); \ -+ Time_F(START); \ -+ for (count=0,run=1; COND(cb); count++) \ -+ { \ -+ unsigned long d[2]; \ -+ func(d,&(sch[0]),DES_ENCRYPT); \ -+ } \ -+ tm[index]=Time_F(STOP); \ -+ fprintf(stderr,"%ld %s's in %.2f second\n",count,name,tm[index]); \ -+ tm[index]=((double)COUNT(cb))/tm[index]; -+ -+#define print_it(name,index) \ -+ fprintf(stderr,"%s bytes per sec = %12.2f (%5.1fuS)\n",name, \ -+ tm[index]*8,1.0e6/tm[index]); -+ -+int main(argc,argv) -+int argc; -+char **argv; -+ { -+ long count; -+ static unsigned char buf[BUFSIZE]; -+ static des_cblock key ={0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0}; -+ static des_cblock key2={0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12}; -+ static des_cblock key3={0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34}; -+ des_key_schedule sch,sch2,sch3; -+ double d,tm[16],max=0; -+ int rank[16]; -+ char *str[16]; -+ int max_idx=0,i,num=0,j; -+#ifndef SIGALARM -+ long ca,cb,cc,cd,ce; -+#endif -+ -+ for (i=0; i<12; i++) -+ { -+ tm[i]=0.0; -+ rank[i]=0; -+ } -+ -+#ifndef TIMES -+ fprintf(stderr,"To get the most acurate results, try to run this\n"); -+ fprintf(stderr,"program when this computer is idle.\n"); -+#endif -+ -+ des_set_key((C_Block *)key,sch); -+ des_set_key((C_Block *)key2,sch2); -+ des_set_key((C_Block *)key3,sch3); -+ -+#ifndef SIGALRM -+ fprintf(stderr,"First we calculate the approximate speed ...\n"); -+ des_set_key((C_Block *)key,sch); -+ count=10; -+ do { -+ long i; -+ unsigned long data[2]; -+ -+ count*=2; -+ Time_F(START); -+ for (i=count; i; i--) -+ des_encrypt(data,&(sch[0]),DES_ENCRYPT); -+ d=Time_F(STOP); -+ } while (d < 3.0); -+ ca=count; -+ cb=count*3; -+ cc=count*3*8/BUFSIZE+1; -+ cd=count*8/BUFSIZE+1; -+ -+ ce=count/20+1; -+#define COND(d) (count != (d)) -+#define COUNT(d) (d) -+#else -+#define COND(c) (run) -+#define COUNT(d) (count) -+ signal(SIGALRM,sig_done); -+ alarm(10); -+#endif -+ -+#ifdef PART1 -+ time_it(des_encrypt_u4_cisc_idx, "des_encrypt_u4_cisc_idx ", 0); -+ time_it(des_encrypt_u16_cisc_idx, "des_encrypt_u16_cisc_idx ", 1); -+ time_it(des_encrypt_u4_risc1_idx, "des_encrypt_u4_risc1_idx ", 2); -+ num+=3; -+#endif -+#ifdef PART2 -+ time_it(des_encrypt_u16_risc1_idx,"des_encrypt_u16_risc1_idx", 3); -+ time_it(des_encrypt_u4_risc2_idx, "des_encrypt_u4_risc2_idx ", 4); -+ time_it(des_encrypt_u16_risc2_idx,"des_encrypt_u16_risc2_idx", 5); -+ num+=3; -+#endif -+#ifdef PART3 -+ time_it(des_encrypt_u4_cisc_ptr, "des_encrypt_u4_cisc_ptr ", 6); -+ time_it(des_encrypt_u16_cisc_ptr, "des_encrypt_u16_cisc_ptr ", 7); -+ time_it(des_encrypt_u4_risc1_ptr, "des_encrypt_u4_risc1_ptr ", 8); -+ num+=3; -+#endif -+#ifdef PART4 -+ time_it(des_encrypt_u16_risc1_ptr,"des_encrypt_u16_risc1_ptr", 9); -+ time_it(des_encrypt_u4_risc2_ptr, "des_encrypt_u4_risc2_ptr ",10); -+ time_it(des_encrypt_u16_risc2_ptr,"des_encrypt_u16_risc2_ptr",11); -+ num+=3; -+#endif -+ -+#ifdef PART1 -+ str[0]=" 4 c i"; -+ print_it("des_encrypt_u4_cisc_idx ",0); -+ max=tm[0]; -+ max_idx=0; -+ str[1]="16 c i"; -+ print_it("des_encrypt_u16_cisc_idx ",1); -+ if (max < tm[1]) { max=tm[1]; max_idx=1; } -+ str[2]=" 4 r1 i"; -+ print_it("des_encrypt_u4_risc1_idx ",2); -+ if (max < tm[2]) { max=tm[2]; max_idx=2; } -+#endif -+#ifdef PART2 -+ str[3]="16 r1 i"; -+ print_it("des_encrypt_u16_risc1_idx",3); -+ if (max < tm[3]) { max=tm[3]; max_idx=3; } -+ str[4]=" 4 r2 i"; -+ print_it("des_encrypt_u4_risc2_idx ",4); -+ if (max < tm[4]) { max=tm[4]; max_idx=4; } -+ str[5]="16 r2 i"; -+ print_it("des_encrypt_u16_risc2_idx",5); -+ if (max < tm[5]) { max=tm[5]; max_idx=5; } -+#endif -+#ifdef PART3 -+ str[6]=" 4 c p"; -+ print_it("des_encrypt_u4_cisc_ptr ",6); -+ if (max < tm[6]) { max=tm[6]; max_idx=6; } -+ str[7]="16 c p"; -+ print_it("des_encrypt_u16_cisc_ptr ",7); -+ if (max < tm[7]) { max=tm[7]; max_idx=7; } -+ str[8]=" 4 r1 p"; -+ print_it("des_encrypt_u4_risc1_ptr ",8); -+ if (max < tm[8]) { max=tm[8]; max_idx=8; } -+#endif -+#ifdef PART4 -+ str[9]="16 r1 p"; -+ print_it("des_encrypt_u16_risc1_ptr",9); -+ if (max < tm[9]) { max=tm[9]; max_idx=9; } -+ str[10]=" 4 r2 p"; -+ print_it("des_encrypt_u4_risc2_ptr ",10); -+ if (max < tm[10]) { max=tm[10]; max_idx=10; } -+ str[11]="16 r2 p"; -+ print_it("des_encrypt_u16_risc2_ptr",11); -+ if (max < tm[11]) { max=tm[11]; max_idx=11; } -+#endif -+ printf("options des ecb/s\n"); -+ printf("%s %12.2f 100.0%%\n",str[max_idx],tm[max_idx]); -+ d=tm[max_idx]; -+ tm[max_idx]= -2.0; -+ max= -1.0; -+ for (;;) -+ { -+ for (i=0; i<12; i++) -+ { -+ if (max < tm[i]) { max=tm[i]; j=i; } -+ } -+ if (max < 0.0) break; -+ printf("%s %12.2f %4.1f%%\n",str[j],tm[j],tm[j]/d*100.0); -+ tm[j]= -2.0; -+ max= -1.0; -+ } -+ -+ switch (max_idx) -+ { -+ case 0: -+ printf("-DDES_DEFAULT_OPTIONS\n"); -+ break; -+ case 1: -+ printf("-DDES_UNROLL\n"); -+ break; -+ case 2: -+ printf("-DDES_RISC1\n"); -+ break; -+ case 3: -+ printf("-DDES_UNROLL -DDES_RISC1\n"); -+ break; -+ case 4: -+ printf("-DDES_RISC2\n"); -+ break; -+ case 5: -+ printf("-DDES_UNROLL -DDES_RISC2\n"); -+ break; -+ case 6: -+ printf("-DDES_PTR\n"); -+ break; -+ case 7: -+ printf("-DDES_UNROLL -DDES_PTR\n"); -+ break; -+ case 8: -+ printf("-DDES_RISC1 -DDES_PTR\n"); -+ break; -+ case 9: -+ printf("-DDES_UNROLL -DDES_RISC1 -DDES_PTR\n"); -+ break; -+ case 10: -+ printf("-DDES_RISC2 -DDES_PTR\n"); -+ break; -+ case 11: -+ printf("-DDES_UNROLL -DDES_RISC2 -DDES_PTR\n"); -+ break; -+ } -+ exit(0); -+#if defined(LINT) || defined(MSDOS) -+ return(0); -+#endif -+ } ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/des_ver.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,60 @@ -+/* crypto/des/des_ver.h */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+extern char *DES_version; /* SSLeay version string */ -+extern char *libdes_version; /* old libdes version string */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/destest.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,871 @@ -+/* crypto/des/destest.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+#if defined(WIN32) || defined(WIN16) || defined(WINDOWS) -+#ifndef MSDOS -+#define MSDOS -+#endif -+#endif -+ -+#include -+#include -+#ifndef MSDOS -+#include -+#else -+#include -+#endif -+#include -+#include "des_locl.h" -+ -+/* tisk tisk - the test keys don't all have odd parity :-( */ -+/* test data */ -+#define NUM_TESTS 34 -+static unsigned char key_data[NUM_TESTS][8]={ -+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, -+ {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, -+ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, -+ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, -+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10}, -+ {0x7C,0xA1,0x10,0x45,0x4A,0x1A,0x6E,0x57}, -+ {0x01,0x31,0xD9,0x61,0x9D,0xC1,0x37,0x6E}, -+ {0x07,0xA1,0x13,0x3E,0x4A,0x0B,0x26,0x86}, -+ {0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E}, -+ {0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6}, -+ {0x01,0x13,0xB9,0x70,0xFD,0x34,0xF2,0xCE}, -+ {0x01,0x70,0xF1,0x75,0x46,0x8F,0xB5,0xE6}, -+ {0x43,0x29,0x7F,0xAD,0x38,0xE3,0x73,0xFE}, -+ {0x07,0xA7,0x13,0x70,0x45,0xDA,0x2A,0x16}, -+ {0x04,0x68,0x91,0x04,0xC2,0xFD,0x3B,0x2F}, -+ {0x37,0xD0,0x6B,0xB5,0x16,0xCB,0x75,0x46}, -+ {0x1F,0x08,0x26,0x0D,0x1A,0xC2,0x46,0x5E}, -+ {0x58,0x40,0x23,0x64,0x1A,0xBA,0x61,0x76}, -+ {0x02,0x58,0x16,0x16,0x46,0x29,0xB0,0x07}, -+ {0x49,0x79,0x3E,0xBC,0x79,0xB3,0x25,0x8F}, -+ {0x4F,0xB0,0x5E,0x15,0x15,0xAB,0x73,0xA7}, -+ {0x49,0xE9,0x5D,0x6D,0x4C,0xA2,0x29,0xBF}, -+ {0x01,0x83,0x10,0xDC,0x40,0x9B,0x26,0xD6}, -+ {0x1C,0x58,0x7F,0x1C,0x13,0x92,0x4F,0xEF}, -+ {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, -+ {0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E}, -+ {0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE}, -+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, -+ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, -+ {0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10}}; -+ -+static unsigned char plain_data[NUM_TESTS][8]={ -+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, -+ {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, -+ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, -+ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, -+ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, -+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, -+ {0x01,0xA1,0xD6,0xD0,0x39,0x77,0x67,0x42}, -+ {0x5C,0xD5,0x4C,0xA8,0x3D,0xEF,0x57,0xDA}, -+ {0x02,0x48,0xD4,0x38,0x06,0xF6,0x71,0x72}, -+ {0x51,0x45,0x4B,0x58,0x2D,0xDF,0x44,0x0A}, -+ {0x42,0xFD,0x44,0x30,0x59,0x57,0x7F,0xA2}, -+ {0x05,0x9B,0x5E,0x08,0x51,0xCF,0x14,0x3A}, -+ {0x07,0x56,0xD8,0xE0,0x77,0x47,0x61,0xD2}, -+ {0x76,0x25,0x14,0xB8,0x29,0xBF,0x48,0x6A}, -+ {0x3B,0xDD,0x11,0x90,0x49,0x37,0x28,0x02}, -+ {0x26,0x95,0x5F,0x68,0x35,0xAF,0x60,0x9A}, -+ {0x16,0x4D,0x5E,0x40,0x4F,0x27,0x52,0x32}, -+ {0x6B,0x05,0x6E,0x18,0x75,0x9F,0x5C,0xCA}, -+ {0x00,0x4B,0xD6,0xEF,0x09,0x17,0x60,0x62}, -+ {0x48,0x0D,0x39,0x00,0x6E,0xE7,0x62,0xF2}, -+ {0x43,0x75,0x40,0xC8,0x69,0x8F,0x3C,0xFA}, -+ {0x07,0x2D,0x43,0xA0,0x77,0x07,0x52,0x92}, -+ {0x02,0xFE,0x55,0x77,0x81,0x17,0xF1,0x2A}, -+ {0x1D,0x9D,0x5C,0x50,0x18,0xF7,0x28,0xC2}, -+ {0x30,0x55,0x32,0x28,0x6D,0x6F,0x29,0x5A}, -+ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, -+ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, -+ {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, -+ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, -+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, -+ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}; -+ -+static unsigned char cipher_data[NUM_TESTS][8]={ -+ {0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7}, -+ {0x73,0x59,0xB2,0x16,0x3E,0x4E,0xDC,0x58}, -+ {0x95,0x8E,0x6E,0x62,0x7A,0x05,0x55,0x7B}, -+ {0xF4,0x03,0x79,0xAB,0x9E,0x0E,0xC5,0x33}, -+ {0x17,0x66,0x8D,0xFC,0x72,0x92,0x53,0x2D}, -+ {0x8A,0x5A,0xE1,0xF8,0x1A,0xB8,0xF2,0xDD}, -+ {0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7}, -+ {0xED,0x39,0xD9,0x50,0xFA,0x74,0xBC,0xC4}, -+ {0x69,0x0F,0x5B,0x0D,0x9A,0x26,0x93,0x9B}, -+ {0x7A,0x38,0x9D,0x10,0x35,0x4B,0xD2,0x71}, -+ {0x86,0x8E,0xBB,0x51,0xCA,0xB4,0x59,0x9A}, -+ {0x71,0x78,0x87,0x6E,0x01,0xF1,0x9B,0x2A}, -+ {0xAF,0x37,0xFB,0x42,0x1F,0x8C,0x40,0x95}, -+ {0x86,0xA5,0x60,0xF1,0x0E,0xC6,0xD8,0x5B}, -+ {0x0C,0xD3,0xDA,0x02,0x00,0x21,0xDC,0x09}, -+ {0xEA,0x67,0x6B,0x2C,0xB7,0xDB,0x2B,0x7A}, -+ {0xDF,0xD6,0x4A,0x81,0x5C,0xAF,0x1A,0x0F}, -+ {0x5C,0x51,0x3C,0x9C,0x48,0x86,0xC0,0x88}, -+ {0x0A,0x2A,0xEE,0xAE,0x3F,0xF4,0xAB,0x77}, -+ {0xEF,0x1B,0xF0,0x3E,0x5D,0xFA,0x57,0x5A}, -+ {0x88,0xBF,0x0D,0xB6,0xD7,0x0D,0xEE,0x56}, -+ {0xA1,0xF9,0x91,0x55,0x41,0x02,0x0B,0x56}, -+ {0x6F,0xBF,0x1C,0xAF,0xCF,0xFD,0x05,0x56}, -+ {0x2F,0x22,0xE4,0x9B,0xAB,0x7C,0xA1,0xAC}, -+ {0x5A,0x6B,0x61,0x2C,0xC2,0x6C,0xCE,0x4A}, -+ {0x5F,0x4C,0x03,0x8E,0xD1,0x2B,0x2E,0x41}, -+ {0x63,0xFA,0xC0,0xD0,0x34,0xD9,0xF7,0x93}, -+ {0x61,0x7B,0x3A,0x0C,0xE8,0xF0,0x71,0x00}, -+ {0xDB,0x95,0x86,0x05,0xF8,0xC8,0xC6,0x06}, -+ {0xED,0xBF,0xD1,0xC6,0x6C,0x29,0xCC,0xC7}, -+ {0x35,0x55,0x50,0xB2,0x15,0x0E,0x24,0x51}, -+ {0xCA,0xAA,0xAF,0x4D,0xEA,0xF1,0xDB,0xAE}, -+ {0xD5,0xD4,0x4F,0xF7,0x20,0x68,0x3D,0x0D}, -+ {0x2A,0x2B,0xB0,0x08,0xDF,0x97,0xC2,0xF2}}; -+ -+static unsigned char cipher_ecb2[NUM_TESTS-1][8]={ -+ {0x92,0x95,0xB5,0x9B,0xB3,0x84,0x73,0x6E}, -+ {0x19,0x9E,0x9D,0x6D,0xF3,0x9A,0xA8,0x16}, -+ {0x2A,0x4B,0x4D,0x24,0x52,0x43,0x84,0x27}, -+ {0x35,0x84,0x3C,0x01,0x9D,0x18,0xC5,0xB6}, -+ {0x4A,0x5B,0x2F,0x42,0xAA,0x77,0x19,0x25}, -+ {0xA0,0x6B,0xA9,0xB8,0xCA,0x5B,0x17,0x8A}, -+ {0xAB,0x9D,0xB7,0xFB,0xED,0x95,0xF2,0x74}, -+ {0x3D,0x25,0x6C,0x23,0xA7,0x25,0x2F,0xD6}, -+ {0xB7,0x6F,0xAB,0x4F,0xBD,0xBD,0xB7,0x67}, -+ {0x8F,0x68,0x27,0xD6,0x9C,0xF4,0x1A,0x10}, -+ {0x82,0x57,0xA1,0xD6,0x50,0x5E,0x81,0x85}, -+ {0xA2,0x0F,0x0A,0xCD,0x80,0x89,0x7D,0xFA}, -+ {0xCD,0x2A,0x53,0x3A,0xDB,0x0D,0x7E,0xF3}, -+ {0xD2,0xC2,0xBE,0x27,0xE8,0x1B,0x68,0xE3}, -+ {0xE9,0x24,0xCF,0x4F,0x89,0x3C,0x5B,0x0A}, -+ {0xA7,0x18,0xC3,0x9F,0xFA,0x9F,0xD7,0x69}, -+ {0x77,0x2C,0x79,0xB1,0xD2,0x31,0x7E,0xB1}, -+ {0x49,0xAB,0x92,0x7F,0xD0,0x22,0x00,0xB7}, -+ {0xCE,0x1C,0x6C,0x7D,0x85,0xE3,0x4A,0x6F}, -+ {0xBE,0x91,0xD6,0xE1,0x27,0xB2,0xE9,0x87}, -+ {0x70,0x28,0xAE,0x8F,0xD1,0xF5,0x74,0x1A}, -+ {0xAA,0x37,0x80,0xBB,0xF3,0x22,0x1D,0xDE}, -+ {0xA6,0xC4,0xD2,0x5E,0x28,0x93,0xAC,0xB3}, -+ {0x22,0x07,0x81,0x5A,0xE4,0xB7,0x1A,0xAD}, -+ {0xDC,0xCE,0x05,0xE7,0x07,0xBD,0xF5,0x84}, -+ {0x26,0x1D,0x39,0x2C,0xB3,0xBA,0xA5,0x85}, -+ {0xB4,0xF7,0x0F,0x72,0xFB,0x04,0xF0,0xDC}, -+ {0x95,0xBA,0xA9,0x4E,0x87,0x36,0xF2,0x89}, -+ {0xD4,0x07,0x3A,0xF1,0x5A,0x17,0x82,0x0E}, -+ {0xEF,0x6F,0xAF,0xA7,0x66,0x1A,0x7E,0x89}, -+ {0xC1,0x97,0xF5,0x58,0x74,0x8A,0x20,0xE7}, -+ {0x43,0x34,0xCF,0xDA,0x22,0xC4,0x86,0xC8}, -+ {0x08,0xD7,0xB4,0xFB,0x62,0x9D,0x08,0x85}}; -+ -+static unsigned char cbc_key [8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; -+static unsigned char cbc2_key[8]={0xf0,0xe1,0xd2,0xc3,0xb4,0xa5,0x96,0x87}; -+static unsigned char cbc3_key[8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; -+static unsigned char cbc_iv [8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; -+static char cbc_data[40]="7654321 Now is the time for \0001"; -+ -+static unsigned char cbc_ok[32]={ -+ 0xcc,0xd1,0x73,0xff,0xab,0x20,0x39,0xf4, -+ 0xac,0xd8,0xae,0xfd,0xdf,0xd8,0xa1,0xeb, -+ 0x46,0x8e,0x91,0x15,0x78,0x88,0xba,0x68, -+ 0x1d,0x26,0x93,0x97,0xf7,0xfe,0x62,0xb4}; -+ -+static unsigned char xcbc_ok[32]={ -+ 0x86,0x74,0x81,0x0D,0x61,0xA4,0xA5,0x48, -+ 0xB9,0x93,0x03,0xE1,0xB8,0xBB,0xBD,0xBD, -+ 0x64,0x30,0x0B,0xB9,0x06,0x65,0x81,0x76, -+ 0x04,0x1D,0x77,0x62,0x17,0xCA,0x2B,0xD2, -+ }; -+ -+static unsigned char cbc3_ok[32]={ -+ 0x3F,0xE3,0x01,0xC9,0x62,0xAC,0x01,0xD0, -+ 0x22,0x13,0x76,0x3C,0x1C,0xBD,0x4C,0xDC, -+ 0x79,0x96,0x57,0xC0,0x64,0xEC,0xF5,0xD4, -+ 0x1C,0x67,0x38,0x12,0xCF,0xDE,0x96,0x75}; -+ -+static unsigned char pcbc_ok[32]={ -+ 0xcc,0xd1,0x73,0xff,0xab,0x20,0x39,0xf4, -+ 0x6d,0xec,0xb4,0x70,0xa0,0xe5,0x6b,0x15, -+ 0xae,0xa6,0xbf,0x61,0xed,0x7d,0x9c,0x9f, -+ 0xf7,0x17,0x46,0x3b,0x8a,0xb3,0xcc,0x88}; -+ -+static unsigned char cfb_key[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; -+static unsigned char cfb_iv[8]={0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef}; -+static unsigned char cfb_buf1[40],cfb_buf2[40],cfb_tmp[8]; -+static unsigned char plain[24]= -+ { -+ 0x4e,0x6f,0x77,0x20,0x69,0x73, -+ 0x20,0x74,0x68,0x65,0x20,0x74, -+ 0x69,0x6d,0x65,0x20,0x66,0x6f, -+ 0x72,0x20,0x61,0x6c,0x6c,0x20 -+ }; -+static unsigned char cfb_cipher8[24]= { -+ 0xf3,0x1f,0xda,0x07,0x01,0x14, 0x62,0xee,0x18,0x7f,0x43,0xd8, -+ 0x0a,0x7c,0xd9,0xb5,0xb0,0xd2, 0x90,0xda,0x6e,0x5b,0x9a,0x87 }; -+static unsigned char cfb_cipher16[24]={ -+ 0xF3,0x09,0x87,0x87,0x7F,0x57, 0xF7,0x3C,0x36,0xB6,0xDB,0x70, -+ 0xD8,0xD5,0x34,0x19,0xD3,0x86, 0xB2,0x23,0xB7,0xB2,0xAD,0x1B }; -+static unsigned char cfb_cipher32[24]={ -+ 0xF3,0x09,0x62,0x49,0xA4,0xDF, 0xA4,0x9F,0x33,0xDC,0x7B,0xAD, -+ 0x4C,0xC8,0x9F,0x64,0xE4,0x53, 0xE5,0xEC,0x67,0x20,0xDA,0xB6 }; -+static unsigned char cfb_cipher48[24]={ -+ 0xF3,0x09,0x62,0x49,0xC7,0xF4, 0x30,0xB5,0x15,0xEC,0xBB,0x85, -+ 0x97,0x5A,0x13,0x8C,0x68,0x60, 0xE2,0x38,0x34,0x3C,0xDC,0x1F }; -+static unsigned char cfb_cipher64[24]={ -+ 0xF3,0x09,0x62,0x49,0xC7,0xF4, 0x6E,0x51,0xA6,0x9E,0x83,0x9B, -+ 0x1A,0x92,0xF7,0x84,0x03,0x46, 0x71,0x33,0x89,0x8E,0xA6,0x22 }; -+ -+static unsigned char ofb_key[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; -+static unsigned char ofb_iv[8]={0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef}; -+static unsigned char ofb_buf1[24],ofb_buf2[24],ofb_tmp[8]; -+static unsigned char ofb_cipher[24]= -+ { -+ 0xf3,0x09,0x62,0x49,0xc7,0xf4,0x6e,0x51, -+ 0x35,0xf2,0x4a,0x24,0x2e,0xeb,0x3d,0x3f, -+ 0x3d,0x6d,0x5b,0xe3,0x25,0x5a,0xf8,0xc3 -+ }; -+ -+DES_LONG cbc_cksum_ret=0xB462FEF7L; -+unsigned char cbc_cksum_data[8]={0x1D,0x26,0x93,0x97,0xf7,0xfe,0x62,0xb4}; -+ -+#ifndef NOPROTO -+static char *pt(unsigned char *p); -+static int cfb_test(int bits, unsigned char *cfb_cipher); -+static int cfb64_test(unsigned char *cfb_cipher); -+static int ede_cfb64_test(unsigned char *cfb_cipher); -+#else -+static char *pt(); -+static int cfb_test(); -+static int cfb64_test(); -+static int ede_cfb64_test(); -+#endif -+ -+int main(argc,argv) -+int argc; -+char *argv[]; -+ { -+ int i,j,err=0; -+ des_cblock in,out,outin,iv3; -+ des_key_schedule ks,ks2,ks3; -+ unsigned char cbc_in[40]; -+ unsigned char cbc_out[40]; -+ DES_LONG cs; -+ unsigned char qret[4][4],cret[8]; -+ DES_LONG lqret[4]; -+ int num; -+ char *str; -+ -+ printf("Doing ecb\n"); -+ for (i=0; i>4)&0xf]; -+ ret[i*2+1]=f[p[i]&0xf]; -+ } -+ ret[16]='\0'; -+ return(ret); -+ } -+ -+#ifndef LIBDES_LIT -+ -+static int cfb_test(bits, cfb_cipher) -+int bits; -+unsigned char *cfb_cipher; -+ { -+ des_key_schedule ks; -+ int i,err=0; -+ -+ des_key_sched((C_Block *)cfb_key,ks); -+ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); -+ des_cfb_encrypt(plain,cfb_buf1,bits,(long)sizeof(plain),ks, -+ (C_Block *)cfb_tmp,DES_ENCRYPT); -+ if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0) -+ { -+ err=1; -+ printf("cfb_encrypt encrypt error\n"); -+ for (i=0; i<24; i+=8) -+ printf("%s\n",pt(&(cfb_buf1[i]))); -+ } -+ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); -+ des_cfb_encrypt(cfb_buf1,cfb_buf2,bits,(long)sizeof(plain),ks, -+ (C_Block *)cfb_tmp,DES_DECRYPT); -+ if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) -+ { -+ err=1; -+ printf("cfb_encrypt decrypt error\n"); -+ for (i=0; i<24; i+=8) -+ printf("%s\n",pt(&(cfb_buf1[i]))); -+ } -+ return(err); -+ } -+ -+static int cfb64_test(cfb_cipher) -+unsigned char *cfb_cipher; -+ { -+ des_key_schedule ks; -+ int err=0,i,n; -+ -+ des_key_sched((C_Block *)cfb_key,ks); -+ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); -+ n=0; -+ des_cfb64_encrypt(plain,cfb_buf1,(long)12,ks, -+ (C_Block *)cfb_tmp,&n,DES_ENCRYPT); -+ des_cfb64_encrypt(&(plain[12]),&(cfb_buf1[12]), -+ (long)sizeof(plain)-12,ks, -+ (C_Block *)cfb_tmp,&n,DES_ENCRYPT); -+ if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0) -+ { -+ err=1; -+ printf("cfb_encrypt encrypt error\n"); -+ for (i=0; i<24; i+=8) -+ printf("%s\n",pt(&(cfb_buf1[i]))); -+ } -+ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); -+ n=0; -+ des_cfb64_encrypt(cfb_buf1,cfb_buf2,(long)17,ks, -+ (C_Block *)cfb_tmp,&n,DES_DECRYPT); -+ des_cfb64_encrypt(&(cfb_buf1[17]),&(cfb_buf2[17]), -+ (long)sizeof(plain)-17,ks, -+ (C_Block *)cfb_tmp,&n,DES_DECRYPT); -+ if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) -+ { -+ err=1; -+ printf("cfb_encrypt decrypt error\n"); -+ for (i=0; i<24; i+=8) -+ printf("%s\n",pt(&(cfb_buf2[i]))); -+ } -+ return(err); -+ } -+ -+static int ede_cfb64_test(cfb_cipher) -+unsigned char *cfb_cipher; -+ { -+ des_key_schedule ks; -+ int err=0,i,n; -+ -+ des_key_sched((C_Block *)cfb_key,ks); -+ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); -+ n=0; -+ des_ede3_cfb64_encrypt(plain,cfb_buf1,(long)12,ks,ks,ks, -+ (C_Block *)cfb_tmp,&n,DES_ENCRYPT); -+ des_ede3_cfb64_encrypt(&(plain[12]),&(cfb_buf1[12]), -+ (long)sizeof(plain)-12,ks,ks,ks, -+ (C_Block *)cfb_tmp,&n,DES_ENCRYPT); -+ if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0) -+ { -+ err=1; -+ printf("ede_cfb_encrypt encrypt error\n"); -+ for (i=0; i<24; i+=8) -+ printf("%s\n",pt(&(cfb_buf1[i]))); -+ } -+ memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); -+ n=0; -+ des_ede3_cfb64_encrypt(cfb_buf1,cfb_buf2,(long)17,ks,ks,ks, -+ (C_Block *)cfb_tmp,&n,DES_DECRYPT); -+ des_ede3_cfb64_encrypt(&(cfb_buf1[17]),&(cfb_buf2[17]), -+ (long)sizeof(plain)-17,ks,ks,ks, -+ (C_Block *)cfb_tmp,&n,DES_DECRYPT); -+ if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) -+ { -+ err=1; -+ printf("ede_cfb_encrypt decrypt error\n"); -+ for (i=0; i<24; i+=8) -+ printf("%s\n",pt(&(cfb_buf2[i]))); -+ } -+ return(err); -+ } -+ -+#endif -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/dx86unix.S Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,3160 @@ -+/* -+ * This file was originally generated by Michael Richardson -+ * via the perl scripts found in the ASM subdir. It remains copyright of -+ * Eric Young, see the file COPYRIGHT. -+ * -+ * This was last done on October 9, 2002. -+ * -+ * While this file does not need to go through cpp, we pass it through -+ * CPP by naming it dx86unix.S instead of dx86unix.s because there is -+ * a bug in Rules.make for .s builds - specifically it references EXTRA_CFLAGS -+ * which may contain stuff that AS doesn't understand instead of -+ * referencing EXTRA_AFLAGS. -+ */ -+ -+ .file "dx86unix.S" -+ .version "01.01" -+.text -+ .align 16 -+.globl des_encrypt -+ .type des_encrypt , @function -+des_encrypt: -+ pushl %esi -+ pushl %edi -+ -+ -+ movl 12(%esp), %esi -+ xorl %ecx, %ecx -+ pushl %ebx -+ pushl %ebp -+ movl (%esi), %eax -+ movl 28(%esp), %ebx -+ movl 4(%esi), %edi -+ -+ -+ roll $4, %eax -+ movl %eax, %esi -+ xorl %edi, %eax -+ andl $0xf0f0f0f0, %eax -+ xorl %eax, %esi -+ xorl %eax, %edi -+ -+ roll $20, %edi -+ movl %edi, %eax -+ xorl %esi, %edi -+ andl $0xfff0000f, %edi -+ xorl %edi, %eax -+ xorl %edi, %esi -+ -+ roll $14, %eax -+ movl %eax, %edi -+ xorl %esi, %eax -+ andl $0x33333333, %eax -+ xorl %eax, %edi -+ xorl %eax, %esi -+ -+ roll $22, %esi -+ movl %esi, %eax -+ xorl %edi, %esi -+ andl $0x03fc03fc, %esi -+ xorl %esi, %eax -+ xorl %esi, %edi -+ -+ roll $9, %eax -+ movl %eax, %esi -+ xorl %edi, %eax -+ andl $0xaaaaaaaa, %eax -+ xorl %eax, %esi -+ xorl %eax, %edi -+ -+.byte 209 -+.byte 199 -+ movl 24(%esp), %ebp -+ cmpl $0, %ebx -+ je .L000start_decrypt -+ -+ -+ movl (%ebp), %eax -+ xorl %ebx, %ebx -+ movl 4(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 8(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 12(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 16(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 20(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 24(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 28(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 32(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 36(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 40(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 44(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 48(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 52(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 56(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 60(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 64(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 68(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 72(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 76(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 80(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 84(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 88(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 92(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 96(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 100(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 104(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 108(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 112(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 116(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 120(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 124(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ jmp .L001end -+.L000start_decrypt: -+ -+ -+ movl 120(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 124(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 112(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 116(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 104(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 108(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 96(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 100(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 88(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 92(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 80(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 84(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 72(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 76(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 64(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 68(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 56(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 60(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 48(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 52(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 40(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 44(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 32(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 36(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 24(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 28(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 16(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 20(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 8(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 12(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl (%ebp), %eax -+ xorl %ebx, %ebx -+ movl 4(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+.L001end: -+ -+ -+ movl 20(%esp), %edx -+.byte 209 -+.byte 206 -+ movl %edi, %eax -+ xorl %esi, %edi -+ andl $0xaaaaaaaa, %edi -+ xorl %edi, %eax -+ xorl %edi, %esi -+ -+ roll $23, %eax -+ movl %eax, %edi -+ xorl %esi, %eax -+ andl $0x03fc03fc, %eax -+ xorl %eax, %edi -+ xorl %eax, %esi -+ -+ roll $10, %edi -+ movl %edi, %eax -+ xorl %esi, %edi -+ andl $0x33333333, %edi -+ xorl %edi, %eax -+ xorl %edi, %esi -+ -+ roll $18, %esi -+ movl %esi, %edi -+ xorl %eax, %esi -+ andl $0xfff0000f, %esi -+ xorl %esi, %edi -+ xorl %esi, %eax -+ -+ roll $12, %edi -+ movl %edi, %esi -+ xorl %eax, %edi -+ andl $0xf0f0f0f0, %edi -+ xorl %edi, %esi -+ xorl %edi, %eax -+ -+ rorl $4, %eax -+ movl %eax, (%edx) -+ movl %esi, 4(%edx) -+ popl %ebp -+ popl %ebx -+ popl %edi -+ popl %esi -+ ret -+.des_encrypt_end: -+ .size des_encrypt , .des_encrypt_end-des_encrypt -+.ident "desasm.pl" -+.text -+ .align 16 -+.globl des_encrypt2 -+ .type des_encrypt2 , @function -+des_encrypt2: -+ pushl %esi -+ pushl %edi -+ -+ -+ movl 12(%esp), %eax -+ xorl %ecx, %ecx -+ pushl %ebx -+ pushl %ebp -+ movl (%eax), %esi -+ movl 28(%esp), %ebx -+ roll $3, %esi -+ movl 4(%eax), %edi -+ roll $3, %edi -+ movl 24(%esp), %ebp -+ cmpl $0, %ebx -+ je .L002start_decrypt -+ -+ -+ movl (%ebp), %eax -+ xorl %ebx, %ebx -+ movl 4(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 8(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 12(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 16(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 20(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 24(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 28(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 32(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 36(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 40(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 44(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 48(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 52(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 56(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 60(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 64(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 68(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 72(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 76(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 80(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 84(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 88(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 92(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 96(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 100(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 104(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 108(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 112(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 116(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 120(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 124(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ jmp .L003end -+.L002start_decrypt: -+ -+ -+ movl 120(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 124(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 112(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 116(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 104(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 108(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 96(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 100(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 88(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 92(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 80(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 84(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 72(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 76(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 64(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 68(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 56(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 60(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 48(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 52(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 40(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 44(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 32(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 36(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 24(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 28(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl 16(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 20(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+ -+ -+ movl 8(%ebp), %eax -+ xorl %ebx, %ebx -+ movl 12(%ebp), %edx -+ xorl %esi, %eax -+ xorl %esi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %edi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %edi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %edi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %edi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %edi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %edi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %edi -+ -+ -+ movl (%ebp), %eax -+ xorl %ebx, %ebx -+ movl 4(%ebp), %edx -+ xorl %edi, %eax -+ xorl %edi, %edx -+ andl $0xfcfcfcfc, %eax -+ andl $0xcfcfcfcf, %edx -+ movb %al, %bl -+ movb %ah, %cl -+ rorl $4, %edx -+ movl des_SPtrans(%ebx),%ebp -+ movb %dl, %bl -+ xorl %ebp, %esi -+ movl 0x200+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movb %dh, %cl -+ shrl $16, %eax -+ movl 0x100+des_SPtrans(%ebx),%ebp -+ xorl %ebp, %esi -+ movb %ah, %bl -+ shrl $16, %edx -+ movl 0x300+des_SPtrans(%ecx),%ebp -+ xorl %ebp, %esi -+ movl 24(%esp), %ebp -+ movb %dh, %cl -+ andl $0xff, %eax -+ andl $0xff, %edx -+ movl 0x600+des_SPtrans(%ebx),%ebx -+ xorl %ebx, %esi -+ movl 0x700+des_SPtrans(%ecx),%ebx -+ xorl %ebx, %esi -+ movl 0x400+des_SPtrans(%eax),%ebx -+ xorl %ebx, %esi -+ movl 0x500+des_SPtrans(%edx),%ebx -+ xorl %ebx, %esi -+.L003end: -+ -+ -+ rorl $3, %edi -+ movl 20(%esp), %eax -+ rorl $3, %esi -+ movl %edi, (%eax) -+ movl %esi, 4(%eax) -+ popl %ebp -+ popl %ebx -+ popl %edi -+ popl %esi -+ ret -+.des_encrypt2_end: -+ .size des_encrypt2 , .des_encrypt2_end-des_encrypt2 -+.ident "desasm.pl" -+.text -+ .align 16 -+.globl des_encrypt3 -+ .type des_encrypt3 , @function -+des_encrypt3: -+ pushl %ebx -+ movl 8(%esp), %ebx -+ pushl %ebp -+ pushl %esi -+ pushl %edi -+ -+ -+ movl (%ebx), %edi -+ movl 4(%ebx), %esi -+ subl $12, %esp -+ -+ -+ roll $4, %edi -+ movl %edi, %edx -+ xorl %esi, %edi -+ andl $0xf0f0f0f0, %edi -+ xorl %edi, %edx -+ xorl %edi, %esi -+ -+ roll $20, %esi -+ movl %esi, %edi -+ xorl %edx, %esi -+ andl $0xfff0000f, %esi -+ xorl %esi, %edi -+ xorl %esi, %edx -+ -+ roll $14, %edi -+ movl %edi, %esi -+ xorl %edx, %edi -+ andl $0x33333333, %edi -+ xorl %edi, %esi -+ xorl %edi, %edx -+ -+ roll $22, %edx -+ movl %edx, %edi -+ xorl %esi, %edx -+ andl $0x03fc03fc, %edx -+ xorl %edx, %edi -+ xorl %edx, %esi -+ -+ roll $9, %edi -+ movl %edi, %edx -+ xorl %esi, %edi -+ andl $0xaaaaaaaa, %edi -+ xorl %edi, %edx -+ xorl %edi, %esi -+ -+ rorl $3, %edx -+ rorl $2, %esi -+ movl %esi, 4(%ebx) -+ movl 36(%esp), %eax -+ movl %edx, (%ebx) -+ movl 40(%esp), %edi -+ movl 44(%esp), %esi -+ movl $1, 8(%esp) -+ movl %eax, 4(%esp) -+ movl %ebx, (%esp) -+ call des_encrypt2 -+ movl $0, 8(%esp) -+ movl %edi, 4(%esp) -+ movl %ebx, (%esp) -+ call des_encrypt2 -+ movl $1, 8(%esp) -+ movl %esi, 4(%esp) -+ movl %ebx, (%esp) -+ call des_encrypt2 -+ addl $12, %esp -+ movl (%ebx), %edi -+ movl 4(%ebx), %esi -+ -+ -+ roll $2, %esi -+ roll $3, %edi -+ movl %edi, %eax -+ xorl %esi, %edi -+ andl $0xaaaaaaaa, %edi -+ xorl %edi, %eax -+ xorl %edi, %esi -+ -+ roll $23, %eax -+ movl %eax, %edi -+ xorl %esi, %eax -+ andl $0x03fc03fc, %eax -+ xorl %eax, %edi -+ xorl %eax, %esi -+ -+ roll $10, %edi -+ movl %edi, %eax -+ xorl %esi, %edi -+ andl $0x33333333, %edi -+ xorl %edi, %eax -+ xorl %edi, %esi -+ -+ roll $18, %esi -+ movl %esi, %edi -+ xorl %eax, %esi -+ andl $0xfff0000f, %esi -+ xorl %esi, %edi -+ xorl %esi, %eax -+ -+ roll $12, %edi -+ movl %edi, %esi -+ xorl %eax, %edi -+ andl $0xf0f0f0f0, %edi -+ xorl %edi, %esi -+ xorl %edi, %eax -+ -+ rorl $4, %eax -+ movl %eax, (%ebx) -+ movl %esi, 4(%ebx) -+ popl %edi -+ popl %esi -+ popl %ebp -+ popl %ebx -+ ret -+.des_encrypt3_end: -+ .size des_encrypt3 , .des_encrypt3_end-des_encrypt3 -+.ident "desasm.pl" -+.text -+ .align 16 -+.globl des_decrypt3 -+ .type des_decrypt3 , @function -+des_decrypt3: -+ pushl %ebx -+ movl 8(%esp), %ebx -+ pushl %ebp -+ pushl %esi -+ pushl %edi -+ -+ -+ movl (%ebx), %edi -+ movl 4(%ebx), %esi -+ subl $12, %esp -+ -+ -+ roll $4, %edi -+ movl %edi, %edx -+ xorl %esi, %edi -+ andl $0xf0f0f0f0, %edi -+ xorl %edi, %edx -+ xorl %edi, %esi -+ -+ roll $20, %esi -+ movl %esi, %edi -+ xorl %edx, %esi -+ andl $0xfff0000f, %esi -+ xorl %esi, %edi -+ xorl %esi, %edx -+ -+ roll $14, %edi -+ movl %edi, %esi -+ xorl %edx, %edi -+ andl $0x33333333, %edi -+ xorl %edi, %esi -+ xorl %edi, %edx -+ -+ roll $22, %edx -+ movl %edx, %edi -+ xorl %esi, %edx -+ andl $0x03fc03fc, %edx -+ xorl %edx, %edi -+ xorl %edx, %esi -+ -+ roll $9, %edi -+ movl %edi, %edx -+ xorl %esi, %edi -+ andl $0xaaaaaaaa, %edi -+ xorl %edi, %edx -+ xorl %edi, %esi -+ -+ rorl $3, %edx -+ rorl $2, %esi -+ movl %esi, 4(%ebx) -+ movl 36(%esp), %esi -+ movl %edx, (%ebx) -+ movl 40(%esp), %edi -+ movl 44(%esp), %eax -+ movl $0, 8(%esp) -+ movl %eax, 4(%esp) -+ movl %ebx, (%esp) -+ call des_encrypt2 -+ movl $1, 8(%esp) -+ movl %edi, 4(%esp) -+ movl %ebx, (%esp) -+ call des_encrypt2 -+ movl $0, 8(%esp) -+ movl %esi, 4(%esp) -+ movl %ebx, (%esp) -+ call des_encrypt2 -+ addl $12, %esp -+ movl (%ebx), %edi -+ movl 4(%ebx), %esi -+ -+ -+ roll $2, %esi -+ roll $3, %edi -+ movl %edi, %eax -+ xorl %esi, %edi -+ andl $0xaaaaaaaa, %edi -+ xorl %edi, %eax -+ xorl %edi, %esi -+ -+ roll $23, %eax -+ movl %eax, %edi -+ xorl %esi, %eax -+ andl $0x03fc03fc, %eax -+ xorl %eax, %edi -+ xorl %eax, %esi -+ -+ roll $10, %edi -+ movl %edi, %eax -+ xorl %esi, %edi -+ andl $0x33333333, %edi -+ xorl %edi, %eax -+ xorl %edi, %esi -+ -+ roll $18, %esi -+ movl %esi, %edi -+ xorl %eax, %esi -+ andl $0xfff0000f, %esi -+ xorl %esi, %edi -+ xorl %esi, %eax -+ -+ roll $12, %edi -+ movl %edi, %esi -+ xorl %eax, %edi -+ andl $0xf0f0f0f0, %edi -+ xorl %edi, %esi -+ xorl %edi, %eax -+ -+ rorl $4, %eax -+ movl %eax, (%ebx) -+ movl %esi, 4(%ebx) -+ popl %edi -+ popl %esi -+ popl %ebp -+ popl %ebx -+ ret -+.des_decrypt3_end: -+ .size des_decrypt3 , .des_decrypt3_end-des_decrypt3 -+.ident "desasm.pl" -+.text -+ .align 16 -+.globl des_ncbc_encrypt -+ .type des_ncbc_encrypt , @function -+des_ncbc_encrypt: -+ -+ pushl %ebp -+ pushl %ebx -+ pushl %esi -+ pushl %edi -+ movl 28(%esp), %ebp -+ -+ movl 36(%esp), %ebx -+ movl (%ebx), %esi -+ movl 4(%ebx), %edi -+ pushl %edi -+ pushl %esi -+ pushl %edi -+ pushl %esi -+ movl %esp, %ebx -+ movl 36(%esp), %esi -+ movl 40(%esp), %edi -+ -+ movl 56(%esp), %ecx -+ -+ pushl %ecx -+ -+ movl 52(%esp), %eax -+ pushl %eax -+ pushl %ebx -+ cmpl $0, %ecx -+ jz .L004decrypt -+ andl $4294967288, %ebp -+ movl 12(%esp), %eax -+ movl 16(%esp), %ebx -+ jz .L005encrypt_finish -+.L006encrypt_loop: -+ movl (%esi), %ecx -+ movl 4(%esi), %edx -+ xorl %ecx, %eax -+ xorl %edx, %ebx -+ movl %eax, 12(%esp) -+ movl %ebx, 16(%esp) -+ call des_encrypt -+ movl 12(%esp), %eax -+ movl 16(%esp), %ebx -+ movl %eax, (%edi) -+ movl %ebx, 4(%edi) -+ addl $8, %esi -+ addl $8, %edi -+ subl $8, %ebp -+ jnz .L006encrypt_loop -+.L005encrypt_finish: -+ movl 56(%esp), %ebp -+ andl $7, %ebp -+ jz .L007finish -+ xorl %ecx, %ecx -+ xorl %edx, %edx -+ movl .L008cbc_enc_jmp_table(,%ebp,4),%ebp -+ jmp *%ebp -+.L009ej7: -+ movb 6(%esi), %dh -+ sall $8, %edx -+.L010ej6: -+ movb 5(%esi), %dh -+.L011ej5: -+ movb 4(%esi), %dl -+.L012ej4: -+ movl (%esi), %ecx -+ jmp .L013ejend -+.L014ej3: -+ movb 2(%esi), %ch -+ sall $8, %ecx -+.L015ej2: -+ movb 1(%esi), %ch -+.L016ej1: -+ movb (%esi), %cl -+.L013ejend: -+ xorl %ecx, %eax -+ xorl %edx, %ebx -+ movl %eax, 12(%esp) -+ movl %ebx, 16(%esp) -+ call des_encrypt -+ movl 12(%esp), %eax -+ movl 16(%esp), %ebx -+ movl %eax, (%edi) -+ movl %ebx, 4(%edi) -+ jmp .L007finish -+.align 16 -+.L004decrypt: -+ andl $4294967288, %ebp -+ movl 20(%esp), %eax -+ movl 24(%esp), %ebx -+ jz .L017decrypt_finish -+.L018decrypt_loop: -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+ movl %eax, 12(%esp) -+ movl %ebx, 16(%esp) -+ call des_encrypt -+ movl 12(%esp), %eax -+ movl 16(%esp), %ebx -+ movl 20(%esp), %ecx -+ movl 24(%esp), %edx -+ xorl %eax, %ecx -+ xorl %ebx, %edx -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+ movl %ecx, (%edi) -+ movl %edx, 4(%edi) -+ movl %eax, 20(%esp) -+ movl %ebx, 24(%esp) -+ addl $8, %esi -+ addl $8, %edi -+ subl $8, %ebp -+ jnz .L018decrypt_loop -+.L017decrypt_finish: -+ movl 56(%esp), %ebp -+ andl $7, %ebp -+ jz .L007finish -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+ movl %eax, 12(%esp) -+ movl %ebx, 16(%esp) -+ call des_encrypt -+ movl 12(%esp), %eax -+ movl 16(%esp), %ebx -+ movl 20(%esp), %ecx -+ movl 24(%esp), %edx -+ xorl %eax, %ecx -+ xorl %ebx, %edx -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+.L019dj7: -+ rorl $16, %edx -+ movb %dl, 6(%edi) -+ shrl $16, %edx -+.L020dj6: -+ movb %dh, 5(%edi) -+.L021dj5: -+ movb %dl, 4(%edi) -+.L022dj4: -+ movl %ecx, (%edi) -+ jmp .L023djend -+.L024dj3: -+ rorl $16, %ecx -+ movb %cl, 2(%edi) -+ sall $16, %ecx -+.L025dj2: -+ movb %ch, 1(%esi) -+.L026dj1: -+ movb %cl, (%esi) -+.L023djend: -+ jmp .L007finish -+.align 16 -+.L007finish: -+ movl 64(%esp), %ecx -+ addl $28, %esp -+ movl %eax, (%ecx) -+ movl %ebx, 4(%ecx) -+ popl %edi -+ popl %esi -+ popl %ebx -+ popl %ebp -+ ret -+.align 16 -+.L008cbc_enc_jmp_table: -+ .long 0 -+ .long .L016ej1 -+ .long .L015ej2 -+ .long .L014ej3 -+ .long .L012ej4 -+ .long .L011ej5 -+ .long .L010ej6 -+ .long .L009ej7 -+.align 16 -+.L027cbc_dec_jmp_table: -+ .long 0 -+ .long .L026dj1 -+ .long .L025dj2 -+ .long .L024dj3 -+ .long .L022dj4 -+ .long .L021dj5 -+ .long .L020dj6 -+ .long .L019dj7 -+.des_ncbc_encrypt_end: -+ .size des_ncbc_encrypt , .des_ncbc_encrypt_end-des_ncbc_encrypt -+.ident "desasm.pl" -+.text -+ .align 16 -+.globl des_ede3_cbc_encrypt -+ .type des_ede3_cbc_encrypt , @function -+des_ede3_cbc_encrypt: -+ -+ pushl %ebp -+ pushl %ebx -+ pushl %esi -+ pushl %edi -+ movl 28(%esp), %ebp -+ -+ movl 44(%esp), %ebx -+ movl (%ebx), %esi -+ movl 4(%ebx), %edi -+ pushl %edi -+ pushl %esi -+ pushl %edi -+ pushl %esi -+ movl %esp, %ebx -+ movl 36(%esp), %esi -+ movl 40(%esp), %edi -+ -+ movl 64(%esp), %ecx -+ -+ movl 56(%esp), %eax -+ pushl %eax -+ -+ movl 56(%esp), %eax -+ pushl %eax -+ -+ movl 56(%esp), %eax -+ pushl %eax -+ pushl %ebx -+ cmpl $0, %ecx -+ jz .L028decrypt -+ andl $4294967288, %ebp -+ movl 16(%esp), %eax -+ movl 20(%esp), %ebx -+ jz .L029encrypt_finish -+.L030encrypt_loop: -+ movl (%esi), %ecx -+ movl 4(%esi), %edx -+ xorl %ecx, %eax -+ xorl %edx, %ebx -+ movl %eax, 16(%esp) -+ movl %ebx, 20(%esp) -+ call des_encrypt3 -+ movl 16(%esp), %eax -+ movl 20(%esp), %ebx -+ movl %eax, (%edi) -+ movl %ebx, 4(%edi) -+ addl $8, %esi -+ addl $8, %edi -+ subl $8, %ebp -+ jnz .L030encrypt_loop -+.L029encrypt_finish: -+ movl 60(%esp), %ebp -+ andl $7, %ebp -+ jz .L031finish -+ xorl %ecx, %ecx -+ xorl %edx, %edx -+ movl .L032cbc_enc_jmp_table(,%ebp,4),%ebp -+ jmp *%ebp -+.L033ej7: -+ movb 6(%esi), %dh -+ sall $8, %edx -+.L034ej6: -+ movb 5(%esi), %dh -+.L035ej5: -+ movb 4(%esi), %dl -+.L036ej4: -+ movl (%esi), %ecx -+ jmp .L037ejend -+.L038ej3: -+ movb 2(%esi), %ch -+ sall $8, %ecx -+.L039ej2: -+ movb 1(%esi), %ch -+.L040ej1: -+ movb (%esi), %cl -+.L037ejend: -+ xorl %ecx, %eax -+ xorl %edx, %ebx -+ movl %eax, 16(%esp) -+ movl %ebx, 20(%esp) -+ call des_encrypt3 -+ movl 16(%esp), %eax -+ movl 20(%esp), %ebx -+ movl %eax, (%edi) -+ movl %ebx, 4(%edi) -+ jmp .L031finish -+.align 16 -+.L028decrypt: -+ andl $4294967288, %ebp -+ movl 24(%esp), %eax -+ movl 28(%esp), %ebx -+ jz .L041decrypt_finish -+.L042decrypt_loop: -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+ movl %eax, 16(%esp) -+ movl %ebx, 20(%esp) -+ call des_decrypt3 -+ movl 16(%esp), %eax -+ movl 20(%esp), %ebx -+ movl 24(%esp), %ecx -+ movl 28(%esp), %edx -+ xorl %eax, %ecx -+ xorl %ebx, %edx -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+ movl %ecx, (%edi) -+ movl %edx, 4(%edi) -+ movl %eax, 24(%esp) -+ movl %ebx, 28(%esp) -+ addl $8, %esi -+ addl $8, %edi -+ subl $8, %ebp -+ jnz .L042decrypt_loop -+.L041decrypt_finish: -+ movl 60(%esp), %ebp -+ andl $7, %ebp -+ jz .L031finish -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+ movl %eax, 16(%esp) -+ movl %ebx, 20(%esp) -+ call des_decrypt3 -+ movl 16(%esp), %eax -+ movl 20(%esp), %ebx -+ movl 24(%esp), %ecx -+ movl 28(%esp), %edx -+ xorl %eax, %ecx -+ xorl %ebx, %edx -+ movl (%esi), %eax -+ movl 4(%esi), %ebx -+.L043dj7: -+ rorl $16, %edx -+ movb %dl, 6(%edi) -+ shrl $16, %edx -+.L044dj6: -+ movb %dh, 5(%edi) -+.L045dj5: -+ movb %dl, 4(%edi) -+.L046dj4: -+ movl %ecx, (%edi) -+ jmp .L047djend -+.L048dj3: -+ rorl $16, %ecx -+ movb %cl, 2(%edi) -+ sall $16, %ecx -+.L049dj2: -+ movb %ch, 1(%esi) -+.L050dj1: -+ movb %cl, (%esi) -+.L047djend: -+ jmp .L031finish -+.align 16 -+.L031finish: -+ movl 76(%esp), %ecx -+ addl $32, %esp -+ movl %eax, (%ecx) -+ movl %ebx, 4(%ecx) -+ popl %edi -+ popl %esi -+ popl %ebx -+ popl %ebp -+ ret -+.align 16 -+.L032cbc_enc_jmp_table: -+ .long 0 -+ .long .L040ej1 -+ .long .L039ej2 -+ .long .L038ej3 -+ .long .L036ej4 -+ .long .L035ej5 -+ .long .L034ej6 -+ .long .L033ej7 -+.align 16 -+.L051cbc_dec_jmp_table: -+ .long 0 -+ .long .L050dj1 -+ .long .L049dj2 -+ .long .L048dj3 -+ .long .L046dj4 -+ .long .L045dj5 -+ .long .L044dj6 -+ .long .L043dj7 -+.des_ede3_cbc_encrypt_end: -+ .size des_ede3_cbc_encrypt , .des_ede3_cbc_encrypt_end-des_ede3_cbc_encrypt -+.ident "desasm.pl" ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/ecb_enc.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,128 @@ -+/* crypto/des/ecb_enc.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+#include "des_locl.h" -+#include "spr.h" -+ -+char *libdes_version="libdes v 3.24 - 20-Apr-1996 - eay"; -+char *DES_version="DES part of SSLeay 0.8.2b 08-Jan-1998"; -+ -+/* RCSID $Id$ */ -+/* This function ifdef'ed out for FreeS/WAN project. */ -+#ifdef notdef -+char *des_options() -+ { -+ static int init=1; -+ static char buf[32]; -+ -+ if (init) -+ { -+ char *ptr,*unroll,*risc,*size; -+ -+ init=0; -+#ifdef DES_PTR -+ ptr="ptr"; -+#else -+ ptr="idx"; -+#endif -+#if defined(DES_RISC1) || defined(DES_RISC2) -+#ifdef DES_RISC1 -+ risc="risc1"; -+#endif -+#ifdef DES_RISC2 -+ risc="risc2"; -+#endif -+#else -+ risc="cisc"; -+#endif -+#ifdef DES_UNROLL -+ unroll="16"; -+#else -+ unroll="4"; -+#endif -+ if (sizeof(DES_LONG) != sizeof(long)) -+ size="int"; -+ else -+ size="long"; -+ sprintf(buf,"des(%s,%s,%s,%s)",ptr,risc,unroll,size); -+ } -+ return(buf); -+ } -+#endif -+ -+ -+void des_ecb_encrypt(input, output, ks, enc) -+des_cblock (*input); -+des_cblock (*output); -+des_key_schedule ks; -+int enc; -+ { -+ register DES_LONG l; -+ register unsigned char *in,*out; -+ DES_LONG ll[2]; -+ -+ in=(unsigned char *)input; -+ out=(unsigned char *)output; -+ c2l(in,l); ll[0]=l; -+ c2l(in,l); ll[1]=l; -+ des_encrypt(ll,ks,enc); -+ l=ll[0]; l2c(l,out); -+ l=ll[1]; l2c(l,out); -+ l=ll[0]=ll[1]=0; -+ } -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/fcrypt.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,152 @@ -+/* NOCW */ -+ -+/* This version of crypt has been developed from my MIT compatable -+ * DES library. -+ * The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au -+ * Eric Young (eay@cryptsoft.com) -+ */ -+ -+/* Modification by Jens Kupferschmidt (Cu) -+ * I have included directive PARA for shared memory computers. -+ * I have included a directive LONGCRYPT to using this routine to cipher -+ * passwords with more then 8 bytes like HP-UX 10.x it used. The MAXPLEN -+ * definition is the maximum of lenght of password and can changed. I have -+ * defined 24. -+ */ -+ -+#include "des_locl.h" -+ -+/* Added more values to handle illegal salt values the way normal -+ * crypt() implementations do. The patch was sent by -+ * Bjorn Gronvall -+ */ -+static unsigned const char con_salt[128]={ -+0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9, -+0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1, -+0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9, -+0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1, -+0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9, -+0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,0x00,0x01, -+0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, -+0x0A,0x0B,0x05,0x06,0x07,0x08,0x09,0x0A, -+0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12, -+0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A, -+0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22, -+0x23,0x24,0x25,0x20,0x21,0x22,0x23,0x24, -+0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C, -+0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34, -+0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C, -+0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44, -+}; -+ -+static unsigned const char cov_2char[64]={ -+0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35, -+0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44, -+0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C, -+0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54, -+0x55,0x56,0x57,0x58,0x59,0x5A,0x61,0x62, -+0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A, -+0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72, -+0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A -+}; -+ -+#ifndef NOPROTO -+void fcrypt_body(DES_LONG *out,des_key_schedule ks, -+ DES_LONG Eswap0, DES_LONG Eswap1); -+ -+#ifdef PERL5 -+char *des_crypt(const char *buf,const char *salt); -+#else -+char *crypt(const char *buf,const char *salt); -+#endif -+#else -+void fcrypt_body(); -+#ifdef PERL5 -+char *des_crypt(); -+#else -+char *crypt(); -+#endif -+#endif -+ -+#ifdef PERL5 -+char *des_crypt(buf,salt) -+#else -+char *crypt(buf,salt) -+#endif -+const char *buf; -+const char *salt; -+ { -+ static char buff[14]; -+ -+ return(des_fcrypt(buf,salt,buff)); -+ } -+ -+ -+char *des_fcrypt(buf,salt,ret) -+const char *buf; -+const char *salt; -+char *ret; -+ { -+ unsigned int i,j,x,y; -+ DES_LONG Eswap0,Eswap1; -+ DES_LONG out[2],ll; -+ des_cblock key; -+ des_key_schedule ks; -+ unsigned char bb[9]; -+ unsigned char *b=bb; -+ unsigned char c,u; -+ -+ /* eay 25/08/92 -+ * If you call crypt("pwd","*") as often happens when you -+ * have * as the pwd field in /etc/passwd, the function -+ * returns *\0XXXXXXXXX -+ * The \0 makes the string look like * so the pwd "*" would -+ * crypt to "*". This was found when replacing the crypt in -+ * our shared libraries. People found that the disbled -+ * accounts effectivly had no passwd :-(. */ -+ x=ret[0]=((salt[0] == '\0')?'A':salt[0]); -+ Eswap0=con_salt[x]<<2; -+ x=ret[1]=((salt[1] == '\0')?'A':salt[1]); -+ Eswap1=con_salt[x]<<6; -+ -+/* EAY -+r=strlen(buf); -+r=(r+7)/8; -+*/ -+ for (i=0; i<8; i++) -+ { -+ c= *(buf++); -+ if (!c) break; -+ key[i]=(c<<1); -+ } -+ for (; i<8; i++) -+ key[i]=0; -+ -+ des_set_key((des_cblock *)(key),ks); -+ fcrypt_body(&(out[0]),ks,Eswap0,Eswap1); -+ -+ ll=out[0]; l2c(ll,b); -+ ll=out[1]; l2c(ll,b); -+ y=0; -+ u=0x80; -+ bb[8]=0; -+ for (i=2; i<13; i++) -+ { -+ c=0; -+ for (j=0; j<6; j++) -+ { -+ c<<=1; -+ if (bb[y] & u) c|=1; -+ u>>=1; -+ if (!u) -+ { -+ y++; -+ u=0x80; -+ } -+ } -+ ret[i]=cov_2char[c]; -+ } -+ ret[13]='\0'; -+ return(ret); -+ } -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/fcrypt_b.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,148 @@ -+/* crypto/des/fcrypt_b.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+/* #include */ -+ -+/* This version of crypt has been developed from my MIT compatable -+ * DES library. -+ * The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au -+ * Eric Young (eay@cryptsoft.com) -+ */ -+ -+#define DES_FCRYPT -+#include "des_locl.h" -+#undef DES_FCRYPT -+ -+#undef PERM_OP -+#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ -+ (b)^=(t),\ -+ (a)^=((t)<<(n))) -+ -+#undef HPERM_OP -+#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ -+ (a)=(a)^(t)^(t>>(16-(n))))\ -+ -+void fcrypt_body(out, ks, Eswap0, Eswap1) -+DES_LONG *out; -+des_key_schedule ks; -+DES_LONG Eswap0; -+DES_LONG Eswap1; -+ { -+ register DES_LONG l,r,t,u; -+#ifdef DES_PTR -+ register unsigned char *des_SP=(unsigned char *)des_SPtrans; -+#endif -+ register DES_LONG *s; -+ register int j; -+ register DES_LONG E0,E1; -+ -+ l=0; -+ r=0; -+ -+ s=(DES_LONG *)ks; -+ E0=Eswap0; -+ E1=Eswap1; -+ -+ for (j=0; j<25; j++) -+ { -+#ifdef DES_UNROLL -+ register int i; -+ -+ for (i=0; i<32; i+=8) -+ { -+ D_ENCRYPT(l,r,i+0); /* 1 */ -+ D_ENCRYPT(r,l,i+2); /* 2 */ -+ D_ENCRYPT(l,r,i+4); /* 1 */ -+ D_ENCRYPT(r,l,i+6); /* 2 */ -+ } -+#else -+ D_ENCRYPT(l,r, 0); /* 1 */ -+ D_ENCRYPT(r,l, 2); /* 2 */ -+ D_ENCRYPT(l,r, 4); /* 3 */ -+ D_ENCRYPT(r,l, 6); /* 4 */ -+ D_ENCRYPT(l,r, 8); /* 5 */ -+ D_ENCRYPT(r,l,10); /* 6 */ -+ D_ENCRYPT(l,r,12); /* 7 */ -+ D_ENCRYPT(r,l,14); /* 8 */ -+ D_ENCRYPT(l,r,16); /* 9 */ -+ D_ENCRYPT(r,l,18); /* 10 */ -+ D_ENCRYPT(l,r,20); /* 11 */ -+ D_ENCRYPT(r,l,22); /* 12 */ -+ D_ENCRYPT(l,r,24); /* 13 */ -+ D_ENCRYPT(r,l,26); /* 14 */ -+ D_ENCRYPT(l,r,28); /* 15 */ -+ D_ENCRYPT(r,l,30); /* 16 */ -+#endif -+ -+ t=l; -+ l=r; -+ r=t; -+ } -+ l=ROTATE(l,3)&0xffffffffL; -+ r=ROTATE(r,3)&0xffffffffL; -+ -+ PERM_OP(l,r,t, 1,0x55555555L); -+ PERM_OP(r,l,t, 8,0x00ff00ffL); -+ PERM_OP(l,r,t, 2,0x33333333L); -+ PERM_OP(r,l,t,16,0x0000ffffL); -+ PERM_OP(l,r,t, 4,0x0f0f0f0fL); -+ -+ out[0]=r; -+ out[1]=l; -+ } -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/options.txt Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,39 @@ -+Note that the UNROLL option makes the 'inner' des loop unroll all 16 rounds -+instead of the default 4. -+RISC1 and RISC2 are 2 alternatives for the inner loop and -+PTR means to use pointers arithmatic instead of arrays. -+ -+FreeBSD - Pentium Pro 200mhz - gcc 2.7.2.2 - assembler 577,000 4620k/s -+IRIX 6.2 - R10000 195mhz - cc (-O3 -n32) - UNROLL RISC2 PTR 496,000 3968k/s -+solaris 2.5.1 usparc 167mhz?? - SC4.0 - UNROLL RISC1 PTR [1] 459,400 3672k/s -+FreeBSD - Pentium Pro 200mhz - gcc 2.7.2.2 - UNROLL RISC1 433,000 3468k/s -+solaris 2.5.1 usparc 167mhz?? - gcc 2.7.2 - UNROLL 380,000 3041k/s -+linux - pentium 100mhz - gcc 2.7.0 - assembler 281,000 2250k/s -+NT 4.0 - pentium 100mhz - VC 4.2 - assembler 281,000 2250k/s -+AIX 4.1? - PPC604 100mhz - cc - UNROLL 275,000 2200k/s -+IRIX 5.3 - R4400 200mhz - gcc 2.6.3 - UNROLL RISC2 PTR 235,300 1882k/s -+IRIX 5.3 - R4400 200mhz - cc - UNROLL RISC2 PTR 233,700 1869k/s -+NT 4.0 - pentium 100mhz - VC 4.2 - UNROLL RISC1 PTR 191,000 1528k/s -+DEC Alpha 165mhz?? - cc - RISC2 PTR [2] 181,000 1448k/s -+linux - pentium 100mhz - gcc 2.7.0 - UNROLL RISC1 PTR 158,500 1268k/s -+HPUX 10 - 9000/887 - cc - UNROLL [3] 148,000 1190k/s -+solaris 2.5.1 - sparc 10 50mhz - gcc 2.7.2 - UNROLL 123,600 989k/s -+IRIX 5.3 - R4000 100mhz - cc - UNROLL RISC2 PTR 101,000 808k/s -+DGUX - 88100 50mhz(?) - gcc 2.6.3 - UNROLL 81,000 648k/s -+solaris 2.4 486 50mhz - gcc 2.6.3 - assembler 65,000 522k/s -+HPUX 10 - 9000/887 - k&r cc (default compiler) - UNROLL PTR 76,000 608k/s -+solaris 2.4 486 50mhz - gcc 2.6.3 - UNROLL RISC2 43,500 344k/s -+AIX - old slow one :-) - cc - 39,000 312k/s -+ -+Notes. -+[1] For the ultra sparc, SunC 4.0 -+ cc -xtarget=ultra -xarch=v8plus -Xa -xO5, running 'des_opts' -+ gives a speed of 344,000 des/s while 'speed' gives 459,000 des/s. -+ I'll record the higher since it is coming from the library but it -+ is all rather weird. -+[2] Similar to the ultra sparc ([1]), 181,000 for 'des_opts' vs 175,000. -+[3] I was unable to get access to this machine when it was not heavily loaded. -+ As such, my timing program was never able to get more that %30 of the CPU. -+ This would cause the program to give much lower speed numbers because -+ it would be 'fighting' to stay in the cache with the other CPU burning -+ processes. ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/podd.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,75 @@ -+/* crypto/des/podd.h */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+static const unsigned char odd_parity[256]={ -+ 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, -+ 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, -+ 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, -+ 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, -+ 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, -+ 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, -+ 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, -+112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, -+128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, -+145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, -+161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, -+176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, -+193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, -+208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, -+224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, -+241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254}; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/set_key.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,246 @@ -+/* crypto/des/set_key.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+/* set_key.c v 1.4 eay 24/9/91 -+ * 1.4 Speed up by 400% :-) -+ * 1.3 added register declarations. -+ * 1.2 unrolled make_key_sched a bit more -+ * 1.1 added norm_expand_bits -+ * 1.0 First working version -+ */ -+#include "des_locl.h" -+#include "podd.h" -+#include "sk.h" -+ -+#ifndef NOPROTO -+static int check_parity(des_cblock (*key)); -+#else -+static int check_parity(); -+#endif -+ -+int des_check_key=0; -+ -+void des_set_odd_parity(key) -+des_cblock (*key); -+ { -+ int i; -+ -+ for (i=0; i>(n))^(b))&(m)),\ -+ * (b)^=(t),\ -+ * (a)=((a)^((t)<<(n)))) -+ */ -+ -+#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ -+ (a)=(a)^(t)^(t>>(16-(n)))) -+ -+/* return 0 if key parity is odd (correct), -+ * return -1 if key parity error, -+ * return -2 if illegal weak key. -+ */ -+int des_set_key(key, schedule) -+des_cblock (*key); -+des_key_schedule schedule; -+ { -+ static int shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0}; -+ register DES_LONG c,d,t,s,t2; -+ register unsigned char *in; -+ register DES_LONG *k; -+ register int i; -+ -+ if (des_check_key) -+ { -+ if (!check_parity(key)) -+ return(-1); -+ -+ if (des_is_weak_key(key)) -+ return(-2); -+ } -+ -+ k=(DES_LONG *)schedule; -+ in=(unsigned char *)key; -+ -+ c2l(in,c); -+ c2l(in,d); -+ -+ /* do PC1 in 60 simple operations */ -+/* PERM_OP(d,c,t,4,0x0f0f0f0fL); -+ HPERM_OP(c,t,-2, 0xcccc0000L); -+ HPERM_OP(c,t,-1, 0xaaaa0000L); -+ HPERM_OP(c,t, 8, 0x00ff0000L); -+ HPERM_OP(c,t,-1, 0xaaaa0000L); -+ HPERM_OP(d,t,-8, 0xff000000L); -+ HPERM_OP(d,t, 8, 0x00ff0000L); -+ HPERM_OP(d,t, 2, 0x33330000L); -+ d=((d&0x00aa00aaL)<<7L)|((d&0x55005500L)>>7L)|(d&0xaa55aa55L); -+ d=(d>>8)|((c&0xf0000000L)>>4); -+ c&=0x0fffffffL; */ -+ -+ /* I now do it in 47 simple operations :-) -+ * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) -+ * for the inspiration. :-) */ -+ PERM_OP (d,c,t,4,0x0f0f0f0fL); -+ HPERM_OP(c,t,-2,0xcccc0000L); -+ HPERM_OP(d,t,-2,0xcccc0000L); -+ PERM_OP (d,c,t,1,0x55555555L); -+ PERM_OP (c,d,t,8,0x00ff00ffL); -+ PERM_OP (d,c,t,1,0x55555555L); -+ d= (((d&0x000000ffL)<<16L)| (d&0x0000ff00L) | -+ ((d&0x00ff0000L)>>16L)|((c&0xf0000000L)>>4L)); -+ c&=0x0fffffffL; -+ -+ for (i=0; i>2L)|(c<<26L)); d=((d>>2L)|(d<<26L)); } -+ else -+ { c=((c>>1L)|(c<<27L)); d=((d>>1L)|(d<<27L)); } -+ c&=0x0fffffffL; -+ d&=0x0fffffffL; -+ /* could be a few less shifts but I am to lazy at this -+ * point in time to investigate */ -+ s= des_skb[0][ (c )&0x3f ]| -+ des_skb[1][((c>> 6)&0x03)|((c>> 7L)&0x3c)]| -+ des_skb[2][((c>>13)&0x0f)|((c>>14L)&0x30)]| -+ des_skb[3][((c>>20)&0x01)|((c>>21L)&0x06) | -+ ((c>>22L)&0x38)]; -+ t= des_skb[4][ (d )&0x3f ]| -+ des_skb[5][((d>> 7L)&0x03)|((d>> 8L)&0x3c)]| -+ des_skb[6][ (d>>15L)&0x3f ]| -+ des_skb[7][((d>>21L)&0x0f)|((d>>22L)&0x30)]; -+ -+ /* table contained 0213 4657 */ -+ t2=((t<<16L)|(s&0x0000ffffL))&0xffffffffL; -+ *(k++)=ROTATE(t2,30)&0xffffffffL; -+ -+ t2=((s>>16L)|(t&0xffff0000L)); -+ *(k++)=ROTATE(t2,26)&0xffffffffL; -+ } -+ return(0); -+ } -+ -+int des_key_sched(key, schedule) -+des_cblock (*key); -+des_key_schedule schedule; -+ { -+ return(des_set_key(key,schedule)); -+ } ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/sk.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,204 @@ -+/* crypto/des/sk.h */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+static const DES_LONG des_skb[8][64]={ -+{ -+/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ -+0x00000000L,0x00000010L,0x20000000L,0x20000010L, -+0x00010000L,0x00010010L,0x20010000L,0x20010010L, -+0x00000800L,0x00000810L,0x20000800L,0x20000810L, -+0x00010800L,0x00010810L,0x20010800L,0x20010810L, -+0x00000020L,0x00000030L,0x20000020L,0x20000030L, -+0x00010020L,0x00010030L,0x20010020L,0x20010030L, -+0x00000820L,0x00000830L,0x20000820L,0x20000830L, -+0x00010820L,0x00010830L,0x20010820L,0x20010830L, -+0x00080000L,0x00080010L,0x20080000L,0x20080010L, -+0x00090000L,0x00090010L,0x20090000L,0x20090010L, -+0x00080800L,0x00080810L,0x20080800L,0x20080810L, -+0x00090800L,0x00090810L,0x20090800L,0x20090810L, -+0x00080020L,0x00080030L,0x20080020L,0x20080030L, -+0x00090020L,0x00090030L,0x20090020L,0x20090030L, -+0x00080820L,0x00080830L,0x20080820L,0x20080830L, -+0x00090820L,0x00090830L,0x20090820L,0x20090830L, -+},{ -+/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ -+0x00000000L,0x02000000L,0x00002000L,0x02002000L, -+0x00200000L,0x02200000L,0x00202000L,0x02202000L, -+0x00000004L,0x02000004L,0x00002004L,0x02002004L, -+0x00200004L,0x02200004L,0x00202004L,0x02202004L, -+0x00000400L,0x02000400L,0x00002400L,0x02002400L, -+0x00200400L,0x02200400L,0x00202400L,0x02202400L, -+0x00000404L,0x02000404L,0x00002404L,0x02002404L, -+0x00200404L,0x02200404L,0x00202404L,0x02202404L, -+0x10000000L,0x12000000L,0x10002000L,0x12002000L, -+0x10200000L,0x12200000L,0x10202000L,0x12202000L, -+0x10000004L,0x12000004L,0x10002004L,0x12002004L, -+0x10200004L,0x12200004L,0x10202004L,0x12202004L, -+0x10000400L,0x12000400L,0x10002400L,0x12002400L, -+0x10200400L,0x12200400L,0x10202400L,0x12202400L, -+0x10000404L,0x12000404L,0x10002404L,0x12002404L, -+0x10200404L,0x12200404L,0x10202404L,0x12202404L, -+},{ -+/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ -+0x00000000L,0x00000001L,0x00040000L,0x00040001L, -+0x01000000L,0x01000001L,0x01040000L,0x01040001L, -+0x00000002L,0x00000003L,0x00040002L,0x00040003L, -+0x01000002L,0x01000003L,0x01040002L,0x01040003L, -+0x00000200L,0x00000201L,0x00040200L,0x00040201L, -+0x01000200L,0x01000201L,0x01040200L,0x01040201L, -+0x00000202L,0x00000203L,0x00040202L,0x00040203L, -+0x01000202L,0x01000203L,0x01040202L,0x01040203L, -+0x08000000L,0x08000001L,0x08040000L,0x08040001L, -+0x09000000L,0x09000001L,0x09040000L,0x09040001L, -+0x08000002L,0x08000003L,0x08040002L,0x08040003L, -+0x09000002L,0x09000003L,0x09040002L,0x09040003L, -+0x08000200L,0x08000201L,0x08040200L,0x08040201L, -+0x09000200L,0x09000201L,0x09040200L,0x09040201L, -+0x08000202L,0x08000203L,0x08040202L,0x08040203L, -+0x09000202L,0x09000203L,0x09040202L,0x09040203L, -+},{ -+/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ -+0x00000000L,0x00100000L,0x00000100L,0x00100100L, -+0x00000008L,0x00100008L,0x00000108L,0x00100108L, -+0x00001000L,0x00101000L,0x00001100L,0x00101100L, -+0x00001008L,0x00101008L,0x00001108L,0x00101108L, -+0x04000000L,0x04100000L,0x04000100L,0x04100100L, -+0x04000008L,0x04100008L,0x04000108L,0x04100108L, -+0x04001000L,0x04101000L,0x04001100L,0x04101100L, -+0x04001008L,0x04101008L,0x04001108L,0x04101108L, -+0x00020000L,0x00120000L,0x00020100L,0x00120100L, -+0x00020008L,0x00120008L,0x00020108L,0x00120108L, -+0x00021000L,0x00121000L,0x00021100L,0x00121100L, -+0x00021008L,0x00121008L,0x00021108L,0x00121108L, -+0x04020000L,0x04120000L,0x04020100L,0x04120100L, -+0x04020008L,0x04120008L,0x04020108L,0x04120108L, -+0x04021000L,0x04121000L,0x04021100L,0x04121100L, -+0x04021008L,0x04121008L,0x04021108L,0x04121108L, -+},{ -+/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ -+0x00000000L,0x10000000L,0x00010000L,0x10010000L, -+0x00000004L,0x10000004L,0x00010004L,0x10010004L, -+0x20000000L,0x30000000L,0x20010000L,0x30010000L, -+0x20000004L,0x30000004L,0x20010004L,0x30010004L, -+0x00100000L,0x10100000L,0x00110000L,0x10110000L, -+0x00100004L,0x10100004L,0x00110004L,0x10110004L, -+0x20100000L,0x30100000L,0x20110000L,0x30110000L, -+0x20100004L,0x30100004L,0x20110004L,0x30110004L, -+0x00001000L,0x10001000L,0x00011000L,0x10011000L, -+0x00001004L,0x10001004L,0x00011004L,0x10011004L, -+0x20001000L,0x30001000L,0x20011000L,0x30011000L, -+0x20001004L,0x30001004L,0x20011004L,0x30011004L, -+0x00101000L,0x10101000L,0x00111000L,0x10111000L, -+0x00101004L,0x10101004L,0x00111004L,0x10111004L, -+0x20101000L,0x30101000L,0x20111000L,0x30111000L, -+0x20101004L,0x30101004L,0x20111004L,0x30111004L, -+},{ -+/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ -+0x00000000L,0x08000000L,0x00000008L,0x08000008L, -+0x00000400L,0x08000400L,0x00000408L,0x08000408L, -+0x00020000L,0x08020000L,0x00020008L,0x08020008L, -+0x00020400L,0x08020400L,0x00020408L,0x08020408L, -+0x00000001L,0x08000001L,0x00000009L,0x08000009L, -+0x00000401L,0x08000401L,0x00000409L,0x08000409L, -+0x00020001L,0x08020001L,0x00020009L,0x08020009L, -+0x00020401L,0x08020401L,0x00020409L,0x08020409L, -+0x02000000L,0x0A000000L,0x02000008L,0x0A000008L, -+0x02000400L,0x0A000400L,0x02000408L,0x0A000408L, -+0x02020000L,0x0A020000L,0x02020008L,0x0A020008L, -+0x02020400L,0x0A020400L,0x02020408L,0x0A020408L, -+0x02000001L,0x0A000001L,0x02000009L,0x0A000009L, -+0x02000401L,0x0A000401L,0x02000409L,0x0A000409L, -+0x02020001L,0x0A020001L,0x02020009L,0x0A020009L, -+0x02020401L,0x0A020401L,0x02020409L,0x0A020409L, -+},{ -+/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ -+0x00000000L,0x00000100L,0x00080000L,0x00080100L, -+0x01000000L,0x01000100L,0x01080000L,0x01080100L, -+0x00000010L,0x00000110L,0x00080010L,0x00080110L, -+0x01000010L,0x01000110L,0x01080010L,0x01080110L, -+0x00200000L,0x00200100L,0x00280000L,0x00280100L, -+0x01200000L,0x01200100L,0x01280000L,0x01280100L, -+0x00200010L,0x00200110L,0x00280010L,0x00280110L, -+0x01200010L,0x01200110L,0x01280010L,0x01280110L, -+0x00000200L,0x00000300L,0x00080200L,0x00080300L, -+0x01000200L,0x01000300L,0x01080200L,0x01080300L, -+0x00000210L,0x00000310L,0x00080210L,0x00080310L, -+0x01000210L,0x01000310L,0x01080210L,0x01080310L, -+0x00200200L,0x00200300L,0x00280200L,0x00280300L, -+0x01200200L,0x01200300L,0x01280200L,0x01280300L, -+0x00200210L,0x00200310L,0x00280210L,0x00280310L, -+0x01200210L,0x01200310L,0x01280210L,0x01280310L, -+},{ -+/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ -+0x00000000L,0x04000000L,0x00040000L,0x04040000L, -+0x00000002L,0x04000002L,0x00040002L,0x04040002L, -+0x00002000L,0x04002000L,0x00042000L,0x04042000L, -+0x00002002L,0x04002002L,0x00042002L,0x04042002L, -+0x00000020L,0x04000020L,0x00040020L,0x04040020L, -+0x00000022L,0x04000022L,0x00040022L,0x04040022L, -+0x00002020L,0x04002020L,0x00042020L,0x04042020L, -+0x00002022L,0x04002022L,0x00042022L,0x04042022L, -+0x00000800L,0x04000800L,0x00040800L,0x04040800L, -+0x00000802L,0x04000802L,0x00040802L,0x04040802L, -+0x00002800L,0x04002800L,0x00042800L,0x04042800L, -+0x00002802L,0x04002802L,0x00042802L,0x04042802L, -+0x00000820L,0x04000820L,0x00040820L,0x04040820L, -+0x00000822L,0x04000822L,0x00040822L,0x04040822L, -+0x00002820L,0x04002820L,0x00042820L,0x04042820L, -+0x00002822L,0x04002822L,0x00042822L,0x04042822L, -+}}; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/speed.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,329 @@ -+/* crypto/des/speed.c */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+/* 11-Sep-92 Andrew Daviel Support for Silicon Graphics IRIX added */ -+/* 06-Apr-92 Luke Brennan Support for VMS and add extra signal calls */ -+ -+#ifndef MSDOS -+#define TIMES -+#endif -+ -+#include -+#ifndef MSDOS -+#include -+#else -+#include -+extern int exit(); -+#endif -+#include -+#ifndef VMS -+#ifndef _IRIX -+#include -+#endif -+#ifdef TIMES -+#include -+#include -+#endif -+#else /* VMS */ -+#include -+struct tms { -+ time_t tms_utime; -+ time_t tms_stime; -+ time_t tms_uchild; /* I dunno... */ -+ time_t tms_uchildsys; /* so these names are a guess :-) */ -+ } -+#endif -+#ifndef TIMES -+#include -+#endif -+ -+#ifdef sun -+#include -+#include -+#endif -+ -+#include "des_locl.h" -+ -+/* The following if from times(3) man page. It may need to be changed */ -+#ifndef HZ -+# ifndef CLK_TCK -+# ifndef _BSD_CLK_TCK_ /* FreeBSD fix */ -+# ifndef VMS -+# define HZ 100.0 -+# else /* VMS */ -+# define HZ 100.0 -+# endif -+# else /* _BSD_CLK_TCK_ */ -+# define HZ ((double)_BSD_CLK_TCK_) -+# endif -+# else /* CLK_TCK */ -+# define HZ ((double)CLK_TCK) -+# endif -+#endif -+ -+#define BUFSIZE ((long)1024) -+long run=0; -+ -+#ifndef NOPROTO -+double Time_F(int s); -+#else -+double Time_F(); -+#endif -+ -+#ifdef SIGALRM -+#if defined(__STDC__) || defined(sgi) || defined(_AIX) -+#define SIGRETTYPE void -+#else -+#define SIGRETTYPE int -+#endif -+ -+#ifndef NOPROTO -+SIGRETTYPE sig_done(int sig); -+#else -+SIGRETTYPE sig_done(); -+#endif -+ -+SIGRETTYPE sig_done(sig) -+int sig; -+ { -+ signal(SIGALRM,sig_done); -+ run=0; -+#ifdef LINT -+ sig=sig; -+#endif -+ } -+#endif -+ -+#define START 0 -+#define STOP 1 -+ -+double Time_F(s) -+int s; -+ { -+ double ret; -+#ifdef TIMES -+ static struct tms tstart,tend; -+ -+ if (s == START) -+ { -+ times(&tstart); -+ return(0); -+ } -+ else -+ { -+ times(&tend); -+ ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ; -+ return((ret == 0.0)?1e-6:ret); -+ } -+#else /* !times() */ -+ static struct timeb tstart,tend; -+ long i; -+ -+ if (s == START) -+ { -+ ftime(&tstart); -+ return(0); -+ } -+ else -+ { -+ ftime(&tend); -+ i=(long)tend.millitm-(long)tstart.millitm; -+ ret=((double)(tend.time-tstart.time))+((double)i)/1e3; -+ return((ret == 0.0)?1e-6:ret); -+ } -+#endif -+ } -+ -+int main(argc,argv) -+int argc; -+char **argv; -+ { -+ long count; -+ static unsigned char buf[BUFSIZE]; -+ static des_cblock key ={0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0}; -+ static des_cblock key2={0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12}; -+ static des_cblock key3={0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34}; -+ des_key_schedule sch,sch2,sch3; -+ double a,b,c,d,e; -+#ifndef SIGALRM -+ long ca,cb,cc,cd,ce; -+#endif -+ -+#ifndef TIMES -+ printf("To get the most acurate results, try to run this\n"); -+ printf("program when this computer is idle.\n"); -+#endif -+ -+ des_set_key((C_Block *)key2,sch2); -+ des_set_key((C_Block *)key3,sch3); -+ -+#ifndef SIGALRM -+ printf("First we calculate the approximate speed ...\n"); -+ des_set_key((C_Block *)key,sch); -+ count=10; -+ do { -+ long i; -+ DES_LONG data[2]; -+ -+ count*=2; -+ Time_F(START); -+ for (i=count; i; i--) -+ des_encrypt(data,&(sch[0]),DES_ENCRYPT); -+ d=Time_F(STOP); -+ } while (d < 3.0); -+ ca=count; -+ cb=count*3; -+ cc=count*3*8/BUFSIZE+1; -+ cd=count*8/BUFSIZE+1; -+ ce=count/20+1; -+ printf("Doing set_key %ld times\n",ca); -+#define COND(d) (count != (d)) -+#define COUNT(d) (d) -+#else -+#define COND(c) (run) -+#define COUNT(d) (count) -+ signal(SIGALRM,sig_done); -+ printf("Doing set_key for 10 seconds\n"); -+ alarm(10); -+#endif -+ -+ Time_F(START); -+ for (count=0,run=1; COND(ca); count++) -+ des_set_key((C_Block *)key,sch); -+ d=Time_F(STOP); -+ printf("%ld set_key's in %.2f seconds\n",count,d); -+ a=((double)COUNT(ca))/d; -+ -+#ifdef SIGALRM -+ printf("Doing des_encrypt's for 10 seconds\n"); -+ alarm(10); -+#else -+ printf("Doing des_encrypt %ld times\n",cb); -+#endif -+ Time_F(START); -+ for (count=0,run=1; COND(cb); count++) -+ { -+ DES_LONG data[2]; -+ -+ des_encrypt(data,&(sch[0]),DES_ENCRYPT); -+ } -+ d=Time_F(STOP); -+ printf("%ld des_encrypt's in %.2f second\n",count,d); -+ b=((double)COUNT(cb)*8)/d; -+ -+#ifdef SIGALRM -+ printf("Doing des_cbc_encrypt on %ld byte blocks for 10 seconds\n", -+ BUFSIZE); -+ alarm(10); -+#else -+ printf("Doing des_cbc_encrypt %ld times on %ld byte blocks\n",cc, -+ BUFSIZE); -+#endif -+ Time_F(START); -+ for (count=0,run=1; COND(cc); count++) -+ des_ncbc_encrypt((C_Block *)buf,(C_Block *)buf,BUFSIZE,&(sch[0]), -+ (C_Block *)&(key[0]),DES_ENCRYPT); -+ d=Time_F(STOP); -+ printf("%ld des_cbc_encrypt's of %ld byte blocks in %.2f second\n", -+ count,BUFSIZE,d); -+ c=((double)COUNT(cc)*BUFSIZE)/d; -+ -+#ifdef SIGALRM -+ printf("Doing des_ede_cbc_encrypt on %ld byte blocks for 10 seconds\n", -+ BUFSIZE); -+ alarm(10); -+#else -+ printf("Doing des_ede_cbc_encrypt %ld times on %ld byte blocks\n",cd, -+ BUFSIZE); -+#endif -+ Time_F(START); -+ for (count=0,run=1; COND(cd); count++) -+ des_ede3_cbc_encrypt((C_Block *)buf,(C_Block *)buf,BUFSIZE, -+ &(sch[0]), -+ &(sch2[0]), -+ &(sch3[0]), -+ (C_Block *)&(key[0]), -+ DES_ENCRYPT); -+ d=Time_F(STOP); -+ printf("%ld des_ede_cbc_encrypt's of %ld byte blocks in %.2f second\n", -+ count,BUFSIZE,d); -+ d=((double)COUNT(cd)*BUFSIZE)/d; -+ -+#ifdef SIGALRM -+ printf("Doing crypt for 10 seconds\n"); -+ alarm(10); -+#else -+ printf("Doing crypt %ld times\n",ce); -+#endif -+ Time_F(START); -+ for (count=0,run=1; COND(ce); count++) -+ crypt("testing1","ef"); -+ e=Time_F(STOP); -+ printf("%ld crypts in %.2f second\n",count,e); -+ e=((double)COUNT(ce))/e; -+ -+ printf("set_key per sec = %12.2f (%9.3fuS)\n",a,1.0e6/a); -+ printf("DES raw ecb bytes per sec = %12.2f (%9.3fuS)\n",b,8.0e6/b); -+ printf("DES cbc bytes per sec = %12.2f (%9.3fuS)\n",c,8.0e6/c); -+ printf("DES ede cbc bytes per sec = %12.2f (%9.3fuS)\n",d,8.0e6/d); -+ printf("crypt per sec = %12.2f (%9.3fuS)\n",e,1.0e6/e); -+ exit(0); -+#if defined(LINT) || defined(MSDOS) -+ return(0); -+#endif -+ } ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/crypto/ciphers/des/spr.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,204 @@ -+/* crypto/des/spr.h */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+const DES_LONG des_SPtrans[8][64]={ -+{ -+/* nibble 0 */ -+0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L, -+0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L, -+0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L, -+0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L, -+0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L, -+0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L, -+0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L, -+0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L, -+0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L, -+0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L, -+0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L, -+0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L, -+0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L, -+0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L, -+0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L, -+0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L, -+},{ -+/* nibble 1 */ -+0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L, -+0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L, -+0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L, -+0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L, -+0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L, -+0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L, -+0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L, -+0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L, -+0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L, -+0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L, -+0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L, -+0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L, -+0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L, -+0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L, -+0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L, -+0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L, -+},{ -+/* nibble 2 */ -+0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L, -+0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L, -+0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L, -+0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L, -+0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L, -+0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L, -+0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L, -+0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L, -+0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L, -+0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L, -+0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L, -+0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L, -+0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L, -+0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L, -+0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L, -+0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L, -+},{ -+/* nibble 3 */ -+0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L, -+0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L, -+0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L, -+0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L, -+0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L, -+0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L, -+0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L, -+0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L, -+0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L, -+0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L, -+0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L, -+0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L, -+0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L, -+0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L, -+0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L, -+0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L, -+},{ -+/* nibble 4 */ -+0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L, -+0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L, -+0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L, -+0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L, -+0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L, -+0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L, -+0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L, -+0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L, -+0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L, -+0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L, -+0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L, -+0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L, -+0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L, -+0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L, -+0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L, -+0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L, -+},{ -+/* nibble 5 */ -+0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L, -+0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L, -+0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L, -+0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L, -+0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L, -+0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L, -+0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L, -+0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L, -+0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L, -+0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L, -+0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L, -+0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L, -+0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L, -+0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L, -+0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L, -+0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L, -+},{ -+/* nibble 6 */ -+0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L, -+0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L, -+0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L, -+0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L, -+0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L, -+0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L, -+0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L, -+0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L, -+0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L, -+0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L, -+0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L, -+0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L, -+0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L, -+0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L, -+0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L, -+0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L, -+},{ -+/* nibble 7 */ -+0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L, -+0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L, -+0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L, -+0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L, -+0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L, -+0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L, -+0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L, -+0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L, -+0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L, -+0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L, -+0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L, -+0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L, -+0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L, -+0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L, -+0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L, -+0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L, -+}}; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/crypto/aes.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,97 @@ -+// I retain copyright in this code but I encourage its free use provided -+// that I don't carry any responsibility for the results. I am especially -+// happy to see it used in free and open source software. If you do use -+// it I would appreciate an acknowledgement of its origin in the code or -+// the product that results and I would also appreciate knowing a little -+// about the use to which it is being put. I am grateful to Frank Yellin -+// for some ideas that are used in this implementation. -+// -+// Dr B. R. Gladman 6th April 2001. -+// -+// This is an implementation of the AES encryption algorithm (Rijndael) -+// designed by Joan Daemen and Vincent Rijmen. This version is designed -+// to provide both fixed and dynamic block and key lengths and can also -+// run with either big or little endian internal byte order (see aes.h). -+// It inputs block and key lengths in bytes with the legal values being -+// 16, 24 and 32. -+ -+/* -+ * Modified by Jari Ruusu, May 1 2001 -+ * - Fixed some compile warnings, code was ok but gcc warned anyway. -+ * - Changed basic types: byte -> unsigned char, word -> u_int32_t -+ * - Major name space cleanup: Names visible to outside now begin -+ * with "aes_" or "AES_". A lot of stuff moved from aes.h to aes.c -+ * - Removed C++ and DLL support as part of name space cleanup. -+ * - Eliminated unnecessary recomputation of tables. (actual bug fix) -+ * - Merged precomputed constant tables to aes.c file. -+ * - Removed data alignment restrictions for portability reasons. -+ * - Made block and key lengths accept bit count (128/192/256) -+ * as well byte count (16/24/32). -+ * - Removed all error checks. This change also eliminated the need -+ * to preinitialize the context struct to zero. -+ * - Removed some totally unused constants. -+ */ -+ -+#ifndef _AES_H -+#define _AES_H -+ -+#if defined(__linux__) && defined(__KERNEL__) -+# include -+#else -+# include -+#endif -+ -+// CONFIGURATION OPTIONS (see also aes.c) -+// -+// Define AES_BLOCK_SIZE to set the cipher block size (16, 24 or 32) or -+// leave this undefined for dynamically variable block size (this will -+// result in much slower code). -+// IMPORTANT NOTE: AES_BLOCK_SIZE is in BYTES (16, 24, 32 or undefined). If -+// left undefined a slower version providing variable block length is compiled -+ -+#define AES_BLOCK_SIZE 16 -+ -+// The number of key schedule words for different block and key lengths -+// allowing for method of computation which requires the length to be a -+// multiple of the key length -+// -+// Nk = 4 6 8 -+// ------------- -+// Nb = 4 | 60 60 64 -+// 6 | 96 90 96 -+// 8 | 120 120 120 -+ -+#if !defined(AES_BLOCK_SIZE) || (AES_BLOCK_SIZE == 32) -+#define AES_KS_LENGTH 120 -+#define AES_RC_LENGTH 29 -+#else -+#define AES_KS_LENGTH 4 * AES_BLOCK_SIZE -+#define AES_RC_LENGTH (9 * AES_BLOCK_SIZE) / 8 - 8 -+#endif -+ -+typedef struct -+{ -+ u_int32_t aes_Nkey; // the number of words in the key input block -+ u_int32_t aes_Nrnd; // the number of cipher rounds -+ u_int32_t aes_e_key[AES_KS_LENGTH]; // the encryption key schedule -+ u_int32_t aes_d_key[AES_KS_LENGTH]; // the decryption key schedule -+#if !defined(AES_BLOCK_SIZE) -+ u_int32_t aes_Ncol; // the number of columns in the cipher state -+#endif -+} aes_context; -+ -+// THE CIPHER INTERFACE -+ -+#if !defined(AES_BLOCK_SIZE) -+extern void aes_set_blk(aes_context *, const int); -+#endif -+extern void aes_set_key(aes_context *, const unsigned char [], const int, const int); -+extern void aes_encrypt(const aes_context *, const unsigned char [], unsigned char []); -+extern void aes_decrypt(const aes_context *, const unsigned char [], unsigned char []); -+ -+// The block length inputs to aes_set_block and aes_set_key are in numbers -+// of bytes or bits. The calls to subroutines must be made in the above -+// order but multiple calls can be made without repeating earlier calls -+// if their parameters have not changed. -+ -+#endif // _AES_H ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/crypto/aes_cbc.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,4 @@ -+/* Glue header */ -+#include "aes.h" -+int AES_set_key(aes_context *aes_ctx, const u_int8_t * key, int keysize); -+int AES_cbc_encrypt(aes_context *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt); ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/crypto/aes_xcbc_mac.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,12 @@ -+#ifndef _AES_XCBC_MAC_H -+#define _AES_XCBC_MAC_H -+ -+typedef u_int32_t aes_block[4]; -+typedef struct { -+ aes_context ctx_k1; -+ aes_block k2; -+ aes_block k3; -+} aes_context_mac; -+int AES_xcbc_mac_set_key(aes_context_mac *ctxm, const u_int8_t *key, int keylen); -+int AES_xcbc_mac_hash(const aes_context_mac *ctxm, const u_int8_t * in, int ilen, u_int8_t hash[16]); -+#endif /* _AES_XCBC_MAC_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/crypto/cbc_generic.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,110 @@ -+#ifndef _CBC_GENERIC_H -+#define _CBC_GENERIC_H -+/* -+ * CBC macro helpers -+ * -+ * Author: JuanJo Ciarlante -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ */ -+ -+/* -+ * Heavily inspired in loop_AES -+ */ -+#define CBC_IMPL_BLK16(name, ctx_type, addr_type, enc_func, dec_func) \ -+int name(ctx_type *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) { \ -+ int ret=ilen, pos; \ -+ const u_int32_t *iv_i; \ -+ if ((ilen) % 16) return 0; \ -+ if (encrypt) { \ -+ pos=0; \ -+ while(pos=0) { \ -+ dec_func(ctx, (const addr_type) in, (addr_type) out); \ -+ if (pos==0) \ -+ iv_i=(const u_int32_t*) (iv); \ -+ else \ -+ iv_i=(const u_int32_t*) (in-16); \ -+ *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \ -+ *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \ -+ *((u_int32_t *)(&out[ 8])) ^= iv_i[2]; \ -+ *((u_int32_t *)(&out[12])) ^= iv_i[3]; \ -+ in-=16; \ -+ out-=16; \ -+ pos-=16; \ -+ } \ -+ } \ -+ return ret; \ -+} -+#define CBC_IMPL_BLK8(name, ctx_type, addr_type, enc_func, dec_func) \ -+int name(ctx_type *ctx, u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) { \ -+ int ret=ilen, pos; \ -+ const u_int32_t *iv_i; \ -+ if ((ilen) % 8) return 0; \ -+ if (encrypt) { \ -+ pos=0; \ -+ while(pos=0) { \ -+ dec_func(ctx, (const addr_type)in, (addr_type)out); \ -+ if (pos==0) \ -+ iv_i=(const u_int32_t*) (iv); \ -+ else \ -+ iv_i=(const u_int32_t*) (in-8); \ -+ *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \ -+ *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \ -+ in-=8; \ -+ out-=8; \ -+ pos-=8; \ -+ } \ -+ } \ -+ return ret; \ -+} -+#define CBC_DECL(name, ctx_type) \ -+int name(ctx_type *ctx, u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) -+/* -+Eg.: -+CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, u_int8_t *, aes_encrypt, aes_decrypt); -+CBC_DECL(AES_cbc_encrypt, aes_context); -+*/ -+#endif /* _CBC_GENERIC_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/crypto/des.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,298 @@ -+/* crypto/des/des.org */ -+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING -+ * -+ * Always modify des.org since des.h is automatically generated from -+ * it during SSLeay configuration. -+ * -+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING -+ */ -+ -+#ifndef HEADER_DES_H -+#define HEADER_DES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+ -+/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a -+ * %20 speed up (longs are 8 bytes, int's are 4). */ -+/* Must be unsigned int on ia64/Itanium or DES breaks badly */ -+ -+#ifdef __KERNEL__ -+#include -+#else -+#include -+#endif -+ -+#ifndef DES_LONG -+#define DES_LONG u_int32_t -+#endif -+ -+typedef unsigned char des_cblock[8]; -+typedef struct { des_cblock ks; } des_key_schedule[16]; -+ -+#define DES_KEY_SZ (sizeof(des_cblock)) -+#define DES_SCHEDULE_SZ (sizeof(des_key_schedule)) -+ -+#define DES_ENCRYPT 1 -+#define DES_DECRYPT 0 -+ -+#define DES_CBC_MODE 0 -+#define DES_PCBC_MODE 1 -+ -+#define des_ecb2_encrypt(i,o,k1,k2,e) \ -+ des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e)) -+ -+#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ -+ des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e)) -+ -+#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \ -+ des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e)) -+ -+#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \ -+ des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n)) -+ -+#define C_Block des_cblock -+#define Key_schedule des_key_schedule -+#ifdef KERBEROS -+#define ENCRYPT DES_ENCRYPT -+#define DECRYPT DES_DECRYPT -+#endif -+#define KEY_SZ DES_KEY_SZ -+#define string_to_key des_string_to_key -+#define read_pw_string des_read_pw_string -+#define random_key des_random_key -+#define pcbc_encrypt des_pcbc_encrypt -+#define set_key des_set_key -+#define key_sched des_key_sched -+#define ecb_encrypt des_ecb_encrypt -+#define cbc_encrypt des_cbc_encrypt -+#define ncbc_encrypt des_ncbc_encrypt -+#define xcbc_encrypt des_xcbc_encrypt -+#define cbc_cksum des_cbc_cksum -+#define quad_cksum des_quad_cksum -+ -+/* For compatibility with the MIT lib - eay 20/05/92 */ -+typedef des_key_schedule bit_64; -+#define des_fixup_key_parity des_set_odd_parity -+#define des_check_key_parity check_parity -+ -+extern int des_check_key; /* defaults to false */ -+extern int des_rw_mode; /* defaults to DES_PCBC_MODE */ -+ -+/* The next line is used to disable full ANSI prototypes, if your -+ * compiler has problems with the prototypes, make sure this line always -+ * evaluates to true :-) */ -+#if defined(MSDOS) || defined(__STDC__) -+#undef NOPROTO -+#endif -+#ifndef NOPROTO -+char *des_options(void); -+void des_ecb3_encrypt(des_cblock *input,des_cblock *output, -+ des_key_schedule ks1,des_key_schedule ks2, -+ des_key_schedule ks3, int enc); -+DES_LONG des_cbc_cksum(des_cblock *input,des_cblock *output, -+ long length,des_key_schedule schedule,des_cblock *ivec); -+void des_cbc_encrypt(des_cblock *input,des_cblock *output,long length, -+ des_key_schedule schedule,des_cblock *ivec,int enc); -+void des_ncbc_encrypt(des_cblock *input,des_cblock *output,long length, -+ des_key_schedule schedule,des_cblock *ivec,int enc); -+void des_xcbc_encrypt(des_cblock *input,des_cblock *output,long length, -+ des_key_schedule schedule,des_cblock *ivec, -+ des_cblock *inw,des_cblock *outw,int enc); -+void des_cfb_encrypt(unsigned char *in,unsigned char *out,int numbits, -+ long length,des_key_schedule schedule,des_cblock *ivec,int enc); -+void des_ecb_encrypt(des_cblock *input,des_cblock *output, -+ des_key_schedule ks,int enc); -+void des_encrypt(DES_LONG *data,des_key_schedule ks, int enc); -+void des_encrypt2(DES_LONG *data,des_key_schedule ks, int enc); -+void des_encrypt3(DES_LONG *data, des_key_schedule ks1, -+ des_key_schedule ks2, des_key_schedule ks3); -+void des_decrypt3(DES_LONG *data, des_key_schedule ks1, -+ des_key_schedule ks2, des_key_schedule ks3); -+void des_ede3_cbc_encrypt(des_cblock *input, des_cblock *output, -+ long length, des_key_schedule ks1, des_key_schedule ks2, -+ des_key_schedule ks3, des_cblock *ivec, int enc); -+void des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out, -+ long length, des_key_schedule ks1, des_key_schedule ks2, -+ des_key_schedule ks3, des_cblock *ivec, int *num, int enc); -+void des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out, -+ long length, des_key_schedule ks1, des_key_schedule ks2, -+ des_key_schedule ks3, des_cblock *ivec, int *num); -+ -+void des_xwhite_in2out(des_cblock (*des_key), des_cblock (*in_white), -+ des_cblock (*out_white)); -+ -+int des_enc_read(int fd,char *buf,int len,des_key_schedule sched, -+ des_cblock *iv); -+int des_enc_write(int fd,char *buf,int len,des_key_schedule sched, -+ des_cblock *iv); -+char *des_fcrypt(const char *buf,const char *salt, char *ret); -+#ifdef PERL5 -+char *des_crypt(const char *buf,const char *salt); -+#else -+/* some stupid compilers complain because I have declared char instead -+ * of const char */ -+#ifndef __KERNEL__ -+#ifdef HEADER_DES_LOCL_H -+char *crypt(const char *buf,const char *salt); -+#else /* HEADER_DES_LOCL_H */ -+char *crypt(void); -+#endif /* HEADER_DES_LOCL_H */ -+#endif /* __KERNEL__ */ -+#endif /* PERL5 */ -+void des_ofb_encrypt(unsigned char *in,unsigned char *out, -+ int numbits,long length,des_key_schedule schedule,des_cblock *ivec); -+void des_pcbc_encrypt(des_cblock *input,des_cblock *output,long length, -+ des_key_schedule schedule,des_cblock *ivec,int enc); -+DES_LONG des_quad_cksum(des_cblock *input,des_cblock *output, -+ long length,int out_count,des_cblock *seed); -+void des_random_seed(des_cblock key); -+void des_random_key(des_cblock ret); -+int des_read_password(des_cblock *key,char *prompt,int verify); -+int des_read_2passwords(des_cblock *key1,des_cblock *key2, -+ char *prompt,int verify); -+int des_read_pw_string(char *buf,int length,char *prompt,int verify); -+void des_set_odd_parity(des_cblock *key); -+int des_is_weak_key(des_cblock *key); -+int des_set_key(des_cblock *key,des_key_schedule schedule); -+int des_key_sched(des_cblock *key,des_key_schedule schedule); -+void des_string_to_key(char *str,des_cblock *key); -+void des_string_to_2keys(char *str,des_cblock *key1,des_cblock *key2); -+void des_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, -+ des_key_schedule schedule, des_cblock *ivec, int *num, int enc); -+void des_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, -+ des_key_schedule schedule, des_cblock *ivec, int *num); -+int des_read_pw(char *buf, char *buff, int size, char *prompt, int verify); -+ -+/* Extra functions from Mark Murray */ -+/* The following functions are not in the normal unix build or the -+ * SSLeay build. When using the SSLeay build, use RAND_seed() -+ * and RAND_bytes() instead. */ -+int des_new_random_key(des_cblock *key); -+void des_init_random_number_generator(des_cblock *key); -+void des_set_random_generator_seed(des_cblock *key); -+void des_set_sequence_number(des_cblock new_sequence_number); -+void des_generate_random_block(des_cblock *block); -+ -+#else -+ -+char *des_options(); -+void des_ecb3_encrypt(); -+DES_LONG des_cbc_cksum(); -+void des_cbc_encrypt(); -+void des_ncbc_encrypt(); -+void des_xcbc_encrypt(); -+void des_cfb_encrypt(); -+void des_ede3_cfb64_encrypt(); -+void des_ede3_ofb64_encrypt(); -+void des_ecb_encrypt(); -+void des_encrypt(); -+void des_encrypt2(); -+void des_encrypt3(); -+void des_decrypt3(); -+void des_ede3_cbc_encrypt(); -+int des_enc_read(); -+int des_enc_write(); -+char *des_fcrypt(); -+#ifdef PERL5 -+char *des_crypt(); -+#else -+char *crypt(); -+#endif -+void des_ofb_encrypt(); -+void des_pcbc_encrypt(); -+DES_LONG des_quad_cksum(); -+void des_random_seed(); -+void des_random_key(); -+int des_read_password(); -+int des_read_2passwords(); -+int des_read_pw_string(); -+void des_set_odd_parity(); -+int des_is_weak_key(); -+int des_set_key(); -+int des_key_sched(); -+void des_string_to_key(); -+void des_string_to_2keys(); -+void des_cfb64_encrypt(); -+void des_ofb64_encrypt(); -+int des_read_pw(); -+void des_xwhite_in2out(); -+ -+/* Extra functions from Mark Murray */ -+/* The following functions are not in the normal unix build or the -+ * SSLeay build. When using the SSLeay build, use RAND_seed() -+ * and RAND_bytes() instead. */ -+#ifdef FreeBSD -+int des_new_random_key(); -+void des_init_random_number_generator(); -+void des_set_random_generator_seed(); -+void des_set_sequence_number(); -+void des_generate_random_block(); -+#endif -+ -+#endif -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/mast.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,33 @@ -+struct mast_callbacks { -+ int (*packet_encap)(struct device *mast, void *context, -+ struct sk_buff *skb, int flowref); -+ int (*link_inquire)(struct device *mast, void *context); -+}; -+ -+ -+struct device *mast_init (int family, -+ struct mast_callbacks *callbacks, -+ unsigned int flags, -+ unsigned int desired_unit, -+ unsigned int max_flowref, -+ void *context); -+ -+int mast_destroy(struct device *mast); -+ -+int mast_recv(struct device *mast, struct sk_buff *skb, int flowref); -+ -+/* free this skb as being useless, increment failure count. */ -+int mast_toast(struct device *mast, struct sk_buff *skb, int flowref); -+ -+int mast_linkstat (struct device *mast, int flowref, -+ int status); -+ -+int mast_setreference (struct device *mast, -+ int defaultSA); -+ -+int mast_setneighbor (struct device *mast, -+ struct sockaddr *source, -+ struct sockaddr *destination, -+ int flowref); -+ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,513 @@ -+#ifndef _OPENSWAN_H -+/* -+ * header file for FreeS/WAN library functions -+ * Copyright (C) 1998, 1999, 2000 Henry Spencer. -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#define _OPENSWAN_H /* seen it, no need to see it again */ -+ -+ -+ -+/* -+ * We've just got to have some datatypes defined... And annoyingly, just -+ * where we get them depends on whether we're in userland or not. -+ */ -+/* things that need to come from one place or the other, depending */ -+#ifdef __KERNEL__ -+#include -+#include -+#include -+#include -+#include -+#define assert(foo) /* nothing */ -+#else -+#include -+#include -+#include -+#include -+#include -+#include -+ -+# define uint8_t u_int8_t -+# define uint16_t u_int16_t -+# define uint32_t u_int32_t -+# define uint64_t u_int64_t -+ -+ -+# define DEBUG_NO_STATIC static -+ -+#endif -+ -+#include -+ -+ -+/* -+ * Grab the kernel version to see if we have NET_21, and therefore -+ * IPv6. Some of this is repeated from ipsec_kversions.h. Of course, -+ * we aren't really testing if the kernel has IPv6, but rather if the -+ * the include files do. -+ */ -+#include -+#ifndef KERNEL_VERSION -+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) -+#define NET_21 -+#endif -+ -+#ifndef IPPROTO_COMP -+# define IPPROTO_COMP 108 -+#endif /* !IPPROTO_COMP */ -+ -+#ifndef IPPROTO_INT -+# define IPPROTO_INT 61 -+#endif /* !IPPROTO_INT */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+#ifndef DEBUG_NO_STATIC -+# define DEBUG_NO_STATIC -+#endif -+#else /* CONFIG_IPSEC_DEBUG */ -+#ifndef DEBUG_NO_STATIC -+# define DEBUG_NO_STATIC static -+#endif -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL /* KERNEL ifdef */ -+#ifndef NAT_TRAVERSAL -+#define NAT_TRAVERSAL -+#endif -+#endif -+#ifdef NAT_TRAVERSAL -+#define ESPINUDP_WITH_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ -+#define ESPINUDP_WITH_NON_ESP 2 /* draft-ietf-ipsec-nat-t-ike-02 */ -+#endif -+ -+/* -+ * Basic data types for the address-handling functions. -+ * ip_address and ip_subnet are supposed to be opaque types; do not -+ * use their definitions directly, they are subject to change! -+ */ -+ -+/* first, some quick fakes in case we're on an old system with no IPv6 */ -+#ifndef s6_addr16 -+struct in6_addr { -+ union -+ { -+ __u8 u6_addr8[16]; -+ __u16 u6_addr16[8]; -+ __u32 u6_addr32[4]; -+ } in6_u; -+#define s6_addr in6_u.u6_addr8 -+#define s6_addr16 in6_u.u6_addr16 -+#define s6_addr32 in6_u.u6_addr32 -+}; -+struct sockaddr_in6 { -+ unsigned short int sin6_family; /* AF_INET6 */ -+ __u16 sin6_port; /* Transport layer port # */ -+ __u32 sin6_flowinfo; /* IPv6 flow information */ -+ struct in6_addr sin6_addr; /* IPv6 address */ -+ __u32 sin6_scope_id; /* scope id (new in RFC2553) */ -+}; -+#endif /* !s6_addr16 */ -+ -+/* then the main types */ -+typedef struct { -+ union { -+ struct sockaddr_in v4; -+ struct sockaddr_in6 v6; -+ } u; -+} ip_address; -+typedef struct { -+ ip_address addr; -+ int maskbits; -+} ip_subnet; -+ -+/* and the SA ID stuff */ -+#ifdef __KERNEL__ -+typedef __u32 ipsec_spi_t; -+#else -+typedef u_int32_t ipsec_spi_t; -+#endif -+typedef struct { /* to identify an SA, we need: */ -+ ip_address dst; /* A. destination host */ -+ ipsec_spi_t spi; /* B. 32-bit SPI, assigned by dest. host */ -+# define SPI_PASS 256 /* magic values... */ -+# define SPI_DROP 257 /* ...for use... */ -+# define SPI_REJECT 258 /* ...with SA_INT */ -+# define SPI_HOLD 259 -+# define SPI_TRAP 260 -+# define SPI_TRAPSUBNET 261 -+ int proto; /* C. protocol */ -+# define SA_ESP 50 /* IPPROTO_ESP */ -+# define SA_AH 51 /* IPPROTO_AH */ -+# define SA_IPIP 4 /* IPPROTO_IPIP */ -+# define SA_COMP 108 /* IPPROTO_COMP */ -+# define SA_INT 61 /* IANA reserved for internal use */ -+} ip_said; -+ -+/* misc */ -+typedef const char *err_t; /* error message, or NULL for success */ -+struct prng { /* pseudo-random-number-generator guts */ -+ unsigned char sbox[256]; -+ int i, j; -+ unsigned long count; -+}; -+ -+ -+/* -+ * definitions for user space, taken from freeswan/ipsec_sa.h -+ */ -+typedef uint32_t IPsecSAref_t; -+ -+#define IPSEC_SA_REF_FIELD_WIDTH (8 * sizeof(IPsecSAref_t)) -+ -+#define IPsecSAref2NFmark(x) ((x) << (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH)) -+#define NFmark2IPsecSAref(x) ((x) >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH)) -+ -+#define IPSEC_SAREF_NULL (~((IPsecSAref_t)0)) -+ -+/* GCC magic for use in function definitions! */ -+#ifdef GCC_LINT -+# define PRINTF_LIKE(n) __attribute__ ((format(printf, n, n+1))) -+# define NEVER_RETURNS __attribute__ ((noreturn)) -+# define UNUSED __attribute__ ((unused)) -+# define BLANK_FORMAT " " /* GCC_LINT whines about empty formats */ -+#else -+# define PRINTF_LIKE(n) /* ignore */ -+# define NEVER_RETURNS /* ignore */ -+# define UNUSED /* ignore */ -+# define BLANK_FORMAT "" -+#endif -+ -+ -+ -+ -+ -+/* -+ * new IPv6-compatible functions -+ */ -+ -+/* text conversions */ -+err_t ttoul(const char *src, size_t srclen, int format, unsigned long *dst); -+size_t ultot(unsigned long src, int format, char *buf, size_t buflen); -+#define ULTOT_BUF (22+1) /* holds 64 bits in octal */ -+err_t ttoaddr(const char *src, size_t srclen, int af, ip_address *dst); -+err_t tnatoaddr(const char *src, size_t srclen, int af, ip_address *dst); -+size_t addrtot(const ip_address *src, int format, char *buf, size_t buflen); -+/* RFC 1886 old IPv6 reverse-lookup format is the bulkiest */ -+#define ADDRTOT_BUF (32*2 + 3 + 1 + 3 + 1 + 1) -+err_t ttosubnet(const char *src, size_t srclen, int af, ip_subnet *dst); -+size_t subnettot(const ip_subnet *src, int format, char *buf, size_t buflen); -+#define SUBNETTOT_BUF (ADDRTOT_BUF + 1 + 3) -+size_t subnetporttot(const ip_subnet *src, int format, char *buf, size_t buflen); -+#define SUBNETPROTOTOT_BUF (SUBNETTOTO_BUF + ULTOT_BUF) -+err_t ttosa(const char *src, size_t srclen, ip_said *dst); -+size_t satot(const ip_said *src, int format, char *bufptr, size_t buflen); -+#define SATOT_BUF (5 + ULTOA_BUF + 1 + ADDRTOT_BUF) -+err_t ttodata(const char *src, size_t srclen, int base, char *buf, -+ size_t buflen, size_t *needed); -+err_t ttodatav(const char *src, size_t srclen, int base, -+ char *buf, size_t buflen, size_t *needed, -+ char *errp, size_t errlen, unsigned int flags); -+#define TTODATAV_BUF 40 /* ttodatav's largest non-literal message */ -+#define TTODATAV_IGNORESPACE (1<<1) /* ignore spaces in base64 encodings*/ -+#define TTODATAV_SPACECOUNTS 0 /* do not ignore spaces in base64 */ -+ -+size_t datatot(const char *src, size_t srclen, int format, char *buf, -+ size_t buflen); -+size_t keyblobtoid(const unsigned char *src, size_t srclen, char *dst, -+ size_t dstlen); -+size_t splitkeytoid(const unsigned char *e, size_t elen, const unsigned char *m, -+ size_t mlen, char *dst, size_t dstlen); -+#define KEYID_BUF 10 /* up to 9 text digits plus NUL */ -+err_t ttoprotoport(char *src, size_t src_len, u_int8_t *proto, u_int16_t *port, -+ int *has_port_wildcard); -+ -+/* initializations */ -+void initsaid(const ip_address *addr, ipsec_spi_t spi, int proto, ip_said *dst); -+err_t loopbackaddr(int af, ip_address *dst); -+err_t unspecaddr(int af, ip_address *dst); -+err_t anyaddr(int af, ip_address *dst); -+err_t initaddr(const unsigned char *src, size_t srclen, int af, ip_address *dst); -+err_t initsubnet(const ip_address *addr, int maskbits, int clash, ip_subnet *dst); -+err_t addrtosubnet(const ip_address *addr, ip_subnet *dst); -+ -+/* misc. conversions and related */ -+err_t rangetosubnet(const ip_address *from, const ip_address *to, ip_subnet *dst); -+int addrtypeof(const ip_address *src); -+int subnettypeof(const ip_subnet *src); -+size_t addrlenof(const ip_address *src); -+size_t addrbytesptr(const ip_address *src, const unsigned char **dst); -+size_t addrbytesof(const ip_address *src, unsigned char *dst, size_t dstlen); -+int masktocount(const ip_address *src); -+void networkof(const ip_subnet *src, ip_address *dst); -+void maskof(const ip_subnet *src, ip_address *dst); -+ -+/* tests */ -+int sameaddr(const ip_address *a, const ip_address *b); -+int addrcmp(const ip_address *a, const ip_address *b); -+int samesubnet(const ip_subnet *a, const ip_subnet *b); -+int addrinsubnet(const ip_address *a, const ip_subnet *s); -+int subnetinsubnet(const ip_subnet *a, const ip_subnet *b); -+int subnetishost(const ip_subnet *s); -+int samesaid(const ip_said *a, const ip_said *b); -+int sameaddrtype(const ip_address *a, const ip_address *b); -+int samesubnettype(const ip_subnet *a, const ip_subnet *b); -+int isanyaddr(const ip_address *src); -+int isunspecaddr(const ip_address *src); -+int isloopbackaddr(const ip_address *src); -+ -+/* low-level grot */ -+int portof(const ip_address *src); -+void setportof(int port, ip_address *dst); -+struct sockaddr *sockaddrof(ip_address *src); -+size_t sockaddrlenof(const ip_address *src); -+ -+/* PRNG */ -+void prng_init(struct prng *prng, const unsigned char *key, size_t keylen); -+void prng_bytes(struct prng *prng, unsigned char *dst, size_t dstlen); -+unsigned long prng_count(struct prng *prng); -+void prng_final(struct prng *prng); -+ -+/* odds and ends */ -+const char *ipsec_version_code(void); -+const char *ipsec_version_string(void); -+const char **ipsec_copyright_notice(void); -+ -+const char *dns_string_rr(int rr, char *buf, int bufsize); -+const char *dns_string_datetime(time_t seconds, -+ char *buf, -+ int bufsize); -+ -+ -+/* -+ * old functions, to be deleted eventually -+ */ -+ -+/* unsigned long */ -+const char * /* NULL for success, else string literal */ -+atoul( -+ const char *src, -+ size_t srclen, /* 0 means strlen(src) */ -+ int base, /* 0 means figure it out */ -+ unsigned long *resultp -+); -+size_t /* space needed for full conversion */ -+ultoa( -+ unsigned long n, -+ int base, -+ char *dst, -+ size_t dstlen -+); -+#define ULTOA_BUF 21 /* just large enough for largest result, */ -+ /* assuming 64-bit unsigned long! */ -+ -+/* Internet addresses */ -+const char * /* NULL for success, else string literal */ -+atoaddr( -+ const char *src, -+ size_t srclen, /* 0 means strlen(src) */ -+ struct in_addr *addr -+); -+size_t /* space needed for full conversion */ -+addrtoa( -+ struct in_addr addr, -+ int format, /* character; 0 means default */ -+ char *dst, -+ size_t dstlen -+); -+#define ADDRTOA_BUF 16 /* just large enough for largest result */ -+ -+/* subnets */ -+const char * /* NULL for success, else string literal */ -+atosubnet( -+ const char *src, -+ size_t srclen, /* 0 means strlen(src) */ -+ struct in_addr *addr, -+ struct in_addr *mask -+); -+size_t /* space needed for full conversion */ -+subnettoa( -+ struct in_addr addr, -+ struct in_addr mask, -+ int format, /* character; 0 means default */ -+ char *dst, -+ size_t dstlen -+); -+#define SUBNETTOA_BUF 32 /* large enough for worst case result */ -+ -+/* ranges */ -+const char * /* NULL for success, else string literal */ -+atoasr( -+ const char *src, -+ size_t srclen, /* 0 means strlen(src) */ -+ char *type, /* 'a', 's', 'r' */ -+ struct in_addr *addrs /* two-element array */ -+); -+size_t /* space needed for full conversion */ -+rangetoa( -+ struct in_addr *addrs, /* two-element array */ -+ int format, /* character; 0 means default */ -+ char *dst, -+ size_t dstlen -+); -+#define RANGETOA_BUF 34 /* large enough for worst case result */ -+ -+/* data types for SA conversion functions */ -+ -+/* generic data, e.g. keys */ -+const char * /* NULL for success, else string literal */ -+atobytes( -+ const char *src, -+ size_t srclen, /* 0 means strlen(src) */ -+ char *dst, -+ size_t dstlen, -+ size_t *lenp /* NULL means don't bother telling me */ -+); -+size_t /* 0 failure, else true size */ -+bytestoa( -+ const char *src, -+ size_t srclen, -+ int format, /* character; 0 means default */ -+ char *dst, -+ size_t dstlen -+); -+ -+/* old versions of generic-data functions; deprecated */ -+size_t /* 0 failure, else true size */ -+atodata( -+ const char *src, -+ size_t srclen, /* 0 means strlen(src) */ -+ char *dst, -+ size_t dstlen -+); -+size_t /* 0 failure, else true size */ -+datatoa( -+ const char *src, -+ size_t srclen, -+ int format, /* character; 0 means default */ -+ char *dst, -+ size_t dstlen -+); -+ -+/* part extraction and special addresses */ -+struct in_addr -+subnetof( -+ struct in_addr addr, -+ struct in_addr mask -+); -+struct in_addr -+hostof( -+ struct in_addr addr, -+ struct in_addr mask -+); -+struct in_addr -+broadcastof( -+ struct in_addr addr, -+ struct in_addr mask -+); -+ -+/* mask handling */ -+int -+goodmask( -+ struct in_addr mask -+); -+int -+masktobits( -+ struct in_addr mask -+); -+struct in_addr -+bitstomask( -+ int n -+); -+ -+ -+ -+/* -+ * general utilities -+ */ -+ -+#ifndef __KERNEL__ -+/* option pickup from files (userland only because of use of FILE) */ -+const char *optionsfrom(const char *filename, int *argcp, char ***argvp, -+ int optind, FILE *errorreport); -+ -+/* sanitize a string */ -+extern size_t sanitize_string(char *buf, size_t size); -+ -+#endif -+ -+ -+/* -+ * ENUM of klips debugging values. Not currently used in klips. -+ * debug flag is actually 32 -bits, but only one bit is ever used, -+ * so we can actually pack it all into a single 32-bit word. -+ */ -+enum klips_debug_flags { -+ KDF_VERBOSE = 0, -+ KDF_XMIT = 1, -+ KDF_NETLINK = 2, /* obsolete */ -+ KDF_XFORM = 3, -+ KDF_EROUTE = 4, -+ KDF_SPI = 5, -+ KDF_RADIJ = 6, -+ KDF_ESP = 7, -+ KDF_AH = 8, /* obsolete */ -+ KDF_RCV = 9, -+ KDF_TUNNEL = 10, -+ KDF_PFKEY = 11, -+ KDF_COMP = 12 -+}; -+ -+ -+/* -+ * Debugging levels for pfkey_lib_debug -+ */ -+#define PF_KEY_DEBUG_PARSE_NONE 0 -+#define PF_KEY_DEBUG_PARSE_PROBLEM 1 -+#define PF_KEY_DEBUG_PARSE_STRUCT 2 -+#define PF_KEY_DEBUG_PARSE_FLOW 4 -+#define PF_KEY_DEBUG_BUILD 8 -+#define PF_KEY_DEBUG_PARSE_MAX 15 -+ -+extern unsigned int pfkey_lib_debug; /* bits selecting what to report */ -+ -+/* -+ * pluto and lwdnsq need to know the maximum size of the commands to, -+ * and replies from lwdnsq. -+ */ -+ -+#define LWDNSQ_CMDBUF_LEN 1024 -+#define LWDNSQ_RESULT_LEN_MAX 4096 -+ -+ -+/* syntax for passthrough SA */ -+#ifndef PASSTHROUGHNAME -+#define PASSTHROUGHNAME "%passthrough" -+#define PASSTHROUGH4NAME "%passthrough4" -+#define PASSTHROUGH6NAME "%passthrough6" -+#define PASSTHROUGHIS "tun0@0.0.0.0" -+#define PASSTHROUGH4IS "tun0@0.0.0.0" -+#define PASSTHROUGH6IS "tun0@::" -+#define PASSTHROUGHTYPE "tun" -+#define PASSTHROUGHSPI 0 -+#define PASSTHROUGHDST 0 -+#endif -+ -+ -+ -+#endif /* _OPENSWAN_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipcomp.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,61 @@ -+/* -+ * IPCOMP zlib interface code. -+ * Copyright (C) 2000 Svenning Soerensen -+ * Copyright (C) 2000, 2001 Richard Guy Briggs -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ -+ RCSID $Id$ -+ -+ */ -+ -+/* SSS */ -+ -+#ifndef _IPCOMP_H -+#define _IPCOMP_H -+ -+/* Prefix all global deflate symbols with "ipcomp_" to avoid collisions with ppp_deflate & ext2comp */ -+#ifndef IPCOMP_PREFIX -+#define IPCOMP_PREFIX -+#endif /* IPCOMP_PREFIX */ -+ -+#ifndef IPPROTO_COMP -+#define IPPROTO_COMP 108 -+#endif /* IPPROTO_COMP */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int sysctl_ipsec_debug_ipcomp; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+struct ipcomphdr { /* IPCOMP header */ -+ __u8 ipcomp_nh; /* Next header (protocol) */ -+ __u8 ipcomp_flags; /* Reserved, must be 0 */ -+ __u16 ipcomp_cpi; /* Compression Parameter Index */ -+}; -+ -+extern struct inet_protocol comp_protocol; -+extern int sysctl_ipsec_debug_ipcomp; -+ -+#define IPCOMP_UNCOMPRESSABLE 0x000000001 -+#define IPCOMP_COMPRESSIONERROR 0x000000002 -+#define IPCOMP_PARMERROR 0x000000004 -+#define IPCOMP_DECOMPRESSIONERROR 0x000000008 -+ -+#define IPCOMP_ADAPT_INITIAL_TRIES 8 -+#define IPCOMP_ADAPT_INITIAL_SKIP 4 -+#define IPCOMP_ADAPT_SUBSEQ_TRIES 2 -+#define IPCOMP_ADAPT_SUBSEQ_SKIP 8 -+ -+/* Function prototypes */ -+struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); -+struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); -+ -+#endif /* _IPCOMP_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_ah.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,190 @@ -+/* -+ * Authentication Header declarations -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#include "ipsec_md5h.h" -+#include "ipsec_sha1.h" -+ -+#ifndef IPPROTO_AH -+#define IPPROTO_AH 51 -+#endif /* IPPROTO_AH */ -+ -+#include "ipsec_auth.h" -+ -+#ifdef __KERNEL__ -+ -+extern struct inet_protocol ah_protocol; -+ -+struct options; -+ -+struct ahhdr /* Generic AH header */ -+{ -+ __u8 ah_nh; /* Next header (protocol) */ -+ __u8 ah_hl; /* AH length, in 32-bit words */ -+ __u16 ah_rv; /* reserved, must be 0 */ -+ __u32 ah_spi; /* Security Parameters Index */ -+ __u32 ah_rpl; /* Replay prevention */ -+ __u8 ah_data[AHHMAC_HASHLEN];/* Authentication hash */ -+}; -+#define AH_BASIC_LEN 8 /* basic AH header is 8 bytes, nh,hl,rv,spi -+ * and the ah_hl, says how many bytes after that -+ * to cover. */ -+ -+extern struct xform_functions ah_xform_funcs[]; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int debug_ah; -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif /* __KERNEL__ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.23 2004/04/05 19:55:04 mcr -+ * Moved from linux/include/freeswan/ipsec_ah.h,v -+ * -+ * Revision 1.22 2004/04/05 19:41:05 mcr -+ * merged alg-branch code. -+ * -+ * Revision 1.21 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.22 2003/12/11 20:14:58 mcr -+ * refactored the xmit code, to move all encapsulation -+ * code into protocol functions. Note that all functions -+ * are essentially done by a single function, which is probably -+ * wrong. -+ * the rcv_functions structures are renamed xform_functions. -+ * -+ * Revision 1.21 2003/12/06 21:21:19 mcr -+ * split up receive path into per-transform files, for -+ * easier later removal. -+ * -+ * Revision 1.20.8.1 2003/12/22 15:25:52 jjo -+ * Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.20 2003/02/06 02:21:34 rgb -+ * -+ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h . -+ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr". -+ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code. -+ * -+ * Revision 1.19 2002/09/16 21:19:13 mcr -+ * fixes for west-ah-icmp-01 - length of AH header must be -+ * calculated properly, and next_header field properly copied. -+ * -+ * Revision 1.18 2002/05/14 02:37:02 rgb -+ * Change reference from _TDB to _IPSA. -+ * -+ * Revision 1.17 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_ah.h,v -+ * -+ * Revision 1.16 2002/02/20 01:27:06 rgb -+ * Ditched a pile of structs only used by the old Netlink interface. -+ * -+ * Revision 1.15 2001/12/11 02:35:57 rgb -+ * Change "struct net_device" to "struct device" for 2.2 compatibility. -+ * -+ * Revision 1.14 2001/11/26 09:23:47 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.13.2.1 2001/09/25 02:18:24 mcr -+ * replace "struct device" with "struct netdevice" -+ * -+ * Revision 1.13 2001/06/14 19:35:08 rgb -+ * Update copyright date. -+ * -+ * Revision 1.12 2000/09/12 03:21:20 rgb -+ * Cleared out unused htonq. -+ * -+ * Revision 1.11 2000/09/08 19:12:55 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.10 2000/01/21 06:13:10 rgb -+ * Tidied up spacing. -+ * Added macros for HMAC padding magic numbers.(kravietz) -+ * -+ * Revision 1.9 1999/12/07 18:16:23 rgb -+ * Fixed comments at end of #endif lines. -+ * -+ * Revision 1.8 1999/04/11 00:28:56 henry -+ * GPL boilerplate -+ * -+ * Revision 1.7 1999/04/06 04:54:25 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.6 1999/01/26 02:06:01 rgb -+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro. -+ * -+ * Revision 1.5 1999/01/22 06:17:49 rgb -+ * Updated macro comments. -+ * Added context types to support algorithm switch code. -+ * 64-bit clean-up -- converting 'u long long' to __u64. -+ * -+ * Revision 1.4 1998/07/14 15:54:56 rgb -+ * Add #ifdef __KERNEL__ to protect kernel-only structures. -+ * -+ * Revision 1.3 1998/06/30 18:05:16 rgb -+ * Comment out references to htonq. -+ * -+ * Revision 1.2 1998/06/25 19:33:46 rgb -+ * Add prototype for protocol receive function. -+ * Rearrange for more logical layout. -+ * -+ * Revision 1.1 1998/06/18 21:27:43 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.4 1998/05/18 22:28:43 rgb -+ * Disable key printing facilities from /proc/net/ipsec_*. -+ * -+ * Revision 1.3 1998/04/21 21:29:07 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.2 1998/04/12 22:03:17 rgb -+ * Updated ESP-3DES-HMAC-MD5-96, -+ * ESP-DES-HMAC-MD5-96, -+ * AH-HMAC-MD5-96, -+ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository -+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts. -+ * -+ * Fixed eroute references in /proc/net/ipsec*. -+ * -+ * Started to patch module unloading memory leaks in ipsec_netlink and -+ * radij tree unloading. -+ * -+ * Revision 1.1 1998/04/09 03:05:55 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:02 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * Added definitions for new AH transforms. -+ * -+ * Revision 0.3 1996/11/20 14:35:48 ji -+ * Minor Cleanup. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_alg.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,260 @@ -+/* -+ * Modular extensions service and registration functions interface -+ * -+ * Author: JuanJo Ciarlante -+ * -+ * ipsec_alg.h,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp -+ * -+ */ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ */ -+#ifndef IPSEC_ALG_H -+#define IPSEC_ALG_H -+ -+/* -+ * gcc >= 3.2 has removed __FUNCTION__, replaced by C99 __func__ -+ * *BUT* its a compiler variable. -+ */ -+#if (__GNUC__ >= 3) -+#ifndef __FUNCTION__ -+#define __FUNCTION__ __func__ -+#endif -+#endif -+ -+/* Version 0.8.1-0 */ -+#define IPSEC_ALG_VERSION 0x00080100 -+ -+#include -+#include -+#include -+/* -+ * The following structs are used via pointers in ipsec_alg object to -+ * avoid ipsec_alg.h coupling with freeswan headers, thus simplifying -+ * module development -+ */ -+struct ipsec_sa; -+struct esp; -+ -+/************************************** -+ * -+ * Main registration object -+ * -+ *************************************/ -+#define IPSEC_ALG_VERSION_QUAD(v) \ -+ (v>>24),((v>>16)&0xff),((v>>8)&0xff),(v&0xff) -+/* -+ * Main ipsec_alg objects: "OOPrograming wannabe" -+ * Hierachy (carefully handled with _minimal_ cast'ing): -+ * -+ * ipsec_alg+ -+ * +->ipsec_alg_enc (ixt_alg_type=SADB_EXT_SUPPORTED_ENCRYPT) -+ * +->ipsec_alg_auth (ixt_alg_type=SADB_EXT_SUPPORTED_AUTH) -+ */ -+ -+/*************************************************************** -+ * -+ * INTERFACE object: struct ipsec_alg -+ * -+ ***************************************************************/ -+ -+/* -+ * common part for every struct ipsec_alg_* -+ * (sortof poor's man OOP) -+ */ -+#define IPSEC_ALG_STRUCT_COMMON \ -+ unsigned ixt_version; /* only allow this version (or 'near')*/ \ -+ struct list_head ixt_list; /* dlinked list */ \ -+ struct module *ixt_module; /* THIS_MODULE */ \ -+ unsigned ixt_state; /* state flags */ \ -+ atomic_t ixt_refcnt; /* ref. count when pointed from ipsec_sa */ \ -+ char ixt_name[16]; /* descriptive short name, eg. "3des" */ \ -+ void *ixt_data; /* private for algo implementation */ \ -+ uint8_t ixt_blocksize; /* blocksize in bytes */ \ -+ \ -+ /* THIS IS A COPY of struct supported (lib/pfkey.h) \ -+ * please keep in sync until we migrate 'supported' stuff \ -+ * to ipsec_alg \ -+ */ \ -+ uint16_t ixt_alg_type; /* correspond to IPSEC_ALG_{ENCRYPT,AUTH} */ \ -+ uint8_t ixt_alg_id; /* enc. alg. number, eg. ESP_3DES */ \ -+ uint8_t ixt_ivlen; /* ivlen in bits, expected to be multiple of 8! */ \ -+ uint16_t ixt_keyminbits;/* min. keybits (of entropy) */ \ -+ uint16_t ixt_keymaxbits;/* max. keybits (of entropy) */ -+ -+#define ixt_support ixt_alg_type -+ -+#define IPSEC_ALG_ST_SUPP 0x01 -+#define IPSEC_ALG_ST_REGISTERED 0x02 -+#define IPSEC_ALG_ST_EXCL 0x04 -+struct ipsec_alg { -+ IPSEC_ALG_STRUCT_COMMON -+}; -+/* -+ * Note the const in cbc_encrypt IV arg: -+ * some ciphers like to toast passed IV (eg. 3DES): make a local IV copy -+ */ -+struct ipsec_alg_enc { -+ IPSEC_ALG_STRUCT_COMMON -+ unsigned ixt_e_keylen; /* raw key length in bytes */ -+ unsigned ixt_e_ctx_size; /* sa_p->key_e_size */ -+ int (*ixt_e_set_key)(struct ipsec_alg_enc *alg, __u8 *key_e, const __u8 *key, size_t keysize); -+ __u8 *(*ixt_e_new_key)(struct ipsec_alg_enc *alg, const __u8 *key, size_t keysize); -+ void (*ixt_e_destroy_key)(struct ipsec_alg_enc *alg, __u8 *key_e); -+ int (*ixt_e_cbc_encrypt)(struct ipsec_alg_enc *alg, __u8 *key_e, __u8 *in, int ilen, const __u8 *iv, int encrypt); -+}; -+struct ipsec_alg_auth { -+ IPSEC_ALG_STRUCT_COMMON -+ unsigned ixt_a_keylen; /* raw key length in bytes */ -+ unsigned ixt_a_ctx_size; /* sa_p->key_a_size */ -+ unsigned ixt_a_authlen; /* 'natural' auth. hash len (bytes) */ -+ int (*ixt_a_hmac_set_key)(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *key, int keylen); -+ int (*ixt_a_hmac_hash)(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *dat, int len, __u8 *hash, int hashlen); -+}; -+/* -+ * These are _copies_ of SADB_EXT_SUPPORTED_{AUTH,ENCRYPT}, -+ * to avoid header coupling for true constants -+ * about headers ... "cp is your friend" --Linus -+ */ -+#define IPSEC_ALG_TYPE_AUTH 14 -+#define IPSEC_ALG_TYPE_ENCRYPT 15 -+ -+/*************************************************************** -+ * -+ * INTERFACE for module loading,testing, and unloading -+ * -+ ***************************************************************/ -+/* - registration calls */ -+int register_ipsec_alg(struct ipsec_alg *); -+int unregister_ipsec_alg(struct ipsec_alg *); -+/* - optional (simple test) for algos */ -+int ipsec_alg_test(unsigned alg_type, unsigned alg_id, int testparm); -+/* inline wrappers (usefull for type validation */ -+static inline int register_ipsec_alg_enc(struct ipsec_alg_enc *ixt) { -+ return register_ipsec_alg((struct ipsec_alg*)ixt); -+} -+static inline int unregister_ipsec_alg_enc(struct ipsec_alg_enc *ixt) { -+ return unregister_ipsec_alg((struct ipsec_alg*)ixt); -+} -+static inline int register_ipsec_alg_auth(struct ipsec_alg_auth *ixt) { -+ return register_ipsec_alg((struct ipsec_alg*)ixt); -+} -+static inline int unregister_ipsec_alg_auth(struct ipsec_alg_auth *ixt) { -+ return unregister_ipsec_alg((struct ipsec_alg*)ixt); -+} -+ -+/***************************************************************** -+ * -+ * INTERFACE for ENC services: key creation, encrypt function -+ * -+ *****************************************************************/ -+ -+#define IPSEC_ALG_ENCRYPT 1 -+#define IPSEC_ALG_DECRYPT 0 -+ -+/* encryption key context creation function */ -+int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p); -+/* -+ * ipsec_alg_esp_encrypt(): encrypt ilen bytes in idat returns -+ * 0 or ERR<0 -+ */ -+int ipsec_alg_esp_encrypt(struct ipsec_sa *sa_p, __u8 *idat, int ilen, const __u8 *iv, int action); -+ -+/*************************************************************** -+ * -+ * INTERFACE for AUTH services: key creation, hash functions -+ * -+ ***************************************************************/ -+int ipsec_alg_auth_key_create(struct ipsec_sa *sa_p); -+int ipsec_alg_sa_esp_hash(const struct ipsec_sa *sa_p, const __u8 *espp, int len, __u8 *hash, int hashlen) ; -+#define ipsec_alg_sa_esp_update(c,k,l) ipsec_alg_sa_esp_hash(c,k,l,NULL,0) -+ -+/* only called from ipsec_init.c */ -+int ipsec_alg_init(void); -+ -+/* algo module glue for static algos */ -+void ipsec_alg_static_init(void); -+typedef int (*ipsec_alg_init_func_t) (void); -+ -+/********************************************** -+ * -+ * INTERFACE for ipsec_sa init and wipe -+ * -+ **********************************************/ -+ -+/* returns true if ipsec_sa has ipsec_alg obj attached */ -+/* -+ * Initializes ipsec_sa's ipsec_alg object, using already loaded -+ * proto, authalg, encalg.; links ipsec_alg objects (enc, auth) -+ */ -+int ipsec_alg_sa_init(struct ipsec_sa *sa_p); -+/* -+ * Destroys ipsec_sa's ipsec_alg object -+ * unlinking ipsec_alg objects -+ */ -+int ipsec_alg_sa_wipe(struct ipsec_sa *sa_p); -+ -+#define IPSEC_ALG_MODULE_INIT_MOD( func_name ) \ -+ static int func_name(void); \ -+ module_init(func_name); \ -+ static int __init func_name(void) -+#define IPSEC_ALG_MODULE_EXIT_MOD( func_name ) \ -+ static void func_name(void); \ -+ module_exit(func_name); \ -+ static void __exit func_name(void) -+ -+#define IPSEC_ALG_MODULE_INIT_STATIC( func_name ) \ -+ extern int func_name(void); \ -+ int func_name(void) -+#define IPSEC_ALG_MODULE_EXIT_STATIC( func_name ) \ -+ extern void func_name(void); \ -+ void func_name(void) -+ -+/********************************************** -+ * -+ * 2.2 backport for some 2.4 useful module stuff -+ * -+ **********************************************/ -+#ifdef MODULE -+#ifndef THIS_MODULE -+#define THIS_MODULE (&__this_module) -+#endif -+#ifndef module_init -+typedef int (*__init_module_func_t)(void); -+typedef void (*__cleanup_module_func_t)(void); -+ -+#define module_init(x) \ -+ int init_module(void) __attribute__((alias(#x))); \ -+ static inline __init_module_func_t __init_module_inline(void) \ -+ { return x; } -+#define module_exit(x) \ -+ void cleanup_module(void) __attribute__((alias(#x))); \ -+ static inline __cleanup_module_func_t __cleanup_module_inline(void) \ -+ { return x; } -+#endif -+#define IPSEC_ALG_MODULE_INIT( func_name ) IPSEC_ALG_MODULE_INIT_MOD( func_name ) -+#define IPSEC_ALG_MODULE_EXIT( func_name ) IPSEC_ALG_MODULE_EXIT_MOD( func_name ) -+ -+#else /* not MODULE */ -+#ifndef THIS_MODULE -+#define THIS_MODULE NULL -+#endif -+/* -+ * I only want module_init() magic -+ * when algo.c file *is THE MODULE*, in all other -+ * cases, initialization is called explicitely from ipsec_alg_init() -+ */ -+#define IPSEC_ALG_MODULE_INIT( func_name ) IPSEC_ALG_MODULE_INIT_STATIC(func_name) -+#define IPSEC_ALG_MODULE_EXIT( func_name ) IPSEC_ALG_MODULE_EXIT_STATIC(func_name) -+#endif -+ -+#endif /* IPSEC_ALG_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_auth.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,100 @@ -+/* -+ * Authentication Header declarations -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#include "ipsec_md5h.h" -+#include "ipsec_sha1.h" -+ -+#ifndef IPSEC_AUTH_H -+#define IPSEC_AUTH_H -+ -+#define AH_FLENGTH 12 /* size of fixed part */ -+#define AHMD5_KMAX 64 /* MD5 max 512 bits key */ -+#define AHMD5_AMAX 12 /* MD5 96 bits of authenticator */ -+ -+#define AHMD596_KLEN 16 /* MD5 128 bits key */ -+#define AHSHA196_KLEN 20 /* SHA1 160 bits key */ -+ -+#define AHMD596_ALEN 16 /* MD5 128 bits authentication length */ -+#define AHSHA196_ALEN 20 /* SHA1 160 bits authentication length */ -+ -+#define AHMD596_BLKLEN 64 /* MD5 block length */ -+#define AHSHA196_BLKLEN 64 /* SHA1 block length */ -+#define AHSHA2_256_BLKLEN 64 /* SHA2-256 block length */ -+#define AHSHA2_384_BLKLEN 128 /* SHA2-384 block length (?) */ -+#define AHSHA2_512_BLKLEN 128 /* SHA2-512 block length */ -+ -+#define AH_BLKLEN_MAX 128 /* keep up to date! */ -+ -+ -+#define AH_AMAX AHSHA196_ALEN /* keep up to date! */ -+#define AHHMAC_HASHLEN 12 /* authenticator length of 96bits */ -+#define AHHMAC_RPLLEN 4 /* 32 bit replay counter */ -+ -+#define DB_AH_PKTRX 0x0001 -+#define DB_AH_PKTRX2 0x0002 -+#define DB_AH_DMP 0x0004 -+#define DB_AH_IPSA 0x0010 -+#define DB_AH_XF 0x0020 -+#define DB_AH_INAU 0x0040 -+#define DB_AH_REPLAY 0x0100 -+ -+#ifdef __KERNEL__ -+ -+/* General HMAC algorithm is described in RFC 2104 */ -+ -+#define HMAC_IPAD 0x36 -+#define HMAC_OPAD 0x5C -+ -+struct md5_ctx { -+ MD5_CTX ictx; /* context after H(K XOR ipad) */ -+ MD5_CTX octx; /* context after H(K XOR opad) */ -+}; -+ -+struct sha1_ctx { -+ SHA1_CTX ictx; /* context after H(K XOR ipad) */ -+ SHA1_CTX octx; /* context after H(K XOR opad) */ -+}; -+ -+struct auth_alg { -+ void (*init)(void *ctx); -+ void (*update)(void *ctx, unsigned char *bytes, __u32 len); -+ void (*final)(unsigned char *hash, void *ctx); -+ int hashlen; -+}; -+ -+struct options; -+ -+#endif /* __KERNEL__ */ -+#endif /* IPSEC_AUTH_H */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.3 2004/04/06 02:49:08 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.2 2004/04/05 19:55:04 mcr -+ * Moved from linux/include/freeswan/ipsec_auth.h,v -+ * -+ * Revision 1.1 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.1 2003/12/06 21:21:19 mcr -+ * split up receive path into per-transform files, for -+ * easier later removal. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_encap.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,149 @@ -+/* -+ * declarations relevant to encapsulation-like operations -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef _IPSEC_ENCAP_H_ -+ -+#define SENT_IP4 16 /* data is two struct in_addr + proto + ports*/ -+ /* (2 * sizeof(struct in_addr)) */ -+ /* sizeof(struct sockaddr_encap) -+ - offsetof(struct sockaddr_encap, Sen.Sip4.Src) */ -+ -+struct sockaddr_encap -+{ -+ __u8 sen_len; /* length */ -+ __u8 sen_family; /* AF_ENCAP */ -+ __u16 sen_type; /* see SENT_* */ -+ union -+ { -+ struct /* SENT_IP4 */ -+ { -+ struct in_addr Src; -+ struct in_addr Dst; -+ __u8 Proto; -+ __u16 Sport; -+ __u16 Dport; -+ } Sip4; -+ } Sen; -+}; -+ -+#define sen_ip_src Sen.Sip4.Src -+#define sen_ip_dst Sen.Sip4.Dst -+#define sen_proto Sen.Sip4.Proto -+#define sen_sport Sen.Sip4.Sport -+#define sen_dport Sen.Sip4.Dport -+ -+#ifndef AF_ENCAP -+#define AF_ENCAP 26 -+#endif /* AF_ENCAP */ -+ -+#define _IPSEC_ENCAP_H_ -+#endif /* _IPSEC_ENCAP_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.19 2004/04/05 19:55:04 mcr -+ * Moved from linux/include/freeswan/ipsec_encap.h,v -+ * -+ * Revision 1.18 2003/10/31 02:27:05 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.17.30.1 2003/09/21 13:59:38 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.17 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_encap.h,v -+ * -+ * Revision 1.16 2001/11/26 09:23:47 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.15.2.1 2001/09/25 02:18:54 mcr -+ * struct eroute moved to ipsec_eroute.h -+ * -+ * Revision 1.15 2001/09/14 16:58:36 rgb -+ * Added support for storing the first and last packets through a HOLD. -+ * -+ * Revision 1.14 2001/09/08 21:13:31 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.13 2001/06/14 19:35:08 rgb -+ * Update copyright date. -+ * -+ * Revision 1.12 2001/05/27 06:12:10 rgb -+ * Added structures for pid, packet count and last access time to eroute. -+ * Added packet count to beginning of /proc/net/ipsec_eroute. -+ * -+ * Revision 1.11 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.10 2000/03/22 16:15:36 rgb -+ * Fixed renaming of dev_get (MB). -+ * -+ * Revision 1.9 2000/01/21 06:13:26 rgb -+ * Added a macro for AF_ENCAP -+ * -+ * Revision 1.8 1999/12/31 14:56:55 rgb -+ * MB fix for 2.3 dev-use-count. -+ * -+ * Revision 1.7 1999/11/18 04:09:18 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.6 1999/09/24 00:34:13 rgb -+ * Add Marc Boucher's support for 2.3.xx+. -+ * -+ * Revision 1.5 1999/04/11 00:28:57 henry -+ * GPL boilerplate -+ * -+ * Revision 1.4 1999/04/06 04:54:25 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.3 1998/10/19 14:44:28 rgb -+ * Added inclusion of freeswan.h. -+ * sa_id structure implemented and used: now includes protocol. -+ * -+ * Revision 1.2 1998/07/14 18:19:33 rgb -+ * Added #ifdef __KERNEL__ directives to restrict scope of header. -+ * -+ * Revision 1.1 1998/06/18 21:27:44 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.2 1998/04/21 21:29:10 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.1 1998/04/09 03:05:58 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:02 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * Minor cosmetic changes. -+ * -+ * Revision 0.3 1996/11/20 14:35:48 ji -+ * Minor Cleanup. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_eroute.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,112 @@ -+/* -+ * @(#) declarations of eroute structures -+ * -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs -+ * Copyright (C) 2001 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ * derived from ipsec_encap.h 1.15 on 2001/9/18 by mcr. -+ * -+ */ -+ -+#ifndef _IPSEC_EROUTE_H_ -+ -+#include "radij.h" -+#include "ipsec_encap.h" -+#include "ipsec_radij.h" -+ -+/* -+ * The "type" is really part of the address as far as the routing -+ * system is concerned. By using only one bit in the type field -+ * for each type, we sort-of make sure that different types of -+ * encapsulation addresses won't be matched against the wrong type. -+ */ -+ -+/* -+ * An entry in the radix tree -+ */ -+ -+struct rjtentry -+{ -+ struct radij_node rd_nodes[2]; /* tree glue, and other values */ -+#define rd_key(r) ((struct sockaddr_encap *)((r)->rd_nodes->rj_key)) -+#define rd_mask(r) ((struct sockaddr_encap *)((r)->rd_nodes->rj_mask)) -+ short rd_flags; -+ short rd_count; -+}; -+ -+struct ident -+{ -+ __u16 type; /* identity type */ -+ __u64 id; /* identity id */ -+ __u8 len; /* identity len */ -+ caddr_t data; /* identity data */ -+}; -+ -+/* -+ * An encapsulation route consists of a pointer to a -+ * radix tree entry and a SAID (a destination_address/SPI/protocol triple). -+ */ -+ -+struct eroute -+{ -+ struct rjtentry er_rjt; -+ ip_said er_said; -+ uint32_t er_pid; -+ uint32_t er_count; -+ uint64_t er_lasttime; -+ struct sockaddr_encap er_eaddr; /* MCR get rid of _encap, it is silly*/ -+ struct sockaddr_encap er_emask; -+ struct ident er_ident_s; -+ struct ident er_ident_d; -+ struct sk_buff* er_first; -+ struct sk_buff* er_last; -+}; -+ -+#define er_dst er_said.dst -+#define er_spi er_said.spi -+ -+#define _IPSEC_EROUTE_H_ -+#endif /* _IPSEC_EROUTE_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.5 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_eroute.h,v -+ * -+ * Revision 1.4 2003/10/31 02:27:05 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.3.30.2 2003/10/29 01:10:19 mcr -+ * elimited "struct sa_id" -+ * -+ * Revision 1.3.30.1 2003/09/21 13:59:38 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.3 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_eroute.h,v -+ * -+ * Revision 1.2 2001/11/26 09:16:13 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:18:54 mcr -+ * struct eroute moved to ipsec_eroute.h -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_errs.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,53 @@ -+/* -+ * @(#) definition of ipsec_errs structure -+ * -+ * Copyright (C) 2001 Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ */ -+ -+/* -+ * This file describes the errors/statistics that FreeSWAN collects. -+ * -+ */ -+ -+struct ipsec_errs { -+ __u32 ips_alg_errs; /* number of algorithm errors */ -+ __u32 ips_auth_errs; /* # of authentication errors */ -+ __u32 ips_encsize_errs; /* # of encryption size errors*/ -+ __u32 ips_encpad_errs; /* # of encryption pad errors*/ -+ __u32 ips_replaywin_errs; /* # of pkt sequence errors */ -+}; -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.4 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_errs.h,v -+ * -+ * Revision 1.3 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_errs.h,v -+ * -+ * Revision 1.2 2001/11/26 09:16:13 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:25:57 mcr -+ * lifetime structure created and common functions created. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_esp.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,147 @@ -+/* -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#include "openswan/ipsec_md5h.h" -+#include "openswan/ipsec_sha1.h" -+ -+#include "crypto/des.h" -+ -+#ifndef IPPROTO_ESP -+#define IPPROTO_ESP 50 -+#endif /* IPPROTO_ESP */ -+ -+#define ESP_HEADER_LEN 8 /* 64 bits header (spi+rpl)*/ -+ -+#define EMT_ESPDESCBC_ULEN 20 /* coming from user mode */ -+#define EMT_ESPDES_KMAX 64 /* 512 bit secret key enough? */ -+#define EMT_ESPDES_KEY_SZ 8 /* 56 bit secret key with parity = 64 bits */ -+#define EMT_ESP3DES_KEY_SZ 24 /* 168 bit secret key with parity = 192 bits */ -+#define EMT_ESPDES_IV_SZ 8 /* IV size */ -+#define ESP_DESCBC_BLKLEN 8 /* DES-CBC block size */ -+ -+#define ESP_IV_MAXSZ 16 /* This is _critical_ */ -+#define ESP_IV_MAXSZ_INT (ESP_IV_MAXSZ/sizeof(int)) -+ -+#define DB_ES_PKTRX 0x0001 -+#define DB_ES_PKTRX2 0x0002 -+#define DB_ES_IPSA 0x0010 -+#define DB_ES_XF 0x0020 -+#define DB_ES_IPAD 0x0040 -+#define DB_ES_INAU 0x0080 -+#define DB_ES_OINFO 0x0100 -+#define DB_ES_OINFO2 0x0200 -+#define DB_ES_OH 0x0400 -+#define DB_ES_REPLAY 0x0800 -+ -+#ifdef __KERNEL__ -+struct des_eks { -+ des_key_schedule ks; -+}; -+ -+extern struct inet_protocol esp_protocol; -+ -+struct options; -+ -+struct esphdr -+{ -+ __u32 esp_spi; /* Security Parameters Index */ -+ __u32 esp_rpl; /* Replay counter */ -+ __u8 esp_iv[8]; /* iv */ -+}; -+ -+extern struct xform_functions esp_xform_funcs[]; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int debug_esp; -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif /* __KERNEL__ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.25 2004/04/06 02:49:08 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.24 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_esp.h,v -+ * -+ * Revision 1.23 2004/04/05 19:41:05 mcr -+ * merged alg-branch code. -+ * -+ * Revision 1.22 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.23 2003/12/11 20:14:58 mcr -+ * refactored the xmit code, to move all encapsulation -+ * code into protocol functions. Note that all functions -+ * are essentially done by a single function, which is probably -+ * wrong. -+ * the rcv_functions structures are renamed xform_functions. -+ * -+ * Revision 1.22 2003/12/06 21:21:19 mcr -+ * split up receive path into per-transform files, for -+ * easier later removal. -+ * -+ * Revision 1.21.8.1 2003/12/22 15:25:52 jjo -+ * Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.21 2003/02/06 02:21:34 rgb -+ * -+ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h . -+ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr". -+ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code. -+ * -+ * Revision 1.20 2002/05/14 02:37:02 rgb -+ * Change reference from _TDB to _IPSA. -+ * -+ * Revision 1.19 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.18 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_esp.h,v -+ * -+ * Revision 1.17 2002/02/20 01:27:07 rgb -+ * Ditched a pile of structs only used by the old Netlink interface. -+ * -+ * Revision 1.16 2001/12/11 02:35:57 rgb -+ * Change "struct net_device" to "struct device" for 2.2 compatibility. -+ * -+ * Revision 1.15 2001/11/26 09:23:48 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.14.2.3 2001/10/23 04:16:42 mcr -+ * get definition of des_key_schedule from des.h -+ * -+ * Revision 1.14.2.2 2001/10/22 20:33:13 mcr -+ * use "des_key_schedule" structure instead of cooking our own. -+ * -+ * Revision 1.14.2.1 2001/09/25 02:18:25 mcr -+ * replace "struct device" with "struct netdevice" -+ * -+ * Revision 1.14 2001/06/14 19:35:08 rgb -+ * Update copyright date. -+ * -+ * Revision 1.13 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.12 2000/08/01 14:51:50 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.11 2000/01/10 16:36:20 rgb -+ * Ditch last of EME option flags, including initiator. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_ipcomp.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,91 @@ -+/* -+ * IP compression header declations -+ * -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef IPSEC_IPCOMP_H -+#define IPSEC_IPCOMP_H -+ -+#include "openswan/ipsec_auth.h" -+ -+/* Prefix all global deflate symbols with "ipcomp_" to avoid collisions with ppp_deflate & ext2comp */ -+#ifndef IPCOMP_PREFIX -+#define IPCOMP_PREFIX -+#endif /* IPCOMP_PREFIX */ -+ -+#ifndef IPPROTO_COMP -+#define IPPROTO_COMP 108 -+#endif /* IPPROTO_COMP */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int sysctl_ipsec_debug_ipcomp; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+struct ipcomphdr { /* IPCOMP header */ -+ __u8 ipcomp_nh; /* Next header (protocol) */ -+ __u8 ipcomp_flags; /* Reserved, must be 0 */ -+ __u16 ipcomp_cpi; /* Compression Parameter Index */ -+}; -+ -+extern struct inet_protocol comp_protocol; -+extern int sysctl_ipsec_debug_ipcomp; -+ -+#define IPCOMP_UNCOMPRESSABLE 0x000000001 -+#define IPCOMP_COMPRESSIONERROR 0x000000002 -+#define IPCOMP_PARMERROR 0x000000004 -+#define IPCOMP_DECOMPRESSIONERROR 0x000000008 -+ -+#define IPCOMP_ADAPT_INITIAL_TRIES 8 -+#define IPCOMP_ADAPT_INITIAL_SKIP 4 -+#define IPCOMP_ADAPT_SUBSEQ_TRIES 2 -+#define IPCOMP_ADAPT_SUBSEQ_SKIP 8 -+ -+/* Function prototypes */ -+struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); -+struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); -+ -+extern struct xform_functions ipcomp_xform_funcs[]; -+ -+#endif /* IPSEC_IPCOMP_H */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.3 2004/04/06 02:49:08 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.2 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_ipcomp.h,v -+ * -+ * Revision 1.1 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.2 2003/12/11 20:14:58 mcr -+ * refactored the xmit code, to move all encapsulation -+ * code into protocol functions. Note that all functions -+ * are essentially done by a single function, which is probably -+ * wrong. -+ * the rcv_functions structures are renamed xform_functions. -+ * -+ * Revision 1.1 2003/12/06 21:21:19 mcr -+ * split up receive path into per-transform files, for -+ * easier later removal. -+ * -+ * -+ * -+ */ -+ -+ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_ipe4.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,68 @@ -+/* -+ * IP-in-IP Header declarations -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* The packet header is an IP header! */ -+ -+struct ipe4_xdata /* transform table data */ -+{ -+ struct in_addr i4_src; -+ struct in_addr i4_dst; -+}; -+ -+#define EMT_IPE4_ULEN 8 /* coming from user mode */ -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.6 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_ipe4.h,v -+ * -+ * Revision 1.5 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_ipe4.h,v -+ * -+ * Revision 1.4 2001/06/14 19:35:08 rgb -+ * Update copyright date. -+ * -+ * Revision 1.3 1999/04/11 00:28:57 henry -+ * GPL boilerplate -+ * -+ * Revision 1.2 1999/04/06 04:54:25 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.1 1998/06/18 21:27:47 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.1 1998/04/09 03:06:07 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:03 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:48:53 ji -+ * Release update only. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_ipip.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,45 @@ -+/* -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef _IPSEC_IPIP_H_ -+ -+#ifndef IPPROTO_IPIP -+#define IPPROTO_IPIP 4 -+#endif /* IPPROTO_ESP */ -+ -+extern struct xform_functions ipip_xform_funcs[]; -+ -+#define _IPSEC_IPIP_H_ -+ -+#endif /* _IPSEC_IPIP_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.2 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_ipip.h,v -+ * -+ * Revision 1.1 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.1 2003/12/11 20:14:58 mcr -+ * refactored the xmit code, to move all encapsulation -+ * code into protocol functions. Note that all functions -+ * are essentially done by a single function, which is probably -+ * wrong. -+ * the rcv_functions structures are renamed xform_functions. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_kversion.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,239 @@ -+#ifndef _FREESWAN_KVERSIONS_H -+/* -+ * header file for FreeS/WAN library functions -+ * Copyright (C) 1998, 1999, 2000 Henry Spencer. -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#define _FREESWAN_KVERSIONS_H /* seen it, no need to see it again */ -+ -+/* -+ * this file contains a series of atomic defines that depend upon -+ * kernel version numbers. The kernel versions are arranged -+ * in version-order number (which is often not chronological) -+ * and each clause enables or disables a feature. -+ */ -+ -+/* -+ * First, assorted kernel-version-dependent trickery. -+ */ -+#include -+#ifndef KERNEL_VERSION -+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) -+#define HEADER_CACHE_BIND_21 -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) -+#define SPINLOCK -+#define PROC_FS_21 -+#define NETLINK_SOCK -+#define NET_21 -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,19) -+#define net_device_stats enet_statistics -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) -+#define SPINLOCK_23 -+#define NETDEV_23 -+# ifndef CONFIG_IP_ALIAS -+# define CONFIG_IP_ALIAS -+# endif -+#include -+#include -+#include -+# ifdef NETLINK_XFRM -+# define NETDEV_25 -+# endif -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,25) -+#define PROC_FS_2325 -+#undef PROC_FS_21 -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30) -+#define PROC_NO_DUMMY -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,35) -+#define SKB_COPY_EXPAND -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,37) -+#define IP_SELECT_IDENT -+#endif -+ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,50)) && defined(CONFIG_NETFILTER) -+#define SKB_RESET_NFCT -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,2) -+#define IP_SELECT_IDENT_NEW -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) -+#define IPH_is_SKB_PULLED -+#define SKB_COW_NEW -+#define PROTO_HANDLER_SINGLE_PARM -+#define IP_FRAGMENT_LINEARIZE 1 -+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) */ -+# ifdef REDHAT_BOGOSITY -+# define IP_SELECT_IDENT_NEW -+# define IPH_is_SKB_PULLED -+# define SKB_COW_NEW -+# define PROTO_HANDLER_SINGLE_PARM -+# endif /* REDHAT_BOGOSITY */ -+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) */ -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) -+#define MALLOC_SLAB -+#define LINUX_KERNEL_HAS_SNPRINTF -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+#define HAVE_NETDEV_PRINTK 1 -+#endif -+ -+#ifdef NET_21 -+# include -+#else -+ /* old kernel in.h has some IPv6 stuff, but not quite enough */ -+# define s6_addr16 s6_addr -+# define AF_INET6 10 -+# define uint8_t __u8 -+# define uint16_t __u16 -+# define uint32_t __u32 -+# define uint64_t __u64 -+#endif -+ -+#ifdef NET_21 -+# define ipsec_kfree_skb(a) kfree_skb(a) -+#else /* NET_21 */ -+# define ipsec_kfree_skb(a) kfree_skb(a, FREE_WRITE) -+#endif /* NET_21 */ -+ -+#ifdef NETDEV_23 -+# define device net_device -+# define ipsec_dev_get dev_get_by_name -+# define __ipsec_dev_get __dev_get_by_name -+# define ipsec_dev_put(x) dev_put(x) -+# define __ipsec_dev_put(x) __dev_put(x) -+# define ipsec_dev_hold(x) dev_hold(x) -+#else /* NETDEV_23 */ -+# define ipsec_dev_get dev_get -+# define __ipsec_dev_put(x) -+# define ipsec_dev_put(x) -+# define ipsec_dev_hold(x) -+#endif /* NETDEV_23 */ -+ -+#ifndef SPINLOCK -+# include -+ /* simulate spin locks and read/write locks */ -+ typedef struct { -+ volatile char lock; -+ } spinlock_t; -+ -+ typedef struct { -+ volatile unsigned int lock; -+ } rwlock_t; -+ -+# define spin_lock_init(x) { (x)->lock = 0;} -+# define rw_lock_init(x) { (x)->lock = 0; } -+ -+# define spin_lock(x) { while ((x)->lock) barrier(); (x)->lock=1;} -+# define spin_lock_irq(x) { cli(); spin_lock(x);} -+# define spin_lock_irqsave(x,flags) { save_flags(flags); spin_lock_irq(x);} -+ -+# define spin_unlock(x) { (x)->lock=0;} -+# define spin_unlock_irq(x) { spin_unlock(x); sti();} -+# define spin_unlock_irqrestore(x,flags) { spin_unlock(x); restore_flags(flags);} -+ -+# define read_lock(x) spin_lock(x) -+# define read_lock_irq(x) spin_lock_irq(x) -+# define read_lock_irqsave(x,flags) spin_lock_irqsave(x,flags) -+ -+# define read_unlock(x) spin_unlock(x) -+# define read_unlock_irq(x) spin_unlock_irq(x) -+# define read_unlock_irqrestore(x,flags) spin_unlock_irqrestore(x,flags) -+ -+# define write_lock(x) spin_lock(x) -+# define write_lock_irq(x) spin_lock_irq(x) -+# define write_lock_irqsave(x,flags) spin_lock_irqsave(x,flags) -+ -+# define write_unlock(x) spin_unlock(x) -+# define write_unlock_irq(x) spin_unlock_irq(x) -+# define write_unlock_irqrestore(x,flags) spin_unlock_irqrestore(x,flags) -+#endif /* !SPINLOCK */ -+ -+#ifndef SPINLOCK_23 -+# define spin_lock_bh(x) spin_lock_irq(x) -+# define spin_unlock_bh(x) spin_unlock_irq(x) -+ -+# define read_lock_bh(x) read_lock_irq(x) -+# define read_unlock_bh(x) read_unlock_irq(x) -+ -+# define write_lock_bh(x) write_lock_irq(x) -+# define write_unlock_bh(x) write_unlock_irq(x) -+#endif /* !SPINLOCK_23 */ -+ -+#ifndef HAVE_NETDEV_PRINTK -+#define netdev_printk(sevlevel, netdev, msglevel, format, arg...) \ -+ printk(sevlevel "%s: " format , netdev->name , ## arg) -+#endif -+ -+#endif /* _FREESWAN_KVERSIONS_H */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.9 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_kversion.h,v -+ * -+ * Revision 1.8 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.7 2003/07/31 22:48:08 mcr -+ * derive NET25-ness from presence of NETLINK_XFRM macro. -+ * -+ * Revision 1.6 2003/06/24 20:22:32 mcr -+ * added new global: ipsecdevices[] so that we can keep track of -+ * the ipsecX devices. They will be referenced with dev_hold(), -+ * so 2.2 may need this as well. -+ * -+ * Revision 1.5 2003/04/03 17:38:09 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * -+ * Revision 1.4 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_kversion.h,v -+ * -+ * Revision 1.3 2002/04/12 03:21:17 mcr -+ * three parameter version of ip_select_ident appears first -+ * in 2.4.2 (RH7.1) not 2.4.4. -+ * -+ * Revision 1.2 2002/03/08 21:35:22 rgb -+ * Defined LINUX_KERNEL_HAS_SNPRINTF to shut up compiler warnings after -+ * 2.4.9. (Andreas Piesk). -+ * -+ * Revision 1.1 2002/01/29 02:11:42 mcr -+ * removal of kversions.h - sources that needed it now use ipsec_param.h. -+ * updating of IPv6 structures to match latest in6.h version. -+ * removed dead code from freeswan.h that also duplicated kversions.h -+ * code. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_life.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,112 @@ -+/* -+ * Definitions relevant to IPSEC lifetimes -+ * Copyright (C) 2001 Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ * This file derived from ipsec_xform.h on 2001/9/18 by mcr. -+ * -+ */ -+ -+/* -+ * This file describes the book keeping fields for the -+ * IPsec Security Association Structure. ("ipsec_sa") -+ * -+ * This structure is never allocated directly by kernel code, -+ * (it is always a static/auto or is part of a structure) -+ * so it does not have a reference count. -+ * -+ */ -+ -+#ifndef _IPSEC_LIFE_H_ -+ -+/* -+ * _count is total count. -+ * _hard is hard limit (kill SA after this number) -+ * _soft is soft limit (try to renew SA after this number) -+ * _last is used in some special cases. -+ * -+ */ -+ -+struct ipsec_lifetime64 -+{ -+ __u64 ipl_count; -+ __u64 ipl_soft; -+ __u64 ipl_hard; -+ __u64 ipl_last; -+}; -+ -+struct ipsec_lifetimes -+{ -+ /* number of bytes processed */ -+ struct ipsec_lifetime64 ipl_bytes; -+ -+ /* number of packets processed */ -+ struct ipsec_lifetime64 ipl_packets; -+ -+ /* time since SA was added */ -+ struct ipsec_lifetime64 ipl_addtime; -+ -+ /* time since SA was first used */ -+ struct ipsec_lifetime64 ipl_usetime; -+ -+ /* from rfc2367: -+ * For CURRENT, the number of different connections, -+ * endpoints, or flows that the association has been -+ * allocated towards. For HARD and SOFT, the number of -+ * these the association may be allocated towards -+ * before it expires. The concept of a connection, -+ * flow, or endpoint is system specific. -+ * -+ * mcr(2001-9-18) it is unclear what purpose these serve for FreeSWAN. -+ * They are maintained for PF_KEY compatibility. -+ */ -+ struct ipsec_lifetime64 ipl_allocations; -+}; -+ -+enum ipsec_life_alive { -+ ipsec_life_harddied = -1, -+ ipsec_life_softdied = 0, -+ ipsec_life_okay = 1 -+}; -+ -+enum ipsec_life_type { -+ ipsec_life_timebased = 1, -+ ipsec_life_countbased= 0 -+}; -+ -+#define _IPSEC_LIFE_H_ -+#endif /* _IPSEC_LIFE_H_ */ -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.4 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_life.h,v -+ * -+ * Revision 1.3 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_life.h,v -+ * -+ * Revision 1.2 2001/11/26 09:16:14 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:25:58 mcr -+ * lifetime structure created and common functions created. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_md5h.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,140 @@ -+/* -+ * RCSID $Id$ -+ */ -+ -+/* -+ * The rest of this file is Copyright RSA DSI. See the following comments -+ * for the full Copyright notice. -+ */ -+ -+#ifndef _IPSEC_MD5H_H_ -+#define _IPSEC_MD5H_H_ -+ -+/* GLOBAL.H - RSAREF types and constants -+ */ -+ -+/* PROTOTYPES should be set to one if and only if the compiler supports -+ function argument prototyping. -+ The following makes PROTOTYPES default to 0 if it has not already -+ been defined with C compiler flags. -+ */ -+#ifndef PROTOTYPES -+#define PROTOTYPES 1 -+#endif /* !PROTOTYPES */ -+ -+/* POINTER defines a generic pointer type */ -+typedef __u8 *POINTER; -+ -+/* UINT2 defines a two byte word */ -+typedef __u16 UINT2; -+ -+/* UINT4 defines a four byte word */ -+typedef __u32 UINT4; -+ -+/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. -+ If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it -+ returns an empty list. -+ */ -+ -+#if PROTOTYPES -+#define PROTO_LIST(list) list -+#else /* PROTOTYPES */ -+#define PROTO_LIST(list) () -+#endif /* PROTOTYPES */ -+ -+ -+/* MD5.H - header file for MD5C.C -+ */ -+ -+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -+rights reserved. -+ -+License to copy and use this software is granted provided that it -+is identified as the "RSA Data Security, Inc. MD5 Message-Digest -+Algorithm" in all material mentioning or referencing this software -+or this function. -+ -+License is also granted to make and use derivative works provided -+that such works are identified as "derived from the RSA Data -+Security, Inc. MD5 Message-Digest Algorithm" in all material -+mentioning or referencing the derived work. -+ -+RSA Data Security, Inc. makes no representations concerning either -+the merchantability of this software or the suitability of this -+software for any particular purpose. It is provided "as is" -+without express or implied warranty of any kind. -+ -+These notices must be retained in any copies of any part of this -+documentation and/or software. -+ */ -+ -+/* MD5 context. */ -+typedef struct { -+ UINT4 state[4]; /* state (ABCD) */ -+ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ -+ unsigned char buffer[64]; /* input buffer */ -+} MD5_CTX; -+ -+void MD5Init PROTO_LIST ((void *)); -+void MD5Update PROTO_LIST -+ ((void *, unsigned char *, __u32)); -+void MD5Final PROTO_LIST ((unsigned char [16], void *)); -+ -+#endif /* _IPSEC_MD5H_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.9 2004/04/05 19:55:05 mcr -+ * Moved from linux/include/freeswan/ipsec_md5h.h,v -+ * -+ * Revision 1.8 2002/09/10 01:45:09 mcr -+ * changed type of MD5_CTX and SHA1_CTX to void * so that -+ * the function prototypes would match, and could be placed -+ * into a pointer to a function. -+ * -+ * Revision 1.7 2002/04/24 07:36:46 mcr -+ * Moved from ./klips/net/ipsec/ipsec_md5h.h,v -+ * -+ * Revision 1.6 1999/12/13 13:59:13 rgb -+ * Quick fix to argument size to Update bugs. -+ * -+ * Revision 1.5 1999/12/07 18:16:23 rgb -+ * Fixed comments at end of #endif lines. -+ * -+ * Revision 1.4 1999/04/06 04:54:26 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.3 1999/01/22 06:19:58 rgb -+ * 64-bit clean-up. -+ * -+ * Revision 1.2 1998/11/30 13:22:54 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.1 1998/06/18 21:27:48 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.2 1998/04/23 20:54:03 rgb -+ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when -+ * verified. -+ * -+ * Revision 1.1 1998/04/09 03:04:21 henry -+ * sources moved up from linux/net/ipsec -+ * these two include files modified not to include others except in kernel -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:03 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:48:53 ji -+ * Release update only. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_param.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,333 @@ -+/* -+ * @(#) FreeSWAN tunable paramaters -+ * -+ * Copyright (C) 2001 Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ */ -+ -+/* -+ * This file provides a set of #define's which may be tuned by various -+ * people/configurations. It keeps all compile-time tunables in one place. -+ * -+ * This file should be included before all other IPsec kernel-only files. -+ * -+ */ -+ -+#ifndef _IPSEC_PARAM_H_ -+ -+#ifdef __KERNEL__ -+#include "ipsec_kversion.h" -+ -+/* Set number of ipsecX virtual devices here. */ -+/* This must be < exp(field width of IPSEC_DEV_FORMAT) */ -+/* It must also be reasonable so as not to overload the memory and CPU */ -+/* constraints of the host. */ -+#define IPSEC_NUM_IF 4 -+/* The field width must be < IF_NAM_SIZ - strlen("ipsec") - 1. */ -+/* With "ipsec" being 5 characters, that means 10 is the max field width */ -+/* but machine memory and CPU constraints are not likely to tollerate */ -+/* more than 3 digits. The default is one digit. */ -+/* Update: userland scripts get upset if they can't find "ipsec0", so */ -+/* for now, no "0"-padding should be used (which would have been helpful */ -+/* to make text-searches work */ -+#define IPSEC_DEV_FORMAT "ipsec%d" -+/* For, say, 500 virtual ipsec devices, I would recommend: */ -+/* #define IPSEC_NUM_IF 500 */ -+/* #define IPSEC_DEV_FORMAT "ipsec%03d" */ -+/* Note that the "interfaces=" line in /etc/ipsec.conf would be, um, challenging. */ -+ -+/* use dynamic ipsecX device allocation */ -+#ifndef CONFIG_IPSEC_DYNDEV -+#define CONFIG_IPSEC_DYNDEV 1 -+#endif /* CONFIG_IPSEC_DYNDEV */ -+ -+ -+#ifdef CONFIG_IPSEC_BIGGATE -+# define SADB_HASHMOD 8069 -+#else /* CONFIG_IPSEC_BIGGATE */ -+# define SADB_HASHMOD 257 -+#endif /* CONFIG_IPSEC_BIGGATE */ -+#endif /* __KERNEL__ */ -+ -+/* -+ * This is for the SA reference table. This number is related to the -+ * maximum number of SAs that KLIPS can concurrently deal with, plus enough -+ * space for keeping expired SAs around. -+ * -+ * TABLE_MAX_WIDTH is the number of bits that we will use. -+ * MAIN_TABLE_WIDTH is the number of bits used for the primary index table. -+ * -+ */ -+#ifndef IPSEC_SA_REF_TABLE_IDX_WIDTH -+# define IPSEC_SA_REF_TABLE_IDX_WIDTH 16 -+#endif -+ -+#ifndef IPSEC_SA_REF_MAINTABLE_IDX_WIDTH -+# define IPSEC_SA_REF_MAINTABLE_IDX_WIDTH 4 -+#endif -+ -+#ifndef IPSEC_SA_REF_FREELIST_NUM_ENTRIES -+# define IPSEC_SA_REF_FREELIST_NUM_ENTRIES 256 -+#endif -+ -+#ifndef IPSEC_SA_REF_CODE -+# define IPSEC_SA_REF_CODE 1 -+#endif -+ -+#ifdef __KERNEL__ -+/* This is defined for 2.4, but not 2.2.... */ -+#ifndef ARPHRD_VOID -+# define ARPHRD_VOID 0xFFFF -+#endif -+ -+/* -+ * Worry about PROC_FS stuff -+ */ -+#if defined(PROC_FS_2325) -+/* kernel 2.4 */ -+# define IPSEC_PROC_LAST_ARG ,int *eof,void *data -+# define IPSEC_PROCFS_DEBUG_NO_STATIC -+# define IPSEC_PROC_SUBDIRS -+#else -+/* kernel <2.4 */ -+# define IPSEC_PROCFS_DEBUG_NO_STATIC DEBUG_NO_STATIC -+ -+# ifndef PROC_NO_DUMMY -+# define IPSEC_PROC_LAST_ARG , int dummy -+# else -+# define IPSEC_PROC_LAST_ARG -+# endif /* !PROC_NO_DUMMY */ -+#endif /* PROC_FS_2325 */ -+ -+#if !defined(LINUX_KERNEL_HAS_SNPRINTF) -+/* GNU CPP specific! */ -+# define snprintf(buf, len, fmt...) sprintf(buf, ##fmt) -+#endif /* !LINUX_KERNEL_HAS_SNPRINTF */ -+ -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+ -+#ifndef KLIPS_FIXES_DES_PARITY -+# define KLIPS_FIXES_DES_PARITY 1 -+#endif /* !KLIPS_FIXES_DES_PARITY */ -+ -+/* we don't really want to print these unless there are really big problems */ -+#ifndef KLIPS_DIVULGE_CYPHER_KEY -+# define KLIPS_DIVULGE_CYPHER_KEY 0 -+#endif /* !KLIPS_DIVULGE_CYPHER_KEY */ -+ -+#ifndef KLIPS_DIVULGE_HMAC_KEY -+# define KLIPS_DIVULGE_HMAC_KEY 0 -+#endif /* !KLIPS_DIVULGE_HMAC_KEY */ -+ -+#ifndef IPSEC_DISALLOW_IPOPTIONS -+# define IPSEC_DISALLOW_IPOPTIONS 1 -+#endif /* !KLIPS_DIVULGE_HMAC_KEY */ -+ -+/* extra toggles for regression testing */ -+#ifdef CONFIG_IPSEC_REGRESS -+ -+/* -+ * should pfkey_acquire() become 100% lossy? -+ * -+ */ -+extern int sysctl_ipsec_regress_pfkey_lossage; -+#ifndef KLIPS_PFKEY_ACQUIRE_LOSSAGE -+# ifdef CONFIG_IPSEC_PFKEY_ACQUIRE_LOSSAGE -+# define KLIPS_PFKEY_ACQUIRE_LOSSAGE 100 -+# else /* CONFIG_IPSEC_PFKEY_ACQUIRE_LOSSAGE */ -+/* not by default! */ -+# define KLIPS_PFKEY_ACQUIRE_LOSSAGE 0 -+# endif /* CONFIG_IPSEC_PFKEY_ACQUIRE_LOSSAGE */ -+#endif /* KLIPS_PFKEY_ACQUIRE_LOSSAGE */ -+ -+#endif /* CONFIG_IPSEC_REGRESS */ -+ -+ -+/* -+ * debugging routines. -+ */ -+#ifdef CONFIG_IPSEC_DEBUG -+extern void ipsec_print_ip(struct iphdr *ip); -+ -+ #define KLIPS_PRINT(flag, format, args...) \ -+ ((flag) ? printk(KERN_INFO format , ## args) : 0) -+ #define KLIPS_PRINTMORE(flag, format, args...) \ -+ ((flag) ? printk(format , ## args) : 0) -+ #define KLIPS_IP_PRINT(flag, ip) \ -+ ((flag) ? ipsec_print_ip(ip) : 0) -+#else /* CONFIG_IPSEC_DEBUG */ -+ #define KLIPS_PRINT(flag, format, args...) do ; while(0) -+ #define KLIPS_PRINTMORE(flag, format, args...) do ; while(0) -+ #define KLIPS_IP_PRINT(flag, ip) do ; while(0) -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ -+/* -+ * Stupid kernel API differences in APIs. Not only do some -+ * kernels not have ip_select_ident, but some have differing APIs, -+ * and SuSE has one with one parameter, but no way of checking to -+ * see what is really what. -+ */ -+ -+#ifdef SUSE_LINUX_2_4_19_IS_STUPID -+#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph) -+#else -+ -+/* simplest case, nothing */ -+#if !defined(IP_SELECT_IDENT) -+#define KLIPS_IP_SELECT_IDENT(iph, skb) do { iph->id = htons(ip_id_count++); } while(0) -+#endif -+ -+/* kernels > 2.3.37-ish */ -+#if defined(IP_SELECT_IDENT) && !defined(IP_SELECT_IDENT_NEW) -+#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst) -+#endif -+ -+/* kernels > 2.4.2 */ -+#if defined(IP_SELECT_IDENT) && defined(IP_SELECT_IDENT_NEW) -+#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst, NULL) -+#endif -+ -+#endif /* SUSE_LINUX_2_4_19_IS_STUPID */ -+ -+/* -+ * make klips fail test:east-espiv-01. -+ * exploit is at testing/attacks/espiv -+ * -+ */ -+#define KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK 0 -+ -+ -+/* IP_FRAGMENT_LINEARIZE is set in freeswan.h if Kernel > 2.4.4 */ -+#ifndef IP_FRAGMENT_LINEARIZE -+# define IP_FRAGMENT_LINEARIZE 0 -+#endif /* IP_FRAGMENT_LINEARIZE */ -+#endif /* __KERNEL__ */ -+ -+#define _IPSEC_PARAM_H_ -+#endif /* _IPSEC_PARAM_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.24 2004/04/05 19:55:06 mcr -+ * Moved from linux/include/freeswan/ipsec_param.h,v -+ * -+ * Revision 1.23 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.22 2003/10/31 02:27:05 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.21.4.1 2003/10/29 01:10:19 mcr -+ * elimited "struct sa_id" -+ * -+ * Revision 1.21 2003/04/03 17:38:18 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * Change indentation for readability. -+ * -+ * Revision 1.20 2003/03/14 08:09:26 rgb -+ * Fixed up CONFIG_IPSEC_DYNDEV definitions. -+ * -+ * Revision 1.19 2003/01/30 02:31:43 rgb -+ * -+ * Rename SAref table macro names for clarity. -+ * -+ * Revision 1.18 2002/09/30 19:06:26 rgb -+ * Reduce default table to 16 bits width. -+ * -+ * Revision 1.17 2002/09/20 15:40:29 rgb -+ * Define switch to activate new SAref code. -+ * Prefix macros with "IPSEC_". -+ * Rework saref freelist. -+ * Restrict some bits to kernel context for use to klips utils. -+ * -+ * Revision 1.16 2002/09/20 05:00:31 rgb -+ * Define switch to divulge hmac keys for debugging. -+ * Added IPOPTIONS switch. -+ * -+ * Revision 1.15 2002/09/19 02:34:24 mcr -+ * define IPSEC_PROC_SUBDIRS if we are 2.4, and use that in ipsec_proc.c -+ * to decide if we are to create /proc/net/ipsec/. -+ * -+ * Revision 1.14 2002/08/30 01:20:54 mcr -+ * reorganized 2.0/2.2/2.4 procfs support macro so match -+ * 2.4 values/typedefs. -+ * -+ * Revision 1.13 2002/07/28 22:03:28 mcr -+ * added some documentation to SA_REF_* -+ * turned on fix for ESPIV attack, now that we have the attack code. -+ * -+ * Revision 1.12 2002/07/26 08:48:31 rgb -+ * Added SA ref table code. -+ * -+ * Revision 1.11 2002/07/23 02:57:45 rgb -+ * Define ARPHRD_VOID for < 2.4 kernels. -+ * -+ * Revision 1.10 2002/05/27 21:37:28 rgb -+ * Set the defaults sanely for those adventurous enough to try more than 1 -+ * digit of ipsec devices. -+ * -+ * Revision 1.9 2002/05/27 18:56:07 rgb -+ * Convert to dynamic ipsec device allocation. -+ * -+ * Revision 1.8 2002/04/24 07:36:47 mcr -+ * Moved from ./klips/net/ipsec/ipsec_param.h,v -+ * -+ * Revision 1.7 2002/04/20 00:12:25 rgb -+ * Added esp IV CBC attack fix, disabled. -+ * -+ * Revision 1.6 2002/01/29 02:11:42 mcr -+ * removal of kversions.h - sources that needed it now use ipsec_param.h. -+ * updating of IPv6 structures to match latest in6.h version. -+ * removed dead code from freeswan.h that also duplicated kversions.h -+ * code. -+ * -+ * Revision 1.5 2002/01/28 19:22:01 mcr -+ * by default, turn off LINEARIZE option -+ * (let kversions.h turn it on) -+ * -+ * Revision 1.4 2002/01/20 20:19:36 mcr -+ * renamed option to IP_FRAGMENT_LINEARIZE. -+ * -+ * Revision 1.3 2002/01/12 02:57:25 mcr -+ * first regression test causes acquire messages to be lost -+ * 100% of the time. This is to help testing of pluto. -+ * -+ * Revision 1.2 2001/11/26 09:16:14 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.3 2001/10/23 04:40:16 mcr -+ * added #define for DIVULGING session keys in debug output. -+ * -+ * Revision 1.1.2.2 2001/10/22 20:53:25 mcr -+ * added a define to control forcing of DES parity. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:20:19 mcr -+ * many common kernel configuration questions centralized. -+ * more things remain that should be moved from freeswan.h. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_policy.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,216 @@ -+#ifndef _IPSEC_POLICY_H -+/* -+ * policy interface file between pluto and applications -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#define _IPSEC_POLICY_H /* seen it, no need to see it again */ -+ -+ -+/* -+ * this file defines an interface between an application (or rather an -+ * application library) and a key/policy daemon. It provides for inquiries -+ * as to the current state of a connected socket, as well as for general -+ * questions. -+ * -+ * In general, the interface is defined as a series of functional interfaces, -+ * and the policy messages should be internal. However, because this is in -+ * fact an ABI between pieces of the system that may get compiled and revised -+ * seperately, this ABI must be public and revision controlled. -+ * -+ * It is expected that the daemon will always support previous versions. -+ */ -+ -+#define IPSEC_POLICY_MSG_REVISION (unsigned)200305061 -+ -+enum ipsec_policy_command { -+ IPSEC_CMD_QUERY_FD = 1, -+ IPSEC_CMD_QUERY_HOSTPAIR = 2, -+ IPSEC_CMD_QUERY_DSTONLY = 3, -+}; -+ -+struct ipsec_policy_msg_head { -+ u_int32_t ipm_version; -+ u_int32_t ipm_msg_len; -+ u_int32_t ipm_msg_type; -+ u_int32_t ipm_msg_seq; -+}; -+ -+enum ipsec_privacy_quality { -+ IPSEC_PRIVACY_NONE = 0, -+ IPSEC_PRIVACY_INTEGRAL = 4, /* not private at all. AH-like */ -+ IPSEC_PRIVACY_UNKNOWN = 8, /* something is claimed, but details unavail */ -+ IPSEC_PRIVACY_ROT13 = 12, /* trivially breakable, i.e. 1DES */ -+ IPSEC_PRIVACY_GAK = 16, /* known eavesdroppers */ -+ IPSEC_PRIVACY_PRIVATE = 32, /* secure for at least a decade */ -+ IPSEC_PRIVACY_STRONG = 64, /* ridiculously secure */ -+ IPSEC_PRIVACY_TORTOISE = 192, /* even stronger, but very slow */ -+ IPSEC_PRIVACY_OTP = 224, /* some kind of *true* one time pad */ -+}; -+ -+enum ipsec_bandwidth_quality { -+ IPSEC_QOS_UNKNOWN = 0, /* unknown bandwidth */ -+ IPSEC_QOS_INTERACTIVE = 16, /* reasonably moderate jitter, moderate fast. -+ Good enough for telnet/ssh. */ -+ IPSEC_QOS_VOIP = 32, /* faster crypto, predicable jitter */ -+ IPSEC_QOS_FTP = 64, /* higher throughput crypto, perhaps hardware -+ offloaded, but latency/jitter may be bad */ -+ IPSEC_QOS_WIRESPEED = 128, /* expect to be able to fill your pipe */ -+}; -+ -+/* moved from programs/pluto/constants.h */ -+/* IPsec AH transform values -+ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.3 -+ * and in http://www.iana.org/assignments/isakmp-registry -+ */ -+enum ipsec_authentication_algo { -+ AH_MD5=2, -+ AH_SHA=3, -+ AH_DES=4, -+ AH_SHA2_256=5, -+ AH_SHA2_384=6, -+ AH_SHA2_512=7 -+}; -+ -+/* IPsec ESP transform values -+ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.4 -+ * and from http://www.iana.org/assignments/isakmp-registry -+ */ -+ -+enum ipsec_cipher_algo { -+ ESP_reserved=0, -+ ESP_DES_IV64=1, -+ ESP_DES=2, -+ ESP_3DES=3, -+ ESP_RC5=4, -+ ESP_IDEA=5, -+ ESP_CAST=6, -+ ESP_BLOWFISH=7, -+ ESP_3IDEA=8, -+ ESP_DES_IV32=9, -+ ESP_RC4=10, -+ ESP_NULL=11, -+ ESP_AES=12, -+}; -+ -+/* IPCOMP transform values -+ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.5 -+ */ -+ -+enum ipsec_comp_algo { -+ IPCOMP_OUI= 1, -+ IPCOMP_DEFLATE= 2, -+ IPCOMP_LZS= 3, -+ IPCOMP_V42BIS= 4 -+}; -+ -+/* Identification type values -+ * RFC 2407 The Internet IP security Domain of Interpretation for ISAKMP 4.6.2.1 -+ */ -+ -+enum ipsec_id_type { -+ ID_IMPOSSIBLE= (-2), /* private to Pluto */ -+ ID_MYID= (-1), /* private to Pluto */ -+ ID_NONE= 0, /* private to Pluto */ -+ ID_IPV4_ADDR= 1, -+ ID_FQDN= 2, -+ ID_USER_FQDN= 3, -+ ID_IPV4_ADDR_SUBNET= 4, -+ ID_IPV6_ADDR= 5, -+ ID_IPV6_ADDR_SUBNET= 6, -+ ID_IPV4_ADDR_RANGE= 7, -+ ID_IPV6_ADDR_RANGE= 8, -+ ID_DER_ASN1_DN= 9, -+ ID_DER_ASN1_GN= 10, -+ ID_KEY_ID= 11 -+}; -+ -+/* Certificate type values -+ * RFC 2408 ISAKMP, chapter 3.9 -+ */ -+enum ipsec_cert_type { -+ CERT_NONE= 0, /* none, or guess from file contents */ -+ CERT_PKCS7_WRAPPED_X509= 1, /* self-signed certificate from disk */ -+ CERT_PGP= 2, -+ CERT_DNS_SIGNED_KEY= 3, /* KEY RR from DNS */ -+ CERT_X509_SIGNATURE= 4, -+ CERT_X509_KEY_EXCHANGE= 5, -+ CERT_KERBEROS_TOKENS= 6, -+ CERT_CRL= 7, -+ CERT_ARL= 8, -+ CERT_SPKI= 9, -+ CERT_X509_ATTRIBUTE= 10, -+ CERT_RAW_RSA= 11, /* raw RSA from config file */ -+}; -+ -+/* a SIG record in ASCII */ -+struct ipsec_dns_sig { -+ char fqdn[256]; -+ char dns_sig[768]; /* empty string if not signed */ -+}; -+ -+struct ipsec_raw_key { -+ char id_name[256]; -+ char fs_keyid[8]; -+}; -+ -+struct ipsec_identity { -+ enum ipsec_id_type ii_type; -+ enum ipsec_cert_type ii_format; -+ union { -+ struct ipsec_dns_sig ipsec_dns_signed; -+ /* some thing for PGP */ -+ /* some thing for PKIX */ -+ struct ipsec_raw_key ipsec_raw_key; -+ } ii_credential; -+}; -+ -+#define IPSEC_MAX_CREDENTIALS 32 -+ -+struct ipsec_policy_cmd_query { -+ struct ipsec_policy_msg_head head; -+ -+ /* Query section */ -+ ip_address query_local; /* us */ -+ ip_address query_remote; /* them */ -+ u_short src_port, dst_port; -+ -+ /* Answer section */ -+ enum ipsec_privacy_quality strength; -+ enum ipsec_bandwidth_quality bandwidth; -+ enum ipsec_authentication_algo auth_detail; -+ enum ipsec_cipher_algo esp_detail; -+ enum ipsec_comp_algo comp_detail; -+ -+ int credential_count; -+ -+ struct ipsec_identity credentials[IPSEC_MAX_CREDENTIALS]; -+}; -+ -+#define IPSEC_POLICY_SOCKET "/var/run/pluto.info" -+ -+/* prototypes */ -+extern err_t ipsec_policy_lookup(int fd, struct ipsec_policy_cmd_query *result); -+extern err_t ipsec_policy_init(void); -+extern err_t ipsec_policy_final(void); -+extern err_t ipsec_policy_readmsg(int policysock, -+ unsigned char *buf, size_t buflen); -+extern err_t ipsec_policy_sendrecv(unsigned char *buf, size_t buflen); -+extern err_t ipsec_policy_cgilookup(struct ipsec_policy_cmd_query *result); -+ -+ -+extern const char *ipsec_policy_version_code(void); -+extern const char *ipsec_policy_version_string(void); -+ -+#endif /* _IPSEC_POLICY_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_proto.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,151 @@ -+/* -+ * @(#) prototypes for FreeSWAN functions -+ * -+ * Copyright (C) 2001 Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ */ -+ -+#ifndef _IPSEC_PROTO_H_ -+ -+#include "ipsec_param.h" -+ -+/* -+ * This file is a kernel only file that declares prototypes for -+ * all intra-module function calls and global data structures. -+ * -+ * Include this file last. -+ * -+ */ -+ -+/* ipsec_init.c */ -+extern struct prng ipsec_prng; -+ -+/* ipsec_sa.c */ -+extern struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD]; -+extern spinlock_t tdb_lock; -+extern int ipsec_sadb_init(void); -+ -+extern struct ipsec_sa *ipsec_sa_getbyid(ip_said *); -+extern int ipsec_sa_put(struct ipsec_sa *); -+extern /* void */ int ipsec_sa_del(struct ipsec_sa *); -+extern /* void */ int ipsec_sa_delchain(struct ipsec_sa *); -+extern /* void */ int ipsec_sa_add(struct ipsec_sa *); -+ -+extern int ipsec_sadb_cleanup(__u8); -+extern int ipsec_sa_wipe(struct ipsec_sa *); -+ -+/* debug declarations */ -+ -+/* ipsec_proc.c */ -+extern int ipsec_proc_init(void); -+extern void ipsec_proc_cleanup(void); -+ -+/* ipsec_radij.c */ -+extern int ipsec_makeroute(struct sockaddr_encap *ea, -+ struct sockaddr_encap *em, -+ ip_said said, -+ uint32_t pid, -+ struct sk_buff *skb, -+ struct ident *ident_s, -+ struct ident *ident_d); -+ -+extern int ipsec_breakroute(struct sockaddr_encap *ea, -+ struct sockaddr_encap *em, -+ struct sk_buff **first, -+ struct sk_buff **last); -+ -+int ipsec_radijinit(void); -+int ipsec_cleareroutes(void); -+int ipsec_radijcleanup(void); -+ -+/* ipsec_life.c */ -+extern enum ipsec_life_alive ipsec_lifetime_check(struct ipsec_lifetime64 *il64, -+ const char *lifename, -+ const char *saname, -+ enum ipsec_life_type ilt, -+ enum ipsec_direction idir, -+ struct ipsec_sa *ips); -+ -+ -+extern int ipsec_lifetime_format(char *buffer, -+ int buflen, -+ char *lifename, -+ enum ipsec_life_type timebaselife, -+ struct ipsec_lifetime64 *lifetime); -+ -+extern void ipsec_lifetime_update_hard(struct ipsec_lifetime64 *lifetime, -+ __u64 newvalue); -+ -+extern void ipsec_lifetime_update_soft(struct ipsec_lifetime64 *lifetime, -+ __u64 newvalue); -+ -+ -+ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ -+extern int debug_xform; -+extern int debug_eroute; -+extern int debug_spi; -+extern int debug_netlink; -+ -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ -+ -+ -+#define _IPSEC_PROTO_H -+#endif /* _IPSEC_PROTO_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.8 2004/04/05 19:55:06 mcr -+ * Moved from linux/include/freeswan/ipsec_proto.h,v -+ * -+ * Revision 1.7 2003/10/31 02:27:05 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.6.30.1 2003/10/29 01:10:19 mcr -+ * elimited "struct sa_id" -+ * -+ * Revision 1.6 2002/05/23 07:13:48 rgb -+ * Added ipsec_sa_put() for releasing an ipsec_sa refcount. -+ * -+ * Revision 1.5 2002/05/14 02:36:40 rgb -+ * Converted reference from ipsec_sa_put to ipsec_sa_add to avoid confusion -+ * with "put" usage in the kernel. -+ * -+ * Revision 1.4 2002/04/24 07:36:47 mcr -+ * Moved from ./klips/net/ipsec/ipsec_proto.h,v -+ * -+ * Revision 1.3 2002/04/20 00:12:25 rgb -+ * Added esp IV CBC attack fix, disabled. -+ * -+ * Revision 1.2 2001/11/26 09:16:15 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:21:01 mcr -+ * ipsec_proto.h created to keep prototypes rather than deal with -+ * cyclic dependancies of structures and prototypes in .h files. -+ * -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_radij.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,176 @@ -+/* -+ * @(#) Definitions relevant to the IPSEC <> radij tree interfacing -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef _IPSEC_RADIJ_H -+ -+#include -+ -+int ipsec_walk(char *); -+ -+int ipsec_rj_walker_procprint(struct radij_node *, void *); -+int ipsec_rj_walker_delete(struct radij_node *, void *); -+ -+/* This structure is used to pass information between -+ * ipsec_eroute_get_info and ipsec_rj_walker_procprint -+ * (through rj_walktree) and between calls of ipsec_rj_walker_procprint. -+ */ -+struct wsbuf -+{ -+ /* from caller of ipsec_eroute_get_info: */ -+ char *const buffer; /* start of buffer provided */ -+ const int length; /* length of buffer provided */ -+ const off_t offset; /* file position of first character of interest */ -+ /* accumulated by ipsec_rj_walker_procprint: */ -+ int len; /* number of character filled into buffer */ -+ off_t begin; /* file position contained in buffer[0] (<=offset) */ -+}; -+ -+extern struct radij_node_head *rnh; -+extern spinlock_t eroute_lock; -+ -+struct eroute * ipsec_findroute(struct sockaddr_encap *); -+ -+#define O1(x) (int)(((x)>>24)&0xff) -+#define O2(x) (int)(((x)>>16)&0xff) -+#define O3(x) (int)(((x)>>8)&0xff) -+#define O4(x) (int)(((x))&0xff) -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int debug_radij; -+void rj_dumptrees(void); -+ -+#define DB_RJ_DUMPTREES 0x0001 -+#define DB_RJ_FINDROUTE 0x0002 -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#define _IPSEC_RADIJ_H -+#endif -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.21 2004/04/29 11:06:42 ken -+ * Last bits from 2.06 procfs updates -+ * -+ * Revision 1.20 2004/04/06 02:49:08 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.19 2004/04/05 19:55:06 mcr -+ * Moved from linux/include/freeswan/ipsec_radij.h,v -+ * -+ * Revision 1.18 2002/04/24 07:36:47 mcr -+ * Moved from ./klips/net/ipsec/ipsec_radij.h,v -+ * -+ * Revision 1.17 2001/11/26 09:23:49 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.16.2.1 2001/09/25 02:21:17 mcr -+ * ipsec_proto.h created to keep prototypes rather than deal with -+ * cyclic dependancies of structures and prototypes in .h files. -+ * -+ * Revision 1.16 2001/09/15 16:24:04 rgb -+ * Re-inject first and last HOLD packet when an eroute REPLACE is done. -+ * -+ * Revision 1.15 2001/09/14 16:58:37 rgb -+ * Added support for storing the first and last packets through a HOLD. -+ * -+ * Revision 1.14 2001/09/08 21:13:32 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.13 2001/06/14 19:35:09 rgb -+ * Update copyright date. -+ * -+ * Revision 1.12 2001/05/27 06:12:11 rgb -+ * Added structures for pid, packet count and last access time to eroute. -+ * Added packet count to beginning of /proc/net/ipsec_eroute. -+ * -+ * Revision 1.11 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.10 1999/11/17 15:53:39 rgb -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * -+ * Revision 1.9 1999/10/01 00:01:23 rgb -+ * Added eroute structure locking. -+ * -+ * Revision 1.8 1999/04/11 00:28:59 henry -+ * GPL boilerplate -+ * -+ * Revision 1.7 1999/04/06 04:54:26 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.6 1999/01/22 06:23:26 rgb -+ * Cruft clean-out. -+ * -+ * Revision 1.5 1998/10/25 02:42:08 rgb -+ * Change return type on ipsec_breakroute and ipsec_makeroute and add an -+ * argument to be able to transmit more infomation about errors. -+ * -+ * Revision 1.4 1998/10/19 14:44:29 rgb -+ * Added inclusion of freeswan.h. -+ * sa_id structure implemented and used: now includes protocol. -+ * -+ * Revision 1.3 1998/07/28 00:03:31 rgb -+ * Comment out temporary inet_nto4u() kluge. -+ * -+ * Revision 1.2 1998/07/14 18:22:00 rgb -+ * Add function to clear the eroute table. -+ * -+ * Revision 1.1 1998/06/18 21:27:49 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.5 1998/05/25 20:30:38 rgb -+ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions. -+ * -+ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and -+ * add ipsec_rj_walker_delete. -+ * -+ * Revision 1.4 1998/05/21 13:02:56 rgb -+ * Imported definitions from ipsec_radij.c and radij.c to support /proc 3k -+ * limit fix. -+ * -+ * Revision 1.3 1998/04/21 21:29:09 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.2 1998/04/14 17:30:39 rgb -+ * Fix up compiling errors for radij tree memory reclamation. -+ * -+ * Revision 1.1 1998/04/09 03:06:10 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:04 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:39:04 ji -+ * Minor cleanups. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_rcv.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,279 @@ -+/* -+ * -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef IPSEC_RCV_H -+#define IPSEC_RCV_H -+ -+#include "openswan/ipsec_auth.h" -+ -+#define DB_RX_PKTRX 0x0001 -+#define DB_RX_PKTRX2 0x0002 -+#define DB_RX_DMP 0x0004 -+#define DB_RX_IPSA 0x0010 -+#define DB_RX_XF 0x0020 -+#define DB_RX_IPAD 0x0040 -+#define DB_RX_INAU 0x0080 -+#define DB_RX_OINFO 0x0100 -+#define DB_RX_OINFO2 0x0200 -+#define DB_RX_OH 0x0400 -+#define DB_RX_REPLAY 0x0800 -+ -+#ifdef __KERNEL__ -+/* struct options; */ -+ -+#define __NO_VERSION__ -+#include -+#include /* for CONFIG_IP_FORWARD */ -+#include -+#include -+ -+#define IPSEC_BIRTH_TEMPLATE_MAXLEN 256 -+ -+struct ipsec_birth_reply { -+ int packet_template_len; -+ unsigned char packet_template[IPSEC_BIRTH_TEMPLATE_MAXLEN]; -+}; -+ -+extern struct ipsec_birth_reply ipsec_ipv4_birth_packet; -+extern struct ipsec_birth_reply ipsec_ipv6_birth_packet; -+ -+enum ipsec_rcv_value { -+ IPSEC_RCV_LASTPROTO=1, -+ IPSEC_RCV_OK=0, -+ IPSEC_RCV_BADPROTO=-1, -+ IPSEC_RCV_BADLEN=-2, -+ IPSEC_RCV_ESP_BADALG=-3, -+ IPSEC_RCV_3DES_BADBLOCKING=-4, -+ IPSEC_RCV_ESP_DECAPFAIL=-5, -+ IPSEC_RCV_DECAPFAIL=-6, -+ IPSEC_RCV_SAIDNOTFOUND=-7, -+ IPSEC_RCV_IPCOMPALONE=-8, -+ IPSEC_RCV_IPCOMPFAILED=-10, -+ IPSEC_RCV_SAIDNOTLIVE=-11, -+ IPSEC_RCV_FAILEDINBOUND=-12, -+ IPSEC_RCV_LIFETIMEFAILED=-13, -+ IPSEC_RCV_BADAUTH=-14, -+ IPSEC_RCV_REPLAYFAILED=-15, -+ IPSEC_RCV_AUTHFAILED=-16, -+ IPSEC_RCV_REPLAYROLLED=-17, -+ IPSEC_RCV_BAD_DECRYPT=-18 -+}; -+ -+struct ipsec_rcv_state { -+ struct sk_buff *skb; -+ struct net_device_stats *stats; -+ struct iphdr *ipp; -+ struct ipsec_sa *ipsp; -+ int len; -+ int ilen; -+ int authlen; -+ int hard_header_len; -+ int iphlen; -+ struct auth_alg *authfuncs; -+ ip_said said; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ __u8 next_header; -+ __u8 hash[AH_AMAX]; -+ char ipsaddr_txt[ADDRTOA_BUF]; -+ char ipdaddr_txt[ADDRTOA_BUF]; -+ __u8 *octx; -+ __u8 *ictx; -+ int ictx_len; -+ int octx_len; -+ union { -+ struct { -+ struct esphdr *espp; -+ } espstuff; -+ struct { -+ struct ahhdr *ahp; -+ } ahstuff; -+ struct { -+ struct ipcomphdr *compp; -+ } ipcompstuff; -+ } protostuff; -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ __u8 natt_type; -+ __u16 natt_sport; -+ __u16 natt_dport; -+ int natt_len; -+#endif -+}; -+ -+extern int -+#ifdef PROTO_HANDLER_SINGLE_PARM -+ipsec_rcv(struct sk_buff *skb); -+#else /* PROTO_HANDLER_SINGLE_PARM */ -+ipsec_rcv(struct sk_buff *skb, -+#ifdef NET_21 -+ unsigned short xlen); -+#else /* NET_21 */ -+ struct device *dev, -+ struct options *opt, -+ __u32 daddr, -+ unsigned short len, -+ __u32 saddr, -+ int redo, -+ struct inet_protocol *protocol); -+#endif /* NET_21 */ -+#endif /* PROTO_HANDLER_SINGLE_PARM */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int debug_rcv; -+#endif /* CONFIG_IPSEC_DEBUG */ -+#define ipsec_rcv_dmp(_x,_y, _z) if (debug_rcv && sysctl_ipsec_debug_verbose) ipsec_dmp(_x,_y,_z) -+ -+extern int sysctl_ipsec_inbound_policy_check; -+#endif /* __KERNEL__ */ -+ -+#endif /* IPSEC_RCV_H */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.21 2004/04/06 02:49:08 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.20 2004/04/05 19:55:06 mcr -+ * Moved from linux/include/freeswan/ipsec_rcv.h,v -+ * -+ * Revision 1.19 2003/12/15 18:13:09 mcr -+ * when compiling with NAT traversal, don't assume that the -+ * kernel has been patched, unless CONFIG_IPSEC_NAT_NON_ESP -+ * is set. -+ * -+ * Revision 1.18 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.17 2002/09/03 16:32:32 mcr -+ * definitions of ipsec_birth_reply. -+ * -+ * Revision 1.16 2002/05/14 02:36:00 rgb -+ * Change references to _TDB to _IPSA. -+ * -+ * Revision 1.15 2002/04/24 07:36:47 mcr -+ * Moved from ./klips/net/ipsec/ipsec_rcv.h,v -+ * -+ * Revision 1.14 2001/09/07 22:15:48 rgb -+ * Fix for removal of transport layer protocol handler arg in 2.4.4. -+ * -+ * Revision 1.13 2001/06/14 19:35:09 rgb -+ * Update copyright date. -+ * -+ * Revision 1.12 2001/03/16 07:36:44 rgb -+ * Fixed #endif comment to sate compiler. -+ * -+ * Revision 1.11 2000/09/21 04:34:21 rgb -+ * Moved declaration of sysctl_ipsec_inbound_policy_check outside -+ * CONFIG_IPSEC_DEBUG. (MB) -+ * -+ * Revision 1.10 2000/09/18 02:36:10 rgb -+ * Exported sysctl_ipsec_inbound_policy_check for skb_decompress(). -+ * -+ * Revision 1.9 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.8 1999/11/18 04:09:19 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.7 1999/05/25 01:45:37 rgb -+ * Fix version macros for 2.0.x as a module. -+ * -+ * Revision 1.6 1999/05/08 21:24:27 rgb -+ * Add includes for 2.2.x include into net/ipv4/protocol.c -+ * -+ * Revision 1.5 1999/05/05 22:02:32 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.4 1999/04/11 00:28:59 henry -+ * GPL boilerplate -+ * -+ * Revision 1.3 1999/04/06 04:54:27 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.2 1999/01/22 20:06:59 rgb -+ * Fixed cut-and-paste error from ipsec_esp.h. -+ * -+ * Revision 1.1 1999/01/21 20:29:12 rgb -+ * Converted from transform switching to algorithm switching. -+ * -+ * Log: ipsec_esp.h,v -+ * Revision 1.4 1998/08/12 00:07:32 rgb -+ * Added data structures for new xforms: null, {,3}dessha1. -+ * -+ * Revision 1.3 1998/07/14 15:57:01 rgb -+ * Add #ifdef __KERNEL__ to protect kernel-only structures. -+ * -+ * Revision 1.2 1998/06/25 19:33:46 rgb -+ * Add prototype for protocol receive function. -+ * Rearrange for more logical layout. -+ * -+ * Revision 1.1 1998/06/18 21:27:45 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.6 1998/06/05 02:28:08 rgb -+ * Minor comment fix. -+ * -+ * Revision 1.5 1998/05/27 22:34:00 rgb -+ * Changed structures to accomodate key separation. -+ * -+ * Revision 1.4 1998/05/18 22:28:43 rgb -+ * Disable key printing facilities from /proc/net/ipsec_*. -+ * -+ * Revision 1.3 1998/04/21 21:29:07 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.2 1998/04/12 22:03:20 rgb -+ * Updated ESP-3DES-HMAC-MD5-96, -+ * ESP-DES-HMAC-MD5-96, -+ * AH-HMAC-MD5-96, -+ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository -+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts. -+ * -+ * Fixed eroute references in /proc/net/ipsec*. -+ * -+ * Started to patch module unloading memory leaks in ipsec_netlink and -+ * radij tree unloading. -+ * -+ * Revision 1.1 1998/04/09 03:06:00 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:02 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.5 1997/06/03 04:24:48 ji -+ * Added ESP-3DES-MD5-96 transform. -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * Added definitions for new ESP transforms. -+ * -+ * Revision 0.3 1996/11/20 14:35:48 ji -+ * Minor Cleanup. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ -+ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_sa.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,341 @@ -+/* -+ * @(#) Definitions of IPsec Security Association (ipsec_sa) -+ * -+ * Copyright (C) 2001, 2002, 2003 -+ * Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ * This file derived from ipsec_xform.h on 2001/9/18 by mcr. -+ * -+ */ -+ -+/* -+ * This file describes the IPsec Security Association Structure. -+ * -+ * This structure keeps track of a single transform that may be done -+ * to a set of packets. It can describe applying the transform or -+ * apply the reverse. (e.g. compression vs expansion). However, it -+ * only describes one at a time. To describe both, two structures would -+ * be used, but since the sides of the transform are performed -+ * on different machines typically it is usual to have only one side -+ * of each association. -+ * -+ */ -+ -+#ifndef _IPSEC_SA_H_ -+ -+#ifdef __KERNEL__ -+#include "ipsec_stats.h" -+#include "ipsec_life.h" -+#include "ipsec_eroute.h" -+#endif /* __KERNEL__ */ -+#include "ipsec_param.h" -+ -+ -+/* SAs are held in a table. -+ * Entries in this table are referenced by IPsecSAref_t values. -+ * IPsecSAref_t values are conceptually subscripts. Because -+ * we want to allocate the table piece-meal, the subscripting -+ * is implemented with two levels, a bit like paged virtual memory. -+ * This representation mechanism is known as an Iliffe Vector. -+ * -+ * The Main table (AKA the refTable) consists of 2^IPSEC_SA_REF_MAINTABLE_IDX_WIDTH -+ * pointers to subtables. -+ * Each subtable has 2^IPSEC_SA_REF_SUBTABLE_IDX_WIDTH entries, each of which -+ * is a pointer to an SA. -+ * -+ * An IPsecSAref_t contains either an exceptional value (signified by the -+ * high-order bit being on) or a reference to a table entry. A table entry -+ * reference has the subtable subscript in the low-order -+ * IPSEC_SA_REF_SUBTABLE_IDX_WIDTH bits and the Main table subscript -+ * in the next lowest IPSEC_SA_REF_MAINTABLE_IDX_WIDTH bits. -+ * -+ * The Maintable entry for an IPsecSAref_t x, a pointer to its subtable, is -+ * IPsecSAref2table(x). It is of type struct IPsecSArefSubTable *. -+ * -+ * The pointer to the SA for x is IPsecSAref2SA(x). It is of type -+ * struct ipsec_sa*. The macro definition clearly shows the two-level -+ * access needed to find the SA pointer. -+ * -+ * The Maintable is allocated when IPsec is initialized. -+ * Each subtable is allocated when needed, but the first is allocated -+ * when IPsec is initialized. -+ * -+ * IPsecSAref_t is designed to be smaller than an NFmark so that -+ * they can be stored in NFmarks and still leave a few bits for other -+ * purposes. The spare bits are in the low order of the NFmark -+ * but in the high order of the IPsecSAref_t, so conversion is required. -+ * We pick the upper bits of NFmark on the theory that they are less likely to -+ * interfere with more pedestrian uses of nfmark. -+ */ -+ -+ -+typedef unsigned short int IPsecRefTableUnusedCount; -+ -+#define IPSEC_SA_REF_TABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH) -+ -+#ifdef __KERNEL__ -+#if ((IPSEC_SA_REF_TABLE_IDX_WIDTH - (1 + IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)) < 0) -+#error "IPSEC_SA_REF_TABLE_IDX_WIDTH("IPSEC_SA_REF_TABLE_IDX_WIDTH") MUST be < 1 + IPSEC_SA_REF_MAINTABLE_IDX_WIDTH("IPSEC_SA_REF_MAINTABLE_IDX_WIDTH")" -+#endif -+ -+#define IPSEC_SA_REF_SUBTABLE_IDX_WIDTH (IPSEC_SA_REF_TABLE_IDX_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH) -+ -+#define IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_MAINTABLE_IDX_WIDTH) -+#define IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) -+ -+#ifdef CONFIG_NETFILTER -+#define IPSEC_SA_REF_HOST_FIELD(x) ((struct sk_buff*)(x))->nfmark -+#define IPSEC_SA_REF_HOST_FIELD_TYPE typeof(IPSEC_SA_REF_HOST_FIELD(NULL)) -+#else /* CONFIG_NETFILTER */ -+/* just make it work for now, it doesn't matter, since there is no nfmark */ -+#define IPSEC_SA_REF_HOST_FIELD_TYPE unsigned long -+#endif /* CONFIG_NETFILTER */ -+#define IPSEC_SA_REF_HOST_FIELD_WIDTH (8 * sizeof(IPSEC_SA_REF_HOST_FIELD_TYPE)) -+#define IPSEC_SA_REF_FIELD_WIDTH (8 * sizeof(IPsecSAref_t)) -+ -+#define IPSEC_SA_REF_MASK (IPSEC_SAREF_NULL >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH)) -+#define IPSEC_SA_REF_TABLE_MASK ((IPSEC_SAREF_NULL >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)) << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) -+#define IPSEC_SA_REF_ENTRY_MASK (IPSEC_SAREF_NULL >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_SUBTABLE_IDX_WIDTH)) -+ -+#define IPsecSAref2table(x) (((x) & IPSEC_SA_REF_TABLE_MASK) >> IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) -+#define IPsecSAref2entry(x) ((x) & IPSEC_SA_REF_ENTRY_MASK) -+#define IPsecSArefBuild(x,y) (((x) << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) + (y)) -+ -+#define IPsecSAref2SA(x) (ipsec_sadb.refTable[IPsecSAref2table(x)]->entry[IPsecSAref2entry(x)]) -+#define IPsecSA2SAref(x) ((x)->ips_ref) -+ -+#define EMT_INBOUND 0x01 /* SA direction, 1=inbound */ -+ -+/* 'struct ipsec_sa' should be 64bit aligned when allocated. */ -+struct ipsec_sa -+{ -+ IPsecSAref_t ips_ref; /* reference table entry number */ -+ atomic_t ips_refcount; /* reference count for this struct */ -+ struct ipsec_sa *ips_hnext; /* next in hash chain */ -+ struct ipsec_sa *ips_inext; /* pointer to next xform */ -+ struct ipsec_sa *ips_onext; /* pointer to prev xform */ -+ -+ struct ifnet *ips_rcvif; /* related rcv encap interface */ -+ -+ ip_said ips_said; /* SA ID */ -+ -+ __u32 ips_seq; /* seq num of msg that initiated this SA */ -+ __u32 ips_pid; /* PID of process that initiated this SA */ -+ __u8 ips_authalg; /* auth algorithm for this SA */ -+ __u8 ips_encalg; /* enc algorithm for this SA */ -+ -+ struct ipsec_stats ips_errs; -+ -+ __u8 ips_replaywin; /* replay window size */ -+ __u8 ips_state; /* state of SA */ -+ __u32 ips_replaywin_lastseq; /* last pkt sequence num */ -+ __u64 ips_replaywin_bitmap; /* bitmap of received pkts */ -+ __u32 ips_replaywin_maxdiff; /* max pkt sequence difference */ -+ -+ __u32 ips_flags; /* generic xform flags */ -+ -+ -+ struct ipsec_lifetimes ips_life; /* lifetime records */ -+ -+ /* selector information */ -+ __u8 ips_transport_protocol; /* protocol for this SA, if ports are involved */ -+ struct sockaddr*ips_addr_s; /* src sockaddr */ -+ struct sockaddr*ips_addr_d; /* dst sockaddr */ -+ struct sockaddr*ips_addr_p; /* proxy sockaddr */ -+ __u16 ips_addr_s_size; -+ __u16 ips_addr_d_size; -+ __u16 ips_addr_p_size; -+ ip_address ips_flow_s; -+ ip_address ips_flow_d; -+ ip_address ips_mask_s; -+ ip_address ips_mask_d; -+ -+ __u16 ips_key_bits_a; /* size of authkey in bits */ -+ __u16 ips_auth_bits; /* size of authenticator in bits */ -+ __u16 ips_key_bits_e; /* size of enckey in bits */ -+ __u16 ips_iv_bits; /* size of IV in bits */ -+ __u8 ips_iv_size; -+ __u16 ips_key_a_size; -+ __u16 ips_key_e_size; -+ -+ caddr_t ips_key_a; /* authentication key */ -+ caddr_t ips_key_e; /* encryption key */ -+ caddr_t ips_iv; /* Initialisation Vector */ -+ -+ struct ident ips_ident_s; /* identity src */ -+ struct ident ips_ident_d; /* identity dst */ -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+ __u16 ips_comp_adapt_tries; /* ipcomp self-adaption tries */ -+ __u16 ips_comp_adapt_skip; /* ipcomp self-adaption to-skip */ -+ __u64 ips_comp_ratio_cbytes; /* compressed bytes */ -+ __u64 ips_comp_ratio_dbytes; /* decompressed (or uncompressed) bytes */ -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ __u8 ips_natt_type; -+ __u8 ips_natt_reserved[3]; -+ __u16 ips_natt_sport; -+ __u16 ips_natt_dport; -+ -+ struct sockaddr *ips_natt_oa; -+ __u16 ips_natt_oa_size; -+ __u16 ips_natt_reserved2; -+#endif -+ -+#if 0 -+ __u32 ips_sens_dpd; -+ __u8 ips_sens_sens_level; -+ __u8 ips_sens_sens_len; -+ __u64* ips_sens_sens_bitmap; -+ __u8 ips_sens_integ_level; -+ __u8 ips_sens_integ_len; -+ __u64* ips_sens_integ_bitmap; -+#endif -+ struct ipsec_alg_enc *ips_alg_enc; -+ struct ipsec_alg_auth *ips_alg_auth; -+ IPsecSAref_t ips_ref_rel; -+}; -+ -+struct IPsecSArefSubTable -+{ -+ struct ipsec_sa* entry[IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES]; -+}; -+ -+struct ipsec_sadb { -+ struct IPsecSArefSubTable* refTable[IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES]; -+ IPsecSAref_t refFreeList[IPSEC_SA_REF_FREELIST_NUM_ENTRIES]; -+ int refFreeListHead; -+ int refFreeListTail; -+ IPsecSAref_t refFreeListCont; -+ IPsecSAref_t said_hash[SADB_HASHMOD]; -+ spinlock_t sadb_lock; -+}; -+ -+extern struct ipsec_sadb ipsec_sadb; -+ -+extern int ipsec_SAref_recycle(void); -+extern int ipsec_SArefSubTable_alloc(unsigned table); -+extern int ipsec_saref_freelist_init(void); -+extern int ipsec_sadb_init(void); -+extern struct ipsec_sa *ipsec_sa_alloc(int*error); /* pass in error var by pointer */ -+extern IPsecSAref_t ipsec_SAref_alloc(int*erorr); /* pass in error var by pointer */ -+extern int ipsec_sa_free(struct ipsec_sa* ips); -+extern int ipsec_sa_put(struct ipsec_sa *ips); -+extern int ipsec_sa_add(struct ipsec_sa *ips); -+extern int ipsec_sa_del(struct ipsec_sa *ips); -+extern int ipsec_sa_delchain(struct ipsec_sa *ips); -+extern int ipsec_sadb_cleanup(__u8 proto); -+extern int ipsec_sadb_free(void); -+extern int ipsec_sa_wipe(struct ipsec_sa *ips); -+#endif /* __KERNEL__ */ -+ -+enum ipsec_direction { -+ ipsec_incoming = 1, -+ ipsec_outgoing = 2 -+}; -+ -+#define _IPSEC_SA_H_ -+#endif /* _IPSEC_SA_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.19 2004/04/05 19:55:06 mcr -+ * Moved from linux/include/freeswan/ipsec_sa.h,v -+ * -+ * Revision 1.18 2004/04/05 19:41:05 mcr -+ * merged alg-branch code. -+ * -+ * Revision 1.17.2.1 2003/12/22 15:25:52 jjo -+ * . Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.17 2003/12/10 01:20:06 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.16 2003/10/31 02:27:05 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.15.4.1 2003/10/29 01:10:19 mcr -+ * elimited "struct sa_id" -+ * -+ * Revision 1.15 2003/05/11 00:53:09 mcr -+ * IPsecSAref_t and macros were moved to freeswan.h. -+ * -+ * Revision 1.14 2003/02/12 19:31:55 rgb -+ * Fixed bug in "file seen" machinery. -+ * Updated copyright year. -+ * -+ * Revision 1.13 2003/01/30 02:31:52 rgb -+ * -+ * Re-wrote comments describing SAref system for accuracy. -+ * Rename SAref table macro names for clarity. -+ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. -+ * Transmit error code through to caller from callee for better diagnosis of problems. -+ * Enclose all macro arguments in parens to avoid any possible obscrure bugs. -+ * -+ * Revision 1.12 2002/10/07 18:31:19 rgb -+ * Change comment to reflect the flexible nature of the main and sub-table widths. -+ * Added a counter for the number of unused entries in each subtable. -+ * Further break up host field type macro to host field. -+ * Move field width sanity checks to ipsec_sa.c -+ * Define a mask for an entire saref. -+ * -+ * Revision 1.11 2002/09/20 15:40:33 rgb -+ * Re-write most of the SAref macros and types to eliminate any pointer references to Entrys. -+ * Fixed SAref/nfmark macros. -+ * Rework saref freeslist. -+ * Place all ipsec sadb globals into one struct. -+ * Restrict some bits to kernel context for use to klips utils. -+ * -+ * Revision 1.10 2002/09/20 05:00:34 rgb -+ * Update copyright date. -+ * -+ * Revision 1.9 2002/09/17 17:19:29 mcr -+ * make it compile even if there is no netfilter - we lost -+ * functionality, but it works, especially on 2.2. -+ * -+ * Revision 1.8 2002/07/28 22:59:53 mcr -+ * clarified/expanded one comment. -+ * -+ * Revision 1.7 2002/07/26 08:48:31 rgb -+ * Added SA ref table code. -+ * -+ * Revision 1.6 2002/05/31 17:27:48 rgb -+ * Comment fix. -+ * -+ * Revision 1.5 2002/05/27 18:55:03 rgb -+ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT. -+ * -+ * Revision 1.4 2002/05/23 07:13:36 rgb -+ * Convert "usecount" to "refcount" to remove ambiguity. -+ * -+ * Revision 1.3 2002/04/24 07:36:47 mcr -+ * Moved from ./klips/net/ipsec/ipsec_sa.h,v -+ * -+ * Revision 1.2 2001/11/26 09:16:15 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:24:58 mcr -+ * struct tdb -> struct ipsec_sa. -+ * sa(tdb) manipulation functions renamed and moved to ipsec_sa.c -+ * ipsec_xform.c removed. header file still contains useful things. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_sha1.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,79 @@ -+/* -+ * RCSID $Id$ -+ */ -+ -+/* -+ * Here is the original comment from the distribution: -+ -+SHA-1 in C -+By Steve Reid -+100% Public Domain -+ -+ * Adapted for use by the IPSEC code by John Ioannidis -+ */ -+ -+ -+#ifndef _IPSEC_SHA1_H_ -+#define _IPSEC_SHA1_H_ -+ -+typedef struct -+{ -+ __u32 state[5]; -+ __u32 count[2]; -+ __u8 buffer[64]; -+} SHA1_CTX; -+ -+void SHA1Transform(__u32 state[5], __u8 buffer[64]); -+void SHA1Init(void *context); -+void SHA1Update(void *context, unsigned char *data, __u32 len); -+void SHA1Final(unsigned char digest[20], void *context); -+ -+ -+#endif /* _IPSEC_SHA1_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.8 2004/04/05 19:55:07 mcr -+ * Moved from linux/include/freeswan/ipsec_sha1.h,v -+ * -+ * Revision 1.7 2002/09/10 01:45:09 mcr -+ * changed type of MD5_CTX and SHA1_CTX to void * so that -+ * the function prototypes would match, and could be placed -+ * into a pointer to a function. -+ * -+ * Revision 1.6 2002/04/24 07:36:47 mcr -+ * Moved from ./klips/net/ipsec/ipsec_sha1.h,v -+ * -+ * Revision 1.5 1999/12/13 13:59:13 rgb -+ * Quick fix to argument size to Update bugs. -+ * -+ * Revision 1.4 1999/12/07 18:16:23 rgb -+ * Fixed comments at end of #endif lines. -+ * -+ * Revision 1.3 1999/04/06 04:54:27 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.2 1998/11/30 13:22:54 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.1 1998/06/18 21:27:50 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.2 1998/04/23 20:54:05 rgb -+ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when -+ * verified. -+ * -+ * Revision 1.1 1998/04/09 03:04:21 henry -+ * sources moved up from linux/net/ipsec -+ * these two include files modified not to include others except in kernel -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:04 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * New transform -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_stats.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,75 @@ -+/* -+ * @(#) definition of ipsec_stats structure -+ * -+ * Copyright (C) 2001 Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ */ -+ -+/* -+ * This file describes the errors/statistics that FreeSWAN collects. -+ */ -+ -+#ifndef _IPSEC_STATS_H_ -+ -+struct ipsec_stats { -+ __u32 ips_alg_errs; /* number of algorithm errors */ -+ __u32 ips_auth_errs; /* # of authentication errors */ -+ __u32 ips_encsize_errs; /* # of encryption size errors*/ -+ __u32 ips_encpad_errs; /* # of encryption pad errors*/ -+ __u32 ips_replaywin_errs; /* # of pkt sequence errors */ -+}; -+ -+extern int ipsec_snprintf(char * buf, ssize_t size, const char *fmt, ...); -+ -+#define _IPSEC_STATS_H_ -+#endif /* _IPSEC_STATS_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.6 2004/04/05 19:55:07 mcr -+ * Moved from linux/include/freeswan/ipsec_stats.h,v -+ * -+ * Revision 1.5 2004/04/05 19:41:05 mcr -+ * merged alg-branch code. -+ * -+ * Revision 1.4 2004/03/28 20:27:19 paul -+ * Included tested and confirmed fixes mcr made and dhr verified for -+ * snprint statements. Changed one other snprintf to use ipsec_snprintf -+ * so it wouldnt break compatibility with 2.0/2.2 kernels. Verified with -+ * dhr. (thanks dhr!) -+ * -+ * Revision 1.4 2004/03/24 01:58:31 mcr -+ * sprintf->snprintf for formatting into proc buffer. -+ * -+ * Revision 1.3.34.1 2004/04/05 04:30:46 mcr -+ * patches for alg-branch to compile/work with 2.x openswan -+ * -+ * Revision 1.3 2002/04/24 07:36:47 mcr -+ * Moved from ./klips/net/ipsec/ipsec_stats.h,v -+ * -+ * Revision 1.2 2001/11/26 09:16:16 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:27:00 mcr -+ * statistics moved to seperate structure. -+ * -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_tunnel.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,265 @@ -+/* -+ * IPSEC tunneling code -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+ -+#ifdef NET_21 -+# define DEV_QUEUE_XMIT(skb, device, pri) {\ -+ skb->dev = device; \ -+ neigh_compat_output(skb); \ -+ /* skb->dst->output(skb); */ \ -+ } -+# define ICMP_SEND(skb_in, type, code, info, dev) \ -+ icmp_send(skb_in, type, code, htonl(info)) -+# define IP_SEND(skb, dev) \ -+ ip_send(skb); -+#else /* NET_21 */ -+# define DEV_QUEUE_XMIT(skb, device, pri) {\ -+ dev_queue_xmit(skb, device, pri); \ -+ } -+# define ICMP_SEND(skb_in, type, code, info, dev) \ -+ icmp_send(skb_in, type, code, info, dev) -+# define IP_SEND(skb, dev) \ -+ if(ntohs(iph->tot_len) > physmtu) { \ -+ ip_fragment(NULL, skb, dev, 0); \ -+ ipsec_kfree_skb(skb); \ -+ } else { \ -+ dev_queue_xmit(skb, dev, SOPRI_NORMAL); \ -+ } -+#endif /* NET_21 */ -+ -+ -+/* -+ * Heavily based on drivers/net/new_tunnel.c. Lots -+ * of ideas also taken from the 2.1.x version of drivers/net/shaper.c -+ */ -+ -+struct ipsectunnelconf -+{ -+ __u32 cf_cmd; -+ union -+ { -+ char cfu_name[12]; -+ } cf_u; -+#define cf_name cf_u.cfu_name -+}; -+ -+#define IPSEC_SET_DEV (SIOCDEVPRIVATE) -+#define IPSEC_DEL_DEV (SIOCDEVPRIVATE + 1) -+#define IPSEC_CLR_DEV (SIOCDEVPRIVATE + 2) -+ -+#ifdef __KERNEL__ -+#include -+#ifndef KERNEL_VERSION -+# define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -+#endif -+struct ipsecpriv -+{ -+ struct sk_buff_head sendq; -+ struct device *dev; -+ struct wait_queue *wait_queue; -+ char locked; -+ int (*hard_start_xmit) (struct sk_buff *skb, -+ struct device *dev); -+ int (*hard_header) (struct sk_buff *skb, -+ struct device *dev, -+ unsigned short type, -+ void *daddr, -+ void *saddr, -+ unsigned len); -+#ifdef NET_21 -+ int (*rebuild_header)(struct sk_buff *skb); -+#else /* NET_21 */ -+ int (*rebuild_header)(void *buff, struct device *dev, -+ unsigned long raddr, struct sk_buff *skb); -+#endif /* NET_21 */ -+ int (*set_mac_address)(struct device *dev, void *addr); -+#ifndef NET_21 -+ void (*header_cache_bind)(struct hh_cache **hhp, struct device *dev, -+ unsigned short htype, __u32 daddr); -+#endif /* !NET_21 */ -+ void (*header_cache_update)(struct hh_cache *hh, struct device *dev, unsigned char * haddr); -+ struct net_device_stats *(*get_stats)(struct device *dev); -+ struct net_device_stats mystats; -+ int mtu; /* What is the desired MTU? */ -+}; -+ -+extern char ipsec_tunnel_c_version[]; -+ -+extern struct device *ipsecdevices[IPSEC_NUM_IF]; -+ -+int ipsec_tunnel_init_devices(void); -+ -+/* void */ int ipsec_tunnel_cleanup_devices(void); -+ -+extern /* void */ int ipsec_init(void); -+ -+extern int ipsec_tunnel_start_xmit(struct sk_buff *skb, struct device *dev); -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int debug_tunnel; -+extern int sysctl_ipsec_debug_verbose; -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif /* __KERNEL__ */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+#define DB_TN_INIT 0x0001 -+#define DB_TN_PROCFS 0x0002 -+#define DB_TN_XMIT 0x0010 -+#define DB_TN_OHDR 0x0020 -+#define DB_TN_CROUT 0x0040 -+#define DB_TN_OXFS 0x0080 -+#define DB_TN_REVEC 0x0100 -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.29 2004/04/05 19:55:07 mcr -+ * Moved from linux/include/freeswan/ipsec_tunnel.h,v -+ * -+ * Revision 1.28 2003/06/24 20:22:32 mcr -+ * added new global: ipsecdevices[] so that we can keep track of -+ * the ipsecX devices. They will be referenced with dev_hold(), -+ * so 2.2 may need this as well. -+ * -+ * Revision 1.27 2003/04/03 17:38:09 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * -+ * Revision 1.26 2003/02/12 19:32:20 rgb -+ * Updated copyright year. -+ * -+ * Revision 1.25 2002/05/27 18:56:07 rgb -+ * Convert to dynamic ipsec device allocation. -+ * -+ * Revision 1.24 2002/04/24 07:36:48 mcr -+ * Moved from ./klips/net/ipsec/ipsec_tunnel.h,v -+ * -+ * Revision 1.23 2001/11/06 19:50:44 rgb -+ * Moved IP_SEND, ICMP_SEND, DEV_QUEUE_XMIT macros to ipsec_tunnel.h for -+ * use also by pfkey_v2_parser.c -+ * -+ * Revision 1.22 2001/09/15 16:24:05 rgb -+ * Re-inject first and last HOLD packet when an eroute REPLACE is done. -+ * -+ * Revision 1.21 2001/06/14 19:35:10 rgb -+ * Update copyright date. -+ * -+ * Revision 1.20 2000/09/15 11:37:02 rgb -+ * Merge in heavily modified Svenning Soerensen's -+ * IPCOMP zlib deflate code. -+ * -+ * Revision 1.19 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.18 2000/07/28 13:50:54 rgb -+ * Changed enet_statistics to net_device_stats and added back compatibility -+ * for pre-2.1.19. -+ * -+ * Revision 1.17 1999/11/19 01:12:15 rgb -+ * Purge unneeded proc_info prototypes, now that static linking uses -+ * dynamic proc_info registration. -+ * -+ * Revision 1.16 1999/11/18 18:51:00 rgb -+ * Changed all device registrations for static linking to -+ * dynamic to reduce the number and size of patches. -+ * -+ * Revision 1.15 1999/11/18 04:14:21 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * Added CONFIG_PROC_FS compiler directives in case it is shut off. -+ * Added Marc Boucher's 2.3.25 proc patches. -+ * -+ * Revision 1.14 1999/05/25 02:50:10 rgb -+ * Fix kernel version macros for 2.0.x static linking. -+ * -+ * Revision 1.13 1999/05/25 02:41:06 rgb -+ * Add ipsec_klipsdebug support for static linking. -+ * -+ * Revision 1.12 1999/05/05 22:02:32 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.11 1999/04/29 15:19:50 rgb -+ * Add return values to init and cleanup functions. -+ * -+ * Revision 1.10 1999/04/16 16:02:39 rgb -+ * Bump up macro to 4 ipsec I/Fs. -+ * -+ * Revision 1.9 1999/04/15 15:37:25 rgb -+ * Forward check changes from POST1_00 branch. -+ * -+ * Revision 1.5.2.1 1999/04/02 04:26:14 rgb -+ * Backcheck from HEAD, pre1.0. -+ * -+ * Revision 1.8 1999/04/11 00:29:01 henry -+ * GPL boilerplate -+ * -+ * Revision 1.7 1999/04/06 04:54:28 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.6 1999/03/31 05:44:48 rgb -+ * Keep PMTU reduction private. -+ * -+ * Revision 1.5 1999/02/10 22:31:20 rgb -+ * Change rebuild_header member to reflect generality of link layer. -+ * -+ * Revision 1.4 1998/12/01 13:22:04 rgb -+ * Added support for debug printing of version info. -+ * -+ * Revision 1.3 1998/07/29 20:42:46 rgb -+ * Add a macro for clearing all tunnel devices. -+ * Rearrange structures and declarations for sharing with userspace. -+ * -+ * Revision 1.2 1998/06/25 20:01:45 rgb -+ * Make prototypes available for ipsec_init and ipsec proc_dir_entries -+ * for static linking. -+ * -+ * Revision 1.1 1998/06/18 21:27:50 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.3 1998/05/18 21:51:50 rgb -+ * Added macros for num of I/F's and a procfs debug switch. -+ * -+ * Revision 1.2 1998/04/21 21:29:09 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.1 1998/04/09 03:06:13 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:05 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.5 1997/06/03 04:24:48 ji -+ * Added transport mode. -+ * Changed the way routing is done. -+ * Lots of bug fixes. -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:39:04 ji -+ * Minor cleanups. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_xform.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,254 @@ -+/* -+ * Definitions relevant to IPSEC transformations -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * COpyright (C) 2003 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef _IPSEC_XFORM_H_ -+ -+#include -+ -+#define XF_NONE 0 /* No transform set */ -+#define XF_IP4 1 /* IPv4 inside IPv4 */ -+#define XF_AHMD5 2 /* AH MD5 */ -+#define XF_AHSHA 3 /* AH SHA */ -+#define XF_ESP3DES 5 /* ESP DES3-CBC */ -+#define XF_AHHMACMD5 6 /* AH-HMAC-MD5 with opt replay prot */ -+#define XF_AHHMACSHA1 7 /* AH-HMAC-SHA1 with opt replay prot */ -+#define XF_ESP3DESMD5 9 /* triple DES, HMAC-MD-5, 128-bits of authentication */ -+#define XF_ESP3DESMD596 10 /* triple DES, HMAC-MD-5, 96-bits of authentication */ -+#define XF_ESPNULLMD596 12 /* NULL, HMAC-MD-5 with 96-bits of authentication */ -+#define XF_ESPNULLSHA196 13 /* NULL, HMAC-SHA-1 with 96-bits of authentication */ -+#define XF_ESP3DESSHA196 14 /* triple DES, HMAC-SHA-1, 96-bits of authentication */ -+#define XF_IP6 15 /* IPv6 inside IPv6 */ -+#define XF_COMPDEFLATE 16 /* IPCOMP deflate */ -+ -+#define XF_CLR 126 /* Clear SA table */ -+#define XF_DEL 127 /* Delete SA */ -+ -+/* IPsec AH transform values -+ * RFC 2407 -+ * draft-ietf-ipsec-doi-tc-mib-02.txt -+ */ -+ -+#define AH_NONE 0 -+#define AH_MD5 2 -+#define AH_SHA 3 -+/* draft-ietf-ipsec-ciph-aes-cbc-03.txt */ -+#define AH_SHA2_256 5 -+#define AH_SHA2_384 6 -+#define AH_SHA2_512 7 -+#define AH_RIPEMD 8 -+#define AH_MAX 15 -+ -+/* IPsec ESP transform values */ -+ -+#define ESP_NONE 0 -+#define ESP_DES 2 -+#define ESP_3DES 3 -+#define ESP_RC5 4 -+#define ESP_IDEA 5 -+#define ESP_CAST 6 -+#define ESP_BLOWFISH 7 -+#define ESP_3IDEA 8 -+#define ESP_RC4 10 -+#define ESP_NULL 11 -+#define ESP_AES 12 -+ -+/* as draft-ietf-ipsec-ciph-aes-cbc-02.txt */ -+#define ESP_MARS 249 -+#define ESP_RC6 250 -+#define ESP_SERPENT 252 -+#define ESP_TWOFISH 253 -+ -+/* IPCOMP transform values */ -+ -+#define IPCOMP_NONE 0 -+#define IPCOMP_OUI 1 -+#define IPCOMP_DEFLAT 2 -+#define IPCOMP_LZS 3 -+#define IPCOMP_V42BIS 4 -+ -+#define XFT_AUTH 0x0001 -+#define XFT_CONF 0x0100 -+ -+/* available if CONFIG_IPSEC_DEBUG is defined */ -+#define DB_XF_INIT 0x0001 -+ -+#define PROTO2TXT(x) \ -+ (x) == IPPROTO_AH ? "AH" : \ -+ (x) == IPPROTO_ESP ? "ESP" : \ -+ (x) == IPPROTO_IPIP ? "IPIP" : \ -+ (x) == IPPROTO_COMP ? "COMP" : \ -+ "UNKNOWN_proto" -+static inline const char *enc_name_id (unsigned id) { -+ static char buf[16]; -+ snprintf(buf, sizeof(buf), "_ID%d", id); -+ return buf; -+} -+static inline const char *auth_name_id (unsigned id) { -+ static char buf[16]; -+ snprintf(buf, sizeof(buf), "_ID%d", id); -+ return buf; -+} -+#define IPS_XFORM_NAME(x) \ -+ PROTO2TXT((x)->ips_said.proto), \ -+ (x)->ips_said.proto == IPPROTO_COMP ? \ -+ ((x)->ips_encalg == SADB_X_CALG_DEFLATE ? \ -+ "_DEFLATE" : "_UNKNOWN_comp") : \ -+ (x)->ips_encalg == ESP_NONE ? "" : \ -+ (x)->ips_encalg == ESP_3DES ? "_3DES" : \ -+ (x)->ips_encalg == ESP_AES ? "_AES" : \ -+ (x)->ips_encalg == ESP_SERPENT ? "_SERPENT" : \ -+ (x)->ips_encalg == ESP_TWOFISH ? "_TWOFISH" : \ -+ enc_name_id(x->ips_encalg)/* "_UNKNOWN_encr" */, \ -+ (x)->ips_authalg == AH_NONE ? "" : \ -+ (x)->ips_authalg == AH_MD5 ? "_HMAC_MD5" : \ -+ (x)->ips_authalg == AH_SHA ? "_HMAC_SHA1" : \ -+ (x)->ips_authalg == AH_SHA2_256 ? "_HMAC_SHA2_256" : \ -+ (x)->ips_authalg == AH_SHA2_384 ? "_HMAC_SHA2_384" : \ -+ (x)->ips_authalg == AH_SHA2_512 ? "_HMAC_SHA2_512" : \ -+ auth_name_id(x->ips_authalg) /* "_UNKNOWN_auth" */ \ -+ -+#ifdef __KERNEL__ -+struct ipsec_rcv_state; -+struct ipsec_xmit_state; -+ -+struct xform_functions { -+ enum ipsec_rcv_value (*rcv_checks)(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb); -+ enum ipsec_rcv_value (*rcv_decrypt)(struct ipsec_rcv_state *irs); -+ -+ enum ipsec_rcv_value (*rcv_setup_auth)(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb, -+ __u32 *replay, -+ unsigned char **authenticator); -+ enum ipsec_rcv_value (*rcv_calc_auth)(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb); -+ -+ enum ipsec_xmit_value (*xmit_setup)(struct ipsec_xmit_state *ixs); -+ enum ipsec_xmit_value (*xmit_encrypt)(struct ipsec_xmit_state *ixs); -+ -+ enum ipsec_xmit_value (*xmit_setup_auth)(struct ipsec_xmit_state *ixs, -+ struct sk_buff *skb, -+ __u32 *replay, -+ unsigned char **authenticator); -+ enum ipsec_xmit_value (*xmit_calc_auth)(struct ipsec_xmit_state *ixs, -+ struct sk_buff *skb); -+ int xmit_headroom; -+ int xmit_needtailroom; -+}; -+ -+#endif /* __KERNEL__ */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern void ipsec_dmp(char *s, caddr_t bb, int len); -+#else /* CONFIG_IPSEC_DEBUG */ -+#define ipsec_dmp(_x, _y, _z) -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ -+#define _IPSEC_XFORM_H_ -+#endif /* _IPSEC_XFORM_H_ */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.40 2004/04/06 02:49:08 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.39 2004/04/05 19:55:07 mcr -+ * Moved from linux/include/freeswan/ipsec_xform.h,v -+ * -+ * Revision 1.38 2004/04/05 19:41:05 mcr -+ * merged alg-branch code. -+ * -+ * Revision 1.37 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.36.34.1 2003/12/22 15:25:52 jjo -+ * Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.36 2002/04/24 07:36:48 mcr -+ * Moved from ./klips/net/ipsec/ipsec_xform.h,v -+ * -+ * Revision 1.35 2001/11/26 09:23:51 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.33.2.1 2001/09/25 02:24:58 mcr -+ * struct tdb -> struct ipsec_sa. -+ * sa(tdb) manipulation functions renamed and moved to ipsec_sa.c -+ * ipsec_xform.c removed. header file still contains useful things. -+ * -+ * Revision 1.34 2001/11/06 19:47:17 rgb -+ * Changed lifetime_packets to uint32 from uint64. -+ * -+ * Revision 1.33 2001/09/08 21:13:34 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.32 2001/07/06 07:40:01 rgb -+ * Reformatted for readability. -+ * Added inbound policy checking fields for use with IPIP SAs. -+ * -+ * Revision 1.31 2001/06/14 19:35:11 rgb -+ * Update copyright date. -+ * -+ * Revision 1.30 2001/05/30 08:14:03 rgb -+ * Removed vestiges of esp-null transforms. -+ * -+ * Revision 1.29 2001/01/30 23:42:47 rgb -+ * Allow pfkey msgs from pid other than user context required for ACQUIRE -+ * and subsequent ADD or UDATE. -+ * -+ * Revision 1.28 2000/11/06 04:30:40 rgb -+ * Add Svenning's adaptive content compression. -+ * -+ * Revision 1.27 2000/09/19 00:38:25 rgb -+ * Fixed algorithm name bugs introduced for ipcomp. -+ * -+ * Revision 1.26 2000/09/17 21:36:48 rgb -+ * Added proto2txt macro. -+ * -+ * Revision 1.25 2000/09/17 18:56:47 rgb -+ * Added IPCOMP support. -+ * -+ * Revision 1.24 2000/09/12 19:34:12 rgb -+ * Defined XF_IP6 from Gerhard for ipv6 tunnel support. -+ * -+ * Revision 1.23 2000/09/12 03:23:14 rgb -+ * Cleaned out now unused tdb_xform and tdb_xdata members of struct tdb. -+ * -+ * Revision 1.22 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.21 2000/09/01 18:32:43 rgb -+ * Added (disabled) sensitivity members to tdb struct. -+ * -+ * Revision 1.20 2000/08/30 05:31:01 rgb -+ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst. -+ * Kill remainder of tdb_xform, tdb_xdata, xformsw. -+ * -+ * Revision 1.19 2000/08/01 14:51:52 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.18 2000/01/21 06:17:45 rgb -+ * Tidied up spacing. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/ipsec_xmit.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,176 @@ -+/* -+ * IPSEC tunneling code -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#include "openswan/ipsec_sa.h" -+ -+enum ipsec_xmit_value -+{ -+ IPSEC_XMIT_STOLEN=2, -+ IPSEC_XMIT_PASS=1, -+ IPSEC_XMIT_OK=0, -+ IPSEC_XMIT_ERRMEMALLOC=-1, -+ IPSEC_XMIT_ESP_BADALG=-2, -+ IPSEC_XMIT_BADPROTO=-3, -+ IPSEC_XMIT_ESP_PUSHPULLERR=-4, -+ IPSEC_XMIT_BADLEN=-5, -+ IPSEC_XMIT_AH_BADALG=-6, -+ IPSEC_XMIT_SAIDNOTFOUND=-7, -+ IPSEC_XMIT_SAIDNOTLIVE=-8, -+ IPSEC_XMIT_REPLAYROLLED=-9, -+ IPSEC_XMIT_LIFETIMEFAILED=-10, -+ IPSEC_XMIT_CANNOTFRAG=-11, -+ IPSEC_XMIT_MSSERR=-12, -+ IPSEC_XMIT_ERRSKBALLOC=-13, -+ IPSEC_XMIT_ENCAPFAIL=-14, -+ IPSEC_XMIT_NODEV=-15, -+ IPSEC_XMIT_NOPRIVDEV=-16, -+ IPSEC_XMIT_NOPHYSDEV=-17, -+ IPSEC_XMIT_NOSKB=-18, -+ IPSEC_XMIT_NOIPV6=-19, -+ IPSEC_XMIT_NOIPOPTIONS=-20, -+ IPSEC_XMIT_TTLEXPIRED=-21, -+ IPSEC_XMIT_BADHHLEN=-22, -+ IPSEC_XMIT_PUSHPULLERR=-23, -+ IPSEC_XMIT_ROUTEERR=-24, -+ IPSEC_XMIT_RECURSDETECT=-25, -+ IPSEC_XMIT_IPSENDFAILURE=-26, -+ IPSEC_XMIT_ESPUDP=-27, -+ IPSEC_XMIT_ESPUDP_BADTYPE=-28, -+}; -+ -+struct ipsec_xmit_state -+{ -+ struct sk_buff *skb; /* working skb pointer */ -+ struct device *dev; /* working dev pointer */ -+ struct ipsecpriv *prv; /* Our device' private space */ -+ struct sk_buff *oskb; /* Original skb pointer */ -+ struct net_device_stats *stats; /* This device's statistics */ -+ struct iphdr *iph; /* Our new IP header */ -+ __u32 newdst; /* The other SG's IP address */ -+ __u32 orgdst; /* Original IP destination address */ -+ __u32 orgedst; /* 1st SG's IP address */ -+ __u32 newsrc; /* The new source SG's IP address */ -+ __u32 orgsrc; /* Original IP source address */ -+ __u32 innersrc; /* Innermost IP source address */ -+ int iphlen; /* IP header length */ -+ int pyldsz; /* upper protocol payload size */ -+ int headroom; -+ int tailroom; -+ int authlen; -+ int max_headroom; /* The extra header space needed */ -+ int max_tailroom; /* The extra stuffing needed */ -+ int ll_headroom; /* The extra link layer hard_header space needed */ -+ int tot_headroom; /* The total header space needed */ -+ int tot_tailroom; /* The totalstuffing needed */ -+ __u8 *saved_header; /* saved copy of the hard header */ -+ unsigned short sport, dport; -+ -+ struct sockaddr_encap matcher; /* eroute search key */ -+ struct eroute *eroute; -+ struct ipsec_sa *ipsp, *ipsq; /* ipsec_sa pointers */ -+ char sa_txt[SATOT_BUF]; -+ size_t sa_len; -+ int hard_header_stripped; /* has the hard header been removed yet? */ -+ int hard_header_len; -+ struct device *physdev; -+/* struct device *virtdev; */ -+ short physmtu; -+ short mtudiff; -+#ifdef NET_21 -+ struct rtable *route; -+#endif /* NET_21 */ -+ ip_said outgoing_said; -+#ifdef NET_21 -+ int pass; -+#endif /* NET_21 */ -+ int error; -+ uint32_t eroute_pid; -+ struct ipsec_sa ips; -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ uint8_t natt_type; -+ uint8_t natt_head; -+ uint16_t natt_sport; -+ uint16_t natt_dport; -+#endif -+}; -+ -+enum ipsec_xmit_value -+ipsec_xmit_sanity_check_dev(struct ipsec_xmit_state *ixs); -+ -+enum ipsec_xmit_value -+ipsec_xmit_sanity_check_skb(struct ipsec_xmit_state *ixs); -+ -+enum ipsec_xmit_value -+ipsec_xmit_encap_bundle(struct ipsec_xmit_state *ixs); -+ -+extern void ipsec_extract_ports(struct iphdr * iph, struct sockaddr_encap * er); -+ -+ -+extern int ipsec_xmit_trap_count; -+extern int ipsec_xmit_trap_sendcount; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int debug_tunnel; -+extern int sysctl_ipsec_debug_verbose; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#define debug_xmit debug_tunnel -+ -+#define ipsec_xmit_dmp(_x,_y, _z) if (debug_xmit && sysctl_ipsec_debug_verbose) ipsec_dmp(_x,_y,_z) -+ -+extern int sysctl_ipsec_icmp; -+extern int sysctl_ipsec_tos; -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.9 2004/04/06 02:49:08 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.8 2004/04/05 19:55:07 mcr -+ * Moved from linux/include/freeswan/ipsec_xmit.h,v -+ * -+ * Revision 1.7 2004/02/03 03:11:40 mcr -+ * new xmit type if the UDP encapsulation is wrong. -+ * -+ * Revision 1.6 2003/12/13 19:10:16 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.5 2003/12/10 01:20:06 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.4 2003/12/06 16:37:04 mcr -+ * 1.4.7a X.509 patch applied. -+ * -+ * Revision 1.3 2003/10/31 02:27:05 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.2.4.2 2003/10/29 01:10:19 mcr -+ * elimited "struct sa_id" -+ * -+ * Revision 1.2.4.1 2003/09/21 13:59:38 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.2 2003/06/20 01:42:13 mcr -+ * added counters to measure how many ACQUIREs we send to pluto, -+ * and how many are successfully sent. -+ * -+ * Revision 1.1 2003/02/12 19:31:03 rgb -+ * Refactored from ipsec_tunnel.c -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/passert.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,64 @@ -+/* -+ * sanitize a string into a printable format. -+ * -+ * Copyright (C) 1998-2002 D. Hugh Redelmeier. -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+ -+#include "openswan.h" -+ -+/* our versions of assert: log result */ -+ -+#ifdef DEBUG -+ -+extern void passert_fail(const char *pred_str -+ , const char *file_str, unsigned long line_no) NEVER_RETURNS; -+ -+extern void pexpect_log(const char *pred_str -+ , const char *file_str, unsigned long line_no); -+ -+# define impossible() passert_fail("impossible", __FILE__, __LINE__) -+ -+extern void switch_fail(int n -+ , const char *file_str, unsigned long line_no) NEVER_RETURNS; -+ -+# define bad_case(n) switch_fail((int) n, __FILE__, __LINE__) -+ -+# define passert(pred) { \ -+ if (!(pred)) \ -+ passert_fail(#pred, __FILE__, __LINE__); \ -+ } -+ -+# define pexpect(pred) { \ -+ if (!(pred)) \ -+ pexpect_log(#pred, __FILE__, __LINE__); \ -+ } -+ -+/* assert that an err_t is NULL; evaluate exactly once */ -+# define happy(x) { \ -+ err_t ugh = x; \ -+ if (ugh != NULL) \ -+ passert_fail(ugh, __FILE__, __LINE__); \ -+ } -+ -+#else /*!DEBUG*/ -+ -+# define impossible() abort() -+# define bad_case(n) abort() -+# define passert(pred) { } /* do nothing */ -+# define happy(x) { (void) x; } /* evaluate non-judgementally */ -+ -+#endif /*!DEBUG*/ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/pfkey_debug.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,54 @@ -+/* -+ * sanitize a string into a printable format. -+ * -+ * Copyright (C) 1998-2002 D. Hugh Redelmeier. -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef _FREESWAN_PFKEY_DEBUG_H -+#define _FREESWAN_PFKEY_DEBUG_H -+ -+#ifdef __KERNEL__ -+ -+/* note, kernel version ignores pfkey levels */ -+# define DEBUGGING(level,args...) \ -+ KLIPS_PRINT(debug_pfkey, "klips_debug:" args) -+ -+# define ERROR(args...) printk(KERN_ERR "klips:" args) -+ -+#else -+ -+extern unsigned int pfkey_lib_debug; -+ -+extern void (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1); -+extern void (*pfkey_error_func)(const char *message, ...) PRINTF_LIKE(1); -+ -+#define DEBUGGING(level,args...) if(pfkey_lib_debug & level) { \ -+ if(pfkey_debug_func != NULL) { \ -+ (*pfkey_debug_func)("pfkey_lib_debug:" args); \ -+ } else { \ -+ printf("pfkey_lib_debug:" args); \ -+ } } -+ -+#define ERROR(args...) if(pfkey_error_func != NULL) { \ -+ (*pfkey_error_func)("pfkey_lib_debug:" args); \ -+ } -+ -+# define MALLOC(size) malloc(size) -+# define FREE(obj) free(obj) -+ -+#endif -+ -+#endif ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/openswan/radij.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,280 @@ -+/* -+ * RCSID $Id$ -+ */ -+ -+/* -+ * This file is defived from ${SRC}/sys/net/radix.h of BSD 4.4lite -+ * -+ * Variable and procedure names have been modified so that they don't -+ * conflict with the original BSD code, as a small number of modifications -+ * have been introduced and we may want to reuse this code in BSD. -+ * -+ * The `j' in `radij' is pronounced as a voiceless guttural (like a Greek -+ * chi or a German ch sound (as `doch', not as in `milch'), or even a -+ * spanish j as in Juan. It is not as far back in the throat like -+ * the corresponding Hebrew sound, nor is it a soft breath like the English h. -+ * It has nothing to do with the Dutch ij sound. -+ * -+ * Here is the appropriate copyright notice: -+ */ -+ -+/* -+ * Copyright (c) 1988, 1989, 1993 -+ * The Regents of the University of California. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * This product includes software developed by the University of -+ * California, Berkeley and its contributors. -+ * 4. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * @(#)radix.h 8.1 (Berkeley) 6/10/93 -+ */ -+ -+#ifndef _RADIJ_H_ -+#define _RADIJ_H_ -+ -+/* -+#define RJ_DEBUG -+*/ -+ -+#ifdef __KERNEL__ -+ -+#ifndef __P -+#ifdef __STDC__ -+#define __P(x) x -+#else -+#define __P(x) () -+#endif -+#endif -+ -+/* -+ * Radix search tree node layout. -+ */ -+ -+struct radij_node -+{ -+ struct radij_mask *rj_mklist; /* list of masks contained in subtree */ -+ struct radij_node *rj_p; /* parent */ -+ short rj_b; /* bit offset; -1-index(netmask) */ -+ char rj_bmask; /* node: mask for bit test*/ -+ u_char rj_flags; /* enumerated next */ -+#define RJF_NORMAL 1 /* leaf contains normal route */ -+#define RJF_ROOT 2 /* leaf is root leaf for tree */ -+#define RJF_ACTIVE 4 /* This node is alive (for rtfree) */ -+ union { -+ struct { /* leaf only data: */ -+ caddr_t rj_Key; /* object of search */ -+ caddr_t rj_Mask; /* netmask, if present */ -+ struct radij_node *rj_Dupedkey; -+ } rj_leaf; -+ struct { /* node only data: */ -+ int rj_Off; /* where to start compare */ -+ struct radij_node *rj_L;/* progeny */ -+ struct radij_node *rj_R;/* progeny */ -+ }rj_node; -+ } rj_u; -+#ifdef RJ_DEBUG -+ int rj_info; -+ struct radij_node *rj_twin; -+ struct radij_node *rj_ybro; -+#endif -+}; -+ -+#define rj_dupedkey rj_u.rj_leaf.rj_Dupedkey -+#define rj_key rj_u.rj_leaf.rj_Key -+#define rj_mask rj_u.rj_leaf.rj_Mask -+#define rj_off rj_u.rj_node.rj_Off -+#define rj_l rj_u.rj_node.rj_L -+#define rj_r rj_u.rj_node.rj_R -+ -+/* -+ * Annotations to tree concerning potential routes applying to subtrees. -+ */ -+ -+extern struct radij_mask { -+ short rm_b; /* bit offset; -1-index(netmask) */ -+ char rm_unused; /* cf. rj_bmask */ -+ u_char rm_flags; /* cf. rj_flags */ -+ struct radij_mask *rm_mklist; /* more masks to try */ -+ caddr_t rm_mask; /* the mask */ -+ int rm_refs; /* # of references to this struct */ -+} *rj_mkfreelist; -+ -+#define MKGet(m) {\ -+ if (rj_mkfreelist) {\ -+ m = rj_mkfreelist; \ -+ rj_mkfreelist = (m)->rm_mklist; \ -+ } else \ -+ R_Malloc(m, struct radij_mask *, sizeof (*(m))); }\ -+ -+#define MKFree(m) { (m)->rm_mklist = rj_mkfreelist; rj_mkfreelist = (m);} -+ -+struct radij_node_head { -+ struct radij_node *rnh_treetop; -+ int rnh_addrsize; /* permit, but not require fixed keys */ -+ int rnh_pktsize; /* permit, but not require fixed keys */ -+#if 0 -+ struct radij_node *(*rnh_addaddr) /* add based on sockaddr */ -+ __P((void *v, void *mask, -+ struct radij_node_head *head, struct radij_node nodes[])); -+#endif -+ int (*rnh_addaddr) /* add based on sockaddr */ -+ __P((void *v, void *mask, -+ struct radij_node_head *head, struct radij_node nodes[])); -+ struct radij_node *(*rnh_addpkt) /* add based on packet hdr */ -+ __P((void *v, void *mask, -+ struct radij_node_head *head, struct radij_node nodes[])); -+#if 0 -+ struct radij_node *(*rnh_deladdr) /* remove based on sockaddr */ -+ __P((void *v, void *mask, struct radij_node_head *head)); -+#endif -+ int (*rnh_deladdr) /* remove based on sockaddr */ -+ __P((void *v, void *mask, struct radij_node_head *head, struct radij_node **node)); -+ struct radij_node *(*rnh_delpkt) /* remove based on packet hdr */ -+ __P((void *v, void *mask, struct radij_node_head *head)); -+ struct radij_node *(*rnh_matchaddr) /* locate based on sockaddr */ -+ __P((void *v, struct radij_node_head *head)); -+ struct radij_node *(*rnh_matchpkt) /* locate based on packet hdr */ -+ __P((void *v, struct radij_node_head *head)); -+ int (*rnh_walktree) /* traverse tree */ -+ __P((struct radij_node_head *head, int (*f)(struct radij_node *rn, void *w), void *w)); -+ struct radij_node rnh_nodes[3]; /* empty tree for common case */ -+}; -+ -+ -+#define Bcmp(a, b, n) memcmp(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n)) -+#define Bcopy(a, b, n) memmove(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n)) -+#define Bzero(p, n) memset((caddr_t)(p), 0, (unsigned)(n)) -+#define R_Malloc(p, t, n) ((p = (t) kmalloc((size_t)(n), GFP_ATOMIC)), Bzero((p),(n))) -+#define Free(p) kfree((caddr_t)p); -+ -+void rj_init __P((void)); -+int rj_inithead __P((void **, int)); -+int rj_refines __P((void *, void *)); -+int rj_walktree __P((struct radij_node_head *head, int (*f)(struct radij_node *rn, void *w), void *w)); -+struct radij_node -+ *rj_addmask __P((void *, int, int)) /* , rgb */ ; -+int /* * */ rj_addroute __P((void *, void *, struct radij_node_head *, -+ struct radij_node [2])) /* , rgb */ ; -+int /* * */ rj_delete __P((void *, void *, struct radij_node_head *, struct radij_node **)) /* , rgb */ ; -+struct radij_node /* rgb */ -+ *rj_insert __P((void *, struct radij_node_head *, int *, -+ struct radij_node [2])), -+ *rj_match __P((void *, struct radij_node_head *)), -+ *rj_newpair __P((void *, int, struct radij_node[2])), -+ *rj_search __P((void *, struct radij_node *)), -+ *rj_search_m __P((void *, struct radij_node *, void *)); -+ -+void rj_deltree(struct radij_node_head *); -+void rj_delnodes(struct radij_node *); -+void rj_free_mkfreelist(void); -+int radijcleartree(void); -+int radijcleanup(void); -+ -+extern struct radij_node_head *mask_rjhead; -+extern int maj_keylen; -+#endif /* __KERNEL__ */ -+ -+#endif /* _RADIJ_H_ */ -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.13 2004/04/05 19:55:08 mcr -+ * Moved from linux/include/freeswan/radij.h,v -+ * -+ * Revision 1.12 2002/04/24 07:36:48 mcr -+ * Moved from ./klips/net/ipsec/radij.h,v -+ * -+ * Revision 1.11 2001/09/20 15:33:00 rgb -+ * Min/max cleanup. -+ * -+ * Revision 1.10 1999/11/18 04:09:20 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.9 1999/05/05 22:02:33 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.8 1999/04/29 15:24:58 rgb -+ * Add check for existence of macros min/max. -+ * -+ * Revision 1.7 1999/04/11 00:29:02 henry -+ * GPL boilerplate -+ * -+ * Revision 1.6 1999/04/06 04:54:29 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.5 1999/01/22 06:30:32 rgb -+ * 64-bit clean-up. -+ * -+ * Revision 1.4 1998/11/30 13:22:55 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.3 1998/10/25 02:43:27 rgb -+ * Change return type on rj_addroute and rj_delete and add and argument -+ * to the latter to be able to transmit more infomation about errors. -+ * -+ * Revision 1.2 1998/07/14 18:09:51 rgb -+ * Add a routine to clear eroute table. -+ * Added #ifdef __KERNEL__ directives to restrict scope of header. -+ * -+ * Revision 1.1 1998/06/18 21:30:22 henry -+ * move sources from klips/src to klips/net/ipsec to keep stupid kernel -+ * build scripts happier about symlinks -+ * -+ * Revision 1.4 1998/05/25 20:34:16 rgb -+ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions. -+ * -+ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and -+ * add ipsec_rj_walker_delete. -+ * -+ * Recover memory for eroute table on unload of module. -+ * -+ * Revision 1.3 1998/04/22 16:51:37 rgb -+ * Tidy up radij debug code from recent rash of modifications to debug code. -+ * -+ * Revision 1.2 1998/04/14 17:30:38 rgb -+ * Fix up compiling errors for radij tree memory reclamation. -+ * -+ * Revision 1.1 1998/04/09 03:06:16 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:04 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:44:45 ji -+ * Release update only. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/pfkey.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,509 @@ -+/* -+ * FreeS/WAN specific PF_KEY headers -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifndef __NET_IPSEC_PF_KEY_H -+#define __NET_IPSEC_PF_KEY_H -+#ifdef __KERNEL__ -+extern struct proto_ops pfkey_proto_ops; -+typedef struct sock pfkey_sock; -+extern int debug_pfkey; -+ -+extern /* void */ int pfkey_init(void); -+extern /* void */ int pfkey_cleanup(void); -+ -+extern struct sock *pfkey_sock_list; -+struct socket_list -+{ -+ struct socket *socketp; -+ struct socket_list *next; -+}; -+extern int pfkey_list_insert_socket(struct socket*, struct socket_list**); -+extern int pfkey_list_remove_socket(struct socket*, struct socket_list**); -+extern struct socket_list *pfkey_open_sockets; -+extern struct socket_list *pfkey_registered_sockets[SADB_SATYPE_MAX+1]; -+ -+struct supported -+{ -+ uint16_t supported_alg_exttype; -+ uint8_t supported_alg_id; -+ uint8_t supported_alg_ivlen; -+ uint16_t supported_alg_minbits; -+ uint16_t supported_alg_maxbits; -+}; -+ -+extern struct supported_list *pfkey_supported_list[SADB_SATYPE_MAX+1]; -+struct supported_list -+{ -+ struct supported *supportedp; -+ struct supported_list *next; -+}; -+extern int pfkey_list_insert_supported(struct supported*, struct supported_list**); -+extern int pfkey_list_remove_supported(struct supported*, struct supported_list**); -+ -+struct sockaddr_key -+{ -+ uint16_t key_family; /* PF_KEY */ -+ uint16_t key_pad; /* not used */ -+ uint32_t key_pid; /* process ID */ -+}; -+ -+struct pfkey_extracted_data -+{ -+ struct ipsec_sa* ips; -+ struct ipsec_sa* ips2; -+ struct eroute *eroute; -+}; -+ -+extern int -+pfkey_alloc_eroute(struct eroute** eroute); -+ -+extern int -+pfkey_sa_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_lifetime_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_address_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_key_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_ident_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_sens_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_prop_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_supported_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_spirange_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_x_kmprivate_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_x_satype_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int -+pfkey_x_debug_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data* extr); -+ -+extern int pfkey_upmsg(struct socket *, struct sadb_msg *); -+extern int pfkey_expire(struct ipsec_sa *, int); -+extern int pfkey_acquire(struct ipsec_sa *); -+#else /* ! __KERNEL__ */ -+ -+extern void (*pfkey_debug_func)(const char *message, ...); -+extern void (*pfkey_error_func)(const char *message, ...); -+extern void pfkey_print(struct sadb_msg *msg, FILE *out); -+ -+ -+#endif /* __KERNEL__ */ -+ -+extern uint8_t satype2proto(uint8_t satype); -+extern uint8_t proto2satype(uint8_t proto); -+extern char* satype2name(uint8_t satype); -+extern char* proto2name(uint8_t proto); -+ -+struct key_opt -+{ -+ uint32_t key_pid; /* process ID */ -+ struct sock *sk; -+}; -+ -+#define key_pid(sk) ((struct key_opt*)&((sk)->protinfo))->key_pid -+ -+/* XXX-mcr this is not an alignment, this is because the count is in 64-bit -+ * words. -+ */ -+#define IPSEC_PFKEYv2_ALIGN (sizeof(uint64_t)/sizeof(uint8_t)) -+#define BITS_PER_OCTET 8 -+#define OCTETBITS 8 -+#define PFKEYBITS 64 -+#define DIVUP(x,y) ((x + y -1) / y) /* divide, rounding upwards */ -+#define ALIGN_N(x,y) (DIVUP(x,y) * y) /* align on y boundary */ -+ -+#define IPSEC_PFKEYv2_LEN(x) ((x) * IPSEC_PFKEYv2_ALIGN) -+#define IPSEC_PFKEYv2_WORDS(x) ((x) / IPSEC_PFKEYv2_ALIGN) -+ -+ -+#define PFKEYv2_MAX_MSGSIZE 4096 -+ -+/* -+ * PF_KEYv2 permitted and required extensions in and out bitmaps -+ */ -+struct pf_key_ext_parsers_def { -+ int (*parser)(struct sadb_ext*); -+ char *parser_name; -+}; -+ -+ -+extern unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_MAX + 1/*ext*/]; -+#define EXT_BITS_IN 0 -+#define EXT_BITS_OUT 1 -+#define EXT_BITS_PERM 0 -+#define EXT_BITS_REQ 1 -+ -+extern void pfkey_extensions_init(struct sadb_ext *extensions[SADB_EXT_MAX + 1]); -+extern void pfkey_extensions_free(struct sadb_ext *extensions[SADB_EXT_MAX + 1]); -+extern void pfkey_msg_free(struct sadb_msg **pfkey_msg); -+ -+extern int pfkey_msg_parse(struct sadb_msg *pfkey_msg, -+ struct pf_key_ext_parsers_def *ext_parsers[], -+ struct sadb_ext **extensions, -+ int dir); -+ -+extern int pfkey_register_reply(int satype, struct sadb_msg *sadb_msg); -+ -+/* -+ * PF_KEYv2 build function prototypes -+ */ -+ -+int -+pfkey_msg_hdr_build(struct sadb_ext** pfkey_ext, -+ uint8_t msg_type, -+ uint8_t satype, -+ uint8_t msg_errno, -+ uint32_t seq, -+ uint32_t pid); -+ -+int -+pfkey_sa_ref_build(struct sadb_ext ** pfkey_ext, -+ uint16_t exttype, -+ uint32_t spi, /* in network order */ -+ uint8_t replay_window, -+ uint8_t sa_state, -+ uint8_t auth, -+ uint8_t encrypt, -+ uint32_t flags, -+ uint32_t/*IPsecSAref_t*/ ref); -+ -+int -+pfkey_sa_build(struct sadb_ext ** pfkey_ext, -+ uint16_t exttype, -+ uint32_t spi, /* in network order */ -+ uint8_t replay_window, -+ uint8_t sa_state, -+ uint8_t auth, -+ uint8_t encrypt, -+ uint32_t flags); -+ -+int -+pfkey_lifetime_build(struct sadb_ext ** pfkey_ext, -+ uint16_t exttype, -+ uint32_t allocations, -+ uint64_t bytes, -+ uint64_t addtime, -+ uint64_t usetime, -+ uint32_t packets); -+ -+int -+pfkey_address_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint8_t proto, -+ uint8_t prefixlen, -+ struct sockaddr* address); -+ -+int -+pfkey_key_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint16_t key_bits, -+ char* key); -+ -+int -+pfkey_ident_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint16_t ident_type, -+ uint64_t ident_id, -+ uint8_t ident_len, -+ char* ident_string); -+ -+#ifdef NAT_TRAVERSAL -+#ifdef __KERNEL__ -+extern int pfkey_nat_t_new_mapping(struct ipsec_sa *, struct sockaddr *, __u16); -+extern int pfkey_x_nat_t_type_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr); -+extern int pfkey_x_nat_t_port_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr); -+#endif /* __KERNEL__ */ -+int -+pfkey_x_nat_t_type_build(struct sadb_ext** pfkey_ext, -+ uint8_t type); -+int -+pfkey_x_nat_t_port_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint16_t port); -+#endif -+ -+int -+pfkey_sens_build(struct sadb_ext** pfkey_ext, -+ uint32_t dpd, -+ uint8_t sens_level, -+ uint8_t sens_len, -+ uint64_t* sens_bitmap, -+ uint8_t integ_level, -+ uint8_t integ_len, -+ uint64_t* integ_bitmap); -+ -+int pfkey_x_protocol_build(struct sadb_ext **, uint8_t); -+ -+ -+int -+pfkey_prop_build(struct sadb_ext** pfkey_ext, -+ uint8_t replay, -+ unsigned int comb_num, -+ struct sadb_comb* comb); -+ -+int -+pfkey_supported_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ unsigned int alg_num, -+ struct sadb_alg* alg); -+ -+int -+pfkey_spirange_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint32_t min, -+ uint32_t max); -+ -+int -+pfkey_x_kmprivate_build(struct sadb_ext** pfkey_ext); -+ -+int -+pfkey_x_satype_build(struct sadb_ext** pfkey_ext, -+ uint8_t satype); -+ -+int -+pfkey_x_debug_build(struct sadb_ext** pfkey_ext, -+ uint32_t tunnel, -+ uint32_t netlink, -+ uint32_t xform, -+ uint32_t eroute, -+ uint32_t spi, -+ uint32_t radij, -+ uint32_t esp, -+ uint32_t ah, -+ uint32_t rcv, -+ uint32_t pfkey, -+ uint32_t ipcomp, -+ uint32_t verbose); -+ -+int -+pfkey_msg_build(struct sadb_msg** pfkey_msg, -+ struct sadb_ext* extensions[], -+ int dir); -+ -+/* in pfkey_v2_debug.c - routines to decode numbers -> strings */ -+const char * -+pfkey_v2_sadb_ext_string(int extnum); -+ -+const char * -+pfkey_v2_sadb_type_string(int sadb_type); -+ -+ -+#endif /* __NET_IPSEC_PF_KEY_H */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.45 2004/04/06 02:49:00 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.44 2003/12/10 01:20:01 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.43 2003/10/31 02:26:44 mcr -+ * pulled up port-selector patches. -+ * -+ * Revision 1.42.2.2 2003/10/29 01:09:32 mcr -+ * added debugging for pfkey library. -+ * -+ * Revision 1.42.2.1 2003/09/21 13:59:34 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.42 2003/08/25 22:08:19 mcr -+ * removed pfkey_proto_init() from pfkey.h for 2.6 support. -+ * -+ * Revision 1.41 2003/05/07 17:28:57 mcr -+ * new function pfkey_debug_func added for us in debugging from -+ -+ * pfkey library. -+ * -+ * Revision 1.40 2003/01/30 02:31:34 rgb -+ * -+ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. -+ * -+ * Revision 1.39 2002/09/20 15:40:21 rgb -+ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc(). -+ * Added ref parameter to pfkey_sa_build(). -+ * Cleaned out unused cruft. -+ * -+ * Revision 1.38 2002/05/14 02:37:24 rgb -+ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips, -+ * ipsec_sa or ipsec_sa. -+ * Added function prototypes for the functions moved to -+ * pfkey_v2_ext_process.c. -+ * -+ * Revision 1.37 2002/04/24 07:36:49 mcr -+ * Moved from ./lib/pfkey.h,v -+ * -+ * Revision 1.36 2002/01/20 20:34:49 mcr -+ * added pfkey_v2_sadb_type_string to decode sadb_type to string. -+ * -+ * Revision 1.35 2001/11/27 05:27:47 mcr -+ * pfkey parses are now maintained by a structure -+ * that includes their name for debug purposes. -+ * -+ * Revision 1.34 2001/11/26 09:23:53 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.33 2001/11/06 19:47:47 rgb -+ * Added packet parameter to lifetime and comb structures. -+ * -+ * Revision 1.32 2001/09/08 21:13:34 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.31 2001/06/14 19:35:16 rgb -+ * Update copyright date. -+ * -+ * Revision 1.30 2001/02/27 07:04:52 rgb -+ * Added satype2name prototype. -+ * -+ * Revision 1.29 2001/02/26 19:59:33 rgb -+ * Ditch unused sadb_satype2proto[], replaced by satype2proto(). -+ * -+ * Revision 1.28 2000/10/10 20:10:19 rgb -+ * Added support for debug_ipcomp and debug_verbose to klipsdebug. -+ * -+ * Revision 1.27 2000/09/21 04:20:45 rgb -+ * Fixed array size off-by-one error. (Thanks Svenning!) -+ * -+ * Revision 1.26 2000/09/12 03:26:05 rgb -+ * Added pfkey_acquire prototype. -+ * -+ * Revision 1.25 2000/09/08 19:21:28 rgb -+ * Fix pfkey_prop_build() parameter to be only single indirection. -+ * -+ * Revision 1.24 2000/09/01 18:46:42 rgb -+ * Added a supported algorithms array lists, one per satype and registered -+ * existing algorithms. -+ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to -+ * list. -+ * -+ * Revision 1.23 2000/08/27 01:55:26 rgb -+ * Define OCTETBITS and PFKEYBITS to avoid using 'magic' numbers in code. -+ * -+ * Revision 1.22 2000/08/20 21:39:23 rgb -+ * Added kernel prototypes for kernel funcitions pfkey_upmsg() and -+ * pfkey_expire(). -+ * -+ * Revision 1.21 2000/08/15 17:29:23 rgb -+ * Fixes from SZI to untested pfkey_prop_build(). -+ * -+ * Revision 1.20 2000/05/10 20:14:19 rgb -+ * Fleshed out sensitivity, proposal and supported extensions. -+ * -+ * Revision 1.19 2000/03/16 14:07:23 rgb -+ * Renamed ALIGN macro to avoid fighting with others in kernel. -+ * -+ * Revision 1.18 2000/01/22 23:24:06 rgb -+ * Added prototypes for proto2satype(), satype2proto() and proto2name(). -+ * -+ * Revision 1.17 2000/01/21 06:26:59 rgb -+ * Converted from double tdb arguments to one structure (extr) -+ * containing pointers to all temporary information structures. -+ * Added klipsdebug switching capability. -+ * Dropped unused argument to pfkey_x_satype_build(). -+ * -+ * Revision 1.16 1999/12/29 21:17:41 rgb -+ * Changed pfkey_msg_build() I/F to include a struct sadb_msg** -+ * parameter for cleaner manipulation of extensions[] and to guard -+ * against potential memory leaks. -+ * Changed the I/F to pfkey_msg_free() for the same reason. -+ * -+ * Revision 1.15 1999/12/09 23:12:54 rgb -+ * Added macro for BITS_PER_OCTET. -+ * Added argument to pfkey_sa_build() to do eroutes. -+ * -+ * Revision 1.14 1999/12/08 20:33:25 rgb -+ * Changed sa_family_t to uint16_t for 2.0.xx compatibility. -+ * -+ * Revision 1.13 1999/12/07 19:53:40 rgb -+ * Removed unused first argument from extension parsers. -+ * Changed __u* types to uint* to avoid use of asm/types.h and -+ * sys/types.h in userspace code. -+ * Added function prototypes for pfkey message and extensions -+ * initialisation and cleanup. -+ * -+ * Revision 1.12 1999/12/01 22:19:38 rgb -+ * Change pfkey_sa_build to accept an SPI in network byte order. -+ * -+ * Revision 1.11 1999/11/27 11:55:26 rgb -+ * Added extern sadb_satype2proto to enable moving protocol lookup table -+ * to lib/pfkey_v2_parse.c. -+ * Delete unused, moved typedefs. -+ * Add argument to pfkey_msg_parse() for direction. -+ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array. -+ * -+ * Revision 1.10 1999/11/23 22:29:21 rgb -+ * This file has been moved in the distribution from klips/net/ipsec to -+ * lib. -+ * Add macros for dealing with alignment and rounding up more opaquely. -+ * The uint_t type defines have been moved to freeswan.h to avoid -+ * chicken-and-egg problems. -+ * Add macros for dealing with alignment and rounding up more opaque. -+ * Added prototypes for using extention header bitmaps. -+ * Added prototypes of all the build functions. -+ * -+ * Revision 1.9 1999/11/20 21:59:48 rgb -+ * Moved socketlist type declarations and prototypes for shared use. -+ * Slightly modified scope of sockaddr_key declaration. -+ * -+ * Revision 1.8 1999/11/17 14:34:25 rgb -+ * Protect sa_family_t from being used in userspace with GLIBC<2. -+ * -+ * Revision 1.7 1999/10/27 19:40:35 rgb -+ * Add a maximum PFKEY packet size macro. -+ * -+ * Revision 1.6 1999/10/26 16:58:58 rgb -+ * Created a sockaddr_key and key_opt socket extension structures. -+ * -+ * Revision 1.5 1999/06/10 05:24:41 rgb -+ * Renamed variables to reduce confusion. -+ * -+ * Revision 1.4 1999/04/29 15:21:11 rgb -+ * Add pfkey support to debugging. -+ * Add return values to init and cleanup functions. -+ * -+ * Revision 1.3 1999/04/15 17:58:07 rgb -+ * Add RCSID labels. -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/pfkeyv2.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,467 @@ -+/* -+ * RCSID $Id$ -+ */ -+ -+/* -+RFC 2367 PF_KEY Key Management API July 1998 -+ -+ -+Appendix D: Sample Header File -+ -+This file defines structures and symbols for the PF_KEY Version 2 -+key management interface. It was written at the U.S. Naval Research -+Laboratory. This file is in the public domain. The authors ask that -+you leave this credit intact on any copies of this file. -+*/ -+#ifndef __PFKEY_V2_H -+#define __PFKEY_V2_H 1 -+ -+#define PF_KEY_V2 2 -+#define PFKEYV2_REVISION 199806L -+ -+#define SADB_RESERVED 0 -+#define SADB_GETSPI 1 -+#define SADB_UPDATE 2 -+#define SADB_ADD 3 -+#define SADB_DELETE 4 -+#define SADB_GET 5 -+#define SADB_ACQUIRE 6 -+#define SADB_REGISTER 7 -+#define SADB_EXPIRE 8 -+#define SADB_FLUSH 9 -+#define SADB_DUMP 10 -+#define SADB_X_PROMISC 11 -+#define SADB_X_PCHANGE 12 -+#define SADB_X_GRPSA 13 -+#define SADB_X_ADDFLOW 14 -+#define SADB_X_DELFLOW 15 -+#define SADB_X_DEBUG 16 -+#define SADB_X_NAT_T_NEW_MAPPING 17 -+#define SADB_MAX 17 -+ -+struct sadb_msg { -+ uint8_t sadb_msg_version; -+ uint8_t sadb_msg_type; -+ uint8_t sadb_msg_errno; -+ uint8_t sadb_msg_satype; -+ uint16_t sadb_msg_len; -+ uint16_t sadb_msg_reserved; -+ uint32_t sadb_msg_seq; -+ uint32_t sadb_msg_pid; -+}; -+ -+struct sadb_ext { -+ uint16_t sadb_ext_len; -+ uint16_t sadb_ext_type; -+}; -+ -+struct sadb_sa { -+ uint16_t sadb_sa_len; -+ uint16_t sadb_sa_exttype; -+ uint32_t sadb_sa_spi; -+ uint8_t sadb_sa_replay; -+ uint8_t sadb_sa_state; -+ uint8_t sadb_sa_auth; -+ uint8_t sadb_sa_encrypt; -+ uint32_t sadb_sa_flags; -+ uint32_t /*IPsecSAref_t*/ sadb_x_sa_ref; /* 32 bits */ -+ uint8_t sadb_x_reserved[4]; -+}; -+ -+struct sadb_sa_v1 { -+ uint16_t sadb_sa_len; -+ uint16_t sadb_sa_exttype; -+ uint32_t sadb_sa_spi; -+ uint8_t sadb_sa_replay; -+ uint8_t sadb_sa_state; -+ uint8_t sadb_sa_auth; -+ uint8_t sadb_sa_encrypt; -+ uint32_t sadb_sa_flags; -+}; -+ -+struct sadb_lifetime { -+ uint16_t sadb_lifetime_len; -+ uint16_t sadb_lifetime_exttype; -+ uint32_t sadb_lifetime_allocations; -+ uint64_t sadb_lifetime_bytes; -+ uint64_t sadb_lifetime_addtime; -+ uint64_t sadb_lifetime_usetime; -+ uint32_t sadb_x_lifetime_packets; -+ uint32_t sadb_x_lifetime_reserved; -+}; -+ -+struct sadb_address { -+ uint16_t sadb_address_len; -+ uint16_t sadb_address_exttype; -+ uint8_t sadb_address_proto; -+ uint8_t sadb_address_prefixlen; -+ uint16_t sadb_address_reserved; -+}; -+ -+struct sadb_key { -+ uint16_t sadb_key_len; -+ uint16_t sadb_key_exttype; -+ uint16_t sadb_key_bits; -+ uint16_t sadb_key_reserved; -+}; -+ -+struct sadb_ident { -+ uint16_t sadb_ident_len; -+ uint16_t sadb_ident_exttype; -+ uint16_t sadb_ident_type; -+ uint16_t sadb_ident_reserved; -+ uint64_t sadb_ident_id; -+}; -+ -+struct sadb_sens { -+ uint16_t sadb_sens_len; -+ uint16_t sadb_sens_exttype; -+ uint32_t sadb_sens_dpd; -+ uint8_t sadb_sens_sens_level; -+ uint8_t sadb_sens_sens_len; -+ uint8_t sadb_sens_integ_level; -+ uint8_t sadb_sens_integ_len; -+ uint32_t sadb_sens_reserved; -+}; -+ -+struct sadb_prop { -+ uint16_t sadb_prop_len; -+ uint16_t sadb_prop_exttype; -+ uint8_t sadb_prop_replay; -+ uint8_t sadb_prop_reserved[3]; -+}; -+ -+struct sadb_comb { -+ uint8_t sadb_comb_auth; -+ uint8_t sadb_comb_encrypt; -+ uint16_t sadb_comb_flags; -+ uint16_t sadb_comb_auth_minbits; -+ uint16_t sadb_comb_auth_maxbits; -+ uint16_t sadb_comb_encrypt_minbits; -+ uint16_t sadb_comb_encrypt_maxbits; -+ uint32_t sadb_comb_reserved; -+ uint32_t sadb_comb_soft_allocations; -+ uint32_t sadb_comb_hard_allocations; -+ uint64_t sadb_comb_soft_bytes; -+ uint64_t sadb_comb_hard_bytes; -+ uint64_t sadb_comb_soft_addtime; -+ uint64_t sadb_comb_hard_addtime; -+ uint64_t sadb_comb_soft_usetime; -+ uint64_t sadb_comb_hard_usetime; -+ uint32_t sadb_x_comb_soft_packets; -+ uint32_t sadb_x_comb_hard_packets; -+}; -+ -+struct sadb_supported { -+ uint16_t sadb_supported_len; -+ uint16_t sadb_supported_exttype; -+ uint32_t sadb_supported_reserved; -+}; -+ -+struct sadb_alg { -+ uint8_t sadb_alg_id; -+ uint8_t sadb_alg_ivlen; -+ uint16_t sadb_alg_minbits; -+ uint16_t sadb_alg_maxbits; -+ uint16_t sadb_alg_reserved; -+}; -+ -+struct sadb_spirange { -+ uint16_t sadb_spirange_len; -+ uint16_t sadb_spirange_exttype; -+ uint32_t sadb_spirange_min; -+ uint32_t sadb_spirange_max; -+ uint32_t sadb_spirange_reserved; -+}; -+ -+struct sadb_x_kmprivate { -+ uint16_t sadb_x_kmprivate_len; -+ uint16_t sadb_x_kmprivate_exttype; -+ uint32_t sadb_x_kmprivate_reserved; -+}; -+ -+struct sadb_x_satype { -+ uint16_t sadb_x_satype_len; -+ uint16_t sadb_x_satype_exttype; -+ uint8_t sadb_x_satype_satype; -+ uint8_t sadb_x_satype_reserved[3]; -+}; -+ -+struct sadb_x_policy { -+ uint16_t sadb_x_policy_len; -+ uint16_t sadb_x_policy_exttype; -+ uint16_t sadb_x_policy_type; -+ uint8_t sadb_x_policy_dir; -+ uint8_t sadb_x_policy_reserved; -+ uint32_t sadb_x_policy_id; -+ uint32_t sadb_x_policy_reserved2; -+}; -+ -+struct sadb_x_debug { -+ uint16_t sadb_x_debug_len; -+ uint16_t sadb_x_debug_exttype; -+ uint32_t sadb_x_debug_tunnel; -+ uint32_t sadb_x_debug_netlink; -+ uint32_t sadb_x_debug_xform; -+ uint32_t sadb_x_debug_eroute; -+ uint32_t sadb_x_debug_spi; -+ uint32_t sadb_x_debug_radij; -+ uint32_t sadb_x_debug_esp; -+ uint32_t sadb_x_debug_ah; -+ uint32_t sadb_x_debug_rcv; -+ uint32_t sadb_x_debug_pfkey; -+ uint32_t sadb_x_debug_ipcomp; -+ uint32_t sadb_x_debug_verbose; -+ uint8_t sadb_x_debug_reserved[4]; -+}; -+ -+struct sadb_x_nat_t_type { -+ uint16_t sadb_x_nat_t_type_len; -+ uint16_t sadb_x_nat_t_type_exttype; -+ uint8_t sadb_x_nat_t_type_type; -+ uint8_t sadb_x_nat_t_type_reserved[3]; -+}; -+struct sadb_x_nat_t_port { -+ uint16_t sadb_x_nat_t_port_len; -+ uint16_t sadb_x_nat_t_port_exttype; -+ uint16_t sadb_x_nat_t_port_port; -+ uint16_t sadb_x_nat_t_port_reserved; -+}; -+ -+/* -+ * A protocol structure for passing through the transport level -+ * protocol. It contains more fields than are actually used/needed -+ * but it is this way to be compatible with the structure used in -+ * OpenBSD (http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pfkeyv2.h) -+ */ -+struct sadb_protocol { -+ uint16_t sadb_protocol_len; -+ uint16_t sadb_protocol_exttype; -+ uint8_t sadb_protocol_proto; -+ uint8_t sadb_protocol_direction; -+ uint8_t sadb_protocol_flags; -+ uint8_t sadb_protocol_reserved2; -+}; -+ -+#define SADB_EXT_RESERVED 0 -+#define SADB_EXT_SA 1 -+#define SADB_EXT_LIFETIME_CURRENT 2 -+#define SADB_EXT_LIFETIME_HARD 3 -+#define SADB_EXT_LIFETIME_SOFT 4 -+#define SADB_EXT_ADDRESS_SRC 5 -+#define SADB_EXT_ADDRESS_DST 6 -+#define SADB_EXT_ADDRESS_PROXY 7 -+#define SADB_EXT_KEY_AUTH 8 -+#define SADB_EXT_KEY_ENCRYPT 9 -+#define SADB_EXT_IDENTITY_SRC 10 -+#define SADB_EXT_IDENTITY_DST 11 -+#define SADB_EXT_SENSITIVITY 12 -+#define SADB_EXT_PROPOSAL 13 -+#define SADB_EXT_SUPPORTED_AUTH 14 -+#define SADB_EXT_SUPPORTED_ENCRYPT 15 -+#define SADB_EXT_SPIRANGE 16 -+#define SADB_X_EXT_KMPRIVATE 17 -+#define SADB_X_EXT_SATYPE2 18 -+#ifdef KERNEL26_HAS_KAME_DUPLICATES -+#define SADB_X_EXT_POLICY 18 -+#endif -+#define SADB_X_EXT_SA2 19 -+#define SADB_X_EXT_ADDRESS_DST2 20 -+#define SADB_X_EXT_ADDRESS_SRC_FLOW 21 -+#define SADB_X_EXT_ADDRESS_DST_FLOW 22 -+#define SADB_X_EXT_ADDRESS_SRC_MASK 23 -+#define SADB_X_EXT_ADDRESS_DST_MASK 24 -+#define SADB_X_EXT_DEBUG 25 -+#define SADB_X_EXT_PROTOCOL 26 -+#define SADB_X_EXT_NAT_T_TYPE 27 -+#define SADB_X_EXT_NAT_T_SPORT 28 -+#define SADB_X_EXT_NAT_T_DPORT 29 -+#define SADB_X_EXT_NAT_T_OA 30 -+#define SADB_EXT_MAX 30 -+ -+/* SADB_X_DELFLOW required over and above SADB_X_SAFLAGS_CLEARFLOW */ -+#define SADB_X_EXT_ADDRESS_DELFLOW \ -+ ( (1<adler to the adler32 checksum of all input read -+ so far (that is, total_in bytes). -+ -+ deflate() may update data_type if it can make a good guess about -+ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered -+ binary. This field is only for information purposes and does not affect -+ the compression algorithm in any manner. -+ -+ deflate() returns Z_OK if some progress has been made (more input -+ processed or more output produced), Z_STREAM_END if all input has been -+ consumed and all output has been produced (only when flush is set to -+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example -+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible -+ (for example avail_in or avail_out was zero). -+*/ -+ -+ -+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -+/* -+ All dynamically allocated data structures for this stream are freed. -+ This function discards any unprocessed input and does not flush any -+ pending output. -+ -+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the -+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed -+ prematurely (some input or output was discarded). In the error case, -+ msg may be set but then points to a static string (which must not be -+ deallocated). -+*/ -+ -+ -+/* -+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); -+ -+ Initializes the internal stream state for decompression. The fields -+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by -+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact -+ value depends on the compression method), inflateInit determines the -+ compression method from the zlib header and allocates all data structures -+ accordingly; otherwise the allocation will be deferred to the first call of -+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to -+ use default allocation functions. -+ -+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the -+ version assumed by the caller. msg is set to null if there is no error -+ message. inflateInit does not perform any decompression apart from reading -+ the zlib header if present: this will be done by inflate(). (So next_in and -+ avail_in may be modified, but next_out and avail_out are unchanged.) -+*/ -+ -+ -+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -+/* -+ inflate decompresses as much data as possible, and stops when the input -+ buffer becomes empty or the output buffer becomes full. It may some -+ introduce some output latency (reading input without producing any output) -+ except when forced to flush. -+ -+ The detailed semantics are as follows. inflate performs one or both of the -+ following actions: -+ -+ - Decompress more input starting at next_in and update next_in and avail_in -+ accordingly. If not all input can be processed (because there is not -+ enough room in the output buffer), next_in is updated and processing -+ will resume at this point for the next call of inflate(). -+ -+ - Provide more output starting at next_out and update next_out and avail_out -+ accordingly. inflate() provides as much output as possible, until there -+ is no more input data or no more space in the output buffer (see below -+ about the flush parameter). -+ -+ Before the call of inflate(), the application should ensure that at least -+ one of the actions is possible, by providing more input and/or consuming -+ more output, and updating the next_* and avail_* values accordingly. -+ The application can consume the uncompressed output when it wants, for -+ example when the output buffer is full (avail_out == 0), or after each -+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it -+ must be called again after making room in the output buffer because there -+ might be more output pending. -+ -+ If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much -+ output as possible to the output buffer. The flushing behavior of inflate is -+ not specified for values of the flush parameter other than Z_SYNC_FLUSH -+ and Z_FINISH, but the current implementation actually flushes as much output -+ as possible anyway. -+ -+ inflate() should normally be called until it returns Z_STREAM_END or an -+ error. However if all decompression is to be performed in a single step -+ (a single call of inflate), the parameter flush should be set to -+ Z_FINISH. In this case all pending input is processed and all pending -+ output is flushed; avail_out must be large enough to hold all the -+ uncompressed data. (The size of the uncompressed data may have been saved -+ by the compressor for this purpose.) The next operation on this stream must -+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH -+ is never required, but can be used to inform inflate that a faster routine -+ may be used for the single inflate() call. -+ -+ If a preset dictionary is needed at this point (see inflateSetDictionary -+ below), inflate sets strm-adler to the adler32 checksum of the -+ dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise -+ it sets strm->adler to the adler32 checksum of all output produced -+ so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or -+ an error code as described below. At the end of the stream, inflate() -+ checks that its computed adler32 checksum is equal to that saved by the -+ compressor and returns Z_STREAM_END only if the checksum is correct. -+ -+ inflate() returns Z_OK if some progress has been made (more input processed -+ or more output produced), Z_STREAM_END if the end of the compressed data has -+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a -+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was -+ corrupted (input stream not conforming to the zlib format or incorrect -+ adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent -+ (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not -+ enough memory, Z_BUF_ERROR if no progress is possible or if there was not -+ enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR -+ case, the application may then call inflateSync to look for a good -+ compression block. -+*/ -+ -+ -+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -+/* -+ All dynamically allocated data structures for this stream are freed. -+ This function discards any unprocessed input and does not flush any -+ pending output. -+ -+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state -+ was inconsistent. In the error case, msg may be set but then points to a -+ static string (which must not be deallocated). -+*/ -+ -+ /* Advanced functions */ -+ -+/* -+ The following functions are needed only in some special applications. -+*/ -+ -+/* -+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, -+ int level, -+ int method, -+ int windowBits, -+ int memLevel, -+ int strategy)); -+ -+ This is another version of deflateInit with more compression options. The -+ fields next_in, zalloc, zfree and opaque must be initialized before by -+ the caller. -+ -+ The method parameter is the compression method. It must be Z_DEFLATED in -+ this version of the library. -+ -+ The windowBits parameter is the base two logarithm of the window size -+ (the size of the history buffer). It should be in the range 8..15 for this -+ version of the library. Larger values of this parameter result in better -+ compression at the expense of memory usage. The default value is 15 if -+ deflateInit is used instead. -+ -+ The memLevel parameter specifies how much memory should be allocated -+ for the internal compression state. memLevel=1 uses minimum memory but -+ is slow and reduces compression ratio; memLevel=9 uses maximum memory -+ for optimal speed. The default value is 8. See zconf.h for total memory -+ usage as a function of windowBits and memLevel. -+ -+ The strategy parameter is used to tune the compression algorithm. Use the -+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a -+ filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no -+ string match). Filtered data consists mostly of small values with a -+ somewhat random distribution. In this case, the compression algorithm is -+ tuned to compress them better. The effect of Z_FILTERED is to force more -+ Huffman coding and less string matching; it is somewhat intermediate -+ between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects -+ the compression ratio but not the correctness of the compressed output even -+ if it is not set appropriately. -+ -+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid -+ method). msg is set to null if there is no error message. deflateInit2 does -+ not perform any compression: this will be done by deflate(). -+*/ -+ -+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, -+ const Bytef *dictionary, -+ uInt dictLength)); -+/* -+ Initializes the compression dictionary from the given byte sequence -+ without producing any compressed output. This function must be called -+ immediately after deflateInit, deflateInit2 or deflateReset, before any -+ call of deflate. The compressor and decompressor must use exactly the same -+ dictionary (see inflateSetDictionary). -+ -+ The dictionary should consist of strings (byte sequences) that are likely -+ to be encountered later in the data to be compressed, with the most commonly -+ used strings preferably put towards the end of the dictionary. Using a -+ dictionary is most useful when the data to be compressed is short and can be -+ predicted with good accuracy; the data can then be compressed better than -+ with the default empty dictionary. -+ -+ Depending on the size of the compression data structures selected by -+ deflateInit or deflateInit2, a part of the dictionary may in effect be -+ discarded, for example if the dictionary is larger than the window size in -+ deflate or deflate2. Thus the strings most likely to be useful should be -+ put at the end of the dictionary, not at the front. -+ -+ Upon return of this function, strm->adler is set to the Adler32 value -+ of the dictionary; the decompressor may later use this value to determine -+ which dictionary has been used by the compressor. (The Adler32 value -+ applies to the whole dictionary even if only a subset of the dictionary is -+ actually used by the compressor.) -+ -+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a -+ parameter is invalid (such as NULL dictionary) or the stream state is -+ inconsistent (for example if deflate has already been called for this stream -+ or if the compression method is bsort). deflateSetDictionary does not -+ perform any compression: this will be done by deflate(). -+*/ -+ -+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, -+ z_streamp source)); -+/* -+ Sets the destination stream as a complete copy of the source stream. -+ -+ This function can be useful when several compression strategies will be -+ tried, for example when there are several ways of pre-processing the input -+ data with a filter. The streams that will be discarded should then be freed -+ by calling deflateEnd. Note that deflateCopy duplicates the internal -+ compression state which can be quite large, so this strategy is slow and -+ can consume lots of memory. -+ -+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent -+ (such as zalloc being NULL). msg is left unchanged in both source and -+ destination. -+*/ -+ -+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -+/* -+ This function is equivalent to deflateEnd followed by deflateInit, -+ but does not free and reallocate all the internal compression state. -+ The stream will keep the same compression level and any other attributes -+ that may have been set by deflateInit2. -+ -+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source -+ stream state was inconsistent (such as zalloc or state being NULL). -+*/ -+ -+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, -+ int level, -+ int strategy)); -+/* -+ Dynamically update the compression level and compression strategy. The -+ interpretation of level and strategy is as in deflateInit2. This can be -+ used to switch between compression and straight copy of the input data, or -+ to switch to a different kind of input data requiring a different -+ strategy. If the compression level is changed, the input available so far -+ is compressed with the old level (and may be flushed); the new level will -+ take effect only at the next call of deflate(). -+ -+ Before the call of deflateParams, the stream state must be set as for -+ a call of deflate(), since the currently available input may have to -+ be compressed and flushed. In particular, strm->avail_out must be non-zero. -+ -+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source -+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR -+ if strm->avail_out was zero. -+*/ -+ -+/* -+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, -+ int windowBits)); -+ -+ This is another version of inflateInit with an extra parameter. The -+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized -+ before by the caller. -+ -+ The windowBits parameter is the base two logarithm of the maximum window -+ size (the size of the history buffer). It should be in the range 8..15 for -+ this version of the library. The default value is 15 if inflateInit is used -+ instead. If a compressed stream with a larger window size is given as -+ input, inflate() will return with the error code Z_DATA_ERROR instead of -+ trying to allocate a larger window. -+ -+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative -+ memLevel). msg is set to null if there is no error message. inflateInit2 -+ does not perform any decompression apart from reading the zlib header if -+ present: this will be done by inflate(). (So next_in and avail_in may be -+ modified, but next_out and avail_out are unchanged.) -+*/ -+ -+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, -+ const Bytef *dictionary, -+ uInt dictLength)); -+/* -+ Initializes the decompression dictionary from the given uncompressed byte -+ sequence. This function must be called immediately after a call of inflate -+ if this call returned Z_NEED_DICT. The dictionary chosen by the compressor -+ can be determined from the Adler32 value returned by this call of -+ inflate. The compressor and decompressor must use exactly the same -+ dictionary (see deflateSetDictionary). -+ -+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a -+ parameter is invalid (such as NULL dictionary) or the stream state is -+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the -+ expected one (incorrect Adler32 value). inflateSetDictionary does not -+ perform any decompression: this will be done by subsequent calls of -+ inflate(). -+*/ -+ -+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -+/* -+ Skips invalid compressed data until a full flush point (see above the -+ description of deflate with Z_FULL_FLUSH) can be found, or until all -+ available input is skipped. No output is provided. -+ -+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR -+ if no more input was provided, Z_DATA_ERROR if no flush point has been found, -+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success -+ case, the application may save the current current value of total_in which -+ indicates where valid compressed data was found. In the error case, the -+ application may repeatedly call inflateSync, providing more input each time, -+ until success or end of the input data. -+*/ -+ -+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -+/* -+ This function is equivalent to inflateEnd followed by inflateInit, -+ but does not free and reallocate all the internal decompression state. -+ The stream will keep attributes that may have been set by inflateInit2. -+ -+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source -+ stream state was inconsistent (such as zalloc or state being NULL). -+*/ -+ -+ -+ /* utility functions */ -+ -+/* -+ The following utility functions are implemented on top of the -+ basic stream-oriented functions. To simplify the interface, some -+ default options are assumed (compression level and memory usage, -+ standard memory allocation functions). The source code of these -+ utility functions can easily be modified if you need special options. -+*/ -+ -+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, -+ const Bytef *source, uLong sourceLen)); -+/* -+ Compresses the source buffer into the destination buffer. sourceLen is -+ the byte length of the source buffer. Upon entry, destLen is the total -+ size of the destination buffer, which must be at least 0.1% larger than -+ sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the -+ compressed buffer. -+ This function can be used to compress a whole file at once if the -+ input file is mmap'ed. -+ compress returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory, Z_BUF_ERROR if there was not enough room in the output -+ buffer. -+*/ -+ -+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, -+ const Bytef *source, uLong sourceLen, -+ int level)); -+/* -+ Compresses the source buffer into the destination buffer. The level -+ parameter has the same meaning as in deflateInit. sourceLen is the byte -+ length of the source buffer. Upon entry, destLen is the total size of the -+ destination buffer, which must be at least 0.1% larger than sourceLen plus -+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. -+ -+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough -+ memory, Z_BUF_ERROR if there was not enough room in the output buffer, -+ Z_STREAM_ERROR if the level parameter is invalid. -+*/ -+ -+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, -+ const Bytef *source, uLong sourceLen)); -+/* -+ Decompresses the source buffer into the destination buffer. sourceLen is -+ the byte length of the source buffer. Upon entry, destLen is the total -+ size of the destination buffer, which must be large enough to hold the -+ entire uncompressed data. (The size of the uncompressed data must have -+ been saved previously by the compressor and transmitted to the decompressor -+ by some mechanism outside the scope of this compression library.) -+ Upon exit, destLen is the actual size of the compressed buffer. -+ This function can be used to decompress a whole file at once if the -+ input file is mmap'ed. -+ -+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not -+ enough memory, Z_BUF_ERROR if there was not enough room in the output -+ buffer, or Z_DATA_ERROR if the input data was corrupted. -+*/ -+ -+ -+typedef voidp gzFile; -+ -+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); -+/* -+ Opens a gzip (.gz) file for reading or writing. The mode parameter -+ is as in fopen ("rb" or "wb") but can also include a compression level -+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for -+ Huffman only compression as in "wb1h". (See the description -+ of deflateInit2 for more information about the strategy parameter.) -+ -+ gzopen can be used to read a file which is not in gzip format; in this -+ case gzread will directly read from the file without decompression. -+ -+ gzopen returns NULL if the file could not be opened or if there was -+ insufficient memory to allocate the (de)compression state; errno -+ can be checked to distinguish the two cases (if errno is zero, the -+ zlib error is Z_MEM_ERROR). */ -+ -+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -+/* -+ gzdopen() associates a gzFile with the file descriptor fd. File -+ descriptors are obtained from calls like open, dup, creat, pipe or -+ fileno (in the file has been previously opened with fopen). -+ The mode parameter is as in gzopen. -+ The next call of gzclose on the returned gzFile will also close the -+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file -+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). -+ gzdopen returns NULL if there was insufficient memory to allocate -+ the (de)compression state. -+*/ -+ -+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -+/* -+ Dynamically update the compression level or strategy. See the description -+ of deflateInit2 for the meaning of these parameters. -+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not -+ opened for writing. -+*/ -+ -+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -+/* -+ Reads the given number of uncompressed bytes from the compressed file. -+ If the input file was not in gzip format, gzread copies the given number -+ of bytes into the buffer. -+ gzread returns the number of uncompressed bytes actually read (0 for -+ end of file, -1 for error). */ -+ -+ZEXTERN int ZEXPORT gzwrite OF((gzFile file, -+ const voidp buf, unsigned len)); -+/* -+ Writes the given number of uncompressed bytes into the compressed file. -+ gzwrite returns the number of uncompressed bytes actually written -+ (0 in case of error). -+*/ -+ -+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); -+/* -+ Converts, formats, and writes the args to the compressed file under -+ control of the format string, as in fprintf. gzprintf returns the number of -+ uncompressed bytes actually written (0 in case of error). -+*/ -+ -+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -+/* -+ Writes the given null-terminated string to the compressed file, excluding -+ the terminating null character. -+ gzputs returns the number of characters written, or -1 in case of error. -+*/ -+ -+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -+/* -+ Reads bytes from the compressed file until len-1 characters are read, or -+ a newline character is read and transferred to buf, or an end-of-file -+ condition is encountered. The string is then terminated with a null -+ character. -+ gzgets returns buf, or Z_NULL in case of error. -+*/ -+ -+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -+/* -+ Writes c, converted to an unsigned char, into the compressed file. -+ gzputc returns the value that was written, or -1 in case of error. -+*/ -+ -+ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -+/* -+ Reads one byte from the compressed file. gzgetc returns this byte -+ or -1 in case of end of file or error. -+*/ -+ -+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -+/* -+ Flushes all pending output into the compressed file. The parameter -+ flush is as in the deflate() function. The return value is the zlib -+ error number (see function gzerror below). gzflush returns Z_OK if -+ the flush parameter is Z_FINISH and all output could be flushed. -+ gzflush should be called only when strictly necessary because it can -+ degrade compression. -+*/ -+ -+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, -+ z_off_t offset, int whence)); -+/* -+ Sets the starting position for the next gzread or gzwrite on the -+ given compressed file. The offset represents a number of bytes in the -+ uncompressed data stream. The whence parameter is defined as in lseek(2); -+ the value SEEK_END is not supported. -+ If the file is opened for reading, this function is emulated but can be -+ extremely slow. If the file is opened for writing, only forward seeks are -+ supported; gzseek then compresses a sequence of zeroes up to the new -+ starting position. -+ -+ gzseek returns the resulting offset location as measured in bytes from -+ the beginning of the uncompressed stream, or -1 in case of error, in -+ particular if the file is opened for writing and the new starting position -+ would be before the current position. -+*/ -+ -+ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -+/* -+ Rewinds the given file. This function is supported only for reading. -+ -+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -+*/ -+ -+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); -+/* -+ Returns the starting position for the next gzread or gzwrite on the -+ given compressed file. This position represents a number of bytes in the -+ uncompressed data stream. -+ -+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -+*/ -+ -+ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -+/* -+ Returns 1 when EOF has previously been detected reading the given -+ input stream, otherwise zero. -+*/ -+ -+ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -+/* -+ Flushes all pending output if necessary, closes the compressed file -+ and deallocates all the (de)compression state. The return value is the zlib -+ error number (see function gzerror below). -+*/ -+ -+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -+/* -+ Returns the error message for the last error which occurred on the -+ given compressed file. errnum is set to zlib error number. If an -+ error occurred in the file system and not in the compression library, -+ errnum is set to Z_ERRNO and the application may consult errno -+ to get the exact error code. -+*/ -+ -+ /* checksum functions */ -+ -+/* -+ These functions are not related to compression but are exported -+ anyway because they might be useful in applications using the -+ compression library. -+*/ -+ -+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -+ -+/* -+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and -+ return the updated checksum. If buf is NULL, this function returns -+ the required initial value for the checksum. -+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed -+ much faster. Usage example: -+ -+ uLong adler = adler32(0L, Z_NULL, 0); -+ -+ while (read_buffer(buffer, length) != EOF) { -+ adler = adler32(adler, buffer, length); -+ } -+ if (adler != original_adler) error(); -+*/ -+ -+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -+/* -+ Update a running crc with the bytes buf[0..len-1] and return the updated -+ crc. If buf is NULL, this function returns the required initial value -+ for the crc. Pre- and post-conditioning (one's complement) is performed -+ within this function so it shouldn't be done by the application. -+ Usage example: -+ -+ uLong crc = crc32(0L, Z_NULL, 0); -+ -+ while (read_buffer(buffer, length) != EOF) { -+ crc = crc32(crc, buffer, length); -+ } -+ if (crc != original_crc) error(); -+*/ -+ -+ -+ /* various hacks, don't look :) */ -+ -+/* deflateInit and inflateInit are macros to allow checking the zlib version -+ * and the compiler's view of z_stream: -+ */ -+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, -+ const char *version, int stream_size)); -+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, -+ const char *version, int stream_size)); -+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, -+ int windowBits, int memLevel, -+ int strategy, const char *version, -+ int stream_size)); -+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, -+ const char *version, int stream_size)); -+#define deflateInit(strm, level) \ -+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -+#define inflateInit(strm) \ -+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ -+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ -+ (strategy), ZLIB_VERSION, sizeof(z_stream)) -+#define inflateInit2(strm, windowBits) \ -+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) -+ -+ -+#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) -+ struct internal_state {int dummy;}; /* hack for buggy compilers */ -+#endif -+ -+ZEXTERN const char * ZEXPORT zError OF((int err)); -+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); -+ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* _ZLIB_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/include/zlib/zutil.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,225 @@ -+/* zutil.h -- internal interface and configuration of the compression library -+ * Copyright (C) 1995-2002 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+/* @(#) $Id$ */ -+ -+#ifndef _Z_UTIL_H -+#define _Z_UTIL_H -+ -+#include "zlib.h" -+ -+#include -+#define HAVE_MEMCPY -+ -+#if 0 // #ifdef STDC -+# include -+# include -+# include -+#endif -+#ifndef __KERNEL__ -+#ifdef NO_ERRNO_H -+ extern int errno; -+#else -+# include -+#endif -+#endif -+ -+#ifndef local -+# define local static -+#endif -+/* compile with -Dlocal if your debugger can't find static symbols */ -+ -+typedef unsigned char uch; -+typedef uch FAR uchf; -+typedef unsigned short ush; -+typedef ush FAR ushf; -+typedef unsigned long ulg; -+ -+extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ -+/* (size given to avoid silly warnings with Visual C++) */ -+ -+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] -+ -+#define ERR_RETURN(strm,err) \ -+ return (strm->msg = ERR_MSG(err), (err)) -+/* To be used only when the state is known to be valid */ -+ -+ /* common constants */ -+ -+#ifndef DEF_WBITS -+# define DEF_WBITS MAX_WBITS -+#endif -+/* default windowBits for decompression. MAX_WBITS is for compression only */ -+ -+#if MAX_MEM_LEVEL >= 8 -+# define DEF_MEM_LEVEL 8 -+#else -+# define DEF_MEM_LEVEL MAX_MEM_LEVEL -+#endif -+/* default memLevel */ -+ -+#define STORED_BLOCK 0 -+#define STATIC_TREES 1 -+#define DYN_TREES 2 -+/* The three kinds of block type */ -+ -+#define MIN_MATCH 3 -+#define MAX_MATCH 258 -+/* The minimum and maximum match lengths */ -+ -+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ -+ -+ /* target dependencies */ -+ -+#ifdef MSDOS -+# define OS_CODE 0x00 -+# if defined(__TURBOC__) || defined(__BORLANDC__) -+# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) -+ /* Allow compilation with ANSI keywords only enabled */ -+ void _Cdecl farfree( void *block ); -+ void *_Cdecl farmalloc( unsigned long nbytes ); -+# else -+# include -+# endif -+# else /* MSC or DJGPP */ -+# include -+# endif -+#endif -+ -+#ifdef OS2 -+# define OS_CODE 0x06 -+#endif -+ -+#ifdef WIN32 /* Window 95 & Windows NT */ -+# define OS_CODE 0x0b -+#endif -+ -+#if defined(VAXC) || defined(VMS) -+# define OS_CODE 0x02 -+# define F_OPEN(name, mode) \ -+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") -+#endif -+ -+#ifdef AMIGA -+# define OS_CODE 0x01 -+#endif -+ -+#if defined(ATARI) || defined(atarist) -+# define OS_CODE 0x05 -+#endif -+ -+#if defined(MACOS) || defined(TARGET_OS_MAC) -+# define OS_CODE 0x07 -+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -+# include /* for fdopen */ -+# else -+# ifndef fdopen -+# define fdopen(fd,mode) NULL /* No fdopen() */ -+# endif -+# endif -+#endif -+ -+#ifdef __50SERIES /* Prime/PRIMOS */ -+# define OS_CODE 0x0F -+#endif -+ -+#ifdef TOPS20 -+# define OS_CODE 0x0a -+#endif -+ -+#if defined(_BEOS_) || defined(RISCOS) -+# define fdopen(fd,mode) NULL /* No fdopen() */ -+#endif -+ -+#if (defined(_MSC_VER) && (_MSC_VER > 600)) -+# define fdopen(fd,type) _fdopen(fd,type) -+#endif -+ -+ -+ /* Common defaults */ -+ -+#ifndef OS_CODE -+# define OS_CODE 0x03 /* assume Unix */ -+#endif -+ -+#ifndef F_OPEN -+# define F_OPEN(name, mode) fopen((name), (mode)) -+#endif -+ -+ /* functions */ -+ -+#ifdef HAVE_STRERROR -+ extern char *strerror OF((int)); -+# define zstrerror(errnum) strerror(errnum) -+#else -+# define zstrerror(errnum) "" -+#endif -+ -+#if defined(pyr) -+# define NO_MEMCPY -+#endif -+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) -+ /* Use our own functions for small and medium model with MSC <= 5.0. -+ * You may have to use the same strategy for Borland C (untested). -+ * The __SC__ check is for Symantec. -+ */ -+# define NO_MEMCPY -+#endif -+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) -+# define HAVE_MEMCPY -+#endif -+#ifdef HAVE_MEMCPY -+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ -+# define zmemcpy _fmemcpy -+# define zmemcmp _fmemcmp -+# define zmemzero(dest, len) _fmemset(dest, 0, len) -+# else -+# define zmemcpy memcpy -+# define zmemcmp memcmp -+# define zmemzero(dest, len) memset(dest, 0, len) -+# endif -+#else -+ extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); -+ extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); -+ extern void zmemzero OF((Bytef* dest, uInt len)); -+#endif -+ -+/* Diagnostic functions */ -+#ifdef DEBUG -+# include -+ extern int z_verbose; -+ extern void z_error OF((char *m)); -+# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -+# define Trace(x) {if (z_verbose>=0) fprintf x ;} -+# define Tracev(x) {if (z_verbose>0) fprintf x ;} -+# define Tracevv(x) {if (z_verbose>1) fprintf x ;} -+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} -+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} -+#else -+# define Assert(cond,msg) -+# define Trace(x) -+# define Tracev(x) -+# define Tracevv(x) -+# define Tracec(c,x) -+# define Tracecv(c,x) -+#endif -+ -+ -+typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, -+ uInt len)); -+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); -+void zcfree OF((voidpf opaque, voidpf ptr)); -+ -+#define ZALLOC(strm, items, size) \ -+ (*((strm)->zalloc))((strm)->opaque, (items), (size)) -+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) -+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} -+ -+#endif /* _Z_UTIL_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/Makefile.objs Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,21 @@ -+obj-y += satot.o -+obj-y += addrtot.o -+obj-y += ultot.o -+obj-y += addrtypeof.o -+obj-y += anyaddr.o -+obj-y += initaddr.o -+obj-y += ultoa.o -+obj-y += addrtoa.o -+obj-y += subnettoa.o -+obj-y += subnetof.o -+obj-y += goodmask.o -+obj-y += datatot.o -+obj-y += rangetoa.o -+obj-y += prng.o -+obj-y += pfkey_v2_parse.o -+obj-y += pfkey_v2_build.o -+obj-y += pfkey_v2_debug.o -+obj-y += pfkey_v2_ext_bits.o -+ -+#version.c: ${LIBFREESWANDIR}/version.in.c ${OPENSWANSRCDIR}/Makefile.ver -+# sed '/"/s/xxx/$(IPSECVERSION)/' ${LIBFREESWANDIR}/version.in.c >$@ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/addrtoa.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,67 @@ -+/* -+ * addresses to ASCII -+ * Copyright (C) 1998, 1999 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+#define NBYTES 4 /* bytes in an address */ -+#define PERBYTE 4 /* three digits plus a dot or NUL */ -+#define BUFLEN (NBYTES*PERBYTE) -+ -+#if BUFLEN != ADDRTOA_BUF -+#error "ADDRTOA_BUF in openswan.h inconsistent with addrtoa() code" -+#endif -+ -+/* -+ - addrtoa - convert binary address to ASCII dotted decimal -+ */ -+size_t /* space needed for full conversion */ -+addrtoa(addr, format, dst, dstlen) -+struct in_addr addr; -+int format; /* character */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ unsigned long a = ntohl(addr.s_addr); -+ int i; -+ size_t n; -+ unsigned long byte; -+ char buf[BUFLEN]; -+ char *p; -+ -+ switch (format) { -+ case 0: -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ p = buf; -+ for (i = NBYTES-1; i >= 0; i--) { -+ byte = (a >> (i*8)) & 0xff; -+ p += ultoa(byte, 10, p, PERBYTE); -+ if (i != 0) -+ *(p-1) = '.'; -+ } -+ n = p - buf; -+ -+ if (dstlen > 0) { -+ if (n > dstlen) -+ buf[dstlen - 1] = '\0'; -+ strcpy(dst, buf); -+ } -+ return n; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/addrtot.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,334 @@ -+/* -+ * addresses to text -+ * Copyright (C) 2000 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+#define IP4BYTES 4 /* bytes in an IPv4 address */ -+#define PERBYTE 4 /* three digits plus a dot or NUL */ -+#define IP6BYTES 16 /* bytes in an IPv6 address */ -+ -+/* forwards */ -+static size_t normal4(const unsigned char *s, size_t len, char *b, char **dp); -+static size_t normal6(const unsigned char *s, size_t len, char *b, char **dp, int squish); -+static size_t reverse4(const unsigned char *s, size_t len, char *b, char **dp); -+static size_t reverse6(const unsigned char *s, size_t len, char *b, char **dp); -+ -+/* -+ - addrtot - convert binary address to text (dotted decimal or IPv6 string) -+ */ -+size_t /* space needed for full conversion */ -+addrtot(src, format, dst, dstlen) -+const ip_address *src; -+int format; /* character */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ const unsigned char *b; -+ size_t n; -+ char buf[1+ADDRTOT_BUF+1]; /* :address: */ -+ char *p; -+ int t = addrtypeof(src); -+# define TF(t, f) (((t)<<8) | (f)) -+ -+ n = addrbytesptr(src, &b); -+ if (n == 0) { -+ bad: -+ dst[0]='\0'; -+ strncat(dst, "", dstlen); -+ return sizeof(""); -+ } -+ -+ switch (TF(t, format)) { -+ case TF(AF_INET, 0): -+ n = normal4(b, n, buf, &p); -+ break; -+ case TF(AF_INET6, 0): -+ n = normal6(b, n, buf, &p, 1); -+ break; -+ case TF(AF_INET, 'Q'): -+ n = normal4(b, n, buf, &p); -+ break; -+ case TF(AF_INET6, 'Q'): -+ n = normal6(b, n, buf, &p, 0); -+ break; -+ case TF(AF_INET, 'r'): -+ n = reverse4(b, n, buf, &p); -+ break; -+ case TF(AF_INET6, 'r'): -+ n = reverse6(b, n, buf, &p); -+ break; -+ default: /* including (AF_INET, 'R') */ -+ goto bad; -+ break; -+ } -+ -+ if (dstlen > 0) { -+ if (dstlen < n) -+ p[dstlen - 1] = '\0'; -+ strcpy(dst, p); -+ } -+ return n; -+} -+ -+/* -+ - normal4 - normal IPv4 address-text conversion -+ */ -+static size_t /* size of text, including NUL */ -+normal4(srcp, srclen, buf, dstp) -+const unsigned char *srcp; -+size_t srclen; -+char *buf; /* guaranteed large enough */ -+char **dstp; /* where to put result pointer */ -+{ -+ int i; -+ char *p; -+ -+ if (srclen != IP4BYTES) /* "can't happen" */ -+ return 0; -+ p = buf; -+ for (i = 0; i < IP4BYTES; i++) { -+ p += ultot(srcp[i], 10, p, PERBYTE); -+ if (i != IP4BYTES - 1) -+ *(p-1) = '.'; /* overwrites the NUL */ -+ } -+ *dstp = buf; -+ return p - buf; -+} -+ -+/* -+ - normal6 - normal IPv6 address-text conversion -+ */ -+static size_t /* size of text, including NUL */ -+normal6(srcp, srclen, buf, dstp, squish) -+const unsigned char *srcp; -+size_t srclen; -+char *buf; /* guaranteed large enough, plus 2 */ -+char **dstp; /* where to put result pointer */ -+int squish; /* whether to squish out 0:0 */ -+{ -+ int i; -+ unsigned long piece; -+ char *p; -+ char *q; -+ -+ if (srclen != IP6BYTES) /* "can't happen" */ -+ return 0; -+ p = buf; -+ *p++ = ':'; -+ for (i = 0; i < IP6BYTES/2; i++) { -+ piece = (srcp[2*i] << 8) + srcp[2*i + 1]; -+ p += ultot(piece, 16, p, 5); /* 5 = abcd + NUL */ -+ *(p-1) = ':'; /* overwrites the NUL */ -+ } -+ *p = '\0'; -+ q = strstr(buf, ":0:0:"); -+ if (squish && q != NULL) { /* zero squishing is possible */ -+ p = q + 1; -+ while (*p == '0' && *(p+1) == ':') -+ p += 2; -+ q++; -+ *q++ = ':'; /* overwrite first 0 */ -+ while (*p != '\0') -+ *q++ = *p++; -+ *q = '\0'; -+ if (!(*(q-1) == ':' && *(q-2) == ':')) -+ *--q = '\0'; /* strip final : unless :: */ -+ p = buf; -+ if (!(*p == ':' && *(p+1) == ':')) -+ p++; /* skip initial : unless :: */ -+ } else { -+ q = p; -+ *--q = '\0'; /* strip final : */ -+ p = buf + 1; /* skip initial : */ -+ } -+ *dstp = p; -+ return q - p + 1; -+} -+ -+/* -+ - reverse4 - IPv4 reverse-lookup conversion -+ */ -+static size_t /* size of text, including NUL */ -+reverse4(srcp, srclen, buf, dstp) -+const unsigned char *srcp; -+size_t srclen; -+char *buf; /* guaranteed large enough */ -+char **dstp; /* where to put result pointer */ -+{ -+ int i; -+ char *p; -+ -+ if (srclen != IP4BYTES) /* "can't happen" */ -+ return 0; -+ p = buf; -+ for (i = IP4BYTES-1; i >= 0; i--) { -+ p += ultot(srcp[i], 10, p, PERBYTE); -+ *(p-1) = '.'; /* overwrites the NUL */ -+ } -+ strcpy(p, "IN-ADDR.ARPA."); -+ *dstp = buf; -+ return strlen(buf) + 1; -+} -+ -+/* -+ - reverse6 - IPv6 reverse-lookup conversion (RFC 1886) -+ * A trifle inefficient, really shouldn't use ultot... -+ */ -+static size_t /* size of text, including NUL */ -+reverse6(srcp, srclen, buf, dstp) -+const unsigned char *srcp; -+size_t srclen; -+char *buf; /* guaranteed large enough */ -+char **dstp; /* where to put result pointer */ -+{ -+ int i; -+ unsigned long piece; -+ char *p; -+ -+ if (srclen != IP6BYTES) /* "can't happen" */ -+ return 0; -+ p = buf; -+ for (i = IP6BYTES-1; i >= 0; i--) { -+ piece = srcp[i]; -+ p += ultot(piece&0xf, 16, p, 2); -+ *(p-1) = '.'; -+ p += ultot(piece>>4, 16, p, 2); -+ *(p-1) = '.'; -+ } -+ strcpy(p, "IP6.ARPA."); -+ *dstp = buf; -+ return strlen(buf) + 1; -+} -+ -+/* -+ - reverse6 - modern IPv6 reverse-lookup conversion (RFC 2874) -+ * this version removed as it was obsoleted in the end. -+ */ -+ -+#ifdef ADDRTOT_MAIN -+ -+#include -+#include -+#include -+#include -+ -+void regress(void); -+ -+int -+main(int argc, char *argv[]) -+{ -+ if (argc < 2) { -+ fprintf(stderr, "Usage: %s {addr|net/mask|begin...end|-r}\n", -+ argv[0]); -+ exit(2); -+ } -+ -+ if (strcmp(argv[1], "-r") == 0) { -+ regress(); -+ fprintf(stderr, "regress() returned?!?\n"); -+ exit(1); -+ } -+ exit(0); -+} -+ -+struct rtab { -+ char *input; -+ char format; -+ char *output; /* NULL means error expected */ -+} rtab[] = { -+ {"1.2.3.0", 0, "1.2.3.0"}, -+ {"1:2::3:4", 0, "1:2::3:4"}, -+ {"1:2::3:4", 'Q', "1:2:0:0:0:0:3:4"}, -+ {"1:2:0:0:3:4:0:0", 0, "1:2::3:4:0:0"}, -+ {"1.2.3.4", 'r' , "4.3.2.1.IN-ADDR.ARPA."}, -+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -+ {"1:2::3:4", 'r', "4.0.0.0.3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.1.0.0.0.IP6.ARPA."}, -+ {NULL, 0, NULL} -+}; -+ -+void -+regress() -+{ -+ struct rtab *r; -+ int status = 0; -+ ip_address a; -+ char in[100]; -+ char buf[100]; -+ const char *oops; -+ size_t n; -+ -+ for (r = rtab; r->input != NULL; r++) { -+ strcpy(in, r->input); -+ -+ /* convert it *to* internal format */ -+ oops = ttoaddr(in, strlen(in), 0, &a); -+ -+ /* now convert it back */ -+ -+ n = addrtot(&a, r->format, buf, sizeof(buf)); -+ -+ if (n == 0 && r->output == NULL) -+ {} /* okay, error expected */ -+ -+ else if (n == 0) { -+ printf("`%s' atoasr failed\n", r->input); -+ status = 1; -+ -+ } else if (r->output == NULL) { -+ printf("`%s' atoasr succeeded unexpectedly '%c'\n", -+ r->input, r->format); -+ status = 1; -+ } else { -+ if (strcasecmp(r->output, buf) != 0) { -+ printf("`%s' '%c' gave `%s', expected `%s'\n", -+ r->input, r->format, buf, r->output); -+ status = 1; -+ } -+ } -+ } -+ exit(status); -+} -+ -+#endif /* ADDRTOT_MAIN */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.15 2004/04/11 17:39:25 mcr -+ * removed internal.h requirements. -+ * -+ * Revision 1.14 2004/03/08 01:59:08 ken -+ * freeswan.h -> openswan.h -+ * -+ * Revision 1.13 2004/01/05 23:21:05 mcr -+ * if the address type is invalid, then return length of -+ * string! -+ * -+ * Revision 1.12 2003/12/30 06:42:48 mcr -+ * added $Log$ -+ * added Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * added Turn off EOLN_NATIVE flag -+ * added -+ * added (Logical change 1.5010) -+ * added -+ * added Revision 1.15 2004/04/11 17:39:25 mcr -+ * added removed internal.h requirements. -+ * added -+ * added Revision 1.14 2004/03/08 01:59:08 ken -+ * added freeswan.h -> openswan.h -+ * added -+ * added Revision 1.13 2004/01/05 23:21:05 mcr -+ * added if the address type is invalid, then return length of -+ * added string! -+ * added -+ * -+ * -+ */ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/addrtypeof.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,93 @@ -+/* -+ * extract parts of an ip_address -+ * Copyright (C) 2000 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - addrtypeof - get the type of an ip_address -+ */ -+int -+addrtypeof(src) -+const ip_address *src; -+{ -+ return src->u.v4.sin_family; -+} -+ -+/* -+ - addrbytesptr - get pointer to the address bytes of an ip_address -+ */ -+size_t /* 0 for error */ -+addrbytesptr(src, dstp) -+const ip_address *src; -+const unsigned char **dstp; /* NULL means just a size query */ -+{ -+ const unsigned char *p; -+ size_t n; -+ -+ switch (src->u.v4.sin_family) { -+ case AF_INET: -+ p = (const unsigned char *)&src->u.v4.sin_addr.s_addr; -+ n = 4; -+ break; -+ case AF_INET6: -+ p = (const unsigned char *)&src->u.v6.sin6_addr; -+ n = 16; -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ if (dstp != NULL) -+ *dstp = p; -+ return n; -+} -+ -+/* -+ - addrlenof - get length of the address bytes of an ip_address -+ */ -+size_t /* 0 for error */ -+addrlenof(src) -+const ip_address *src; -+{ -+ return addrbytesptr(src, NULL); -+} -+ -+/* -+ - addrbytesof - get the address bytes of an ip_address -+ */ -+size_t /* 0 for error */ -+addrbytesof(src, dst, dstlen) -+const ip_address *src; -+unsigned char *dst; -+size_t dstlen; -+{ -+ const unsigned char *p; -+ size_t n; -+ size_t ncopy; -+ -+ n = addrbytesptr(src, &p); -+ if (n == 0) -+ return 0; -+ -+ if (dstlen > 0) { -+ ncopy = n; -+ if (ncopy > dstlen) -+ ncopy = dstlen; -+ memcpy(dst, p, ncopy); -+ } -+ return n; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/anyaddr.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,145 @@ -+/* -+ * special addresses -+ * Copyright (C) 2000 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* these are mostly fallbacks for the no-IPv6-support-in-library case */ -+#ifndef IN6ADDR_ANY_INIT -+#define IN6ADDR_ANY_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}} -+#endif -+#ifndef IN6ADDR_LOOPBACK_INIT -+#define IN6ADDR_LOOPBACK_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}} -+#endif -+ -+static struct in6_addr v6any = IN6ADDR_ANY_INIT; -+static struct in6_addr v6loop = IN6ADDR_LOOPBACK_INIT; -+ -+/* -+ - anyaddr - initialize to the any-address value -+ */ -+err_t /* NULL for success, else string literal */ -+anyaddr(af, dst) -+int af; /* address family */ -+ip_address *dst; -+{ -+ uint32_t v4any = htonl(INADDR_ANY); -+ -+ switch (af) { -+ case AF_INET: -+ return initaddr((unsigned char *)&v4any, sizeof(v4any), af, dst); -+ break; -+ case AF_INET6: -+ return initaddr((unsigned char *)&v6any, sizeof(v6any), af, dst); -+ break; -+ default: -+ return "unknown address family in anyaddr/unspecaddr"; -+ break; -+ } -+} -+ -+/* -+ - unspecaddr - initialize to the unspecified-address value -+ */ -+err_t /* NULL for success, else string literal */ -+unspecaddr(af, dst) -+int af; /* address family */ -+ip_address *dst; -+{ -+ return anyaddr(af, dst); -+} -+ -+/* -+ - loopbackaddr - initialize to the loopback-address value -+ */ -+err_t /* NULL for success, else string literal */ -+loopbackaddr(af, dst) -+int af; /* address family */ -+ip_address *dst; -+{ -+ uint32_t v4loop = htonl(INADDR_LOOPBACK); -+ -+ switch (af) { -+ case AF_INET: -+ return initaddr((unsigned char *)&v4loop, sizeof(v4loop), af, dst); -+ break; -+ case AF_INET6: -+ return initaddr((unsigned char *)&v6loop, sizeof(v6loop), af, dst); -+ break; -+ default: -+ return "unknown address family in loopbackaddr"; -+ break; -+ } -+} -+ -+/* -+ - isanyaddr - test for the any-address value -+ */ -+int -+isanyaddr(src) -+const ip_address *src; -+{ -+ uint32_t v4any = htonl(INADDR_ANY); -+ int cmp; -+ -+ switch (src->u.v4.sin_family) { -+ case AF_INET: -+ cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4any, sizeof(v4any)); -+ break; -+ case AF_INET6: -+ cmp = memcmp(&src->u.v6.sin6_addr, &v6any, sizeof(v6any)); -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ return (cmp == 0) ? 1 : 0; -+} -+ -+/* -+ - isunspecaddr - test for the unspecified-address value -+ */ -+int -+isunspecaddr(src) -+const ip_address *src; -+{ -+ return isanyaddr(src); -+} -+ -+/* -+ - isloopbackaddr - test for the loopback-address value -+ */ -+int -+isloopbackaddr(src) -+const ip_address *src; -+{ -+ uint32_t v4loop = htonl(INADDR_LOOPBACK); -+ int cmp; -+ -+ switch (src->u.v4.sin_family) { -+ case AF_INET: -+ cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4loop, sizeof(v4loop)); -+ break; -+ case AF_INET6: -+ cmp = memcmp(&src->u.v6.sin6_addr, &v6loop, sizeof(v6loop)); -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ return (cmp == 0) ? 1 : 0; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/datatot.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,232 @@ -+/* -+ * convert from binary data (e.g. key) to text form -+ * Copyright (C) 2000 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+static void convert(const char *src, size_t nreal, int format, char *out); -+ -+/* -+ - datatot - convert data bytes to text -+ */ -+size_t /* true length (with NUL) for success */ -+datatot(src, srclen, format, dst, dstlen) -+const char *src; -+size_t srclen; -+int format; /* character indicating what format */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ size_t inblocksize; /* process this many bytes at a time */ -+ size_t outblocksize; /* producing this many */ -+ size_t breakevery; /* add a _ every this many (0 means don't) */ -+ size_t sincebreak; /* output bytes since last _ */ -+ char breakchar; /* character used to break between groups */ -+ char inblock[10]; /* enough for any format */ -+ char outblock[10]; /* enough for any format */ -+ char fake[1]; /* fake output area for dstlen == 0 */ -+ size_t needed; /* return value */ -+ char *stop; /* where the terminating NUL will go */ -+ size_t ntodo; /* remaining input */ -+ size_t nreal; -+ char *out; -+ char *prefix; -+ -+ breakevery = 0; -+ breakchar = '_'; -+ -+ switch (format) { -+ case 0: -+ case 'h': -+ format = 'x'; -+ breakevery = 8; -+ /* FALLTHROUGH */ -+ case 'x': -+ inblocksize = 1; -+ outblocksize = 2; -+ prefix = "0x"; -+ break; -+ case ':': -+ format = 'x'; -+ breakevery = 2; -+ breakchar = ':'; -+ /* FALLTHROUGH */ -+ case 16: -+ inblocksize = 1; -+ outblocksize = 2; -+ prefix = ""; -+ format = 'x'; -+ break; -+ case 's': -+ inblocksize = 3; -+ outblocksize = 4; -+ prefix = "0s"; -+ break; -+ case 64: /* beware, equals ' ' */ -+ inblocksize = 3; -+ outblocksize = 4; -+ prefix = ""; -+ format = 's'; -+ break; -+ default: -+ return 0; -+ break; -+ } -+ assert(inblocksize < sizeof(inblock)); -+ assert(outblocksize < sizeof(outblock)); -+ assert(breakevery % outblocksize == 0); -+ -+ if (srclen == 0) -+ return 0; -+ ntodo = srclen; -+ -+ if (dstlen == 0) { /* dispose of awkward special case */ -+ dst = fake; -+ dstlen = 1; -+ } -+ stop = dst + dstlen - 1; -+ -+ nreal = strlen(prefix); -+ needed = nreal; /* for starters */ -+ if (dstlen <= nreal) { /* prefix won't fit */ -+ strncpy(dst, prefix, dstlen - 1); -+ dst += dstlen - 1; -+ } else { -+ strcpy(dst, prefix); -+ dst += nreal; -+ } -+ assert(dst <= stop); -+ sincebreak = 0; -+ -+ while (ntodo > 0) { -+ if (ntodo < inblocksize) { /* incomplete input */ -+ memset(inblock, 0, sizeof(inblock)); -+ memcpy(inblock, src, ntodo); -+ src = inblock; -+ nreal = ntodo; -+ ntodo = inblocksize; -+ } else -+ nreal = inblocksize; -+ out = (outblocksize > stop - dst) ? outblock : dst; -+ -+ convert(src, nreal, format, out); -+ needed += outblocksize; -+ sincebreak += outblocksize; -+ if (dst < stop) { -+ if (out != dst) { -+ assert(outblocksize > stop - dst); -+ memcpy(dst, out, stop - dst); -+ dst = stop; -+ } else -+ dst += outblocksize; -+ } -+ -+ src += inblocksize; -+ ntodo -= inblocksize; -+ if (breakevery != 0 && sincebreak >= breakevery && ntodo > 0) { -+ if (dst < stop) -+ *dst++ = breakchar; -+ needed++; -+ sincebreak = 0; -+ } -+ } -+ -+ assert(dst <= stop); -+ *dst++ = '\0'; -+ needed++; -+ -+ return needed; -+} -+ -+/* -+ - convert - convert one input block to one output block -+ */ -+static void -+convert(src, nreal, format, out) -+const char *src; -+size_t nreal; /* how much of the input block is real */ -+int format; -+char *out; -+{ -+ static char hex[] = "0123456789abcdef"; -+ static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -+ "abcdefghijklmnopqrstuvwxyz" -+ "0123456789+/"; -+ unsigned char c; -+ unsigned char c1, c2, c3; -+ -+ assert(nreal > 0); -+ switch (format) { -+ case 'x': -+ assert(nreal == 1); -+ c = (unsigned char)*src; -+ *out++ = hex[c >> 4]; -+ *out++ = hex[c & 0xf]; -+ break; -+ case 's': -+ c1 = (unsigned char)*src++; -+ c2 = (unsigned char)*src++; -+ c3 = (unsigned char)*src++; -+ *out++ = base64[c1 >> 2]; /* top 6 bits of c1 */ -+ c = (c1 & 0x3) << 4; /* bottom 2 of c1... */ -+ c |= c2 >> 4; /* ...top 4 of c2 */ -+ *out++ = base64[c]; -+ if (nreal == 1) -+ *out++ = '='; -+ else { -+ c = (c2 & 0xf) << 2; /* bottom 4 of c2... */ -+ c |= c3 >> 6; /* ...top 2 of c3 */ -+ *out++ = base64[c]; -+ } -+ if (nreal <= 2) -+ *out++ = '='; -+ else -+ *out++ = base64[c3 & 0x3f]; /* bottom 6 of c3 */ -+ break; -+ default: -+ assert(nreal == 0); /* unknown format */ -+ break; -+ } -+} -+ -+/* -+ - datatoa - convert data to ASCII -+ * backward-compatibility synonym for datatot -+ */ -+size_t /* true length (with NUL) for success */ -+datatoa(src, srclen, format, dst, dstlen) -+const char *src; -+size_t srclen; -+int format; /* character indicating what format */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ return datatot(src, srclen, format, dst, dstlen); -+} -+ -+/* -+ - bytestoa - convert data bytes to ASCII -+ * backward-compatibility synonym for datatot -+ */ -+size_t /* true length (with NUL) for success */ -+bytestoa(src, srclen, format, dst, dstlen) -+const char *src; -+size_t srclen; -+int format; /* character indicating what format */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ return datatot(src, srclen, format, dst, dstlen); -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/goodmask.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,100 @@ -+/* -+ * minor utilities for subnet-mask manipulation -+ * Copyright (C) 1998, 1999 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+#ifndef ABITS -+#define ABITS 32 /* bits in an IPv4 address */ -+#endif -+ -+/* -+ - goodmask - is this a good (^1*0*$) subnet mask? -+ * You are not expected to understand this. See Henry S. Warren Jr, -+ * "Functions realizable with word-parallel logical and two's-complement -+ * addition instructions", CACM 20.6 (June 1977), p.439. -+ */ -+int /* predicate */ -+goodmask(mask) -+struct in_addr mask; -+{ -+ unsigned long x = ntohl(mask.s_addr); -+ /* clear rightmost contiguous string of 1-bits */ -+# define CRCS1B(x) (((x|(x-1))+1)&x) -+# define TOPBIT (1UL << 31) -+ -+ /* either zero, or has one string of 1-bits which is left-justified */ -+ if (x == 0 || (CRCS1B(x) == 0 && (x&TOPBIT))) -+ return 1; -+ return 0; -+} -+ -+/* -+ - masktobits - how many bits in this mask? -+ * The algorithm is essentially a binary search, but highly optimized -+ * for this particular task. -+ */ -+int /* -1 means !goodmask() */ -+masktobits(mask) -+struct in_addr mask; -+{ -+ unsigned long m = ntohl(mask.s_addr); -+ int masklen; -+ -+ if (!goodmask(mask)) -+ return -1; -+ -+ if (m&0x00000001UL) -+ return 32; -+ masklen = 0; -+ if (m&(0x0000ffffUL<<1)) { /* <<1 for 1-origin numbering */ -+ masklen |= 0x10; -+ m <<= 16; -+ } -+ if (m&(0x00ff0000UL<<1)) { -+ masklen |= 0x08; -+ m <<= 8; -+ } -+ if (m&(0x0f000000UL<<1)) { -+ masklen |= 0x04; -+ m <<= 4; -+ } -+ if (m&(0x30000000UL<<1)) { -+ masklen |= 0x02; -+ m <<= 2; -+ } -+ if (m&(0x40000000UL<<1)) -+ masklen |= 0x01; -+ -+ return masklen; -+} -+ -+/* -+ - bitstomask - return a mask with this many high bits on -+ */ -+struct in_addr -+bitstomask(n) -+int n; -+{ -+ struct in_addr result; -+ -+ if (n > 0 && n <= ABITS) -+ result.s_addr = htonl(~((1UL << (ABITS - n)) - 1)); -+ else if (n == 0) -+ result.s_addr = 0; -+ else -+ result.s_addr = 0; /* best error report we can do */ -+ return result; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/initaddr.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,50 @@ -+/* -+ * initialize address structure -+ * Copyright (C) 2000 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - initaddr - initialize ip_address from bytes -+ */ -+err_t /* NULL for success, else string literal */ -+initaddr(src, srclen, af, dst) -+const unsigned char *src; -+size_t srclen; -+int af; /* address family */ -+ip_address *dst; -+{ -+ switch (af) { -+ case AF_INET: -+ if (srclen != 4) -+ return "IPv4 address must be exactly 4 bytes"; -+ dst->u.v4.sin_family = af; -+ dst->u.v4.sin_port = 0; /* unused */ -+ memcpy((char *)&dst->u.v4.sin_addr.s_addr, src, srclen); -+ break; -+ case AF_INET6: -+ if (srclen != 16) -+ return "IPv6 address must be exactly 16 bytes"; -+ dst->u.v6.sin6_family = af; -+ dst->u.v6.sin6_flowinfo = 0; /* unused */ -+ dst->u.v6.sin6_port = 0; /* unused */ -+ memcpy((char *)&dst->u.v6.sin6_addr, src, srclen); -+ break; -+ default: -+ return "unknown address family in initaddr"; -+ break; -+ } -+ return NULL; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/pfkey_v2_build.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1559 @@ -+/* -+ * RFC2367 PF_KEYv2 Key management API message parser -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* -+ * Template from klips/net/ipsec/ipsec/ipsec_parser.c. -+ */ -+ -+char pfkey_v2_build_c_version[] = "$Id$"; -+ -+/* -+ * Some ugly stuff to allow consistent debugging code for use in the -+ * kernel and in user space -+*/ -+ -+#ifdef __KERNEL__ -+ -+# include /* for printk */ -+ -+# include "openswan/ipsec_kversion.h" /* for malloc switch */ -+# ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+# else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+# endif /* MALLOC_SLAB */ -+# include /* error codes */ -+# include /* size_t */ -+# include /* mark_bh */ -+ -+# include /* struct device, and other headers */ -+# include /* eth_type_trans */ -+# include /* struct iphdr */ -+# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+# include /* struct ipv6hdr */ -+# endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ -+ -+# define MALLOC(size) kmalloc(size, GFP_ATOMIC) -+# define FREE(obj) kfree(obj) -+# include -+#else /* __KERNEL__ */ -+ -+# include -+# include -+# include -+# include -+# include /* memset */ -+ -+# include -+ -+#endif /* __KERNEL__ */ -+ -+#include -+#include -+ -+#ifdef __KERNEL__ -+#include "openswan/radij.h" /* rd_nodes */ -+#include "openswan/ipsec_encap.h" /* sockaddr_encap */ -+#endif /* __KERNEL__ */ -+ -+ -+#include "openswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */ -+#include "openswan/pfkey_debug.h" -+ -+ -+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) -+ -+void -+pfkey_extensions_init(struct sadb_ext *extensions[SADB_EXT_MAX + 1]) -+{ -+ int i; -+ -+ for (i = 0; i != SADB_EXT_MAX + 1; i++) { -+ extensions[i] = NULL; -+ } -+} -+ -+void -+pfkey_extensions_free(struct sadb_ext *extensions[SADB_EXT_MAX + 1]) -+{ -+ int i; -+ -+ if(!extensions) { -+ return; -+ } -+ -+ if(extensions[0]) { -+ memset(extensions[0], 0, sizeof(struct sadb_msg)); -+ FREE(extensions[0]); -+ extensions[0] = NULL; -+ } -+ -+ for (i = 1; i != SADB_EXT_MAX + 1; i++) { -+ if(extensions[i]) { -+ memset(extensions[i], 0, extensions[i]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); -+ FREE(extensions[i]); -+ extensions[i] = NULL; -+ } -+ } -+} -+ -+void -+pfkey_msg_free(struct sadb_msg **pfkey_msg) -+{ -+ if(*pfkey_msg) { -+ memset(*pfkey_msg, 0, (*pfkey_msg)->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); -+ FREE(*pfkey_msg); -+ *pfkey_msg = NULL; -+ } -+} -+ -+/* Default extension builders taken from the KLIPS code */ -+ -+int -+pfkey_msg_hdr_build(struct sadb_ext** pfkey_ext, -+ uint8_t msg_type, -+ uint8_t satype, -+ uint8_t msg_errno, -+ uint32_t seq, -+ uint32_t pid) -+{ -+ int error = 0; -+ struct sadb_msg *pfkey_msg = (struct sadb_msg *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build:\n"); -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build: " -+ "on_entry &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n", -+ &pfkey_ext, -+ pfkey_ext, -+ *pfkey_ext); -+ /* sanity checks... */ -+ if(pfkey_msg) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build: " -+ "why is pfkey_msg already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(!msg_type) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build: " -+ "msg type not set, must be non-zero..\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(msg_type > SADB_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build: " -+ "msg type too large:%d.\n", -+ msg_type); -+ SENDERR(EINVAL); -+ } -+ -+ if(satype > SADB_SATYPE_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build: " -+ "satype %d > max %d\n", -+ satype, SADB_SATYPE_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_msg = (struct sadb_msg*) -+ MALLOC(sizeof(struct sadb_msg)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_msg, 0, sizeof(struct sadb_msg)); -+ -+ pfkey_msg->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN; -+ -+ pfkey_msg->sadb_msg_type = msg_type; -+ pfkey_msg->sadb_msg_satype = satype; -+ -+ pfkey_msg->sadb_msg_version = PF_KEY_V2; -+ pfkey_msg->sadb_msg_errno = msg_errno; -+ pfkey_msg->sadb_msg_reserved = 0; -+ pfkey_msg->sadb_msg_seq = seq; -+ pfkey_msg->sadb_msg_pid = pid; -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_hdr_build: " -+ "on_exit &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n", -+ &pfkey_ext, -+ pfkey_ext, -+ *pfkey_ext); -+errlab: -+ return error; -+} -+ -+int -+pfkey_sa_ref_build(struct sadb_ext ** pfkey_ext, -+ uint16_t exttype, -+ uint32_t spi, -+ uint8_t replay_window, -+ uint8_t sa_state, -+ uint8_t auth, -+ uint8_t encrypt, -+ uint32_t flags, -+ uint32_t/*IPsecSAref_t*/ ref) -+{ -+ int error = 0; -+ struct sadb_sa *pfkey_sa = (struct sadb_sa *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "spi=%08x replay=%d sa_state=%d auth=%d encrypt=%d flags=%d\n", -+ ntohl(spi), /* in network order */ -+ replay_window, -+ sa_state, -+ auth, -+ encrypt, -+ flags); -+ /* sanity checks... */ -+ if(pfkey_sa) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "why is pfkey_sa already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(exttype != SADB_EXT_SA && -+ exttype != SADB_X_EXT_SA2) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "invalid exttype=%d.\n", -+ exttype); -+ SENDERR(EINVAL); -+ } -+ -+ if(replay_window > 64) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "replay window size: %d -- must be 0 <= size <= 64\n", -+ replay_window); -+ SENDERR(EINVAL); -+ } -+ -+ if(auth > SADB_AALG_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "auth=%d > SADB_AALG_MAX=%d.\n", -+ auth, -+ SADB_AALG_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(encrypt > SADB_EALG_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "encrypt=%d > SADB_EALG_MAX=%d.\n", -+ encrypt, -+ SADB_EALG_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(sa_state > SADB_SASTATE_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "sa_state=%d exceeds MAX=%d.\n", -+ sa_state, -+ SADB_SASTATE_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(sa_state == SADB_SASTATE_DEAD) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "sa_state=%d is DEAD=%d is not allowed.\n", -+ sa_state, -+ SADB_SASTATE_DEAD); -+ SENDERR(EINVAL); -+ } -+ -+ if((IPSEC_SAREF_NULL != ref) && (ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n", -+ ref, -+ IPSEC_SAREF_NULL, -+ IPSEC_SA_REF_TABLE_NUM_ENTRIES); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_sa = (struct sadb_sa*) -+ MALLOC(sizeof(struct sadb_sa)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sa_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_sa, 0, sizeof(struct sadb_sa)); -+ -+ pfkey_sa->sadb_sa_len = sizeof(*pfkey_sa) / IPSEC_PFKEYv2_ALIGN; -+ pfkey_sa->sadb_sa_exttype = exttype; -+ pfkey_sa->sadb_sa_spi = spi; -+ pfkey_sa->sadb_sa_replay = replay_window; -+ pfkey_sa->sadb_sa_state = sa_state; -+ pfkey_sa->sadb_sa_auth = auth; -+ pfkey_sa->sadb_sa_encrypt = encrypt; -+ pfkey_sa->sadb_sa_flags = flags; -+ pfkey_sa->sadb_x_sa_ref = ref; -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_sa_build(struct sadb_ext ** pfkey_ext, -+ uint16_t exttype, -+ uint32_t spi, -+ uint8_t replay_window, -+ uint8_t sa_state, -+ uint8_t auth, -+ uint8_t encrypt, -+ uint32_t flags) -+{ -+ return pfkey_sa_ref_build(pfkey_ext, -+ exttype, -+ spi, -+ replay_window, -+ sa_state, -+ auth, -+ encrypt, -+ flags, -+ IPSEC_SAREF_NULL); -+} -+ -+int -+pfkey_lifetime_build(struct sadb_ext ** pfkey_ext, -+ uint16_t exttype, -+ uint32_t allocations, -+ uint64_t bytes, -+ uint64_t addtime, -+ uint64_t usetime, -+ uint32_t packets) -+{ -+ int error = 0; -+ struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_lifetime_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_lifetime) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_lifetime_build: " -+ "why is pfkey_lifetime already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(exttype != SADB_EXT_LIFETIME_CURRENT && -+ exttype != SADB_EXT_LIFETIME_HARD && -+ exttype != SADB_EXT_LIFETIME_SOFT) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_lifetime_build: " -+ "invalid exttype=%d.\n", -+ exttype); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_lifetime = (struct sadb_lifetime*) -+ MALLOC(sizeof(struct sadb_lifetime)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_lifetime_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_lifetime, 0, sizeof(struct sadb_lifetime)); -+ -+ pfkey_lifetime->sadb_lifetime_len = sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN; -+ pfkey_lifetime->sadb_lifetime_exttype = exttype; -+ pfkey_lifetime->sadb_lifetime_allocations = allocations; -+ pfkey_lifetime->sadb_lifetime_bytes = bytes; -+ pfkey_lifetime->sadb_lifetime_addtime = addtime; -+ pfkey_lifetime->sadb_lifetime_usetime = usetime; -+ pfkey_lifetime->sadb_x_lifetime_packets = packets; -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_address_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint8_t proto, -+ uint8_t prefixlen, -+ struct sockaddr* address) -+{ -+ int error = 0; -+ int saddr_len = 0; -+ char ipaddr_txt[ADDRTOT_BUF + 6/*extra for port number*/]; -+ struct sadb_address *pfkey_address = (struct sadb_address *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_address_build: " -+ "exttype=%d proto=%d prefixlen=%d\n", -+ exttype, -+ proto, -+ prefixlen); -+ /* sanity checks... */ -+ if(pfkey_address) { -+ ERROR("pfkey_address_build: " -+ "why is pfkey_address already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if (!address) { -+ ERROR("pfkey_address_build: " "address is NULL\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(exttype) { -+ case SADB_EXT_ADDRESS_SRC: -+ case SADB_EXT_ADDRESS_DST: -+ case SADB_EXT_ADDRESS_PROXY: -+ case SADB_X_EXT_ADDRESS_DST2: -+ case SADB_X_EXT_ADDRESS_SRC_FLOW: -+ case SADB_X_EXT_ADDRESS_DST_FLOW: -+ case SADB_X_EXT_ADDRESS_SRC_MASK: -+ case SADB_X_EXT_ADDRESS_DST_MASK: -+#ifdef NAT_TRAVERSAL -+ case SADB_X_EXT_NAT_T_OA: -+#endif -+ break; -+ default: -+ ERROR("pfkey_address_build: " -+ "unrecognised ext_type=%d.\n", -+ exttype); -+ SENDERR(EINVAL); -+ } -+ -+ switch(address->sa_family) { -+ case AF_INET: -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_address_build: " -+ "found address family AF_INET.\n"); -+ saddr_len = sizeof(struct sockaddr_in); -+ sprintf(ipaddr_txt, "%d.%d.%d.%d:%d" -+ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 0) & 0xFF -+ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 8) & 0xFF -+ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 16) & 0xFF -+ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 24) & 0xFF -+ , ntohs(((struct sockaddr_in*)address)->sin_port)); -+ break; -+ case AF_INET6: -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_address_build: " -+ "found address family AF_INET6.\n"); -+ saddr_len = sizeof(struct sockaddr_in6); -+ sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x-%x" -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[0]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[1]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[2]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[3]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[4]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[5]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[6]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[7]) -+ , ntohs(((struct sockaddr_in6*)address)->sin6_port)); -+ break; -+ default: -+ ERROR("pfkey_address_build: " -+ "address->sa_family=%d not supported.\n", -+ address->sa_family); -+ SENDERR(EPFNOSUPPORT); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_address_build: " -+ "found address=%s.\n", -+ ipaddr_txt); -+ if(prefixlen != 0) { -+ ERROR("pfkey_address_build: " -+ "address prefixes not supported yet.\n"); -+ SENDERR(EAFNOSUPPORT); /* not supported yet */ -+ } -+ -+ /* allocate some memory for the extension */ -+ pfkey_address = (struct sadb_address*) -+ MALLOC(ALIGN_N(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)); -+ *pfkey_ext = (struct sadb_ext*)pfkey_address; -+ -+ if(pfkey_address == NULL ) { -+ ERROR("pfkey_lifetime_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_address, -+ 0, -+ ALIGN_N(sizeof(struct sadb_address) + saddr_len, -+ IPSEC_PFKEYv2_ALIGN)); -+ -+ pfkey_address->sadb_address_len = DIVUP(sizeof(struct sadb_address) + saddr_len, -+ IPSEC_PFKEYv2_ALIGN); -+ -+ pfkey_address->sadb_address_exttype = exttype; -+ pfkey_address->sadb_address_proto = proto; -+ pfkey_address->sadb_address_prefixlen = prefixlen; -+ pfkey_address->sadb_address_reserved = 0; -+ -+ memcpy((char*)pfkey_address + sizeof(struct sadb_address), -+ address, -+ saddr_len); -+ -+#if 0 -+ for(i = 0; i < sizeof(struct sockaddr_in) - offsetof(struct sockaddr_in, sin_zero); i++) { -+ pfkey_address_s_ska.sin_zero[i] = 0; -+ } -+#endif -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_address_build: " -+ "successful created len: %d.\n", pfkey_address->sadb_address_len); -+ -+ errlab: -+ return error; -+} -+ -+int -+pfkey_key_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint16_t key_bits, -+ char* key) -+{ -+ int error = 0; -+ struct sadb_key *pfkey_key = (struct sadb_key *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_key_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_key) { -+ ERROR("pfkey_key_build: " -+ "why is pfkey_key already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(!key_bits) { -+ ERROR("pfkey_key_build: " -+ "key_bits is zero, it must be non-zero.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if( !((exttype == SADB_EXT_KEY_AUTH) || (exttype == SADB_EXT_KEY_ENCRYPT))) { -+ ERROR("pfkey_key_build: " -+ "unsupported extension type=%d.\n", -+ exttype); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_key = (struct sadb_key*) -+ MALLOC(sizeof(struct sadb_key) + -+ DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN))) { -+ ERROR("pfkey_key_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_key, -+ 0, -+ sizeof(struct sadb_key) + -+ DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN); -+ -+ pfkey_key->sadb_key_len = DIVUP(sizeof(struct sadb_key) * IPSEC_PFKEYv2_ALIGN + key_bits, -+ 64); -+ pfkey_key->sadb_key_exttype = exttype; -+ pfkey_key->sadb_key_bits = key_bits; -+ pfkey_key->sadb_key_reserved = 0; -+ memcpy((char*)pfkey_key + sizeof(struct sadb_key), -+ key, -+ DIVUP(key_bits, 8)); -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_ident_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint16_t ident_type, -+ uint64_t ident_id, -+ uint8_t ident_len, -+ char* ident_string) -+{ -+ int error = 0; -+ struct sadb_ident *pfkey_ident = (struct sadb_ident *)*pfkey_ext; -+ int data_len = ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_ident_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_ident) { -+ ERROR("pfkey_ident_build: " -+ "why is pfkey_ident already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if( ! ((exttype == SADB_EXT_IDENTITY_SRC) || -+ (exttype == SADB_EXT_IDENTITY_DST))) { -+ ERROR("pfkey_ident_build: " -+ "unsupported extension type=%d.\n", -+ exttype); -+ SENDERR(EINVAL); -+ } -+ -+ if((ident_type == SADB_IDENTTYPE_RESERVED)) { -+ ERROR("pfkey_ident_build: " -+ "ident_type must be non-zero.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(ident_type > SADB_IDENTTYPE_MAX) { -+ ERROR("pfkey_ident_build: " -+ "identtype=%d out of range.\n", -+ ident_type); -+ SENDERR(EINVAL); -+ } -+ -+ if(((ident_type == SADB_IDENTTYPE_PREFIX) || -+ (ident_type == SADB_IDENTTYPE_FQDN)) && -+ !ident_string) { -+ ERROR("pfkey_ident_build: " -+ "string required to allocate size of extension.\n"); -+ SENDERR(EINVAL); -+ } -+ -+#if 0 -+ if((ident_type == SADB_IDENTTYPE_USERFQDN) ) { -+ } -+#endif -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_ident = (struct sadb_ident*) -+ MALLOC(ident_len * IPSEC_PFKEYv2_ALIGN))) { -+ ERROR("pfkey_ident_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_ident, 0, ident_len * IPSEC_PFKEYv2_ALIGN); -+ -+ pfkey_ident->sadb_ident_len = ident_len; -+ pfkey_ident->sadb_ident_exttype = exttype; -+ pfkey_ident->sadb_ident_type = ident_type; -+ pfkey_ident->sadb_ident_reserved = 0; -+ pfkey_ident->sadb_ident_id = ident_id; -+ memcpy((char*)pfkey_ident + sizeof(struct sadb_ident), -+ ident_string, -+ data_len); -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_sens_build(struct sadb_ext** pfkey_ext, -+ uint32_t dpd, -+ uint8_t sens_level, -+ uint8_t sens_len, -+ uint64_t* sens_bitmap, -+ uint8_t integ_level, -+ uint8_t integ_len, -+ uint64_t* integ_bitmap) -+{ -+ int error = 0; -+ struct sadb_sens *pfkey_sens = (struct sadb_sens *)*pfkey_ext; -+ int i; -+ uint64_t* bitmap; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sens_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_sens) { -+ ERROR("pfkey_sens_build: " -+ "why is pfkey_sens already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_sens_build: " -+ "Sorry, I can't build exttype=%d yet.\n", -+ (*pfkey_ext)->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_sens = (struct sadb_sens*) -+ MALLOC(sizeof(struct sadb_sens) + -+ (sens_len + integ_len) * sizeof(uint64_t)))) { -+ ERROR("pfkey_sens_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_sens, -+ 0, -+ sizeof(struct sadb_sens) + -+ (sens_len + integ_len) * sizeof(uint64_t)); -+ -+ pfkey_sens->sadb_sens_len = (sizeof(struct sadb_sens) + -+ (sens_len + integ_len) * sizeof(uint64_t)) / IPSEC_PFKEYv2_ALIGN; -+ pfkey_sens->sadb_sens_exttype = SADB_EXT_SENSITIVITY; -+ pfkey_sens->sadb_sens_dpd = dpd; -+ pfkey_sens->sadb_sens_sens_level = sens_level; -+ pfkey_sens->sadb_sens_sens_len = sens_len; -+ pfkey_sens->sadb_sens_integ_level = integ_level; -+ pfkey_sens->sadb_sens_integ_len = integ_len; -+ pfkey_sens->sadb_sens_reserved = 0; -+ -+ bitmap = (uint64_t*)((char*)pfkey_ext + sizeof(struct sadb_sens)); -+ for(i = 0; i < sens_len; i++) { -+ *bitmap = sens_bitmap[i]; -+ bitmap++; -+ } -+ for(i = 0; i < integ_len; i++) { -+ *bitmap = integ_bitmap[i]; -+ bitmap++; -+ } -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_prop_build(struct sadb_ext** pfkey_ext, -+ uint8_t replay, -+ unsigned int comb_num, -+ struct sadb_comb* comb) -+{ -+ int error = 0; -+ int i; -+ struct sadb_prop *pfkey_prop = (struct sadb_prop *)*pfkey_ext; -+ struct sadb_comb *combp; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_prop_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_prop) { -+ ERROR("pfkey_prop_build: " -+ "why is pfkey_prop already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_prop = (struct sadb_prop*) -+ MALLOC(sizeof(struct sadb_prop) + -+ comb_num * sizeof(struct sadb_comb)))) { -+ ERROR("pfkey_prop_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_prop, -+ 0, -+ sizeof(struct sadb_prop) + -+ comb_num * sizeof(struct sadb_comb)); -+ -+ pfkey_prop->sadb_prop_len = (sizeof(struct sadb_prop) + -+ comb_num * sizeof(struct sadb_comb)) / IPSEC_PFKEYv2_ALIGN; -+ -+ pfkey_prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; -+ pfkey_prop->sadb_prop_replay = replay; -+ -+ for(i=0; i<3; i++) { -+ pfkey_prop->sadb_prop_reserved[i] = 0; -+ } -+ -+ combp = (struct sadb_comb*)((char*)*pfkey_ext + sizeof(struct sadb_prop)); -+ for(i = 0; i < comb_num; i++) { -+ memcpy (combp, &(comb[i]), sizeof(struct sadb_comb)); -+ combp++; -+ } -+ -+#if 0 -+ uint8_t sadb_comb_auth; -+ uint8_t sadb_comb_encrypt; -+ uint16_t sadb_comb_flags; -+ uint16_t sadb_comb_auth_minbits; -+ uint16_t sadb_comb_auth_maxbits; -+ uint16_t sadb_comb_encrypt_minbits; -+ uint16_t sadb_comb_encrypt_maxbits; -+ uint32_t sadb_comb_reserved; -+ uint32_t sadb_comb_soft_allocations; -+ uint32_t sadb_comb_hard_allocations; -+ uint64_t sadb_comb_soft_bytes; -+ uint64_t sadb_comb_hard_bytes; -+ uint64_t sadb_comb_soft_addtime; -+ uint64_t sadb_comb_hard_addtime; -+ uint64_t sadb_comb_soft_usetime; -+ uint64_t sadb_comb_hard_usetime; -+ uint32_t sadb_comb_soft_packets; -+ uint32_t sadb_comb_hard_packets; -+#endif -+errlab: -+ return error; -+} -+ -+int -+pfkey_supported_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ unsigned int alg_num, -+ struct sadb_alg* alg) -+{ -+ int error = 0; -+ unsigned int i; -+ struct sadb_supported *pfkey_supported = (struct sadb_supported *)*pfkey_ext; -+ struct sadb_alg *pfkey_alg; -+ -+ /* sanity checks... */ -+ if(pfkey_supported) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_supported_build: " -+ "why is pfkey_supported already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if( !((exttype == SADB_EXT_SUPPORTED_AUTH) || (exttype == SADB_EXT_SUPPORTED_ENCRYPT))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_supported_build: " -+ "unsupported extension type=%d.\n", -+ exttype); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_supported = (struct sadb_supported*) -+ MALLOC(sizeof(struct sadb_supported) + -+ alg_num * -+ sizeof(struct sadb_alg)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_supported_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_supported, -+ 0, -+ sizeof(struct sadb_supported) + -+ alg_num * -+ sizeof(struct sadb_alg)); -+ -+ pfkey_supported->sadb_supported_len = (sizeof(struct sadb_supported) + -+ alg_num * -+ sizeof(struct sadb_alg)) / -+ IPSEC_PFKEYv2_ALIGN; -+ pfkey_supported->sadb_supported_exttype = exttype; -+ pfkey_supported->sadb_supported_reserved = 0; -+ -+ pfkey_alg = (struct sadb_alg*)((char*)pfkey_supported + sizeof(struct sadb_supported)); -+ for(i = 0; i < alg_num; i++) { -+ memcpy (pfkey_alg, &(alg[i]), sizeof(struct sadb_alg)); -+ pfkey_alg->sadb_alg_reserved = 0; -+ pfkey_alg++; -+ } -+ -+#if 0 -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_supported_build: " -+ "Sorry, I can't build exttype=%d yet.\n", -+ (*pfkey_ext)->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ -+ uint8_t sadb_alg_id; -+ uint8_t sadb_alg_ivlen; -+ uint16_t sadb_alg_minbits; -+ uint16_t sadb_alg_maxbits; -+ uint16_t sadb_alg_reserved; -+#endif -+errlab: -+ return error; -+} -+ -+int -+pfkey_spirange_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint32_t min, /* in network order */ -+ uint32_t max) /* in network order */ -+{ -+ int error = 0; -+ struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)*pfkey_ext; -+ -+ /* sanity checks... */ -+ if(pfkey_spirange) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_spirange_build: " -+ "why is pfkey_spirange already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(ntohl(max) < ntohl(min)) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_spirange_build: " -+ "minspi=%08x must be < maxspi=%08x.\n", -+ ntohl(min), -+ ntohl(max)); -+ SENDERR(EINVAL); -+ } -+ -+ if(ntohl(min) <= 255) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_spirange_build: " -+ "minspi=%08x must be > 255.\n", -+ ntohl(min)); -+ SENDERR(EEXIST); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_spirange = (struct sadb_spirange*) -+ MALLOC(sizeof(struct sadb_spirange)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_spirange_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_spirange, -+ 0, -+ sizeof(struct sadb_spirange)); -+ -+ pfkey_spirange->sadb_spirange_len = sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN; -+ -+ pfkey_spirange->sadb_spirange_exttype = SADB_EXT_SPIRANGE; -+ pfkey_spirange->sadb_spirange_min = min; -+ pfkey_spirange->sadb_spirange_max = max; -+ pfkey_spirange->sadb_spirange_reserved = 0; -+ errlab: -+ return error; -+} -+ -+int -+pfkey_x_kmprivate_build(struct sadb_ext** pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)*pfkey_ext; -+ -+ /* sanity checks... */ -+ if(pfkey_x_kmprivate) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_kmprivate_build: " -+ "why is pfkey_x_kmprivate already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_kmprivate_build: " -+ "Sorry, I can't build exttype=%d yet.\n", -+ (*pfkey_ext)->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ -+ if(!(*pfkey_ext = (struct sadb_ext*) -+ pfkey_x_kmprivate = (struct sadb_x_kmprivate*) -+ MALLOC(sizeof(struct sadb_x_kmprivate)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_kmprivate_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_x_kmprivate, -+ 0, -+ sizeof(struct sadb_x_kmprivate)); -+ -+ pfkey_x_kmprivate->sadb_x_kmprivate_len = -+ sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN; -+ -+ pfkey_x_kmprivate->sadb_x_kmprivate_exttype = SADB_X_EXT_KMPRIVATE; -+ pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0; -+errlab: -+ return error; -+} -+ -+int -+pfkey_x_satype_build(struct sadb_ext** pfkey_ext, -+ uint8_t satype) -+{ -+ int error = 0; -+ int i; -+ struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_satype_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_x_satype) { -+ ERROR("pfkey_x_satype_build: " -+ "why is pfkey_x_satype already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(!satype) { -+ ERROR("pfkey_x_satype_build: " -+ "SA type not set, must be non-zero.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(satype > SADB_SATYPE_MAX) { -+ ERROR("pfkey_x_satype_build: " -+ "satype %d > max %d\n", -+ satype, SADB_SATYPE_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_satype = (struct sadb_x_satype*) -+ MALLOC(sizeof(struct sadb_x_satype)))) { -+ ERROR("pfkey_x_satype_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ memset(pfkey_x_satype, -+ 0, -+ sizeof(struct sadb_x_satype)); -+ -+ pfkey_x_satype->sadb_x_satype_len = sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN; -+ -+ pfkey_x_satype->sadb_x_satype_exttype = SADB_X_EXT_SATYPE2; -+ pfkey_x_satype->sadb_x_satype_satype = satype; -+ for(i=0; i<3; i++) { -+ pfkey_x_satype->sadb_x_satype_reserved[i] = 0; -+ } -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_x_debug_build(struct sadb_ext** pfkey_ext, -+ uint32_t tunnel, -+ uint32_t netlink, -+ uint32_t xform, -+ uint32_t eroute, -+ uint32_t spi, -+ uint32_t radij, -+ uint32_t esp, -+ uint32_t ah, -+ uint32_t rcv, -+ uint32_t pfkey, -+ uint32_t ipcomp, -+ uint32_t verbose) -+{ -+ int error = 0; -+ int i; -+ struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_debug_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_x_debug) { -+ ERROR("pfkey_x_debug_build: " -+ "why is pfkey_x_debug already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_debug_build: " -+ "tunnel=%x netlink=%x xform=%x eroute=%x spi=%x radij=%x esp=%x ah=%x rcv=%x pfkey=%x ipcomp=%x verbose=%x?\n", -+ tunnel, netlink, xform, eroute, spi, radij, esp, ah, rcv, pfkey, ipcomp, verbose); -+ -+ if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_debug = (struct sadb_x_debug*) -+ MALLOC(sizeof(struct sadb_x_debug)))) { -+ ERROR("pfkey_x_debug_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+#if 0 -+ memset(pfkey_x_debug, -+ 0, -+ sizeof(struct sadb_x_debug)); -+#endif -+ -+ pfkey_x_debug->sadb_x_debug_len = sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN; -+ pfkey_x_debug->sadb_x_debug_exttype = SADB_X_EXT_DEBUG; -+ -+ pfkey_x_debug->sadb_x_debug_tunnel = tunnel; -+ pfkey_x_debug->sadb_x_debug_netlink = netlink; -+ pfkey_x_debug->sadb_x_debug_xform = xform; -+ pfkey_x_debug->sadb_x_debug_eroute = eroute; -+ pfkey_x_debug->sadb_x_debug_spi = spi; -+ pfkey_x_debug->sadb_x_debug_radij = radij; -+ pfkey_x_debug->sadb_x_debug_esp = esp; -+ pfkey_x_debug->sadb_x_debug_ah = ah; -+ pfkey_x_debug->sadb_x_debug_rcv = rcv; -+ pfkey_x_debug->sadb_x_debug_pfkey = pfkey; -+ pfkey_x_debug->sadb_x_debug_ipcomp = ipcomp; -+ pfkey_x_debug->sadb_x_debug_verbose = verbose; -+ -+ for(i=0; i<4; i++) { -+ pfkey_x_debug->sadb_x_debug_reserved[i] = 0; -+ } -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_x_nat_t_type_build(struct sadb_ext** pfkey_ext, -+ uint8_t type) -+{ -+ int error = 0; -+ int i; -+ struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_type_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_x_nat_t_type) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_type_build: " -+ "why is pfkey_x_nat_t_type already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_type_build: " -+ "type=%d\n", type); -+ -+ if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_type = (struct sadb_x_nat_t_type*) -+ MALLOC(sizeof(struct sadb_x_nat_t_type)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_type_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ -+ pfkey_x_nat_t_type->sadb_x_nat_t_type_len = sizeof(struct sadb_x_nat_t_type) / IPSEC_PFKEYv2_ALIGN; -+ pfkey_x_nat_t_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE; -+ pfkey_x_nat_t_type->sadb_x_nat_t_type_type = type; -+ for(i=0; i<3; i++) { -+ pfkey_x_nat_t_type->sadb_x_nat_t_type_reserved[i] = 0; -+ } -+ -+errlab: -+ return error; -+} -+int -+pfkey_x_nat_t_port_build(struct sadb_ext** pfkey_ext, -+ uint16_t exttype, -+ uint16_t port) -+{ -+ int error = 0; -+ struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)*pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_port_build:\n"); -+ /* sanity checks... */ -+ if(pfkey_x_nat_t_port) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_port_build: " -+ "why is pfkey_x_nat_t_port already pointing to something?\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(exttype) { -+ case SADB_X_EXT_NAT_T_SPORT: -+ case SADB_X_EXT_NAT_T_DPORT: -+ break; -+ default: -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_nat_t_port_build: " -+ "unrecognised ext_type=%d.\n", -+ exttype); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_port_build: " -+ "ext=%d, port=%d\n", exttype, port); -+ -+ if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_port = (struct sadb_x_nat_t_port*) -+ MALLOC(sizeof(struct sadb_x_nat_t_port)))) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_x_nat_t_port_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ -+ pfkey_x_nat_t_port->sadb_x_nat_t_port_len = sizeof(struct sadb_x_nat_t_port) / IPSEC_PFKEYv2_ALIGN; -+ pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype = exttype; -+ pfkey_x_nat_t_port->sadb_x_nat_t_port_port = port; -+ pfkey_x_nat_t_port->sadb_x_nat_t_port_reserved = 0; -+ -+errlab: -+ return error; -+} -+ -+int pfkey_x_protocol_build(struct sadb_ext **pfkey_ext, -+ uint8_t protocol) -+{ -+ int error = 0; -+ struct sadb_protocol * p = (struct sadb_protocol *)*pfkey_ext; -+ DEBUGGING(PF_KEY_DEBUG_BUILD,"pfkey_x_protocol_build: protocol=%u\n", protocol); -+ /* sanity checks... */ -+ if (p != 0) { -+ ERROR("pfkey_x_protocol_build: bogus protocol pointer\n"); -+ SENDERR(EINVAL); -+ } -+ if ((p = (struct sadb_protocol*)MALLOC(sizeof(*p))) == 0) { -+ ERROR("pfkey_build: memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ *pfkey_ext = (struct sadb_ext *)p; -+ p->sadb_protocol_len = sizeof(*p) / sizeof(uint64_t); -+ p->sadb_protocol_exttype = SADB_X_EXT_PROTOCOL; -+ p->sadb_protocol_proto = protocol; -+ p->sadb_protocol_flags = 0; -+ p->sadb_protocol_reserved2 = 0; -+ errlab: -+ return error; -+} -+ -+ -+#if I_DONT_THINK_THIS_WILL_BE_USEFUL -+int (*ext_default_builders[SADB_EXT_MAX +1])(struct sadb_msg*, struct sadb_ext*) -+ = -+{ -+ NULL, /* pfkey_msg_build, */ -+ pfkey_sa_build, -+ pfkey_lifetime_build, -+ pfkey_lifetime_build, -+ pfkey_lifetime_build, -+ pfkey_address_build, -+ pfkey_address_build, -+ pfkey_address_build, -+ pfkey_key_build, -+ pfkey_key_build, -+ pfkey_ident_build, -+ pfkey_ident_build, -+ pfkey_sens_build, -+ pfkey_prop_build, -+ pfkey_supported_build, -+ pfkey_supported_build, -+ pfkey_spirange_build, -+ pfkey_x_kmprivate_build, -+ pfkey_x_satype_build, -+ pfkey_sa_build, -+ pfkey_address_build, -+ pfkey_address_build, -+ pfkey_address_build, -+ pfkey_address_build, -+ pfkey_address_build, -+ pfkey_x_ext_debug_build -+}; -+#endif -+ -+int -+pfkey_msg_build(struct sadb_msg **pfkey_msg, struct sadb_ext *extensions[], int dir) -+{ -+ int error = 0; -+ unsigned ext; -+ unsigned total_size; -+ struct sadb_ext *pfkey_ext; -+ int extensions_seen = 0; -+#ifndef __KERNEL__ -+ struct sadb_ext *extensions_check[SADB_EXT_MAX + 1]; -+#endif -+ -+ if(!extensions[0]) { -+ ERROR("pfkey_msg_build: " -+ "extensions[0] must be specified (struct sadb_msg).\n"); -+ SENDERR(EINVAL); -+ } -+ -+ /* figure out the total size for all the requested extensions */ -+ total_size = IPSEC_PFKEYv2_WORDS(sizeof(struct sadb_msg)); -+ for(ext = 1; ext <= SADB_EXT_MAX; ext++) { -+ if(extensions[ext]) { -+ total_size += (extensions[ext])->sadb_ext_len; -+ } -+ } -+ -+ /* allocate that much space */ -+ *pfkey_msg = (struct sadb_msg*)MALLOC(total_size * IPSEC_PFKEYv2_ALIGN); -+ if(*pfkey_msg == NULL) { -+ ERROR("pfkey_msg_build: " -+ "memory allocation failed\n"); -+ SENDERR(ENOMEM); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_build: " -+ "pfkey_msg=0p%p allocated %lu bytes, &(extensions[0])=0p%p\n", -+ *pfkey_msg, -+ (unsigned long)(total_size * IPSEC_PFKEYv2_ALIGN), -+ &(extensions[0])); -+ -+ memcpy(*pfkey_msg, -+ extensions[0], -+ sizeof(struct sadb_msg)); -+ (*pfkey_msg)->sadb_msg_len = total_size; -+ (*pfkey_msg)->sadb_msg_reserved = 0; -+ extensions_seen = 1 ; -+ -+ /* -+ * point pfkey_ext to immediately after the space for the header, -+ * i.e. at the first extension location. -+ */ -+ pfkey_ext = (struct sadb_ext*)(((char*)(*pfkey_msg)) + sizeof(struct sadb_msg)); -+ -+ for(ext = 1; ext <= SADB_EXT_MAX; ext++) { -+ /* copy from extension[ext] to buffer */ -+ if(extensions[ext]) { -+ /* Is this type of extension permitted for this type of message? */ -+ if(!(extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type] & -+ 1<sadb_msg_type], -+ 1<sadb_ext_len * IPSEC_PFKEYv2_ALIGN), -+ ext, -+ extensions[ext]->sadb_ext_type); -+ -+ memcpy(pfkey_ext, -+ extensions[ext], -+ (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); -+ ((char*)pfkey_ext) += (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN; -+ /* Mark that we have seen this extension and remember the header location */ -+ extensions_seen |= ( 1 << ext ); -+ } -+ } -+ -+ /* check required extensions */ -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_build: " -+ "extensions permitted=%08x, seen=%08x, required=%08x.\n", -+ extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type], -+ extensions_seen, -+ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]); -+ -+ if((extensions_seen & -+ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) != -+ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) { -+ DEBUGGING(PF_KEY_DEBUG_BUILD, -+ "pfkey_msg_build: " -+ "required extensions missing:%08x.\n", -+ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type] - -+ (extensions_seen & -+ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) ); -+ SENDERR(EINVAL); -+ } -+ -+#ifndef __KERNEL__ -+/* -+ * this is silly, there is no need to reparse the message that we just built. -+ * -+ */ -+ if((error = pfkey_msg_parse(*pfkey_msg, NULL, extensions_check, dir))) { -+ ERROR( -+ "pfkey_msg_build: " -+ "Trouble parsing newly built pfkey message, error=%d.\n", -+ error); -+ SENDERR(-error); -+ } -+#endif -+ -+errlab: -+ -+ return error; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.49 2004/04/12 02:59:06 mcr -+ * erroneously moved pfkey_v2_build.c -+ * -+ * Revision 1.48 2004/04/09 18:00:40 mcr -+ * Moved from linux/lib/libfreeswan/pfkey_v2_build.c,v -+ * -+ * Revision 1.47 2004/03/08 01:59:08 ken -+ * freeswan.h -> openswan.h -+ * -+ * Revision 1.46 2003/12/10 01:20:19 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.45 2003/12/04 23:01:12 mcr -+ * removed ipsec_netlink.h -+ * -+ * Revision 1.44 2003/10/31 02:27:12 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.43.4.2 2003/10/29 01:11:32 mcr -+ * added debugging for pfkey library. -+ * -+ * Revision 1.43.4.1 2003/09/21 13:59:44 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.43 2003/05/07 17:29:17 mcr -+ * new function pfkey_debug_func added for us in debugging from -+ * pfkey library. -+ * -+ * Revision 1.42 2003/01/30 02:32:09 rgb -+ * -+ * Rename SAref table macro names for clarity. -+ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. -+ * -+ * Revision 1.41 2002/12/13 18:16:02 mcr -+ * restored sa_ref code -+ * -+ * Revision 1.40 2002/12/13 18:06:52 mcr -+ * temporarily removed sadb_x_sa_ref reference for 2.xx -+ * -+ * Revision 1.39 2002/12/13 17:43:28 mcr -+ * commented out access to sadb_x_sa_ref for 2.xx branch -+ * -+ * Revision 1.38 2002/10/09 03:12:05 dhr -+ * -+ * [kenb+dhr] 64-bit fixes -+ * -+ * Revision 1.37 2002/09/20 15:40:39 rgb -+ * Added new function pfkey_sa_ref_build() to accomodate saref parameter. -+ * -+ * Revision 1.36 2002/09/20 05:01:22 rgb -+ * Generalise for platform independance: fix (ia64) using unsigned for sizes. -+ * -+ * Revision 1.35 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.34 2002/05/23 07:14:11 rgb -+ * Cleaned up %p variants to 0p%p for test suite cleanup. -+ * -+ * Revision 1.33 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.32 2002/04/24 07:36:40 mcr -+ * Moved from ./lib/pfkey_v2_build.c,v -+ * -+ * Revision 1.31 2002/01/29 22:25:35 rgb -+ * Re-add ipsec_kversion.h to keep MALLOC happy. -+ * -+ * Revision 1.30 2002/01/29 01:59:09 mcr -+ * removal of kversions.h - sources that needed it now use ipsec_param.h. -+ * updating of IPv6 structures to match latest in6.h version. -+ * removed dead code from openswan.h that also duplicated kversions.h -+ * code. -+ * -+ * Revision 1.29 2001/12/19 21:06:09 rgb -+ * Added port numbers to pfkey_address_build() debugging. -+ * -+ * Revision 1.28 2001/11/06 19:47:47 rgb -+ * Added packet parameter to lifetime and comb structures. -+ * -+ * Revision 1.27 2001/10/18 04:45:24 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/openswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.26 2001/09/08 21:13:34 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.25 2001/06/14 19:35:16 rgb -+ * Update copyright date. -+ * -+ * Revision 1.24 2001/03/20 03:49:45 rgb -+ * Ditch superfluous debug_pfkey declaration. -+ * Move misplaced openswan.h inclusion for kernel case. -+ * -+ * Revision 1.23 2001/03/16 07:41:50 rgb -+ * Put openswan.h include before pluto includes. -+ * -+ * Revision 1.22 2001/02/27 22:24:56 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.21 2000/11/17 18:10:30 rgb -+ * Fixed bugs mostly relating to spirange, to treat all spi variables as -+ * network byte order since this is the way PF_KEYv2 stored spis. -+ * -+ * Revision 1.20 2000/10/12 00:02:39 rgb -+ * Removed 'format, ##' nonsense from debug macros for RH7.0. -+ * -+ * Revision 1.19 2000/10/10 20:10:20 rgb -+ * Added support for debug_ipcomp and debug_verbose to klipsdebug. -+ * -+ * Revision 1.18 2000/09/12 18:59:54 rgb -+ * Added Gerhard's IPv6 support to pfkey parts of libopenswan. -+ * -+ * Revision 1.17 2000/09/12 03:27:00 rgb -+ * Moved DEBUGGING definition to compile kernel with debug off. -+ * -+ * Revision 1.16 2000/09/08 19:22:12 rgb -+ * Fixed pfkey_prop_build() parameter to be only single indirection. -+ * Fixed struct alg copy. -+ * -+ * Revision 1.15 2000/08/20 21:40:01 rgb -+ * Added an address parameter sanity check to pfkey_address_build(). -+ * -+ * Revision 1.14 2000/08/15 17:29:23 rgb -+ * Fixes from SZI to untested pfkey_prop_build(). -+ * -+ * Revision 1.13 2000/06/02 22:54:14 rgb -+ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support. -+ * -+ * Revision 1.12 2000/05/10 19:24:01 rgb -+ * Fleshed out sensitivity, proposal and supported extensions. -+ * -+ * Revision 1.11 2000/03/16 14:07:23 rgb -+ * Renamed ALIGN macro to avoid fighting with others in kernel. -+ * -+ * Revision 1.10 2000/01/24 21:14:35 rgb -+ * Added disabled pluto pfkey lib debug flag. -+ * -+ * Revision 1.9 2000/01/21 06:27:32 rgb -+ * Added address cases for eroute flows. -+ * Removed unused code. -+ * Dropped unused argument to pfkey_x_satype_build(). -+ * Indented compiler directives for readability. -+ * Added klipsdebug switching capability. -+ * Fixed SADB_EXT_MAX bug not permitting last extension access. -+ * -+ * Revision 1.8 1999/12/29 21:17:41 rgb -+ * Changed pfkey_msg_build() I/F to include a struct sadb_msg** -+ * parameter for cleaner manipulation of extensions[] and to guard -+ * against potential memory leaks. -+ * Changed the I/F to pfkey_msg_free() for the same reason. -+ * -+ * Revision 1.7 1999/12/09 23:12:20 rgb -+ * Removed unused cruft. -+ * Added argument to pfkey_sa_build() to do eroutes. -+ * Fixed exttype check in as yet unused pfkey_lifetime_build(). -+ * -+ * Revision 1.6 1999/12/07 19:54:29 rgb -+ * Removed static pluto debug flag. -+ * Added functions for pfkey message and extensions initialisation -+ * and cleanup. -+ * -+ * Revision 1.5 1999/12/01 22:20:06 rgb -+ * Changed pfkey_sa_build to accept an SPI in network byte order. -+ * Added to quiet userspace compiler. -+ * Moved pfkey_lib_debug variable into the library. -+ * Removed SATYPE check from pfkey_msg_hdr_build so FLUSH will work. -+ * Added extension assembly debugging. -+ * Isolated assignment with brackets to be sure of scope. -+ * -+ * Revision 1.4 1999/11/27 11:57:35 rgb -+ * Added ipv6 headers. -+ * Remove over-zealous algorithm sanity checkers from pfkey_sa_build. -+ * Debugging error messages added. -+ * Fixed missing auth and encrypt assignment bug. -+ * Add argument to pfkey_msg_parse() for direction. -+ * Move parse-after-build check inside pfkey_msg_build(). -+ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array. -+ * Add CVS log entry to bottom of file. -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/pfkey_v2_debug.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,176 @@ -+/* -+ * @(#) pfkey version 2 debugging messages -+ * -+ * Copyright (C) 2001 Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ */ -+ -+#ifdef __KERNEL__ -+ -+# include /* for printk */ -+ -+# include "openswan/ipsec_kversion.h" /* for malloc switch */ -+# ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+# else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+# endif /* MALLOC_SLAB */ -+# include /* error codes */ -+# include /* size_t */ -+# include /* mark_bh */ -+ -+# include /* struct device, and other headers */ -+# include /* eth_type_trans */ -+extern int debug_pfkey; -+ -+#else /* __KERNEL__ */ -+ -+# include -+# include -+# include -+ -+#endif /* __KERNEL__ */ -+ -+#include "openswan.h" -+#include "pfkeyv2.h" -+#include "pfkey.h" -+ -+/* -+ * This file provides ASCII translations of PF_KEY magic numbers. -+ * -+ */ -+ -+static char *pfkey_sadb_ext_strings[]={ -+ "reserved", /* SADB_EXT_RESERVED 0 */ -+ "security-association", /* SADB_EXT_SA 1 */ -+ "lifetime-current", /* SADB_EXT_LIFETIME_CURRENT 2 */ -+ "lifetime-hard", /* SADB_EXT_LIFETIME_HARD 3 */ -+ "lifetime-soft", /* SADB_EXT_LIFETIME_SOFT 4 */ -+ "source-address", /* SADB_EXT_ADDRESS_SRC 5 */ -+ "destination-address", /* SADB_EXT_ADDRESS_DST 6 */ -+ "proxy-address", /* SADB_EXT_ADDRESS_PROXY 7 */ -+ "authentication-key", /* SADB_EXT_KEY_AUTH 8 */ -+ "cipher-key", /* SADB_EXT_KEY_ENCRYPT 9 */ -+ "source-identity", /* SADB_EXT_IDENTITY_SRC 10 */ -+ "destination-identity", /* SADB_EXT_IDENTITY_DST 11 */ -+ "sensitivity-label", /* SADB_EXT_SENSITIVITY 12 */ -+ "proposal", /* SADB_EXT_PROPOSAL 13 */ -+ "supported-auth", /* SADB_EXT_SUPPORTED_AUTH 14 */ -+ "supported-cipher", /* SADB_EXT_SUPPORTED_ENCRYPT 15 */ -+ "spi-range", /* SADB_EXT_SPIRANGE 16 */ -+ "X-kmpprivate", /* SADB_X_EXT_KMPRIVATE 17 */ -+ "X-satype2", /* SADB_X_EXT_SATYPE2 18 */ -+ "X-security-association", /* SADB_X_EXT_SA2 19 */ -+ "X-destination-address2", /* SADB_X_EXT_ADDRESS_DST2 20 */ -+ "X-source-flow-address", /* SADB_X_EXT_ADDRESS_SRC_FLOW 21 */ -+ "X-dest-flow-address", /* SADB_X_EXT_ADDRESS_DST_FLOW 22 */ -+ "X-source-mask", /* SADB_X_EXT_ADDRESS_SRC_MASK 23 */ -+ "X-dest-mask", /* SADB_X_EXT_ADDRESS_DST_MASK 24 */ -+ "X-set-debug", /* SADB_X_EXT_DEBUG 25 */ -+#ifdef NAT_TRAVERSAL -+ "X-NAT-T-type", /* SADB_X_EXT_NAT_T_TYPE 26 */ -+ "X-NAT-T-sport", /* SADB_X_EXT_NAT_T_SPORT 27 */ -+ "X-NAT-T-dport", /* SADB_X_EXT_NAT_T_DPORT 28 */ -+ "X-NAT-T-OA", /* SADB_X_EXT_NAT_T_OA 29 */ -+#endif -+}; -+ -+const char * -+pfkey_v2_sadb_ext_string(int ext) -+{ -+ if(ext <= SADB_EXT_MAX) { -+ return pfkey_sadb_ext_strings[ext]; -+ } else { -+ return "unknown-ext"; -+ } -+} -+ -+ -+static char *pfkey_sadb_type_strings[]={ -+ "reserved", /* SADB_RESERVED */ -+ "getspi", /* SADB_GETSPI */ -+ "update", /* SADB_UPDATE */ -+ "add", /* SADB_ADD */ -+ "delete", /* SADB_DELETE */ -+ "get", /* SADB_GET */ -+ "acquire", /* SADB_ACQUIRE */ -+ "register", /* SADB_REGISTER */ -+ "expire", /* SADB_EXPIRE */ -+ "flush", /* SADB_FLUSH */ -+ "dump", /* SADB_DUMP */ -+ "x-promisc", /* SADB_X_PROMISC */ -+ "x-pchange", /* SADB_X_PCHANGE */ -+ "x-groupsa", /* SADB_X_GRPSA */ -+ "x-addflow(eroute)", /* SADB_X_ADDFLOW */ -+ "x-delflow(eroute)", /* SADB_X_DELFLOW */ -+ "x-debug", /* SADB_X_DEBUG */ -+}; -+ -+const char * -+pfkey_v2_sadb_type_string(int sadb_type) -+{ -+ if(sadb_type <= SADB_MAX) { -+ return pfkey_sadb_type_strings[sadb_type]; -+ } else { -+ return "unknown-sadb-type"; -+ } -+} -+ -+ -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.9 2004/03/08 01:59:08 ken -+ * freeswan.h -> openswan.h -+ * -+ * Revision 1.8 2003/12/10 01:20:19 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.7 2002/09/20 05:01:26 rgb -+ * Fixed limit inclusion error in both type and ext string conversion. -+ * -+ * Revision 1.6 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.5 2002/04/24 07:36:40 mcr -+ * Moved from ./lib/pfkey_v2_debug.c,v -+ * -+ * Revision 1.4 2002/01/29 22:25:36 rgb -+ * Re-add ipsec_kversion.h to keep MALLOC happy. -+ * -+ * Revision 1.3 2002/01/29 01:59:09 mcr -+ * removal of kversions.h - sources that needed it now use ipsec_param.h. -+ * updating of IPv6 structures to match latest in6.h version. -+ * removed dead code from openswan.h that also duplicated kversions.h -+ * code. -+ * -+ * Revision 1.2 2002/01/20 20:34:50 mcr -+ * added pfkey_v2_sadb_type_string to decode sadb_type to string. -+ * -+ * Revision 1.1 2001/11/27 05:30:06 mcr -+ * initial set of debug strings for pfkey debugging. -+ * this will eventually only be included for debug builds. -+ * -+ * Revision 1.1 2001/09/21 04:12:03 mcr -+ * first compilable version. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/pfkey_v2_ext_bits.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,808 @@ -+/* -+ * RFC2367 PF_KEYv2 Key management API message parser -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* -+ * Template from klips/net/ipsec/ipsec/ipsec_parse.c. -+ */ -+ -+char pfkey_v2_ext_bits_c_version[] = "$Id$"; -+ -+/* -+ * Some ugly stuff to allow consistent debugging code for use in the -+ * kernel and in user space -+*/ -+ -+#ifdef __KERNEL__ -+ -+# include /* for printk */ -+ -+# include "openswan/ipsec_kversion.h" /* for malloc switch */ -+# ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+# else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+# endif /* MALLOC_SLAB */ -+# include /* error codes */ -+# include /* size_t */ -+# include /* mark_bh */ -+ -+# include /* struct device, and other headers */ -+# include /* eth_type_trans */ -+# include /* struct iphdr */ -+# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+# include -+# endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ -+ -+#else /* __KERNEL__ */ -+ -+# include -+# include -+# include -+#endif -+ -+#include -+#include -+#include -+ -+unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_MAX + 1/*ext*/] = { -+ -+/* INBOUND EXTENSIONS */ -+{ -+ -+/* PERMITTED IN */ -+{ -+/* SADB_RESERVED */ -+0 -+, -+/* SADB_GETSPI */ -+1< openswan.h -+ * -+ * Revision 1.19 2003/12/22 21:38:13 mcr -+ * removed extraenous #endif. -+ * -+ * Revision 1.18 2003/12/22 19:34:41 mcr -+ * added 0.6c NAT-T patch. -+ * -+ * Revision 1.17 2003/12/10 01:20:19 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.16 2003/10/31 02:27:12 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.15.30.1 2003/09/21 13:59:44 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.15 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.14 2002/04/24 07:36:40 mcr -+ * Moved from ./lib/pfkey_v2_ext_bits.c,v -+ * -+ * Revision 1.13 2002/01/29 22:25:36 rgb -+ * Re-add ipsec_kversion.h to keep MALLOC happy. -+ * -+ * Revision 1.12 2002/01/29 01:59:10 mcr -+ * removal of kversions.h - sources that needed it now use ipsec_param.h. -+ * updating of IPv6 structures to match latest in6.h version. -+ * removed dead code from openswan.h that also duplicated kversions.h -+ * code. -+ * -+ * Revision 1.11 2001/10/18 04:45:24 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/openswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.10 2001/09/08 21:13:35 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.9 2001/06/14 19:35:16 rgb -+ * Update copyright date. -+ * -+ * Revision 1.8 2001/03/26 23:07:36 rgb -+ * Remove requirement for auth and enc key from UPDATE. -+ * -+ * Revision 1.7 2000/09/12 22:35:37 rgb -+ * Restructured to remove unused extensions from CLEARFLOW messages. -+ * -+ * Revision 1.6 2000/09/09 06:39:01 rgb -+ * Added comments for clarity. -+ * -+ * Revision 1.5 2000/06/02 22:54:14 rgb -+ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support. -+ * -+ * Revision 1.4 2000/01/21 06:27:56 rgb -+ * Added address cases for eroute flows. -+ * Added comments for each message type. -+ * Added klipsdebug switching capability. -+ * Fixed GRPSA bitfields. -+ * -+ * Revision 1.3 1999/12/01 22:20:27 rgb -+ * Remove requirement for a proxy address in an incoming getspi message. -+ * -+ * Revision 1.2 1999/11/27 11:57:06 rgb -+ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array. -+ * Add CVS log entry to bottom of file. -+ * Cleaned out unused bits. -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/pfkey_v2_parse.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1820 @@ -+/* -+ * RFC2367 PF_KEYv2 Key management API message parser -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* -+ * Template from klips/net/ipsec/ipsec/ipsec_parser.c. -+ */ -+ -+char pfkey_v2_parse_c_version[] = "$Id$"; -+ -+/* -+ * Some ugly stuff to allow consistent debugging code for use in the -+ * kernel and in user space -+*/ -+ -+#ifdef __KERNEL__ -+ -+# include /* for printk */ -+ -+#include "openswan/ipsec_kversion.h" /* for malloc switch */ -+ -+# ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+# else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+# endif /* MALLOC_SLAB */ -+# include /* error codes */ -+# include /* size_t */ -+# include /* mark_bh */ -+ -+# include /* struct device, and other headers */ -+# include /* eth_type_trans */ -+# include /* struct iphdr */ -+# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+# include /* struct ipv6hdr */ -+# endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ -+extern int debug_pfkey; -+ -+# include -+ -+#include "openswan/ipsec_encap.h" -+ -+#else /* __KERNEL__ */ -+ -+# include -+# include -+# include -+ -+# include -+# include "constants.h" -+# include "programs/pluto/defs.h" /* for PRINTF_LIKE */ -+ -+#endif /* __KERNEL__ */ -+ -+ -+#include -+#include -+ -+#include "openswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */ -+ -+/* -+ * how to handle debugging for pfkey. -+ */ -+#include -+ -+unsigned int pfkey_lib_debug = PF_KEY_DEBUG_PARSE_NONE; -+void (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1); -+void (*pfkey_error_func)(const char *message, ...) PRINTF_LIKE(1); -+ -+ -+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) -+ -+struct satype_tbl { -+ uint8_t proto; -+ uint8_t satype; -+ char* name; -+} static satype_tbl[] = { -+#ifdef __KERNEL__ -+ { IPPROTO_ESP, SADB_SATYPE_ESP, "ESP" }, -+ { IPPROTO_AH, SADB_SATYPE_AH, "AH" }, -+ { IPPROTO_IPIP, SADB_X_SATYPE_IPIP, "IPIP" }, -+#ifdef CONFIG_IPSEC_IPCOMP -+ { IPPROTO_COMP, SADB_X_SATYPE_COMP, "COMP" }, -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ { IPPROTO_INT, SADB_X_SATYPE_INT, "INT" }, -+#else /* __KERNEL__ */ -+ { SA_ESP, SADB_SATYPE_ESP, "ESP" }, -+ { SA_AH, SADB_SATYPE_AH, "AH" }, -+ { SA_IPIP, SADB_X_SATYPE_IPIP, "IPIP" }, -+ { SA_COMP, SADB_X_SATYPE_COMP, "COMP" }, -+ { SA_INT, SADB_X_SATYPE_INT, "INT" }, -+#endif /* __KERNEL__ */ -+ { 0, 0, "UNKNOWN" } -+}; -+ -+uint8_t -+satype2proto(uint8_t satype) -+{ -+ int i =0; -+ -+ while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) { -+ i++; -+ } -+ return satype_tbl[i].proto; -+} -+ -+uint8_t -+proto2satype(uint8_t proto) -+{ -+ int i = 0; -+ -+ while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) { -+ i++; -+ } -+ return satype_tbl[i].satype; -+} -+ -+char* -+satype2name(uint8_t satype) -+{ -+ int i = 0; -+ -+ while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) { -+ i++; -+ } -+ return satype_tbl[i].name; -+} -+ -+char* -+proto2name(uint8_t proto) -+{ -+ int i = 0; -+ -+ while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) { -+ i++; -+ } -+ return satype_tbl[i].name; -+} -+ -+/* Default extension parsers taken from the KLIPS code */ -+ -+DEBUG_NO_STATIC int -+pfkey_sa_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext; -+#if 0 -+ struct sadb_sa sav2; -+#endif -+ -+ /* sanity checks... */ -+ if(!pfkey_sa) { -+ ERROR("pfkey_sa_parse: " -+ "NULL pointer passed in.\n"); -+ SENDERR(EINVAL); -+ } -+ -+#if 0 -+ /* check if this structure is short, and if so, fix it up. -+ * XXX this is NOT the way to do things. -+ */ -+ if(pfkey_sa->sadb_sa_len == sizeof(struct sadb_sa_v1)/IPSEC_PFKEYv2_ALIGN) { -+ -+ /* yes, so clear out a temporary structure, and copy first */ -+ memset(&sav2, 0, sizeof(sav2)); -+ memcpy(&sav2, pfkey_sa, sizeof(struct sadb_sa_v1)); -+ sav2.sadb_x_sa_ref=-1; -+ sav2.sadb_sa_len = sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN; -+ -+ pfkey_sa = &sav2; -+ } -+#endif -+ -+ -+ if(pfkey_sa->sadb_sa_len != sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN) { -+ ERROR( -+ "pfkey_sa_parse: " -+ "length wrong pfkey_sa->sadb_sa_len=%d sizeof(struct sadb_sa)=%d.\n", -+ pfkey_sa->sadb_sa_len, -+ (int)sizeof(struct sadb_sa)); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_sa->sadb_sa_encrypt > SADB_EALG_MAX) { -+ ERROR( -+ "pfkey_sa_parse: " -+ "pfkey_sa->sadb_sa_encrypt=%d > SADB_EALG_MAX=%d.\n", -+ pfkey_sa->sadb_sa_encrypt, -+ SADB_EALG_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_sa->sadb_sa_auth > SADB_AALG_MAX) { -+ ERROR( -+ "pfkey_sa_parse: " -+ "pfkey_sa->sadb_sa_auth=%d > SADB_AALG_MAX=%d.\n", -+ pfkey_sa->sadb_sa_auth, -+ SADB_AALG_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_sa->sadb_sa_state > SADB_SASTATE_MAX) { -+ ERROR( -+ "pfkey_sa_parse: " -+ "state=%d exceeds MAX=%d.\n", -+ pfkey_sa->sadb_sa_state, -+ SADB_SASTATE_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_sa->sadb_sa_state == SADB_SASTATE_DEAD) { -+ ERROR( -+ "pfkey_sa_parse: " -+ "state=%d is DEAD=%d.\n", -+ pfkey_sa->sadb_sa_state, -+ SADB_SASTATE_DEAD); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_sa->sadb_sa_replay > 64) { -+ ERROR( -+ "pfkey_sa_parse: " -+ "replay window size: %d -- must be 0 <= size <= 64\n", -+ pfkey_sa->sadb_sa_replay); -+ SENDERR(EINVAL); -+ } -+ -+ if(! ((pfkey_sa->sadb_sa_exttype == SADB_EXT_SA) || -+ (pfkey_sa->sadb_sa_exttype == SADB_X_EXT_SA2))) -+ { -+ ERROR( -+ "pfkey_sa_parse: " -+ "unknown exttype=%d, expecting SADB_EXT_SA=%d or SADB_X_EXT_SA2=%d.\n", -+ pfkey_sa->sadb_sa_exttype, -+ SADB_EXT_SA, -+ SADB_X_EXT_SA2); -+ SENDERR(EINVAL); -+ } -+ -+ if((IPSEC_SAREF_NULL != pfkey_sa->sadb_x_sa_ref) && (pfkey_sa->sadb_x_sa_ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH))) { -+ ERROR( -+ "pfkey_sa_parse: " -+ "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n", -+ pfkey_sa->sadb_x_sa_ref, -+ IPSEC_SAREF_NULL, -+ IPSEC_SA_REF_TABLE_NUM_ENTRIES); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_sa_parse: " -+ "successfully found len=%d exttype=%d(%s) spi=%08lx replay=%d state=%d auth=%d encrypt=%d flags=%d ref=%d.\n", -+ pfkey_sa->sadb_sa_len, -+ pfkey_sa->sadb_sa_exttype, -+ pfkey_v2_sadb_ext_string(pfkey_sa->sadb_sa_exttype), -+ (long unsigned int)ntohl(pfkey_sa->sadb_sa_spi), -+ pfkey_sa->sadb_sa_replay, -+ pfkey_sa->sadb_sa_state, -+ pfkey_sa->sadb_sa_auth, -+ pfkey_sa->sadb_sa_encrypt, -+ pfkey_sa->sadb_sa_flags, -+ pfkey_sa->sadb_x_sa_ref); -+ -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_lifetime_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_lifetime_parse:enter\n"); -+ /* sanity checks... */ -+ if(!pfkey_lifetime) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_lifetime_parse: " -+ "NULL pointer passed in.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_lifetime->sadb_lifetime_len != -+ sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_lifetime_parse: " -+ "length wrong pfkey_lifetime->sadb_lifetime_len=%d sizeof(struct sadb_lifetime)=%d.\n", -+ pfkey_lifetime->sadb_lifetime_len, -+ (int)sizeof(struct sadb_lifetime)); -+ SENDERR(EINVAL); -+ } -+ -+ if((pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_HARD) && -+ (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_SOFT) && -+ (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_CURRENT)) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_lifetime_parse: " -+ "unexpected ext_type=%d.\n", -+ pfkey_lifetime->sadb_lifetime_exttype); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_lifetime_parse: " -+ "life_type=%d(%s) alloc=%u bytes=%u add=%u use=%u pkts=%u.\n", -+ pfkey_lifetime->sadb_lifetime_exttype, -+ pfkey_v2_sadb_ext_string(pfkey_lifetime->sadb_lifetime_exttype), -+ pfkey_lifetime->sadb_lifetime_allocations, -+ (unsigned)pfkey_lifetime->sadb_lifetime_bytes, -+ (unsigned)pfkey_lifetime->sadb_lifetime_addtime, -+ (unsigned)pfkey_lifetime->sadb_lifetime_usetime, -+ pfkey_lifetime->sadb_x_lifetime_packets); -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_address_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ int saddr_len = 0; -+ struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext; -+ struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address)); -+ char ipaddr_txt[ADDRTOT_BUF]; -+ -+ /* sanity checks... */ -+ if(!pfkey_address) { -+ ERROR( -+ "pfkey_address_parse: " -+ "NULL pointer passed in.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_address->sadb_address_len < -+ (sizeof(struct sadb_address) + sizeof(struct sockaddr))/ -+ IPSEC_PFKEYv2_ALIGN) { -+ ERROR("pfkey_address_parse: " -+ "size wrong 1 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n", -+ pfkey_address->sadb_address_len, -+ (int)sizeof(struct sadb_address), -+ (int)sizeof(struct sockaddr)); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_address->sadb_address_reserved) { -+ ERROR("pfkey_address_parse: " -+ "res=%d, must be zero.\n", -+ pfkey_address->sadb_address_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_address->sadb_address_exttype) { -+ case SADB_EXT_ADDRESS_SRC: -+ case SADB_EXT_ADDRESS_DST: -+ case SADB_EXT_ADDRESS_PROXY: -+ case SADB_X_EXT_ADDRESS_DST2: -+ case SADB_X_EXT_ADDRESS_SRC_FLOW: -+ case SADB_X_EXT_ADDRESS_DST_FLOW: -+ case SADB_X_EXT_ADDRESS_SRC_MASK: -+ case SADB_X_EXT_ADDRESS_DST_MASK: -+#ifdef NAT_TRAVERSAL -+ case SADB_X_EXT_NAT_T_OA: -+#endif -+ break; -+ default: -+ ERROR( -+ "pfkey_address_parse: " -+ "unexpected ext_type=%d.\n", -+ pfkey_address->sadb_address_exttype); -+ SENDERR(EINVAL); -+ } -+ -+ switch(s->sa_family) { -+ case AF_INET: -+ saddr_len = sizeof(struct sockaddr_in); -+ sprintf(ipaddr_txt, "%d.%d.%d.%d" -+ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 0) & 0xFF -+ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 8) & 0xFF -+ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 16) & 0xFF -+ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 24) & 0xFF); -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_address_parse: " -+ "found exttype=%u(%s) family=%d(AF_INET) address=%s proto=%u port=%u.\n", -+ pfkey_address->sadb_address_exttype, -+ pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype), -+ s->sa_family, -+ ipaddr_txt, -+ pfkey_address->sadb_address_proto, -+ ntohs(((struct sockaddr_in*)s)->sin_port)); -+ break; -+ case AF_INET6: -+ saddr_len = sizeof(struct sockaddr_in6); -+ sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x" -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[0]) -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[1]) -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[2]) -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[3]) -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[4]) -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[5]) -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[6]) -+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[7])); -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_address_parse: " -+ "found exttype=%u(%s) family=%d(AF_INET6) address=%s proto=%u port=%u.\n", -+ pfkey_address->sadb_address_exttype, -+ pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype), -+ s->sa_family, -+ ipaddr_txt, -+ pfkey_address->sadb_address_proto, -+ ((struct sockaddr_in6*)s)->sin6_port); -+ break; -+ default: -+ ERROR( -+ "pfkey_address_parse: " -+ "s->sa_family=%d not supported.\n", -+ s->sa_family); -+ SENDERR(EPFNOSUPPORT); -+ } -+ -+ if(pfkey_address->sadb_address_len != -+ DIVUP(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)) { -+ ERROR( -+ "pfkey_address_parse: " -+ "size wrong 2 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n", -+ pfkey_address->sadb_address_len, -+ (int)sizeof(struct sadb_address), -+ saddr_len); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_address->sadb_address_prefixlen != 0) { -+ ERROR( -+ "pfkey_address_parse: " -+ "address prefixes not supported yet.\n"); -+ SENDERR(EAFNOSUPPORT); /* not supported yet */ -+ } -+ -+ /* XXX check if port!=0 */ -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_address_parse: successful.\n"); -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_key_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_key *pfkey_key = (struct sadb_key *)pfkey_ext; -+ -+ /* sanity checks... */ -+ -+ if(!pfkey_key) { -+ ERROR( -+ "pfkey_key_parse: " -+ "NULL pointer passed in.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_key->sadb_key_len < sizeof(struct sadb_key) / IPSEC_PFKEYv2_ALIGN) { -+ ERROR( -+ "pfkey_key_parse: " -+ "size wrong ext_len=%d, key_ext_len=%d.\n", -+ pfkey_key->sadb_key_len, -+ (int)sizeof(struct sadb_key)); -+ SENDERR(EINVAL); -+ } -+ -+ if(!pfkey_key->sadb_key_bits) { -+ ERROR( -+ "pfkey_key_parse: " -+ "key length set to zero, must be non-zero.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_key->sadb_key_len != -+ DIVUP(sizeof(struct sadb_key) * OCTETBITS + pfkey_key->sadb_key_bits, -+ PFKEYBITS)) { -+ ERROR( -+ "pfkey_key_parse: " -+ "key length=%d does not agree with extension length=%d.\n", -+ pfkey_key->sadb_key_bits, -+ pfkey_key->sadb_key_len); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_key->sadb_key_reserved) { -+ ERROR( -+ "pfkey_key_parse: " -+ "res=%d, must be zero.\n", -+ pfkey_key->sadb_key_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ if(! ( (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_AUTH) || -+ (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_ENCRYPT))) { -+ ERROR( -+ "pfkey_key_parse: " -+ "expecting extension type AUTH or ENCRYPT, got %d.\n", -+ pfkey_key->sadb_key_exttype); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_key_parse: " -+ "success, found len=%d exttype=%d(%s) bits=%d reserved=%d.\n", -+ pfkey_key->sadb_key_len, -+ pfkey_key->sadb_key_exttype, -+ pfkey_v2_sadb_ext_string(pfkey_key->sadb_key_exttype), -+ pfkey_key->sadb_key_bits, -+ pfkey_key->sadb_key_reserved); -+ -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_ident_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_ident *pfkey_ident = (struct sadb_ident *)pfkey_ext; -+ -+ /* sanity checks... */ -+ if(pfkey_ident->sadb_ident_len < sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) { -+ ERROR( -+ "pfkey_ident_parse: " -+ "size wrong ext_len=%d, key_ext_len=%d.\n", -+ pfkey_ident->sadb_ident_len, -+ (int)sizeof(struct sadb_ident)); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_ident->sadb_ident_type > SADB_IDENTTYPE_MAX) { -+ ERROR( -+ "pfkey_ident_parse: " -+ "ident_type=%d out of range, must be less than %d.\n", -+ pfkey_ident->sadb_ident_type, -+ SADB_IDENTTYPE_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_ident->sadb_ident_reserved) { -+ ERROR( -+ "pfkey_ident_parse: " -+ "res=%d, must be zero.\n", -+ pfkey_ident->sadb_ident_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ /* string terminator/padding must be zero */ -+ if(pfkey_ident->sadb_ident_len > sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) { -+ if(*((char*)pfkey_ident + pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1)) { -+ ERROR( -+ "pfkey_ident_parse: " -+ "string padding must be zero, last is 0x%02x.\n", -+ *((char*)pfkey_ident + -+ pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1)); -+ SENDERR(EINVAL); -+ } -+ } -+ -+ if( ! ((pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC) || -+ (pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_DST))) { -+ ERROR( -+ "pfkey_key_parse: " -+ "expecting extension type IDENTITY_SRC or IDENTITY_DST, got %d.\n", -+ pfkey_ident->sadb_ident_exttype); -+ SENDERR(EINVAL); -+ } -+ -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_sens_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_sens *pfkey_sens = (struct sadb_sens *)pfkey_ext; -+ -+ /* sanity checks... */ -+ if(pfkey_sens->sadb_sens_len < sizeof(struct sadb_sens) / IPSEC_PFKEYv2_ALIGN) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_sens_parse: " -+ "size wrong ext_len=%d, key_ext_len=%d.\n", -+ pfkey_sens->sadb_sens_len, -+ (int)sizeof(struct sadb_sens)); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_sens_parse: " -+ "Sorry, I can't parse exttype=%d yet.\n", -+ pfkey_ext->sadb_ext_type); -+#if 0 -+ SENDERR(EINVAL); /* don't process these yet */ -+#endif -+ -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_prop_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ int i, num_comb; -+ struct sadb_prop *pfkey_prop = (struct sadb_prop *)pfkey_ext; -+ struct sadb_comb *pfkey_comb = (struct sadb_comb *)((char*)pfkey_ext + sizeof(struct sadb_prop)); -+ -+ /* sanity checks... */ -+ if((pfkey_prop->sadb_prop_len < sizeof(struct sadb_prop) / IPSEC_PFKEYv2_ALIGN) || -+ (((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) % sizeof(struct sadb_comb))) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "size wrong ext_len=%d, prop_ext_len=%d comb_ext_len=%d.\n", -+ pfkey_prop->sadb_prop_len, -+ (int)sizeof(struct sadb_prop), -+ (int)sizeof(struct sadb_comb)); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_prop->sadb_prop_replay > 64) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "replay window size: %d -- must be 0 <= size <= 64\n", -+ pfkey_prop->sadb_prop_replay); -+ SENDERR(EINVAL); -+ } -+ -+ for(i=0; i<3; i++) { -+ if(pfkey_prop->sadb_prop_reserved[i]) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "res[%d]=%d, must be zero.\n", -+ i, pfkey_prop->sadb_prop_reserved[i]); -+ SENDERR(EINVAL); -+ } -+ } -+ -+ num_comb = ((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) / sizeof(struct sadb_comb); -+ -+ for(i = 0; i < num_comb; i++) { -+ if(pfkey_comb->sadb_comb_auth > SADB_AALG_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_auth=%d > SADB_AALG_MAX=%d.\n", -+ i, -+ pfkey_comb->sadb_comb_auth, -+ SADB_AALG_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_comb->sadb_comb_auth) { -+ if(!pfkey_comb->sadb_comb_auth_minbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_auth_minbits=0, fatal.\n", -+ i); -+ SENDERR(EINVAL); -+ } -+ if(!pfkey_comb->sadb_comb_auth_maxbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_auth_maxbits=0, fatal.\n", -+ i); -+ SENDERR(EINVAL); -+ } -+ if(pfkey_comb->sadb_comb_auth_minbits > pfkey_comb->sadb_comb_auth_maxbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_auth_minbits=%d > maxbits=%d, fatal.\n", -+ i, -+ pfkey_comb->sadb_comb_auth_minbits, -+ pfkey_comb->sadb_comb_auth_maxbits); -+ SENDERR(EINVAL); -+ } -+ } else { -+ if(pfkey_comb->sadb_comb_auth_minbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_auth_minbits=%d != 0, fatal.\n", -+ i, -+ pfkey_comb->sadb_comb_auth_minbits); -+ SENDERR(EINVAL); -+ } -+ if(pfkey_comb->sadb_comb_auth_maxbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_auth_maxbits=%d != 0, fatal.\n", -+ i, -+ pfkey_comb->sadb_comb_auth_maxbits); -+ SENDERR(EINVAL); -+ } -+ } -+ -+ if(pfkey_comb->sadb_comb_encrypt > SADB_EALG_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_comb_parse: " -+ "pfkey_comb[%d]->sadb_comb_encrypt=%d > SADB_EALG_MAX=%d.\n", -+ i, -+ pfkey_comb->sadb_comb_encrypt, -+ SADB_EALG_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_comb->sadb_comb_encrypt) { -+ if(!pfkey_comb->sadb_comb_encrypt_minbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_encrypt_minbits=0, fatal.\n", -+ i); -+ SENDERR(EINVAL); -+ } -+ if(!pfkey_comb->sadb_comb_encrypt_maxbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=0, fatal.\n", -+ i); -+ SENDERR(EINVAL); -+ } -+ if(pfkey_comb->sadb_comb_encrypt_minbits > pfkey_comb->sadb_comb_encrypt_maxbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d > maxbits=%d, fatal.\n", -+ i, -+ pfkey_comb->sadb_comb_encrypt_minbits, -+ pfkey_comb->sadb_comb_encrypt_maxbits); -+ SENDERR(EINVAL); -+ } -+ } else { -+ if(pfkey_comb->sadb_comb_encrypt_minbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d != 0, fatal.\n", -+ i, -+ pfkey_comb->sadb_comb_encrypt_minbits); -+ SENDERR(EINVAL); -+ } -+ if(pfkey_comb->sadb_comb_encrypt_maxbits) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=%d != 0, fatal.\n", -+ i, -+ pfkey_comb->sadb_comb_encrypt_maxbits); -+ SENDERR(EINVAL); -+ } -+ } -+ -+ /* XXX do sanity check on flags */ -+ -+ if(pfkey_comb->sadb_comb_hard_allocations && pfkey_comb->sadb_comb_soft_allocations > pfkey_comb->sadb_comb_hard_allocations) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_soft_allocations=%d > hard_allocations=%d, fatal.\n", -+ i, -+ pfkey_comb->sadb_comb_soft_allocations, -+ pfkey_comb->sadb_comb_hard_allocations); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_comb->sadb_comb_hard_bytes && pfkey_comb->sadb_comb_soft_bytes > pfkey_comb->sadb_comb_hard_bytes) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_soft_bytes=%Ld > hard_bytes=%Ld, fatal.\n", -+ i, -+ (unsigned long long int)pfkey_comb->sadb_comb_soft_bytes, -+ (unsigned long long int)pfkey_comb->sadb_comb_hard_bytes); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_comb->sadb_comb_hard_addtime && pfkey_comb->sadb_comb_soft_addtime > pfkey_comb->sadb_comb_hard_addtime) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_soft_addtime=%Ld > hard_addtime=%Ld, fatal.\n", -+ i, -+ (unsigned long long int)pfkey_comb->sadb_comb_soft_addtime, -+ (unsigned long long int)pfkey_comb->sadb_comb_hard_addtime); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_comb->sadb_comb_hard_usetime && pfkey_comb->sadb_comb_soft_usetime > pfkey_comb->sadb_comb_hard_usetime) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_comb_soft_usetime=%Ld > hard_usetime=%Ld, fatal.\n", -+ i, -+ (unsigned long long int)pfkey_comb->sadb_comb_soft_usetime, -+ (unsigned long long int)pfkey_comb->sadb_comb_hard_usetime); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_comb->sadb_x_comb_hard_packets && pfkey_comb->sadb_x_comb_soft_packets > pfkey_comb->sadb_x_comb_hard_packets) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "pfkey_comb[%d]->sadb_x_comb_soft_packets=%d > hard_packets=%d, fatal.\n", -+ i, -+ pfkey_comb->sadb_x_comb_soft_packets, -+ pfkey_comb->sadb_x_comb_hard_packets); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_comb->sadb_comb_reserved) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_prop_parse: " -+ "comb[%d].res=%d, must be zero.\n", -+ i, -+ pfkey_comb->sadb_comb_reserved); -+ SENDERR(EINVAL); -+ } -+ pfkey_comb++; -+ } -+ -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_supported_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ unsigned int i, num_alg; -+ struct sadb_supported *pfkey_supported = (struct sadb_supported *)pfkey_ext; -+ struct sadb_alg *pfkey_alg = (struct sadb_alg*)((char*)pfkey_ext + sizeof(struct sadb_supported)); -+ -+ /* sanity checks... */ -+ if((pfkey_supported->sadb_supported_len < -+ sizeof(struct sadb_supported) / IPSEC_PFKEYv2_ALIGN) || -+ (((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) - -+ sizeof(struct sadb_supported)) % sizeof(struct sadb_alg))) { -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_supported_parse: " -+ "size wrong ext_len=%d, supported_ext_len=%d alg_ext_len=%d.\n", -+ pfkey_supported->sadb_supported_len, -+ (int)sizeof(struct sadb_supported), -+ (int)sizeof(struct sadb_alg)); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_supported->sadb_supported_reserved) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_supported_parse: " -+ "res=%d, must be zero.\n", -+ pfkey_supported->sadb_supported_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ num_alg = ((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_supported)) / sizeof(struct sadb_alg); -+ -+ for(i = 0; i < num_alg; i++) { -+ /* process algo description */ -+ if(pfkey_alg->sadb_alg_reserved) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_supported_parse: " -+ "alg[%d], id=%d, ivlen=%d, minbits=%d, maxbits=%d, res=%d, must be zero.\n", -+ i, -+ pfkey_alg->sadb_alg_id, -+ pfkey_alg->sadb_alg_ivlen, -+ pfkey_alg->sadb_alg_minbits, -+ pfkey_alg->sadb_alg_maxbits, -+ pfkey_alg->sadb_alg_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ /* XXX can alg_id auth/enc be determined from info given? -+ Yes, but OpenBSD's method does not iteroperate with rfc2367. -+ rgb, 2000-04-06 */ -+ -+ switch(pfkey_supported->sadb_supported_exttype) { -+ case SADB_EXT_SUPPORTED_AUTH: -+ if(pfkey_alg->sadb_alg_id > SADB_AALG_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_supported_parse: " -+ "alg[%d], alg_id=%d > SADB_AALG_MAX=%d, fatal.\n", -+ i, -+ pfkey_alg->sadb_alg_id, -+ SADB_AALG_MAX); -+ SENDERR(EINVAL); -+ } -+ break; -+ case SADB_EXT_SUPPORTED_ENCRYPT: -+ if(pfkey_alg->sadb_alg_id > SADB_EALG_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_supported_parse: " -+ "alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n", -+ i, -+ pfkey_alg->sadb_alg_id, -+ SADB_EALG_MAX); -+ SENDERR(EINVAL); -+ } -+ break; -+ default: -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_supported_parse: " -+ "alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n", -+ i, -+ pfkey_alg->sadb_alg_id, -+ SADB_EALG_MAX); -+ SENDERR(EINVAL); -+ } -+ pfkey_alg++; -+ } -+ -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_spirange_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)pfkey_ext; -+ -+ /* sanity checks... */ -+ if(pfkey_spirange->sadb_spirange_len != -+ sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_spirange_parse: " -+ "size wrong ext_len=%d, key_ext_len=%d.\n", -+ pfkey_spirange->sadb_spirange_len, -+ (int)sizeof(struct sadb_spirange)); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_spirange->sadb_spirange_reserved) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_spirange_parse: " -+ "reserved=%d must be set to zero.\n", -+ pfkey_spirange->sadb_spirange_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ if(ntohl(pfkey_spirange->sadb_spirange_max) < ntohl(pfkey_spirange->sadb_spirange_min)) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_spirange_parse: " -+ "minspi=%08x must be < maxspi=%08x.\n", -+ ntohl(pfkey_spirange->sadb_spirange_min), -+ ntohl(pfkey_spirange->sadb_spirange_max)); -+ SENDERR(EINVAL); -+ } -+ -+ if(ntohl(pfkey_spirange->sadb_spirange_min) <= 255) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_spirange_parse: " -+ "minspi=%08x must be > 255.\n", -+ ntohl(pfkey_spirange->sadb_spirange_min)); -+ SENDERR(EEXIST); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_spirange_parse: " -+ "ext_len=%u ext_type=%u(%s) min=%u max=%u res=%u.\n", -+ pfkey_spirange->sadb_spirange_len, -+ pfkey_spirange->sadb_spirange_exttype, -+ pfkey_v2_sadb_ext_string(pfkey_spirange->sadb_spirange_exttype), -+ pfkey_spirange->sadb_spirange_min, -+ pfkey_spirange->sadb_spirange_max, -+ pfkey_spirange->sadb_spirange_reserved); -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_kmprivate_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)pfkey_ext; -+ -+ /* sanity checks... */ -+ if(pfkey_x_kmprivate->sadb_x_kmprivate_len < -+ sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_kmprivate_parse: " -+ "size wrong ext_len=%d, key_ext_len=%d.\n", -+ pfkey_x_kmprivate->sadb_x_kmprivate_len, -+ (int)sizeof(struct sadb_x_kmprivate)); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_x_kmprivate->sadb_x_kmprivate_reserved) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_kmprivate_parse: " -+ "reserved=%d must be set to zero.\n", -+ pfkey_x_kmprivate->sadb_x_kmprivate_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_kmprivate_parse: " -+ "Sorry, I can't parse exttype=%d yet.\n", -+ pfkey_ext->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_satype_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ int i; -+ struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_x_satype_parse: enter\n"); -+ /* sanity checks... */ -+ if(pfkey_x_satype->sadb_x_satype_len != -+ sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_satype_parse: " -+ "size wrong ext_len=%d, key_ext_len=%d.\n", -+ pfkey_x_satype->sadb_x_satype_len, -+ (int)sizeof(struct sadb_x_satype)); -+ SENDERR(EINVAL); -+ } -+ -+ if(!pfkey_x_satype->sadb_x_satype_satype) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_satype_parse: " -+ "satype is zero, must be non-zero.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_x_satype->sadb_x_satype_satype > SADB_SATYPE_MAX) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_satype_parse: " -+ "satype %d > max %d, invalid.\n", -+ pfkey_x_satype->sadb_x_satype_satype, SADB_SATYPE_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(satype2proto(pfkey_x_satype->sadb_x_satype_satype))) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_satype_parse: " -+ "proto lookup from satype=%d failed.\n", -+ pfkey_x_satype->sadb_x_satype_satype); -+ SENDERR(EINVAL); -+ } -+ -+ for(i = 0; i < 3; i++) { -+ if(pfkey_x_satype->sadb_x_satype_reserved[i]) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_satype_parse: " -+ "reserved[%d]=%d must be set to zero.\n", -+ i, pfkey_x_satype->sadb_x_satype_reserved[i]); -+ SENDERR(EINVAL); -+ } -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_x_satype_parse: " -+ "len=%u ext=%u(%s) satype=%u(%s) res=%u,%u,%u.\n", -+ pfkey_x_satype->sadb_x_satype_len, -+ pfkey_x_satype->sadb_x_satype_exttype, -+ pfkey_v2_sadb_ext_string(pfkey_x_satype->sadb_x_satype_exttype), -+ pfkey_x_satype->sadb_x_satype_satype, -+ satype2name(pfkey_x_satype->sadb_x_satype_satype), -+ pfkey_x_satype->sadb_x_satype_reserved[0], -+ pfkey_x_satype->sadb_x_satype_reserved[1], -+ pfkey_x_satype->sadb_x_satype_reserved[2]); -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_ext_debug_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ int i; -+ struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_x_debug_parse: enter\n"); -+ /* sanity checks... */ -+ if(pfkey_x_debug->sadb_x_debug_len != -+ sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_debug_parse: " -+ "size wrong ext_len=%d, key_ext_len=%d.\n", -+ pfkey_x_debug->sadb_x_debug_len, -+ (int)sizeof(struct sadb_x_debug)); -+ SENDERR(EINVAL); -+ } -+ -+ for(i = 0; i < 4; i++) { -+ if(pfkey_x_debug->sadb_x_debug_reserved[i]) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_debug_parse: " -+ "reserved[%d]=%d must be set to zero.\n", -+ i, pfkey_x_debug->sadb_x_debug_reserved[i]); -+ SENDERR(EINVAL); -+ } -+ } -+ -+errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_ext_protocol_parse(struct sadb_ext *pfkey_ext) -+{ -+ int error = 0; -+ struct sadb_protocol *p = (struct sadb_protocol *)pfkey_ext; -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_protocol_parse:\n"); -+ /* sanity checks... */ -+ -+ if (p->sadb_protocol_len != sizeof(*p)/IPSEC_PFKEYv2_ALIGN) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_x_protocol_parse: size wrong ext_len=%d, key_ext_len=%d.\n", -+ p->sadb_protocol_len, (int)sizeof(*p)); -+ SENDERR(EINVAL); -+ } -+ -+ if (p->sadb_protocol_reserved2 != 0) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_protocol_parse: res=%d, must be zero.\n", -+ p->sadb_protocol_reserved2); -+ SENDERR(EINVAL); -+ } -+ -+ errlab: -+ return error; -+} -+ -+#ifdef NAT_TRAVERSAL -+DEBUG_NO_STATIC int -+pfkey_x_ext_nat_t_type_parse(struct sadb_ext *pfkey_ext) -+{ -+ return 0; -+} -+DEBUG_NO_STATIC int -+pfkey_x_ext_nat_t_port_parse(struct sadb_ext *pfkey_ext) -+{ -+ return 0; -+} -+#endif -+ -+#define DEFINEPARSER(NAME) static struct pf_key_ext_parsers_def NAME##_def={NAME, #NAME}; -+ -+DEFINEPARSER(pfkey_sa_parse); -+DEFINEPARSER(pfkey_lifetime_parse); -+DEFINEPARSER(pfkey_address_parse); -+DEFINEPARSER(pfkey_key_parse); -+DEFINEPARSER(pfkey_ident_parse); -+DEFINEPARSER(pfkey_sens_parse); -+DEFINEPARSER(pfkey_prop_parse); -+DEFINEPARSER(pfkey_supported_parse); -+DEFINEPARSER(pfkey_spirange_parse); -+DEFINEPARSER(pfkey_x_kmprivate_parse); -+DEFINEPARSER(pfkey_x_satype_parse); -+DEFINEPARSER(pfkey_x_ext_debug_parse); -+DEFINEPARSER(pfkey_x_ext_protocol_parse); -+#ifdef NAT_TRAVERSAL -+DEFINEPARSER(pfkey_x_ext_nat_t_type_parse); -+DEFINEPARSER(pfkey_x_ext_nat_t_port_parse); -+#endif -+ -+struct pf_key_ext_parsers_def *ext_default_parsers[]= -+{ -+ NULL, /* pfkey_msg_parse, */ -+ &pfkey_sa_parse_def, -+ &pfkey_lifetime_parse_def, -+ &pfkey_lifetime_parse_def, -+ &pfkey_lifetime_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_key_parse_def, -+ &pfkey_key_parse_def, -+ &pfkey_ident_parse_def, -+ &pfkey_ident_parse_def, -+ &pfkey_sens_parse_def, -+ &pfkey_prop_parse_def, -+ &pfkey_supported_parse_def, -+ &pfkey_supported_parse_def, -+ &pfkey_spirange_parse_def, -+ &pfkey_x_kmprivate_parse_def, -+ &pfkey_x_satype_parse_def, -+ &pfkey_sa_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_address_parse_def, -+ &pfkey_x_ext_debug_parse_def, -+ &pfkey_x_ext_protocol_parse_def -+#ifdef NAT_TRAVERSAL -+ , -+ &pfkey_x_ext_nat_t_type_parse_def, -+ &pfkey_x_ext_nat_t_port_parse_def, -+ &pfkey_x_ext_nat_t_port_parse_def, -+ &pfkey_address_parse_def -+#endif -+}; -+ -+int -+pfkey_msg_parse(struct sadb_msg *pfkey_msg, -+ struct pf_key_ext_parsers_def *ext_parsers[], -+ struct sadb_ext *extensions[], -+ int dir) -+{ -+ int error = 0; -+ int remain; -+ struct sadb_ext *pfkey_ext; -+ int extensions_seen = 0; -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_msg_parse: " -+ "parsing message ver=%d, type=%d(%s), errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n", -+ pfkey_msg->sadb_msg_version, -+ pfkey_msg->sadb_msg_type, -+ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type), -+ pfkey_msg->sadb_msg_errno, -+ pfkey_msg->sadb_msg_satype, -+ satype2name(pfkey_msg->sadb_msg_satype), -+ pfkey_msg->sadb_msg_len, -+ pfkey_msg->sadb_msg_reserved, -+ pfkey_msg->sadb_msg_seq, -+ pfkey_msg->sadb_msg_pid); -+ -+ if(ext_parsers == NULL) ext_parsers = ext_default_parsers; -+ -+ pfkey_extensions_init(extensions); -+ -+ remain = pfkey_msg->sadb_msg_len; -+ remain -= sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN; -+ -+ pfkey_ext = (struct sadb_ext*)((char*)pfkey_msg + -+ sizeof(struct sadb_msg)); -+ -+ extensions[0] = (struct sadb_ext *) pfkey_msg; -+ -+ -+ if(pfkey_msg->sadb_msg_version != PF_KEY_V2) { -+ ERROR("pfkey_msg_parse: " -+ "not PF_KEY_V2 msg, found %d, should be %d.\n", -+ pfkey_msg->sadb_msg_version, -+ PF_KEY_V2); -+ SENDERR(EINVAL); -+ } -+ -+ if(!pfkey_msg->sadb_msg_type) { -+ ERROR("pfkey_msg_parse: " -+ "msg type not set, must be non-zero..\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(pfkey_msg->sadb_msg_type > SADB_MAX) { -+ ERROR("pfkey_msg_parse: " -+ "msg type=%d > max=%d.\n", -+ pfkey_msg->sadb_msg_type, -+ SADB_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_msg->sadb_msg_type) { -+ case SADB_GETSPI: -+ case SADB_UPDATE: -+ case SADB_ADD: -+ case SADB_DELETE: -+ case SADB_GET: -+ case SADB_X_GRPSA: -+ case SADB_X_ADDFLOW: -+ if(!satype2proto(pfkey_msg->sadb_msg_satype)) { -+ ERROR("pfkey_msg_parse: " -+ "satype %d conversion to proto failed for msg_type %d (%s).\n", -+ pfkey_msg->sadb_msg_satype, -+ pfkey_msg->sadb_msg_type, -+ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type)); -+ SENDERR(EINVAL); -+ } else { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "satype %d(%s) conversion to proto gives %d for msg_type %d(%s).\n", -+ pfkey_msg->sadb_msg_satype, -+ satype2name(pfkey_msg->sadb_msg_satype), -+ satype2proto(pfkey_msg->sadb_msg_satype), -+ pfkey_msg->sadb_msg_type, -+ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type)); -+ } -+ case SADB_ACQUIRE: -+ case SADB_REGISTER: -+ case SADB_EXPIRE: -+ if(!pfkey_msg->sadb_msg_satype) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "satype is zero, must be non-zero for msg_type %d(%s).\n", -+ pfkey_msg->sadb_msg_type, -+ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type)); -+ SENDERR(EINVAL); -+ } -+ default: -+ break; -+ } -+ -+ /* errno must not be set in downward messages */ -+ /* this is not entirely true... a response to an ACQUIRE could return an error */ -+ if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type != SADB_ACQUIRE) && pfkey_msg->sadb_msg_errno) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "errno set to %d.\n", -+ pfkey_msg->sadb_msg_errno); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_msg_parse: " -+ "remain=%d, ext_type=%d(%s), ext_len=%d.\n", -+ remain, -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), -+ pfkey_ext->sadb_ext_len); -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_msg_parse: " -+ "extensions permitted=%08x, required=%08x.\n", -+ extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type], -+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]); -+ -+ extensions_seen = 1; -+ -+ while( (remain * IPSEC_PFKEYv2_ALIGN) >= sizeof(struct sadb_ext) ) { -+ /* Is there enough message left to support another extension header? */ -+ if(remain < pfkey_ext->sadb_ext_len) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "remain %d less than ext len %d.\n", -+ remain, pfkey_ext->sadb_ext_len); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_msg_parse: " -+ "parsing ext type=%d(%s) remain=%d.\n", -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), -+ remain); -+ -+ /* Is the extension header type valid? */ -+ if((pfkey_ext->sadb_ext_type > SADB_EXT_MAX) || (!pfkey_ext->sadb_ext_type)) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "ext type %d(%s) invalid, SADB_EXT_MAX=%d.\n", -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), -+ SADB_EXT_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ /* Have we already seen this type of extension? */ -+ if((extensions_seen & ( 1 << pfkey_ext->sadb_ext_type )) != 0) -+ { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "ext type %d(%s) already seen.\n", -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type)); -+ SENDERR(EINVAL); -+ } -+ -+ /* Do I even know about this type of extension? */ -+ if(ext_parsers[pfkey_ext->sadb_ext_type]==NULL) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "ext type %d(%s) unknown, ignoring.\n", -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type)); -+ goto next_ext; -+ } -+ -+ /* Is this type of extension permitted for this type of message? */ -+ if(!(extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type] & -+ 1<sadb_ext_type)) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "ext type %d(%s) not permitted, exts_perm_in=%08x, 1<sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), -+ extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type], -+ 1<sadb_ext_type); -+ SENDERR(EINVAL); -+ } -+ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_msg_parse: " -+ "remain=%d ext_type=%d(%s) ext_len=%d parsing ext 0p%p with parser %s.\n", -+ remain, -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), -+ pfkey_ext->sadb_ext_len, -+ pfkey_ext, -+ ext_parsers[pfkey_ext->sadb_ext_type]->parser_name); -+ -+ /* Parse the extension */ -+ if((error = -+ (*ext_parsers[pfkey_ext->sadb_ext_type]->parser)(pfkey_ext))) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "extension parsing for type %d(%s) failed with error %d.\n", -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), -+ error); -+ SENDERR(-error); -+ } -+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, -+ "pfkey_msg_parse: " -+ "Extension %d(%s) parsed.\n", -+ pfkey_ext->sadb_ext_type, -+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type)); -+ -+ /* Mark that we have seen this extension and remember the header location */ -+ extensions_seen |= ( 1 << pfkey_ext->sadb_ext_type ); -+ extensions[pfkey_ext->sadb_ext_type] = pfkey_ext; -+ -+ next_ext: -+ /* Calculate how much message remains */ -+ remain -= pfkey_ext->sadb_ext_len; -+ -+ if(!remain) { -+ break; -+ } -+ /* Find the next extension header */ -+ pfkey_ext = (struct sadb_ext*)((char*)pfkey_ext + -+ pfkey_ext->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); -+ } -+ -+ if(remain) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "unexpected remainder of %d.\n", -+ remain); -+ /* why is there still something remaining? */ -+ SENDERR(EINVAL); -+ } -+ -+ /* check required extensions */ -+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, -+ "pfkey_msg_parse: " -+ "extensions permitted=%08x, seen=%08x, required=%08x.\n", -+ extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type], -+ extensions_seen, -+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]); -+ -+ /* don't check further if it is an error return message since it -+ may not have a body */ -+ if(pfkey_msg->sadb_msg_errno) { -+ SENDERR(-error); -+ } -+ -+ if((extensions_seen & -+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]) != -+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "required extensions missing:%08x.\n", -+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type] - -+ (extensions_seen & -+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type])); -+ SENDERR(EINVAL); -+ } -+ -+ if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type == SADB_X_DELFLOW) -+ && ((extensions_seen & SADB_X_EXT_ADDRESS_DELFLOW) -+ != SADB_X_EXT_ADDRESS_DELFLOW) -+ && (((extensions_seen & (1<sadb_sa_flags -+ & SADB_X_SAFLAGS_CLEARFLOW) -+ != SADB_X_SAFLAGS_CLEARFLOW))) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "required SADB_X_DELFLOW extensions missing: either %08x must be present or %08x must be present with SADB_X_SAFLAGS_CLEARFLOW set.\n", -+ SADB_X_EXT_ADDRESS_DELFLOW -+ - (extensions_seen & SADB_X_EXT_ADDRESS_DELFLOW), -+ (1<sadb_msg_type) { -+ case SADB_ADD: -+ case SADB_UPDATE: -+ /* check maturity */ -+ if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != -+ SADB_SASTATE_MATURE) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "state=%d for add or update should be MATURE=%d.\n", -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state, -+ SADB_SASTATE_MATURE); -+ SENDERR(EINVAL); -+ } -+ -+ /* check AH and ESP */ -+ switch(((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype) { -+ case SADB_SATYPE_AH: -+ if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) && -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_auth != -+ SADB_AALG_NONE)) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "auth alg is zero, must be non-zero for AH SAs.\n"); -+ SENDERR(EINVAL); -+ } -+ if(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt != -+ SADB_EALG_NONE) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "AH handed encalg=%d, must be zero.\n", -+ ((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt); -+ SENDERR(EINVAL); -+ } -+ break; -+ case SADB_SATYPE_ESP: -+ if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) && -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt != -+ SADB_EALG_NONE)) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "encrypt alg=%d is zero, must be non-zero for ESP=%d SAs.\n", -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype); -+ SENDERR(EINVAL); -+ } -+ if((((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt == -+ SADB_EALG_NULL) && -+ (((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth == -+ SADB_AALG_NONE) ) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "ESP handed encNULL+authNONE, illegal combination.\n"); -+ SENDERR(EINVAL); -+ } -+ break; -+ case SADB_X_SATYPE_COMP: -+ if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) && -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt != -+ SADB_EALG_NONE)) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "encrypt alg=%d is zero, must be non-zero for COMP=%d SAs.\n", -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype); -+ SENDERR(EINVAL); -+ } -+ if(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth != -+ SADB_AALG_NONE) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "COMP handed auth=%d, must be zero.\n", -+ ((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth); -+ SENDERR(EINVAL); -+ } -+ break; -+ default: -+ break; -+ } -+ if(ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi) <= 255) { -+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, -+ "pfkey_msg_parse: " -+ "spi=%08x must be > 255.\n", -+ ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi)); -+ SENDERR(EINVAL); -+ } -+ default: -+ break; -+ } -+errlab: -+ -+ return error; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.59 2004/04/18 03:03:49 mcr -+ * renamed common include files from pluto directory. -+ * -+ * Revision 1.58 2004/03/08 01:59:08 ken -+ * freeswan.h -> openswan.h -+ * -+ * Revision 1.57 2003/12/10 01:20:19 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.56 2003/12/04 23:01:12 mcr -+ * removed ipsec_netlink.h -+ * -+ * Revision 1.55 2003/11/07 01:30:37 ken -+ * Cast sizeof() to int to keep things 64bit clean -+ * -+ * Revision 1.54 2003/10/31 02:27:12 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.53.20.2 2003/10/29 01:11:32 mcr -+ * added debugging for pfkey library. -+ * -+ * Revision 1.53.20.1 2003/09/21 13:59:44 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.53 2003/01/30 02:32:09 rgb -+ * -+ * Rename SAref table macro names for clarity. -+ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. -+ * -+ * Revision 1.52 2002/12/30 06:53:07 mcr -+ * deal with short SA structures... #if 0 out for now. Probably -+ * not quite the right way. -+ * -+ * Revision 1.51 2002/12/13 18:16:02 mcr -+ * restored sa_ref code -+ * -+ * Revision 1.50 2002/12/13 18:06:52 mcr -+ * temporarily removed sadb_x_sa_ref reference for 2.xx -+ * -+ * Revision 1.49 2002/10/05 05:02:58 dhr -+ * -+ * C labels go on statements -+ * -+ * Revision 1.48 2002/09/20 15:40:45 rgb -+ * Added sadb_x_sa_ref to struct sadb_sa. -+ * -+ * Revision 1.47 2002/09/20 05:01:31 rgb -+ * Fixed usage of pfkey_lib_debug. -+ * Format for function declaration style consistency. -+ * Added text labels to elucidate numeric values presented. -+ * Re-organised debug output to reduce noise in output. -+ * -+ * Revision 1.46 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.45 2002/05/23 07:14:11 rgb -+ * Cleaned up %p variants to 0p%p for test suite cleanup. -+ * -+ * Revision 1.44 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.43 2002/04/24 07:36:40 mcr -+ * Moved from ./lib/pfkey_v2_parse.c,v -+ * -+ * Revision 1.42 2002/01/29 22:25:36 rgb -+ * Re-add ipsec_kversion.h to keep MALLOC happy. -+ * -+ * Revision 1.41 2002/01/29 01:59:10 mcr -+ * removal of kversions.h - sources that needed it now use ipsec_param.h. -+ * updating of IPv6 structures to match latest in6.h version. -+ * removed dead code from openswan.h that also duplicated kversions.h -+ * code. -+ * -+ * Revision 1.40 2002/01/20 20:34:50 mcr -+ * added pfkey_v2_sadb_type_string to decode sadb_type to string. -+ * -+ * Revision 1.39 2001/11/27 05:29:22 mcr -+ * pfkey parses are now maintained by a structure -+ * that includes their name for debug purposes. -+ * DEBUGGING() macro changed so that it takes a debug -+ * level so that pf_key() can use this to decode the -+ * structures without innundanting humans. -+ * Also uses pfkey_v2_sadb_ext_string() in messages. -+ * -+ * Revision 1.38 2001/11/06 19:47:47 rgb -+ * Added packet parameter to lifetime and comb structures. -+ * -+ * Revision 1.37 2001/10/18 04:45:24 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/openswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.36 2001/06/14 19:35:16 rgb -+ * Update copyright date. -+ * -+ * Revision 1.35 2001/05/03 19:44:51 rgb -+ * Standardise on SENDERR() macro. -+ * -+ * Revision 1.34 2001/03/16 07:41:51 rgb -+ * Put openswan.h include before pluto includes. -+ * -+ * Revision 1.33 2001/02/27 07:13:51 rgb -+ * Added satype2name() function. -+ * Added text to default satype_tbl entry. -+ * Added satype2name() conversions for most satype debug output. -+ * -+ * Revision 1.32 2001/02/26 20:01:09 rgb -+ * Added internal IP protocol 61 for magic SAs. -+ * Ditch unused sadb_satype2proto[], replaced by satype2proto(). -+ * Re-formatted debug output (split lines, consistent spacing). -+ * Removed acquire, register and expire requirements for a known satype. -+ * Changed message type checking to a switch structure. -+ * Verify expected NULL auth for IPCOMP. -+ * Enforced spi > 0x100 requirement, now that pass uses a magic SA for -+ * appropriate message types. -+ * -+ * Revision 1.31 2000/12/01 07:09:00 rgb -+ * Added ipcomp sanity check to require encalgo is set. -+ * -+ * Revision 1.30 2000/11/17 18:10:30 rgb -+ * Fixed bugs mostly relating to spirange, to treat all spi variables as -+ * network byte order since this is the way PF_KEYv2 stored spis. -+ * -+ * Revision 1.29 2000/10/12 00:02:39 rgb -+ * Removed 'format, ##' nonsense from debug macros for RH7.0. -+ * -+ * Revision 1.28 2000/09/20 16:23:04 rgb -+ * Remove over-paranoid extension check in the presence of sadb_msg_errno. -+ * -+ * Revision 1.27 2000/09/20 04:04:21 rgb -+ * Changed static functions to DEBUG_NO_STATIC to reveal function names in -+ * oopsen. -+ * -+ * Revision 1.26 2000/09/15 11:37:02 rgb -+ * Merge in heavily modified Svenning Soerensen's -+ * IPCOMP zlib deflate code. -+ * -+ * Revision 1.25 2000/09/12 22:35:37 rgb -+ * Restructured to remove unused extensions from CLEARFLOW messages. -+ * -+ * Revision 1.24 2000/09/12 18:59:54 rgb -+ * Added Gerhard's IPv6 support to pfkey parts of libopenswan. -+ * -+ * Revision 1.23 2000/09/12 03:27:00 rgb -+ * Moved DEBUGGING definition to compile kernel with debug off. -+ * -+ * Revision 1.22 2000/09/09 06:39:27 rgb -+ * Restrict pfkey errno check to downward messages only. -+ * -+ * Revision 1.21 2000/09/08 19:22:34 rgb -+ * Enabled pfkey_sens_parse(). -+ * Added check for errno on downward acquire messages only. -+ * -+ * Revision 1.20 2000/09/01 18:48:23 rgb -+ * Fixed reserved check bug and added debug output in -+ * pfkey_supported_parse(). -+ * Fixed debug output label bug in pfkey_ident_parse(). -+ * -+ * Revision 1.19 2000/08/27 01:55:26 rgb -+ * Define OCTETBITS and PFKEYBITS to avoid using 'magic' numbers in code. -+ * -+ * Revision 1.18 2000/08/24 17:00:36 rgb -+ * Ignore unknown extensions instead of failing. -+ * -+ * Revision 1.17 2000/06/02 22:54:14 rgb -+ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support. -+ * -+ * Revision 1.16 2000/05/10 19:25:11 rgb -+ * Fleshed out proposal and supported extensions. -+ * -+ * Revision 1.15 2000/01/24 21:15:31 rgb -+ * Added disabled pluto pfkey lib debug flag. -+ * Added algo debugging reporting. -+ * -+ * Revision 1.14 2000/01/22 23:24:29 rgb -+ * Added new functions proto2satype() and satype2proto() and lookup -+ * table satype_tbl. Also added proto2name() since it was easy. -+ * -+ * Revision 1.13 2000/01/21 09:43:59 rgb -+ * Cast ntohl(spi) as (unsigned long int) to shut up compiler. -+ * -+ * Revision 1.12 2000/01/21 06:28:19 rgb -+ * Added address cases for eroute flows. -+ * Indented compiler directives for readability. -+ * Added klipsdebug switching capability. -+ * -+ * Revision 1.11 1999/12/29 21:14:59 rgb -+ * Fixed debug text cut and paste typo. -+ * -+ * Revision 1.10 1999/12/10 17:45:24 rgb -+ * Added address debugging. -+ * -+ * Revision 1.9 1999/12/09 23:11:42 rgb -+ * Ditched include since we no longer use memset(). -+ * Use new pfkey_extensions_init() instead of memset(). -+ * Added check for SATYPE in pfkey_msg_build(). -+ * Tidy up comments and debugging comments. -+ * -+ * Revision 1.8 1999/12/07 19:55:26 rgb -+ * Removed unused first argument from extension parsers. -+ * Removed static pluto debug flag. -+ * Moved message type and state checking to pfkey_msg_parse(). -+ * Changed print[fk] type from lx to x to quiet compiler. -+ * Removed redundant remain check. -+ * Changed __u* types to uint* to avoid use of asm/types.h and -+ * sys/types.h in userspace code. -+ * -+ * Revision 1.7 1999/12/01 22:20:51 rgb -+ * Moved pfkey_lib_debug variable into the library. -+ * Added pfkey version check into header parsing. -+ * Added check for SATYPE only for those extensions that require a -+ * non-zero value. -+ * -+ * Revision 1.6 1999/11/27 11:58:05 rgb -+ * Added ipv6 headers. -+ * Moved sadb_satype2proto protocol lookup table from -+ * klips/net/ipsec/pfkey_v2_parser.c. -+ * Enable lifetime_current checking. -+ * Debugging error messages added. -+ * Add argument to pfkey_msg_parse() for direction. -+ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array. -+ * Add CVS log entry to bottom of file. -+ * Moved auth and enc alg check to pfkey_msg_parse(). -+ * Enable accidentally disabled spirange parsing. -+ * Moved protocol/algorithm checks from klips/net/ipsec/pfkey_v2_parser.c -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/prng.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,201 @@ -+/* -+ * crypto-class pseudorandom number generator -+ * currently uses same algorithm as RC4(TM), from Schneier 2nd ed p397 -+ * Copyright (C) 2002 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - prng_init - initialize PRNG from a key -+ */ -+void -+prng_init(prng, key, keylen) -+struct prng *prng; -+const unsigned char *key; -+size_t keylen; -+{ -+ unsigned char k[256]; -+ int i, j; -+ unsigned const char *p; -+ unsigned const char *keyend = key + keylen; -+ unsigned char t; -+ -+ for (i = 0; i <= 255; i++) -+ prng->sbox[i] = i; -+ p = key; -+ for (i = 0; i <= 255; i++) { -+ k[i] = *p++; -+ if (p >= keyend) -+ p = key; -+ } -+ j = 0; -+ for (i = 0; i <= 255; i++) { -+ j = (j + prng->sbox[i] + k[i]) & 0xff; -+ t = prng->sbox[i]; -+ prng->sbox[i] = prng->sbox[j]; -+ prng->sbox[j] = t; -+ k[i] = 0; /* clear out key memory */ -+ } -+ prng->i = 0; -+ prng->j = 0; -+ prng->count = 0; -+} -+ -+/* -+ - prng_bytes - get some pseudorandom bytes from PRNG -+ */ -+void -+prng_bytes(prng, dst, dstlen) -+struct prng *prng; -+unsigned char *dst; -+size_t dstlen; -+{ -+ int i, j, t; -+ unsigned char *p = dst; -+ size_t remain = dstlen; -+# define MAX 4000000000ul -+ -+ while (remain > 0) { -+ i = (prng->i + 1) & 0xff; -+ prng->i = i; -+ j = (prng->j + prng->sbox[i]) & 0xff; -+ prng->j = j; -+ t = prng->sbox[i]; -+ prng->sbox[i] = prng->sbox[j]; -+ prng->sbox[j] = t; -+ t = (t + prng->sbox[i]) & 0xff; -+ *p++ = prng->sbox[t]; -+ remain--; -+ } -+ if (prng->count < MAX - dstlen) -+ prng->count += dstlen; -+ else -+ prng->count = MAX; -+} -+ -+/* -+ - prnt_count - how many bytes have been extracted from PRNG so far? -+ */ -+unsigned long -+prng_count(prng) -+struct prng *prng; -+{ -+ return prng->count; -+} -+ -+/* -+ - prng_final - clear out PRNG to ensure nothing left in memory -+ */ -+void -+prng_final(prng) -+struct prng *prng; -+{ -+ int i; -+ -+ for (i = 0; i <= 255; i++) -+ prng->sbox[i] = 0; -+ prng->i = 0; -+ prng->j = 0; -+ prng->count = 0; /* just for good measure */ -+} -+ -+ -+ -+#ifdef PRNG_MAIN -+ -+#include -+ -+void regress(); -+ -+int -+main(argc, argv) -+int argc; -+char *argv[]; -+{ -+ struct prng pr; -+ unsigned char buf[100]; -+ unsigned char *p; -+ size_t n; -+ -+ if (argc < 2) { -+ fprintf(stderr, "Usage: %s {key|-r}\n", argv[0]); -+ exit(2); -+ } -+ -+ if (strcmp(argv[1], "-r") == 0) { -+ regress(); -+ fprintf(stderr, "regress() returned?!?\n"); -+ exit(1); -+ } -+ -+ prng_init(&pr, argv[1], strlen(argv[1])); -+ prng_bytes(&pr, buf, 32); -+ printf("0x"); -+ for (p = buf, n = 32; n > 0; p++, n--) -+ printf("%02x", *p); -+ printf("\n%lu bytes\n", prng_count(&pr)); -+ prng_final(&pr); -+ exit(0); -+} -+ -+void -+regress() -+{ -+ struct prng pr; -+ unsigned char buf[100]; -+ unsigned char *p; -+ size_t n; -+ /* somewhat non-random sample key */ -+ unsigned char key[] = "here we go gathering nuts in May"; -+ /* first thirty bytes of output from that key */ -+ unsigned char good[] = "\x3f\x02\x8e\x4a\x2a\xea\x23\x18\x92\x7c" -+ "\x09\x52\x83\x61\xaa\x26\xce\xbb\x9d\x71" -+ "\x71\xe5\x10\x22\xaf\x60\x54\x8d\x5b\x28"; -+ int nzero, none; -+ int show = 0; -+ -+ prng_init(&pr, key, strlen(key)); -+ prng_bytes(&pr, buf, sizeof(buf)); -+ for (p = buf, n = sizeof(buf); n > 0; p++, n--) { -+ if (*p == 0) -+ nzero++; -+ if (*p == 255) -+ none++; -+ } -+ if (nzero > 3 || none > 3) { -+ fprintf(stderr, "suspiciously non-random output!\n"); -+ show = 1; -+ } -+ if (memcmp(buf, good, strlen(good)) != 0) { -+ fprintf(stderr, "incorrect output!\n"); -+ show = 1; -+ } -+ if (show) { -+ fprintf(stderr, "0x"); -+ for (p = buf, n = sizeof(buf); n > 0; p++, n--) -+ fprintf(stderr, "%02x", *p); -+ fprintf(stderr, "\n"); -+ exit(1); -+ } -+ if (prng_count(&pr) != sizeof(buf)) { -+ fprintf(stderr, "got %u bytes, but count is %lu\n", -+ sizeof(buf), prng_count(&pr)); -+ exit(1); -+ } -+ prng_final(&pr); -+ exit(0); -+} -+ -+#endif /* PRNG_MAIN */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/rangetoa.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,60 @@ -+/* -+ * convert binary form of address range to ASCII -+ * Copyright (C) 1998, 1999 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - rangetoa - convert address range to ASCII -+ */ -+size_t /* space needed for full conversion */ -+rangetoa(addrs, format, dst, dstlen) -+struct in_addr addrs[2]; -+int format; /* character */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ size_t len; -+ size_t rest; -+ int n; -+ char *p; -+ -+ switch (format) { -+ case 0: -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ len = addrtoa(addrs[0], 0, dst, dstlen); -+ if (len < dstlen) -+ for (p = dst + len - 1, n = 3; len < dstlen && n > 0; -+ p++, len++, n--) -+ *p = '.'; -+ else -+ p = NULL; -+ if (len < dstlen) -+ rest = dstlen - len; -+ else { -+ if (dstlen > 0) -+ *(dst + dstlen - 1) = '\0'; -+ rest = 0; -+ } -+ -+ len += addrtoa(addrs[1], 0, p, rest); -+ -+ return len; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/satot.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,133 @@ -+/* -+ * convert from binary form of SA ID to text -+ * Copyright (C) 2000, 2001 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+static struct typename { -+ char type; -+ char *name; -+} typenames[] = { -+ { SA_AH, "ah" }, -+ { SA_ESP, "esp" }, -+ { SA_IPIP, "tun" }, -+ { SA_COMP, "comp" }, -+ { SA_INT, "int" }, -+ { 0, NULL } -+}; -+ -+/* -+ - satot - convert SA to text "ah507@1.2.3.4" -+ */ -+size_t /* space needed for full conversion */ -+satot(sa, format, dst, dstlen) -+const ip_said *sa; -+int format; /* character */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ size_t len = 0; /* 0 means "not recognized yet" */ -+ int base; -+ int showversion; /* use delimiter to show IP version? */ -+ struct typename *tn; -+ char *p; -+ char *pre; -+ char buf[10+1+ULTOT_BUF+ADDRTOT_BUF]; -+ char unk[10]; -+ -+ switch (format) { -+ case 0: -+ base = 16; -+ showversion = 1; -+ break; -+ case 'f': -+ base = 17; -+ showversion = 1; -+ break; -+ case 'x': -+ base = 'x'; -+ showversion = 0; -+ break; -+ case 'd': -+ base = 10; -+ showversion = 0; -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ memset(buf, 0, sizeof(buf)); -+ -+ pre = NULL; -+ for (tn = typenames; tn->name != NULL; tn++) -+ if (sa->proto == tn->type) { -+ pre = tn->name; -+ break; /* NOTE BREAK OUT */ -+ } -+ if (pre == NULL) { /* unknown protocol */ -+ strcpy(unk, "unk"); -+ (void) ultot((unsigned char)sa->proto, 10, unk+strlen(unk), -+ sizeof(unk)-strlen(unk)); -+ pre = unk; -+ } -+ -+ if (strcmp(pre, PASSTHROUGHTYPE) == 0 && -+ sa->spi == PASSTHROUGHSPI && -+ isunspecaddr(&sa->dst)) { -+ strcpy(buf, (addrtypeof(&sa->dst) == AF_INET) ? -+ PASSTHROUGH4NAME : -+ PASSTHROUGH6NAME); -+ len = strlen(buf); -+ } -+ -+ if (sa->proto == SA_INT) { -+ switch (ntohl(sa->spi)) { -+ case SPI_PASS: p = "%pass"; break; -+ case SPI_DROP: p = "%drop"; break; -+ case SPI_REJECT: p = "%reject"; break; -+ case SPI_HOLD: p = "%hold"; break; -+ case SPI_TRAP: p = "%trap"; break; -+ case SPI_TRAPSUBNET: p = "%trapsubnet"; break; -+ default: p = NULL; break; -+ } -+ if (p != NULL) { -+ strcpy(buf, p); -+ len = strlen(buf); -+ } -+ } -+ -+ if (len == 0) { /* general case needed */ -+ strcpy(buf, pre); -+ len = strlen(buf); -+ if (showversion) { -+ *(buf+len) = (addrtypeof(&sa->dst) == AF_INET) ? '.' : -+ ':'; -+ len++; -+ *(buf+len) = '\0'; -+ } -+ len += ultot(ntohl(sa->spi), base, buf+len, sizeof(buf)-len); -+ *(buf+len-1) = '@'; -+ len += addrtot(&sa->dst, 0, buf+len, sizeof(buf)-len); -+ *(buf+len) = '\0'; -+ } -+ -+ if (dst != NULL) { -+ if (len > dstlen) -+ *(buf+dstlen-1) = '\0'; -+ strcpy(dst, buf); -+ } -+ return len; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/subnetof.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,59 @@ -+/* -+ * minor network-address manipulation utilities -+ * Copyright (C) 1998, 1999 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - subnetof - given address and mask, return subnet part -+ */ -+struct in_addr -+subnetof(addr, mask) -+struct in_addr addr; -+struct in_addr mask; -+{ -+ struct in_addr result; -+ -+ result.s_addr = addr.s_addr & mask.s_addr; -+ return result; -+} -+ -+/* -+ - hostof - given address and mask, return host part -+ */ -+struct in_addr -+hostof(addr, mask) -+struct in_addr addr; -+struct in_addr mask; -+{ -+ struct in_addr result; -+ -+ result.s_addr = addr.s_addr & ~mask.s_addr; -+ return result; -+} -+ -+/* -+ - broadcastof - given (network) address and mask, return broadcast address -+ */ -+struct in_addr -+broadcastof(addr, mask) -+struct in_addr addr; -+struct in_addr mask; -+{ -+ struct in_addr result; -+ -+ result.s_addr = addr.s_addr | ~mask.s_addr; -+ return result; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/subnettoa.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,61 @@ -+/* -+ * convert binary form of subnet description to ASCII -+ * Copyright (C) 1998, 1999 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - subnettoa - convert address and mask to ASCII "addr/mask" -+ * Output expresses the mask as a bit count if possible, else dotted decimal. -+ */ -+size_t /* space needed for full conversion */ -+subnettoa(addr, mask, format, dst, dstlen) -+struct in_addr addr; -+struct in_addr mask; -+int format; /* character */ -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ size_t len; -+ size_t rest; -+ int n; -+ char *p; -+ -+ switch (format) { -+ case 0: -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ len = addrtoa(addr, 0, dst, dstlen); -+ if (len < dstlen) { -+ dst[len - 1] = '/'; -+ p = dst + len; -+ rest = dstlen - len; -+ } else { -+ p = NULL; -+ rest = 0; -+ } -+ -+ n = masktobits(mask); -+ if (n >= 0) -+ len += ultoa((unsigned long)n, 10, p, rest); -+ else -+ len += addrtoa(mask, 0, p, rest); -+ -+ return len; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/ultoa.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,66 @@ -+/* -+ * convert unsigned long to ASCII -+ * Copyright (C) 1998, 1999 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - ultoa - convert unsigned long to decimal ASCII -+ */ -+size_t /* length required for full conversion */ -+ultoa(n, base, dst, dstlen) -+unsigned long n; -+int base; -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ char buf[3*sizeof(unsigned long) + 1]; -+ char *bufend = buf + sizeof(buf); -+ size_t len; -+ char *p; -+ static char hex[] = "0123456789abcdef"; -+ -+ p = bufend; -+ *--p = '\0'; -+ if (base == 10) { -+ do { -+ *--p = n%10 + '0'; -+ n /= 10; -+ } while (n != 0); -+ } else if (base == 16) { -+ do { -+ *--p = hex[n&0xf]; -+ n >>= 4; -+ } while (n != 0); -+ *--p = 'x'; -+ *--p = '0'; -+ } else if (base == 8) { -+ do { -+ *--p = (n&07) + '0'; -+ n >>= 3; -+ } while (n != 0); -+ *--p = '0'; -+ } else -+ *--p = '?'; -+ -+ len = bufend - p; -+ -+ if (dstlen > 0) { -+ if (len > dstlen) -+ *(p + dstlen - 1) = '\0'; -+ strcpy(dst, p); -+ } -+ return len; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/libfreeswan/ultot.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,82 @@ -+/* -+ * convert unsigned long to text -+ * Copyright (C) 2000 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+#include "openswan.h" -+ -+/* -+ - ultot - convert unsigned long to text -+ */ -+size_t /* length required for full conversion */ -+ultot(n, base, dst, dstlen) -+unsigned long n; -+int base; -+char *dst; /* need not be valid if dstlen is 0 */ -+size_t dstlen; -+{ -+ char buf[3*sizeof(unsigned long) + 1]; -+ char *bufend = buf + sizeof(buf); -+ size_t len; -+ char *p; -+ static char hex[] = "0123456789abcdef"; -+# define HEX32 (32/4) -+ -+ p = bufend; -+ *--p = '\0'; -+ switch (base) { -+ case 10: -+ case 'd': -+ do { -+ *--p = n%10 + '0'; -+ n /= 10; -+ } while (n != 0); -+ break; -+ case 16: -+ case 17: -+ case 'x': -+ do { -+ *--p = hex[n&0xf]; -+ n >>= 4; -+ } while (n != 0); -+ if (base == 17) -+ while (bufend - p < HEX32 + 1) -+ *--p = '0'; -+ if (base == 'x') { -+ *--p = 'x'; -+ *--p = '0'; -+ } -+ break; -+ case 8: -+ case 'o': -+ do { -+ *--p = (n&07) + '0'; -+ n >>= 3; -+ } while (n != 0); -+ if (base == 'o') -+ *--p = '0'; -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ len = bufend - p; -+ if (dstlen > 0) { -+ if (len > dstlen) -+ *(p + dstlen - 1) = '\0'; -+ strcpy(dst, p); -+ } -+ return len; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/Makefile Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,118 @@ -+# (kernel) Makefile for IPCOMP zlib deflate code -+# Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+# Copyright (C) 2000 Svenning Soerensen -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by the -+# Free Software Foundation; either version 2 of the License, or (at your -+# option) any later version. See . -+# -+# This program is distributed in 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. -+# -+# RCSID $Id$ -+# -+ -+ -+ -+include ../Makefile.inc -+ -+ -+ -+ifndef TOPDIR -+TOPDIR := /usr/src/linux -+endif -+ -+ -+L_TARGET := zlib.a -+ -+obj-y := -+ -+include Makefile.objs -+ -+EXTRA_CFLAGS += $(KLIPSCOMPILE) -+ -+EXTRA_CFLAGS += -Wall -+#EXTRA_CFLAGS += -Wconversion -+#EXTRA_CFLAGS += -Wmissing-prototypes -+EXTRA_CFLAGS += -Wpointer-arith -+#EXTRA_CFLAGS += -Wcast-qual -+#EXTRA_CFLAGS += -Wmissing-declarations -+EXTRA_CFLAGS += -Wstrict-prototypes -+#EXTRA_CFLAGS += -pedantic -+#EXTRA_CFLAGS += -W -+#EXTRA_CFLAGS += -Wwrite-strings -+EXTRA_CFLAGS += -Wbad-function-cast -+EXTRA_CFLAGS += -DIPCOMP_PREFIX -+ -+.S.o: -+ $(CC) -D__ASSEMBLY__ -DNO_UNDERLINE -traditional -c $< -o $*.o -+ -+asm-obj-$(CONFIG_M586) += match586.o -+asm-obj-$(CONFIG_M586TSC) += match586.o -+asm-obj-$(CONFIG_M586MMX) += match586.o -+asm-obj-$(CONFIG_M686) += match686.o -+asm-obj-$(CONFIG_MPENTIUMIII) += match686.o -+asm-obj-$(CONFIG_MPENTIUM4) += match686.o -+asm-obj-$(CONFIG_MK6) += match586.o -+asm-obj-$(CONFIG_MK7) += match686.o -+asm-obj-$(CONFIG_MCRUSOE) += match586.o -+asm-obj-$(CONFIG_MWINCHIPC6) += match586.o -+asm-obj-$(CONFIG_MWINCHIP2) += match686.o -+asm-obj-$(CONFIG_MWINCHIP3D) += match686.o -+ -+obj-y += $(asm-obj-y) -+ifneq ($(strip $(asm-obj-y)),) -+ EXTRA_CFLAGS += -DASMV -+endif -+ -+active-objs := $(sort $(obj-y) $(obj-m)) -+L_OBJS := $(obj-y) -+M_OBJS := $(obj-m) -+MIX_OBJS := $(filter $(export-objs), $(active-objs)) -+ -+include $(TOPDIR)/Rules.make -+ -+$(obj-y) : $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h -+ -+ -+clean: -+ -rm -f *.o *.a -+ -+checkprograms: -+programs: $(L_TARGET) -+ -+# -+# $Log$ -+# Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+# Turn off EOLN_NATIVE flag -+# -+# (Logical change 1.5010) -+# -+# Revision 1.9 2002/04/24 07:55:32 mcr -+# #include patches and Makefiles for post-reorg compilation. -+# -+# Revision 1.8 2002/04/24 07:36:44 mcr -+# Moved from ./zlib/Makefile,v -+# -+# Revision 1.7 2002/03/27 23:34:35 mcr -+# added programs: target -+# -+# Revision 1.6 2001/12/05 20:19:08 henry -+# use new compile-control variable -+# -+# Revision 1.5 2001/11/27 16:38:08 mcr -+# added new "checkprograms" target to deal with programs that -+# are required for "make check", but that may not be ready to -+# build for every user due to external dependancies. -+# -+# Revision 1.4 2001/10/24 14:46:24 henry -+# Makefile.inc -+# -+# Revision 1.3 2001/04/21 23:05:24 rgb -+# Update asm directives for 2.4 style makefiles. -+# -+# Revision 1.2 2001/01/29 22:22:00 rgb -+# Convert to 2.4 new style with back compat. -+# -+# Revision 1.1.1.1 2000/09/29 18:51:33 rgb -+# zlib_beginnings -+# -+# ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/Makefile.objs Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,27 @@ -+obj-$(CONFIG_IPSEC_IPCOMP) += adler32.o -+obj-$(CONFIG_IPSEC_IPCOMP) += deflate.o -+obj-$(CONFIG_IPSEC_IPCOMP) += infblock.o -+obj-$(CONFIG_IPSEC_IPCOMP) += infcodes.o -+obj-$(CONFIG_IPSEC_IPCOMP) += inffast.o -+obj-$(CONFIG_IPSEC_IPCOMP) += inflate.o -+obj-$(CONFIG_IPSEC_IPCOMP) += inftrees.o -+obj-$(CONFIG_IPSEC_IPCOMP) += infutil.o -+obj-$(CONFIG_IPSEC_IPCOMP) += trees.o -+obj-$(CONFIG_IPSEC_IPCOMP) += zutil.o -+ -+asm-obj-$(CONFIG_M586) += ${LIBZLIBSRCDIR}/match586.o -+asm-obj-$(CONFIG_M586TSC) += ${LIBZLIBSRCDIR}/match586.o -+asm-obj-$(CONFIG_M586MMX) += ${LIBZLIBSRCDIR}/match586.o -+asm-obj-$(CONFIG_M686) += ${LIBZLIBSRCDIR}/match686.o -+asm-obj-$(CONFIG_MPENTIUMIII) += ${LIBZLIBSRCDIR}/match686.o -+asm-obj-$(CONFIG_MPENTIUM4) += ${LIBZLIBSRCDIR}/match686.o -+asm-obj-$(CONFIG_MK6) += ${LIBZLIBSRCDIR}/match586.o -+asm-obj-$(CONFIG_MK7) += ${LIBZLIBSRCDIR}/match686.o -+asm-obj-$(CONFIG_MCRUSOE) += ${LIBZLIBSRCDIR}/match586.o -+asm-obj-$(CONFIG_MWINCHIPC6) += ${LIBZLIBSRCDIR}/match586.o -+asm-obj-$(CONFIG_MWINCHIP2) += ${LIBZLIBSRCDIR}/match686.o -+asm-obj-$(CONFIG_MWINCHIP3D) += ${LIBZLIBSRCDIR}/match686.o -+ -+EXTRA_CFLAGS += -DIPCOMP_PREFIX -+ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/README Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,147 @@ -+zlib 1.1.4 is a general purpose data compression library. All the code -+is thread safe. The data format used by the zlib library -+is described by RFCs (Request for Comments) 1950 to 1952 in the files -+http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate -+format) and rfc1952.txt (gzip format). These documents are also available in -+other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html -+ -+All functions of the compression library are documented in the file zlib.h -+(volunteer to write man pages welcome, contact jloup@gzip.org). A usage -+example of the library is given in the file example.c which also tests that -+the library is working correctly. Another example is given in the file -+minigzip.c. The compression library itself is composed of all source files -+except example.c and minigzip.c. -+ -+To compile all files and run the test program, follow the instructions -+given at the top of Makefile. In short "make test; make install" -+should work for most machines. For Unix: "./configure; make test; make install" -+For MSDOS, use one of the special makefiles such as Makefile.msc. -+For VMS, use Make_vms.com or descrip.mms. -+ -+Questions about zlib should be sent to , or to -+Gilles Vollant for the Windows DLL version. -+The zlib home page is http://www.zlib.org or http://www.gzip.org/zlib/ -+Before reporting a problem, please check this site to verify that -+you have the latest version of zlib; otherwise get the latest version and -+check whether the problem still exists or not. -+ -+PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html -+before asking for help. -+ -+Mark Nelson wrote an article about zlib for the Jan. 1997 -+issue of Dr. Dobb's Journal; a copy of the article is available in -+http://dogma.net/markn/articles/zlibtool/zlibtool.htm -+ -+The changes made in version 1.1.4 are documented in the file ChangeLog. -+The only changes made since 1.1.3 are bug corrections: -+ -+- ZFREE was repeated on same allocation on some error conditions. -+ This creates a security problem described in -+ http://www.zlib.org/advisory-2002-03-11.txt -+- Returned incorrect error (Z_MEM_ERROR) on some invalid data -+- Avoid accesses before window for invalid distances with inflate window -+ less than 32K. -+- force windowBits > 8 to avoid a bug in the encoder for a window size -+ of 256 bytes. (A complete fix will be available in 1.1.5). -+ -+The beta version 1.1.5beta includes many more changes. A new official -+version 1.1.5 will be released as soon as extensive testing has been -+completed on it. -+ -+ -+Unsupported third party contributions are provided in directory "contrib". -+ -+A Java implementation of zlib is available in the Java Development Kit -+http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html -+See the zlib home page http://www.zlib.org for details. -+ -+A Perl interface to zlib written by Paul Marquess -+is in the CPAN (Comprehensive Perl Archive Network) sites -+http://www.cpan.org/modules/by-module/Compress/ -+ -+A Python interface to zlib written by A.M. Kuchling -+is available in Python 1.5 and later versions, see -+http://www.python.org/doc/lib/module-zlib.html -+ -+A zlib binding for TCL written by Andreas Kupries -+is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html -+ -+An experimental package to read and write files in .zip format, -+written on top of zlib by Gilles Vollant , is -+available at http://www.winimage.com/zLibDll/unzip.html -+and also in the contrib/minizip directory of zlib. -+ -+ -+Notes for some targets: -+ -+- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc -+ and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL -+ The zlib DLL support was initially done by Alessandro Iacopetti and is -+ now maintained by Gilles Vollant . Check the zlib DLL -+ home page at http://www.winimage.com/zLibDll -+ -+ From Visual Basic, you can call the DLL functions which do not take -+ a structure as argument: compress, uncompress and all gz* functions. -+ See contrib/visual-basic.txt for more information, or get -+ http://www.tcfb.com/dowseware/cmp-z-it.zip -+ -+- For 64-bit Irix, deflate.c must be compiled without any optimization. -+ With -O, one libpng test fails. The test works in 32 bit mode (with -+ the -n32 compiler flag). The compiler bug has been reported to SGI. -+ -+- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 -+ it works when compiled with cc. -+ -+- on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 -+ is necessary to get gzprintf working correctly. This is done by configure. -+ -+- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works -+ with other compilers. Use "make test" to check your compiler. -+ -+- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. -+ -+- For Turbo C the small model is supported only with reduced performance to -+ avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 -+ -+- For PalmOs, see http://www.cs.uit.no/~perm/PASTA/pilot/software.html -+ Per Harald Myrvang -+ -+ -+Acknowledgments: -+ -+ The deflate format used by zlib was defined by Phil Katz. The deflate -+ and zlib specifications were written by L. Peter Deutsch. Thanks to all the -+ people who reported problems and suggested various improvements in zlib; -+ they are too numerous to cite here. -+ -+Copyright notice: -+ -+ (C) 1995-2002 Jean-loup Gailly and Mark Adler -+ -+ This software is provided 'as-is', without any express or implied -+ warranty. In no event will the authors be held liable for any damages -+ arising from the use of this software. -+ -+ Permission is granted to anyone to use this software for any purpose, -+ including commercial applications, and to alter it and redistribute it -+ freely, subject to the following restrictions: -+ -+ 1. The origin of this software must not be misrepresented; you must not -+ claim that you wrote the original software. If you use this software -+ in a product, an acknowledgment in the product documentation would be -+ appreciated but is not required. -+ 2. Altered source versions must be plainly marked as such, and must not be -+ misrepresented as being the original software. -+ 3. This notice may not be removed or altered from any source distribution. -+ -+ Jean-loup Gailly Mark Adler -+ jloup@gzip.org madler@alumni.caltech.edu -+ -+If you use the zlib library in a product, we would appreciate *not* -+receiving lengthy legal documents to sign. The sources are provided -+for free but without warranty of any kind. The library has been -+entirely written by Jean-loup Gailly and Mark Adler; it does not -+include third-party code. -+ -+If you redistribute modified sources, we would appreciate that you include -+in the file ChangeLog history information documenting your changes. ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/README.freeswan Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,13 @@ -+The only changes made to these files for use in FreeS/WAN are: -+ -+ - In zconf.h, macros are defined to prefix global symbols with "ipcomp_" -+ (or "_ipcomp"), when compiled with -DIPCOMP_PREFIX. -+ - The copyright strings are defined local (static) -+ -+ The above changes are made to avoid name collisions with ppp_deflate -+ and ext2compr. -+ -+ - Files not needed for FreeS/WAN have been removed -+ -+ See the "README" file for information about where to obtain the complete -+ zlib package. ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/adler32.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,49 @@ -+/* adler32.c -- compute the Adler-32 checksum of a data stream -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* @(#) $Id$ */ -+ -+#include -+#include "zconf.h" -+ -+#define BASE 65521L /* largest prime smaller than 65536 */ -+#define NMAX 5552 -+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ -+ -+#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} -+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); -+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); -+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); -+#define DO16(buf) DO8(buf,0); DO8(buf,8); -+ -+/* ========================================================================= */ -+uLong ZEXPORT adler32(adler, buf, len) -+ uLong adler; -+ const Bytef *buf; -+ uInt len; -+{ -+ unsigned long s1 = adler & 0xffff; -+ unsigned long s2 = (adler >> 16) & 0xffff; -+ int k; -+ -+ if (buf == Z_NULL) return 1L; -+ -+ while (len > 0) { -+ k = len < NMAX ? len : NMAX; -+ len -= k; -+ while (k >= 16) { -+ DO16(buf); -+ buf += 16; -+ k -= 16; -+ } -+ if (k != 0) do { -+ s1 += *buf++; -+ s2 += s1; -+ } while (--k); -+ s1 %= BASE; -+ s2 %= BASE; -+ } -+ return (s2 << 16) | s1; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/deflate.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1351 @@ -+/* deflate.c -- compress data using the deflation algorithm -+ * Copyright (C) 1995-2002 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* -+ * ALGORITHM -+ * -+ * The "deflation" process depends on being able to identify portions -+ * of the input text which are identical to earlier input (within a -+ * sliding window trailing behind the input currently being processed). -+ * -+ * The most straightforward technique turns out to be the fastest for -+ * most input files: try all possible matches and select the longest. -+ * The key feature of this algorithm is that insertions into the string -+ * dictionary are very simple and thus fast, and deletions are avoided -+ * completely. Insertions are performed at each input character, whereas -+ * string matches are performed only when the previous match ends. So it -+ * is preferable to spend more time in matches to allow very fast string -+ * insertions and avoid deletions. The matching algorithm for small -+ * strings is inspired from that of Rabin & Karp. A brute force approach -+ * is used to find longer strings when a small match has been found. -+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze -+ * (by Leonid Broukhis). -+ * A previous version of this file used a more sophisticated algorithm -+ * (by Fiala and Greene) which is guaranteed to run in linear amortized -+ * time, but has a larger average cost, uses more memory and is patented. -+ * However the F&G algorithm may be faster for some highly redundant -+ * files if the parameter max_chain_length (described below) is too large. -+ * -+ * ACKNOWLEDGEMENTS -+ * -+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and -+ * I found it in 'freeze' written by Leonid Broukhis. -+ * Thanks to many people for bug reports and testing. -+ * -+ * REFERENCES -+ * -+ * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". -+ * Available in ftp://ds.internic.net/rfc/rfc1951.txt -+ * -+ * A description of the Rabin and Karp algorithm is given in the book -+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. -+ * -+ * Fiala,E.R., and Greene,D.H. -+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 -+ * -+ */ -+ -+/* @(#) $Id$ */ -+ -+#include "deflate.h" -+ -+local const char deflate_copyright[] = -+ " deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly "; -+/* -+ If you use the zlib library in a product, an acknowledgment is welcome -+ in the documentation of your product. If for some reason you cannot -+ include such an acknowledgment, I would appreciate that you keep this -+ copyright string in the executable of your product. -+ */ -+ -+/* =========================================================================== -+ * Function prototypes. -+ */ -+typedef enum { -+ need_more, /* block not completed, need more input or more output */ -+ block_done, /* block flush performed */ -+ finish_started, /* finish started, need only more output at next deflate */ -+ finish_done /* finish done, accept no more input or output */ -+} block_state; -+ -+typedef block_state (*compress_func) OF((deflate_state *s, int flush)); -+/* Compression function. Returns the block state after the call. */ -+ -+local void fill_window OF((deflate_state *s)); -+local block_state deflate_stored OF((deflate_state *s, int flush)); -+local block_state deflate_fast OF((deflate_state *s, int flush)); -+local block_state deflate_slow OF((deflate_state *s, int flush)); -+local void lm_init OF((deflate_state *s)); -+local void putShortMSB OF((deflate_state *s, uInt b)); -+local void flush_pending OF((z_streamp strm)); -+local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); -+#ifdef ASMV -+ void match_init OF((void)); /* asm code initialization */ -+ uInt longest_match OF((deflate_state *s, IPos cur_match)); -+#else -+local uInt longest_match OF((deflate_state *s, IPos cur_match)); -+#endif -+ -+#ifdef DEBUG -+local void check_match OF((deflate_state *s, IPos start, IPos match, -+ int length)); -+#endif -+ -+/* =========================================================================== -+ * Local data -+ */ -+ -+#define NIL 0 -+/* Tail of hash chains */ -+ -+#ifndef TOO_FAR -+# define TOO_FAR 4096 -+#endif -+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ -+ -+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -+/* Minimum amount of lookahead, except at the end of the input file. -+ * See deflate.c for comments about the MIN_MATCH+1. -+ */ -+ -+/* Values for max_lazy_match, good_match and max_chain_length, depending on -+ * the desired pack level (0..9). The values given below have been tuned to -+ * exclude worst case performance for pathological files. Better values may be -+ * found for specific files. -+ */ -+typedef struct config_s { -+ ush good_length; /* reduce lazy search above this match length */ -+ ush max_lazy; /* do not perform lazy search above this match length */ -+ ush nice_length; /* quit search above this match length */ -+ ush max_chain; -+ compress_func func; -+} config; -+ -+local const config configuration_table[10] = { -+/* good lazy nice chain */ -+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -+/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ -+/* 2 */ {4, 5, 16, 8, deflate_fast}, -+/* 3 */ {4, 6, 32, 32, deflate_fast}, -+ -+/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ -+/* 5 */ {8, 16, 32, 32, deflate_slow}, -+/* 6 */ {8, 16, 128, 128, deflate_slow}, -+/* 7 */ {8, 32, 128, 256, deflate_slow}, -+/* 8 */ {32, 128, 258, 1024, deflate_slow}, -+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ -+ -+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 -+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different -+ * meaning. -+ */ -+ -+#define EQUAL 0 -+/* result of memcmp for equal strings */ -+ -+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ -+ -+/* =========================================================================== -+ * Update a hash value with the given input byte -+ * IN assertion: all calls to to UPDATE_HASH are made with consecutive -+ * input characters, so that a running hash key can be computed from the -+ * previous key instead of complete recalculation each time. -+ */ -+#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) -+ -+ -+/* =========================================================================== -+ * Insert string str in the dictionary and set match_head to the previous head -+ * of the hash chain (the most recent string with same hash key). Return -+ * the previous length of the hash chain. -+ * If this file is compiled with -DFASTEST, the compression level is forced -+ * to 1, and no hash chains are maintained. -+ * IN assertion: all calls to to INSERT_STRING are made with consecutive -+ * input characters and the first MIN_MATCH bytes of str are valid -+ * (except for the last MIN_MATCH-1 bytes of the input file). -+ */ -+#ifdef FASTEST -+#define INSERT_STRING(s, str, match_head) \ -+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ -+ match_head = s->head[s->ins_h], \ -+ s->head[s->ins_h] = (Pos)(str)) -+#else -+#define INSERT_STRING(s, str, match_head) \ -+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ -+ s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ -+ s->head[s->ins_h] = (Pos)(str)) -+#endif -+ -+/* =========================================================================== -+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems). -+ * prev[] will be initialized on the fly. -+ */ -+#define CLEAR_HASH(s) \ -+ s->head[s->hash_size-1] = NIL; \ -+ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); -+ -+/* ========================================================================= */ -+int ZEXPORT deflateInit_(strm, level, version, stream_size) -+ z_streamp strm; -+ int level; -+ const char *version; -+ int stream_size; -+{ -+ return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, -+ Z_DEFAULT_STRATEGY, version, stream_size); -+ /* To do: ignore strm->next_in if we use it as window */ -+} -+ -+/* ========================================================================= */ -+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, -+ version, stream_size) -+ z_streamp strm; -+ int level; -+ int method; -+ int windowBits; -+ int memLevel; -+ int strategy; -+ const char *version; -+ int stream_size; -+{ -+ deflate_state *s; -+ int noheader = 0; -+ static const char* my_version = ZLIB_VERSION; -+ -+ ushf *overlay; -+ /* We overlay pending_buf and d_buf+l_buf. This works since the average -+ * output size for (length,distance) codes is <= 24 bits. -+ */ -+ -+ if (version == Z_NULL || version[0] != my_version[0] || -+ stream_size != sizeof(z_stream)) { -+ return Z_VERSION_ERROR; -+ } -+ if (strm == Z_NULL) return Z_STREAM_ERROR; -+ -+ strm->msg = Z_NULL; -+ if (strm->zalloc == Z_NULL) { -+ return Z_STREAM_ERROR; -+/* strm->zalloc = zcalloc; -+ strm->opaque = (voidpf)0;*/ -+ } -+ if (strm->zfree == Z_NULL) return Z_STREAM_ERROR; /* strm->zfree = zcfree; */ -+ -+ if (level == Z_DEFAULT_COMPRESSION) level = 6; -+#ifdef FASTEST -+ level = 1; -+#endif -+ -+ if (windowBits < 0) { /* undocumented feature: suppress zlib header */ -+ noheader = 1; -+ windowBits = -windowBits; -+ } -+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || -+ windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || -+ strategy < 0 || strategy > Z_HUFFMAN_ONLY) { -+ return Z_STREAM_ERROR; -+ } -+ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); -+ if (s == Z_NULL) return Z_MEM_ERROR; -+ strm->state = (struct internal_state FAR *)s; -+ s->strm = strm; -+ -+ s->noheader = noheader; -+ s->w_bits = windowBits; -+ s->w_size = 1 << s->w_bits; -+ s->w_mask = s->w_size - 1; -+ -+ s->hash_bits = memLevel + 7; -+ s->hash_size = 1 << s->hash_bits; -+ s->hash_mask = s->hash_size - 1; -+ s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); -+ -+ s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); -+ s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); -+ s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); -+ -+ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ -+ -+ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); -+ s->pending_buf = (uchf *) overlay; -+ s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); -+ -+ if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || -+ s->pending_buf == Z_NULL) { -+ strm->msg = ERR_MSG(Z_MEM_ERROR); -+ deflateEnd (strm); -+ return Z_MEM_ERROR; -+ } -+ s->d_buf = overlay + s->lit_bufsize/sizeof(ush); -+ s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; -+ -+ s->level = level; -+ s->strategy = strategy; -+ s->method = (Byte)method; -+ -+ return deflateReset(strm); -+} -+ -+/* ========================================================================= */ -+int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) -+ z_streamp strm; -+ const Bytef *dictionary; -+ uInt dictLength; -+{ -+ deflate_state *s; -+ uInt length = dictLength; -+ uInt n; -+ IPos hash_head = 0; -+ -+ if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || -+ strm->state->status != INIT_STATE) return Z_STREAM_ERROR; -+ -+ s = strm->state; -+ strm->adler = adler32(strm->adler, dictionary, dictLength); -+ -+ if (length < MIN_MATCH) return Z_OK; -+ if (length > MAX_DIST(s)) { -+ length = MAX_DIST(s); -+#ifndef USE_DICT_HEAD -+ dictionary += dictLength - length; /* use the tail of the dictionary */ -+#endif -+ } -+ zmemcpy(s->window, dictionary, length); -+ s->strstart = length; -+ s->block_start = (long)length; -+ -+ /* Insert all strings in the hash table (except for the last two bytes). -+ * s->lookahead stays null, so s->ins_h will be recomputed at the next -+ * call of fill_window. -+ */ -+ s->ins_h = s->window[0]; -+ UPDATE_HASH(s, s->ins_h, s->window[1]); -+ for (n = 0; n <= length - MIN_MATCH; n++) { -+ INSERT_STRING(s, n, hash_head); -+ } -+ if (hash_head) hash_head = 0; /* to make compiler happy */ -+ return Z_OK; -+} -+ -+/* ========================================================================= */ -+int ZEXPORT deflateReset (strm) -+ z_streamp strm; -+{ -+ deflate_state *s; -+ -+ if (strm == Z_NULL || strm->state == Z_NULL || -+ strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; -+ -+ strm->total_in = strm->total_out = 0; -+ strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ -+ strm->data_type = Z_UNKNOWN; -+ -+ s = (deflate_state *)strm->state; -+ s->pending = 0; -+ s->pending_out = s->pending_buf; -+ -+ if (s->noheader < 0) { -+ s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ -+ } -+ s->status = s->noheader ? BUSY_STATE : INIT_STATE; -+ strm->adler = 1; -+ s->last_flush = Z_NO_FLUSH; -+ -+ _tr_init(s); -+ lm_init(s); -+ -+ return Z_OK; -+} -+ -+/* ========================================================================= */ -+int ZEXPORT deflateParams(strm, level, strategy) -+ z_streamp strm; -+ int level; -+ int strategy; -+{ -+ deflate_state *s; -+ compress_func func; -+ int err = Z_OK; -+ -+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; -+ s = strm->state; -+ -+ if (level == Z_DEFAULT_COMPRESSION) { -+ level = 6; -+ } -+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { -+ return Z_STREAM_ERROR; -+ } -+ func = configuration_table[s->level].func; -+ -+ if (func != configuration_table[level].func && strm->total_in != 0) { -+ /* Flush the last buffer: */ -+ err = deflate(strm, Z_PARTIAL_FLUSH); -+ } -+ if (s->level != level) { -+ s->level = level; -+ s->max_lazy_match = configuration_table[level].max_lazy; -+ s->good_match = configuration_table[level].good_length; -+ s->nice_match = configuration_table[level].nice_length; -+ s->max_chain_length = configuration_table[level].max_chain; -+ } -+ s->strategy = strategy; -+ return err; -+} -+ -+/* ========================================================================= -+ * Put a short in the pending buffer. The 16-bit value is put in MSB order. -+ * IN assertion: the stream state is correct and there is enough room in -+ * pending_buf. -+ */ -+local void putShortMSB (s, b) -+ deflate_state *s; -+ uInt b; -+{ -+ put_byte(s, (Byte)(b >> 8)); -+ put_byte(s, (Byte)(b & 0xff)); -+} -+ -+/* ========================================================================= -+ * Flush as much pending output as possible. All deflate() output goes -+ * through this function so some applications may wish to modify it -+ * to avoid allocating a large strm->next_out buffer and copying into it. -+ * (See also read_buf()). -+ */ -+local void flush_pending(strm) -+ z_streamp strm; -+{ -+ unsigned len = strm->state->pending; -+ -+ if (len > strm->avail_out) len = strm->avail_out; -+ if (len == 0) return; -+ -+ zmemcpy(strm->next_out, strm->state->pending_out, len); -+ strm->next_out += len; -+ strm->state->pending_out += len; -+ strm->total_out += len; -+ strm->avail_out -= len; -+ strm->state->pending -= len; -+ if (strm->state->pending == 0) { -+ strm->state->pending_out = strm->state->pending_buf; -+ } -+} -+ -+/* ========================================================================= */ -+int ZEXPORT deflate (strm, flush) -+ z_streamp strm; -+ int flush; -+{ -+ int old_flush; /* value of flush param for previous deflate call */ -+ deflate_state *s; -+ -+ if (strm == Z_NULL || strm->state == Z_NULL || -+ flush > Z_FINISH || flush < 0) { -+ return Z_STREAM_ERROR; -+ } -+ s = strm->state; -+ -+ if (strm->next_out == Z_NULL || -+ (strm->next_in == Z_NULL && strm->avail_in != 0) || -+ (s->status == FINISH_STATE && flush != Z_FINISH)) { -+ ERR_RETURN(strm, Z_STREAM_ERROR); -+ } -+ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); -+ -+ s->strm = strm; /* just in case */ -+ old_flush = s->last_flush; -+ s->last_flush = flush; -+ -+ /* Write the zlib header */ -+ if (s->status == INIT_STATE) { -+ -+ uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; -+ uInt level_flags = (s->level-1) >> 1; -+ -+ if (level_flags > 3) level_flags = 3; -+ header |= (level_flags << 6); -+ if (s->strstart != 0) header |= PRESET_DICT; -+ header += 31 - (header % 31); -+ -+ s->status = BUSY_STATE; -+ putShortMSB(s, header); -+ -+ /* Save the adler32 of the preset dictionary: */ -+ if (s->strstart != 0) { -+ putShortMSB(s, (uInt)(strm->adler >> 16)); -+ putShortMSB(s, (uInt)(strm->adler & 0xffff)); -+ } -+ strm->adler = 1L; -+ } -+ -+ /* Flush as much pending output as possible */ -+ if (s->pending != 0) { -+ flush_pending(strm); -+ if (strm->avail_out == 0) { -+ /* Since avail_out is 0, deflate will be called again with -+ * more output space, but possibly with both pending and -+ * avail_in equal to zero. There won't be anything to do, -+ * but this is not an error situation so make sure we -+ * return OK instead of BUF_ERROR at next call of deflate: -+ */ -+ s->last_flush = -1; -+ return Z_OK; -+ } -+ -+ /* Make sure there is something to do and avoid duplicate consecutive -+ * flushes. For repeated and useless calls with Z_FINISH, we keep -+ * returning Z_STREAM_END instead of Z_BUFF_ERROR. -+ */ -+ } else if (strm->avail_in == 0 && flush <= old_flush && -+ flush != Z_FINISH) { -+ ERR_RETURN(strm, Z_BUF_ERROR); -+ } -+ -+ /* User must not provide more input after the first FINISH: */ -+ if (s->status == FINISH_STATE && strm->avail_in != 0) { -+ ERR_RETURN(strm, Z_BUF_ERROR); -+ } -+ -+ /* Start a new block or continue the current one. -+ */ -+ if (strm->avail_in != 0 || s->lookahead != 0 || -+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { -+ block_state bstate; -+ -+ bstate = (*(configuration_table[s->level].func))(s, flush); -+ -+ if (bstate == finish_started || bstate == finish_done) { -+ s->status = FINISH_STATE; -+ } -+ if (bstate == need_more || bstate == finish_started) { -+ if (strm->avail_out == 0) { -+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ -+ } -+ return Z_OK; -+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call -+ * of deflate should use the same flush parameter to make sure -+ * that the flush is complete. So we don't have to output an -+ * empty block here, this will be done at next call. This also -+ * ensures that for a very small output buffer, we emit at most -+ * one empty block. -+ */ -+ } -+ if (bstate == block_done) { -+ if (flush == Z_PARTIAL_FLUSH) { -+ _tr_align(s); -+ } else { /* FULL_FLUSH or SYNC_FLUSH */ -+ _tr_stored_block(s, (char*)0, 0L, 0); -+ /* For a full flush, this empty block will be recognized -+ * as a special marker by inflate_sync(). -+ */ -+ if (flush == Z_FULL_FLUSH) { -+ CLEAR_HASH(s); /* forget history */ -+ } -+ } -+ flush_pending(strm); -+ if (strm->avail_out == 0) { -+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ -+ return Z_OK; -+ } -+ } -+ } -+ Assert(strm->avail_out > 0, "bug2"); -+ -+ if (flush != Z_FINISH) return Z_OK; -+ if (s->noheader) return Z_STREAM_END; -+ -+ /* Write the zlib trailer (adler32) */ -+ putShortMSB(s, (uInt)(strm->adler >> 16)); -+ putShortMSB(s, (uInt)(strm->adler & 0xffff)); -+ flush_pending(strm); -+ /* If avail_out is zero, the application will call deflate again -+ * to flush the rest. -+ */ -+ s->noheader = -1; /* write the trailer only once! */ -+ return s->pending != 0 ? Z_OK : Z_STREAM_END; -+} -+ -+/* ========================================================================= */ -+int ZEXPORT deflateEnd (strm) -+ z_streamp strm; -+{ -+ int status; -+ -+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; -+ -+ status = strm->state->status; -+ if (status != INIT_STATE && status != BUSY_STATE && -+ status != FINISH_STATE) { -+ return Z_STREAM_ERROR; -+ } -+ -+ /* Deallocate in reverse order of allocations: */ -+ TRY_FREE(strm, strm->state->pending_buf); -+ TRY_FREE(strm, strm->state->head); -+ TRY_FREE(strm, strm->state->prev); -+ TRY_FREE(strm, strm->state->window); -+ -+ ZFREE(strm, strm->state); -+ strm->state = Z_NULL; -+ -+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; -+} -+ -+/* ========================================================================= -+ * Copy the source state to the destination state. -+ * To simplify the source, this is not supported for 16-bit MSDOS (which -+ * doesn't have enough memory anyway to duplicate compression states). -+ */ -+int ZEXPORT deflateCopy (dest, source) -+ z_streamp dest; -+ z_streamp source; -+{ -+#ifdef MAXSEG_64K -+ return Z_STREAM_ERROR; -+#else -+ deflate_state *ds; -+ deflate_state *ss; -+ ushf *overlay; -+ -+ -+ if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { -+ return Z_STREAM_ERROR; -+ } -+ -+ ss = source->state; -+ -+ *dest = *source; -+ -+ ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); -+ if (ds == Z_NULL) return Z_MEM_ERROR; -+ dest->state = (struct internal_state FAR *) ds; -+ *ds = *ss; -+ ds->strm = dest; -+ -+ ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); -+ ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); -+ ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); -+ overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); -+ ds->pending_buf = (uchf *) overlay; -+ -+ if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || -+ ds->pending_buf == Z_NULL) { -+ deflateEnd (dest); -+ return Z_MEM_ERROR; -+ } -+ /* following zmemcpy do not work for 16-bit MSDOS */ -+ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); -+ zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); -+ zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); -+ zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); -+ -+ ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); -+ ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); -+ ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; -+ -+ ds->l_desc.dyn_tree = ds->dyn_ltree; -+ ds->d_desc.dyn_tree = ds->dyn_dtree; -+ ds->bl_desc.dyn_tree = ds->bl_tree; -+ -+ return Z_OK; -+#endif -+} -+ -+/* =========================================================================== -+ * Read a new buffer from the current input stream, update the adler32 -+ * and total number of bytes read. All deflate() input goes through -+ * this function so some applications may wish to modify it to avoid -+ * allocating a large strm->next_in buffer and copying from it. -+ * (See also flush_pending()). -+ */ -+local int read_buf(strm, buf, size) -+ z_streamp strm; -+ Bytef *buf; -+ unsigned size; -+{ -+ unsigned len = strm->avail_in; -+ -+ if (len > size) len = size; -+ if (len == 0) return 0; -+ -+ strm->avail_in -= len; -+ -+ if (!strm->state->noheader) { -+ strm->adler = adler32(strm->adler, strm->next_in, len); -+ } -+ zmemcpy(buf, strm->next_in, len); -+ strm->next_in += len; -+ strm->total_in += len; -+ -+ return (int)len; -+} -+ -+/* =========================================================================== -+ * Initialize the "longest match" routines for a new zlib stream -+ */ -+local void lm_init (s) -+ deflate_state *s; -+{ -+ s->window_size = (ulg)2L*s->w_size; -+ -+ CLEAR_HASH(s); -+ -+ /* Set the default configuration parameters: -+ */ -+ s->max_lazy_match = configuration_table[s->level].max_lazy; -+ s->good_match = configuration_table[s->level].good_length; -+ s->nice_match = configuration_table[s->level].nice_length; -+ s->max_chain_length = configuration_table[s->level].max_chain; -+ -+ s->strstart = 0; -+ s->block_start = 0L; -+ s->lookahead = 0; -+ s->match_length = s->prev_length = MIN_MATCH-1; -+ s->match_available = 0; -+ s->ins_h = 0; -+#ifdef ASMV -+ match_init(); /* initialize the asm code */ -+#endif -+} -+ -+/* =========================================================================== -+ * Set match_start to the longest match starting at the given string and -+ * return its length. Matches shorter or equal to prev_length are discarded, -+ * in which case the result is equal to prev_length and match_start is -+ * garbage. -+ * IN assertions: cur_match is the head of the hash chain for the current -+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 -+ * OUT assertion: the match length is not greater than s->lookahead. -+ */ -+#ifndef ASMV -+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or -+ * match.S. The code will be functionally equivalent. -+ */ -+#ifndef FASTEST -+local uInt longest_match(s, cur_match) -+ deflate_state *s; -+ IPos cur_match; /* current match */ -+{ -+ unsigned chain_length = s->max_chain_length;/* max hash chain length */ -+ register Bytef *scan = s->window + s->strstart; /* current string */ -+ register Bytef *match; /* matched string */ -+ register int len; /* length of current match */ -+ int best_len = s->prev_length; /* best match length so far */ -+ int nice_match = s->nice_match; /* stop if match long enough */ -+ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? -+ s->strstart - (IPos)MAX_DIST(s) : NIL; -+ /* Stop when cur_match becomes <= limit. To simplify the code, -+ * we prevent matches with the string of window index 0. -+ */ -+ Posf *prev = s->prev; -+ uInt wmask = s->w_mask; -+ -+#ifdef UNALIGNED_OK -+ /* Compare two bytes at a time. Note: this is not always beneficial. -+ * Try with and without -DUNALIGNED_OK to check. -+ */ -+ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; -+ register ush scan_start = *(ushf*)scan; -+ register ush scan_end = *(ushf*)(scan+best_len-1); -+#else -+ register Bytef *strend = s->window + s->strstart + MAX_MATCH; -+ register Byte scan_end1 = scan[best_len-1]; -+ register Byte scan_end = scan[best_len]; -+#endif -+ -+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. -+ * It is easy to get rid of this optimization if necessary. -+ */ -+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); -+ -+ /* Do not waste too much time if we already have a good match: */ -+ if (s->prev_length >= s->good_match) { -+ chain_length >>= 2; -+ } -+ /* Do not look for matches beyond the end of the input. This is necessary -+ * to make deflate deterministic. -+ */ -+ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; -+ -+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); -+ -+ do { -+ Assert(cur_match < s->strstart, "no future"); -+ match = s->window + cur_match; -+ -+ /* Skip to next match if the match length cannot increase -+ * or if the match length is less than 2: -+ */ -+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) -+ /* This code assumes sizeof(unsigned short) == 2. Do not use -+ * UNALIGNED_OK if your compiler uses a different size. -+ */ -+ if (*(ushf*)(match+best_len-1) != scan_end || -+ *(ushf*)match != scan_start) continue; -+ -+ /* It is not necessary to compare scan[2] and match[2] since they are -+ * always equal when the other bytes match, given that the hash keys -+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at -+ * strstart+3, +5, ... up to strstart+257. We check for insufficient -+ * lookahead only every 4th comparison; the 128th check will be made -+ * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is -+ * necessary to put more guard bytes at the end of the window, or -+ * to check more often for insufficient lookahead. -+ */ -+ Assert(scan[2] == match[2], "scan[2]?"); -+ scan++, match++; -+ do { -+ } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && -+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) && -+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) && -+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) && -+ scan < strend); -+ /* The funny "do {}" generates better code on most compilers */ -+ -+ /* Here, scan <= window+strstart+257 */ -+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); -+ if (*scan == *match) scan++; -+ -+ len = (MAX_MATCH - 1) - (int)(strend-scan); -+ scan = strend - (MAX_MATCH-1); -+ -+#else /* UNALIGNED_OK */ -+ -+ if (match[best_len] != scan_end || -+ match[best_len-1] != scan_end1 || -+ *match != *scan || -+ *++match != scan[1]) continue; -+ -+ /* The check at best_len-1 can be removed because it will be made -+ * again later. (This heuristic is not always a win.) -+ * It is not necessary to compare scan[2] and match[2] since they -+ * are always equal when the other bytes match, given that -+ * the hash keys are equal and that HASH_BITS >= 8. -+ */ -+ scan += 2, match++; -+ Assert(*scan == *match, "match[2]?"); -+ -+ /* We check for insufficient lookahead only every 8th comparison; -+ * the 256th check will be made at strstart+258. -+ */ -+ do { -+ } while (*++scan == *++match && *++scan == *++match && -+ *++scan == *++match && *++scan == *++match && -+ *++scan == *++match && *++scan == *++match && -+ *++scan == *++match && *++scan == *++match && -+ scan < strend); -+ -+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); -+ -+ len = MAX_MATCH - (int)(strend - scan); -+ scan = strend - MAX_MATCH; -+ -+#endif /* UNALIGNED_OK */ -+ -+ if (len > best_len) { -+ s->match_start = cur_match; -+ best_len = len; -+ if (len >= nice_match) break; -+#ifdef UNALIGNED_OK -+ scan_end = *(ushf*)(scan+best_len-1); -+#else -+ scan_end1 = scan[best_len-1]; -+ scan_end = scan[best_len]; -+#endif -+ } -+ } while ((cur_match = prev[cur_match & wmask]) > limit -+ && --chain_length != 0); -+ -+ if ((uInt)best_len <= s->lookahead) return (uInt)best_len; -+ return s->lookahead; -+} -+ -+#else /* FASTEST */ -+/* --------------------------------------------------------------------------- -+ * Optimized version for level == 1 only -+ */ -+local uInt longest_match(s, cur_match) -+ deflate_state *s; -+ IPos cur_match; /* current match */ -+{ -+ register Bytef *scan = s->window + s->strstart; /* current string */ -+ register Bytef *match; /* matched string */ -+ register int len; /* length of current match */ -+ register Bytef *strend = s->window + s->strstart + MAX_MATCH; -+ -+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. -+ * It is easy to get rid of this optimization if necessary. -+ */ -+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); -+ -+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); -+ -+ Assert(cur_match < s->strstart, "no future"); -+ -+ match = s->window + cur_match; -+ -+ /* Return failure if the match length is less than 2: -+ */ -+ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; -+ -+ /* The check at best_len-1 can be removed because it will be made -+ * again later. (This heuristic is not always a win.) -+ * It is not necessary to compare scan[2] and match[2] since they -+ * are always equal when the other bytes match, given that -+ * the hash keys are equal and that HASH_BITS >= 8. -+ */ -+ scan += 2, match += 2; -+ Assert(*scan == *match, "match[2]?"); -+ -+ /* We check for insufficient lookahead only every 8th comparison; -+ * the 256th check will be made at strstart+258. -+ */ -+ do { -+ } while (*++scan == *++match && *++scan == *++match && -+ *++scan == *++match && *++scan == *++match && -+ *++scan == *++match && *++scan == *++match && -+ *++scan == *++match && *++scan == *++match && -+ scan < strend); -+ -+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); -+ -+ len = MAX_MATCH - (int)(strend - scan); -+ -+ if (len < MIN_MATCH) return MIN_MATCH - 1; -+ -+ s->match_start = cur_match; -+ return len <= s->lookahead ? len : s->lookahead; -+} -+#endif /* FASTEST */ -+#endif /* ASMV */ -+ -+#ifdef DEBUG -+/* =========================================================================== -+ * Check that the match at match_start is indeed a match. -+ */ -+local void check_match(s, start, match, length) -+ deflate_state *s; -+ IPos start, match; -+ int length; -+{ -+ /* check that the match is indeed a match */ -+ if (zmemcmp(s->window + match, -+ s->window + start, length) != EQUAL) { -+ fprintf(stderr, " start %u, match %u, length %d\n", -+ start, match, length); -+ do { -+ fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); -+ } while (--length != 0); -+ z_error("invalid match"); -+ } -+ if (z_verbose > 1) { -+ fprintf(stderr,"\\[%d,%d]", start-match, length); -+ do { putc(s->window[start++], stderr); } while (--length != 0); -+ } -+} -+#else -+# define check_match(s, start, match, length) -+#endif -+ -+/* =========================================================================== -+ * Fill the window when the lookahead becomes insufficient. -+ * Updates strstart and lookahead. -+ * -+ * IN assertion: lookahead < MIN_LOOKAHEAD -+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD -+ * At least one byte has been read, or avail_in == 0; reads are -+ * performed for at least two bytes (required for the zip translate_eol -+ * option -- not supported here). -+ */ -+local void fill_window(s) -+ deflate_state *s; -+{ -+ register unsigned n, m; -+ register Posf *p; -+ unsigned more; /* Amount of free space at the end of the window. */ -+ uInt wsize = s->w_size; -+ -+ do { -+ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); -+ -+ /* Deal with !@#$% 64K limit: */ -+ if (more == 0 && s->strstart == 0 && s->lookahead == 0) { -+ more = wsize; -+ -+ } else if (more == (unsigned)(-1)) { -+ /* Very unlikely, but possible on 16 bit machine if strstart == 0 -+ * and lookahead == 1 (input done one byte at time) -+ */ -+ more--; -+ -+ /* If the window is almost full and there is insufficient lookahead, -+ * move the upper half to the lower one to make room in the upper half. -+ */ -+ } else if (s->strstart >= wsize+MAX_DIST(s)) { -+ -+ zmemcpy(s->window, s->window+wsize, (unsigned)wsize); -+ s->match_start -= wsize; -+ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ -+ s->block_start -= (long) wsize; -+ -+ /* Slide the hash table (could be avoided with 32 bit values -+ at the expense of memory usage). We slide even when level == 0 -+ to keep the hash table consistent if we switch back to level > 0 -+ later. (Using level 0 permanently is not an optimal usage of -+ zlib, so we don't care about this pathological case.) -+ */ -+ n = s->hash_size; -+ p = &s->head[n]; -+ do { -+ m = *--p; -+ *p = (Pos)(m >= wsize ? m-wsize : NIL); -+ } while (--n); -+ -+ n = wsize; -+#ifndef FASTEST -+ p = &s->prev[n]; -+ do { -+ m = *--p; -+ *p = (Pos)(m >= wsize ? m-wsize : NIL); -+ /* If n is not on any hash chain, prev[n] is garbage but -+ * its value will never be used. -+ */ -+ } while (--n); -+#endif -+ more += wsize; -+ } -+ if (s->strm->avail_in == 0) return; -+ -+ /* If there was no sliding: -+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && -+ * more == window_size - lookahead - strstart -+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) -+ * => more >= window_size - 2*WSIZE + 2 -+ * In the BIG_MEM or MMAP case (not yet supported), -+ * window_size == input_size + MIN_LOOKAHEAD && -+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. -+ * Otherwise, window_size == 2*WSIZE so more >= 2. -+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2. -+ */ -+ Assert(more >= 2, "more < 2"); -+ -+ n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); -+ s->lookahead += n; -+ -+ /* Initialize the hash value now that we have some input: */ -+ if (s->lookahead >= MIN_MATCH) { -+ s->ins_h = s->window[s->strstart]; -+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -+#if MIN_MATCH != 3 -+ Call UPDATE_HASH() MIN_MATCH-3 more times -+#endif -+ } -+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, -+ * but this is not important since only literal bytes will be emitted. -+ */ -+ -+ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); -+} -+ -+/* =========================================================================== -+ * Flush the current block, with given end-of-file flag. -+ * IN assertion: strstart is set to the end of the current match. -+ */ -+#define FLUSH_BLOCK_ONLY(s, eof) { \ -+ _tr_flush_block(s, (s->block_start >= 0L ? \ -+ (charf *)&s->window[(unsigned)s->block_start] : \ -+ (charf *)Z_NULL), \ -+ (ulg)((long)s->strstart - s->block_start), \ -+ (eof)); \ -+ s->block_start = s->strstart; \ -+ flush_pending(s->strm); \ -+ Tracev((stderr,"[FLUSH]")); \ -+} -+ -+/* Same but force premature exit if necessary. */ -+#define FLUSH_BLOCK(s, eof) { \ -+ FLUSH_BLOCK_ONLY(s, eof); \ -+ if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ -+} -+ -+/* =========================================================================== -+ * Copy without compression as much as possible from the input stream, return -+ * the current block state. -+ * This function does not insert new strings in the dictionary since -+ * uncompressible data is probably not useful. This function is used -+ * only for the level=0 compression option. -+ * NOTE: this function should be optimized to avoid extra copying from -+ * window to pending_buf. -+ */ -+local block_state deflate_stored(s, flush) -+ deflate_state *s; -+ int flush; -+{ -+ /* Stored blocks are limited to 0xffff bytes, pending_buf is limited -+ * to pending_buf_size, and each stored block has a 5 byte header: -+ */ -+ ulg max_block_size = 0xffff; -+ ulg max_start; -+ -+ if (max_block_size > s->pending_buf_size - 5) { -+ max_block_size = s->pending_buf_size - 5; -+ } -+ -+ /* Copy as much as possible from input to output: */ -+ for (;;) { -+ /* Fill the window as much as possible: */ -+ if (s->lookahead <= 1) { -+ -+ Assert(s->strstart < s->w_size+MAX_DIST(s) || -+ s->block_start >= (long)s->w_size, "slide too late"); -+ -+ fill_window(s); -+ if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; -+ -+ if (s->lookahead == 0) break; /* flush the current block */ -+ } -+ Assert(s->block_start >= 0L, "block gone"); -+ -+ s->strstart += s->lookahead; -+ s->lookahead = 0; -+ -+ /* Emit a stored block if pending_buf will be full: */ -+ max_start = s->block_start + max_block_size; -+ if (s->strstart == 0 || (ulg)s->strstart >= max_start) { -+ /* strstart == 0 is possible when wraparound on 16-bit machine */ -+ s->lookahead = (uInt)(s->strstart - max_start); -+ s->strstart = (uInt)max_start; -+ FLUSH_BLOCK(s, 0); -+ } -+ /* Flush if we may have to slide, otherwise block_start may become -+ * negative and the data will be gone: -+ */ -+ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { -+ FLUSH_BLOCK(s, 0); -+ } -+ } -+ FLUSH_BLOCK(s, flush == Z_FINISH); -+ return flush == Z_FINISH ? finish_done : block_done; -+} -+ -+/* =========================================================================== -+ * Compress as much as possible from the input stream, return the current -+ * block state. -+ * This function does not perform lazy evaluation of matches and inserts -+ * new strings in the dictionary only for unmatched strings or for short -+ * matches. It is used only for the fast compression options. -+ */ -+local block_state deflate_fast(s, flush) -+ deflate_state *s; -+ int flush; -+{ -+ IPos hash_head = NIL; /* head of the hash chain */ -+ int bflush; /* set if current block must be flushed */ -+ -+ for (;;) { -+ /* Make sure that we always have enough lookahead, except -+ * at the end of the input file. We need MAX_MATCH bytes -+ * for the next match, plus MIN_MATCH bytes to insert the -+ * string following the next match. -+ */ -+ if (s->lookahead < MIN_LOOKAHEAD) { -+ fill_window(s); -+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { -+ return need_more; -+ } -+ if (s->lookahead == 0) break; /* flush the current block */ -+ } -+ -+ /* Insert the string window[strstart .. strstart+2] in the -+ * dictionary, and set hash_head to the head of the hash chain: -+ */ -+ if (s->lookahead >= MIN_MATCH) { -+ INSERT_STRING(s, s->strstart, hash_head); -+ } -+ -+ /* Find the longest match, discarding those <= prev_length. -+ * At this point we have always match_length < MIN_MATCH -+ */ -+ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { -+ /* To simplify the code, we prevent matches with the string -+ * of window index 0 (in particular we have to avoid a match -+ * of the string with itself at the start of the input file). -+ */ -+ if (s->strategy != Z_HUFFMAN_ONLY) { -+ s->match_length = longest_match (s, hash_head); -+ } -+ /* longest_match() sets match_start */ -+ } -+ if (s->match_length >= MIN_MATCH) { -+ check_match(s, s->strstart, s->match_start, s->match_length); -+ -+ _tr_tally_dist(s, s->strstart - s->match_start, -+ s->match_length - MIN_MATCH, bflush); -+ -+ s->lookahead -= s->match_length; -+ -+ /* Insert new strings in the hash table only if the match length -+ * is not too large. This saves time but degrades compression. -+ */ -+#ifndef FASTEST -+ if (s->match_length <= s->max_insert_length && -+ s->lookahead >= MIN_MATCH) { -+ s->match_length--; /* string at strstart already in hash table */ -+ do { -+ s->strstart++; -+ INSERT_STRING(s, s->strstart, hash_head); -+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are -+ * always MIN_MATCH bytes ahead. -+ */ -+ } while (--s->match_length != 0); -+ s->strstart++; -+ } else -+#endif -+ { -+ s->strstart += s->match_length; -+ s->match_length = 0; -+ s->ins_h = s->window[s->strstart]; -+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -+#if MIN_MATCH != 3 -+ Call UPDATE_HASH() MIN_MATCH-3 more times -+#endif -+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not -+ * matter since it will be recomputed at next deflate call. -+ */ -+ } -+ } else { -+ /* No match, output a literal byte */ -+ Tracevv((stderr,"%c", s->window[s->strstart])); -+ _tr_tally_lit (s, s->window[s->strstart], bflush); -+ s->lookahead--; -+ s->strstart++; -+ } -+ if (bflush) FLUSH_BLOCK(s, 0); -+ } -+ FLUSH_BLOCK(s, flush == Z_FINISH); -+ return flush == Z_FINISH ? finish_done : block_done; -+} -+ -+/* =========================================================================== -+ * Same as above, but achieves better compression. We use a lazy -+ * evaluation for matches: a match is finally adopted only if there is -+ * no better match at the next window position. -+ */ -+local block_state deflate_slow(s, flush) -+ deflate_state *s; -+ int flush; -+{ -+ IPos hash_head = NIL; /* head of hash chain */ -+ int bflush; /* set if current block must be flushed */ -+ -+ /* Process the input block. */ -+ for (;;) { -+ /* Make sure that we always have enough lookahead, except -+ * at the end of the input file. We need MAX_MATCH bytes -+ * for the next match, plus MIN_MATCH bytes to insert the -+ * string following the next match. -+ */ -+ if (s->lookahead < MIN_LOOKAHEAD) { -+ fill_window(s); -+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { -+ return need_more; -+ } -+ if (s->lookahead == 0) break; /* flush the current block */ -+ } -+ -+ /* Insert the string window[strstart .. strstart+2] in the -+ * dictionary, and set hash_head to the head of the hash chain: -+ */ -+ if (s->lookahead >= MIN_MATCH) { -+ INSERT_STRING(s, s->strstart, hash_head); -+ } -+ -+ /* Find the longest match, discarding those <= prev_length. -+ */ -+ s->prev_length = s->match_length, s->prev_match = s->match_start; -+ s->match_length = MIN_MATCH-1; -+ -+ if (hash_head != NIL && s->prev_length < s->max_lazy_match && -+ s->strstart - hash_head <= MAX_DIST(s)) { -+ /* To simplify the code, we prevent matches with the string -+ * of window index 0 (in particular we have to avoid a match -+ * of the string with itself at the start of the input file). -+ */ -+ if (s->strategy != Z_HUFFMAN_ONLY) { -+ s->match_length = longest_match (s, hash_head); -+ } -+ /* longest_match() sets match_start */ -+ -+ if (s->match_length <= 5 && (s->strategy == Z_FILTERED || -+ (s->match_length == MIN_MATCH && -+ s->strstart - s->match_start > TOO_FAR))) { -+ -+ /* If prev_match is also MIN_MATCH, match_start is garbage -+ * but we will ignore the current match anyway. -+ */ -+ s->match_length = MIN_MATCH-1; -+ } -+ } -+ /* If there was a match at the previous step and the current -+ * match is not better, output the previous match: -+ */ -+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { -+ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; -+ /* Do not insert strings in hash table beyond this. */ -+ -+ check_match(s, s->strstart-1, s->prev_match, s->prev_length); -+ -+ _tr_tally_dist(s, s->strstart -1 - s->prev_match, -+ s->prev_length - MIN_MATCH, bflush); -+ -+ /* Insert in hash table all strings up to the end of the match. -+ * strstart-1 and strstart are already inserted. If there is not -+ * enough lookahead, the last two strings are not inserted in -+ * the hash table. -+ */ -+ s->lookahead -= s->prev_length-1; -+ s->prev_length -= 2; -+ do { -+ if (++s->strstart <= max_insert) { -+ INSERT_STRING(s, s->strstart, hash_head); -+ } -+ } while (--s->prev_length != 0); -+ s->match_available = 0; -+ s->match_length = MIN_MATCH-1; -+ s->strstart++; -+ -+ if (bflush) FLUSH_BLOCK(s, 0); -+ -+ } else if (s->match_available) { -+ /* If there was no match at the previous position, output a -+ * single literal. If there was a match but the current match -+ * is longer, truncate the previous match to a single literal. -+ */ -+ Tracevv((stderr,"%c", s->window[s->strstart-1])); -+ _tr_tally_lit(s, s->window[s->strstart-1], bflush); -+ if (bflush) { -+ FLUSH_BLOCK_ONLY(s, 0); -+ } -+ s->strstart++; -+ s->lookahead--; -+ if (s->strm->avail_out == 0) return need_more; -+ } else { -+ /* There is no previous match to compare with, wait for -+ * the next step to decide. -+ */ -+ s->match_available = 1; -+ s->strstart++; -+ s->lookahead--; -+ } -+ } -+ Assert (flush != Z_NO_FLUSH, "no flush?"); -+ if (s->match_available) { -+ Tracevv((stderr,"%c", s->window[s->strstart-1])); -+ _tr_tally_lit(s, s->window[s->strstart-1], bflush); -+ s->match_available = 0; -+ } -+ FLUSH_BLOCK(s, flush == Z_FINISH); -+ return flush == Z_FINISH ? finish_done : block_done; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/deflate.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,318 @@ -+/* deflate.h -- internal compression state -+ * Copyright (C) 1995-2002 Jean-loup Gailly -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+/* @(#) $Id$ */ -+ -+#ifndef _DEFLATE_H -+#define _DEFLATE_H -+ -+#include "zlib/zutil.h" -+ -+/* =========================================================================== -+ * Internal compression state. -+ */ -+ -+#define LENGTH_CODES 29 -+/* number of length codes, not counting the special END_BLOCK code */ -+ -+#define LITERALS 256 -+/* number of literal bytes 0..255 */ -+ -+#define L_CODES (LITERALS+1+LENGTH_CODES) -+/* number of Literal or Length codes, including the END_BLOCK code */ -+ -+#define D_CODES 30 -+/* number of distance codes */ -+ -+#define BL_CODES 19 -+/* number of codes used to transfer the bit lengths */ -+ -+#define HEAP_SIZE (2*L_CODES+1) -+/* maximum heap size */ -+ -+#define MAX_BITS 15 -+/* All codes must not exceed MAX_BITS bits */ -+ -+#define INIT_STATE 42 -+#define BUSY_STATE 113 -+#define FINISH_STATE 666 -+/* Stream status */ -+ -+ -+/* Data structure describing a single value and its code string. */ -+typedef struct ct_data_s { -+ union { -+ ush freq; /* frequency count */ -+ ush code; /* bit string */ -+ } fc; -+ union { -+ ush dad; /* father node in Huffman tree */ -+ ush len; /* length of bit string */ -+ } dl; -+} FAR ct_data; -+ -+#define Freq fc.freq -+#define Code fc.code -+#define Dad dl.dad -+#define Len dl.len -+ -+typedef struct static_tree_desc_s static_tree_desc; -+ -+typedef struct tree_desc_s { -+ ct_data *dyn_tree; /* the dynamic tree */ -+ int max_code; /* largest code with non zero frequency */ -+ static_tree_desc *stat_desc; /* the corresponding static tree */ -+} FAR tree_desc; -+ -+typedef ush Pos; -+typedef Pos FAR Posf; -+typedef unsigned IPos; -+ -+/* A Pos is an index in the character window. We use short instead of int to -+ * save space in the various tables. IPos is used only for parameter passing. -+ */ -+ -+typedef struct internal_state { -+ z_streamp strm; /* pointer back to this zlib stream */ -+ int status; /* as the name implies */ -+ Bytef *pending_buf; /* output still pending */ -+ ulg pending_buf_size; /* size of pending_buf */ -+ Bytef *pending_out; /* next pending byte to output to the stream */ -+ int pending; /* nb of bytes in the pending buffer */ -+ int noheader; /* suppress zlib header and adler32 */ -+ Byte data_type; /* UNKNOWN, BINARY or ASCII */ -+ Byte method; /* STORED (for zip only) or DEFLATED */ -+ int last_flush; /* value of flush param for previous deflate call */ -+ -+ /* used by deflate.c: */ -+ -+ uInt w_size; /* LZ77 window size (32K by default) */ -+ uInt w_bits; /* log2(w_size) (8..16) */ -+ uInt w_mask; /* w_size - 1 */ -+ -+ Bytef *window; -+ /* Sliding window. Input bytes are read into the second half of the window, -+ * and move to the first half later to keep a dictionary of at least wSize -+ * bytes. With this organization, matches are limited to a distance of -+ * wSize-MAX_MATCH bytes, but this ensures that IO is always -+ * performed with a length multiple of the block size. Also, it limits -+ * the window size to 64K, which is quite useful on MSDOS. -+ * To do: use the user input buffer as sliding window. -+ */ -+ -+ ulg window_size; -+ /* Actual size of window: 2*wSize, except when the user input buffer -+ * is directly used as sliding window. -+ */ -+ -+ Posf *prev; -+ /* Link to older string with same hash index. To limit the size of this -+ * array to 64K, this link is maintained only for the last 32K strings. -+ * An index in this array is thus a window index modulo 32K. -+ */ -+ -+ Posf *head; /* Heads of the hash chains or NIL. */ -+ -+ uInt ins_h; /* hash index of string to be inserted */ -+ uInt hash_size; /* number of elements in hash table */ -+ uInt hash_bits; /* log2(hash_size) */ -+ uInt hash_mask; /* hash_size-1 */ -+ -+ uInt hash_shift; -+ /* Number of bits by which ins_h must be shifted at each input -+ * step. It must be such that after MIN_MATCH steps, the oldest -+ * byte no longer takes part in the hash key, that is: -+ * hash_shift * MIN_MATCH >= hash_bits -+ */ -+ -+ long block_start; -+ /* Window position at the beginning of the current output block. Gets -+ * negative when the window is moved backwards. -+ */ -+ -+ uInt match_length; /* length of best match */ -+ IPos prev_match; /* previous match */ -+ int match_available; /* set if previous match exists */ -+ uInt strstart; /* start of string to insert */ -+ uInt match_start; /* start of matching string */ -+ uInt lookahead; /* number of valid bytes ahead in window */ -+ -+ uInt prev_length; -+ /* Length of the best match at previous step. Matches not greater than this -+ * are discarded. This is used in the lazy match evaluation. -+ */ -+ -+ uInt max_chain_length; -+ /* To speed up deflation, hash chains are never searched beyond this -+ * length. A higher limit improves compression ratio but degrades the -+ * speed. -+ */ -+ -+ uInt max_lazy_match; -+ /* Attempt to find a better match only when the current match is strictly -+ * smaller than this value. This mechanism is used only for compression -+ * levels >= 4. -+ */ -+# define max_insert_length max_lazy_match -+ /* Insert new strings in the hash table only if the match length is not -+ * greater than this length. This saves time but degrades compression. -+ * max_insert_length is used only for compression levels <= 3. -+ */ -+ -+ int level; /* compression level (1..9) */ -+ int strategy; /* favor or force Huffman coding*/ -+ -+ uInt good_match; -+ /* Use a faster search when the previous match is longer than this */ -+ -+ int nice_match; /* Stop searching when current match exceeds this */ -+ -+ /* used by trees.c: */ -+ /* Didn't use ct_data typedef below to supress compiler warning */ -+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ -+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ -+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ -+ -+ struct tree_desc_s l_desc; /* desc. for literal tree */ -+ struct tree_desc_s d_desc; /* desc. for distance tree */ -+ struct tree_desc_s bl_desc; /* desc. for bit length tree */ -+ -+ ush bl_count[MAX_BITS+1]; -+ /* number of codes at each bit length for an optimal tree */ -+ -+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ -+ int heap_len; /* number of elements in the heap */ -+ int heap_max; /* element of largest frequency */ -+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. -+ * The same heap array is used to build all trees. -+ */ -+ -+ uch depth[2*L_CODES+1]; -+ /* Depth of each subtree used as tie breaker for trees of equal frequency -+ */ -+ -+ uchf *l_buf; /* buffer for literals or lengths */ -+ -+ uInt lit_bufsize; -+ /* Size of match buffer for literals/lengths. There are 4 reasons for -+ * limiting lit_bufsize to 64K: -+ * - frequencies can be kept in 16 bit counters -+ * - if compression is not successful for the first block, all input -+ * data is still in the window so we can still emit a stored block even -+ * when input comes from standard input. (This can also be done for -+ * all blocks if lit_bufsize is not greater than 32K.) -+ * - if compression is not successful for a file smaller than 64K, we can -+ * even emit a stored file instead of a stored block (saving 5 bytes). -+ * This is applicable only for zip (not gzip or zlib). -+ * - creating new Huffman trees less frequently may not provide fast -+ * adaptation to changes in the input data statistics. (Take for -+ * example a binary file with poorly compressible code followed by -+ * a highly compressible string table.) Smaller buffer sizes give -+ * fast adaptation but have of course the overhead of transmitting -+ * trees more frequently. -+ * - I can't count above 4 -+ */ -+ -+ uInt last_lit; /* running index in l_buf */ -+ -+ ushf *d_buf; -+ /* Buffer for distances. To simplify the code, d_buf and l_buf have -+ * the same number of elements. To use different lengths, an extra flag -+ * array would be necessary. -+ */ -+ -+ ulg opt_len; /* bit length of current block with optimal trees */ -+ ulg static_len; /* bit length of current block with static trees */ -+ uInt matches; /* number of string matches in current block */ -+ int last_eob_len; /* bit length of EOB code for last block */ -+ -+#ifdef DEBUG -+ ulg compressed_len; /* total bit length of compressed file mod 2^32 */ -+ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ -+#endif -+ -+ ush bi_buf; -+ /* Output buffer. bits are inserted starting at the bottom (least -+ * significant bits). -+ */ -+ int bi_valid; -+ /* Number of valid bits in bi_buf. All bits above the last valid bit -+ * are always zero. -+ */ -+ -+} FAR deflate_state; -+ -+/* Output a byte on the stream. -+ * IN assertion: there is enough room in pending_buf. -+ */ -+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} -+ -+ -+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -+/* Minimum amount of lookahead, except at the end of the input file. -+ * See deflate.c for comments about the MIN_MATCH+1. -+ */ -+ -+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) -+/* In order to simplify the code, particularly on 16 bit machines, match -+ * distances are limited to MAX_DIST instead of WSIZE. -+ */ -+ -+ /* in trees.c */ -+void _tr_init OF((deflate_state *s)); -+int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); -+void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, -+ int eof)); -+void _tr_align OF((deflate_state *s)); -+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, -+ int eof)); -+ -+#define d_code(dist) \ -+ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) -+/* Mapping from a distance to a distance code. dist is the distance - 1 and -+ * must not have side effects. _dist_code[256] and _dist_code[257] are never -+ * used. -+ */ -+ -+#ifndef DEBUG -+/* Inline versions of _tr_tally for speed: */ -+ -+#if defined(GEN_TREES_H) || !defined(STDC) -+ extern uch _length_code[]; -+ extern uch _dist_code[]; -+#else -+ extern const uch _length_code[]; -+ extern const uch _dist_code[]; -+#endif -+ -+# define _tr_tally_lit(s, c, flush) \ -+ { uch cc = (c); \ -+ s->d_buf[s->last_lit] = 0; \ -+ s->l_buf[s->last_lit++] = cc; \ -+ s->dyn_ltree[cc].Freq++; \ -+ flush = (s->last_lit == s->lit_bufsize-1); \ -+ } -+# define _tr_tally_dist(s, distance, length, flush) \ -+ { uch len = (length); \ -+ ush dist = (distance); \ -+ s->d_buf[s->last_lit] = dist; \ -+ s->l_buf[s->last_lit++] = len; \ -+ dist--; \ -+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ -+ s->dyn_dtree[d_code(dist)].Freq++; \ -+ flush = (s->last_lit == s->lit_bufsize-1); \ -+ } -+#else -+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) -+# define _tr_tally_dist(s, distance, length, flush) \ -+ flush = _tr_tally(s, distance, length) -+#endif -+ -+#endif /* _DEFLATE_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/infblock.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,403 @@ -+/* infblock.c -- interpret and process block types to last block -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+#include -+#include "infblock.h" -+#include "inftrees.h" -+#include "infcodes.h" -+#include "infutil.h" -+ -+struct inflate_codes_state {int dummy;}; /* for buggy compilers */ -+ -+/* simplify the use of the inflate_huft type with some defines */ -+#define exop word.what.Exop -+#define bits word.what.Bits -+ -+/* Table for deflate from PKZIP's appnote.txt. */ -+local const uInt border[] = { /* Order of the bit length code lengths */ -+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; -+ -+/* -+ Notes beyond the 1.93a appnote.txt: -+ -+ 1. Distance pointers never point before the beginning of the output -+ stream. -+ 2. Distance pointers can point back across blocks, up to 32k away. -+ 3. There is an implied maximum of 7 bits for the bit length table and -+ 15 bits for the actual data. -+ 4. If only one code exists, then it is encoded using one bit. (Zero -+ would be more efficient, but perhaps a little confusing.) If two -+ codes exist, they are coded using one bit each (0 and 1). -+ 5. There is no way of sending zero distance codes--a dummy must be -+ sent if there are none. (History: a pre 2.0 version of PKZIP would -+ store blocks with no distance codes, but this was discovered to be -+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow -+ zero distance codes, which is sent as one code of zero bits in -+ length. -+ 6. There are up to 286 literal/length codes. Code 256 represents the -+ end-of-block. Note however that the static length tree defines -+ 288 codes just to fill out the Huffman codes. Codes 286 and 287 -+ cannot be used though, since there is no length base or extra bits -+ defined for them. Similarily, there are up to 30 distance codes. -+ However, static trees define 32 codes (all 5 bits) to fill out the -+ Huffman codes, but the last two had better not show up in the data. -+ 7. Unzip can check dynamic Huffman blocks for complete code sets. -+ The exception is that a single code would not be complete (see #4). -+ 8. The five bits following the block type is really the number of -+ literal codes sent minus 257. -+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits -+ (1+6+6). Therefore, to output three times the length, you output -+ three codes (1+1+1), whereas to output four times the same length, -+ you only need two codes (1+3). Hmm. -+ 10. In the tree reconstruction algorithm, Code = Code + Increment -+ only if BitLength(i) is not zero. (Pretty obvious.) -+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) -+ 12. Note: length code 284 can represent 227-258, but length code 285 -+ really is 258. The last length deserves its own, short code -+ since it gets used a lot in very redundant files. The length -+ 258 is special since 258 - 3 (the min match length) is 255. -+ 13. The literal/length and distance code bit lengths are read as a -+ single stream of lengths. It is possible (and advantageous) for -+ a repeat code (16, 17, or 18) to go across the boundary between -+ the two sets of lengths. -+ */ -+ -+ -+void inflate_blocks_reset(s, z, c) -+inflate_blocks_statef *s; -+z_streamp z; -+uLongf *c; -+{ -+ if (c != Z_NULL) -+ *c = s->check; -+ if (s->mode == BTREE || s->mode == DTREE) -+ ZFREE(z, s->sub.trees.blens); -+ if (s->mode == CODES) -+ inflate_codes_free(s->sub.decode.codes, z); -+ s->mode = TYPE; -+ s->bitk = 0; -+ s->bitb = 0; -+ s->read = s->write = s->window; -+ if (s->checkfn != Z_NULL) -+ z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); -+ Tracev((stderr, "inflate: blocks reset\n")); -+} -+ -+ -+inflate_blocks_statef *inflate_blocks_new(z, c, w) -+z_streamp z; -+check_func c; -+uInt w; -+{ -+ inflate_blocks_statef *s; -+ -+ if ((s = (inflate_blocks_statef *)ZALLOC -+ (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) -+ return s; -+ if ((s->hufts = -+ (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) -+ { -+ ZFREE(z, s); -+ return Z_NULL; -+ } -+ if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) -+ { -+ ZFREE(z, s->hufts); -+ ZFREE(z, s); -+ return Z_NULL; -+ } -+ s->end = s->window + w; -+ s->checkfn = c; -+ s->mode = TYPE; -+ Tracev((stderr, "inflate: blocks allocated\n")); -+ inflate_blocks_reset(s, z, Z_NULL); -+ return s; -+} -+ -+ -+int inflate_blocks(s, z, r) -+inflate_blocks_statef *s; -+z_streamp z; -+int r; -+{ -+ uInt t; /* temporary storage */ -+ uLong b; /* bit buffer */ -+ uInt k; /* bits in bit buffer */ -+ Bytef *p; /* input data pointer */ -+ uInt n; /* bytes available there */ -+ Bytef *q; /* output window write pointer */ -+ uInt m; /* bytes to end of window or read pointer */ -+ -+ /* copy input/output information to locals (UPDATE macro restores) */ -+ LOAD -+ -+ /* process input based on current state */ -+ while (1) switch (s->mode) -+ { -+ case TYPE: -+ NEEDBITS(3) -+ t = (uInt)b & 7; -+ s->last = t & 1; -+ switch (t >> 1) -+ { -+ case 0: /* stored */ -+ Tracev((stderr, "inflate: stored block%s\n", -+ s->last ? " (last)" : "")); -+ DUMPBITS(3) -+ t = k & 7; /* go to byte boundary */ -+ DUMPBITS(t) -+ s->mode = LENS; /* get length of stored block */ -+ break; -+ case 1: /* fixed */ -+ Tracev((stderr, "inflate: fixed codes block%s\n", -+ s->last ? " (last)" : "")); -+ { -+ uInt bl, bd; -+ inflate_huft *tl, *td; -+ -+ inflate_trees_fixed(&bl, &bd, &tl, &td, z); -+ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); -+ if (s->sub.decode.codes == Z_NULL) -+ { -+ r = Z_MEM_ERROR; -+ LEAVE -+ } -+ } -+ DUMPBITS(3) -+ s->mode = CODES; -+ break; -+ case 2: /* dynamic */ -+ Tracev((stderr, "inflate: dynamic codes block%s\n", -+ s->last ? " (last)" : "")); -+ DUMPBITS(3) -+ s->mode = TABLE; -+ break; -+ case 3: /* illegal */ -+ DUMPBITS(3) -+ s->mode = BAD; -+ z->msg = (char*)"invalid block type"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+ break; -+ case LENS: -+ NEEDBITS(32) -+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) -+ { -+ s->mode = BAD; -+ z->msg = (char*)"invalid stored block lengths"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+ s->sub.left = (uInt)b & 0xffff; -+ b = k = 0; /* dump bits */ -+ Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); -+ s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); -+ break; -+ case STORED: -+ if (n == 0) -+ LEAVE -+ NEEDOUT -+ t = s->sub.left; -+ if (t > n) t = n; -+ if (t > m) t = m; -+ zmemcpy(q, p, t); -+ p += t; n -= t; -+ q += t; m -= t; -+ if ((s->sub.left -= t) != 0) -+ break; -+ Tracev((stderr, "inflate: stored end, %lu total out\n", -+ z->total_out + (q >= s->read ? q - s->read : -+ (s->end - s->read) + (q - s->window)))); -+ s->mode = s->last ? DRY : TYPE; -+ break; -+ case TABLE: -+ NEEDBITS(14) -+ s->sub.trees.table = t = (uInt)b & 0x3fff; -+#ifndef PKZIP_BUG_WORKAROUND -+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) -+ { -+ s->mode = BAD; -+ z->msg = (char*)"too many length or distance symbols"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+#endif -+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); -+ if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) -+ { -+ r = Z_MEM_ERROR; -+ LEAVE -+ } -+ DUMPBITS(14) -+ s->sub.trees.index = 0; -+ Tracev((stderr, "inflate: table sizes ok\n")); -+ s->mode = BTREE; -+ case BTREE: -+ while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) -+ { -+ NEEDBITS(3) -+ s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; -+ DUMPBITS(3) -+ } -+ while (s->sub.trees.index < 19) -+ s->sub.trees.blens[border[s->sub.trees.index++]] = 0; -+ s->sub.trees.bb = 7; -+ t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, -+ &s->sub.trees.tb, s->hufts, z); -+ if (t != Z_OK) -+ { -+ r = t; -+ if (r == Z_DATA_ERROR) -+ { -+ ZFREE(z, s->sub.trees.blens); -+ s->mode = BAD; -+ } -+ LEAVE -+ } -+ s->sub.trees.index = 0; -+ Tracev((stderr, "inflate: bits tree ok\n")); -+ s->mode = DTREE; -+ case DTREE: -+ while (t = s->sub.trees.table, -+ s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) -+ { -+ inflate_huft *h; -+ uInt i, j, c; -+ -+ t = s->sub.trees.bb; -+ NEEDBITS(t) -+ h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); -+ t = h->bits; -+ c = h->base; -+ if (c < 16) -+ { -+ DUMPBITS(t) -+ s->sub.trees.blens[s->sub.trees.index++] = c; -+ } -+ else /* c == 16..18 */ -+ { -+ i = c == 18 ? 7 : c - 14; -+ j = c == 18 ? 11 : 3; -+ NEEDBITS(t + i) -+ DUMPBITS(t) -+ j += (uInt)b & inflate_mask[i]; -+ DUMPBITS(i) -+ i = s->sub.trees.index; -+ t = s->sub.trees.table; -+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || -+ (c == 16 && i < 1)) -+ { -+ ZFREE(z, s->sub.trees.blens); -+ s->mode = BAD; -+ z->msg = (char*)"invalid bit length repeat"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ } -+ c = c == 16 ? s->sub.trees.blens[i - 1] : 0; -+ do { -+ s->sub.trees.blens[i++] = c; -+ } while (--j); -+ s->sub.trees.index = i; -+ } -+ } -+ s->sub.trees.tb = Z_NULL; -+ { -+ uInt bl, bd; -+ inflate_huft *tl, *td; -+ inflate_codes_statef *c; -+ -+ bl = 9; /* must be <= 9 for lookahead assumptions */ -+ bd = 6; /* must be <= 9 for lookahead assumptions */ -+ t = s->sub.trees.table; -+ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), -+ s->sub.trees.blens, &bl, &bd, &tl, &td, -+ s->hufts, z); -+ if (t != Z_OK) -+ { -+ if (t == (uInt)Z_DATA_ERROR) -+ { -+ ZFREE(z, s->sub.trees.blens); -+ s->mode = BAD; -+ } -+ r = t; -+ LEAVE -+ } -+ Tracev((stderr, "inflate: trees ok\n")); -+ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) -+ { -+ r = Z_MEM_ERROR; -+ LEAVE -+ } -+ s->sub.decode.codes = c; -+ } -+ ZFREE(z, s->sub.trees.blens); -+ s->mode = CODES; -+ case CODES: -+ UPDATE -+ if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) -+ return inflate_flush(s, z, r); -+ r = Z_OK; -+ inflate_codes_free(s->sub.decode.codes, z); -+ LOAD -+ Tracev((stderr, "inflate: codes end, %lu total out\n", -+ z->total_out + (q >= s->read ? q - s->read : -+ (s->end - s->read) + (q - s->window)))); -+ if (!s->last) -+ { -+ s->mode = TYPE; -+ break; -+ } -+ s->mode = DRY; -+ case DRY: -+ FLUSH -+ if (s->read != s->write) -+ LEAVE -+ s->mode = DONE; -+ case DONE: -+ r = Z_STREAM_END; -+ LEAVE -+ case BAD: -+ r = Z_DATA_ERROR; -+ LEAVE -+ default: -+ r = Z_STREAM_ERROR; -+ LEAVE -+ } -+} -+ -+ -+int inflate_blocks_free(s, z) -+inflate_blocks_statef *s; -+z_streamp z; -+{ -+ inflate_blocks_reset(s, z, Z_NULL); -+ ZFREE(z, s->window); -+ ZFREE(z, s->hufts); -+ ZFREE(z, s); -+ Tracev((stderr, "inflate: blocks freed\n")); -+ return Z_OK; -+} -+ -+ -+void inflate_set_dictionary(s, d, n) -+inflate_blocks_statef *s; -+const Bytef *d; -+uInt n; -+{ -+ zmemcpy(s->window, d, n); -+ s->read = s->write = s->window + n; -+} -+ -+ -+/* Returns true if inflate is currently at the end of a block generated -+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. -+ * IN assertion: s != Z_NULL -+ */ -+int inflate_blocks_sync_point(s) -+inflate_blocks_statef *s; -+{ -+ return s->mode == LENS; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/infblock.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,39 @@ -+/* infblock.h -- header to use infblock.c -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+struct inflate_blocks_state; -+typedef struct inflate_blocks_state FAR inflate_blocks_statef; -+ -+extern inflate_blocks_statef * inflate_blocks_new OF(( -+ z_streamp z, -+ check_func c, /* check function */ -+ uInt w)); /* window size */ -+ -+extern int inflate_blocks OF(( -+ inflate_blocks_statef *, -+ z_streamp , -+ int)); /* initial return code */ -+ -+extern void inflate_blocks_reset OF(( -+ inflate_blocks_statef *, -+ z_streamp , -+ uLongf *)); /* check value on output */ -+ -+extern int inflate_blocks_free OF(( -+ inflate_blocks_statef *, -+ z_streamp)); -+ -+extern void inflate_set_dictionary OF(( -+ inflate_blocks_statef *s, -+ const Bytef *d, /* dictionary */ -+ uInt n)); /* dictionary length */ -+ -+extern int inflate_blocks_sync_point OF(( -+ inflate_blocks_statef *s)); ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/infcodes.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,251 @@ -+/* infcodes.c -- process literals and length/distance pairs -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+#include -+#include "inftrees.h" -+#include "infblock.h" -+#include "infcodes.h" -+#include "infutil.h" -+#include "inffast.h" -+ -+/* simplify the use of the inflate_huft type with some defines */ -+#define exop word.what.Exop -+#define bits word.what.Bits -+ -+typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ -+ START, /* x: set up for LEN */ -+ LEN, /* i: get length/literal/eob next */ -+ LENEXT, /* i: getting length extra (have base) */ -+ DIST, /* i: get distance next */ -+ DISTEXT, /* i: getting distance extra */ -+ COPY, /* o: copying bytes in window, waiting for space */ -+ LIT, /* o: got literal, waiting for output space */ -+ WASH, /* o: got eob, possibly still output waiting */ -+ END, /* x: got eob and all data flushed */ -+ BADCODE} /* x: got error */ -+inflate_codes_mode; -+ -+/* inflate codes private state */ -+struct inflate_codes_state { -+ -+ /* mode */ -+ inflate_codes_mode mode; /* current inflate_codes mode */ -+ -+ /* mode dependent information */ -+ uInt len; -+ union { -+ struct { -+ inflate_huft *tree; /* pointer into tree */ -+ uInt need; /* bits needed */ -+ } code; /* if LEN or DIST, where in tree */ -+ uInt lit; /* if LIT, literal */ -+ struct { -+ uInt get; /* bits to get for extra */ -+ uInt dist; /* distance back to copy from */ -+ } copy; /* if EXT or COPY, where and how much */ -+ } sub; /* submode */ -+ -+ /* mode independent information */ -+ Byte lbits; /* ltree bits decoded per branch */ -+ Byte dbits; /* dtree bits decoder per branch */ -+ inflate_huft *ltree; /* literal/length/eob tree */ -+ inflate_huft *dtree; /* distance tree */ -+ -+}; -+ -+ -+inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) -+uInt bl, bd; -+inflate_huft *tl; -+inflate_huft *td; /* need separate declaration for Borland C++ */ -+z_streamp z; -+{ -+ inflate_codes_statef *c; -+ -+ if ((c = (inflate_codes_statef *) -+ ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) -+ { -+ c->mode = START; -+ c->lbits = (Byte)bl; -+ c->dbits = (Byte)bd; -+ c->ltree = tl; -+ c->dtree = td; -+ Tracev((stderr, "inflate: codes new\n")); -+ } -+ return c; -+} -+ -+ -+int inflate_codes(s, z, r) -+inflate_blocks_statef *s; -+z_streamp z; -+int r; -+{ -+ uInt j; /* temporary storage */ -+ inflate_huft *t; /* temporary pointer */ -+ uInt e; /* extra bits or operation */ -+ uLong b; /* bit buffer */ -+ uInt k; /* bits in bit buffer */ -+ Bytef *p; /* input data pointer */ -+ uInt n; /* bytes available there */ -+ Bytef *q; /* output window write pointer */ -+ uInt m; /* bytes to end of window or read pointer */ -+ Bytef *f; /* pointer to copy strings from */ -+ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ -+ -+ /* copy input/output information to locals (UPDATE macro restores) */ -+ LOAD -+ -+ /* process input and output based on current state */ -+ while (1) switch (c->mode) -+ { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ -+ case START: /* x: set up for LEN */ -+#ifndef SLOW -+ if (m >= 258 && n >= 10) -+ { -+ UPDATE -+ r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); -+ LOAD -+ if (r != Z_OK) -+ { -+ c->mode = r == Z_STREAM_END ? WASH : BADCODE; -+ break; -+ } -+ } -+#endif /* !SLOW */ -+ c->sub.code.need = c->lbits; -+ c->sub.code.tree = c->ltree; -+ c->mode = LEN; -+ case LEN: /* i: get length/literal/eob next */ -+ j = c->sub.code.need; -+ NEEDBITS(j) -+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); -+ DUMPBITS(t->bits) -+ e = (uInt)(t->exop); -+ if (e == 0) /* literal */ -+ { -+ c->sub.lit = t->base; -+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? -+ "inflate: literal '%c'\n" : -+ "inflate: literal 0x%02x\n", t->base)); -+ c->mode = LIT; -+ break; -+ } -+ if (e & 16) /* length */ -+ { -+ c->sub.copy.get = e & 15; -+ c->len = t->base; -+ c->mode = LENEXT; -+ break; -+ } -+ if ((e & 64) == 0) /* next table */ -+ { -+ c->sub.code.need = e; -+ c->sub.code.tree = t + t->base; -+ break; -+ } -+ if (e & 32) /* end of block */ -+ { -+ Tracevv((stderr, "inflate: end of block\n")); -+ c->mode = WASH; -+ break; -+ } -+ c->mode = BADCODE; /* invalid code */ -+ z->msg = (char*)"invalid literal/length code"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ case LENEXT: /* i: getting length extra (have base) */ -+ j = c->sub.copy.get; -+ NEEDBITS(j) -+ c->len += (uInt)b & inflate_mask[j]; -+ DUMPBITS(j) -+ c->sub.code.need = c->dbits; -+ c->sub.code.tree = c->dtree; -+ Tracevv((stderr, "inflate: length %u\n", c->len)); -+ c->mode = DIST; -+ case DIST: /* i: get distance next */ -+ j = c->sub.code.need; -+ NEEDBITS(j) -+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); -+ DUMPBITS(t->bits) -+ e = (uInt)(t->exop); -+ if (e & 16) /* distance */ -+ { -+ c->sub.copy.get = e & 15; -+ c->sub.copy.dist = t->base; -+ c->mode = DISTEXT; -+ break; -+ } -+ if ((e & 64) == 0) /* next table */ -+ { -+ c->sub.code.need = e; -+ c->sub.code.tree = t + t->base; -+ break; -+ } -+ c->mode = BADCODE; /* invalid code */ -+ z->msg = (char*)"invalid distance code"; -+ r = Z_DATA_ERROR; -+ LEAVE -+ case DISTEXT: /* i: getting distance extra */ -+ j = c->sub.copy.get; -+ NEEDBITS(j) -+ c->sub.copy.dist += (uInt)b & inflate_mask[j]; -+ DUMPBITS(j) -+ Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); -+ c->mode = COPY; -+ case COPY: /* o: copying bytes in window, waiting for space */ -+ f = q - c->sub.copy.dist; -+ while (f < s->window) /* modulo window size-"while" instead */ -+ f += s->end - s->window; /* of "if" handles invalid distances */ -+ while (c->len) -+ { -+ NEEDOUT -+ OUTBYTE(*f++) -+ if (f == s->end) -+ f = s->window; -+ c->len--; -+ } -+ c->mode = START; -+ break; -+ case LIT: /* o: got literal, waiting for output space */ -+ NEEDOUT -+ OUTBYTE(c->sub.lit) -+ c->mode = START; -+ break; -+ case WASH: /* o: got eob, possibly more output */ -+ if (k > 7) /* return unused byte, if any */ -+ { -+ Assert(k < 16, "inflate_codes grabbed too many bytes") -+ k -= 8; -+ n++; -+ p--; /* can always return one */ -+ } -+ FLUSH -+ if (s->read != s->write) -+ LEAVE -+ c->mode = END; -+ case END: -+ r = Z_STREAM_END; -+ LEAVE -+ case BADCODE: /* x: got error */ -+ r = Z_DATA_ERROR; -+ LEAVE -+ default: -+ r = Z_STREAM_ERROR; -+ LEAVE -+ } -+#ifdef NEED_DUMMY_RETURN -+ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ -+#endif -+} -+ -+ -+void inflate_codes_free(c, z) -+inflate_codes_statef *c; -+z_streamp z; -+{ -+ ZFREE(z, c); -+ Tracev((stderr, "inflate: codes free\n")); -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/infcodes.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,31 @@ -+/* infcodes.h -- header to use infcodes.c -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+#ifndef _INFCODES_H -+#define _INFCODES_H -+ -+struct inflate_codes_state; -+typedef struct inflate_codes_state FAR inflate_codes_statef; -+ -+extern inflate_codes_statef *inflate_codes_new OF(( -+ uInt, uInt, -+ inflate_huft *, inflate_huft *, -+ z_streamp )); -+ -+extern int inflate_codes OF(( -+ inflate_blocks_statef *, -+ z_streamp , -+ int)); -+ -+extern void inflate_codes_free OF(( -+ inflate_codes_statef *, -+ z_streamp )); -+ -+#endif /* _INFCODES_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/inffast.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,183 @@ -+/* inffast.c -- process literals and length/distance pairs fast -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+#include -+#include "inftrees.h" -+#include "infblock.h" -+#include "infcodes.h" -+#include "infutil.h" -+#include "inffast.h" -+ -+struct inflate_codes_state {int dummy;}; /* for buggy compilers */ -+ -+/* simplify the use of the inflate_huft type with some defines */ -+#define exop word.what.Exop -+#define bits word.what.Bits -+ -+/* macros for bit input with no checking and for returning unused bytes */ -+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;} -+ -+/* Called with number of bytes left to write in window at least 258 -+ (the maximum string length) and number of input bytes available -+ at least ten. The ten bytes are six bytes for the longest length/ -+ distance pair plus four bytes for overloading the bit buffer. */ -+ -+int inflate_fast(bl, bd, tl, td, s, z) -+uInt bl, bd; -+inflate_huft *tl; -+inflate_huft *td; /* need separate declaration for Borland C++ */ -+inflate_blocks_statef *s; -+z_streamp z; -+{ -+ inflate_huft *t; /* temporary pointer */ -+ uInt e; /* extra bits or operation */ -+ uLong b; /* bit buffer */ -+ uInt k; /* bits in bit buffer */ -+ Bytef *p; /* input data pointer */ -+ uInt n; /* bytes available there */ -+ Bytef *q; /* output window write pointer */ -+ uInt m; /* bytes to end of window or read pointer */ -+ uInt ml; /* mask for literal/length tree */ -+ uInt md; /* mask for distance tree */ -+ uInt c; /* bytes to copy */ -+ uInt d; /* distance back to copy from */ -+ Bytef *r; /* copy source pointer */ -+ -+ /* load input, output, bit values */ -+ LOAD -+ -+ /* initialize masks */ -+ ml = inflate_mask[bl]; -+ md = inflate_mask[bd]; -+ -+ /* do until not enough input or output space for fast loop */ -+ do { /* assume called with m >= 258 && n >= 10 */ -+ /* get literal/length code */ -+ GRABBITS(20) /* max bits for literal/length code */ -+ if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) -+ { -+ DUMPBITS(t->bits) -+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? -+ "inflate: * literal '%c'\n" : -+ "inflate: * literal 0x%02x\n", t->base)); -+ *q++ = (Byte)t->base; -+ m--; -+ continue; -+ } -+ do { -+ DUMPBITS(t->bits) -+ if (e & 16) -+ { -+ /* get extra bits for length */ -+ e &= 15; -+ c = t->base + ((uInt)b & inflate_mask[e]); -+ DUMPBITS(e) -+ Tracevv((stderr, "inflate: * length %u\n", c)); -+ -+ /* decode distance base of block to copy */ -+ GRABBITS(15); /* max bits for distance code */ -+ e = (t = td + ((uInt)b & md))->exop; -+ do { -+ DUMPBITS(t->bits) -+ if (e & 16) -+ { -+ /* get extra bits to add to distance base */ -+ e &= 15; -+ GRABBITS(e) /* get extra bits (up to 13) */ -+ d = t->base + ((uInt)b & inflate_mask[e]); -+ DUMPBITS(e) -+ Tracevv((stderr, "inflate: * distance %u\n", d)); -+ -+ /* do the copy */ -+ m -= c; -+ r = q - d; -+ if (r < s->window) /* wrap if needed */ -+ { -+ do { -+ r += s->end - s->window; /* force pointer in window */ -+ } while (r < s->window); /* covers invalid distances */ -+ e = s->end - r; -+ if (c > e) -+ { -+ c -= e; /* wrapped copy */ -+ do { -+ *q++ = *r++; -+ } while (--e); -+ r = s->window; -+ do { -+ *q++ = *r++; -+ } while (--c); -+ } -+ else /* normal copy */ -+ { -+ *q++ = *r++; c--; -+ *q++ = *r++; c--; -+ do { -+ *q++ = *r++; -+ } while (--c); -+ } -+ } -+ else /* normal copy */ -+ { -+ *q++ = *r++; c--; -+ *q++ = *r++; c--; -+ do { -+ *q++ = *r++; -+ } while (--c); -+ } -+ break; -+ } -+ else if ((e & 64) == 0) -+ { -+ t += t->base; -+ e = (t += ((uInt)b & inflate_mask[e]))->exop; -+ } -+ else -+ { -+ z->msg = (char*)"invalid distance code"; -+ UNGRAB -+ UPDATE -+ return Z_DATA_ERROR; -+ } -+ } while (1); -+ break; -+ } -+ if ((e & 64) == 0) -+ { -+ t += t->base; -+ if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) -+ { -+ DUMPBITS(t->bits) -+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? -+ "inflate: * literal '%c'\n" : -+ "inflate: * literal 0x%02x\n", t->base)); -+ *q++ = (Byte)t->base; -+ m--; -+ break; -+ } -+ } -+ else if (e & 32) -+ { -+ Tracevv((stderr, "inflate: * end of block\n")); -+ UNGRAB -+ UPDATE -+ return Z_STREAM_END; -+ } -+ else -+ { -+ z->msg = (char*)"invalid literal/length code"; -+ UNGRAB -+ UPDATE -+ return Z_DATA_ERROR; -+ } -+ } while (1); -+ } while (m >= 258 && n >= 10); -+ -+ /* not enough input or output--restore pointers and return */ -+ UNGRAB -+ UPDATE -+ return Z_OK; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/inffast.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,22 @@ -+/* inffast.h -- header to use inffast.c -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+#ifndef _INFFAST_H -+#define _INFFAST_H -+ -+extern int inflate_fast OF(( -+ uInt, -+ uInt, -+ inflate_huft *, -+ inflate_huft *, -+ inflate_blocks_statef *, -+ z_streamp )); -+ -+#endif /* _INFFAST_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/inffixed.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,151 @@ -+/* inffixed.h -- table for decoding fixed codes -+ * Generated automatically by the maketree.c program -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+local uInt fixed_bl = 9; -+local uInt fixed_bd = 5; -+local inflate_huft fixed_tl[] = { -+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, -+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, -+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, -+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, -+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, -+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, -+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, -+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, -+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, -+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, -+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, -+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, -+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, -+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, -+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, -+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, -+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, -+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, -+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, -+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, -+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, -+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, -+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, -+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, -+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, -+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, -+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, -+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, -+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, -+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, -+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, -+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, -+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, -+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, -+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, -+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, -+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, -+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, -+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, -+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, -+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, -+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, -+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, -+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, -+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, -+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, -+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, -+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, -+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, -+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, -+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, -+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, -+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, -+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, -+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, -+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, -+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, -+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, -+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, -+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, -+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, -+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, -+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, -+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, -+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, -+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, -+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, -+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, -+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, -+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, -+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, -+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, -+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, -+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, -+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, -+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, -+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, -+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, -+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, -+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, -+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, -+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, -+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, -+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, -+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, -+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, -+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, -+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, -+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, -+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, -+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, -+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, -+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, -+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, -+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, -+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, -+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, -+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, -+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, -+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, -+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, -+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, -+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, -+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, -+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, -+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, -+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, -+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, -+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, -+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, -+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, -+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, -+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, -+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, -+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, -+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, -+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, -+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, -+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, -+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, -+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, -+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, -+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, -+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, -+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, -+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, -+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, -+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} -+ }; -+local inflate_huft fixed_td[] = { -+ {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, -+ {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, -+ {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, -+ {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, -+ {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, -+ {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, -+ {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, -+ {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} -+ }; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/inflate.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,368 @@ -+/* inflate.c -- zlib interface to inflate modules -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+#include -+#include "infblock.h" -+ -+struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ -+ -+typedef enum { -+ METHOD, /* waiting for method byte */ -+ FLAG, /* waiting for flag byte */ -+ DICT4, /* four dictionary check bytes to go */ -+ DICT3, /* three dictionary check bytes to go */ -+ DICT2, /* two dictionary check bytes to go */ -+ DICT1, /* one dictionary check byte to go */ -+ DICT0, /* waiting for inflateSetDictionary */ -+ BLOCKS, /* decompressing blocks */ -+ CHECK4, /* four check bytes to go */ -+ CHECK3, /* three check bytes to go */ -+ CHECK2, /* two check bytes to go */ -+ CHECK1, /* one check byte to go */ -+ DONE, /* finished check, done */ -+ BAD} /* got an error--stay here */ -+inflate_mode; -+ -+/* inflate private state */ -+struct internal_state { -+ -+ /* mode */ -+ inflate_mode mode; /* current inflate mode */ -+ -+ /* mode dependent information */ -+ union { -+ uInt method; /* if FLAGS, method byte */ -+ struct { -+ uLong was; /* computed check value */ -+ uLong need; /* stream check value */ -+ } check; /* if CHECK, check values to compare */ -+ uInt marker; /* if BAD, inflateSync's marker bytes count */ -+ } sub; /* submode */ -+ -+ /* mode independent information */ -+ int nowrap; /* flag for no wrapper */ -+ uInt wbits; /* log2(window size) (8..15, defaults to 15) */ -+ inflate_blocks_statef -+ *blocks; /* current inflate_blocks state */ -+ -+}; -+ -+ -+int ZEXPORT inflateReset(z) -+z_streamp z; -+{ -+ if (z == Z_NULL || z->state == Z_NULL) -+ return Z_STREAM_ERROR; -+ z->total_in = z->total_out = 0; -+ z->msg = Z_NULL; -+ z->state->mode = z->state->nowrap ? BLOCKS : METHOD; -+ inflate_blocks_reset(z->state->blocks, z, Z_NULL); -+ Tracev((stderr, "inflate: reset\n")); -+ return Z_OK; -+} -+ -+ -+int ZEXPORT inflateEnd(z) -+z_streamp z; -+{ -+ if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) -+ return Z_STREAM_ERROR; -+ if (z->state->blocks != Z_NULL) -+ inflate_blocks_free(z->state->blocks, z); -+ ZFREE(z, z->state); -+ z->state = Z_NULL; -+ Tracev((stderr, "inflate: end\n")); -+ return Z_OK; -+} -+ -+ -+int ZEXPORT inflateInit2_(z, w, version, stream_size) -+z_streamp z; -+int w; -+const char *version; -+int stream_size; -+{ -+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || -+ stream_size != sizeof(z_stream)) -+ return Z_VERSION_ERROR; -+ -+ /* initialize state */ -+ if (z == Z_NULL) -+ return Z_STREAM_ERROR; -+ z->msg = Z_NULL; -+ if (z->zalloc == Z_NULL) -+ { -+ return Z_STREAM_ERROR; -+/* z->zalloc = zcalloc; -+ z->opaque = (voidpf)0; -+*/ -+ } -+ if (z->zfree == Z_NULL) return Z_STREAM_ERROR; /* z->zfree = zcfree; */ -+ if ((z->state = (struct internal_state FAR *) -+ ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) -+ return Z_MEM_ERROR; -+ z->state->blocks = Z_NULL; -+ -+ /* handle undocumented nowrap option (no zlib header or check) */ -+ z->state->nowrap = 0; -+ if (w < 0) -+ { -+ w = - w; -+ z->state->nowrap = 1; -+ } -+ -+ /* set window size */ -+ if (w < 8 || w > 15) -+ { -+ inflateEnd(z); -+ return Z_STREAM_ERROR; -+ } -+ z->state->wbits = (uInt)w; -+ -+ /* create inflate_blocks state */ -+ if ((z->state->blocks = -+ inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) -+ == Z_NULL) -+ { -+ inflateEnd(z); -+ return Z_MEM_ERROR; -+ } -+ Tracev((stderr, "inflate: allocated\n")); -+ -+ /* reset state */ -+ inflateReset(z); -+ return Z_OK; -+} -+ -+ -+int ZEXPORT inflateInit_(z, version, stream_size) -+z_streamp z; -+const char *version; -+int stream_size; -+{ -+ return inflateInit2_(z, DEF_WBITS, version, stream_size); -+} -+ -+ -+#define NEEDBYTE {if(z->avail_in==0)return r;r=f;} -+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) -+ -+int ZEXPORT inflate(z, f) -+z_streamp z; -+int f; -+{ -+ int r; -+ uInt b; -+ -+ if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) -+ return Z_STREAM_ERROR; -+ f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; -+ r = Z_BUF_ERROR; -+ while (1) switch (z->state->mode) -+ { -+ case METHOD: -+ NEEDBYTE -+ if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) -+ { -+ z->state->mode = BAD; -+ z->msg = (char*)"unknown compression method"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ if ((z->state->sub.method >> 4) + 8 > z->state->wbits) -+ { -+ z->state->mode = BAD; -+ z->msg = (char*)"invalid window size"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ z->state->mode = FLAG; -+ case FLAG: -+ NEEDBYTE -+ b = NEXTBYTE; -+ if (((z->state->sub.method << 8) + b) % 31) -+ { -+ z->state->mode = BAD; -+ z->msg = (char*)"incorrect header check"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ Tracev((stderr, "inflate: zlib header ok\n")); -+ if (!(b & PRESET_DICT)) -+ { -+ z->state->mode = BLOCKS; -+ break; -+ } -+ z->state->mode = DICT4; -+ case DICT4: -+ NEEDBYTE -+ z->state->sub.check.need = (uLong)NEXTBYTE << 24; -+ z->state->mode = DICT3; -+ case DICT3: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE << 16; -+ z->state->mode = DICT2; -+ case DICT2: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE << 8; -+ z->state->mode = DICT1; -+ case DICT1: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE; -+ z->adler = z->state->sub.check.need; -+ z->state->mode = DICT0; -+ return Z_NEED_DICT; -+ case DICT0: -+ z->state->mode = BAD; -+ z->msg = (char*)"need dictionary"; -+ z->state->sub.marker = 0; /* can try inflateSync */ -+ return Z_STREAM_ERROR; -+ case BLOCKS: -+ r = inflate_blocks(z->state->blocks, z, r); -+ if (r == Z_DATA_ERROR) -+ { -+ z->state->mode = BAD; -+ z->state->sub.marker = 0; /* can try inflateSync */ -+ break; -+ } -+ if (r == Z_OK) -+ r = f; -+ if (r != Z_STREAM_END) -+ return r; -+ r = f; -+ inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); -+ if (z->state->nowrap) -+ { -+ z->state->mode = DONE; -+ break; -+ } -+ z->state->mode = CHECK4; -+ case CHECK4: -+ NEEDBYTE -+ z->state->sub.check.need = (uLong)NEXTBYTE << 24; -+ z->state->mode = CHECK3; -+ case CHECK3: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE << 16; -+ z->state->mode = CHECK2; -+ case CHECK2: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE << 8; -+ z->state->mode = CHECK1; -+ case CHECK1: -+ NEEDBYTE -+ z->state->sub.check.need += (uLong)NEXTBYTE; -+ -+ if (z->state->sub.check.was != z->state->sub.check.need) -+ { -+ z->state->mode = BAD; -+ z->msg = (char*)"incorrect data check"; -+ z->state->sub.marker = 5; /* can't try inflateSync */ -+ break; -+ } -+ Tracev((stderr, "inflate: zlib check ok\n")); -+ z->state->mode = DONE; -+ case DONE: -+ return Z_STREAM_END; -+ case BAD: -+ return Z_DATA_ERROR; -+ default: -+ return Z_STREAM_ERROR; -+ } -+#ifdef NEED_DUMMY_RETURN -+ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ -+#endif -+} -+ -+ -+int ZEXPORT inflateSetDictionary(z, dictionary, dictLength) -+z_streamp z; -+const Bytef *dictionary; -+uInt dictLength; -+{ -+ uInt length = dictLength; -+ -+ if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0) -+ return Z_STREAM_ERROR; -+ -+ if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR; -+ z->adler = 1L; -+ -+ if (length >= ((uInt)1<state->wbits)) -+ { -+ length = (1<state->wbits)-1; -+ dictionary += dictLength - length; -+ } -+ inflate_set_dictionary(z->state->blocks, dictionary, length); -+ z->state->mode = BLOCKS; -+ return Z_OK; -+} -+ -+ -+int ZEXPORT inflateSync(z) -+z_streamp z; -+{ -+ uInt n; /* number of bytes to look at */ -+ Bytef *p; /* pointer to bytes */ -+ uInt m; /* number of marker bytes found in a row */ -+ uLong r, w; /* temporaries to save total_in and total_out */ -+ -+ /* set up */ -+ if (z == Z_NULL || z->state == Z_NULL) -+ return Z_STREAM_ERROR; -+ if (z->state->mode != BAD) -+ { -+ z->state->mode = BAD; -+ z->state->sub.marker = 0; -+ } -+ if ((n = z->avail_in) == 0) -+ return Z_BUF_ERROR; -+ p = z->next_in; -+ m = z->state->sub.marker; -+ -+ /* search */ -+ while (n && m < 4) -+ { -+ static const Byte mark[4] = {0, 0, 0xff, 0xff}; -+ if (*p == mark[m]) -+ m++; -+ else if (*p) -+ m = 0; -+ else -+ m = 4 - m; -+ p++, n--; -+ } -+ -+ /* restore */ -+ z->total_in += p - z->next_in; -+ z->next_in = p; -+ z->avail_in = n; -+ z->state->sub.marker = m; -+ -+ /* return no joy or set up to restart on a new block */ -+ if (m != 4) -+ return Z_DATA_ERROR; -+ r = z->total_in; w = z->total_out; -+ inflateReset(z); -+ z->total_in = r; z->total_out = w; -+ z->state->mode = BLOCKS; -+ return Z_OK; -+} -+ -+ -+/* Returns true if inflate is currently at the end of a block generated -+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP -+ * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH -+ * but removes the length bytes of the resulting empty stored block. When -+ * decompressing, PPP checks that at the end of input packet, inflate is -+ * waiting for these length bytes. -+ */ -+int ZEXPORT inflateSyncPoint(z) -+z_streamp z; -+{ -+ if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL) -+ return Z_STREAM_ERROR; -+ return inflate_blocks_sync_point(z->state->blocks); -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/inftrees.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,454 @@ -+/* inftrees.c -- generate Huffman trees for efficient decoding -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+#include -+#include "inftrees.h" -+ -+#if !defined(BUILDFIXED) && !defined(STDC) -+# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */ -+#endif -+ -+local const char inflate_copyright[] = -+ " inflate 1.1.4 Copyright 1995-2002 Mark Adler "; -+/* -+ If you use the zlib library in a product, an acknowledgment is welcome -+ in the documentation of your product. If for some reason you cannot -+ include such an acknowledgment, I would appreciate that you keep this -+ copyright string in the executable of your product. -+ */ -+struct internal_state {int dummy;}; /* for buggy compilers */ -+ -+/* simplify the use of the inflate_huft type with some defines */ -+#define exop word.what.Exop -+#define bits word.what.Bits -+ -+ -+local int huft_build OF(( -+ uIntf *, /* code lengths in bits */ -+ uInt, /* number of codes */ -+ uInt, /* number of "simple" codes */ -+ const uIntf *, /* list of base values for non-simple codes */ -+ const uIntf *, /* list of extra bits for non-simple codes */ -+ inflate_huft * FAR*,/* result: starting table */ -+ uIntf *, /* maximum lookup bits (returns actual) */ -+ inflate_huft *, /* space for trees */ -+ uInt *, /* hufts used in space */ -+ uIntf * )); /* space for values */ -+ -+/* Tables for deflate from PKZIP's appnote.txt. */ -+local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ -+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, -+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; -+ /* see note #13 above about 258 */ -+local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ -+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, -+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ -+local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ -+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, -+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, -+ 8193, 12289, 16385, 24577}; -+local const uInt cpdext[30] = { /* Extra bits for distance codes */ -+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, -+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, -+ 12, 12, 13, 13}; -+ -+/* -+ Huffman code decoding is performed using a multi-level table lookup. -+ The fastest way to decode is to simply build a lookup table whose -+ size is determined by the longest code. However, the time it takes -+ to build this table can also be a factor if the data being decoded -+ is not very long. The most common codes are necessarily the -+ shortest codes, so those codes dominate the decoding time, and hence -+ the speed. The idea is you can have a shorter table that decodes the -+ shorter, more probable codes, and then point to subsidiary tables for -+ the longer codes. The time it costs to decode the longer codes is -+ then traded against the time it takes to make longer tables. -+ -+ This results of this trade are in the variables lbits and dbits -+ below. lbits is the number of bits the first level table for literal/ -+ length codes can decode in one step, and dbits is the same thing for -+ the distance codes. Subsequent tables are also less than or equal to -+ those sizes. These values may be adjusted either when all of the -+ codes are shorter than that, in which case the longest code length in -+ bits is used, or when the shortest code is *longer* than the requested -+ table size, in which case the length of the shortest code in bits is -+ used. -+ -+ There are two different values for the two tables, since they code a -+ different number of possibilities each. The literal/length table -+ codes 286 possible values, or in a flat code, a little over eight -+ bits. The distance table codes 30 possible values, or a little less -+ than five bits, flat. The optimum values for speed end up being -+ about one bit more than those, so lbits is 8+1 and dbits is 5+1. -+ The optimum values may differ though from machine to machine, and -+ possibly even between compilers. Your mileage may vary. -+ */ -+ -+ -+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ -+#define BMAX 15 /* maximum bit length of any code */ -+ -+local int huft_build(b, n, s, d, e, t, m, hp, hn, v) -+uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ -+uInt n; /* number of codes (assumed <= 288) */ -+uInt s; /* number of simple-valued codes (0..s-1) */ -+const uIntf *d; /* list of base values for non-simple codes */ -+const uIntf *e; /* list of extra bits for non-simple codes */ -+inflate_huft * FAR *t; /* result: starting table */ -+uIntf *m; /* maximum lookup bits, returns actual */ -+inflate_huft *hp; /* space for trees */ -+uInt *hn; /* hufts used in space */ -+uIntf *v; /* working area: values in order of bit length */ -+/* Given a list of code lengths and a maximum table size, make a set of -+ tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR -+ if the given code set is incomplete (the tables are still built in this -+ case), or Z_DATA_ERROR if the input is invalid. */ -+{ -+ -+ uInt a; /* counter for codes of length k */ -+ uInt c[BMAX+1]; /* bit length count table */ -+ uInt f; /* i repeats in table every f entries */ -+ int g; /* maximum code length */ -+ int h; /* table level */ -+ register uInt i; /* counter, current code */ -+ register uInt j; /* counter */ -+ register int k; /* number of bits in current code */ -+ int l; /* bits per table (returned in m) */ -+ uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ -+ register uIntf *p; /* pointer into c[], b[], or v[] */ -+ inflate_huft *q; /* points to current table */ -+ struct inflate_huft_s r; /* table entry for structure assignment */ -+ inflate_huft *u[BMAX]; /* table stack */ -+ register int w; /* bits before this table == (l * h) */ -+ uInt x[BMAX+1]; /* bit offsets, then code stack */ -+ uIntf *xp; /* pointer into x */ -+ int y; /* number of dummy codes added */ -+ uInt z; /* number of entries in current table */ -+ -+ -+ /* Generate counts for each bit length */ -+ p = c; -+#define C0 *p++ = 0; -+#define C2 C0 C0 C0 C0 -+#define C4 C2 C2 C2 C2 -+ C4 /* clear c[]--assume BMAX+1 is 16 */ -+ p = b; i = n; -+ do { -+ c[*p++]++; /* assume all entries <= BMAX */ -+ } while (--i); -+ if (c[0] == n) /* null input--all zero length codes */ -+ { -+ *t = (inflate_huft *)Z_NULL; -+ *m = 0; -+ return Z_OK; -+ } -+ -+ -+ /* Find minimum and maximum length, bound *m by those */ -+ l = *m; -+ for (j = 1; j <= BMAX; j++) -+ if (c[j]) -+ break; -+ k = j; /* minimum code length */ -+ if ((uInt)l < j) -+ l = j; -+ for (i = BMAX; i; i--) -+ if (c[i]) -+ break; -+ g = i; /* maximum code length */ -+ if ((uInt)l > i) -+ l = i; -+ *m = l; -+ -+ -+ /* Adjust last length count to fill out codes, if needed */ -+ for (y = 1 << j; j < i; j++, y <<= 1) -+ if ((y -= c[j]) < 0) -+ return Z_DATA_ERROR; -+ if ((y -= c[i]) < 0) -+ return Z_DATA_ERROR; -+ c[i] += y; -+ -+ -+ /* Generate starting offsets into the value table for each length */ -+ x[1] = j = 0; -+ p = c + 1; xp = x + 2; -+ while (--i) { /* note that i == g from above */ -+ *xp++ = (j += *p++); -+ } -+ -+ -+ /* Make a table of values in order of bit lengths */ -+ p = b; i = 0; -+ do { -+ if ((j = *p++) != 0) -+ v[x[j]++] = i; -+ } while (++i < n); -+ n = x[g]; /* set n to length of v */ -+ -+ -+ /* Generate the Huffman codes and for each, make the table entries */ -+ x[0] = i = 0; /* first Huffman code is zero */ -+ p = v; /* grab values in bit order */ -+ h = -1; /* no tables yet--level -1 */ -+ w = -l; /* bits decoded == (l * h) */ -+ u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ -+ q = (inflate_huft *)Z_NULL; /* ditto */ -+ z = 0; /* ditto */ -+ -+ /* go through the bit lengths (k already is bits in shortest code) */ -+ for (; k <= g; k++) -+ { -+ a = c[k]; -+ while (a--) -+ { -+ /* here i is the Huffman code of length k bits for value *p */ -+ /* make tables up to required level */ -+ while (k > w + l) -+ { -+ h++; -+ w += l; /* previous table always l bits */ -+ -+ /* compute minimum size table less than or equal to l bits */ -+ z = g - w; -+ z = z > (uInt)l ? l : z; /* table size upper limit */ -+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ -+ { /* too few codes for k-w bit table */ -+ f -= a + 1; /* deduct codes from patterns left */ -+ xp = c + k; -+ if (j < z) -+ while (++j < z) /* try smaller tables up to z bits */ -+ { -+ if ((f <<= 1) <= *++xp) -+ break; /* enough codes to use up j bits */ -+ f -= *xp; /* else deduct codes from patterns */ -+ } -+ } -+ z = 1 << j; /* table entries for j-bit table */ -+ -+ /* allocate new table */ -+ if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ -+ return Z_DATA_ERROR; /* overflow of MANY */ -+ u[h] = q = hp + *hn; -+ *hn += z; -+ -+ /* connect to last table, if there is one */ -+ if (h) -+ { -+ x[h] = i; /* save pattern for backing up */ -+ r.bits = (Byte)l; /* bits to dump before this table */ -+ r.exop = (Byte)j; /* bits in this table */ -+ j = i >> (w - l); -+ r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ -+ u[h-1][j] = r; /* connect to last table */ -+ } -+ else -+ *t = q; /* first table is returned result */ -+ } -+ -+ /* set up table entry in r */ -+ r.bits = (Byte)(k - w); -+ if (p >= v + n) -+ r.exop = 128 + 64; /* out of values--invalid code */ -+ else if (*p < s) -+ { -+ r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ -+ r.base = *p++; /* simple code is just the value */ -+ } -+ else -+ { -+ r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ -+ r.base = d[*p++ - s]; -+ } -+ -+ /* fill code-like entries with r */ -+ f = 1 << (k - w); -+ for (j = i >> w; j < z; j += f) -+ q[j] = r; -+ -+ /* backwards increment the k-bit code i */ -+ for (j = 1 << (k - 1); i & j; j >>= 1) -+ i ^= j; -+ i ^= j; -+ -+ /* backup over finished tables */ -+ mask = (1 << w) - 1; /* needed on HP, cc -O bug */ -+ while ((i & mask) != x[h]) -+ { -+ h--; /* don't need to update q */ -+ w -= l; -+ mask = (1 << w) - 1; -+ } -+ } -+ } -+ -+ -+ /* Return Z_BUF_ERROR if we were given an incomplete table */ -+ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; -+} -+ -+ -+int inflate_trees_bits(c, bb, tb, hp, z) -+uIntf *c; /* 19 code lengths */ -+uIntf *bb; /* bits tree desired/actual depth */ -+inflate_huft * FAR *tb; /* bits tree result */ -+inflate_huft *hp; /* space for trees */ -+z_streamp z; /* for messages */ -+{ -+ int r; -+ uInt hn = 0; /* hufts used in space */ -+ uIntf *v; /* work area for huft_build */ -+ -+ if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) -+ return Z_MEM_ERROR; -+ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, -+ tb, bb, hp, &hn, v); -+ if (r == Z_DATA_ERROR) -+ z->msg = (char*)"oversubscribed dynamic bit lengths tree"; -+ else if (r == Z_BUF_ERROR || *bb == 0) -+ { -+ z->msg = (char*)"incomplete dynamic bit lengths tree"; -+ r = Z_DATA_ERROR; -+ } -+ ZFREE(z, v); -+ return r; -+} -+ -+ -+int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z) -+uInt nl; /* number of literal/length codes */ -+uInt nd; /* number of distance codes */ -+uIntf *c; /* that many (total) code lengths */ -+uIntf *bl; /* literal desired/actual bit depth */ -+uIntf *bd; /* distance desired/actual bit depth */ -+inflate_huft * FAR *tl; /* literal/length tree result */ -+inflate_huft * FAR *td; /* distance tree result */ -+inflate_huft *hp; /* space for trees */ -+z_streamp z; /* for messages */ -+{ -+ int r; -+ uInt hn = 0; /* hufts used in space */ -+ uIntf *v; /* work area for huft_build */ -+ -+ /* allocate work area */ -+ if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) -+ return Z_MEM_ERROR; -+ -+ /* build literal/length tree */ -+ r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); -+ if (r != Z_OK || *bl == 0) -+ { -+ if (r == Z_DATA_ERROR) -+ z->msg = (char*)"oversubscribed literal/length tree"; -+ else if (r != Z_MEM_ERROR) -+ { -+ z->msg = (char*)"incomplete literal/length tree"; -+ r = Z_DATA_ERROR; -+ } -+ ZFREE(z, v); -+ return r; -+ } -+ -+ /* build distance tree */ -+ r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); -+ if (r != Z_OK || (*bd == 0 && nl > 257)) -+ { -+ if (r == Z_DATA_ERROR) -+ z->msg = (char*)"oversubscribed distance tree"; -+ else if (r == Z_BUF_ERROR) { -+#ifdef PKZIP_BUG_WORKAROUND -+ r = Z_OK; -+ } -+#else -+ z->msg = (char*)"incomplete distance tree"; -+ r = Z_DATA_ERROR; -+ } -+ else if (r != Z_MEM_ERROR) -+ { -+ z->msg = (char*)"empty distance tree with lengths"; -+ r = Z_DATA_ERROR; -+ } -+ ZFREE(z, v); -+ return r; -+#endif -+ } -+ -+ /* done */ -+ ZFREE(z, v); -+ return Z_OK; -+} -+ -+ -+/* build fixed tables only once--keep them here */ -+#ifdef BUILDFIXED -+local int fixed_built = 0; -+#define FIXEDH 544 /* number of hufts used by fixed tables */ -+local inflate_huft fixed_mem[FIXEDH]; -+local uInt fixed_bl; -+local uInt fixed_bd; -+local inflate_huft *fixed_tl; -+local inflate_huft *fixed_td; -+#else -+#include "inffixed.h" -+#endif -+ -+ -+int inflate_trees_fixed(bl, bd, tl, td, z) -+uIntf *bl; /* literal desired/actual bit depth */ -+uIntf *bd; /* distance desired/actual bit depth */ -+inflate_huft * FAR *tl; /* literal/length tree result */ -+inflate_huft * FAR *td; /* distance tree result */ -+z_streamp z; /* for memory allocation */ -+{ -+#ifdef BUILDFIXED -+ /* build fixed tables if not already */ -+ if (!fixed_built) -+ { -+ int k; /* temporary variable */ -+ uInt f = 0; /* number of hufts used in fixed_mem */ -+ uIntf *c; /* length list for huft_build */ -+ uIntf *v; /* work area for huft_build */ -+ -+ /* allocate memory */ -+ if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) -+ return Z_MEM_ERROR; -+ if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) -+ { -+ ZFREE(z, c); -+ return Z_MEM_ERROR; -+ } -+ -+ /* literal table */ -+ for (k = 0; k < 144; k++) -+ c[k] = 8; -+ for (; k < 256; k++) -+ c[k] = 9; -+ for (; k < 280; k++) -+ c[k] = 7; -+ for (; k < 288; k++) -+ c[k] = 8; -+ fixed_bl = 9; -+ huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, -+ fixed_mem, &f, v); -+ -+ /* distance table */ -+ for (k = 0; k < 30; k++) -+ c[k] = 5; -+ fixed_bd = 5; -+ huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, -+ fixed_mem, &f, v); -+ -+ /* done */ -+ ZFREE(z, v); -+ ZFREE(z, c); -+ fixed_built = 1; -+ } -+#endif -+ *bl = fixed_bl; -+ *bd = fixed_bd; -+ *tl = fixed_tl; -+ *td = fixed_td; -+ return Z_OK; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/inftrees.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,63 @@ -+/* inftrees.h -- header to use inftrees.c -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+/* Huffman code lookup table entry--this entry is four bytes for machines -+ that have 16-bit pointers (e.g. PC's in the small or medium model). */ -+ -+#ifndef _INFTREES_H -+#define _INFTREES_H -+ -+typedef struct inflate_huft_s FAR inflate_huft; -+ -+struct inflate_huft_s { -+ union { -+ struct { -+ Byte Exop; /* number of extra bits or operation */ -+ Byte Bits; /* number of bits in this code or subcode */ -+ } what; -+ uInt pad; /* pad structure to a power of 2 (4 bytes for */ -+ } word; /* 16-bit, 8 bytes for 32-bit int's) */ -+ uInt base; /* literal, length base, distance base, -+ or table offset */ -+}; -+ -+/* Maximum size of dynamic tree. The maximum found in a long but non- -+ exhaustive search was 1004 huft structures (850 for length/literals -+ and 154 for distances, the latter actually the result of an -+ exhaustive search). The actual maximum is not known, but the -+ value below is more than safe. */ -+#define MANY 1440 -+ -+extern int inflate_trees_bits OF(( -+ uIntf *, /* 19 code lengths */ -+ uIntf *, /* bits tree desired/actual depth */ -+ inflate_huft * FAR *, /* bits tree result */ -+ inflate_huft *, /* space for trees */ -+ z_streamp)); /* for messages */ -+ -+extern int inflate_trees_dynamic OF(( -+ uInt, /* number of literal/length codes */ -+ uInt, /* number of distance codes */ -+ uIntf *, /* that many (total) code lengths */ -+ uIntf *, /* literal desired/actual bit depth */ -+ uIntf *, /* distance desired/actual bit depth */ -+ inflate_huft * FAR *, /* literal/length tree result */ -+ inflate_huft * FAR *, /* distance tree result */ -+ inflate_huft *, /* space for trees */ -+ z_streamp)); /* for messages */ -+ -+extern int inflate_trees_fixed OF(( -+ uIntf *, /* literal desired/actual bit depth */ -+ uIntf *, /* distance desired/actual bit depth */ -+ inflate_huft * FAR *, /* literal/length tree result */ -+ inflate_huft * FAR *, /* distance tree result */ -+ z_streamp)); /* for memory allocation */ -+ -+#endif /* _INFTREES_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/infutil.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,87 @@ -+/* inflate_util.c -- data and routines common to blocks and codes -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+#include -+#include "infblock.h" -+#include "inftrees.h" -+#include "infcodes.h" -+#include "infutil.h" -+ -+struct inflate_codes_state {int dummy;}; /* for buggy compilers */ -+ -+/* And'ing with mask[n] masks the lower n bits */ -+uInt inflate_mask[17] = { -+ 0x0000, -+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, -+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -+}; -+ -+ -+/* copy as much as possible from the sliding window to the output area */ -+int inflate_flush(s, z, r) -+inflate_blocks_statef *s; -+z_streamp z; -+int r; -+{ -+ uInt n; -+ Bytef *p; -+ Bytef *q; -+ -+ /* local copies of source and destination pointers */ -+ p = z->next_out; -+ q = s->read; -+ -+ /* compute number of bytes to copy as far as end of window */ -+ n = (uInt)((q <= s->write ? s->write : s->end) - q); -+ if (n > z->avail_out) n = z->avail_out; -+ if (n && r == Z_BUF_ERROR) r = Z_OK; -+ -+ /* update counters */ -+ z->avail_out -= n; -+ z->total_out += n; -+ -+ /* update check information */ -+ if (s->checkfn != Z_NULL) -+ z->adler = s->check = (*s->checkfn)(s->check, q, n); -+ -+ /* copy as far as end of window */ -+ zmemcpy(p, q, n); -+ p += n; -+ q += n; -+ -+ /* see if more to copy at beginning of window */ -+ if (q == s->end) -+ { -+ /* wrap pointers */ -+ q = s->window; -+ if (s->write == s->end) -+ s->write = s->window; -+ -+ /* compute bytes to copy */ -+ n = (uInt)(s->write - q); -+ if (n > z->avail_out) n = z->avail_out; -+ if (n && r == Z_BUF_ERROR) r = Z_OK; -+ -+ /* update counters */ -+ z->avail_out -= n; -+ z->total_out += n; -+ -+ /* update check information */ -+ if (s->checkfn != Z_NULL) -+ z->adler = s->check = (*s->checkfn)(s->check, q, n); -+ -+ /* copy */ -+ zmemcpy(p, q, n); -+ p += n; -+ q += n; -+ } -+ -+ /* update pointers */ -+ z->next_out = p; -+ s->read = q; -+ -+ /* done */ -+ return r; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/infutil.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,98 @@ -+/* infutil.h -- types and macros common to blocks and codes -+ * Copyright (C) 1995-2002 Mark Adler -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* WARNING: this file should *not* be used by applications. It is -+ part of the implementation of the compression library and is -+ subject to change. Applications should only use zlib.h. -+ */ -+ -+#ifndef _INFUTIL_H -+#define _INFUTIL_H -+ -+typedef enum { -+ TYPE, /* get type bits (3, including end bit) */ -+ LENS, /* get lengths for stored */ -+ STORED, /* processing stored block */ -+ TABLE, /* get table lengths */ -+ BTREE, /* get bit lengths tree for a dynamic block */ -+ DTREE, /* get length, distance trees for a dynamic block */ -+ CODES, /* processing fixed or dynamic block */ -+ DRY, /* output remaining window bytes */ -+ DONE, /* finished last block, done */ -+ BAD} /* got a data error--stuck here */ -+inflate_block_mode; -+ -+/* inflate blocks semi-private state */ -+struct inflate_blocks_state { -+ -+ /* mode */ -+ inflate_block_mode mode; /* current inflate_block mode */ -+ -+ /* mode dependent information */ -+ union { -+ uInt left; /* if STORED, bytes left to copy */ -+ struct { -+ uInt table; /* table lengths (14 bits) */ -+ uInt index; /* index into blens (or border) */ -+ uIntf *blens; /* bit lengths of codes */ -+ uInt bb; /* bit length tree depth */ -+ inflate_huft *tb; /* bit length decoding tree */ -+ } trees; /* if DTREE, decoding info for trees */ -+ struct { -+ inflate_codes_statef -+ *codes; -+ } decode; /* if CODES, current state */ -+ } sub; /* submode */ -+ uInt last; /* true if this block is the last block */ -+ -+ /* mode independent information */ -+ uInt bitk; /* bits in bit buffer */ -+ uLong bitb; /* bit buffer */ -+ inflate_huft *hufts; /* single malloc for tree space */ -+ Bytef *window; /* sliding window */ -+ Bytef *end; /* one byte after sliding window */ -+ Bytef *read; /* window read pointer */ -+ Bytef *write; /* window write pointer */ -+ check_func checkfn; /* check function */ -+ uLong check; /* check on output */ -+ -+}; -+ -+ -+/* defines for inflate input/output */ -+/* update pointers and return */ -+#define UPDBITS {s->bitb=b;s->bitk=k;} -+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} -+#define UPDOUT {s->write=q;} -+#define UPDATE {UPDBITS UPDIN UPDOUT} -+#define LEAVE {UPDATE return inflate_flush(s,z,r);} -+/* get bytes and bits */ -+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} -+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} -+#define NEXTBYTE (n--,*p++) -+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} -+/* output bytes */ -+#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) -+#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} -+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} -+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} -+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} -+#define OUTBYTE(a) {*q++=(Byte)(a);m--;} -+/* load local pointers */ -+#define LOAD {LOADIN LOADOUT} -+ -+/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ -+extern uInt inflate_mask[17]; -+ -+/* copy as much as possible from the sliding window to the output area */ -+extern int inflate_flush OF(( -+ inflate_blocks_statef *, -+ z_streamp , -+ int)); -+ -+struct internal_state {int dummy;}; /* for buggy compilers */ -+ -+#endif /* _INFUTIL_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/match586.S Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,357 @@ -+/* match.s -- Pentium-optimized version of longest_match() -+ * Written for zlib 1.1.2 -+ * Copyright (C) 1998 Brian Raiter -+ * -+ * This is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License. -+ */ -+ -+#ifndef NO_UNDERLINE -+#define match_init _ipcomp_match_init -+#define longest_match _ipcomp_longest_match -+#else -+#define match_init ipcomp_match_init -+#define longest_match ipcomp_longest_match -+#endif -+ -+#define MAX_MATCH (258) -+#define MIN_MATCH (3) -+#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) -+#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) -+ -+/* stack frame offsets */ -+ -+#define wmask 0 /* local copy of s->wmask */ -+#define window 4 /* local copy of s->window */ -+#define windowbestlen 8 /* s->window + bestlen */ -+#define chainlenscanend 12 /* high word: current chain len */ -+ /* low word: last bytes sought */ -+#define scanstart 16 /* first two bytes of string */ -+#define scanalign 20 /* dword-misalignment of string */ -+#define nicematch 24 /* a good enough match size */ -+#define bestlen 28 /* size of best match so far */ -+#define scan 32 /* ptr to string wanting match */ -+ -+#define LocalVarsSize (36) -+/* saved ebx 36 */ -+/* saved edi 40 */ -+/* saved esi 44 */ -+/* saved ebp 48 */ -+/* return address 52 */ -+#define deflatestate 56 /* the function arguments */ -+#define curmatch 60 -+ -+/* Offsets for fields in the deflate_state structure. These numbers -+ * are calculated from the definition of deflate_state, with the -+ * assumption that the compiler will dword-align the fields. (Thus, -+ * changing the definition of deflate_state could easily cause this -+ * program to crash horribly, without so much as a warning at -+ * compile time. Sigh.) -+ */ -+#define dsWSize 36 -+#define dsWMask 44 -+#define dsWindow 48 -+#define dsPrev 56 -+#define dsMatchLen 88 -+#define dsPrevMatch 92 -+#define dsStrStart 100 -+#define dsMatchStart 104 -+#define dsLookahead 108 -+#define dsPrevLen 112 -+#define dsMaxChainLen 116 -+#define dsGoodMatch 132 -+#define dsNiceMatch 136 -+ -+ -+.file "match.S" -+ -+.globl match_init, longest_match -+ -+.text -+ -+/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ -+ -+longest_match: -+ -+/* Save registers that the compiler may be using, and adjust %esp to */ -+/* make room for our stack frame. */ -+ -+ pushl %ebp -+ pushl %edi -+ pushl %esi -+ pushl %ebx -+ subl $LocalVarsSize, %esp -+ -+/* Retrieve the function arguments. %ecx will hold cur_match */ -+/* throughout the entire function. %edx will hold the pointer to the */ -+/* deflate_state structure during the function's setup (before */ -+/* entering the main loop). */ -+ -+ movl deflatestate(%esp), %edx -+ movl curmatch(%esp), %ecx -+ -+/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ -+ -+ movl dsNiceMatch(%edx), %eax -+ movl dsLookahead(%edx), %ebx -+ cmpl %eax, %ebx -+ jl LookaheadLess -+ movl %eax, %ebx -+LookaheadLess: movl %ebx, nicematch(%esp) -+ -+/* register Bytef *scan = s->window + s->strstart; */ -+ -+ movl dsWindow(%edx), %esi -+ movl %esi, window(%esp) -+ movl dsStrStart(%edx), %ebp -+ lea (%esi,%ebp), %edi -+ movl %edi, scan(%esp) -+ -+/* Determine how many bytes the scan ptr is off from being */ -+/* dword-aligned. */ -+ -+ movl %edi, %eax -+ negl %eax -+ andl $3, %eax -+ movl %eax, scanalign(%esp) -+ -+/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ -+/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ -+ -+ movl dsWSize(%edx), %eax -+ subl $MIN_LOOKAHEAD, %eax -+ subl %eax, %ebp -+ jg LimitPositive -+ xorl %ebp, %ebp -+LimitPositive: -+ -+/* unsigned chain_length = s->max_chain_length; */ -+/* if (s->prev_length >= s->good_match) { */ -+/* chain_length >>= 2; */ -+/* } */ -+ -+ movl dsPrevLen(%edx), %eax -+ movl dsGoodMatch(%edx), %ebx -+ cmpl %ebx, %eax -+ movl dsMaxChainLen(%edx), %ebx -+ jl LastMatchGood -+ shrl $2, %ebx -+LastMatchGood: -+ -+/* chainlen is decremented once beforehand so that the function can */ -+/* use the sign flag instead of the zero flag for the exit test. */ -+/* It is then shifted into the high word, to make room for the scanend */ -+/* scanend value, which it will always accompany. */ -+ -+ decl %ebx -+ shll $16, %ebx -+ -+/* int best_len = s->prev_length; */ -+ -+ movl dsPrevLen(%edx), %eax -+ movl %eax, bestlen(%esp) -+ -+/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ -+ -+ addl %eax, %esi -+ movl %esi, windowbestlen(%esp) -+ -+/* register ush scan_start = *(ushf*)scan; */ -+/* register ush scan_end = *(ushf*)(scan+best_len-1); */ -+ -+ movw (%edi), %bx -+ movw %bx, scanstart(%esp) -+ movw -1(%edi,%eax), %bx -+ movl %ebx, chainlenscanend(%esp) -+ -+/* Posf *prev = s->prev; */ -+/* uInt wmask = s->w_mask; */ -+ -+ movl dsPrev(%edx), %edi -+ movl dsWMask(%edx), %edx -+ mov %edx, wmask(%esp) -+ -+/* Jump into the main loop. */ -+ -+ jmp LoopEntry -+ -+.balign 16 -+ -+/* do { -+ * match = s->window + cur_match; -+ * if (*(ushf*)(match+best_len-1) != scan_end || -+ * *(ushf*)match != scan_start) continue; -+ * [...] -+ * } while ((cur_match = prev[cur_match & wmask]) > limit -+ * && --chain_length != 0); -+ * -+ * Here is the inner loop of the function. The function will spend the -+ * majority of its time in this loop, and majority of that time will -+ * be spent in the first ten instructions. -+ * -+ * Within this loop: -+ * %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend) -+ * %ecx = curmatch -+ * %edx = curmatch & wmask -+ * %esi = windowbestlen - i.e., (window + bestlen) -+ * %edi = prev -+ * %ebp = limit -+ * -+ * Two optimization notes on the choice of instructions: -+ * -+ * The first instruction uses a 16-bit address, which costs an extra, -+ * unpairable cycle. This is cheaper than doing a 32-bit access and -+ * zeroing the high word, due to the 3-cycle misalignment penalty which -+ * would occur half the time. This also turns out to be cheaper than -+ * doing two separate 8-bit accesses, as the memory is so rarely in the -+ * L1 cache. -+ * -+ * The window buffer, however, apparently spends a lot of time in the -+ * cache, and so it is faster to retrieve the word at the end of the -+ * match string with two 8-bit loads. The instructions that test the -+ * word at the beginning of the match string, however, are executed -+ * much less frequently, and there it was cheaper to use 16-bit -+ * instructions, which avoided the necessity of saving off and -+ * subsequently reloading one of the other registers. -+ */ -+LookupLoop: -+ /* 1 U & V */ -+ movw (%edi,%edx,2), %cx /* 2 U pipe */ -+ movl wmask(%esp), %edx /* 2 V pipe */ -+ cmpl %ebp, %ecx /* 3 U pipe */ -+ jbe LeaveNow /* 3 V pipe */ -+ subl $0x00010000, %ebx /* 4 U pipe */ -+ js LeaveNow /* 4 V pipe */ -+LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */ -+ andl %ecx, %edx /* 5 V pipe */ -+ cmpb %bl, %al /* 6 U pipe */ -+ jnz LookupLoop /* 6 V pipe */ -+ movb (%esi,%ecx), %ah -+ cmpb %bh, %ah -+ jnz LookupLoop -+ movl window(%esp), %eax -+ movw (%eax,%ecx), %ax -+ cmpw scanstart(%esp), %ax -+ jnz LookupLoop -+ -+/* Store the current value of chainlen. */ -+ -+ movl %ebx, chainlenscanend(%esp) -+ -+/* Point %edi to the string under scrutiny, and %esi to the string we */ -+/* are hoping to match it up with. In actuality, %esi and %edi are */ -+/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ -+/* initialized to -(MAX_MATCH_8 - scanalign). */ -+ -+ movl window(%esp), %esi -+ movl scan(%esp), %edi -+ addl %ecx, %esi -+ movl scanalign(%esp), %eax -+ movl $(-MAX_MATCH_8), %edx -+ lea MAX_MATCH_8(%edi,%eax), %edi -+ lea MAX_MATCH_8(%esi,%eax), %esi -+ -+/* Test the strings for equality, 8 bytes at a time. At the end, -+ * adjust %edx so that it is offset to the exact byte that mismatched. -+ * -+ * We already know at this point that the first three bytes of the -+ * strings match each other, and they can be safely passed over before -+ * starting the compare loop. So what this code does is skip over 0-3 -+ * bytes, as much as necessary in order to dword-align the %edi -+ * pointer. (%esi will still be misaligned three times out of four.) -+ * -+ * It should be confessed that this loop usually does not represent -+ * much of the total running time. Replacing it with a more -+ * straightforward "rep cmpsb" would not drastically degrade -+ * performance. -+ */ -+LoopCmps: -+ movl (%esi,%edx), %eax -+ movl (%edi,%edx), %ebx -+ xorl %ebx, %eax -+ jnz LeaveLoopCmps -+ movl 4(%esi,%edx), %eax -+ movl 4(%edi,%edx), %ebx -+ xorl %ebx, %eax -+ jnz LeaveLoopCmps4 -+ addl $8, %edx -+ jnz LoopCmps -+ jmp LenMaximum -+LeaveLoopCmps4: addl $4, %edx -+LeaveLoopCmps: testl $0x0000FFFF, %eax -+ jnz LenLower -+ addl $2, %edx -+ shrl $16, %eax -+LenLower: subb $1, %al -+ adcl $0, %edx -+ -+/* Calculate the length of the match. If it is longer than MAX_MATCH, */ -+/* then automatically accept it as the best possible match and leave. */ -+ -+ lea (%edi,%edx), %eax -+ movl scan(%esp), %edi -+ subl %edi, %eax -+ cmpl $MAX_MATCH, %eax -+ jge LenMaximum -+ -+/* If the length of the match is not longer than the best match we */ -+/* have so far, then forget it and return to the lookup loop. */ -+ -+ movl deflatestate(%esp), %edx -+ movl bestlen(%esp), %ebx -+ cmpl %ebx, %eax -+ jg LongerMatch -+ movl chainlenscanend(%esp), %ebx -+ movl windowbestlen(%esp), %esi -+ movl dsPrev(%edx), %edi -+ movl wmask(%esp), %edx -+ andl %ecx, %edx -+ jmp LookupLoop -+ -+/* s->match_start = cur_match; */ -+/* best_len = len; */ -+/* if (len >= nice_match) break; */ -+/* scan_end = *(ushf*)(scan+best_len-1); */ -+ -+LongerMatch: movl nicematch(%esp), %ebx -+ movl %eax, bestlen(%esp) -+ movl %ecx, dsMatchStart(%edx) -+ cmpl %ebx, %eax -+ jge LeaveNow -+ movl window(%esp), %esi -+ addl %eax, %esi -+ movl %esi, windowbestlen(%esp) -+ movl chainlenscanend(%esp), %ebx -+ movw -1(%edi,%eax), %bx -+ movl dsPrev(%edx), %edi -+ movl %ebx, chainlenscanend(%esp) -+ movl wmask(%esp), %edx -+ andl %ecx, %edx -+ jmp LookupLoop -+ -+/* Accept the current string, with the maximum possible length. */ -+ -+LenMaximum: movl deflatestate(%esp), %edx -+ movl $MAX_MATCH, bestlen(%esp) -+ movl %ecx, dsMatchStart(%edx) -+ -+/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ -+/* return s->lookahead; */ -+ -+LeaveNow: -+ movl deflatestate(%esp), %edx -+ movl bestlen(%esp), %ebx -+ movl dsLookahead(%edx), %eax -+ cmpl %eax, %ebx -+ jg LookaheadRet -+ movl %ebx, %eax -+LookaheadRet: -+ -+/* Restore the stack and return from whence we came. */ -+ -+ addl $LocalVarsSize, %esp -+ popl %ebx -+ popl %esi -+ popl %edi -+ popl %ebp -+match_init: ret ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/match686.S Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,330 @@ -+/* match.s -- Pentium-Pro-optimized version of longest_match() -+ * Written for zlib 1.1.2 -+ * Copyright (C) 1998 Brian Raiter -+ * -+ * This is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License. -+ */ -+ -+#ifndef NO_UNDERLINE -+#define match_init _ipcomp_match_init -+#define longest_match _ipcomp_longest_match -+#else -+#define match_init ipcomp_match_init -+#define longest_match ipcomp_longest_match -+#endif -+ -+#define MAX_MATCH (258) -+#define MIN_MATCH (3) -+#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) -+#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) -+ -+/* stack frame offsets */ -+ -+#define chainlenwmask 0 /* high word: current chain len */ -+ /* low word: s->wmask */ -+#define window 4 /* local copy of s->window */ -+#define windowbestlen 8 /* s->window + bestlen */ -+#define scanstart 16 /* first two bytes of string */ -+#define scanend 12 /* last two bytes of string */ -+#define scanalign 20 /* dword-misalignment of string */ -+#define nicematch 24 /* a good enough match size */ -+#define bestlen 28 /* size of best match so far */ -+#define scan 32 /* ptr to string wanting match */ -+ -+#define LocalVarsSize (36) -+/* saved ebx 36 */ -+/* saved edi 40 */ -+/* saved esi 44 */ -+/* saved ebp 48 */ -+/* return address 52 */ -+#define deflatestate 56 /* the function arguments */ -+#define curmatch 60 -+ -+/* Offsets for fields in the deflate_state structure. These numbers -+ * are calculated from the definition of deflate_state, with the -+ * assumption that the compiler will dword-align the fields. (Thus, -+ * changing the definition of deflate_state could easily cause this -+ * program to crash horribly, without so much as a warning at -+ * compile time. Sigh.) -+ */ -+#define dsWSize 36 -+#define dsWMask 44 -+#define dsWindow 48 -+#define dsPrev 56 -+#define dsMatchLen 88 -+#define dsPrevMatch 92 -+#define dsStrStart 100 -+#define dsMatchStart 104 -+#define dsLookahead 108 -+#define dsPrevLen 112 -+#define dsMaxChainLen 116 -+#define dsGoodMatch 132 -+#define dsNiceMatch 136 -+ -+ -+.file "match.S" -+ -+.globl match_init, longest_match -+ -+.text -+ -+/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ -+ -+longest_match: -+ -+/* Save registers that the compiler may be using, and adjust %esp to */ -+/* make room for our stack frame. */ -+ -+ pushl %ebp -+ pushl %edi -+ pushl %esi -+ pushl %ebx -+ subl $LocalVarsSize, %esp -+ -+/* Retrieve the function arguments. %ecx will hold cur_match */ -+/* throughout the entire function. %edx will hold the pointer to the */ -+/* deflate_state structure during the function's setup (before */ -+/* entering the main loop). */ -+ -+ movl deflatestate(%esp), %edx -+ movl curmatch(%esp), %ecx -+ -+/* uInt wmask = s->w_mask; */ -+/* unsigned chain_length = s->max_chain_length; */ -+/* if (s->prev_length >= s->good_match) { */ -+/* chain_length >>= 2; */ -+/* } */ -+ -+ movl dsPrevLen(%edx), %eax -+ movl dsGoodMatch(%edx), %ebx -+ cmpl %ebx, %eax -+ movl dsWMask(%edx), %eax -+ movl dsMaxChainLen(%edx), %ebx -+ jl LastMatchGood -+ shrl $2, %ebx -+LastMatchGood: -+ -+/* chainlen is decremented once beforehand so that the function can */ -+/* use the sign flag instead of the zero flag for the exit test. */ -+/* It is then shifted into the high word, to make room for the wmask */ -+/* value, which it will always accompany. */ -+ -+ decl %ebx -+ shll $16, %ebx -+ orl %eax, %ebx -+ movl %ebx, chainlenwmask(%esp) -+ -+/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ -+ -+ movl dsNiceMatch(%edx), %eax -+ movl dsLookahead(%edx), %ebx -+ cmpl %eax, %ebx -+ jl LookaheadLess -+ movl %eax, %ebx -+LookaheadLess: movl %ebx, nicematch(%esp) -+ -+/* register Bytef *scan = s->window + s->strstart; */ -+ -+ movl dsWindow(%edx), %esi -+ movl %esi, window(%esp) -+ movl dsStrStart(%edx), %ebp -+ lea (%esi,%ebp), %edi -+ movl %edi, scan(%esp) -+ -+/* Determine how many bytes the scan ptr is off from being */ -+/* dword-aligned. */ -+ -+ movl %edi, %eax -+ negl %eax -+ andl $3, %eax -+ movl %eax, scanalign(%esp) -+ -+/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ -+/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ -+ -+ movl dsWSize(%edx), %eax -+ subl $MIN_LOOKAHEAD, %eax -+ subl %eax, %ebp -+ jg LimitPositive -+ xorl %ebp, %ebp -+LimitPositive: -+ -+/* int best_len = s->prev_length; */ -+ -+ movl dsPrevLen(%edx), %eax -+ movl %eax, bestlen(%esp) -+ -+/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ -+ -+ addl %eax, %esi -+ movl %esi, windowbestlen(%esp) -+ -+/* register ush scan_start = *(ushf*)scan; */ -+/* register ush scan_end = *(ushf*)(scan+best_len-1); */ -+/* Posf *prev = s->prev; */ -+ -+ movzwl (%edi), %ebx -+ movl %ebx, scanstart(%esp) -+ movzwl -1(%edi,%eax), %ebx -+ movl %ebx, scanend(%esp) -+ movl dsPrev(%edx), %edi -+ -+/* Jump into the main loop. */ -+ -+ movl chainlenwmask(%esp), %edx -+ jmp LoopEntry -+ -+.balign 16 -+ -+/* do { -+ * match = s->window + cur_match; -+ * if (*(ushf*)(match+best_len-1) != scan_end || -+ * *(ushf*)match != scan_start) continue; -+ * [...] -+ * } while ((cur_match = prev[cur_match & wmask]) > limit -+ * && --chain_length != 0); -+ * -+ * Here is the inner loop of the function. The function will spend the -+ * majority of its time in this loop, and majority of that time will -+ * be spent in the first ten instructions. -+ * -+ * Within this loop: -+ * %ebx = scanend -+ * %ecx = curmatch -+ * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) -+ * %esi = windowbestlen - i.e., (window + bestlen) -+ * %edi = prev -+ * %ebp = limit -+ */ -+LookupLoop: -+ andl %edx, %ecx -+ movzwl (%edi,%ecx,2), %ecx -+ cmpl %ebp, %ecx -+ jbe LeaveNow -+ subl $0x00010000, %edx -+ js LeaveNow -+LoopEntry: movzwl -1(%esi,%ecx), %eax -+ cmpl %ebx, %eax -+ jnz LookupLoop -+ movl window(%esp), %eax -+ movzwl (%eax,%ecx), %eax -+ cmpl scanstart(%esp), %eax -+ jnz LookupLoop -+ -+/* Store the current value of chainlen. */ -+ -+ movl %edx, chainlenwmask(%esp) -+ -+/* Point %edi to the string under scrutiny, and %esi to the string we */ -+/* are hoping to match it up with. In actuality, %esi and %edi are */ -+/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ -+/* initialized to -(MAX_MATCH_8 - scanalign). */ -+ -+ movl window(%esp), %esi -+ movl scan(%esp), %edi -+ addl %ecx, %esi -+ movl scanalign(%esp), %eax -+ movl $(-MAX_MATCH_8), %edx -+ lea MAX_MATCH_8(%edi,%eax), %edi -+ lea MAX_MATCH_8(%esi,%eax), %esi -+ -+/* Test the strings for equality, 8 bytes at a time. At the end, -+ * adjust %edx so that it is offset to the exact byte that mismatched. -+ * -+ * We already know at this point that the first three bytes of the -+ * strings match each other, and they can be safely passed over before -+ * starting the compare loop. So what this code does is skip over 0-3 -+ * bytes, as much as necessary in order to dword-align the %edi -+ * pointer. (%esi will still be misaligned three times out of four.) -+ * -+ * It should be confessed that this loop usually does not represent -+ * much of the total running time. Replacing it with a more -+ * straightforward "rep cmpsb" would not drastically degrade -+ * performance. -+ */ -+LoopCmps: -+ movl (%esi,%edx), %eax -+ xorl (%edi,%edx), %eax -+ jnz LeaveLoopCmps -+ movl 4(%esi,%edx), %eax -+ xorl 4(%edi,%edx), %eax -+ jnz LeaveLoopCmps4 -+ addl $8, %edx -+ jnz LoopCmps -+ jmp LenMaximum -+LeaveLoopCmps4: addl $4, %edx -+LeaveLoopCmps: testl $0x0000FFFF, %eax -+ jnz LenLower -+ addl $2, %edx -+ shrl $16, %eax -+LenLower: subb $1, %al -+ adcl $0, %edx -+ -+/* Calculate the length of the match. If it is longer than MAX_MATCH, */ -+/* then automatically accept it as the best possible match and leave. */ -+ -+ lea (%edi,%edx), %eax -+ movl scan(%esp), %edi -+ subl %edi, %eax -+ cmpl $MAX_MATCH, %eax -+ jge LenMaximum -+ -+/* If the length of the match is not longer than the best match we */ -+/* have so far, then forget it and return to the lookup loop. */ -+ -+ movl deflatestate(%esp), %edx -+ movl bestlen(%esp), %ebx -+ cmpl %ebx, %eax -+ jg LongerMatch -+ movl windowbestlen(%esp), %esi -+ movl dsPrev(%edx), %edi -+ movl scanend(%esp), %ebx -+ movl chainlenwmask(%esp), %edx -+ jmp LookupLoop -+ -+/* s->match_start = cur_match; */ -+/* best_len = len; */ -+/* if (len >= nice_match) break; */ -+/* scan_end = *(ushf*)(scan+best_len-1); */ -+ -+LongerMatch: movl nicematch(%esp), %ebx -+ movl %eax, bestlen(%esp) -+ movl %ecx, dsMatchStart(%edx) -+ cmpl %ebx, %eax -+ jge LeaveNow -+ movl window(%esp), %esi -+ addl %eax, %esi -+ movl %esi, windowbestlen(%esp) -+ movzwl -1(%edi,%eax), %ebx -+ movl dsPrev(%edx), %edi -+ movl %ebx, scanend(%esp) -+ movl chainlenwmask(%esp), %edx -+ jmp LookupLoop -+ -+/* Accept the current string, with the maximum possible length. */ -+ -+LenMaximum: movl deflatestate(%esp), %edx -+ movl $MAX_MATCH, bestlen(%esp) -+ movl %ecx, dsMatchStart(%edx) -+ -+/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ -+/* return s->lookahead; */ -+ -+LeaveNow: -+ movl deflatestate(%esp), %edx -+ movl bestlen(%esp), %ebx -+ movl dsLookahead(%edx), %eax -+ cmpl %eax, %ebx -+ jg LookaheadRet -+ movl %ebx, %eax -+LookaheadRet: -+ -+/* Restore the stack and return from whence we came. */ -+ -+ addl $LocalVarsSize, %esp -+ popl %ebx -+ popl %esi -+ popl %edi -+ popl %ebp -+match_init: ret ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/trees.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1214 @@ -+/* trees.c -- output deflated data using Huffman coding -+ * Copyright (C) 1995-2002 Jean-loup Gailly -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* -+ * ALGORITHM -+ * -+ * The "deflation" process uses several Huffman trees. The more -+ * common source values are represented by shorter bit sequences. -+ * -+ * Each code tree is stored in a compressed form which is itself -+ * a Huffman encoding of the lengths of all the code strings (in -+ * ascending order by source values). The actual code strings are -+ * reconstructed from the lengths in the inflate process, as described -+ * in the deflate specification. -+ * -+ * REFERENCES -+ * -+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". -+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc -+ * -+ * Storer, James A. -+ * Data Compression: Methods and Theory, pp. 49-50. -+ * Computer Science Press, 1988. ISBN 0-7167-8156-5. -+ * -+ * Sedgewick, R. -+ * Algorithms, p290. -+ * Addison-Wesley, 1983. ISBN 0-201-06672-6. -+ */ -+ -+/* @(#) $Id$ */ -+ -+/* #define GEN_TREES_H */ -+ -+#include "deflate.h" -+ -+#ifdef DEBUG -+# include -+#endif -+ -+/* =========================================================================== -+ * Constants -+ */ -+ -+#define MAX_BL_BITS 7 -+/* Bit length codes must not exceed MAX_BL_BITS bits */ -+ -+#define END_BLOCK 256 -+/* end of block literal code */ -+ -+#define REP_3_6 16 -+/* repeat previous bit length 3-6 times (2 bits of repeat count) */ -+ -+#define REPZ_3_10 17 -+/* repeat a zero length 3-10 times (3 bits of repeat count) */ -+ -+#define REPZ_11_138 18 -+/* repeat a zero length 11-138 times (7 bits of repeat count) */ -+ -+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ -+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; -+ -+local const int extra_dbits[D_CODES] /* extra bits for each distance code */ -+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; -+ -+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ -+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; -+ -+local const uch bl_order[BL_CODES] -+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; -+/* The lengths of the bit length codes are sent in order of decreasing -+ * probability, to avoid transmitting the lengths for unused bit length codes. -+ */ -+ -+#define Buf_size (8 * 2*sizeof(char)) -+/* Number of bits used within bi_buf. (bi_buf might be implemented on -+ * more than 16 bits on some systems.) -+ */ -+ -+/* =========================================================================== -+ * Local data. These are initialized only once. -+ */ -+ -+#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ -+ -+#if defined(GEN_TREES_H) || !defined(STDC) -+/* non ANSI compilers may not accept trees.h */ -+ -+local ct_data static_ltree[L_CODES+2]; -+/* The static literal tree. Since the bit lengths are imposed, there is no -+ * need for the L_CODES extra codes used during heap construction. However -+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init -+ * below). -+ */ -+ -+local ct_data static_dtree[D_CODES]; -+/* The static distance tree. (Actually a trivial tree since all codes use -+ * 5 bits.) -+ */ -+ -+uch _dist_code[DIST_CODE_LEN]; -+/* Distance codes. The first 256 values correspond to the distances -+ * 3 .. 258, the last 256 values correspond to the top 8 bits of -+ * the 15 bit distances. -+ */ -+ -+uch _length_code[MAX_MATCH-MIN_MATCH+1]; -+/* length code for each normalized match length (0 == MIN_MATCH) */ -+ -+local int base_length[LENGTH_CODES]; -+/* First normalized length for each code (0 = MIN_MATCH) */ -+ -+local int base_dist[D_CODES]; -+/* First normalized distance for each code (0 = distance of 1) */ -+ -+#else -+# include "trees.h" -+#endif /* GEN_TREES_H */ -+ -+struct static_tree_desc_s { -+ const ct_data *static_tree; /* static tree or NULL */ -+ const intf *extra_bits; /* extra bits for each code or NULL */ -+ int extra_base; /* base index for extra_bits */ -+ int elems; /* max number of elements in the tree */ -+ int max_length; /* max bit length for the codes */ -+}; -+ -+local static_tree_desc static_l_desc = -+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; -+ -+local static_tree_desc static_d_desc = -+{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; -+ -+local static_tree_desc static_bl_desc = -+{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; -+ -+/* =========================================================================== -+ * Local (static) routines in this file. -+ */ -+ -+local void tr_static_init OF((void)); -+local void init_block OF((deflate_state *s)); -+local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); -+local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); -+local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); -+local void build_tree OF((deflate_state *s, tree_desc *desc)); -+local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); -+local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); -+local int build_bl_tree OF((deflate_state *s)); -+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, -+ int blcodes)); -+local void compress_block OF((deflate_state *s, const ct_data *ltree, -+ const ct_data *dtree)); -+local void set_data_type OF((deflate_state *s)); -+local unsigned bi_reverse OF((unsigned value, int length)); -+local void bi_windup OF((deflate_state *s)); -+local void bi_flush OF((deflate_state *s)); -+local void copy_block OF((deflate_state *s, charf *buf, unsigned len, -+ int header)); -+ -+#ifdef GEN_TREES_H -+local void gen_trees_header OF((void)); -+#endif -+ -+#ifndef DEBUG -+# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) -+ /* Send a code of the given tree. c and tree must not have side effects */ -+ -+#else /* DEBUG */ -+# define send_code(s, c, tree) \ -+ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ -+ send_bits(s, tree[c].Code, tree[c].Len); } -+#endif -+ -+/* =========================================================================== -+ * Output a short LSB first on the stream. -+ * IN assertion: there is enough room in pendingBuf. -+ */ -+#define put_short(s, w) { \ -+ put_byte(s, (uch)((w) & 0xff)); \ -+ put_byte(s, (uch)((ush)(w) >> 8)); \ -+} -+ -+/* =========================================================================== -+ * Send a value on a given number of bits. -+ * IN assertion: length <= 16 and value fits in length bits. -+ */ -+#ifdef DEBUG -+local void send_bits OF((deflate_state *s, int value, int length)); -+ -+local void send_bits(s, value, length) -+ deflate_state *s; -+ int value; /* value to send */ -+ int length; /* number of bits */ -+{ -+ Tracevv((stderr," l %2d v %4x ", length, value)); -+ Assert(length > 0 && length <= 15, "invalid length"); -+ s->bits_sent += (ulg)length; -+ -+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and -+ * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) -+ * unused bits in value. -+ */ -+ if (s->bi_valid > (int)Buf_size - length) { -+ s->bi_buf |= (value << s->bi_valid); -+ put_short(s, s->bi_buf); -+ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); -+ s->bi_valid += length - Buf_size; -+ } else { -+ s->bi_buf |= value << s->bi_valid; -+ s->bi_valid += length; -+ } -+} -+#else /* !DEBUG */ -+ -+#define send_bits(s, value, length) \ -+{ int len = length;\ -+ if (s->bi_valid > (int)Buf_size - len) {\ -+ int val = value;\ -+ s->bi_buf |= (val << s->bi_valid);\ -+ put_short(s, s->bi_buf);\ -+ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ -+ s->bi_valid += len - Buf_size;\ -+ } else {\ -+ s->bi_buf |= (value) << s->bi_valid;\ -+ s->bi_valid += len;\ -+ }\ -+} -+#endif /* DEBUG */ -+ -+ -+#define MAX(a,b) (a >= b ? a : b) -+/* the arguments must not have side effects */ -+ -+/* =========================================================================== -+ * Initialize the various 'constant' tables. -+ */ -+local void tr_static_init() -+{ -+#if defined(GEN_TREES_H) || !defined(STDC) -+ static int static_init_done = 0; -+ int n; /* iterates over tree elements */ -+ int bits; /* bit counter */ -+ int length; /* length value */ -+ int code; /* code value */ -+ int dist; /* distance index */ -+ ush bl_count[MAX_BITS+1]; -+ /* number of codes at each bit length for an optimal tree */ -+ -+ if (static_init_done) return; -+ -+ /* For some embedded targets, global variables are not initialized: */ -+ static_l_desc.static_tree = static_ltree; -+ static_l_desc.extra_bits = extra_lbits; -+ static_d_desc.static_tree = static_dtree; -+ static_d_desc.extra_bits = extra_dbits; -+ static_bl_desc.extra_bits = extra_blbits; -+ -+ /* Initialize the mapping length (0..255) -> length code (0..28) */ -+ length = 0; -+ for (code = 0; code < LENGTH_CODES-1; code++) { -+ base_length[code] = length; -+ for (n = 0; n < (1< dist code (0..29) */ -+ dist = 0; -+ for (code = 0 ; code < 16; code++) { -+ base_dist[code] = dist; -+ for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ -+ for ( ; code < D_CODES; code++) { -+ base_dist[code] = dist << 7; -+ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { -+ _dist_code[256 + dist++] = (uch)code; -+ } -+ } -+ Assert (dist == 256, "tr_static_init: 256+dist != 512"); -+ -+ /* Construct the codes of the static literal tree */ -+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; -+ n = 0; -+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; -+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; -+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; -+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; -+ /* Codes 286 and 287 do not exist, but we must include them in the -+ * tree construction to get a canonical Huffman tree (longest code -+ * all ones) -+ */ -+ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); -+ -+ /* The static distance tree is trivial: */ -+ for (n = 0; n < D_CODES; n++) { -+ static_dtree[n].Len = 5; -+ static_dtree[n].Code = bi_reverse((unsigned)n, 5); -+ } -+ static_init_done = 1; -+ -+# ifdef GEN_TREES_H -+ gen_trees_header(); -+# endif -+#endif /* defined(GEN_TREES_H) || !defined(STDC) */ -+} -+ -+/* =========================================================================== -+ * Genererate the file trees.h describing the static trees. -+ */ -+#ifdef GEN_TREES_H -+# ifndef DEBUG -+# include -+# endif -+ -+# define SEPARATOR(i, last, width) \ -+ ((i) == (last)? "\n};\n\n" : \ -+ ((i) % (width) == (width)-1 ? ",\n" : ", ")) -+ -+void gen_trees_header() -+{ -+ FILE *header = fopen("trees.h", "w"); -+ int i; -+ -+ Assert (header != NULL, "Can't open trees.h"); -+ fprintf(header, -+ "/* header created automatically with -DGEN_TREES_H */\n\n"); -+ -+ fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); -+ for (i = 0; i < L_CODES+2; i++) { -+ fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, -+ static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); -+ } -+ -+ fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); -+ for (i = 0; i < D_CODES; i++) { -+ fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, -+ static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); -+ } -+ -+ fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); -+ for (i = 0; i < DIST_CODE_LEN; i++) { -+ fprintf(header, "%2u%s", _dist_code[i], -+ SEPARATOR(i, DIST_CODE_LEN-1, 20)); -+ } -+ -+ fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); -+ for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { -+ fprintf(header, "%2u%s", _length_code[i], -+ SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); -+ } -+ -+ fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); -+ for (i = 0; i < LENGTH_CODES; i++) { -+ fprintf(header, "%1u%s", base_length[i], -+ SEPARATOR(i, LENGTH_CODES-1, 20)); -+ } -+ -+ fprintf(header, "local const int base_dist[D_CODES] = {\n"); -+ for (i = 0; i < D_CODES; i++) { -+ fprintf(header, "%5u%s", base_dist[i], -+ SEPARATOR(i, D_CODES-1, 10)); -+ } -+ -+ fclose(header); -+} -+#endif /* GEN_TREES_H */ -+ -+/* =========================================================================== -+ * Initialize the tree data structures for a new zlib stream. -+ */ -+void _tr_init(s) -+ deflate_state *s; -+{ -+ tr_static_init(); -+ -+ s->l_desc.dyn_tree = s->dyn_ltree; -+ s->l_desc.stat_desc = &static_l_desc; -+ -+ s->d_desc.dyn_tree = s->dyn_dtree; -+ s->d_desc.stat_desc = &static_d_desc; -+ -+ s->bl_desc.dyn_tree = s->bl_tree; -+ s->bl_desc.stat_desc = &static_bl_desc; -+ -+ s->bi_buf = 0; -+ s->bi_valid = 0; -+ s->last_eob_len = 8; /* enough lookahead for inflate */ -+#ifdef DEBUG -+ s->compressed_len = 0L; -+ s->bits_sent = 0L; -+#endif -+ -+ /* Initialize the first block of the first file: */ -+ init_block(s); -+} -+ -+/* =========================================================================== -+ * Initialize a new block. -+ */ -+local void init_block(s) -+ deflate_state *s; -+{ -+ int n; /* iterates over tree elements */ -+ -+ /* Initialize the trees. */ -+ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; -+ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; -+ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; -+ -+ s->dyn_ltree[END_BLOCK].Freq = 1; -+ s->opt_len = s->static_len = 0L; -+ s->last_lit = s->matches = 0; -+} -+ -+#define SMALLEST 1 -+/* Index within the heap array of least frequent node in the Huffman tree */ -+ -+ -+/* =========================================================================== -+ * Remove the smallest element from the heap and recreate the heap with -+ * one less element. Updates heap and heap_len. -+ */ -+#define pqremove(s, tree, top) \ -+{\ -+ top = s->heap[SMALLEST]; \ -+ s->heap[SMALLEST] = s->heap[s->heap_len--]; \ -+ pqdownheap(s, tree, SMALLEST); \ -+} -+ -+/* =========================================================================== -+ * Compares to subtrees, using the tree depth as tie breaker when -+ * the subtrees have equal frequency. This minimizes the worst case length. -+ */ -+#define smaller(tree, n, m, depth) \ -+ (tree[n].Freq < tree[m].Freq || \ -+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) -+ -+/* =========================================================================== -+ * Restore the heap property by moving down the tree starting at node k, -+ * exchanging a node with the smallest of its two sons if necessary, stopping -+ * when the heap property is re-established (each father smaller than its -+ * two sons). -+ */ -+local void pqdownheap(s, tree, k) -+ deflate_state *s; -+ ct_data *tree; /* the tree to restore */ -+ int k; /* node to move down */ -+{ -+ int v = s->heap[k]; -+ int j = k << 1; /* left son of k */ -+ while (j <= s->heap_len) { -+ /* Set j to the smallest of the two sons: */ -+ if (j < s->heap_len && -+ smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { -+ j++; -+ } -+ /* Exit if v is smaller than both sons */ -+ if (smaller(tree, v, s->heap[j], s->depth)) break; -+ -+ /* Exchange v with the smallest son */ -+ s->heap[k] = s->heap[j]; k = j; -+ -+ /* And continue down the tree, setting j to the left son of k */ -+ j <<= 1; -+ } -+ s->heap[k] = v; -+} -+ -+/* =========================================================================== -+ * Compute the optimal bit lengths for a tree and update the total bit length -+ * for the current block. -+ * IN assertion: the fields freq and dad are set, heap[heap_max] and -+ * above are the tree nodes sorted by increasing frequency. -+ * OUT assertions: the field len is set to the optimal bit length, the -+ * array bl_count contains the frequencies for each bit length. -+ * The length opt_len is updated; static_len is also updated if stree is -+ * not null. -+ */ -+local void gen_bitlen(s, desc) -+ deflate_state *s; -+ tree_desc *desc; /* the tree descriptor */ -+{ -+ ct_data *tree = desc->dyn_tree; -+ int max_code = desc->max_code; -+ const ct_data *stree = desc->stat_desc->static_tree; -+ const intf *extra = desc->stat_desc->extra_bits; -+ int base = desc->stat_desc->extra_base; -+ int max_length = desc->stat_desc->max_length; -+ int h; /* heap index */ -+ int n, m; /* iterate over the tree elements */ -+ int bits; /* bit length */ -+ int xbits; /* extra bits */ -+ ush f; /* frequency */ -+ int overflow = 0; /* number of elements with bit length too large */ -+ -+ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; -+ -+ /* In a first pass, compute the optimal bit lengths (which may -+ * overflow in the case of the bit length tree). -+ */ -+ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ -+ -+ for (h = s->heap_max+1; h < HEAP_SIZE; h++) { -+ n = s->heap[h]; -+ bits = tree[tree[n].Dad].Len + 1; -+ if (bits > max_length) bits = max_length, overflow++; -+ tree[n].Len = (ush)bits; -+ /* We overwrite tree[n].Dad which is no longer needed */ -+ -+ if (n > max_code) continue; /* not a leaf node */ -+ -+ s->bl_count[bits]++; -+ xbits = 0; -+ if (n >= base) xbits = extra[n-base]; -+ f = tree[n].Freq; -+ s->opt_len += (ulg)f * (bits + xbits); -+ if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); -+ } -+ if (overflow == 0) return; -+ -+ Trace((stderr,"\nbit length overflow\n")); -+ /* This happens for example on obj2 and pic of the Calgary corpus */ -+ -+ /* Find the first bit length which could increase: */ -+ do { -+ bits = max_length-1; -+ while (s->bl_count[bits] == 0) bits--; -+ s->bl_count[bits]--; /* move one leaf down the tree */ -+ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ -+ s->bl_count[max_length]--; -+ /* The brother of the overflow item also moves one step up, -+ * but this does not affect bl_count[max_length] -+ */ -+ overflow -= 2; -+ } while (overflow > 0); -+ -+ /* Now recompute all bit lengths, scanning in increasing frequency. -+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all -+ * lengths instead of fixing only the wrong ones. This idea is taken -+ * from 'ar' written by Haruhiko Okumura.) -+ */ -+ for (bits = max_length; bits != 0; bits--) { -+ n = s->bl_count[bits]; -+ while (n != 0) { -+ m = s->heap[--h]; -+ if (m > max_code) continue; -+ if (tree[m].Len != (unsigned) bits) { -+ Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); -+ s->opt_len += ((long)bits - (long)tree[m].Len) -+ *(long)tree[m].Freq; -+ tree[m].Len = (ush)bits; -+ } -+ n--; -+ } -+ } -+} -+ -+/* =========================================================================== -+ * Generate the codes for a given tree and bit counts (which need not be -+ * optimal). -+ * IN assertion: the array bl_count contains the bit length statistics for -+ * the given tree and the field len is set for all tree elements. -+ * OUT assertion: the field code is set for all tree elements of non -+ * zero code length. -+ */ -+local void gen_codes (tree, max_code, bl_count) -+ ct_data *tree; /* the tree to decorate */ -+ int max_code; /* largest code with non zero frequency */ -+ ushf *bl_count; /* number of codes at each bit length */ -+{ -+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */ -+ ush code = 0; /* running code value */ -+ int bits; /* bit index */ -+ int n; /* code index */ -+ -+ /* The distribution counts are first used to generate the code values -+ * without bit reversal. -+ */ -+ for (bits = 1; bits <= MAX_BITS; bits++) { -+ next_code[bits] = code = (code + bl_count[bits-1]) << 1; -+ } -+ /* Check that the bit counts in bl_count are consistent. The last code -+ * must be all ones. -+ */ -+ Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; -+ const ct_data *stree = desc->stat_desc->static_tree; -+ int elems = desc->stat_desc->elems; -+ int n, m; /* iterate over heap elements */ -+ int max_code = -1; /* largest code with non zero frequency */ -+ int node; /* new node being created */ -+ -+ /* Construct the initial heap, with least frequent element in -+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. -+ * heap[0] is not used. -+ */ -+ s->heap_len = 0, s->heap_max = HEAP_SIZE; -+ -+ for (n = 0; n < elems; n++) { -+ if (tree[n].Freq != 0) { -+ s->heap[++(s->heap_len)] = max_code = n; -+ s->depth[n] = 0; -+ } else { -+ tree[n].Len = 0; -+ } -+ } -+ -+ /* The pkzip format requires that at least one distance code exists, -+ * and that at least one bit should be sent even if there is only one -+ * possible code. So to avoid special checks later on we force at least -+ * two codes of non zero frequency. -+ */ -+ while (s->heap_len < 2) { -+ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); -+ tree[node].Freq = 1; -+ s->depth[node] = 0; -+ s->opt_len--; if (stree) s->static_len -= stree[node].Len; -+ /* node is 0 or 1 so it does not have extra bits */ -+ } -+ desc->max_code = max_code; -+ -+ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, -+ * establish sub-heaps of increasing lengths: -+ */ -+ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); -+ -+ /* Construct the Huffman tree by repeatedly combining the least two -+ * frequent nodes. -+ */ -+ node = elems; /* next internal node of the tree */ -+ do { -+ pqremove(s, tree, n); /* n = node of least frequency */ -+ m = s->heap[SMALLEST]; /* m = node of next least frequency */ -+ -+ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ -+ s->heap[--(s->heap_max)] = m; -+ -+ /* Create a new node father of n and m */ -+ tree[node].Freq = tree[n].Freq + tree[m].Freq; -+ s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); -+ tree[n].Dad = tree[m].Dad = (ush)node; -+#ifdef DUMP_BL_TREE -+ if (tree == s->bl_tree) { -+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", -+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); -+ } -+#endif -+ /* and insert the new node in the heap */ -+ s->heap[SMALLEST] = node++; -+ pqdownheap(s, tree, SMALLEST); -+ -+ } while (s->heap_len >= 2); -+ -+ s->heap[--(s->heap_max)] = s->heap[SMALLEST]; -+ -+ /* At this point, the fields freq and dad are set. We can now -+ * generate the bit lengths. -+ */ -+ gen_bitlen(s, (tree_desc *)desc); -+ -+ /* The field len is now set, we can generate the bit codes */ -+ gen_codes ((ct_data *)tree, max_code, s->bl_count); -+} -+ -+/* =========================================================================== -+ * Scan a literal or distance tree to determine the frequencies of the codes -+ * in the bit length tree. -+ */ -+local void scan_tree (s, tree, max_code) -+ deflate_state *s; -+ ct_data *tree; /* the tree to be scanned */ -+ int max_code; /* and its largest code of non zero frequency */ -+{ -+ int n; /* iterates over all tree elements */ -+ int prevlen = -1; /* last emitted length */ -+ int curlen; /* length of current code */ -+ int nextlen = tree[0].Len; /* length of next code */ -+ int count = 0; /* repeat count of the current code */ -+ int max_count = 7; /* max repeat count */ -+ int min_count = 4; /* min repeat count */ -+ -+ if (nextlen == 0) max_count = 138, min_count = 3; -+ tree[max_code+1].Len = (ush)0xffff; /* guard */ -+ -+ for (n = 0; n <= max_code; n++) { -+ curlen = nextlen; nextlen = tree[n+1].Len; -+ if (++count < max_count && curlen == nextlen) { -+ continue; -+ } else if (count < min_count) { -+ s->bl_tree[curlen].Freq += count; -+ } else if (curlen != 0) { -+ if (curlen != prevlen) s->bl_tree[curlen].Freq++; -+ s->bl_tree[REP_3_6].Freq++; -+ } else if (count <= 10) { -+ s->bl_tree[REPZ_3_10].Freq++; -+ } else { -+ s->bl_tree[REPZ_11_138].Freq++; -+ } -+ count = 0; prevlen = curlen; -+ if (nextlen == 0) { -+ max_count = 138, min_count = 3; -+ } else if (curlen == nextlen) { -+ max_count = 6, min_count = 3; -+ } else { -+ max_count = 7, min_count = 4; -+ } -+ } -+} -+ -+/* =========================================================================== -+ * Send a literal or distance tree in compressed form, using the codes in -+ * bl_tree. -+ */ -+local void send_tree (s, tree, max_code) -+ deflate_state *s; -+ ct_data *tree; /* the tree to be scanned */ -+ int max_code; /* and its largest code of non zero frequency */ -+{ -+ int n; /* iterates over all tree elements */ -+ int prevlen = -1; /* last emitted length */ -+ int curlen; /* length of current code */ -+ int nextlen = tree[0].Len; /* length of next code */ -+ int count = 0; /* repeat count of the current code */ -+ int max_count = 7; /* max repeat count */ -+ int min_count = 4; /* min repeat count */ -+ -+ /* tree[max_code+1].Len = -1; */ /* guard already set */ -+ if (nextlen == 0) max_count = 138, min_count = 3; -+ -+ for (n = 0; n <= max_code; n++) { -+ curlen = nextlen; nextlen = tree[n+1].Len; -+ if (++count < max_count && curlen == nextlen) { -+ continue; -+ } else if (count < min_count) { -+ do { send_code(s, curlen, s->bl_tree); } while (--count != 0); -+ -+ } else if (curlen != 0) { -+ if (curlen != prevlen) { -+ send_code(s, curlen, s->bl_tree); count--; -+ } -+ Assert(count >= 3 && count <= 6, " 3_6?"); -+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); -+ -+ } else if (count <= 10) { -+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); -+ -+ } else { -+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); -+ } -+ count = 0; prevlen = curlen; -+ if (nextlen == 0) { -+ max_count = 138, min_count = 3; -+ } else if (curlen == nextlen) { -+ max_count = 6, min_count = 3; -+ } else { -+ max_count = 7, min_count = 4; -+ } -+ } -+} -+ -+/* =========================================================================== -+ * Construct the Huffman tree for the bit lengths and return the index in -+ * bl_order of the last bit length code to send. -+ */ -+local int build_bl_tree(s) -+ deflate_state *s; -+{ -+ int max_blindex; /* index of last bit length code of non zero freq */ -+ -+ /* Determine the bit length frequencies for literal and distance trees */ -+ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); -+ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); -+ -+ /* Build the bit length tree: */ -+ build_tree(s, (tree_desc *)(&(s->bl_desc))); -+ /* opt_len now includes the length of the tree representations, except -+ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. -+ */ -+ -+ /* Determine the number of bit length codes to send. The pkzip format -+ * requires that at least 4 bit length codes be sent. (appnote.txt says -+ * 3 but the actual value used is 4.) -+ */ -+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { -+ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; -+ } -+ /* Update opt_len to include the bit length tree and counts */ -+ s->opt_len += 3*(max_blindex+1) + 5+5+4; -+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", -+ s->opt_len, s->static_len)); -+ -+ return max_blindex; -+} -+ -+/* =========================================================================== -+ * Send the header for a block using dynamic Huffman trees: the counts, the -+ * lengths of the bit length codes, the literal tree and the distance tree. -+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. -+ */ -+local void send_all_trees(s, lcodes, dcodes, blcodes) -+ deflate_state *s; -+ int lcodes, dcodes, blcodes; /* number of codes for each tree */ -+{ -+ int rank; /* index in bl_order */ -+ -+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); -+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, -+ "too many codes"); -+ Tracev((stderr, "\nbl counts: ")); -+ send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ -+ send_bits(s, dcodes-1, 5); -+ send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ -+ for (rank = 0; rank < blcodes; rank++) { -+ Tracev((stderr, "\nbl code %2d ", bl_order[rank])); -+ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); -+ } -+ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); -+ -+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ -+ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); -+ -+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ -+ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -+} -+ -+/* =========================================================================== -+ * Send a stored block -+ */ -+void _tr_stored_block(s, buf, stored_len, eof) -+ deflate_state *s; -+ charf *buf; /* input block */ -+ ulg stored_len; /* length of input block */ -+ int eof; /* true if this is the last block for a file */ -+{ -+ send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ -+#ifdef DEBUG -+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; -+ s->compressed_len += (stored_len + 4) << 3; -+#endif -+ copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ -+} -+ -+/* =========================================================================== -+ * Send one empty static block to give enough lookahead for inflate. -+ * This takes 10 bits, of which 7 may remain in the bit buffer. -+ * The current inflate code requires 9 bits of lookahead. If the -+ * last two codes for the previous block (real code plus EOB) were coded -+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode -+ * the last real code. In this case we send two empty static blocks instead -+ * of one. (There are no problems if the previous block is stored or fixed.) -+ * To simplify the code, we assume the worst case of last real code encoded -+ * on one bit only. -+ */ -+void _tr_align(s) -+ deflate_state *s; -+{ -+ send_bits(s, STATIC_TREES<<1, 3); -+ send_code(s, END_BLOCK, static_ltree); -+#ifdef DEBUG -+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ -+#endif -+ bi_flush(s); -+ /* Of the 10 bits for the empty block, we have already sent -+ * (10 - bi_valid) bits. The lookahead for the last real code (before -+ * the EOB of the previous block) was thus at least one plus the length -+ * of the EOB plus what we have just sent of the empty static block. -+ */ -+ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { -+ send_bits(s, STATIC_TREES<<1, 3); -+ send_code(s, END_BLOCK, static_ltree); -+#ifdef DEBUG -+ s->compressed_len += 10L; -+#endif -+ bi_flush(s); -+ } -+ s->last_eob_len = 7; -+} -+ -+/* =========================================================================== -+ * Determine the best encoding for the current block: dynamic trees, static -+ * trees or store, and output the encoded block to the zip file. -+ */ -+void _tr_flush_block(s, buf, stored_len, eof) -+ deflate_state *s; -+ charf *buf; /* input block, or NULL if too old */ -+ ulg stored_len; /* length of input block */ -+ int eof; /* true if this is the last block for a file */ -+{ -+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ -+ int max_blindex = 0; /* index of last bit length code of non zero freq */ -+ -+ /* Build the Huffman trees unless a stored block is forced */ -+ if (s->level > 0) { -+ -+ /* Check if the file is ascii or binary */ -+ if (s->data_type == Z_UNKNOWN) set_data_type(s); -+ -+ /* Construct the literal and distance trees */ -+ build_tree(s, (tree_desc *)(&(s->l_desc))); -+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, -+ s->static_len)); -+ -+ build_tree(s, (tree_desc *)(&(s->d_desc))); -+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, -+ s->static_len)); -+ /* At this point, opt_len and static_len are the total bit lengths of -+ * the compressed block data, excluding the tree representations. -+ */ -+ -+ /* Build the bit length tree for the above two trees, and get the index -+ * in bl_order of the last bit length code to send. -+ */ -+ max_blindex = build_bl_tree(s); -+ -+ /* Determine the best encoding. Compute first the block length in bytes*/ -+ opt_lenb = (s->opt_len+3+7)>>3; -+ static_lenb = (s->static_len+3+7)>>3; -+ -+ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", -+ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, -+ s->last_lit)); -+ -+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb; -+ -+ } else { -+ Assert(buf != (char*)0, "lost buf"); -+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ -+ } -+ -+#ifdef FORCE_STORED -+ if (buf != (char*)0) { /* force stored block */ -+#else -+ if (stored_len+4 <= opt_lenb && buf != (char*)0) { -+ /* 4: two words for the lengths */ -+#endif -+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. -+ * Otherwise we can't have processed more than WSIZE input bytes since -+ * the last block flush, because compression would have been -+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to -+ * transform a block into a stored block. -+ */ -+ _tr_stored_block(s, buf, stored_len, eof); -+ -+#ifdef FORCE_STATIC -+ } else if (static_lenb >= 0) { /* force static trees */ -+#else -+ } else if (static_lenb == opt_lenb) { -+#endif -+ send_bits(s, (STATIC_TREES<<1)+eof, 3); -+ compress_block(s, static_ltree, static_dtree); -+#ifdef DEBUG -+ s->compressed_len += 3 + s->static_len; -+#endif -+ } else { -+ send_bits(s, (DYN_TREES<<1)+eof, 3); -+ send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, -+ max_blindex+1); -+ compress_block(s, s->dyn_ltree, s->dyn_dtree); -+#ifdef DEBUG -+ s->compressed_len += 3 + s->opt_len; -+#endif -+ } -+ Assert (s->compressed_len == s->bits_sent, "bad compressed size"); -+ /* The above check is made mod 2^32, for files larger than 512 MB -+ * and uLong implemented on 32 bits. -+ */ -+ init_block(s); -+ -+ if (eof) { -+ bi_windup(s); -+#ifdef DEBUG -+ s->compressed_len += 7; /* align on byte boundary */ -+#endif -+ } -+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, -+ s->compressed_len-7*eof)); -+} -+ -+/* =========================================================================== -+ * Save the match info and tally the frequency counts. Return true if -+ * the current block must be flushed. -+ */ -+int _tr_tally (s, dist, lc) -+ deflate_state *s; -+ unsigned dist; /* distance of matched string */ -+ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -+{ -+ s->d_buf[s->last_lit] = (ush)dist; -+ s->l_buf[s->last_lit++] = (uch)lc; -+ if (dist == 0) { -+ /* lc is the unmatched char */ -+ s->dyn_ltree[lc].Freq++; -+ } else { -+ s->matches++; -+ /* Here, lc is the match length - MIN_MATCH */ -+ dist--; /* dist = match distance - 1 */ -+ Assert((ush)dist < (ush)MAX_DIST(s) && -+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && -+ (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); -+ -+ s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; -+ s->dyn_dtree[d_code(dist)].Freq++; -+ } -+ -+#ifdef TRUNCATE_BLOCK -+ /* Try to guess if it is profitable to stop the current block here */ -+ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { -+ /* Compute an upper bound for the compressed length */ -+ ulg out_length = (ulg)s->last_lit*8L; -+ ulg in_length = (ulg)((long)s->strstart - s->block_start); -+ int dcode; -+ for (dcode = 0; dcode < D_CODES; dcode++) { -+ out_length += (ulg)s->dyn_dtree[dcode].Freq * -+ (5L+extra_dbits[dcode]); -+ } -+ out_length >>= 3; -+ Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", -+ s->last_lit, in_length, out_length, -+ 100L - out_length*100L/in_length)); -+ if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; -+ } -+#endif -+ return (s->last_lit == s->lit_bufsize-1); -+ /* We avoid equality with lit_bufsize because of wraparound at 64K -+ * on 16 bit machines and because stored blocks are restricted to -+ * 64K-1 bytes. -+ */ -+} -+ -+/* =========================================================================== -+ * Send the block data compressed using the given Huffman trees -+ */ -+local void compress_block(s, ltree, dtree) -+ deflate_state *s; -+ const ct_data *ltree; /* literal tree */ -+ const ct_data *dtree; /* distance tree */ -+{ -+ unsigned dist; /* distance of matched string */ -+ int lc; /* match length or unmatched char (if dist == 0) */ -+ unsigned lx = 0; /* running index in l_buf */ -+ unsigned code; /* the code to send */ -+ int extra; /* number of extra bits to send */ -+ -+ if (s->last_lit != 0) do { -+ dist = s->d_buf[lx]; -+ lc = s->l_buf[lx++]; -+ if (dist == 0) { -+ send_code(s, lc, ltree); /* send a literal byte */ -+ Tracecv(isgraph(lc), (stderr," '%c' ", lc)); -+ } else { -+ /* Here, lc is the match length - MIN_MATCH */ -+ code = _length_code[lc]; -+ send_code(s, code+LITERALS+1, ltree); /* send the length code */ -+ extra = extra_lbits[code]; -+ if (extra != 0) { -+ lc -= base_length[code]; -+ send_bits(s, lc, extra); /* send the extra length bits */ -+ } -+ dist--; /* dist is now the match distance - 1 */ -+ code = d_code(dist); -+ Assert (code < D_CODES, "bad d_code"); -+ -+ send_code(s, code, dtree); /* send the distance code */ -+ extra = extra_dbits[code]; -+ if (extra != 0) { -+ dist -= base_dist[code]; -+ send_bits(s, dist, extra); /* send the extra distance bits */ -+ } -+ } /* literal or match pair ? */ -+ -+ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ -+ Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); -+ -+ } while (lx < s->last_lit); -+ -+ send_code(s, END_BLOCK, ltree); -+ s->last_eob_len = ltree[END_BLOCK].Len; -+} -+ -+/* =========================================================================== -+ * Set the data type to ASCII or BINARY, using a crude approximation: -+ * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. -+ * IN assertion: the fields freq of dyn_ltree are set and the total of all -+ * frequencies does not exceed 64K (to fit in an int on 16 bit machines). -+ */ -+local void set_data_type(s) -+ deflate_state *s; -+{ -+ int n = 0; -+ unsigned ascii_freq = 0; -+ unsigned bin_freq = 0; -+ while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; -+ while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; -+ while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; -+ s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); -+} -+ -+/* =========================================================================== -+ * Reverse the first len bits of a code, using straightforward code (a faster -+ * method would use a table) -+ * IN assertion: 1 <= len <= 15 -+ */ -+local unsigned bi_reverse(code, len) -+ unsigned code; /* the value to invert */ -+ int len; /* its bit length */ -+{ -+ register unsigned res = 0; -+ do { -+ res |= code & 1; -+ code >>= 1, res <<= 1; -+ } while (--len > 0); -+ return res >> 1; -+} -+ -+/* =========================================================================== -+ * Flush the bit buffer, keeping at most 7 bits in it. -+ */ -+local void bi_flush(s) -+ deflate_state *s; -+{ -+ if (s->bi_valid == 16) { -+ put_short(s, s->bi_buf); -+ s->bi_buf = 0; -+ s->bi_valid = 0; -+ } else if (s->bi_valid >= 8) { -+ put_byte(s, (Byte)s->bi_buf); -+ s->bi_buf >>= 8; -+ s->bi_valid -= 8; -+ } -+} -+ -+/* =========================================================================== -+ * Flush the bit buffer and align the output on a byte boundary -+ */ -+local void bi_windup(s) -+ deflate_state *s; -+{ -+ if (s->bi_valid > 8) { -+ put_short(s, s->bi_buf); -+ } else if (s->bi_valid > 0) { -+ put_byte(s, (Byte)s->bi_buf); -+ } -+ s->bi_buf = 0; -+ s->bi_valid = 0; -+#ifdef DEBUG -+ s->bits_sent = (s->bits_sent+7) & ~7; -+#endif -+} -+ -+/* =========================================================================== -+ * Copy a stored block, storing first the length and its -+ * one's complement if requested. -+ */ -+local void copy_block(s, buf, len, header) -+ deflate_state *s; -+ charf *buf; /* the input data */ -+ unsigned len; /* its length */ -+ int header; /* true if block header must be written */ -+{ -+ bi_windup(s); /* align on byte boundary */ -+ s->last_eob_len = 8; /* enough lookahead for inflate */ -+ -+ if (header) { -+ put_short(s, (ush)len); -+ put_short(s, (ush)~len); -+#ifdef DEBUG -+ s->bits_sent += 2*16; -+#endif -+ } -+#ifdef DEBUG -+ s->bits_sent += (ulg)len<<3; -+#endif -+ while (len--) { -+ put_byte(s, *buf++); -+ } -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/trees.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,128 @@ -+/* header created automatically with -DGEN_TREES_H */ -+ -+local const ct_data static_ltree[L_CODES+2] = { -+{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, -+{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, -+{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, -+{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, -+{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, -+{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, -+{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, -+{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, -+{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, -+{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, -+{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, -+{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, -+{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, -+{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, -+{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, -+{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, -+{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, -+{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, -+{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, -+{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, -+{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, -+{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, -+{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, -+{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, -+{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, -+{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, -+{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, -+{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, -+{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, -+{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, -+{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, -+{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, -+{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, -+{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, -+{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, -+{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, -+{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, -+{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, -+{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, -+{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, -+{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, -+{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, -+{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, -+{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, -+{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, -+{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, -+{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, -+{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, -+{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, -+{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, -+{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, -+{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, -+{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, -+{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, -+{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, -+{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, -+{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, -+{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} -+}; -+ -+local const ct_data static_dtree[D_CODES] = { -+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, -+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, -+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, -+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, -+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, -+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} -+}; -+ -+const uch _dist_code[DIST_CODE_LEN] = { -+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, -+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, -+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, -+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, -+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, -+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, -+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, -+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, -+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, -+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, -+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 -+}; -+ -+const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { -+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, -+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, -+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, -+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, -+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, -+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, -+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, -+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 -+}; -+ -+local const int base_length[LENGTH_CODES] = { -+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, -+64, 80, 96, 112, 128, 160, 192, 224, 0 -+}; -+ -+local const int base_dist[D_CODES] = { -+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, -+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, -+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 -+}; -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/zconf.h Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,309 @@ -+/* zconf.h -- configuration of the zlib compression library -+ * Copyright (C) 1995-2002 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* @(#) $Id$ */ -+ -+#ifndef _ZCONF_H -+#define _ZCONF_H -+ -+/* -+ * If you *really* need a unique prefix for all types and library functions, -+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. -+ */ -+#ifdef IPCOMP_PREFIX -+# define deflateInit_ ipcomp_deflateInit_ -+# define deflate ipcomp_deflate -+# define deflateEnd ipcomp_deflateEnd -+# define inflateInit_ ipcomp_inflateInit_ -+# define inflate ipcomp_inflate -+# define inflateEnd ipcomp_inflateEnd -+# define deflateInit2_ ipcomp_deflateInit2_ -+# define deflateSetDictionary ipcomp_deflateSetDictionary -+# define deflateCopy ipcomp_deflateCopy -+# define deflateReset ipcomp_deflateReset -+# define deflateParams ipcomp_deflateParams -+# define inflateInit2_ ipcomp_inflateInit2_ -+# define inflateSetDictionary ipcomp_inflateSetDictionary -+# define inflateSync ipcomp_inflateSync -+# define inflateSyncPoint ipcomp_inflateSyncPoint -+# define inflateReset ipcomp_inflateReset -+# define compress ipcomp_compress -+# define compress2 ipcomp_compress2 -+# define uncompress ipcomp_uncompress -+# define adler32 ipcomp_adler32 -+# define crc32 ipcomp_crc32 -+# define get_crc_table ipcomp_get_crc_table -+/* SSS: these also need to be prefixed to avoid clash with ppp_deflate and ext2compression */ -+# define inflate_blocks ipcomp_deflate_blocks -+# define inflate_blocks_free ipcomp_deflate_blocks_free -+# define inflate_blocks_new ipcomp_inflate_blocks_new -+# define inflate_blocks_reset ipcomp_inflate_blocks_reset -+# define inflate_blocks_sync_point ipcomp_inflate_blocks_sync_point -+# define inflate_set_dictionary ipcomp_inflate_set_dictionary -+# define inflate_codes ipcomp_inflate_codes -+# define inflate_codes_free ipcomp_inflate_codes_free -+# define inflate_codes_new ipcomp_inflate_codes_new -+# define inflate_fast ipcomp_inflate_fast -+# define inflate_trees_bits ipcomp_inflate_trees_bits -+# define inflate_trees_dynamic ipcomp_inflate_trees_dynamic -+# define inflate_trees_fixed ipcomp_inflate_trees_fixed -+# define inflate_flush ipcomp_inflate_flush -+# define inflate_mask ipcomp_inflate_mask -+# define _dist_code _ipcomp_dist_code -+# define _length_code _ipcomp_length_code -+# define _tr_align _ipcomp_tr_align -+# define _tr_flush_block _ipcomp_tr_flush_block -+# define _tr_init _ipcomp_tr_init -+# define _tr_stored_block _ipcomp_tr_stored_block -+# define _tr_tally _ipcomp_tr_tally -+# define zError ipcomp_zError -+# define z_errmsg ipcomp_z_errmsg -+# define zlibVersion ipcomp_zlibVersion -+# define match_init ipcomp_match_init -+# define longest_match ipcomp_longest_match -+#endif -+ -+#ifdef Z_PREFIX -+# define Byte z_Byte -+# define uInt z_uInt -+# define uLong z_uLong -+# define Bytef z_Bytef -+# define charf z_charf -+# define intf z_intf -+# define uIntf z_uIntf -+# define uLongf z_uLongf -+# define voidpf z_voidpf -+# define voidp z_voidp -+#endif -+ -+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) -+# define WIN32 -+#endif -+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) -+# ifndef __32BIT__ -+# define __32BIT__ -+# endif -+#endif -+#if defined(__MSDOS__) && !defined(MSDOS) -+# define MSDOS -+#endif -+ -+/* -+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more -+ * than 64k bytes at a time (needed on systems with 16-bit int). -+ */ -+#if defined(MSDOS) && !defined(__32BIT__) -+# define MAXSEG_64K -+#endif -+#ifdef MSDOS -+# define UNALIGNED_OK -+#endif -+ -+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) -+# define STDC -+#endif -+#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) -+# ifndef STDC -+# define STDC -+# endif -+#endif -+ -+#ifndef STDC -+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -+# define const -+# endif -+#endif -+ -+/* Some Mac compilers merge all .h files incorrectly: */ -+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) -+# define NO_DUMMY_DECL -+#endif -+ -+/* Old Borland C incorrectly complains about missing returns: */ -+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) -+# define NEED_DUMMY_RETURN -+#endif -+ -+ -+/* Maximum value for memLevel in deflateInit2 */ -+#ifndef MAX_MEM_LEVEL -+# ifdef MAXSEG_64K -+# define MAX_MEM_LEVEL 8 -+# else -+# define MAX_MEM_LEVEL 9 -+# endif -+#endif -+ -+/* Maximum value for windowBits in deflateInit2 and inflateInit2. -+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files -+ * created by gzip. (Files created by minigzip can still be extracted by -+ * gzip.) -+ */ -+#ifndef MAX_WBITS -+# define MAX_WBITS 15 /* 32K LZ77 window */ -+#endif -+ -+/* The memory requirements for deflate are (in bytes): -+ (1 << (windowBits+2)) + (1 << (memLevel+9)) -+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) -+ plus a few kilobytes for small objects. For example, if you want to reduce -+ the default memory requirements from 256K to 128K, compile with -+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" -+ Of course this will generally degrade compression (there's no free lunch). -+ -+ The memory requirements for inflate are (in bytes) 1 << windowBits -+ that is, 32K for windowBits=15 (default value) plus a few kilobytes -+ for small objects. -+*/ -+ -+ /* Type declarations */ -+ -+#ifndef OF /* function prototypes */ -+# ifdef STDC -+# define OF(args) args -+# else -+# define OF(args) () -+# endif -+#endif -+ -+/* The following definitions for FAR are needed only for MSDOS mixed -+ * model programming (small or medium model with some far allocations). -+ * This was tested only with MSC; for other MSDOS compilers you may have -+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, -+ * just define FAR to be empty. -+ */ -+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) -+ /* MSC small or medium model */ -+# define SMALL_MEDIUM -+# ifdef _MSC_VER -+# define FAR _far -+# else -+# define FAR far -+# endif -+#endif -+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) -+# ifndef __32BIT__ -+# define SMALL_MEDIUM -+# define FAR _far -+# endif -+#endif -+ -+/* Compile with -DZLIB_DLL for Windows DLL support */ -+#if defined(ZLIB_DLL) -+# if defined(_WINDOWS) || defined(WINDOWS) -+# ifdef FAR -+# undef FAR -+# endif -+# include -+# define ZEXPORT WINAPI -+# ifdef WIN32 -+# define ZEXPORTVA WINAPIV -+# else -+# define ZEXPORTVA FAR _cdecl _export -+# endif -+# endif -+# if defined (__BORLANDC__) -+# if (__BORLANDC__ >= 0x0500) && defined (WIN32) -+# include -+# define ZEXPORT __declspec(dllexport) WINAPI -+# define ZEXPORTRVA __declspec(dllexport) WINAPIV -+# else -+# if defined (_Windows) && defined (__DLL__) -+# define ZEXPORT _export -+# define ZEXPORTVA _export -+# endif -+# endif -+# endif -+#endif -+ -+#if defined (__BEOS__) -+# if defined (ZLIB_DLL) -+# define ZEXTERN extern __declspec(dllexport) -+# else -+# define ZEXTERN extern __declspec(dllimport) -+# endif -+#endif -+ -+#ifndef ZEXPORT -+# define ZEXPORT -+#endif -+#ifndef ZEXPORTVA -+# define ZEXPORTVA -+#endif -+#ifndef ZEXTERN -+# define ZEXTERN extern -+#endif -+ -+#ifndef FAR -+# define FAR -+#endif -+ -+#if !defined(MACOS) && !defined(TARGET_OS_MAC) -+typedef unsigned char Byte; /* 8 bits */ -+#endif -+typedef unsigned int uInt; /* 16 bits or more */ -+typedef unsigned long uLong; /* 32 bits or more */ -+ -+#ifdef SMALL_MEDIUM -+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -+# define Bytef Byte FAR -+#else -+ typedef Byte FAR Bytef; -+#endif -+typedef char FAR charf; -+typedef int FAR intf; -+typedef uInt FAR uIntf; -+typedef uLong FAR uLongf; -+ -+#ifdef STDC -+ typedef void FAR *voidpf; -+ typedef void *voidp; -+#else -+ typedef Byte FAR *voidpf; -+ typedef Byte *voidp; -+#endif -+ -+#ifdef HAVE_UNISTD_H -+# include /* for off_t */ -+# include /* for SEEK_* and off_t */ -+# define z_off_t off_t -+#endif -+#ifndef SEEK_SET -+# define SEEK_SET 0 /* Seek from beginning of file. */ -+# define SEEK_CUR 1 /* Seek from current position. */ -+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -+#endif -+#ifndef z_off_t -+# define z_off_t long -+#endif -+ -+/* MVS linker does not support external names larger than 8 bytes */ -+#if defined(__MVS__) -+# pragma map(deflateInit_,"DEIN") -+# pragma map(deflateInit2_,"DEIN2") -+# pragma map(deflateEnd,"DEEND") -+# pragma map(inflateInit_,"ININ") -+# pragma map(inflateInit2_,"ININ2") -+# pragma map(inflateEnd,"INEND") -+# pragma map(inflateSync,"INSY") -+# pragma map(inflateSetDictionary,"INSEDI") -+# pragma map(inflate_blocks,"INBL") -+# pragma map(inflate_blocks_new,"INBLNE") -+# pragma map(inflate_blocks_free,"INBLFR") -+# pragma map(inflate_blocks_reset,"INBLRE") -+# pragma map(inflate_codes_free,"INCOFR") -+# pragma map(inflate_codes,"INCO") -+# pragma map(inflate_fast,"INFA") -+# pragma map(inflate_flush,"INFLU") -+# pragma map(inflate_mask,"INMA") -+# pragma map(inflate_set_dictionary,"INSEDI2") -+# pragma map(ipcomp_inflate_copyright,"INCOPY") -+# pragma map(inflate_trees_bits,"INTRBI") -+# pragma map(inflate_trees_dynamic,"INTRDY") -+# pragma map(inflate_trees_fixed,"INTRFI") -+# pragma map(inflate_trees_free,"INTRFR") -+#endif -+ -+#endif /* _ZCONF_H */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/lib/zlib/zutil.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,227 @@ -+/* zutil.c -- target dependent utility functions for the compression library -+ * Copyright (C) 1995-2002 Jean-loup Gailly. -+ * For conditions of distribution and use, see copyright notice in zlib.h -+ */ -+ -+/* @(#) $Id$ */ -+ -+#include -+ -+#define MY_ZCALLOC -+ -+struct internal_state {int dummy;}; /* for buggy compilers */ -+ -+#ifndef STDC -+extern void exit OF((int)); -+#endif -+ -+const char *z_errmsg[10] = { -+"need dictionary", /* Z_NEED_DICT 2 */ -+"stream end", /* Z_STREAM_END 1 */ -+"", /* Z_OK 0 */ -+"file error", /* Z_ERRNO (-1) */ -+"stream error", /* Z_STREAM_ERROR (-2) */ -+"data error", /* Z_DATA_ERROR (-3) */ -+"insufficient memory", /* Z_MEM_ERROR (-4) */ -+"buffer error", /* Z_BUF_ERROR (-5) */ -+"incompatible version",/* Z_VERSION_ERROR (-6) */ -+""}; -+ -+ -+const char * ZEXPORT zlibVersion() -+{ -+ return ZLIB_VERSION; -+} -+ -+#ifdef DEBUG -+ -+# ifndef verbose -+# define verbose 0 -+# endif -+int z_verbose = verbose; -+ -+void z_error (m) -+ char *m; -+{ -+ fprintf(stderr, "%s\n", m); -+ exit(1); -+} -+#endif -+ -+/* exported to allow conversion of error code to string for compress() and -+ * uncompress() -+ */ -+const char * ZEXPORT zError(err) -+ int err; -+{ -+ return ERR_MSG(err); -+} -+ -+ -+#ifndef HAVE_MEMCPY -+ -+void zmemcpy(dest, source, len) -+ Bytef* dest; -+ const Bytef* source; -+ uInt len; -+{ -+ if (len == 0) return; -+ do { -+ *dest++ = *source++; /* ??? to be unrolled */ -+ } while (--len != 0); -+} -+ -+int zmemcmp(s1, s2, len) -+ const Bytef* s1; -+ const Bytef* s2; -+ uInt len; -+{ -+ uInt j; -+ -+ for (j = 0; j < len; j++) { -+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; -+ } -+ return 0; -+} -+ -+void zmemzero(dest, len) -+ Bytef* dest; -+ uInt len; -+{ -+ if (len == 0) return; -+ do { -+ *dest++ = 0; /* ??? to be unrolled */ -+ } while (--len != 0); -+} -+#endif -+ -+#ifdef __TURBOC__ -+#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) -+/* Small and medium model in Turbo C are for now limited to near allocation -+ * with reduced MAX_WBITS and MAX_MEM_LEVEL -+ */ -+# define MY_ZCALLOC -+ -+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes -+ * and farmalloc(64K) returns a pointer with an offset of 8, so we -+ * must fix the pointer. Warning: the pointer must be put back to its -+ * original form in order to free it, use zcfree(). -+ */ -+ -+#define MAX_PTR 10 -+/* 10*64K = 640K */ -+ -+local int next_ptr = 0; -+ -+typedef struct ptr_table_s { -+ voidpf org_ptr; -+ voidpf new_ptr; -+} ptr_table; -+ -+local ptr_table table[MAX_PTR]; -+/* This table is used to remember the original form of pointers -+ * to large buffers (64K). Such pointers are normalized with a zero offset. -+ * Since MSDOS is not a preemptive multitasking OS, this table is not -+ * protected from concurrent access. This hack doesn't work anyway on -+ * a protected system like OS/2. Use Microsoft C instead. -+ */ -+ -+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) -+{ -+ voidpf buf = opaque; /* just to make some compilers happy */ -+ ulg bsize = (ulg)items*size; -+ -+ /* If we allocate less than 65520 bytes, we assume that farmalloc -+ * will return a usable pointer which doesn't have to be normalized. -+ */ -+ if (bsize < 65520L) { -+ buf = farmalloc(bsize); -+ if (*(ush*)&buf != 0) return buf; -+ } else { -+ buf = farmalloc(bsize + 16L); -+ } -+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL; -+ table[next_ptr].org_ptr = buf; -+ -+ /* Normalize the pointer to seg:0 */ -+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; -+ *(ush*)&buf = 0; -+ table[next_ptr++].new_ptr = buf; -+ return buf; -+} -+ -+void zcfree (voidpf opaque, voidpf ptr) -+{ -+ int n; -+ if (*(ush*)&ptr != 0) { /* object < 64K */ -+ farfree(ptr); -+ return; -+ } -+ /* Find the original pointer */ -+ for (n = 0; n < next_ptr; n++) { -+ if (ptr != table[n].new_ptr) continue; -+ -+ farfree(table[n].org_ptr); -+ while (++n < next_ptr) { -+ table[n-1] = table[n]; -+ } -+ next_ptr--; -+ return; -+ } -+ ptr = opaque; /* just to make some compilers happy */ -+ Assert(0, "zcfree: ptr not found"); -+} -+#endif -+#endif /* __TURBOC__ */ -+ -+ -+#if defined(M_I86) && !defined(__32BIT__) -+/* Microsoft C in 16-bit mode */ -+ -+# define MY_ZCALLOC -+ -+#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) -+# define _halloc halloc -+# define _hfree hfree -+#endif -+ -+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) -+{ -+ if (opaque) opaque = 0; /* to make compiler happy */ -+ return _halloc((long)items, size); -+} -+ -+void zcfree (voidpf opaque, voidpf ptr) -+{ -+ if (opaque) opaque = 0; /* to make compiler happy */ -+ _hfree(ptr); -+} -+ -+#endif /* MSC */ -+ -+ -+#ifndef MY_ZCALLOC /* Any system without a special alloc function */ -+ -+#ifndef STDC -+extern voidp calloc OF((uInt items, uInt size)); -+extern void free OF((voidpf ptr)); -+#endif -+ -+voidpf zcalloc (opaque, items, size) -+ voidpf opaque; -+ unsigned items; -+ unsigned size; -+{ -+ if (opaque) items += size - size; /* make compiler happy */ -+ return (voidpf)calloc(items, size); -+} -+ -+void zcfree (opaque, ptr) -+ voidpf opaque; -+ voidpf ptr; -+{ -+ free(ptr); -+ if (opaque) return; /* make compiler happy */ -+} -+ -+#endif /* MY_ZCALLOC */ ---- linux/net/Config.in.orig Fri Feb 9 14:34:13 2001 -+++ linux/net/Config.in Thu Feb 22 19:40:08 2001 -@@ -88,4 +88,9 @@ - #bool 'Network code profiler' CONFIG_NET_PROFILE - endmenu - -+tristate 'IP Security Protocol (FreeS/WAN IPSEC)' CONFIG_IPSEC -+if [ "$CONFIG_IPSEC" != "n" ]; then -+ source net/ipsec/Config.in -+fi -+ - endmenu -RCSID $Id$ ---- linux/net/Makefile.preipsec Mon Jun 11 22:15:27 2001 -+++ linux/net/Makefile Tue Nov 6 21:07:43 2001 -@@ -17,6 +17,7 @@ - subdir-$(CONFIG_NET) += 802 sched - subdir-$(CONFIG_INET) += ipv4 - subdir-$(CONFIG_NETFILTER) += ipv4/netfilter -+subdir-$(CONFIG_IPSEC) += ipsec - subdir-$(CONFIG_UNIX) += unix - subdir-$(CONFIG_IPV6) += ipv6 - ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/Config.in Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,76 @@ -+# -+# IPSEC configuration -+# Copyright (C) 1998, 1999, 2000,2001 Richard Guy Briggs. -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by the -+# Free Software Foundation; either version 2 of the License, or (at your -+# option) any later version. See . -+# -+# This program is distributed in 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. -+# -+# RCSID $Id$ -+ -+comment 'IPSec options (Openswan)' -+ -+bool ' IPSEC: IP-in-IP encapsulation (tunnel mode)' CONFIG_IPSEC_IPIP -+ -+bool ' IPSEC: Authentication Header' CONFIG_IPSEC_AH -+if [ "$CONFIG_IPSEC_AH" = "y" -o "$CONFIG_IPSEC_ESP" = "y" ]; then -+ bool ' HMAC-MD5 authentication algorithm' CONFIG_IPSEC_AUTH_HMAC_MD5 -+ bool ' HMAC-SHA1 authentication algorithm' CONFIG_IPSEC_AUTH_HMAC_SHA1 -+fi -+ -+bool ' IPSEC: Encapsulating Security Payload' CONFIG_IPSEC_ESP -+if [ "$CONFIG_IPSEC_ESP" = "y" ]; then -+ bool ' 3DES encryption algorithm' CONFIG_IPSEC_ENC_3DES -+ bool ' AES encryption algorithm' CONFIG_IPSEC_ENC_AES -+fi -+ -+bool ' IPSEC Modular Extensions' CONFIG_IPSEC_ALG -+if [ "$CONFIG_IPSEC_ALG" != "n" ]; then -+ source net/ipsec/alg/Config.in -+fi -+ -+bool ' IPSEC: IP Compression' CONFIG_IPSEC_IPCOMP -+ -+bool ' IPSEC Debugging Option' CONFIG_IPSEC_DEBUG -+ -+# -+# -+# $Log$ -+# Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+# Turn off EOLN_NATIVE flag -+# -+# (Logical change 1.5010) -+# -+# Revision 1.30 2004/06/23 09:49:37 ken -+# Free -> Open -+# -+# Revision 1.29 2004/04/06 02:49:25 mcr -+# pullup of algo code from alg-branch. -+# -+# Revision 1.28 2004/02/03 03:12:26 mcr -+# remove NAT-traversal option from IPsec config, -+# as it should be in the kernel configuration if -+# the NAT-T patch is installed. -+# -+# Revision 1.27.2.2 2004/04/05 04:30:46 mcr -+# patches for alg-branch to compile/work with 2.x openswan -+# -+# Revision 1.27.2.1 2003/12/23 12:48:25 jjo -+# Added missing alg part to linux/net/ipsec/Config.in -+# -+# Revision 1.27 2003/12/10 01:14:27 mcr -+# NAT-traversal patches to KLIPS. -+# -+# Revision 1.26 2002/04/24 07:36:26 mcr -+# Moved from ./klips/net/ipsec/Config.in,v -+# -+# Revision 1.25 2002/02/21 19:55:12 mcr -+# removed all traces of IPSEC_CONFIG_REGRESS because it -+# screwed up 2.2's "make menuconfig" scripts. -+# -+# Revision 1.24 2002/01/28 20:24:31 mcr -+# commented out IPSEC_REGRESS option from user visible config. -+# -+# -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/Makefile Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,337 @@ -+# Makefile for KLIPS kernel code as a module -+# Copyright (C) 1998, 1999, 2000,2001 Richard Guy Briggs. -+# Copyright (C) 2002 Michael Richardson -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by the -+# Free Software Foundation; either version 2 of the License, or (at your -+# option) any later version. See . -+# -+# This program is distributed in 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. -+# -+# RCSID $Id$ -+# -+# Note! Dependencies are done automagically by 'make dep', which also -+# removes any old dependencies. DON'T put your own dependencies here -+# unless it's something special (ie not a .c file). -+# -+ -+ifeq ($(strip $(KLIPSMODULE)),) -+OPENSWANSRCDIR=. -+else -+OPENSWANSRCDIR=../../.. -+endif -+-include ${OPENSWANSRCDIR}/Makefile.ver -+ -+ifeq ($(strip $(KLIPS_TOP)),) -+KLIPS_TOP=../.. -+endif -+ -+ifneq ($(strip $(KLIPSMODULE)),) -+ -+ifndef TOPDIR -+TOPDIR:=/usr/src/linux -+endif -+export TOPDIR -+ -+endif -+ -+# -+# This magic from User-Mode-Linux list. It gets list of -I options, as -+# UML needs some extra, that varry by revision. -+# -+KERNEL_CFLAGS= $(shell $(MAKE) -C $(TOPDIR) --no-print-directory -s -f Makefile ARCH=$(ARCH) MAKEFLAGS= script SCRIPT='@echo $$(CFLAGS)' ) -+ -+MODULE_CFLAGS= $(shell $(MAKE) -C $(TOPDIR) --no-print-directory -s -f Makefile ARCH=$(ARCH) MAKEFLAGS= script SCRIPT='@echo $$(MODFLAGS)' ) -+ -+subdir- := -+subdir-n := -+subdir-y := -+subdir-m := -+ -+ -+MOD_DESTDIR:=net/ipsec -+ -+export TOPDIR -+ -+all: ipsec.o -+ -+foo: -+ echo KERNEL: ${KERNEL_CFLAGS} -+ echo MODULE: ${MODULE_CFLAGS} -+ -+ipsec.o: foo -+ -+O_TARGET := ipsec.o -+obj-y := ipsec_init.o ipsec_sa.o ipsec_radij.o radij.o -+obj-y += ipsec_life.o ipsec_proc.o -+obj-y += ipsec_tunnel.o ipsec_xmit.o ipsec_rcv.o ipsec_ipip.o -+obj-y += sysctl_net_ipsec.o -+obj-y += pfkey_v2.o pfkey_v2_parser.o pfkey_v2_ext_process.o -+obj-y += version.o -+obj-$(CONFIG_IPSEC_AH) += ipsec_ah.o -+obj-$(CONFIG_IPSEC_ESP) += ipsec_esp.o -+obj-$(CONFIG_IPSEC_IPCOMP)+= ipsec_ipcomp.o -+ -+CFLAGS_ipsec_alg.o += -DEXPORT_SYMTAB -+obj-$(CONFIG_IPSEC_ALG) += ipsec_alg.o -+obj-$(CONFIG_IPSEC_ENC_AES) += ipsec_alg_aes.o -+obj-$(CONFIG_IPSEC_ENC_CRYPTOAPI) += ipsec_alg_cryptoapi.o -+ -+export-objs += ipsec_alg.o -+ -+ -+LIBDESDIR=${KLIPS_TOP}/crypto/ciphers/des -+VPATH+= ${LIBDESDIR} -+ -+include ${LIBDESDIR}/Makefile.objs -+ -+LIBFREESWANDIR=${KLIPS_TOP}/lib/libfreeswan -+VPATH+=${LIBFREESWANDIR} -+ -+include ${LIBFREESWANDIR}/Makefile.objs -+ -+# IPcomp stuff -+obj-$(CONFIG_IPSEC_IPCOMP) += ipcomp.o -+ -+LIBZLIBSRCDIR=${KLIPS_TOP}/lib/zlib -+VPATH+=${LIBZLIBSRCDIR} -+ -+LIBAESDIR=$(KLIPS_TOP)/crypto/ciphers/aes -+VPATH+=${LIBAESDIR} -+include ${LIBAESDIR}/Makefile.objs -+ -+# CFLAGS='$(CFLAGS)' \ -+# MODULE_CFLAGS='$(MODULE_CFLAGS)' KERNEL_CFLAGS='$(KERNEL_CFLAGS)' \ -+# -+include ${LIBZLIBSRCDIR}/Makefile.objs -+ -+export-objs := radij.o -+ -+EXTRA_CFLAGS += $(ALGO_FLAGS) -+ -+ -+# include file with .h-style macros that would otherwise be created by -+# config. Must occur before other includes. -+ifneq ($(strip $(MODULE_DEF_INCLUDE)),) -+EXTRA_CFLAGS += -include ${MODULE_DEF_INCLUDE} -+endif -+ -+# 'override CFLAGS' should really be 'EXTRA_CFLAGS' -+#EXTRA_CFLAGS += -nostdinc -+EXTRA_CFLAGS += -I${KLIPS_TOP}/include -+ -+EXTRA_CFLAGS += -I${TOPDIR}/include -+EXTRA_CFLAGS += -I${LIBZLIBSRCDIR} -+ -+ifeq ($(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION),2.4.2-2) -+EXTRA_CFLAGS += -DREDHAT_BOGOSITY -+endif -+ -+ifeq ($(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION),2.4.3-12) -+EXTRA_CFLAGS += -DREDHAT_BOGOSITY -+endif -+ -+ -+#ifeq ($(CONFIG_IPSEC_DEBUG),y) -+#EXTRA_CFLAGS += -g -+#endif -+ -+#ifeq ($(CONFIG_IPSEC_ALG), y) -+EXTRA_CFLAGS += -DCONFIG_IPSEC_ALG -+#endif -+# MOST of these flags are in KERNEL_CFLAGS already! -+ -+EXTRA_CFLAGS += $(KLIPSCOMPILE) -+EXTRA_CFLAGS += -Wall -+#EXTRA_CFLAGS += -Werror -+#EXTRA_CFLAGS += -Wconversion -+#EXTRA_CFLAGS += -Wmissing-prototypes -+# cannot use both -Wpointer-arith and -Werror with CONFIG_HIGHMEM -+# include/linux/highmem.h has an inline function definition that uses void* arithmentic. -+ifeq ($(CONFIG_NOHIGHMEM),y) -+EXTRA_CFLAGS += -Wpointer-arith -+endif -+#EXTRA_CFLAGS += -Wcast-qual -+#EXTRA_CFLAGS += -Wmissing-declarations -+#EXTRA_CFLAGS += -Wstrict-prototypes -+#EXTRA_CFLAGS += -pedantic -+#EXTRA_CFLAGS += -O3 -+#EXTRA_CFLAGS += -W -+#EXTRA_CFLAGS += -Wwrite-strings -+#EXTRA_CFLAGS += -Wbad-function-cast -+ -+ifneq ($(strip $(KLIPSMODULE)),) -+# for when we aren't building in the kernel tree -+EXTRA_CFLAGS += -DARCH=${ARCH} -+EXTRA_CFLAGS += -DMODVERSIONS -+EXTRA_CFLAGS += -include ${TOPDIR}/include/linux/modversions.h -+EXTRA_CFLAGS += ${MODULE_CFLAGS} -+endif -+ -+EXTRA_CFLAGS += ${KERNEL_CFLAGS} -+ -+#EXTRA_CFLAGS += -DRJ_DEBUG -DRJ_DEBUG2 -+ -+ -+# GCC 3.2 (and we presume any other 3.x) wants -falign-functions -+# in place of the traditional -malign-functions. Getting this -+# wrong leads to a warning, which is fatal due to our use of -Werror. -+ifeq ($(patsubst 3.%,3,$(shell $(CC) -dumpversion)),3) -+override CFLAGS:=$(subst -malign-functions=,-falign-functions=,$(CFLAGS)) -+endif -+ -+ -+obj-$(CONFIG_IPSEC_AUTH_HMAC_MD5) += ipsec_md5c.o -+obj-$(CONFIG_IPSEC_AUTH_HMAC_SHA1) += ipsec_sha1.o -+ -+### -+### Pre Rules.make -+### -+# undo O_TARGET, obj-y if no static -+ifneq ($(CONFIG_IPSEC),y) -+O_TARGET := -+ipsec_obj-y := $(obj-y) -+obj-y := -+subdir-y := -+endif -+ -+# Define obj-m if modular ipsec -+ifeq ($(CONFIG_IPSEC),m) -+obj-m += ipsec.o -+endif -+ -+ -+# These rules translate from new to old makefile rules -+# Translate to Rules.make lists. -+multi-used := $(filter $(list-multi), $(obj-y) $(obj-m)) -+multi-objs := $(foreach m, $(multi-used), $($(basename $(m))-objs)) -+active-objs := $(sort $(multi-objs) $(obj-y) $(obj-m)) -+O_OBJS := $(obj-y) -+M_OBJS := $(obj-m) -+MIX_OBJS := $(filter $(export-objs), $(active-objs)) -+OX_OBJS := $(export-objs) -+SUB_DIRS := $(subdir-y) -+ALL_SUB_DIRS := $(subdir-y) $(subdir-m) -+MOD_SUB_DIRS := $(subdir-m) -+ -+# dunno why, but some 2.2 setups may need explicit -DEXPORT_SYMTAB -+# uncomment next line if ipsec_alg.c compilation fails with -+# "parse error before `EXPORT_SYMTAB_not_defined'" --Juanjo -+ -+include $(TOPDIR)/Rules.make -+ -+### -+### Post Rules.make -+### -+# for modular ipsec, no O_TARGET defined => define ipsec.o creation rules -+ifeq ($(CONFIG_IPSEC),m) -+ipsec.o : $(ipsec_obj-y) -+ rm -f $@ -+ $(LD) $(LD_EXTRAFLAGS) -r $(ipsec_obj-y) -o $@ -+endif -+ -+$(ipsec_obj-y) $(obj-y) $(obj-m): $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h -+ -+#$(obj-y) $(obj-m): $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h -+ -+USE_STANDARD_AS_RULE=true -+ -+clean: -+ $(MAKE) -C alg clean -+ -rm -f *.o -+ -rm -f .*.o.flags -+ -rm -f version.c -+ -+tags TAGS: *.c *.h libfreeswan/*.c libfreeswan/*.h -+ etags *.c ../../include/*.h ../../include/freeswan/*.h -+ ctags *.c ../../include/*.h ../../include/freeswan/*.h -+ -+tar: -+ tar -cvf /dev/f1 . -+ -+# -+# $Log$ -+# Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+# Turn off EOLN_NATIVE flag -+# -+# (Logical change 1.5010) -+# -+# Revision 1.72 2004/06/22 14:44:07 ken -+# Merge nice version of Nate's CryptoAPI patch -+# -+# Revision 1.71 2004/04/18 03:04:21 mcr -+# removed duplicate version.o reference. -+# -+# Revision 1.70 2004/04/14 05:09:39 ken -+# We need to link version.o -+# -+# Revision 1.69 2004/04/12 04:02:39 ken -+# version.o no longer exists -+# -+# Revision 1.68 2004/04/11 17:08:41 mcr -+# moved PASSTHROUGH definitions to openswan.h -+# requirement for internal.h removed. -+# version.c is now generated by patch at patch-time. -+# -+# Revision 1.67 2004/04/06 02:49:25 mcr -+# pullup of algo code from alg-branch. -+# -+# Revision 1.66 2004/04/03 19:44:41 ken -+# FREESWANSRCDIR -> OPENSWANSRCDIR (patch by folken) -+# -+# Revision 1.65 2004/02/09 16:22:07 paul -+# Added -f to rm version.c in clean target to prevent bogus error -+# -+# Revision 1.64 2003/12/22 19:40:57 mcr -+# NAT-T patches 0.6c. -+# -+# Revision 1.63 2003/12/13 19:10:21 mcr -+# refactored rcv and xmit code - same as FS 2.05. -+# -+# Revision 1.62.4.2 2004/04/05 04:30:46 mcr -+# patches for alg-branch to compile/work with 2.x openswan -+# -+# Revision 1.62.4.1 2003/12/22 15:25:52 jjo -+# Merged algo-0.8.1-rc11-test1 into alg-branch -+# -+# Revision 1.62 2003/10/31 02:27:55 mcr -+# pulled up port-selector patches and sa_id elimination. -+# -+# Revision 1.61.4.1 2003/10/29 01:30:41 mcr -+# elimited "struct sa_id". -+# -+# Revision 1.61 2003/06/22 21:07:46 mcr -+# adjusted TAGS target in makefile to be useful in 2.00 source layout. -+# -+# Revision 1.60 2003/05/03 23:45:23 mcr -+# rm .o.flags and generated version.c file. -+# -+# Revision 1.59 2003/02/12 19:32:47 rgb -+# Added ipsec_xmit to the list of object files. -+# -+# Revision 1.58 2003/01/03 00:36:44 rgb -+# -+# Added emacs compile-command. -+# -+# Revision 1.57 2002/11/08 23:49:53 mcr -+# use KERNEL_CFLAGS and MODULE_CFLAGS to get proper list -+# of include directories. -+# This also eliminates some of the guesswork in the kernel -+# configuration file. -+# -+# Revision 1.56 2002/11/08 23:23:18 mcr -+# attempt to guess kernel compilation flags (i.e. list of -I) -+# by using some magic targets in the kernel makefile. -+# -+# Revision 1.55 2002/11/08 10:13:33 mcr -+# added additional include directories for module builds for 2.4.19. -+# -+# Revision 1.54 2002/10/20 06:10:30 build -+# CONFIG_NOHIGHMEM for -Wpointer-arith RPM building issues. -+# -+# (elided rest of log) -+# -+# Local Variables: -+# compile-command: "(cd ../../.. && source umlsetup.sh && make -C ${POOLSPACE} module/ipsec.o)" -+# End Variables: -+# -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/Config.alg_aes.in Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,3 @@ -+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then -+ tristate ' AES encryption algorithm' CONFIG_IPSEC_ALG_AES -+fi ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/Config.alg_cryptoapi.in Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,6 @@ -+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then -+ dep_tristate ' CRYPTOAPI ciphers support (needs cryptoapi patch)' CONFIG_IPSEC_ALG_CRYPTOAPI $CONFIG_CRYPTO -+ if [ "$CONFIG_IPSEC_ALG_CRYPTOAPI" != "n" ]; then -+ bool ' CRYPTOAPI proprietary ciphers ' CONFIG_IPSEC_ALG_NON_LIBRE -+ fi -+fi ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/Config.in Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,3 @@ -+#Placeholder -+source net/ipsec/alg/Config.alg_aes.in -+source net/ipsec/alg/Config.alg_cryptoapi.in ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/Makefile Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,112 @@ -+# Makefile,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp -+ifeq ($(strip $(KLIPSMODULE)),) -+FREESWANSRCDIR=. -+else -+FREESWANSRCDIR=../../../.. -+endif -+ifeq ($(strip $(KLIPS_TOP)),) -+KLIPS_TOP=../../.. -+override EXTRA_CFLAGS += -I$(KLIPS_TOP)/include -+endif -+ -+ifeq ($(CONFIG_IPSEC_DEBUG),y) -+override EXTRA_CFLAGS += -g -+endif -+ -+# LIBCRYPTO normally comes as an argument from "parent" Makefile -+# (this applies both to FS' "make module" and eg. Linux' "make modules" -+# But make dep doest follow same evaluations, so we need this default: -+LIBCRYPTO=$(TOPDIR)/lib/libcrypto -+ -+override EXTRA_CFLAGS += -I$(LIBCRYPTO)/include -+override EXTRA_CFLAGS += -Wall -Wpointer-arith -Wstrict-prototypes -+ -+MOD_LIST_NAME := NET_MISC_MODULES -+ -+#O_TARGET := static_init.o -+ -+subdir- := -+subdir-n := -+subdir-y := -+subdir-m := -+ -+obj-y := static_init.o -+ -+ARCH_ASM-y := -+ARCH_ASM-$(CONFIG_M586) := i586 -+ARCH_ASM-$(CONFIG_M586TSC) := i586 -+ARCH_ASM-$(CONFIG_M586MMX) := i586 -+ARCH_ASM-$(CONFIG_MK6) := i586 -+ARCH_ASM-$(CONFIG_M686) := i686 -+ARCH_ASM-$(CONFIG_MPENTIUMIII) := i686 -+ARCH_ASM-$(CONFIG_MPENTIUM4) := i686 -+ARCH_ASM-$(CONFIG_MK7) := i686 -+ARCH_ASM-$(CONFIG_MCRUSOE) := i586 -+ARCH_ASM-$(CONFIG_MWINCHIPC6) := i586 -+ARCH_ASM-$(CONFIG_MWINCHIP2) := i586 -+ARCH_ASM-$(CONFIG_MWINCHIP3D) := i586 -+ARCH_ASM-$(CONFIG_USERMODE) := i586 -+ -+ARCH_ASM :=$(ARCH_ASM-y) -+ifdef NO_ASM -+ARCH_ASM := -+endif -+ -+# The algorithm makefiles may put dependences, short-circuit them -+null: -+ -+makefiles=$(filter-out %.preipsec, $(wildcard Makefile.alg_*)) -+ifneq ($(makefiles),) -+#include Makefile.alg_aes -+#include Makefile.alg_aes-opt -+include $(makefiles) -+endif -+ -+# These rules translate from new to old makefile rules -+# Translate to Rules.make lists. -+multi-used := $(filter $(list-multi), $(obj-y) $(obj-m)) -+multi-objs := $(foreach m, $(multi-used), $($(basename $(m))-objs)) -+active-objs := $(sort $(multi-objs) $(obj-y) $(obj-m)) -+O_OBJS := $(obj-y) -+M_OBJS := $(obj-m) -+MIX_OBJS := $(filter $(export-objs), $(active-objs)) -+#OX_OBJS := $(export-objs) -+SUB_DIRS := $(subdir-y) -+ALL_SUB_DIRS := $(subdir-y) $(subdir-m) -+MOD_SUB_DIRS := $(subdir-m) -+ -+ -+static_init_mod.o: $(obj-y) -+ rm -f $@ -+ $(LD) $(LD_EXTRAFLAGS) $(obj-y) -r -o $@ -+ -+perlasm: $(LIBCRYPTO)/perlasm -+ ln -sf $? $@ -+ -+$(obj-y) $(obj-m): $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h $(KLIPS_TOP)/include/freeswan/ipsec_alg.h -+$(alg_obj-y) $(alg_obj-m): perlasm $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h $(KLIPS_TOP)/include/freeswan/ipsec_alg.h -+ -+ -+all_alg_modules: perlasm $(ALG_MODULES) -+ @echo "ALG_MODULES=$(ALG_MODULES)" -+ -+ -+# -+# Construct alg. init. function: call ipsec_ALGO_init() for every static algo -+# Needed when there are static algos (with static or modular ipsec.o) -+# -+static_init.c: $(TOPDIR)/include/linux/autoconf.h Makefile $(makefiles) scripts/mk-static_init.c.sh -+ @echo "Re-creating $@" -+ $(SHELL) scripts/mk-static_init.c.sh $(static_init-func-y) > $@ -+ -+clean: -+ @for i in $(ALG_SUBDIRS);do test -d $$i && make -C $$i clean;done;exit 0 -+ @find . -type l -exec rm -f {} \; -+ -rm -f perlasm -+ -rm -rf $(ALG_SUBDIRS) -+ -rm -f *.o static_init.c -+ -+ifdef TOPDIR -+include $(TOPDIR)/Rules.make -+endif -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/Makefile.alg_aes Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,23 @@ -+MOD_AES := ipsec_aes.o -+ -+ALG_MODULES += $(MOD_AES) -+ALG_SUBDIRS += libaes -+ -+obj-$(CONFIG_IPSEC_ALG_AES) += $(MOD_AES) -+static_init-func-$(CONFIG_IPSEC_ALG_AES)+= ipsec_aes_init -+alg_obj-$(CONFIG_IPSEC_ALG_AES) += ipsec_alg_aes.o -+ -+AES_OBJS := ipsec_alg_aes.o libaes/libaes.a -+ -+$(MOD_AES): libaes $(AES_OBJS) -+ $(LD) $(EXTRA_LDFLAGS) -r $(AES_OBJS) -o $@ -+ -+libaes: $(LIBCRYPTO)/libaes -+ test -d $@ || mkdir $@ ;exit 0 -+ test -d $@/asm || mkdir $@/asm;exit 0 -+ cd $@ && ln -sf $?/Makefile $?/*.[chS] . -+ cd $@/asm && ln -sf $?/asm/*.S . -+ -+libaes/libaes.a: libaes -+ ( cd libaes && \ -+ $(MAKE) CC='$(CC)' 'ARCH_ASM=$(ARCH_ASM)' CFLAGS='$(CFLAGS) $(EXTRA_CFLAGS)' libaes.a ;) ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/Makefile.alg_cryptoapi Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,14 @@ -+MOD_CRYPTOAPI := ipsec_cryptoapi.o -+ -+ifneq ($(wildcard $(TOPDIR)/include/linux/crypto.h),) -+ALG_MODULES += $(MOD_CRYPTOAPI) -+obj-$(CONFIG_IPSEC_ALG_CRYPTOAPI) += $(MOD_CRYPTOAPI) -+static_init-func-$(CONFIG_IPSEC_ALG_CRYPTOAPI)+= ipsec_cryptoapi_init -+alg_obj-$(CONFIG_IPSEC_ALG_CRYPTOAPI) += ipsec_alg_cryptoapi.o -+else -+$(warning "Linux CryptoAPI (2.4.22+ or 2.6.x) not found, not building ipsec_cryptoapi.o") -+endif -+ -+CRYPTOAPI_OBJS := ipsec_alg_cryptoapi.o -+$(MOD_CRYPTOAPI): $(CRYPTOAPI_OBJS) -+ $(LD) -r $(CRYPTOAPI_OBJS) -o $@ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/ipsec_alg_aes.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,253 @@ -+/* -+ * ipsec_alg AES cipher stubs -+ * -+ * Author: JuanJo Ciarlante -+ * -+ * ipsec_alg_aes.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * Fixes by: -+ * PK: Pawel Krawczyk -+ * Fixes list: -+ * PK: make XCBC comply with latest draft (keylength) -+ * -+ */ -+#include -+#include -+ -+/* -+ * special case: ipsec core modular with this static algo inside: -+ * must avoid MODULE magic for this file -+ */ -+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_AES -+#undef MODULE -+#endif -+ -+#include -+#include -+ -+#include /* printk() */ -+#include /* error codes */ -+#include /* size_t */ -+#include -+ -+/* Check if __exit is defined, if not null it */ -+#ifndef __exit -+#define __exit -+#endif -+ -+/* Low freeswan header coupling */ -+#include "freeswan/ipsec_alg.h" -+#include "libaes/aes_cbc.h" -+ -+#define CONFIG_IPSEC_ALG_AES_MAC 1 -+ -+#define AES_CONTEXT_T aes_context -+MODULE_AUTHOR("JuanJo Ciarlante "); -+static int debug=0; -+MODULE_PARM(debug, "i"); -+static int test=0; -+MODULE_PARM(test, "i"); -+static int excl=0; -+MODULE_PARM(excl, "i"); -+static int keyminbits=0; -+MODULE_PARM(keyminbits, "i"); -+static int keymaxbits=0; -+MODULE_PARM(keymaxbits, "i"); -+ -+#if CONFIG_IPSEC_ALG_AES_MAC -+#include "libaes/aes_xcbc_mac.h" -+ -+/* -+ * Not IANA number yet (draft-ietf-ipsec-ciph-aes-xcbc-mac-00.txt). -+ * We use 9 for non-modular algorithm and none for modular, thus -+ * forcing user to specify one on module load. -kravietz -+ */ -+#ifdef MODULE -+static int auth_id=0; -+#else -+static int auth_id=9; -+#endif -+MODULE_PARM(auth_id, "i"); -+#endif -+ -+#define ESP_AES 12 /* truely _constant_ :) */ -+ -+/* 128, 192 or 256 */ -+#define ESP_AES_KEY_SZ_MIN 16 /* 128 bit secret key */ -+#define ESP_AES_KEY_SZ_MAX 32 /* 256 bit secret key */ -+#define ESP_AES_CBC_BLK_LEN 16 /* AES-CBC block size */ -+ -+/* Values according to draft-ietf-ipsec-ciph-aes-xcbc-mac-02.txt -+ * -kravietz -+ */ -+#define ESP_AES_MAC_KEY_SZ 16 /* 128 bit MAC key */ -+#define ESP_AES_MAC_BLK_LEN 16 /* 128 bit block */ -+ -+static int _aes_set_key(struct ipsec_alg_enc *alg, __u8 * key_e, const __u8 * key, size_t keysize) { -+ int ret; -+ AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e; -+ ret=AES_set_key(ctx, key, keysize)!=0? 0: -EINVAL; -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_aes_set_key:" -+ "ret=%d key_e=%p key=%p keysize=%d\n", -+ ret, key_e, key, keysize); -+ return ret; -+} -+static int _aes_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) { -+ AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e; -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_aes_cbc_encrypt:" -+ "key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n", -+ key_e, in, ilen, iv, encrypt); -+ return AES_cbc_encrypt(ctx, in, in, ilen, iv, encrypt); -+} -+#if CONFIG_IPSEC_ALG_AES_MAC -+static int _aes_mac_set_key(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * key, int keylen) { -+ aes_context_mac *ctxm=(aes_context_mac *)key_a; -+ return AES_xcbc_mac_set_key(ctxm, key, keylen)? 0 : -EINVAL; -+} -+static int _aes_mac_hash(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * dat, int len, __u8 * hash, int hashlen) { -+ int ret; -+ char hash_buf[16]; -+ aes_context_mac *ctxm=(aes_context_mac *)key_a; -+ ret=AES_xcbc_mac_hash(ctxm, dat, len, hash_buf); -+ memcpy(hash, hash_buf, hashlen); -+ return ret; -+} -+static struct ipsec_alg_auth ipsec_alg_AES_MAC = { -+ ixt_version: IPSEC_ALG_VERSION, -+ ixt_module: THIS_MODULE, -+ ixt_refcnt: ATOMIC_INIT(0), -+ ixt_alg_type: IPSEC_ALG_TYPE_AUTH, -+ ixt_alg_id: 0, -+ ixt_name: "aes_mac", -+ ixt_blocksize: ESP_AES_MAC_BLK_LEN, -+ ixt_keyminbits: ESP_AES_MAC_KEY_SZ*8, -+ ixt_keymaxbits: ESP_AES_MAC_KEY_SZ*8, -+ ixt_a_keylen: ESP_AES_MAC_KEY_SZ, -+ ixt_a_ctx_size: sizeof(aes_context_mac), -+ ixt_a_hmac_set_key: _aes_mac_set_key, -+ ixt_a_hmac_hash:_aes_mac_hash, -+}; -+#endif /* CONFIG_IPSEC_ALG_AES_MAC */ -+static struct ipsec_alg_enc ipsec_alg_AES = { -+ ixt_version: IPSEC_ALG_VERSION, -+ ixt_module: THIS_MODULE, -+ ixt_refcnt: ATOMIC_INIT(0), -+ ixt_alg_type: IPSEC_ALG_TYPE_ENCRYPT, -+ ixt_alg_id: ESP_AES, -+ ixt_name: "aes", -+ ixt_blocksize: ESP_AES_CBC_BLK_LEN, -+ ixt_keyminbits: ESP_AES_KEY_SZ_MIN*8, -+ ixt_keymaxbits: ESP_AES_KEY_SZ_MAX*8, -+ ixt_e_keylen: ESP_AES_KEY_SZ_MAX, -+ ixt_e_ctx_size: sizeof(AES_CONTEXT_T), -+ ixt_e_set_key: _aes_set_key, -+ ixt_e_cbc_encrypt:_aes_cbc_encrypt, -+}; -+ -+IPSEC_ALG_MODULE_INIT( ipsec_aes_init ) -+{ -+ int ret, test_ret; -+ if (keyminbits) -+ ipsec_alg_AES.ixt_keyminbits=keyminbits; -+ if (keymaxbits) { -+ ipsec_alg_AES.ixt_keymaxbits=keymaxbits; -+ if (keymaxbits*8>ipsec_alg_AES.ixt_keymaxbits) -+ ipsec_alg_AES.ixt_e_keylen=keymaxbits*8; -+ } -+ if (excl) ipsec_alg_AES.ixt_state |= IPSEC_ALG_ST_EXCL; -+ ret=register_ipsec_alg_enc(&ipsec_alg_AES); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", -+ ipsec_alg_AES.ixt_alg_type, -+ ipsec_alg_AES.ixt_alg_id, -+ ipsec_alg_AES.ixt_name, -+ ret); -+ if (ret==0 && test) { -+ test_ret=ipsec_alg_test( -+ ipsec_alg_AES.ixt_alg_type, -+ ipsec_alg_AES.ixt_alg_id, -+ test); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", -+ ipsec_alg_AES.ixt_alg_type, -+ ipsec_alg_AES.ixt_alg_id, -+ test_ret); -+ } -+#if CONFIG_IPSEC_ALG_AES_MAC -+ if (auth_id!=0){ -+ int ret; -+ ipsec_alg_AES_MAC.ixt_alg_id=auth_id; -+ ret=register_ipsec_alg_auth(&ipsec_alg_AES_MAC); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", -+ ipsec_alg_AES_MAC.ixt_alg_type, -+ ipsec_alg_AES_MAC.ixt_alg_id, -+ ipsec_alg_AES_MAC.ixt_name, -+ ret); -+ if (ret==0 && test) { -+ test_ret=ipsec_alg_test( -+ ipsec_alg_AES_MAC.ixt_alg_type, -+ ipsec_alg_AES_MAC.ixt_alg_id, -+ test); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", -+ ipsec_alg_AES_MAC.ixt_alg_type, -+ ipsec_alg_AES_MAC.ixt_alg_id, -+ test_ret); -+ } -+ } else { -+ printk(KERN_DEBUG "klips_debug: experimental ipsec_alg_AES_MAC not registered [Ok] (auth_id=%d)\n", auth_id); -+ } -+#endif /* CONFIG_IPSEC_ALG_AES_MAC */ -+ return ret; -+} -+IPSEC_ALG_MODULE_EXIT( ipsec_aes_fini ) -+{ -+#if CONFIG_IPSEC_ALG_AES_MAC -+ if (auth_id) unregister_ipsec_alg_auth(&ipsec_alg_AES_MAC); -+#endif /* CONFIG_IPSEC_ALG_AES_MAC */ -+ unregister_ipsec_alg_enc(&ipsec_alg_AES); -+ return; -+} -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+#if 0+NOT_YET -+#ifndef MODULE -+/* -+ * This is intended for static module setups, currently -+ * doesn't work for modular ipsec.o with static algos inside -+ */ -+static int setup_keybits(const char *str) -+{ -+ unsigned aux; -+ char *end; -+ -+ aux = simple_strtoul(str,&end,0); -+ if (aux != 128 && aux != 192 && aux != 256) -+ return 0; -+ keyminbits = aux; -+ -+ if (*end == 0 || *end != ',') -+ return 1; -+ str=end+1; -+ aux = simple_strtoul(str, NULL, 0); -+ if (aux != 128 && aux != 192 && aux != 256) -+ return 0; -+ if (aux >= keyminbits) -+ keymaxbits = aux; -+ return 1; -+} -+__setup("ipsec_aes_keybits=", setup_keybits); -+#endif -+#endif -+EXPORT_NO_SYMBOLS; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/ipsec_alg_cryptoapi.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,421 @@ -+/* -+ * ipsec_alg to linux cryptoapi GLUE -+ * -+ * Authors: CODE.ar TEAM -+ * Harpo MAxx -+ * JuanJo Ciarlante -+ * Luciano Ruete -+ * -+ * ipsec_alg_cryptoapi.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * Example usage: -+ * modinfo -p ipsec_cryptoapi (quite useful info, including supported algos) -+ * modprobe ipsec_cryptoapi -+ * modprobe ipsec_cryptoapi test=1 -+ * modprobe ipsec_cryptoapi excl=1 (exclusive cipher/algo) -+ * modprobe ipsec_cryptoapi noauto=1 aes=1 twofish=1 (only these ciphers) -+ * modprobe ipsec_cryptoapi aes=128,128 (force these keylens) -+ * modprobe ipsec_cryptoapi des_ede3=0 (everything but 3DES) -+ */ -+#include -+#include -+ -+/* -+ * special case: ipsec core modular with this static algo inside: -+ * must avoid MODULE magic for this file -+ */ -+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_CRYPTOAPI -+#undef MODULE -+#endif -+ -+#include -+#include -+ -+#include /* printk() */ -+#include /* error codes */ -+#include /* size_t */ -+#include -+ -+/* Check if __exit is defined, if not null it */ -+#ifndef __exit -+#define __exit -+#endif -+ -+/* warn the innocent */ -+#if !defined (CONFIG_CRYPTO) && !defined (CONFIG_CRYPTO_MODULE) -+#warning "No linux CryptoAPI found, install 2.4.22+ or 2.6.x" -+#define NO_CRYPTOAPI_SUPPORT -+#endif -+/* Low freeswan header coupling */ -+#include "freeswan/ipsec_alg.h" -+ -+#include -+#ifdef CRYPTO_API_VERSION_CODE -+#warning "Old CryptoAPI is not supported. Only linux-2.4.22+ or linux-2.6.x are supported" -+#define NO_CRYPTOAPI_SUPPORT -+#endif -+ -+#ifdef NO_CRYPTOAPI_SUPPORT -+#warning "Building an unusable module :P" -+/* Catch old CryptoAPI by not allowing module to load */ -+IPSEC_ALG_MODULE_INIT( ipsec_cryptoapi_init ) -+{ -+ printk(KERN_WARNING "ipsec_cryptoapi.o was not built on stock Linux CryptoAPI (2.4.22+ or 2.6.x), not loading.\n"); -+ return -EINVAL; -+} -+#else -+#include -+#include -+#include -+ -+#define CIPHERNAME_AES "aes" -+#define CIPHERNAME_3DES "des3_ede" -+#define CIPHERNAME_BLOWFISH "blowfish" -+#define CIPHERNAME_CAST "cast5" -+#define CIPHERNAME_SERPENT "serpent" -+#define CIPHERNAME_TWOFISH "twofish" -+ -+#define ESP_3DES 3 -+#define ESP_AES 12 -+#define ESP_BLOWFISH 7 /* truely _constant_ :) */ -+#define ESP_CAST 6 /* quite constant :) */ -+#define ESP_SERPENT 252 /* from ipsec drafts */ -+#define ESP_TWOFISH 253 /* from ipsec drafts */ -+ -+#define AH_MD5 2 -+#define AH_SHA 3 -+#define DIGESTNAME_MD5 "md5" -+#define DIGESTNAME_SHA1 "sha1" -+ -+MODULE_AUTHOR("Juanjo Ciarlante, Harpo MAxx, Luciano Ruete"); -+static int debug=0; -+MODULE_PARM(debug, "i"); -+static int test=0; -+MODULE_PARM(test, "i"); -+static int excl=0; -+MODULE_PARM(excl, "i"); -+ -+static int noauto = 0; -+MODULE_PARM(noauto,"i"); -+MODULE_PARM_DESC(noauto, "Dont try all known algos, just setup enabled ones"); -+ -+static int des_ede3[] = {-1, -1}; -+static int aes[] = {-1, -1}; -+static int blowfish[] = {-1, -1}; -+static int cast[] = {-1, -1}; -+static int serpent[] = {-1, -1}; -+static int twofish[] = {-1, -1}; -+ -+MODULE_PARM(des_ede3,"1-2i"); -+MODULE_PARM(aes,"1-2i"); -+MODULE_PARM(blowfish,"1-2i"); -+MODULE_PARM(cast,"1-2i"); -+MODULE_PARM(serpent,"1-2i"); -+MODULE_PARM(twofish,"1-2i"); -+MODULE_PARM_DESC(des_ede3, "0: disable | 1: force_enable | min,max: dontuse"); -+MODULE_PARM_DESC(aes, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(blowfish, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(cast, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(serpent, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(twofish, "0: disable | 1: force_enable | min,max: keybitlens"); -+ -+struct ipsec_alg_capi_cipher { -+ const char *ciphername; /* cryptoapi's ciphername */ -+ unsigned blocksize; -+ unsigned short minbits; -+ unsigned short maxbits; -+ int *parm; /* lkm param for this cipher */ -+ struct ipsec_alg_enc alg; /* note it's not a pointer */ -+}; -+static struct ipsec_alg_capi_cipher alg_capi_carray[] = { -+ { CIPHERNAME_AES , 16, 128, 256, aes , { ixt_alg_id: ESP_AES, }}, -+ { CIPHERNAME_TWOFISH , 16, 128, 256, twofish, { ixt_alg_id: ESP_TWOFISH, }}, -+ { CIPHERNAME_SERPENT , 16, 128, 256, serpent, { ixt_alg_id: ESP_SERPENT, }}, -+ { CIPHERNAME_CAST , 8, 128, 128, cast , { ixt_alg_id: ESP_CAST, }}, -+ { CIPHERNAME_BLOWFISH , 8, 96, 448, blowfish,{ ixt_alg_id: ESP_BLOWFISH, }}, -+ { CIPHERNAME_3DES , 8, 192, 192, des_ede3,{ ixt_alg_id: ESP_3DES, }}, -+ { NULL, 0, 0, 0, NULL, {} } -+}; -+#ifdef NOT_YET -+struct ipsec_alg_capi_digest { -+ const char *digestname; /* cryptoapi's digestname */ -+ struct digest_implementation *di; -+ struct ipsec_alg_auth alg; /* note it's not a pointer */ -+}; -+static struct ipsec_alg_capi_cipher alg_capi_darray[] = { -+ { DIGESTNAME_MD5, NULL, { ixt_alg_id: AH_MD5, }}, -+ { DIGESTNAME_SHA1, NULL, { ixt_alg_id: AH_SHA, }}, -+ { NULL, NULL, {} } -+}; -+#endif -+/* -+ * "generic" linux cryptoapi setup_cipher() function -+ */ -+int setup_cipher(const char *ciphername) -+{ -+ return crypto_alg_available(ciphername, 0); -+} -+ -+/* -+ * setups ipsec_alg_capi_cipher "hyper" struct components, calling -+ * register_ipsec_alg for cointaned ipsec_alg object -+ */ -+static void _capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e); -+static __u8 * _capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen); -+static int _capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt); -+ -+static int -+setup_ipsec_alg_capi_cipher(struct ipsec_alg_capi_cipher *cptr) -+{ -+ int ret; -+ cptr->alg.ixt_version = IPSEC_ALG_VERSION; -+ cptr->alg.ixt_module = THIS_MODULE; -+ atomic_set (& cptr->alg.ixt_refcnt, 0); -+ strncpy (cptr->alg.ixt_name , cptr->ciphername, sizeof (cptr->alg.ixt_name)); -+ -+ cptr->alg.ixt_blocksize=cptr->blocksize; -+ cptr->alg.ixt_keyminbits=cptr->minbits; -+ cptr->alg.ixt_keymaxbits=cptr->maxbits; -+ cptr->alg.ixt_state = 0; -+ if (excl) cptr->alg.ixt_state |= IPSEC_ALG_ST_EXCL; -+ cptr->alg.ixt_e_keylen=cptr->alg.ixt_keymaxbits/8; -+ cptr->alg.ixt_e_ctx_size = 0; -+ cptr->alg.ixt_alg_type = IPSEC_ALG_TYPE_ENCRYPT; -+ cptr->alg.ixt_e_new_key = _capi_new_key; -+ cptr->alg.ixt_e_destroy_key = _capi_destroy_key; -+ cptr->alg.ixt_e_cbc_encrypt = _capi_cbc_encrypt; -+ cptr->alg.ixt_data = cptr; -+ -+ ret=register_ipsec_alg_enc(&cptr->alg); -+ printk("setup_ipsec_alg_capi_cipher(): " -+ "alg_type=%d alg_id=%d name=%s " -+ "keyminbits=%d keymaxbits=%d, ret=%d\n", -+ cptr->alg.ixt_alg_type, -+ cptr->alg.ixt_alg_id, -+ cptr->alg.ixt_name, -+ cptr->alg.ixt_keyminbits, -+ cptr->alg.ixt_keymaxbits, -+ ret); -+ return ret; -+} -+/* -+ * called in ipsec_sa_wipe() time, will destroy key contexts -+ * and do 1 unbind() -+ */ -+static void -+_capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e) -+{ -+ struct crypto_tfm *tfm=(struct crypto_tfm*)key_e; -+ -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug: _capi_destroy_key:" -+ "name=%s key_e=%p \n", -+ alg->ixt_name, key_e); -+ if (!key_e) { -+ printk(KERN_ERR "klips_debug: _capi_destroy_key:" -+ "name=%s NULL key_e!\n", -+ alg->ixt_name); -+ return; -+ } -+ crypto_free_tfm(tfm); -+} -+ -+/* -+ * create new key context, need alg->ixt_data to know which -+ * (of many) cipher inside this module is the target -+ */ -+static __u8 * -+_capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen) -+{ -+ struct ipsec_alg_capi_cipher *cptr; -+ struct crypto_tfm *tfm=NULL; -+ -+ cptr = alg->ixt_data; -+ if (!cptr) { -+ printk(KERN_ERR "_capi_new_key(): " -+ "NULL ixt_data (?!) for \"%s\" algo\n" -+ , alg->ixt_name); -+ goto err; -+ } -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_capi_new_key:" -+ "name=%s cptr=%p key=%p keysize=%d\n", -+ alg->ixt_name, cptr, key, keylen); -+ -+ /* -+ * alloc tfm -+ */ -+ tfm = crypto_alloc_tfm(cptr->ciphername, CRYPTO_TFM_MODE_CBC); -+ if (!tfm) { -+ printk(KERN_ERR "_capi_new_key(): " -+ "NULL tfm for \"%s\" cryptoapi (\"%s\") algo\n" -+ , alg->ixt_name, cptr->ciphername); -+ goto err; -+ } -+ if (crypto_cipher_setkey(tfm, key, keylen) < 0) { -+ printk(KERN_ERR "_capi_new_key(): " -+ "failed new_key() for \"%s\" cryptoapi algo (keylen=%d)\n" -+ , alg->ixt_name, keylen); -+ crypto_free_tfm(tfm); -+ tfm=NULL; -+ } -+err: -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_capi_new_key:" -+ "name=%s key=%p keylen=%d tfm=%p\n", -+ alg->ixt_name, key, keylen, tfm); -+ return (__u8 *) tfm; -+} -+/* -+ * core encryption function: will use cx->ci to call actual cipher's -+ * cbc function -+ */ -+static int -+_capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) { -+ int error =0; -+ struct crypto_tfm *tfm=(struct crypto_tfm *)key_e; -+ struct scatterlist sg = { -+ .page = virt_to_page(in), -+ .offset = (unsigned long)(in) % PAGE_SIZE, -+ .length=ilen, -+ }; -+ if (debug > 1) -+ printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" -+ "key_e=%p " -+ "in=%p out=%p ilen=%d iv=%p encrypt=%d\n" -+ , key_e -+ , in, in, ilen, iv, encrypt); -+ crypto_cipher_set_iv(tfm, iv, crypto_tfm_alg_ivsize(tfm)); -+ if (encrypt) -+ error = crypto_cipher_encrypt (tfm, &sg, &sg, ilen); -+ else -+ error = crypto_cipher_decrypt (tfm, &sg, &sg, ilen); -+ if (debug > 1) -+ printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" -+ "error=%d\n" -+ , error); -+ return (error<0)? error : ilen; -+} -+/* -+ * main initialization loop: for each cipher in list, do -+ * 1) setup cryptoapi cipher else continue -+ * 2) register ipsec_alg object -+ */ -+static int -+setup_cipher_list (struct ipsec_alg_capi_cipher* clist) -+{ -+ struct ipsec_alg_capi_cipher *cptr; -+ /* foreach cipher in list ... */ -+ for (cptr=clist;cptr->ciphername;cptr++) { -+ /* -+ * see if cipher has been disabled (0) or -+ * if noauto set and not enabled (1) -+ */ -+ if (cptr->parm[0] == 0 || (noauto && cptr->parm[0] < 0)) { -+ if (debug>0) -+ printk(KERN_INFO "setup_cipher_list(): " -+ "ciphername=%s skipped at user request: " -+ "noauto=%d parm[0]=%d parm[1]=%d\n" -+ , cptr->ciphername -+ , noauto -+ , cptr->parm[0] -+ , cptr->parm[1]); -+ continue; -+ } -+ /* -+ * use a local ci to avoid touching cptr->ci, -+ * if register ipsec_alg success then bind cipher -+ */ -+ if( setup_cipher(cptr->ciphername) ) { -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:" -+ "setup_cipher_list():" -+ "ciphername=%s found\n" -+ , cptr->ciphername); -+ if (setup_ipsec_alg_capi_cipher(cptr) == 0) { -+ -+ -+ } else { -+ printk(KERN_ERR "klips_debug:" -+ "setup_cipher_list():" -+ "ciphername=%s failed ipsec_alg_register\n" -+ , cptr->ciphername); -+ } -+ } else { -+ if (debug>0) -+ printk(KERN_INFO "setup_cipher_list(): lookup for ciphername=%s: not found \n", -+ cptr->ciphername); -+ } -+ } -+ return 0; -+} -+/* -+ * deregister ipsec_alg objects and unbind ciphers -+ */ -+static int -+unsetup_cipher_list (struct ipsec_alg_capi_cipher* clist) -+{ -+ struct ipsec_alg_capi_cipher *cptr; -+ /* foreach cipher in list ... */ -+ for (cptr=clist;cptr->ciphername;cptr++) { -+ if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) { -+ unregister_ipsec_alg_enc(&cptr->alg); -+ } -+ } -+ return 0; -+} -+/* -+ * test loop for registered algos -+ */ -+static int -+test_cipher_list (struct ipsec_alg_capi_cipher* clist) -+{ -+ int test_ret; -+ struct ipsec_alg_capi_cipher *cptr; -+ /* foreach cipher in list ... */ -+ for (cptr=clist;cptr->ciphername;cptr++) { -+ if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) { -+ test_ret=ipsec_alg_test( -+ cptr->alg.ixt_alg_type, -+ cptr->alg.ixt_alg_id, -+ test); -+ printk("test_cipher_list(alg_type=%d alg_id=%d): test_ret=%d\n", -+ cptr->alg.ixt_alg_type, -+ cptr->alg.ixt_alg_id, -+ test_ret); -+ } -+ } -+ return 0; -+} -+ -+IPSEC_ALG_MODULE_INIT( ipsec_cryptoapi_init ) -+{ -+ int ret, test_ret; -+ if ((ret=setup_cipher_list(alg_capi_carray)) < 0) -+ return -EPROTONOSUPPORT; -+ if (ret==0 && test) { -+ test_ret=test_cipher_list(alg_capi_carray); -+ } -+ return ret; -+} -+IPSEC_ALG_MODULE_EXIT( ipsec_cryptoapi_fini ) -+{ -+ unsetup_cipher_list(alg_capi_carray); -+ return; -+} -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+EXPORT_NO_SYMBOLS; -+#endif /* NO_CRYPTOAPI_SUPPORT */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/alg/scripts/mk-static_init.c.sh Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,18 @@ -+#!/bin/sh -+cat << EOF -+#include -+#include -+#include "freeswan/ipsec_alg.h" -+$(for i in $*; do -+ test -z "$i" && continue -+ echo "extern int $i(void);" -+done) -+void ipsec_alg_static_init(void){ -+ int __attribute__ ((unused)) err=0; -+$(for i in $*; do -+ test -z "$i" && continue -+ echo " if ((err=$i()) < 0)" -+ echo " printk(KERN_WARNING \"$i() returned %d\", err);" -+done) -+} -+EOF ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/defconfig Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,146 @@ -+ -+# -+# RCSID $Id$ -+# -+ -+# -+# FreeS/WAN IPSec implementation, KLIPS kernel config defaults -+# -+ -+# -+# First, lets override stuff already set or not in the kernel config. -+# -+# We can't even think about leaving this off... -+CONFIG_INET=y -+ -+# -+# This must be on for subnet protection. -+CONFIG_IP_FORWARD=y -+ -+# Shut off IPSEC masquerading if it has been enabled, since it will -+# break the compile. IPPROTO_ESP and IPPROTO_AH were included in -+# net/ipv4/ip_masq.c when they should have gone into include/linux/in.h. -+CONFIG_IP_MASQUERADE_IPSEC=n -+ -+# -+# Next, lets set the recommended FreeS/WAN configuration. -+# -+ -+# To config as static (preferred), 'y'. To config as module, 'm'. -+CONFIG_IPSEC=y -+ -+# To do tunnel mode IPSec, this must be enabled. -+CONFIG_IPSEC_IPIP=y -+ -+# To enable authentication, say 'y'. (Highly recommended) -+CONFIG_IPSEC_AH=y -+ -+# Authentication algorithm(s): -+CONFIG_IPSEC_AUTH_HMAC_MD5=y -+CONFIG_IPSEC_AUTH_HMAC_SHA1=y -+ -+# To enable encryption, say 'y'. (Highly recommended) -+CONFIG_IPSEC_ESP=y -+ -+# Encryption algorithm(s): -+CONFIG_IPSEC_ENC_3DES=y -+CONFIG_IPSEC_ENC_AES=y -+ -+# modular algo extensions (and new ALGOs) -+CONFIG_IPSEC_ALG=y -+CONFIG_IPSEC_ENC_3DES=y -+CONFIG_IPSEC_ENC_AES=y -+ -+CONFIG_IPSEC_ALG_TWOFISH=m -+CONFIG_IPSEC_ALG_BLOWFISH=m -+CONFIG_IPSEC_ALG_SERPENT=m -+CONFIG_IPSEC_ALG_MD5=m -+CONFIG_IPSEC_ALG_SHA1=m -+CONFIG_IPSEC_ALG_SHA2=m -+#CONFIG_IPSEC_ALG_CAST=n -+#CONFIG_IPSEC_ALG_NULL=n -+ -+# Use CryptoAPI for ALG? - by default, no. -+CONFIG_IPSEC_ENC_CRYPTOAPI=n -+ -+ -+# IP Compression: new, probably still has minor bugs. -+CONFIG_IPSEC_IPCOMP=y -+ -+# To enable userspace-switchable KLIPS debugging, say 'y'. -+CONFIG_IPSEC_DEBUG=y -+ -+# NAT Traversal -+CONFIG_IPSEC_NAT_TRAVERSAL=y -+ -+# -+# -+# $Log$ -+# Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+# Turn off EOLN_NATIVE flag -+# -+# (Logical change 1.5010) -+# -+# Revision 1.25 2004/07/05 01:03:53 mcr -+# fix for adding cryptoapi code. -+# keep it off for now, since UMLs do not have it yet. -+# -+# Revision 1.24 2004/04/06 02:49:25 mcr -+# pullup of algo code from alg-branch. -+# -+# Revision 1.23.2.2 2004/04/05 04:30:46 mcr -+# patches for alg-branch to compile/work with 2.x openswan -+# -+# Revision 1.23.2.1 2003/12/22 15:25:52 jjo -+# . Merged algo-0.8.1-rc11-test1 into alg-branch -+# -+# Revision 1.23 2003/12/10 01:14:27 mcr -+# NAT-traversal patches to KLIPS. -+# -+# Revision 1.22 2003/02/24 19:37:27 mcr -+# changed default compilation mode to static. -+# -+# Revision 1.21 2002/04/24 07:36:27 mcr -+# Moved from ./klips/net/ipsec/defconfig,v -+# -+# Revision 1.20 2002/04/02 04:07:40 mcr -+# default build is now 'm'odule for KLIPS -+# -+# Revision 1.19 2002/03/08 18:57:17 rgb -+# Added a blank line at the beginning of the file to make it easier for -+# other projects to patch ./arch/i386/defconfig, for example -+# LIDS+grSecurity requested by Jason Pattie. -+# -+# Revision 1.18 2000/11/30 17:26:56 rgb -+# Cleaned out unused options and enabled ipcomp by default. -+# -+# Revision 1.17 2000/09/15 11:37:01 rgb -+# Merge in heavily modified Svenning Soerensen's -+# IPCOMP zlib deflate code. -+# -+# Revision 1.16 2000/09/08 19:12:55 rgb -+# Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+# -+# Revision 1.15 2000/05/24 19:37:13 rgb -+# *** empty log message *** -+# -+# Revision 1.14 2000/05/11 21:14:57 henry -+# just commenting the FOOBAR=y lines out is not enough -+# -+# Revision 1.13 2000/05/10 20:17:58 rgb -+# Comment out netlink defaults, which are no longer needed. -+# -+# Revision 1.12 2000/05/10 19:13:38 rgb -+# Added configure option to shut off no eroute passthrough. -+# -+# Revision 1.11 2000/03/16 07:09:46 rgb -+# Hardcode PF_KEYv2 support. -+# Disable IPSEC_ICMP by default. -+# Remove DES config option from defaults file. -+# -+# Revision 1.10 2000/01/11 03:09:42 rgb -+# Added a default of 'y' to PF_KEYv2 keying I/F. -+# -+# Revision 1.9 1999/05/08 21:23:12 rgb -+# Added support for 2.2.x kernels. -+# -+# Revision 1.8 1999/04/06 04:54:25 rgb -+# Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+# patch shell fixes. -+# -+# ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipcomp.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,725 @@ -+/* -+ * IPCOMP zlib interface code. -+ * Copyright (C) 2000 Svenning Soerensen -+ * Copyright (C) 2000, 2001 Richard Guy Briggs -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipcomp_c_version[] = "RCSID $Id$"; -+ -+/* SSS */ -+ -+#include -+#include -+ -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include -+#include -+#include -+#include -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+ -+#include -+ -+#ifdef NET_21 -+# include -+# include -+# include -+# define proto_priv cb -+#endif /* NET21 */ -+#include -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" /* sysctl_ipsec_inbound_policy_check */ -+#include "openswan/ipcomp.h" -+#include "zlib/zlib.h" -+#include "zlib/zutil.h" -+ -+#include /* SADB_X_CALG_DEFLATE */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int sysctl_ipsec_debug_ipcomp = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+static -+struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask); -+ -+static -+voidpf my_zcalloc(voidpf opaque, uInt items, uInt size) -+{ -+ return (voidpf) kmalloc(items*size, GFP_ATOMIC); -+} -+ -+static -+void my_zfree(voidpf opaque, voidpf address) -+{ -+ kfree(address); -+} -+ -+struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags) -+{ -+ struct iphdr *iph; -+ unsigned int iphlen, pyldsz, cpyldsz; -+ unsigned char *buffer; -+ z_stream zs; -+ int zresult; -+ -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: .\n"); -+ -+ if(skb == NULL) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "passed in NULL skb, returning ERROR.\n"); -+ if(flags != NULL) { -+ *flags |= IPCOMP_PARMERROR; -+ } -+ return skb; -+ } -+ -+ if(ips == NULL) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "passed in NULL ipsec_sa needed for cpi, returning ERROR.\n"); -+ if(flags) { -+ *flags |= IPCOMP_PARMERROR; -+ } -+ return skb; -+ } -+ -+ if (flags == NULL) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "passed in NULL flags, returning ERROR.\n"); -+ ipsec_kfree_skb(skb); -+ return NULL; -+ } -+ -+#ifdef NET_21 -+ iph = skb->nh.iph; -+#else /* NET_21 */ -+ iph = skb->ip_hdr; -+#endif /* NET_21 */ -+ -+ switch (iph->protocol) { -+ case IPPROTO_COMP: -+ case IPPROTO_AH: -+ case IPPROTO_ESP: -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "skipping compression of packet with ip protocol %d.\n", -+ iph->protocol); -+ *flags |= IPCOMP_UNCOMPRESSABLE; -+ return skb; -+ } -+ -+ /* Don't compress packets already fragmented */ -+ if (iph->frag_off & __constant_htons(IP_MF | IP_OFFSET)) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "skipping compression of fragmented packet.\n"); -+ *flags |= IPCOMP_UNCOMPRESSABLE; -+ return skb; -+ } -+ -+ iphlen = iph->ihl << 2; -+ pyldsz = ntohs(iph->tot_len) - iphlen; -+ -+ /* Don't compress less than 90 bytes (rfc 2394) */ -+ if (pyldsz < 90) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "skipping compression of tiny packet, len=%d.\n", -+ pyldsz); -+ *flags |= IPCOMP_UNCOMPRESSABLE; -+ return skb; -+ } -+ -+ /* Adaptive decision */ -+ if (ips->ips_comp_adapt_skip) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "skipping compression: ips_comp_adapt_skip=%d.\n", -+ ips->ips_comp_adapt_skip); -+ ips->ips_comp_adapt_skip--; -+ *flags |= IPCOMP_UNCOMPRESSABLE; -+ return skb; -+ } -+ -+ zs.zalloc = my_zcalloc; -+ zs.zfree = my_zfree; -+ zs.opaque = 0; -+ -+ /* We want to use deflateInit2 because we don't want the adler -+ header. */ -+ zresult = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -11, -+ DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); -+ if (zresult != Z_OK) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_compress: " -+ "deflateInit2() returned error %d (%s), " -+ "skipping compression.\n", -+ zresult, -+ zs.msg ? zs.msg : zError(zresult)); -+ *flags |= IPCOMP_COMPRESSIONERROR; -+ return skb; -+ } -+ -+ -+ /* Max output size. Result should be max this size. -+ * Implementation specific tweak: -+ * If it's not at least 32 bytes and 6.25% smaller than -+ * the original packet, it's probably not worth wasting -+ * the receiver's CPU cycles decompressing it. -+ * Your mileage may vary. -+ */ -+ cpyldsz = pyldsz - sizeof(struct ipcomphdr) - (pyldsz <= 512 ? 32 : pyldsz >> 4); -+ -+ buffer = kmalloc(cpyldsz, GFP_ATOMIC); -+ if (!buffer) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_compress: " -+ "unable to kmalloc(%d, GFP_ATOMIC), " -+ "skipping compression.\n", -+ cpyldsz); -+ *flags |= IPCOMP_COMPRESSIONERROR; -+ deflateEnd(&zs); -+ return skb; -+ } -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { -+ __u8 *c; -+ int i; -+ -+ c = (__u8*)iph + iphlen; -+ for(i = 0; i < pyldsz; i++, c++) { -+ if(!(i % 16)) { -+ printk(KERN_INFO "skb_compress: before:"); -+ } -+ printk("%02x ", *c); -+ if(!((i + 1) % 16)) { -+ printk("\n"); -+ } -+ } -+ if(i % 16) { -+ printk("\n"); -+ } -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ zs.next_in = (char *) iph + iphlen; /* start of payload */ -+ zs.avail_in = pyldsz; -+ zs.next_out = buffer; /* start of compressed payload */ -+ zs.avail_out = cpyldsz; -+ -+ /* Finish compression in one step */ -+ zresult = deflate(&zs, Z_FINISH); -+ -+ /* Free all dynamically allocated buffers */ -+ deflateEnd(&zs); -+ if (zresult != Z_STREAM_END) { -+ *flags |= IPCOMP_UNCOMPRESSABLE; -+ kfree(buffer); -+ -+ /* Adjust adaptive counters */ -+ if (++(ips->ips_comp_adapt_tries) == IPCOMP_ADAPT_INITIAL_TRIES) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "first %d packets didn't compress, " -+ "skipping next %d\n", -+ IPCOMP_ADAPT_INITIAL_TRIES, -+ IPCOMP_ADAPT_INITIAL_SKIP); -+ ips->ips_comp_adapt_skip = IPCOMP_ADAPT_INITIAL_SKIP; -+ } -+ else if (ips->ips_comp_adapt_tries == IPCOMP_ADAPT_INITIAL_TRIES + IPCOMP_ADAPT_SUBSEQ_TRIES) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "next %d packets didn't compress, " -+ "skipping next %d\n", -+ IPCOMP_ADAPT_SUBSEQ_TRIES, -+ IPCOMP_ADAPT_SUBSEQ_SKIP); -+ ips->ips_comp_adapt_skip = IPCOMP_ADAPT_SUBSEQ_SKIP; -+ ips->ips_comp_adapt_tries = IPCOMP_ADAPT_INITIAL_TRIES; -+ } -+ -+ return skb; -+ } -+ -+ /* resulting compressed size */ -+ cpyldsz -= zs.avail_out; -+ -+ /* Insert IPCOMP header */ -+ ((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_nh = iph->protocol; -+ ((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_flags = 0; -+ /* use the bottom 16 bits of the spi for the cpi. The top 16 bits are -+ for internal reference only. */ -+ ((struct ipcomphdr*) (((char*)iph) + iphlen))->ipcomp_cpi = htons((__u16)(ntohl(ips->ips_said.spi) & 0x0000ffff)); -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_compress: " -+ "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: raw=%d, comp=%d.\n", -+ ntohl(ips->ips_said.spi), -+ ntohl(ips->ips_said.spi) & 0x0000ffff, -+ ntohs(((struct ipcomphdr*)(((char*)iph)+iphlen))->ipcomp_cpi), -+ pyldsz, -+ cpyldsz); -+ -+ /* Update IP header */ -+ iph->protocol = IPPROTO_COMP; -+ iph->tot_len = htons(iphlen + sizeof(struct ipcomphdr) + cpyldsz); -+#if 1 /* XXX checksum is done by ipsec_tunnel ? */ -+ iph->check = 0; -+ iph->check = ip_fast_csum((char *) iph, iph->ihl); -+#endif -+ -+ /* Copy compressed payload */ -+ memcpy((char *) iph + iphlen + sizeof(struct ipcomphdr), -+ buffer, -+ cpyldsz); -+ kfree(buffer); -+ -+ /* Update skb length/tail by "unputting" the shrinkage */ -+ skb_put(skb, -+ cpyldsz + sizeof(struct ipcomphdr) - pyldsz); -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { -+ __u8 *c; -+ int i; -+ -+ c = (__u8*)iph + iphlen + sizeof(struct ipcomphdr); -+ for(i = 0; i < cpyldsz; i++, c++) { -+ if(!(i % 16)) { -+ printk(KERN_INFO "skb_compress: result:"); -+ } -+ printk("%02x ", *c); -+ if(!((i + 1) % 16)) { -+ printk("\n"); -+ } -+ } -+ if(i % 16) { -+ printk("\n"); -+ } -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ ips->ips_comp_adapt_skip = 0; -+ ips->ips_comp_adapt_tries = 0; -+ -+ return skb; -+} -+ -+struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags) -+{ -+ struct sk_buff *nskb = NULL; -+ -+ /* original ip header */ -+ struct iphdr *oiph, *iph; -+ unsigned int iphlen, pyldsz, cpyldsz; -+ z_stream zs; -+ int zresult; -+ -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_decompress: .\n"); -+ -+ if(!skb) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "passed in NULL skb, returning ERROR.\n"); -+ if (flags) *flags |= IPCOMP_PARMERROR; -+ return skb; -+ } -+ -+ if(!ips && sysctl_ipsec_inbound_policy_check) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "passed in NULL ipsec_sa needed for comp alg, returning ERROR.\n"); -+ if (flags) *flags |= IPCOMP_PARMERROR; -+ return skb; -+ } -+ -+ if (!flags) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "passed in NULL flags, returning ERROR.\n"); -+ ipsec_kfree_skb(skb); -+ return NULL; -+ } -+ -+#ifdef NET_21 -+ oiph = skb->nh.iph; -+#else /* NET_21 */ -+ oiph = skb->ip_hdr; -+#endif /* NET_21 */ -+ -+ iphlen = oiph->ihl << 2; -+ -+ if (oiph->protocol != IPPROTO_COMP) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "called with non-IPCOMP packet (protocol=%d)," -+ "skipping decompression.\n", -+ oiph->protocol); -+ *flags |= IPCOMP_PARMERROR; -+ return skb; -+ } -+ -+ if ( (((struct ipcomphdr*)((char*) oiph + iphlen))->ipcomp_flags != 0) -+ || ((((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi -+ != htons(SADB_X_CALG_DEFLATE)) -+ && sysctl_ipsec_inbound_policy_check -+ && (!ips || (ips && (ips->ips_encalg != SADB_X_CALG_DEFLATE)))) ) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "called with incompatible IPCOMP packet (flags=%d, " -+ "cpi=%d), ips-compalg=%d, skipping decompression.\n", -+ ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_flags), -+ ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi), -+ ips ? ips->ips_encalg : 0); -+ *flags |= IPCOMP_PARMERROR; -+ -+ return skb; -+ } -+ -+ if (ntohs(oiph->frag_off) & ~0x4000) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "called with fragmented IPCOMP packet, " -+ "skipping decompression.\n"); -+ *flags |= IPCOMP_PARMERROR; -+ return skb; -+ } -+ -+ /* original compressed payload size */ -+ cpyldsz = ntohs(oiph->tot_len) - iphlen - sizeof(struct ipcomphdr); -+ -+ zs.zalloc = my_zcalloc; -+ zs.zfree = my_zfree; -+ zs.opaque = 0; -+ -+ zs.next_in = (char *) oiph + iphlen + sizeof(struct ipcomphdr); -+ zs.avail_in = cpyldsz; -+ -+ /* Maybe we should be a bit conservative about memory -+ requirements and use inflateInit2 */ -+ /* Beware, that this might make us unable to decompress packets -+ from other implementations - HINT: check PGPnet source code */ -+ /* We want to use inflateInit2 because we don't want the adler -+ header. */ -+ zresult = inflateInit2(&zs, -15); -+ if (zresult != Z_OK) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "inflateInit2() returned error %d (%s), " -+ "skipping decompression.\n", -+ zresult, -+ zs.msg ? zs.msg : zError(zresult)); -+ *flags |= IPCOMP_DECOMPRESSIONERROR; -+ -+ return skb; -+ } -+ -+ /* We have no way of knowing the exact length of the resulting -+ decompressed output before we have actually done the decompression. -+ For now, we guess that the packet will not be bigger than the -+ attached ipsec device's mtu or 16260, whichever is biggest. -+ This may be wrong, since the sender's mtu may be bigger yet. -+ XXX This must be dealt with later XXX -+ */ -+ -+ /* max payload size */ -+ pyldsz = skb->dev ? (skb->dev->mtu < 16260 ? 16260 : skb->dev->mtu) -+ : (65520 - iphlen); -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_decompress: " -+ "max payload size: %d\n", pyldsz); -+ -+ while (pyldsz > (cpyldsz + sizeof(struct ipcomphdr)) && -+ (nskb = skb_copy_ipcomp(skb, -+ pyldsz - cpyldsz - sizeof(struct ipcomphdr), -+ GFP_ATOMIC)) == NULL) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "unable to skb_copy_ipcomp(skb, %d, GFP_ATOMIC), " -+ "trying with less payload size.\n", -+ (int)(pyldsz - cpyldsz - sizeof(struct ipcomphdr))); -+ pyldsz >>=1; -+ } -+ -+ if (!nskb) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "unable to allocate memory, dropping packet.\n"); -+ *flags |= IPCOMP_DECOMPRESSIONERROR; -+ inflateEnd(&zs); -+ -+ return skb; -+ } -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { -+ __u8 *c; -+ int i; -+ -+ c = (__u8*)oiph + iphlen + sizeof(struct ipcomphdr); -+ for(i = 0; i < cpyldsz; i++, c++) { -+ if(!(i % 16)) { -+ printk(KERN_INFO "skb_decompress: before:"); -+ } -+ printk("%02x ", *c); -+ if(!((i + 1) % 16)) { -+ printk("\n"); -+ } -+ } -+ if(i % 16) { -+ printk("\n"); -+ } -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#ifdef NET_21 -+ iph = nskb->nh.iph; -+#else /* NET_21 */ -+ iph = nskb->ip_hdr; -+#endif /* NET_21 */ -+ zs.next_out = (char *)iph + iphlen; -+ zs.avail_out = pyldsz; -+ -+ zresult = inflate(&zs, Z_SYNC_FLUSH); -+ -+ /* work around a bug in zlib, which sometimes wants to taste an extra -+ * byte when being used in the (undocumented) raw deflate mode. -+ */ -+ if (zresult == Z_OK && !zs.avail_in && zs.avail_out) { -+ __u8 zerostuff = 0; -+ -+ zs.next_in = &zerostuff; -+ zs.avail_in = 1; -+ zresult = inflate(&zs, Z_FINISH); -+ } -+ -+ inflateEnd(&zs); -+ if (zresult != Z_STREAM_END) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_error:skb_decompress: " -+ "inflate() returned error %d (%s), " -+ "skipping decompression.\n", -+ zresult, -+ zs.msg ? zs.msg : zError(zresult)); -+ *flags |= IPCOMP_DECOMPRESSIONERROR; -+ ipsec_kfree_skb(nskb); -+ -+ return skb; -+ } -+ -+ /* Update IP header */ -+ /* resulting decompressed size */ -+ pyldsz -= zs.avail_out; -+ iph->tot_len = htons(iphlen + pyldsz); -+ iph->protocol = ((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_nh; -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_decompress: " -+ "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: comp=%d, raw=%d, nh=%d.\n", -+ ips ? ntohl(ips->ips_said.spi) : 0, -+ ips ? ntohl(ips->ips_said.spi) & 0x0000ffff : 0, -+ ntohs(((struct ipcomphdr*)(((char*)oiph)+iphlen))->ipcomp_cpi), -+ cpyldsz, -+ pyldsz, -+ iph->protocol); -+ -+#if 1 /* XXX checksum is done by ipsec_rcv ? */ -+ iph->check = 0; -+ iph->check = ip_fast_csum((char*) iph, iph->ihl); -+#endif -+ -+ /* Update skb length/tail by "unputting" the unused data area */ -+ skb_put(nskb, -zs.avail_out); -+ -+ ipsec_kfree_skb(skb); -+ -+ if (iph->protocol == IPPROTO_COMP) -+ { -+#ifdef CONFIG_IPSEC_DEBUG -+ if(sysctl_ipsec_debug_ipcomp) -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_decompress: " -+ "Eh? inner packet is also compressed, dropping.\n"); -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ ipsec_kfree_skb(nskb); -+ return NULL; -+ } -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { -+ __u8 *c; -+ int i; -+ -+ c = (__u8*)iph + iphlen; -+ for(i = 0; i < pyldsz; i++, c++) { -+ if(!(i % 16)) { -+ printk(KERN_INFO "skb_decompress: result:"); -+ } -+ printk("%02x ", *c); -+ if(!((i + 1) % 16)) { -+ printk("\n"); -+ } -+ } -+ if(i % 16) { -+ printk("\n"); -+ } -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ return nskb; -+} -+ -+ -+/* this is derived from skb_copy() in linux 2.2.14 */ -+/* May be incompatible with other kernel versions!! */ -+static -+struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask) -+{ -+ struct sk_buff *n; -+ struct iphdr *iph; -+ unsigned long offset; -+ unsigned int iphlen; -+ -+ if(!skb) { -+ KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, -+ "klips_debug:skb_copy_ipcomp: " -+ "passed in NULL skb, returning NULL.\n"); -+ return NULL; -+ } -+ -+ /* -+ * Allocate the copy buffer -+ */ -+ -+#ifdef NET_21 -+ iph = skb->nh.iph; -+#else /* NET_21 */ -+ iph = skb->ip_hdr; -+#endif /* NET_21 */ -+ if (!iph) return NULL; -+ iphlen = iph->ihl << 2; -+ -+ n=alloc_skb(skb->end - skb->head + data_growth, gfp_mask); -+ if(n==NULL) -+ return NULL; -+ -+ /* -+ * Shift between the two data areas in bytes -+ */ -+ -+ offset=n->head-skb->head; -+ -+ /* Set the data pointer */ -+ skb_reserve(n,skb->data-skb->head); -+ /* Set the tail pointer and length */ -+ skb_put(n,skb->len+data_growth); -+ /* Copy the bytes up to and including the ip header */ -+ memcpy(n->head, -+ skb->head, -+ ((char *)iph - (char *)skb->head) + iphlen); -+ n->list=NULL; -+ n->next=NULL; -+ n->prev=NULL; -+ n->sk=NULL; -+ n->dev=skb->dev; -+ if (skb->h.raw) -+ n->h.raw=skb->h.raw+offset; -+ else -+ n->h.raw=NULL; -+ n->protocol=skb->protocol; -+#ifdef NET_21 -+ n->csum = 0; -+ n->priority=skb->priority; -+ n->dst=dst_clone(skb->dst); -+ n->nh.raw=skb->nh.raw+offset; -+#ifndef NETDEV_23 -+ n->is_clone=0; -+#endif /* NETDEV_23 */ -+ atomic_set(&n->users, 1); -+ n->destructor = NULL; -+ n->security=skb->security; -+ memcpy(n->cb, skb->cb, sizeof(skb->cb)); -+#ifdef CONFIG_IP_FIREWALL -+ n->fwmark = skb->fwmark; -+#endif -+#else /* NET_21 */ -+ n->link3=NULL; -+ n->when=skb->when; -+ n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset); -+ n->saddr=skb->saddr; -+ n->daddr=skb->daddr; -+ n->raddr=skb->raddr; -+ n->seq=skb->seq; -+ n->end_seq=skb->end_seq; -+ n->ack_seq=skb->ack_seq; -+ n->acked=skb->acked; -+ n->free=1; -+ n->arp=skb->arp; -+ n->tries=0; -+ n->lock=0; -+ n->users=0; -+ memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv)); -+#endif /* NET_21 */ -+ if (skb->mac.raw) -+ n->mac.raw=skb->mac.raw+offset; -+ else -+ n->mac.raw=NULL; -+#ifndef NETDEV_23 -+ n->used=skb->used; -+#endif /* !NETDEV_23 */ -+ n->pkt_type=skb->pkt_type; -+#ifndef NETDEV_23 -+ n->pkt_bridged=skb->pkt_bridged; -+#endif /* NETDEV_23 */ -+ n->ip_summed=0; -+ n->stamp=skb->stamp; -+#ifndef NETDEV_23 /* this seems to have been removed in 2.4 */ -+#if defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE) -+ n->shapelatency=skb->shapelatency; /* Latency on frame */ -+ n->shapeclock=skb->shapeclock; /* Time it should go out */ -+ n->shapelen=skb->shapelen; /* Frame length in clocks */ -+ n->shapestamp=skb->shapestamp; /* Stamp for shaper */ -+ n->shapepend=skb->shapepend; /* Pending */ -+#endif /* defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE) */ -+#endif /* NETDEV_23 */ -+#ifdef CONFIG_HIPPI -+ n->private.ifield=skb->private.ifield; -+#endif /* CONFIG_HIPPI */ -+ -+ return n; -+} ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_ah.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,363 @@ -+/* -+ * processing code for AH -+ * Copyright (C) 2003-2004 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_ah_c_version[] = "RCSID $Id$"; -+#include -+#include -+ -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define proto_priv cb -+#endif /* NET21 */ -+#include -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipsec_xmit.h" -+ -+#include "openswan/ipsec_auth.h" -+ -+#ifdef CONFIG_IPSEC_AH -+#include "openswan/ipsec_ah.h" -+#endif /* CONFIG_IPSEC_AH */ -+ -+#include "openswan/ipsec_proto.h" -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_ah = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+__u32 zeroes[AH_AMAX]; -+ -+#ifdef CONFIG_IPSEC_AH -+enum ipsec_rcv_value -+ipsec_rcv_ah_checks(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb) -+{ -+ int ahminlen; -+ -+ ahminlen = irs->hard_header_len + sizeof(struct iphdr); -+ -+ /* take care not to deref this pointer until we check the minlen though */ -+ irs->protostuff.ahstuff.ahp = (struct ahhdr *) (skb->data + irs->iphlen); -+ -+ if((skb->len < ahminlen+sizeof(struct ahhdr)) || -+ (skb->len < ahminlen+(irs->protostuff.ahstuff.ahp->ah_hl << 2))) { -+ KLIPS_PRINT(debug_rcv & DB_RX_INAU, -+ "klips_debug:ipsec_rcv: " -+ "runt ah packet of skb->len=%d received from %s, dropped.\n", -+ skb->len, -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_BADLEN; -+ } -+ -+ irs->said.spi = irs->protostuff.ahstuff.ahp->ah_spi; -+ -+ /* XXX we only support the one 12-byte authenticator for now */ -+ if(irs->protostuff.ahstuff.ahp->ah_hl != ((AHHMAC_HASHLEN+AHHMAC_RPLLEN) >> 2)) { -+ KLIPS_PRINT(debug_rcv & DB_RX_INAU, -+ "klips_debug:ipsec_rcv: " -+ "bad authenticator length %ld, expected %lu from %s.\n", -+ (long)(irs->protostuff.ahstuff.ahp->ah_hl << 2), -+ (unsigned long) sizeof(struct ahhdr), -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_BADLEN; -+ } -+ -+ return IPSEC_RCV_OK; -+} -+ -+ -+enum ipsec_rcv_value -+ipsec_rcv_ah_setup_auth(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb, -+ __u32 *replay, -+ unsigned char **authenticator) -+{ -+ struct ahhdr *ahp = irs->protostuff.ahstuff.ahp; -+ -+ *replay = ntohl(ahp->ah_rpl); -+ *authenticator = ahp->ah_data; -+ -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_rcv_value -+ipsec_rcv_ah_authcalc(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb) -+{ -+ struct auth_alg *aa; -+ struct ahhdr *ahp = irs->protostuff.ahstuff.ahp; -+ union { -+ MD5_CTX md5; -+ SHA1_CTX sha1; -+ } tctx; -+ struct iphdr ipo; -+ int ahhlen; -+ -+ aa = irs->authfuncs; -+ -+ /* copy the initialized keying material */ -+ memcpy(&tctx, irs->ictx, irs->ictx_len); -+ -+ ipo = *irs->ipp; -+ ipo.tos = 0; /* mutable RFC 2402 3.3.3.1.1.1 */ -+ ipo.frag_off = 0; -+ ipo.ttl = 0; -+ ipo.check = 0; -+ -+ -+ /* do the sanitized header */ -+ (*aa->update)((void*)&tctx, (caddr_t)&ipo, sizeof(struct iphdr)); -+ -+ /* XXX we didn't do the options here! */ -+ -+ /* now do the AH header itself */ -+ ahhlen = AH_BASIC_LEN + (ahp->ah_hl << 2); -+ (*aa->update)((void*)&tctx, (caddr_t)ahp, ahhlen - AHHMAC_HASHLEN); -+ -+ /* now, do some zeroes */ -+ (*aa->update)((void*)&tctx, (caddr_t)zeroes, AHHMAC_HASHLEN); -+ -+ /* finally, do the packet contents themselves */ -+ (*aa->update)((void*)&tctx, -+ (caddr_t)skb->data + irs->iphlen + ahhlen, -+ skb->len - irs->iphlen - ahhlen); -+ -+ (*aa->final)(irs->hash, (void *)&tctx); -+ -+ memcpy(&tctx, irs->octx, irs->octx_len); -+ -+ (*aa->update)((void *)&tctx, irs->hash, aa->hashlen); -+ (*aa->final)(irs->hash, (void *)&tctx); -+ -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_rcv_value -+ipsec_rcv_ah_decap(struct ipsec_rcv_state *irs) -+{ -+ struct ahhdr *ahp = irs->protostuff.ahstuff.ahp; -+ struct sk_buff *skb; -+ int ahhlen; -+ -+ skb=irs->skb; -+ -+ ahhlen = AH_BASIC_LEN + (ahp->ah_hl << 2); -+ -+ irs->ipp->tot_len = htons(ntohs(irs->ipp->tot_len) - ahhlen); -+ irs->next_header = ahp->ah_nh; -+ -+ /* -+ * move the IP header forward by the size of the AH header, which -+ * will remove the the AH header from the packet. -+ */ -+ memmove((void *)(skb->data + ahhlen), -+ (void *)(skb->data), irs->iphlen); -+ -+ ipsec_rcv_dmp("ah postmove", skb->data, skb->len); -+ -+ /* skb_pull below, will move up by ahhlen */ -+ -+ /* XXX not clear how this can happen, as the message indicates */ -+ if(skb->len < ahhlen) { -+ printk(KERN_WARNING -+ "klips_error:ipsec_rcv: " -+ "tried to skb_pull ahhlen=%d, %d available. This should never happen, please report.\n", -+ ahhlen, -+ (int)(skb->len)); -+ return IPSEC_RCV_DECAPFAIL; -+ } -+ skb_pull(skb, ahhlen); -+ -+ irs->ipp = (struct iphdr *)skb->data; -+ -+ ipsec_rcv_dmp("ah postpull", skb->data, skb->len); -+ -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_xmit_ah_setup(struct ipsec_xmit_state *ixs) -+{ -+ struct iphdr ipo; -+ struct ahhdr *ahp; -+ __u8 hash[AH_AMAX]; -+ union { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ MD5_CTX md5; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ SHA1_CTX sha1; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ } tctx; -+ unsigned char *dat = (unsigned char *)ixs->iph; -+ -+ ahp = (struct ahhdr *)(dat + ixs->iphlen); -+ ahp->ah_spi = ixs->ipsp->ips_said.spi; -+ ahp->ah_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); -+ ahp->ah_rv = 0; -+ ahp->ah_nh = ixs->iph->protocol; -+ ahp->ah_hl = (sizeof(struct ahhdr) >> 2) - sizeof(__u64)/sizeof(__u32); -+ ixs->iph->protocol = IPPROTO_AH; -+ ipsec_xmit_dmp("ahp", (char*)ahp, sizeof(*ahp)); -+ -+ ipo = *ixs->iph; -+ ipo.tos = 0; -+ ipo.frag_off = 0; -+ ipo.ttl = 0; -+ ipo.check = 0; -+ ipsec_xmit_dmp("ipo", (char*)&ipo, sizeof(ipo)); -+ -+ switch(ixs->ipsp->ips_authalg) { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ ipsec_xmit_dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr)); -+ ipsec_xmit_dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (unsigned char *)ahp, -+ sizeof(struct ahhdr) - sizeof(ahp->ah_data)); -+ ipsec_xmit_dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN); -+ ipsec_xmit_dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, dat + ixs->iphlen + sizeof(struct ahhdr), -+ ixs->skb->len - ixs->iphlen - sizeof(struct ahhdr)); -+ ipsec_xmit_dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ ipsec_xmit_dmp("ictx hash", (char*)&hash, sizeof(hash)); -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ ipsec_xmit_dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, hash, AHMD596_ALEN); -+ ipsec_xmit_dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ ipsec_xmit_dmp("octx hash", (char*)&hash, sizeof(hash)); -+ -+ memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ SHA1Update(&tctx.sha1, (unsigned char *)&ipo, sizeof (struct iphdr)); -+ SHA1Update(&tctx.sha1, (unsigned char *)ahp, sizeof(struct ahhdr) - sizeof(ahp->ah_data)); -+ SHA1Update(&tctx.sha1, (unsigned char *)zeroes, AHHMAC_HASHLEN); -+ SHA1Update(&tctx.sha1, dat + ixs->iphlen + sizeof(struct ahhdr), -+ ixs->skb->len - ixs->iphlen - sizeof(struct ahhdr)); -+ SHA1Final(hash, &tctx.sha1); -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); -+ SHA1Final(hash, &tctx.sha1); -+ -+ memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_AH_BADALG; -+ } -+#ifdef NET_21 -+ ixs->skb->h.raw = (unsigned char*)ahp; -+#endif /* NET_21 */ -+ -+ return IPSEC_XMIT_OK; -+} -+ -+struct xform_functions ah_xform_funcs[]={ -+ { rcv_checks: ipsec_rcv_ah_checks, -+ rcv_setup_auth: ipsec_rcv_ah_setup_auth, -+ rcv_calc_auth: ipsec_rcv_ah_authcalc, -+ rcv_decrypt: ipsec_rcv_ah_decap, -+ -+ xmit_setup: ipsec_xmit_ah_setup, -+ xmit_headroom: sizeof(struct ahhdr), -+ xmit_needtailroom: 0, -+ }, -+}; -+ -+struct inet_protocol ah_protocol = -+{ -+ ipsec_rcv, /* AH handler */ -+ NULL, /* TUNNEL error control */ -+#ifdef NETDEV_25 -+ 1, /* no policy */ -+#else -+ 0, /* next */ -+ IPPROTO_AH, /* protocol ID */ -+ 0, /* copy */ -+ NULL, /* data */ -+ "AH" /* name */ -+#endif -+}; -+ -+#endif /* CONFIG_IPSEC_AH */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.2 2004/04/06 02:49:25 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_alg.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,953 @@ -+/* -+ * Modular extensions service and registration functions -+ * -+ * Author: JuanJo Ciarlante -+ * -+ * Version: 0.8.1 -+ * -+ * ipsec_alg.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ */ -+#ifdef CONFIG_IPSEC_ALG -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#include -+#include -+#include /* memcmp() */ -+#include /* get_random_bytes() */ -+#include /* error codes */ -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define proto_priv cb -+#endif /* NET21 */ -+#include "openswan/ipsec_param.h" -+#include -+#include "openswan/ipsec_sa.h" -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+#if defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH) -+# include "openswan/ipsec_ah.h" -+#endif /* defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH) */ -+#ifdef CONFIG_IPSEC_ESP -+# include "openswan/ipsec_esp.h" -+#endif /* !CONFIG_IPSEC_ESP */ -+#ifdef CONFIG_IPSEC_IPCOMP -+# include "openswan/ipcomp.h" -+#endif /* CONFIG_IPSEC_COMP */ -+ -+#include -+#include -+ -+#include "openswan/ipsec_alg.h" -+ -+#ifndef CONFIG_IPSEC_ALG -+#error This file _MUST_ be compiled with CONFIG_IPSEC_ALG enabled ! -+#endif -+#if SADB_EALG_MAX < 255 -+#warning Compiling with limited ESP support ( SADB_EALG_MAX < 256 ) -+#endif -+ -+static rwlock_t ipsec_alg_lock = RW_LOCK_UNLOCKED; -+#define IPSEC_ALG_HASHSZ 16 /* must be power of 2, even 2^0=1 */ -+static struct list_head ipsec_alg_hash_table[IPSEC_ALG_HASHSZ]; -+ -+/* Old gcc's will fail here */ -+#define barf_out(fmt, args...) do { printk(KERN_ERR "%s: (%s) " fmt, __FUNCTION__, ixt->ixt_name , ## args)\ -+ ; goto out; } while(0) -+ -+/* -+ * Must be already protected by lock -+ */ -+static void __ipsec_alg_usage_inc(struct ipsec_alg *ixt) { -+ if (ixt->ixt_module) -+ __MOD_INC_USE_COUNT(ixt->ixt_module); -+ atomic_inc(&ixt->ixt_refcnt); -+} -+static void __ipsec_alg_usage_dec(struct ipsec_alg *ixt) { -+ atomic_dec(&ixt->ixt_refcnt); -+ if (ixt->ixt_module) -+ __MOD_DEC_USE_COUNT(ixt->ixt_module); -+} -+/* -+ * simple hash function, optimized for 0-hash (1 list) special -+ * case -+ */ -+#if IPSEC_ALG_HASHSZ > 1 -+static inline unsigned ipsec_alg_hashfn(int alg_type, int alg_id) { -+ return ((alg_type^alg_id)&(IPSEC_ALG_HASHSZ-1)); -+} -+#else -+#define ipsec_alg_hashfn(x,y) (0) -+#endif -+ -+/***************************************************************** -+ * -+ * INTERNAL table handling: insert, delete, find -+ * -+ *****************************************************************/ -+ -+/* -+ * hash table initialization, called from ipsec_alg_init() -+ */ -+static void ipsec_alg_hash_init(void) { -+ struct list_head *head = ipsec_alg_hash_table; -+ int i = IPSEC_ALG_HASHSZ; -+ do { -+ INIT_LIST_HEAD(head); -+ head++; -+ i--; -+ } while (i); -+} -+/* -+ * hash list lookup by {alg_type, alg_id} and table head, -+ * must be already protected by lock -+ */ -+static struct ipsec_alg *__ipsec_alg_find(unsigned alg_type, unsigned alg_id, struct list_head * head) { -+ struct list_head *p; -+ struct ipsec_alg *ixt=NULL; -+ for (p=head->next; p!=head; p=p->next) { -+ ixt = list_entry(p, struct ipsec_alg, ixt_list); -+ if (ixt->ixt_alg_type == alg_type && ixt->ixt_alg_id==alg_id) { -+ goto out; -+ } -+ } -+ ixt=NULL; -+out: -+ return ixt; -+} -+/* -+ * inserts (in front) a new entry in hash table, -+ * called from ipsec_alg_register() when new algorithm is registered. -+ */ -+static int ipsec_alg_insert(struct ipsec_alg *ixt) { -+ int ret=-EINVAL; -+ unsigned hashval=ipsec_alg_hashfn(ixt->ixt_alg_type, ixt->ixt_alg_id); -+ struct list_head *head= ipsec_alg_hash_table + hashval; -+ struct ipsec_alg *ixt_cur; -+ /* new element must be virgin ... */ -+ if (ixt->ixt_list.next != &ixt->ixt_list || -+ ixt->ixt_list.prev != &ixt->ixt_list) { -+ printk(KERN_ERR "ipsec_alg_insert: ixt object \"%s\" " -+ "list head not initialized\n", -+ ixt->ixt_name); -+ return ret; -+ } -+ write_lock_bh(&ipsec_alg_lock); -+ ixt_cur = __ipsec_alg_find(ixt->ixt_alg_type, ixt->ixt_alg_id, head); -+ /* if previous (current) ipsec_alg found check excl flag of _anyone_ */ -+ if (ixt_cur && ((ixt->ixt_state|ixt_cur->ixt_state) & IPSEC_ALG_ST_EXCL)) -+ barf_out("ipsec_alg for alg_type=%d, alg_id=%d already exist. " -+ "Not loaded (ret=%d).\n", -+ ixt->ixt_alg_type, -+ ixt->ixt_alg_id, ret=-EEXIST); -+ list_add(&ixt->ixt_list, head); -+ ixt->ixt_state |= IPSEC_ALG_ST_REGISTERED; -+ ret=0; -+out: -+ write_unlock_bh(&ipsec_alg_lock); -+ return ret; -+} -+/* -+ * deletes an existing entry in hash table, -+ * called from ipsec_alg_unregister() when algorithm is unregistered. -+ */ -+static int ipsec_alg_delete(struct ipsec_alg *ixt) { -+ write_lock_bh(&ipsec_alg_lock); -+ list_del(&ixt->ixt_list); -+ write_unlock_bh(&ipsec_alg_lock); -+ return 0; -+} -+/* -+ * here @user context (read-only when @kernel bh context) -+ * -> no bh disabling -+ * -+ * called from ipsec_sa_init() -> ipsec_alg_sa_init() -+ */ -+static struct ipsec_alg *ipsec_alg_get(int alg_type, int alg_id) { -+ unsigned hashval=ipsec_alg_hashfn(alg_type, alg_id); -+ struct list_head *head= ipsec_alg_hash_table + hashval; -+ struct ipsec_alg *ixt; -+ read_lock(&ipsec_alg_lock); -+ ixt=__ipsec_alg_find(alg_type, alg_id, head); -+ if (ixt) __ipsec_alg_usage_inc(ixt); -+ read_unlock(&ipsec_alg_lock); -+ return ixt; -+} -+ -+static void ipsec_alg_put(struct ipsec_alg *ixt) { -+ __ipsec_alg_usage_dec((struct ipsec_alg *)ixt); -+} -+ -+/***************************************************************** -+ * -+ * INTERFACE for ENC services: key creation, encrypt function -+ * -+ *****************************************************************/ -+ -+/* -+ * main encrypt service entry point -+ * called from ipsec_rcv() with encrypt=IPSEC_ALG_DECRYPT and -+ * ipsec_tunnel_start_xmit with encrypt=IPSEC_ALG_ENCRYPT -+ */ -+int ipsec_alg_esp_encrypt(struct ipsec_sa *sa_p, __u8 * idat, int ilen, const __u8 * iv, int encrypt) { -+ int ret; -+ struct ipsec_alg_enc *ixt_e=sa_p->ips_alg_enc; -+ KLIPS_PRINT(debug_rcv||debug_tunnel, -+ "klips_debug:ipsec_alg_esp_encrypt: " -+ "entering with encalg=%d, ixt_e=%p\n", -+ sa_p->ips_encalg, ixt_e); -+ if (!ixt_e) { -+ KLIPS_PRINT(debug_rcv||debug_tunnel, -+ "klips_debug:ipsec_alg_esp_encrypt: " -+ "NULL ipsec_alg_enc object\n"); -+ return -1; -+ } -+ KLIPS_PRINT(debug_rcv||debug_tunnel, -+ "klips_debug:ipsec_alg_esp_encrypt: " -+ "calling cbc_encrypt encalg=%d " -+ "ips_key_e=%p idat=%p ilen=%d iv=%p, encrypt=%d\n", -+ sa_p->ips_encalg, -+ sa_p->ips_key_e, idat, ilen, iv, encrypt); -+ ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, sa_p->ips_key_e, idat, ilen, iv, encrypt); -+ KLIPS_PRINT(debug_rcv||debug_tunnel, -+ "klips_debug:ipsec_alg_esp_encrypt: " -+ "returned ret=%d\n", -+ ret); -+ return ret; -+} -+/* -+ * encryption key context creation function -+ * called from pfkey_v2_parser.c:pfkey_ips_init() -+ */ -+int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p) { -+ int ret=-EINVAL; -+ int keyminbits, keymaxbits; -+ caddr_t ekp; -+ struct ipsec_alg_enc *ixt_e=sa_p->ips_alg_enc; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_alg_enc_key_create: " -+ "entering with encalg=%d ixt_e=%p\n", -+ sa_p->ips_encalg, ixt_e); -+ if (!ixt_e) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_alg_enc_key_create: " -+ "NULL ipsec_alg_enc object\n"); -+ return -EPROTO; -+ } -+ -+ /* -+ * grRRR... DES 7bits jurassic stuff ... f*ckk --jjo -+ */ -+ switch(ixt_e->ixt_alg_id) { -+ case ESP_3DES: -+ keyminbits=keymaxbits=192;break; -+ case ESP_DES: -+ keyminbits=keymaxbits=64;break; -+ default: -+ keyminbits=ixt_e->ixt_keyminbits; -+ keymaxbits=ixt_e->ixt_keymaxbits; -+ } -+ if(sa_p->ips_key_bits_eips_key_bits_e>keymaxbits) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_alg_enc_key_create: " -+ "incorrect encryption key size for id=%d: %d bits -- " -+ "must be between %d,%d bits\n" /*octets (bytes)\n"*/, -+ ixt_e->ixt_alg_id, -+ sa_p->ips_key_bits_e, keyminbits, keymaxbits); -+ ret=-EINVAL; -+ goto ixt_out; -+ } -+ /* save encryption key pointer */ -+ ekp = sa_p->ips_key_e; -+ -+ -+ if (ixt_e->ixt_e_new_key) { -+ sa_p->ips_key_e = ixt_e->ixt_e_new_key(ixt_e, -+ ekp, sa_p->ips_key_bits_e/8); -+ ret = (sa_p->ips_key_e)? 0 : -EINVAL; -+ } else { -+ if((sa_p->ips_key_e = (caddr_t) -+ kmalloc((sa_p->ips_key_e_size = ixt_e->ixt_e_ctx_size), -+ GFP_ATOMIC)) == NULL) { -+ ret=-ENOMEM; -+ goto ixt_out; -+ } -+ /* zero-out key_e */ -+ memset(sa_p->ips_key_e, 0, sa_p->ips_key_e_size); -+ -+ /* I cast here to allow more decoupling in alg module */ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_alg_enc_key_create: about to call:" -+ "set_key(key_e=%p, ekp=%p, key_size=%d)\n", -+ (caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8); -+ ret = ixt_e->ixt_e_set_key(ixt_e, (caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8); -+ } -+ /* paranoid */ -+ memset(ekp, 0, sa_p->ips_key_bits_e/8); -+ kfree(ekp); -+ixt_out: -+ return ret; -+} -+ -+/*************************************************************** -+ * -+ * INTERFACE for AUTH services: key creation, hash functions -+ * -+ ***************************************************************/ -+ -+/* -+ * auth key context creation function -+ * called from pfkey_v2_parser.c:pfkey_ips_init() -+ */ -+int ipsec_alg_auth_key_create(struct ipsec_sa *sa_p) { -+ int ret=-EINVAL; -+ struct ipsec_alg_auth *ixt_a=sa_p->ips_alg_auth; -+ int keyminbits, keymaxbits; -+ unsigned char *akp; -+ unsigned int aks; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_alg_auth_key_create: " -+ "entering with authalg=%d ixt_a=%p\n", -+ sa_p->ips_authalg, ixt_a); -+ if (!ixt_a) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_alg_auth_key_create: " -+ "NULL ipsec_alg_auth object\n"); -+ return -EPROTO; -+ } -+ keyminbits=ixt_a->ixt_keyminbits; -+ keymaxbits=ixt_a->ixt_keymaxbits; -+ if(sa_p->ips_key_bits_aips_key_bits_a>keymaxbits) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_alg_auth_key_create: incorrect auth" -+ "key size: %d bits -- must be between %d,%d bits\n"/*octets (bytes)\n"*/, -+ sa_p->ips_key_bits_a, keyminbits, keymaxbits); -+ ret=-EINVAL; -+ goto ixt_out; -+ } -+ /* save auth key pointer */ -+ sa_p->ips_auth_bits = ixt_a->ixt_a_keylen * 8; /* XXX XXX */ -+ akp = sa_p->ips_key_a; -+ aks = sa_p->ips_key_a_size; -+ -+ /* will hold: 2 ctx and a blocksize buffer: kb */ -+ sa_p->ips_key_a_size = ixt_a->ixt_a_ctx_size; -+ if((sa_p->ips_key_a = -+ (caddr_t) kmalloc(sa_p->ips_key_a_size, GFP_ATOMIC)) == NULL) { -+ ret=-ENOMEM; -+ goto ixt_out; -+ } -+ ixt_a->ixt_a_hmac_set_key(ixt_a, sa_p->ips_key_a, akp, sa_p->ips_key_bits_a/8); /* XXX XXX */ -+ ret=0; -+ memset(akp, 0, aks); -+ kfree(akp); -+ -+ixt_out: -+ return ret; -+} -+ -+ -+int ipsec_alg_sa_esp_hash(const struct ipsec_sa *sa_p, const __u8 *espp, int len, __u8 *hash, int hashlen) { -+ struct ipsec_alg_auth *ixt_a=sa_p->ips_alg_auth; -+ if (!ixt_a) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_sa_esp_hash: " -+ "NULL ipsec_alg_auth object\n"); -+ return -EPROTO; -+ } -+ KLIPS_PRINT(debug_tunnel|debug_rcv, -+ "klips_debug:ipsec_sa_esp_hash: " -+ "hashing %p (%d bytes) to %p (%d bytes)\n", -+ espp, len, -+ hash, hashlen); -+ ixt_a->ixt_a_hmac_hash(ixt_a, -+ sa_p->ips_key_a, -+ espp, len, -+ hash, hashlen); -+ return 0; -+} -+ -+/*************************************************************** -+ * -+ * INTERFACE for module loading,testing, and unloading -+ * -+ ***************************************************************/ -+ -+/* validation for registering (enc) module */ -+static int check_enc(struct ipsec_alg_enc *ixt) { -+ int ret=-EINVAL; -+ if (ixt->ixt_alg_id==0 || ixt->ixt_alg_id > SADB_EALG_MAX) -+ barf_out("invalid alg_id=%d >= %d\n", ixt->ixt_alg_id, SADB_EALG_MAX); -+ if (ixt->ixt_blocksize==0) /* || ixt->ixt_blocksize%2) need for ESP_NULL */ -+ barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_blocksize); -+ if (ixt->ixt_keyminbits==0 && ixt->ixt_keymaxbits==0 && ixt->ixt_e_keylen==0) -+ goto zero_key_ok; -+ if (ixt->ixt_keyminbits==0) -+ barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_keyminbits); -+ if (ixt->ixt_keymaxbits==0) -+ barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_keymaxbits); -+ if (ixt->ixt_e_keylen==0) -+ barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_e_keylen); -+zero_key_ok: -+ if (ixt->ixt_e_ctx_size==0 && ixt->ixt_e_new_key == NULL) -+ barf_out(KERN_ERR "invalid key_e_size=%d and ixt_e_new_key=NULL\n", ixt->ixt_e_ctx_size); -+ if (ixt->ixt_e_cbc_encrypt==NULL) -+ barf_out(KERN_ERR "e_cbc_encrypt() must be not NULL\n"); -+ ret=0; -+out: -+ return ret; -+} -+ -+/* validation for registering (auth) module */ -+static int check_auth(struct ipsec_alg_auth *ixt) -+{ -+ int ret=-EINVAL; -+ if (ixt->ixt_alg_id==0 || ixt->ixt_alg_id > SADB_AALG_MAX) -+ barf_out("invalid alg_id=%d > %d (SADB_AALG_MAX)\n", ixt->ixt_alg_id, SADB_AALG_MAX); -+ if (ixt->ixt_blocksize==0 || ixt->ixt_blocksize%2) -+ barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_blocksize); -+ if (ixt->ixt_blocksize>AH_BLKLEN_MAX) -+ barf_out(KERN_ERR "sorry blocksize=%d > %d. " -+ "Please increase AH_BLKLEN_MAX and recompile\n", -+ ixt->ixt_blocksize, -+ AH_BLKLEN_MAX); -+ if (ixt->ixt_keyminbits==0 && ixt->ixt_keymaxbits==0 && ixt->ixt_a_keylen==0) -+ goto zero_key_ok; -+ if (ixt->ixt_keyminbits==0) -+ barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_keyminbits); -+ if (ixt->ixt_keymaxbits==0) -+ barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_keymaxbits); -+ if (ixt->ixt_keymaxbits!=ixt->ixt_keyminbits) -+ barf_out(KERN_ERR "keymaxbits must equal keyminbits (not sure).\n"); -+ if (ixt->ixt_a_keylen==0) -+ barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_a_keylen); -+zero_key_ok: -+ if (ixt->ixt_a_ctx_size==0) -+ barf_out(KERN_ERR "invalid a_ctx_size=%d\n", ixt->ixt_a_ctx_size); -+ if (ixt->ixt_a_hmac_set_key==NULL) -+ barf_out(KERN_ERR "a_hmac_set_key() must be not NULL\n"); -+ if (ixt->ixt_a_hmac_hash==NULL) -+ barf_out(KERN_ERR "a_hmac_hash() must be not NULL\n"); -+ ret=0; -+out: -+ return ret; -+} -+ -+/* -+ * Generic (enc, auth) registration entry point -+ */ -+int register_ipsec_alg(struct ipsec_alg *ixt) { -+ int ret=-EINVAL; -+ /* Validation */ -+ if (ixt==NULL) -+ barf_out("NULL ipsec_alg object passed\n"); -+ if ((ixt->ixt_version&0xffffff00) != (IPSEC_ALG_VERSION&0xffffff00)) -+ barf_out("incorrect version: %d.%d.%d-%d, " -+ "must be %d.%d.%d[-%d]\n", -+ IPSEC_ALG_VERSION_QUAD(ixt->ixt_version), -+ IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION)); -+ switch(ixt->ixt_alg_type) { -+ case IPSEC_ALG_TYPE_AUTH: -+ if ((ret=check_auth((struct ipsec_alg_auth *)ixt)<0)) -+ goto out; -+ break; -+ case IPSEC_ALG_TYPE_ENCRYPT: -+ if ((ret=check_enc((struct ipsec_alg_enc *)ixt)<0)) -+ goto out; -+ /* -+ * Adapted two lines below: -+ * ivlen == 0 is possible (NULL enc has blocksize==1) -+ * -+ * fixed NULL support by David De Reu -+ */ -+ if (ixt->ixt_ivlen == 0 && ixt->ixt_blocksize > 1) -+ ixt->ixt_ivlen = ixt->ixt_blocksize*8; -+ break; -+ default: -+ barf_out("alg_type=%d not supported\n", ixt->ixt_alg_type); -+ } -+ INIT_LIST_HEAD(&ixt->ixt_list); -+ ret = ipsec_alg_insert(ixt); -+ if (ret<0) -+ barf_out(KERN_WARNING "ipsec_alg for alg_id=%d failed." -+ "Not loaded (ret=%d).\n", -+ ixt->ixt_alg_id, ret); -+ -+ ret = pfkey_list_insert_supported((struct supported *)&ixt->ixt_support, &(pfkey_supported_list[SADB_SATYPE_ESP])); -+ if (ret==0) { -+ ixt->ixt_state |= IPSEC_ALG_ST_SUPP; -+ /* send register event to userspace */ -+ pfkey_register_reply(SADB_SATYPE_ESP, NULL); -+ } else -+ printk(KERN_ERR "pfkey_list_insert_supported returned %d. " -+ "Loading anyway.\n", ret); -+ ret=0; -+out: -+ return ret; -+} -+ -+/* -+ * unregister ipsec_alg object from own tables, if -+ * success => calls pfkey_list_remove_supported() -+ */ -+int unregister_ipsec_alg(struct ipsec_alg *ixt) { -+ int ret= -EINVAL; -+ switch(ixt->ixt_alg_type) { -+ case IPSEC_ALG_TYPE_AUTH: -+ case IPSEC_ALG_TYPE_ENCRYPT: -+ break; -+ default: -+ /* this is not a typo :) */ -+ barf_out("frog found in list (\"%s\"): ixt_p=NULL\n", -+ ixt->ixt_name); -+ } -+ -+ ret=ipsec_alg_delete(ixt); -+ if (ixt->ixt_state&IPSEC_ALG_ST_SUPP) { -+ ixt->ixt_state &= ~IPSEC_ALG_ST_SUPP; -+ pfkey_list_remove_supported((struct supported *)&ixt->ixt_support, &(pfkey_supported_list[SADB_SATYPE_ESP])); -+ /* send register event to userspace */ -+ pfkey_register_reply(SADB_SATYPE_ESP, NULL); -+ } -+ -+out: -+ return ret; -+} -+ -+/* -+ * Must be called from user context -+ * used at module load type for testing algo implementation -+ */ -+static int ipsec_alg_test_encrypt(int enc_alg, int test) { -+ int ret; -+ caddr_t buf = NULL; -+ int iv_size, keysize, key_e_size; -+ struct ipsec_alg_enc *ixt_e; -+ void *tmp_key_e = NULL; -+ #define BUFSZ 1024 -+ #define MARGIN 0 -+ #define test_enc (buf+MARGIN) -+ #define test_dec (test_enc+BUFSZ+MARGIN) -+ #define test_tmp (test_dec+BUFSZ+MARGIN) -+ #define test_key_e (test_tmp+BUFSZ+MARGIN) -+ #define test_iv (test_key_e+key_e_size+MARGIN) -+ #define test_key (test_iv+iv_size+MARGIN) -+ #define test_size (BUFSZ*3+key_e_size+iv_size+keysize+MARGIN*7) -+ ixt_e=(struct ipsec_alg_enc *)ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, enc_alg); -+ if (ixt_e==NULL) { -+ KLIPS_PRINT(1, -+ "klips_debug: ipsec_alg_test_encrypt: " -+ "encalg=%d object not found\n", -+ enc_alg); -+ ret=-EINVAL; -+ goto out; -+ } -+ iv_size=ixt_e->ixt_ivlen / 8; -+ key_e_size=ixt_e->ixt_e_ctx_size; -+ keysize=ixt_e->ixt_e_keylen; -+ KLIPS_PRINT(1, -+ "klips_debug: ipsec_alg_test_encrypt: " -+ "enc_alg=%d blocksize=%d key_e_size=%d keysize=%d\n", -+ enc_alg, iv_size, key_e_size, keysize); -+ if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) { -+ ret= -ENOMEM; -+ goto out; -+ } -+ get_random_bytes(test_key, keysize); -+ get_random_bytes(test_iv, iv_size); -+ if (ixt_e->ixt_e_new_key) { -+ tmp_key_e = ixt_e->ixt_e_new_key(ixt_e, test_key, keysize); -+ ret = tmp_key_e ? 0 : -EINVAL; -+ } else { -+ tmp_key_e = test_key_e; -+ ret = ixt_e->ixt_e_set_key(ixt_e, test_key_e, test_key, keysize); -+ } -+ if (ret < 0) -+ goto out; -+ get_random_bytes(test_enc, BUFSZ); -+ memcpy(test_tmp, test_enc, BUFSZ); -+ ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_enc, BUFSZ, test_iv, 1); -+ printk(KERN_INFO -+ "klips_info: ipsec_alg_test_encrypt: " -+ "cbc_encrypt=1 ret=%d\n", -+ ret); -+ ret=memcmp(test_enc, test_tmp, BUFSZ); -+ printk(KERN_INFO -+ "klips_info: ipsec_alg_test_encrypt: " -+ "memcmp(enc, tmp) ret=%d: %s\n", ret, -+ ret!=0? "OK. (encr->DIFFers)" : "FAIL! (encr->SAME)" ); -+ memcpy(test_dec, test_enc, BUFSZ); -+ ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_dec, BUFSZ, test_iv, 0); -+ printk(KERN_INFO -+ "klips_info: ipsec_alg_test_encrypt: " -+ "cbc_encrypt=0 ret=%d\n", ret); -+ ret=memcmp(test_dec, test_tmp, BUFSZ); -+ printk(KERN_INFO -+ "klips_info: ipsec_alg_test_encrypt: " -+ "memcmp(dec,tmp) ret=%d: %s\n", ret, -+ ret==0? "OK. (encr->decr->SAME)" : "FAIL! (encr->decr->DIFFers)" ); -+ { -+ /* Shamelessly taken from drivers/md sources O:) */ -+ unsigned long now; -+ int i, count, max=0; -+ int encrypt, speed; -+ for (encrypt=0; encrypt <2;encrypt ++) { -+ for (i = 0; i < 5; i++) { -+ now = jiffies; -+ count = 0; -+ while (jiffies == now) { -+ mb(); -+ ixt_e->ixt_e_cbc_encrypt(ixt_e, -+ tmp_key_e, test_tmp, -+ BUFSZ, test_iv, encrypt); -+ mb(); -+ count++; -+ mb(); -+ } -+ if (count > max) -+ max = count; -+ } -+ speed = max * (HZ * BUFSZ / 1024); -+ printk(KERN_INFO -+ "klips_info: ipsec_alg_test_encrypt: " -+ "%s %s speed=%d KB/s\n", -+ ixt_e->ixt_name, -+ encrypt? "encrypt": "decrypt", speed); -+ } -+ } -+out: -+ if (tmp_key_e && ixt_e->ixt_e_destroy_key) ixt_e->ixt_e_destroy_key(ixt_e, tmp_key_e); -+ if (buf) kfree(buf); -+ if (ixt_e) ipsec_alg_put((struct ipsec_alg *)ixt_e); -+ return ret; -+ #undef test_enc -+ #undef test_dec -+ #undef test_tmp -+ #undef test_key_e -+ #undef test_iv -+ #undef test_key -+ #undef test_size -+} -+ -+/* -+ * Must be called from user context -+ * used at module load type for testing algo implementation -+ */ -+static int ipsec_alg_test_auth(int auth_alg, int test) { -+ int ret; -+ caddr_t buf = NULL; -+ int blocksize, keysize, key_a_size; -+ struct ipsec_alg_auth *ixt_a; -+ #define BUFSZ 1024 -+ #define MARGIN 0 -+ #define test_auth (buf+MARGIN) -+ #define test_key_a (test_auth+BUFSZ+MARGIN) -+ #define test_key (test_key_a+key_a_size+MARGIN) -+ #define test_hash (test_key+keysize+MARGIN) -+ #define test_size (BUFSZ+key_a_size+keysize+AHHMAC_HASHLEN+MARGIN*4) -+ ixt_a=(struct ipsec_alg_auth *)ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, auth_alg); -+ if (ixt_a==NULL) { -+ KLIPS_PRINT(1, -+ "klips_debug: ipsec_alg_test_auth: " -+ "encalg=%d object not found\n", -+ auth_alg); -+ ret=-EINVAL; -+ goto out; -+ } -+ blocksize=ixt_a->ixt_blocksize; -+ key_a_size=ixt_a->ixt_a_ctx_size; -+ keysize=ixt_a->ixt_a_keylen; -+ KLIPS_PRINT(1, -+ "klips_debug: ipsec_alg_test_auth: " -+ "auth_alg=%d blocksize=%d key_a_size=%d keysize=%d\n", -+ auth_alg, blocksize, key_a_size, keysize); -+ if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) { -+ ret= -ENOMEM; -+ goto out; -+ } -+ get_random_bytes(test_key, keysize); -+ ret = ixt_a->ixt_a_hmac_set_key(ixt_a, test_key_a, test_key, keysize); -+ if (ret < 0 ) -+ goto out; -+ get_random_bytes(test_auth, BUFSZ); -+ ret=ixt_a->ixt_a_hmac_hash(ixt_a, test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN); -+ printk(KERN_INFO -+ "klips_info: ipsec_alg_test_auth: " -+ "ret=%d\n", ret); -+ { -+ /* Shamelessly taken from drivers/md sources O:) */ -+ unsigned long now; -+ int i, count, max=0; -+ int speed; -+ for (i = 0; i < 5; i++) { -+ now = jiffies; -+ count = 0; -+ while (jiffies == now) { -+ mb(); -+ ixt_a->ixt_a_hmac_hash(ixt_a, test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN); -+ mb(); -+ count++; -+ mb(); -+ } -+ if (count > max) -+ max = count; -+ } -+ speed = max * (HZ * BUFSZ / 1024); -+ printk(KERN_INFO -+ "klips_info: ipsec_alg_test_auth: " -+ "%s hash speed=%d KB/s\n", -+ ixt_a->ixt_name, -+ speed); -+ } -+out: -+ if (buf) kfree(buf); -+ if (ixt_a) ipsec_alg_put((struct ipsec_alg *)ixt_a); -+ return ret; -+ #undef test_auth -+ #undef test_key_a -+ #undef test_key -+ #undef test_hash -+ #undef test_size -+} -+ -+int ipsec_alg_test(unsigned alg_type, unsigned alg_id, int test) { -+ switch(alg_type) { -+ case IPSEC_ALG_TYPE_ENCRYPT: -+ return ipsec_alg_test_encrypt(alg_id, test); -+ break; -+ case IPSEC_ALG_TYPE_AUTH: -+ return ipsec_alg_test_auth(alg_id, test); -+ break; -+ } -+ printk(KERN_ERR "klips_info: ipsec_alg_test() called incorrectly: " -+ "alg_type=%d alg_id=%d\n", -+ alg_type, alg_id); -+ return -EINVAL; -+} -+ -+int ipsec_alg_init(void) { -+ KLIPS_PRINT(1, "klips_info:ipsec_alg_init: " -+ "KLIPS alg v=%d.%d.%d-%d (EALG_MAX=%d, AALG_MAX=%d)\n", -+ IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION), -+ SADB_EALG_MAX, SADB_AALG_MAX); -+ /* Initialize tables */ -+ write_lock_bh(&ipsec_alg_lock); -+ ipsec_alg_hash_init(); -+ write_unlock_bh(&ipsec_alg_lock); -+ -+ /* Initialize static algos */ -+ KLIPS_PRINT(1, "klips_info:ipsec_alg_init: " -+ "calling ipsec_alg_static_init()\n"); -+ -+ /* If we are suppose to use our AES, and don't have CryptoAPI enabled... */ -+#if defined(CONFIG_IPSEC_ENC_AES) && CONFIG_IPSEC_ENC_AES && !defined(CONFIG_IPSEC_ENC_AES_MODULE) && !CONFIG_IPSEC_ENC_CRYPTOAPI && !defined(CONFIG_IPSEC_ENC_CRYPTOAPI_MODULE) -+ { -+ extern int ipsec_aes_init(void); -+ ipsec_aes_init(); -+ } -+#endif -+ -+ /* If we are doing CryptoAPI, then init */ -+#if defined(CONFIG_IPSEC_ENC_CRYPTOAPI) && CONFIG_IPSEC_ENC_CRYPTOAPI && !defined(CONFIG_IPSEC_ENC_CRYPTOAPI_MODULE) -+ { -+ extern int ipsec_cryptoapi_init(void); -+ ipsec_cryptoapi_init(); -+ } -+#endif -+ -+ -+ return 0; -+} -+ -+/********************************************** -+ * -+ * INTERFACE for ipsec_sa init and wipe -+ * -+ **********************************************/ -+ -+/* -+ * Called from pluto -> pfkey_v2_parser.c:pfkey_ipsec_sa_init() -+ */ -+int ipsec_alg_sa_init(struct ipsec_sa *sa_p) { -+ struct ipsec_alg_enc *ixt_e; -+ struct ipsec_alg_auth *ixt_a; -+ -+ /* Only ESP for now ... */ -+ if (sa_p->ips_said.proto != IPPROTO_ESP) -+ return -EPROTONOSUPPORT; -+ KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_init() :" -+ "entering for encalg=%d, authalg=%d\n", -+ sa_p->ips_encalg, sa_p->ips_authalg); -+ if ((ixt_e=(struct ipsec_alg_enc *) -+ ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, sa_p->ips_encalg))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug: ipsec_alg_sa_init() :" -+ "found ipsec_alg (ixt_e=%p) for encalg=%d\n", -+ ixt_e, sa_p->ips_encalg); -+ sa_p->ips_alg_enc=ixt_e; -+ } -+ if ((ixt_a=(struct ipsec_alg_auth *) -+ ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, sa_p->ips_authalg))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug: ipsec_alg_sa_init() :" -+ "found ipsec_alg (ixt_a=%p) for auth=%d\n", -+ ixt_a, sa_p->ips_authalg); -+ sa_p->ips_alg_auth=ixt_a; -+ } -+ return 0; -+} -+ -+/* -+ * Called from pluto -> ipsec_sa.c:ipsec_sa_delchain() -+ */ -+int ipsec_alg_sa_wipe(struct ipsec_sa *sa_p) { -+ struct ipsec_alg *ixt; -+ if ((ixt=(struct ipsec_alg *)sa_p->ips_alg_enc)) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_wipe() :" -+ "unlinking for encalg=%d\n", -+ ixt->ixt_alg_id); -+ ipsec_alg_put(ixt); -+ } -+ if ((ixt=(struct ipsec_alg *)sa_p->ips_alg_auth)) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_wipe() :" -+ "unlinking for authalg=%d\n", -+ ixt->ixt_alg_id); -+ ipsec_alg_put(ixt); -+ } -+ return 0; -+} -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_xform_get_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length IPSEC_PROC_LAST_ARG) -+{ -+ int len = 0; -+ off_t begin = 0; -+ int i; -+ struct list_head *head; -+ struct ipsec_alg *ixt; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_tncfg_get_info: " -+ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", -+ buffer, -+ *start, -+ (int)offset, -+ length); -+ -+ for(i = 0, head = ipsec_alg_hash_table; i< IPSEC_ALG_HASHSZ; i++, head++) -+ { -+ struct list_head *p; -+ for (p=head->next; p!=head; p=p->next) -+ { -+ ixt = list_entry(p, struct ipsec_alg, ixt_list); -+ len += ipsec_snprintf(buffer+len, length-len, -+ "VERSION=%d TYPE=%d ID=%d NAME=%s REFCNT=%d ", -+ ixt->ixt_version, ixt->ixt_alg_type, ixt->ixt_alg_id, -+ ixt->ixt_name, ixt->ixt_refcnt); -+ -+ len += ipsec_snprintf(buffer+len, length-len, -+ "STATE=%08x BLOCKSIZE=%d IVLEN=%d KEYMINBITS=%d KEYMAXBITS=%d ", -+ ixt->ixt_state, ixt->ixt_blocksize, -+ ixt->ixt_ivlen, ixt->ixt_keyminbits, ixt->ixt_keymaxbits); -+ -+ len += ipsec_snprintf(buffer+len, length-len, -+ "IVLEN=%d KEYMINBITS=%d KEYMAXBITS=%d ", -+ ixt->ixt_ivlen, ixt->ixt_keyminbits, ixt->ixt_keymaxbits); -+ -+ switch(ixt->ixt_alg_type) -+ { -+ case IPSEC_ALG_TYPE_AUTH: -+ { -+ struct ipsec_alg_auth *auth = (struct ipsec_alg_auth *)ixt; -+ -+ len += ipsec_snprintf(buffer+len, length-len, -+ "KEYLEN=%d CTXSIZE=%d AUTHLEN=%d ", -+ auth->ixt_a_keylen, auth->ixt_a_ctx_size, -+ auth->ixt_a_authlen); -+ break; -+ } -+ case IPSEC_ALG_TYPE_ENCRYPT: -+ { -+ struct ipsec_alg_enc *enc = (struct ipsec_alg_enc *)ixt; -+ len += ipsec_snprintf(buffer+len, length-len, -+ "KEYLEN=%d CTXSIZE=%d ", -+ enc->ixt_e_keylen, enc->ixt_e_ctx_size); -+ -+ break; -+ } -+ } -+ -+ len += ipsec_snprintf(buffer+len, length-len, "\n"); -+ } -+ } -+ -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ len -= (offset - begin); /* Start slop */ -+ if (len > length) -+ len = length; -+ return len; -+} -+ -+ -+/* -+ * As the author of this module, I ONLY ALLOW using it from -+ * GPL (or same LICENSE TERMS as kernel source) modules. -+ * -+ * In respect to hardware crypto engines this means: -+ * * Closed-source device drivers ARE NOT ALLOWED to use -+ * this interface. -+ * * Closed-source VHDL/Verilog firmware running on -+ * the crypto hardware device IS ALLOWED to use this interface -+ * via a GPL (or same LICENSE TERMS as kernel source) device driver. -+ * --Juan Jose Ciarlante 20/03/2002 (thanks RGB for the correct wording) -+ */ -+ -+/* -+ * These symbols can only be used from GPL modules -+ * for now, I'm disabling this because it creates false -+ * symbol problems for old modutils. -+ */ -+ -+/* #ifndef EXPORT_SYMBOL_GPL */ -+#undef EXPORT_SYMBOL_GPL -+#define EXPORT_SYMBOL_GPL EXPORT_SYMBOL -+/* #endif */ -+EXPORT_SYMBOL_GPL(register_ipsec_alg); -+EXPORT_SYMBOL_GPL(unregister_ipsec_alg); -+EXPORT_SYMBOL_GPL(ipsec_alg_test); -+#endif /* CONFIG_IPSEC_ALG */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_alg_aes.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,263 @@ -+/* -+ * ipsec_alg AES cipher stubs -+ * -+ * Author: JuanJo Ciarlante -+ * -+ * ipsec_alg_aes.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * Fixes by: -+ * PK: Pawel Krawczyk -+ * Fixes list: -+ * PK: make XCBC comply with latest draft (keylength) -+ * -+ */ -+#include -+#include -+ -+/* -+ * special case: ipsec core modular with this static algo inside: -+ * must avoid MODULE magic for this file -+ */ -+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_AES -+#undef MODULE -+#endif -+ -+#include -+#include -+ -+#include /* printk() */ -+#include /* error codes */ -+#include /* size_t */ -+#include -+ -+/* Check if __exit is defined, if not null it */ -+#ifndef __exit -+#define __exit -+#endif -+ -+/* Low freeswan header coupling */ -+#include "openswan/ipsec_alg.h" -+#include "crypto/aes_cbc.h" -+ -+#define CONFIG_IPSEC_ALG_AES_MAC 1 -+ -+#define AES_CONTEXT_T aes_context -+MODULE_AUTHOR("JuanJo Ciarlante "); -+static int debug=0; -+MODULE_PARM(debug, "i"); -+static int test=0; -+MODULE_PARM(test, "i"); -+static int excl=0; -+MODULE_PARM(excl, "i"); -+static int keyminbits=0; -+MODULE_PARM(keyminbits, "i"); -+static int keymaxbits=0; -+MODULE_PARM(keymaxbits, "i"); -+ -+#if CONFIG_IPSEC_ALG_AES_MAC -+#include "crypto/aes_xcbc_mac.h" -+ -+/* -+ * Not IANA number yet (draft-ietf-ipsec-ciph-aes-xcbc-mac-00.txt). -+ * We use 9 for non-modular algorithm and none for modular, thus -+ * forcing user to specify one on module load. -kravietz -+ */ -+#ifdef MODULE -+static int auth_id=0; -+#else -+static int auth_id=9; -+#endif -+MODULE_PARM(auth_id, "i"); -+#endif -+ -+#define ESP_AES 12 /* truely _constant_ :) */ -+ -+/* 128, 192 or 256 */ -+#define ESP_AES_KEY_SZ_MIN 16 /* 128 bit secret key */ -+#define ESP_AES_KEY_SZ_MAX 32 /* 256 bit secret key */ -+#define ESP_AES_CBC_BLK_LEN 16 /* AES-CBC block size */ -+ -+/* Values according to draft-ietf-ipsec-ciph-aes-xcbc-mac-02.txt -+ * -kravietz -+ */ -+#define ESP_AES_MAC_KEY_SZ 16 /* 128 bit MAC key */ -+#define ESP_AES_MAC_BLK_LEN 16 /* 128 bit block */ -+ -+static int _aes_set_key(struct ipsec_alg_enc *alg, __u8 * key_e, const __u8 * key, size_t keysize) { -+ int ret; -+ AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e; -+ ret=AES_set_key(ctx, key, keysize)!=0? 0: -EINVAL; -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_aes_set_key:" -+ "ret=%d key_e=%p key=%p keysize=%d\n", -+ ret, key_e, key, keysize); -+ return ret; -+} -+static int _aes_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) { -+ AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e; -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_aes_cbc_encrypt:" -+ "key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n", -+ key_e, in, ilen, iv, encrypt); -+ return AES_cbc_encrypt(ctx, in, in, ilen, iv, encrypt); -+} -+#if CONFIG_IPSEC_ALG_AES_MAC -+static int _aes_mac_set_key(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * key, int keylen) { -+ aes_context_mac *ctxm=(aes_context_mac *)key_a; -+ return AES_xcbc_mac_set_key(ctxm, key, keylen)? 0 : -EINVAL; -+} -+static int _aes_mac_hash(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * dat, int len, __u8 * hash, int hashlen) { -+ int ret; -+ char hash_buf[16]; -+ aes_context_mac *ctxm=(aes_context_mac *)key_a; -+ ret=AES_xcbc_mac_hash(ctxm, dat, len, hash_buf); -+ memcpy(hash, hash_buf, hashlen); -+ return ret; -+} -+static struct ipsec_alg_auth ipsec_alg_AES_MAC = { -+ ixt_version: IPSEC_ALG_VERSION, -+ ixt_module: THIS_MODULE, -+ ixt_refcnt: ATOMIC_INIT(0), -+ ixt_alg_type: IPSEC_ALG_TYPE_AUTH, -+ ixt_alg_id: 0, -+ ixt_name: "aes_mac", -+ ixt_blocksize: ESP_AES_MAC_BLK_LEN, -+ ixt_keyminbits: ESP_AES_MAC_KEY_SZ*8, -+ ixt_keymaxbits: ESP_AES_MAC_KEY_SZ*8, -+ ixt_a_keylen: ESP_AES_MAC_KEY_SZ, -+ ixt_a_ctx_size: sizeof(aes_context_mac), -+ ixt_a_hmac_set_key: _aes_mac_set_key, -+ ixt_a_hmac_hash:_aes_mac_hash, -+}; -+#endif /* CONFIG_IPSEC_ALG_AES_MAC */ -+static struct ipsec_alg_enc ipsec_alg_AES = { -+ ixt_version: IPSEC_ALG_VERSION, -+ ixt_module: THIS_MODULE, -+ ixt_refcnt: ATOMIC_INIT(0), -+ ixt_alg_type: IPSEC_ALG_TYPE_ENCRYPT, -+ ixt_alg_id: ESP_AES, -+ ixt_name: "aes", -+ ixt_blocksize: ESP_AES_CBC_BLK_LEN, -+ ixt_keyminbits: ESP_AES_KEY_SZ_MIN*8, -+ ixt_keymaxbits: ESP_AES_KEY_SZ_MAX*8, -+ ixt_e_keylen: ESP_AES_KEY_SZ_MAX, -+ ixt_e_ctx_size: sizeof(AES_CONTEXT_T), -+ ixt_e_set_key: _aes_set_key, -+ ixt_e_cbc_encrypt:_aes_cbc_encrypt, -+}; -+ -+#if defined(CONFIG_IPSEC_ENC_AES_MODULE) -+IPSEC_ALG_MODULE_INIT_MOD( ipsec_aes_init ) -+#else -+IPSEC_ALG_MODULE_INIT_STATIC( ipsec_aes_init ) -+#endif -+{ -+ int ret, test_ret; -+ -+ if (keyminbits) -+ ipsec_alg_AES.ixt_keyminbits=keyminbits; -+ if (keymaxbits) { -+ ipsec_alg_AES.ixt_keymaxbits=keymaxbits; -+ if (keymaxbits*8>ipsec_alg_AES.ixt_keymaxbits) -+ ipsec_alg_AES.ixt_e_keylen=keymaxbits*8; -+ } -+ if (excl) ipsec_alg_AES.ixt_state |= IPSEC_ALG_ST_EXCL; -+ ret=register_ipsec_alg_enc(&ipsec_alg_AES); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", -+ ipsec_alg_AES.ixt_alg_type, -+ ipsec_alg_AES.ixt_alg_id, -+ ipsec_alg_AES.ixt_name, -+ ret); -+ if (ret==0 && test) { -+ test_ret=ipsec_alg_test( -+ ipsec_alg_AES.ixt_alg_type, -+ ipsec_alg_AES.ixt_alg_id, -+ test); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", -+ ipsec_alg_AES.ixt_alg_type, -+ ipsec_alg_AES.ixt_alg_id, -+ test_ret); -+ } -+#if CONFIG_IPSEC_ALG_AES_MAC -+ if (auth_id!=0){ -+ int ret; -+ ipsec_alg_AES_MAC.ixt_alg_id=auth_id; -+ ret=register_ipsec_alg_auth(&ipsec_alg_AES_MAC); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", -+ ipsec_alg_AES_MAC.ixt_alg_type, -+ ipsec_alg_AES_MAC.ixt_alg_id, -+ ipsec_alg_AES_MAC.ixt_name, -+ ret); -+ if (ret==0 && test) { -+ test_ret=ipsec_alg_test( -+ ipsec_alg_AES_MAC.ixt_alg_type, -+ ipsec_alg_AES_MAC.ixt_alg_id, -+ test); -+ printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", -+ ipsec_alg_AES_MAC.ixt_alg_type, -+ ipsec_alg_AES_MAC.ixt_alg_id, -+ test_ret); -+ } -+ } else { -+ printk(KERN_DEBUG "klips_debug: experimental ipsec_alg_AES_MAC not registered [Ok] (auth_id=%d)\n", auth_id); -+ } -+#endif /* CONFIG_IPSEC_ALG_AES_MAC */ -+ return ret; -+} -+ -+#if defined(CONFIG_IPSEC_ENC_AES_MODULE) -+IPSEC_ALG_MODULE_EXIT_MOD( ipsec_aes_fini ) -+#else -+IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_aes_fini ) -+#endif -+{ -+#if CONFIG_IPSEC_ALG_AES_MAC -+ if (auth_id) unregister_ipsec_alg_auth(&ipsec_alg_AES_MAC); -+#endif /* CONFIG_IPSEC_ALG_AES_MAC */ -+ unregister_ipsec_alg_enc(&ipsec_alg_AES); -+ return; -+} -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+#if 0+NOT_YET -+#ifndef MODULE -+/* -+ * This is intended for static module setups, currently -+ * doesn't work for modular ipsec.o with static algos inside -+ */ -+static int setup_keybits(const char *str) -+{ -+ unsigned aux; -+ char *end; -+ -+ aux = simple_strtoul(str,&end,0); -+ if (aux != 128 && aux != 192 && aux != 256) -+ return 0; -+ keyminbits = aux; -+ -+ if (*end == 0 || *end != ',') -+ return 1; -+ str=end+1; -+ aux = simple_strtoul(str, NULL, 0); -+ if (aux != 128 && aux != 192 && aux != 256) -+ return 0; -+ if (aux >= keyminbits) -+ keymaxbits = aux; -+ return 1; -+} -+__setup("ipsec_aes_keybits=", setup_keybits); -+#endif -+#endif -+EXPORT_NO_SYMBOLS; ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_alg_cryptoapi.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,421 @@ -+/* -+ * ipsec_alg to linux cryptoapi GLUE -+ * -+ * Authors: CODE.ar TEAM -+ * Harpo MAxx -+ * JuanJo Ciarlante -+ * Luciano Ruete -+ * -+ * ipsec_alg_cryptoapi.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * Example usage: -+ * modinfo -p ipsec_cryptoapi (quite useful info, including supported algos) -+ * modprobe ipsec_cryptoapi -+ * modprobe ipsec_cryptoapi test=1 -+ * modprobe ipsec_cryptoapi excl=1 (exclusive cipher/algo) -+ * modprobe ipsec_cryptoapi noauto=1 aes=1 twofish=1 (only these ciphers) -+ * modprobe ipsec_cryptoapi aes=128,128 (force these keylens) -+ * modprobe ipsec_cryptoapi des_ede3=0 (everything but 3DES) -+ */ -+#include -+#include -+ -+/* -+ * special case: ipsec core modular with this static algo inside: -+ * must avoid MODULE magic for this file -+ */ -+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_CRYPTOAPI -+#undef MODULE -+#endif -+ -+#include -+#include -+ -+#include /* printk() */ -+#include /* error codes */ -+#include /* size_t */ -+#include -+ -+/* Check if __exit is defined, if not null it */ -+#ifndef __exit -+#define __exit -+#endif -+ -+/* warn the innocent */ -+#if !defined (CONFIG_CRYPTO) && !defined (CONFIG_CRYPTO_MODULE) -+#warning "No linux CryptoAPI found, install 2.4.22+ or 2.6.x" -+#define NO_CRYPTOAPI_SUPPORT -+#endif -+/* Low Openswan header coupling */ -+#include "openswan/ipsec_alg.h" -+ -+#include -+#ifdef CRYPTO_API_VERSION_CODE -+#warning "Old CryptoAPI is not supported. Only linux-2.4.22+ or linux-2.6.x are supported" -+#define NO_CRYPTOAPI_SUPPORT -+#endif -+ -+#ifdef NO_CRYPTOAPI_SUPPORT -+#warning "Building an unusable module :P" -+/* Catch old CryptoAPI by not allowing module to load */ -+IPSEC_ALG_MODULE_INIT_STATIC( ipsec_cryptoapi_init ) -+{ -+ printk(KERN_WARNING "ipsec_cryptoapi.o was not built on stock Linux CryptoAPI (2.4.22+ or 2.6.x), not loading.\n"); -+ return -EINVAL; -+} -+#else -+#include -+#include -+#include -+ -+#define CIPHERNAME_AES "aes" -+#define CIPHERNAME_3DES "des3_ede" -+#define CIPHERNAME_BLOWFISH "blowfish" -+#define CIPHERNAME_CAST "cast5" -+#define CIPHERNAME_SERPENT "serpent" -+#define CIPHERNAME_TWOFISH "twofish" -+ -+#define ESP_3DES 3 -+#define ESP_AES 12 -+#define ESP_BLOWFISH 7 /* truely _constant_ :) */ -+#define ESP_CAST 6 /* quite constant :) */ -+#define ESP_SERPENT 252 /* from ipsec drafts */ -+#define ESP_TWOFISH 253 /* from ipsec drafts */ -+ -+#define AH_MD5 2 -+#define AH_SHA 3 -+#define DIGESTNAME_MD5 "md5" -+#define DIGESTNAME_SHA1 "sha1" -+ -+MODULE_AUTHOR("Juanjo Ciarlante, Harpo MAxx, Luciano Ruete"); -+static int debug=0; -+MODULE_PARM(debug, "i"); -+static int test=0; -+MODULE_PARM(test, "i"); -+static int excl=0; -+MODULE_PARM(excl, "i"); -+ -+static int noauto = 0; -+MODULE_PARM(noauto,"i"); -+MODULE_PARM_DESC(noauto, "Dont try all known algos, just setup enabled ones"); -+ -+static int des_ede3[] = {-1, -1}; -+static int aes[] = {-1, -1}; -+static int blowfish[] = {-1, -1}; -+static int cast[] = {-1, -1}; -+static int serpent[] = {-1, -1}; -+static int twofish[] = {-1, -1}; -+ -+MODULE_PARM(des_ede3,"1-2i"); -+MODULE_PARM(aes,"1-2i"); -+MODULE_PARM(blowfish,"1-2i"); -+MODULE_PARM(cast,"1-2i"); -+MODULE_PARM(serpent,"1-2i"); -+MODULE_PARM(twofish,"1-2i"); -+MODULE_PARM_DESC(des_ede3, "0: disable | 1: force_enable | min,max: dontuse"); -+MODULE_PARM_DESC(aes, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(blowfish, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(cast, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(serpent, "0: disable | 1: force_enable | min,max: keybitlens"); -+MODULE_PARM_DESC(twofish, "0: disable | 1: force_enable | min,max: keybitlens"); -+ -+struct ipsec_alg_capi_cipher { -+ const char *ciphername; /* cryptoapi's ciphername */ -+ unsigned blocksize; -+ unsigned short minbits; -+ unsigned short maxbits; -+ int *parm; /* lkm param for this cipher */ -+ struct ipsec_alg_enc alg; /* note it's not a pointer */ -+}; -+static struct ipsec_alg_capi_cipher alg_capi_carray[] = { -+ { CIPHERNAME_AES , 16, 128, 256, aes , { ixt_alg_id: ESP_AES, }}, -+ { CIPHERNAME_TWOFISH , 16, 128, 256, twofish, { ixt_alg_id: ESP_TWOFISH, }}, -+ { CIPHERNAME_SERPENT , 16, 128, 256, serpent, { ixt_alg_id: ESP_SERPENT, }}, -+ { CIPHERNAME_CAST , 8, 128, 128, cast , { ixt_alg_id: ESP_CAST, }}, -+ { CIPHERNAME_BLOWFISH , 8, 96, 448, blowfish,{ ixt_alg_id: ESP_BLOWFISH, }}, -+ { CIPHERNAME_3DES , 8, 192, 192, des_ede3,{ ixt_alg_id: ESP_3DES, }}, -+ { NULL, 0, 0, 0, NULL, {} } -+}; -+#ifdef NOT_YET -+struct ipsec_alg_capi_digest { -+ const char *digestname; /* cryptoapi's digestname */ -+ struct digest_implementation *di; -+ struct ipsec_alg_auth alg; /* note it's not a pointer */ -+}; -+static struct ipsec_alg_capi_cipher alg_capi_darray[] = { -+ { DIGESTNAME_MD5, NULL, { ixt_alg_id: AH_MD5, }}, -+ { DIGESTNAME_SHA1, NULL, { ixt_alg_id: AH_SHA, }}, -+ { NULL, NULL, {} } -+}; -+#endif -+/* -+ * "generic" linux cryptoapi setup_cipher() function -+ */ -+int setup_cipher(const char *ciphername) -+{ -+ return crypto_alg_available(ciphername, 0); -+} -+ -+/* -+ * setups ipsec_alg_capi_cipher "hyper" struct components, calling -+ * register_ipsec_alg for cointaned ipsec_alg object -+ */ -+static void _capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e); -+static __u8 * _capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen); -+static int _capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt); -+ -+static int -+setup_ipsec_alg_capi_cipher(struct ipsec_alg_capi_cipher *cptr) -+{ -+ int ret; -+ cptr->alg.ixt_version = IPSEC_ALG_VERSION; -+ cptr->alg.ixt_module = THIS_MODULE; -+ atomic_set (& cptr->alg.ixt_refcnt, 0); -+ strncpy (cptr->alg.ixt_name , cptr->ciphername, sizeof (cptr->alg.ixt_name)); -+ -+ cptr->alg.ixt_blocksize=cptr->blocksize; -+ cptr->alg.ixt_keyminbits=cptr->minbits; -+ cptr->alg.ixt_keymaxbits=cptr->maxbits; -+ cptr->alg.ixt_state = 0; -+ if (excl) cptr->alg.ixt_state |= IPSEC_ALG_ST_EXCL; -+ cptr->alg.ixt_e_keylen=cptr->alg.ixt_keymaxbits/8; -+ cptr->alg.ixt_e_ctx_size = 0; -+ cptr->alg.ixt_alg_type = IPSEC_ALG_TYPE_ENCRYPT; -+ cptr->alg.ixt_e_new_key = _capi_new_key; -+ cptr->alg.ixt_e_destroy_key = _capi_destroy_key; -+ cptr->alg.ixt_e_cbc_encrypt = _capi_cbc_encrypt; -+ cptr->alg.ixt_data = cptr; -+ -+ ret=register_ipsec_alg_enc(&cptr->alg); -+ printk("setup_ipsec_alg_capi_cipher(): " -+ "alg_type=%d alg_id=%d name=%s " -+ "keyminbits=%d keymaxbits=%d, ret=%d\n", -+ cptr->alg.ixt_alg_type, -+ cptr->alg.ixt_alg_id, -+ cptr->alg.ixt_name, -+ cptr->alg.ixt_keyminbits, -+ cptr->alg.ixt_keymaxbits, -+ ret); -+ return ret; -+} -+/* -+ * called in ipsec_sa_wipe() time, will destroy key contexts -+ * and do 1 unbind() -+ */ -+static void -+_capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e) -+{ -+ struct crypto_tfm *tfm=(struct crypto_tfm*)key_e; -+ -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug: _capi_destroy_key:" -+ "name=%s key_e=%p \n", -+ alg->ixt_name, key_e); -+ if (!key_e) { -+ printk(KERN_ERR "klips_debug: _capi_destroy_key:" -+ "name=%s NULL key_e!\n", -+ alg->ixt_name); -+ return; -+ } -+ crypto_free_tfm(tfm); -+} -+ -+/* -+ * create new key context, need alg->ixt_data to know which -+ * (of many) cipher inside this module is the target -+ */ -+static __u8 * -+_capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen) -+{ -+ struct ipsec_alg_capi_cipher *cptr; -+ struct crypto_tfm *tfm=NULL; -+ -+ cptr = alg->ixt_data; -+ if (!cptr) { -+ printk(KERN_ERR "_capi_new_key(): " -+ "NULL ixt_data (?!) for \"%s\" algo\n" -+ , alg->ixt_name); -+ goto err; -+ } -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_capi_new_key:" -+ "name=%s cptr=%p key=%p keysize=%d\n", -+ alg->ixt_name, cptr, key, keylen); -+ -+ /* -+ * alloc tfm -+ */ -+ tfm = crypto_alloc_tfm(cptr->ciphername, CRYPTO_TFM_MODE_CBC); -+ if (!tfm) { -+ printk(KERN_ERR "_capi_new_key(): " -+ "NULL tfm for \"%s\" cryptoapi (\"%s\") algo\n" -+ , alg->ixt_name, cptr->ciphername); -+ goto err; -+ } -+ if (crypto_cipher_setkey(tfm, key, keylen) < 0) { -+ printk(KERN_ERR "_capi_new_key(): " -+ "failed new_key() for \"%s\" cryptoapi algo (keylen=%d)\n" -+ , alg->ixt_name, keylen); -+ crypto_free_tfm(tfm); -+ tfm=NULL; -+ } -+err: -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:_capi_new_key:" -+ "name=%s key=%p keylen=%d tfm=%p\n", -+ alg->ixt_name, key, keylen, tfm); -+ return (__u8 *) tfm; -+} -+/* -+ * core encryption function: will use cx->ci to call actual cipher's -+ * cbc function -+ */ -+static int -+_capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) { -+ int error =0; -+ struct crypto_tfm *tfm=(struct crypto_tfm *)key_e; -+ struct scatterlist sg = { -+ .page = virt_to_page(in), -+ .offset = (unsigned long)(in) % PAGE_SIZE, -+ .length=ilen, -+ }; -+ if (debug > 1) -+ printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" -+ "key_e=%p " -+ "in=%p out=%p ilen=%d iv=%p encrypt=%d\n" -+ , key_e -+ , in, in, ilen, iv, encrypt); -+ crypto_cipher_set_iv(tfm, iv, crypto_tfm_alg_ivsize(tfm)); -+ if (encrypt) -+ error = crypto_cipher_encrypt (tfm, &sg, &sg, ilen); -+ else -+ error = crypto_cipher_decrypt (tfm, &sg, &sg, ilen); -+ if (debug > 1) -+ printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" -+ "error=%d\n" -+ , error); -+ return (error<0)? error : ilen; -+} -+/* -+ * main initialization loop: for each cipher in list, do -+ * 1) setup cryptoapi cipher else continue -+ * 2) register ipsec_alg object -+ */ -+static int -+setup_cipher_list (struct ipsec_alg_capi_cipher* clist) -+{ -+ struct ipsec_alg_capi_cipher *cptr; -+ /* foreach cipher in list ... */ -+ for (cptr=clist;cptr->ciphername;cptr++) { -+ /* -+ * see if cipher has been disabled (0) or -+ * if noauto set and not enabled (1) -+ */ -+ if (cptr->parm[0] == 0 || (noauto && cptr->parm[0] < 0)) { -+ if (debug>0) -+ printk(KERN_INFO "setup_cipher_list(): " -+ "ciphername=%s skipped at user request: " -+ "noauto=%d parm[0]=%d parm[1]=%d\n" -+ , cptr->ciphername -+ , noauto -+ , cptr->parm[0] -+ , cptr->parm[1]); -+ continue; -+ } -+ /* -+ * use a local ci to avoid touching cptr->ci, -+ * if register ipsec_alg success then bind cipher -+ */ -+ if( setup_cipher(cptr->ciphername) ) { -+ if (debug > 0) -+ printk(KERN_DEBUG "klips_debug:" -+ "setup_cipher_list():" -+ "ciphername=%s found\n" -+ , cptr->ciphername); -+ if (setup_ipsec_alg_capi_cipher(cptr) == 0) { -+ -+ -+ } else { -+ printk(KERN_ERR "klips_debug:" -+ "setup_cipher_list():" -+ "ciphername=%s failed ipsec_alg_register\n" -+ , cptr->ciphername); -+ } -+ } else { -+ if (debug>0) -+ printk(KERN_INFO "setup_cipher_list(): lookup for ciphername=%s: not found \n", -+ cptr->ciphername); -+ } -+ } -+ return 0; -+} -+/* -+ * deregister ipsec_alg objects and unbind ciphers -+ */ -+static int -+unsetup_cipher_list (struct ipsec_alg_capi_cipher* clist) -+{ -+ struct ipsec_alg_capi_cipher *cptr; -+ /* foreach cipher in list ... */ -+ for (cptr=clist;cptr->ciphername;cptr++) { -+ if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) { -+ unregister_ipsec_alg_enc(&cptr->alg); -+ } -+ } -+ return 0; -+} -+/* -+ * test loop for registered algos -+ */ -+static int -+test_cipher_list (struct ipsec_alg_capi_cipher* clist) -+{ -+ int test_ret; -+ struct ipsec_alg_capi_cipher *cptr; -+ /* foreach cipher in list ... */ -+ for (cptr=clist;cptr->ciphername;cptr++) { -+ if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) { -+ test_ret=ipsec_alg_test( -+ cptr->alg.ixt_alg_type, -+ cptr->alg.ixt_alg_id, -+ test); -+ printk("test_cipher_list(alg_type=%d alg_id=%d): test_ret=%d\n", -+ cptr->alg.ixt_alg_type, -+ cptr->alg.ixt_alg_id, -+ test_ret); -+ } -+ } -+ return 0; -+} -+ -+IPSEC_ALG_MODULE_INIT_STATIC( ipsec_cryptoapi_init ) -+{ -+ int ret, test_ret; -+ if ((ret=setup_cipher_list(alg_capi_carray)) < 0) -+ return -EPROTONOSUPPORT; -+ if (ret==0 && test) { -+ test_ret=test_cipher_list(alg_capi_carray); -+ } -+ return ret; -+} -+IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_cryptoapi_fini ) -+{ -+ unsetup_cipher_list(alg_capi_carray); -+ return; -+} -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+EXPORT_NO_SYMBOLS; -+#endif /* NO_CRYPTOAPI_SUPPORT */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_esp.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,558 @@ -+/* -+ * processing code for ESP -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_esp_c_version[] = "RCSID $Id$"; -+#include -+#include -+ -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define proto_priv cb -+#endif /* NET21 */ -+#include -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipsec_xmit.h" -+ -+#include "openswan/ipsec_auth.h" -+ -+#ifdef CONFIG_IPSEC_ESP -+#include "openswan/ipsec_esp.h" -+#endif /* CONFIG_IPSEC_ESP */ -+ -+#include "openswan/ipsec_proto.h" -+#include "openswan/ipsec_alg.h" -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_esp = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ -+#ifdef CONFIG_IPSEC_ESP -+enum ipsec_rcv_value -+ipsec_rcv_esp_checks(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb) -+{ -+ __u8 proto; -+ int len; /* packet length */ -+ -+ len = skb->len; -+ proto = irs->ipp->protocol; -+ -+ /* XXX this will need to be 8 for IPv6 */ -+ if ((proto == IPPROTO_ESP) && ((len - irs->iphlen) % 4)) { -+ printk("klips_error:ipsec_rcv: " -+ "got packet with content length = %d from %s -- should be on 4 octet boundary, packet dropped\n", -+ len - irs->iphlen, -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_BADLEN; -+ } -+ -+ if(skb->len < (irs->hard_header_len + sizeof(struct iphdr) + sizeof(struct esphdr))) { -+ KLIPS_PRINT(debug_rcv & DB_RX_INAU, -+ "klips_debug:ipsec_rcv: " -+ "runt esp packet of skb->len=%d received from %s, dropped.\n", -+ skb->len, -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_BADLEN; -+ } -+ -+ irs->protostuff.espstuff.espp = (struct esphdr *)(skb->data + irs->iphlen); -+ irs->said.spi = irs->protostuff.espstuff.espp->esp_spi; -+ -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_rcv_value -+ipsec_rcv_esp_decrypt_setup(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb, -+ __u32 *replay, -+ unsigned char **authenticator) -+{ -+ struct esphdr *espp = irs->protostuff.espstuff.espp; -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "packet from %s received with seq=%d (iv)=0x%08x%08x iplen=%d esplen=%d sa=%s\n", -+ irs->ipsaddr_txt, -+ (__u32)ntohl(espp->esp_rpl), -+ (__u32)ntohl(*((__u32 *)(espp->esp_iv) )), -+ (__u32)ntohl(*((__u32 *)(espp->esp_iv) + 1)), -+ irs->len, -+ irs->ilen, -+ irs->sa_len ? irs->sa : " (error)"); -+ -+ *replay = ntohl(espp->esp_rpl); -+ *authenticator = &(skb->data[irs->len - irs->authlen]); -+ -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_rcv_value -+ipsec_rcv_esp_authcalc(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb) -+{ -+ struct auth_alg *aa; -+ struct esphdr *espp = irs->protostuff.espstuff.espp; -+ union { -+ MD5_CTX md5; -+ SHA1_CTX sha1; -+ } tctx; -+ -+#ifdef CONFIG_IPSEC_ALG -+ if (irs->ipsp->ips_alg_auth) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "ipsec_alg hashing proto=%d... ", -+ irs->said.proto); -+ if(irs->said.proto == IPPROTO_ESP) { -+ ipsec_alg_sa_esp_hash(irs->ipsp, -+ (caddr_t)espp, irs->ilen, -+ irs->hash, AHHMAC_HASHLEN); -+ return IPSEC_RCV_OK; -+ } -+ return IPSEC_RCV_BADPROTO; -+ } -+#endif -+ aa = irs->authfuncs; -+ -+ /* copy the initialized keying material */ -+ memcpy(&tctx, irs->ictx, irs->ictx_len); -+ -+ (*aa->update)((void *)&tctx, (caddr_t)espp, irs->ilen); -+ -+ (*aa->final)(irs->hash, (void *)&tctx); -+ -+ memcpy(&tctx, irs->octx, irs->octx_len); -+ -+ (*aa->update)((void *)&tctx, irs->hash, aa->hashlen); -+ (*aa->final)(irs->hash, (void *)&tctx); -+ -+ return IPSEC_RCV_OK; -+} -+ -+ -+enum ipsec_rcv_value -+ipsec_rcv_esp_decrypt(struct ipsec_rcv_state *irs) -+{ -+ struct ipsec_sa *ipsp = irs->ipsp; -+ struct esphdr *espp = irs->protostuff.espstuff.espp; -+ int esphlen = 0; -+ __u8 *idat; /* pointer to content to be decrypted/authenticated */ -+ __u32 iv[2]; -+ int pad = 0, padlen; -+ int badpad = 0; -+ int i; -+ struct sk_buff *skb; -+#ifdef CONFIG_IPSEC_ALG -+ struct ipsec_alg_enc *ixt_e=NULL; -+#endif /* CONFIG_IPSEC_ALG */ -+ -+ skb=irs->skb; -+ -+ idat = skb->data + irs->iphlen; -+ -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_e=ipsp->ips_alg_enc)) { -+ esphlen = ESP_HEADER_LEN + ixt_e->ixt_ivlen/8; -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "encalg=%d esphlen=%d\n", -+ ipsp->ips_encalg, esphlen); -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ipsp->ips_encalg) { -+ case ESP_3DES: -+ iv[0] = *((__u32 *)(espp->esp_iv) ); -+ iv[1] = *((__u32 *)(espp->esp_iv) + 1); -+ esphlen = sizeof(struct esphdr); -+ break; -+ default: -+ ipsp->ips_errs.ips_alg_errs += 1; -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_ESP_BADALG; -+ } -+ -+ idat += esphlen; -+ irs->ilen -= esphlen; -+ -+#ifdef CONFIG_IPSEC_ALG -+ if (ixt_e) -+ { -+ if (ipsec_alg_esp_encrypt(ipsp, -+ idat, irs->ilen, espp->esp_iv, -+ IPSEC_ALG_DECRYPT) <= 0) -+ { -+ printk("klips_error:ipsec_rcv: " -+ "got packet with esplen = %d " -+ "from %s -- should be on " -+ "ENC(%d) octet boundary, " -+ "packet dropped\n", -+ irs->ilen, -+ irs->ipsaddr_txt, -+ ipsp->ips_encalg); -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_BAD_DECRYPT; -+ } -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ipsp->ips_encalg) { -+ case ESP_3DES: -+ if ((irs->ilen) % 8) { -+ ipsp->ips_errs.ips_encsize_errs += 1; -+ printk("klips_error:ipsec_rcv: " -+ "got packet with esplen = %d from %s -- should be on 8 octet boundary, packet dropped\n", -+ irs->ilen, -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_3DES_BADBLOCKING; -+ } -+ des_ede3_cbc_encrypt((des_cblock *)idat, -+ (des_cblock *)idat, -+ irs->ilen, -+ ((struct des_eks *)(ipsp->ips_key_e))[0].ks, -+ ((struct des_eks *)(ipsp->ips_key_e))[1].ks, -+ ((struct des_eks *)(ipsp->ips_key_e))[2].ks, -+ (des_cblock *)iv, 0); -+ break; -+ } -+ -+ ipsec_rcv_dmp("postdecrypt", skb->data, skb->len); -+ -+ irs->next_header = idat[irs->ilen - 1]; -+ padlen = idat[irs->ilen - 2]; -+ pad = padlen + 2 + irs->authlen; -+ -+ KLIPS_PRINT(debug_rcv & DB_RX_IPAD, -+ "klips_debug:ipsec_rcv: " -+ "padlen=%d, contents: 0x: 0x 0x ...\n", -+ padlen); -+ -+ for (i = 1; i <= padlen; i++) { -+ if((i % 16) == 1) { -+ KLIPS_PRINT(debug_rcv & DB_RX_IPAD, -+ "klips_debug: %02x:", -+ i - 1); -+ } -+ KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD, -+ " %02x", -+ idat[irs->ilen - 2 - padlen + i - 1]); -+ if(i != idat[irs->ilen - 2 - padlen + i - 1]) { -+ badpad = 1; -+ } -+ if((i % 16) == 0) { -+ KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD, -+ "\n"); -+ } -+ } -+ if((i % 16) != 1) { -+ KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD, -+ "\n"); -+ } -+ if(badpad) { -+ KLIPS_PRINT(debug_rcv & DB_RX_IPAD, -+ "klips_debug:ipsec_rcv: " -+ "warning, decrypted packet from %s has bad padding\n", -+ irs->ipsaddr_txt); -+ KLIPS_PRINT(debug_rcv & DB_RX_IPAD, -+ "klips_debug:ipsec_rcv: " -+ "...may be bad decryption -- not dropped\n"); -+ ipsp->ips_errs.ips_encpad_errs += 1; -+ } -+ -+ KLIPS_PRINT(debug_rcv & DB_RX_IPAD, -+ "klips_debug:ipsec_rcv: " -+ "packet decrypted from %s: next_header = %d, padding = %d\n", -+ irs->ipsaddr_txt, -+ irs->next_header, -+ pad - 2 - irs->authlen); -+ -+ irs->ipp->tot_len = htons(ntohs(irs->ipp->tot_len) - (esphlen + pad)); -+ -+ /* -+ * move the IP header forward by the size of the ESP header, which -+ * will remove the the ESP header from the packet. -+ */ -+ memmove((void *)(skb->data + esphlen), -+ (void *)(skb->data), irs->iphlen); -+ -+ ipsec_rcv_dmp("esp postmove", skb->data, skb->len); -+ -+ /* skb_pull below, will move up by esphlen */ -+ -+ /* XXX not clear how this can happen, as the message indicates */ -+ if(skb->len < esphlen) { -+ printk(KERN_WARNING -+ "klips_error:ipsec_rcv: " -+ "tried to skb_pull esphlen=%d, %d available. This should never happen, please report.\n", -+ esphlen, (int)(skb->len)); -+ return IPSEC_RCV_ESP_DECAPFAIL; -+ } -+ skb_pull(skb, esphlen); -+ -+ irs->ipp = (struct iphdr *)skb->data; -+ -+ ipsec_rcv_dmp("esp postpull", skb->data, skb->len); -+ -+ /* now, trip off the padding from the end */ -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "trimming to %d.\n", -+ irs->len - esphlen - pad); -+ if(pad + esphlen <= irs->len) { -+ skb_trim(skb, irs->len - esphlen - pad); -+ } else { -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "bogus packet, size is zero or negative, dropping.\n"); -+ return IPSEC_RCV_DECAPFAIL; -+ } -+ -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_xmit_esp_setup(struct ipsec_xmit_state *ixs) -+{ -+ __u32 iv[2]; -+ struct esphdr *espp; -+ int ilen = 0; -+ int padlen = 0, i; -+ unsigned char *dat; -+ unsigned char *idat, *pad; -+ __u8 hash[AH_AMAX]; -+ union { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ MD5_CTX md5; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ SHA1_CTX sha1; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ } tctx; -+ -+ dat = (unsigned char *)ixs->iph; -+ -+ espp = (struct esphdr *)(dat + ixs->iphlen); -+ espp->esp_spi = ixs->ipsp->ips_said.spi; -+ espp->esp_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); -+ -+ switch(ixs->ipsp->ips_encalg) { -+#if defined(CONFIG_IPSEC_ENC_3DES) -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ iv[0] = *((__u32*)&(espp->esp_iv) ) = -+ ((__u32*)(ixs->ipsp->ips_iv))[0]; -+ iv[1] = *((__u32*)&(espp->esp_iv) + 1) = -+ ((__u32*)(ixs->ipsp->ips_iv))[1]; -+ break; -+#endif /* defined(CONFIG_IPSEC_ENC_3DES) */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+ -+ idat = dat + ixs->iphlen + sizeof(struct esphdr); -+ ilen = ixs->skb->len - (ixs->iphlen + sizeof(struct esphdr) + ixs->authlen); -+ -+ /* Self-describing padding */ -+ pad = &dat[ixs->skb->len - ixs->tailroom]; -+ padlen = ixs->tailroom - 2 - ixs->authlen; -+ for (i = 0; i < padlen; i++) { -+ pad[i] = i + 1; -+ } -+ dat[ixs->skb->len - ixs->authlen - 2] = padlen; -+ -+ dat[ixs->skb->len - ixs->authlen - 1] = ixs->iph->protocol; -+ ixs->iph->protocol = IPPROTO_ESP; -+ -+ switch(ixs->ipsp->ips_encalg) { -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+ des_ede3_cbc_encrypt((des_cblock *)idat, -+ (des_cblock *)idat, -+ ilen, -+ ((struct des_eks *)(ixs->ipsp->ips_key_e))[0].ks, -+ ((struct des_eks *)(ixs->ipsp->ips_key_e))[1].ks, -+ ((struct des_eks *)(ixs->ipsp->ips_key_e))[2].ks, -+ (des_cblock *)iv, 1); -+ break; -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+ -+ switch(ixs->ipsp->ips_encalg) { -+#if defined(CONFIG_IPSEC_ENC_3DES) -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ /* XXX update IV with the last 8 octets of the encryption */ -+#if KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK -+ ((__u32*)(ixs->ipsp->ips_iv))[0] = -+ ((__u32 *)(idat))[(ilen >> 2) - 2]; -+ ((__u32*)(ixs->ipsp->ips_iv))[1] = -+ ((__u32 *)(idat))[(ilen >> 2) - 1]; -+#else /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */ -+ prng_bytes(&ipsec_prng, (char *)ixs->ipsp->ips_iv, EMT_ESPDES_IV_SZ); -+#endif /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */ -+ break; -+#endif /* defined(CONFIG_IPSEC_ENC_3DES) */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+ -+ switch(ixs->ipsp->ips_authalg) { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: -+ ipsec_xmit_dmp("espp", (char*)espp, ixs->skb->len - ixs->iphlen - ixs->authlen); -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ ipsec_xmit_dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (caddr_t)espp, ixs->skb->len - ixs->iphlen - ixs->authlen); -+ ipsec_xmit_dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ ipsec_xmit_dmp("ictx hash", (char*)&hash, sizeof(hash)); -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ ipsec_xmit_dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, hash, AHMD596_ALEN); -+ ipsec_xmit_dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ ipsec_xmit_dmp("octx hash", (char*)&hash, sizeof(hash)); -+ memcpy(&(dat[ixs->skb->len - ixs->authlen]), hash, ixs->authlen); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ SHA1Update(&tctx.sha1, (caddr_t)espp, ixs->skb->len - ixs->iphlen - ixs->authlen); -+ SHA1Final(hash, &tctx.sha1); -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); -+ SHA1Final(hash, &tctx.sha1); -+ memcpy(&(dat[ixs->skb->len - ixs->authlen]), hash, ixs->authlen); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ case AH_NONE: -+ break; -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_AH_BADALG; -+ } -+#ifdef NET_21 -+ ixs->skb->h.raw = (unsigned char*)espp; -+#endif /* NET_21 */ -+ -+ return IPSEC_XMIT_OK; -+} -+ -+ -+struct xform_functions esp_xform_funcs[]={ -+ { rcv_checks: ipsec_rcv_esp_checks, -+ rcv_setup_auth: ipsec_rcv_esp_decrypt_setup, -+ rcv_calc_auth: ipsec_rcv_esp_authcalc, -+ rcv_decrypt: ipsec_rcv_esp_decrypt, -+ -+ xmit_setup: ipsec_xmit_esp_setup, -+ xmit_headroom: sizeof(struct esphdr), -+ xmit_needtailroom: 1, -+ }, -+}; -+ -+struct inet_protocol esp_protocol = -+{ -+ ipsec_rcv, /* ESP handler */ -+ NULL, /* TUNNEL error control */ -+#ifdef NETDEV_25 -+ 1, /* no policy */ -+#else -+ 0, /* next */ -+ IPPROTO_ESP, /* protocol ID */ -+ 0, /* copy */ -+ NULL, /* data */ -+ "ESP" /* name */ -+#endif -+}; -+ -+ -+ -+#endif /* !CONFIG_IPSEC_ESP */ -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.2 2004/04/06 02:49:25 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_init.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,531 @@ -+/* -+ * @(#) Initialization code. -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998 - 2002 Richard Guy Briggs -+ * 2001 - 2004 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * /proc system code was split out into ipsec_proc.c after rev. 1.70. -+ * -+ */ -+ -+char ipsec_init_c_version[] = "RCSID $Id$"; -+ -+#include -+#include -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include /* struct sockaddr_in */ -+#include -+#include /* get_random_bytes() */ -+#include -+ -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* 23_SPINLOCK */ -+# include /* *lock* */ -+# endif /* 23_SPINLOCK */ -+#endif /* SPINLOCK */ -+ -+#ifdef NET_21 -+# include -+# include -+#endif /* NET_21 */ -+ -+#include -+#include -+ -+#ifdef CONFIG_PROC_FS -+# include -+#endif /* CONFIG_PROC_FS */ -+ -+#ifdef NETLINK_SOCK -+# include -+#else -+# include -+#endif -+ -+#include "openswan/radij.h" -+ -+#include "openswan/ipsec_life.h" -+#include "openswan/ipsec_stats.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+ -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+# include "openswan/ipcomp.h" -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#include "openswan/ipsec_proto.h" -+#include "openswan/ipsec_alg.h" -+ -+#include -+#include -+ -+#if !defined(CONFIG_IPSEC_ESP) && !defined(CONFIG_IPSEC_AH) -+#error "kernel configuration must include ESP or AH" -+#endif -+ -+/* -+ * seems to be present in 2.4.10 (Linus), but also in some RH and other -+ * distro kernels of a lower number. -+ */ -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_eroute = 0; -+int debug_spi = 0; -+int debug_netlink = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+struct prng ipsec_prng; -+ -+extern int ipsec_device_event(struct notifier_block *dnot, unsigned long event, void *ptr); -+/* -+ * the following structure is required so that we receive -+ * event notifications when network devices are enabled and -+ * disabled (ifconfig up and down). -+ */ -+static struct notifier_block ipsec_dev_notifier={ -+ ipsec_device_event, -+ NULL, -+ 0 -+}; -+ -+#ifdef CONFIG_SYSCTL -+extern int ipsec_sysctl_register(void); -+extern void ipsec_sysctl_unregister(void); -+#endif -+ -+static inline int -+openswan_inet_add_protocol(struct inet_protocol *prot, unsigned protocol) -+{ -+#ifdef NETDEV_25 -+ return inet_add_protocol(prot, protocol); -+#else -+ inet_add_protocol(prot); -+ return 0; -+#endif -+} -+ -+static inline int -+openswan_inet_del_protocol(struct inet_protocol *prot, unsigned protocol) -+{ -+#ifdef NETDEV_25 -+ return inet_del_protocol(prot, protocol); -+#else -+ inet_del_protocol(prot); -+ return 0; -+#endif -+} -+ -+/* void */ -+int -+ipsec_init(void) -+{ -+ int error = 0; -+ unsigned char seed[256]; -+#ifdef CONFIG_IPSEC_ENC_3DES -+ extern int des_check_key; -+ -+ /* turn off checking of keys */ -+ des_check_key=0; -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ -+ KLIPS_PRINT(1, "klips_info:ipsec_init: " -+ "KLIPS startup, Openswan KLIPS IPsec stack version: %s\n", -+ ipsec_version_code()); -+ -+ error |= ipsec_proc_init(); -+ -+#ifdef SPINLOCK -+ ipsec_sadb.sadb_lock = SPIN_LOCK_UNLOCKED; -+#else /* SPINLOCK */ -+ ipsec_sadb.sadb_lock = 0; -+#endif /* SPINLOCK */ -+ -+#ifndef SPINLOCK -+ tdb_lock.lock = 0; -+ eroute_lock.lock = 0; -+#endif /* !SPINLOCK */ -+ -+ error |= ipsec_sadb_init(); -+ error |= ipsec_radijinit(); -+ -+ error |= pfkey_init(); -+ -+ error |= register_netdevice_notifier(&ipsec_dev_notifier); -+ -+#ifdef CONFIG_IPSEC_ESP -+ openswan_inet_add_protocol(&esp_protocol, IPPROTO_ESP); -+#endif /* CONFIG_IPSEC_ESP */ -+ -+#ifdef CONFIG_IPSEC_AH -+ openswan_inet_add_protocol(&ah_protocol, IPPROTO_AH); -+#endif /* CONFIG_IPSEC_AH */ -+ -+/* we never actually link IPCOMP to the stack */ -+#ifdef IPCOMP_USED_ALONE -+#ifdef CONFIG_IPSEC_IPCOMP -+ openswan_inet_add_protocol(&comp_protocol, IPPROTO_COMP); -+#endif /* CONFIG_IPSEC_IPCOMP */ -+#endif -+ -+ error |= ipsec_tunnel_init_devices(); -+ -+ -+#ifdef CONFIG_SYSCTL -+ error |= ipsec_sysctl_register(); -+#endif -+ -+#ifdef CONFIG_IPSEC_ALG -+ ipsec_alg_init(); -+#endif -+ -+ get_random_bytes((void *)seed, sizeof(seed)); -+ prng_init(&ipsec_prng, seed, sizeof(seed)); -+ -+ return error; -+} -+ -+ -+/* void */ -+int -+ipsec_cleanup(void) -+{ -+ int error = 0; -+ -+#ifdef CONFIG_SYSCTL -+ ipsec_sysctl_unregister(); -+#endif -+ KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ -+ "klips_debug:ipsec_cleanup: " -+ "calling ipsec_tunnel_cleanup_devices.\n"); -+ error |= ipsec_tunnel_cleanup_devices(); -+ -+ KLIPS_PRINT(debug_netlink, "called ipsec_tunnel_cleanup_devices"); -+ -+/* we never actually link IPCOMP to the stack */ -+#ifdef IPCOMP_USED_ALONE -+#ifdef CONFIG_IPSEC_IPCOMP -+ if (openswan_inet_del_protocol(&comp_protocol, IPPROTO_COMP) < 0) -+ printk(KERN_INFO "klips_debug:ipsec_cleanup: " -+ "comp close: can't remove protocol\n"); -+#endif /* CONFIG_IPSEC_IPCOMP */ -+#endif /* IPCOMP_USED_ALONE */ -+ -+#ifdef CONFIG_IPSEC_AH -+ if (openswan_inet_del_protocol(&ah_protocol, IPPROTO_AH) < 0) -+ printk(KERN_INFO "klips_debug:ipsec_cleanup: " -+ "ah close: can't remove protocol\n"); -+#endif /* CONFIG_IPSEC_AH */ -+ -+#ifdef CONFIG_IPSEC_ESP -+ if (openswan_inet_del_protocol(&esp_protocol, IPPROTO_ESP) < 0) -+ printk(KERN_INFO "klips_debug:ipsec_cleanup: " -+ "esp close: can't remove protocol\n"); -+#endif /* CONFIG_IPSEC_ESP */ -+ -+ error |= unregister_netdevice_notifier(&ipsec_dev_notifier); -+ -+ KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ -+ "klips_debug:ipsec_cleanup: " -+ "calling ipsec_sadb_cleanup.\n"); -+ error |= ipsec_sadb_cleanup(0); -+ error |= ipsec_sadb_free(); -+ -+ KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ -+ "klips_debug:ipsec_cleanup: " -+ "calling ipsec_radijcleanup.\n"); -+ error |= ipsec_radijcleanup(); -+ -+ KLIPS_PRINT(debug_pfkey, /* debug_tunnel & DB_TN_INIT, */ -+ "klips_debug:ipsec_cleanup: " -+ "calling pfkey_cleanup.\n"); -+ error |= pfkey_cleanup(); -+ -+ ipsec_proc_cleanup(); -+ -+ prng_final(&ipsec_prng); -+ -+ return error; -+} -+ -+#ifdef MODULE -+int -+init_module(void) -+{ -+ int error = 0; -+ -+ error |= ipsec_init(); -+ -+ return error; -+} -+ -+int -+cleanup_module(void) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ -+ "klips_debug:cleanup_module: " -+ "calling ipsec_cleanup.\n"); -+ -+ error |= ipsec_cleanup(); -+ -+ KLIPS_PRINT(1, "klips_info:cleanup_module: " -+ "ipsec module unloaded.\n"); -+ -+ return error; -+} -+#endif /* MODULE */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.93 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.92 2004/03/30 15:30:39 ken -+ * Proper Capitalization -+ * -+ * Revision 1.91 2004/03/22 01:51:51 ken -+ * We are open -+ * -+ * Revision 1.90.4.2 2004/04/05 04:30:46 mcr -+ * patches for alg-branch to compile/work with 2.x openswan -+ * -+ * Revision 1.90.4.1 2003/12/22 15:25:52 jjo -+ * Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.90 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.89.4.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.89 2003/07/31 22:47:16 mcr -+ * preliminary (untested by FS-team) 2.5 patches. -+ * -+ * Revision 1.88 2003/06/22 20:05:36 mcr -+ * clarified why IPCOMP was not being registered, and put a new -+ * #ifdef in rather than #if 0. -+ * -+ * Revision 1.87 2002/09/20 15:40:51 rgb -+ * Added a lock to the global ipsec_sadb struct for future use. -+ * Split ipsec_sadb_cleanup from new funciton ipsec_sadb_free to avoid problem -+ * of freeing newly created structures when clearing the reftable upon startup -+ * to start from a known state. -+ * -+ * Revision 1.86 2002/08/15 18:39:15 rgb -+ * Move ipsec_prng outside debug code. -+ * -+ * Revision 1.85 2002/05/14 02:35:29 rgb -+ * Change reference to tdb to ipsa. -+ * -+ * Revision 1.84 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.83 2002/04/24 07:36:28 mcr -+ * Moved from ./klips/net/ipsec/ipsec_init.c,v -+ * -+ * Revision 1.82 2002/04/20 00:12:25 rgb -+ * Added esp IV CBC attack fix, disabled. -+ * -+ * Revision 1.81 2002/04/09 16:13:32 mcr -+ * switch license to straight GPL. -+ * -+ * Revision 1.80 2002/03/24 07:34:08 rgb -+ * Sanity check for at least one of AH or ESP configured. -+ * -+ * Revision 1.79 2002/02/05 22:55:15 mcr -+ * added MODULE_LICENSE declaration. -+ * This macro does not appear in all kernel versions (see comment). -+ * -+ * Revision 1.78 2002/01/29 17:17:55 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.77 2002/01/29 04:00:51 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.76 2002/01/29 02:13:17 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.75 2001/11/26 09:23:48 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.74 2001/11/22 05:44:11 henry -+ * new version stuff -+ * -+ * Revision 1.71.2.2 2001/10/22 20:51:00 mcr -+ * explicitely set des_check_key. -+ * -+ * Revision 1.71.2.1 2001/09/25 02:19:39 mcr -+ * /proc manipulation code moved to new ipsec_proc.c -+ * -+ * Revision 1.73 2001/11/06 19:47:17 rgb -+ * Changed lifetime_packets to uint32 from uint64. -+ * -+ * Revision 1.72 2001/10/18 04:45:19 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.71 2001/09/20 15:32:45 rgb -+ * Minor pfkey lifetime fixes. -+ * -+ * Revision 1.70 2001/07/06 19:51:21 rgb -+ * Added inbound policy checking code for IPIP SAs. -+ * -+ * Revision 1.69 2001/06/14 19:33:26 rgb -+ * Silence startup message for console, but allow it to be logged. -+ * Update copyright date. -+ * -+ * Revision 1.68 2001/05/29 05:14:36 rgb -+ * Added PMTU to /proc/net/ipsec_tncfg output. See 'man 5 ipsec_tncfg'. -+ * -+ * Revision 1.67 2001/05/04 16:34:52 rgb -+ * Rremove erroneous checking of return codes for proc_net_* in 2.4. -+ * -+ * Revision 1.66 2001/05/03 19:40:34 rgb -+ * Check error return codes in startup and shutdown. -+ * -+ * Revision 1.65 2001/02/28 05:03:27 rgb -+ * Clean up and rationalise startup messages. -+ * -+ * Revision 1.64 2001/02/27 22:24:53 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.63 2000/11/29 20:14:06 rgb -+ * Add src= to the output of /proc/net/ipsec_spi and delete dst from IPIP. -+ * -+ * Revision 1.62 2000/11/06 04:31:24 rgb -+ * Ditched spin_lock_irqsave in favour of spin_lock_bh. -+ * Fixed longlong for pre-2.4 kernels (Svenning). -+ * Add Svenning's adaptive content compression. -+ * Disabled registration of ipcomp handler. -+ * -+ * Revision 1.61 2000/10/11 13:37:54 rgb -+ * #ifdef out debug print that causes proc/net/ipsec_version to oops. -+ * -+ * Revision 1.60 2000/09/20 03:59:01 rgb -+ * Change static info functions to DEBUG_NO_STATIC to reveal function names -+ * in oopsen. -+ * -+ * Revision 1.59 2000/09/16 01:06:26 rgb -+ * Added cast of var to silence compiler warning about long fed to int -+ * format. -+ * -+ * Revision 1.58 2000/09/15 11:37:01 rgb -+ * Merge in heavily modified Svenning Soerensen's -+ * IPCOMP zlib deflate code. -+ * -+ * Revision 1.57 2000/09/12 03:21:50 rgb -+ * Moved radij_c_version printing to ipsec_version_get_info(). -+ * Reformatted ipsec_version_get_info(). -+ * Added sysctl_{,un}register() calls. -+ * -+ * Revision 1.56 2000/09/08 19:16:50 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * Removed all references to CONFIG_IPSEC_PFKEYv2. -+ * -+ * Revision 1.55 2000/08/30 05:19:03 rgb -+ * Cleaned up no longer used spi_next, netlink register/unregister, other -+ * minor cleanup. -+ * Removed cruft replaced by TDB_XFORM_NAME. -+ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst. -+ * Moved debug version strings to printk when /proc/net/ipsec_version is -+ * called. -+ * -+ * Revision 1.54 2000/08/20 18:31:05 rgb -+ * Changed cosmetic alignment in spi_info. -+ * Changed addtime and usetime to use actual value which is relative -+ * anyways, as intended. (Momchil) -+ * -+ * Revision 1.53 2000/08/18 17:37:03 rgb -+ * Added an (int) cast to shut up the compiler... -+ * -+ * Revision 1.52 2000/08/01 14:51:50 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.51 2000/07/25 20:41:22 rgb -+ * Removed duplicate parameter in spi_getinfo. -+ * -+ * Revision 1.50 2000/07/17 03:21:45 rgb -+ * Removed /proc/net/ipsec_spinew. -+ * -+ * Revision 1.49 2000/06/28 05:46:51 rgb -+ * Renamed ivlen to iv_bits for consistency. -+ * Changed output of add and use times to be relative to now. -+ * -+ * Revision 1.48 2000/05/11 18:26:10 rgb -+ * Commented out calls to netlink_attach/detach to avoid activating netlink -+ * in the kenrel config. -+ * -+ * Revision 1.47 2000/05/10 22:35:26 rgb -+ * Comment out most of the startup version information. -+ * -+ * Revision 1.46 2000/03/22 16:15:36 rgb -+ * Fixed renaming of dev_get (MB). -+ * -+ * Revision 1.45 2000/03/16 06:40:48 rgb -+ * Hardcode PF_KEYv2 support. -+ * -+ * Revision 1.44 2000/01/22 23:19:20 rgb -+ * Simplified code to use existing macro TDB_XFORM_NAME(). -+ * -+ * Revision 1.43 2000/01/21 06:14:04 rgb -+ * Print individual stats only if non-zero. -+ * Removed 'bits' from each keylength for brevity. -+ * Shortened lifetimes legend for brevity. -+ * Changed wording from 'last_used' to the clearer 'idle'. -+ * -+ * Revision 1.42 1999/12/31 14:57:19 rgb -+ * MB fix for new dummy-less proc_get_info in 2.3.35. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_ipcomp.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,276 @@ -+/* -+ * processing code for IPCOMP -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_ipcomp_c_version[] = "RCSID $Id$"; -+#include -+#include -+ -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define proto_priv cb -+#endif /* NET21 */ -+#include -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipsec_xmit.h" -+ -+#include "openswan/ipsec_auth.h" -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+#include "openswan/ipsec_ipcomp.h" -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#include "openswan/ipsec_proto.h" -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_ipcomp = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+enum ipsec_rcv_value -+ipsec_rcv_ipcomp_checks(struct ipsec_rcv_state *irs, -+ struct sk_buff *skb) -+{ -+ int ipcompminlen; -+ -+ ipcompminlen = irs->hard_header_len + sizeof(struct iphdr); -+ -+ if(skb->len < (ipcompminlen + sizeof(struct ipcomphdr))) { -+ KLIPS_PRINT(debug_rcv & DB_RX_INAU, -+ "klips_debug:ipsec_rcv: " -+ "runt comp packet of skb->len=%d received from %s, dropped.\n", -+ skb->len, -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_BADLEN; -+ } -+ -+ irs->protostuff.ipcompstuff.compp = (struct ipcomphdr *)(skb->data + irs->iphlen); -+ irs->said.spi = htonl((__u32)ntohs(irs->protostuff.ipcompstuff.compp->ipcomp_cpi)); -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_rcv_value -+ipsec_rcv_ipcomp_decomp(struct ipsec_rcv_state *irs) -+{ -+ unsigned int flags = 0; -+ struct ipsec_sa *ipsp = irs->ipsp; -+ struct sk_buff *skb; -+ -+ skb=irs->skb; -+ -+ ipsec_xmit_dmp("ipcomp", skb->data, skb->len); -+ -+ if(ipsp == NULL) { -+ return IPSEC_RCV_SAIDNOTFOUND; -+ } -+ -+#if 0 -+ /* we want to check that this wasn't the first SA on the list, because -+ * we don't support bare IPCOMP, for unexplained reasons. MCR -+ */ -+ if (ipsp->ips_onext != NULL) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "Incoming packet with outer IPCOMP header SA:%s: not yet supported by KLIPS, dropped\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ -+ return IPSEC_RCV_IPCOMPALONE; -+ } -+#endif -+ -+ if(sysctl_ipsec_inbound_policy_check && -+ ((((ntohl(ipsp->ips_said.spi) & 0x0000ffff) != ntohl(irs->said.spi)) && -+ (ipsp->ips_encalg != ntohl(irs->said.spi)) /* this is a workaround for peer non-compliance with rfc2393 */ -+ ))) { -+ char sa2[SATOT_BUF]; -+ size_t sa_len2 = 0; -+ -+ sa_len2 = satot(&ipsp->ips_said, 0, sa2, sizeof(sa2)); -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "Incoming packet with SA(IPCA):%s does not match policy SA(IPCA):%s cpi=%04x cpi->spi=%08x spi=%08x, spi->cpi=%04x for SA grouping, dropped.\n", -+ irs->sa_len ? irs->sa : " (error)", -+ ipsp != NULL ? (sa_len2 ? sa2 : " (error)") : "NULL", -+ ntohs(irs->protostuff.ipcompstuff.compp->ipcomp_cpi), -+ (__u32)ntohl(irs->said.spi), -+ ipsp != NULL ? (__u32)ntohl((ipsp->ips_said.spi)) : 0, -+ ipsp != NULL ? (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff) : 0); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_SAIDNOTFOUND; -+ } -+ -+ ipsp->ips_comp_ratio_cbytes += ntohs(irs->ipp->tot_len); -+ irs->next_header = irs->protostuff.ipcompstuff.compp->ipcomp_nh; -+ -+ skb = skb_decompress(skb, ipsp, &flags); -+ if (!skb || flags) { -+ spin_unlock(&tdb_lock); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "skb_decompress() returned error flags=%x, dropped.\n", -+ flags); -+ if (irs->stats) { -+ if (flags) -+ irs->stats->rx_errors++; -+ else -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_IPCOMPFAILED; -+ } -+ -+ /* make sure we update the pointer */ -+ irs->skb = skb; -+ -+#ifdef NET_21 -+ irs->ipp = skb->nh.iph; -+#else /* NET_21 */ -+ irs->ipp = skb->ip_hdr; -+#endif /* NET_21 */ -+ -+ ipsp->ips_comp_ratio_dbytes += ntohs(irs->ipp->tot_len); -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "packet decompressed SA(IPCA):%s cpi->spi=%08x spi=%08x, spi->cpi=%04x, nh=%d.\n", -+ irs->sa_len ? irs->sa : " (error)", -+ (__u32)ntohl(irs->said.spi), -+ ipsp != NULL ? (__u32)ntohl((ipsp->ips_said.spi)) : 0, -+ ipsp != NULL ? (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff) : 0, -+ irs->next_header); -+ KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, irs->ipp); -+ -+ return IPSEC_RCV_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_xmit_ipcomp_setup(struct ipsec_xmit_state *ixs) -+{ -+ unsigned int flags = 0; -+#ifdef CONFIG_IPSEC_DEBUG -+ unsigned int old_tot_len = ntohs(ixs->iph->tot_len); -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ ixs->ipsp->ips_comp_ratio_dbytes += ntohs(ixs->iph->tot_len); -+ -+ ixs->skb = skb_compress(ixs->skb, ixs->ipsp, &flags); -+ -+#ifdef NET_21 -+ ixs->iph = ixs->skb->nh.iph; -+#else /* NET_21 */ -+ ixs->iph = ixs->skb->ip_hdr; -+#endif /* NET_21 */ -+ -+ ixs->ipsp->ips_comp_ratio_cbytes += ntohs(ixs->iph->tot_len); -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_tunnel & DB_TN_CROUT) -+ { -+ if (old_tot_len > ntohs(ixs->iph->tot_len)) -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "packet shrunk from %d to %d bytes after compression, cpi=%04x (should be from spi=%08x, spi&0xffff=%04x.\n", -+ old_tot_len, ntohs(ixs->iph->tot_len), -+ ntohs(((struct ipcomphdr*)(((char*)ixs->iph) + ((ixs->iph->ihl) << 2)))->ipcomp_cpi), -+ ntohl(ixs->ipsp->ips_said.spi), -+ (__u16)(ntohl(ixs->ipsp->ips_said.spi) & 0x0000ffff)); -+ else -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "packet did not compress (flags = %d).\n", -+ flags); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ return IPSEC_XMIT_OK; -+} -+ -+struct xform_functions ipcomp_xform_funcs[]={ -+ {rcv_checks: ipsec_rcv_ipcomp_checks, -+ rcv_decrypt: ipsec_rcv_ipcomp_decomp, -+ xmit_setup: ipsec_xmit_ipcomp_setup, -+ xmit_headroom: 0, -+ xmit_needtailroom: 0, -+ }, -+}; -+ -+#if 0 -+/* We probably don't want to install a pure IPCOMP protocol handler, but -+ only want to handle IPCOMP if it is encapsulated inside an ESP payload -+ (which is already handled) */ -+#ifdef CONFIG_IPSEC_IPCOMP -+struct inet_protocol comp_protocol = -+{ -+ ipsec_rcv, /* COMP handler */ -+ NULL, /* COMP error control */ -+#ifdef NETDEV_25 -+ 1, /* no policy */ -+#else -+ 0, /* next */ -+ IPPROTO_COMP, /* protocol ID */ -+ 0, /* copy */ -+ NULL, /* data */ -+ "COMP" /* name */ -+#endif -+}; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+#endif -+ -+#endif /* CONFIG_IPSEC_IPCOMP */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_ipip.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,133 @@ -+/* -+ * processing code for IPIP -+ * Copyright (C) 2003 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_ipip_c_version[] = "RCSID $Id$"; -+#include -+#include -+ -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define proto_priv cb -+#endif /* NET21 */ -+#include -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipsec_xmit.h" -+ -+#include "openswan/ipsec_auth.h" -+#include "openswan/ipsec_ipip.h" -+#include "openswan/ipsec_param.h" -+ -+#include "openswan/ipsec_proto.h" -+ -+enum ipsec_xmit_value -+ipsec_xmit_ipip_setup(struct ipsec_xmit_state *ixs) -+{ -+ ixs->iph->version = 4; -+ -+ switch(sysctl_ipsec_tos) { -+ case 0: -+#ifdef NET_21 -+ ixs->iph->tos = ixs->skb->nh.iph->tos; -+#else /* NET_21 */ -+ ixs->iph->tos = ixs->skb->ip_hdr->tos; -+#endif /* NET_21 */ -+ break; -+ case 1: -+ ixs->iph->tos = 0; -+ break; -+ default: -+ break; -+ } -+#ifdef NET_21 -+#ifdef NETDEV_23 -+ ixs->iph->ttl = sysctl_ip_default_ttl; -+#else /* NETDEV_23 */ -+ ixs->iph->ttl = ip_statistics.IpDefaultTTL; -+#endif /* NETDEV_23 */ -+#else /* NET_21 */ -+ ixs->iph->ttl = 64; /* ip_statistics.IpDefaultTTL; */ -+#endif /* NET_21 */ -+ ixs->iph->frag_off = 0; -+ ixs->iph->saddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_s))->sin_addr.s_addr; -+ ixs->iph->daddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_d))->sin_addr.s_addr; -+ ixs->iph->protocol = IPPROTO_IPIP; -+ ixs->iph->ihl = sizeof(struct iphdr) >> 2; -+ -+ KLIPS_IP_SELECT_IDENT(ixs->iph, ixs->skb); -+ -+ ixs->newdst = (__u32)ixs->iph->daddr; -+ ixs->newsrc = (__u32)ixs->iph->saddr; -+ -+#ifdef NET_21 -+ ixs->skb->h.ipiph = ixs->skb->nh.iph; -+#endif /* NET_21 */ -+ return IPSEC_XMIT_OK; -+} -+ -+struct xform_functions ipip_xform_funcs[]={ -+ { rcv_checks: NULL, -+ rcv_setup_auth: NULL, -+ rcv_calc_auth: NULL, -+ rcv_decrypt: NULL, -+ -+ xmit_setup: ipsec_xmit_ipip_setup, -+ xmit_headroom: sizeof(struct iphdr), -+ xmit_needtailroom: 0, -+ }, -+}; -+ -+ -+ -+ -+ -+ -+ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_life.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,263 @@ -+/* -+ * @(#) lifetime structure utilities -+ * -+ * Copyright (C) 2001 Richard Guy Briggs -+ * and Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ */ -+ -+/* -+ * This provides series of utility functions for dealing with lifetime -+ * structures. -+ * -+ * ipsec_check_lifetime - returns -1 hard lifetime exceeded -+ * 0 soft lifetime exceeded -+ * 1 everything is okay -+ * based upon whether or not the count exceeds hard/soft -+ * -+ */ -+ -+#define __NO_VERSION__ -+#include -+#include /* for CONFIG_IP_FORWARD */ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#include /* struct device, struct net_device_stats and other headers */ -+#include /* eth_type_trans */ -+#include -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_life.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_eroute.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+ -+#include "openswan/ipsec_sa.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_ipe4.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+#include "openswan/ipcomp.h" -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+ -+ -+enum ipsec_life_alive -+ipsec_lifetime_check(struct ipsec_lifetime64 *il64, -+ const char *lifename, -+ const char *saname, -+ enum ipsec_life_type ilt, -+ enum ipsec_direction idir, -+ struct ipsec_sa *ips) -+{ -+ __u64 count; -+ const char *dir; -+ -+ if(saname == NULL) { -+ saname = "unknown-SA"; -+ } -+ -+ if(idir == ipsec_incoming) { -+ dir = "incoming"; -+ } else { -+ dir = "outgoing"; -+ } -+ -+ -+ if(ilt == ipsec_life_timebased) { -+ count = jiffies/HZ - il64->ipl_count; -+ } else { -+ count = il64->ipl_count; -+ } -+ -+ if(il64->ipl_hard && -+ (count > il64->ipl_hard)) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_lifetime_check: " -+ "hard %s lifetime of SA:<%s%s%s> %s has been reached, SA expired, " -+ "%s packet dropped.\n", -+ lifename, -+ IPS_XFORM_NAME(ips), -+ saname, -+ dir); -+ -+ pfkey_expire(ips, 1); -+ return ipsec_life_harddied; -+ } -+ -+ if(il64->ipl_soft && -+ (count > il64->ipl_soft)) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_lifetime_check: " -+ "soft %s lifetime of SA:<%s%s%s> %s has been reached, SA expiring, " -+ "soft expire message sent up, %s packet still processed.\n", -+ lifename, -+ IPS_XFORM_NAME(ips), -+ saname, -+ dir); -+ -+ if(ips->ips_state != SADB_SASTATE_DYING) { -+ pfkey_expire(ips, 0); -+ } -+ ips->ips_state = SADB_SASTATE_DYING; -+ -+ return ipsec_life_softdied; -+ } -+ return ipsec_life_okay; -+} -+ -+ -+/* -+ * This function takes a buffer (with length), a lifetime name and type, -+ * and formats a string to represent the current values of the lifetime. -+ * -+ * It returns the number of bytes that the format took (or would take, -+ * if the buffer were large enough: snprintf semantics). -+ * This is used in /proc routines and in debug output. -+ */ -+int -+ipsec_lifetime_format(char *buffer, -+ int buflen, -+ char *lifename, -+ enum ipsec_life_type timebaselife, -+ struct ipsec_lifetime64 *lifetime) -+{ -+ int len = 0; -+ __u64 count; -+ -+ if(timebaselife == ipsec_life_timebased) { -+ count = jiffies/HZ - lifetime->ipl_count; -+ } else { -+ count = lifetime->ipl_count; -+ } -+ -+ if(lifetime->ipl_count > 1 || -+ lifetime->ipl_soft || -+ lifetime->ipl_hard) { -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)) -+ len = ipsec_snprintf(buffer, buflen, -+ "%s(%Lu,%Lu,%Lu)", -+ lifename, -+ count, -+ lifetime->ipl_soft, -+ lifetime->ipl_hard); -+#else /* XXX high 32 bits are not displayed */ -+ len = ipsec_snprintf(buffer, buflen, -+ "%s(%lu,%lu,%lu)", -+ lifename, -+ (unsigned long)count, -+ (unsigned long)lifetime->ipl_soft, -+ (unsigned long)lifetime->ipl_hard); -+#endif -+ } -+ -+ return len; -+} -+ -+void -+ipsec_lifetime_update_hard(struct ipsec_lifetime64 *lifetime, -+ __u64 newvalue) -+{ -+ if(newvalue && -+ (!lifetime->ipl_hard || -+ (newvalue < lifetime->ipl_hard))) { -+ lifetime->ipl_hard = newvalue; -+ -+ if(!lifetime->ipl_soft && -+ (lifetime->ipl_hard < lifetime->ipl_soft)) { -+ lifetime->ipl_soft = lifetime->ipl_hard; -+ } -+ } -+} -+ -+void -+ipsec_lifetime_update_soft(struct ipsec_lifetime64 *lifetime, -+ __u64 newvalue) -+{ -+ if(newvalue && -+ (!lifetime->ipl_soft || -+ (newvalue < lifetime->ipl_soft))) { -+ lifetime->ipl_soft = newvalue; -+ -+ if(lifetime->ipl_hard && -+ (lifetime->ipl_hard < lifetime->ipl_soft)) { -+ lifetime->ipl_soft = lifetime->ipl_hard; -+ } -+ } -+} -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.12 2004/04/23 20:44:35 ken -+ * Update comments -+ * -+ * Revision 1.11 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.10 2004/03/30 11:03:10 paul -+ * two more occurances of snprintf, found by Sam from a users oops msg. -+ * -+ * Revision 1.9 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.8.4.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.8 2003/02/06 02:00:10 rgb -+ * Fixed incorrect debugging text label -+ * -+ * Revision 1.7 2002/05/23 07:16:26 rgb -+ * Fixed absolute/relative reference to lifetime count printout. -+ * -+ * Revision 1.6 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.5 2002/04/24 07:36:28 mcr -+ * Moved from ./klips/net/ipsec/ipsec_life.c,v -+ * -+ * Revision 1.4 2002/01/29 17:17:55 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.3 2002/01/29 02:13:17 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.2 2001/11/26 09:16:14 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:25:57 mcr -+ * lifetime structure created and common functions created. -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_mast.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1080 @@ -+/* -+ * IPSEC MAST code. -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_mast_c_version[] = "RCSID $Id$"; -+ -+#define __NO_VERSION__ -+#include -+#include /* for CONFIG_IP_FORWARD */ -+#include -+#include /* printk() */ -+ -+#include "freeswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include /* struct tcphdr */ -+#include /* struct udphdr */ -+#include -+#include -+#include -+#include -+#include -+#undef dev_kfree_skb -+#define dev_kfree_skb(a,b) kfree_skb(a) -+#define PHYSDEV_TYPE -+#include -+#include /* icmp_send() */ -+#include -+#include -+ -+#include -+ -+#include "freeswan/radij.h" -+#include "freeswan/ipsec_life.h" -+#include "freeswan/ipsec_xform.h" -+#include "freeswan/ipsec_eroute.h" -+#include "freeswan/ipsec_encap.h" -+#include "freeswan/ipsec_radij.h" -+#include "freeswan/ipsec_sa.h" -+#include "freeswan/ipsec_tunnel.h" -+#include "freeswan/ipsec_mast.h" -+#include "freeswan/ipsec_ipe4.h" -+#include "freeswan/ipsec_ah.h" -+#include "freeswan/ipsec_esp.h" -+ -+#include -+#include -+ -+#include "freeswan/ipsec_proto.h" -+ -+int ipsec_maxdevice_count = -1; -+ -+DEBUG_NO_STATIC int -+ipsec_mast_open(struct device *dev) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ -+ /* -+ * Can't open until attached. -+ */ -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_open: " -+ "dev = %s, prv->dev = %s\n", -+ dev->name, prv->dev?prv->dev->name:"NONE"); -+ -+ if (prv->dev == NULL) -+ return -ENODEV; -+ -+ MOD_INC_USE_COUNT; -+ return 0; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_mast_close(struct device *dev) -+{ -+ MOD_DEC_USE_COUNT; -+ return 0; -+} -+ -+static inline int ipsec_mast_xmit2(struct sk_buff *skb) -+{ -+ return ip_send(skb); -+} -+ -+enum ipsec_xmit_value -+ipsec_mast_send(struct ipsec_xmit_state*ixs) -+{ -+ /* new route/dst cache code from James Morris */ -+ ixs->skb->dev = ixs->physdev; -+ /*skb_orphan(ixs->skb);*/ -+ if((ixs->error = ip_route_output(&ixs->route, -+ ixs->skb->nh.iph->daddr, -+ ixs->pass ? 0 : ixs->skb->nh.iph->saddr, -+ RT_TOS(ixs->skb->nh.iph->tos), -+ ixs->physdev->iflink /* rgb: should this be 0? */))) { -+ ixs->stats->tx_errors++; -+ KLIPS_PRINT(debug_mast & DB_MAST_XMIT, -+ "klips_debug:ipsec_xmit_send: " -+ "ip_route_output failed with error code %d, rt->u.dst.dev=%s, dropped\n", -+ ixs->error, -+ ixs->route->u.dst.dev->name); -+ return IPSEC_XMIT_ROUTEERR; -+ } -+ if(ixs->dev == ixs->route->u.dst.dev) { -+ ip_rt_put(ixs->route); -+ /* This is recursion, drop it. */ -+ ixs->stats->tx_errors++; -+ KLIPS_PRINT(debug_mast & DB_MAST_XMIT, -+ "klips_debug:ipsec_xmit_send: " -+ "suspect recursion, dev=rt->u.dst.dev=%s, dropped\n", -+ ixs->dev->name); -+ return IPSEC_XMIT_RECURSDETECT; -+ } -+ dst_release(ixs->skb->dst); -+ ixs->skb->dst = &ixs->route->u.dst; -+ ixs->stats->tx_bytes += ixs->skb->len; -+ if(ixs->skb->len < ixs->skb->nh.raw - ixs->skb->data) { -+ ixs->stats->tx_errors++; -+ printk(KERN_WARNING -+ "klips_error:ipsec_xmit_send: " -+ "tried to __skb_pull nh-data=%ld, %d available. This should never happen, please report.\n", -+ (unsigned long)(ixs->skb->nh.raw - ixs->skb->data), -+ ixs->skb->len); -+ return IPSEC_XMIT_PUSHPULLERR; -+ } -+ __skb_pull(ixs->skb, ixs->skb->nh.raw - ixs->skb->data); -+#ifdef SKB_RESET_NFCT -+ nf_conntrack_put(ixs->skb->nfct); -+ ixs->skb->nfct = NULL; -+#ifdef CONFIG_NETFILTER_DEBUG -+ ixs->skb->nf_debug = 0; -+#endif /* CONFIG_NETFILTER_DEBUG */ -+#endif /* SKB_RESET_NFCT */ -+ KLIPS_PRINT(debug_mast & DB_MAST_XMIT, -+ "klips_debug:ipsec_xmit_send: " -+ "...done, calling ip_send() on device:%s\n", -+ ixs->skb->dev ? ixs->skb->dev->name : "NULL"); -+ KLIPS_IP_PRINT(debug_mast & DB_MAST_XMIT, ixs->skb->nh.iph); -+ { -+ int err; -+ -+ err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, ixs->skb, NULL, ixs->route->u.dst.dev, -+ ipsec_mast_xmit2); -+ if(err != NET_XMIT_SUCCESS && err != NET_XMIT_CN) { -+ if(net_ratelimit()) -+ printk(KERN_ERR -+ "klips_error:ipsec_xmit_send: " -+ "ip_send() failed, err=%d\n", -+ -err); -+ ixs->stats->tx_errors++; -+ ixs->stats->tx_aborted_errors++; -+ ixs->skb = NULL; -+ return IPSEC_XMIT_IPSENDFAILURE; -+ } -+ } -+ ixs->stats->tx_packets++; -+ -+ ixs->skb = NULL; -+ -+ return IPSEC_XMIT_OK; -+} -+ -+void -+ipsec_mast_cleanup(struct ipsec_xmit_state*ixs) -+{ -+#if defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) -+ netif_wake_queue(ixs->dev); -+#else /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ -+ ixs->dev->tbusy = 0; -+#endif /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ -+ if(ixs->saved_header) { -+ kfree(ixs->saved_header); -+ } -+ if(ixs->skb) { -+ dev_kfree_skb(ixs->skb, FREE_WRITE); -+ } -+ if(ixs->oskb) { -+ dev_kfree_skb(ixs->oskb, FREE_WRITE); -+ } -+ if (ixs->ips.ips_ident_s.data) { -+ kfree(ixs->ips.ips_ident_s.data); -+ } -+ if (ixs->ips.ips_ident_d.data) { -+ kfree(ixs->ips.ips_ident_d.data); -+ } -+} -+ -+#if 0 -+/* -+ * This function assumes it is being called from dev_queue_xmit() -+ * and that skb is filled properly by that function. -+ */ -+int -+ipsec_mast_start_xmit(struct sk_buff *skb, struct device *dev, IPsecSAref_t SAref) -+{ -+ struct ipsec_xmit_state ixs_mem; -+ struct ipsec_xmit_state *ixs = &ixs_mem; -+ enum ipsec_xmit_value stat = IPSEC_XMIT_OK; -+ -+ /* dev could be a mast device, but should be optional, I think... */ -+ /* SAref is also optional, but one of the two must be present. */ -+ /* I wonder if it could accept no device or saref and guess? */ -+ -+/* ipsec_xmit_sanity_check_dev(ixs); */ -+ -+ ipsec_xmit_sanity_check_skb(ixs); -+ -+ ipsec_xmit_adjust_hard_header(ixs); -+ -+ stat = ipsec_xmit_encap_bundle(ixs); -+ if(stat != IPSEC_XMIT_OK) { -+ /* SA processing failed */ -+ } -+ -+ ipsec_xmit_hard_header_restore(); -+} -+#endif -+ -+DEBUG_NO_STATIC struct net_device_stats * -+ipsec_mast_get_stats(struct device *dev) -+{ -+ return &(((struct ipsecpriv *)(dev->priv))->mystats); -+} -+ -+/* -+ * Revectored calls. -+ * For each of these calls, a field exists in our private structure. -+ */ -+ -+DEBUG_NO_STATIC int -+ipsec_mast_hard_header(struct sk_buff *skb, struct device *dev, -+ unsigned short type, void *daddr, void *saddr, unsigned len) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ struct device *tmp; -+ int ret; -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(skb == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_hard_header: " -+ "no skb...\n"); -+ return -ENODATA; -+ } -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_hard_header: " -+ "no device...\n"); -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_hard_header: " -+ "skb->dev=%s dev=%s.\n", -+ skb->dev ? skb->dev->name : "NULL", -+ dev->name); -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_hard_header: " -+ "no private space associated with dev=%s\n", -+ dev->name ? dev->name : "NULL"); -+ return -ENODEV; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_hard_header: " -+ "no physical device associated with dev=%s\n", -+ dev->name ? dev->name : "NULL"); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ /* check if we have to send a IPv6 packet. It might be a Router -+ Solicitation, where the building of the packet happens in -+ reverse order: -+ 1. ll hdr, -+ 2. IPv6 hdr, -+ 3. ICMPv6 hdr -+ -> skb->nh.raw is still uninitialized when this function is -+ called!! If this is no IPv6 packet, we can print debugging -+ messages, otherwise we skip all debugging messages and just -+ build the ll header */ -+ if(type != ETH_P_IPV6) { -+ /* execute this only, if we don't have to build the -+ header for a IPv6 packet */ -+ if(!prv->hard_header) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_hard_header: " -+ "physical device has been detached, packet dropped 0p%p->0p%p len=%d type=%d dev=%s->NULL ", -+ saddr, -+ daddr, -+ len, -+ type, -+ dev->name); -+ KLIPS_PRINTMORE(debug_mast & DB_MAST_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+#define da ((struct device *)(prv->dev))->dev_addr -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_hard_header: " -+ "Revectored 0p%p->0p%p len=%d type=%d dev=%s->%s dev_addr=%02x:%02x:%02x:%02x:%02x:%02x ", -+ saddr, -+ daddr, -+ len, -+ type, -+ dev->name, -+ prv->dev->name, -+ da[0], da[1], da[2], da[3], da[4], da[5]); -+ KLIPS_PRINTMORE(debug_mast & DB_MAST_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+ } else { -+ KLIPS_PRINT(debug_mast, -+ "klips_debug:ipsec_mast_hard_header: " -+ "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n"); -+ } -+ tmp = skb->dev; -+ skb->dev = prv->dev; -+ ret = prv->hard_header(skb, prv->dev, type, (void *)daddr, (void *)saddr, len); -+ skb->dev = tmp; -+ return ret; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_mast_rebuild_header(struct sk_buff *skb) -+{ -+ struct ipsecpriv *prv = skb->dev->priv; -+ struct device *tmp; -+ int ret; -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(skb->dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_rebuild_header: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_rebuild_header: " -+ "no private space associated with dev=%s", -+ skb->dev->name ? skb->dev->name : "NULL"); -+ return -ENODEV; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_rebuild_header: " -+ "no physical device associated with dev=%s", -+ skb->dev->name ? skb->dev->name : "NULL"); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ if(!prv->rebuild_header) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_rebuild_header: " -+ "physical device has been detached, packet dropped skb->dev=%s->NULL ", -+ skb->dev->name); -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast: " -+ "Revectored rebuild_header dev=%s->%s ", -+ skb->dev->name, prv->dev->name); -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+ tmp = skb->dev; -+ skb->dev = prv->dev; -+ -+ ret = prv->rebuild_header(skb); -+ skb->dev = tmp; -+ return ret; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_mast_set_mac_address(struct device *dev, void *addr) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_set_mac_address: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_set_mac_address: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return -ENODEV; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_set_mac_address: " -+ "no physical device associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ if(!prv->set_mac_address) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_set_mac_address: " -+ "physical device has been detached, cannot set - skb->dev=%s->NULL\n", -+ dev->name); -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_set_mac_address: " -+ "Revectored dev=%s->%s addr=0p%p\n", -+ dev->name, prv->dev->name, addr); -+ return prv->set_mac_address(prv->dev, addr); -+ -+} -+ -+DEBUG_NO_STATIC void -+ipsec_mast_cache_update(struct hh_cache *hh, struct device *dev, unsigned char * haddr) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_cache_update: " -+ "no device..."); -+ return; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_cache_update: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_cache_update: " -+ "no physical device associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ stats->tx_dropped++; -+ return; -+ } -+ -+ if(!prv->header_cache_update) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_cache_update: " -+ "physical device has been detached, cannot set - skb->dev=%s->NULL\n", -+ dev->name); -+ return; -+ } -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast: " -+ "Revectored cache_update\n"); -+ prv->header_cache_update(hh, prv->dev, haddr); -+ return; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_mast_neigh_setup(struct neighbour *n) -+{ -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_neigh_setup:\n"); -+ -+ if (n->nud_state == NUD_NONE) { -+ n->ops = &arp_broken_ops; -+ n->output = n->ops->output; -+ } -+ return 0; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_mast_neigh_setup_dev(struct device *dev, struct neigh_parms *p) -+{ -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_neigh_setup_dev: " -+ "setting up %s\n", -+ dev ? dev->name : "NULL"); -+ -+ if (p->tbl->family == AF_INET) { -+ p->neigh_setup = ipsec_mast_neigh_setup; -+ p->ucast_probes = 0; -+ p->mcast_probes = 0; -+ } -+ return 0; -+} -+ -+/* -+ * We call the attach routine to attach another device. -+ */ -+ -+DEBUG_NO_STATIC int -+ipsec_mast_attach(struct device *dev, struct device *physdev) -+{ -+ int i; -+ struct ipsecpriv *prv = dev->priv; -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_attach: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_attach: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return -ENODATA; -+ } -+ -+ prv->dev = physdev; -+ prv->hard_start_xmit = physdev->hard_start_xmit; -+ prv->get_stats = physdev->get_stats; -+ -+ if (physdev->hard_header) { -+ prv->hard_header = physdev->hard_header; -+ dev->hard_header = ipsec_mast_hard_header; -+ } else -+ dev->hard_header = NULL; -+ -+ if (physdev->rebuild_header) { -+ prv->rebuild_header = physdev->rebuild_header; -+ dev->rebuild_header = ipsec_mast_rebuild_header; -+ } else -+ dev->rebuild_header = NULL; -+ -+ if (physdev->set_mac_address) { -+ prv->set_mac_address = physdev->set_mac_address; -+ dev->set_mac_address = ipsec_mast_set_mac_address; -+ } else -+ dev->set_mac_address = NULL; -+ -+ if (physdev->header_cache_update) { -+ prv->header_cache_update = physdev->header_cache_update; -+ dev->header_cache_update = ipsec_mast_cache_update; -+ } else -+ dev->header_cache_update = NULL; -+ -+ dev->hard_header_len = physdev->hard_header_len; -+ -+/* prv->neigh_setup = physdev->neigh_setup; */ -+ dev->neigh_setup = ipsec_mast_neigh_setup_dev; -+ dev->mtu = 16260; /* 0xfff0; */ /* dev->mtu; */ -+ prv->mtu = physdev->mtu; -+ -+#ifdef PHYSDEV_TYPE -+ dev->type = physdev->type; /* ARPHRD_MAST; */ -+#endif /* PHYSDEV_TYPE */ -+ -+ dev->addr_len = physdev->addr_len; -+ for (i=0; iaddr_len; i++) { -+ dev->dev_addr[i] = physdev->dev_addr[i]; -+ } -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_mast & DB_MAST_INIT) { -+ printk(KERN_INFO "klips_debug:ipsec_mast_attach: " -+ "physical device %s being attached has HW address: %2x", -+ physdev->name, physdev->dev_addr[0]); -+ for (i=1; i < physdev->addr_len; i++) { -+ printk(":%02x", physdev->dev_addr[i]); -+ } -+ printk("\n"); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ return 0; -+} -+ -+/* -+ * We call the detach routine to detach the ipsec mast from another device. -+ */ -+ -+DEBUG_NO_STATIC int -+ipsec_mast_detach(struct device *dev) -+{ -+ int i; -+ struct ipsecpriv *prv = dev->priv; -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_detach: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_REVEC, -+ "klips_debug:ipsec_mast_detach: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return -ENODATA; -+ } -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_detach: " -+ "physical device %s being detached from virtual device %s\n", -+ prv->dev ? prv->dev->name : "NULL", -+ dev->name); -+ -+ prv->dev = NULL; -+ prv->hard_start_xmit = NULL; -+ prv->get_stats = NULL; -+ -+ prv->hard_header = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->hard_header = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+ prv->rebuild_header = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->rebuild_header = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+ prv->set_mac_address = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->set_mac_address = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+ prv->header_cache_update = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->header_cache_update = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+#ifdef DETACH_AND_DOWN -+ dev->neigh_setup = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+ dev->hard_header_len = 0; -+#ifdef DETACH_AND_DOWN -+ dev->mtu = 0; -+#endif /* DETACH_AND_DOWN */ -+ prv->mtu = 0; -+ for (i=0; idev_addr[i] = 0; -+ } -+ dev->addr_len = 0; -+#ifdef PHYSDEV_TYPE -+ dev->type = ARPHRD_VOID; /* ARPHRD_MAST; */ -+#endif /* PHYSDEV_TYPE */ -+ -+ return 0; -+} -+ -+/* -+ * We call the clear routine to detach all ipsec masts from other devices. -+ */ -+DEBUG_NO_STATIC int -+ipsec_mast_clear(void) -+{ -+ int i; -+ struct device *ipsecdev = NULL, *prvdev; -+ struct ipsecpriv *prv; -+ char name[9]; -+ int ret; -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_clear: .\n"); -+ -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ sprintf(name, IPSEC_DEV_FORMAT, i); -+ if((ipsecdev = ipsec_dev_get(name)) != NULL) { -+ if((prv = (struct ipsecpriv *)(ipsecdev->priv))) { -+ prvdev = (struct device *)(prv->dev); -+ if(prvdev) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_clear: " -+ "physical device for device %s is %s\n", -+ name, prvdev->name); -+ if((ret = ipsec_mast_detach(ipsecdev))) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_clear: " -+ "error %d detatching device %s from device %s.\n", -+ ret, name, prvdev->name); -+ return ret; -+ } -+ } -+ } -+ } -+ } -+ return 0; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_mast_ioctl(struct device *dev, struct ifreq *ifr, int cmd) -+{ -+ struct ipsecmastconf *cf = (struct ipsecmastconf *)&ifr->ifr_data; -+ struct ipsecpriv *prv = dev->priv; -+ struct device *them; /* physical device */ -+#ifdef CONFIG_IP_ALIAS -+ char *colon; -+ char realphysname[IFNAMSIZ]; -+#endif /* CONFIG_IP_ALIAS */ -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "device not supplied.\n"); -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "tncfg service call #%d for dev=%s\n", -+ cmd, -+ dev->name ? dev->name : "NULL"); -+ switch (cmd) { -+ /* attach a virtual ipsec? device to a physical device */ -+ case IPSEC_SET_DEV: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "calling ipsec_mast_attatch...\n"); -+#ifdef CONFIG_IP_ALIAS -+ /* If this is an IP alias interface, get its real physical name */ -+ strncpy(realphysname, cf->cf_name, IFNAMSIZ); -+ realphysname[IFNAMSIZ-1] = 0; -+ colon = strchr(realphysname, ':'); -+ if (colon) *colon = 0; -+ them = ipsec_dev_get(realphysname); -+#else /* CONFIG_IP_ALIAS */ -+ them = ipsec_dev_get(cf->cf_name); -+#endif /* CONFIG_IP_ALIAS */ -+ -+ if (them == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "physical device %s requested is null\n", -+ cf->cf_name); -+ return -ENXIO; -+ } -+ -+#if 0 -+ if (them->flags & IFF_UP) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "physical device %s requested is not up.\n", -+ cf->cf_name); -+ return -ENXIO; -+ } -+#endif -+ -+ if (prv && prv->dev) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "virtual device is already connected to %s.\n", -+ prv->dev->name ? prv->dev->name : "NULL"); -+ return -EBUSY; -+ } -+ return ipsec_mast_attach(dev, them); -+ -+ case IPSEC_DEL_DEV: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "calling ipsec_mast_detatch.\n"); -+ if (! prv->dev) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "physical device not connected.\n"); -+ return -ENODEV; -+ } -+ return ipsec_mast_detach(dev); -+ -+ case IPSEC_CLR_DEV: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "calling ipsec_mast_clear.\n"); -+ return ipsec_mast_clear(); -+ -+ default: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_ioctl: " -+ "unknown command %d.\n", -+ cmd); -+ return -EOPNOTSUPP; -+ } -+} -+ -+int -+ipsec_mast_device_event(struct notifier_block *unused, unsigned long event, void *ptr) -+{ -+ struct device *dev = ptr; -+ struct device *ipsec_dev; -+ struct ipsecpriv *priv; -+ char name[9]; -+ int i; -+ -+ if (dev == NULL) { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "dev=NULL for event type %ld.\n", -+ event); -+ return(NOTIFY_DONE); -+ } -+ -+ /* check for loopback devices */ -+ if (dev && (dev->flags & IFF_LOOPBACK)) { -+ return(NOTIFY_DONE); -+ } -+ -+ switch (event) { -+ case NETDEV_DOWN: -+ /* look very carefully at the scope of these compiler -+ directives before changing anything... -- RGB */ -+ -+ case NETDEV_UNREGISTER: -+ switch (event) { -+ case NETDEV_DOWN: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_DOWN dev=%s flags=%x\n", -+ dev->name, -+ dev->flags); -+ if(strncmp(dev->name, "ipsec", strlen("ipsec")) == 0) { -+ printk(KERN_CRIT "IPSEC EVENT: KLIPS device %s shut down.\n", -+ dev->name); -+ } -+ break; -+ case NETDEV_UNREGISTER: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_UNREGISTER dev=%s flags=%x\n", -+ dev->name, -+ dev->flags); -+ break; -+ } -+ -+ /* find the attached physical device and detach it. */ -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ sprintf(name, IPSEC_DEV_FORMAT, i); -+ ipsec_dev = ipsec_dev_get(name); -+ if(ipsec_dev) { -+ priv = (struct ipsecpriv *)(ipsec_dev->priv); -+ if(priv) { -+ ; -+ if(((struct device *)(priv->dev)) == dev) { -+ /* dev_close(ipsec_dev); */ -+ /* return */ ipsec_mast_detach(ipsec_dev); -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "device '%s' has been detached.\n", -+ ipsec_dev->name); -+ break; -+ } -+ } else { -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "device '%s' has no private data space!\n", -+ ipsec_dev->name); -+ } -+ } -+ } -+ break; -+ case NETDEV_UP: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_UP dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_REBOOT: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_REBOOT dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_CHANGE: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_CHANGE dev=%s flags=%x\n", -+ dev->name, -+ dev->flags); -+ break; -+ case NETDEV_REGISTER: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_REGISTER dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_CHANGEMTU: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_CHANGEMTU dev=%s to mtu=%d\n", -+ dev->name, -+ dev->mtu); -+ break; -+ case NETDEV_CHANGEADDR: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_CHANGEADDR dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_GOING_DOWN: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_GOING_DOWN dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_CHANGENAME: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "NETDEV_CHANGENAME dev=%s\n", -+ dev->name); -+ break; -+ default: -+ KLIPS_PRINT(debug_mast & DB_MAST_INIT, -+ "klips_debug:ipsec_mast_device_event: " -+ "event type %ld unrecognised for dev=%s\n", -+ event, -+ dev->name); -+ break; -+ } -+ return NOTIFY_DONE; -+} -+ -+/* -+ * Called when an ipsec mast device is initialized. -+ * The ipsec mast device structure is passed to us. -+ */ -+ -+int -+ipsec_mast_init(struct device *dev) -+{ -+ int i; -+ -+ KLIPS_PRINT(debug_mast, -+ "klips_debug:ipsec_mast_init: " -+ "allocating %lu bytes initialising device: %s\n", -+ (unsigned long) sizeof(struct ipsecpriv), -+ dev->name ? dev->name : "NULL"); -+ -+ /* Add our mast functions to the device */ -+ dev->open = ipsec_mast_open; -+ dev->stop = ipsec_mast_close; -+ dev->hard_start_xmit = ipsec_mast_start_xmit; -+ dev->get_stats = ipsec_mast_get_stats; -+ -+ dev->priv = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL); -+ if (dev->priv == NULL) -+ return -ENOMEM; -+ memset((caddr_t)(dev->priv), 0, sizeof(struct ipsecpriv)); -+ -+ for(i = 0; i < sizeof(zeroes); i++) { -+ ((__u8*)(zeroes))[i] = 0; -+ } -+ -+ dev->set_multicast_list = NULL; -+ dev->do_ioctl = ipsec_mast_ioctl; -+ dev->hard_header = NULL; -+ dev->rebuild_header = NULL; -+ dev->set_mac_address = NULL; -+ dev->header_cache_update= NULL; -+ dev->neigh_setup = ipsec_mast_neigh_setup_dev; -+ dev->hard_header_len = 0; -+ dev->mtu = 0; -+ dev->addr_len = 0; -+ dev->type = ARPHRD_VOID; /* ARPHRD_MAST; */ /* ARPHRD_ETHER; */ -+ dev->tx_queue_len = 10; /* Small queue */ -+ memset((caddr_t)(dev->broadcast),0xFF, ETH_ALEN); /* what if this is not attached to ethernet? */ -+ -+ /* New-style flags. */ -+ dev->flags = IFF_NOARP /* 0 */ /* Petr Novak */; -+ dev_init_buffers(dev); -+ -+ /* We're done. Have I forgotten anything? */ -+ return 0; -+} -+ -+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -+/* Module specific interface (but it links with the rest of IPSEC) */ -+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -+ -+int -+ipsec_mast_probe(struct device *dev) -+{ -+ ipsec_mast_init(dev); -+ return 0; -+} -+ -+int -+ipsec_mast_init_devices(void) -+{ -+ return 0; -+} -+ -+/* void */ -+int -+ipsec_mast_cleanup_devices(void) -+{ -+ int error = 0; -+ int i; -+ char name[10]; -+ struct device *dev_mast; -+ -+ for(i = 0; i < ipsec_mastdevice_count; i++) { -+ sprintf(name, MAST_DEV_FORMAT, i); -+ if((dev_mast = ipsec_dev_get(name)) == NULL) { -+ break; -+ } -+ unregister_netdev(dev_mast); -+ kfree(dev_mast->priv); -+ dev_mast->priv=NULL; -+ } -+ return error; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.3 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.2.4.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.2 2003/06/22 20:06:17 mcr -+ * refactored mast code still had lots of ipsecX junk in it. -+ * -+ * Revision 1.1 2003/02/12 19:31:12 rgb -+ * Refactored from ipsec_tunnel.c -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_md5c.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,448 @@ -+/* -+ * RCSID $Id$ -+ */ -+ -+/* -+ * The rest of the code is derived from MD5C.C by RSADSI. Minor cosmetic -+ * changes to accomodate it in the kernel by ji. -+ */ -+ -+#include -+#include -+ -+#include "openswan/ipsec_md5h.h" -+ -+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm -+ */ -+ -+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -+rights reserved. -+ -+License to copy and use this software is granted provided that it -+is identified as the "RSA Data Security, Inc. MD5 Message-Digest -+Algorithm" in all material mentioning or referencing this software -+or this function. -+ -+License is also granted to make and use derivative works provided -+that such works are identified as "derived from the RSA Data -+Security, Inc. MD5 Message-Digest Algorithm" in all material -+mentioning or referencing the derived work. -+ -+RSA Data Security, Inc. makes no representations concerning either -+the merchantability of this software or the suitability of this -+software for any particular purpose. It is provided "as is" -+without express or implied warranty of any kind. -+ -+These notices must be retained in any copies of any part of this -+documentation and/or software. -+ */ -+ -+/* -+ * Additions by JI -+ * -+ * HAVEMEMCOPY is defined if mem* routines are available -+ * -+ * HAVEHTON is defined if htons() and htonl() can be used -+ * for big/little endian conversions -+ * -+ */ -+ -+#define HAVEMEMCOPY -+#ifdef __LITTLE_ENDIAN -+#define LITTLENDIAN -+#endif -+#ifdef __BIG_ENDIAN -+#define BIGENDIAN -+#endif -+ -+/* Constants for MD5Transform routine. -+ */ -+ -+#define S11 7 -+#define S12 12 -+#define S13 17 -+#define S14 22 -+#define S21 5 -+#define S22 9 -+#define S23 14 -+#define S24 20 -+#define S31 4 -+#define S32 11 -+#define S33 16 -+#define S34 23 -+#define S41 6 -+#define S42 10 -+#define S43 15 -+#define S44 21 -+ -+static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); -+ -+#ifdef LITTLEENDIAN -+#define Encode MD5_memcpy -+#define Decode MD5_memcpy -+#else -+static void Encode PROTO_LIST -+ ((unsigned char *, UINT4 *, unsigned int)); -+static void Decode PROTO_LIST -+ ((UINT4 *, unsigned char *, unsigned int)); -+#endif -+ -+#ifdef HAVEMEMCOPY -+/* no need to include here; defines these */ -+#define MD5_memcpy memcpy -+#define MD5_memset memset -+#else -+#ifdef HAVEBCOPY -+#define MD5_memcpy(_a,_b,_c) bcopy((_b),(_a),(_c)) -+#define MD5_memset(_a,_b,_c) bzero((_a),(_c)) -+#else -+static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); -+static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); -+#endif -+#endif -+static unsigned char PADDING[64] = { -+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -+}; -+ -+/* F, G, H and I are basic MD5 functions. -+ */ -+#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -+#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) -+#define H(x, y, z) ((x) ^ (y) ^ (z)) -+#define I(x, y, z) ((y) ^ ((x) | (~z))) -+ -+/* ROTATE_LEFT rotates x left n bits. -+ */ -+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) -+ -+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. -+Rotation is separate from addition to prevent recomputation. -+ */ -+#define FF(a, b, c, d, x, s, ac) { \ -+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ -+ (a) = ROTATE_LEFT ((a), (s)); \ -+ (a) += (b); \ -+ } -+#define GG(a, b, c, d, x, s, ac) { \ -+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ -+ (a) = ROTATE_LEFT ((a), (s)); \ -+ (a) += (b); \ -+ } -+#define HH(a, b, c, d, x, s, ac) { \ -+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ -+ (a) = ROTATE_LEFT ((a), (s)); \ -+ (a) += (b); \ -+ } -+#define II(a, b, c, d, x, s, ac) { \ -+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ -+ (a) = ROTATE_LEFT ((a), (s)); \ -+ (a) += (b); \ -+ } -+ -+/* -+ * MD5 initialization. Begins an MD5 operation, writing a new context. -+ */ -+void MD5Init(void *vcontext) -+{ -+ MD5_CTX *context = vcontext; -+ -+ context->count[0] = context->count[1] = 0; -+ /* Load magic initialization constants. -+*/ -+ context->state[0] = 0x67452301; -+ context->state[1] = 0xefcdab89; -+ context->state[2] = 0x98badcfe; -+ context->state[3] = 0x10325476; -+} -+ -+/* MD5 block update operation. Continues an MD5 message-digest -+ operation, processing another message block, and updating the -+ context. -+ */ -+void MD5Update (vcontext, input, inputLen) -+ void *vcontext; -+ unsigned char *input; /* input block */ -+ __u32 inputLen; /* length of input block */ -+{ -+ MD5_CTX *context = vcontext; -+ __u32 i; -+ unsigned int index, partLen; -+ -+ /* Compute number of bytes mod 64 */ -+ index = (unsigned int)((context->count[0] >> 3) & 0x3F); -+ -+ /* Update number of bits */ -+ if ((context->count[0] += ((UINT4)inputLen << 3)) -+ < ((UINT4)inputLen << 3)) -+ context->count[1]++; -+ context->count[1] += ((UINT4)inputLen >> 29); -+ -+ partLen = 64 - index; -+ -+ /* Transform as many times as possible. -+*/ -+ if (inputLen >= partLen) { -+ MD5_memcpy -+ ((POINTER)&context->buffer[index], (POINTER)input, partLen); -+ MD5Transform (context->state, context->buffer); -+ -+ for (i = partLen; i + 63 < inputLen; i += 64) -+ MD5Transform (context->state, &input[i]); -+ -+ index = 0; -+ } -+ else -+ i = 0; -+ -+ /* Buffer remaining input */ -+ MD5_memcpy -+ ((POINTER)&context->buffer[index], (POINTER)&input[i], -+ inputLen-i); -+} -+ -+/* MD5 finalization. Ends an MD5 message-digest operation, writing the -+ the message digest and zeroizing the context. -+ */ -+void MD5Final (digest, vcontext) -+unsigned char digest[16]; /* message digest */ -+void *vcontext; /* context */ -+{ -+ MD5_CTX *context = vcontext; -+ unsigned char bits[8]; -+ unsigned int index, padLen; -+ -+ /* Save number of bits */ -+ Encode (bits, context->count, 8); -+ -+ /* Pad out to 56 mod 64. -+*/ -+ index = (unsigned int)((context->count[0] >> 3) & 0x3f); -+ padLen = (index < 56) ? (56 - index) : (120 - index); -+ MD5Update (context, PADDING, padLen); -+ -+ /* Append length (before padding) */ -+ MD5Update (context, bits, 8); -+ -+ if (digest != NULL) /* Bill Simpson's padding */ -+ { -+ /* store state in digest */ -+ Encode (digest, context->state, 16); -+ -+ /* Zeroize sensitive information. -+ */ -+ MD5_memset ((POINTER)context, 0, sizeof (*context)); -+ } -+} -+ -+/* MD5 basic transformation. Transforms state based on block. -+ */ -+static void MD5Transform (state, block) -+UINT4 state[4]; -+unsigned char block[64]; -+{ -+ UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; -+ -+ Decode (x, block, 64); -+ -+ /* Round 1 */ -+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ -+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ -+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ -+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ -+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ -+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ -+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ -+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ -+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ -+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ -+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ -+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ -+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ -+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ -+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ -+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ -+ -+ /* Round 2 */ -+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ -+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ -+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ -+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ -+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ -+ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ -+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ -+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ -+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ -+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ -+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ -+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ -+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ -+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ -+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ -+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ -+ -+ /* Round 3 */ -+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ -+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ -+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ -+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ -+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ -+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ -+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ -+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ -+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ -+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ -+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ -+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ -+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ -+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ -+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ -+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ -+ -+ /* Round 4 */ -+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ -+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ -+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ -+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ -+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ -+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ -+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ -+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ -+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ -+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ -+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ -+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ -+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ -+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ -+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ -+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ -+ -+ state[0] += a; -+ state[1] += b; -+ state[2] += c; -+ state[3] += d; -+ -+ /* Zeroize sensitive information. -+*/ -+ MD5_memset ((POINTER)x, 0, sizeof (x)); -+} -+ -+#ifndef LITTLEENDIAN -+ -+/* Encodes input (UINT4) into output (unsigned char). Assumes len is -+ a multiple of 4. -+ */ -+static void Encode (output, input, len) -+unsigned char *output; -+UINT4 *input; -+unsigned int len; -+{ -+ unsigned int i, j; -+ -+ for (i = 0, j = 0; j < len; i++, j += 4) { -+ output[j] = (unsigned char)(input[i] & 0xff); -+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); -+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); -+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); -+ } -+} -+ -+/* Decodes input (unsigned char) into output (UINT4). Assumes len is -+ a multiple of 4. -+ */ -+static void Decode (output, input, len) -+UINT4 *output; -+unsigned char *input; -+unsigned int len; -+{ -+ unsigned int i, j; -+ -+ for (i = 0, j = 0; j < len; i++, j += 4) -+ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | -+ (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); -+} -+ -+#endif -+ -+#ifndef HAVEMEMCOPY -+#ifndef HAVEBCOPY -+/* Note: Replace "for loop" with standard memcpy if possible. -+ */ -+ -+static void MD5_memcpy (output, input, len) -+POINTER output; -+POINTER input; -+unsigned int len; -+{ -+ unsigned int i; -+ -+ for (i = 0; i < len; i++) -+ -+ output[i] = input[i]; -+} -+ -+/* Note: Replace "for loop" with standard memset if possible. -+ */ -+ -+static void MD5_memset (output, value, len) -+POINTER output; -+int value; -+unsigned int len; -+{ -+ unsigned int i; -+ -+ for (i = 0; i < len; i++) -+ ((char *)output)[i] = (char)value; -+} -+#endif -+#endif -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.8 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.7 2002/09/10 01:45:14 mcr -+ * changed type of MD5_CTX and SHA1_CTX to void * so that -+ * the function prototypes would match, and could be placed -+ * into a pointer to a function. -+ * -+ * Revision 1.6 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.5 2002/04/24 07:36:28 mcr -+ * Moved from ./klips/net/ipsec/ipsec_md5c.c,v -+ * -+ * Revision 1.4 1999/12/13 13:59:12 rgb -+ * Quick fix to argument size to Update bugs. -+ * -+ * Revision 1.3 1999/05/21 18:09:28 henry -+ * unnecessary include causes trouble in 2.2 -+ * -+ * Revision 1.2 1999/04/06 04:54:26 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.1 1998/06/18 21:27:48 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.2 1998/04/23 20:54:02 rgb -+ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when -+ * verified. -+ * -+ * Revision 1.1 1998/04/09 03:06:08 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:04 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.3 1996/11/20 14:48:53 ji -+ * Release update only. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_proc.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1127 @@ -+/* -+ * @(#) /proc file system interface code. -+ * -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs -+ * 2001 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * Split out from ipsec_init.c version 1.70. -+ */ -+ -+char ipsec_proc_c_version[] = "RCSID $Id$"; -+ -+ -+#include -+#include -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include /* struct sockaddr_in */ -+#include -+#include -+#ifdef SPINLOCK -+#ifdef SPINLOCK_23 -+#include /* *lock* */ -+#else /* SPINLOCK_23 */ -+#include /* *lock* */ -+#endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+#include -+#include -+#endif /* NET_21 */ -+#include -+#include -+#ifdef CONFIG_PROC_FS -+#include -+#endif /* CONFIG_PROC_FS */ -+#ifdef NETLINK_SOCK -+#include -+#else -+#include -+#endif -+ -+#include "openswan/radij.h" -+ -+#include "openswan/ipsec_life.h" -+#include "openswan/ipsec_stats.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_xmit.h" -+ -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+#include "openswan/ipcomp.h" -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#include "openswan/ipsec_proto.h" -+ -+#include -+#include -+ -+#ifdef CONFIG_PROC_FS -+ -+#ifdef IPSEC_PROC_SUBDIRS -+static struct proc_dir_entry *proc_net_ipsec_dir = NULL; -+static struct proc_dir_entry *proc_eroute_dir = NULL; -+static struct proc_dir_entry *proc_spi_dir = NULL; -+static struct proc_dir_entry *proc_spigrp_dir = NULL; -+static struct proc_dir_entry *proc_birth_dir = NULL; -+static struct proc_dir_entry *proc_stats_dir = NULL; -+#endif -+ -+struct ipsec_birth_reply ipsec_ipv4_birth_packet; -+struct ipsec_birth_reply ipsec_ipv6_birth_packet; -+ -+#define DECREMENT_UNSIGNED(X, amount) ((amount < (X)) ? (X)-amount : 0) -+ -+extern int ipsec_xform_get_info(char *buffer, char **start, -+ off_t offset, int length IPSEC_PROC_LAST_ARG); -+ -+ -+/* ipsec_snprintf: like snprintf except -+ * - size is signed and a negative value is treated as if it were 0 -+ * - the returned result is never negative -- -+ * an error generates a "?" or null output (depending on space). -+ * (Our callers are too lazy to check for an error return.) -+ * -+ * @param buf String buffer -+ * @param size Size of the string -+ * @param fmt printf string -+ * @param ... Variables to be displayed in fmt -+ * @return int Return code -+ */ -+int ipsec_snprintf(char *buf, ssize_t size, const char *fmt, ...) -+{ -+ va_list args; -+ int i; -+ size_t possize = size < 0? 0 : size; -+ va_start(args, fmt); -+ i = vsnprintf(buf,possize,fmt,args); -+ va_end(args); -+ if (i < 0) { -+ /* create empty output in place of error */ -+ i = 0; -+ if (size > 0) { -+ *buf = '\0'; -+ } -+ } -+ return i; -+} -+ -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_eroute_get_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length IPSEC_PROC_LAST_ARG) -+{ -+ struct wsbuf w = {buffer, length, offset, 0, 0}; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_radij & DB_RJ_DUMPTREES) -+ rj_dumptrees(); /* XXXXXXXXX */ -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_eroute_get_info: " -+ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", -+ buffer, -+ *start, -+ (int)offset, -+ length); -+ -+ spin_lock_bh(&eroute_lock); -+ -+ rj_walktree(rnh, ipsec_rj_walker_procprint, &w); -+/* rj_walktree(mask_rjhead, ipsec_rj_walker_procprint, &w); */ -+ -+ spin_unlock_bh(&eroute_lock); -+ -+ *start = buffer + (offset - w.begin); /* Start of wanted data */ -+ return w.len - (offset - w.begin); -+} -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_spi_get_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length IPSEC_PROC_LAST_ARG) -+{ -+ const int max_content = length > 0? length-1 : 0; -+ int len = 0; -+ off_t begin = 0; -+ int i; -+ struct ipsec_sa *sa_p; -+ char sa[SATOT_BUF]; -+ char buf_s[SUBNETTOA_BUF]; -+ char buf_d[SUBNETTOA_BUF]; -+ size_t sa_len; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_spi_get_info: " -+ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", -+ buffer, -+ *start, -+ (int)offset, -+ length); -+ -+ spin_lock_bh(&tdb_lock); -+ -+ for (i = 0; i < SADB_HASHMOD; i++) { -+ for (sa_p = ipsec_sadb_hash[i]; -+ sa_p; -+ sa_p = sa_p->ips_hnext) { -+ atomic_inc(&sa_p->ips_refcount); -+ sa_len = satot(&sa_p->ips_said, 'x', sa, sizeof(sa)); -+ len += ipsec_snprintf(buffer+len, length-len, "%s ", -+ sa_len ? sa : " (error)"); -+ -+ len += ipsec_snprintf(buffer+len, length-len, "%s%s%s", -+ IPS_XFORM_NAME(sa_p)); -+ -+ len += ipsec_snprintf(buffer+len, length-len, ": dir=%s", -+ (sa_p->ips_flags & EMT_INBOUND) ? -+ "in " : "out"); -+ -+ if(sa_p->ips_addr_s) { -+ addrtoa(((struct sockaddr_in*)(sa_p->ips_addr_s))->sin_addr, -+ 0, buf_s, sizeof(buf_s)); -+ len += ipsec_snprintf(buffer+len, length-len, " src=%s", -+ buf_s); -+ } -+ -+ if((sa_p->ips_said.proto == IPPROTO_IPIP) -+ && (sa_p->ips_flags & SADB_X_SAFLAGS_INFLOW)) { -+ subnettoa(sa_p->ips_flow_s.u.v4.sin_addr, -+ sa_p->ips_mask_s.u.v4.sin_addr, -+ 0, -+ buf_s, -+ sizeof(buf_s)); -+ -+ subnettoa(sa_p->ips_flow_d.u.v4.sin_addr, -+ sa_p->ips_mask_d.u.v4.sin_addr, -+ 0, -+ buf_d, -+ sizeof(buf_d)); -+ -+ len += ipsec_snprintf(buffer+len, length-len, " policy=%s->%s", -+ buf_s, buf_d); -+ } -+ -+ if(sa_p->ips_iv_bits) { -+ int j; -+ len += ipsec_snprintf(buffer+len, length-len, " iv_bits=%dbits iv=0x", -+ sa_p->ips_iv_bits); -+ -+ for(j = 0; j < sa_p->ips_iv_bits / 8; j++) { -+ len += ipsec_snprintf(buffer+len, length-len, "%02x", -+ (__u32)((__u8*)(sa_p->ips_iv))[j]); -+ } -+ } -+ -+ if(sa_p->ips_encalg || sa_p->ips_authalg) { -+ if(sa_p->ips_replaywin) { -+ len += ipsec_snprintf(buffer+len, length-len, " ooowin=%d", -+ sa_p->ips_replaywin); -+ } -+ if(sa_p->ips_errs.ips_replaywin_errs) { -+ len += ipsec_snprintf(buffer+len, length-len, " ooo_errs=%d", -+ sa_p->ips_errs.ips_replaywin_errs); -+ } -+ if(sa_p->ips_replaywin_lastseq) { -+ len += ipsec_snprintf(buffer+len, length-len, " seq=%d", -+ sa_p->ips_replaywin_lastseq); -+ } -+ if(sa_p->ips_replaywin_bitmap) { -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) -+ len += ipsec_snprintf(buffer+len, length-len, " bit=0x%Lx", -+ sa_p->ips_replaywin_bitmap); -+#else -+ len += ipsec_snprintf(buffer+len, length-len, " bit=0x%x%08x", -+ (__u32)(sa_p->ips_replaywin_bitmap >> 32), -+ (__u32)sa_p->ips_replaywin_bitmap); -+#endif -+ } -+ if(sa_p->ips_replaywin_maxdiff) { -+ len += ipsec_snprintf(buffer+len, length-len, " max_seq_diff=%d", -+ sa_p->ips_replaywin_maxdiff); -+ } -+ } -+ if(sa_p->ips_flags & ~EMT_INBOUND) { -+ len += ipsec_snprintf(buffer+len, length-len, " flags=0x%x", -+ sa_p->ips_flags & ~EMT_INBOUND); -+ len += ipsec_snprintf(buffer+len, length-len, "<"); -+ /* flag printing goes here */ -+ len += ipsec_snprintf(buffer+len, length-len, ">"); -+ } -+ if(sa_p->ips_auth_bits) { -+ len += ipsec_snprintf(buffer+len, length-len, " alen=%d", -+ sa_p->ips_auth_bits); -+ } -+ if(sa_p->ips_key_bits_a) { -+ len += ipsec_snprintf(buffer+len, length-len, " aklen=%d", -+ sa_p->ips_key_bits_a); -+ } -+ if(sa_p->ips_errs.ips_auth_errs) { -+ len += ipsec_snprintf(buffer+len, length-len, " auth_errs=%d", -+ sa_p->ips_errs.ips_auth_errs); -+ } -+ if(sa_p->ips_key_bits_e) { -+ len += ipsec_snprintf(buffer+len, length-len, " eklen=%d", -+ sa_p->ips_key_bits_e); -+ } -+ if(sa_p->ips_errs.ips_encsize_errs) { -+ len += ipsec_snprintf(buffer+len, length-len, " encr_size_errs=%d", -+ sa_p->ips_errs.ips_encsize_errs); -+ } -+ if(sa_p->ips_errs.ips_encpad_errs) { -+ len += ipsec_snprintf(buffer+len, length-len, " encr_pad_errs=%d", -+ sa_p->ips_errs.ips_encpad_errs); -+ } -+ -+ len += ipsec_snprintf(buffer+len, length-len, " life(c,s,h)="); -+ -+ len += ipsec_lifetime_format(buffer + len, -+ length - len, -+ "alloc", -+ ipsec_life_countbased, -+ &sa_p->ips_life.ipl_allocations); -+ -+ len += ipsec_lifetime_format(buffer + len, -+ length - len, -+ "bytes", -+ ipsec_life_countbased, -+ &sa_p->ips_life.ipl_bytes); -+ -+ len += ipsec_lifetime_format(buffer + len, -+ length - len, -+ "addtime", -+ ipsec_life_timebased, -+ &sa_p->ips_life.ipl_addtime); -+ -+ len += ipsec_lifetime_format(buffer + len, -+ length - len, -+ "usetime", -+ ipsec_life_timebased, -+ &sa_p->ips_life.ipl_usetime); -+ -+ len += ipsec_lifetime_format(buffer + len, -+ length - len, -+ "packets", -+ ipsec_life_countbased, -+ &sa_p->ips_life.ipl_packets); -+ -+ if(sa_p->ips_life.ipl_usetime.ipl_last) { /* XXX-MCR should be last? */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) -+ len += ipsec_snprintf(buffer+len, length-len, " idle=%Ld", -+ jiffies / HZ - sa_p->ips_life.ipl_usetime.ipl_last); -+#else -+ len += ipsec_snprintf(buffer+len, length-len, " idle=%lu", -+ jiffies / HZ - (unsigned long)sa_p->ips_life.ipl_usetime.ipl_last); -+#endif -+ } -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+ if(sa_p->ips_said.proto == IPPROTO_COMP && -+ (sa_p->ips_comp_ratio_dbytes || -+ sa_p->ips_comp_ratio_cbytes)) { -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) -+ len += ipsec_snprintf(buffer+len, length-len, " ratio=%Ld:%Ld", -+ sa_p->ips_comp_ratio_dbytes, -+ sa_p->ips_comp_ratio_cbytes); -+#else -+ len += ipsec_snprintf(buffer+len, length-len, " ratio=%lu:%lu", -+ (unsigned long)sa_p->ips_comp_ratio_dbytes, -+ (unsigned long)sa_p->ips_comp_ratio_cbytes); -+#endif -+ } -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if(sa_p->ips_natt_type != 0) { -+ char *natttype_name; -+ -+ switch(sa_p->ips_natt_type) -+ { -+ case ESPINUDP_WITH_NON_IKE: -+ natttype_name="nonike"; -+ break; -+ case ESPINUDP_WITH_NON_ESP: -+ natttype_name="nonesp"; -+ break; -+ default: -+ natttype_name = "unknown"; -+ break; -+ } -+ -+ len += ipsec_snprintf(buffer + len, length-len, " natencap=%s", -+ natttype_name); -+ -+ len += ipsec_snprintf(buffer + len, length-len, " natsport=%d", -+ sa_p->ips_natt_sport); -+ -+ len += ipsec_snprintf(buffer + len,length-len, " natdport=%d", -+ sa_p->ips_natt_dport); -+ } -+#endif /* CONFIG_IPSEC_NAT_TRAVERSAL */ -+ -+ len += ipsec_snprintf(buffer + len,length-len, " refcount=%d", -+ atomic_read(&sa_p->ips_refcount)); -+ -+ len += ipsec_snprintf(buffer+len, length-len, " ref=%d", -+ sa_p->ips_ref); -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_xform) { -+ len += ipsec_snprintf(buffer+len, length-len, " reftable=%lu refentry=%lu", -+ (unsigned long)IPsecSAref2table(sa_p->ips_ref), -+ (unsigned long)IPsecSAref2entry(sa_p->ips_ref)); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ len += ipsec_snprintf(buffer+len, length-len, "\n"); -+ -+ atomic_dec(&sa_p->ips_refcount); -+ -+ if (len >= max_content) { -+ /* we've done all that can fit -- stop loops */ -+ len = max_content; /* truncate crap */ -+ goto done_spi_i; -+ } else { -+ const off_t pos = begin + len; /* file position of end of what we've generated */ -+ -+ if (pos <= offset) { -+ /* all is before first interesting character: -+ * discard, but note where we are. -+ */ -+ len = 0; -+ begin = pos; -+ } -+ } -+ } -+ } -+ -+done_spi_i: -+ spin_unlock_bh(&tdb_lock); -+ -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ return len - (offset - begin); -+} -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_spigrp_get_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length IPSEC_PROC_LAST_ARG) -+{ -+ /* Limit of useful snprintf output */ -+ const int max_content = length > 0? length-1 : 0; -+ -+ int len = 0; -+ off_t begin = 0; -+ int i; -+ struct ipsec_sa *sa_p, *sa_p2; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_spigrp_get_info: " -+ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", -+ buffer, -+ *start, -+ (int)offset, -+ length); -+ -+ spin_lock_bh(&tdb_lock); -+ -+ for (i = 0; i < SADB_HASHMOD; i++) { -+ for (sa_p = ipsec_sadb_hash[i]; -+ sa_p != NULL; -+ sa_p = sa_p->ips_hnext) -+ { -+ atomic_inc(&sa_p->ips_refcount); -+ if(sa_p->ips_inext == NULL) { -+ sa_p2 = sa_p; -+ while(sa_p2 != NULL) { -+ atomic_inc(&sa_p2->ips_refcount); -+ sa_len = satot(&sa_p2->ips_said, -+ 'x', sa, sizeof(sa)); -+ -+ len += ipsec_snprintf(buffer+len, length-len, "%s ", -+ sa_len ? sa : " (error)"); -+ atomic_dec(&sa_p2->ips_refcount); -+ sa_p2 = sa_p2->ips_onext; -+ } -+ len += ipsec_snprintf(buffer+len, length-len, "\n"); -+ } -+ -+ atomic_dec(&sa_p->ips_refcount); -+ -+ if (len >= max_content) { -+ /* we've done all that can fit -- stop loops */ -+ len = max_content; /* truncate crap */ -+ goto done_spigrp_i; -+ } else { -+ const off_t pos = begin + len; -+ -+ if (pos <= offset) { -+ /* all is before first interesting character: -+ * discard, but note where we are. -+ */ -+ len = 0; -+ begin = pos; -+ } -+ } -+ } -+ } -+ -+done_spigrp_i: -+ spin_unlock_bh(&tdb_lock); -+ -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ return len - (offset - begin); -+} -+ -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_tncfg_get_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length IPSEC_PROC_LAST_ARG) -+{ -+ /* limit of useful snprintf output */ -+ const int max_content = length > 0? length-1 : 0; -+ int len = 0; -+ off_t begin = 0; -+ int i; -+ char name[9]; -+ struct device *dev, *privdev; -+ struct ipsecpriv *priv; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_tncfg_get_info: " -+ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", -+ buffer, -+ *start, -+ (int)offset, -+ length); -+ -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ ipsec_snprintf(name, (ssize_t) sizeof(name), IPSEC_DEV_FORMAT, i); -+ dev = __ipsec_dev_get(name); -+ if(dev) { -+ priv = (struct ipsecpriv *)(dev->priv); -+ len += ipsec_snprintf(buffer+len, length-len, "%s", -+ dev->name); -+ if(priv) { -+ privdev = (struct device *)(priv->dev); -+ len += ipsec_snprintf(buffer+len, length-len, " -> %s", -+ privdev ? privdev->name : "NULL"); -+ len += ipsec_snprintf(buffer+len, length-len, " mtu=%d(%d) -> %d", -+ dev->mtu, -+ priv->mtu, -+ privdev ? privdev->mtu : 0); -+ } else { -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_tncfg_get_info: device '%s' has no private data space!\n", -+ dev->name); -+ } -+ len += ipsec_snprintf(buffer+len, length-len, "\n"); -+ -+ if (len >= max_content) { -+ /* we've done all that can fit -- stop loop */ -+ len = max_content; /* truncate crap */ -+ break; -+ } else { -+ const off_t pos = begin + len; -+ if (pos <= offset) { -+ len = 0; -+ begin = pos; -+ } -+ } -+ } -+ } -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ len -= (offset - begin); /* Start slop */ -+ if (len > length) -+ len = length; -+ return len; -+} -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_version_get_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length IPSEC_PROC_LAST_ARG) -+{ -+ int len = 0; -+ off_t begin = 0; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_version_get_info: " -+ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", -+ buffer, -+ *start, -+ (int)offset, -+ length); -+ -+ len += ipsec_snprintf(buffer + len,length-len, "Openswan version: %s\n", -+ ipsec_version_code()); -+#if 0 -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_version_get_info: " -+ "ipsec_init version: %s\n", -+ ipsec_init_c_version); -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_version_get_info: " -+ "ipsec_tunnel version: %s\n", -+ ipsec_tunnel_c_version); -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_version_get_info: " -+ "ipsec_netlink version: %s\n", -+ ipsec_netlink_c_version); -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_version_get_info: " -+ "radij_c_version: %s\n", -+ radij_c_version); -+#endif -+ -+ -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ len -= (offset - begin); /* Start slop */ -+ if (len > length) -+ len = length; -+ return len; -+} -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_birth_info(char *page, -+ char **start, -+ off_t offset, -+ int count, -+ int *eof, -+ void *data) -+{ -+ struct ipsec_birth_reply *ibr = (struct ipsec_birth_reply *)data; -+ int len; -+ -+ if(offset >= ibr->packet_template_len) { -+ if(eof) { -+ *eof=1; -+ } -+ return 0; -+ } -+ -+ len = ibr->packet_template_len; -+ len -= offset; -+ if (len > count) -+ len = count; -+ -+ memcpy(page + offset, ibr->packet_template+offset, len); -+ -+ return len; -+} -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_birth_set(struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ struct ipsec_birth_reply *ibr = (struct ipsec_birth_reply *)data; -+ int len; -+ -+ MOD_INC_USE_COUNT; -+ if(count > IPSEC_BIRTH_TEMPLATE_MAXLEN) { -+ len = IPSEC_BIRTH_TEMPLATE_MAXLEN; -+ } else { -+ len = count; -+ } -+ -+ if(copy_from_user(ibr->packet_template, buffer, len)) { -+ MOD_DEC_USE_COUNT; -+ return -EFAULT; -+ } -+ ibr->packet_template_len = len; -+ -+ MOD_DEC_USE_COUNT; -+ -+ return len; -+} -+ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_klipsdebug_get_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length IPSEC_PROC_LAST_ARG) -+{ -+ int len = 0; -+ off_t begin = 0; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, -+ "klips_debug:ipsec_klipsdebug_get_info: " -+ "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", -+ buffer, -+ *start, -+ (int)offset, -+ length); -+ -+ len += ipsec_snprintf(buffer+len, length-len, "debug_tunnel=%08x.\n", debug_tunnel); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_xform=%08x.\n", debug_xform); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_eroute=%08x.\n", debug_eroute); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_spi=%08x.\n", debug_spi); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_radij=%08x.\n", debug_radij); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_esp=%08x.\n", debug_esp); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_ah=%08x.\n", debug_ah); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_rcv=%08x.\n", debug_rcv); -+ len += ipsec_snprintf(buffer+len, length-len, "debug_pfkey=%08x.\n", debug_pfkey); -+ -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ len -= (offset - begin); /* Start slop */ -+ if (len > length) -+ len = length; -+ return len; -+} -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+IPSEC_PROCFS_DEBUG_NO_STATIC -+int -+ipsec_stats_get_int_info(char *buffer, -+ char **start, -+ off_t offset, -+ int length, -+ int *eof, -+ void *data) -+{ -+ -+ const int max_content = length > 0? length-1 : 0; -+ int len = 0; -+ int *thing; -+ -+ thing = (int *)data; -+ -+ len = ipsec_snprintf(buffer+len, length-len, "%08x\n", *thing); -+ -+ if (len >= max_content) -+ len = max_content; /* truncate crap */ -+ -+ *start = buffer + offset; /* Start of wanted data */ -+ return len > offset? len - offset : 0; -+ -+} -+ -+#ifndef PROC_FS_2325 -+struct proc_dir_entry ipsec_eroute = -+{ -+ 0, -+ 12, "ipsec_eroute", -+ S_IFREG | S_IRUGO, 1, 0, 0, 0, -+ &proc_net_inode_operations, -+ ipsec_eroute_get_info, -+ NULL, NULL, NULL, NULL, NULL -+}; -+ -+struct proc_dir_entry ipsec_spi = -+{ -+ 0, -+ 9, "ipsec_spi", -+ S_IFREG | S_IRUGO, 1, 0, 0, 0, -+ &proc_net_inode_operations, -+ ipsec_spi_get_info, -+ NULL, NULL, NULL, NULL, NULL -+}; -+ -+struct proc_dir_entry ipsec_spigrp = -+{ -+ 0, -+ 12, "ipsec_spigrp", -+ S_IFREG | S_IRUGO, 1, 0, 0, 0, -+ &proc_net_inode_operations, -+ ipsec_spigrp_get_info, -+ NULL, NULL, NULL, NULL, NULL -+}; -+ -+struct proc_dir_entry ipsec_tncfg = -+{ -+ 0, -+ 11, "ipsec_tncfg", -+ S_IFREG | S_IRUGO, 1, 0, 0, 0, -+ &proc_net_inode_operations, -+ ipsec_tncfg_get_info, -+ NULL, NULL, NULL, NULL, NULL -+}; -+ -+struct proc_dir_entry ipsec_version = -+{ -+ 0, -+ 13, "ipsec_version", -+ S_IFREG | S_IRUGO, 1, 0, 0, 0, -+ &proc_net_inode_operations, -+ ipsec_version_get_info, -+ NULL, NULL, NULL, NULL, NULL -+}; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+struct proc_dir_entry ipsec_klipsdebug = -+{ -+ 0, -+ 16, "ipsec_klipsdebug", -+ S_IFREG | S_IRUGO, 1, 0, 0, 0, -+ &proc_net_inode_operations, -+ ipsec_klipsdebug_get_info, -+ NULL, NULL, NULL, NULL, NULL -+}; -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif /* !PROC_FS_2325 */ -+#endif /* CONFIG_PROC_FS */ -+ -+#if defined(PROC_FS_2325) -+struct ipsec_proc_list { -+ char *name; -+ struct proc_dir_entry **parent; -+ struct proc_dir_entry **dir; -+ read_proc_t *readthing; -+ write_proc_t *writething; -+ void *data; -+}; -+static struct ipsec_proc_list proc_items[]={ -+#ifdef CONFIG_IPSEC_DEBUG -+ {"klipsdebug", &proc_net_ipsec_dir, NULL, ipsec_klipsdebug_get_info, NULL, NULL}, -+#endif -+ {"eroute", &proc_net_ipsec_dir, &proc_eroute_dir, NULL, NULL, NULL}, -+ {"all", &proc_eroute_dir, NULL, ipsec_eroute_get_info, NULL, NULL}, -+ {"spi", &proc_net_ipsec_dir, &proc_spi_dir, NULL, NULL, NULL}, -+ {"all", &proc_spi_dir, NULL, ipsec_spi_get_info, NULL, NULL}, -+ {"spigrp", &proc_net_ipsec_dir, &proc_spigrp_dir, NULL, NULL, NULL}, -+ {"all", &proc_spigrp_dir, NULL, ipsec_spigrp_get_info, NULL, NULL}, -+ {"birth", &proc_net_ipsec_dir, &proc_birth_dir, NULL, NULL, NULL}, -+ {"ipv4", &proc_birth_dir, NULL, ipsec_birth_info, ipsec_birth_set, (void *)&ipsec_ipv4_birth_packet}, -+ {"ipv6", &proc_birth_dir, NULL, ipsec_birth_info, ipsec_birth_set, (void *)&ipsec_ipv6_birth_packet}, -+ {"tncfg", &proc_net_ipsec_dir, NULL, ipsec_tncfg_get_info, NULL, NULL}, -+ {"xforms", &proc_net_ipsec_dir, NULL, ipsec_xform_get_info, NULL, NULL}, -+ {"stats", &proc_net_ipsec_dir, &proc_stats_dir, NULL, NULL, NULL}, -+ {"trap_count", &proc_stats_dir, NULL, ipsec_stats_get_int_info, NULL, &ipsec_xmit_trap_count}, -+ {"trap_sendcount", &proc_stats_dir, NULL, ipsec_stats_get_int_info, NULL, &ipsec_xmit_trap_sendcount}, -+ {"version", &proc_net_ipsec_dir, NULL, ipsec_version_get_info, NULL, NULL}, -+ {NULL, NULL, NULL, NULL, NULL, NULL} -+}; -+#endif -+ -+int -+ipsec_proc_init() -+{ -+ int error = 0; -+#ifdef IPSEC_PROC_SUBDIRS -+ struct proc_dir_entry *item; -+#endif -+ -+ /* -+ * just complain because pluto won't run without /proc! -+ */ -+#ifndef CONFIG_PROC_FS -+#error You must have PROC_FS built in to use KLIPS -+#endif -+ -+ /* for 2.0 kernels */ -+#if !defined(PROC_FS_2325) && !defined(PROC_FS_21) -+ error |= proc_register_dynamic(&proc_net, &ipsec_eroute); -+ error |= proc_register_dynamic(&proc_net, &ipsec_spi); -+ error |= proc_register_dynamic(&proc_net, &ipsec_spigrp); -+ error |= proc_register_dynamic(&proc_net, &ipsec_tncfg); -+ error |= proc_register_dynamic(&proc_net, &ipsec_version); -+#ifdef CONFIG_IPSEC_DEBUG -+ error |= proc_register_dynamic(&proc_net, &ipsec_klipsdebug); -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif -+ -+ /* for 2.2 kernels */ -+#if !defined(PROC_FS_2325) && defined(PROC_FS_21) -+ error |= proc_register(proc_net, &ipsec_eroute); -+ error |= proc_register(proc_net, &ipsec_spi); -+ error |= proc_register(proc_net, &ipsec_spigrp); -+ error |= proc_register(proc_net, &ipsec_tncfg); -+ error |= proc_register(proc_net, &ipsec_version); -+#ifdef CONFIG_IPSEC_DEBUG -+ error |= proc_register(proc_net, &ipsec_klipsdebug); -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif -+ -+ /* for 2.4 kernels */ -+#if defined(PROC_FS_2325) -+ /* create /proc/net/ipsec */ -+ -+ /* zero these out before we initialize /proc/net/ipsec/birth/stuff */ -+ memset(&ipsec_ipv4_birth_packet, 0, sizeof(struct ipsec_birth_reply)); -+ memset(&ipsec_ipv6_birth_packet, 0, sizeof(struct ipsec_birth_reply)); -+ -+ proc_net_ipsec_dir = proc_mkdir("ipsec", proc_net); -+ if(proc_net_ipsec_dir == NULL) { -+ /* no point in continuing */ -+ return 1; -+ } -+ -+ { -+ struct ipsec_proc_list *it; -+ -+ it=proc_items; -+ while(it->name!=NULL) { -+ if(it->dir) { -+ /* make a dir instead */ -+ item = proc_mkdir(it->name, *it->parent); -+ *it->dir = item; -+ } else { -+ item = create_proc_entry(it->name, 0400, *it->parent); -+ } -+ if(item) { -+ item->read_proc = it->readthing; -+ item->write_proc = it->writething; -+ item->data = it->data; -+#ifdef MODULE -+ item->owner = THIS_MODULE; -+#endif -+ } else { -+ error |= 1; -+ } -+ it++; -+ } -+ } -+ -+ /* now create some symlinks to provide compatibility */ -+ proc_symlink("ipsec_eroute", proc_net, "ipsec/eroute/all"); -+ proc_symlink("ipsec_spi", proc_net, "ipsec/spi/all"); -+ proc_symlink("ipsec_spigrp", proc_net, "ipsec/spigrp/all"); -+ proc_symlink("ipsec_tncfg", proc_net, "ipsec/tncfg"); -+ proc_symlink("ipsec_version",proc_net, "ipsec/version"); -+ proc_symlink("ipsec_klipsdebug",proc_net,"ipsec/klipsdebug"); -+ -+#endif /* !PROC_FS_2325 */ -+ -+ return error; -+} -+ -+void -+ipsec_proc_cleanup() -+{ -+ -+ /* for 2.0 and 2.2 kernels */ -+#if !defined(PROC_FS_2325) -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (proc_net_unregister(ipsec_klipsdebug.low_ino) != 0) -+ printk("klips_debug:ipsec_cleanup: " -+ "cannot unregister /proc/net/ipsec_klipsdebug\n"); -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ if (proc_net_unregister(ipsec_version.low_ino) != 0) -+ printk("klips_debug:ipsec_cleanup: " -+ "cannot unregister /proc/net/ipsec_version\n"); -+ if (proc_net_unregister(ipsec_eroute.low_ino) != 0) -+ printk("klips_debug:ipsec_cleanup: " -+ "cannot unregister /proc/net/ipsec_eroute\n"); -+ if (proc_net_unregister(ipsec_spi.low_ino) != 0) -+ printk("klips_debug:ipsec_cleanup: " -+ "cannot unregister /proc/net/ipsec_spi\n"); -+ if (proc_net_unregister(ipsec_spigrp.low_ino) != 0) -+ printk("klips_debug:ipsec_cleanup: " -+ "cannot unregister /proc/net/ipsec_spigrp\n"); -+ if (proc_net_unregister(ipsec_tncfg.low_ino) != 0) -+ printk("klips_debug:ipsec_cleanup: " -+ "cannot unregister /proc/net/ipsec_tncfg\n"); -+#endif -+ -+ /* for 2.4 kernels */ -+#if defined(PROC_FS_2325) -+ { -+ struct ipsec_proc_list *it; -+ -+ /* find end of list */ -+ it=proc_items; -+ while(it->name!=NULL) { -+ it++; -+ } -+ it--; -+ -+ do { -+ remove_proc_entry(it->name, *it->parent); -+ it--; -+ } while(it > proc_items); -+ } -+ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ remove_proc_entry("ipsec_klipsdebug", proc_net); -+#endif /* CONFIG_IPSEC_DEBUG */ -+ remove_proc_entry("ipsec_eroute", proc_net); -+ remove_proc_entry("ipsec_spi", proc_net); -+ remove_proc_entry("ipsec_spigrp", proc_net); -+ remove_proc_entry("ipsec_tncfg", proc_net); -+ remove_proc_entry("ipsec_version", proc_net); -+ remove_proc_entry("ipsec", proc_net); -+#endif /* 2.4 kernel */ -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.30 2004/04/25 21:23:11 ken -+ * Pull in dhr's changes from FreeS/WAN 2.06 -+ * -+ * Revision 1.29 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.28 2004/03/28 20:29:58 paul -+ * ssize_t, not ssized_t -+ * -+ * Revision 1.27 2004/03/28 20:27:20 paul -+ * Included tested and confirmed fixes mcr made and dhr verified for -+ * snprint statements. Changed one other snprintf to use ipsec_snprintf -+ * so it wouldnt break compatibility with 2.0/2.2 kernels. Verified with -+ * dhr. (thanks dhr!) -+ * -+ * Revision 1.26 2004/02/09 22:07:06 mcr -+ * added information about nat-traversal setting to spi-output. -+ * -+ * Revision 1.25.4.1 2004/04/05 04:30:46 mcr -+ * patches for alg-branch to compile/work with 2.x openswan -+ * -+ * Revision 1.25 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.24.4.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.24 2003/06/20 01:42:21 mcr -+ * added counters to measure how many ACQUIREs we send to pluto, -+ * and how many are successfully sent. -+ * -+ * Revision 1.23 2003/04/03 17:38:09 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * -+ * Revision 1.22 2002/09/20 15:40:57 rgb -+ * Renamed saref macros for consistency and brevity. -+ * -+ * Revision 1.21 2002/09/20 05:01:35 rgb -+ * Print ref and reftable, refentry seperately. -+ * -+ * Revision 1.20 2002/09/19 02:35:39 mcr -+ * do not define structures needed by /proc/net/ipsec/ if we -+ * aren't going create that directory. -+ * -+ * Revision 1.19 2002/09/10 01:43:25 mcr -+ * fixed problem in /-* comment. -+ * -+ * Revision 1.18 2002/09/03 16:22:11 mcr -+ * fixed initialization of birth/stuff values - some simple -+ * screw ups in the code. -+ * removed debugging that was left in by mistake. -+ * -+ * Revision 1.17 2002/09/02 17:54:53 mcr -+ * changed how the table driven /proc entries are created so that -+ * making subdirs is now explicit rather than implicit. -+ * -+ * Revision 1.16 2002/08/30 01:23:37 mcr -+ * reorganized /proc creating code to clear up ifdefs, -+ * make the 2.4 code table driven, and put things into -+ * /proc/net/ipsec subdir. Symlinks are left for compatibility. -+ * -+ * Revision 1.15 2002/08/13 19:01:25 mcr -+ * patches from kenb to permit compilation of FreeSWAN on ia64. -+ * des library patched to use proper DES_LONG type for ia64. -+ * -+ * Revision 1.14 2002/07/26 08:48:31 rgb -+ * Added SA ref table code. -+ * -+ * Revision 1.13 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.12 2002/05/27 18:56:07 rgb -+ * Convert to dynamic ipsec device allocation. -+ * -+ * Revision 1.11 2002/05/23 07:14:50 rgb -+ * Added refcount code. -+ * Cleaned up %p variants to 0p%p for test suite cleanup. -+ * Convert "usecount" to "refcount" to remove ambiguity. -+ * -+ * Revision 1.10 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.9 2002/04/24 07:36:28 mcr -+ * Moved from ./klips/net/ipsec/ipsec_proc.c,v -+ * -+ * Revision 1.8 2002/01/29 17:17:55 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.7 2002/01/29 04:00:52 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.6 2002/01/29 02:13:17 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.5 2002/01/12 02:54:30 mcr -+ * beginnings of /proc/net/ipsec dir. -+ * -+ * Revision 1.4 2001/12/11 02:21:05 rgb -+ * Don't include module version here, fixing 2.2 compile bug. -+ * -+ * Revision 1.3 2001/12/05 07:19:44 rgb -+ * Fixed extraneous #include "version.c" bug causing modular KLIPS failure. -+ * -+ * Revision 1.2 2001/11/26 09:16:14 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.74 2001/11/22 05:44:11 henry -+ * new version stuff -+ * -+ * Revision 1.1.2.1 2001/09/25 02:19:40 mcr -+ * /proc manipulation code moved to new ipsec_proc.c -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_radij.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,869 @@ -+/* -+ * Interface between the IPSEC code and the radix (radij) tree code -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#include -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, struct net_device_stats and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* 23_SPINLOCK */ -+# include /* *lock* */ -+# endif /* 23_SPINLOCK */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+#endif -+#include -+#include -+ -+#include "openswan/ipsec_eroute.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_tunnel.h" /* struct ipsecpriv */ -+#include "openswan/ipsec_xform.h" -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_radij = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+struct radij_node_head *rnh = NULL; -+#ifdef SPINLOCK -+spinlock_t eroute_lock = SPIN_LOCK_UNLOCKED; -+#else /* SPINLOCK */ -+spinlock_t eroute_lock; -+#endif /* SPINLOCK */ -+ -+int -+ipsec_radijinit(void) -+{ -+ maj_keylen = sizeof (struct sockaddr_encap); -+ -+ rj_init(); -+ -+ if (rj_inithead((void **)&rnh, /*16*/offsetof(struct sockaddr_encap, sen_type) * sizeof(__u8)) == 0) /* 16 is bit offset of sen_type */ -+ return -1; -+ return 0; -+} -+ -+int -+ipsec_radijcleanup(void) -+{ -+ int error; -+ -+ spin_lock_bh(&eroute_lock); -+ -+ error = radijcleanup(); -+ -+ spin_unlock_bh(&eroute_lock); -+ -+ return error; -+} -+ -+int -+ipsec_cleareroutes(void) -+{ -+ int error; -+ -+ spin_lock_bh(&eroute_lock); -+ -+ error = radijcleartree(); -+ -+ spin_unlock_bh(&eroute_lock); -+ -+ return error; -+} -+ -+int -+ipsec_breakroute(struct sockaddr_encap *eaddr, -+ struct sockaddr_encap *emask, -+ struct sk_buff **first, -+ struct sk_buff **last) -+{ -+ struct eroute *ro; -+ struct radij_node *rn; -+ int error; -+#ifdef CONFIG_IPSEC_DEBUG -+ -+ if (debug_eroute) { -+ char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; -+ subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2)); -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_breakroute: " -+ "attempting to delete eroute for %s:%d->%s:%d %d\n", -+ buf1, ntohs(eaddr->sen_sport), -+ buf2, ntohs(eaddr->sen_dport), eaddr->sen_proto); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ spin_lock_bh(&eroute_lock); -+ -+ if ((error = rj_delete(eaddr, emask, rnh, &rn)) != 0) { -+ spin_unlock_bh(&eroute_lock); -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_breakroute: " -+ "node not found, eroute delete failed.\n"); -+ return error; -+ } -+ -+ spin_unlock_bh(&eroute_lock); -+ -+ ro = (struct eroute *)rn; -+ -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_breakroute: " -+ "deleted eroute=0p%p, ident=0p%p->0p%p, first=0p%p, last=0p%p\n", -+ ro, -+ ro->er_ident_s.data, -+ ro->er_ident_d.data, -+ ro->er_first, -+ ro->er_last); -+ -+ if (ro->er_ident_s.data != NULL) { -+ kfree(ro->er_ident_s.data); -+ } -+ if (ro->er_ident_d.data != NULL) { -+ kfree(ro->er_ident_d.data); -+ } -+ if (ro->er_first != NULL) { -+#if 0 -+ struct net_device_stats *stats = (struct net_device_stats *) &(((struct ipsecpriv *)(ro->er_first->dev->priv))->mystats); -+ stats->tx_dropped--; -+#endif -+ *first = ro->er_first; -+ } -+ if (ro->er_last != NULL) { -+#if 0 -+ struct net_device_stats *stats = (struct net_device_stats *) &(((struct ipsecpriv *)(ro->er_last->dev->priv))->mystats); -+ stats->tx_dropped--; -+#endif -+ *last = ro->er_last; -+ } -+ -+ if (rn->rj_flags & (RJF_ACTIVE | RJF_ROOT)) -+ panic ("ipsec_breakroute RMT_DELEROUTE root or active node\n"); -+ memset((caddr_t)rn, 0, sizeof (struct eroute)); -+ kfree(rn); -+ -+ return 0; -+} -+ -+int -+ipsec_makeroute(struct sockaddr_encap *eaddr, -+ struct sockaddr_encap *emask, -+ ip_said said, -+ uint32_t pid, -+ struct sk_buff *skb, -+ struct ident *ident_s, -+ struct ident *ident_d) -+{ -+ struct eroute *retrt; -+ int error; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ -+ if (debug_eroute) { -+ -+ { -+ char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; -+ -+ subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2)); -+ sa_len = satot(&said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_makeroute: " -+ "attempting to allocate %lu bytes to insert eroute for %s->%s, SA: %s, PID:%d, skb=0p%p, ident:%s->%s\n", -+ (unsigned long) sizeof(struct eroute), -+ buf1, -+ buf2, -+ sa_len ? sa : " (error)", -+ pid, -+ skb, -+ (ident_s ? (ident_s->data ? ident_s->data : "NULL") : "NULL"), -+ (ident_d ? (ident_d->data ? ident_d->data : "NULL") : "NULL")); -+ } -+ { -+ char buf1[sizeof(struct sockaddr_encap)*2 + 1], -+ buf2[sizeof(struct sockaddr_encap)*2 + 1]; -+ int i; -+ unsigned char *b1 = buf1, -+ *b2 = buf2, -+ *ea = (unsigned char *)eaddr, -+ *em = (unsigned char *)emask; -+ -+ -+ for (i=0; ier_eaddr = *eaddr; -+ retrt->er_emask = *emask; -+ retrt->er_said = said; -+ retrt->er_pid = pid; -+ retrt->er_count = 0; -+ retrt->er_lasttime = jiffies/HZ; -+ rd_key((&(retrt->er_rjt))) = &(retrt->er_eaddr); -+ -+ if (ident_s && ident_s->type != SADB_IDENTTYPE_RESERVED) { -+ int data_len = ident_s->len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); -+ -+ retrt->er_ident_s.type = ident_s->type; -+ retrt->er_ident_s.id = ident_s->id; -+ retrt->er_ident_s.len = ident_s->len; -+ if(data_len) { -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_makeroute: " -+ "attempting to allocate %u bytes for ident_s.\n", -+ data_len); -+ if(!(retrt->er_ident_s.data = kmalloc(data_len, GFP_KERNEL))) { -+ kfree(retrt); -+ printk("klips_error:ipsec_makeroute: not able to allocate kernel memory (%d)\n", data_len); -+ return ENOMEM; -+ } -+ memcpy(retrt->er_ident_s.data, ident_s->data, data_len); -+ } else { -+ retrt->er_ident_s.data = NULL; -+ } -+ } -+ -+ if (ident_d && ident_d->type != SADB_IDENTTYPE_RESERVED) { -+ int data_len = ident_d->len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); -+ -+ retrt->er_ident_d.type = ident_d->type; -+ retrt->er_ident_d.id = ident_d->id; -+ retrt->er_ident_d.len = ident_d->len; -+ if(data_len) { -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_makeroute: " -+ "attempting to allocate %u bytes for ident_d.\n", -+ data_len); -+ if(!(retrt->er_ident_d.data = kmalloc(data_len, GFP_KERNEL))) { -+ if (retrt->er_ident_s.data) -+ kfree(retrt->er_ident_s.data); -+ kfree(retrt); -+ printk("klips_error:ipsec_makeroute: not able to allocate kernel memory (%d)\n", data_len); -+ return ENOMEM; -+ } -+ memcpy(retrt->er_ident_d.data, ident_d->data, data_len); -+ } else { -+ retrt->er_ident_d.data = NULL; -+ } -+ } -+ retrt->er_first = skb; -+ retrt->er_last = NULL; -+ -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_makeroute: " -+ "calling rj_addroute now\n"); -+ -+ spin_lock_bh(&eroute_lock); -+ -+ error = rj_addroute(&(retrt->er_eaddr), &(retrt->er_emask), -+ rnh, retrt->er_rjt.rd_nodes); -+ -+ spin_unlock_bh(&eroute_lock); -+ -+ if(error) { -+ sa_len = satot(&said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_makeroute: " -+ "rj_addroute not able to insert eroute for SA:%s (error:%d)\n", -+ sa_len ? sa : " (error)", error); -+ if (retrt->er_ident_s.data) -+ kfree(retrt->er_ident_s.data); -+ if (retrt->er_ident_d.data) -+ kfree(retrt->er_ident_d.data); -+ -+ kfree(retrt); -+ -+ return error; -+ } -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_eroute) { -+ char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; -+/* -+ subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2)); -+*/ -+ subnettoa(rd_key((&(retrt->er_rjt)))->sen_ip_src, rd_mask((&(retrt->er_rjt)))->sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(rd_key((&(retrt->er_rjt)))->sen_ip_dst, rd_mask((&(retrt->er_rjt)))->sen_ip_dst, 0, buf2, sizeof(buf2)); -+ sa_len = satot(&retrt->er_said, 0, sa, sizeof(sa)); -+ -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_makeroute: " -+ "pid=%05d " -+ "count=%10d " -+ "lasttime=%6d " -+ "%-18s -> %-18s => %s\n", -+ retrt->er_pid, -+ retrt->er_count, -+ (int)(jiffies/HZ - retrt->er_lasttime), -+ buf1, -+ buf2, -+ sa_len ? sa : " (error)"); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_makeroute: " -+ "succeeded.\n"); -+ return 0; -+} -+ -+struct eroute * -+ipsec_findroute(struct sockaddr_encap *eaddr) -+{ -+ struct radij_node *rn; -+#ifdef CONFIG_IPSEC_DEBUG -+ char buf1[ADDRTOA_BUF], buf2[ADDRTOA_BUF]; -+ -+ if (debug_radij & DB_RJ_FINDROUTE) { -+ addrtoa(eaddr->sen_ip_src, 0, buf1, sizeof(buf1)); -+ addrtoa(eaddr->sen_ip_dst, 0, buf2, sizeof(buf2)); -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:ipsec_findroute: " -+ "%s:%d->%s:%d %d\n", -+ buf1, ntohs(eaddr->sen_sport), -+ buf2, ntohs(eaddr->sen_dport), -+ eaddr->sen_proto); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ rn = rj_match((caddr_t)eaddr, rnh); -+ if(rn) { -+ KLIPS_PRINT(debug_eroute && sysctl_ipsec_debug_verbose, -+ "klips_debug:ipsec_findroute: " -+ "found, points to proto=%d, spi=%x, dst=%x.\n", -+ ((struct eroute*)rn)->er_said.proto, -+ ntohl(((struct eroute*)rn)->er_said.spi), -+ ntohl(((struct eroute*)rn)->er_said.dst.u.v4.sin_addr.s_addr)); -+ } -+ return (struct eroute *)rn; -+} -+ -+#ifdef CONFIG_PROC_FS -+/** ipsec_rj_walker_procprint: print one line of eroute table output. -+ * -+ * Theoretical BUG: if w->length is less than the length -+ * of some line we should produce, that line will never -+ * be finished. In effect, the "file" will stop part way -+ * through that line. -+ */ -+int -+ipsec_rj_walker_procprint(struct radij_node *rn, void *w0) -+{ -+ struct eroute *ro = (struct eroute *)rn; -+ struct rjtentry *rd = (struct rjtentry *)rn; -+ struct wsbuf *w = (struct wsbuf *)w0; -+ char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; -+ char buf3[16]; -+ char sa[SATOT_BUF]; -+ size_t sa_len, buf_len; -+ struct sockaddr_encap *key, *mask; -+ -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:ipsec_rj_walker_procprint: " -+ "rn=0p%p, w0=0p%p\n", -+ rn, -+ w0); -+ if (rn->rj_b >= 0) { -+ return 0; -+ } -+ -+ key = rd_key(rd); -+ mask = rd_mask(rd); -+ -+ if (key == NULL || mask == NULL) { -+ return 0; -+ } -+ -+ buf_len = subnettoa(key->sen_ip_src, mask->sen_ip_src, 0, buf1, sizeof(buf1)); -+ if(key->sen_sport != 0) { -+ sprintf(buf1+buf_len-1, ":%d", ntohs(key->sen_sport)); -+ } -+ -+ buf_len = subnettoa(key->sen_ip_dst, mask->sen_ip_dst, 0, buf2, sizeof(buf2)); -+ if(key->sen_dport != 0) { -+ sprintf(buf2+buf_len-1, ":%d", ntohs(key->sen_dport)); -+ } -+ -+ buf3[0]='\0'; -+ if(key->sen_proto != 0) { -+ sprintf(buf3, ":%d", key->sen_proto); -+ } -+ -+ sa_len = satot(&ro->er_said, 'x', sa, sizeof(sa)); -+ w->len += ipsec_snprintf(w->buffer + w->len, -+ w->length - w->len, -+ "%-10d " -+ "%-18s -> %-18s => %s%s\n", -+ ro->er_count, -+ buf1, -+ buf2, -+ sa_len ? sa : " (error)", -+ buf3); -+ -+ { -+ /* snprintf can only fill the last character with NUL -+ * so the maximum useful character is w->length-1. -+ * However, if w->length == 0, we cannot go back. -+ * (w->length surely cannot be negative.) -+ */ -+ int max_content = w->length > 0? w->length-1 : 0; -+ -+ if (w->len >= max_content) { -+ /* we've done all that can fit -- stop treewalking */ -+ w->len = max_content; /* truncate crap */ -+ return -ENOBUFS; -+ } else { -+ const off_t pos = w->begin + w->len; /* file position of end of what we've generated */ -+ -+ if (pos <= w->offset) { -+ /* all is before first interesting character: -+ * discard, but note where we are. -+ */ -+ w->len = 0; -+ w->begin = pos; -+ } -+ return 0; -+ } -+ } -+} -+#endif /* CONFIG_PROC_FS */ -+ -+int -+ipsec_rj_walker_delete(struct radij_node *rn, void *w0) -+{ -+ struct eroute *ro; -+ struct rjtentry *rd = (struct rjtentry *)rn; -+ struct radij_node *rn2; -+ int error; -+ struct sockaddr_encap *key, *mask; -+ -+ key = rd_key(rd); -+ mask = rd_mask(rd); -+ -+ if(!key || !mask) { -+ return -ENODATA; -+ } -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_radij) { -+ char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; -+ subnettoa(key->sen_ip_src, mask->sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(key->sen_ip_dst, mask->sen_ip_dst, 0, buf2, sizeof(buf2)); -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:ipsec_rj_walker_delete: " -+ "deleting: %s -> %s\n", -+ buf1, -+ buf2); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ if((error = rj_delete(key, mask, rnh, &rn2))) { -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:ipsec_rj_walker_delete: " -+ "rj_delete failed with error=%d.\n", error); -+ return error; -+ } -+ -+ if(rn2 != rn) { -+ printk("klips_debug:ipsec_rj_walker_delete: " -+ "tried to delete a different node?!? This should never happen!\n"); -+ } -+ -+ ro = (struct eroute *)rn; -+ -+ if (ro->er_ident_s.data) -+ kfree(ro->er_ident_s.data); -+ if (ro->er_ident_d.data) -+ kfree(ro->er_ident_d.data); -+ -+ memset((caddr_t)rn, 0, sizeof (struct eroute)); -+ kfree(rn); -+ -+ return 0; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.70 2004/04/25 21:10:52 ken -+ * Pull in dhr's changes from FreeS/WAN 2.06 -+ * -+ * Revision 1.69 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.68 2004/03/28 20:27:20 paul -+ * Included tested and confirmed fixes mcr made and dhr verified for -+ * snprint statements. Changed one other snprintf to use ipsec_snprintf -+ * so it wouldnt break compatibility with 2.0/2.2 kernels. Verified with -+ * dhr. (thanks dhr!) -+ * -+ * Revision 1.67.4.1 2004/04/05 04:30:46 mcr -+ * patches for alg-branch to compile/work with 2.x openswan -+ * -+ * Revision 1.67 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.66.24.2 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.66.24.1 2003/09/21 13:59:56 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.66 2002/10/12 23:11:53 dhr -+ * -+ * [KenB + DHR] more 64-bit cleanup -+ * -+ * Revision 1.65 2002/09/20 05:01:40 rgb -+ * Added memory allocation debugging. -+ * -+ * Revision 1.64 2002/05/31 01:46:05 mcr -+ * added && sysctl_ipsec_debug_verbose verbose to ipsec_findroute -+ * as requested in PR#14. -+ * -+ * Revision 1.63 2002/05/23 07:14:11 rgb -+ * Cleaned up %p variants to 0p%p for test suite cleanup. -+ * -+ * Revision 1.62 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.61 2002/04/24 07:36:29 mcr -+ * Moved from ./klips/net/ipsec/ipsec_radij.c,v -+ * -+ * Revision 1.60 2002/02/19 23:59:45 rgb -+ * Removed redundant compiler directives. -+ * -+ * Revision 1.59 2002/02/06 04:13:47 mcr -+ * missing #ifdef CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.58 2002/01/29 17:17:56 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.57 2002/01/29 04:00:52 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.56 2002/01/29 02:13:17 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.55 2001/11/26 09:23:48 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.53.2.1 2001/09/25 02:26:32 mcr -+ * headers adjusted for new usage. -+ * -+ * Revision 1.54 2001/10/18 04:45:20 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.53 2001/09/19 17:19:40 rgb -+ * Debug output bugfix for NetCelo's PF_KEY ident patch. -+ * -+ * Revision 1.52 2001/09/19 16:33:37 rgb -+ * Temporarily disable ident fields to /proc/net/ipsec_eroute. -+ * -+ * Revision 1.51 2001/09/15 16:24:04 rgb -+ * Re-inject first and last HOLD packet when an eroute REPLACE is done. -+ * -+ * Revision 1.50 2001/09/14 16:58:36 rgb -+ * Added support for storing the first and last packets through a HOLD. -+ * -+ * Revision 1.49 2001/09/08 21:13:32 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.48 2001/06/15 04:12:56 rgb -+ * Fixed kernel memory allocation error return code polarity bug. -+ * -+ * Revision 1.47 2001/06/14 19:35:09 rgb -+ * Update copyright date. -+ * -+ * Revision 1.46 2001/06/08 08:47:18 rgb -+ * Fixed for debug disabled. -+ * -+ * Revision 1.45 2001/05/27 06:12:11 rgb -+ * Added structures for pid, packet count and last access time to eroute. -+ * Added packet count to beginning of /proc/net/ipsec_eroute. -+ * -+ * Revision 1.44 2001/05/03 19:41:01 rgb -+ * Initialise error return variable. -+ * Use more appropriate return value for ipsec_rj_walker_delete(). -+ * -+ * Revision 1.43 2001/02/27 22:24:54 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.42 2001/02/27 06:21:57 rgb -+ * Added findroute success instrumentation. -+ * -+ * Revision 1.41 2000/11/06 04:32:08 rgb -+ * Ditched spin_lock_irqsave in favour of spin_lock_bh. -+ * -+ * Revision 1.40 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.39 2000/08/30 05:25:20 rgb -+ * Correct debug text in ipsec_breakroute() from incorrect -+ * "ipsec_callback". -+ * -+ * Revision 1.38 2000/07/28 14:58:31 rgb -+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. -+ * -+ * Revision 1.37 2000/03/16 14:02:50 rgb -+ * Fixed debug scope to enable compilation with debug off. -+ * -+ * Revision 1.36 2000/01/21 06:14:46 rgb -+ * Added debugging text to ipsec_rj_walker_delete(). -+ * Set return code to negative for consistency. -+ * -+ * Revision 1.35 1999/11/23 23:05:24 rgb -+ * Use provided macro ADDRTOA_BUF instead of hardcoded value. -+ * -+ * Revision 1.34 1999/11/18 04:13:56 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * Added CONFIG_PROC_FS compiler directives in case it is shut off. -+ * -+ * Revision 1.33 1999/11/17 15:53:39 rgb -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * -+ * Revision 1.32 1999/10/26 13:58:33 rgb -+ * Put spinlock flags variable declaration outside the debug compiler -+ * directive to enable compilation with debug shut off. -+ * -+ * Revision 1.31 1999/10/15 22:13:29 rgb -+ * Clean out cruft. -+ * Align /proc/net/ipsec_eroute output for easier readability. -+ * Fix double linefeed in radij debug output. -+ * Fix double locking bug that locks up 2.0.36 but not 2.0.38. -+ * -+ * Revision 1.30 1999/10/08 18:37:33 rgb -+ * Fix end-of-line spacing to sate whining PHMs. -+ * -+ * Revision 1.29 1999/10/03 18:52:45 rgb -+ * Spinlock support for 2.0.xx. -+ * Dumb return code spin_unlock fix. -+ * -+ * Revision 1.28 1999/10/01 16:22:24 rgb -+ * Switch from assignment init. to functional init. of spinlocks. -+ * -+ * Revision 1.27 1999/10/01 15:44:53 rgb -+ * Move spinlock header include to 2.1> scope. -+ * -+ * Revision 1.26 1999/10/01 00:01:23 rgb -+ * Added eroute structure locking. -+ * -+ * Revision 1.25 1999/06/10 16:07:30 rgb -+ * Silence delete eroute on no debug. -+ * -+ * Revision 1.24 1999/05/09 03:25:36 rgb -+ * Fix bug introduced by 2.2 quick-and-dirty patch. -+ * -+ * Revision 1.23 1999/05/05 22:02:31 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.22 1999/04/29 15:17:23 rgb -+ * Add return values to init and cleanup functions. -+ * Add sanity checking for null pointer arguments. -+ * -+ * Revision 1.21 1999/04/11 00:28:58 henry -+ * GPL boilerplate -+ * -+ * Revision 1.20 1999/04/06 04:54:26 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.19 1999/02/17 16:50:35 rgb -+ * Clean out unused cruft. -+ * Consolidate for space and speed efficiency. -+ * Convert DEBUG_IPSEC to KLIPS_PRINT -+ * -+ * Revision 1.18 1999/01/22 06:22:06 rgb -+ * Cruft clean-out. -+ * 64-bit clean-up. -+ * -+ * Revision 1.17 1998/12/02 03:09:39 rgb -+ * Clean up debug printing conditionals to compile with debugging off. -+ * -+ * Revision 1.16 1998/12/01 13:49:39 rgb -+ * Wrap version info printing in debug switches. -+ * -+ * Revision 1.15 1998/11/30 13:22:54 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.14 1998/10/31 06:48:17 rgb -+ * Fixed up comments in #endif directives. -+ * -+ * Revision 1.13 1998/10/27 13:48:09 rgb -+ * Cleaned up /proc/net/ipsec_* filesystem for easy parsing by scripts. -+ * Fixed less(1) truncated output bug. -+ * Code clean-up. -+ * -+ * Revision 1.12 1998/10/25 02:41:36 rgb -+ * Change return type on ipsec_breakroute and ipsec_makeroute and add an -+ * argument to be able to transmit more infomation about errors. -+ * Fix cut-and-paste debug statement identifier. -+ * -+ * Revision 1.11 1998/10/22 06:45:39 rgb -+ * Cleaned up cruft. -+ * Convert to use satoa for printk. -+ * -+ * Revision 1.10 1998/10/19 14:44:28 rgb -+ * Added inclusion of freeswan.h. -+ * sa_id structure implemented and used: now includes protocol. -+ * -+ * Revision 1.9 1998/10/09 04:30:52 rgb -+ * Added 'klips_debug' prefix to all klips printk debug statements. -+ * Deleted old commented out cruft. -+ * -+ * Revision 1.8 1998/08/06 17:24:23 rgb -+ * Fix addrtoa return code bug from stale manpage advice preventing packets -+ * from being erouted. -+ * -+ * Revision 1.7 1998/08/06 07:44:59 rgb -+ * Fixed /proc/net/ipsec_eroute subnettoa and addrtoa return value bug that -+ * ended up in nothing being printed. -+ * -+ * Revision 1.6 1998/08/05 22:16:41 rgb -+ * Cleanup to prevent cosmetic errors (ie. debug output) from being fatal. -+ * -+ * Revision 1.5 1998/07/29 20:38:44 rgb -+ * Debug and fix subnettoa and addrtoa output. -+ * -+ * Revision 1.4 1998/07/28 00:02:39 rgb -+ * Converting to exclusive use of addrtoa. -+ * Fix eroute delete. -+ * -+ * Revision 1.3 1998/07/14 18:21:26 rgb -+ * Add function to clear the eroute table. -+ * -+ * Revision 1.2 1998/06/23 02:59:14 rgb -+ * Added debugging output to eroute add/delete routines. -+ * -+ * Revision 1.9 1998/06/18 21:29:06 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid kernel -+ * build scripts happier in presence of symbolic links -+ * -+ * Revision 1.8 1998/06/05 02:32:26 rgb -+ * Fix spi ntoh kernel debug output. -+ * -+ * Revision 1.7 1998/05/25 20:30:37 rgb -+ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions. -+ * -+ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and -+ * add ipsec_rj_walker_delete. -+ * -+ * Revision 1.6 1998/05/21 13:08:57 rgb -+ * Rewrote procinfo subroutines to avoid *bad things* when more that 3k of -+ * information is available for printout. -+ * -+ * Revision 1.5 1998/05/18 21:35:55 rgb -+ * Clean up output for numerical consistency and readability. Zero freed -+ * eroute memory. -+ * -+ * Revision 1.4 1998/04/21 21:28:58 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.3 1998/04/14 17:30:39 rgb -+ * Fix up compiling errors for radij tree memory reclamation. -+ * -+ * Revision 1.2 1998/04/12 22:03:23 rgb -+ * Updated ESP-3DES-HMAC-MD5-96, -+ * ESP-DES-HMAC-MD5-96, -+ * AH-HMAC-MD5-96, -+ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository -+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts. -+ * -+ * Fixed eroute references in /proc/net/ipsec*. -+ * -+ * Started to patch module unloading memory leaks in ipsec_netlink and -+ * radij tree unloading. -+ * -+ * Revision 1.1 1998/04/09 03:06:10 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:03 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:39:04 ji -+ * Minor cleanups. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_rcv.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1922 @@ -+/* -+ * receive code -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998-2003 Richard Guy Briggs. -+ * Copyright (C) 2004 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_rcv_c_version[] = "RCSID $Id$"; -+ -+#include -+#include -+ -+#define __NO_VERSION__ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define proto_priv cb -+#endif /* NET21 */ -+#include -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+ -+#include "openswan/ipsec_auth.h" -+ -+#include "openswan/ipsec_esp.h" -+ -+#ifdef CONFIG_IPSEC_AH -+#include "openswan/ipsec_ah.h" -+#endif /* CONFIG_IPSEC_AH */ -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+#include "openswan/ipsec_ipcomp.h" -+#endif /* CONFIG_IPSEC_COMP */ -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+#include "openswan/ipsec_alg.h" -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_rcv = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+int sysctl_ipsec_inbound_policy_check = 1; -+ -+/* This is a private use protocol, and AT&T should be ashamed. They should have -+ * used protocol # 59, which is "no next header" instead of 0xFE. -+ */ -+#ifndef IPPROTO_ATT_HEARTBEAT -+#define IPPROTO_ATT_HEARTBEAT 0xFE -+#endif -+ -+#ifdef CONFIG_IPSEC_DEBUG -+void -+ipsec_dmp(char *s, caddr_t bb, int len) -+{ -+ int i; -+ unsigned char *b = bb; -+ -+ -+ printk(KERN_INFO "klips_debug:ipsec_tunnel_:dmp: " -+ "at %s, len=%d:", -+ s, -+ len); -+ for (i=0; i < len; i++) { -+ if(!(i%16)){ -+ printk("\nklips_debug: "); -+ } -+ printk(" %02x", *b++); -+ } -+ printk("\n"); -+} -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+/* -+ * Check-replay-window routine, adapted from the original -+ * by J. Hughes, from draft-ietf-ipsec-esp-des-md5-03.txt -+ * -+ * This is a routine that implements a 64 packet window. This is intend- -+ * ed on being an implementation sample. -+ */ -+ -+DEBUG_NO_STATIC int -+ipsec_checkreplaywindow(struct ipsec_sa*ipsp, __u32 seq) -+{ -+ __u32 diff; -+ -+ if (ipsp->ips_replaywin == 0) /* replay shut off */ -+ return 1; -+ if (seq == 0) -+ return 0; /* first == 0 or wrapped */ -+ -+ /* new larger sequence number */ -+ if (seq > ipsp->ips_replaywin_lastseq) { -+ return 1; /* larger is good */ -+ } -+ diff = ipsp->ips_replaywin_lastseq - seq; -+ -+ /* too old or wrapped */ /* if wrapped, kill off SA? */ -+ if (diff >= ipsp->ips_replaywin) { -+ return 0; -+ } -+ /* this packet already seen */ -+ if (ipsp->ips_replaywin_bitmap & (1 << diff)) -+ return 0; -+ return 1; /* out of order but good */ -+} -+ -+DEBUG_NO_STATIC int -+ipsec_updatereplaywindow(struct ipsec_sa*ipsp, __u32 seq) -+{ -+ __u32 diff; -+ -+ if (ipsp->ips_replaywin == 0) /* replay shut off */ -+ return 1; -+ if (seq == 0) -+ return 0; /* first == 0 or wrapped */ -+ -+ /* new larger sequence number */ -+ if (seq > ipsp->ips_replaywin_lastseq) { -+ diff = seq - ipsp->ips_replaywin_lastseq; -+ -+ /* In win, set bit for this pkt */ -+ if (diff < ipsp->ips_replaywin) -+ ipsp->ips_replaywin_bitmap = -+ (ipsp->ips_replaywin_bitmap << diff) | 1; -+ else -+ /* This packet has way larger seq num */ -+ ipsp->ips_replaywin_bitmap = 1; -+ -+ if(seq - ipsp->ips_replaywin_lastseq - 1 > ipsp->ips_replaywin_maxdiff) { -+ ipsp->ips_replaywin_maxdiff = seq - ipsp->ips_replaywin_lastseq - 1; -+ } -+ ipsp->ips_replaywin_lastseq = seq; -+ return 1; /* larger is good */ -+ } -+ diff = ipsp->ips_replaywin_lastseq - seq; -+ -+ /* too old or wrapped */ /* if wrapped, kill off SA? */ -+ if (diff >= ipsp->ips_replaywin) { -+/* -+ if(seq < 0.25*max && ipsp->ips_replaywin_lastseq > 0.75*max) { -+ ipsec_sa_delchain(ipsp); -+ } -+*/ -+ return 0; -+ } -+ /* this packet already seen */ -+ if (ipsp->ips_replaywin_bitmap & (1 << diff)) -+ return 0; -+ ipsp->ips_replaywin_bitmap |= (1 << diff); /* mark as seen */ -+ return 1; /* out of order but good */ -+} -+ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+struct auth_alg ipsec_rcv_md5[]={ -+ {MD5Init, MD5Update, MD5Final, AHMD596_ALEN} -+}; -+ -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+struct auth_alg ipsec_rcv_sha1[]={ -+ {SHA1Init, SHA1Update, SHA1Final, AHSHA196_ALEN} -+}; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+ -+enum ipsec_rcv_value -+ipsec_rcv_decap_once(struct ipsec_rcv_state *irs, struct xform_functions *proto_funcs) -+{ -+ int iphlen; -+ unsigned char *dat; -+ __u8 proto; -+ struct in_addr ipsaddr; -+ struct in_addr ipdaddr; -+ int replay = 0; /* replay value in AH or ESP packet */ -+ struct ipsec_sa* ipsnext = NULL; /* next SA towards inside of packet */ -+ struct ipsec_sa *newipsp; -+ struct iphdr *ipp; -+ struct sk_buff *skb; -+#ifdef CONFIG_IPSEC_ALG -+ struct ipsec_alg_auth *ixt_a=NULL; -+#endif /* CONFIG_IPSEC_ALG */ -+ -+ skb = irs->skb; -+ irs->len = skb->len; -+ dat = skb->data; -+ ipp = irs->ipp; -+ proto = ipp->protocol; -+ ipsaddr.s_addr = ipp->saddr; -+ addrtoa(ipsaddr, 0, irs->ipsaddr_txt, sizeof(irs->ipsaddr_txt)); -+ ipdaddr.s_addr = ipp->daddr; -+ addrtoa(ipdaddr, 0, irs->ipdaddr_txt, sizeof(irs->ipdaddr_txt)); -+ -+ iphlen = ipp->ihl << 2; -+ irs->iphlen=iphlen; -+ ipp->check = 0; /* we know the sum is good */ -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv_decap_once: " -+ "decap (%d) from %s -> %s\n", -+ proto, irs->ipsaddr_txt, irs->ipdaddr_txt); -+ -+ /* -+ * Find tunnel control block and (indirectly) call the -+ * appropriate tranform routine. The resulting sk_buf -+ * is a valid IP packet ready to go through input processing. -+ */ -+ -+ irs->said.dst.u.v4.sin_addr.s_addr = ipp->daddr; -+ irs->said.dst.u.v4.sin_family = AF_INET; -+ -+ if(proto_funcs->rcv_checks) { -+ enum ipsec_rcv_value retval = -+ (*proto_funcs->rcv_checks)(irs, skb); -+ -+ if(retval < 0) { -+ return retval; -+ } -+ } -+ -+ irs->said.proto = proto; -+ irs->sa_len = satot(&irs->said, 0, irs->sa, sizeof(irs->sa)); -+ if(irs->sa_len == 0) { -+ strcpy(irs->sa, "(error)"); -+ } -+ -+ newipsp = ipsec_sa_getbyid(&irs->said); -+ if (newipsp == NULL) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "no ipsec_sa for SA:%s: incoming packet with no SA dropped\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_SAIDNOTFOUND; -+ } -+ -+ /* MCR - XXX this is bizarre. ipsec_sa_getbyid returned it, having incremented the refcount, -+ * why in the world would we decrement it here? -+ -+ ipsec_sa_put(irs->ipsp);*/ /* incomplete */ -+ -+ /* If it is in larval state, drop the packet, we cannot process yet. */ -+ if(newipsp->ips_state == SADB_SASTATE_LARVAL) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "ipsec_sa in larval state, cannot be used yet, dropping packet.\n"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ ipsec_sa_put(newipsp); -+ return IPSEC_RCV_SAIDNOTLIVE; -+ } -+ -+ if(newipsp->ips_state == SADB_SASTATE_DEAD) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "ipsec_sa in dead state, cannot be used any more, dropping packet.\n"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ ipsec_sa_put(newipsp); -+ return IPSEC_RCV_SAIDNOTLIVE; -+ } -+ -+ if(sysctl_ipsec_inbound_policy_check) { -+ if(irs->ipp->saddr != ((struct sockaddr_in*)(newipsp->ips_addr_s))->sin_addr.s_addr) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s, src=%s of pkt does not agree with expected SA source address policy.\n", -+ irs->sa_len ? irs->sa : " (error)", -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ ipsec_sa_put(newipsp); -+ return IPSEC_RCV_FAILEDINBOUND; -+ } -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s, src=%s of pkt agrees with expected SA source address policy.\n", -+ irs->sa_len ? irs->sa : " (error)", -+ irs->ipsaddr_txt); -+ -+ /* -+ * at this point, we have looked up a new SA, and we want to make sure that if this -+ * isn't the first SA in the list, that the previous SA actually points at this one. -+ */ -+ if(irs->ipsp) { -+ if(irs->ipsp->ips_inext != newipsp) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "unexpected SA:%s: does not agree with ips->inext policy, dropped\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ ipsec_sa_put(newipsp); -+ return IPSEC_RCV_FAILEDINBOUND; -+ } -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s grouping from previous SA is OK.\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ } else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s First SA in group.\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ } -+ -+ /* -+ * previously, at this point, we checked if the back pointer from the new SA that -+ * we just found matched the back pointer. But, we won't do this check anymore, -+ * because we want to be able to nest SAs -+ */ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "natt_type=%u tdbp->ips_natt_type=%u : %s\n", -+ irs->natt_type, newipsp->ips_natt_type, -+ (irs->natt_type==newipsp->ips_natt_type)?"ok":"bad"); -+ if (irs->natt_type != newipsp->ips_natt_type) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s does not agree with expected NAT-T policy.\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ ipsec_sa_put(newipsp); -+ return IPSEC_RCV_FAILEDINBOUND; -+ } -+#endif -+ } -+ -+ /* okay, SA checks out, so free any previous SA, and record a new one */ -+ -+ if(irs->ipsp) { -+ ipsec_sa_put(irs->ipsp); -+ } -+ irs->ipsp=newipsp; -+ -+ /* note that the outer code will free the irs->ipsp if there is an error */ -+ -+ -+ /* now check the lifetimes */ -+ if(ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_bytes, "bytes", -+ irs->sa, ipsec_life_countbased, ipsec_incoming, -+ irs->ipsp) == ipsec_life_harddied || -+ ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_addtime, "addtime", -+ irs->sa, ipsec_life_timebased, ipsec_incoming, -+ irs->ipsp) == ipsec_life_harddied || -+ ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_addtime, "usetime", -+ irs->sa, ipsec_life_timebased, ipsec_incoming, -+ irs->ipsp) == ipsec_life_harddied || -+ ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_packets, "packets", -+ irs->sa, ipsec_life_countbased, ipsec_incoming, -+ irs->ipsp) == ipsec_life_harddied) { -+ ipsec_sa_delchain(irs->ipsp); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv_decap_once: " -+ "decap (%d) failed lifetime check\n", -+ proto); -+ -+ return IPSEC_RCV_LIFETIMEFAILED; -+ } -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if ((irs->natt_type) && -+ ( (irs->ipp->saddr != (((struct sockaddr_in*)(newipsp->ips_addr_s))->sin_addr.s_addr)) || -+ (irs->natt_sport != newipsp->ips_natt_sport) -+ )) { -+ struct sockaddr sipaddr; -+ /** Advertise NAT-T addr change to pluto **/ -+ sipaddr.sa_family = AF_INET; -+ ((struct sockaddr_in*)&sipaddr)->sin_addr.s_addr = irs->ipp->saddr; -+ ((struct sockaddr_in*)&sipaddr)->sin_port = htons(irs->natt_sport); -+ pfkey_nat_t_new_mapping(newipsp, &sipaddr, irs->natt_sport); -+ /** -+ * Then allow or block packet depending on -+ * sysctl_ipsec_inbound_policy_check. -+ * -+ * In all cases, pluto will update SA if new mapping is -+ * accepted. -+ */ -+ if (sysctl_ipsec_inbound_policy_check) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s, src=%s:%u of pkt does not agree with expected " -+ "SA source address policy (pluto has been informed).\n", -+ irs->sa_len ? irs->sa : " (error)", -+ irs->ipsaddr_txt, irs->natt_sport); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ ipsec_sa_put(newipsp); -+ return IPSEC_RCV_FAILEDINBOUND; -+ } -+ } -+#endif -+ -+ irs->authfuncs=NULL; -+ /* authenticate, if required */ -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_a=irs->ipsp->ips_alg_auth)) { -+ irs->authlen = AHHMAC_HASHLEN; -+ irs->authfuncs = NULL; -+ irs->ictx = NULL; -+ irs->octx = NULL; -+ irs->ictx_len = 0; -+ irs->octx_len = 0; -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "authalg=%d authlen=%d\n", -+ irs->ipsp->ips_authalg, -+ irs->authlen); -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(irs->ipsp->ips_authalg) { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: -+ irs->authlen = AHHMAC_HASHLEN; -+ irs->authfuncs = ipsec_rcv_md5; -+ irs->ictx = (void *)&((struct md5_ctx*)(irs->ipsp->ips_key_a))->ictx; -+ irs->octx = (void *)&((struct md5_ctx*)(irs->ipsp->ips_key_a))->octx; -+ irs->ictx_len = sizeof(((struct md5_ctx*)(irs->ipsp->ips_key_a))->ictx); -+ irs->octx_len = sizeof(((struct md5_ctx*)(irs->ipsp->ips_key_a))->octx); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: -+ irs->authlen = AHHMAC_HASHLEN; -+ irs->authfuncs = ipsec_rcv_sha1; -+ irs->ictx = (void *)&((struct sha1_ctx*)(irs->ipsp->ips_key_a))->ictx; -+ irs->octx = (void *)&((struct sha1_ctx*)(irs->ipsp->ips_key_a))->octx; -+ irs->ictx_len = sizeof(((struct sha1_ctx*)(irs->ipsp->ips_key_a))->ictx); -+ irs->octx_len = sizeof(((struct sha1_ctx*)(irs->ipsp->ips_key_a))->octx); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ case AH_NONE: -+ irs->authlen = 0; -+ irs->authfuncs = NULL; -+ irs->ictx = NULL; -+ irs->octx = NULL; -+ irs->ictx_len = 0; -+ irs->octx_len = 0; -+ break; -+ default: -+ irs->ipsp->ips_errs.ips_alg_errs += 1; -+ if(irs->stats) { -+ irs->stats->rx_errors++; -+ } -+ return IPSEC_RCV_BADAUTH; -+ } -+ -+ irs->ilen = irs->len - iphlen - irs->authlen; -+ if(irs->ilen <= 0) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "runt %s packet with no data, dropping.\n", -+ (proto == IPPROTO_ESP ? "esp" : "ah")); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_BADLEN; -+ } -+ -+#ifdef CONFIG_IPSEC_ALG -+ if(irs->authfuncs || ixt_a) { -+#else -+ if(irs->authfuncs) { -+#endif -+ unsigned char *authenticator = NULL; -+ -+ if(proto_funcs->rcv_setup_auth) { -+ enum ipsec_rcv_value retval -+ = (*proto_funcs->rcv_setup_auth)(irs, skb, -+ &replay, -+ &authenticator); -+ if(retval < 0) { -+ return retval; -+ } -+ } -+ -+ if(!authenticator) { -+ irs->ipsp->ips_errs.ips_auth_errs += 1; -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_BADAUTH; -+ } -+ -+ if(!ipsec_checkreplaywindow(irs->ipsp, replay)) { -+ irs->ipsp->ips_errs.ips_replaywin_errs += 1; -+ KLIPS_PRINT(debug_rcv & DB_RX_REPLAY, -+ "klips_debug:ipsec_rcv: " -+ "duplicate frame from %s, packet dropped\n", -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_REPLAYFAILED; -+ } -+ -+ /* -+ * verify authenticator -+ */ -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "encalg = %d, authalg = %d.\n", -+ irs->ipsp->ips_encalg, -+ irs->ipsp->ips_authalg); -+ -+ /* calculate authenticator */ -+ if(proto_funcs->rcv_calc_auth == NULL) { -+ return IPSEC_RCV_BADAUTH; -+ } -+ (*proto_funcs->rcv_calc_auth)(irs, skb); -+ -+ if (memcmp(irs->hash, authenticator, irs->authlen)) { -+ irs->ipsp->ips_errs.ips_auth_errs += 1; -+ KLIPS_PRINT(debug_rcv & DB_RX_INAU, -+ "klips_debug:ipsec_rcv: " -+ "auth failed on incoming packet from %s: hash=%08x%08x%08x auth=%08x%08x%08x, dropped\n", -+ irs->ipsaddr_txt, -+ ntohl(*(__u32*)&irs->hash[0]), -+ ntohl(*(__u32*)&irs->hash[4]), -+ ntohl(*(__u32*)&irs->hash[8]), -+ ntohl(*(__u32*)authenticator), -+ ntohl(*((__u32*)authenticator + 1)), -+ ntohl(*((__u32*)authenticator + 2))); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_AUTHFAILED; -+ } else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "authentication successful.\n"); -+ } -+ -+ /* Crypto hygiene: clear memory used to calculate autheticator. -+ * The length varies with the algorithm. -+ */ -+ memset(irs->hash, 0, irs->authlen); -+ -+ /* If the sequence number == 0, expire SA, it had rolled */ -+ if(irs->ipsp->ips_replaywin && !replay /* !irs->ipsp->ips_replaywin_lastseq */) { -+ ipsec_sa_delchain(irs->ipsp); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "replay window counter rolled, expiring SA.\n"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_REPLAYROLLED; -+ } -+ -+ /* now update the replay counter */ -+ if (!ipsec_updatereplaywindow(irs->ipsp, replay)) { -+ irs->ipsp->ips_errs.ips_replaywin_errs += 1; -+ KLIPS_PRINT(debug_rcv & DB_RX_REPLAY, -+ "klips_debug:ipsec_rcv: " -+ "duplicate frame from %s, packet dropped\n", -+ irs->ipsaddr_txt); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_REPLAYROLLED; -+ } -+ } -+ -+ if(proto_funcs->rcv_decrypt) { -+ enum ipsec_rcv_value retval = -+ (*proto_funcs->rcv_decrypt)(irs); -+ -+ if(retval != IPSEC_RCV_OK) { -+ return retval; -+ } -+ } -+ -+ /* -+ * Adjust pointers -+ */ -+ skb = irs->skb; -+ irs->len = skb->len; -+ dat = skb->data; -+ -+#ifdef NET_21 -+/* skb->h.ipiph=(struct iphdr *)skb->data; */ -+ skb->nh.raw = skb->data; -+ skb->h.raw = skb->nh.raw + (skb->nh.iph->ihl << 2); -+ -+ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); -+#else /* NET_21 */ -+ skb->h.iph=(struct iphdr *)skb->data; -+ skb->ip_hdr=(struct iphdr *)skb->data; -+ memset(skb->proto_priv, 0, sizeof(struct options)); -+#endif /* NET_21 */ -+ -+ ipp = (struct iphdr *)dat; -+ ipsaddr.s_addr = ipp->saddr; -+ addrtoa(ipsaddr, 0, irs->ipsaddr_txt, sizeof(irs->ipsaddr_txt)); -+ ipdaddr.s_addr = ipp->daddr; -+ addrtoa(ipdaddr, 0, irs->ipdaddr_txt, sizeof(irs->ipdaddr_txt)); -+ /* -+ * Discard the original ESP/AH header -+ */ -+ ipp->protocol = irs->next_header; -+ -+ ipp->check = 0; /* NOTE: this will be included in checksum */ -+ ipp->check = ip_fast_csum((unsigned char *)dat, iphlen >> 2); -+ -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "after <%s%s%s>, SA:%s:\n", -+ IPS_XFORM_NAME(irs->ipsp), -+ irs->sa_len ? irs->sa : " (error)"); -+ KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp); -+ -+ skb->protocol = htons(ETH_P_IP); -+ skb->ip_summed = 0; -+ -+ ipsnext = irs->ipsp->ips_inext; -+ if(sysctl_ipsec_inbound_policy_check) { -+ if(ipsnext) { -+ if( -+ ipp->protocol != IPPROTO_AH -+ && ipp->protocol != IPPROTO_ESP -+#ifdef CONFIG_IPSEC_IPCOMP -+ && ipp->protocol != IPPROTO_COMP -+ && (ipsnext->ips_said.proto != IPPROTO_COMP -+ || ipsnext->ips_inext) -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ && ipp->protocol != IPPROTO_IPIP -+ && ipp->protocol != 0xFE /* added to support heartbeats to AT&T SIG/GIG */ -+ ) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "packet with incomplete policy dropped, last successful SA:%s.\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ if(irs->stats) { -+ irs->stats->rx_dropped++; -+ } -+ return IPSEC_RCV_FAILEDINBOUND; -+ } -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s, Another IPSEC header to process.\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ } else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "No ips_inext from this SA:%s.\n", -+ irs->sa_len ? irs->sa : " (error)"); -+ } -+ } -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+ /* update ipcomp ratio counters, even if no ipcomp packet is present */ -+ if (ipsnext -+ && ipsnext->ips_said.proto == IPPROTO_COMP -+ && ipp->protocol != IPPROTO_COMP) { -+ ipsnext->ips_comp_ratio_cbytes += ntohs(ipp->tot_len); -+ ipsnext->ips_comp_ratio_dbytes += ntohs(ipp->tot_len); -+ } -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+ irs->ipsp->ips_life.ipl_bytes.ipl_count += irs->len; -+ irs->ipsp->ips_life.ipl_bytes.ipl_last = irs->len; -+ -+ if(!irs->ipsp->ips_life.ipl_usetime.ipl_count) { -+ irs->ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ; -+ } -+ irs->ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ; -+ irs->ipsp->ips_life.ipl_packets.ipl_count += 1; -+ -+#ifdef CONFIG_NETFILTER -+ if(proto == IPPROTO_ESP || proto == IPPROTO_AH) { -+ skb->nfmark = (skb->nfmark & (~(IPsecSAref2NFmark(IPSEC_SA_REF_MASK)))) -+ | IPsecSAref2NFmark(IPsecSA2SAref(irs->ipsp)); -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "%s SA sets skb->nfmark=0x%x.\n", -+ proto == IPPROTO_ESP ? "ESP" : "AH", -+ (unsigned)skb->nfmark); -+ } -+#endif /* CONFIG_NETFILTER */ -+ -+ return IPSEC_RCV_OK; -+} -+ -+ -+int -+#ifdef PROTO_HANDLER_SINGLE_PARM -+ipsec_rcv(struct sk_buff *skb) -+#else /* PROTO_HANDLER_SINGLE_PARM */ -+#ifdef NET_21 -+ipsec_rcv(struct sk_buff *skb, unsigned short xlen) -+#else /* NET_21 */ -+ipsec_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, -+ __u32 daddr_unused, unsigned short xlen, __u32 saddr, -+ int redo, struct inet_protocol *protocol) -+#endif /* NET_21 */ -+#endif /* PROTO_HANDLER_SINGLE_PARM */ -+{ -+#ifdef NET_21 -+#ifdef CONFIG_IPSEC_DEBUG -+ struct device *dev = skb->dev; -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif /* NET_21 */ -+ unsigned char protoc; -+ struct iphdr *ipp; -+ struct ipsec_sa *ipsp = NULL; -+ struct net_device_stats *stats = NULL; /* This device's statistics */ -+ struct device *ipsecdev = NULL, *prvdev; -+ struct ipsecpriv *prv; -+ char name[9]; -+ int i; -+ struct in_addr ipsaddr; -+ struct in_addr ipdaddr; -+ -+ struct ipsec_sa* ipsnext = NULL; /* next SA towards inside of packet */ -+ struct ipsec_rcv_state irs; -+ -+ /* Don't unlink in the middle of a turnaround */ -+ MOD_INC_USE_COUNT; -+ -+ memset(&irs, 0, sizeof(struct ipsec_rcv_state)); -+ -+ if (skb == NULL) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NULL skb passed in.\n"); -+ goto rcvleave; -+ } -+ -+ if (skb->data == NULL) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NULL skb->data passed in, packet is bogus, dropping.\n"); -+ goto rcvleave; -+ } -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if (skb->sk && skb->nh.iph && skb->nh.iph->protocol==IPPROTO_UDP) { -+ /** -+ * Packet comes from udp_queue_rcv_skb so it is already defrag, -+ * checksum verified, ... (ie safe to use) -+ * -+ * If the packet is not for us, return -1 and udp_queue_rcv_skb -+ * will continue to handle it (do not kfree skb !!). -+ */ -+#ifndef UDP_OPT_IN_SOCK -+ struct udp_opt { -+ __u32 esp_in_udp; -+ }; -+ struct udp_opt *tp = (struct udp_opt *)&(skb->sk->tp_pinfo.af_tcp); -+#else -+ struct udp_opt *tp = &(skb->sk->tp_pinfo.af_udp); -+#endif -+ struct iphdr *ip = (struct iphdr *)skb->nh.iph; -+ struct udphdr *udp = (struct udphdr *)((__u32 *)ip+ip->ihl); -+ __u8 *udpdata = (__u8 *)udp + sizeof(struct udphdr); -+ __u32 *udpdata32 = (__u32 *)udpdata; -+ -+ irs.natt_sport = ntohs(udp->source); -+ irs.natt_dport = ntohs(udp->dest); -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "suspected ESPinUDP packet (NAT-Traversal) [%d].\n", -+ tp->esp_in_udp); -+ KLIPS_IP_PRINT(debug_rcv, ip); -+ -+ if (udpdata < skb->tail) { -+ unsigned int len = skb->tail - udpdata; -+ if ((len==1) && (udpdata[0]==0xff)) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ /* not IPv6 compliant message */ -+ "NAT-keepalive from %d.%d.%d.%d.\n", NIPQUAD(ip->saddr)); -+ goto rcvleave; -+ } -+ else if ( (tp->esp_in_udp == ESPINUDP_WITH_NON_IKE) && -+ (len > (2*sizeof(__u32) + sizeof(struct esphdr))) && -+ (udpdata32[0]==0) && (udpdata32[1]==0) ) { -+ /* ESP Packet with Non-IKE header */ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "ESPinUDP pkt with Non-IKE - spi=0x%x\n", -+ ntohl(udpdata32[2])); -+ irs.natt_type = ESPINUDP_WITH_NON_IKE; -+ irs.natt_len = sizeof(struct udphdr)+(2*sizeof(__u32)); -+ } -+ else if ( (tp->esp_in_udp == ESPINUDP_WITH_NON_ESP) && -+ (len > sizeof(struct esphdr)) && -+ (udpdata32[0]!=0) ) { -+ /* ESP Packet without Non-ESP header */ -+ irs.natt_type = ESPINUDP_WITH_NON_ESP; -+ irs.natt_len = sizeof(struct udphdr); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "ESPinUDP pkt without Non-ESP - spi=0x%x\n", -+ ntohl(udpdata32[0])); -+ } -+ else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "IKE packet - not handled here\n"); -+ MOD_DEC_USE_COUNT; -+ return -1; -+ } -+ } -+ else { -+ MOD_DEC_USE_COUNT; -+ return -1; -+ } -+ } -+#endif -+ -+#ifdef IPH_is_SKB_PULLED -+ /* In Linux 2.4.4, the IP header has been skb_pull()ed before the -+ packet is passed to us. So we'll skb_push() to get back to it. */ -+ if (skb->data == skb->h.raw) { -+ skb_push(skb, skb->h.raw - skb->nh.raw); -+ } -+#endif /* IPH_is_SKB_PULLED */ -+ -+ /* dev->hard_header_len is unreliable and should not be used */ -+ irs.hard_header_len = skb->mac.raw ? (skb->data - skb->mac.raw) : 0; -+ if((irs.hard_header_len < 0) || (irs.hard_header_len > skb_headroom(skb))) -+ irs.hard_header_len = 0; -+ -+#ifdef NET_21 -+ /* if skb was cloned (most likely due to a packet sniffer such as -+ tcpdump being momentarily attached to the interface), make -+ a copy of our own to modify */ -+ if(skb_cloned(skb)) { -+ /* include any mac header while copying.. */ -+ if(skb_headroom(skb) < irs.hard_header_len) { -+ printk(KERN_WARNING "klips_error:ipsec_rcv: " -+ "tried to skb_push hhlen=%d, %d available. This should never happen, please report.\n", -+ irs.hard_header_len, -+ skb_headroom(skb)); -+ goto rcvleave; -+ } -+ skb_push(skb, irs.hard_header_len); -+ if -+#ifdef SKB_COW_NEW -+ (skb_cow(skb, skb_headroom(skb)) != 0) -+#else /* SKB_COW_NEW */ -+ ((skb = skb_cow(skb, skb_headroom(skb))) == NULL) -+#endif /* SKB_COW_NEW */ -+ { -+ goto rcvleave; -+ } -+ if(skb->len < irs.hard_header_len) { -+ printk(KERN_WARNING "klips_error:ipsec_rcv: " -+ "tried to skb_pull hhlen=%d, %d available. This should never happen, please report.\n", -+ irs.hard_header_len, -+ skb->len); -+ goto rcvleave; -+ } -+ skb_pull(skb, irs.hard_header_len); -+ } -+ -+#endif /* NET_21 */ -+ -+#if IP_FRAGMENT_LINEARIZE -+ /* In Linux 2.4.4, we may have to reassemble fragments. They are -+ not assembled automatically to save TCP from having to copy -+ twice. -+ */ -+ if (skb_is_nonlinear(skb)) { -+ if (skb_linearize(skb, GFP_ATOMIC) != 0) { -+ goto rcvleave; -+ } -+ } -+#endif /* IP_FRAGMENT_LINEARIZE */ -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if (irs.natt_len) { -+ /** -+ * Now, we are sure packet is ESPinUDP. Remove natt_len bytes from -+ * packet and modify protocol to ESP. -+ */ -+ if (((unsigned char *)skb->data > (unsigned char *)skb->nh.iph) && -+ ((unsigned char *)skb->nh.iph > (unsigned char *)skb->head)) { -+ unsigned int _len = (unsigned char *)skb->data - -+ (unsigned char *)skb->nh.iph; -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: adjusting skb: skb_push(%u)\n", -+ _len); -+ skb_push(skb, _len); -+ } -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "removing %d bytes from ESPinUDP packet\n", irs.natt_len); -+ ipp = (struct iphdr *)skb->data; -+ irs.iphlen = ipp->ihl << 2; -+ ipp->tot_len = htons(ntohs(ipp->tot_len) - irs.natt_len); -+ if (skb->len < irs.iphlen + irs.natt_len) { -+ printk(KERN_WARNING -+ "klips_error:ipsec_rcv: " -+ "ESPinUDP packet is too small (%d < %d+%d). " -+ "This should never happen, please report.\n", -+ (int)(skb->len), irs.iphlen, irs.natt_len); -+ goto rcvleave; -+ } -+ memmove(skb->data + irs.natt_len, skb->data, irs.iphlen); -+ skb_pull(skb, irs.natt_len); -+ -+ /* update nh.iph */ -+ ipp = skb->nh.iph = (struct iphdr *)skb->data; -+ -+ /* modify protocol */ -+ ipp->protocol = IPPROTO_ESP; -+ -+ skb->sk = NULL; -+ -+ KLIPS_IP_PRINT(debug_rcv, skb->nh.iph); -+ } -+#endif -+ -+ ipp = skb->nh.iph; -+ ipsaddr.s_addr = ipp->saddr; -+ addrtoa(ipsaddr, 0, irs.ipsaddr_txt, sizeof(irs.ipsaddr_txt)); -+ ipdaddr.s_addr = ipp->daddr; -+ addrtoa(ipdaddr, 0, irs.ipdaddr_txt, sizeof(irs.ipdaddr_txt)); -+ irs.iphlen = ipp->ihl << 2; -+ -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "<<< Info -- "); -+ KLIPS_PRINTMORE(debug_rcv && skb->dev, "skb->dev=%s ", -+ skb->dev->name ? skb->dev->name : "NULL"); -+ KLIPS_PRINTMORE(debug_rcv && dev, "dev=%s ", -+ dev->name ? dev->name : "NULL"); -+ KLIPS_PRINTMORE(debug_rcv, "\n"); -+ -+ KLIPS_PRINT(debug_rcv && !(skb->dev && dev && (skb->dev == dev)), -+ "klips_debug:ipsec_rcv: " -+ "Informational -- **if this happens, find out why** skb->dev:%s is not equal to dev:%s\n", -+ skb->dev ? (skb->dev->name ? skb->dev->name : "NULL") : "NULL", -+ dev ? (dev->name ? dev->name : "NULL") : "NULL"); -+ -+ protoc = ipp->protocol; -+#ifndef NET_21 -+ if((!protocol) || (protocol->protocol != protoc)) { -+ KLIPS_PRINT(debug_rcv & DB_RX_IPSA, -+ "klips_debug:ipsec_rcv: " -+ "protocol arg is NULL or unequal to the packet contents, this is odd, using value in packet.\n"); -+ } -+#endif /* !NET_21 */ -+ -+ if( (protoc != IPPROTO_AH) && -+#ifdef CONFIG_IPSEC_IPCOMP_disabled_until_we_register_IPCOMP_HANDLER -+ (protoc != IPPROTO_COMP) && -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ (protoc != IPPROTO_ESP) ) { -+ KLIPS_PRINT(debug_rcv & DB_RX_IPSA, -+ "klips_debug:ipsec_rcv: Why the hell is someone " -+ "passing me a non-ipsec protocol = %d packet? -- dropped.\n", -+ protoc); -+ goto rcvleave; -+ } -+ -+ if(skb->dev) { -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ sprintf(name, IPSEC_DEV_FORMAT, i); -+ if(!strcmp(name, skb->dev->name)) { -+ prv = (struct ipsecpriv *)(skb->dev->priv); -+ if(prv) { -+ stats = (struct net_device_stats *) &(prv->mystats); -+ } -+ ipsecdev = skb->dev; -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "Info -- pkt already proc'ed a group of ipsec headers, processing next group of ipsec headers.\n"); -+ break; -+ } -+ if((ipsecdev = __ipsec_dev_get(name)) == NULL) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_error:ipsec_rcv: " -+ "device %s does not exist\n", -+ name); -+ } -+ prv = ipsecdev ? (struct ipsecpriv *)(ipsecdev->priv) : NULL; -+ prvdev = prv ? (struct device *)(prv->dev) : NULL; -+ -+#if 0 -+ KLIPS_PRINT(debug_rcv && prvdev, -+ "klips_debug:ipsec_rcv: " -+ "physical device for device %s is %s\n", -+ name, -+ prvdev->name); -+#endif -+ if(prvdev && skb->dev && -+ !strcmp(prvdev->name, skb->dev->name)) { -+ stats = prv ? ((struct net_device_stats *) &(prv->mystats)) : NULL; -+ skb->dev = ipsecdev; -+ KLIPS_PRINT(debug_rcv && prvdev, -+ "klips_debug:ipsec_rcv: " -+ "assigning packet ownership to virtual device %s from physical device %s.\n", -+ name, prvdev->name); -+ if(stats) { -+ stats->rx_packets++; -+ } -+ break; -+ } -+ } -+ } else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "device supplied with skb is NULL\n"); -+ } -+ -+ if(stats == NULL) { -+ KLIPS_PRINT((debug_rcv), -+ "klips_error:ipsec_rcv: " -+ "packet received from physical I/F (%s) not connected to ipsec I/F. Cannot record stats. May not have SA for decoding. Is IPSEC traffic expected on this I/F? Check routing.\n", -+ skb->dev ? (skb->dev->name ? skb->dev->name : "NULL") : "NULL"); -+ } -+ -+ KLIPS_IP_PRINT(debug_rcv, ipp); -+ -+ /* begin decapsulating loop here */ -+ -+ /* -+ The spinlock is to prevent any other process from -+ accessing or deleting the ipsec_sa hash table or any of the -+ ipsec_sa s while we are using and updating them. -+ -+ This is not optimal, but was relatively straightforward -+ at the time. A better way to do it has been planned for -+ more than a year, to lock the hash table and put reference -+ counts on each ipsec_sa instead. This is not likely to happen -+ in KLIPS1 unless a volunteer contributes it, but will be -+ designed into KLIPS2. -+ */ -+ spin_lock(&tdb_lock); -+ -+ /* set up for decap loop */ -+ irs.stats= stats; -+ irs.ipp = ipp; -+ irs.ipsp = NULL; -+ irs.ilen = 0; -+ irs.authlen=0; -+ irs.authfuncs=NULL; -+ irs.skb = skb; -+ -+ do { -+ int decap_stat; -+ struct xform_functions *proto_funcs; -+ -+ switch(irs.ipp->protocol) { -+ case IPPROTO_ESP: -+ proto_funcs = esp_xform_funcs; -+ break; -+ -+#ifdef CONFIG_IPSEC_AH -+ case IPPROTO_AH: -+ proto_funcs = ah_xform_funcs; -+ break; -+#endif /* !CONFIG_IPSEC_AH */ -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+ case IPPROTO_COMP: -+ proto_funcs = ipcomp_xform_funcs; -+ break; -+#endif /* !CONFIG_IPSEC_IPCOMP */ -+ default: -+ if(irs.stats) { -+ irs.stats->rx_errors++; -+ } -+ decap_stat = IPSEC_RCV_BADPROTO; -+ goto rcvleave; -+ } -+ -+ decap_stat = ipsec_rcv_decap_once(&irs, proto_funcs); -+ -+ if(decap_stat != IPSEC_RCV_OK) { -+ spin_unlock(&tdb_lock); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: decap_once failed: %d\n", -+ decap_stat); -+ -+ goto rcvleave; -+ } -+ /* end decapsulation loop here */ -+ } while( (irs.ipp->protocol == IPPROTO_ESP ) -+ || (irs.ipp->protocol == IPPROTO_AH ) -+#ifdef CONFIG_IPSEC_IPCOMP -+ || (irs.ipp->protocol == IPPROTO_COMP) -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ ); -+ -+ /* set up for decap loop */ -+ ipp =irs.ipp; -+ ipsp =irs.ipsp; -+ ipsnext = ipsp->ips_inext; -+ skb = irs.skb; -+ -+ /* if there is an IPCOMP, but we don't have an IPPROTO_COMP, -+ * then we can just skip it -+ */ -+#ifdef CONFIG_IPSEC_IPCOMP -+ if(ipsnext && ipsnext->ips_said.proto == IPPROTO_COMP) { -+ ipsp = ipsnext; -+ ipsnext = ipsp->ips_inext; -+ } -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if ((irs.natt_type) && (ipp->protocol != IPPROTO_IPIP)) { -+ /** -+ * NAT-Traversal and Transport Mode: -+ * we need to correct TCP/UDP checksum -+ * -+ * If we've got NAT-OA, we can fix checksum without recalculation. -+ */ -+ __u32 natt_oa = ipsp->ips_natt_oa ? -+ ((struct sockaddr_in*)(ipsp->ips_natt_oa))->sin_addr.s_addr : 0; -+ __u16 pkt_len = skb->tail - (unsigned char *)ipp; -+ __u16 data_len = pkt_len - (ipp->ihl << 2); -+ -+ switch (ipp->protocol) { -+ case IPPROTO_TCP: -+ if (data_len >= sizeof(struct tcphdr)) { -+ struct tcphdr *tcp = (struct tcphdr *)((__u32 *)ipp+ipp->ihl); -+ if (natt_oa) { -+ __u32 buff[2] = { ~natt_oa, ipp->saddr }; -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: " -+ "fix TCP checksum using NAT-OA\n"); -+ tcp->check = csum_fold( -+ csum_partial((unsigned char *)buff, sizeof(buff), -+ tcp->check^0xffff)); -+ } -+ else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: recalc TCP checksum\n"); -+ if (pkt_len > (ntohs(ipp->tot_len))) -+ data_len -= (pkt_len - ntohs(ipp->tot_len)); -+ tcp->check = 0; -+ tcp->check = csum_tcpudp_magic(ipp->saddr, ipp->daddr, -+ data_len, IPPROTO_TCP, -+ csum_partial((unsigned char *)tcp, data_len, 0)); -+ } -+ } -+ else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: can't fix TCP checksum\n"); -+ } -+ break; -+ case IPPROTO_UDP: -+ if (data_len >= sizeof(struct udphdr)) { -+ struct udphdr *udp = (struct udphdr *)((__u32 *)ipp+ipp->ihl); -+ if (udp->check == 0) { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: UDP checksum already 0\n"); -+ } -+ else if (natt_oa) { -+ __u32 buff[2] = { ~natt_oa, ipp->saddr }; -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: " -+ "fix UDP checksum using NAT-OA\n"); -+ udp->check = csum_fold( -+ csum_partial((unsigned char *)buff, sizeof(buff), -+ udp->check^0xffff)); -+ } -+ else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: zero UDP checksum\n"); -+ udp->check = 0; -+ } -+ } -+ else { -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: can't fix UDP checksum\n"); -+ } -+ break; -+ default: -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "NAT-T & TRANSPORT: non TCP/UDP packet -- do nothing\n"); -+ break; -+ } -+ } -+#endif -+ -+ /* -+ * XXX this needs to be locked from when it was first looked -+ * up in the decapsulation loop. Perhaps it is better to put -+ * the IPIP decap inside the loop. -+ */ -+ if(ipsnext) { -+ ipsp = ipsnext; -+ irs.sa_len = satot(&irs.said, 0, irs.sa, sizeof(irs.sa)); -+ if((ipp->protocol != IPPROTO_IPIP) && -+ ( 0xFE != ipp->protocol)) { /* added to support AT&T heartbeats to SIG/GIG */ -+ spin_unlock(&tdb_lock); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s, Hey! How did this get through? Dropped.\n", -+ irs.sa_len ? irs.sa : " (error)"); -+ if(stats) { -+ stats->rx_dropped++; -+ } -+ goto rcvleave; -+ } -+ if(sysctl_ipsec_inbound_policy_check) { -+ if((ipsnext = ipsp->ips_inext)) { -+ char sa2[SATOT_BUF]; -+ size_t sa_len2; -+ sa_len2 = satot(&ipsnext->ips_said, 0, sa2, sizeof(sa2)); -+ spin_unlock(&tdb_lock); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "unexpected SA:%s after IPIP SA:%s\n", -+ sa_len2 ? sa2 : " (error)", -+ irs.sa_len ? irs.sa : " (error)"); -+ if(stats) { -+ stats->rx_dropped++; -+ } -+ goto rcvleave; -+ } -+ if(ipp->saddr != ((struct sockaddr_in*)(ipsp->ips_addr_s))->sin_addr.s_addr) { -+ spin_unlock(&tdb_lock); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s, src=%s of pkt does not agree with expected SA source address policy.\n", -+ irs.sa_len ? irs.sa : " (error)", -+ irs.ipsaddr_txt); -+ if(stats) { -+ stats->rx_dropped++; -+ } -+ goto rcvleave; -+ } -+ } -+ -+ if(ipp->protocol == IPPROTO_IPIP) /* added to support AT&T heartbeats to SIG/GIG */ -+ { -+ /* -+ * XXX this needs to be locked from when it was first looked -+ * up in the decapsulation loop. Perhaps it is better to put -+ * the IPIP decap inside the loop. -+ */ -+ ipsp->ips_life.ipl_bytes.ipl_count += skb->len; -+ ipsp->ips_life.ipl_bytes.ipl_last = skb->len; -+ -+ if(!ipsp->ips_life.ipl_usetime.ipl_count) { -+ ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ; -+ } -+ ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ; -+ ipsp->ips_life.ipl_packets.ipl_count += 1; -+ -+ if(skb->len < irs.iphlen) { -+ spin_unlock(&tdb_lock); -+ printk(KERN_WARNING "klips_debug:ipsec_rcv: " -+ "tried to skb_pull iphlen=%d, %d available. This should never happen, please report.\n", -+ irs.iphlen, -+ (int)(skb->len)); -+ -+ goto rcvleave; -+ } -+ skb_pull(skb, irs.iphlen); -+ -+#ifdef NET_21 -+ ipp = (struct iphdr *)skb->nh.raw = skb->data; -+ skb->h.raw = skb->nh.raw + (skb->nh.iph->ihl << 2); -+ -+ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); -+#else /* NET_21 */ -+ ipp = skb->ip_hdr = skb->h.iph = (struct iphdr *)skb->data; -+ -+ memset(skb->proto_priv, 0, sizeof(struct options)); -+#endif /* NET_21 */ -+ ipsaddr.s_addr = ipp->saddr; -+ addrtoa(ipsaddr, 0, irs.ipsaddr_txt, sizeof(irs.ipsaddr_txt)); -+ ipdaddr.s_addr = ipp->daddr; -+ addrtoa(ipdaddr, 0, irs.ipdaddr_txt, sizeof(irs.ipdaddr_txt)); -+ -+ skb->protocol = htons(ETH_P_IP); -+ skb->ip_summed = 0; -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "IPIP tunnel stripped.\n"); -+ KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp); -+ } -+ -+ if(sysctl_ipsec_inbound_policy_check -+ /* -+ Note: "xor" (^) logically replaces "not equal" -+ (!=) and "bitwise or" (|) logically replaces -+ "boolean or" (||). This is done to speed up -+ execution by doing only bitwise operations and -+ no branch operations -+ */ -+ && (((ipp->saddr & ipsp->ips_mask_s.u.v4.sin_addr.s_addr) -+ ^ ipsp->ips_flow_s.u.v4.sin_addr.s_addr) -+ | ((ipp->daddr & ipsp->ips_mask_d.u.v4.sin_addr.s_addr) -+ ^ ipsp->ips_flow_d.u.v4.sin_addr.s_addr)) ) -+ { -+ char sflow_txt[SUBNETTOA_BUF], dflow_txt[SUBNETTOA_BUF]; -+ -+ subnettoa(ipsp->ips_flow_s.u.v4.sin_addr, -+ ipsp->ips_mask_s.u.v4.sin_addr, -+ 0, sflow_txt, sizeof(sflow_txt)); -+ subnettoa(ipsp->ips_flow_d.u.v4.sin_addr, -+ ipsp->ips_mask_d.u.v4.sin_addr, -+ 0, dflow_txt, sizeof(dflow_txt)); -+ spin_unlock(&tdb_lock); -+ KLIPS_PRINT(debug_rcv, -+ "klips_debug:ipsec_rcv: " -+ "SA:%s, inner tunnel policy [%s -> %s] does not agree with pkt contents [%s -> %s].\n", -+ irs.sa_len ? irs.sa : " (error)", -+ sflow_txt, -+ dflow_txt, -+ irs.ipsaddr_txt, -+ irs.ipdaddr_txt); -+ if(stats) { -+ stats->rx_dropped++; -+ } -+ goto rcvleave; -+ } -+#ifdef CONFIG_NETFILTER -+ skb->nfmark = (skb->nfmark & (~(IPsecSAref2NFmark(IPSEC_SA_REF_TABLE_MASK)))) -+ | IPsecSAref2NFmark(IPsecSA2SAref(ipsp)); -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "IPIP SA sets skb->nfmark=0x%x.\n", -+ (unsigned)skb->nfmark); -+#endif /* CONFIG_NETFILTER */ -+ } -+ -+ spin_unlock(&tdb_lock); -+ -+#ifdef NET_21 -+ if(stats) { -+ stats->rx_bytes += skb->len; -+ } -+ if(skb->dst) { -+ dst_release(skb->dst); -+ skb->dst = NULL; -+ } -+ skb->pkt_type = PACKET_HOST; -+ if(irs.hard_header_len && -+ (skb->mac.raw != (skb->data - irs.hard_header_len)) && -+ (irs.hard_header_len <= skb_headroom(skb))) { -+ /* copy back original MAC header */ -+ memmove(skb->data - irs.hard_header_len, skb->mac.raw, irs.hard_header_len); -+ skb->mac.raw = skb->data - irs.hard_header_len; -+ } -+#endif /* NET_21 */ -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+ if(ipp->protocol == IPPROTO_COMP) { -+ unsigned int flags = 0; -+ -+ if(sysctl_ipsec_inbound_policy_check) { -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "inbound policy checking enabled, IPCOMP follows IPIP, dropped.\n"); -+ if (stats) { -+ stats->rx_errors++; -+ } -+ goto rcvleave; -+ } -+ /* -+ XXX need a ipsec_sa for updating ratio counters but it is not -+ following policy anyways so it is not a priority -+ */ -+ skb = skb_decompress(skb, NULL, &flags); -+ if (!skb || flags) { -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "skb_decompress() returned error flags: %d, dropped.\n", -+ flags); -+ if (stats) { -+ stats->rx_errors++; -+ } -+ goto rcvleave; -+ } -+ } -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#ifdef SKB_RESET_NFCT -+ nf_conntrack_put(skb->nfct); -+ skb->nfct = NULL; -+#ifdef CONFIG_NETFILTER_DEBUG -+ skb->nf_debug = 0; -+#endif /* CONFIG_NETFILTER_DEBUG */ -+#endif /* SKB_RESET_NFCT */ -+ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, -+ "klips_debug:ipsec_rcv: " -+ "netif_rx() called.\n"); -+ netif_rx(skb); -+ -+ MOD_DEC_USE_COUNT; -+ return(0); -+ -+ rcvleave: -+ if(skb) { -+ ipsec_kfree_skb(skb); -+ } -+ -+ MOD_DEC_USE_COUNT; -+ return(0); -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.143.4.2 2004/08/22 03:29:06 mcr -+ * include udp.h regardless of nat-t support. -+ * -+ * Revision 1.143.4.1 2004/08/21 02:14:58 ken -+ * Patch from Jochen Eisinger for AT&T MTS Heartbeat packet support -+ * -+ * Revision 1.143 2004/05/10 22:27:00 mcr -+ * fix for ESP-3DES-noauth test case. -+ * -+ * Revision 1.142 2004/05/10 22:25:57 mcr -+ * reformat of calls to ipsec_lifetime_check(). -+ * -+ * Revision 1.141 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.140 2004/02/03 03:12:53 mcr -+ * removed erroneously, double patched code. -+ * -+ * Revision 1.139 2004/01/05 23:21:29 mcr -+ * initialize sin_family in ipsec_rcv.c -+ * -+ * Revision 1.138 2003/12/24 19:46:52 mcr -+ * if sock.h patch has not been applied, then define appropriate -+ * structure so we can use it. This is serious inferior, and -+ * depends upon the concept that the structure in question is -+ * smaller than the other members of that union. -+ * getting rid of differing methods is a better solution. -+ * -+ * Revision 1.137 2003/12/22 19:40:57 mcr -+ * NAT-T patches 0.6c. -+ * -+ * Revision 1.136 2003/12/15 18:13:12 mcr -+ * when compiling with NAT traversal, don't assume that the -+ * kernel has been patched, unless CONFIG_IPSEC_NAT_NON_ESP -+ * is set. -+ * -+ * Revision 1.135 2003/12/13 19:10:21 mcr -+ * refactored rcv and xmit code - same as FS 2.05. -+ * -+ * Revision 1.134.2.1 2003/12/22 15:25:52 jjo -+ * Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.134 2003/12/10 01:14:27 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.133 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.132.2.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.132 2003/09/02 19:51:48 mcr -+ * fixes for PR#252. -+ * -+ * Revision 1.131 2003/07/31 22:47:16 mcr -+ * preliminary (untested by FS-team) 2.5 patches. -+ * -+ * Revision 1.130 2003/04/03 17:38:25 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * Clarified logic for non-connected devices. -+ * -+ * Revision 1.129 2003/02/06 02:21:34 rgb -+ * -+ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h . -+ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr". -+ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code. -+ * -+ * Revision 1.128 2002/12/13 20:58:03 rgb -+ * Relegated MCR's recent "_dmp" routine to debug_verbose. -+ * Cleaned up printing of source and destination addresses in debug output. -+ * -+ * Revision 1.127 2002/12/04 16:00:16 rgb -+ * -+ * Fixed AH decapsulation pointer update bug and added some comments and -+ * debugging. -+ * This bug was caught by west-ah-0[12]. -+ * -+ * Revision 1.126 2002/11/04 05:03:43 mcr -+ * fixes for IPCOMP. There were two problems: -+ * 1) the irs->ipp pointer was not being updated properly after -+ * the ESP descryption. The meant nothing for IPIP, as the -+ * later IP header overwrote the earlier one. -+ * 2) the more serious problem was that skb_decompress will -+ * usually allocate a new SKB, so we have to make sure that -+ * it doesn't get lost. -+ * #2 meant removing the skb argument from the ->decrypt routine -+ * and moving it to the irs->skb, so it could be value/result. -+ * -+ * Revision 1.125 2002/11/01 01:53:35 dhr -+ * -+ * fix typo -+ * -+ * Revision 1.124 2002/10/31 22:49:01 dhr -+ * -+ * - eliminate unused variable "hash" -+ * - reduce scope of variable "authenticator" -+ * - add comment on a couple of tricky bits -+ * -+ * Revision 1.123 2002/10/31 22:39:56 dhr -+ * -+ * use correct type for result of function calls -+ * -+ * Revision 1.122 2002/10/31 22:36:25 dhr -+ * -+ * simplify complex test -+ * -+ * Revision 1.121 2002/10/31 22:34:04 dhr -+ * -+ * ipsprev is never used: ditch it -+ * -+ * Revision 1.120 2002/10/31 22:30:21 dhr -+ * -+ * eliminate redundant assignments -+ * -+ * Revision 1.119 2002/10/31 22:27:43 dhr -+ * -+ * make whitespace canonical -+ * -+ * Revision 1.118 2002/10/30 05:47:17 rgb -+ * Fixed cut-and-paste error mis-identifying comp runt as ah. -+ * -+ * Revision 1.117 2002/10/17 16:37:45 rgb -+ * Remove compp intermediate variable and in-line its contents -+ * where used -+ * -+ * Revision 1.116 2002/10/12 23:11:53 dhr -+ * -+ * [KenB + DHR] more 64-bit cleanup -+ * -+ * Revision 1.115 2002/10/07 19:06:58 rgb -+ * Minor fixups and activation to west-rcv-nfmark-set-01 test to check for SA reference properly set on incoming. -+ * -+ * Revision 1.114 2002/10/07 18:31:31 rgb -+ * Set saref on incoming packets. -+ * -+ * Revision 1.113 2002/09/16 21:28:12 mcr -+ * adjust hash length for HMAC calculation - must look at whether -+ * it is MD5 or SHA1. -+ * -+ * Revision 1.112 2002/09/16 21:19:15 mcr -+ * fixes for west-ah-icmp-01 - length of AH header must be -+ * calculated properly, and next_header field properly copied. -+ * -+ * Revision 1.111 2002/09/10 02:45:56 mcr -+ * re-factored the ipsec_rcv function into several functions, -+ * ipsec_rcv_decap_once, and a set of functions for AH, ESP and IPCOMP. -+ * In addition, the MD5 and SHA1 functions are replaced with pointers. -+ * -+ * Revision 1.110 2002/08/30 06:34:33 rgb -+ * Fix scope of shift in AH header length check. -+ * -+ * Revision 1.109 2002/08/27 16:49:20 rgb -+ * Fixed ESP short packet DOS (and AH and IPCOMP). -+ * -+ * Revision 1.108 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.107 2002/05/27 18:58:18 rgb -+ * Convert to dynamic ipsec device allocation. -+ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT. -+ * -+ * Revision 1.106 2002/05/23 07:15:21 rgb -+ * Pointer clean-up. -+ * Added refcount code. -+ * -+ * Revision 1.105 2002/05/14 02:35:06 rgb -+ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips, -+ * ipsec_sa or ipsec_sa. -+ * Change references to _TDB to _IPSA. -+ * -+ * Revision 1.104 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.103 2002/04/24 07:36:30 mcr -+ * Moved from ./klips/net/ipsec/ipsec_rcv.c,v -+ * -+ * Revision 1.102 2002/01/29 17:17:56 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.101 2002/01/29 04:00:52 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.100 2002/01/29 02:13:17 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.99 2002/01/28 21:40:59 mcr -+ * should use #if to test boolean option rather than #ifdef. -+ * -+ * Revision 1.98 2002/01/20 20:19:36 mcr -+ * renamed option to IP_FRAGMENT_LINEARIZE. -+ * -+ * Revision 1.97 2002/01/12 02:55:36 mcr -+ * fix for post-2.4.4 to linearize skb's when ESP packet -+ * was assembled from fragments. -+ * -+ * Revision 1.96 2001/11/26 09:23:49 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.93.2.2 2001/10/22 20:54:07 mcr -+ * include des.h, removed phony prototypes and fixed calling -+ * conventions to match real prototypes. -+ * -+ * Revision 1.93.2.1 2001/09/25 02:22:22 mcr -+ * struct tdb -> struct ipsec_sa. -+ * lifetime checks moved to ipsec_life.c -+ * some sa(tdb) manipulation functions renamed. -+ * -+ * Revision 1.95 2001/11/06 19:49:07 rgb -+ * Added variable descriptions. -+ * Removed unauthenticated sequence==0 check to prevent DoS. -+ * -+ * Revision 1.94 2001/10/18 04:45:20 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.93 2001/09/07 22:17:24 rgb -+ * Fix for removal of transport layer protocol handler arg in 2.4.4. -+ * Fix to accomodate peer non-conformance to IPCOMP rfc2393. -+ * -+ * Revision 1.92 2001/08/27 19:44:41 rgb -+ * Fix error in comment. -+ * -+ * Revision 1.91 2001/07/20 19:31:48 dhr -+ * [DHR] fix source and destination subnets of policy in diagnostic -+ * -+ * Revision 1.90 2001/07/06 19:51:09 rgb -+ * Added inbound policy checking code for IPIP SAs. -+ * Renamed unused function argument for ease and intuitive naming. -+ * -+ * Revision 1.89 2001/06/22 19:35:23 rgb -+ * Disable ipcomp processing if we are handed a ipcomp packet with no esp -+ * or ah header. -+ * Print protocol if we are handed a non-ipsec packet. -+ * -+ * Revision 1.88 2001/06/20 06:30:47 rgb -+ * Fixed transport mode IPCOMP policy check bug. -+ * -+ * Revision 1.87 2001/06/13 20:58:40 rgb -+ * Added parentheses around assignment used as truth value to silence -+ * compiler. -+ * -+ * Revision 1.86 2001/06/07 22:25:23 rgb -+ * Added a source address policy check for tunnel mode. It still does -+ * not check client addresses and masks. -+ * Only decapsulate IPIP if it is expected. -+ * -+ * Revision 1.85 2001/05/30 08:14:02 rgb -+ * Removed vestiges of esp-null transforms. -+ * -+ * Revision 1.84 2001/05/27 06:12:11 rgb -+ * Added structures for pid, packet count and last access time to eroute. -+ * Added packet count to beginning of /proc/net/ipsec_eroute. -+ * -+ * Revision 1.83 2001/05/04 16:45:47 rgb -+ * Remove unneeded code. ipp is not used after this point. -+ * -+ * Revision 1.82 2001/05/04 16:36:00 rgb -+ * Fix skb_cow() call for 2.4.4. (SS) -+ * -+ * Revision 1.81 2001/05/02 14:46:53 rgb -+ * Fix typo for compiler directive to pull IPH back. -+ * -+ * Revision 1.80 2001/04/30 19:46:34 rgb -+ * Update for 2.4.4. We now receive the skb with skb->data pointing to -+ * h.raw. -+ * -+ * Revision 1.79 2001/04/23 15:01:15 rgb -+ * Added spin_lock() check to prevent double-locking for multiple -+ * transforms and hence kernel lock-ups with SMP kernels. -+ * Minor spin_unlock() adjustments to unlock before non-dependant prints -+ * and IPSEC device stats updates. -+ * -+ * Revision 1.78 2001/04/21 23:04:24 rgb -+ * Check if soft expire has already been sent before sending another to -+ * prevent ACQUIRE flooding. -+ * -+ * Revision 1.77 2001/03/16 07:35:20 rgb -+ * Ditch extra #if 1 around now permanent policy checking code. -+ * -+ * Revision 1.76 2001/02/27 22:24:54 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.75 2001/02/19 22:28:30 rgb -+ * Minor change to virtual device discovery code to assert which I/F has -+ * been found. -+ * -+ * Revision 1.74 2000/11/25 03:50:36 rgb -+ * Oops fix by minor re-arrangement of code to avoid accessing a freed tdb. -+ * -+ * Revision 1.73 2000/11/09 20:52:15 rgb -+ * More spinlock shuffling, locking earlier and unlocking later in rcv to -+ * include ipcomp and prevent races, renaming some tdb variables that got -+ * forgotten, moving some unlocks to include tdbs and adding a missing -+ * unlock. Thanks to Svenning for some of these. -+ * -+ * Revision 1.72 2000/11/09 20:11:22 rgb -+ * Minor shuffles to fix non-standard kernel config option selection. -+ * -+ * Revision 1.71 2000/11/06 04:36:18 rgb -+ * Ditched spin_lock_irqsave in favour of spin_lock. -+ * Minor initial protocol check rewrite. -+ * Clean up debug printing. -+ * Clean up tdb handling on ipcomp. -+ * Fixed transport mode null pointer de-reference without ipcomp. -+ * Add Svenning's adaptive content compression. -+ * Disabled registration of ipcomp handler. -+ * -+ * Revision 1.70 2000/10/30 23:41:43 henry -+ * Hans-Joerg Hoexer's null-pointer fix -+ * -+ * Revision 1.69 2000/10/10 18:54:16 rgb -+ * Added a fix for incoming policy check with ipcomp enabled but -+ * uncompressible. -+ * -+ * Revision 1.68 2000/09/22 17:53:12 rgb -+ * Fixed ipcomp tdb pointers update for policy checking. -+ * -+ * Revision 1.67 2000/09/21 03:40:58 rgb -+ * Added more debugging to try and track down the cpi outward copy problem. -+ * -+ * Revision 1.66 2000/09/20 04:00:10 rgb -+ * Changed static functions to DEBUG_NO_STATIC to reveal function names for -+ * debugging oopsen. -+ * -+ * Revision 1.65 2000/09/19 07:07:16 rgb -+ * Added debugging to inbound policy check for ipcomp. -+ * Added missing spin_unlocks (thanks Svenning!). -+ * Fixed misplaced tdbnext pointers causing mismatched ipip policy check. -+ * Protect ipcomp policy check following ipip decap with sysctl switch. -+ * -+ * Revision 1.64 2000/09/18 21:27:29 rgb -+ * 2.0 fixes. -+ * -+ * Revision 1.63 2000/09/18 02:35:50 rgb -+ * Added policy checking to ipcomp and re-enabled policy checking by -+ * default. -+ * Optimised satoa calls. -+ * -+ * Revision 1.62 2000/09/17 21:02:32 rgb -+ * Clean up debugging, removing slow timestamp debug code. -+ * -+ * Revision 1.61 2000/09/16 01:07:55 rgb -+ * Fixed erroneous ref from struct ipcomp to struct ipcomphdr. -+ * -+ * Revision 1.60 2000/09/15 11:37:01 rgb -+ * Merge in heavily modified Svenning Soerensen's -+ * IPCOMP zlib deflate code. -+ * -+ * Revision 1.59 2000/09/15 04:56:20 rgb -+ * Remove redundant satoa() call, reformat comment. -+ * -+ * Revision 1.58 2000/09/13 08:00:52 rgb -+ * Flick on inbound policy checking. -+ * -+ * Revision 1.57 2000/09/12 03:22:19 rgb -+ * Converted inbound_policy_check to sysctl. -+ * Re-enabled policy backcheck. -+ * Moved policy checks to top and within tdb lock. -+ * -+ * Revision 1.56 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.55 2000/08/28 18:15:46 rgb -+ * Added MB's nf-debug reset patch. -+ * -+ * Revision 1.54 2000/08/27 01:41:26 rgb -+ * More minor tweaks to the bad padding debug code. -+ * -+ * Revision 1.53 2000/08/24 16:54:16 rgb -+ * Added KLIPS_PRINTMORE macro to continue lines without KERN_INFO level -+ * info. -+ * Tidied up device reporting at the start of ipsec_rcv. -+ * Tidied up bad padding debugging and processing. -+ * -+ * Revision 1.52 2000/08/20 21:36:03 rgb -+ * Activated pfkey_expire() calls. -+ * Added a hard/soft expiry parameter to pfkey_expire(). -+ * Added sanity checking to avoid propagating zero or smaller-length skbs -+ * from a bogus decryption. -+ * Re-arranged the order of soft and hard expiry to conform to RFC2367. -+ * Clean up references to CONFIG_IPSEC_PFKEYv2. -+ * -+ * Revision 1.51 2000/08/18 21:23:30 rgb -+ * Improve bad padding warning so that the printk buffer doesn't get -+ * trampled. -+ * -+ * Revision 1.50 2000/08/01 14:51:51 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.49 2000/07/28 13:50:53 rgb -+ * Changed enet_statistics to net_device_stats and added back compatibility -+ * for pre-2.1.19. -+ * -+ * Revision 1.48 2000/05/10 19:14:40 rgb -+ * Only check usetime against soft and hard limits if the tdb has been -+ * used. -+ * Cast output of ntohl so that the broken prototype doesn't make our -+ * compile noisy. -+ * -+ * Revision 1.47 2000/05/09 17:45:43 rgb -+ * Fix replay bitmap corruption bug upon receipt of bogus packet -+ * with correct SPI. This was a DoS. -+ * -+ * Revision 1.46 2000/03/27 02:31:58 rgb -+ * Fixed authentication failure printout bug. -+ * -+ * Revision 1.45 2000/03/22 16:15:37 rgb -+ * Fixed renaming of dev_get (MB). -+ * -+ * Revision 1.44 2000/03/16 08:17:24 rgb -+ * Hardcode PF_KEYv2 support. -+ * Fixed minor bug checking AH header length. -+ * -+ * Revision 1.43 2000/03/14 12:26:59 rgb -+ * Added skb->nfct support for clearing netfilter conntrack bits (MB). -+ * -+ * Revision 1.42 2000/01/26 10:04:04 rgb -+ * Fixed inbound policy checking on transport mode bug. -+ * Fixed noisy 2.0 printk arguments. -+ * -+ * Revision 1.41 2000/01/24 20:58:02 rgb -+ * Improve debugging/reporting support for (disabled) inbound -+ * policy checking. -+ * -+ * Revision 1.40 2000/01/22 23:20:10 rgb -+ * Fixed up inboud policy checking code. -+ * Cleaned out unused crud. -+ * -+ * Revision 1.39 2000/01/21 06:15:29 rgb -+ * Added sanity checks on skb_push(), skb_pull() to prevent panics. -+ * Fixed cut-and-paste debug_tunnel to debug_rcv. -+ * Added inbound policy checking code, disabled. -+ * Simplified output code by updating ipp to post-IPIP decapsulation. -+ * -+ * elided pre-2000 comments. Use "cvs log" -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_sa.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1383 @@ -+/* -+ * Common routines for IPsec SA maintenance routines. -+ * -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ * -+ * This is the file formerly known as "ipsec_xform.h" -+ * -+ */ -+ -+#include -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* vmalloc() */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include -+#ifdef SPINLOCK -+#ifdef SPINLOCK_23 -+#include /* *lock* */ -+#else /* SPINLOCK_23 */ -+#include /* *lock* */ -+#endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+#include -+#include -+#endif -+#include -+#include -+ -+#include "openswan/radij.h" -+ -+#include "openswan/ipsec_stats.h" -+#include "openswan/ipsec_life.h" -+#include "openswan/ipsec_sa.h" -+#include "openswan/ipsec_xform.h" -+ -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_ipe4.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+#include "openswan/ipsec_alg.h" -+ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_xform = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) -+ -+struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD]; -+#ifdef SPINLOCK -+spinlock_t tdb_lock = SPIN_LOCK_UNLOCKED; -+#else /* SPINLOCK */ -+spinlock_t tdb_lock; -+#endif /* SPINLOCK */ -+ -+struct ipsec_sadb ipsec_sadb; -+ -+#if IPSEC_SA_REF_CODE -+ -+/* the sub table must be narrower (or equal) in bits than the variable type -+ in the main table to count the number of unused entries in it. */ -+typedef struct { -+ int testSizeOf_refSubTable : -+ ((sizeof(IPsecRefTableUnusedCount) * 8) < IPSEC_SA_REF_SUBTABLE_IDX_WIDTH ? -1 : 1); -+} dummy; -+ -+ -+/* The field where the saref will be hosted in the skb must be wide enough to -+ accomodate the information it needs to store. */ -+typedef struct { -+ int testSizeOf_refField : -+ (IPSEC_SA_REF_HOST_FIELD_WIDTH < IPSEC_SA_REF_TABLE_IDX_WIDTH ? -1 : 1 ); -+} dummy2; -+ -+ -+#define IPS_HASH(said) (((said)->spi + (said)->dst.u.v4.sin_addr.s_addr + (said)->proto) % SADB_HASHMOD) -+ -+ -+void -+ipsec_SAtest(void) -+{ -+ IPsecSAref_t SAref = 258; -+ struct ipsec_sa ips; -+ ips.ips_ref = 772; -+ -+ printk("klips_debug:ipsec_SAtest: " -+ "IPSEC_SA_REF_SUBTABLE_IDX_WIDTH=%u\n" -+ "IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES=%u\n" -+ "IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES=%u\n" -+ "IPSEC_SA_REF_HOST_FIELD_WIDTH=%lu\n" -+ "IPSEC_SA_REF_TABLE_MASK=%x\n" -+ "IPSEC_SA_REF_ENTRY_MASK=%x\n" -+ "IPsecSAref2table(%d)=%u\n" -+ "IPsecSAref2entry(%d)=%u\n" -+ "IPsecSAref2NFmark(%d)=%u\n" -+ "IPsecSAref2SA(%d)=%p\n" -+ "IPsecSA2SAref(%p)=%d\n" -+ , -+ IPSEC_SA_REF_SUBTABLE_IDX_WIDTH, -+ IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES, -+ IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES, -+ (unsigned long) IPSEC_SA_REF_HOST_FIELD_WIDTH, -+ IPSEC_SA_REF_TABLE_MASK, -+ IPSEC_SA_REF_ENTRY_MASK, -+ SAref, IPsecSAref2table(SAref), -+ SAref, IPsecSAref2entry(SAref), -+ SAref, IPsecSAref2NFmark(SAref), -+ SAref, IPsecSAref2SA(SAref), -+ (&ips), IPsecSA2SAref((&ips)) -+ ); -+ return; -+} -+ -+int -+ipsec_SAref_recycle(void) -+{ -+ int table; -+ int entry; -+ int error = 0; -+ -+ ipsec_sadb.refFreeListHead = -1; -+ ipsec_sadb.refFreeListTail = -1; -+ -+ if(ipsec_sadb.refFreeListCont == IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES * IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_recycle: " -+ "end of table reached, continuing at start..\n"); -+ ipsec_sadb.refFreeListCont = 0; -+ } -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_recycle: " -+ "recycling, continuing from SAref=%d (0p%p), table=%d, entry=%d.\n", -+ ipsec_sadb.refFreeListCont, -+ (ipsec_sadb.refTable[IPsecSAref2table(ipsec_sadb.refFreeListCont)] != NULL) ? IPsecSAref2SA(ipsec_sadb.refFreeListCont) : NULL, -+ IPsecSAref2table(ipsec_sadb.refFreeListCont), -+ IPsecSAref2entry(ipsec_sadb.refFreeListCont)); -+ -+ for(table = IPsecSAref2table(ipsec_sadb.refFreeListCont); -+ table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; -+ table++) { -+ if(ipsec_sadb.refTable[table] == NULL) { -+ error = ipsec_SArefSubTable_alloc(table); -+ if(error) { -+ return error; -+ } -+ } -+ for(entry = IPsecSAref2entry(ipsec_sadb.refFreeListCont); -+ entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; -+ entry++) { -+ if(ipsec_sadb.refTable[table]->entry[entry] == NULL) { -+ ipsec_sadb.refFreeList[++ipsec_sadb.refFreeListTail] = IPsecSArefBuild(table, entry); -+ if(ipsec_sadb.refFreeListTail == (IPSEC_SA_REF_FREELIST_NUM_ENTRIES - 1)) { -+ ipsec_sadb.refFreeListHead = 0; -+ ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListTail] + 1; -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_recycle: " -+ "SArefFreeList refilled.\n"); -+ return 0; -+ } -+ } -+ } -+ } -+ -+ if(ipsec_sadb.refFreeListTail == -1) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_recycle: " -+ "out of room in the SArefTable.\n"); -+ -+ return(-ENOSPC); -+ } -+ -+ ipsec_sadb.refFreeListHead = 0; -+ ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListTail] + 1; -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_recycle: " -+ "SArefFreeList partly refilled to %d of %d.\n", -+ ipsec_sadb.refFreeListTail, -+ IPSEC_SA_REF_FREELIST_NUM_ENTRIES); -+ return 0; -+} -+ -+int -+ipsec_SArefSubTable_alloc(unsigned table) -+{ -+ unsigned entry; -+ struct IPsecSArefSubTable* SArefsub; -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SArefSubTable_alloc: " -+ "allocating %lu bytes for table %u of %u.\n", -+ (unsigned long) (IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES * sizeof(struct ipsec_sa *)), -+ table, -+ IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES); -+ -+ /* allocate another sub-table */ -+ SArefsub = vmalloc(IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES * sizeof(struct ipsec_sa *)); -+ if(SArefsub == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SArefSubTable_alloc: " -+ "error allocating memory for table %u of %u!\n", -+ table, -+ IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES); -+ return -ENOMEM; -+ } -+ -+ /* add this sub-table to the main table */ -+ ipsec_sadb.refTable[table] = SArefsub; -+ -+ /* initialise each element to NULL */ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SArefSubTable_alloc: " -+ "initialising %u elements (2 ^ %u) of table %u.\n", -+ IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES, -+ IPSEC_SA_REF_SUBTABLE_IDX_WIDTH, -+ table); -+ for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { -+ SArefsub->entry[entry] = NULL; -+ } -+ -+ return 0; -+} -+#endif /* IPSEC_SA_REF_CODE */ -+ -+int -+ipsec_saref_freelist_init(void) -+{ -+ int i; -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_saref_freelist_init: " -+ "initialising %u elements of FreeList.\n", -+ IPSEC_SA_REF_FREELIST_NUM_ENTRIES); -+ -+ for(i = 0; i < IPSEC_SA_REF_FREELIST_NUM_ENTRIES; i++) { -+ ipsec_sadb.refFreeList[i] = IPSEC_SAREF_NULL; -+ } -+ ipsec_sadb.refFreeListHead = -1; -+ ipsec_sadb.refFreeListCont = 0; -+ ipsec_sadb.refFreeListTail = -1; -+ -+ return 0; -+} -+ -+int -+ipsec_sadb_init(void) -+{ -+ int error = 0; -+ unsigned i; -+ -+ for(i = 0; i < SADB_HASHMOD; i++) { -+ ipsec_sadb_hash[i] = NULL; -+ } -+ /* parts above are for the old style SADB hash table */ -+ -+ -+#if IPSEC_SA_REF_CODE -+ /* initialise SA reference table */ -+ -+ /* initialise the main table */ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_init: " -+ "initialising main table of size %u (2 ^ %u).\n", -+ IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES, -+ IPSEC_SA_REF_MAINTABLE_IDX_WIDTH); -+ { -+ unsigned table; -+ for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { -+ ipsec_sadb.refTable[table] = NULL; -+ } -+ } -+ -+ /* allocate the first sub-table */ -+ error = ipsec_SArefSubTable_alloc(0); -+ if(error) { -+ return error; -+ } -+ -+ error = ipsec_saref_freelist_init(); -+#endif /* IPSEC_SA_REF_CODE */ -+ return error; -+} -+ -+#if IPSEC_SA_REF_CODE -+IPsecSAref_t -+ipsec_SAref_alloc(int*error) /* pass in error var by pointer */ -+{ -+ IPsecSAref_t SAref; -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_alloc: " -+ "SAref requested... head=%d, cont=%d, tail=%d, listsize=%d.\n", -+ ipsec_sadb.refFreeListHead, -+ ipsec_sadb.refFreeListCont, -+ ipsec_sadb.refFreeListTail, -+ IPSEC_SA_REF_FREELIST_NUM_ENTRIES); -+ -+ if(ipsec_sadb.refFreeListHead == -1) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_alloc: " -+ "FreeList empty, recycling...\n"); -+ *error = ipsec_SAref_recycle(); -+ if(*error) { -+ return IPSEC_SAREF_NULL; -+ } -+ } -+ -+ SAref = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListHead]; -+ if(SAref == IPSEC_SAREF_NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_alloc: " -+ "unexpected error, refFreeListHead = %d points to invalid entry.\n", -+ ipsec_sadb.refFreeListHead); -+ *error = -ESPIPE; -+ return IPSEC_SAREF_NULL; -+ } -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_alloc: " -+ "allocating SAref=%d, table=%u, entry=%u of %u.\n", -+ SAref, -+ IPsecSAref2table(SAref), -+ IPsecSAref2entry(SAref), -+ IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES * IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES); -+ -+ ipsec_sadb.refFreeList[ipsec_sadb.refFreeListHead] = IPSEC_SAREF_NULL; -+ ipsec_sadb.refFreeListHead++; -+ if(ipsec_sadb.refFreeListHead > ipsec_sadb.refFreeListTail) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_SAref_alloc: " -+ "last FreeList entry allocated, resetting list head to empty.\n"); -+ ipsec_sadb.refFreeListHead = -1; -+ } -+ -+ return SAref; -+} -+#endif /* IPSEC_SA_REF_CODE */ -+ -+int -+ipsec_sa_print(struct ipsec_sa *ips) -+{ -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ printk(KERN_INFO "klips_debug: SA:"); -+ if(ips == NULL) { -+ printk("NULL\n"); -+ return -ENOENT; -+ } -+ printk(" ref=%d", ips->ips_ref); -+ printk(" refcount=%d", atomic_read(&ips->ips_refcount)); -+ if(ips->ips_hnext != NULL) { -+ printk(" hnext=0p%p", ips->ips_hnext); -+ } -+ if(ips->ips_inext != NULL) { -+ printk(" inext=0p%p", ips->ips_inext); -+ } -+ if(ips->ips_onext != NULL) { -+ printk(" onext=0p%p", ips->ips_onext); -+ } -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ printk(" said=%s", sa_len ? sa : " (error)"); -+ if(ips->ips_seq) { -+ printk(" seq=%u", ips->ips_seq); -+ } -+ if(ips->ips_pid) { -+ printk(" pid=%u", ips->ips_pid); -+ } -+ if(ips->ips_authalg) { -+ printk(" authalg=%u", ips->ips_authalg); -+ } -+ if(ips->ips_encalg) { -+ printk(" encalg=%u", ips->ips_encalg); -+ } -+ printk(" XFORM=%s%s%s", IPS_XFORM_NAME(ips)); -+ if(ips->ips_replaywin) { -+ printk(" ooowin=%u", ips->ips_replaywin); -+ } -+ if(ips->ips_flags) { -+ printk(" flags=%u", ips->ips_flags); -+ } -+ if(ips->ips_addr_s) { -+ char buf[SUBNETTOA_BUF]; -+ addrtoa(((struct sockaddr_in*)(ips->ips_addr_s))->sin_addr, -+ 0, buf, sizeof(buf)); -+ printk(" src=%s", buf); -+ } -+ if(ips->ips_addr_d) { -+ char buf[SUBNETTOA_BUF]; -+ addrtoa(((struct sockaddr_in*)(ips->ips_addr_s))->sin_addr, -+ 0, buf, sizeof(buf)); -+ printk(" dst=%s", buf); -+ } -+ if(ips->ips_addr_p) { -+ char buf[SUBNETTOA_BUF]; -+ addrtoa(((struct sockaddr_in*)(ips->ips_addr_p))->sin_addr, -+ 0, buf, sizeof(buf)); -+ printk(" proxy=%s", buf); -+ } -+ if(ips->ips_key_bits_a) { -+ printk(" key_bits_a=%u", ips->ips_key_bits_a); -+ } -+ if(ips->ips_key_bits_e) { -+ printk(" key_bits_e=%u", ips->ips_key_bits_e); -+ } -+ -+ printk("\n"); -+ return 0; -+} -+ -+struct ipsec_sa* -+ipsec_sa_alloc(int*error) /* pass in error var by pointer */ -+{ -+ struct ipsec_sa* ips; -+ -+ if((ips = kmalloc(sizeof(*ips), GFP_ATOMIC) ) == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_alloc: " -+ "memory allocation error\n"); -+ *error = -ENOMEM; -+ return NULL; -+ } -+ memset((caddr_t)ips, 0, sizeof(*ips)); -+#if IPSEC_SA_REF_CODE -+ ips->ips_ref = ipsec_SAref_alloc(error); /* pass in error return by pointer */ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_alloc: " -+ "allocated %lu bytes for ipsec_sa struct=0p%p ref=%d.\n", -+ (unsigned long) sizeof(*ips), -+ ips, -+ ips->ips_ref); -+ if(ips->ips_ref == IPSEC_SAREF_NULL) { -+ kfree(ips); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_alloc: " -+ "SAref allocation error\n"); -+ return NULL; -+ } -+ -+ atomic_inc(&ips->ips_refcount); -+ IPsecSAref2SA(ips->ips_ref) = ips; -+#endif /* IPSEC_SA_REF_CODE */ -+ -+ *error = 0; -+ return(ips); -+} -+ -+int -+ipsec_sa_free(struct ipsec_sa* ips) -+{ -+ return ipsec_sa_wipe(ips); -+} -+ -+struct ipsec_sa * -+ipsec_sa_getbyid(ip_said *said) -+{ -+ int hashval; -+ struct ipsec_sa *ips; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ if(said == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_error:ipsec_sa_getbyid: " -+ "null pointer passed in!\n"); -+ return NULL; -+ } -+ -+ sa_len = satot(said, 0, sa, sizeof(sa)); -+ -+ hashval = IPS_HASH(said); -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_getbyid: " -+ "linked entry in ipsec_sa table for hash=%d of SA:%s requested.\n", -+ hashval, -+ sa_len ? sa : " (error)"); -+ -+ if((ips = ipsec_sadb_hash[hashval]) == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_getbyid: " -+ "no entries in ipsec_sa table for hash=%d of SA:%s.\n", -+ hashval, -+ sa_len ? sa : " (error)"); -+ return NULL; -+ } -+ -+ for (; ips; ips = ips->ips_hnext) { -+ if ((ips->ips_said.spi == said->spi) && -+ (ips->ips_said.dst.u.v4.sin_addr.s_addr == said->dst.u.v4.sin_addr.s_addr) && -+ (ips->ips_said.proto == said->proto)) { -+ atomic_inc(&ips->ips_refcount); -+ return ips; -+ } -+ } -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_getbyid: " -+ "no entry in linked list for hash=%d of SA:%s.\n", -+ hashval, -+ sa_len ? sa : " (error)"); -+ return NULL; -+} -+ -+int -+ipsec_sa_put(struct ipsec_sa *ips) -+{ -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ if(ips == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_error:ipsec_sa_put: " -+ "null pointer passed in!\n"); -+ return -1; -+ } -+ -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_put: " -+ "ipsec_sa SA:%s, ref:%d reference count decremented.\n", -+ sa_len ? sa : " (error)", -+ ips->ips_ref); -+ -+ atomic_dec(&ips->ips_refcount); -+ -+ return 0; -+} -+ -+/* -+ The ipsec_sa table better *NOT* be locked before it is handed in, or SMP locks will happen -+*/ -+int -+ipsec_sa_add(struct ipsec_sa *ips) -+{ -+ int error = 0; -+ unsigned int hashval; -+ -+ if(ips == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_error:ipsec_sa_add: " -+ "null pointer passed in!\n"); -+ return -ENODATA; -+ } -+ hashval = IPS_HASH(&ips->ips_said); -+ -+ atomic_inc(&ips->ips_refcount); -+ spin_lock_bh(&tdb_lock); -+ -+ ips->ips_hnext = ipsec_sadb_hash[hashval]; -+ ipsec_sadb_hash[hashval] = ips; -+ -+ spin_unlock_bh(&tdb_lock); -+ -+ return error; -+} -+ -+/* -+ The ipsec_sa table better be locked before it is handed in, or races might happen -+*/ -+int -+ipsec_sa_del(struct ipsec_sa *ips) -+{ -+ unsigned int hashval; -+ struct ipsec_sa *ipstp; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ if(ips == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_error:ipsec_sa_del: " -+ "null pointer passed in!\n"); -+ return -ENODATA; -+ } -+ -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ if(ips->ips_inext || ips->ips_onext) { -+ KLIPS_PRINT(debug_xform, -+ "klips_error:ipsec_sa_del: " -+ "SA:%s still linked!\n", -+ sa_len ? sa : " (error)"); -+ return -EMLINK; -+ } -+ -+ hashval = IPS_HASH(&ips->ips_said); -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_del: " -+ "deleting SA:%s, hashval=%d.\n", -+ sa_len ? sa : " (error)", -+ hashval); -+ if(ipsec_sadb_hash[hashval] == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_del: " -+ "no entries in ipsec_sa table for hash=%d of SA:%s.\n", -+ hashval, -+ sa_len ? sa : " (error)"); -+ return -ENOENT; -+ } -+ -+ if (ips == ipsec_sadb_hash[hashval]) { -+ ipsec_sadb_hash[hashval] = ipsec_sadb_hash[hashval]->ips_hnext; -+ ips->ips_hnext = NULL; -+ atomic_dec(&ips->ips_refcount); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_del: " -+ "successfully deleted first ipsec_sa in chain.\n"); -+ return 0; -+ } else { -+ for (ipstp = ipsec_sadb_hash[hashval]; -+ ipstp; -+ ipstp = ipstp->ips_hnext) { -+ if (ipstp->ips_hnext == ips) { -+ ipstp->ips_hnext = ips->ips_hnext; -+ ips->ips_hnext = NULL; -+ atomic_dec(&ips->ips_refcount); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_del: " -+ "successfully deleted link in ipsec_sa chain.\n"); -+ return 0; -+ } -+ } -+ } -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_del: " -+ "no entries in linked list for hash=%d of SA:%s.\n", -+ hashval, -+ sa_len ? sa : " (error)"); -+ return -ENOENT; -+} -+ -+/* -+ The ipsec_sa table better be locked before it is handed in, or races -+ might happen -+*/ -+int -+ipsec_sa_delchain(struct ipsec_sa *ips) -+{ -+ struct ipsec_sa *ipsdel; -+ int error = 0; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ if(ips == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_error:ipsec_sa_delchain: " -+ "null pointer passed in!\n"); -+ return -ENODATA; -+ } -+ -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_delchain: " -+ "passed SA:%s\n", -+ sa_len ? sa : " (error)"); -+ while(ips->ips_onext != NULL) { -+ ips = ips->ips_onext; -+ } -+ -+ while(ips) { -+ /* XXX send a pfkey message up to advise of deleted ipsec_sa */ -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_delchain: " -+ "unlinking and delting SA:%s", -+ sa_len ? sa : " (error)"); -+ ipsdel = ips; -+ ips = ips->ips_inext; -+ if(ips != NULL) { -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ ", inext=%s", -+ sa_len ? sa : " (error)"); -+ atomic_dec(&ipsdel->ips_refcount); -+ ipsdel->ips_inext = NULL; -+ atomic_dec(&ips->ips_refcount); -+ ips->ips_onext = NULL; -+ } -+ KLIPS_PRINT(debug_xform, -+ ".\n"); -+ if((error = ipsec_sa_del(ipsdel))) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_delchain: " -+ "ipsec_sa_del returned error %d.\n", -error); -+ return error; -+ } -+ if((error = ipsec_sa_wipe(ipsdel))) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_delchain: " -+ "ipsec_sa_wipe returned error %d.\n", -error); -+ return error; -+ } -+ } -+ return error; -+} -+ -+int -+ipsec_sadb_cleanup(__u8 proto) -+{ -+ unsigned i; -+ int error = 0; -+ struct ipsec_sa *ips, **ipsprev, *ipsdel; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_cleanup: " -+ "cleaning up proto=%d.\n", -+ proto); -+ -+ spin_lock_bh(&tdb_lock); -+ -+ for (i = 0; i < SADB_HASHMOD; i++) { -+ ipsprev = &(ipsec_sadb_hash[i]); -+ ips = ipsec_sadb_hash[i]; -+ if(ips != NULL) { -+ atomic_inc(&ips->ips_refcount); -+ } -+ for(; ips != NULL;) { -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_cleanup: " -+ "checking SA:%s, hash=%d, ref=%d", -+ sa_len ? sa : " (error)", -+ i, -+ ips->ips_ref); -+ ipsdel = ips; -+ ips = ipsdel->ips_hnext; -+ if(ips != NULL) { -+ atomic_inc(&ips->ips_refcount); -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ ", hnext=%s", -+ sa_len ? sa : " (error)"); -+ } -+ if(*ipsprev != NULL) { -+ sa_len = satot(&(*ipsprev)->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ ", *ipsprev=%s", -+ sa_len ? sa : " (error)"); -+ if((*ipsprev)->ips_hnext) { -+ sa_len = satot(&(*ipsprev)->ips_hnext->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ ", *ipsprev->ips_hnext=%s", -+ sa_len ? sa : " (error)"); -+ } -+ } -+ KLIPS_PRINT(debug_xform, -+ ".\n"); -+ if(proto == 0 || (proto == ipsdel->ips_said.proto)) { -+ sa_len = satot(&ipsdel->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_cleanup: " -+ "deleting SA chain:%s.\n", -+ sa_len ? sa : " (error)"); -+ if((error = ipsec_sa_delchain(ipsdel))) { -+ SENDERR(-error); -+ } -+ ipsprev = &(ipsec_sadb_hash[i]); -+ ips = ipsec_sadb_hash[i]; -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_cleanup: " -+ "deleted SA chain:%s", -+ sa_len ? sa : " (error)"); -+ if(ips != NULL) { -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ ", ipsec_sadb_hash[%d]=%s", -+ i, -+ sa_len ? sa : " (error)"); -+ } -+ if(*ipsprev != NULL) { -+ sa_len = satot(&(*ipsprev)->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ ", *ipsprev=%s", -+ sa_len ? sa : " (error)"); -+ if((*ipsprev)->ips_hnext != NULL) { -+ sa_len = satot(&(*ipsprev)->ips_hnext->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ ", *ipsprev->ips_hnext=%s", -+ sa_len ? sa : " (error)"); -+ } -+ } -+ KLIPS_PRINT(debug_xform, -+ ".\n"); -+ } else { -+ ipsprev = &ipsdel; -+ } -+ if(ipsdel != NULL) { -+ ipsec_sa_put(ipsdel); -+ } -+ } -+ } -+ errlab: -+ -+ spin_unlock_bh(&tdb_lock); -+ -+ -+#if IPSEC_SA_REF_CODE -+ /* clean up SA reference table */ -+ -+ /* go through the ref table and clean out all the SAs */ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_cleanup: " -+ "removing SAref entries and tables."); -+ { -+ unsigned table, entry; -+ for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_cleanup: " -+ "cleaning SAref table=%u.\n", -+ table); -+ if(ipsec_sadb.refTable[table] == NULL) { -+ printk("\n"); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_cleanup: " -+ "cleaned %u used refTables.\n", -+ table); -+ break; -+ } -+ for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { -+ if(ipsec_sadb.refTable[table]->entry[entry] != NULL) { -+ ipsec_sa_delchain(ipsec_sadb.refTable[table]->entry[entry]); -+ ipsec_sadb.refTable[table]->entry[entry] = NULL; -+ } -+ } -+ } -+ } -+#endif /* IPSEC_SA_REF_CODE */ -+ -+ return(error); -+} -+ -+int -+ipsec_sadb_free(void) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_free: " -+ "freeing SArefTable memory.\n"); -+ -+ /* clean up SA reference table */ -+ -+ /* go through the ref table and clean out all the SAs if any are -+ left and free table memory */ -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_free: " -+ "removing SAref entries and tables.\n"); -+ { -+ unsigned table, entry; -+ for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_free: " -+ "removing SAref table=%u.\n", -+ table); -+ if(ipsec_sadb.refTable[table] == NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sadb_free: " -+ "removed %u used refTables.\n", -+ table); -+ break; -+ } -+ for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { -+ if(ipsec_sadb.refTable[table]->entry[entry] != NULL) { -+ ipsec_sa_delchain(ipsec_sadb.refTable[table]->entry[entry]); -+ ipsec_sadb.refTable[table]->entry[entry] = NULL; -+ } -+ } -+ vfree(ipsec_sadb.refTable[table]); -+ ipsec_sadb.refTable[table] = NULL; -+ } -+ } -+ -+ return(error); -+} -+ -+int -+ipsec_sa_wipe(struct ipsec_sa *ips) -+{ -+ if(ips == NULL) { -+ return -ENODATA; -+ } -+ -+ /* if(atomic_dec_and_test(ips)) { -+ }; */ -+ -+#if IPSEC_SA_REF_CODE -+ /* remove me from the SArefTable */ -+ { -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa)); -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_wipe: " -+ "removing SA=%s(0p%p), SAref=%d, table=%d(0p%p), entry=%d from the refTable.\n", -+ sa_len ? sa : " (error)", -+ ips, -+ ips->ips_ref, -+ IPsecSAref2table(IPsecSA2SAref(ips)), -+ ipsec_sadb.refTable[IPsecSAref2table(IPsecSA2SAref(ips))], -+ IPsecSAref2entry(IPsecSA2SAref(ips))); -+ } -+ if(ips->ips_ref == IPSEC_SAREF_NULL) { -+ KLIPS_PRINT(debug_xform, -+ "klips_debug:ipsec_sa_wipe: " -+ "why does this SA not have a valid SAref?.\n"); -+ } -+ ipsec_sadb.refTable[IPsecSAref2table(IPsecSA2SAref(ips))]->entry[IPsecSAref2entry(IPsecSA2SAref(ips))] = NULL; -+ ips->ips_ref = IPSEC_SAREF_NULL; -+ ipsec_sa_put(ips); -+#endif /* IPSEC_SA_REF_CODE */ -+ -+ /* paranoid clean up */ -+ if(ips->ips_addr_s != NULL) { -+ memset((caddr_t)(ips->ips_addr_s), 0, ips->ips_addr_s_size); -+ kfree(ips->ips_addr_s); -+ } -+ ips->ips_addr_s = NULL; -+ -+ if(ips->ips_addr_d != NULL) { -+ memset((caddr_t)(ips->ips_addr_d), 0, ips->ips_addr_d_size); -+ kfree(ips->ips_addr_d); -+ } -+ ips->ips_addr_d = NULL; -+ -+ if(ips->ips_addr_p != NULL) { -+ memset((caddr_t)(ips->ips_addr_p), 0, ips->ips_addr_p_size); -+ kfree(ips->ips_addr_p); -+ } -+ ips->ips_addr_p = NULL; -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if(ips->ips_natt_oa) { -+ memset((caddr_t)(ips->ips_natt_oa), 0, ips->ips_natt_oa_size); -+ kfree(ips->ips_natt_oa); -+ } -+ ips->ips_natt_oa = NULL; -+#endif -+ -+ if(ips->ips_key_a != NULL) { -+ memset((caddr_t)(ips->ips_key_a), 0, ips->ips_key_a_size); -+ kfree(ips->ips_key_a); -+ } -+ ips->ips_key_a = NULL; -+ -+ if(ips->ips_key_e != NULL) { -+#ifdef CONFIG_IPSEC_ALG -+ if (ips->ips_alg_enc&&ips->ips_alg_enc->ixt_e_destroy_key) { -+ ips->ips_alg_enc->ixt_e_destroy_key(ips->ips_alg_enc, -+ ips->ips_key_e); -+ } else { -+#endif /* CONFIG_IPSEC_ALG */ -+ memset((caddr_t)(ips->ips_key_e), 0, ips->ips_key_e_size); -+ kfree(ips->ips_key_e); -+#ifdef CONFIG_IPSEC_ALG -+ } -+#endif /* CONFIG_IPSEC_ALG */ -+ } -+ ips->ips_key_e = NULL; -+ -+ if(ips->ips_iv != NULL) { -+ memset((caddr_t)(ips->ips_iv), 0, ips->ips_iv_size); -+ kfree(ips->ips_iv); -+ } -+ ips->ips_iv = NULL; -+ -+ if(ips->ips_ident_s.data != NULL) { -+ memset((caddr_t)(ips->ips_ident_s.data), -+ 0, -+ ips->ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); -+ kfree(ips->ips_ident_s.data); -+ } -+ ips->ips_ident_s.data = NULL; -+ -+ if(ips->ips_ident_d.data != NULL) { -+ memset((caddr_t)(ips->ips_ident_d.data), -+ 0, -+ ips->ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); -+ kfree(ips->ips_ident_d.data); -+ } -+ ips->ips_ident_d.data = NULL; -+ -+#ifdef CONFIG_IPSEC_ALG -+ if (ips->ips_alg_enc||ips->ips_alg_auth) { -+ ipsec_alg_sa_wipe(ips); -+ } -+#endif /* CONFIG_IPSEC_ALG */ -+ -+ memset((caddr_t)ips, 0, sizeof(*ips)); -+ kfree(ips); -+ ips = NULL; -+ -+ return 0; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.23 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.22.2.1 2003/12/22 15:25:52 jjo -+ * . Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.22 2003/12/10 01:14:27 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.21 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.20.4.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.20 2003/02/06 01:50:34 rgb -+ * Fixed initialisation bug for first sadb hash bucket that would only manifest itself on platforms where NULL != 0. -+ * -+ * Revision 1.19 2003/01/30 02:32:22 rgb -+ * -+ * Rename SAref table macro names for clarity. -+ * Transmit error code through to caller from callee for better diagnosis of problems. -+ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug. -+ * -+ * Revision 1.18 2002/10/12 23:11:53 dhr -+ * -+ * [KenB + DHR] more 64-bit cleanup -+ * -+ * Revision 1.17 2002/10/07 18:31:43 rgb -+ * Move field width sanity checks to ipsec_sa.c -+ * -+ * Revision 1.16 2002/09/20 15:41:02 rgb -+ * Re-wrote most of the SAref code to eliminate Entry pointers. -+ * Added SAref code compiler directive switch. -+ * Added a saref test function for testing macros. -+ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc(). -+ * Split ipsec_sadb_cleanup from new funciton ipsec_sadb_free to avoid problem -+ * of freeing newly created structures when clearing the reftable upon startup -+ * to start from a known state. -+ * Place all ipsec sadb globals into one struct. -+ * Rework saref freelist. -+ * Added memory allocation debugging. -+ * -+ * Revision 1.15 2002/09/20 05:01:44 rgb -+ * Update copyright date. -+ * -+ * Revision 1.14 2002/08/13 19:01:25 mcr -+ * patches from kenb to permit compilation of FreeSWAN on ia64. -+ * des library patched to use proper DES_LONG type for ia64. -+ * -+ * Revision 1.13 2002/07/29 03:06:20 mcr -+ * get rid of variable not used warnings. -+ * -+ * Revision 1.12 2002/07/26 08:48:31 rgb -+ * Added SA ref table code. -+ * -+ * Revision 1.11 2002/06/04 16:48:49 rgb -+ * Tidied up pointer code for processor independance. -+ * -+ * Revision 1.10 2002/05/23 07:16:17 rgb -+ * Added ipsec_sa_put() for releasing an ipsec_sa refcount. -+ * Pointer clean-up. -+ * Added refcount code. -+ * Convert "usecount" to "refcount" to remove ambiguity. -+ * -+ * Revision 1.9 2002/05/14 02:34:49 rgb -+ * Converted reference from ipsec_sa_put to ipsec_sa_add to avoid confusion -+ * with "put" usage in the kernel. -+ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips, -+ * ipsec_sa or ipsec_sa. -+ * Added some preliminary refcount code. -+ * -+ * Revision 1.8 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.7 2002/04/24 07:36:30 mcr -+ * Moved from ./klips/net/ipsec/ipsec_sa.c,v -+ * -+ * Revision 1.6 2002/04/20 00:12:25 rgb -+ * Added esp IV CBC attack fix, disabled. -+ * -+ * Revision 1.5 2002/01/29 17:17:56 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.4 2002/01/29 04:00:52 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.3 2002/01/29 02:13:18 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.2 2001/11/26 09:16:15 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.1.2.2 2001/10/22 21:05:41 mcr -+ * removed phony prototype for des_set_key. -+ * -+ * Revision 1.1.2.1 2001/09/25 02:24:57 mcr -+ * struct tdb -> struct ipsec_sa. -+ * sa(tdb) manipulation functions renamed and moved to ipsec_sa.c -+ * ipsec_xform.c removed. header file still contains useful things. -+ * -+ * -+ * -+ * CLONED from ipsec_xform.c: -+ * Revision 1.53 2001/09/08 21:13:34 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.52 2001/06/14 19:35:11 rgb -+ * Update copyright date. -+ * -+ * Revision 1.51 2001/05/30 08:14:03 rgb -+ * Removed vestiges of esp-null transforms. -+ * -+ * Revision 1.50 2001/05/03 19:43:18 rgb -+ * Initialise error return variable. -+ * Update SENDERR macro. -+ * Fix sign of error return code for ipsec_tdbcleanup(). -+ * Use more appropriate return code for ipsec_tdbwipe(). -+ * -+ * Revision 1.49 2001/04/19 18:56:17 rgb -+ * Fixed tdb table locking comments. -+ * -+ * Revision 1.48 2001/02/27 22:24:55 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.47 2000/11/06 04:32:08 rgb -+ * Ditched spin_lock_irqsave in favour of spin_lock_bh. -+ * -+ * Revision 1.46 2000/09/20 16:21:57 rgb -+ * Cleaned up ident string alloc/free. -+ * -+ * Revision 1.45 2000/09/08 19:16:51 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * Removed all references to CONFIG_IPSEC_PFKEYv2. -+ * -+ * Revision 1.44 2000/08/30 05:29:04 rgb -+ * Compiler-define out no longer used tdb_init() in ipsec_xform.c. -+ * -+ * Revision 1.43 2000/08/18 21:30:41 rgb -+ * Purged all tdb_spi, tdb_proto and tdb_dst macros. They are unclear. -+ * -+ * Revision 1.42 2000/08/01 14:51:51 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.41 2000/07/28 14:58:31 rgb -+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. -+ * -+ * Revision 1.40 2000/06/28 05:50:11 rgb -+ * Actually set iv_bits. -+ * -+ * Revision 1.39 2000/05/10 23:11:09 rgb -+ * Added netlink debugging output. -+ * Added a cast to quiet down the ntohl bug. -+ * -+ * Revision 1.38 2000/05/10 19:18:42 rgb -+ * Cast output of ntohl so that the broken prototype doesn't make our -+ * compile noisy. -+ * -+ * Revision 1.37 2000/03/16 14:04:59 rgb -+ * Hardwired CONFIG_IPSEC_PFKEYv2 on. -+ * -+ * Revision 1.36 2000/01/26 10:11:28 rgb -+ * Fixed spacing in error text causing run-in words. -+ * -+ * Revision 1.35 2000/01/21 06:17:16 rgb -+ * Tidied up compiler directive indentation for readability. -+ * Added ictx,octx vars for simplification.(kravietz) -+ * Added macros for HMAC padding magic numbers.(kravietz) -+ * Fixed missing key length reporting bug. -+ * Fixed bug in tdbwipe to return immediately on NULL tdbp passed in. -+ * -+ * Revision 1.34 1999/12/08 00:04:19 rgb -+ * Fixed SA direction overwriting bug for netlink users. -+ * -+ * Revision 1.33 1999/12/01 22:16:44 rgb -+ * Minor formatting changes in ESP MD5 initialisation. -+ * -+ * Revision 1.32 1999/11/25 09:06:36 rgb -+ * Fixed error return messages, should be returning negative numbers. -+ * Implemented SENDERR macro for propagating error codes. -+ * Added debug message and separate error code for algorithms not compiled -+ * in. -+ * -+ * Revision 1.31 1999/11/23 23:06:26 rgb -+ * Sort out pfkey and freeswan headers, putting them in a library path. -+ * -+ * Revision 1.30 1999/11/18 04:09:20 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.29 1999/11/17 15:53:40 rgb -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * -+ * Revision 1.28 1999/10/18 20:04:01 rgb -+ * Clean-out unused cruft. -+ * -+ * Revision 1.27 1999/10/03 19:01:03 rgb -+ * Spinlock support for 2.3.xx and 2.0.xx kernels. -+ * -+ * Revision 1.26 1999/10/01 16:22:24 rgb -+ * Switch from assignment init. to functional init. of spinlocks. -+ * -+ * Revision 1.25 1999/10/01 15:44:54 rgb -+ * Move spinlock header include to 2.1> scope. -+ * -+ * Revision 1.24 1999/10/01 00:03:46 rgb -+ * Added tdb structure locking. -+ * Minor formatting changes. -+ * Add function to initialize tdb hash table. -+ * -+ * Revision 1.23 1999/05/25 22:42:12 rgb -+ * Add deltdbchain() debugging. -+ * -+ * Revision 1.22 1999/05/25 21:24:31 rgb -+ * Add debugging statements to deltdbchain(). -+ * -+ * Revision 1.21 1999/05/25 03:51:48 rgb -+ * Refix error return code. -+ * -+ * Revision 1.20 1999/05/25 03:34:07 rgb -+ * Fix error return for flush. -+ * -+ * Revision 1.19 1999/05/09 03:25:37 rgb -+ * Fix bug introduced by 2.2 quick-and-dirty patch. -+ * -+ * Revision 1.18 1999/05/05 22:02:32 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.17 1999/04/29 15:20:16 rgb -+ * Change gettdb parameter to a pointer to reduce stack loading and -+ * facilitate parameter sanity checking. -+ * Add sanity checking for null pointer arguments. -+ * Add debugging instrumentation. -+ * Add function deltdbchain() which will take care of unlinking, -+ * zeroing and deleting a chain of tdbs. -+ * Add a parameter to tdbcleanup to be able to delete a class of SAs. -+ * tdbwipe now actually zeroes the tdb as well as any of its pointed -+ * structures. -+ * -+ * Revision 1.16 1999/04/16 15:36:29 rgb -+ * Fix cut-and-paste error causing a memory leak in IPIP TDB freeing. -+ * -+ * Revision 1.15 1999/04/11 00:29:01 henry -+ * GPL boilerplate -+ * -+ * Revision 1.14 1999/04/06 04:54:28 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.13 1999/02/19 18:23:01 rgb -+ * Nix debug off compile warning. -+ * -+ * Revision 1.12 1999/02/17 16:52:16 rgb -+ * Consolidate satoa()s for space and speed efficiency. -+ * Convert DEBUG_IPSEC to KLIPS_PRINT -+ * Clean out unused cruft. -+ * Ditch NET_IPIP dependancy. -+ * Loop for 3des key setting. -+ * -+ * Revision 1.11 1999/01/26 02:09:05 rgb -+ * Remove ah/esp/IPIP switching on include files. -+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro. -+ * Removed dead code. -+ * Clean up debug code when switched off. -+ * Remove references to INET_GET_PROTOCOL. -+ * Added code exclusion macros to reduce code from unused algorithms. -+ * -+ * Revision 1.10 1999/01/22 06:28:55 rgb -+ * Cruft clean-out. -+ * Put random IV generation in kernel. -+ * Added algorithm switch code. -+ * Enhanced debugging. -+ * 64-bit clean-up. -+ * -+ * Revision 1.9 1998/11/30 13:22:55 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.8 1998/11/25 04:59:06 rgb -+ * Add conditionals for no IPIP tunnel code. -+ * Delete commented out code. -+ * -+ * Revision 1.7 1998/10/31 06:50:41 rgb -+ * Convert xform ASCII names to no spaces. -+ * Fixed up comments in #endif directives. -+ * -+ * Revision 1.6 1998/10/19 14:44:28 rgb -+ * Added inclusion of freeswan.h. -+ * sa_id structure implemented and used: now includes protocol. -+ * -+ * Revision 1.5 1998/10/09 04:32:19 rgb -+ * Added 'klips_debug' prefix to all klips printk debug statements. -+ * -+ * Revision 1.4 1998/08/12 00:11:31 rgb -+ * Added new xform functions to the xform table. -+ * Fixed minor debug output spelling error. -+ * -+ * Revision 1.3 1998/07/09 17:45:31 rgb -+ * Clarify algorithm not available message. -+ * -+ * Revision 1.2 1998/06/23 03:00:51 rgb -+ * Check for presence of IPIP protocol if it is setup one way (we don't -+ * know what has been set up the other way and can only assume it will be -+ * symmetrical with the exception of keys). -+ * -+ * Revision 1.1 1998/06/18 21:27:51 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.3 1998/06/11 05:54:59 rgb -+ * Added transform version string pointer to xformsw initialisations. -+ * -+ * Revision 1.2 1998/04/21 21:28:57 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.1 1998/04/09 03:06:13 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:02 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.5 1997/06/03 04:24:48 ji -+ * Added ESP-3DES-MD5-96 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * Added new transforms. -+ * -+ * Revision 0.3 1996/11/20 14:39:04 ji -+ * Minor cleanups. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_sha1.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,219 @@ -+/* -+ * RCSID $Id$ -+ */ -+ -+/* -+ * The rest of the code is derived from sha1.c by Steve Reid, which is -+ * public domain. -+ * Minor cosmetic changes to accomodate it in the Linux kernel by ji. -+ */ -+ -+#include -+#include -+ -+#include "openswan/ipsec_sha1.h" -+ -+#if defined(rol) -+#undef rol -+#endif -+ -+#define SHA1HANDSOFF -+ -+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) -+ -+/* blk0() and blk() perform the initial expand. */ -+/* I got the idea of expanding during the round function from SSLeay */ -+#ifdef __LITTLE_ENDIAN -+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ -+ |(rol(block->l[i],8)&0x00FF00FF)) -+#else -+#define blk0(i) block->l[i] -+#endif -+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ -+ ^block->l[(i+2)&15]^block->l[i&15],1)) -+ -+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); -+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); -+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); -+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); -+ -+ -+/* Hash a single 512-bit block. This is the core of the algorithm. */ -+ -+void SHA1Transform(__u32 state[5], __u8 buffer[64]) -+{ -+__u32 a, b, c, d, e; -+typedef union { -+ unsigned char c[64]; -+ __u32 l[16]; -+} CHAR64LONG16; -+CHAR64LONG16* block; -+#ifdef SHA1HANDSOFF -+static unsigned char workspace[64]; -+ block = (CHAR64LONG16*)workspace; -+ memcpy(block, buffer, 64); -+#else -+ block = (CHAR64LONG16*)buffer; -+#endif -+ /* Copy context->state[] to working vars */ -+ a = state[0]; -+ b = state[1]; -+ c = state[2]; -+ d = state[3]; -+ e = state[4]; -+ /* 4 rounds of 20 operations each. Loop unrolled. */ -+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); -+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); -+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); -+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); -+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); -+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); -+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); -+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); -+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); -+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); -+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); -+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); -+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); -+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); -+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); -+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); -+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); -+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); -+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); -+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); -+ /* Add the working vars back into context.state[] */ -+ state[0] += a; -+ state[1] += b; -+ state[2] += c; -+ state[3] += d; -+ state[4] += e; -+ /* Wipe variables */ -+ a = b = c = d = e = 0; -+} -+ -+ -+/* SHA1Init - Initialize new context */ -+ -+void SHA1Init(void *vcontext) -+{ -+ SHA1_CTX* context = vcontext; -+ -+ /* SHA1 initialization constants */ -+ context->state[0] = 0x67452301; -+ context->state[1] = 0xEFCDAB89; -+ context->state[2] = 0x98BADCFE; -+ context->state[3] = 0x10325476; -+ context->state[4] = 0xC3D2E1F0; -+ context->count[0] = context->count[1] = 0; -+} -+ -+ -+/* Run your data through this. */ -+ -+void SHA1Update(void *vcontext, unsigned char* data, __u32 len) -+{ -+ SHA1_CTX* context = vcontext; -+ __u32 i, j; -+ -+ j = context->count[0]; -+ if ((context->count[0] += len << 3) < j) -+ context->count[1]++; -+ context->count[1] += (len>>29); -+ j = (j >> 3) & 63; -+ if ((j + len) > 63) { -+ memcpy(&context->buffer[j], data, (i = 64-j)); -+ SHA1Transform(context->state, context->buffer); -+ for ( ; i + 63 < len; i += 64) { -+ SHA1Transform(context->state, &data[i]); -+ } -+ j = 0; -+ } -+ else i = 0; -+ memcpy(&context->buffer[j], &data[i], len - i); -+} -+ -+ -+/* Add padding and return the message digest. */ -+ -+void SHA1Final(unsigned char digest[20], void *vcontext) -+{ -+ __u32 i, j; -+ unsigned char finalcount[8]; -+ SHA1_CTX* context = vcontext; -+ -+ for (i = 0; i < 8; i++) { -+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] -+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ -+ } -+ SHA1Update(context, (unsigned char *)"\200", 1); -+ while ((context->count[0] & 504) != 448) { -+ SHA1Update(context, (unsigned char *)"\0", 1); -+ } -+ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ -+ for (i = 0; i < 20; i++) { -+ digest[i] = (unsigned char) -+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); -+ } -+ /* Wipe variables */ -+ i = j = 0; -+ memset(context->buffer, 0, 64); -+ memset(context->state, 0, 20); -+ memset(context->count, 0, 8); -+ memset(&finalcount, 0, 8); -+#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */ -+ SHA1Transform(context->state, context->buffer); -+#endif -+} -+ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.9 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.8 2002/09/10 01:45:14 mcr -+ * changed type of MD5_CTX and SHA1_CTX to void * so that -+ * the function prototypes would match, and could be placed -+ * into a pointer to a function. -+ * -+ * Revision 1.7 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.6 2002/04/24 07:36:30 mcr -+ * Moved from ./klips/net/ipsec/ipsec_sha1.c,v -+ * -+ * Revision 1.5 1999/12/13 13:59:13 rgb -+ * Quick fix to argument size to Update bugs. -+ * -+ * Revision 1.4 1999/04/11 00:29:00 henry -+ * GPL boilerplate -+ * -+ * Revision 1.3 1999/04/06 04:54:27 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.2 1999/01/22 06:55:50 rgb -+ * 64-bit clean-up. -+ * -+ * Revision 1.1 1998/06/18 21:27:50 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.2 1998/04/23 20:54:04 rgb -+ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when -+ * verified. -+ * -+ * Revision 1.1 1998/04/09 03:06:11 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:05 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * New transform -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_tunnel.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,2645 @@ -+/* -+ * IPSEC Tunneling code. Heavily based on drivers/net/new_tunnel.c -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_tunnel_c_version[] = "RCSID $Id$"; -+ -+#define __NO_VERSION__ -+#include -+#include /* for CONFIG_IP_FORWARD */ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include /* struct tcphdr */ -+#include /* struct udphdr */ -+#include -+#include -+#ifdef NET_21 -+# include -+# include -+# define ip_chk_addr inet_addr_type -+# define IS_MYADDR RTN_LOCAL -+# include -+# undef dev_kfree_skb -+# define dev_kfree_skb(a,b) kfree_skb(a) -+# define PHYSDEV_TYPE -+#endif /* NET_21 */ -+#include -+#include /* icmp_send() */ -+#include -+#ifdef NETDEV_23 -+# include -+#endif /* NETDEV_23 */ -+ -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_life.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_eroute.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_sa.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_xmit.h" -+#include "openswan/ipsec_ipe4.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+#include -+#endif -+ -+static __u32 zeroes[64]; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_tunnel = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_open(struct device *dev) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ -+ /* -+ * Can't open until attached. -+ */ -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_open: " -+ "dev = %s, prv->dev = %s\n", -+ dev->name, prv->dev?prv->dev->name:"NONE"); -+ -+ if (prv->dev == NULL) -+ return -ENODEV; -+ -+ MOD_INC_USE_COUNT; -+ return 0; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_close(struct device *dev) -+{ -+ MOD_DEC_USE_COUNT; -+ return 0; -+} -+ -+#ifdef NETDEV_23 -+static inline int ipsec_tunnel_xmit2(struct sk_buff *skb) -+{ -+#ifdef NETDEV_25 /* 2.6 kernels */ -+ return dst_output(skb); -+#else -+ return ip_send(skb); -+#endif -+} -+#endif /* NETDEV_23 */ -+ -+enum ipsec_xmit_value -+ipsec_tunnel_strip_hard_header(struct ipsec_xmit_state *ixs) -+{ -+ /* ixs->physdev->hard_header_len is unreliable and should not be used */ -+ ixs->hard_header_len = (unsigned char *)(ixs->iph) - ixs->skb->data; -+ -+ if(ixs->hard_header_len < 0) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_error:ipsec_xmit_strip_hard_header: " -+ "Negative hard_header_len (%d)?!\n", ixs->hard_header_len); -+ ixs->stats->tx_dropped++; -+ return IPSEC_XMIT_BADHHLEN; -+ } -+ -+ /* while ixs->physdev->hard_header_len is unreliable and -+ * should not be trusted, it accurate and required for ATM, GRE and -+ * some other interfaces to work. Thanks to Willy Tarreau -+ * . -+ */ -+ if(ixs->hard_header_len == 0) { /* no hard header present */ -+ ixs->hard_header_stripped = 1; -+ ixs->hard_header_len = ixs->physdev->hard_header_len; -+ } -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_tunnel & DB_TN_XMIT) { -+ int i; -+ char c; -+ -+ printk(KERN_INFO "klips_debug:ipsec_xmit_strip_hard_header: " -+ ">>> skb->len=%ld hard_header_len:%d", -+ (unsigned long int)ixs->skb->len, ixs->hard_header_len); -+ c = ' '; -+ for (i=0; i < ixs->hard_header_len; i++) { -+ printk("%c%02x", c, ixs->skb->data[i]); -+ c = ':'; -+ } -+ printk(" \n"); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph); -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_strip_hard_header: " -+ "Original head,tailroom: %d,%d\n", -+ skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); -+ -+ return IPSEC_XMIT_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_tunnel_SAlookup(struct ipsec_xmit_state *ixs) -+{ -+ /* -+ * First things first -- look us up in the erouting tables. -+ */ -+ ixs->matcher.sen_len = sizeof (struct sockaddr_encap); -+ ixs->matcher.sen_family = AF_ENCAP; -+ ixs->matcher.sen_type = SENT_IP4; -+ ixs->matcher.sen_ip_src.s_addr = ixs->iph->saddr; -+ ixs->matcher.sen_ip_dst.s_addr = ixs->iph->daddr; -+ ixs->matcher.sen_proto = ixs->iph->protocol; -+ ipsec_extract_ports(ixs->iph, &ixs->matcher); -+ -+ /* -+ * The spinlock is to prevent any other process from accessing or deleting -+ * the eroute while we are using and updating it. -+ */ -+ spin_lock(&eroute_lock); -+ -+ ixs->eroute = ipsec_findroute(&ixs->matcher); -+ -+ if(ixs->iph->protocol == IPPROTO_UDP) { -+ if(ixs->skb->sk) { -+ ixs->sport=ntohs(ixs->skb->sk->sport); -+ ixs->dport=ntohs(ixs->skb->sk->dport); -+ } else if((ntohs(ixs->iph->frag_off) & IP_OFFSET) == 0 && -+ ((ixs->skb->len - ixs->hard_header_len) >= -+ ((ixs->iph->ihl << 2) + sizeof(struct udphdr)))) { -+ ixs->sport=ntohs(((struct udphdr*)((caddr_t)ixs->iph+(ixs->iph->ihl<<2)))->source); -+ ixs->dport=ntohs(((struct udphdr*)((caddr_t)ixs->iph + (ixs->iph->ihl<<2)))->dest); -+ } else { -+ ixs->sport=0; ixs->dport=0; -+ } -+ } -+ -+ /* default to a %drop eroute */ -+ ixs->outgoing_said.proto = IPPROTO_INT; -+ ixs->outgoing_said.spi = htonl(SPI_DROP); -+ ixs->outgoing_said.dst.u.v4.sin_addr.s_addr = INADDR_ANY; -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_SAlookup: " -+ "checking for local udp/500 IKE packet " -+ "saddr=%x, er=0p%p, daddr=%x, er_dst=%x, proto=%d sport=%d dport=%d\n", -+ ntohl((unsigned int)ixs->iph->saddr), -+ ixs->eroute, -+ ntohl((unsigned int)ixs->iph->daddr), -+ ixs->eroute ? ntohl((unsigned int)ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr) : 0, -+ ixs->iph->protocol, -+ ixs->sport, -+ ixs->dport); -+ -+ /* -+ * Quick cheat for now...are we udp/500? If so, let it through -+ * without interference since it is most likely an IKE packet. -+ */ -+ -+ if (ip_chk_addr((unsigned long)ixs->iph->saddr) == IS_MYADDR -+ && (!ixs->eroute -+ || ixs->iph->daddr == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr -+ || INADDR_ANY == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr) -+ -+ && ((ixs->sport == 500) || (ixs->sport == 4500))) { -+ /* Whatever the eroute, this is an IKE message -+ * from us (i.e. not being forwarded). -+ * Furthermore, if there is a tunnel eroute, -+ * the destination is the peer for this eroute. -+ * So %pass the packet: modify the default %drop. -+ */ -+ ixs->outgoing_said.spi = htonl(SPI_PASS); -+ if(!(ixs->skb->sk) && ((ntohs(ixs->iph->frag_off) & IP_MF) != 0)) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_SAlookup: " -+ "local UDP/500 (probably IKE) passthrough: base fragment, rest of fragments will probably get filtered.\n"); -+ } -+ } else if (ixs->eroute) { -+ ixs->eroute->er_count++; -+ ixs->eroute->er_lasttime = jiffies/HZ; -+ if(ixs->eroute->er_said.proto==IPPROTO_INT -+ && ixs->eroute->er_said.spi==htonl(SPI_HOLD)) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_SAlookup: " -+ "shunt SA of HOLD: skb stored in HOLD.\n"); -+ if(ixs->eroute->er_last != NULL) { -+ kfree_skb(ixs->eroute->er_last); -+ } -+ ixs->eroute->er_last = ixs->skb; -+ ixs->skb = NULL; -+ ixs->stats->tx_dropped++; -+ spin_unlock(&eroute_lock); -+ return IPSEC_XMIT_STOLEN; -+ } -+ ixs->outgoing_said = ixs->eroute->er_said; -+ ixs->eroute_pid = ixs->eroute->er_pid; -+ /* Copy of the ident for the TRAP/TRAPSUBNET eroutes */ -+ if(ixs->outgoing_said.proto==IPPROTO_INT -+ && (ixs->outgoing_said.spi==htonl(SPI_TRAP) -+ || (ixs->outgoing_said.spi==htonl(SPI_TRAPSUBNET)))) { -+ int len; -+ -+ ixs->ips.ips_ident_s.type = ixs->eroute->er_ident_s.type; -+ ixs->ips.ips_ident_s.id = ixs->eroute->er_ident_s.id; -+ ixs->ips.ips_ident_s.len = ixs->eroute->er_ident_s.len; -+ if (ixs->ips.ips_ident_s.len) { -+ len = ixs->ips.ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_SAlookup: " -+ "allocating %d bytes for ident_s shunt SA of HOLD: skb stored in HOLD.\n", -+ len); -+ if ((ixs->ips.ips_ident_s.data = kmalloc(len, GFP_ATOMIC)) == NULL) { -+ printk(KERN_WARNING "klips_debug:ipsec_xmit_SAlookup: " -+ "Failed, tried to allocate %d bytes for source ident.\n", -+ len); -+ ixs->stats->tx_dropped++; -+ spin_unlock(&eroute_lock); -+ return IPSEC_XMIT_ERRMEMALLOC; -+ } -+ memcpy(ixs->ips.ips_ident_s.data, ixs->eroute->er_ident_s.data, len); -+ } -+ ixs->ips.ips_ident_d.type = ixs->eroute->er_ident_d.type; -+ ixs->ips.ips_ident_d.id = ixs->eroute->er_ident_d.id; -+ ixs->ips.ips_ident_d.len = ixs->eroute->er_ident_d.len; -+ if (ixs->ips.ips_ident_d.len) { -+ len = ixs->ips.ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_SAlookup: " -+ "allocating %d bytes for ident_d shunt SA of HOLD: skb stored in HOLD.\n", -+ len); -+ if ((ixs->ips.ips_ident_d.data = kmalloc(len, GFP_ATOMIC)) == NULL) { -+ printk(KERN_WARNING "klips_debug:ipsec_xmit_SAlookup: " -+ "Failed, tried to allocate %d bytes for dest ident.\n", -+ len); -+ ixs->stats->tx_dropped++; -+ spin_unlock(&eroute_lock); -+ return IPSEC_XMIT_ERRMEMALLOC; -+ } -+ memcpy(ixs->ips.ips_ident_d.data, ixs->eroute->er_ident_d.data, len); -+ } -+ } -+ } -+ -+ spin_unlock(&eroute_lock); -+ return IPSEC_XMIT_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_tunnel_restore_hard_header(struct ipsec_xmit_state*ixs) -+{ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_restore_hard_header: " -+ "After recursive xforms -- head,tailroom: %d,%d\n", -+ skb_headroom(ixs->skb), -+ skb_tailroom(ixs->skb)); -+ -+ if(ixs->saved_header) { -+ if(skb_headroom(ixs->skb) < ixs->hard_header_len) { -+ printk(KERN_WARNING -+ "klips_error:ipsec_xmit_restore_hard_header: " -+ "tried to skb_push hhlen=%d, %d available. This should never happen, please report.\n", -+ ixs->hard_header_len, -+ skb_headroom(ixs->skb)); -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_PUSHPULLERR; -+ -+ } -+ skb_push(ixs->skb, ixs->hard_header_len); -+ { -+ int i; -+ for (i = 0; i < ixs->hard_header_len; i++) { -+ ixs->skb->data[i] = ixs->saved_header[i]; -+ } -+ } -+ } -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if (ixs->natt_type && ixs->natt_head) { -+ struct iphdr *ipp = ixs->skb->nh.iph; -+ struct udphdr *udp; -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "encapsuling packet into UDP (NAT-Traversal) (%d %d)\n", -+ ixs->natt_type, ixs->natt_head); -+ -+ ixs->iphlen = ipp->ihl << 2; -+ ipp->tot_len = -+ htons(ntohs(ipp->tot_len) + ixs->natt_head); -+ if(skb_tailroom(ixs->skb) < ixs->natt_head) { -+ printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: " -+ "tried to skb_put %d, %d available. " -+ "This should never happen, please report.\n", -+ ixs->natt_head, -+ skb_tailroom(ixs->skb)); -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESPUDP; -+ } -+ skb_put(ixs->skb, ixs->natt_head); -+ -+ udp = (struct udphdr *)((char *)ipp + ixs->iphlen); -+ -+ /* move ESP hdr after UDP hdr */ -+ memmove((void *)((char *)udp + ixs->natt_head), -+ (void *)(udp), -+ ntohs(ipp->tot_len) - ixs->iphlen - ixs->natt_head); -+ -+ /* clear UDP & Non-IKE Markers (if any) */ -+ memset(udp, 0, ixs->natt_head); -+ -+ /* fill UDP with usefull informations ;-) */ -+ udp->source = htons(ixs->natt_sport); -+ udp->dest = htons(ixs->natt_dport); -+ udp->len = htons(ntohs(ipp->tot_len) - ixs->iphlen); -+ -+ /* set protocol */ -+ ipp->protocol = IPPROTO_UDP; -+ -+ /* fix IP checksum */ -+ ipp->check = 0; -+ ipp->check = ip_fast_csum((unsigned char *)ipp, ipp->ihl); -+ } -+#endif -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_restore_hard_header: " -+ "With hard_header, final head,tailroom: %d,%d\n", -+ skb_headroom(ixs->skb), -+ skb_tailroom(ixs->skb)); -+ -+ return IPSEC_XMIT_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_tunnel_send(struct ipsec_xmit_state*ixs) -+{ -+#ifdef NETDEV_25 -+ struct flowi fl; -+#endif -+ -+#ifdef NET_21 /* 2.2 and 2.4 kernels */ -+ /* new route/dst cache code from James Morris */ -+ ixs->skb->dev = ixs->physdev; -+#ifdef NETDEV_25 -+ fl.oif = ixs->physdev->iflink; -+ fl.nl_u.ip4_u.daddr = ixs->skb->nh.iph->daddr; -+ fl.nl_u.ip4_u.saddr = ixs->pass ? 0 : ixs->skb->nh.iph->saddr; -+ fl.nl_u.ip4_u.tos = RT_TOS(ixs->skb->nh.iph->tos); -+ fl.proto = ixs->skb->nh.iph->protocol; -+ if ((ixs->error = ip_route_output_key(&ixs->route, &fl))) { -+#else -+ /*skb_orphan(ixs->skb);*/ -+ if((ixs->error = ip_route_output(&ixs->route, -+ ixs->skb->nh.iph->daddr, -+ ixs->pass ? 0 : ixs->skb->nh.iph->saddr, -+ RT_TOS(ixs->skb->nh.iph->tos), -+ /* mcr->rgb: should this be 0 instead? */ -+ ixs->physdev->iflink))) { -+#endif -+ ixs->stats->tx_errors++; -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_send: " -+ "ip_route_output failed with error code %d, rt->u.dst.dev=%s, dropped\n", -+ ixs->error, -+ ixs->route->u.dst.dev->name); -+ return IPSEC_XMIT_ROUTEERR; -+ } -+ if(ixs->dev == ixs->route->u.dst.dev) { -+ ip_rt_put(ixs->route); -+ /* This is recursion, drop it. */ -+ ixs->stats->tx_errors++; -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_send: " -+ "suspect recursion, dev=rt->u.dst.dev=%s, dropped\n", -+ ixs->dev->name); -+ return IPSEC_XMIT_RECURSDETECT; -+ } -+ dst_release(ixs->skb->dst); -+ ixs->skb->dst = &ixs->route->u.dst; -+ ixs->stats->tx_bytes += ixs->skb->len; -+ if(ixs->skb->len < ixs->skb->nh.raw - ixs->skb->data) { -+ ixs->stats->tx_errors++; -+ printk(KERN_WARNING -+ "klips_error:ipsec_xmit_send: " -+ "tried to __skb_pull nh-data=%ld, %d available. This should never happen, please report.\n", -+ (unsigned long)(ixs->skb->nh.raw - ixs->skb->data), -+ ixs->skb->len); -+ return IPSEC_XMIT_PUSHPULLERR; -+ } -+ __skb_pull(ixs->skb, ixs->skb->nh.raw - ixs->skb->data); -+#ifdef SKB_RESET_NFCT -+ if(!ixs->pass) { -+ nf_conntrack_put(ixs->skb->nfct); -+ ixs->skb->nfct = NULL; -+ } -+#ifdef CONFIG_NETFILTER_DEBUG -+ ixs->skb->nf_debug = 0; -+#endif /* CONFIG_NETFILTER_DEBUG */ -+#endif /* SKB_RESET_NFCT */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_send: " -+ "...done, calling ip_send() on device:%s\n", -+ ixs->skb->dev ? ixs->skb->dev->name : "NULL"); -+ KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->skb->nh.iph); -+#ifdef NETDEV_23 /* 2.4 kernels */ -+ { -+ int err; -+ -+ err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, ixs->skb, NULL, ixs->route->u.dst.dev, -+ ipsec_tunnel_xmit2); -+ if(err != NET_XMIT_SUCCESS && err != NET_XMIT_CN) { -+ if(net_ratelimit()) -+ printk(KERN_ERR -+ "klips_error:ipsec_xmit_send: " -+ "ip_send() failed, err=%d\n", -+ -err); -+ ixs->stats->tx_errors++; -+ ixs->stats->tx_aborted_errors++; -+ ixs->skb = NULL; -+ return IPSEC_XMIT_IPSENDFAILURE; -+ } -+ } -+#else /* NETDEV_23 */ /* 2.2 kernels */ -+ ip_send(ixs->skb); -+#endif /* NETDEV_23 */ -+#else /* NET_21 */ /* 2.0 kernels */ -+ ixs->skb->arp = 1; -+ /* ISDN/ASYNC PPP from Matjaz Godec. */ -+ /* skb->protocol = htons(ETH_P_IP); */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_send: " -+ "...done, calling dev_queue_xmit() or ip_fragment().\n"); -+ IP_SEND(ixs->skb, ixs->physdev); -+#endif /* NET_21 */ -+ ixs->stats->tx_packets++; -+ -+ ixs->skb = NULL; -+ -+ return IPSEC_XMIT_OK; -+} -+ -+void -+ipsec_tunnel_cleanup(struct ipsec_xmit_state*ixs) -+{ -+#if defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) -+ netif_wake_queue(ixs->dev); -+#else /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ -+ ixs->dev->tbusy = 0; -+#endif /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ -+ if(ixs->saved_header) { -+ kfree(ixs->saved_header); -+ } -+ if(ixs->skb) { -+ dev_kfree_skb(ixs->skb, FREE_WRITE); -+ } -+ if(ixs->oskb) { -+ dev_kfree_skb(ixs->oskb, FREE_WRITE); -+ } -+ if (ixs->ips.ips_ident_s.data) { -+ kfree(ixs->ips.ips_ident_s.data); -+ } -+ if (ixs->ips.ips_ident_d.data) { -+ kfree(ixs->ips.ips_ident_d.data); -+ } -+} -+ -+/* -+ * This function assumes it is being called from dev_queue_xmit() -+ * and that skb is filled properly by that function. -+ */ -+int -+ipsec_tunnel_start_xmit(struct sk_buff *skb, struct device *dev) -+{ -+ struct ipsec_xmit_state ixs_mem; -+ struct ipsec_xmit_state *ixs = &ixs_mem; -+ enum ipsec_xmit_value stat; -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ ixs->natt_type = 0, ixs->natt_head = 0; -+ ixs->natt_sport = 0, ixs->natt_dport = 0; -+#endif -+ -+ memset((caddr_t)ixs, 0, sizeof(*ixs)); -+ ixs->oskb = NULL; -+ ixs->saved_header = NULL; /* saved copy of the hard header */ -+ ixs->route = NULL; -+ memset((caddr_t)&(ixs->ips), 0, sizeof(ixs->ips)); -+ ixs->dev = dev; -+ ixs->skb = skb; -+ -+ stat = ipsec_xmit_sanity_check_dev(ixs); -+ if(stat != IPSEC_XMIT_OK) { -+ goto cleanup; -+ } -+ -+ stat = ipsec_xmit_sanity_check_skb(ixs); -+ if(stat != IPSEC_XMIT_OK) { -+ goto cleanup; -+ } -+ -+ stat = ipsec_tunnel_strip_hard_header(ixs); -+ if(stat != IPSEC_XMIT_OK) { -+ goto cleanup; -+ } -+ -+ stat = ipsec_tunnel_SAlookup(ixs); -+ if(stat != IPSEC_XMIT_OK) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_tunnel_start_xmit: SAlookup failed: %d\n", -+ stat); -+ goto cleanup; -+ } -+ -+ ixs->innersrc = ixs->iph->saddr; -+ /* start encapsulation loop here XXX */ -+ do { -+ stat = ipsec_xmit_encap_bundle(ixs); -+ if(stat != IPSEC_XMIT_OK) { -+ if(stat == IPSEC_XMIT_PASS) { -+ goto bypass; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_tunnel_start_xmit: encap_bundle failed: %d\n", -+ stat); -+ goto cleanup; -+ } -+ -+ ixs->matcher.sen_ip_src.s_addr = ixs->iph->saddr; -+ ixs->matcher.sen_ip_dst.s_addr = ixs->iph->daddr; -+ ixs->matcher.sen_proto = ixs->iph->protocol; -+ ipsec_extract_ports(ixs->iph, &ixs->matcher); -+ -+ spin_lock(&eroute_lock); -+ ixs->eroute = ipsec_findroute(&ixs->matcher); -+ if(ixs->eroute) { -+ ixs->outgoing_said = ixs->eroute->er_said; -+ ixs->eroute_pid = ixs->eroute->er_pid; -+ ixs->eroute->er_count++; -+ ixs->eroute->er_lasttime = jiffies/HZ; -+ } -+ spin_unlock(&eroute_lock); -+ -+ KLIPS_PRINT((debug_tunnel & DB_TN_XMIT) && -+ /* ((ixs->orgdst != ixs->newdst) || (ixs->orgsrc != ixs->newsrc)) */ -+ (ixs->orgedst != ixs->outgoing_said.dst.u.v4.sin_addr.s_addr) && -+ ixs->outgoing_said.dst.u.v4.sin_addr.s_addr && -+ ixs->eroute, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "We are recursing here.\n"); -+ -+ } while(/*((ixs->orgdst != ixs->newdst) || (ixs->orgsrc != ixs->newsrc))*/ -+ (ixs->orgedst != ixs->outgoing_said.dst.u.v4.sin_addr.s_addr) && -+ ixs->outgoing_said.dst.u.v4.sin_addr.s_addr && -+ ixs->eroute); -+ -+ stat = ipsec_tunnel_restore_hard_header(ixs); -+ if(stat != IPSEC_XMIT_OK) { -+ goto cleanup; -+ } -+ -+ bypass: -+ stat = ipsec_tunnel_send(ixs); -+ -+ cleanup: -+ ipsec_tunnel_cleanup(ixs); -+ -+ return 0; -+} -+ -+DEBUG_NO_STATIC struct net_device_stats * -+ipsec_tunnel_get_stats(struct device *dev) -+{ -+ return &(((struct ipsecpriv *)(dev->priv))->mystats); -+} -+ -+/* -+ * Revectored calls. -+ * For each of these calls, a field exists in our private structure. -+ */ -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_hard_header(struct sk_buff *skb, struct device *dev, -+ unsigned short type, void *daddr, void *saddr, unsigned len) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ struct device *tmp; -+ int ret; -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(skb == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "no skb...\n"); -+ return -ENODATA; -+ } -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "no device...\n"); -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "skb->dev=%s dev=%s.\n", -+ skb->dev ? skb->dev->name : "NULL", -+ dev->name); -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "no private space associated with dev=%s\n", -+ dev->name ? dev->name : "NULL"); -+ return -ENODEV; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "no physical device associated with dev=%s\n", -+ dev->name ? dev->name : "NULL"); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ /* check if we have to send a IPv6 packet. It might be a Router -+ Solicitation, where the building of the packet happens in -+ reverse order: -+ 1. ll hdr, -+ 2. IPv6 hdr, -+ 3. ICMPv6 hdr -+ -> skb->nh.raw is still uninitialized when this function is -+ called!! If this is no IPv6 packet, we can print debugging -+ messages, otherwise we skip all debugging messages and just -+ build the ll header */ -+ if(type != ETH_P_IPV6) { -+ /* execute this only, if we don't have to build the -+ header for a IPv6 packet */ -+ if(!prv->hard_header) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "physical device has been detached, packet dropped 0p%p->0p%p len=%d type=%d dev=%s->NULL ", -+ saddr, -+ daddr, -+ len, -+ type, -+ dev->name); -+#ifdef NET_21 -+ KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+#else /* NET_21 */ -+ KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->ip_hdr->saddr), -+ (__u32)ntohl(skb->ip_hdr->daddr) ); -+#endif /* NET_21 */ -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+#define da ((struct device *)(prv->dev))->dev_addr -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "Revectored 0p%p->0p%p len=%d type=%d dev=%s->%s dev_addr=%02x:%02x:%02x:%02x:%02x:%02x ", -+ saddr, -+ daddr, -+ len, -+ type, -+ dev->name, -+ prv->dev->name, -+ da[0], da[1], da[2], da[3], da[4], da[5]); -+#ifdef NET_21 -+ KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+#else /* NET_21 */ -+ KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->ip_hdr->saddr), -+ (__u32)ntohl(skb->ip_hdr->daddr) ); -+#endif /* NET_21 */ -+ } else { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_hard_header: " -+ "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n"); -+ } -+ tmp = skb->dev; -+ skb->dev = prv->dev; -+ ret = prv->hard_header(skb, prv->dev, type, (void *)daddr, (void *)saddr, len); -+ skb->dev = tmp; -+ return ret; -+} -+ -+DEBUG_NO_STATIC int -+#ifdef NET_21 -+ipsec_tunnel_rebuild_header(struct sk_buff *skb) -+#else /* NET_21 */ -+ipsec_tunnel_rebuild_header(void *buff, struct device *dev, -+ unsigned long raddr, struct sk_buff *skb) -+#endif /* NET_21 */ -+{ -+ struct ipsecpriv *prv = skb->dev->priv; -+ struct device *tmp; -+ int ret; -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(skb->dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_rebuild_header: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_rebuild_header: " -+ "no private space associated with dev=%s", -+ skb->dev->name ? skb->dev->name : "NULL"); -+ return -ENODEV; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_rebuild_header: " -+ "no physical device associated with dev=%s", -+ skb->dev->name ? skb->dev->name : "NULL"); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ if(!prv->rebuild_header) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_rebuild_header: " -+ "physical device has been detached, packet dropped skb->dev=%s->NULL ", -+ skb->dev->name); -+#ifdef NET_21 -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+#else /* NET_21 */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->ip_hdr->saddr), -+ (__u32)ntohl(skb->ip_hdr->daddr) ); -+#endif /* NET_21 */ -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel: " -+ "Revectored rebuild_header dev=%s->%s ", -+ skb->dev->name, prv->dev->name); -+#ifdef NET_21 -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->nh.iph->saddr), -+ (__u32)ntohl(skb->nh.iph->daddr) ); -+#else /* NET_21 */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "ip=%08x->%08x\n", -+ (__u32)ntohl(skb->ip_hdr->saddr), -+ (__u32)ntohl(skb->ip_hdr->daddr) ); -+#endif /* NET_21 */ -+ tmp = skb->dev; -+ skb->dev = prv->dev; -+ -+#ifdef NET_21 -+ ret = prv->rebuild_header(skb); -+#else /* NET_21 */ -+ ret = prv->rebuild_header(buff, prv->dev, raddr, skb); -+#endif /* NET_21 */ -+ skb->dev = tmp; -+ return ret; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_set_mac_address(struct device *dev, void *addr) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_set_mac_address: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_set_mac_address: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return -ENODEV; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_set_mac_address: " -+ "no physical device associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ stats->tx_dropped++; -+ return -ENODEV; -+ } -+ -+ if(!prv->set_mac_address) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_set_mac_address: " -+ "physical device has been detached, cannot set - skb->dev=%s->NULL\n", -+ dev->name); -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_set_mac_address: " -+ "Revectored dev=%s->%s addr=0p%p\n", -+ dev->name, prv->dev->name, addr); -+ return prv->set_mac_address(prv->dev, addr); -+ -+} -+ -+#ifndef NET_21 -+DEBUG_NO_STATIC void -+ipsec_tunnel_cache_bind(struct hh_cache **hhp, struct device *dev, -+ unsigned short htype, __u32 daddr) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_bind: " -+ "no device..."); -+ return; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_bind: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_bind: " -+ "no physical device associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ stats->tx_dropped++; -+ return; -+ } -+ -+ if(!prv->header_cache_bind) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_bind: " -+ "physical device has been detached, cannot set - skb->dev=%s->NULL\n", -+ dev->name); -+ stats->tx_dropped++; -+ return; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_bind: " -+ "Revectored \n"); -+ prv->header_cache_bind(hhp, prv->dev, htype, daddr); -+ return; -+} -+#endif /* !NET_21 */ -+ -+ -+DEBUG_NO_STATIC void -+ipsec_tunnel_cache_update(struct hh_cache *hh, struct device *dev, unsigned char * haddr) -+{ -+ struct ipsecpriv *prv = dev->priv; -+ -+ struct net_device_stats *stats; /* This device's statistics */ -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_update: " -+ "no device..."); -+ return; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_update: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return; -+ } -+ -+ stats = (struct net_device_stats *) &(prv->mystats); -+ -+ if(prv->dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_update: " -+ "no physical device associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ stats->tx_dropped++; -+ return; -+ } -+ -+ if(!prv->header_cache_update) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_cache_update: " -+ "physical device has been detached, cannot set - skb->dev=%s->NULL\n", -+ dev->name); -+ return; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel: " -+ "Revectored cache_update\n"); -+ prv->header_cache_update(hh, prv->dev, haddr); -+ return; -+} -+ -+#ifdef NET_21 -+DEBUG_NO_STATIC int -+ipsec_tunnel_neigh_setup(struct neighbour *n) -+{ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_neigh_setup:\n"); -+ -+ if (n->nud_state == NUD_NONE) { -+ n->ops = &arp_broken_ops; -+ n->output = n->ops->output; -+ } -+ return 0; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_neigh_setup_dev(struct device *dev, struct neigh_parms *p) -+{ -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_neigh_setup_dev: " -+ "setting up %s\n", -+ dev ? dev->name : "NULL"); -+ -+ if (p->tbl->family == AF_INET) { -+ p->neigh_setup = ipsec_tunnel_neigh_setup; -+ p->ucast_probes = 0; -+ p->mcast_probes = 0; -+ } -+ return 0; -+} -+#endif /* NET_21 */ -+ -+/* -+ * We call the attach routine to attach another device. -+ */ -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_attach(struct device *dev, struct device *physdev) -+{ -+ int i; -+ struct ipsecpriv *prv = dev->priv; -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_attach: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_attach: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return -ENODATA; -+ } -+ -+ prv->dev = physdev; -+ prv->hard_start_xmit = physdev->hard_start_xmit; -+ prv->get_stats = physdev->get_stats; -+ -+ if (physdev->hard_header) { -+ prv->hard_header = physdev->hard_header; -+ dev->hard_header = ipsec_tunnel_hard_header; -+ } else -+ dev->hard_header = NULL; -+ -+ if (physdev->rebuild_header) { -+ prv->rebuild_header = physdev->rebuild_header; -+ dev->rebuild_header = ipsec_tunnel_rebuild_header; -+ } else -+ dev->rebuild_header = NULL; -+ -+ if (physdev->set_mac_address) { -+ prv->set_mac_address = physdev->set_mac_address; -+ dev->set_mac_address = ipsec_tunnel_set_mac_address; -+ } else -+ dev->set_mac_address = NULL; -+ -+#ifndef NET_21 -+ if (physdev->header_cache_bind) { -+ prv->header_cache_bind = physdev->header_cache_bind; -+ dev->header_cache_bind = ipsec_tunnel_cache_bind; -+ } else -+ dev->header_cache_bind = NULL; -+#endif /* !NET_21 */ -+ -+ if (physdev->header_cache_update) { -+ prv->header_cache_update = physdev->header_cache_update; -+ dev->header_cache_update = ipsec_tunnel_cache_update; -+ } else -+ dev->header_cache_update = NULL; -+ -+ dev->hard_header_len = physdev->hard_header_len; -+ -+#ifdef NET_21 -+/* prv->neigh_setup = physdev->neigh_setup; */ -+ dev->neigh_setup = ipsec_tunnel_neigh_setup_dev; -+#endif /* NET_21 */ -+ dev->mtu = 16260; /* 0xfff0; */ /* dev->mtu; */ -+ prv->mtu = physdev->mtu; -+ -+#ifdef PHYSDEV_TYPE -+ dev->type = physdev->type; /* ARPHRD_TUNNEL; */ -+#endif /* PHYSDEV_TYPE */ -+ -+ dev->addr_len = physdev->addr_len; -+ for (i=0; iaddr_len; i++) { -+ dev->dev_addr[i] = physdev->dev_addr[i]; -+ } -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_tunnel & DB_TN_INIT) { -+ printk(KERN_INFO "klips_debug:ipsec_tunnel_attach: " -+ "physical device %s being attached has HW address: %2x", -+ physdev->name, physdev->dev_addr[0]); -+ for (i=1; i < physdev->addr_len; i++) { -+ printk(":%02x", physdev->dev_addr[i]); -+ } -+ printk("\n"); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ return 0; -+} -+ -+/* -+ * We call the detach routine to detach the ipsec tunnel from another device. -+ */ -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_detach(struct device *dev) -+{ -+ int i; -+ struct ipsecpriv *prv = dev->priv; -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_detach: " -+ "no device..."); -+ return -ENODEV; -+ } -+ -+ if(prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, -+ "klips_debug:ipsec_tunnel_detach: " -+ "no private space associated with dev=%s", -+ dev->name ? dev->name : "NULL"); -+ return -ENODATA; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_detach: " -+ "physical device %s being detached from virtual device %s\n", -+ prv->dev ? prv->dev->name : "NULL", -+ dev->name); -+ -+ ipsec_dev_put(prv->dev); -+ prv->dev = NULL; -+ prv->hard_start_xmit = NULL; -+ prv->get_stats = NULL; -+ -+ prv->hard_header = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->hard_header = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+ prv->rebuild_header = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->rebuild_header = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+ prv->set_mac_address = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->set_mac_address = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+#ifndef NET_21 -+ prv->header_cache_bind = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->header_cache_bind = NULL; -+#endif /* DETACH_AND_DOWN */ -+#endif /* !NET_21 */ -+ -+ prv->header_cache_update = NULL; -+#ifdef DETACH_AND_DOWN -+ dev->header_cache_update = NULL; -+#endif /* DETACH_AND_DOWN */ -+ -+#ifdef NET_21 -+/* prv->neigh_setup = NULL; */ -+#ifdef DETACH_AND_DOWN -+ dev->neigh_setup = NULL; -+#endif /* DETACH_AND_DOWN */ -+#endif /* NET_21 */ -+ dev->hard_header_len = 0; -+#ifdef DETACH_AND_DOWN -+ dev->mtu = 0; -+#endif /* DETACH_AND_DOWN */ -+ prv->mtu = 0; -+ for (i=0; idev_addr[i] = 0; -+ } -+ dev->addr_len = 0; -+#ifdef PHYSDEV_TYPE -+ dev->type = ARPHRD_VOID; /* ARPHRD_TUNNEL; */ -+#endif /* PHYSDEV_TYPE */ -+ -+ return 0; -+} -+ -+/* -+ * We call the clear routine to detach all ipsec tunnels from other devices. -+ */ -+DEBUG_NO_STATIC int -+ipsec_tunnel_clear(void) -+{ -+ int i; -+ struct device *ipsecdev = NULL, *prvdev; -+ struct ipsecpriv *prv; -+ char name[9]; -+ int ret; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_clear: .\n"); -+ -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ ipsecdev = ipsecdevices[i]; -+ if(ipsecdev != NULL) { -+ if((prv = (struct ipsecpriv *)(ipsecdev->priv))) { -+ prvdev = (struct device *)(prv->dev); -+ if(prvdev) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_clear: " -+ "physical device for device %s is %s\n", -+ name, prvdev->name); -+ if((ret = ipsec_tunnel_detach(ipsecdev))) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_clear: " -+ "error %d detatching device %s from device %s.\n", -+ ret, name, prvdev->name); -+ return ret; -+ } -+ } -+ } -+ } -+ } -+ return 0; -+} -+ -+DEBUG_NO_STATIC int -+ipsec_tunnel_ioctl(struct device *dev, struct ifreq *ifr, int cmd) -+{ -+ struct ipsectunnelconf *cf = (struct ipsectunnelconf *)&ifr->ifr_data; -+ struct ipsecpriv *prv = dev->priv; -+ struct device *them; /* physical device */ -+#ifdef CONFIG_IP_ALIAS -+ char *colon; -+ char realphysname[IFNAMSIZ]; -+#endif /* CONFIG_IP_ALIAS */ -+ -+ if(dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "device not supplied.\n"); -+ return -ENODEV; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "tncfg service call #%d for dev=%s\n", -+ cmd, -+ dev->name ? dev->name : "NULL"); -+ switch (cmd) { -+ /* attach a virtual ipsec? device to a physical device */ -+ case IPSEC_SET_DEV: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "calling ipsec_tunnel_attatch...\n"); -+#ifdef CONFIG_IP_ALIAS -+ /* If this is an IP alias interface, get its real physical name */ -+ strncpy(realphysname, cf->cf_name, IFNAMSIZ); -+ realphysname[IFNAMSIZ-1] = 0; -+ colon = strchr(realphysname, ':'); -+ if (colon) *colon = 0; -+ them = ipsec_dev_get(realphysname); -+#else /* CONFIG_IP_ALIAS */ -+ them = ipsec_dev_get(cf->cf_name); -+#endif /* CONFIG_IP_ALIAS */ -+ -+ if (them == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "physical device %s requested is null\n", -+ cf->cf_name); -+ ipsec_dev_put(them); -+ return -ENXIO; -+ } -+ -+#if 0 -+ if (them->flags & IFF_UP) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "physical device %s requested is not up.\n", -+ cf->cf_name); -+ ipsec_dev_put(them); -+ return -ENXIO; -+ } -+#endif -+ -+ if (prv && prv->dev) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "virtual device is already connected to %s.\n", -+ prv->dev->name ? prv->dev->name : "NULL"); -+ ipsec_dev_put(them); -+ return -EBUSY; -+ } -+ return ipsec_tunnel_attach(dev, them); -+ -+ case IPSEC_DEL_DEV: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "calling ipsec_tunnel_detatch.\n"); -+ if (! prv->dev) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "physical device not connected.\n"); -+ return -ENODEV; -+ } -+ return ipsec_tunnel_detach(dev); -+ -+ case IPSEC_CLR_DEV: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "calling ipsec_tunnel_clear.\n"); -+ return ipsec_tunnel_clear(); -+ -+ default: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_ioctl: " -+ "unknown command %d.\n", -+ cmd); -+ return -EOPNOTSUPP; -+ } -+} -+ -+int -+ipsec_device_event(struct notifier_block *unused, unsigned long event, void *ptr) -+{ -+ struct device *dev = ptr; -+ struct device *ipsec_dev; -+ struct ipsecpriv *priv; -+ int i; -+ -+ if (dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "dev=NULL for event type %ld.\n", -+ event); -+ return(NOTIFY_DONE); -+ } -+ -+ /* check for loopback devices */ -+ if (dev && (dev->flags & IFF_LOOPBACK)) { -+ return(NOTIFY_DONE); -+ } -+ -+ switch (event) { -+ case NETDEV_DOWN: -+ /* look very carefully at the scope of these compiler -+ directives before changing anything... -- RGB */ -+#ifdef NET_21 -+ case NETDEV_UNREGISTER: -+ switch (event) { -+ case NETDEV_DOWN: -+#endif /* NET_21 */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_DOWN dev=%s flags=%x\n", -+ dev->name, -+ dev->flags); -+ if(strncmp(dev->name, "ipsec", strlen("ipsec")) == 0) { -+ printk(KERN_CRIT "IPSEC EVENT: KLIPS device %s shut down.\n", -+ dev->name); -+ } -+#ifdef NET_21 -+ break; -+ case NETDEV_UNREGISTER: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_UNREGISTER dev=%s flags=%x\n", -+ dev->name, -+ dev->flags); -+ break; -+ } -+#endif /* NET_21 */ -+ -+ /* find the attached physical device and detach it. */ -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ ipsec_dev = ipsecdevices[i]; -+ -+ if(ipsec_dev) { -+ priv = (struct ipsecpriv *)(ipsec_dev->priv); -+ if(priv) { -+ ; -+ if(((struct device *)(priv->dev)) == dev) { -+ /* dev_close(ipsec_dev); */ -+ /* return */ ipsec_tunnel_detach(ipsec_dev); -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "device '%s' has been detached.\n", -+ ipsec_dev->name); -+ break; -+ } -+ } else { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "device '%s' has no private data space!\n", -+ ipsec_dev->name); -+ } -+ } -+ } -+ break; -+ case NETDEV_UP: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_UP dev=%s\n", -+ dev->name); -+ break; -+#ifdef NET_21 -+ case NETDEV_REBOOT: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_REBOOT dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_CHANGE: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_CHANGE dev=%s flags=%x\n", -+ dev->name, -+ dev->flags); -+ break; -+ case NETDEV_REGISTER: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_REGISTER dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_CHANGEMTU: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_CHANGEMTU dev=%s to mtu=%d\n", -+ dev->name, -+ dev->mtu); -+ break; -+ case NETDEV_CHANGEADDR: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_CHANGEADDR dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_GOING_DOWN: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_GOING_DOWN dev=%s\n", -+ dev->name); -+ break; -+ case NETDEV_CHANGENAME: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "NETDEV_CHANGENAME dev=%s\n", -+ dev->name); -+ break; -+#endif /* NET_21 */ -+ default: -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_device_event: " -+ "event type %ld unrecognised for dev=%s\n", -+ event, -+ dev->name); -+ break; -+ } -+ return NOTIFY_DONE; -+} -+ -+/* -+ * Called when an ipsec tunnel device is initialized. -+ * The ipsec tunnel device structure is passed to us. -+ */ -+ -+int -+ipsec_tunnel_init(struct device *dev) -+{ -+ int i; -+ -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_init: " -+ "allocating %lu bytes initialising device: %s\n", -+ (unsigned long) sizeof(struct ipsecpriv), -+ dev->name ? dev->name : "NULL"); -+ -+ /* Add our tunnel functions to the device */ -+ dev->open = ipsec_tunnel_open; -+ dev->stop = ipsec_tunnel_close; -+ dev->hard_start_xmit = ipsec_tunnel_start_xmit; -+ dev->get_stats = ipsec_tunnel_get_stats; -+ -+ dev->priv = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL); -+ if (dev->priv == NULL) -+ return -ENOMEM; -+ memset((caddr_t)(dev->priv), 0, sizeof(struct ipsecpriv)); -+ -+ for(i = 0; i < sizeof(zeroes); i++) { -+ ((__u8*)(zeroes))[i] = 0; -+ } -+ -+#ifndef NET_21 -+ /* Initialize the tunnel device structure */ -+ for (i = 0; i < DEV_NUMBUFFS; i++) -+ skb_queue_head_init(&dev->buffs[i]); -+#endif /* !NET_21 */ -+ -+ dev->set_multicast_list = NULL; -+ dev->do_ioctl = ipsec_tunnel_ioctl; -+ dev->hard_header = NULL; -+ dev->rebuild_header = NULL; -+ dev->set_mac_address = NULL; -+#ifndef NET_21 -+ dev->header_cache_bind = NULL; -+#endif /* !NET_21 */ -+ dev->header_cache_update= NULL; -+ -+#ifdef NET_21 -+/* prv->neigh_setup = NULL; */ -+ dev->neigh_setup = ipsec_tunnel_neigh_setup_dev; -+#endif /* NET_21 */ -+ dev->hard_header_len = 0; -+ dev->mtu = 0; -+ dev->addr_len = 0; -+ dev->type = ARPHRD_VOID; /* ARPHRD_TUNNEL; */ /* ARPHRD_ETHER; */ -+ dev->tx_queue_len = 10; /* Small queue */ -+ memset((caddr_t)(dev->broadcast),0xFF, ETH_ALEN); /* what if this is not attached to ethernet? */ -+ -+ /* New-style flags. */ -+ dev->flags = IFF_NOARP /* 0 */ /* Petr Novak */; -+#ifdef NET_21 -+ dev_init_buffers(dev); -+#else /* NET_21 */ -+ dev->family = AF_INET; -+ dev->pa_addr = 0; -+ dev->pa_brdaddr = 0; -+ dev->pa_mask = 0; -+ dev->pa_alen = 4; -+#endif /* NET_21 */ -+ -+ /* We're done. Have I forgotten anything? */ -+ return 0; -+} -+ -+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -+/* Module specific interface (but it links with the rest of IPSEC) */ -+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -+ -+int -+ipsec_tunnel_probe(struct device *dev) -+{ -+ ipsec_tunnel_init(dev); -+ return 0; -+} -+ -+struct device *ipsecdevices[IPSEC_NUM_IF]; -+ -+int -+ipsec_tunnel_init_devices(void) -+{ -+ int i; -+ char name[IFNAMSIZ]; -+ struct device *dev_ipsec; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_init_devices: " -+ "creating and registering IPSEC_NUM_IF=%u devices, allocating %lu per device, IFNAMSIZ=%u.\n", -+ IPSEC_NUM_IF, -+ (unsigned long) (sizeof(struct device) + IFNAMSIZ), -+ IFNAMSIZ); -+ -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ sprintf(name, IPSEC_DEV_FORMAT, i); -+ dev_ipsec = (struct device*)kmalloc(sizeof(struct device), GFP_KERNEL); -+ if (dev_ipsec == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_init_devices: " -+ "failed to allocate memory for device %s, quitting device init.\n", -+ name); -+ return -ENOMEM; -+ } -+ memset((caddr_t)dev_ipsec, 0, sizeof(struct device)); -+#ifdef NETDEV_23 -+ strncpy(dev_ipsec->name, name, sizeof(dev_ipsec->name)); -+#else /* NETDEV_23 */ -+ dev_ipsec->name = (char*)kmalloc(IFNAMSIZ, GFP_KERNEL); -+ if (dev_ipsec->name == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_init_devices: " -+ "failed to allocate memory for device %s name, quitting device init.\n", -+ name); -+ return -ENOMEM; -+ } -+ memset((caddr_t)dev_ipsec->name, 0, IFNAMSIZ); -+ strncpy(dev_ipsec->name, name, IFNAMSIZ); -+#endif /* NETDEV_23 */ -+ dev_ipsec->next = NULL; -+ dev_ipsec->init = &ipsec_tunnel_probe; -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_init_devices: " -+ "registering device %s\n", -+ dev_ipsec->name); -+ -+ /* reference and hold the device reference */ -+ dev_hold(dev_ipsec); -+ ipsecdevices[i]=dev_ipsec; -+ -+ if (register_netdev(dev_ipsec) != 0) { -+ KLIPS_PRINT(1 || debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_init_devices: " -+ "registering device %s failed, quitting device init.\n", -+ dev_ipsec->name); -+ return -EIO; -+ } else { -+ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, -+ "klips_debug:ipsec_tunnel_init_devices: " -+ "registering device %s succeeded, continuing...\n", -+ dev_ipsec->name); -+ } -+ } -+ return 0; -+} -+ -+/* void */ -+int -+ipsec_tunnel_cleanup_devices(void) -+{ -+ int error = 0; -+ int i; -+ char name[32]; -+ struct device *dev_ipsec; -+ -+ for(i = 0; i < IPSEC_NUM_IF; i++) { -+ dev_ipsec = ipsecdevices[i]; -+ if(dev_ipsec == NULL) { -+ continue; -+ } -+ -+ /* release reference */ -+ ipsecdevices[i]=NULL; -+ ipsec_dev_put(dev_ipsec); -+ -+ KLIPS_PRINT(debug_tunnel, "Unregistering %s (refcnt=%d)\n", -+ name, -+ atomic_read(&dev_ipsec->refcnt)); -+ unregister_netdev(dev_ipsec); -+ KLIPS_PRINT(debug_tunnel, "Unregisted %s\n", name); -+#ifndef NETDEV_23 -+ kfree(dev_ipsec->name); -+ dev_ipsec->name=NULL; -+#endif /* !NETDEV_23 */ -+ kfree(dev_ipsec->priv); -+ dev_ipsec->priv=NULL; -+ } -+ return error; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.220 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.219 2004/02/03 03:13:17 mcr -+ * minor edits for readability, and error reporting. -+ * -+ * Revision 1.218 2004/01/27 20:29:20 mcr -+ * fix for unregister_netdev() problem for underlying eth0. -+ * -+ * Revision 1.217 2003/12/10 01:14:27 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.216 2003/12/04 23:01:17 mcr -+ * removed ipsec_netlink.h -+ * -+ * Revision 1.215 2003/12/04 16:35:16 ken -+ * Fix for ATM devices where physdev->hard_header_len *is* correct -+ * -+ * Revision 1.214 2003/11/25 23:52:37 mcr -+ * fix typo in patch - ixs-> needed. -+ * -+ * Revision 1.213 2003/11/24 18:25:49 mcr -+ * patch from willy@w.ods.org to fix problems with ATM interfaces. -+ * -+ * Revision 1.212 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.211.2.2 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.211.2.1 2003/09/21 13:59:56 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.211 2003/09/10 16:46:30 mcr -+ * patches for 2.4 backport/2.6 existence. -+ * -+ * Revision 1.210 2003/07/31 22:47:16 mcr -+ * preliminary (untested by FS-team) 2.5 patches. -+ * -+ * Revision 1.209 2003/06/22 21:28:43 mcr -+ * inability to unload module was caused by calls to dev_get -+ * (ipsec_dev_get), to gather a device from a name. There is -+ * simply no reason to look the devices up - they should be kept -+ * in a nice array, ready for use. -+ * -+ * Revision 1.208 2003/06/22 21:25:07 mcr -+ * all staticly counted ipsecXXX device support removed. -+ * -+ * Revision 1.207 2003/04/02 20:15:37 mcr -+ * fix for PR#204 - do not clear connection tracking info if we -+ * the packet is being sent in the clear. -+ * -+ * Revision 1.206 2003/02/12 19:32:51 rgb -+ * Refactored file to: -+ * ipsec_xmit.c -+ * ipsec_xmit.h -+ * ipsec_mast.c -+ * -+ * Revision 1.205 2003/02/06 17:47:00 rgb -+ * -+ * Remove unused ipsec_tunnel_lock() and ipsec_tunnel_unlock() code. -+ * Refactor ipsec_tunnel_start_xmit() further into: -+ * ipsec_xmit_sanity_check_dev() -+ * ipsec_xmit_sanity_check_skb() -+ * ipsec_xmit_strip_hard_header() -+ * ipsec_xmit_restore_hard_header() -+ * ipsec_xmit_send() -+ * ipsec_xmit_cleanup() -+ * and start a skeletal ipsec_mast_start_xmit() . -+ * -+ * Revision 1.204 2003/02/06 06:43:46 rgb -+ * -+ * Refactor ipsec_tunnel_start_xmit, bringing out: -+ * ipsec_xmit_SAlookup -+ * ipsec_xmit_encap_once -+ * ipsec_xmit_encap_bundle -+ * -+ * Revision 1.203 2003/02/06 02:21:34 rgb -+ * -+ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h . -+ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr". -+ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code. -+ * -+ * Revision 1.202 2003/01/03 07:38:01 rgb -+ * -+ * Start to refactor ipsec_tunnel_start_xmit() by putting local variables -+ * into struct ipsec_xmit_state and renaming a few variables to give more -+ * unique or searchable names. -+ * -+ * Revision 1.201 2003/01/03 00:31:28 rgb -+ * -+ * Clean up memset usage, including fixing 2 places where keys were not -+ * properly wiped. -+ * -+ * Revision 1.200 2002/12/06 02:24:02 mcr -+ * patches for compiling against SUSE 8.1 kernels. Requires -+ * an additional -DSUSE_LINUX_2_4_19_IS_STUPID. -+ * -+ * Revision 1.199 2002/10/12 23:11:53 dhr -+ * -+ * [KenB + DHR] more 64-bit cleanup -+ * -+ * Revision 1.198 2002/10/05 05:02:58 dhr -+ * -+ * C labels go on statements -+ * -+ * Revision 1.197 2002/09/20 05:01:50 rgb -+ * Added compiler directive to switch on IP options and fix IP options bug. -+ * Make ip->ihl treatment consistent using shifts rather than multiplications. -+ * Check for large enough packet before accessing udp header for IKE bypass. -+ * Added memory allocation debugging. -+ * Fixed potential memory allocation failure-induced oops. -+ * -+ * Revision 1.196 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.195 2002/07/23 03:36:07 rgb -+ * Fixed 2.2 device initialisation hang. -+ * -+ * Revision 1.194 2002/05/27 21:40:34 rgb -+ * Set unused ipsec devices to ARPHRD_VOID to avoid confusing iproute2. -+ * Cleaned up intermediate step to dynamic device allocation. -+ * -+ * Revision 1.193 2002/05/27 19:31:36 rgb -+ * Convert to dynamic ipsec device allocation. -+ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT. -+ * -+ * Revision 1.192 2002/05/23 07:14:28 rgb -+ * Added refcount code. -+ * Cleaned up %p variants to 0p%p for test suite cleanup. -+ * -+ * Revision 1.191 2002/05/14 02:34:37 rgb -+ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips, -+ * ipsec_sa or ipsec_sa. -+ * -+ * Revision 1.190 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.189 2002/04/24 07:36:32 mcr -+ * Moved from ./klips/net/ipsec/ipsec_tunnel.c,v -+ * -+ * Revision 1.188 2002/04/20 00:12:25 rgb -+ * Added esp IV CBC attack fix, disabled. -+ * -+ * Revision 1.187 2002/03/23 19:55:17 rgb -+ * Fix for 2.2 local IKE fragmentation blackhole. Still won't work if -+ * iptraf or another pcap app is running. -+ * -+ * Revision 1.186 2002/03/19 03:26:22 rgb -+ * Applied DHR's tunnel patch to streamline IKE/specialSA processing. -+ * -+ * Revision 1.185 2002/02/20 04:13:05 rgb -+ * Send back ICMP_PKT_FILTERED upon %reject. -+ * -+ * Revision 1.184 2002/01/29 17:17:56 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.183 2002/01/29 04:00:53 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.182 2002/01/29 02:13:18 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.181 2002/01/07 20:00:33 rgb -+ * Added IKE destination port debugging. -+ * -+ * Revision 1.180 2001/12/21 21:49:54 rgb -+ * Fixed bug as a result of moving IKE bypass above %trap/%hold code. -+ * -+ * Revision 1.179 2001/12/19 21:08:14 rgb -+ * Added transport protocol ports to ipsec_print_ip(). -+ * Update eroute info for non-SA targets. -+ * Added obey DF code disabled. -+ * Fixed formatting bugs in ipsec_tunnel_hard_header(). -+ * -+ * Revision 1.178 2001/12/05 09:36:10 rgb -+ * Moved the UDP/500 IKE check just above the %hold/%trap checks to avoid -+ * IKE packets being stolen by the %hold (and returned to the sending KMd -+ * in an ACQUIRE, ironically ;-). -+ * -+ * Revision 1.177 2001/11/26 09:23:50 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.170.2.1 2001/09/25 02:28:27 mcr -+ * struct tdb -> struct ipsec_sa. -+ * lifetime checks moved to common routines. -+ * cleaned up includes. -+ * -+ * Revision 1.170.2.2 2001/10/22 21:08:01 mcr -+ * include des.h, removed phony prototypes and fixed calling -+ * conventions to match real prototypes. -+ * -+ * Revision 1.176 2001/11/09 18:32:31 rgb -+ * Added Hans Schultz' fragmented UDP/500 IKE socket port selector. -+ * -+ * Revision 1.175 2001/11/06 20:47:00 rgb -+ * Added Eric Espie's TRAPSUBNET fix, minus spin-lock-bh dabbling. -+ * -+ * Revision 1.174 2001/11/06 19:50:43 rgb -+ * Moved IP_SEND, ICMP_SEND, DEV_QUEUE_XMIT macros to ipsec_tunnel.h for -+ * use also by pfkey_v2_parser.c -+ * -+ * Revision 1.173 2001/10/29 21:53:44 henry -+ * tone down the device-down message slightly, until we can make it smarter -+ * -+ * Revision 1.172 2001/10/26 04:59:37 rgb -+ * Added a critical level syslog message if an ipsec device goes down. -+ * -+ * Revision 1.171 2001/10/18 04:45:21 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.170 2001/09/25 00:09:50 rgb -+ * Added NetCelo's TRAPSUBNET code to convert a new type TRAPSUBNET into a -+ * HOLD. -+ * -+ * Revision 1.169 2001/09/15 16:24:05 rgb -+ * Re-inject first and last HOLD packet when an eroute REPLACE is done. -+ * -+ * Revision 1.168 2001/09/14 16:58:37 rgb -+ * Added support for storing the first and last packets through a HOLD. -+ * -+ * Revision 1.167 2001/09/08 21:13:33 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.166 2001/08/27 19:47:59 rgb -+ * Clear tdb before usage. -+ * Added comment: clear IF before calling routing? -+ * -+ * Revision 1.165 2001/07/03 01:23:53 rgb -+ * Send back ICMP iff DF set, !ICMP, offset==0, sysctl_icmp, iph->tot_len > -+ * emtu, and don't drop. -+ * -+ * Revision 1.164 2001/06/14 19:35:10 rgb -+ * Update copyright date. -+ * -+ * Revision 1.163 2001/06/06 20:28:51 rgb -+ * Added sanity checks for NULL skbs and devices. -+ * Added more debugging output to various functions. -+ * Removed redundant dev->priv argument to ipsec_tunnel_{at,de}tach(). -+ * Renamed ipsec_tunnel_attach() virtual and physical device arguments. -+ * Corrected neigh_setup() device function assignment. -+ * Keep valid pointers to ipsec_tunnel_*() on detach. -+ * Set dev->type to the originally-initiallised value. -+ * -+ * Revision 1.162 2001/06/01 07:28:04 rgb -+ * Added sanity checks for detached devices. Don't down virtual devices -+ * to prevent packets going out in the clear if the detached device comes -+ * back up. -+ * -+ * Revision 1.161 2001/05/30 08:14:52 rgb -+ * Removed vestiges of esp-null transforms. -+ * NetDev Notifier instrumentation to track down disappearing devices. -+ * -+ * Revision 1.160 2001/05/29 05:15:12 rgb -+ * Added SS' PMTU patch which notifies sender if packet doesn't fit -+ * physical MTU (if it wasn't ICMP) and then drops it. -+ * -+ * Revision 1.159 2001/05/27 06:12:12 rgb -+ * Added structures for pid, packet count and last access time to eroute. -+ * Added packet count to beginning of /proc/net/ipsec_eroute. -+ * -+ * Revision 1.158 2001/05/24 05:39:33 rgb -+ * Applied source zeroing to 2.2 ip_route_output() call as well to enable -+ * PASS eroutes for opportunism. -+ * -+ * Revision 1.157 2001/05/23 22:35:28 rgb -+ * 2.4 source override simplification. -+ * -+ * Revision 1.156 2001/05/23 21:41:31 rgb -+ * Added error return code printing on ip_route_output(). -+ * -+ * Revision 1.155 2001/05/23 05:09:13 rgb -+ * Fixed incorrect ip_route_output() failure message. -+ * -+ * Revision 1.154 2001/05/21 14:53:31 rgb -+ * Added debug statement for case when ip_route_output() fails, causing -+ * packet to be dropped, but log looked ok. -+ * -+ * Revision 1.153 2001/05/19 02:37:54 rgb -+ * Fixed missing comment termination. -+ * -+ * Revision 1.152 2001/05/19 02:35:50 rgb -+ * Debug code optimisation for non-debug speed. -+ * Kernel version compiler define comments. -+ * 2.2 and 2.4 kernel ip_send device and ip debug output added. -+ * -+ * Revision 1.151 2001/05/18 16:17:35 rgb -+ * Changed reference from "magic" to "shunt" SAs. -+ * -+ * Revision 1.150 2001/05/18 16:12:19 rgb -+ * Changed UDP/500 bypass test from 3 nested ifs to one anded if. -+ * -+ * Revision 1.149 2001/05/16 04:39:33 rgb -+ * Add default == eroute.dest to IKE bypass conditions for magic eroutes. -+ * -+ * Revision 1.148 2001/05/05 03:31:41 rgb -+ * IP frag debugging updates and enhancements. -+ * -+ * Revision 1.147 2001/05/03 19:41:40 rgb -+ * Added SS' skb_cow fix for 2.4.4. -+ * -+ * Revision 1.146 2001/04/30 19:28:16 rgb -+ * Update for 2.4.4. ip_select_ident() now has 3 args. -+ * -+ * Revision 1.145 2001/04/23 14:56:10 rgb -+ * Added spin_lock() check to prevent double-locking for multiple -+ * transforms and hence kernel lock-ups with SMP kernels. -+ * -+ * Revision 1.144 2001/04/21 23:04:45 rgb -+ * Define out skb->used for 2.4 kernels. -+ * Check if soft expire has already been sent before sending another to -+ * prevent ACQUIRE flooding. -+ * -+ * Revision 1.143 2001/03/16 07:37:21 rgb -+ * Added comments to all #endifs. -+ * -+ * Revision 1.142 2001/02/28 05:03:27 rgb -+ * Clean up and rationalise startup messages. -+ * -+ * Revision 1.141 2001/02/27 22:24:54 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.140 2001/02/27 06:40:12 rgb -+ * Fixed TRAP->HOLD eroute byte order. -+ * -+ * Revision 1.139 2001/02/26 20:38:59 rgb -+ * Added compiler defines for 2.4.x-specific code. -+ * -+ * Revision 1.138 2001/02/26 19:57:27 rgb -+ * Implement magic SAs %drop, %reject, %trap, %hold, %pass as part -+ * of the new SPD and to support opportunistic. -+ * Drop sysctl_ipsec_{no_eroute_pass,opportunistic}, replaced by magic SAs. -+ * -+ * Revision 1.137 2001/02/19 22:29:49 rgb -+ * Fixes for presence of active ipv6 segments which share ipsec physical -+ * device (gg). -+ * -+ * Revision 1.136 2001/01/29 22:30:38 rgb -+ * Fixed minor acquire debug printing bug. -+ * -+ * Revision 1.135 2001/01/29 22:19:45 rgb -+ * Zero source address for 2.4 bypass route lookup. -+ * -+ * Revision 1.134 2001/01/23 20:19:49 rgb -+ * 2.4 fix to remove removed is_clone member. -+ * -+ * Revision 1.133 2000/12/09 22:08:35 rgb -+ * Fix NET_23 bug, should be NETDEV_23. -+ * -+ * Revision 1.132 2000/12/01 06:54:50 rgb -+ * Fix for new 2.4 IP TTL default variable name. -+ * -+ * Revision 1.131 2000/11/09 20:52:15 rgb -+ * More spinlock shuffling, locking earlier and unlocking later in rcv to -+ * include ipcomp and prevent races, renaming some tdb variables that got -+ * forgotten, moving some unlocks to include tdbs and adding a missing -+ * unlock. Thanks to Svenning for some of these. -+ * -+ * Revision 1.130 2000/11/09 20:11:22 rgb -+ * Minor shuffles to fix non-standard kernel config option selection. -+ * -+ * Revision 1.129 2000/11/06 04:32:49 rgb -+ * Clean up debug printing. -+ * Copy skb->protocol for all kernel versions. -+ * Ditched spin_lock_irqsave in favour of spin_lock. -+ * Disabled TTL decrement, done in ip_forward. -+ * Added debug printing before pfkey_acquire(). -+ * Fixed printk-deltdbchain-spin_lock races (Svenning). -+ * Use defaultTTL for 2.1+ kernels. -+ * Add Svenning's adaptive content compression. -+ * Fix up debug display arguments. -+ * -+ * Revision 1.128 2000/09/28 00:58:57 rgb -+ * Moved the IKE passthrough check after the eroute lookup so we can pass -+ * IKE through intermediate tunnels. -+ * -+ * Revision 1.127 2000/09/22 17:52:11 rgb -+ * Fixed misleading ipcomp debug output. -+ * -+ * Revision 1.126 2000/09/22 04:22:56 rgb -+ * Fixed dumb spi->cpi conversion error. -+ * -+ * Revision 1.125 2000/09/21 04:34:48 rgb -+ * A few debug-specific things should be hidden under -+ * CONFIG_IPSEC_DEBUG.(MB) -+ * Improved ip_send() error handling.(MB) -+ * -+ * Revision 1.124 2000/09/21 03:40:58 rgb -+ * Added more debugging to try and track down the cpi outward copy problem. -+ * -+ * Revision 1.123 2000/09/19 07:08:49 rgb -+ * Added debugging to outgoing compression report. -+ * -+ * Revision 1.122 2000/09/18 19:21:26 henry -+ * RGB-supplied fix for RH5.2 problem -+ * -+ * Revision 1.121 2000/09/17 21:05:09 rgb -+ * Added tdb to skb_compress call to write in cpi. -+ * -+ * Revision 1.120 2000/09/17 16:57:16 rgb -+ * Added Svenning's patch to remove restriction of ipcomp to innermost -+ * transform. -+ * -+ * Revision 1.119 2000/09/15 11:37:01 rgb -+ * Merge in heavily modified Svenning Soerensen's -+ * IPCOMP zlib deflate code. -+ * -+ * Revision 1.118 2000/09/15 04:57:16 rgb -+ * Moved debug output after sanity check. -+ * Added tos copy sysctl. -+ * -+ * Revision 1.117 2000/09/12 03:22:51 rgb -+ * Converted ipsec_icmp, no_eroute_pass, opportunistic and #if0 debugs to -+ * sysctl. -+ * -+ * Revision 1.116 2000/09/08 19:18:19 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * Added outgoing opportunistic hook, ifdef'ed out. -+ * -+ * Revision 1.115 2000/08/30 05:27:29 rgb -+ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst. -+ * Kill remainder of tdb_xform, tdb_xdata, xformsw. -+ * -+ * Revision 1.114 2000/08/28 18:15:46 rgb -+ * Added MB's nf-debug reset patch. -+ * -+ * Revision 1.113 2000/08/27 02:26:40 rgb -+ * Send all no-eroute-bypass, pluto-bypass and passthrough packets through -+ * fragmentation machinery for 2.0, 2.2 and 2.4 kernels. -+ * -+ * Revision 1.112 2000/08/20 21:37:33 rgb -+ * Activated pfkey_expire() calls. -+ * Added a hard/soft expiry parameter to pfkey_expire(). (Momchil) -+ * Re-arranged the order of soft and hard expiry to conform to RFC2367. -+ * Clean up references to CONFIG_IPSEC_PFKEYv2. -+ * -+ * Revision 1.111 2000/08/01 14:51:51 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.110 2000/07/28 14:58:31 rgb -+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. -+ * -+ * Revision 1.109 2000/07/28 13:50:54 rgb -+ * Changed enet_statistics to net_device_stats and added back compatibility -+ * for pre-2.1.19. -+ * -+ * Revision 1.108 2000/05/16 03:03:11 rgb -+ * Updates for 2.3.99pre8 from MB. -+ * -+ * Revision 1.107 2000/05/10 23:08:21 rgb -+ * Print a debug warning about bogus packets received by the outgoing -+ * processing machinery only when klipsdebug is not set to none. -+ * Comment out the device initialisation informational messages. -+ * -+ * Revision 1.106 2000/05/10 19:17:14 rgb -+ * Define an IP_SEND macro, intending to have all packet passthroughs -+ * use fragmentation. This didn't quite work, but is a step in the -+ * right direction. -+ * Added buffer allocation debugging statements. -+ * Added configure option to shut off no eroute passthrough. -+ * Only check usetime against soft and hard limits if the tdb has been -+ * used. -+ * Cast output of ntohl so that the broken prototype doesn't make our -+ * compile noisy. -+ * -+ * Revision 1.105 2000/03/22 16:15:37 rgb -+ * Fixed renaming of dev_get (MB). -+ * -+ * Revision 1.104 2000/03/16 14:04:15 rgb -+ * Indented headers for readability. -+ * Fixed debug scope to enable compilation with debug off. -+ * Added macros for ip_chk_addr and IS_MYADDR for identifying self. -+ * -+ * Revision 1.103 2000/03/16 07:11:07 rgb -+ * Hardcode PF_KEYv2 support. -+ * Fixed bug which allowed UDP/500 packet from another machine -+ * through in the clear. -+ * Added disabled skb->protocol fix for ISDN/ASYNC PPP from Matjaz Godec. -+ * -+ * Revision 1.102 2000/03/14 12:26:59 rgb -+ * Added skb->nfct support for clearing netfilter conntrack bits (MB). -+ * -+ * Revision 1.101 2000/02/14 21:05:22 rgb -+ * Added MB's netif_queue fix for kernels 2.3.43+. -+ * -+ * Revision 1.100 2000/01/26 10:04:57 rgb -+ * Fixed noisy 2.0 printk arguments. -+ * -+ * Revision 1.99 2000/01/21 06:16:25 rgb -+ * Added sanity checks on skb_push(), skb_pull() to prevent panics. -+ * Switched to AF_ENCAP macro. -+ * Shortened debug output per packet and re-arranging debug_tunnel -+ * bitmap flags, while retaining necessary information to avoid -+ * trampling the kernel print ring buffer. -+ * Reformatted recursion switch code. -+ * Changed all references to tdb_proto to tdb_said.proto for clarity. -+ * -+ * Revision 1.98 2000/01/13 08:09:31 rgb -+ * Shuffled debug_tunnel switches to focus output. -+ * Fixed outgoing recursion bug, limiting to recursing only if the remote -+ * SG changes and if it is valid, ie. not passthrough. -+ * Clarified a number of debug messages. -+ * -+ * Revision 1.97 2000/01/10 16:37:16 rgb -+ * MB support for new ip_select_ident() upon disappearance of -+ * ip_id_count in 2.3.36+. -+ * -+ * Revision 1.96 1999/12/31 14:59:08 rgb -+ * MB fix to use new skb_copy_expand in kernel 2.3.35. -+ * -+ * Revision 1.95 1999/12/29 21:15:44 rgb -+ * Fix tncfg to aliased device bug. -+ * -+ * Revision 1.94 1999/12/22 04:26:06 rgb -+ * Converted all 'static' functions to 'DEBUG_NO_STATIC' to enable -+ * debugging by providing external labels to all functions with debugging -+ * turned on. -+ * -+ * Revision 1.93 1999/12/13 13:30:14 rgb -+ * Changed MTU reports and HW address reporting back to debug only. -+ * -+ * Revision 1.92 1999/12/07 18:57:56 rgb -+ * Fix PFKEY symbol compile error (SADB_*) without pfkey enabled. -+ * -+ * Revision 1.91 1999/12/01 22:15:36 rgb -+ * Add checks for LARVAL and DEAD SAs. -+ * Change state of SA from MATURE to DYING when a soft lifetime is -+ * reached and print debug warning. -+ * -+ * Revision 1.90 1999/11/23 23:04:04 rgb -+ * Use provided macro ADDRTOA_BUF instead of hardcoded value. -+ * Sort out pfkey and freeswan headers, putting them in a library path. -+ * -+ * Revision 1.89 1999/11/18 18:50:59 rgb -+ * Changed all device registrations for static linking to -+ * dynamic to reduce the number and size of patches. -+ * -+ * Revision 1.88 1999/11/18 04:09:19 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.87 1999/11/17 15:53:40 rgb -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * -+ * Revision 1.86 1999/10/16 18:25:37 rgb -+ * Moved SA lifetime expiry checks before packet processing. -+ * Expire SA on replay counter rollover. -+ * -+ * Revision 1.85 1999/10/16 04:24:31 rgb -+ * Add stats for time since last packet. -+ * -+ * Revision 1.84 1999/10/16 00:30:47 rgb -+ * Added SA lifetime counting. -+ * -+ * Revision 1.83 1999/10/15 22:15:57 rgb -+ * Clean out cruft. -+ * Add debugging. -+ * -+ * Revision 1.82 1999/10/08 18:26:19 rgb -+ * Fix 2.0.3x outgoing fragmented packet memory leak. -+ * -+ * Revision 1.81 1999/10/05 02:38:54 rgb -+ * Lower the default mtu of virtual devices to 16260. -+ * -+ * Revision 1.80 1999/10/03 18:56:41 rgb -+ * Spinlock support for 2.3.xx. -+ * Don't forget to undo spinlocks on error! -+ * Check for valid eroute before copying the structure. -+ * -+ * Revision 1.79 1999/10/01 15:44:53 rgb -+ * Move spinlock header include to 2.1> scope. -+ * -+ * Revision 1.78 1999/10/01 00:02:43 rgb -+ * Added tdb structure locking. -+ * Added eroute structure locking. -+ * -+ * Revision 1.77 1999/09/30 02:52:29 rgb -+ * Add Marc Boucher's Copy-On-Write code (same as ipsec_rcv.c). -+ * -+ * Revision 1.76 1999/09/25 19:31:27 rgb -+ * Refine MSS hack to affect SYN, but not SYN+ACK packets. -+ * -+ * Revision 1.75 1999/09/24 22:52:38 rgb -+ * Fix two things broken in 2.0.38 by trying to fix network notifiers. -+ * -+ * Revision 1.74 1999/09/24 00:30:37 rgb -+ * Add test for changed source as well as destination to check for -+ * recursion. -+ * -+ * Revision 1.73 1999/09/23 20:52:24 rgb -+ * Add James Morris' MSS hack patch, disabled. -+ * -+ * Revision 1.72 1999/09/23 20:22:40 rgb -+ * Enable, tidy and fix network notifier code. -+ * -+ * Revision 1.71 1999/09/23 18:09:05 rgb -+ * Clean up 2.2.x fragmenting traces. -+ * Disable dev->type switching, forcing ARPHRD_TUNNEL. -+ * -+ * Revision 1.70 1999/09/22 14:14:24 rgb -+ * Add sanity checks for revectored calls to prevent calling a downed I/F. -+ * -+ * Revision 1.69 1999/09/21 15:00:57 rgb -+ * Add Marc Boucher's packet size check. -+ * Flesh out network device notifier code. -+ * -+ * Revision 1.68 1999/09/18 11:39:57 rgb -+ * Start to add (disabled) netdevice notifier code. -+ * -+ * Revision 1.67 1999/09/17 23:44:40 rgb -+ * Add a comment warning potential code hackers to stay away from mac.raw. -+ * -+ * Revision 1.66 1999/09/17 18:04:02 rgb -+ * Add fix for unpredictable hard_header_len for ISDN folks (thanks MB). -+ * Ditch TTL decrement in 2.2 (MB). -+ * -+ * Revision 1.65 1999/09/15 23:15:35 henry -+ * Marc Boucher's PPP fixes -+ * -+ * Revision 1.64 1999/09/07 13:40:53 rgb -+ * Ditch unreliable references to skb->mac.raw. -+ * -+ * Revision 1.63 1999/08/28 11:33:09 rgb -+ * Check for null skb->mac pointer. -+ * -+ * Revision 1.62 1999/08/28 02:02:30 rgb -+ * Add Marc Boucher's fix for properly dealing with skb->sk. -+ * -+ * Revision 1.61 1999/08/27 05:23:05 rgb -+ * Clean up skb->data/raw/nh/h manipulation. -+ * Add Marc Boucher's mods to aid tcpdump. -+ * Add sanity checks to skb->raw/nh/h pointer copies in skb_copy_expand. -+ * Re-order hard_header stripping -- might be able to remove it... -+ * -+ * Revision 1.60 1999/08/26 20:01:02 rgb -+ * Tidy up compiler directives and macros. -+ * Re-enable ICMP for tunnels where inner_dst != outer_dst. -+ * Remove unnecessary skb->dev = physdev assignment affecting 2.2.x. -+ * -+ * Revision 1.59 1999/08/25 15:44:41 rgb -+ * Clean up from 2.2.x instrumenting for compilation under 2.0.36. -+ * -+ * Revision 1.58 1999/08/25 15:00:54 rgb -+ * Add dst cache code for 2.2.xx. -+ * Add sanity check for skb packet header pointers. -+ * Add/modify debugging instrumentation to *_start_xmit, *_hard_header and -+ * *_rebuild_header. -+ * Add neigh_* cache code. -+ * Change dev->type back to ARPHRD_TUNNEL. -+ * -+ * Revision 1.57 1999/08/17 21:50:23 rgb -+ * Fixed minor debug output bugs. -+ * Regrouped error recovery exit code. -+ * Added compiler directives to remove unwanted code and symbols. -+ * Shut off ICMP messages: to be refined to only send ICMP to remote systems. -+ * Add debugging code for output function addresses. -+ * Fix minor bug in (possibly unused) header_cache_bind function. -+ * Add device neighbour caching code. -+ * Change dev->type from ARPHRD_TUNNEL to physdev->type. -+ * -+ * Revision 1.56 1999/08/03 17:22:56 rgb -+ * Debug output clarification using KERN_* macros. Other inactive changes -+ * added. -+ * -+ * Revision 1.55 1999/08/03 16:58:46 rgb -+ * Fix skb_copy_expand size bug. Was getting incorrect size. -+ * -+ * Revision 1.54 1999/07/14 19:32:38 rgb -+ * Fix oversize packet crash and ssh stalling in 2.2.x kernels. -+ * -+ * Revision 1.53 1999/06/10 15:44:02 rgb -+ * Minor reformatting and clean-up. -+ * -+ * Revision 1.52 1999/05/09 03:25:36 rgb -+ * Fix bug introduced by 2.2 quick-and-dirty patch. -+ * -+ * Revision 1.51 1999/05/08 21:24:59 rgb -+ * Add casting to silence the 2.2.x compile. -+ * -+ * Revision 1.50 1999/05/05 22:02:32 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.49 1999/04/29 15:18:52 rgb -+ * Change gettdb parameter to a pointer to reduce stack loading and -+ * facilitate parameter sanity checking. -+ * Fix undetected bug that might have tried to access a null pointer. -+ * Eliminate unnessessary usage of tdb_xform member to further switch -+ * away from the transform switch to the algorithm switch. -+ * Add return values to init and cleanup functions. -+ * -+ * Revision 1.48 1999/04/16 15:38:00 rgb -+ * Minor rearrangement of freeing code to avoid memory leaks with impossible or -+ * rare situations. -+ * -+ * Revision 1.47 1999/04/15 15:37:25 rgb -+ * Forward check changes from POST1_00 branch. -+ * -+ * Revision 1.32.2.4 1999/04/13 21:00:18 rgb -+ * Ditch 'things I wish I had known before...'. -+ * -+ * Revision 1.32.2.3 1999/04/13 20:34:38 rgb -+ * Free skb after fragmentation. -+ * Use stats more effectively. -+ * Add I/F to mtu notch-down reporting. -+ * -+ * Revision 1.32.2.2 1999/04/02 04:26:14 rgb -+ * Backcheck from HEAD, pre1.0. -+ * -+ * Revision 1.46 1999/04/11 00:29:00 henry -+ * GPL boilerplate -+ * -+ * Revision 1.45 1999/04/07 15:42:01 rgb -+ * Fix mtu/ping bug AGAIN! -+ * -+ * Revision 1.44 1999/04/06 04:54:27 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.43 1999/04/04 03:57:07 rgb -+ * ip_fragment() doesn't free the supplied skb. Freed. -+ * -+ * Revision 1.42 1999/04/01 23:27:15 rgb -+ * Preload size of virtual mtu. -+ * -+ * Revision 1.41 1999/04/01 09:31:23 rgb -+ * Invert meaning of ICMP PMTUD config option and clarify. -+ * Code clean-up. -+ * -+ * Revision 1.40 1999/04/01 04:37:17 rgb -+ * SSH stalling bug fix. -+ * -+ * Revision 1.39 1999/03/31 23:44:28 rgb -+ * Don't send ICMP on DF and frag_off. -+ * -+ * Revision 1.38 1999/03/31 15:20:10 rgb -+ * Quiet down debugging. -+ * -+ * Revision 1.37 1999/03/31 08:30:31 rgb -+ * Add switch to shut off ICMP PMTUD packets. -+ * -+ * Revision 1.36 1999/03/31 05:44:47 rgb -+ * Keep PMTU reduction private. -+ * -+ * Revision 1.35 1999/03/27 15:13:02 rgb -+ * PMTU/fragmentation bug fix. -+ * -+ * Revision 1.34 1999/03/17 21:19:26 rgb -+ * Fix kmalloc nonatomic bug. -+ * -+ * Revision 1.33 1999/03/17 15:38:42 rgb -+ * Code clean-up. -+ * ESP_NULL IV bug fix. -+ * -+ * Revision 1.32 1999/03/01 20:44:25 rgb -+ * Code clean-up. -+ * Memory leak bug fix. -+ * -+ * Revision 1.31 1999/02/27 00:02:09 rgb -+ * Tune to report the MTU reduction once, rather than after every recursion -+ * through the encapsulating code, preventing tcp stream stalling. -+ * -+ * Revision 1.30 1999/02/24 20:21:01 rgb -+ * Reformat debug printk's. -+ * Fix recursive encapsulation, dynamic MTU bugs and add debugging code. -+ * Clean-up. -+ * -+ * Revision 1.29 1999/02/22 17:08:14 rgb -+ * Fix recursive encapsulation code. -+ * -+ * Revision 1.28 1999/02/19 18:27:02 rgb -+ * Improve DF, fragmentation and PMTU behaviour and add dynamic MTU discovery. -+ * -+ * Revision 1.27 1999/02/17 16:51:37 rgb -+ * Clean out unused cruft. -+ * Temporarily tone down volume of debug output. -+ * Temporarily shut off fragment rejection. -+ * Disabled temporary failed recursive encapsulation loop. -+ * -+ * Revision 1.26 1999/02/12 21:21:26 rgb -+ * Move KLIPS_PRINT to ipsec_netlink.h for accessibility. -+ * -+ * Revision 1.25 1999/02/11 19:38:27 rgb -+ * More clean-up. -+ * Add sanity checking for skb_copy_expand() to prevent kernel panics on -+ * skb_put() values out of range. -+ * Fix head/tailroom calculation causing skb_put() out-of-range values. -+ * Fix return values to prevent 'nonatomic alloc_skb' warnings. -+ * Allocate new skb iff needed. -+ * Added more debug statements. -+ * Make headroom depend on structure, not hard-coded values. -+ * -+ * Revision 1.24 1999/02/10 23:20:33 rgb -+ * Shut up annoying 'statement has no effect' compiler warnings with -+ * debugging compiled out. -+ * -+ * Revision 1.23 1999/02/10 22:36:30 rgb -+ * Clean-up obsolete, unused and messy code. -+ * Converted most IPSEC_DEBUG statements to KLIPS_PRINT macros. -+ * Rename ipsec_tunnel_do_xmit to ipsec_tunnel_start_xmit and eliminated -+ * original ipsec_tunnel_start_xmit. -+ * Send all packet with different inner and outer destinations directly to -+ * the attached physical device, rather than back through ip_forward, -+ * preventing disappearing routes problems. -+ * Do sanity checking before investing too much CPU in allocating new -+ * structures. -+ * Fail on IP header options: We cannot process them yet. -+ * Add some helpful comments. -+ * Use virtual device for parameters instead of physical device. -+ * -+ * Revision 1.22 1999/02/10 03:03:02 rgb -+ * Duh. Fixed the TTL bug: forgot to update the checksum. -+ * -+ * Revision 1.21 1999/02/09 23:17:53 rgb -+ * Add structure members to ipsec_print_ip debug function. -+ * Temporarily fix TTL bug preventing tunnel mode from functioning. -+ * -+ * Revision 1.20 1999/02/09 00:14:25 rgb -+ * Add KLIPSPRINT macro. (Not used yet, though.) -+ * Delete old ip_tunnel code (BADCODE). -+ * Decrement TTL in outgoing packet. -+ * Set TTL on new IPIP_TUNNEL to default, not existing packet TTL. -+ * Delete ethernet only feature and fix hard-coded hard_header_len. -+ * -+ * Revision 1.19 1999/01/29 17:56:22 rgb -+ * 64-bit re-fix submitted by Peter Onion. -+ * -+ * Revision 1.18 1999/01/28 22:43:24 rgb -+ * Fixed bug in ipsec_print_ip that caused an OOPS, found by P.Onion. -+ * -+ * Revision 1.17 1999/01/26 02:08:16 rgb -+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro. -+ * Removed dead code. -+ * -+ * Revision 1.16 1999/01/22 06:25:26 rgb -+ * Cruft clean-out. -+ * Added algorithm switch code. -+ * 64-bit clean-up. -+ * Passthrough on IPIP protocol, spi 0x0 fix. -+ * Enhanced debugging. -+ * -+ * Revision 1.15 1998/12/01 13:22:04 rgb -+ * Added support for debug printing of version info. -+ * -+ * Revision 1.14 1998/11/30 13:22:55 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.13 1998/11/17 21:13:52 rgb -+ * Put IKE port bypass debug output in user-switched debug statements. -+ * -+ * Revision 1.12 1998/11/13 13:20:25 rgb -+ * Fixed ntohs bug in udp/500 hole for IKE. -+ * -+ * Revision 1.11 1998/11/10 08:01:19 rgb -+ * Kill tcp/500 hole, keep udp/500 hole. -+ * -+ * Revision 1.10 1998/11/09 21:29:26 rgb -+ * If no eroute is found, discard packet and incr. tx_error. -+ * -+ * Revision 1.9 1998/10/31 06:50:00 rgb -+ * Add tcp/udp/500 bypass. -+ * Fixed up comments in #endif directives. -+ * -+ * Revision 1.8 1998/10/27 00:34:31 rgb -+ * Reformat debug output of IP headers. -+ * Newlines added before calls to ipsec_print_ip. -+ * -+ * Revision 1.7 1998/10/19 14:44:28 rgb -+ * Added inclusion of freeswan.h. -+ * sa_id structure implemented and used: now includes protocol. -+ * -+ * Revision 1.6 1998/10/09 04:31:35 rgb -+ * Added 'klips_debug' prefix to all klips printk debug statements. -+ * -+ * Revision 1.5 1998/08/28 03:09:51 rgb -+ * Prevent kernel log spam with default route through ipsec. -+ * -+ * Revision 1.4 1998/08/05 22:23:09 rgb -+ * Change setdev return code to ENXIO for a non-existant physical device. -+ * -+ * Revision 1.3 1998/07/29 20:41:11 rgb -+ * Add ipsec_tunnel_clear to clear all tunnel attachments. -+ * -+ * Revision 1.2 1998/06/25 20:00:33 rgb -+ * Clean up #endif comments. -+ * Rename dev_ipsec to dev_ipsec0 for consistency. -+ * Document ipsec device fields. -+ * Make ipsec_tunnel_probe visible from rest of kernel for static linking. -+ * Get debugging report for *every* ipsec device initialisation. -+ * Comment out redundant code. -+ * -+ * Revision 1.1 1998/06/18 21:27:50 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.8 1998/06/14 23:49:40 rgb -+ * Clarify version reporting on module loading. -+ * -+ * Revision 1.7 1998/05/27 23:19:20 rgb -+ * Added version reporting. -+ * -+ * Revision 1.6 1998/05/18 21:56:23 rgb -+ * Clean up for numerical consistency of output and cleaning up debug code. -+ * -+ * Revision 1.5 1998/05/12 02:44:23 rgb -+ * Clarifying 'no e-route to host' message. -+ * -+ * Revision 1.4 1998/04/30 15:34:35 rgb -+ * Enclosed most remaining debugging statements in #ifdef's to make it quieter. -+ * -+ * Revision 1.3 1998/04/21 21:28:54 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.2 1998/04/12 22:03:24 rgb -+ * Updated ESP-3DES-HMAC-MD5-96, -+ * ESP-DES-HMAC-MD5-96, -+ * AH-HMAC-MD5-96, -+ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository -+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts. -+ * -+ * Fixed eroute references in /proc/net/ipsec*. -+ * -+ * Started to patch module unloading memory leaks in ipsec_netlink and -+ * radij tree unloading. -+ * -+ * Revision 1.1 1998/04/09 03:06:12 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:04 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.5 1997/06/03 04:24:48 ji -+ * Added transport mode. -+ * Changed the way routing is done. -+ * Lots of bug fixes. -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:39:04 ji -+ * Minor cleanups. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * Local Variables: -+ * c-style: linux -+ * End: -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_xform.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,351 @@ -+/* -+ * Common routines for IPSEC transformations. -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+#include -+#include -+#include /* printk() */ -+ -+#include "freeswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#include /* get_random_bytes() */ -+#include -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+#endif -+#include -+#include -+ -+#include "freeswan/radij.h" -+#include "freeswan/ipsec_encap.h" -+#include "freeswan/ipsec_radij.h" -+#include "freeswan/ipsec_xform.h" -+#include "freeswan/ipsec_ipe4.h" -+#include "freeswan/ipsec_ah.h" -+#include "freeswan/ipsec_esp.h" -+ -+#include -+#include -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_xform = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#ifdef SPINLOCK -+spinlock_t tdb_lock = SPIN_LOCK_UNLOCKED; -+#else /* SPINLOCK */ -+spinlock_t tdb_lock; -+#endif /* SPINLOCK */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.63 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.62.30.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.62 2002/05/14 02:34:21 rgb -+ * Delete stale code. -+ * -+ * Revision 1.61 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.60 2002/04/24 07:36:33 mcr -+ * Moved from ./klips/net/ipsec/ipsec_xform.c,v -+ * -+ * Revision 1.59 2002/03/29 15:01:36 rgb -+ * Delete decommissioned code. -+ * -+ * Revision 1.58 2002/01/29 17:17:57 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.57 2002/01/29 04:00:53 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.56 2001/11/27 05:17:22 mcr -+ * turn off the worst of the per-packet debugging. -+ * -+ * Revision 1.55 2001/11/26 09:23:50 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.54 2001/10/18 04:45:21 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.53 2001/09/08 21:13:34 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * -+ * Revision 1.52 2001/06/14 19:35:11 rgb -+ * Update copyright date. -+ * -+ * Revision 1.51 2001/05/30 08:14:03 rgb -+ * Removed vestiges of esp-null transforms. -+ * -+ * Revision 1.50 2001/05/03 19:43:18 rgb -+ * Initialise error return variable. -+ * Update SENDERR macro. -+ * Fix sign of error return code for ipsec_tdbcleanup(). -+ * Use more appropriate return code for ipsec_tdbwipe(). -+ * -+ * Revision 1.49 2001/04/19 18:56:17 rgb -+ * Fixed tdb table locking comments. -+ * -+ * Revision 1.48 2001/02/27 22:24:55 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.47 2000/11/06 04:32:08 rgb -+ * Ditched spin_lock_irqsave in favour of spin_lock_bh. -+ * -+ * Revision 1.46 2000/09/20 16:21:57 rgb -+ * Cleaned up ident string alloc/free. -+ * -+ * Revision 1.45 2000/09/08 19:16:51 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * Removed all references to CONFIG_IPSEC_PFKEYv2. -+ * -+ * Revision 1.44 2000/08/30 05:29:04 rgb -+ * Compiler-define out no longer used tdb_init() in ipsec_xform.c. -+ * -+ * Revision 1.43 2000/08/18 21:30:41 rgb -+ * Purged all tdb_spi, tdb_proto and tdb_dst macros. They are unclear. -+ * -+ * Revision 1.42 2000/08/01 14:51:51 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.41 2000/07/28 14:58:31 rgb -+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. -+ * -+ * Revision 1.40 2000/06/28 05:50:11 rgb -+ * Actually set iv_bits. -+ * -+ * Revision 1.39 2000/05/10 23:11:09 rgb -+ * Added netlink debugging output. -+ * Added a cast to quiet down the ntohl bug. -+ * -+ * Revision 1.38 2000/05/10 19:18:42 rgb -+ * Cast output of ntohl so that the broken prototype doesn't make our -+ * compile noisy. -+ * -+ * Revision 1.37 2000/03/16 14:04:59 rgb -+ * Hardwired CONFIG_IPSEC_PFKEYv2 on. -+ * -+ * Revision 1.36 2000/01/26 10:11:28 rgb -+ * Fixed spacing in error text causing run-in words. -+ * -+ * Revision 1.35 2000/01/21 06:17:16 rgb -+ * Tidied up compiler directive indentation for readability. -+ * Added ictx,octx vars for simplification.(kravietz) -+ * Added macros for HMAC padding magic numbers.(kravietz) -+ * Fixed missing key length reporting bug. -+ * Fixed bug in tdbwipe to return immediately on NULL tdbp passed in. -+ * -+ * Revision 1.34 1999/12/08 00:04:19 rgb -+ * Fixed SA direction overwriting bug for netlink users. -+ * -+ * Revision 1.33 1999/12/01 22:16:44 rgb -+ * Minor formatting changes in ESP MD5 initialisation. -+ * -+ * Revision 1.32 1999/11/25 09:06:36 rgb -+ * Fixed error return messages, should be returning negative numbers. -+ * Implemented SENDERR macro for propagating error codes. -+ * Added debug message and separate error code for algorithms not compiled -+ * in. -+ * -+ * Revision 1.31 1999/11/23 23:06:26 rgb -+ * Sort out pfkey and freeswan headers, putting them in a library path. -+ * -+ * Revision 1.30 1999/11/18 04:09:20 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.29 1999/11/17 15:53:40 rgb -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * -+ * Revision 1.28 1999/10/18 20:04:01 rgb -+ * Clean-out unused cruft. -+ * -+ * Revision 1.27 1999/10/03 19:01:03 rgb -+ * Spinlock support for 2.3.xx and 2.0.xx kernels. -+ * -+ * Revision 1.26 1999/10/01 16:22:24 rgb -+ * Switch from assignment init. to functional init. of spinlocks. -+ * -+ * Revision 1.25 1999/10/01 15:44:54 rgb -+ * Move spinlock header include to 2.1> scope. -+ * -+ * Revision 1.24 1999/10/01 00:03:46 rgb -+ * Added tdb structure locking. -+ * Minor formatting changes. -+ * Add function to initialize tdb hash table. -+ * -+ * Revision 1.23 1999/05/25 22:42:12 rgb -+ * Add deltdbchain() debugging. -+ * -+ * Revision 1.22 1999/05/25 21:24:31 rgb -+ * Add debugging statements to deltdbchain(). -+ * -+ * Revision 1.21 1999/05/25 03:51:48 rgb -+ * Refix error return code. -+ * -+ * Revision 1.20 1999/05/25 03:34:07 rgb -+ * Fix error return for flush. -+ * -+ * Revision 1.19 1999/05/09 03:25:37 rgb -+ * Fix bug introduced by 2.2 quick-and-dirty patch. -+ * -+ * Revision 1.18 1999/05/05 22:02:32 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.17 1999/04/29 15:20:16 rgb -+ * Change gettdb parameter to a pointer to reduce stack loading and -+ * facilitate parameter sanity checking. -+ * Add sanity checking for null pointer arguments. -+ * Add debugging instrumentation. -+ * Add function deltdbchain() which will take care of unlinking, -+ * zeroing and deleting a chain of tdbs. -+ * Add a parameter to tdbcleanup to be able to delete a class of SAs. -+ * tdbwipe now actually zeroes the tdb as well as any of its pointed -+ * structures. -+ * -+ * Revision 1.16 1999/04/16 15:36:29 rgb -+ * Fix cut-and-paste error causing a memory leak in IPIP TDB freeing. -+ * -+ * Revision 1.15 1999/04/11 00:29:01 henry -+ * GPL boilerplate -+ * -+ * Revision 1.14 1999/04/06 04:54:28 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.13 1999/02/19 18:23:01 rgb -+ * Nix debug off compile warning. -+ * -+ * Revision 1.12 1999/02/17 16:52:16 rgb -+ * Consolidate satoa()s for space and speed efficiency. -+ * Convert DEBUG_IPSEC to KLIPS_PRINT -+ * Clean out unused cruft. -+ * Ditch NET_IPIP dependancy. -+ * Loop for 3des key setting. -+ * -+ * Revision 1.11 1999/01/26 02:09:05 rgb -+ * Remove ah/esp/IPIP switching on include files. -+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro. -+ * Removed dead code. -+ * Clean up debug code when switched off. -+ * Remove references to INET_GET_PROTOCOL. -+ * Added code exclusion macros to reduce code from unused algorithms. -+ * -+ * Revision 1.10 1999/01/22 06:28:55 rgb -+ * Cruft clean-out. -+ * Put random IV generation in kernel. -+ * Added algorithm switch code. -+ * Enhanced debugging. -+ * 64-bit clean-up. -+ * -+ * Revision 1.9 1998/11/30 13:22:55 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.8 1998/11/25 04:59:06 rgb -+ * Add conditionals for no IPIP tunnel code. -+ * Delete commented out code. -+ * -+ * Revision 1.7 1998/10/31 06:50:41 rgb -+ * Convert xform ASCII names to no spaces. -+ * Fixed up comments in #endif directives. -+ * -+ * Revision 1.6 1998/10/19 14:44:28 rgb -+ * Added inclusion of freeswan.h. -+ * sa_id structure implemented and used: now includes protocol. -+ * -+ * Revision 1.5 1998/10/09 04:32:19 rgb -+ * Added 'klips_debug' prefix to all klips printk debug statements. -+ * -+ * Revision 1.4 1998/08/12 00:11:31 rgb -+ * Added new xform functions to the xform table. -+ * Fixed minor debug output spelling error. -+ * -+ * Revision 1.3 1998/07/09 17:45:31 rgb -+ * Clarify algorithm not available message. -+ * -+ * Revision 1.2 1998/06/23 03:00:51 rgb -+ * Check for presence of IPIP protocol if it is setup one way (we don't -+ * know what has been set up the other way and can only assume it will be -+ * symmetrical with the exception of keys). -+ * -+ * Revision 1.1 1998/06/18 21:27:51 henry -+ * move sources from klips/src to klips/net/ipsec, to keep stupid -+ * kernel-build scripts happier in the presence of symlinks -+ * -+ * Revision 1.3 1998/06/11 05:54:59 rgb -+ * Added transform version string pointer to xformsw initialisations. -+ * -+ * Revision 1.2 1998/04/21 21:28:57 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.1 1998/04/09 03:06:13 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:02 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.5 1997/06/03 04:24:48 ji -+ * Added ESP-3DES-MD5-96 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * Added new transforms. -+ * -+ * Revision 0.3 1996/11/20 14:39:04 ji -+ * Minor cleanups. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/ipsec_xmit.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1869 @@ -+/* -+ * IPSEC Transmit code. -+ * Copyright (C) 1996, 1997 John Ioannidis. -+ * Copyright (C) 1998-2003 Richard Guy Briggs. -+ * Copyright (C) 2004 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ */ -+ -+char ipsec_xmit_c_version[] = "RCSID $Id$"; -+ -+#define __NO_VERSION__ -+#include -+#include /* for CONFIG_IP_FORWARD */ -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include /* struct tcphdr */ -+#include /* struct udphdr */ -+#include -+#include -+#ifdef NET_21 -+# define MSS_HACK_ /* experimental */ -+# include -+# include -+# include -+# define proto_priv cb -+#endif /* NET_21 */ -+#include -+#include /* icmp_send() */ -+#include -+#ifdef NETDEV_23 -+# include -+#endif /* NETDEV_23 */ -+ -+#include -+#ifdef MSS_HACK -+# include /* TCP options */ -+#endif /* MSS_HACK */ -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_life.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_eroute.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xmit.h" -+#include "openswan/ipsec_sa.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_ipe4.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+ -+#ifdef CONFIG_IPSEC_IPCOMP -+#include "openswan/ipcomp.h" -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+#include "openswan/ipsec_alg.h" -+ -+ -+/* -+ * Stupid kernel API differences in APIs. Not only do some -+ * kernels not have ip_select_ident, but some have differing APIs, -+ * and SuSE has one with one parameter, but no way of checking to -+ * see what is really what. -+ */ -+ -+#ifdef SUSE_LINUX_2_4_19_IS_STUPID -+#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph) -+#else -+ -+/* simplest case, nothing */ -+#if !defined(IP_SELECT_IDENT) -+#define KLIPS_IP_SELECT_IDENT(iph, skb) do { iph->id = htons(ip_id_count++); } while(0) -+#endif -+ -+/* kernels > 2.3.37-ish */ -+#if defined(IP_SELECT_IDENT) && !defined(IP_SELECT_IDENT_NEW) -+#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst) -+#endif -+ -+/* kernels > 2.4.2 */ -+#if defined(IP_SELECT_IDENT) && defined(IP_SELECT_IDENT_NEW) -+#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst, NULL) -+#endif -+ -+#endif /* SUSE_LINUX_2_4_19_IS_STUPID */ -+ -+ -+static __u32 zeroes[64]; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int sysctl_ipsec_debug_verbose = 0; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+int ipsec_xmit_trap_count = 0; -+int ipsec_xmit_trap_sendcount = 0; -+ -+int sysctl_ipsec_icmp = 0; -+int sysctl_ipsec_tos = 0; -+ -+#ifdef CONFIG_IPSEC_DEBUG_ -+DEBUG_NO_STATIC void -+dmp(char *s, caddr_t bb, int len) -+{ -+ int i; -+ unsigned char *b = bb; -+ -+ if (debug_tunnel) { -+ printk(KERN_INFO "klips_debug:ipsec_tunnel_:dmp: " -+ "at %s, len=%d:", -+ s, -+ len); -+ for (i=0; i < len; i++) { -+ if(!(i%16)){ -+ printk("\nklips_debug: "); -+ } -+ printk(" %02x", *b++); -+ } -+ printk("\n"); -+ } -+} -+#else /* CONFIG_IPSEC_DEBUG */ -+#define dmp(_x, _y, _z) -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#ifndef SKB_COPY_EXPAND -+/* -+ * This is mostly skbuff.c:skb_copy(). -+ */ -+struct sk_buff * -+skb_copy_expand(struct sk_buff *skb, int headroom, int tailroom, int priority) -+{ -+ struct sk_buff *n; -+ unsigned long offset; -+ -+ /* -+ * Do sanity checking -+ */ -+ if((headroom < 0) || (tailroom < 0) || ((headroom+tailroom) < 0)) { -+ printk(KERN_WARNING -+ "klips_error:skb_copy_expand: " -+ "Illegal negative head,tailroom %d,%d\n", -+ headroom, -+ tailroom); -+ return NULL; -+ } -+ /* -+ * Allocate the copy buffer -+ */ -+ -+#ifndef NET_21 -+ IS_SKB(skb); -+#endif /* !NET_21 */ -+ -+ -+ n=alloc_skb(skb->end - skb->head + headroom + tailroom, priority); -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:skb_copy_expand: " -+ "allocating %d bytes, head=0p%p data=0p%p tail=0p%p end=0p%p end-head=%d tail-data=%d\n", -+ skb->end - skb->head + headroom + tailroom, -+ skb->head, -+ skb->data, -+ skb->tail, -+ skb->end, -+ skb->end - skb->head, -+ skb->tail - skb->data); -+ -+ if(n==NULL) -+ return NULL; -+ -+ /* -+ * Shift between the two data areas in bytes -+ */ -+ -+ /* Set the data pointer */ -+ skb_reserve(n,skb->data-skb->head+headroom); -+ /* Set the tail pointer and length */ -+ if(skb_tailroom(n) < skb->len) { -+ printk(KERN_WARNING "klips_error:skb_copy_expand: " -+ "tried to skb_put %ld, %d available. This should never happen, please report.\n", -+ (unsigned long int)skb->len, -+ skb_tailroom(n)); -+ ipsec_kfree_skb(n); -+ return NULL; -+ } -+ skb_put(n,skb->len); -+ -+ offset=n->head + headroom - skb->head; -+ -+ /* Copy the bytes */ -+ memcpy(n->head + headroom, skb->head,skb->end-skb->head); -+#ifdef NET_21 -+ n->csum=skb->csum; -+ n->priority=skb->priority; -+ n->dst=dst_clone(skb->dst); -+ if(skb->nh.raw) -+ n->nh.raw=skb->nh.raw+offset; -+#ifndef NETDEV_23 -+ n->is_clone=0; -+#endif /* NETDEV_23 */ -+ atomic_set(&n->users, 1); -+ n->destructor = NULL; -+ n->security=skb->security; -+#else /* NET_21 */ -+ n->link3=NULL; -+ n->when=skb->when; -+ if(skb->ip_hdr) -+ n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset); -+ n->saddr=skb->saddr; -+ n->daddr=skb->daddr; -+ n->raddr=skb->raddr; -+ n->seq=skb->seq; -+ n->end_seq=skb->end_seq; -+ n->ack_seq=skb->ack_seq; -+ n->acked=skb->acked; -+ n->free=1; -+ n->arp=skb->arp; -+ n->tries=0; -+ n->lock=0; -+ n->users=0; -+#endif /* NET_21 */ -+ n->protocol=skb->protocol; -+ n->list=NULL; -+ n->sk=NULL; -+ n->dev=skb->dev; -+ if(skb->h.raw) -+ n->h.raw=skb->h.raw+offset; -+ if(skb->mac.raw) -+ n->mac.raw=skb->mac.raw+offset; -+ memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv)); -+#ifndef NETDEV_23 -+ n->used=skb->used; -+#endif /* !NETDEV_23 */ -+ n->pkt_type=skb->pkt_type; -+ n->stamp=skb->stamp; -+ -+#ifndef NET_21 -+ IS_SKB(n); -+#endif /* !NET_21 */ -+ return n; -+} -+#endif /* !SKB_COPY_EXPAND */ -+ -+#ifdef CONFIG_IPSEC_DEBUG -+void -+ipsec_print_ip(struct iphdr *ip) -+{ -+ char buf[ADDRTOA_BUF]; -+ -+ printk(KERN_INFO "klips_debug: IP:"); -+ printk(" ihl:%d", ip->ihl << 2); -+ printk(" ver:%d", ip->version); -+ printk(" tos:%d", ip->tos); -+ printk(" tlen:%d", ntohs(ip->tot_len)); -+ printk(" id:%d", ntohs(ip->id)); -+ printk(" %s%s%sfrag_off:%d", -+ ip->frag_off & __constant_htons(IP_CE) ? "CE " : "", -+ ip->frag_off & __constant_htons(IP_DF) ? "DF " : "", -+ ip->frag_off & __constant_htons(IP_MF) ? "MF " : "", -+ (ntohs(ip->frag_off) & IP_OFFSET) << 3); -+ printk(" ttl:%d", ip->ttl); -+ printk(" proto:%d", ip->protocol); -+ if(ip->protocol == IPPROTO_UDP) -+ printk(" (UDP)"); -+ if(ip->protocol == IPPROTO_TCP) -+ printk(" (TCP)"); -+ if(ip->protocol == IPPROTO_ICMP) -+ printk(" (ICMP)"); -+ printk(" chk:%d", ntohs(ip->check)); -+ addrtoa(*((struct in_addr*)(&ip->saddr)), 0, buf, sizeof(buf)); -+ printk(" saddr:%s", buf); -+ if(ip->protocol == IPPROTO_UDP) -+ printk(":%d", -+ ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->source)); -+ if(ip->protocol == IPPROTO_TCP) -+ printk(":%d", -+ ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->source)); -+ addrtoa(*((struct in_addr*)(&ip->daddr)), 0, buf, sizeof(buf)); -+ printk(" daddr:%s", buf); -+ if(ip->protocol == IPPROTO_UDP) -+ printk(":%d", -+ ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest)); -+ if(ip->protocol == IPPROTO_TCP) -+ printk(":%d", -+ ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest)); -+ if(ip->protocol == IPPROTO_ICMP) -+ printk(" type:code=%d:%d", -+ ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->type, -+ ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->code); -+ printk("\n"); -+ -+ if(sysctl_ipsec_debug_verbose) { -+ __u8 *c; -+ int i; -+ -+ c = ((__u8*)ip) + ip->ihl*4; -+ for(i = 0; i < ntohs(ip->tot_len) - ip->ihl*4; i++ /*, c++*/) { -+ if(!(i % 16)) { -+ printk(KERN_INFO -+ "klips_debug: @%03x:", -+ i); -+ } -+ printk(" %02x", /***/c[i]); -+ if(!((i + 1) % 16)) { -+ printk("\n"); -+ } -+ } -+ if(i % 16) { -+ printk("\n"); -+ } -+ } -+} -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#ifdef MSS_HACK -+/* -+ * Issues: -+ * 1) Fragments arriving in the tunnel should probably be rejected. -+ * 2) How does this affect syncookies, mss_cache, dst cache ? -+ * 3) Path MTU discovery handling needs to be reviewed. For example, -+ * if we receive an ICMP 'packet too big' message from an intermediate -+ * router specifying it's next hop MTU, our stack may process this and -+ * adjust the MSS without taking our AH/ESP overheads into account. -+ */ -+ -+ -+/* -+ * Recaclulate checksum using differences between changed datum, -+ * borrowed from netfilter. -+ */ -+DEBUG_NO_STATIC u_int16_t -+ipsec_fast_csum(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck) -+{ -+ u_int32_t diffs[] = { oldvalinv, newval }; -+ return csum_fold(csum_partial((char *)diffs, sizeof(diffs), -+ oldcheck^0xFFFF)); -+} -+ -+/* -+ * Determine effective MSS. -+ * -+ * Note that we assume that there is always an MSS option for our own -+ * SYN segments, which is mentioned in tcp_syn_build_options(), kernel 2.2.x. -+ * This could change, and we should probably parse TCP options instead. -+ * -+ */ -+DEBUG_NO_STATIC u_int8_t -+ipsec_adjust_mss(struct sk_buff *skb, struct tcphdr *tcph, u_int16_t mtu) -+{ -+ u_int16_t oldmss, newmss; -+ u_int32_t *mssp; -+ struct sock *sk = skb->sk; -+ -+ newmss = tcp_sync_mss(sk, mtu); -+ printk(KERN_INFO "klips: setting mss to %u\n", newmss); -+ mssp = (u_int32_t *)tcph + sizeof(struct tcphdr) / sizeof(u_int32_t); -+ oldmss = ntohl(*mssp) & 0x0000FFFF; -+ *mssp = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | newmss); -+ tcph->check = ipsec_fast_csum(htons(~oldmss), -+ htons(newmss), tcph->check); -+ return 1; -+} -+#endif /* MSS_HACK */ -+ -+/* -+ * Sanity checks -+ */ -+enum ipsec_xmit_value -+ipsec_xmit_sanity_check_dev(struct ipsec_xmit_state *ixs) -+{ -+ -+ if (ixs->dev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_error:ipsec_xmit_sanity_check_dev: " -+ "No device associated with skb!\n" ); -+ return IPSEC_XMIT_NODEV; -+ } -+ -+ ixs->prv = ixs->dev->priv; -+ if (ixs->prv == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_error:ipsec_xmit_sanity_check_dev: " -+ "Device has no private structure!\n" ); -+ return IPSEC_XMIT_NOPRIVDEV; -+ } -+ -+ ixs->physdev = ixs->prv->dev; -+ if (ixs->physdev == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_error:ipsec_xmit_sanity_check_dev: " -+ "Device is not attached to physical device!\n" ); -+ return IPSEC_XMIT_NOPHYSDEV; -+ } -+ -+ ixs->physmtu = ixs->physdev->mtu; -+ -+ ixs->stats = (struct net_device_stats *) &(ixs->prv->mystats); -+ -+ return IPSEC_XMIT_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_xmit_sanity_check_skb(struct ipsec_xmit_state *ixs) -+{ -+ /* -+ * Return if there is nothing to do. (Does this ever happen?) XXX -+ */ -+ if (ixs->skb == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_error:ipsec_xmit_sanity_check_skb: " -+ "Nothing to do!\n" ); -+ return IPSEC_XMIT_NOSKB; -+ } -+#ifdef NET_21 -+ /* if skb was cloned (most likely due to a packet sniffer such as -+ tcpdump being momentarily attached to the interface), make -+ a copy of our own to modify */ -+ if(skb_cloned(ixs->skb)) { -+ if -+#ifdef SKB_COW_NEW -+ (skb_cow(ixs->skb, skb_headroom(ixs->skb)) != 0) -+#else /* SKB_COW_NEW */ -+ ((ixs->skb = skb_cow(ixs->skb, skb_headroom(ixs->skb))) == NULL) -+#endif /* SKB_COW_NEW */ -+ { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_error:ipsec_xmit_sanity_check_skb: " -+ "skb_cow failed to allocate buffer, dropping.\n" ); -+ ixs->stats->tx_dropped++; -+ return IPSEC_XMIT_ERRSKBALLOC; -+ } -+ } -+#endif /* NET_21 */ -+ -+#ifdef NET_21 -+ ixs->iph = ixs->skb->nh.iph; -+#else /* NET_21 */ -+ ixs->iph = ixs->skb->ip_hdr; -+#endif /* NET_21 */ -+ -+ /* sanity check for IP version as we can't handle IPv6 right now */ -+ if (ixs->iph->version != 4) { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_xmit_sanity_check_skb: " -+ "found IP Version %d but cannot process other IP versions than v4.\n", -+ ixs->iph->version); /* XXX */ -+ ixs->stats->tx_dropped++; -+ return IPSEC_XMIT_NOIPV6; -+ } -+ -+#if IPSEC_DISALLOW_IPOPTIONS -+ if ((ixs->iph->ihl << 2) != sizeof (struct iphdr)) { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_xmit_sanity_check_skb: " -+ "cannot process IP header options yet. May be mal-formed packet.\n"); /* XXX */ -+ ixs->stats->tx_dropped++; -+ return IPSEC_XMIT_NOIPOPTIONS; -+ } -+#endif /* IPSEC_DISALLOW_IPOPTIONS */ -+ -+#ifndef NET_21 -+ if (ixs->iph->ttl <= 0) { -+ /* Tell the sender its packet died... */ -+ ICMP_SEND(ixs->skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, ixs->physdev); -+ -+ KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_xmit_sanity_check_skb: " -+ "TTL=0, too many hops!\n"); -+ ixs->stats->tx_dropped++; -+ return IPSEC_XMIT_TTLEXPIRED; -+ } -+#endif /* !NET_21 */ -+ -+ return IPSEC_XMIT_OK; -+} -+ -+enum ipsec_xmit_value -+ipsec_xmit_encap_once(struct ipsec_xmit_state *ixs) -+{ -+#ifdef CONFIG_IPSEC_ESP -+ struct esphdr *espp; -+#ifdef CONFIG_IPSEC_ENC_3DES -+ __u32 iv[ESP_IV_MAXSZ_INT]; -+#endif /* !CONFIG_IPSEC_ENC_3DES */ -+ unsigned char *idat, *pad; -+ int authlen = 0, padlen = 0, i; -+#endif /* !CONFIG_IPSEC_ESP */ -+#ifdef CONFIG_IPSEC_AH -+ struct iphdr ipo; -+ struct ahhdr *ahp; -+#endif /* CONFIG_IPSEC_AH */ -+#if defined(CONFIG_IPSEC_AUTH_HMAC_MD5) || defined(CONFIG_IPSEC_AUTH_HMAC_SHA1) -+ union { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ MD5_CTX md5; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ SHA1_CTX sha1; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ } tctx; -+ __u8 hash[AH_AMAX]; -+#endif /* defined(CONFIG_IPSEC_AUTH_HMAC_MD5) || defined(CONFIG_IPSEC_AUTH_HMAC_SHA1) */ -+ int headroom = 0, tailroom = 0, ilen = 0, len = 0; -+ unsigned char *dat; -+ int blocksize = 8; /* XXX: should be inside ixs --jjo */ -+#ifdef CONFIG_IPSEC_ALG -+ struct ipsec_alg_enc *ixt_e = NULL; -+ struct ipsec_alg_auth *ixt_a = NULL; -+#endif /* CONFIG_IPSEC_ALG */ -+ -+ ixs->iphlen = ixs->iph->ihl << 2; -+ ixs->pyldsz = ntohs(ixs->iph->tot_len) - ixs->iphlen; -+ ixs->sa_len = satot(&ixs->ipsp->ips_said, 0, ixs->sa_txt, SATOT_BUF); -+ KLIPS_PRINT(debug_tunnel & DB_TN_OXFS, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "calling output for <%s%s%s>, SA:%s\n", -+ IPS_XFORM_NAME(ixs->ipsp), -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ -+ switch(ixs->ipsp->ips_said.proto) { -+#ifdef CONFIG_IPSEC_AH -+ case IPPROTO_AH: -+ headroom += sizeof(struct ahhdr); -+ break; -+#endif /* CONFIG_IPSEC_AH */ -+#ifdef CONFIG_IPSEC_ESP -+ case IPPROTO_ESP: -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_e=ixs->ipsp->ips_alg_enc)) { -+ blocksize = ixt_e->ixt_blocksize; -+ headroom += ESP_HEADER_LEN + ixt_e->ixt_ivlen/8; -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_encalg) { -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+ headroom += sizeof(struct esphdr); -+ break; -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_a=ixs->ipsp->ips_alg_auth)) { -+ tailroom += AHHMAC_HASHLEN; -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_authalg) { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: -+ authlen = AHHMAC_HASHLEN; -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: -+ authlen = AHHMAC_HASHLEN; -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ case AH_NONE: -+ break; -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+#ifdef CONFIG_IPSEC_ALG -+ tailroom += blocksize != 1 ? -+ ((blocksize - ((ixs->pyldsz + 2) % blocksize)) % blocksize) + 2 : -+ ((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2; -+#else -+ tailroom += ((8 - ((ixs->pyldsz + 2 * sizeof(unsigned char)) % 8)) % 8) + 2; -+#endif /* CONFIG_IPSEC_ALG */ -+ tailroom += authlen; -+ break; -+#endif /* !CONFIG_IPSEC_ESP */ -+#ifdef CONFIG_IPSEC_IPIP -+ case IPPROTO_IPIP: -+ headroom += sizeof(struct iphdr); -+ ixs->iphlen = sizeof(struct iphdr); -+ break; -+#endif /* !CONFIG_IPSEC_IPIP */ -+#ifdef CONFIG_IPSEC_IPCOMP -+ case IPPROTO_COMP: -+ break; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_BADPROTO; -+ } -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "pushing %d bytes, putting %d, proto %d.\n", -+ headroom, tailroom, ixs->ipsp->ips_said.proto); -+ if(skb_headroom(ixs->skb) < headroom) { -+ printk(KERN_WARNING -+ "klips_error:ipsec_xmit_encap_once: " -+ "tried to skb_push headroom=%d, %d available. This should never happen, please report.\n", -+ headroom, skb_headroom(ixs->skb)); -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_PUSHPULLERR; -+ } -+ dat = skb_push(ixs->skb, headroom); -+ ilen = ixs->skb->len - tailroom; -+ if(skb_tailroom(ixs->skb) < tailroom) { -+ printk(KERN_WARNING -+ "klips_error:ipsec_xmit_encap_once: " -+ "tried to skb_put %d, %d available. This should never happen, please report.\n", -+ tailroom, skb_tailroom(ixs->skb)); -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_PUSHPULLERR; -+ } -+ skb_put(ixs->skb, tailroom); -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "head,tailroom: %d,%d before xform.\n", -+ skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); -+ len = ixs->skb->len; -+ if(len > 0xfff0) { -+ printk(KERN_WARNING "klips_error:ipsec_xmit_encap_once: " -+ "tot_len (%d) > 65520. This should never happen, please report.\n", -+ len); -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_BADLEN; -+ } -+ memmove((void *)dat, (void *)(dat + headroom), ixs->iphlen); -+ ixs->iph = (struct iphdr *)dat; -+ ixs->iph->tot_len = htons(ixs->skb->len); -+ -+ switch(ixs->ipsp->ips_said.proto) { -+#ifdef CONFIG_IPSEC_ESP -+ case IPPROTO_ESP: -+ espp = (struct esphdr *)(dat + ixs->iphlen); -+ espp->esp_spi = ixs->ipsp->ips_said.spi; -+ espp->esp_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); -+ -+#ifdef CONFIG_IPSEC_ALG -+ if (!ixt_e) -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_encalg) { -+#if defined(CONFIG_IPSEC_ENC_3DES) -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ iv[0] = *((__u32*)&(espp->esp_iv) ) = -+ ((__u32*)(ixs->ipsp->ips_iv))[0]; -+ iv[1] = *((__u32*)&(espp->esp_iv) + 1) = -+ ((__u32*)(ixs->ipsp->ips_iv))[1]; -+ break; -+#endif /* defined(CONFIG_IPSEC_ENC_3DES) */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+ -+ idat = dat + ixs->iphlen + headroom; -+ ilen = len - (ixs->iphlen + headroom + authlen); -+ -+ /* Self-describing padding */ -+ pad = &dat[len - tailroom]; -+ padlen = tailroom - 2 - authlen; -+ for (i = 0; i < padlen; i++) { -+ pad[i] = i + 1; -+ } -+ dat[len - authlen - 2] = padlen; -+ -+ dat[len - authlen - 1] = ixs->iph->protocol; -+ ixs->iph->protocol = IPPROTO_ESP; -+ -+#ifdef CONFIG_IPSEC_ALG -+ /* Do all operations here: -+ * copy IV->ESP, encrypt, update ips IV -+ */ -+ if (ixt_e) { -+ int ret; -+ memcpy(espp->esp_iv, -+ ixs->ipsp->ips_iv, -+ ixt_e->ixt_ivlen/8); -+ ret=ipsec_alg_esp_encrypt(ixs->ipsp, -+ idat, ilen, espp->esp_iv, -+ IPSEC_ALG_ENCRYPT); -+ memcpy(ixs->ipsp->ips_iv, -+ idat + ilen - ixt_e->ixt_ivlen/8, -+ ixt_e->ixt_ivlen/8); -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_encalg) { -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+ des_ede3_cbc_encrypt((des_cblock *)idat, -+ (des_cblock *)idat, -+ ilen, -+ ((struct des_eks *)(ixs->ipsp->ips_key_e))[0].ks, -+ ((struct des_eks *)(ixs->ipsp->ips_key_e))[1].ks, -+ ((struct des_eks *)(ixs->ipsp->ips_key_e))[2].ks, -+ (des_cblock *)iv, 1); -+ break; -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+ -+#ifdef CONFIG_IPSEC_ALG -+ if (!ixt_e) -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_encalg) { -+#if defined(CONFIG_IPSEC_ENC_3DES) -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ /* XXX update IV with the last 8 octets of the encryption */ -+#if KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK -+ ((__u32*)(ixs->ipsp->ips_iv))[0] = -+ ((__u32 *)(idat))[(ilen >> 2) - 2]; -+ ((__u32*)(ixs->ipsp->ips_iv))[1] = -+ ((__u32 *)(idat))[(ilen >> 2) - 1]; -+#else /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */ -+ prng_bytes(&ipsec_prng, (char *)ixs->ipsp->ips_iv, EMT_ESPDES_IV_SZ); -+#endif /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */ -+ break; -+#endif /* defined(CONFIG_IPSEC_ENC_3DES) */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_ESP_BADALG; -+ } -+ -+#ifdef CONFIG_IPSEC_ALG -+ if (ixt_a) { -+ ipsec_alg_sa_esp_hash(ixs->ipsp, -+ (caddr_t)espp, len - ixs->iphlen - authlen, -+ &(dat[len - authlen]), authlen); -+ -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_authalg) { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: -+ dmp("espp", (char*)espp, len - ixs->iphlen - authlen); -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (caddr_t)espp, len - ixs->iphlen - authlen); -+ dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ dmp("ictx hash", (char*)&hash, sizeof(hash)); -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, hash, AHMD596_ALEN); -+ dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ dmp("octx hash", (char*)&hash, sizeof(hash)); -+ memcpy(&(dat[len - authlen]), hash, authlen); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ SHA1Update(&tctx.sha1, (caddr_t)espp, len - ixs->iphlen - authlen); -+ SHA1Final(hash, &tctx.sha1); -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); -+ SHA1Final(hash, &tctx.sha1); -+ memcpy(&(dat[len - authlen]), hash, authlen); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ case AH_NONE: -+ break; -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_AH_BADALG; -+ } -+#ifdef NET_21 -+ ixs->skb->h.raw = (unsigned char*)espp; -+#endif /* NET_21 */ -+ break; -+#endif /* !CONFIG_IPSEC_ESP */ -+#ifdef CONFIG_IPSEC_AH -+ case IPPROTO_AH: -+ ahp = (struct ahhdr *)(dat + ixs->iphlen); -+ ahp->ah_spi = ixs->ipsp->ips_said.spi; -+ ahp->ah_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); -+ ahp->ah_rv = 0; -+ ahp->ah_nh = ixs->iph->protocol; -+ ahp->ah_hl = (headroom >> 2) - sizeof(__u64)/sizeof(__u32); -+ ixs->iph->protocol = IPPROTO_AH; -+ dmp("ahp", (char*)ahp, sizeof(*ahp)); -+ -+ ipo = *ixs->iph; -+ ipo.tos = 0; -+ ipo.frag_off = 0; -+ ipo.ttl = 0; -+ ipo.check = 0; -+ dmp("ipo", (char*)&ipo, sizeof(ipo)); -+ -+ switch(ixs->ipsp->ips_authalg) { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr)); -+ dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data)); -+ dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN); -+ dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, dat + ixs->iphlen + headroom, len - ixs->iphlen - headroom); -+ dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ dmp("ictx hash", (char*)&hash, sizeof(hash)); -+ tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Update(&tctx.md5, hash, AHMD596_ALEN); -+ dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); -+ MD5Final(hash, &tctx.md5); -+ dmp("octx hash", (char*)&hash, sizeof(hash)); -+ -+ memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; -+ SHA1Update(&tctx.sha1, (unsigned char *)&ipo, sizeof (struct iphdr)); -+ SHA1Update(&tctx.sha1, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data)); -+ SHA1Update(&tctx.sha1, (unsigned char *)zeroes, AHHMAC_HASHLEN); -+ SHA1Update(&tctx.sha1, dat + ixs->iphlen + headroom, len - ixs->iphlen - headroom); -+ SHA1Final(hash, &tctx.sha1); -+ tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; -+ SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); -+ SHA1Final(hash, &tctx.sha1); -+ -+ memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); -+ -+ /* paranoid */ -+ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); -+ memset((caddr_t)hash, 0, sizeof(*hash)); -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_AH_BADALG; -+ } -+#ifdef NET_21 -+ ixs->skb->h.raw = (unsigned char*)ahp; -+#endif /* NET_21 */ -+ break; -+#endif /* CONFIG_IPSEC_AH */ -+#ifdef CONFIG_IPSEC_IPIP -+ case IPPROTO_IPIP: -+ ixs->iph->version = 4; -+ switch(sysctl_ipsec_tos) { -+ case 0: -+#ifdef NET_21 -+ ixs->iph->tos = ixs->skb->nh.iph->tos; -+#else /* NET_21 */ -+ ixs->iph->tos = ixs->skb->ip_hdr->tos; -+#endif /* NET_21 */ -+ break; -+ case 1: -+ ixs->iph->tos = 0; -+ break; -+ default: -+ break; -+ } -+#ifdef NET_21 -+#ifdef NETDEV_23 -+ ixs->iph->ttl = sysctl_ip_default_ttl; -+#else /* NETDEV_23 */ -+ ixs->iph->ttl = ip_statistics.IpDefaultTTL; -+#endif /* NETDEV_23 */ -+#else /* NET_21 */ -+ ixs->iph->ttl = 64; /* ip_statistics.IpDefaultTTL; */ -+#endif /* NET_21 */ -+ ixs->iph->frag_off = 0; -+ ixs->iph->saddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_s))->sin_addr.s_addr; -+ ixs->iph->daddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_d))->sin_addr.s_addr; -+ ixs->iph->protocol = IPPROTO_IPIP; -+ ixs->iph->ihl = sizeof(struct iphdr) >> 2; -+ -+ KLIPS_IP_SELECT_IDENT(ixs->iph, ixs->skb); -+ -+ ixs->newdst = (__u32)ixs->iph->daddr; -+ ixs->newsrc = (__u32)ixs->iph->saddr; -+ -+#ifdef NET_21 -+ ixs->skb->h.ipiph = ixs->skb->nh.iph; -+#endif /* NET_21 */ -+ break; -+#endif /* !CONFIG_IPSEC_IPIP */ -+#ifdef CONFIG_IPSEC_IPCOMP -+ case IPPROTO_COMP: -+ { -+ unsigned int flags = 0; -+#ifdef CONFIG_IPSEC_DEBUG -+ unsigned int old_tot_len = ntohs(ixs->iph->tot_len); -+#endif /* CONFIG_IPSEC_DEBUG */ -+ ixs->ipsp->ips_comp_ratio_dbytes += ntohs(ixs->iph->tot_len); -+ -+ ixs->skb = skb_compress(ixs->skb, ixs->ipsp, &flags); -+ -+#ifdef NET_21 -+ ixs->iph = ixs->skb->nh.iph; -+#else /* NET_21 */ -+ ixs->iph = ixs->skb->ip_hdr; -+#endif /* NET_21 */ -+ -+ ixs->ipsp->ips_comp_ratio_cbytes += ntohs(ixs->iph->tot_len); -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_tunnel & DB_TN_CROUT) -+ { -+ if (old_tot_len > ntohs(ixs->iph->tot_len)) -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "packet shrunk from %d to %d bytes after compression, cpi=%04x (should be from spi=%08x, spi&0xffff=%04x.\n", -+ old_tot_len, ntohs(ixs->iph->tot_len), -+ ntohs(((struct ipcomphdr*)(((char*)ixs->iph) + ((ixs->iph->ihl) << 2)))->ipcomp_cpi), -+ ntohl(ixs->ipsp->ips_said.spi), -+ (__u16)(ntohl(ixs->ipsp->ips_said.spi) & 0x0000ffff)); -+ else -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "packet did not compress (flags = %d).\n", -+ flags); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ } -+ break; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ default: -+ ixs->stats->tx_errors++; -+ return IPSEC_XMIT_BADPROTO; -+ } -+ -+#ifdef NET_21 -+ ixs->skb->nh.raw = ixs->skb->data; -+#else /* NET_21 */ -+ ixs->skb->ip_hdr = ixs->skb->h.iph = (struct iphdr *) ixs->skb->data; -+#endif /* NET_21 */ -+ ixs->iph->check = 0; -+ ixs->iph->check = ip_fast_csum((unsigned char *)ixs->iph, ixs->iph->ihl); -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_once: " -+ "after <%s%s%s>, SA:%s:\n", -+ IPS_XFORM_NAME(ixs->ipsp), -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph); -+ -+ ixs->ipsp->ips_life.ipl_bytes.ipl_count += len; -+ ixs->ipsp->ips_life.ipl_bytes.ipl_last = len; -+ -+ if(!ixs->ipsp->ips_life.ipl_usetime.ipl_count) { -+ ixs->ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ; -+ } -+ ixs->ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ; -+ ixs->ipsp->ips_life.ipl_packets.ipl_count++; -+ -+ ixs->ipsp = ixs->ipsp->ips_onext; -+ -+ return IPSEC_XMIT_OK; -+} -+ -+/* -+ * If the IP packet (iph) is a carrying TCP/UDP, then set the encaps -+ * source and destination ports to those from the TCP/UDP header. -+ */ -+void ipsec_extract_ports(struct iphdr * iph, struct sockaddr_encap * er) -+{ -+ struct udphdr *udp; -+ -+ switch (iph->protocol) { -+ case IPPROTO_UDP: -+ case IPPROTO_TCP: -+ /* -+ * The ports are at the same offsets in a TCP and UDP -+ * header so hack it ... -+ */ -+ udp = (struct udphdr*)(((char*)iph)+(iph->ihl<<2)); -+ er->sen_sport = udp->source; -+ er->sen_dport = udp->dest; -+ break; -+ default: -+ er->sen_sport = 0; -+ er->sen_dport = 0; -+ break; -+ } -+} -+ -+/* -+ * A TRAP eroute is installed and we want to replace it with a HOLD -+ * eroute. -+ */ -+static int create_hold_eroute(struct eroute *origtrap, -+ struct sk_buff * skb, struct iphdr * iph, -+ uint32_t eroute_pid) -+{ -+ struct eroute hold_eroute; -+ ip_said hold_said; -+ struct sk_buff *first, *last; -+ int error; -+ -+ first = last = NULL; -+ memset((caddr_t)&hold_eroute, 0, sizeof(hold_eroute)); -+ memset((caddr_t)&hold_said, 0, sizeof(hold_said)); -+ -+ hold_said.proto = IPPROTO_INT; -+ hold_said.spi = htonl(SPI_HOLD); -+ hold_said.dst.u.v4.sin_addr.s_addr = INADDR_ANY; -+ -+ hold_eroute.er_eaddr.sen_len = sizeof(struct sockaddr_encap); -+ hold_eroute.er_emask.sen_len = sizeof(struct sockaddr_encap); -+ hold_eroute.er_eaddr.sen_family = AF_ENCAP; -+ hold_eroute.er_emask.sen_family = AF_ENCAP; -+ hold_eroute.er_eaddr.sen_type = SENT_IP4; -+ hold_eroute.er_emask.sen_type = 255; -+ -+ hold_eroute.er_eaddr.sen_ip_src.s_addr = iph->saddr; -+ hold_eroute.er_eaddr.sen_ip_dst.s_addr = iph->daddr; -+ hold_eroute.er_emask.sen_ip_src.s_addr = INADDR_BROADCAST; -+ hold_eroute.er_emask.sen_ip_dst.s_addr = INADDR_BROADCAST; -+ hold_eroute.er_emask.sen_sport = 0; -+ hold_eroute.er_emask.sen_dport = 0; -+ hold_eroute.er_pid = eroute_pid; -+ hold_eroute.er_count = 0; -+ hold_eroute.er_lasttime = jiffies/HZ; -+ -+ /* -+ * if it wasn't captured by a wildcard, then don't record it as -+ * a wildcard. -+ */ -+ if(origtrap->er_eaddr.sen_proto != 0) { -+ hold_eroute.er_eaddr.sen_proto = iph->protocol; -+ -+ if((iph->protocol == IPPROTO_TCP || -+ iph->protocol == IPPROTO_UDP) && -+ (origtrap->er_eaddr.sen_sport != 0 || -+ origtrap->er_eaddr.sen_dport != 0)) { -+ -+ if(origtrap->er_eaddr.sen_sport != 0) -+ hold_eroute.er_emask.sen_sport = ~0; -+ -+ if(origtrap->er_eaddr.sen_dport != 0) -+ hold_eroute.er_emask.sen_dport = ~0; -+ -+ ipsec_extract_ports(iph, &hold_eroute.er_eaddr); -+ } -+ } -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_pfkey) { -+ char buf1[64], buf2[64]; -+ subnettoa(hold_eroute.er_eaddr.sen_ip_src, -+ hold_eroute.er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(hold_eroute.er_eaddr.sen_ip_dst, -+ hold_eroute.er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "calling breakeroute and makeroute for %s:%d->%s:%d %d HOLD eroute.\n", -+ buf1, ntohs(hold_eroute.er_eaddr.sen_sport), -+ buf2, ntohs(hold_eroute.er_eaddr.sen_dport), -+ hold_eroute.er_eaddr.sen_proto); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ if (ipsec_breakroute(&(hold_eroute.er_eaddr), &(hold_eroute.er_emask), -+ &first, &last)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "HOLD breakeroute found nothing.\n"); -+ } else { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "HOLD breakroute deleted %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u %u\n", -+ NIPQUAD(hold_eroute.er_eaddr.sen_ip_src), -+ ntohs(hold_eroute.er_eaddr.sen_sport), -+ NIPQUAD(hold_eroute.er_eaddr.sen_ip_dst), -+ ntohs(hold_eroute.er_eaddr.sen_dport), -+ hold_eroute.er_eaddr.sen_proto); -+ } -+ if (first != NULL) -+ kfree_skb(first); -+ if (last != NULL) -+ kfree_skb(last); -+ -+ error = ipsec_makeroute(&(hold_eroute.er_eaddr), -+ &(hold_eroute.er_emask), -+ hold_said, eroute_pid, skb, NULL, NULL); -+ if (error) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "HOLD makeroute returned %d, failed.\n", error); -+ } else { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "HOLD makeroute call successful.\n"); -+ } -+ return (error == 0); -+} -+ -+enum ipsec_xmit_value -+ipsec_xmit_encap_bundle(struct ipsec_xmit_state *ixs) -+{ -+#ifdef CONFIG_IPSEC_ALG -+ struct ipsec_alg_enc *ixt_e = NULL; -+ struct ipsec_alg_auth *ixt_a = NULL; -+ int blocksize = 8; -+#endif /* CONFIG_IPSEC_ALG */ -+ enum ipsec_xmit_value bundle_stat = IPSEC_XMIT_OK; -+ -+ ixs->newdst = ixs->orgdst = ixs->iph->daddr; -+ ixs->newsrc = ixs->orgsrc = ixs->iph->saddr; -+ ixs->orgedst = ixs->outgoing_said.dst.u.v4.sin_addr.s_addr; -+ ixs->iphlen = ixs->iph->ihl << 2; -+ ixs->pyldsz = ntohs(ixs->iph->tot_len) - ixs->iphlen; -+ ixs->max_headroom = ixs->max_tailroom = 0; -+ -+ if (ixs->outgoing_said.proto == IPPROTO_INT) { -+ switch (ntohl(ixs->outgoing_said.spi)) { -+ case SPI_DROP: -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "shunt SA of DROP or no eroute: dropping.\n"); -+ ixs->stats->tx_dropped++; -+ break; -+ -+ case SPI_REJECT: -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "shunt SA of REJECT: notifying and dropping.\n"); -+ ICMP_SEND(ixs->skb, -+ ICMP_DEST_UNREACH, -+ ICMP_PKT_FILTERED, -+ 0, -+ ixs->physdev); -+ ixs->stats->tx_dropped++; -+ break; -+ -+ case SPI_PASS: -+#ifdef NET_21 -+ ixs->pass = 1; -+#endif /* NET_21 */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "PASS: calling dev_queue_xmit\n"); -+ return IPSEC_XMIT_PASS; -+ goto cleanup; -+ -+ case SPI_HOLD: -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "shunt SA of HOLD: this does not make sense here, dropping.\n"); -+ ixs->stats->tx_dropped++; -+ break; -+ -+ case SPI_TRAP: -+ case SPI_TRAPSUBNET: -+ { -+ struct sockaddr_in src, dst; -+#ifdef CONFIG_IPSEC_DEBUG -+ char bufsrc[ADDRTOA_BUF], bufdst[ADDRTOA_BUF]; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ /* Signal all listening KMds with a PF_KEY ACQUIRE */ -+ -+ src.sin_family = AF_INET; -+ dst.sin_family = AF_INET; -+ src.sin_addr.s_addr = ixs->iph->saddr; -+ dst.sin_addr.s_addr = ixs->iph->daddr; -+ -+ ixs->ips.ips_transport_protocol = 0; -+ src.sin_port = 0; -+ dst.sin_port = 0; -+ { -+ int i; -+ for(i = 0; -+ i < sizeof(struct sockaddr_in) -+ - offsetof(struct sockaddr_in, sin_zero); -+ i++) { -+ src.sin_zero[i] = 0; -+ dst.sin_zero[i] = 0; -+ } -+ } -+ -+ if(ixs->eroute->er_eaddr.sen_proto != 0) { -+ ixs->ips.ips_transport_protocol = ixs->iph->protocol; -+ -+ if(ixs->eroute->er_eaddr.sen_sport != 0) { -+ src.sin_port = -+ (ixs->iph->protocol == IPPROTO_UDP -+ ? ((struct udphdr*) (((caddr_t)ixs->iph) + (ixs->iph->ihl << 2)))->source -+ : (ixs->iph->protocol == IPPROTO_TCP -+ ? ((struct tcphdr*)((caddr_t)ixs->iph + (ixs->iph->ihl << 2)))->source -+ : 0)); -+ } -+ if(ixs->eroute->er_eaddr.sen_dport != 0) { -+ dst.sin_port = -+ (ixs->iph->protocol == IPPROTO_UDP -+ ? ((struct udphdr*) (((caddr_t)ixs->iph) + (ixs->iph->ihl << 2)))->dest -+ : (ixs->iph->protocol == IPPROTO_TCP -+ ? ((struct tcphdr*)((caddr_t)ixs->iph + (ixs->iph->ihl << 2)))->dest -+ : 0)); -+ } -+ } -+ -+ ixs->ips.ips_addr_s = (struct sockaddr*)(&src); -+ ixs->ips.ips_addr_d = (struct sockaddr*)(&dst); -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "SADB_ACQUIRE sent with src=%s:%d, dst=%s:%d, proto=%d.\n", -+ addrtoa(((struct sockaddr_in*)(ixs->ips.ips_addr_s))->sin_addr, 0, bufsrc, sizeof(bufsrc)) <= ADDRTOA_BUF ? bufsrc : "BAD_ADDR", -+ ntohs(((struct sockaddr_in*)(ixs->ips.ips_addr_s))->sin_port), -+ addrtoa(((struct sockaddr_in*)(ixs->ips.ips_addr_d))->sin_addr, 0, bufdst, sizeof(bufdst)) <= ADDRTOA_BUF ? bufdst : "BAD_ADDR", -+ ntohs(((struct sockaddr_in*)(ixs->ips.ips_addr_d))->sin_port), -+ ixs->ips.ips_said.proto); -+ -+ /* increment count of total traps needed */ -+ ipsec_xmit_trap_count++; -+ -+ if (pfkey_acquire(&ixs->ips) == 0) { -+ -+ /* note that we succeeded */ -+ ipsec_xmit_trap_sendcount++; -+ -+ if (ixs->outgoing_said.spi==htonl(SPI_TRAPSUBNET)) { -+ /* -+ * The spinlock is to prevent any other -+ * process from accessing or deleting -+ * the eroute while we are using and -+ * updating it. -+ */ -+ spin_lock(&eroute_lock); -+ ixs->eroute = ipsec_findroute(&ixs->matcher); -+ if(ixs->eroute) { -+ ixs->eroute->er_said.spi = htonl(SPI_HOLD); -+ ixs->eroute->er_first = ixs->skb; -+ ixs->skb = NULL; -+ } -+ spin_unlock(&eroute_lock); -+ } else if (create_hold_eroute(ixs->eroute, -+ ixs->skb, -+ ixs->iph, -+ ixs->eroute_pid)) { -+ ixs->skb = NULL; -+ } -+ /* whether or not the above succeeded, we continue */ -+ -+ } -+ ixs->stats->tx_dropped++; -+ } -+ default: -+ /* XXX what do we do with an unknown shunt spi? */ -+ break; -+ } /* switch (ntohl(ixs->outgoing_said.spi)) */ -+ return IPSEC_XMIT_STOLEN; -+ } /* if (ixs->outgoing_said.proto == IPPROTO_INT) */ -+ -+ /* -+ The spinlock is to prevent any other process from -+ accessing or deleting the ipsec_sa hash table or any of the -+ ipsec_sa s while we are using and updating them. -+ -+ This is not optimal, but was relatively straightforward -+ at the time. A better way to do it has been planned for -+ more than a year, to lock the hash table and put reference -+ counts on each ipsec_sa instead. This is not likely to happen -+ in KLIPS1 unless a volunteer contributes it, but will be -+ designed into KLIPS2. -+ */ -+ spin_lock(&tdb_lock); -+ -+ ixs->ipsp = ipsec_sa_getbyid(&ixs->outgoing_said); -+ ixs->sa_len = satot(&ixs->outgoing_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt)); -+ -+ if (ixs->ipsp == NULL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "no ipsec_sa for SA%s: outgoing packet with no SA, dropped.\n", -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ ixs->stats->tx_dropped++; -+ bundle_stat = IPSEC_XMIT_SAIDNOTFOUND; -+ goto cleanup; -+ } -+ -+ ipsec_sa_put(ixs->ipsp); /* incomplete */ -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "found ipsec_sa -- SA:<%s%s%s> %s\n", -+ IPS_XFORM_NAME(ixs->ipsp), -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ -+ /* -+ * How much headroom do we need to be able to apply -+ * all the grouped transforms? -+ */ -+ ixs->ipsq = ixs->ipsp; /* save the head of the ipsec_sa chain */ -+ while (ixs->ipsp) { -+ ixs->sa_len = satot(&ixs->ipsp->ips_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt)); -+ if(ixs->sa_len == 0) { -+ strcpy(ixs->sa_txt, "(error)"); -+ } -+ -+ /* If it is in larval state, drop the packet, we cannot process yet. */ -+ if(ixs->ipsp->ips_state == SADB_SASTATE_LARVAL) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "ipsec_sa in larval state for SA:<%s%s%s> %s, cannot be used yet, dropping packet.\n", -+ IPS_XFORM_NAME(ixs->ipsp), -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_SAIDNOTLIVE; -+ goto cleanup; -+ } -+ -+ if(ixs->ipsp->ips_state == SADB_SASTATE_DEAD) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "ipsec_sa in dead state for SA:<%s%s%s> %s, can no longer be used, dropping packet.\n", -+ IPS_XFORM_NAME(ixs->ipsp), -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_SAIDNOTLIVE; -+ goto cleanup; -+ } -+ -+ /* If the replay window counter == -1, expire SA, it will roll */ -+ if(ixs->ipsp->ips_replaywin && ixs->ipsp->ips_replaywin_lastseq == -1) { -+ pfkey_expire(ixs->ipsp, 1); -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "replay window counter rolled for SA:<%s%s%s> %s, packet dropped, expiring SA.\n", -+ IPS_XFORM_NAME(ixs->ipsp), -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ ipsec_sa_delchain(ixs->ipsp); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_REPLAYROLLED; -+ goto cleanup; -+ } -+ -+ /* -+ * if this is the first time we are using this SA, mark start time, -+ * and offset hard/soft counters by "now" for later checking. -+ */ -+#if 0 -+ if(ixs->ipsp->ips_life.ipl_usetime.count == 0) { -+ ixs->ipsp->ips_life.ipl_usetime.count = jiffies; -+ ixs->ipsp->ips_life.ipl_usetime.hard += jiffies; -+ ixs->ipsp->ips_life.ipl_usetime.soft += jiffies; -+ } -+#endif -+ -+ -+ if(ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_bytes, "bytes", ixs->sa_txt, -+ ipsec_life_countbased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied || -+ ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_addtime, "addtime",ixs->sa_txt, -+ ipsec_life_timebased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied || -+ ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_usetime, "usetime",ixs->sa_txt, -+ ipsec_life_timebased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied || -+ ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_packets, "packets",ixs->sa_txt, -+ ipsec_life_countbased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied) { -+ -+ ipsec_sa_delchain(ixs->ipsp); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_LIFETIMEFAILED; -+ goto cleanup; -+ } -+ -+ -+ ixs->headroom = ixs->tailroom = 0; -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "calling room for <%s%s%s>, SA:%s\n", -+ IPS_XFORM_NAME(ixs->ipsp), -+ ixs->sa_len ? ixs->sa_txt : " (error)"); -+ switch(ixs->ipsp->ips_said.proto) { -+#ifdef CONFIG_IPSEC_AH -+ case IPPROTO_AH: -+ ixs->headroom += sizeof(struct ahhdr); -+ break; -+#endif /* CONFIG_IPSEC_AH */ -+#ifdef CONFIG_IPSEC_ESP -+ case IPPROTO_ESP: -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_e=ixs->ipsp->ips_alg_enc)) { -+ blocksize = ixt_e->ixt_blocksize; -+ ixs->headroom += ESP_HEADER_LEN + ixt_e->ixt_ivlen/8; -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_encalg) { -+#ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+ ixs->headroom += sizeof(struct esphdr); -+ break; -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ default: -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_ESP_BADALG; -+ goto cleanup; -+ } -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_a=ixs->ipsp->ips_alg_auth)) { -+ ixs->tailroom += AHHMAC_HASHLEN; -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ixs->ipsp->ips_authalg) { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: -+ ixs->tailroom += AHHMAC_HASHLEN; -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: -+ ixs->tailroom += AHHMAC_HASHLEN; -+ break; -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ case AH_NONE: -+ break; -+ default: -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_AH_BADALG; -+ goto cleanup; -+ } -+#ifdef CONFIG_IPSEC_ALG -+ ixs->tailroom += blocksize != 1 ? -+ ((blocksize - ((ixs->pyldsz + 2) % blocksize)) % blocksize) + 2 : -+ ((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2; -+#else -+ ixs->tailroom += ((8 - ((ixs->pyldsz + 2 * sizeof(unsigned char)) % 8)) % 8) + 2; -+#endif /* CONFIG_IPSEC_ALG */ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if ((ixs->ipsp->ips_natt_type) && (!ixs->natt_type)) { -+ ixs->natt_type = ixs->ipsp->ips_natt_type; -+ ixs->natt_sport = ixs->ipsp->ips_natt_sport; -+ ixs->natt_dport = ixs->ipsp->ips_natt_dport; -+ switch (ixs->natt_type) { -+ case ESPINUDP_WITH_NON_IKE: -+ ixs->natt_head = sizeof(struct udphdr)+(2*sizeof(__u32)); -+ break; -+ -+ case ESPINUDP_WITH_NON_ESP: -+ ixs->natt_head = sizeof(struct udphdr); -+ break; -+ -+ default: -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT -+ , "klips_xmit: invalid nat-t type %d" -+ , ixs->natt_type); -+ bundle_stat = IPSEC_XMIT_ESPUDP_BADTYPE; -+ goto cleanup; -+ -+ break; -+ } -+ ixs->tailroom += ixs->natt_head; -+ } -+#endif -+ break; -+#endif /* !CONFIG_IPSEC_ESP */ -+#ifdef CONFIG_IPSEC_IPIP -+ case IPPROTO_IPIP: -+ ixs->headroom += sizeof(struct iphdr); -+ break; -+#endif /* !CONFIG_IPSEC_IPIP */ -+ case IPPROTO_COMP: -+#ifdef CONFIG_IPSEC_IPCOMP -+ /* -+ We can't predict how much the packet will -+ shrink without doing the actual compression. -+ We could do it here, if we were the first -+ encapsulation in the chain. That might save -+ us a skb_copy_expand, since we might fit -+ into the existing skb then. However, this -+ would be a bit unclean (and this hack has -+ bit us once), so we better not do it. After -+ all, the skb_copy_expand is cheap in -+ comparison to the actual compression. -+ At least we know the packet will not grow. -+ */ -+ break; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ default: -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_BADPROTO; -+ goto cleanup; -+ } -+ ixs->ipsp = ixs->ipsp->ips_onext; -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "Required head,tailroom: %d,%d\n", -+ ixs->headroom, ixs->tailroom); -+ ixs->max_headroom += ixs->headroom; -+ ixs->max_tailroom += ixs->tailroom; -+ ixs->pyldsz += (ixs->headroom + ixs->tailroom); -+ } -+ ixs->ipsp = ixs->ipsq; /* restore the head of the ipsec_sa chain */ -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "existing head,tailroom: %d,%d before applying xforms with head,tailroom: %d,%d .\n", -+ skb_headroom(ixs->skb), skb_tailroom(ixs->skb), -+ ixs->max_headroom, ixs->max_tailroom); -+ -+ ixs->tot_headroom += ixs->max_headroom; -+ ixs->tot_tailroom += ixs->max_tailroom; -+ -+ ixs->mtudiff = ixs->prv->mtu + ixs->tot_headroom + ixs->tot_tailroom - ixs->physmtu; -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "mtu:%d physmtu:%d tothr:%d tottr:%d mtudiff:%d ippkttotlen:%d\n", -+ ixs->prv->mtu, ixs->physmtu, -+ ixs->tot_headroom, ixs->tot_tailroom, ixs->mtudiff, ntohs(ixs->iph->tot_len)); -+ if(ixs->mtudiff > 0) { -+ int newmtu = ixs->physmtu - (ixs->tot_headroom + ((ixs->tot_tailroom + 2) & ~7) + 5); -+ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_info:ipsec_xmit_encap_bundle: " -+ "dev %s mtu of %d decreased by %d to %d\n", -+ ixs->dev->name, -+ ixs->prv->mtu, -+ ixs->prv->mtu - newmtu, -+ newmtu); -+ ixs->prv->mtu = newmtu; -+#ifdef NET_21 -+#if 0 -+ ixs->skb->dst->pmtu = ixs->prv->mtu; /* RGB */ -+#endif /* 0 */ -+#else /* NET_21 */ -+#if 0 -+ ixs->dev->mtu = ixs->prv->mtu; /* RGB */ -+#endif /* 0 */ -+#endif /* NET_21 */ -+ } -+ -+ /* -+ If the sender is doing PMTU discovery, and the -+ packet doesn't fit within ixs->prv->mtu, notify him -+ (unless it was an ICMP packet, or it was not the -+ zero-offset packet) and send it anyways. -+ -+ Note: buggy firewall configuration may prevent the -+ ICMP packet from getting back. -+ */ -+ if(sysctl_ipsec_icmp -+ && ixs->prv->mtu < ntohs(ixs->iph->tot_len) -+ && (ixs->iph->frag_off & __constant_htons(IP_DF)) ) { -+ int notify = ixs->iph->protocol != IPPROTO_ICMP -+ && (ixs->iph->frag_off & __constant_htons(IP_OFFSET)) == 0; -+ -+#ifdef IPSEC_obey_DF -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "fragmentation needed and DF set; %sdropping packet\n", -+ notify ? "sending ICMP and " : ""); -+ if (notify) -+ ICMP_SEND(ixs->skb, -+ ICMP_DEST_UNREACH, -+ ICMP_FRAG_NEEDED, -+ ixs->prv->mtu, -+ ixs->physdev); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_CANNOTFRAG; -+ goto cleanup; -+#else /* IPSEC_obey_DF */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "fragmentation needed and DF set; %spassing packet\n", -+ notify ? "sending ICMP and " : ""); -+ if (notify) -+ ICMP_SEND(ixs->skb, -+ ICMP_DEST_UNREACH, -+ ICMP_FRAG_NEEDED, -+ ixs->prv->mtu, -+ ixs->physdev); -+#endif /* IPSEC_obey_DF */ -+ } -+ -+#ifdef MSS_HACK -+ /* -+ * If this is a transport mode TCP packet with -+ * SYN set, determine an effective MSS based on -+ * AH/ESP overheads determined above. -+ */ -+ if (ixs->iph->protocol == IPPROTO_TCP -+ && ixs->outgoing_said.proto != IPPROTO_IPIP) { -+ struct tcphdr *tcph = ixs->skb->h.th; -+ if (tcph->syn && !tcph->ack) { -+ if(!ipsec_adjust_mss(ixs->skb, tcph, ixs->prv->mtu)) { -+ printk(KERN_WARNING -+ "klips_warning:ipsec_xmit_encap_bundle: " -+ "ipsec_adjust_mss() failed\n"); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_MSSERR; -+ goto cleanup; -+ } -+ } -+ } -+#endif /* MSS_HACK */ -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if ((ixs->natt_type) && (ixs->outgoing_said.proto != IPPROTO_IPIP)) { -+ /** -+ * NAT-Traversal and Transport Mode: -+ * we need to correct TCP/UDP checksum -+ * -+ * If we've got NAT-OA, we can fix checksum without recalculation. -+ * If we don't we can zero udp checksum. -+ */ -+ __u32 natt_oa = ixs->ipsp->ips_natt_oa ? -+ ((struct sockaddr_in*)(ixs->ipsp->ips_natt_oa))->sin_addr.s_addr : 0; -+ __u16 pkt_len = ixs->skb->tail - (unsigned char *)ixs->iph; -+ __u16 data_len = pkt_len - (ixs->iph->ihl << 2); -+ switch (ixs->iph->protocol) { -+ case IPPROTO_TCP: -+ if (data_len >= sizeof(struct tcphdr)) { -+ struct tcphdr *tcp = (struct tcphdr *)((__u32 *)ixs->iph+ixs->iph->ihl); -+ if (natt_oa) { -+ __u32 buff[2] = { ~ixs->iph->daddr, natt_oa }; -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: " -+ "fix TCP checksum using NAT-OA\n"); -+ tcp->check = csum_fold( -+ csum_partial((unsigned char *)buff, sizeof(buff), -+ tcp->check^0xffff)); -+ } -+ else { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: do not recalc TCP checksum\n"); -+ } -+ } -+ else { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: can't fix TCP checksum\n"); -+ } -+ break; -+ case IPPROTO_UDP: -+ if (data_len >= sizeof(struct udphdr)) { -+ struct udphdr *udp = (struct udphdr *)((__u32 *)ixs->iph+ixs->iph->ihl); -+ if (udp->check == 0) { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: UDP checksum already 0\n"); -+ } -+ else if (natt_oa) { -+ __u32 buff[2] = { ~ixs->iph->daddr, natt_oa }; -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: " -+ "fix UDP checksum using NAT-OA\n"); -+ udp->check = csum_fold( -+ csum_partial((unsigned char *)buff, sizeof(buff), -+ udp->check^0xffff)); -+ } -+ else { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: zero UDP checksum\n"); -+ udp->check = 0; -+ } -+ } -+ else { -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: can't fix UDP checksum\n"); -+ } -+ break; -+ default: -+ KLIPS_PRINT(debug_tunnel, -+ "klips_debug:ipsec_tunnel_start_xmit: " -+ "NAT-T & TRANSPORT: non TCP/UDP packet -- do nothing\n"); -+ break; -+ } -+ } -+#endif /* CONFIG_IPSEC_NAT_TRAVERSAL */ -+ -+ if(!ixs->hard_header_stripped) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "allocating %d bytes for hardheader.\n", -+ ixs->hard_header_len); -+ if((ixs->saved_header = kmalloc(ixs->hard_header_len, GFP_ATOMIC)) == NULL) { -+ printk(KERN_WARNING "klips_debug:ipsec_xmit_encap_bundle: " -+ "Failed, tried to allocate %d bytes for temp hard_header.\n", -+ ixs->hard_header_len); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_ERRMEMALLOC; -+ goto cleanup; -+ } -+ { -+ int i; -+ for (i = 0; i < ixs->hard_header_len; i++) { -+ ixs->saved_header[i] = ixs->skb->data[i]; -+ } -+ } -+ if(ixs->skb->len < ixs->hard_header_len) { -+ printk(KERN_WARNING "klips_error:ipsec_xmit_encap_bundle: " -+ "tried to skb_pull hhlen=%d, %d available. This should never happen, please report.\n", -+ ixs->hard_header_len, (int)(ixs->skb->len)); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_ESP_PUSHPULLERR; -+ goto cleanup; -+ } -+ skb_pull(ixs->skb, ixs->hard_header_len); -+ ixs->hard_header_stripped = 1; -+ -+/* ixs->iph = (struct iphdr *) (ixs->skb->data); */ -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "head,tailroom: %d,%d after hard_header stripped.\n", -+ skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); -+ KLIPS_IP_PRINT(debug_tunnel & DB_TN_CROUT, ixs->iph); -+ } else { -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "hard header already stripped.\n"); -+ } -+ -+ ixs->ll_headroom = (ixs->hard_header_len + 15) & ~15; -+ -+ if ((skb_headroom(ixs->skb) >= ixs->max_headroom + 2 * ixs->ll_headroom) && -+ (skb_tailroom(ixs->skb) >= ixs->max_tailroom) -+#ifndef NET_21 -+ && ixs->skb->free -+#endif /* !NET_21 */ -+ ) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "data fits in existing skb\n"); -+ } else { -+ struct sk_buff* tskb; -+ -+ if(!ixs->oskb) { -+ ixs->oskb = ixs->skb; -+ } -+ -+ tskb = skb_copy_expand(ixs->skb, -+ /* The need for 2 * link layer length here remains unexplained...RGB */ -+ ixs->max_headroom + 2 * ixs->ll_headroom, -+ ixs->max_tailroom, -+ GFP_ATOMIC); -+#ifdef NET_21 -+ if(tskb && ixs->skb->sk) { -+ skb_set_owner_w(tskb, ixs->skb->sk); -+ } -+#endif /* NET_21 */ -+ if(ixs->skb != ixs->oskb) { -+ ipsec_kfree_skb(ixs->skb); -+ } -+ ixs->skb = tskb; -+ if (!ixs->skb) { -+ printk(KERN_WARNING -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "Failed, tried to allocate %d head and %d tailroom\n", -+ ixs->max_headroom, ixs->max_tailroom); -+ ixs->stats->tx_errors++; -+ bundle_stat = IPSEC_XMIT_ERRSKBALLOC; -+ goto cleanup; -+ } -+ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, -+ "klips_debug:ipsec_xmit_encap_bundle: " -+ "head,tailroom: %d,%d after allocation\n", -+ skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); -+ } -+ -+ /* -+ * Apply grouped transforms to packet -+ */ -+ while (ixs->ipsp) { -+ enum ipsec_xmit_value encap_stat = IPSEC_XMIT_OK; -+ -+ encap_stat = ipsec_xmit_encap_once(ixs); -+ if(encap_stat != IPSEC_XMIT_OK) { -+ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, -+ "klips_debug:ipsec_xmit_encap_bundle: encap_once failed: %d\n", -+ encap_stat); -+ -+ bundle_stat = IPSEC_XMIT_ENCAPFAIL; -+ goto cleanup; -+ } -+ } -+ /* end encapsulation loop here XXX */ -+ cleanup: -+ spin_unlock(&tdb_lock); -+ return bundle_stat; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.8 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.7 2004/02/03 03:13:41 mcr -+ * mark invalid encapsulation states. -+ * -+ * Revision 1.6.2.1 2003/12/22 15:25:52 jjo -+ * Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.6 2003/12/10 01:14:27 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.5 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.4.4.2 2003/10/29 01:37:39 mcr -+ * when creating %hold from %trap, only make the %hold as -+ * specific as the %trap was - so if the protocol and ports -+ * were wildcards, then the %hold will be too. -+ * -+ * Revision 1.4.4.1 2003/09/21 13:59:56 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.4 2003/06/20 02:28:10 mcr -+ * misstype of variable name, not detected by module build. -+ * -+ * Revision 1.3 2003/06/20 01:42:21 mcr -+ * added counters to measure how many ACQUIREs we send to pluto, -+ * and how many are successfully sent. -+ * -+ * Revision 1.2 2003/04/03 17:38:35 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * Normalised coding style. -+ * Simplified logic and reduced duplication of code. -+ * -+ * Revision 1.1 2003/02/12 19:31:23 rgb -+ * Refactored from ipsec_tunnel.c -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/pfkey_v2.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,2126 @@ -+/* -+ * @(#) RFC2367 PF_KEYv2 Key management API domain socket I/F -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* -+ * Template from /usr/src/linux-2.0.36/net/unix/af_unix.c. -+ * Hints from /usr/src/linux-2.0.36/net/ipv4/udp.c. -+ */ -+ -+#define __NO_VERSION__ -+#include -+#include -+#include -+#include -+ -+#include "openswan/ipsec_param.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* struct socket */ -+#include -+#include -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include -+#include -+#include -+#include /* struct sock */ -+/* #include */ -+#include -+#ifdef CONFIG_PROC_FS -+# include -+#endif /* CONFIG_PROC_FS */ -+ -+#include -+ -+#include -+#ifdef NET_21 -+# include -+# include -+#endif /* NET_21 */ -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+ -+#ifdef CONFIG_IPSEC_DEBUG -+int debug_pfkey = 0; -+extern int sysctl_ipsec_debug_verbose; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) -+ -+#ifndef SOCKOPS_WRAPPED -+#define SOCKOPS_WRAPPED(name) name -+#endif /* SOCKOPS_WRAPPED */ -+ -+extern struct proto_ops pfkey_ops; -+struct sock *pfkey_sock_list = NULL; -+struct supported_list *pfkey_supported_list[SADB_SATYPE_MAX+1]; -+ -+struct socket_list *pfkey_open_sockets = NULL; -+struct socket_list *pfkey_registered_sockets[SADB_SATYPE_MAX+1]; -+ -+int pfkey_msg_interp(struct sock *, struct sadb_msg *, struct sadb_msg **); -+ -+int -+pfkey_list_remove_socket(struct socket *socketp, struct socket_list **sockets) -+{ -+ struct socket_list *socket_listp,*prev; -+ -+ if(!socketp) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_remove_socket: " -+ "NULL socketp handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ if(!sockets) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_remove_socket: " -+ "NULL sockets list handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ socket_listp = *sockets; -+ prev = NULL; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_remove_socket: " -+ "removing sock=0p%p\n", -+ socketp); -+ -+ while(socket_listp != NULL) { -+ if(socket_listp->socketp == socketp) { -+ if(prev != NULL) { -+ prev->next = socket_listp->next; -+ } else { -+ *sockets = socket_listp->next; -+ } -+ -+ kfree((void*)socket_listp); -+ -+ break; -+ } -+ prev = socket_listp; -+ socket_listp = socket_listp->next; -+ } -+ -+ return 0; -+} -+ -+int -+pfkey_list_insert_socket(struct socket *socketp, struct socket_list **sockets) -+{ -+ struct socket_list *socket_listp; -+ -+ if(!socketp) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_socket: " -+ "NULL socketp handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ if(!sockets) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_socket: " -+ "NULL sockets list handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_socket: " -+ "allocating %lu bytes for socketp=0p%p\n", -+ (unsigned long) sizeof(struct socket_list), -+ socketp); -+ -+ if((socket_listp = (struct socket_list *)kmalloc(sizeof(struct socket_list), GFP_KERNEL)) == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_socket: " -+ "memory allocation error.\n"); -+ return -ENOMEM; -+ } -+ -+ socket_listp->socketp = socketp; -+ socket_listp->next = *sockets; -+ *sockets = socket_listp; -+ -+ return 0; -+} -+ -+int -+pfkey_list_remove_supported(struct supported *supported, struct supported_list **supported_list) -+{ -+ struct supported_list *supported_listp = *supported_list, *prev = NULL; -+ -+ if(!supported) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_remove_supported: " -+ "NULL supported handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ if(!supported_list) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_remove_supported: " -+ "NULL supported_list handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_remove_supported: " -+ "removing supported=0p%p\n", -+ supported); -+ -+ while(supported_listp != NULL) { -+ if(supported_listp->supportedp == supported) { -+ if(prev != NULL) { -+ prev->next = supported_listp->next; -+ } else { -+ *supported_list = supported_listp->next; -+ } -+ -+ kfree((void*)supported_listp); -+ -+ break; -+ } -+ prev = supported_listp; -+ supported_listp = supported_listp->next; -+ } -+ -+ return 0; -+} -+ -+int -+pfkey_list_insert_supported(struct supported *supported, struct supported_list **supported_list) -+{ -+ struct supported_list *supported_listp; -+ -+ if(!supported) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_supported: " -+ "NULL supported handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ if(!supported_list) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_supported: " -+ "NULL supported_list handed in, failed.\n"); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_supported: " -+ "allocating %lu bytes for incoming, supported=0p%p, supported_list=0p%p\n", -+ (unsigned long) sizeof(struct supported_list), -+ supported, -+ supported_list); -+ -+ supported_listp = (struct supported_list *)kmalloc(sizeof(struct supported_list), GFP_KERNEL); -+ if(supported_listp == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_supported: " -+ "memory allocation error.\n"); -+ return -ENOMEM; -+ } -+ -+ supported_listp->supportedp = supported; -+ supported_listp->next = *supported_list; -+ *supported_list = supported_listp; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_list_insert_supported: " -+ "outgoing, supported=0p%p, supported_list=0p%p\n", -+ supported, -+ supported_list); -+ -+ return 0; -+} -+ -+#ifndef NET_21 -+DEBUG_NO_STATIC void -+pfkey_state_change(struct sock *sk) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_state_change: .\n"); -+ if(!sk->dead) { -+ wake_up_interruptible(sk->sleep); -+ } -+} -+#endif /* !NET_21 */ -+ -+#ifndef NET_21 -+DEBUG_NO_STATIC void -+pfkey_data_ready(struct sock *sk, int len) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_data_ready: " -+ "sk=0p%p len=%d\n", -+ sk, -+ len); -+ if(!sk->dead) { -+ wake_up_interruptible(sk->sleep); -+ sock_wake_async(sk->socket, 1); -+ } -+} -+ -+DEBUG_NO_STATIC void -+pfkey_write_space(struct sock *sk) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_write_space: .\n"); -+ if(!sk->dead) { -+ wake_up_interruptible(sk->sleep); -+ sock_wake_async(sk->socket, 2); -+ } -+} -+#endif /* !NET_21 */ -+ -+DEBUG_NO_STATIC void -+pfkey_insert_socket(struct sock *sk) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_insert_socket: " -+ "sk=0p%p\n", -+ sk); -+ cli(); -+ sk->next=pfkey_sock_list; -+ pfkey_sock_list=sk; -+ sti(); -+} -+ -+DEBUG_NO_STATIC void -+pfkey_remove_socket(struct sock *sk) -+{ -+ struct sock **s; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_remove_socket: .\n"); -+ cli(); -+ s=&pfkey_sock_list; -+ -+ while(*s!=NULL) { -+ if(*s==sk) { -+ *s=sk->next; -+ sk->next=NULL; -+ sti(); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_remove_socket: " -+ "succeeded.\n"); -+ return; -+ } -+ s=&((*s)->next); -+ } -+ sti(); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_remove_socket: " -+ "not found.\n"); -+ return; -+} -+ -+DEBUG_NO_STATIC void -+pfkey_destroy_socket(struct sock *sk) -+{ -+ struct sk_buff *skb; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_destroy_socket: .\n"); -+ pfkey_remove_socket(sk); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_destroy_socket: " -+ "pfkey_remove_socket called.\n"); -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_destroy_socket: " -+ "sk(0p%p)->(&0p%p)receive_queue.{next=0p%p,prev=0p%p}.\n", -+ sk, -+ &(sk->receive_queue), -+ sk->receive_queue.next, -+ sk->receive_queue.prev); -+ while(sk && ((skb=skb_dequeue(&(sk->receive_queue)))!=NULL)) { -+#ifdef NET_21 -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_pfkey && sysctl_ipsec_debug_verbose) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_destroy_socket: " -+ "skb=0p%p dequeued.\n", skb); -+ printk(KERN_INFO "klips_debug:pfkey_destroy_socket: " -+ "pfkey_skb contents:"); -+ printk(" next:0p%p", skb->next); -+ printk(" prev:0p%p", skb->prev); -+ printk(" list:0p%p", skb->list); -+ printk(" sk:0p%p", skb->sk); -+ printk(" stamp:%ld.%ld", skb->stamp.tv_sec, skb->stamp.tv_usec); -+ printk(" dev:0p%p", skb->dev); -+ if(skb->dev) { -+ if(skb->dev->name) { -+ printk(" dev->name:%s", skb->dev->name); -+ } else { -+ printk(" dev->name:NULL?"); -+ } -+ } else { -+ printk(" dev:NULL"); -+ } -+ printk(" h:0p%p", skb->h.raw); -+ printk(" nh:0p%p", skb->nh.raw); -+ printk(" mac:0p%p", skb->mac.raw); -+ printk(" dst:0p%p", skb->dst); -+ if(sysctl_ipsec_debug_verbose) { -+ int i; -+ -+ printk(" cb"); -+ for(i=0; i<48; i++) { -+ printk(":%2x", skb->cb[i]); -+ } -+ } -+ printk(" len:%d", skb->len); -+ printk(" csum:%d", skb->csum); -+#ifndef NETDEV_23 -+ printk(" used:%d", skb->used); -+ printk(" is_clone:%d", skb->is_clone); -+#endif /* NETDEV_23 */ -+ printk(" cloned:%d", skb->cloned); -+ printk(" pkt_type:%d", skb->pkt_type); -+ printk(" ip_summed:%d", skb->ip_summed); -+ printk(" priority:%d", skb->priority); -+ printk(" protocol:%d", skb->protocol); -+ printk(" security:%d", skb->security); -+ printk(" truesize:%d", skb->truesize); -+ printk(" head:0p%p", skb->head); -+ printk(" data:0p%p", skb->data); -+ printk(" tail:0p%p", skb->tail); -+ printk(" end:0p%p", skb->end); -+ if(sysctl_ipsec_debug_verbose) { -+ unsigned char* i; -+ printk(" data"); -+ for(i = skb->head; i < skb->end; i++) { -+ printk(":%2x", (unsigned char)(*(i))); -+ } -+ } -+ printk(" destructor:0p%p", skb->destructor); -+ printk("\n"); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+#endif /* NET_21 */ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_destroy_socket: " -+ "skb=0p%p freed.\n", -+ skb); -+ ipsec_kfree_skb(skb); -+ } -+ -+ sk->dead = 1; -+ sk_free(sk); -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_destroy_socket: destroyed.\n"); -+} -+ -+int -+pfkey_upmsg(struct socket *sock, struct sadb_msg *pfkey_msg) -+{ -+ int error = 0; -+ struct sk_buff * skb = NULL; -+ struct sock *sk; -+ -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_upmsg: " -+ "NULL socket passed in.\n"); -+ return -EINVAL; -+ } -+ -+ if(pfkey_msg == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_upmsg: " -+ "NULL pfkey_msg passed in.\n"); -+ return -EINVAL; -+ } -+ -+#ifdef NET_21 -+ sk = sock->sk; -+#else /* NET_21 */ -+ sk = sock->data; -+#endif /* NET_21 */ -+ -+ if(sk == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_upmsg: " -+ "NULL sock passed in.\n"); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_upmsg: " -+ "allocating %d bytes...\n", -+ (int)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)); -+ if(!(skb = alloc_skb(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN, GFP_ATOMIC) )) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_upmsg: " -+ "no buffers left to send up a message.\n"); -+ return -ENOBUFS; -+ } -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_upmsg: " -+ "...allocated at 0p%p.\n", -+ skb); -+ -+ skb->dev = NULL; -+ -+ if(skb_tailroom(skb) < pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) { -+ printk(KERN_WARNING "klips_error:pfkey_upmsg: " -+ "tried to skb_put %ld, %d available. This should never happen, please report.\n", -+ (unsigned long int)pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN, -+ skb_tailroom(skb)); -+ ipsec_kfree_skb(skb); -+ return -ENOBUFS; -+ } -+ skb->h.raw = skb_put(skb, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); -+ memcpy(skb->h.raw, pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); -+ -+#ifndef NET_21 -+ skb->free = 1; -+#endif /* !NET_21 */ -+ -+ if((error = sock_queue_rcv_skb(sk, skb)) < 0) { -+ skb->sk=NULL; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_upmsg: " -+ "error=%d calling sock_queue_rcv_skb with skb=0p%p.\n", -+ error, -+ skb); -+ ipsec_kfree_skb(skb); -+ return error; -+ } -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_create(struct socket *sock, int protocol) -+{ -+ struct sock *sk; -+ -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "socket NULL.\n"); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "sock=0p%p type:%d state:%d flags:%ld protocol:%d\n", -+ sock, -+ sock->type, -+ (unsigned int)(sock->state), -+ sock->flags, protocol); -+ -+ if(sock->type != SOCK_RAW) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "only SOCK_RAW supported.\n"); -+ return -ESOCKTNOSUPPORT; -+ } -+ -+ if(protocol != PF_KEY_V2) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "protocol not PF_KEY_V2.\n"); -+ return -EPROTONOSUPPORT; -+ } -+ -+ if((current->uid != 0)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "must be root to open pfkey sockets.\n"); -+ return -EACCES; -+ } -+ -+#ifdef NET_21 -+ sock->state = SS_UNCONNECTED; -+#endif /* NET_21 */ -+ MOD_INC_USE_COUNT; -+#ifdef NET_21 -+ if((sk=(struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, 1)) == NULL) -+#else /* NET_21 */ -+ if((sk=(struct sock *)sk_alloc(GFP_KERNEL)) == NULL) -+#endif /* NET_21 */ -+ { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "Out of memory trying to allocate.\n"); -+ MOD_DEC_USE_COUNT; -+ return -ENOMEM; -+ } -+ -+#ifndef NET_21 -+ memset(sk, 0, sizeof(*sk)); -+#endif /* !NET_21 */ -+ -+#ifdef NET_21 -+ sock_init_data(sock, sk); -+ -+ sk->destruct = NULL; -+ sk->reuse = 1; -+ sock->ops = &pfkey_ops; -+ -+ sk->zapped=0; -+ sk->family = PF_KEY; -+/* sk->num = protocol; */ -+ sk->protocol = protocol; -+ key_pid(sk) = current->pid; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "sock->fasync_list=0p%p sk->sleep=0p%p.\n", -+ sock->fasync_list, -+ sk->sleep); -+#else /* NET_21 */ -+ sk->type=sock->type; -+ init_timer(&sk->timer); -+ skb_queue_head_init(&sk->write_queue); -+ skb_queue_head_init(&sk->receive_queue); -+ skb_queue_head_init(&sk->back_log); -+ sk->rcvbuf=SK_RMEM_MAX; -+ sk->sndbuf=SK_WMEM_MAX; -+ sk->allocation=GFP_KERNEL; -+ sk->state=TCP_CLOSE; -+ sk->priority=SOPRI_NORMAL; -+ sk->state_change=pfkey_state_change; -+ sk->data_ready=pfkey_data_ready; -+ sk->write_space=pfkey_write_space; -+ sk->error_report=pfkey_state_change; -+ sk->mtu=4096; -+ sk->socket=sock; -+ sock->data=(void *)sk; -+ sk->sleep=sock->wait; -+#endif /* NET_21 */ -+ -+ pfkey_insert_socket(sk); -+ pfkey_list_insert_socket(sock, &pfkey_open_sockets); -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_create: " -+ "Socket sock=0p%p sk=0p%p initialised.\n", sock, sk); -+ return 0; -+} -+ -+#ifndef NET_21 -+DEBUG_NO_STATIC int -+pfkey_dup(struct socket *newsock, struct socket *oldsock) -+{ -+ struct sock *sk; -+ -+ if(newsock==NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_dup: " -+ "No new socket attached.\n"); -+ return -EINVAL; -+ } -+ -+ if(oldsock==NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_dup: " -+ "No old socket attached.\n"); -+ return -EINVAL; -+ } -+ -+#ifdef NET_21 -+ sk=oldsock->sk; -+#else /* NET_21 */ -+ sk=oldsock->data; -+#endif /* NET_21 */ -+ -+ /* May not have data attached */ -+ if(sk==NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_dup: " -+ "No sock attached to old socket.\n"); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_dup: .\n"); -+ -+ return pfkey_create(newsock, sk->protocol); -+} -+#endif /* !NET_21 */ -+ -+DEBUG_NO_STATIC int -+#ifdef NETDEV_23 -+pfkey_release(struct socket *sock) -+#else /* NETDEV_23 */ -+pfkey_release(struct socket *sock, struct socket *peersock) -+#endif /* NETDEV_23 */ -+{ -+ struct sock *sk; -+ int i; -+ -+ if(sock==NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_release: " -+ "No socket attached.\n"); -+ return 0; /* -EINVAL; */ -+ } -+ -+#ifdef NET_21 -+ sk=sock->sk; -+#else /* NET_21 */ -+ sk=sock->data; -+#endif /* NET_21 */ -+ -+ /* May not have data attached */ -+ if(sk==NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_release: " -+ "No sk attached to sock=0p%p.\n", sock); -+ return 0; /* -EINVAL; */ -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_release: " -+ "sock=0p%p sk=0p%p\n", sock, sk); -+ -+#ifdef NET_21 -+ if(!sk->dead) -+#endif /* NET_21 */ -+ if(sk->state_change) { -+ sk->state_change(sk); -+ } -+ -+#ifdef NET_21 -+ sock->sk = NULL; -+#else /* NET_21 */ -+ sock->data = NULL; -+#endif /* NET_21 */ -+ -+ /* Try to flush out this socket. Throw out buffers at least */ -+ pfkey_destroy_socket(sk); -+ pfkey_list_remove_socket(sock, &pfkey_open_sockets); -+ for(i = SADB_SATYPE_UNSPEC; i <= SADB_SATYPE_MAX; i++) { -+ pfkey_list_remove_socket(sock, &(pfkey_registered_sockets[i])); -+ } -+ -+ MOD_DEC_USE_COUNT; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_release: " -+ "succeeded.\n"); -+ -+ return 0; -+} -+ -+#ifndef NET_21 -+DEBUG_NO_STATIC int -+pfkey_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_bind: " -+ "operation not supported.\n"); -+ return -EINVAL; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_connect: " -+ "operation not supported.\n"); -+ return -EINVAL; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_socketpair(struct socket *a, struct socket *b) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_socketpair: " -+ "operation not supported.\n"); -+ return -EINVAL; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_accept(struct socket *sock, struct socket *newsock, int flags) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_aaccept: " -+ "operation not supported.\n"); -+ return -EINVAL; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, -+ int peer) -+{ -+ struct sockaddr *ska = (struct sockaddr*)uaddr; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getname: .\n"); -+ ska->sa_family = PF_KEY; -+ *uaddr_len = sizeof(*ska); -+ return 0; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_select(struct socket *sock, int sel_type, select_table *wait) -+{ -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_select: " -+ ".sock=0p%p sk=0p%p sel_type=%d\n", -+ sock, -+ sock->data, -+ sel_type); -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_select: " -+ "Null socket passed in.\n"); -+ return -EINVAL; -+ } -+ return datagram_select(sock->data, sel_type, wait); -+} -+ -+DEBUG_NO_STATIC int -+pfkey_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ioctl: " -+ "not supported.\n"); -+ return -EINVAL; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_listen(struct socket *sock, int backlog) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_listen: " -+ "not supported.\n"); -+ return -EINVAL; -+} -+#endif /* !NET_21 */ -+ -+DEBUG_NO_STATIC int -+pfkey_shutdown(struct socket *sock, int mode) -+{ -+ struct sock *sk; -+ -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_shutdown: " -+ "NULL socket passed in.\n"); -+ return -EINVAL; -+ } -+ -+#ifdef NET_21 -+ sk=sock->sk; -+#else /* NET_21 */ -+ sk=sock->data; -+#endif /* NET_21 */ -+ -+ if(sk == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_shutdown: " -+ "No sock attached to socket.\n"); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_shutdown: " -+ "mode=%x.\n", mode); -+ mode++; -+ -+ if(mode&SEND_SHUTDOWN) { -+ sk->shutdown|=SEND_SHUTDOWN; -+ sk->state_change(sk); -+ } -+ -+ if(mode&RCV_SHUTDOWN) { -+ sk->shutdown|=RCV_SHUTDOWN; -+ sk->state_change(sk); -+ } -+ return 0; -+} -+ -+#ifndef NET_21 -+DEBUG_NO_STATIC int -+pfkey_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) -+{ -+#ifndef NET_21 -+ struct sock *sk; -+ -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_setsockopt: " -+ "Null socket passed in.\n"); -+ return -EINVAL; -+ } -+ -+ sk=sock->data; -+ -+ if(sk == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_setsockopt: " -+ "Null sock passed in.\n"); -+ return -EINVAL; -+ } -+#endif /* !NET_21 */ -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_setsockopt: .\n"); -+ if(level!=SOL_SOCKET) { -+ return -EOPNOTSUPP; -+ } -+#ifdef NET_21 -+ return sock_setsockopt(sock, level, optname, optval, optlen); -+#else /* NET_21 */ -+ return sock_setsockopt(sk, level, optname, optval, optlen); -+#endif /* NET_21 */ -+} -+ -+DEBUG_NO_STATIC int -+pfkey_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) -+{ -+#ifndef NET_21 -+ struct sock *sk; -+ -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_setsockopt: " -+ "Null socket passed in.\n"); -+ return -EINVAL; -+ } -+ -+ sk=sock->data; -+ -+ if(sk == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_setsockopt: " -+ "Null sock passed in.\n"); -+ return -EINVAL; -+ } -+#endif /* !NET_21 */ -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getsockopt: .\n"); -+ if(level!=SOL_SOCKET) { -+ return -EOPNOTSUPP; -+ } -+#ifdef NET_21 -+ return sock_getsockopt(sock, level, optname, optval, optlen); -+#else /* NET_21 */ -+ return sock_getsockopt(sk, level, optname, optval, optlen); -+#endif /* NET_21 */ -+} -+ -+DEBUG_NO_STATIC int -+pfkey_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) -+{ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_fcntl: " -+ "not supported.\n"); -+ return -EINVAL; -+} -+#endif /* !NET_21 */ -+ -+/* -+ * Send PF_KEY data down. -+ */ -+ -+DEBUG_NO_STATIC int -+#ifdef NET_21 -+pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) -+#else /* NET_21 */ -+pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nonblock, int flags) -+#endif /* NET_21 */ -+{ -+ struct sock *sk; -+ int error = 0; -+ struct sadb_msg *pfkey_msg = NULL, *pfkey_reply = NULL; -+ -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "Null socket passed in.\n"); -+ SENDERR(EINVAL); -+ } -+ -+#ifdef NET_21 -+ sk = sock->sk; -+#else /* NET_21 */ -+ sk = sock->data; -+#endif /* NET_21 */ -+ -+ if(sk == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "Null sock passed in.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(msg == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "Null msghdr passed in.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: .\n"); -+ if(sk->err) { -+ error = sock_error(sk); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "sk->err is non-zero, returns %d.\n", -+ error); -+ SENDERR(-error); -+ } -+ -+ if((current->uid != 0)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "must be root to send messages to pfkey sockets.\n"); -+ SENDERR(EACCES); -+ } -+ -+#ifdef NET_21 -+ if(msg->msg_control) -+#else /* NET_21 */ -+ if(flags || msg->msg_control) -+#endif /* NET_21 */ -+ { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "can't set flags or set msg_control.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(sk->shutdown & SEND_SHUTDOWN) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "shutdown.\n"); -+ send_sig(SIGPIPE, current, 0); -+ SENDERR(EPIPE); -+ } -+ -+ if(len < sizeof(struct sadb_msg)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "bogus msg len of %d, too small.\n", len); -+ SENDERR(EMSGSIZE); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "allocating %d bytes for downward message.\n", -+ len); -+ if((pfkey_msg = (struct sadb_msg*)kmalloc(len, GFP_KERNEL)) == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "memory allocation error.\n"); -+ SENDERR(ENOBUFS); -+ } -+ -+ memcpy_fromiovec((void *)pfkey_msg, msg->msg_iov, len); -+ -+ if(pfkey_msg->sadb_msg_version != PF_KEY_V2) { -+ KLIPS_PRINT(1 || debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "not PF_KEY_V2 msg, found %d, should be %d.\n", -+ pfkey_msg->sadb_msg_version, -+ PF_KEY_V2); -+ kfree((void*)pfkey_msg); -+ return -EINVAL; -+ } -+ -+ if(len != pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "bogus msg len of %d, not %d byte aligned.\n", -+ len, (int)IPSEC_PFKEYv2_ALIGN); -+ SENDERR(EMSGSIZE); -+ } -+ -+#if 0 -+ /* This check is questionable, since a downward message could be -+ the result of an ACQUIRE either from kernel (PID==0) or -+ userspace (some other PID). */ -+ /* check PID */ -+ if(pfkey_msg->sadb_msg_pid != current->pid) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "pid (%d) does not equal sending process pid (%d).\n", -+ pfkey_msg->sadb_msg_pid, current->pid); -+ SENDERR(EINVAL); -+ } -+#endif -+ -+ if(pfkey_msg->sadb_msg_reserved) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "reserved field must be zero, set to %d.\n", -+ pfkey_msg->sadb_msg_reserved); -+ SENDERR(EINVAL); -+ } -+ -+ if((pfkey_msg->sadb_msg_type > SADB_MAX) || (!pfkey_msg->sadb_msg_type)){ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "msg type too large or small:%d.\n", -+ pfkey_msg->sadb_msg_type); -+ SENDERR(EINVAL); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "msg sent for parsing.\n"); -+ -+ if((error = pfkey_msg_interp(sk, pfkey_msg, &pfkey_reply))) { -+ struct socket_list *pfkey_socketsp; -+ -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " -+ "pfkey_msg_parse returns %d.\n", -+ error); -+ -+ if((pfkey_reply = (struct sadb_msg*)kmalloc(sizeof(struct sadb_msg), GFP_KERNEL)) == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "memory allocation error.\n"); -+ SENDERR(ENOBUFS); -+ } -+ memcpy((void*)pfkey_reply, (void*)pfkey_msg, sizeof(struct sadb_msg)); -+ pfkey_reply->sadb_msg_errno = -error; -+ pfkey_reply->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN; -+ -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ int error_upmsg = 0; -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " -+ "sending up error=%d message=0p%p to socket=0p%p.\n", -+ error, -+ pfkey_reply, -+ pfkey_socketsp->socketp); -+ if((error_upmsg = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " -+ "sending up error message to socket=0p%p failed with error=%d.\n", -+ pfkey_socketsp->socketp, -+ error_upmsg); -+ /* pfkey_msg_free(&pfkey_reply); */ -+ /* SENDERR(-error); */ -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " -+ "sending up error message to socket=0p%p succeeded.\n", -+ pfkey_socketsp->socketp); -+ } -+ -+ pfkey_msg_free(&pfkey_reply); -+ -+ SENDERR(-error); -+ } -+ -+ errlab: -+ if (pfkey_msg) { -+ kfree((void*)pfkey_msg); -+ } -+ -+ if(error) { -+ return error; -+ } else { -+ return len; -+ } -+} -+ -+/* -+ * Receive PF_KEY data up. -+ */ -+ -+DEBUG_NO_STATIC int -+#ifdef NET_21 -+pfkey_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm) -+#else /* NET_21 */ -+pfkey_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock, int flags, int *addr_len) -+#endif /* NET_21 */ -+{ -+ struct sock *sk; -+#ifdef NET_21 -+ int noblock = flags & MSG_DONTWAIT; -+#endif /* NET_21 */ -+ struct sk_buff *skb; -+ int error; -+ -+ if(sock == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_recvmsg: " -+ "Null socket passed in.\n"); -+ return -EINVAL; -+ } -+ -+#ifdef NET_21 -+ sk = sock->sk; -+#else /* NET_21 */ -+ sk = sock->data; -+#endif /* NET_21 */ -+ -+ if(sk == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_recvmsg: " -+ "Null sock passed in for sock=0p%p.\n", sock); -+ return -EINVAL; -+ } -+ -+ if(msg == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_recvmsg: " -+ "Null msghdr passed in for sock=0p%p, sk=0p%p.\n", -+ sock, sk); -+ return -EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_recvmsg: sock=0p%p sk=0p%p msg=0p%p size=%d.\n", -+ sock, sk, msg, size); -+ if(flags & ~MSG_PEEK) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "flags (%d) other than MSG_PEEK not supported.\n", -+ flags); -+ return -EOPNOTSUPP; -+ } -+ -+#ifdef NET_21 -+ msg->msg_namelen = 0; /* sizeof(*ska); */ -+#else /* NET_21 */ -+ if(addr_len) { -+ *addr_len = 0; /* sizeof(*ska); */ -+ } -+#endif /* NET_21 */ -+ -+ if(sk->err) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sendmsg: " -+ "sk->err=%d.\n", sk->err); -+ return sock_error(sk); -+ } -+ -+ if((skb = skb_recv_datagram(sk, flags, noblock, &error) ) == NULL) { -+ return error; -+ } -+ -+ if(size > skb->len) { -+ size = skb->len; -+ } -+#ifdef NET_21 -+ else if(size len) { -+ msg->msg_flags |= MSG_TRUNC; -+ } -+#endif /* NET_21 */ -+ -+ skb_copy_datagram_iovec(skb, 0, msg->msg_iov, size); -+ sk->stamp=skb->stamp; -+ -+ skb_free_datagram(sk, skb); -+ return size; -+} -+ -+#ifdef NET_21 -+struct net_proto_family pfkey_family_ops = { -+ PF_KEY, -+ pfkey_create -+}; -+ -+struct proto_ops SOCKOPS_WRAPPED(pfkey_ops) = { -+#ifdef NETDEV_23 -+ family: PF_KEY, -+ release: pfkey_release, -+ bind: sock_no_bind, -+ connect: sock_no_connect, -+ socketpair: sock_no_socketpair, -+ accept: sock_no_accept, -+ getname: sock_no_getname, -+ poll: datagram_poll, -+ ioctl: sock_no_ioctl, -+ listen: sock_no_listen, -+ shutdown: pfkey_shutdown, -+ setsockopt: sock_no_setsockopt, -+ getsockopt: sock_no_getsockopt, -+ sendmsg: pfkey_sendmsg, -+ recvmsg: pfkey_recvmsg, -+ mmap: sock_no_mmap, -+#else /* NETDEV_23 */ -+ PF_KEY, -+ sock_no_dup, -+ pfkey_release, -+ sock_no_bind, -+ sock_no_connect, -+ sock_no_socketpair, -+ sock_no_accept, -+ sock_no_getname, -+ datagram_poll, -+ sock_no_ioctl, -+ sock_no_listen, -+ pfkey_shutdown, -+ sock_no_setsockopt, -+ sock_no_getsockopt, -+ sock_no_fcntl, -+ pfkey_sendmsg, -+ pfkey_recvmsg -+#endif /* NETDEV_23 */ -+}; -+ -+#ifdef NETDEV_23 -+#include -+SOCKOPS_WRAP(pfkey, PF_KEY); -+#endif /* NETDEV_23 */ -+ -+#else /* NET_21 */ -+struct proto_ops pfkey_proto_ops = { -+ PF_KEY, -+ pfkey_create, -+ pfkey_dup, -+ pfkey_release, -+ pfkey_bind, -+ pfkey_connect, -+ pfkey_socketpair, -+ pfkey_accept, -+ pfkey_getname, -+ pfkey_select, -+ pfkey_ioctl, -+ pfkey_listen, -+ pfkey_shutdown, -+ pfkey_setsockopt, -+ pfkey_getsockopt, -+ pfkey_fcntl, -+ pfkey_sendmsg, -+ pfkey_recvmsg -+}; -+#endif /* NET_21 */ -+ -+#ifdef CONFIG_PROC_FS -+#ifndef PROC_FS_2325 -+DEBUG_NO_STATIC -+#endif /* PROC_FS_2325 */ -+int -+pfkey_get_info(char *buffer, char **start, off_t offset, int length -+#ifndef PROC_NO_DUMMY -+, int dummy -+#endif /* !PROC_NO_DUMMY */ -+) -+{ -+ const int max_content = length > 0? length-1 : 0; -+ off_t begin=0; -+ int len=0; -+ struct sock *sk=pfkey_sock_list; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if(!sysctl_ipsec_debug_verbose) { -+#endif /* CONFIG_IPSEC_DEBUG */ -+ len+= snprintf(buffer,length, -+ " sock pid socket next prev e n p sndbf Flags Type St\n"); -+#ifdef CONFIG_IPSEC_DEBUG -+ } else { -+ len+= snprintf(buffer,length, -+ " sock pid d sleep socket next prev e r z n p sndbf stamp Flags Type St\n"); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ while(sk!=NULL) { -+#ifdef CONFIG_IPSEC_DEBUG -+ if(!sysctl_ipsec_debug_verbose) { -+#endif /* CONFIG_IPSEC_DEBUG */ -+ len += ipsec_snprintf(buffer+len, length-len, -+ "%8p %5d %8p %8p %8p %d %d %d %5d %08lX %8X %2X\n", -+ sk, -+ key_pid(sk), -+ sk->socket, -+ sk->next, -+ sk->prev, -+ sk->err, -+ sk->num, -+ sk->protocol, -+ sk->sndbuf, -+ sk->socket->flags, -+ sk->socket->type, -+ sk->socket->state); -+#ifdef CONFIG_IPSEC_DEBUG -+ } else { -+ len += ipsec_snprintf(buffer+len, length-len, -+ "%8p %5d %d %8p %8p %8p %8p %d %d %d %d %d %5d %d.%06d %08lX %8X %2X\n", -+ sk, -+ key_pid(sk), -+ sk->dead, -+ sk->sleep, -+ sk->socket, -+ sk->next, -+ sk->prev, -+ sk->err, -+ sk->reuse, -+ sk->zapped, -+ sk->num, -+ sk->protocol, -+ sk->sndbuf, -+ (unsigned int)sk->stamp.tv_sec, -+ (unsigned int)sk->stamp.tv_usec, -+ sk->socket->flags, -+ sk->socket->type, -+ sk->socket->state); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ if (len >= max_content) { -+ /* we've done all that can fit -- stop loop */ -+ len = max_content; /* truncate crap */ -+ break; -+ } else { -+ -+ const off_t pos = begin + len; /* file position of end of what we've generated */ -+ -+ if (pos <= offset) { -+ /* all is before first interesting character: -+ * discard, but note where we are. -+ */ -+ len = 0; -+ begin = pos; -+ } -+ } -+ sk=sk->next; -+ -+ } -+ -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ return len - (offset - begin); -+ -+} -+ -+#ifndef PROC_FS_2325 -+DEBUG_NO_STATIC -+#endif /* PROC_FS_2325 */ -+int -+pfkey_supported_get_info(char *buffer, char **start, off_t offset, int length -+#ifndef PROC_NO_DUMMY -+, int dummy -+#endif /* !PROC_NO_DUMMY */ -+) -+{ -+ const int max_content = length > 0? length-1 : 0; -+ off_t begin=0; -+ int len=0; -+ int satype; -+ struct supported_list *pfkey_supported_p; -+ -+ len += ipsec_snprintf(buffer, length, -+ "satype exttype alg_id ivlen minbits maxbits\n"); -+ -+ for(satype = SADB_SATYPE_UNSPEC; satype <= SADB_SATYPE_MAX; satype++) { -+ pfkey_supported_p = pfkey_supported_list[satype]; -+ while(pfkey_supported_p) { -+ len += ipsec_snprintf(buffer+len, length-len, -+ " %2d %2d %2d %3d %3d %3d\n", -+ satype, -+ pfkey_supported_p->supportedp->supported_alg_exttype, -+ pfkey_supported_p->supportedp->supported_alg_id, -+ pfkey_supported_p->supportedp->supported_alg_ivlen, -+ pfkey_supported_p->supportedp->supported_alg_minbits, -+ pfkey_supported_p->supportedp->supported_alg_maxbits); -+ -+ if (len >= max_content) { -+ /* we've done all that can fit -- stop loop */ -+ len = max_content; /* truncate crap */ -+ break; -+ } else { -+ const off_t pos = begin + len; /* file position of end of what we've generated */ -+ -+ if (pos <= offset) { -+ /* all is before first interesting character: -+ * discard, but note where we are. -+ */ -+ len = 0; -+ begin = pos; -+ } -+ } -+ -+ pfkey_supported_p = pfkey_supported_p->next; -+ } -+ } -+ -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ return len - (offset - begin); -+ -+} -+ -+#ifndef PROC_FS_2325 -+DEBUG_NO_STATIC -+#endif /* PROC_FS_2325 */ -+int -+pfkey_registered_get_info(char *buffer, char **start, off_t offset, int length -+#ifndef PROC_NO_DUMMY -+, int dummy -+#endif /* !PROC_NO_DUMMY */ -+) -+{ -+ const int max_content = length > 0? length-1 : 0; -+ off_t begin=0; -+ int len=0; -+ int satype; -+ struct socket_list *pfkey_sockets; -+ -+ len += ipsec_snprintf(buffer, length, -+ "satype socket pid sk\n"); -+ -+ for(satype = SADB_SATYPE_UNSPEC; satype <= SADB_SATYPE_MAX; satype++) { -+ pfkey_sockets = pfkey_registered_sockets[satype]; -+ while(pfkey_sockets) { -+#ifdef NET_21 -+ len += ipsec_snprintf(buffer+len, length-len, -+ " %2d %8p %5d %8p\n", -+ satype, -+ pfkey_sockets->socketp, -+ key_pid(pfkey_sockets->socketp->sk), -+ pfkey_sockets->socketp->sk); -+#else /* NET_21 */ -+ len += ipsec_snprintf(buffer+len, length-len, -+ " %2d %8p N/A %8p\n", -+ satype, -+ pfkey_sockets->socketp, -+#if 0 -+ key_pid((pfkey_sockets->socketp)->data), -+#endif -+ (pfkey_sockets->socketp)->data); -+#endif /* NET_21 */ -+ -+ if (len >= max_content) { -+ /* we've done all that can fit -- stop loop (could stop two) */ -+ len = max_content; /* truncate crap */ -+ break; -+ } else { -+ const off_t pos = begin + len; /* file position of end of what we've generated */ -+ -+ if (pos <= offset) { -+ /* all is before first interesting character: -+ * discard, but note where we are. -+ */ -+ len = 0; -+ begin = pos; -+ } -+ } -+ -+ -+ pfkey_sockets = pfkey_sockets->next; -+ } -+ } -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ return len - (offset - begin); -+} -+ -+#ifndef PROC_FS_2325 -+struct proc_dir_entry proc_net_pfkey = -+{ -+ 0, -+ 6, "pf_key", -+ S_IFREG | S_IRUGO, 1, 0, 0, -+ 0, &proc_net_inode_operations, -+ pfkey_get_info -+}; -+struct proc_dir_entry proc_net_pfkey_supported = -+{ -+ 0, -+ 16, "pf_key_supported", -+ S_IFREG | S_IRUGO, 1, 0, 0, -+ 0, &proc_net_inode_operations, -+ pfkey_supported_get_info -+}; -+struct proc_dir_entry proc_net_pfkey_registered = -+{ -+ 0, -+ 17, "pf_key_registered", -+ S_IFREG | S_IRUGO, 1, 0, 0, -+ 0, &proc_net_inode_operations, -+ pfkey_registered_get_info -+}; -+#endif /* !PROC_FS_2325 */ -+#endif /* CONFIG_PROC_FS */ -+ -+DEBUG_NO_STATIC int -+supported_add_all(int satype, struct supported supported[], int size) -+{ -+ int i; -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:init_pfkey: " -+ "sizeof(supported_init_)[%d]/sizeof(struct supported)[%d]=%d.\n", -+ satype, -+ size, -+ (int)sizeof(struct supported), -+ (int)(size/sizeof(struct supported))); -+ -+ for(i = 0; i < size / sizeof(struct supported); i++) { -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:init_pfkey: " -+ "i=%d inserting satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n", -+ i, -+ satype, -+ supported[i].supported_alg_exttype, -+ supported[i].supported_alg_id, -+ supported[i].supported_alg_ivlen, -+ supported[i].supported_alg_minbits, -+ supported[i].supported_alg_maxbits); -+ -+ error |= pfkey_list_insert_supported(&(supported[i]), -+ &(pfkey_supported_list[satype])); -+ } -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+supported_remove_all(int satype) -+{ -+ int error = 0; -+ struct supported*supportedp; -+ -+ while(pfkey_supported_list[satype]) { -+ supportedp = pfkey_supported_list[satype]->supportedp; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:init_pfkey: " -+ "removing satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n", -+ satype, -+ supportedp->supported_alg_exttype, -+ supportedp->supported_alg_id, -+ supportedp->supported_alg_ivlen, -+ supportedp->supported_alg_minbits, -+ supportedp->supported_alg_maxbits); -+ -+ error |= pfkey_list_remove_supported(supportedp, -+ &(pfkey_supported_list[satype])); -+ } -+ return error; -+} -+ -+int -+pfkey_init(void) -+{ -+ int error = 0; -+ int i; -+ -+ static struct supported supported_init_ah[] = { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_MD5HMAC, 0, 128, 128}, -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_SHA1HMAC, 0, 160, 160} -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ }; -+ static struct supported supported_init_esp[] = { -+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_MD5HMAC, 0, 128, 128}, -+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_SHA1HMAC, 0, 160, 160}, -+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+#ifdef CONFIG_IPSEC_ENC_3DES -+ {SADB_EXT_SUPPORTED_ENCRYPT, SADB_EALG_3DESCBC, 64, 168, 168}, -+#endif /* CONFIG_IPSEC_ENC_3DES */ -+ }; -+ static struct supported supported_init_ipip[] = { -+ {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv4_in_IPv4, 0, 32, 32} -+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+ , {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv6_in_IPv4, 0, 128, 32} -+ , {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv4_in_IPv6, 0, 32, 128} -+ , {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv6_in_IPv6, 0, 128, 128} -+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ -+ }; -+#ifdef CONFIG_IPSEC_IPCOMP -+ static struct supported supported_init_ipcomp[] = { -+ {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_CALG_DEFLATE, 0, 1, 1} -+ }; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#if 0 -+ printk(KERN_INFO -+ "klips_info:pfkey_init: " -+ "FreeS/WAN: initialising PF_KEYv2 domain sockets.\n"); -+#endif -+ -+ for(i = SADB_SATYPE_UNSPEC; i <= SADB_SATYPE_MAX; i++) { -+ pfkey_registered_sockets[i] = NULL; -+ pfkey_supported_list[i] = NULL; -+ } -+ -+ error |= supported_add_all(SADB_SATYPE_AH, supported_init_ah, sizeof(supported_init_ah)); -+ error |= supported_add_all(SADB_SATYPE_ESP, supported_init_esp, sizeof(supported_init_esp)); -+#ifdef CONFIG_IPSEC_IPCOMP -+ error |= supported_add_all(SADB_X_SATYPE_COMP, supported_init_ipcomp, sizeof(supported_init_ipcomp)); -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ error |= supported_add_all(SADB_X_SATYPE_IPIP, supported_init_ipip, sizeof(supported_init_ipip)); -+ -+#ifdef NET_21 -+ error |= sock_register(&pfkey_family_ops); -+#else /* NET_21 */ -+ error |= sock_register(pfkey_proto_ops.family, &pfkey_proto_ops); -+#endif /* NET_21 */ -+ -+#ifdef CONFIG_PROC_FS -+# ifndef PROC_FS_2325 -+# ifdef PROC_FS_21 -+ error |= proc_register(proc_net, &proc_net_pfkey); -+ error |= proc_register(proc_net, &proc_net_pfkey_supported); -+ error |= proc_register(proc_net, &proc_net_pfkey_registered); -+# else /* PROC_FS_21 */ -+ error |= proc_register_dynamic(&proc_net, &proc_net_pfkey); -+ error |= proc_register_dynamic(&proc_net, &proc_net_pfkey_supported); -+ error |= proc_register_dynamic(&proc_net, &proc_net_pfkey_registered); -+# endif /* PROC_FS_21 */ -+# else /* !PROC_FS_2325 */ -+ proc_net_create ("pf_key", 0, pfkey_get_info); -+ proc_net_create ("pf_key_supported", 0, pfkey_supported_get_info); -+ proc_net_create ("pf_key_registered", 0, pfkey_registered_get_info); -+# endif /* !PROC_FS_2325 */ -+#endif /* CONFIG_PROC_FS */ -+ -+ return error; -+} -+ -+int -+pfkey_cleanup(void) -+{ -+ int error = 0; -+ -+ printk(KERN_INFO "klips_info:pfkey_cleanup: " -+ "shutting down PF_KEY domain sockets.\n"); -+#ifdef NET_21 -+ error |= sock_unregister(PF_KEY); -+#else /* NET_21 */ -+ error |= sock_unregister(pfkey_proto_ops.family); -+#endif /* NET_21 */ -+ -+ error |= supported_remove_all(SADB_SATYPE_AH); -+ error |= supported_remove_all(SADB_SATYPE_ESP); -+#ifdef CONFIG_IPSEC_IPCOMP -+ error |= supported_remove_all(SADB_X_SATYPE_COMP); -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ error |= supported_remove_all(SADB_X_SATYPE_IPIP); -+ -+#ifdef CONFIG_PROC_FS -+# ifndef PROC_FS_2325 -+ if (proc_net_unregister(proc_net_pfkey.low_ino) != 0) -+ printk("klips_debug:pfkey_cleanup: " -+ "cannot unregister /proc/net/pf_key\n"); -+ if (proc_net_unregister(proc_net_pfkey_supported.low_ino) != 0) -+ printk("klips_debug:pfkey_cleanup: " -+ "cannot unregister /proc/net/pf_key_supported\n"); -+ if (proc_net_unregister(proc_net_pfkey_registered.low_ino) != 0) -+ printk("klips_debug:pfkey_cleanup: " -+ "cannot unregister /proc/net/pf_key_registered\n"); -+# else /* !PROC_FS_2325 */ -+ proc_net_remove ("pf_key"); -+ proc_net_remove ("pf_key_supported"); -+ proc_net_remove ("pf_key_registered"); -+# endif /* !PROC_FS_2325 */ -+#endif /* CONFIG_PROC_FS */ -+ -+ /* other module unloading cleanup happens here */ -+ return error; -+} -+ -+#ifdef MODULE -+#if 0 -+int -+init_module(void) -+{ -+ pfkey_init(); -+ return 0; -+} -+ -+void -+cleanup_module(void) -+{ -+ pfkey_cleanup(); -+} -+#endif /* 0 */ -+#else /* MODULE */ -+void -+pfkey_proto_init(struct net_proto *pro) -+{ -+ pfkey_init(); -+} -+#endif /* MODULE */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.81 2004/04/25 21:23:11 ken -+ * Pull in dhr's changes from FreeS/WAN 2.06 -+ * -+ * Revision 1.80 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.79.4.1 2003/12/22 15:25:52 jjo -+ * . Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.79 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.78.4.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.78 2003/04/03 17:38:09 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * -+ * Revision 1.77 2002/10/17 16:49:36 mcr -+ * sock->ops should reference the unwrapped options so that -+ * we get hacked in locking on SMP systems. -+ * -+ * Revision 1.76 2002/10/12 23:11:53 dhr -+ * -+ * [KenB + DHR] more 64-bit cleanup -+ * -+ * Revision 1.75 2002/09/20 05:01:57 rgb -+ * Added memory allocation debugging. -+ * -+ * Revision 1.74 2002/09/19 02:42:50 mcr -+ * do not define the pfkey_ops function for now. -+ * -+ * Revision 1.73 2002/09/17 17:29:23 mcr -+ * #if 0 out some dead code - pfkey_ops is never used as written. -+ * -+ * Revision 1.72 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.71 2002/05/23 07:14:11 rgb -+ * Cleaned up %p variants to 0p%p for test suite cleanup. -+ * -+ * Revision 1.70 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.69 2002/04/24 07:36:33 mcr -+ * Moved from ./klips/net/ipsec/pfkey_v2.c,v -+ * -+ * Revision 1.68 2002/03/08 01:15:17 mcr -+ * put some internal structure only debug messages behind -+ * && sysctl_ipsec_debug_verbose. -+ * -+ * Revision 1.67 2002/01/29 17:17:57 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.66 2002/01/29 04:00:54 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.65 2002/01/29 02:13:18 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.64 2001/11/26 09:23:51 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.61.2.1 2001/09/25 02:28:44 mcr -+ * cleaned up includes. -+ * -+ * Revision 1.63 2001/11/12 19:38:00 rgb -+ * Continue trying other sockets even if one fails and return only original -+ * error. -+ * -+ * Revision 1.62 2001/10/18 04:45:22 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.61 2001/09/20 15:32:59 rgb -+ * Min/max cleanup. -+ * -+ * Revision 1.60 2001/06/14 19:35:12 rgb -+ * Update copyright date. -+ * -+ * Revision 1.59 2001/06/13 15:35:48 rgb -+ * Fixed #endif comments. -+ * -+ * Revision 1.58 2001/05/04 16:37:24 rgb -+ * Remove erroneous checking of return codes for proc_net_* in 2.4. -+ * -+ * Revision 1.57 2001/05/03 19:43:36 rgb -+ * Initialise error return variable. -+ * Check error return codes in startup and shutdown. -+ * Standardise on SENDERR() macro. -+ * -+ * Revision 1.56 2001/04/21 23:05:07 rgb -+ * Define out skb->used for 2.4 kernels. -+ * -+ * Revision 1.55 2001/02/28 05:03:28 rgb -+ * Clean up and rationalise startup messages. -+ * -+ * Revision 1.54 2001/02/27 22:24:55 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.53 2001/02/27 06:48:18 rgb -+ * Fixed pfkey socket unregister log message to reflect type and function. -+ * -+ * Revision 1.52 2001/02/26 22:34:38 rgb -+ * Fix error return code that was getting overwritten by the error return -+ * code of an upmsg. -+ * -+ * Revision 1.51 2001/01/30 23:42:47 rgb -+ * Allow pfkey msgs from pid other than user context required for ACQUIRE -+ * and subsequent ADD or UDATE. -+ * -+ * Revision 1.50 2001/01/23 20:22:59 rgb -+ * 2.4 fix to remove removed is_clone member. -+ * -+ * Revision 1.49 2000/11/06 04:33:47 rgb -+ * Changed non-exported functions to DEBUG_NO_STATIC. -+ * -+ * Revision 1.48 2000/09/29 19:47:41 rgb -+ * Update copyright. -+ * -+ * Revision 1.47 2000/09/22 04:23:04 rgb -+ * Added more debugging to pfkey_upmsg() call from pfkey_sendmsg() error. -+ * -+ * Revision 1.46 2000/09/21 04:20:44 rgb -+ * Fixed array size off-by-one error. (Thanks Svenning!) -+ * -+ * Revision 1.45 2000/09/20 04:01:26 rgb -+ * Changed static functions to DEBUG_NO_STATIC for revealing function names -+ * in oopsen. -+ * -+ * Revision 1.44 2000/09/19 00:33:17 rgb -+ * 2.0 fixes. -+ * -+ * Revision 1.43 2000/09/16 01:28:13 rgb -+ * Fixed use of 0 in p format warning. -+ * -+ * Revision 1.42 2000/09/16 01:09:41 rgb -+ * Fixed debug format warning for pointers that was expecting ints. -+ * -+ * Revision 1.41 2000/09/13 15:54:00 rgb -+ * Rewrote pfkey_get_info(), added pfkey_{supported,registered}_get_info(). -+ * Moved supported algos add and remove to functions. -+ * -+ * Revision 1.40 2000/09/12 18:49:28 rgb -+ * Added IPIP tunnel and IPCOMP register support. -+ * -+ * Revision 1.39 2000/09/12 03:23:49 rgb -+ * Converted #if0 debugs to sysctl. -+ * Removed debug_pfkey initialisations that prevented no_debug loading or -+ * linking. -+ * -+ * Revision 1.38 2000/09/09 06:38:02 rgb -+ * Return positive errno in pfkey_reply error message. -+ * -+ * Revision 1.37 2000/09/08 19:19:09 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * Clean-up of long-unused crud... -+ * Create pfkey error message on on failure. -+ * Give pfkey_list_{insert,remove}_{socket,supported}() some error -+ * checking. -+ * -+ * Revision 1.36 2000/09/01 18:49:38 rgb -+ * Reap experimental NET_21_ bits. -+ * Turned registered sockets list into an array of one list per satype. -+ * Remove references to deprecated sklist_{insert,remove}_socket. -+ * Removed leaking socket debugging code. -+ * Removed duplicate pfkey_insert_socket in pfkey_create. -+ * Removed all references to pfkey msg->msg_name, since it is not used for -+ * pfkey. -+ * Added a supported algorithms array lists, one per satype and registered -+ * existing algorithms. -+ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to -+ * list. -+ * Only send pfkey_expire() messages to sockets registered for that satype. -+ * -+ * Revision 1.35 2000/08/24 17:03:00 rgb -+ * Corrected message size error return code for PF_KEYv2. -+ * Removed downward error prohibition. -+ * -+ * Revision 1.34 2000/08/21 16:32:26 rgb -+ * Re-formatted for cosmetic consistency and readability. -+ * -+ * Revision 1.33 2000/08/20 21:38:24 rgb -+ * Added a pfkey_reply parameter to pfkey_msg_interp(). (Momchil) -+ * Extended the upward message initiation of pfkey_sendmsg(). (Momchil) -+ * -+ * Revision 1.32 2000/07/28 14:58:31 rgb -+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. -+ * -+ * Revision 1.31 2000/05/16 03:04:00 rgb -+ * Updates for 2.3.99pre8 from MB. -+ * -+ * Revision 1.30 2000/05/10 19:22:21 rgb -+ * Use sklist private functions for 2.3.xx compatibility. -+ * -+ * Revision 1.29 2000/03/22 16:17:03 rgb -+ * Fixed SOCKOPS_WRAPPED macro for SMP (MB). -+ * -+ * Revision 1.28 2000/02/21 19:30:45 rgb -+ * Removed references to pkt_bridged for 2.3.47 compatibility. -+ * -+ * Revision 1.27 2000/02/14 21:07:00 rgb -+ * Fixed /proc/net/pf-key legend spacing. -+ * -+ * Revision 1.26 2000/01/22 03:46:59 rgb -+ * Fixed pfkey error return mechanism so that we are able to free the -+ * local copy of the pfkey_msg, plugging a memory leak and silencing -+ * the bad object free complaints. -+ * -+ * Revision 1.25 2000/01/21 06:19:44 rgb -+ * Moved pfkey_list_remove_socket() calls to before MOD_USE_DEC_COUNT. -+ * Added debugging to pfkey_upmsg. -+ * -+ * Revision 1.24 2000/01/10 16:38:23 rgb -+ * MB fixups for 2.3.x. -+ * -+ * Revision 1.23 1999/12/09 23:22:16 rgb -+ * Added more instrumentation for debugging 2.0 socket -+ * selection/reading. -+ * Removed erroneous 2.0 wait==NULL check bug in select. -+ * -+ * Revision 1.22 1999/12/08 20:32:16 rgb -+ * Tidied up 2.0.xx support, after major pfkey work, eliminating -+ * msg->msg_name twiddling in the process, since it is not defined -+ * for PF_KEYv2. -+ * -+ * Revision 1.21 1999/12/01 22:17:19 rgb -+ * Set skb->dev to zero on new skb in case it is a reused skb. -+ * Added check for skb_put overflow and freeing to avoid upmsg on error. -+ * Added check for wrong pfkey version and freeing to avoid upmsg on -+ * error. -+ * Shut off content dumping in pfkey_destroy. -+ * Added debugging message for size of buffer allocated for upmsg. -+ * -+ * Revision 1.20 1999/11/27 12:11:00 rgb -+ * Minor clean-up, enabling quiet operation of pfkey if desired. -+ * -+ * Revision 1.19 1999/11/25 19:04:21 rgb -+ * Update proc_fs code for pfkey to use dynamic registration. -+ * -+ * Revision 1.18 1999/11/25 09:07:17 rgb -+ * Implemented SENDERR macro for propagating error codes. -+ * Fixed error return code bug. -+ * -+ * Revision 1.17 1999/11/23 23:07:20 rgb -+ * Change name of pfkey_msg_parser to pfkey_msg_interp since it no longer -+ * parses. (PJO) -+ * Sort out pfkey and freeswan headers, putting them in a library path. -+ * -+ * Revision 1.16 1999/11/20 22:00:22 rgb -+ * Moved socketlist type declarations and prototypes for shared use. -+ * Renamed reformatted and generically extended for use by other socket -+ * lists pfkey_{del,add}_open_socket to pfkey_list_{remove,insert}_socket. -+ * -+ * Revision 1.15 1999/11/18 04:15:09 rgb -+ * Make pfkey_data_ready temporarily available for 2.2.x testing. -+ * Clean up pfkey_destroy_socket() debugging statements. -+ * Add Peter Onion's code to send messages up to all listening sockets. -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * Replaced all kernel version macros to shorter, readable form. -+ * Added CONFIG_PROC_FS compiler directives in case it is shut off. -+ * -+ * Revision 1.14 1999/11/17 16:01:00 rgb -+ * Make pfkey_data_ready temporarily available for 2.2.x testing. -+ * Clean up pfkey_destroy_socket() debugging statements. -+ * Add Peter Onion's code to send messages up to all listening sockets. -+ * Changed #include "../../../lib/freeswan.h" to #include -+ * which works due to -Ilibfreeswan in the klips/net/ipsec/Makefile. -+ * -+ * Revision 1.13 1999/10/27 19:59:51 rgb -+ * Removed af_unix comments that are no longer relevant. -+ * Added debug prink statements. -+ * Added to the /proc output in pfkey_get_info. -+ * Made most functions non-static to enable oops tracing. -+ * Re-enable skb dequeueing and freeing. -+ * Fix skb_alloc() and skb_put() size bug in pfkey_upmsg(). -+ * -+ * Revision 1.12 1999/10/26 17:05:42 rgb -+ * Complete re-ordering based on proto_ops structure order. -+ * Separated out proto_ops structures for 2.0.x and 2.2.x for clarity. -+ * Simplification to use built-in socket ops where possible for 2.2.x. -+ * Add shorter macros for compiler directives to visually clean-up. -+ * Add lots of sk skb dequeueing debugging statements. -+ * Added to the /proc output in pfkey_get_info. -+ * -+ * Revision 1.11 1999/09/30 02:55:10 rgb -+ * Bogus skb detection. -+ * Fix incorrect /proc/net/ipsec-eroute printk message. -+ * -+ * Revision 1.10 1999/09/21 15:22:13 rgb -+ * Temporary fix while I figure out the right way to destroy sockets. -+ * -+ * Revision 1.9 1999/07/08 19:19:44 rgb -+ * Fix pointer format warning. -+ * Fix missing member error under 2.0.xx kernels. -+ * -+ * Revision 1.8 1999/06/13 07:24:04 rgb -+ * Add more debugging. -+ * -+ * Revision 1.7 1999/06/10 05:24:17 rgb -+ * Clarified compiler directives. -+ * Renamed variables to reduce confusion. -+ * Used sklist_*_socket() kernel functions to simplify 2.2.x socket support. -+ * Added lots of sanity checking. -+ * -+ * Revision 1.6 1999/06/03 18:59:50 rgb -+ * More updates to 2.2.x socket support. Almost works, oops at end of call. -+ * -+ * Revision 1.5 1999/05/25 22:44:05 rgb -+ * Start fixing 2.2 sockets. -+ * -+ * Revision 1.4 1999/04/29 15:21:34 rgb -+ * Move log to the end of the file. -+ * Eliminate min/max redefinition in #include . -+ * Correct path for pfkey #includes -+ * Standardise an error return method. -+ * Add debugging instrumentation. -+ * Move message type checking to pfkey_msg_parse(). -+ * Add check for errno incorrectly set. -+ * Add check for valid PID. -+ * Add check for reserved illegally set. -+ * Add check for message out of bounds. -+ * -+ * Revision 1.3 1999/04/15 17:58:07 rgb -+ * Add RCSID labels. -+ * -+ * Revision 1.2 1999/04/15 15:37:26 rgb -+ * Forward check changes from POST1_00 branch. -+ * -+ * Revision 1.1.2.2 1999/04/13 20:37:12 rgb -+ * Header Title correction. -+ * -+ * Revision 1.1.2.1 1999/03/26 20:58:55 rgb -+ * Add pfkeyv2 support to KLIPS. -+ * -+ * -+ * RFC 2367 -+ * PF_KEY_v2 Key Management API -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/pfkey_v2_ext_process.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,922 @@ -+/* -+ * @(#) RFC2367 PF_KEYv2 Key management API message parser -+ * Copyright (C) 1998-2003 Richard Guy Briggs. -+ * Copyright (C) 2004 Michael Richardson -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* -+ * Template from klips/net/ipsec/ipsec/ipsec_netlink.c. -+ */ -+ -+char pfkey_v2_ext_process_c_version[] = "$Id$"; -+ -+#include -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+ -+#include -+ -+#include -+ -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define ip_chk_addr inet_addr_type -+# define IS_MYADDR RTN_LOCAL -+#endif -+#include -+#include -+#ifdef NETLINK_SOCK -+# include -+#else -+# include -+#endif -+ -+#include /* get_random_bytes() */ -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipcomp.h" -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+#include "openswan/ipsec_alg.h" -+ -+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) -+ -+int -+pfkey_sa_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext; -+ int error = 0; -+ struct ipsec_sa* ipsp; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sa_process: .\n"); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sa_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_ext->sadb_ext_type) { -+ case SADB_EXT_SA: -+ ipsp = extr->ips; -+ break; -+ case SADB_X_EXT_SA2: -+ if(extr->ips2 == NULL) { -+ extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */ -+ } -+ if(extr->ips2 == NULL) { -+ SENDERR(-error); -+ } -+ ipsp = extr->ips2; -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sa_process: " -+ "invalid exttype=%d.\n", -+ pfkey_ext->sadb_ext_type); -+ SENDERR(EINVAL); -+ } -+ -+ ipsp->ips_said.spi = pfkey_sa->sadb_sa_spi; -+ ipsp->ips_replaywin = pfkey_sa->sadb_sa_replay; -+ ipsp->ips_state = pfkey_sa->sadb_sa_state; -+ ipsp->ips_flags = pfkey_sa->sadb_sa_flags; -+ ipsp->ips_replaywin_lastseq = ipsp->ips_replaywin_bitmap = 0; -+ ipsp->ips_ref_rel = pfkey_sa->sadb_x_sa_ref; -+ -+ switch(ipsp->ips_said.proto) { -+ case IPPROTO_AH: -+ ipsp->ips_authalg = pfkey_sa->sadb_sa_auth; -+ ipsp->ips_encalg = SADB_EALG_NONE; -+ break; -+ case IPPROTO_ESP: -+ ipsp->ips_authalg = pfkey_sa->sadb_sa_auth; -+ ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt; -+#ifdef CONFIG_IPSEC_ALG -+ ipsec_alg_sa_init(ipsp); -+#endif /* CONFIG_IPSEC_ALG */ -+ break; -+ case IPPROTO_IPIP: -+ ipsp->ips_authalg = AH_NONE; -+ ipsp->ips_encalg = ESP_NONE; -+ break; -+#ifdef CONFIG_IPSEC_IPCOMP -+ case IPPROTO_COMP: -+ ipsp->ips_authalg = AH_NONE; -+ ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt; -+ break; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ case IPPROTO_INT: -+ ipsp->ips_authalg = AH_NONE; -+ ipsp->ips_encalg = ESP_NONE; -+ break; -+ case 0: -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sa_process: " -+ "unknown proto=%d.\n", -+ ipsp->ips_said.proto); -+ SENDERR(EINVAL); -+ } -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_lifetime_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_lifetime_process: .\n"); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_lifetime_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_lifetime->sadb_lifetime_exttype) { -+ case SADB_EXT_LIFETIME_CURRENT: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_lifetime_process: " -+ "lifetime_current not supported yet.\n"); -+ SENDERR(EINVAL); -+ break; -+ case SADB_EXT_LIFETIME_HARD: -+ ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_allocations, -+ pfkey_lifetime->sadb_lifetime_allocations); -+ -+ ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_bytes, -+ pfkey_lifetime->sadb_lifetime_bytes); -+ -+ ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_addtime, -+ pfkey_lifetime->sadb_lifetime_addtime); -+ -+ ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_usetime, -+ pfkey_lifetime->sadb_lifetime_usetime); -+ -+ break; -+ -+ case SADB_EXT_LIFETIME_SOFT: -+ ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_allocations, -+ pfkey_lifetime->sadb_lifetime_allocations); -+ -+ ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_bytes, -+ pfkey_lifetime->sadb_lifetime_bytes); -+ -+ ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_addtime, -+ pfkey_lifetime->sadb_lifetime_addtime); -+ -+ ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_usetime, -+ pfkey_lifetime->sadb_lifetime_usetime); -+ -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_lifetime_process: " -+ "invalid exttype=%d.\n", -+ pfkey_ext->sadb_ext_type); -+ SENDERR(EINVAL); -+ } -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_address_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ int saddr_len = 0; -+ char ipaddr_txt[ADDRTOA_BUF]; -+ unsigned char **sap; -+ unsigned short * portp = 0; -+ struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext; -+ struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address)); -+ struct ipsec_sa* ipsp; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process:\n"); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(s->sa_family) { -+ case AF_INET: -+ saddr_len = sizeof(struct sockaddr_in); -+ addrtoa(((struct sockaddr_in*)s)->sin_addr, 0, ipaddr_txt, sizeof(ipaddr_txt)); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found address family=%d, AF_INET, %s.\n", -+ s->sa_family, -+ ipaddr_txt); -+ break; -+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+ case AF_INET6: -+ saddr_len = sizeof(struct sockaddr_in6); -+ break; -+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "s->sa_family=%d not supported.\n", -+ s->sa_family); -+ SENDERR(EPFNOSUPPORT); -+ } -+ -+ switch(pfkey_address->sadb_address_exttype) { -+ case SADB_EXT_ADDRESS_SRC: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found src address.\n"); -+ sap = (unsigned char **)&(extr->ips->ips_addr_s); -+ extr->ips->ips_addr_s_size = saddr_len; -+ break; -+ case SADB_EXT_ADDRESS_DST: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found dst address.\n"); -+ sap = (unsigned char **)&(extr->ips->ips_addr_d); -+ extr->ips->ips_addr_d_size = saddr_len; -+ break; -+ case SADB_EXT_ADDRESS_PROXY: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found proxy address.\n"); -+ sap = (unsigned char **)&(extr->ips->ips_addr_p); -+ extr->ips->ips_addr_p_size = saddr_len; -+ break; -+ case SADB_X_EXT_ADDRESS_DST2: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found 2nd dst address.\n"); -+ if(extr->ips2 == NULL) { -+ extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */ -+ } -+ if(extr->ips2 == NULL) { -+ SENDERR(-error); -+ } -+ sap = (unsigned char **)&(extr->ips2->ips_addr_d); -+ extr->ips2->ips_addr_d_size = saddr_len; -+ break; -+ case SADB_X_EXT_ADDRESS_SRC_FLOW: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found src flow address.\n"); -+ if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { -+ SENDERR(ENOMEM); -+ } -+ sap = (unsigned char **)&(extr->eroute->er_eaddr.sen_ip_src); -+ portp = &(extr->eroute->er_eaddr.sen_sport); -+ break; -+ case SADB_X_EXT_ADDRESS_DST_FLOW: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found dst flow address.\n"); -+ if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { -+ SENDERR(ENOMEM); -+ } -+ sap = (unsigned char **)&(extr->eroute->er_eaddr.sen_ip_dst); -+ portp = &(extr->eroute->er_eaddr.sen_dport); -+ break; -+ case SADB_X_EXT_ADDRESS_SRC_MASK: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found src mask address.\n"); -+ if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { -+ SENDERR(ENOMEM); -+ } -+ sap = (unsigned char **)&(extr->eroute->er_emask.sen_ip_src); -+ portp = &(extr->eroute->er_emask.sen_sport); -+ break; -+ case SADB_X_EXT_ADDRESS_DST_MASK: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found dst mask address.\n"); -+ if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) { -+ SENDERR(ENOMEM); -+ } -+ sap = (unsigned char **)&(extr->eroute->er_emask.sen_ip_dst); -+ portp = &(extr->eroute->er_emask.sen_dport); -+ break; -+#ifdef NAT_TRAVERSAL -+ case SADB_X_EXT_NAT_T_OA: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "found NAT-OA address.\n"); -+ sap = (unsigned char **)&(extr->ips->ips_natt_oa); -+ extr->ips->ips_natt_oa_size = saddr_len; -+ break; -+#endif -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "unrecognised ext_type=%d.\n", -+ pfkey_address->sadb_address_exttype); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_address->sadb_address_exttype) { -+ case SADB_EXT_ADDRESS_SRC: -+ case SADB_EXT_ADDRESS_DST: -+ case SADB_EXT_ADDRESS_PROXY: -+ case SADB_X_EXT_ADDRESS_DST2: -+#ifdef NAT_TRAVERSAL -+ case SADB_X_EXT_NAT_T_OA: -+#endif -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "allocating %d bytes for saddr.\n", -+ saddr_len); -+ if(!(*sap = kmalloc(saddr_len, GFP_KERNEL))) { -+ SENDERR(ENOMEM); -+ } -+ memcpy(*sap, s, saddr_len); -+ break; -+ default: -+ if(s->sa_family != AF_INET) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "s->sa_family=%d not supported.\n", -+ s->sa_family); -+ SENDERR(EPFNOSUPPORT); -+ } -+ (unsigned long)(*sap) = ((struct sockaddr_in*)s)->sin_addr.s_addr; -+ if (portp != 0) -+ *portp = ((struct sockaddr_in*)s)->sin_port; -+#ifdef CONFIG_IPSEC_DEBUG -+ if(extr->eroute) { -+ char buf1[64], buf2[64]; -+ if (debug_pfkey) { -+ subnettoa(extr->eroute->er_eaddr.sen_ip_src, -+ extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(extr->eroute->er_eaddr.sen_ip_dst, -+ extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_parse: " -+ "extr->eroute set to %s:%d->%s:%d\n", -+ buf1, -+ ntohs(extr->eroute->er_eaddr.sen_sport), -+ buf2, -+ ntohs(extr->eroute->er_eaddr.sen_dport)); -+ } -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ } -+ -+ ipsp = extr->ips; -+ switch(pfkey_address->sadb_address_exttype) { -+ case SADB_X_EXT_ADDRESS_DST2: -+ ipsp = extr->ips2; -+ case SADB_EXT_ADDRESS_DST: -+ if(s->sa_family == AF_INET) { -+ ipsp->ips_said.dst.u.v4.sin_addr.s_addr = ((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr.s_addr; -+ ipsp->ips_said.dst.u.v4.sin_family = AF_INET; -+ addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr, -+ 0, -+ ipaddr_txt, -+ sizeof(ipaddr_txt)); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "ips_said.dst set to %s.\n", -+ ipaddr_txt); -+ } else { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: " -+ "uh, ips_said.dst doesn't do address family=%d yet, said will be invalid.\n", -+ s->sa_family); -+ } -+ default: -+ break; -+ } -+ -+ /* XXX check if port!=0 */ -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_address_process: successful.\n"); -+ errlab: -+ return error; -+} -+ -+int -+pfkey_key_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct sadb_key *pfkey_key = (struct sadb_key *)pfkey_ext; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_key_process: .\n"); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_key_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_key->sadb_key_exttype) { -+ case SADB_EXT_KEY_AUTH: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_key_process: " -+ "allocating %d bytes for authkey.\n", -+ DIVUP(pfkey_key->sadb_key_bits, 8)); -+ if(!(extr->ips->ips_key_a = kmalloc(DIVUP(pfkey_key->sadb_key_bits, 8), GFP_KERNEL))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_key_process: " -+ "memory allocation error.\n"); -+ SENDERR(ENOMEM); -+ } -+ extr->ips->ips_key_bits_a = pfkey_key->sadb_key_bits; -+ extr->ips->ips_key_a_size = DIVUP(pfkey_key->sadb_key_bits, 8); -+ memcpy(extr->ips->ips_key_a, -+ (char*)pfkey_key + sizeof(struct sadb_key), -+ extr->ips->ips_key_a_size); -+ break; -+ case SADB_EXT_KEY_ENCRYPT: /* Key(s) */ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_key_process: " -+ "allocating %d bytes for enckey.\n", -+ DIVUP(pfkey_key->sadb_key_bits, 8)); -+ if(!(extr->ips->ips_key_e = kmalloc(DIVUP(pfkey_key->sadb_key_bits, 8), GFP_KERNEL))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_key_process: " -+ "memory allocation error.\n"); -+ SENDERR(ENOMEM); -+ } -+ extr->ips->ips_key_bits_e = pfkey_key->sadb_key_bits; -+ extr->ips->ips_key_e_size = DIVUP(pfkey_key->sadb_key_bits, 8); -+ memcpy(extr->ips->ips_key_e, -+ (char*)pfkey_key + sizeof(struct sadb_key), -+ extr->ips->ips_key_e_size); -+ break; -+ default: -+ SENDERR(EINVAL); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_key_process: " -+ "success.\n"); -+errlab: -+ return error; -+} -+ -+int -+pfkey_ident_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct sadb_ident *pfkey_ident = (struct sadb_ident *)pfkey_ext; -+ int data_len; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ident_process: .\n"); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ident_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_ident->sadb_ident_exttype) { -+ case SADB_EXT_IDENTITY_SRC: -+ data_len = pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); -+ -+ extr->ips->ips_ident_s.type = pfkey_ident->sadb_ident_type; -+ extr->ips->ips_ident_s.id = pfkey_ident->sadb_ident_id; -+ extr->ips->ips_ident_s.len = pfkey_ident->sadb_ident_len; -+ if(data_len) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ident_process: " -+ "allocating %d bytes for ident_s.\n", -+ data_len); -+ if(!(extr->ips->ips_ident_s.data -+ = kmalloc(data_len, GFP_KERNEL))) { -+ SENDERR(ENOMEM); -+ } -+ memcpy(extr->ips->ips_ident_s.data, -+ (char*)pfkey_ident + sizeof(struct sadb_ident), -+ data_len); -+ } else { -+ extr->ips->ips_ident_s.data = NULL; -+ } -+ break; -+ case SADB_EXT_IDENTITY_DST: /* Identity(ies) */ -+ data_len = pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); -+ -+ extr->ips->ips_ident_d.type = pfkey_ident->sadb_ident_type; -+ extr->ips->ips_ident_d.id = pfkey_ident->sadb_ident_id; -+ extr->ips->ips_ident_d.len = pfkey_ident->sadb_ident_len; -+ if(data_len) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ident_process: " -+ "allocating %d bytes for ident_d.\n", -+ data_len); -+ if(!(extr->ips->ips_ident_d.data -+ = kmalloc(data_len, GFP_KERNEL))) { -+ SENDERR(ENOMEM); -+ } -+ memcpy(extr->ips->ips_ident_d.data, -+ (char*)pfkey_ident + sizeof(struct sadb_ident), -+ data_len); -+ } else { -+ extr->ips->ips_ident_d.data = NULL; -+ } -+ break; -+ default: -+ SENDERR(EINVAL); -+ } -+errlab: -+ return error; -+} -+ -+int -+pfkey_sens_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_sens_process: " -+ "Sorry, I can't process exttype=%d yet.\n", -+ pfkey_ext->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ errlab: -+ return error; -+} -+ -+int -+pfkey_prop_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_prop_process: " -+ "Sorry, I can't process exttype=%d yet.\n", -+ pfkey_ext->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ -+ errlab: -+ return error; -+} -+ -+int -+pfkey_supported_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_supported_process: " -+ "Sorry, I can't process exttype=%d yet.\n", -+ pfkey_ext->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_spirange_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_spirange_process: .\n"); -+/* errlab: */ -+ return error; -+} -+ -+int -+pfkey_x_kmprivate_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_kmprivate_process: " -+ "Sorry, I can't process exttype=%d yet.\n", -+ pfkey_ext->sadb_ext_type); -+ SENDERR(EINVAL); /* don't process these yet */ -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_x_satype_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_satype_process: .\n"); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_satype_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(extr->ips2 == NULL) { -+ extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */ -+ } -+ if(extr->ips2 == NULL) { -+ SENDERR(-error); -+ } -+ if(!(extr->ips2->ips_said.proto = satype2proto(pfkey_x_satype->sadb_x_satype_satype))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_satype_process: " -+ "proto lookup from satype=%d failed.\n", -+ pfkey_x_satype->sadb_x_satype_satype); -+ SENDERR(EINVAL); -+ } -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_satype_process: " -+ "protocol==%d decoded from satype==%d(%s).\n", -+ extr->ips2->ips_said.proto, -+ pfkey_x_satype->sadb_x_satype_satype, -+ satype2name(pfkey_x_satype->sadb_x_satype_satype)); -+ -+errlab: -+ return error; -+} -+ -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+int -+pfkey_x_nat_t_type_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)pfkey_ext; -+ -+ if(!pfkey_x_nat_t_type) { -+ printk("klips_debug:pfkey_x_nat_t_type_process: " -+ "null pointer passed in\n"); -+ SENDERR(EINVAL); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_nat_t_type_process: %d.\n", -+ pfkey_x_nat_t_type->sadb_x_nat_t_type_type); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_nat_t_type_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_x_nat_t_type->sadb_x_nat_t_type_type) { -+ case ESPINUDP_WITH_NON_IKE: /* with Non-IKE (older version) */ -+ case ESPINUDP_WITH_NON_ESP: /* with Non-ESP */ -+ -+ extr->ips->ips_natt_type = pfkey_x_nat_t_type->sadb_x_nat_t_type_type; -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_nat_t_type_process: " -+ "unknown type %d.\n", -+ pfkey_x_nat_t_type->sadb_x_nat_t_type_type); -+ SENDERR(EINVAL); -+ break; -+ } -+ -+errlab: -+ return error; -+} -+ -+int -+pfkey_x_nat_t_port_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)pfkey_ext; -+ -+ if(!pfkey_x_nat_t_port) { -+ printk("klips_debug:pfkey_x_nat_t_port_process: " -+ "null pointer passed in\n"); -+ SENDERR(EINVAL); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_nat_t_port_process: %d/%d.\n", -+ pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype, -+ pfkey_x_nat_t_port->sadb_x_nat_t_port_port); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_nat_t_type_process: " -+ "extr or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype) { -+ case SADB_X_EXT_NAT_T_SPORT: -+ extr->ips->ips_natt_sport = pfkey_x_nat_t_port->sadb_x_nat_t_port_port; -+ break; -+ case SADB_X_EXT_NAT_T_DPORT: -+ extr->ips->ips_natt_dport = pfkey_x_nat_t_port->sadb_x_nat_t_port_port; -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_nat_t_port_process: " -+ "unknown exttype %d.\n", -+ pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype); -+ SENDERR(EINVAL); -+ break; -+ } -+ -+errlab: -+ return error; -+} -+#endif -+ -+int -+pfkey_x_debug_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)pfkey_ext; -+ -+ if(!pfkey_x_debug) { -+ printk("klips_debug:pfkey_x_debug_process: " -+ "null pointer passed in\n"); -+ SENDERR(EINVAL); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_debug_process: .\n"); -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if(pfkey_x_debug->sadb_x_debug_netlink >> -+ (sizeof(pfkey_x_debug->sadb_x_debug_netlink) * 8 - 1)) { -+ pfkey_x_debug->sadb_x_debug_netlink &= -+ ~(1 << (sizeof(pfkey_x_debug->sadb_x_debug_netlink) * 8 -1)); -+ debug_tunnel |= pfkey_x_debug->sadb_x_debug_tunnel; -+ debug_netlink |= pfkey_x_debug->sadb_x_debug_netlink; -+ debug_xform |= pfkey_x_debug->sadb_x_debug_xform; -+ debug_eroute |= pfkey_x_debug->sadb_x_debug_eroute; -+ debug_spi |= pfkey_x_debug->sadb_x_debug_spi; -+ debug_radij |= pfkey_x_debug->sadb_x_debug_radij; -+ debug_esp |= pfkey_x_debug->sadb_x_debug_esp; -+ debug_ah |= pfkey_x_debug->sadb_x_debug_ah; -+ debug_rcv |= pfkey_x_debug->sadb_x_debug_rcv; -+ debug_pfkey |= pfkey_x_debug->sadb_x_debug_pfkey; -+#ifdef CONFIG_IPSEC_IPCOMP -+ sysctl_ipsec_debug_ipcomp |= pfkey_x_debug->sadb_x_debug_ipcomp; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ sysctl_ipsec_debug_verbose |= pfkey_x_debug->sadb_x_debug_verbose; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_debug_process: " -+ "set\n"); -+ } else { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_debug_process: " -+ "unset\n"); -+ debug_tunnel &= pfkey_x_debug->sadb_x_debug_tunnel; -+ debug_netlink &= pfkey_x_debug->sadb_x_debug_netlink; -+ debug_xform &= pfkey_x_debug->sadb_x_debug_xform; -+ debug_eroute &= pfkey_x_debug->sadb_x_debug_eroute; -+ debug_spi &= pfkey_x_debug->sadb_x_debug_spi; -+ debug_radij &= pfkey_x_debug->sadb_x_debug_radij; -+ debug_esp &= pfkey_x_debug->sadb_x_debug_esp; -+ debug_ah &= pfkey_x_debug->sadb_x_debug_ah; -+ debug_rcv &= pfkey_x_debug->sadb_x_debug_rcv; -+ debug_pfkey &= pfkey_x_debug->sadb_x_debug_pfkey; -+#ifdef CONFIG_IPSEC_IPCOMP -+ sysctl_ipsec_debug_ipcomp &= pfkey_x_debug->sadb_x_debug_ipcomp; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ sysctl_ipsec_debug_verbose &= pfkey_x_debug->sadb_x_debug_verbose; -+ } -+#else /* CONFIG_IPSEC_DEBUG */ -+ printk("klips_debug:pfkey_x_debug_process: " -+ "debugging not enabled\n"); -+ SENDERR(EINVAL); -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+errlab: -+ return error; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.15 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.14 2004/02/03 03:13:59 mcr -+ * no longer #ifdef out NON_ESP mode. That was a mistake. -+ * -+ * Revision 1.13 2003/12/15 18:13:12 mcr -+ * when compiling with NAT traversal, don't assume that the -+ * kernel has been patched, unless CONFIG_IPSEC_NAT_NON_ESP -+ * is set. -+ * -+ * Revision 1.12.2.1 2003/12/22 15:25:52 jjo -+ * Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.12 2003/12/10 01:14:27 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.11 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.10.4.2 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.10.4.1 2003/09/21 13:59:56 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.10 2003/02/06 01:51:41 rgb -+ * Removed no longer relevant comment -+ * -+ * Revision 1.9 2003/01/30 02:32:44 rgb -+ * -+ * Transmit error code through to caller from callee for better diagnosis of problems. -+ * -+ * Revision 1.8 2002/12/13 22:42:22 mcr -+ * restored sa_ref code -+ * -+ * Revision 1.7 2002/12/13 22:40:48 mcr -+ * temporarily removed sadb_x_sa_ref reference for 2.xx -+ * -+ * Revision 1.6 2002/10/05 05:02:58 dhr -+ * -+ * C labels go on statements -+ * -+ * Revision 1.5 2002/09/20 15:41:08 rgb -+ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc(). -+ * Added sadb_x_sa_ref to struct sadb_sa. -+ * -+ * Revision 1.4 2002/09/20 05:02:02 rgb -+ * Added memory allocation debugging. -+ * -+ * Revision 1.3 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.2 2002/05/27 18:55:03 rgb -+ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT. -+ * -+ * Revision 1.1 2002/05/14 02:33:51 rgb -+ * Moved all the extension processing functions to pfkey_v2_ext_process.c. -+ * -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/pfkey_v2_parser.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,4018 @@ -+/* -+ * @(#) RFC2367 PF_KEYv2 Key management API message parser -+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* -+ * Template from klips/net/ipsec/ipsec/ipsec_netlink.c. -+ */ -+ -+char pfkey_v2_parser_c_version[] = "$Id$"; -+ -+#include -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+ -+#include -+ -+#include -+ -+#ifdef SPINLOCK -+# ifdef SPINLOCK_23 -+# include /* *lock* */ -+# else /* SPINLOCK_23 */ -+# include /* *lock* */ -+# endif /* SPINLOCK_23 */ -+#endif /* SPINLOCK */ -+#ifdef NET_21 -+# include -+# include -+# define ip_chk_addr inet_addr_type -+# define IS_MYADDR RTN_LOCAL -+#endif -+#include -+#include -+#ifdef NETLINK_SOCK -+# include -+#else -+# include -+#endif -+ -+#include /* get_random_bytes() */ -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_sa.h" -+ -+#include "openswan/ipsec_radij.h" -+#include "openswan/ipsec_xform.h" -+#include "openswan/ipsec_ah.h" -+#include "openswan/ipsec_esp.h" -+#include "openswan/ipsec_tunnel.h" -+#include "openswan/ipsec_rcv.h" -+#include "openswan/ipcomp.h" -+ -+#include -+#include -+ -+#include "openswan/ipsec_proto.h" -+#include "openswan/ipsec_alg.h" -+ -+ -+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) -+ -+struct sklist_t { -+ struct socket *sk; -+ struct sklist_t* next; -+} pfkey_sklist_head, *pfkey_sklist, *pfkey_sklist_prev; -+ -+__u32 pfkey_msg_seq = 0; -+ -+ -+#if 0 -+#define DUMP_SAID dump_said(&extr->ips->ips_said, __LINE__) -+#define DUMP_SAID2 dump_said(&extr.ips->ips_said, __LINE__) -+static void dump_said(ip_said *s, int line) -+{ -+ char msa[SATOT_BUF]; -+ size_t msa_len; -+ -+ msa_len = satot(s, 0, msa, sizeof(msa)); -+ -+ printk("line: %d msa: %s\n", line, msa); -+} -+#endif -+ -+ -+int -+pfkey_alloc_eroute(struct eroute** eroute) -+{ -+ int error = 0; -+ if(*eroute) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_alloc_eroute: " -+ "eroute struct already allocated\n"); -+ SENDERR(EEXIST); -+ } -+ -+ if((*eroute = kmalloc(sizeof(**eroute), GFP_ATOMIC) ) == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_alloc_eroute: " -+ "memory allocation error\n"); -+ SENDERR(ENOMEM); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_alloc_eroute: " -+ "allocating %lu bytes for an eroute at 0p%p\n", -+ (unsigned long) sizeof(**eroute), *eroute); -+ -+ memset((caddr_t)*eroute, 0, sizeof(**eroute)); -+ (*eroute)->er_eaddr.sen_len = -+ (*eroute)->er_emask.sen_len = sizeof(struct sockaddr_encap); -+ (*eroute)->er_eaddr.sen_family = -+ (*eroute)->er_emask.sen_family = AF_ENCAP; -+ (*eroute)->er_eaddr.sen_type = SENT_IP4; -+ (*eroute)->er_emask.sen_type = 255; -+ (*eroute)->er_pid = 0; -+ (*eroute)->er_count = 0; -+ (*eroute)->er_lasttime = jiffies/HZ; -+ -+ errlab: -+ return(error); -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_protocol_process(struct sadb_ext *pfkey_ext, -+ struct pfkey_extracted_data *extr) -+{ -+ int error = 0; -+ struct sadb_protocol * p = (struct sadb_protocol *)pfkey_ext; -+ -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process: %p\n", extr); -+ -+ if (extr == 0) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_protocol_process:" -+ "extr is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ if (extr->eroute == 0) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_protocol_process:" -+ "extr->eroute is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ extr->eroute->er_eaddr.sen_proto = p->sadb_protocol_proto; -+ extr->eroute->er_emask.sen_proto = p->sadb_protocol_proto ? ~0:0; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_protocol_process: protocol = %d.\n", -+ p->sadb_protocol_proto); -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_ipsec_sa_init(struct ipsec_sa *ipsp, struct sadb_ext **extensions) -+{ -+ int i; -+ int error = 0; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ char ipaddr_txt[ADDRTOA_BUF]; -+ char ipaddr2_txt[ADDRTOA_BUF]; -+#if defined (CONFIG_IPSEC_AUTH_HMAC_MD5) || defined (CONFIG_IPSEC_AUTH_HMAC_SHA1) -+ unsigned char kb[AHMD596_BLKLEN]; -+#endif -+#ifdef CONFIG_IPSEC_ALG -+ struct ipsec_alg_enc *ixt_e = NULL; -+ struct ipsec_alg_auth *ixt_a = NULL; -+#endif /* CONFIG_IPSEC_ALG */ -+ -+ if(ipsp == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "ipsp is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ sa_len = satot(&ipsp->ips_said, 0, sa, sizeof(sa)); -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "(pfkey defined) called for SA:%s\n", -+ sa_len ? sa : " (error)"); -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "calling init routine of %s%s%s\n", -+ IPS_XFORM_NAME(ipsp)); -+ -+ switch(ipsp->ips_said.proto) { -+ -+#ifdef CONFIG_IPSEC_IPIP -+ case IPPROTO_IPIP: { -+ addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_s))->sin_addr, -+ 0, -+ ipaddr_txt, sizeof(ipaddr_txt)); -+ addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr, -+ 0, -+ ipaddr2_txt, sizeof(ipaddr_txt)); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "(pfkey defined) IPIP ipsec_sa set for %s->%s.\n", -+ ipaddr_txt, -+ ipaddr2_txt); -+ } -+ break; -+#endif /* !CONFIG_IPSEC_IPIP */ -+#ifdef CONFIG_IPSEC_AH -+ case IPPROTO_AH: -+ switch(ipsp->ips_authalg) { -+# ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: { -+ unsigned char *akp; -+ unsigned int aks; -+ MD5_CTX *ictx; -+ MD5_CTX *octx; -+ -+ if(ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, -+ ipsp->ips_key_bits_a, AHMD596_KLEN * 8); -+ SENDERR(EINVAL); -+ } -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "hmac md5-96 key is 0x%08x %08x %08x %08x\n", -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ -+ ipsp->ips_auth_bits = AHMD596_ALEN * 8; -+ -+ /* save the pointer to the key material */ -+ akp = ipsp->ips_key_a; -+ aks = ipsp->ips_key_a_size; -+ -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "allocating %lu bytes for md5_ctx.\n", -+ (unsigned long) sizeof(struct md5_ctx)); -+ if((ipsp->ips_key_a = (caddr_t) -+ kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { -+ ipsp->ips_key_a = akp; -+ SENDERR(ENOMEM); -+ } -+ ipsp->ips_key_a_size = sizeof(struct md5_ctx); -+ -+ for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { -+ kb[i] = akp[i] ^ HMAC_IPAD; -+ } -+ for (; i < AHMD596_BLKLEN; i++) { -+ kb[i] = HMAC_IPAD; -+ } -+ -+ ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx); -+ MD5Init(ictx); -+ MD5Update(ictx, kb, AHMD596_BLKLEN); -+ -+ for (i = 0; i < AHMD596_BLKLEN; i++) { -+ kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); -+ } -+ -+ octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx); -+ MD5Init(octx); -+ MD5Update(octx, kb, AHMD596_BLKLEN); -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", -+ ((__u32*)ictx)[0], -+ ((__u32*)ictx)[1], -+ ((__u32*)ictx)[2], -+ ((__u32*)ictx)[3], -+ ((__u32*)octx)[0], -+ ((__u32*)octx)[1], -+ ((__u32*)octx)[2], -+ ((__u32*)octx)[3] ); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ -+ /* zero key buffer -- paranoid */ -+ memset(akp, 0, aks); -+ kfree(akp); -+ } -+ break; -+# endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+# ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: { -+ unsigned char *akp; -+ unsigned int aks; -+ SHA1_CTX *ictx; -+ SHA1_CTX *octx; -+ -+ if(ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, -+ ipsp->ips_key_bits_a, AHSHA196_KLEN * 8); -+ SENDERR(EINVAL); -+ } -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ -+ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; -+ -+ /* save the pointer to the key material */ -+ akp = ipsp->ips_key_a; -+ aks = ipsp->ips_key_a_size; -+ -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "allocating %lu bytes for sha1_ctx.\n", -+ (unsigned long) sizeof(struct sha1_ctx)); -+ if((ipsp->ips_key_a = (caddr_t) -+ kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { -+ ipsp->ips_key_a = akp; -+ SENDERR(ENOMEM); -+ } -+ ipsp->ips_key_a_size = sizeof(struct sha1_ctx); -+ -+ for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { -+ kb[i] = akp[i] ^ HMAC_IPAD; -+ } -+ for (; i < AHMD596_BLKLEN; i++) { -+ kb[i] = HMAC_IPAD; -+ } -+ -+ ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx); -+ SHA1Init(ictx); -+ SHA1Update(ictx, kb, AHSHA196_BLKLEN); -+ -+ for (i = 0; i < AHSHA196_BLKLEN; i++) { -+ kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); -+ } -+ -+ octx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->octx); -+ SHA1Init(octx); -+ SHA1Update(octx, kb, AHSHA196_BLKLEN); -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", -+ ((__u32*)ictx)[0], -+ ((__u32*)ictx)[1], -+ ((__u32*)ictx)[2], -+ ((__u32*)ictx)[3], -+ ((__u32*)octx)[0], -+ ((__u32*)octx)[1], -+ ((__u32*)octx)[2], -+ ((__u32*)octx)[3] ); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ /* zero key buffer -- paranoid */ -+ memset(akp, 0, aks); -+ kfree(akp); -+ } -+ break; -+# endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "authalg=%d support not available in the kernel", -+ ipsp->ips_authalg); -+ SENDERR(EINVAL); -+ } -+ break; -+#endif /* CONFIG_IPSEC_AH */ -+#ifdef CONFIG_IPSEC_ESP -+ case IPPROTO_ESP: { -+#if defined (CONFIG_IPSEC_AUTH_HMAC_MD5) || defined (CONFIG_IPSEC_AUTH_HMAC_SHA1) -+ unsigned char *akp; -+ unsigned int aks; -+#endif -+#if defined (CONFIG_IPSEC_ENC_3DES) -+ unsigned char *ekp; -+ unsigned int eks; -+#endif -+ -+ ipsp->ips_iv_size = 0; -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_e=ipsp->ips_alg_enc)) { -+ ipsp->ips_iv_size = ixt_e->ixt_ivlen/8; -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ipsp->ips_encalg) { -+# ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+# endif /* CONFIG_IPSEC_ENC_3DES */ -+# if defined(CONFIG_IPSEC_ENC_3DES) -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "allocating %u bytes for iv.\n", -+ EMT_ESPDES_IV_SZ); -+ if((ipsp->ips_iv = (caddr_t) -+ kmalloc((ipsp->ips_iv_size = EMT_ESPDES_IV_SZ), GFP_ATOMIC)) == NULL) { -+ SENDERR(ENOMEM); -+ } -+ prng_bytes(&ipsec_prng, (char *)ipsp->ips_iv, EMT_ESPDES_IV_SZ); -+ ipsp->ips_iv_bits = ipsp->ips_iv_size * 8; -+ ipsp->ips_iv_size = EMT_ESPDES_IV_SZ; -+ break; -+# endif /* defined(CONFIG_IPSEC_ENC_3DES) */ -+ case ESP_NONE: -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "encalg=%d support not available in the kernel", -+ ipsp->ips_encalg); -+ SENDERR(EINVAL); -+ } -+ -+ /* Create IV */ -+ if (ipsp->ips_iv_size) { -+ if((ipsp->ips_iv = (caddr_t) -+ kmalloc(ipsp->ips_iv_size, GFP_ATOMIC)) == NULL) { -+ SENDERR(ENOMEM); -+ } -+ prng_bytes(&ipsec_prng, (char *)ipsp->ips_iv, ipsp->ips_iv_size); -+ ipsp->ips_iv_bits = ipsp->ips_iv_size * 8; -+ } -+ -+#ifdef CONFIG_IPSEC_ALG -+ if (ixt_e) { -+ if ((error=ipsec_alg_enc_key_create(ipsp)) < 0) -+ SENDERR(-error); -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ switch(ipsp->ips_encalg) { -+# ifdef CONFIG_IPSEC_ENC_3DES -+ case ESP_3DES: -+ if(ipsp->ips_key_bits_e != (EMT_ESP3DES_KEY_SZ * 8)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "incorrect encryption key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, -+ ipsp->ips_key_bits_e, EMT_ESP3DES_KEY_SZ * 8); -+ SENDERR(EINVAL); -+ } -+ -+ /* save encryption key pointer */ -+ ekp = ipsp->ips_key_e; -+ eks = ipsp->ips_key_e_size; -+ -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "allocating %lu bytes for 3des.\n", -+ (unsigned long) (3 * sizeof(struct des_eks))); -+ if((ipsp->ips_key_e = (caddr_t) -+ kmalloc(3 * sizeof(struct des_eks), GFP_ATOMIC)) == NULL) { -+ ipsp->ips_key_e = ekp; -+ SENDERR(ENOMEM); -+ } -+ ipsp->ips_key_e_size = 3 * sizeof(struct des_eks); -+ -+ for(i = 0; i < 3; i++) { -+#if KLIPS_DIVULGE_CYPHER_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "3des key %d/3 is 0x%08x%08x\n", -+ i + 1, -+ ntohl(*((__u32 *)ekp + i * 2)), -+ ntohl(*((__u32 *)ekp + i * 2 + 1))); -+# endif -+#if KLIPS_FIXES_DES_PARITY -+ /* force parity */ -+ des_set_odd_parity((des_cblock *)(ekp + EMT_ESPDES_KEY_SZ * i)); -+#endif -+ error = des_set_key((des_cblock *)(ekp + EMT_ESPDES_KEY_SZ * i), -+ ((struct des_eks *)(ipsp->ips_key_e))[i].ks); -+ if (error == -1) -+ printk("klips_debug:pfkey_ipsec_sa_init: " -+ "parity error in des key %d/3\n", -+ i + 1); -+ else if (error == -2) -+ printk("klips_debug:pfkey_ipsec_sa_init: " -+ "illegal weak des key %d/3\n", i + 1); -+ if (error) { -+ memset(ekp, 0, eks); -+ kfree(ekp); -+ SENDERR(EINVAL); -+ } -+ } -+ -+ /* paranoid */ -+ memset(ekp, 0, eks); -+ kfree(ekp); -+ break; -+# endif /* CONFIG_IPSEC_ENC_3DES */ -+ case ESP_NONE: -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "encalg=%d support not available in the kernel", -+ ipsp->ips_encalg); -+ SENDERR(EINVAL); -+ } -+ -+#ifdef CONFIG_IPSEC_ALG -+ if ((ixt_a=ipsp->ips_alg_auth)) { -+ if ((error=ipsec_alg_auth_key_create(ipsp)) < 0) -+ SENDERR(-error); -+ } else -+#endif /* CONFIG_IPSEC_ALG */ -+ -+ switch(ipsp->ips_authalg) { -+# ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 -+ case AH_MD5: { -+ MD5_CTX *ictx; -+ MD5_CTX *octx; -+ -+ if(ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, -+ ipsp->ips_key_bits_a, -+ AHMD596_KLEN * 8); -+ SENDERR(EINVAL); -+ } -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "hmac md5-96 key is 0x%08x %08x %08x %08x\n", -+ ntohl(*(((__u32 *)(ipsp->ips_key_a))+0)), -+ ntohl(*(((__u32 *)(ipsp->ips_key_a))+1)), -+ ntohl(*(((__u32 *)(ipsp->ips_key_a))+2)), -+ ntohl(*(((__u32 *)(ipsp->ips_key_a))+3))); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ ipsp->ips_auth_bits = AHMD596_ALEN * 8; -+ -+ /* save the pointer to the key material */ -+ akp = ipsp->ips_key_a; -+ aks = ipsp->ips_key_a_size; -+ -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "allocating %lu bytes for md5_ctx.\n", -+ (unsigned long) sizeof(struct md5_ctx)); -+ if((ipsp->ips_key_a = (caddr_t) -+ kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { -+ ipsp->ips_key_a = akp; -+ SENDERR(ENOMEM); -+ } -+ ipsp->ips_key_a_size = sizeof(struct md5_ctx); -+ -+ for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { -+ kb[i] = akp[i] ^ HMAC_IPAD; -+ } -+ for (; i < AHMD596_BLKLEN; i++) { -+ kb[i] = HMAC_IPAD; -+ } -+ -+ ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx); -+ MD5Init(ictx); -+ MD5Update(ictx, kb, AHMD596_BLKLEN); -+ -+ for (i = 0; i < AHMD596_BLKLEN; i++) { -+ kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); -+ } -+ -+ octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx); -+ MD5Init(octx); -+ MD5Update(octx, kb, AHMD596_BLKLEN); -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", -+ ((__u32*)ictx)[0], -+ ((__u32*)ictx)[1], -+ ((__u32*)ictx)[2], -+ ((__u32*)ictx)[3], -+ ((__u32*)octx)[0], -+ ((__u32*)octx)[1], -+ ((__u32*)octx)[2], -+ ((__u32*)octx)[3] ); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ /* paranoid */ -+ memset(akp, 0, aks); -+ kfree(akp); -+ break; -+ } -+# endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ -+# ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 -+ case AH_SHA: { -+ SHA1_CTX *ictx; -+ SHA1_CTX *octx; -+ -+ if(ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, -+ ipsp->ips_key_bits_a, -+ AHSHA196_KLEN * 8); -+ SENDERR(EINVAL); -+ } -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), -+ ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; -+ -+ /* save the pointer to the key material */ -+ akp = ipsp->ips_key_a; -+ aks = ipsp->ips_key_a_size; -+ -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "allocating %lu bytes for sha1_ctx.\n", -+ (unsigned long) sizeof(struct sha1_ctx)); -+ if((ipsp->ips_key_a = (caddr_t) -+ kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { -+ ipsp->ips_key_a = akp; -+ SENDERR(ENOMEM); -+ } -+ ipsp->ips_key_a_size = sizeof(struct sha1_ctx); -+ -+ for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { -+ kb[i] = akp[i] ^ HMAC_IPAD; -+ } -+ for (; i < AHMD596_BLKLEN; i++) { -+ kb[i] = HMAC_IPAD; -+ } -+ -+ ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx); -+ SHA1Init(ictx); -+ SHA1Update(ictx, kb, AHSHA196_BLKLEN); -+ -+ for (i = 0; i < AHSHA196_BLKLEN; i++) { -+ kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); -+ } -+ -+ octx = &((struct sha1_ctx*)(ipsp->ips_key_a))->octx; -+ SHA1Init(octx); -+ SHA1Update(octx, kb, AHSHA196_BLKLEN); -+ -+# if KLIPS_DIVULGE_HMAC_KEY -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", -+ ((__u32*)ictx)[0], -+ ((__u32*)ictx)[1], -+ ((__u32*)ictx)[2], -+ ((__u32*)ictx)[3], -+ ((__u32*)octx)[0], -+ ((__u32*)octx)[1], -+ ((__u32*)octx)[2], -+ ((__u32*)octx)[3] ); -+# endif /* KLIPS_DIVULGE_HMAC_KEY */ -+ memset(akp, 0, aks); -+ kfree(akp); -+ break; -+ } -+# endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ -+ case AH_NONE: -+ break; -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "authalg=%d support not available in the kernel.\n", -+ ipsp->ips_authalg); -+ SENDERR(EINVAL); -+ } -+ } -+ break; -+#endif /* !CONFIG_IPSEC_ESP */ -+#ifdef CONFIG_IPSEC_IPCOMP -+ case IPPROTO_COMP: -+ ipsp->ips_comp_adapt_tries = 0; -+ ipsp->ips_comp_adapt_skip = 0; -+ ipsp->ips_comp_ratio_cbytes = 0; -+ ipsp->ips_comp_ratio_dbytes = 0; -+ break; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ default: -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_ipsec_sa_init: " -+ "proto=%d unknown.\n", -+ ipsp->ips_said.proto); -+ SENDERR(EINVAL); -+ } -+ -+ errlab: -+ return(error); -+} -+ -+ -+int -+pfkey_safe_build(int error, struct sadb_ext *extensions[SADB_MAX+1]) -+{ -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build: " -+ "error=%d\n", -+ error); -+ if (!error) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:" -+ "success.\n"); -+ return 1; -+ } else { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:" -+ "caught error %d\n", -+ error); -+ pfkey_extensions_free(extensions); -+ return 0; -+ } -+} -+ -+ -+DEBUG_NO_STATIC int -+pfkey_getspi_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ ipsec_spi_t minspi = htonl(256), maxspi = htonl(-1L); -+ int found_avail = 0; -+ struct ipsec_sa *ipsq; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getspi_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ if(extr == NULL || extr->ips == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getspi_parse: " -+ "error, extr or extr->ipsec_sa pointer NULL\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(extensions[SADB_EXT_SPIRANGE]) { -+ minspi = ((struct sadb_spirange *)extensions[SADB_EXT_SPIRANGE])->sadb_spirange_min; -+ maxspi = ((struct sadb_spirange *)extensions[SADB_EXT_SPIRANGE])->sadb_spirange_max; -+ } -+ -+ if(maxspi == minspi) { -+ extr->ips->ips_said.spi = maxspi; -+ ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if(ipsq != NULL) { -+ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); -+ ipsec_sa_put(ipsq); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getspi_parse: " -+ "EMT_GETSPI found an old ipsec_sa for SA: %s, delete it first.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(EEXIST); -+ } else { -+ found_avail = 1; -+ } -+ } else { -+ int i = 0; -+ __u32 rand_val; -+ __u32 spi_diff; -+ while( ( i < (spi_diff = (ntohl(maxspi) - ntohl(minspi)))) && !found_avail ) { -+ prng_bytes(&ipsec_prng, (char *) &(rand_val), -+ ( (spi_diff < (2^8)) ? 1 : -+ ( (spi_diff < (2^16)) ? 2 : -+ ( (spi_diff < (2^24)) ? 3 : -+ 4 ) ) ) ); -+ extr->ips->ips_said.spi = htonl(ntohl(minspi) + -+ (rand_val % -+ (spi_diff + 1))); -+ i++; -+ ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if(ipsq == NULL) { -+ found_avail = 1; -+ } else { -+ ipsec_sa_put(ipsq); -+ } -+ } -+ } -+ -+ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); -+ -+ if (!found_avail) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getspi_parse: " -+ "found an old ipsec_sa for SA: %s, delete it first.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(EEXIST); -+ } -+ -+ if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == IS_MYADDR) { -+ extr->ips->ips_flags |= EMT_INBOUND; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getspi_parse: " -+ "existing ipsec_sa not found (this is good) for SA: %s, %s-bound, allocating.\n", -+ sa_len ? sa : " (error)", -+ extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); -+ -+ /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ -+ extr->ips->ips_rcvif = NULL; -+ extr->ips->ips_life.ipl_addtime.ipl_count = jiffies/HZ; -+ -+ extr->ips->ips_state = SADB_SASTATE_LARVAL; -+ -+ if(!extr->ips->ips_life.ipl_allocations.ipl_count) { -+ extr->ips->ips_life.ipl_allocations.ipl_count += 1; -+ } -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_GETSPI, -+ satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ 0, -+ SADB_SASTATE_LARVAL, -+ 0, -+ 0, -+ 0, -+ extr->ips->ips_ref), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_s), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_d), -+ extensions_reply) )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " -+ "failed to build the getspi reply message extensions\n"); -+ goto errlab; -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " -+ "failed to build the getspi reply message\n"); -+ SENDERR(-error); -+ } -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " -+ "sending up getspi reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " -+ "sending up getspi reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ if((error = ipsec_sa_add(extr->ips))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " -+ "failed to add the larval SA=%s with error=%d.\n", -+ sa_len ? sa : " (error)", -+ error); -+ SENDERR(-error); -+ } -+ extr->ips = NULL; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_getspi_parse: " -+ "successful for SA: %s\n", -+ sa_len ? sa : " (error)"); -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_update_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct ipsec_sa* ipsq; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ struct ipsec_sa *nat_t_ips_saved = NULL; -+#endif -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: " -+ "error, sa_state=%d must be MATURE=%d\n", -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state, -+ SADB_SASTATE_MATURE); -+ SENDERR(EINVAL); -+ } -+ -+ if(extr == NULL || extr->ips == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: " -+ "error, extr or extr->ips pointer NULL\n"); -+ SENDERR(EINVAL); -+ } -+ -+ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); -+ -+ spin_lock_bh(&tdb_lock); -+ -+ ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if (ipsq == NULL) { -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: " -+ "reserved ipsec_sa for SA: %s not found. Call SADB_GETSPI first or call SADB_ADD instead.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(ENOENT); -+ } -+ -+ if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == IS_MYADDR) { -+ extr->ips->ips_flags |= EMT_INBOUND; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: " -+ "existing ipsec_sa found (this is good) for SA: %s, %s-bound, updating.\n", -+ sa_len ? sa : " (error)", -+ extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if (extr->ips->ips_natt_sport || extr->ips->ips_natt_dport) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: only updating NAT-T ports " -+ "(%u:%u -> %u:%u)\n", -+ ipsq->ips_natt_sport, ipsq->ips_natt_dport, -+ extr->ips->ips_natt_sport, extr->ips->ips_natt_dport); -+ -+ if (extr->ips->ips_natt_sport) { -+ ipsq->ips_natt_sport = extr->ips->ips_natt_sport; -+ if (ipsq->ips_addr_s->sa_family == AF_INET) { -+ ((struct sockaddr_in *)(ipsq->ips_addr_s))->sin_port = htons(extr->ips->ips_natt_sport); -+ } -+ } -+ -+ if (extr->ips->ips_natt_dport) { -+ ipsq->ips_natt_dport = extr->ips->ips_natt_dport; -+ if (ipsq->ips_addr_d->sa_family == AF_INET) { -+ ((struct sockaddr_in *)(ipsq->ips_addr_d))->sin_port = htons(extr->ips->ips_natt_dport); -+ } -+ } -+ -+ nat_t_ips_saved = extr->ips; -+ extr->ips = ipsq; -+ } -+ else { -+#endif -+ -+ /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ -+ extr->ips->ips_rcvif = NULL; -+ if ((error = pfkey_ipsec_sa_init(extr->ips, extensions))) { -+ ipsec_sa_put(ipsq); -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: " -+ "not successful for SA: %s, deleting.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(-error); -+ } -+ -+ extr->ips->ips_life.ipl_addtime.ipl_count = ipsq->ips_life.ipl_addtime.ipl_count; -+ ipsec_sa_put(ipsq); -+ if((error = ipsec_sa_delchain(ipsq))) { -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: " -+ "error=%d, trouble deleting intermediate ipsec_sa for SA=%s.\n", -+ error, -+ sa_len ? sa : " (error)"); -+ SENDERR(-error); -+ } -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ } -+#endif -+ -+ spin_unlock_bh(&tdb_lock); -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_UPDATE, -+ satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ extr->ips->ips_replaywin, -+ extr->ips->ips_state, -+ extr->ips->ips_authalg, -+ extr->ips->ips_encalg, -+ extr->ips->ips_flags, -+ extr->ips->ips_ref), -+ extensions_reply) -+ /* The 3 lifetime extentions should only be sent if non-zero. */ -+ && (extensions[SADB_EXT_LIFETIME_HARD] -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD], -+ SADB_EXT_LIFETIME_HARD, -+ extr->ips->ips_life.ipl_allocations.ipl_hard, -+ extr->ips->ips_life.ipl_bytes.ipl_hard, -+ extr->ips->ips_life.ipl_addtime.ipl_hard, -+ extr->ips->ips_life.ipl_usetime.ipl_hard, -+ extr->ips->ips_life.ipl_packets.ipl_hard), -+ extensions_reply) : 1) -+ && (extensions[SADB_EXT_LIFETIME_SOFT] -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT], -+ SADB_EXT_LIFETIME_SOFT, -+ extr->ips->ips_life.ipl_allocations.ipl_count, -+ extr->ips->ips_life.ipl_bytes.ipl_count, -+ extr->ips->ips_life.ipl_addtime.ipl_count, -+ extr->ips->ips_life.ipl_usetime.ipl_count, -+ extr->ips->ips_life.ipl_packets.ipl_count), -+ extensions_reply) : 1) -+ && (extr->ips->ips_life.ipl_allocations.ipl_count -+ || extr->ips->ips_life.ipl_bytes.ipl_count -+ || extr->ips->ips_life.ipl_addtime.ipl_count -+ || extr->ips->ips_life.ipl_usetime.ipl_count -+ || extr->ips->ips_life.ipl_packets.ipl_count -+ -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_CURRENT], -+ SADB_EXT_LIFETIME_CURRENT, -+ extr->ips->ips_life.ipl_allocations.ipl_count, -+ extr->ips->ips_life.ipl_bytes.ipl_count, -+ extr->ips->ips_life.ipl_addtime.ipl_count, -+ extr->ips->ips_life.ipl_usetime.ipl_count, -+ extr->ips->ips_life.ipl_packets.ipl_count), -+ extensions_reply) : 1) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_s), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_d), -+ extensions_reply) -+ && (extr->ips->ips_ident_s.data -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC], -+ SADB_EXT_IDENTITY_SRC, -+ extr->ips->ips_ident_s.type, -+ extr->ips->ips_ident_s.id, -+ extr->ips->ips_ident_s.len, -+ extr->ips->ips_ident_s.data), -+ extensions_reply) : 1) -+ && (extr->ips->ips_ident_d.data -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST], -+ SADB_EXT_IDENTITY_DST, -+ extr->ips->ips_ident_d.type, -+ extr->ips->ips_ident_d.id, -+ extr->ips->ips_ident_d.len, -+ extr->ips->ips_ident_d.data), -+ extensions_reply) : 1) -+#if 0 -+ /* FIXME: This won't work yet because I have not finished -+ it. */ -+ && (extr->ips->ips_sens_ -+ ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY], -+ extr->ips->ips_sens_dpd, -+ extr->ips->ips_sens_sens_level, -+ extr->ips->ips_sens_sens_len, -+ extr->ips->ips_sens_sens_bitmap, -+ extr->ips->ips_sens_integ_level, -+ extr->ips->ips_sens_integ_len, -+ extr->ips->ips_sens_integ_bitmap), -+ extensions_reply) : 1) -+#endif -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " -+ "failed to build the update reply message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " -+ "failed to build the update reply message\n"); -+ SENDERR(-error); -+ } -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " -+ "sending up update reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " -+ "sending up update reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ if (nat_t_ips_saved) { -+ /** -+ * As we _really_ update existing SA, we keep tdbq and need to delete -+ * parsed ips (nat_t_ips_saved, was extr->ips). -+ * -+ * goto errlab with extr->ips = nat_t_ips_saved will free it. -+ */ -+ -+ extr->ips = nat_t_ips_saved; -+ -+ error = 0; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse (NAT-T ports): " -+ "successful for SA: %s\n", -+ sa_len ? sa : " (error)"); -+ -+ goto errlab; -+ } -+#endif -+ -+ if((error = ipsec_sa_add(extr->ips))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " -+ "failed to update the mature SA=%s with error=%d.\n", -+ sa_len ? sa : " (error)", -+ error); -+ SENDERR(-error); -+ } -+ extr->ips = NULL; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_update_parse: " -+ "successful for SA: %s\n", -+ sa_len ? sa : " (error)"); -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_add_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct ipsec_sa* ipsq; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_add_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_add_parse: " -+ "error, sa_state=%d must be MATURE=%d\n", -+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state, -+ SADB_SASTATE_MATURE); -+ SENDERR(EINVAL); -+ } -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_add_parse: " -+ "extr or extr->ips pointer NULL\n"); -+ SENDERR(EINVAL); -+ } -+ -+ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); -+ -+ ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if(ipsq != NULL) { -+ ipsec_sa_put(ipsq); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_add_parse: " -+ "found an old ipsec_sa for SA%s, delete it first.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(EEXIST); -+ } -+ -+ if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == IS_MYADDR) { -+ extr->ips->ips_flags |= EMT_INBOUND; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_add_parse: " -+ "existing ipsec_sa not found (this is good) for SA%s, %s-bound, allocating.\n", -+ sa_len ? sa : " (error)", -+ extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); -+ -+ /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ -+ extr->ips->ips_rcvif = NULL; -+ -+ if ((error = pfkey_ipsec_sa_init(extr->ips, extensions))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_add_parse: " -+ "not successful for SA: %s, deleting.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(-error); -+ } -+ -+ extr->ips->ips_life.ipl_addtime.ipl_count = jiffies / HZ; -+ if(!extr->ips->ips_life.ipl_allocations.ipl_count) { -+ extr->ips->ips_life.ipl_allocations.ipl_count += 1; -+ } -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_ADD, -+ satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ extr->ips->ips_replaywin, -+ extr->ips->ips_state, -+ extr->ips->ips_authalg, -+ extr->ips->ips_encalg, -+ extr->ips->ips_flags, -+ extr->ips->ips_ref), -+ extensions_reply) -+ /* The 3 lifetime extentions should only be sent if non-zero. */ -+ && (extensions[SADB_EXT_LIFETIME_HARD] -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD], -+ SADB_EXT_LIFETIME_HARD, -+ extr->ips->ips_life.ipl_allocations.ipl_hard, -+ extr->ips->ips_life.ipl_bytes.ipl_hard, -+ extr->ips->ips_life.ipl_addtime.ipl_hard, -+ extr->ips->ips_life.ipl_usetime.ipl_hard, -+ extr->ips->ips_life.ipl_packets.ipl_hard), -+ extensions_reply) : 1) -+ && (extensions[SADB_EXT_LIFETIME_SOFT] -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT], -+ SADB_EXT_LIFETIME_SOFT, -+ extr->ips->ips_life.ipl_allocations.ipl_soft, -+ extr->ips->ips_life.ipl_bytes.ipl_soft, -+ extr->ips->ips_life.ipl_addtime.ipl_soft, -+ extr->ips->ips_life.ipl_usetime.ipl_soft, -+ extr->ips->ips_life.ipl_packets.ipl_soft), -+ extensions_reply) : 1) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_s), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_d), -+ extensions_reply) -+ && (extr->ips->ips_ident_s.data -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC], -+ SADB_EXT_IDENTITY_SRC, -+ extr->ips->ips_ident_s.type, -+ extr->ips->ips_ident_s.id, -+ extr->ips->ips_ident_s.len, -+ extr->ips->ips_ident_s.data), -+ extensions_reply) : 1) -+ && (extr->ips->ips_ident_d.data -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST], -+ SADB_EXT_IDENTITY_DST, -+ extr->ips->ips_ident_d.type, -+ extr->ips->ips_ident_d.id, -+ extr->ips->ips_ident_d.len, -+ extr->ips->ips_ident_d.data), -+ extensions_reply) : 1) -+#if 0 -+ /* FIXME: This won't work yet because I have not finished -+ it. */ -+ && (extr->ips->ips_sens_ -+ ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY], -+ extr->ips->ips_sens_dpd, -+ extr->ips->ips_sens_sens_level, -+ extr->ips->ips_sens_sens_len, -+ extr->ips->ips_sens_sens_bitmap, -+ extr->ips->ips_sens_integ_level, -+ extr->ips->ips_sens_integ_len, -+ extr->ips->ips_sens_integ_bitmap), -+ extensions_reply) : 1) -+#endif -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " -+ "failed to build the add reply message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " -+ "failed to build the add reply message\n"); -+ SENDERR(-error); -+ } -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " -+ "sending up add reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " -+ "sending up add reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ if((error = ipsec_sa_add(extr->ips))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " -+ "failed to add the mature SA=%s with error=%d.\n", -+ sa_len ? sa : " (error)", -+ error); -+ SENDERR(-error); -+ } -+ extr->ips = NULL; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_add_parse: " -+ "successful for SA: %s\n", -+ sa_len ? sa : " (error)"); -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_delete_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ struct ipsec_sa *ipsp; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ int error = 0; -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_delete_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_delete_parse: " -+ "extr or extr->ips pointer NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); -+ -+ spin_lock_bh(&tdb_lock); -+ -+ ipsp = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if (ipsp == NULL) { -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_delete_parse: " -+ "ipsec_sa not found for SA:%s, could not delete.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(ESRCH); -+ } -+ -+ ipsec_sa_put(ipsp); -+ if((error = ipsec_sa_delchain(ipsp))) { -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_delete_parse: " -+ "error=%d returned trying to delete ipsec_sa for SA:%s.\n", -+ error, -+ sa_len ? sa : " (error)"); -+ SENDERR(-error); -+ } -+ spin_unlock_bh(&tdb_lock); -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_DELETE, -+ satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ 0, -+ 0, -+ 0, -+ 0, -+ 0, -+ extr->ips->ips_ref), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_s), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_d), -+ extensions_reply) -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " -+ "failed to build the delete reply message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " -+ "failed to build the delete reply message\n"); -+ SENDERR(-error); -+ } -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " -+ "sending up delete reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " -+ "sending up delete reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_get_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct ipsec_sa *ipsp; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_get_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ if(!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_get_parse: " -+ "extr or extr->ips pointer NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); -+ -+ spin_lock_bh(&tdb_lock); -+ -+ ipsp = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if (ipsp == NULL) { -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " -+ "ipsec_sa not found for SA=%s, could not get.\n", -+ sa_len ? sa : " (error)"); -+ SENDERR(ESRCH); -+ } -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_GET, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ extr->ips->ips_replaywin, -+ extr->ips->ips_state, -+ extr->ips->ips_authalg, -+ extr->ips->ips_encalg, -+ extr->ips->ips_flags, -+ extr->ips->ips_ref), -+ extensions_reply) -+ /* The 3 lifetime extentions should only be sent if non-zero. */ -+ && (ipsp->ips_life.ipl_allocations.ipl_count -+ || ipsp->ips_life.ipl_bytes.ipl_count -+ || ipsp->ips_life.ipl_addtime.ipl_count -+ || ipsp->ips_life.ipl_usetime.ipl_count -+ || ipsp->ips_life.ipl_packets.ipl_count -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_CURRENT], -+ SADB_EXT_LIFETIME_CURRENT, -+ ipsp->ips_life.ipl_allocations.ipl_count, -+ ipsp->ips_life.ipl_bytes.ipl_count, -+ ipsp->ips_life.ipl_addtime.ipl_count, -+ ipsp->ips_life.ipl_usetime.ipl_count, -+ ipsp->ips_life.ipl_packets.ipl_count), -+ extensions_reply) : 1) -+ && (ipsp->ips_life.ipl_allocations.ipl_hard -+ || ipsp->ips_life.ipl_bytes.ipl_hard -+ || ipsp->ips_life.ipl_addtime.ipl_hard -+ || ipsp->ips_life.ipl_usetime.ipl_hard -+ || ipsp->ips_life.ipl_packets.ipl_hard -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD], -+ SADB_EXT_LIFETIME_HARD, -+ ipsp->ips_life.ipl_allocations.ipl_hard, -+ ipsp->ips_life.ipl_bytes.ipl_hard, -+ ipsp->ips_life.ipl_addtime.ipl_hard, -+ ipsp->ips_life.ipl_usetime.ipl_hard, -+ ipsp->ips_life.ipl_packets.ipl_hard), -+ extensions_reply) : 1) -+ && (ipsp->ips_life.ipl_allocations.ipl_soft -+ || ipsp->ips_life.ipl_bytes.ipl_soft -+ || ipsp->ips_life.ipl_addtime.ipl_soft -+ || ipsp->ips_life.ipl_usetime.ipl_soft -+ || ipsp->ips_life.ipl_packets.ipl_soft -+ ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT], -+ SADB_EXT_LIFETIME_SOFT, -+ ipsp->ips_life.ipl_allocations.ipl_soft, -+ ipsp->ips_life.ipl_bytes.ipl_soft, -+ ipsp->ips_life.ipl_addtime.ipl_soft, -+ ipsp->ips_life.ipl_usetime.ipl_soft, -+ ipsp->ips_life.ipl_packets.ipl_soft), -+ extensions_reply) : 1) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_s), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_d), -+ extensions_reply) -+ && (extr->ips->ips_addr_p -+ ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_PROXY], -+ SADB_EXT_ADDRESS_PROXY, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_p), -+ extensions_reply) : 1) -+#if 0 -+ /* FIXME: This won't work yet because the keys are not -+ stored directly in the ipsec_sa. They are stored as -+ contexts. */ -+ && (extr->ips->ips_key_a_size -+ ? pfkey_safe_build(error = pfkey_key_build(&extensions_reply[SADB_EXT_KEY_AUTH], -+ SADB_EXT_KEY_AUTH, -+ extr->ips->ips_key_a_size * 8, -+ extr->ips->ips_key_a), -+ extensions_reply) : 1) -+ /* FIXME: This won't work yet because the keys are not -+ stored directly in the ipsec_sa. They are stored as -+ key schedules. */ -+ && (extr->ips->ips_key_e_size -+ ? pfkey_safe_build(error = pfkey_key_build(&extensions_reply[SADB_EXT_KEY_ENCRYPT], -+ SADB_EXT_KEY_ENCRYPT, -+ extr->ips->ips_key_e_size * 8, -+ extr->ips->ips_key_e), -+ extensions_reply) : 1) -+#endif -+ && (extr->ips->ips_ident_s.data -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC], -+ SADB_EXT_IDENTITY_SRC, -+ extr->ips->ips_ident_s.type, -+ extr->ips->ips_ident_s.id, -+ extr->ips->ips_ident_s.len, -+ extr->ips->ips_ident_s.data), -+ extensions_reply) : 1) -+ && (extr->ips->ips_ident_d.data -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST], -+ SADB_EXT_IDENTITY_DST, -+ extr->ips->ips_ident_d.type, -+ extr->ips->ips_ident_d.id, -+ extr->ips->ips_ident_d.len, -+ extr->ips->ips_ident_d.data), -+ extensions_reply) : 1) -+#if 0 -+ /* FIXME: This won't work yet because I have not finished -+ it. */ -+ && (extr->ips->ips_sens_ -+ ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY], -+ extr->ips->ips_sens_dpd, -+ extr->ips->ips_sens_sens_level, -+ extr->ips->ips_sens_sens_len, -+ extr->ips->ips_sens_sens_bitmap, -+ extr->ips->ips_sens_integ_level, -+ extr->ips->ips_sens_integ_len, -+ extr->ips->ips_sens_integ_bitmap), -+ extensions_reply) : 1) -+#endif -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " -+ "failed to build the get reply message extensions\n"); -+ ipsec_sa_put(ipsp); -+ spin_unlock_bh(&tdb_lock); -+ SENDERR(-error); -+ } -+ -+ ipsec_sa_put(ipsp); -+ spin_unlock_bh(&tdb_lock); -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " -+ "failed to build the get reply message\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_upmsg(sk->socket, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " -+ "failed to send the get reply message\n"); -+ SENDERR(-error); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " -+ "succeeded in sending get reply message.\n"); -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_acquire_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_acquire_parse: .\n"); -+ -+ /* XXX I don't know if we want an upper bound, since userspace may -+ want to register itself for an satype > SADB_SATYPE_MAX. */ -+ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_acquire_parse: " -+ "SATYPE=%d invalid.\n", -+ satype); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(pfkey_registered_sockets[satype])) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " -+ "no sockets registered for SAtype=%d(%s).\n", -+ satype, -+ satype2name(satype)); -+ SENDERR(EPROTONOSUPPORT); -+ } -+ -+ for(pfkey_socketsp = pfkey_registered_sockets[satype]; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " -+ "sending up acquire reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " -+ "sending up acquire reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_register_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_parse: .\n"); -+ -+ /* XXX I don't know if we want an upper bound, since userspace may -+ want to register itself for an satype > SADB_SATYPE_MAX. */ -+ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_parse: " -+ "SATYPE=%d invalid.\n", -+ satype); -+ SENDERR(EINVAL); -+ } -+ -+ if(!pfkey_list_insert_socket(sk->socket, -+ &(pfkey_registered_sockets[satype]))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_parse: " -+ "SATYPE=%02d(%s) successfully registered by KMd (pid=%d).\n", -+ satype, -+ satype2name(satype), -+ key_pid(sk)); -+ }; -+ -+ /* send up register msg with supported SATYPE algos */ -+ -+ error=pfkey_register_reply(satype, (struct sadb_msg*)extensions[SADB_EXT_RESERVED]); -+ errlab: -+ return error; -+} -+ -+int -+pfkey_register_reply(int satype, struct sadb_msg *sadb_msg) -+{ -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ struct supported_list *pfkey_supported_listp; -+ unsigned int alg_num_a = 0, alg_num_e = 0; -+ struct sadb_alg *alg_a = NULL, *alg_e = NULL, *alg_ap = NULL, *alg_ep = NULL; -+ int error = 0; -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " -+ "SAtype=%d unspecified or unknown.\n", -+ satype); -+ SENDERR(EINVAL); -+ } -+ if(!(pfkey_registered_sockets[satype])) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " -+ "no sockets registered for SAtype=%d(%s).\n", -+ satype, -+ satype2name(satype)); -+ SENDERR(EPROTONOSUPPORT); -+ } -+ /* send up register msg with supported SATYPE algos */ -+ pfkey_supported_listp = pfkey_supported_list[satype]; -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "pfkey_supported_list[%d]=0p%p\n", -+ satype, -+ pfkey_supported_list[satype]); -+ while(pfkey_supported_listp) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "checking supported=0p%p\n", -+ pfkey_supported_listp); -+ if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_AUTH) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "adding auth alg.\n"); -+ alg_num_a++; -+ } -+ if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_ENCRYPT) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "adding encrypt alg.\n"); -+ alg_num_e++; -+ } -+ pfkey_supported_listp = pfkey_supported_listp->next; -+ } -+ -+ if(alg_num_a) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "allocating %lu bytes for auth algs.\n", -+ (unsigned long) (alg_num_a * sizeof(struct sadb_alg))); -+ if((alg_a = kmalloc(alg_num_a * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "auth alg memory allocation error\n"); -+ SENDERR(ENOMEM); -+ } -+ alg_ap = alg_a; -+ } -+ -+ if(alg_num_e) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "allocating %lu bytes for enc algs.\n", -+ (unsigned long) (alg_num_e * sizeof(struct sadb_alg))); -+ if((alg_e = kmalloc(alg_num_e * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "enc alg memory allocation error\n"); -+ SENDERR(ENOMEM); -+ } -+ alg_ep = alg_e; -+ } -+ -+ pfkey_supported_listp = pfkey_supported_list[satype]; -+ while(pfkey_supported_listp) { -+ if(alg_num_a) { -+ if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_AUTH) { -+ alg_ap->sadb_alg_id = pfkey_supported_listp->supportedp->supported_alg_id; -+ alg_ap->sadb_alg_ivlen = pfkey_supported_listp->supportedp->supported_alg_ivlen; -+ alg_ap->sadb_alg_minbits = pfkey_supported_listp->supportedp->supported_alg_minbits; -+ alg_ap->sadb_alg_maxbits = pfkey_supported_listp->supportedp->supported_alg_maxbits; -+ alg_ap->sadb_alg_reserved = 0; -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_register_reply: " -+ "adding auth=0p%p\n", -+ alg_ap); -+ alg_ap++; -+ } -+ } -+ if(alg_num_e) { -+ if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_ENCRYPT) { -+ alg_ep->sadb_alg_id = pfkey_supported_listp->supportedp->supported_alg_id; -+ alg_ep->sadb_alg_ivlen = pfkey_supported_listp->supportedp->supported_alg_ivlen; -+ alg_ep->sadb_alg_minbits = pfkey_supported_listp->supportedp->supported_alg_minbits; -+ alg_ep->sadb_alg_maxbits = pfkey_supported_listp->supportedp->supported_alg_maxbits; -+ alg_ep->sadb_alg_reserved = 0; -+ KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, -+ "klips_debug:pfkey_register_reply: " -+ "adding encrypt=0p%p\n", -+ alg_ep); -+ alg_ep++; -+ } -+ } -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_register_reply: " -+ "found satype=%d(%s) exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_supported_listp->supportedp->supported_alg_exttype, -+ pfkey_supported_listp->supportedp->supported_alg_id, -+ pfkey_supported_listp->supportedp->supported_alg_ivlen, -+ pfkey_supported_listp->supportedp->supported_alg_minbits, -+ pfkey_supported_listp->supportedp->supported_alg_maxbits); -+ pfkey_supported_listp = pfkey_supported_listp->next; -+ } -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_REGISTER, -+ satype, -+ 0, -+ sadb_msg? sadb_msg->sadb_msg_seq : ++pfkey_msg_seq, -+ sadb_msg? sadb_msg->sadb_msg_pid: current->pid), -+ extensions_reply) && -+ (alg_num_a ? pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[SADB_EXT_SUPPORTED_AUTH], -+ SADB_EXT_SUPPORTED_AUTH, -+ alg_num_a, -+ alg_a), -+ extensions_reply) : 1) && -+ (alg_num_e ? pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[SADB_EXT_SUPPORTED_ENCRYPT], -+ SADB_EXT_SUPPORTED_ENCRYPT, -+ alg_num_e, -+ alg_e), -+ extensions_reply) : 1))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " -+ "failed to build the register message extensions_reply\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " -+ "failed to build the register message\n"); -+ SENDERR(-error); -+ } -+ /* this should go to all registered sockets for that satype only */ -+ for(pfkey_socketsp = pfkey_registered_sockets[satype]; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " -+ "sending up acquire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " -+ "sending up register message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ errlab: -+ if(alg_a) { -+ kfree(alg_a); -+ } -+ if(alg_e) { -+ kfree(alg_e); -+ } -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_expire_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct socket_list *pfkey_socketsp; -+#ifdef CONFIG_IPSEC_DEBUG -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_expire_parse: .\n"); -+ -+ if(pfkey_open_sockets) { -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: " -+ "sending up expire reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: " -+ "sending up expire reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ } -+ -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_flush_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ uint8_t proto = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_flush_parse: " -+ "flushing type %d SAs\n", -+ satype); -+ -+ if(satype && !(proto = satype2proto(satype))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_flush_parse: " -+ "satype %d lookup failed.\n", -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype); -+ SENDERR(EINVAL); -+ } -+ -+ if ((error = ipsec_sadb_cleanup(proto))) { -+ SENDERR(-error); -+ } -+ -+ if(pfkey_open_sockets) { -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: " -+ "sending up flush reply message for satype=%d(%s) (proto=%d) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ proto, -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: " -+ "sending up flush reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ } -+ -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_dump_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_dump_parse: .\n"); -+ -+ SENDERR(ENOSYS); -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_promisc_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_promisc_parse: .\n"); -+ -+ SENDERR(ENOSYS); -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_pchange_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_pchange_parse: .\n"); -+ -+ SENDERR(ENOSYS); -+ errlab: -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_grpsa_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ struct ipsec_sa *ips1p, *ips2p, *ipsp; -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ char sa1[SATOT_BUF], sa2[SATOT_BUF]; -+ size_t sa_len1, sa_len2 = 0; -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ if(extr == NULL || extr->ips == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "extr or extr->ips is NULL, fatal.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ sa_len1 = satot(&extr->ips->ips_said, 0, sa1, sizeof(sa1)); -+ if(extr->ips2 != NULL) { -+ sa_len2 = satot(&extr->ips2->ips_said, 0, sa2, sizeof(sa2)); -+ } -+ -+ spin_lock_bh(&tdb_lock); -+ -+ ips1p = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if(ips1p == NULL) { -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "reserved ipsec_sa for SA1: %s not found. Call SADB_ADD/UPDATE first.\n", -+ sa_len1 ? sa1 : " (error)"); -+ SENDERR(ENOENT); -+ } -+ if(extr->ips2) { /* GRPSA */ -+ ips2p = ipsec_sa_getbyid(&(extr->ips2->ips_said)); -+ if(ips2p == NULL) { -+ ipsec_sa_put(ips1p); -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "reserved ipsec_sa for SA2: %s not found. Call SADB_ADD/UPDATE first.\n", -+ sa_len2 ? sa2 : " (error)"); -+ SENDERR(ENOENT); -+ } -+ -+ /* Is either one already linked? */ -+ if(ips1p->ips_onext) { -+ ipsec_sa_put(ips1p); -+ ipsec_sa_put(ips2p); -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "ipsec_sa for SA: %s is already linked.\n", -+ sa_len1 ? sa1 : " (error)"); -+ SENDERR(EEXIST); -+ } -+ if(ips2p->ips_inext) { -+ ipsec_sa_put(ips1p); -+ ipsec_sa_put(ips2p); -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "ipsec_sa for SA: %s is already linked.\n", -+ sa_len2 ? sa2 : " (error)"); -+ SENDERR(EEXIST); -+ } -+ -+ /* Is extr->ips already linked to extr->ips2? */ -+ ipsp = ips2p; -+ while(ipsp) { -+ if(ipsp == ips1p) { -+ ipsec_sa_put(ips1p); -+ ipsec_sa_put(ips2p); -+ spin_unlock_bh(&tdb_lock); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "ipsec_sa for SA: %s is already linked to %s.\n", -+ sa_len1 ? sa1 : " (error)", -+ sa_len2 ? sa2 : " (error)"); -+ SENDERR(EEXIST); -+ } -+ ipsp = ipsp->ips_onext; -+ } -+ -+ /* link 'em */ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "linking ipsec_sa SA: %s with %s.\n", -+ sa_len1 ? sa1 : " (error)", -+ sa_len2 ? sa2 : " (error)"); -+ ips1p->ips_onext = ips2p; -+ ips2p->ips_inext = ips1p; -+ } else { /* UNGRPSA */ -+ ipsec_sa_put(ips1p); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_grpsa_parse: " -+ "unlinking ipsec_sa SA: %s.\n", -+ sa_len1 ? sa1 : " (error)"); -+ while(ips1p->ips_onext) { -+ ips1p = ips1p->ips_onext; -+ } -+ while(ips1p->ips_inext) { -+ ipsp = ips1p; -+ ips1p = ips1p->ips_inext; -+ ipsec_sa_put(ips1p); -+ ipsp->ips_inext = NULL; -+ ipsec_sa_put(ipsp); -+ ips1p->ips_onext = NULL; -+ } -+ } -+ -+ spin_unlock_bh(&tdb_lock); -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_X_GRPSA, -+ satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ extr->ips->ips_replaywin, -+ extr->ips->ips_state, -+ extr->ips->ips_authalg, -+ extr->ips->ips_encalg, -+ extr->ips->ips_flags, -+ extr->ips->ips_ref), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_d), -+ extensions_reply) -+ && (extr->ips2 -+ ? (pfkey_safe_build(error = pfkey_x_satype_build(&extensions_reply[SADB_X_EXT_SATYPE2], -+ ((struct sadb_x_satype*)extensions[SADB_X_EXT_SATYPE2])->sadb_x_satype_satype -+ /* proto2satype(extr->ips2->ips_said.proto) */), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_X_EXT_SA2], -+ SADB_X_EXT_SA2, -+ extr->ips2->ips_said.spi, -+ extr->ips2->ips_replaywin, -+ extr->ips2->ips_state, -+ extr->ips2->ips_authalg, -+ extr->ips2->ips_encalg, -+ extr->ips2->ips_flags, -+ extr->ips2->ips_ref), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST2], -+ SADB_X_EXT_ADDRESS_DST2, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips2->ips_addr_d), -+ extensions_reply) ) : 1 ) -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " -+ "failed to build the x_grpsa reply message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " -+ "failed to build the x_grpsa reply message\n"); -+ SENDERR(-error); -+ } -+ -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " -+ "sending up x_grpsa reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " -+ "sending up x_grpsa reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " -+ "succeeded in sending x_grpsa reply message.\n"); -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_addflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+#ifdef CONFIG_IPSEC_DEBUG -+ char buf1[64], buf2[64]; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ ip_address srcflow, dstflow, srcmask, dstmask; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ memset((caddr_t)&srcflow, 0, sizeof(srcflow)); -+ memset((caddr_t)&dstflow, 0, sizeof(dstflow)); -+ memset((caddr_t)&srcmask, 0, sizeof(srcmask)); -+ memset((caddr_t)&dstmask, 0, sizeof(dstmask)); -+ -+ if(!extr || !(extr->ips) || !(extr->eroute)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "missing extr, ipsec_sa or eroute data.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ srcflow.u.v4.sin_family = AF_INET; -+ dstflow.u.v4.sin_family = AF_INET; -+ srcmask.u.v4.sin_family = AF_INET; -+ dstmask.u.v4.sin_family = AF_INET; -+ srcflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_src; -+ dstflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_dst; -+ srcmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_src; -+ dstmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_dst; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_pfkey) { -+ subnettoa(extr->eroute->er_eaddr.sen_ip_src, -+ extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(extr->eroute->er_eaddr.sen_ip_dst, -+ extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "calling breakeroute and/or makeroute for %s->%s\n", -+ buf1, buf2); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ if(extr->ips->ips_flags & SADB_X_SAFLAGS_INFLOW) { -+/* if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == IS_MYADDR) */ -+ struct ipsec_sa *ipsp, *ipsq; -+ char sa[SATOT_BUF]; -+ size_t sa_len; -+ -+ ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); -+ if(ipsq == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "ipsec_sa not found, cannot set incoming policy.\n"); -+ SENDERR(ENOENT); -+ } -+ -+ ipsp = ipsq; -+ while(ipsp && ipsp->ips_said.proto != IPPROTO_IPIP) { -+ ipsp = ipsp->ips_inext; -+ } -+ -+ if(ipsp == NULL) { -+ ipsec_sa_put(ipsq); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "SA chain does not have an IPIP SA, cannot set incoming policy.\n"); -+ SENDERR(ENOENT); -+ } -+ -+ sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); -+ -+ ipsp->ips_flags |= SADB_X_SAFLAGS_INFLOW; -+ ipsp->ips_flow_s = srcflow; -+ ipsp->ips_flow_d = dstflow; -+ ipsp->ips_mask_s = srcmask; -+ ipsp->ips_mask_d = dstmask; -+ -+ ipsec_sa_put(ipsq); -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "inbound eroute, setting incoming policy information in IPIP ipsec_sa for SA: %s.\n", -+ sa_len ? sa : " (error)"); -+ } else { -+ struct sk_buff *first = NULL, *last = NULL; -+ -+ if(extr->ips->ips_flags & SADB_X_SAFLAGS_REPLACEFLOW) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "REPLACEFLOW flag set, calling breakeroute.\n"); -+ if ((error = ipsec_breakroute(&(extr->eroute->er_eaddr), -+ &(extr->eroute->er_emask), -+ &first, &last))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "breakeroute returned %d. first=0p%p, last=0p%p\n", -+ error, -+ first, -+ last); -+ if(first != NULL) { -+ ipsec_kfree_skb(first); -+ } -+ if(last != NULL) { -+ ipsec_kfree_skb(last); -+ } -+ SENDERR(-error); -+ } -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "calling makeroute.\n"); -+ -+ if ((error = ipsec_makeroute(&(extr->eroute->er_eaddr), -+ &(extr->eroute->er_emask), -+ extr->ips->ips_said, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid, -+ NULL, -+ &(extr->ips->ips_ident_s), -+ &(extr->ips->ips_ident_d)))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "makeroute returned %d.\n", error); -+ SENDERR(-error); -+ } -+ if(first != NULL) { -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "first=0p%p HOLD packet re-injected.\n", -+ first); -+ DEV_QUEUE_XMIT(first, first->dev, SOPRI_NORMAL); -+ } -+ if(last != NULL) { -+ KLIPS_PRINT(debug_eroute, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "last=0p%p HOLD packet re-injected.\n", -+ last); -+ DEV_QUEUE_XMIT(last, last->dev, SOPRI_NORMAL); -+ } -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "makeroute call successful.\n"); -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_X_ADDFLOW, -+ satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ extr->ips->ips_replaywin, -+ extr->ips->ips_state, -+ extr->ips->ips_authalg, -+ extr->ips->ips_encalg, -+ extr->ips->ips_flags, -+ extr->ips->ips_ref), -+ extensions_reply) -+ && (extensions[SADB_EXT_ADDRESS_SRC] -+ ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_s), -+ extensions_reply) : 1) -+ && (extensions[SADB_EXT_ADDRESS_DST] -+ ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ extr->ips->ips_addr_d), -+ extensions_reply) : 1) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_FLOW], -+ SADB_X_EXT_ADDRESS_SRC_FLOW, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&srcflow), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_FLOW], -+ SADB_X_EXT_ADDRESS_DST_FLOW, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&dstflow), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_MASK], -+ SADB_X_EXT_ADDRESS_SRC_MASK, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&srcmask), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_MASK], -+ SADB_X_EXT_ADDRESS_DST_MASK, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&dstmask), -+ extensions_reply) -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " -+ "failed to build the x_addflow reply message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " -+ "failed to build the x_addflow reply message\n"); -+ SENDERR(-error); -+ } -+ -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " -+ "sending up x_addflow reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " -+ "sending up x_addflow reply message for satype=%d(%s) (proto=%d) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ extr->ips->ips_said.proto, -+ pfkey_socketsp->socketp); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_addflow_parse: " -+ "extr->ips cleaned up and freed.\n"); -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_delflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+#ifdef CONFIG_IPSEC_DEBUG -+ char buf1[64], buf2[64]; -+#endif /* CONFIG_IPSEC_DEBUG */ -+ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_reply = NULL; -+ struct socket_list *pfkey_socketsp; -+ uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; -+ ip_address srcflow, dstflow, srcmask, dstmask; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: .\n"); -+ -+ pfkey_extensions_init(extensions_reply); -+ -+ memset((caddr_t)&srcflow, 0, sizeof(srcflow)); -+ memset((caddr_t)&dstflow, 0, sizeof(dstflow)); -+ memset((caddr_t)&srcmask, 0, sizeof(srcmask)); -+ memset((caddr_t)&dstmask, 0, sizeof(dstmask)); -+ -+ if(!extr || !(extr->ips)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: " -+ "extr, or extr->ips is NULL, fatal\n"); -+ SENDERR(EINVAL); -+ } -+ -+ if(extr->ips->ips_flags & SADB_X_SAFLAGS_CLEARFLOW) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: " -+ "CLEARFLOW flag set, calling cleareroutes.\n"); -+ if ((error = ipsec_cleareroutes())) -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: " -+ "cleareroutes returned %d.\n", error); -+ SENDERR(-error); -+ } else { -+ struct sk_buff *first = NULL, *last = NULL; -+ -+ if(!(extr->eroute)) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: " -+ "extr->eroute is NULL, fatal.\n"); -+ SENDERR(EINVAL); -+ } -+ -+ srcflow.u.v4.sin_family = AF_INET; -+ dstflow.u.v4.sin_family = AF_INET; -+ srcmask.u.v4.sin_family = AF_INET; -+ dstmask.u.v4.sin_family = AF_INET; -+ srcflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_src; -+ dstflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_dst; -+ srcmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_src; -+ dstmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_dst; -+ -+#ifdef CONFIG_IPSEC_DEBUG -+ if (debug_pfkey) { -+ subnettoa(extr->eroute->er_eaddr.sen_ip_src, -+ extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); -+ subnettoa(extr->eroute->er_eaddr.sen_ip_dst, -+ extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: " -+ "calling breakeroute for %s->%s\n", -+ buf1, buf2); -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ error = ipsec_breakroute(&(extr->eroute->er_eaddr), -+ &(extr->eroute->er_emask), -+ &first, &last); -+ if(error) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: " -+ "breakeroute returned %d. first=0p%p, last=0p%p\n", -+ error, -+ first, -+ last); -+ } -+ if(first != NULL) { -+ ipsec_kfree_skb(first); -+ } -+ if(last != NULL) { -+ ipsec_kfree_skb(last); -+ } -+ if(error) { -+ SENDERR(-error); -+ } -+ } -+ -+ if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], -+ SADB_X_DELFLOW, -+ satype, -+ 0, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, -+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ extr->ips->ips_replaywin, -+ extr->ips->ips_state, -+ extr->ips->ips_authalg, -+ extr->ips->ips_encalg, -+ extr->ips->ips_flags, -+ extr->ips->ips_ref), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_FLOW], -+ SADB_X_EXT_ADDRESS_SRC_FLOW, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&srcflow), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_FLOW], -+ SADB_X_EXT_ADDRESS_DST_FLOW, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&dstflow), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_MASK], -+ SADB_X_EXT_ADDRESS_SRC_MASK, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&srcmask), -+ extensions_reply) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_MASK], -+ SADB_X_EXT_ADDRESS_DST_MASK, -+ 0, /*extr->ips->ips_said.proto,*/ -+ 0, -+ (struct sockaddr*)&dstmask), -+ extensions_reply) -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " -+ "failed to build the x_delflow reply message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " -+ "failed to build the x_delflow reply message\n"); -+ SENDERR(-error); -+ } -+ -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " -+ "sending up x_delflow reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " -+ "sending up x_delflow reply message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_delflow_parse: " -+ "extr->ips cleaned up and freed.\n"); -+ -+ errlab: -+ if (pfkey_reply) { -+ pfkey_msg_free(&pfkey_reply); -+ } -+ pfkey_extensions_free(extensions_reply); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_msg_debug_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ int error = 0; -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_x_msg_debug_parse: .\n"); -+ -+/* errlab:*/ -+ return error; -+} -+ -+/* pfkey_expire expects the ipsec_sa table to be locked before being called. */ -+int -+pfkey_expire(struct ipsec_sa *ipsp, int hard) -+{ -+ struct sadb_ext *extensions[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_msg = NULL; -+ struct socket_list *pfkey_socketsp; -+ int error = 0; -+ uint8_t satype; -+ -+ pfkey_extensions_init(extensions); -+ -+ if(!(satype = proto2satype(ipsp->ips_said.proto))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_expire: " -+ "satype lookup for protocol %d lookup failed.\n", -+ ipsp->ips_said.proto); -+ SENDERR(EINVAL); -+ } -+ -+ if(!pfkey_open_sockets) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " -+ "no sockets listening.\n"); -+ SENDERR(EPROTONOSUPPORT); -+ } -+ -+ if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions[0], -+ SADB_EXPIRE, -+ satype, -+ 0, -+ ++pfkey_msg_seq, -+ 0), -+ extensions) -+ && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions[SADB_EXT_SA], -+ SADB_EXT_SA, -+ ipsp->ips_said.spi, -+ ipsp->ips_replaywin, -+ ipsp->ips_state, -+ ipsp->ips_authalg, -+ ipsp->ips_encalg, -+ ipsp->ips_flags, -+ ipsp->ips_ref), -+ extensions) -+ && pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_CURRENT], -+ SADB_EXT_LIFETIME_CURRENT, -+ ipsp->ips_life.ipl_allocations.ipl_count, -+ ipsp->ips_life.ipl_bytes.ipl_count, -+ ipsp->ips_life.ipl_addtime.ipl_count, -+ ipsp->ips_life.ipl_usetime.ipl_count, -+ ipsp->ips_life.ipl_packets.ipl_count), -+ extensions) -+ && (hard ? -+ pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_HARD], -+ SADB_EXT_LIFETIME_HARD, -+ ipsp->ips_life.ipl_allocations.ipl_hard, -+ ipsp->ips_life.ipl_bytes.ipl_hard, -+ ipsp->ips_life.ipl_addtime.ipl_hard, -+ ipsp->ips_life.ipl_usetime.ipl_hard, -+ ipsp->ips_life.ipl_packets.ipl_hard), -+ extensions) -+ : pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_SOFT], -+ SADB_EXT_LIFETIME_SOFT, -+ ipsp->ips_life.ipl_allocations.ipl_soft, -+ ipsp->ips_life.ipl_bytes.ipl_soft, -+ ipsp->ips_life.ipl_addtime.ipl_soft, -+ ipsp->ips_life.ipl_usetime.ipl_soft, -+ ipsp->ips_life.ipl_packets.ipl_soft), -+ extensions)) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ 0, /* ipsp->ips_said.proto, */ -+ 0, -+ ipsp->ips_addr_s), -+ extensions) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ 0, /* ipsp->ips_said.proto, */ -+ 0, -+ ipsp->ips_addr_d), -+ extensions))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " -+ "failed to build the expire message extensions\n"); -+ spin_unlock(&tdb_lock); -+ goto errlab; -+ } -+ -+ if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " -+ "failed to build the expire message\n"); -+ SENDERR(-error); -+ } -+ -+ for(pfkey_socketsp = pfkey_open_sockets; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " -+ "sending up expire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " -+ "sending up expire message for satype=%d(%s) (proto=%d) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ ipsp->ips_said.proto, -+ pfkey_socketsp->socketp); -+ } -+ -+ errlab: -+ if (pfkey_msg) { -+ pfkey_msg_free(&pfkey_msg); -+ } -+ pfkey_extensions_free(extensions); -+ return error; -+} -+ -+int -+pfkey_acquire(struct ipsec_sa *ipsp) -+{ -+ struct sadb_ext *extensions[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_msg = NULL; -+ struct socket_list *pfkey_socketsp; -+ int error = 0; -+ struct sadb_comb comb[] = { -+ /* auth; encrypt; flags; */ -+ /* auth_minbits; auth_maxbits; encrypt_minbits; encrypt_maxbits; */ -+ /* reserved; soft_allocations; hard_allocations; soft_bytes; hard_bytes; */ -+ /* soft_addtime; hard_addtime; soft_usetime; hard_usetime; */ -+ /* soft_packets; hard_packets; */ -+ { SADB_AALG_MD5HMAC, SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS, -+ 128, 128, 168, 168, -+ 0, 0, 0, 0, 0, -+ 57600, 86400, 57600, 86400, -+ 0, 0 }, -+ { SADB_AALG_SHA1HMAC, SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS, -+ 160, 160, 168, 168, -+ 0, 0, 0, 0, 0, -+ 57600, 86400, 57600, 86400, -+ 0, 0 } -+ }; -+ -+ /* XXX This should not be hard-coded. It should be taken from the spdb */ -+ uint8_t satype = SADB_SATYPE_ESP; -+ -+ pfkey_extensions_init(extensions); -+ -+ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: " -+ "SAtype=%d unspecified or unknown.\n", -+ satype); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(pfkey_registered_sockets[satype])) { -+ KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " -+ "no sockets registered for SAtype=%d(%s).\n", -+ satype, -+ satype2name(satype)); -+ SENDERR(EPROTONOSUPPORT); -+ } -+ -+ if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions[0], -+ SADB_ACQUIRE, -+ satype, -+ 0, -+ ++pfkey_msg_seq, -+ 0), -+ extensions) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ ipsp->ips_transport_protocol, -+ 0, -+ ipsp->ips_addr_s), -+ extensions) -+ && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ ipsp->ips_transport_protocol, -+ 0, -+ ipsp->ips_addr_d), -+ extensions) -+#if 0 -+ && (ipsp->ips_addr_p -+ ? pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_PROXY], -+ SADB_EXT_ADDRESS_PROXY, -+ ipsp->ips_transport_protocol, -+ 0, -+ ipsp->ips_addr_p), -+ extensions) : 1) -+#endif -+ && (ipsp->ips_ident_s.type != SADB_IDENTTYPE_RESERVED -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_SRC], -+ SADB_EXT_IDENTITY_SRC, -+ ipsp->ips_ident_s.type, -+ ipsp->ips_ident_s.id, -+ ipsp->ips_ident_s.len, -+ ipsp->ips_ident_s.data), -+ extensions) : 1) -+ -+ && (ipsp->ips_ident_d.type != SADB_IDENTTYPE_RESERVED -+ ? pfkey_safe_build(error = pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_DST], -+ SADB_EXT_IDENTITY_DST, -+ ipsp->ips_ident_d.type, -+ ipsp->ips_ident_d.id, -+ ipsp->ips_ident_d.len, -+ ipsp->ips_ident_d.data), -+ extensions) : 1) -+#if 0 -+ /* FIXME: This won't work yet because I have not finished -+ it. */ -+ && (ipsp->ips_sens_ -+ ? pfkey_safe_build(error = pfkey_sens_build(&extensions[SADB_EXT_SENSITIVITY], -+ ipsp->ips_sens_dpd, -+ ipsp->ips_sens_sens_level, -+ ipsp->ips_sens_sens_len, -+ ipsp->ips_sens_sens_bitmap, -+ ipsp->ips_sens_integ_level, -+ ipsp->ips_sens_integ_len, -+ ipsp->ips_sens_integ_bitmap), -+ extensions) : 1) -+#endif -+ && pfkey_safe_build(error = pfkey_prop_build(&extensions[SADB_EXT_PROPOSAL], -+ 64, /* replay */ -+ sizeof(comb)/sizeof(struct sadb_comb), -+ &(comb[0])), -+ extensions) -+ )) { -+ KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " -+ "failed to build the acquire message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) { -+ KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " -+ "failed to build the acquire message\n"); -+ SENDERR(-error); -+ } -+ -+#if KLIPS_PFKEY_ACQUIRE_LOSSAGE > 0 -+ if(sysctl_ipsec_regress_pfkey_lossage) { -+ return(0); -+ } -+#endif -+ -+ /* this should go to all registered sockets for that satype only */ -+ for(pfkey_socketsp = pfkey_registered_sockets[satype]; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) { -+ KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " -+ "sending up acquire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: " -+ "sending up acquire message for satype=%d(%s) to socket=0p%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ errlab: -+ if (pfkey_msg) { -+ pfkey_msg_free(&pfkey_msg); -+ } -+ pfkey_extensions_free(extensions); -+ return error; -+} -+ -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+int -+pfkey_nat_t_new_mapping(struct ipsec_sa *ipsp, struct sockaddr *ipaddr, -+ __u16 sport) -+{ -+ struct sadb_ext *extensions[SADB_EXT_MAX+1]; -+ struct sadb_msg *pfkey_msg = NULL; -+ struct socket_list *pfkey_socketsp; -+ int error = 0; -+ uint8_t satype = (ipsp->ips_said.proto==IPPROTO_ESP) ? SADB_SATYPE_ESP : 0; -+ -+ /* Construct SADB_X_NAT_T_NEW_MAPPING message */ -+ -+ pfkey_extensions_init(extensions); -+ -+ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " -+ "SAtype=%d unspecified or unknown.\n", -+ satype); -+ SENDERR(EINVAL); -+ } -+ -+ if(!(pfkey_registered_sockets[satype])) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " -+ "no sockets registered for SAtype=%d(%s).\n", -+ satype, -+ satype2name(satype)); -+ SENDERR(EPROTONOSUPPORT); -+ } -+ -+ if (!(pfkey_safe_build -+ (error = pfkey_msg_hdr_build(&extensions[0], SADB_X_NAT_T_NEW_MAPPING, -+ satype, 0, ++pfkey_msg_seq, 0), extensions) -+ /* SA */ -+ && pfkey_safe_build -+ (error = pfkey_sa_build(&extensions[SADB_EXT_SA], -+ SADB_EXT_SA, ipsp->ips_said.spi, 0, 0, 0, 0, 0), extensions) -+ /* ADDRESS_SRC = old addr */ -+ && pfkey_safe_build -+ (error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, ipsp->ips_said.proto, 0, ipsp->ips_addr_s), -+ extensions) -+ /* NAT_T_SPORT = old port */ -+ && pfkey_safe_build -+ (error = pfkey_x_nat_t_port_build(&extensions[SADB_X_EXT_NAT_T_SPORT], -+ SADB_X_EXT_NAT_T_SPORT, ipsp->ips_natt_sport), extensions) -+ /* ADDRESS_DST = new addr */ -+ && pfkey_safe_build -+ (error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, ipsp->ips_said.proto, 0, ipaddr), extensions) -+ /* NAT_T_DPORT = new port */ -+ && pfkey_safe_build -+ (error = pfkey_x_nat_t_port_build(&extensions[SADB_X_EXT_NAT_T_DPORT], -+ SADB_X_EXT_NAT_T_DPORT, sport), extensions) -+ )) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " -+ "failed to build the nat_t_new_mapping message extensions\n"); -+ SENDERR(-error); -+ } -+ -+ if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " -+ "failed to build the nat_t_new_mapping message\n"); -+ SENDERR(-error); -+ } -+ -+ /* this should go to all registered sockets for that satype only */ -+ for(pfkey_socketsp = pfkey_registered_sockets[satype]; -+ pfkey_socketsp; -+ pfkey_socketsp = pfkey_socketsp->next) { -+ if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " -+ "sending up nat_t_new_mapping message for satype=%d(%s) to socket=%p failed with error=%d.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp, -+ error); -+ SENDERR(-error); -+ } -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " -+ "sending up nat_t_new_mapping message for satype=%d(%s) to socket=%p succeeded.\n", -+ satype, -+ satype2name(satype), -+ pfkey_socketsp->socketp); -+ } -+ -+ errlab: -+ if (pfkey_msg) { -+ pfkey_msg_free(&pfkey_msg); -+ } -+ pfkey_extensions_free(extensions); -+ return error; -+} -+ -+DEBUG_NO_STATIC int -+pfkey_x_nat_t_new_mapping_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) -+{ -+ /* SADB_X_NAT_T_NEW_MAPPING not used in kernel */ -+ return -EINVAL; -+} -+#endif -+ -+DEBUG_NO_STATIC int (*ext_processors[SADB_EXT_MAX+1])(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) = -+{ -+ NULL, /* pfkey_msg_process, */ -+ pfkey_sa_process, -+ pfkey_lifetime_process, -+ pfkey_lifetime_process, -+ pfkey_lifetime_process, -+ pfkey_address_process, -+ pfkey_address_process, -+ pfkey_address_process, -+ pfkey_key_process, -+ pfkey_key_process, -+ pfkey_ident_process, -+ pfkey_ident_process, -+ pfkey_sens_process, -+ pfkey_prop_process, -+ pfkey_supported_process, -+ pfkey_supported_process, -+ pfkey_spirange_process, -+ pfkey_x_kmprivate_process, -+ pfkey_x_satype_process, -+ pfkey_sa_process, -+ pfkey_address_process, -+ pfkey_address_process, -+ pfkey_address_process, -+ pfkey_address_process, -+ pfkey_address_process, -+ pfkey_x_debug_process, -+ pfkey_x_protocol_process -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ , -+ pfkey_x_nat_t_type_process, -+ pfkey_x_nat_t_port_process, -+ pfkey_x_nat_t_port_process, -+ pfkey_address_process -+#endif -+}; -+ -+ -+DEBUG_NO_STATIC int (*msg_parsers[SADB_MAX +1])(struct sock *sk, struct sadb_ext *extensions[], struct pfkey_extracted_data* extr) -+ = -+{ -+ NULL, /* RESERVED */ -+ pfkey_getspi_parse, -+ pfkey_update_parse, -+ pfkey_add_parse, -+ pfkey_delete_parse, -+ pfkey_get_parse, -+ pfkey_acquire_parse, -+ pfkey_register_parse, -+ pfkey_expire_parse, -+ pfkey_flush_parse, -+ pfkey_dump_parse, -+ pfkey_x_promisc_parse, -+ pfkey_x_pchange_parse, -+ pfkey_x_grpsa_parse, -+ pfkey_x_addflow_parse, -+ pfkey_x_delflow_parse, -+ pfkey_x_msg_debug_parse -+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -+ , pfkey_x_nat_t_new_mapping_parse -+#endif -+}; -+ -+int -+pfkey_build_reply(struct sadb_msg *pfkey_msg, struct pfkey_extracted_data *extr, -+ struct sadb_msg **pfkey_reply) -+{ -+ struct sadb_ext *extensions[SADB_EXT_MAX+1]; -+ int error = 0; -+ int msg_type = pfkey_msg->sadb_msg_type; -+ int seq = pfkey_msg->sadb_msg_seq; -+ -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " -+ "building reply with type: %d\n", -+ msg_type); -+ pfkey_extensions_init(extensions); -+ if (!extr || !extr->ips) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " -+ "bad ipsec_sa passed\n"); -+ return EINVAL; -+ } -+ error = pfkey_safe_build(pfkey_msg_hdr_build(&extensions[0], -+ msg_type, -+ proto2satype(extr->ips->ips_said.proto), -+ 0, -+ seq, -+ pfkey_msg->sadb_msg_pid), -+ extensions) && -+ (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & -+ 1 << SADB_EXT_SA) -+ || pfkey_safe_build(pfkey_sa_ref_build(&extensions[SADB_EXT_SA], -+ SADB_EXT_SA, -+ extr->ips->ips_said.spi, -+ extr->ips->ips_replaywin, -+ extr->ips->ips_state, -+ extr->ips->ips_authalg, -+ extr->ips->ips_encalg, -+ extr->ips->ips_flags, -+ extr->ips->ips_ref), -+ extensions)) && -+ (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & -+ 1 << SADB_EXT_LIFETIME_CURRENT) -+ || pfkey_safe_build(pfkey_lifetime_build(&extensions -+ [SADB_EXT_LIFETIME_CURRENT], -+ SADB_EXT_LIFETIME_CURRENT, -+ extr->ips->ips_life.ipl_allocations.ipl_count, -+ extr->ips->ips_life.ipl_bytes.ipl_count, -+ extr->ips->ips_life.ipl_addtime.ipl_count, -+ extr->ips->ips_life.ipl_usetime.ipl_count, -+ extr->ips->ips_life.ipl_packets.ipl_count), -+ extensions)) && -+ (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & -+ 1 << SADB_EXT_ADDRESS_SRC) -+ || pfkey_safe_build(pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], -+ SADB_EXT_ADDRESS_SRC, -+ extr->ips->ips_said.proto, -+ 0, -+ extr->ips->ips_addr_s), -+ extensions)) && -+ (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & -+ 1 << SADB_EXT_ADDRESS_DST) -+ || pfkey_safe_build(pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], -+ SADB_EXT_ADDRESS_DST, -+ extr->ips->ips_said.proto, -+ 0, -+ extr->ips->ips_addr_d), -+ extensions)); -+ -+ if (error == 0) { -+ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " -+ "building extensions failed\n"); -+ return EINVAL; -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_build_reply: " -+ "built extensions, proceed to build the message\n"); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_build_reply: " -+ "extensions[1]=0p%p\n", -+ extensions[1]); -+ error = pfkey_msg_build(pfkey_reply, extensions, EXT_BITS_OUT); -+ pfkey_extensions_free(extensions); -+ -+ return error; -+} -+ -+int -+pfkey_msg_interp(struct sock *sk, struct sadb_msg *pfkey_msg, -+ struct sadb_msg **pfkey_reply) -+{ -+ int error = 0; -+ int i; -+ struct sadb_ext *extensions[SADB_EXT_MAX+1]; -+ struct pfkey_extracted_data extr = {NULL, NULL, NULL}; -+ -+ pfkey_extensions_init(extensions); -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "parsing message ver=%d, type=%d, errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n", -+ pfkey_msg->sadb_msg_version, -+ pfkey_msg->sadb_msg_type, -+ pfkey_msg->sadb_msg_errno, -+ pfkey_msg->sadb_msg_satype, -+ satype2name(pfkey_msg->sadb_msg_satype), -+ pfkey_msg->sadb_msg_len, -+ pfkey_msg->sadb_msg_reserved, -+ pfkey_msg->sadb_msg_seq, -+ pfkey_msg->sadb_msg_pid); -+ -+ extr.ips = ipsec_sa_alloc(&error); /* pass in error var by pointer */ -+ if(extr.ips == NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "memory allocation error.\n"); -+ SENDERR(-error); -+ } -+ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "allocated extr->ips=0p%p.\n", -+ extr.ips); -+ -+ if(pfkey_msg->sadb_msg_satype > SADB_SATYPE_MAX) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "satype %d > max %d\n", -+ pfkey_msg->sadb_msg_satype, -+ SADB_SATYPE_MAX); -+ SENDERR(EINVAL); -+ } -+ -+ switch(pfkey_msg->sadb_msg_type) { -+ case SADB_GETSPI: -+ case SADB_UPDATE: -+ case SADB_ADD: -+ case SADB_DELETE: -+ case SADB_X_GRPSA: -+ case SADB_X_ADDFLOW: -+ -+ if(!(extr.ips->ips_said.proto = satype2proto(pfkey_msg->sadb_msg_satype))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "satype %d lookup failed.\n", -+ pfkey_msg->sadb_msg_satype); -+ SENDERR(EINVAL); -+ } else { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "satype %d lookups to proto=%d.\n", -+ pfkey_msg->sadb_msg_satype, -+ extr.ips->ips_said.proto); -+ } -+ break; -+ default: -+ break; -+ } -+ -+ /* The NULL below causes the default extension parsers to be used */ -+ /* Parse the extensions */ -+ if((error = pfkey_msg_parse(pfkey_msg, NULL, extensions, EXT_BITS_IN))) -+ { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "message parsing failed with error %d.\n", -+ error); -+ SENDERR(-error); -+ } -+ -+ /* Process the extensions */ -+ for(i=1; i <= SADB_EXT_MAX;i++) { -+ if(extensions[i] != NULL) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "processing ext %d 0p%p with processor 0p%p.\n", -+ i, extensions[i], ext_processors[i]); -+ if((error = ext_processors[i](extensions[i], &extr))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "extension processing for type %d failed with error %d.\n", -+ i, -+ error); -+ SENDERR(-error); -+ } -+ -+ } -+ -+ } -+ -+ /* Parse the message types */ -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "parsing message type %d(%s) with msg_parser 0p%p.\n", -+ pfkey_msg->sadb_msg_type, -+ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type), -+ msg_parsers[pfkey_msg->sadb_msg_type]); -+ if((error = msg_parsers[pfkey_msg->sadb_msg_type](sk, extensions, &extr))) { -+ KLIPS_PRINT(debug_pfkey, -+ "klips_debug:pfkey_msg_interp: " -+ "message parsing failed with error %d.\n", -+ error); -+ SENDERR(-error); -+ } -+ -+#if 0 -+ error = pfkey_build_reply(pfkey_msg, &extr, pfkey_reply); -+ if (error) { -+ *pfkey_reply = NULL; -+ } -+#endif -+ errlab: -+ if(extr.ips != NULL) { -+ ipsec_sa_wipe(extr.ips); -+ } -+ if(extr.ips2 != NULL) { -+ ipsec_sa_wipe(extr.ips2); -+ } -+ if (extr.eroute != NULL) { -+ kfree(extr.eroute); -+ } -+ return(error); -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.123 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.122.2.2 2004/04/05 04:30:46 mcr -+ * patches for alg-branch to compile/work with 2.x openswan -+ * -+ * Revision 1.122.2.1 2003/12/22 15:25:52 jjo -+ * . Merged algo-0.8.1-rc11-test1 into alg-branch -+ * -+ * Revision 1.122 2003/12/10 01:14:27 mcr -+ * NAT-traversal patches to KLIPS. -+ * -+ * Revision 1.121 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.120.4.2 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.120.4.1 2003/09/21 13:59:56 mcr -+ * pre-liminary X.509 patch - does not yet pass tests. -+ * -+ * Revision 1.120 2003/04/03 17:38:09 rgb -+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. -+ * -+ * Revision 1.119 2003/02/06 01:52:37 rgb -+ * Removed no longer relevant comment -+ * -+ * Revision 1.118 2003/01/30 02:32:44 rgb -+ * -+ * Transmit error code through to caller from callee for better diagnosis of problems. -+ * -+ * Revision 1.117 2003/01/16 18:48:13 rgb -+ * -+ * Fixed sign bug in error return from an sa allocation call in -+ * pfkey_msg_interp. -+ * -+ * Revision 1.116 2002/10/17 16:38:01 rgb -+ * Change pfkey_alloc_eroute() to never static since its consumers -+ * have been moved outside the file. -+ * -+ * Revision 1.115 2002/10/12 23:11:53 dhr -+ * -+ * [KenB + DHR] more 64-bit cleanup -+ * -+ * Revision 1.114 2002/10/05 05:02:58 dhr -+ * -+ * C labels go on statements -+ * -+ * Revision 1.113 2002/09/30 19:11:22 rgb -+ * Turn on debugging for upgoing acquire messages to test for reliability. -+ * -+ * Revision 1.112 2002/09/20 15:41:16 rgb -+ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc(). -+ * Added sadb_x_sa_ref to struct sadb_sa. -+ * Added ref parameter to pfkey_sa_build(). -+ * -+ * Revision 1.111 2002/09/20 05:02:08 rgb -+ * Added memory allocation debugging. -+ * Convert to switch to divulge hmac keys for debugging. -+ * Added text labels to elucidate numeric values presented. -+ * -+ * Revision 1.110 2002/08/03 18:03:05 mcr -+ * loop that checks for SPI's to have been already linked -+ * fails to actually step to next pointer, but continuously -+ * resets to head of list. Wrong pointer used. -+ * test east-icmp-02 revealed this. -+ * -+ * Revision 1.109 2002/07/26 08:48:31 rgb -+ * Added SA ref table code. -+ * -+ * Revision 1.108 2002/05/27 18:55:03 rgb -+ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT. -+ * -+ * Revision 1.107 2002/05/23 07:16:08 rgb -+ * Added ipsec_sa_put() for releasing an ipsec_sa refcount. -+ * Pointer clean-up. -+ * Added refcount code. -+ * -+ * Revision 1.106 2002/05/14 02:34:13 rgb -+ * Converted reference from ipsec_sa_put to ipsec_sa_add to avoid confusion -+ * with "put" usage in the kernel. -+ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips, -+ * ipsec_sa or ipsec_sa. -+ * Moved all the extension parsing functions to pfkey_v2_ext_process.c. -+ * -+ * Revision 1.105 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.104 2002/04/24 07:36:34 mcr -+ * Moved from ./klips/net/ipsec/pfkey_v2_parser.c,v -+ * -+ * Revision 1.103 2002/04/20 00:12:25 rgb -+ * Added esp IV CBC attack fix, disabled. -+ * -+ * Revision 1.102 2002/03/08 01:15:17 mcr -+ * put some internal structure only debug messages behind -+ * && sysctl_ipsec_debug_verbose. -+ * -+ * Revision 1.101 2002/01/29 17:17:57 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.100 2002/01/29 04:00:54 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.99 2002/01/29 02:13:19 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.98 2002/01/12 02:57:57 mcr -+ * first regression test causes acquire messages to be lost -+ * 100% of the time. This is to help testing of pluto. -+ * -+ * Revision 1.97 2001/11/26 09:23:52 rgb -+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes. -+ * -+ * Revision 1.93.2.4 2001/10/23 04:20:27 mcr -+ * parity was forced on wrong structure! prototypes help here. -+ * -+ * Revision 1.93.2.3 2001/10/22 21:14:59 mcr -+ * include des.h, removed phony prototypes and fixed calling -+ * conventions to match real prototypes. -+ * -+ * Revision 1.93.2.2 2001/10/15 05:39:03 mcr -+ * %08lx is not the right format for u32. Use %08x. 64-bit safe? ha. -+ * -+ * Revision 1.93.2.1 2001/09/25 02:30:14 mcr -+ * struct tdb -> struct ipsec_sa. -+ * use new lifetime structure. common format routines for debug. -+ * -+ * Revision 1.96 2001/11/06 20:47:54 rgb -+ * Fixed user context call to ipsec_dev_start_xmit() bug. Call -+ * dev_queue_xmit() instead. -+ * -+ * Revision 1.95 2001/11/06 19:47:46 rgb -+ * Added packet parameter to lifetime and comb structures. -+ * -+ * Revision 1.94 2001/10/18 04:45:23 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.93 2001/09/20 15:32:59 rgb -+ * Min/max cleanup. -+ * -+ * Revision 1.92 2001/09/19 16:35:48 rgb -+ * PF_KEY ident fix for getspi from NetCelo (puttdb duplication). -+ * -+ * Revision 1.91 2001/09/15 16:24:06 rgb -+ * Re-inject first and last HOLD packet when an eroute REPLACE is done. -+ * -+ * Revision 1.90 2001/09/14 16:58:38 rgb -+ * Added support for storing the first and last packets through a HOLD. -+ * -+ * Revision 1.89 2001/09/08 21:14:07 rgb -+ * Added pfkey ident extension support for ISAKMPd. (NetCelo) -+ * Better state coherency (error management) between pf_key and IKE daemon. -+ * (NetCelo) -+ * -+ * Revision 1.88 2001/08/27 19:42:44 rgb -+ * Fix memory leak of encrypt and auth structs in pfkey register. -+ * -+ * Revision 1.87 2001/07/06 19:50:46 rgb -+ * Removed unused debugging code. -+ * Added inbound policy checking code for IPIP SAs. -+ * -+ * Revision 1.86 2001/06/20 06:26:04 rgb -+ * Changed missing SA errors from EEXIST to ENOENT and added debug output -+ * for already linked SAs. -+ * -+ * Revision 1.85 2001/06/15 04:57:02 rgb -+ * Remove single error return condition check and check for all errors in -+ * the case of a replace eroute delete operation. This means that -+ * applications must expect to be deleting something before replacing it -+ * and if nothing is found, complain. -+ * -+ * Revision 1.84 2001/06/14 19:35:12 rgb -+ * Update copyright date. -+ * -+ * Revision 1.83 2001/06/12 00:03:19 rgb -+ * Silence debug set/unset under normal conditions. -+ * -+ * Revision 1.82 2001/05/30 08:14:04 rgb -+ * Removed vestiges of esp-null transforms. -+ * -+ * Revision 1.81 2001/05/27 06:12:12 rgb -+ * Added structures for pid, packet count and last access time to eroute. -+ * Added packet count to beginning of /proc/net/ipsec_eroute. -+ * -+ * Revision 1.80 2001/05/03 19:43:59 rgb -+ * Check error return codes for all build function calls. -+ * Standardise on SENDERR() macro. -+ * -+ * Revision 1.79 2001/04/20 21:09:16 rgb -+ * Cleaned up fixed tdbwipes. -+ * Free pfkey_reply and clean up extensions_reply for grpsa, addflow and -+ * delflow (Per Cederqvist) plugging memleaks. -+ * -+ * Revision 1.78 2001/04/19 19:02:39 rgb -+ * Fixed extr.tdb freeing, stealing it for getspi, update and add. -+ * Refined a couple of spinlocks, fixed the one in update. -+ * -+ * Revision 1.77 2001/04/18 20:26:16 rgb -+ * Wipe/free eroute and both tdbs from extr at end of pfkey_msg_interp() -+ * instead of inside each message type parser. This fixes two memleaks. -+ * -+ * Revision 1.76 2001/04/17 23:51:18 rgb -+ * Quiet down pfkey_x_debug_process(). -+ * -+ * Revision 1.75 2001/03/29 01:55:05 rgb -+ * Fixed pfkey key init memleak. -+ * Fixed pfkey encryption key debug output. -+ * -+ * Revision 1.74 2001/03/27 05:29:14 rgb -+ * Debug output cleanup/silencing. -+ * -+ * Revision 1.73 2001/02/28 05:03:28 rgb -+ * Clean up and rationalise startup messages. -+ * -+ * Revision 1.72 2001/02/27 22:24:56 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.71 2001/02/27 06:59:30 rgb -+ * Added satype2name() conversions most places satype is debug printed. -+ * -+ * Revision 1.70 2001/02/26 22:37:08 rgb -+ * Fixed 'unknown proto' INT bug in new code. -+ * Added satype to protocol debugging instrumentation. -+ * -+ * Revision 1.69 2001/02/26 19:57:51 rgb -+ * Re-formatted debug output (split lines, consistent spacing). -+ * Fixed as yet undetected FLUSH bug which called ipsec_tdbcleanup() -+ * with an satype instead of proto. -+ * Checked for satype consistency and fixed minor bugs. -+ * Fixed undetected ungrpspi bug that tried to upmsg a second tdb. -+ * Check for satype sanity in pfkey_expire(). -+ * Added satype sanity check to addflow. -+ * -+ * Revision 1.68 2001/02/12 23:14:40 rgb -+ * Remove double spin lock in pfkey_expire(). -+ * -+ * Revision 1.67 2001/01/31 19:23:40 rgb -+ * Fixed double-unlock bug introduced by grpsa upmsg (found by Lars Heete). -+ * -+ * Revision 1.66 2001/01/29 22:20:04 rgb -+ * Fix minor add upmsg lifetime bug. -+ * -+ * Revision 1.65 2001/01/24 06:12:33 rgb -+ * Fixed address extension compile bugs just introduced. -+ * -+ * Revision 1.64 2001/01/24 00:31:15 rgb -+ * Added upmsg for addflow/delflow. -+ * -+ * Revision 1.63 2001/01/23 22:02:55 rgb -+ * Added upmsg to x_grpsa. -+ * Fixed lifetimes extentions to add/update/get upmsg. -+ * -+ * Revision 1.62 2000/11/30 21:47:51 rgb -+ * Fix error return bug after returning from pfkey_tdb_init(). -+ * -+ * Revision 1.61 2000/11/17 18:10:29 rgb -+ * Fixed bugs mostly relating to spirange, to treat all spi variables as -+ * network byte order since this is the way PF_KEYv2 stored spis. -+ * -+ * Revision 1.60 2000/11/06 04:34:53 rgb -+ * Changed non-exported functions to DEBUG_NO_STATIC. -+ * Add Svenning's adaptive content compression. -+ * Ditched spin_lock_irqsave in favour of spin_lock/_bh. -+ * Fixed double unlock bug (Svenning). -+ * Fixed pfkey_msg uninitialized bug in pfkey_{expire,acquire}(). -+ * Fixed incorrect extension type (prop) in pfkey)acquire(). -+ * -+ * Revision 1.59 2000/10/11 15:25:12 rgb -+ * Fixed IPCOMP disabled compile bug. -+ * -+ * Revision 1.58 2000/10/11 14:54:03 rgb -+ * Fixed pfkey_acquire() satype to SADB_SATYPE_ESP and removed pfkey -+ * protocol violations of setting pfkey_address_build() protocol parameter -+ * to non-zero except in the case of pfkey_acquire(). -+ * -+ * Revision 1.57 2000/10/10 20:10:18 rgb -+ * Added support for debug_ipcomp and debug_verbose to klipsdebug. -+ * -+ * Revision 1.56 2000/10/06 20:24:36 rgb -+ * Fixes to pfkey_acquire to initialize extensions[] and use correct -+ * ipproto. -+ * -+ * Revision 1.55 2000/10/03 03:20:57 rgb -+ * Added brackets to get a?b:c scope right for pfkey_register reply. -+ * -+ * Revision 1.54 2000/09/29 19:49:30 rgb -+ * As-yet-unused-bits cleanup. -+ * -+ * Revision 1.53 2000/09/28 00:35:45 rgb -+ * Padded SATYPE printout in pfkey_register for vertical alignment. -+ * -+ * Revision 1.52 2000/09/20 16:21:58 rgb -+ * Cleaned up ident string alloc/free. -+ * -+ * Revision 1.51 2000/09/20 04:04:20 rgb -+ * Changed static functions to DEBUG_NO_STATIC to reveal function names in -+ * oopsen. -+ * -+ * Revision 1.50 2000/09/16 01:10:53 rgb -+ * Fixed unused var warning with debug off. -+ * -+ * Revision 1.49 2000/09/15 11:37:02 rgb -+ * Merge in heavily modified Svenning Soerensen's -+ * IPCOMP zlib deflate code. -+ * -+ * Revision 1.48 2000/09/15 04:57:57 rgb -+ * Cleaned up existing IPCOMP code before svenning addition. -+ * Initialize pfkey_reply and extensions_reply in case of early error in -+ * message parsing functions (thanks Kai!). -+ * -+ * Revision 1.47 2000/09/13 08:02:56 rgb -+ * Added KMd registration notification. -+ * -+ * Revision 1.46 2000/09/12 22:35:36 rgb -+ * Restructured to remove unused extensions from CLEARFLOW messages. -+ * -+ * Revision 1.45 2000/09/12 03:24:23 rgb -+ * Converted #if0 debugs to sysctl. -+ * -+ * Revision 1.44 2000/09/09 06:38:39 rgb -+ * Correct SADB message type for update, add and delete. -+ * -+ * Revision 1.43 2000/09/08 19:19:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * Removed all references to CONFIG_IPSEC_PFKEYv2. -+ * Put in sanity checks in most msg type parsers to catch invalid satypes -+ * and empty socket lists. -+ * Moved spin-locks in pfkey_get_parse() to simplify. -+ * Added pfkey_acquire(). -+ * Added upwards messages to update, add, delete, acquire_parse, -+ * expire_parse and flush. -+ * Fix pfkey_prop_build() parameter to be only single indirection. -+ * Changed all replies to use pfkey_reply. -+ * Check return code on puttdb() and deltdbchain() in getspi, update, -+ * add, delete. -+ * Fixed up all pfkey replies to open and registered sockets. -+ * -+ * Revision 1.42 2000/09/01 18:50:26 rgb -+ * Added a supported algorithms array lists, one per satype and registered -+ * existing algorithms. -+ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to -+ * list. -+ * Only send pfkey_expire() messages to sockets registered for that satype. -+ * Added reply to pfkey_getspi_parse(). -+ * Added reply to pfkey_get_parse(). -+ * Fixed debug output label bug in pfkey_lifetime_process(). -+ * Cleaned up pfkey_sa_process a little. -+ * Moved pfkey_safe_build() above message type parsers to make it available -+ * for creating replies. -+ * Added comments for future work in pfkey_acquire_parse(). -+ * Fleshed out guts of pfkey_register_parse(). -+ * -+ * Revision 1.41 2000/08/24 16:58:11 rgb -+ * Fixed key debugging variables. -+ * Fixed error return code for a failed search. -+ * Changed order of pfkey_get operations. -+ * -+ * Revision 1.40 2000/08/21 16:32:27 rgb -+ * Re-formatted for cosmetic consistency and readability. -+ * -+ * Revision 1.39 2000/08/20 21:38:57 rgb -+ * Bugfixes to as-yet-unused pfkey_update_parse() and -+ * pfkey_register_parse(). (Momchil) -+ * Added functions pfkey_safe_build(), pfkey_expire() and -+ * pfkey_build_reply(). (Momchil) -+ * Added a pfkey_reply parameter to pfkey_msg_interp(). (Momchil) -+ * -+ * Revision 1.38 2000/08/18 21:30:41 rgb -+ * Purged all tdb_spi, tdb_proto and tdb_dst macros. They are unclear. -+ * -+ * Revision 1.37 2000/08/18 18:18:02 rgb -+ * Cosmetic and descriptive changes made to debug test. -+ * getspi and update fixes from Momchil. -+ * -+ * Revision 1.36 2000/08/15 15:41:55 rgb -+ * Fixed the (as yet unused and untested) pfkey_getspi() routine. -+ * -+ * Revision 1.35 2000/08/01 14:51:52 rgb -+ * Removed _all_ remaining traces of DES. -+ * -+ * Revision 1.34 2000/07/28 14:58:32 rgb -+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. -+ * -+ * Revision 1.33 2000/06/28 05:50:11 rgb -+ * Actually set iv_bits. -+ * -+ * Revision 1.32 2000/05/30 18:36:56 rgb -+ * Fix AH auth hash setup bug. This breaks interop with previous PF_KEY -+ * FreeS/WAN, but fixes interop with other implementations. -+ * -+ * Revision 1.31 2000/03/16 14:05:48 rgb -+ * Fixed brace scope preventing non-debug compile. -+ * Added null parameter check for pfkey_x_debug(). -+ * -+ * Revision 1.30 2000/01/22 23:21:13 rgb -+ * Use new function satype2proto(). -+ * -+ * Revision 1.29 2000/01/22 08:40:21 rgb -+ * Invert condition to known value to avoid AF_INET6 in 2.0.36. -+ * -+ * Revision 1.28 2000/01/22 07:58:57 rgb -+ * Fixed REPLACEFLOW bug, missing braces around KLIPS_PRINT *and* SENDERR. -+ * -+ * Revision 1.27 2000/01/22 03:48:01 rgb -+ * Added extr pointer component debugging. -+ * -+ * Revision 1.26 2000/01/21 09:41:25 rgb -+ * Changed a (void*) to (char*) cast to do proper pointer math. -+ * Don't call tdbwipe if tdb2 is NULL. -+ * -+ * Revision 1.25 2000/01/21 06:21:01 rgb -+ * Added address cases for eroute flows. -+ * Tidied up compiler directive indentation for readability. -+ * Added ictx,octx vars for simplification. -+ * Added macros for HMAC padding magic numbers. -+ * Converted from double tdb arguments to one structure (extr) -+ * containing pointers to all temporary information structures -+ * and checking for valid arguments to all ext processors and -+ * msg type parsers. -+ * Added spiungrp'ing. -+ * Added klipsdebug switching capability. -+ * Removed sa_process() check for zero protocol. -+ * Added address case for DST2 for grouping. -+ * Added/changed minor debugging instrumentation. -+ * Fixed spigrp for single said, ungrouping case. -+ * Added code to parse addflow and delflow messages. -+ * Removed redundant statements duplicating tdbwipe() functionality -+ * and causing double kfrees. -+ * Permit addflow to have a protocol of 0. -+ * -+ * Revision 1.24 1999/12/09 23:23:00 rgb -+ * Added check to pfkey_sa_process() to do eroutes. -+ * Converted to DIVUP() macro. -+ * Converted if() to switch() in pfkey_register_parse(). -+ * Use new pfkey_extensions_init() instead of memset(). -+ * -+ * Revision 1.23 1999/12/01 22:18:13 rgb -+ * Preset minspi and maxspi values in case and spirange extension is not -+ * included and check for the presence of an spirange extension before -+ * using it. Initialise tdb_sastate to LARVAL. -+ * Fixed debugging output typo. -+ * Fixed authentication context initialisation bugs (4 places). -+ * -+ * Revision 1.22 1999/11/27 11:53:08 rgb -+ * Moved pfkey_msg_parse prototype to pfkey.h -+ * Moved exts_permitted/required prototype to pfkey.h. -+ * Moved sadb_satype2proto protocol lookup table to lib/pfkey_v2_parse.c. -+ * Deleted SADB_X_EXT_SA2 code from pfkey_sa_process() since it will never -+ * be called. -+ * Moved protocol/algorithm checks to lib/pfkey_v2_parse.c -+ * Debugging error messages added. -+ * Enable lifetime_current checking. -+ * Remove illegal requirement for SA extension to be present in an -+ * originating GETSPI call. -+ * Re-instate requirement for UPDATE or ADD message to be MATURE. -+ * Add argument to pfkey_msg_parse() for direction. -+ * Fixed IPIP dst address bug and purged redundant, leaky code. -+ * -+ * Revision 1.21 1999/11/24 05:24:20 rgb -+ * hanged 'void*extensions' to 'struct sadb_ext*extensions'. -+ * Fixed indention. -+ * Ditched redundant replay check. -+ * Fixed debug message text from 'parse' to 'process'. -+ * Added more debug output. -+ * Forgot to zero extensions array causing bug, fixed. -+ * -+ * Revision 1.20 1999/11/23 23:08:13 rgb -+ * Move all common parsing code to lib/pfkey_v2_parse.c and rename -+ * remaining bits to *_process. (PJO) -+ * Add macros for dealing with alignment and rounding up more opaquely. -+ * Use provided macro ADDRTOA_BUF instead of hardcoded value. -+ * Sort out pfkey and freeswan headers, putting them in a library path. -+ * Corrected a couple of bugs in as-yet-inactive code. -+ * -+ * Revision 1.19 1999/11/20 22:01:10 rgb -+ * Add more descriptive error messages for non-zero reserved fields. -+ * Add more descriptive error message for spirange parsing. -+ * Start on supported extension parsing. -+ * Start on register and get message parsing. -+ * -+ * Revision 1.18 1999/11/18 04:09:20 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.17 1999/11/17 15:53:41 rgb -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * -+ * Revision 1.16 1999/10/26 16:57:43 rgb -+ * Add shorter macros for compiler directives to visually clean-up. -+ * Give ipv6 code meaningful compiler directive. -+ * Add comments to other #if 0 debug code. -+ * Remove unused *_bh_atomic() calls. -+ * Fix mis-placed spinlock. -+ * -+ * Revision 1.15 1999/10/16 18:27:10 rgb -+ * Clean-up unused cruft. -+ * Fix-up lifetime_allocations_c and lifetime_addtime_c initialisations. -+ * -+ * Revision 1.14 1999/10/08 18:37:34 rgb -+ * Fix end-of-line spacing to sate whining PHMs. -+ * -+ * Revision 1.13 1999/10/03 18:49:12 rgb -+ * Spinlock fixes for 2.0.xx and 2.3.xx. -+ * -+ * Revision 1.12 1999/10/01 15:44:54 rgb -+ * Move spinlock header include to 2.1> scope. -+ * -+ * Revision 1.11 1999/10/01 00:05:45 rgb -+ * Added tdb structure locking. -+ * Use 'jiffies' instead of do_get_timeofday(). -+ * Fix lifetime assignments. -+ * -+ * Revision 1.10 1999/09/21 15:24:45 rgb -+ * Rework spirange code to save entropy and prevent endless loops. -+ * -+ * Revision 1.9 1999/09/16 12:10:21 rgb -+ * Minor fixes to random spi selection for correctness and entropy conservation. -+ * -+ * Revision 1.8 1999/05/25 22:54:46 rgb -+ * Fix comparison that should be an assignment in an if. -+ * -+ * Revision 1.7 1999/05/09 03:25:37 rgb -+ * Fix bug introduced by 2.2 quick-and-dirty patch. -+ * -+ * Revision 1.6 1999/05/08 21:32:30 rgb -+ * Fix error return reporting. -+ * -+ * Revision 1.5 1999/05/05 22:02:33 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.4 1999/04/29 15:22:40 rgb -+ * Standardise an error return method. -+ * Add debugging instrumentation. -+ * Add check for existence of macros min/max. -+ * Add extensions permitted/required in/out filters. -+ * Add satype-to-protocol table. -+ * Add a second tdb pointer to each parser to accomodate GRPSA. -+ * Move AH & no_algo_set to GETSPI, UPDATE and ADD. -+ * Add OOO window check. -+ * Add support for IPPROTO_IPIP and hooks for IPPROTO_COMP. -+ * Add timestamp to lifetime parse. -+ * Fix address structure length checking bug. -+ * Fix address structure allocation bug (forgot to kmalloc!). -+ * Add checks for extension lengths. -+ * Add checks for extension reserved illegal values. -+ * Add check for spirange legal values. -+ * Add an extension type for parsing a second satype, SA and -+ * DST_ADDRESS. -+ * Make changes to tdb_init() template to get pfkey_tdb_init(), -+ * eliminating any mention of xformsw. -+ * Implement getspi, update and grpsa (not tested). -+ * Add stubs for as yet unimplemented message types. -+ * Add table of message parsers to substitute for msg_parse switch. -+ * -+ * Revision 1.3 1999/04/15 17:58:07 rgb -+ * Add RCSID labels. -+ * -+ * Revision 1.2 1999/04/15 15:37:26 rgb -+ * Forward check changes from POST1_00 branch. -+ * -+ * Revision 1.1.2.1 1999/03/26 20:58:56 rgb -+ * Add pfkeyv2 support to KLIPS. -+ * -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/radij.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,1225 @@ -+char radij_c_version[] = "RCSID $Id$"; -+ -+/* -+ * This file is defived from ${SRC}/sys/net/radix.c of BSD 4.4lite -+ * -+ * Variable and procedure names have been modified so that they don't -+ * conflict with the original BSD code, as a small number of modifications -+ * have been introduced and we may want to reuse this code in BSD. -+ * -+ * The `j' in `radij' is pronounced as a voiceless guttural (like a Greek -+ * chi or a German ch sound (as `doch', not as in `milch'), or even a -+ * spanish j as in Juan. It is not as far back in the throat like -+ * the corresponding Hebrew sound, nor is it a soft breath like the English h. -+ * It has nothing to do with the Dutch ij sound. -+ * -+ * Here is the appropriate copyright notice: -+ */ -+ -+/* -+ * Copyright (c) 1988, 1989, 1993 -+ * The Regents of the University of California. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * This product includes software developed by the University of -+ * California, Berkeley and its contributors. -+ * 4. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * @(#)radix.c 8.2 (Berkeley) 1/4/94 -+ */ -+ -+/* -+ * Routines to build and maintain radix trees for routing lookups. -+ */ -+ -+#include -+#include -+#include /* printk() */ -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef MALLOC_SLAB -+# include /* kmalloc() */ -+#else /* MALLOC_SLAB */ -+# include /* kmalloc() */ -+#endif /* MALLOC_SLAB */ -+#include /* error codes */ -+#include /* size_t */ -+#include /* mark_bh */ -+ -+#include /* struct device, and other headers */ -+#include /* eth_type_trans */ -+#include /* struct iphdr */ -+#include -+#ifdef NET_21 -+# include -+# include -+#endif /* NET_21 */ -+#include -+#include -+ -+#include -+ -+#include "openswan/radij.h" -+#include "openswan/ipsec_encap.h" -+#include "openswan/ipsec_radij.h" -+ -+int maj_keylen; -+struct radij_mask *rj_mkfreelist; -+struct radij_node_head *mask_rjhead; -+static int gotOddMasks; -+static char *maskedKey; -+static char *rj_zeroes, *rj_ones; -+ -+#define rj_masktop (mask_rjhead->rnh_treetop) -+#ifdef Bcmp -+# undef Bcmp -+#endif /* Bcmp */ -+#define Bcmp(a, b, l) (l == 0 ? 0 : memcmp((caddr_t)(b), (caddr_t)(a), (size_t)l)) -+/* -+ * The data structure for the keys is a radix tree with one way -+ * branching removed. The index rj_b at an internal node n represents a bit -+ * position to be tested. The tree is arranged so that all descendants -+ * of a node n have keys whose bits all agree up to position rj_b - 1. -+ * (We say the index of n is rj_b.) -+ * -+ * There is at least one descendant which has a one bit at position rj_b, -+ * and at least one with a zero there. -+ * -+ * A route is determined by a pair of key and mask. We require that the -+ * bit-wise logical and of the key and mask to be the key. -+ * We define the index of a route to associated with the mask to be -+ * the first bit number in the mask where 0 occurs (with bit number 0 -+ * representing the highest order bit). -+ * -+ * We say a mask is normal if every bit is 0, past the index of the mask. -+ * If a node n has a descendant (k, m) with index(m) == index(n) == rj_b, -+ * and m is a normal mask, then the route applies to every descendant of n. -+ * If the index(m) < rj_b, this implies the trailing last few bits of k -+ * before bit b are all 0, (and hence consequently true of every descendant -+ * of n), so the route applies to all descendants of the node as well. -+ * -+ * The present version of the code makes no use of normal routes, -+ * but similar logic shows that a non-normal mask m such that -+ * index(m) <= index(n) could potentially apply to many children of n. -+ * Thus, for each non-host route, we attach its mask to a list at an internal -+ * node as high in the tree as we can go. -+ */ -+ -+struct radij_node * -+rj_search(v_arg, head) -+ void *v_arg; -+ struct radij_node *head; -+{ -+ register struct radij_node *x; -+ register caddr_t v; -+ -+ for (x = head, v = v_arg; x->rj_b >= 0;) { -+ if (x->rj_bmask & v[x->rj_off]) -+ x = x->rj_r; -+ else -+ x = x->rj_l; -+ } -+ return (x); -+}; -+ -+struct radij_node * -+rj_search_m(v_arg, head, m_arg) -+ struct radij_node *head; -+ void *v_arg, *m_arg; -+{ -+ register struct radij_node *x; -+ register caddr_t v = v_arg, m = m_arg; -+ -+ for (x = head; x->rj_b >= 0;) { -+ if ((x->rj_bmask & m[x->rj_off]) && -+ (x->rj_bmask & v[x->rj_off])) -+ x = x->rj_r; -+ else -+ x = x->rj_l; -+ } -+ return x; -+}; -+ -+int -+rj_refines(m_arg, n_arg) -+ void *m_arg, *n_arg; -+{ -+ register caddr_t m = m_arg, n = n_arg; -+ register caddr_t lim, lim2 = lim = n + *(u_char *)n; -+ int longer = (*(u_char *)n++) - (int)(*(u_char *)m++); -+ int masks_are_equal = 1; -+ -+ if (longer > 0) -+ lim -= longer; -+ while (n < lim) { -+ if (*n & ~(*m)) -+ return 0; -+ if (*n++ != *m++) -+ masks_are_equal = 0; -+ -+ } -+ while (n < lim2) -+ if (*n++) -+ return 0; -+ if (masks_are_equal && (longer < 0)) -+ for (lim2 = m - longer; m < lim2; ) -+ if (*m++) -+ return 1; -+ return (!masks_are_equal); -+} -+ -+ -+struct radij_node * -+rj_match(v_arg, head) -+ void *v_arg; -+ struct radij_node_head *head; -+{ -+ caddr_t v = v_arg; -+ register struct radij_node *t = head->rnh_treetop, *x; -+ register caddr_t cp = v, cp2, cp3; -+ caddr_t cplim, mstart; -+ struct radij_node *saved_t, *top = t; -+ int off = t->rj_off, vlen = *(u_char *)cp, matched_off; -+ -+ /* -+ * Open code rj_search(v, top) to avoid overhead of extra -+ * subroutine call. -+ */ -+ for (; t->rj_b >= 0; ) { -+ if (t->rj_bmask & cp[t->rj_off]) -+ t = t->rj_r; -+ else -+ t = t->rj_l; -+ } -+ /* -+ * See if we match exactly as a host destination -+ */ -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:rj_match: " -+ "* See if we match exactly as a host destination\n"); -+ -+ cp += off; cp2 = t->rj_key + off; cplim = v + vlen; -+ for (; cp < cplim; cp++, cp2++) -+ if (*cp != *cp2) -+ goto on1; -+ /* -+ * This extra grot is in case we are explicitly asked -+ * to look up the default. Ugh! -+ */ -+ if ((t->rj_flags & RJF_ROOT) && t->rj_dupedkey) -+ t = t->rj_dupedkey; -+ return t; -+on1: -+ matched_off = cp - v; -+ saved_t = t; -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:rj_match: " -+ "** try to match a leaf, t=0p%p\n", t); -+ do { -+ if (t->rj_mask) { -+ /* -+ * Even if we don't match exactly as a hosts; -+ * we may match if the leaf we wound up at is -+ * a route to a net. -+ */ -+ cp3 = matched_off + t->rj_mask; -+ cp2 = matched_off + t->rj_key; -+ for (; cp < cplim; cp++) -+ if ((*cp2++ ^ *cp) & *cp3++) -+ break; -+ if (cp == cplim) -+ return t; -+ cp = matched_off + v; -+ } -+ } while ((t = t->rj_dupedkey)); -+ t = saved_t; -+ /* start searching up the tree */ -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:rj_match: " -+ "*** start searching up the tree, t=0p%p\n", -+ t); -+ do { -+ register struct radij_mask *m; -+ -+ t = t->rj_p; -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:rj_match: " -+ "**** t=0p%p\n", -+ t); -+ if ((m = t->rj_mklist)) { -+ /* -+ * After doing measurements here, it may -+ * turn out to be faster to open code -+ * rj_search_m here instead of always -+ * copying and masking. -+ */ -+ /* off = min(t->rj_off, matched_off); */ -+ off = t->rj_off; -+ if (matched_off < off) -+ off = matched_off; -+ mstart = maskedKey + off; -+ do { -+ cp2 = mstart; -+ cp3 = m->rm_mask + off; -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:rj_match: " -+ "***** cp2=0p%p cp3=0p%p\n", -+ cp2, cp3); -+ for (cp = v + off; cp < cplim;) -+ *cp2++ = *cp++ & *cp3++; -+ x = rj_search(maskedKey, t); -+ while (x && x->rj_mask != m->rm_mask) -+ x = x->rj_dupedkey; -+ if (x && -+ (Bcmp(mstart, x->rj_key + off, -+ vlen - off) == 0)) -+ return x; -+ } while ((m = m->rm_mklist)); -+ } -+ } while (t != top); -+ KLIPS_PRINT(debug_radij, -+ "klips_debug:rj_match: " -+ "***** not found.\n"); -+ return 0; -+}; -+ -+#ifdef RJ_DEBUG -+int rj_nodenum; -+struct radij_node *rj_clist; -+int rj_saveinfo; -+DEBUG_NO_STATIC void traverse(struct radij_node *); -+#ifdef RJ_DEBUG2 -+int rj_debug = 1; -+#else -+int rj_debug = 0; -+#endif /* RJ_DEBUG2 */ -+#endif /* RJ_DEBUG */ -+ -+struct radij_node * -+rj_newpair(v, b, nodes) -+ void *v; -+ int b; -+ struct radij_node nodes[2]; -+{ -+ register struct radij_node *tt = nodes, *t = tt + 1; -+ t->rj_b = b; t->rj_bmask = 0x80 >> (b & 7); -+ t->rj_l = tt; t->rj_off = b >> 3; -+ tt->rj_b = -1; tt->rj_key = (caddr_t)v; tt->rj_p = t; -+ tt->rj_flags = t->rj_flags = RJF_ACTIVE; -+#ifdef RJ_DEBUG -+ tt->rj_info = rj_nodenum++; t->rj_info = rj_nodenum++; -+ tt->rj_twin = t; tt->rj_ybro = rj_clist; rj_clist = tt; -+#endif /* RJ_DEBUG */ -+ return t; -+} -+ -+struct radij_node * -+rj_insert(v_arg, head, dupentry, nodes) -+ void *v_arg; -+ struct radij_node_head *head; -+ int *dupentry; -+ struct radij_node nodes[2]; -+{ -+ caddr_t v = v_arg; -+ struct radij_node *top = head->rnh_treetop; -+ int head_off = top->rj_off, vlen = (int)*((u_char *)v); -+ register struct radij_node *t = rj_search(v_arg, top); -+ register caddr_t cp = v + head_off; -+ register int b; -+ struct radij_node *tt; -+ /* -+ *find first bit at which v and t->rj_key differ -+ */ -+ { -+ register caddr_t cp2 = t->rj_key + head_off; -+ register int cmp_res; -+ caddr_t cplim = v + vlen; -+ -+ while (cp < cplim) -+ if (*cp2++ != *cp++) -+ goto on1; -+ *dupentry = 1; -+ return t; -+on1: -+ *dupentry = 0; -+ cmp_res = (cp[-1] ^ cp2[-1]) & 0xff; -+ for (b = (cp - v) << 3; cmp_res; b--) -+ cmp_res >>= 1; -+ } -+ { -+ register struct radij_node *p, *x = top; -+ cp = v; -+ do { -+ p = x; -+ if (cp[x->rj_off] & x->rj_bmask) -+ x = x->rj_r; -+ else x = x->rj_l; -+ } while (b > (unsigned) x->rj_b); /* x->rj_b < b && x->rj_b >= 0 */ -+#ifdef RJ_DEBUG -+ if (rj_debug) -+ printk("klips_debug:rj_insert: Going In:\n"), traverse(p); -+#endif /* RJ_DEBUG */ -+ t = rj_newpair(v_arg, b, nodes); tt = t->rj_l; -+ if ((cp[p->rj_off] & p->rj_bmask) == 0) -+ p->rj_l = t; -+ else -+ p->rj_r = t; -+ x->rj_p = t; t->rj_p = p; /* frees x, p as temp vars below */ -+ if ((cp[t->rj_off] & t->rj_bmask) == 0) { -+ t->rj_r = x; -+ } else { -+ t->rj_r = tt; t->rj_l = x; -+ } -+#ifdef RJ_DEBUG -+ if (rj_debug) -+ printk("klips_debug:rj_insert: Coming out:\n"), traverse(p); -+#endif /* RJ_DEBUG */ -+ } -+ return (tt); -+} -+ -+struct radij_node * -+rj_addmask(n_arg, search, skip) -+ int search, skip; -+ void *n_arg; -+{ -+ caddr_t netmask = (caddr_t)n_arg; -+ register struct radij_node *x; -+ register caddr_t cp, cplim; -+ register int b, mlen, j; -+ int maskduplicated; -+ -+ mlen = *(u_char *)netmask; -+ if (search) { -+ x = rj_search(netmask, rj_masktop); -+ mlen = *(u_char *)netmask; -+ if (Bcmp(netmask, x->rj_key, mlen) == 0) -+ return (x); -+ } -+ R_Malloc(x, struct radij_node *, maj_keylen + 2 * sizeof (*x)); -+ if (x == 0) -+ return (0); -+ Bzero(x, maj_keylen + 2 * sizeof (*x)); -+ cp = (caddr_t)(x + 2); -+ Bcopy(netmask, cp, mlen); -+ netmask = cp; -+ x = rj_insert(netmask, mask_rjhead, &maskduplicated, x); -+ /* -+ * Calculate index of mask. -+ */ -+ cplim = netmask + mlen; -+ for (cp = netmask + skip; cp < cplim; cp++) -+ if (*(u_char *)cp != 0xff) -+ break; -+ b = (cp - netmask) << 3; -+ if (cp != cplim) { -+ if (*cp != 0) { -+ gotOddMasks = 1; -+ for (j = 0x80; j; b++, j >>= 1) -+ if ((j & *cp) == 0) -+ break; -+ } -+ } -+ x->rj_b = -1 - b; -+ return (x); -+} -+ -+#if 0 -+struct radij_node * -+#endif -+int -+rj_addroute(v_arg, n_arg, head, treenodes) -+ void *v_arg, *n_arg; -+ struct radij_node_head *head; -+ struct radij_node treenodes[2]; -+{ -+ caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg; -+ register struct radij_node *t, *x=NULL, *tt; -+ struct radij_node *saved_tt, *top = head->rnh_treetop; -+ short b = 0, b_leaf; -+ int mlen, keyduplicated; -+ caddr_t cplim; -+ struct radij_mask *m, **mp; -+ -+ /* -+ * In dealing with non-contiguous masks, there may be -+ * many different routes which have the same mask. -+ * We will find it useful to have a unique pointer to -+ * the mask to speed avoiding duplicate references at -+ * nodes and possibly save time in calculating indices. -+ */ -+ if (netmask) { -+ x = rj_search(netmask, rj_masktop); -+ mlen = *(u_char *)netmask; -+ if (Bcmp(netmask, x->rj_key, mlen) != 0) { -+ x = rj_addmask(netmask, 0, top->rj_off); -+ if (x == 0) -+ return -ENOMEM; /* (0) rgb */ -+ } -+ netmask = x->rj_key; -+ b = -1 - x->rj_b; -+ } -+ /* -+ * Deal with duplicated keys: attach node to previous instance -+ */ -+ saved_tt = tt = rj_insert(v, head, &keyduplicated, treenodes); -+#ifdef RJ_DEBUG -+ printk("addkey: duplicated: %d\n", keyduplicated); -+#endif -+ if (keyduplicated) { -+ do { -+ if (tt->rj_mask == netmask) -+ return -EEXIST; /* -ENXIO; (0) rgb */ -+ t = tt; -+ if (netmask == 0 || -+ (tt->rj_mask && rj_refines(netmask, tt->rj_mask))) -+ break; -+ } while ((tt = tt->rj_dupedkey)); -+ /* -+ * If the mask is not duplicated, we wouldn't -+ * find it among possible duplicate key entries -+ * anyway, so the above test doesn't hurt. -+ * -+ * We sort the masks for a duplicated key the same way as -+ * in a masklist -- most specific to least specific. -+ * This may require the unfortunate nuisance of relocating -+ * the head of the list. -+ */ -+ if (tt && t == saved_tt) { -+ struct radij_node *xx = x; -+ /* link in at head of list */ -+ (tt = treenodes)->rj_dupedkey = t; -+ tt->rj_flags = t->rj_flags; -+ tt->rj_p = x = t->rj_p; -+ if (x->rj_l == t) x->rj_l = tt; else x->rj_r = tt; -+ saved_tt = tt; x = xx; -+ } else { -+ (tt = treenodes)->rj_dupedkey = t->rj_dupedkey; -+ t->rj_dupedkey = tt; -+ } -+#ifdef RJ_DEBUG -+ t=tt+1; tt->rj_info = rj_nodenum++; t->rj_info = rj_nodenum++; -+ tt->rj_twin = t; tt->rj_ybro = rj_clist; rj_clist = tt; -+#endif /* RJ_DEBUG */ -+ t = saved_tt; -+ tt->rj_key = (caddr_t) v; -+ tt->rj_b = -1; -+ tt->rj_flags = t->rj_flags & ~RJF_ROOT; -+ } -+ /* -+ * Put mask in tree. -+ */ -+ if (netmask) { -+ tt->rj_mask = netmask; -+ tt->rj_b = x->rj_b; -+ } -+ t = saved_tt->rj_p; -+ b_leaf = -1 - t->rj_b; -+ if (t->rj_r == saved_tt) x = t->rj_l; else x = t->rj_r; -+ /* Promote general routes from below */ -+ if (x->rj_b < 0) { -+ if (x->rj_mask && (x->rj_b >= b_leaf) && x->rj_mklist == 0) { -+ MKGet(m); -+ if (m) { -+ Bzero(m, sizeof *m); -+ m->rm_b = x->rj_b; -+ m->rm_mask = x->rj_mask; -+ x->rj_mklist = t->rj_mklist = m; -+ } -+ } -+ } else if (x->rj_mklist) { -+ /* -+ * Skip over masks whose index is > that of new node -+ */ -+ for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist) -+ if (m->rm_b >= b_leaf) -+ break; -+ t->rj_mklist = m; *mp = 0; -+ } -+ /* Add new route to highest possible ancestor's list */ -+ if ((netmask == 0) || (b > t->rj_b )) { -+#ifdef RJ_DEBUG -+ printk("klips:radij.c: netmask = %p or b(%d)>t->rjb(%d)\n", netmask, b, t->rj_b); -+#endif -+ return 0; /* tt rgb */ /* can't lift at all */ -+ } -+ b_leaf = tt->rj_b; -+ do { -+ x = t; -+ t = t->rj_p; -+ } while (b <= t->rj_b && x != top); -+ /* -+ * Search through routes associated with node to -+ * insert new route according to index. -+ * For nodes of equal index, place more specific -+ * masks first. -+ */ -+ cplim = netmask + mlen; -+ for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist) { -+ if (m->rm_b < b_leaf) -+ continue; -+ if (m->rm_b > b_leaf) -+ break; -+ if (m->rm_mask == netmask) { -+ m->rm_refs++; -+ tt->rj_mklist = m; -+#ifdef RJ_DEBUG -+ printk("klips:radij.c: m->rm_mask %p == netmask\n", netmask); -+#endif -+ return 0; /* tt rgb */ -+ } -+ if (rj_refines(netmask, m->rm_mask)) -+ break; -+ } -+ MKGet(m); -+ if (m == 0) { -+ printk("klips_debug:rj_addroute: " -+ "Mask for route not entered\n"); -+ return 0; /* (tt) rgb */ -+ } -+ Bzero(m, sizeof *m); -+ m->rm_b = b_leaf; -+ m->rm_mask = netmask; -+ m->rm_mklist = *mp; -+ *mp = m; -+ tt->rj_mklist = m; -+#ifdef RJ_DEBUG -+ printk("klips:radij.c: addroute done\n"); -+#endif -+ return 0; /* tt rgb */ -+} -+ -+int -+rj_delete(v_arg, netmask_arg, head, node) -+ void *v_arg, *netmask_arg; -+ struct radij_node_head *head; -+ struct radij_node **node; -+{ -+ register struct radij_node *t, *p, *x, *tt; -+ struct radij_mask *m, *saved_m, **mp; -+ struct radij_node *dupedkey, *saved_tt, *top; -+ caddr_t v, netmask; -+ int b, head_off, vlen; -+ -+ v = v_arg; -+ netmask = netmask_arg; -+ x = head->rnh_treetop; -+ tt = rj_search(v, x); -+ head_off = x->rj_off; -+ vlen = *(u_char *)v; -+ saved_tt = tt; -+ top = x; -+ if (tt == 0 || -+ Bcmp(v + head_off, tt->rj_key + head_off, vlen - head_off)) -+ return -EFAULT; /* (0) rgb */ -+ /* -+ * Delete our route from mask lists. -+ */ -+ if ((dupedkey = tt->rj_dupedkey)) { -+ if (netmask) -+ netmask = rj_search(netmask, rj_masktop)->rj_key; -+ while (tt->rj_mask != netmask) -+ if ((tt = tt->rj_dupedkey) == 0) -+ return -ENOENT; /* -ENXIO; (0) rgb */ -+ } -+ if (tt->rj_mask == 0 || (saved_m = m = tt->rj_mklist) == 0) -+ goto on1; -+ if (m->rm_mask != tt->rj_mask) { -+ printk("klips_debug:rj_delete: " -+ "inconsistent annotation\n"); -+ goto on1; -+ } -+ if (--m->rm_refs >= 0) -+ goto on1; -+ b = -1 - tt->rj_b; -+ t = saved_tt->rj_p; -+ if (b > t->rj_b) -+ goto on1; /* Wasn't lifted at all */ -+ do { -+ x = t; -+ t = t->rj_p; -+ } while (b <= t->rj_b && x != top); -+ for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist) -+ if (m == saved_m) { -+ *mp = m->rm_mklist; -+ MKFree(m); -+ break; -+ } -+ if (m == 0) -+ printk("klips_debug:rj_delete: " -+ "couldn't find our annotation\n"); -+on1: -+ /* -+ * Eliminate us from tree -+ */ -+ if (tt->rj_flags & RJF_ROOT) -+ return -EFAULT; /* (0) rgb */ -+#ifdef RJ_DEBUG -+ /* Get us out of the creation list */ -+ for (t = rj_clist; t && t->rj_ybro != tt; t = t->rj_ybro) {} -+ if (t) t->rj_ybro = tt->rj_ybro; -+#endif /* RJ_DEBUG */ -+ t = tt->rj_p; -+ if (dupedkey) { -+ if (tt == saved_tt) { -+ x = dupedkey; x->rj_p = t; -+ if (t->rj_l == tt) t->rj_l = x; else t->rj_r = x; -+ } else { -+ for (x = p = saved_tt; p && p->rj_dupedkey != tt;) -+ p = p->rj_dupedkey; -+ if (p) p->rj_dupedkey = tt->rj_dupedkey; -+ else printk("klips_debug:rj_delete: " -+ "couldn't find node that we started with\n"); -+ } -+ t = tt + 1; -+ if (t->rj_flags & RJF_ACTIVE) { -+#ifndef RJ_DEBUG -+ *++x = *t; p = t->rj_p; -+#else -+ b = t->rj_info; *++x = *t; t->rj_info = b; p = t->rj_p; -+#endif /* RJ_DEBUG */ -+ if (p->rj_l == t) p->rj_l = x; else p->rj_r = x; -+ x->rj_l->rj_p = x; x->rj_r->rj_p = x; -+ } -+ goto out; -+ } -+ if (t->rj_l == tt) x = t->rj_r; else x = t->rj_l; -+ p = t->rj_p; -+ if (p->rj_r == t) p->rj_r = x; else p->rj_l = x; -+ x->rj_p = p; -+ /* -+ * Demote routes attached to us. -+ */ -+ if (t->rj_mklist) { -+ if (x->rj_b >= 0) { -+ for (mp = &x->rj_mklist; (m = *mp);) -+ mp = &m->rm_mklist; -+ *mp = t->rj_mklist; -+ } else { -+ for (m = t->rj_mklist; m;) { -+ struct radij_mask *mm = m->rm_mklist; -+ if (m == x->rj_mklist && (--(m->rm_refs) < 0)) { -+ x->rj_mklist = 0; -+ MKFree(m); -+ } else -+ printk("klips_debug:rj_delete: " -+ "Orphaned Mask 0p%p at 0p%p\n", m, x); -+ m = mm; -+ } -+ } -+ } -+ /* -+ * We may be holding an active internal node in the tree. -+ */ -+ x = tt + 1; -+ if (t != x) { -+#ifndef RJ_DEBUG -+ *t = *x; -+#else -+ b = t->rj_info; *t = *x; t->rj_info = b; -+#endif /* RJ_DEBUG */ -+ t->rj_l->rj_p = t; t->rj_r->rj_p = t; -+ p = x->rj_p; -+ if (p->rj_l == x) p->rj_l = t; else p->rj_r = t; -+ } -+out: -+ tt->rj_flags &= ~RJF_ACTIVE; -+ tt[1].rj_flags &= ~RJF_ACTIVE; -+ *node = tt; -+ return 0; /* (tt) rgb */ -+} -+ -+int -+rj_walktree(h, f, w) -+ struct radij_node_head *h; -+ register int (*f)(struct radij_node *,void *); -+ void *w; -+{ -+ int error; -+ struct radij_node *base, *next; -+ register struct radij_node *rn; -+ -+ if(!h || !f /* || !w */) { -+ return -ENODATA; -+ } -+ -+ rn = h->rnh_treetop; -+ /* -+ * This gets complicated because we may delete the node -+ * while applying the function f to it, so we need to calculate -+ * the successor node in advance. -+ */ -+ /* First time through node, go left */ -+ while (rn->rj_b >= 0) -+ rn = rn->rj_l; -+ for (;;) { -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_radij) { -+ printk("klips_debug:rj_walktree: " -+ "for: rn=0p%p rj_b=%d rj_flags=%x", -+ rn, -+ rn->rj_b, -+ rn->rj_flags); -+ rn->rj_b >= 0 ? -+ printk(" node off=%x\n", -+ rn->rj_off) : -+ printk(" leaf key = %08x->%08x\n", -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr), -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr)) -+ ; -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ base = rn; -+ /* If at right child go back up, otherwise, go right */ -+ while (rn->rj_p->rj_r == rn && (rn->rj_flags & RJF_ROOT) == 0) -+ rn = rn->rj_p; -+ /* Find the next *leaf* since next node might vanish, too */ -+ for (rn = rn->rj_p->rj_r; rn->rj_b >= 0;) -+ rn = rn->rj_l; -+ next = rn; -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_radij) { -+ printk("klips_debug:rj_walktree: " -+ "processing leaves, rn=0p%p rj_b=%d rj_flags=%x", -+ rn, -+ rn->rj_b, -+ rn->rj_flags); -+ rn->rj_b >= 0 ? -+ printk(" node off=%x\n", -+ rn->rj_off) : -+ printk(" leaf key = %08x->%08x\n", -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr), -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr)) -+ ; -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ /* Process leaves */ -+ while ((rn = base)) { -+ base = rn->rj_dupedkey; -+#ifdef CONFIG_IPSEC_DEBUG -+ if(debug_radij) { -+ printk("klips_debug:rj_walktree: " -+ "while: base=0p%p rn=0p%p rj_b=%d rj_flags=%x", -+ base, -+ rn, -+ rn->rj_b, -+ rn->rj_flags); -+ rn->rj_b >= 0 ? -+ printk(" node off=%x\n", -+ rn->rj_off) : -+ printk(" leaf key = %08x->%08x\n", -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr), -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr)) -+ ; -+ } -+#endif /* CONFIG_IPSEC_DEBUG */ -+ if (!(rn->rj_flags & RJF_ROOT) && (error = (*f)(rn, w))) -+ return (-error); -+ } -+ rn = next; -+ if (rn->rj_flags & RJF_ROOT) -+ return (0); -+ } -+ /* NOTREACHED */ -+} -+ -+int -+rj_inithead(head, off) -+ void **head; -+ int off; -+{ -+ register struct radij_node_head *rnh; -+ register struct radij_node *t, *tt, *ttt; -+ if (*head) -+ return (1); -+ R_Malloc(rnh, struct radij_node_head *, sizeof (*rnh)); -+ if (rnh == NULL) -+ return (0); -+ Bzero(rnh, sizeof (*rnh)); -+ *head = rnh; -+ t = rj_newpair(rj_zeroes, off, rnh->rnh_nodes); -+ ttt = rnh->rnh_nodes + 2; -+ t->rj_r = ttt; -+ t->rj_p = t; -+ tt = t->rj_l; -+ tt->rj_flags = t->rj_flags = RJF_ROOT | RJF_ACTIVE; -+ tt->rj_b = -1 - off; -+ *ttt = *tt; -+ ttt->rj_key = rj_ones; -+ rnh->rnh_addaddr = rj_addroute; -+ rnh->rnh_deladdr = rj_delete; -+ rnh->rnh_matchaddr = rj_match; -+ rnh->rnh_walktree = rj_walktree; -+ rnh->rnh_treetop = t; -+ return (1); -+} -+ -+void -+rj_init() -+{ -+ char *cp, *cplim; -+ -+ if (maj_keylen == 0) { -+ printk("klips_debug:rj_init: " -+ "radij functions require maj_keylen be set\n"); -+ return; -+ } -+ R_Malloc(rj_zeroes, char *, 3 * maj_keylen); -+ if (rj_zeroes == NULL) -+ panic("rj_init"); -+ Bzero(rj_zeroes, 3 * maj_keylen); -+ rj_ones = cp = rj_zeroes + maj_keylen; -+ maskedKey = cplim = rj_ones + maj_keylen; -+ while (cp < cplim) -+ *cp++ = -1; -+ if (rj_inithead((void **)&mask_rjhead, 0) == 0) -+ panic("rj_init 2"); -+} -+ -+void -+rj_preorder(struct radij_node *rn, int l) -+{ -+ int i; -+ -+ if (rn == NULL){ -+ printk("klips_debug:rj_preorder: " -+ "NULL pointer\n"); -+ return; -+ } -+ -+ if (rn->rj_b >= 0){ -+ rj_preorder(rn->rj_l, l+1); -+ rj_preorder(rn->rj_r, l+1); -+ printk("klips_debug:"); -+ for (i=0; irj_off); -+ } else { -+ printk("klips_debug:"); -+ for (i=0; irj_flags); -+ if (rn->rj_flags & RJF_ACTIVE) { -+ printk(" @key=0p%p", -+ rn->rj_key); -+ printk(" key = %08x->%08x", -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr), -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr)); -+ printk(" @mask=0p%p", -+ rn->rj_mask); -+ if (rn->rj_mask) -+ printk(" mask = %08x->%08x", -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_mask)->sen_ip_src.s_addr), -+ (u_int)ntohl(((struct sockaddr_encap *)rn->rj_mask)->sen_ip_dst.s_addr)); -+ if (rn->rj_dupedkey) -+ printk(" dupedkey = 0p%p", -+ rn->rj_dupedkey); -+ } -+ printk("\n"); -+ } -+} -+ -+#ifdef RJ_DEBUG -+DEBUG_NO_STATIC void traverse(struct radij_node *p) -+{ -+ rj_preorder(p, 0); -+} -+#endif /* RJ_DEBUG */ -+ -+void -+rj_dumptrees(void) -+{ -+ rj_preorder(rnh->rnh_treetop, 0); -+} -+ -+void -+rj_free_mkfreelist(void) -+{ -+ struct radij_mask *mknp, *mknp2; -+ -+ mknp = rj_mkfreelist; -+ while(mknp) -+ { -+ mknp2 = mknp; -+ mknp = mknp->rm_mklist; -+ kfree(mknp2); -+ } -+} -+ -+int -+radijcleartree(void) -+{ -+ return rj_walktree(rnh, ipsec_rj_walker_delete, NULL); -+} -+ -+int -+radijcleanup(void) -+{ -+ int error = 0; -+ -+ error = radijcleartree(); -+ -+ rj_free_mkfreelist(); -+ -+/* rj_walktree(mask_rjhead, ipsec_rj_walker_delete, NULL); */ -+ if(mask_rjhead) { -+ kfree(mask_rjhead); -+ } -+ -+ if(rj_zeroes) { -+ kfree(rj_zeroes); -+ } -+ -+ if(rnh) { -+ kfree(rnh); -+ } -+ -+ return error; -+} -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.46 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.45 2003/10/31 02:27:55 mcr -+ * pulled up port-selector patches and sa_id elimination. -+ * -+ * Revision 1.44.30.1 2003/10/29 01:30:41 mcr -+ * elimited "struct sa_id". -+ * -+ * Revision 1.44 2002/07/24 18:44:54 rgb -+ * Type fiddling to tame ia64 compiler. -+ * -+ * Revision 1.43 2002/05/23 07:14:11 rgb -+ * Cleaned up %p variants to 0p%p for test suite cleanup. -+ * -+ * Revision 1.42 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.41 2002/04/24 07:36:35 mcr -+ * Moved from ./klips/net/ipsec/radij.c,v -+ * -+ * Revision 1.40 2002/01/29 17:17:58 mcr -+ * moved include of ipsec_param.h to after include of linux/kernel.h -+ * otherwise, it seems that some option that is set in ipsec_param.h -+ * screws up something subtle in the include path to kernel.h, and -+ * it complains on the snprintf() prototype. -+ * -+ * Revision 1.39 2002/01/29 04:00:55 mcr -+ * more excise of kversions.h header. -+ * -+ * Revision 1.38 2002/01/29 02:13:19 mcr -+ * introduction of ipsec_kversion.h means that include of -+ * ipsec_param.h must preceed any decisions about what files to -+ * include to deal with differences in kernel source. -+ * -+ * Revision 1.37 2001/10/18 04:45:23 rgb -+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h, -+ * lib/freeswan.h version macros moved to lib/kversions.h. -+ * Other compiler directive cleanups. -+ * -+ * Revision 1.36 2001/08/22 13:43:51 henry -+ * eliminate the single use of min() to avoid problems with Linus changing it -+ * -+ * Revision 1.35 2001/06/15 04:57:29 rgb -+ * Clarified error return codes. -+ * Changed mask add already exists to EEXIST. -+ * Changed mask delete did not exist to ENOENT. -+ * -+ * Revision 1.34 2001/05/03 19:44:26 rgb -+ * Fix sign of error return codes for rj_addroute(). -+ * -+ * Revision 1.33 2001/02/27 22:24:56 rgb -+ * Re-formatting debug output (line-splitting, joining, 1arg/line). -+ * Check for satoa() return codes. -+ * -+ * Revision 1.32 2001/02/27 06:23:15 rgb -+ * Debug line splitting. -+ * -+ * Revision 1.31 2000/11/06 04:35:21 rgb -+ * Clear table *before* releasing other items in radijcleanup. -+ * -+ * Revision 1.30 2000/09/20 04:07:40 rgb -+ * Changed static functions to DEBUG_NO_STATIC to reveal function names in -+ * oopsen. -+ * -+ * Revision 1.29 2000/09/12 03:25:02 rgb -+ * Moved radij_c_version printing to ipsec_version_get_info(). -+ * -+ * Revision 1.28 2000/09/08 19:12:56 rgb -+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG. -+ * -+ * Revision 1.27 2000/07/28 14:58:32 rgb -+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5. -+ * -+ * Revision 1.26 2000/05/10 23:11:37 rgb -+ * Comment out most of the startup version information. -+ * -+ * Revision 1.25 2000/01/21 06:21:47 rgb -+ * Change return codes to negative on error. -+ * -+ * Revision 1.24 1999/11/18 04:09:20 rgb -+ * Replaced all kernel version macros to shorter, readable form. -+ * -+ * Revision 1.23 1999/11/17 15:53:41 rgb -+ * Changed all occurrences of #include "../../../lib/freeswan.h" -+ * to #include which works due to -Ilibfreeswan in the -+ * klips/net/ipsec/Makefile. -+ * -+ * Revision 1.22 1999/10/15 22:17:28 rgb -+ * Modify radijcleanup() to call radijcleartree(). -+ * -+ * Revision 1.21 1999/10/08 18:37:34 rgb -+ * Fix end-of-line spacing to sate whining PHMs. -+ * -+ * Revision 1.20 1999/10/01 15:44:54 rgb -+ * Move spinlock header include to 2.1> scope. -+ * -+ * Revision 1.19 1999/10/01 08:35:52 rgb -+ * Add spinlock include to shut up compiler for 2.0.38. -+ * -+ * Revision 1.18 1999/09/23 18:02:52 rgb -+ * De-alarm the search failure message so it doesn't sound so grave. -+ * -+ * Revision 1.17 1999/05/25 21:26:01 rgb -+ * Fix rj_walktree() sanity checking bug. -+ * -+ * Revision 1.16 1999/05/09 03:25:38 rgb -+ * Fix bug introduced by 2.2 quick-and-dirty patch. -+ * -+ * Revision 1.15 1999/05/05 22:02:33 rgb -+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher . -+ * -+ * Revision 1.14 1999/04/29 15:24:15 rgb -+ * Add sanity checking for null pointer arguments. -+ * Standardise an error return method. -+ * -+ * Revision 1.13 1999/04/11 00:29:02 henry -+ * GPL boilerplate -+ * -+ * Revision 1.12 1999/04/06 04:54:28 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ * Revision 1.11 1999/02/17 16:52:53 rgb -+ * Convert DEBUG_IPSEC to KLIPS_PRINT -+ * Clean out unused cruft. -+ * -+ * Revision 1.10 1999/01/22 06:30:05 rgb -+ * Cruft clean-out. -+ * 64-bit clean-up. -+ * -+ * Revision 1.9 1998/12/01 13:22:04 rgb -+ * Added support for debug printing of version info. -+ * -+ * Revision 1.8 1998/11/30 13:22:55 rgb -+ * Rationalised all the klips kernel file headers. They are much shorter -+ * now and won't conflict under RH5.2. -+ * -+ * Revision 1.7 1998/10/25 02:43:26 rgb -+ * Change return type on rj_addroute and rj_delete and add and argument -+ * to the latter to be able to transmit more infomation about errors. -+ * -+ * Revision 1.6 1998/10/19 14:30:06 rgb -+ * Added inclusion of freeswan.h. -+ * -+ * Revision 1.5 1998/10/09 04:33:27 rgb -+ * Added 'klips_debug' prefix to all klips printk debug statements. -+ * Fixed output formatting slightly. -+ * -+ * Revision 1.4 1998/07/28 00:06:59 rgb -+ * Add debug detail to tree traversing. -+ * -+ * Revision 1.3 1998/07/14 18:07:58 rgb -+ * Add a routine to clear the eroute tree. -+ * -+ * Revision 1.2 1998/06/25 20:03:22 rgb -+ * Cleanup #endif comments. Debug output for rj_init. -+ * -+ * Revision 1.1 1998/06/18 21:30:22 henry -+ * move sources from klips/src to klips/net/ipsec to keep stupid kernel -+ * build scripts happier about symlinks -+ * -+ * Revision 1.8 1998/05/25 20:34:15 rgb -+ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions. -+ * -+ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and -+ * add ipsec_rj_walker_delete. -+ * -+ * Recover memory for eroute table on unload of module. -+ * -+ * Revision 1.7 1998/05/21 12:58:58 rgb -+ * Moved 'extern' definitions to ipsec_radij.h to support /proc 3k limit fix. -+ * -+ * Revision 1.6 1998/04/23 20:57:29 rgb -+ * Cleaned up compiler warnings for unused debugging functions. -+ * -+ * Revision 1.5 1998/04/22 16:51:38 rgb -+ * Tidy up radij debug code from recent rash of modifications to debug code. -+ * -+ * Revision 1.4 1998/04/21 21:28:56 rgb -+ * Rearrange debug switches to change on the fly debug output from user -+ * space. Only kernel changes checked in at this time. radij.c was also -+ * changed to temporarily remove buggy debugging code in rj_delete causing -+ * an OOPS and hence, netlink device open errors. -+ * -+ * Revision 1.3 1998/04/14 17:30:37 rgb -+ * Fix up compiling errors for radij tree memory reclamation. -+ * -+ * Revision 1.2 1998/04/12 22:03:25 rgb -+ * Updated ESP-3DES-HMAC-MD5-96, -+ * ESP-DES-HMAC-MD5-96, -+ * AH-HMAC-MD5-96, -+ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository -+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts. -+ * -+ * Fixed eroute references in /proc/net/ipsec*. -+ * -+ * Started to patch module unloading memory leaks in ipsec_netlink and -+ * radij tree unloading. -+ * -+ * Revision 1.1 1998/04/09 03:06:15 henry -+ * sources moved up from linux/net/ipsec -+ * -+ * Revision 1.1.1.1 1998/04/08 05:35:03 henry -+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8 -+ * -+ * Revision 0.4 1997/01/15 01:28:15 ji -+ * No changes. -+ * -+ * Revision 0.3 1996/11/20 14:39:04 ji -+ * Minor cleanups. -+ * Rationalized debugging code. -+ * -+ * Revision 0.2 1996/11/02 00:18:33 ji -+ * First limited release. -+ * -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/sysctl_net_ipsec.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,196 @@ -+/* -+ * sysctl interface to net IPSEC subsystem. -+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in 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. -+ * -+ * RCSID $Id$ -+ */ -+ -+/* -*- linux-c -*- -+ * -+ * Initiated April 3, 1998, Richard Guy Briggs -+ */ -+ -+#include -+#include -+ -+#include "openswan/ipsec_param.h" -+ -+#ifdef CONFIG_SYSCTL -+ -+#define NET_IPSEC 2112 /* Random number */ -+#ifdef CONFIG_IPSEC_DEBUG -+extern int debug_ah; -+extern int debug_esp; -+extern int debug_tunnel; -+extern int debug_eroute; -+extern int debug_spi; -+extern int debug_radij; -+extern int debug_netlink; -+extern int debug_xform; -+extern int debug_rcv; -+extern int debug_pfkey; -+extern int sysctl_ipsec_debug_verbose; -+#ifdef CONFIG_IPSEC_IPCOMP -+extern int sysctl_ipsec_debug_ipcomp; -+#endif /* CONFIG_IPSEC_IPCOMP */ -+#endif /* CONFIG_IPSEC_DEBUG */ -+ -+extern int sysctl_ipsec_icmp; -+extern int sysctl_ipsec_inbound_policy_check; -+extern int sysctl_ipsec_tos; -+int sysctl_ipsec_regress_pfkey_lossage; -+ -+enum { -+#ifdef CONFIG_IPSEC_DEBUG -+ NET_IPSEC_DEBUG_AH=1, -+ NET_IPSEC_DEBUG_ESP=2, -+ NET_IPSEC_DEBUG_TUNNEL=3, -+ NET_IPSEC_DEBUG_EROUTE=4, -+ NET_IPSEC_DEBUG_SPI=5, -+ NET_IPSEC_DEBUG_RADIJ=6, -+ NET_IPSEC_DEBUG_NETLINK=7, -+ NET_IPSEC_DEBUG_XFORM=8, -+ NET_IPSEC_DEBUG_RCV=9, -+ NET_IPSEC_DEBUG_PFKEY=10, -+ NET_IPSEC_DEBUG_VERBOSE=11, -+ NET_IPSEC_DEBUG_IPCOMP=12, -+#endif /* CONFIG_IPSEC_DEBUG */ -+ NET_IPSEC_ICMP=13, -+ NET_IPSEC_INBOUND_POLICY_CHECK=14, -+ NET_IPSEC_TOS=15, -+ NET_IPSEC_REGRESS_PFKEY_LOSSAGE=16, -+}; -+ -+static ctl_table ipsec_table[] = { -+#ifdef CONFIG_IPSEC_DEBUG -+ { NET_IPSEC_DEBUG_AH, "debug_ah", &debug_ah, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_ESP, "debug_esp", &debug_esp, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_TUNNEL, "debug_tunnel", &debug_tunnel, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_EROUTE, "debug_eroute", &debug_eroute, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_SPI, "debug_spi", &debug_spi, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_RADIJ, "debug_radij", &debug_radij, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_NETLINK, "debug_netlink", &debug_netlink, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_XFORM, "debug_xform", &debug_xform, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_RCV, "debug_rcv", &debug_rcv, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_PFKEY, "debug_pfkey", &debug_pfkey, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_DEBUG_VERBOSE, "debug_verbose",&sysctl_ipsec_debug_verbose, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+#ifdef CONFIG_IPSEC_IPCOMP -+ { NET_IPSEC_DEBUG_IPCOMP, "debug_ipcomp", &sysctl_ipsec_debug_ipcomp, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+#endif /* CONFIG_IPSEC_IPCOMP */ -+ -+#ifdef CONFIG_IPSEC_REGRESS -+ { NET_IPSEC_REGRESS_PFKEY_LOSSAGE, "pfkey_lossage", -+ &sysctl_ipsec_regress_pfkey_lossage, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+#endif /* CONFIG_IPSEC_REGRESS */ -+ -+#endif /* CONFIG_IPSEC_DEBUG */ -+ { NET_IPSEC_ICMP, "icmp", &sysctl_ipsec_icmp, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_INBOUND_POLICY_CHECK, "inbound_policy_check", &sysctl_ipsec_inbound_policy_check, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ { NET_IPSEC_TOS, "tos", &sysctl_ipsec_tos, -+ sizeof(int), 0644, NULL, &proc_dointvec}, -+ {0} -+}; -+ -+static ctl_table ipsec_net_table[] = { -+ { NET_IPSEC, "ipsec", NULL, 0, 0555, ipsec_table }, -+ { 0 } -+}; -+ -+static ctl_table ipsec_root_table[] = { -+ { CTL_NET, "net", NULL, 0, 0555, ipsec_net_table }, -+ { 0 } -+}; -+ -+static struct ctl_table_header *ipsec_table_header; -+ -+int ipsec_sysctl_register(void) -+{ -+ ipsec_table_header = register_sysctl_table(ipsec_root_table, 0); -+ if (!ipsec_table_header) { -+ return -ENOMEM; -+ } -+ return 0; -+} -+ -+void ipsec_sysctl_unregister(void) -+{ -+ unregister_sysctl_table(ipsec_table_header); -+} -+ -+#endif /* CONFIG_SYSCTL */ -+ -+/* -+ * $Log$ -+ * Revision 1.3 2004-11-25 10:19:50 kergoth.com!kergoth -+ * Turn off EOLN_NATIVE flag -+ * -+ * (Logical change 1.5010) -+ * -+ * Revision 1.16 2004/04/06 02:49:26 mcr -+ * pullup of algo code from alg-branch. -+ * -+ * Revision 1.15 2002/04/24 07:55:32 mcr -+ * #include patches and Makefiles for post-reorg compilation. -+ * -+ * Revision 1.14 2002/04/24 07:36:35 mcr -+ * Moved from ./klips/net/ipsec/sysctl_net_ipsec.c,v -+ * -+ * Revision 1.13 2002/01/12 02:58:32 mcr -+ * first regression test causes acquire messages to be lost -+ * 100% of the time. This is to help testing of pluto. -+ * -+ * Revision 1.12 2001/06/14 19:35:13 rgb -+ * Update copyright date. -+ * -+ * Revision 1.11 2001/02/26 19:58:13 rgb -+ * Drop sysctl_ipsec_{no_eroute_pass,opportunistic}, replaced by magic SAs. -+ * -+ * Revision 1.10 2000/09/16 01:50:15 rgb -+ * Protect sysctl_ipsec_debug_ipcomp with compiler defines too so that the -+ * linker won't blame rj_delete() for missing symbols. ;-> Damn statics... -+ * -+ * Revision 1.9 2000/09/15 23:17:51 rgb -+ * Moved stuff around to compile with debug off. -+ * -+ * Revision 1.8 2000/09/15 11:37:02 rgb -+ * Merge in heavily modified Svenning Soerensen's -+ * IPCOMP zlib deflate code. -+ * -+ * Revision 1.7 2000/09/15 07:37:15 rgb -+ * Munged silly log comment that was causing a warning. -+ * -+ * Revision 1.6 2000/09/15 04:58:23 rgb -+ * Added tos runtime switch. -+ * Removed 'sysctl_ipsec_' prefix from /proc/sys/net/ipsec/ filenames. -+ * -+ * Revision 1.5 2000/09/12 03:25:28 rgb -+ * Filled in and implemented sysctl. -+ * -+ * Revision 1.4 1999/04/11 00:29:03 henry -+ * GPL boilerplate -+ * -+ * Revision 1.3 1999/04/06 04:54:29 rgb -+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes -+ * patch shell fixes. -+ * -+ */ ---- /dev/null Tue Mar 11 13:02:56 2003 -+++ linux/net/ipsec/version.c Mon Feb 9 13:51:03 2004 -@@ -0,0 +1,44 @@ -+/* -+ * return IPsec version information -+ * Copyright (C) 2001 Henry Spencer. -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in 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 Library General Public -+ * License for more details. -+ * -+ * RCSID $Id$ -+ */ -+ -+#ifdef __KERNEL__ -+#include -+#endif -+ -+#include "openswan.h" -+ -+#define V "cvs2002Mar12_01:19:03" /* substituted in by Makefile */ -+static const char openswan_number[] = V; -+static const char openswan_string[] = "Openswan " V; -+ -+/* -+ - ipsec_version_code - return IPsec version number/code, as string -+ */ -+const char * -+ipsec_version_code() -+{ -+ return openswan_number; -+} -+ -+/* -+ - ipsec_version_string - return full version string -+ */ -+const char * -+ipsec_version_string() -+{ -+ return openswan_string; -+} -RCSID $Id$ ---- ./net/ipv4/af_inet.c.preipsec Wed Apr 26 15:13:17 2000 -+++ ./net/ipv4/af_inet.c Fri Jun 30 15:01:27 2000 -@@ -1019,6 +1019,17 @@ - ip_mr_init(); - #endif - -+#if defined(CONFIG_IPSEC) -+ { -+ extern /* void */ int ipsec_init(void); -+ /* -+ * Initialise AF_INET ESP and AH protocol support including -+ * e-routing and SA tables -+ */ -+ ipsec_init(); -+ } -+#endif /* CONFIG_IPSEC */ -+ - /* - * Create all the /proc entries. - */ ---- /dev/null Fri May 10 13:59:54 2002 -+++ linux/net/ipsec/Makefile.ver Sun Jul 28 22:10:40 2002 -@@ -0,0 +1 @@ -+IPSECVERSION=cvs2002Mar12_01:19:03 -make[1]: Leaving directory `/data/mtx/oe/tmp/work/openswan-2.2.0-r0/openswan-2.2.0' diff --git a/linux/linux-mtx-1-2.4.27/14-au1000-eth-link-beat.diff b/linux/linux-mtx-1-2.4.27/14-au1000-eth-link-beat.diff deleted file mode 100644 index f848d2a224..0000000000 --- a/linux/linux-mtx-1-2.4.27/14-au1000-eth-link-beat.diff +++ /dev/null @@ -1,64 +0,0 @@ ---- linux/drivers/net/au1000_eth.c.orig 2004-11-23 12:01:00.551663672 +0100 -+++ linux/drivers/net/au1000_eth.c 2004-11-23 12:08:36.795304096 +0100 -@@ -6,7 +6,9 @@ - * Copyright 2002 TimeSys Corp. - * Author: MontaVista Software, Inc. - * ppopov@mvista.com or source@mvista.com -- * -+ * Bjoern Riemer 2004 -+ * riemer@fokus.fraunhofer.de or riemer@riemer-nt.de -+ * // fixed the link beat detection with ioctls (SIOCGMIIPHY) - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it -@@ -1383,6 +1385,10 @@ - aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed); - control = MAC_DISABLE_RX_OWN | MAC_RX_ENABLE | MAC_TX_ENABLE; - #ifndef CONFIG_CPU_LITTLE_ENDIAN -+ /*riemer: fix for startup without cable */ -+ if (!link) -+ dev->flags &= ~IFF_RUNNING; -+ - control |= MAC_BIG_ENDIAN; - #endif - if (link && (dev->if_port == IF_PORT_100BASEFX)) { -@@ -1841,17 +1847,35 @@ - - static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) - { -- //u16 *data = (u16 *)&rq->ifr_data; -+/* -+// This structure is used in all SIOCxMIIxxx ioctl calls -+struct mii_ioctl_data { -+ 0 u16 phy_id; -+ 1 u16 reg_num; -+ 2 u16 val_in; -+ 3 u16 val_out; -+};*/ -+ u16 *data = (u16 *)&rq->ifr_data; -+ struct au1000_private *aup = (struct au1000_private *) dev->priv; -+ //struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data; - - /* fixme */ - switch(cmd) { - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ -- //data[0] = PHY_ADDRESS; -+ case SIOCGMIIPHY: -+ if (!netif_running(dev)) -+ return -EINVAL; -+ data[0] = aup->phy_addr; - case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ -- //data[3] = mdio_read(ioaddr, data[0], data[1]); -+ case SIOCGMIIREG: -+ data[3] = mdio_read(dev, data[0], data[1]); -+ //data->val_out = mdio_read(dev,data->phy_id,data->reg_num); - return 0; - case SIOCDEVPRIVATE+2: /* Write the specified MII register */ -- //mdio_write(ioaddr, data[0], data[1], data[2]); -+ case SIOCSMIIREG: -+ if (!capable(CAP_NET_ADMIN)) -+ return -EPERM; -+ mdio_write(dev, data[0], data[1],data[2]); - return 0; - default: - return -EOPNOTSUPP; diff --git a/linux/linux-mtx-1-2.4.27/15-au1000-pci-fixup-non-coherent-pre-ac.diff b/linux/linux-mtx-1-2.4.27/15-au1000-pci-fixup-non-coherent-pre-ac.diff deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-mtx-1-2.4.27/defconfig-mtx-1 b/linux/linux-mtx-1-2.4.27/defconfig-mtx-1 deleted file mode 100644 index 0afef23a7b..0000000000 --- a/linux/linux-mtx-1-2.4.27/defconfig-mtx-1 +++ /dev/null @@ -1,1200 +0,0 @@ -# -# Automatically generated by make menuconfig: don't edit -# -CONFIG_MIPS=y -CONFIG_MIPS32=y -# CONFIG_MIPS64 is not set - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_MIPS_BOSPORUS is not set -# CONFIG_MIPS_MIRAGE is not set -# CONFIG_MIPS_DB1000 is not set -# CONFIG_MIPS_DB1100 is not set -# CONFIG_MIPS_DB1500 is not set -# CONFIG_MIPS_DB1550 is not set -# CONFIG_MIPS_PB1000 is not set -# CONFIG_MIPS_PB1100 is not set -# CONFIG_MIPS_PB1500 is not set -# CONFIG_MIPS_HYDROGEN3 is not set -# CONFIG_MIPS_PB1550 is not set -# CONFIG_MIPS_XXS1500 is not set -CONFIG_MIPS_MTX1=y -# CONFIG_COGENT_CSB250 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_LASAT is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_MOMENCO_JAGUAR_ATX is not set -# CONFIG_PMC_BIG_SUR is not set -# CONFIG_PMC_STRETCH is not set -# CONFIG_PMC_YOSEMITE is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_NINO is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP27 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -# CONFIG_HIGHMEM is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -CONFIG_SOC_AU1X00=y -CONFIG_SOC_AU1500=y -CONFIG_NONCOHERENT_IO=y -# CONFIG_MIPS_AU1000 is not set - -# -# CPU selection -# -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_RM9000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_PAGE_SIZE_4KB=y -# CONFIG_PAGE_SIZE_16KB is not set -# CONFIG_PAGE_SIZE_64KB is not set -CONFIG_CPU_HAS_PREFETCH=y -# CONFIG_VTAG_ICACHE is not set -CONFIG_64BIT_PHYS_ADDR=y -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -# CONFIG_CPU_HAS_LLDSCD is not set -# CONFIG_CPU_HAS_WB is not set -CONFIG_CPU_HAS_SYNC=y - -# -# General setup -# -CONFIG_CPU_LITTLE_ENDIAN=y -# CONFIG_BUILD_ELF64 is not set -CONFIG_NET=y -CONFIG_PCI=y -CONFIG_PCI_NEW=y -CONFIG_PCI_AUTO=y -CONFIG_PCI_NAMES=y -# CONFIG_ISA is not set -# CONFIG_TC is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set - -# -# PCI Hotplug Support -# -# CONFIG_HOTPLUG_PCI is not set -# CONFIG_HOTPLUG_PCI_COMPAQ is not set -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -# CONFIG_HOTPLUG_PCI_SHPC is not set -# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set -# CONFIG_HOTPLUG_PCI_PCIE is not set -# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_ELF=y -# CONFIG_MIPS32_COMPAT is not set -# CONFIG_MIPS32_O32 is not set -# CONFIG_MIPS32_N32 is not set -# CONFIG_BINFMT_ELF32 is not set -# CONFIG_BINFMT_MISC is not set -# CONFIG_OOM_KILLER is not set -# CONFIG_CMDLINE_BOOL is not set -# CONFIG_PM is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_CMDLINE_PARTS is not set -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_CFI_AMDSTD_RETRY=y -CONFIG_MTD_CFI_AMDSTD_RETRY_MAX=5 -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set -# CONFIG_MTD_JEDEC is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_DB1X00 is not set -CONFIG_MTD_MTX1=y -# CONFIG_MTD_CSTM_MIPS_IXX is not set -# CONFIG_MTD_OCELOT is not set -# CONFIG_MTD_LASAT is not set -# CONFIG_MTD_PCI is not set -# CONFIG_MTD_PCMCIA is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -# CONFIG_MTD_DOCPROBE is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_CISS_MONITOR_THREAD is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_SX8 is not set -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=m -CONFIG_BLK_DEV_RAM_SIZE=4096 -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_BLK_STATS is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -# CONFIG_BLK_DEV_LVM is not set - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=m -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_IP_PIMSM_V2=y -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -CONFIG_SYN_COOKIES=y - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m -# CONFIG_IP_NF_NAT_LOCAL is not set -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m -# CONFIG_IP_NF_COMPAT_IPCHAINS is not set -# CONFIG_IP_NF_COMPAT_IPFWADM is not set - -# -# IP: Virtual Server Configuration -# -# CONFIG_IP_VS is not set -CONFIG_IPV6=m - -# -# IPv6: Netfilter Configuration -# -CONFIG_IP6_NF_QUEUE=m -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -# CONFIG_KHTTPD is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -CONFIG_VLAN_8021Q=m -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m -# CONFIG_NET_SCH_HFSC is not set -CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_RED=m -CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_TEQL=m -CONFIG_NET_SCH_TBF=m -CONFIG_NET_SCH_GRED=m -# CONFIG_NET_SCH_NETEM is not set -CONFIG_NET_SCH_DSMARK=m -CONFIG_NET_SCH_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -CONFIG_NET_CLS_TCINDEX=m -CONFIG_NET_CLS_ROUTE4=m -CONFIG_NET_CLS_ROUTE=y -CONFIG_NET_CLS_FW=m -CONFIG_NET_CLS_U32=m -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -CONFIG_NET_PKTGEN=m -CONFIG_IPSEC_NAT_TRAVERSAL=y -CONFIG_IPSEC=m -CONFIG_IPSEC_IPIP=y -CONFIG_IPSEC_AH=y -CONFIG_IPSEC_AUTH_HMAC_MD5=y -CONFIG_IPSEC_AUTH_HMAC_SHA1=y -CONFIG_IPSEC_ESP=y -CONFIG_IPSEC_ENC_3DES=y -CONFIG_IPSEC_ENC_AES=y -CONFIG_IPSEC_ALG=y -CONFIG_IPSEC_ALG_AES=m -CONFIG_IPSEC_ALG_CRYPTOAPI=m -CONFIG_IPSEC_ALG_NON_LIBRE=y -CONFIG_IPSEC_IPCOMP=y -CONFIG_IPSEC_DEBUG=y - -# -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI support -# -CONFIG_SCSI=m -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=40 -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 -# CONFIG_CHR_DEV_SG is not set -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_MEGARAID2 is not set -# CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_SATA_SVW is not set -# CONFIG_SCSI_SATA_PROMISE is not set -# CONFIG_SCSI_SATA_SX4 is not set -# CONFIG_SCSI_SATA_SIL is not set -# CONFIG_SCSI_SATA_SIS is not set -# CONFIG_SCSI_SATA_VIA is not set -# CONFIG_SCSI_SATA_VITESSE is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_NCR53C8XX is not set -# CONFIG_SCSI_SYM53C8XX is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set -# CONFIG_FUSION_BOOT is not set -# CONFIG_FUSION_ISENSE is not set -# CONFIG_FUSION_CTL is not set -# CONFIG_FUSION_LAN is not set - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -CONFIG_MIPS_AU1X00_ENET=y -# CONFIG_BCM5222_DUAL_PHY is not set -# CONFIG_SUNLANCE is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -# CONFIG_STRIP is not set -# CONFIG_WAVELAN is not set -# CONFIG_ARLAN is not set -CONFIG_AIRONET4500=m -CONFIG_AIRONET4500_NONCS=m -# CONFIG_AIRONET4500_PNP is not set -CONFIG_AIRONET4500_PCI=y -# CONFIG_AIRONET4500_ISA is not set -# CONFIG_AIRONET4500_I365 is not set -CONFIG_AIRONET4500_PROC=m -CONFIG_AIRO=m -# CONFIG_HERMES is not set -# CONFIG_PLX_HERMES is not set -# CONFIG_TMD_HERMES is not set -# CONFIG_PCI_HERMES is not set -CONFIG_NET_WIRELESS=y - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -CONFIG_SHAPER=m - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input core support -# -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_UINPUT is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -CONFIG_SERIAL_NONSTANDARD=y -# CONFIG_COMPUTONE is not set -# CONFIG_ROCKETPORT is not set -# CONFIG_CYCLADES is not set -# CONFIG_DIGIEPCA is not set -# CONFIG_DIGI is not set -# CONFIG_ESPSERIAL is not set -# CONFIG_MOXA_INTELLIO is not set -# CONFIG_MOXA_SMARTIO is not set -# CONFIG_ISI is not set -# CONFIG_SYNCLINK is not set -# CONFIG_SYNCLINKMP is not set -# CONFIG_N_HDLC is not set -# CONFIG_RISCOM8 is not set -# CONFIG_SPECIALIX is not set -# CONFIG_SX is not set -# CONFIG_RIO is not set -# CONFIG_STALDRV is not set -# CONFIG_SERIAL_TX3912 is not set -# CONFIG_SERIAL_TX3912_CONSOLE is not set -# CONFIG_SERIAL_TXX9 is not set -# CONFIG_SERIAL_TXX9_CONSOLE is not set -CONFIG_AU1X00_UART=y -CONFIG_AU1X00_SERIAL_CONSOLE=y -# CONFIG_AU1X00_USB_TTY is not set -# CONFIG_AU1X00_USB_RAW is not set -# CONFIG_TXX927_SERIAL is not set -# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_QIC02_TAPE is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_DEVICE_INTERFACE is not set -# CONFIG_IPMI_KCS is not set -# CONFIG_IPMI_WATCHDOG is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_SCx200 is not set -# CONFIG_SCx200_GPIO is not set -# CONFIG_AMD_PM768 is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set - -# -# Direct Rendering Manager (XFree86 DRI support) -# -# CONFIG_DRM is not set -CONFIG_AU1X00_GPIO=m -# CONFIG_TS_AU1X00_ADS7846 is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_QFMT_V2 is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BEFS_DEBUG is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -# CONFIG_UMSDOS_FS is not set -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_CRAMFS is not set -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -# CONFIG_JFS_FS is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set -CONFIG_NTFS_FS=m -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=m -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set -# CONFIG_XFS_FS is not set -# CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_RT is not set -# CONFIG_XFS_TRACE is not set -# CONFIG_XFS_DEBUG is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_DIRECTIO is not set -CONFIG_ROOT_NFS=y -CONFIG_NFSD=y -CONFIG_NFSD_V3=y -# CONFIG_NFSD_TCP is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_SMB_UNIX is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -CONFIG_ZISOFS_FS=m - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-15" -CONFIG_NLS_CODEPAGE_437=m -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -CONFIG_NLS_CODEPAGE_850=m -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -CONFIG_NLS_ISO8859_1=m -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -CONFIG_NLS_ISO8859_15=m -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -CONFIG_NLS_UTF8=m - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -# CONFIG_I2C_PARPORT is not set -# CONFIG_VIDEO_BT848 is not set -# CONFIG_VIDEO_PMS is not set -CONFIG_VIDEO_CPIA=m -# CONFIG_VIDEO_CPIA_PP is not set -CONFIG_VIDEO_CPIA_USB=m -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_ZORAN_BUZ is not set -# CONFIG_VIDEO_ZORAN_DC10 is not set -# CONFIG_VIDEO_ZORAN_LML33 is not set -# CONFIG_VIDEO_ZR36120 is not set -# CONFIG_VIDEO_MEYE is not set - -# -# Radio Adapters -# -# CONFIG_RADIO_GEMTEK_PCI is not set -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_MAESTRO is not set -# CONFIG_RADIO_MIROPCM20 is not set - -# -# Sound -# -CONFIG_SOUND=m -# CONFIG_SOUND_ALI5455 is not set -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_MIDI_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_MAESTRO3 is not set -# CONFIG_SOUND_FORTE is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_RME96XX is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_AU1X00 is not set -# CONFIG_SOUND_AU1550_PSC is not set -# CONFIG_SOUND_AU1550_I2S is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -# CONFIG_MIDI_VIA82CXXX is not set -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -# CONFIG_SOUND_DMAP is not set -# CONFIG_SOUND_AD1816 is not set -# CONFIG_SOUND_AD1889 is not set -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_ADLIB is not set -# CONFIG_SOUND_ACI_MIXER is not set -# CONFIG_SOUND_CS4232 is not set -# CONFIG_SOUND_SSCAPE is not set -# CONFIG_SOUND_GUS is not set -# CONFIG_SOUND_VMIDI is not set -# CONFIG_SOUND_TRIX is not set -# CONFIG_SOUND_MSS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_NM256 is not set -# CONFIG_SOUND_MAD16 is not set -# CONFIG_SOUND_PAS is not set -# CONFIG_PAS_JOYSTICK is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_SB is not set -# CONFIG_SOUND_AWE32_SYNTH is not set -# CONFIG_SOUND_KAHLUA is not set -# CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_OPL3SA2 is not set -# CONFIG_SOUND_YMFPCI is not set -# CONFIG_SOUND_YMFPCI_LEGACY is not set -# CONFIG_SOUND_UART6850 is not set -# CONFIG_SOUND_AEDSP16 is not set -# CONFIG_SOUND_TVMIXER is not set -# CONFIG_SOUND_AD1980 is not set -# CONFIG_SOUND_WM97XX is not set - -# -# USB support -# -CONFIG_USB=y -# CONFIG_USB_DEBUG is not set -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -CONFIG_USB_OHCI=y -CONFIG_USB_NON_PCI_OHCI=y -CONFIG_USB_AUDIO=m -CONFIG_USB_EMI26=m -CONFIG_USB_MIDI=m -CONFIG_USB_STORAGE=m -CONFIG_USB_STORAGE_DEBUG=y -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -# CONFIG_USB_STORAGE_ISD200 is not set -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m -# CONFIG_USB_HID is not set -# CONFIG_USB_HIDINPUT is not set -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -CONFIG_USB_DC2XX=m -CONFIG_USB_MDC800=m -CONFIG_USB_SCANNER=m -CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -# CONFIG_USB_W9968CF is not set -CONFIG_USB_VICAM=m -CONFIG_USB_DSBR=m -CONFIG_USB_DABUSB=m -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_KAWETH=m -CONFIG_USB_CATC=m -CONFIG_USB_CDCETHER=m -CONFIG_USB_USBNET=m -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_DEBUG is not set -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=m -CONFIG_USB_SERIAL_VISOR=m -CONFIG_USB_SERIAL_IPAQ=m -CONFIG_USB_SERIAL_IR=m -CONFIG_USB_SERIAL_EDGEPORT=m -CONFIG_USB_SERIAL_EDGEPORT_TI=m -CONFIG_USB_SERIAL_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -CONFIG_USB_SERIAL_KEYSPAN_USA28=y -CONFIG_USB_SERIAL_KEYSPAN_USA28X=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -CONFIG_USB_SERIAL_KEYSPAN_USA19=y -CONFIG_USB_SERIAL_KEYSPAN_USA18X=y -CONFIG_USB_SERIAL_KEYSPAN_USA19W=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -CONFIG_USB_SERIAL_KEYSPAN_MPR=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_RIO500=m -CONFIG_USB_AUERSWALD=m -CONFIG_USB_TIGL=m -CONFIG_USB_BRLVGER=m -CONFIG_USB_LCD=m - -# -# Support for USB gadgets -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -CONFIG_BLUEZ_HCIUSB=m -CONFIG_BLUEZ_HCIUSB_SCO=y -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y -CONFIG_BLUEZ_HCIBFUSB=m -# CONFIG_BLUEZ_HCIDTL1 is not set -# CONFIG_BLUEZ_HCIBT3C is not set -# CONFIG_BLUEZ_HCIBLUECARD is not set -# CONFIG_BLUEZ_HCIBTUART is not set -CONFIG_BLUEZ_HCIVHCI=m - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_RUNTIME_DEBUG is not set -# CONFIG_KGDB is not set -# CONFIG_GDB_CONSOLE is not set -# CONFIG_DEBUG_INFO is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MIPS_UNCACHED is not set -CONFIG_LOG_BUF_SHIFT=0 - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=m -CONFIG_CRYPTO_SHA1=m -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_DES=m -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_DEFLATE=m -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_TEST=m - -# -# Library routines -# -CONFIG_CRC32=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_FW_LOADER=m diff --git a/linux/linux-mtx-1-2.4.27/mtx-1-board-reset.diff b/linux/linux-mtx-1-2.4.27/mtx-1-board-reset.diff deleted file mode 100644 index 9a13c2a403..0000000000 --- a/linux/linux-mtx-1-2.4.27/mtx-1-board-reset.diff +++ /dev/null @@ -1,15 +0,0 @@ ---- linux/arch/mips/au1000/mtx-1/board_setup.c.orig 2004-10-13 19:05:15.340583632 +0200 -+++ linux/arch/mips/au1000/mtx-1/board_setup.c 2004-10-13 19:01:03.402883984 +0200 -@@ -48,6 +48,12 @@ - - extern struct rtc_ops no_rtc_ops; - -+void board_reset (void) -+{ -+ /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ -+ au_writel(0x00000000, 0xAE00001C); -+} -+ - void __init board_setup(void) - { - rtc_ops = &no_rtc_ops; diff --git a/linux/linux-mtx-1-2.4.27/zimage-flash-bin.patch b/linux/linux-mtx-1-2.4.27/zimage-flash-bin.patch deleted file mode 100644 index dca79a3000..0000000000 --- a/linux/linux-mtx-1-2.4.27/zimage-flash-bin.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -Nurb oe/tmp/work/linux-mtx-1-2.4.27-r0/linux/arch/mips/zboot/pb1xxx/Makefile linux.m/arch/mips/zboot/pb1xxx/Makefile ---- oe/tmp/work/linux-mtx-1-2.4.27-r0/linux/arch/mips/zboot/pb1xxx/Makefile 2004-10-13 21:08:49.840408328 +0200 -+++ linux.m/arch/mips/zboot/pb1xxx/Makefile 2004-10-13 21:08:29.736464592 +0200 -@@ -131,5 +131,7 @@ - zImage.flash: zImage - $(OBJCOPY) -O srec --adjust-vma 0x3ed00000 \ - ../images/zImage.$(BNAME) ../images/$(BNAME).flash.srec -+ $(OBJCOPY) -O binary --adjust-vma 0x3ed00000 \ -+ ../images/zImage.$(BNAME) ../images/$(BNAME).flash.bin - - include $(TOPDIR)/Rules.make diff --git a/linux/linux-mtx-1_2.4.24.bb b/linux/linux-mtx-1_2.4.24.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-mtx-1_2.4.27.bb b/linux/linux-mtx-1_2.4.27.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-netvista-2.4.27/netvista_defconfig b/linux/linux-netvista-2.4.27/netvista_defconfig deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-netvista_2.4.27.bb b/linux/linux-netvista_2.4.27.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-omap-2.6-2.6.9-omap1/omap1610h2/defconfig b/linux/linux-omap-2.6-2.6.9-omap1/omap1610h2/defconfig deleted file mode 100644 index 8b4d7f27ce..0000000000 --- a/linux/linux-omap-2.6-2.6.9-omap1/omap1610h2/defconfig +++ /dev/null @@ -1,840 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.9-rc4-omap1 -# Thu Oct 14 16:30:44 2004 -# -CONFIG_ARM=y -CONFIG_MMU=y -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_IOMAP=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y -CONFIG_BROKEN_ON_SMP=y - -# -# General setup -# -CONFIG_LOCALVERSION="" -# CONFIG_SWAP is not set -CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_HOTPLUG is not set -# CONFIG_IKCONFIG is not set -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SHMEM=y -# CONFIG_TINY_SHMEM is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODVERSIONS is not set -# CONFIG_KMOD is not set - -# -# System Type -# -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP3XX is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_IXP2000 is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_LH7A40X is not set -CONFIG_ARCH_OMAP=y -# CONFIG_ARCH_VERSATILE_PB is not set -# CONFIG_ARCH_IMX is not set -# CONFIG_ARCH_H720X is not set - -# -# TI OMAP Implementations -# - -# -# OMAP Core Type -# -# CONFIG_ARCH_OMAP730 is not set -# CONFIG_ARCH_OMAP1510 is not set -CONFIG_ARCH_OMAP16XX=y -CONFIG_ARCH_OMAP_OTG=y - -# -# OMAP Board Type -# -# CONFIG_MACH_OMAP_INNOVATOR is not set -CONFIG_MACH_OMAP_H2=y -# CONFIG_MACH_OMAP_H3 is not set -# CONFIG_MACH_OMAP_H4 is not set -# CONFIG_MACH_OMAP_OSK is not set -# CONFIG_MACH_OMAP_GENERIC is not set - -# -# OMAP Feature Selections -# -# CONFIG_OMAP_BOOT_TAG is not set -CONFIG_OMAP_MUX=y -# CONFIG_OMAP_MUX_DEBUG is not set -CONFIG_OMAP_MUX_WARNINGS=y -CONFIG_OMAP_LL_DEBUG_UART1=y -# CONFIG_OMAP_LL_DEBUG_UART2 is not set -# CONFIG_OMAP_LL_DEBUG_UART3 is not set -CONFIG_OMAP_ARM_192MHZ=y -# CONFIG_OMAP_ARM_168MHZ is not set -# CONFIG_OMAP_ARM_120MHZ is not set -# CONFIG_OMAP_ARM_60MHZ is not set -# CONFIG_OMAP_ARM_30MHZ is not set -# CONFIG_OMAP_DSP is not set - -# -# h720x Implementations -# - -# -# Processor Type -# -CONFIG_CPU_32=y -CONFIG_CPU_ARM926T=y -CONFIG_CPU_32v5=y -CONFIG_CPU_ABRT_EV5TJ=y -CONFIG_CPU_COPY_V4WB=y -CONFIG_CPU_TLB_V4WBI=y - -# -# Processor Features -# -CONFIG_ARM_THUMB=y -# CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_WRITETHROUGH is not set -# CONFIG_CPU_CACHE_ROUND_ROBIN is not set - -# -# General setup -# -# CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0x10C08000 -CONFIG_ZBOOT_ROM_BSS=0x10200000 - -# -# At least one math emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set -# CONFIG_FPE_FASTFPE is not set -# CONFIG_VFP is not set -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_AOUT=y -# CONFIG_BINFMT_MISC is not set - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_PM is not set -CONFIG_PREEMPT=y -# CONFIG_ARTHUR is not set -CONFIG_CMDLINE="mem=32M console=ttyS0,115200n8 initrd=0x10A00000,8M root=/dev/ram0 rw ip=dhcp devfs=mount" -# CONFIG_LEDS is not set -CONFIG_ALIGNMENT_TRAP=y - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_UB is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK_DEV is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -CONFIG_MII=y -CONFIG_NET_VENDOR_SMC=y -CONFIG_SMC91X=y -# CONFIG_SMC9194 is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -CONFIG_PPP=y -# CONFIG_PPP_MULTILINK is not set -# CONFIG_PPP_FILTER is not set -# CONFIG_PPP_ASYNC is not set -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPPOE is not set -CONFIG_SLIP=y -CONFIG_SLIP_COMPRESSED=y -# CONFIG_SLIP_SMART is not set -# CONFIG_SLIP_MODE_SLIP6 is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support -# - -# -# I2O device support -# - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_RAW is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -# CONFIG_KEYBOARD_ATKBD is not set -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -CONFIG_KEYBOARD_OMAP=y -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_NR_UARTS=4 -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_8250_OMAP=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -# CONFIG_LEGACY_PTYS is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_NOWAYOUT=y - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set - -# -# USB-based Watchdog Cards -# -# CONFIG_USBPCWATCHDOG is not set -# CONFIG_OMAP16XX_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -CONFIG_OMAP_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set - -# -# I2C support -# -CONFIG_I2C=y -# CONFIG_I2C_CHARDEV is not set - -# -# I2C Algorithms -# -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -# CONFIG_I2C_ALGOPCA is not set - -# -# I2C Hardware Bus support -# -# CONFIG_I2C_AMD756 is not set -# CONFIG_I2C_AMD8111 is not set -# CONFIG_I2C_ISA is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_SCx200_ACB is not set -# CONFIG_I2C_PCA_ISA is not set -CONFIG_I2C_OMAP=y - -# -# Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ASB100 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_FSCHER is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83627HF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_EEPROM is not set -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -CONFIG_ISP1301_OMAP=m -CONFIG_TPS65010=y -# CONFIG_SENSORS_TLV320AIC23 is not set -CONFIG_GPIOEXPANDER_OMAP=y -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=y - -# -# Video For Linux -# - -# -# Video Adapters -# -# CONFIG_VIDEO_CPIA is not set -# CONFIG_VIDEO_SAA5246A is not set -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_OVCAMCHIP is not set - -# -# Radio Adapters -# -# CONFIG_RADIO_MAESTRO is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -# CONFIG_EXT2_FS_POSIX_ACL is not set -# CONFIG_EXT2_FS_SECURITY is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -CONFIG_ROMFS_FS=y -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_SYSFS=y -CONFIG_DEVFS_FS=y -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS_XATTR is not set -# CONFIG_TMPFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set -# CONFIG_RPCSEC_GSS_SPKM3 is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set - -# -# Native Language Support -# -# CONFIG_NLS is not set - -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=y - -# -# Graphics support -# -CONFIG_FB=y -CONFIG_FB_MODE_HELPERS=y -CONFIG_FB_OMAP=y -CONFIG_FB_OMAP_INTERNAL_LCDC=y -# CONFIG_FB_OMAP_EXTERNAL_LCDC is not set -# CONFIG_FB_OMAP_DMA_TUNE is not set -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y - -# -# Logo configuration -# -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -CONFIG_LOGO_LINUX_CLUT224=y - -# -# Sound -# -CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# -# CONFIG_SND is not set - -# -# Open Sound System -# -CONFIG_SOUND_PRIME=y -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_OSS is not set -# CONFIG_SOUND_TVMIXER is not set -# CONFIG_SOUND_AD1980 is not set - -# -# Misc devices -# - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -# CONFIG_USB_DEVICEFS is not set -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_OTG is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_EHCI_HCD is not set -CONFIG_USB_OHCI_HCD=m -# CONFIG_USB_UHCI_HCD is not set -# CONFIG_USB_SL811HS is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH_TTY is not set -# CONFIG_USB_MIDI is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_STORAGE is not set - -# -# USB Human Interface Devices (HID) -# -# CONFIG_USB_HID is not set - -# -# USB HID Boot Protocol drivers -# -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_EGALAX is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set - -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_STV680 is not set - -# -# USB Network adaptors -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_TIGL is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGETSERVO is not set - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# Synchronous Serial Interfaces (SSI) -# -CONFIG_OMAP_UWIRE=y - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# Kernel hacking -# -CONFIG_DEBUG_KERNEL=y -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_SPINLOCK is not set -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_INFO=y -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set -CONFIG_DEBUG_ERRORS=y -CONFIG_SCHEDSTATS=y -CONFIG_DEBUG_LL=y -# CONFIG_DEBUG_ICEDCC is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -CONFIG_CRC_CCITT=y -CONFIG_CRC32=y -# CONFIG_LIBCRC32C is not set diff --git a/linux/linux-omap-2.6-2.6.9-omap1/schedstats-arm.patch b/linux/linux-omap-2.6-2.6.9-omap1/schedstats-arm.patch deleted file mode 100644 index f5823a9943..0000000000 --- a/linux/linux-omap-2.6-2.6.9-omap1/schedstats-arm.patch +++ /dev/null @@ -1,26 +0,0 @@ - -# -# Patch managed by http://www.holgerschurig.de/patcher.html -# - ---- linux-2.6.9-rc4/arch/arm/Kconfig.debug~schedstats-arm -+++ linux-2.6.9-rc4/arch/arm/Kconfig.debug -@@ -57,6 +57,18 @@ - time and disk space needed for compilation of the kernel. If in - doubt say N. - -+config SCHEDSTATS -+ bool "Collect scheduler statistics" -+ depends on DEBUG_KERNEL && PROC_FS -+ help -+ If you say Y here, additional code will be inserted into the -+ scheduler and related routines to collect statistics about -+ scheduler behavior and provide them in /proc/schedstat. These -+ stats may be useful for both tuning and debugging the scheduler -+ If you aren't debugging the scheduler or trying to tune a specific -+ application, you can say N to avoid the very slight overhead -+ this adds. -+ - # These options are only for real kernel hackers who want to get their hands dirty. - config DEBUG_LL - bool "Kernel low-level debugging functions" diff --git a/linux/linux-omap-2.6_2.6.9-omap1.bb b/linux/linux-omap-2.6_2.6.9-omap1.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-sun4cdm-2.4.26/defconfig b/linux/linux-sun4cdm-2.4.26/defconfig deleted file mode 100644 index 8704f6307e..0000000000 --- a/linux/linux-sun4cdm-2.4.26/defconfig +++ /dev/null @@ -1,473 +0,0 @@ -# -# Automatically generated by make menuconfig: don't edit -# -CONFIG_UID16=y -CONFIG_HIGHMEM=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# General setup -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -# CONFIG_SMP is not set -CONFIG_SPARC32=y -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_MCA is not set -# CONFIG_PCMCIA is not set -CONFIG_SBUS=y -CONFIG_SBUSCHAR=y -CONFIG_BUSMOUSE=y -CONFIG_SUN_MOUSE=y -CONFIG_SERIAL=y -CONFIG_SUN_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SUN_KEYBOARD=y -CONFIG_SUN_CONSOLE=y -CONFIG_SUN_AUXIO=y -CONFIG_SUN_IO=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -CONFIG_SUN_PM=y -# CONFIG_SUN4 is not set -CONFIG_PCI=y -# CONFIG_PCI_NAMES is not set -CONFIG_SUN_OPENPROMFS=m -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_AOUT=y -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -CONFIG_SUNOS_EMUL=y -# CONFIG_OOM_KILLER is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set -# CONFIG_PRINTER is not set - -# -# Console drivers -# -# CONFIG_PROM_CONSOLE is not set - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_RIVA is not set -# CONFIG_FB_CLGEN is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_PM3 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_INTEL is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_TRIDENT is not set -CONFIG_FB_SBUS=y -# CONFIG_FB_CGSIX is not set -CONFIG_FB_BWTWO=y -CONFIG_FB_CGTHREE=y -# CONFIG_FB_TCX is not set -# CONFIG_FB_CGFOURTEEN is not set -# CONFIG_FB_P9100 is not set -# CONFIG_FB_LEO is not set -# CONFIG_FB_PCI is not set -# CONFIG_FB_IT8181 is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_MFB=y -CONFIG_FBCON_CFB8=y -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FONT_SUN8x16=y -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FBCON_FONTS is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Misc Linux/SPARC drivers -# -CONFIG_SUN_OPENPROMIO=m -CONFIG_SUN_MOSTEK_RTC=m -# CONFIG_SUN_BPP is not set -# CONFIG_SUN_VIDEOPIX is not set -# CONFIG_SUN_AURORA is not set -# CONFIG_TADPOLE_TS102_UCTRL is not set -# CONFIG_SUN_JSFLASH is not set -CONFIG_APM_RTC_IS_GMT=y -CONFIG_RTC=y - -# -# Linux/SPARC audio subsystem (EXPERIMENTAL) -# -# CONFIG_SPARCAUDIO is not set -# CONFIG_SPARCAUDIO_AMD7930 is not set -# CONFIG_SPARCAUDIO_DBRI is not set -# CONFIG_SPARCAUDIO_CS4231 is not set -# CONFIG_SPARCAUDIO_DUMMY is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_NBD is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -# CONFIG_BLK_DEV_LVM is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set -CONFIG_UNIX=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_IP_PNP_RARP=y -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -CONFIG_IPV6=y -# CONFIG_KHTTPD is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IP_SCTP=m -# CONFIG_SCTP_DBG_MSG is not set -CONFIG_SCTP_DBG_OBJCNT=y -# CONFIG_SCTP_HMAC_NONE is not set -# CONFIG_SCTP_HMAC_SHA1 is not set -CONFIG_SCTP_HMAC_MD5=y -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -CONFIG_NET_PKTGEN=m - -# -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_HD is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# SCSI support -# -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 -CONFIG_CHR_DEV_SG=m -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -CONFIG_SCSI_SUNESP=y -CONFIG_SCSI_QLOGICPTI=m - -# -# Fibre Channel support -# -# CONFIG_FC4 is not set -# CONFIG_FC4_SOC is not set -# CONFIG_FC4_SOCAL is not set -# CONFIG_SCSI_PLUTO is not set -# CONFIG_SCSI_FCAL is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y -CONFIG_DUMMY=m -# CONFIG_BONDING is not set -CONFIG_TUN=m -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -CONFIG_SUNLANCE=y -CONFIG_HAPPYMEAL=m -CONFIG_SUNBMAC=m -CONFIG_SUNQE=m -# CONFIG_MYRI_SBUS is not set -# CONFIG_VORTEX is not set - -# -# Unix98 PTY support -# -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_QFMT_V2 is not set -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set -# CONFIG_BFS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -CONFIG_CRAMFS=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=m -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_JFS_FS is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=m -CONFIG_EXT2_FS=y -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set -CONFIG_XFS_FS=m -CONFIG_XFS_QUOTA=y -CONFIG_XFS_RT=y -# CONFIG_XFS_TRACE is not set -# CONFIG_XFS_DEBUG is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_DIRECTIO is not set -CONFIG_ROOT_NFS=y -# CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -# CONFIG_SMB_FS is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SUN_PARTITION=y -# CONFIG_SMB_NLS is not set -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Bluetooth support -# -# CONFIG_BLUEZ is not set - -# -# Watchdog -# -# CONFIG_SOFT_WATCHDOG is not set - -# -# Kernel hacking -# -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_HIGHMEM is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_IOVIRT is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -CONFIG_LOG_BUF_SHIFT=14 - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_DEFLATE=y -# CONFIG_CRYPTO_TEST is not set - -# -# Library routines -# -CONFIG_CRC32=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/linux/linux-sun4cdm-2.6.8.1/sun4c_defconfig b/linux/linux-sun4cdm-2.6.8.1/sun4c_defconfig deleted file mode 100644 index 49b84791ae..0000000000 --- a/linux/linux-sun4cdm-2.6.8.1/sun4c_defconfig +++ /dev/null @@ -1,689 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MMU=y -CONFIG_UID16=y -CONFIG_HIGHMEM=y -CONFIG_GENERIC_ISA_DMA=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y -CONFIG_BROKEN_ON_SMP=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_HOTPLUG is not set -# CONFIG_IKCONFIG is not set -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# General setup -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -CONFIG_SPARC32=y -CONFIG_SBUS=y -CONFIG_SBUSCHAR=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SUN_AUXIO=y -CONFIG_SUN_IO=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_SUN_PM=y -# CONFIG_SUN4 is not set -CONFIG_PCI=y -# CONFIG_PCI_LEGACY_PROC is not set -# CONFIG_PCI_NAMES is not set -CONFIG_SUN_OPENPROMFS=m -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_AOUT=y -CONFIG_BINFMT_MISC=m -CONFIG_SUNOS_EMUL=y - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_DEBUG_DRIVER is not set - -# -# Graphics support -# -CONFIG_FB=y -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_ASILIANT is not set -# CONFIG_FB_IMSTT is not set -CONFIG_FB_BW2=y -CONFIG_FB_CG3=y -CONFIG_FB_CG6=y -# CONFIG_FB_RIVA is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON_OLD is not set -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_KYRO is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_TRIDENT is not set -CONFIG_FB_SBUS=y -# CONFIG_FB_TCX is not set -# CONFIG_FB_CG14 is not set -# CONFIG_FB_P9100 is not set -# CONFIG_FB_LEO is not set -# CONFIG_FB_PCI is not set -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_MDA_CONSOLE is not set -# CONFIG_PROM_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FONTS is not set -CONFIG_FONT_SUN8x16=y -# CONFIG_FONT_SUN12x22 is not set - -# -# Logo configuration -# -# CONFIG_LOGO is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_SUNCORE=y -CONFIG_SERIAL_SUNZILOG=y -CONFIG_SERIAL_SUNZILOG_CONSOLE=y -CONFIG_SERIAL_SUNSU=y -CONFIG_SERIAL_SUNSU_CONSOLE=y -# CONFIG_SERIAL_SUNSAB is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y - -# -# Misc Linux/SPARC drivers -# -CONFIG_SUN_OPENPROMIO=m -CONFIG_SUN_MOSTEK_RTC=m -# CONFIG_SUN_BPP is not set -# CONFIG_SUN_VIDEOPIX is not set -# CONFIG_TADPOLE_TS102_UCTRL is not set -# CONFIG_SUN_JSFLASH is not set -CONFIG_APM_RTC_IS_GMT=y -CONFIG_RTC=m - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_CRYPTOLOOP=m -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_SX8 is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# SCSI device support -# -CONFIG_SCSI=y -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI Transport Attributes -# -CONFIG_SCSI_SPI_ATTRS=m -# CONFIG_SCSI_FC_ATTRS is not set - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_3W_9XXX is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_IPS is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -CONFIG_SCSI_QLOGICPTI=m -CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA21XX is not set -# CONFIG_SCSI_QLA22XX is not set -# CONFIG_SCSI_QLA2300 is not set -# CONFIG_SCSI_QLA2322 is not set -# CONFIG_SCSI_QLA6312 is not set -# CONFIG_SCSI_QLA6322 is not set -# CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set -CONFIG_SCSI_SUNESP=y - -# -# Fibre Channel support -# -# CONFIG_FC4 is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y -CONFIG_UNIX=y -CONFIG_NET_KEY=m -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -CONFIG_IPV6=y -CONFIG_IPV6_PRIVACY=y -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -# CONFIG_NETFILTER is not set -CONFIG_XFRM=y -CONFIG_XFRM_USER=m - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IP_SCTP=m -# CONFIG_SCTP_DBG_MSG is not set -CONFIG_SCTP_DBG_OBJCNT=y -# CONFIG_SCTP_HMAC_NONE is not set -# CONFIG_SCTP_HMAC_SHA1 is not set -CONFIG_SCTP_HMAC_MD5=y -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing -# -CONFIG_NET_PKTGEN=m -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -CONFIG_NETDEVICES=y -CONFIG_DUMMY=m -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m -# CONFIG_ETHERTAP is not set - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -CONFIG_MII=m -CONFIG_SUNLANCE=y -CONFIG_HAPPYMEAL=m -CONFIG_SUNBMAC=m -CONFIG_SUNQE=m -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_S2IO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Unix98 PTY support -# -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -# CONFIG_INPUT_TSDEV is not set -CONFIG_INPUT_EVDEV=m -CONFIG_INPUT_EVBUG=m - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=m -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=m -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=m -CONFIG_KEYBOARD_SUNKBD=m -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=m -CONFIG_MOUSE_SERIAL=m -# CONFIG_MOUSE_VSXXXAA is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -CONFIG_XFS_FS=m -CONFIG_XFS_RT=y -CONFIG_XFS_QUOTA=y -CONFIG_XFS_SECURITY=y -CONFIG_XFS_POSIX_ACL=y -# CONFIG_MINIX_FS is not set -CONFIG_ROMFS_FS=m -# CONFIG_QUOTA is not set -CONFIG_QUOTACTL=y -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=m -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_KCORE=y -CONFIG_SYSFS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS_XATTR=y -# CONFIG_DEVPTS_FS_SECURITY is not set -# CONFIG_TMPFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -CONFIG_CRAMFS=y -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -CONFIG_SUNRPC_GSS=m -CONFIG_RPCSEC_GSS_KRB5=m -# CONFIG_SMB_FS is not set -CONFIG_CIFS=m -# CONFIG_CIFS_STATS is not set -# CONFIG_CIFS_XATTR is not set -# CONFIG_CIFS_POSIX is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -CONFIG_AFS_FS=m -CONFIG_RXRPC=m - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SUN_PARTITION=y - -# -# Native Language Support -# -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ASCII is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set - -# -# Kernel hacking -# -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_SLAB is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_HIGHMEM is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_BUGVERBOSE is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -# CONFIG_CRYPTO_TEA is not set -CONFIG_CRYPTO_ARC4=m -# CONFIG_CRYPTO_KHAZAD is not set -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_CRC32C=m -# CONFIG_CRYPTO_TEST is not set - -# -# Library routines -# -# CONFIG_CRC_CCITT is not set -CONFIG_CRC32=y -CONFIG_LIBCRC32C=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/linux/linux-sun4cdm_2.4.26.bb b/linux/linux-sun4cdm_2.4.26.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-sun4cdm_2.6.8.1.bb b/linux/linux-sun4cdm_2.6.8.1.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/linux-xxs1500-2.4.21/Makefile b/linux/linux-xxs1500-2.4.21/Makefile deleted file mode 100644 index 7ef3faa145..0000000000 --- a/linux/linux-xxs1500-2.4.21/Makefile +++ /dev/null @@ -1,756 +0,0 @@ -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# Copyright (C) 1994, 1995, 1996 by Ralf Baechle -# DECStation modifications by Paul M. Antoine, 1996 -# Copyright (C) 2002, 2003 Maciej W. Rozycki -# -# This file is included by the global makefile so that you can add your own -# architecture-specific flags and dependencies. Remember to do have actions -# for "archclean" and "archdep" for cleaning up and making dependencies for -# this architecture -# - -# -# Select the object file format to substitute into the linker script. -# -ifdef CONFIG_CPU_LITTLE_ENDIAN -tool-prefix = mipsel-linux- -ld-emul = elf32ltsmip -else -tool-prefix = mips-linux- -ld-emul = elf32btsmip -endif - -ifdef CONFIG_CROSSCOMPILE -CROSS_COMPILE = $(tool-prefix) -endif - -check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi) - -# -# -# GCC uses -G 0 -mabicalls -fpic as default. We don't want PIC in the kernel -# code since it only slows down the whole thing. At some point we might make -# use of global pointer optimizations but their use of $28 conflicts with -# the current pointer optimization. -# -# The DECStation requires an ECOFF kernel for remote booting, other MIPS -# machines may also. Since BFD is incredibly buggy with respect to -# crossformat linking we rely on the elf2ecoff tool for format conversion. -# -GCCFLAGS := -I $(TOPDIR)/include/asm/gcc -GCCFLAGS += -G 0 -mno-abicalls -fno-pic -pipe -GCCFLAGS += $(call check_gcc, -finline-limit=100000,) -LINKFLAGS += -G 0 -static # -N -MODFLAGS += -mlong-calls - -ifdef CONFIG_DEBUG_INFO -GCCFLAGS += -g -ifdef CONFIG_SB1XXX_CORELIS -GCCFLAGS += -mno-sched-prolog -fno-omit-frame-pointer -endif -endif - -# -# Use: $(call set_gccflags,,,,,) -# -# , -- preferred CPU and ISA designations (may require -# recent tools) -# , -- fallback CPU and ISA designations (have to work -# with up to the oldest supported tools) -# -- an ISA designation used as an ABI selector for -# gcc versions that do not support "-mabi=32" -# (depending on the CPU type, either "mips1" or -# "mips2") -# -set_gccflags = $(shell \ -while :; do \ - cpu=$(1); isa=-$(2); \ - for gcc_opt in -march= -mcpu=; do \ - $(CC) $$gcc_opt$$cpu $$isa -S -o /dev/null \ - -xc /dev/null > /dev/null 2>&1 && \ - break 2; \ - done; \ - cpu=$(3); isa=-$(4); \ - for gcc_opt in -march= -mcpu=; do \ - $(CC) $$gcc_opt$$cpu $$isa -S -o /dev/null \ - -xc /dev/null > /dev/null 2>&1 && \ - break 2; \ - done; \ - break; \ -done; \ -gcc_abi=-mabi=32; gcc_cpu=$$cpu; \ -if $(CC) $$gcc_abi -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then \ - gcc_isa=$$isa; \ -else \ - gcc_abi=; gcc_isa=-$(5); \ -fi; \ -gas_abi=-Wa,-32; gas_cpu=$$cpu; gas_isa=-Wa,$$isa; \ -while :; do \ - for gas_opt in -Wa,-march= -Wa,-mcpu=; do \ - $(CC) $$gas_abi $$gas_opt$$cpu $$gas_isa -Wa,-Z -c \ - -o /dev/null -xassembler /dev/null > /dev/null 2>&1 && \ - break 2; \ - done; \ - gas_abi=; gas_opt=; gas_cpu=; gas_isa=; \ - break; \ -done; \ -echo $$gcc_abi $$gcc_opt$$gcc_cpu $$gcc_isa $$gas_abi $$gas_opt$$gas_cpu $$gas_isa) - -# -# CPU-dependent compiler/assembler options for optimization. -# -ifdef CONFIG_CPU_R3000 -GCCFLAGS += $(call set_gccflags,r3000,mips1,r3000,mips1,mips1) -endif -ifdef CONFIG_CPU_TX39XX -GCCFLAGS += $(call set_gccflags,r3900,mips1,r3000,mips1,mips1) -endif -ifdef CONFIG_CPU_R6000 -GCCFLAGS += $(call set_gccflags,r6000,mips2,r6000,mips2,mips2) \ - -Wa,--trap -endif -ifdef CONFIG_CPU_R4300 -GCCFLAGS += $(call set_gccflags,r4300,mips3,r4300,mips3,mips2) \ - -Wa,--trap -endif -ifdef CONFIG_CPU_VR41XX -GCCFLAGS += $(call set_gccflags,r4100,mips3,r4600,mips3,mips2) \ - -Wa,--trap -endif -ifdef CONFIG_CPU_R4X00 -GCCFLAGS += $(call set_gccflags,r4600,mips3,r4600,mips3,mips2) \ - -Wa,--trap -endif -ifdef CONFIG_CPU_TX49XX -GCCFLAGS += $(call set_gccflags,r4600,mips3,r4600,mips3,mips2) \ - -Wa,--trap -endif -ifdef CONFIG_CPU_MIPS32 -GCCFLAGS += $(call set_gccflags,mips32,mips32,r4600,mips3,mips2) \ - -Wa,--trap -endif -ifdef CONFIG_CPU_MIPS64 -GCCFLAGS += $(call set_gccflags,mips64,mips64,r4600,mips3,mips2) \ - -Wa,--trap -endif -ifdef CONFIG_CPU_R5000 -GCCFLAGS += $(call set_gccflags,r5000,mips4,r5000,mips4,mips2) \ - -Wa,--trap -endif -ifdef CONFIG_CPU_R5432 -GCCFLAGS += $(call set_gccflags,r5400,mips4,r5000,mips4,mips2) \ - -Wa,--trap -endif -ifdef CONFIG_CPU_NEVADA -GCCFLAGS += $(call set_gccflags,rm5200,mips4,r5000,mips4,mips2) \ - -Wa,--trap -#GCCFLAGS += $(call check_gcc,-mmad,) -endif -ifdef CONFIG_CPU_RM7000 -GCCFLAGS += $(call set_gccflags,rm7000,mips4,r5000,mips4,mips2) \ - -Wa,--trap -endif -ifdef CONFIG_CPU_RM9000 -GCCFLAGS += $(call set_gccflags,rm9000,mips4,r5000,mips4,mips2) \ - -Wa,--trap -endif -ifdef CONFIG_CPU_SB1 -GCCFLAGS += $(call set_gccflags,sb1,mips64,r5000,mips4,mips2) \ - -Wa,--trap -ifdef CONFIG_SB1_PASS_1_WORKAROUNDS -MODFLAGS += -msb1-pass1-workarounds -endif -endif - -AFLAGS += $(GCCFLAGS) -CFLAGS += $(GCCFLAGS) -LDFLAGS += -m $(ld-emul) - - -# -# We unconditionally build the math emulator -# -CORE_FILES += arch/mips/math-emu/fpu_emulator.o -SUBDIRS += arch/mips/math-emu - -# -# ramdisk/initrd support -# You need a compressed ramdisk image, named ramdisk.gz in -# arch/mips/ramdisk -# -ifdef CONFIG_EMBEDDED_RAMDISK -CORE_FILES += arch/mips/ramdisk/ramdisk.o -SUBDIRS += arch/mips/ramdisk -endif - - -# -# Board-dependent options and extra files -# - -# -# Acer PICA 61, Mips Magnum 4000 and Olivetti M700. -# -ifdef CONFIG_MIPS_JAZZ -CORE_FILES += arch/mips/jazz/jazz.o -SUBDIRS += arch/mips/jazz arch/mips/arc -LIBS += arch/mips/arc/arclib.a -LOADADDR := 0x80080000 -endif - -# -# Au1000 (Alchemy Semi PB1000) eval board -# -ifdef CONFIG_MIPS_PB1000 -LIBS += arch/mips/au1000/pb1000/pb1000.o \ - arch/mips/au1000/common/au1000.o -SUBDIRS += arch/mips/au1000/pb1000 arch/mips/au1000/common -LOADADDR := 0x80100000 -endif - -# -# Au1100 (Alchemy Semi PB1100) eval board -# -ifdef CONFIG_MIPS_PB1100 -LIBS += arch/mips/au1000/pb1100/pb1100.o \ - arch/mips/au1000/common/au1000.o -SUBDIRS += arch/mips/au1000/pb1100 arch/mips/au1000/common -LOADADDR += 0x80100000 -endif - -# -# Au1500 (Alchemy Semi PB1500) eval board -# -ifdef CONFIG_MIPS_PB1500 -LIBS += arch/mips/au1000/pb1500/pb1500.o \ - arch/mips/au1000/common/au1000.o -SUBDIRS += arch/mips/au1000/pb1500 arch/mips/au1000/common -LOADADDR := 0x80100000 -endif - -# -# Au1x00 (AMD/Alchemy) eval boards -# -ifdef CONFIG_MIPS_DB1000 -LIBS += arch/mips/au1000/db1x00/db1x00.o \ - arch/mips/au1000/common/au1000.o -SUBDIRS += arch/mips/au1000/db1x00 arch/mips/au1000/common -LOADADDR += 0x80100000 -endif - -ifdef CONFIG_MIPS_DB1500 -LIBS += arch/mips/au1000/db1x00/db1x00.o \ - arch/mips/au1000/common/au1000.o -SUBDIRS += arch/mips/au1000/db1x00 arch/mips/au1000/common -LOADADDR += 0x80100000 -endif - -ifdef CONFIG_MIPS_DB1100 -LIBS += arch/mips/au1000/db1x00/db1x00.o \ - arch/mips/au1000/common/au1000.o -SUBDIRS += arch/mips/au1000/db1x00 arch/mips/au1000/common -LOADADDR += 0x80100000 -endif - -ifdef CONFIG_MIPS_HYDROGEN3 -LIBS += arch/mips/au1000/hydrogen3/hydrogen3.o \ - arch/mips/au1000/common/au1000.o -SUBDIRS += arch/mips/au1000/hydrogen3 arch/mips/au1000/common -LOADADDR += 0x80100000 -endif - -ifdef CONFIG_MIPS_BOSPORUS -LIBS += arch/mips/au1000/db1x00/db1x00.o \ - arch/mips/au1000/common/au1000.o -SUBDIRS += arch/mips/au1000/db1x00 arch/mips/au1000/common -LOADADDR += 0x80100000 -endif - -ifdef CONFIG_MIPS_MIRAGE -LIBS += arch/mips/au1000/db1x00/db1x00.o \ - arch/mips/au1000/common/au1000.o -SUBDIRS += arch/mips/au1000/db1x00 arch/mips/au1000/common -LOADADDR += 0x80100000 -endif - -ifdef CONFIG_MIPS_XXS1500 -LIBS += arch/mips/au1000/xxs1500/xxs1500.o \ - arch/mips/au1000/common/au1000.o -SUBDIRS += arch/mips/au1000/xxs1500 arch/mips/au1000/common -LOADADDR += 0x80100000 -endif - -ifdef CONFIG_MIPS_MTX1 -LIBS += arch/mips/au1000/mtx-1/mtx-1.o \ - arch/mips/au1000/common/au1000.o -SUBDIRS += arch/mips/au1000/mtx-1 arch/mips/au1000/common -LOADADDR += 0x80100000 -endif - -ifdef CONFIG_MIPS_PB1550 -LIBS += arch/mips/au1000/pb1550/pb1550.o \ - arch/mips/au1000/common/au1000.o -SUBDIRS += arch/mips/au1000/pb1550 arch/mips/au1000/common -LOADADDR += 0x80100000 -endif - - -# -# Cogent CSB250 -# -ifdef CONFIG_COGENT_CSB250 -LIBS += arch/mips/au1000/csb250/csb250.o \ - arch/mips/au1000/common/au1000.o -SUBDIRS += arch/mips/au1000/csb250 arch/mips/au1000/common -LOADADDR := 0x80100000 -endif - -ifdef CONFIG_PCI -CORE_FILES += arch/mips/pci/pci-core.o -SUBDIRS += arch/mips/pci -endif - -# -# Algorithmics P4032 -# -ifdef CONFIG_ALGOR_P4032 -CORE_FILES += arch/mips/algor/algor.o -SUBDIRS += arch/mips/algor -LOADADDR := 0x80000000 -endif - -# -# Baget/MIPS -# -ifdef CONFIG_BAGET_MIPS -SUBDIRS += arch/mips/baget arch/mips/baget/prom -LIBS += arch/mips/baget/baget.a arch/mips/baget/prom/bagetlib.a -LOADADDR := 0x80001000 -endif - -# -# Cobalt Server -# -ifdef CONFIG_MIPS_COBALT -SUBDIRS += arch/mips/cobalt -CORE_FILES += arch/mips/cobalt/cobalt.o -LOADADDR := 0x80080000 -endif - -# -# DECstation family -# -ifdef CONFIG_DECSTATION -CORE_FILES += arch/mips/dec/dec.o -SUBDIRS += arch/mips/dec arch/mips/dec/prom -LIBS += arch/mips/dec/prom/rexlib.a -LOADADDR := 0x80040000 -endif - -# -# Galileo EV64120 Board -# -ifdef CONFIG_MIPS_EV64120 -LIBS += arch/mips/gt64120/common/gt64120.o \ - arch/mips/gt64120/ev64120/ev64120.o -SUBDIRS += arch/mips/gt64120/common arch/mips/gt64120/ev64120 -LOADADDR := 0x80100000 -endif - -# -# Galileo EV96100 Board -# -ifdef CONFIG_MIPS_EV96100 -LIBS += arch/mips/galileo-boards/ev96100/ev96100.o -SUBDIRS += arch/mips/galileo-boards/ev96100 -LOADADDR := 0x80100000 -endif - -# -# Globespan IVR eval board with QED 5231 CPU -# -ifdef CONFIG_MIPS_IVR -LIBS += arch/mips/ite-boards/ivr/ivr.o \ - arch/mips/ite-boards/generic/it8172.o -SUBDIRS += arch/mips/ite-boards/generic arch/mips/ite-boards/ivr -LOADADDR := 0x80100000 -endif - -# -# HP LaserJet -# -ifdef CONFIG_HP_LASERJET -SUBDIRS += arch/mips/hp-lj -LIBS += arch/mips/hp-lj/hp-lj.o -LOADADDR := 0x80030000 -endif - -# -# ITE 8172 eval board with QED 5231 CPU -# -ifdef CONFIG_MIPS_ITE8172 -LIBS += arch/mips/ite-boards/qed-4n-s01b/ite.o \ - arch/mips/ite-boards/generic/it8172.o -SUBDIRS += arch/mips/ite-boards/generic arch/mips/ite-boards/qed-4n-s01b -LOADADDR := 0x80100000 -endif - -# -# MIPS Atlas board -# -ifdef CONFIG_MIPS_ATLAS -LIBS += arch/mips/mips-boards/atlas/atlas.o \ - arch/mips/mips-boards/generic/mipsboards.o -SUBDIRS += arch/mips/mips-boards/generic arch/mips/mips-boards/atlas -LOADADDR := 0x80100000 -endif - -# -# MIPS Malta board -# -ifdef CONFIG_MIPS_MALTA -LIBS += arch/mips/mips-boards/malta/malta.o \ - arch/mips/mips-boards/generic/mipsboards.o -SUBDIRS += arch/mips/mips-boards/malta arch/mips/mips-boards/generic -LOADADDR := 0x80100000 -endif - -# -# MIPS SEAD board -# -ifdef CONFIG_MIPS_SEAD -LIBS += arch/mips/mips-boards/sead/sead.o \ - arch/mips/mips-boards/generic/mipsboards.o -SUBDIRS += arch/mips/mips-boards/generic arch/mips/mips-boards/sead -LOADADDR := 0x80100000 -endif - -# -# Momentum Ocelot board -# -ifdef CONFIG_MOMENCO_OCELOT -# The Ocelot setup.o must be linked early - it does the ioremap() for the -# mips_io_port_base. -CORE_FILES += arch/mips/gt64120/common/gt64120.o \ - arch/mips/gt64120/momenco_ocelot/momenco_ocelot.o -SUBDIRS += arch/mips/gt64120/common arch/mips/gt64120/momenco_ocelot -LOADADDR := 0x80100000 -endif - -# -# Momentum Ocelot-G board -# -ifdef CONFIG_MOMENCO_OCELOT_G -# The Ocelot-G setup.o must be linked early - it does the ioremap() for the -# mips_io_port_base. -CORE_FILES += arch/mips/momentum/ocelot_g/ocelot_g.o -SUBDIRS += arch/mips/momentum/ocelot_g -LOADADDR := 0x80100000 -endif - -# -# Momentum Ocelot-C and -CS boards -# -ifdef CONFIG_MOMENCO_OCELOT_C -# The Ocelot-C[S] setup.o must be linked early - it does the ioremap() for the -# mips_io_port_base. -CORE_FILES += arch/mips/momentum/ocelot_c/ocelot_c.o -SUBDIRS += arch/mips/momentum/ocelot_c -LOADADDR := 0x80100000 -endif - -ifdef CONFIG_MOMENCO_JAGUAR_ATX -LIBS += arch/mips/momentum/jaguar_atx/jaguar_atx.o -SUBDIRS += arch/mips/momentum/jaguar_atx -ifdef CONFIG_JAGUAR_DMALOW -LOADADDR := 0x88000000 -else -LOADADDR := 0x80100000 -endif -endif - -# -# NEC DDB Vrc-5074 -# -ifdef CONFIG_DDB5074 -SUBDIRS += arch/mips/ddb5xxx/common arch/mips/ddb5xxx/ddb5074 -LIBS += arch/mips/ddb5xxx/common/ddb5xxx.o arch/mips/ddb5xxx/ddb5074/ddb5074.o -LOADADDR := 0x80080000 -endif - -# -# NEC DDB Vrc-5476 -# -ifdef CONFIG_DDB5476 -SUBDIRS += arch/mips/ddb5xxx/common arch/mips/ddb5xxx/ddb5476 -LIBS += arch/mips/ddb5xxx/common/ddb5xxx.o \ - arch/mips/ddb5xxx/ddb5476/ddb5476.o -LOADADDR := 0x80080000 -endif - -# -# NEC DDB Vrc-5477 -# -ifdef CONFIG_DDB5477 -SUBDIRS += arch/mips/ddb5xxx/common arch/mips/ddb5xxx/ddb5477 -LIBS += arch/mips/ddb5xxx/common/ddb5xxx.o \ - arch/mips/ddb5xxx/ddb5477/ddb5477.o -LOADADDR := 0x80100000 -endif - -ifdef CONFIG_LASAT -LIBS += arch/mips/lasat/lasatkern.o -SUBDIRS += arch/mips/lasat -LOADADDR += 0x80000000 -endif -# -# NEC Osprey (vr4181) board -# -ifdef CONFIG_NEC_OSPREY -SUBDIRS += arch/mips/vr4181/common arch/mips/vr4181/osprey -LIBS += arch/mips/vr4181/common/vr4181.o \ - arch/mips/vr4181/osprey/osprey.o -LOADADDR := 0x80002000 -endif - -# -# NEC Eagle/Hawk (VR4122/VR4131) board -# -ifdef CONFIG_NEC_EAGLE -SUBDIRS += arch/mips/vr41xx/common \ - arch/mips/vr41xx/nec-eagle -CORE_FILES += arch/mips/vr41xx/common/vr41xx.o \ - arch/mips/vr41xx/nec-eagle/eagle.o -LOADADDR := 0x80000000 -endif - -# -# ZAO Networks Capcella (VR4131) -# -ifdef CONFIG_ZAO_CAPCELLA -SUBDIRS += arch/mips/vr41xx/common \ - arch/mips/vr41xx/zao-capcella -CORE_FILES += arch/mips/vr41xx/common/vr41xx.o \ - arch/mips/vr41xx/zao-capcella/capcella.o -LOADADDR := 0x80000000 -endif - -# -# Victor MP-C303/304 (VR4122) -# -ifdef CONFIG_VICTOR_MPC30X -SUBDIRS += arch/mips/vr41xx/common \ - arch/mips/vr41xx/victor-mpc30x -CORE_FILES += arch/mips/vr41xx/common/vr41xx.o \ - arch/mips/vr41xx/victor-mpc30x/mpc30x.o -LOADADDR := 0x80001000 -endif - -# -# IBM WorkPad z50 (VR4121) -# -ifdef CONFIG_IBM_WORKPAD -SUBDIRS += arch/mips/vr41xx/common \ - arch/mips/vr41xx/ibm-workpad -CORE_FILES += arch/mips/vr41xx/common/vr41xx.o \ - arch/mips/vr41xx/ibm-workpad/workpad.o -LOADADDR += 0x80004000 -endif - -# -# CASIO CASSIPEIA E-55/65 (VR4111) -# -ifdef CONFIG_CASIO_E55 -SUBDIRS += arch/mips/vr41xx/common \ - arch/mips/vr41xx/casio-e55 -CORE_FILES += arch/mips/vr41xx/common/vr41xx.o \ - arch/mips/vr41xx/casio-e55/e55.o -LOADADDR += 0x80004000 -endif - -# -# TANBAC TB0226 Mbase (VR4131) -# -ifdef CONFIG_TANBAC_TB0226 -SUBDIRS += arch/mips/vr41xx/common \ - arch/mips/vr41xx/tanbac-tb0226 -CORE_FILES += arch/mips/vr41xx/common/vr41xx.o \ - arch/mips/vr41xx/tanbac-tb0226/tb0226.o -LOADADDR := 0x80000000 -endif - -# -# TANBAC TB0229 (VR4131DIMM) -# -ifdef CONFIG_TANBAC_TB0229 -SUBDIRS += arch/mips/vr41xx/common \ - arch/mips/vr41xx/tanbac-tb0229 -CORE_FILES += arch/mips/vr41xx/common/vr41xx.o \ - arch/mips/vr41xx/tanbac-tb0229/tb0229.o -LOADADDR := 0x80000000 -endif - -# -# Philips Nino -# -ifdef CONFIG_NINO -CORE_FILES += arch/mips/philips/nino/nino.o -SUBDIRS += arch/mips/philips/nino -LOADADDR := 0x80000000 -endif - -# -# SGI IP22 (Indy/Indigo2) -# -ifdef CONFIG_SGI_IP22 -CORE_FILES += arch/mips/sgi-ip22/ip22-kern.o -LIBS += arch/mips/arc/arclib.a -SUBDIRS += arch/mips/sgi-ip22 arch/mips/arc -# -# Set LOADADDR to >= 0x88069000 if you want to leave space for symmon, -# 0x88002000 for production kernels. Note that the value must be -# 8kb aligned or the handling of the current variable will break. -# -LOADADDR := 0x88002000 -endif - -# -# Sibyte SB1250 SOC and Broadcom (SiByte) BCM112x SOCs -# -ifneq ($(CONFIG_SIBYTE_SB1250)$(CONFIG_SIBYTE_BCM112X),) -# This is a LIB so that it links at the end, and initcalls are later -# the sequence; but it is built as an object so that modules don't get -# removed (as happens, even if they have __initcall/module_init) -LIBS += arch/mips/sibyte/sb1250/sb1250.o -SUBDIRS += arch/mips/sibyte/sb1250 -LOADADDR := 0x80100000 -endif - -# -# Sibyte boards: -# -# BCM91250A (SWARM), -# BCM91250E (Sentosa), -# BCM91120C (CRhine), -# BCM91120x (Carmel), -# BCM91125C (CRhone), -# BCM91125E (Rhone). -# -ifdef CONFIG_SIBYTE_BOARD -LIBS += arch/mips/sibyte/swarm/sbswarm.a -SUBDIRS += arch/mips/sibyte/swarm -endif - -# -# Sibyte CFE firmware -# -ifdef CONFIG_SIBYTE_CFE -LIBS += arch/mips/sibyte/cfe/cfe.a -SUBDIRS += arch/mips/sibyte/cfe -endif - -# -# SNI RM200 PCI -# -ifdef CONFIG_SNI_RM200_PCI -CORE_FILES += arch/mips/sni/sni.o -SUBDIRS += arch/mips/sni arch/mips/arc -LIBS += arch/mips/arc/arclib.a -LOADADDR := 0x80080000 -endif - -# -# Toshiba JMR-TX3927 board -# -ifdef CONFIG_TOSHIBA_JMR3927 -CORE_FILES += arch/mips/jmr3927/rbhma3100/jmr3927.o \ - arch/mips/jmr3927/common/tx3927.o -SUBDIRS += arch/mips/jmr3927/rbhma3100 arch/mips/jmr3927/common -LOADADDR := 0x80050000 -endif - -# -# Toshiba RBTX4927 board or -# Toshiba RBTX4937 board -# -ifdef CONFIG_TOSHIBA_RBTX4927 -MIPS = arch/mips -CEC = tx4927 -COMMON = $(MIPS)/$(CEC)/common -BOARD = $(MIPS)/$(CEC)/toshiba_rbtx4927 -LIBS += $(BOARD)/toshiba_rbtx4927.o $(COMMON)/tx4927.o -SUBDIRS += $(BOARD) $(COMMON) -LOADADDR += 0x80020000 -endif - -# -# Choosing incompatible machines durings configuration will result in -# error messages during linking. Select a default linkscript if -# none has been choosen above. -# -vmlinux: arch/$(ARCH)/ld.script - -arch/$(ARCH)/ld.script: arch/$(ARCH)/ld.script.in arch/$(ARCH)/Makefile - sed -e 's/@@LOADADDR@@/$(LOADADDR)/' <$< >$@ -LINKFLAGS += -T arch/$(ARCH)/ld.script - -HEAD := arch/mips/kernel/head.o arch/mips/kernel/init_task.o - -SUBDIRS := $(addprefix arch/mips/, tools) $(SUBDIRS) $(addprefix arch/mips/, kernel mm lib) -CORE_FILES := arch/mips/kernel/kernel.o arch/mips/mm/mm.o $(CORE_FILES) -LIBS := arch/mips/lib/lib.a $(LIBS) - -ifdef CONFIG_BAGET_MIPS - -BAGETBOOT = $(MAKE) -C arch/$(ARCH)/baget - -balo: vmlinux - $(BAGETBOOT) balo - -endif - -ifdef CONFIG_MIPS_EV64120 -gboot: vmlinux - $(MAKE) -C arch/$(ARCH)/galileo-boards/ev64120/compressed -endif - -ifdef CONFIG_LASAT -rom.bin rom.sw: vmlinux - $(MAKE) -C arch/$(ARCH)/lasat/image $@ -endif - -MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot -MAKEZBOOT = $(MAKE) -C arch/$(ARCH)/zboot -BOOT_TARGETS = zImage zImage.initrd zImage.flash zImage.flash.bin - -vmlinux.ecoff: vmlinux - @$(MAKEBOOT) $@ - - $(BOOT_TARGETS): vmlinux - @$(MAKEZBOOT) $@ - -vmlinux.srec: vmlinux - @$(MAKEBOOT) $@ - -archclean: - @$(MAKEBOOT) clean - @$(MAKEZBOOT) clean - rm -f arch/$(ARCH)/ld.script - $(MAKE) -C arch/$(ARCH)/tools clean - $(MAKE) -C arch/mips/baget clean - $(MAKE) -C arch/mips/lasat clean - -archmrproper: - @$(MAKEBOOT) mrproper - $(RM) $(TOPDIR)/include/asm-$(ARCH)/offset.h - $(MAKE) -C arch/$(ARCH)/tools mrproper - -archdep: - if [ ! -f $(TOPDIR)/include/asm-$(ARCH)/offset.h ]; then \ - touch $(TOPDIR)/include/asm-$(ARCH)/offset.h; \ - fi; - @$(MAKEBOOT) dep diff --git a/linux/linux-xxs1500-2.4.21/defconfig-xxs1500 b/linux/linux-xxs1500-2.4.21/defconfig-xxs1500 deleted file mode 100644 index 0fc84863ca..0000000000 --- a/linux/linux-xxs1500-2.4.21/defconfig-xxs1500 +++ /dev/null @@ -1,1199 +0,0 @@ -# -# Automatically generated by make menuconfig: don't edit -# -CONFIG_MIPS=y -CONFIG_MIPS32=y -# CONFIG_MIPS64 is not set - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_MIPS_BOSPORUS is not set -# CONFIG_MIPS_MIRAGE is not set -# CONFIG_MIPS_DB1000 is not set -# CONFIG_MIPS_DB1100 is not set -# CONFIG_MIPS_DB1500 is not set -# CONFIG_MIPS_PB1000 is not set -# CONFIG_MIPS_PB1100 is not set -# CONFIG_MIPS_PB1500 is not set -CONFIG_MIPS_XXS1500=y -# CONFIG_MIPS_MTX1 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_LASAT is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_NINO is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP27 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -# CONFIG_HIGHMEM is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -CONFIG_SOC_AU1X00=y -CONFIG_SOC_AU1500=y -CONFIG_PCI=y -CONFIG_NEW_PCI=y -CONFIG_PCI_AUTO=y -CONFIG_NONCOHERENT_IO=y -CONFIG_PC_KEYB=y -# CONFIG_MIPS_AU1000 is not set - -# -# CPU selection -# -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_CPU_HAS_PREFETCH=y -# CONFIG_VTAG_ICACHE is not set -CONFIG_64BIT_PHYS_ADDR=y -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -# CONFIG_CPU_HAS_LLDSCD is not set -# CONFIG_CPU_HAS_WB is not set -CONFIG_CPU_HAS_SYNC=y - -# -# General setup -# -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_NET=y -CONFIG_PCI_NAMES=y -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_TC is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -# CONFIG_CARDBUS is not set -# CONFIG_TCIC is not set -# CONFIG_I82092 is not set -# CONFIG_I82365 is not set -CONFIG_PCMCIA_AU1X00=m -# CONFIG_PCMCIA_PB1X00 is not set -# CONFIG_PCMCIA_DB1X00 is not set -CONFIG_PCMCIA_XXS1500=y -# CONFIG_PCMCIA_VRC4173 is not set - -# -# PCI Hotplug Support -# -# CONFIG_HOTPLUG_PCI is not set -# CONFIG_HOTPLUG_PCI_COMPAQ is not set -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -# CONFIG_HOTPLUG_PCI_ACPI is not set -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_ELF=y -# CONFIG_MIPS32_COMPAT is not set -# CONFIG_MIPS32_O32 is not set -# CONFIG_MIPS32_N32 is not set -# CONFIG_BINFMT_ELF32 is not set -# CONFIG_BINFMT_MISC is not set -# CONFIG_PM is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_CMDLINE_PARTS is not set -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MTD_CFI_STAA is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set -# CONFIG_MTD_JEDEC is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_PB1000 is not set -# CONFIG_MTD_PB1500 is not set -# CONFIG_MTD_PB1100 is not set -# CONFIG_MTD_BOSPORUS is not set -CONFIG_MTD_XXS1500=y -# CONFIG_MTD_MTX1 is not set -# CONFIG_MTD_DB1X00 is not set -# CONFIG_MTD_CSTM_MIPS_IXX is not set -# CONFIG_MTD_OCELOT is not set -# CONFIG_MTD_LASAT is not set -# CONFIG_MTD_PCI is not set -# CONFIG_MTD_PCMCIA is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set -# CONFIG_MTD_DOC1000 is not set -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOCPROBE is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -# CONFIG_PARPORT_PC_PCMCIA is not set -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_IP22 is not set -# CONFIG_PARPORT_OTHER is not set -CONFIG_PARPORT_1284=y - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_BLK_STATS is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -# CONFIG_BLK_DEV_LVM is not set - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK_DEV is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_ROUTE_LARGE_TABLES=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -CONFIG_INET_ECN=y -CONFIG_SYN_COOKIES=y - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m -# CONFIG_IP_NF_NAT_LOCAL is not set -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -# CONFIG_IP_NF_COMPAT_IPCHAINS is not set -# CONFIG_IP_NF_COMPAT_IPFWADM is not set -CONFIG_IPV6=m - -# -# IPv6: Netfilter Configuration -# -CONFIG_IP6_NF_QUEUE=m -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set -CONFIG_VLAN_8021Q=m -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m -CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_RED=m -CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_TEQL=m -CONFIG_NET_SCH_TBF=m -CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DSMARK=m -CONFIG_NET_SCH_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -CONFIG_NET_CLS_TCINDEX=m -CONFIG_NET_CLS_ROUTE4=m -CONFIG_NET_CLS_ROUTE=y -CONFIG_NET_CLS_FW=m -CONFIG_NET_CLS_U32=m -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=m - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=m -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=m -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -CONFIG_BLK_DEV_IDECS=m -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -CONFIG_BLK_DEV_IDEPCI=y -# CONFIG_BLK_DEV_GENERIC is not set -# CONFIG_IDEPCI_SHARE_IRQ is not set -CONFIG_BLK_DEV_IDEDMA_PCI=y -CONFIG_BLK_DEV_OFFBOARD=y -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -# CONFIG_BLK_DEV_ADMA100 is not set -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_WDC_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_AMD74XX_OVERRIDE is not set -# CONFIG_BLK_DEV_CMD64X is not set -# CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_HPT34X_AUTODMA is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_PIIX is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_PDC202XX_BURST is not set -# CONFIG_BLK_DEV_PDC202XX_NEW is not set -# CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_BLK_DEV_SC1200 is not set -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SIIMAGE is not set -# CONFIG_BLK_DEV_SIS5513 is not set -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_IDE_CHIPSETS is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_IDE_MODES=y -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set -# CONFIG_BLK_DEV_ATARAID_SII is not set - -# -# SCSI support -# -CONFIG_SCSI=m -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=m -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 -# CONFIG_CHR_DEV_SG is not set -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_PPA is not set -# CONFIG_SCSI_IMM is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_NCR53C8XX is not set -# CONFIG_SCSI_SYM53C8XX is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_PCMCIA=y -CONFIG_PCMCIA_AHA152X=m -CONFIG_PCMCIA_FDOMAIN=m -CONFIG_PCMCIA_NINJA_SCSI=m -# CONFIG_PCMCIA_QLOGIC is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -CONFIG_MIPS_AU1X00_ENET=y -CONFIG_BCM5222_DUAL_PHY=y -# CONFIG_SUNLANCE is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -# CONFIG_STRIP is not set -# CONFIG_WAVELAN is not set -# CONFIG_ARLAN is not set -# CONFIG_AIRONET4500 is not set -# CONFIG_AIRONET4500_NONCS is not set -# CONFIG_AIRONET4500_PROC is not set -# CONFIG_AIRO is not set -# CONFIG_HERMES is not set -# CONFIG_PLX_HERMES is not set -# CONFIG_PCI_HERMES is not set -# CONFIG_PCMCIA_HERMES is not set -CONFIG_AIRO_CS=m -CONFIG_NET_WIRELESS=y - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -CONFIG_SHAPER=m - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_AXNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -# CONFIG_ARCNET_COM20020_CS is not set -# CONFIG_PCMCIA_IBMTR is not set -CONFIG_NET_PCMCIA_RADIO=y -# CONFIG_PCMCIA_RAYCS is not set -# CONFIG_PCMCIA_NETWAVE is not set -# CONFIG_PCMCIA_WAVELAN is not set -# CONFIG_AIRONET4500_CS is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input core support -# -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -CONFIG_SERIAL_NONSTANDARD=y -# CONFIG_COMPUTONE is not set -# CONFIG_ROCKETPORT is not set -# CONFIG_CYCLADES is not set -# CONFIG_DIGIEPCA is not set -# CONFIG_DIGI is not set -# CONFIG_ESPSERIAL is not set -# CONFIG_MOXA_INTELLIO is not set -# CONFIG_MOXA_SMARTIO is not set -# CONFIG_ISI is not set -# CONFIG_SYNCLINK is not set -# CONFIG_SYNCLINKMP is not set -# CONFIG_N_HDLC is not set -# CONFIG_RISCOM8 is not set -# CONFIG_SPECIALIX is not set -# CONFIG_SX is not set -# CONFIG_RIO is not set -# CONFIG_STALDRV is not set -# CONFIG_SERIAL_TX3912 is not set -# CONFIG_SERIAL_TX3912_CONSOLE is not set -# CONFIG_SERIAL_TXX9 is not set -# CONFIG_SERIAL_TXX9_CONSOLE is not set -CONFIG_AU1X00_UART=y -CONFIG_AU1X00_SERIAL_CONSOLE=y -# CONFIG_AU1X00_USB_TTY is not set -# CONFIG_AU1X00_USB_RAW is not set -# CONFIG_TXX927_SERIAL is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 -# CONFIG_PRINTER is not set -# CONFIG_PPDEV is not set -# CONFIG_TIPAR is not set - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_ALGOBIT=m -# CONFIG_I2C_PHILIPSPAR is not set -# CONFIG_I2C_ELV is not set -# CONFIG_I2C_VELLEMAN is not set -# CONFIG_SCx200_I2C is not set -# CONFIG_SCx200_ACB is not set -# CONFIG_I2C_ALGOPCF is not set -CONFIG_I2C_CHARDEV=m -# CONFIG_I2C_PROC is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_QIC02_TAPE is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_DEVICE_INTERFACE is not set -# CONFIG_IPMI_KCS is not set -# CONFIG_IPMI_WATCHDOG is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_SCx200_GPIO is not set -# CONFIG_AMD_PM768 is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# PCMCIA character devices -# -# CONFIG_PCMCIA_SERIAL_CS is not set -# CONFIG_SYNCLINK_CS is not set -# CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BEFS_DEBUG is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=2 -# CONFIG_CRAMFS is not set -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -# CONFIG_JFS_FS is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=m -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_ROOT_NFS=y -CONFIG_NFSD=y -CONFIG_NFSD_V3=y -# CONFIG_NFSD_TCP is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -CONFIG_ZISOFS_FS=m - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -# CONFIG_I2C_PARPORT is not set -CONFIG_VIDEO_BT848=m -# CONFIG_VIDEO_PMS is not set -CONFIG_VIDEO_BWQCAM=m -CONFIG_VIDEO_CQCAM=m -CONFIG_VIDEO_W9966=m -CONFIG_VIDEO_CPIA=m -# CONFIG_VIDEO_CPIA_PP is not set -CONFIG_VIDEO_CPIA_USB=m -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_ZORAN_BUZ is not set -# CONFIG_VIDEO_ZORAN_DC10 is not set -# CONFIG_VIDEO_ZORAN_LML33 is not set -# CONFIG_VIDEO_ZR36120 is not set -# CONFIG_VIDEO_MEYE is not set - -# -# Radio Adapters -# -# CONFIG_RADIO_GEMTEK_PCI is not set -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_MAESTRO is not set -# CONFIG_RADIO_MIROPCM20 is not set - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y -# CONFIG_MDA_CONSOLE is not set - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_RIVA is not set -# CONFIG_FB_CLGEN is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_PM3 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_INTEL is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_E1356 is not set -CONFIG_FB_MB86290=y -CONFIG_FB_LYNX3DM=y -# CONFIG_FB_VIRTUAL is not set -CONFIG_FBCON_ADVANCED=y -# CONFIG_FBCON_MFB is not set -# CONFIG_FBCON_CFB2 is not set -# CONFIG_FBCON_CFB4 is not set -# CONFIG_FBCON_CFB8 is not set -CONFIG_FBCON_CFB16=y -# CONFIG_FBCON_CFB24 is not set -# CONFIG_FBCON_CFB32 is not set -# CONFIG_FBCON_AFB is not set -# CONFIG_FBCON_ILBM is not set -# CONFIG_FBCON_IPLAN2P2 is not set -# CONFIG_FBCON_IPLAN2P4 is not set -# CONFIG_FBCON_IPLAN2P8 is not set -# CONFIG_FBCON_MAC is not set -# CONFIG_FBCON_VGA_PLANES is not set -# CONFIG_FBCON_VGA is not set -# CONFIG_FBCON_HGA is not set -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set - -# -# Sound -# -CONFIG_SOUND=y -# CONFIG_SOUND_ALI5455 is not set -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_MIDI_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_MAESTRO3 is not set -# CONFIG_SOUND_FORTE is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_RME96XX is not set -# CONFIG_SOUND_SONICVIBES is not set -CONFIG_SOUND_AU1X00=y -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -# CONFIG_MIDI_VIA82CXXX is not set -# CONFIG_SOUND_OSS is not set -# CONFIG_SOUND_TVMIXER is not set - -# -# USB support -# -CONFIG_USB=y -# CONFIG_USB_DEBUG is not set -# CONFIG_USB_DEVICEFS is not set -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -CONFIG_USB_OHCI=y -CONFIG_USB_NON_PCI_OHCI=y -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_MIDI is not set -CONFIG_USB_STORAGE=m -CONFIG_USB_STORAGE_DEBUG=y -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -CONFIG_USB_STORAGE_SDDR09=y -# CONFIG_USB_STORAGE_SDDR55 is not set -CONFIG_USB_STORAGE_JUMPSHOT=y -# CONFIG_USB_ACM is not set -CONFIG_USB_PRINTER=m -CONFIG_USB_HID=m -# CONFIG_USB_HIDINPUT is not set -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -# CONFIG_USB_DSBR is not set -CONFIG_USB_DABUSB=m -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_KAWETH=m -CONFIG_USB_CATC=m -CONFIG_USB_CDCETHER=m -CONFIG_USB_USBNET=m -CONFIG_USB_USS720=m - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_DEBUG is not set -CONFIG_USB_SERIAL_GENERIC=y -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_IPAQ is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_EDGEPORT_TI is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_KLSI is not set -# CONFIG_USB_SERIAL_KOBIL_SCT is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_XIRCOM is not set -# CONFIG_USB_SERIAL_OMNINET is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_TIGL is not set -# CONFIG_USB_BRLVGER is not set -CONFIG_USB_LCD=m - -# -# Bluetooth support -# -# CONFIG_BLUEZ is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_RUNTIME_DEBUG is not set -# CONFIG_KGDB is not set -# CONFIG_GDB_CONSOLE is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MIPS_UNCACHED is not set - -# -# Library routines -# -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/linux/linux-xxs1500-2.4.21/zboot-Makefile-flags.diff b/linux/linux-xxs1500-2.4.21/zboot-Makefile-flags.diff deleted file mode 100644 index da17a12f38..0000000000 --- a/linux/linux-xxs1500-2.4.21/zboot-Makefile-flags.diff +++ /dev/null @@ -1,11 +0,0 @@ ---- arch/mips/zboot/Makefile.o 2004-10-09 19:44:27.380145288 +0200 -+++ arch/mips/zboot/Makefile 2004-10-09 19:46:17.643382728 +0200 -@@ -27,7 +27,7 @@ - - CFLAGS := $(CPPFLAGS) -O2 -D__BOOTER__ \ - -fomit-frame-pointer -fno-strict-aliasing -fno-common \ -- -G 0 -mno-abicalls -fno-pic -mcpu=r4600 -mips2 \ -+ -G 0 -mno-abicalls -fno-pic -mabi=32 -march=mips32 -mips32 \ - -I$(TOPDIR)/arch/$(ARCH)/zboot/include \ - -I$(TOPDIR)/include/asm - AFLAGS += -D__BOOTER__ diff --git a/linux/linux-xxs1500_2.4.21.bb b/linux/linux-xxs1500_2.4.21.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/mnci-ramses-2.4.21-rmk2-pxa1.bb b/linux/mnci-ramses-2.4.21-rmk2-pxa1.bb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/mnci-ramses-2.4.21-rmk2-pxa1/diff-2.4.21-rmk2-pxa1.gz b/linux/mnci-ramses-2.4.21-rmk2-pxa1/diff-2.4.21-rmk2-pxa1.gz deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/linux/mnci-ramses-2.4.21-rmk2-pxa1/mnci-combined.patch b/linux/mnci-ramses-2.4.21-rmk2-pxa1/mnci-combined.patch deleted file mode 100644 index 55d91b9a36..0000000000 --- a/linux/mnci-ramses-2.4.21-rmk2-pxa1/mnci-combined.patch +++ /dev/null @@ -1,19914 +0,0 @@ - -# This is a cumulative patch consisting of: -# -# linux-vtcomparison.patch -# linux-mkdep.patch -# linux-iw241_we16-6.patch -# arm-noshortloads.patch -# pxa-pcmcia.patch -# pxa-smc91x.patch -# pxa-usb.patch -# pxa-usbeth.patch -# pxa-irda.patch -# pxa-ac97.patch -# pxa-timerint.patch -# fb-buffered.patch -# fb-turn180.patch -# i2c-ds1337.patch -# keyb-input.patch -# keyb-module.patch -# logo-noscrollregion.patch -# net-dhcp-timeout.patch -# pm.patch -# swap-performance.patch -# small-nocramdisk.patch -# smc91x-ethtool.patch -# ucb1x00.patch -# vmalloc.patch -# usb-sl811.patch -# orinoco013e.patch -# ramses.patch -# ramses-ac97.patch -# ramses-keyb.patch -# ramses-mtd.patch -# ramses-orinoco-ignorecis.patch -# ramses-pcmcia.patch -# ramses-serial.patch -# ramses-smc91x.patch -# ramses-sysctl.patch -# ramses-ucb1x00-dejitter.patch -# ramses-lcd.patch -# ramses-usb.patch -# ramses-corevolt.patch -# wedge.patch -# usb-sonycamera.patch -# ramses-ucb1x00-rotate.patch -# vt-noblank.patch -# -# Patch managed by http://www.holgerschurig.de/patcher.html -# - ---- linux-2.4.21/Makefile~linux-mkdep -+++ linux-2.4.21/Makefile -@@ -14,10 +14,11 @@ - else echo sh; fi ; fi) - TOPDIR := $(shell /bin/pwd) - -+PATH := /usr/local/arm/3.3/bin:$(PATH) - HPATH = $(TOPDIR)/include - FINDHPATH = $(HPATH)/asm $(HPATH)/linux $(HPATH)/scsi $(HPATH)/net $(HPATH)/math-emu - --HOSTCC = gcc -+HOSTCC = ccache gcc - HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer - - CROSS_COMPILE = arm-linux- -@@ -28,7 +29,7 @@ - - AS = $(CROSS_COMPILE)as - LD = $(CROSS_COMPILE)ld --CC = $(CROSS_COMPILE)gcc -+CC = ccache $(CROSS_COMPILE)gcc - CPP = $(CC) -E - AR = $(CROSS_COMPILE)ar - NM = $(CROSS_COMPILE)nm -@@ -80,6 +81,7 @@ - # makefile but the arguement can be passed to make if needed. - # - -+export INSTALL_MOD_PATH = /tftpboot/ramses2 - MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) - export MODLIB - -@@ -140,7 +142,6 @@ - DRIVERS-y += drivers/serial/serial.o \ - drivers/char/char.o \ - drivers/block/block.o \ -- drivers/misc/misc.o \ - drivers/net/net.o - DRIVERS-$(CONFIG_AGP) += drivers/char/agp/agp.o - DRIVERS-$(CONFIG_DRM_NEW) += drivers/char/drm/drm.o -@@ -197,6 +198,7 @@ - DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o - DRIVERS-$(CONFIG_PLD) += drivers/pld/pld.o - DRIVERS-$(CONFIG_ARCH_AT91RM9200) += drivers/at91/at91drv.o -+DRIVERS-y += drivers/misc/misc.o - - DRIVERS := $(DRIVERS-y) - -@@ -416,7 +418,7 @@ - endif - .PHONY: _modinst_post - _modinst_post: _modinst_post_pcmcia -- if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi -+# if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi - - # Backwards compatibilty symlinks for people still using old versions - # of pcmcia-cs with hard coded pathnames on insmod. Remove -@@ -495,7 +497,7 @@ - ifdef CONFIG_MODVERSIONS - $(MAKE) update-modverfile - endif -- scripts/mkdep -- `find $(FINDHPATH) \( -name SCCS -o -name .svn \) -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend -+ $(foreach, dir, $(FINDHPATH), scripts/mkdep -- `find $(dir) -name SCCS -prune -o -follow -name \*.h ! -name modversions.h -print` >> .hdepend) - scripts/mkdep -- init/*.c > .depend - - ifdef CONFIG_MODVERSIONS -@@ -574,3 +576,14 @@ - . scripts/mkversion > .version ; \ - rpm -ta $(TOPDIR)/../$(KERNELPATH).tar.gz ; \ - rm $(TOPDIR)/../$(KERNELPATH).tar.gz -+ -+ -+ -+# -+# Burn Linux Image for ArmBoot using the bdi2000 -+# -+burn burn_zImage: -+ python ../hwtester/burner.py arch/arm/boot/zImage 0x40000 -+ -+publish: arch/arm/boot/zImage -+ cp arch/arm/boot/zImage /tftpboot/bdi/zImage.testing ---- linux-2.4.21/arch/arm/Makefile~arm-noshortloads -+++ linux-2.4.21/arch/arm/Makefile -@@ -55,8 +55,8 @@ - #tune-$(CONFIG_CPU_XSCALE) :=-mtune=xscale - tune-$(CONFIG_CPU_XSCALE) :=-mtune=strongarm - --CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm --CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm -+CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -msoft-float -Uarm -+CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -msoft-float -Uarm - AFLAGS +=$(apcs-y) $(arch-y) -msoft-float - - ifeq ($(CONFIG_CPU_26),y) -@@ -289,7 +289,7 @@ - arch/arm/kernel arch/arm/mm arch/arm/lib: dummy - $(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" $(subst $@, _dir_$@, $@) - --bzImage zImage zinstall Image xipImage bootpImage install: vmlinux -+bzImage zImage zinstall Image xipImage bootpImage: vmlinux - @$(MAKEBOOT) $@ - - CLEAN_FILES += \ ---- linux-2.4.21/arch/arm/config.in~pm -+++ linux-2.4.21/arch/arm/config.in -@@ -152,6 +152,7 @@ - dep_bool ' Intel DBPXA250 Development Platform' CONFIG_ARCH_LUBBOCK $CONFIG_ARCH_PXA - dep_bool ' Accelent Xscale IDP' CONFIG_ARCH_PXA_IDP $CONFIG_ARCH_PXA - dep_bool ' Intrinsyc CerfBoard' CONFIG_ARCH_PXA_CERF $CONFIG_ARCH_PXA -+dep_bool ' M und N Ramses' CONFIG_ARCH_RAMSES $CONFIG_ARCH_PXA - dep_bool ' Trizeps-II MT6N' CONFIG_ARCH_TRIZEPS2 $CONFIG_ARCH_PXA - - if [ "$CONFIG_ARCH_PXA_CERF" = "y" ]; then -@@ -586,6 +587,7 @@ - tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF - tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC - dep_bool 'Power Management support (experimental)' CONFIG_PM $CONFIG_EXPERIMENTAL -+dep_bool 'Advanced power management emulation support' CONFIG_APM $CONFIG_PM - dep_tristate 'RISC OS personality' CONFIG_ARTHUR $CONFIG_CPU_32 - string 'Default kernel command string' CONFIG_CMDLINE "" - ---- /dev/null -+++ linux-2.4.21/arch/arm/def-configs/ramses -@@ -0,0 +1,1128 @@ -+# -+# Automatically generated by make menuconfig: don't edit -+# -+CONFIG_ARM=y -+# CONFIG_EISA is not set -+# CONFIG_SBUS is not set -+# CONFIG_MCA is not set -+CONFIG_UID16=y -+CONFIG_RWSEM_GENERIC_SPINLOCK=y -+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -+# CONFIG_GENERIC_BUST_SPINLOCK is not set -+# CONFIG_GENERIC_ISA_DMA is not set -+ -+# -+# Code maturity level options -+# -+CONFIG_EXPERIMENTAL=y -+# CONFIG_OBSOLETE is not set -+ -+# -+# Loadable module support -+# -+CONFIG_MODULES=y -+# CONFIG_MODVERSIONS is not set -+CONFIG_KMOD=y -+ -+# -+# System Type -+# -+# CONFIG_ARCH_ANAKIN is not set -+# CONFIG_ARCH_ARCA5K is not set -+# CONFIG_ARCH_CLPS7500 is not set -+# CONFIG_ARCH_CLPS711X is not set -+# CONFIG_ARCH_CO285 is not set -+CONFIG_ARCH_PXA=y -+# CONFIG_ARCH_EBSA110 is not set -+# CONFIG_ARCH_CAMELOT is not set -+# CONFIG_ARCH_FOOTBRIDGE is not set -+# CONFIG_ARCH_INTEGRATOR is not set -+# CONFIG_ARCH_OMAHA is not set -+# CONFIG_ARCH_L7200 is not set -+# CONFIG_ARCH_MX1ADS is not set -+# CONFIG_ARCH_RPC is not set -+# CONFIG_ARCH_RISCSTATION is not set -+# CONFIG_ARCH_SA1100 is not set -+# CONFIG_ARCH_SHARK is not set -+# CONFIG_ARCH_AT91RM9200 is not set -+ -+# -+# Archimedes/A5000 Implementations -+# -+# CONFIG_ARCH_ARC is not set -+# CONFIG_ARCH_A5K is not set -+ -+# -+# Footbridge Implementations -+# -+# CONFIG_ARCH_CATS is not set -+# CONFIG_ARCH_PERSONAL_SERVER is not set -+# CONFIG_ARCH_EBSA285_ADDIN is not set -+# CONFIG_ARCH_EBSA285_HOST is not set -+# CONFIG_ARCH_NETWINDER is not set -+ -+# -+# SA11x0 Implementations -+# -+# CONFIG_SA1100_ACCELENT is not set -+# CONFIG_SA1100_ASSABET is not set -+# CONFIG_ASSABET_NEPONSET is not set -+# CONFIG_SA1100_ADSAGC is not set -+# CONFIG_SA1100_ADSBITSY is not set -+# CONFIG_SA1100_ADSBITSYPLUS is not set -+# CONFIG_SA1100_BRUTUS is not set -+# CONFIG_SA1100_CEP is not set -+# CONFIG_SA1100_CERF is not set -+# CONFIG_SA1100_H3100 is not set -+# CONFIG_SA1100_H3600 is not set -+# CONFIG_SA1100_H3800 is not set -+# CONFIG_SA1100_H3XXX is not set -+# CONFIG_H3600_SLEEVE is not set -+# CONFIG_SA1100_EXTENEX1 is not set -+# CONFIG_SA1100_FLEXANET is not set -+# CONFIG_SA1100_FREEBIRD is not set -+# CONFIG_SA1100_FRODO is not set -+# CONFIG_SA1100_GRAPHICSCLIENT is not set -+# CONFIG_SA1100_GRAPHICSMASTER is not set -+# CONFIG_SA1100_HACKKIT is not set -+# CONFIG_SA1100_BADGE4 is not set -+# CONFIG_SA1100_JORNADA720 is not set -+# CONFIG_SA1100_HUW_WEBPANEL is not set -+# CONFIG_SA1100_ITSY is not set -+# CONFIG_SA1100_LART is not set -+# CONFIG_SA1100_NANOENGINE is not set -+# CONFIG_SA1100_OMNIMETER is not set -+# CONFIG_SA1100_PANGOLIN is not set -+# CONFIG_SA1100_PLEB is not set -+# CONFIG_SA1100_PT_SYSTEM3 is not set -+# CONFIG_SA1100_SHANNON is not set -+# CONFIG_SA1100_SHERMAN is not set -+# CONFIG_SA1100_SIMPAD is not set -+# CONFIG_SA1100_SIMPUTER is not set -+# CONFIG_SA1100_PFS168 is not set -+# CONFIG_SA1100_VICTOR is not set -+# CONFIG_SA1100_XP860 is not set -+# CONFIG_SA1100_YOPY is not set -+# CONFIG_SA1100_USB is not set -+# CONFIG_SA1100_USB_NETLINK is not set -+# CONFIG_SA1100_USB_CHAR is not set -+# CONFIG_SA1100_SSP is not set -+ -+# -+# AT91RM9200 Implementations -+# -+# CONFIG_ARCH_AT91RM9200DK is not set -+ -+# -+# Intel PXA250/210 Implementations -+# -+# CONFIG_ARCH_LUBBOCK is not set -+# CONFIG_ARCH_PXA_IDP is not set -+# CONFIG_ARCH_PXA_CERF is not set -+CONFIG_ARCH_RAMSES=y -+# CONFIG_ARCH_TRIZEPS2 is not set -+CONFIG_PXA_USB=m -+CONFIG_PXA_USB_NETLINK=m -+CONFIG_PXA_USB_CHAR=m -+ -+# -+# CLPS711X/EP721X Implementations -+# -+# CONFIG_ARCH_AUTCPU12 is not set -+# CONFIG_ARCH_CDB89712 is not set -+# CONFIG_ARCH_CLEP7312 is not set -+# CONFIG_ARCH_EDB7211 is not set -+# CONFIG_ARCH_FORTUNET is not set -+# CONFIG_ARCH_GUIDEA07 is not set -+# CONFIG_ARCH_P720T is not set -+# CONFIG_ARCH_EP7211 is not set -+# CONFIG_ARCH_EP7212 is not set -+# CONFIG_ARCH_ACORN is not set -+# CONFIG_PLD is not set -+# CONFIG_FOOTBRIDGE is not set -+# CONFIG_FOOTBRIDGE_HOST is not set -+# CONFIG_FOOTBRIDGE_ADDIN is not set -+CONFIG_CPU_32=y -+# CONFIG_CPU_26 is not set -+# CONFIG_CPU_ARM610 is not set -+# CONFIG_CPU_ARM710 is not set -+# CONFIG_CPU_ARM720T is not set -+# CONFIG_CPU_ARM920T is not set -+# CONFIG_CPU_ARM922T is not set -+# CONFIG_CPU_ARM926T is not set -+# CONFIG_CPU_ARM1020 is not set -+# CONFIG_CPU_ARM1020E is not set -+# CONFIG_CPU_ARM1022 is not set -+# CONFIG_CPU_ARM1026 is not set -+# CONFIG_CPU_SA110 is not set -+# CONFIG_CPU_SA1100 is not set -+CONFIG_CPU_32v5=y -+CONFIG_CPU_XSCALE=y -+# CONFIG_XSCALE_CACHE_ERRATA is not set -+# CONFIG_CPU_32v3 is not set -+# CONFIG_CPU_32v4 is not set -+# CONFIG_DISCONTIGMEM is not set -+ -+# -+# General setup -+# -+# CONFIG_PCI is not set -+# CONFIG_ISA is not set -+# CONFIG_ISA_DMA is not set -+CONFIG_ZBOOT_ROM=y -+CONFIG_ZBOOT_ROM_TEXT=00040000 -+CONFIG_ZBOOT_ROM_BSS=a00c0000 -+CONFIG_CPU_FREQ=y -+CONFIG_HOTPLUG=y -+ -+# -+# PCMCIA/CardBus support -+# -+CONFIG_PCMCIA=y -+# CONFIG_I82092 is not set -+# CONFIG_I82365 is not set -+# CONFIG_TCIC is not set -+# CONFIG_PCMCIA_CLPS6700 is not set -+# CONFIG_PCMCIA_SA1100 is not set -+CONFIG_PCMCIA_PXA=y -+ -+# -+# MMC device drivers -+# -+CONFIG_MMC=m -+CONFIG_MMC_PXA=m -+CONFIG_MMC_BLOCK=m -+CONFIG_MMC_PARTITIONS=y -+CONFIG_NET=y -+CONFIG_SYSVIPC=y -+# CONFIG_BSD_PROCESS_ACCT is not set -+CONFIG_SYSCTL=y -+# CONFIG_XIP_KERNEL is not set -+CONFIG_FPE_NWFPE=y -+# CONFIG_FPE_NWFPE_XP is not set -+# CONFIG_FPE_FASTFPE is not set -+CONFIG_KCORE_ELF=y -+# CONFIG_KCORE_AOUT is not set -+# CONFIG_BINFMT_AOUT is not set -+CONFIG_BINFMT_ELF=y -+# CONFIG_BINFMT_MISC is not set -+CONFIG_PM=y -+CONFIG_APM=y -+# CONFIG_ARTHUR is not set -+CONFIG_CMDLINE="debug" -+CONFIG_ALIGNMENT_TRAP=y -+ -+# -+# Parallel port support -+# -+# CONFIG_PARPORT is not set -+ -+# -+# Memory Technology Devices (MTD) -+# -+CONFIG_MTD=y -+# CONFIG_MTD_DEBUG is not set -+CONFIG_MTD_PARTITIONS=y -+# CONFIG_MTD_CONCAT is not set -+# CONFIG_MTD_REDBOOT_PARTS is not set -+# CONFIG_MTD_CMDLINE_PARTS is not set -+# CONFIG_MTD_AFS_PARTS is not set -+CONFIG_MTD_CHAR=y -+CONFIG_MTD_BLOCK=y -+# CONFIG_FTL is not set -+# CONFIG_NFTL is not set -+ -+# -+# RAM/ROM/Flash chip drivers -+# -+CONFIG_MTD_CFI=y -+# CONFIG_MTD_JEDECPROBE is not set -+CONFIG_MTD_GEN_PROBE=y -+CONFIG_MTD_CFI_ADV_OPTIONS=y -+CONFIG_MTD_CFI_NOSWAP=y -+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -+CONFIG_MTD_CFI_GEOMETRY=y -+# CONFIG_MTD_CFI_B1 is not set -+# CONFIG_MTD_CFI_B2 is not set -+CONFIG_MTD_CFI_B4=y -+# CONFIG_MTD_CFI_B8 is not set -+# CONFIG_MTD_CFI_I1 is not set -+CONFIG_MTD_CFI_I2=y -+# CONFIG_MTD_CFI_I4 is not set -+# CONFIG_MTD_CFI_I8 is not set -+CONFIG_MTD_CFI_INTELEXT=y -+# CONFIG_MTD_CFI_AMDSTD is not set -+# CONFIG_MTD_CFI_STAA is not set -+# CONFIG_MTD_RAM is not set -+# CONFIG_MTD_ROM is not set -+# CONFIG_MTD_ABSENT is not set -+# CONFIG_MTD_OBSOLETE_CHIPS is not set -+# CONFIG_MTD_AMDSTD is not set -+# CONFIG_MTD_SHARP is not set -+# CONFIG_MTD_JEDEC is not set -+ -+# -+# Mapping drivers for chip access -+# -+# CONFIG_MTD_PHYSMAP is not set -+# CONFIG_MTD_LUBBOCK is not set -+CONFIG_MTD_RAMSES=y -+# CONFIG_MTD_NORA is not set -+# CONFIG_MTD_ARM_INTEGRATOR is not set -+# CONFIG_MTD_CDB89712 is not set -+# CONFIG_MTD_SA1100 is not set -+# CONFIG_MTD_DC21285 is not set -+# CONFIG_MTD_IQ80310 is not set -+# CONFIG_MTD_FORTUNET is not set -+# CONFIG_MTD_EPXA is not set -+# CONFIG_MTD_AUTCPU12 is not set -+# CONFIG_MTD_EDB7312 is not set -+# CONFIG_MTD_IMPA7 is not set -+# CONFIG_MTD_CEIVA is not set -+# CONFIG_MTD_PCI is not set -+# CONFIG_MTD_PCMCIA is not set -+ -+# -+# Self-contained MTD device drivers -+# -+# CONFIG_MTD_PMC551 is not set -+# CONFIG_MTD_SLRAM is not set -+# CONFIG_MTD_MTDRAM is not set -+# CONFIG_MTD_BLKMTD is not set -+# CONFIG_MTD_DOC1000 is not set -+# CONFIG_MTD_DOC2000 is not set -+# CONFIG_MTD_DOC2001 is not set -+# CONFIG_MTD_DOCPROBE is not set -+ -+# -+# NAND Flash Device Drivers -+# -+# CONFIG_MTD_NAND is not set -+ -+# -+# Plug and Play configuration -+# -+# CONFIG_PNP is not set -+# CONFIG_ISAPNP is not set -+ -+# -+# Block devices -+# -+# CONFIG_BLK_DEV_FD is not set -+# CONFIG_BLK_DEV_XD is not set -+# CONFIG_PARIDE is not set -+# CONFIG_BLK_CPQ_DA is not set -+# CONFIG_BLK_CPQ_CISS_DA is not set -+# CONFIG_CISS_SCSI_TAPE is not set -+# CONFIG_BLK_DEV_DAC960 is not set -+# CONFIG_BLK_DEV_UMEM is not set -+CONFIG_BLK_DEV_LOOP=m -+CONFIG_BLK_DEV_NBD=m -+# CONFIG_BLK_DEV_RAM is not set -+# CONFIG_BLK_DEV_INITRD is not set -+CONFIG_BLK_STATS=y -+ -+# -+# Multi-device support (RAID and LVM) -+# -+# CONFIG_MD is not set -+# CONFIG_BLK_DEV_MD is not set -+# CONFIG_MD_LINEAR is not set -+# CONFIG_MD_RAID0 is not set -+# CONFIG_MD_RAID1 is not set -+# CONFIG_MD_RAID5 is not set -+# CONFIG_MD_MULTIPATH is not set -+# CONFIG_BLK_DEV_LVM is not set -+ -+# -+# Networking options -+# -+CONFIG_PACKET=y -+# CONFIG_PACKET_MMAP is not set -+CONFIG_NETLINK_DEV=m -+# CONFIG_NETFILTER is not set -+# CONFIG_FILTER is not set -+CONFIG_UNIX=y -+CONFIG_INET=y -+# CONFIG_IP_MULTICAST is not set -+# CONFIG_IP_ADVANCED_ROUTER is not set -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+# CONFIG_IP_PNP_BOOTP is not set -+# CONFIG_IP_PNP_RARP is not set -+CONFIG_NET_IPIP=m -+CONFIG_NET_IPGRE=m -+# CONFIG_ARPD is not set -+# CONFIG_INET_ECN is not set -+# CONFIG_SYN_COOKIES is not set -+# CONFIG_IPV6 is not set -+# CONFIG_KHTTPD is not set -+# CONFIG_ATM is not set -+CONFIG_VLAN_8021Q=m -+# CONFIG_IPX is not set -+# CONFIG_ATALK is not set -+ -+# -+# Appletalk devices -+# -+# CONFIG_DEV_APPLETALK is not set -+# CONFIG_DECNET is not set -+CONFIG_BRIDGE=m -+# CONFIG_X25 is not set -+# CONFIG_LAPB is not set -+# CONFIG_LLC is not set -+# CONFIG_NET_DIVERT is not set -+# CONFIG_ECONET is not set -+# CONFIG_WAN_ROUTER is not set -+# CONFIG_NET_FASTROUTE is not set -+# CONFIG_NET_HW_FLOWCONTROL is not set -+ -+# -+# QoS and/or fair queueing -+# -+# CONFIG_NET_SCHED is not set -+ -+# -+# Network testing -+# -+# CONFIG_NET_PKTGEN is not set -+ -+# -+# Network device support -+# -+CONFIG_NETDEVICES=y -+ -+# -+# ARCnet devices -+# -+# CONFIG_ARCNET is not set -+# CONFIG_DUMMY is not set -+# CONFIG_BONDING is not set -+# CONFIG_EQUALIZER is not set -+# CONFIG_TUN is not set -+# CONFIG_ETHERTAP is not set -+ -+# -+# Ethernet (10 or 100Mbit) -+# -+CONFIG_NET_ETHERNET=y -+# CONFIG_ARM_AM79C961A is not set -+# CONFIG_ARM_CIRRUS is not set -+# CONFIG_SUNLANCE is not set -+# CONFIG_SUNBMAC is not set -+# CONFIG_SUNQE is not set -+# CONFIG_SUNGEM is not set -+# CONFIG_NET_VENDOR_3COM is not set -+# CONFIG_LANCE is not set -+CONFIG_NET_VENDOR_SMC=y -+# CONFIG_WD80x3 is not set -+# CONFIG_ULTRAMCA is not set -+# CONFIG_ULTRA is not set -+# CONFIG_ULTRA32 is not set -+# CONFIG_SMC9194 is not set -+CONFIG_SMC91X=y -+# CONFIG_NET_VENDOR_RACAL is not set -+# CONFIG_NET_ISA is not set -+# CONFIG_NET_PCI is not set -+# CONFIG_NET_POCKET is not set -+ -+# -+# Ethernet (1000 Mbit) -+# -+# CONFIG_ACENIC is not set -+# CONFIG_DL2K is not set -+# CONFIG_E1000 is not set -+# CONFIG_MYRI_SBUS is not set -+# CONFIG_NS83820 is not set -+# CONFIG_HAMACHI is not set -+# CONFIG_YELLOWFIN is not set -+# CONFIG_R8169 is not set -+# CONFIG_SK98LIN is not set -+# CONFIG_TIGON3 is not set -+# CONFIG_FDDI is not set -+# CONFIG_HIPPI is not set -+# CONFIG_PLIP is not set -+CONFIG_PPP=m -+# CONFIG_PPP_MULTILINK is not set -+# CONFIG_PPP_FILTER is not set -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPPOE=m -+# CONFIG_SLIP is not set -+ -+# -+# Wireless LAN (non-hamradio) -+# -+CONFIG_NET_RADIO=y -+# CONFIG_STRIP is not set -+# CONFIG_WAVELAN is not set -+# CONFIG_ARLAN is not set -+# CONFIG_AIRONET4500 is not set -+# CONFIG_AIRONET4500_NONCS is not set -+# CONFIG_AIRONET4500_PROC is not set -+CONFIG_HERMES=m -+CONFIG_PCMCIA_HERMES=m -+# CONFIG_AIRO_CS is not set -+CONFIG_NET_WIRELESS=y -+ -+# -+# Token Ring devices -+# -+# CONFIG_TR is not set -+# CONFIG_NET_FC is not set -+# CONFIG_RCPCI is not set -+# CONFIG_SHAPER is not set -+ -+# -+# Wan interfaces -+# -+# CONFIG_WAN is not set -+ -+# -+# PCMCIA network device support -+# -+CONFIG_NET_PCMCIA=y -+# CONFIG_PCMCIA_3C589 is not set -+# CONFIG_PCMCIA_3C574 is not set -+# CONFIG_PCMCIA_FMVJ18X is not set -+# CONFIG_PCMCIA_PCNET is not set -+# CONFIG_PCMCIA_AXNET is not set -+# CONFIG_PCMCIA_NMCLAN is not set -+# CONFIG_PCMCIA_SMC91C92 is not set -+# CONFIG_PCMCIA_XIRC2PS is not set -+# CONFIG_ARCNET_COM20020_CS is not set -+# CONFIG_PCMCIA_IBMTR is not set -+# CONFIG_NET_PCMCIA_RADIO is not set -+ -+# -+# Amateur Radio support -+# -+# CONFIG_HAMRADIO is not set -+ -+# -+# IrDA (infrared) support -+# -+CONFIG_IRDA=m -+CONFIG_IRLAN=m -+CONFIG_IRNET=m -+CONFIG_IRCOMM=m -+CONFIG_IRDA_ULTRA=y -+CONFIG_IRDA_CACHE_LAST_LSAP=y -+CONFIG_IRDA_FAST_RR=y -+CONFIG_IRDA_DEBUG=y -+ -+# -+# Infrared-port device drivers -+# -+CONFIG_IRTTY_SIR=m -+CONFIG_IRPORT_SIR=m -+# CONFIG_DONGLE is not set -+# CONFIG_USB_IRDA is not set -+# CONFIG_NSC_FIR is not set -+# CONFIG_WINBOND_FIR is not set -+# CONFIG_TOSHIBA_OLD is not set -+# CONFIG_TOSHIBA_FIR is not set -+# CONFIG_SMC_IRCC_FIR is not set -+# CONFIG_ALI_FIR is not set -+# CONFIG_VLSI_FIR is not set -+CONFIG_PXA_FIR=m -+ -+# -+# ATA/ATAPI/MFM/RLL support -+# -+# CONFIG_IDE is not set -+# CONFIG_BLK_DEV_IDE_MODES is not set -+# CONFIG_BLK_DEV_HD is not set -+ -+# -+# SCSI support -+# -+CONFIG_SCSI=m -+CONFIG_BLK_DEV_SD=m -+CONFIG_SD_EXTRA_DEVS=4 -+# CONFIG_CHR_DEV_ST is not set -+# CONFIG_CHR_DEV_OSST is not set -+# CONFIG_BLK_DEV_SR is not set -+# CONFIG_CHR_DEV_SG is not set -+# CONFIG_SCSI_DEBUG_QUEUES is not set -+# CONFIG_SCSI_MULTI_LUN is not set -+# CONFIG_SCSI_CONSTANTS is not set -+# CONFIG_SCSI_LOGGING is not set -+ -+# -+# SCSI low-level drivers -+# -+# CONFIG_SCSI_7000FASST is not set -+# CONFIG_SCSI_ACARD is not set -+# CONFIG_SCSI_AHA152X is not set -+# CONFIG_SCSI_AHA1542 is not set -+# CONFIG_SCSI_AHA1740 is not set -+# CONFIG_SCSI_AACRAID is not set -+# CONFIG_SCSI_AIC7XXX is not set -+# CONFIG_SCSI_AIC79XX is not set -+# CONFIG_SCSI_AIC7XXX_OLD is not set -+# CONFIG_SCSI_DPT_I2O is not set -+# CONFIG_SCSI_ADVANSYS is not set -+# CONFIG_SCSI_IN2000 is not set -+# CONFIG_SCSI_AM53C974 is not set -+# CONFIG_SCSI_MEGARAID is not set -+# CONFIG_SCSI_BUSLOGIC is not set -+# CONFIG_SCSI_DMX3191D is not set -+# CONFIG_SCSI_DTC3280 is not set -+# CONFIG_SCSI_EATA is not set -+# CONFIG_SCSI_EATA_DMA is not set -+# CONFIG_SCSI_EATA_PIO is not set -+# CONFIG_SCSI_FUTURE_DOMAIN is not set -+# CONFIG_SCSI_GDTH is not set -+# CONFIG_SCSI_GENERIC_NCR5380 is not set -+# CONFIG_SCSI_INITIO is not set -+# CONFIG_SCSI_INIA100 is not set -+# CONFIG_SCSI_NCR53C406A is not set -+# CONFIG_SCSI_NCR53C7xx is not set -+# CONFIG_SCSI_PAS16 is not set -+# CONFIG_SCSI_PCI2000 is not set -+# CONFIG_SCSI_PCI2220I is not set -+# CONFIG_SCSI_PSI240I is not set -+# CONFIG_SCSI_QLOGIC_FAS is not set -+# CONFIG_SCSI_SIM710 is not set -+# CONFIG_SCSI_SYM53C416 is not set -+# CONFIG_SCSI_T128 is not set -+# CONFIG_SCSI_U14_34F is not set -+# CONFIG_SCSI_NSP32 is not set -+# CONFIG_SCSI_DEBUG is not set -+ -+# -+# PCMCIA SCSI adapter support -+# -+# CONFIG_SCSI_PCMCIA is not set -+ -+# -+# I2O device support -+# -+# CONFIG_I2O is not set -+# CONFIG_I2O_BLOCK is not set -+# CONFIG_I2O_LAN is not set -+# CONFIG_I2O_SCSI is not set -+# CONFIG_I2O_PROC is not set -+ -+# -+# ISDN subsystem -+# -+# CONFIG_ISDN is not set -+ -+# -+# Input core support -+# -+CONFIG_INPUT=y -+CONFIG_INPUT_KEYBDEV=y -+CONFIG_INPUT_RAMSES_KEYB=y -+CONFIG_INPUT_RAMSES_WEDGE=y -+# CONFIG_INPUT_MOUSEDEV is not set -+# CONFIG_INPUT_JOYDEV is not set -+CONFIG_INPUT_EVDEV=y -+# CONFIG_INPUT_MX1TS is not set -+ -+# -+# Character devices -+# -+CONFIG_VT=y -+CONFIG_VT_CONSOLE=y -+CONFIG_SERIAL=y -+CONFIG_SERIAL_CONSOLE=y -+# CONFIG_SERIAL_EXTENDED is not set -+# CONFIG_SERIAL_NONSTANDARD is not set -+ -+# -+# Serial drivers -+# -+# CONFIG_SERIAL_ANAKIN is not set -+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set -+# CONFIG_SERIAL_AMBA is not set -+# CONFIG_SERIAL_AMBA_CONSOLE is not set -+# CONFIG_SERIAL_CLPS711X is not set -+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -+# CONFIG_SERIAL_21285 is not set -+# CONFIG_SERIAL_21285_OLD is not set -+# CONFIG_SERIAL_21285_CONSOLE is not set -+# CONFIG_SERIAL_UART00 is not set -+# CONFIG_SERIAL_UART00_CONSOLE is not set -+# CONFIG_SERIAL_SA1100 is not set -+# CONFIG_SERIAL_SA1100_CONSOLE is not set -+# CONFIG_SERIAL_OMAHA is not set -+# CONFIG_SERIAL_OMAHA_CONSOLE is not set -+# CONFIG_SERIAL_AT91 is not set -+# CONFIG_SERIAL_AT91_CONSOLE is not set -+# CONFIG_SERIAL_8250 is not set -+# CONFIG_SERIAL_8250_CONSOLE is not set -+# CONFIG_SERIAL_8250_EXTENDED is not set -+# CONFIG_SERIAL_8250_MANY_PORTS is not set -+# CONFIG_SERIAL_8250_SHARE_IRQ is not set -+# CONFIG_SERIAL_8250_DETECT_IRQ is not set -+# CONFIG_SERIAL_8250_MULTIPORT is not set -+# CONFIG_SERIAL_8250_HUB6 is not set -+CONFIG_UNIX98_PTYS=y -+CONFIG_UNIX98_PTY_COUNT=32 -+ -+# -+# I2C support -+# -+CONFIG_I2C=y -+# CONFIG_I2C_ALGOBIT is not set -+# CONFIG_I2C_ALGOPCF is not set -+CONFIG_I2C_PXA_ALGO=y -+CONFIG_I2C_PXA_ADAP=y -+CONFIG_I2C_CHARDEV=m -+CONFIG_I2C_PROC=m -+# CONFIG_I2C_DS1307 is not set -+CONFIG_I2C_DS1337=y -+ -+# -+# L3 serial bus support -+# -+# CONFIG_L3 is not set -+# CONFIG_L3_ALGOBIT is not set -+# CONFIG_L3_BIT_SA1100_GPIO is not set -+# CONFIG_L3_SA1111 is not set -+# CONFIG_BIT_SA1100_GPIO is not set -+ -+# -+# Mice -+# -+# CONFIG_BUSMOUSE is not set -+# CONFIG_MOUSE is not set -+ -+# -+# Joysticks -+# -+# CONFIG_INPUT_GAMEPORT is not set -+# CONFIG_INPUT_NS558 is not set -+# CONFIG_INPUT_LIGHTNING is not set -+# CONFIG_INPUT_PCIGAME is not set -+# CONFIG_INPUT_CS461X is not set -+# CONFIG_INPUT_EMU10K1 is not set -+# CONFIG_INPUT_SERIO is not set -+# CONFIG_INPUT_SERPORT is not set -+# CONFIG_INPUT_ANALOG is not set -+# CONFIG_INPUT_A3D is not set -+# CONFIG_INPUT_ADI is not set -+# CONFIG_INPUT_COBRA is not set -+# CONFIG_INPUT_GF2K is not set -+# CONFIG_INPUT_GRIP is not set -+# CONFIG_INPUT_INTERACT is not set -+# CONFIG_INPUT_TMDC is not set -+# CONFIG_INPUT_SIDEWINDER is not set -+# CONFIG_INPUT_IFORCE_USB is not set -+# CONFIG_INPUT_IFORCE_232 is not set -+# CONFIG_INPUT_WARRIOR is not set -+# CONFIG_INPUT_MAGELLAN is not set -+# CONFIG_INPUT_SPACEORB is not set -+# CONFIG_INPUT_SPACEBALL is not set -+# CONFIG_INPUT_STINGER is not set -+# CONFIG_INPUT_DB9 is not set -+# CONFIG_INPUT_GAMECON is not set -+# CONFIG_INPUT_TURBOGRAFX is not set -+# CONFIG_QIC02_TAPE is not set -+# CONFIG_IPMI_HANDLER is not set -+# CONFIG_IPMI_PANIC_EVENT is not set -+# CONFIG_IPMI_DEVICE_INTERFACE is not set -+# CONFIG_IPMI_KCS is not set -+# CONFIG_IPMI_WATCHDOG is not set -+ -+# -+# Watchdog Cards -+# -+# CONFIG_WATCHDOG is not set -+# CONFIG_SCx200_GPIO is not set -+# CONFIG_AMD_PM768 is not set -+# CONFIG_NVRAM is not set -+CONFIG_RTC=m -+CONFIG_PXA_RTC=m -+# CONFIG_DTLK is not set -+# CONFIG_R3964 is not set -+# CONFIG_APPLICOM is not set -+ -+# -+# Ftape, the floppy tape device driver -+# -+# CONFIG_FTAPE is not set -+# CONFIG_AGP is not set -+# CONFIG_DRM is not set -+ -+# -+# PCMCIA character devices -+# -+# CONFIG_PCMCIA_SERIAL_CS is not set -+# CONFIG_SYNCLINK_CS is not set -+ -+# -+# Multimedia devices -+# -+CONFIG_VIDEO_DEV=m -+ -+# -+# Video For Linux -+# -+CONFIG_VIDEO_PROC_FS=y -+# CONFIG_I2C_PARPORT is not set -+# CONFIG_VIDEO_BT848 is not set -+# CONFIG_VIDEO_PMS is not set -+# CONFIG_VIDEO_CPIA is not set -+# CONFIG_VIDEO_SAA5249 is not set -+# CONFIG_TUNER_3036 is not set -+# CONFIG_VIDEO_STRADIS is not set -+# CONFIG_VIDEO_ZORAN is not set -+# CONFIG_VIDEO_ZORAN_BUZ is not set -+# CONFIG_VIDEO_ZORAN_DC10 is not set -+# CONFIG_VIDEO_ZORAN_LML33 is not set -+# CONFIG_VIDEO_ZR36120 is not set -+# CONFIG_VIDEO_MEYE is not set -+# CONFIG_VIDEO_CYBERPRO is not set -+ -+# -+# Radio Adapters -+# -+# CONFIG_RADIO_GEMTEK_PCI is not set -+# CONFIG_RADIO_MAXIRADIO is not set -+# CONFIG_RADIO_MAESTRO is not set -+# CONFIG_RADIO_MIROPCM20 is not set -+ -+# -+# File systems -+# -+# CONFIG_QUOTA is not set -+# CONFIG_AUTOFS_FS is not set -+# CONFIG_AUTOFS4_FS is not set -+# CONFIG_REISERFS_FS is not set -+# CONFIG_REISERFS_CHECK is not set -+# CONFIG_REISERFS_PROC_INFO is not set -+# CONFIG_ADFS_FS is not set -+# CONFIG_ADFS_FS_RW is not set -+# CONFIG_AFFS_FS is not set -+# CONFIG_HFS_FS is not set -+# CONFIG_BEFS_FS is not set -+# CONFIG_BEFS_DEBUG is not set -+# CONFIG_BFS_FS is not set -+# CONFIG_EXT3_FS is not set -+# CONFIG_JBD is not set -+# CONFIG_JBD_DEBUG is not set -+CONFIG_FAT_FS=m -+CONFIG_MSDOS_FS=m -+# CONFIG_UMSDOS_FS is not set -+CONFIG_VFAT_FS=m -+# CONFIG_EFS_FS is not set -+# CONFIG_JFFS_FS is not set -+CONFIG_JFFS2_FS=y -+CONFIG_JFFS2_FS_DEBUG=0 -+CONFIG_CRAMFS=m -+# CONFIG_CRAMFS_LINEAR is not set -+# CONFIG_CRAMFS_LINEAR_XIP is not set -+# CONFIG_ROOT_CRAMFS_LINEAR is not set -+CONFIG_TMPFS=y -+CONFIG_RAMFS=y -+# CONFIG_ISO9660_FS is not set -+# CONFIG_JOLIET is not set -+# CONFIG_ZISOFS is not set -+# CONFIG_JFS_FS is not set -+# CONFIG_JFS_DEBUG is not set -+# CONFIG_JFS_STATISTICS is not set -+# CONFIG_MINIX_FS is not set -+# CONFIG_VXFS_FS is not set -+# CONFIG_NTFS_FS is not set -+# CONFIG_NTFS_RW is not set -+# CONFIG_HPFS_FS is not set -+CONFIG_PROC_FS=y -+CONFIG_DEVFS_FS=y -+CONFIG_DEVFS_MOUNT=y -+# CONFIG_DEVFS_DEBUG is not set -+# CONFIG_DEVPTS_FS is not set -+# CONFIG_QNX4FS_FS is not set -+# CONFIG_QNX4FS_RW is not set -+# CONFIG_ROMFS_FS is not set -+CONFIG_EXT2_FS=m -+# CONFIG_SYSV_FS is not set -+# CONFIG_UDF_FS is not set -+# CONFIG_UDF_RW is not set -+# CONFIG_UFS_FS is not set -+# CONFIG_UFS_FS_WRITE is not set -+ -+# -+# Network File Systems -+# -+# CONFIG_CODA_FS is not set -+# CONFIG_INTERMEZZO_FS is not set -+CONFIG_NFS_FS=y -+# CONFIG_NFS_V3 is not set -+CONFIG_ROOT_NFS=y -+# CONFIG_NFSD is not set -+# CONFIG_NFSD_V3 is not set -+# CONFIG_NFSD_TCP is not set -+CONFIG_SUNRPC=y -+CONFIG_LOCKD=y -+# CONFIG_SMB_FS is not set -+# CONFIG_NCP_FS is not set -+# CONFIG_NCPFS_PACKET_SIGNING is not set -+# CONFIG_NCPFS_IOCTL_LOCKING is not set -+# CONFIG_NCPFS_STRONG is not set -+# CONFIG_NCPFS_NFS_NS is not set -+# CONFIG_NCPFS_OS2_NS is not set -+# CONFIG_NCPFS_SMALLDOS is not set -+# CONFIG_NCPFS_NLS is not set -+# CONFIG_NCPFS_EXTRAS is not set -+# CONFIG_ZISOFS_FS is not set -+ -+# -+# Partition Types -+# -+# CONFIG_PARTITION_ADVANCED is not set -+CONFIG_MSDOS_PARTITION=y -+# CONFIG_SMB_NLS is not set -+CONFIG_NLS=y -+ -+# -+# Native Language Support -+# -+CONFIG_NLS_DEFAULT="iso8859-1" -+CONFIG_NLS_CODEPAGE_437=m -+CONFIG_NLS_CODEPAGE_737=m -+CONFIG_NLS_CODEPAGE_775=m -+CONFIG_NLS_CODEPAGE_850=m -+CONFIG_NLS_CODEPAGE_852=m -+CONFIG_NLS_CODEPAGE_855=m -+CONFIG_NLS_CODEPAGE_857=m -+CONFIG_NLS_CODEPAGE_860=m -+CONFIG_NLS_CODEPAGE_861=m -+CONFIG_NLS_CODEPAGE_862=m -+CONFIG_NLS_CODEPAGE_863=m -+CONFIG_NLS_CODEPAGE_864=m -+CONFIG_NLS_CODEPAGE_865=m -+CONFIG_NLS_CODEPAGE_866=m -+CONFIG_NLS_CODEPAGE_869=m -+CONFIG_NLS_CODEPAGE_936=m -+CONFIG_NLS_CODEPAGE_950=m -+CONFIG_NLS_CODEPAGE_932=m -+CONFIG_NLS_CODEPAGE_949=m -+CONFIG_NLS_CODEPAGE_874=m -+CONFIG_NLS_ISO8859_8=m -+CONFIG_NLS_CODEPAGE_1250=m -+CONFIG_NLS_CODEPAGE_1251=m -+CONFIG_NLS_ISO8859_1=m -+CONFIG_NLS_ISO8859_2=m -+CONFIG_NLS_ISO8859_3=m -+CONFIG_NLS_ISO8859_4=m -+CONFIG_NLS_ISO8859_5=m -+CONFIG_NLS_ISO8859_6=m -+CONFIG_NLS_ISO8859_7=m -+CONFIG_NLS_ISO8859_9=m -+CONFIG_NLS_ISO8859_13=m -+CONFIG_NLS_ISO8859_14=m -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_KOI8_R=m -+CONFIG_NLS_KOI8_U=m -+CONFIG_NLS_UTF8=m -+ -+# -+# Console drivers -+# -+CONFIG_PC_KEYMAP=y -+# CONFIG_VGA_CONSOLE is not set -+ -+# -+# Frame-buffer support -+# -+CONFIG_FB=y -+CONFIG_DUMMY_CONSOLE=y -+# CONFIG_FB_ACORN is not set -+# CONFIG_FB_ANAKIN is not set -+# CONFIG_FB_CLPS711X is not set -+# CONFIG_FB_SA1100 is not set -+# CONFIG_FB_DBMX1 is not set -+CONFIG_FB_PXA=y -+# CONFIG_FB_PXA_8BPP is not set -+CONFIG_FB_PXA_16BPP=y -+# CONFIG_FB_CYBER2000 is not set -+# CONFIG_FB_VIRTUAL is not set -+CONFIG_FBCON_ADVANCED=y -+# CONFIG_FBCON_MFB is not set -+# CONFIG_FBCON_CFB2 is not set -+# CONFIG_FBCON_CFB4 is not set -+# CONFIG_FBCON_CFB8 is not set -+CONFIG_FBCON_CFB16=y -+# CONFIG_FBCON_CFB24 is not set -+# CONFIG_FBCON_CFB32 is not set -+# CONFIG_FBCON_AFB is not set -+# CONFIG_FBCON_ILBM is not set -+# CONFIG_FBCON_IPLAN2P2 is not set -+# CONFIG_FBCON_IPLAN2P4 is not set -+# CONFIG_FBCON_IPLAN2P8 is not set -+# CONFIG_FBCON_MAC is not set -+# CONFIG_FBCON_VGA_PLANES is not set -+# CONFIG_FBCON_VGA is not set -+# CONFIG_FBCON_HGA is not set -+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -+# CONFIG_FBCON_FONTS is not set -+CONFIG_FONT_8x8=y -+CONFIG_FONT_8x16=y -+ -+# -+# Sound -+# -+CONFIG_SOUND=y -+# CONFIG_SOUND_ALI5455 is not set -+# CONFIG_SOUND_BT878 is not set -+# CONFIG_SOUND_CMPCI is not set -+# CONFIG_SOUND_EMU10K1 is not set -+# CONFIG_MIDI_EMU10K1 is not set -+# CONFIG_SOUND_FUSION is not set -+# CONFIG_SOUND_CS4281 is not set -+# CONFIG_SOUND_ES1370 is not set -+# CONFIG_SOUND_ES1371 is not set -+# CONFIG_SOUND_ESSSOLO1 is not set -+# CONFIG_SOUND_MAESTRO is not set -+# CONFIG_SOUND_MAESTRO3 is not set -+# CONFIG_SOUND_FORTE is not set -+# CONFIG_SOUND_ICH is not set -+# CONFIG_SOUND_RME96XX is not set -+# CONFIG_SOUND_SONICVIBES is not set -+# CONFIG_SOUND_TRIDENT is not set -+# CONFIG_SOUND_MSNDCLAS is not set -+# CONFIG_SOUND_MSNDPIN is not set -+# CONFIG_SOUND_VIA82CXXX is not set -+# CONFIG_MIDI_VIA82CXXX is not set -+# CONFIG_SOUND_OSS is not set -+# CONFIG_SOUND_VIDC is not set -+# CONFIG_SOUND_WAVEARTIST is not set -+CONFIG_SOUND_PXA_AC97=y -+# CONFIG_SOUND_TVMIXER is not set -+ -+# -+# Multimedia Capabilities Port drivers -+# -+CONFIG_MCP=y -+# CONFIG_MCP_SA1100 is not set -+# CONFIG_MCP_UCB1200 is not set -+# CONFIG_MCP_UCB1200_AUDIO is not set -+# CONFIG_MCP_UCB1200_TS is not set -+CONFIG_MCP_UCB1400_TS=y -+ -+# -+# USB support -+# -+CONFIG_USB=m -+# CONFIG_USB_DEBUG is not set -+CONFIG_USB_DEVICEFS=y -+# CONFIG_USB_BANDWIDTH is not set -+# CONFIG_USB_EHCI_HCD is not set -+# CONFIG_USB_UHCI is not set -+# CONFIG_USB_UHCI_ALT is not set -+# CONFIG_USB_OHCI is not set -+# CONFIG_USB_OHCI_SA1111 is not set -+CONFIG_USB_SL811HS_ALT=m -+CONFIG_USB_AUDIO=m -+CONFIG_USB_EMI26=m -+# CONFIG_USB_BLUETOOTH is not set -+CONFIG_USB_MIDI=m -+CONFIG_USB_STORAGE=m -+CONFIG_USB_STORAGE_DEBUG=y -+CONFIG_USB_STORAGE_DATAFAB=y -+CONFIG_USB_STORAGE_FREECOM=y -+# CONFIG_USB_STORAGE_ISD200 is not set -+CONFIG_USB_STORAGE_DPCM=y -+CONFIG_USB_STORAGE_HP8200e=y -+CONFIG_USB_STORAGE_SDDR09=y -+CONFIG_USB_STORAGE_SDDR55=y -+CONFIG_USB_STORAGE_JUMPSHOT=y -+# CONFIG_USB_ACM is not set -+CONFIG_USB_PRINTER=m -+CONFIG_USB_HID=m -+CONFIG_USB_HIDINPUT=y -+CONFIG_USB_HIDDEV=y -+CONFIG_USB_KBD=m -+# CONFIG_USB_MOUSE is not set -+# CONFIG_USB_AIPTEK is not set -+# CONFIG_USB_WACOM is not set -+# CONFIG_USB_KBTAB is not set -+# CONFIG_USB_POWERMATE is not set -+CONFIG_USB_DC2XX=m -+CONFIG_USB_MDC800=m -+CONFIG_USB_SCANNER=m -+CONFIG_USB_MICROTEK=m -+CONFIG_USB_HPUSBSCSI=m -+CONFIG_USB_IBMCAM=m -+CONFIG_USB_KONICAWC=m -+CONFIG_USB_OV511=m -+CONFIG_USB_PWC=m -+CONFIG_USB_SE401=m -+CONFIG_USB_STV680=m -+CONFIG_USB_VICAM=m -+# CONFIG_USB_DSBR is not set -+# CONFIG_USB_DABUSB is not set -+# CONFIG_USB_PEGASUS is not set -+# CONFIG_USB_RTL8150 is not set -+# CONFIG_USB_KAWETH is not set -+# CONFIG_USB_CATC is not set -+# CONFIG_USB_CDCETHER is not set -+# CONFIG_USB_USBNET is not set -+# CONFIG_USB_USS720 is not set -+ -+# -+# USB Serial Converter support -+# -+CONFIG_USB_SERIAL=m -+# CONFIG_USB_SERIAL_DEBUG is not set -+CONFIG_USB_SERIAL_GENERIC=y -+CONFIG_USB_SERIAL_BELKIN=m -+CONFIG_USB_SERIAL_WHITEHEAT=m -+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -+CONFIG_USB_SERIAL_EMPEG=m -+# CONFIG_USB_SERIAL_FTDI_SIO is not set -+# CONFIG_USB_SERIAL_VISOR is not set -+# CONFIG_USB_SERIAL_IPAQ is not set -+# CONFIG_USB_SERIAL_IR is not set -+# CONFIG_USB_SERIAL_EDGEPORT is not set -+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set -+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -+# CONFIG_USB_SERIAL_KEYSPAN is not set -+# CONFIG_USB_SERIAL_MCT_U232 is not set -+# CONFIG_USB_SERIAL_KLSI is not set -+# CONFIG_USB_SERIAL_KOBIL_SCT is not set -+# CONFIG_USB_SERIAL_PL2303 is not set -+# CONFIG_USB_SERIAL_CYBERJACK is not set -+# CONFIG_USB_SERIAL_XIRCOM is not set -+# CONFIG_USB_SERIAL_OMNINET is not set -+# CONFIG_USB_RIO500 is not set -+# CONFIG_USB_AUERSWALD is not set -+# CONFIG_USB_TIGL is not set -+# CONFIG_USB_BRLVGER is not set -+# CONFIG_USB_LCD is not set -+ -+# -+# Bluetooth support -+# -+# CONFIG_BLUEZ is not set -+ -+# -+# Kernel hacking -+# -+CONFIG_FRAME_POINTER=y -+# CONFIG_DEBUG_USER is not set -+# CONFIG_DEBUG_INFO is not set -+# CONFIG_NO_PGT_CACHE is not set -+# CONFIG_DEBUG_KERNEL is not set -+# CONFIG_DEBUG_SLAB is not set -+# CONFIG_MAGIC_SYSRQ is not set -+# CONFIG_DEBUG_SPINLOCK is not set -+# CONFIG_DEBUG_WAITQ is not set -+# CONFIG_DEBUG_BUGVERBOSE is not set -+# CONFIG_DEBUG_ERRORS is not set -+# CONFIG_DEBUG_LL is not set -+# CONFIG_DEBUG_DC21285_PORT is not set -+# CONFIG_DEBUG_CLPS711X_UART2 is not set -+ -+# -+# Library routines -+# -+CONFIG_ZLIB_INFLATE=y -+CONFIG_ZLIB_DEFLATE=y ---- linux-2.4.21/arch/arm/mach-pxa/Makefile~pm -+++ linux-2.4.21/arch/arm/mach-pxa/Makefile -@@ -14,8 +14,11 @@ - obj-n := - obj- := - --export-objs := generic.o irq.o dma.o sa1111.o \ -- usb_ctl.o usb_recv.o usb_send.o -+export-objs := apm.o generic.o irq.o dma.o sa1111.o \ -+ usb_ctl.o usb_recv.o usb_send.o pm.o -+ -+ -+export-objs += ramses.o - - # Common support (must be linked before board specific support) - obj-y += generic.o irq.o dma.o -@@ -27,6 +30,7 @@ - obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o - obj-$(CONFIG_ARCH_PXA_CERF) += cerf.o - obj-$(CONFIG_ARCH_PXA_IDP) += idp.o -+obj-$(CONFIG_ARCH_RAMSES) += ramses.o - obj-$(CONFIG_ARCH_TRIZEPS2) += trizeps2.o - - # Support for blinky lights -@@ -48,6 +52,7 @@ - - # Misc features - obj-$(CONFIG_PM) += pm.o sleep.o -+obj-$(CONFIG_APM) += apm.o - obj-$(CONFIG_CPU_FREQ) += cpu-pxa.o - - include $(TOPDIR)/Rules.make ---- /dev/null -+++ linux-2.4.21/arch/arm/mach-pxa/apm.c -@@ -0,0 +1,491 @@ -+/* -+ * bios-less APM driver for ARM Linux -+ * Jamey Hicks -+ * adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com) -+ * -+ * APM 1.2 Reference: -+ * Intel Corporation, Microsoft Corporation. Advanced Power Management -+ * (APM) BIOS Interface Specification, Revision 1.2, February 1996. -+ * -+ * [This document is available from Microsoft at: -+ * http://www.microsoft.com/hwdev/busbios/amp_12.htm] -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#ifdef CONFIG_SA1100_H3XXX -+#include -+#endif -+ -+#include "pm-common.c" -+ -+struct apm_bios_info apm_bios_info = { -+ /* this driver simulates APM version 1.2 */ -+ version: 0x102, -+ flags: APM_32_BIT_SUPPORT -+}; -+ -+/* -+ * The apm_bios device is one of the misc char devices. -+ * This is its minor number. -+ */ -+#define APM_MINOR_DEV 134 -+ -+/* -+ * See Documentation/Config.help for the configuration options. -+ * -+ * Various options can be changed at boot time as follows: -+ * (We allow underscores for compatibility with the modules code) -+ * apm=on/off enable/disable APM -+ * [no-]power[-_]off power off on shutdown -+ */ -+ -+/* -+ * Maximum number of events stored -+ */ -+#define APM_MAX_EVENTS 10 -+ -+/* -+ * The per-file APM data -+ */ -+struct apm_user { -+ int magic; -+ struct apm_user * next; -+ int suser: 1; -+ int suspend_wait: 1; -+ int suspend_result; -+ int suspends_pending; -+ int standbys_pending; -+ int suspends_read; -+ int standbys_read; -+ int event_head; -+ int event_tail; -+ apm_event_t events[APM_MAX_EVENTS]; -+}; -+ -+/* -+ * The magic number in apm_user -+ */ -+#define APM_BIOS_MAGIC 0x4101 -+ -+/* -+ * Local variables -+ */ -+ -+#ifdef CONFIG_APM_RTC_IS_GMT -+#define clock_cmos_diff 0 -+#define got_clock_diff 1 -+#endif -+static int apm_disabled; -+#ifdef CONFIG_SMP -+static int power_off; -+#else -+static int power_off = 1; -+#endif -+static int exit_kapmd; -+static int kapmd_running; -+ -+static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); -+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); -+static struct apm_user * user_list = NULL; -+ -+static char driver_version[] = "1.13"; /* no spaces */ -+ -+typedef struct lookup_t { -+ int key; -+ char * msg; -+} lookup_t; -+ -+static const lookup_t error_table[] = { -+/* N/A { APM_SUCCESS, "Operation succeeded" }, */ -+ { APM_DISABLED, "Power management disabled" }, -+ { APM_CONNECTED, "Real mode interface already connected" }, -+ { APM_NOT_CONNECTED, "Interface not connected" }, -+ { APM_16_CONNECTED, "16 bit interface already connected" }, -+/* N/A { APM_16_UNSUPPORTED, "16 bit interface not supported" }, */ -+ { APM_32_CONNECTED, "32 bit interface already connected" }, -+ { APM_32_UNSUPPORTED, "32 bit interface not supported" }, -+ { APM_BAD_DEVICE, "Unrecognized device ID" }, -+ { APM_BAD_PARAM, "Parameter out of range" }, -+ { APM_NOT_ENGAGED, "Interface not engaged" }, -+ { APM_BAD_FUNCTION, "Function not supported" }, -+ { APM_RESUME_DISABLED, "Resume timer disabled" }, -+ { APM_BAD_STATE, "Unable to enter requested state" }, -+/* N/A { APM_NO_EVENTS, "No events pending" }, */ -+ { APM_NO_ERROR, "BIOS did not set a return code" }, -+ { APM_NOT_PRESENT, "No APM present" } -+}; -+#define ERROR_COUNT (sizeof(error_table)/sizeof(lookup_t)) -+ -+static int (*apm_get_power_status)(u_char *ac_line_status, -+ u_char *battery_status, -+ u_char *battery_flag, -+ u_char *battery_percentage, -+ u_short *battery_life) = 0; -+ -+void apm_register_get_power_status( int (*fn)(u_char *ac_line_status, -+ u_char *battery_status, -+ u_char *battery_flag, -+ u_char *battery_percentage, -+ u_short *battery_life)) -+{ -+ apm_get_power_status = fn; -+} -+ -+static int queue_empty(struct apm_user *as) -+{ -+ return as->event_head == as->event_tail; -+} -+ -+static apm_event_t get_queued_event(struct apm_user *as) -+{ -+ as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; -+ return as->events[as->event_tail]; -+} -+ -+static int check_apm_user(struct apm_user *as, const char *func) -+{ -+ if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) { -+ printk(KERN_ERR "apm: %s passed bad filp\n", func); -+ return 1; -+ } -+ return 0; -+} -+ -+static ssize_t do_read(struct file *fp, char *buf, size_t count, loff_t *ppos) -+{ -+ struct apm_user * as; -+ int i; -+ apm_event_t event; -+ DECLARE_WAITQUEUE(wait, current); -+ -+ as = fp->private_data; -+ if (check_apm_user(as, "read")) -+ return -EIO; -+ if (count < sizeof(apm_event_t)) -+ return -EINVAL; -+ if (queue_empty(as)) { -+ if (fp->f_flags & O_NONBLOCK) -+ return -EAGAIN; -+ add_wait_queue(&apm_waitqueue, &wait); -+ printk("do_read: waiting\n"); -+repeat: -+ set_current_state(TASK_INTERRUPTIBLE); -+ if (queue_empty(as) && !signal_pending(current)) { -+ schedule(); -+ goto repeat; -+ } -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&apm_waitqueue, &wait); -+ } -+ i = count; -+ while ((i >= sizeof(event)) && !queue_empty(as)) { -+ event = get_queued_event(as); -+ printk(" do_read: event=%d\n", event); -+ if (copy_to_user(buf, &event, sizeof(event))) { -+ if (i < count) -+ break; -+ return -EFAULT; -+ } -+ switch (event) { -+ case APM_SYS_SUSPEND: -+ case APM_USER_SUSPEND: -+ as->suspends_read++; -+ break; -+ -+ case APM_SYS_STANDBY: -+ case APM_USER_STANDBY: -+ as->standbys_read++; -+ break; -+ } -+ buf += sizeof(event); -+ i -= sizeof(event); -+ } -+ if (i < count) -+ return count - i; -+ if (signal_pending(current)) -+ return -ERESTARTSYS; -+ return 0; -+} -+ -+static unsigned int do_poll(struct file *fp, poll_table * wait) -+{ -+ struct apm_user * as; -+ -+ as = fp->private_data; -+ if (check_apm_user(as, "poll")) -+ return 0; -+ poll_wait(fp, &apm_waitqueue, wait); -+ if (!queue_empty(as)) -+ return POLLIN | POLLRDNORM; -+ return 0; -+} -+ -+static int do_ioctl(struct inode * inode, struct file *filp, -+ u_int cmd, u_long arg) -+{ -+ struct apm_user * as; -+ -+ as = filp->private_data; -+ if (check_apm_user(as, "ioctl")) -+ return -EIO; -+ if (!as->suser) -+ return -EPERM; -+ switch (cmd) { -+ case APM_IOC_SUSPEND: -+ pm_suggest_suspend(); -+ break; -+ default: -+ printk("//hs %x\n", cmd); -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+static int do_release(struct inode * inode, struct file * filp) -+{ -+ struct apm_user * as; -+ -+ as = filp->private_data; -+ if (check_apm_user(as, "release")) -+ return 0; -+ filp->private_data = NULL; -+ lock_kernel(); -+ unlock_kernel(); -+ kfree(as); -+ return 0; -+} -+ -+static int do_open(struct inode * inode, struct file * filp) -+{ -+ struct apm_user * as; -+ -+ as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL); -+ if (as == NULL) { -+ printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n", -+ sizeof(*as)); -+ return -ENOMEM; -+ } -+ as->magic = APM_BIOS_MAGIC; -+ as->event_tail = as->event_head = 0; -+ as->suspends_pending = as->standbys_pending = 0; -+ as->suspends_read = as->standbys_read = 0; -+ /* -+ * XXX - this is a tiny bit broken, when we consider BSD -+ * process accounting. If the device is opened by root, we -+ * instantly flag that we used superuser privs. Who knows, -+ * we might close the device immediately without doing a -+ * privileged operation -- cevans -+ */ -+ as->suser = capable(CAP_SYS_ADMIN); -+ as->next = user_list; -+ user_list = as; -+ filp->private_data = as; -+ return 0; -+} -+ -+static int apm_get_info(char *buf, char **start, off_t fpos, int length) -+{ -+ char * p; -+ unsigned short dx; -+ unsigned short error; -+ unsigned char ac_line_status = 0xff; -+ unsigned char battery_status = 0xff; -+ unsigned char battery_flag = 0xff; -+ unsigned char percentage = 0xff; -+ int time_units = -1; -+ char *units = "?"; -+ -+ p = buf; -+ -+ if ( (smp_num_cpus == 1) && -+ apm_get_power_status && -+ !(error = apm_get_power_status(&ac_line_status, -+ &battery_status, &battery_flag, &percentage, &dx))) { -+ if (apm_bios_info.version > 0x100) { -+ if (dx != 0xffff) { -+ units = (dx & 0x8000) ? "min" : "sec"; -+ time_units = dx & 0x7fff; -+ } -+ } -+ } -+ /* Arguments, with symbols from linux/apm_bios.h. Information is -+ from the Get Power Status (0x0a) call unless otherwise noted. -+ -+ 0) Linux driver version (this will change if format changes) -+ 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2. -+ 2) APM flags from APM Installation Check (0x00): -+ bit 0: APM_16_BIT_SUPPORT -+ bit 1: APM_32_BIT_SUPPORT -+ bit 2: APM_IDLE_SLOWS_CLOCK -+ bit 3: APM_BIOS_DISABLED -+ bit 4: APM_BIOS_DISENGAGED -+ 3) AC line status -+ 0x00: Off-line -+ 0x01: On-line -+ 0x02: On backup power (BIOS >= 1.1 only) -+ 0xff: Unknown -+ 4) Battery status -+ 0x00: High -+ 0x01: Low -+ 0x02: Critical -+ 0x03: Charging -+ 0x04: Selected battery not present (BIOS >= 1.2 only) -+ 0xff: Unknown -+ 5) Battery flag -+ bit 0: High -+ bit 1: Low -+ bit 2: Critical -+ bit 3: Charging -+ bit 7: No system battery -+ 0xff: Unknown -+ 6) Remaining battery life (percentage of charge): -+ 0-100: valid -+ -1: Unknown -+ 7) Remaining battery life (time units): -+ Number of remaining minutes or seconds -+ -1: Unknown -+ 8) min = minutes; sec = seconds */ -+ -+ p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", -+ driver_version, -+ (apm_bios_info.version >> 8) & 0xff, -+ apm_bios_info.version & 0xff, -+ apm_bios_info.flags, -+ ac_line_status, -+ battery_status, -+ battery_flag, -+ percentage, -+ time_units, -+ units); -+ -+ return p - buf; -+} -+ -+#ifndef MODULE -+static int __init apm_setup(char *str) -+{ -+ int invert; -+ -+printk("//hs apm_setup\n"); -+ while ((str != NULL) && (*str != '\0')) { -+ if (strncmp(str, "off", 3) == 0) -+ apm_disabled = 1; -+ if (strncmp(str, "on", 2) == 0) -+ apm_disabled = 0; -+ invert = (strncmp(str, "no-", 3) == 0); -+ if (invert) -+ str += 3; -+ if ((strncmp(str, "power-off", 9) == 0) || -+ (strncmp(str, "power_off", 9) == 0)) -+ power_off = !invert; -+ str = strchr(str, ','); -+ if (str != NULL) -+ str += strspn(str, ", \t"); -+ } -+ return 1; -+} -+ -+__setup("apm=", apm_setup); -+#endif -+ -+static struct file_operations apm_bios_fops = { -+ owner: THIS_MODULE, -+ read: do_read, -+ poll: do_poll, -+ ioctl: do_ioctl, -+ open: do_open, -+ release: do_release, -+}; -+ -+static struct miscdevice apm_device = { -+ APM_MINOR_DEV, -+ "apm_bios", -+ &apm_bios_fops -+}; -+ -+#define APM_INIT_ERROR_RETURN return -1 -+ -+/* -+ * Just start the APM thread. We do NOT want to do APM BIOS -+ * calls from anything but the APM thread, if for no other reason -+ * than the fact that we don't trust the APM BIOS. This way, -+ * most common APM BIOS problems that lead to protection errors -+ * etc will have at least some level of being contained... -+ * -+ * In short, if something bad happens, at least we have a choice -+ * of just killing the apm thread.. -+ */ -+static int __init apm_init(void) -+{ -+ if (apm_bios_info.version == 0) { -+ printk(KERN_INFO "apm: BIOS not found.\n"); -+ APM_INIT_ERROR_RETURN; -+ } -+ printk(KERN_INFO -+ "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n", -+ ((apm_bios_info.version >> 8) & 0xff), -+ (apm_bios_info.version & 0xff), -+ apm_bios_info.flags, -+ driver_version); -+ -+ if (apm_disabled) { -+ printk(KERN_NOTICE "apm: disabled on user request.\n"); -+ APM_INIT_ERROR_RETURN; -+ } -+ -+ if (PM_IS_ACTIVE()) { -+ printk(KERN_NOTICE "apm: overridden by ACPI.\n"); -+ APM_INIT_ERROR_RETURN; -+ } -+ pm_active = 1; -+ -+ create_proc_info_entry("apm", 0, NULL, apm_get_info); -+ -+ misc_register(&apm_device); -+ -+ return 0; -+} -+ -+module_init(apm_init); -+ -+#ifdef MODULE -+static void __exit apm_exit(void) -+{ -+ misc_deregister(&apm_device); -+ remove_proc_entry("apm", NULL); -+ if (power_off) -+ pm_power_off = NULL; -+ exit_kapmd = 1; -+ while (kapmd_running) -+ schedule(); -+ pm_active = 0; -+} -+ -+module_exit(apm_exit); -+ -+MODULE_AUTHOR("Jamey Hicks, pulling bits from original by Stephen Rothwell"); -+MODULE_DESCRIPTION("A minimal emulation of APM"); -+MODULE_PARM(power_off, "i"); -+MODULE_PARM_DESC(power_off, "Enable power off"); -+#endif ---- linux-2.4.21/arch/arm/mach-pxa/cpu-pxa.c~ramses-corevolt -+++ linux-2.4.21/arch/arm/mach-pxa/cpu-pxa.c -@@ -39,7 +39,7 @@ - - #include - --#define DEBUGGING 1 -+#define DEBUGGING 0 - - #if DEBUGGING - static unsigned int freq_debug = DEBUGGING; -@@ -52,6 +52,7 @@ - unsigned int khz; - unsigned int cccr; - unsigned int pxbus; -+ unsigned int corevolt; - } pxa_freqs_t; - - #define CCLKCFG_TURBO 0x1 -@@ -79,23 +80,23 @@ - - static pxa_freqs_t pxa250_valid_freqs[] = - { -- {199100, 0x141, 99}, /* mem= 99, run=199, turbo=199, PXbus= 99 */ -- {298600, 0x1c1, 99}, /* mem= 99, run=199, turbo=298, PXbus= 99 */ -- {398100, 0x241, 99}, /* mem= 99, run=199, turbo=398, PXbus= 99 */ -+ {199100, 0x141, 99, 115}, /* mem= 99, run=199, turbo=199, PXbus= 99 */ -+ {298600, 0x1c1, 99, 125}, /* mem= 99, run=199, turbo=298, PXbus= 99 */ -+ {398100, 0x241, 99, 135}, /* mem= 99, run=199, turbo=398, PXbus= 99 */ - {0,0} - }; - - static pxa_freqs_t pxa255_valid_freqs[] = - { -- { 99000, 0x121, 50}, /* mem= 99, run= 99, turbo= 99, PXbus= 50 */ --OC( {118000, 0x122, 59},)/* mem=118, run=118, turbo=118, PXbus= 59 OC'd mem */ -- {199100, 0x141, 99}, /* mem= 99, run=199, turbo=199, PXbus= 99 */ --OC( {236000, 0x142,118},)/* mem=118, run=236, turbo=236, PXbus=118 OC'd mem */ -- {298600, 0x1c1, 99}, /* mem= 99, run=199, turbo=298, PXbus= 99 */ --OC( {354000, 0x1c2,118},)/* mem=118, run=236, turbo=354, PXbus=118 OC'd mem */ -- {398099, 0x241, 99}, /* mem= 99, run=199, turbo=398, PXbus= 99 */ -- {398100, 0x161,196}, /* mem= 99, run=398, turbo=398, PXbus=196 */ --OC( {471000, 0x162,236},)/* mem=118, run=471, turbo=471, PXbus=236 OC'd mem/core/bus */ -+ { 99000, 0x121, 50, 105}, /* mem= 99, run= 99, turbo= 99, PXbus= 50 */ -+OC( {118000, 0x122, 59, 115},)/* mem=118, run=118, turbo=118, PXbus= 59 OC'd mem */ -+ {199100, 0x141, 99, 115}, /* mem= 99, run=199, turbo=199, PXbus= 99 */ -+OC( {236000, 0x142,118, 125},)/* mem=118, run=236, turbo=236, PXbus=118 OC'd mem */ -+ {298600, 0x1c1, 99, 125}, /* mem= 99, run=199, turbo=298, PXbus= 99 */ -+OC( {354000, 0x1c2,118, 135},)/* mem=118, run=236, turbo=354, PXbus=118 OC'd mem */ -+ {398099, 0x241, 99, 135}, /* mem= 99, run=199, turbo=398, PXbus= 99 */ -+ {398100, 0x161,196, 135}, /* mem= 99, run=398, turbo=398, PXbus=196 */ -+OC( {471000, 0x162,236, 150},)/* mem=118, run=471, turbo=471, PXbus=236 OC'd mem/core/bus */ - {0,0} - }; - -@@ -109,7 +110,7 @@ - int i=0; - while( pxa_valid_freqs[i].khz) - { -- if( pxa_valid_freqs[i].khz == khz) -+ if (pxa_valid_freqs[i].khz == khz) - return &pxa_valid_freqs[i]; - i++; - } -@@ -141,14 +142,17 @@ - void *ramstart = phys_to_virt(0xa0000000); - pxa_freqs_t *freq_info; - -- if( ! supported) return; -+ if (! supported) return; - - freq_info = pxa_get_freq_info( khz); - -- if( ! freq_info) return; -+ if (! freq_info) return; -+ -+ if (freq_info->corevolt > ramses_corevolt_shadow) -+ ramses_set_corevolt(freq_info->corevolt); - - CCCR = freq_info->cccr; -- if( freq_debug) -+ if (freq_debug) - printk(KERN_INFO "Changing CPU frequency to %d Mhz (PXbus=%dMhz).\n", - khz/1000, freq_info->pxbus); - -@@ -184,6 +188,9 @@ - : "r" (&MDREFR), "r" (CCLKCFG_TURBO|CCLKCFG_FCS), "r" (ramstart) - : "r4", "r5"); - local_irq_restore(flags); -+ -+ if (freq_info->corevolt < ramses_corevolt_shadow) -+ ramses_set_corevolt(freq_info->corevolt); - } - - static int pxa_init_freqs( void) -@@ -191,19 +198,19 @@ - int cpu_ver; - asm("mrc%? p15, 0, %0, c0, c0" : "=r" (cpu_ver)); - -- if( (cpu_ver & 0xf) <= PXA250_REV_A1) -+ if ((cpu_ver & 0xf) <= PXA250_REV_A1) - { - return 0; - } - -- if( (cpu_ver & 0xf) <= PXA250_REV_B2) -+ if ((cpu_ver & 0xf) <= PXA250_REV_B2) - { -- if( freq_debug) printk(KERN_INFO "Using PXA250 frequency points.\n"); -+ if (freq_debug) printk(KERN_INFO "Using PXA250 frequency points.\n"); - pxa_valid_freqs = pxa250_valid_freqs; - } - else /* C0 and above */ - { -- if( freq_debug) printk(KERN_INFO "Using PXA255 frequency points.\n"); -+ if (freq_debug) printk(KERN_INFO "Using PXA255 frequency points.\n"); - pxa_valid_freqs = pxa255_valid_freqs; - } - -@@ -212,24 +219,23 @@ - - static int __init pxa_clk_init(void) - { -- if( pxa_init_freqs()) -+ if (pxa_init_freqs()) - { -- if( freq_debug) printk(KERN_INFO "Registering CPU frequency change support.\n"); -+ if (freq_debug) printk(KERN_INFO "Registering CPU frequency change support.\n"); - supported = 1; - - cpufreq_init( get_clk_frequency_khz(0), PXA25x_MIN_FREQ, PXA25x_MAX_FREQ); -- cpufreq_setfunctions(pxa_validate_speed, pxa_setspeed); - } - else - { -- if( freq_debug) printk(KERN_INFO "Disabling CPU frequency change support.\n"); -+ if (freq_debug) printk(KERN_INFO "Disabling CPU frequency change support.\n"); - /* Note that we have to initialize the generic code in order to - * release a lock (cpufreq_sem). Any registration for freq changes - * (e.g. lcd driver) will get blocked otherwise. - */ - cpufreq_init( 0, 0, 0); -- cpufreq_setfunctions(pxa_validate_speed, pxa_setspeed); - } -+ cpufreq_setfunctions(pxa_validate_speed, pxa_setspeed); - - return 0; - } ---- linux-2.4.21/arch/arm/mach-pxa/generic.c~pm -+++ linux-2.4.21/arch/arm/mach-pxa/generic.c -@@ -28,6 +28,11 @@ - #include - #include - -+#ifdef CONFIG_PXA_RTC_HACK -+#include -+#include -+#endif -+ - #include "generic.h" - - /* -@@ -139,4 +144,41 @@ - { - iotable_init(standard_io_desc); - get_clk_frequency_khz( 1); -+#ifdef CONFIG_PXA_RTC_HACK -+ pxa_rtc_hack_init(); -+#endif -+} -+ -+ -+ -+#ifdef CONFIG_PXA_RTC_HACK -+unsigned long *save_RCNR = 0; -+ -+void pxa_rtc_hack_init(void) -+{ -+ /* -+ This has to be here since I guess the bootmem API is the -+ right choice to allocate the memory during boot -+ place. And we are sure that timer iqr is not already -+ running. -+ - Christian Pellegin -+ */ -+ unsigned long pxa_rtc_hack = 0; -+ -+ pxa_rtc_hack = meminfo.bank[meminfo.nr_banks-1].start + -+ meminfo.bank[meminfo.nr_banks-1].size - -+ PAGE_SIZE; -+ reserve_bootmem(pxa_rtc_hack, PAGE_SIZE); -+ printk("Reserved %ld bytes at %lx for RTC hack\n", -+ PAGE_SIZE, pxa_rtc_hack); -+ save_RCNR = (unsigned long *) phys_to_virt(pxa_rtc_hack); -+ if ( (save_RCNR[0] ^ save_RCNR[1]) == 0xffffffff ) { -+ printk("Restoring saved RCNR value to %ld (from %lx)\n", -+ save_RCNR[0], (unsigned long) save_RCNR); -+ RCNR = save_RCNR[0]; -+ } -+ else { -+ printk("No valid saved RCNR value found at %lx\n", (unsigned long) save_RCNR); -+ } - } -+#endif /* CONFIG_PXA_RTC_HACK */ ---- linux-2.4.21/arch/arm/mach-pxa/generic.h~pm -+++ linux-2.4.21/arch/arm/mach-pxa/generic.h -@@ -17,3 +17,7 @@ - mi->bank[__nr].size = (__size), \ - mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27) - -+#ifdef CONFIG_PXA_RTC_HACK -+void pxa_rtc_hack_init(void); -+extern unsigned long *save_RCNR; -+#endif ---- /dev/null -+++ linux-2.4.21/arch/arm/mach-pxa/pm-common.c -@@ -0,0 +1,285 @@ -+/* -+ * SA1100 Power Management Routines -+ * -+ * Copyright (c) 2001 Cliff Brake -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License. -+ * -+ * History: -+ * -+ * 2001-02-06: Cliff Brake Initial code -+ * -+ * 2001-02-25: Sukjae Cho & -+ * Chester Kuo -+ * Save more value for the resume function! Support -+ * Bitsy/Assabet/Freebird board -+ * -+ * 2001-08-29: Nicolas Pitre -+ * Cleaned up, pushed platform dependent stuff -+ * in the platform specific files. -+ * -+ * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array. -+ * Storage is local on the stack now. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+ -+#ifdef CONFIG_IPAQ_HANDHELD -+#include -+#endif -+ -+#define __KERNEL_SYSCALLS__ -+#include -+ -+ -+ -+static char pm_helper_path[128] = "/etc/apm/apmd_proxy"; -+extern int exec_usermodehelper(char *path, char **argv, char **envp); -+int debug_pm = 0; -+static int pm_helper_veto = 0; -+ -+static int -+run_sbin_pm_helper( pm_request_t action ) -+{ -+ int i; -+ char *argv[3], *envp[8]; -+ -+ if (!pm_helper_path[0]) -+ return 2; -+ -+ if ( action != PM_SUSPEND && action != PM_RESUME ) -+ return 1; -+ -+ /* Be root */ -+ current->uid = current->gid = 0; -+ -+ i = 0; -+ argv[i++] = pm_helper_path; -+ argv[i++] = (action == PM_RESUME ? "resume" : "suspend"); -+ -+ if (action == PM_RESUME) -+ argv[i++]="suspend"; -+ -+ argv[i] = 0; -+ -+ i = 0; -+ /* minimal command environment */ -+ envp[i++] = "HOME=/"; -+ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; -+ envp[i] = 0; -+ -+ /* other stuff we want to pass to /sbin/pm_helper */ -+ return exec_usermodehelper (argv [0], argv, envp); -+} -+ -+/* -+ * If pm_suggest_suspend_hook is non-NULL, it is called by pm_suggest_suspend. -+ */ -+int (*pm_suggest_suspend_hook)(int state); -+EXPORT_SYMBOL(pm_suggest_suspend_hook); -+ -+/* -+ * If pm_use_sbin_pm_helper is nonzero, then run_sbin_pm_helper is called before suspend and after resume -+ */ -+int pm_use_sbin_pm_helper = 1; -+EXPORT_SYMBOL(pm_use_sbin_pm_helper); -+ -+/* -+ * If sysctl_pm_do_suspend_hook is non-NULL, it is called by sysctl_pm_do_suspend. -+ * If it returns a true value, then pm_suspend is not called. -+ * Use this to hook in apmd, for now. -+ */ -+int (*pm_sysctl_suspend_hook)(int state); -+EXPORT_SYMBOL(pm_sysctl_suspend_hook); -+ -+int pm_suspend(void); -+ -+int pm_suggest_suspend(void) -+{ -+ int retval; -+ -+ if (pm_suggest_suspend_hook) { -+ if (pm_suggest_suspend_hook(PM_SUSPEND)) -+ return 0; -+ } -+ -+ if (pm_use_sbin_pm_helper) { -+ pid_t pid; -+ int res; -+ int status = 0; -+ unsigned int old_fs; -+ -+ pid = kernel_thread ((int (*) (void *)) run_sbin_pm_helper, (void *) PM_SUSPEND, 0 ); -+ if ( pid < 0 ) -+ return pid; -+ -+ if (debug_pm) -+ printk(KERN_CRIT "%s:%d got pid=%d\n", __FUNCTION__, __LINE__, pid); -+ -+ old_fs = get_fs (); -+ set_fs (get_ds ()); -+ res = waitpid(pid, &status, __WCLONE); -+ set_fs (old_fs); -+ -+ if ( pid != res ) { -+ if (debug_pm) -+ printk(KERN_CRIT ": waitpid returned %d (exit_code=%d); not suspending\n", res, status ); -+ -+ return -1; -+ } -+ -+ /*if ( WIFEXITED(status) && ( WIFEXITSTATUS(status) != 0 )) {*/ -+ if (( status & 0xff7f ) != 0 ) { -+ if (pm_helper_veto) { -+ if (debug_pm) -+ printk(KERN_CRIT "%s: SUSPEND WAS CANCELLED BY pm_helper (exit status %d)\n", __FUNCTION__, status >> 8); -+ return -1; -+ } else { -+ if (debug_pm) -+ printk(KERN_CRIT "%s: pm_helper returned %d, but going ahead anyway\n", __FUNCTION__, status >> 8); -+ } -+ } -+ } -+ -+ if (debug_pm) -+ printk(KERN_CRIT "%s: REALLY SUSPENDING NOW\n", __FUNCTION__ ); -+ -+ if (pm_sysctl_suspend_hook) { -+ if (pm_sysctl_suspend_hook(PM_SUSPEND)) -+ return 0; -+ } -+ -+ retval = pm_suspend(); -+ if (retval) { -+ if (debug_pm) -+ printk(KERN_CRIT "pm_suspend returned %d\n", retval); -+ return retval; -+ } -+ -+ if (pm_use_sbin_pm_helper) { -+ pid_t pid; -+ -+ if (debug_pm) -+ printk(KERN_CRIT "%s: running pm_helper for wakeup\n", __FUNCTION__); -+ -+ pid = kernel_thread ((int (*) (void *)) run_sbin_pm_helper, (void *) PM_RESUME, 0 ); -+ if ( pid < 0 ) -+ return pid; -+ -+ if ( pid != waitpid ( pid, NULL, __WCLONE )) -+ return -1; -+ } -+ -+ return 0; -+} -+ -+EXPORT_SYMBOL(pm_suggest_suspend); -+ -+ -+/* -+ * Send us to sleep. -+ */ -+int pm_suspend(void) -+{ -+ int retval; -+ -+ retval = pm_send_all(PM_SUSPEND, (void *)3); -+ if ( retval ) -+ return retval; -+ -+#ifdef CONFIG_IPAQ_HANDHELD -+ retval = h3600_power_management(PM_SUSPEND); -+ if (retval) { -+ pm_send_all(PM_RESUME, (void *)0); -+ return retval; -+ } -+#endif -+ -+ retval = pm_do_suspend(); -+ -+#ifdef CONFIG_IPAQ_HANDHELD -+ /* Allow the power management routines to override resuming */ -+ while ( h3600_power_management(PM_RESUME) ) -+ retval = pm_do_suspend(); -+#endif -+ -+ pm_send_all(PM_RESUME, (void *)0); -+ -+ return retval; -+} -+EXPORT_SYMBOL(pm_suspend); -+ -+#ifdef CONFIG_SYSCTL -+/* -+ * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than -+ * linux/sysctl.h. -+ * -+ * This means our interface here won't survive long - it needs a new -+ * interface. Quick hack to get this working - use sysctl id 9999. -+ */ -+#warning ACPI broke the kernel, this interface needs to be fixed up. -+#define CTL_ACPI 9999 -+#define ACPI_S1_SLP_TYP 19 -+ -+/* -+ * Send us to sleep. -+ */ -+static int sysctl_pm_do_suspend(void) -+{ -+ int retval; -+ -+ retval = pm_send_all(PM_SUSPEND, (void *)3); -+ -+ if (retval == 0) { -+ retval = pm_do_suspend(); -+ -+ pm_send_all(PM_RESUME, (void *)0); -+ } -+ -+ return retval; -+} -+ -+static struct ctl_table pm_table[] = -+{ -+ {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend}, -+ {2, "helper", pm_helper_path, sizeof(pm_helper_path), 0644, NULL, (proc_handler *)&proc_dostring}, -+ {3, "debug", &debug_pm, sizeof(debug_pm), 0644, NULL, (proc_handler *)&proc_dointvec}, -+ {4, "helper_veto", &pm_helper_veto, sizeof(pm_helper_veto), 0644, NULL, (proc_handler *)&proc_dointvec}, -+ {0} -+}; -+ -+static struct ctl_table pm_dir_table[] = -+{ -+ {CTL_ACPI, "pm", NULL, 0, 0555, pm_table}, -+ {0} -+}; -+ -+/* -+ * Initialize power interface -+ */ -+static int __init pm_init(void) -+{ -+ register_sysctl_table(pm_dir_table, 1); -+ return 0; -+} -+ -+__initcall(pm_init); -+ -+#endif -+ ---- linux-2.4.21/arch/arm/mach-pxa/pm.c~pm -+++ linux-2.4.21/arch/arm/mach-pxa/pm.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -82,7 +83,7 @@ - - /* - * Temporary solution. This won't be necessary once -- * we move pxa support into the serial/* driver -+ * we move pxa support into the serial driver - * Save the FF UART - */ - SAVE(FFIER); -@@ -176,7 +177,7 @@ - - /* - * Temporary solution. This won't be necessary once -- * we move pxa support into the serial/* driver. -+ * we move pxa support into the serial driver. - * Restore the FF UART. - */ - RESTORE(FFMCR); -@@ -209,6 +210,12 @@ - return virt_to_phys(sp); - } - -+#ifndef CONFIG_APM -+/* -+ * This code is only needed if we don't compile in APM support. -+ * If we compile APM support in, then this code is in pm-common.c -+ */ -+ - #ifdef CONFIG_SYSCTL - /* - * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than -@@ -263,3 +270,6 @@ - __initcall(pm_init); - - #endif -+#endif -+ -+EXPORT_SYMBOL(pm_do_suspend); ---- linux-2.4.21/arch/arm/mach-pxa/pxa_usb.h~pxa-usb -+++ linux-2.4.21/arch/arm/mach-pxa/pxa_usb.h -@@ -39,6 +39,7 @@ - int pxa_usb_xmitter_avail( void ); - int pxa_usb_send(char *buf, int len, usb_callback_t callback); - void sa110a_usb_send_reset(void); -+void pxa_usb_send_reset(void); - - /* in usb_recev.c */ - int pxa_usb_recv(char *buf, int len, usb_callback_t callback); ---- /dev/null -+++ linux-2.4.21/arch/arm/mach-pxa/ramses.c -@@ -0,0 +1,844 @@ -+/* -+ * linux/arch/arm/mach-pxa/ramses.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. -+ * -+ * Copyright (c) 2002,2003,2004 by M&N Logistik-Lösungen Online GmbH -+ * written by Holger Schurig -+ * -+ * 2001-09-13: Cliff Brake -+ * Initial code -+ * -+ * 2002-10-09: adaptions to ramses -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef CONFIG_APM -+#include -+#endif -+#define USE_UCB -+//#define PFI_LED -+#define PFI_TURNOFF -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef USE_UCB -+#include "../drivers/misc/ucb1x00.h" -+#endif -+ -+#include "generic.h" -+ -+ -+/* shadow registers for write only registers */ -+u16 ramses_control_shadow = -+ RAMSES_CONTROL_LED_BLUE_ + -+ RAMSES_CONTROL_LED_ORANGE_ + -+ RAMSES_CONTROL_SCANNER_WAKE_ + -+ RAMSES_CONTROL_SCANNER_TRIG_; -+ -+/* various flags the change the behavior of the kernel */ -+unsigned int ramses_flags = -+ RAMSES_FLAGS_KEY_SCAN + -+ RAMSES_FLAGS_KEY_SUSPEND + -+ RAMSES_FLAGS_KEY_OFF; -+ -+ -+/******************************************************************/ -+/* Corevoltage settings */ -+/******************************************************************/ -+ -+int ramses_corevolt_shadow = 150; -+ -+void ramses_set_corevolt(int volt) -+{ -+ int val = 0; -+ switch (volt) { -+ case 150: -+ val = 5; -+ break; -+ case 135: -+ val = 8; -+ break; -+ case 125: -+ val = 10; -+ break; -+ case 115: -+ val = 12; -+ break; -+ case 105: -+ val = 14; -+ break; -+ } -+ if (val) { -+ ramses_corevolt_shadow = volt; -+ RAMSES_COREVOLT = val; -+ RAMSES_CPLD_PERIPH_PWR |= CORE_VAR_EN; -+ } -+} -+ -+ -+/******************************************************************/ -+/* LCD stuff */ -+/******************************************************************/ -+ -+u16 ramses_lcd_type; -+ -+void ramses_lcd_power_on(void) -+{ -+ //printk("--> ramses_lcd_power_on\n"); -+ -+ /* 1. VCC */ -+ RAMSES_CPLD_LCD |= RAMSES_LCD_VCC; -+ -+ /* 2. Signal */ -+ -+ /* 3. the PWM */ -+ CKEN |= (CKEN0_PWM0 | CKEN1_PWM1); -+ -+ /* 4. nDISPOFF (done at backlight_on time) */ -+ RAMSES_CPLD_LCD |= RAMSES_LCD_DISPOFF; -+} -+ -+ -+void ramses_lcd_power_off(void) -+{ -+ //printk("--> ramses_lcd_power_off\n"); -+ if (RAMSES_CPLD_LCD & RAMSES_LCD_DISPOFF) { -+ //printk("--> turn bl off first\n"); -+ ramses_lcd_backlight_off(); -+ } -+ -+ /* 1. nDISPOFF (just to be sure) */ -+ RAMSES_CPLD_LCD &= ~RAMSES_LCD_DISPOFF; -+ -+ // for Torisan: wait until all has been sent out -+ if (ramses_lcd_type == 2) { -+ int i; -+ for (i=0; i<33; i++) -+ udelay(1500); -+ } -+ -+ /* 2. disable the PWM */ -+ set_GPIO_mode(GPIO16_PWM0 | GPIO_OUT); -+ set_GPIO_mode(GPIO17_PWM1 | GPIO_OUT); -+ CKEN &= ~(CKEN0_PWM0 | CKEN1_PWM1); -+ -+ /* 3. SIGNAL */ -+ -+ /* 4. VCC */ -+ RAMSES_CPLD_LCD &= ~RAMSES_LCD_VCC; -+} -+ -+ -+void ramses_lcd_backlight_on(void) -+{ -+ int i; -+ -+ //printk("--> ramses_lcd_backlight_on\n"); -+ if ((ramses_control_shadow & RAMSES_CONTROL_LCD_BLIGHT) != 0) -+ return; -+ //printk(" state: %d\n", ramses_control_shadow & RAMSES_CONTROL_LCD_BLIGHT); -+ -+ set_GPIO_mode(GPIO17_PWM1 | GPIO_OUT); -+ -+ /* 4. nDISPOFF */ -+ RAMSES_CPLD_LCD |= RAMSES_LCD_DISPOFF; -+ -+ /* Backlight can be turned on at any time */ -+ RAMSES_LCD_BLIGHT_ON(); -+ -+ for (i=0; i<33; i++) -+ udelay(1500); -+ set_GPIO_mode(GPIO16_PWM0_MD); -+ set_GPIO_mode(GPIO17_PWM1_MD); -+} -+ -+ -+void ramses_lcd_backlight_off(void) -+{ -+ int i; -+ -+ //printk("--> ramses_lcd_backlight_off\n"); -+ if ((ramses_control_shadow & RAMSES_CONTROL_LCD_BLIGHT) == 0) -+ return; -+ //printk(" state: %d\n", ramses_control_shadow & RAMSES_CONTROL_LCD_BLIGHT); -+ -+ set_GPIO_mode(GPIO17_PWM1 | GPIO_OUT); -+ for (i=0; i<100; i++) -+ udelay(1500); -+ -+ /* Backlight can be turned off at any time */ -+ RAMSES_LCD_BLIGHT_OFF(); -+ udelay(1500); -+ -+ /* 1. nDISPOFF */ -+ if (ramses_lcd_type != 2) -+ RAMSES_CPLD_LCD &= ~RAMSES_LCD_DISPOFF; -+ -+ //set_GPIO_mode(GPIO16_PWM0 | GPIO_IN); -+ //set_GPIO_mode(GPIO17_PWM1 | GPIO_IN); -+} -+ -+ -+void ramses_lcd_set_brightness(int b) -+{ -+ if (b > 255) b = 255; -+ if (b < 0) b = 0; -+ PWM_PWDUTY1 = 510-(b<<1); -+} -+ -+ -+int ramses_lcd_get_brightness(void) -+{ -+ return 255-(PWM_PWDUTY1 >> 1); -+} -+ -+ -+void ramses_lcd_set_contrast(int c) -+{ -+ if (c > 255) c = 255; -+ if (c < 0) c = 0; -+ PWM_PWDUTY0 = 542-c; -+} -+ -+ -+int ramses_lcd_get_contrast(void) -+{ -+ return 542-PWM_PWDUTY0; -+} -+ -+ -+void ramses_lcd_set_intensity(int i) -+{ -+ //printk("--> ramses_lcd_set_intensity(%d)\n", i); -+ if (i) { -+ ramses_lcd_backlight_on(); -+ } else { -+ ramses_lcd_backlight_off(); -+ } -+} -+ -+ -+int ramses_lcd_get_intensity(void) -+{ -+ return ramses_control_shadow & RAMSES_CONTROL_LCD_BLIGHT; -+} -+ -+ -+ -+ -+ -+/******************************************************************/ -+/* HDQ communication */ -+/******************************************************************/ -+ -+#define GPIO_HDQ 2 -+ -+#define HDQ_LO GPCR(GPIO_HDQ) = GPIO_bit(GPIO_HDQ) -+#define HDQ_HI GPSR(GPIO_HDQ) = GPIO_bit(GPIO_HDQ) -+#define HDQ_GET (GPLR(GPIO_HDQ) & (1 << GPIO_HDQ)) -+ -+#define MAXLOOPS 800 -+#define MAXTRIES 3 -+ -+ -+static void hdq_break(void) -+{ -+ HDQ_LO; -+ set_GPIO_mode(GPIO_HDQ | GPIO_OUT); -+ udelay(220); -+ HDQ_HI; -+ udelay(50); -+} -+ -+ -+/** -+ * Send data on the 1-bit wire. -+ * -+ * LSB first. Depending on the bit, do the low phase short or -+ * small. The used timings in usec's are made so that our send -+ * stuff has exactly the timing that the BQ2050 battery sends -+ * us back. -+*/ -+static void hdq_put_data(unsigned char cmd) -+{ -+ unsigned char mask = 1; -+ -+ HDQ_HI; -+ set_GPIO_mode(GPIO_HDQ | GPIO_OUT); -+ -+ while (1) { -+ HDQ_LO; -+ udelay(cmd & mask ? 37 : 115); -+ HDQ_HI; -+ udelay(cmd & mask ? 163 : 85); -+ if (mask == 0x80) break; -+ mask = mask << 1; -+ } -+ set_GPIO_mode(GPIO_HDQ | GPIO_IN); -+} -+ -+ -+/** -+ * Receive data on the 1-bit wire. -+ * -+ * Little state-machine with two states (yuck) that measures the time -+ * in the low-state. If it exceeds some value, then the bit was a 0, -+ * otherwise it's a 1. -+*/ -+static int hdq_get_data(void) -+{ -+ enum { ST_WAITLOW, ST_LOW }; -+ -+ int i; -+ int lastlow = 0; -+ int state = ST_WAITLOW; -+ unsigned char mask = 1; -+ unsigned char d = 0; -+ -+ for (i=0; i %08x\n", old_shadow, ramses_control_shadow); -+ -+ RAMSES_CPLD_PERIPH_PWR &= ~PER_PWR_EN; -+ break; -+ -+ case PM_RESUME: -+ RAMSES_CPLD_PERIPH_PWR |= PER_PWR_EN; -+ ramses_control_shadow = old_shadow; -+ PWM_CTRL0 = old_ctrl0; -+ PWM_CTRL1 = old_ctrl1; -+ PWM_PERVAL0 = old_perval0; -+ PWM_PERVAL1 = old_perval1; -+ PWM_PWDUTY0 = old_duty0; -+ PWM_PWDUTY1 = old_duty1; -+ -+ break; -+ } -+ return 0; -+} -+ -+#endif -+ -+ -+ -+static void pf_interrupt(int irq, void *dummy, struct pt_regs *fp) -+{ -+#ifdef PFI_LED -+ RAMSES_LED_BLUE_ON(); -+ RAMSES_LED_ORANGE_ON(); -+#endif -+#ifdef PFI_TURNOFF -+ // Make sure we can't be turned on by setting low onto the CPLD's columns -+ RAMSES_CPLD_KB_COL_LOW = 0; -+ RAMSES_CPLD_KB_COL_HIGH = 0; -+ -+ // turn power off -+ RAMSES_POWER_OFF(); -+ -+ // wait until VCC fades -+ while (1) { } -+#endif -+} -+ -+ -+void ramses_shut_off(void) -+{ -+ // Make sure we can't be turned on by setting low onto the CPLD's columns -+ RAMSES_CPLD_KB_COL_LOW = 0; -+ RAMSES_CPLD_KB_COL_HIGH = 0; -+ //printk("--> ramses_shut_off calling ramses_lcd_backlight_off\n"); -+ ramses_lcd_backlight_off(); -+ //printk("--> ramses_shut_off calling ramses_lcd_power_off\n"); -+ ramses_lcd_power_off(); -+ -+ // turn power off -+ RAMSES_POWER_OFF(); -+ -+ // wait until voltage fades -+ while (1) {} -+} -+ -+ -+ -+ -+#ifdef CONFIG_APM -+static int ramses_get_power_status(u_char *ac_line_status, -+ u_char *battery_status, -+ u_char *battery_flag, -+ u_char *battery_percentage, -+ u_short *battery_life) -+{ -+#ifdef USE_UCB -+ int adc3; -+ struct ucb1x00 *ucb = ucb1x00_get(); -+ -+ ucb1x00_adc_enable(ucb); -+ adc3 = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD3, 0); -+ ucb1x00_adc_disable(ucb); -+ -+ /* -+ * when charged: 0..430 -+ * when discharging: 0..340 -+ */ -+ -+#define CHG_LO 165 -+#define CHG_HI 420 -+#define OFF_LO 60 -+#define OFF_HI 350 -+ if ((RAMSES_CPLD_MISC_STATUS & RAMSES_CHG_STS) == 0) { -+ // in Docking-Station -+ if (adc3 > CHG_HI) adc3 = CHG_HI; -+ if (adc3 < CHG_LO) adc3 = CHG_LO; -+ adc3 -= CHG_LO; -+ *battery_percentage = adc3 * 100 / (CHG_HI-CHG_LO); -+ *ac_line_status = 0x01; -+ } else { -+ // offline -+ if (adc3 > OFF_HI) adc3 = OFF_HI; -+ if (adc3 < OFF_LO) adc3 = OFF_LO; -+ adc3 -= OFF_LO; -+ *battery_percentage = adc3 * 100 / (OFF_HI-OFF_LO); -+ *ac_line_status = 0x00; -+ } -+ -+ if (*battery_percentage > 100) -+ *battery_percentage = 100; -+ -+ if (*ac_line_status) { -+ *battery_status = 3; // charging -+ *battery_flag = 1<<3; -+ } else -+ if (*battery_percentage >= 30) { -+ *battery_status = 0; // high -+ *battery_flag = 1<<0; -+ } else -+ if (*battery_percentage >= 15) { -+ *battery_status = 1; // low -+ *battery_flag = 1<<1; -+ } else { -+ *battery_status = 2; // critical -+ *battery_flag = 1<<2; -+ } -+ -+ // assume 5.5 hours operation, 330 minutes -+ *battery_life = (*battery_percentage * 330 / 100) | 0x8000; -+#endif -+ -+ -+#ifdef USE_HDQ -+#error HDQ -+ // SAE is something like mAh * 10 -+ int sae, sael; -+ -+ sael = ramses_hdq_get_reg(HDQ_SAEL); -+ sae = ramses_hdq_get_reg(HDQ_SAEH); -+ -+ if (sae == -1 || sael == -1) { -+ //printk("ramses: could not read HDQ_SAE\n"); -+ *ac_line_status = 0xff; -+ *battery_status = 0xff; -+ *battery_flag = 0xff; -+ *battery_percentage = 0xff; -+ *battery_life = -1; -+ return 0; -+ } -+ -+ sae = (sae << 16) + sael; -+ if (sae > 27000) { -+ printk("ramses: capped HDQ_SAE from %d to 27000\n", sae); -+ sae = 27000; -+ } -+ -+ if (sae < 4000) { -+ *battery_status = 2; // critical -+ *battery_flag = 1<<2; -+ } else -+ if (sae < 10000) { -+ *battery_status = 1; // low -+ *battery_flag = 1<<1; -+ } else { -+ *battery_status = 0; // high -+ *battery_flag = 1<<0; -+ } -+ -+ if ((RAMSES_CPLD_MISC_STATUS & RAMSES_CHG_STS) == 0) { -+ *battery_status = 3; // charging -+ *battery_flag = 1<<3; -+ *ac_line_status = 0x01; // online -+ } else { -+ *ac_line_status = 0x00; // offline -+ } -+ -+ *battery_percentage = sae / 270; -+ *battery_life = (sae / 56) | 0x8000; -+#endif -+ -+ -+#if !defined(USE_UCB) && !defined(USE_HDQ) -+#error NONE -+ *ac_line_status = 0xff; -+ *battery_status = 0xff; -+ *battery_flag = 0xff; -+ *battery_percentage = 0xff; -+ *battery_life = -1; -+#endif -+ -+ return 0; -+} -+#endif -+ -+ -+ -+ -+/******************************************************************/ -+/* Initialisation */ -+/******************************************************************/ -+ -+static struct map_desc ramses_io_desc[] __initdata = { -+ /* virtual physical length domain r w c b */ -+ { RAMSES_IDE_BASE, RAMSES_IDE_PHYS, RAMSES_IDE_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, -+ { RAMSES_ETH_BASE, RAMSES_ETH_PHYS, RAMSES_ETH_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, -+ { RAMSES_COREVOLT_BASE, RAMSES_COREVOLT_PHYS, RAMSES_COREVOLT_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, -+ { RAMSES_CPLD_BASE, RAMSES_CPLD_PHYS, RAMSES_CPLD_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, -+ { RAMSES_CONTROL_BASE, RAMSES_CONTROL_PHYS, RAMSES_CONTROL_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, -+ LAST_DESC -+}; -+ -+ -+ -+ -+ -+/* -+ * Uncompressing Linux...... done, booting the kernel. -+ * Linux version 2.4.19-rmk4-pxa1-mn ... -+ * CPU: Intel XScale-PXA250 revision 4 -+ * Machine: Ramses -+ * fixup_ramses() -+ */ -+ -+static void __init -+fixup_ramses(struct machine_desc *desc, struct param_struct *params, -+ char **cmdline, struct meminfo *mi) -+{ -+ SET_BANK (0, 0xa0000000,128*1024*1024); -+ mi->nr_banks = 1; -+} -+ -+ -+ -+ -+/* -+ * fixup_ramses() -+ * ramses_map_io() -+ */ -+ -+static void __init ramses_map_io(void) -+{ -+ u16 smc_eeprom_read(long ioaddr, u16 location); -+ -+ pxa_map_io(); -+ iotable_init(ramses_io_desc); -+ -+#ifdef IPAQ -+ // set power managament stuff -+ PGSR0 = GPSRx_SleepValue; -+ PGSR1 = GPSRy_SleepValue; -+ PGSR2 = GPSRz_SleepValue; -+ PWER = PWER_GPIO0 | PWER_RTC; -+ PFER = PWER_GPIO0 | PWER_RTC; -+ PRER = 0; -+#endif -+ -+ ramses_lcd_type = smc_eeprom_read(RAMSES_ETH_BASE+0x300, RAMSES_LCD_TYPE_OFFSET); -+ // here we could make a special case about ramses_lcd_type == 0xffff -+ ramses_flags |= (ramses_lcd_type & RAMSES_FLAGS_LCD_FBTURN); -+} -+ -+ -+ -+ -+/* -+ * ramses_map_io() -+ * Memory clock: 99.53MHz (*27) -+ * Run Mode clock: 199.07MHz (*2) -+ * Turbo Mode clock: 398.13MHz (*2.0, active) * On node 0 totalpages: 16384 -+ * zone(0): 32768 pages. -+ * zone(1): 0 pages. -+ * zone(2): 0 pages. -+ * Kernel command line: root=/dev/nfsroot ... -+ * ramses_init_irq() -+ */ -+ -+static void __init ramses_init_irq(void) -+{ -+ set_GPIO_IRQ_edge(21, GPIO_FALLING_EDGE); // UCB 1400 -+ -+ RAMSES_SCANNER_OFF(); -+ RAMSES_GSM_OFF(); -+ RAMSES_GSM_RESET_OFF(); -+ RAMSES_GSM_BOOT_OFF(); -+ pxa_init_irq(); -+} -+ -+ -+ -+ -+/* -+ * ramses_init_irq() -+ * Console: colour dummy device 80x30 -+ * serial_console_init -+ * serial_console_setup -+ * Calibrating delay loop... 397.31 BogoMIPS -+ * Memory: 128MB = 128MB total -+ * Memory: 127872KB available (1355K code, 272K data, 112K init) -+ * Dentry cache hash table entries: 16384 (order: 5, 131072 bytes) -+ * Inode cache hash table entries: 8192 (order: 4, 65536 bytes) -+ * Mount-cache hash table entries: 2048 (order: 2, 16384 bytes) -+ * Buffer-cache hash table entries: 8192 (order: 3, 32768 bytes) -+ * Page-cache hash table entries: 32768 (order: 5, 131072 bytes) -+ * POSIX conformance testing by UNIFIX -+ * Linux NET4.0 for Linux 2.4 -+ * Based upon Swansea University Computer Society NET3.039 -+ * Initializing RT netlink socket -+ * ramses_init() -+ */ -+ -+static int __init ramses_init(void) -+{ -+ unsigned int irq_gpio_pin; -+ -+ // Set IRQ for Touchpanel (via UCB 1400) -+ irq_gpio_pin = IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ); -+ set_GPIO_IRQ_edge(irq_gpio_pin, TOUCH_PANEL_IRQ_EDGE); -+ -+ // Set IRQ for Power Fail Interrupt -+ set_GPIO_IRQ_edge(1, GPIO_FALLING_EDGE); -+ request_irq(IRQ_GPIO(1), pf_interrupt, 0, "PWR FAIL", NULL); -+ -+ // Setup IRQ edge for Ethernet -+ //set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(27), GPIO_RISING_EDGE); -+ set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(ETHERNET_IRQ), ETHERNET_IRQ_EDGE); -+ -+ // Configure PWMs for LCD -+ PWM_CTRL0 = 0; -+ PWM_PERVAL0 = 512; -+ PWM_PWDUTY0 = 440; -+ PWM_CTRL1 = 0; -+ PWM_PERVAL1 = 512; -+ PWM_PWDUTY1 = 450; -+ -+ // Request Memory Regions of core components -+ request_mem_region(RAMSES_CONTROL_BASE, RAMSES_CONTROL_SIZE, "Ramses Control"); -+ request_mem_region(RAMSES_CPLD_BASE, RAMSES_CPLD_SIZE, "Ramses CPLD"); -+ request_mem_region(RAMSES_COREVOLT_BASE, RAMSES_COREVOLT_SIZE, "Ramses Corevolt"); -+ -+#ifdef CONFIG_PM -+#ifdef PM_DEBUG -+ pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ramses_pm_callback, "ramses"); -+#else -+ pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ramses_pm_callback); -+#endif -+ //TODO PWER (PXA255: 3-25) -+ //TODO PRER (PXA255: 3-26) -+ //TODO PFER (PXA255: 3-27) -+ //TODO PSSR (PXA255: 3-29) -+ //TODO PGSR0..PGSR2 (PXA255: 3-32) -+#endif -+ -+#ifdef CONFIG_APM -+ apm_register_get_power_status(ramses_get_power_status); -+#endif -+ -+ PCFR = PCFR_OPDE | PCFR_FS | PCFR_FP; // PXA255: 3-24 -+ -+ pm_power_off = ramses_shut_off; -+ -+ return 0; -+} -+ -+__initcall(ramses_init); -+ -+ -+ -+/* -+ * ramses_init() -+ * Using PXA255 frequency points. -+ * Registering CPU frequency change support. -+ * CPU clock: 398.131 MHz (99.000-400.000 MHz) -+ * Starting kswapd -+ * devfs: v1.12a (20020514) Richard Gooch (rgooch@atnf.csiro.au) -+ * devfs: boot_options: 0x1 -+ * pty: 256 Unix98 ptys configured -+ * pxa & ti16c754b serial driver -+ * tts/0 at irq 14 is a PXA UART -+ * tts/1 at irq 13 is a PXA UART -+ * tts/2 at irq 12 is a PXA UART -+ * tts/3 at irq 45 is a TI16750 -+ * tts/4 at irq 46 is a TI16750 -+ * tts/5 at irq 47 is a TI16750 -+ * tts/6 at irq 48 is a TI16750 -+ * LAN91C111: You shouldn't use auto-probing with insmod! -+ * SMSC LAN91C111 Driver (v2.2), (Linux Kernel 2.4 + Support for Odd Byte) ... -+ * eth0: SMC91C11xFD(rev:1) at 0xf0100300 IRQ:26 MEMSIZE ... -+ * ac97_codec: AC97 Audio codec, id: 0x5053:0x4304 (Philips UCB1400) -+ * NET4: Linux TCP/IP 1.0 for NET4.0 -+ * IP Protocols: ICMP, UDP, TCP -+ * IP: routing cache hash table of 512 buckets, 4Kbytes -+ * TCP: Hash tables configured (established 4096 bind 4096) -+ * IP-Config: ... -+ * NET4: Unix domain sockets 1.0/SMP for Linux NET4.0. -+ * NetWinder Floating Point Emulator V0.95 (c) 1998-1999 Rebel.com -+ * Looking up port of RPC 100003/2 on 192.168.233.66 -+ * Looking up port of RPC 100005/1 on 192.168.233.66 -+ * VFS: Mounted root (nfs filesystem). -+ * Mounted devfs on /dev -+ * Freeing init memory: 68K -+ * INIT: version 2.84 booting -+ */ -+ -+ -+ -+MACHINE_START(RAMSES, "Ramses") -+ MAINTAINER("M&N Logistik-Lösungen Online GmbH") -+ BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000) -+ BOOT_PARAMS(0xa0000100) -+ FIXUP(fixup_ramses) -+ MAPIO(ramses_map_io) -+ INITIRQ(ramses_init_irq) -+MACHINE_END -+ -+EXPORT_SYMBOL(ramses_lcd_type); -+EXPORT_SYMBOL(ramses_lcd_power_on); -+EXPORT_SYMBOL(ramses_lcd_power_off); -+EXPORT_SYMBOL(ramses_lcd_backlight_on); -+EXPORT_SYMBOL(ramses_lcd_backlight_off); -+EXPORT_SYMBOL(ramses_lcd_set_intensity); -+EXPORT_SYMBOL(ramses_lcd_set_brightness); -+EXPORT_SYMBOL(ramses_lcd_set_contrast); -+EXPORT_SYMBOL(ramses_lcd_get_intensity); -+EXPORT_SYMBOL(ramses_lcd_get_brightness); -+EXPORT_SYMBOL(ramses_lcd_get_contrast); -+EXPORT_SYMBOL(ramses_hdq_get_reg); -+EXPORT_SYMBOL(ramses_set_corevolt); -+EXPORT_SYMBOL(ramses_corevolt_shadow); ---- linux-2.4.21/arch/arm/mach-pxa/usb-char.c~pxa-usb -+++ linux-2.4.21/arch/arm/mach-pxa/usb-char.c -@@ -211,7 +211,6 @@ - static void twiddle_descriptors( void ) - { - desc_t * pDesc = pxa_usb_get_descriptor_ptr(); -- string_desc_t * pString; - - pDesc->b.ep1.wMaxPacketSize = make_word_c( RX_PACKET_SIZE ); - pDesc->b.ep1.bmAttributes = USB_EP_BULK; -@@ -220,6 +219,7 @@ - - if ( machine_is_extenex1() ) { - #ifdef CONFIG_SA1100_EXTENEX1 -+ string_desc_t * pString; - pDesc->dev.idVendor = make_word_c( 0xC9F ); - pDesc->dev.idProduct = 1; - pDesc->dev.bcdDevice = make_word_c( 0x0001 ); ---- linux-2.4.21/arch/arm/mach-pxa/usb-eth.c~pxa-usbeth -+++ linux-2.4.21/arch/arm/mach-pxa/usb-eth.c -@@ -52,6 +52,7 @@ - - #define ETHERNET_VENDOR_ID 0x49f - #define ETHERNET_PRODUCT_ID 0x505A -+#define ETHERNET_DEVICE_ID 0x0200 - #define MAX_PACKET 32768 - #define MIN(a, b) (((a) < (b)) ? (a) : (b)) - -@@ -329,6 +330,7 @@ - pd->b.ep2.wMaxPacketSize = make_word( usb_wsize ); - pd->dev.idVendor = ETHERNET_VENDOR_ID; - pd->dev.idProduct = ETHERNET_PRODUCT_ID; -+ pd->dev.bcdDevice = ETHERNET_DEVICE_ID; - pstr = pxa_usb_kmalloc_string_descriptor( "PXA USB NIC" ); - if ( pstr ) { - pxa_usb_set_string_descriptor( 1, pstr ); ---- linux-2.4.21/drivers/char/Config.in~i2c-ds1337 -+++ linux-2.4.21/drivers/char/Config.in -@@ -164,6 +164,7 @@ - - if [ "$CONFIG_I2C" != "n" ]; then - dep_tristate ' DS1307 RTC' CONFIG_I2C_DS1307 $CONFIG_I2C -+ dep_tristate ' DS1337 RTC' CONFIG_I2C_DS1337 $CONFIG_I2C - fi - - source drivers/l3/Config.in ---- linux-2.4.21/drivers/char/Makefile~i2c-ds1337 -+++ linux-2.4.21/drivers/char/Makefile -@@ -21,10 +21,11 @@ - # All of the (potential) objects that export symbols. - # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. - --export-objs := busmouse.o console.o keyboard.o sysrq.o \ -+export-objs := vt.o busmouse.o console.o keyboard.o sysrq.o \ - misc.o pty.o random.o selection.o serial.o \ - sonypi.o tty_io.o tty_ioctl.o generic_serial.o \ -- au1000_gpio.o hp_psaux.o nvram.o scx200.o -+ au1000_gpio.o hp_psaux.o nvram.o scx200.o \ -+ input_keyb.o - - mod-subdirs := joystick ftape drm drm-4.0 pcmcia - -@@ -129,6 +130,11 @@ - ifeq ($(CONFIG_SA1100_CERF_CPLD),y) - KEYBD += cerf_keyb.o - endif -+ ifeq ($(CONFIG_ARCH_RAMSES),y) -+ KEYMAP = german.o -+ KEYBD += input_keyb.o -+ obj-m += sysctl.o -+ endif - ifeq ($(CONFIG_ARCH_FORTUNET),y) - KEYMAP := defkeymap.o - endif -@@ -337,6 +343,7 @@ - - # I2C char devices - obj-$(CONFIG_I2C_DS1307) += ds1307.o -+obj-$(CONFIG_I2C_DS1337) += ds1337.o - - subdir-$(CONFIG_MWAVE) += mwave - ifeq ($(CONFIG_MWAVE),y) -@@ -372,4 +379,7 @@ - set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ - - qtronixmap.c: qtronixmap.map -+ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ -+ -+german.c: german.map - set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ ---- linux-2.4.21/drivers/char/console.c~keyb-module -+++ linux-2.4.21/drivers/char/console.c -@@ -150,7 +150,7 @@ - static int con_open(struct tty_struct *, struct file *); - static void vc_init(unsigned int console, unsigned int rows, - unsigned int cols, int do_clear); --static void blank_screen(unsigned long dummy); -+//static void blank_screen(unsigned long dummy); - static void gotoxy(int currcons, int new_x, int new_y); - static void save_cur(int currcons); - static void reset_terminal(int currcons, int do_clear); -@@ -158,7 +158,7 @@ - static void set_vesa_blanking(unsigned long arg); - static void set_cursor(int currcons); - static void hide_cursor(int currcons); --static void unblank_screen_t(unsigned long dummy); -+//static void unblank_screen_t(unsigned long dummy); - static void console_callback(void *ignored); - - static int printable; /* Is console ready for printing? */ -@@ -167,7 +167,7 @@ - int console_blanked; - - static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */ --static int blankinterval = 10*60*HZ; -+//static int blankinterval = 10*60*HZ; - static int vesa_off_interval; - - static struct tq_struct console_callback_tq = { -@@ -209,9 +209,9 @@ - * Hook so that the power management routines can (un)blank - * the console on our behalf. - */ --int (*console_blank_hook)(int); -+//int (*console_blank_hook)(int); - --static struct timer_list console_timer; -+//static struct timer_list console_timer; - - /* - * Low-Level Functions -@@ -543,7 +543,7 @@ - - static void set_cursor(int currcons) - { -- if (!IS_FG || console_blanked || vcmode == KD_GRAPHICS) -+ if (!IS_FG || vcmode == KD_GRAPHICS) - return; - if (deccm) { - if (currcons == sel_cons) -@@ -1287,7 +1287,7 @@ - update_attr(currcons); - break; - case 9: /* set blanking interval */ -- blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ; -+ //blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ; - poke_blanked_console(); - break; - case 10: /* set bell frequency in Hz */ -@@ -2575,11 +2575,11 @@ - if (tty_register_driver(&console_driver)) - panic("Couldn't register console driver\n"); - -- init_timer(&console_timer); -- console_timer.function = blank_screen; -- if (blankinterval) { -- mod_timer(&console_timer, jiffies + blankinterval); -- } -+ //init_timer(&console_timer); -+ //console_timer.function = blank_screen; -+ //if (blankinterval) { -+ // mod_timer(&console_timer, jiffies + blankinterval); -+ //} - - /* - * kmalloc is not running yet - we use the bootmem allocator. -@@ -2744,11 +2744,12 @@ - */ - static void vesa_powerdown_screen(unsigned long dummy) - { -- console_timer.function = unblank_screen_t; -+ //console_timer.function = unblank_screen_t; - - vesa_powerdown(); - } - -+#if 0 - static void timer_do_blank_screen(int entering_gfx, int from_timer_handler) - { - int currcons = fg_console; -@@ -2797,12 +2798,14 @@ - if (vesa_blank_mode) - sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1); - } -+#endif - - void do_blank_screen(int entering_gfx) - { -- timer_do_blank_screen(entering_gfx, 0); -+ //timer_do_blank_screen(entering_gfx, 0); - } - -+#if 0 - /* - * This is a timer handler - */ -@@ -2810,12 +2813,14 @@ - { - unblank_screen(); - } -+#endif - - /* - * Called by timer as well as from vt_console_driver - */ - void unblank_screen(void) - { -+#if 0 - int currcons; - - if (!console_blanked) -@@ -2842,6 +2847,7 @@ - /* Low-level driver cannot restore -> do it ourselves */ - update_screen(fg_console); - set_cursor(fg_console); -+#endif - } - - /* -@@ -2849,11 +2855,12 @@ - */ - static void blank_screen(unsigned long dummy) - { -- timer_do_blank_screen(0, 1); -+ //timer_do_blank_screen(0, 1); - } - - void poke_blanked_console(void) - { -+#if 0 - del_timer(&console_timer); - if (!vt_cons[fg_console] || vt_cons[fg_console]->vc_mode == KD_GRAPHICS) - return; -@@ -2863,6 +2870,7 @@ - } else if (blankinterval) { - mod_timer(&console_timer, jiffies + blankinterval); - } -+#endif - } - - /* -@@ -3088,7 +3096,7 @@ - unblank_screen(); - break; - case PM_SUSPEND: -- do_blank_screen(0); -+ //do_blank_screen(0); - break; - } - return 0; -@@ -3106,7 +3114,8 @@ - EXPORT_SYMBOL(video_scan_lines); - EXPORT_SYMBOL(vc_resize); - EXPORT_SYMBOL(fg_console); --EXPORT_SYMBOL(console_blank_hook); -+//EXPORT_SYMBOL(console_blank_hook); -+EXPORT_SYMBOL(console_driver); - #ifdef CONFIG_VT - EXPORT_SYMBOL(vt_cons); - #endif ---- /dev/null -+++ linux-2.4.21/drivers/char/ds1337.c -@@ -0,0 +1,545 @@ -+/* -+ * ds1337.c -+ * -+ * Device driver for Dallas Semiconductor's Real Time Controller DS1337. -+ * -+ * Copyright (C) 2003 M&N Logistik-Lösungen Online GmbH -+ * -+ * 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. -+ * -+ * Documentation for this Chip: http://pdfserv.maxim-ic.com/arpdf/DS1337.pdf -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "ds1337.h" -+ -+//#define DEBUG 1 -+ -+#if DEBUG -+static unsigned int rtc_debug = DEBUG; -+#else -+#define rtc_debug 0 /* gcc will remove all the debug code for us */ -+#endif -+ -+static unsigned short slave_address = DS1337_I2C_SLAVE_ADDR; -+struct i2c_driver ds1337_driver; -+struct i2c_client *ds1337_i2c_client = 0; -+static spinlock_t ds1337_rtc_lock = SPIN_LOCK_UNLOCKED; -+ -+static unsigned short ignore[] = { I2C_CLIENT_END }; -+static unsigned short normal_addr[] = { DS1337_I2C_SLAVE_ADDR, I2C_CLIENT_END }; -+ -+static int ds1337_rtc_ioctl(struct inode *, struct file *, unsigned int, unsigned long); -+static int ds1337_rtc_noop(struct inode *inode, struct file *file); -+ -+static int ds1337_probe(struct i2c_adapter *adap); -+static int ds1337_detach(struct i2c_client *client); -+static int ds1337_command(struct i2c_client *client, unsigned int cmd, void *arg); -+ -+ -+static struct i2c_client_address_data addr_data = { -+ .normal_i2c = normal_addr, -+ .normal_i2c_range = ignore, -+ .probe = ignore, -+ .probe_range = ignore, -+ .ignore = ignore, -+ .ignore_range = ignore, -+ .force = ignore, -+}; -+ -+static struct file_operations rtc_fops = { -+ .owner = THIS_MODULE, -+ .ioctl = ds1337_rtc_ioctl, -+ .open = ds1337_rtc_noop, -+ .release = ds1337_rtc_noop, -+}; -+ -+static struct miscdevice ds1337_rtc_miscdev = { -+ RTC_MINOR, -+ "rtc", -+ &rtc_fops -+}; -+ -+ -+struct i2c_driver ds1337_driver = { -+ .name = "DS1337", -+ .id = I2C_DRIVERID_DS1337, -+ .flags = I2C_DF_NOTIFY, -+ .attach_adapter = ds1337_probe, -+ .detach_client = ds1337_detach, -+ .command = ds1337_command -+}; -+ -+#define DAT(x) ((unsigned int)((x)->data)) /* keep the control register info */ -+ -+ -+static int ds1337_readram(char *buf, int len) -+{ -+ unsigned long flags; -+ unsigned char ad[1] = { 0 }; -+ int ret; -+ struct i2c_msg msgs[2] = { -+ {ds1337_i2c_client->addr, 0, 1, ad}, -+ {ds1337_i2c_client->addr, I2C_M_RD, len, buf} -+ }; -+ -+ spin_lock_irqsave(&ds1337_rtc_lock, flags); -+ ret = i2c_transfer(ds1337_i2c_client->adapter, msgs, 2); -+ spin_unlock_irqrestore(&ds1337_rtc_lock, flags); -+ -+ return ret; -+} -+ -+ -+static void ds1337_setreg(struct i2c_client *c, unsigned char reg, unsigned char val) -+{ -+ unsigned char buf[2]; -+ buf[0] = reg; -+ buf[1] = val; -+ i2c_master_send(c, (char *) buf, 2); -+} -+ -+static int ds1337_attach(struct i2c_adapter *adap, int addr, -+ unsigned short flags, int kind) -+{ -+ struct i2c_client *c; -+ unsigned char buf[DS1337_MEM_SIZE], ad[1] = { 7 }; -+ struct i2c_msg msgs[2] = { -+ {addr, 0, 1, ad}, -+ {addr, I2C_M_RD, 1, buf} -+ }; -+ int ret; -+ -+ if (rtc_debug>1) -+ printk("%s(adap,%d,%d,%d)\n", __FUNCTION__, addr, flags, kind); -+ -+ c = (struct i2c_client *) kmalloc(sizeof(*c), GFP_KERNEL); -+ if (!c) -+ return -ENOMEM; -+ -+ strcpy(c->name, "DS1337"); -+ c->id = ds1337_driver.id; -+ c->flags = 0; -+ c->addr = addr; -+ c->adapter = adap; -+ c->driver = &ds1337_driver; -+ c->data = NULL; -+ -+ ret = i2c_transfer(c->adapter, msgs, 2); -+ -+ if (ret == 2) { -+ DAT(c) = buf[0]; -+ } else -+ printk("ds1337_attach(): i2c_transfer() returned %d.\n", ret); -+ -+ ds1337_i2c_client = c; -+ -+ ds1337_readram(buf, DS1337_MEM_SIZE); -+ -+ // set 24 hour mode -+ ds1337_setreg(c, 0x2, buf[2] | DS1337_HOUR24); -+ // INTCN sets INTB to alarm2 (disables SQW) -+ ds1337_setreg(c, 0x5, buf[5] & 0x7f); // clear century -+ ds1337_setreg(c, 0x7, 0x00); // clear Alarm 1 seconds -+ ds1337_setreg(c, 0x8, 0x00); // clear Alarm 1 minutes -+ ds1337_setreg(c, 0x9, 0x40); // clear Alarm 1 hours, 24 hour on -+ ds1337_setreg(c, 0xA, 0x00); // clear Alarm 1 date -+ ds1337_setreg(c, 0xB, 0x00); // clear Alarm 2 minutes -+ ds1337_setreg(c, 0xC, 0x40); // clear Alarm 2 hours, 24 hour on -+ ds1337_setreg(c, 0xD, 0x00); // clear Alarm 2 date -+ ds1337_setreg(c, 0xe, 4); // nEOSC enabled -+ ds1337_setreg(c, 0xf, 0); // clear OSF, A2F, A1F -+ -+ return i2c_attach_client(c); -+} -+ -+ -+static int ds1337_probe(struct i2c_adapter *adap) -+{ -+ if (rtc_debug>1) -+ printk("%s()\n", __FUNCTION__); -+ -+ return i2c_probe(adap, &addr_data, ds1337_attach); -+} -+ -+ -+static int ds1337_detach(struct i2c_client *client) -+{ -+ if (rtc_debug>1) -+ printk("%s()\n", __FUNCTION__); -+ -+ i2c_detach_client(client); -+ -+ return 0; -+} -+ -+ -+static void ds1337_convert_to_time(struct rtc_time *dt, char *buf) -+{ -+ if (rtc_debug>1) -+ printk("%s()\n", __FUNCTION__); -+ -+ dt->tm_sec = BCD_TO_BIN(buf[0]); -+ dt->tm_min = BCD_TO_BIN(buf[1]); -+ dt->tm_hour = DS1337_HOURS_24(buf[2]); -+ -+ dt->tm_mday = BCD_TO_BIN(buf[4]); -+ /* dt->tm_mon is zero-based */ -+ dt->tm_mon = BCD_TO_BIN(buf[5]) - 1; -+ /* year is 1900 + dt->tm_year */ -+ dt->tm_year = BCD_TO_BIN(buf[6]) + 100; -+ -+ if (rtc_debug > 2) { -+ printk("ds1337_get_datetime: year = %d\n", dt->tm_year); -+ printk("ds1337_get_datetime: mon = %d\n", dt->tm_mon); -+ printk("ds1337_get_datetime: mday = %d\n", dt->tm_mday); -+ printk("ds1337_get_datetime: hour = %d\n", dt->tm_hour); -+ printk("ds1337_get_datetime: min = %d\n", dt->tm_min); -+ printk("ds1337_get_datetime: sec = %d\n", dt->tm_sec); -+ } -+} -+ -+ -+static int ds1337_get_datetime(struct i2c_client *client, -+ struct rtc_time *dt) -+{ -+ unsigned char buf[7], addr[1] = { 0 }; -+ struct i2c_msg msgs[2] = { -+ {client->addr, 0, 1, addr}, -+ {client->addr, I2C_M_RD, 7, buf} -+ }; -+ int ret = -EIO; -+ -+ if (rtc_debug) -+ printk("%s()\n", __FUNCTION__); -+ -+ memset(buf, 0, sizeof(buf)); -+ -+ ret = i2c_transfer(client->adapter, msgs, 2); -+ -+ if (ret == 2) { -+ ds1337_convert_to_time(dt, buf); -+ ret = 0; -+ } else -+ printk("ds1337_get_datetime(), i2c_transfer() returned %d\n", ret); -+ -+ return ret; -+} -+ -+ -+static int ds1337_set_datetime(struct i2c_client *client, -+ struct rtc_time *dt, int datetoo) -+{ -+ unsigned char buf[8]; -+ int ret, len = 4; -+ -+ if (rtc_debug) -+ printk("%s()\n", __FUNCTION__); -+ -+ if (rtc_debug > 2) { -+ printk("ds1337_set_datetime: tm_year = %d\n", dt->tm_year); -+ printk("ds1337_set_datetime: tm_mon = %d\n", dt->tm_mon); -+ printk("ds1337_set_datetime: tm_mday = %d\n", dt->tm_mday); -+ printk("ds1337_set_datetime: tm_hour = %d\n", dt->tm_hour); -+ printk("ds1337_set_datetime: tm_min = %d\n", dt->tm_min); -+ printk("ds1337_set_datetime: tm_sec = %d\n", dt->tm_sec); -+ } -+ -+ buf[0] = 0; /* register address on DS1337 */ -+ buf[1] = (BIN_TO_BCD(dt->tm_sec)); -+ buf[2] = (BIN_TO_BCD(dt->tm_min)); -+ buf[3] = (BIN_TO_BCD(dt->tm_hour)) | DS1337_HOUR24; -+ -+ if (datetoo) { -+ len = 8; -+ /* we skip buf[4] as we don't use day-of-week. */ -+ buf[5] = (BIN_TO_BCD(dt->tm_mday)); -+ buf[6] = (BIN_TO_BCD(dt->tm_mon + 1)); -+ /* The year only ranges from 0-99, we are being passed an offset from 1900, -+ * and the chip calulates leap years based on 2000, thus we adjust by 100. -+ */ -+ buf[7] = (BIN_TO_BCD(dt->tm_year - 100)); -+ } -+ ret = i2c_master_send(client, (char *) buf, len); -+ if (ret == len) -+ ret = 0; -+ else -+ printk("ds1337_set_datetime(), i2c_master_send() returned %d\n", -+ ret); -+ -+ -+ return ret; -+} -+ -+ -+#if 0 -+static int ds1337_get_ctrl(struct i2c_client *client, unsigned char *ctrl) -+{ -+ *ctrl = DAT(client); -+ -+ if (rtc_debug) -+ printk("%s():%d\n", __FUNCTION__, *ctrl); -+ -+ return 0; -+} -+ -+ -+static int ds1337_set_ctrl(struct i2c_client *client, unsigned char *cinfo) -+{ -+ unsigned char buf[2]; -+ int ret; -+ -+ if (rtc_debug) -+ printk("%s(%d)\n", __FUNCTION__, *cinfo); -+ -+ buf[0] = 7; /* control register address on DS1337 */ -+ buf[1] = *cinfo; -+ /* save the control reg info in the client data field so that get_ctrl -+ * function doesn't have to do an I2C transfer to get it. -+ */ -+ DAT(client) = buf[1]; -+ -+ ret = i2c_master_send(client, (char *) buf, 2); -+ -+ return ret; -+} -+#endif -+ -+ -+static int ds1337_command(struct i2c_client *client, unsigned int cmd, -+ void *arg) -+{ -+ if (rtc_debug) -+ printk("%s(client,,%u,arg)\n", __FUNCTION__, cmd); -+ -+ switch (cmd) { -+ case DS1337_GETDATETIME: -+ return ds1337_get_datetime(client, arg); -+ -+ case DS1337_SETTIME: -+ return ds1337_set_datetime(client, arg, 0); -+ -+ case DS1337_SETDATETIME: -+ return ds1337_set_datetime(client, arg, 1); -+ -+ default: -+ return -EINVAL; -+ } -+} -+ -+ -+static int ds1337_rtc_noop(struct inode *inode, struct file *file) -+{ -+ return 0; -+} -+ -+ -+static int ds1337_rtc_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ unsigned long flags; -+ struct rtc_time wtime; -+ int status = 0; -+ -+ if (rtc_debug) -+ printk("%s()\n", __FUNCTION__); -+ -+ switch (cmd) { -+ default: -+ case RTC_UIE_ON: // mask ints from RTC updates -+ case RTC_UIE_OFF: -+ case RTC_PIE_ON: // allow periodic interrupts -+ case RTC_PIE_OFF: -+ case RTC_AIE_ON: // mask alarm int enable bit -+ case RTC_AIE_OFF: -+ case RTC_ALM_SET: -+ /* -+ * This expects a struct rtc_time. Writing 0xff means -+ * "don't care" or "match all". Only the tm_hour, -+ * tm_min and tm_sec are used. -+ */ -+ case RTC_ALM_READ: -+ // get_rtc_alm_time(&wtime); -+ case RTC_IRQP_READ: // Read the periodic IRQ rate -+ case RTC_IRQP_SET: // Set periodic IRQ rate -+ case RTC_EPOCH_READ: -+ // return put_user (epoch, (unsigned long *)arg); -+ case RTC_EPOCH_SET: -+ case RTC_WKALM_SET: -+ case RTC_WKALM_RD: -+ status = -EINVAL; -+ break; -+ -+ case RTC_RD_TIME: -+ spin_lock_irqsave(&ds1337_rtc_lock, flags); -+ ds1337_command(ds1337_i2c_client, DS1337_GETDATETIME, &wtime); -+ spin_unlock_irqrestore(&ds1337_rtc_lock, flags); -+ -+ if (copy_to_user((void *) arg, &wtime, sizeof(struct rtc_time))) -+ status = -EFAULT; -+ break; -+ -+ case RTC_SET_TIME: -+ if (!capable(CAP_SYS_TIME)) { -+ status = -EACCES; -+ break; -+ } -+ -+ if (copy_from_user -+ (&wtime, (struct rtc_time *) arg, sizeof(struct rtc_time))) { -+ status = -EFAULT; -+ break; -+ } -+ -+ spin_lock_irqsave(&ds1337_rtc_lock, flags); -+ ds1337_command(ds1337_i2c_client, DS1337_SETDATETIME, &wtime); -+ spin_unlock_irqrestore(&ds1337_rtc_lock, flags); -+ break; -+ } -+ -+ return status; -+} -+ -+ -+static char *ds1337_mon2str(unsigned int mon) -+{ -+ char *mon2str[12] = { -+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", -+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -+ }; -+ if (mon > 11) -+ return "error"; -+ else -+ return mon2str[mon]; -+} -+ -+ -+static int ds1337_rtc_proc_output(char *buf) -+{ -+#define CHECK(ctrl,bit) ((ctrl & bit) ? "yes" : "no") -+ -+ unsigned char ram[DS1337_MEM_SIZE]; -+ int ret; -+ -+ char *p = buf; -+ -+ ret = ds1337_readram(ram, DS1337_MEM_SIZE); -+ if (ret > 0) { -+#ifdef DEBUG -+ int i; -+ char text[9]; -+#endif -+ struct rtc_time dt; -+ -+ p += sprintf(p, "DS1337 (i2c Serial Real Time Clock)\n"); -+ -+ ds1337_convert_to_time(&dt, ram); -+ p += sprintf(p, "Date/Time: %02d-%s-%04d %02d:%02d:%02d\n", -+ dt.tm_mday, ds1337_mon2str(dt.tm_mon), -+ dt.tm_year + 1900, dt.tm_hour, dt.tm_min, dt.tm_sec); -+ -+#ifdef DEBUG -+ p += sprintf(p, "RAM dump:\n"); -+ text[8] = '\0'; -+ for (i = 0; i < DS1337_MEM_SIZE; i++) { -+ if ((i % 8) == 0) -+ p += sprintf(p, "%02X: ", i); -+ p += sprintf(p, "%02X ", ram[i]); -+ -+ if ((ram[i] < 32) || (ram[i] > 126)) -+ ram[i] = '.'; -+ text[i % 8] = ram[i]; -+ if ((i % 8) == 7) -+ p += sprintf(p, "%s\n", text); -+ } -+ p += sprintf(p, "\n"); -+#endif -+ } else { -+ p += sprintf(p, "Failed to read RTC memory!\n"); -+ } -+ -+ return p - buf; -+} -+ -+ -+static int ds1337_rtc_read_proc(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = ds1337_rtc_proc_output(page); -+ -+ if (len <= off + count) -+ *eof = 1; -+ *start = page + off; -+ len -= off; -+ if (len > count) -+ len = count; -+ if (len < 0) -+ len = 0; -+ return len; -+} -+ -+ -+static __init int ds1337_init(void) -+{ -+ int retval = 0; -+ -+ if (rtc_debug>1) -+ printk("%s()\n", __FUNCTION__); -+ -+ if (slave_address != 0xffff) { -+ normal_addr[0] = slave_address; -+ } -+ -+ if (normal_addr[0] == 0xffff) { -+ printk(KERN_ERR -+ "I2C: Invalid slave address for DS1337 RTC (%#x)\n", -+ normal_addr[0]); -+ return -EINVAL; -+ } -+ -+ retval = i2c_add_driver(&ds1337_driver); -+ -+ if (retval == 0) { -+ misc_register(&ds1337_rtc_miscdev); -+ create_proc_read_entry(DS1337_PROC_NAME, 0, 0, -+ ds1337_rtc_read_proc, NULL); -+ printk("I2C: DS1337 RTC driver loaded\n"); -+ } -+ return retval; -+} -+ -+ -+static __exit void ds1337_exit(void) -+{ -+ if (rtc_debug>1) -+ printk("%s()\n", __FUNCTION__); -+ -+ remove_proc_entry(DS1337_PROC_NAME, NULL); -+ misc_deregister(&ds1337_rtc_miscdev); -+ i2c_del_driver(&ds1337_driver); -+} -+ -+ -+module_init(ds1337_init); -+module_exit(ds1337_exit); -+ -+MODULE_PARM(slave_address, "i"); -+MODULE_PARM_DESC(slave_address, "I2C slave address for DS1337 RTC"); -+ -+MODULE_AUTHOR("M&N Logistik-Lösungen Online GmbH"); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ linux-2.4.21/drivers/char/ds1337.h -@@ -0,0 +1,43 @@ -+/* -+ * ds1337.h -+ * -+ * Copyright (C) 2003 M&N Logistik-Lösungen Online GmbH -+ * -+ * 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 DS1337_H -+#define DS1337_H -+ -+#define DS1337_I2C_SLAVE_ADDR 0x68 -+//#define DS1337_RAM_ADDR_START 0x10 -+//#define DS1337_RAM_ADDR_END 0x10 -+#define DS1337_MEM_SIZE 0x10 -+ -+#define DS1337_PROC_NAME "driver/ds1337" -+ -+struct rtc_mem { -+ unsigned int loc; -+ unsigned int nr; -+ unsigned char *data; -+}; -+ -+#define DS1337_GETDATETIME 0 -+#define DS1337_SETTIME 1 -+#define DS1337_SETDATETIME 2 -+ -+#define DS1337_RATE_1HZ 0x00 /* Rate Select 1 Hz */ -+#define DS1337_RATE_4096HZ 0x01 /* Rate Select 4096 kHz */ -+#define DS1337_RATE_8192HZ 0x02 /* Rate Select 8192 kHz */ -+#define DS1337_RATE_32768HZ 0x03 /* Rate Select 32768 kHz */ -+ -+#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10) -+#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10) -+ -+#define DS1337_HOUR12 0x40 -+#define DS1337_HOUR24 0x00 -+#define DS1337_HOURS_24(val) BCD_TO_BIN((val & 0x3f)) -+ -+#endif ---- /dev/null -+++ linux-2.4.21/drivers/char/german.map -@@ -0,0 +1,528 @@ -+keymaps 0-2,4-6,8-10,12 -+keycode 1 = Escape Escape -+ alt keycode 1 = Meta_Escape -+ shift alt keycode 1 = Meta_Escape -+keycode 2 = one exclam -+ alt keycode 2 = Meta_one -+ shift alt keycode 2 = Meta_exclam -+keycode 3 = two quotedbl twosuperior nul -+ alt keycode 3 = Meta_two -+ shift alt keycode 3 = Meta_quotedbl -+ control alt keycode 3 = Meta_nul -+keycode 4 = three section threesuperior Escape -+ alt keycode 4 = Meta_three -+ control alt keycode 4 = Meta_Escape -+keycode 5 = four dollar -+ alt keycode 5 = Meta_four -+ shift alt keycode 5 = Meta_dollar -+keycode 6 = five percent -+ alt keycode 6 = Meta_five -+ shift alt keycode 6 = Meta_percent -+keycode 7 = six ampersand -+ control keycode 7 = Control_asciicircum -+ alt keycode 7 = Meta_six -+ shift alt keycode 7 = Meta_ampersand -+keycode 8 = seven slash braceleft -+ alt keycode 8 = Meta_seven -+ shift alt keycode 8 = Meta_slash -+ altgr alt keycode 8 = Meta_braceleft -+keycode 9 = eight parenleft bracketleft -+ alt keycode 9 = Meta_eight -+ shift alt keycode 9 = Meta_parenleft -+ altgr alt keycode 9 = Meta_bracketleft -+keycode 10 = nine parenright bracketright -+ altgr control keycode 10 = Control_bracketright -+ alt keycode 10 = Meta_nine -+ shift alt keycode 10 = Meta_parenright -+ altgr alt keycode 10 = Meta_bracketright -+keycode 11 = zero equal braceright -+ alt keycode 11 = Meta_zero -+ shift alt keycode 11 = Meta_equal -+ altgr alt keycode 11 = Meta_braceright -+keycode 12 = ssharp question backslash -+ altgr control keycode 12 = Control_backslash -+ shift alt keycode 12 = Meta_question -+ altgr alt keycode 12 = Meta_backslash -+keycode 13 = apostrophe grave -+ alt keycode 13 = 0x08b4 -+ shift alt keycode 13 = Meta_grave -+keycode 14 = BackSpace Delete -+ alt keycode 14 = Meta_BackSpace -+ shift alt keycode 14 = Meta_Delete -+keycode 15 = Tab Tab -+ alt keycode 15 = Meta_Tab -+ shift alt keycode 15 = Meta_Tab -+keycode 16 = +q +Q at Control_q Control_q Control_q Meta_q Meta_Q Meta_at Meta_Control_q -+keycode 17 = w -+keycode 18 = +e +E currency Control_e Control_e Control_e Meta_e Meta_E Meta_e Meta_Control_e -+keycode 19 = r -+keycode 20 = t -+keycode 21 = z -+keycode 22 = u -+keycode 23 = i -+keycode 24 = o -+keycode 25 = p -+keycode 26 = +udiaeresis +Udiaeresis -+keycode 27 = plus asterisk asciitilde -+ alt keycode 27 = Meta_plus -+ shift alt keycode 27 = Meta_asterisk -+keycode 28 = Return -+ alt keycode 28 = Meta_Control_m -+keycode 29 = Control -+keycode 30 = a -+keycode 31 = s -+keycode 32 = d -+keycode 33 = f -+keycode 34 = g -+keycode 35 = h -+keycode 36 = j -+keycode 37 = k -+keycode 38 = l -+keycode 39 = +odiaeresis +Odiaeresis -+keycode 40 = +adiaeresis +Adiaeresis -+keycode 41 = asciicircum degree Meta_asciicircum Control_asciicircum -+ control alt keycode 41 = Meta_Control_asciicircum -+keycode 42 = Shift -+keycode 43 = numbersign apostrophe -+ alt keycode 43 = Meta_numbersign -+ shift alt keycode 43 = Meta_apostrophe -+keycode 44 = y -+keycode 45 = x -+keycode 46 = c -+keycode 47 = v -+keycode 48 = b -+keycode 49 = n -+keycode 50 = +m +M mu Control_m Control_m Control_m Meta_m Meta_M Meta_m Meta_Control_m -+keycode 51 = comma semicolon -+ alt keycode 51 = Meta_comma -+ shift alt keycode 51 = Meta_semicolon -+keycode 52 = period colon -+ alt keycode 52 = Meta_period -+ shift alt keycode 52 = Meta_colon -+keycode 53 = minus underscore Meta_minus -+ shift control keycode 53 = Control_underscore -+ alt keycode 53 = Meta_minus -+ shift alt keycode 53 = Meta_underscore -+keycode 54 = Shift -+keycode 55 = KP_Multiply -+ altgr keycode 55 = Hex_C -+keycode 56 = Alt -+keycode 57 = space space Meta_space nul -+ alt keycode 57 = Meta_space -+ shift alt keycode 57 = Meta_space -+ control alt keycode 57 = Meta_nul -+keycode 58 = Caps_Lock -+keycode 59 = F1 F13 Console_13 F25 -+ altgr control keycode 59 = F1 -+ alt keycode 59 = Console_1 -+ control alt keycode 59 = Console_1 -+keycode 60 = F2 F14 Console_14 F26 -+ altgr control keycode 60 = F2 -+ alt keycode 60 = Console_2 -+ control alt keycode 60 = Console_2 -+keycode 61 = F3 F15 Console_15 F27 -+ altgr control keycode 61 = F3 -+ alt keycode 61 = Console_3 -+ control alt keycode 61 = Console_3 -+keycode 62 = F4 F16 Console_16 F28 -+ altgr control keycode 62 = F4 -+ alt keycode 62 = Console_4 -+ control alt keycode 62 = Console_4 -+keycode 63 = F5 F17 Console_17 F29 -+ altgr control keycode 63 = F5 -+ alt keycode 63 = Console_5 -+ control alt keycode 63 = Console_5 -+keycode 64 = F6 F18 Console_18 F30 -+ altgr control keycode 64 = F6 -+ alt keycode 64 = Console_6 -+ control alt keycode 64 = Console_6 -+keycode 65 = F7 F19 Console_19 F31 -+ altgr control keycode 65 = F7 -+ alt keycode 65 = Console_7 -+ control alt keycode 65 = Console_7 -+keycode 66 = F8 F20 Console_20 F32 -+ altgr control keycode 66 = F8 -+ alt keycode 66 = Console_8 -+ control alt keycode 66 = Console_8 -+keycode 67 = F9 F21 Console_21 F33 -+ altgr control keycode 67 = F9 -+ alt keycode 67 = Console_9 -+ control alt keycode 67 = Console_9 -+keycode 68 = F10 F22 Console_22 F34 -+ altgr control keycode 68 = F10 -+ alt keycode 68 = Console_10 -+ control alt keycode 68 = Console_10 -+keycode 69 = Num_Lock -+ altgr keycode 69 = Hex_A -+keycode 70 = Scroll_Lock Show_Memory Show_Registers Show_State -+ alt keycode 70 = Scroll_Lock -+keycode 71 = KP_7 -+ altgr keycode 71 = Hex_7 -+ alt keycode 71 = Ascii_7 -+keycode 72 = KP_8 -+ altgr keycode 72 = Hex_8 -+ alt keycode 72 = Ascii_8 -+keycode 73 = KP_9 -+ altgr keycode 73 = Hex_9 -+ alt keycode 73 = Ascii_9 -+keycode 74 = KP_Subtract -+ altgr keycode 74 = Hex_D -+keycode 75 = KP_4 -+ altgr keycode 75 = Hex_4 -+ alt keycode 75 = Ascii_4 -+keycode 76 = KP_5 -+ altgr keycode 76 = Hex_5 -+ alt keycode 76 = Ascii_5 -+keycode 77 = KP_6 -+ altgr keycode 77 = Hex_6 -+ alt keycode 77 = Ascii_6 -+keycode 78 = KP_Add -+ altgr keycode 78 = Hex_E -+keycode 79 = KP_1 -+ altgr keycode 79 = Hex_1 -+ alt keycode 79 = Ascii_1 -+keycode 80 = KP_2 -+ altgr keycode 80 = Hex_2 -+ alt keycode 80 = Ascii_2 -+keycode 81 = KP_3 -+ altgr keycode 81 = Hex_3 -+ alt keycode 81 = Ascii_3 -+keycode 82 = KP_0 -+ altgr keycode 82 = Hex_0 -+ alt keycode 82 = Ascii_0 -+keycode 83 = KP_Comma -+ altgr control keycode 83 = Boot -+ control alt keycode 83 = Boot -+#keycode 84 = Last_Console -+keycode 85 = -+keycode 86 = less greater bar -+ alt keycode 86 = Meta_less -+ shift alt keycode 86 = Meta_greater -+ altgr alt keycode 86 = Meta_bar -+keycode 87 = F11 F23 Console_23 F35 -+ altgr control keycode 87 = F11 -+ alt keycode 87 = Console_11 -+ control alt keycode 87 = Console_11 -+keycode 88 = F12 F24 Console_24 F36 -+ altgr control keycode 88 = F12 -+ alt keycode 88 = Console_12 -+ control alt keycode 88 = Console_12 -+keycode 89 = slash question degree -+ alt keycode 89 = Meta_slash -+ shift alt keycode 89 = Meta_question -+keycode 90 = -+keycode 91 = -+keycode 92 = -+keycode 93 = -+keycode 94 = -+keycode 95 = -+keycode 96 = KP_Enter -+ altgr keycode 96 = Hex_F -+keycode 97 = Control -+keycode 98 = KP_Divide -+ altgr keycode 98 = Hex_B -+keycode 99 = Compose -+keycode 100 = AltGr -+ alt keycode 100 = Compose -+keycode 101 = Break -+keycode 102 = Find -+keycode 103 = Up -+ alt keycode 103 = KeyboardSignal -+keycode 104 = Prior -+ shift keycode 104 = Scroll_Backward -+keycode 105 = Left -+# alt keycode 105 = Decr_Console -+keycode 106 = Right -+# alt keycode 106 = Incr_Console -+keycode 107 = Select -+keycode 108 = Down -+keycode 109 = Next -+ shift keycode 109 = Scroll_Forward -+keycode 110 = Insert -+keycode 111 = Remove -+ altgr control keycode 111 = Boot -+ control alt keycode 111 = Boot -+keycode 112 = Macro -+ shift alt keycode 112 = VoidSymbol -+ altgr alt keycode 112 = VoidSymbol -+keycode 113 = F13 -+ shift alt keycode 113 = VoidSymbol -+ altgr alt keycode 113 = VoidSymbol -+keycode 114 = F14 -+ shift alt keycode 114 = VoidSymbol -+ altgr alt keycode 114 = VoidSymbol -+keycode 115 = Help -+ shift alt keycode 115 = VoidSymbol -+ altgr alt keycode 115 = VoidSymbol -+keycode 116 = Do -+ shift alt keycode 116 = VoidSymbol -+ altgr alt keycode 116 = VoidSymbol -+keycode 117 = F17 -+ shift alt keycode 117 = VoidSymbol -+ altgr alt keycode 117 = VoidSymbol -+keycode 118 = KP_MinPlus -+ shift alt keycode 118 = VoidSymbol -+ altgr alt keycode 118 = VoidSymbol -+keycode 119 = Pause -+keycode 120 = -+keycode 121 = -+keycode 122 = -+keycode 123 = -+keycode 124 = -+#keycode 125 = Decr_Console -+#keycode 126 = Incr_Console -+keycode 127 = Compose -+string F1 = "\033[[A" -+string F2 = "\033[[B" -+string F3 = "\033[[C" -+string F4 = "\033[[D" -+string F5 = "\033[[E" -+string F6 = "\033[17~" -+string F7 = "\033[18~" -+string F8 = "\033[19~" -+string F9 = "\033[20~" -+string F10 = "\033[21~" -+string F11 = "\033[23~" -+string F12 = "\033[24~" -+string F13 = "\033[25~" -+string F14 = "\033[26~" -+string F15 = "\033[28~" -+string F16 = "\033[29~" -+string F17 = "\033[31~" -+string F18 = "\033[32~" -+string F19 = "\033[33~" -+string F20 = "\033[34~" -+string Find = "\033[1~" -+string Insert = "\033[2~" -+string Remove = "\033[3~" -+string Select = "\033[4~" -+string Prior = "\033[5~" -+string Next = "\033[6~" -+string Macro = "\033[M" -+string Pause = "\033[P" -+compose '!' '!' to '¡' -+compose '"' 'A' to 'Ä' -+compose '"' 'E' to 'Ë' -+compose '"' 'I' to 'Ï' -+compose '"' 'O' to 'Ö' -+compose '"' 'U' to 'Ü' -+compose '"' 'Y' to '¾' -+compose '"' 'a' to 'ä' -+compose '"' 'c' to '©' -+compose '"' 'e' to 'ë' -+compose '"' 'i' to 'ï' -+compose '"' 'o' to 'ö' -+compose '"' 'r' to '®' -+compose '"' 'u' to 'ü' -+compose '"' 'y' to 'ÿ' -+compose '(' 'c' to '©' -+compose '(' 'r' to '®' -+compose '+' '-' to '±' -+compose ',' 'A' to '¡' -+compose ',' 'C' to 'Ç' -+compose ',' 'E' to 'Ê' -+compose ',' 'G' to '«' -+compose ',' 'I' to 'Ç' -+compose ',' 'K' to 'Ó' -+compose ',' 'L' to '¦' -+compose ',' 'N' to 'Ñ' -+compose ',' 'R' to '£' -+compose ',' 'S' to 'ª' -+compose ',' 'T' to 'Þ' -+compose ',' 'U' to 'Ù' -+compose ',' 'a' to '±' -+compose ',' 'c' to 'ç' -+compose ',' 'e' to 'ê' -+compose ',' 'g' to '»' -+compose ',' 'i' to 'ç' -+compose ',' 'k' to 'ó' -+compose ',' 'l' to '¶' -+compose ',' 'n' to 'ñ' -+compose ',' 'r' to '³' -+compose ',' 's' to 'º' -+compose ',' 't' to 'þ' -+compose ',' 'u' to 'ù' -+compose '-' ':' to '÷' -+compose '-' 'A' to 'ª' -+compose '-' 'C' to '¢' -+compose '-' 'D' to 'Ð' -+compose '-' 'E' to '¤' -+compose '-' 'H' to '¡' -+compose '-' 'L' to '£' -+compose '-' 'O' to 'º' -+compose '-' 'T' to '¬' -+compose '-' 'Y' to '¥' -+compose '-' 'a' to 'ª' -+compose '-' 'c' to '¢' -+compose '-' 'd' to 'ð' -+compose '-' 'e' to '¤' -+compose '-' 'h' to '±' -+compose '-' 'l' to '£' -+compose '-' 'l' to '¥' -+compose '-' 'l' to '³' -+compose '-' 'o' to 'º' -+compose '-' 't' to '¼' -+compose '.' '.' to '·' -+compose '.' 'C' to 'Å' -+compose '.' 'C' to 'Õ' -+compose '.' 'E' to 'Ì' -+compose '.' 'I' to '©' -+compose '.' 'Z' to '¯' -+compose '.' 'c' to 'å' -+compose '.' 'c' to 'õ' -+compose '.' 'e' to 'ì' -+compose '.' 'i' to '¹' -+compose '.' 'z' to '¿' -+compose '/' 'D' to 'Ð' -+compose '/' 'L' to '£' -+compose '/' 'O' to 'Ø' -+compose '/' 'T' to '¬' -+compose '/' 'c' to '¢' -+compose '/' 'd' to 'ð' -+compose '/' 'l' to '³' -+compose '/' 'o' to 'ø' -+compose '/' 't' to '¼' -+compose '0' 'A' to 'Å' -+compose '0' 'U' to 'Ù' -+compose '0' 'a' to 'å' -+compose '0' 'u' to 'ù' -+compose '1' '2' to '½' -+compose '1' '4' to '¼' -+compose '3' '4' to '¾' -+compose ':' '-' to '÷' -+compose ':' 'A' to 'Ä' -+compose ':' 'E' to 'Ë' -+compose ':' 'O' to 'Ö' -+compose ':' 'U' to 'Ü' -+compose ':' 'a' to 'ä' -+compose ':' 'e' to 'ë' -+compose ':' 'o' to 'ö' -+compose ':' 'u' to 'ü' -+compose '<' '<' to '«' -+compose '>' '>' to '»' -+compose '?' '?' to '¿' -+compose 'A' 'A' to 'Å' -+compose 'A' 'E' to 'Æ' -+compose 'I' 'J' to '¾' -+compose 'L' '=' to '£' -+compose 'N' 'G' to '½' -+compose 'N' 'H' to 'Ñ' -+compose 'N' 'N' to 'Ñ' -+compose 'N' 'Y' to 'Ñ' -+compose 'N' 'h' to 'Ñ' -+compose 'N' 'n' to 'Ñ' -+compose 'N' 'y' to 'Ñ' -+compose 'O' 'A' to 'Å' -+compose 'O' 'E' to '¼' -+compose 'O' 'e' to '¼' -+compose 'T' 'H' to 'Þ' -+compose 'U' 'U' to 'Ù' -+compose 'Y' '=' to '¥' -+compose '\'' 'A' to 'Á' -+compose '\'' 'C' to 'Æ' -+compose '\'' 'E' to 'É' -+compose '\'' 'I' to 'Í' -+compose '\'' 'L' to 'Å' -+compose '\'' 'N' to 'Ñ' -+compose '\'' 'O' to 'Ó' -+compose '\'' 'R' to 'À' -+compose '\'' 'S' to '¦' -+compose '\'' 'U' to 'Ú' -+compose '\'' 'Y' to 'Ý' -+compose '\'' 'Z' to '¬' -+compose '\'' 'a' to 'á' -+compose '\'' 'c' to 'æ' -+compose '\'' 'e' to 'é' -+compose '\'' 'i' to 'í' -+compose '\'' 'l' to 'å' -+compose '\'' 'n' to 'ñ' -+compose '\'' 'o' to 'ó' -+compose '\'' 'r' to 'à' -+compose '\'' 's' to '¶' -+compose '\'' 'u' to 'ú' -+compose '\'' 'y' to 'ý' -+compose '\'' 'z' to '¼' -+compose '^' '!' to '¡' -+compose '^' '*' to '×' -+compose '^' '.' to '·' -+compose '^' '/' to '÷' -+compose '^' '1' to '¹' -+compose '^' '2' to '²' -+compose '^' '3' to '³' -+compose '^' ':' to '÷' -+compose '^' '?' to '¿' -+compose '^' 'A' to 'Â' -+compose '^' 'C' to 'Ç' -+compose '^' 'D' to 'Ð' -+compose '^' 'E' to 'Ê' -+compose '^' 'G' to 'Ô' -+compose '^' 'H' to '¦' -+compose '^' 'I' to 'Î' -+compose '^' 'J' to '¬' -+compose '^' 'L' to '¥' -+compose '^' 'N' to 'Ñ' -+compose '^' 'R' to 'Ø' -+compose '^' 'S' to '¦' -+compose '^' 'T' to '«' -+compose '^' 'U' to 'Û' -+compose '^' 'Z' to '´' -+compose '^' 'a' to 'â' -+compose '^' 'c' to 'ç' -+compose '^' 'd' to 'ð' -+compose '^' 'e' to 'ê' -+compose '^' 'g' to 'ø' -+compose '^' 'h' to '¶' -+compose '^' 'i' to 'î' -+compose '^' 'j' to '¼' -+compose '^' 'l' to 'µ' -+compose '^' 'n' to 'ñ' -+compose '^' 'o' to 'ô' -+compose '^' 'r' to 'ø' -+compose '^' 's' to '¨' -+compose '^' 't' to '»' -+compose '^' 'u' to 'û' -+compose '^' 'x' to '×' -+compose '^' 'z' to '¸' -+compose '`' 'A' to 'À' -+compose '`' 'E' to 'È' -+compose '`' 'I' to 'Ì' -+compose '`' 'O' to 'Ò' -+compose '`' 'U' to 'Ù' -+compose '`' 'a' to 'à' -+compose '`' 'e' to 'è' -+compose '`' 'i' to 'ì' -+compose '`' 'o' to 'ò' -+compose '`' 'u' to 'ù' -+compose 'a' 'a' to 'å' -+compose 'a' 'e' to 'æ' -+compose 'c' '/' to '¢' -+compose 'c' '=' to '¢' -+compose 'e' '=' to '¤' -+compose 'i' 'j' to 'ÿ' -+compose 'm' 'u' to 'µ' -+compose 'n' 'g' to '¿' -+compose 'n' 'h' to 'ñ' -+compose 'n' 'n' to 'ñ' -+compose 'o' 'a' to 'å' -+compose 'o' 'e' to '½' -+compose 's' 's' to 'ß' -+compose 's' 'z' to 'ß' -+compose 't' 'h' to 'þ' -+compose 'u' 'u' to 'ù' -+compose 'v' 'S' to '¦' -+compose 'v' 'Z' to '´' -+compose 'v' 's' to '¨' -+compose 'v' 'z' to '¸' -+compose 'x' 'x' to '×' -+compose '~' 'A' to 'Ã' -+compose '~' 'G' to '«' -+compose '~' 'I' to '¥' -+compose '~' 'N' to 'Ñ' -+compose '~' 'O' to 'Õ' -+compose '~' 'U' to 'Ý' -+compose '~' 'a' to 'ã' -+compose '~' 'g' to '»' -+compose '~' 'i' to 'µ' -+compose '~' 'n' to 'ñ' -+compose '~' 'o' to 'õ' -+compose '~' 'u' to 'ý' ---- /dev/null -+++ linux-2.4.21/drivers/char/input_keyb.c -@@ -0,0 +1,167 @@ -+/* -+ * linux/drivers/char/input_keyb.c by Russ Dill -+ * taken from pc_keyb.c -+ * -+ * This code grabs keypresses from the input layer and makes them -+ * available to the console. -+ * -+ * 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 -+ -+/* Simple translation table for the SysRq keys */ -+ -+unsigned char input_sysrq_xlate[128] = -+ "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ -+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ -+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ -+ "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ -+ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ -+ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ -+ "\r\000/"; /* 0x60 - 0x6f */ -+ -+/* -+ * Translation of escaped scancodes to keycodes. -+ * This is now user-settable. -+ * The keycodes 1-88,96-111,119 are fairly standard, and -+ * should probably not be changed - changing might confuse X. -+ * X also interprets scancode 0x5d (KEY_Begin). -+ * -+ * For 1-88 keycode equals scancode. -+ */ -+ -+#define E0_KPENTER 96 -+#define E0_RCTRL 97 -+#define E0_KPSLASH 98 -+#define E0_PRSCR 99 -+#define E0_RALT 100 -+#define E0_BREAK 101 /* (control-pause) */ -+#define E0_HOME 102 -+#define E0_UP 103 -+#define E0_PGUP 104 -+#define E0_LEFT 105 -+#define E0_RIGHT 106 -+#define E0_END 107 -+#define E0_DOWN 108 -+#define E0_PGDN 109 -+#define E0_INS 110 -+#define E0_DEL 111 -+ -+#define E1_PAUSE 119 -+ -+/* -+ * New microsoft keyboard is rumoured to have -+ * e0 5b (left window button), e0 5c (right window button), -+ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU] -+ * [or: Windows_L, Windows_R, TaskMan] -+ */ -+#define E0_MSLW 125 -+ -+static unsigned char e0_keys[128] = { -+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */ -+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */ -+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */ -+ 0, 0, 0, 0, 0, E0_RCTRL, 0, 0, /* 0x18-0x1f */ -+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */ -+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */ -+ 0, 0, 0, 0, 0, 0, 0, E0_PRSCR, /* 0x30-0x37 */ -+ E0_RALT, 0, 0, 0, 0, 0, 0, 0, /* 0x38-0x3f */ -+ 0, 0, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */ -+ E0_UP, E0_PGUP, 0, E0_LEFT, 0, E0_RIGHT, 0, E0_END, /* 0x48-0x4f */ -+ E0_DOWN, E0_PGDN, 0, 0, 0, 0, 0, 0, /* 0x50-0x57 */ -+ 0, 0, 0, E0_MSLW, 0, 0, 0, 0, /* 0x58-0x5f */ -+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ -+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x68-0x6f */ -+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */ -+ 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */ -+}; -+ -+int input_setkeycode(unsigned int scancode, unsigned int keycode) -+{ -+ if (scancode > 255 || keycode > 127) return -EINVAL; -+ e0_keys[scancode - 128] = keycode; -+ return 0; -+} -+ -+int input_getkeycode(unsigned int scancode) -+{ -+ return scancode > 255 ? -EINVAL : e0_keys[scancode - 128]; -+} -+ -+#define KBD_REPORT_UNKN -+int input_translate(unsigned char scancode, unsigned char *keycode, -+ char raw_mode) -+{ -+ static int prev_scancode; -+ -+ /* special prefix scancodes.. */ -+ if (scancode == 0xe0 || scancode == 0xe1) { -+ prev_scancode = scancode; -+ return 0; -+ } -+ if (prev_scancode) { -+ /* -+ * usually it will be 0xe0, but a Pause key generates -+ * e1 1d 45 e1 9d c5 when pressed, and nothing when released -+ */ -+ if (prev_scancode != 0xe0) { -+ if (prev_scancode == 0xe1 && scancode == 0x1d) { -+ prev_scancode = 0x100; -+ return 0; -+ } else if (prev_scancode == 0x100 && scancode == 0x45) { -+ *keycode = E1_PAUSE; -+ prev_scancode = 0; -+ } else { -+#ifdef KBD_REPORT_UNKN -+ if (!raw_mode) -+ printk(KERN_INFO "keyboard: unknown e1 escape sequence\n"); -+#endif -+ prev_scancode = 0; -+ return 0; -+ } -+ } else { -+ prev_scancode = 0; -+ -+ if (e0_keys[scancode]) -+ *keycode = e0_keys[scancode]; -+ else { -+#ifdef KBD_REPORT_UNKN -+ if (!raw_mode) -+ printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n", -+ scancode); -+#endif -+ return 0; -+ } -+ } -+ } else -+ *keycode = scancode; -+ return 1; -+} -+ -+char input_unexpected_up(unsigned char keycode) -+{ -+ return 0200; -+} -+ -+/* Allow for loadable keyboard drivers */ -+EXPORT_SYMBOL(input_setkeycode); -+EXPORT_SYMBOL(input_unexpected_up); -+EXPORT_SYMBOL(input_translate); -+EXPORT_SYMBOL(input_sysrq_xlate); -+EXPORT_SYMBOL(input_getkeycode); -+EXPORT_SYMBOL(k_setkeycode); -+EXPORT_SYMBOL(k_unexpected_up); -+EXPORT_SYMBOL(k_translate); -+EXPORT_SYMBOL(k_getkeycode); -+#ifdef CONFIG_MAGIC_SYSRQ -+EXPORT_SYMBOL(k_sysrq_key); -+EXPORT_SYMBOL(k_sysrq_xlate); -+#endif ---- linux-2.4.21/drivers/char/keyboard.c~wedge -+++ linux-2.4.21/drivers/char/keyboard.c -@@ -77,6 +77,7 @@ - void (*kbd_ledfunc)(unsigned int led); - EXPORT_SYMBOL(handle_scancode); - EXPORT_SYMBOL(kbd_ledfunc); -+EXPORT_SYMBOL(key_maps); - EXPORT_SYMBOL(kbd_refresh_leds); - - extern void ctrl_alt_del(void); ---- linux-2.4.21/drivers/char/serial.c~ramses-serial -+++ linux-2.4.21/drivers/char/serial.c -@@ -1,138 +1,8 @@ --/* -- * linux/drivers/char/serial.c -- * -- * Copyright (C) 1991, 1992 Linus Torvalds -- * Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, -- * 1998, 1999 Theodore Ts'o -- * -- * Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92. Now -- * much more extensible to support other serial cards based on the -- * 16450/16550A UART's. Added support for the AST FourPort and the -- * Accent Async board. -- * -- * set_serial_info fixed to set the flags, custom divisor, and uart -- * type fields. Fix suggested by Michael K. Johnson 12/12/92. -- * -- * 11/95: TIOCMIWAIT, TIOCGICOUNT by Angelo Haritsis -- * -- * 03/96: Modularised by Angelo Haritsis -- * -- * rs_set_termios fixed to look also for changes of the input -- * flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK. -- * Bernd Anhäupl 05/17/96. -- * -- * 1/97: Extended dumb serial ports are a config option now. -- * Saves 4k. Michael A. Griffith -- * -- * 8/97: Fix bug in rs_set_termios with RTS -- * Stanislav V. Voronyi -- * -- * 3/98: Change the IRQ detection, use of probe_irq_o*(), -- * suppress TIOCSERGWILD and TIOCSERSWILD -- * Etienne Lorrain -- * -- * 4/98: Added changes to support the ARM architecture proposed by -- * Russell King -- * -- * 5/99: Updated to include support for the XR16C850 and ST16C654 -- * uarts. Stuart MacDonald -- * -- * 8/99: Generalized PCI support added. Theodore Ts'o -- * -- * 3/00: Rid circular buffer of redundant xmit_cnt. Fix a -- * few races on freeing buffers too. -- * Alan Modra -- * -- * 5/00: Support for the RSA-DV II/S card added. -- * Kiyokazu SUTO -- * -- * 6/00: Remove old-style timer, use timer_list -- * Andrew Morton -- * -- * 7/00: Support Timedia/Sunix/Exsys PCI cards -- * -- * 7/00: fix some returns on failure not using MOD_DEC_USE_COUNT. -- * Arnaldo Carvalho de Melo -- * -- * 10/00: add in optional software flow control for serial console. -- * Kanoj Sarcar (Modified by Theodore Ts'o) -- * -- * 02/02: Fix for AMD Elan bug in transmit irq routine, by -- * Christer Weinigel , -- * Robert Schwebel , -- * Juergen Beisert , -- * Theodore Ts'o -- */ -- --static char *serial_version = "5.05c"; --static char *serial_revdate = "2001-07-08"; -- --/* -- * Serial driver configuration section. Here are the various options: -- * -- * CONFIG_HUB6 -- * Enables support for the venerable Bell Technologies -- * HUB6 card. -- * -- * CONFIG_SERIAL_MANY_PORTS -- * Enables support for ports beyond the standard, stupid -- * COM 1/2/3/4. -- * -- * CONFIG_SERIAL_MULTIPORT -- * Enables support for special multiport board support. -- * -- * CONFIG_SERIAL_SHARE_IRQ -- * Enables support for multiple serial ports on one IRQ -- * -- * CONFIG_SERIAL_DETECT_IRQ -- * Enable the autodetection of IRQ on standart ports -- * -- * SERIAL_PARANOIA_CHECK -- * Check the magic number for the async_structure where -- * ever possible. -- * -- * CONFIG_SERIAL_ACPI -- * Enable support for serial console port and serial -- * debug port as defined by the SPCR and DBGP tables in -- * ACPI 2.0. -- */ -+#undef DEBUG - - #include - #include - --#undef SERIAL_PARANOIA_CHECK --#define CONFIG_SERIAL_NOPAUSE_IO --#define SERIAL_DO_RESTART -- --#if 0 --/* These defines are normally controlled by the autoconf.h */ --#define CONFIG_SERIAL_MANY_PORTS --#define CONFIG_SERIAL_SHARE_IRQ --#define CONFIG_SERIAL_DETECT_IRQ --#define CONFIG_SERIAL_MULTIPORT --#define CONFIG_HUB6 --#endif -- --#ifdef CONFIG_PCI --#define ENABLE_SERIAL_PCI --#ifndef CONFIG_SERIAL_SHARE_IRQ --#define CONFIG_SERIAL_SHARE_IRQ --#endif --#ifndef CONFIG_SERIAL_MANY_PORTS --#define CONFIG_SERIAL_MANY_PORTS --#endif --#endif -- --#ifdef CONFIG_SERIAL_ACPI --#define ENABLE_SERIAL_ACPI --#endif -- --#if defined(CONFIG_ISAPNP)|| (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE)) --#ifndef ENABLE_SERIAL_PNP --#define ENABLE_SERIAL_PNP --#endif --#endif -- - #ifdef CONFIG_ARCH_PXA - #define pxa_port(x) ((x) == PORT_PXA) - #define pxa_buggy_port(x) ({ \ -@@ -149,39 +19,16 @@ - #undef SERIAL_DEBUG_OPEN - #undef SERIAL_DEBUG_FLOW - #undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT --#undef SERIAL_DEBUG_PCI --#undef SERIAL_DEBUG_AUTOCONF - - /* Sanity checks */ - --#ifdef CONFIG_SERIAL_MULTIPORT --#ifndef CONFIG_SERIAL_SHARE_IRQ --#define CONFIG_SERIAL_SHARE_IRQ --#endif --#endif -- --#ifdef CONFIG_HUB6 --#ifndef CONFIG_SERIAL_MANY_PORTS --#define CONFIG_SERIAL_MANY_PORTS --#endif --#ifndef CONFIG_SERIAL_SHARE_IRQ --#define CONFIG_SERIAL_SHARE_IRQ --#endif --#endif -- - #ifdef MODULE - #undef CONFIG_SERIAL_CONSOLE - #endif - --#define CONFIG_SERIAL_RSA -- - #define RS_STROBE_TIME (10*HZ) - #define RS_ISR_PASS_LIMIT 256 - --#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) --#define SERIAL_INLINE --#endif -- - /* - * End of serial driver configuration section. - */ -@@ -213,53 +60,51 @@ - #include - #include - #include --#if (LINUX_VERSION_CODE >= 131343) - #include --#endif --#if (LINUX_VERSION_CODE >= 131336) - #include --#endif - #include - #ifdef CONFIG_SERIAL_CONSOLE - #include - #endif --#ifdef ENABLE_SERIAL_PCI --#include --#endif --#ifdef ENABLE_SERIAL_PNP --#include --#endif - #ifdef CONFIG_MAGIC_SYSRQ - #include - #endif - --/* -- * All of the compatibilty code so we can compile serial.c against -- * older kernels is hidden in serial_compat.h -- */ --#if defined(LOCAL_HEADERS) || (LINUX_VERSION_CODE < 0x020317) /* 2.3.23 */ --#include "serial_compat.h" --#endif -- - #include - #include - #include - #include - --#if defined(CONFIG_MAC_SERIAL) --#define SERIAL_DEV_OFFSET ((_machine == _MACH_prep || _machine == _MACH_chrp) ? 0 : 2) --#else --#define SERIAL_DEV_OFFSET 0 --#endif -+#define _INLINE_ - --#ifdef SERIAL_INLINE --#define _INLINE_ inline -+/* -+ * The TI16754 has 4 UARTS. They are selected with nCS3 and some -+ * address bits: -+ * -+ * 12 8 4 -+ * nA8, nCS[3] for MN_UART_1, address mask 1110 1110 0000 0000 = 0xEE00 -+ * nA9, nCS[3] for MN_UART_1, address mask 1110 1101 0000 0000 = 0xED00 -+ * nA10, nCS[3] for MN_UART_1, address mask 1110 1011 0000 0000 = 0xEB00 -+ * nA11, nCS[3] for MN_UART_1, address mask 1110 0111 0000 0000 = 0xE700 -+ */ -+#define RAMSES_UARTA_PHYS (PXA_CS3_PHYS+0xEE00) -+#define RAMSES_UARTB_PHYS (PXA_CS3_PHYS+0xED00) -+#define RAMSES_UARTC_PHYS (PXA_CS3_PHYS+0xEB00) -+#define RAMSES_UARTD_PHYS (PXA_CS3_PHYS+0xE700) -+static void *ramses_uarta; // address cookie for UART A -+static void *ramses_uartb; // address cookie for UART B -+static void *ramses_uartc; // address cookie for UART C/Scanner -+static void *ramses_uartd; // address cookie for UART D -+static int ramses_stay_on = 0; -+ -+#ifdef DEBUG -+#define DPRINTK(fmt,args...) printk("//HS " fmt, ## args) -+static int show_io = 1; - #else --#define _INLINE_ -+#define DPRINTK(fmt,args...) -+static int show_io = 0; - #endif - --static char *serial_name = "Serial driver"; -- - static DECLARE_TASK_QUEUE(tq_serial); - - static struct tty_driver serial_driver, callout_driver; -@@ -282,9 +127,6 @@ - */ - - static struct async_struct *IRQ_ports[NR_IRQS]; --#ifdef CONFIG_SERIAL_MULTIPORT --static struct rs_multiport_struct rs_multiport[NR_IRQS]; --#endif - static int IRQ_timeout[NR_IRQS]; - #ifdef CONFIG_SERIAL_CONSOLE - static struct console sercons; -@@ -294,8 +136,6 @@ - static unsigned long break_pressed; /* break, really ... */ - #endif - --static unsigned detect_uart_irq (struct serial_state * state); --static void autoconfig(struct serial_state * state); - static void change_speed(struct async_struct *info, struct termios *old); - static void rs_wait_until_sent(struct tty_struct *tty, int timeout); - -@@ -325,46 +165,74 @@ - { 0, 0} - }; - --#if defined(CONFIG_SERIAL_RSA) && defined(MODULE) -- --#define PORT_RSA_MAX 4 --static int probe_rsa[PORT_RSA_MAX]; --static int force_rsa[PORT_RSA_MAX]; -- --MODULE_PARM(probe_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i"); --MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); --MODULE_PARM(force_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i"); --MODULE_PARM_DESC(force_rsa, "Force I/O ports for RSA"); --#endif /* CONFIG_SERIAL_RSA */ -- --struct serial_state rs_table[RS_TABLE_SIZE] = { -- SERIAL_PORT_DFNS /* Defined in serial.h */ -+static struct serial_state rs_table[] = { -+ { -+ type: PORT_PXA, -+ xmit_fifo_size: 32, -+ baud_base: 921600, -+ iomem_base: (void *)&FFUART, -+ iomem_reg_shift: 2, -+ io_type: SERIAL_IO_MEM32, -+ irq: IRQ_FFUART, -+ flags: ASYNC_SKIP_TEST, -+ }, { -+ type: PORT_PXA, -+ xmit_fifo_size: 32, -+ baud_base: 921600, -+ iomem_base: (void *)&BTUART, -+ iomem_reg_shift: 2, -+ io_type: SERIAL_IO_MEM32, -+ irq: IRQ_BTUART, -+ flags: ASYNC_SKIP_TEST, -+ }, { -+ type: PORT_PXA, -+ xmit_fifo_size: 32, -+ baud_base: 921600, -+ iomem_base: (void *)&STUART, -+ iomem_reg_shift: 2, -+ io_type: SERIAL_IO_MEM32, -+ irq: IRQ_STUART, -+ flags: ASYNC_SKIP_TEST, -+ }, { -+ type: PORT_16750, -+ xmit_fifo_size: 64, -+ baud_base: 115200*2, -+ iomem_base: (void *)0, -+ iomem_reg_shift: 2, -+ io_type: SERIAL_IO_MEM, -+ irq: IRQ_GPIO(7), -+ flags: ASYNC_SKIP_TEST, -+ }, { -+ type: PORT_16750, -+ xmit_fifo_size: 64, -+ baud_base: 115200*2, -+ iomem_base: (void *)0, -+ iomem_reg_shift: 2, -+ io_type: SERIAL_IO_MEM, -+ irq: IRQ_GPIO(24), -+ flags: ASYNC_SKIP_TEST, -+ }, { -+ type: PORT_16750, -+ xmit_fifo_size: 64, -+ baud_base: 115200*2, -+ iomem_base: (void *)0, -+ iomem_reg_shift: 2, -+ io_type: SERIAL_IO_MEM, -+ irq: IRQ_GPIO(25), -+ flags: ASYNC_SKIP_TEST, -+ }, { -+ type: PORT_16750, -+ xmit_fifo_size: 64, -+ baud_base: 115200*2, -+ iomem_base: (void *)0, -+ iomem_reg_shift: 2, -+ io_type: SERIAL_IO_MEM, -+ irq: IRQ_GPIO(26), -+ flags: ASYNC_SKIP_TEST, -+ } - }; - - #define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state)) --int serial_nr_ports = NR_PORTS; -- --#if (defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP)) --#define NR_PCI_BOARDS 8 -- --static struct pci_board_inst serial_pci_board[NR_PCI_BOARDS]; -- --#ifndef IS_PCI_REGION_IOPORT --#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \ -- IORESOURCE_IO) --#endif --#ifndef IS_PCI_REGION_IOMEM --#define IS_PCI_REGION_IOMEM(dev, r) (pci_resource_flags((dev), (r)) & \ -- IORESOURCE_MEM) --#endif --#ifndef PCI_IRQ_RESOURCE --#define PCI_IRQ_RESOURCE(dev, r) ((dev)->irq_resource[r].start) --#endif --#ifndef pci_get_subvendor --#define pci_get_subvendor(dev) ((dev)->subsystem_vendor) --#define pci_get_subdevice(dev) ((dev)->subsystem_device) --#endif --#endif /* ENABLE_SERIAL_PCI || ENABLE_SERIAL_PNP */ - - #ifndef PREPARE_FUNC - #define PREPARE_FUNC(dev) (dev->prepare) -@@ -403,39 +271,21 @@ - #endif - - --static inline int serial_paranoia_check(struct async_struct *info, -- kdev_t device, const char *routine) --{ --#ifdef SERIAL_PARANOIA_CHECK -- static const char *badmagic = -- "Warning: bad magic number for serial struct (%s) in %s\n"; -- static const char *badinfo = -- "Warning: null async_struct for (%s) in %s\n"; -- -- if (!info) { -- printk(badinfo, kdevname(device), routine); -- return 1; -- } -- if (info->magic != SERIAL_MAGIC) { -- printk(badmagic, kdevname(device), routine); -- return 1; -- } --#endif -- return 0; --} -- - static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset) - { -+ unsigned int value; - switch (info->io_type) { --#ifdef CONFIG_HUB6 -- case SERIAL_IO_HUB6: -- outb(info->hub6 - 1 + offset, info->port); -- return inb(info->port+1); --#endif - case SERIAL_IO_MEM: -- return readb((unsigned long) info->iomem_base + -+ value = readb((unsigned long) info->iomem_base + - (offset<iomem_reg_shift)); -+ udelay(10); -+ if (show_io) printk("in %02x = %02x\n", offset, value); -+ return value; - case SERIAL_IO_MEM32: -+ value = readl((unsigned long) info->iomem_base + -+ (offset<iomem_reg_shift)); -+ if (show_io) printk("in %02x = %02x\n", offset, value); -+ return value; - return readl((unsigned long) info->iomem_base + - (offset<iomem_reg_shift)); - default: -@@ -447,17 +297,14 @@ - int value) - { - switch (info->io_type) { --#ifdef CONFIG_HUB6 -- case SERIAL_IO_HUB6: -- outb(info->hub6 - 1 + offset, info->port); -- outb(value, info->port+1); -- break; --#endif - case SERIAL_IO_MEM: -+ if (show_io) printk("out %02x, %02x\n", offset, value); - writeb(value, (unsigned long) info->iomem_base + - (offset<iomem_reg_shift)); -+ udelay(10); - break; - case SERIAL_IO_MEM32: -+ if (show_io) printk("out %02x, %02x\n", offset, value); - writel(value, (unsigned long) info->iomem_base + - (offset<iomem_reg_shift)); - break; -@@ -509,9 +356,6 @@ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - -- if (serial_paranoia_check(info, tty->device, "rs_stop")) -- return; -- - save_flags(flags); cli(); - if (info->IER & UART_IER_THRI) { - info->IER &= ~UART_IER_THRI; -@@ -529,9 +373,6 @@ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - -- if (serial_paranoia_check(info, tty->device, "rs_start")) -- return; -- - save_flags(flags); cli(); - if (info->xmit.head != info->xmit.tail - && info->xmit.buf -@@ -689,11 +530,7 @@ - #endif - *status = serial_inp(info, UART_LSR); - } while ((*status & UART_LSR_DR) && (max_count-- > 0)); --#if (LINUX_VERSION_CODE > 131394) /* 2.1.66 */ - tty_flip_buffer_push(tty); --#else -- queue_task_irq_off(&tty->flip.tqueue, &tq_timer); --#endif - } - - static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) -@@ -758,11 +595,6 @@ - icount->dsr++; - if (status & UART_MSR_DDCD) { - icount->dcd++; --#ifdef CONFIG_HARD_PPS -- if ((info->flags & ASYNC_HARDPPS_CD) && -- (status & UART_MSR_DCD)) -- hardpps(); --#endif - } - if (status & UART_MSR_DCTS) - icount->cts++; -@@ -810,120 +642,23 @@ - } - } - --#ifdef CONFIG_SERIAL_SHARE_IRQ --/* -- * This is the serial driver's generic interrupt routine -- */ --static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) --{ -- int status, iir; -- struct async_struct * info; -- int pass_counter = 0; -- struct async_struct *end_mark = 0; --#ifdef CONFIG_SERIAL_MULTIPORT -- int first_multi = 0; -- struct rs_multiport_struct *multi; --#endif -- --#ifdef SERIAL_DEBUG_INTR -- printk("rs_interrupt(%d)...", irq); --#endif -- -- info = IRQ_ports[irq]; -- if (!info) -- return; -- --#ifdef CONFIG_SERIAL_MULTIPORT -- multi = &rs_multiport[irq]; -- if (multi->port_monitor) -- first_multi = inb(multi->port_monitor); --#endif -- -- do { -- if (!info->tty || -- ((iir=serial_in(info, UART_IIR)) & UART_IIR_NO_INT)) { -- if (!end_mark) -- end_mark = info; -- goto next; -- } --#ifdef SERIAL_DEBUG_INTR -- printk("IIR = %x...", serial_in(info, UART_IIR)); --#endif -- end_mark = 0; -- -- info->last_active = jiffies; -- -- status = serial_inp(info, UART_LSR); --#ifdef SERIAL_DEBUG_INTR -- printk("status = %x...", status); --#endif -- if (status & UART_LSR_DR) -- receive_chars(info, &status, regs); -- check_modem_status(info); --#ifdef CONFIG_MELAN -- if ((status & UART_LSR_THRE) || -- /* for buggy ELAN processors */ -- ((iir & UART_IIR_ID) == UART_IIR_THRI)) -- transmit_chars(info, 0); --#else -- if (status & UART_LSR_THRE) -- transmit_chars(info, 0); --#endif -- -- next: -- info = info->next_port; -- if (!info) { -- info = IRQ_ports[irq]; -- if (pass_counter++ > RS_ISR_PASS_LIMIT) { --#if 0 -- printk("rs loop break\n"); --#endif -- break; /* Prevent infinite loops */ -- } -- continue; -- } -- } while (end_mark != info); --#ifdef CONFIG_SERIAL_MULTIPORT -- if (multi->port_monitor) -- printk("rs port monitor (normal) irq %d: 0x%x, 0x%x\n", -- info->state->irq, first_multi, -- inb(multi->port_monitor)); --#endif --#ifdef SERIAL_DEBUG_INTR -- printk("end.\n"); --#endif --} --#endif /* #ifdef CONFIG_SERIAL_SHARE_IRQ */ -- - - /* - * This is the serial driver's interrupt routine for a single port - */ - static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) - { -- int status, iir; -+ int status; - int pass_counter = 0; - struct async_struct * info; --#ifdef CONFIG_SERIAL_MULTIPORT -- int first_multi = 0; -- struct rs_multiport_struct *multi; --#endif - - #ifdef SERIAL_DEBUG_INTR - printk("rs_interrupt_single(%d)...", irq); - #endif -- - info = IRQ_ports[irq]; - if (!info || !info->tty) - return; - --#ifdef CONFIG_SERIAL_MULTIPORT -- multi = &rs_multiport[irq]; -- if (multi->port_monitor) -- first_multi = inb(multi->port_monitor); --#endif -- -- iir = serial_in(info, UART_IIR); - do { - status = serial_inp(info, UART_LSR); - #ifdef SERIAL_DEBUG_INTR -@@ -932,120 +667,23 @@ - if (status & UART_LSR_DR) - receive_chars(info, &status, regs); - check_modem_status(info); -- if ((status & UART_LSR_THRE) || -- /* For buggy ELAN processors */ -- ((iir & UART_IIR_ID) == UART_IIR_THRI)) -+ if (status & UART_LSR_THRE) - transmit_chars(info, 0); - if (pass_counter++ > RS_ISR_PASS_LIMIT) { --#if SERIAL_DEBUG_INTR -+#if 0 - printk("rs_single loop break.\n"); - #endif - break; - } -- iir = serial_in(info, UART_IIR); --#ifdef SERIAL_DEBUG_INTR -- printk("IIR = %x...", iir); --#endif -- } while ((iir & UART_IIR_NO_INT) == 0); -- info->last_active = jiffies; --#ifdef CONFIG_SERIAL_MULTIPORT -- if (multi->port_monitor) -- printk("rs port monitor (single) irq %d: 0x%x, 0x%x\n", -- info->state->irq, first_multi, -- inb(multi->port_monitor)); --#endif --#ifdef SERIAL_DEBUG_INTR -- printk("end.\n"); --#endif --} -- --#ifdef CONFIG_SERIAL_MULTIPORT --/* -- * This is the serial driver's for multiport boards -- */ --static void rs_interrupt_multi(int irq, void *dev_id, struct pt_regs * regs) --{ -- int status; -- struct async_struct * info; -- int pass_counter = 0; -- int first_multi= 0; -- struct rs_multiport_struct *multi; -- - #ifdef SERIAL_DEBUG_INTR -- printk("rs_interrupt_multi(%d)...", irq); -+ printk("IIR = %x...", serial_in(info, UART_IIR)); - #endif -- -- info = IRQ_ports[irq]; -- if (!info) -- return; -- multi = &rs_multiport[irq]; -- if (!multi->port1) { -- /* Should never happen */ -- printk("rs_interrupt_multi: NULL port1!\n"); -- return; -- } -- if (multi->port_monitor) -- first_multi = inb(multi->port_monitor); -- -- while (1) { -- if (!info->tty || -- (serial_in(info, UART_IIR) & UART_IIR_NO_INT)) -- goto next; -- -+ } while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT)); - info->last_active = jiffies; -- -- status = serial_inp(info, UART_LSR); --#ifdef SERIAL_DEBUG_INTR -- printk("status = %x...", status); --#endif -- if (status & UART_LSR_DR) -- receive_chars(info, &status, regs); -- check_modem_status(info); -- if (status & UART_LSR_THRE) -- transmit_chars(info, 0); -- -- next: -- info = info->next_port; -- if (info) -- continue; -- -- info = IRQ_ports[irq]; -- /* -- * The user was a bonehead, and misconfigured their -- * multiport info. Rather than lock up the kernel -- * in an infinite loop, if we loop too many times, -- * print a message and break out of the loop. -- */ -- if (pass_counter++ > RS_ISR_PASS_LIMIT) { -- printk("Misconfigured multiport serial info " -- "for irq %d. Breaking out irq loop\n", irq); -- break; -- } -- if (multi->port_monitor) -- printk("rs port monitor irq %d: 0x%x, 0x%x\n", -- info->state->irq, first_multi, -- inb(multi->port_monitor)); -- if ((inb(multi->port1) & multi->mask1) != multi->match1) -- continue; -- if (!multi->port2) -- break; -- if ((inb(multi->port2) & multi->mask2) != multi->match2) -- continue; -- if (!multi->port3) -- break; -- if ((inb(multi->port3) & multi->mask3) != multi->match3) -- continue; -- if (!multi->port4) -- break; -- if ((inb(multi->port4) & multi->mask4) != multi->match4) -- continue; -- break; -- } - #ifdef SERIAL_DEBUG_INTR - printk("end.\n"); - #endif - } --#endif - - /* - * ------------------------------------------------------------------- -@@ -1107,22 +745,6 @@ - if (!info) - continue; - save_flags(flags); cli(); --#ifdef CONFIG_SERIAL_SHARE_IRQ -- if (info->next_port) { -- do { -- serial_out(info, UART_IER, 0); -- info->IER |= UART_IER_THRI; -- serial_out(info, UART_IER, info->IER); -- info = info->next_port; -- } while (info); --#ifdef CONFIG_SERIAL_MULTIPORT -- if (rs_multiport[i].port1) -- rs_interrupt_multi(i, NULL, NULL); -- else --#endif -- rs_interrupt(i, NULL, NULL); -- } else --#endif /* CONFIG_SERIAL_SHARE_IRQ */ - rs_interrupt_single(i, NULL, NULL); - restore_flags(flags); - } -@@ -1132,11 +754,7 @@ - - if (IRQ_ports[0]) { - save_flags(flags); cli(); --#ifdef CONFIG_SERIAL_SHARE_IRQ -- rs_interrupt(0, NULL, NULL); --#else - rs_interrupt_single(0, NULL, NULL); --#endif - restore_flags(flags); - - mod_timer(&serial_timer, jiffies + IRQ_timeout[0]); -@@ -1177,50 +795,6 @@ - IRQ_timeout[irq] = (timeout > 3) ? timeout-2 : 1; - } - --#ifdef CONFIG_SERIAL_RSA --/* Attempts to turn on the RSA FIFO. Returns zero on failure */ --static int enable_rsa(struct async_struct *info) --{ -- unsigned char mode; -- int result; -- unsigned long flags; -- -- save_flags(flags); cli(); -- mode = serial_inp(info, UART_RSA_MSR); -- result = mode & UART_RSA_MSR_FIFO; -- -- if (!result) { -- serial_outp(info, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); -- mode = serial_inp(info, UART_RSA_MSR); -- result = mode & UART_RSA_MSR_FIFO; -- } -- -- restore_flags(flags); -- return result; --} -- --/* Attempts to turn off the RSA FIFO. Returns zero on failure */ --static int disable_rsa(struct async_struct *info) --{ -- unsigned char mode; -- int result; -- unsigned long flags; -- -- save_flags(flags); cli(); -- mode = serial_inp(info, UART_RSA_MSR); -- result = !(mode & UART_RSA_MSR_FIFO); -- -- if (!result) { -- serial_outp(info, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); -- mode = serial_inp(info, UART_RSA_MSR); -- result = !(mode & UART_RSA_MSR_FIFO); -- } -- -- restore_flags(flags); -- return result; --} --#endif /* CONFIG_SERIAL_RSA */ -- - static int startup(struct async_struct * info) - { - unsigned long flags; -@@ -1228,9 +802,6 @@ - void (*handler)(int, void *, struct pt_regs *); - struct serial_state *state= info->state; - unsigned long page; --#ifdef CONFIG_SERIAL_MANY_PORTS -- unsigned short ICP; --#endif - - page = get_zeroed_page(GFP_KERNEL); - if (!page) -@@ -1258,6 +829,22 @@ - printk("starting up ttys%d (irq %d)...", info->line, state->irq); - #endif - -+ // Special handling to give power to devices -+ switch (info->line) { -+ case 3: -+ //printk("gsm on\n"); -+ RAMSES_GSM_ON(); -+ break; -+ case 4: -+ //printk("uart on\n"); -+ RAMSES_UART_ON(); -+ break; -+ case 5: -+ //printk("scanner on\n"); -+ RAMSES_SCANNER_ON(); -+ break; -+ } -+ - if (uart_config[state->type].flags & UART_STARTECH) { - /* Wake up UART */ - serial_outp(info, UART_LCR, 0xBF); -@@ -1305,25 +892,12 @@ - serial_outp(info, UART_LCR, 0); - } - --#ifdef CONFIG_SERIAL_RSA -- /* -- * If this is an RSA port, see if we can kick it up to the -- * higher speed clock. -- */ -- if (state->type == PORT_RSA) { -- if (state->baud_base != SERIAL_RSA_BAUD_BASE && -- enable_rsa(info)) -- state->baud_base = SERIAL_RSA_BAUD_BASE; -- if (state->baud_base == SERIAL_RSA_BAUD_BASE) -- serial_outp(info, UART_RSA_FRR, 0); -- } --#endif -- - #ifdef CONFIG_ARCH_PXA - if (state->type == PORT_PXA) { - switch ((long)state->iomem_base) { - case (long)&FFUART: CKEN |= CKEN6_FFUART; break; - case (long)&BTUART: CKEN |= CKEN7_BTUART; break; -+ //HS TODO: cerf keeps the clock on - case (long)&STUART: CKEN |= CKEN5_STUART; break; - } - } -@@ -1344,6 +918,7 @@ - /* - * Clear the interrupt registers. - */ -+ (void) serial_inp(info, UART_IIR); - (void) serial_inp(info, UART_LSR); - (void) serial_inp(info, UART_RX); - (void) serial_inp(info, UART_IIR); -@@ -1371,18 +946,8 @@ - if (state->irq && (!IRQ_ports[state->irq] || - !IRQ_ports[state->irq]->next_port)) { - if (IRQ_ports[state->irq]) { --#ifdef CONFIG_SERIAL_SHARE_IRQ -- free_irq(state->irq, &IRQ_ports[state->irq]); --#ifdef CONFIG_SERIAL_MULTIPORT -- if (rs_multiport[state->irq].port1) -- handler = rs_interrupt_multi; -- else --#endif -- handler = rs_interrupt; --#else - retval = -EBUSY; - goto errout; --#endif /* CONFIG_SERIAL_SHARE_IRQ */ - } else - handler = rs_interrupt_single; - -@@ -1417,12 +982,6 @@ - info->MCR = 0; - if (info->tty->termios->c_cflag & CBAUD) - info->MCR = UART_MCR_DTR | UART_MCR_RTS; --#ifdef CONFIG_SERIAL_MANY_PORTS -- if (info->flags & ASYNC_FOURPORT) { -- if (state->irq == 0) -- info->MCR |= UART_MCR_OUT1; -- } else --#endif - { - if (state->irq != 0) - info->MCR |= UART_MCR_OUT2; -@@ -1437,18 +996,9 @@ - */ - info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; - if (pxa_port(state->type)) -- info->IER |= UART_IER_UUE | UART_IER_RTOIE; -+ info->IER |= UART_IER_UUE | UART_IER_RTOIE; //HS TODO: UART_IER_THRI for PXA uarts? - serial_outp(info, UART_IER, info->IER); /* enable interrupts */ - --#ifdef CONFIG_SERIAL_MANY_PORTS -- if (info->flags & ASYNC_FOURPORT) { -- /* Enable interrupts on the AST Fourport board */ -- ICP = (info->port & 0xFE0) | 0x01F; -- outb_p(0x80, ICP); -- (void) inb_p(ICP); -- } --#endif -- - /* - * And clear the interrupt registers again for luck. - */ -@@ -1469,7 +1019,6 @@ - /* - * Set up the tty->alt_speed kludge - */ --#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */ - if (info->tty) { - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; -@@ -1480,7 +1029,6 @@ - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - } --#endif - - /* - * and set the speed of the serial port -@@ -1516,6 +1064,30 @@ - state->irq); - #endif - -+ switch (info->line) { -+ case 3: -+ if (ramses_stay_on & RAMSES_CONTROL_GSM_PWR) { -+ //printk("gsm on\n"); -+ RAMSES_GSM_OFF(); -+ } -+ //else printk("gsm stays on\n"); -+ break; -+ case 4: -+ if (ramses_stay_on & RAMSES_CONTROL_UART_PWR) { -+ //printk("uart off\n"); -+ RAMSES_UART_OFF(); -+ } -+ //else printk("uart stays on\n"); -+ break; -+ case 5: -+ if (ramses_stay_on & RAMSES_CONTROL_SCANNER_PWR) { -+ //printk("scanner off\n"); -+ RAMSES_SCANNER_OFF(); -+ } -+ //else printk("scanner on\n"); -+ break; -+ } -+ - save_flags(flags); cli(); /* Disable interrupts */ - - /* -@@ -1561,13 +1133,6 @@ - - info->IER = 0; - serial_outp(info, UART_IER, 0x00); /* disable all intrs */ --#ifdef CONFIG_SERIAL_MANY_PORTS -- if (info->flags & ASYNC_FOURPORT) { -- /* reset interrupts on the AST Fourport board */ -- (void) inb((info->port & 0xFE0) | 0x01F); -- info->MCR |= UART_MCR_OUT1; -- } else --#endif - info->MCR &= ~UART_MCR_OUT2; - if (pxa_buggy_port(state->type)) - info->MCR ^= UART_MCR_OUT2; -@@ -1586,16 +1151,6 @@ - UART_FCR_CLEAR_XMIT)); - serial_outp(info, UART_FCR, 0); - --#ifdef CONFIG_SERIAL_RSA -- /* -- * Reset the RSA board back to 115kbps compat mode. -- */ -- if ((state->type == PORT_RSA) && -- (state->baud_base == SERIAL_RSA_BAUD_BASE && -- disable_rsa(info))) -- state->baud_base = SERIAL_RSA_BAUD_BASE_LO; --#endif -- - #ifdef CONFIG_ARCH_PXA - if (state->type == PORT_PXA - #ifdef CONFIG_SERIAL_CONSOLE -@@ -1634,37 +1189,6 @@ - restore_flags(flags); - } - --#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */ --static int baud_table[] = { -- 0, 50, 75, 110, 134, 150, 200, 300, -- 600, 1200, 1800, 2400, 4800, 9600, 19200, -- 38400, 57600, 115200, 230400, 460800, 0 }; -- --static int tty_get_baud_rate(struct tty_struct *tty) --{ -- struct async_struct * info = (struct async_struct *)tty->driver_data; -- unsigned int cflag, i; -- -- cflag = tty->termios->c_cflag; -- -- i = cflag & CBAUD; -- if (i & CBAUDEX) { -- i &= ~CBAUDEX; -- if (i < 1 || i > 2) -- tty->termios->c_cflag &= ~CBAUDEX; -- else -- i += 15; -- } -- if (i == 15) { -- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) -- i += 1; -- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) -- i += 2; -- } -- return baud_table[i]; --} --#endif -- - /* - * This routine is called to set the UART divisor registers to match - * the specified baud rate for a serial port. -@@ -1711,12 +1235,6 @@ - baud = tty_get_baud_rate(info->tty); - if (!baud) - baud = 9600; /* B0 transition handled in rs_set_termios */ --#ifdef CONFIG_SERIAL_RSA -- if ((info->state->type == PORT_RSA) && -- (info->state->baud_base != SERIAL_RSA_BAUD_BASE) && -- enable_rsa(info)) -- info->state->baud_base = SERIAL_RSA_BAUD_BASE; --#endif - baud_base = info->state->baud_base; - if (info->state->type == PORT_16C950) { - if (baud <= baud_base) -@@ -1778,10 +1296,6 @@ - if (uart_config[info->state->type].flags & UART_USE_FIFO) { - if ((info->state->baud_base / quot) < 2400) - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; --#ifdef CONFIG_SERIAL_RSA -- else if (info->state->type == PORT_RSA) -- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14; --#endif - else - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; - } -@@ -1864,9 +1378,6 @@ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - -- if (serial_paranoia_check(info, tty->device, "rs_put_char")) -- return; -- - if (!tty || !info->xmit.buf) - return; - -@@ -1888,9 +1399,6 @@ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - -- if (serial_paranoia_check(info, tty->device, "rs_flush_chars")) -- return; -- - if (info->xmit.head == info->xmit.tail - || tty->stopped - || tty->hw_stopped -@@ -1900,8 +1408,6 @@ - save_flags(flags); cli(); - info->IER |= UART_IER_THRI; - serial_out(info, UART_IER, info->IER); -- if (pxa_buggy_port(info->state->type)) -- rs_interrupt_single(info->state->irq, NULL, NULL); - restore_flags(flags); - } - -@@ -1912,9 +1418,6 @@ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - -- if (serial_paranoia_check(info, tty->device, "rs_write")) -- return 0; -- - if (!tty || !info->xmit.buf || !tmp_buf) - return 0; - -@@ -1978,11 +1481,6 @@ - && !(info->IER & UART_IER_THRI)) { - info->IER |= UART_IER_THRI; - serial_out(info, UART_IER, info->IER); -- if (pxa_buggy_port(info->state->type)) { -- save_flags(flags); cli(); -- rs_interrupt_single(info->state->irq, NULL, NULL); -- restore_flags(flags); -- } - } - return ret; - } -@@ -1991,8 +1489,6 @@ - { - struct async_struct *info = (struct async_struct *)tty->driver_data; - -- if (serial_paranoia_check(info, tty->device, "rs_write_room")) -- return 0; - return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); - } - -@@ -2000,8 +1496,6 @@ - { - struct async_struct *info = (struct async_struct *)tty->driver_data; - -- if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer")) -- return 0; - return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); - } - -@@ -2010,8 +1504,6 @@ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - -- if (serial_paranoia_check(info, tty->device, "rs_flush_buffer")) -- return; - save_flags(flags); cli(); - info->xmit.head = info->xmit.tail = 0; - restore_flags(flags); -@@ -2032,16 +1524,11 @@ - { - struct async_struct *info = (struct async_struct *)tty->driver_data; - -- if (serial_paranoia_check(info, tty->device, "rs_send_char")) -- return; -- - info->x_char = ch; - if (ch) { - /* Make sure transmit interrupts are on */ - info->IER |= UART_IER_THRI; - serial_out(info, UART_IER, info->IER); -- if (pxa_buggy_port(info->state->type)) -- rs_interrupt_single(info->state->irq, NULL, NULL); - } - } - -@@ -2064,9 +1551,6 @@ - tty->ldisc.chars_in_buffer(tty)); - #endif - -- if (serial_paranoia_check(info, tty->device, "rs_throttle")) -- return; -- - if (I_IXOFF(tty)) - rs_send_xchar(tty, STOP_CHAR(tty)); - -@@ -2089,9 +1573,6 @@ - tty->ldisc.chars_in_buffer(tty)); - #endif - -- if (serial_paranoia_check(info, tty->device, "rs_unthrottle")) -- return; -- - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; -@@ -2134,7 +1615,6 @@ - tmp.close_delay = state->close_delay; - tmp.closing_wait = state->closing_wait; - tmp.custom_divisor = state->custom_divisor; -- tmp.hub6 = state->hub6; - tmp.io_type = state->io_type; - if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) - return -EFAULT; -@@ -2160,8 +1640,7 @@ - new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; - - change_irq = new_serial.irq != state->irq; -- change_port = (new_port != ((int) state->port)) || -- (new_serial.hub6 != state->hub6); -+ change_port = (new_port != ((int) state->port)); - - if (!capable(CAP_SYS_ADMIN)) { - if (change_irq || change_port || -@@ -2198,7 +1677,6 @@ - if (new_serial.type) { - for (i = 0 ; i < NR_PORTS; i++) - if ((state != &rs_table[i]) && -- (rs_table[i].io_type == SERIAL_IO_PORT) && - (rs_table[i].port == new_port) && - rs_table[i].type) - return -EADDRINUSE; -@@ -2220,18 +1698,11 @@ - state->custom_divisor = new_serial.custom_divisor; - state->close_delay = new_serial.close_delay * HZ/100; - state->closing_wait = new_serial.closing_wait * HZ/100; --#if (LINUX_VERSION_CODE > 0x20100) - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; --#endif - info->xmit_fifo_size = state->xmit_fifo_size = - new_serial.xmit_fifo_size; - - if ((state->type != PORT_UNKNOWN) && state->port) { --#ifdef CONFIG_SERIAL_RSA -- if (old_state.type == PORT_RSA) -- release_region(state->port + UART_RSA_BASE, 16); -- else --#endif - release_region(state->port,8); - } - state->type = new_serial.type; -@@ -2243,31 +1714,19 @@ - shutdown(info); - state->irq = new_serial.irq; - info->port = state->port = new_port; -- info->hub6 = state->hub6 = new_serial.hub6; -- if (info->hub6) -- info->io_type = state->io_type = SERIAL_IO_HUB6; -- else if (info->io_type == SERIAL_IO_HUB6) -- info->io_type = state->io_type = SERIAL_IO_PORT; - } - if ((state->type != PORT_UNKNOWN) && state->port) { --#ifdef CONFIG_SERIAL_RSA -- if (state->type == PORT_RSA) -- request_region(state->port + UART_RSA_BASE, -- 16, "serial_rsa(set)"); -- else --#endif - request_region(state->port,8,"serial(set)"); - } - - - check_and_exit: -- if ((!state->port && !state->iomem_base) || !state->type) -+ if (!state->port || !state->type) - return 0; - if (info->flags & ASYNC_INITIALIZED) { - if (((old_state.flags & ASYNC_SPD_MASK) != - (state->flags & ASYNC_SPD_MASK)) || - (old_state.custom_divisor != state->custom_divisor)) { --#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */ - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) -@@ -2276,7 +1735,6 @@ - info->tty->alt_speed = 230400; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; --#endif - change_speed(info, 0); - } - } else -@@ -2414,60 +1872,14 @@ - return 0; - } - --static int do_autoconfig(struct async_struct * info) --{ -- int irq, retval; -- -- if (!capable(CAP_SYS_ADMIN)) -- return -EPERM; -- -- if (info->state->count > 1) -- return -EBUSY; -- -- shutdown(info); -- -- autoconfig(info->state); -- if ((info->state->flags & ASYNC_AUTO_IRQ) && -- (info->state->port != 0 || info->state->iomem_base != 0) && -- (info->state->type != PORT_UNKNOWN)) { -- irq = detect_uart_irq(info->state); -- if (irq > 0) -- info->state->irq = irq; -- } -- -- retval = startup(info); -- if (retval) -- return retval; -- return 0; --} -- - /* - * rs_break() --- routine which turns the break handling on or off - */ --#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */ --static void send_break( struct async_struct * info, int duration) --{ -- if (!CONFIGURED_SERIAL_PORT(info)) -- return; -- current->state = TASK_INTERRUPTIBLE; -- current->timeout = jiffies + duration; -- cli(); -- info->LCR |= UART_LCR_SBC; -- serial_out(info, UART_LCR, info->LCR); -- schedule(); -- info->LCR &= ~UART_LCR_SBC; -- serial_out(info, UART_LCR, info->LCR); -- sti(); --} --#else - static void rs_break(struct tty_struct *tty, int break_state) - { - struct async_struct * info = (struct async_struct *)tty->driver_data; - unsigned long flags; - -- if (serial_paranoia_check(info, tty->device, "rs_break")) -- return; -- - if (!CONFIGURED_SERIAL_PORT(info)) - return; - save_flags(flags); cli(); -@@ -2478,121 +1890,6 @@ - serial_out(info, UART_LCR, info->LCR); - restore_flags(flags); - } --#endif -- --#ifdef CONFIG_SERIAL_MULTIPORT --static int get_multiport_struct(struct async_struct * info, -- struct serial_multiport_struct *retinfo) --{ -- struct serial_multiport_struct ret; -- struct rs_multiport_struct *multi; -- -- multi = &rs_multiport[info->state->irq]; -- -- ret.port_monitor = multi->port_monitor; -- -- ret.port1 = multi->port1; -- ret.mask1 = multi->mask1; -- ret.match1 = multi->match1; -- -- ret.port2 = multi->port2; -- ret.mask2 = multi->mask2; -- ret.match2 = multi->match2; -- -- ret.port3 = multi->port3; -- ret.mask3 = multi->mask3; -- ret.match3 = multi->match3; -- -- ret.port4 = multi->port4; -- ret.mask4 = multi->mask4; -- ret.match4 = multi->match4; -- -- ret.irq = info->state->irq; -- -- if (copy_to_user(retinfo,&ret,sizeof(*retinfo))) -- return -EFAULT; -- return 0; --} -- --static int set_multiport_struct(struct async_struct * info, -- struct serial_multiport_struct *in_multi) --{ -- struct serial_multiport_struct new_multi; -- struct rs_multiport_struct *multi; -- struct serial_state *state; -- int was_multi, now_multi; -- int retval; -- void (*handler)(int, void *, struct pt_regs *); -- -- if (!capable(CAP_SYS_ADMIN)) -- return -EPERM; -- state = info->state; -- -- if (copy_from_user(&new_multi, in_multi, -- sizeof(struct serial_multiport_struct))) -- return -EFAULT; -- -- if (new_multi.irq != state->irq || state->irq == 0 || -- !IRQ_ports[state->irq]) -- return -EINVAL; -- -- multi = &rs_multiport[state->irq]; -- was_multi = (multi->port1 != 0); -- -- multi->port_monitor = new_multi.port_monitor; -- -- if (multi->port1) -- release_region(multi->port1,1); -- multi->port1 = new_multi.port1; -- multi->mask1 = new_multi.mask1; -- multi->match1 = new_multi.match1; -- if (multi->port1) -- request_region(multi->port1,1,"serial(multiport1)"); -- -- if (multi->port2) -- release_region(multi->port2,1); -- multi->port2 = new_multi.port2; -- multi->mask2 = new_multi.mask2; -- multi->match2 = new_multi.match2; -- if (multi->port2) -- request_region(multi->port2,1,"serial(multiport2)"); -- -- if (multi->port3) -- release_region(multi->port3,1); -- multi->port3 = new_multi.port3; -- multi->mask3 = new_multi.mask3; -- multi->match3 = new_multi.match3; -- if (multi->port3) -- request_region(multi->port3,1,"serial(multiport3)"); -- -- if (multi->port4) -- release_region(multi->port4,1); -- multi->port4 = new_multi.port4; -- multi->mask4 = new_multi.mask4; -- multi->match4 = new_multi.match4; -- if (multi->port4) -- request_region(multi->port4,1,"serial(multiport4)"); -- -- now_multi = (multi->port1 != 0); -- -- if (IRQ_ports[state->irq]->next_port && -- (was_multi != now_multi)) { -- free_irq(state->irq, &IRQ_ports[state->irq]); -- if (now_multi) -- handler = rs_interrupt_multi; -- else -- handler = rs_interrupt; -- -- retval = request_irq(state->irq, handler, SA_SHIRQ, -- "serial", &IRQ_ports[state->irq]); -- if (retval) { -- printk("Couldn't reallocate serial interrupt " -- "driver!!\n"); -- } -- } -- return 0; --} --#endif - - static int rs_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg) -@@ -2601,12 +1898,6 @@ - struct async_icount cprev, cnow; /* kernel counter temps */ - struct serial_icounter_struct icount; - unsigned long flags; --#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */ -- int retval, tmp; --#endif -- -- if (serial_paranoia_check(info, tty->device, "rs_ioctl")) -- return -ENODEV; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && -@@ -2616,45 +1907,6 @@ - } - - switch (cmd) { --#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */ -- case TCSBRK: /* SVID version: non-zero arg --> no break */ -- retval = tty_check_change(tty); -- if (retval) -- return retval; -- tty_wait_until_sent(tty, 0); -- if (signal_pending(current)) -- return -EINTR; -- if (!arg) { -- send_break(info, HZ/4); /* 1/4 second */ -- if (signal_pending(current)) -- return -EINTR; -- } -- return 0; -- case TCSBRKP: /* support for POSIX tcsendbreak() */ -- retval = tty_check_change(tty); -- if (retval) -- return retval; -- tty_wait_until_sent(tty, 0); -- if (signal_pending(current)) -- return -EINTR; -- send_break(info, arg ? arg*(HZ/10) : HZ/4); -- if (signal_pending(current)) -- return -EINTR; -- return 0; -- case TIOCGSOFTCAR: -- tmp = C_CLOCAL(tty) ? 1 : 0; -- if (copy_to_user((void *)arg, &tmp, sizeof(int))) -- return -EFAULT; -- return 0; -- case TIOCSSOFTCAR: -- if (copy_from_user(&tmp, (void *)arg, sizeof(int))) -- return -EFAULT; -- -- tty->termios->c_cflag = -- ((tty->termios->c_cflag & ~CLOCAL) | -- (tmp ? CLOCAL : 0)); -- return 0; --#endif - case TIOCMGET: - return get_modem_info(info, (unsigned int *) arg); - case TIOCMBIS: -@@ -2667,9 +1919,6 @@ - case TIOCSSERIAL: - return set_serial_info(info, - (struct serial_struct *) arg); -- case TIOCSERCONFIG: -- return do_autoconfig(info); -- - case TIOCSERGETLSR: /* Get line status register */ - return get_lsr_info(info, (unsigned int *) arg); - -@@ -2679,15 +1928,6 @@ - return -EFAULT; - return 0; - --#ifdef CONFIG_SERIAL_MULTIPORT -- case TIOCSERGETMULTI: -- return get_multiport_struct(info, -- (struct serial_multiport_struct *) arg); -- case TIOCSERSETMULTI: -- return set_multiport_struct(info, -- (struct serial_multiport_struct *) arg); --#endif -- - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest -@@ -2754,6 +1994,39 @@ - printk ("TIOCSER?WILD ioctl obsolete, ignored.\n"); - return 0; - -+ case TIOCSERSETMULTI: -+ switch (arg) { -+ -+ // switch devices on -+ case 2: RAMSES_LCD_BLIGHT_ON(); break; -+ case 3: RAMSES_GSM_ON(); break; -+ case 4: RAMSES_UART_ON(); break; -+ case 5: RAMSES_SCANNER_ON(); break; -+ case 7: RAMSES_SCANNER_WAKE_ON(); break; -+ case 8: RAMSES_SCANNER_TRIG_ON(); break; -+ case 9: RAMSES_GSM_RESET_ON(); break; -+ -+ // switch devices off -+ case 12: RAMSES_LCD_BLIGHT_OFF(); break; -+ case 13: RAMSES_GSM_OFF(); break; -+ case 14: RAMSES_UART_OFF(); break; -+ case 15: RAMSES_SCANNER_OFF(); break; -+ case 17: RAMSES_SCANNER_WAKE_OFF(); break; -+ case 18: RAMSES_SCANNER_TRIG_OFF(); break; -+ case 19: RAMSES_GSM_RESET_OFF(); break; -+ -+ // disable automatic poweroff on file-handle close -+ case 23: ramses_stay_on |= RAMSES_CONTROL_GSM_PWR; break; -+ case 24: ramses_stay_on |= RAMSES_CONTROL_UART_PWR; break; -+ case 25: ramses_stay_on |= RAMSES_CONTROL_SCANNER_PWR; break; -+ -+ // enable automatic poweroff on file-handle close -+ case 33: ramses_stay_on &= ~RAMSES_CONTROL_GSM_PWR; break; -+ case 34: ramses_stay_on &= ~RAMSES_CONTROL_UART_PWR; break; -+ case 35: ramses_stay_on &= ~RAMSES_CONTROL_SCANNER_PWR; break; -+ } -+ return 0; -+ - default: - return -ENOIOCTLCMD; - } -@@ -2801,18 +2074,6 @@ - tty->hw_stopped = 0; - rs_start(tty); - } -- --#if 0 -- /* -- * No need to wake up processes in open wait, since they -- * sample the CLOCAL flag once, and don't recheck it. -- * XXX It's not clear whether the current behavior is correct -- * or not. Hence, this may change..... -- */ -- if (!(old_termios->c_cflag & CLOCAL) && -- (tty->termios->c_cflag & CLOCAL)) -- wake_up_interruptible(&info->open_wait); --#endif - } - - /* -@@ -2831,9 +2092,6 @@ - struct serial_state *state; - unsigned long flags; - -- if (!info || serial_paranoia_check(info, tty->device, "rs_close")) -- return; -- - state = info->state; - - save_flags(flags); cli(); -@@ -2933,10 +2191,7 @@ - { - struct async_struct * info = (struct async_struct *)tty->driver_data; - unsigned long orig_jiffies, char_time; -- int lsr; -- -- if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent")) -- return; -+ int lsr, old_show_io; - - if (info->state->type == PORT_UNKNOWN) - return; -@@ -2974,9 +2229,11 @@ - printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time); - printk("jiff=%lu...", jiffies); - #endif -+ old_show_io = show_io; -+ show_io = 0; - while (!((lsr = serial_inp(info, UART_LSR)) & UART_LSR_TEMT)) { - #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT -- printk("lsr = %d (jiff=%lu)...", lsr, jiffies); -+ printk("lsr = %02x (jiff=%lu)...", lsr, jiffies); - #endif - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); -@@ -2986,8 +2243,9 @@ - break; - } - #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT -- printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); -+ printk("lsr = %02x (jiff=%lu)...done\n", lsr, jiffies); - #endif -+ show_io = old_show_io; - } - - /* -@@ -2998,9 +2256,6 @@ - struct async_struct * info = (struct async_struct *)tty->driver_data; - struct serial_state *state = info->state; - -- if (serial_paranoia_check(info, tty->device, "rs_hangup")) -- return; -- - state = info->state; - - rs_flush_buffer(tty); -@@ -3036,12 +2291,8 @@ - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); --#ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); --#else -- return -EAGAIN; --#endif - } - - /* -@@ -3114,14 +2365,10 @@ - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(info->flags & ASYNC_INITIALIZED)) { --#ifdef SERIAL_DO_RESTART - if (info->flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; --#else -- retval = -EAGAIN; --#endif - break; - } - if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && -@@ -3223,16 +2470,12 @@ - } - tty->driver_data = info; - info->tty = tty; -- if (serial_paranoia_check(info, tty->device, "rs_open")) -- return -ENODEV; - - #ifdef SERIAL_DEBUG_OPEN - printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, - info->state->count); - #endif --#if (LINUX_VERSION_CODE > 0x20100) - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; --#endif - - /* - * This relies on lock_kernel() stuff so wants tidying for 2.5 -@@ -3254,12 +2497,8 @@ - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); --#ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); --#else -- return -EAGAIN; --#endif - } - - /* -@@ -3313,17 +2552,14 @@ - int ret; - unsigned long flags; - -- /* -- * Return zero characters for ports not claimed by driver. -- */ -- if (state->type == PORT_UNKNOWN) { -- return 0; /* ignore unused ports */ -- } -- - ret = sprintf(buf, "%d: uart:%s port:%lX irq:%d", - state->line, uart_config[state->type].name, -- (state->port ? state->port : (long)state->iomem_base), -- state->irq); -+ state->port, state->irq); -+ -+ if (!state->port || (state->type == PORT_UNKNOWN)) { -+ ret += sprintf(buf+ret, "\n"); -+ return ret; -+ } - - /* - * Figure out the current RS-232 lines -@@ -3334,7 +2570,6 @@ - info->magic = SERIAL_MAGIC; - info->port = state->port; - info->flags = state->flags; -- info->hub6 = state->hub6; - info->io_type = state->io_type; - info->iomem_base = state->iomem_base; - info->iomem_reg_shift = state->iomem_reg_shift; -@@ -3389,13 +2624,13 @@ - } - - static int rs_read_proc(char *page, char **start, off_t off, int count, -- int *eof, void *data) -+ int *eof, void *data) - { - int i, len = 0, l; - off_t begin = 0; - -- len += sprintf(page, "serinfo:1.0 driver:%s%s revision:%s\n", -- serial_version, LOCAL_VERSTRING, serial_revdate); -+ len += sprintf(page, "serial: %s\n", -+ LOCAL_VERSTRING); - for (i = 0; i < NR_PORTS && len < 4000; i++) { - l = line_info(page + len, &rs_table[i]); - len += l; -@@ -3423,2038 +2658,63 @@ - */ - - /* -- * This routine prints out the appropriate serial driver version -- * number, and identifies which options were configured into this -- * driver. -- */ --static char serial_options[] __initdata = --#ifdef CONFIG_HUB6 -- " HUB-6" --#define SERIAL_OPT --#endif --#ifdef CONFIG_SERIAL_MANY_PORTS -- " MANY_PORTS" --#define SERIAL_OPT --#endif --#ifdef CONFIG_SERIAL_MULTIPORT -- " MULTIPORT" --#define SERIAL_OPT --#endif --#ifdef CONFIG_SERIAL_SHARE_IRQ -- " SHARE_IRQ" --#define SERIAL_OPT --#endif --#ifdef CONFIG_SERIAL_DETECT_IRQ -- " DETECT_IRQ" --#define SERIAL_OPT --#endif --#ifdef ENABLE_SERIAL_PCI -- " SERIAL_PCI" --#define SERIAL_OPT --#endif --#ifdef ENABLE_SERIAL_PNP -- " ISAPNP" --#define SERIAL_OPT --#endif --#ifdef ENABLE_SERIAL_ACPI -- " SERIAL_ACPI" --#define SERIAL_OPT --#endif --#ifdef SERIAL_OPT -- " enabled\n"; --#else -- " no serial options enabled\n"; --#endif --#undef SERIAL_OPT -- --static _INLINE_ void show_serial_version(void) --{ -- printk(KERN_INFO "%s version %s%s (%s) with%s", serial_name, -- serial_version, LOCAL_VERSTRING, serial_revdate, -- serial_options); --} -- --/* -- * This routine detect the IRQ of a serial port by clearing OUT2 when -- * no UART interrupt are requested (IER = 0) (*GPL*). This seems to work at -- * each time, as long as no other device permanently request the IRQ. -- * If no IRQ is detected, or multiple IRQ appear, this function returns 0. -- * The variable "state" and the field "state->port" should not be null. -- */ --static unsigned detect_uart_irq (struct serial_state * state) --{ -- int irq; -- unsigned long irqs; -- unsigned char save_mcr, save_ier; -- struct async_struct scr_info; /* serial_{in,out} because HUB6 */ -- --#ifdef CONFIG_SERIAL_MANY_PORTS -- unsigned char save_ICP=0; /* no warning */ -- unsigned short ICP=0; -- -- if (state->flags & ASYNC_FOURPORT) { -- ICP = (state->port & 0xFE0) | 0x01F; -- save_ICP = inb_p(ICP); -- outb_p(0x80, ICP); -- (void) inb_p(ICP); -- } --#endif -- scr_info.magic = SERIAL_MAGIC; -- scr_info.state = state; -- scr_info.port = state->port; -- scr_info.flags = state->flags; --#ifdef CONFIG_HUB6 -- scr_info.hub6 = state->hub6; --#endif -- scr_info.io_type = state->io_type; -- scr_info.iomem_base = state->iomem_base; -- scr_info.iomem_reg_shift = state->iomem_reg_shift; -- -- /* forget possible initially masked and pending IRQ */ -- probe_irq_off(probe_irq_on()); -- save_mcr = serial_inp(&scr_info, UART_MCR); -- save_ier = serial_inp(&scr_info, UART_IER); -- serial_outp(&scr_info, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2); -- -- irqs = probe_irq_on(); -- serial_outp(&scr_info, UART_MCR, 0); -- udelay (10); -- if (state->flags & ASYNC_FOURPORT) { -- serial_outp(&scr_info, UART_MCR, -- UART_MCR_DTR | UART_MCR_RTS); -- } else { -- serial_outp(&scr_info, UART_MCR, -- UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); -- } -- serial_outp(&scr_info, UART_IER, 0x0f); /* enable all intrs */ -- (void)serial_inp(&scr_info, UART_LSR); -- (void)serial_inp(&scr_info, UART_RX); -- (void)serial_inp(&scr_info, UART_IIR); -- (void)serial_inp(&scr_info, UART_MSR); -- serial_outp(&scr_info, UART_TX, 0xFF); -- udelay (20); -- irq = probe_irq_off(irqs); -- -- serial_outp(&scr_info, UART_MCR, save_mcr); -- serial_outp(&scr_info, UART_IER, save_ier); --#ifdef CONFIG_SERIAL_MANY_PORTS -- if (state->flags & ASYNC_FOURPORT) -- outb_p(save_ICP, ICP); --#endif -- return (irq > 0)? irq : 0; --} -- --/* -- * This is a quickie test to see how big the FIFO is. -- * It doesn't work at all the time, more's the pity. -- */ --static int size_fifo(struct async_struct *info) --{ -- unsigned char old_fcr, old_mcr, old_dll, old_dlm; -- int count; -- -- old_fcr = serial_inp(info, UART_FCR); -- old_mcr = serial_inp(info, UART_MCR); -- serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO | -- UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); -- serial_outp(info, UART_MCR, UART_MCR_LOOP); -- serial_outp(info, UART_LCR, UART_LCR_DLAB); -- old_dll = serial_inp(info, UART_DLL); -- old_dlm = serial_inp(info, UART_DLM); -- serial_outp(info, UART_DLL, 0x01); -- serial_outp(info, UART_DLM, 0x00); -- serial_outp(info, UART_LCR, 0x03); -- for (count = 0; count < 256; count++) -- serial_outp(info, UART_TX, count); -- mdelay(20); -- for (count = 0; (serial_inp(info, UART_LSR) & UART_LSR_DR) && -- (count < 256); count++) -- serial_inp(info, UART_RX); -- serial_outp(info, UART_FCR, old_fcr); -- serial_outp(info, UART_MCR, old_mcr); -- serial_outp(info, UART_LCR, UART_LCR_DLAB); -- serial_outp(info, UART_DLL, old_dll); -- serial_outp(info, UART_DLM, old_dlm); -- -- return count; --} -- --/* -- * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's. -- * When this function is called we know it is at least a StarTech -- * 16650 V2, but it might be one of several StarTech UARTs, or one of -- * its clones. (We treat the broken original StarTech 16650 V1 as a -- * 16550, and why not? Startech doesn't seem to even acknowledge its -- * existence.) -- * -- * What evil have men's minds wrought... -- */ --static void autoconfig_startech_uarts(struct async_struct *info, -- struct serial_state *state, -- unsigned long flags) --{ -- unsigned char scratch, scratch2, scratch3, scratch4; -- -- /* -- * First we check to see if it's an Oxford Semiconductor UART. -- * -- * If we have to do this here because some non-National -- * Semiconductor clone chips lock up if you try writing to the -- * LSR register (which serial_icr_read does) -- */ -- if (state->type == PORT_16550A) { -- /* -- * EFR [4] must be set else this test fails -- * -- * This shouldn't be necessary, but Mike Hudson -- * (Exoray@isys.ca) claims that it's needed for 952 -- * dual UART's (which are not recommended for new designs). -- */ -- info->ACR = 0; -- serial_out(info, UART_LCR, 0xBF); -- serial_out(info, UART_EFR, 0x10); -- serial_out(info, UART_LCR, 0x00); -- /* Check for Oxford Semiconductor 16C950 */ -- scratch = serial_icr_read(info, UART_ID1); -- scratch2 = serial_icr_read(info, UART_ID2); -- scratch3 = serial_icr_read(info, UART_ID3); -- -- if (scratch == 0x16 && scratch2 == 0xC9 && -- (scratch3 == 0x50 || scratch3 == 0x52 || -- scratch3 == 0x54)) { -- state->type = PORT_16C950; -- state->revision = serial_icr_read(info, UART_REV) | -- (scratch3 << 8); -- return; -- } -- } -- -- /* -- * We check for a XR16C850 by setting DLL and DLM to 0, and -- * then reading back DLL and DLM. If DLM reads back 0x10, -- * then the UART is a XR16C850 and the DLL contains the chip -- * revision. If DLM reads back 0x14, then the UART is a -- * XR16C854. -- * -- */ -- -- /* Save the DLL and DLM */ -- -- serial_outp(info, UART_LCR, UART_LCR_DLAB); -- scratch3 = serial_inp(info, UART_DLL); -- scratch4 = serial_inp(info, UART_DLM); -- -- serial_outp(info, UART_DLL, 0); -- serial_outp(info, UART_DLM, 0); -- scratch2 = serial_inp(info, UART_DLL); -- scratch = serial_inp(info, UART_DLM); -- serial_outp(info, UART_LCR, 0); -- -- if (scratch == 0x10 || scratch == 0x14) { -- if (scratch == 0x10) -- state->revision = scratch2; -- state->type = PORT_16850; -- return; -- } -- -- /* Restore the DLL and DLM */ -- -- serial_outp(info, UART_LCR, UART_LCR_DLAB); -- serial_outp(info, UART_DLL, scratch3); -- serial_outp(info, UART_DLM, scratch4); -- serial_outp(info, UART_LCR, 0); -- /* -- * We distinguish between the '654 and the '650 by counting -- * how many bytes are in the FIFO. I'm using this for now, -- * since that's the technique that was sent to me in the -- * serial driver update, but I'm not convinced this works. -- * I've had problems doing this in the past. -TYT -- */ -- if (size_fifo(info) == 64) -- state->type = PORT_16654; -- else -- state->type = PORT_16650V2; --} -- --/* -- * 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 serial_state * state) --{ -- unsigned char status1, status2, scratch, scratch2, scratch3; -- unsigned char save_lcr, save_mcr; -- struct async_struct *info, scr_info; -- unsigned long flags; -- -- state->type = PORT_UNKNOWN; -- --#ifdef SERIAL_DEBUG_AUTOCONF -- printk("Testing ttyS%d (0x%04lx, 0x%04x)...\n", state->line, -- state->port, (unsigned) state->iomem_base); --#endif -- -- if (!CONFIGURED_SERIAL_PORT(state)) -- return; -- -- info = &scr_info; /* This is just for serial_{in,out} */ -- -- info->magic = SERIAL_MAGIC; -- info->state = state; -- info->port = state->port; -- info->flags = state->flags; --#ifdef CONFIG_HUB6 -- info->hub6 = state->hub6; --#endif -- info->io_type = state->io_type; -- info->iomem_base = state->iomem_base; -- info->iomem_reg_shift = state->iomem_reg_shift; -- -- save_flags(flags); cli(); -- -- if (!(state->flags & ASYNC_BUGGY_UART) && -- !state->iomem_base) { -- /* -- * Do a simple existence test first; if we fail this, -- * there's no point trying anything else. -- * -- * 0x80 is used as a nonsense port to prevent against -- * false positives due to ISA bus float. The -- * assumption is that 0x80 is a non-existent port; -- * which should be safe since include/asm/io.h also -- * makes this assumption. -- */ -- scratch = serial_inp(info, UART_IER); -- serial_outp(info, UART_IER, 0); --#ifdef __i386__ -- outb(0xff, 0x080); --#endif -- scratch2 = serial_inp(info, UART_IER); -- serial_outp(info, UART_IER, 0x0F); --#ifdef __i386__ -- outb(0, 0x080); --#endif -- scratch3 = serial_inp(info, UART_IER); -- serial_outp(info, UART_IER, scratch); -- if (scratch2 || scratch3 != 0x0F) { --#ifdef SERIAL_DEBUG_AUTOCONF -- printk("serial: ttyS%d: simple autoconfig failed " -- "(%02x, %02x)\n", state->line, -- scratch2, scratch3); --#endif -- restore_flags(flags); -- return; /* We failed; there's nothing here */ -- } -- } -- -- save_mcr = serial_in(info, UART_MCR); -- save_lcr = serial_in(info, UART_LCR); -- -- /* -- * Check to see if a UART is really there. Certain broken -- * internal modems based on the Rockwell chipset fail this -- * test, because they apparently don't implement the loopback -- * test mode. So this test is skipped on the COM 1 through -- * COM 4 ports. This *should* be safe, since no board -- * manufacturer would be stupid enough to design a board -- * that conflicts with COM 1-4 --- we hope! -- */ -- if (!(state->flags & ASYNC_SKIP_TEST)) { -- serial_outp(info, UART_MCR, UART_MCR_LOOP | 0x0A); -- status1 = serial_inp(info, UART_MSR) & 0xF0; -- serial_outp(info, UART_MCR, save_mcr); -- if (status1 != 0x90) { --#ifdef SERIAL_DEBUG_AUTOCONF -- printk("serial: ttyS%d: no UART loopback failed\n", -- state->line); --#endif -- restore_flags(flags); -- return; -- } -- } -- serial_outp(info, UART_LCR, 0xBF); /* set up for StarTech test */ -- serial_outp(info, UART_EFR, 0); /* EFR is the same as FCR */ -- serial_outp(info, UART_LCR, 0); -- serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); -- scratch = serial_in(info, UART_IIR) >> 6; -- switch (scratch) { -- case 0: -- state->type = PORT_16450; -- break; -- case 1: -- state->type = PORT_UNKNOWN; -- break; -- case 2: -- state->type = PORT_16550; -- break; -- case 3: -- state->type = PORT_16550A; -- break; -- } -- if (state->type == PORT_16550A) { -- /* Check for Startech UART's */ -- serial_outp(info, UART_LCR, UART_LCR_DLAB); -- if (serial_in(info, UART_EFR) == 0) { -- state->type = PORT_16650; -- } else { -- serial_outp(info, UART_LCR, 0xBF); -- if (serial_in(info, UART_EFR) == 0) -- autoconfig_startech_uarts(info, state, flags); -- } -- } -- if (state->type == PORT_16550A) { -- /* Check for TI 16750 */ -- serial_outp(info, UART_LCR, save_lcr | UART_LCR_DLAB); -- serial_outp(info, UART_FCR, -- UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); -- scratch = serial_in(info, UART_IIR) >> 5; -- if (scratch == 7) { -- /* -- * If this is a 16750, and not a cheap UART -- * clone, then it should only go into 64 byte -- * mode if the UART_FCR7_64BYTE bit was set -- * while UART_LCR_DLAB was latched. -- */ -- serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); -- serial_outp(info, UART_LCR, 0); -- serial_outp(info, UART_FCR, -- UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); -- scratch = serial_in(info, UART_IIR) >> 5; -- if (scratch == 6) -- state->type = PORT_16750; -- } -- serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); -- } --#if defined(CONFIG_SERIAL_RSA) && defined(MODULE) -- if (state->type == PORT_16550A) { -- int i; -- -- for (i = 0 ; i < PORT_RSA_MAX ; ++i) { -- if (!probe_rsa[i] && !force_rsa[i]) -- break; -- if (((probe_rsa[i] != state->port) || -- check_region(state->port + UART_RSA_BASE, 16)) && -- (force_rsa[i] != state->port)) -- continue; -- if (!enable_rsa(info)) -- continue; -- state->type = PORT_RSA; -- state->baud_base = SERIAL_RSA_BAUD_BASE; -- break; -- } -- } --#endif -- serial_outp(info, UART_LCR, save_lcr); -- if (state->type == PORT_16450) { -- scratch = serial_in(info, UART_SCR); -- serial_outp(info, UART_SCR, 0xa5); -- status1 = serial_in(info, UART_SCR); -- serial_outp(info, UART_SCR, 0x5a); -- status2 = serial_in(info, UART_SCR); -- serial_outp(info, UART_SCR, scratch); -- -- if ((status1 != 0xa5) || (status2 != 0x5a)) -- state->type = PORT_8250; -- } -- state->xmit_fifo_size = uart_config[state->type].dfl_xmit_fifo_size; -- -- if (state->type == PORT_UNKNOWN) { -- restore_flags(flags); -- return; -- } -- -- if (info->port) { --#ifdef CONFIG_SERIAL_RSA -- if (state->type == PORT_RSA) -- request_region(info->port + UART_RSA_BASE, 16, -- "serial_rsa(auto)"); -- else --#endif -- request_region(info->port,8,"serial(auto)"); -- } -- -- /* -- * Reset the UART. -- */ --#ifdef CONFIG_SERIAL_RSA -- if (state->type == PORT_RSA) -- serial_outp(info, UART_RSA_FRR, 0); --#endif -- serial_outp(info, UART_MCR, save_mcr); -- serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO | -- UART_FCR_CLEAR_RCVR | -- UART_FCR_CLEAR_XMIT)); -- serial_outp(info, UART_FCR, 0); -- (void)serial_in(info, UART_RX); -- serial_outp(info, UART_IER, 0); -- -- restore_flags(flags); --} -- --int register_serial(struct serial_struct *req); --void unregister_serial(int line); -- --#if (LINUX_VERSION_CODE > 0x20100) --EXPORT_SYMBOL(register_serial); --EXPORT_SYMBOL(unregister_serial); --#else --static struct symbol_table serial_syms = { --#include -- X(register_serial), -- X(unregister_serial), --#include --}; --#endif -- -- --#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP) -- --static void __devinit printk_pnp_dev_id(unsigned short vendor, -- unsigned short device) --{ -- printk("%c%c%c%x%x%x%x", -- 'A' + ((vendor >> 2) & 0x3f) - 1, -- 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, -- 'A' + ((vendor >> 8) & 0x1f) - 1, -- (device >> 4) & 0x0f, -- device & 0x0f, -- (device >> 12) & 0x0f, -- (device >> 8) & 0x0f); --} -- --static _INLINE_ int get_pci_port(struct pci_dev *dev, -- struct pci_board *board, -- struct serial_struct *req, -- int idx) --{ -- unsigned long port; -- int base_idx; -- int max_port; -- int offset; -- -- base_idx = SPCI_FL_GET_BASE(board->flags); -- if (board->flags & SPCI_FL_BASE_TABLE) -- base_idx += idx; -- -- if (board->flags & SPCI_FL_REGION_SZ_CAP) { -- max_port = pci_resource_len(dev, base_idx) / 8; -- if (idx >= max_port) -- return 1; -- } -- -- offset = board->first_uart_offset; -- -- /* Timedia/SUNIX uses a mixture of BARs and offsets */ -- /* Ugh, this is ugly as all hell --- TYT */ -- if(dev->vendor == PCI_VENDOR_ID_TIMEDIA ) /* 0x1409 */ -- switch(idx) { -- case 0: base_idx=0; -- break; -- case 1: base_idx=0; offset=8; -- break; -- case 2: base_idx=1; -- break; -- case 3: base_idx=1; offset=8; -- break; -- case 4: /* BAR 2*/ -- case 5: /* BAR 3 */ -- case 6: /* BAR 4*/ -- case 7: base_idx=idx-2; /* BAR 5*/ -- } -- -- /* Some Titan cards are also a little weird */ -- if (dev->vendor == PCI_VENDOR_ID_TITAN && -- (dev->device == PCI_DEVICE_ID_TITAN_400L || -- dev->device == PCI_DEVICE_ID_TITAN_800L)) { -- switch (idx) { -- case 0: base_idx = 1; -- break; -- case 1: base_idx = 2; -- break; -- default: -- base_idx = 4; -- offset = 8 * (idx - 2); -- } -- -- } -- -- /* HP's Diva chip puts the 4th/5th serial port further out, and -- * some serial ports are supposed to be hidden on certain models. -- */ -- if (dev->vendor == PCI_VENDOR_ID_HP && -- dev->device == PCI_DEVICE_ID_HP_SAS) { -- switch (dev->subsystem_device) { -- case 0x104B: /* Maestro */ -- if (idx == 3) idx++; -- break; -- case 0x1282: /* Everest / Longs Peak */ -- if (idx > 0) idx++; -- if (idx > 2) idx++; -- break; -- } -- if (idx > 2) { -- offset = 0x18; -- } -- } -- -- port = pci_resource_start(dev, base_idx) + offset; -- -- if ((board->flags & SPCI_FL_BASE_TABLE) == 0) -- port += idx * (board->uart_offset ? board->uart_offset : 8); -- -- if (IS_PCI_REGION_IOPORT(dev, base_idx)) { -- req->port = port; -- if (HIGH_BITS_OFFSET) -- req->port_high = port >> HIGH_BITS_OFFSET; -- else -- req->port_high = 0; -- return 0; -- } -- req->io_type = SERIAL_IO_MEM; -- req->iomem_base = ioremap(port, board->uart_offset); -- req->iomem_reg_shift = board->reg_shift; -- req->port = 0; -- return 0; --} -- --static _INLINE_ int get_pci_irq(struct pci_dev *dev, -- struct pci_board *board, -- int idx) --{ -- int base_idx; -- -- if ((board->flags & SPCI_FL_IRQRESOURCE) == 0) -- return dev->irq; -- -- base_idx = SPCI_FL_GET_IRQBASE(board->flags); -- if (board->flags & SPCI_FL_IRQ_TABLE) -- base_idx += idx; -- -- return PCI_IRQ_RESOURCE(dev, base_idx); --} -- --/* -- * Common enabler code shared by both PCI and ISAPNP probes -- */ --static void __devinit start_pci_pnp_board(struct pci_dev *dev, -- struct pci_board *board) --{ -- int k, line; -- struct serial_struct serial_req; -- int base_baud; -- -- if (PREPARE_FUNC(dev) && (PREPARE_FUNC(dev))(dev) < 0) { -- printk("serial: PNP device '"); -- printk_pnp_dev_id(dev->vendor, dev->device); -- printk("' prepare failed\n"); -- return; -- } -- -- if (ACTIVATE_FUNC(dev) && (ACTIVATE_FUNC(dev))(dev) < 0) { -- printk("serial: PNP device '"); -- printk_pnp_dev_id(dev->vendor, dev->device); -- printk("' activate failed\n"); -- return; -- } -- -- /* -- * Run the initialization function, if any -- */ -- if (board->init_fn && ((board->init_fn)(dev, board, 1) != 0)) -- return; -- -- /* -- * Register the serial board in the array if we need to -- * shutdown the board on a module unload or card removal -- */ -- if (DEACTIVATE_FUNC(dev) || board->init_fn) { -- for (k=0; k < NR_PCI_BOARDS; k++) -- if (serial_pci_board[k].dev == 0) -- break; -- if (k >= NR_PCI_BOARDS) -- return; -- serial_pci_board[k].board = *board; -- serial_pci_board[k].dev = dev; -- } -- -- base_baud = board->base_baud; -- if (!base_baud) -- base_baud = BASE_BAUD; -- memset(&serial_req, 0, sizeof(serial_req)); -- -- for (k=0; k < board->num_ports; k++) { -- serial_req.irq = get_pci_irq(dev, board, k); -- if (get_pci_port(dev, board, &serial_req, k)) -- break; -- serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE; --#ifdef SERIAL_DEBUG_PCI -- printk("Setup PCI/PNP port: port %x, irq %d, type %d\n", -- serial_req.port, serial_req.irq, serial_req.io_type); --#endif -- line = register_serial(&serial_req); -- if (line < 0) -- break; -- rs_table[line].baud_base = base_baud; -- rs_table[line].dev = dev; -- } --} --#endif /* ENABLE_SERIAL_PCI || ENABLE_SERIAL_PNP */ -- --#ifdef ENABLE_SERIAL_PCI --/* -- * Some PCI serial cards using the PLX 9050 PCI interface chip require -- * that the card interrupt be explicitly enabled or disabled. This -- * seems to be mainly needed on card using the PLX which also use I/O -- * mapped memory. -- */ --static int __devinit --pci_plx9050_fn(struct pci_dev *dev, struct pci_board *board, int enable) --{ -- u8 data, *p, irq_config; -- int pci_config; -- -- irq_config = 0x41; -- pci_config = PCI_COMMAND_MEMORY; -- if (dev->vendor == PCI_VENDOR_ID_PANACOM) -- irq_config = 0x43; -- if ((dev->vendor == PCI_VENDOR_ID_PLX) && -- (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) { -- /* -- * As the megawolf cards have the int pins active -- * high, and have 2 UART chips, both ints must be -- * enabled on the 9050. Also, the UARTS are set in -- * 16450 mode by default, so we have to enable the -- * 16C950 'enhanced' mode so that we can use the deep -- * FIFOs -- */ -- irq_config = 0x5b; -- pci_config = PCI_COMMAND_MEMORY | PCI_COMMAND_IO; -- } -- -- pci_read_config_byte(dev, PCI_COMMAND, &data); -- -- if (enable) -- pci_write_config_byte(dev, PCI_COMMAND, -- data | pci_config); -- -- /* enable/disable interrupts */ -- p = ioremap(pci_resource_start(dev, 0), 0x80); -- writel(enable ? irq_config : 0x00, (unsigned long)p + 0x4c); -- iounmap(p); -- -- if (!enable) -- pci_write_config_byte(dev, PCI_COMMAND, -- data & ~pci_config); -- return 0; --} -- -- --/* -- * SIIG serial cards have an PCI interface chip which also controls -- * the UART clocking frequency. Each UART can be clocked independently -- * (except cards equiped with 4 UARTs) and initial clocking settings -- * are stored in the EEPROM chip. It can cause problems because this -- * version of serial driver doesn't support differently clocked UART's -- * on single PCI card. To prevent this, initialization functions set -- * high frequency clocking for all UART's on given card. It is safe (I -- * hope) because it doesn't touch EEPROM settings to prevent conflicts -- * with other OSes (like M$ DOS). -- * -- * SIIG support added by Andrey Panin , 10/1999 -- * -- * There is two family of SIIG serial cards with different PCI -- * interface chip and different configuration methods: -- * - 10x cards have control registers in IO and/or memory space; -- * - 20x cards have control registers in standard PCI configuration space. -- * -- * SIIG initialization functions exported for use by parport_serial.c module. -- */ -- --#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc) --#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8) -- --int __devinit --pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable) --{ -- u16 data, *p; -- -- if (!enable) return 0; -- -- p = ioremap(pci_resource_start(dev, 0), 0x80); -- -- switch (dev->device & 0xfff8) { -- case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */ -- data = 0xffdf; -- break; -- case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */ -- data = 0xf7ff; -- break; -- default: /* 1S1P, 4S */ -- data = 0xfffb; -- break; -- } -- -- writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28); -- iounmap(p); -- return 0; --} --EXPORT_SYMBOL(pci_siig10x_fn); -- --#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc) --#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc) -- --int __devinit --pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable) --{ -- u8 data; -- -- if (!enable) return 0; -- -- /* Change clock frequency for the first UART. */ -- pci_read_config_byte(dev, 0x6f, &data); -- pci_write_config_byte(dev, 0x6f, data & 0xef); -- -- /* If this card has 2 UART, we have to do the same with second UART. */ -- if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) || -- ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) { -- pci_read_config_byte(dev, 0x73, &data); -- pci_write_config_byte(dev, 0x73, data & 0xef); -- } -- return 0; --} --EXPORT_SYMBOL(pci_siig20x_fn); -- --/* Added for EKF Intel i960 serial boards */ --static int __devinit --pci_inteli960ni_fn(struct pci_dev *dev, -- struct pci_board *board, -- int enable) --{ -- unsigned long oldval; -- -- if (!(pci_get_subdevice(dev) & 0x1000)) -- return(-1); -- -- if (!enable) /* is there something to deinit? */ -- return(0); -- --#ifdef SERIAL_DEBUG_PCI -- printk(KERN_DEBUG " Subsystem ID %lx (intel 960)\n", -- (unsigned long) board->subdevice); --#endif -- /* is firmware started? */ -- pci_read_config_dword(dev, 0x44, (void*) &oldval); -- if (oldval == 0x00001000L) { /* RESET value */ -- printk(KERN_DEBUG "Local i960 firmware missing"); -- return(-1); -- } -- return(0); --} -- --/* -- * Timedia has an explosion of boards, and to avoid the PCI table from -- * growing *huge*, we use this function to collapse some 70 entries -- * in the PCI table into one, for sanity's and compactness's sake. -- */ --static unsigned short timedia_single_port[] = { -- 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0 }; --static unsigned short timedia_dual_port[] = { -- 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085, -- 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079, -- 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079, -- 0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079, -- 0xD079, 0 }; --static unsigned short timedia_quad_port[] = { -- 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157, -- 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159, -- 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056, -- 0xB157, 0 }; --static unsigned short timedia_eight_port[] = { -- 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166, -- 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0 }; --static struct timedia_struct { -- int num; -- unsigned short *ids; --} timedia_data[] = { -- { 1, timedia_single_port }, -- { 2, timedia_dual_port }, -- { 4, timedia_quad_port }, -- { 8, timedia_eight_port }, -- { 0, 0 } --}; -- --static int __devinit --pci_timedia_fn(struct pci_dev *dev, struct pci_board *board, int enable) --{ -- int i, j; -- unsigned short *ids; -- -- if (!enable) -- return 0; -- -- for (i=0; timedia_data[i].num; i++) { -- ids = timedia_data[i].ids; -- for (j=0; ids[j]; j++) { -- if (pci_get_subdevice(dev) == ids[j]) { -- board->num_ports = timedia_data[i].num; -- return 0; -- } -- } -- } -- return 0; --} -- --/* -- * HP's Remote Management Console. The Diva chip came in several -- * different versions. N-class, L2000 and A500 have two Diva chips, each -- * with 3 UARTs (the third UART on the second chip is unused). Superdome -- * and Keystone have one Diva chip with 3 UARTs. Some later machines have -- * one Diva chip, but it has been expanded to 5 UARTs. -- */ --static int __devinit --pci_hp_diva(struct pci_dev *dev, struct pci_board *board, int enable) --{ -- if (!enable) -- return 0; -- -- switch (dev->subsystem_device) { -- case 0x1049: /* Prelude Diva 1 */ -- case 0x1223: /* Superdome */ -- case 0x1226: /* Keystone */ -- case 0x1282: /* Everest / Longs Peak */ -- board->num_ports = 3; -- break; -- case 0x104A: /* Prelude Diva 2 */ -- board->num_ports = 2; -- break; -- case 0x104B: /* Maestro */ -- board->num_ports = 4; -- break; -- case 0x1227: /* Powerbar */ -- board->num_ports = 1; -- break; -- } -- -- return 0; --} -- --static int __devinit --pci_xircom_fn(struct pci_dev *dev, struct pci_board *board, int enable) --{ -- __set_current_state(TASK_UNINTERRUPTIBLE); -- schedule_timeout(HZ/10); -- return 0; --} -- --/* -- * This is the configuration table for all of the PCI serial boards -- * which we support. It is directly indexed by the pci_board_num_t enum -- * value, which is encoded in the pci_device_id PCI probe table's -- * driver_data member. -- */ --enum pci_board_num_t { -- pbn_b0_1_115200, -- pbn_default = 0, -- -- pbn_b0_2_115200, -- pbn_b0_4_115200, -- -- pbn_b0_1_921600, -- pbn_b0_2_921600, -- pbn_b0_4_921600, -- -- pbn_b0_bt_1_115200, -- pbn_b0_bt_2_115200, -- pbn_b0_bt_1_460800, -- pbn_b0_bt_2_460800, -- pbn_b0_bt_2_921600, -- -- pbn_b1_1_115200, -- pbn_b1_2_115200, -- pbn_b1_4_115200, -- pbn_b1_8_115200, -- -- pbn_b1_2_921600, -- pbn_b1_4_921600, -- pbn_b1_8_921600, -- -- pbn_b1_2_1382400, -- pbn_b1_4_1382400, -- pbn_b1_8_1382400, -- -- pbn_b2_1_115200, -- pbn_b2_8_115200, -- pbn_b2_4_460800, -- pbn_b2_8_460800, -- pbn_b2_16_460800, -- pbn_b2_4_921600, -- pbn_b2_8_921600, -- -- pbn_b2_bt_1_115200, -- pbn_b2_bt_2_115200, -- pbn_b2_bt_4_115200, -- pbn_b2_bt_2_921600, -- -- pbn_panacom, -- pbn_panacom2, -- pbn_panacom4, -- pbn_plx_romulus, -- pbn_oxsemi, -- pbn_timedia, -- pbn_intel_i960, -- pbn_sgi_ioc3, -- pbn_hp_diva, --#ifdef CONFIG_DDB5074 -- pbn_nec_nile4, --#endif --#if 0 -- pbn_dci_pccom8, --#endif -- pbn_xircom_combo, -- -- pbn_siig10x_0, -- pbn_siig10x_1, -- pbn_siig10x_2, -- pbn_siig10x_4, -- pbn_siig20x_0, -- pbn_siig20x_2, -- pbn_siig20x_4, -- -- pbn_computone_4, -- pbn_computone_6, -- pbn_computone_8, --}; -- --static struct pci_board pci_boards[] __devinitdata = { -- /* -- * PCI Flags, Number of Ports, Base (Maximum) Baud Rate, -- * Offset to get to next UART's registers, -- * Register shift to use for memory-mapped I/O, -- * Initialization function, first UART offset -- */ -- -- /* Generic serial board, pbn_b0_1_115200, pbn_default */ -- { SPCI_FL_BASE0, 1, 115200 }, /* pbn_b0_1_115200, -- pbn_default */ -- -- { SPCI_FL_BASE0, 2, 115200 }, /* pbn_b0_2_115200 */ -- { SPCI_FL_BASE0, 4, 115200 }, /* pbn_b0_4_115200 */ -- -- { SPCI_FL_BASE0, 1, 921600 }, /* pbn_b0_1_921600 */ -- { SPCI_FL_BASE0, 2, 921600 }, /* pbn_b0_2_921600 */ -- { SPCI_FL_BASE0, 4, 921600 }, /* pbn_b0_4_921600 */ -- -- { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b0_bt_1_115200 */ -- { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b0_bt_2_115200 */ -- { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 460800 }, /* pbn_b0_bt_1_460800 */ -- { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 460800 }, /* pbn_b0_bt_2_460800 */ -- { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b0_bt_2_921600 */ -- -- { SPCI_FL_BASE1, 1, 115200 }, /* pbn_b1_1_115200 */ -- { SPCI_FL_BASE1, 2, 115200 }, /* pbn_b1_2_115200 */ -- { SPCI_FL_BASE1, 4, 115200 }, /* pbn_b1_4_115200 */ -- { SPCI_FL_BASE1, 8, 115200 }, /* pbn_b1_8_115200 */ -- -- { SPCI_FL_BASE1, 2, 921600 }, /* pbn_b1_2_921600 */ -- { SPCI_FL_BASE1, 4, 921600 }, /* pbn_b1_4_921600 */ -- { SPCI_FL_BASE1, 8, 921600 }, /* pbn_b1_8_921600 */ -- -- { SPCI_FL_BASE1, 2, 1382400 }, /* pbn_b1_2_1382400 */ -- { SPCI_FL_BASE1, 4, 1382400 }, /* pbn_b1_4_1382400 */ -- { SPCI_FL_BASE1, 8, 1382400 }, /* pbn_b1_8_1382400 */ -- -- { SPCI_FL_BASE2, 1, 115200 }, /* pbn_b2_1_115200 */ -- { SPCI_FL_BASE2, 8, 115200 }, /* pbn_b2_8_115200 */ -- { SPCI_FL_BASE2, 4, 460800 }, /* pbn_b2_4_460800 */ -- { SPCI_FL_BASE2, 8, 460800 }, /* pbn_b2_8_460800 */ -- { SPCI_FL_BASE2, 16, 460800 }, /* pbn_b2_16_460800 */ -- { SPCI_FL_BASE2, 4, 921600 }, /* pbn_b2_4_921600 */ -- { SPCI_FL_BASE2, 8, 921600 }, /* pbn_b2_8_921600 */ -- -- { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b2_bt_1_115200 */ -- { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b2_bt_2_115200 */ -- { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 }, /* pbn_b2_bt_4_115200 */ -- { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b2_bt_2_921600 */ -- -- { SPCI_FL_BASE2, 2, 921600, /* IOMEM */ /* pbn_panacom */ -- 0x400, 7, pci_plx9050_fn }, -- { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_panacom2 */ -- 0x400, 7, pci_plx9050_fn }, -- { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_panacom4 */ -- 0x400, 7, pci_plx9050_fn }, -- { SPCI_FL_BASE2, 4, 921600, /* pbn_plx_romulus */ -- 0x20, 2, pci_plx9050_fn, 0x03 }, -- /* This board uses the size of PCI Base region 0 to -- * signal now many ports are available */ -- { SPCI_FL_BASE0 | SPCI_FL_REGION_SZ_CAP, 32, 115200 }, /* pbn_oxsemi */ -- { SPCI_FL_BASE_TABLE, 1, 921600, /* pbn_timedia */ -- 0, 0, pci_timedia_fn }, -- /* EKF addition for i960 Boards form EKF with serial port */ -- { SPCI_FL_BASE0, 32, 921600, /* max 256 ports */ /* pbn_intel_i960 */ -- 8<<2, 2, pci_inteli960ni_fn, 0x10000}, -- { SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE, /* pbn_sgi_ioc3 */ -- 1, 458333, 0, 0, 0, 0x20178 }, -- { SPCI_FL_BASE0, 5, 115200, 8, 0, pci_hp_diva, 0}, /* pbn_hp_diva */ --#ifdef CONFIG_DDB5074 -- /* -- * NEC Vrc-5074 (Nile 4) builtin UART. -- * Conditionally compiled in since this is a motherboard device. -- */ -- { SPCI_FL_BASE0, 1, 520833, /* pbn_nec_nile4 */ -- 64, 3, NULL, 0x300 }, --#endif --#if 0 /* PCI_DEVICE_ID_DCI_PCCOM8 ? */ /* pbn_dci_pccom8 */ -- { SPCI_FL_BASE3, 8, 115200, 8 }, --#endif -- { SPCI_FL_BASE0, 1, 115200, /* pbn_xircom_combo */ -- 0, 0, pci_xircom_fn }, -- -- { SPCI_FL_BASE2, 1, 460800, /* pbn_siig10x_0 */ -- 0, 0, pci_siig10x_fn }, -- { SPCI_FL_BASE2, 1, 921600, /* pbn_siig10x_1 */ -- 0, 0, pci_siig10x_fn }, -- { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siig10x_2 */ -- 0, 0, pci_siig10x_fn }, -- { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siig10x_4 */ -- 0, 0, pci_siig10x_fn }, -- { SPCI_FL_BASE0, 1, 921600, /* pbn_siix20x_0 */ -- 0, 0, pci_siig20x_fn }, -- { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siix20x_2 */ -- 0, 0, pci_siig20x_fn }, -- { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siix20x_4 */ -- 0, 0, pci_siig20x_fn }, -- -- { SPCI_FL_BASE0, 4, 921600, /* IOMEM */ /* pbn_computone_4 */ -- 0x40, 2, NULL, 0x200 }, -- { SPCI_FL_BASE0, 6, 921600, /* IOMEM */ /* pbn_computone_6 */ -- 0x40, 2, NULL, 0x200 }, -- { SPCI_FL_BASE0, 8, 921600, /* IOMEM */ /* pbn_computone_8 */ -- 0x40, 2, NULL, 0x200 }, --}; -- --/* -- * Given a complete unknown PCI device, try to use some heuristics to -- * guess what the configuration might be, based on the pitiful PCI -- * serial specs. Returns 0 on success, 1 on failure. -+ * The serial driver boot-time initialization code! - */ --static int __devinit serial_pci_guess_board(struct pci_dev *dev, -- struct pci_board *board) -+static int __init rs_init(void) - { -- int num_iomem = 0, num_port = 0, first_port = -1; - int i; -+ struct serial_state * state; - -- /* -- * If it is not a communications device or the programming -- * interface is greater than 6, give up. -- * -- * (Should we try to make guesses for multiport serial devices -- * later?) -- */ -- if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) && -- ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) || -- (dev->class & 0xff) > 6) -- return 1; -- -- for (i=0; i < 6; i++) { -- if (IS_PCI_REGION_IOPORT(dev, i)) { -- num_port++; -- if (first_port == -1) -- first_port = i; -- } -- if (IS_PCI_REGION_IOMEM(dev, i)) -- num_iomem++; -- } -+ printk("pxa & ti16c754b serial driver\n"); -+ set_GPIO_IRQ_edge(7, GPIO_RISING_EDGE); -+ set_GPIO_IRQ_edge(24, GPIO_RISING_EDGE); -+ set_GPIO_IRQ_edge(25, GPIO_RISING_EDGE); -+ set_GPIO_IRQ_edge(26, GPIO_RISING_EDGE); - -- /* -- * If there is exactly one port of 8 bytes, use it. -- */ -- if (num_port == 1 && pci_resource_len(dev, first_port) == 8) { -- board->flags = first_port; -- return 0; -+ if (!request_mem_region(RAMSES_UARTA_PHYS, 16*4, "Ramses UART A")) -+ printk(KERN_ERR "unable to reserve region\n"); -+ else { -+ ramses_uarta = ioremap_nocache(RAMSES_UARTA_PHYS, 16*4); -+ if (!ramses_uarta) -+ printk(KERN_ERR "unable to map region\n"); -+ else { -+ //printk("ramses_uarta cookie is: %08x\n", (unsigned int) ramses_uarta); -+ rs_table[3].iomem_base = ramses_uarta; - } -- -- /* -- * If there is 1 or 0 iomem regions, and exactly one port, use -- * it. -- */ -- if (num_iomem <= 1 && num_port == 1) { -- board->flags = first_port; -- return 0; - } -- return 1; --} -- --static int __devinit serial_init_one(struct pci_dev *dev, -- const struct pci_device_id *ent) --{ -- struct pci_board *board, tmp; -- int rc; -- -- board = &pci_boards[ent->driver_data]; -- -- rc = pci_enable_device(dev); -- if (rc) return rc; -- -- if (ent->driver_data == pbn_default && -- serial_pci_guess_board(dev, board)) -- return -ENODEV; -- else if (serial_pci_guess_board(dev, &tmp) == 0) { -- printk(KERN_INFO "Redundant entry in serial pci_table. " -- "Please send the output of\n" -- "lspci -vv, this message (%04x,%04x,%04x,%04x)\n" -- "and the manufacturer and name of " -- "serial board or modem board\n" -- "to serial-pci-info@lists.sourceforge.net.\n", -- dev->vendor, dev->device, -- pci_get_subvendor(dev), pci_get_subdevice(dev)); -- } -- -- start_pci_pnp_board(dev, board); -- -- return 0; --} -- --static void __devexit serial_remove_one(struct pci_dev *dev) --{ -- int i; -- -- /* -- * Iterate through all of the ports finding those that belong -- * to this PCI device. -- */ -- for(i = 0; i < NR_PORTS; i++) { -- if (rs_table[i].dev != dev) -- continue; -- unregister_serial(i); -- rs_table[i].dev = 0; -+ if (!request_mem_region(RAMSES_UARTB_PHYS, 16*4, "Ramses UART B")) -+ printk(KERN_ERR "unable to reserve region\n"); -+ else { -+ ramses_uartb = ioremap_nocache(RAMSES_UARTB_PHYS, 16*4); -+ if (!ramses_uartb) -+ printk(KERN_ERR "unable to map region\n"); -+ else { -+ //printk("ramses_uartb cookie is: %08x\n", (unsigned int) ramses_uartb); -+ rs_table[4].iomem_base = ramses_uartb; - } -- /* -- * Now execute any board-specific shutdown procedure -- */ -- for (i=0; i < NR_PCI_BOARDS; i++) { -- struct pci_board_inst *brd = &serial_pci_board[i]; -- -- if (serial_pci_board[i].dev != dev) -- continue; -- if (brd->board.init_fn) -- (brd->board.init_fn)(brd->dev, &brd->board, 0); -- if (DEACTIVATE_FUNC(brd->dev)) -- (DEACTIVATE_FUNC(brd->dev))(brd->dev); -- serial_pci_board[i].dev = 0; - } --} -- -- --static struct pci_device_id serial_pci_tbl[] __devinitdata = { -- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, -- PCI_SUBVENDOR_ID_CONNECT_TECH, -- PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0, -- pbn_b1_8_1382400 }, -- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, -- PCI_SUBVENDOR_ID_CONNECT_TECH, -- PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0, -- pbn_b1_4_1382400 }, -- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, -- PCI_SUBVENDOR_ID_CONNECT_TECH, -- PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0, -- pbn_b1_2_1382400 }, -- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, -- PCI_SUBVENDOR_ID_CONNECT_TECH, -- PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0, -- pbn_b1_8_1382400 }, -- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, -- PCI_SUBVENDOR_ID_CONNECT_TECH, -- PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0, -- pbn_b1_4_1382400 }, -- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, -- PCI_SUBVENDOR_ID_CONNECT_TECH, -- PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0, -- pbn_b1_2_1382400 }, -- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, -- PCI_SUBVENDOR_ID_CONNECT_TECH, -- PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0, -- pbn_b1_8_921600 }, -- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, -- PCI_SUBVENDOR_ID_CONNECT_TECH, -- PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0, -- pbn_b1_8_921600 }, -- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, -- PCI_SUBVENDOR_ID_CONNECT_TECH, -- PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0, -- pbn_b1_4_921600 }, -- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, -- PCI_SUBVENDOR_ID_CONNECT_TECH, -- PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0, -- pbn_b1_4_921600 }, -- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, -- PCI_SUBVENDOR_ID_CONNECT_TECH, -- PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0, -- pbn_b1_2_921600 }, -- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, -- PCI_SUBVENDOR_ID_CONNECT_TECH, -- PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0, -- pbn_b1_8_921600 }, -- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, -- PCI_SUBVENDOR_ID_CONNECT_TECH, -- PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0, -- pbn_b1_8_921600 }, -- { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, -- PCI_SUBVENDOR_ID_CONNECT_TECH, -- PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0, -- pbn_b1_4_921600 }, -- -- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b2_bt_1_115200 }, -- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b2_bt_2_115200 }, -- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b2_bt_4_115200 }, -- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b2_bt_2_115200 }, -- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b2_bt_4_115200 }, -- { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b2_8_115200 }, -- -- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b2_bt_2_115200 }, -- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b2_bt_2_921600 }, -- /* VScom SPCOM800, from sl@s.pl */ -- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b2_8_921600 }, -- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b2_4_921600 }, -- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, -- PCI_SUBVENDOR_ID_KEYSPAN, -- PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0, -- pbn_panacom }, -- { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_panacom4 }, -- { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_panacom2 }, -- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, -- PCI_SUBVENDOR_ID_CHASE_PCIFAST, -- PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0, -- pbn_b2_4_460800 }, -- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, -- PCI_SUBVENDOR_ID_CHASE_PCIFAST, -- PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0, -- pbn_b2_8_460800 }, -- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, -- PCI_SUBVENDOR_ID_CHASE_PCIFAST, -- PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0, -- pbn_b2_16_460800 }, -- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, -- PCI_SUBVENDOR_ID_CHASE_PCIFAST, -- PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0, -- pbn_b2_16_460800 }, -- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, -- PCI_SUBVENDOR_ID_CHASE_PCIRAS, -- PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0, -- pbn_b2_4_460800 }, -- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, -- PCI_SUBVENDOR_ID_CHASE_PCIRAS, -- PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0, -- pbn_b2_8_460800 }, -- /* Megawolf Romulus PCI Serial Card, from Mike Hudson */ -- /* (Exoray@isys.ca) */ -- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS, -- 0x10b5, 0x106a, 0, 0, -- pbn_plx_romulus }, -- { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b1_4_115200 }, -- { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b1_2_115200 }, -- { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b1_8_115200 }, -- { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b1_8_115200 }, -- { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954, -- PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, 0, 0, -- pbn_b0_4_921600 }, -- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b0_4_115200 }, -- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b0_bt_2_921600 }, -- -- /* Digitan DS560-558, from jimd@esoft.com */ -- { PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b1_1_115200 }, -- -- /* 3Com US Robotics 56k Voice Internal PCI model 5610 */ -- { PCI_VENDOR_ID_USR, 0x1008, -- PCI_ANY_ID, PCI_ANY_ID, }, -- -- /* Titan Electronic cards */ -- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b0_1_921600 }, -- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b0_2_921600 }, -- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b0_4_921600 }, -- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b0_4_921600 }, -- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L, -- PCI_ANY_ID, PCI_ANY_ID, -- SPCI_FL_BASE1, 1, 921600 }, -- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L, -- PCI_ANY_ID, PCI_ANY_ID, -- SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 }, -- /* The 400L and 800L have a custom hack in get_pci_port */ -- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L, -- PCI_ANY_ID, PCI_ANY_ID, -- SPCI_FL_BASE_TABLE, 4, 921600 }, -- { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L, -- PCI_ANY_ID, PCI_ANY_ID, -- SPCI_FL_BASE_TABLE, 8, 921600 }, -- -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig10x_0 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig10x_0 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig10x_0 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig10x_2 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig10x_2 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig10x_2 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig10x_4 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig10x_4 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig10x_4 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig20x_0 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig20x_0 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig20x_0 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig20x_2 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig20x_2 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig20x_2 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig20x_4 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig20x_4 }, -- { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_siig20x_4 }, -- -- /* Computone devices submitted by Doug McNash dmcnash@computone.com */ -- { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, -- PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4, -- 0, 0, pbn_computone_4 }, -- { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, -- PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8, -- 0, 0, pbn_computone_8 }, -- { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, -- PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6, -- 0, 0, pbn_computone_6 }, -- -- { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_oxsemi }, -- { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889, -- PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, pbn_timedia }, -- -- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b0_bt_2_115200 }, -- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b0_bt_2_115200 }, -- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b0_bt_2_115200 }, -- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b0_bt_2_460800 }, -- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b0_bt_2_460800 }, -- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b0_bt_2_460800 }, -- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b0_bt_1_115200 }, -- { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b0_bt_1_460800 }, -- -- /* RAStel 2 port modem, gerg@moreton.com.au */ -- { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b2_bt_2_115200 }, -- -- /* EKF addition for i960 Boards form EKF with serial port */ -- { PCI_VENDOR_ID_INTEL, 0x1960, -- 0xE4BF, PCI_ANY_ID, 0, 0, -- pbn_intel_i960 }, -- -- /* Xircom Cardbus/Ethernet combos */ -- { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_xircom_combo }, -- -- /* -- * Untested PCI modems, sent in from various folks... -- */ -- -- /* Elsa Model 56K PCI Modem, from Andreas Rath */ -- { PCI_VENDOR_ID_ROCKWELL, 0x1004, -- 0x1048, 0x1500, 0, 0, -- pbn_b1_1_115200 }, -- -- { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, -- 0xFF00, 0, 0, 0, -- pbn_sgi_ioc3 }, -- -- /* HP Diva card */ -- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_SAS, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_hp_diva }, -- { PCI_VENDOR_ID_HP, 0x1290, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_b2_1_115200 }, -- --#ifdef CONFIG_DDB5074 -- /* -- * NEC Vrc-5074 (Nile 4) builtin UART. -- * Conditionally compiled in since this is a motherboard device. -- */ -- { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NILE4, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_nec_nile4 }, --#endif -- --#if 0 /* PCI_DEVICE_ID_DCI_PCCOM8 ? */ -- { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8, -- PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- pbn_dci_pccom8 }, --#endif -- -- { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, -- PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xffff00, }, -- { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, -- PCI_CLASS_COMMUNICATION_MODEM << 8, 0xffff00, }, -- { 0, } --}; -- --MODULE_DEVICE_TABLE(pci, serial_pci_tbl); -- --static struct pci_driver serial_pci_driver = { -- name: "serial", -- probe: serial_init_one, -- remove: __devexit_p(serial_remove_one), -- id_table: serial_pci_tbl, --}; -- -- --/* -- * Query PCI space for known serial boards -- * If found, add them to the PCI device space in rs_table[] -- * -- * Accept a maximum of eight boards -- * -- */ --static void __devinit probe_serial_pci(void) --{ --#ifdef SERIAL_DEBUG_PCI -- printk(KERN_DEBUG "Entered probe_serial_pci()\n"); --#endif -- -- /* Register call PCI serial devices. Null out -- * the driver name upon failure, as a signal -- * not to attempt to unregister the driver later -- */ -- if (pci_module_init (&serial_pci_driver) != 0) -- serial_pci_driver.name = ""; -- --#ifdef SERIAL_DEBUG_PCI -- printk(KERN_DEBUG "Leaving probe_serial_pci() (probe finished)\n"); --#endif -- return; --} -- --#endif /* ENABLE_SERIAL_PCI */ -- --#ifdef ENABLE_SERIAL_PNP -- --struct pnp_board { -- unsigned short vendor; -- unsigned short device; --}; -- --static struct pnp_board pnp_devices[] __devinitdata = { -- /* Archtek America Corp. */ -- /* Archtek SmartLink Modem 3334BT Plug & Play */ -- { ISAPNP_VENDOR('A', 'A', 'C'), ISAPNP_DEVICE(0x000F) }, -- /* Anchor Datacomm BV */ -- /* SXPro 144 External Data Fax Modem Plug & Play */ -- { ISAPNP_VENDOR('A', 'D', 'C'), ISAPNP_DEVICE(0x0001) }, -- /* SXPro 288 External Data Fax Modem Plug & Play */ -- { ISAPNP_VENDOR('A', 'D', 'C'), ISAPNP_DEVICE(0x0002) }, -- /* Rockwell 56K ACF II Fax+Data+Voice Modem */ -- { ISAPNP_VENDOR('A', 'K', 'Y'), ISAPNP_DEVICE(0x1021) }, -- /* AZT3005 PnP SOUND DEVICE */ -- { ISAPNP_VENDOR('A', 'Z', 'T'), ISAPNP_DEVICE(0x4001) }, -- /* Best Data Products Inc. Smart One 336F PnP Modem */ -- { ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336) }, -- /* Boca Research */ -- /* Boca Complete Ofc Communicator 14.4 Data-FAX */ -- { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x0A49) }, -- /* Boca Research 33,600 ACF Modem */ -- { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x1400) }, -- /* Boca 33.6 Kbps Internal FD34FSVD */ -- { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x3400) }, -- /* Boca 33.6 Kbps Internal FD34FSVD */ -- { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x0A49) }, -- /* Best Data Products Inc. Smart One 336F PnP Modem */ -- { ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336) }, -- /* Computer Peripherals Inc */ -- /* EuroViVa CommCenter-33.6 SP PnP */ -- { ISAPNP_VENDOR('C', 'P', 'I'), ISAPNP_DEVICE(0x4050) }, -- /* Creative Labs */ -- /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */ -- { ISAPNP_VENDOR('C', 'T', 'L'), ISAPNP_DEVICE(0x3001) }, -- /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */ -- { ISAPNP_VENDOR('C', 'T', 'L'), ISAPNP_DEVICE(0x3011) }, -- /* Creative */ -- /* Creative Modem Blaster Flash56 DI5601-1 */ -- { ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x1032) }, -- /* Creative Modem Blaster V.90 DI5660 */ -- { ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x2001) }, -- /* FUJITSU */ -- /* Fujitsu 33600 PnP-I2 R Plug & Play */ -- { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0202) }, -- /* Fujitsu FMV-FX431 Plug & Play */ -- { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0205) }, -- /* Fujitsu 33600 PnP-I4 R Plug & Play */ -- { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0206) }, -- /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */ -- { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0209) }, -- /* Archtek America Corp. */ -- /* Archtek SmartLink Modem 3334BT Plug & Play */ -- { ISAPNP_VENDOR('G', 'V', 'C'), ISAPNP_DEVICE(0x000F) }, -- /* Hayes */ -- /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */ -- { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x0001) }, -- /* Hayes Optima 336 V.34 + FAX + Voice PnP */ -- { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x000C) }, -- /* Hayes Optima 336B V.34 + FAX + Voice PnP */ -- { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x000D) }, -- /* Hayes Accura 56K Ext Fax Modem PnP */ -- { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5670) }, -- /* Hayes Accura 56K Ext Fax Modem PnP */ -- { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5674) }, -- /* Hayes Accura 56K Fax Modem PnP */ -- { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5675) }, -- /* Hayes 288, V.34 + FAX */ -- { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0xF000) }, -- /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */ -- { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0xF001) }, -- /* IBM */ -- /* IBM Thinkpad 701 Internal Modem Voice */ -- { ISAPNP_VENDOR('I', 'B', 'M'), ISAPNP_DEVICE(0x0033) }, -- /* Intertex */ -- /* Intertex 28k8 33k6 Voice EXT PnP */ -- { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xC801) }, -- /* Intertex 33k6 56k Voice EXT PnP */ -- { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xC901) }, -- /* Intertex 28k8 33k6 Voice SP EXT PnP */ -- { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xD801) }, -- /* Intertex 33k6 56k Voice SP EXT PnP */ -- { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xD901) }, -- /* Intertex 28k8 33k6 Voice SP INT PnP */ -- { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF401) }, -- /* Intertex 28k8 33k6 Voice SP EXT PnP */ -- { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF801) }, -- /* Intertex 33k6 56k Voice SP EXT PnP */ -- { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF901) }, -- /* Kortex International */ -- /* KORTEX 28800 Externe PnP */ -- { ISAPNP_VENDOR('K', 'O', 'R'), ISAPNP_DEVICE(0x4522) }, -- /* KXPro 33.6 Vocal ASVD PnP */ -- { ISAPNP_VENDOR('K', 'O', 'R'), ISAPNP_DEVICE(0xF661) }, -- /* Lasat */ -- /* LASAT Internet 33600 PnP */ -- { ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x4040) }, -- /* Lasat Safire 560 PnP */ -- { ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x4540) }, -- /* Lasat Safire 336 PnP */ -- { ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x5440) }, -- /* Microcom, Inc. */ -- /* Microcom TravelPorte FAST V.34 Plug & Play */ -- { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x281) }, -- /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */ -- { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0336) }, -- /* Microcom DeskPorte FAST EP 28.8 Plug & Play */ -- { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0339) }, -- /* Microcom DeskPorte 28.8P Plug & Play */ -- { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0342) }, -- /* Microcom DeskPorte FAST ES 28.8 Plug & Play */ -- { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0500) }, -- /* Microcom DeskPorte FAST ES 28.8 Plug & Play */ -- { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0501) }, -- /* Microcom DeskPorte 28.8S Internal Plug & Play */ -- { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0502) }, -- /* Motorola */ -- /* Motorola BitSURFR Plug & Play */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1105) }, -- /* Motorola TA210 Plug & Play */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1111) }, -- /* Motorola HMTA 200 (ISDN) Plug & Play */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1114) }, -- /* Motorola BitSURFR Plug & Play */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1115) }, -- /* Motorola Lifestyle 28.8 Internal */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1190) }, -- /* Motorola V.3400 Plug & Play */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1501) }, -- /* Motorola Lifestyle 28.8 V.34 Plug & Play */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1502) }, -- /* Motorola Power 28.8 V.34 Plug & Play */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1505) }, -- /* Motorola ModemSURFR External 28.8 Plug & Play */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1509) }, -- /* Motorola Premier 33.6 Desktop Plug & Play */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x150A) }, -- /* Motorola VoiceSURFR 56K External PnP */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x150F) }, -- /* Motorola ModemSURFR 56K External PnP */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1510) }, -- /* Motorola ModemSURFR 56K Internal PnP */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1550) }, -- /* Motorola ModemSURFR Internal 28.8 Plug & Play */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1560) }, -- /* Motorola Premier 33.6 Internal Plug & Play */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1580) }, -- /* Motorola OnlineSURFR 28.8 Internal Plug & Play */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x15B0) }, -- /* Motorola VoiceSURFR 56K Internal PnP */ -- { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x15F0) }, -- /* Com 1 */ -- /* Deskline K56 Phone System PnP */ -- { ISAPNP_VENDOR('M', 'V', 'X'), ISAPNP_DEVICE(0x00A1) }, -- /* PC Rider K56 Phone System PnP */ -- { ISAPNP_VENDOR('M', 'V', 'X'), ISAPNP_DEVICE(0x00F2) }, -- /* Pace 56 Voice Internal Plug & Play Modem */ -- { ISAPNP_VENDOR('P', 'M', 'C'), ISAPNP_DEVICE(0x2430) }, -- /* Generic */ -- /* Generic standard PC COM port */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0500) }, -- /* Generic 16550A-compatible COM port */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0501) }, -- /* Compaq 14400 Modem */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC000) }, -- /* Compaq 2400/9600 Modem */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC001) }, -- /* Dial-Up Networking Serial Cable between 2 PCs */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC031) }, -- /* Dial-Up Networking Parallel Cable between 2 PCs */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC032) }, -- /* Standard 9600 bps Modem */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC100) }, -- /* Standard 14400 bps Modem */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC101) }, -- /* Standard 28800 bps Modem*/ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC102) }, -- /* Standard Modem*/ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC103) }, -- /* Standard 9600 bps Modem*/ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC104) }, -- /* Standard 14400 bps Modem*/ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC105) }, -- /* Standard 28800 bps Modem*/ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC106) }, -- /* Standard Modem */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC107) }, -- /* Standard 9600 bps Modem */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC108) }, -- /* Standard 14400 bps Modem */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC109) }, -- /* Standard 28800 bps Modem */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10A) }, -- /* Standard Modem */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10B) }, -- /* Standard 9600 bps Modem */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10C) }, -- /* Standard 14400 bps Modem */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10D) }, -- /* Standard 28800 bps Modem */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10E) }, -- /* Standard Modem */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10F) }, -- /* Standard PCMCIA Card Modem */ -- { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x2000) }, -- /* Rockwell */ -- /* Modular Technology */ -- /* Rockwell 33.6 DPF Internal PnP */ -- /* Modular Technology 33.6 Internal PnP */ -- { ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x0030) }, -- /* Kortex International */ -- /* KORTEX 14400 Externe PnP */ -- { ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x0100) }, -- /* Viking Components, Inc */ -- /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */ -- { ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x4920) }, -- /* Rockwell */ -- /* British Telecom */ -- /* Modular Technology */ -- /* Rockwell 33.6 DPF External PnP */ -- /* BT Prologue 33.6 External PnP */ -- /* Modular Technology 33.6 External PnP */ -- { ISAPNP_VENDOR('R', 'S', 'S'), ISAPNP_DEVICE(0x00A0) }, -- /* Viking 56K FAX INT */ -- { ISAPNP_VENDOR('R', 'S', 'S'), ISAPNP_DEVICE(0x0262) }, -- /* SupraExpress 28.8 Data/Fax PnP modem */ -- { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1310) }, -- /* SupraExpress 33.6 Data/Fax PnP modem */ -- { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1421) }, -- /* SupraExpress 33.6 Data/Fax PnP modem */ -- { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1590) }, -- /* SupraExpress 33.6 Data/Fax PnP modem */ -- { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1760) }, -- /* Phoebe Micro */ -- /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */ -- { ISAPNP_VENDOR('T', 'E', 'X'), ISAPNP_DEVICE(0x0011) }, -- /* Archtek America Corp. */ -- /* Archtek SmartLink Modem 3334BT Plug & Play */ -- { ISAPNP_VENDOR('U', 'A', 'C'), ISAPNP_DEVICE(0x000F) }, -- /* 3Com Corp. */ -- /* Gateway Telepath IIvi 33.6 */ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0000) }, -- /* Sportster Vi 14.4 PnP FAX Voicemail */ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0004) }, -- /* U.S. Robotics 33.6K Voice INT PnP */ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0006) }, -- /* U.S. Robotics 33.6K Voice EXT PnP */ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0007) }, -- /* U.S. Robotics 33.6K Voice INT PnP */ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2002) }, -- /* U.S. Robotics 56K Voice INT PnP */ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2070) }, -- /* U.S. Robotics 56K Voice EXT PnP */ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2080) }, -- /* U.S. Robotics 56K FAX INT */ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3031) }, -- /* U.S. Robotics 56K Voice INT PnP */ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3070) }, -- /* U.S. Robotics 56K Voice EXT PnP */ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3080) }, -- /* U.S. Robotics 56K Voice INT PnP */ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3090) }, -- /* U.S. Robotics 56K Message */ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9100) }, -- /* U.S. Robotics 56K FAX EXT PnP*/ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9160) }, -- /* U.S. Robotics 56K FAX INT PnP*/ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9170) }, -- /* U.S. Robotics 56K Voice EXT PnP*/ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9180) }, -- /* U.S. Robotics 56K Voice INT PnP*/ -- { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9190) }, -- { 0, } --}; -- --static inline void avoid_irq_share(struct pci_dev *dev) --{ -- int i, map = 0x1FF8; -- struct serial_state *state = rs_table; -- struct isapnp_irq *irq; -- struct isapnp_resources *res = dev->sysdata; -- -- for (i = 0; i < NR_PORTS; i++) { -- if (state->type != PORT_UNKNOWN) -- clear_bit(state->irq, &map); -- state++; -- } -- -- for ( ; res; res = res->alt) -- for(irq = res->irq; irq; irq = irq->next) -- irq->map = map; --} -- --static char *modem_names[] __devinitdata = { -- "MODEM", "Modem", "modem", "FAX", "Fax", "fax", -- "56K", "56k", "K56", "33.6", "28.8", "14.4", -- "33,600", "28,800", "14,400", "33.600", "28.800", "14.400", -- "33600", "28800", "14400", "V.90", "V.34", "V.32", 0 --}; -- --static int __devinit check_name(char *name) --{ -- char **tmp = modem_names; -- -- while (*tmp) { -- if (strstr(name, *tmp)) -- return 1; -- tmp++; -+ if (!request_mem_region(RAMSES_UARTC_PHYS, 16*4, "Ramses UART C")) -+ printk(KERN_ERR "unable to reserve region\n"); -+ else { -+ ramses_uartc = ioremap_nocache(RAMSES_UARTC_PHYS, 16*4); -+ if (!ramses_uartc) -+ printk(KERN_ERR "unable to map region\n"); -+ else { -+ //printk("ramses_uartc cookie is: %08x\n", (unsigned int) ramses_uartc); -+ rs_table[5].iomem_base = ramses_uartc; - } -- return 0; --} -- --static inline int check_compatible_id(struct pci_dev *dev) --{ -- int i; -- for (i = 0; i < DEVICE_COUNT_COMPATIBLE; i++) -- if ((dev->vendor_compatible[i] == -- ISAPNP_VENDOR('P', 'N', 'P')) && -- (swab16(dev->device_compatible[i]) >= 0xc000) && -- (swab16(dev->device_compatible[i]) <= 0xdfff)) -- return 0; -- return 1; --} -- --/* -- * Given a complete unknown ISA PnP device, try to use some heuristics to -- * detect modems. Currently use such heuristic set: -- * - dev->name or dev->bus->name must contain "modem" substring; -- * - device must have only one IO region (8 byte long) with base adress -- * 0x2e8, 0x3e8, 0x2f8 or 0x3f8. -- * -- * Such detection looks very ugly, but can detect at least some of numerous -- * ISA PnP modems, alternatively we must hardcode all modems in pnp_devices[] -- * table. -- */ --static int _INLINE_ serial_pnp_guess_board(struct pci_dev *dev, -- struct pci_board *board) --{ -- struct isapnp_resources *res = (struct isapnp_resources *)dev->sysdata; -- struct isapnp_resources *resa; -- -- if (!(check_name(dev->name) || check_name(dev->bus->name)) && -- !(check_compatible_id(dev))) -- return 1; -- -- if (!res || res->next) -- return 1; -- -- for (resa = res->alt; resa; resa = resa->alt) { -- struct isapnp_port *port; -- for (port = res->port; port; port = port->next) -- if ((port->size == 8) && -- ((port->min == 0x2f8) || -- (port->min == 0x3f8) || -- (port->min == 0x2e8) || -- (port->min == 0x3e8))) -- return 0; - } -- -- return 1; --} -- --static void __devinit probe_serial_pnp(void) --{ -- struct pci_dev *dev = NULL; -- struct pnp_board *pnp_board; -- struct pci_board board; -- --#ifdef SERIAL_DEBUG_PNP -- printk("Entered probe_serial_pnp()\n"); --#endif -- if (!isapnp_present()) { --#ifdef SERIAL_DEBUG_PNP -- printk("Leaving probe_serial_pnp() (no isapnp)\n"); --#endif -- return; -+ if (!request_mem_region(RAMSES_UARTD_PHYS, 16*4, "Ramses UART D")) -+ printk(KERN_ERR "unable to reserve region\n"); -+ else { -+ ramses_uartd = ioremap_nocache(RAMSES_UARTD_PHYS, 16*4); -+ if (!ramses_uartd) -+ printk(KERN_ERR "unable to map region\n"); -+ else { -+ //printk("ramses_uartd cookie is: %08x\n", (unsigned int) ramses_uartd); -+ rs_table[6].iomem_base = ramses_uartd; - } -- -- isapnp_for_each_dev(dev) { -- if (dev->active) -- continue; -- -- memset(&board, 0, sizeof(board)); -- board.flags = SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT; -- board.num_ports = 1; -- board.base_baud = 115200; -- -- for (pnp_board = pnp_devices; pnp_board->vendor; pnp_board++) -- if ((dev->vendor == pnp_board->vendor) && -- (dev->device == pnp_board->device)) -- break; -- -- if (pnp_board->vendor) { -- /* Special case that's more efficient to hardcode */ -- if ((pnp_board->vendor == ISAPNP_VENDOR('A', 'K', 'Y') && -- pnp_board->device == ISAPNP_DEVICE(0x1021))) -- board.flags |= SPCI_FL_NO_SHIRQ; -- } else { -- if (serial_pnp_guess_board(dev, &board)) -- continue; - } -- -- if (board.flags & SPCI_FL_NO_SHIRQ) -- avoid_irq_share(dev); -- start_pci_pnp_board(dev, &board); -- } -- --#ifdef SERIAL_DEBUG_PNP -- printk("Leaving probe_serial_pnp() (probe finished)\n"); --#endif -- return; --} -- --#endif /* ENABLE_SERIAL_PNP */ -- --/* -- * The serial driver boot-time initialization code! -- */ --static int __init rs_init(void) --{ -- int i; -- struct serial_state * state; -- - init_bh(SERIAL_BH, do_serial_bh); - init_timer(&serial_timer); - serial_timer.function = rs_timer; -@@ -5463,10 +2723,6 @@ - for (i = 0; i < NR_IRQS; i++) { - IRQ_ports[i] = 0; - IRQ_timeout[i] = 0; --#ifdef CONFIG_SERIAL_MULTIPORT -- memset(&rs_multiport[i], 0, -- sizeof(struct rs_multiport_struct)); --#endif - } - #ifdef CONFIG_SERIAL_CONSOLE - /* -@@ -5480,29 +2736,25 @@ - rs_table[i].irq = 0; - } - #endif -- show_serial_version(); -- - /* Initialize the tty_driver structure */ - - memset(&serial_driver, 0, sizeof(struct tty_driver)); - serial_driver.magic = TTY_DRIVER_MAGIC; --#if (LINUX_VERSION_CODE > 0x20100) - serial_driver.driver_name = "serial"; --#endif --#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) -+#if defined(CONFIG_DEVFS_FS) - serial_driver.name = "tts/%d"; - #else - serial_driver.name = "ttyS"; - #endif - serial_driver.major = TTY_MAJOR; -- serial_driver.minor_start = 64 + SERIAL_DEV_OFFSET; -- serial_driver.name_base = SERIAL_DEV_OFFSET; -+ serial_driver.minor_start = 64; -+ serial_driver.name_base = 0; - serial_driver.num = NR_PORTS; - serial_driver.type = TTY_DRIVER_TYPE_SERIAL; - serial_driver.subtype = SERIAL_TYPE_NORMAL; - serial_driver.init_termios = tty_std_termios; - serial_driver.init_termios.c_cflag = -- B9600 | CS8 | CREAD | HUPCL | CLOCAL; -+ B115200 | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; - serial_driver.refcount = &serial_refcount; - serial_driver.table = serial_table; -@@ -5524,31 +2776,25 @@ - serial_driver.stop = rs_stop; - serial_driver.start = rs_start; - serial_driver.hangup = rs_hangup; --#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */ - serial_driver.break_ctl = rs_break; --#endif --#if (LINUX_VERSION_CODE >= 131343) - serial_driver.send_xchar = rs_send_xchar; - serial_driver.wait_until_sent = rs_wait_until_sent; - serial_driver.read_proc = rs_read_proc; --#endif - - /* - * The callout device is just like normal device except for - * major number and the subtype code. - */ - callout_driver = serial_driver; --#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) -+#if defined(CONFIG_DEVFS_FS) - callout_driver.name = "cua/%d"; - #else - callout_driver.name = "cua"; - #endif - callout_driver.major = TTYAUX_MAJOR; - callout_driver.subtype = SERIAL_TYPE_CALLOUT; --#if (LINUX_VERSION_CODE >= 131343) - callout_driver.read_proc = 0; - callout_driver.proc_entry = 0; --#endif - - if (tty_register_driver(&serial_driver)) - panic("Couldn't register serial driver\n"); -@@ -5569,53 +2815,23 @@ - state->icount.frame = state->icount.parity = 0; - state->icount.overrun = state->icount.brk = 0; - state->irq = irq_cannonicalize(state->irq); -- if (state->hub6) -- state->io_type = SERIAL_IO_HUB6; - if (state->port && check_region(state->port,8)) { - state->type = PORT_UNKNOWN; - continue; - } --#ifdef CONFIG_MCA -- if ((state->flags & ASYNC_BOOT_ONLYMCA) && !MCA_bus) -- continue; --#endif -- if (state->flags & ASYNC_BOOT_AUTOCONF) { -- state->type = PORT_UNKNOWN; -- autoconfig(state); -- } - } - for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { - if (state->type == PORT_UNKNOWN) - continue; -- if ( (state->flags & ASYNC_BOOT_AUTOCONF) -- && (state->flags & ASYNC_AUTO_IRQ) -- && (state->port != 0 || state->iomem_base != 0)) -- state->irq = detect_uart_irq(state); -- if (state->io_type == SERIAL_IO_MEM) { -- printk(KERN_INFO"ttyS%02d%s at 0x%p (irq = %d) is a %s\n", -- state->line + SERIAL_DEV_OFFSET, -- (state->flags & ASYNC_FOURPORT) ? " FourPort" : "", -- state->iomem_base, state->irq, -- uart_config[state->type].name); -- } -- else { -- printk(KERN_INFO "ttyS%02d%s at 0x%04lx (irq = %d) is a %s\n", -- state->line + SERIAL_DEV_OFFSET, -- (state->flags & ASYNC_FOURPORT) ? " FourPort" : "", -- state->port, state->irq, -+ printk(KERN_INFO"tts/%d at irq %d is a %s\n", -+ state->line, -+ state->irq, - uart_config[state->type].name); -- } - tty_register_devfs(&serial_driver, 0, - serial_driver.minor_start + state->line); - tty_register_devfs(&callout_driver, 0, - callout_driver.minor_start + state->line); - } --#ifdef ENABLE_SERIAL_PCI -- probe_serial_pci(); --#endif --#ifdef ENABLE_SERIAL_PNP -- probe_serial_pnp(); --#endif - return 0; - } - -@@ -5627,6 +2843,8 @@ - { - int i = req->line; - -+ printk("%s\n", __FUNCTION__); -+ - if (i >= NR_IRQS) - return(-ENOENT); - rs_table[i].magic = 0; -@@ -5639,7 +2857,6 @@ - rs_table[i].flags = req->flags; - rs_table[i].close_delay = req->close_delay; - rs_table[i].io_type = req->io_type; -- rs_table[i].hub6 = req->hub6; - rs_table[i].iomem_base = req->iomem_base; - rs_table[i].iomem_reg_shift = req->iomem_reg_shift; - rs_table[i].type = req->type; -@@ -5726,7 +2943,6 @@ - info->iomem_base = req->iomem_base; - info->iomem_reg_shift = req->iomem_reg_shift; - } -- autoconfig(state); - if (state->type == PORT_UNKNOWN) { - restore_flags(flags); - printk("register_serial(): autoconfig failed\n"); -@@ -5734,11 +2950,8 @@ - } - restore_flags(flags); - -- if ((state->flags & ASYNC_AUTO_IRQ) && CONFIGURED_SERIAL_PORT(state)) -- state->irq = detect_uart_irq(state); -- - printk(KERN_INFO "ttyS%02d at %s 0x%04lx (irq = %d) is a %s\n", -- state->line + SERIAL_DEV_OFFSET, -+ state->line, - state->iomem_base ? "iomem" : "port", - state->iomem_base ? (unsigned long)state->iomem_base : - state->port, state->irq, uart_config[state->type].name); -@@ -5746,7 +2959,7 @@ - serial_driver.minor_start + state->line); - tty_register_devfs(&callout_driver, 0, - callout_driver.minor_start + state->line); -- return state->line + SERIAL_DEV_OFFSET; -+ return state->line; - } - - /** -@@ -5785,7 +2998,6 @@ - int i; - struct async_struct *info; - -- /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ - del_timer_sync(&serial_timer); - save_flags(flags); cli(); - remove_bh(SERIAL_BH); -@@ -5803,41 +3015,31 @@ - kfree(info); - } - if ((rs_table[i].type != PORT_UNKNOWN) && rs_table[i].port) { --#ifdef CONFIG_SERIAL_RSA -- if (rs_table[i].type == PORT_RSA) -- release_region(rs_table[i].port + -- UART_RSA_BASE, 16); -- else --#endif - release_region(rs_table[i].port, 8); - } --#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP) -- if (rs_table[i].iomem_base) -- iounmap(rs_table[i].iomem_base); --#endif -- } --#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP) -- for (i=0; i < NR_PCI_BOARDS; i++) { -- struct pci_board_inst *brd = &serial_pci_board[i]; -- -- if (serial_pci_board[i].dev == 0) -- continue; -- if (brd->board.init_fn) -- (brd->board.init_fn)(brd->dev, &brd->board, 0); -- if (DEACTIVATE_FUNC(brd->dev)) -- (DEACTIVATE_FUNC(brd->dev))(brd->dev); - } --#endif - if (tmp_buf) { - unsigned long pg = (unsigned long) tmp_buf; - tmp_buf = NULL; - free_page(pg); - } - --#ifdef ENABLE_SERIAL_PCI -- if (serial_pci_driver.name[0]) -- pci_unregister_driver (&serial_pci_driver); --#endif -+ if (ramses_uarta) { -+ iounmap(ramses_uarta); -+ release_mem_region(RAMSES_UARTA_PHYS, 16*4); -+ } -+ if (ramses_uartb) { -+ iounmap(ramses_uartb); -+ release_mem_region(RAMSES_UARTB_PHYS, 16*4); -+ } -+ if (ramses_uartc) { -+ iounmap(ramses_uartc); -+ release_mem_region(RAMSES_UARTC_PHYS, 16*4); -+ } -+ if (ramses_uartd) { -+ iounmap(ramses_uartd); -+ release_mem_region(RAMSES_UARTD_PHYS, 16*4); -+ } - } - - module_init(rs_init); -@@ -5946,7 +3148,7 @@ - static struct async_struct *info; - struct serial_state *state; - unsigned cval; -- int baud = 9600; -+ int baud = 115200; - int bits = 8; - int parity = 'n'; - int doflow = 0; -@@ -5954,6 +3156,8 @@ - int quot = 0; - char *s; - -+ printk("%s\n", __FUNCTION__); -+ - if (options) { - baud = simple_strtoul(options, NULL, 10); - s = options; -@@ -6028,19 +3232,12 @@ - info->state = state; - info->port = state->port; - info->flags = state->flags; --#ifdef CONFIG_HUB6 -- info->hub6 = state->hub6; --#endif - info->io_type = state->io_type; - info->iomem_base = state->iomem_base; - info->iomem_reg_shift = state->iomem_reg_shift; - quot = state->baud_base / baud; - cval = cflag & (CSIZE | CSTOPB); --#if defined(__powerpc__) || defined(__alpha__) -- cval >>= 8; --#else /* !__powerpc__ && !__alpha__ */ - cval >>= 4; --#endif /* !__powerpc__ && !__alpha__ */ - if (cflag & PARENB) - cval |= UART_LCR_PARITY; - if (!(cflag & PARODD)) -@@ -6082,9 +3279,14 @@ - */ - void __init serial_console_init(void) - { -+ printk("%s\n", __FUNCTION__); -+ - register_console(&sercons); - } - #endif -+ -+EXPORT_SYMBOL(register_serial); -+EXPORT_SYMBOL(unregister_serial); - - /* - Local variables: ---- /dev/null -+++ linux-2.4.21/drivers/char/sysctl.c -@@ -0,0 +1,948 @@ -+/* -+ * /proc/sys-board - Interface to the 16 bit latch and other -+ * ramses-related hardware settings -+ * -+ * (C) 2002,2003 by M&N Logistik-Lösungen Online GmbH -+ * written by H.Schurig -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "../drivers/misc/ucb1x00.h" -+ -+//#define DEBUG -+//define CPLD_LED 1 -+//define POTI 1 -+ -+/* -+ * This is the number for the "board" entry in /proc/sys: -+ */ -+#define RAMSES_SYSCTL 1312 -+ -+/* -+ * These are the numbers for the entries in /etc/sys/board -+ */ -+enum { -+ CTL_NAME=991, -+ CTL_CPLD_VERSION, -+ CTL_BOOTLOADER_CRC, -+ CTL_LINUX_CRC, -+ CTL_LED_BLUE, -+ CTL_LED_ORANGE, -+ CTL_UART, -+ CTL_MMC, -+ CTL_POWEROFF, -+ CTL_GSM_POWER, -+ CTL_GSM_RESET, -+ CTL_SCANNER_POWER, -+ CTL_SCANNER_WAKE, -+ CTL_SCANNER_TRIG, -+ CTL_SCANNER_BEAM, -+ CTL_KEY_SCAN, -+ CTL_KEY_SUSPEND, -+ CTL_KEY_OFF, -+ CTL_USBBUS_POWER, -+ CTL_USBCHIP_POWER, -+#ifdef CPLD_LED -+ CTL_LED_CPLD, -+ CTL_LED_CPLD_RED, -+#endif -+ CTL_LCD_VCC, -+ CTL_LCD_DISPOFF, -+ CTL_LCD_BLIGHT, -+#ifdef DEBUG -+ CTL_LCD_PWM0, -+ CTL_LCD_PWM1, -+#endif -+ CTL_LCD_BRIGHTNESS, -+ CTL_LCD_CONTRAST, -+ CTL_LCD_FBTURN, -+ CTL_LCD_TYPE, -+ CTL_CONTROL_SHADOW, -+ CTL_COREVOLT, -+#ifdef POTI -+ CTL_LCD_POTI_NINC, -+ CTL_LCD_POTI_NCS, -+ CTL_LCD_POTI_UP, -+#endif -+#ifdef CONFIG_MCP_UCB1400_TS -+ CTL_ADC0, -+ CTL_ADC1, -+ CTL_ADC2, -+ CTL_ADC3, -+#else -+#error NO UCB -+#endif -+ CTL_CHG_STS, -+ CTL_WALL_IN, -+ CTL_BATT_TMP, -+ CTL_BATT_LMD, -+ CTL_BATT_VSB, -+ CTL_BATT_RCAC, -+ CTL_BATT_CACT, -+ CTL_BATT_SAE, -+ CTL_BATT_DCR, -+}; -+ -+static const char ramses_board_name[] = "ramses"; -+static int dummy_int = 0; -+static char dummy_str[80]; -+ -+ -+ -+/******************************************************************/ -+/* ADC communication */ -+/******************************************************************/ -+ -+ -+#ifdef CONFIG_MCP_UCB1400_TS -+static int adc_get(int channel) -+{ -+ int val; -+ struct ucb1x00 *ucb = ucb1x00_get(); -+ -+ ucb1x00_adc_enable(ucb); -+ val = ucb1x00_adc_read(ucb, channel, 0); -+ ucb1x00_adc_disable(ucb); -+ -+ return val; -+} -+#endif -+ -+ -+ -+static int -+ramses_sysctl_handler(ctl_table * ctl, int write, struct file *filp, -+ void *buffer, size_t * lenp) -+{ -+ int *valp = ctl->data; -+ int val; -+ int ret; -+ unsigned crc; -+ void *flash; -+ -+#ifdef DEBUG -+ printk("ramses_control_shadow: %04x\n", ramses_control_shadow); -+#endif -+ -+ // Update parameters from the real registers -+ switch (ctl->ctl_name) { -+ case CTL_CPLD_VERSION: -+ sprintf(dummy_str,"20%02ld-%02ld-%02ld.%ld\n", -+ RAMSES_CPLD_YEAR & 0xff, -+ RAMSES_CPLD_MONTH & 0xff, -+ RAMSES_CPLD_DAY & 0xff, -+ RAMSES_CPLD_REV & 0xff); -+ return proc_dostring(ctl,write,filp,buffer,lenp); -+ -+ case CTL_BOOTLOADER_CRC: -+ flash = ioremap_nocache(RAMSES_FLASH_PHYS, 0x40000); -+ crc = ether_crc_le(0x40000, flash); -+ iounmap(flash); -+ sprintf(dummy_str,"%08x", crc); -+ return proc_dostring(ctl,write,filp,buffer,lenp); -+ -+ case CTL_LINUX_CRC: -+ flash = ioremap_nocache(RAMSES_FLASH_PHYS+0x40000, 3*0x40000); -+ crc = ether_crc_le(3*0x40000, flash); -+ iounmap(flash); -+ sprintf(dummy_str,"%08x", crc); -+ return proc_dostring(ctl,write,filp,buffer,lenp); -+ -+ case CTL_LED_BLUE: -+ *valp = (ramses_control_shadow & RAMSES_CONTROL_LED_BLUE_) == 0; -+ break; -+ case CTL_LED_ORANGE: -+ *valp = (ramses_control_shadow & RAMSES_CONTROL_LED_ORANGE_) == 0; -+ break; -+ case CTL_UART: -+ *valp = (ramses_control_shadow & RAMSES_CONTROL_UART_PWR) != 0; -+ break; -+ case CTL_MMC: -+ *valp = (ramses_control_shadow & RAMSES_CONTROL_MMC_PWR) != 0; -+ break; -+ case CTL_POWEROFF: -+ *valp = 0; -+ break; -+ case CTL_GSM_POWER: -+ *valp = (ramses_control_shadow & RAMSES_CONTROL_GSM_PWR) != 0; -+ break; -+ case CTL_GSM_RESET: -+ *valp = (ramses_control_shadow & RAMSES_CONTROL_GSM_RESET) != 0; -+ break; -+ -+ case CTL_SCANNER_POWER: -+ *valp = (ramses_control_shadow & RAMSES_CONTROL_SCANNER_PWR) != 0; -+ break; -+ case CTL_SCANNER_WAKE: -+ *valp = (ramses_control_shadow & RAMSES_CONTROL_SCANNER_WAKE_) == 0; -+ break; -+ case CTL_SCANNER_TRIG: -+ *valp = (ramses_control_shadow & RAMSES_CONTROL_SCANNER_TRIG_) == 0; -+ break; -+ case CTL_SCANNER_BEAM: -+ *valp = ramses_flags & RAMSES_FLAGS_SCANNER_BEAM; -+ break; -+ -+ case CTL_KEY_SCAN: -+ *valp = (ramses_flags & RAMSES_FLAGS_KEY_SCAN) != 0; -+ break; -+ case CTL_KEY_SUSPEND: -+ *valp = (ramses_flags & RAMSES_FLAGS_KEY_SUSPEND) != 0; -+ break; -+ case CTL_KEY_OFF: -+ *valp = (ramses_flags & RAMSES_FLAGS_KEY_OFF) != 0; -+ break; -+ -+ case CTL_USBBUS_POWER: -+ *valp = (ramses_control_shadow & RAMSES_CONTROL_USB) != 0; -+ break; -+ case CTL_USBCHIP_POWER: -+ *valp = (RAMSES_CPLD_PERIPH_PWR & USB_HOST_PWR_EN) != 0; -+ break; -+#ifdef CPLD_LED -+ case CTL_LED_CPLD: -+ *valp = (RAMSES_CPLD_LED_CONTROL & CPLD_LED1) == 0; -+ break; -+ case CTL_LED_CPLD_RED: -+ *valp = (RAMSES_CPLD_LED_CONTROL & CPLD_LED2) == 0; -+ break; -+#endif -+ case CTL_LCD_BLIGHT: -+ *valp = (ramses_control_shadow & RAMSES_CONTROL_LCD_BLIGHT) != 0; -+ break; -+ case CTL_LCD_VCC: -+ *valp = (RAMSES_CPLD_LCD & RAMSES_LCD_VCC) != 0; -+ break; -+ case CTL_LCD_DISPOFF: -+ *valp = (RAMSES_CPLD_LCD & RAMSES_LCD_DISPOFF) != 0; -+ break; -+#ifdef DEBUG -+ case CTL_LCD_PWM0: -+ *valp = PWM_PWDUTY0; -+ break; -+ case CTL_LCD_PWM1: -+#ifdef OLDCODE -+ *valp = ramses_lcd_pwm1_shadow; -+#else -+ *valp = PWM_PWDUTY1; -+#endif -+ break; -+#endif -+ case CTL_LCD_BRIGHTNESS: -+ *valp = ramses_lcd_get_brightness(); -+ break; -+ case CTL_LCD_CONTRAST: -+ *valp = ramses_lcd_get_contrast(); -+ break; -+ case CTL_LCD_FBTURN: -+ *valp = (ramses_flags & RAMSES_FLAGS_LCD_FBTURN) != 0; -+ break; -+ case CTL_LCD_TYPE: -+ *valp = ramses_lcd_type; -+ break; -+ -+ case CTL_CONTROL_SHADOW: -+ sprintf(dummy_str,"%04x", ramses_control_shadow); -+ return proc_dostring(ctl,write,filp,buffer,lenp); -+ -+ case CTL_COREVOLT: -+ *valp = ramses_corevolt_shadow; -+ break; -+ -+#ifdef POTI -+ case CTL_LCD_POTI_NINC: -+ *valp = (RAMSES_CPLD_LCD & RAMSES_LCD_PINC) != 0; -+ break; -+ case CTL_LCD_POTI_NCS: -+ *valp = (RAMSES_CPLD_LCD & RAMSES_LCD_PCS) != 0; -+ break; -+ case CTL_LCD_POTI_UP: -+ *valp = (RAMSES_CPLD_LCD & RAMSES_LCD_PUP) != 0; -+ break; -+#endif -+ -+#ifdef CONFIG_MCP_UCB1400_TS -+ case CTL_ADC0: -+ *valp = adc_get(UCB_ADC_INP_AD0); -+ break; -+ case CTL_ADC1: -+ *valp = adc_get(UCB_ADC_INP_AD1); -+ break; -+ case CTL_ADC2: -+ *valp = adc_get(UCB_ADC_INP_AD2); -+ break; -+ case CTL_ADC3: -+ *valp = adc_get(UCB_ADC_INP_AD3); -+ break; -+#endif -+ -+ case CTL_CHG_STS: -+ *valp = (RAMSES_CPLD_MISC_STATUS & RAMSES_CHG_STS) == 0; -+ break; -+ case CTL_WALL_IN: -+ *valp = (RAMSES_CPLD_MISC_STATUS & RAMSES_WALL_IN) != 0; -+ break; -+ -+ case CTL_BATT_TMP: -+ *valp = ramses_hdq_get_reg(HDQ_TMP) >> 4; -+ break; -+ case CTL_BATT_LMD: -+ *valp = ramses_hdq_get_reg(HDQ_LMD); -+ break; -+ case CTL_BATT_VSB: -+ *valp = ramses_hdq_get_reg(HDQ_VSB); -+ break; -+ case CTL_BATT_RCAC: -+ *valp = ramses_hdq_get_reg(HDQ_RCAC) & 0x7f; -+ break; -+ case CTL_BATT_CACT: -+ *valp = ramses_hdq_get_reg(HDQ_CACT); -+ break; -+ case CTL_BATT_SAE: -+ *valp = ramses_hdq_get_reg(HDQ_SAEH) << 8 | ramses_hdq_get_reg(HDQ_SAEL); -+ break; -+ case CTL_BATT_DCR: -+ *valp = ramses_hdq_get_reg(HDQ_DCR); -+ break; -+ -+ default: -+ // Just ignore unsupported parameters -+ break; -+ } -+ -+ // Save old state -+ val = *valp; -+ -+ // Perform the generic integer operation -+ if ((ret = proc_dointvec(ctl, write, filp, buffer, lenp)) != 0) -+ return (ret); -+ -+ // Write changes out to the registers -+ if (write && *valp != val) { -+ -+ val = *valp; -+ switch (ctl->ctl_name) { -+ -+ case CTL_LED_BLUE: -+ if (val) -+ RAMSES_LED_BLUE_ON() -+ else -+ RAMSES_LED_BLUE_OFF(); -+ break; -+ -+ case CTL_LED_ORANGE: -+ if (val) -+ RAMSES_LED_ORANGE_ON() -+ else -+ RAMSES_LED_ORANGE_OFF(); -+ break; -+ -+ case CTL_UART: -+ if (val) -+ RAMSES_UART_ON() -+ else -+ RAMSES_UART_OFF(); -+ break; -+ -+ case CTL_MMC: -+ if (val) -+ RAMSES_MMC_ON() -+ else -+ RAMSES_MMC_OFF(); -+ break; -+ -+ case CTL_POWEROFF: -+ if (val) -+ pm_power_off(); -+ break; -+ -+ case CTL_GSM_POWER: -+ if (val) -+ RAMSES_GSM_ON() -+ else -+ RAMSES_GSM_OFF(); -+ break; -+ -+ case CTL_GSM_RESET: -+ if (val) -+ RAMSES_GSM_RESET_ON() -+ else -+ RAMSES_GSM_RESET_OFF(); -+ break; -+ -+ case CTL_SCANNER_POWER: -+ if (val) -+ RAMSES_SCANNER_ON() -+ else -+ RAMSES_SCANNER_OFF(); -+ break; -+ -+ case CTL_SCANNER_WAKE: -+ if (val) -+ RAMSES_SCANNER_WAKE_ON() -+ else -+ RAMSES_SCANNER_WAKE_OFF(); -+ break; -+ -+ case CTL_SCANNER_TRIG: -+ if (val) -+ RAMSES_SCANNER_TRIG_ON() -+ else -+ RAMSES_SCANNER_TRIG_OFF(); -+ break; -+ -+ case CTL_SCANNER_BEAM: -+ if (val) -+ ramses_flags |= RAMSES_FLAGS_SCANNER_BEAM; -+ else -+ ramses_flags &= ~RAMSES_FLAGS_SCANNER_BEAM; -+ break; -+ -+ case CTL_KEY_SCAN: -+ if (val) -+ ramses_flags |= RAMSES_FLAGS_KEY_SCAN; -+ else -+ ramses_flags &= ~RAMSES_FLAGS_KEY_SCAN; -+ break; -+ -+ case CTL_KEY_SUSPEND: -+ if (val) -+ ramses_flags |= RAMSES_FLAGS_KEY_SUSPEND; -+ else -+ ramses_flags &= ~RAMSES_FLAGS_KEY_SUSPEND; -+ break; -+ -+ case CTL_KEY_OFF: -+ if (val) -+ ramses_flags |= RAMSES_FLAGS_KEY_OFF; -+ else -+ ramses_flags &= ~RAMSES_FLAGS_KEY_OFF; -+ break; -+ -+ case CTL_USBBUS_POWER: -+ if (val) -+ RAMSES_USB_BUS_ON() -+ else -+ RAMSES_USB_BUS_OFF(); -+ break; -+ -+ case CTL_USBCHIP_POWER: -+ if (val) -+ RAMSES_CPLD_PERIPH_PWR |= USB_HOST_PWR_EN; -+ else -+ RAMSES_CPLD_PERIPH_PWR &= ~USB_HOST_PWR_EN; -+ break; -+ -+#ifdef CPLD_LED -+ case CTL_LED_CPLD: -+ if (val) -+ RAMSES_CPLD_LED_CONTROL &= ~CPLD_LED1; -+ else -+ RAMSES_CPLD_LED_CONTROL |= CPLD_LED1; -+ break; -+ -+ case CTL_LED_CPLD_RED: -+ if (val) -+ RAMSES_CPLD_LED_CONTROL &= ~CPLD_LED2; -+ else -+ RAMSES_CPLD_LED_CONTROL |= CPLD_LED2; -+ break; -+#endif -+ -+ case CTL_LCD_BLIGHT: -+ if (val) -+ ramses_lcd_backlight_on(); -+ else -+ ramses_lcd_backlight_off(); -+ break; -+ -+ case CTL_LCD_VCC: -+ if (val) -+ RAMSES_CPLD_LCD |= RAMSES_LCD_VCC; -+ else -+ RAMSES_CPLD_LCD &= ~RAMSES_LCD_VCC; -+ break; -+ -+ case CTL_LCD_DISPOFF: -+ if (val) -+ RAMSES_CPLD_LCD |= RAMSES_LCD_DISPOFF; -+ else -+ RAMSES_CPLD_LCD &= ~RAMSES_LCD_DISPOFF; -+ break; -+ -+#ifdef DEBUG -+ case CTL_LCD_PWM0: -+ PWM_PWDUTY0 = val; -+ break; -+ -+ case CTL_LCD_PWM1: -+#ifdef OLDCODE -+ ramses_lcd_set_pwm1(val); -+#else -+ PWM_PWDUTY1 = val; -+#endif -+ break; -+#endif -+ -+ case CTL_LCD_BRIGHTNESS: -+ ramses_lcd_set_brightness(val); -+ break; -+ -+ case CTL_LCD_CONTRAST: -+ ramses_lcd_set_contrast(val); -+ break; -+ -+ case CTL_LCD_FBTURN: -+ if (val) -+ ramses_flags |= RAMSES_FLAGS_LCD_FBTURN; -+ else -+ ramses_flags &= ~RAMSES_FLAGS_LCD_FBTURN; -+ break; -+ -+ case CTL_COREVOLT: -+ ramses_set_corevolt(val); -+ break; -+ -+#ifdef POTI -+ case CTL_LCD_POTI_NCS: -+ if (val) -+ RAMSES_CPLD_LCD |= RAMSES_LCD_PCS; -+ else -+ RAMSES_CPLD_LCD &= ~RAMSES_LCD_PCS; -+ break; -+ case CTL_LCD_POTI_NINC: -+ if (val) -+ RAMSES_CPLD_LCD |= RAMSES_LCD_PINC; -+ else -+ RAMSES_CPLD_LCD &= ~RAMSES_LCD_PINC; -+ break; -+ case CTL_LCD_POTI_UP: -+ if (val) -+ RAMSES_CPLD_LCD |= RAMSES_LCD_PUP; -+ else -+ RAMSES_CPLD_LCD &= ~RAMSES_LCD_PUP; -+ break; -+#endif -+ -+ default: -+ // Just ignore unsupported parameters -+ break; -+ } -+ } -+ -+#ifdef DEBUG -+ printk("ramses_control_shadow new: %04x\n", ramses_control_shadow); -+#endif -+ return ret; -+} -+ -+ -+ -+static ctl_table ramses_table[] = { -+ { -+ procname: "sys_name", -+ ctl_name: CTL_NAME, -+ data: &ramses_board_name, -+ maxlen: sizeof(ramses_board_name), -+ proc_handler: &proc_dostring, -+ mode: 0444, // read-only -+ }, { -+ procname: "sys_cpldver", -+ ctl_name: CTL_CPLD_VERSION, -+ data: &dummy_str, -+ maxlen: sizeof(dummy_str), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, // read-only -+ }, { -+ procname: "sys_bootcrc", -+ ctl_name: CTL_BOOTLOADER_CRC, -+ data: &dummy_str, -+ maxlen: sizeof(dummy_str), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, // read-only -+ }, { -+ procname: "sys_linuxcrc", -+ ctl_name: CTL_LINUX_CRC, -+ data: &dummy_str, -+ maxlen: sizeof(dummy_str), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, // read-only -+ }, { -+ procname: "led_blue", -+ ctl_name: CTL_LED_BLUE, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "led_orange", -+ ctl_name: CTL_LED_ORANGE, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "pwr_uart", -+ ctl_name: CTL_UART, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "pwr_mmc", -+ ctl_name: CTL_MMC, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "pwr_off", -+ ctl_name: CTL_POWEROFF, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "gsm_power", -+ ctl_name: CTL_GSM_POWER, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "gsm_reset", -+ ctl_name: CTL_GSM_RESET, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "scanner_power", -+ ctl_name: CTL_SCANNER_POWER, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "scanner_wake", -+ ctl_name: CTL_SCANNER_WAKE, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "scanner_trig", -+ ctl_name: CTL_SCANNER_TRIG, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "scanner_beam", -+ ctl_name: CTL_SCANNER_BEAM, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "key_scan", -+ ctl_name: CTL_KEY_SCAN, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "key_suspend", -+ ctl_name: CTL_KEY_SUSPEND, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "key_off", -+ ctl_name: CTL_KEY_OFF, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "usb_bus_power", -+ ctl_name: CTL_USBBUS_POWER, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "usb_chip_power", -+ ctl_name: CTL_USBCHIP_POWER, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, -+#if LED_CPLD -+ { -+ procname: "led_cpld", -+ ctl_name: CTL_LED_CPLD, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "led_cpld_red", -+ ctl_name: CTL_LED_CPLD_RED, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, -+#endif -+ { -+ procname: "lcd_backlight", -+ ctl_name: CTL_LCD_BLIGHT, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "lcd_vcc", -+ ctl_name: CTL_LCD_VCC, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "lcd_dispoff", -+ ctl_name: CTL_LCD_DISPOFF, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "lcd_brightness", -+ ctl_name: CTL_LCD_BRIGHTNESS, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "lcd_contrast", -+ ctl_name: CTL_LCD_CONTRAST, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "lcd_fbturn", -+ ctl_name: CTL_LCD_FBTURN, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "lcd_type", -+ ctl_name: CTL_LCD_TYPE, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, -+ }, -+#ifdef POTI -+ { -+ procname: "lcd_poti_ncs", -+ ctl_name: CTL_LCD_POTI_NCS, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "lcd_poti_ninc", -+ ctl_name: CTL_LCD_POTI_NINC, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "lcd_poti_up", -+ ctl_name: CTL_LCD_POTI_UP, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, -+#endif -+#ifdef DEBUG -+ { -+ procname: "lcd_pwm0", -+ ctl_name: CTL_LCD_PWM0, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, { -+ procname: "lcd_pwm1", -+ ctl_name: CTL_LCD_PWM1, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, -+#endif -+ { -+ procname: "sys_shadowreg", -+ ctl_name: CTL_CONTROL_SHADOW, -+ data: &dummy_str, -+ maxlen: sizeof(dummy_str), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, -+ }, -+ { -+ procname: "pwr_corevolt", -+ ctl_name: CTL_COREVOLT, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0664, -+ }, -+#ifdef CONFIG_MCP_UCB1400_TS -+ { -+ procname: "adc0_vcc", -+ ctl_name: CTL_ADC0, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, -+ }, { -+ procname: "adc1_ntc", -+ ctl_name: CTL_ADC1, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, -+ }, { -+ procname: "adc2_goldcap", -+ ctl_name: CTL_ADC2, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, -+ }, { -+ procname: "adc3_batt", -+ ctl_name: CTL_ADC3, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, -+ }, -+#else -+#error No UCB -+#endif -+ { -+ procname: "pwr_wall_in", -+ ctl_name: CTL_WALL_IN, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, -+ }, { -+ procname: "batt_charge", -+ ctl_name: CTL_CHG_STS, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, -+ }, { -+ procname: "batt_temp", -+ ctl_name: CTL_BATT_TMP, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, -+ }, { -+ procname: "batt_lmd", -+ ctl_name: CTL_BATT_LMD, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, -+ }, { -+ procname: "batt_vsb", -+ ctl_name: CTL_BATT_VSB, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, -+ }, { -+ procname: "batt_rcac", -+ ctl_name: CTL_BATT_RCAC, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, -+ }, { -+ procname: "batt_cact", -+ ctl_name: CTL_BATT_CACT, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, -+ }, { -+ procname: "batt_sae", -+ ctl_name: CTL_BATT_SAE, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, -+ }, { -+ procname: "batt_dcr", -+ ctl_name: CTL_BATT_DCR, -+ data: &dummy_int, -+ maxlen: sizeof(int), -+ proc_handler: &ramses_sysctl_handler, -+ mode: 0444, -+ }, -+ -+ {0} -+ }; -+ -+static ctl_table ramses_root_table[] = { -+ {RAMSES_SYSCTL, "board", NULL, 0, 0555, ramses_table}, -+ {0} -+ }; -+ -+ -+static struct ctl_table_header *ramses_table_header; -+ -+ -+static int __init ramses_sysctl_init(void) -+{ -+ ramses_table_header = register_sysctl_table(ramses_root_table, 0); -+ if (!ramses_table_header) -+ return -ENOMEM; -+ return 0; -+} -+ -+static void __exit ramses_sysctl_exit(void) -+{ -+ unregister_sysctl_table(ramses_table_header); -+} -+ -+ -+module_init(ramses_sysctl_init); -+module_exit(ramses_sysctl_exit); -+ -+MODULE_AUTHOR("Holger Schurig "); -+MODULE_DESCRIPTION("Implements /proc/sys/board"); -+MODULE_LICENSE("GPL"); ---- linux-2.4.21/drivers/char/vt.c~linux-vtcomparison -+++ linux-2.4.21/drivers/char/vt.c -@@ -163,7 +163,9 @@ - - if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry))) - return -EFAULT; -- if (i >= NR_KEYS || s >= MAX_NR_KEYMAPS) -+ if (i >= NR_KEYS) -+ return -EINVAL; -+ if (s >= MAX_NR_KEYMAPS) - return -EINVAL; - - switch (cmd) { ---- linux-2.4.21/drivers/input/Config.in~keyb-input -+++ linux-2.4.21/drivers/input/Config.in -@@ -7,6 +7,8 @@ - - tristate 'Input core support' CONFIG_INPUT - dep_tristate ' Keyboard support' CONFIG_INPUT_KEYBDEV $CONFIG_INPUT -+dep_tristate ' Ramses keyboard' CONFIG_INPUT_RAMSES_KEYB $CONFIG_INPUT_KEYBDEV $CONFIG_ARCH_RAMSES -+dep_tristate ' Ramses wedge' CONFIG_INPUT_RAMSES_WEDGE $CONFIG_INPUT_RAMSES_KEYB - dep_tristate ' Mouse support' CONFIG_INPUT_MOUSEDEV $CONFIG_INPUT - if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then - int ' Horizontal screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024 ---- linux-2.4.21/drivers/input/Makefile~ramses-keyb -+++ linux-2.4.21/drivers/input/Makefile -@@ -8,7 +8,7 @@ - - # Objects that export symbols. - --export-objs := input.o -+export-objs := input.o ramses_keyb.o - - # Object file lists. - -@@ -21,10 +21,12 @@ - - obj-$(CONFIG_INPUT) += input.o - obj-$(CONFIG_INPUT_KEYBDEV) += keybdev.o -+obj-$(CONFIG_INPUT_RAMSES_KEYB) += ramses_keyb.o - obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o - obj-$(CONFIG_INPUT_JOYDEV) += joydev.o - obj-$(CONFIG_INPUT_EVDEV) += evdev.o - obj-$(CONFIG_INPUT_MX1TS) += mx1ts.o -+obj-$(CONFIG_INPUT_RAMSES_WEDGE) += wedge.o - - # The global Rules.make. - ---- /dev/null -+++ linux-2.4.21/drivers/input/ramses_cellmap.h -@@ -0,0 +1,34 @@ -+static int ramses_cellmap[][8] = { -+ { KEY_A, KEY_B, KEY_C, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 0 -+ { KEY_D, KEY_E, KEY_F, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 1 -+ { KEY_G, KEY_H, KEY_I, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 2 -+ { KEY_J, KEY_K, KEY_L, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 3 -+ { KEY_M, KEY_N, KEY_O, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 4 -+ { KEY_P, KEY_Q, KEY_R, KEY_S, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 5 -+ { KEY_T, KEY_U, KEY_V, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 6 -+ { KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 7 -+ { KEY_AE, KEY_OE, KEY_UE, KEY_SZ, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 8 -+ { KEY_sA, KEY_sB, KEY_sC, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 9 -+ { KEY_sD, KEY_sE, KEY_sF, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 10 -+ { KEY_sG, KEY_sH, KEY_sI, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 11 -+ { KEY_sJ, KEY_sK, KEY_sL, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 12 -+ { KEY_sM, KEY_sN, KEY_sO, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 13 -+ { KEY_sP, KEY_sQ, KEY_sR, KEY_sS, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 14 -+ { KEY_sT, KEY_sU, KEY_sV, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 15 -+ { KEY_sW, KEY_sX, KEY_sY, KEY_sZ, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 16 -+ { KEY_sAE, KEY_sOE, KEY_sUE, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 17 -+ { KEY_COLON, KEY_FSLASH,KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 18 -+ { KEY_SEMI, KEY_BSLASH,KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 19 -+ { KEY_COMMA, KEY_STAR, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 20 -+ { KEY_UNDERL,KEY_EQUAL, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 21 -+ { KEY_PLUS, KEY_MINUS, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 22 -+ { KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 24 -+ { KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 24 -+ { KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 25 -+ { KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 26 -+ { KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 27 -+ { KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 28 -+ { KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 29 -+ { KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 30 -+ { KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, // 31 -+}; ---- /dev/null -+++ linux-2.4.21/drivers/input/ramses_keyb.c -@@ -0,0 +1,596 @@ -+/* -+ * Keyboard driver using input layer -+ * -+ * (C) 2002,2003 by M&N Logistik-Lösungen Online GmbH -+ * written by H.Schurig -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+// Debug -+//#define DEBUG -+//#define DEBUG_DUMP_KEYSTATE -+#ifdef DEBUG -+# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args) -+# define PRINTK(fmt, args...) printk(fmt, ## args) -+#else -+# define DPRINTK(fmt, args...) -+# define PRINTK(fmt, args...) -+#endif -+ -+ -+/* -+ * Timeouts -+ */ -+#define SCANINTERVAL HZ/10 -+#define TRIGOFFINTERVAL HZ*2 -+#define CELLINTERVAL HZ+HZ/2 -+#define MAPINTERVAL 15*HZ -+#define SUSPEND_COUNTER 40 -+#define SUSPEND_LED_COUNTER 8 -+#define SUSPEND_NOW 0xffff -+#define KEYBD_MATRIX_SETTLING_TIME_US 100 -+ -+ -+/* -+ * macros for matrix keyboard driver -+ */ -+#define KEYBD_MATRIX_NUMBER_INPUTS 7 -+#define KEYBD_MATRIX_NUMBER_OUTPUTS 14 -+ -+#define KEYBD_MATRIX_SET_OUTPUTS(outputs) \ -+{\ -+ RAMSES_CPLD_KB_COL_LOW = outputs;\ -+ RAMSES_CPLD_KB_COL_HIGH = outputs >> 7;\ -+} -+ -+#define KEYBD_MATRIX_GET_INPUTS(inputs) \ -+{\ -+ inputs = (RAMSES_CPLD_KB_ROW & 0x7f);\ -+} -+ -+ -+// External functions (are they in some #include file?) -+extern int input_setkeycode(unsigned int scancode, unsigned int keycode); -+extern int input_getkeycode(unsigned int scancode); -+extern int input_translate(unsigned char scancode, unsigned char *keycode, -+ char raw_mode); -+extern char input_unexpected_up(unsigned char keycode); -+extern unsigned char input_sysrq_xlate[]; -+extern int pm_suggest_suspend(void); -+ -+// Keyboard-Related definitions -+#define KEYBD_MATRIX_INPUT_MASK ((1 << KEYBD_MATRIX_NUMBER_INPUTS)-1) -+#define KEYBD_MATRIX_OUTPUT_MASK ((1 << KEYBD_MATRIX_NUMBER_OUTPUTS)-1) -+ -+#include "ramses_scancodes.h" -+#include "ramses_keymap.h" -+#include "ramses_cellmap.h" -+ -+ -+static char *kbd_name = "Keyboard"; -+struct input_dev ramses_kbd_dev; -+static struct timer_list reenable_timer; -+static struct timer_list trigoff_timer; -+static struct tq_struct tq_suspend; -+static __u16 keystate_cur[KEYBD_MATRIX_NUMBER_OUTPUTS]; -+static __u16 keystate_prev[KEYBD_MATRIX_NUMBER_OUTPUTS]; -+static __u16 keystate_keep[KEYBD_MATRIX_NUMBER_OUTPUTS]; // used for auto-repeat -+static struct timer_list cell_timer; -+static int curr_map = MAP_NORMAL; -+static int cell_key = -1; -+static int cell_sel = -1; -+static struct pm_dev *pm_keyb; -+static int suspend_counter = 0; -+ -+ -+void ramses_key(int keycode) -+{ -+ DPRINTK("keycode: %d 0x%x\n", keycode, keycode); -+ if (KVAL(keycode)) { -+ switch (KMOD(keycode)) { -+ case KM_SHIFT: -+ DPRINTK("shift\n"); -+ input_report_key(&ramses_kbd_dev, KEY_LEFTSHIFT, 1); -+ break; -+ case KM_CTRL: -+ DPRINTK("ctrl\n"); -+ input_report_key(&ramses_kbd_dev, KEY_LEFTCTRL, 1); -+ break; -+ case KM_ALT: -+ DPRINTK("alt\n"); -+ input_report_key(&ramses_kbd_dev, KEY_LEFTALT, 1); -+ break; -+ case KM_ALTGR: -+ DPRINTK("altgr\n"); -+ input_report_key(&ramses_kbd_dev, KEY_RIGHTALT, 1); -+ break; -+ case KM_ALTCTRL: -+ DPRINTK("alt+ctrl\n"); -+ input_report_key(&ramses_kbd_dev, KEY_LEFTALT, 1); -+ input_report_key(&ramses_kbd_dev, KEY_LEFTCTRL, 1); -+ break; -+ } -+ -+ DPRINTK("report: %d 0x%x\n", KVAL(keycode), KVAL(keycode)); -+ input_report_key(&ramses_kbd_dev, KVAL(keycode), 1); -+ input_report_key(&ramses_kbd_dev, KVAL(keycode), 0); -+ -+ switch (KMOD(keycode)) { -+ case KM_SHIFT: -+ input_report_key(&ramses_kbd_dev, KEY_LEFTSHIFT, 0); -+ break; -+ case KM_CTRL: -+ input_report_key(&ramses_kbd_dev, KEY_LEFTCTRL, 0); -+ break; -+ case KM_ALT: -+ input_report_key(&ramses_kbd_dev, KEY_LEFTALT, 0); -+ break; -+ case KM_ALTGR: -+ input_report_key(&ramses_kbd_dev, KEY_RIGHTALT, 0); -+ break; -+ case KM_ALTCTRL: -+ input_report_key(&ramses_kbd_dev, KEY_LEFTALT, 0); -+ input_report_key(&ramses_kbd_dev, KEY_LEFTCTRL, 0); -+ break; -+ } -+ } -+} -+ -+static void kbd_cell_timer(unsigned long keepmap) -+{ -+ int keycode; -+ -+ if (cell_sel != -1) { -+ keycode = ramses_cellmap[cell_key][cell_sel]; -+ //DPRINTK("key: %d sel: %d keycode: %d 0x%x\n", cell_key, cell_sel, keycode, keycode); -+ ramses_key(keycode); -+ cell_sel = -1; -+ } -+ -+ if (!keepmap && curr_map!=MAP_NORMAL) { -+ DPRINTK("normal map because of %ld\n", keepmap); -+ curr_map = MAP_NORMAL; -+ RAMSES_LED_BLUE_OFF(); -+ RAMSES_LED_ORANGE_OFF(); -+ } -+} -+ -+static void kbd_setleds(void) -+{ -+ if (suspend_counter >= SUSPEND_LED_COUNTER) { -+ if (suspend_counter & 4) { -+ RAMSES_LED_ORANGE_OFF(); -+ RAMSES_LED_BLUE_ON(); -+ } else { -+ RAMSES_LED_ORANGE_ON(); -+ RAMSES_LED_BLUE_OFF(); -+ } -+ return; -+ } -+ -+ switch (curr_map) { -+ case MAP_NORMAL: -+ RAMSES_LED_BLUE_OFF(); -+ RAMSES_LED_ORANGE_OFF(); -+ return; -+ -+ case MAP_BLUE: -+ RAMSES_LED_BLUE_ON(); -+ RAMSES_LED_ORANGE_OFF(); -+ return; -+ -+ case MAP_ORANGE: -+ RAMSES_LED_BLUE_OFF(); -+ RAMSES_LED_ORANGE_ON(); -+ return; -+ -+ case MAP_CAPS: -+ RAMSES_LED_BLUE_ON(); -+ RAMSES_LED_ORANGE_ON(); -+ return; -+ } -+ DPRINTK("unknown map\n"); -+} -+ -+ -+static void kbd_start_scanner(void) -+{ -+ RAMSES_SCANNER_TRIG_OFF(); -+ RAMSES_SCANNER_WAKE_OFF(); -+ RAMSES_SCANNER_TRIG_ON(); -+ mod_timer(&trigoff_timer, jiffies + TRIGOFFINTERVAL); -+} -+ -+static void kbd_stop_scanner(unsigned long dummy) -+{ -+ RAMSES_SCANNER_TRIG_OFF(); -+} -+ -+static int kbd_dokeycode(unsigned char scancode, int down) -+{ -+ int i,keycode; -+ -+ //DPRINTK("calling with (%d,%x,%d)\n", scancode, scancode, down); -+ if (scancode >= MAX_SCANCODES) { -+ printk("%s: scancode too big for table\n", __FUNCTION__); -+ return 0; -+ } -+ -+ keycode = ramses_keymap[scancode][curr_map]; -+ -+ -+ if (keycode==KEY_SCAN) { -+ if ((ramses_flags & RAMSES_FLAGS_KEY_SCAN) == 0) -+ return 0; -+ -+ DPRINTK("scan btn\n"); -+ if (down) { -+ if (ramses_flags & RAMSES_FLAGS_SCANNER_BEAM) { -+ // just turn on laser beam -+ RAMSES_SCANNER_WAKE_ON(); -+ } else { -+ kbd_start_scanner(); -+ } -+ } else { -+ if (ramses_flags & RAMSES_FLAGS_SCANNER_BEAM) { -+ kbd_start_scanner(); -+ } else { -+ kbd_stop_scanner(0); -+ } -+ } -+ return 0; -+ } -+ -+ -+ if (keycode==KEY_SUSP) { -+ if ((ramses_flags & RAMSES_FLAGS_KEY_SUSPEND) == 0) -+ return 0; -+ -+ if (down) { -+ suspend_counter++; -+ if (suspend_counter >= SUSPEND_COUNTER) { -+ suspend_counter = SUSPEND_NOW; -+ } -+ } else { -+ if (suspend_counter == SUSPEND_NOW) { -+ curr_map = MAP_NORMAL; -+ schedule_task(&tq_suspend); -+ } -+ suspend_counter = 0; -+ } -+ return down; -+ } -+ -+ -+ if (keycode==KEY_OFF) { -+ if (down || ((ramses_flags & RAMSES_FLAGS_KEY_OFF) == 0)) -+ return 0; -+ curr_map = MAP_NORMAL; -+ ramses_shut_off(); -+ return 0; -+ } -+ -+ -+ if (!down) -+ return 0; -+ -+ -+ DPRINTK("curr_map %d scancode %d keycode %d 0x%x typ %d\n", curr_map, scancode, keycode, keycode, KMOD(keycode)); -+ -+ -+ // Cell-Phone keyboard handling -+ if (KMOD(keycode)==KM_CELL) { -+ //DPRINTK("cell phone key %d\n", KVAL(keycode)); -+ -+ // did we press a different cell-phone key as last time? -+ if (KVAL(keycode)!=cell_key) -+ kbd_cell_timer(1); -+ -+ cell_key = KVAL(keycode); // store current cell-phone key -+ cell_sel++; // increase current sub-key -+ if (ramses_cellmap[cell_key][cell_sel]==0) // if at end of sub-key list, back off -+ cell_sel = 0; -+ //DPRINTK("cell_key: %d cell_sel: %d\n", cell_key, cell_sel); -+ // auto-emit via kbd_cell_timer -+ mod_timer(&cell_timer, jiffies + CELLINTERVAL); -+ return 0; // do not revert to keys_normal -+ } -+ -+ -+ // if we pressed any other key then a cell-phone key, we look if the -+ // current half-pressed cell-phone key should be emitted -+ kbd_cell_timer(1); -+ -+ -+ switch(keycode) { -+ -+ // Keymap handling -+ -+ case KEY_NORM: -+ DPRINTK("norm key map\n"); -+ curr_map = MAP_NORMAL; -+ return 0; -+ -+ case KEY_BLUE: -+ //DPRINTK("blue key map\n"); -+ curr_map = MAP_BLUE; -+ mod_timer(&cell_timer, jiffies + MAPINTERVAL); // automatically disable keymap -+ return 0; -+ -+ case KEY_ORNG: -+ //DPRINTK("orange key map\n"); -+ curr_map = MAP_ORANGE; -+ mod_timer(&cell_timer, jiffies + MAPINTERVAL); // automatically disable keymap -+ return 0; -+ -+ case KEY_CAPS: -+ DPRINTK("caps key map\n"); -+ curr_map = MAP_CAPS; -+ mod_timer(&cell_timer, jiffies + MAPINTERVAL); // automatically disable keymap -+ return 0; -+ -+ case KEY_BRIP: -+ i = ramses_lcd_get_brightness()-6; -+ ramses_lcd_set_brightness(i); -+ mod_timer(&cell_timer, jiffies + MAPINTERVAL); // automatically disable keymap -+ return 0; -+ -+ case KEY_BRIM: -+ i = ramses_lcd_get_brightness()+6; -+ ramses_lcd_set_brightness(i); -+ mod_timer(&cell_timer, jiffies + MAPINTERVAL); // automatically disable keymap -+ return 0; -+ -+ case KEY_CTRM: -+ i = ramses_lcd_get_contrast()+3; -+ ramses_lcd_set_contrast(i); -+ mod_timer(&cell_timer, jiffies + MAPINTERVAL); // automatically disable keymap -+ return 0; -+ -+ case KEY_CTRP: -+ i = ramses_lcd_get_contrast()-3; -+ ramses_lcd_set_contrast(i); -+ mod_timer(&cell_timer, jiffies + MAPINTERVAL); // automatically disable keymap -+ return 0; -+ } -+ -+ // normal keys -+ -+ ramses_key(keycode); -+ -+ if (curr_map!=MAP_NORMAL) -+ DPRINTK("back to normal map\n"); -+ curr_map = MAP_NORMAL; -+ RAMSES_LED_BLUE_OFF(); -+ RAMSES_LED_ORANGE_OFF(); -+ return 0; -+} -+ -+ -+/** -+ * @param rescan 0 if we look for pressed keys, 1 if we look for released keys -+ * -+ * This routine get's called from the ISR (then rescan is always 0) or from -+ * the reenable_timer function (then rescan is 1). -+ */ -+static void kbd_scan_keyboard(unsigned long rescan) -+{ -+ int i,n; -+ int cols; -+ unsigned char code; -+ __u16 keystate_xor[KEYBD_MATRIX_NUMBER_OUTPUTS]; -+ -+ -+ // Find out if a key (or more) was pressed down. It's possible that -+ // because of spikes we got an interrupt, but when the IRQ service -+ // routine fired there is currently no detectable key. If this is -+ // true, then delay some times and re-try, but not too often. -+ -+ cols = 0; -+ for(n=0; n<10; n++) { -+ for (i = 0; i < KEYBD_MATRIX_NUMBER_OUTPUTS; i++) { -+ KEYBD_MATRIX_SET_OUTPUTS( 1 << i ); -+ udelay(KEYBD_MATRIX_SETTLING_TIME_US); -+ KEYBD_MATRIX_GET_INPUTS(keystate_cur[i]); -+ if (keystate_cur[i]) -+ cols++; -+ } -+ if (cols || rescan) -+ break; -+ udelay(KEYBD_MATRIX_SETTLING_TIME_US*50); -+ } -+ -+ // if rescan is true, we are in the process of turning on the IRQ. -+ // Ignore any spurious IRQ. However, if we got an IRQ but could not -+ // detect any key, we note this on the console, clear the keystate -+ // completely and make sure the IRQ gets re-enabled via the timer -+ // shortly. -+ -+ if (!cols && !rescan) { -+ printk("%s: spurious kbd int\n", __FUNCTION__); -+ for (i = 0; i < KEYBD_MATRIX_NUMBER_OUTPUTS; i++) { -+ keystate_cur[i] = 0; -+ keystate_prev[i] = 0; -+ } -+ mod_timer(&reenable_timer, jiffies + SCANINTERVAL); -+ return; -+ } -+ -+ pm_access(pm_keyb); -+ -+ // Okay, all went well. We now keystate_cur[] may contain the rows -+ // where we had keypresses, e.g. -+ // 0 0 0 2 0 0 0 0 0 0 0 0 0 0 -+ // We would see this if DEBUG_DUMP_KEYSTATE is on: -+ -+#ifdef DEBUG_DUMP_KEYSTATE -+ cols = 0; -+ for (i = 0; i < KEYBD_MATRIX_NUMBER_OUTPUTS; i++) { -+ printk("%d-%d ",keystate_cur[i], keystate_keep[i]); -+ } -+ printk("\n"); -+#endif -+ -+ cols = 0; -+ for (i = 0; i < KEYBD_MATRIX_NUMBER_OUTPUTS; i++) { -+ -+ // detect which key has changes doing an XOR of old state with new state -+ keystate_xor[i] = keystate_prev[i] ^ keystate_cur[i]; -+ //printk("%d: prev %d cur %d xor %d keep %d\n", i, keystate_prev[i], keystate_cur[i], keystate_xor[i], keystate_keep[i]); -+ -+ // some key changed, find out which one and do the scancode handling -+ if (keystate_xor[i] || keystate_keep[i]) { -+ for (n = 0; n < KEYBD_MATRIX_NUMBER_INPUTS; n++) -+ { -+ if ( (keystate_keep[i] & keystate_cur[i]) || -+ (keystate_xor[i] & (1 << n)) ) -+ { -+ int res; -+ code = n * KEYBD_MATRIX_NUMBER_OUTPUTS + i + 1; -+ res = kbd_dokeycode(code, keystate_cur[i] & (1 << n) ? 1 : 0); -+ kbd_setleds(); -+ if (res) { -+ keystate_keep[i] = 1 << n; -+ goto out; -+ } -+ } -+ } -+ } -+out: -+ keystate_prev[i] = keystate_cur[i]; -+ } -+ -+ -+ // fire reenable time if we are in the ISR -+ if (!rescan) -+ mod_timer(&reenable_timer, jiffies + SCANINTERVAL); -+} -+ -+ -+ -+static void kbd_reenable_timer(unsigned long dummy) -+{ -+ // re-scan the keyboard (to detect released keys) -+ kbd_scan_keyboard(1); -+ -+ // re-enable interrupts from the CPLD -+ KEYBD_MATRIX_SET_OUTPUTS( KEYBD_MATRIX_OUTPUT_MASK ); -+} -+ -+ -+ -+ -+ -+/** -+ * Referenced by request_irq() -+ */ -+static void kbd_interrupt(int irq, void *dummy, struct pt_regs *fp) -+{ -+ kbd_scan_keyboard(0); -+} -+ -+static void ramseskbd_suspend(void *data) -+{ -+ pm_suggest_suspend(); -+} -+ -+ -+static int __init ramseskbd_init(void) -+{ -+ int irq_gpio_pin; -+ -+ // Activate the normal pc-keycodes for the input-layer-keyboard -+ k_setkeycode = input_setkeycode; -+ k_getkeycode = input_getkeycode; -+ k_translate = input_translate; -+ k_unexpected_up = input_unexpected_up; -+#ifdef CONFIG_MAGIC_SYSRQ -+ k_sysrq_key = 0x54; -+ k_sysrq_xlate = input_sysrq_xlate; -+#endif -+ -+ // In linux-2.5.x we can do -+ // init_input_dev(&ramses_kbd_dev); -+ // but here we don't have this on linux-2.4, so we fill it with zeros: -+ memset(&ramses_kbd_dev, 0, sizeof(ramses_kbd_dev)); -+ ramses_kbd_dev.name = kbd_name; -+ -+ // which events we can produce (only keypresses): -+ ramses_kbd_dev.evbit[0] = BIT(EV_KEY); -+ -+ // which keypresses we can produce (all): -+ memset(&ramses_kbd_dev.keybit, 0xff, sizeof(ramses_kbd_dev.keybit)); -+ -+ // We set the 14 output columns to 0. This stops the CPLD to -+ // generate an IRQ before we finished our setup -+ KEYBD_MATRIX_SET_OUTPUTS(0); -+ -+ // Turn all LEDs off, meaning that we have the normal keymap active -+ RAMSES_LED_BLUE_OFF(); -+ RAMSES_LED_ORANGE_OFF(); -+ // TODO: used leds.c? -+ -+ // Now we make sure that the GPIO for our IRQ is programmed correctly -+ irq_gpio_pin = IRQ_TO_GPIO_2_80(RAMSES_KEYBOARD_IRQ); -+ GPDR(irq_gpio_pin) &= ~GPIO_bit(irq_gpio_pin); -+ set_GPIO_IRQ_edge(irq_gpio_pin, RAMSES_KEYBOARD_IRQ_EDGE); -+ request_irq(RAMSES_KEYBOARD_IRQ, kbd_interrupt, 0, kbd_name, NULL); -+ -+ // Initialize timer to re-enable IRQs. That's our method of keyboard de-prelling -+ init_timer(&reenable_timer); -+ reenable_timer.function = kbd_reenable_timer; -+ -+ init_timer(&trigoff_timer); -+ trigoff_timer.function = kbd_stop_scanner; -+ -+ // Initialize to escape the blue mode, so we emit the current cell-phone key -+ init_timer(&cell_timer); -+ cell_timer.function = kbd_cell_timer; -+ -+ tq_suspend.routine = ramseskbd_suspend; -+ -+ // Register with Power-Management -+#ifdef PM_DEBUG -+ pm_keyb = pm_register(PM_SYS_DEV, PM_SYS_KBC+1, NULL, "ramses_keyb"); -+#else -+ pm_keyb = pm_register(PM_SYS_DEV, PM_SYS_KBC+1, NULL); -+#endif -+ -+ // Register our keyboard -+ input_register_device(&ramses_kbd_dev); -+ -+ // We set the 14 output columns to 1. This allows the CPLD to -+ // generate an IRQ when one of the rows goes high -+ KEYBD_MATRIX_SET_OUTPUTS(KEYBD_MATRIX_OUTPUT_MASK); -+ -+ return 0; -+} -+ -+ -+static void __exit ramseskbd_exit(void) -+{ -+ // make IRQs impossible, return the IRQ and unregister us -+ KEYBD_MATRIX_SET_OUTPUTS(0); -+ free_irq(RAMSES_KEYBOARD_IRQ, NULL); -+ pm_unregister(pm_keyb); -+ input_unregister_device(&ramses_kbd_dev); -+} -+ -+ -+module_init(ramseskbd_init); -+module_exit(ramseskbd_exit); -+ -+MODULE_AUTHOR("Holger Schurig "); -+MODULE_DESCRIPTION("Ramses keyboard driver"); -+MODULE_LICENSE("GPL"); -+EXPORT_SYMBOL(ramses_key); -+EXPORT_SYMBOL(ramses_kbd_dev); ---- /dev/null -+++ linux-2.4.21/drivers/input/ramses_keymap.h -@@ -0,0 +1,68 @@ -+// Normal Map -+static int ramses_keymap[][6] = { -+/* Normal Blue Orange Caps Spare Spare */ -+/* 0 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 1 */ {KEY_SUSP, KEY_SUSP, KEY_SUSP, KEY_OFF, KEY_SUSP, KEY_SUSP }, -+/* 2 */ {KEY_UP, KEY_UP, KEY_PGUP, KEY_UP, KEY_noop, KEY_noop }, -+/* 3 */ {KEY_1, KEY_SPACE, KEY_BRIM, KEY_SPACE, KEY_noop, KEY_noop }, -+/* 4 */ {KEY_4, KEY_ghi , KEY_CTRM, KEY_GHI , KEY_noop, KEY_noop }, -+/* 5 */ {KEY_7, KEY_pqrs, KEY_cel7, KEY_PQRS, KEY_noop, KEY_noop }, -+/* 6 */ {KEY_DOT, KEY_uml, KEY_celP, KEY_UML, KEY_noop, KEY_noop }, -+/* 7 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 8 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 9 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 10 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 11 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 12 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 13 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 14 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 15 */ {KEY_ENTER, KEY_ENTER, KEY_ENTER, KEY_ENTER, KEY_ENTER, KEY_ENTER}, -+/* 16 */ {KEY_DOWN, KEY_DOWN, KEY_PGDN, KEY_DOWN, KEY_noop, KEY_noop }, -+/* 17 */ {KEY_2, KEY_abc , KEY_BRIP, KEY_ABC , KEY_noop, KEY_noop }, -+/* 18 */ {KEY_5, KEY_jkl , KEY_CTRP, KEY_JKL, KEY_noop, KEY_noop }, -+/* 19 */ {KEY_8, KEY_tuv , KEY_cel8, KEY_TUV, KEY_noop, KEY_noop }, -+ -+/* Normal Blue Orange Caps Spare Spare */ -+/* 20 */ {KEY_0, KEY_TAB, KEY_cel0, KEY_BTAB, KEY_noop, KEY_noop }, -+/* 21 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 22 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 23 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 24 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 25 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 26 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 27 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 28 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 29 */ {KEY_ESC, KEY_ESC, KEY_ESC, KEY_ESC, KEY_ESC, KEY_ESC }, -+/* 30 */ {KEY_RIGHT, KEY_RIGHT, KEY_END, KEY_C2, KEY_noop, KEY_noop }, -+/* 31 */ {KEY_3, KEY_def, KEY_FXIT, KEY_DEF, KEY_noop, KEY_noop }, -+/* 32 */ {KEY_6, KEY_mno , KEY_FRST, KEY_MNO, KEY_noop, KEY_noop }, -+/* 33 */ {KEY_9, KEY_wxyz, KEY_cel9, KEY_WXYZ, KEY_noop, KEY_noop }, -+/* 34 */ {KEY_BACKSPACE,KEY_ATSIGN,KEY_BAR, KEY_noop, KEY_noop, KEY_noop }, -+/* 35 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 36 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 37 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 38 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 39 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+ -+/* Normal Blue Orange Caps Spare Spare */ -+/* 40 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 41 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 42 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 43 */ {KEY_SCAN, KEY_SCAN, KEY_SCAN, KEY_SCAN, KEY_SCAN, KEY_SCAN }, -+/* 44 */ {KEY_LEFT, KEY_LEFT, KEY_HOME, KEY_C1, KEY_noop, KEY_noop }, -+/* 45 */ {KEY_OFF, KEY_OFF, KEY_OFF, KEY_OFF, KEY_OFF, KEY_OFF }, -+/* 46 */ {KEY_F1, KEY_F4, KEY_F7, KEY_F10, KEY_noop, KEY_noop }, -+/* 47 */ {KEY_F2, KEY_F5, KEY_F8, KEY_F11, KEY_noop, KEY_noop }, -+/* 48 */ {KEY_F3, KEY_F6, KEY_F9, KEY_F12, KEY_noop, KEY_noop }, -+/* 49 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 50 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 51 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 52 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 53 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 54 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 55 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 56 */ {KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop, KEY_noop }, -+/* 57 */ {KEY_SCAN, KEY_SCAN, KEY_SCAN, KEY_SCAN, KEY_SCAN, KEY_SCAN }, -+/* 58 */ {KEY_BLUE, KEY_NORM, KEY_CAPS, KEY_NORM, KEY_NORM, KEY_NORM }, -+/* 59 */ {KEY_ORNG, KEY_CAPS, KEY_NORM, KEY_NORM, KEY_NORM, KEY_NORM }, -+}; ---- /dev/null -+++ linux-2.4.21/drivers/input/ramses_scancodes.h -@@ -0,0 +1,134 @@ -+#ifndef _RAMSES_SCANCODES_H -+#define _RAMSES_SCANCODES_H -+ -+#define KMOD(a) (a & 0xff00) -+#undef KVAL -+#define KVAL(a) (a & 0x00ff) -+ -+// which modifiers to send before/after -+#define KM_SPECIAL 0x300 -+#define KM_CELL 0x400 -+#define KM_SHIFT 0x500 -+#define KM_ALT 0x600 -+#define KM_CTRL 0x700 -+#define KM_ALTGR 0x800 -+#define KM_ALTCTRL 0x900 -+ -+// or special keys -+#define KEY_noop KM_SPECIAL + 0 -+#define KEY_OFF KM_SPECIAL + 1 -+#define KEY_SUSP KM_SPECIAL + 2 -+#define KEY_SCAN KM_SPECIAL + 3 -+#define KEY_CTRM KM_SPECIAL + 4 -+#define KEY_CTRP KM_SPECIAL + 5 -+#define KEY_BRIM KM_SPECIAL + 6 -+#define KEY_BRIP KM_SPECIAL + 7 -+ -+#define KEY_NORM KM_SPECIAL + 10 -+#define KEY_BLUE KM_SPECIAL + 11 -+#define KEY_ORNG KM_SPECIAL + 12 -+#define KEY_CAPS KM_SPECIAL + 13 -+ -+ -+// our cell-phone like keys -+#define KEY_abc KM_CELL + 0 -+#define KEY_def KM_CELL + 1 -+#define KEY_ghi KM_CELL + 2 -+#define KEY_jkl KM_CELL + 3 -+#define KEY_mno KM_CELL + 4 -+#define KEY_pqrs KM_CELL + 5 -+#define KEY_tuv KM_CELL + 6 -+#define KEY_wxyz KM_CELL + 7 -+#define KEY_uml KM_CELL + 8 -+#define KEY_ABC KM_CELL + 9 -+#define KEY_DEF KM_CELL + 10 -+#define KEY_GHI KM_CELL + 11 -+#define KEY_JKL KM_CELL + 12 -+#define KEY_MNO KM_CELL + 13 -+#define KEY_PQRS KM_CELL + 14 -+#define KEY_TUV KM_CELL + 15 -+#define KEY_WXYZ KM_CELL + 16 -+#define KEY_UML KM_CELL + 17 -+#define KEY_cel7 KM_CELL + 18 -+#define KEY_cel8 KM_CELL + 19 -+#define KEY_cel9 KM_CELL + 20 -+#define KEY_celP KM_CELL + 21 -+#define KEY_cel0 KM_CELL + 22 -+ -+// Shift-Keys -+#define KEY_sA KM_SHIFT + KEY_A -+#define KEY_sB KM_SHIFT + KEY_B -+#define KEY_sC KM_SHIFT + KEY_C -+#define KEY_sD KM_SHIFT + KEY_D -+#define KEY_sE KM_SHIFT + KEY_E -+#define KEY_sF KM_SHIFT + KEY_F -+#define KEY_sG KM_SHIFT + KEY_G -+#define KEY_sH KM_SHIFT + KEY_H -+#define KEY_sI KM_SHIFT + KEY_I -+#define KEY_sJ KM_SHIFT + KEY_J -+#define KEY_sK KM_SHIFT + KEY_K -+#define KEY_sL KM_SHIFT + KEY_L -+#define KEY_sM KM_SHIFT + KEY_M -+#define KEY_sN KM_SHIFT + KEY_N -+#define KEY_sO KM_SHIFT + KEY_O -+#define KEY_sP KM_SHIFT + KEY_P -+#define KEY_sQ KM_SHIFT + KEY_Q -+#define KEY_sR KM_SHIFT + KEY_R -+#define KEY_sS KM_SHIFT + KEY_S -+#define KEY_sT KM_SHIFT + KEY_T -+#define KEY_sU KM_SHIFT + KEY_U -+#define KEY_sV KM_SHIFT + KEY_V -+#define KEY_sW KM_SHIFT + KEY_W -+#define KEY_sX KM_SHIFT + KEY_X -+#define KEY_sY KM_SHIFT + KEY_Y -+#define KEY_sZ KM_SHIFT + KEY_Z -+ -+// Umlaute -+#define KEY_sAE KM_SHIFT + 40 -+#define KEY_sOE KM_SHIFT + 39 -+#define KEY_sUE KM_SHIFT + 26 -+#define KEY_AE 40 -+#define KEY_OE 39 -+#define KEY_UE 26 -+#define KEY_SZ 12 -+ -+// AS400-Keys -+#define KEY_FRST KM_ALT + KEY_R -+#define KEY_FXIT KM_ALT + KEY_X -+ -+// Console-Switch -+#define KEY_C1 KM_ALTCTRL + KEY_F1 -+#define KEY_C2 KM_ALTCTRL + KEY_F2 -+ -+// additional keys from the german keyboard -+#undef KEY_MINUS -+#undef KEY_EQUAL -+#undef KEY_Y -+#undef KEY_Z -+#define KEY_Y 44 -+#define KEY_Z 21 -+#define KEY_STAR 55 -+#define KEY_COLON KM_SHIFT + 52 -+#define KEY_UNDERL KM_SHIFT + 53 -+#define KEY_ATSIGN KM_ALTGR + 16 -+#define KEY_BAR KM_ALTGR + 86 -+#define KEY_EQUAL KM_SHIFT + 11 -+#define KEY_SEMI KM_SHIFT + 51 -+#define KEY_BSLASH KM_ALTGR + 12 -+#define KEY_FSLASH KM_SHIFT + KEY_7 -+#define KEY_MINUS 53 -+#define KEY_PLUS 27 -+#define KEY_GAENSE KM_SHIFT + 3 -+#define KEY_PARA KM_SHIFT + 4 -+#define KEY_HASH 43 -+#define KEY_PGUP KEY_PAGEUP -+#define KEY_PGDN KEY_PAGEDOWN -+#define KEY_BTAB KM_SHIFT + KEY_TAB -+ -+#define MAP_NORMAL 0 -+#define MAP_BLUE 1 -+#define MAP_ORANGE 2 -+#define MAP_CAPS 3 -+#define MAX_SCANCODES 100 -+ -+#endif ---- /dev/null -+++ linux-2.4.21/drivers/input/wedge.c -@@ -0,0 +1,241 @@ -+/* -+ * Virtual keyboard wedge using input layer -+ * -+ * (C) 2002,2003 by M&N Logistik-Lösungen Online GmbH -+ * written by H.Schurig -+ * -+ * Creates a misc char device /dev/misc/wedge. Any output to this -+ * device will be translated (via a german keyboard map) into scancodes -+ * and re-submitted into the keyboard channel. Any console, X-Windows -+ * or Qt/Embedded application will be able to receive this info. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+ -+// Debug -+//#define DEBUG 1 -+#ifdef DEBUG -+# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args) -+# define PRINTK(fmt, args...) printk(fmt, ## args) -+#else -+# define DPRINTK(fmt, args...) -+# define PRINTK(fmt, args...) -+#endif -+ -+ -+// Defines -+#define KBD_STUFF_MAX_BYTES 512 -+ -+// Für den IOCTL -+#define WEDGE_RAWKEY_DOWN _IOW('w', 0x72, unsigned long) -+#define WEDGE_RAWKEY_UP _IOW('w', 0x73, unsigned long) -+#define WEDGE_TS_ABS_X _IOW('w', 0x74, unsigned long) -+#define WEDGE_TS_ABS_Y _IOW('w', 0x75, unsigned long) -+#define WEDGE_TS_ABS_PRESSURE _IOW('w', 0x76, unsigned long) -+ -+// Externs -+#define MAX_NR_KEYMAPS 256 -+extern void ramses_key(int keycode); -+extern unsigned short *key_maps[MAX_NR_KEYMAPS]; -+extern struct input_dev ramses_kbd_dev; -+extern void ucb1x00_ts_evt_add(void *, u16 pressure, u16 x, u16 y); -+ -+// for special keys -+struct wedge_lookup_t { -+ u_short c; -+ u_short keysym; -+}; -+ -+struct wedge_lookup_t wedge_lookup[] = { -+ { 0x0a, 0x001c, }, -+ { 0x2f, 0x0508, }, -+}; -+ -+ -+ -+ -+static void *outbuf; -+ -+static int wedge_open(struct inode *inode, struct file *filp) -+{ -+ int ret; -+ -+ ret = -ENXIO; -+ outbuf = kmalloc(KBD_STUFF_MAX_BYTES, GFP_KERNEL); -+ if (!outbuf) -+ goto out; -+ -+ ret = 0; -+ -+out: -+ if (ret) { -+ kfree(outbuf); -+ } -+ return ret; -+} -+ -+ -+static int wedge_close(struct inode *inode, struct file *filp) -+{ -+ kfree(outbuf); -+ return 0; -+} -+ -+ -+static int wedge_search_map(u_short map[], int c) -+{ -+ int i; -+ -+ for (i=0; i"); -+MODULE_DESCRIPTION("PXA mcp low level support"); -+MODULE_LICENSE("GPL"); ---- linux-2.4.21/drivers/misc/mcp.h~ucb1x00 -+++ linux-2.4.21/drivers/misc/mcp.h -@@ -43,6 +43,7 @@ - - /* noddy implementation alert! */ - struct mcp *mcp_get(void); -+void mcp_put(void); - int mcp_register(struct mcp *); - - #define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate) ---- linux-2.4.21/drivers/misc/ucb1x00-core.c~pm -+++ linux-2.4.21/drivers/misc/ucb1x00-core.c -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -181,8 +182,9 @@ - if (val & UCB_ADC_DAT_VAL) - break; - /* yield to other processes */ -- set_current_state(TASK_INTERRUPTIBLE); -- schedule_timeout(1); -+ //HS set_current_state(TASK_INTERRUPTIBLE); -+ //HS schedule_timeout(1); -+ udelay(200); - } - - return UCB_ADC_DAT(val); -@@ -209,7 +211,8 @@ - struct ucb1x00 *ucb = (struct ucb1x00 *)dev->data; - unsigned int isr; - -- if (rqst == PM_RESUME) { -+ switch (rqst) { -+ case PM_RESUME: - ucb1x00_enable(ucb); - isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS); - ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr); -@@ -521,7 +524,9 @@ - */ - static int __init ucb1x00_configure(struct ucb1x00 *ucb) - { -+#ifndef CONFIG_ARCH_RAMSES - unsigned int irq_gpio_pin = 0; -+#endif - int irq, default_irq = NO_IRQ; - - #ifdef CONFIG_ARCH_SA1100 -@@ -611,11 +616,13 @@ - /* - * Eventually, this will disappear. - */ -+#ifndef CONFIG_ARCH_RAMSES - if (irq_gpio_pin) - #ifdef CONFIG_ARCH_PXA_IDP - set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_FALLING_EDGE); - #else - set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_RISING_EDGE); -+#endif - #endif - irq = ucb1x00_detect_irq(ucb); - if (irq != NO_IRQ) { ---- linux-2.4.21/drivers/misc/ucb1x00-ts.c~ramses-ucb1x00-dejitter -+++ linux-2.4.21/drivers/misc/ucb1x00-ts.c -@@ -29,6 +29,7 @@ - - #include - #include -+#include - - #include "ucb1x00.h" - -@@ -97,7 +98,7 @@ - }; - - static struct ucb1x00_ts ucbts; --static int adcsync = UCB_NOSYNC; -+static int adcsync = UCB_SYNC; - - static int ucb1x00_ts_startup(struct ucb1x00_ts *ts); - static void ucb1x00_ts_shutdown(struct ucb1x00_ts *ts); -@@ -116,8 +117,14 @@ - next_head = (ts->evt_head + 1) & (NR_EVENTS - 1); - if (next_head != ts->evt_tail) { - ts->events[ts->evt_head].pressure = pressure; -+#if 0 - ts->events[ts->evt_head].x = x; - ts->events[ts->evt_head].y = y; -+#else -+ // rotate by -90 -+ ts->events[ts->evt_head].x = y; -+ ts->events[ts->evt_head].y = x; -+#endif - do_gettimeofday(&ts->events[ts->evt_head].stamp); - ts->evt_head = next_head; - -@@ -256,11 +263,11 @@ - - #define ucb1x00_ts_evt_clear(ts) do { } while (0) - --static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y) -+void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y) - { -- input_report_abs(&ts->idev, ABS_X, x); -- input_report_abs(&ts->idev, ABS_Y, y); -- input_report_abs(&ts->idev, ABS_PRESSURE, pressure); -+ input_report_abs(&ucbts.idev, ABS_X, y); -+ input_report_abs(&ucbts.idev, ABS_Y, x); -+ input_report_abs(&ucbts.idev, ABS_PRESSURE, pressure); - } - - static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts) -@@ -335,7 +342,7 @@ - UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | - UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); - -- return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync); -+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSMY, ts->adcsync); - } - - /* -@@ -346,19 +353,15 @@ - */ - static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts) - { -- ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -- UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | -- UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -- ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -- UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | -- UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -+ unsigned int res; - ucb1x00_reg_write(ts->ucb, UCB_TS_CR, - UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | - UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); - -- udelay(55); -+ udelay(600); - -- return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync); -+ res = ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSMY, ts->adcsync); -+ return res; - } - - /* -@@ -369,19 +372,15 @@ - */ - static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts) - { -+ unsigned int res; - ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -- UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | -- UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -- ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -- UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | -- UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -- ucb1x00_reg_write(ts->ucb, UCB_TS_CR, -- UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | -+ UCB_TS_CR_TSPY_GND | UCB_TS_CR_TSMY_POW | - UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); - -- udelay(55); -+ udelay(300); - -- return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync); -+ res = ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync); -+ return res; - } - - /* -@@ -430,8 +429,9 @@ - * We could run as a real-time thread. However, thus far - * this doesn't seem to be necessary. - */ --// tsk->policy = SCHED_FIFO; --// tsk->rt_priority = 1; -+//HS -+ tsk->policy = SCHED_FIFO; -+ tsk->rt_priority = 1; - - /* only want to receive SIGKILL */ - spin_lock_irq(&tsk->sigmask_lock); -@@ -451,8 +451,8 @@ - ucb1x00_adc_enable(ts->ucb); - - x = ucb1x00_ts_read_xpos(ts); -- y = ucb1x00_ts_read_ypos(ts); - p = ucb1x00_ts_read_pressure(ts); -+ y = ucb1x00_ts_read_ypos(ts); - - /* - * Switch back to interrupt mode. -@@ -461,7 +461,7 @@ - ucb1x00_adc_disable(ts->ucb); - - set_task_state(tsk, TASK_UNINTERRUPTIBLE); -- schedule_timeout(HZ / 100); -+ schedule_timeout(HZ / 200); - if (signal_pending(tsk)) - break; - -@@ -504,7 +504,7 @@ - } - - set_task_state(tsk, TASK_INTERRUPTIBLE); -- schedule_timeout(HZ / 100); -+ schedule_timeout(HZ / 200); - } - - if (signal_pending(tsk)) -@@ -655,8 +655,8 @@ - char *p; - - while ((p = strsep(&str, ",")) != NULL) { -- if (strcmp(p, "sync") == 0) -- adcsync = UCB_SYNC; -+ if (strcmp(p, "nosync") == 0) -+ adcsync = UCB_NOSYNC; - } - - return 1; -@@ -674,6 +674,7 @@ - module_init(ucb1x00_ts_init); - module_exit(ucb1x00_ts_exit); - -+EXPORT_SYMBOL(ucb1x00_ts_evt_add); - MODULE_AUTHOR("Russell King "); - MODULE_DESCRIPTION("UCB1x00 touchscreen driver"); - MODULE_LICENSE("GPL"); ---- linux-2.4.21/drivers/mtd/maps/Config.in~ramses-mtd -+++ linux-2.4.21/drivers/mtd/maps/Config.in -@@ -76,6 +76,7 @@ - - if [ "$CONFIG_ARM" = "y" ]; then - dep_tristate ' CFI Flash device mapped on Lubbock board' CONFIG_MTD_LUBBOCK $CONFIG_MTD_CFI $CONFIG_ARCH_LUBBOCK $CONFIG_MTD_PARTITIONS -+ dep_tristate ' CFI Flash device mapped on Ramses board' CONFIG_MTD_RAMSES $CONFIG_MTD_CFI $CONFIG_ARCH_RAMSES $CONFIG_MTD_PARTITIONS - dep_tristate ' CFI Flash device mapped on Nora' CONFIG_MTD_NORA $CONFIG_MTD_CFI - dep_tristate ' CFI Flash device mapped on ARM Integrator/P720T' CONFIG_MTD_ARM_INTEGRATOR $CONFIG_MTD_CFI - dep_tristate ' Cirrus CDB89712 evaluation board mappings' CONFIG_MTD_CDB89712 $CONFIG_MTD_CFI $CONFIG_ARCH_CDB89712 ---- linux-2.4.21/drivers/mtd/maps/Makefile~ramses-mtd -+++ linux-2.4.21/drivers/mtd/maps/Makefile -@@ -16,6 +16,7 @@ - obj-$(CONFIG_MTD_EPXA) += epxa-flash.o - obj-$(CONFIG_MTD_IQ80310) += iq80310.o - obj-$(CONFIG_MTD_LUBBOCK) += lubbock.o -+obj-$(CONFIG_MTD_RAMSES) += ramses.o - obj-$(CONFIG_MTD_PXA_CERF) += pxa_cerf.o - obj-$(CONFIG_MTD_TRIZEPS2) += trizeps2.o - obj-$(CONFIG_MTD_L440GX) += l440gx.o ---- /dev/null -+++ linux-2.4.21/drivers/mtd/maps/ramses.c -@@ -0,0 +1,167 @@ -+/* -+ * Map driver for the Ramses developer platform. -+ * -+ * 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 -+ -+ -+#define WINDOW_ADDR 0 -+#define WINDOW_SIZE 32*1024*1024 -+ -+static __u8 ramses_read8(struct map_info *map, unsigned long ofs) -+{ -+ return *(__u8 *)(map->map_priv_1 + ofs); -+} -+ -+static __u16 ramses_read16(struct map_info *map, unsigned long ofs) -+{ -+ return *(__u16 *)(map->map_priv_1 + ofs); -+} -+ -+static __u32 ramses_read32(struct map_info *map, unsigned long ofs) -+{ -+ return *(__u32 *)(map->map_priv_1 + ofs); -+} -+ -+static void ramses_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -+{ -+ memcpy(to, (void *)(map->map_priv_1 + from), len); -+} -+ -+static void ramses_write8(struct map_info *map, __u8 d, unsigned long adr) -+{ -+ *(__u8 *)(map->map_priv_1 + adr) = d; -+} -+ -+static void ramses_write16(struct map_info *map, __u16 d, unsigned long adr) -+{ -+ *(__u16 *)(map->map_priv_1 + adr) = d; -+} -+ -+static void ramses_write32(struct map_info *map, __u32 d, unsigned long adr) -+{ -+ *(__u32 *)(map->map_priv_1 + adr) = d; -+} -+ -+static void ramses_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -+{ -+ memcpy((void *)(map->map_priv_1 + to), from, len); -+} -+ -+static struct map_info ramses_map = { -+ name: "Flash", -+ size: WINDOW_SIZE, -+ read8: ramses_read8, -+ read16: ramses_read16, -+ read32: ramses_read32, -+ copy_from: ramses_copy_from, -+ write8: ramses_write8, -+ write16: ramses_write16, -+ write32: ramses_write32, -+ copy_to: ramses_copy_to -+}; -+ -+static struct mtd_partition ramses_partitions[] = { -+ { -+ name: "Bootloader", -+ size: 0x00040000, -+ offset: 0, -+ },{ -+ name: "Kernel", -+ size: 0x00100000, -+ offset: 0x00040000, -+ },{ -+ name: "Filesystem", -+ size: MTDPART_SIZ_FULL, -+ offset: 0x00140000 -+ } -+}; -+ -+#define NB_OF(x) (sizeof(x)/sizeof(x[0])) -+ -+static struct mtd_info *mymtd; -+static struct mtd_partition *parsed_parts; -+ -+extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts); -+ -+static int __init init_ramses(void) -+{ -+ struct mtd_partition *parts; -+ int nb_parts = 0; -+ int parsed_nr_parts = 0; -+ char *part_type = "static"; -+ -+ ramses_map.buswidth = (BOOT_DEF & 1) ? 2 : 4; -+ printk( "Probing flash at physical address 0x%08x (%d-bit buswidth)\n", -+ WINDOW_ADDR, ramses_map.buswidth * 8 ); -+#ifdef CONFIG_ARCH_RAMSES -+ FLASH_WRITE_PROTECT_DISABLE(); -+#endif -+ ramses_map.map_priv_1 = (unsigned long)__ioremap(WINDOW_ADDR, WINDOW_SIZE, 0); -+ if (!ramses_map.map_priv_1) { -+ printk("Failed to ioremap\n"); -+ return -EIO; -+ } -+ mymtd = do_map_probe("cfi_probe", &ramses_map); -+ if (!mymtd) { -+ iounmap((void *)ramses_map.map_priv_1); -+ return -ENXIO; -+ } -+ mymtd->module = THIS_MODULE; -+ -+#ifdef CONFIG_MTD_REDBOOT_PARTS -+ if (parsed_nr_parts == 0) { -+ int ret = parse_redboot_partitions(mymtd, &parsed_parts); -+ -+ if (ret > 0) { -+ part_type = "RedBoot"; -+ parsed_nr_parts = ret; -+ } -+ } -+#endif -+ -+ if (parsed_nr_parts > 0) { -+ parts = parsed_parts; -+ nb_parts = parsed_nr_parts; -+ } else { -+ parts = ramses_partitions; -+ nb_parts = NB_OF(ramses_partitions); -+ } -+ if (nb_parts) { -+ printk(KERN_NOTICE "Using %s partition definition\n", part_type); -+ add_mtd_partitions(mymtd, parts, nb_parts); -+ } else { -+ add_mtd_device(mymtd); -+ } -+ return 0; -+} -+ -+static void __exit cleanup_ramses(void) -+{ -+ if (mymtd) { -+ del_mtd_partitions(mymtd); -+ map_destroy(mymtd); -+ if (parsed_parts) -+ kfree(parsed_parts); -+ } -+ if (ramses_map.map_priv_1) -+ iounmap((void *)ramses_map.map_priv_1); -+#ifdef CONFIG_ARCH_RAMSES -+ FLASH_WRITE_PROTECT_ENABLE(); -+#endif -+ return; -+} -+ -+module_init(init_ramses); -+module_exit(cleanup_ramses); -+ ---- linux-2.4.21/drivers/net/irda/pxa_ir.c~pxa-irda -+++ linux-2.4.21/drivers/net/irda/pxa_ir.c -@@ -38,6 +38,7 @@ - #include - #include - -+#include - #include - #include - #include -@@ -786,6 +787,7 @@ - * Suspend the IrDA interface. - */ - -+/* - static int pxa250_irda_shutdown(struct pxa250_irda *si) - { - -@@ -793,6 +795,7 @@ - return 0; - - } -+*/ - - - static int pxa250_irda_suspend(struct net_device *dev, int state) -@@ -1141,11 +1144,11 @@ - /* allocate consistent buffers for dma access - * buffers have to be aligned and situated in dma capable memory region; - */ -- si->rxbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA ,HPSIR_MAX_RXLEN , &si->rxbuf_dma); -+ si->rxbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA ,HPSIR_MAX_RXLEN , &si->rxbuf_dma, 0); - if (! si->rxbuf_dma_virt ) - goto err_rxbuf_dma; - -- si->txbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA, HPSIR_MAX_TXLEN, &si->txbuf_dma); -+ si->txbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA, HPSIR_MAX_TXLEN, &si->txbuf_dma, 0); - if (! si->txbuf_dma_virt ) - goto err_txbuf_dma; - ---- linux-2.4.21/drivers/net/smc91x.c~pxa-smc91x -+++ linux-2.4.21/drivers/net/smc91x.c -@@ -46,10 +46,13 @@ - . 12/20/01 Jeff Sutherland initial port to Xscale PXA with DMA support - . 04/07/03 Nicolas Pitre unified SMC91x driver, killed irq races, - . more bus abstraction, big cleanup, etc. -+ . 20/08/03 Holger Schurig add ethtool support - ----------------------------------------------------------------------------*/ - -+#define DRV_NAME "smc91x" -+ - static const char version[] = -- "smc91x.c: v1.0, mar 07 2003 by Nicolas Pitre \n"; -+ DRV_NAME ": v1.1 Aug 20 2003 by Nicolas Pitre \n"; - - /* Debugging level */ - #ifndef SMC_DEBUG -@@ -67,6 +70,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -78,6 +82,7 @@ - #include - #include - #include -+#include - - #include "smc91x.h" - -@@ -105,7 +110,7 @@ - static int irq = SMC_IRQ; - - #ifndef SMC_NOWAIT --# define SMC_NOWAIT 0 -+# define SMC_NOWAIT 1 - #endif - static int nowait = SMC_NOWAIT; - -@@ -116,6 +121,11 @@ - MODULE_PARM_DESC(irq, "IRQ number"); - MODULE_PARM_DESC(nowait, "set to 1 for no wait state"); - -+static int -+smc_read_phy_register(unsigned long ioaddr, int phyaddr, int phyreg); -+static void -+smc_write_phy_register( unsigned long ioaddr, int phyaddr, -+ int phyreg, int phydata ); - - /*------------------------------------------------------------------------ - . -@@ -143,7 +153,12 @@ - . but to the expense of reduced TX throughput and increased IRQ overhead. - . Note this is not a cure for a too slow data bus or too high IRQ latency. - */ --#define THROTTLE_TX_PKTS 0 -+#define THROTTLE_TX_PKTS 1 -+ -+/* -+ . This defines if we want to compile ethtool support into the driver -+*/ -+#define WITH_ETHTOOL 1 - - - /* store this information for the driver.. */ -@@ -310,14 +325,14 @@ - if (nowait) - SMC_SET_CONFIG( SMC_GET_CONFIG() | CONFIG_NO_WAIT ); - --#ifdef POWER_DOWN -+#if POWER_DOWN - /* Release from possible power-down state */ - /* Configuration register is not affected by Soft Reset */ - SMC_SELECT_BANK( 1 ); - SMC_SET_CONFIG( SMC_GET_CONFIG() | CONFIG_EPH_POWER_EN ); - status = smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG); - status &= ~PHY_CNTL_PDN; -- smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG); -+ smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, status); - #endif - - /* this should pause enough for the chip to be happy */ -@@ -390,10 +405,10 @@ - SMC_SET_RCR( RCR_CLEAR ); - SMC_SET_TCR( TCR_CLEAR ); - --#ifdef POWER_DOWN -+#if POWER_DOWN - status = smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG); - status |= PHY_CNTL_PDN; -- smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG); -+ smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, status); - - /* finally, shut the chip down */ - SMC_SELECT_BANK( 1 ); -@@ -1628,14 +1643,18 @@ - // Setup the default Register Modes - lp->tcr_cur_mode = TCR_DEFAULT; - lp->rcr_cur_mode = RCR_DEFAULT; -- lp->rpc_cur_mode = RPC_DEFAULT; - - /* Set default parameters */ - #ifdef CONFIG_ARCH_RAMSES -- lp->ctl_autoneg = 0; -- lp->ctl_rfduplx = 0; -+ lp->rpc_cur_mode = (RPC_ANEG | (RPC_LED_10 << RPC_LSXA_SHFT) | (RPC_LED_TX_RX << RPC_LSXB_SHFT) | RPC_DPLX); -+ -+ // 10 MBit/S, auto-negotiation only for 10 MB/s -+ lp->ctl_autoneg = 1; -+ lp->ctl_rfduplx = 1; - lp->ctl_rspeed = 10; - #else -+ lp->rpc_cur_mode = RPC_DEFAULT; -+ - lp->ctl_autoneg = 1; - lp->ctl_rfduplx = 1; - lp->ctl_rspeed = 100; -@@ -1680,6 +1699,127 @@ - return 0; - } - -+/*---------------------------------------------------- -+ . smc_ioctl -+ . -+ . This ioctl is currently only used by ethtool(8) to -+ . access the serial EEPROM -+ -----------------------------------------------------*/ -+ -+#if WITH_ETHTOOL -+ -+#define SMC91x_EEPROM_SIZE (0x40*2) -+ -+u16 smc_eeprom_read(long ioaddr, u16 location) -+{ -+ u16 val; -+ u16 oldBank; -+ u16 oldPtr; -+ -+ cli(); -+ // Save chip settings -+ oldBank = SMC_CURRENT_BANK(); -+ SMC_SELECT_BANK( 2 ); -+ oldPtr = SMC_GET_PTR(); -+ -+ // Set location in EEPROM to be read -+ SMC_SET_PTR(location); -+ -+ // Set EEPROM_SELECT and RELOAD bits in control register -+ SMC_SELECT_BANK( 1 ); -+ val = SMC_GET_CTL(); -+ SMC_SET_CTL(val | CTL_EEPROM_SELECT | CTL_RELOAD); -+ -+ // Wait until RELEAD is finished -+ while (SMC_GET_CTL() & CTL_RELOAD) ; -+ -+ // Get EEPROM data -+ val = SMC_inw(ioaddr, GP_REG); -+ -+ // Restore chip settings -+ SMC_SELECT_BANK( 2 ); -+ SMC_SET_PTR(oldPtr); -+ SMC_SELECT_BANK( oldBank ); -+ sti(); -+ -+ return val; -+} -+ -+static int smc_get_eeprom(struct net_device *dev, u8 *buf) -+{ -+ int i; -+ u16 *ebuf = (u16 *)buf; -+ -+ for (i = 0; i < SMC91x_EEPROM_SIZE/2; i++) { -+ ebuf[i] = smc_eeprom_read(dev->base_addr, i); -+ } -+ return 0; -+} -+ -+static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -+{ -+ u32 etcmd; -+ int ret = -EINVAL; -+ -+ if (cmd != SIOCETHTOOL) -+ return -EOPNOTSUPP; -+ -+ if (get_user(etcmd, (u32 *)rq->ifr_data)) -+ return -EFAULT; -+ -+ switch (etcmd) { -+ -+ /* Get driver info */ -+ case ETHTOOL_GDRVINFO: { -+ struct ethtool_drvinfo edrv; -+ -+ memset(&edrv, 0, sizeof(edrv)); -+ edrv.cmd = etcmd; -+ strcpy(edrv.driver, DRV_NAME); -+ sprintf(edrv.bus_info, "ISA:%8.8lx:%d", dev->base_addr, dev->irq); -+ edrv.eedump_len = SMC91x_EEPROM_SIZE; -+ ret = copy_to_user(rq->ifr_data, &edrv, sizeof(edrv)) ? -EFAULT : 0; -+ break; -+ } -+ -+ /* Get EEPROM data */ -+ case ETHTOOL_GEEPROM: { -+ struct ethtool_eeprom eeprom; -+ u8 eebuf[SMC91x_EEPROM_SIZE]; -+ int r; -+ -+ if (copy_from_user(&eeprom, rq->ifr_data, sizeof(eeprom))) -+ return -EFAULT; -+ -+ if (eeprom.offset > eeprom.offset+eeprom.len) -+ return -EINVAL; -+ -+ if ((eeprom.offset+eeprom.len) > SMC91x_EEPROM_SIZE) { -+ eeprom.len = SMC91x_EEPROM_SIZE-eeprom.offset; -+ } -+ eeprom.magic = 0; -+ if (copy_to_user(rq->ifr_data, &eeprom, sizeof(eeprom))) -+ return -EFAULT; -+ -+ rq->ifr_data += offsetof(struct ethtool_eeprom, data); -+ -+ r = smc_get_eeprom(dev, eebuf); -+ -+ if (r) -+ return r; -+ if (copy_to_user(rq->ifr_data, eebuf+eeprom.offset, eeprom.len)) -+ return -EFAULT; -+ return 0; -+ -+ } -+ } -+ -+ return ret; -+} -+ -+#endif -+ -+ - /*------------------------------------------------------------ - . Get the current statistics. - . This may be called with the card open or closed. -@@ -1925,6 +2065,9 @@ - dev->watchdog_timeo = HZ/10; - dev->get_stats = smc_query_statistics; - dev->set_multicast_list = smc_set_multicast_list; -+#if WITH_ETHTOOL -+ dev->do_ioctl = smc_ioctl; -+#endif - - return 0; - -@@ -1961,12 +2104,17 @@ - smc_shutdown(global_dev); - break; - case PM_RESUME: -+ udelay(5000); - smc_reset(global_dev); - smc_enable(global_dev); - SMC_SELECT_BANK( 1 ); - SMC_SET_MAC_ADDR(global_dev->dev_addr); -- if (lp->version >= 0x70) -- smc_phy_configure(global_dev); -+ if (global_dev->flags & IFF_UP) { -+ if (lp->version >= 0x70) -+ smc_phy_configure(global_dev); -+ } else { -+ smc_shutdown(global_dev); -+ } - break; - } - return 0; -@@ -2054,6 +2202,15 @@ - int ioaddr = RAMSES_ETH_BASE + 0x300; - global_dev->irq = SMC_IRQ; - ret = smc_probe(global_dev, ioaddr); -+#ifdef POWER_DOWN -+ smc_shutdown(global_dev); -+#endif -+ } -+#elif defined(CONFIG_ARCH_RAMSES) -+ { -+ int ioaddr = RAMSES_ETH_BASE + 0x300; -+ global_dev->irq = SMC_IRQ; -+ ret = smc_probe(global_dev, ioaddr); - } - #else - if (global_dev->base_addr == -1) { -@@ -2083,7 +2240,11 @@ - #ifdef CONFIG_PM - if (ret == 0) { - struct smc_local *lp = (struct smc_local *)global_dev->priv; -+#ifdef PM_DEBUG -+ lp->pm = pm_register(PM_SYS_UNKNOWN, 0x73393178, smc_pm_callback, "smc91x"); -+#else - lp->pm = pm_register(PM_SYS_UNKNOWN, 0x73393178, smc_pm_callback); -+#endif - } - #endif - ---- linux-2.4.21/drivers/net/smc91x.h~ramses-smc91x -+++ linux-2.4.21/drivers/net/smc91x.h -@@ -79,6 +79,11 @@ - #include - #define SMC_IOADDR (RAMSES_ETH_PHYS + 0x300) - #define SMC_IRQ ETHERNET_IRQ -+ -+#elif CONFIG_ARCH_RAMSES -+#include -+#define SMC_IOADDR (RAMSES_ETH_PHYS + 0x300) -+#define SMC_IRQ ETHERNET_IRQ - #endif - - #define SMC_CAN_USE_8BIT 1 ---- linux-2.4.21/drivers/net/wireless/hermes.c~orinoco013e -+++ linux-2.4.21/drivers/net/wireless/hermes.c -@@ -52,7 +52,6 @@ - - #include "hermes.h" - --static char version[] __initdata = "hermes.c: 4 Dec 2002 David Gibson "; - MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller"); - MODULE_AUTHOR("David Gibson "); - #ifdef MODULE_LICENSE -@@ -226,7 +225,8 @@ - * Returns: < 0 on internal error, 0 on success, > 0 on error returned by the firmware - * - * Callable from any context, but locking is your problem. */ --int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, hermes_response_t *resp) -+int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, -+ hermes_response_t *resp) - { - int err; - int k; -@@ -469,13 +469,17 @@ - - err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, NULL); - if (err) -- goto out; -+ return err; - - err = hermes_bap_seek(hw, bap, rid, 0); - if (err) -- goto out; -+ return err; - - rlength = hermes_read_reg(hw, dreg); -+ -+ if (! rlength) -+ return -ENOENT; -+ - rtype = hermes_read_reg(hw, dreg); - - if (length) -@@ -495,8 +499,7 @@ - nwords = min((unsigned)rlength - 1, bufsize / 2); - hermes_read_words(hw, dreg, buf, nwords); - -- out: -- return err; -+ return 0; - } - - int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, -@@ -511,7 +514,7 @@ - - err = hermes_bap_seek(hw, bap, rid, 0); - if (err) -- goto out; -+ return err; - - hermes_write_reg(hw, dreg, length); - hermes_write_reg(hw, dreg, rid); -@@ -523,7 +526,6 @@ - err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE, - rid, NULL); - -- out: - return err; - } - -@@ -539,9 +541,12 @@ - - static int __init init_hermes(void) - { -- printk(KERN_DEBUG "%s\n", version); -- - return 0; - } - -+static void __exit exit_hermes(void) -+{ -+} -+ - module_init(init_hermes); -+module_exit(exit_hermes); ---- linux-2.4.21/drivers/net/wireless/hermes.h~orinoco013e -+++ linux-2.4.21/drivers/net/wireless/hermes.h -@@ -250,7 +250,6 @@ - u16 scanreason; /* ??? */ - struct hermes_scan_apinfo aps[35]; /* Scan result */ - } __attribute__ ((packed)); -- - #define HERMES_LINKSTATUS_NOT_CONNECTED (0x0000) - #define HERMES_LINKSTATUS_CONNECTED (0x0001) - #define HERMES_LINKSTATUS_DISCONNECTED (0x0002) -@@ -278,7 +277,7 @@ - - /* Basic control structure */ - typedef struct hermes { -- ulong iobase; -+ unsigned long iobase; - int io_space; /* 1 if we IO-mapped IO, 0 for memory-mapped IO? */ - #define HERMES_IO 1 - #define HERMES_MEM 0 -@@ -368,7 +367,7 @@ - if (hw->io_space) { - insw(hw->iobase + off, buf, count); - } else { -- int i; -+ unsigned i; - u16 *p; - - /* This needs to *not* byteswap (like insw()) but -@@ -388,7 +387,7 @@ - if (hw->io_space) { - outsw(hw->iobase + off, buf, count); - } else { -- int i; -+ unsigned i; - const u16 *p; - - /* This needs to *not* byteswap (like outsw()) but -@@ -398,6 +397,21 @@ - for (i = 0, p = buf; i < count; i++) { - writew(le16_to_cpu(*p++), hw->iobase + off); - } -+ } -+} -+ -+static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count) -+{ -+ unsigned i; -+ -+ off = off << hw->reg_spacing;; -+ -+ if (hw->io_space) { -+ for (i = 0; i < count; i++) -+ outw(0, hw->iobase + off); -+ } else { -+ for (i = 0; i < count; i++) -+ writew(0, hw->iobase + off); - } - } - ---- linux-2.4.21/drivers/net/wireless/ieee802_11.h~orinoco013e -+++ linux-2.4.21/drivers/net/wireless/ieee802_11.h -@@ -9,6 +9,8 @@ - bytes is allowed, which is a bit confusing, I suspect this - represents the 2304 bytes of real data, plus a possible 8 bytes of - WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */ -+ -+ - #define IEEE802_11_HLEN 30 - #define IEEE802_11_FRAME_LEN (IEEE802_11_DATA_LEN + IEEE802_11_HLEN) - ---- linux-2.4.21/drivers/net/wireless/orinoco.c~orinoco013e -+++ linux-2.4.21/drivers/net/wireless/orinoco.c -@@ -1,4 +1,4 @@ --/* orinoco.c 0.13b - (formerly known as dldwd_cs.c and orinoco_cs.c) -+/* orinoco.c 0.13e - (formerly known as dldwd_cs.c and orinoco_cs.c) - * - * A driver for Hermes or Prism 2 chipset based PCMCIA wireless - * adaptors, with Lucent/Agere, Intersil or Symbol firmware. -@@ -117,7 +117,7 @@ - * o Init of priv->tx_rate_ctrl in firmware specific section. - * o Prism2/Symbol rate, upto should be 0xF and not 0x15. Doh ! - * o Spectrum card always need cor_reset (for every reset) -- * o Fix cor_reset to not loose bit 7 in the register -+ * o Fix cor_reset to not lose bit 7 in the register - * o flush_stale_links to remove zombie Pcmcia instances - * o Ack previous hermes event before reset - * Me (with my little hands) -@@ -289,7 +289,7 @@ - * which are used as the dev->open, dev->stop, priv->reset - * callbacks if none are specified when alloc_orinocodev() is - * called. -- * o Removed orinoco_plx_interupt() and orinoco_pci_interrupt(). -+ * o Removed orinoco_plx_interrupt() and orinoco_pci_interrupt(). - * They didn't do anything. - * - * v0.12 -> v0.12a - 4 Jul 2002 - David Gibson -@@ -345,13 +345,54 @@ - * we are connected (avoids cofusing the firmware), and only - * give LINKSTATUS printk()s if the status has changed. - * -+ * v0.13b -> v0.13c - 11 Mar 2003 - David Gibson -+ * o Cleanup: use dev instead of priv in various places. -+ * o Bug fix: Don't ReleaseConfiguration on RESET_PHYSICAL event -+ * if we're in the middle of a (driver initiated) hard reset. -+ * o Bug fix: ETH_ZLEN is supposed to include the header -+ * (Dionysus Blazakis & Manish Karir) -+ * o Convert to using workqueues instead of taskqueues (and -+ * backwards compatibility macros for pre 2.5.41 kernels). -+ * o Drop redundant (I think...) MOD_{INC,DEC}_USE_COUNT in -+ * airport.c -+ * o New orinoco_tmd.c init module from Joerg Dorchain for -+ * TMD7160 based PCI to PCMCIA bridges (similar to -+ * orinoco_plx.c). -+ * -+ * v0.13c -> v0.13d - 22 Apr 2003 - David Gibson -+ * o Make hw_unavailable a counter, rather than just a flag, this -+ * is necessary to avoid some races (such as a card being -+ * removed in the middle of orinoco_reset(). -+ * o Restore Release/RequestConfiguration in the PCMCIA event handler -+ * when dealing with a driver initiated hard reset. This is -+ * necessary to prevent hangs due to a spurious interrupt while -+ * the reset is in progress. -+ * o Clear the 802.11 header when transmitting, even though we -+ * don't use it. This fixes a long standing bug on some -+ * firmwares, which seem to get confused if that isn't done. -+ * o Be less eager to de-encapsulate SNAP frames, only do so if -+ * the OUI is 00:00:00 or 00:00:f8, leave others alone. The old -+ * behaviour broke CDP (Cisco Discovery Protocol). -+ * o Use dev instead of priv for free_irq() as well as -+ * request_irq() (oops). -+ * o Attempt to reset rather than giving up if we get too many -+ * IRQs. -+ * o Changed semantics of __orinoco_down() so it can be called -+ * safely with hw_unavailable set. It also now clears the -+ * linkstatus (since we're going to have to reassociate). -+ * -+ * v0.13d -> v0.13e - 12 May 2003 - David Gibson -+ * o Support for post-2.5.68 return values from irq handler. -+ * o Fixed bug where underlength packets would be double counted -+ * in the rx_dropped statistics. -+ * o Provided a module parameter to suppress linkstatus messages. -+ * - * TODO -- - * o New wireless extensions API (patch from Moustafa -- * Youssef, updated by Jim Carter). -- * o Fix PCMCIA hard resets with pcmcia-cs. -+ * Youssef, updated by Jim Carter and Pavel Roskin). - * o Handle de-encapsulation within network layer, provide 802.11 - * headers (patch from Thomas 'Dent' Mirlacher) -+ * o RF monitor mode support - * o Fix possible races in SPY handling. - * o Disconnect wireless extensions from fundamental configuration. - * o (maybe) Software WEP support (patch from Stano Meduna). -@@ -373,27 +414,27 @@ - * flag after taking the lock, and if it is set, give up on whatever - * they are doing and drop the lock again. The orinoco_lock() - * function handles this (it unlocks and returns -EBUSY if -- * hw_unavailable is true). */ -+ * hw_unavailable is non-zero). */ - - #include - - #include - #include - #include --#include - #include - #include - #include - #include - #include --#include --#include --#include - #include - #include - #include - #include - -+#include -+#include -+#include -+ - #include "hermes.h" - #include "hermes_rid.h" - #include "orinoco.h" -@@ -416,6 +457,9 @@ - EXPORT_SYMBOL(orinoco_debug); - #endif - -+static int suppress_linkstatus; /* = 0 */ -+MODULE_PARM(suppress_linkstatus, "i"); -+ - /********************************************************************/ - /* Compile time configuration and compatibility stuff */ - /********************************************************************/ -@@ -443,8 +487,10 @@ - #define USER_BAP 0 - #define IRQ_BAP 1 - #define MAX_IRQLOOPS_PER_IRQ 10 --#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of how many events the -- device could legitimately generate */ -+#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of -+ * how many events the -+ * device could -+ * legitimately generate */ - #define SMALL_KEY_SIZE 5 - #define LARGE_KEY_SIZE 13 - #define TX_NICBUF_SIZE_BUG 1585 /* Bug in Symbol firmware */ -@@ -480,8 +526,8 @@ - {10, 1, 1, 1}, - {20, 0, 2, 2}, - {20, 1, 6, 3}, -- {55, 0, 4, 4}, -- {55, 1, 7, 7}, -+ {55, 0, 4, 4}, -+ {55, 1, 7, 7}, - {110, 0, 5, 8}, - }; - #define BITRATE_TABLE_SIZE (sizeof(bitrate_table) / sizeof(bitrate_table[0])) -@@ -522,7 +568,7 @@ - - /* Hardware control routines */ - --static int __orinoco_program_rids(struct orinoco_private *priv); -+static int __orinoco_program_rids(struct net_device *dev); - - static int __orinoco_hw_set_bitrate(struct orinoco_private *priv); - static int __orinoco_hw_setup_wep(struct orinoco_private *priv); -@@ -535,37 +581,17 @@ - static void __orinoco_set_multicast_list(struct net_device *dev); - - /* Interrupt handling routines */ --static void __orinoco_ev_tick(struct orinoco_private *priv, hermes_t *hw); --static void __orinoco_ev_wterr(struct orinoco_private *priv, hermes_t *hw); --static void __orinoco_ev_infdrop(struct orinoco_private *priv, hermes_t *hw); --static void __orinoco_ev_info(struct orinoco_private *priv, hermes_t *hw); --static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw); --static void __orinoco_ev_txexc(struct orinoco_private *priv, hermes_t *hw); --static void __orinoco_ev_tx(struct orinoco_private *priv, hermes_t *hw); --static void __orinoco_ev_alloc(struct orinoco_private *priv, hermes_t *hw); -+static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw); -+static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw); -+static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw); -+static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw); -+static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw); -+static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw); -+static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw); -+static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw); - - /* ioctl() routines */ --static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq); --static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq); --static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq); --static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq); --static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq); --static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq); --static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq); --static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq); --static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq); --static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq); --static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq); --static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq); --static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq); --static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *frq); --static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *frq); --static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq); --static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq); --static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq); --static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq); -- --static int orinoco_debug_dump_recs(struct orinoco_private *priv); -+static int orinoco_debug_dump_recs(struct net_device *dev); - - /********************************************************************/ - /* Function prototypes */ -@@ -577,7 +603,7 @@ - struct hermes *hw = &priv->hw; - int err; - -- err = __orinoco_program_rids(priv); -+ err = __orinoco_program_rids(dev); - if (err) { - printk(KERN_ERR "%s: Error %d configuring card\n", - dev->name, err); -@@ -606,14 +632,25 @@ - - netif_stop_queue(dev); - -- err = hermes_disable_port(hw, 0); -- if (err) { -- printk(KERN_ERR "%s: Error %d disabling MAC port\n", -- dev->name, err); -- return err; -+ if (! priv->hw_unavailable) { -+ if (! priv->broken_disableport) { -+ err = hermes_disable_port(hw, 0); -+ if (err) { -+ /* Some firmwares (e.g. Intersil 1.3.x) seem -+ * to have problems disabling the port, oh -+ * well, too bad. */ -+ printk(KERN_WARNING "%s: Error %d disabling MAC port\n", -+ dev->name, err); -+ priv->broken_disableport = 1; -+ } -+ } -+ hermes_set_irqmask(hw, 0); -+ hermes_write_regn(hw, EVACK, 0xffff); - } -- hermes_set_irqmask(hw, 0); -- hermes_write_regn(hw, EVACK, 0xffff); -+ -+ /* firmware will have to reassociate */ -+ priv->last_linkstatus = 0xffff; -+ priv->connected = 0; - - return 0; - } -@@ -656,38 +693,38 @@ - if (err) - return err; - -- priv->open = 1; -- - err = __orinoco_up(dev); - -+ if (! err) -+ priv->open = 1; -+ - orinoco_unlock(priv, &flags); - - return err; - } - --static int orinoco_stop(struct net_device *dev) -+int orinoco_stop(struct net_device *dev) - { - struct orinoco_private *priv = dev->priv; - int err = 0; - - /* We mustn't use orinoco_lock() here, because we need to be -- able to close the interface, even if hw_unavailable is set -+ able to close the interface even if hw_unavailable is set - (e.g. as we're released after a PC Card removal) */ - spin_lock_irq(&priv->lock); - - priv->open = 0; - -- if (! priv->hw_unavailable) -- err = __orinoco_down(dev); -+ err = __orinoco_down(dev); - - spin_unlock_irq(&priv->lock); - - return err; - } - --static int __orinoco_program_rids(struct orinoco_private *priv) -+static int __orinoco_program_rids(struct net_device *dev) - { -- struct net_device *dev = priv->ndev; -+ struct orinoco_private *priv = dev->priv; - hermes_t *hw = &priv->hw; - int err; - struct hermes_idstring idbuf; -@@ -873,51 +910,84 @@ - } - - /* xyzzy */ --static int orinoco_reconfigure(struct orinoco_private *priv) -+static int orinoco_reconfigure(struct net_device *dev) - { -+ struct orinoco_private *priv = dev->priv; - struct hermes *hw = &priv->hw; - unsigned long flags; - int err = 0; - -- orinoco_lock(priv, &flags); -+ if (priv->broken_disableport) { -+ schedule_work(&priv->reset_work); -+ return 0; -+ } -+ -+ err = orinoco_lock(priv, &flags); -+ if (err) -+ return err; - -+ - err = hermes_disable_port(hw, 0); - if (err) { -- printk(KERN_ERR "%s: Unable to disable port in orinco_reconfigure()\n", -- priv->ndev->name); -+ printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n", -+ dev->name); -+ priv->broken_disableport = 1; - goto out; - } - -- err = __orinoco_program_rids(priv); -- if (err) -+ err = __orinoco_program_rids(dev); -+ if (err) { -+ printk(KERN_WARNING "%s: Unable to reconfigure card\n", -+ dev->name); - goto out; -+ } - - err = hermes_enable_port(hw, 0); - if (err) { -- printk(KERN_ERR "%s: Unable to enable port in orinco_reconfigure()\n", -- priv->ndev->name); -+ printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", -+ dev->name); - goto out; - } - - out: -+ if (err) { -+ printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); -+ schedule_work(&priv->reset_work); -+ err = 0; -+ } -+ - orinoco_unlock(priv, &flags); - return err; - - } - - /* This must be called from user context, without locks held - use -- * schedule_task() */ -+ * schedule_work() */ - static void orinoco_reset(struct net_device *dev) - { - struct orinoco_private *priv = dev->priv; -+ struct hermes *hw = &priv->hw; - int err; - unsigned long flags; - - err = orinoco_lock(priv, &flags); - if (err) -+ /* When the hardware becomes available again, whatever -+ * detects that is responsible for re-initializing -+ * it. So no need for anything further*/ - return; - -- priv->hw_unavailable = 1; -+ netif_stop_queue(dev); -+ -+ /* Shut off interrupts. Depending on what state the hardware -+ * is in, this might not work, but we'll try anyway */ -+ hermes_set_irqmask(hw, 0); -+ hermes_write_regn(hw, EVACK, 0xffff); -+ -+ priv->hw_unavailable++; -+ priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */ -+ priv->connected = 0; -+ - orinoco_unlock(priv, &flags); - - if (priv->hard_reset) -@@ -936,18 +1006,22 @@ - return; - } - -- spin_lock_irqsave(&priv->lock, flags); -+ spin_lock_irq(&priv->lock); /* This has to be called from user context */ - -- priv->hw_unavailable = 0; -+ priv->hw_unavailable--; - -- err = __orinoco_up(dev); -- if (err) { -- printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n", -- dev->name, err); -- } else -- dev->trans_start = jiffies; -+ /* priv->open or priv->hw_unavailable might have changed while -+ * we dropped the lock */ -+ if (priv->open && (! priv->hw_unavailable)) { -+ err = __orinoco_up(dev); -+ if (err) { -+ printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n", -+ dev->name, err); -+ } else -+ dev->trans_start = jiffies; -+ } - -- orinoco_unlock(priv, &flags); -+ spin_unlock_irq(&priv->lock); - - return; - } -@@ -979,10 +1053,18 @@ - } - } - -+/* Does the frame have a SNAP header indicating it should be -+ * de-encapsulated to Ethernet-II? */ - static inline int --is_snap(struct header_struct *hdr) -+is_ethersnap(struct header_struct *hdr) - { -- return (hdr->dsap == 0xAA) && (hdr->ssap == 0xAA) && (hdr->ctrl == 0x3); -+ /* We de-encapsulate all packets which, a) have SNAP headers -+ * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header -+ * and where b) the OUI of the SNAP header is 00:00:00 or -+ * 00:00:f8 - we need both because different APs appear to use -+ * different OUIs for some reason */ -+ return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0) -+ && ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) ); - } - - static void -@@ -1140,7 +1222,8 @@ - return 0; - } - --static int orinoco_hw_get_bssid(struct orinoco_private *priv, char buf[ETH_ALEN]) -+static int orinoco_hw_get_bssid(struct orinoco_private *priv, -+ char buf[ETH_ALEN]) - { - hermes_t *hw = &priv->hw; - int err = 0; -@@ -1159,7 +1242,7 @@ - } - - static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, -- char buf[IW_ESSID_MAX_SIZE+1]) -+ char buf[IW_ESSID_MAX_SIZE+1]) - { - hermes_t *hw = &priv->hw; - int err = 0; -@@ -1236,9 +1319,8 @@ - } - - if ( (channel < 1) || (channel > NUM_CHANNELS) ) { -- struct net_device *dev = priv->ndev; -- -- printk(KERN_WARNING "%s: Channel out of range (%d)!\n", dev->name, channel); -+ printk(KERN_WARNING "%s: Channel out of range (%d)!\n", -+ priv->ndev->name, channel); - err = -EBUSY; - goto out; - -@@ -1253,8 +1335,8 @@ - return err ? err : freq; - } - --static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates, -- s32 *rates, int max) -+static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, -+ int *numrates, s32 *rates, int max) - { - hermes_t *hw = &priv->hw; - struct hermes_idstring list; -@@ -1287,9 +1369,6 @@ - } - - #if 0 --#ifndef ORINOCO_DEBUG --static inline void show_rx_frame(struct orinoco_rxframe_hdr *frame) {} --#else - static void show_rx_frame(struct orinoco_rxframe_hdr *frame) - { - printk(KERN_DEBUG "RX descriptor:\n"); -@@ -1346,17 +1425,16 @@ - frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]); - printk(KERN_DEBUG " ethertype = 0x%04x\n", frame->ethertype); - } --#endif --#endif -+#endif /* 0 */ - - /* - * Interrupt handler - */ --void orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs) -+irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs) - { -- struct orinoco_private *priv = (struct orinoco_private *) dev_id; -+ struct net_device *dev = (struct net_device *)dev_id; -+ struct orinoco_private *priv = dev->priv; - hermes_t *hw = &priv->hw; -- struct net_device *dev = priv->ndev; - int count = MAX_IRQLOOPS_PER_IRQ; - u16 evstat, events; - /* These are used to detect a runaway interrupt situation */ -@@ -1367,12 +1445,17 @@ - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) { -- /* If hw is unavailable */ -- return; -+ /* If hw is unavailable - we don't know if the irq was -+ * for us or not */ -+ return IRQ_HANDLED; - } - - evstat = hermes_read_regn(hw, EVSTAT); - events = evstat & hw->inten; -+ if (! events) { -+ orinoco_unlock(priv, &flags); -+ return IRQ_NONE; -+ } - - if (jiffies != last_irq_jiffy) - loops_this_jiffy = 0; -@@ -1380,11 +1463,11 @@ - - while (events && count--) { - if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) { -- printk(KERN_CRIT "%s: IRQ handler is looping too \ --much! Shutting down.\n", -- dev->name); -- /* Perform an emergency shutdown */ -+ printk(KERN_WARNING "%s: IRQ handler is looping too " -+ "much! Resetting.\n", dev->name); -+ /* Disable interrupts for now */ - hermes_set_irqmask(hw, 0); -+ schedule_work(&priv->reset_work); - break; - } - -@@ -1395,21 +1478,21 @@ - } - - if (events & HERMES_EV_TICK) -- __orinoco_ev_tick(priv, hw); -+ __orinoco_ev_tick(dev, hw); - if (events & HERMES_EV_WTERR) -- __orinoco_ev_wterr(priv, hw); -+ __orinoco_ev_wterr(dev, hw); - if (events & HERMES_EV_INFDROP) -- __orinoco_ev_infdrop(priv, hw); -+ __orinoco_ev_infdrop(dev, hw); - if (events & HERMES_EV_INFO) -- __orinoco_ev_info(priv, hw); -+ __orinoco_ev_info(dev, hw); - if (events & HERMES_EV_RX) -- __orinoco_ev_rx(priv, hw); -+ __orinoco_ev_rx(dev, hw); - if (events & HERMES_EV_TXEXC) -- __orinoco_ev_txexc(priv, hw); -+ __orinoco_ev_txexc(dev, hw); - if (events & HERMES_EV_TX) -- __orinoco_ev_tx(priv, hw); -+ __orinoco_ev_tx(dev, hw); - if (events & HERMES_EV_ALLOC) -- __orinoco_ev_alloc(priv, hw); -+ __orinoco_ev_alloc(dev, hw); - - hermes_write_regn(hw, EVACK, events); - -@@ -1418,30 +1501,34 @@ - }; - - orinoco_unlock(priv, &flags); -+ return IRQ_HANDLED; - } - --static void __orinoco_ev_tick(struct orinoco_private *priv, hermes_t *hw) -+static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw) - { -- printk(KERN_DEBUG "%s: TICK\n", priv->ndev->name); -+ printk(KERN_DEBUG "%s: TICK\n", dev->name); - } - --static void __orinoco_ev_wterr(struct orinoco_private *priv, hermes_t *hw) -+static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw) - { - /* This seems to happen a fair bit under load, but ignoring it - seems to work fine...*/ - printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n", -- priv->ndev->name); -+ dev->name); - } - --static void __orinoco_ev_infdrop(struct orinoco_private *priv, hermes_t *hw) -+static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw) - { -- printk(KERN_WARNING "%s: Information frame lost.\n", priv->ndev->name); -+ printk(KERN_WARNING "%s: Information frame lost.\n", dev->name); - } - - static void print_linkstatus(struct net_device *dev, u16 status) - { - char * s; - -+ if (suppress_linkstatus) -+ return; -+ - switch (status) { - case HERMES_LINKSTATUS_NOT_CONNECTED: - s = "Not Connected"; -@@ -1472,9 +1559,9 @@ - dev->name, s, status); - } - --static void __orinoco_ev_info(struct orinoco_private *priv, hermes_t *hw) -+static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) - { -- struct net_device *dev = priv->ndev; -+ struct orinoco_private *priv = dev->priv; - u16 infofid; - struct { - u16 len; -@@ -1573,9 +1660,9 @@ - } - } - --static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw) -+static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) - { -- struct net_device *dev = priv->ndev; -+ struct orinoco_private *priv = dev->priv; - struct net_device_stats *stats = &priv->stats; - struct iw_statistics *wstats = &priv->wstats; - struct sk_buff *skb = NULL; -@@ -1664,14 +1751,13 @@ - * So, check ourselves */ - if(((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || - ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || -- is_snap(&hdr)) { -+ is_ethersnap(&hdr)) { - /* These indicate a SNAP within 802.2 LLC within - 802.11 frame which we'll need to de-encapsulate to - the original EthernetII frame. */ - - if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */ - stats->rx_length_errors++; -- stats->rx_dropped++; - goto drop; - } - -@@ -1726,9 +1812,9 @@ - return; - } - --static void __orinoco_ev_txexc(struct orinoco_private *priv, hermes_t *hw) -+static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) - { -- struct net_device *dev = priv->ndev; -+ struct orinoco_private *priv = dev->priv; - struct net_device_stats *stats = &priv->stats; - u16 fid = hermes_read_regn(hw, TXCOMPLFID); - struct hermes_tx_descriptor desc; -@@ -1752,8 +1838,9 @@ - hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); - } - --static void __orinoco_ev_tx(struct orinoco_private *priv, hermes_t *hw) -+static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw) - { -+ struct orinoco_private *priv = dev->priv; - struct net_device_stats *stats = &priv->stats; - - stats->tx_packets++; -@@ -1761,9 +1848,10 @@ - hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); - } - --static void __orinoco_ev_alloc(struct orinoco_private *priv, hermes_t *hw) -+static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw) - { -- struct net_device *dev = priv->ndev; -+ struct orinoco_private *priv = dev->priv; -+ - u16 fid = hermes_read_regn(hw, ALLOCFID); - - if (fid != priv->txfid) { -@@ -1945,7 +2033,7 @@ - - TRACE_ENTER(dev->name); - -- /* No need to lock, the resetting flag is already set in -+ /* No need to lock, the hw_unavailable flag is already set in - * alloc_orinocodev() */ - priv->nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN; - -@@ -2081,8 +2169,6 @@ - priv->wep_on = 0; - priv->tx_key = 0; - -- priv->hw_unavailable = 0; -- - err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); - if (err == -EIO) { - /* Try workaround for old Symbol firmware bug */ -@@ -2102,6 +2188,12 @@ - goto out; - } - -+ /* Make the hardware available, as long as it hasn't been -+ * removed elsewhere (e.g. by PCMCIA hot unplug) */ -+ spin_lock_irq(&priv->lock); -+ priv->hw_unavailable--; -+ spin_unlock_irq(&priv->lock); -+ - printk(KERN_DEBUG "%s: ready\n", dev->name); - - out: -@@ -2267,7 +2359,7 @@ - - /* Length of the packet body */ - /* FIXME: what if the skb is smaller than this? */ -- len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN); -+ len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN); - - eh = (struct ethhdr *)skb->data; - -@@ -2281,6 +2373,12 @@ - goto fail; - } - -+ /* Clear the 802.11 header and data length fields - some -+ * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused -+ * if this isn't done. */ -+ hermes_clear_words(hw, HERMES_DATA0, -+ HERMES_802_3_OFFSET - HERMES_802_11_OFFSET); -+ - /* Encapsulate Ethernet-II frames */ - if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */ - struct header_struct hdr; -@@ -2362,7 +2460,7 @@ - - stats->tx_errors++; - -- schedule_task(&priv->timeout_task); -+ schedule_work(&priv->reset_work); - } - - static int -@@ -2532,7 +2630,7 @@ - } - - err = orinoco_hw_get_bitratelist(priv, &numrates, -- range.bitrate, IW_MAX_BITRATES); -+ range.bitrate, IW_MAX_BITRATES); - if (err) - return err; - range.num_bitrates = numrates; -@@ -2799,7 +2897,7 @@ - erq->flags = 1; - erq->length = strlen(essidbuf) + 1; - if (erq->pointer) -- if ( copy_to_user(erq->pointer, essidbuf, erq->length) ) -+ if (copy_to_user(erq->pointer, essidbuf, erq->length)) - return -EFAULT; - - TRACE_EXIT(dev->name); -@@ -3128,7 +3226,7 @@ - rrq->value = 5500000; - else - rrq->value = val * 1000000; -- break; -+ break; - case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */ - case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */ - for (i = 0; i < BITRATE_TABLE_SIZE; i++) -@@ -3754,7 +3852,7 @@ - - printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); - -- schedule_task(&priv->timeout_task); -+ schedule_work(&priv->reset_work); - break; - - case SIOCIWFIRSTPRIV + 0x2: /* set_port3 */ -@@ -3827,7 +3925,7 @@ - break; - - case SIOCIWLASTPRIV: -- err = orinoco_debug_dump_recs(priv); -+ err = orinoco_debug_dump_recs(dev); - if (err) - printk(KERN_ERR "%s: Unable to dump records (%d)\n", - dev->name, err); -@@ -3839,7 +3937,7 @@ - } - - if (! err && changed && netif_running(dev)) { -- err = orinoco_reconfigure(priv); -+ err = orinoco_reconfigure(dev); - } - - TRACE_EXIT(dev->name); -@@ -3924,7 +4022,7 @@ - DEBUG_REC(PRIID,WORDS), - DEBUG_REC(PRISUPRANGE,WORDS), - DEBUG_REC(CFIACTRANGES,WORDS), -- DEBUG_REC(NICSERNUM,WORDS), -+ DEBUG_REC(NICSERNUM,XSTRING), - DEBUG_REC(NICID,WORDS), - DEBUG_REC(MFISUPRANGE,WORDS), - DEBUG_REC(CFISUPRANGE,WORDS), -@@ -3961,8 +4059,9 @@ - - #define DEBUG_LTV_SIZE 128 - --static int orinoco_debug_dump_recs(struct orinoco_private *priv) -+static int orinoco_debug_dump_recs(struct net_device *dev) - { -+ struct orinoco_private *priv = dev->priv; - hermes_t *hw = &priv->hw; - u8 *val8; - u16 *val16; -@@ -4051,6 +4150,7 @@ - dev->do_ioctl = orinoco_ioctl; - dev->change_mtu = orinoco_change_mtu; - dev->set_multicast_list = orinoco_set_multicast_list; -+ /* we use the default eth_mac_addr for setting the MAC addr */ - - /* Set up default callbacks */ - dev->open = orinoco_open; -@@ -4062,7 +4162,7 @@ - priv->hw_unavailable = 1; /* orinoco_init() must clear this - * before anything else touches the - * hardware */ -- INIT_TQUEUE(&priv->timeout_task, (void (*)(void *))orinoco_reset, dev); -+ INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev); - - priv->last_linkstatus = 0xffff; - priv->connected = 0; -@@ -4079,13 +4179,14 @@ - - EXPORT_SYMBOL(__orinoco_up); - EXPORT_SYMBOL(__orinoco_down); -+EXPORT_SYMBOL(orinoco_stop); - EXPORT_SYMBOL(orinoco_reinit_firmware); - - EXPORT_SYMBOL(orinoco_interrupt); - - /* Can't be declared "const" or the whole __initdata section will - * become const */ --static char version[] __initdata = "orinoco.c 0.13b (David Gibson and others)"; -+static char version[] __initdata = "orinoco.c 0.13e (David Gibson and others)"; - - static int __init init_orinoco(void) - { ---- linux-2.4.21/drivers/net/wireless/orinoco.h~orinoco013e -+++ linux-2.4.21/drivers/net/wireless/orinoco.h -@@ -11,9 +11,29 @@ - #include - #include - #include --#include -+#include - #include "hermes.h" - -+/* Workqueue / task queue backwards compatibility stuff */ -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) -+#include -+#else -+#include -+#define work_struct tq_struct -+#define INIT_WORK INIT_TQUEUE -+#define schedule_work schedule_task -+#endif -+ -+/* Interrupt handler backwards compatibility stuff */ -+#ifndef IRQ_NONE -+ -+#define IRQ_NONE -+#define IRQ_HANDLED -+typedef void irqreturn_t; -+ -+#endif -+ - /* To enable debug messages */ - //#define ORINOCO_DEBUG 3 - -@@ -36,13 +56,13 @@ - - - struct orinoco_private { -- void *card; /* Pointer to card dependant structure */ -+ void *card; /* Pointer to card dependent structure */ - int (*hard_reset)(struct orinoco_private *); - - /* Synchronisation stuff */ - spinlock_t lock; - int hw_unavailable; -- struct tq_struct timeout_task; -+ struct work_struct reset_work; - - /* driver state */ - int open; -@@ -72,6 +92,7 @@ - int has_sensitivity; - int nicbuf_size; - u16 channel_mask; -+ int broken_disableport; - - /* Configuration paramaters */ - u32 iw_mode; -@@ -111,9 +132,9 @@ - int (*hard_reset)(struct orinoco_private *)); - extern int __orinoco_up(struct net_device *dev); - extern int __orinoco_down(struct net_device *dev); --int orinoco_reinit_firmware(struct net_device *dev); -- --extern void orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs); -+extern int orinoco_stop(struct net_device *dev); -+extern int orinoco_reinit_firmware(struct net_device *dev); -+extern irqreturn_t orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs); - - /********************************************************************/ - /* Locking and synchronization functions */ ---- linux-2.4.21/drivers/net/wireless/orinoco_cs.c~orinoco013e -+++ linux-2.4.21/drivers/net/wireless/orinoco_cs.c -@@ -1,4 +1,4 @@ --/* orinoco_cs.c 0.13b - (formerly known as dldwd_cs.c) -+/* orinoco_cs.c 0.13e - (formerly known as dldwd_cs.c) - * - * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such - * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/ -@@ -22,11 +22,7 @@ - #include - #include - #include --#include - #include --#include --#include --#include - #include - #include - #include -@@ -38,7 +34,10 @@ - #include - #include - #include --#include -+ -+#include -+#include -+#include - - #include "orinoco.h" - -@@ -62,7 +61,7 @@ - - /* Some D-Link cards have buggy CIS. They do work at 5v properly, but - * don't have any CIS entry for it. This workaround it... */ --static int ignore_cis_vcc; /* = 0 */ -+static int ignore_cis_vcc = 1; - - MODULE_PARM(irq_mask, "i"); - MODULE_PARM(irq_list, "1-4i"); -@@ -145,8 +144,10 @@ - /* PCMCIA stuff */ - /********************************************************************/ - -+/* In 2.5 (as of 2.5.69 at least) there is a cs_error exported which -+ * does this, but it's not in 2.4 so we do our own for now. */ - static void --cs_error(client_handle_t handle, int func, int ret) -+orinoco_cs_error(client_handle_t handle, int func, int ret) - { - error_info_t err = { func, ret }; - CardServices(ReportError, handle, &err); -@@ -202,6 +203,7 @@ - link->priv = dev; - - /* Initialize the dev_link_t structure */ -+ init_timer(&link->release); - link->release.function = &orinoco_cs_release; - link->release.data = (u_long) link; - -@@ -240,7 +242,7 @@ - - ret = CardServices(RegisterClient, &link->handle, &client_reg); - if (ret != CS_SUCCESS) { -- cs_error(link->handle, RegisterClient, ret); -+ orinoco_cs_error(link->handle, RegisterClient, ret); - orinoco_cs_detach(link); - return NULL; - } -@@ -269,19 +271,12 @@ - return; - } - -- /* -- If the device is currently configured and active, we won't -- actually delete it yet. Instead, it is marked so that when -- the release() function is called, that will trigger a proper -- detach(). -- */ - if (link->state & DEV_CONFIG) { --#ifdef PCMCIA_DEBUG -- printk(KERN_DEBUG "orinoco_cs: detach postponed, '%s' " -- "still locked\n", link->dev->dev_name); --#endif -- link->state |= DEV_STALE_LINK; -- return; -+ orinoco_cs_release((u_long)link); -+ if (link->state & DEV_CONFIG) { -+ link->state |= DEV_STALE_LINK; -+ return; -+ } - } - - /* Break the link with Card Services */ -@@ -368,7 +363,7 @@ - CS_CHECK(GetFirstTuple, handle, &tuple); - while (1) { - cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); -- cistpl_cftable_entry_t dflt = { index: 0 }; -+ cistpl_cftable_entry_t dflt = { .index = 0 }; - - CFG_CHECK(GetTupleData, handle, &tuple); - CFG_CHECK(ParseTuple, handle, &tuple, &parse); -@@ -472,7 +467,7 @@ - link->irq.IRQInfo2 |= 1 << irq_list[i]; - - link->irq.Handler = orinoco_interrupt; -- link->irq.Instance = priv; -+ link->irq.Instance = dev; - - CS_CHECK(RequestIRQ, link->handle, &link->irq); - } -@@ -532,7 +527,7 @@ - return; - - cs_failed: -- cs_error(link->handle, last_fn, last_ret); -+ orinoco_cs_error(link->handle, last_fn, last_ret); - - failed: - orinoco_cs_release((u_long) link); -@@ -549,18 +544,13 @@ - dev_link_t *link = (dev_link_t *) arg; - struct net_device *dev = link->priv; - struct orinoco_private *priv = dev->priv; -+ unsigned long flags; - -- /* -- If the device is currently in use, we won't release until it -- is actually closed, because until then, we can't be sure that -- no one will try to access the device or its data structures. -- */ -- if (priv->open) { -- DEBUG(0, "orinoco_cs: release postponed, '%s' still open\n", -- link->dev->dev_name); -- link->state |= DEV_STALE_CONFIG; -- return; -- } -+ /* We're committed to taking the device away now, so mark the -+ * hardware as unavailable */ -+ spin_lock_irqsave(&priv->lock, flags); -+ priv->hw_unavailable++; -+ spin_unlock_irqrestore(&priv->lock, flags); - - /* Don't bother checking to see if these succeed or not */ - CardServices(ReleaseConfiguration, link->handle); -@@ -593,14 +583,9 @@ - orinoco_lock(priv, &flags); - - netif_device_detach(dev); -- priv->hw_unavailable = 1; -+ priv->hw_unavailable++; - - orinoco_unlock(priv, &flags); -- --/* if (link->open) */ --/* orinoco_cs_stop(dev); */ -- -- mod_timer(&link->release, jiffies + HZ / 20); - } - break; - -@@ -619,13 +604,8 @@ - a better way, short of rewriting the PCMCIA - layer to not suck :-( */ - if (! test_bit(0, &card->hard_reset_in_progress)) { -- err = orinoco_lock(priv, &flags); -- if (err) { -- printk(KERN_ERR "%s: hw_unavailable on SUSPEND/RESET_PHYSICAL\n", -- dev->name); -- break; -- } -- -+ spin_lock_irqsave(&priv->lock, flags); -+ - err = __orinoco_down(dev); - if (err) - printk(KERN_WARNING "%s: %s: Error %d downing interface\n", -@@ -634,9 +614,9 @@ - err); - - netif_device_detach(dev); -- priv->hw_unavailable = 1; -- -- orinoco_unlock(priv, &flags); -+ priv->hw_unavailable++; -+ -+ spin_unlock_irqrestore(&priv->lock, flags); - } - - CardServices(ReleaseConfiguration, link->handle); -@@ -653,10 +633,6 @@ - CardServices(RequestConfiguration, link->handle, - &link->conf); - -- /* If we're only getting these events because -- of the ResetCard in the hard reset, we -- don't need to do anything - orinoco_reset() -- will handle reinitialization. */ - if (! test_bit(0, &card->hard_reset_in_progress)) { - err = orinoco_reinit_firmware(dev); - if (err) { -@@ -668,9 +644,9 @@ - spin_lock_irqsave(&priv->lock, flags); - - netif_device_attach(dev); -- priv->hw_unavailable = 0; -+ priv->hw_unavailable--; - -- if (priv->open) { -+ if (priv->open && ! priv->hw_unavailable) { - err = __orinoco_up(dev); - if (err) - printk(KERN_ERR "%s: Error %d restarting card\n", -@@ -678,7 +654,7 @@ - - } - -- orinoco_unlock(priv, &flags); -+ spin_unlock_irqrestore(&priv->lock, flags); - } - } - break; -@@ -693,7 +669,7 @@ - - /* Can't be declared "const" or the whole __initdata section will - * become const */ --static char version[] __initdata = "orinoco_cs.c 0.13b (David Gibson and others)"; -+static char version[] __initdata = "orinoco_cs.c 0.13e (David Gibson and others)"; - - static int __init - init_orinoco_cs(void) -@@ -722,7 +698,6 @@ - if (dev_list) - DEBUG(0, "orinoco_cs: Removing leftover devices.\n"); - while (dev_list != NULL) { -- del_timer(&dev_list->release); - if (dev_list->state & DEV_CONFIG) - orinoco_cs_release((u_long) dev_list); - orinoco_cs_detach(dev_list); ---- linux-2.4.21/drivers/pcmcia/pxa/Makefile~ramses-pcmcia -+++ linux-2.4.21/drivers/pcmcia/pxa/Makefile -@@ -12,6 +12,7 @@ - obj-$(CONFIG_ARCH_PXA_IDP) += pxa_idp.o - obj-$(CONFIG_ARCH_TRIZEPS2) += trizeps2.o - obj-$(CONFIG_ARCH_PXA_CERF) += ../sa1100_cerf.o -+obj-$(CONFIG_ARCH_RAMSES) += ramses.o - - obj-m := $(O_TARGET) - ---- linux-2.4.21/drivers/pcmcia/pxa/pxa.c~pxa-pcmcia -+++ linux-2.4.21/drivers/pcmcia/pxa/pxa.c -@@ -187,7 +187,6 @@ - struct pcmcia_state state[PXA_PCMCIA_MAX_SOCK]; - struct pcmcia_state_array state_array; - unsigned int i, clock; -- unsigned long mecr; - - printk(KERN_INFO "Intel PXA250/210 PCMCIA (CS release %s)\n", CS_RELEASE); - -@@ -240,6 +239,8 @@ - pcmcia_low_level=&pxa_idp_pcmcia_ops; - } else if( machine_is_pxa_cerf()){ - pcmcia_low_level=&cerf_pcmcia_ops; -+ } else if( machine_is_ramses()){ -+ pcmcia_low_level=&ramses_pcmcia_ops; - } else if (machine_is_trizeps2()){ - #ifdef CONFIG_ARCH_TRIZEPS2 - pcmcia_low_level=&trizeps2_pcmcia_ops; -@@ -835,7 +836,7 @@ - static int pxa_pcmcia_set_io_map(unsigned int sock, - struct pccard_io_map *map){ - unsigned int clock, speed; -- unsigned long mecr, start; -+ unsigned long start; - - DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock); - -@@ -941,7 +942,7 @@ - static int pxa_pcmcia_set_mem_map(unsigned int sock, - struct pccard_mem_map *map){ - unsigned int clock, speed; -- unsigned long mecr, start; -+ unsigned long start; - - DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock); - -@@ -1076,7 +1077,6 @@ - char *p=buf; - unsigned int sock=(unsigned int)data; - unsigned int clock = get_lclk_frequency_10khz(); -- unsigned long mecr = MECR; - - p+=sprintf(p, "k_flags : %s%s%s%s%s%s%s\n", - pxa_pcmcia_socket[sock].k_state.detect?"detect ":"", ---- linux-2.4.21/drivers/pcmcia/pxa/pxa.h~ramses-pcmcia -+++ linux-2.4.21/drivers/pcmcia/pxa/pxa.h -@@ -228,6 +228,7 @@ - extern struct pcmcia_low_level lubbock_pcmcia_ops; - extern struct pcmcia_low_level pxa_idp_pcmcia_ops; - extern struct pcmcia_low_level cerf_pcmcia_ops; -+extern struct pcmcia_low_level ramses_pcmcia_ops; - extern struct pcmcia_low_level trizeps2_pcmcia_ops; - - #endif /* !defined(_PCMCIA_PXA_H) */ ---- /dev/null -+++ linux-2.4.21/drivers/pcmcia/pxa/ramses.c -@@ -0,0 +1,223 @@ -+/* -+ * linux/drivers/pcmcia/pxa/ramses.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. -+ * -+ * Copyright (c) 2003 M&N Logistik-Lösungen Online GmbH -+ * -+ * Platform specific routines for the Ramses, based on those -+ * first done for the Lubbock and PXA IDP. -+ * -+ */ -+ -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+static int -+ramses_pcmcia_init(struct pcmcia_init *init) -+{ -+ int return_val = 0; -+ -+ /* Set PCMCIA Socket 0 power to standby mode. -+ * RAMSES has dedicated CPLD pins for all this stuff :-) -+ */ -+ -+ /* both slots disabled, reset NOT active */ -+ RAMSES_CPLD_PCCARD_EN = PCC0_ENABLE | PCC1_ENABLE; -+ -+ RAMSES_CPLD_PCCARD_PWR = 0; //all power to both slots off -+ //GPDR(IRQ_TO_GPIO_2_80(CFCARD_CD_VALID)) &= ~GPIO_bit(IRQ_TO_GPIO_2_80(CFCARD_CD_VALID)); -+ set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(CFCARD_CD_VALID), GPIO_BOTH_EDGES); -+ //GPDR(IRQ_TO_GPIO_2_80(CFCARD_RDYINT)) &= ~GPIO_bit(IRQ_TO_GPIO_2_80(CFCARD_RDYINT)); -+ set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(CFCARD_RDYINT), GPIO_FALLING_EDGE); -+ -+ return_val += -+ request_irq(CFCARD_CD_VALID, init->handler, SA_INTERRUPT, -+ "CF-Card CD", NULL); -+ -+ if (return_val < 0) { -+ return -1; -+ } -+ -+ return 2; -+} -+ -+static int -+ramses_pcmcia_shutdown(void) -+{ -+ -+ free_irq(CFCARD_CD_VALID, NULL); -+ -+ RAMSES_CPLD_PCCARD_EN = 0x03; //disable slots -+ udelay(200); -+ RAMSES_CPLD_PCCARD_PWR = 0; //shut off all power -+ -+ return 0; -+} -+ -+static int -+ramses_pcmcia_socket_state(struct pcmcia_state_array *state_array) -+{ -+ unsigned long status; -+ int return_val = 1; -+ int i; -+ volatile unsigned long *stat_regs[2] = { -+ &RAMSES_CPLD_PCCARD0_STATUS, -+ &RAMSES_CPLD_PCCARD1_STATUS -+ }; -+ -+ if (state_array->size < 2) -+ return -1; -+ -+ memset(state_array->state, 0, -+ (state_array->size) * sizeof (struct pcmcia_state)); -+ -+ for (i = 1; i < 2; i++) { -+ -+ status = *stat_regs[i]; -+ -+ /* this one is a gpio */ -+ state_array->state[i].detect = (PCC_DETECT(i)) ? 0 : 1; -+ -+ state_array->state[i].ready = ((status & _PCC_IRQ) == 0) ? 0 : 1; -+ state_array->state[i].bvd1 = (status & PCC_BVD1) ? 0 : 1; -+ state_array->state[i].bvd2 = (status & PCC_BVD2) ? 0 : 1; -+ state_array->state[i].wrprot = (status & _PCC_WRPROT) ? 1 : 0; -+ state_array->state[i].vs_3v = (status & PCC_VS1) ? 0 : 1; -+ state_array->state[i].vs_Xv = (status & PCC_VS2) ? 0 : 1; -+ } -+ -+ state_array->state[0].detect = 0; -+ state_array->state[0].ready = 0; -+ state_array->state[0].bvd1 = 0; -+ state_array->state[0].bvd2 = 0; -+ state_array->state[0].wrprot = 0; -+ state_array->state[0].vs_3v = 0; -+ state_array->state[0].vs_Xv = 0; -+ -+ return return_val; -+} -+ -+static int -+ramses_pcmcia_get_irq_info(struct pcmcia_irq_info *info) -+{ -+ switch (info->sock) { -+ case 0: -+ //info->irq = PCMCIA_S0_RDYINT; -+ //printk("//hs ramses_pcmcia_get_irq_info called for slot 0\n"); -+ break; -+ -+ case 1: -+ info->irq = CFCARD_RDYINT; -+ break; -+ -+ default: -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static int -+ramses_pcmcia_configure_socket(unsigned int sock, socket_state_t *state) -+{ -+ /* The Ramses uses the Maxim MAX1602, with the following connections: -+ * -+ * Socket 0 (PCMCIA): -+ * MAX1602 PXA_IDP Register -+ * Pin Signal RAMSES_CPLD_PCCARD_PWR: -+ * ----- ------- ---------------------- -+ * A0VPP PCC0_PWR0 bit0 -+ * A1VPP PCC0_PWR1 bit1 -+ * A0VCC PCC0_PWR2 bit2 -+ * A1VCC PCC0_PWR3 bit3 -+ * VX VCC -+ * VY +3.3V -+ * 12IN +12V -+ * CODE +3.3V Cirrus Code, CODE = High (VY) -+ * -+ * Socket 1 (PCMCIA): -+ * MAX1602 PXA_IDP Register -+ * Pin Signal RAMSES_CPLD_PCCARD_PWR: -+ * ----- ------- ---------------------- -+ * A0VPP PCC1_PWR0 bit4 -+ * A1VPP PCC1_PWR1 bit5 -+ * A0VCC PCC1_PWR2 bit6 -+ * A1VCC PCC1_PWR3 bit7 -+ * VX VCC -+ * VY +3.3V -+ * 12IN +12V -+ * CODE +3.3V Cirrus Code, CODE = High (VY) -+ * -+ */ -+ -+ if (sock == 1) { -+ -+ switch (state->Vcc) { -+ case 0: -+ RAMSES_CPLD_PCCARD_EN |= PCC1_ENABLE; // disable socket -+ udelay(200); -+ RAMSES_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3); -+ break; -+ -+ case 33: -+ RAMSES_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3); -+ RAMSES_CPLD_PCCARD_PWR |= PCC1_PWR3; -+ RAMSES_CPLD_PCCARD_EN &= ~PCC1_ENABLE; //turn it on -+ break; -+ -+ case 50: -+ RAMSES_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3); -+ RAMSES_CPLD_PCCARD_PWR |= PCC1_PWR2; -+ RAMSES_CPLD_PCCARD_EN &= ~PCC1_ENABLE; -+ break; -+ -+ default: -+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", -+ __FUNCTION__, state->Vcc); -+ return -1; -+ } -+ -+ switch (state->Vpp) { -+ case 0: -+ RAMSES_CPLD_PCCARD_PWR &= ~(PCC1_PWR0 | PCC1_PWR1); -+ break; -+ -+ case 120: -+ RAMSES_CPLD_PCCARD_PWR &= ~(PCC1_PWR0 | PCC1_PWR1); -+ RAMSES_CPLD_PCCARD_PWR |= PCC1_PWR1; -+ break; -+ -+ default: -+ if (state->Vpp == state->Vcc) -+ RAMSES_CPLD_PCCARD_PWR = -+ (RAMSES_CPLD_PCCARD_PWR & -+ ~(PCC1_PWR0 | PCC1_PWR1)) | PCC1_PWR0; -+ else { -+ printk(KERN_ERR "%s(): unrecognized Vpp %u\n", -+ __FUNCTION__, state->Vpp); -+ return -1; -+ } -+ } -+ RAMSES_CPLD_PCCARD_EN = (state->flags & SS_RESET) ? (RAMSES_CPLD_PCCARD_EN | PCC1_RESET) -+ : (RAMSES_CPLD_PCCARD_EN & ~PCC1_RESET); -+ } -+ return 0; -+} -+ -+struct pcmcia_low_level ramses_pcmcia_ops = { -+ ramses_pcmcia_init, -+ ramses_pcmcia_shutdown, -+ ramses_pcmcia_socket_state, -+ ramses_pcmcia_get_irq_info, -+ ramses_pcmcia_configure_socket -+}; ---- linux-2.4.21/drivers/scsi/scsi.h~usb-sonycamera -+++ linux-2.4.21/drivers/scsi/scsi.h -@@ -610,6 +610,7 @@ - unsigned remap:1; /* support remapping */ - unsigned starved:1; /* unable to process commands because - host busy */ -+ unsigned no_start_on_add:1; /* do not issue start on add */ - - // Flag to allow revalidate to succeed in sd_open - int allow_revalidate; ---- linux-2.4.21/drivers/scsi/scsi_scan.c~usb-sonycamera -+++ linux-2.4.21/drivers/scsi/scsi_scan.c -@@ -37,6 +37,8 @@ - #define BLIST_ISDISK 0x100 /* Treat as (removable) disk */ - #define BLIST_ISROM 0x200 /* Treat as (removable) CD-ROM */ - #define BLIST_LARGELUN 0x400 /* LUNs larger than 7 despite reporting as SCSI 2 */ -+#define BLIST_NOSTARTONADD 0x1000 /* do not do automatic start on add */ -+ - - static void print_inquiry(unsigned char *data); - static int scan_scsis_single(unsigned int channel, unsigned int dev, -@@ -110,9 +112,10 @@ - {"HP", "C1750A", "3226", BLIST_NOLUN}, /* scanjet iic */ - {"HP", "C1790A", "", BLIST_NOLUN}, /* scanjet iip */ - {"HP", "C2500A", "", BLIST_NOLUN}, /* scanjet iicx */ -- {"HP", "A6188A", "*", BLIST_SPARSELUN}, /* HP Va7100 Array */ -- {"HP", "A6189A", "*", BLIST_SPARSELUN}, /* HP Va7400 Array */ -- {"HP", "A6189B", "*", BLIST_SPARSELUN}, /* HP Va7410 Array */ -+ {"HP", "A6188A", "*", BLIST_SPARSELUN | BLIST_LARGELUN},/* HP Va7100 Array */ -+ {"HP", "A6189A", "*", BLIST_SPARSELUN | BLIST_LARGELUN},/* HP Va7400 Array */ -+ {"HP", "A6189B", "*", BLIST_SPARSELUN | BLIST_LARGELUN},/* HP Va7110 Array */ -+ {"HP", "A6218A", "*", BLIST_SPARSELUN | BLIST_LARGELUN},/* HP Va7410 Array */ - {"YAMAHA", "CDR100", "1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ - {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0 - * extra reset */ -@@ -145,7 +148,7 @@ - {"EMULEX", "MD21/S2 ESDI", "*", BLIST_SINGLELUN}, - {"CANON", "IPUBJD", "*", BLIST_SPARSELUN}, - {"nCipher", "Fastness Crypto", "*", BLIST_FORCELUN}, -- {"DEC","HSG80","*", BLIST_FORCELUN}, -+ {"DEC","HSG80","*", BLIST_FORCELUN | BLIST_NOSTARTONADD}, - {"COMPAQ","LOGICAL VOLUME","*", BLIST_FORCELUN}, - {"COMPAQ","CR3500","*", BLIST_FORCELUN}, - {"NEC", "PD-1 ODX654P", "*", BLIST_FORCELUN | BLIST_SINGLELUN}, -@@ -173,7 +176,11 @@ - {"HP", "NetRAID-4M", "*", BLIST_FORCELUN}, - {"ADAPTEC", "AACRAID", "*", BLIST_FORCELUN}, - {"ADAPTEC", "Adaptec 5400S", "*", BLIST_FORCELUN}, -- {"COMPAQ", "MSA1000", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, -+ {"APPLE", "Xserve", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, -+ {"COMPAQ", "MSA1000", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_NOSTARTONADD}, -+ {"COMPAQ", "MSA1000 VOLUME", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_NOSTARTONADD}, -+ {"COMPAQ", "HSV110", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_NOSTARTONADD}, -+ {"HP", "HSV100", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_NOSTARTONADD}, - {"HP", "C1557A", "*", BLIST_FORCELUN}, - {"IBM", "AuSaV1S2", "*", BLIST_FORCELUN}, - {"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, -@@ -182,7 +189,8 @@ - {"HITACHI", "DF500", "*", BLIST_SPARSELUN}, - {"HITACHI", "DF600", "*", BLIST_SPARSELUN}, - {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, -- {"HITACHI", "OPEN-", "*", BLIST_SPARSELUN}, /* HITACHI XP Arrays */ -+ {"HITACHI", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HITACHI XP Arrays */ -+ {"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HITACHI 9960 */ - {"WINSYS","FLASHDISK G6", "*", BLIST_SPARSELUN}, - {"DotHill","SANnet RAID X300", "*", BLIST_SPARSELUN}, - {"SUN", "T300", "*", BLIST_SPARSELUN}, -@@ -194,6 +202,12 @@ - {"SGI", "TP9400", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"SGI", "TP9500", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"MYLEX", "DACARMRB", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, -+ {"PLATYPUS", "CX5", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, -+ {"Raidtec", "FCR", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, -+ {"HP", "C7200", "*", BLIST_SPARSELUN}, /* Medium Changer */ -+ {"SMSC", "USB 2 HS", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, -+ {"XYRATEX", "RS", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, -+ {"NEC", "iStorage", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN}, - - /* - * Must be at end of list... -@@ -209,10 +223,14 @@ - static unsigned int max_scsi_luns = 1; - #endif - -+static unsigned int scsi_allow_ghost_devices = 0; -+ - #ifdef MODULE - - MODULE_PARM(max_scsi_luns, "i"); - MODULE_PARM_DESC(max_scsi_luns, "last scsi LUN (should be between 1 and 2^32-1)"); -+MODULE_PARM(scsi_allow_ghost_devices, "i"); -+MODULE_PARM_DESC(scsi_allow_ghost_devices, "allow devices marked as being offline to be accessed anyway (0 = off, else allow ghosts on lun 0 through scsi_allow_ghost_devices - 1"); - - #else - -@@ -232,6 +250,21 @@ - - __setup("max_scsi_luns=", scsi_luns_setup); - -+static int __init scsi_allow_ghost_devices_setup(char *str) -+{ -+ unsigned int tmp; -+ -+ if (get_option(&str, &tmp) == 1) { -+ scsi_allow_ghost_devices = tmp; -+ return 1; -+ } else { -+ printk("scsi_allow_ghost_devices_setup: usage scsi_allow_ghost_devices=n (0: off else\nallow ghost devices (ghost devices are devices that report themselves as\nbeing offline but which we allow access to anyway) on lun 0 through n - 1.\n"); -+ return 0; -+ } -+} -+ -+__setup("scsi_allow_ghost_devices=", scsi_allow_ghost_devices_setup); -+ - #endif - - static void print_inquiry(unsigned char *data) -@@ -608,6 +641,7 @@ - } else { - /* assume no peripheral if any other sort of error */ - scsi_release_request(SRpnt); -+ scsi_release_commandblocks(SDpnt); - return 0; - } - } -@@ -618,6 +652,24 @@ - */ - - /* -+ * If we are offline and we are on a LUN != 0, then skip this entry. -+ * If we are on a BLIST_FORCELUN device this will stop the scan at -+ * the first offline LUN (typically the correct thing to do). If -+ * we are on a BLIST_SPARSELUN device then this won't stop the scan, -+ * but it will keep us from having false entries in our device -+ * array. DL -+ * -+ * NOTE: Need to test this to make sure it doesn't cause problems -+ * with tape autoloaders, multidisc CD changers, and external -+ * RAID chassis that might use sparse luns or multiluns... DL -+ */ -+ if (lun != 0 && (scsi_result[0] >> 5) == 1) { -+ scsi_release_request(SRpnt); -+ scsi_release_commandblocks(SDpnt); -+ return 0; -+ } -+ -+ /* - * Get any flags for this device. - */ - bflags = get_device_flags (scsi_result); -@@ -655,8 +707,11 @@ - - SDpnt->removable = (0x80 & scsi_result[1]) >> 7; - /* Use the peripheral qualifier field to determine online/offline */ -- if (((scsi_result[0] >> 5) & 7) == 1) SDpnt->online = FALSE; -- else SDpnt->online = TRUE; -+ if ((((scsi_result[0] >> 5) & 7) == 1) && -+ (lun >= scsi_allow_ghost_devices)) -+ SDpnt->online = FALSE; -+ else -+ SDpnt->online = TRUE; - SDpnt->lockable = SDpnt->removable; - SDpnt->changed = 0; - SDpnt->access_count = 0; -@@ -742,6 +797,13 @@ - if ((bflags & BLIST_BORKEN) == 0) - SDpnt->borken = 0; - -+ /* -+ * Some devices may not want to have a start command automatically -+ * issued when a device is added. -+ */ -+ if (bflags & BLIST_NOSTARTONADD) -+ SDpnt->no_start_on_add = 1; -+ - /* - * If we want to only allow I/O to one of the luns attached to this device - * at a time, then we set this flag. -@@ -857,11 +919,26 @@ - * I think we need REPORT LUNS in future to avoid scanning - * of unused LUNs. But, that is another item. - */ -+ /* - if (*max_dev_lun < shpnt->max_lun) - *max_dev_lun = shpnt->max_lun; - else if ((max_scsi_luns >> 1) >= *max_dev_lun) - *max_dev_lun += shpnt->max_lun; - else *max_dev_lun = max_scsi_luns; -+ */ -+ /* -+ * Blech...the above code is broken. When you have a device -+ * that is present, and it is a FORCELUN device, then we -+ * need to scan *all* the luns on that device. Besides, -+ * skipping the scanning of LUNs is a false optimization. -+ * Scanning for a LUN on a present device is a very fast -+ * operation, it's scanning for devices that don't exist that -+ * is expensive and slow (although if you are truly scanning -+ * through MAX_SCSI_LUNS devices that would be bad, I hope -+ * all of the controllers out there set a reasonable value -+ * in shpnt->max_lun). DL -+ */ -+ *max_dev_lun = shpnt->max_lun; - return 1; - } - /* ---- linux-2.4.21/drivers/scsi/sd.c~usb-sonycamera -+++ linux-2.4.21/drivers/scsi/sd.c -@@ -775,7 +775,8 @@ - char nbuff[6]; - unsigned char *buffer; - unsigned long spintime_value = 0; -- int the_result, retries, spintime; -+ int retries, spintime; -+ unsigned int the_result; - int sector_size; - Scsi_Request *SRpnt; - -@@ -817,7 +818,7 @@ - do { - retries = 0; - -- while (retries < 3) { -+ do { - cmd[0] = TEST_UNIT_READY; - cmd[1] = (rscsi_disks[i].device->scsi_level <= SCSI_2) ? - ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0; -@@ -832,10 +833,10 @@ - - the_result = SRpnt->sr_result; - retries++; -- if (the_result == 0 -- || SRpnt->sr_sense_buffer[2] != UNIT_ATTENTION) -- break; -- } -+ } while (retries < 3 -+ && (the_result !=0 -+ || ((driver_byte(the_result) & DRIVER_SENSE) -+ && SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION))); - - /* - * If the drive has indicated to us that it doesn't have -@@ -853,24 +854,47 @@ - break; - } - -+ if ((driver_byte(the_result) & DRIVER_SENSE) == 0) { -+ /* no sense, TUR either succeeded or failed -+ * with a status error */ -+ if(!spintime && the_result != 0) -+ printk(KERN_NOTICE "%s: Unit Not Ready, error = 0x%x\n", nbuff, the_result); -+ break; -+ } -+ -+ /* -+ * The device does not want the automatic start to be issued. -+ */ -+ if (rscsi_disks[i].device->no_start_on_add) { -+ break; -+ } -+ -+ /* -+ * If manual intervention is required, or this is an -+ * absent USB storage device, a spinup is meaningless. -+ */ -+ if (SRpnt->sr_sense_buffer[2] == NOT_READY && -+ SRpnt->sr_sense_buffer[12] == 4 /* not ready */ && -+ SRpnt->sr_sense_buffer[13] == 3) { -+ break; /* manual intervention required */ - /* Look for non-removable devices that return NOT_READY. - * Issue command to spin up drive for these cases. */ -- if (the_result && !rscsi_disks[i].device->removable && -- SRpnt->sr_sense_buffer[2] == NOT_READY) { -+ } else if (the_result && !rscsi_disks[i].device->removable && -+ SRpnt->sr_sense_buffer[2] == NOT_READY) { - unsigned long time1; - if (!spintime) { - printk("%s: Spinning up disk...", nbuff); - cmd[0] = START_STOP; - cmd[1] = (rscsi_disks[i].device->scsi_level <= SCSI_2) ? -- ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0; -- cmd[1] |= 1; /* Return immediately */ -+ ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0; -+ cmd[1] |= 1; /* Return immediately */ - memset((void *) &cmd[2], 0, 8); -- cmd[4] = 1; /* Start spin cycle */ -+ cmd[4] = 1; /* Start spin cycle */ - SRpnt->sr_cmd_len = 0; - SRpnt->sr_sense_buffer[0] = 0; - SRpnt->sr_sense_buffer[2] = 0; - -- SRpnt->sr_data_direction = SCSI_DATA_READ; -+ SRpnt->sr_data_direction = SCSI_DATA_NONE; - scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, - 0/*512*/, SD_TIMEOUT, MAX_RETRIES); - spintime_value = jiffies; -@@ -883,6 +907,14 @@ - time1 = schedule_timeout(time1); - } while(time1); - printk("."); -+ } else { -+ /* we don't understand the sense code, so it's -+ * probably pointless to loop */ -+ if(!spintime) { -+ printk(KERN_NOTICE "%s: Unit Not Ready, sense:\n", nbuff); -+ print_req_sense("", SRpnt); -+ } -+ break; - } - } while (the_result && spintime && - time_after(spintime_value + 100 * HZ, jiffies)); ---- linux-2.4.21/drivers/sound/ac97_codec.c~ucb1x00 -+++ linux-2.4.21/drivers/sound/ac97_codec.c -@@ -547,6 +547,12 @@ - val = SOUND_CAP_EXCL_INPUT; - break; - -+ case SOUND_MIXER_AC97: -+ if (get_user(val, (int *)arg)) -+ return -EFAULT; -+ val = codec->codec_read(codec, val); -+ return put_user(val, (int *)arg); -+ - default: /* read a specific mixer */ - i = _IOC_NR(cmd); - -@@ -575,6 +581,11 @@ - codec->recmask_io(codec, 0, val); - - return 0; -+ -+ case SOUND_MIXER_AC97: -+ codec->codec_write(codec, val >> 16 & 0xffff, val & 0xffff); -+ return 0; -+ - default: /* write a specific mixer */ - i = _IOC_NR(cmd); - ---- linux-2.4.21/drivers/sound/pxa-ac97.c~pxa-ac97 -+++ linux-2.4.21/drivers/sound/pxa-ac97.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -164,6 +165,11 @@ - //pxa_ac97_write(&pxa_ac97_codec, 0x6a, 0x1ff7); - pxa_ac97_write(&pxa_ac97_codec, 0x6a, 0x0050); - pxa_ac97_write(&pxa_ac97_codec, 0x6c, 0x0030); -+#if CONFIG_ARCH_RAMSES -+ pxa_ac97_codec.supported_mixers = SOUND_MASK_VOLUME | SOUND_MASK_IGAIN; -+ pxa_ac97_codec.stereo_mixers = SOUND_MASK_VOLUME | SOUND_MASK_IGAIN; -+ pxa_ac97_codec.record_sources = SOUND_MASK_MIC | SOUND_MASK_LINE; -+#endif - } - - pxa_ac97_refcount++; -@@ -198,7 +204,7 @@ - static int mixer_ioctl( struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) - { -- int ret, val; -+ int ret; - - ret = pxa_ac97_codec.mixer_ioctl(&pxa_ac97_codec, cmd, arg); - if (ret) -@@ -282,6 +288,7 @@ - /* fall through */ - - case SOUND_PCM_READ_RATE: -+ val = 0; - if (file->f_mode & FMODE_READ) - val = codec_adc_rate; - if (file->f_mode & FMODE_WRITE) -@@ -342,6 +349,44 @@ - }; - - -+#ifdef CONFIG_PM -+ -+static int pxa_ac97_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) -+{ -+ down(&pxa_ac97_mutex); -+ -+ switch (rqst) { -+ case PM_SUSPEND: -+ // TODO: set to low-power state? -+ GCR = GCR_ACLINK_OFF; -+ CKEN &= ~CKEN2_AC97; -+ break; -+ -+ case PM_RESUME: -+ CKEN |= CKEN2_AC97; -+ -+ GCR = 0; -+ udelay(10); -+ GCR = GCR_COLD_RST|GCR_CDONE_IE|GCR_SDONE_IE; -+ while (!(GSR & GSR_PCR)) { -+ schedule(); -+ } -+ -+ // need little hack for UCB1400 (should be moved elsewhere) -+ pxa_ac97_write(&pxa_ac97_codec,AC97_EXTENDED_STATUS,1); -+ pxa_ac97_write(&pxa_ac97_codec, 0x6a, 0x0050); -+ pxa_ac97_write(&pxa_ac97_codec, 0x6c, 0x0030); -+ break; -+ } -+ -+ up(&pxa_ac97_mutex); -+ -+ return 0; -+} -+ -+#endif -+ -+ - static int __init pxa_ac97_init(void) - { - int ret; -@@ -354,11 +399,18 @@ - ac97_audio_state.dev_dsp = register_sound_dsp(&ac97_audio_fops, -1); - pxa_ac97_codec.dev_mixer = register_sound_mixer(&mixer_fops, -1); - -+#ifdef PM_DEBUG -+ ac97_audio_state.pmdev = pm_register(PM_SYS_UNKNOWN, 0x71783937, pxa_ac97_pm_callback, "pxa-ac97"); -+#else -+ ac97_audio_state.pmdev = pm_register(PM_SYS_UNKNOWN, 0x71783937, pxa_ac97_pm_callback); -+#endif -+ - return 0; - } - - static void __exit pxa_ac97_exit(void) - { -+ pm_unregister(ac97_audio_state.pmdev); - unregister_sound_dsp(ac97_audio_state.dev_dsp); - unregister_sound_mixer(pxa_ac97_codec.dev_mixer); - pxa_ac97_put(); ---- linux-2.4.21/drivers/sound/pxa-audio.h~pm -+++ linux-2.4.21/drivers/sound/pxa-audio.h -@@ -47,6 +47,9 @@ - int wr_ref:1; /* open reference for playback */ - int (*client_ioctl)(struct inode *, struct file *, uint, ulong); - struct semaphore sem; /* prevent races in attach/release */ -+#ifdef CONFIG_PM -+ struct pm_dev *pmdev; /* Power management */ -+#endif - } audio_state_t; - - extern int pxa_audio_attach(struct inode *inode, struct file *file, ---- linux-2.4.21/drivers/usb/Config.in~pxa-usb -+++ linux-2.4.21/drivers/usb/Config.in -@@ -5,7 +5,7 @@ - comment 'USB support' - - # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. --if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SA1111" = "y" -o "$CONFIG_ARCH_AT91RM9200" = "y" ]; then -+if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SA1111" = "y" -o "$CONFIG_ARCH_AT91RM9200" = "y" -o "$CONFIG_ARCH_PXA" = "y" ]; then - tristate 'Support for USB' CONFIG_USB - else - define_bool CONFIG_USB n ---- linux-2.4.21/drivers/usb/Makefile~usb-sl811 -+++ linux-2.4.21/drivers/usb/Makefile -@@ -80,6 +80,9 @@ - ifeq ($(CONFIG_USB_OHCI),y) - obj-y += host/usb-ohci.o host/usb-ohci-sa1111.o - endif -+ -+subdir-$(CONFIG_USB_SL811HS_ALT)+= host -+ - subdir-$(CONFIG_USB_OHCI_AT91) += host - ifeq ($(CONFIG_USB_OHCI_AT91),y) - obj-y += host/usb-ohci.o ---- linux-2.4.21/drivers/usb/hcd.c~ramses-usb -+++ linux-2.4.21/drivers/usb/hcd.c -@@ -662,7 +662,9 @@ - pci_set_drvdata(dev, hcd); - hcd->driver = driver; - hcd->description = driver->description; -+#ifdef TODO - hcd->pdev = dev; -+#endif - printk (KERN_INFO "%s %s: %s\n", - hcd->description, dev->slot_name, dev->name); - -@@ -1201,6 +1203,7 @@ - return status; - - // NOTE: 2.5 does this if !URB_NO_DMA_MAP transfer flag -+#ifdef TODO - if (usb_pipecontrol (urb->pipe)) - urb->setup_dma = pci_map_single ( - #ifdef CONFIG_PCI -@@ -1223,7 +1226,7 @@ - usb_pipein (urb->pipe) - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE); -- -+#endif - if (urb->dev == hcd->bus->root_hub) - status = rh_urb_enqueue (hcd, urb); - else -@@ -1488,6 +1491,7 @@ - // hcd_monitor_hook(MONITOR_URB_UPDATE, urb, dev) - - // NOTE: 2.5 does this if !URB_NO_DMA_MAP transfer flag -+#ifdef TODO - if (usb_pipecontrol (urb->pipe)) - pci_unmap_single ( - #ifdef CONFIG_PCI -@@ -1510,6 +1514,7 @@ - usb_pipein (urb->pipe) - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE); -+#endif - - /* pass ownership to the completion handler */ - urb->complete (urb); ---- linux-2.4.21/drivers/usb/host/Config.in~usb-sl811 -+++ linux-2.4.21/drivers/usb/host/Config.in -@@ -13,6 +13,9 @@ - fi - dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB - dep_tristate ' SA1111 OHCI-compatible host interface support' CONFIG_USB_OHCI_SA1111 $CONFIG_USB -+if [ "$CONFIG_ARM" = "y" -o "$CONFIG_X86" = "y" ]; then -+ dep_tristate ' SL811HS Alternate (x86, StrongARM, isosynchronous mode)' CONFIG_USB_SL811HS_ALT $CONFIG_USB $CONFIG_EXPERIMENTAL -+fi - if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then - dep_tristate ' AT91RM9200 OHCI-compatible host interface support' CONFIG_USB_OHCI_AT91 $CONFIG_USB - fi ---- linux-2.4.21/drivers/usb/host/Makefile~usb-sl811 -+++ linux-2.4.21/drivers/usb/host/Makefile -@@ -10,6 +10,7 @@ - obj-$(CONFIG_USB_UHCI) += usb-uhci.o - obj-$(CONFIG_USB_OHCI) += usb-ohci.o usb-ohci-pci.o - obj-$(CONFIG_USB_OHCI_SA1111) += usb-ohci.o usb-ohci-sa1111.o -+obj-$(CONFIG_USB_SL811HS_ALT) += sl811.o - obj-$(CONFIG_USB_OHCI_AT91) += usb-ohci.o - - # Extract lists of the multi-part drivers. ---- /dev/null -+++ linux-2.4.21/drivers/usb/host/sl811.c -@@ -0,0 +1,2782 @@ -+/* -+ * SL811 Host Controller Interface driver for USB. -+ * -+ * Copyright (c) 2003/06, Courage Co., Ltd. -+ * -+ * Based on: -+ * 1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap, -+ * Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, -+ * Adam Richter, Gregory P. Smith; -+ * 2.Original SL811 driver (hc_sl811.o) by Pei Liu -+ * 3.Rewrited as sl811.o by Yin Aihua -+ * -+ * It's now support isochornous mode and more effective than hc_sl811.o -+ * Support x86 architecture now. -+ * -+ * 19.09.2003 (05.06.2003) HNE -+ * sl811_alloc_hc: Set "bus->bus_name" at init. -+ * sl811_reg_test (hc_reset,regTest): -+ * Stop output at first failed pattern. -+ * Down-Grade for Kernel 2.4.20 and from 2.4.22 -+ * Split hardware dependency into files sl811-x86.h and sl811-arm.h. -+ * -+ * 22.09.2003 HNE -+ * sl811_found_hc: First patterntest, than interrupt enable. -+ * Do nothing, if patterntest failed. Release IO if failed. -+ * Stop Interrupts first, than remove handle. (Old blocked Shared IRQ) -+ * Alternate IO-Base for second Controller (CF/USB1). -+ * -+ * 24.09.2003 HNE -+ * Remove all arm specific source (moved into include/asm/sl811-hw.h). -+ * -+ * 03.10.2003 HNE -+ * Low level only for port IO into hardware-include. -+ * -+ * To do: -+ * 1.Modify the timeout part, it's some messy -+ * 2.Use usb-a and usb-b set in Ping-Pong mode -+ * o Floppy do not work. -+ * o driver crash, if io region can't register -+ * o Only tested as module. Compiled-in version not tested! -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the 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 "../hcd.h" -+#include "../hub.h" -+#include "sl811.h" -+ -+#define DRIVER_VERSION "v0.30" -+#define MODNAME "SL811" -+#define DRIVER_AUTHOR "Yin Aihua , Henry Nestler " -+#define DRIVER_DESC "Sl811 USB Host Controller Alternate Driver" -+ -+static LIST_HEAD(sl811_hcd_list); -+ -+/* -+ * 0: normal prompt and information -+ * 1: error should not occur in normal -+ * 2: error maybe occur in normal -+ * 3: useful and detail debug information -+ * 4: function level enter and level inforamtion -+ * 5: endless information will output because of timer function or interrupt -+ */ -+static int debug = 0; -+MODULE_PARM(debug,"i"); -+MODULE_PARM_DESC(debug,"debug level"); -+ -+#include /* Include hardware and board depens */ -+ -+static void sl811_rh_int_timer_do(unsigned long ptr); -+static void sl811_transfer_done(struct sl811_hc *hc, int sof); -+ -+/* -+ * Read a byte of data from the SL811H/SL11H -+ */ -+static __u8 inline sl811_read(struct sl811_hc *hc, __u8 offset) -+{ -+ sl811_write_index (hc, offset); -+ return (sl811_read_data (hc)); -+} -+ -+/* -+ * Write a byte of data to the SL811H/SL11H -+ */ -+static void inline sl811_write(struct sl811_hc *hc, __u8 offset, __u8 data) -+{ -+ sl811_write_index_data (hc, offset, data); -+} -+ -+/* -+ * Read consecutive bytes of data from the SL811H/SL11H buffer -+ */ -+static void inline sl811_read_buf(struct sl811_hc *hc, __u8 offset, __u8 *buf, __u8 size) -+{ -+ sl811_write_index (hc, offset); -+ while (size--) { -+ *buf++ = sl811_read_data(hc); -+ } -+} -+ -+/* -+ * Write consecutive bytes of data to the SL811H/SL11H buffer -+ */ -+static void inline sl811_write_buf(struct sl811_hc *hc, __u8 offset, __u8 *buf, __u8 size) -+{ -+ sl811_write_index (hc, offset); -+ while (size--) { -+ sl811_write_data (hc, *buf); -+ buf++; -+ } -+} -+ -+/* -+ * This routine test the Read/Write functionality of SL811HS registers -+ */ -+static int sl811_reg_test(struct sl811_hc *hc) -+{ -+ int i, data, result = 0; -+ __u8 buf[256]; -+ -+ for (i = 0x10; i < 256; i++) { -+ /* save the original buffer */ -+ buf[i] = sl811_read(hc, i); -+ -+ /* Write the new data to the buffer */ -+ sl811_write(hc, i, ~i); -+ } -+ -+ /* compare the written data */ -+ for (i = 0x10; i < 256; i++) { -+ data = sl811_read(hc, i); -+ if (data != (__u8) ~i) { -+ PDEBUG(1, "reg %02x expected %02x got %02x", i, (__u8) ~i, data); -+ result = -1; -+ -+ /* If no Debug, show only first failed Address */ -+ if (!debug) -+ break; -+ } -+ } -+ -+ /* restore the data */ -+ for (i = 0x10; i < 256; i++) -+ sl811_write(hc, i, buf[i]); -+ -+ return result; -+} -+ -+/* -+ * Display all SL811HS register values -+ */ -+#if 0 /* unused (hne) */ -+static void sl811_reg_show(struct sl811_hc *hc) -+{ -+ int i; -+ -+ for (i = 0; i < 256; i++) -+ PDEBUG(4, "offset %d: 0x%x", i, sl811_read(hc, i)); -+} -+#endif -+ -+/* -+ * This function enables SL811HS interrupts -+ */ -+static void sl811_enable_interrupt(struct sl811_hc *hc) -+{ -+ PDEBUG(4, "enter"); -+ sl811_write(hc, SL811_INTR, SL811_INTR_DONE_A | SL811_INTR_SOF | SL811_INTR_INSRMV); -+} -+ -+/* -+ * This function disables SL811HS interrupts -+ */ -+static void sl811_disable_interrupt(struct sl811_hc *hc) -+{ -+ PDEBUG(4, "enter"); -+ // Disable all other interrupt except for insert/remove. -+ sl811_write(hc, SL811_INTR, SL811_INTR_INSRMV); -+} -+ -+/* -+ * SL811 Virtual Root Hub -+ */ -+ -+/* Device descriptor */ -+static __u8 sl811_rh_dev_des[] = -+{ -+ 0x12, /* __u8 bLength; */ -+ 0x01, /* __u8 bDescriptorType; Device */ -+ 0x10, /* __u16 bcdUSB; v1.1 */ -+ 0x01, -+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ -+ 0x00, /* __u8 bDeviceSubClass; */ -+ 0x00, /* __u8 bDeviceProtocol; */ -+ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ -+ 0x00, /* __u16 idVendor; */ -+ 0x00, -+ 0x00, /* __u16 idProduct; */ -+ 0x00, -+ 0x00, /* __u16 bcdDevice; */ -+ 0x00, -+ 0x00, /* __u8 iManufacturer; */ -+ 0x02, /* __u8 iProduct; */ -+ 0x01, /* __u8 iSerialNumber; */ -+ 0x01 /* __u8 bNumConfigurations; */ -+}; -+ -+/* Configuration descriptor */ -+static __u8 sl811_rh_config_des[] = -+{ -+ 0x09, /* __u8 bLength; */ -+ 0x02, /* __u8 bDescriptorType; Configuration */ -+ 0x19, /* __u16 wTotalLength; */ -+ 0x00, -+ 0x01, /* __u8 bNumInterfaces; */ -+ 0x01, /* __u8 bConfigurationValue; */ -+ 0x00, /* __u8 iConfiguration; */ -+ 0x40, /* __u8 bmAttributes; -+ Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, -+ 4..0: resvd */ -+ 0x00, /* __u8 MaxPower; */ -+ -+ /* interface */ -+ 0x09, /* __u8 if_bLength; */ -+ 0x04, /* __u8 if_bDescriptorType; Interface */ -+ 0x00, /* __u8 if_bInterfaceNumber; */ -+ 0x00, /* __u8 if_bAlternateSetting; */ -+ 0x01, /* __u8 if_bNumEndpoints; */ -+ 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ -+ 0x00, /* __u8 if_bInterfaceSubClass; */ -+ 0x00, /* __u8 if_bInterfaceProtocol; */ -+ 0x00, /* __u8 if_iInterface; */ -+ -+ /* endpoint */ -+ 0x07, /* __u8 ep_bLength; */ -+ 0x05, /* __u8 ep_bDescriptorType; Endpoint */ -+ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ -+ 0x03, /* __u8 ep_bmAttributes; Interrupt */ -+ 0x08, /* __u16 ep_wMaxPacketSize; */ -+ 0x00, -+ 0xff /* __u8 ep_bInterval; 255 ms */ -+}; -+ -+/* root hub class descriptor*/ -+static __u8 sl811_rh_hub_des[] = -+{ -+ 0x09, /* __u8 bLength; */ -+ 0x29, /* __u8 bDescriptorType; Hub-descriptor */ -+ 0x01, /* __u8 bNbrPorts; */ -+ 0x00, /* __u16 wHubCharacteristics; */ -+ 0x00, -+ 0x50, /* __u8 bPwrOn2pwrGood; 2ms */ -+ 0x00, /* __u8 bHubContrCurrent; 0 mA */ -+ 0xfc, /* __u8 DeviceRemovable; *** 7 Ports max *** */ -+ 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ -+}; -+ -+/* -+ * This function examine the port change in the virtual root hub. HUB INTERRUPT ENDPOINT. -+ */ -+static int sl811_rh_send_irq(struct sl811_hc *hc, __u8 *rh_change, int rh_len) -+{ -+ __u8 data = 0; -+ -+ PDEBUG(5, "enter"); -+ -+ /* -+ * Right now, It is assume the power is good and no changes and only one port. -+ */ -+ if (hc->rh_status.wPortChange & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) { -+ data = 1<<1; -+ *(__u8 *)rh_change = data; -+ return 1; -+ } else -+ return 0; -+} -+ -+/* -+ * This function creates a timer that act as interrupt pipe in the virtual hub. -+ * -+ * Note: The virtual root hub's interrupt pipe are polled by the timer -+ * every "interval" ms -+ */ -+static void sl811_rh_init_int_timer(struct urb * urb) -+{ -+ struct sl811_hc *hc = urb->dev->bus->hcpriv; -+ hc->rh.interval = urb->interval; -+ -+ init_timer(&hc->rh.rh_int_timer); -+ hc->rh.rh_int_timer.function = sl811_rh_int_timer_do; -+ hc->rh.rh_int_timer.data = (unsigned long)urb; -+ hc->rh.rh_int_timer.expires = jiffies + -+ (HZ * (urb->interval < 30? 30: urb->interval)) / 1000; -+ add_timer (&hc->rh.rh_int_timer); -+} -+ -+/* -+ * This function is called when the timer expires. It gets the the port -+ * change data and pass along to the upper protocol. -+ */ -+static void sl811_rh_int_timer_do(unsigned long ptr) -+{ -+ int len; -+ struct urb *urb = (struct urb *)ptr; -+ struct sl811_hc *hc = urb->dev->bus->hcpriv; -+ PDEBUG (5, "enter"); -+ -+ if(hc->rh.send) { -+ len = sl811_rh_send_irq(hc, urb->transfer_buffer, -+ urb->transfer_buffer_length); -+ if (len > 0) { -+ urb->actual_length = len; -+ if (urb->complete) -+ urb->complete(urb); -+ } -+ } -+ -+#ifdef SL811_TIMEOUT -+ -+{ -+ struct list_head *head, *tmp; -+ struct sl811_urb_priv *urbp; -+ struct urb *u; -+ int i; -+ static int timeout_count = 0; -+ -+// check time out every second -+ if (++timeout_count > 4) { -+ int max_scan = hc->active_urbs; -+ timeout_count = 0; -+ for (i = 0; i < 6; ++i) { -+ head = &hc->urb_list[i]; -+ tmp = head->next; -+ while (tmp != head && max_scan--) { -+ u = list_entry(tmp, struct urb, urb_list); -+ urbp = (struct sl811_urb_priv *)u->hcpriv; -+ tmp = tmp->next; -+ // Check if the URB timed out -+ if (u->timeout && time_after_eq(jiffies, urbp->inserttime + u->timeout)) { -+ PDEBUG(3, "urb = %p time out, we kill it", urb); -+ u->transfer_flags |= USB_TIMEOUT_KILLED; -+ } -+ } -+ } -+ } -+} -+ -+#endif -+ // re-activate the timer -+ sl811_rh_init_int_timer(urb); -+} -+ -+/* helper macro */ -+#define OK(x) len = (x); break -+ -+/* -+ * This function handles all USB request to the the virtual root hub -+ */ -+static int sl811_rh_submit_urb(struct urb *urb) -+{ -+ struct usb_device *usb_dev = urb->dev; -+ struct sl811_hc *hc = usb_dev->bus->hcpriv; -+ struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *)urb->setup_packet; -+ void *data = urb->transfer_buffer; -+ int buf_len = urb->transfer_buffer_length; -+ unsigned int pipe = urb->pipe; -+ __u8 data_buf[16]; -+ __u8 *bufp = data_buf; -+ int len = 0; -+ int status = 0; -+ -+ __u16 bmRType_bReq; -+ __u16 wValue; -+ __u16 wIndex; -+ __u16 wLength; -+ -+ if (usb_pipeint(pipe)) { -+ hc->rh.urb = urb; -+ hc->rh.send = 1; -+ hc->rh.interval = urb->interval; -+ sl811_rh_init_int_timer(urb); -+ urb->status = 0; -+ -+ return 0; -+ } -+ -+ bmRType_bReq = cmd->bRequestType | (cmd->bRequest << 8); -+ wValue = le16_to_cpu (cmd->wValue); -+ wIndex = le16_to_cpu (cmd->wIndex); -+ wLength = le16_to_cpu (cmd->wLength); -+ -+ PDEBUG(5, "submit rh urb, req = %d(%x) len=%d", bmRType_bReq, bmRType_bReq, wLength); -+ -+ /* Request Destination: -+ without flags: Device, -+ USB_RECIP_INTERFACE: interface, -+ USB_RECIP_ENDPOINT: endpoint, -+ USB_TYPE_CLASS means HUB here, -+ USB_RECIP_OTHER | USB_TYPE_CLASS almost ever means HUB_PORT here -+ */ -+ switch (bmRType_bReq) { -+ case RH_GET_STATUS: -+ *(__u16 *)bufp = cpu_to_le16(1); -+ OK(2); -+ -+ case RH_GET_STATUS | USB_RECIP_INTERFACE: -+ *(__u16 *)bufp = cpu_to_le16(0); -+ OK(2); -+ -+ case RH_GET_STATUS | USB_RECIP_ENDPOINT: -+ *(__u16 *)bufp = cpu_to_le16(0); -+ OK(2); -+ -+ case RH_GET_STATUS | USB_TYPE_CLASS: -+ *(__u32 *)bufp = cpu_to_le32(0); -+ OK(4); -+ -+ case RH_GET_STATUS | USB_RECIP_OTHER | USB_TYPE_CLASS: -+ *(__u32 *)bufp = cpu_to_le32(hc->rh_status.wPortChange<<16 | hc->rh_status.wPortStatus); -+ OK(4); -+ -+ case RH_CLEAR_FEATURE | USB_RECIP_ENDPOINT: -+ switch (wValue) { -+ case 1: -+ OK(0); -+ } -+ break; -+ -+ case RH_CLEAR_FEATURE | USB_TYPE_CLASS: -+ switch (wValue) { -+ case C_HUB_LOCAL_POWER: -+ OK(0); -+ -+ case C_HUB_OVER_CURRENT: -+ OK(0); -+ } -+ break; -+ -+ case RH_CLEAR_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS: -+ switch (wValue) { -+ case USB_PORT_FEAT_ENABLE: -+ hc->rh_status.wPortStatus &= ~USB_PORT_STAT_ENABLE; -+ OK(0); -+ -+ case USB_PORT_FEAT_SUSPEND: -+ hc->rh_status.wPortStatus &= ~USB_PORT_STAT_SUSPEND; -+ OK(0); -+ -+ case USB_PORT_FEAT_POWER: -+ hc->rh_status.wPortStatus &= ~USB_PORT_STAT_POWER; -+ OK(0); -+ -+ case USB_PORT_FEAT_C_CONNECTION: -+ hc->rh_status.wPortChange &= ~USB_PORT_STAT_C_CONNECTION; -+ OK(0); -+ -+ case USB_PORT_FEAT_C_ENABLE: -+ hc->rh_status.wPortChange &= ~USB_PORT_STAT_C_ENABLE; -+ OK(0); -+ -+ case USB_PORT_FEAT_C_SUSPEND: -+ hc->rh_status.wPortChange &= ~USB_PORT_STAT_C_SUSPEND; -+ OK(0); -+ -+ case USB_PORT_FEAT_C_OVER_CURRENT: -+ hc->rh_status.wPortChange &= ~USB_PORT_STAT_C_OVERCURRENT; -+ OK(0); -+ -+ case USB_PORT_FEAT_C_RESET: -+ hc->rh_status.wPortChange &= ~USB_PORT_STAT_C_RESET; -+ OK(0); -+ } -+ break; -+ -+ case RH_SET_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS: -+ switch (wValue) { -+ case USB_PORT_FEAT_SUSPEND: -+ hc->rh_status.wPortStatus |= USB_PORT_STAT_SUSPEND; -+ OK(0); -+ -+ case USB_PORT_FEAT_RESET: -+ hc->rh_status.wPortStatus |= USB_PORT_STAT_RESET; -+ hc->rh_status.wPortChange = 0; -+ hc->rh_status.wPortChange |= USB_PORT_STAT_C_RESET; -+ hc->rh_status.wPortStatus &= ~USB_PORT_STAT_RESET; -+ hc->rh_status.wPortStatus |= USB_PORT_STAT_ENABLE; -+ OK(0); -+ -+ case USB_PORT_FEAT_POWER: -+ hc->rh_status.wPortStatus |= USB_PORT_STAT_POWER; -+ OK(0); -+ -+ case USB_PORT_FEAT_ENABLE: -+ hc->rh_status.wPortStatus |= USB_PORT_STAT_ENABLE; -+ OK(0); -+ } -+ break; -+ -+ case RH_SET_ADDRESS: -+ hc->rh.devnum = wValue; -+ OK(0); -+ -+ case RH_GET_DESCRIPTOR: -+ switch ((wValue & 0xff00) >> 8) { -+ case USB_DT_DEVICE: -+ len = sizeof(sl811_rh_dev_des); -+ bufp = sl811_rh_dev_des; -+ OK(len); -+ -+ case USB_DT_CONFIG: -+ len = sizeof(sl811_rh_config_des); -+ bufp = sl811_rh_config_des; -+ OK(len); -+ -+ case USB_DT_STRING: -+ len = usb_root_hub_string(wValue & 0xff, (int)(long)0, "SL811HS", data, wLength); -+ if (len > 0) { -+ bufp = data; -+ OK(len); -+ } -+ -+ default: -+ status = -EPIPE; -+ } -+ break; -+ -+ case RH_GET_DESCRIPTOR | USB_TYPE_CLASS: -+ len = sizeof(sl811_rh_hub_des); -+ bufp = sl811_rh_hub_des; -+ OK(len); -+ -+ case RH_GET_CONFIGURATION: -+ bufp[0] = 0x01; -+ OK(1); -+ -+ case RH_SET_CONFIGURATION: -+ OK(0); -+ -+ default: -+ PDEBUG(1, "unsupported root hub command"); -+ status = -EPIPE; -+ } -+ -+ len = min(len, buf_len); -+ if (data != bufp) -+ memcpy(data, bufp, len); -+ urb->actual_length = len; -+ urb->status = status; -+ -+ PDEBUG(5, "len = %d, status = %d", len, status); -+ -+ urb->hcpriv = NULL; -+ urb->dev = NULL; -+ if (urb->complete) -+ urb->complete(urb); -+ -+ return 0; -+} -+ -+/* -+ * This function unlinks the URB -+ */ -+static int sl811_rh_unlink_urb(struct urb *urb) -+{ -+ struct sl811_hc *hc = urb->dev->bus->hcpriv; -+ -+ PDEBUG(5, "enter"); -+ -+ if (hc->rh.urb == urb) { -+ hc->rh.send = 0; -+ del_timer(&hc->rh.rh_int_timer); -+ hc->rh.urb = NULL; -+ urb->hcpriv = NULL; -+ usb_dec_dev_use(urb->dev); -+ urb->dev = NULL; -+ if (urb->transfer_flags & USB_ASYNC_UNLINK) { -+ urb->status = -ECONNRESET; -+ if (urb->complete) -+ urb->complete(urb); -+ } else -+ urb->status = -ENOENT; -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function connect the virtual root hub to the USB stack -+ */ -+static int sl811_connect_rh(struct sl811_hc * hc) -+{ -+ struct usb_device *usb_dev; -+ -+ hc->rh.devnum = 0; -+ usb_dev = usb_alloc_dev(NULL, hc->bus); -+ if (!usb_dev) -+ return -ENOMEM; -+ -+ hc->bus->root_hub = usb_dev; -+ usb_connect(usb_dev); -+ -+ if (usb_new_device(usb_dev)) { -+ usb_free_dev(usb_dev); -+ return -ENODEV; -+ } -+ -+ PDEBUG(5, "leave success"); -+ -+ return 0; -+} -+ -+/* -+ * This function allocates private data space for the usb device -+ */ -+static int sl811_alloc_dev_priv(struct usb_device *usb_dev) -+{ -+ return 0; -+} -+ -+/* -+ * This function de-allocates private data space for the usb devic -+ */ -+static int sl811_free_dev_priv (struct usb_device *usb_dev) -+{ -+ return 0; -+} -+ -+/* -+ * This function allocates private data space for the urb -+ */ -+static struct sl811_urb_priv* sl811_alloc_urb_priv(struct urb *urb) -+{ -+ struct sl811_urb_priv *urbp; -+ -+ urbp = kmalloc(sizeof(*urbp), GFP_KERNEL); -+ if (!urbp) -+ return NULL; -+ -+ memset(urbp, 0, sizeof(*urbp)); -+ -+ INIT_LIST_HEAD(&urbp->td_list); -+ -+ urbp->urb = urb; -+ urb->hcpriv = urbp; -+ -+ return urbp; -+} -+ -+/* -+ * This function free private data space for the urb -+ */ -+static void sl811_free_urb_priv(struct urb *urb) -+{ -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ struct sl811_td *td; -+ struct list_head *head, *tmp; -+ -+ if (!urbp) -+ return ; -+ -+ head = &urbp->td_list; -+ tmp = head->next; -+ -+ while (tmp != head) { -+ td = list_entry(tmp, struct sl811_td, td_list); -+ tmp = tmp->next; -+ kfree(td); -+ } -+ -+ kfree(urbp); -+ urb->hcpriv = NULL; -+ -+ return ; -+} -+ -+/* -+ * This function calculate the bus time need by this td. -+ * Fix me! Can this use usb_calc_bus_time()? -+ */ -+static void sl811_calc_td_time(struct sl811_td *td) -+{ -+#if 1 -+ int time; -+ int len = td->len; -+ struct sl811_hc *hc = td->urb->dev->bus->hcpriv; -+ -+ if (hc->rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) -+ time = 8*8*len + 1024; -+ else { -+ if (td->ctrl & SL811_USB_CTRL_PREAMBLE) -+ time = 8*8*len + 2048; -+ else -+ time = 8*len + 256; -+ } -+ -+ time += 2*10 * len; -+ -+ td->bustime = time; -+ -+#else -+ -+ unsigned long tmp; -+ int time; -+ int low_speed = usb_pipeslow(td->urb->pipe); -+ int input_dir = usb_pipein(td->urb->pipe); -+ int bytecount = td->len; -+ int isoc = usb_pipeisoc(td->urb->pipe); -+ -+ if (low_speed) { /* no isoc. here */ -+ if (input_dir) { -+ tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L; -+ time = (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); -+ } else { -+ tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L; -+ time = (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); -+ } -+ } else if (!isoc){ /* for full-speed: */ -+ tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; -+ time = (9107L + BW_HOST_DELAY + tmp); -+ } else { /* for isoc: */ -+ tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; -+ time = (((input_dir) ? 7268L : 6265L) + BW_HOST_DELAY + tmp); -+ } -+ -+ td->bustime = time / 84; -+ -+#endif -+} -+ -+/* -+ * This function calculate the remainder bus time in current frame. -+ */ -+static inline int sl811_calc_bus_remainder(struct sl811_hc *hc) -+{ -+ return (sl811_read(hc, SL811_SOFCNTDIV) * 64); -+} -+ -+/* -+ * This function allocates td for the urb -+ */ -+static struct sl811_td* sl811_alloc_td(struct urb *urb) -+{ -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ struct sl811_td *td; -+ -+ td = kmalloc(sizeof (*td), GFP_KERNEL); -+ if (!td) -+ return NULL; -+ -+ memset(td, 0, sizeof(*td)); -+ -+ INIT_LIST_HEAD(&td->td_list); -+ -+ td->urb = urb; -+ list_add_tail(&td->td_list, &urbp->td_list); -+ -+ return td; -+} -+ -+/* -+ * Fill the td. -+ */ -+static inline void sl811_fill_td(struct sl811_td *td, __u8 ctrl, __u8 addr, __u8 len, __u8 pidep, __u8 dev, __u8 *buf) -+{ -+ td->ctrl = ctrl; -+ td->addr = addr; -+ td->len = len; -+ td->pidep = pidep; -+ td->dev = dev; -+ td->buf = buf; -+ td->left = len; -+ td->errcnt = 3; -+} -+ -+/* -+ * Fill the td. -+ */ -+static inline void sl811_reset_td(struct sl811_td *td) -+{ -+ td->status = 0; -+ td->left = td->len; -+ td->done = 0; -+ td->errcnt = 3; -+ td->nakcnt = 0; -+ td->td_status = 0; -+} -+ -+static void sl811_print_td(int level, struct sl811_td *td) -+{ -+ PDEBUG(level, "td = %p, ctrl = %x, addr = %x, len = %x, pidep = %x\n " -+ "dev = %x, status = %x, left = %x, errcnt = %x, done = %x\n " -+ "buf = %p, bustime = %d, td_status = %d\n", -+ td, td->ctrl, td->addr, td->len, td->pidep, -+ td->dev, td->status, td->left, td->errcnt, td->done, -+ td->buf, td->bustime, td->td_status); -+} -+ -+/* -+ * Isochronous transfers -+ */ -+static int sl811_submit_isochronous(struct urb *urb) -+{ -+ __u8 dev = usb_pipedevice(urb->pipe); -+ __u8 pidep = PIDEP(usb_packetid(urb->pipe), usb_pipeendpoint(urb->pipe)); -+ __u8 ctrl = 0; -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ struct sl811_td *td = NULL; -+ int i; -+ -+ PDEBUG(4, "enter, urb = %p, urbp = %p", urb, urbp); -+ -+ /* Can't have low speed bulk transfers */ -+ if (usb_pipeslow(urb->pipe)) { -+ PDEBUG(1, "error, urb = %p, low speed device", urb); -+ return -EINVAL; -+ } -+ -+ if (usb_pipeout(urb->pipe)) -+ ctrl |= SL811_USB_CTRL_DIR_OUT; -+ -+ ctrl |= SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE | SL811_USB_CTRL_ISO; -+ -+ for (i = 0; i < urb->number_of_packets; i++) { -+ urb->iso_frame_desc[i].actual_length = 0; -+ urb->iso_frame_desc[i].status = -EXDEV; -+ -+ td = sl811_alloc_td(urb); -+ if (!td) -+ return -ENOMEM; -+ -+ sl811_fill_td(td, ctrl, SL811_DATA_START, -+ urb->iso_frame_desc[i].length, -+ pidep, dev, -+ urb->transfer_buffer + urb->iso_frame_desc[i].offset); -+ sl811_calc_td_time(td); -+ if (urbp->cur_td == NULL) -+ urbp->cur_td = urbp->first_td = td; -+ } -+ -+ urbp->last_td = td; -+ -+ PDEBUG(4, "leave success"); -+ -+/* -+// for debug -+ { -+ struct list_head *head, *tmp; -+ struct sl811_td *td; -+ int i = 0; -+ head = &urbp->td_list; -+ tmp = head->next; -+ -+ if (list_empty(&urbp->td_list)) { -+ PDEBUG(1, "bug!!! td list is empty!"); -+ return -ENODEV; -+ } -+ -+ while (tmp != head) { -+ ++i; -+ td = list_entry(tmp, struct sl811_td, td_list); -+ PDEBUG(2, "td = %p, i = %d", td, i); -+ tmp = tmp->next; -+ } -+ } -+*/ -+ return 0; -+} -+ -+/* -+ * Reset isochronous transfers -+ */ -+static void sl811_reset_isochronous(struct urb *urb) -+{ -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ struct sl811_td *td = NULL; -+ struct list_head *head, *tmp; -+ int i; -+ -+ PDEBUG(4, "enter, urb = %p", urb); -+ -+ for (i = 0; i < urb->number_of_packets; i++) { -+ urb->iso_frame_desc[i].actual_length = 0; -+ urb->iso_frame_desc[i].status = -EXDEV; -+ } -+ -+ head = &urbp->td_list; -+ tmp = head->next; -+ while (tmp != head) { -+ td = list_entry(tmp, struct sl811_td, td_list); -+ tmp = tmp->next; -+ sl811_reset_td(td); -+ } -+ -+ urbp->cur_td = urbp->first_td; -+ -+ urb->status = -EINPROGRESS; -+ urb->actual_length = 0; -+ urb->error_count = 0; -+} -+ -+/* -+ * Result the iso urb. -+ */ -+static void sl811_result_isochronous(struct urb *urb) -+{ -+ struct list_head *tmp, *head; -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ int status = 0; -+ struct sl811_td *td; -+ int i; -+ -+ PDEBUG(4, "enter, urb = %p", urb); -+ -+ urb->actual_length = 0; -+ -+ i = 0; -+ head = &urbp->td_list; -+ tmp = head->next; -+ while (tmp != head) { -+ td = list_entry(tmp, struct sl811_td, td_list); -+ tmp = tmp->next; -+ -+ if (!td->done) { -+ if (urbp->unlink) -+ urb->status = -ENOENT; -+ else { -+ PDEBUG(1, "we should not get here!"); -+ urb->status = -EXDEV; -+ } -+ return ; -+ } -+ if (td->td_status) { -+ status = td->td_status; -+ urb->error_count++; -+ PDEBUG(1, "error: td = %p, td status = %d", td, td->td_status); -+ } -+ -+ urb->iso_frame_desc[i].actual_length = td->len - td->left; -+ urb->actual_length += td->len - td->left; -+ urb->iso_frame_desc[i].status = td->td_status; -+ ++i; -+ if (td->left) -+ PDEBUG(3, "short packet, td = %p, len = %d, left = %d", td, td->len, td->left); -+ } -+ -+ urb->status = status; -+/* -+// for debug -+ PDEBUG(2, "iso urb complete, len = %d, status =%d ", urb->actual_length, urb->status); -+*/ -+ PDEBUG(4, "leave success"); -+} -+ -+/* -+ * Interrupt transfers -+ */ -+static int sl811_submit_interrupt(struct urb *urb) -+{ -+ int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); -+ int len = urb->transfer_buffer_length; -+ __u8 *data = urb->transfer_buffer; -+ __u8 dev = usb_pipedevice(urb->pipe); -+ __u8 pidep = PIDEP(usb_packetid(urb->pipe), usb_pipeendpoint(urb->pipe)); -+ __u8 ctrl = 0; -+ struct sl811_hc *hc = urb->dev->bus->hcpriv; -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ struct sl811_td *td = NULL; -+ -+ PDEBUG(4, "enter, urb = %p", urb); -+ -+ if (len > maxsze) { -+ PDEBUG(1, "length is big than max packet size, len = %d, max packet = %d", len, maxsze); -+ return -EINVAL; -+ } -+ if (usb_pipeslow(urb->pipe) && !(hc->rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED)) -+ ctrl |= SL811_USB_CTRL_PREAMBLE; -+ -+ ctrl |= SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE; -+ if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) -+ ctrl |= SL811_USB_CTRL_TOGGLE_1; -+ usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); -+ td = sl811_alloc_td(urb); -+ if (!td) -+ return -ENOMEM; -+ -+ sl811_fill_td(td, ctrl, SL811_DATA_START, len, pidep, dev, data); -+ sl811_calc_td_time(td); -+ urbp->cur_td = urbp->first_td = urbp->last_td = td; -+ urbp->interval = 0; -+ -+ PDEBUG(4, "leave success"); -+ -+ return 0; -+} -+ -+/* -+ * Reset interrupt transfers -+ */ -+static void sl811_reset_interrupt(struct urb *urb) -+{ -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ struct sl811_td *td = urbp->cur_td; -+ -+ PDEBUG(4, "enter, interval = %d", urb->interval); -+ -+ td->ctrl &= ~SL811_USB_CTRL_TOGGLE_1; -+ if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) -+ td->ctrl |= SL811_USB_CTRL_TOGGLE_1; -+ usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); -+ -+ sl811_reset_td(td); -+ -+ urbp->interval = urb->interval; -+ -+ urb->status = -EINPROGRESS; -+ urb->actual_length = 0; -+} -+ -+/* -+ * Result the interrupt urb. -+ */ -+static void sl811_result_interrupt(struct urb *urb) -+{ -+ struct list_head *tmp; -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ struct sl811_td *td; -+ int toggle; -+ -+ PDEBUG(4, "enter, urb = %p", urb); -+ -+ urb->actual_length = 0; -+ -+ tmp = &urbp->td_list; -+ tmp = tmp->next; -+ td = list_entry(tmp, struct sl811_td, td_list); -+ -+ // success. -+ if (td->done && td->td_status == 0) { -+ urb->actual_length += td->len - td->left; -+ urb->status = 0; -+ return ; -+ } -+ // tranfer is done but fail, reset the toggle. -+ else if (td->done && td->td_status) { -+ urb->status = td->td_status; -+reset_toggle: -+ toggle = (td->ctrl & SL811_USB_CTRL_TOGGLE_1) ? 1 : 0; -+ usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), toggle); -+ PDEBUG(3, "error: td = %p, td status = %d", td, td->td_status); -+ return ; -+ } -+ // unlink, and not do transfer yet -+ else if (td->done == 0 && urbp->unlink && td->td_status == 0) { -+ urb->status = -ENOENT; -+ PDEBUG(3, "unlink and not transfer!"); -+ return ; -+ } -+ // unlink, and transfer not complete yet. -+ else if (td->done == 0 && urbp->unlink && td->td_status) { -+ urb->status = -ENOENT; -+ PDEBUG(3, "unlink and not complete!"); -+ goto reset_toggle; -+ } -+ // must be bug!!! -+ else {// (td->done == 0 && urbp->unlink == 0) -+ PDEBUG(1, "we should not get here!"); -+ urb->status = -EPIPE; -+ return ; -+ } -+} -+ -+/* -+ * Control transfers -+ */ -+static int sl811_submit_control(struct urb *urb) -+{ -+ int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); -+ int len = urb->transfer_buffer_length; -+ __u8 *data = urb->transfer_buffer; -+ __u8 dev = usb_pipedevice(urb->pipe); -+ __u8 pidep = 0; -+ __u8 ctrl = 0; -+ struct sl811_hc *hc = urb->dev->bus->hcpriv; -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ struct sl811_td *td = NULL; -+ -+ PDEBUG(4, "enter, urb = %p", urb); -+ -+ if (usb_pipeslow(urb->pipe) && !(hc->rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED)) -+ ctrl |= SL811_USB_CTRL_PREAMBLE; -+ -+ /* Build SETUP TD */ -+ pidep = PIDEP(USB_PID_SETUP, usb_pipeendpoint(urb->pipe)); -+ ctrl |= SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE | SL811_USB_CTRL_DIR_OUT; -+ td = sl811_alloc_td(urb); -+ if (!td) -+ return -ENOMEM; -+ -+ sl811_fill_td(td, ctrl, SL811_DATA_START, 8, pidep, dev, urb->setup_packet); -+ sl811_calc_td_time(td); -+ -+ urbp->cur_td = urbp->first_td = td; -+ -+ /* -+ * If direction is "send", change the frame from SETUP (0x2D) -+ * to OUT (0xE1). Else change it from SETUP to IN (0x69). -+ */ -+ pidep = PIDEP(usb_packetid(urb->pipe), usb_pipeendpoint(urb->pipe)); -+ if (usb_pipeout(urb->pipe)) -+ ctrl |= SL811_USB_CTRL_DIR_OUT; -+ else -+ ctrl &= ~SL811_USB_CTRL_DIR_OUT; -+ -+ /* Build the DATA TD's */ -+ while (len > 0) { -+ int pktsze = len; -+ -+ if (pktsze > maxsze) -+ pktsze = maxsze; -+ -+ /* Alternate Data0/1 (start with Data1) */ -+ ctrl ^= SL811_USB_CTRL_TOGGLE_1; -+ -+ td = sl811_alloc_td(urb); -+ if (!td) -+ return -ENOMEM; -+ -+ sl811_fill_td(td, ctrl, SL811_DATA_START, pktsze, pidep, dev, data); -+ sl811_calc_td_time(td); -+ -+ data += pktsze; -+ len -= pktsze; -+ } -+ -+ /* Build the final TD for control status */ -+ td = sl811_alloc_td(urb); -+ if (!td) -+ return -ENOMEM; -+ -+ /* It's IN if the pipe is an output pipe or we're not expecting data back */ -+ if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length) { -+ pidep = PIDEP(USB_PID_IN, usb_pipeendpoint(urb->pipe)); -+ ctrl &= ~SL811_USB_CTRL_DIR_OUT; -+ } else { -+ pidep = PIDEP(USB_PID_OUT, usb_pipeendpoint(urb->pipe)); -+ ctrl |= SL811_USB_CTRL_DIR_OUT; -+ } -+ -+ /* End in Data1 */ -+ ctrl |= SL811_USB_CTRL_TOGGLE_1; -+ -+ sl811_fill_td(td, ctrl, SL811_DATA_START, 0, pidep, dev, 0); -+ sl811_calc_td_time(td); -+ urbp->last_td = td; -+/* -+// for debug -+ { -+ struct list_head *head, *tmp; -+ struct sl811_td *td; -+ int i = 0; -+ head = &urbp->td_list; -+ tmp = head->next; -+ -+ if (list_empty(&urbp->td_list)) { -+ PDEBUG(1, "bug!!! td list is empty!"); -+ return -ENODEV; -+ } -+ -+ while (tmp != head) { -+ ++i; -+ td = list_entry(tmp, struct sl811_td, td_list); -+ PDEBUG(3, "td = %p, i = %d", td, i); -+ tmp = tmp->next; -+ } -+ } -+*/ -+ PDEBUG(4, "leave success"); -+ -+ return 0; -+} -+ -+/* -+ * Result the control urb. -+ */ -+static void sl811_result_control(struct urb *urb) -+{ -+ struct list_head *tmp, *head; -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ struct sl811_td *td; -+ -+ PDEBUG(4, "enter, urb = %p", urb); -+ -+ if (list_empty(&urbp->td_list)) { -+ PDEBUG(1, "td list is empty"); -+ return ; -+ } -+ -+ head = &urbp->td_list; -+ -+ tmp = head->next; -+ td = list_entry(tmp, struct sl811_td, td_list); -+ -+ /* The first TD is the SETUP phase, check the status, but skip the count */ -+ if (!td->done) { -+ PDEBUG(3, "setup phase error, td = %p, done = %d", td, td->done); -+ goto err_done; -+ } -+ if (td->td_status) { -+ PDEBUG(3, "setup phase error, td = %p, td status = %d", td, td->td_status); -+ goto err_status; -+ } -+ -+ urb->actual_length = 0; -+ -+ /* The rest of the TD's (but the last) are data */ -+ tmp = tmp->next; -+ while (tmp != head && tmp->next != head) { -+ td = list_entry(tmp, struct sl811_td, td_list); -+ tmp = tmp->next; -+ if (!td->done) { -+ PDEBUG(3, "data phase error, td = %p, done = %d", td, td->done); -+ goto err_done; -+ } -+ if (td->td_status) { -+ PDEBUG(3, "data phase error, td = %p, td status = %d", td, td->td_status); -+ goto err_status; -+ } -+ -+ urb->actual_length += td->len - td->left; -+ // short packet. -+ if (td->left) { -+ PDEBUG(3, "data phase short packet, td = %p, count = %d", td, td->len - td->left); -+ break; -+ } -+ } -+ -+ /* The last td is status phase */ -+ td = urbp->last_td; -+ if (!td->done) { -+ PDEBUG(3, "status phase error, td = %p, done = %d", td, td->done); -+ goto err_done; -+ } -+ if (td->td_status) { -+ PDEBUG(3, "status phase error, td = %p, td status = %d", td, td->td_status); -+ goto err_status; -+ } -+ -+ PDEBUG(4, "leave success"); -+ -+ urb->status = 0; -+ return ; -+ -+err_done: -+ if (urbp->unlink) -+ urb->status = -ENOENT; -+ else { -+ PDEBUG(1, "we should not get here! td = %p", td); -+ urb->status = -EPIPE; -+ } -+ return ; -+ -+err_status: -+ urb->status = td->td_status; -+ return ; -+} -+ -+/* -+ * Bulk transfers -+ */ -+static int sl811_submit_bulk(struct urb *urb) -+{ -+ int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); -+ int len = urb->transfer_buffer_length; -+ __u8 *data = urb->transfer_buffer; -+ __u8 dev = usb_pipedevice(urb->pipe); -+ __u8 pidep = PIDEP(usb_packetid(urb->pipe), usb_pipeendpoint(urb->pipe)); -+ __u8 ctrl = 0; -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ struct sl811_td *td = NULL; -+ -+ PDEBUG(4, "enter, urb = %p", urb); -+ -+ if (len < 0) { -+ PDEBUG(1, "error, urb = %p, len = %d", urb, len); -+ return -EINVAL; -+ } -+ -+ /* Can't have low speed bulk transfers */ -+ if (usb_pipeslow(urb->pipe)) { -+ PDEBUG(1, "error, urb = %p, low speed device", urb); -+ return -EINVAL; -+ } -+ -+ if (usb_pipeout(urb->pipe)) -+ ctrl |= SL811_USB_CTRL_DIR_OUT; -+ -+ ctrl |= SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE; -+ -+ /* Build the DATA TD's */ -+ do { /* Allow zero length packets */ -+ int pktsze = len; -+ -+ if (pktsze > maxsze) -+ pktsze = maxsze; -+ -+ td = sl811_alloc_td(urb); -+ if (!td) -+ return -ENOMEM; -+ -+ /* Alternate Data0/1 (start with Data1) */ -+ ctrl &= ~SL811_USB_CTRL_TOGGLE_1; -+ if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) -+ ctrl |= SL811_USB_CTRL_TOGGLE_1; -+ usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); -+ -+ sl811_fill_td(td, ctrl, SL811_DATA_START, pktsze, pidep, dev, data); -+ sl811_calc_td_time(td); -+ -+ if (urbp->cur_td == NULL) -+ urbp->cur_td = urbp->first_td = td; -+ -+ data += pktsze; -+ len -= maxsze; -+ } while (len > 0); -+ -+ /* -+ * USB_ZERO_PACKET means adding a 0-length packet, if -+ * direction is OUT and the transfer_length was an -+ * exact multiple of maxsze, hence -+ * (len = transfer_length - N * maxsze) == 0 -+ * however, if transfer_length == 0, the zero packet -+ * was already prepared above. -+ */ -+ if (usb_pipeout(urb->pipe) && (urb->transfer_flags & USB_ZERO_PACKET) && -+ !len && urb->transfer_buffer_length) { -+ -+ td = sl811_alloc_td(urb); -+ if (!td) -+ return -ENOMEM; -+ -+ /* Alternate Data0/1 (start with Data1) */ -+ ctrl &= ~SL811_USB_CTRL_TOGGLE_1; -+ if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) -+ ctrl |= SL811_USB_CTRL_TOGGLE_1; -+ usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); -+ -+ sl811_fill_td(td, ctrl, SL811_DATA_START, 0, pidep, dev, 0); -+ sl811_calc_td_time(td); -+ } -+ -+ urbp->last_td = td; -+ -+ PDEBUG(4, "leave success"); -+ -+ return 0; -+} -+ -+/* -+ * Reset bulk transfers -+ */ -+static int sl811_reset_bulk(struct urb *urb) -+{ -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ struct sl811_td *td; -+ struct list_head *head, *tmp; -+ -+ PDEBUG(4, "enter, urb = %p", urb); -+ -+ -+ head = &urbp->td_list; -+ tmp = head->next; -+ -+ while (tmp != head) { -+ td = list_entry(tmp, struct sl811_td, td_list); -+ -+ /* Alternate Data0/1 (start with Data1) */ -+ td->ctrl &= ~SL811_USB_CTRL_TOGGLE_1; -+ if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) -+ td->ctrl |= SL811_USB_CTRL_TOGGLE_1; -+ usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); -+ -+ sl811_reset_td(td); -+ } -+ -+ urb->status = -EINPROGRESS; -+ urb->actual_length = 0; -+ urbp->cur_td = urbp->first_td; -+ -+ PDEBUG(4, "leave success"); -+ -+ return 0; -+} -+ -+/* -+ * Result the bulk urb. -+ */ -+static void sl811_result_bulk(struct urb *urb) -+{ -+ struct list_head *tmp, *head; -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ struct sl811_td *td = NULL; -+ int toggle; -+ -+ PDEBUG(4, "enter, urb = %p", urb); -+ -+ urb->actual_length = 0; -+ -+ head = &urbp->td_list; -+ tmp = head->next; -+ while (tmp != head) { -+ td = list_entry(tmp, struct sl811_td, td_list); -+ tmp = tmp->next; -+ -+ // success. -+ if (td->done && td->td_status == 0) { -+ urb->actual_length += td->len - td->left; -+ -+ // short packet -+ if (td->left) { -+ urb->status = 0; -+ PDEBUG(3, "short packet, td = %p, count = %d", td, td->len - td->left); -+ goto reset_toggle; -+ } -+ } -+ // tranfer is done but fail, reset the toggle. -+ else if (td->done && td->td_status) { -+ urb->status = td->td_status; -+ PDEBUG(3, "error: td = %p, td status = %d", td, td->td_status); -+ goto reset_toggle; -+ } -+ // unlink, and not do transfer yet -+ else if (td->done == 0 && urbp->unlink && td->td_status == 0) { -+ urb->status = -ENOENT; -+ PDEBUG(3, "unlink and not transfer!"); -+ return ; -+ } -+ // unlink, and transfer not complete yet. -+ else if (td->done == 0 && urbp->unlink && td->td_status) { -+ PDEBUG(3, "unlink and not complete!"); -+ urb->status = -ENOENT; -+ goto reset_toggle; -+ } -+ // must be bug!!! -+ else {// (td->done == 0 && urbp->unlink == 0) -+ urb->status = -EPIPE; -+ PDEBUG(1, "we should not get here!"); -+ return ; -+ } -+ } -+ -+ PDEBUG(4, "leave success"); -+ urb->status = 0; -+ return ; -+ -+reset_toggle: -+ toggle = (td->ctrl & SL811_USB_CTRL_TOGGLE_1) ? 1 : 0; -+ usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), toggle); -+} -+ -+/* -+ * Find the first urb have the same dev and endpoint. -+ */ -+static inline int sl811_find_same_urb(struct list_head *head, struct urb *urb) -+{ -+ struct list_head *tmp; -+ struct urb *u; -+ -+ if (!head || !urb) -+ return 0; -+ -+ tmp = head->next; -+ -+ while (tmp != head) { -+ u = list_entry(tmp, struct urb, urb_list); -+ if (u == urb) -+ return 1; -+ tmp = tmp->next; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Find the first urb have the same dev and endpoint. -+ */ -+static inline struct urb* sl811_find_same_devep(struct list_head *head, struct urb *urb) -+{ -+ struct list_head *tmp; -+ struct urb *u; -+ -+ if (!head || !urb) -+ return NULL; -+ -+ tmp = head->next; -+ -+ while (tmp != head) { -+ u = list_entry(tmp, struct urb, urb_list); -+ if ((usb_pipe_endpdev(u->pipe)) == (usb_pipe_endpdev(urb->pipe))) -+ return u; -+ tmp = tmp->next; -+ } -+ -+ return NULL; -+} -+ -+/* -+ * This function is called by the USB core API when an URB is available to -+ * process. -+ */ -+static int sl811_submit_urb(struct urb *urb) -+{ -+ struct sl811_hc *hc = urb->dev->bus->hcpriv; -+ unsigned int pipe = urb->pipe; -+ struct list_head *head = NULL; -+ unsigned long flags; -+ int bustime; -+ int ret = 0; -+ -+ if (!urb) { -+ PDEBUG(1, "urb is null"); -+ return -EINVAL; -+ } -+ -+ if (urb->hcpriv) { -+ PDEBUG(1, "urbp is not null, urb = %p, urbp = %p", urb, urb->hcpriv); -+ return -EINVAL; -+ } -+ -+ if (!urb->dev || !urb->dev->bus || !hc) { -+ PDEBUG(1, "dev or bus or hc is null"); -+ return -ENODEV; -+ } -+ -+ if (usb_endpoint_halted(urb->dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { -+ PDEBUG(2, "sl811_submit_urb: endpoint_halted"); -+ return -EPIPE; -+ } -+ -+ if (usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)) > SL811_DATA_LIMIT) { -+ printk(KERN_ERR "Packet size is big for SL811, should < %d!\n", SL811_DATA_LIMIT); -+ return -EINVAL; -+ } -+ -+ /* a request to the virtual root hub */ -+ if (usb_pipedevice(pipe) == hc->rh.devnum) -+ return sl811_rh_submit_urb(urb); -+ -+ spin_lock_irqsave(&hc->hc_lock, flags); -+ spin_lock(&urb->lock); -+ -+ switch (usb_pipetype(urb->pipe)) { -+ case PIPE_ISOCHRONOUS: -+ head = &hc->iso_list; -+ break; -+ case PIPE_INTERRUPT: -+ head = &hc->intr_list; -+ break; -+ case PIPE_CONTROL: -+ head = &hc->ctrl_list; -+ break; -+ case PIPE_BULK: -+ head = &hc->bulk_list; -+ break; -+ } -+ -+ if (sl811_find_same_devep(head, urb)) { -+ list_add(&urb->urb_list, &hc->wait_list); -+ PDEBUG(4, "add to wait list"); -+ goto out_unlock; -+ } -+ -+ if (!sl811_alloc_urb_priv(urb)) { -+ ret = -ENOMEM; -+ goto out_unlock; -+ } -+ -+ switch (usb_pipetype(urb->pipe)) { -+ case PIPE_ISOCHRONOUS: -+ if (urb->number_of_packets <= 0) { -+ ret = -EINVAL; -+ break; -+ } -+ bustime = usb_check_bandwidth(urb->dev, urb); -+ if (bustime < 0) { -+ ret = bustime; -+ break; -+ } -+ if (!(ret = sl811_submit_isochronous(urb))) -+ usb_claim_bandwidth(urb->dev, urb, bustime, 1); -+ break; -+ case PIPE_INTERRUPT: -+ bustime = usb_check_bandwidth(urb->dev, urb); -+ if (bustime < 0) -+ ret = bustime; -+ else if (!(ret = sl811_submit_interrupt(urb))) -+ usb_claim_bandwidth(urb->dev, urb, bustime, 0); -+ break; -+ case PIPE_CONTROL: -+ ret = sl811_submit_control(urb); -+ break; -+ case PIPE_BULK: -+ ret = sl811_submit_bulk(urb); -+ break; -+ } -+ -+ if (!ret) { -+ ((struct sl811_urb_priv *)urb->hcpriv)->inserttime = jiffies; -+ list_add(&urb->urb_list, head); -+ PDEBUG(4, "add to type list"); -+ urb->status = -EINPROGRESS; -+ if (++hc->active_urbs == 1) -+ sl811_enable_interrupt(hc); -+ goto out_unlock; -+ } else { -+ PDEBUG(2, "submit urb fail! error = %d", ret); -+ sl811_free_urb_priv(urb); -+ } -+ -+out_unlock: -+ spin_unlock(&urb->lock); -+ spin_unlock_irqrestore(&hc->hc_lock, flags); -+ -+ return ret; -+} -+ -+/* -+ * Submit the urb the wait list. -+ */ -+static int sl811_submit_urb_with_lock(struct urb *urb) -+{ -+ struct sl811_hc *hc = urb->dev->bus->hcpriv; -+ struct list_head *head = NULL; -+ int bustime; -+ int ret = 0; -+ -+ spin_lock(&urb->lock); -+ -+ switch (usb_pipetype(urb->pipe)) { -+ case PIPE_ISOCHRONOUS: -+ head = &hc->iso_list; -+ break; -+ case PIPE_INTERRUPT: -+ head = &hc->intr_list; -+ break; -+ case PIPE_CONTROL: -+ head = &hc->ctrl_list; -+ break; -+ case PIPE_BULK: -+ head = &hc->bulk_list; -+ break; -+ } -+ -+ if (!sl811_alloc_urb_priv(urb)) { -+ ret = -ENOMEM; -+ goto out_unlock; -+ } -+ -+ switch (usb_pipetype(urb->pipe)) { -+ case PIPE_ISOCHRONOUS: -+ if (urb->number_of_packets <= 0) { -+ ret = -EINVAL; -+ break; -+ } -+ bustime = usb_check_bandwidth(urb->dev, urb); -+ if (bustime < 0) { -+ ret = bustime; -+ break; -+ } -+ if (!(ret = sl811_submit_isochronous(urb))) -+ usb_claim_bandwidth(urb->dev, urb, bustime, 1); -+ break; -+ case PIPE_INTERRUPT: -+ bustime = usb_check_bandwidth(urb->dev, urb); -+ if (bustime < 0) -+ ret = bustime; -+ else if (!(ret = sl811_submit_interrupt(urb))) -+ usb_claim_bandwidth(urb->dev, urb, bustime, 0); -+ break; -+ case PIPE_CONTROL: -+ ret = sl811_submit_control(urb); -+ break; -+ case PIPE_BULK: -+ ret = sl811_submit_bulk(urb); -+ break; -+ } -+ -+ if (ret == 0) { -+ ((struct sl811_urb_priv *)urb->hcpriv)->inserttime = jiffies; -+ list_add(&urb->urb_list, head); -+ PDEBUG(4, "add to type list"); -+ urb->status = -EINPROGRESS; -+ if (++hc->active_urbs == 1) -+ sl811_enable_interrupt(hc); -+ goto out_unlock; -+ } else { -+ PDEBUG(2, "submit urb fail! error = %d", ret); -+ sl811_free_urb_priv(urb); -+ } -+ -+out_unlock: -+ spin_unlock(&urb->lock); -+ -+ return ret; -+} -+ -+/* -+ * Reset the urb -+ */ -+static void sl811_reset_urb(struct urb *urb) -+{ -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ -+ switch (usb_pipetype(urb->pipe)) { -+ case PIPE_ISOCHRONOUS: -+ sl811_reset_isochronous(urb); -+ break; -+ case PIPE_INTERRUPT: -+ sl811_reset_interrupt(urb); -+ break; -+ case PIPE_CONTROL: -+ return; -+ case PIPE_BULK: -+ sl811_reset_bulk(urb); -+ break; -+ } -+ urbp->inserttime = jiffies; -+} -+ -+/* -+ * Return the result of a transfer -+ */ -+static void sl811_result_urb(struct urb *urb) -+{ -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ struct sl811_hc *hc = urb->dev->bus->hcpriv; -+ struct list_head *head = NULL; -+ struct urb *u = NULL; -+ int reset = 0; -+ int ring = 0; -+ -+ if (urb->status != -EINPROGRESS) { -+ PDEBUG(1, "urb status is not EINPROGRESS!"); -+ return ; -+ } -+ -+ spin_lock(&urb->lock); -+ -+ switch (usb_pipetype(urb->pipe)) { -+ case PIPE_ISOCHRONOUS: -+ head = &hc->iso_list; -+ sl811_result_isochronous(urb); -+ -+ // if the urb is not unlink and is in a urb "ring", we reset it -+ if (!urbp->unlink && urb->next) -+ ring = 1; -+ break; -+ case PIPE_INTERRUPT: -+ head = &hc->intr_list; -+ sl811_result_interrupt(urb); -+ -+ // if the urb is not unlink and not "once" query, we reset. -+ if (!urbp->unlink && urb->interval) -+ reset = 1; -+ break; -+ case PIPE_CONTROL: -+ head = &hc->ctrl_list; -+ sl811_result_control(urb); -+ break; -+ case PIPE_BULK: -+ head = &hc->bulk_list; -+ sl811_result_bulk(urb); -+ -+ // if the urb is not unlink and is in a urb "ring", we reset it -+ if (!urbp->unlink && urb->next) -+ ring = 1; -+ break; -+ } -+ -+ PDEBUG(4, "result urb status = %d", urb->status); -+ -+ if (ring && urb->next == urb) -+ reset = 1; -+ -+ if (!reset) { -+ switch (usb_pipetype(urb->pipe)) { -+ case PIPE_ISOCHRONOUS: -+ usb_release_bandwidth(urb->dev, urb, 1); -+ break; -+ case PIPE_INTERRUPT: -+ usb_release_bandwidth(urb->dev, urb, 0); -+ break; -+ } -+ sl811_free_urb_priv(urb); -+ } -+ -+ spin_unlock(&urb->lock); -+ -+ if (urb->complete) -+ urb->complete(urb); -+ -+ if (reset) { -+ spin_lock(&urb->lock); -+ sl811_reset_urb(urb); -+ if (usb_pipeint(urb->pipe)) -+ list_add(&urb->urb_list, &hc->idle_intr_list); -+ else -+ list_add(&urb->urb_list, head); -+ spin_unlock(&urb->lock); -+ } else { -+ if (--hc->active_urbs <= 0) { -+ hc->active_urbs = 0; -+ sl811_disable_interrupt(hc); -+ } -+ -+ if (ring) -+ u = urb->next; -+ else -+ u = sl811_find_same_devep(&hc->wait_list, urb); -+ -+ if (u) { -+ if (!list_empty(&u->urb_list)) -+ list_del(&u->urb_list); -+ if (sl811_submit_urb_with_lock(u)) -+ list_add(&u->urb_list, &hc->wait_list); -+ } -+ } -+} -+ -+ -+#ifdef SL811_TIMEOUT -+ -+/* -+ * Unlink the urb from the urb list -+ */ -+static int sl811_unlink_urb(struct urb *urb) -+{ -+ unsigned long flags; -+ struct sl811_hc *hc; -+ struct sl811_urb_priv *urbp; -+ int call = 0; -+ int schedule = 0; -+ int count = 0; -+ -+ if (!urb) { -+ PDEBUG(1, "urb is null"); -+ return -EINVAL; -+ } -+ -+ if (!urb->dev || !urb->dev->bus) { -+ PDEBUG(1, "dev or bus is null"); -+ return -ENODEV; -+ } -+ -+ hc = urb->dev->bus->hcpriv; -+ urbp = urb->hcpriv; -+ -+ /* a request to the virtual root hub */ -+ if (usb_pipedevice(urb->pipe) == hc->rh.devnum) -+ return sl811_rh_unlink_urb(urb); -+ -+ spin_lock_irqsave(&hc->hc_lock, flags); -+ spin_lock(&urb->lock); -+ -+ // in wait list -+ if (sl811_find_same_urb(&hc->wait_list, urb)) { -+ PDEBUG(4, "unlink urb in wait list"); -+ list_del_init(&urb->urb_list); -+ urb->status = -ENOENT; -+ call = 1; -+ goto out; -+ } -+ -+ // in intr idle list. -+ if (sl811_find_same_urb(&hc->idle_intr_list, urb)) { -+ PDEBUG(4, "unlink urb in idle intr list"); -+ list_del_init(&urb->urb_list); -+ urb->status = -ENOENT; -+ sl811_free_urb_priv(urb); -+ usb_release_bandwidth(urb->dev, urb, 0); -+ if (--hc->active_urbs <= 0) { -+ hc->active_urbs = 0; -+ sl811_disable_interrupt(hc); -+ } -+ call = 1; -+ goto out; -+ } -+ -+ if (urb->status == -EINPROGRESS) { -+ PDEBUG(3, "urb is still in progress"); -+ urbp->unlink = 1; -+ -+re_unlink: -+ // Is it in progress? -+ urbp = urb->hcpriv; -+ if (urbp && hc->cur_td == urbp->cur_td) { -+ ++count; -+ if (sl811_read(hc, 0) & SL811_USB_CTRL_ARM) { -+ PDEBUG(3, "unlink: cur td is still in progress! count = %d", count); -+re_schedule: -+ schedule = 1; -+ spin_unlock(&urb->lock); -+ spin_unlock_irqrestore(&hc->hc_lock, flags); -+ schedule_timeout(HZ/50); -+ spin_lock_irqsave(&hc->hc_lock, flags); -+ spin_lock(&urb->lock); -+ } else { -+ PDEBUG(3, "unlink: lost of interrupt? do parse! count = %d", count); -+ spin_unlock(&urb->lock); -+ sl811_transfer_done(hc, 0); -+ spin_lock(&urb->lock); -+ } -+ goto re_unlink; -+ } -+ -+ if (list_empty(&urb->urb_list)) { -+ PDEBUG(3, "unlink: list empty!"); -+ goto out; -+ } -+ -+ if (urb->transfer_flags & USB_TIMEOUT_KILLED) { -+ PDEBUG(3, "unlink: time out killed"); -+ // it is timeout killed by us -+ goto result; -+ } else if (urb->transfer_flags & USB_ASYNC_UNLINK) { -+ // we do nothing, just let it be processing later -+ PDEBUG(3, "unlink async, do nothing"); -+ goto out; -+ } else { -+ // synchron without callback -+ PDEBUG(3, "unlink synchron, we wait the urb complete or timeout"); -+ if (schedule == 0) { -+ PDEBUG(3, "goto re_schedule"); -+ goto re_schedule; -+ } else { -+ PDEBUG(3, "already scheduled"); -+ goto result; -+ } -+ } -+ } else if (!list_empty(&urb->urb_list)) { -+ PDEBUG(1, "urb = %p, status = %d is in a list, why?", urb, urb->status); -+ //list_del_init(&urb->urb_list); -+ //call = 1; -+ } -+ -+out: -+ spin_unlock(&urb->lock); -+ spin_unlock_irqrestore(&hc->hc_lock, flags); -+ -+ if (call && urb->complete) -+ urb->complete(urb); -+ -+ return 0; -+ -+result: -+ spin_unlock(&urb->lock); -+ -+ list_del_init(&urb->urb_list); -+ sl811_result_urb(urb); -+ -+ spin_unlock_irqrestore(&hc->hc_lock, flags); -+ -+ return 0; -+} -+ -+#else -+ -+/* -+ * Unlink the urb from the urb list -+ */ -+static int sl811_unlink_urb(struct urb *urb) -+{ -+ unsigned long flags; -+ struct sl811_hc *hc; -+ struct sl811_urb_priv *urbp; -+ int call = 0; -+ -+ if (!urb) { -+ PDEBUG(1, "urb is null"); -+ return -EINVAL; -+ } -+ -+ if (!urb->dev || !urb->dev->bus) { -+ PDEBUG(1, "dev or bus is null"); -+ return -ENODEV; -+ } -+ -+ hc = urb->dev->bus->hcpriv; -+ urbp = urb->hcpriv; -+ -+ /* a request to the virtual root hub */ -+ if (usb_pipedevice(urb->pipe) == hc->rh.devnum) -+ return sl811_rh_unlink_urb(urb); -+ -+ spin_lock_irqsave(&hc->hc_lock, flags); -+ spin_lock(&urb->lock); -+ -+ // in wait list -+ if (sl811_find_same_urb(&hc->wait_list, urb)) { -+ PDEBUG(2, "unlink urb in wait list"); -+ list_del_init(&urb->urb_list); -+ urb->status = -ENOENT; -+ call = 1; -+ goto out; -+ } -+ -+ if (urb->status == -EINPROGRESS) { -+ PDEBUG(2, "urb is still in progress"); -+ urbp->unlink = 1; -+ -+ // Is it in progress? -+ urbp = urb->hcpriv; -+ if (urbp && hc->cur_td == urbp->cur_td) { -+ // simple, let it out -+ PDEBUG(2, "unlink: cur td is still in progress!"); -+ hc->cur_td = NULL; -+ } -+ -+ goto result; -+ } else if (!list_empty(&urb->urb_list)) { -+ PDEBUG(1, "urb = %p, status = %d is in a list, why?", urb, urb->status); -+ list_del_init(&urb->urb_list); -+ if (urbp) -+ goto result; -+ else -+ call = 1; -+ } -+ -+out: -+ spin_unlock(&urb->lock); -+ spin_unlock_irqrestore(&hc->hc_lock, flags); -+ -+ if (call && urb->complete) -+ urb->complete(urb); -+ -+ return 0; -+ -+result: -+ spin_unlock(&urb->lock); -+ -+ list_del_init(&urb->urb_list); -+ sl811_result_urb(urb); -+ -+ spin_unlock_irqrestore(&hc->hc_lock, flags); -+ -+ return 0; -+} -+ -+#endif -+ -+static int sl811_get_current_frame_number(struct usb_device *usb_dev) -+{ -+ return ((struct sl811_hc *)(usb_dev->bus->hcpriv))->frame_number; -+} -+ -+static struct usb_operations sl811_device_operations = -+{ -+ sl811_alloc_dev_priv, -+ sl811_free_dev_priv, -+ sl811_get_current_frame_number, -+ sl811_submit_urb, -+ sl811_unlink_urb -+}; -+ -+/* -+ * This functions transmit a td. -+ */ -+static inline void sl811_trans_cur_td(struct sl811_hc *hc, struct sl811_td *td) -+{ -+ sl811_print_td(4, td); -+ sl811_write_buf(hc, SL811_ADDR_A, &td->addr, 4); -+ if (td->len && (td->ctrl & SL811_USB_CTRL_DIR_OUT)) -+ sl811_write_buf(hc, td->addr, td->buf, td->len); -+ -+ sl811_write(hc, SL811_CTRL_A, td->ctrl); -+} -+ -+ -+/* -+ * This function checks the status of the transmitted or received packet -+ * and copy the data from the SL811HS register into a buffer. -+ */ -+static void sl811_parse_cur_td(struct sl811_hc *hc, struct sl811_td *td) -+{ -+ struct urb *urb = td->urb; -+#ifdef SL811_DEBUG -+ int dev = usb_pipedevice(td->urb->pipe); -+ int ep = usb_pipeendpoint(td->urb->pipe); -+#endif -+ -+ sl811_read_buf(hc, SL811_STS_A, &td->status, 2); -+ -+ if (td->status & SL811_USB_STS_ACK) { -+ td->done = 1; -+ -+/* if ((td->ctrl & SL811_USB_CTRL_TOGGLE_1) != (td->status & SL811_USB_STS_TOGGLE_1)) { -+ PDEBUG(2, "dev %d endpoint %d unexpect data toggle!", dev, ep); -+ td->td_status = -EILSEQ; -+ } -+*/ -+ if (!(td->ctrl & SL811_USB_CTRL_DIR_OUT) && td->len > 0) -+ sl811_read_buf(hc, td->addr, td->buf, td->len - td->left); -+ -+ if (td->left && (urb->transfer_flags & USB_DISABLE_SPD)) { -+ PDEBUG(2, "dev %d endpoint %d unexpect short packet! td = %p", dev, ep, td); -+ td->td_status = -EREMOTEIO; -+ } else -+ td->td_status = 0; -+ } else if (td->status & SL811_USB_STS_STALL) { -+ PDEBUG(2, "dev %d endpoint %d halt, td = %p", dev, ep, td); -+ td->td_status = -EPIPE; -+ if (urb->dev) -+ usb_endpoint_halt(td->urb->dev, usb_pipeendpoint(td->urb->pipe), usb_pipeout(td->urb->pipe)); -+ td->done = 1; -+ } else if (td->status & SL811_USB_STS_OVERFLOW) { -+ PDEBUG(1, "dev %d endpoint %d overflow, sl811 only support packet less than %d", dev, ep, SL811_DATA_LIMIT); -+ td->td_status = -EOVERFLOW; -+ td->done = 1; -+ } else if (td->status & SL811_USB_STS_TIMEOUT ) { -+ PDEBUG(2, "dev %d endpoint %d timeout, td = %p", dev, ep, td); -+ td->td_status = -ETIMEDOUT; -+ if (--td->errcnt == 0) -+ td->done = 1; -+ } else if (td->status & SL811_USB_STS_ERROR) { -+ PDEBUG(2, "dev %d endpoint %d error, td = %p", dev, ep, td); -+ td->td_status = -EILSEQ; -+ if (--td->errcnt == 0) -+ td->done = 1; -+ } else if (td->status & SL811_USB_STS_NAK) { -+ ++td->nakcnt; -+ PDEBUG(3, "dev %d endpoint %d nak, td = %p, count = %d", dev, ep, td, td->nakcnt); -+ td->td_status = -EINPROGRESS; -+ if (!usb_pipeslow(td->urb->pipe) && td->nakcnt > 1024) { -+ PDEBUG(2, "too many naks, td = %p, count = %d", td, td->nakcnt); -+ td->td_status = -ETIMEDOUT; -+ td->done = 1; -+ } -+ } -+ -+ sl811_print_td(4, td); -+} -+ -+/* -+ * This function checks the status of current urb. -+ */ -+static int sl811_parse_cur_urb(struct urb *urb) -+{ -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ struct sl811_td *td = urbp->cur_td; -+ struct list_head *tmp; -+ -+ sl811_print_td(5, td); -+ -+ // this td not done yet. -+ if (!td->done) -+ return 0; -+ -+ // the last ld, so the urb is done. -+ if (td == urbp->last_td) { -+ PDEBUG(4, "urb = %p is done success", td->urb); -+ if (usb_pipeisoc(td->urb->pipe)) -+ PDEBUG(4, "ISO URB DONE, td = %p", td); -+ return 1; -+ } -+ -+ // iso transfer, we always advance to next td -+ if (usb_pipeisoc(td->urb->pipe)) { -+ tmp = &td->td_list; -+ tmp = tmp->next; -+ urbp->cur_td = list_entry(tmp, struct sl811_td, td_list); -+ PDEBUG(4, "ISO NEXT, td = %p", urbp->cur_td); -+ return 0; -+ } -+ -+ // some error occur, so the urb is done. -+ if (td->td_status) { -+ PDEBUG(3, "urb = %p is done error, td status is = %d", td->urb, td->td_status); -+ return 1; -+ } -+ -+ // short packet. -+ if (td->left) { -+ if (usb_pipecontrol(td->urb->pipe)) { -+ // control packet, we advance to the last td -+ PDEBUG(3, "ctrl short packet, advance to last td"); -+ urbp->cur_td = urbp->last_td; -+ return 0; -+ } else { -+ // interrut and bulk packet, urb is over. -+ PDEBUG(3, "bulk or intr short packet, urb is over"); -+ return 1; -+ } -+ } -+ -+ // we advance to next td. -+ tmp = &td->td_list; -+ tmp = tmp->next; -+ urbp->cur_td = list_entry(tmp, struct sl811_td, td_list); -+#ifdef SL811_DEBUG -+ PDEBUG(4, "advance to the next td, urb = %p, td = %p", urb, urbp->cur_td); -+ sl811_print_td(5, urbp->cur_td); -+ if (td == urbp->cur_td) -+ PDEBUG(1, "bug!!!"); -+#endif -+ return 0; -+} -+ -+/* -+ * Find the next td to transfer. -+ */ -+static inline struct sl811_td* sl811_schedule_next_td(struct urb *urb, struct sl811_td *cur_td) -+{ -+ struct sl811_urb_priv *urbp = urb->hcpriv; -+ -+ PDEBUG(4, "urb at %p, cur td at %p", urb, cur_td); -+ -+ // iso don't schedule the td in the same frame. -+ if (usb_pipeisoc(cur_td->urb->pipe)) -+ return NULL; -+ -+ // cur td is not complete -+ if (!cur_td->done) -+ return NULL; -+ -+ // here, urbp->cur_td is already the next td; -+ return urbp->cur_td; -+} -+ -+/* -+ * Scan the list to find a active urb -+ */ -+static inline struct urb* sl811_get_list_next_urb(struct sl811_hc *hc, struct list_head *next) -+{ -+ struct urb *urb; -+ int i; -+ -+ if (list_empty(next)) -+ return NULL; -+ -+ if (next == hc->cur_list) -+ return NULL; -+ -+ for (i = 0; i < 4; ++i) -+ if (next == &hc->urb_list[i]) -+ return NULL; -+ -+ urb = list_entry(next, struct urb, urb_list); -+ PDEBUG(4, "next urb in list is at %p", urb); -+ -+ return urb; -+} -+ -+/* -+ * Find the next td to transfer. -+ */ -+static struct sl811_td* sl811_schedule_next_urb(struct sl811_hc *hc, struct list_head *next) -+{ -+ struct urb *urb = NULL; -+ int back_loop = 1; -+ struct list_head *old_list = hc->cur_list; -+ -+ // try to get next urb in the same list. -+ if (next) { -+ urb = sl811_get_list_next_urb(hc, next); -+ if (!urb) -+ ++hc->cur_list; -+ } -+ -+ // try other list. -+ if (!urb) { -+re_loop: -+ // try all the list. -+ while (hc->cur_list < &hc->urb_list[4]) { -+ if ((urb = sl811_get_list_next_urb(hc, hc->cur_list->next))) -+ return ((struct sl811_urb_priv *)urb->hcpriv)->cur_td; -+ ++hc->cur_list; -+ } -+ // the last list is try -+ if (back_loop && (old_list >= &hc->ctrl_list)) { -+ hc->cur_list = &hc->ctrl_list; -+ back_loop = 0; -+ goto re_loop; -+ } -+ } -+ -+ if (hc->cur_list > &hc->urb_list[3]) -+ hc->cur_list = &hc->ctrl_list; -+ -+ return NULL; -+} -+ -+/* -+ * This function process the transfer rusult. -+ */ -+static void sl811_transfer_done(struct sl811_hc *hc, int sof) -+{ -+ struct sl811_td *cur_td = hc->cur_td, *next_td = NULL; -+ struct urb *cur_urb = NULL; -+ struct list_head *next = NULL; -+ int done; -+ -+ PDEBUG(5, "enter"); -+ -+ if (cur_td == NULL) { -+ PDEBUG(1, "in done interrupt, but td is null, be already parsed?"); -+ return ; -+ } -+ -+ cur_urb = cur_td->urb; -+ hc->cur_td = NULL; -+ next = &cur_urb->urb_list; -+ next = next->next; -+ -+ spin_lock(&cur_urb->lock); -+ sl811_parse_cur_td(hc, cur_td); -+ done = sl811_parse_cur_urb(cur_urb); -+ spin_unlock(&cur_urb->lock); -+ -+ if (done) { -+ list_del_init(&cur_urb->urb_list); -+ cur_td = NULL; -+ sl811_result_urb(cur_urb); -+ } -+ -+ if (sof) -+ return ; -+ -+ if (!done) { -+ next_td = sl811_schedule_next_td(cur_urb, cur_td); -+ if (next_td && next_td != cur_td && (sl811_calc_bus_remainder(hc) > next_td->bustime)) { -+ hc->cur_td = next_td; -+ PDEBUG(5, "ADD TD"); -+ sl811_trans_cur_td(hc, next_td); -+ return ; -+ } -+ } -+ -+ while (1) { -+ next_td = sl811_schedule_next_urb(hc, next); -+ if (!next_td) -+ return; -+ if (next_td == cur_td) -+ return; -+ next = &next_td->urb->urb_list; -+ next = next->next; -+ if (sl811_calc_bus_remainder(hc) > next_td->bustime) { -+ hc->cur_td = next_td; -+ PDEBUG(5, "ADD TD"); -+ sl811_trans_cur_td(hc, next_td); -+ return ; -+ } -+ } -+} -+ -+/* -+ * -+ */ -+static void inline sl811_dec_intr_interval(struct sl811_hc *hc) -+{ -+ struct list_head *head, *tmp; -+ struct urb *urb; -+ struct sl811_urb_priv *urbp; -+ -+ if (list_empty(&hc->idle_intr_list)) -+ return ; -+ -+ head = &hc->idle_intr_list; -+ tmp = head->next; -+ -+ while (tmp != head) { -+ urb = list_entry(tmp, struct urb, urb_list); -+ tmp = tmp->next; -+ spin_lock(&urb->lock); -+ urbp = urb->hcpriv; -+ if (--urbp->interval == 0) { -+ list_del(&urb->urb_list); -+ list_add(&urb->urb_list, &hc->intr_list); -+ PDEBUG(4, "intr urb active"); -+ } -+ spin_unlock(&urb->lock); -+ } -+} -+ -+/* -+ * The sof interrupt is happen. -+ */ -+static void sl811_start_sof(struct sl811_hc *hc) -+{ -+ struct sl811_td *next_td; -+#ifdef SL811_DEBUG -+ static struct sl811_td *repeat_td = NULL; -+ static int repeat_cnt = 1; -+#endif -+ if (++hc->frame_number > 1024) -+ hc->frame_number = 0; -+ -+ if (hc->active_urbs == 0) -+ return ; -+ -+ sl811_dec_intr_interval(hc); -+ -+ if (hc->cur_td) { -+ if (sl811_read(hc, 0) & SL811_USB_CTRL_ARM) { -+#ifdef SL811_DEBUG -+ if (repeat_td == hc->cur_td) -+ ++repeat_cnt; -+ else { -+ if (repeat_cnt >= 2) -+ PDEBUG(2, "cur td = %p repeat %d", hc->cur_td, repeat_cnt); -+ repeat_cnt = 1; -+ repeat_td = hc->cur_td; -+ } -+#endif -+ return ; -+ } else { -+ PDEBUG(2, "lost of interrupt in sof? do parse!"); -+ sl811_transfer_done(hc, 1); -+ -+ // let this frame idle -+ return; -+ } -+ } -+ -+ hc->cur_list = &hc->iso_list; -+ -+ if (hc->active_urbs == 0) -+ return ; -+ -+ next_td = sl811_schedule_next_urb(hc, NULL); -+ if (!next_td) { -+#ifdef SL811_DEBUG -+ if (list_empty(&hc->idle_intr_list)) -+ PDEBUG(2, "not schedule a td, why? urbs = %d", hc->active_urbs); -+#endif -+ return; -+ } -+ if (sl811_calc_bus_remainder(hc) > next_td->bustime) { -+ hc->cur_td = next_td; -+ sl811_trans_cur_td(hc, next_td); -+ } else -+ PDEBUG(2, "bus time if not enough, why?"); -+} -+ -+/* -+ * This function resets SL811HS controller and detects the speed of -+ * the connecting device -+ * -+ * Return: 0 = no device attached; 1 = USB device attached -+ */ -+static int sl811_hc_reset(struct sl811_hc *hc) -+{ -+ int status ; -+ -+ sl811_write(hc, SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI); -+ sl811_write(hc, SL811_CTRL1, SL811_CTRL1_RESET); -+ -+ mdelay(20); -+ -+ // Disable hardware SOF generation, clear all irq status. -+ sl811_write(hc, SL811_CTRL1, 0); -+ mdelay(2); -+ sl811_write(hc, SL811_INTRSTS, 0xff); -+ status = sl811_read(hc, SL811_INTRSTS); -+ -+ if (status & SL811_INTR_NOTPRESENT) { -+ // Device is not present -+ PDEBUG(0, "Device not present"); -+ hc->rh_status.wPortStatus &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE); -+ hc->rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION; -+ sl811_write(hc, SL811_INTR, SL811_INTR_INSRMV); -+ return 0; -+ } -+ -+ // Send SOF to address 0, endpoint 0. -+ sl811_write(hc, SL811_LEN_B, 0); -+ sl811_write(hc, SL811_PIDEP_B, PIDEP(USB_PID_SOF, 0)); -+ sl811_write(hc, SL811_DEV_B, 0x00); -+ sl811_write (hc, SL811_SOFLOW, SL811_12M_HI); -+ -+ if (status & SL811_INTR_SPEED_FULL) { -+ /* full speed device connect directly to root hub */ -+ PDEBUG (0, "Full speed Device attached"); -+ -+ sl811_write(hc, SL811_CTRL1, SL811_CTRL1_RESET); -+ mdelay(20); -+ sl811_write(hc, SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI); -+ sl811_write(hc, SL811_CTRL1, SL811_CTRL1_SOF); -+ -+ /* start the SOF or EOP */ -+ sl811_write(hc, SL811_CTRL_B, SL811_USB_CTRL_ARM); -+ hc->rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION; -+ hc->rh_status.wPortStatus &= ~USB_PORT_STAT_LOW_SPEED; -+ mdelay(2); -+ sl811_write (hc, SL811_INTRSTS, 0xff); -+ } else { -+ /* slow speed device connect directly to root-hub */ -+ PDEBUG(0, "Low speed Device attached"); -+ -+ sl811_write(hc, SL811_CTRL1, SL811_CTRL1_RESET); -+ mdelay(20); -+ sl811_write(hc, SL811_CTRL2, SL811_CTL2_HOST | SL811_CTL2_DSWAP | SL811_12M_HI); -+ sl811_write(hc, SL811_CTRL1, SL811_CTRL1_SPEED_LOW | SL811_CTRL1_SOF); -+ -+ /* start the SOF or EOP */ -+ sl811_write(hc, SL811_CTRL_B, SL811_USB_CTRL_ARM); -+ hc->rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION | USB_PORT_STAT_LOW_SPEED; -+ mdelay(2); -+ sl811_write(hc, SL811_INTRSTS, 0xff); -+ } -+ -+ hc->rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION; -+ sl811_write(hc, SL811_INTR, SL811_INTR_INSRMV); -+ -+ return 1; -+} -+ -+/* -+ * Interrupt service routine. -+ */ -+static void sl811_interrupt(int irq, void *__hc, struct pt_regs * r) -+{ -+ __u8 status; -+ struct sl811_hc *hc = __hc; -+ -+ status = sl811_read(hc, SL811_INTRSTS); -+ if (status == 0) -+ return ; /* Not me */ -+ -+ sl811_write(hc, SL811_INTRSTS, 0xff); -+ -+ if (status & SL811_INTR_INSRMV) { -+ sl811_write(hc, SL811_INTR, 0); -+ sl811_write(hc, SL811_CTRL1, 0); -+ // wait for device stable -+ mdelay(100); -+ sl811_hc_reset(hc); -+ return ; -+ } -+ -+ spin_lock(&hc->hc_lock); -+ -+ if (status & SL811_INTR_DONE_A) { -+ if (status & SL811_INTR_SOF) { -+ sl811_transfer_done(hc, 1); -+ PDEBUG(4, "sof in done!"); -+ sl811_start_sof(hc); -+ } else -+ sl811_transfer_done(hc, 0); -+ } else if (status & SL811_INTR_SOF) -+ sl811_start_sof(hc); -+ -+ spin_unlock(&hc->hc_lock); -+ -+ return ; -+} -+ -+/* -+ * This function allocates all data structure and store in the -+ * private data structure. -+ * -+ * Return value : data structure for the host controller -+ */ -+static struct sl811_hc* __devinit sl811_alloc_hc(void) -+{ -+ struct sl811_hc *hc; -+ struct usb_bus *bus; -+ int i; -+ -+ PDEBUG(4, "enter"); -+ -+ hc = (struct sl811_hc *)kmalloc(sizeof(struct sl811_hc), GFP_KERNEL); -+ if (!hc) -+ return NULL; -+ -+ memset(hc, 0, sizeof(struct sl811_hc)); -+ -+ hc->rh_status.wPortStatus = USB_PORT_STAT_POWER; -+ hc->rh_status.wPortChange = 0; -+ -+ hc->active_urbs = 0; -+ INIT_LIST_HEAD(&hc->hc_hcd_list); -+ list_add(&hc->hc_hcd_list, &sl811_hcd_list); -+ -+ init_waitqueue_head(&hc->waitq); -+ -+ for (i = 0; i < 6; ++i) -+ INIT_LIST_HEAD(&hc->urb_list[i]); -+ -+ hc->cur_list = &hc->iso_list; -+ -+ bus = usb_alloc_bus(&sl811_device_operations); -+ if (!bus) { -+ kfree (hc); -+ return NULL; -+ } -+ -+ hc->bus = bus; -+ bus->bus_name = MODNAME; -+ bus->hcpriv = hc; -+ -+ return hc; -+} -+ -+/* -+ * This function De-allocate all resources -+ */ -+static void sl811_release_hc(struct sl811_hc *hc) -+{ -+ PDEBUG(4, "enter"); -+ -+ /* disconnect all devices */ -+ if (hc->bus->root_hub) -+ usb_disconnect(&hc->bus->root_hub); -+ -+ // Stop interrupt handle -+ if (hc->irq) -+ free_irq(hc->irq, hc); -+ hc->irq = 0; -+ -+ /* Stop interrupt for sharing */ -+ if (hc->addr_io) { -+ /* Disable Interrupts */ -+ sl811_write(hc, SL811_INTR, 0); -+ -+ /* Remove all Interrupt events */ -+ mdelay(2); -+ sl811_write(hc, SL811_INTRSTS, 0xff); -+ } -+ -+ /* free io regions */ -+ sl811_release_regions(hc); -+ -+ usb_deregister_bus(hc->bus); -+ usb_free_bus(hc->bus); -+ -+ list_del(&hc->hc_hcd_list); -+ INIT_LIST_HEAD(&hc->hc_hcd_list); -+ -+ kfree (hc); -+} -+ -+/* -+ * This function request IO memory regions, request IRQ, and -+ * allocate all other resources. -+ * -+ * Input: addr_io = first IO address -+ * data_io = second IO address -+ * irq = interrupt number -+ * -+ * Return: 0 = success or error condition -+ */ -+static int __devinit sl811_found_hc(int addr_io, int data_io, int irq) -+{ -+ struct sl811_hc *hc; -+ -+ PDEBUG(4, "enter"); -+ -+ hc = sl811_alloc_hc(); -+ if (!hc) -+ return -ENOMEM; -+ -+ if (sl811_request_regions (hc, addr_io, data_io, MODNAME)) { -+ PDEBUG(1, "ioport %X,%X is in use!", addr_io, data_io); -+ sl811_release_hc(hc); -+ return -EBUSY; -+ } -+ -+ if (sl811_reg_test(hc)) { -+ PDEBUG(1, "SL811 register test failed!"); -+ sl811_release_hc(hc); -+ return -ENODEV; -+ } -+ -+//#ifdef SL811_DEBUG_VERBOSE -+ { -+ __u8 u = sl811_read(hc, SL811_HWREV); -+ -+ // Show the hardware revision of chip -+ PDEBUG(1, "SL811 HW: %02Xh", u); -+ switch (u & 0xF0) { -+ case 0x00: PDEBUG(1, "SL11H"); break; -+ case 0x10: PDEBUG(1, "SL811HS rev1.2"); break; -+ case 0x20: PDEBUG(1, "SL811HS rev1.5"); break; -+ default: PDEBUG(1, "Revision unknown!"); -+ } -+ } -+//#endif // SL811_DEBUG_VERBOSE -+ -+ sl811_init_irq(); -+ -+ usb_register_bus(hc->bus); -+ -+ if (request_irq(irq, sl811_interrupt, SA_SHIRQ, MODNAME, hc)) { -+ PDEBUG(1, "request interrupt %d failed", irq); -+ sl811_release_hc(hc); -+ return -EBUSY; -+ } -+ hc->irq = irq; -+ -+ printk(KERN_INFO __FILE__ ": USB SL811 at %08x,%08x, IRQ %d\n", -+ hc->addr_io, hc->data_io, irq); -+ -+ sl811_hc_reset(hc); -+ sl811_connect_rh(hc); -+ -+ return 0; -+} -+ -+/* -+ * This is an init function, and it is the first function being called -+ * -+ * Return: 0 = success or error condition -+ */ -+static int __init sl811_hcd_init(void) -+{ -+ int ret = -ENODEV; -+ -+ PDEBUG(4, "enter"); -+ -+ info(DRIVER_VERSION " : " DRIVER_DESC); -+ -+#ifdef CONFIG_X86 -+ { -+ int count; -+ // registering some instance -+ for (count = 0; count < MAX_CONTROLERS; count++) { -+ if (io[count]) { -+ ret = sl811_found_hc(io[count], io[count]+OFFSET_DATA_REG, irq[count]); -+ if (ret) -+ return (ret); -+ } -+ } -+ } -+#endif -+#ifdef CONFIG_ARCH_RAMSES -+ ret = sl811_found_hc(0,0,SL811HS_IRQ); -+#endif -+ -+ return ret; -+} -+ -+/* -+ * This is a cleanup function, and it is called when module is unloaded. -+ */ -+static void __exit sl811_hcd_cleanup(void) -+{ -+ struct list_head *list = sl811_hcd_list.next; -+ struct sl811_hc *hc; -+ -+ PDEBUG(4, "enter"); -+ -+ for (; list != &sl811_hcd_list; ) { -+ hc = list_entry(list, struct sl811_hc, hc_hcd_list); -+ list = list->next; -+ sl811_release_hc(hc); -+ } -+} -+ -+module_init(sl811_hcd_init); -+module_exit(sl811_hcd_cleanup); -+ -+MODULE_AUTHOR(DRIVER_AUTHOR); -+MODULE_DESCRIPTION(DRIVER_DESC); ---- /dev/null -+++ linux-2.4.21/drivers/usb/host/sl811.h -@@ -0,0 +1,177 @@ -+#ifndef __LINUX_SL811_H -+#define __LINUX_SL811_H -+ -+#define SL811_DEBUG -+ -+#ifdef SL811_DEBUG -+ #define PDEBUG(level, fmt, args...) \ -+ if (debug >= (level)) info("[%s:%d] " fmt, \ -+ __PRETTY_FUNCTION__, __LINE__ , ## args) -+#else -+ #define PDEBUG(level, fmt, args...) do {} while(0) -+#endif -+ -+//#define SL811_TIMEOUT -+ -+/* Sl811 host control register */ -+#define SL811_CTRL_A 0x00 -+#define SL811_ADDR_A 0x01 -+#define SL811_LEN_A 0x02 -+#define SL811_STS_A 0x03 /* read */ -+#define SL811_PIDEP_A 0x03 /* write */ -+#define SL811_CNT_A 0x04 /* read */ -+#define SL811_DEV_A 0x04 /* write */ -+#define SL811_CTRL1 0x05 -+#define SL811_INTR 0x06 -+#define SL811_CTRL_B 0x08 -+#define SL811_ADDR_B 0x09 -+#define SL811_LEN_B 0x0A -+#define SL811_STS_B 0x0B /* read */ -+#define SL811_PIDEP_B 0x0B /* write */ -+#define SL811_CNT_B 0x0C /* read */ -+#define SL811_DEV_B 0x0C /* write */ -+#define SL811_INTRSTS 0x0D /* write clears bitwise */ -+#define SL811_HWREV 0x0E /* read */ -+#define SL811_SOFLOW 0x0E /* write */ -+#define SL811_SOFCNTDIV 0x0F /* read */ -+#define SL811_CTRL2 0x0F /* write */ -+ -+/* USB control register bits (addr 0x00 and addr 0x08) */ -+#define SL811_USB_CTRL_ARM 0x01 -+#define SL811_USB_CTRL_ENABLE 0x02 -+#define SL811_USB_CTRL_DIR_OUT 0x04 -+#define SL811_USB_CTRL_ISO 0x10 -+#define SL811_USB_CTRL_SOF 0x20 -+#define SL811_USB_CTRL_TOGGLE_1 0x40 -+#define SL811_USB_CTRL_PREAMBLE 0x80 -+ -+/* USB status register bits (addr 0x03 and addr 0x0B) */ -+#define SL811_USB_STS_ACK 0x01 -+#define SL811_USB_STS_ERROR 0x02 -+#define SL811_USB_STS_TIMEOUT 0x04 -+#define SL811_USB_STS_TOGGLE_1 0x08 -+#define SL811_USB_STS_SETUP 0x10 -+#define SL811_USB_STS_OVERFLOW 0x20 -+#define SL811_USB_STS_NAK 0x40 -+#define SL811_USB_STS_STALL 0x80 -+ -+/* Control register 1 bits (addr 0x05) */ -+#define SL811_CTRL1_SOF 0x01 -+#define SL811_CTRL1_RESET 0x08 -+#define SL811_CTRL1_JKSTATE 0x10 -+#define SL811_CTRL1_SPEED_LOW 0x20 -+#define SL811_CTRL1_SUSPEND 0x40 -+ -+/* Interrut enable (addr 0x06) and interrupt status register bits (addr 0x0D) */ -+#define SL811_INTR_DONE_A 0x01 -+#define SL811_INTR_DONE_B 0x02 -+#define SL811_INTR_SOF 0x10 -+#define SL811_INTR_INSRMV 0x20 -+#define SL811_INTR_DETECT 0x40 -+#define SL811_INTR_NOTPRESENT 0x40 -+#define SL811_INTR_SPEED_FULL 0x80 /* only in status reg */ -+ -+/* HW rev and SOF lo register bits (addr 0x0E) */ -+#define SL811_HWR_HWREV 0xF0 -+ -+/* SOF counter and control reg 2 (addr 0x0F) */ -+#define SL811_CTL2_SOFHI 0x3F -+#define SL811_CTL2_DSWAP 0x40 -+#define SL811_CTL2_HOST 0x80 -+ -+/* Set up for 1-ms SOF time. */ -+#define SL811_12M_LOW 0xE0 -+#define SL811_12M_HI 0x2E -+ -+#define SL811_DATA_START 0x10 -+#define SL811_DATA_LIMIT 240 -+ -+ -+/* Requests: bRequest << 8 | bmRequestType */ -+#define RH_GET_STATUS 0x0080 -+#define RH_CLEAR_FEATURE 0x0100 -+#define RH_SET_FEATURE 0x0300 -+#define RH_SET_ADDRESS 0x0500 -+#define RH_GET_DESCRIPTOR 0x0680 -+#define RH_SET_DESCRIPTOR 0x0700 -+#define RH_GET_CONFIGURATION 0x0880 -+#define RH_SET_CONFIGURATION 0x0900 -+#define RH_GET_STATE 0x0280 -+#define RH_GET_INTERFACE 0x0A80 -+#define RH_SET_INTERFACE 0x0B00 -+#define RH_SYNC_FRAME 0x0C80 -+ -+ -+#define PIDEP(pid, ep) (((pid) & 0x0f) << 4 | (ep)) -+ -+/* Virtual Root HUB */ -+struct virt_root_hub { -+ int devnum; /* Address of Root Hub endpoint */ -+ void *urb; /* interrupt URB of root hub */ -+ int send; /* active flag */ -+ int interval; /* intervall of roothub interrupt transfers */ -+ struct timer_list rh_int_timer; /* intervall timer for rh interrupt EP */ -+}; -+ -+struct sl811_td { -+ /* hardware */ -+ __u8 ctrl; /* control register */ -+ -+ /* write */ -+ __u8 addr; /* base adrress register */ -+ __u8 len; /* base length register */ -+ __u8 pidep; /* PId and endpoint register */ -+ __u8 dev; /* device address register */ -+ -+ /* read */ -+ __u8 status; /* status register */ -+ __u8 left; /* transfer count register */ -+ -+ /* software */ -+ __u8 errcnt; /* error count, begin with 3 */ -+ __u8 done; /* is this td tranfer done */ -+ __u8 *buf; /* point to data buffer for tranfer */ -+ int bustime; /* the bus time need by this td */ -+ int td_status; /* the status of this td */ -+ int nakcnt; /* number of naks */ -+ struct urb *urb; /* the urb this td belongs to */ -+ struct list_head td_list; /* link to a list of the urb */ -+}; -+ -+struct sl811_urb_priv { -+ struct urb *urb; /* the urb this priv beloings to */ -+ struct list_head td_list; /* list of all the td of this urb */ -+ struct sl811_td *cur_td; /* current td is in processing or it will be */ -+ struct sl811_td *first_td; /* the first td of this urb */ -+ struct sl811_td *last_td; /* the last td of this urb */ -+ int interval; /* the query time value for intr urb */ -+ int unlink; /* is the this urb unlinked */ -+ unsigned long inserttime; /* the time when insert to list */ -+}; -+ -+struct sl811_hc { -+ spinlock_t hc_lock; /* Lock for this structure */ -+ -+ int irq; /* IRQ number this hc use */ -+ int addr_io; /* I/O address line address */ -+ int data_io; /* I/O data line address */ -+ struct virt_root_hub rh; /* root hub */ -+ struct usb_port_status rh_status;/* root hub port status */ -+ struct list_head urb_list[6]; /* set of urbs, the order is iso,intr,ctrl,bulk,inactive intr, wait */ -+ struct list_head *cur_list; /* the current list is in process */ -+ wait_queue_head_t waitq; /* deletion of URBs and devices needs a waitqueue */ -+ struct sl811_td *cur_td; /* point to the td is in process */ -+ struct list_head hc_hcd_list; /* list of all hci_hcd */ -+ struct usb_bus *bus; /* our bus */ -+ int active_urbs; /* total number of active usbs */ -+ int frame_number; /* the current frame number, we do't use it, any one need it? */ -+}; -+ -+#define iso_list urb_list[0] /* set of isoc urbs */ -+#define intr_list urb_list[1] /* ordered (tree) set of int urbs */ -+#define ctrl_list urb_list[2] /* set of ctrl urbs */ -+#define bulk_list urb_list[3] /* set of bulk urbs */ -+#define idle_intr_list urb_list[4] /* set of intr urbs in its idle time*/ -+#define wait_list urb_list[5] /* set of wait urbs */ -+ -+#endif ---- linux-2.4.21/drivers/usb/storage/transport.h~usb-sonycamera -+++ linux-2.4.21/drivers/usb/storage/transport.h -@@ -75,6 +75,8 @@ - #define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */ - #endif - -+#define US_PR_DEVICE 0xff /* Use device's value */ -+ - /* - * Bulk only data structures - */ ---- linux-2.4.21/drivers/usb/storage/unusual_devs.h~usb-sonycamera -+++ linux-2.4.21/drivers/usb/storage/unusual_devs.h -@@ -223,10 +223,10 @@ - US_FL_FIX_INQUIRY | US_FL_START_STOP ), - - /* This entry is needed because the device reports Sub=ff */ --UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0440, -+UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450, - "Sony", -- "DSC-S30/S70/S75/505V/F505/F707/F717", -- US_SC_SCSI, US_PR_CB, NULL, -+ "DSC-S30/S70/S75/505V/F505/F707/F717/P8", -+ US_SC_SCSI, US_PR_DEVICE, NULL, - US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE ), - - /* Reported by wim@geeks.nl */ ---- linux-2.4.21/drivers/usb/storage/usb.c~usb-sonycamera -+++ linux-2.4.21/drivers/usb/storage/usb.c -@@ -622,7 +622,9 @@ - - /* Determine subclass and protocol, or copy from the interface */ - subclass = unusual_dev->useProtocol; -- protocol = unusual_dev->useTransport; -+ protocol = (unusual_dev->useTransport == US_PR_DEVICE) ? -+ altsetting->bInterfaceProtocol : -+ unusual_dev->useTransport; - flags = unusual_dev->flags; - - /* ---- linux-2.4.21/drivers/video/fbcon-cfb16.c~fb-turn180 -+++ linux-2.4.21/drivers/video/fbcon-cfb16.c -@@ -34,6 +34,41 @@ - #endif - }; - -+static u8 mirrortab_cfb16[] = { -+ 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 -+}; -+ - void fbcon_cfb16_setup(struct display *p) - { - p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<1; -@@ -46,6 +81,53 @@ - int bytes = p->next_line, linesize = bytes * fontheight(p), rows; - u8 *src, *dst; - -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ char *scrn_end = p->screen_base + p->var.xres*p->var.yres * 2; -+/* -+ printk("---@paul@-------------------------\n"\ -+ "fbcon_cfb16_bmove() %d %d %d %d %d %d\n", -+ sx,sy,dx,dy,height,width -+ ); -+*/ -+ if (sx == 0 && dx == 0 && width * fontwidth(p) * 2 == bytes) -+ { -+ fb_memmove( -+ scrn_end - dy * linesize, -+ scrn_end - sy * linesize, -+ height * linesize -+ ); -+ return; -+ } -+ if (fontwidthlog(p)) { -+ sx <<= fontwidthlog(p)+1; -+ dx <<= fontwidthlog(p)+1; -+ width <<= fontwidthlog(p)+1; -+ } else { -+ sx *= fontwidth(p)*2; -+ dx *= fontwidth(p)*2; -+ width *= fontwidth(p)*2; -+ } -+ if (dy < sy || (dy == sy && dx < sx)) { -+ src = scrn_end + sy * linesize + sx; -+ dst = scrn_end + dy * linesize + dx; -+ for (rows = height * fontheight(p); rows--;) -+ { -+ fb_memmove(dst, src, width); -+ src += bytes; -+ dst += bytes; -+ } -+ } else { -+ src = scrn_end + (sy+height) * linesize + sx - bytes; -+ dst = scrn_end + (dy+height) * linesize + dx - bytes; -+ for (rows = height * fontheight(p); rows--;) -+ { -+ fb_memmove(dst, src, width); -+ src -= bytes; -+ dst -= bytes; -+ } -+ } -+/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ -+ } else { - if (sx == 0 && dx == 0 && width * fontwidth(p) * 2 == bytes) { - fb_memmove(p->screen_base + dy * linesize, - p->screen_base + sy * linesize, -@@ -78,6 +160,8 @@ - dst -= bytes; - } - } -+ } -+/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ - } - - static inline void rectfill(u8 *dest, int width, int height, u32 data, -@@ -108,10 +192,16 @@ - int bytes = p->next_line, lines = height * fontheight(p); - u32 bgx; - -- dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 2; -- -- bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]; -- -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ dest = p->screen_base -+ + p->var.xres*p->var.yres * 2 -+ - (sy+height) * fontheight(p) * bytes -+ + sx * fontwidth(p) * 2; -+ bgx = 1; -+ } else { -+ dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 2; -+ bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]; -+ } - width *= fontwidth(p)/4; - if (width * 8 == bytes) - rectfill(dest, lines * width * 4, 1, bgx, bytes); -@@ -126,14 +216,69 @@ - int bytes = p->next_line, rows; - u32 eorx, fgx, bgx; - -- dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2; -- - fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)]; - bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)]; - fgx |= (fgx << 16); - bgx |= (bgx << 16); - eorx = fgx ^ bgx; - -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ dest = p->screen_base -+ + p->var.xres*p->var.yres * 2 -+ - yy * fontheight(p) * bytes -+ - xx * fontwidth(p) * 2; -+ -+ switch (fontwidth(p)) { -+ case 4: -+ cdat = p->fontdata + (c & p->charmask) * fontheight(p); -+ for (rows = fontheight(p); rows--; dest += bytes) -+ { -+ bits = mirrortab_cfb16[*cdat++]; -+ fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest-8); -+ fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-4); -+ } -+ case 8: -+ cdat = p->fontdata + (c & p->charmask) * fontheight(p); -+ for (rows = fontheight(p); rows--; dest += bytes) -+ { -+ bits = mirrortab_cfb16[*cdat++]; -+ fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest-16); -+ fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-12); -+ fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-8); -+ fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest-4); -+ } -+ break; -+ case 12: -+ cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1); -+ for (rows = fontheight(p); rows--; dest += bytes) { -+ bits = mirrortab_cfb16[*cdat++]; -+ fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest-24); -+ fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-20); -+ fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-16); -+ fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest-12); -+ bits = mirrortab_cfb16[*cdat++]; -+ fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest-8); -+ fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-4); -+ } -+ case 16: -+ cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1); -+ for (rows = fontheight(p); rows--; dest += bytes) { -+ bits = mirrortab_cfb16[*cdat++]; -+ fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest-32); -+ fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-28); -+ fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-24); -+ fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest-20); -+ bits = mirrortab_cfb16[*cdat++]; -+ fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest-16); -+ fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-12); -+ fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-8); -+ fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest-4); -+ } -+ break; -+ } -+/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ -+ } else { -+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2; - switch (fontwidth(p)) { - case 4: - case 8: -@@ -167,6 +312,8 @@ - } - break; - } -+ } -+/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ - } - - void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p, -@@ -177,7 +324,6 @@ - int rows, bytes = p->next_line; - u32 eorx, fgx, bgx; - -- dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2; - c = scr_readw(s); - fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)]; - bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)]; -@@ -185,6 +331,81 @@ - bgx |= (bgx << 16); - eorx = fgx ^ bgx; - -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ dest0 = p->screen_base -+ + p->var.xres * p->var.yres * 2 -+ - yy * fontheight(p) * bytes -+ - xx * fontwidth(p) * 2; -+ -+ switch (fontwidth(p)) { -+ case 4: -+ while (count--) { -+ c = scr_readw(s++) & p->charmask; -+ cdat = p->fontdata + c * fontheight(p); -+ for (rows = fontheight(p), dest = dest0; rows--; dest -= bytes) -+ { -+ u8 bits = mirrortab_cfb16[*cdat++]; -+ fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest-8); -+ fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-4); -+ } -+ dest0 -= fontwidth(p)*2; -+ } -+ case 8: -+ while (count--) { -+ c = scr_readw(s++) & p->charmask; -+ cdat = p->fontdata + c * fontheight(p); -+ for (rows = fontheight(p), dest = dest0; rows--; dest -= bytes) -+ { -+ u8 bits = mirrortab_cfb16[*cdat++]; -+ fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest-16); -+ fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-12); -+ fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-8); -+ fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest-4); -+ } -+ dest0 -= fontwidth(p)*2; -+ } -+ break; -+ case 12: -+ while (count--) { -+ c = scr_readw(s++) & p->charmask; -+ cdat = p->fontdata + (c * fontheight(p) << 1); -+ for (rows = fontheight(p), dest = dest0; rows--; dest -= bytes) -+ { -+ u8 bits = mirrortab_cfb16[*cdat++]; -+ fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest-24); -+ fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-20); -+ fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-16); -+ fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest-12); -+ bits = mirrortab_cfb16[*cdat++]; -+ fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest-8); -+ fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-4); -+ } -+ dest0 -= fontwidth(p)*2; -+ } -+ case 16: -+ while (count--) { -+ c = scr_readw(s++) & p->charmask; -+ cdat = p->fontdata + (c * fontheight(p) << 1); -+ for (rows = fontheight(p), dest = dest0; rows--; dest -= bytes) -+ { -+ u8 bits = mirrortab_cfb16[*cdat++]; -+ fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest-32); -+ fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-28); -+ fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-24); -+ fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest-20); -+ bits = mirrortab_cfb16[*cdat++]; -+ fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest-16); -+ fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-12); -+ fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-8); -+ fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest-4); -+ } -+ dest0 -= fontwidth(p)*2; -+ } -+ break; -+ } -+/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ -+ } else { -+ dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2; - switch (fontwidth(p)) { - case 4: - case 8: -@@ -226,6 +447,8 @@ - } - break; - } -+ } -+/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ - } - - void fbcon_cfb16_revc(struct display *p, int xx, int yy) -@@ -233,6 +456,32 @@ - u8 *dest; - int bytes = p->next_line, rows; - -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ dest = p->screen_base -+ + p->var.xres*p->var.yres * 2 -+ - yy * fontheight(p) * bytes -+ - xx * fontwidth(p) * 2; -+ for (rows = fontheight(p); rows--; dest -= bytes) { -+ switch (fontwidth(p)) { -+ case 16: -+ fb_writel(fb_readl(dest-32) ^ 0xffffffff, dest-32); -+ fb_writel(fb_readl(dest-28) ^ 0xffffffff, dest-28); -+ /* FALL THROUGH */ -+ case 12: -+ fb_writel(fb_readl(dest-24) ^ 0xffffffff, dest-24); -+ fb_writel(fb_readl(dest-20) ^ 0xffffffff, dest-20); -+ /* FALL THROUGH */ -+ case 8: -+ fb_writel(fb_readl(dest-16) ^ 0xffffffff, dest-16); -+ fb_writel(fb_readl(dest-12) ^ 0xffffffff, dest-12); -+ /* FALL THROUGH */ -+ case 4: -+ fb_writel(fb_readl(dest-8) ^ 0xffffffff, dest-8); -+ fb_writel(fb_readl(dest-4) ^ 0xffffffff, dest-4); -+ } -+ } -+/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ -+ } else { - dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p)*2; - for (rows = fontheight(p); rows--; dest += bytes) { - switch (fontwidth(p)) { -@@ -253,6 +502,8 @@ - fb_writel(fb_readl(dest+4) ^ 0xffffffff, dest+4); - } - } -+ } -+/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ - } - - void fbcon_cfb16_clear_margins(struct vc_data *conp, struct display *p, -@@ -268,6 +519,9 @@ - bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]; - - if (!bottom_only && (right_width = p->var.xres-right_start)) -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ printk("---@paul@------------------------- fbcon-cfb16 clear margins\n"); -+ } - rectfill(p->screen_base+right_start*2, right_width, - p->var.yres_virtual, bgx, bytes); - if ((bottom_width = p->var.yres-bottom_start)) ---- linux-2.4.21/drivers/video/fbcon-cfb8.c~fb-turn180 -+++ linux-2.4.21/drivers/video/fbcon-cfb8.c -@@ -39,6 +39,41 @@ - #endif - }; - -+static u8 mirrortab_cfb8[] = { -+ 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 -+}; -+ - void fbcon_cfb8_setup(struct display *p) - { - p->next_line = p->line_length ? p->line_length : p->var.xres_virtual; -@@ -51,10 +86,57 @@ - int bytes = p->next_line, linesize = bytes * fontheight(p), rows; - u8 *src,*dst; - -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+/* -+ printk("---@paul@-------------------------\n"\ -+ "fbcon_cfb8_bmove() %d %d %d %d %d %d\n", -+ sx,sy,dx,dy,height,width -+ ); -+*/ -+ if (sx == 0 && dx == 0 && width * fontwidth(p) == bytes) -+ { -+ fb_memmove( -+ p->screen_base + p->var.xres*p->var.yres - dy * linesize, -+ p->screen_base + p->var.xres*p->var.yres - sy * linesize, -+ height * linesize); -+ return; -+ } -+ if (fontwidthlog(p)) { -+ sx <<= fontwidthlog(p); dx <<= fontwidthlog(p); width <<= fontwidthlog(p); -+ } else { -+ sx *= fontwidth(p); dx *= fontwidth(p); width *= fontwidth(p); -+ } -+ if (dy < sy || (dy == sy && dx < sx)) -+ { -+ src = p->screen_base + p->var.xres*p->var.yres -+ - sy * linesize - sx; -+ dst = p->screen_base + p->var.xres*p->var.yres -+ - dy * linesize - dx; -+ for (rows = height * fontheight(p) ; rows-- ;) -+ { -+ fb_memmove(dst, src, width); -+ src += bytes; -+ dst += bytes; -+ } -+ } else -+ { -+ src = p->screen_base + p->var.xres*p->var.yres -+ - (sy+height) * linesize - sx + bytes; -+ dst = p->screen_base + p->var.xres*p->var.yres -+ - (dy+height) * linesize - dx + bytes; -+ for (rows = height * fontheight(p) ; rows-- ;) -+ { -+ fb_memmove(dst, src, width); -+ src -= bytes; -+ dst -= bytes; -+ } -+ } -+/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ -+ } else { - if (sx == 0 && dx == 0 && width * fontwidth(p) == bytes) { -- fb_memmove(p->screen_base + dy * linesize, -- p->screen_base + sy * linesize, -- height * linesize); -+ fb_memmove(p->screen_base + dy * linesize, -+ p->screen_base + sy * linesize, -+ height * linesize); - return; - } - if (fontwidthlog(p)) { -@@ -79,6 +161,7 @@ - dst -= bytes; - } - } -+/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ - } - - static inline void rectfill(u8 *dest, int width, int height, u8 data, -@@ -97,11 +180,17 @@ - int bytes=p->next_line,lines=height * fontheight(p); - u8 bgx; - -- dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p); -- -- bgx=attr_bgcol_ec(p,conp); -- -- width *= fontwidth(p); -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ bgx=attr_bgcol_ec(p,conp); -+ width *= fontwidth(p); -+ dest = p->screen_base + p->var.xres*p->var.yres -+ - (sy+height) * fontheight(p) * bytes -+ + sx * fontwidth(p); -+ } else { -+ dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p); -+ bgx=attr_bgcol_ec(p,conp); -+ width *= fontwidth(p); -+ } - if (width == bytes) - rectfill(dest, lines * width, 1, bgx, bytes); - else -@@ -114,8 +203,8 @@ - u8 *dest,*cdat; - int bytes=p->next_line,rows; - u32 eorx,fgx,bgx; -+ u8 chrrow; - -- dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p); - if (fontwidth(p) <= 8) - cdat = p->fontdata + (c & p->charmask) * fontheight(p); - else -@@ -129,6 +218,53 @@ - bgx |= (bgx << 16); - eorx = fgx ^ bgx; - -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ dest = p->screen_base -+ + p->var.xres*p->var.yres -+ - yy * fontheight(p) * bytes -+ - xx * fontwidth(p); -+ -+ switch (fontwidth(p)) { -+ case 4: -+ for (rows = fontheight(p) ; rows-- ; dest += bytes) -+ { -+ chrrow = mirrortab_cfb8[*cdat++]; -+ fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx) ^ bgx, dest-4); -+ } -+ break; -+ case 8: -+ for (rows = fontheight(p) ; rows-- ; dest += bytes) -+ { -+ chrrow = mirrortab_cfb8[*cdat++]; -+ fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx) ^ bgx, dest-8); -+ fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-4); -+ } -+ break; -+ case 12: -+ for (rows = fontheight(p) ; rows-- ; dest += bytes) -+ { -+ chrrow = mirrortab_cfb8[*cdat++]; -+ fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx) ^ bgx, dest-12); -+ fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-8); -+ chrrow = mirrortab_cfb8[*cdat++]; -+ fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx) ^ bgx, dest-4); -+ } -+ break; -+ case 16: -+ for (rows = fontheight(p) ; rows-- ; dest += bytes) -+ { -+ chrrow = mirrortab_cfb8[*cdat++]; -+ fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx) ^ bgx, dest-16); -+ fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-12); -+ chrrow = mirrortab_cfb8[*cdat++]; -+ fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx) ^ bgx, dest-8); -+ fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-4); -+ } -+ break; -+ } -+/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ -+ } else { -+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p); - switch (fontwidth(p)) { - case 4: - for (rows = fontheight(p) ; rows-- ; dest += bytes) -@@ -152,6 +288,8 @@ - } - break; - } -+ } -+/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ - } - - void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p, -@@ -161,8 +299,8 @@ - u16 c; - int rows,bytes=p->next_line; - u32 eorx, fgx, bgx; -+ u8 chrrow; - -- dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p); - c = scr_readw(s); - fgx = attr_fgcol(p, c); - bgx = attr_bgcol(p, c); -@@ -171,6 +309,76 @@ - bgx |= (bgx << 8); - bgx |= (bgx << 16); - eorx = fgx ^ bgx; -+ -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ dest0 = p->screen_base -+ + p->var.xres*p->var.yres -+ - yy * fontheight(p) * bytes -+ - xx * fontwidth(p); -+ switch (fontwidth(p)) { -+ case 4: -+ while (count--) { -+ c = scr_readw(s++) & p->charmask; -+ cdat = p->fontdata + c * fontheight(p); -+ -+ for (rows = fontheight(p), dest = dest0; rows-- ; dest -= bytes) -+ { -+ chrrow = mirrortab_cfb8[*cdat++]; -+ fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx) ^ bgx, dest-4); -+ } -+ dest0 -= 4; -+ } -+ break; -+ case 8: -+ while (count--) { -+ c = scr_readw(s++) & p->charmask; -+ cdat = p->fontdata + c * fontheight(p); -+ for (rows = fontheight(p), dest = dest0; rows-- ; dest -= bytes) -+ { -+ chrrow = mirrortab_cfb8[*cdat++]; -+ fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx) ^ bgx, dest-8); -+ fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-4); -+ } -+ dest0 -= 8; -+ } -+ break; -+ case 12: -+ while (count--) { -+ c = scr_readw(s++) & p->charmask; -+ cdat = p->fontdata + (c * fontheight(p) << 1); -+ -+ for (rows = fontheight(p), dest = dest0; rows-- ; dest -= bytes) -+ { -+ chrrow = mirrortab_cfb8[*cdat++]; -+ fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx) ^ bgx, dest-12); -+ fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-8); -+ chrrow = mirrortab_cfb8[*cdat++]; -+ fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx) ^ bgx, dest-4); -+ } -+ dest0 -= fontwidth(p); -+ } -+ break; -+ case 16: -+ while (count--) { -+ c = scr_readw(s++) & p->charmask; -+ cdat = p->fontdata + (c * fontheight(p) << 1); -+ -+ for (rows = fontheight(p), dest = dest0; rows-- ; dest -= bytes) -+ { -+ chrrow = mirrortab_cfb8[*cdat++]; -+ fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx) ^ bgx, dest-16); -+ fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-12); -+ chrrow = mirrortab_cfb8[*cdat++]; -+ fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx) ^ bgx, dest-8); -+ fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-4); -+ } -+ dest0 -= fontwidth(p); -+ } -+ break; -+ } /* switch (fontwidth(p)) */ -+/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ -+ } else { -+ dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p); - switch (fontwidth(p)) { - case 4: - while (count--) { -@@ -212,6 +420,8 @@ - } - break; - } -+ } -+/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ - } - - void fbcon_cfb8_revc(struct display *p, int xx, int yy) -@@ -219,6 +429,21 @@ - u8 *dest; - int bytes=p->next_line, rows; - -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ dest = p->screen_base + p->var.xres*p->var.yres -+ - yy * fontheight(p) * bytes -+ - xx * fontwidth(p); -+ for (rows = fontheight(p) ; rows-- ; dest -= bytes) { -+ switch (fontwidth(p)) { -+ case 16: fb_writel(fb_readl(dest-16) ^ 0x0f0f0f0f, dest-16); /* fall thru */ -+ case 12: fb_writel(fb_readl(dest-12) ^ 0x0f0f0f0f, dest-12); /* fall thru */ -+ case 8: fb_writel(fb_readl(dest-8) ^ 0x0f0f0f0f, dest-8); /* fall thru */ -+ case 4: fb_writel(fb_readl(dest-4) ^ 0x0f0f0f0f, dest-4); /* fall thru */ -+ default: break; -+ } -+ } -+/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ -+ } else { - dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p); - for (rows = fontheight(p) ; rows-- ; dest += bytes) { - switch (fontwidth(p)) { -@@ -229,6 +454,8 @@ - default: break; - } - } -+ } -+/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */ - } - - void fbcon_cfb8_clear_margins(struct vc_data *conp, struct display *p, -@@ -244,6 +471,9 @@ - bgx=attr_bgcol_ec(p,conp); - - if (!bottom_only && (right_width = p->var.xres-right_start)) -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ printk("---@paul@------------------------- fbcon-cfb8 clear margins\n"); -+ } - rectfill(p->screen_base+right_start, right_width, p->var.yres_virtual, - bgx, bytes); - if ((bottom_width = p->var.yres-bottom_start)) ---- linux-2.4.21/drivers/video/fbcon.c~fb-turn180 -+++ linux-2.4.21/drivers/video/fbcon.c -@@ -1558,6 +1558,7 @@ - update_region(fg_console, - conp->vc_origin + conp->vc_size_row * conp->vc_top, - conp->vc_size_row * (conp->vc_bottom - conp->vc_top) / 2); -+ conp->vc_top = 0; - return 0; - } - return 1; -@@ -2209,7 +2210,16 @@ - src = logo; - bdepth = depth/8; - for( y1 = 0; y1 < LOGO_H; y1++ ) { -- dst = fb + y1*line + x*bdepth; -+ -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+/* -+ Das ist NICHT die richtige Stelle für den Ramses 16 BPP Modus -+ aber dafür die weiter unten. -+*/ -+ dst = fb + p->var.xres*p->var.yres*bdepth -1 - y1*line - x*bdepth; -+ } else { -+ dst = fb + y1*line + x*bdepth; -+ } - for( x1 = 0; x1 < LOGO_W; x1++, src++ ) { - val = (*src << redshift) | - (*src << greenshift) | -@@ -2217,18 +2227,32 @@ - if (bdepth == 4 && !((long)dst & 3)) { - /* Some cards require 32bit access */ - fb_writel (val, dst); -- dst += 4; -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ dst -= 4; -+ } else { -+ dst += 4; -+ } - } else if (bdepth == 2 && !((long)dst & 1)) { - /* others require 16bit access */ - fb_writew (val,dst); -- dst +=2; -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ dst -= 2; -+ } else { -+ dst +=2; -+ } - } else { -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ for( i = bdepth-1; i >= 0; --i ) -+ fb_writeb (val >> (i*8), dst--); -+ -+ } else { - #ifdef __LITTLE_ENDIAN -- for( i = 0; i < bdepth; ++i ) -+ for( i = 0; i < bdepth; ++i ) - #else -- for( i = bdepth-1; i >= 0; --i ) -+ for( i = bdepth-1; i >= 0; --i ) - #endif -- fb_writeb (val >> (i*8), dst++); -+ fb_writeb (val >> (i*8), dst++); -+ } - } - } - } -@@ -2239,28 +2263,42 @@ - src = linux_logo16; - bdepth = (depth+7)/8; - for( y1 = 0; y1 < LOGO_H; y1++ ) { -- dst = fb + y1*line + x*bdepth; -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ dst = fb + p->var.xres*p->var.yres*bdepth -1 - y1*line - x*bdepth; -+ } else { -+ dst = fb + y1*line + x*bdepth; -+ } - for( x1 = 0; x1 < LOGO_W/2; x1++, src++ ) { - pix = *src >> 4; /* upper nibble */ - val = (pix << redshift) | - (pix << greenshift) | - (pix << blueshift); -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ for( i = bdepth-1; i >= 0; --i ) -+ fb_writeb (val >> (i*8), dst--); -+ } else { - #ifdef __LITTLE_ENDIAN -- for( i = 0; i < bdepth; ++i ) -+ for( i = 0; i < bdepth; ++i ) - #else -- for( i = bdepth-1; i >= 0; --i ) -+ for( i = bdepth-1; i >= 0; --i ) - #endif -- fb_writeb (val >> (i*8), dst++); -+ fb_writeb (val >> (i*8), dst++); -+ } - pix = *src & 0x0f; /* lower nibble */ - val = (pix << redshift) | - (pix << greenshift) | - (pix << blueshift); -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ for( i = bdepth-1; i >= 0; --i ) -+ fb_writeb (val >> (i*8), dst--); -+ } else { - #ifdef __LITTLE_ENDIAN -- for( i = 0; i < bdepth; ++i ) -+ for( i = 0; i < bdepth; ++i ) - #else -- for( i = bdepth-1; i >= 0; --i ) -+ for( i = bdepth-1; i >= 0; --i ) - #endif -- fb_writeb (val >> (i*8), dst++); -+ fb_writeb (val >> (i*8), dst++); -+ } - } - } - } -@@ -2287,7 +2325,11 @@ - - src = logo; - for( y1 = 0; y1 < LOGO_H; y1++ ) { -- dst = fb + y1*line + x*bdepth; -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ dst = fb + p->var.xres*p->var.yres*bdepth -1 - y1*line - x*bdepth; -+ } else { -+ dst = fb + y1*line + x*bdepth; -+ } - for( x1 = 0; x1 < LOGO_W; x1++, src++ ) { - val = safe_shift((linux_logo_red[*src-32] & redmask), redshift) | - safe_shift((linux_logo_green[*src-32] & greenmask), greenshift) | -@@ -2295,18 +2337,31 @@ - if (bdepth == 4 && !((long)dst & 3)) { - /* Some cards require 32bit access */ - fb_writel (val, dst); -- dst += 4; -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ dst -= 4; -+ } else { -+ dst += 4; -+ } - } else if (bdepth == 2 && !((long)dst & 1)) { - /* others require 16bit access */ - fb_writew (val,dst); -- dst +=2; -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ dst -= 2; -+ } else { -+ dst +=2; -+ } - } else { -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ for( i = bdepth-1; i >= 0; --i ) -+ fb_writeb (val >> (i*8), dst--); -+ } else { - #ifdef __LITTLE_ENDIAN -- for( i = 0; i < bdepth; ++i ) -+ for( i = 0; i < bdepth; ++i ) - #else -- for( i = bdepth-1; i >= 0; --i ) -+ for( i = bdepth-1; i >= 0; --i ) - #endif -- fb_writeb (val >> (i*8), dst++); -+ fb_writeb (val >> (i*8), dst++); -+ } - } - } - } -@@ -2331,13 +2386,24 @@ - if (depth == 8 && p->type == FB_TYPE_PACKED_PIXELS) { - /* depth 8 or more, packed, with color registers */ - -- src = logo; -- for( y1 = 0; y1 < LOGO_H; y1++ ) { -- dst = fb + y1*line + x; -- for( x1 = 0; x1 < LOGO_W; x1++ ) -- fb_writeb (*src++, dst++); -- } -- done = 1; -+ if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) { -+ src = logo; -+ for( y1 = 0; y1 < LOGO_H; y1++ ) -+ { -+ dst = fb + p->var.xres*p->var.yres -1 - y1*line - x; -+ for( x1 = 0; x1 < LOGO_W; x1++ ) -+ fb_writeb (*src++, dst--); -+ } -+ done = 1; -+ } else { -+ src = logo; -+ for( y1 = 0; y1 < LOGO_H; y1++ ) { -+ dst = fb + y1*line + x; -+ for( x1 = 0; x1 < LOGO_W; x1++ ) -+ fb_writeb (*src++, dst++); -+ } -+ done = 1; -+ } - } - #endif - #if defined(CONFIG_FBCON_AFB) || defined(CONFIG_FBCON_ILBM) || \ ---- linux-2.4.21/drivers/video/fbmem.c~fb-buffered -+++ linux-2.4.21/drivers/video/fbmem.c -@@ -302,7 +302,7 @@ - { "sa1100", sa1100fb_init, NULL }, - #endif - #ifdef CONFIG_FB_PXA -- { "pxa", pxafb_init, NULL }, -+ { "pxa", pxafb_init, NULL }, - #endif - #ifdef CONFIG_FB_SUN3 - { "sun3", sun3fb_init, sun3fb_setup }, -@@ -672,7 +672,11 @@ - #elif defined(__hppa__) - pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; - #elif defined(__ia64__) || defined(__arm__) -+#ifdef CONFIG_PXA -+ vma->vm_page_prot = pgprot_noncached_buffered(vma->vm_page_prot); -+#else - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -+#endif - #elif defined(__hppa__) - pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; - #else ---- linux-2.4.21/drivers/video/pxafb.c~ramses-lcd -+++ linux-2.4.21/drivers/video/pxafb.c -@@ -45,8 +45,6 @@ - - #include